[Intel-gfx] [PATCH] mesa: add DRI2 swap buffers support

Jesse Barnes jbarnes at virtuousgeek.org
Wed Apr 15 00:24:37 CEST 2009


Add support to Mesa for handling the new DRI2 swapbuffers request,
along with support in the Intel drivers for the new setBuffers
callback, which is responsible for updating the renderbuffers
appropriately following a swapbuffers call.

diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
index 335bf62..24a2391 100644
--- a/include/GL/internal/dri_interface.h
+++ b/include/GL/internal/dri_interface.h
@@ -706,6 +706,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 b6eeb91..976a09e 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"
@@ -60,6 +61,8 @@ struct __GLXDRIdisplayPrivateRec {
     int driMajor;
     int driMinor;
     int driPatch;
+
+    int swapAvailable;
 };
 
 struct __GLXDRIcontextPrivateRec {
@@ -217,8 +220,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)
@@ -471,6 +506,9 @@ _X_HIDDEN __GLXDRIdisplay *dri2CreateDisplay(Display *dpy)
     }
 
     pdp->driPatch = 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 38c2e7b..ebb32fa 100644
--- a/src/mesa/drivers/dri/common/dri_util.c
+++ b/src/mesa/drivers/dri/common/dri_util.c
@@ -483,6 +483,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)
@@ -827,6 +836,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_buffers.c b/src/mesa/drivers/dri/intel/intel_buffers.c
index f1249f7..8d2ee1b 100644
--- a/src/mesa/drivers/dri/intel/intel_buffers.c
+++ b/src/mesa/drivers/dri/intel/intel_buffers.c
@@ -321,7 +321,7 @@ intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb)
 static void
 intelDrawBuffer(GLcontext * ctx, GLenum mode)
 {
-   if (ctx->DrawBuffer->Name == 0) {
+   if (ctx->DrawBuffer && ctx->DrawBuffer->Name == 0) {
       struct intel_context *const intel = intel_context(ctx);
 
       intel->is_front_buffer_rendering = (mode == GL_FRONT_LEFT);
diff --git a/src/mesa/drivers/dri/intel/intel_context.c b/src/mesa/drivers/dri/intel/intel_context.c
index 3436b8e..f583cdb 100644
--- a/src/mesa/drivers/dri/intel/intel_context.c
+++ b/src/mesa/drivers/dri/intel/intel_context.c
@@ -173,6 +173,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)
 {
@@ -431,6 +455,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 65e6294..9982cff 100644
--- a/src/mesa/drivers/dri/intel/intel_screen.c
+++ b/src/mesa/drivers/dri/intel/intel_screen.c
@@ -214,6 +214,11 @@ static const __DRItexBufferExtension intelTexBufferExtension = {
    intelSetTexBuffer2,
 };
 
+static const __DRI2flushExtension intelFlushExtension = {
+    { __DRI2_FLUSH, __DRI2_FLUSH_VERSION },
+    intelFlushDrawable,
+};
+
 static const __DRIextension *intelScreenExtensions[] = {
     &driReadDrawableExtension,
     &driCopySubBufferExtension.base,
@@ -478,11 +483,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];
@@ -703,11 +706,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;
@@ -834,4 +836,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 a9b9e10..6bdb05e 100644
--- a/src/mesa/drivers/dri/intel/intel_screen.h
+++ b/src/mesa/drivers/dri/intel/intel_screen.h
@@ -104,4 +104,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