"Fossies" - the Fresh Open Source Software Archive

Member "mesa-20.1.8/src/gallium/state_trackers/dri/dri_helpers.c" (16 Sep 2020, 22154 Bytes) of package /linux/misc/mesa-20.1.8.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "dri_helpers.c" see the Fossies "Dox" file reference documentation.

    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 "state_tracker/st_cb_fbo.h"
   30 #include "main/texobj.h"
   31 
   32 #include "dri_helpers.h"
   33 
   34 static bool
   35 dri2_is_opencl_interop_loaded_locked(struct dri_screen *screen)
   36 {
   37    return screen->opencl_dri_event_add_ref &&
   38           screen->opencl_dri_event_release &&
   39           screen->opencl_dri_event_wait &&
   40           screen->opencl_dri_event_get_fence;
   41 }
   42 
   43 static bool
   44 dri2_load_opencl_interop(struct dri_screen *screen)
   45 {
   46 #if defined(RTLD_DEFAULT)
   47    bool success;
   48 
   49    mtx_lock(&screen->opencl_func_mutex);
   50 
   51    if (dri2_is_opencl_interop_loaded_locked(screen)) {
   52       mtx_unlock(&screen->opencl_func_mutex);
   53       return true;
   54    }
   55 
   56    screen->opencl_dri_event_add_ref =
   57       dlsym(RTLD_DEFAULT, "opencl_dri_event_add_ref");
   58    screen->opencl_dri_event_release =
   59       dlsym(RTLD_DEFAULT, "opencl_dri_event_release");
   60    screen->opencl_dri_event_wait =
   61       dlsym(RTLD_DEFAULT, "opencl_dri_event_wait");
   62    screen->opencl_dri_event_get_fence =
   63       dlsym(RTLD_DEFAULT, "opencl_dri_event_get_fence");
   64 
   65    success = dri2_is_opencl_interop_loaded_locked(screen);
   66    mtx_unlock(&screen->opencl_func_mutex);
   67    return success;
   68 #else
   69    return false;
   70 #endif
   71 }
   72 
   73 struct dri2_fence {
   74    struct dri_screen *driscreen;
   75    struct pipe_fence_handle *pipe_fence;
   76    void *cl_event;
   77 };
   78 
   79 static unsigned dri2_fence_get_caps(__DRIscreen *_screen)
   80 {
   81    struct dri_screen *driscreen = dri_screen(_screen);
   82    struct pipe_screen *screen = driscreen->base.screen;
   83    unsigned caps = 0;
   84 
   85    if (screen->get_param(screen, PIPE_CAP_NATIVE_FENCE_FD))
   86       caps |= __DRI_FENCE_CAP_NATIVE_FD;
   87 
   88    return caps;
   89 }
   90 
   91 static void *
   92 dri2_create_fence(__DRIcontext *_ctx)
   93 {
   94    struct st_context_iface *stapi = dri_context(_ctx)->st;
   95    struct dri2_fence *fence = CALLOC_STRUCT(dri2_fence);
   96 
   97    if (!fence)
   98       return NULL;
   99 
  100    stapi->flush(stapi, 0, &fence->pipe_fence, NULL, NULL);
  101 
  102    if (!fence->pipe_fence) {
  103       FREE(fence);
  104       return NULL;
  105    }
  106 
  107    fence->driscreen = dri_screen(_ctx->driScreenPriv);
  108    return fence;
  109 }
  110 
  111 static void *
  112 dri2_create_fence_fd(__DRIcontext *_ctx, int fd)
  113 {
  114    struct st_context_iface *stapi = dri_context(_ctx)->st;
  115    struct pipe_context *ctx = stapi->pipe;
  116    struct dri2_fence *fence = CALLOC_STRUCT(dri2_fence);
  117 
  118    if (fd == -1) {
  119       /* exporting driver created fence, flush: */
  120       stapi->flush(stapi, ST_FLUSH_FENCE_FD, &fence->pipe_fence, NULL, NULL);
  121    } else {
  122       /* importing a foreign fence fd: */
  123       ctx->create_fence_fd(ctx, &fence->pipe_fence, fd, PIPE_FD_TYPE_NATIVE_SYNC);
  124    }
  125    if (!fence->pipe_fence) {
  126       FREE(fence);
  127       return NULL;
  128    }
  129 
  130    fence->driscreen = dri_screen(_ctx->driScreenPriv);
  131    return fence;
  132 }
  133 
  134 static int
  135 dri2_get_fence_fd(__DRIscreen *_screen, void *_fence)
  136 {
  137    struct dri_screen *driscreen = dri_screen(_screen);
  138    struct pipe_screen *screen = driscreen->base.screen;
  139    struct dri2_fence *fence = (struct dri2_fence*)_fence;
  140 
  141    return screen->fence_get_fd(screen, fence->pipe_fence);
  142 }
  143 
  144 static void *
  145 dri2_get_fence_from_cl_event(__DRIscreen *_screen, intptr_t cl_event)
  146 {
  147    struct dri_screen *driscreen = dri_screen(_screen);
  148    struct dri2_fence *fence;
  149 
  150    if (!dri2_load_opencl_interop(driscreen))
  151       return NULL;
  152 
  153    fence = CALLOC_STRUCT(dri2_fence);
  154    if (!fence)
  155       return NULL;
  156 
  157    fence->cl_event = (void*)cl_event;
  158 
  159    if (!driscreen->opencl_dri_event_add_ref(fence->cl_event)) {
  160       free(fence);
  161       return NULL;
  162    }
  163 
  164    fence->driscreen = driscreen;
  165    return fence;
  166 }
  167 
  168 static void
  169 dri2_destroy_fence(__DRIscreen *_screen, void *_fence)
  170 {
  171    struct dri_screen *driscreen = dri_screen(_screen);
  172    struct pipe_screen *screen = driscreen->base.screen;
  173    struct dri2_fence *fence = (struct dri2_fence*)_fence;
  174 
  175    if (fence->pipe_fence)
  176       screen->fence_reference(screen, &fence->pipe_fence, NULL);
  177    else if (fence->cl_event)
  178       driscreen->opencl_dri_event_release(fence->cl_event);
  179    else
  180       assert(0);
  181 
  182    FREE(fence);
  183 }
  184 
  185 static GLboolean
  186 dri2_client_wait_sync(__DRIcontext *_ctx, void *_fence, unsigned flags,
  187                       uint64_t timeout)
  188 {
  189    struct dri2_fence *fence = (struct dri2_fence*)_fence;
  190    struct dri_screen *driscreen = fence->driscreen;
  191    struct pipe_screen *screen = driscreen->base.screen;
  192 
  193    /* No need to flush. The context was flushed when the fence was created. */
  194 
  195    if (fence->pipe_fence)
  196       return screen->fence_finish(screen, NULL, fence->pipe_fence, timeout);
  197    else if (fence->cl_event) {
  198       struct pipe_fence_handle *pipe_fence =
  199          driscreen->opencl_dri_event_get_fence(fence->cl_event);
  200 
  201       if (pipe_fence)
  202          return screen->fence_finish(screen, NULL, pipe_fence, timeout);
  203       else
  204          return driscreen->opencl_dri_event_wait(fence->cl_event, timeout);
  205    }
  206    else {
  207       assert(0);
  208       return false;
  209    }
  210 }
  211 
  212 static void
  213 dri2_server_wait_sync(__DRIcontext *_ctx, void *_fence, unsigned flags)
  214 {
  215    struct pipe_context *ctx = dri_context(_ctx)->st->pipe;
  216    struct dri2_fence *fence = (struct dri2_fence*)_fence;
  217 
  218    /* We might be called here with a NULL fence as a result of WaitSyncKHR
  219     * on a EGL_KHR_reusable_sync fence. Nothing to do here in such case.
  220     */
  221    if (!fence)
  222       return;
  223 
  224    if (ctx->fence_server_sync)
  225       ctx->fence_server_sync(ctx, fence->pipe_fence);
  226 }
  227 
  228 const __DRI2fenceExtension dri2FenceExtension = {
  229    .base = { __DRI2_FENCE, 2 },
  230 
  231    .create_fence = dri2_create_fence,
  232    .get_fence_from_cl_event = dri2_get_fence_from_cl_event,
  233    .destroy_fence = dri2_destroy_fence,
  234    .client_wait_sync = dri2_client_wait_sync,
  235    .server_wait_sync = dri2_server_wait_sync,
  236    .get_capabilities = dri2_fence_get_caps,
  237    .create_fence_fd = dri2_create_fence_fd,
  238    .get_fence_fd = dri2_get_fence_fd,
  239 };
  240 
  241 __DRIimage *
  242 dri2_lookup_egl_image(struct dri_screen *screen, void *handle)
  243 {
  244    const __DRIimageLookupExtension *loader = screen->sPriv->dri2.image;
  245    __DRIimage *img;
  246 
  247    if (!loader->lookupEGLImage)
  248       return NULL;
  249 
  250    img = loader->lookupEGLImage(screen->sPriv,
  251                 handle, screen->sPriv->loaderPrivate);
  252 
  253    return img;
  254 }
  255 
  256 __DRIimage *
  257 dri2_create_image_from_renderbuffer2(__DRIcontext *context,
  258                      int renderbuffer, void *loaderPrivate,
  259                                      unsigned *error)
  260 {
  261    struct gl_context *ctx = ((struct st_context *)dri_context(context)->st)->ctx;
  262    struct gl_renderbuffer *rb;
  263    struct pipe_resource *tex;
  264    __DRIimage *img;
  265 
  266    /* Section 3.9 (EGLImage Specification and Management) of the EGL 1.5
  267     * specification says:
  268     *
  269     *   "If target is EGL_GL_RENDERBUFFER and buffer is not the name of a
  270     *    renderbuffer object, or if buffer is the name of a multisampled
  271     *    renderbuffer object, the error EGL_BAD_PARAMETER is generated."
  272     *
  273     *   "If target is EGL_GL_TEXTURE_2D , EGL_GL_TEXTURE_CUBE_MAP_*,
  274     *    EGL_GL_RENDERBUFFER or EGL_GL_TEXTURE_3D and buffer refers to the
  275     *    default GL texture object (0) for the corresponding GL target, the
  276     *    error EGL_BAD_PARAMETER is generated."
  277     *   (rely on _mesa_lookup_renderbuffer returning NULL in this case)
  278     */
  279    rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
  280    if (!rb || rb->NumSamples > 0) {
  281       *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
  282       return NULL;
  283    }
  284 
  285    tex = st_get_renderbuffer_resource(rb);
  286    if (!tex) {
  287       *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
  288       return NULL;
  289    }
  290 
  291    img = CALLOC_STRUCT(__DRIimageRec);
  292    if (!img) {
  293       *error = __DRI_IMAGE_ERROR_BAD_ALLOC;
  294       return NULL;
  295    }
  296 
  297    img->dri_format = driGLFormatToImageFormat(rb->Format);
  298    img->loader_private = loaderPrivate;
  299 
  300    pipe_resource_reference(&img->texture, tex);
  301 
  302    *error = __DRI_IMAGE_ERROR_SUCCESS;
  303    return img;
  304 }
  305 
  306 __DRIimage *
  307 dri2_create_image_from_renderbuffer(__DRIcontext *context,
  308                     int renderbuffer, void *loaderPrivate)
  309 {
  310    unsigned error;
  311    return dri2_create_image_from_renderbuffer2(context, renderbuffer,
  312                                                loaderPrivate, &error);
  313 }
  314 
  315 void
  316 dri2_destroy_image(__DRIimage *img)
  317 {
  318    pipe_resource_reference(&img->texture, NULL);
  319    FREE(img);
  320 }
  321 
  322 
  323 __DRIimage *
  324 dri2_create_from_texture(__DRIcontext *context, int target, unsigned texture,
  325                          int depth, int level, unsigned *error,
  326                          void *loaderPrivate)
  327 {
  328    __DRIimage *img;
  329    struct gl_context *ctx = ((struct st_context *)dri_context(context)->st)->ctx;
  330    struct gl_texture_object *obj;
  331    struct pipe_resource *tex;
  332    GLuint face = 0;
  333 
  334    obj = _mesa_lookup_texture(ctx, texture);
  335    if (!obj || obj->Target != target) {
  336       *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
  337       return NULL;
  338    }
  339 
  340    tex = st_get_texobj_resource(obj);
  341    if (!tex) {
  342       *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
  343       return NULL;
  344    }
  345 
  346    if (target == GL_TEXTURE_CUBE_MAP)
  347       face = depth;
  348 
  349    _mesa_test_texobj_completeness(ctx, obj);
  350    if (!obj->_BaseComplete || (level > 0 && !obj->_MipmapComplete)) {
  351       *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
  352       return NULL;
  353    }
  354 
  355    if (level < obj->BaseLevel || level > obj->_MaxLevel) {
  356       *error = __DRI_IMAGE_ERROR_BAD_MATCH;
  357       return NULL;
  358    }
  359 
  360    if (target == GL_TEXTURE_3D && obj->Image[face][level]->Depth < depth) {
  361       *error = __DRI_IMAGE_ERROR_BAD_MATCH;
  362       return NULL;
  363    }
  364 
  365    img = CALLOC_STRUCT(__DRIimageRec);
  366    if (!img) {
  367       *error = __DRI_IMAGE_ERROR_BAD_ALLOC;
  368       return NULL;
  369    }
  370 
  371    img->level = level;
  372    img->layer = depth;
  373    img->dri_format = driGLFormatToImageFormat(obj->Image[face][level]->TexFormat);
  374 
  375    img->loader_private = loaderPrivate;
  376 
  377    pipe_resource_reference(&img->texture, tex);
  378 
  379    *error = __DRI_IMAGE_ERROR_SUCCESS;
  380    return img;
  381 }
  382 
  383 static const struct dri2_format_mapping dri2_format_table[] = {
  384       { DRM_FORMAT_ABGR16161616F, __DRI_IMAGE_FORMAT_ABGR16161616F,
  385         __DRI_IMAGE_COMPONENTS_RGBA,      PIPE_FORMAT_R16G16B16A16_FLOAT, 1,
  386         { { 0, 0, 0, __DRI_IMAGE_FORMAT_ABGR16161616F, 4 } } },
  387       { DRM_FORMAT_XBGR16161616F, __DRI_IMAGE_FORMAT_XBGR16161616F,
  388         __DRI_IMAGE_COMPONENTS_RGB,       PIPE_FORMAT_R16G16B16X16_FLOAT, 1,
  389         { { 0, 0, 0, __DRI_IMAGE_FORMAT_XBGR16161616F, 4 } } },
  390       { DRM_FORMAT_ARGB2101010,   __DRI_IMAGE_FORMAT_ARGB2101010,
  391         __DRI_IMAGE_COMPONENTS_RGBA,      PIPE_FORMAT_B10G10R10A2_UNORM, 1,
  392         { { 0, 0, 0, __DRI_IMAGE_FORMAT_ARGB2101010, 4 } } },
  393       { DRM_FORMAT_XRGB2101010,   __DRI_IMAGE_FORMAT_XRGB2101010,
  394         __DRI_IMAGE_COMPONENTS_RGB,       PIPE_FORMAT_B10G10R10X2_UNORM, 1,
  395         { { 0, 0, 0, __DRI_IMAGE_FORMAT_XRGB2101010, 4 } } },
  396       { DRM_FORMAT_ABGR2101010,   __DRI_IMAGE_FORMAT_ABGR2101010,
  397         __DRI_IMAGE_COMPONENTS_RGBA,      PIPE_FORMAT_R10G10B10A2_UNORM, 1,
  398         { { 0, 0, 0, __DRI_IMAGE_FORMAT_ABGR2101010, 4 } } },
  399       { DRM_FORMAT_XBGR2101010,   __DRI_IMAGE_FORMAT_XBGR2101010,
  400         __DRI_IMAGE_COMPONENTS_RGB,       PIPE_FORMAT_R10G10B10X2_UNORM, 1,
  401         { { 0, 0, 0, __DRI_IMAGE_FORMAT_XBGR2101010, 4 } } },
  402       { DRM_FORMAT_ARGB8888,      __DRI_IMAGE_FORMAT_ARGB8888,
  403         __DRI_IMAGE_COMPONENTS_RGBA,      PIPE_FORMAT_BGRA8888_UNORM, 1,
  404         { { 0, 0, 0, __DRI_IMAGE_FORMAT_ARGB8888, 4 } } },
  405       { DRM_FORMAT_ABGR8888,      __DRI_IMAGE_FORMAT_ABGR8888,
  406         __DRI_IMAGE_COMPONENTS_RGBA,      PIPE_FORMAT_RGBA8888_UNORM, 1,
  407         { { 0, 0, 0, __DRI_IMAGE_FORMAT_ABGR8888, 4 } } },
  408       { __DRI_IMAGE_FOURCC_SARGB8888,     __DRI_IMAGE_FORMAT_SARGB8,
  409         __DRI_IMAGE_COMPONENTS_RGBA,      PIPE_FORMAT_BGRA8888_SRGB, 1,
  410         { { 0, 0, 0, __DRI_IMAGE_FORMAT_SARGB8, 4 } } },
  411       { DRM_FORMAT_XRGB8888,      __DRI_IMAGE_FORMAT_XRGB8888,
  412         __DRI_IMAGE_COMPONENTS_RGB,       PIPE_FORMAT_BGRX8888_UNORM, 1,
  413         { { 0, 0, 0, __DRI_IMAGE_FORMAT_XRGB8888, 4 }, } },
  414       { DRM_FORMAT_XBGR8888,      __DRI_IMAGE_FORMAT_XBGR8888,
  415         __DRI_IMAGE_COMPONENTS_RGB,       PIPE_FORMAT_RGBX8888_UNORM, 1,
  416         { { 0, 0, 0, __DRI_IMAGE_FORMAT_XBGR8888, 4 }, } },
  417       { DRM_FORMAT_ARGB1555,      __DRI_IMAGE_FORMAT_ARGB1555,
  418         __DRI_IMAGE_COMPONENTS_RGBA,      PIPE_FORMAT_B5G5R5A1_UNORM, 1,
  419         { { 0, 0, 0, __DRI_IMAGE_FORMAT_ARGB1555, 2 } } },
  420       { DRM_FORMAT_RGB565,        __DRI_IMAGE_FORMAT_RGB565,
  421         __DRI_IMAGE_COMPONENTS_RGB,       PIPE_FORMAT_B5G6R5_UNORM, 1,
  422         { { 0, 0, 0, __DRI_IMAGE_FORMAT_RGB565, 2 } } },
  423       { DRM_FORMAT_R8,            __DRI_IMAGE_FORMAT_R8,
  424         __DRI_IMAGE_COMPONENTS_R,         PIPE_FORMAT_R8_UNORM, 1,
  425         { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, } },
  426       { DRM_FORMAT_R16,           __DRI_IMAGE_FORMAT_R16,
  427         __DRI_IMAGE_COMPONENTS_R,         PIPE_FORMAT_R16_UNORM, 1,
  428         { { 0, 0, 0, __DRI_IMAGE_FORMAT_R16, 1 }, } },
  429       { DRM_FORMAT_GR88,          __DRI_IMAGE_FORMAT_GR88,
  430         __DRI_IMAGE_COMPONENTS_RG,        PIPE_FORMAT_RG88_UNORM, 1,
  431         { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88, 2 }, } },
  432       { DRM_FORMAT_GR1616,        __DRI_IMAGE_FORMAT_GR1616,
  433         __DRI_IMAGE_COMPONENTS_RG,        PIPE_FORMAT_RG1616_UNORM, 1,
  434         { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR1616, 2 }, } },
  435 
  436       { DRM_FORMAT_YUV410, __DRI_IMAGE_FORMAT_NONE,
  437         __DRI_IMAGE_COMPONENTS_Y_U_V,     PIPE_FORMAT_IYUV, 3,
  438         { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
  439           { 1, 2, 2, __DRI_IMAGE_FORMAT_R8, 1 },
  440           { 2, 2, 2, __DRI_IMAGE_FORMAT_R8, 1 } } },
  441       { DRM_FORMAT_YUV411, __DRI_IMAGE_FORMAT_NONE,
  442         __DRI_IMAGE_COMPONENTS_Y_U_V,     PIPE_FORMAT_IYUV, 3,
  443         { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
  444           { 1, 2, 0, __DRI_IMAGE_FORMAT_R8, 1 },
  445           { 2, 2, 0, __DRI_IMAGE_FORMAT_R8, 1 } } },
  446       { DRM_FORMAT_YUV420,        __DRI_IMAGE_FORMAT_NONE,
  447         __DRI_IMAGE_COMPONENTS_Y_U_V,     PIPE_FORMAT_IYUV, 3,
  448         { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
  449           { 1, 1, 1, __DRI_IMAGE_FORMAT_R8, 1 },
  450           { 2, 1, 1, __DRI_IMAGE_FORMAT_R8, 1 } } },
  451       { DRM_FORMAT_YUV422,        __DRI_IMAGE_FORMAT_NONE,
  452         __DRI_IMAGE_COMPONENTS_Y_U_V,     PIPE_FORMAT_IYUV, 3,
  453         { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
  454           { 1, 1, 0, __DRI_IMAGE_FORMAT_R8, 1 },
  455           { 2, 1, 0, __DRI_IMAGE_FORMAT_R8, 1 } } },
  456       { DRM_FORMAT_YUV444,        __DRI_IMAGE_FORMAT_NONE,
  457         __DRI_IMAGE_COMPONENTS_Y_U_V,     PIPE_FORMAT_IYUV, 3,
  458         { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
  459           { 1, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
  460           { 2, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 } } },
  461 
  462       { DRM_FORMAT_YVU410,        __DRI_IMAGE_FORMAT_NONE,
  463         __DRI_IMAGE_COMPONENTS_Y_U_V,     PIPE_FORMAT_IYUV, 3,
  464         { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
  465           { 2, 2, 2, __DRI_IMAGE_FORMAT_R8, 1 },
  466           { 1, 2, 2, __DRI_IMAGE_FORMAT_R8, 1 } } },
  467       { DRM_FORMAT_YVU411,        __DRI_IMAGE_FORMAT_NONE,
  468         __DRI_IMAGE_COMPONENTS_Y_U_V,     PIPE_FORMAT_IYUV, 3,
  469         { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
  470           { 2, 2, 0, __DRI_IMAGE_FORMAT_R8, 1 },
  471           { 1, 2, 0, __DRI_IMAGE_FORMAT_R8, 1 } } },
  472       { DRM_FORMAT_YVU420,        __DRI_IMAGE_FORMAT_NONE,
  473         __DRI_IMAGE_COMPONENTS_Y_U_V,     PIPE_FORMAT_IYUV, 3,
  474         { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
  475           { 2, 1, 1, __DRI_IMAGE_FORMAT_R8, 1 },
  476           { 1, 1, 1, __DRI_IMAGE_FORMAT_R8, 1 } } },
  477       { DRM_FORMAT_YVU422,        __DRI_IMAGE_FORMAT_NONE,
  478         __DRI_IMAGE_COMPONENTS_Y_U_V,     PIPE_FORMAT_IYUV, 3,
  479         { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
  480           { 2, 1, 0, __DRI_IMAGE_FORMAT_R8, 1 },
  481           { 1, 1, 0, __DRI_IMAGE_FORMAT_R8, 1 } } },
  482       { DRM_FORMAT_YVU444,        __DRI_IMAGE_FORMAT_NONE,
  483         __DRI_IMAGE_COMPONENTS_Y_U_V,     PIPE_FORMAT_IYUV, 3,
  484         { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
  485           { 2, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
  486           { 1, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 } } },
  487 
  488       { DRM_FORMAT_NV12,          __DRI_IMAGE_FORMAT_NONE,
  489         __DRI_IMAGE_COMPONENTS_Y_UV,      PIPE_FORMAT_NV12, 2,
  490         { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
  491           { 1, 1, 1, __DRI_IMAGE_FORMAT_GR88, 2 } } },
  492 
  493       { DRM_FORMAT_P010,          __DRI_IMAGE_FORMAT_NONE,
  494         __DRI_IMAGE_COMPONENTS_Y_UV,      PIPE_FORMAT_P016, 2,
  495         { { 0, 0, 0, __DRI_IMAGE_FORMAT_R16, 2 },
  496           { 1, 1, 1, __DRI_IMAGE_FORMAT_GR1616, 4 } } },
  497       { DRM_FORMAT_P012,          __DRI_IMAGE_FORMAT_NONE,
  498         __DRI_IMAGE_COMPONENTS_Y_UV,      PIPE_FORMAT_P016, 2,
  499         { { 0, 0, 0, __DRI_IMAGE_FORMAT_R16, 2 },
  500           { 1, 1, 1, __DRI_IMAGE_FORMAT_GR1616, 4 } } },
  501       { DRM_FORMAT_P016,          __DRI_IMAGE_FORMAT_NONE,
  502         __DRI_IMAGE_COMPONENTS_Y_UV,      PIPE_FORMAT_P016, 2,
  503         { { 0, 0, 0, __DRI_IMAGE_FORMAT_R16, 2 },
  504           { 1, 1, 1, __DRI_IMAGE_FORMAT_GR1616, 4 } } },
  505 
  506       { DRM_FORMAT_NV16,          __DRI_IMAGE_FORMAT_NONE,
  507         __DRI_IMAGE_COMPONENTS_Y_UV,      PIPE_FORMAT_NV12, 2,
  508         { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
  509           { 1, 1, 0, __DRI_IMAGE_FORMAT_GR88, 2 } } },
  510 
  511       { DRM_FORMAT_AYUV,      __DRI_IMAGE_FORMAT_ABGR8888,
  512         __DRI_IMAGE_COMPONENTS_AYUV,      PIPE_FORMAT_AYUV, 1,
  513         { { 0, 0, 0, __DRI_IMAGE_FORMAT_ABGR8888, 4 } } },
  514       { DRM_FORMAT_XYUV8888,      __DRI_IMAGE_FORMAT_XBGR8888,
  515         __DRI_IMAGE_COMPONENTS_XYUV,      PIPE_FORMAT_XYUV, 1,
  516         { { 0, 0, 0, __DRI_IMAGE_FORMAT_XBGR8888, 4 } } },
  517 
  518       /* For YUYV and UYVY buffers, we set up two overlapping DRI images
  519        * and treat them as planar buffers in the compositors.
  520        * Plane 0 is GR88 and samples YU or YV pairs and places Y into
  521        * the R component, while plane 1 is ARGB/ABGR and samples YUYV/UYVY
  522        * clusters and places pairs and places U into the G component and
  523        * V into A.  This lets the texture sampler interpolate the Y
  524        * components correctly when sampling from plane 0, and interpolate
  525        * U and V correctly when sampling from plane 1. */
  526       { DRM_FORMAT_YUYV,          __DRI_IMAGE_FORMAT_NONE,
  527         __DRI_IMAGE_COMPONENTS_Y_XUXV,    PIPE_FORMAT_YUYV, 2,
  528         { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88, 2 },
  529           { 0, 1, 0, __DRI_IMAGE_FORMAT_ARGB8888, 4 } } },
  530       { DRM_FORMAT_UYVY,          __DRI_IMAGE_FORMAT_NONE,
  531         __DRI_IMAGE_COMPONENTS_Y_UXVX,    PIPE_FORMAT_UYVY, 2,
  532         { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88, 2 },
  533           { 0, 1, 0, __DRI_IMAGE_FORMAT_ABGR8888, 4 } } }
  534 };
  535 
  536 const struct dri2_format_mapping *
  537 dri2_get_mapping_by_fourcc(int fourcc)
  538 {
  539    for (unsigned i = 0; i < ARRAY_SIZE(dri2_format_table); i++) {
  540       if (dri2_format_table[i].dri_fourcc == fourcc)
  541          return &dri2_format_table[i];
  542    }
  543 
  544    return NULL;
  545 }
  546 
  547 const struct dri2_format_mapping *
  548 dri2_get_mapping_by_format(int format)
  549 {
  550    for (unsigned i = 0; i < ARRAY_SIZE(dri2_format_table); i++) {
  551       if (dri2_format_table[i].dri_format == format)
  552          return &dri2_format_table[i];
  553    }
  554 
  555    return NULL;
  556 }
  557 
  558 enum pipe_format
  559 dri2_get_pipe_format_for_dri_format(int format)
  560 {
  561    for (unsigned i = 0; i < ARRAY_SIZE(dri2_format_table); i++) {
  562       if (dri2_format_table[i].dri_format == format)
  563          return dri2_format_table[i].pipe_format;
  564    }
  565 
  566    return PIPE_FORMAT_NONE;
  567 }
  568 
  569 boolean
  570 dri2_yuv_dma_buf_supported(struct dri_screen *screen,
  571                            const struct dri2_format_mapping *map)
  572 {
  573    struct pipe_screen *pscreen = screen->base.screen;
  574 
  575    for (unsigned i = 0; i < map->nplanes; i++) {
  576       if (!pscreen->is_format_supported(pscreen,
  577             dri2_get_pipe_format_for_dri_format(map->planes[i].dri_format),
  578             screen->target, 0, 0, PIPE_BIND_SAMPLER_VIEW))
  579          return false;
  580    }
  581    return true;
  582 }
  583 
  584 boolean
  585 dri2_query_dma_buf_formats(__DRIscreen *_screen, int max, int *formats,
  586                            int *count)
  587 {
  588    struct dri_screen *screen = dri_screen(_screen);
  589    struct pipe_screen *pscreen = screen->base.screen;
  590    int i, j;
  591 
  592    for (i = 0, j = 0; (i < ARRAY_SIZE(dri2_format_table)) &&
  593          (j < max || max == 0); i++) {
  594       const struct dri2_format_mapping *map = &dri2_format_table[i];
  595 
  596       /* The sRGB format is not a real FourCC as defined by drm_fourcc.h, so we
  597        * must not leak it out to clients.
  598        */
  599       if (dri2_format_table[i].dri_fourcc == __DRI_IMAGE_FOURCC_SARGB8888)
  600          continue;
  601 
  602       if (pscreen->is_format_supported(pscreen, map->pipe_format,
  603                                        screen->target, 0, 0,
  604                                        PIPE_BIND_RENDER_TARGET) ||
  605           pscreen->is_format_supported(pscreen, map->pipe_format,
  606                                        screen->target, 0, 0,
  607                                        PIPE_BIND_SAMPLER_VIEW) ||
  608           dri2_yuv_dma_buf_supported(screen, map)) {
  609          if (j < max)
  610             formats[j] = map->dri_fourcc;
  611          j++;
  612       }
  613    }
  614    *count = j;
  615    return true;
  616 }
  617 
  618 /* vim: set sw=3 ts=8 sts=3 expandtab: */