Michael wrote:
> 
> On Sun, Mar 10, 2002 at 10:44:00PM +0000, Keith Whitwell wrote:
> > Nice.  How kludged is kludged?
> 
> Attached.
> 
> Most of it is just uncommenting what's already there, and adding a call
> (probably in the wrong place as MakeCurrent seems to be called a lot,
> hence the check added to avoid enabling over and over) if
> RADEON_PAGEFLIP exists.  Plus sorting out drawOffset.
> 
> I removed what I assume is either for old clients or a bogus emit_state
> call in the clear stuff, and I suspect an off-by-1 error somewhere,
> which I hacked by removing the -1 from the x2,y2 figures (you get a
> flashing line at the bottom and right of the screen otherwise)
> 
> Lots of things are broken about it (switching to a console, the obvious
> effects with windowed apps, single buffered demos that don't call
> glSwapBuffers don't display anything (there don't appear to be any none
> doublebuffered visuals for the tests in the driver to ever fail?)
> 
> But it seems to work fine with q3, rtcw and fullscreen stuff.
> 
> Occasionally it exits on the dark side too no doubt a call to
> CloseFullScreen would help.
> 
> At the moment 1024x768 (which I expected to get the biggest benefit)
> hits lack of texture space and/or maybe depth clears / lack of
> hierarchical z, even with the pixmap cache set to 1 page and low
> texturing - at the mo this is still only a 2 or 3 fps gain there.
> 

Michael,

I've added some code in the DDX driver to keep the back buffer uptodate so
that the 'flicker' is gone, and pageflipping looks just like normal
swapbuffers.

I've done this with the miext/shadow module keeping track of dirty regions and
then firing off a bunch of blits in the BlockHandler to repair the
backbuffer.  This is pretty simple - 50 lines of code? - there are a couple of
improvements to be made before I commit.

Keith
Index: lib/GL/mesa/src/drv/radeon/radeon_context.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/radeon/radeon_context.c,v
retrieving revision 1.7.2.19
diff -u -r1.7.2.19 radeon_context.c
--- lib/GL/mesa/src/drv/radeon/radeon_context.c 2 May 2002 13:28:07 -0000       
1.7.2.19
+++ lib/GL/mesa/src/drv/radeon/radeon_context.c 20 May 2002 15:27:24 -0000
@@ -70,6 +70,8 @@
 int RADEON_DEBUG = (0);
 #endif
 
+static GLboolean radeonOpenFullScreen( __DRIcontextPrivate *driContextPriv );
+static GLboolean radeonCloseFullScreen( __DRIcontextPrivate *driContextPriv );
 
 
 /* Return the width and height of the given buffer.
@@ -669,6 +671,10 @@
       if (newRadeonCtx->vb.enabled)
         radeonVtxfmtMakeCurrent( newRadeonCtx->glCtx );
 
+      /* FIXME */
+      if (getenv("RADEON_PAGEFLIP") || 1)
+        radeonOpenFullScreen ( driContextPriv ); 
+
    } else {
       if (RADEON_DEBUG & DEBUG_DRI)
         fprintf(stderr, "%s ctx %p\n", __FUNCTION__, NULL);
@@ -699,14 +705,15 @@
 static GLboolean
 radeonOpenFullScreen( __DRIcontextPrivate *driContextPriv )
 {
-   fprintf(stderr, "%s\n", __FUNCTION__);
-#if 0
+#if 1
    radeonContextPtr rmesa = (radeonContextPtr)driContextPriv->driverPrivate;
    GLint ret;
 
+   if (0) fprintf(stderr, "%s\n", __FUNCTION__);
+
    /* FIXME: Do we need to check this?
     */
-   if ( !rmesa->glCtx->Visual.doubleBufferMode )
+   if ( !rmesa->glCtx->Visual.doubleBufferMode || rmesa->doPageFlip )
       return GL_TRUE;
 
    LOCK_HARDWARE( rmesa );
@@ -714,11 +721,12 @@
 
    /* Ignore errors.  If this fails, we simply don't do page flipping.
     */
-   ret = drmRadeonFullScreen( rmesa->driFd, GL_TRUE );
+   ret = drmRadeonFullScreen( rmesa->dri.fd, GL_TRUE );
 
    UNLOCK_HARDWARE( rmesa );
 
    rmesa->doPageFlip = ( ret == 0 );
+   rmesa->currentPage = 0;
 #endif
    return GL_TRUE;
 }
@@ -728,16 +736,16 @@
 static GLboolean
 radeonCloseFullScreen( __DRIcontextPrivate *driContextPriv )
 {
-   fprintf(stderr, "%s\n", __FUNCTION__);
-#if 0
+#if 1
    radeonContextPtr rmesa = (radeonContextPtr)driContextPriv->driverPrivate;
 
+   if (0) fprintf(stderr, "%s\n", __FUNCTION__);
    LOCK_HARDWARE( rmesa );
    radeonWaitForIdleLocked( rmesa );
 
    /* Don't care if this fails, we're not page flipping anymore.
     */
-   drmRadeonFullScreen( rmesa->driFd, GL_FALSE );
+   drmRadeonFullScreen( rmesa->dri.fd, GL_FALSE );
 
    UNLOCK_HARDWARE( rmesa );
 
Index: lib/GL/mesa/src/drv/radeon/radeon_span.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/radeon/radeon_span.c,v
retrieving revision 1.11.2.4
diff -u -r1.11.2.4 radeon_span.c
--- lib/GL/mesa/src/drv/radeon/radeon_span.c    25 Mar 2002 10:27:15 -0000      
1.11.2.4
+++ lib/GL/mesa/src/drv/radeon/radeon_span.c    20 May 2002 15:27:34 -0000
@@ -292,12 +292,22 @@
 
    switch ( mode ) {
    case GL_FRONT_LEFT:
-      rmesa->state.pixel.readOffset = rmesa->radeonScreen->frontOffset;
-      rmesa->state.pixel.readPitch  = rmesa->radeonScreen->frontPitch;
+      if ( rmesa->doPageFlip && rmesa->currentPage == 0 ) {
+        rmesa->state.color.drawOffset = rmesa->radeonScreen->backOffset;
+        rmesa->state.color.drawPitch  = rmesa->radeonScreen->backPitch;
+      } else {
+       rmesa->state.color.drawOffset = rmesa->radeonScreen->frontOffset;
+       rmesa->state.color.drawPitch  = rmesa->radeonScreen->frontPitch;
+      }
       break;
    case GL_BACK_LEFT:
-      rmesa->state.pixel.readOffset = rmesa->radeonScreen->backOffset;
-      rmesa->state.pixel.readPitch  = rmesa->radeonScreen->backPitch;
+      if ( rmesa->doPageFlip && rmesa->currentPage == 1 ) {
+       rmesa->state.color.drawOffset = rmesa->radeonScreen->frontOffset;
+       rmesa->state.color.drawPitch  = rmesa->radeonScreen->frontPitch;
+      } else {
+        rmesa->state.color.drawOffset = rmesa->radeonScreen->backOffset;
+        rmesa->state.color.drawPitch  = rmesa->radeonScreen->backPitch;
+      }
       break;
    default:
       assert(0);
Index: lib/GL/mesa/src/drv/radeon/radeon_state.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/radeon/radeon_state.c,v
retrieving revision 1.10.2.23
diff -u -r1.10.2.23 radeon_state.c
--- lib/GL/mesa/src/drv/radeon/radeon_state.c   10 May 2002 14:38:59 -0000      
1.10.2.23
+++ lib/GL/mesa/src/drv/radeon/radeon_state.c   20 May 2002 15:27:35 -0000
@@ -1508,7 +1508,9 @@
       rmesa->pClipRects = (XF86DRIClipRectPtr)dPriv->pClipRects;
       break;
    case GL_BACK_LEFT:
-      if ( dPriv->numBackClipRects == 0 ) {
+      /* Can't ignore 2d windows if we are page flipping.
+       */
+      if ( dPriv->numBackClipRects == 0 || rmesa->doPageFlip ) {
         rmesa->numClipRects = dPriv->numClipRects;
         rmesa->pClipRects = (XF86DRIClipRectPtr)dPriv->pClipRects;
       }
@@ -1540,14 +1542,24 @@
    switch ( mode ) {
    case GL_FRONT_LEFT:
       FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_FALSE );
-      rmesa->state.color.drawOffset = rmesa->radeonScreen->frontOffset;
-      rmesa->state.color.drawPitch  = rmesa->radeonScreen->frontPitch;
+      if ( rmesa->doPageFlip && rmesa->currentPage == 0 ) {
+        rmesa->state.color.drawOffset = rmesa->radeonScreen->backOffset;
+        rmesa->state.color.drawPitch  = rmesa->radeonScreen->backPitch;
+      } else {
+       rmesa->state.color.drawOffset = rmesa->radeonScreen->frontOffset;
+       rmesa->state.color.drawPitch  = rmesa->radeonScreen->frontPitch;
+      }
       radeonSetCliprects( rmesa, GL_FRONT_LEFT );
       break;
    case GL_BACK_LEFT:
       FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_FALSE );
-      rmesa->state.color.drawOffset = rmesa->radeonScreen->backOffset;
-      rmesa->state.color.drawPitch  = rmesa->radeonScreen->backPitch;
+      if ( rmesa->doPageFlip && rmesa->currentPage == 1 ) {
+       rmesa->state.color.drawOffset = rmesa->radeonScreen->frontOffset;
+       rmesa->state.color.drawPitch  = rmesa->radeonScreen->frontPitch;
+      } else {
+        rmesa->state.color.drawOffset = rmesa->radeonScreen->backOffset;
+        rmesa->state.color.drawPitch  = rmesa->radeonScreen->backPitch;
+      }
       radeonSetCliprects( rmesa, GL_BACK_LEFT );
       break;
    default:
Index: programs/Xserver/hw/xfree86/drivers/ati/Imakefile
===================================================================
RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/drivers/ati/Imakefile,v
retrieving revision 1.7
diff -u -r1.7 Imakefile
--- programs/Xserver/hw/xfree86/drivers/ati/Imakefile   27 Jan 2002 20:05:30 -0000     
 1.7
+++ programs/Xserver/hw/xfree86/drivers/ati/Imakefile   20 May 2002 15:27:39 -0000
@@ -185,6 +185,7 @@
            -I$(XF86SRC)/vgahw -I$(XF86SRC)/fbdevhw \
            -I$(SERVERSRC)/cfb -I$(SERVERSRC)/mfb \
            -I$(SERVERSRC)/fb -I$(SERVERSRC)/mi \
+          -I$(SERVERSRC)/miext/shadow \
            -I$(SERVERSRC)/render -I$(SERVERSRC)/Xext -I$(SERVERSRC)/include \
            $(DRIINCLUDES) -I$(FONTINCSRC) -I$(EXTINCSRC) -I$(XINCLUDESRC)
 #endif
Index: programs/Xserver/hw/xfree86/drivers/ati/radeon.h
===================================================================
RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon.h,v
retrieving revision 1.19.2.1
diff -u -r1.19.2.1 radeon.h
--- programs/Xserver/hw/xfree86/drivers/ati/radeon.h    25 Mar 2002 10:35:48 -0000     
 1.19.2.1
+++ programs/Xserver/hw/xfree86/drivers/ati/radeon.h    20 May 2002 15:27:39 -0000
@@ -368,6 +368,8 @@
     unsigned char     *PCI;             /* Map */
 
     Bool              depthMoves;       /* Enable depth moves -- slow! */
+ 
+    Bool              allowPageFlip;    /* Enable 3d page flipping */
 
     drmSize           agpSize;
     drmHandle         agpMemHandle;     /* Handle from drmAgpAlloc */
Index: programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.c,v
retrieving revision 1.21.2.3
diff -u -r1.21.2.3 radeon_dri.c
--- programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.c        25 Mar 2002 10:35:48 
-0000      1.21.2.3
+++ programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.c        20 May 2002 15:27:39 
+-0000
@@ -46,6 +46,8 @@
 #include "xf86.h"
 #include "windowstr.h"
 
+
+#include "shadow.h"
                                /* GLX/DRI/DRM definitions */
 #define _XF86DRI_SERVER_
 #include "GL/glxtokens.h"
@@ -663,6 +665,60 @@
     info->accel->NeedToSync = TRUE;
 }
 
+
+
+/* Use the miext/shadow module to maintain a list of dirty rectangles.
+ * These are blitted to the back buffer to keep both buffers clean
+ * during page-flipping when the 3d application isn't fullscreen.
+ *
+ * Unlike most use of the shadow code, both buffers are in video
+ * memory.  
+ *
+ * An alternative to this would be to organize for all on-screen
+ * drawing operations to be duplicated for the two buffers.  That
+ * might be faster, but seems like a lot more work...  
+ */
+
+
+/* This should be done *before* XAA syncs or fires its buffer.
+ * Otherwise will have to fire it again???
+ */
+static void
+radeonDRIShadowUpdate (ScreenPtr pScreen, shadowBufPtr pBuf)
+{
+   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+   RADEONInfoPtr info = RADEONPTR(pScrn);
+   RegionPtr damage = &pBuf->damage;
+   int i, num =  REGION_NUM_RECTS(damage);
+   BoxPtr pbox = REGION_RECTS(damage);
+
+/*     xf86DrvMsg(pScreen->myNum, X_WARNING, */
+/*           "%s\n", __FUNCTION__); */
+   
+   (*info->accel->SetupForScreenToScreenCopy)(pScrn, 
+                                             1, 1, GXcopy,
+                                             (CARD32)(-1), -1);
+
+   for (i = 0 ; i < num ; i++, pbox++) {
+/*        xf86DrvMsg(pScreen->myNum, X_WARNING, */
+/*              "box %d: %d,%d %d,%d offset %d,%d\n", */
+/*              i, */
+/*              pbox->x1, pbox->y1,  */
+/*              pbox->x2, pbox->y2,  */
+/*              info->backX, info->backY); */
+      
+      (*info->accel->SubsequentScreenToScreenCopy)(pScrn,
+                                                  pbox->x1,
+                                                  pbox->y1,
+                                                  pbox->x1 + info->backX, 
+                                                  pbox->y1 + info->backY,
+                                                  pbox->x2 - pbox->x1, 
+                                                  pbox->y2 - pbox->y1);
+       
+   }
+} 
+
+
 /* Initialize the AGP state.  Request memory for use in AGP space, and
    initialize the Radeon registers to point to that memory. */
 static Bool RADEONDRIAgpInit(RADEONInfoPtr info, ScreenPtr pScreen)
@@ -1460,6 +1516,8 @@
 
     pRADEONDRI->sarea_priv_offset = sizeof(XF86DRISAREARec);
 
+    shadowInit (pScreen, radeonDRIShadowUpdate, 0);
+
     return TRUE;
 }
 
@@ -1533,3 +1591,6 @@
        info->pVisualConfigsPriv = NULL;
     }
 }
+
+
+
Index: programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c,v
retrieving revision 1.19
diff -u -r1.19 radeon_driver.c
--- programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c     27 Jan 2002 20:05:31 
-0000      1.19
+++ programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c     20 May 2002 15:27:42 
+-0000
@@ -52,7 +52,7 @@
  * This server does not yet support these XFree86 4.0 features:
  * !!!! FIXME !!!!
  *   DDC1 & DDC2
- *   shadowfb
+ *   shadowfb (Note: dri uses shadow for another purpose in radeon_dri_shadow.c)
  *   overlay planes
  *
  * Modified by Marc Aurele La France ([EMAIL PROTECTED]) for ATI driver merge.
@@ -130,6 +130,7 @@
     OPTION_RING_SIZE,
     OPTION_BUFFER_SIZE,
     OPTION_DEPTH_MOVE,
+    OPTION_NO_PAGE_FLIP,
 #endif
     OPTION_CRT_SCREEN,
     OPTION_PANEL_SIZE,
@@ -150,6 +151,7 @@
     { OPTION_RING_SIZE,    "RingSize",         OPTV_INTEGER, {0}, FALSE },
     { OPTION_BUFFER_SIZE,  "BufferSize",       OPTV_INTEGER, {0}, FALSE },
     { OPTION_DEPTH_MOVE,   "EnableDepthMoves", OPTV_BOOLEAN, {0}, FALSE },
+    { OPTION_NO_PAGE_FLIP, "DisablePageFlip",  OPTV_BOOLEAN, {0}, FALSE },
 #endif
     { OPTION_CRT_SCREEN,   "CrtScreen",        OPTV_BOOLEAN, {0}, FALSE},
     { OPTION_PANEL_SIZE,   "PanelSize",        OPTV_ANYSTR,  {0}, FALSE },
@@ -293,6 +295,11 @@
     "GlxSetVisualConfigs",
     NULL
 };
+
+static const char *driShadowSymbols[] = {
+    "shadowInit",
+    NULL
+};
 #endif
 
 static const char *vbeSymbols[] = {
@@ -1980,6 +1987,22 @@
                   "Depth moves disabled by default\n");
     }
 
+    if ((info->allowPageFlip = !xf86ReturnOptValBool(info->Options,
+                                                    OPTION_NO_PAGE_FLIP, 
+                                                    FALSE))) {
+       if (!xf86LoadSubModule(pScrn, "shadow")) {
+         info->allowPageFlip = 0;
+         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling page flipping\n");
+       }
+       else {
+         xf86LoaderReqSymLists(driShadowSymbols, NULL);
+         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Page flipping enabled\n");
+       }
+    } else {
+       xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Disabling page flipping\n");
+    }
+
+
     return TRUE;
 }
 #endif
@@ -2637,7 +2660,7 @@
         * pixmap cache.  Should be enough for a fullscreen background
         * image plus some leftovers.
         */
-       info->textureSize = info->FbMapSize - 6 * bufferSize;
+       info->textureSize = info->FbMapSize - 4 * bufferSize;
 
        /* If that gives us less than half the available memory, let's
         * be greedy and grab some more.  Sorry, I care more about 3D
@@ -2700,6 +2723,9 @@
 
        scanlines = info->backOffset / width_bytes - 1;
        if (scanlines > 8191) scanlines = 8191;
+
+       info->backY = scanlines;
+       info->backX = (info->backOffset - (scanlines * width_bytes - 1)) / cpp;
 
        MemBox.x1 = 0;
        MemBox.y1 = 0;
Index: programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_state.c
===================================================================
RCS file: 
/cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_state.c,v
retrieving revision 1.12.2.8
diff -u -r1.12.2.8 radeon_state.c
--- programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_state.c      25 Mar 
2002 10:29:12 -0000      1.12.2.8
+++ programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_state.c      20 May 
+2002 15:27:48 -0000
@@ -51,7 +51,8 @@
        OUT_RING( CP_PACKET0( RADEON_RE_TOP_LEFT, 0 ) );
        OUT_RING( (box->y1 << 16) | box->x1 );
        OUT_RING( CP_PACKET0( RADEON_RE_WIDTH_HEIGHT, 0 ) );
-       OUT_RING( ((box->y2 - 1) << 16) | (box->x2 - 1) );
+/*     OUT_RING( ((box->y2 - 1) << 16) | (box->x2 - 1) );*/
+       OUT_RING( (box->y2 << 16) | box->x2 );
        ADVANCE_RING();
 }
 
@@ -580,11 +581,12 @@
        radeon_cp_performance_boxes( dev_priv );
 #endif
 
-       BEGIN_RING( 6 );
+       BEGIN_RING( 4 );
 
        RADEON_WAIT_UNTIL_3D_IDLE();
+/*
        RADEON_WAIT_UNTIL_PAGE_FLIPPED();
-
+*/
        OUT_RING( CP_PACKET0( RADEON_CRTC_OFFSET, 0 ) );
 
        if ( dev_priv->current_page == 0 ) {
@@ -1047,6 +1049,7 @@
 
        /* Needed for depth clears via triangles???
         */
+#if 0  
        if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) {
                radeon_emit_state( dev_priv,
                                   &sarea_priv->context_state,
@@ -1058,7 +1061,7 @@
                                       RADEON_UPLOAD_TEX2IMAGES |
                                       RADEON_REQUIRE_QUIESCENCE);
        }
-
+#endif
        radeon_cp_dispatch_clear( dev, &clear, depth_boxes );
 
        return 0;

Reply via email to