Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright © 2013 Keith Packard
  3.  *
  4.  * Permission to use, copy, modify, distribute, and sell this software and its
  5.  * documentation for any purpose is hereby granted without fee, provided that
  6.  * the above copyright notice appear in all copies and that both that copyright
  7.  * notice and this permission notice appear in supporting documentation, and
  8.  * that the name of the copyright holders not be used in advertising or
  9.  * publicity pertaining to distribution of the software without specific,
  10.  * written prior permission.  The copyright holders make no representations
  11.  * about the suitability of this software for any purpose.  It is provided "as
  12.  * is" without express or implied warranty.
  13.  *
  14.  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  15.  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  16.  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  17.  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  18.  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  19.  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  20.  * OF THIS SOFTWARE.
  21.  */
  22.  
  23. /*
  24.  * Portions of this code were adapted from dri2_glx.c which carries the
  25.  * following copyright:
  26.  *
  27.  * Copyright © 2008 Red Hat, Inc.
  28.  *
  29.  * Permission is hereby granted, free of charge, to any person obtaining a
  30.  * copy of this software and associated documentation files (the "Soft-
  31.  * ware"), to deal in the Software without restriction, including without
  32.  * limitation the rights to use, copy, modify, merge, publish, distribute,
  33.  * and/or sell copies of the Software, and to permit persons to whom the
  34.  * Software is furnished to do so, provided that the above copyright
  35.  * notice(s) and this permission notice appear in all copies of the Soft-
  36.  * ware and that both the above copyright notice(s) and this permission
  37.  * notice appear in supporting documentation.
  38.  *
  39.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  40.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
  41.  * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
  42.  * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
  43.  * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
  44.  * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  45.  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  46.  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
  47.  * MANCE OF THIS SOFTWARE.
  48.  *
  49.  * Except as contained in this notice, the name of a copyright holder shall
  50.  * not be used in advertising or otherwise to promote the sale, use or
  51.  * other dealings in this Software without prior written authorization of
  52.  * the copyright holder.
  53.  *
  54.  * Authors:
  55.  *   Kristian Høgsberg (krh@redhat.com)
  56.  */
  57.  
  58. #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
  59.  
  60. #include <X11/Xlib.h>
  61. #include <X11/extensions/Xfixes.h>
  62. #include <X11/Xlib-xcb.h>
  63. #include <X11/xshmfence.h>
  64. #include <xcb/xcb.h>
  65. #include <xcb/dri3.h>
  66. #include <xcb/present.h>
  67. #include <GL/gl.h>
  68. #include "glxclient.h"
  69. #include <dlfcn.h>
  70. #include <fcntl.h>
  71. #include <unistd.h>
  72. #include <sys/types.h>
  73. #include <sys/mman.h>
  74. #include <sys/time.h>
  75.  
  76. #include "dri_common.h"
  77. #include "dri3_priv.h"
  78. #include "loader.h"
  79. #include "dri2.h"
  80.  
  81. static const struct glx_context_vtable dri3_context_vtable;
  82.  
  83. static inline void
  84. dri3_fence_reset(xcb_connection_t *c, struct dri3_buffer *buffer)
  85. {
  86.    xshmfence_reset(buffer->shm_fence);
  87. }
  88.  
  89. static inline void
  90. dri3_fence_set(struct dri3_buffer *buffer)
  91. {
  92.    xshmfence_trigger(buffer->shm_fence);
  93. }
  94.  
  95. static inline void
  96. dri3_fence_trigger(xcb_connection_t *c, struct dri3_buffer *buffer)
  97. {
  98.    xcb_sync_trigger_fence(c, buffer->sync_fence);
  99. }
  100.  
  101. static inline void
  102. dri3_fence_await(xcb_connection_t *c, struct dri3_buffer *buffer)
  103. {
  104.    xcb_flush(c);
  105.    xshmfence_await(buffer->shm_fence);
  106. }
  107.  
  108. static inline Bool
  109. dri3_fence_triggered(struct dri3_buffer *buffer)
  110. {
  111.    return xshmfence_query(buffer->shm_fence);
  112. }
  113.  
  114. static void
  115. dri3_destroy_context(struct glx_context *context)
  116. {
  117.    struct dri3_context *pcp = (struct dri3_context *) context;
  118.    struct dri3_screen *psc = (struct dri3_screen *) context->psc;
  119.  
  120.    driReleaseDrawables(&pcp->base);
  121.  
  122.    free((char *) context->extensions);
  123.  
  124.    (*psc->core->destroyContext) (pcp->driContext);
  125.  
  126.    free(pcp);
  127. }
  128.  
  129. static Bool
  130. dri3_bind_context(struct glx_context *context, struct glx_context *old,
  131.                   GLXDrawable draw, GLXDrawable read)
  132. {
  133.    struct dri3_context *pcp = (struct dri3_context *) context;
  134.    struct dri3_screen *psc = (struct dri3_screen *) pcp->base.psc;
  135.    struct dri3_drawable *pdraw, *pread;
  136.  
  137.    pdraw = (struct dri3_drawable *) driFetchDrawable(context, draw);
  138.    pread = (struct dri3_drawable *) driFetchDrawable(context, read);
  139.  
  140.    driReleaseDrawables(&pcp->base);
  141.  
  142.    if (pdraw == NULL || pread == NULL)
  143.       return GLXBadDrawable;
  144.  
  145.    if (!(*psc->core->bindContext) (pcp->driContext,
  146.                                    pdraw->driDrawable, pread->driDrawable))
  147.       return GLXBadContext;
  148.  
  149.    return Success;
  150. }
  151.  
  152. static void
  153. dri3_unbind_context(struct glx_context *context, struct glx_context *new)
  154. {
  155.    struct dri3_context *pcp = (struct dri3_context *) context;
  156.    struct dri3_screen *psc = (struct dri3_screen *) pcp->base.psc;
  157.  
  158.    (*psc->core->unbindContext) (pcp->driContext);
  159. }
  160.  
  161. static struct glx_context *
  162. dri3_create_context_attribs(struct glx_screen *base,
  163.                             struct glx_config *config_base,
  164.                             struct glx_context *shareList,
  165.                             unsigned num_attribs,
  166.                             const uint32_t *attribs,
  167.                             unsigned *error)
  168. {
  169.    struct dri3_context *pcp = NULL;
  170.    struct dri3_context *pcp_shared = NULL;
  171.    struct dri3_screen *psc = (struct dri3_screen *) base;
  172.    __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;
  173.    __DRIcontext *shared = NULL;
  174.  
  175.    uint32_t minor_ver = 1;
  176.    uint32_t major_ver = 2;
  177.    uint32_t flags = 0;
  178.    unsigned api;
  179.    int reset = __DRI_CTX_RESET_NO_NOTIFICATION;
  180.    uint32_t ctx_attribs[2 * 5];
  181.    unsigned num_ctx_attribs = 0;
  182.    uint32_t render_type;
  183.  
  184.    /* Remap the GLX tokens to DRI2 tokens.
  185.     */
  186.    if (!dri2_convert_glx_attribs(num_attribs, attribs,
  187.                                  &major_ver, &minor_ver,
  188.                                  &render_type, &flags, &api,
  189.                                  &reset, error))
  190.       goto error_exit;
  191.  
  192.    /* Check the renderType value */
  193.    if (!validate_renderType_against_config(config_base, render_type))
  194.        goto error_exit;
  195.  
  196.    if (shareList) {
  197.       pcp_shared = (struct dri3_context *) shareList;
  198.       shared = pcp_shared->driContext;
  199.    }
  200.  
  201.    pcp = calloc(1, sizeof *pcp);
  202.    if (pcp == NULL) {
  203.       *error = __DRI_CTX_ERROR_NO_MEMORY;
  204.       goto error_exit;
  205.    }
  206.  
  207.    if (!glx_context_init(&pcp->base, &psc->base, &config->base))
  208.       goto error_exit;
  209.  
  210.    ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MAJOR_VERSION;
  211.    ctx_attribs[num_ctx_attribs++] = major_ver;
  212.    ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MINOR_VERSION;
  213.    ctx_attribs[num_ctx_attribs++] = minor_ver;
  214.  
  215.    /* Only send a value when the non-default value is requested.  By doing
  216.     * this we don't have to check the driver's DRI3 version before sending the
  217.     * default value.
  218.     */
  219.    if (reset != __DRI_CTX_RESET_NO_NOTIFICATION) {
  220.       ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_RESET_STRATEGY;
  221.       ctx_attribs[num_ctx_attribs++] = reset;
  222.    }
  223.  
  224.    if (flags != 0) {
  225.       ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_FLAGS;
  226.  
  227.       /* The current __DRI_CTX_FLAG_* values are identical to the
  228.        * GLX_CONTEXT_*_BIT values.
  229.        */
  230.       ctx_attribs[num_ctx_attribs++] = flags;
  231.    }
  232.  
  233.    pcp->driContext =
  234.       (*psc->image_driver->createContextAttribs) (psc->driScreen,
  235.                                                   api,
  236.                                                   config->driConfig,
  237.                                                   shared,
  238.                                                   num_ctx_attribs / 2,
  239.                                                   ctx_attribs,
  240.                                                   error,
  241.                                                   pcp);
  242.  
  243.    if (pcp->driContext == NULL)
  244.       goto error_exit;
  245.  
  246.    pcp->base.vtable = &dri3_context_vtable;
  247.  
  248.    return &pcp->base;
  249.  
  250. error_exit:
  251.    free(pcp);
  252.  
  253.    return NULL;
  254. }
  255.  
  256. static struct glx_context *
  257. dri3_create_context(struct glx_screen *base,
  258.                     struct glx_config *config_base,
  259.                     struct glx_context *shareList, int renderType)
  260. {
  261.    unsigned int error;
  262.  
  263.    return dri3_create_context_attribs(base, config_base, shareList,
  264.                                       0, NULL, &error);
  265. }
  266.  
  267. static void
  268. dri3_free_render_buffer(struct dri3_drawable *pdraw, struct dri3_buffer *buffer);
  269.  
  270. static void
  271. dri3_update_num_back(struct dri3_drawable *priv)
  272. {
  273.    priv->num_back = 1;
  274.    if (priv->flipping) {
  275.       if (!priv->is_pixmap && !(priv->present_capabilities & XCB_PRESENT_CAPABILITY_ASYNC))
  276.          priv->num_back++;
  277.       priv->num_back++;
  278.    }
  279.    if (priv->swap_interval == 0)
  280.       priv->num_back++;
  281. }
  282.  
  283. static void
  284. dri3_destroy_drawable(__GLXDRIdrawable *base)
  285. {
  286.    struct dri3_screen *psc = (struct dri3_screen *) base->psc;
  287.    struct dri3_drawable *pdraw = (struct dri3_drawable *) base;
  288.    xcb_connection_t     *c = XGetXCBConnection(pdraw->base.psc->dpy);
  289.    int i;
  290.  
  291.    (*psc->core->destroyDrawable) (pdraw->driDrawable);
  292.  
  293.    for (i = 0; i < DRI3_NUM_BUFFERS; i++) {
  294.       if (pdraw->buffers[i])
  295.          dri3_free_render_buffer(pdraw, pdraw->buffers[i]);
  296.    }
  297.  
  298.    if (pdraw->special_event)
  299.       xcb_unregister_for_special_event(c, pdraw->special_event);
  300.    free(pdraw);
  301. }
  302.  
  303. static __GLXDRIdrawable *
  304. dri3_create_drawable(struct glx_screen *base, XID xDrawable,
  305.                      GLXDrawable drawable, struct glx_config *config_base)
  306. {
  307.    struct dri3_drawable *pdraw;
  308.    struct dri3_screen *psc = (struct dri3_screen *) base;
  309.    __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;
  310.    GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1;
  311.  
  312.    pdraw = calloc(1, sizeof(*pdraw));
  313.    if (!pdraw)
  314.       return NULL;
  315.  
  316.    pdraw->base.destroyDrawable = dri3_destroy_drawable;
  317.    pdraw->base.xDrawable = xDrawable;
  318.    pdraw->base.drawable = drawable;
  319.    pdraw->base.psc = &psc->base;
  320.    pdraw->swap_interval = 1; /* default may be overridden below */
  321.    pdraw->have_back = 0;
  322.    pdraw->have_fake_front = 0;
  323.  
  324.    if (psc->config)
  325.       psc->config->configQueryi(psc->driScreen,
  326.                                 "vblank_mode", &vblank_mode);
  327.  
  328.    switch (vblank_mode) {
  329.    case DRI_CONF_VBLANK_NEVER:
  330.    case DRI_CONF_VBLANK_DEF_INTERVAL_0:
  331.       pdraw->swap_interval = 0;
  332.       break;
  333.    case DRI_CONF_VBLANK_DEF_INTERVAL_1:
  334.    case DRI_CONF_VBLANK_ALWAYS_SYNC:
  335.    default:
  336.       pdraw->swap_interval = 1;
  337.       break;
  338.    }
  339.  
  340.    dri3_update_num_back(pdraw);
  341.  
  342.    (void) __glXInitialize(psc->base.dpy);
  343.  
  344.    /* Create a new drawable */
  345.    pdraw->driDrawable =
  346.       (*psc->image_driver->createNewDrawable) (psc->driScreen,
  347.                                                config->driConfig, pdraw);
  348.  
  349.    if (!pdraw->driDrawable) {
  350.       free(pdraw);
  351.       return NULL;
  352.    }
  353.  
  354.    /*
  355.     * Make sure server has the same swap interval we do for the new
  356.     * drawable.
  357.     */
  358.    if (psc->vtable.setSwapInterval)
  359.       psc->vtable.setSwapInterval(&pdraw->base, pdraw->swap_interval);
  360.  
  361.    return &pdraw->base;
  362. }
  363.  
  364. static void
  365. show_fps(struct dri3_drawable *draw, uint64_t current_ust)
  366. {
  367.    const uint64_t interval =
  368.       ((struct dri3_screen *) draw->base.psc)->show_fps_interval;
  369.  
  370.    draw->frames++;
  371.  
  372.    /* DRI3+Present together uses microseconds for UST. */
  373.    if (draw->previous_ust + interval * 1000000 <= current_ust) {
  374.       if (draw->previous_ust) {
  375.          fprintf(stderr, "libGL: FPS = %.1f\n",
  376.                  ((uint64_t) draw->frames * 1000000) /
  377.                  (double)(current_ust - draw->previous_ust));
  378.       }
  379.       draw->frames = 0;
  380.       draw->previous_ust = current_ust;
  381.    }
  382. }
  383.  
  384. /*
  385.  * Process one Present event
  386.  */
  387. static void
  388. dri3_handle_present_event(struct dri3_drawable *priv, xcb_present_generic_event_t *ge)
  389. {
  390.    struct dri3_screen *psc = (struct dri3_screen *) priv->base.psc;
  391.  
  392.    switch (ge->evtype) {
  393.    case XCB_PRESENT_CONFIGURE_NOTIFY: {
  394.       xcb_present_configure_notify_event_t *ce = (void *) ge;
  395.  
  396.       priv->width = ce->width;
  397.       priv->height = ce->height;
  398.       break;
  399.    }
  400.    case XCB_PRESENT_COMPLETE_NOTIFY: {
  401.       xcb_present_complete_notify_event_t *ce = (void *) ge;
  402.  
  403.       /* Compute the processed SBC number from the received 32-bit serial number merged
  404.        * with the upper 32-bits of the sent 64-bit serial number while checking for
  405.        * wrap
  406.        */
  407.       if (ce->kind == XCB_PRESENT_COMPLETE_KIND_PIXMAP) {
  408.          priv->recv_sbc = (priv->send_sbc & 0xffffffff00000000LL) | ce->serial;
  409.          if (priv->recv_sbc > priv->send_sbc)
  410.             priv->recv_sbc -= 0x100000000;
  411.          switch (ce->mode) {
  412.          case XCB_PRESENT_COMPLETE_MODE_FLIP:
  413.             priv->flipping = true;
  414.             break;
  415.          case XCB_PRESENT_COMPLETE_MODE_COPY:
  416.             priv->flipping = false;
  417.             break;
  418.          }
  419.          dri3_update_num_back(priv);
  420.  
  421.          if (psc->show_fps_interval)
  422.             show_fps(priv, ce->ust);
  423.  
  424.          priv->ust = ce->ust;
  425.          priv->msc = ce->msc;
  426.       } else {
  427.          priv->recv_msc_serial = ce->serial;
  428.          priv->notify_ust = ce->ust;
  429.          priv->notify_msc = ce->msc;
  430.       }
  431.       break;
  432.    }
  433.    case XCB_PRESENT_EVENT_IDLE_NOTIFY: {
  434.       xcb_present_idle_notify_event_t *ie = (void *) ge;
  435.       int b;
  436.  
  437.       for (b = 0; b < sizeof (priv->buffers) / sizeof (priv->buffers[0]); b++) {
  438.          struct dri3_buffer        *buf = priv->buffers[b];
  439.  
  440.          if (buf && buf->pixmap == ie->pixmap) {
  441.             buf->busy = 0;
  442.             if (priv->num_back <= b && b < DRI3_MAX_BACK) {
  443.                dri3_free_render_buffer(priv, buf);
  444.                priv->buffers[b] = NULL;
  445.             }
  446.             break;
  447.          }
  448.       }
  449.       break;
  450.    }
  451.    }
  452.    free(ge);
  453. }
  454.  
  455. static bool
  456. dri3_wait_for_event(__GLXDRIdrawable *pdraw)
  457. {
  458.    xcb_connection_t *c = XGetXCBConnection(pdraw->psc->dpy);
  459.    struct dri3_drawable *priv = (struct dri3_drawable *) pdraw;
  460.    xcb_generic_event_t *ev;
  461.    xcb_present_generic_event_t *ge;
  462.  
  463.    xcb_flush(c);
  464.    ev = xcb_wait_for_special_event(c, priv->special_event);
  465.    if (!ev)
  466.       return false;
  467.    ge = (void *) ev;
  468.    dri3_handle_present_event(priv, ge);
  469.    return true;
  470. }
  471.  
  472. /** dri3_wait_for_msc
  473.  *
  474.  * Get the X server to send an event when the target msc/divisor/remainder is
  475.  * reached.
  476.  */
  477. static int
  478. dri3_wait_for_msc(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
  479.                   int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc)
  480. {
  481.    xcb_connection_t *c = XGetXCBConnection(pdraw->psc->dpy);
  482.    struct dri3_drawable *priv = (struct dri3_drawable *) pdraw;
  483.    uint32_t msc_serial;
  484.  
  485.    /* Ask for the an event for the target MSC */
  486.    msc_serial = ++priv->send_msc_serial;
  487.    xcb_present_notify_msc(c,
  488.                           priv->base.xDrawable,
  489.                           msc_serial,
  490.                           target_msc,
  491.                           divisor,
  492.                           remainder);
  493.  
  494.    xcb_flush(c);
  495.  
  496.    /* Wait for the event */
  497.    if (priv->special_event) {
  498.       while ((int32_t) (msc_serial - priv->recv_msc_serial) > 0) {
  499.          if (!dri3_wait_for_event(pdraw))
  500.             return 0;
  501.       }
  502.    }
  503.  
  504.    *ust = priv->notify_ust;
  505.    *msc = priv->notify_msc;
  506.    *sbc = priv->recv_sbc;
  507.  
  508.    return 1;
  509. }
  510.  
  511. /** dri3_drawable_get_msc
  512.  *
  513.  * Return the current UST/MSC/SBC triplet by asking the server
  514.  * for an event
  515.  */
  516. static int
  517. dri3_drawable_get_msc(struct glx_screen *psc, __GLXDRIdrawable *pdraw,
  518.                       int64_t *ust, int64_t *msc, int64_t *sbc)
  519. {
  520.    return dri3_wait_for_msc(pdraw, 0, 0, 0, ust, msc,sbc);
  521. }
  522.  
  523. /** dri3_wait_for_sbc
  524.  *
  525.  * Wait for the completed swap buffer count to reach the specified
  526.  * target. Presumably the application knows that this will be reached with
  527.  * outstanding complete events, or we're going to be here awhile.
  528.  */
  529. static int
  530. dri3_wait_for_sbc(__GLXDRIdrawable *pdraw, int64_t target_sbc, int64_t *ust,
  531.                   int64_t *msc, int64_t *sbc)
  532. {
  533.    struct dri3_drawable *priv = (struct dri3_drawable *) pdraw;
  534.  
  535.    /* From the GLX_OML_sync_control spec:
  536.     *
  537.     *     "If <target_sbc> = 0, the function will block until all previous
  538.     *      swaps requested with glXSwapBuffersMscOML for that window have
  539.     *      completed."
  540.     */
  541.    if (!target_sbc)
  542.       target_sbc = priv->send_sbc;
  543.  
  544.    while (priv->recv_sbc < target_sbc) {
  545.       if (!dri3_wait_for_event(pdraw))
  546.          return 0;
  547.    }
  548.  
  549.    *ust = priv->ust;
  550.    *msc = priv->msc;
  551.    *sbc = priv->recv_sbc;
  552.    return 1;
  553. }
  554.  
  555. /**
  556.  * Asks the driver to flush any queued work necessary for serializing with the
  557.  * X command stream, and optionally the slightly more strict requirement of
  558.  * glFlush() equivalence (which would require flushing even if nothing had
  559.  * been drawn to a window system framebuffer, for example).
  560.  */
  561. static void
  562. dri3_flush(struct dri3_screen *psc,
  563.            struct dri3_drawable *draw,
  564.            unsigned flags,
  565.            enum __DRI2throttleReason throttle_reason)
  566. {
  567.    struct glx_context *gc = __glXGetCurrentContext();
  568.  
  569.    if (gc) {
  570.       struct dri3_context *dri3Ctx = (struct dri3_context *)gc;
  571.  
  572.       (*psc->f->flush_with_flags)(dri3Ctx->driContext, draw->driDrawable, flags, throttle_reason);
  573.    }
  574. }
  575.  
  576. static xcb_gcontext_t
  577. dri3_drawable_gc(struct dri3_drawable *priv)
  578. {
  579.    if (!priv->gc) {
  580.       uint32_t v;
  581.       xcb_connection_t *c = XGetXCBConnection(priv->base.psc->dpy);
  582.  
  583.       v = 0;
  584.       xcb_create_gc(c,
  585.                     (priv->gc = xcb_generate_id(c)),
  586.                     priv->base.xDrawable,
  587.                     XCB_GC_GRAPHICS_EXPOSURES,
  588.                     &v);
  589.    }
  590.    return priv->gc;
  591. }
  592.  
  593. static struct dri3_buffer *
  594. dri3_back_buffer(struct dri3_drawable *priv)
  595. {
  596.    return priv->buffers[DRI3_BACK_ID(priv->cur_back)];
  597. }
  598.  
  599. static struct dri3_buffer *
  600. dri3_fake_front_buffer(struct dri3_drawable *priv)
  601. {
  602.    return priv->buffers[DRI3_FRONT_ID];
  603. }
  604.  
  605. static void
  606. dri3_copy_area (xcb_connection_t *c  /**< */,
  607.                 xcb_drawable_t    src_drawable  /**< */,
  608.                 xcb_drawable_t    dst_drawable  /**< */,
  609.                 xcb_gcontext_t    gc  /**< */,
  610.                 int16_t           src_x  /**< */,
  611.                 int16_t           src_y  /**< */,
  612.                 int16_t           dst_x  /**< */,
  613.                 int16_t           dst_y  /**< */,
  614.                 uint16_t          width  /**< */,
  615.                 uint16_t          height  /**< */)
  616. {
  617.    xcb_void_cookie_t cookie;
  618.  
  619.    cookie = xcb_copy_area_checked(c,
  620.                                   src_drawable,
  621.                                   dst_drawable,
  622.                                   gc,
  623.                                   src_x,
  624.                                   src_y,
  625.                                   dst_x,
  626.                                   dst_y,
  627.                                   width,
  628.                                   height);
  629.    xcb_discard_reply(c, cookie.sequence);
  630. }
  631.  
  632. static void
  633. dri3_copy_sub_buffer(__GLXDRIdrawable *pdraw, int x, int y,
  634.                      int width, int height,
  635.                      Bool flush)
  636. {
  637.    struct dri3_drawable *priv = (struct dri3_drawable *) pdraw;
  638.    struct dri3_screen *psc = (struct dri3_screen *) pdraw->psc;
  639.    struct dri3_context *pcp = (struct dri3_context *) __glXGetCurrentContext();
  640.    xcb_connection_t     *c = XGetXCBConnection(priv->base.psc->dpy);
  641.    struct dri3_buffer *back;
  642.  
  643.    unsigned flags = __DRI2_FLUSH_DRAWABLE;
  644.  
  645.    /* Check we have the right attachments */
  646.    if (!priv->have_back || priv->is_pixmap)
  647.       return;
  648.  
  649.    if (flush)
  650.       flags |= __DRI2_FLUSH_CONTEXT;
  651.    dri3_flush(psc, priv, flags, __DRI2_THROTTLE_SWAPBUFFER);
  652.  
  653.    back = dri3_back_buffer(priv);
  654.    y = priv->height - y - height;
  655.  
  656.    if (psc->is_different_gpu && (&pcp->base != &dummyContext) && pcp->base.psc == &psc->base) {
  657.       /* Update the linear buffer part of the back buffer
  658.        * for the dri3_copy_area operation
  659.        */
  660.       psc->image->blitImage(pcp->driContext,
  661.                             back->linear_buffer,
  662.                             back->image,
  663.                             0, 0, back->width,
  664.                             back->height,
  665.                             0, 0, back->width,
  666.                             back->height, __BLIT_FLAG_FLUSH);
  667.       /* We use blitImage to update our fake front,
  668.        */
  669.       if (priv->have_fake_front)
  670.          psc->image->blitImage(pcp->driContext,
  671.                                dri3_fake_front_buffer(priv)->image,
  672.                                back->image,
  673.                                x, y, width, height,
  674.                                x, y, width, height, __BLIT_FLAG_FLUSH);
  675.    }
  676.  
  677.    dri3_fence_reset(c, back);
  678.    dri3_copy_area(c,
  679.                   dri3_back_buffer(priv)->pixmap,
  680.                   priv->base.xDrawable,
  681.                   dri3_drawable_gc(priv),
  682.                   x, y, x, y, width, height);
  683.    dri3_fence_trigger(c, back);
  684.    /* Refresh the fake front (if present) after we just damaged the real
  685.     * front.
  686.     */
  687.    if (priv->have_fake_front && !psc->is_different_gpu) {
  688.       dri3_fence_reset(c, dri3_fake_front_buffer(priv));
  689.       dri3_copy_area(c,
  690.                      dri3_back_buffer(priv)->pixmap,
  691.                      dri3_fake_front_buffer(priv)->pixmap,
  692.                      dri3_drawable_gc(priv),
  693.                      x, y, x, y, width, height);
  694.       dri3_fence_trigger(c, dri3_fake_front_buffer(priv));
  695.       dri3_fence_await(c, dri3_fake_front_buffer(priv));
  696.    }
  697.    dri3_fence_await(c, back);
  698. }
  699.  
  700. static void
  701. dri3_copy_drawable(struct dri3_drawable *priv, Drawable dest, Drawable src)
  702. {
  703.    struct dri3_screen *psc = (struct dri3_screen *) priv->base.psc;
  704.    xcb_connection_t     *c = XGetXCBConnection(priv->base.psc->dpy);
  705.  
  706.    dri3_flush(psc, priv, __DRI2_FLUSH_DRAWABLE, 0);
  707.  
  708.    dri3_fence_reset(c, dri3_fake_front_buffer(priv));
  709.    dri3_copy_area(c,
  710.                   src, dest,
  711.                   dri3_drawable_gc(priv),
  712.                   0, 0, 0, 0, priv->width, priv->height);
  713.    dri3_fence_trigger(c, dri3_fake_front_buffer(priv));
  714.    dri3_fence_await(c, dri3_fake_front_buffer(priv));
  715. }
  716.  
  717. static void
  718. dri3_wait_x(struct glx_context *gc)
  719. {
  720.    struct dri3_context *pcp = (struct dri3_context *) gc;
  721.    struct dri3_drawable *priv = (struct dri3_drawable *)
  722.       GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable);
  723.    struct dri3_screen *psc;
  724.    struct dri3_buffer *front;
  725.  
  726.    if (priv == NULL || !priv->have_fake_front)
  727.       return;
  728.  
  729.    psc = (struct dri3_screen *) priv->base.psc;
  730.    front = dri3_fake_front_buffer(priv);
  731.  
  732.    dri3_copy_drawable(priv, front->pixmap, priv->base.xDrawable);
  733.  
  734.    /* In the psc->is_different_gpu case, the linear buffer has been updated,
  735.     * but not yet the tiled buffer.
  736.     * Copy back to the tiled buffer we use for rendering.
  737.     * Note that we don't need flushing.
  738.     */
  739.    if (psc->is_different_gpu && (&pcp->base != &dummyContext) && pcp->base.psc == &psc->base)
  740.       psc->image->blitImage(pcp->driContext,
  741.                             front->image,
  742.                             front->linear_buffer,
  743.                             0, 0, front->width,
  744.                             front->height,
  745.                             0, 0, front->width,
  746.                             front->height, 0);
  747. }
  748.  
  749. static void
  750. dri3_wait_gl(struct glx_context *gc)
  751. {
  752.    struct dri3_context *pcp = (struct dri3_context *) gc;
  753.    struct dri3_drawable *priv = (struct dri3_drawable *)
  754.       GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable);
  755.    struct dri3_screen *psc;
  756.    struct dri3_buffer *front;
  757.  
  758.    if (priv == NULL || !priv->have_fake_front)
  759.       return;
  760.  
  761.    psc = (struct dri3_screen *) priv->base.psc;
  762.    front = dri3_fake_front_buffer(priv);
  763.  
  764.    /* In the psc->is_different_gpu case, we update the linear_buffer
  765.     * before updating the real front.
  766.     */
  767.    if (psc->is_different_gpu && (&pcp->base != &dummyContext) && pcp->base.psc == &psc->base)
  768.       psc->image->blitImage(pcp->driContext,
  769.                             front->linear_buffer,
  770.                             front->image,
  771.                             0, 0, front->width,
  772.                             front->height,
  773.                             0, 0, front->width,
  774.                             front->height, __BLIT_FLAG_FLUSH);
  775.    dri3_copy_drawable(priv, priv->base.xDrawable, front->pixmap);
  776. }
  777.  
  778. /**
  779.  * Called by the driver when it needs to update the real front buffer with the
  780.  * contents of its fake front buffer.
  781.  */
  782. static void
  783. dri3_flush_front_buffer(__DRIdrawable *driDrawable, void *loaderPrivate)
  784. {
  785.    struct glx_context *gc;
  786.    struct dri3_drawable *pdraw = loaderPrivate;
  787.    struct dri3_screen *psc;
  788.  
  789.    if (!pdraw)
  790.       return;
  791.  
  792.    if (!pdraw->base.psc)
  793.       return;
  794.  
  795.    psc = (struct dri3_screen *) pdraw->base.psc;
  796.  
  797.    (void) __glXInitialize(psc->base.dpy);
  798.  
  799.    gc = __glXGetCurrentContext();
  800.  
  801.    dri3_flush(psc, pdraw, __DRI2_FLUSH_DRAWABLE, __DRI2_THROTTLE_FLUSHFRONT);
  802.  
  803.    dri3_wait_gl(gc);
  804. }
  805.  
  806. static uint32_t
  807. dri3_cpp_for_format(uint32_t format) {
  808.    switch (format) {
  809.    case  __DRI_IMAGE_FORMAT_R8:
  810.       return 1;
  811.    case  __DRI_IMAGE_FORMAT_RGB565:
  812.    case  __DRI_IMAGE_FORMAT_GR88:
  813.       return 2;
  814.    case  __DRI_IMAGE_FORMAT_XRGB8888:
  815.    case  __DRI_IMAGE_FORMAT_ARGB8888:
  816.    case  __DRI_IMAGE_FORMAT_ABGR8888:
  817.    case  __DRI_IMAGE_FORMAT_XBGR8888:
  818.    case  __DRI_IMAGE_FORMAT_XRGB2101010:
  819.    case  __DRI_IMAGE_FORMAT_ARGB2101010:
  820.    case  __DRI_IMAGE_FORMAT_SARGB8:
  821.       return 4;
  822.    case  __DRI_IMAGE_FORMAT_NONE:
  823.    default:
  824.       return 0;
  825.    }
  826. }
  827.  
  828.  
  829. /** dri3_alloc_render_buffer
  830.  *
  831.  * Use the driver createImage function to construct a __DRIimage, then
  832.  * get a file descriptor for that and create an X pixmap from that
  833.  *
  834.  * Allocate an xshmfence for synchronization
  835.  */
  836. static struct dri3_buffer *
  837. dri3_alloc_render_buffer(struct glx_screen *glx_screen, Drawable draw,
  838.                          unsigned int format, int width, int height, int depth)
  839. {
  840.    struct dri3_screen *psc = (struct dri3_screen *) glx_screen;
  841.    Display *dpy = glx_screen->dpy;
  842.    struct dri3_buffer *buffer;
  843.    __DRIimage *pixmap_buffer;
  844.    xcb_connection_t *c = XGetXCBConnection(dpy);
  845.    xcb_pixmap_t pixmap;
  846.    xcb_sync_fence_t sync_fence;
  847.    struct xshmfence *shm_fence;
  848.    int buffer_fd, fence_fd;
  849.    int stride;
  850.  
  851.    /* Create an xshmfence object and
  852.     * prepare to send that to the X server
  853.     */
  854.  
  855.    fence_fd = xshmfence_alloc_shm();
  856.    if (fence_fd < 0) {
  857.       ErrorMessageF("DRI3 Fence object allocation failure %s\n", strerror(errno));
  858.       return NULL;
  859.    }
  860.    shm_fence = xshmfence_map_shm(fence_fd);
  861.    if (shm_fence == NULL) {
  862.       ErrorMessageF("DRI3 Fence object map failure %s\n", strerror(errno));
  863.       goto no_shm_fence;
  864.    }
  865.  
  866.    /* Allocate the image from the driver
  867.     */
  868.    buffer = calloc(1, sizeof (struct dri3_buffer));
  869.    if (!buffer)
  870.       goto no_buffer;
  871.  
  872.    buffer->cpp = dri3_cpp_for_format(format);
  873.    if (!buffer->cpp) {
  874.       ErrorMessageF("DRI3 buffer format %d invalid\n", format);
  875.       goto no_image;
  876.    }
  877.  
  878.    if (!psc->is_different_gpu) {
  879.       buffer->image = (*psc->image->createImage) (psc->driScreen,
  880.                                                   width, height,
  881.                                                   format,
  882.                                                   __DRI_IMAGE_USE_SHARE |
  883.                                                   __DRI_IMAGE_USE_SCANOUT,
  884.                                                   buffer);
  885.       pixmap_buffer = buffer->image;
  886.  
  887.       if (!buffer->image) {
  888.          ErrorMessageF("DRI3 gpu image creation failure\n");
  889.          goto no_image;
  890.       }
  891.    } else {
  892.       buffer->image = (*psc->image->createImage) (psc->driScreen,
  893.                                                   width, height,
  894.                                                   format,
  895.                                                   0,
  896.                                                   buffer);
  897.  
  898.       if (!buffer->image) {
  899.          ErrorMessageF("DRI3 other gpu image creation failure\n");
  900.          goto no_image;
  901.       }
  902.  
  903.       buffer->linear_buffer = (*psc->image->createImage) (psc->driScreen,
  904.                                                           width, height,
  905.                                                           format,
  906.                                                           __DRI_IMAGE_USE_SHARE |
  907.                                                           __DRI_IMAGE_USE_LINEAR,
  908.                                                           buffer);
  909.       pixmap_buffer = buffer->linear_buffer;
  910.  
  911.       if (!buffer->linear_buffer) {
  912.          ErrorMessageF("DRI3 gpu linear image creation failure\n");
  913.          goto no_linear_buffer;
  914.       }
  915.    }
  916.  
  917.    /* X wants the stride, so ask the image for it
  918.     */
  919.    if (!(*psc->image->queryImage)(pixmap_buffer, __DRI_IMAGE_ATTRIB_STRIDE, &stride)) {
  920.       ErrorMessageF("DRI3 get image stride failed\n");
  921.       goto no_buffer_attrib;
  922.    }
  923.  
  924.    buffer->pitch = stride;
  925.  
  926.    if (!(*psc->image->queryImage)(pixmap_buffer, __DRI_IMAGE_ATTRIB_FD, &buffer_fd)) {
  927.       ErrorMessageF("DRI3 get image FD failed\n");
  928.       goto no_buffer_attrib;
  929.    }
  930.  
  931.    xcb_dri3_pixmap_from_buffer(c,
  932.                                (pixmap = xcb_generate_id(c)),
  933.                                draw,
  934.                                buffer->size,
  935.                                width, height, buffer->pitch,
  936.                                depth, buffer->cpp * 8,
  937.                                buffer_fd);
  938.  
  939.    xcb_dri3_fence_from_fd(c,
  940.                           pixmap,
  941.                           (sync_fence = xcb_generate_id(c)),
  942.                           false,
  943.                           fence_fd);
  944.  
  945.    buffer->pixmap = pixmap;
  946.    buffer->own_pixmap = true;
  947.    buffer->sync_fence = sync_fence;
  948.    buffer->shm_fence = shm_fence;
  949.    buffer->width = width;
  950.    buffer->height = height;
  951.  
  952.    /* Mark the buffer as idle
  953.     */
  954.    dri3_fence_set(buffer);
  955.  
  956.    return buffer;
  957.  
  958. no_buffer_attrib:
  959.    (*psc->image->destroyImage)(pixmap_buffer);
  960. no_linear_buffer:
  961.    if (psc->is_different_gpu)
  962.       (*psc->image->destroyImage)(buffer->image);
  963. no_image:
  964.    free(buffer);
  965. no_buffer:
  966.    xshmfence_unmap_shm(shm_fence);
  967. no_shm_fence:
  968.    close(fence_fd);
  969.    ErrorMessageF("DRI3 alloc_render_buffer failed\n");
  970.    return NULL;
  971. }
  972.  
  973. /** dri3_free_render_buffer
  974.  *
  975.  * Free everything associated with one render buffer including pixmap, fence
  976.  * stuff and the driver image
  977.  */
  978. static void
  979. dri3_free_render_buffer(struct dri3_drawable *pdraw, struct dri3_buffer *buffer)
  980. {
  981.    struct dri3_screen   *psc = (struct dri3_screen *) pdraw->base.psc;
  982.    xcb_connection_t     *c = XGetXCBConnection(pdraw->base.psc->dpy);
  983.  
  984.    if (buffer->own_pixmap)
  985.       xcb_free_pixmap(c, buffer->pixmap);
  986.    xcb_sync_destroy_fence(c, buffer->sync_fence);
  987.    xshmfence_unmap_shm(buffer->shm_fence);
  988.    (*psc->image->destroyImage)(buffer->image);
  989.    if (buffer->linear_buffer)
  990.       (*psc->image->destroyImage)(buffer->linear_buffer);
  991.    free(buffer);
  992. }
  993.  
  994.  
  995. /** dri3_flush_present_events
  996.  *
  997.  * Process any present events that have been received from the X server
  998.  */
  999. static void
  1000. dri3_flush_present_events(struct dri3_drawable *priv)
  1001. {
  1002.    xcb_connection_t     *c = XGetXCBConnection(priv->base.psc->dpy);
  1003.  
  1004.    /* Check to see if any configuration changes have occurred
  1005.     * since we were last invoked
  1006.     */
  1007.    if (priv->special_event) {
  1008.       xcb_generic_event_t    *ev;
  1009.  
  1010.       while ((ev = xcb_poll_for_special_event(c, priv->special_event)) != NULL) {
  1011.          xcb_present_generic_event_t *ge = (void *) ev;
  1012.          dri3_handle_present_event(priv, ge);
  1013.       }
  1014.    }
  1015. }
  1016.  
  1017. /** dri3_update_drawable
  1018.  *
  1019.  * Called the first time we use the drawable and then
  1020.  * after we receive present configure notify events to
  1021.  * track the geometry of the drawable
  1022.  */
  1023. static int
  1024. dri3_update_drawable(__DRIdrawable *driDrawable, void *loaderPrivate)
  1025. {
  1026.    struct dri3_drawable *priv = loaderPrivate;
  1027.    xcb_connection_t     *c = XGetXCBConnection(priv->base.psc->dpy);
  1028.  
  1029.    /* First time through, go get the current drawable geometry
  1030.     */
  1031.    if (priv->width == 0 || priv->height == 0 || priv->depth == 0) {
  1032.       xcb_get_geometry_cookie_t                 geom_cookie;
  1033.       xcb_get_geometry_reply_t                  *geom_reply;
  1034.       xcb_void_cookie_t                         cookie;
  1035.       xcb_generic_error_t                       *error;
  1036.       xcb_present_query_capabilities_cookie_t   present_capabilities_cookie;
  1037.       xcb_present_query_capabilities_reply_t    *present_capabilities_reply;
  1038.  
  1039.  
  1040.       /* Try to select for input on the window.
  1041.        *
  1042.        * If the drawable is a window, this will get our events
  1043.        * delivered.
  1044.        *
  1045.        * Otherwise, we'll get a BadWindow error back from this request which
  1046.        * will let us know that the drawable is a pixmap instead.
  1047.        */
  1048.  
  1049.  
  1050.       cookie = xcb_present_select_input_checked(c,
  1051.                                                 (priv->eid = xcb_generate_id(c)),
  1052.                                                 priv->base.xDrawable,
  1053.                                                 XCB_PRESENT_EVENT_MASK_CONFIGURE_NOTIFY|
  1054.                                                 XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY|
  1055.                                                 XCB_PRESENT_EVENT_MASK_IDLE_NOTIFY);
  1056.  
  1057.       present_capabilities_cookie = xcb_present_query_capabilities(c, priv->base.xDrawable);
  1058.  
  1059.       /* Create an XCB event queue to hold present events outside of the usual
  1060.        * application event queue
  1061.        */
  1062.       priv->special_event = xcb_register_for_special_xge(c,
  1063.                                                          &xcb_present_id,
  1064.                                                          priv->eid,
  1065.                                                          priv->stamp);
  1066.  
  1067.       geom_cookie = xcb_get_geometry(c, priv->base.xDrawable);
  1068.  
  1069.       geom_reply = xcb_get_geometry_reply(c, geom_cookie, NULL);
  1070.  
  1071.       if (!geom_reply)
  1072.          return false;
  1073.  
  1074.       priv->width = geom_reply->width;
  1075.       priv->height = geom_reply->height;
  1076.       priv->depth = geom_reply->depth;
  1077.       priv->is_pixmap = false;
  1078.  
  1079.       free(geom_reply);
  1080.  
  1081.       /* Check to see if our select input call failed. If it failed with a
  1082.        * BadWindow error, then assume the drawable is a pixmap. Destroy the
  1083.        * special event queue created above and mark the drawable as a pixmap
  1084.        */
  1085.  
  1086.       error = xcb_request_check(c, cookie);
  1087.  
  1088.       present_capabilities_reply = xcb_present_query_capabilities_reply(c,
  1089.                                                                         present_capabilities_cookie,
  1090.                                                                         NULL);
  1091.  
  1092.       if (present_capabilities_reply) {
  1093.          priv->present_capabilities = present_capabilities_reply->capabilities;
  1094.          free(present_capabilities_reply);
  1095.       } else
  1096.          priv->present_capabilities = 0;
  1097.  
  1098.       if (error) {
  1099.          if (error->error_code != BadWindow) {
  1100.             free(error);
  1101.             return false;
  1102.          }
  1103.          priv->is_pixmap = true;
  1104.          xcb_unregister_for_special_event(c, priv->special_event);
  1105.          priv->special_event = NULL;
  1106.       }
  1107.    }
  1108.    dri3_flush_present_events(priv);
  1109.    return true;
  1110. }
  1111.  
  1112. /* the DRIimage createImage function takes __DRI_IMAGE_FORMAT codes, while
  1113.  * the createImageFromFds call takes __DRI_IMAGE_FOURCC codes. To avoid
  1114.  * complete confusion, just deal in __DRI_IMAGE_FORMAT codes for now and
  1115.  * translate to __DRI_IMAGE_FOURCC codes in the call to createImageFromFds
  1116.  */
  1117. static int
  1118. image_format_to_fourcc(int format)
  1119. {
  1120.  
  1121.    /* Convert from __DRI_IMAGE_FORMAT to __DRI_IMAGE_FOURCC (sigh) */
  1122.    switch (format) {
  1123.    case __DRI_IMAGE_FORMAT_SARGB8: return __DRI_IMAGE_FOURCC_SARGB8888;
  1124.    case __DRI_IMAGE_FORMAT_RGB565: return __DRI_IMAGE_FOURCC_RGB565;
  1125.    case __DRI_IMAGE_FORMAT_XRGB8888: return __DRI_IMAGE_FOURCC_XRGB8888;
  1126.    case __DRI_IMAGE_FORMAT_ARGB8888: return __DRI_IMAGE_FOURCC_ARGB8888;
  1127.    case __DRI_IMAGE_FORMAT_ABGR8888: return __DRI_IMAGE_FOURCC_ABGR8888;
  1128.    case __DRI_IMAGE_FORMAT_XBGR8888: return __DRI_IMAGE_FOURCC_XBGR8888;
  1129.    }
  1130.    return 0;
  1131. }
  1132.  
  1133. /** dri3_get_pixmap_buffer
  1134.  *
  1135.  * Get the DRM object for a pixmap from the X server and
  1136.  * wrap that with a __DRIimage structure using createImageFromFds
  1137.  */
  1138. static struct dri3_buffer *
  1139. dri3_get_pixmap_buffer(__DRIdrawable *driDrawable,
  1140.                        unsigned int format,
  1141.                        enum dri3_buffer_type buffer_type,
  1142.                        void *loaderPrivate)
  1143. {
  1144.    struct dri3_drawable                 *pdraw = loaderPrivate;
  1145.    int                                  buf_id = dri3_pixmap_buf_id(buffer_type);
  1146.    struct dri3_buffer                   *buffer = pdraw->buffers[buf_id];
  1147.    Pixmap                               pixmap;
  1148.    xcb_dri3_buffer_from_pixmap_cookie_t bp_cookie;
  1149.    xcb_dri3_buffer_from_pixmap_reply_t  *bp_reply;
  1150.    int                                  *fds;
  1151.    Display                              *dpy;
  1152.    struct dri3_screen                   *psc;
  1153.    xcb_connection_t                     *c;
  1154.    xcb_sync_fence_t                     sync_fence;
  1155.    struct xshmfence                     *shm_fence;
  1156.    int                                  fence_fd;
  1157.    __DRIimage                           *image_planar;
  1158.    int                                  stride, offset;
  1159.  
  1160.    if (buffer)
  1161.       return buffer;
  1162.  
  1163.    pixmap = pdraw->base.xDrawable;
  1164.    psc = (struct dri3_screen *) pdraw->base.psc;
  1165.    dpy = psc->base.dpy;
  1166.    c = XGetXCBConnection(dpy);
  1167.  
  1168.    buffer = calloc(1, sizeof (struct dri3_buffer));
  1169.    if (!buffer)
  1170.       goto no_buffer;
  1171.  
  1172.    fence_fd = xshmfence_alloc_shm();
  1173.    if (fence_fd < 0)
  1174.       goto no_fence;
  1175.    shm_fence = xshmfence_map_shm(fence_fd);
  1176.    if (shm_fence == NULL) {
  1177.       close (fence_fd);
  1178.       goto no_fence;
  1179.    }
  1180.  
  1181.    xcb_dri3_fence_from_fd(c,
  1182.                           pixmap,
  1183.                           (sync_fence = xcb_generate_id(c)),
  1184.                           false,
  1185.                           fence_fd);
  1186.  
  1187.    /* Get an FD for the pixmap object
  1188.     */
  1189.    bp_cookie = xcb_dri3_buffer_from_pixmap(c, pixmap);
  1190.    bp_reply = xcb_dri3_buffer_from_pixmap_reply(c, bp_cookie, NULL);
  1191.    if (!bp_reply)
  1192.       goto no_image;
  1193.    fds = xcb_dri3_buffer_from_pixmap_reply_fds(c, bp_reply);
  1194.  
  1195.    stride = bp_reply->stride;
  1196.    offset = 0;
  1197.  
  1198.    /* createImageFromFds creates a wrapper __DRIimage structure which
  1199.     * can deal with multiple planes for things like Yuv images. So, once
  1200.     * we've gotten the planar wrapper, pull the single plane out of it and
  1201.     * discard the wrapper.
  1202.     */
  1203.    image_planar = (*psc->image->createImageFromFds) (psc->driScreen,
  1204.                                                      bp_reply->width,
  1205.                                                      bp_reply->height,
  1206.                                                      image_format_to_fourcc(format),
  1207.                                                      fds, 1,
  1208.                                                      &stride, &offset, buffer);
  1209.    close(fds[0]);
  1210.    if (!image_planar)
  1211.       goto no_image;
  1212.  
  1213.    buffer->image = (*psc->image->fromPlanar)(image_planar, 0, buffer);
  1214.  
  1215.    (*psc->image->destroyImage)(image_planar);
  1216.  
  1217.    if (!buffer->image)
  1218.       goto no_image;
  1219.  
  1220.    buffer->pixmap = pixmap;
  1221.    buffer->own_pixmap = false;
  1222.    buffer->width = bp_reply->width;
  1223.    buffer->height = bp_reply->height;
  1224.    buffer->buffer_type = buffer_type;
  1225.    buffer->shm_fence = shm_fence;
  1226.    buffer->sync_fence = sync_fence;
  1227.  
  1228.    pdraw->buffers[buf_id] = buffer;
  1229.    return buffer;
  1230.  
  1231. no_image:
  1232.    xcb_sync_destroy_fence(c, sync_fence);
  1233.    xshmfence_unmap_shm(shm_fence);
  1234. no_fence:
  1235.    free(buffer);
  1236. no_buffer:
  1237.    return NULL;
  1238. }
  1239.  
  1240. /** dri3_find_back
  1241.  *
  1242.  * Find an idle back buffer. If there isn't one, then
  1243.  * wait for a present idle notify event from the X server
  1244.  */
  1245. static int
  1246. dri3_find_back(xcb_connection_t *c, struct dri3_drawable *priv)
  1247. {
  1248.    int  b;
  1249.    xcb_generic_event_t *ev;
  1250.    xcb_present_generic_event_t *ge;
  1251.  
  1252.    for (;;) {
  1253.       for (b = 0; b < priv->num_back; b++) {
  1254.          int id = DRI3_BACK_ID((b + priv->cur_back) % priv->num_back);
  1255.          struct dri3_buffer *buffer = priv->buffers[id];
  1256.  
  1257.          if (!buffer || !buffer->busy) {
  1258.             priv->cur_back = id;
  1259.             return id;
  1260.          }
  1261.       }
  1262.       xcb_flush(c);
  1263.       ev = xcb_wait_for_special_event(c, priv->special_event);
  1264.       if (!ev)
  1265.          return -1;
  1266.       ge = (void *) ev;
  1267.       dri3_handle_present_event(priv, ge);
  1268.    }
  1269. }
  1270.  
  1271. /** dri3_get_buffer
  1272.  *
  1273.  * Find a front or back buffer, allocating new ones as necessary
  1274.  */
  1275. static struct dri3_buffer *
  1276. dri3_get_buffer(__DRIdrawable *driDrawable,
  1277.                 unsigned int format,
  1278.                 enum dri3_buffer_type buffer_type,
  1279.                 void *loaderPrivate)
  1280. {
  1281.    struct dri3_context *pcp = (struct dri3_context *) __glXGetCurrentContext();
  1282.    struct dri3_drawable *priv = loaderPrivate;
  1283.    struct dri3_screen *psc = (struct dri3_screen *) priv->base.psc;
  1284.    xcb_connection_t     *c = XGetXCBConnection(priv->base.psc->dpy);
  1285.    struct dri3_buffer      *buffer;
  1286.    int                  buf_id;
  1287.  
  1288.    if (buffer_type == dri3_buffer_back) {
  1289.       buf_id = dri3_find_back(c, priv);
  1290.  
  1291.       if (buf_id < 0)
  1292.          return NULL;
  1293.    } else {
  1294.       buf_id = DRI3_FRONT_ID;
  1295.    }
  1296.  
  1297.    buffer = priv->buffers[buf_id];
  1298.  
  1299.    /* Allocate a new buffer if there isn't an old one, or if that
  1300.     * old one is the wrong size
  1301.     */
  1302.    if (!buffer || buffer->width != priv->width || buffer->height != priv->height) {
  1303.       struct dri3_buffer   *new_buffer;
  1304.  
  1305.       /* Allocate the new buffers
  1306.        */
  1307.       new_buffer = dri3_alloc_render_buffer(priv->base.psc,
  1308.                                             priv->base.xDrawable,
  1309.                                             format, priv->width, priv->height, priv->depth);
  1310.       if (!new_buffer)
  1311.          return NULL;
  1312.  
  1313.       /* When resizing, copy the contents of the old buffer, waiting for that
  1314.        * copy to complete using our fences before proceeding
  1315.        */
  1316.       switch (buffer_type) {
  1317.       case dri3_buffer_back:
  1318.          if (buffer) {
  1319.             if (!buffer->linear_buffer) {
  1320.                dri3_fence_reset(c, new_buffer);
  1321.                dri3_fence_await(c, buffer);
  1322.                dri3_copy_area(c,
  1323.                               buffer->pixmap,
  1324.                               new_buffer->pixmap,
  1325.                               dri3_drawable_gc(priv),
  1326.                               0, 0, 0, 0, priv->width, priv->height);
  1327.             dri3_fence_trigger(c, new_buffer);
  1328.             } else if ((&pcp->base != &dummyContext) && pcp->base.psc == &psc->base) {
  1329.                psc->image->blitImage(pcp->driContext,
  1330.                                      new_buffer->image,
  1331.                                      buffer->image,
  1332.                                      0, 0, priv->width,
  1333.                                      priv->height,
  1334.                                      0, 0, priv->width,
  1335.                                      priv->height, 0);
  1336.             }
  1337.             dri3_free_render_buffer(priv, buffer);
  1338.          }
  1339.          break;
  1340.       case dri3_buffer_front:
  1341.          dri3_fence_reset(c, new_buffer);
  1342.          dri3_copy_area(c,
  1343.                         priv->base.xDrawable,
  1344.                         new_buffer->pixmap,
  1345.                         dri3_drawable_gc(priv),
  1346.                         0, 0, 0, 0, priv->width, priv->height);
  1347.          dri3_fence_trigger(c, new_buffer);
  1348.  
  1349.          if (new_buffer->linear_buffer && (&pcp->base != &dummyContext) && pcp->base.psc == &psc->base) {
  1350.             dri3_fence_await(c, new_buffer);
  1351.             psc->image->blitImage(pcp->driContext,
  1352.                                   new_buffer->image,
  1353.                                   new_buffer->linear_buffer,
  1354.                                   0, 0, priv->width,
  1355.                                   priv->height,
  1356.                                   0, 0, priv->width,
  1357.                                   priv->height, 0);
  1358.          }
  1359.          break;
  1360.       }
  1361.       buffer = new_buffer;
  1362.       buffer->buffer_type = buffer_type;
  1363.       priv->buffers[buf_id] = buffer;
  1364.    }
  1365.    dri3_fence_await(c, buffer);
  1366.  
  1367.    /* Return the requested buffer */
  1368.    return buffer;
  1369. }
  1370.  
  1371. /** dri3_free_buffers
  1372.  *
  1373.  * Free the front bufffer or all of the back buffers. Used
  1374.  * when the application changes which buffers it needs
  1375.  */
  1376. static void
  1377. dri3_free_buffers(__DRIdrawable *driDrawable,
  1378.                  enum dri3_buffer_type buffer_type,
  1379.                  void *loaderPrivate)
  1380. {
  1381.    struct dri3_drawable *priv = loaderPrivate;
  1382.    struct dri3_buffer      *buffer;
  1383.    int                  first_id;
  1384.    int                  n_id;
  1385.    int                  buf_id;
  1386.  
  1387.    switch (buffer_type) {
  1388.    case dri3_buffer_back:
  1389.       first_id = DRI3_BACK_ID(0);
  1390.       n_id = DRI3_MAX_BACK;
  1391.       break;
  1392.    case dri3_buffer_front:
  1393.       first_id = DRI3_FRONT_ID;
  1394.       n_id = 1;
  1395.    }
  1396.  
  1397.    for (buf_id = first_id; buf_id < first_id + n_id; buf_id++) {
  1398.       buffer = priv->buffers[buf_id];
  1399.       if (buffer) {
  1400.          dri3_free_render_buffer(priv, buffer);
  1401.          priv->buffers[buf_id] = NULL;
  1402.       }
  1403.    }
  1404. }
  1405.  
  1406. /** dri3_get_buffers
  1407.  *
  1408.  * The published buffer allocation API.
  1409.  * Returns all of the necessary buffers, allocating
  1410.  * as needed.
  1411.  */
  1412. static int
  1413. dri3_get_buffers(__DRIdrawable *driDrawable,
  1414.                  unsigned int format,
  1415.                  uint32_t *stamp,
  1416.                  void *loaderPrivate,
  1417.                  uint32_t buffer_mask,
  1418.                  struct __DRIimageList *buffers)
  1419. {
  1420.    struct dri3_drawable *priv = loaderPrivate;
  1421.    struct dri3_screen *psc = (struct dri3_screen *) priv->base.psc;
  1422.    struct dri3_buffer   *front, *back;
  1423.  
  1424.    buffers->image_mask = 0;
  1425.    buffers->front = NULL;
  1426.    buffers->back = NULL;
  1427.  
  1428.    front = NULL;
  1429.    back = NULL;
  1430.  
  1431.    if (!dri3_update_drawable(driDrawable, loaderPrivate))
  1432.       return false;
  1433.  
  1434.    /* pixmaps always have front buffers */
  1435.    if (priv->is_pixmap)
  1436.       buffer_mask |= __DRI_IMAGE_BUFFER_FRONT;
  1437.  
  1438.    if (buffer_mask & __DRI_IMAGE_BUFFER_FRONT) {
  1439.       /* All pixmaps are owned by the server gpu.
  1440.        * When we use a different gpu, we can't use the pixmap
  1441.        * as buffer since it is potentially tiled a way
  1442.        * our device can't understand. In this case, use
  1443.        * a fake front buffer. Hopefully the pixmap
  1444.        * content will get synced with the fake front
  1445.        * buffer.
  1446.        */
  1447.       if (priv->is_pixmap && !psc->is_different_gpu)
  1448.          front = dri3_get_pixmap_buffer(driDrawable,
  1449.                                         format,
  1450.                                         dri3_buffer_front,
  1451.                                         loaderPrivate);
  1452.       else
  1453.          front = dri3_get_buffer(driDrawable,
  1454.                                  format,
  1455.                                  dri3_buffer_front,
  1456.                                  loaderPrivate);
  1457.  
  1458.       if (!front)
  1459.          return false;
  1460.    } else {
  1461.       dri3_free_buffers(driDrawable, dri3_buffer_front, loaderPrivate);
  1462.       priv->have_fake_front = 0;
  1463.    }
  1464.  
  1465.    if (buffer_mask & __DRI_IMAGE_BUFFER_BACK) {
  1466.       back = dri3_get_buffer(driDrawable,
  1467.                              format,
  1468.                              dri3_buffer_back,
  1469.                              loaderPrivate);
  1470.       if (!back)
  1471.          return false;
  1472.       priv->have_back = 1;
  1473.    } else {
  1474.       dri3_free_buffers(driDrawable, dri3_buffer_back, loaderPrivate);
  1475.       priv->have_back = 0;
  1476.    }
  1477.  
  1478.    if (front) {
  1479.       buffers->image_mask |= __DRI_IMAGE_BUFFER_FRONT;
  1480.       buffers->front = front->image;
  1481.       priv->have_fake_front = psc->is_different_gpu || !priv->is_pixmap;
  1482.    }
  1483.  
  1484.    if (back) {
  1485.       buffers->image_mask |= __DRI_IMAGE_BUFFER_BACK;
  1486.       buffers->back = back->image;
  1487.    }
  1488.  
  1489.    priv->stamp = stamp;
  1490.  
  1491.    return true;
  1492. }
  1493.  
  1494. /* The image loader extension record for DRI3
  1495.  */
  1496. static const __DRIimageLoaderExtension imageLoaderExtension = {
  1497.    .base = { __DRI_IMAGE_LOADER, 1 },
  1498.  
  1499.    .getBuffers          = dri3_get_buffers,
  1500.    .flushFrontBuffer    = dri3_flush_front_buffer,
  1501. };
  1502.  
  1503. const __DRIuseInvalidateExtension dri3UseInvalidate = {
  1504.    .base = { __DRI_USE_INVALIDATE, 1 }
  1505. };
  1506.  
  1507. static const __DRIextension *loader_extensions[] = {
  1508.    &imageLoaderExtension.base,
  1509.    &systemTimeExtension.base,
  1510.    &dri3UseInvalidate.base,
  1511.    NULL
  1512. };
  1513.  
  1514. /** dri3_swap_buffers
  1515.  *
  1516.  * Make the current back buffer visible using the present extension
  1517.  */
  1518. static int64_t
  1519. dri3_swap_buffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
  1520.                   int64_t remainder, Bool flush)
  1521. {
  1522.    struct dri3_context *pcp = (struct dri3_context *) __glXGetCurrentContext();
  1523.    struct dri3_drawable *priv = (struct dri3_drawable *) pdraw;
  1524.    struct dri3_screen *psc = (struct dri3_screen *) priv->base.psc;
  1525.    Display *dpy = priv->base.psc->dpy;
  1526.    xcb_connection_t *c = XGetXCBConnection(dpy);
  1527.    struct dri3_buffer *back;
  1528.    int64_t ret = 0;
  1529.    uint32_t options = XCB_PRESENT_OPTION_NONE;
  1530.  
  1531.    unsigned flags = __DRI2_FLUSH_DRAWABLE;
  1532.    if (flush)
  1533.       flags |= __DRI2_FLUSH_CONTEXT;
  1534.    dri3_flush(psc, priv, flags, __DRI2_THROTTLE_SWAPBUFFER);
  1535.  
  1536.    back = priv->buffers[DRI3_BACK_ID(priv->cur_back)];
  1537.    if (psc->is_different_gpu && back) {
  1538.       /* Update the linear buffer before presenting the pixmap */
  1539.       psc->image->blitImage(pcp->driContext,
  1540.                             back->linear_buffer,
  1541.                             back->image,
  1542.                             0, 0, back->width,
  1543.                             back->height,
  1544.                             0, 0, back->width,
  1545.                             back->height, __BLIT_FLAG_FLUSH);
  1546.       /* Update the fake front */
  1547.       if (priv->have_fake_front)
  1548.          psc->image->blitImage(pcp->driContext,
  1549.                                priv->buffers[DRI3_FRONT_ID]->image,
  1550.                                back->image,
  1551.                                0, 0, priv->width,
  1552.                                priv->height,
  1553.                                0, 0, priv->width,
  1554.                                priv->height, __BLIT_FLAG_FLUSH);
  1555.    }
  1556.  
  1557.    dri3_flush_present_events(priv);
  1558.  
  1559.    if (back && !priv->is_pixmap) {
  1560.       dri3_fence_reset(c, back);
  1561.  
  1562.       /* Compute when we want the frame shown by taking the last known successful
  1563.        * MSC and adding in a swap interval for each outstanding swap request.
  1564.        * target_msc=divisor=remainder=0 means "Use glXSwapBuffers() semantic"
  1565.        */
  1566.       ++priv->send_sbc;
  1567.       if (target_msc == 0 && divisor == 0 && remainder == 0)
  1568.          target_msc = priv->msc + priv->swap_interval * (priv->send_sbc - priv->recv_sbc);
  1569.       else if (divisor == 0 && remainder > 0) {
  1570.          /* From the GLX_OML_sync_control spec:
  1571.           *
  1572.           *     "If <divisor> = 0, the swap will occur when MSC becomes
  1573.           *      greater than or equal to <target_msc>."
  1574.           *
  1575.           * Note that there's no mention of the remainder.  The Present extension
  1576.           * throws BadValue for remainder != 0 with divisor == 0, so just drop
  1577.           * the passed in value.
  1578.           */
  1579.          remainder = 0;
  1580.       }
  1581.  
  1582.       /* From the GLX_EXT_swap_control spec:
  1583.        *
  1584.        *     "If <interval> is set to a value of 0, buffer swaps are not
  1585.        *      synchronized to a video frame."
  1586.        *
  1587.        * Implementation note: It is possible to enable triple buffering behaviour
  1588.        * by not using XCB_PRESENT_OPTION_ASYNC, but this should not be the default.
  1589.        */
  1590.       if (priv->swap_interval == 0)
  1591.           options |= XCB_PRESENT_OPTION_ASYNC;
  1592.  
  1593.       back->busy = 1;
  1594.       back->last_swap = priv->send_sbc;
  1595.       xcb_present_pixmap(c,
  1596.                          priv->base.xDrawable,
  1597.                          back->pixmap,
  1598.                          (uint32_t) priv->send_sbc,
  1599.                          0,                                    /* valid */
  1600.                          0,                                    /* update */
  1601.                          0,                                    /* x_off */
  1602.                          0,                                    /* y_off */
  1603.                          None,                                 /* target_crtc */
  1604.                          None,
  1605.                          back->sync_fence,
  1606.                          options,
  1607.                          target_msc,
  1608.                          divisor,
  1609.                          remainder, 0, NULL);
  1610.       ret = (int64_t) priv->send_sbc;
  1611.  
  1612.       /* If there's a fake front, then copy the source back buffer
  1613.        * to the fake front to keep it up to date. This needs
  1614.        * to reset the fence and make future users block until
  1615.        * the X server is done copying the bits
  1616.        */
  1617.       if (priv->have_fake_front && !psc->is_different_gpu) {
  1618.          dri3_fence_reset(c, priv->buffers[DRI3_FRONT_ID]);
  1619.          dri3_copy_area(c,
  1620.                         back->pixmap,
  1621.                         priv->buffers[DRI3_FRONT_ID]->pixmap,
  1622.                         dri3_drawable_gc(priv),
  1623.                         0, 0, 0, 0, priv->width, priv->height);
  1624.          dri3_fence_trigger(c, priv->buffers[DRI3_FRONT_ID]);
  1625.       }
  1626.       xcb_flush(c);
  1627.       if (priv->stamp)
  1628.          ++(*priv->stamp);
  1629.    }
  1630.  
  1631.    (*psc->f->invalidate)(priv->driDrawable);
  1632.  
  1633.    return ret;
  1634. }
  1635.  
  1636. static int
  1637. dri3_get_buffer_age(__GLXDRIdrawable *pdraw)
  1638. {
  1639.    xcb_connection_t *c = XGetXCBConnection(pdraw->psc->dpy);
  1640.    struct dri3_drawable *priv = (struct dri3_drawable *) pdraw;
  1641.    int back_id = DRI3_BACK_ID(dri3_find_back(c, priv));
  1642.  
  1643.    if (back_id < 0 || !priv->buffers[back_id])
  1644.       return 0;
  1645.  
  1646.    if (priv->buffers[back_id]->last_swap != 0)
  1647.       return priv->send_sbc - priv->buffers[back_id]->last_swap + 1;
  1648.    else
  1649.       return 0;
  1650. }
  1651.  
  1652. /** dri3_open
  1653.  *
  1654.  * Wrapper around xcb_dri3_open
  1655.  */
  1656. static int
  1657. dri3_open(Display *dpy,
  1658.           Window root,
  1659.           CARD32 provider)
  1660. {
  1661.    xcb_dri3_open_cookie_t       cookie;
  1662.    xcb_dri3_open_reply_t        *reply;
  1663.    xcb_connection_t             *c = XGetXCBConnection(dpy);
  1664.    int                          fd;
  1665.  
  1666.    cookie = xcb_dri3_open(c,
  1667.                           root,
  1668.                           provider);
  1669.  
  1670.    reply = xcb_dri3_open_reply(c, cookie, NULL);
  1671.    if (!reply)
  1672.       return -1;
  1673.  
  1674.    if (reply->nfd != 1) {
  1675.       free(reply);
  1676.       return -1;
  1677.    }
  1678.  
  1679.    fd = xcb_dri3_open_reply_fds(c, reply)[0];
  1680.    fcntl(fd, F_SETFD, FD_CLOEXEC);
  1681.  
  1682.    return fd;
  1683. }
  1684.  
  1685.  
  1686. /** dri3_destroy_screen
  1687.  */
  1688. static void
  1689. dri3_destroy_screen(struct glx_screen *base)
  1690. {
  1691.    struct dri3_screen *psc = (struct dri3_screen *) base;
  1692.  
  1693.    /* Free the direct rendering per screen data */
  1694.    (*psc->core->destroyScreen) (psc->driScreen);
  1695.    driDestroyConfigs(psc->driver_configs);
  1696.    close(psc->fd);
  1697.    free(psc);
  1698. }
  1699.  
  1700. /** dri3_set_swap_interval
  1701.  *
  1702.  * Record the application swap interval specification,
  1703.  */
  1704. static int
  1705. dri3_set_swap_interval(__GLXDRIdrawable *pdraw, int interval)
  1706. {
  1707.    struct dri3_drawable *priv =  (struct dri3_drawable *) pdraw;
  1708.    GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1;
  1709.    struct dri3_screen *psc = (struct dri3_screen *) priv->base.psc;
  1710.  
  1711.    if (psc->config)
  1712.       psc->config->configQueryi(psc->driScreen,
  1713.                                 "vblank_mode", &vblank_mode);
  1714.  
  1715.    switch (vblank_mode) {
  1716.    case DRI_CONF_VBLANK_NEVER:
  1717.       if (interval != 0)
  1718.          return GLX_BAD_VALUE;
  1719.       break;
  1720.    case DRI_CONF_VBLANK_ALWAYS_SYNC:
  1721.       if (interval <= 0)
  1722.          return GLX_BAD_VALUE;
  1723.       break;
  1724.    default:
  1725.       break;
  1726.    }
  1727.  
  1728.    priv->swap_interval = interval;
  1729.    dri3_update_num_back(priv);
  1730.  
  1731.    return 0;
  1732. }
  1733.  
  1734. /** dri3_get_swap_interval
  1735.  *
  1736.  * Return the stored swap interval
  1737.  */
  1738. static int
  1739. dri3_get_swap_interval(__GLXDRIdrawable *pdraw)
  1740. {
  1741.    struct dri3_drawable *priv =  (struct dri3_drawable *) pdraw;
  1742.  
  1743.   return priv->swap_interval;
  1744. }
  1745.  
  1746. static void
  1747. dri3_bind_tex_image(Display * dpy,
  1748.                     GLXDrawable drawable,
  1749.                     int buffer, const int *attrib_list)
  1750. {
  1751.    struct glx_context *gc = __glXGetCurrentContext();
  1752.    struct dri3_context *pcp = (struct dri3_context *) gc;
  1753.    __GLXDRIdrawable *base = GetGLXDRIDrawable(dpy, drawable);
  1754.    struct dri3_drawable *pdraw = (struct dri3_drawable *) base;
  1755.    struct dri3_screen *psc;
  1756.  
  1757.    if (pdraw != NULL) {
  1758.       psc = (struct dri3_screen *) base->psc;
  1759.  
  1760.       (*psc->f->invalidate)(pdraw->driDrawable);
  1761.  
  1762.       XSync(dpy, false);
  1763.  
  1764.       (*psc->texBuffer->setTexBuffer2) (pcp->driContext,
  1765.                                         pdraw->base.textureTarget,
  1766.                                         pdraw->base.textureFormat,
  1767.                                         pdraw->driDrawable);
  1768.    }
  1769. }
  1770.  
  1771. static void
  1772. dri3_release_tex_image(Display * dpy, GLXDrawable drawable, int buffer)
  1773. {
  1774.    struct glx_context *gc = __glXGetCurrentContext();
  1775.    struct dri3_context *pcp = (struct dri3_context *) gc;
  1776.    __GLXDRIdrawable *base = GetGLXDRIDrawable(dpy, drawable);
  1777.    struct dri3_drawable *pdraw = (struct dri3_drawable *) base;
  1778.    struct dri3_screen *psc;
  1779.  
  1780.    if (pdraw != NULL) {
  1781.       psc = (struct dri3_screen *) base->psc;
  1782.  
  1783.       if (psc->texBuffer->base.version >= 3 &&
  1784.           psc->texBuffer->releaseTexBuffer != NULL)
  1785.          (*psc->texBuffer->releaseTexBuffer) (pcp->driContext,
  1786.                                               pdraw->base.textureTarget,
  1787.                                               pdraw->driDrawable);
  1788.    }
  1789. }
  1790.  
  1791. static const struct glx_context_vtable dri3_context_vtable = {
  1792.    .destroy             = dri3_destroy_context,
  1793.    .bind                = dri3_bind_context,
  1794.    .unbind              = dri3_unbind_context,
  1795.    .wait_gl             = dri3_wait_gl,
  1796.    .wait_x              = dri3_wait_x,
  1797.    .use_x_font          = DRI_glXUseXFont,
  1798.    .bind_tex_image      = dri3_bind_tex_image,
  1799.    .release_tex_image   = dri3_release_tex_image,
  1800.    .get_proc_address    = NULL,
  1801. };
  1802.  
  1803. /** dri3_bind_extensions
  1804.  *
  1805.  * Enable all of the extensions supported on DRI3
  1806.  */
  1807. static void
  1808. dri3_bind_extensions(struct dri3_screen *psc, struct glx_display * priv,
  1809.                      const char *driverName)
  1810. {
  1811.    const __DRIextension **extensions;
  1812.    unsigned mask;
  1813.    int i;
  1814.  
  1815.    extensions = psc->core->getExtensions(psc->driScreen);
  1816.  
  1817.    __glXEnableDirectExtension(&psc->base, "GLX_SGI_video_sync");
  1818.    __glXEnableDirectExtension(&psc->base, "GLX_SGI_swap_control");
  1819.    __glXEnableDirectExtension(&psc->base, "GLX_MESA_swap_control");
  1820.    __glXEnableDirectExtension(&psc->base, "GLX_SGI_make_current_read");
  1821.    __glXEnableDirectExtension(&psc->base, "GLX_INTEL_swap_event");
  1822.  
  1823.    mask = psc->image_driver->getAPIMask(psc->driScreen);
  1824.  
  1825.    __glXEnableDirectExtension(&psc->base, "GLX_ARB_create_context");
  1826.    __glXEnableDirectExtension(&psc->base, "GLX_ARB_create_context_profile");
  1827.  
  1828.    if ((mask & (1 << __DRI_API_GLES2)) != 0)
  1829.       __glXEnableDirectExtension(&psc->base,
  1830.                                  "GLX_EXT_create_context_es2_profile");
  1831.  
  1832.    for (i = 0; extensions[i]; i++) {
  1833.       /* when on a different gpu than the server, the server pixmaps
  1834.        * can have a tiling mode we can't read. Thus we can't create
  1835.        * a texture from them.
  1836.        */
  1837.       if (!psc->is_different_gpu &&
  1838.          (strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0)) {
  1839.          psc->texBuffer = (__DRItexBufferExtension *) extensions[i];
  1840.          __glXEnableDirectExtension(&psc->base, "GLX_EXT_texture_from_pixmap");
  1841.       }
  1842.  
  1843.       if ((strcmp(extensions[i]->name, __DRI2_FLUSH) == 0)) {
  1844.          psc->f = (__DRI2flushExtension *) extensions[i];
  1845.          /* internal driver extension, no GL extension exposed */
  1846.       }
  1847.  
  1848.       if (strcmp(extensions[i]->name, __DRI_IMAGE) == 0)
  1849.          psc->image = (__DRIimageExtension *) extensions[i];
  1850.  
  1851.       if ((strcmp(extensions[i]->name, __DRI2_CONFIG_QUERY) == 0))
  1852.          psc->config = (__DRI2configQueryExtension *) extensions[i];
  1853.  
  1854.       if (strcmp(extensions[i]->name, __DRI2_ROBUSTNESS) == 0)
  1855.          __glXEnableDirectExtension(&psc->base,
  1856.                                     "GLX_ARB_create_context_robustness");
  1857.  
  1858.       if (strcmp(extensions[i]->name, __DRI2_RENDERER_QUERY) == 0) {
  1859.          psc->rendererQuery = (__DRI2rendererQueryExtension *) extensions[i];
  1860.          __glXEnableDirectExtension(&psc->base, "GLX_MESA_query_renderer");
  1861.       }
  1862.    }
  1863. }
  1864.  
  1865. static const struct glx_screen_vtable dri3_screen_vtable = {
  1866.    .create_context         = dri3_create_context,
  1867.    .create_context_attribs = dri3_create_context_attribs,
  1868.    .query_renderer_integer = dri3_query_renderer_integer,
  1869.    .query_renderer_string  = dri3_query_renderer_string,
  1870. };
  1871.  
  1872. /** dri3_create_screen
  1873.  *
  1874.  * Initialize DRI3 on the specified screen.
  1875.  *
  1876.  * Opens the DRI device, locates the appropriate DRI driver
  1877.  * and loads that.
  1878.  *
  1879.  * Checks to see if the driver supports the necessary extensions
  1880.  *
  1881.  * Initializes the driver for the screen and sets up our structures
  1882.  */
  1883.  
  1884. static struct glx_screen *
  1885. dri3_create_screen(int screen, struct glx_display * priv)
  1886. {
  1887.    xcb_connection_t *c = XGetXCBConnection(priv->dpy);
  1888.    const __DRIconfig **driver_configs;
  1889.    const __DRIextension **extensions;
  1890.    const struct dri3_display *const pdp = (struct dri3_display *)
  1891.       priv->dri3Display;
  1892.    struct dri3_screen *psc;
  1893.    __GLXDRIscreen *psp;
  1894.    struct glx_config *configs = NULL, *visuals = NULL;
  1895.    char *driverName, *deviceName, *tmp;
  1896.    int i;
  1897.  
  1898.    psc = calloc(1, sizeof *psc);
  1899.    if (psc == NULL)
  1900.       return NULL;
  1901.  
  1902.    psc->fd = -1;
  1903.  
  1904.    if (!glx_screen_init(&psc->base, screen, priv)) {
  1905.       free(psc);
  1906.       return NULL;
  1907.    }
  1908.  
  1909.    psc->fd = dri3_open(priv->dpy, RootWindow(priv->dpy, screen), None);
  1910.    if (psc->fd < 0) {
  1911.       int conn_error = xcb_connection_has_error(c);
  1912.  
  1913.       glx_screen_cleanup(&psc->base);
  1914.       free(psc);
  1915.       InfoMessageF("screen %d does not appear to be DRI3 capable\n", screen);
  1916.  
  1917.       if (conn_error)
  1918.          ErrorMessageF("Connection closed during DRI3 initialization failure");
  1919.  
  1920.       return NULL;
  1921.    }
  1922.  
  1923.    psc->fd = loader_get_user_preferred_fd(psc->fd, &psc->is_different_gpu);
  1924.    deviceName = NULL;
  1925.  
  1926.    driverName = loader_get_driver_for_fd(psc->fd, 0);
  1927.    if (!driverName) {
  1928.       ErrorMessageF("No driver found\n");
  1929.       goto handle_error;
  1930.    }
  1931.  
  1932.    psc->driver = driOpenDriver(driverName);
  1933.    if (psc->driver == NULL) {
  1934.       ErrorMessageF("driver pointer missing\n");
  1935.       goto handle_error;
  1936.    }
  1937.  
  1938.    extensions = driGetDriverExtensions(psc->driver, driverName);
  1939.    if (extensions == NULL)
  1940.       goto handle_error;
  1941.  
  1942.    for (i = 0; extensions[i]; i++) {
  1943.       if (strcmp(extensions[i]->name, __DRI_CORE) == 0)
  1944.          psc->core = (__DRIcoreExtension *) extensions[i];
  1945.       if (strcmp(extensions[i]->name, __DRI_IMAGE_DRIVER) == 0)
  1946.          psc->image_driver = (__DRIimageDriverExtension *) extensions[i];
  1947.    }
  1948.  
  1949.  
  1950.    if (psc->core == NULL) {
  1951.       ErrorMessageF("core dri driver extension not found\n");
  1952.       goto handle_error;
  1953.    }
  1954.  
  1955.    if (psc->image_driver == NULL) {
  1956.       ErrorMessageF("image driver extension not found\n");
  1957.       goto handle_error;
  1958.    }
  1959.  
  1960.    psc->driScreen =
  1961.       psc->image_driver->createNewScreen2(screen, psc->fd,
  1962.                                           pdp->loader_extensions,
  1963.                                           extensions,
  1964.                                           &driver_configs, psc);
  1965.  
  1966.    if (psc->driScreen == NULL) {
  1967.       ErrorMessageF("failed to create dri screen\n");
  1968.       goto handle_error;
  1969.    }
  1970.  
  1971.    dri3_bind_extensions(psc, priv, driverName);
  1972.  
  1973.    if (!psc->image || psc->image->base.version < 7 || !psc->image->createImageFromFds) {
  1974.       ErrorMessageF("Version 7 or imageFromFds image extension not found\n");
  1975.       goto handle_error;
  1976.    }
  1977.  
  1978.    if (!psc->f || psc->f->base.version < 4) {
  1979.       ErrorMessageF("Version 4 or later of flush extension not found\n");
  1980.       goto handle_error;
  1981.    }
  1982.  
  1983.    if (psc->is_different_gpu && psc->image->base.version < 9) {
  1984.       ErrorMessageF("Different GPU, but image extension version 9 or later not found\n");
  1985.       goto handle_error;
  1986.    }
  1987.  
  1988.    if (psc->is_different_gpu && !psc->image->blitImage) {
  1989.       ErrorMessageF("Different GPU, but blitImage not implemented for this driver\n");
  1990.       goto handle_error;
  1991.    }
  1992.  
  1993.    if (!psc->is_different_gpu && (
  1994.        !psc->texBuffer || psc->texBuffer->base.version < 2 ||
  1995.        !psc->texBuffer->setTexBuffer2
  1996.        )) {
  1997.       ErrorMessageF("Version 2 or later of texBuffer extension not found\n");
  1998.       goto handle_error;
  1999.    }
  2000.  
  2001.    configs = driConvertConfigs(psc->core, psc->base.configs, driver_configs);
  2002.    visuals = driConvertConfigs(psc->core, psc->base.visuals, driver_configs);
  2003.  
  2004.    if (!configs || !visuals) {
  2005.        ErrorMessageF("No matching fbConfigs or visuals found\n");
  2006.        goto handle_error;
  2007.    }
  2008.  
  2009.    glx_config_destroy_list(psc->base.configs);
  2010.    psc->base.configs = configs;
  2011.    glx_config_destroy_list(psc->base.visuals);
  2012.    psc->base.visuals = visuals;
  2013.  
  2014.    psc->driver_configs = driver_configs;
  2015.  
  2016.    psc->base.vtable = &dri3_screen_vtable;
  2017.    psp = &psc->vtable;
  2018.    psc->base.driScreen = psp;
  2019.    psp->destroyScreen = dri3_destroy_screen;
  2020.    psp->createDrawable = dri3_create_drawable;
  2021.    psp->swapBuffers = dri3_swap_buffers;
  2022.  
  2023.    psp->getDrawableMSC = dri3_drawable_get_msc;
  2024.    psp->waitForMSC = dri3_wait_for_msc;
  2025.    psp->waitForSBC = dri3_wait_for_sbc;
  2026.    psp->setSwapInterval = dri3_set_swap_interval;
  2027.    psp->getSwapInterval = dri3_get_swap_interval;
  2028.    __glXEnableDirectExtension(&psc->base, "GLX_OML_sync_control");
  2029.  
  2030.    psp->copySubBuffer = dri3_copy_sub_buffer;
  2031.    __glXEnableDirectExtension(&psc->base, "GLX_MESA_copy_sub_buffer");
  2032.  
  2033.    psp->getBufferAge = dri3_get_buffer_age;
  2034.    __glXEnableDirectExtension(&psc->base, "GLX_EXT_buffer_age");
  2035.  
  2036.    free(driverName);
  2037.    free(deviceName);
  2038.  
  2039.    tmp = getenv("LIBGL_SHOW_FPS");
  2040.    psc->show_fps_interval = tmp ? atoi(tmp) : 0;
  2041.    if (psc->show_fps_interval < 0)
  2042.       psc->show_fps_interval = 0;
  2043.  
  2044.    InfoMessageF("Using DRI3 for screen %d\n", screen);
  2045.  
  2046.    return &psc->base;
  2047.  
  2048. handle_error:
  2049.    CriticalErrorMessageF("failed to load driver: %s\n", driverName);
  2050.  
  2051.    if (configs)
  2052.        glx_config_destroy_list(configs);
  2053.    if (visuals)
  2054.        glx_config_destroy_list(visuals);
  2055.    if (psc->driScreen)
  2056.        psc->core->destroyScreen(psc->driScreen);
  2057.    psc->driScreen = NULL;
  2058.    if (psc->fd >= 0)
  2059.       close(psc->fd);
  2060.    if (psc->driver)
  2061.       dlclose(psc->driver);
  2062.  
  2063.    free(driverName);
  2064.    free(deviceName);
  2065.    glx_screen_cleanup(&psc->base);
  2066.    free(psc);
  2067.  
  2068.    return NULL;
  2069. }
  2070.  
  2071. /** dri_destroy_display
  2072.  *
  2073.  * Called from __glXFreeDisplayPrivate.
  2074.  */
  2075. static void
  2076. dri3_destroy_display(__GLXDRIdisplay * dpy)
  2077. {
  2078.    free(dpy);
  2079. }
  2080.  
  2081. /** dri3_create_display
  2082.  *
  2083.  * Allocate, initialize and return a __DRIdisplayPrivate object.
  2084.  * This is called from __glXInitialize() when we are given a new
  2085.  * display pointer. This is public to that function, but hidden from
  2086.  * outside of libGL.
  2087.  */
  2088. _X_HIDDEN __GLXDRIdisplay *
  2089. dri3_create_display(Display * dpy)
  2090. {
  2091.    struct dri3_display                  *pdp;
  2092.    xcb_connection_t                     *c = XGetXCBConnection(dpy);
  2093.    xcb_dri3_query_version_cookie_t      dri3_cookie;
  2094.    xcb_dri3_query_version_reply_t       *dri3_reply;
  2095.    xcb_present_query_version_cookie_t   present_cookie;
  2096.    xcb_present_query_version_reply_t    *present_reply;
  2097.    xcb_generic_error_t                  *error;
  2098.    const xcb_query_extension_reply_t    *extension;
  2099.  
  2100.    xcb_prefetch_extension_data(c, &xcb_dri3_id);
  2101.    xcb_prefetch_extension_data(c, &xcb_present_id);
  2102.  
  2103.    extension = xcb_get_extension_data(c, &xcb_dri3_id);
  2104.    if (!(extension && extension->present))
  2105.       return NULL;
  2106.  
  2107.    extension = xcb_get_extension_data(c, &xcb_present_id);
  2108.    if (!(extension && extension->present))
  2109.       return NULL;
  2110.  
  2111.    dri3_cookie = xcb_dri3_query_version(c,
  2112.                                         XCB_DRI3_MAJOR_VERSION,
  2113.                                         XCB_DRI3_MINOR_VERSION);
  2114.  
  2115.  
  2116.    present_cookie = xcb_present_query_version(c,
  2117.                                    XCB_PRESENT_MAJOR_VERSION,
  2118.                                    XCB_PRESENT_MINOR_VERSION);
  2119.  
  2120.    pdp = malloc(sizeof *pdp);
  2121.    if (pdp == NULL)
  2122.       return NULL;
  2123.  
  2124.    dri3_reply = xcb_dri3_query_version_reply(c, dri3_cookie, &error);
  2125.    if (!dri3_reply) {
  2126.       free(error);
  2127.       goto no_extension;
  2128.    }
  2129.  
  2130.    pdp->dri3Major = dri3_reply->major_version;
  2131.    pdp->dri3Minor = dri3_reply->minor_version;
  2132.    free(dri3_reply);
  2133.  
  2134.    present_reply = xcb_present_query_version_reply(c, present_cookie, &error);
  2135.    if (!present_reply) {
  2136.       free(error);
  2137.       goto no_extension;
  2138.    }
  2139.    pdp->presentMajor = present_reply->major_version;
  2140.    pdp->presentMinor = present_reply->minor_version;
  2141.    free(present_reply);
  2142.  
  2143.    pdp->base.destroyDisplay = dri3_destroy_display;
  2144.    pdp->base.createScreen = dri3_create_screen;
  2145.  
  2146.    loader_set_logger(dri_message);
  2147.  
  2148.    pdp->loader_extensions = loader_extensions;
  2149.  
  2150.    return &pdp->base;
  2151. no_extension:
  2152.    free(pdp);
  2153.    return NULL;
  2154. }
  2155.  
  2156. #endif /* GLX_DIRECT_RENDERING */
  2157.