1/**************************************************************************
2 *
3 * Copyright 2010 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
29#include "pipe/p_screen.h"
30#include "pipe/p_state.h"
31#include "util/u_memory.h"
32#include "util/u_debug.h"
33
34#include "rbug_public.h"
35#include "rbug_screen.h"
36#include "rbug_context.h"
37#include "rbug_objects.h"
38
39DEBUG_GET_ONCE_BOOL_OPTION(rbug, "GALLIUM_RBUG", false)
40
41static void
42rbug_screen_destroy(struct pipe_screen *_screen)
43{
44   struct rbug_screen *rb_screen = rbug_screen(_screen);
45   struct pipe_screen *screen = rb_screen->screen;
46
47   screen->destroy(screen);
48
49   FREE(rb_screen);
50}
51
52static const char *
53rbug_screen_get_name(struct pipe_screen *_screen)
54{
55   struct rbug_screen *rb_screen = rbug_screen(_screen);
56   struct pipe_screen *screen = rb_screen->screen;
57
58   return screen->get_name(screen);
59}
60
61static const char *
62rbug_screen_get_vendor(struct pipe_screen *_screen)
63{
64   struct rbug_screen *rb_screen = rbug_screen(_screen);
65   struct pipe_screen *screen = rb_screen->screen;
66
67   return screen->get_vendor(screen);
68}
69
70static const char *
71rbug_screen_get_device_vendor(struct pipe_screen *_screen)
72{
73   struct rbug_screen *rb_screen = rbug_screen(_screen);
74   struct pipe_screen *screen = rb_screen->screen;
75
76   return screen->get_device_vendor(screen);
77}
78
79static const void *
80rbug_screen_get_compiler_options(struct pipe_screen *_screen,
81                                 enum pipe_shader_ir ir,
82                                 enum pipe_shader_type shader)
83{
84   struct pipe_screen *screen = rbug_screen(_screen)->screen;
85
86   return screen->get_compiler_options(screen, ir, shader);
87}
88
89static struct disk_cache *
90rbug_screen_get_disk_shader_cache(struct pipe_screen *_screen)
91{
92   struct pipe_screen *screen = rbug_screen(_screen)->screen;
93
94   return screen->get_disk_shader_cache(screen);
95}
96
97static int
98rbug_screen_get_param(struct pipe_screen *_screen,
99                      enum pipe_cap param)
100{
101   struct rbug_screen *rb_screen = rbug_screen(_screen);
102   struct pipe_screen *screen = rb_screen->screen;
103
104   return screen->get_param(screen,
105                            param);
106}
107
108static int
109rbug_screen_get_shader_param(struct pipe_screen *_screen,
110                             enum pipe_shader_type shader,
111                             enum pipe_shader_cap param)
112{
113   struct rbug_screen *rb_screen = rbug_screen(_screen);
114   struct pipe_screen *screen = rb_screen->screen;
115
116   return screen->get_shader_param(screen, shader,
117                            param);
118}
119
120static float
121rbug_screen_get_paramf(struct pipe_screen *_screen,
122                       enum pipe_capf param)
123{
124   struct rbug_screen *rb_screen = rbug_screen(_screen);
125   struct pipe_screen *screen = rb_screen->screen;
126
127   return screen->get_paramf(screen,
128                             param);
129}
130
131static bool
132rbug_screen_is_format_supported(struct pipe_screen *_screen,
133                                enum pipe_format format,
134                                enum pipe_texture_target target,
135                                unsigned sample_count,
136                                unsigned storage_sample_count,
137                                unsigned tex_usage)
138{
139   struct rbug_screen *rb_screen = rbug_screen(_screen);
140   struct pipe_screen *screen = rb_screen->screen;
141
142   return screen->is_format_supported(screen,
143                                      format,
144                                      target,
145                                      sample_count,
146                                      storage_sample_count,
147                                      tex_usage);
148}
149
150static void
151rbug_screen_query_dmabuf_modifiers(struct pipe_screen *_screen,
152                                   enum pipe_format format, int max,
153                                   uint64_t *modifiers,
154                                   unsigned int *external_only, int *count)
155{
156   struct rbug_screen *rb_screen = rbug_screen(_screen);
157   struct pipe_screen *screen = rb_screen->screen;
158
159   screen->query_dmabuf_modifiers(screen,
160                                  format,
161                                  max,
162                                  modifiers,
163                                  external_only,
164                                  count);
165}
166
167static bool
168rbug_screen_is_dmabuf_modifier_supported(struct pipe_screen *_screen,
169                                         uint64_t modifier,
170                                         enum pipe_format format,
171                                         bool *external_only)
172{
173   struct rbug_screen *rb_screen = rbug_screen(_screen);
174   struct pipe_screen *screen = rb_screen->screen;
175
176   return screen->is_dmabuf_modifier_supported(screen,
177                                               modifier,
178                                               format,
179                                               external_only);
180}
181
182static unsigned int
183rbug_screen_get_dmabuf_modifier_planes(struct pipe_screen *_screen,
184                                       uint64_t modifier,
185                                       enum pipe_format format)
186{
187   struct rbug_screen *rb_screen = rbug_screen(_screen);
188   struct pipe_screen *screen = rb_screen->screen;
189
190   return screen->get_dmabuf_modifier_planes(screen, modifier, format);
191}
192
193static int
194rbug_screen_get_sparse_texture_virtual_page_size(struct pipe_screen *_screen,
195                                                 enum pipe_texture_target target,
196                                                 bool multi_sample,
197                                                 enum pipe_format format,
198                                                 unsigned offset, unsigned size,
199                                                 int *x, int *y, int *z)
200{
201   struct rbug_screen *rb_screen = rbug_screen(_screen);
202   struct pipe_screen *screen = rb_screen->screen;
203
204   return screen->get_sparse_texture_virtual_page_size(screen, target, multi_sample,
205                                                       format, offset, size, x, y, z);
206}
207
208static struct pipe_context *
209rbug_screen_context_create(struct pipe_screen *_screen,
210                           void *priv, unsigned flags)
211{
212   struct rbug_screen *rb_screen = rbug_screen(_screen);
213   struct pipe_screen *screen = rb_screen->screen;
214   struct pipe_context *result;
215
216   result = screen->context_create(screen, priv, flags);
217   if (result)
218      return rbug_context_create(_screen, result);
219   return NULL;
220}
221
222static bool
223rbug_screen_can_create_resource(struct pipe_screen *_screen,
224                                const struct pipe_resource *templat)
225{
226   struct rbug_screen *rb_screen = rbug_screen(_screen);
227   struct pipe_screen *screen = rb_screen->screen;
228
229   return screen->can_create_resource(screen,
230                                      templat);
231}
232
233static struct pipe_resource *
234rbug_screen_resource_create(struct pipe_screen *_screen,
235                            const struct pipe_resource *templat)
236{
237   struct rbug_screen *rb_screen = rbug_screen(_screen);
238   struct pipe_screen *screen = rb_screen->screen;
239   struct pipe_resource *result;
240
241   result = screen->resource_create(screen,
242                                    templat);
243
244   if (result)
245      return rbug_resource_create(rb_screen, result);
246   return NULL;
247}
248
249static struct pipe_resource *
250rbug_screen_resource_create_with_modifiers(struct pipe_screen *_screen,
251                                           const struct pipe_resource *templat,
252                                           const uint64_t *modifiers, int count)
253{
254   struct rbug_screen *rb_screen = rbug_screen(_screen);
255   struct pipe_screen *screen = rb_screen->screen;
256   struct pipe_resource *result;
257
258   result = screen->resource_create_with_modifiers(screen,
259                                                   templat,
260                                                   modifiers,
261                                                   count);
262
263   if (result)
264      return rbug_resource_create(rb_screen, result);
265   return NULL;
266}
267
268static struct pipe_resource *
269rbug_screen_resource_from_handle(struct pipe_screen *_screen,
270                                 const struct pipe_resource *templ,
271                                 struct winsys_handle *handle,
272                                 unsigned usage)
273{
274   struct rbug_screen *rb_screen = rbug_screen(_screen);
275   struct pipe_screen *screen = rb_screen->screen;
276   struct pipe_resource *result;
277
278   result = screen->resource_from_handle(screen, templ, handle, usage);
279
280   result = rbug_resource_create(rbug_screen(_screen), result);
281
282   return result;
283}
284
285static bool
286rbug_screen_check_resource_capability(struct pipe_screen *_screen,
287                                      struct pipe_resource *_resource,
288                                      unsigned bind)
289{
290   struct rbug_screen *rb_screen = rbug_screen(_screen);
291   struct rbug_resource *rb_resource = rbug_resource(_resource);
292   struct pipe_screen *screen = rb_screen->screen;
293   struct pipe_resource *resource = rb_resource->resource;
294
295   return screen->check_resource_capability(screen, resource, bind);
296}
297
298static bool
299rbug_screen_resource_get_handle(struct pipe_screen *_screen,
300                                struct pipe_context *_pipe,
301                                struct pipe_resource *_resource,
302                                struct winsys_handle *handle,
303                                unsigned usage)
304{
305   struct rbug_screen *rb_screen = rbug_screen(_screen);
306   struct rbug_context *rb_pipe = rbug_context(_pipe);
307   struct rbug_resource *rb_resource = rbug_resource(_resource);
308   struct pipe_screen *screen = rb_screen->screen;
309   struct pipe_resource *resource = rb_resource->resource;
310
311   return screen->resource_get_handle(screen, rb_pipe ? rb_pipe->pipe : NULL,
312                                      resource, handle, usage);
313}
314
315static bool
316rbug_screen_resource_get_param(struct pipe_screen *_screen,
317                               struct pipe_context *_pipe,
318                               struct pipe_resource *_resource,
319                               unsigned plane,
320                               unsigned layer,
321                               unsigned level,
322                               enum pipe_resource_param param,
323                               unsigned handle_usage,
324                               uint64_t *value)
325{
326   struct rbug_screen *rb_screen = rbug_screen(_screen);
327   struct rbug_context *rb_pipe = rbug_context(_pipe);
328   struct rbug_resource *rb_resource = rbug_resource(_resource);
329   struct pipe_screen *screen = rb_screen->screen;
330   struct pipe_resource *resource = rb_resource->resource;
331
332   return screen->resource_get_param(screen, rb_pipe ? rb_pipe->pipe : NULL,
333                                     resource, plane, layer, level, param,
334                                     handle_usage, value);
335}
336
337
338static void
339rbug_screen_resource_get_info(struct pipe_screen *_screen,
340                              struct pipe_resource *_resource,
341                              unsigned *stride,
342                              unsigned *offset)
343{
344   struct rbug_screen *rb_screen = rbug_screen(_screen);
345   struct rbug_resource *rb_resource = rbug_resource(_resource);
346   struct pipe_screen *screen = rb_screen->screen;
347   struct pipe_resource *resource = rb_resource->resource;
348
349   screen->resource_get_info(screen, resource, stride, offset);
350}
351
352static void
353rbug_screen_resource_changed(struct pipe_screen *_screen,
354                             struct pipe_resource *_resource)
355{
356   struct rbug_screen *rb_screen = rbug_screen(_screen);
357   struct rbug_resource *rb_resource = rbug_resource(_resource);
358   struct pipe_screen *screen = rb_screen->screen;
359   struct pipe_resource *resource = rb_resource->resource;
360
361   screen->resource_changed(screen, resource);
362}
363
364static void
365rbug_screen_resource_destroy(struct pipe_screen *screen,
366                             struct pipe_resource *_resource)
367{
368   rbug_resource_destroy(rbug_resource(_resource));
369}
370
371static void
372rbug_screen_flush_frontbuffer(struct pipe_screen *_screen,
373                              struct pipe_context *_ctx,
374                              struct pipe_resource *_resource,
375                              unsigned level, unsigned layer,
376                              void *context_private, struct pipe_box *sub_box)
377{
378   struct rbug_screen *rb_screen = rbug_screen(_screen);
379   struct rbug_resource *rb_resource = rbug_resource(_resource);
380   struct pipe_screen *screen = rb_screen->screen;
381   struct pipe_resource *resource = rb_resource->resource;
382   struct pipe_context *ctx = _ctx ? rbug_context(_ctx)->pipe : NULL;
383
384   screen->flush_frontbuffer(screen,
385                             ctx,
386                             resource,
387                             level, layer,
388                             context_private, sub_box);
389}
390
391static void
392rbug_screen_fence_reference(struct pipe_screen *_screen,
393                            struct pipe_fence_handle **ptr,
394                            struct pipe_fence_handle *fence)
395{
396   struct rbug_screen *rb_screen = rbug_screen(_screen);
397   struct pipe_screen *screen = rb_screen->screen;
398
399   screen->fence_reference(screen,
400                           ptr,
401                           fence);
402}
403
404static bool
405rbug_screen_fence_finish(struct pipe_screen *_screen,
406                         struct pipe_context *_ctx,
407                         struct pipe_fence_handle *fence,
408                         uint64_t timeout)
409{
410   struct rbug_screen *rb_screen = rbug_screen(_screen);
411   struct pipe_screen *screen = rb_screen->screen;
412   struct pipe_context *ctx = _ctx ? rbug_context(_ctx)->pipe : NULL;
413
414   return screen->fence_finish(screen, ctx, fence, timeout);
415}
416
417static int
418rbug_screen_fence_get_fd(struct pipe_screen *_screen,
419                         struct pipe_fence_handle *fence)
420{
421   struct rbug_screen *rb_screen = rbug_screen(_screen);
422   struct pipe_screen *screen = rb_screen->screen;
423
424   return screen->fence_get_fd(screen, fence);
425}
426
427static char *
428rbug_screen_finalize_nir(struct pipe_screen *_screen, void *nir)
429{
430   struct pipe_screen *screen = rbug_screen(_screen)->screen;
431
432   return screen->finalize_nir(screen, nir);
433}
434
435bool
436rbug_enabled()
437{
438   return debug_get_option_rbug();
439}
440
441struct pipe_screen *
442rbug_screen_create(struct pipe_screen *screen)
443{
444   struct rbug_screen *rb_screen;
445
446   if (!debug_get_option_rbug())
447      return screen;
448
449   rb_screen = CALLOC_STRUCT(rbug_screen);
450   if (!rb_screen)
451      return screen;
452
453   (void) mtx_init(&rb_screen->list_mutex, mtx_plain);
454   list_inithead(&rb_screen->contexts);
455   list_inithead(&rb_screen->resources);
456   list_inithead(&rb_screen->surfaces);
457   list_inithead(&rb_screen->transfers);
458
459#define SCR_INIT(_member) \
460   rb_screen->base._member = screen->_member ? rbug_screen_##_member : NULL
461
462   rb_screen->base.destroy = rbug_screen_destroy;
463   rb_screen->base.get_name = rbug_screen_get_name;
464   rb_screen->base.get_vendor = rbug_screen_get_vendor;
465   SCR_INIT(get_compiler_options);
466   SCR_INIT(get_disk_shader_cache);
467   rb_screen->base.get_device_vendor = rbug_screen_get_device_vendor;
468   rb_screen->base.get_param = rbug_screen_get_param;
469   rb_screen->base.get_shader_param = rbug_screen_get_shader_param;
470   rb_screen->base.get_paramf = rbug_screen_get_paramf;
471   rb_screen->base.is_format_supported = rbug_screen_is_format_supported;
472   SCR_INIT(query_dmabuf_modifiers);
473   SCR_INIT(is_dmabuf_modifier_supported);
474   SCR_INIT(get_dmabuf_modifier_planes);
475   rb_screen->base.context_create = rbug_screen_context_create;
476   SCR_INIT(can_create_resource);
477   rb_screen->base.resource_create = rbug_screen_resource_create;
478   SCR_INIT(resource_create_with_modifiers);
479   rb_screen->base.resource_from_handle = rbug_screen_resource_from_handle;
480   SCR_INIT(check_resource_capability);
481   rb_screen->base.resource_get_handle = rbug_screen_resource_get_handle;
482   SCR_INIT(resource_get_param);
483   SCR_INIT(resource_get_info);
484   SCR_INIT(resource_changed);
485   rb_screen->base.resource_destroy = rbug_screen_resource_destroy;
486   rb_screen->base.flush_frontbuffer = rbug_screen_flush_frontbuffer;
487   rb_screen->base.fence_reference = rbug_screen_fence_reference;
488   rb_screen->base.fence_finish = rbug_screen_fence_finish;
489   rb_screen->base.fence_get_fd = rbug_screen_fence_get_fd;
490   SCR_INIT(finalize_nir);
491   SCR_INIT(get_sparse_texture_virtual_page_size);
492
493   rb_screen->screen = screen;
494
495   rb_screen->private_context = screen->context_create(screen, NULL, 0);
496   if (!rb_screen->private_context)
497      goto err_free;
498
499   rb_screen->rbug = rbug_start(rb_screen);
500
501   if (!rb_screen->rbug)
502      goto err_context;
503
504   return &rb_screen->base;
505
506err_context:
507   rb_screen->private_context->destroy(rb_screen->private_context);
508err_free:
509   FREE(rb_screen);
510   return screen;
511}
512