Home | History | Annotate | Download | only in x11
      1 /*
      2  * Mesa 3-D graphics library
      3  * Version:  7.8
      4  *
      5  * Copyright (C) 2009-2010 Chia-I Wu <olv (at) 0xlab.org>
      6  *
      7  * Permission is hereby granted, free of charge, to any person obtaining a
      8  * copy of this software and associated documentation files (the "Software"),
      9  * to deal in the Software without restriction, including without limitation
     10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     11  * and/or sell copies of the Software, and to permit persons to whom the
     12  * Software is furnished to do so, subject to the following conditions:
     13  *
     14  * The above copyright notice and this permission notice shall be included
     15  * in all copies or substantial portions of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     22  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     23  * DEALINGS IN THE SOFTWARE.
     24  */
     25 
     26 #include "util/u_memory.h"
     27 #include "util/u_math.h"
     28 #include "util/u_format.h"
     29 #include "util/u_inlines.h"
     30 #include "util/u_hash_table.h"
     31 #include "pipe/p_compiler.h"
     32 #include "pipe/p_screen.h"
     33 #include "pipe/p_context.h"
     34 #include "pipe/p_state.h"
     35 #include "state_tracker/drm_driver.h"
     36 #include "egllog.h"
     37 
     38 #include "native_x11.h"
     39 #include "x11_screen.h"
     40 
     41 #include "common/native_helper.h"
     42 #ifdef HAVE_WAYLAND_BACKEND
     43 #include "common/native_wayland_drm_bufmgr_helper.h"
     44 #endif
     45 
     46 #ifdef GLX_DIRECT_RENDERING
     47 
     48 struct dri2_display {
     49    struct native_display base;
     50    Display *dpy;
     51    boolean own_dpy;
     52 
     53    const struct native_event_handler *event_handler;
     54 
     55    struct x11_screen *xscr;
     56    int xscr_number;
     57    const char *dri_driver;
     58    int dri_major, dri_minor;
     59 
     60    struct dri2_config *configs;
     61    int num_configs;
     62 
     63    struct util_hash_table *surfaces;
     64 #ifdef HAVE_WAYLAND_BACKEND
     65    struct wl_drm *wl_server_drm; /* for EGL_WL_bind_wayland_display */
     66 #endif
     67 };
     68 
     69 struct dri2_surface {
     70    struct native_surface base;
     71    Drawable drawable;
     72    enum pipe_format color_format;
     73    struct dri2_display *dri2dpy;
     74 
     75    unsigned int server_stamp;
     76    unsigned int client_stamp;
     77    int width, height;
     78    struct pipe_resource *textures[NUM_NATIVE_ATTACHMENTS];
     79    uint valid_mask;
     80 
     81    boolean have_back, have_fake;
     82 
     83    struct x11_drawable_buffer *last_xbufs;
     84    int last_num_xbufs;
     85 };
     86 
     87 struct dri2_config {
     88    struct native_config base;
     89 };
     90 
     91 static INLINE struct dri2_display *
     92 dri2_display(const struct native_display *ndpy)
     93 {
     94    return (struct dri2_display *) ndpy;
     95 }
     96 
     97 static INLINE struct dri2_surface *
     98 dri2_surface(const struct native_surface *nsurf)
     99 {
    100    return (struct dri2_surface *) nsurf;
    101 }
    102 
    103 static INLINE struct dri2_config *
    104 dri2_config(const struct native_config *nconf)
    105 {
    106    return (struct dri2_config *) nconf;
    107 }
    108 
    109 /**
    110  * Process the buffers returned by the server.
    111  */
    112 static void
    113 dri2_surface_process_drawable_buffers(struct native_surface *nsurf,
    114                                       struct x11_drawable_buffer *xbufs,
    115                                       int num_xbufs)
    116 {
    117    struct dri2_surface *dri2surf = dri2_surface(nsurf);
    118    struct dri2_display *dri2dpy = dri2surf->dri2dpy;
    119    struct pipe_resource templ;
    120    struct winsys_handle whandle;
    121    uint valid_mask;
    122    int i;
    123 
    124    /* free the old textures */
    125    for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++)
    126       pipe_resource_reference(&dri2surf->textures[i], NULL);
    127    dri2surf->valid_mask = 0x0;
    128 
    129    dri2surf->have_back = FALSE;
    130    dri2surf->have_fake = FALSE;
    131 
    132    if (!xbufs)
    133       return;
    134 
    135    memset(&templ, 0, sizeof(templ));
    136    templ.target = PIPE_TEXTURE_2D;
    137    templ.last_level = 0;
    138    templ.width0 = dri2surf->width;
    139    templ.height0 = dri2surf->height;
    140    templ.depth0 = 1;
    141    templ.array_size = 1;
    142    templ.format = dri2surf->color_format;
    143    templ.bind = PIPE_BIND_RENDER_TARGET;
    144 
    145    valid_mask = 0x0;
    146    for (i = 0; i < num_xbufs; i++) {
    147       struct x11_drawable_buffer *xbuf = &xbufs[i];
    148       const char *desc;
    149       enum native_attachment natt;
    150 
    151       switch (xbuf->attachment) {
    152       case DRI2BufferFrontLeft:
    153          natt = NATIVE_ATTACHMENT_FRONT_LEFT;
    154          desc = "DRI2 Front Buffer";
    155          break;
    156       case DRI2BufferFakeFrontLeft:
    157          natt = NATIVE_ATTACHMENT_FRONT_LEFT;
    158          desc = "DRI2 Fake Front Buffer";
    159          dri2surf->have_fake = TRUE;
    160          break;
    161       case DRI2BufferBackLeft:
    162          natt = NATIVE_ATTACHMENT_BACK_LEFT;
    163          desc = "DRI2 Back Buffer";
    164          dri2surf->have_back = TRUE;
    165          break;
    166       default:
    167          desc = NULL;
    168          break;
    169       }
    170 
    171       if (!desc || dri2surf->textures[natt]) {
    172          if (!desc)
    173             _eglLog(_EGL_WARNING, "unknown buffer %d", xbuf->attachment);
    174          else
    175             _eglLog(_EGL_WARNING, "both real and fake front buffers are listed");
    176          continue;
    177       }
    178 
    179       memset(&whandle, 0, sizeof(whandle));
    180       whandle.stride = xbuf->pitch;
    181       whandle.handle = xbuf->name;
    182       dri2surf->textures[natt] = dri2dpy->base.screen->resource_from_handle(
    183          dri2dpy->base.screen, &templ, &whandle);
    184       if (dri2surf->textures[natt])
    185          valid_mask |= 1 << natt;
    186    }
    187 
    188    dri2surf->valid_mask = valid_mask;
    189 }
    190 
    191 /**
    192  * Get the buffers from the server.
    193  */
    194 static void
    195 dri2_surface_get_buffers(struct native_surface *nsurf, uint buffer_mask)
    196 {
    197    struct dri2_surface *dri2surf = dri2_surface(nsurf);
    198    struct dri2_display *dri2dpy = dri2surf->dri2dpy;
    199    unsigned int dri2atts[NUM_NATIVE_ATTACHMENTS * 2];
    200    int num_ins, num_outs, att;
    201    struct x11_drawable_buffer *xbufs;
    202    uint bpp = util_format_get_blocksizebits(dri2surf->color_format);
    203    boolean with_format = FALSE; /* never ask for depth/stencil */
    204 
    205    /* We must get the front on servers which doesn't support with format
    206     * due to a silly bug in core dri2. You can't copy to/from a buffer
    207     * that you haven't requested and you recive BadValue errors */
    208    if (dri2surf->dri2dpy->dri_minor < 1) {
    209       with_format = FALSE;
    210       buffer_mask |= (1 << NATIVE_ATTACHMENT_FRONT_LEFT);
    211    }
    212 
    213    /* prepare the attachments */
    214    num_ins = 0;
    215    for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
    216       if (native_attachment_mask_test(buffer_mask, att)) {
    217          unsigned int dri2att;
    218 
    219          switch (att) {
    220          case NATIVE_ATTACHMENT_FRONT_LEFT:
    221             dri2att = DRI2BufferFrontLeft;
    222             break;
    223          case NATIVE_ATTACHMENT_BACK_LEFT:
    224             dri2att = DRI2BufferBackLeft;
    225             break;
    226          case NATIVE_ATTACHMENT_FRONT_RIGHT:
    227             dri2att = DRI2BufferFrontRight;
    228             break;
    229          case NATIVE_ATTACHMENT_BACK_RIGHT:
    230             dri2att = DRI2BufferBackRight;
    231             break;
    232          default:
    233             assert(0);
    234             dri2att = 0;
    235             break;
    236          }
    237 
    238          dri2atts[num_ins++] = dri2att;
    239          if (with_format)
    240             dri2atts[num_ins++] = bpp;
    241       }
    242    }
    243    if (with_format)
    244       num_ins /= 2;
    245 
    246    xbufs = x11_drawable_get_buffers(dri2dpy->xscr, dri2surf->drawable,
    247                                     &dri2surf->width, &dri2surf->height,
    248                                     dri2atts, with_format, num_ins, &num_outs);
    249 
    250    /* we should be able to do better... */
    251    if (xbufs && dri2surf->last_num_xbufs == num_outs &&
    252        memcmp(dri2surf->last_xbufs, xbufs, sizeof(*xbufs) * num_outs) == 0) {
    253       FREE(xbufs);
    254       dri2surf->client_stamp = dri2surf->server_stamp;
    255       return;
    256    }
    257 
    258    dri2_surface_process_drawable_buffers(&dri2surf->base, xbufs, num_outs);
    259 
    260    dri2surf->server_stamp++;
    261    dri2surf->client_stamp = dri2surf->server_stamp;
    262 
    263    if (dri2surf->last_xbufs)
    264       FREE(dri2surf->last_xbufs);
    265    dri2surf->last_xbufs = xbufs;
    266    dri2surf->last_num_xbufs = num_outs;
    267 }
    268 
    269 /**
    270  * Update the buffers of the surface.  This is a slow function due to the
    271  * round-trip to the server.
    272  */
    273 static boolean
    274 dri2_surface_update_buffers(struct native_surface *nsurf, uint buffer_mask)
    275 {
    276    struct dri2_surface *dri2surf = dri2_surface(nsurf);
    277 
    278    dri2_surface_get_buffers(&dri2surf->base, buffer_mask);
    279 
    280    return ((dri2surf->valid_mask & buffer_mask) == buffer_mask);
    281 }
    282 
    283 /**
    284  * Return TRUE if the surface receives DRI2_InvalidateBuffers events.
    285  */
    286 static INLINE boolean
    287 dri2_surface_receive_events(struct native_surface *nsurf)
    288 {
    289    struct dri2_surface *dri2surf = dri2_surface(nsurf);
    290    return (dri2surf->dri2dpy->dri_minor >= 3);
    291 }
    292 
    293 static boolean
    294 dri2_surface_flush_frontbuffer(struct native_surface *nsurf)
    295 {
    296    struct dri2_surface *dri2surf = dri2_surface(nsurf);
    297    struct dri2_display *dri2dpy = dri2surf->dri2dpy;
    298 
    299    /* copy to real front buffer */
    300    if (dri2surf->have_fake)
    301       x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
    302             0, 0, dri2surf->width, dri2surf->height,
    303             DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft);
    304 
    305    /* force buffers to be updated in next validation call */
    306    if (!dri2_surface_receive_events(&dri2surf->base)) {
    307       dri2surf->server_stamp++;
    308       dri2dpy->event_handler->invalid_surface(&dri2dpy->base,
    309             &dri2surf->base, dri2surf->server_stamp);
    310    }
    311 
    312    return TRUE;
    313 }
    314 
    315 static boolean
    316 dri2_surface_swap_buffers(struct native_surface *nsurf, int num_rects,
    317                           const int *rects)
    318 {
    319    struct dri2_surface *dri2surf = dri2_surface(nsurf);
    320    struct dri2_display *dri2dpy = dri2surf->dri2dpy;
    321 
    322    /* copy to front buffer */
    323    if (dri2surf->have_back) {
    324       if (num_rects > 0)
    325          x11_drawable_copy_buffers_region(dri2dpy->xscr, dri2surf->drawable,
    326                num_rects, rects,
    327                DRI2BufferBackLeft, DRI2BufferFrontLeft);
    328       else
    329          x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
    330                0, 0, dri2surf->width, dri2surf->height,
    331                DRI2BufferBackLeft, DRI2BufferFrontLeft);
    332    }
    333 
    334    /* and update fake front buffer */
    335    if (dri2surf->have_fake) {
    336       if (num_rects > 0)
    337          x11_drawable_copy_buffers_region(dri2dpy->xscr, dri2surf->drawable,
    338                num_rects, rects,
    339                DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
    340       else
    341          x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
    342                0, 0, dri2surf->width, dri2surf->height,
    343                DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
    344    }
    345 
    346    /* force buffers to be updated in next validation call */
    347    if (!dri2_surface_receive_events(&dri2surf->base)) {
    348       dri2surf->server_stamp++;
    349       dri2dpy->event_handler->invalid_surface(&dri2dpy->base,
    350             &dri2surf->base, dri2surf->server_stamp);
    351    }
    352 
    353    return TRUE;
    354 }
    355 
    356 static boolean
    357 dri2_surface_present(struct native_surface *nsurf,
    358                      const struct native_present_control *ctrl)
    359 {
    360    boolean ret;
    361 
    362    if (ctrl->swap_interval)
    363       return FALSE;
    364 
    365    switch (ctrl->natt) {
    366    case NATIVE_ATTACHMENT_FRONT_LEFT:
    367       ret = dri2_surface_flush_frontbuffer(nsurf);
    368       break;
    369    case NATIVE_ATTACHMENT_BACK_LEFT:
    370       ret = dri2_surface_swap_buffers(nsurf, ctrl->num_rects, ctrl->rects);
    371       break;
    372    default:
    373       ret = FALSE;
    374       break;
    375    }
    376 
    377    return ret;
    378 }
    379 
    380 static boolean
    381 dri2_surface_validate(struct native_surface *nsurf, uint attachment_mask,
    382                       unsigned int *seq_num, struct pipe_resource **textures,
    383                       int *width, int *height)
    384 {
    385    struct dri2_surface *dri2surf = dri2_surface(nsurf);
    386 
    387    if (dri2surf->server_stamp != dri2surf->client_stamp ||
    388        (dri2surf->valid_mask & attachment_mask) != attachment_mask) {
    389       if (!dri2_surface_update_buffers(&dri2surf->base, attachment_mask))
    390          return FALSE;
    391    }
    392 
    393    if (seq_num)
    394       *seq_num = dri2surf->client_stamp;
    395 
    396    if (textures) {
    397       int att;
    398       for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
    399          if (native_attachment_mask_test(attachment_mask, att)) {
    400             struct pipe_resource *ptex = dri2surf->textures[att];
    401 
    402             textures[att] = NULL;
    403             pipe_resource_reference(&textures[att], ptex);
    404          }
    405       }
    406    }
    407 
    408    if (width)
    409       *width = dri2surf->width;
    410    if (height)
    411       *height = dri2surf->height;
    412 
    413    return TRUE;
    414 }
    415 
    416 static void
    417 dri2_surface_wait(struct native_surface *nsurf)
    418 {
    419    struct dri2_surface *dri2surf = dri2_surface(nsurf);
    420    struct dri2_display *dri2dpy = dri2surf->dri2dpy;
    421 
    422    if (dri2surf->have_fake) {
    423       x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
    424             0, 0, dri2surf->width, dri2surf->height,
    425             DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
    426    }
    427 }
    428 
    429 static void
    430 dri2_surface_destroy(struct native_surface *nsurf)
    431 {
    432    struct dri2_surface *dri2surf = dri2_surface(nsurf);
    433    int i;
    434 
    435    if (dri2surf->last_xbufs)
    436       FREE(dri2surf->last_xbufs);
    437 
    438    for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
    439       struct pipe_resource *ptex = dri2surf->textures[i];
    440       pipe_resource_reference(&ptex, NULL);
    441    }
    442 
    443    if (dri2surf->drawable) {
    444       x11_drawable_enable_dri2(dri2surf->dri2dpy->xscr,
    445             dri2surf->drawable, FALSE);
    446 
    447       util_hash_table_remove(dri2surf->dri2dpy->surfaces,
    448             (void *) dri2surf->drawable);
    449    }
    450    FREE(dri2surf);
    451 }
    452 
    453 static struct dri2_surface *
    454 dri2_display_create_surface(struct native_display *ndpy,
    455                             Drawable drawable,
    456                             enum pipe_format color_format)
    457 {
    458    struct dri2_display *dri2dpy = dri2_display(ndpy);
    459    struct dri2_surface *dri2surf;
    460 
    461    dri2surf = CALLOC_STRUCT(dri2_surface);
    462    if (!dri2surf)
    463       return NULL;
    464 
    465    dri2surf->dri2dpy = dri2dpy;
    466    dri2surf->drawable = drawable;
    467    dri2surf->color_format = color_format;
    468 
    469    dri2surf->base.destroy = dri2_surface_destroy;
    470    dri2surf->base.present = dri2_surface_present;
    471    dri2surf->base.validate = dri2_surface_validate;
    472    dri2surf->base.wait = dri2_surface_wait;
    473 
    474    if (drawable) {
    475       x11_drawable_enable_dri2(dri2dpy->xscr, drawable, TRUE);
    476       /* initialize the geometry */
    477       dri2_surface_update_buffers(&dri2surf->base, 0x0);
    478 
    479       util_hash_table_set(dri2surf->dri2dpy->surfaces,
    480             (void *) dri2surf->drawable, (void *) &dri2surf->base);
    481    }
    482 
    483    return dri2surf;
    484 }
    485 
    486 static struct native_surface *
    487 dri2_display_create_window_surface(struct native_display *ndpy,
    488                                    EGLNativeWindowType win,
    489                                    const struct native_config *nconf)
    490 {
    491    struct dri2_surface *dri2surf;
    492 
    493    dri2surf = dri2_display_create_surface(ndpy,
    494          (Drawable) win, nconf->color_format);
    495    return (dri2surf) ? &dri2surf->base : NULL;
    496 }
    497 
    498 static struct native_surface *
    499 dri2_display_create_pixmap_surface(struct native_display *ndpy,
    500                                    EGLNativePixmapType pix,
    501                                    const struct native_config *nconf)
    502 {
    503    struct dri2_surface *dri2surf;
    504 
    505    if (!nconf) {
    506       struct dri2_display *dri2dpy = dri2_display(ndpy);
    507       uint depth, nconf_depth;
    508       int i;
    509 
    510       depth = x11_drawable_get_depth(dri2dpy->xscr, (Drawable) pix);
    511       for (i = 0; i < dri2dpy->num_configs; i++) {
    512          nconf_depth = util_format_get_blocksizebits(
    513                dri2dpy->configs[i].base.color_format);
    514          /* simple depth match for now */
    515          if (depth == nconf_depth ||
    516              (depth == 24 && depth + 8 == nconf_depth)) {
    517             nconf = &dri2dpy->configs[i].base;
    518             break;
    519          }
    520       }
    521 
    522       if (!nconf)
    523          return NULL;
    524    }
    525 
    526    dri2surf = dri2_display_create_surface(ndpy,
    527          (Drawable) pix, nconf->color_format);
    528    return (dri2surf) ? &dri2surf->base : NULL;
    529 }
    530 
    531 static int
    532 choose_color_format(const __GLcontextModes *mode, enum pipe_format formats[32])
    533 {
    534    int count = 0;
    535 
    536    switch (mode->rgbBits) {
    537    case 32:
    538       formats[count++] = PIPE_FORMAT_B8G8R8A8_UNORM;
    539       formats[count++] = PIPE_FORMAT_A8R8G8B8_UNORM;
    540       break;
    541    case 24:
    542       formats[count++] = PIPE_FORMAT_B8G8R8X8_UNORM;
    543       formats[count++] = PIPE_FORMAT_X8R8G8B8_UNORM;
    544       formats[count++] = PIPE_FORMAT_B8G8R8A8_UNORM;
    545       formats[count++] = PIPE_FORMAT_A8R8G8B8_UNORM;
    546       break;
    547    case 16:
    548       formats[count++] = PIPE_FORMAT_B5G6R5_UNORM;
    549       break;
    550    default:
    551       break;
    552    }
    553 
    554    return count;
    555 }
    556 
    557 static boolean
    558 is_format_supported(struct pipe_screen *screen,
    559                     enum pipe_format fmt, unsigned sample_count, boolean is_color)
    560 {
    561    return screen->is_format_supported(screen, fmt, PIPE_TEXTURE_2D, sample_count,
    562          (is_color) ? PIPE_BIND_RENDER_TARGET :
    563          PIPE_BIND_DEPTH_STENCIL);
    564 }
    565 
    566 static boolean
    567 dri2_display_convert_config(struct native_display *ndpy,
    568                             const __GLcontextModes *mode,
    569                             struct native_config *nconf)
    570 {
    571    enum pipe_format formats[32];
    572    int num_formats, i;
    573    int sample_count = 0;
    574 
    575    if (!(mode->renderType & GLX_RGBA_BIT) || !mode->rgbMode)
    576       return FALSE;
    577 
    578    /* only interested in native renderable configs */
    579    if (!mode->xRenderable || !mode->drawableType)
    580       return FALSE;
    581 
    582    /* fast/slow configs are probably not relevant */
    583    if (mode->visualRating == GLX_SLOW_CONFIG)
    584       return FALSE;
    585 
    586    nconf->buffer_mask = 1 << NATIVE_ATTACHMENT_FRONT_LEFT;
    587    if (mode->doubleBufferMode)
    588       nconf->buffer_mask |= 1 << NATIVE_ATTACHMENT_BACK_LEFT;
    589    if (mode->stereoMode) {
    590       nconf->buffer_mask |= 1 << NATIVE_ATTACHMENT_FRONT_RIGHT;
    591       if (mode->doubleBufferMode)
    592          nconf->buffer_mask |= 1 << NATIVE_ATTACHMENT_BACK_RIGHT;
    593    }
    594 
    595    /* choose color format */
    596    num_formats = choose_color_format(mode, formats);
    597    for (i = 0; i < num_formats; i++) {
    598       if (is_format_supported(ndpy->screen, formats[i], sample_count, TRUE)) {
    599          nconf->color_format = formats[i];
    600          break;
    601       }
    602    }
    603    if (nconf->color_format == PIPE_FORMAT_NONE)
    604       return FALSE;
    605 
    606    if ((mode->drawableType & GLX_WINDOW_BIT) && mode->visualID)
    607       nconf->window_bit = TRUE;
    608    if (mode->drawableType & GLX_PIXMAP_BIT)
    609       nconf->pixmap_bit = TRUE;
    610 
    611    nconf->native_visual_id = mode->visualID;
    612    switch (mode->visualType) {
    613    case GLX_TRUE_COLOR:
    614       nconf->native_visual_type = TrueColor;
    615       break;
    616    case GLX_DIRECT_COLOR:
    617       nconf->native_visual_type = DirectColor;
    618       break;
    619    case GLX_PSEUDO_COLOR:
    620       nconf->native_visual_type = PseudoColor;
    621       break;
    622    case GLX_STATIC_COLOR:
    623       nconf->native_visual_type = StaticColor;
    624       break;
    625    case GLX_GRAY_SCALE:
    626       nconf->native_visual_type = GrayScale;
    627       break;
    628    case GLX_STATIC_GRAY:
    629       nconf->native_visual_type = StaticGray;
    630       break;
    631    }
    632    nconf->level = mode->level;
    633 
    634    if (mode->transparentPixel == GLX_TRANSPARENT_RGB) {
    635       nconf->transparent_rgb = TRUE;
    636       nconf->transparent_rgb_values[0] = mode->transparentRed;
    637       nconf->transparent_rgb_values[1] = mode->transparentGreen;
    638       nconf->transparent_rgb_values[2] = mode->transparentBlue;
    639    }
    640 
    641    return TRUE;
    642 }
    643 
    644 static const struct native_config **
    645 dri2_display_get_configs(struct native_display *ndpy, int *num_configs)
    646 {
    647    struct dri2_display *dri2dpy = dri2_display(ndpy);
    648    const struct native_config **configs;
    649    int i;
    650 
    651    /* first time */
    652    if (!dri2dpy->configs) {
    653       const __GLcontextModes *modes;
    654       int num_modes, count;
    655 
    656       modes = x11_screen_get_glx_configs(dri2dpy->xscr);
    657       if (!modes)
    658          return NULL;
    659       num_modes = x11_context_modes_count(modes);
    660 
    661       dri2dpy->configs = CALLOC(num_modes, sizeof(*dri2dpy->configs));
    662       if (!dri2dpy->configs)
    663          return NULL;
    664 
    665       count = 0;
    666       for (i = 0; i < num_modes; i++) {
    667          struct native_config *nconf = &dri2dpy->configs[count].base;
    668 
    669          if (dri2_display_convert_config(&dri2dpy->base, modes, nconf)) {
    670             int j;
    671             /* look for duplicates */
    672             for (j = 0; j < count; j++) {
    673                if (memcmp(&dri2dpy->configs[j], nconf, sizeof(*nconf)) == 0)
    674                   break;
    675             }
    676             if (j == count)
    677                count++;
    678          }
    679          modes = modes->next;
    680       }
    681 
    682       dri2dpy->num_configs = count;
    683    }
    684 
    685    configs = MALLOC(dri2dpy->num_configs * sizeof(*configs));
    686    if (configs) {
    687       for (i = 0; i < dri2dpy->num_configs; i++)
    688          configs[i] = (const struct native_config *) &dri2dpy->configs[i];
    689       if (num_configs)
    690          *num_configs = dri2dpy->num_configs;
    691    }
    692 
    693    return configs;
    694 }
    695 
    696 static boolean
    697 dri2_display_get_pixmap_format(struct native_display *ndpy,
    698                                EGLNativePixmapType pix,
    699                                enum pipe_format *format)
    700 {
    701    struct dri2_display *dri2dpy = dri2_display(ndpy);
    702    boolean ret = EGL_TRUE;
    703    uint depth;
    704 
    705    depth = x11_drawable_get_depth(dri2dpy->xscr, (Drawable) pix);
    706    switch (depth) {
    707    case 32:
    708    case 24:
    709       *format = PIPE_FORMAT_B8G8R8A8_UNORM;
    710       break;
    711    case 16:
    712       *format = PIPE_FORMAT_B5G6R5_UNORM;
    713       break;
    714    default:
    715       *format = PIPE_FORMAT_NONE;
    716       ret = EGL_FALSE;
    717       break;
    718    }
    719 
    720    return ret;
    721 }
    722 
    723 static int
    724 dri2_display_get_param(struct native_display *ndpy,
    725                        enum native_param_type param)
    726 {
    727    int val;
    728 
    729    switch (param) {
    730    case NATIVE_PARAM_USE_NATIVE_BUFFER:
    731       /* DRI2GetBuffers uses the native buffers */
    732       val = TRUE;
    733       break;
    734    case NATIVE_PARAM_PRESERVE_BUFFER:
    735       /* DRI2CopyRegion is used */
    736       val = TRUE;
    737       break;
    738    case NATIVE_PARAM_PRESENT_REGION:
    739       val = TRUE;
    740       break;
    741    case NATIVE_PARAM_MAX_SWAP_INTERVAL:
    742    default:
    743       val = 0;
    744       break;
    745    }
    746 
    747    return val;
    748 }
    749 
    750 static void
    751 dri2_display_destroy(struct native_display *ndpy)
    752 {
    753    struct dri2_display *dri2dpy = dri2_display(ndpy);
    754 
    755    if (dri2dpy->configs)
    756       FREE(dri2dpy->configs);
    757 
    758    if (dri2dpy->base.screen)
    759       dri2dpy->base.screen->destroy(dri2dpy->base.screen);
    760 
    761    if (dri2dpy->surfaces)
    762       util_hash_table_destroy(dri2dpy->surfaces);
    763 
    764    if (dri2dpy->xscr)
    765       x11_screen_destroy(dri2dpy->xscr);
    766    if (dri2dpy->own_dpy)
    767       XCloseDisplay(dri2dpy->dpy);
    768    FREE(dri2dpy);
    769 }
    770 
    771 static void
    772 dri2_display_invalidate_buffers(struct x11_screen *xscr, Drawable drawable,
    773                                 void *user_data)
    774 {
    775    struct native_display *ndpy = (struct native_display* ) user_data;
    776    struct dri2_display *dri2dpy = dri2_display(ndpy);
    777    struct native_surface *nsurf;
    778    struct dri2_surface *dri2surf;
    779 
    780    nsurf = (struct native_surface *)
    781       util_hash_table_get(dri2dpy->surfaces, (void *) drawable);
    782    if (!nsurf)
    783       return;
    784 
    785    dri2surf = dri2_surface(nsurf);
    786 
    787    dri2surf->server_stamp++;
    788    dri2dpy->event_handler->invalid_surface(&dri2dpy->base,
    789          &dri2surf->base, dri2surf->server_stamp);
    790 }
    791 
    792 /**
    793  * Initialize DRI2 and pipe screen.
    794  */
    795 static boolean
    796 dri2_display_init_screen(struct native_display *ndpy)
    797 {
    798    struct dri2_display *dri2dpy = dri2_display(ndpy);
    799    int fd;
    800 
    801    if (!x11_screen_support(dri2dpy->xscr, X11_SCREEN_EXTENSION_DRI2) ||
    802        !x11_screen_support(dri2dpy->xscr, X11_SCREEN_EXTENSION_GLX)) {
    803       _eglLog(_EGL_WARNING, "GLX/DRI2 is not supported");
    804       return FALSE;
    805    }
    806 
    807    dri2dpy->dri_driver = x11_screen_probe_dri2(dri2dpy->xscr,
    808          &dri2dpy->dri_major, &dri2dpy->dri_minor);
    809 
    810    fd = x11_screen_enable_dri2(dri2dpy->xscr,
    811          dri2_display_invalidate_buffers, &dri2dpy->base);
    812    if (fd < 0)
    813       return FALSE;
    814 
    815    dri2dpy->base.screen =
    816       dri2dpy->event_handler->new_drm_screen(&dri2dpy->base,
    817             dri2dpy->dri_driver, fd);
    818    if (!dri2dpy->base.screen) {
    819       _eglLog(_EGL_DEBUG, "failed to create DRM screen");
    820       return FALSE;
    821    }
    822 
    823    return TRUE;
    824 }
    825 
    826 static unsigned
    827 dri2_display_hash_table_hash(void *key)
    828 {
    829    XID drawable = pointer_to_uintptr(key);
    830    return (unsigned) drawable;
    831 }
    832 
    833 static int
    834 dri2_display_hash_table_compare(void *key1, void *key2)
    835 {
    836    return ((char *) key1 - (char *) key2);
    837 }
    838 
    839 #ifdef HAVE_WAYLAND_BACKEND
    840 
    841 static int
    842 dri2_display_authenticate(void *user_data, uint32_t magic)
    843 {
    844    struct native_display *ndpy = user_data;
    845    struct dri2_display *dri2dpy = dri2_display(ndpy);
    846 
    847    return x11_screen_authenticate(dri2dpy->xscr, magic);
    848 }
    849 
    850 static struct wayland_drm_callbacks wl_drm_callbacks = {
    851    dri2_display_authenticate,
    852    egl_g3d_wl_drm_helper_reference_buffer,
    853    egl_g3d_wl_drm_helper_unreference_buffer
    854 };
    855 
    856 static boolean
    857 dri2_display_bind_wayland_display(struct native_display *ndpy,
    858                                   struct wl_display *wl_dpy)
    859 {
    860    struct dri2_display *dri2dpy = dri2_display(ndpy);
    861 
    862    if (dri2dpy->wl_server_drm)
    863       return FALSE;
    864 
    865    dri2dpy->wl_server_drm = wayland_drm_init(wl_dpy,
    866          x11_screen_get_device_name(dri2dpy->xscr),
    867          &wl_drm_callbacks, ndpy);
    868 
    869    if (!dri2dpy->wl_server_drm)
    870       return FALSE;
    871 
    872    return TRUE;
    873 }
    874 
    875 static boolean
    876 dri2_display_unbind_wayland_display(struct native_display *ndpy,
    877                                     struct wl_display *wl_dpy)
    878 {
    879    struct dri2_display *dri2dpy = dri2_display(ndpy);
    880 
    881    if (!dri2dpy->wl_server_drm)
    882       return FALSE;
    883 
    884    wayland_drm_uninit(dri2dpy->wl_server_drm);
    885    dri2dpy->wl_server_drm = NULL;
    886 
    887    return TRUE;
    888 }
    889 
    890 static struct native_display_wayland_bufmgr dri2_display_wayland_bufmgr = {
    891    dri2_display_bind_wayland_display,
    892    dri2_display_unbind_wayland_display,
    893    egl_g3d_wl_drm_common_wl_buffer_get_resource,
    894    egl_g3d_wl_drm_common_query_buffer
    895 };
    896 
    897 #endif /* HAVE_WAYLAND_BACKEND */
    898 
    899 struct native_display *
    900 x11_create_dri2_display(Display *dpy,
    901                         const struct native_event_handler *event_handler)
    902 {
    903    struct dri2_display *dri2dpy;
    904 
    905    dri2dpy = CALLOC_STRUCT(dri2_display);
    906    if (!dri2dpy)
    907       return NULL;
    908 
    909    dri2dpy->event_handler = event_handler;
    910 
    911    dri2dpy->dpy = dpy;
    912    if (!dri2dpy->dpy) {
    913       dri2dpy->dpy = XOpenDisplay(NULL);
    914       if (!dri2dpy->dpy) {
    915          dri2_display_destroy(&dri2dpy->base);
    916          return NULL;
    917       }
    918       dri2dpy->own_dpy = TRUE;
    919    }
    920 
    921    dri2dpy->xscr_number = DefaultScreen(dri2dpy->dpy);
    922    dri2dpy->xscr = x11_screen_create(dri2dpy->dpy, dri2dpy->xscr_number);
    923    if (!dri2dpy->xscr) {
    924       dri2_display_destroy(&dri2dpy->base);
    925       return NULL;
    926    }
    927 
    928    dri2dpy->surfaces = util_hash_table_create(dri2_display_hash_table_hash,
    929          dri2_display_hash_table_compare);
    930    if (!dri2dpy->surfaces) {
    931       dri2_display_destroy(&dri2dpy->base);
    932       return NULL;
    933    }
    934 
    935    dri2dpy->base.init_screen = dri2_display_init_screen;
    936    dri2dpy->base.destroy = dri2_display_destroy;
    937    dri2dpy->base.get_param = dri2_display_get_param;
    938    dri2dpy->base.get_configs = dri2_display_get_configs;
    939    dri2dpy->base.get_pixmap_format = dri2_display_get_pixmap_format;
    940    dri2dpy->base.copy_to_pixmap = native_display_copy_to_pixmap;
    941    dri2dpy->base.create_window_surface = dri2_display_create_window_surface;
    942    dri2dpy->base.create_pixmap_surface = dri2_display_create_pixmap_surface;
    943 #ifdef HAVE_WAYLAND_BACKEND
    944    dri2dpy->base.wayland_bufmgr = &dri2_display_wayland_bufmgr;
    945 #endif
    946 
    947    return &dri2dpy->base;
    948 }
    949 
    950 #else /* GLX_DIRECT_RENDERING */
    951 
    952 struct native_display *
    953 x11_create_dri2_display(Display *dpy,
    954                         const struct native_event_handler *event_handler)
    955 {
    956    return NULL;
    957 }
    958 
    959 #endif /* GLX_DIRECT_RENDERING */
    960