Home | History | Annotate | Download | only in dri
      1 /*
      2  * Mesa 3-D graphics library
      3  *
      4  * Copyright 2009, VMware, Inc.
      5  * All Rights Reserved.
      6  * Copyright (C) 2010 LunarG Inc.
      7  *
      8  * Permission is hereby granted, free of charge, to any person obtaining a
      9  * copy of this software and associated documentation files (the "Software"),
     10  * to deal in the Software without restriction, including without limitation
     11  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     12  * and/or sell copies of the Software, and to permit persons to whom the
     13  * Software is furnished to do so, subject to the following conditions:
     14  *
     15  * The above copyright notice and this permission notice shall be included
     16  * in all copies or substantial portions 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 MERCHANTABILITY,
     20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     21  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
     22  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     23  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     24  * OTHER DEALINGS IN THE SOFTWARE.
     25  *
     26  * Authors:
     27  *    Keith Whitwell <keithw (at) vmware.com> Jakob Bornecrantz
     28  *    <wallbraker (at) gmail.com> Chia-I Wu <olv (at) lunarg.com>
     29  */
     30 
     31 #include <xf86drm.h>
     32 #include <dlfcn.h>
     33 #include <fcntl.h>
     34 #include "GL/mesa_glinterop.h"
     35 #include "util/u_memory.h"
     36 #include "util/u_inlines.h"
     37 #include "util/u_format.h"
     38 #include "util/u_debug.h"
     39 #include "state_tracker/drm_driver.h"
     40 #include "state_tracker/st_cb_bufferobjects.h"
     41 #include "state_tracker/st_cb_fbo.h"
     42 #include "state_tracker/st_cb_texture.h"
     43 #include "state_tracker/st_texture.h"
     44 #include "state_tracker/st_context.h"
     45 #include "pipe-loader/pipe_loader.h"
     46 #include "main/bufferobj.h"
     47 #include "main/texobj.h"
     48 
     49 #include "dri_screen.h"
     50 #include "dri_context.h"
     51 #include "dri_drawable.h"
     52 #include "dri_query_renderer.h"
     53 #include "dri2_buffer.h"
     54 
     55 static int convert_fourcc(int format, int *dri_components_p)
     56 {
     57    int dri_components;
     58    switch(format) {
     59    case __DRI_IMAGE_FOURCC_RGB565:
     60       format = __DRI_IMAGE_FORMAT_RGB565;
     61       dri_components = __DRI_IMAGE_COMPONENTS_RGB;
     62       break;
     63    case __DRI_IMAGE_FOURCC_ARGB8888:
     64       format = __DRI_IMAGE_FORMAT_ARGB8888;
     65       dri_components = __DRI_IMAGE_COMPONENTS_RGBA;
     66       break;
     67    case __DRI_IMAGE_FOURCC_XRGB8888:
     68       format = __DRI_IMAGE_FORMAT_XRGB8888;
     69       dri_components = __DRI_IMAGE_COMPONENTS_RGB;
     70       break;
     71    case __DRI_IMAGE_FOURCC_ABGR8888:
     72       format = __DRI_IMAGE_FORMAT_ABGR8888;
     73       dri_components = __DRI_IMAGE_COMPONENTS_RGBA;
     74       break;
     75    case __DRI_IMAGE_FOURCC_XBGR8888:
     76       format = __DRI_IMAGE_FORMAT_XBGR8888;
     77       dri_components = __DRI_IMAGE_COMPONENTS_RGB;
     78       break;
     79    case __DRI_IMAGE_FOURCC_R8:
     80       format = __DRI_IMAGE_FORMAT_R8;
     81       dri_components = __DRI_IMAGE_COMPONENTS_R;
     82       break;
     83    case __DRI_IMAGE_FOURCC_GR88:
     84       format = __DRI_IMAGE_FORMAT_GR88;
     85       dri_components = __DRI_IMAGE_COMPONENTS_RG;
     86       break;
     87    /*
     88     * For multi-planar YUV formats, we return the format of the first
     89     * plane only.  Since there is only one caller which supports multi-
     90     * planar YUV it gets to figure out the remaining planes on it's
     91     * own.
     92     */
     93    case __DRI_IMAGE_FOURCC_YUV420:
     94    case __DRI_IMAGE_FOURCC_YVU420:
     95       format = __DRI_IMAGE_FORMAT_R8;
     96       dri_components = __DRI_IMAGE_COMPONENTS_Y_U_V;
     97       break;
     98    case __DRI_IMAGE_FOURCC_NV12:
     99       format = __DRI_IMAGE_FORMAT_R8;
    100       dri_components = __DRI_IMAGE_COMPONENTS_Y_UV;
    101       break;
    102    default:
    103       return -1;
    104    }
    105    *dri_components_p = dri_components;
    106    return format;
    107 }
    108 
    109 /* NOTE this probably isn't going to do the right thing for YUV images
    110  * (but I think the same can be said for intel_query_image()).  I think
    111  * only needed for exporting dmabuf's, so I think I won't loose much
    112  * sleep over it.
    113  */
    114 static int convert_to_fourcc(int format)
    115 {
    116    switch(format) {
    117    case __DRI_IMAGE_FORMAT_RGB565:
    118       format = __DRI_IMAGE_FOURCC_RGB565;
    119       break;
    120    case __DRI_IMAGE_FORMAT_ARGB8888:
    121       format = __DRI_IMAGE_FOURCC_ARGB8888;
    122       break;
    123    case __DRI_IMAGE_FORMAT_XRGB8888:
    124       format = __DRI_IMAGE_FOURCC_XRGB8888;
    125       break;
    126    case __DRI_IMAGE_FORMAT_ABGR8888:
    127       format = __DRI_IMAGE_FOURCC_ABGR8888;
    128       break;
    129    case __DRI_IMAGE_FORMAT_XBGR8888:
    130       format = __DRI_IMAGE_FOURCC_XBGR8888;
    131       break;
    132    case __DRI_IMAGE_FORMAT_R8:
    133       format = __DRI_IMAGE_FOURCC_R8;
    134       break;
    135    case __DRI_IMAGE_FORMAT_GR88:
    136       format = __DRI_IMAGE_FOURCC_GR88;
    137       break;
    138    default:
    139       return -1;
    140    }
    141    return format;
    142 }
    143 
    144 static enum pipe_format dri2_format_to_pipe_format (int format)
    145 {
    146    enum pipe_format pf;
    147 
    148    switch (format) {
    149    case __DRI_IMAGE_FORMAT_RGB565:
    150       pf = PIPE_FORMAT_B5G6R5_UNORM;
    151       break;
    152    case __DRI_IMAGE_FORMAT_XRGB8888:
    153       pf = PIPE_FORMAT_BGRX8888_UNORM;
    154       break;
    155    case __DRI_IMAGE_FORMAT_ARGB8888:
    156       pf = PIPE_FORMAT_BGRA8888_UNORM;
    157       break;
    158    case __DRI_IMAGE_FORMAT_ABGR8888:
    159       pf = PIPE_FORMAT_RGBA8888_UNORM;
    160       break;
    161    case __DRI_IMAGE_FORMAT_R8:
    162       pf = PIPE_FORMAT_R8_UNORM;
    163       break;
    164    case __DRI_IMAGE_FORMAT_GR88:
    165       pf = PIPE_FORMAT_RG88_UNORM;
    166       break;
    167    default:
    168       pf = PIPE_FORMAT_NONE;
    169       break;
    170    }
    171 
    172    return pf;
    173 }
    174 
    175 /**
    176  * DRI2 flush extension.
    177  */
    178 static void
    179 dri2_flush_drawable(__DRIdrawable *dPriv)
    180 {
    181    dri_flush(dPriv->driContextPriv, dPriv, __DRI2_FLUSH_DRAWABLE, -1);
    182 }
    183 
    184 static void
    185 dri2_invalidate_drawable(__DRIdrawable *dPriv)
    186 {
    187    struct dri_drawable *drawable = dri_drawable(dPriv);
    188 
    189    dri2InvalidateDrawable(dPriv);
    190    drawable->dPriv->lastStamp = drawable->dPriv->dri2.stamp;
    191    drawable->texture_mask = 0;
    192 
    193    p_atomic_inc(&drawable->base.stamp);
    194 }
    195 
    196 static const __DRI2flushExtension dri2FlushExtension = {
    197     .base = { __DRI2_FLUSH, 4 },
    198 
    199     .flush                = dri2_flush_drawable,
    200     .invalidate           = dri2_invalidate_drawable,
    201     .flush_with_flags     = dri_flush,
    202 };
    203 
    204 /**
    205  * Retrieve __DRIbuffer from the DRI loader.
    206  */
    207 static __DRIbuffer *
    208 dri2_drawable_get_buffers(struct dri_drawable *drawable,
    209                           const enum st_attachment_type *atts,
    210                           unsigned *count)
    211 {
    212    __DRIdrawable *dri_drawable = drawable->dPriv;
    213    const __DRIdri2LoaderExtension *loader = drawable->sPriv->dri2.loader;
    214    boolean with_format;
    215    __DRIbuffer *buffers;
    216    int num_buffers;
    217    unsigned attachments[10];
    218    unsigned num_attachments, i;
    219 
    220    assert(loader);
    221    with_format = dri_with_format(drawable->sPriv);
    222 
    223    num_attachments = 0;
    224 
    225    /* for Xserver 1.6.0 (DRI2 version 1) we always need to ask for the front */
    226    if (!with_format)
    227       attachments[num_attachments++] = __DRI_BUFFER_FRONT_LEFT;
    228 
    229    for (i = 0; i < *count; i++) {
    230       enum pipe_format format;
    231       unsigned bind;
    232       int att, depth;
    233 
    234       dri_drawable_get_format(drawable, atts[i], &format, &bind);
    235       if (format == PIPE_FORMAT_NONE)
    236          continue;
    237 
    238       switch (atts[i]) {
    239       case ST_ATTACHMENT_FRONT_LEFT:
    240          /* already added */
    241          if (!with_format)
    242             continue;
    243          att = __DRI_BUFFER_FRONT_LEFT;
    244          break;
    245       case ST_ATTACHMENT_BACK_LEFT:
    246          att = __DRI_BUFFER_BACK_LEFT;
    247          break;
    248       case ST_ATTACHMENT_FRONT_RIGHT:
    249          att = __DRI_BUFFER_FRONT_RIGHT;
    250          break;
    251       case ST_ATTACHMENT_BACK_RIGHT:
    252          att = __DRI_BUFFER_BACK_RIGHT;
    253          break;
    254       default:
    255          continue;
    256       }
    257 
    258       /*
    259        * In this switch statement we must support all formats that
    260        * may occur as the stvis->color_format.
    261        */
    262       switch(format) {
    263       case PIPE_FORMAT_BGRA8888_UNORM:
    264 	 depth = 32;
    265 	 break;
    266       case PIPE_FORMAT_BGRX8888_UNORM:
    267 	 depth = 24;
    268 	 break;
    269       case PIPE_FORMAT_B5G6R5_UNORM:
    270 	 depth = 16;
    271 	 break;
    272       default:
    273 	 depth = util_format_get_blocksizebits(format);
    274 	 assert(!"Unexpected format in dri2_drawable_get_buffers()");
    275       }
    276 
    277       attachments[num_attachments++] = att;
    278       if (with_format) {
    279          attachments[num_attachments++] = depth;
    280       }
    281    }
    282 
    283    if (with_format) {
    284       num_attachments /= 2;
    285       buffers = loader->getBuffersWithFormat(dri_drawable,
    286             &dri_drawable->w, &dri_drawable->h,
    287             attachments, num_attachments,
    288             &num_buffers, dri_drawable->loaderPrivate);
    289    }
    290    else {
    291       buffers = loader->getBuffers(dri_drawable,
    292             &dri_drawable->w, &dri_drawable->h,
    293             attachments, num_attachments,
    294             &num_buffers, dri_drawable->loaderPrivate);
    295    }
    296 
    297    if (buffers)
    298       *count = num_buffers;
    299 
    300    return buffers;
    301 }
    302 
    303 static bool
    304 dri_image_drawable_get_buffers(struct dri_drawable *drawable,
    305                                struct __DRIimageList *images,
    306                                const enum st_attachment_type *statts,
    307                                unsigned statts_count)
    308 {
    309    __DRIdrawable *dPriv = drawable->dPriv;
    310    __DRIscreen *sPriv = drawable->sPriv;
    311    unsigned int image_format = __DRI_IMAGE_FORMAT_NONE;
    312    enum pipe_format pf;
    313    uint32_t buffer_mask = 0;
    314    unsigned i, bind;
    315 
    316    for (i = 0; i < statts_count; i++) {
    317       dri_drawable_get_format(drawable, statts[i], &pf, &bind);
    318       if (pf == PIPE_FORMAT_NONE)
    319          continue;
    320 
    321       switch (statts[i]) {
    322       case ST_ATTACHMENT_FRONT_LEFT:
    323          buffer_mask |= __DRI_IMAGE_BUFFER_FRONT;
    324          break;
    325       case ST_ATTACHMENT_BACK_LEFT:
    326          buffer_mask |= __DRI_IMAGE_BUFFER_BACK;
    327          break;
    328       default:
    329          continue;
    330       }
    331 
    332       switch (pf) {
    333       case PIPE_FORMAT_B5G6R5_UNORM:
    334          image_format = __DRI_IMAGE_FORMAT_RGB565;
    335          break;
    336       case PIPE_FORMAT_BGRX8888_UNORM:
    337          image_format = __DRI_IMAGE_FORMAT_XRGB8888;
    338          break;
    339       case PIPE_FORMAT_BGRA8888_UNORM:
    340          image_format = __DRI_IMAGE_FORMAT_ARGB8888;
    341          break;
    342       case PIPE_FORMAT_RGBA8888_UNORM:
    343          image_format = __DRI_IMAGE_FORMAT_ABGR8888;
    344          break;
    345       default:
    346          image_format = __DRI_IMAGE_FORMAT_NONE;
    347          break;
    348       }
    349    }
    350 
    351    return (*sPriv->image.loader->getBuffers) (dPriv, image_format,
    352                                        (uint32_t *) &drawable->base.stamp,
    353                                        dPriv->loaderPrivate, buffer_mask,
    354                                        images);
    355 }
    356 
    357 static __DRIbuffer *
    358 dri2_allocate_buffer(__DRIscreen *sPriv,
    359                      unsigned attachment, unsigned format,
    360                      int width, int height)
    361 {
    362    struct dri_screen *screen = dri_screen(sPriv);
    363    struct dri2_buffer *buffer;
    364    struct pipe_resource templ;
    365    enum pipe_format pf;
    366    unsigned bind = 0;
    367    struct winsys_handle whandle;
    368 
    369    switch (attachment) {
    370       case __DRI_BUFFER_FRONT_LEFT:
    371       case __DRI_BUFFER_FAKE_FRONT_LEFT:
    372          bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
    373          break;
    374       case __DRI_BUFFER_BACK_LEFT:
    375          bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
    376          break;
    377       case __DRI_BUFFER_DEPTH:
    378       case __DRI_BUFFER_DEPTH_STENCIL:
    379       case __DRI_BUFFER_STENCIL:
    380             bind = PIPE_BIND_DEPTH_STENCIL; /* XXX sampler? */
    381          break;
    382    }
    383 
    384    /* because we get the handle and stride */
    385    bind |= PIPE_BIND_SHARED;
    386 
    387    switch (format) {
    388       case 32:
    389          pf = PIPE_FORMAT_BGRA8888_UNORM;
    390          break;
    391       case 24:
    392          pf = PIPE_FORMAT_BGRX8888_UNORM;
    393          break;
    394       case 16:
    395          pf = PIPE_FORMAT_Z16_UNORM;
    396          break;
    397       default:
    398          return NULL;
    399    }
    400 
    401    buffer = CALLOC_STRUCT(dri2_buffer);
    402    if (!buffer)
    403       return NULL;
    404 
    405    memset(&templ, 0, sizeof(templ));
    406    templ.bind = bind;
    407    templ.format = pf;
    408    templ.target = PIPE_TEXTURE_2D;
    409    templ.last_level = 0;
    410    templ.width0 = width;
    411    templ.height0 = height;
    412    templ.depth0 = 1;
    413    templ.array_size = 1;
    414 
    415    buffer->resource =
    416       screen->base.screen->resource_create(screen->base.screen, &templ);
    417    if (!buffer->resource) {
    418       FREE(buffer);
    419       return NULL;
    420    }
    421 
    422    memset(&whandle, 0, sizeof(whandle));
    423    if (screen->can_share_buffer)
    424       whandle.type = DRM_API_HANDLE_TYPE_SHARED;
    425    else
    426       whandle.type = DRM_API_HANDLE_TYPE_KMS;
    427 
    428    screen->base.screen->resource_get_handle(screen->base.screen, NULL,
    429          buffer->resource, &whandle,
    430          PIPE_HANDLE_USAGE_EXPLICIT_FLUSH | PIPE_HANDLE_USAGE_READ);
    431 
    432    buffer->base.attachment = attachment;
    433    buffer->base.name = whandle.handle;
    434    buffer->base.cpp = util_format_get_blocksize(pf);
    435    buffer->base.pitch = whandle.stride;
    436 
    437    return &buffer->base;
    438 }
    439 
    440 static void
    441 dri2_release_buffer(__DRIscreen *sPriv, __DRIbuffer *bPriv)
    442 {
    443    struct dri2_buffer *buffer = dri2_buffer(bPriv);
    444 
    445    pipe_resource_reference(&buffer->resource, NULL);
    446    FREE(buffer);
    447 }
    448 
    449 /*
    450  * Backend functions for st_framebuffer interface.
    451  */
    452 
    453 static void
    454 dri2_allocate_textures(struct dri_context *ctx,
    455                        struct dri_drawable *drawable,
    456                        const enum st_attachment_type *statts,
    457                        unsigned statts_count)
    458 {
    459    __DRIscreen *sPriv = drawable->sPriv;
    460    __DRIdrawable *dri_drawable = drawable->dPriv;
    461    struct dri_screen *screen = dri_screen(sPriv);
    462    struct pipe_resource templ;
    463    boolean alloc_depthstencil = FALSE;
    464    unsigned i, j, bind;
    465    const __DRIimageLoaderExtension *image = sPriv->image.loader;
    466    /* Image specific variables */
    467    struct __DRIimageList images;
    468    /* Dri2 specific variables */
    469    __DRIbuffer *buffers = NULL;
    470    struct winsys_handle whandle;
    471    unsigned num_buffers = statts_count;
    472 
    473    /* First get the buffers from the loader */
    474    if (image) {
    475       if (!dri_image_drawable_get_buffers(drawable, &images,
    476                                           statts, statts_count))
    477          return;
    478    }
    479    else {
    480       buffers = dri2_drawable_get_buffers(drawable, statts, &num_buffers);
    481       if (!buffers || (drawable->old_num == num_buffers &&
    482                        drawable->old_w == dri_drawable->w &&
    483                        drawable->old_h == dri_drawable->h &&
    484                        memcmp(drawable->old, buffers,
    485                               sizeof(__DRIbuffer) * num_buffers) == 0))
    486          return;
    487    }
    488 
    489    /* Second clean useless resources*/
    490 
    491    /* See if we need a depth-stencil buffer. */
    492    for (i = 0; i < statts_count; i++) {
    493       if (statts[i] == ST_ATTACHMENT_DEPTH_STENCIL) {
    494          alloc_depthstencil = TRUE;
    495          break;
    496       }
    497    }
    498 
    499    /* Delete the resources we won't need. */
    500    for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
    501       /* Don't delete the depth-stencil buffer, we can reuse it. */
    502       if (i == ST_ATTACHMENT_DEPTH_STENCIL && alloc_depthstencil)
    503          continue;
    504 
    505       /* Flush the texture before unreferencing, so that other clients can
    506        * see what the driver has rendered.
    507        */
    508       if (i != ST_ATTACHMENT_DEPTH_STENCIL && drawable->textures[i]) {
    509          struct pipe_context *pipe = ctx->st->pipe;
    510          pipe->flush_resource(pipe, drawable->textures[i]);
    511       }
    512 
    513       pipe_resource_reference(&drawable->textures[i], NULL);
    514    }
    515 
    516    if (drawable->stvis.samples > 1) {
    517       for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
    518          boolean del = TRUE;
    519 
    520          /* Don't delete MSAA resources for the attachments which are enabled,
    521           * we can reuse them. */
    522          for (j = 0; j < statts_count; j++) {
    523             if (i == statts[j]) {
    524                del = FALSE;
    525                break;
    526             }
    527          }
    528 
    529          if (del) {
    530             pipe_resource_reference(&drawable->msaa_textures[i], NULL);
    531          }
    532       }
    533    }
    534 
    535    /* Third use the buffers retrieved to fill the drawable info */
    536 
    537    memset(&templ, 0, sizeof(templ));
    538    templ.target = screen->target;
    539    templ.last_level = 0;
    540    templ.depth0 = 1;
    541    templ.array_size = 1;
    542 
    543    if (image) {
    544       if (images.image_mask & __DRI_IMAGE_BUFFER_FRONT) {
    545          struct pipe_resource **buf =
    546             &drawable->textures[ST_ATTACHMENT_FRONT_LEFT];
    547          struct pipe_resource *texture = images.front->texture;
    548 
    549          dri_drawable->w = texture->width0;
    550          dri_drawable->h = texture->height0;
    551 
    552          pipe_resource_reference(buf, texture);
    553       }
    554 
    555       if (images.image_mask & __DRI_IMAGE_BUFFER_BACK) {
    556          struct pipe_resource **buf =
    557             &drawable->textures[ST_ATTACHMENT_BACK_LEFT];
    558          struct pipe_resource *texture = images.back->texture;
    559 
    560          dri_drawable->w = texture->width0;
    561          dri_drawable->h = texture->height0;
    562 
    563          pipe_resource_reference(buf, texture);
    564       }
    565 
    566       /* Note: if there is both a back and a front buffer,
    567        * then they have the same size.
    568        */
    569       templ.width0 = dri_drawable->w;
    570       templ.height0 = dri_drawable->h;
    571    }
    572    else {
    573       memset(&whandle, 0, sizeof(whandle));
    574 
    575       /* Process DRI-provided buffers and get pipe_resources. */
    576       for (i = 0; i < num_buffers; i++) {
    577          __DRIbuffer *buf = &buffers[i];
    578          enum st_attachment_type statt;
    579          enum pipe_format format;
    580 
    581          switch (buf->attachment) {
    582          case __DRI_BUFFER_FRONT_LEFT:
    583             if (!screen->auto_fake_front) {
    584                continue; /* invalid attachment */
    585             }
    586             /* fallthrough */
    587          case __DRI_BUFFER_FAKE_FRONT_LEFT:
    588             statt = ST_ATTACHMENT_FRONT_LEFT;
    589             break;
    590          case __DRI_BUFFER_BACK_LEFT:
    591             statt = ST_ATTACHMENT_BACK_LEFT;
    592             break;
    593          default:
    594             continue; /* invalid attachment */
    595          }
    596 
    597          dri_drawable_get_format(drawable, statt, &format, &bind);
    598          if (format == PIPE_FORMAT_NONE)
    599             continue;
    600 
    601          /* dri2_drawable_get_buffers has already filled dri_drawable->w
    602           * and dri_drawable->h */
    603          templ.width0 = dri_drawable->w;
    604          templ.height0 = dri_drawable->h;
    605          templ.format = format;
    606          templ.bind = bind;
    607          whandle.handle = buf->name;
    608          whandle.stride = buf->pitch;
    609          whandle.offset = 0;
    610          if (screen->can_share_buffer)
    611             whandle.type = DRM_API_HANDLE_TYPE_SHARED;
    612          else
    613             whandle.type = DRM_API_HANDLE_TYPE_KMS;
    614          drawable->textures[statt] =
    615             screen->base.screen->resource_from_handle(screen->base.screen,
    616                   &templ, &whandle,
    617                   PIPE_HANDLE_USAGE_EXPLICIT_FLUSH | PIPE_HANDLE_USAGE_READ);
    618          assert(drawable->textures[statt]);
    619       }
    620    }
    621 
    622    /* Allocate private MSAA colorbuffers. */
    623    if (drawable->stvis.samples > 1) {
    624       for (i = 0; i < statts_count; i++) {
    625          enum st_attachment_type statt = statts[i];
    626 
    627          if (statt == ST_ATTACHMENT_DEPTH_STENCIL)
    628             continue;
    629 
    630          if (drawable->textures[statt]) {
    631             templ.format = drawable->textures[statt]->format;
    632             templ.bind = drawable->textures[statt]->bind & ~PIPE_BIND_SCANOUT;
    633             templ.nr_samples = drawable->stvis.samples;
    634 
    635             /* Try to reuse the resource.
    636              * (the other resource parameters should be constant)
    637              */
    638             if (!drawable->msaa_textures[statt] ||
    639                 drawable->msaa_textures[statt]->width0 != templ.width0 ||
    640                 drawable->msaa_textures[statt]->height0 != templ.height0) {
    641                /* Allocate a new one. */
    642                pipe_resource_reference(&drawable->msaa_textures[statt], NULL);
    643 
    644                drawable->msaa_textures[statt] =
    645                   screen->base.screen->resource_create(screen->base.screen,
    646                                                        &templ);
    647                assert(drawable->msaa_textures[statt]);
    648 
    649                /* If there are any MSAA resources, we should initialize them
    650                 * such that they contain the same data as the single-sample
    651                 * resources we just got from the X server.
    652                 *
    653                 * The reason for this is that the state tracker (and
    654                 * therefore the app) can access the MSAA resources only.
    655                 * The single-sample resources are not exposed
    656                 * to the state tracker.
    657                 *
    658                 */
    659                dri_pipe_blit(ctx->st->pipe,
    660                              drawable->msaa_textures[statt],
    661                              drawable->textures[statt]);
    662             }
    663          }
    664          else {
    665             pipe_resource_reference(&drawable->msaa_textures[statt], NULL);
    666          }
    667       }
    668    }
    669 
    670    /* Allocate a private depth-stencil buffer. */
    671    if (alloc_depthstencil) {
    672       enum st_attachment_type statt = ST_ATTACHMENT_DEPTH_STENCIL;
    673       struct pipe_resource **zsbuf;
    674       enum pipe_format format;
    675       unsigned bind;
    676 
    677       dri_drawable_get_format(drawable, statt, &format, &bind);
    678 
    679       if (format) {
    680          templ.format = format;
    681          templ.bind = bind;
    682 
    683          if (drawable->stvis.samples > 1) {
    684             templ.nr_samples = drawable->stvis.samples;
    685             zsbuf = &drawable->msaa_textures[statt];
    686          }
    687          else {
    688             templ.nr_samples = 0;
    689             zsbuf = &drawable->textures[statt];
    690          }
    691 
    692          /* Try to reuse the resource.
    693           * (the other resource parameters should be constant)
    694           */
    695          if (!*zsbuf ||
    696              (*zsbuf)->width0 != templ.width0 ||
    697              (*zsbuf)->height0 != templ.height0) {
    698             /* Allocate a new one. */
    699             pipe_resource_reference(zsbuf, NULL);
    700             *zsbuf = screen->base.screen->resource_create(screen->base.screen,
    701                                                           &templ);
    702             assert(*zsbuf);
    703          }
    704       }
    705       else {
    706          pipe_resource_reference(&drawable->msaa_textures[statt], NULL);
    707          pipe_resource_reference(&drawable->textures[statt], NULL);
    708       }
    709    }
    710 
    711    /* For DRI2, we may get the same buffers again from the server.
    712     * To prevent useless imports of gem names, drawable->old* is used
    713     * to bypass the import if we get the same buffers. This doesn't apply
    714     * to DRI3/Wayland, users of image.loader, since the buffer is managed
    715     * by the client (no import), and the back buffer is going to change
    716     * at every redraw.
    717     */
    718    if (!image) {
    719       drawable->old_num = num_buffers;
    720       drawable->old_w = dri_drawable->w;
    721       drawable->old_h = dri_drawable->h;
    722       memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * num_buffers);
    723    }
    724 }
    725 
    726 static void
    727 dri2_flush_frontbuffer(struct dri_context *ctx,
    728                        struct dri_drawable *drawable,
    729                        enum st_attachment_type statt)
    730 {
    731    __DRIdrawable *dri_drawable = drawable->dPriv;
    732    const __DRIimageLoaderExtension *image = drawable->sPriv->image.loader;
    733    const __DRIdri2LoaderExtension *loader = drawable->sPriv->dri2.loader;
    734    struct pipe_context *pipe = ctx->st->pipe;
    735 
    736    if (statt != ST_ATTACHMENT_FRONT_LEFT)
    737       return;
    738 
    739    if (drawable->stvis.samples > 1) {
    740       /* Resolve the front buffer. */
    741       dri_pipe_blit(ctx->st->pipe,
    742                     drawable->textures[ST_ATTACHMENT_FRONT_LEFT],
    743                     drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT]);
    744    }
    745 
    746    if (drawable->textures[ST_ATTACHMENT_FRONT_LEFT]) {
    747       pipe->flush_resource(pipe, drawable->textures[ST_ATTACHMENT_FRONT_LEFT]);
    748    }
    749 
    750    pipe->flush(pipe, NULL, 0);
    751 
    752    if (image) {
    753       image->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate);
    754    }
    755    else if (loader->flushFrontBuffer) {
    756       loader->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate);
    757    }
    758 }
    759 
    760 static void
    761 dri2_update_tex_buffer(struct dri_drawable *drawable,
    762                        struct dri_context *ctx,
    763                        struct pipe_resource *res)
    764 {
    765    /* no-op */
    766 }
    767 
    768 static __DRIimage *
    769 dri2_lookup_egl_image(struct dri_screen *screen, void *handle)
    770 {
    771    const __DRIimageLookupExtension *loader = screen->sPriv->dri2.image;
    772    __DRIimage *img;
    773 
    774    if (!loader->lookupEGLImage)
    775       return NULL;
    776 
    777    img = loader->lookupEGLImage(screen->sPriv,
    778 				handle, screen->sPriv->loaderPrivate);
    779 
    780    return img;
    781 }
    782 
    783 static __DRIimage *
    784 dri2_create_image_from_winsys(__DRIscreen *_screen,
    785                               int width, int height, int format,
    786                               int num_handles, struct winsys_handle *whandle,
    787                               void *loaderPrivate)
    788 {
    789    struct dri_screen *screen = dri_screen(_screen);
    790    struct pipe_screen *pscreen = screen->base.screen;
    791    __DRIimage *img;
    792    struct pipe_resource templ;
    793    unsigned tex_usage;
    794    enum pipe_format pf;
    795    int i;
    796 
    797    tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
    798 
    799    pf = dri2_format_to_pipe_format (format);
    800    if (pf == PIPE_FORMAT_NONE)
    801       return NULL;
    802 
    803    img = CALLOC_STRUCT(__DRIimageRec);
    804    if (!img)
    805       return NULL;
    806 
    807    memset(&templ, 0, sizeof(templ));
    808    templ.bind = tex_usage;
    809    templ.target = screen->target;
    810    templ.last_level = 0;
    811    templ.depth0 = 1;
    812    templ.array_size = 1;
    813 
    814    for (i = num_handles - 1; i >= 0; i--) {
    815       struct pipe_resource *tex;
    816 
    817       /* TODO: something a lot less ugly */
    818       switch (i) {
    819       case 0:
    820          templ.width0 = width;
    821          templ.height0 = height;
    822          templ.format = pf;
    823          break;
    824       case 1:
    825          templ.width0 = width / 2;
    826          templ.height0 = height / 2;
    827          templ.format = (num_handles == 2) ?
    828                PIPE_FORMAT_RG88_UNORM :   /* NV12, etc */
    829                PIPE_FORMAT_R8_UNORM;      /* I420, etc */
    830          break;
    831       case 2:
    832          templ.width0 = width / 2;
    833          templ.height0 = height / 2;
    834          templ.format = PIPE_FORMAT_R8_UNORM;
    835          break;
    836       default:
    837          unreachable("too many planes!");
    838       }
    839 
    840       tex = pscreen->resource_from_handle(pscreen,
    841             &templ, &whandle[i], PIPE_HANDLE_USAGE_READ_WRITE);
    842       if (!tex) {
    843          pipe_resource_reference(&img->texture, NULL);
    844          FREE(img);
    845          return NULL;
    846       }
    847 
    848       tex->next = img->texture;
    849       img->texture = tex;
    850    }
    851 
    852    img->level = 0;
    853    img->layer = 0;
    854    img->dri_format = format;
    855    img->use = 0;
    856    img->loader_private = loaderPrivate;
    857 
    858    return img;
    859 }
    860 
    861 static __DRIimage *
    862 dri2_create_image_from_name(__DRIscreen *_screen,
    863                             int width, int height, int format,
    864                             int name, int pitch, void *loaderPrivate)
    865 {
    866    struct winsys_handle whandle;
    867    enum pipe_format pf;
    868 
    869    memset(&whandle, 0, sizeof(whandle));
    870    whandle.type = DRM_API_HANDLE_TYPE_SHARED;
    871    whandle.handle = name;
    872 
    873    pf = dri2_format_to_pipe_format (format);
    874    if (pf == PIPE_FORMAT_NONE)
    875       return NULL;
    876 
    877    whandle.stride = pitch * util_format_get_blocksize(pf);
    878 
    879    return dri2_create_image_from_winsys(_screen, width, height, format,
    880                                         1, &whandle, loaderPrivate);
    881 }
    882 
    883 static __DRIimage *
    884 dri2_create_image_from_fd(__DRIscreen *_screen,
    885                           int width, int height, int fourcc,
    886                           int *fds, int num_fds, int *strides,
    887                           int *offsets, unsigned *error,
    888                           int *dri_components, void *loaderPrivate)
    889 {
    890    struct winsys_handle whandles[3];
    891    int format;
    892    __DRIimage *img = NULL;
    893    unsigned err = __DRI_IMAGE_ERROR_SUCCESS;
    894    int expected_num_fds, i;
    895 
    896    switch (fourcc) {
    897    case __DRI_IMAGE_FOURCC_YUV420:
    898    case __DRI_IMAGE_FOURCC_YVU420:
    899       expected_num_fds = 3;
    900       break;
    901    case __DRI_IMAGE_FOURCC_NV12:
    902       expected_num_fds = 2;
    903       break;
    904    default:
    905       expected_num_fds = 1;
    906       break;
    907    }
    908 
    909    if (num_fds != expected_num_fds) {
    910       err = __DRI_IMAGE_ERROR_BAD_MATCH;
    911       goto exit;
    912    }
    913 
    914    format = convert_fourcc(fourcc, dri_components);
    915    if (format == -1) {
    916       err = __DRI_IMAGE_ERROR_BAD_MATCH;
    917       goto exit;
    918    }
    919 
    920    memset(whandles, 0, sizeof(whandles));
    921 
    922    for (i = 0; i < num_fds; i++) {
    923       if (fds[i] < 0) {
    924          err = __DRI_IMAGE_ERROR_BAD_ALLOC;
    925          goto exit;
    926       }
    927 
    928       whandles[i].type = DRM_API_HANDLE_TYPE_FD;
    929       whandles[i].handle = (unsigned)fds[i];
    930       whandles[i].stride = (unsigned)strides[i];
    931       whandles[i].offset = (unsigned)offsets[i];
    932    }
    933 
    934    if (fourcc == __DRI_IMAGE_FOURCC_YVU420) {
    935       /* convert to YUV420 by swapping 2nd and 3rd planes: */
    936       struct winsys_handle tmp = whandles[1];
    937       whandles[1] = whandles[2];
    938       whandles[2] = tmp;
    939       fourcc = __DRI_IMAGE_FOURCC_YUV420;
    940    }
    941 
    942    img = dri2_create_image_from_winsys(_screen, width, height, format,
    943                                        num_fds, whandles, loaderPrivate);
    944    if(img == NULL)
    945       err = __DRI_IMAGE_ERROR_BAD_ALLOC;
    946 
    947 exit:
    948    if (error)
    949       *error = err;
    950 
    951    return img;
    952 }
    953 
    954 static __DRIimage *
    955 dri2_create_image_from_renderbuffer(__DRIcontext *context,
    956 				    int renderbuffer, void *loaderPrivate)
    957 {
    958    struct dri_context *ctx = dri_context(context);
    959 
    960    if (!ctx->st->get_resource_for_egl_image)
    961       return NULL;
    962 
    963    /* TODO */
    964    return NULL;
    965 }
    966 
    967 static __DRIimage *
    968 dri2_create_image(__DRIscreen *_screen,
    969                    int width, int height, int format,
    970                    unsigned int use, void *loaderPrivate)
    971 {
    972    struct dri_screen *screen = dri_screen(_screen);
    973    __DRIimage *img;
    974    struct pipe_resource templ;
    975    unsigned tex_usage;
    976    enum pipe_format pf;
    977 
    978    tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
    979    if (use & __DRI_IMAGE_USE_SCANOUT)
    980       tex_usage |= PIPE_BIND_SCANOUT;
    981    if (use & __DRI_IMAGE_USE_SHARE)
    982       tex_usage |= PIPE_BIND_SHARED;
    983    if (use & __DRI_IMAGE_USE_LINEAR)
    984       tex_usage |= PIPE_BIND_LINEAR;
    985    if (use & __DRI_IMAGE_USE_CURSOR) {
    986       if (width != 64 || height != 64)
    987          return NULL;
    988       tex_usage |= PIPE_BIND_CURSOR;
    989    }
    990 
    991    pf = dri2_format_to_pipe_format (format);
    992    if (pf == PIPE_FORMAT_NONE)
    993       return NULL;
    994 
    995    img = CALLOC_STRUCT(__DRIimageRec);
    996    if (!img)
    997       return NULL;
    998 
    999    memset(&templ, 0, sizeof(templ));
   1000    templ.bind = tex_usage;
   1001    templ.format = pf;
   1002    templ.target = PIPE_TEXTURE_2D;
   1003    templ.last_level = 0;
   1004    templ.width0 = width;
   1005    templ.height0 = height;
   1006    templ.depth0 = 1;
   1007    templ.array_size = 1;
   1008 
   1009    img->texture = screen->base.screen->resource_create(screen->base.screen, &templ);
   1010    if (!img->texture) {
   1011       FREE(img);
   1012       return NULL;
   1013    }
   1014 
   1015    img->level = 0;
   1016    img->layer = 0;
   1017    img->dri_format = format;
   1018    img->dri_components = 0;
   1019    img->use = use;
   1020 
   1021    img->loader_private = loaderPrivate;
   1022    return img;
   1023 }
   1024 
   1025 static GLboolean
   1026 dri2_query_image(__DRIimage *image, int attrib, int *value)
   1027 {
   1028    struct winsys_handle whandle;
   1029    unsigned usage;
   1030 
   1031    if (image->use & __DRI_IMAGE_USE_BACKBUFFER)
   1032       usage = PIPE_HANDLE_USAGE_EXPLICIT_FLUSH | PIPE_HANDLE_USAGE_READ;
   1033    else
   1034       usage = PIPE_HANDLE_USAGE_READ_WRITE;
   1035 
   1036    memset(&whandle, 0, sizeof(whandle));
   1037 
   1038    switch (attrib) {
   1039    case __DRI_IMAGE_ATTRIB_STRIDE:
   1040       whandle.type = DRM_API_HANDLE_TYPE_KMS;
   1041       image->texture->screen->resource_get_handle(image->texture->screen,
   1042             NULL, image->texture, &whandle, usage);
   1043       *value = whandle.stride;
   1044       return GL_TRUE;
   1045    case __DRI_IMAGE_ATTRIB_HANDLE:
   1046       whandle.type = DRM_API_HANDLE_TYPE_KMS;
   1047       image->texture->screen->resource_get_handle(image->texture->screen,
   1048          NULL, image->texture, &whandle, usage);
   1049       *value = whandle.handle;
   1050       return GL_TRUE;
   1051    case __DRI_IMAGE_ATTRIB_NAME:
   1052       whandle.type = DRM_API_HANDLE_TYPE_SHARED;
   1053       image->texture->screen->resource_get_handle(image->texture->screen,
   1054          NULL, image->texture, &whandle, usage);
   1055       *value = whandle.handle;
   1056       return GL_TRUE;
   1057    case __DRI_IMAGE_ATTRIB_FD:
   1058       whandle.type= DRM_API_HANDLE_TYPE_FD;
   1059       if (!image->texture->screen->resource_get_handle(image->texture->screen,
   1060             NULL, image->texture, &whandle, usage))
   1061          return GL_FALSE;
   1062 
   1063       *value = whandle.handle;
   1064       return GL_TRUE;
   1065    case __DRI_IMAGE_ATTRIB_FORMAT:
   1066       *value = image->dri_format;
   1067       return GL_TRUE;
   1068    case __DRI_IMAGE_ATTRIB_WIDTH:
   1069       *value = image->texture->width0;
   1070       return GL_TRUE;
   1071    case __DRI_IMAGE_ATTRIB_HEIGHT:
   1072       *value = image->texture->height0;
   1073       return GL_TRUE;
   1074    case __DRI_IMAGE_ATTRIB_COMPONENTS:
   1075       if (image->dri_components == 0)
   1076          return GL_FALSE;
   1077       *value = image->dri_components;
   1078       return GL_TRUE;
   1079    case __DRI_IMAGE_ATTRIB_FOURCC:
   1080       *value = convert_to_fourcc(image->dri_format);
   1081       return GL_TRUE;
   1082    case __DRI_IMAGE_ATTRIB_NUM_PLANES:
   1083       *value = 1;
   1084       return GL_TRUE;
   1085    default:
   1086       return GL_FALSE;
   1087    }
   1088 }
   1089 
   1090 static __DRIimage *
   1091 dri2_dup_image(__DRIimage *image, void *loaderPrivate)
   1092 {
   1093    __DRIimage *img;
   1094 
   1095    img = CALLOC_STRUCT(__DRIimageRec);
   1096    if (!img)
   1097       return NULL;
   1098 
   1099    img->texture = NULL;
   1100    pipe_resource_reference(&img->texture, image->texture);
   1101    img->level = image->level;
   1102    img->layer = image->layer;
   1103    img->dri_format = image->dri_format;
   1104    /* This should be 0 for sub images, but dup is also used for base images. */
   1105    img->dri_components = image->dri_components;
   1106    img->loader_private = loaderPrivate;
   1107 
   1108    return img;
   1109 }
   1110 
   1111 static GLboolean
   1112 dri2_validate_usage(__DRIimage *image, unsigned int use)
   1113 {
   1114    /*
   1115     * Gallium drivers are bad at adding usages to the resources
   1116     * once opened again in another process, which is the main use
   1117     * case for this, so we have to lie.
   1118     */
   1119    if (image != NULL)
   1120       return GL_TRUE;
   1121    else
   1122       return GL_FALSE;
   1123 }
   1124 
   1125 static __DRIimage *
   1126 dri2_from_names(__DRIscreen *screen, int width, int height, int format,
   1127                 int *names, int num_names, int *strides, int *offsets,
   1128                 void *loaderPrivate)
   1129 {
   1130    __DRIimage *img;
   1131    int dri_components;
   1132    struct winsys_handle whandle;
   1133 
   1134    if (num_names != 1)
   1135       return NULL;
   1136 
   1137    format = convert_fourcc(format, &dri_components);
   1138    if (format == -1)
   1139       return NULL;
   1140 
   1141    memset(&whandle, 0, sizeof(whandle));
   1142    whandle.type = DRM_API_HANDLE_TYPE_SHARED;
   1143    whandle.handle = names[0];
   1144    whandle.stride = strides[0];
   1145    whandle.offset = offsets[0];
   1146 
   1147    img = dri2_create_image_from_winsys(screen, width, height, format,
   1148                                        1, &whandle, loaderPrivate);
   1149    if (img == NULL)
   1150       return NULL;
   1151 
   1152    img->dri_components = dri_components;
   1153    return img;
   1154 }
   1155 
   1156 static __DRIimage *
   1157 dri2_from_planar(__DRIimage *image, int plane, void *loaderPrivate)
   1158 {
   1159    __DRIimage *img;
   1160 
   1161    if (plane != 0)
   1162       return NULL;
   1163 
   1164    if (image->dri_components == 0)
   1165       return NULL;
   1166 
   1167    img = dri2_dup_image(image, loaderPrivate);
   1168    if (img == NULL)
   1169       return NULL;
   1170 
   1171    /* set this to 0 for sub images. */
   1172    img->dri_components = 0;
   1173    return img;
   1174 }
   1175 
   1176 static __DRIimage *
   1177 dri2_create_from_texture(__DRIcontext *context, int target, unsigned texture,
   1178                          int depth, int level, unsigned *error,
   1179                          void *loaderPrivate)
   1180 {
   1181    __DRIimage *img;
   1182    struct gl_context *ctx = ((struct st_context *)dri_context(context)->st)->ctx;
   1183    struct gl_texture_object *obj;
   1184    struct pipe_resource *tex;
   1185    GLuint face = 0;
   1186 
   1187    obj = _mesa_lookup_texture(ctx, texture);
   1188    if (!obj || obj->Target != target) {
   1189       *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
   1190       return NULL;
   1191    }
   1192 
   1193    tex = st_get_texobj_resource(obj);
   1194    if (!tex) {
   1195       *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
   1196       return NULL;
   1197    }
   1198 
   1199    if (target == GL_TEXTURE_CUBE_MAP)
   1200       face = depth;
   1201 
   1202    _mesa_test_texobj_completeness(ctx, obj);
   1203    if (!obj->_BaseComplete || (level > 0 && !obj->_MipmapComplete)) {
   1204       *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
   1205       return NULL;
   1206    }
   1207 
   1208    if (level < obj->BaseLevel || level > obj->_MaxLevel) {
   1209       *error = __DRI_IMAGE_ERROR_BAD_MATCH;
   1210       return NULL;
   1211    }
   1212 
   1213    if (target == GL_TEXTURE_3D && obj->Image[face][level]->Depth < depth) {
   1214       *error = __DRI_IMAGE_ERROR_BAD_MATCH;
   1215       return NULL;
   1216    }
   1217 
   1218    img = CALLOC_STRUCT(__DRIimageRec);
   1219    if (!img) {
   1220       *error = __DRI_IMAGE_ERROR_BAD_ALLOC;
   1221       return NULL;
   1222    }
   1223 
   1224    img->level = level;
   1225    img->layer = depth;
   1226    img->dri_format = driGLFormatToImageFormat(obj->Image[face][level]->TexFormat);
   1227 
   1228    img->loader_private = loaderPrivate;
   1229 
   1230    if (img->dri_format == __DRI_IMAGE_FORMAT_NONE) {
   1231       *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
   1232       free(img);
   1233       return NULL;
   1234    }
   1235 
   1236    pipe_resource_reference(&img->texture, tex);
   1237 
   1238    *error = __DRI_IMAGE_ERROR_SUCCESS;
   1239    return img;
   1240 }
   1241 
   1242 static __DRIimage *
   1243 dri2_from_fds(__DRIscreen *screen, int width, int height, int fourcc,
   1244               int *fds, int num_fds, int *strides, int *offsets,
   1245               void *loaderPrivate)
   1246 {
   1247    __DRIimage *img;
   1248    int dri_components;
   1249 
   1250    img = dri2_create_image_from_fd(screen, width, height, fourcc,
   1251                                    fds, num_fds, strides, offsets, NULL,
   1252                                    &dri_components, loaderPrivate);
   1253    if (img == NULL)
   1254       return NULL;
   1255 
   1256    img->dri_components = dri_components;
   1257    return img;
   1258 }
   1259 
   1260 static __DRIimage *
   1261 dri2_from_dma_bufs(__DRIscreen *screen,
   1262                    int width, int height, int fourcc,
   1263                    int *fds, int num_fds,
   1264                    int *strides, int *offsets,
   1265                    enum __DRIYUVColorSpace yuv_color_space,
   1266                    enum __DRISampleRange sample_range,
   1267                    enum __DRIChromaSiting horizontal_siting,
   1268                    enum __DRIChromaSiting vertical_siting,
   1269                    unsigned *error,
   1270                    void *loaderPrivate)
   1271 {
   1272    __DRIimage *img;
   1273    int dri_components;
   1274 
   1275    img = dri2_create_image_from_fd(screen, width, height, fourcc,
   1276                                    fds, num_fds, strides, offsets, error,
   1277                                    &dri_components, loaderPrivate);
   1278    if (img == NULL)
   1279       return NULL;
   1280 
   1281    img->yuv_color_space = yuv_color_space;
   1282    img->sample_range = sample_range;
   1283    img->horizontal_siting = horizontal_siting;
   1284    img->vertical_siting = vertical_siting;
   1285    img->dri_components = dri_components;
   1286 
   1287    *error = __DRI_IMAGE_ERROR_SUCCESS;
   1288    return img;
   1289 }
   1290 
   1291 static void
   1292 dri2_blit_image(__DRIcontext *context, __DRIimage *dst, __DRIimage *src,
   1293                 int dstx0, int dsty0, int dstwidth, int dstheight,
   1294                 int srcx0, int srcy0, int srcwidth, int srcheight,
   1295                 int flush_flag)
   1296 {
   1297    struct dri_context *ctx = dri_context(context);
   1298    struct pipe_context *pipe = ctx->st->pipe;
   1299    struct pipe_screen *screen;
   1300    struct pipe_fence_handle *fence;
   1301    struct pipe_blit_info blit;
   1302 
   1303    if (!dst || !src)
   1304       return;
   1305 
   1306    memset(&blit, 0, sizeof(blit));
   1307    blit.dst.resource = dst->texture;
   1308    blit.dst.box.x = dstx0;
   1309    blit.dst.box.y = dsty0;
   1310    blit.dst.box.width = dstwidth;
   1311    blit.dst.box.height = dstheight;
   1312    blit.dst.box.depth = 1;
   1313    blit.dst.format = dst->texture->format;
   1314    blit.src.resource = src->texture;
   1315    blit.src.box.x = srcx0;
   1316    blit.src.box.y = srcy0;
   1317    blit.src.box.width = srcwidth;
   1318    blit.src.box.height = srcheight;
   1319    blit.src.box.depth = 1;
   1320    blit.src.format = src->texture->format;
   1321    blit.mask = PIPE_MASK_RGBA;
   1322    blit.filter = PIPE_TEX_FILTER_NEAREST;
   1323 
   1324    pipe->blit(pipe, &blit);
   1325 
   1326    if (flush_flag == __BLIT_FLAG_FLUSH) {
   1327       pipe->flush_resource(pipe, dst->texture);
   1328       ctx->st->flush(ctx->st, 0, NULL);
   1329    } else if (flush_flag == __BLIT_FLAG_FINISH) {
   1330       screen = dri_screen(ctx->sPriv)->base.screen;
   1331       pipe->flush_resource(pipe, dst->texture);
   1332       ctx->st->flush(ctx->st, 0, &fence);
   1333       (void) screen->fence_finish(screen, NULL, fence, PIPE_TIMEOUT_INFINITE);
   1334       screen->fence_reference(screen, &fence, NULL);
   1335    }
   1336 }
   1337 
   1338 static void *
   1339 dri2_map_image(__DRIcontext *context, __DRIimage *image,
   1340                 int x0, int y0, int width, int height,
   1341                 unsigned int flags, int *stride, void **data)
   1342 {
   1343    struct dri_context *ctx = dri_context(context);
   1344    struct pipe_context *pipe = ctx->st->pipe;
   1345    enum pipe_transfer_usage pipe_access = 0;
   1346    struct pipe_transfer *trans;
   1347    void *map;
   1348 
   1349    if (!image || !data || *data)
   1350       return NULL;
   1351 
   1352    if (flags & __DRI_IMAGE_TRANSFER_READ)
   1353          pipe_access |= PIPE_TRANSFER_READ;
   1354    if (flags & __DRI_IMAGE_TRANSFER_WRITE)
   1355          pipe_access |= PIPE_TRANSFER_WRITE;
   1356 
   1357    map = pipe_transfer_map(pipe, image->texture,
   1358                            0, 0, pipe_access, x0, y0, width, height,
   1359                            &trans);
   1360    if (map) {
   1361       *data = trans;
   1362       *stride = trans->stride;
   1363    }
   1364 
   1365    return map;
   1366 }
   1367 
   1368 static void
   1369 dri2_unmap_image(__DRIcontext *context, __DRIimage *image, void *data)
   1370 {
   1371    struct dri_context *ctx = dri_context(context);
   1372    struct pipe_context *pipe = ctx->st->pipe;
   1373 
   1374    pipe_transfer_unmap(pipe, (struct pipe_transfer *)data);
   1375 }
   1376 
   1377 static void
   1378 dri2_destroy_image(__DRIimage *img)
   1379 {
   1380    pipe_resource_reference(&img->texture, NULL);
   1381    FREE(img);
   1382 }
   1383 
   1384 static int
   1385 dri2_get_capabilities(__DRIscreen *_screen)
   1386 {
   1387    struct dri_screen *screen = dri_screen(_screen);
   1388 
   1389    return (screen->can_share_buffer ? __DRI_IMAGE_CAP_GLOBAL_NAMES : 0);
   1390 }
   1391 
   1392 /* The extension is modified during runtime if DRI_PRIME is detected */
   1393 static __DRIimageExtension dri2ImageExtension = {
   1394     .base = { __DRI_IMAGE, 12 },
   1395 
   1396     .createImageFromName          = dri2_create_image_from_name,
   1397     .createImageFromRenderbuffer  = dri2_create_image_from_renderbuffer,
   1398     .destroyImage                 = dri2_destroy_image,
   1399     .createImage                  = dri2_create_image,
   1400     .queryImage                   = dri2_query_image,
   1401     .dupImage                     = dri2_dup_image,
   1402     .validateUsage                = dri2_validate_usage,
   1403     .createImageFromNames         = dri2_from_names,
   1404     .fromPlanar                   = dri2_from_planar,
   1405     .createImageFromTexture       = dri2_create_from_texture,
   1406     .createImageFromFds           = NULL,
   1407     .createImageFromDmaBufs       = NULL,
   1408     .blitImage                    = dri2_blit_image,
   1409     .getCapabilities              = dri2_get_capabilities,
   1410     .mapImage                     = dri2_map_image,
   1411     .unmapImage                   = dri2_unmap_image,
   1412 };
   1413 
   1414 
   1415 static bool
   1416 dri2_is_opencl_interop_loaded_locked(struct dri_screen *screen)
   1417 {
   1418    return screen->opencl_dri_event_add_ref &&
   1419           screen->opencl_dri_event_release &&
   1420           screen->opencl_dri_event_wait &&
   1421           screen->opencl_dri_event_get_fence;
   1422 }
   1423 
   1424 static bool
   1425 dri2_load_opencl_interop(struct dri_screen *screen)
   1426 {
   1427 #if defined(RTLD_DEFAULT)
   1428    bool success;
   1429 
   1430    pipe_mutex_lock(screen->opencl_func_mutex);
   1431 
   1432    if (dri2_is_opencl_interop_loaded_locked(screen)) {
   1433       pipe_mutex_unlock(screen->opencl_func_mutex);
   1434       return true;
   1435    }
   1436 
   1437    screen->opencl_dri_event_add_ref =
   1438       dlsym(RTLD_DEFAULT, "opencl_dri_event_add_ref");
   1439    screen->opencl_dri_event_release =
   1440       dlsym(RTLD_DEFAULT, "opencl_dri_event_release");
   1441    screen->opencl_dri_event_wait =
   1442       dlsym(RTLD_DEFAULT, "opencl_dri_event_wait");
   1443    screen->opencl_dri_event_get_fence =
   1444       dlsym(RTLD_DEFAULT, "opencl_dri_event_get_fence");
   1445 
   1446    success = dri2_is_opencl_interop_loaded_locked(screen);
   1447    pipe_mutex_unlock(screen->opencl_func_mutex);
   1448    return success;
   1449 #else
   1450    return false;
   1451 #endif
   1452 }
   1453 
   1454 struct dri2_fence {
   1455    struct dri_screen *driscreen;
   1456    struct pipe_fence_handle *pipe_fence;
   1457    void *cl_event;
   1458 };
   1459 
   1460 static unsigned dri2_fence_get_caps(__DRIscreen *_screen)
   1461 {
   1462    struct dri_screen *driscreen = dri_screen(_screen);
   1463    struct pipe_screen *screen = driscreen->base.screen;
   1464    unsigned caps = 0;
   1465 
   1466    if (screen->get_param(screen, PIPE_CAP_NATIVE_FENCE_FD))
   1467       caps |= __DRI_FENCE_CAP_NATIVE_FD;
   1468 
   1469    return caps;
   1470 }
   1471 
   1472 static void *
   1473 dri2_create_fence(__DRIcontext *_ctx)
   1474 {
   1475    struct pipe_context *ctx = dri_context(_ctx)->st->pipe;
   1476    struct dri2_fence *fence = CALLOC_STRUCT(dri2_fence);
   1477 
   1478    if (!fence)
   1479       return NULL;
   1480 
   1481    ctx->flush(ctx, &fence->pipe_fence, 0);
   1482 
   1483    if (!fence->pipe_fence) {
   1484       FREE(fence);
   1485       return NULL;
   1486    }
   1487 
   1488    fence->driscreen = dri_screen(_ctx->driScreenPriv);
   1489    return fence;
   1490 }
   1491 
   1492 static void *
   1493 dri2_create_fence_fd(__DRIcontext *_ctx, int fd)
   1494 {
   1495    struct pipe_context *ctx = dri_context(_ctx)->st->pipe;
   1496    struct dri2_fence *fence = CALLOC_STRUCT(dri2_fence);
   1497 
   1498    if (fd == -1) {
   1499       /* exporting driver created fence, flush: */
   1500       ctx->flush(ctx, &fence->pipe_fence,
   1501                  PIPE_FLUSH_DEFERRED | PIPE_FLUSH_FENCE_FD);
   1502    } else {
   1503       /* importing a foreign fence fd: */
   1504       ctx->create_fence_fd(ctx, &fence->pipe_fence, fd);
   1505    }
   1506    if (!fence->pipe_fence) {
   1507       FREE(fence);
   1508       return NULL;
   1509    }
   1510 
   1511    fence->driscreen = dri_screen(_ctx->driScreenPriv);
   1512    return fence;
   1513 }
   1514 
   1515 static int
   1516 dri2_get_fence_fd(__DRIscreen *_screen, void *_fence)
   1517 {
   1518    struct dri_screen *driscreen = dri_screen(_screen);
   1519    struct pipe_screen *screen = driscreen->base.screen;
   1520    struct dri2_fence *fence = (struct dri2_fence*)_fence;
   1521 
   1522    return screen->fence_get_fd(screen, fence->pipe_fence);
   1523 }
   1524 
   1525 static void *
   1526 dri2_get_fence_from_cl_event(__DRIscreen *_screen, intptr_t cl_event)
   1527 {
   1528    struct dri_screen *driscreen = dri_screen(_screen);
   1529    struct dri2_fence *fence;
   1530 
   1531    if (!dri2_load_opencl_interop(driscreen))
   1532       return NULL;
   1533 
   1534    fence = CALLOC_STRUCT(dri2_fence);
   1535    if (!fence)
   1536       return NULL;
   1537 
   1538    fence->cl_event = (void*)cl_event;
   1539 
   1540    if (!driscreen->opencl_dri_event_add_ref(fence->cl_event)) {
   1541       free(fence);
   1542       return NULL;
   1543    }
   1544 
   1545    fence->driscreen = driscreen;
   1546    return fence;
   1547 }
   1548 
   1549 static void
   1550 dri2_destroy_fence(__DRIscreen *_screen, void *_fence)
   1551 {
   1552    struct dri_screen *driscreen = dri_screen(_screen);
   1553    struct pipe_screen *screen = driscreen->base.screen;
   1554    struct dri2_fence *fence = (struct dri2_fence*)_fence;
   1555 
   1556    if (fence->pipe_fence)
   1557       screen->fence_reference(screen, &fence->pipe_fence, NULL);
   1558    else if (fence->cl_event)
   1559       driscreen->opencl_dri_event_release(fence->cl_event);
   1560    else
   1561       assert(0);
   1562 
   1563    FREE(fence);
   1564 }
   1565 
   1566 static GLboolean
   1567 dri2_client_wait_sync(__DRIcontext *_ctx, void *_fence, unsigned flags,
   1568                       uint64_t timeout)
   1569 {
   1570    struct dri2_fence *fence = (struct dri2_fence*)_fence;
   1571    struct dri_screen *driscreen = fence->driscreen;
   1572    struct pipe_screen *screen = driscreen->base.screen;
   1573 
   1574    /* No need to flush. The context was flushed when the fence was created. */
   1575 
   1576    if (fence->pipe_fence)
   1577       return screen->fence_finish(screen, NULL, fence->pipe_fence, timeout);
   1578    else if (fence->cl_event) {
   1579       struct pipe_fence_handle *pipe_fence =
   1580          driscreen->opencl_dri_event_get_fence(fence->cl_event);
   1581 
   1582       if (pipe_fence)
   1583          return screen->fence_finish(screen, NULL, pipe_fence, timeout);
   1584       else
   1585          return driscreen->opencl_dri_event_wait(fence->cl_event, timeout);
   1586    }
   1587    else {
   1588       assert(0);
   1589       return false;
   1590    }
   1591 }
   1592 
   1593 static void
   1594 dri2_server_wait_sync(__DRIcontext *_ctx, void *_fence, unsigned flags)
   1595 {
   1596    struct pipe_context *ctx = dri_context(_ctx)->st->pipe;
   1597    struct dri2_fence *fence = (struct dri2_fence*)_fence;
   1598 
   1599    if (ctx->fence_server_sync)
   1600       ctx->fence_server_sync(ctx, fence->pipe_fence);
   1601 }
   1602 
   1603 static __DRI2fenceExtension dri2FenceExtension = {
   1604    .base = { __DRI2_FENCE, 2 },
   1605 
   1606    .create_fence = dri2_create_fence,
   1607    .get_fence_from_cl_event = dri2_get_fence_from_cl_event,
   1608    .destroy_fence = dri2_destroy_fence,
   1609    .client_wait_sync = dri2_client_wait_sync,
   1610    .server_wait_sync = dri2_server_wait_sync,
   1611    .get_capabilities = dri2_fence_get_caps,
   1612    .create_fence_fd = dri2_create_fence_fd,
   1613    .get_fence_fd = dri2_get_fence_fd,
   1614 };
   1615 
   1616 static const __DRIrobustnessExtension dri2Robustness = {
   1617    .base = { __DRI2_ROBUSTNESS, 1 }
   1618 };
   1619 
   1620 static int
   1621 dri2_interop_query_device_info(__DRIcontext *_ctx,
   1622                                struct mesa_glinterop_device_info *out)
   1623 {
   1624    struct pipe_screen *screen = dri_context(_ctx)->st->pipe->screen;
   1625 
   1626    /* There is no version 0, thus we do not support it */
   1627    if (out->version == 0)
   1628       return MESA_GLINTEROP_INVALID_VERSION;
   1629 
   1630    out->pci_segment_group = screen->get_param(screen, PIPE_CAP_PCI_GROUP);
   1631    out->pci_bus = screen->get_param(screen, PIPE_CAP_PCI_BUS);
   1632    out->pci_device = screen->get_param(screen, PIPE_CAP_PCI_DEVICE);
   1633    out->pci_function = screen->get_param(screen, PIPE_CAP_PCI_FUNCTION);
   1634 
   1635    out->vendor_id = screen->get_param(screen, PIPE_CAP_VENDOR_ID);
   1636    out->device_id = screen->get_param(screen, PIPE_CAP_DEVICE_ID);
   1637 
   1638    /* Instruct the caller that we support up-to version one of the interface */
   1639    out->version = 1;
   1640 
   1641    return MESA_GLINTEROP_SUCCESS;
   1642 }
   1643 
   1644 static int
   1645 dri2_interop_export_object(__DRIcontext *_ctx,
   1646                            struct mesa_glinterop_export_in *in,
   1647                            struct mesa_glinterop_export_out *out)
   1648 {
   1649    struct st_context_iface *st = dri_context(_ctx)->st;
   1650    struct pipe_screen *screen = st->pipe->screen;
   1651    struct gl_context *ctx = ((struct st_context *)st)->ctx;
   1652    struct pipe_resource *res = NULL;
   1653    struct winsys_handle whandle;
   1654    unsigned target, usage;
   1655    boolean success;
   1656 
   1657    /* There is no version 0, thus we do not support it */
   1658    if (in->version == 0 || out->version == 0)
   1659       return MESA_GLINTEROP_INVALID_VERSION;
   1660 
   1661    /* Validate the target. */
   1662    switch (in->target) {
   1663    case GL_TEXTURE_BUFFER:
   1664    case GL_TEXTURE_1D:
   1665    case GL_TEXTURE_2D:
   1666    case GL_TEXTURE_3D:
   1667    case GL_TEXTURE_RECTANGLE:
   1668    case GL_TEXTURE_1D_ARRAY:
   1669    case GL_TEXTURE_2D_ARRAY:
   1670    case GL_TEXTURE_CUBE_MAP_ARRAY:
   1671    case GL_TEXTURE_CUBE_MAP:
   1672    case GL_TEXTURE_2D_MULTISAMPLE:
   1673    case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
   1674    case GL_TEXTURE_EXTERNAL_OES:
   1675    case GL_RENDERBUFFER:
   1676    case GL_ARRAY_BUFFER:
   1677       target = in->target;
   1678       break;
   1679    case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
   1680    case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
   1681    case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
   1682    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
   1683    case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
   1684    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
   1685       target = GL_TEXTURE_CUBE_MAP;
   1686       break;
   1687    default:
   1688       return MESA_GLINTEROP_INVALID_TARGET;
   1689    }
   1690 
   1691    /* Validate the simple case of miplevel. */
   1692    if ((target == GL_RENDERBUFFER || target == GL_ARRAY_BUFFER) &&
   1693        in->miplevel != 0)
   1694       return MESA_GLINTEROP_INVALID_MIP_LEVEL;
   1695 
   1696    /* Validate the OpenGL object and get pipe_resource. */
   1697    mtx_lock(&ctx->Shared->Mutex);
   1698 
   1699    if (target == GL_ARRAY_BUFFER) {
   1700       /* Buffer objects.
   1701        *
   1702        * The error checking is based on the documentation of
   1703        * clCreateFromGLBuffer from OpenCL 2.0 SDK.
   1704        */
   1705       struct gl_buffer_object *buf = _mesa_lookup_bufferobj(ctx, in->obj);
   1706 
   1707       /* From OpenCL 2.0 SDK, clCreateFromGLBuffer:
   1708        *  "CL_INVALID_GL_OBJECT if bufobj is not a GL buffer object or is
   1709        *   a GL buffer object but does not have an existing data store or
   1710        *   the size of the buffer is 0."
   1711        */
   1712       if (!buf || buf->Size == 0) {
   1713          mtx_unlock(&ctx->Shared->Mutex);
   1714          return MESA_GLINTEROP_INVALID_OBJECT;
   1715       }
   1716 
   1717       res = st_buffer_object(buf)->buffer;
   1718       if (!res) {
   1719          /* this shouldn't happen */
   1720          mtx_unlock(&ctx->Shared->Mutex);
   1721          return MESA_GLINTEROP_INVALID_OBJECT;
   1722       }
   1723 
   1724       out->buf_offset = 0;
   1725       out->buf_size = buf->Size;
   1726 
   1727       buf->UsageHistory |= USAGE_DISABLE_MINMAX_CACHE;
   1728    } else if (target == GL_RENDERBUFFER) {
   1729       /* Renderbuffers.
   1730        *
   1731        * The error checking is based on the documentation of
   1732        * clCreateFromGLRenderbuffer from OpenCL 2.0 SDK.
   1733        */
   1734       struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, in->obj);
   1735 
   1736       /* From OpenCL 2.0 SDK, clCreateFromGLRenderbuffer:
   1737        *   "CL_INVALID_GL_OBJECT if renderbuffer is not a GL renderbuffer
   1738        *    object or if the width or height of renderbuffer is zero."
   1739        */
   1740       if (!rb || rb->Width == 0 || rb->Height == 0) {
   1741          mtx_unlock(&ctx->Shared->Mutex);
   1742          return MESA_GLINTEROP_INVALID_OBJECT;
   1743       }
   1744 
   1745       /* From OpenCL 2.0 SDK, clCreateFromGLRenderbuffer:
   1746        *   "CL_INVALID_OPERATION if renderbuffer is a multi-sample GL
   1747        *    renderbuffer object."
   1748        */
   1749       if (rb->NumSamples > 1) {
   1750          mtx_unlock(&ctx->Shared->Mutex);
   1751          return MESA_GLINTEROP_INVALID_OPERATION;
   1752       }
   1753 
   1754       /* From OpenCL 2.0 SDK, clCreateFromGLRenderbuffer:
   1755        *   "CL_OUT_OF_RESOURCES if there is a failure to allocate resources
   1756        *    required by the OpenCL implementation on the device."
   1757        */
   1758       res = st_renderbuffer(rb)->texture;
   1759       if (!res) {
   1760          mtx_unlock(&ctx->Shared->Mutex);
   1761          return MESA_GLINTEROP_OUT_OF_RESOURCES;
   1762       }
   1763 
   1764       out->internal_format = rb->InternalFormat;
   1765       out->view_minlevel = 0;
   1766       out->view_numlevels = 1;
   1767       out->view_minlayer = 0;
   1768       out->view_numlayers = 1;
   1769    } else {
   1770       /* Texture objects.
   1771        *
   1772        * The error checking is based on the documentation of
   1773        * clCreateFromGLTexture from OpenCL 2.0 SDK.
   1774        */
   1775       struct gl_texture_object *obj = _mesa_lookup_texture(ctx, in->obj);
   1776 
   1777       if (obj)
   1778          _mesa_test_texobj_completeness(ctx, obj);
   1779 
   1780       /* From OpenCL 2.0 SDK, clCreateFromGLTexture:
   1781        *   "CL_INVALID_GL_OBJECT if texture is not a GL texture object whose
   1782        *    type matches texture_target, if the specified miplevel of texture
   1783        *    is not defined, or if the width or height of the specified
   1784        *    miplevel is zero or if the GL texture object is incomplete."
   1785        */
   1786       if (!obj ||
   1787           obj->Target != target ||
   1788           !obj->_BaseComplete ||
   1789           (in->miplevel > 0 && !obj->_MipmapComplete)) {
   1790          mtx_unlock(&ctx->Shared->Mutex);
   1791          return MESA_GLINTEROP_INVALID_OBJECT;
   1792       }
   1793 
   1794       /* From OpenCL 2.0 SDK, clCreateFromGLTexture:
   1795        *   "CL_INVALID_MIP_LEVEL if miplevel is less than the value of
   1796        *    levelbase (for OpenGL implementations) or zero (for OpenGL ES
   1797        *    implementations); or greater than the value of q (for both OpenGL
   1798        *    and OpenGL ES). levelbase and q are defined for the texture in
   1799        *    section 3.8.10 (Texture Completeness) of the OpenGL 2.1
   1800        *    specification and section 3.7.10 of the OpenGL ES 2.0."
   1801        */
   1802       if (in->miplevel < obj->BaseLevel || in->miplevel > obj->_MaxLevel) {
   1803          mtx_unlock(&ctx->Shared->Mutex);
   1804          return MESA_GLINTEROP_INVALID_MIP_LEVEL;
   1805       }
   1806 
   1807       if (!st_finalize_texture(ctx, st->pipe, obj, 0)) {
   1808          mtx_unlock(&ctx->Shared->Mutex);
   1809          return MESA_GLINTEROP_OUT_OF_RESOURCES;
   1810       }
   1811 
   1812       res = st_get_texobj_resource(obj);
   1813       if (!res) {
   1814          /* Incomplete texture buffer object? This shouldn't really occur. */
   1815          mtx_unlock(&ctx->Shared->Mutex);
   1816          return MESA_GLINTEROP_INVALID_OBJECT;
   1817       }
   1818 
   1819       if (target == GL_TEXTURE_BUFFER) {
   1820          out->internal_format = obj->BufferObjectFormat;
   1821          out->buf_offset = obj->BufferOffset;
   1822          out->buf_size = obj->BufferSize == -1 ? obj->BufferObject->Size :
   1823                                                  obj->BufferSize;
   1824 
   1825          obj->BufferObject->UsageHistory |= USAGE_DISABLE_MINMAX_CACHE;
   1826       } else {
   1827          out->internal_format = obj->Image[0][0]->InternalFormat;
   1828          out->view_minlevel = obj->MinLevel;
   1829          out->view_numlevels = obj->NumLevels;
   1830          out->view_minlayer = obj->MinLayer;
   1831          out->view_numlayers = obj->NumLayers;
   1832       }
   1833    }
   1834 
   1835    /* Get the handle. */
   1836    switch (in->access) {
   1837    case MESA_GLINTEROP_ACCESS_READ_WRITE:
   1838       usage = PIPE_HANDLE_USAGE_READ_WRITE;
   1839       break;
   1840    case MESA_GLINTEROP_ACCESS_READ_ONLY:
   1841       usage = PIPE_HANDLE_USAGE_READ;
   1842       break;
   1843    case MESA_GLINTEROP_ACCESS_WRITE_ONLY:
   1844       usage = PIPE_HANDLE_USAGE_WRITE;
   1845       break;
   1846    default:
   1847       usage = 0;
   1848    }
   1849 
   1850    memset(&whandle, 0, sizeof(whandle));
   1851    whandle.type = DRM_API_HANDLE_TYPE_FD;
   1852 
   1853    success = screen->resource_get_handle(screen, st->pipe, res, &whandle,
   1854                                          usage);
   1855    mtx_unlock(&ctx->Shared->Mutex);
   1856 
   1857    if (!success)
   1858       return MESA_GLINTEROP_OUT_OF_HOST_MEMORY;
   1859 
   1860    out->dmabuf_fd = whandle.handle;
   1861    out->out_driver_data_written = 0;
   1862 
   1863    if (res->target == PIPE_BUFFER)
   1864       out->buf_offset += whandle.offset;
   1865 
   1866    /* Instruct the caller that we support up-to version one of the interface */
   1867    in->version = 1;
   1868    out->version = 1;
   1869 
   1870    return MESA_GLINTEROP_SUCCESS;
   1871 }
   1872 
   1873 static const __DRI2interopExtension dri2InteropExtension = {
   1874    .base = { __DRI2_INTEROP, 1 },
   1875    .query_device_info = dri2_interop_query_device_info,
   1876    .export_object = dri2_interop_export_object
   1877 };
   1878 
   1879 /*
   1880  * Backend function init_screen.
   1881  */
   1882 
   1883 static const __DRIextension *dri_screen_extensions[] = {
   1884    &driTexBufferExtension.base,
   1885    &dri2FlushExtension.base,
   1886    &dri2ImageExtension.base,
   1887    &dri2RendererQueryExtension.base,
   1888    &dri2ConfigQueryExtension.base,
   1889    &dri2ThrottleExtension.base,
   1890    &dri2FenceExtension.base,
   1891    &dri2InteropExtension.base,
   1892    NULL
   1893 };
   1894 
   1895 static const __DRIextension *dri_robust_screen_extensions[] = {
   1896    &driTexBufferExtension.base,
   1897    &dri2FlushExtension.base,
   1898    &dri2ImageExtension.base,
   1899    &dri2RendererQueryExtension.base,
   1900    &dri2ConfigQueryExtension.base,
   1901    &dri2ThrottleExtension.base,
   1902    &dri2FenceExtension.base,
   1903    &dri2InteropExtension.base,
   1904    &dri2Robustness.base,
   1905    NULL
   1906 };
   1907 
   1908 /**
   1909  * This is the driver specific part of the createNewScreen entry point.
   1910  *
   1911  * Returns the struct gl_config supported by this driver.
   1912  */
   1913 static const __DRIconfig **
   1914 dri2_init_screen(__DRIscreen * sPriv)
   1915 {
   1916    const __DRIconfig **configs;
   1917    struct dri_screen *screen;
   1918    struct pipe_screen *pscreen = NULL;
   1919    const struct drm_conf_ret *throttle_ret;
   1920    const struct drm_conf_ret *dmabuf_ret;
   1921    int fd;
   1922 
   1923    screen = CALLOC_STRUCT(dri_screen);
   1924    if (!screen)
   1925       return NULL;
   1926 
   1927    screen->sPriv = sPriv;
   1928    screen->fd = sPriv->fd;
   1929    pipe_mutex_init(screen->opencl_func_mutex);
   1930 
   1931    sPriv->driverPrivate = (void *)screen;
   1932 
   1933    if (screen->fd < 0 || (fd = fcntl(screen->fd, F_DUPFD_CLOEXEC, 3)) < 0)
   1934       goto free_screen;
   1935 
   1936    if (pipe_loader_drm_probe_fd(&screen->dev, fd))
   1937       pscreen = pipe_loader_create_screen(screen->dev);
   1938 
   1939    if (!pscreen)
   1940        goto release_pipe;
   1941 
   1942    throttle_ret = pipe_loader_configuration(screen->dev, DRM_CONF_THROTTLE);
   1943    dmabuf_ret = pipe_loader_configuration(screen->dev, DRM_CONF_SHARE_FD);
   1944 
   1945    if (throttle_ret && throttle_ret->val.val_int != -1) {
   1946       screen->throttling_enabled = TRUE;
   1947       screen->default_throttle_frames = throttle_ret->val.val_int;
   1948    }
   1949 
   1950    if (dmabuf_ret && dmabuf_ret->val.val_bool) {
   1951       uint64_t cap;
   1952 
   1953       if (drmGetCap(sPriv->fd, DRM_CAP_PRIME, &cap) == 0 &&
   1954           (cap & DRM_PRIME_CAP_IMPORT)) {
   1955          dri2ImageExtension.createImageFromFds = dri2_from_fds;
   1956          dri2ImageExtension.createImageFromDmaBufs = dri2_from_dma_bufs;
   1957       }
   1958    }
   1959 
   1960    if (pscreen->get_param(pscreen, PIPE_CAP_DEVICE_RESET_STATUS_QUERY)) {
   1961       sPriv->extensions = dri_robust_screen_extensions;
   1962       screen->has_reset_status_query = true;
   1963    }
   1964    else
   1965       sPriv->extensions = dri_screen_extensions;
   1966 
   1967    configs = dri_init_screen_helper(screen, pscreen, screen->dev->driver_name);
   1968    if (!configs)
   1969       goto destroy_screen;
   1970 
   1971    screen->can_share_buffer = true;
   1972    screen->auto_fake_front = dri_with_format(sPriv);
   1973    screen->broken_invalidate = !sPriv->dri2.useInvalidate;
   1974    screen->lookup_egl_image = dri2_lookup_egl_image;
   1975 
   1976    return configs;
   1977 
   1978 destroy_screen:
   1979    dri_destroy_screen_helper(screen);
   1980 
   1981 release_pipe:
   1982    if (screen->dev)
   1983       pipe_loader_release(&screen->dev, 1);
   1984    else
   1985       close(fd);
   1986 
   1987 free_screen:
   1988    FREE(screen);
   1989    return NULL;
   1990 }
   1991 
   1992 /**
   1993  * This is the driver specific part of the createNewScreen entry point.
   1994  *
   1995  * Returns the struct gl_config supported by this driver.
   1996  */
   1997 static const __DRIconfig **
   1998 dri_kms_init_screen(__DRIscreen * sPriv)
   1999 {
   2000 #if defined(GALLIUM_SOFTPIPE)
   2001    const __DRIconfig **configs;
   2002    struct dri_screen *screen;
   2003    struct pipe_screen *pscreen = NULL;
   2004    uint64_t cap;
   2005    int fd;
   2006 
   2007    screen = CALLOC_STRUCT(dri_screen);
   2008    if (!screen)
   2009       return NULL;
   2010 
   2011    screen->sPriv = sPriv;
   2012    screen->fd = sPriv->fd;
   2013 
   2014    sPriv->driverPrivate = (void *)screen;
   2015 
   2016    if (screen->fd < 0 || (fd = fcntl(screen->fd, F_DUPFD_CLOEXEC, 3)) < 0)
   2017       goto free_screen;
   2018 
   2019    if (pipe_loader_sw_probe_kms(&screen->dev, fd))
   2020       pscreen = pipe_loader_create_screen(screen->dev);
   2021 
   2022    if (!pscreen)
   2023        goto release_pipe;
   2024 
   2025    if (drmGetCap(sPriv->fd, DRM_CAP_PRIME, &cap) == 0 &&
   2026           (cap & DRM_PRIME_CAP_IMPORT)) {
   2027       dri2ImageExtension.createImageFromFds = dri2_from_fds;
   2028       dri2ImageExtension.createImageFromDmaBufs = dri2_from_dma_bufs;
   2029    }
   2030 
   2031    sPriv->extensions = dri_screen_extensions;
   2032 
   2033    configs = dri_init_screen_helper(screen, pscreen, "swrast");
   2034    if (!configs)
   2035       goto destroy_screen;
   2036 
   2037    screen->can_share_buffer = false;
   2038    screen->auto_fake_front = dri_with_format(sPriv);
   2039    screen->broken_invalidate = !sPriv->dri2.useInvalidate;
   2040    screen->lookup_egl_image = dri2_lookup_egl_image;
   2041 
   2042    return configs;
   2043 
   2044 destroy_screen:
   2045    dri_destroy_screen_helper(screen);
   2046 
   2047 release_pipe:
   2048    if (screen->dev)
   2049       pipe_loader_release(&screen->dev, 1);
   2050    else
   2051       close(fd);
   2052 
   2053 free_screen:
   2054    FREE(screen);
   2055 #endif // GALLIUM_SOFTPIPE
   2056    return NULL;
   2057 }
   2058 
   2059 static boolean
   2060 dri2_create_buffer(__DRIscreen * sPriv,
   2061                    __DRIdrawable * dPriv,
   2062                    const struct gl_config * visual, boolean isPixmap)
   2063 {
   2064    struct dri_drawable *drawable = NULL;
   2065 
   2066    if (!dri_create_buffer(sPriv, dPriv, visual, isPixmap))
   2067       return FALSE;
   2068 
   2069    drawable = dPriv->driverPrivate;
   2070 
   2071    drawable->allocate_textures = dri2_allocate_textures;
   2072    drawable->flush_frontbuffer = dri2_flush_frontbuffer;
   2073    drawable->update_tex_buffer = dri2_update_tex_buffer;
   2074 
   2075    return TRUE;
   2076 }
   2077 
   2078 /**
   2079  * DRI driver virtual function table.
   2080  *
   2081  * DRI versions differ in their implementation of init_screen and swap_buffers.
   2082  */
   2083 const struct __DriverAPIRec galliumdrm_driver_api = {
   2084    .InitScreen = dri2_init_screen,
   2085    .DestroyScreen = dri_destroy_screen,
   2086    .CreateContext = dri_create_context,
   2087    .DestroyContext = dri_destroy_context,
   2088    .CreateBuffer = dri2_create_buffer,
   2089    .DestroyBuffer = dri_destroy_buffer,
   2090    .MakeCurrent = dri_make_current,
   2091    .UnbindContext = dri_unbind_context,
   2092 
   2093    .AllocateBuffer = dri2_allocate_buffer,
   2094    .ReleaseBuffer  = dri2_release_buffer,
   2095 };
   2096 
   2097 /**
   2098  * DRI driver virtual function table.
   2099  *
   2100  * KMS/DRM version of the DriverAPI above sporting a different InitScreen
   2101  * hook. The latter is used to explicitly initialise the kms_swrast driver
   2102  * rather than selecting the approapriate driver as suggested by the loader.
   2103  */
   2104 const struct __DriverAPIRec dri_kms_driver_api = {
   2105    .InitScreen = dri_kms_init_screen,
   2106    .DestroyScreen = dri_destroy_screen,
   2107    .CreateContext = dri_create_context,
   2108    .DestroyContext = dri_destroy_context,
   2109    .CreateBuffer = dri2_create_buffer,
   2110    .DestroyBuffer = dri_destroy_buffer,
   2111    .MakeCurrent = dri_make_current,
   2112    .UnbindContext = dri_unbind_context,
   2113 
   2114    .AllocateBuffer = dri2_allocate_buffer,
   2115    .ReleaseBuffer  = dri2_release_buffer,
   2116 };
   2117 
   2118 /* This is the table of extensions that the loader will dlsym() for. */
   2119 const __DRIextension *galliumdrm_driver_extensions[] = {
   2120     &driCoreExtension.base,
   2121     &driImageDriverExtension.base,
   2122     &driDRI2Extension.base,
   2123     &gallium_config_options.base,
   2124     &dri2FenceExtension.base,
   2125     NULL
   2126 };
   2127 
   2128 /* vim: set sw=3 ts=8 sts=3 expandtab: */
   2129