Path: blob/21.2-virgl/src/gallium/frontends/dri/dri_helpers.c
4565 views
/*1* Copyright (C) 1999-2007 Brian Paul All Rights Reserved.2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice shall be included11* in all copies or substantial portions of the Software.12*13* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS14* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,15* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL16* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR17* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,18* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR19* OTHER DEALINGS IN THE SOFTWARE.20*/2122#include <dlfcn.h>23#include "drm-uapi/drm_fourcc.h"24#include "util/u_memory.h"25#include "pipe/p_screen.h"26#include "state_tracker/st_texture.h"27#include "state_tracker/st_context.h"28#include "state_tracker/st_cb_fbo.h"29#include "main/texobj.h"3031#include "dri_helpers.h"3233static bool34dri2_is_opencl_interop_loaded_locked(struct dri_screen *screen)35{36return screen->opencl_dri_event_add_ref &&37screen->opencl_dri_event_release &&38screen->opencl_dri_event_wait &&39screen->opencl_dri_event_get_fence;40}4142static bool43dri2_load_opencl_interop(struct dri_screen *screen)44{45#if defined(RTLD_DEFAULT)46bool success;4748mtx_lock(&screen->opencl_func_mutex);4950if (dri2_is_opencl_interop_loaded_locked(screen)) {51mtx_unlock(&screen->opencl_func_mutex);52return true;53}5455screen->opencl_dri_event_add_ref =56dlsym(RTLD_DEFAULT, "opencl_dri_event_add_ref");57screen->opencl_dri_event_release =58dlsym(RTLD_DEFAULT, "opencl_dri_event_release");59screen->opencl_dri_event_wait =60dlsym(RTLD_DEFAULT, "opencl_dri_event_wait");61screen->opencl_dri_event_get_fence =62dlsym(RTLD_DEFAULT, "opencl_dri_event_get_fence");6364success = dri2_is_opencl_interop_loaded_locked(screen);65mtx_unlock(&screen->opencl_func_mutex);66return success;67#else68return false;69#endif70}7172struct dri2_fence {73struct dri_screen *driscreen;74struct pipe_fence_handle *pipe_fence;75void *cl_event;76};7778static unsigned dri2_fence_get_caps(__DRIscreen *_screen)79{80struct dri_screen *driscreen = dri_screen(_screen);81struct pipe_screen *screen = driscreen->base.screen;82unsigned caps = 0;8384if (screen->get_param(screen, PIPE_CAP_NATIVE_FENCE_FD))85caps |= __DRI_FENCE_CAP_NATIVE_FD;8687return caps;88}8990static void *91dri2_create_fence(__DRIcontext *_ctx)92{93struct st_context_iface *stapi = dri_context(_ctx)->st;94struct dri2_fence *fence = CALLOC_STRUCT(dri2_fence);9596if (!fence)97return NULL;9899stapi->flush(stapi, 0, &fence->pipe_fence, NULL, NULL);100101if (!fence->pipe_fence) {102FREE(fence);103return NULL;104}105106fence->driscreen = dri_screen(_ctx->driScreenPriv);107return fence;108}109110static void *111dri2_create_fence_fd(__DRIcontext *_ctx, int fd)112{113struct st_context_iface *stapi = dri_context(_ctx)->st;114struct pipe_context *ctx = stapi->pipe;115struct dri2_fence *fence = CALLOC_STRUCT(dri2_fence);116117if (fd == -1) {118/* exporting driver created fence, flush: */119stapi->flush(stapi, ST_FLUSH_FENCE_FD, &fence->pipe_fence, NULL, NULL);120} else {121/* importing a foreign fence fd: */122ctx->create_fence_fd(ctx, &fence->pipe_fence, fd, PIPE_FD_TYPE_NATIVE_SYNC);123}124if (!fence->pipe_fence) {125FREE(fence);126return NULL;127}128129fence->driscreen = dri_screen(_ctx->driScreenPriv);130return fence;131}132133static int134dri2_get_fence_fd(__DRIscreen *_screen, void *_fence)135{136struct dri_screen *driscreen = dri_screen(_screen);137struct pipe_screen *screen = driscreen->base.screen;138struct dri2_fence *fence = (struct dri2_fence*)_fence;139140return screen->fence_get_fd(screen, fence->pipe_fence);141}142143static void *144dri2_get_fence_from_cl_event(__DRIscreen *_screen, intptr_t cl_event)145{146struct dri_screen *driscreen = dri_screen(_screen);147struct dri2_fence *fence;148149if (!dri2_load_opencl_interop(driscreen))150return NULL;151152fence = CALLOC_STRUCT(dri2_fence);153if (!fence)154return NULL;155156fence->cl_event = (void*)cl_event;157158if (!driscreen->opencl_dri_event_add_ref(fence->cl_event)) {159free(fence);160return NULL;161}162163fence->driscreen = driscreen;164return fence;165}166167static void168dri2_destroy_fence(__DRIscreen *_screen, void *_fence)169{170struct dri_screen *driscreen = dri_screen(_screen);171struct pipe_screen *screen = driscreen->base.screen;172struct dri2_fence *fence = (struct dri2_fence*)_fence;173174if (fence->pipe_fence)175screen->fence_reference(screen, &fence->pipe_fence, NULL);176else if (fence->cl_event)177driscreen->opencl_dri_event_release(fence->cl_event);178else179assert(0);180181FREE(fence);182}183184static GLboolean185dri2_client_wait_sync(__DRIcontext *_ctx, void *_fence, unsigned flags,186uint64_t timeout)187{188struct dri2_fence *fence = (struct dri2_fence*)_fence;189struct dri_screen *driscreen = fence->driscreen;190struct pipe_screen *screen = driscreen->base.screen;191192/* No need to flush. The context was flushed when the fence was created. */193194if (fence->pipe_fence)195return screen->fence_finish(screen, NULL, fence->pipe_fence, timeout);196else if (fence->cl_event) {197struct pipe_fence_handle *pipe_fence =198driscreen->opencl_dri_event_get_fence(fence->cl_event);199200if (pipe_fence)201return screen->fence_finish(screen, NULL, pipe_fence, timeout);202else203return driscreen->opencl_dri_event_wait(fence->cl_event, timeout);204}205else {206assert(0);207return false;208}209}210211static void212dri2_server_wait_sync(__DRIcontext *_ctx, void *_fence, unsigned flags)213{214struct pipe_context *ctx = dri_context(_ctx)->st->pipe;215struct dri2_fence *fence = (struct dri2_fence*)_fence;216217/* We might be called here with a NULL fence as a result of WaitSyncKHR218* on a EGL_KHR_reusable_sync fence. Nothing to do here in such case.219*/220if (!fence)221return;222223if (ctx->fence_server_sync)224ctx->fence_server_sync(ctx, fence->pipe_fence);225}226227const __DRI2fenceExtension dri2FenceExtension = {228.base = { __DRI2_FENCE, 2 },229230.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};239240__DRIimage *241dri2_lookup_egl_image(struct dri_screen *screen, void *handle)242{243const __DRIimageLookupExtension *loader = screen->sPriv->dri2.image;244__DRIimage *img;245246if (!loader->lookupEGLImage)247return NULL;248249img = loader->lookupEGLImage(screen->sPriv,250handle, screen->sPriv->loaderPrivate);251252return img;253}254255__DRIimage *256dri2_create_image_from_renderbuffer2(__DRIcontext *context,257int renderbuffer, void *loaderPrivate,258unsigned *error)259{260struct st_context *st_ctx = (struct st_context *)dri_context(context)->st;261struct gl_context *ctx = st_ctx->ctx;262struct pipe_context *p_ctx = st_ctx->pipe;263struct gl_renderbuffer *rb;264struct pipe_resource *tex;265__DRIimage *img;266267/* Section 3.9 (EGLImage Specification and Management) of the EGL 1.5268* specification says:269*270* "If target is EGL_GL_RENDERBUFFER and buffer is not the name of a271* renderbuffer object, or if buffer is the name of a multisampled272* renderbuffer object, the error EGL_BAD_PARAMETER is generated."273*274* "If target is EGL_GL_TEXTURE_2D , EGL_GL_TEXTURE_CUBE_MAP_*,275* EGL_GL_RENDERBUFFER or EGL_GL_TEXTURE_3D and buffer refers to the276* default GL texture object (0) for the corresponding GL target, the277* error EGL_BAD_PARAMETER is generated."278* (rely on _mesa_lookup_renderbuffer returning NULL in this case)279*/280rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);281if (!rb || rb->NumSamples > 0) {282*error = __DRI_IMAGE_ERROR_BAD_PARAMETER;283return NULL;284}285286tex = st_get_renderbuffer_resource(rb);287if (!tex) {288*error = __DRI_IMAGE_ERROR_BAD_PARAMETER;289return NULL;290}291292img = CALLOC_STRUCT(__DRIimageRec);293if (!img) {294*error = __DRI_IMAGE_ERROR_BAD_ALLOC;295return NULL;296}297298img->dri_format = driGLFormatToImageFormat(rb->Format);299img->loader_private = loaderPrivate;300img->sPriv = context->driScreenPriv;301302pipe_resource_reference(&img->texture, tex);303304/* If the resource supports EGL_MESA_image_dma_buf_export, make sure that305* it's in a shareable state. Do this now while we still have the access to306* the context.307*/308if (dri2_get_mapping_by_format(img->dri_format))309p_ctx->flush_resource(p_ctx, tex);310311ctx->Shared->HasExternallySharedImages = true;312*error = __DRI_IMAGE_ERROR_SUCCESS;313return img;314}315316__DRIimage *317dri2_create_image_from_renderbuffer(__DRIcontext *context,318int renderbuffer, void *loaderPrivate)319{320unsigned error;321return dri2_create_image_from_renderbuffer2(context, renderbuffer,322loaderPrivate, &error);323}324325void326dri2_destroy_image(__DRIimage *img)327{328const __DRIimageLoaderExtension *imgLoader = img->sPriv->image.loader;329const __DRIdri2LoaderExtension *dri2Loader = img->sPriv->dri2.loader;330331if (imgLoader && imgLoader->base.version >= 4 &&332imgLoader->destroyLoaderImageState) {333imgLoader->destroyLoaderImageState(img->loader_private);334} else if (dri2Loader && dri2Loader->base.version >= 5 &&335dri2Loader->destroyLoaderImageState) {336dri2Loader->destroyLoaderImageState(img->loader_private);337}338339pipe_resource_reference(&img->texture, NULL);340FREE(img);341}342343344__DRIimage *345dri2_create_from_texture(__DRIcontext *context, int target, unsigned texture,346int depth, int level, unsigned *error,347void *loaderPrivate)348{349__DRIimage *img;350struct st_context *st_ctx = (struct st_context *)dri_context(context)->st;351struct gl_context *ctx = st_ctx->ctx;352struct pipe_context *p_ctx = st_ctx->pipe;353struct gl_texture_object *obj;354struct pipe_resource *tex;355GLuint face = 0;356357obj = _mesa_lookup_texture(ctx, texture);358if (!obj || obj->Target != target) {359*error = __DRI_IMAGE_ERROR_BAD_PARAMETER;360return NULL;361}362363tex = st_get_texobj_resource(obj);364if (!tex) {365*error = __DRI_IMAGE_ERROR_BAD_PARAMETER;366return NULL;367}368369if (target == GL_TEXTURE_CUBE_MAP)370face = depth;371372_mesa_test_texobj_completeness(ctx, obj);373if (!obj->_BaseComplete || (level > 0 && !obj->_MipmapComplete)) {374*error = __DRI_IMAGE_ERROR_BAD_PARAMETER;375return NULL;376}377378if (level < obj->Attrib.BaseLevel || level > obj->_MaxLevel) {379*error = __DRI_IMAGE_ERROR_BAD_MATCH;380return NULL;381}382383if (target == GL_TEXTURE_3D && obj->Image[face][level]->Depth < depth) {384*error = __DRI_IMAGE_ERROR_BAD_MATCH;385return NULL;386}387388img = CALLOC_STRUCT(__DRIimageRec);389if (!img) {390*error = __DRI_IMAGE_ERROR_BAD_ALLOC;391return NULL;392}393394img->level = level;395img->layer = depth;396img->dri_format = driGLFormatToImageFormat(obj->Image[face][level]->TexFormat);397398img->loader_private = loaderPrivate;399img->sPriv = context->driScreenPriv;400401pipe_resource_reference(&img->texture, tex);402403/* If the resource supports EGL_MESA_image_dma_buf_export, make sure that404* it's in a shareable state. Do this now while we still have the access to405* the context.406*/407if (dri2_get_mapping_by_format(img->dri_format))408p_ctx->flush_resource(p_ctx, tex);409410ctx->Shared->HasExternallySharedImages = true;411*error = __DRI_IMAGE_ERROR_SUCCESS;412return img;413}414415static const struct dri2_format_mapping dri2_format_table[] = {416{ DRM_FORMAT_ABGR16161616F, __DRI_IMAGE_FORMAT_ABGR16161616F,417__DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_R16G16B16A16_FLOAT, 1,418{ { 0, 0, 0, __DRI_IMAGE_FORMAT_ABGR16161616F } } },419{ DRM_FORMAT_XBGR16161616F, __DRI_IMAGE_FORMAT_XBGR16161616F,420__DRI_IMAGE_COMPONENTS_RGB, PIPE_FORMAT_R16G16B16X16_FLOAT, 1,421{ { 0, 0, 0, __DRI_IMAGE_FORMAT_XBGR16161616F } } },422{ __DRI_IMAGE_FOURCC_RGBA16161616, __DRI_IMAGE_FORMAT_ABGR16161616,423__DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_R16G16B16A16_UNORM, 1,424{ { 0, 0, 0, __DRI_IMAGE_FORMAT_ABGR16161616 } } },425{ DRM_FORMAT_ARGB2101010, __DRI_IMAGE_FORMAT_ARGB2101010,426__DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_B10G10R10A2_UNORM, 1,427{ { 0, 0, 0, __DRI_IMAGE_FORMAT_ARGB2101010 } } },428{ DRM_FORMAT_XRGB2101010, __DRI_IMAGE_FORMAT_XRGB2101010,429__DRI_IMAGE_COMPONENTS_RGB, PIPE_FORMAT_B10G10R10X2_UNORM, 1,430{ { 0, 0, 0, __DRI_IMAGE_FORMAT_XRGB2101010 } } },431{ DRM_FORMAT_ABGR2101010, __DRI_IMAGE_FORMAT_ABGR2101010,432__DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_R10G10B10A2_UNORM, 1,433{ { 0, 0, 0, __DRI_IMAGE_FORMAT_ABGR2101010 } } },434{ DRM_FORMAT_XBGR2101010, __DRI_IMAGE_FORMAT_XBGR2101010,435__DRI_IMAGE_COMPONENTS_RGB, PIPE_FORMAT_R10G10B10X2_UNORM, 1,436{ { 0, 0, 0, __DRI_IMAGE_FORMAT_XBGR2101010 } } },437{ DRM_FORMAT_ARGB8888, __DRI_IMAGE_FORMAT_ARGB8888,438__DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_BGRA8888_UNORM, 1,439{ { 0, 0, 0, __DRI_IMAGE_FORMAT_ARGB8888 } } },440{ DRM_FORMAT_ABGR8888, __DRI_IMAGE_FORMAT_ABGR8888,441__DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_RGBA8888_UNORM, 1,442{ { 0, 0, 0, __DRI_IMAGE_FORMAT_ABGR8888 } } },443{ __DRI_IMAGE_FOURCC_SARGB8888, __DRI_IMAGE_FORMAT_SARGB8,444__DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_BGRA8888_SRGB, 1,445{ { 0, 0, 0, __DRI_IMAGE_FORMAT_SARGB8 } } },446{ DRM_FORMAT_XRGB8888, __DRI_IMAGE_FORMAT_XRGB8888,447__DRI_IMAGE_COMPONENTS_RGB, PIPE_FORMAT_BGRX8888_UNORM, 1,448{ { 0, 0, 0, __DRI_IMAGE_FORMAT_XRGB8888 } } },449{ DRM_FORMAT_XBGR8888, __DRI_IMAGE_FORMAT_XBGR8888,450__DRI_IMAGE_COMPONENTS_RGB, PIPE_FORMAT_RGBX8888_UNORM, 1,451{ { 0, 0, 0, __DRI_IMAGE_FORMAT_XBGR8888 } } },452{ DRM_FORMAT_ARGB1555, __DRI_IMAGE_FORMAT_ARGB1555,453__DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_B5G5R5A1_UNORM, 1,454{ { 0, 0, 0, __DRI_IMAGE_FORMAT_ARGB1555 } } },455{ DRM_FORMAT_RGB565, __DRI_IMAGE_FORMAT_RGB565,456__DRI_IMAGE_COMPONENTS_RGB, PIPE_FORMAT_B5G6R5_UNORM, 1,457{ { 0, 0, 0, __DRI_IMAGE_FORMAT_RGB565 } } },458{ DRM_FORMAT_R8, __DRI_IMAGE_FORMAT_R8,459__DRI_IMAGE_COMPONENTS_R, PIPE_FORMAT_R8_UNORM, 1,460{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R8 } } },461{ DRM_FORMAT_R16, __DRI_IMAGE_FORMAT_R16,462__DRI_IMAGE_COMPONENTS_R, PIPE_FORMAT_R16_UNORM, 1,463{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R16 } } },464{ DRM_FORMAT_GR88, __DRI_IMAGE_FORMAT_GR88,465__DRI_IMAGE_COMPONENTS_RG, PIPE_FORMAT_RG88_UNORM, 1,466{ { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88 } } },467{ DRM_FORMAT_GR1616, __DRI_IMAGE_FORMAT_GR1616,468__DRI_IMAGE_COMPONENTS_RG, PIPE_FORMAT_RG1616_UNORM, 1,469{ { 0, 0, 0, __DRI_IMAGE_FORMAT_GR1616 } } },470471{ DRM_FORMAT_YUV410, __DRI_IMAGE_FORMAT_NONE,472__DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3,473{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R8 },474{ 1, 2, 2, __DRI_IMAGE_FORMAT_R8 },475{ 2, 2, 2, __DRI_IMAGE_FORMAT_R8 } } },476{ DRM_FORMAT_YUV411, __DRI_IMAGE_FORMAT_NONE,477__DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3,478{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R8 },479{ 1, 2, 0, __DRI_IMAGE_FORMAT_R8 },480{ 2, 2, 0, __DRI_IMAGE_FORMAT_R8 } } },481{ DRM_FORMAT_YUV420, __DRI_IMAGE_FORMAT_NONE,482__DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3,483{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R8 },484{ 1, 1, 1, __DRI_IMAGE_FORMAT_R8 },485{ 2, 1, 1, __DRI_IMAGE_FORMAT_R8 } } },486{ DRM_FORMAT_YUV422, __DRI_IMAGE_FORMAT_NONE,487__DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3,488{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R8 },489{ 1, 1, 0, __DRI_IMAGE_FORMAT_R8 },490{ 2, 1, 0, __DRI_IMAGE_FORMAT_R8 } } },491{ DRM_FORMAT_YUV444, __DRI_IMAGE_FORMAT_NONE,492__DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3,493{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R8 },494{ 1, 0, 0, __DRI_IMAGE_FORMAT_R8 },495{ 2, 0, 0, __DRI_IMAGE_FORMAT_R8 } } },496497{ DRM_FORMAT_YVU410, __DRI_IMAGE_FORMAT_NONE,498__DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3,499{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R8 },500{ 2, 2, 2, __DRI_IMAGE_FORMAT_R8 },501{ 1, 2, 2, __DRI_IMAGE_FORMAT_R8 } } },502{ DRM_FORMAT_YVU411, __DRI_IMAGE_FORMAT_NONE,503__DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3,504{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R8 },505{ 2, 2, 0, __DRI_IMAGE_FORMAT_R8 },506{ 1, 2, 0, __DRI_IMAGE_FORMAT_R8 } } },507{ DRM_FORMAT_YVU420, __DRI_IMAGE_FORMAT_NONE,508__DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3,509{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R8 },510{ 2, 1, 1, __DRI_IMAGE_FORMAT_R8 },511{ 1, 1, 1, __DRI_IMAGE_FORMAT_R8 } } },512{ DRM_FORMAT_YVU422, __DRI_IMAGE_FORMAT_NONE,513__DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3,514{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R8 },515{ 2, 1, 0, __DRI_IMAGE_FORMAT_R8 },516{ 1, 1, 0, __DRI_IMAGE_FORMAT_R8 } } },517{ DRM_FORMAT_YVU444, __DRI_IMAGE_FORMAT_NONE,518__DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3,519{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R8 },520{ 2, 0, 0, __DRI_IMAGE_FORMAT_R8 },521{ 1, 0, 0, __DRI_IMAGE_FORMAT_R8 } } },522523{ DRM_FORMAT_NV12, __DRI_IMAGE_FORMAT_NONE,524__DRI_IMAGE_COMPONENTS_Y_UV, PIPE_FORMAT_NV12, 2,525{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R8 },526{ 1, 1, 1, __DRI_IMAGE_FORMAT_GR88 } } },527528{ DRM_FORMAT_P010, __DRI_IMAGE_FORMAT_NONE,529__DRI_IMAGE_COMPONENTS_Y_UV, PIPE_FORMAT_P010, 2,530{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R16 },531{ 1, 1, 1, __DRI_IMAGE_FORMAT_GR1616 } } },532{ DRM_FORMAT_P012, __DRI_IMAGE_FORMAT_NONE,533__DRI_IMAGE_COMPONENTS_Y_UV, PIPE_FORMAT_P012, 2,534{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R16 },535{ 1, 1, 1, __DRI_IMAGE_FORMAT_GR1616 } } },536{ DRM_FORMAT_P016, __DRI_IMAGE_FORMAT_NONE,537__DRI_IMAGE_COMPONENTS_Y_UV, PIPE_FORMAT_P016, 2,538{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R16 },539{ 1, 1, 1, __DRI_IMAGE_FORMAT_GR1616 } } },540541{ DRM_FORMAT_NV16, __DRI_IMAGE_FORMAT_NONE,542__DRI_IMAGE_COMPONENTS_Y_UV, PIPE_FORMAT_NV12, 2,543{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R8 },544{ 1, 1, 0, __DRI_IMAGE_FORMAT_GR88 } } },545546{ DRM_FORMAT_AYUV, __DRI_IMAGE_FORMAT_ABGR8888,547__DRI_IMAGE_COMPONENTS_AYUV, PIPE_FORMAT_AYUV, 1,548{ { 0, 0, 0, __DRI_IMAGE_FORMAT_ABGR8888 } } },549{ DRM_FORMAT_XYUV8888, __DRI_IMAGE_FORMAT_XBGR8888,550__DRI_IMAGE_COMPONENTS_XYUV, PIPE_FORMAT_XYUV, 1,551{ { 0, 0, 0, __DRI_IMAGE_FORMAT_XBGR8888 } } },552553{ DRM_FORMAT_Y410, __DRI_IMAGE_FORMAT_ABGR2101010,554__DRI_IMAGE_COMPONENTS_AYUV, PIPE_FORMAT_Y410, 1,555{ { 0, 0, 0, __DRI_IMAGE_FORMAT_ABGR2101010 } } },556557/* Y412 is an unusual format. It has the same layout as Y416 (i.e.,558* 16-bits of physical storage per channel), but the low 4 bits of each559* component are unused padding. The writer is supposed to write zeros560* to these bits.561*/562{ DRM_FORMAT_Y412, __DRI_IMAGE_FORMAT_ABGR16161616,563__DRI_IMAGE_COMPONENTS_AYUV, PIPE_FORMAT_Y412, 1,564{ { 0, 0, 0, __DRI_IMAGE_FORMAT_ABGR16161616 } } },565{ DRM_FORMAT_Y416, __DRI_IMAGE_FORMAT_ABGR16161616,566__DRI_IMAGE_COMPONENTS_AYUV, PIPE_FORMAT_Y416, 1,567{ { 0, 0, 0, __DRI_IMAGE_FORMAT_ABGR16161616 } } },568569/* For YUYV and UYVY buffers, we set up two overlapping DRI images570* and treat them as planar buffers in the compositors.571* Plane 0 is GR88 and samples YU or YV pairs and places Y into572* the R component, while plane 1 is ARGB/ABGR and samples YUYV/UYVY573* clusters and places pairs and places U into the G component and574* V into A. This lets the texture sampler interpolate the Y575* components correctly when sampling from plane 0, and interpolate576* U and V correctly when sampling from plane 1. */577{ DRM_FORMAT_YUYV, __DRI_IMAGE_FORMAT_NONE,578__DRI_IMAGE_COMPONENTS_Y_XUXV, PIPE_FORMAT_YUYV, 2,579{ { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88 },580{ 0, 1, 0, __DRI_IMAGE_FORMAT_ARGB8888 } } },581{ DRM_FORMAT_UYVY, __DRI_IMAGE_FORMAT_NONE,582__DRI_IMAGE_COMPONENTS_Y_UXVX, PIPE_FORMAT_UYVY, 2,583{ { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88 },584{ 0, 1, 0, __DRI_IMAGE_FORMAT_ABGR8888 } } },585586/* The Y21x formats work in a similar fashion to the YUYV and UYVY587* formats.588*/589{ DRM_FORMAT_Y210, __DRI_IMAGE_FORMAT_NONE,590__DRI_IMAGE_COMPONENTS_Y_XUXV, PIPE_FORMAT_Y210, 2,591{ { 0, 0, 0, __DRI_IMAGE_FORMAT_GR1616 },592{ 0, 1, 0, __DRI_IMAGE_FORMAT_ABGR16161616 } } },593/* Y212 is an unusual format. It has the same layout as Y216 (i.e.,594* 16-bits of physical storage per channel), but the low 4 bits of each595* component are unused padding. The writer is supposed to write zeros596* to these bits.597*/598{ DRM_FORMAT_Y212, __DRI_IMAGE_FORMAT_NONE,599__DRI_IMAGE_COMPONENTS_Y_XUXV, PIPE_FORMAT_Y212, 2,600{ { 0, 0, 0, __DRI_IMAGE_FORMAT_GR1616 },601{ 0, 1, 0, __DRI_IMAGE_FORMAT_ABGR16161616 } } },602{ DRM_FORMAT_Y216, __DRI_IMAGE_FORMAT_NONE,603__DRI_IMAGE_COMPONENTS_Y_XUXV, PIPE_FORMAT_Y216, 2,604{ { 0, 0, 0, __DRI_IMAGE_FORMAT_GR1616 },605{ 0, 1, 0, __DRI_IMAGE_FORMAT_ABGR16161616 } } },606};607608const struct dri2_format_mapping *609dri2_get_mapping_by_fourcc(int fourcc)610{611for (unsigned i = 0; i < ARRAY_SIZE(dri2_format_table); i++) {612if (dri2_format_table[i].dri_fourcc == fourcc)613return &dri2_format_table[i];614}615616return NULL;617}618619const struct dri2_format_mapping *620dri2_get_mapping_by_format(int format)621{622if (format == __DRI_IMAGE_FORMAT_NONE)623return NULL;624625for (unsigned i = 0; i < ARRAY_SIZE(dri2_format_table); i++) {626if (dri2_format_table[i].dri_format == format)627return &dri2_format_table[i];628}629630return NULL;631}632633enum pipe_format634dri2_get_pipe_format_for_dri_format(int format)635{636for (unsigned i = 0; i < ARRAY_SIZE(dri2_format_table); i++) {637if (dri2_format_table[i].dri_format == format)638return dri2_format_table[i].pipe_format;639}640641return PIPE_FORMAT_NONE;642}643644boolean645dri2_yuv_dma_buf_supported(struct dri_screen *screen,646const struct dri2_format_mapping *map)647{648struct pipe_screen *pscreen = screen->base.screen;649650for (unsigned i = 0; i < map->nplanes; i++) {651if (!pscreen->is_format_supported(pscreen,652dri2_get_pipe_format_for_dri_format(map->planes[i].dri_format),653screen->target, 0, 0, PIPE_BIND_SAMPLER_VIEW))654return false;655}656return true;657}658659boolean660dri2_query_dma_buf_formats(__DRIscreen *_screen, int max, int *formats,661int *count)662{663struct dri_screen *screen = dri_screen(_screen);664struct pipe_screen *pscreen = screen->base.screen;665int i, j;666667for (i = 0, j = 0; (i < ARRAY_SIZE(dri2_format_table)) &&668(j < max || max == 0); i++) {669const struct dri2_format_mapping *map = &dri2_format_table[i];670671/* The sRGB format is not a real FourCC as defined by drm_fourcc.h, so we672* must not leak it out to clients. The RGBA16161616 format isn't673* real either, but at some point it could be. Don't leak it out form674* now.675*/676if (dri2_format_table[i].dri_fourcc == __DRI_IMAGE_FOURCC_SARGB8888 ||677dri2_format_table[i].dri_fourcc == __DRI_IMAGE_FOURCC_RGBA16161616)678continue;679680if (pscreen->is_format_supported(pscreen, map->pipe_format,681screen->target, 0, 0,682PIPE_BIND_RENDER_TARGET) ||683pscreen->is_format_supported(pscreen, map->pipe_format,684screen->target, 0, 0,685PIPE_BIND_SAMPLER_VIEW) ||686dri2_yuv_dma_buf_supported(screen, map)) {687if (j < max)688formats[j] = map->dri_fourcc;689j++;690}691}692*count = j;693return true;694}695696/* vim: set sw=3 ts=8 sts=3 expandtab: */697698699