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/u_format.h"
29#include "util/u_memory.h"
30#include "util/simple_list.h"
31
32#include "tr_dump.h"
33#include "tr_dump_defines.h"
34#include "tr_dump_state.h"
35#include "tr_texture.h"
36#include "tr_context.h"
37#include "tr_screen.h"
38#include "tr_public.h"
39
40
41static boolean trace = FALSE;
42
43static const char *
44trace_screen_get_name(struct pipe_screen *_screen)
45{
46   struct trace_screen *tr_scr = trace_screen(_screen);
47   struct pipe_screen *screen = tr_scr->screen;
48   const char *result;
49
50   trace_dump_call_begin("pipe_screen", "get_name");
51
52   trace_dump_arg(ptr, screen);
53
54   result = screen->get_name(screen);
55
56   trace_dump_ret(string, result);
57
58   trace_dump_call_end();
59
60   return result;
61}
62
63
64static const char *
65trace_screen_get_vendor(struct pipe_screen *_screen)
66{
67   struct trace_screen *tr_scr = trace_screen(_screen);
68   struct pipe_screen *screen = tr_scr->screen;
69   const char *result;
70
71   trace_dump_call_begin("pipe_screen", "get_vendor");
72
73   trace_dump_arg(ptr, screen);
74
75   result = screen->get_vendor(screen);
76
77   trace_dump_ret(string, result);
78
79   trace_dump_call_end();
80
81   return result;
82}
83
84
85static const char *
86trace_screen_get_device_vendor(struct pipe_screen *_screen)
87{
88   struct trace_screen *tr_scr = trace_screen(_screen);
89   struct pipe_screen *screen = tr_scr->screen;
90   const char *result;
91
92   trace_dump_call_begin("pipe_screen", "get_device_vendor");
93
94   trace_dump_arg(ptr, screen);
95
96   result = screen->get_device_vendor(screen);
97
98   trace_dump_ret(string, result);
99
100   trace_dump_call_end();
101
102   return result;
103}
104
105
106static struct disk_cache *
107trace_screen_get_disk_shader_cache(struct pipe_screen *_screen)
108{
109   struct trace_screen *tr_scr = trace_screen(_screen);
110   struct pipe_screen *screen = tr_scr->screen;
111
112   trace_dump_call_begin("pipe_screen", "get_disk_shader_cache");
113
114   trace_dump_arg(ptr, screen);
115
116   struct disk_cache *result = screen->get_disk_shader_cache(screen);
117
118   trace_dump_ret(ptr, result);
119
120   trace_dump_call_end();
121
122   return result;
123}
124
125
126static int
127trace_screen_get_param(struct pipe_screen *_screen,
128                       enum pipe_cap param)
129{
130   struct trace_screen *tr_scr = trace_screen(_screen);
131   struct pipe_screen *screen = tr_scr->screen;
132   int result;
133
134   trace_dump_call_begin("pipe_screen", "get_param");
135
136   trace_dump_arg(ptr, screen);
137   trace_dump_arg(int, param);
138
139   result = screen->get_param(screen, param);
140
141   trace_dump_ret(int, result);
142
143   trace_dump_call_end();
144
145   return result;
146}
147
148
149static int
150trace_screen_get_shader_param(struct pipe_screen *_screen,
151                              enum pipe_shader_type shader,
152                              enum pipe_shader_cap param)
153{
154   struct trace_screen *tr_scr = trace_screen(_screen);
155   struct pipe_screen *screen = tr_scr->screen;
156   int result;
157
158   trace_dump_call_begin("pipe_screen", "get_shader_param");
159
160   trace_dump_arg(ptr, screen);
161   trace_dump_arg(uint, shader);
162   trace_dump_arg(int, param);
163
164   result = screen->get_shader_param(screen, shader, param);
165
166   trace_dump_ret(int, result);
167
168   trace_dump_call_end();
169
170   return result;
171}
172
173
174static float
175trace_screen_get_paramf(struct pipe_screen *_screen,
176                        enum pipe_capf param)
177{
178   struct trace_screen *tr_scr = trace_screen(_screen);
179   struct pipe_screen *screen = tr_scr->screen;
180   float result;
181
182   trace_dump_call_begin("pipe_screen", "get_paramf");
183
184   trace_dump_arg(ptr, screen);
185   trace_dump_arg(int, param);
186
187   result = screen->get_paramf(screen, param);
188
189   trace_dump_ret(float, result);
190
191   trace_dump_call_end();
192
193   return result;
194}
195
196
197static int
198trace_screen_get_compute_param(struct pipe_screen *_screen,
199                               enum pipe_shader_ir ir_type,
200                               enum pipe_compute_cap param, void *data)
201{
202   struct trace_screen *tr_scr = trace_screen(_screen);
203   struct pipe_screen *screen = tr_scr->screen;
204   int result;
205
206   trace_dump_call_begin("pipe_screen", "get_compute_param");
207
208   trace_dump_arg(ptr, screen);
209   trace_dump_arg(int, ir_type);
210   trace_dump_arg(int, param);
211   trace_dump_arg(ptr, data);
212
213   result = screen->get_compute_param(screen, ir_type, param, data);
214
215   trace_dump_ret(int, result);
216
217   trace_dump_call_end();
218
219   return result;
220}
221
222
223static boolean
224trace_screen_is_format_supported(struct pipe_screen *_screen,
225                                 enum pipe_format format,
226                                 enum pipe_texture_target target,
227                                 unsigned sample_count,
228                                 unsigned storage_sample_count,
229                                 unsigned tex_usage)
230{
231   struct trace_screen *tr_scr = trace_screen(_screen);
232   struct pipe_screen *screen = tr_scr->screen;
233   boolean result;
234
235   trace_dump_call_begin("pipe_screen", "is_format_supported");
236
237   trace_dump_arg(ptr, screen);
238   trace_dump_arg(format, format);
239   trace_dump_arg(int, target);
240   trace_dump_arg(uint, sample_count);
241   trace_dump_arg(uint, tex_usage);
242
243   result = screen->is_format_supported(screen, format, target, sample_count,
244                                        storage_sample_count, tex_usage);
245
246   trace_dump_ret(bool, result);
247
248   trace_dump_call_end();
249
250   return result;
251}
252
253
254static struct pipe_context *
255trace_screen_context_create(struct pipe_screen *_screen, void *priv,
256                            unsigned flags)
257{
258   struct trace_screen *tr_scr = trace_screen(_screen);
259   struct pipe_screen *screen = tr_scr->screen;
260   struct pipe_context *result;
261
262   trace_dump_call_begin("pipe_screen", "context_create");
263
264   trace_dump_arg(ptr, screen);
265   trace_dump_arg(ptr, priv);
266   trace_dump_arg(uint, flags);
267
268   result = screen->context_create(screen, priv, flags);
269
270   trace_dump_ret(ptr, result);
271
272   trace_dump_call_end();
273
274   result = trace_context_create(tr_scr, result);
275
276   return result;
277}
278
279
280static void
281trace_screen_flush_frontbuffer(struct pipe_screen *_screen,
282                               struct pipe_resource *resource,
283                               unsigned level, unsigned layer,
284                               void *context_private,
285                               struct pipe_box *sub_box)
286{
287   struct trace_screen *tr_scr = trace_screen(_screen);
288   struct pipe_screen *screen = tr_scr->screen;
289
290   trace_dump_call_begin("pipe_screen", "flush_frontbuffer");
291
292   trace_dump_arg(ptr, screen);
293   trace_dump_arg(ptr, resource);
294   trace_dump_arg(uint, level);
295   trace_dump_arg(uint, layer);
296   /* XXX: hide, as there is nothing we can do with this
297   trace_dump_arg(ptr, context_private);
298   */
299
300   screen->flush_frontbuffer(screen, resource, level, layer, context_private, sub_box);
301
302   trace_dump_call_end();
303}
304
305
306static void
307trace_screen_get_driver_uuid(struct pipe_screen *_screen, char *uuid)
308{
309   struct pipe_screen *screen = trace_screen(_screen)->screen;
310
311   trace_dump_call_begin("pipe_screen", "get_driver_uuid");
312   trace_dump_arg(ptr, screen);
313
314   screen->get_driver_uuid(screen, uuid);
315
316   trace_dump_ret(string, uuid);
317   trace_dump_call_end();
318}
319
320static void
321trace_screen_get_device_uuid(struct pipe_screen *_screen, char *uuid)
322{
323   struct pipe_screen *screen = trace_screen(_screen)->screen;
324
325   trace_dump_call_begin("pipe_screen", "get_device_uuid");
326   trace_dump_arg(ptr, screen);
327
328   screen->get_device_uuid(screen, uuid);
329
330   trace_dump_ret(string, uuid);
331   trace_dump_call_end();
332}
333
334
335/********************************************************************
336 * texture
337 */
338
339
340static struct pipe_resource *
341trace_screen_resource_create(struct pipe_screen *_screen,
342                            const struct pipe_resource *templat)
343{
344   struct trace_screen *tr_scr = trace_screen(_screen);
345   struct pipe_screen *screen = tr_scr->screen;
346   struct pipe_resource *result;
347
348   trace_dump_call_begin("pipe_screen", "resource_create");
349
350   trace_dump_arg(ptr, screen);
351   trace_dump_arg(resource_template, templat);
352
353   result = screen->resource_create(screen, templat);
354
355   trace_dump_ret(ptr, result);
356
357   trace_dump_call_end();
358
359   if (result)
360      result->screen = _screen;
361   return result;
362}
363
364static struct pipe_resource *
365trace_screen_resource_from_handle(struct pipe_screen *_screen,
366                                 const struct pipe_resource *templ,
367                                 struct winsys_handle *handle,
368                                  unsigned usage)
369{
370   struct trace_screen *tr_screen = trace_screen(_screen);
371   struct pipe_screen *screen = tr_screen->screen;
372   struct pipe_resource *result;
373
374   /* TODO trace call */
375
376   result = screen->resource_from_handle(screen, templ, handle, usage);
377
378   if (result)
379      result->screen = _screen;
380   return result;
381}
382
383static bool
384trace_screen_check_resource_capability(struct pipe_screen *_screen,
385                                       struct pipe_resource *resource,
386                                       unsigned bind)
387{
388   struct pipe_screen *screen = trace_screen(_screen)->screen;
389
390   return screen->check_resource_capability(screen, resource, bind);
391}
392
393static boolean
394trace_screen_resource_get_handle(struct pipe_screen *_screen,
395                                 struct pipe_context *_pipe,
396                                struct pipe_resource *resource,
397                                struct winsys_handle *handle,
398                                 unsigned usage)
399{
400   struct trace_screen *tr_screen = trace_screen(_screen);
401   struct trace_context *tr_pipe = _pipe ? trace_context(_pipe) : NULL;
402   struct pipe_screen *screen = tr_screen->screen;
403
404   /* TODO trace call */
405
406   return screen->resource_get_handle(screen, tr_pipe ? tr_pipe->pipe : NULL,
407                                      resource, handle, usage);
408}
409
410static void
411trace_screen_resource_get_info(struct pipe_screen *_screen,
412                               struct pipe_resource *resource,
413                               unsigned *stride,
414                               unsigned *offset)
415{
416   struct trace_screen *tr_screen = trace_screen(_screen);
417   struct pipe_screen *screen = tr_screen->screen;
418
419   /* TODO trace call */
420
421   screen->resource_get_info(screen, resource, stride, offset);
422}
423
424static struct pipe_resource *
425trace_screen_resource_from_memobj(struct pipe_screen *_screen,
426                                  const struct pipe_resource *templ,
427                                  struct pipe_memory_object *memobj,
428                                  uint64_t offset)
429{
430   struct pipe_screen *screen = trace_screen(_screen)->screen;
431
432   trace_dump_call_begin("pipe_screen", "resource_from_memobj");
433   trace_dump_arg(ptr, screen);
434   trace_dump_arg(resource_template, templ);
435   trace_dump_arg(ptr, memobj);
436   trace_dump_arg(uint, offset);
437
438   struct pipe_resource *res =
439      screen->resource_from_memobj(screen, templ, memobj, offset);
440
441   if (!res)
442      return NULL;
443   res->screen = _screen;
444
445   trace_dump_ret(ptr, res);
446   trace_dump_call_end();
447   return res;
448}
449
450static void
451trace_screen_resource_changed(struct pipe_screen *_screen,
452                              struct pipe_resource *resource)
453{
454   struct trace_screen *tr_scr = trace_screen(_screen);
455   struct pipe_screen *screen = tr_scr->screen;
456
457   trace_dump_call_begin("pipe_screen", "resource_changed");
458
459   trace_dump_arg(ptr, screen);
460   trace_dump_arg(ptr, resource);
461
462   if (screen->resource_changed)
463      screen->resource_changed(screen, resource);
464
465   trace_dump_call_end();
466}
467
468static void
469trace_screen_resource_destroy(struct pipe_screen *_screen,
470			      struct pipe_resource *resource)
471{
472   struct trace_screen *tr_scr = trace_screen(_screen);
473   struct pipe_screen *screen = tr_scr->screen;
474
475   /* Don't trace this, because due to the lack of pipe_resource wrapping,
476    * we can get this call from inside of driver calls, which would try
477    * to lock an already-locked mutex.
478    */
479   screen->resource_destroy(screen, resource);
480}
481
482
483/********************************************************************
484 * fence
485 */
486
487
488static void
489trace_screen_fence_reference(struct pipe_screen *_screen,
490                             struct pipe_fence_handle **pdst,
491                             struct pipe_fence_handle *src)
492{
493   struct trace_screen *tr_scr = trace_screen(_screen);
494   struct pipe_screen *screen = tr_scr->screen;
495   struct pipe_fence_handle *dst;
496
497   assert(pdst);
498   dst = *pdst;
499
500   trace_dump_call_begin("pipe_screen", "fence_reference");
501
502   trace_dump_arg(ptr, screen);
503   trace_dump_arg(ptr, dst);
504   trace_dump_arg(ptr, src);
505
506   screen->fence_reference(screen, pdst, src);
507
508   trace_dump_call_end();
509}
510
511
512static int
513trace_screen_fence_get_fd(struct pipe_screen *_screen,
514                          struct pipe_fence_handle *fence)
515{
516   struct trace_screen *tr_scr = trace_screen(_screen);
517   struct pipe_screen *screen = tr_scr->screen;
518   int result;
519
520   trace_dump_call_begin("pipe_screen", "fence_get_fd");
521
522   trace_dump_arg(ptr, screen);
523   trace_dump_arg(ptr, fence);
524
525   result = screen->fence_get_fd(screen, fence);
526
527   trace_dump_ret(int, result);
528
529   trace_dump_call_end();
530
531   return result;
532}
533
534
535static boolean
536trace_screen_fence_finish(struct pipe_screen *_screen,
537                          struct pipe_context *_ctx,
538                          struct pipe_fence_handle *fence,
539                          uint64_t timeout)
540{
541   struct trace_screen *tr_scr = trace_screen(_screen);
542   struct pipe_screen *screen = tr_scr->screen;
543   struct pipe_context *ctx = _ctx ? trace_context(_ctx)->pipe : NULL;
544   int result;
545
546   trace_dump_call_begin("pipe_screen", "fence_finish");
547
548   trace_dump_arg(ptr, screen);
549   trace_dump_arg(ptr, ctx);
550   trace_dump_arg(ptr, fence);
551   trace_dump_arg(uint, timeout);
552
553   result = screen->fence_finish(screen, ctx, fence, timeout);
554
555   trace_dump_ret(bool, result);
556
557   trace_dump_call_end();
558
559   return result;
560}
561
562
563/********************************************************************
564 * memobj
565 */
566
567static struct pipe_memory_object *
568trace_screen_memobj_create_from_handle(struct pipe_screen *_screen,
569                                       struct winsys_handle *handle,
570                                       bool dedicated)
571{
572   struct pipe_screen *screen = trace_screen(_screen)->screen;
573
574   trace_dump_call_begin("pipe_screen", "memobj_create_from_handle");
575   trace_dump_arg(ptr, screen);
576   trace_dump_arg(ptr, handle);
577   trace_dump_arg(bool, dedicated);
578
579   struct pipe_memory_object *res =
580      screen->memobj_create_from_handle(screen, handle, dedicated);
581
582   trace_dump_ret(ptr, res);
583   trace_dump_call_end();
584
585   return res;
586}
587
588static void
589trace_screen_memobj_destroy(struct pipe_screen *_screen,
590                            struct pipe_memory_object *memobj)
591{
592   struct pipe_screen *screen = trace_screen(_screen)->screen;
593
594   trace_dump_call_begin("pipe_screen", "memobj_destroy");
595   trace_dump_arg(ptr, screen);
596   trace_dump_arg(ptr, memobj);
597   trace_dump_call_end();
598
599   screen->memobj_destroy(screen, memobj);
600}
601
602
603/********************************************************************
604 * screen
605 */
606
607static uint64_t
608trace_screen_get_timestamp(struct pipe_screen *_screen)
609{
610   struct trace_screen *tr_scr = trace_screen(_screen);
611   struct pipe_screen *screen = tr_scr->screen;
612   uint64_t result;
613
614   trace_dump_call_begin("pipe_screen", "get_timestamp");
615   trace_dump_arg(ptr, screen);
616
617   result = screen->get_timestamp(screen);
618
619   trace_dump_ret(uint, result);
620   trace_dump_call_end();
621
622   return result;
623}
624
625static void
626trace_screen_destroy(struct pipe_screen *_screen)
627{
628   struct trace_screen *tr_scr = trace_screen(_screen);
629   struct pipe_screen *screen = tr_scr->screen;
630
631   trace_dump_call_begin("pipe_screen", "destroy");
632   trace_dump_arg(ptr, screen);
633   trace_dump_call_end();
634
635   screen->destroy(screen);
636
637   FREE(tr_scr);
638}
639
640boolean
641trace_enabled(void)
642{
643   static boolean firstrun = TRUE;
644
645   if (!firstrun)
646      return trace;
647   firstrun = FALSE;
648
649   if(trace_dump_trace_begin()) {
650      trace_dumping_start();
651      trace = TRUE;
652   }
653
654   return trace;
655}
656
657struct pipe_screen *
658trace_screen_create(struct pipe_screen *screen)
659{
660   struct trace_screen *tr_scr;
661
662   if (!trace_enabled())
663      goto error1;
664
665   trace_dump_call_begin("", "pipe_screen_create");
666
667   tr_scr = CALLOC_STRUCT(trace_screen);
668   if (!tr_scr)
669      goto error2;
670
671#define SCR_INIT(_member) \
672   tr_scr->base._member = screen->_member ? trace_screen_##_member : NULL
673
674   tr_scr->base.destroy = trace_screen_destroy;
675   tr_scr->base.get_name = trace_screen_get_name;
676   tr_scr->base.get_vendor = trace_screen_get_vendor;
677   tr_scr->base.get_device_vendor = trace_screen_get_device_vendor;
678   SCR_INIT(get_disk_shader_cache);
679   tr_scr->base.get_param = trace_screen_get_param;
680   tr_scr->base.get_shader_param = trace_screen_get_shader_param;
681   tr_scr->base.get_paramf = trace_screen_get_paramf;
682   tr_scr->base.get_compute_param = trace_screen_get_compute_param;
683   tr_scr->base.is_format_supported = trace_screen_is_format_supported;
684   assert(screen->context_create);
685   tr_scr->base.context_create = trace_screen_context_create;
686   tr_scr->base.resource_create = trace_screen_resource_create;
687   tr_scr->base.resource_from_handle = trace_screen_resource_from_handle;
688   SCR_INIT(check_resource_capability);
689   tr_scr->base.resource_get_handle = trace_screen_resource_get_handle;
690   SCR_INIT(resource_get_info);
691   SCR_INIT(resource_from_memobj);
692   SCR_INIT(resource_changed);
693   tr_scr->base.resource_destroy = trace_screen_resource_destroy;
694   tr_scr->base.fence_reference = trace_screen_fence_reference;
695   SCR_INIT(fence_get_fd);
696   tr_scr->base.fence_finish = trace_screen_fence_finish;
697   SCR_INIT(memobj_create_from_handle);
698   SCR_INIT(memobj_destroy);
699   tr_scr->base.flush_frontbuffer = trace_screen_flush_frontbuffer;
700   tr_scr->base.get_timestamp = trace_screen_get_timestamp;
701   SCR_INIT(get_driver_uuid);
702   SCR_INIT(get_device_uuid);
703
704   tr_scr->screen = screen;
705
706   trace_dump_ret(ptr, screen);
707   trace_dump_call_end();
708
709   return &tr_scr->base;
710
711error2:
712   trace_dump_ret(ptr, screen);
713   trace_dump_call_end();
714error1:
715   return screen;
716}
717
718
719struct trace_screen *
720trace_screen(struct pipe_screen *screen)
721{
722   assert(screen);
723   assert(screen->destroy == trace_screen_destroy);
724   return (struct trace_screen *)screen;
725}
726