Home | History | Annotate | Download | only in drm
      1 /*
      2  * Mesa 3-D graphics library
      3  * Version:  7.9
      4  *
      5  * Copyright 2009, VMware, Inc.
      6  * All Rights Reserved.
      7  * Copyright (C) 2010 LunarG Inc.
      8  *
      9  * Permission is hereby granted, free of charge, to any person obtaining a
     10  * copy of this software and associated documentation files (the "Software"),
     11  * to deal in the Software without restriction, including without limitation
     12  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     13  * and/or sell copies of the Software, and to permit persons to whom the
     14  * Software is furnished to do so, subject to the following conditions:
     15  *
     16  * The above copyright notice and this permission notice shall be included
     17  * in all copies or substantial portions of the Software.
     18  *
     19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     20  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     21  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     22  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     23  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     24  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     25  *
     26  * Authors:
     27  *    Keith Whitwell <keithw (at) vmware.com>
     28  *    Jakob Bornecrantz <wallbraker (at) gmail.com>
     29  *    Chia-I Wu <olv (at) lunarg.com>
     30  */
     31 
     32 #include "util/u_memory.h"
     33 #include "util/u_inlines.h"
     34 #include "util/u_format.h"
     35 #include "util/u_debug.h"
     36 #include "state_tracker/drm_driver.h"
     37 
     38 #include "dri_screen.h"
     39 #include "dri_context.h"
     40 #include "dri_drawable.h"
     41 #include "dri2_buffer.h"
     42 
     43 /**
     44  * DRI2 flush extension.
     45  */
     46 static void
     47 dri2_flush_drawable(__DRIdrawable *dPriv)
     48 {
     49    struct dri_context *ctx = dri_get_current(dPriv->driScreenPriv);
     50    struct dri_drawable *drawable = dri_drawable(dPriv);
     51 
     52    struct pipe_resource *ptex = drawable->textures[ST_ATTACHMENT_BACK_LEFT];
     53 
     54    if (ctx) {
     55       if (ptex && ctx->pp && drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL])
     56          pp_run(ctx->pp, ptex, ptex, drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]);
     57 
     58       ctx->st->flush(ctx->st, 0, NULL);
     59    }
     60 }
     61 
     62 static void
     63 dri2_invalidate_drawable(__DRIdrawable *dPriv)
     64 {
     65    struct dri_drawable *drawable = dri_drawable(dPriv);
     66 
     67    dri2InvalidateDrawable(dPriv);
     68    drawable->dPriv->lastStamp = drawable->dPriv->dri2.stamp;
     69 
     70    p_atomic_inc(&drawable->base.stamp);
     71 }
     72 
     73 static const __DRI2flushExtension dri2FlushExtension = {
     74     { __DRI2_FLUSH, __DRI2_FLUSH_VERSION },
     75     dri2_flush_drawable,
     76     dri2_invalidate_drawable,
     77 };
     78 
     79 /**
     80  * Retrieve __DRIbuffer from the DRI loader.
     81  */
     82 static __DRIbuffer *
     83 dri2_drawable_get_buffers(struct dri_drawable *drawable,
     84                           const enum st_attachment_type *statts,
     85                           unsigned *count)
     86 {
     87    __DRIdrawable *dri_drawable = drawable->dPriv;
     88    struct __DRIdri2LoaderExtensionRec *loader = drawable->sPriv->dri2.loader;
     89    boolean with_format;
     90    __DRIbuffer *buffers;
     91    int num_buffers;
     92    unsigned attachments[10];
     93    unsigned num_attachments, i;
     94 
     95    assert(loader);
     96    with_format = dri_with_format(drawable->sPriv);
     97 
     98    num_attachments = 0;
     99 
    100    /* for Xserver 1.6.0 (DRI2 version 1) we always need to ask for the front */
    101    if (!with_format)
    102       attachments[num_attachments++] = __DRI_BUFFER_FRONT_LEFT;
    103 
    104    for (i = 0; i < *count; i++) {
    105       enum pipe_format format;
    106       unsigned bind;
    107       int att, depth;
    108 
    109       dri_drawable_get_format(drawable, statts[i], &format, &bind);
    110       if (format == PIPE_FORMAT_NONE)
    111          continue;
    112 
    113       switch (statts[i]) {
    114       case ST_ATTACHMENT_FRONT_LEFT:
    115          /* already added */
    116          if (!with_format)
    117             continue;
    118          att = __DRI_BUFFER_FRONT_LEFT;
    119          break;
    120       case ST_ATTACHMENT_BACK_LEFT:
    121          att = __DRI_BUFFER_BACK_LEFT;
    122          break;
    123       case ST_ATTACHMENT_FRONT_RIGHT:
    124          att = __DRI_BUFFER_FRONT_RIGHT;
    125          break;
    126       case ST_ATTACHMENT_BACK_RIGHT:
    127          att = __DRI_BUFFER_BACK_RIGHT;
    128          break;
    129       case ST_ATTACHMENT_DEPTH_STENCIL:
    130          att = __DRI_BUFFER_DEPTH_STENCIL;
    131          break;
    132       default:
    133          att = -1;
    134          break;
    135       }
    136 
    137       /*
    138        * In this switch statement we must support all formats that
    139        * may occur as the stvis->color_format or
    140        * stvis->depth_stencil_format.
    141        */
    142       switch(format) {
    143       case PIPE_FORMAT_B8G8R8A8_UNORM:
    144 	 depth = 32;
    145 	 break;
    146       case PIPE_FORMAT_B8G8R8X8_UNORM:
    147 	 depth = 24;
    148 	 break;
    149       case PIPE_FORMAT_B5G6R5_UNORM:
    150 	 depth = 16;
    151 	 break;
    152       case PIPE_FORMAT_Z16_UNORM:
    153 	 att = __DRI_BUFFER_DEPTH;
    154 	 depth = 16;
    155 	 break;
    156       case PIPE_FORMAT_Z24X8_UNORM:
    157       case PIPE_FORMAT_X8Z24_UNORM:
    158 	 att = __DRI_BUFFER_DEPTH;
    159 	 depth = 24;
    160 	 break;
    161       case PIPE_FORMAT_Z24_UNORM_S8_UINT:
    162       case PIPE_FORMAT_S8_UINT_Z24_UNORM:
    163 	 depth = 32;
    164 	 break;
    165       case PIPE_FORMAT_Z32_UNORM:
    166 	 att = __DRI_BUFFER_DEPTH;
    167 	 depth = 32;
    168 	 break;
    169       default:
    170 	 depth = util_format_get_blocksizebits(format);
    171 	 assert(!"Unexpected format in dri2_drawable_get_buffers()");
    172       }
    173 
    174       if (att >= 0) {
    175          attachments[num_attachments++] = att;
    176          if (with_format) {
    177             attachments[num_attachments++] = depth;
    178          }
    179       }
    180    }
    181 
    182    if (with_format) {
    183       num_attachments /= 2;
    184       buffers = loader->getBuffersWithFormat(dri_drawable,
    185             &dri_drawable->w, &dri_drawable->h,
    186             attachments, num_attachments,
    187             &num_buffers, dri_drawable->loaderPrivate);
    188    }
    189    else {
    190       buffers = loader->getBuffers(dri_drawable,
    191             &dri_drawable->w, &dri_drawable->h,
    192             attachments, num_attachments,
    193             &num_buffers, dri_drawable->loaderPrivate);
    194    }
    195 
    196    if (buffers)
    197       *count = num_buffers;
    198 
    199    return buffers;
    200 }
    201 
    202 /**
    203  * Process __DRIbuffer and convert them into pipe_resources.
    204  */
    205 static void
    206 dri2_drawable_process_buffers(struct dri_drawable *drawable,
    207                               __DRIbuffer *buffers, unsigned count)
    208 {
    209    struct dri_screen *screen = dri_screen(drawable->sPriv);
    210    __DRIdrawable *dri_drawable = drawable->dPriv;
    211    struct pipe_resource templ;
    212    struct winsys_handle whandle;
    213    boolean have_depth = FALSE;
    214    unsigned i, bind;
    215 
    216    if (drawable->old_num == count &&
    217        drawable->old_w == dri_drawable->w &&
    218        drawable->old_h == dri_drawable->h &&
    219        memcmp(drawable->old, buffers, sizeof(__DRIbuffer) * count) == 0)
    220       return;
    221 
    222    for (i = 0; i < ST_ATTACHMENT_COUNT; i++)
    223       pipe_resource_reference(&drawable->textures[i], NULL);
    224 
    225    memset(&templ, 0, sizeof(templ));
    226    templ.target = screen->target;
    227    templ.last_level = 0;
    228    templ.width0 = dri_drawable->w;
    229    templ.height0 = dri_drawable->h;
    230    templ.depth0 = 1;
    231    templ.array_size = 1;
    232 
    233    memset(&whandle, 0, sizeof(whandle));
    234 
    235    for (i = 0; i < count; i++) {
    236       __DRIbuffer *buf = &buffers[i];
    237       enum st_attachment_type statt;
    238       enum pipe_format format;
    239 
    240       switch (buf->attachment) {
    241       case __DRI_BUFFER_FRONT_LEFT:
    242          if (!screen->auto_fake_front) {
    243             statt = ST_ATTACHMENT_INVALID;
    244             break;
    245          }
    246          /* fallthrough */
    247       case __DRI_BUFFER_FAKE_FRONT_LEFT:
    248          statt = ST_ATTACHMENT_FRONT_LEFT;
    249          break;
    250       case __DRI_BUFFER_BACK_LEFT:
    251          statt = ST_ATTACHMENT_BACK_LEFT;
    252          break;
    253       case __DRI_BUFFER_DEPTH:
    254       case __DRI_BUFFER_DEPTH_STENCIL:
    255       case __DRI_BUFFER_STENCIL:
    256          /* use only the first depth/stencil buffer */
    257          if (!have_depth) {
    258             have_depth = TRUE;
    259             statt = ST_ATTACHMENT_DEPTH_STENCIL;
    260          }
    261          else {
    262             statt = ST_ATTACHMENT_INVALID;
    263          }
    264          break;
    265       default:
    266          statt = ST_ATTACHMENT_INVALID;
    267          break;
    268       }
    269 
    270       dri_drawable_get_format(drawable, statt, &format, &bind);
    271       if (statt == ST_ATTACHMENT_INVALID || format == PIPE_FORMAT_NONE)
    272          continue;
    273 
    274       templ.format = format;
    275       templ.bind = bind;
    276       whandle.handle = buf->name;
    277       whandle.stride = buf->pitch;
    278 
    279       drawable->textures[statt] =
    280          screen->base.screen->resource_from_handle(screen->base.screen,
    281                &templ, &whandle);
    282    }
    283 
    284    drawable->old_num = count;
    285    drawable->old_w = dri_drawable->w;
    286    drawable->old_h = dri_drawable->h;
    287    memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * count);
    288 }
    289 
    290 static __DRIbuffer *
    291 dri2_allocate_buffer(__DRIscreen *sPriv,
    292                      unsigned attachment, unsigned format,
    293                      int width, int height)
    294 {
    295    struct dri_screen *screen = dri_screen(sPriv);
    296    struct dri2_buffer *buffer;
    297    struct pipe_resource templ;
    298    enum pipe_format pf;
    299    unsigned bind = 0;
    300    struct winsys_handle whandle;
    301 
    302    switch (attachment) {
    303       case __DRI_BUFFER_FRONT_LEFT:
    304       case __DRI_BUFFER_FAKE_FRONT_LEFT:
    305          bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
    306          break;
    307       case __DRI_BUFFER_BACK_LEFT:
    308          bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
    309          break;
    310       case __DRI_BUFFER_DEPTH:
    311       case __DRI_BUFFER_DEPTH_STENCIL:
    312       case __DRI_BUFFER_STENCIL:
    313             bind = PIPE_BIND_DEPTH_STENCIL; /* XXX sampler? */
    314          break;
    315    }
    316 
    317    /* because we get the handle and stride */
    318    bind |= PIPE_BIND_SHARED;
    319 
    320    switch (format) {
    321       case 32:
    322          pf = PIPE_FORMAT_B8G8R8A8_UNORM;
    323          break;
    324       case 24:
    325          pf = PIPE_FORMAT_B8G8R8X8_UNORM;
    326          break;
    327       case 16:
    328          pf = PIPE_FORMAT_Z16_UNORM;
    329          break;
    330       default:
    331          return NULL;
    332    }
    333 
    334    buffer = CALLOC_STRUCT(dri2_buffer);
    335    if (!buffer)
    336       return NULL;
    337 
    338    memset(&templ, 0, sizeof(templ));
    339    templ.bind = bind;
    340    templ.format = pf;
    341    templ.target = PIPE_TEXTURE_2D;
    342    templ.last_level = 0;
    343    templ.width0 = width;
    344    templ.height0 = height;
    345    templ.depth0 = 1;
    346    templ.array_size = 1;
    347 
    348    buffer->resource =
    349       screen->base.screen->resource_create(screen->base.screen, &templ);
    350    if (!buffer->resource) {
    351       FREE(buffer);
    352       return NULL;
    353    }
    354 
    355    memset(&whandle, 0, sizeof(whandle));
    356    whandle.type = DRM_API_HANDLE_TYPE_SHARED;
    357    screen->base.screen->resource_get_handle(screen->base.screen,
    358          buffer->resource, &whandle);
    359 
    360    buffer->base.attachment = attachment;
    361    buffer->base.name = whandle.handle;
    362    buffer->base.cpp = util_format_get_blocksize(pf);
    363    buffer->base.pitch = whandle.stride;
    364 
    365    return &buffer->base;
    366 }
    367 
    368 static void
    369 dri2_release_buffer(__DRIscreen *sPriv, __DRIbuffer *bPriv)
    370 {
    371    struct dri2_buffer *buffer = dri2_buffer(bPriv);
    372 
    373    pipe_resource_reference(&buffer->resource, NULL);
    374    FREE(buffer);
    375 }
    376 
    377 /*
    378  * Backend functions for st_framebuffer interface.
    379  */
    380 
    381 static void
    382 dri2_allocate_textures(struct dri_drawable *drawable,
    383                        const enum st_attachment_type *statts,
    384                        unsigned count)
    385 {
    386    __DRIbuffer *buffers;
    387    unsigned num_buffers = count;
    388 
    389    buffers = dri2_drawable_get_buffers(drawable, statts, &num_buffers);
    390    if (buffers)
    391       dri2_drawable_process_buffers(drawable, buffers, num_buffers);
    392 }
    393 
    394 static void
    395 dri2_flush_frontbuffer(struct dri_drawable *drawable,
    396                        enum st_attachment_type statt)
    397 {
    398    __DRIdrawable *dri_drawable = drawable->dPriv;
    399    struct __DRIdri2LoaderExtensionRec *loader = drawable->sPriv->dri2.loader;
    400 
    401    if (loader->flushFrontBuffer == NULL)
    402       return;
    403 
    404    if (statt == ST_ATTACHMENT_FRONT_LEFT) {
    405       loader->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate);
    406    }
    407 }
    408 
    409 static void
    410 dri2_update_tex_buffer(struct dri_drawable *drawable,
    411                        struct dri_context *ctx,
    412                        struct pipe_resource *res)
    413 {
    414    /* no-op */
    415 }
    416 
    417 static __DRIimage *
    418 dri2_lookup_egl_image(struct dri_screen *screen, void *handle)
    419 {
    420    __DRIimageLookupExtension *loader = screen->sPriv->dri2.image;
    421    __DRIimage *img;
    422 
    423    if (!loader->lookupEGLImage)
    424       return NULL;
    425 
    426    img = loader->lookupEGLImage(screen->sPriv,
    427 				handle, screen->sPriv->loaderPrivate);
    428 
    429    return img;
    430 }
    431 
    432 static __DRIimage *
    433 dri2_create_image_from_name(__DRIscreen *_screen,
    434                             int width, int height, int format,
    435                             int name, int pitch, void *loaderPrivate)
    436 {
    437    struct dri_screen *screen = dri_screen(_screen);
    438    __DRIimage *img;
    439    struct pipe_resource templ;
    440    struct winsys_handle whandle;
    441    unsigned tex_usage;
    442    enum pipe_format pf;
    443 
    444    tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
    445 
    446    switch (format) {
    447    case __DRI_IMAGE_FORMAT_RGB565:
    448       pf = PIPE_FORMAT_B5G6R5_UNORM;
    449       break;
    450    case __DRI_IMAGE_FORMAT_XRGB8888:
    451       pf = PIPE_FORMAT_B8G8R8X8_UNORM;
    452       break;
    453    case __DRI_IMAGE_FORMAT_ARGB8888:
    454       pf = PIPE_FORMAT_B8G8R8A8_UNORM;
    455       break;
    456    case __DRI_IMAGE_FORMAT_ABGR8888:
    457       pf = PIPE_FORMAT_R8G8B8A8_UNORM;
    458       break;
    459    default:
    460       pf = PIPE_FORMAT_NONE;
    461       break;
    462    }
    463    if (pf == PIPE_FORMAT_NONE)
    464       return NULL;
    465 
    466    img = CALLOC_STRUCT(__DRIimageRec);
    467    if (!img)
    468       return NULL;
    469 
    470    memset(&templ, 0, sizeof(templ));
    471    templ.bind = tex_usage;
    472    templ.format = pf;
    473    templ.target = screen->target;
    474    templ.last_level = 0;
    475    templ.width0 = width;
    476    templ.height0 = height;
    477    templ.depth0 = 1;
    478    templ.array_size = 1;
    479 
    480    memset(&whandle, 0, sizeof(whandle));
    481    whandle.handle = name;
    482    whandle.stride = pitch * util_format_get_blocksize(pf);
    483 
    484    img->texture = screen->base.screen->resource_from_handle(screen->base.screen,
    485          &templ, &whandle);
    486    if (!img->texture) {
    487       FREE(img);
    488       return NULL;
    489    }
    490 
    491    img->level = 0;
    492    img->layer = 0;
    493    img->dri_format = format;
    494    img->loader_private = loaderPrivate;
    495 
    496    return img;
    497 }
    498 
    499 static __DRIimage *
    500 dri2_create_image_from_renderbuffer(__DRIcontext *context,
    501 				    int renderbuffer, void *loaderPrivate)
    502 {
    503    struct dri_context *ctx = dri_context(context);
    504 
    505    if (!ctx->st->get_resource_for_egl_image)
    506       return NULL;
    507 
    508    /* TODO */
    509    return NULL;
    510 }
    511 
    512 static __DRIimage *
    513 dri2_create_image(__DRIscreen *_screen,
    514                    int width, int height, int format,
    515                    unsigned int use, void *loaderPrivate)
    516 {
    517    struct dri_screen *screen = dri_screen(_screen);
    518    __DRIimage *img;
    519    struct pipe_resource templ;
    520    unsigned tex_usage;
    521    enum pipe_format pf;
    522 
    523    tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
    524    if (use & __DRI_IMAGE_USE_SCANOUT)
    525       tex_usage |= PIPE_BIND_SCANOUT;
    526    if (use & __DRI_IMAGE_USE_SHARE)
    527       tex_usage |= PIPE_BIND_SHARED;
    528    if (use & __DRI_IMAGE_USE_CURSOR) {
    529       if (width != 64 || height != 64)
    530          return NULL;
    531       tex_usage |= PIPE_BIND_CURSOR;
    532    }
    533 
    534    switch (format) {
    535    case __DRI_IMAGE_FORMAT_RGB565:
    536       pf = PIPE_FORMAT_B5G6R5_UNORM;
    537       break;
    538    case __DRI_IMAGE_FORMAT_XRGB8888:
    539       pf = PIPE_FORMAT_B8G8R8X8_UNORM;
    540       break;
    541    case __DRI_IMAGE_FORMAT_ARGB8888:
    542       pf = PIPE_FORMAT_B8G8R8A8_UNORM;
    543       break;
    544    case __DRI_IMAGE_FORMAT_ABGR8888:
    545       pf = PIPE_FORMAT_R8G8B8A8_UNORM;
    546       break;
    547    default:
    548       pf = PIPE_FORMAT_NONE;
    549       break;
    550    }
    551    if (pf == PIPE_FORMAT_NONE)
    552       return NULL;
    553 
    554    img = CALLOC_STRUCT(__DRIimageRec);
    555    if (!img)
    556       return NULL;
    557 
    558    memset(&templ, 0, sizeof(templ));
    559    templ.bind = tex_usage;
    560    templ.format = pf;
    561    templ.target = PIPE_TEXTURE_2D;
    562    templ.last_level = 0;
    563    templ.width0 = width;
    564    templ.height0 = height;
    565    templ.depth0 = 1;
    566    templ.array_size = 1;
    567 
    568    img->texture = screen->base.screen->resource_create(screen->base.screen, &templ);
    569    if (!img->texture) {
    570       FREE(img);
    571       return NULL;
    572    }
    573 
    574    img->level = 0;
    575    img->layer = 0;
    576    img->dri_format = format;
    577    img->dri_components = 0;
    578 
    579    img->loader_private = loaderPrivate;
    580    return img;
    581 }
    582 
    583 static GLboolean
    584 dri2_query_image(__DRIimage *image, int attrib, int *value)
    585 {
    586    struct winsys_handle whandle;
    587    memset(&whandle, 0, sizeof(whandle));
    588 
    589    switch (attrib) {
    590    case __DRI_IMAGE_ATTRIB_STRIDE:
    591       image->texture->screen->resource_get_handle(image->texture->screen,
    592             image->texture, &whandle);
    593       *value = whandle.stride;
    594       return GL_TRUE;
    595    case __DRI_IMAGE_ATTRIB_HANDLE:
    596       whandle.type = DRM_API_HANDLE_TYPE_KMS;
    597       image->texture->screen->resource_get_handle(image->texture->screen,
    598          image->texture, &whandle);
    599       *value = whandle.handle;
    600       return GL_TRUE;
    601    case __DRI_IMAGE_ATTRIB_NAME:
    602       whandle.type = DRM_API_HANDLE_TYPE_SHARED;
    603       image->texture->screen->resource_get_handle(image->texture->screen,
    604          image->texture, &whandle);
    605       *value = whandle.handle;
    606       return GL_TRUE;
    607    case __DRI_IMAGE_ATTRIB_FORMAT:
    608       *value = image->dri_format;
    609       return GL_TRUE;
    610    case __DRI_IMAGE_ATTRIB_WIDTH:
    611       *value = image->texture->width0;
    612       return GL_TRUE;
    613    case __DRI_IMAGE_ATTRIB_HEIGHT:
    614       *value = image->texture->height0;
    615       return GL_TRUE;
    616    case __DRI_IMAGE_ATTRIB_COMPONENTS:
    617       if (image->dri_components == 0)
    618          return GL_FALSE;
    619       *value = image->dri_components;
    620       return GL_TRUE;
    621    default:
    622       return GL_FALSE;
    623    }
    624 }
    625 
    626 static __DRIimage *
    627 dri2_dup_image(__DRIimage *image, void *loaderPrivate)
    628 {
    629    __DRIimage *img;
    630 
    631    img = CALLOC_STRUCT(__DRIimageRec);
    632    if (!img)
    633       return NULL;
    634 
    635    img->texture = NULL;
    636    pipe_resource_reference(&img->texture, image->texture);
    637    img->level = image->level;
    638    img->layer = image->layer;
    639    /* This should be 0 for sub images, but dup is also used for base images. */
    640    img->dri_components = image->dri_components;
    641    img->loader_private = loaderPrivate;
    642 
    643    return img;
    644 }
    645 
    646 static GLboolean
    647 dri2_validate_usage(__DRIimage *image, unsigned int use)
    648 {
    649    /*
    650     * Gallium drivers are bad at adding usages to the resources
    651     * once opened again in another process, which is the main use
    652     * case for this, so we have to lie.
    653     */
    654    if (image != NULL)
    655       return GL_TRUE;
    656    else
    657       return GL_FALSE;
    658 }
    659 
    660 static __DRIimage *
    661 dri2_from_names(__DRIscreen *screen, int width, int height, int format,
    662                 int *names, int num_names, int *strides, int *offsets,
    663                 void *loaderPrivate)
    664 {
    665    __DRIimage *img;
    666    int stride, dri_components;
    667 
    668    if (num_names != 1)
    669       return NULL;
    670    if (offsets[0] != 0)
    671       return NULL;
    672 
    673    switch(format) {
    674    case __DRI_IMAGE_FOURCC_RGB565:
    675       format = __DRI_IMAGE_FORMAT_RGB565;
    676       dri_components = __DRI_IMAGE_COMPONENTS_RGB;
    677       break;
    678    case __DRI_IMAGE_FOURCC_ARGB8888:
    679       format = __DRI_IMAGE_FORMAT_ARGB8888;
    680       dri_components = __DRI_IMAGE_COMPONENTS_RGBA;
    681       break;
    682    case __DRI_IMAGE_FOURCC_XRGB8888:
    683       format = __DRI_IMAGE_FORMAT_XRGB8888;
    684       dri_components = __DRI_IMAGE_COMPONENTS_RGB;
    685       break;
    686    case __DRI_IMAGE_FOURCC_ABGR8888:
    687       format = __DRI_IMAGE_FORMAT_ABGR8888;
    688       dri_components = __DRI_IMAGE_COMPONENTS_RGBA;
    689       break;
    690    case __DRI_IMAGE_FOURCC_XBGR8888:
    691       format = __DRI_IMAGE_FORMAT_XBGR8888;
    692       dri_components = __DRI_IMAGE_COMPONENTS_RGB;
    693       break;
    694    default:
    695       return NULL;
    696    }
    697 
    698    /* Strides are in bytes not pixels. */
    699    stride = strides[0] /4;
    700 
    701    img = dri2_create_image_from_name(screen, width, height, format,
    702                                      names[0], stride, loaderPrivate);
    703    if (img == NULL)
    704       return NULL;
    705 
    706    img->dri_components = dri_components;
    707    return img;
    708 }
    709 
    710 static __DRIimage *
    711 dri2_from_planar(__DRIimage *image, int plane, void *loaderPrivate)
    712 {
    713    __DRIimage *img;
    714 
    715    if (plane != 0)
    716       return NULL;
    717 
    718    if (image->dri_components == 0)
    719       return NULL;
    720 
    721    img = dri2_dup_image(image, loaderPrivate);
    722    if (img == NULL)
    723       return NULL;
    724 
    725    /* set this to 0 for sub images. */
    726    img->dri_components = 0;
    727    return img;
    728 }
    729 
    730 static void
    731 dri2_destroy_image(__DRIimage *img)
    732 {
    733    pipe_resource_reference(&img->texture, NULL);
    734    FREE(img);
    735 }
    736 
    737 static struct __DRIimageExtensionRec dri2ImageExtension = {
    738     { __DRI_IMAGE, 5 },
    739     dri2_create_image_from_name,
    740     dri2_create_image_from_renderbuffer,
    741     dri2_destroy_image,
    742     dri2_create_image,
    743     dri2_query_image,
    744     dri2_dup_image,
    745     dri2_validate_usage,
    746     dri2_from_names,
    747     dri2_from_planar,
    748 };
    749 
    750 /*
    751  * Backend function init_screen.
    752  */
    753 
    754 static const __DRIextension *dri_screen_extensions[] = {
    755    &driTexBufferExtension.base,
    756    &dri2FlushExtension.base,
    757    &dri2ImageExtension.base,
    758    &dri2ConfigQueryExtension.base,
    759    NULL
    760 };
    761 
    762 static const __DRIextension *dri_screen_extensions_throttle[] = {
    763    &driTexBufferExtension.base,
    764    &dri2FlushExtension.base,
    765    &dri2ImageExtension.base,
    766    &dri2ConfigQueryExtension.base,
    767    &dri2ThrottleExtension.base,
    768    NULL
    769 };
    770 
    771 /**
    772  * This is the driver specific part of the createNewScreen entry point.
    773  *
    774  * Returns the struct gl_config supported by this driver.
    775  */
    776 static const __DRIconfig **
    777 dri2_init_screen(__DRIscreen * sPriv)
    778 {
    779    const __DRIconfig **configs;
    780    struct dri_screen *screen;
    781    struct pipe_screen *pscreen;
    782    const struct drm_conf_ret *throttle_ret = NULL;
    783 
    784    screen = CALLOC_STRUCT(dri_screen);
    785    if (!screen)
    786       return NULL;
    787 
    788    screen->sPriv = sPriv;
    789    screen->fd = sPriv->fd;
    790 
    791    sPriv->driverPrivate = (void *)screen;
    792 
    793    pscreen = driver_descriptor.create_screen(screen->fd);
    794    if (driver_descriptor.configuration)
    795       throttle_ret = driver_descriptor.configuration(DRM_CONF_THROTTLE);
    796 
    797    if (throttle_ret && throttle_ret->val.val_int != -1) {
    798       sPriv->extensions = dri_screen_extensions_throttle;
    799       screen->default_throttle_frames = throttle_ret->val.val_int;
    800    } else
    801       sPriv->extensions = dri_screen_extensions;
    802 
    803    /* dri_init_screen_helper checks pscreen for us */
    804 
    805    configs = dri_init_screen_helper(screen, pscreen, 32);
    806    if (!configs)
    807       goto fail;
    808 
    809    sPriv->api_mask = 0;
    810    if (screen->st_api->profile_mask & ST_PROFILE_DEFAULT_MASK)
    811       sPriv->api_mask |= 1 << __DRI_API_OPENGL;
    812    if (screen->st_api->profile_mask & ST_PROFILE_OPENGL_ES1_MASK)
    813       sPriv->api_mask |= 1 << __DRI_API_GLES;
    814    if (screen->st_api->profile_mask & ST_PROFILE_OPENGL_ES2_MASK)
    815       sPriv->api_mask |= 1 << __DRI_API_GLES2;
    816 
    817    screen->auto_fake_front = dri_with_format(sPriv);
    818    screen->broken_invalidate = !sPriv->dri2.useInvalidate;
    819    screen->lookup_egl_image = dri2_lookup_egl_image;
    820 
    821    return configs;
    822 fail:
    823    dri_destroy_screen_helper(screen);
    824    FREE(screen);
    825    return NULL;
    826 }
    827 
    828 static boolean
    829 dri2_create_buffer(__DRIscreen * sPriv,
    830                    __DRIdrawable * dPriv,
    831                    const struct gl_config * visual, boolean isPixmap)
    832 {
    833    struct dri_drawable *drawable = NULL;
    834 
    835    if (!dri_create_buffer(sPriv, dPriv, visual, isPixmap))
    836       return FALSE;
    837 
    838    drawable = dPriv->driverPrivate;
    839 
    840    drawable->allocate_textures = dri2_allocate_textures;
    841    drawable->flush_frontbuffer = dri2_flush_frontbuffer;
    842    drawable->update_tex_buffer = dri2_update_tex_buffer;
    843 
    844    return TRUE;
    845 }
    846 
    847 /**
    848  * DRI driver virtual function table.
    849  *
    850  * DRI versions differ in their implementation of init_screen and swap_buffers.
    851  */
    852 const struct __DriverAPIRec driDriverAPI = {
    853    .InitScreen = dri2_init_screen,
    854    .DestroyScreen = dri_destroy_screen,
    855    .CreateContext = dri_create_context,
    856    .DestroyContext = dri_destroy_context,
    857    .CreateBuffer = dri2_create_buffer,
    858    .DestroyBuffer = dri_destroy_buffer,
    859    .MakeCurrent = dri_make_current,
    860    .UnbindContext = dri_unbind_context,
    861 
    862    .AllocateBuffer = dri2_allocate_buffer,
    863    .ReleaseBuffer  = dri2_release_buffer,
    864 };
    865 
    866 /* This is the table of extensions that the loader will dlsym() for. */
    867 PUBLIC const __DRIextension *__driDriverExtensions[] = {
    868     &driCoreExtension.base,
    869     &driDRI2Extension.base,
    870     NULL
    871 };
    872 
    873 /* vim: set sw=3 ts=8 sts=3 expandtab: */
    874