[Intel-gfx] [PATCH] mesa/intel: add DRI2 swapbuffers interface

Jesse Barnes jbarnes at virtuousgeek.org
Fri Feb 27 20:22:33 CET 2009


On Thursday, February 26, 2009 1:31:03 pm Jesse Barnes wrote:
> Add support to Mesa and the intel driver for the new DRI2 swapbuffers
> interface.  Uses the new flush hook to make sure any outstanding rendering
> is complete before sending the swapbuffers request.

Need to update the FBconfigs too; we now support the exchange method.

-- 
Jesse Barnes, Intel Open Source Technology Center

diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
index a726b93..b663028 100644
--- a/include/GL/internal/dri_interface.h
+++ b/include/GL/internal/dri_interface.h
@@ -681,6 +681,9 @@ struct __DRIdri2ExtensionRec {
 				      __DRIcontext *shared,
 				      void *loaderPrivate);
 
+    void (*setBuffers)(__DRIdrawable *drawable,
+		       __DRIbuffer *buffers,
+		       int count);
 };
 
 #endif
diff --git a/src/glx/x11/dri2.c b/src/glx/x11/dri2.c
index f967432..7af5484 100644
--- a/src/glx/x11/dri2.c
+++ b/src/glx/x11/dri2.c
@@ -30,7 +30,7 @@
  *   Kristian Høgsberg (krh at redhat.com)
  */
 
-
+#include <stdio.h>
 #define NEED_REPLIES
 #include <X11/Xlibint.h>
 #include <X11/extensions/Xext.h>
@@ -299,3 +299,51 @@ void DRI2CopyRegion(Display *dpy, XID drawable, XserverRegion region,
     UnlockDisplay(dpy);
     SyncHandle();
 }
+
+DRI2Buffer *DRI2SwapBuffers(Display *dpy, XID drawable, int *recv_count)
+{
+    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+    xDRI2SwapBuffersReq *req;
+    xDRI2SwapBuffersReply rep;
+    xDRI2Buffer repBuffer;
+    DRI2Buffer *new_buffers;
+    int i;
+
+    XextCheckExtension (dpy, info, dri2ExtensionName, False);
+
+    LockDisplay(dpy);
+    GetReq(DRI2SwapBuffers, req);
+    req->reqType = info->codes->major_opcode;
+    req->dri2ReqType = X_DRI2SwapBuffers;
+    req->drawable = drawable;
+
+    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+	UnlockDisplay(dpy);
+	SyncHandle();
+	return NULL;
+    }
+
+    new_buffers = Xmalloc(rep.count * sizeof *new_buffers);
+    if (new_buffers == NULL) {
+	_XEatData(dpy, rep.count * sizeof repBuffer);
+	UnlockDisplay(dpy);
+	SyncHandle();
+	return NULL;
+    }
+
+    for (i = 0; i < rep.count; i++) {
+	_XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer);
+	new_buffers[i].attachment = repBuffer.attachment;
+	new_buffers[i].name = repBuffer.name;
+	new_buffers[i].pitch = repBuffer.pitch;
+	new_buffers[i].cpp = repBuffer.cpp;
+	new_buffers[i].flags = repBuffer.flags;
+    }
+
+    *recv_count = rep.count;
+
+    UnlockDisplay(dpy);
+    SyncHandle();
+
+    return new_buffers;
+}
diff --git a/src/glx/x11/dri2.h b/src/glx/x11/dri2.h
index 356c6bc..83dfaf6 100644
--- a/src/glx/x11/dri2.h
+++ b/src/glx/x11/dri2.h
@@ -67,4 +67,7 @@ extern void
 DRI2CopyRegion(Display *dpy, XID drawable, XserverRegion region,
 	       CARD32 dest, CARD32 src);
 
+extern DRI2Buffer *
+DRI2SwapBuffers(Display *dpy, XID drawable, int *count);
+
 #endif
diff --git a/src/glx/x11/dri2_glx.c b/src/glx/x11/dri2_glx.c
index 0ef5d3a..f80f201 100644
--- a/src/glx/x11/dri2_glx.c
+++ b/src/glx/x11/dri2_glx.c
@@ -35,6 +35,7 @@
 #include <X11/Xlib.h>
 #include <X11/extensions/Xfixes.h>
 #include <X11/extensions/Xdamage.h>
+#include "glapi.h"
 #include "glxclient.h"
 #include "glcontextmodes.h"
 #include "xf86dri.h"
@@ -61,6 +62,8 @@ struct __GLXDRIdisplayPrivateRec {
     int driMinor;
     int driPatch;
 
+    int swapAvailable;
+
     unsigned long configureSeqno;
     Bool (*oldConfigProc)(Display *, XEvent *, xEvent *);
 };
@@ -223,8 +226,40 @@ static void dri2CopySubBuffer(__GLXDRIdrawable *pdraw,
 static void dri2SwapBuffers(__GLXDRIdrawable *pdraw)
 {
     __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw;
+    __GLXdisplayPrivate *dpyPriv = __glXInitialize(priv->base.psc->dpy);
+    __GLXDRIdisplayPrivate *pdp =
+	(__GLXDRIdisplayPrivate *)dpyPriv->dri2Display;
+    __GLXscreenConfigs *psc = pdraw->psc;
+    DRI2Buffer *buffers;
+    int i, count;
+
+#ifdef __DRI2_FLUSH
+    if (pdraw->psc->f)
+    	(*pdraw->psc->f->flush)(pdraw->driDrawable);
+#endif
+
+    /* Old servers can't handle swapbuffers */
+    if (!pdp->swapAvailable)
+	return dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height);
+
+    buffers = DRI2SwapBuffers(pdraw->psc->dpy, pdraw->drawable, &count);
+    if (buffers == NULL || !count)
+	return dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height);
+
+    /* Update our buffer list with what was returned */
+    for (i = 0; i < count; i++) {
+	    priv->buffers[i].attachment = buffers[i].attachment;
+	    priv->buffers[i].name = buffers[i].name;
+	    priv->buffers[i].pitch = buffers[i].pitch;
+	    priv->buffers[i].cpp = buffers[i].cpp;
+	    priv->buffers[i].flags = buffers[i].flags;
+    }
 
-    dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height);
+    priv->bufferCount = count;
+
+    (*psc->dri2->setBuffers)(pdraw->driDrawable, priv->buffers, count);
+
+    Xfree(buffers);
 }
 
 static void dri2WaitX(__GLXDRIdrawable *pdraw)
@@ -517,6 +552,9 @@ _X_HIDDEN __GLXDRIdisplay *dri2CreateDisplay(Display *dpy)
 
     pdp->driPatch = 0;
     pdp->configureSeqno = 0;
+    pdp->swapAvailable = 0;
+    if (pdp->driMinor > 0)
+	pdp->swapAvailable = 1;
 
     pdp->base.destroyDisplay = dri2DestroyDisplay;
     pdp->base.createScreen = dri2CreateScreen;
diff --git a/src/mesa/drivers/dri/common/dri_util.c b/src/mesa/drivers/dri/common/dri_util.c
index ae79055..90a39df 100644
--- a/src/mesa/drivers/dri/common/dri_util.c
+++ b/src/mesa/drivers/dri/common/dri_util.c
@@ -488,6 +488,15 @@ dri2CreateNewDrawable(__DRIscreen *screen,
     return pdraw;
 }
 
+static void
+dri2SetBuffers(__DRIdrawable *draw, __DRIbuffer *buffers, int count)
+{
+    __DRIscreen *psp = draw->driScreenPriv;
+
+    if (psp->DriverAPI.SetBuffers)
+	    (*psp->DriverAPI.SetBuffers)(draw, buffers, count);
+}
+
 
 static void
 driDestroyDrawable(__DRIdrawable *pdp)
@@ -832,6 +841,7 @@ const __DRIdri2Extension driDRI2Extension = {
     dri2CreateNewScreen,
     dri2CreateNewDrawable,
     dri2CreateNewContext,
+    dri2SetBuffers,
 };
 
 /* This is the table of extensions that the loader will dlsym() for. */
diff --git a/src/mesa/drivers/dri/common/dri_util.h b/src/mesa/drivers/dri/common/dri_util.h
index c95a5c8..2a6e1cd 100644
--- a/src/mesa/drivers/dri/common/dri_util.h
+++ b/src/mesa/drivers/dri/common/dri_util.h
@@ -225,6 +225,13 @@ struct __DriverAPIRec {
 
     /* DRI2 Entry point */
     const __DRIconfig **(*InitScreen2) (__DRIscreen * priv);
+
+    /**
+     * Update the render buffers with a new set
+     */
+    void (*SetBuffers) ( __DRIdrawable *drawable,
+			 __DRIbuffer *buffers,
+			 int count);
 };
 
 extern const struct __DriverAPIRec driDriverAPI;
diff --git a/src/mesa/drivers/dri/intel/intel_context.c b/src/mesa/drivers/dri/intel/intel_context.c
index 1aa173d..bef1907 100644
--- a/src/mesa/drivers/dri/intel/intel_context.c
+++ b/src/mesa/drivers/dri/intel/intel_context.c
@@ -169,6 +169,30 @@ intelGetString(GLcontext * ctx, GLenum name)
    }
 }
 
+/*
+ * DRI may give us with a new set of buffers after a flip or swap, so
+ * update the attachments here.
+ */
+void intelSetBuffers(__DRIdrawable *drawable,
+		     __DRIbuffer *buffers,
+		     int count)
+{
+   __DRIcontext *context = drawable->driContextPriv;
+   struct intel_framebuffer *intel_fb = drawable->driverPrivate;
+   struct intel_context *intel = context->driverPrivate;
+   struct intel_renderbuffer *rb;
+   struct intel_region *region;
+   const char *region_name;
+   int i;
+
+   /*
+    * Ignore the buffers & count args, we'll just pick them up from our
+    * drawable.
+    */
+   intel_update_renderbuffers(context, drawable);
+   intel_draw_buffer(&intel->ctx, &intel_fb->Base);
+}
+
 void
 intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
 {
@@ -399,6 +423,16 @@ intel_glFlush(GLcontext *ctx)
    intel_flush(ctx, GL_TRUE);
 }
 
+void intelFlushDrawable(__DRIdrawable *drawable)
+{
+    __DRIdrawablePrivate * dPriv = drawable->driverPrivate;
+    struct intel_context *intel =
+	(struct intel_context *) dPriv->driContextPriv->driverPrivate;
+    GLcontext *ctx = &intel->ctx;
+
+    intel_flush(ctx, GL_TRUE);
+}
+
 void
 intelFinish(GLcontext * ctx)
 {
diff --git a/src/mesa/drivers/dri/intel/intel_extensions.h b/src/mesa/drivers/dri/intel/intel_extensions.h
index 97147ec..9283ee9 100644
--- a/src/mesa/drivers/dri/intel/intel_extensions.h
+++ b/src/mesa/drivers/dri/intel/intel_extensions.h
@@ -32,5 +32,8 @@
 extern void
 intelInitExtensions(GLcontext *ctx, GLboolean enable_imaging);
 
+extern void
+intelFlushDrawable(__DRIdrawable *drawable);
+
 
 #endif
diff --git a/src/mesa/drivers/dri/intel/intel_screen.c b/src/mesa/drivers/dri/intel/intel_screen.c
index 09eba13..8a50a17 100644
--- a/src/mesa/drivers/dri/intel/intel_screen.c
+++ b/src/mesa/drivers/dri/intel/intel_screen.c
@@ -211,6 +211,11 @@ static const __DRItexBufferExtension intelTexBufferExtension = {
    intelSetTexBuffer,
 };
 
+static const __DRI2flushExtension intelFlushExtension = {
+    { __DRI2_FLUSH, __DRI2_FLUSH_VERSION },
+    intelFlushDrawable,
+};
+
 static const __DRIextension *intelScreenExtensions[] = {
     &driReadDrawableExtension,
     &driCopySubBufferExtension.base,
@@ -475,11 +480,9 @@ intelFillInModes(__DRIscreenPrivate *psp,
    unsigned back_buffer_factor;
    int i;
 
-   /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
-    * support pageflipping at all.
-    */
    static const GLenum back_buffer_modes[] = {
-      GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
+       GLX_NONE, GLX_SWAP_UNDEFINED_OML,
+       GLX_SWAP_EXCHANGE_OML, GLX_SWAP_COPY_OML
    };
 
    uint8_t depth_bits_array[3];
@@ -697,11 +700,10 @@ __DRIconfig **intelInitScreen2(__DRIscreenPrivate *psp)
    intelScreenPrivate *intelScreen;
    GLenum fb_format[3];
    GLenum fb_type[3];
-   /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
-    * support pageflipping at all.
-    */
+
    static const GLenum back_buffer_modes[] = {
-      GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
+       GLX_NONE, GLX_SWAP_UNDEFINED_OML,
+       GLX_SWAP_EXCHANGE_OML, GLX_SWAP_COPY_OML
    };
    uint8_t depth_bits[4], stencil_bits[4], msaa_samples_array[1];
    int color;
@@ -828,4 +830,6 @@ const struct __DriverAPIRec driDriverAPI = {
    .CopySubBuffer	 = intelCopySubBuffer,
 
    .InitScreen2		 = intelInitScreen2,
+
+   .SetBuffers		 = intelSetBuffers,
 };
diff --git a/src/mesa/drivers/dri/intel/intel_screen.h b/src/mesa/drivers/dri/intel/intel_screen.h
index e1036de..b23dcee 100644
--- a/src/mesa/drivers/dri/intel/intel_screen.h
+++ b/src/mesa/drivers/dri/intel/intel_screen.h
@@ -103,4 +103,7 @@ intelMakeCurrent(__DRIcontextPrivate * driContextPriv,
 
 extern struct intel_context *intelScreenContext(intelScreenPrivate *intelScreen);
 
+extern void intelSetBuffers(__DRIdrawable *drawable, __DRIbuffer *buffers,
+			    int count);
+
 #endif




More information about the Intel-gfx mailing list