dri3: cache pointer to back instead of looking up.
[mesa.git] / src / glx / dri3_glx.c
index ba8018476713e59d4740e44786a8b1cef13cf2d9..3092bc1e9914eeeca6ccc8807134684ce7711195 100644 (file)
@@ -76,6 +76,7 @@
 #include "dri_common.h"
 #include "dri3_priv.h"
 #include "loader.h"
+#include "dri2.h"
 
 static const struct glx_context_vtable dri3_context_vtable;
 
@@ -1307,6 +1308,17 @@ static const __DRIimageLoaderExtension imageLoaderExtension = {
    .flushFrontBuffer    = dri3_flush_front_buffer,
 };
 
+const __DRIuseInvalidateExtension dri3UseInvalidate = {
+   .base = { __DRI_USE_INVALIDATE, 1 }
+};
+
+static const __DRIextension *loader_extensions[] = {
+   &imageLoaderExtension.base,
+   &systemTimeExtension.base,
+   &dri3UseInvalidate.base,
+   NULL
+};
+
 /** dri3_swap_buffers
  *
  * Make the current back buffer visible using the present extension
@@ -1319,7 +1331,7 @@ dri3_swap_buffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
    struct dri3_screen *psc = (struct dri3_screen *) priv->base.psc;
    Display *dpy = priv->base.psc->dpy;
    xcb_connection_t *c = XGetXCBConnection(dpy);
-   int buf_id = DRI3_BACK_ID(priv->cur_back);
+   struct dri3_buffer *back;
    int64_t ret = 0;
 
    unsigned flags = __DRI2_FLUSH_DRAWABLE;
@@ -1327,10 +1339,11 @@ dri3_swap_buffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
       flags |= __DRI2_FLUSH_CONTEXT;
    dri3_flush(psc, priv, flags, __DRI2_THROTTLE_SWAPBUFFER);
 
+   back = priv->buffers[DRI3_BACK_ID(priv->cur_back)];
    dri3_flush_present_events(priv);
 
-   if (priv->buffers[buf_id] && !priv->is_pixmap) {
-      dri3_fence_reset(c, priv->buffers[buf_id]);
+   if (back && !priv->is_pixmap) {
+      dri3_fence_reset(c, back);
 
       /* Compute when we want the frame shown by taking the last known successful
        * MSC and adding in a swap interval for each outstanding swap request
@@ -1339,10 +1352,11 @@ dri3_swap_buffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
       if (target_msc == 0)
          target_msc = priv->msc + priv->swap_interval * (priv->send_sbc - priv->recv_sbc);
 
-      priv->buffers[buf_id]->busy = 1;
+      back->busy = 1;
+      back->last_swap = priv->send_sbc;
       xcb_present_pixmap(c,
                          priv->base.xDrawable,
-                         priv->buffers[buf_id]->pixmap,
+                         back->pixmap,
                          (uint32_t) priv->send_sbc,
                          0,                                    /* valid */
                          0,                                    /* update */
@@ -1350,7 +1364,7 @@ dri3_swap_buffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
                          0,                                    /* y_off */
                          None,                                 /* target_crtc */
                          None,
-                         priv->buffers[buf_id]->sync_fence,
+                         back->sync_fence,
                          XCB_PRESENT_OPTION_NONE,
                          target_msc,
                          divisor,
@@ -1365,7 +1379,7 @@ dri3_swap_buffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
       if (priv->have_fake_front) {
          dri3_fence_reset(c, priv->buffers[DRI3_FRONT_ID]);
          dri3_copy_area(c,
-                        priv->buffers[buf_id]->pixmap,
+                        back->pixmap,
                         priv->buffers[DRI3_FRONT_ID]->pixmap,
                         dri3_drawable_gc(priv),
                         0, 0, 0, 0, priv->width, priv->height);
@@ -1376,9 +1390,27 @@ dri3_swap_buffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
          ++(*priv->stamp);
    }
 
+   (*psc->f->invalidate)(priv->driDrawable);
+
    return ret;
 }
 
+static int
+dri3_get_buffer_age(__GLXDRIdrawable *pdraw)
+{
+   xcb_connection_t *c = XGetXCBConnection(pdraw->psc->dpy);
+   struct dri3_drawable *priv = (struct dri3_drawable *) pdraw;
+   int back_id = DRI3_BACK_ID(dri3_find_back(c, priv));
+
+   if (back_id < 0 || !priv->buffers[back_id])
+      return 0;
+
+   if (priv->buffers[back_id]->last_swap != 0)
+      return priv->send_sbc - priv->buffers[back_id]->last_swap + 1;
+   else
+      return 0;
+}
+
 /** dri3_open
  *
  * Wrapper around xcb_dri3_open
@@ -1510,7 +1542,8 @@ dri3_release_tex_image(Display * dpy, GLXDrawable drawable, int buffer)
    if (pdraw != NULL) {
       psc = (struct dri3_screen *) base->psc;
 
-      if (psc->texBuffer->releaseTexBuffer)
+      if (psc->texBuffer->base.version >= 3 &&
+          psc->texBuffer->releaseTexBuffer != NULL)
          (*psc->texBuffer->releaseTexBuffer) (pcp->driContext,
                                               pdraw->base.textureTarget,
                                               pdraw->driDrawable);
@@ -1518,15 +1551,15 @@ dri3_release_tex_image(Display * dpy, GLXDrawable drawable, int buffer)
 }
 
 static const struct glx_context_vtable dri3_context_vtable = {
-   dri3_destroy_context,
-   dri3_bind_context,
-   dri3_unbind_context,
-   dri3_wait_gl,
-   dri3_wait_x,
-   DRI_glXUseXFont,
-   dri3_bind_tex_image,
-   dri3_release_tex_image,
-   NULL, /* get_proc_address */
+   .destroy             = dri3_destroy_context,
+   .bind                = dri3_bind_context,
+   .unbind              = dri3_unbind_context,
+   .wait_gl             = dri3_wait_gl,
+   .wait_x              = dri3_wait_x,
+   .use_x_font          = DRI_glXUseXFont,
+   .bind_tex_image      = dri3_bind_tex_image,
+   .release_tex_image   = dri3_release_tex_image,
+   .get_proc_address    = NULL,
 };
 
 /** dri3_bind_extensions
@@ -1569,18 +1602,28 @@ dri3_bind_extensions(struct dri3_screen *psc, struct glx_display * priv,
          /* internal driver extension, no GL extension exposed */
       }
 
+      if (strcmp(extensions[i]->name, __DRI_IMAGE) == 0)
+         psc->image = (__DRIimageExtension *) extensions[i];
+
       if ((strcmp(extensions[i]->name, __DRI2_CONFIG_QUERY) == 0))
          psc->config = (__DRI2configQueryExtension *) extensions[i];
 
       if (strcmp(extensions[i]->name, __DRI2_ROBUSTNESS) == 0)
          __glXEnableDirectExtension(&psc->base,
                                     "GLX_ARB_create_context_robustness");
+
+      if (strcmp(extensions[i]->name, __DRI2_RENDERER_QUERY) == 0) {
+         psc->rendererQuery = (__DRI2rendererQueryExtension *) extensions[i];
+         __glXEnableDirectExtension(&psc->base, "GLX_MESA_query_renderer");
+      }
    }
 }
 
 static const struct glx_screen_vtable dri3_screen_vtable = {
-   dri3_create_context,
-   dri3_create_context_attribs
+   .create_context         = dri3_create_context,
+   .create_context_attribs = dri3_create_context_attribs,
+   .query_renderer_integer = dri3_query_renderer_integer,
+   .query_renderer_string  = dri3_query_renderer_string,
 };
 
 /** dri3_create_screen
@@ -1671,8 +1714,7 @@ dri3_create_screen(int screen, struct glx_display * priv)
 
    psc->driScreen =
       psc->image_driver->createNewScreen2(screen, psc->fd,
-                                          (const __DRIextension **)
-                                          &pdp->loader_extensions[0],
+                                          pdp->loader_extensions,
                                           extensions,
                                           &driver_configs, psc);
 
@@ -1681,20 +1723,13 @@ dri3_create_screen(int screen, struct glx_display * priv)
       goto handle_error;
    }
 
-   extensions = (*psc->core->getExtensions)(psc->driScreen);
-
-   for (i = 0; extensions[i]; i++) {
-      if (strcmp(extensions[i]->name, __DRI_IMAGE) == 0)
-         psc->image = (__DRIimageExtension *) extensions[i];
-   }
+   dri3_bind_extensions(psc, priv, driverName);
 
-   if (psc->image == NULL) {
-      ErrorMessageF("image extension not found\n");
+   if (!psc->image || psc->image->base.version < 7 || !psc->image->createImageFromFds) {
+      ErrorMessageF("Version 7 or imageFromFds image extension not found\n");
       goto handle_error;
    }
 
-   dri3_bind_extensions(psc, priv, driverName);
-
    if (!psc->f || psc->f->base.version < 4) {
       ErrorMessageF("Version 4 or later of flush extension not found\n");
       goto handle_error;
@@ -1710,8 +1745,10 @@ dri3_create_screen(int screen, struct glx_display * priv)
    configs = driConvertConfigs(psc->core, psc->base.configs, driver_configs);
    visuals = driConvertConfigs(psc->core, psc->base.visuals, driver_configs);
 
-   if (!configs || !visuals)
+   if (!configs || !visuals) {
+       ErrorMessageF("No matching fbConfigs or visuals found\n");
        goto handle_error;
+   }
 
    glx_config_destroy_list(psc->base.configs);
    psc->base.configs = configs;
@@ -1737,6 +1774,9 @@ dri3_create_screen(int screen, struct glx_display * priv)
    psp->copySubBuffer = dri3_copy_sub_buffer;
    __glXEnableDirectExtension(&psc->base, "GLX_MESA_copy_sub_buffer");
 
+   psp->getBufferAge = dri3_get_buffer_age;
+   __glXEnableDirectExtension(&psc->base, "GLX_EXT_buffer_age");
+
    free(driverName);
    free(deviceName);
 
@@ -1786,7 +1826,6 @@ _X_HIDDEN __GLXDRIdisplay *
 dri3_create_display(Display * dpy)
 {
    struct dri3_display                  *pdp;
-   int                                  i;
    xcb_connection_t                     *c = XGetXCBConnection(dpy);
    xcb_dri3_query_version_cookie_t      dri3_cookie;
    xcb_dri3_query_version_reply_t       *dri3_reply;
@@ -1842,13 +1881,8 @@ dri3_create_display(Display * dpy)
    pdp->base.createScreen = dri3_create_screen;
 
    loader_set_logger(dri_message);
-   i = 0;
-
-   pdp->loader_extensions[i++] = &imageLoaderExtension.base;
-
-   pdp->loader_extensions[i++] = &systemTimeExtension.base;
 
-   pdp->loader_extensions[i++] = NULL;
+   pdp->loader_extensions = loader_extensions;
 
    return &pdp->base;
 no_extension: