1bf215546Sopenharmony_ci/**************************************************************************
2bf215546Sopenharmony_ci *
3bf215546Sopenharmony_ci * Copyright 2008 VMware, Inc.
4bf215546Sopenharmony_ci * All Rights Reserved.
5bf215546Sopenharmony_ci *
6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the
8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to
11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
12bf215546Sopenharmony_ci * the following conditions:
13bf215546Sopenharmony_ci *
14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the
15bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions
16bf215546Sopenharmony_ci * of the Software.
17bf215546Sopenharmony_ci *
18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25bf215546Sopenharmony_ci *
26bf215546Sopenharmony_ci **************************************************************************/
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci
29bf215546Sopenharmony_ci/**
30bf215546Sopenharmony_ci * @file
31bf215546Sopenharmony_ci * Trace dumping functions.
32bf215546Sopenharmony_ci *
33bf215546Sopenharmony_ci * For now we just use standard XML for dumping the trace calls, as this is
34bf215546Sopenharmony_ci * simple to write, parse, and visually inspect, but the actual representation
35bf215546Sopenharmony_ci * is abstracted out of this file, so that we can switch to a binary
36bf215546Sopenharmony_ci * representation if/when it becomes justified.
37bf215546Sopenharmony_ci *
38bf215546Sopenharmony_ci * @author Jose Fonseca <jfonseca@vmware.com>
39bf215546Sopenharmony_ci */
40bf215546Sopenharmony_ci
41bf215546Sopenharmony_ci#include "pipe/p_config.h"
42bf215546Sopenharmony_ci
43bf215546Sopenharmony_ci#include <stdio.h>
44bf215546Sopenharmony_ci#include <stdlib.h>
45bf215546Sopenharmony_ci
46bf215546Sopenharmony_ci/* for access() */
47bf215546Sopenharmony_ci#ifdef _WIN32
48bf215546Sopenharmony_ci# include <io.h>
49bf215546Sopenharmony_ci#endif
50bf215546Sopenharmony_ci
51bf215546Sopenharmony_ci#include "pipe/p_compiler.h"
52bf215546Sopenharmony_ci#include "os/os_thread.h"
53bf215546Sopenharmony_ci#include "util/os_time.h"
54bf215546Sopenharmony_ci#include "util/u_debug.h"
55bf215546Sopenharmony_ci#include "util/u_memory.h"
56bf215546Sopenharmony_ci#include "util/u_string.h"
57bf215546Sopenharmony_ci#include "util/u_math.h"
58bf215546Sopenharmony_ci#include "util/format/u_format.h"
59bf215546Sopenharmony_ci#include "compiler/nir/nir.h"
60bf215546Sopenharmony_ci
61bf215546Sopenharmony_ci#include "tr_dump.h"
62bf215546Sopenharmony_ci#include "tr_screen.h"
63bf215546Sopenharmony_ci#include "tr_texture.h"
64bf215546Sopenharmony_ci
65bf215546Sopenharmony_ci
66bf215546Sopenharmony_cistatic bool close_stream = false;
67bf215546Sopenharmony_cistatic FILE *stream = NULL;
68bf215546Sopenharmony_cistatic mtx_t call_mutex = _MTX_INITIALIZER_NP;
69bf215546Sopenharmony_cistatic long unsigned call_no = 0;
70bf215546Sopenharmony_cistatic bool dumping = false;
71bf215546Sopenharmony_cistatic long nir_count = 0;
72bf215546Sopenharmony_ci
73bf215546Sopenharmony_cistatic bool trigger_active = true;
74bf215546Sopenharmony_cistatic char *trigger_filename = NULL;
75bf215546Sopenharmony_ci
76bf215546Sopenharmony_civoid
77bf215546Sopenharmony_citrace_dump_trigger_active(bool active)
78bf215546Sopenharmony_ci{
79bf215546Sopenharmony_ci   trigger_active = active;
80bf215546Sopenharmony_ci}
81bf215546Sopenharmony_ci
82bf215546Sopenharmony_civoid
83bf215546Sopenharmony_citrace_dump_check_trigger(void)
84bf215546Sopenharmony_ci{
85bf215546Sopenharmony_ci   if (!trigger_filename)
86bf215546Sopenharmony_ci      return;
87bf215546Sopenharmony_ci
88bf215546Sopenharmony_ci   mtx_lock(&call_mutex);
89bf215546Sopenharmony_ci   if (trigger_active) {
90bf215546Sopenharmony_ci      trigger_active = false;
91bf215546Sopenharmony_ci   } else {
92bf215546Sopenharmony_ci      if (!access(trigger_filename, 2 /* W_OK but compiles on Windows */)) {
93bf215546Sopenharmony_ci         if (!unlink(trigger_filename)) {
94bf215546Sopenharmony_ci            trigger_active = true;
95bf215546Sopenharmony_ci         } else {
96bf215546Sopenharmony_ci            fprintf(stderr, "error removing trigger file\n");
97bf215546Sopenharmony_ci            trigger_active = false;
98bf215546Sopenharmony_ci         }
99bf215546Sopenharmony_ci      }
100bf215546Sopenharmony_ci   }
101bf215546Sopenharmony_ci   mtx_unlock(&call_mutex);
102bf215546Sopenharmony_ci}
103bf215546Sopenharmony_ci
104bf215546Sopenharmony_cibool
105bf215546Sopenharmony_citrace_dump_is_triggered(void)
106bf215546Sopenharmony_ci{
107bf215546Sopenharmony_ci   return trigger_active && !!trigger_filename;
108bf215546Sopenharmony_ci}
109bf215546Sopenharmony_ci
110bf215546Sopenharmony_cistatic inline void
111bf215546Sopenharmony_citrace_dump_write(const char *buf, size_t size)
112bf215546Sopenharmony_ci{
113bf215546Sopenharmony_ci   if (stream && trigger_active) {
114bf215546Sopenharmony_ci      fwrite(buf, size, 1, stream);
115bf215546Sopenharmony_ci   }
116bf215546Sopenharmony_ci}
117bf215546Sopenharmony_ci
118bf215546Sopenharmony_ci
119bf215546Sopenharmony_cistatic inline void
120bf215546Sopenharmony_citrace_dump_writes(const char *s)
121bf215546Sopenharmony_ci{
122bf215546Sopenharmony_ci   trace_dump_write(s, strlen(s));
123bf215546Sopenharmony_ci}
124bf215546Sopenharmony_ci
125bf215546Sopenharmony_ci
126bf215546Sopenharmony_cistatic inline void
127bf215546Sopenharmony_citrace_dump_writef(const char *format, ...)
128bf215546Sopenharmony_ci{
129bf215546Sopenharmony_ci   static char buf[1024];
130bf215546Sopenharmony_ci   unsigned len;
131bf215546Sopenharmony_ci   va_list ap;
132bf215546Sopenharmony_ci   va_start(ap, format);
133bf215546Sopenharmony_ci   len = vsnprintf(buf, sizeof(buf), format, ap);
134bf215546Sopenharmony_ci   va_end(ap);
135bf215546Sopenharmony_ci   trace_dump_write(buf, len);
136bf215546Sopenharmony_ci}
137bf215546Sopenharmony_ci
138bf215546Sopenharmony_ci
139bf215546Sopenharmony_cistatic inline void
140bf215546Sopenharmony_citrace_dump_escape(const char *str)
141bf215546Sopenharmony_ci{
142bf215546Sopenharmony_ci   const unsigned char *p = (const unsigned char *)str;
143bf215546Sopenharmony_ci   unsigned char c;
144bf215546Sopenharmony_ci   while((c = *p++) != 0) {
145bf215546Sopenharmony_ci      if(c == '<')
146bf215546Sopenharmony_ci         trace_dump_writes("&lt;");
147bf215546Sopenharmony_ci      else if(c == '>')
148bf215546Sopenharmony_ci         trace_dump_writes("&gt;");
149bf215546Sopenharmony_ci      else if(c == '&')
150bf215546Sopenharmony_ci         trace_dump_writes("&amp;");
151bf215546Sopenharmony_ci      else if(c == '\'')
152bf215546Sopenharmony_ci         trace_dump_writes("&apos;");
153bf215546Sopenharmony_ci      else if(c == '\"')
154bf215546Sopenharmony_ci         trace_dump_writes("&quot;");
155bf215546Sopenharmony_ci      else if(c >= 0x20 && c <= 0x7e)
156bf215546Sopenharmony_ci         trace_dump_writef("%c", c);
157bf215546Sopenharmony_ci      else
158bf215546Sopenharmony_ci         trace_dump_writef("&#%u;", c);
159bf215546Sopenharmony_ci   }
160bf215546Sopenharmony_ci}
161bf215546Sopenharmony_ci
162bf215546Sopenharmony_ci
163bf215546Sopenharmony_cistatic inline void
164bf215546Sopenharmony_citrace_dump_indent(unsigned level)
165bf215546Sopenharmony_ci{
166bf215546Sopenharmony_ci   unsigned i;
167bf215546Sopenharmony_ci   for(i = 0; i < level; ++i)
168bf215546Sopenharmony_ci      trace_dump_writes("\t");
169bf215546Sopenharmony_ci}
170bf215546Sopenharmony_ci
171bf215546Sopenharmony_ci
172bf215546Sopenharmony_cistatic inline void
173bf215546Sopenharmony_citrace_dump_newline(void)
174bf215546Sopenharmony_ci{
175bf215546Sopenharmony_ci   trace_dump_writes("\n");
176bf215546Sopenharmony_ci}
177bf215546Sopenharmony_ci
178bf215546Sopenharmony_ci
179bf215546Sopenharmony_cistatic inline void
180bf215546Sopenharmony_citrace_dump_tag_begin(const char *name)
181bf215546Sopenharmony_ci{
182bf215546Sopenharmony_ci   trace_dump_writes("<");
183bf215546Sopenharmony_ci   trace_dump_writes(name);
184bf215546Sopenharmony_ci   trace_dump_writes(">");
185bf215546Sopenharmony_ci}
186bf215546Sopenharmony_ci
187bf215546Sopenharmony_cistatic inline void
188bf215546Sopenharmony_citrace_dump_tag_begin1(const char *name,
189bf215546Sopenharmony_ci                      const char *attr1, const char *value1)
190bf215546Sopenharmony_ci{
191bf215546Sopenharmony_ci   trace_dump_writes("<");
192bf215546Sopenharmony_ci   trace_dump_writes(name);
193bf215546Sopenharmony_ci   trace_dump_writes(" ");
194bf215546Sopenharmony_ci   trace_dump_writes(attr1);
195bf215546Sopenharmony_ci   trace_dump_writes("='");
196bf215546Sopenharmony_ci   trace_dump_escape(value1);
197bf215546Sopenharmony_ci   trace_dump_writes("'>");
198bf215546Sopenharmony_ci}
199bf215546Sopenharmony_ci
200bf215546Sopenharmony_ci
201bf215546Sopenharmony_cistatic inline void
202bf215546Sopenharmony_citrace_dump_tag_end(const char *name)
203bf215546Sopenharmony_ci{
204bf215546Sopenharmony_ci   trace_dump_writes("</");
205bf215546Sopenharmony_ci   trace_dump_writes(name);
206bf215546Sopenharmony_ci   trace_dump_writes(">");
207bf215546Sopenharmony_ci}
208bf215546Sopenharmony_ci
209bf215546Sopenharmony_civoid
210bf215546Sopenharmony_citrace_dump_trace_flush(void)
211bf215546Sopenharmony_ci{
212bf215546Sopenharmony_ci   if (stream) {
213bf215546Sopenharmony_ci      fflush(stream);
214bf215546Sopenharmony_ci   }
215bf215546Sopenharmony_ci}
216bf215546Sopenharmony_ci
217bf215546Sopenharmony_cistatic void
218bf215546Sopenharmony_citrace_dump_trace_close(void)
219bf215546Sopenharmony_ci{
220bf215546Sopenharmony_ci   if (stream) {
221bf215546Sopenharmony_ci      trigger_active = true;
222bf215546Sopenharmony_ci      trace_dump_writes("</trace>\n");
223bf215546Sopenharmony_ci      if (close_stream) {
224bf215546Sopenharmony_ci         fclose(stream);
225bf215546Sopenharmony_ci         close_stream = false;
226bf215546Sopenharmony_ci         stream = NULL;
227bf215546Sopenharmony_ci      }
228bf215546Sopenharmony_ci      call_no = 0;
229bf215546Sopenharmony_ci      free(trigger_filename);
230bf215546Sopenharmony_ci   }
231bf215546Sopenharmony_ci}
232bf215546Sopenharmony_ci
233bf215546Sopenharmony_ci
234bf215546Sopenharmony_cistatic void
235bf215546Sopenharmony_citrace_dump_call_time(int64_t time)
236bf215546Sopenharmony_ci{
237bf215546Sopenharmony_ci   if (stream) {
238bf215546Sopenharmony_ci      trace_dump_indent(2);
239bf215546Sopenharmony_ci      trace_dump_tag_begin("time");
240bf215546Sopenharmony_ci      trace_dump_int(time);
241bf215546Sopenharmony_ci      trace_dump_tag_end("time");
242bf215546Sopenharmony_ci      trace_dump_newline();
243bf215546Sopenharmony_ci   }
244bf215546Sopenharmony_ci}
245bf215546Sopenharmony_ci
246bf215546Sopenharmony_ci
247bf215546Sopenharmony_cibool
248bf215546Sopenharmony_citrace_dump_trace_begin(void)
249bf215546Sopenharmony_ci{
250bf215546Sopenharmony_ci   const char *filename;
251bf215546Sopenharmony_ci
252bf215546Sopenharmony_ci   filename = debug_get_option("GALLIUM_TRACE", NULL);
253bf215546Sopenharmony_ci   if (!filename)
254bf215546Sopenharmony_ci      return false;
255bf215546Sopenharmony_ci
256bf215546Sopenharmony_ci   nir_count = debug_get_num_option("GALLIUM_TRACE_NIR", 32);
257bf215546Sopenharmony_ci
258bf215546Sopenharmony_ci   if (!stream) {
259bf215546Sopenharmony_ci
260bf215546Sopenharmony_ci      if (strcmp(filename, "stderr") == 0) {
261bf215546Sopenharmony_ci         close_stream = false;
262bf215546Sopenharmony_ci         stream = stderr;
263bf215546Sopenharmony_ci      }
264bf215546Sopenharmony_ci      else if (strcmp(filename, "stdout") == 0) {
265bf215546Sopenharmony_ci         close_stream = false;
266bf215546Sopenharmony_ci         stream = stdout;
267bf215546Sopenharmony_ci      }
268bf215546Sopenharmony_ci      else {
269bf215546Sopenharmony_ci         close_stream = true;
270bf215546Sopenharmony_ci         stream = fopen(filename, "wt");
271bf215546Sopenharmony_ci         if (!stream)
272bf215546Sopenharmony_ci            return false;
273bf215546Sopenharmony_ci      }
274bf215546Sopenharmony_ci
275bf215546Sopenharmony_ci      trace_dump_writes("<?xml version='1.0' encoding='UTF-8'?>\n");
276bf215546Sopenharmony_ci      trace_dump_writes("<?xml-stylesheet type='text/xsl' href='trace.xsl'?>\n");
277bf215546Sopenharmony_ci      trace_dump_writes("<trace version='0.1'>\n");
278bf215546Sopenharmony_ci
279bf215546Sopenharmony_ci      /* Many applications don't exit cleanly, others may create and destroy a
280bf215546Sopenharmony_ci       * screen multiple times, so we only write </trace> tag and close at exit
281bf215546Sopenharmony_ci       * time.
282bf215546Sopenharmony_ci       */
283bf215546Sopenharmony_ci      atexit(trace_dump_trace_close);
284bf215546Sopenharmony_ci
285bf215546Sopenharmony_ci      const char *trigger = debug_get_option("GALLIUM_TRACE_TRIGGER", NULL);
286bf215546Sopenharmony_ci      if (trigger) {
287bf215546Sopenharmony_ci         trigger_filename = strdup(trigger);
288bf215546Sopenharmony_ci         trigger_active = false;
289bf215546Sopenharmony_ci      } else
290bf215546Sopenharmony_ci         trigger_active = true;
291bf215546Sopenharmony_ci   }
292bf215546Sopenharmony_ci
293bf215546Sopenharmony_ci   return true;
294bf215546Sopenharmony_ci}
295bf215546Sopenharmony_ci
296bf215546Sopenharmony_cibool trace_dump_trace_enabled(void)
297bf215546Sopenharmony_ci{
298bf215546Sopenharmony_ci   return stream ? true : false;
299bf215546Sopenharmony_ci}
300bf215546Sopenharmony_ci
301bf215546Sopenharmony_ci/*
302bf215546Sopenharmony_ci * Call lock
303bf215546Sopenharmony_ci */
304bf215546Sopenharmony_ci
305bf215546Sopenharmony_civoid trace_dump_call_lock(void)
306bf215546Sopenharmony_ci{
307bf215546Sopenharmony_ci   mtx_lock(&call_mutex);
308bf215546Sopenharmony_ci}
309bf215546Sopenharmony_ci
310bf215546Sopenharmony_civoid trace_dump_call_unlock(void)
311bf215546Sopenharmony_ci{
312bf215546Sopenharmony_ci   mtx_unlock(&call_mutex);
313bf215546Sopenharmony_ci}
314bf215546Sopenharmony_ci
315bf215546Sopenharmony_ci/*
316bf215546Sopenharmony_ci * Dumping control
317bf215546Sopenharmony_ci */
318bf215546Sopenharmony_ci
319bf215546Sopenharmony_civoid trace_dumping_start_locked(void)
320bf215546Sopenharmony_ci{
321bf215546Sopenharmony_ci   dumping = true;
322bf215546Sopenharmony_ci}
323bf215546Sopenharmony_ci
324bf215546Sopenharmony_civoid trace_dumping_stop_locked(void)
325bf215546Sopenharmony_ci{
326bf215546Sopenharmony_ci   dumping = false;
327bf215546Sopenharmony_ci}
328bf215546Sopenharmony_ci
329bf215546Sopenharmony_cibool trace_dumping_enabled_locked(void)
330bf215546Sopenharmony_ci{
331bf215546Sopenharmony_ci   return dumping;
332bf215546Sopenharmony_ci}
333bf215546Sopenharmony_ci
334bf215546Sopenharmony_civoid trace_dumping_start(void)
335bf215546Sopenharmony_ci{
336bf215546Sopenharmony_ci   mtx_lock(&call_mutex);
337bf215546Sopenharmony_ci   trace_dumping_start_locked();
338bf215546Sopenharmony_ci   mtx_unlock(&call_mutex);
339bf215546Sopenharmony_ci}
340bf215546Sopenharmony_ci
341bf215546Sopenharmony_civoid trace_dumping_stop(void)
342bf215546Sopenharmony_ci{
343bf215546Sopenharmony_ci   mtx_lock(&call_mutex);
344bf215546Sopenharmony_ci   trace_dumping_stop_locked();
345bf215546Sopenharmony_ci   mtx_unlock(&call_mutex);
346bf215546Sopenharmony_ci}
347bf215546Sopenharmony_ci
348bf215546Sopenharmony_cibool trace_dumping_enabled(void)
349bf215546Sopenharmony_ci{
350bf215546Sopenharmony_ci   bool ret;
351bf215546Sopenharmony_ci   mtx_lock(&call_mutex);
352bf215546Sopenharmony_ci   ret = trace_dumping_enabled_locked();
353bf215546Sopenharmony_ci   mtx_unlock(&call_mutex);
354bf215546Sopenharmony_ci   return ret;
355bf215546Sopenharmony_ci}
356bf215546Sopenharmony_ci
357bf215546Sopenharmony_ci/*
358bf215546Sopenharmony_ci * Dump functions
359bf215546Sopenharmony_ci */
360bf215546Sopenharmony_ci
361bf215546Sopenharmony_cistatic int64_t call_start_time = 0;
362bf215546Sopenharmony_ci
363bf215546Sopenharmony_civoid trace_dump_call_begin_locked(const char *klass, const char *method)
364bf215546Sopenharmony_ci{
365bf215546Sopenharmony_ci   if (!dumping)
366bf215546Sopenharmony_ci      return;
367bf215546Sopenharmony_ci
368bf215546Sopenharmony_ci   ++call_no;
369bf215546Sopenharmony_ci   trace_dump_indent(1);
370bf215546Sopenharmony_ci   trace_dump_writes("<call no=\'");
371bf215546Sopenharmony_ci   trace_dump_writef("%lu", call_no);
372bf215546Sopenharmony_ci   trace_dump_writes("\' class=\'");
373bf215546Sopenharmony_ci   trace_dump_escape(klass);
374bf215546Sopenharmony_ci   trace_dump_writes("\' method=\'");
375bf215546Sopenharmony_ci   trace_dump_escape(method);
376bf215546Sopenharmony_ci   trace_dump_writes("\'>");
377bf215546Sopenharmony_ci   trace_dump_newline();
378bf215546Sopenharmony_ci
379bf215546Sopenharmony_ci   call_start_time = os_time_get();
380bf215546Sopenharmony_ci}
381bf215546Sopenharmony_ci
382bf215546Sopenharmony_civoid trace_dump_call_end_locked(void)
383bf215546Sopenharmony_ci{
384bf215546Sopenharmony_ci   int64_t call_end_time;
385bf215546Sopenharmony_ci
386bf215546Sopenharmony_ci   if (!dumping)
387bf215546Sopenharmony_ci      return;
388bf215546Sopenharmony_ci
389bf215546Sopenharmony_ci   call_end_time = os_time_get();
390bf215546Sopenharmony_ci
391bf215546Sopenharmony_ci   trace_dump_call_time(call_end_time - call_start_time);
392bf215546Sopenharmony_ci   trace_dump_indent(1);
393bf215546Sopenharmony_ci   trace_dump_tag_end("call");
394bf215546Sopenharmony_ci   trace_dump_newline();
395bf215546Sopenharmony_ci   fflush(stream);
396bf215546Sopenharmony_ci}
397bf215546Sopenharmony_ci
398bf215546Sopenharmony_civoid trace_dump_call_begin(const char *klass, const char *method)
399bf215546Sopenharmony_ci{
400bf215546Sopenharmony_ci   mtx_lock(&call_mutex);
401bf215546Sopenharmony_ci   trace_dump_call_begin_locked(klass, method);
402bf215546Sopenharmony_ci}
403bf215546Sopenharmony_ci
404bf215546Sopenharmony_civoid trace_dump_call_end(void)
405bf215546Sopenharmony_ci{
406bf215546Sopenharmony_ci   trace_dump_call_end_locked();
407bf215546Sopenharmony_ci   mtx_unlock(&call_mutex);
408bf215546Sopenharmony_ci}
409bf215546Sopenharmony_ci
410bf215546Sopenharmony_civoid trace_dump_arg_begin(const char *name)
411bf215546Sopenharmony_ci{
412bf215546Sopenharmony_ci   if (!dumping)
413bf215546Sopenharmony_ci      return;
414bf215546Sopenharmony_ci
415bf215546Sopenharmony_ci   trace_dump_indent(2);
416bf215546Sopenharmony_ci   trace_dump_tag_begin1("arg", "name", name);
417bf215546Sopenharmony_ci}
418bf215546Sopenharmony_ci
419bf215546Sopenharmony_civoid trace_dump_arg_end(void)
420bf215546Sopenharmony_ci{
421bf215546Sopenharmony_ci   if (!dumping)
422bf215546Sopenharmony_ci      return;
423bf215546Sopenharmony_ci
424bf215546Sopenharmony_ci   trace_dump_tag_end("arg");
425bf215546Sopenharmony_ci   trace_dump_newline();
426bf215546Sopenharmony_ci}
427bf215546Sopenharmony_ci
428bf215546Sopenharmony_civoid trace_dump_ret_begin(void)
429bf215546Sopenharmony_ci{
430bf215546Sopenharmony_ci   if (!dumping)
431bf215546Sopenharmony_ci      return;
432bf215546Sopenharmony_ci
433bf215546Sopenharmony_ci   trace_dump_indent(2);
434bf215546Sopenharmony_ci   trace_dump_tag_begin("ret");
435bf215546Sopenharmony_ci}
436bf215546Sopenharmony_ci
437bf215546Sopenharmony_civoid trace_dump_ret_end(void)
438bf215546Sopenharmony_ci{
439bf215546Sopenharmony_ci   if (!dumping)
440bf215546Sopenharmony_ci      return;
441bf215546Sopenharmony_ci
442bf215546Sopenharmony_ci   trace_dump_tag_end("ret");
443bf215546Sopenharmony_ci   trace_dump_newline();
444bf215546Sopenharmony_ci}
445bf215546Sopenharmony_ci
446bf215546Sopenharmony_civoid trace_dump_bool(int value)
447bf215546Sopenharmony_ci{
448bf215546Sopenharmony_ci   if (!dumping)
449bf215546Sopenharmony_ci      return;
450bf215546Sopenharmony_ci
451bf215546Sopenharmony_ci   trace_dump_writef("<bool>%c</bool>", value ? '1' : '0');
452bf215546Sopenharmony_ci}
453bf215546Sopenharmony_ci
454bf215546Sopenharmony_civoid trace_dump_int(long long int value)
455bf215546Sopenharmony_ci{
456bf215546Sopenharmony_ci   if (!dumping)
457bf215546Sopenharmony_ci      return;
458bf215546Sopenharmony_ci
459bf215546Sopenharmony_ci   trace_dump_writef("<int>%lli</int>", value);
460bf215546Sopenharmony_ci}
461bf215546Sopenharmony_ci
462bf215546Sopenharmony_civoid trace_dump_uint(long long unsigned value)
463bf215546Sopenharmony_ci{
464bf215546Sopenharmony_ci   if (!dumping)
465bf215546Sopenharmony_ci      return;
466bf215546Sopenharmony_ci
467bf215546Sopenharmony_ci   trace_dump_writef("<uint>%llu</uint>", value);
468bf215546Sopenharmony_ci}
469bf215546Sopenharmony_ci
470bf215546Sopenharmony_civoid trace_dump_float(double value)
471bf215546Sopenharmony_ci{
472bf215546Sopenharmony_ci   if (!dumping)
473bf215546Sopenharmony_ci      return;
474bf215546Sopenharmony_ci
475bf215546Sopenharmony_ci   trace_dump_writef("<float>%g</float>", value);
476bf215546Sopenharmony_ci}
477bf215546Sopenharmony_ci
478bf215546Sopenharmony_civoid trace_dump_bytes(const void *data,
479bf215546Sopenharmony_ci                      size_t size)
480bf215546Sopenharmony_ci{
481bf215546Sopenharmony_ci   static const char hex_table[16] = "0123456789ABCDEF";
482bf215546Sopenharmony_ci   const uint8_t *p = data;
483bf215546Sopenharmony_ci   size_t i;
484bf215546Sopenharmony_ci
485bf215546Sopenharmony_ci   if (!dumping)
486bf215546Sopenharmony_ci      return;
487bf215546Sopenharmony_ci
488bf215546Sopenharmony_ci   trace_dump_writes("<bytes>");
489bf215546Sopenharmony_ci   for(i = 0; i < size; ++i) {
490bf215546Sopenharmony_ci      uint8_t byte = *p++;
491bf215546Sopenharmony_ci      char hex[2];
492bf215546Sopenharmony_ci      hex[0] = hex_table[byte >> 4];
493bf215546Sopenharmony_ci      hex[1] = hex_table[byte & 0xf];
494bf215546Sopenharmony_ci      trace_dump_write(hex, 2);
495bf215546Sopenharmony_ci   }
496bf215546Sopenharmony_ci   trace_dump_writes("</bytes>");
497bf215546Sopenharmony_ci}
498bf215546Sopenharmony_ci
499bf215546Sopenharmony_civoid trace_dump_box_bytes(const void *data,
500bf215546Sopenharmony_ci                          struct pipe_resource *resource,
501bf215546Sopenharmony_ci			  const struct pipe_box *box,
502bf215546Sopenharmony_ci			  unsigned stride,
503bf215546Sopenharmony_ci			  unsigned slice_stride)
504bf215546Sopenharmony_ci{
505bf215546Sopenharmony_ci   enum pipe_format format = resource->format;
506bf215546Sopenharmony_ci   size_t size;
507bf215546Sopenharmony_ci
508bf215546Sopenharmony_ci   assert(box->height > 0);
509bf215546Sopenharmony_ci   assert(box->depth > 0);
510bf215546Sopenharmony_ci
511bf215546Sopenharmony_ci   size =  util_format_get_nblocksx(format, box->width )      * util_format_get_blocksize(format)
512bf215546Sopenharmony_ci        + (util_format_get_nblocksy(format, box->height) - 1) * stride
513bf215546Sopenharmony_ci        +                                  (box->depth   - 1) * slice_stride;
514bf215546Sopenharmony_ci
515bf215546Sopenharmony_ci   /*
516bf215546Sopenharmony_ci    * Only dump buffer transfers to avoid huge files.
517bf215546Sopenharmony_ci    * TODO: Make this run-time configurable
518bf215546Sopenharmony_ci    */
519bf215546Sopenharmony_ci   if (resource->target != PIPE_BUFFER) {
520bf215546Sopenharmony_ci      size = 0;
521bf215546Sopenharmony_ci   }
522bf215546Sopenharmony_ci
523bf215546Sopenharmony_ci   trace_dump_bytes(data, size);
524bf215546Sopenharmony_ci}
525bf215546Sopenharmony_ci
526bf215546Sopenharmony_civoid trace_dump_string(const char *str)
527bf215546Sopenharmony_ci{
528bf215546Sopenharmony_ci   if (!dumping)
529bf215546Sopenharmony_ci      return;
530bf215546Sopenharmony_ci
531bf215546Sopenharmony_ci   trace_dump_writes("<string>");
532bf215546Sopenharmony_ci   trace_dump_escape(str);
533bf215546Sopenharmony_ci   trace_dump_writes("</string>");
534bf215546Sopenharmony_ci}
535bf215546Sopenharmony_ci
536bf215546Sopenharmony_civoid trace_dump_enum(const char *value)
537bf215546Sopenharmony_ci{
538bf215546Sopenharmony_ci   if (!dumping)
539bf215546Sopenharmony_ci      return;
540bf215546Sopenharmony_ci
541bf215546Sopenharmony_ci   trace_dump_writes("<enum>");
542bf215546Sopenharmony_ci   trace_dump_escape(value);
543bf215546Sopenharmony_ci   trace_dump_writes("</enum>");
544bf215546Sopenharmony_ci}
545bf215546Sopenharmony_ci
546bf215546Sopenharmony_civoid trace_dump_array_begin(void)
547bf215546Sopenharmony_ci{
548bf215546Sopenharmony_ci   if (!dumping)
549bf215546Sopenharmony_ci      return;
550bf215546Sopenharmony_ci
551bf215546Sopenharmony_ci   trace_dump_writes("<array>");
552bf215546Sopenharmony_ci}
553bf215546Sopenharmony_ci
554bf215546Sopenharmony_civoid trace_dump_array_end(void)
555bf215546Sopenharmony_ci{
556bf215546Sopenharmony_ci   if (!dumping)
557bf215546Sopenharmony_ci      return;
558bf215546Sopenharmony_ci
559bf215546Sopenharmony_ci   trace_dump_writes("</array>");
560bf215546Sopenharmony_ci}
561bf215546Sopenharmony_ci
562bf215546Sopenharmony_civoid trace_dump_elem_begin(void)
563bf215546Sopenharmony_ci{
564bf215546Sopenharmony_ci   if (!dumping)
565bf215546Sopenharmony_ci      return;
566bf215546Sopenharmony_ci
567bf215546Sopenharmony_ci   trace_dump_writes("<elem>");
568bf215546Sopenharmony_ci}
569bf215546Sopenharmony_ci
570bf215546Sopenharmony_civoid trace_dump_elem_end(void)
571bf215546Sopenharmony_ci{
572bf215546Sopenharmony_ci   if (!dumping)
573bf215546Sopenharmony_ci      return;
574bf215546Sopenharmony_ci
575bf215546Sopenharmony_ci   trace_dump_writes("</elem>");
576bf215546Sopenharmony_ci}
577bf215546Sopenharmony_ci
578bf215546Sopenharmony_civoid trace_dump_struct_begin(const char *name)
579bf215546Sopenharmony_ci{
580bf215546Sopenharmony_ci   if (!dumping)
581bf215546Sopenharmony_ci      return;
582bf215546Sopenharmony_ci
583bf215546Sopenharmony_ci   trace_dump_writef("<struct name='%s'>", name);
584bf215546Sopenharmony_ci}
585bf215546Sopenharmony_ci
586bf215546Sopenharmony_civoid trace_dump_struct_end(void)
587bf215546Sopenharmony_ci{
588bf215546Sopenharmony_ci   if (!dumping)
589bf215546Sopenharmony_ci      return;
590bf215546Sopenharmony_ci
591bf215546Sopenharmony_ci   trace_dump_writes("</struct>");
592bf215546Sopenharmony_ci}
593bf215546Sopenharmony_ci
594bf215546Sopenharmony_civoid trace_dump_member_begin(const char *name)
595bf215546Sopenharmony_ci{
596bf215546Sopenharmony_ci   if (!dumping)
597bf215546Sopenharmony_ci      return;
598bf215546Sopenharmony_ci
599bf215546Sopenharmony_ci   trace_dump_writef("<member name='%s'>", name);
600bf215546Sopenharmony_ci}
601bf215546Sopenharmony_ci
602bf215546Sopenharmony_civoid trace_dump_member_end(void)
603bf215546Sopenharmony_ci{
604bf215546Sopenharmony_ci   if (!dumping)
605bf215546Sopenharmony_ci      return;
606bf215546Sopenharmony_ci
607bf215546Sopenharmony_ci   trace_dump_writes("</member>");
608bf215546Sopenharmony_ci}
609bf215546Sopenharmony_ci
610bf215546Sopenharmony_civoid trace_dump_null(void)
611bf215546Sopenharmony_ci{
612bf215546Sopenharmony_ci   if (!dumping)
613bf215546Sopenharmony_ci      return;
614bf215546Sopenharmony_ci
615bf215546Sopenharmony_ci   trace_dump_writes("<null/>");
616bf215546Sopenharmony_ci}
617bf215546Sopenharmony_ci
618bf215546Sopenharmony_civoid trace_dump_ptr(const void *value)
619bf215546Sopenharmony_ci{
620bf215546Sopenharmony_ci   if (!dumping)
621bf215546Sopenharmony_ci      return;
622bf215546Sopenharmony_ci
623bf215546Sopenharmony_ci   if(value)
624bf215546Sopenharmony_ci      trace_dump_writef("<ptr>0x%08lx</ptr>", (unsigned long)(uintptr_t)value);
625bf215546Sopenharmony_ci   else
626bf215546Sopenharmony_ci      trace_dump_null();
627bf215546Sopenharmony_ci}
628bf215546Sopenharmony_ci
629bf215546Sopenharmony_civoid trace_dump_surface_ptr(struct pipe_surface *_surface)
630bf215546Sopenharmony_ci{
631bf215546Sopenharmony_ci   if (!dumping)
632bf215546Sopenharmony_ci      return;
633bf215546Sopenharmony_ci
634bf215546Sopenharmony_ci   if (_surface) {
635bf215546Sopenharmony_ci      struct trace_surface *tr_surf = trace_surface(_surface);
636bf215546Sopenharmony_ci      trace_dump_ptr(tr_surf->surface);
637bf215546Sopenharmony_ci   } else {
638bf215546Sopenharmony_ci      trace_dump_null();
639bf215546Sopenharmony_ci   }
640bf215546Sopenharmony_ci}
641bf215546Sopenharmony_ci
642bf215546Sopenharmony_civoid trace_dump_transfer_ptr(struct pipe_transfer *_transfer)
643bf215546Sopenharmony_ci{
644bf215546Sopenharmony_ci   if (!dumping)
645bf215546Sopenharmony_ci      return;
646bf215546Sopenharmony_ci
647bf215546Sopenharmony_ci   if (_transfer) {
648bf215546Sopenharmony_ci      struct trace_transfer *tr_tran = trace_transfer(_transfer);
649bf215546Sopenharmony_ci      trace_dump_ptr(tr_tran->transfer);
650bf215546Sopenharmony_ci   } else {
651bf215546Sopenharmony_ci      trace_dump_null();
652bf215546Sopenharmony_ci   }
653bf215546Sopenharmony_ci}
654bf215546Sopenharmony_ci
655bf215546Sopenharmony_civoid trace_dump_nir(void *nir)
656bf215546Sopenharmony_ci{
657bf215546Sopenharmony_ci   if (!dumping)
658bf215546Sopenharmony_ci      return;
659bf215546Sopenharmony_ci
660bf215546Sopenharmony_ci   if (nir_count < 0) {
661bf215546Sopenharmony_ci      fputs("<string>...</string>", stream);
662bf215546Sopenharmony_ci      return;
663bf215546Sopenharmony_ci   }
664bf215546Sopenharmony_ci
665bf215546Sopenharmony_ci   if ((nir_count--) == 0) {
666bf215546Sopenharmony_ci      fputs("<string>Set GALLIUM_TRACE_NIR to a sufficiently big number "
667bf215546Sopenharmony_ci            "to enable NIR shader dumping.</string>", stream);
668bf215546Sopenharmony_ci      return;
669bf215546Sopenharmony_ci   }
670bf215546Sopenharmony_ci
671bf215546Sopenharmony_ci   // NIR doesn't have a print to string function.  Use CDATA and hope for the
672bf215546Sopenharmony_ci   // best.
673bf215546Sopenharmony_ci   if (stream) {
674bf215546Sopenharmony_ci      fputs("<string><![CDATA[", stream);
675bf215546Sopenharmony_ci      nir_print_shader(nir, stream);
676bf215546Sopenharmony_ci      fputs("]]></string>", stream);
677bf215546Sopenharmony_ci   }
678bf215546Sopenharmony_ci}
679