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