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

Jesse Barnes jbarnes at virtuousgeek.org
Thu Feb 26 22:31:03 CET 2009


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.

Signed-off-by: Jesse Barnes <jbarnes at virtuousgeek.org>

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..f39decf 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
 
-    dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height);
+    /* 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;
+    }
+
+    priv->bufferCount = count;
+
+    (*psc->dri2->setBuffers)(pdraw->driDrawable, priv->buffers, count);
+
+    Xfree(buffers);
 }
 
 static void dri2WaitX(__GLXDRIdrawable *pdraw)
@@ -517,6 +552,12 @@ _X_HIDDEN __GLXDRIdisplay *dri2CreateDisplay(Display *dpy)
 
     pdp->driPatch = 0;
     pdp->configureSeqno = 0;
+    pdp->swapAvailable = 0;
+    printf("dri2 version %d.%d\n", pdp->driMajor, pdp->driMinor);
+    if (pdp->driMinor > 0) {
+	printf("enabling buffer swaps\n");
+	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..75afc45 100644
--- a/src/mesa/drivers/dri/common/dri_util.c
+++ b/src/mesa/drivers/dri/common/dri_util.c
@@ -488,6 +488,14 @@ dri2CreateNewDrawable(__DRIscreen *screen,
     return pdraw;
 }
 
+static void
+dri2SetBuffers(__DRIdrawable *draw, __DRIbuffer *buffers, int count)
+{
+    __DRIscreen *psp = draw->driScreenPriv;
+
+    (*psp->DriverAPI.SetBuffers)(draw, buffers, count);
+}
+
 
 static void
 driDestroyDrawable(__DRIdrawable *pdp)
@@ -832,6 +840,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..38ab561 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,
@@ -828,4 +833,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