Merge branch 'arb_half_float_vertex'
[mesa.git] / src / mesa / drivers / dri / unichrome / via_ioctl.c
index 30ca7f67553525be80b44fa36aef38943f2e298d..c9a31f3383c8a270ec3487c8d6133e6fee9c9ced 100644 (file)
 #include <stdio.h>
 #include <unistd.h>
 
-#include "glheader.h"
-#include "mtypes.h"
-#include "macros.h"
-#include "dd.h"
+#include "main/glheader.h"
+#include "main/mtypes.h"
+#include "main/macros.h"
+#include "main/dd.h"
 #include "swrast/swrast.h"
 
-#include "mm.h"
+#include "main/mm.h"
 #include "via_context.h"
 #include "via_tris.h"
 #include "via_ioctl.h"
-#include "via_state.h"
+#include "via_fb.h"
+#include "via_3d_reg.h"
 
 #include "vblank.h"
 #include "drm.h"
@@ -73,7 +74,7 @@
 #define VIA_BLIT_FILL 0xF0
 #define VIA_BLIT_SET 0xFF
 
-static void dump_dma( viaContextPtr vmesa )
+static void dump_dma( struct via_context *vmesa )
 {
    GLuint i;
    GLuint *data = (GLuint *)vmesa->dma;
@@ -89,7 +90,7 @@ static void dump_dma( viaContextPtr vmesa )
 
 
 
-void viaCheckDma(viaContextPtr vmesa, GLuint bytes)
+void viaCheckDma(struct via_context *vmesa, GLuint bytes)
 {
     VIA_FINISH_PRIM( vmesa );
     if (vmesa->dmaLow + bytes > VIA_DMA_HIGHWATER) {
@@ -105,7 +106,7 @@ void viaCheckDma(viaContextPtr vmesa, GLuint bytes)
 } while (0)
 
 
-static void viaBlit(viaContextPtr vmesa, GLuint bpp,
+static void viaBlit(struct via_context *vmesa, GLuint bpp,
                    GLuint srcBase, GLuint srcPitch, 
                    GLuint dstBase, GLuint dstPitch,
                    GLuint w, GLuint h, 
@@ -116,9 +117,12 @@ static void viaBlit(viaContextPtr vmesa, GLuint bpp,
     GLuint dwGEMode, srcX, dstX, cmd;
     RING_VARS;
 
-    if (VIA_DEBUG)
-       fprintf(stderr, "%s bpp %d src %x/%x dst %x/%x w %d h %d  mode: %x color: 0x%08x mask 0x%08x\n",
-              __FUNCTION__, bpp, srcBase, srcPitch, dstBase, dstPitch, w,h, blitMode, color, nMask);
+    if (VIA_DEBUG & DEBUG_2D)
+       fprintf(stderr, 
+              "%s bpp %d src %x/%x dst %x/%x w %d h %d "
+              " mode: %x color: 0x%08x mask 0x%08x\n",
+              __FUNCTION__, bpp, srcBase, srcPitch, dstBase,
+              dstPitch, w,h, blitMode, color, nMask);
 
 
     if (!w || !h)
@@ -166,8 +170,8 @@ static void viaBlit(viaContextPtr vmesa, GLuint bpp,
     ADVANCE_RING();
 }
 
-static void viaFillBuffer(viaContextPtr vmesa,
-                         viaBuffer *buffer,
+static void viaFillBuffer(struct via_context *vmesa,
+                         struct via_renderbuffer *buffer,
                          drm_clip_rect_t *pbox,
                          int nboxes,
                          GLuint pixel,
@@ -177,12 +181,12 @@ static void viaFillBuffer(viaContextPtr vmesa,
    GLuint i;
 
    for (i = 0; i < nboxes ; i++) {        
-      int x = pbox[i].x1 - vmesa->drawX;
-      int y = pbox[i].y1 - vmesa->drawY;
+      int x = pbox[i].x1 - buffer->drawX;
+      int y = pbox[i].y1 - buffer->drawY;
       int w = pbox[i].x2 - pbox[i].x1;
       int h = pbox[i].y2 - pbox[i].y1;
 
-      int offset = (buffer->orig + 
+      int offset = (buffer->offset + 
                    y * buffer->pitch + 
                    x * bytePerPixel);
 
@@ -197,11 +201,12 @@ static void viaFillBuffer(viaContextPtr vmesa,
 
 
 
-static void viaClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
-                     GLint cx, GLint cy, GLint cw, GLint ch)
+static void viaClear(GLcontext *ctx, GLbitfield mask)
 {
-   viaContextPtr vmesa = VIA_CONTEXT(ctx);
-   __DRIdrawablePrivate *dPriv = vmesa->driDrawable;
+   struct via_context *vmesa = VIA_CONTEXT(ctx);
+   __DRIdrawable *dPriv = vmesa->driDrawable;
+   struct via_renderbuffer *const vrb = 
+     (struct via_renderbuffer *) dPriv->driverPrivate;
    int flag = 0;
    GLuint i = 0;
    GLuint clear_depth_mask = 0xf << 28;
@@ -209,56 +214,76 @@ static void viaClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
 
    VIA_FLUSH_DMA(vmesa);
 
-   if (mask & DD_FRONT_LEFT_BIT) {
+   if (mask & BUFFER_BIT_FRONT_LEFT) {
       flag |= VIA_FRONT;
-      mask &= ~DD_FRONT_LEFT_BIT;
+      mask &= ~BUFFER_BIT_FRONT_LEFT;
    }
 
-   if (mask & DD_BACK_LEFT_BIT) {
+   if (mask & BUFFER_BIT_BACK_LEFT) {
       flag |= VIA_BACK;        
-      mask &= ~DD_BACK_LEFT_BIT;
+      mask &= ~BUFFER_BIT_BACK_LEFT;
    }
 
-   if (mask & DD_DEPTH_BIT) {
+   if (mask & BUFFER_BIT_DEPTH) {
       flag |= VIA_DEPTH;
       clear_depth = (GLuint)(ctx->Depth.Clear * vmesa->ClearDepth);
       clear_depth_mask &= ~vmesa->depth_clear_mask;
-      mask &= ~DD_DEPTH_BIT;
+      mask &= ~BUFFER_BIT_DEPTH;
    }
     
-   if (mask & DD_STENCIL_BIT) {
+   if (mask & BUFFER_BIT_STENCIL) {
       if (vmesa->have_hw_stencil) {
-        if (ctx->Stencil.WriteMask[0] == 0xff) {
+        if ((ctx->Stencil.WriteMask[0] & 0xff) == 0xff) {
            flag |= VIA_DEPTH;
            clear_depth &= ~0xff;
            clear_depth |= (ctx->Stencil.Clear & 0xff);
            clear_depth_mask &= ~vmesa->stencil_clear_mask;
-           mask &= ~DD_STENCIL_BIT;
+           mask &= ~BUFFER_BIT_STENCIL;
         }
         else {
-           if (VIA_DEBUG)
-              fprintf(stderr, "XXX: Clear stencil writemask %x -- need triangles (or a ROP?)\n", 
+           if (VIA_DEBUG & DEBUG_2D)
+              fprintf(stderr, "Clear stencil writemask %x\n", 
                       ctx->Stencil.WriteMask[0]);
         }
       }
    }
+
+   /* 16bpp doesn't support masked clears */
+   if (vmesa->viaScreen->bytesPerPixel == 2 &&
+       vmesa->ClearMask & 0xf0000000) {
+      if (flag & VIA_FRONT)
+         mask |= BUFFER_BIT_FRONT_LEFT;
+      if (flag & VIA_BACK)
+         mask |= BUFFER_BIT_BACK_LEFT;
+      flag &= ~(VIA_FRONT | VIA_BACK);
+   }
     
    if (flag) {
       drm_clip_rect_t *boxes, *tmp_boxes = 0;
       int nr = 0;
+      GLint cx, cy, cw, ch;
+      GLboolean all;
 
       LOCK_HARDWARE(vmesa);
            
+      /* get region after locking: */
+      cx = ctx->DrawBuffer->_Xmin;
+      cy = ctx->DrawBuffer->_Ymin;
+      cw = ctx->DrawBuffer->_Xmax - cx;
+      ch = ctx->DrawBuffer->_Ymax - cy;
+      all = (cw == ctx->DrawBuffer->Width && ch == ctx->DrawBuffer->Height);
+
       /* flip top to bottom */
       cy = dPriv->h - cy - ch;
-      cx += vmesa->drawX + vmesa->drawXoff;
-      cy += vmesa->drawY;
+      cx += vrb->drawX;
+      cy += vrb->drawY;
         
       if (!all) {
         drm_clip_rect_t *b = vmesa->pClipRects;         
         
-        boxes = tmp_boxes = (drm_clip_rect_t *)malloc(vmesa->numClipRects * 
-                                                      sizeof(drm_clip_rect_t)); 
+        boxes = tmp_boxes = 
+           (drm_clip_rect_t *)malloc(vmesa->numClipRects * 
+                                     sizeof(drm_clip_rect_t)); 
         if (!boxes) {
            UNLOCK_HARDWARE(vmesa);
            return;
@@ -290,15 +315,18 @@ static void viaClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
       }
            
       if (flag & VIA_FRONT) {
-        viaFillBuffer(vmesa, &vmesa->front, boxes, nr, vmesa->ClearColor, vmesa->ClearMask);
+        viaFillBuffer(vmesa, &vmesa->front, boxes, nr, vmesa->ClearColor,
+                      vmesa->ClearMask);
       } 
                
       if (flag & VIA_BACK) {
-        viaFillBuffer(vmesa, &vmesa->back, boxes, nr, vmesa->ClearColor, vmesa->ClearMask);
+        viaFillBuffer(vmesa, &vmesa->back, boxes, nr, vmesa->ClearColor, 
+                      vmesa->ClearMask);
       }
 
       if (flag & VIA_DEPTH) {
-        viaFillBuffer(vmesa, &vmesa->depth, boxes, nr, clear_depth, clear_depth_mask);
+        viaFillBuffer(vmesa, &vmesa->depth, boxes, nr, clear_depth,
+                      clear_depth_mask);
       }                
 
       viaFlushDmaLocked(vmesa, VIA_NO_CLIPRECTS);
@@ -309,29 +337,29 @@ static void viaClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
    }
    
    if (mask)
-      _swrast_Clear(ctx, mask, all, cx, cy, cw, ch);
+      _swrast_Clear(ctx, mask);
 }
 
 
 
 
-static void viaDoSwapBuffers(viaContextPtr vmesa,
+static void viaDoSwapBuffers(struct via_context *vmesa,
                             drm_clip_rect_t *b,
                             GLuint nbox)
 {    
    GLuint bytePerPixel = vmesa->viaScreen->bitsPerPixel >> 3;
-   viaBuffer *front = &vmesa->front;
-   viaBuffer *back = &vmesa->back;
+   struct via_renderbuffer *front = &vmesa->front;
+   struct via_renderbuffer *back = &vmesa->back;
    GLuint i;
         
    for (i = 0; i < nbox; i++, b++) {        
-      GLint x = b->x1 - vmesa->drawX;
-      GLint y = b->y1 - vmesa->drawY;
+      GLint x = b->x1 - back->drawX;
+      GLint y = b->y1 - back->drawY;
       GLint w = b->x2 - b->x1;
       GLint h = b->y2 - b->y1;
        
-      GLuint src = back->orig + y * back->pitch + x * bytePerPixel;
-      GLuint dest = front->orig + y * front->pitch + x * bytePerPixel;
+      GLuint src = back->offset + y * back->pitch + x * bytePerPixel;
+      GLuint dest = front->offset + y * front->pitch + x * bytePerPixel;
 
       viaBlit(vmesa, 
              bytePerPixel << 3, 
@@ -340,96 +368,302 @@ static void viaDoSwapBuffers(viaContextPtr vmesa,
              w, h,
              VIA_BLIT_COPY, 0, 0); 
    }
+
+   viaFlushDmaLocked(vmesa, VIA_NO_CLIPRECTS); /* redundant */
 }
 
 
+static void viaEmitBreadcrumbLocked( struct via_context *vmesa )
+{
+   struct via_renderbuffer *buffer = &vmesa->breadcrumb;
+   GLuint value = vmesa->lastBreadcrumbWrite + 1;
 
+   if (VIA_DEBUG & DEBUG_IOCTL) 
+      fprintf(stderr, "%s %d\n", __FUNCTION__, value);
 
-/*
- * Copy the back buffer to the front buffer. 
- */
-void viaCopyBuffer(const __DRIdrawablePrivate *dPriv)
+   assert(!vmesa->dmaLow);
+
+   viaBlit(vmesa,
+          buffer->bpp, 
+          buffer->offset, buffer->pitch,
+          buffer->offset, buffer->pitch, 
+          1, 1,
+          VIA_BLIT_FILL, value, 0); 
+
+   viaFlushDmaLocked(vmesa, VIA_NO_CLIPRECTS); /* often redundant */
+   vmesa->lastBreadcrumbWrite = value;
+}
+
+void viaEmitBreadcrumb( struct via_context *vmesa )
 {
-   viaContextPtr vmesa = (viaContextPtr)dPriv->driContextPriv->driverPrivate;
-   GLboolean missed_target;
+   LOCK_HARDWARE(vmesa);
+   if (vmesa->dmaLow) 
+      viaFlushDmaLocked(vmesa, 0);
+
+   viaEmitBreadcrumbLocked( vmesa );
+   UNLOCK_HARDWARE(vmesa);
+}
+
+static GLboolean viaCheckIdle( struct via_context *vmesa )
+{
+   if ((vmesa->regEngineStatus[0] & 0xFFFEFFFF) == 0x00020000) {
+      return GL_TRUE;
+   }
+   return GL_FALSE;
+}
+
+
+GLboolean viaCheckBreadcrumb( struct via_context *vmesa, GLuint value )
+{
+   GLuint *buf = (GLuint *)vmesa->breadcrumb.map; 
+   vmesa->lastBreadcrumbRead = *buf;
+
+   if (VIA_DEBUG & DEBUG_IOCTL) 
+      fprintf(stderr, "%s %d < %d: %d\n", __FUNCTION__, value, 
+             vmesa->lastBreadcrumbRead,
+             !VIA_GEQ_WRAP(value, vmesa->lastBreadcrumbRead));
+
+   return !VIA_GEQ_WRAP(value, vmesa->lastBreadcrumbRead);
+}
+
+static void viaWaitBreadcrumb( struct via_context *vmesa, GLuint value )
+{
+   if (VIA_DEBUG & DEBUG_IOCTL) 
+      fprintf(stderr, "%s %d\n", __FUNCTION__, value);
+
+   assert(!VIA_GEQ_WRAP(value, vmesa->lastBreadcrumbWrite));
+
+   while (!viaCheckBreadcrumb( vmesa, value )) {
+      viaSwapOutWork( vmesa );
+      via_release_pending_textures( vmesa );
+   }
+}
 
+
+void viaWaitIdle( struct via_context *vmesa, GLboolean light )
+{
    VIA_FLUSH_DMA(vmesa);
-   driWaitForVBlank( dPriv, & vmesa->vbl_seq, vmesa->vblank_flags, & missed_target );
-   if ( missed_target ) {
-      vmesa->swap_missed_count++;
-      vmesa->get_ust( &vmesa->swap_missed_ust );
+
+   if (VIA_DEBUG & DEBUG_IOCTL)
+      fprintf(stderr, "%s lastDma %d lastBreadcrumbWrite %d\n",
+             __FUNCTION__, vmesa->lastDma, vmesa->lastBreadcrumbWrite);
+
+   /* Need to emit a new breadcrumb?
+    */
+   if (vmesa->lastDma == vmesa->lastBreadcrumbWrite) {
+      LOCK_HARDWARE(vmesa);
+      viaEmitBreadcrumbLocked( vmesa );
+      UNLOCK_HARDWARE(vmesa);
    }
-   LOCK_HARDWARE(vmesa);
 
-   viaDoSwapBuffers(vmesa, dPriv->pClipRects, dPriv->numClipRects);
-   viaFlushDmaLocked(vmesa, VIA_NO_CLIPRECTS);
+   /* Need to wait?
+    */
+   if (VIA_GEQ_WRAP(vmesa->lastDma, vmesa->lastBreadcrumbRead)) 
+      viaWaitBreadcrumb( vmesa, vmesa->lastDma );
 
+   if (light) return;
+
+   LOCK_HARDWARE(vmesa);
+   while(!viaCheckIdle(vmesa))
+      ;
    UNLOCK_HARDWARE(vmesa);
-   vmesa->swap_count++;
-   vmesa->get_ust( &vmesa->swap_ust );
+   via_release_pending_textures(vmesa);
+}
+
+
+void viaWaitIdleLocked( struct via_context *vmesa, GLboolean light )
+{
+   if (vmesa->dmaLow) 
+      viaFlushDmaLocked(vmesa, 0);
+
+   if (VIA_DEBUG & DEBUG_IOCTL)
+      fprintf(stderr, "%s lastDma %d lastBreadcrumbWrite %d\n",
+             __FUNCTION__, vmesa->lastDma, vmesa->lastBreadcrumbWrite);
+
+   /* Need to emit a new breadcrumb?
+    */
+   if (vmesa->lastDma == vmesa->lastBreadcrumbWrite) {
+      viaEmitBreadcrumbLocked( vmesa );
+   }
+
+   /* Need to wait?
+    */
+   if (vmesa->lastDma >= vmesa->lastBreadcrumbRead) 
+      viaWaitBreadcrumb( vmesa, vmesa->lastDma );
+
+   if (light) return;
+
+   while(!viaCheckIdle(vmesa))
+      ;
+
+   via_release_pending_textures(vmesa);
 }
 
+
+
+/* Wait for command stream to be processed *and* the next vblank to
+ * occur.  Equivalent to calling WAIT_IDLE() and then WaitVBlank,
+ * except that WAIT_IDLE() will spin the CPU polling, while this is
+ * IRQ driven.
+ */
+static void viaWaitIdleVBlank(  __DRIdrawable *dPriv, 
+                              struct via_context *vmesa,
+                              GLuint value )
+{
+   GLboolean missed_target;
+   __DRIscreen *psp = dPriv->driScreenPriv;
+
+   VIA_FLUSH_DMA(vmesa); 
+
+   if (!value)
+      return;
+
+   do {
+      if (value < vmesa->lastBreadcrumbRead ||
+         vmesa->thrashing)
+        viaSwapOutWork(vmesa);
+
+      driWaitForVBlank( dPriv, & missed_target );
+      if ( missed_target ) {
+        vmesa->swap_missed_count++;
+        (*psp->systemTime->getUST)( &vmesa->swap_missed_ust );
+      }
+   } 
+   while (!viaCheckBreadcrumb(vmesa, value));   
+
+   vmesa->thrashing = 0;       /* reset flag on swap */
+   vmesa->swap_count++;   
+   via_release_pending_textures( vmesa );
+}
+
+
+
+static void viaDoPageFlipLocked(struct via_context *vmesa, GLuint offset)
+{
+   RING_VARS;
+
+   if (VIA_DEBUG & DEBUG_2D)
+      fprintf(stderr, "%s %x\n", __FUNCTION__, offset);
+
+   if (!vmesa->nDoneFirstFlip) {
+      vmesa->nDoneFirstFlip = GL_TRUE;
+      BEGIN_RING(4);
+      OUT_RING(HALCYON_HEADER2);
+      OUT_RING(0x00fe0000);
+      OUT_RING(0x0000000e);
+      OUT_RING(0x0000000e);
+      ADVANCE_RING();
+   }
+
+   BEGIN_RING(4);
+   OUT_RING( HALCYON_HEADER2 );
+   OUT_RING( 0x00fe0000 );
+   OUT_RING((HC_SubA_HFBBasL << 24) | (offset & 0xFFFFF8) | 0x2);
+   OUT_RING((HC_SubA_HFBDrawFirst << 24) |
+           ((offset & 0xFF000000) >> 24) | 0x0100);
+   ADVANCE_RING();
+
+   vmesa->pfCurrentOffset = vmesa->sarea->pfCurrentOffset = offset;
+
+   viaFlushDmaLocked(vmesa, VIA_NO_CLIPRECTS); /* often redundant */
+}
+
+void viaResetPageFlippingLocked(struct via_context *vmesa)
+{
+   if (VIA_DEBUG & DEBUG_2D)
+      fprintf(stderr, "%s\n", __FUNCTION__);
+
+   viaDoPageFlipLocked( vmesa, 0 );
+
+   if (vmesa->front.offset != 0) {
+      struct via_renderbuffer buffer_tmp;
+      memcpy(&buffer_tmp, &vmesa->back, sizeof(struct via_renderbuffer));
+      memcpy(&vmesa->back, &vmesa->front, sizeof(struct via_renderbuffer));
+      memcpy(&vmesa->front, &buffer_tmp, sizeof(struct via_renderbuffer));
+   }
+
+   assert(vmesa->front.offset == 0);
+   vmesa->doPageFlip = vmesa->allowPageFlip = 0;
+}
+
+
 /*
- * XXX implement when full-screen extension is done.
+ * Copy the back buffer to the front buffer. 
  */
-void viaPageFlip(const __DRIdrawablePrivate *dPriv)
+void viaCopyBuffer(__DRIdrawable *dPriv)
 {
-    viaContextPtr vmesa = (viaContextPtr)dPriv->driContextPriv->driverPrivate;
-    viaBuffer buffer_tmp;
-    GLboolean missed_target;
+   struct via_context *vmesa = 
+      (struct via_context *)dPriv->driContextPriv->driverPrivate;
+   __DRIscreen *psp = dPriv->driScreenPriv;
+
+   if (VIA_DEBUG & DEBUG_IOCTL)
+      fprintf(stderr, 
+             "%s: lastSwap[1] %d lastSwap[0] %d lastWrite %d lastRead %d\n",
+             __FUNCTION__,
+             vmesa->lastSwap[1], 
+             vmesa->lastSwap[0], 
+             vmesa->lastBreadcrumbWrite,
+             vmesa->lastBreadcrumbRead);
 
+   VIA_FLUSH_DMA(vmesa);
 
-    VIA_FLUSH_DMA(vmesa);
-    driWaitForVBlank( dPriv, &vmesa->vbl_seq, vmesa->vblank_flags, &missed_target );
-    if ( missed_target ) {
-       vmesa->swap_missed_count++;
-       vmesa->get_ust( &vmesa->swap_missed_ust );
-    }
-    LOCK_HARDWARE(vmesa);
+   if (dPriv->vblFlags == VBLANK_FLAG_SYNC &&
+       vmesa->lastBreadcrumbWrite > 1)
+      viaWaitIdleVBlank(dPriv, vmesa, vmesa->lastBreadcrumbWrite-1);
+   else
+      viaWaitIdleVBlank(dPriv, vmesa, vmesa->lastSwap[1]);
 
-    {
-        RING_VARS;
-
-       if (!vmesa->nDoneFirstFlip) {
-           vmesa->nDoneFirstFlip = GL_FALSE; /* XXX: FIXME LATER!!! */
-           BEGIN_RING(4);
-           OUT_RING(HALCYON_HEADER2);
-           OUT_RING(0x00fe0000);
-           OUT_RING(0x0000000e);
-           OUT_RING(0x0000000e);
-           ADVANCE_RING();
-       }
-
-       BEGIN_RING(4);
-       OUT_RING( HALCYON_HEADER2 );
-       OUT_RING( 0x00fe0000 );
-       OUT_RING((HC_SubA_HFBBasL << 24) | (vmesa->back.offset & 0xFFFFF8) | 0x2);
-       OUT_RING((HC_SubA_HFBDrawFirst << 24) |
-                ((vmesa->back.offset & 0xFF000000) >> 24) | 0x0100);
-       ADVANCE_RING();
+   LOCK_HARDWARE(vmesa);
 
-    }
+   /* Catch and cleanup situation where we were pageflipping but have
+    * stopped.
+    */
+   if (dPriv->numClipRects && vmesa->sarea->pfCurrentOffset != 0) {
+      viaResetPageFlippingLocked(vmesa);
+      UNLOCK_HARDWARE(vmesa);
+      return;
+   }
+
+   viaDoSwapBuffers(vmesa, dPriv->pClipRects, dPriv->numClipRects);
+   vmesa->lastSwap[1] = vmesa->lastSwap[0];
+   vmesa->lastSwap[0] = vmesa->lastBreadcrumbWrite;
+   viaEmitBreadcrumbLocked(vmesa);
+   UNLOCK_HARDWARE(vmesa);
+
+   (*psp->systemTime->getUST)( &vmesa->swap_ust );
+}
 
-    viaFlushDmaLocked(vmesa, VIA_NO_CLIPRECTS);    
+
+void viaPageFlip(__DRIdrawable *dPriv)
+{
+    struct via_context *vmesa = 
+       (struct via_context *)dPriv->driContextPriv->driverPrivate;
+    struct via_renderbuffer buffer_tmp;
+    __DRIscreen *psp = dPriv->driScreenPriv;
+
+    VIA_FLUSH_DMA(vmesa);
+   if (dPriv->vblFlags == VBLANK_FLAG_SYNC &&
+       vmesa->lastBreadcrumbWrite > 1)
+      viaWaitIdleVBlank(dPriv, vmesa, vmesa->lastBreadcrumbWrite - 1);
+   else
+      viaWaitIdleVBlank(dPriv, vmesa, vmesa->lastSwap[0]);
+
+    LOCK_HARDWARE(vmesa);
+    viaDoPageFlipLocked(vmesa, vmesa->back.offset);
+    vmesa->lastSwap[1] = vmesa->lastSwap[0];
+    vmesa->lastSwap[0] = vmesa->lastBreadcrumbWrite;
+    viaEmitBreadcrumbLocked(vmesa);
     UNLOCK_HARDWARE(vmesa);
-    vmesa->swap_count++;
-    vmesa->get_ust( &vmesa->swap_ust );
+
+    (*psp->systemTime->getUST)( &vmesa->swap_ust );
+
 
     /* KW: FIXME: When buffers are freed, could free frontbuffer by
      * accident:
      */
-    memcpy(&buffer_tmp, &vmesa->back, sizeof(viaBuffer));
-    memcpy(&vmesa->back, &vmesa->front, sizeof(viaBuffer));
-    memcpy(&vmesa->front, &buffer_tmp, sizeof(viaBuffer));
-    
-    if(vmesa->currentPage) {
-       vmesa->currentPage = 0;
-    }
-    else {
-       vmesa->currentPage = 1;
-    }
-
-    if (VIA_DEBUG) fprintf(stderr, "%s - out\n", __FUNCTION__);        
+    memcpy(&buffer_tmp, &vmesa->back, sizeof(struct via_renderbuffer));
+    memcpy(&vmesa->back, &vmesa->front, sizeof(struct via_renderbuffer));
+    memcpy(&vmesa->front, &buffer_tmp, sizeof(struct via_renderbuffer));
 }
 
 
@@ -437,7 +671,7 @@ void viaPageFlip(const __DRIdrawablePrivate *dPriv)
 
 #define VIA_CMDBUF_MAX_LAG 50000
 
-static int fire_buffer(viaContextPtr vmesa)
+static int fire_buffer(struct via_context *vmesa)
 {
    drm_via_cmdbuffer_t bufI;
    int ret;
@@ -459,7 +693,8 @@ static int fire_buffer(viaContextPtr vmesa)
       } while (ret == -EAGAIN);
       if (ret) {
         UNLOCK_HARDWARE(vmesa);
-        fprintf(stderr, "%s: DRM_VIA_CMDBUF_SIZE returned %d\n", __FUNCTION__, ret);
+        fprintf(stderr, "%s: DRM_VIA_CMDBUF_SIZE returned %d\n",
+                __FUNCTION__, ret);
         abort();
         return ret;
       }
@@ -472,7 +707,8 @@ static int fire_buffer(viaContextPtr vmesa)
       } while (ret == -EAGAIN);
       if (ret) {
         UNLOCK_HARDWARE(vmesa);
-        fprintf(stderr, "%s: DRM_VIA_CMDBUFFER returned %d\n", __FUNCTION__, ret);
+        fprintf(stderr, "%s: DRM_VIA_CMDBUFFER returned %d\n",
+                __FUNCTION__, ret);
         abort();
         /* If this fails, the original code fell back to the PCI path. 
          */
@@ -482,14 +718,14 @@ static int fire_buffer(viaContextPtr vmesa)
 
       /* Fall through to PCI handling?!?
        */
-      WAIT_IDLE(vmesa);
+      viaWaitIdleLocked(vmesa, GL_FALSE);
    }
            
    ret = drmCommandWrite(vmesa->driFd, DRM_VIA_PCICMD, &bufI, sizeof(bufI));
    if (ret) {
       UNLOCK_HARDWARE(vmesa);
       dump_dma(vmesa);
-      fprintf(stderr, "%s: DRM_VIA_PCICMD returned %d\n", __FUNCTION__, ret);      
+      fprintf(stderr, "%s: DRM_VIA_PCICMD returned %d\n", __FUNCTION__, ret); 
       abort();
    }
 
@@ -501,10 +737,10 @@ static int fire_buffer(viaContextPtr vmesa)
  * into the head of the DMA buffer being flushed.  Fires the buffer
  * for each cliprect.
  */
-static void via_emit_cliprect(viaContextPtr vmesa,
+static void via_emit_cliprect(struct via_context *vmesa,
                              drm_clip_rect_t *b) 
 {
-   viaBuffer *buffer = vmesa->drawBuffer;
+   struct via_renderbuffer *buffer = vmesa->drawBuffer;
    GLuint *vb = (GLuint *)(vmesa->dma + vmesa->dmaCliprectAddr);
 
    GLuint format = (vmesa->viaScreen->bitsPerPixel == 0x20 
@@ -512,10 +748,11 @@ static void via_emit_cliprect(viaContextPtr vmesa,
                    : HC_HDBFM_RGB565);
 
    GLuint pitch = buffer->pitch;
-   GLuint offset = buffer->orig;
+   GLuint offset = buffer->offset;
 
    if (0)
-      fprintf(stderr, "emit cliprect for box %d,%d %d,%d\n", b->x1, b->y1, b->x2, b->y2);
+      fprintf(stderr, "emit cliprect for box %d,%d %d,%d\n", 
+             b->x1, b->y1, b->x2, b->y2);
 
    vb[0] = HC_HEADER2;
    vb[1] = (HC_ParaType_NotTex << 16);
@@ -529,13 +766,11 @@ static void via_emit_cliprect(viaContextPtr vmesa,
       vb[3] = (HC_SubA_HClipLR << 24) | (b->x1 << 12) | b->x2;
    }
            
-   vb[4] = ((HC_SubA_HDBBasL << 24) | (offset & 0xFFFFFF));
-   vb[5] = ((HC_SubA_HDBBasH << 24) | ((offset & 0xFF000000)) >> 24); 
-   vb[6] = ((HC_SubA_HDBFM << 24) | HC_HDBLoc_Local | format | pitch);     
+   vb[4] = (HC_SubA_HDBBasL << 24) | (offset & 0xFFFFFF);
+   vb[5] = (HC_SubA_HDBBasH << 24) | ((offset & 0xFF000000) >> 24); 
 
-   /* Seems to be ignored on CLE266:
-    */
-   vb[7] = ((HC_SubA_HSPXYOS << 24) | ((32 - vmesa->drawXoff) << HC_HSPXOS_SHIFT));
+   vb[6] = (HC_SubA_HSPXYOS << 24);
+   vb[7] = (HC_SubA_HDBFM << 24) | HC_HDBLoc_Local | format | pitch;
 }
 
 
@@ -562,16 +797,17 @@ static int intersect_rect(drm_clip_rect_t *out,
     return 1;
 }
 
-void viaFlushDmaLocked(viaContextPtr vmesa, GLuint flags)
+void viaFlushDmaLocked(struct via_context *vmesa, GLuint flags)
 {
    int i;
    RING_VARS;
 
-   if (VIA_DEBUG)
+   if (VIA_DEBUG & (DEBUG_IOCTL|DEBUG_DMA))
       fprintf(stderr, "%s\n", __FUNCTION__);
 
    if (*(GLuint *)vmesa->driHwLock != (DRM_LOCK_HELD|vmesa->hHWContext) &&
-       *(GLuint *)vmesa->driHwLock != (DRM_LOCK_HELD|DRM_LOCK_CONT|vmesa->hHWContext)) {
+       *(GLuint *)vmesa->driHwLock != 
+       (DRM_LOCK_HELD|DRM_LOCK_CONT|vmesa->hHWContext)) {
       fprintf(stderr, "%s called without lock held\n", __FUNCTION__);
       abort();
    }
@@ -625,13 +861,14 @@ void viaFlushDmaLocked(viaContextPtr vmesa, GLuint flags)
    case 0:
       break;
    default:
-      if (VIA_DEBUG)
+      if (VIA_DEBUG & DEBUG_IOCTL)
         fprintf(stderr, "%s: unaligned value for vmesa->dmaLow: %x\n",
                 __FUNCTION__, vmesa->dmaLow);
    }
 
+   vmesa->lastDma = vmesa->lastBreadcrumbWrite;
 
-   if (VIA_DEBUG)
+   if (VIA_DEBUG & DEBUG_DMA)
       dump_dma( vmesa );
 
    if (flags & VIA_NO_CLIPRECTS) {
@@ -647,22 +884,18 @@ void viaFlushDmaLocked(viaContextPtr vmesa, GLuint flags)
    }
    else if (vmesa->numClipRects) {
       drm_clip_rect_t *pbox = vmesa->pClipRects;
-      if (0) fprintf(stderr, "%s: %d cliprects\n", __FUNCTION__, vmesa->numClipRects);
-      
+
       for (i = 0; i < vmesa->numClipRects; i++) {
         drm_clip_rect_t b;
 
-        b.x1 = pbox[i].x1 - (vmesa->drawX + vmesa->drawXoff);
-        b.x2 = pbox[i].x2 - (vmesa->drawX + vmesa->drawXoff);
-        b.y1 = pbox[i].y1 - vmesa->drawY;
-        b.y2 = pbox[i].y2 - vmesa->drawY;
+        b.x1 = pbox[i].x1;
+        b.x2 = pbox[i].x2;
+        b.y1 = pbox[i].y1;
+        b.y2 = pbox[i].y2;
 
-        if (vmesa->glCtx->Scissor.Enabled &&
+        if (vmesa->scissor &&
             !intersect_rect(&b, &b, &vmesa->scissorRect)) 
            continue;
-        
-        b.x1 += vmesa->drawXoff;
-        b.x2 += vmesa->drawXoff;
 
         via_emit_cliprect(vmesa, &b);
 
@@ -686,12 +919,12 @@ void viaFlushDmaLocked(viaContextPtr vmesa, GLuint flags)
    vmesa->newEmitState = ~0;
 }
 
-void viaWrapPrimitive( viaContextPtr vmesa )
+void viaWrapPrimitive( struct via_context *vmesa )
 {
    GLenum renderPrimitive = vmesa->renderPrimitive;
    GLenum hwPrimitive = vmesa->hwPrimitive;
 
-   if (VIA_DEBUG) fprintf(stderr, "%s\n", __FUNCTION__);
+   if (VIA_DEBUG & DEBUG_PRIMS) fprintf(stderr, "%s\n", __FUNCTION__);
    
    if (vmesa->dmaLastPrim)
       viaFinishPrimitive( vmesa );
@@ -705,7 +938,7 @@ void viaWrapPrimitive( viaContextPtr vmesa )
 
 }
 
-void viaFlushDma(viaContextPtr vmesa)
+void viaFlushDma(struct via_context *vmesa)
 {
    if (vmesa->dmaLow) {
       assert(!vmesa->dmaLastPrim);
@@ -718,15 +951,15 @@ void viaFlushDma(viaContextPtr vmesa)
 
 static void viaFlush(GLcontext *ctx)
 {
-    viaContextPtr vmesa = VIA_CONTEXT(ctx);
+    struct via_context *vmesa = VIA_CONTEXT(ctx);
     VIA_FLUSH_DMA(vmesa);
 }
 
 static void viaFinish(GLcontext *ctx)
 {
-    viaContextPtr vmesa = VIA_CONTEXT(ctx);
+    struct via_context *vmesa = VIA_CONTEXT(ctx);
     VIA_FLUSH_DMA(vmesa);
-    WAIT_IDLE(vmesa);
+    viaWaitIdle(vmesa, GL_FALSE);
 }
 
 static void viaClearStencil(GLcontext *ctx,  int s)