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