1/* 2 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included 12 * in all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 */ 22 23#include <dlfcn.h> 24#include "drm-uapi/drm_fourcc.h" 25#include "util/u_memory.h" 26#include "pipe/p_screen.h" 27#include "state_tracker/st_texture.h" 28#include "state_tracker/st_context.h" 29#include "main/texobj.h" 30 31#include "dri_helpers.h" 32 33static bool 34dri2_is_opencl_interop_loaded_locked(struct dri_screen *screen) 35{ 36 return screen->opencl_dri_event_add_ref && 37 screen->opencl_dri_event_release && 38 screen->opencl_dri_event_wait && 39 screen->opencl_dri_event_get_fence; 40} 41 42static bool 43dri2_load_opencl_interop(struct dri_screen *screen) 44{ 45#if defined(RTLD_DEFAULT) 46 bool success; 47 48 mtx_lock(&screen->opencl_func_mutex); 49 50 if (dri2_is_opencl_interop_loaded_locked(screen)) { 51 mtx_unlock(&screen->opencl_func_mutex); 52 return true; 53 } 54 55 screen->opencl_dri_event_add_ref = 56 dlsym(RTLD_DEFAULT, "opencl_dri_event_add_ref"); 57 screen->opencl_dri_event_release = 58 dlsym(RTLD_DEFAULT, "opencl_dri_event_release"); 59 screen->opencl_dri_event_wait = 60 dlsym(RTLD_DEFAULT, "opencl_dri_event_wait"); 61 screen->opencl_dri_event_get_fence = 62 dlsym(RTLD_DEFAULT, "opencl_dri_event_get_fence"); 63 64 success = dri2_is_opencl_interop_loaded_locked(screen); 65 mtx_unlock(&screen->opencl_func_mutex); 66 return success; 67#else 68 return false; 69#endif 70} 71 72struct dri2_fence { 73 struct dri_screen *driscreen; 74 struct pipe_fence_handle *pipe_fence; 75 void *cl_event; 76}; 77 78static unsigned dri2_fence_get_caps(__DRIscreen *_screen) 79{ 80 struct dri_screen *driscreen = dri_screen(_screen); 81 struct pipe_screen *screen = driscreen->base.screen; 82 unsigned caps = 0; 83 84 if (screen->get_param(screen, PIPE_CAP_NATIVE_FENCE_FD)) 85 caps |= __DRI_FENCE_CAP_NATIVE_FD; 86 87 return caps; 88} 89 90static void * 91dri2_create_fence(__DRIcontext *_ctx) 92{ 93 struct st_context_iface *stapi = dri_context(_ctx)->st; 94 struct dri2_fence *fence = CALLOC_STRUCT(dri2_fence); 95 96 if (!fence) 97 return NULL; 98 99 stapi->flush(stapi, 0, &fence->pipe_fence, NULL, NULL); 100 101 if (!fence->pipe_fence) { 102 FREE(fence); 103 return NULL; 104 } 105 106 fence->driscreen = dri_screen(_ctx->driScreenPriv); 107 return fence; 108} 109 110static void * 111dri2_create_fence_fd(__DRIcontext *_ctx, int fd) 112{ 113 struct st_context_iface *stapi = dri_context(_ctx)->st; 114 struct pipe_context *ctx = stapi->pipe; 115 struct dri2_fence *fence = CALLOC_STRUCT(dri2_fence); 116 117 if (fd == -1) { 118 /* exporting driver created fence, flush: */ 119 stapi->flush(stapi, ST_FLUSH_FENCE_FD, &fence->pipe_fence, NULL, NULL); 120 } else { 121 /* importing a foreign fence fd: */ 122 ctx->create_fence_fd(ctx, &fence->pipe_fence, fd, PIPE_FD_TYPE_NATIVE_SYNC); 123 } 124 if (!fence->pipe_fence) { 125 FREE(fence); 126 return NULL; 127 } 128 129 fence->driscreen = dri_screen(_ctx->driScreenPriv); 130 return fence; 131} 132 133static int 134dri2_get_fence_fd(__DRIscreen *_screen, void *_fence) 135{ 136 struct dri_screen *driscreen = dri_screen(_screen); 137 struct pipe_screen *screen = driscreen->base.screen; 138 struct dri2_fence *fence = (struct dri2_fence*)_fence; 139 140 return screen->fence_get_fd(screen, fence->pipe_fence); 141} 142 143static void * 144dri2_get_fence_from_cl_event(__DRIscreen *_screen, intptr_t cl_event) 145{ 146 struct dri_screen *driscreen = dri_screen(_screen); 147 struct dri2_fence *fence; 148 149 if (!dri2_load_opencl_interop(driscreen)) 150 return NULL; 151 152 fence = CALLOC_STRUCT(dri2_fence); 153 if (!fence) 154 return NULL; 155 156 fence->cl_event = (void*)cl_event; 157 158 if (!driscreen->opencl_dri_event_add_ref(fence->cl_event)) { 159 free(fence); 160 return NULL; 161 } 162 163 fence->driscreen = driscreen; 164 return fence; 165} 166 167static void 168dri2_destroy_fence(__DRIscreen *_screen, void *_fence) 169{ 170 struct dri_screen *driscreen = dri_screen(_screen); 171 struct pipe_screen *screen = driscreen->base.screen; 172 struct dri2_fence *fence = (struct dri2_fence*)_fence; 173 174 if (fence->pipe_fence) 175 screen->fence_reference(screen, &fence->pipe_fence, NULL); 176 else if (fence->cl_event) 177 driscreen->opencl_dri_event_release(fence->cl_event); 178 else 179 assert(0); 180 181 FREE(fence); 182} 183 184static GLboolean 185dri2_client_wait_sync(__DRIcontext *_ctx, void *_fence, unsigned flags, 186 uint64_t timeout) 187{ 188 struct dri2_fence *fence = (struct dri2_fence*)_fence; 189 struct dri_screen *driscreen = fence->driscreen; 190 struct pipe_screen *screen = driscreen->base.screen; 191 192 /* No need to flush. The context was flushed when the fence was created. */ 193 194 if (fence->pipe_fence) 195 return screen->fence_finish(screen, NULL, fence->pipe_fence, timeout); 196 else if (fence->cl_event) { 197 struct pipe_fence_handle *pipe_fence = 198 driscreen->opencl_dri_event_get_fence(fence->cl_event); 199 200 if (pipe_fence) 201 return screen->fence_finish(screen, NULL, pipe_fence, timeout); 202 else 203 return driscreen->opencl_dri_event_wait(fence->cl_event, timeout); 204 } 205 else { 206 assert(0); 207 return false; 208 } 209} 210 211static void 212dri2_server_wait_sync(__DRIcontext *_ctx, void *_fence, unsigned flags) 213{ 214 struct pipe_context *ctx = dri_context(_ctx)->st->pipe; 215 struct dri2_fence *fence = (struct dri2_fence*)_fence; 216 217 /* We might be called here with a NULL fence as a result of WaitSyncKHR 218 * on a EGL_KHR_reusable_sync fence. Nothing to do here in such case. 219 */ 220 if (!fence) 221 return; 222 223 if (ctx->fence_server_sync) 224 ctx->fence_server_sync(ctx, fence->pipe_fence); 225} 226 227const __DRI2fenceExtension dri2FenceExtension = { 228 .base = { __DRI2_FENCE, 2 }, 229 230 .create_fence = dri2_create_fence, 231 .get_fence_from_cl_event = dri2_get_fence_from_cl_event, 232 .destroy_fence = dri2_destroy_fence, 233 .client_wait_sync = dri2_client_wait_sync, 234 .server_wait_sync = dri2_server_wait_sync, 235 .get_capabilities = dri2_fence_get_caps, 236 .create_fence_fd = dri2_create_fence_fd, 237 .get_fence_fd = dri2_get_fence_fd, 238}; 239 240__DRIimage * 241dri2_lookup_egl_image(struct dri_screen *screen, void *handle) 242{ 243 const __DRIimageLookupExtension *loader = screen->sPriv->dri2.image; 244 __DRIimage *img; 245 246 if (!loader->lookupEGLImage) 247 return NULL; 248 249 img = loader->lookupEGLImage(screen->sPriv, 250 handle, screen->sPriv->loaderPrivate); 251 252 return img; 253} 254 255boolean 256dri2_validate_egl_image(struct dri_screen *screen, void *handle) 257{ 258 const __DRIimageLookupExtension *loader = screen->sPriv->dri2.image; 259 260 return loader->validateEGLImage(handle, screen->sPriv->loaderPrivate); 261} 262 263__DRIimage * 264dri2_lookup_egl_image_validated(struct dri_screen *screen, void *handle) 265{ 266 const __DRIimageLookupExtension *loader = screen->sPriv->dri2.image; 267 268 return loader->lookupEGLImageValidated(handle, screen->sPriv->loaderPrivate); 269} 270 271__DRIimage * 272dri2_create_image_from_renderbuffer2(__DRIcontext *context, 273 int renderbuffer, void *loaderPrivate, 274 unsigned *error) 275{ 276 struct st_context *st_ctx = (struct st_context *)dri_context(context)->st; 277 struct gl_context *ctx = st_ctx->ctx; 278 struct pipe_context *p_ctx = st_ctx->pipe; 279 struct gl_renderbuffer *rb; 280 struct pipe_resource *tex; 281 __DRIimage *img; 282 283 /* Section 3.9 (EGLImage Specification and Management) of the EGL 1.5 284 * specification says: 285 * 286 * "If target is EGL_GL_RENDERBUFFER and buffer is not the name of a 287 * renderbuffer object, or if buffer is the name of a multisampled 288 * renderbuffer object, the error EGL_BAD_PARAMETER is generated." 289 * 290 * "If target is EGL_GL_TEXTURE_2D , EGL_GL_TEXTURE_CUBE_MAP_*, 291 * EGL_GL_RENDERBUFFER or EGL_GL_TEXTURE_3D and buffer refers to the 292 * default GL texture object (0) for the corresponding GL target, the 293 * error EGL_BAD_PARAMETER is generated." 294 * (rely on _mesa_lookup_renderbuffer returning NULL in this case) 295 */ 296 rb = _mesa_lookup_renderbuffer(ctx, renderbuffer); 297 if (!rb || rb->NumSamples > 0) { 298 *error = __DRI_IMAGE_ERROR_BAD_PARAMETER; 299 return NULL; 300 } 301 302 tex = rb->texture; 303 if (!tex) { 304 *error = __DRI_IMAGE_ERROR_BAD_PARAMETER; 305 return NULL; 306 } 307 308 img = CALLOC_STRUCT(__DRIimageRec); 309 if (!img) { 310 *error = __DRI_IMAGE_ERROR_BAD_ALLOC; 311 return NULL; 312 } 313 314 img->dri_format = driGLFormatToImageFormat(rb->Format); 315 img->internal_format = rb->InternalFormat; 316 img->loader_private = loaderPrivate; 317 img->sPriv = context->driScreenPriv; 318 img->in_fence_fd = -1; 319 320 pipe_resource_reference(&img->texture, tex); 321 322 /* If the resource supports EGL_MESA_image_dma_buf_export, make sure that 323 * it's in a shareable state. Do this now while we still have the access to 324 * the context. 325 */ 326 if (dri2_get_mapping_by_format(img->dri_format)) 327 p_ctx->flush_resource(p_ctx, tex); 328 329 ctx->Shared->HasExternallySharedImages = true; 330 *error = __DRI_IMAGE_ERROR_SUCCESS; 331 return img; 332} 333 334__DRIimage * 335dri2_create_image_from_renderbuffer(__DRIcontext *context, 336 int renderbuffer, void *loaderPrivate) 337{ 338 unsigned error; 339 return dri2_create_image_from_renderbuffer2(context, renderbuffer, 340 loaderPrivate, &error); 341} 342 343void 344dri2_destroy_image(__DRIimage *img) 345{ 346 const __DRIimageLoaderExtension *imgLoader = img->sPriv->image.loader; 347 const __DRIdri2LoaderExtension *dri2Loader = img->sPriv->dri2.loader; 348 349 if (imgLoader && imgLoader->base.version >= 4 && 350 imgLoader->destroyLoaderImageState) { 351 imgLoader->destroyLoaderImageState(img->loader_private); 352 } else if (dri2Loader && dri2Loader->base.version >= 5 && 353 dri2Loader->destroyLoaderImageState) { 354 dri2Loader->destroyLoaderImageState(img->loader_private); 355 } 356 357 pipe_resource_reference(&img->texture, NULL); 358 359 if (img->in_fence_fd != -1) 360 close(img->in_fence_fd); 361 362 FREE(img); 363} 364 365 366__DRIimage * 367dri2_create_from_texture(__DRIcontext *context, int target, unsigned texture, 368 int depth, int level, unsigned *error, 369 void *loaderPrivate) 370{ 371 __DRIimage *img; 372 struct st_context *st_ctx = (struct st_context *)dri_context(context)->st; 373 struct gl_context *ctx = st_ctx->ctx; 374 struct pipe_context *p_ctx = st_ctx->pipe; 375 struct gl_texture_object *obj; 376 struct pipe_resource *tex; 377 GLuint face = 0; 378 379 obj = _mesa_lookup_texture(ctx, texture); 380 if (!obj || obj->Target != target) { 381 *error = __DRI_IMAGE_ERROR_BAD_PARAMETER; 382 return NULL; 383 } 384 385 tex = st_get_texobj_resource(obj); 386 if (!tex) { 387 *error = __DRI_IMAGE_ERROR_BAD_PARAMETER; 388 return NULL; 389 } 390 391 if (target == GL_TEXTURE_CUBE_MAP) 392 face = depth; 393 394 _mesa_test_texobj_completeness(ctx, obj); 395 if (!obj->_BaseComplete || (level > 0 && !obj->_MipmapComplete)) { 396 *error = __DRI_IMAGE_ERROR_BAD_PARAMETER; 397 return NULL; 398 } 399 400 if (level < obj->Attrib.BaseLevel || level > obj->_MaxLevel) { 401 *error = __DRI_IMAGE_ERROR_BAD_MATCH; 402 return NULL; 403 } 404 405 if (target == GL_TEXTURE_3D && obj->Image[face][level]->Depth < depth) { 406 *error = __DRI_IMAGE_ERROR_BAD_MATCH; 407 return NULL; 408 } 409 410 img = CALLOC_STRUCT(__DRIimageRec); 411 if (!img) { 412 *error = __DRI_IMAGE_ERROR_BAD_ALLOC; 413 return NULL; 414 } 415 416 img->level = level; 417 img->layer = depth; 418 img->in_fence_fd = -1; 419 img->dri_format = driGLFormatToImageFormat(obj->Image[face][level]->TexFormat); 420 img->internal_format = obj->Image[face][level]->InternalFormat; 421 422 img->loader_private = loaderPrivate; 423 img->sPriv = context->driScreenPriv; 424 425 pipe_resource_reference(&img->texture, tex); 426 427 /* If the resource supports EGL_MESA_image_dma_buf_export, make sure that 428 * it's in a shareable state. Do this now while we still have the access to 429 * the context. 430 */ 431 if (dri2_get_mapping_by_format(img->dri_format)) 432 p_ctx->flush_resource(p_ctx, tex); 433 434 ctx->Shared->HasExternallySharedImages = true; 435 *error = __DRI_IMAGE_ERROR_SUCCESS; 436 return img; 437} 438 439static const struct dri2_format_mapping dri2_format_table[] = { 440 { DRM_FORMAT_ABGR16161616F, __DRI_IMAGE_FORMAT_ABGR16161616F, 441 __DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_R16G16B16A16_FLOAT, 1, 442 { { 0, 0, 0, __DRI_IMAGE_FORMAT_ABGR16161616F } } }, 443 { DRM_FORMAT_XBGR16161616F, __DRI_IMAGE_FORMAT_XBGR16161616F, 444 __DRI_IMAGE_COMPONENTS_RGB, PIPE_FORMAT_R16G16B16X16_FLOAT, 1, 445 { { 0, 0, 0, __DRI_IMAGE_FORMAT_XBGR16161616F } } }, 446 { DRM_FORMAT_ABGR16161616, __DRI_IMAGE_FORMAT_ABGR16161616, 447 __DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_R16G16B16A16_UNORM, 1, 448 { { 0, 0, 0, __DRI_IMAGE_FORMAT_ABGR16161616 } } }, 449 { DRM_FORMAT_XBGR16161616, __DRI_IMAGE_FORMAT_XBGR16161616, 450 __DRI_IMAGE_COMPONENTS_RGB, PIPE_FORMAT_R16G16B16X16_UNORM, 1, 451 { { 0, 0, 0, __DRI_IMAGE_FORMAT_XBGR16161616 } } }, 452 { DRM_FORMAT_ARGB2101010, __DRI_IMAGE_FORMAT_ARGB2101010, 453 __DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_B10G10R10A2_UNORM, 1, 454 { { 0, 0, 0, __DRI_IMAGE_FORMAT_ARGB2101010 } } }, 455 { DRM_FORMAT_XRGB2101010, __DRI_IMAGE_FORMAT_XRGB2101010, 456 __DRI_IMAGE_COMPONENTS_RGB, PIPE_FORMAT_B10G10R10X2_UNORM, 1, 457 { { 0, 0, 0, __DRI_IMAGE_FORMAT_XRGB2101010 } } }, 458 { DRM_FORMAT_ABGR2101010, __DRI_IMAGE_FORMAT_ABGR2101010, 459 __DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_R10G10B10A2_UNORM, 1, 460 { { 0, 0, 0, __DRI_IMAGE_FORMAT_ABGR2101010 } } }, 461 { DRM_FORMAT_XBGR2101010, __DRI_IMAGE_FORMAT_XBGR2101010, 462 __DRI_IMAGE_COMPONENTS_RGB, PIPE_FORMAT_R10G10B10X2_UNORM, 1, 463 { { 0, 0, 0, __DRI_IMAGE_FORMAT_XBGR2101010 } } }, 464 { DRM_FORMAT_ARGB8888, __DRI_IMAGE_FORMAT_ARGB8888, 465 __DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_BGRA8888_UNORM, 1, 466 { { 0, 0, 0, __DRI_IMAGE_FORMAT_ARGB8888 } } }, 467 { DRM_FORMAT_ABGR8888, __DRI_IMAGE_FORMAT_ABGR8888, 468 __DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_RGBA8888_UNORM, 1, 469 { { 0, 0, 0, __DRI_IMAGE_FORMAT_ABGR8888 } } }, 470 { __DRI_IMAGE_FOURCC_SARGB8888, __DRI_IMAGE_FORMAT_SARGB8, 471 __DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_BGRA8888_SRGB, 1, 472 { { 0, 0, 0, __DRI_IMAGE_FORMAT_SARGB8 } } }, 473 { DRM_FORMAT_XRGB8888, __DRI_IMAGE_FORMAT_XRGB8888, 474 __DRI_IMAGE_COMPONENTS_RGB, PIPE_FORMAT_BGRX8888_UNORM, 1, 475 { { 0, 0, 0, __DRI_IMAGE_FORMAT_XRGB8888 } } }, 476 { DRM_FORMAT_XBGR8888, __DRI_IMAGE_FORMAT_XBGR8888, 477 __DRI_IMAGE_COMPONENTS_RGB, PIPE_FORMAT_RGBX8888_UNORM, 1, 478 { { 0, 0, 0, __DRI_IMAGE_FORMAT_XBGR8888 } } }, 479 { DRM_FORMAT_ARGB1555, __DRI_IMAGE_FORMAT_ARGB1555, 480 __DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_B5G5R5A1_UNORM, 1, 481 { { 0, 0, 0, __DRI_IMAGE_FORMAT_ARGB1555 } } }, 482 { DRM_FORMAT_RGB565, __DRI_IMAGE_FORMAT_RGB565, 483 __DRI_IMAGE_COMPONENTS_RGB, PIPE_FORMAT_B5G6R5_UNORM, 1, 484 { { 0, 0, 0, __DRI_IMAGE_FORMAT_RGB565 } } }, 485 { DRM_FORMAT_R8, __DRI_IMAGE_FORMAT_R8, 486 __DRI_IMAGE_COMPONENTS_R, PIPE_FORMAT_R8_UNORM, 1, 487 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8 } } }, 488 { DRM_FORMAT_R16, __DRI_IMAGE_FORMAT_R16, 489 __DRI_IMAGE_COMPONENTS_R, PIPE_FORMAT_R16_UNORM, 1, 490 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R16 } } }, 491 { DRM_FORMAT_GR88, __DRI_IMAGE_FORMAT_GR88, 492 __DRI_IMAGE_COMPONENTS_RG, PIPE_FORMAT_RG88_UNORM, 1, 493 { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88 } } }, 494 { DRM_FORMAT_GR1616, __DRI_IMAGE_FORMAT_GR1616, 495 __DRI_IMAGE_COMPONENTS_RG, PIPE_FORMAT_RG1616_UNORM, 1, 496 { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR1616 } } }, 497 498 { DRM_FORMAT_YUV410, __DRI_IMAGE_FORMAT_NONE, 499 __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3, 500 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8 }, 501 { 1, 2, 2, __DRI_IMAGE_FORMAT_R8 }, 502 { 2, 2, 2, __DRI_IMAGE_FORMAT_R8 } } }, 503 { DRM_FORMAT_YUV411, __DRI_IMAGE_FORMAT_NONE, 504 __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3, 505 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8 }, 506 { 1, 2, 0, __DRI_IMAGE_FORMAT_R8 }, 507 { 2, 2, 0, __DRI_IMAGE_FORMAT_R8 } } }, 508 { DRM_FORMAT_YUV420, __DRI_IMAGE_FORMAT_NONE, 509 __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3, 510 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8 }, 511 { 1, 1, 1, __DRI_IMAGE_FORMAT_R8 }, 512 { 2, 1, 1, __DRI_IMAGE_FORMAT_R8 } } }, 513 { DRM_FORMAT_YUV422, __DRI_IMAGE_FORMAT_NONE, 514 __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3, 515 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8 }, 516 { 1, 1, 0, __DRI_IMAGE_FORMAT_R8 }, 517 { 2, 1, 0, __DRI_IMAGE_FORMAT_R8 } } }, 518 { DRM_FORMAT_YUV444, __DRI_IMAGE_FORMAT_NONE, 519 __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3, 520 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8 }, 521 { 1, 0, 0, __DRI_IMAGE_FORMAT_R8 }, 522 { 2, 0, 0, __DRI_IMAGE_FORMAT_R8 } } }, 523 524 { DRM_FORMAT_YVU410, __DRI_IMAGE_FORMAT_NONE, 525 __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3, 526 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8 }, 527 { 2, 2, 2, __DRI_IMAGE_FORMAT_R8 }, 528 { 1, 2, 2, __DRI_IMAGE_FORMAT_R8 } } }, 529 { DRM_FORMAT_YVU411, __DRI_IMAGE_FORMAT_NONE, 530 __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3, 531 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8 }, 532 { 2, 2, 0, __DRI_IMAGE_FORMAT_R8 }, 533 { 1, 2, 0, __DRI_IMAGE_FORMAT_R8 } } }, 534 { DRM_FORMAT_YVU420, __DRI_IMAGE_FORMAT_NONE, 535 __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3, 536 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8 }, 537 { 2, 1, 1, __DRI_IMAGE_FORMAT_R8 }, 538 { 1, 1, 1, __DRI_IMAGE_FORMAT_R8 } } }, 539 { DRM_FORMAT_YVU422, __DRI_IMAGE_FORMAT_NONE, 540 __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3, 541 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8 }, 542 { 2, 1, 0, __DRI_IMAGE_FORMAT_R8 }, 543 { 1, 1, 0, __DRI_IMAGE_FORMAT_R8 } } }, 544 { DRM_FORMAT_YVU444, __DRI_IMAGE_FORMAT_NONE, 545 __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3, 546 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8 }, 547 { 2, 0, 0, __DRI_IMAGE_FORMAT_R8 }, 548 { 1, 0, 0, __DRI_IMAGE_FORMAT_R8 } } }, 549 550 { DRM_FORMAT_NV12, __DRI_IMAGE_FORMAT_NONE, 551 __DRI_IMAGE_COMPONENTS_Y_UV, PIPE_FORMAT_NV12, 2, 552 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8 }, 553 { 1, 1, 1, __DRI_IMAGE_FORMAT_GR88 } } }, 554 555 { DRM_FORMAT_P010, __DRI_IMAGE_FORMAT_NONE, 556 __DRI_IMAGE_COMPONENTS_Y_UV, PIPE_FORMAT_P010, 2, 557 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R16 }, 558 { 1, 1, 1, __DRI_IMAGE_FORMAT_GR1616 } } }, 559 { DRM_FORMAT_P012, __DRI_IMAGE_FORMAT_NONE, 560 __DRI_IMAGE_COMPONENTS_Y_UV, PIPE_FORMAT_P012, 2, 561 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R16 }, 562 { 1, 1, 1, __DRI_IMAGE_FORMAT_GR1616 } } }, 563 { DRM_FORMAT_P016, __DRI_IMAGE_FORMAT_NONE, 564 __DRI_IMAGE_COMPONENTS_Y_UV, PIPE_FORMAT_P016, 2, 565 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R16 }, 566 { 1, 1, 1, __DRI_IMAGE_FORMAT_GR1616 } } }, 567 568 { DRM_FORMAT_NV16, __DRI_IMAGE_FORMAT_NONE, 569 __DRI_IMAGE_COMPONENTS_Y_UV, PIPE_FORMAT_NV12, 2, 570 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8 }, 571 { 1, 1, 0, __DRI_IMAGE_FORMAT_GR88 } } }, 572 573 { DRM_FORMAT_AYUV, __DRI_IMAGE_FORMAT_ABGR8888, 574 __DRI_IMAGE_COMPONENTS_AYUV, PIPE_FORMAT_AYUV, 1, 575 { { 0, 0, 0, __DRI_IMAGE_FORMAT_ABGR8888 } } }, 576 { DRM_FORMAT_XYUV8888, __DRI_IMAGE_FORMAT_XBGR8888, 577 __DRI_IMAGE_COMPONENTS_XYUV, PIPE_FORMAT_XYUV, 1, 578 { { 0, 0, 0, __DRI_IMAGE_FORMAT_XBGR8888 } } }, 579 580 { DRM_FORMAT_Y410, __DRI_IMAGE_FORMAT_ABGR2101010, 581 __DRI_IMAGE_COMPONENTS_AYUV, PIPE_FORMAT_Y410, 1, 582 { { 0, 0, 0, __DRI_IMAGE_FORMAT_ABGR2101010 } } }, 583 584 /* Y412 is an unusual format. It has the same layout as Y416 (i.e., 585 * 16-bits of physical storage per channel), but the low 4 bits of each 586 * component are unused padding. The writer is supposed to write zeros 587 * to these bits. 588 */ 589 { DRM_FORMAT_Y412, __DRI_IMAGE_FORMAT_ABGR16161616, 590 __DRI_IMAGE_COMPONENTS_AYUV, PIPE_FORMAT_Y412, 1, 591 { { 0, 0, 0, __DRI_IMAGE_FORMAT_ABGR16161616 } } }, 592 { DRM_FORMAT_Y416, __DRI_IMAGE_FORMAT_ABGR16161616, 593 __DRI_IMAGE_COMPONENTS_AYUV, PIPE_FORMAT_Y416, 1, 594 { { 0, 0, 0, __DRI_IMAGE_FORMAT_ABGR16161616 } } }, 595 596 /* For YUYV and UYVY buffers, we set up two overlapping DRI images 597 * and treat them as planar buffers in the compositors. 598 * Plane 0 is GR88 and samples YU or YV pairs and places Y into 599 * the R component, while plane 1 is ARGB/ABGR and samples YUYV/UYVY 600 * clusters and places pairs and places U into the G component and 601 * V into A. This lets the texture sampler interpolate the Y 602 * components correctly when sampling from plane 0, and interpolate 603 * U and V correctly when sampling from plane 1. */ 604 { DRM_FORMAT_YUYV, __DRI_IMAGE_FORMAT_NONE, 605 __DRI_IMAGE_COMPONENTS_Y_XUXV, PIPE_FORMAT_YUYV, 2, 606 { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88 }, 607 { 0, 1, 0, __DRI_IMAGE_FORMAT_ARGB8888 } } }, 608 { DRM_FORMAT_UYVY, __DRI_IMAGE_FORMAT_NONE, 609 __DRI_IMAGE_COMPONENTS_Y_UXVX, PIPE_FORMAT_UYVY, 2, 610 { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88 }, 611 { 0, 1, 0, __DRI_IMAGE_FORMAT_ABGR8888 } } }, 612 613 /* The Y21x formats work in a similar fashion to the YUYV and UYVY 614 * formats. 615 */ 616 { DRM_FORMAT_Y210, __DRI_IMAGE_FORMAT_NONE, 617 __DRI_IMAGE_COMPONENTS_Y_XUXV, PIPE_FORMAT_Y210, 2, 618 { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR1616 }, 619 { 0, 1, 0, __DRI_IMAGE_FORMAT_ABGR16161616 } } }, 620 /* Y212 is an unusual format. It has the same layout as Y216 (i.e., 621 * 16-bits of physical storage per channel), but the low 4 bits of each 622 * component are unused padding. The writer is supposed to write zeros 623 * to these bits. 624 */ 625 { DRM_FORMAT_Y212, __DRI_IMAGE_FORMAT_NONE, 626 __DRI_IMAGE_COMPONENTS_Y_XUXV, PIPE_FORMAT_Y212, 2, 627 { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR1616 }, 628 { 0, 1, 0, __DRI_IMAGE_FORMAT_ABGR16161616 } } }, 629 { DRM_FORMAT_Y216, __DRI_IMAGE_FORMAT_NONE, 630 __DRI_IMAGE_COMPONENTS_Y_XUXV, PIPE_FORMAT_Y216, 2, 631 { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR1616 }, 632 { 0, 1, 0, __DRI_IMAGE_FORMAT_ABGR16161616 } } }, 633}; 634 635const struct dri2_format_mapping * 636dri2_get_mapping_by_fourcc(int fourcc) 637{ 638 for (unsigned i = 0; i < ARRAY_SIZE(dri2_format_table); i++) { 639 if (dri2_format_table[i].dri_fourcc == fourcc) 640 return &dri2_format_table[i]; 641 } 642 643 return NULL; 644} 645 646const struct dri2_format_mapping * 647dri2_get_mapping_by_format(int format) 648{ 649 if (format == __DRI_IMAGE_FORMAT_NONE) 650 return NULL; 651 652 for (unsigned i = 0; i < ARRAY_SIZE(dri2_format_table); i++) { 653 if (dri2_format_table[i].dri_format == format) 654 return &dri2_format_table[i]; 655 } 656 657 return NULL; 658} 659 660enum pipe_format 661dri2_get_pipe_format_for_dri_format(int format) 662{ 663 for (unsigned i = 0; i < ARRAY_SIZE(dri2_format_table); i++) { 664 if (dri2_format_table[i].dri_format == format) 665 return dri2_format_table[i].pipe_format; 666 } 667 668 return PIPE_FORMAT_NONE; 669} 670 671boolean 672dri2_yuv_dma_buf_supported(struct dri_screen *screen, 673 const struct dri2_format_mapping *map) 674{ 675 struct pipe_screen *pscreen = screen->base.screen; 676 677 for (unsigned i = 0; i < map->nplanes; i++) { 678 if (!pscreen->is_format_supported(pscreen, 679 dri2_get_pipe_format_for_dri_format(map->planes[i].dri_format), 680 screen->target, 0, 0, PIPE_BIND_SAMPLER_VIEW)) 681 return false; 682 } 683 return true; 684} 685 686boolean 687dri2_query_dma_buf_formats(__DRIscreen *_screen, int max, int *formats, 688 int *count) 689{ 690 struct dri_screen *screen = dri_screen(_screen); 691 struct pipe_screen *pscreen = screen->base.screen; 692 int i, j; 693 694 for (i = 0, j = 0; (i < ARRAY_SIZE(dri2_format_table)) && 695 (j < max || max == 0); i++) { 696 const struct dri2_format_mapping *map = &dri2_format_table[i]; 697 698 /* The sRGB format is not a real FourCC as defined by drm_fourcc.h, so we 699 * must not leak it out to clients. */ 700 if (dri2_format_table[i].dri_fourcc == __DRI_IMAGE_FOURCC_SARGB8888) 701 continue; 702 703 if (pscreen->is_format_supported(pscreen, map->pipe_format, 704 screen->target, 0, 0, 705 PIPE_BIND_RENDER_TARGET) || 706 pscreen->is_format_supported(pscreen, map->pipe_format, 707 screen->target, 0, 0, 708 PIPE_BIND_SAMPLER_VIEW) || 709 dri2_yuv_dma_buf_supported(screen, map)) { 710 if (j < max) 711 formats[j] = map->dri_fourcc; 712 j++; 713 } 714 } 715 *count = j; 716 return true; 717} 718 719/* vim: set sw=3 ts=8 sts=3 expandtab: */ 720