glx: move the glFlush call one layer down
[mesa.git] / src / glx / dri2_glx.c
index cb3412e8fc694f04e8559d3e7d99b19116f11949..30f6913010a010f6da530f5ef6bf531524561929 100644 (file)
@@ -439,12 +439,16 @@ dri2DrawableGetMSC(struct glx_screen *psc, __GLXDRIdrawable *pdraw,
 
    get_msc_cookie = xcb_dri2_get_msc_unchecked(c, pdraw->xDrawable);
    get_msc_reply = xcb_dri2_get_msc_reply(c, get_msc_cookie, NULL);
+
+   if (!get_msc_reply)
+      return 0;
+
    *ust = merge_counter(get_msc_reply->ust_hi, get_msc_reply->ust_lo);
    *msc = merge_counter(get_msc_reply->msc_hi, get_msc_reply->msc_lo);
    *sbc = merge_counter(get_msc_reply->sbc_hi, get_msc_reply->sbc_lo);
    free(get_msc_reply);
 
-   return 0;
+   return 1;
 }
 
 static int
@@ -467,12 +471,16 @@ dri2WaitForMSC(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
                                                  divisor_hi, divisor_lo,
                                                  remainder_hi, remainder_lo);
    wait_msc_reply = xcb_dri2_wait_msc_reply(c, wait_msc_cookie, NULL);
+
+   if (!wait_msc_reply)
+      return 0;
+
    *ust = merge_counter(wait_msc_reply->ust_hi, wait_msc_reply->ust_lo);
    *msc = merge_counter(wait_msc_reply->msc_hi, wait_msc_reply->msc_lo);
    *sbc = merge_counter(wait_msc_reply->sbc_hi, wait_msc_reply->sbc_lo);
    free(wait_msc_reply);
 
-   return 0;
+   return 1;
 }
 
 static int
@@ -489,12 +497,16 @@ dri2WaitForSBC(__GLXDRIdrawable *pdraw, int64_t target_sbc, int64_t *ust,
    wait_sbc_cookie = xcb_dri2_wait_sbc_unchecked(c, pdraw->xDrawable,
                                                  target_sbc_hi, target_sbc_lo);
    wait_sbc_reply = xcb_dri2_wait_sbc_reply(c, wait_sbc_cookie, NULL);
+
+   if (!wait_sbc_reply)
+      return 0;
+
    *ust = merge_counter(wait_sbc_reply->ust_hi, wait_sbc_reply->ust_lo);
    *msc = merge_counter(wait_sbc_reply->msc_hi, wait_sbc_reply->msc_lo);
    *sbc = merge_counter(wait_sbc_reply->sbc_hi, wait_sbc_reply->sbc_lo);
    free(wait_sbc_reply);
 
-   return 0;
+   return 1;
 }
 
 /**
@@ -522,7 +534,7 @@ dri2Throttle(struct dri2_screen *psc,
 static void
 __dri2CopySubBuffer(__GLXDRIdrawable *pdraw, int x, int y,
                    int width, int height,
-                   enum __DRI2throttleReason reason)
+                   enum __DRI2throttleReason reason, Bool flush)
 {
    struct dri2_drawable *priv = (struct dri2_drawable *) pdraw;
    struct dri2_screen *psc = (struct dri2_screen *) pdraw->psc;
@@ -538,6 +550,10 @@ __dri2CopySubBuffer(__GLXDRIdrawable *pdraw, int x, int y,
    xrect.width = width;
    xrect.height = height;
 
+   if (flush) {
+      glFlush();
+   }
+
    if (psc->f)
       (*psc->f->flush) (priv->driDrawable);
 
@@ -559,10 +575,10 @@ __dri2CopySubBuffer(__GLXDRIdrawable *pdraw, int x, int y,
 
 static void
 dri2CopySubBuffer(__GLXDRIdrawable *pdraw, int x, int y,
-                 int width, int height)
+                 int width, int height, Bool flush)
 {
    __dri2CopySubBuffer(pdraw, x, y, width, height,
-                      __DRI2_THROTTLE_COPYSUBBUFFER);
+                      __DRI2_THROTTLE_COPYSUBBUFFER, flush);
 }
 
 
@@ -719,7 +735,7 @@ static void show_fps(struct dri2_drawable *draw)
 
 static int64_t
 dri2SwapBuffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
-               int64_t remainder)
+               int64_t remainder, Bool flush)
 {
     struct dri2_drawable *priv = (struct dri2_drawable *) pdraw;
     struct glx_display *dpyPriv = __glXInitialize(priv->base.psc->dpy);
@@ -735,22 +751,53 @@ dri2SwapBuffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
     /* Old servers can't handle swapbuffers */
     if (!pdp->swapAvailable) {
        __dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height,
-                          __DRI2_THROTTLE_SWAPBUFFER);
+                          __DRI2_THROTTLE_SWAPBUFFER, flush);
     } else {
-#ifdef X_DRI2SwapBuffers
-    if (psc->f) {
-       struct glx_context *gc = __glXGetCurrentContext();
+       xcb_connection_t *c = XGetXCBConnection(pdraw->psc->dpy);
+       xcb_dri2_swap_buffers_cookie_t swap_buffers_cookie;
+       xcb_dri2_swap_buffers_reply_t *swap_buffers_reply;
+       uint32_t target_msc_hi, target_msc_lo;
+       uint32_t divisor_hi, divisor_lo;
+       uint32_t remainder_hi, remainder_lo;
+
+       if (flush) {
+          glFlush();
+       }
+
+       if (psc->f) {
+          struct glx_context *gc = __glXGetCurrentContext();
 
-       if (gc) {
-         (*psc->f->flush)(priv->driDrawable);
+          if (gc) {
+             (*psc->f->flush)(priv->driDrawable);
+          }
        }
-    }
 
        dri2Throttle(psc, priv, __DRI2_THROTTLE_SWAPBUFFER);
 
-       DRI2SwapBuffers(psc->base.dpy, pdraw->xDrawable,
-                      target_msc, divisor, remainder, &ret);
-#endif
+       split_counter(target_msc, &target_msc_hi, &target_msc_lo);
+       split_counter(divisor, &divisor_hi, &divisor_lo);
+       split_counter(remainder, &remainder_hi, &remainder_lo);
+
+       swap_buffers_cookie =
+          xcb_dri2_swap_buffers_unchecked(c, pdraw->xDrawable,
+                                          target_msc_hi, target_msc_lo,
+                                          divisor_hi, divisor_lo,
+                                          remainder_hi, remainder_lo);
+       /* Immediately wait on the swapbuffers reply.  If we didn't, we'd have
+        * to do so some time before reusing a (non-pageflipped) backbuffer.
+        * Otherwise, the new rendering could get ahead of the X Server's
+        * dispatch of the swapbuffer and you'd display garbage.
+        *
+        * We use XSync() first to reap the invalidate events through the event
+        * filter, to ensure that the next drawing doesn't use an invalidated
+        * buffer.
+        */
+       XSync(pdraw->psc->dpy, False);
+       swap_buffers_reply =
+          xcb_dri2_swap_buffers_reply(c, swap_buffers_cookie, NULL);
+       ret = merge_counter(swap_buffers_reply->swap_hi,
+                           swap_buffers_reply->swap_lo);
+       free(swap_buffers_reply);
     }
 
     if (psc->show_fps) {
@@ -812,11 +859,10 @@ dri2GetBuffersWithFormat(__DRIdrawable * driDrawable,
    return pdraw->buffers;
 }
 
-#ifdef X_DRI2SwapInterval
-
 static int
 dri2SetSwapInterval(__GLXDRIdrawable *pdraw, int interval)
 {
+   xcb_connection_t *c = XGetXCBConnection(pdraw->psc->dpy);
    struct dri2_drawable *priv =  (struct dri2_drawable *) pdraw;
    GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1;
    struct dri2_screen *psc = (struct dri2_screen *) priv->base.psc;
@@ -838,7 +884,7 @@ dri2SetSwapInterval(__GLXDRIdrawable *pdraw, int interval)
       break;
    }
 
-   DRI2SwapInterval(priv->base.psc->dpy, priv->base.xDrawable, interval);
+   xcb_dri2_swap_interval(c, priv->base.xDrawable, interval);
    priv->swap_interval = interval;
 
    return 0;
@@ -852,8 +898,6 @@ dri2GetSwapInterval(__GLXDRIdrawable *pdraw)
   return priv->swap_interval;
 }
 
-#endif /* X_DRI2SwapInterval */
-
 static const __DRIdri2LoaderExtension dri2LoaderExtension = {
    {__DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION},
    dri2GetBuffers,
@@ -974,7 +1018,7 @@ dri2BindExtensions(struct dri2_screen *psc, const __DRIextension **extensions)
    __glXEnableDirectExtension(&psc->base, "GLX_SGI_make_current_read");
 
    /* FIXME: if DRI2 version supports it... */
-   __glXEnableDirectExtension(&psc->base, "INTEL_swap_event");
+   __glXEnableDirectExtension(&psc->base, "GLX_INTEL_swap_event");
 
    if (psc->dri2->base.version >= 3) {
       const unsigned mask = psc->dri2->getAPIMask(psc->driScreen);
@@ -1147,10 +1191,8 @@ dri2CreateScreen(int screen, struct glx_display * priv)
       psp->getDrawableMSC = dri2DrawableGetMSC;
       psp->waitForMSC = dri2WaitForMSC;
       psp->waitForSBC = dri2WaitForSBC;
-#ifdef X_DRI2SwapInterval
       psp->setSwapInterval = dri2SetSwapInterval;
       psp->getSwapInterval = dri2GetSwapInterval;
-#endif
       __glXEnableDirectExtension(&psc->base, "GLX_OML_sync_control");
    }