1/**************************************************************************
2 *
3 * Copyright 2008 VMware, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28#include "util/format/u_format.h"
29#include "util/u_memory.h"
30#include "util/hash_table.h"
31#include "util/simple_list.h"
32
33#include "tr_dump.h"
34#include "tr_dump_defines.h"
35#include "tr_dump_state.h"
36#include "tr_texture.h"
37#include "tr_context.h"
38#include "tr_screen.h"
39#include "tr_public.h"
40
41
42static bool trace = false;
43static struct hash_table *trace_screens;
44
45static const char *
46trace_screen_get_name(struct pipe_screen *_screen)
47{
48   struct trace_screen *tr_scr = trace_screen(_screen);
49   struct pipe_screen *screen = tr_scr->screen;
50   const char *result;
51
52   trace_dump_call_begin("pipe_screen", "get_name");
53
54   trace_dump_arg(ptr, screen);
55
56   result = screen->get_name(screen);
57
58   trace_dump_ret(string, result);
59
60   trace_dump_call_end();
61
62   return result;
63}
64
65
66static const char *
67trace_screen_get_vendor(struct pipe_screen *_screen)
68{
69   struct trace_screen *tr_scr = trace_screen(_screen);
70   struct pipe_screen *screen = tr_scr->screen;
71   const char *result;
72
73   trace_dump_call_begin("pipe_screen", "get_vendor");
74
75   trace_dump_arg(ptr, screen);
76
77   result = screen->get_vendor(screen);
78
79   trace_dump_ret(string, result);
80
81   trace_dump_call_end();
82
83   return result;
84}
85
86
87static const char *
88trace_screen_get_device_vendor(struct pipe_screen *_screen)
89{
90   struct trace_screen *tr_scr = trace_screen(_screen);
91   struct pipe_screen *screen = tr_scr->screen;
92   const char *result;
93
94   trace_dump_call_begin("pipe_screen", "get_device_vendor");
95
96   trace_dump_arg(ptr, screen);
97
98   result = screen->get_device_vendor(screen);
99
100   trace_dump_ret(string, result);
101
102   trace_dump_call_end();
103
104   return result;
105}
106
107
108static const void *
109trace_screen_get_compiler_options(struct pipe_screen *_screen,
110                                  enum pipe_shader_ir ir,
111                                  enum pipe_shader_type shader)
112{
113   struct trace_screen *tr_scr = trace_screen(_screen);
114   struct pipe_screen *screen = tr_scr->screen;
115
116   return screen->get_compiler_options(screen, ir, shader);
117}
118
119
120static struct disk_cache *
121trace_screen_get_disk_shader_cache(struct pipe_screen *_screen)
122{
123   struct trace_screen *tr_scr = trace_screen(_screen);
124   struct pipe_screen *screen = tr_scr->screen;
125
126   trace_dump_call_begin("pipe_screen", "get_disk_shader_cache");
127
128   trace_dump_arg(ptr, screen);
129
130   struct disk_cache *result = screen->get_disk_shader_cache(screen);
131
132   trace_dump_ret(ptr, result);
133
134   trace_dump_call_end();
135
136   return result;
137}
138
139
140static int
141trace_screen_get_param(struct pipe_screen *_screen,
142                       enum pipe_cap param)
143{
144   struct trace_screen *tr_scr = trace_screen(_screen);
145   struct pipe_screen *screen = tr_scr->screen;
146   int result;
147
148   trace_dump_call_begin("pipe_screen", "get_param");
149
150   trace_dump_arg(ptr, screen);
151   trace_dump_arg(int, param);
152
153   result = screen->get_param(screen, param);
154
155   trace_dump_ret(int, result);
156
157   trace_dump_call_end();
158
159   return result;
160}
161
162
163static int
164trace_screen_get_shader_param(struct pipe_screen *_screen,
165                              enum pipe_shader_type shader,
166                              enum pipe_shader_cap param)
167{
168   struct trace_screen *tr_scr = trace_screen(_screen);
169   struct pipe_screen *screen = tr_scr->screen;
170   int result;
171
172   trace_dump_call_begin("pipe_screen", "get_shader_param");
173
174   trace_dump_arg(ptr, screen);
175   trace_dump_arg(uint, shader);
176   trace_dump_arg(int, param);
177
178   result = screen->get_shader_param(screen, shader, param);
179
180   trace_dump_ret(int, result);
181
182   trace_dump_call_end();
183
184   return result;
185}
186
187
188static float
189trace_screen_get_paramf(struct pipe_screen *_screen,
190                        enum pipe_capf param)
191{
192   struct trace_screen *tr_scr = trace_screen(_screen);
193   struct pipe_screen *screen = tr_scr->screen;
194   float result;
195
196   trace_dump_call_begin("pipe_screen", "get_paramf");
197
198   trace_dump_arg(ptr, screen);
199   trace_dump_arg(int, param);
200
201   result = screen->get_paramf(screen, param);
202
203   trace_dump_ret(float, result);
204
205   trace_dump_call_end();
206
207   return result;
208}
209
210
211static int
212trace_screen_get_compute_param(struct pipe_screen *_screen,
213                               enum pipe_shader_ir ir_type,
214                               enum pipe_compute_cap param, void *data)
215{
216   struct trace_screen *tr_scr = trace_screen(_screen);
217   struct pipe_screen *screen = tr_scr->screen;
218   int result;
219
220   trace_dump_call_begin("pipe_screen", "get_compute_param");
221
222   trace_dump_arg(ptr, screen);
223   trace_dump_arg(int, ir_type);
224   trace_dump_arg(int, param);
225   trace_dump_arg(ptr, data);
226
227   result = screen->get_compute_param(screen, ir_type, param, data);
228
229   trace_dump_ret(int, result);
230
231   trace_dump_call_end();
232
233   return result;
234}
235
236
237static bool
238trace_screen_is_format_supported(struct pipe_screen *_screen,
239                                 enum pipe_format format,
240                                 enum pipe_texture_target target,
241                                 unsigned sample_count,
242                                 unsigned storage_sample_count,
243                                 unsigned tex_usage)
244{
245   struct trace_screen *tr_scr = trace_screen(_screen);
246   struct pipe_screen *screen = tr_scr->screen;
247   bool result;
248
249   trace_dump_call_begin("pipe_screen", "is_format_supported");
250
251   trace_dump_arg(ptr, screen);
252   trace_dump_arg(format, format);
253   trace_dump_arg(int, target);
254   trace_dump_arg(uint, sample_count);
255   trace_dump_arg(uint, tex_usage);
256
257   result = screen->is_format_supported(screen, format, target, sample_count,
258                                        storage_sample_count, tex_usage);
259
260   trace_dump_ret(bool, result);
261
262   trace_dump_call_end();
263
264   return result;
265}
266
267static void
268trace_context_replace_buffer_storage(struct pipe_context *_pipe,
269                                     struct pipe_resource *dst,
270                                     struct pipe_resource *src,
271                                     unsigned num_rebinds,
272                                     uint32_t rebind_mask,
273                                     unsigned delete_buffer_id)
274{
275   struct trace_context *tr_ctx = trace_context(_pipe);
276   struct pipe_context *pipe = tr_ctx->pipe;
277
278   trace_dump_call_begin("pipe_context", "replace_buffer_storage");
279
280   trace_dump_arg(ptr, pipe);
281   trace_dump_arg(ptr, dst);
282   trace_dump_arg(ptr, src);
283   trace_dump_arg(uint, num_rebinds);
284   trace_dump_arg(uint, rebind_mask);
285   trace_dump_arg(uint, delete_buffer_id);
286   trace_dump_call_end();
287
288   tr_ctx->replace_buffer_storage(pipe, dst, src, num_rebinds, rebind_mask, delete_buffer_id);
289}
290
291static struct pipe_fence_handle *
292trace_context_create_fence(struct pipe_context *_pipe, struct tc_unflushed_batch_token *token)
293{
294   struct trace_context *tr_ctx = trace_context(_pipe);
295   struct pipe_context *pipe = tr_ctx->pipe;
296
297   trace_dump_call_begin("pipe_context", "create_fence");
298
299   trace_dump_arg(ptr, pipe);
300   trace_dump_arg(ptr, token);
301
302   struct pipe_fence_handle *ret = tr_ctx->create_fence(pipe, token);
303   trace_dump_ret(ptr, ret);
304   trace_dump_call_end();
305
306   return ret;
307}
308
309static bool
310trace_context_is_resource_busy(struct pipe_screen *_screen,
311                               struct pipe_resource *resource,
312                               unsigned usage)
313{
314   struct trace_screen *tr_scr = trace_screen(_screen);
315   struct pipe_screen *screen = tr_scr->screen;
316   bool result;
317
318   trace_dump_call_begin("pipe_screen", "is_resource_busy");
319
320   trace_dump_arg(ptr, screen);
321   trace_dump_arg(ptr, resource);
322   trace_dump_arg(uint, usage);
323
324   result = tr_scr->is_resource_busy(screen, resource, usage);
325
326   trace_dump_ret(bool, result);
327
328   trace_dump_call_end();
329
330   return result;
331}
332
333struct pipe_context *
334trace_context_create_threaded(struct pipe_screen *screen, struct pipe_context *pipe,
335                              tc_replace_buffer_storage_func *replace_buffer,
336                              struct threaded_context_options *options)
337{
338   if (!trace_screens)
339      return pipe;
340
341   struct hash_entry *he = _mesa_hash_table_search(trace_screens, screen);
342   if (!he)
343      return pipe;
344   struct trace_screen *tr_scr = trace_screen(he->data);
345
346   if (tr_scr->trace_tc)
347      return pipe;
348
349   struct pipe_context *ctx = trace_context_create(tr_scr, pipe);
350   if (!ctx)
351      return pipe;
352
353   struct trace_context *tr_ctx = trace_context(ctx);
354   tr_ctx->replace_buffer_storage = *replace_buffer;
355   tr_ctx->create_fence = options->create_fence;
356   tr_scr->is_resource_busy = options->is_resource_busy;
357   tr_ctx->threaded = true;
358   *replace_buffer = trace_context_replace_buffer_storage;
359   if (options->create_fence)
360      options->create_fence = trace_context_create_fence;
361   if (options->is_resource_busy)
362      options->is_resource_busy = trace_context_is_resource_busy;
363   return ctx;
364}
365
366static struct pipe_context *
367trace_screen_context_create(struct pipe_screen *_screen, void *priv,
368                            unsigned flags)
369{
370   struct trace_screen *tr_scr = trace_screen(_screen);
371   struct pipe_screen *screen = tr_scr->screen;
372   struct pipe_context *result;
373
374   result = screen->context_create(screen, priv, flags);
375
376   trace_dump_call_begin("pipe_screen", "context_create");
377
378   trace_dump_arg(ptr, screen);
379   trace_dump_arg(ptr, priv);
380   trace_dump_arg(uint, flags);
381
382   trace_dump_ret(ptr, result);
383
384   trace_dump_call_end();
385
386   if (result && (tr_scr->trace_tc || result->draw_vbo != tc_draw_vbo))
387      result = trace_context_create(tr_scr, result);
388
389   return result;
390}
391
392
393static void
394trace_screen_flush_frontbuffer(struct pipe_screen *_screen,
395                               struct pipe_context *_pipe,
396                               struct pipe_resource *resource,
397                               unsigned level, unsigned layer,
398                               void *context_private,
399                               struct pipe_box *sub_box)
400{
401   struct trace_screen *tr_scr = trace_screen(_screen);
402   struct pipe_screen *screen = tr_scr->screen;
403   struct pipe_context *pipe = _pipe ? trace_get_possibly_threaded_context(_pipe) : NULL;
404
405   trace_dump_call_begin("pipe_screen", "flush_frontbuffer");
406
407   trace_dump_arg(ptr, screen);
408   trace_dump_arg(ptr, resource);
409   trace_dump_arg(uint, level);
410   trace_dump_arg(uint, layer);
411   /* XXX: hide, as there is nothing we can do with this
412   trace_dump_arg(ptr, context_private);
413   */
414
415   trace_dump_call_end();
416
417   screen->flush_frontbuffer(screen, pipe, resource, level, layer, context_private, sub_box);
418}
419
420
421static void
422trace_screen_get_driver_uuid(struct pipe_screen *_screen, char *uuid)
423{
424   struct pipe_screen *screen = trace_screen(_screen)->screen;
425
426   trace_dump_call_begin("pipe_screen", "get_driver_uuid");
427   trace_dump_arg(ptr, screen);
428
429   screen->get_driver_uuid(screen, uuid);
430
431   trace_dump_ret(string, uuid);
432   trace_dump_call_end();
433}
434
435static void
436trace_screen_get_device_uuid(struct pipe_screen *_screen, char *uuid)
437{
438   struct pipe_screen *screen = trace_screen(_screen)->screen;
439
440   trace_dump_call_begin("pipe_screen", "get_device_uuid");
441   trace_dump_arg(ptr, screen);
442
443   screen->get_device_uuid(screen, uuid);
444
445   trace_dump_ret(string, uuid);
446   trace_dump_call_end();
447}
448
449
450/********************************************************************
451 * texture
452 */
453
454static void *
455trace_screen_map_memory(struct pipe_screen *_screen,
456                        struct pipe_memory_allocation *pmem)
457{
458   struct trace_screen *tr_scr = trace_screen(_screen);
459   struct pipe_screen *screen = tr_scr->screen;
460   void *result;
461
462   trace_dump_call_begin("pipe_screen", "map_memory");
463
464   trace_dump_arg(ptr, screen);
465   trace_dump_arg(ptr, pmem);
466
467   result = screen->map_memory(screen, pmem);
468
469   trace_dump_ret(ptr, result);
470
471   trace_dump_call_end();
472
473   return result;
474}
475
476static void
477trace_screen_unmap_memory(struct pipe_screen *_screen,
478                          struct pipe_memory_allocation *pmem)
479{
480   struct trace_screen *tr_scr = trace_screen(_screen);
481   struct pipe_screen *screen = tr_scr->screen;
482
483   trace_dump_call_begin("pipe_screen", "unmap_memory");
484
485   trace_dump_arg(ptr, screen);
486   trace_dump_arg(ptr, pmem);
487
488   screen->unmap_memory(screen, pmem);
489
490
491   trace_dump_call_end();
492}
493
494static struct pipe_memory_allocation *
495trace_screen_allocate_memory(struct pipe_screen *_screen,
496                             uint64_t size)
497{
498   struct trace_screen *tr_scr = trace_screen(_screen);
499   struct pipe_screen *screen = tr_scr->screen;
500   struct pipe_memory_allocation *result;
501
502   trace_dump_call_begin("pipe_screen", "allocate_memory");
503
504   trace_dump_arg(ptr, screen);
505   trace_dump_arg(uint, size);
506
507   result = screen->allocate_memory(screen, size);
508
509   trace_dump_ret(ptr, result);
510
511   trace_dump_call_end();
512
513   return result;
514}
515
516static void
517trace_screen_free_memory(struct pipe_screen *_screen,
518                         struct pipe_memory_allocation *pmem)
519{
520   struct trace_screen *tr_scr = trace_screen(_screen);
521   struct pipe_screen *screen = tr_scr->screen;
522
523   trace_dump_call_begin("pipe_screen", "free_memory");
524
525   trace_dump_arg(ptr, screen);
526   trace_dump_arg(ptr, pmem);
527
528   screen->free_memory(screen, pmem);
529
530
531   trace_dump_call_end();
532}
533
534static bool
535trace_screen_resource_bind_backing(struct pipe_screen *_screen,
536                                   struct pipe_resource *resource,
537                                   struct pipe_memory_allocation *pmem,
538                                   uint64_t offset)
539{
540   struct trace_screen *tr_scr = trace_screen(_screen);
541   struct pipe_screen *screen = tr_scr->screen;
542   bool result;
543
544   trace_dump_call_begin("pipe_screen", "resource_bind_backing");
545
546   trace_dump_arg(ptr, screen);
547   trace_dump_arg(ptr, resource);
548   trace_dump_arg(ptr, pmem);
549   trace_dump_arg(uint, offset);
550
551   result = screen->resource_bind_backing(screen, resource, pmem, offset);
552
553   trace_dump_ret(bool, result);
554
555   trace_dump_call_end();
556
557   return result;
558}
559
560static struct pipe_resource *
561trace_screen_resource_create_unbacked(struct pipe_screen *_screen,
562                                      const struct pipe_resource *templat,
563                                      uint64_t *size_required)
564{
565   struct trace_screen *tr_scr = trace_screen(_screen);
566   struct pipe_screen *screen = tr_scr->screen;
567   struct pipe_resource *result;
568
569   trace_dump_call_begin("pipe_screen", "resource_create_unbacked");
570
571   trace_dump_arg(ptr, screen);
572   trace_dump_arg(resource_template, templat);
573
574   result = screen->resource_create_unbacked(screen, templat, size_required);
575
576   trace_dump_ret_begin();
577   trace_dump_uint(*size_required);
578   trace_dump_ret_end();
579   trace_dump_ret(ptr, result);
580
581   trace_dump_call_end();
582
583   if (result)
584      result->screen = _screen;
585   return result;
586}
587
588static struct pipe_resource *
589trace_screen_resource_create(struct pipe_screen *_screen,
590                            const struct pipe_resource *templat)
591{
592   struct trace_screen *tr_scr = trace_screen(_screen);
593   struct pipe_screen *screen = tr_scr->screen;
594   struct pipe_resource *result;
595
596   trace_dump_call_begin("pipe_screen", "resource_create");
597
598   trace_dump_arg(ptr, screen);
599   trace_dump_arg(resource_template, templat);
600
601   result = screen->resource_create(screen, templat);
602
603   trace_dump_ret(ptr, result);
604
605   trace_dump_call_end();
606
607   if (result)
608      result->screen = _screen;
609   return result;
610}
611
612static struct pipe_resource *
613trace_screen_resource_create_with_modifiers(struct pipe_screen *_screen, const struct pipe_resource *templat,
614                                            const uint64_t *modifiers, int modifiers_count)
615{
616   struct trace_screen *tr_scr = trace_screen(_screen);
617   struct pipe_screen *screen = tr_scr->screen;
618   struct pipe_resource *result;
619
620   trace_dump_call_begin("pipe_screen", "resource_create_with_modifiers");
621
622   trace_dump_arg(ptr, screen);
623   trace_dump_arg(resource_template, templat);
624   trace_dump_arg_array(uint, modifiers, modifiers_count);
625
626   result = screen->resource_create_with_modifiers(screen, templat, modifiers, modifiers_count);
627
628   trace_dump_ret(ptr, result);
629
630   trace_dump_call_end();
631
632   if (result)
633      result->screen = _screen;
634   return result;
635}
636
637static struct pipe_resource *
638trace_screen_resource_from_handle(struct pipe_screen *_screen,
639                                 const struct pipe_resource *templ,
640                                 struct winsys_handle *handle,
641                                  unsigned usage)
642{
643   struct trace_screen *tr_screen = trace_screen(_screen);
644   struct pipe_screen *screen = tr_screen->screen;
645   struct pipe_resource *result;
646
647   /* TODO trace call */
648
649   result = screen->resource_from_handle(screen, templ, handle, usage);
650
651   if (result)
652      result->screen = _screen;
653   return result;
654}
655
656static bool
657trace_screen_check_resource_capability(struct pipe_screen *_screen,
658                                       struct pipe_resource *resource,
659                                       unsigned bind)
660{
661   struct pipe_screen *screen = trace_screen(_screen)->screen;
662
663   return screen->check_resource_capability(screen, resource, bind);
664}
665
666static bool
667trace_screen_resource_get_handle(struct pipe_screen *_screen,
668                                 struct pipe_context *_pipe,
669                                struct pipe_resource *resource,
670                                struct winsys_handle *handle,
671                                 unsigned usage)
672{
673   struct trace_screen *tr_screen = trace_screen(_screen);
674   struct pipe_context *pipe = _pipe ? trace_get_possibly_threaded_context(_pipe) : NULL;
675   struct pipe_screen *screen = tr_screen->screen;
676
677   /* TODO trace call */
678
679   return screen->resource_get_handle(screen, pipe,
680                                      resource, handle, usage);
681}
682
683static bool
684trace_screen_resource_get_param(struct pipe_screen *_screen,
685                                struct pipe_context *_pipe,
686                                struct pipe_resource *resource,
687                                unsigned plane,
688                                unsigned layer,
689                                unsigned level,
690                                enum pipe_resource_param param,
691                                unsigned handle_usage,
692                                uint64_t *value)
693{
694   struct trace_screen *tr_screen = trace_screen(_screen);
695   struct pipe_context *pipe = _pipe ? trace_get_possibly_threaded_context(_pipe) : NULL;
696   struct pipe_screen *screen = tr_screen->screen;
697
698   /* TODO trace call */
699
700   return screen->resource_get_param(screen, pipe,
701                                     resource, plane, layer, level, param,
702                                     handle_usage, value);
703}
704
705static void
706trace_screen_resource_get_info(struct pipe_screen *_screen,
707                               struct pipe_resource *resource,
708                               unsigned *stride,
709                               unsigned *offset)
710{
711   struct trace_screen *tr_screen = trace_screen(_screen);
712   struct pipe_screen *screen = tr_screen->screen;
713
714   /* TODO trace call */
715
716   screen->resource_get_info(screen, resource, stride, offset);
717}
718
719static struct pipe_resource *
720trace_screen_resource_from_memobj(struct pipe_screen *_screen,
721                                  const struct pipe_resource *templ,
722                                  struct pipe_memory_object *memobj,
723                                  uint64_t offset)
724{
725   struct pipe_screen *screen = trace_screen(_screen)->screen;
726
727   trace_dump_call_begin("pipe_screen", "resource_from_memobj");
728   trace_dump_arg(ptr, screen);
729   trace_dump_arg(resource_template, templ);
730   trace_dump_arg(ptr, memobj);
731   trace_dump_arg(uint, offset);
732
733   struct pipe_resource *res =
734      screen->resource_from_memobj(screen, templ, memobj, offset);
735
736   if (!res)
737      return NULL;
738   res->screen = _screen;
739
740   trace_dump_ret(ptr, res);
741   trace_dump_call_end();
742   return res;
743}
744
745static void
746trace_screen_resource_changed(struct pipe_screen *_screen,
747                              struct pipe_resource *resource)
748{
749   struct trace_screen *tr_scr = trace_screen(_screen);
750   struct pipe_screen *screen = tr_scr->screen;
751
752   trace_dump_call_begin("pipe_screen", "resource_changed");
753
754   trace_dump_arg(ptr, screen);
755   trace_dump_arg(ptr, resource);
756
757   if (screen->resource_changed)
758      screen->resource_changed(screen, resource);
759
760   trace_dump_call_end();
761}
762
763static void
764trace_screen_resource_destroy(struct pipe_screen *_screen,
765			      struct pipe_resource *resource)
766{
767   struct trace_screen *tr_scr = trace_screen(_screen);
768   struct pipe_screen *screen = tr_scr->screen;
769
770   /* Don't trace this, because due to the lack of pipe_resource wrapping,
771    * we can get this call from inside of driver calls, which would try
772    * to lock an already-locked mutex.
773    */
774   screen->resource_destroy(screen, resource);
775}
776
777
778/********************************************************************
779 * fence
780 */
781
782
783static void
784trace_screen_fence_reference(struct pipe_screen *_screen,
785                             struct pipe_fence_handle **pdst,
786                             struct pipe_fence_handle *src)
787{
788   struct trace_screen *tr_scr = trace_screen(_screen);
789   struct pipe_screen *screen = tr_scr->screen;
790   struct pipe_fence_handle *dst;
791
792   assert(pdst);
793   dst = *pdst;
794
795   trace_dump_call_begin("pipe_screen", "fence_reference");
796
797   trace_dump_arg(ptr, screen);
798   trace_dump_arg(ptr, dst);
799   trace_dump_arg(ptr, src);
800
801   screen->fence_reference(screen, pdst, src);
802
803   trace_dump_call_end();
804}
805
806
807static int
808trace_screen_fence_get_fd(struct pipe_screen *_screen,
809                          struct pipe_fence_handle *fence)
810{
811   struct trace_screen *tr_scr = trace_screen(_screen);
812   struct pipe_screen *screen = tr_scr->screen;
813   int result;
814
815   trace_dump_call_begin("pipe_screen", "fence_get_fd");
816
817   trace_dump_arg(ptr, screen);
818   trace_dump_arg(ptr, fence);
819
820   result = screen->fence_get_fd(screen, fence);
821
822   trace_dump_ret(int, result);
823
824   trace_dump_call_end();
825
826   return result;
827}
828
829
830static bool
831trace_screen_fence_finish(struct pipe_screen *_screen,
832                          struct pipe_context *_ctx,
833                          struct pipe_fence_handle *fence,
834                          uint64_t timeout)
835{
836   struct trace_screen *tr_scr = trace_screen(_screen);
837   struct pipe_screen *screen = tr_scr->screen;
838   struct pipe_context *ctx = _ctx ? trace_get_possibly_threaded_context(_ctx) : NULL;
839   int result;
840
841   result = screen->fence_finish(screen, ctx, fence, timeout);
842
843
844   trace_dump_call_begin("pipe_screen", "fence_finish");
845
846   trace_dump_arg(ptr, screen);
847   trace_dump_arg(ptr, ctx);
848   trace_dump_arg(ptr, fence);
849   trace_dump_arg(uint, timeout);
850
851   trace_dump_ret(bool, result);
852
853   trace_dump_call_end();
854
855   return result;
856}
857
858
859/********************************************************************
860 * memobj
861 */
862
863static struct pipe_memory_object *
864trace_screen_memobj_create_from_handle(struct pipe_screen *_screen,
865                                       struct winsys_handle *handle,
866                                       bool dedicated)
867{
868   struct pipe_screen *screen = trace_screen(_screen)->screen;
869
870   trace_dump_call_begin("pipe_screen", "memobj_create_from_handle");
871   trace_dump_arg(ptr, screen);
872   trace_dump_arg(ptr, handle);
873   trace_dump_arg(bool, dedicated);
874
875   struct pipe_memory_object *res =
876      screen->memobj_create_from_handle(screen, handle, dedicated);
877
878   trace_dump_ret(ptr, res);
879   trace_dump_call_end();
880
881   return res;
882}
883
884static void
885trace_screen_memobj_destroy(struct pipe_screen *_screen,
886                            struct pipe_memory_object *memobj)
887{
888   struct pipe_screen *screen = trace_screen(_screen)->screen;
889
890   trace_dump_call_begin("pipe_screen", "memobj_destroy");
891   trace_dump_arg(ptr, screen);
892   trace_dump_arg(ptr, memobj);
893   trace_dump_call_end();
894
895   screen->memobj_destroy(screen, memobj);
896}
897
898
899/********************************************************************
900 * screen
901 */
902
903static uint64_t
904trace_screen_get_timestamp(struct pipe_screen *_screen)
905{
906   struct trace_screen *tr_scr = trace_screen(_screen);
907   struct pipe_screen *screen = tr_scr->screen;
908   uint64_t result;
909
910   trace_dump_call_begin("pipe_screen", "get_timestamp");
911   trace_dump_arg(ptr, screen);
912
913   result = screen->get_timestamp(screen);
914
915   trace_dump_ret(uint, result);
916   trace_dump_call_end();
917
918   return result;
919}
920
921static char *
922trace_screen_finalize_nir(struct pipe_screen *_screen, void *nir)
923{
924   struct pipe_screen *screen = trace_screen(_screen)->screen;
925
926   return screen->finalize_nir(screen, nir);
927}
928
929static void
930trace_screen_destroy(struct pipe_screen *_screen)
931{
932   struct trace_screen *tr_scr = trace_screen(_screen);
933   struct pipe_screen *screen = tr_scr->screen;
934
935   trace_dump_call_begin("pipe_screen", "destroy");
936   trace_dump_arg(ptr, screen);
937   trace_dump_call_end();
938
939   if (trace_screens) {
940      struct hash_entry *he = _mesa_hash_table_search(trace_screens, screen);
941      if (he) {
942         _mesa_hash_table_remove(trace_screens, he);
943         if (!_mesa_hash_table_num_entries(trace_screens)) {
944            _mesa_hash_table_destroy(trace_screens, NULL);
945            trace_screens = NULL;
946         }
947      }
948   }
949
950   screen->destroy(screen);
951
952   FREE(tr_scr);
953}
954
955static void
956trace_screen_query_memory_info(struct pipe_screen *_screen, struct pipe_memory_info *info)
957{
958   struct trace_screen *tr_scr = trace_screen(_screen);
959   struct pipe_screen *screen = tr_scr->screen;
960
961   trace_dump_call_begin("pipe_screen", "query_memory_info");
962
963   trace_dump_arg(ptr, screen);
964
965   screen->query_memory_info(screen, info);
966
967   trace_dump_ret(memory_info, info);
968
969   trace_dump_call_end();
970}
971
972static void
973trace_screen_query_dmabuf_modifiers(struct pipe_screen *_screen, enum pipe_format format, int max, uint64_t *modifiers, unsigned int *external_only, int *count)
974{
975   struct trace_screen *tr_scr = trace_screen(_screen);
976   struct pipe_screen *screen = tr_scr->screen;
977
978   trace_dump_call_begin("pipe_screen", "query_dmabuf_modifiers");
979
980   trace_dump_arg(ptr, screen);
981   trace_dump_arg(format, format);
982   trace_dump_arg(int, max);
983
984   screen->query_dmabuf_modifiers(screen, format, max, modifiers, external_only, count);
985
986   if (max)
987      trace_dump_arg_array(uint, modifiers, *count);
988   else
989      trace_dump_arg_array(uint, modifiers, max);
990   trace_dump_arg_array(uint, external_only, max);
991   trace_dump_ret_begin();
992   trace_dump_uint(*count);
993   trace_dump_ret_end();
994
995   trace_dump_call_end();
996}
997
998static bool
999trace_screen_is_dmabuf_modifier_supported(struct pipe_screen *_screen, uint64_t modifier, enum pipe_format format, bool *external_only)
1000{
1001   struct trace_screen *tr_scr = trace_screen(_screen);
1002   struct pipe_screen *screen = tr_scr->screen;
1003
1004   trace_dump_call_begin("pipe_screen", "is_dmabuf_modifier_supported");
1005
1006   trace_dump_arg(ptr, screen);
1007   trace_dump_arg(uint, modifier);
1008   trace_dump_arg(format, format);
1009
1010   bool ret = screen->is_dmabuf_modifier_supported(screen, modifier, format, external_only);
1011
1012   trace_dump_arg_begin("external_only");
1013   trace_dump_bool(external_only ? *external_only : false);
1014   trace_dump_arg_end();
1015
1016   trace_dump_ret(bool, ret);
1017
1018   trace_dump_call_end();
1019   return ret;
1020}
1021
1022static unsigned int
1023trace_screen_get_dmabuf_modifier_planes(struct pipe_screen *_screen, uint64_t modifier, enum pipe_format format)
1024{
1025   struct trace_screen *tr_scr = trace_screen(_screen);
1026   struct pipe_screen *screen = tr_scr->screen;
1027
1028   trace_dump_call_begin("pipe_screen", "get_dmabuf_modifier_planes");
1029
1030   trace_dump_arg(ptr, screen);
1031   trace_dump_arg(uint, modifier);
1032   trace_dump_arg(format, format);
1033
1034   unsigned ret = screen->get_dmabuf_modifier_planes(screen, modifier, format);
1035
1036   trace_dump_ret(uint, ret);
1037
1038   trace_dump_call_end();
1039   return ret;
1040}
1041
1042static struct pipe_vertex_state *
1043trace_screen_create_vertex_state(struct pipe_screen *_screen,
1044                                 struct pipe_vertex_buffer *buffer,
1045                                 const struct pipe_vertex_element *elements,
1046                                 unsigned num_elements,
1047                                 struct pipe_resource *indexbuf,
1048                                 uint32_t full_velem_mask)
1049{
1050   struct trace_screen *tr_scr = trace_screen(_screen);
1051   struct pipe_screen *screen = tr_scr->screen;
1052
1053   trace_dump_call_begin("pipe_screen", "create_vertex_state");
1054
1055   trace_dump_arg(ptr, screen);
1056   trace_dump_arg(ptr, buffer->buffer.resource);
1057   trace_dump_arg(vertex_buffer, buffer);
1058   trace_dump_arg_begin("elements");
1059   trace_dump_struct_array(vertex_element, elements, num_elements);
1060   trace_dump_arg_end();
1061   trace_dump_arg(uint, num_elements);
1062   trace_dump_arg(ptr, indexbuf);
1063   trace_dump_arg(uint, full_velem_mask);
1064
1065   struct pipe_vertex_state *vstate =
1066      screen->create_vertex_state(screen, buffer, elements, num_elements,
1067                                  indexbuf, full_velem_mask);
1068   trace_dump_ret(ptr, vstate);
1069   trace_dump_call_end();
1070   return vstate;
1071}
1072
1073static void trace_screen_vertex_state_destroy(struct pipe_screen *_screen,
1074                                              struct pipe_vertex_state *state)
1075{
1076   struct trace_screen *tr_scr = trace_screen(_screen);
1077   struct pipe_screen *screen = tr_scr->screen;
1078
1079   trace_dump_call_begin("pipe_screen", "vertex_state_destroy");
1080   trace_dump_arg(ptr, screen);
1081   trace_dump_arg(ptr, state);
1082   trace_dump_call_end();
1083
1084   screen->vertex_state_destroy(screen, state);
1085}
1086
1087bool
1088trace_enabled(void)
1089{
1090   static bool firstrun = true;
1091
1092   if (!firstrun)
1093      return trace;
1094   firstrun = false;
1095
1096   if(trace_dump_trace_begin()) {
1097      trace_dumping_start();
1098      trace = true;
1099   }
1100
1101   return trace;
1102}
1103
1104struct pipe_screen *
1105trace_screen_create(struct pipe_screen *screen)
1106{
1107   struct trace_screen *tr_scr;
1108
1109#ifdef ZINK_WITH_SWRAST_VK
1110   /* if zink+lavapipe is enabled, ensure that only one driver is traced */
1111   const char *driver = debug_get_option("MESA_LOADER_DRIVER_OVERRIDE", NULL);
1112   if (driver && !strcmp(driver, "zink")) {
1113      /* the user wants zink: check whether they want to trace zink or lavapipe */
1114      bool trace_lavapipe = debug_get_bool_option("ZINK_TRACE_LAVAPIPE", false);
1115      if (!strncmp(screen->get_name(screen), "zink", 4)) {
1116         /* this is the zink screen: only trace if lavapipe tracing is disabled */
1117         if (trace_lavapipe)
1118            return screen;
1119      } else {
1120         /* this is the llvmpipe screen: only trace if lavapipe tracing is enabled */
1121         if (!trace_lavapipe)
1122            return screen;
1123      }
1124   }
1125#endif
1126   if (!trace_enabled())
1127      goto error1;
1128
1129   trace_dump_call_begin("", "pipe_screen_create");
1130
1131   tr_scr = CALLOC_STRUCT(trace_screen);
1132   if (!tr_scr)
1133      goto error2;
1134
1135#define SCR_INIT(_member) \
1136   tr_scr->base._member = screen->_member ? trace_screen_##_member : NULL
1137
1138   tr_scr->base.destroy = trace_screen_destroy;
1139   tr_scr->base.get_name = trace_screen_get_name;
1140   tr_scr->base.get_vendor = trace_screen_get_vendor;
1141   tr_scr->base.get_device_vendor = trace_screen_get_device_vendor;
1142   SCR_INIT(get_compiler_options);
1143   SCR_INIT(get_disk_shader_cache);
1144   tr_scr->base.get_param = trace_screen_get_param;
1145   tr_scr->base.get_shader_param = trace_screen_get_shader_param;
1146   tr_scr->base.get_paramf = trace_screen_get_paramf;
1147   tr_scr->base.get_compute_param = trace_screen_get_compute_param;
1148   tr_scr->base.is_format_supported = trace_screen_is_format_supported;
1149   assert(screen->context_create);
1150   tr_scr->base.context_create = trace_screen_context_create;
1151   tr_scr->base.resource_create = trace_screen_resource_create;
1152   SCR_INIT(resource_create_with_modifiers);
1153   tr_scr->base.resource_create_unbacked = trace_screen_resource_create_unbacked;
1154   tr_scr->base.resource_bind_backing = trace_screen_resource_bind_backing;
1155   tr_scr->base.resource_from_handle = trace_screen_resource_from_handle;
1156   tr_scr->base.allocate_memory = trace_screen_allocate_memory;
1157   tr_scr->base.free_memory = trace_screen_free_memory;
1158   tr_scr->base.map_memory = trace_screen_map_memory;
1159   tr_scr->base.unmap_memory = trace_screen_unmap_memory;
1160   SCR_INIT(query_memory_info);
1161   SCR_INIT(query_dmabuf_modifiers);
1162   SCR_INIT(is_dmabuf_modifier_supported);
1163   SCR_INIT(get_dmabuf_modifier_planes);
1164   SCR_INIT(check_resource_capability);
1165   tr_scr->base.resource_get_handle = trace_screen_resource_get_handle;
1166   SCR_INIT(resource_get_param);
1167   SCR_INIT(resource_get_info);
1168   SCR_INIT(resource_from_memobj);
1169   SCR_INIT(resource_changed);
1170   tr_scr->base.resource_destroy = trace_screen_resource_destroy;
1171   tr_scr->base.fence_reference = trace_screen_fence_reference;
1172   SCR_INIT(fence_get_fd);
1173   tr_scr->base.fence_finish = trace_screen_fence_finish;
1174   SCR_INIT(memobj_create_from_handle);
1175   SCR_INIT(memobj_destroy);
1176   tr_scr->base.flush_frontbuffer = trace_screen_flush_frontbuffer;
1177   tr_scr->base.get_timestamp = trace_screen_get_timestamp;
1178   SCR_INIT(get_driver_uuid);
1179   SCR_INIT(get_device_uuid);
1180   SCR_INIT(finalize_nir);
1181   SCR_INIT(create_vertex_state);
1182   SCR_INIT(vertex_state_destroy);
1183   tr_scr->base.transfer_helper = screen->transfer_helper;
1184
1185   tr_scr->screen = screen;
1186
1187   trace_dump_ret(ptr, screen);
1188   trace_dump_call_end();
1189
1190   if (!trace_screens)
1191      trace_screens = _mesa_hash_table_create(NULL, _mesa_hash_pointer, _mesa_key_pointer_equal);
1192   _mesa_hash_table_insert(trace_screens, screen, tr_scr);
1193
1194   tr_scr->trace_tc = debug_get_bool_option("GALLIUM_TRACE_TC", false);
1195
1196   return &tr_scr->base;
1197
1198error2:
1199   trace_dump_ret(ptr, screen);
1200   trace_dump_call_end();
1201error1:
1202   return screen;
1203}
1204
1205
1206struct trace_screen *
1207trace_screen(struct pipe_screen *screen)
1208{
1209   assert(screen);
1210   assert(screen->destroy == trace_screen_destroy);
1211   return (struct trace_screen *)screen;
1212}
1213