rpms/xorg-x11-drv-intel/devel dri2-page-flip.patch, NONE, 1.1 xorg-x11-drv-intel.spec, 1.19, 1.20

Kristian Høgsberg krh at fedoraproject.org
Sun Aug 9 00:53:26 UTC 2009


Author: krh

Update of /cvs/pkgs/rpms/xorg-x11-drv-intel/devel
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv28330

Modified Files:
	xorg-x11-drv-intel.spec 
Added Files:
	dri2-page-flip.patch 
Log Message:
* Fri Aug 7 2009 Kristian Høgsberg <krh at redhat.com> - 2.8.0-4
- Add dri2-page-flip.patch to enable full screen pageflipping.
  Fixes XKCD #619.


dri2-page-flip.patch:
 drmmode_display.c |  126 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 i830.h            |    6 ++
 i830_dri.c        |   62 ++++++++++++++++++++++++--
 i830_dri.h        |    6 ++
 4 files changed, 194 insertions(+), 6 deletions(-)

--- NEW FILE dri2-page-flip.patch ---
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 814743b..05541de 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -30,6 +30,7 @@
 #endif
 
 #include <errno.h>
+#include <poll.h>
 
 #include <sys/ioctl.h>
 
@@ -43,6 +44,11 @@ typedef struct {
     uint32_t fb_id;
     drmModeResPtr mode_res;
     int cpp;
+    
+    drmEventContext event_context;
+    void *swap_data;
+    int old_fb_id;
+    int flip_count;
 } drmmode_rec, *drmmode_ptr;
 
 typedef struct {
@@ -343,6 +349,7 @@ static PixmapPtr
 drmmode_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
 {
 	ScrnInfoPtr pScrn = crtc->scrn;
+	I830Ptr     pI830 = I830PTR(pScrn);
 	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 	drmmode_ptr drmmode = drmmode_crtc->drmmode;
 	unsigned long rotate_pitch;
@@ -375,12 +382,16 @@ drmmode_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
 	if (drmmode_crtc->rotate_bo)
 		i830_set_pixmap_bo(rotate_pixmap, drmmode_crtc->rotate_bo);
 
+	pI830->shadow_present = TRUE;
+
 	return rotate_pixmap;
 }
 
 static void
 drmmode_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
 {
+	ScrnInfoPtr pScrn = crtc->scrn;
+	I830Ptr     pI830 = I830PTR(pScrn);
 	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 	drmmode_ptr drmmode = drmmode_crtc->drmmode;
 
@@ -398,6 +409,7 @@ drmmode_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *dat
 		dri_bo_unreference(drmmode_crtc->rotate_bo);
 		drmmode_crtc->rotate_bo = NULL;
 	}
+	pI830->shadow_present = FALSE;
 }
 
 static void
@@ -1085,15 +1097,111 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
 	return FALSE;
 }
 
+Bool
+drmmode_do_pageflip(DrawablePtr pDraw, dri_bo *new_front, dri_bo *old_front,
+		    void *data)
+{
+    ScreenPtr pScreen = pDraw->pScreen;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+    xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
+    drmmode_crtc_private_ptr drmmode_crtc = config->crtc[0]->driver_private;
+    drmmode_ptr drmmode = drmmode_crtc->drmmode;
+    unsigned int pitch = pScrn->displayWidth * pI830->cpp;
+    int i;
+    unsigned int crtc_id;
+
+    /*
+     * Create a new handle for the back buffer
+     */
+    drmmode->old_fb_id = drmmode->fb_id;
+    if (drmModeAddFB(drmmode->fd, pScrn->virtualX, pScrn->virtualY,
+		     pScrn->depth, pScrn->bitsPerPixel, pitch,
+		     new_front->handle, &drmmode->fb_id))
+	    goto error_out;
+
+    /*
+     * Queue flips on all enabled CRTCs
+     * Note that if/when we get per-CRTC buffers, we'll have to update this.
+     * Right now it assumes a single shared fb across all CRTCs, with the
+     * kernel fixing up the offset of each CRTC as necessary.
+     *
+     * Also, flips queued on disabled or incorrectly configured displays
+     * may never complete; this is a configuration error.
+     */
+    drmmode->flip_count = 0;
+    for (i = 0; i < config->num_crtc; i++) {
+	    xf86CrtcPtr crtc = config->crtc[i];
+
+	    if (!crtc->enabled)
+		    continue;
+
+	    drmmode_crtc = crtc->driver_private;
+	    crtc_id = drmmode_crtc->mode_crtc->crtc_id;
+	    drmmode->swap_data = data;
+	    if (drmModePageFlip(drmmode->fd, crtc_id, drmmode->fb_id, drmmode)) {
+		    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+			       "flip queue failed: %s\n", strerror(errno));
+		    goto error_undo;
+	    }
+	    drmmode->flip_count++;
+    }
+
+    pScrn->fbOffset = new_front->offset;
+    pI830->front_buffer->bo = new_front;
+    pI830->front_buffer->offset = new_front->offset;
+
+    return TRUE;
+
+error_undo:
+    drmModeRmFB(drmmode->fd, drmmode->fb_id);
+    drmmode->fb_id = drmmode->old_fb_id;
+
+error_out:
+    xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Page flip failed: %s\n",
+	       strerror(errno));
+    return FALSE;
+}
+
 static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = {
 	drmmode_xf86crtc_resize
 };
 
+static void
+drmmode_page_flip_handler(int fd,
+			  unsigned int frame, 
+			  unsigned int tv_sec,
+			  unsigned int tv_usec,
+			  void *user_data)
+{
+    drmmode_ptr drmmode = user_data;
+
+    drmmode->flip_count--;
+    if (drmmode->flip_count > 0)
+	return;
+
+    drmModeRmFB(drmmode->fd, drmmode->old_fb_id);
+
+    DRI2SwapComplete(drmmode->swap_data);
+}
+
+static void
+drm_wakeup_handler(pointer data, int err, pointer p)
+{
+    drmmode_ptr drmmode = data;
+    fd_set *read_mask = p;
+
+    if (err >= 0 && FD_ISSET(drmmode->fd, read_mask))
+	drmHandleEvent(drmmode->fd, &drmmode->event_context);
+}
+
 Bool drmmode_pre_init(ScrnInfoPtr pScrn, int fd, int cpp)
 {
 	xf86CrtcConfigPtr   xf86_config;
+	I830Ptr pI830 = I830PTR(pScrn);
 	drmmode_ptr drmmode;
-	int i;
+	unsigned int i, bad_crtc = 0;
+	int ret;
 
 	drmmode = xnfalloc(sizeof *drmmode);
 	drmmode->fd = fd;
@@ -1120,6 +1227,22 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, int fd, int cpp)
 
 	xf86InitialConfiguration(pScrn, TRUE);
 
+	/* Check for swapbuffers support */
+	ret = drmModePageFlip(drmmode->fd, bad_crtc, 1, NULL);
+	if (ret < 0 && errno == ENOENT) { /* bad CRTC or FB number */
+		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+			   "Kernel page flipping support detected, enabling\n");
+		pI830->use_swap_buffers = TRUE;
+
+		drmmode->event_context.version = DRM_EVENT_CONTEXT_VERSION;
+		drmmode->event_context.page_flip_handler =
+		    drmmode_page_flip_handler;
+		AddGeneralSocket(fd);
+		RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
+					       drm_wakeup_handler,
+					       drmmode);
+	}
+
 	return TRUE;
 }
 
diff --git a/src/i830.h b/src/i830.h
index 58afe76..16e3c55 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -65,6 +65,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "sarea.h"
 #define _XF86DRI_SERVER_
 #include "dri.h"
+#include "dri2.h"
 #include "GL/glxint.h"
 #include "i830_dri.h"
 #include "intel_bufmgr.h"
@@ -395,6 +396,7 @@ typedef struct _I830Rec {
 #endif
 
    XF86ModReqInfo shadowReq; /* to test for later libshadow */
+   Bool shadow_present;
    Rotation rotation;
    void (*PointerMoved)(int, int, int);
    CreateScreenResourcesProcPtr    CreateScreenResources;
@@ -496,6 +498,8 @@ typedef struct _I830Rec {
    int drmSubFD;
    char deviceName[64];
 
+   Bool use_swap_buffers;
+
    /* Broken-out options. */
    OptionInfoPtr Options;
 
@@ -691,6 +695,8 @@ void I830DRI2CloseScreen(ScreenPtr pScreen);
 extern Bool drmmode_pre_init(ScrnInfoPtr pScrn, int fd, int cpp);
 extern int drmmode_get_pipe_from_crtc_id(drm_intel_bufmgr *bufmgr, xf86CrtcPtr crtc);
 extern int drmmode_output_dpms_status(xf86OutputPtr output);
+extern Bool drmmode_do_pageflip(DrawablePtr pDraw, dri_bo *new_front,
+				dri_bo *old_front, void *data);
 extern void drmmode_copy_fb(ScrnInfoPtr pScrn);
 
 extern Bool i830_crtc_on(xf86CrtcPtr crtc);
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 40d11e4..b34b9b7 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -45,6 +45,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include <errno.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <sys/time.h>
+#include <time.h>
 
 #include "xf86.h"
 #include "xf86_OSproc.h"
@@ -73,11 +75,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 extern XF86ModuleData dri2ModuleData;
 #endif
 
-typedef struct {
-    PixmapPtr pPixmap;
-    unsigned int attachment;
-} I830DRI2BufferPrivateRec, *I830DRI2BufferPrivatePtr;
-
 #ifndef USE_DRI2_1_1_0
 static DRI2BufferPtr
 I830DRI2CreateBuffers(DrawablePtr pDraw, unsigned int *attachments, int count)
@@ -359,6 +356,54 @@ I830DRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion,
 
 }
 
+#if DRI2INFOREC_VERSION >= 4
+
+/*
+ * DRI2SwapBuffers should try to do a buffer swap if possible, however:
+ *   - if we're swapping buffers smaller than the screen, we have to blit
+ *   - if the back buffer doesn't match the screen depth, we have to blit
+ *   - otherwise we try to swap, and return to the caller the new front
+ *     and back buffers
+ */
+static Bool
+I830DRI2SwapBuffers(DrawablePtr pDraw,
+		    DRI2BufferPtr front, DRI2BufferPtr back, void *data)
+{
+    ScreenPtr pScreen = pDraw->pScreen;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+    I830DRI2BufferPrivatePtr front_priv, back_priv;
+    dri_bo *tmp_bo;
+    int tmp;
+
+    front_priv = front->driverPrivate;
+    back_priv = back->driverPrivate;
+
+    if (pI830->shadow_present)
+	return FALSE;
+
+    /* Swap BO names so DRI works */
+    tmp = front->name;
+    front->name = back->name;
+    back->name = tmp;
+
+    /* Swap pixmap bos */
+    dri_bo_reference(i830_get_pixmap_bo(front_priv->pPixmap));
+
+    tmp_bo = i830_get_pixmap_bo(front_priv->pPixmap);
+    i830_set_pixmap_bo(front_priv->pPixmap,
+		       i830_get_pixmap_bo(back_priv->pPixmap));
+    i830_set_pixmap_bo(back_priv->pPixmap, tmp_bo); /* should be screen */
+
+    if (front_priv->pPixmap != pScreen->GetScreenPixmap(pScreen))
+	FatalError("swapbuffers with bad front\n");
+
+    /* Page flip the full screen buffer */
+    return drmmode_do_pageflip(pDraw, i830_get_pixmap_bo(front_priv->pPixmap),
+			       i830_get_pixmap_bo(back_priv->pPixmap), data);
+}
+#endif
+
 Bool I830DRI2ScreenInit(ScreenPtr pScreen)
 {
     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
@@ -428,6 +473,13 @@ Bool I830DRI2ScreenInit(ScreenPtr pScreen)
 # endif
 #endif
 
+#if DRI2INFOREC_VERSION >= 4
+    if (pI830->use_swap_buffers) {
+	info.version = 4;
+	info.SwapBuffers = I830DRI2SwapBuffers;
+    }
+#endif
+
     info.CopyRegion = I830DRI2CopyRegion;
 
     return DRI2ScreenInit(pScreen, &info);
diff --git a/src/i830_dri.h b/src/i830_dri.h
index bedbcbe..e35e940 100644
--- a/src/i830_dri.h
+++ b/src/i830_dri.h
@@ -2,6 +2,7 @@
 #ifndef _I830_DRI_H
 #define _I830_DRI_H
 
+#include "xorg-server.h"
 #include "xf86drm.h"
 #include "i830_common.h"
 
@@ -58,4 +59,9 @@ typedef struct {
    int dummy;
 } I830DRIContextRec, *I830DRIContextPtr;
 
+typedef struct {
+    PixmapPtr pPixmap;
+    unsigned int attachment;
+} I830DRI2BufferPrivateRec, *I830DRI2BufferPrivatePtr;
+
 #endif


Index: xorg-x11-drv-intel.spec
===================================================================
RCS file: /cvs/pkgs/rpms/xorg-x11-drv-intel/devel/xorg-x11-drv-intel.spec,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -p -r1.19 -r1.20
--- xorg-x11-drv-intel.spec	4 Aug 2009 05:58:19 -0000	1.19
+++ xorg-x11-drv-intel.spec	9 Aug 2009 00:53:25 -0000	1.20
@@ -8,7 +8,7 @@
 Summary:   Xorg X11 Intel video driver
 Name:      xorg-x11-drv-intel
 Version:   2.8.0
-Release:   3%{?dist}
+Release:   4%{?dist}
 URL:       http://www.x.org
 License:   MIT
 Group:     User Interface/X Hardware Support
@@ -30,6 +30,7 @@ Patch4: intel-abi-fix.patch
 Patch20: intel-2.8.0-kms-get-crtc.patch
 
 Patch30: intel-chip-names.patch
+Patch40: dri2-page-flip.patch
 
 ExclusiveArch: %{ix86} x86_64 ia64
 
@@ -82,6 +83,7 @@ Debugging tools for Intel graphics chips
 %patch4 -p1 -b .abi
 %patch20 -p1 -b .get-crtc
 %patch30 -p1 -b .names
+%patch40 -p1 -b .flip
 
 %build
  
@@ -137,6 +139,10 @@ rm -rf $RPM_BUILD_ROOT
 %{_mandir}/man1/intel_*.1*
 
 %changelog
+* Fri Aug 7 2009 Kristian Høgsberg <krh at redhat.com> - 2.8.0-4
+- Add dri2-page-flip.patch to enable full screen pageflipping.
+  Fixes XKCD #619.
+
 * Tue Aug 04 2009 Dave Airlie <airlied at redhat.com> 2.8.0-3
 - add ABI fixes for RAC removal
 




More information about the fedora-extras-commits mailing list