Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

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