i965: Emit zero initialization for NV VP temporaries as required.
[mesa.git] / src / mesa / drivers / dri / unichrome / via_ioctl.c
index 4fd5b30e99883aac82451a257ee1fa70f818dd78..6746f552ae6d3335792d2813be12076ba2f56f71 100644 (file)
@@ -3,7 +3,7 @@
  * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
-v * copy of this software and associated documentation files (the "Software"),
+ * copy of this software and associated documentation files (the "Software"),
  * to deal in the Software without restriction, including without limitation
  * the rights to use, copy, modify, merge, publish, distribute, sub license,
  * and/or sell copies of the Software, and to permit persons to whom the
@@ -24,16 +24,19 @@ v * copy of this software and associated documentation files (the "Software"),
 #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"
@@ -72,25 +75,139 @@ v * copy of this software and associated documentation files (the "Software"),
 #define VIA_BLIT_FILL 0xF0
 #define VIA_BLIT_SET 0xFF
 
-#define DEPTH_SCALE ((1 << 16) - 1)
+static void dump_dma( struct via_context *vmesa )
+{
+   GLuint i;
+   GLuint *data = (GLuint *)vmesa->dma;
+   for (i = 0; i < vmesa->dmaLow; i += 16) {
+      fprintf(stderr, "%04x:   ", i);
+      fprintf(stderr, "%08x  ", *data++);
+      fprintf(stderr, "%08x  ", *data++);
+      fprintf(stderr, "%08x  ", *data++);
+      fprintf(stderr, "%08x\n", *data++);
+   }
+   fprintf(stderr, "******************************************\n");
+}
 
-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) {
-       viaFlushPrims(vmesa);
+       viaFlushDma(vmesa);
     }
 }
 
 
 
-static void viaClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
-                     GLint cx, GLint cy, GLint cw, GLint ch)
+#define SetReg2DAGP(nReg, nData) do {          \
+    OUT_RING( ((nReg) >> 2) | 0xF0000000 );    \
+    OUT_RING( nData );                         \
+} while (0)
+
+
+static void viaBlit(struct via_context *vmesa, GLuint bpp,
+                   GLuint srcBase, GLuint srcPitch, 
+                   GLuint dstBase, GLuint dstPitch,
+                   GLuint w, GLuint h, 
+                   GLuint blitMode, 
+                   GLuint color, GLuint nMask ) 
 {
-   viaContextPtr vmesa = VIA_CONTEXT(ctx);
+
+    GLuint dwGEMode, srcX, dstX, cmd;
+    RING_VARS;
+
+    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)
+        return;
+
+    switch (bpp) {
+    case 16:
+        dwGEMode = VIA_GEM_16bpp;
+       srcX = (srcBase & 0x1f) >> 1;
+       dstX = (dstBase & 0x1f) >> 1;
+        break;
+    case 32:
+        dwGEMode = VIA_GEM_32bpp;
+       srcX = (srcBase & 0x1f) >> 2;
+       dstX = (dstBase & 0x1f) >> 2;
+       break;
+    default:
+        return;
+    }
+
+    switch(blitMode) {
+    case VIA_BLIT_FILL:
+       cmd = VIA_GEC_BLT | VIA_GEC_FIXCOLOR_PAT | (VIA_BLIT_FILL << 24);
+       break;
+    case VIA_BLIT_COPY:
+       cmd = VIA_GEC_BLT | (VIA_BLIT_COPY << 24);
+       break;
+    default:
+        return;
+    }  
+
+    BEGIN_RING(22);
+    SetReg2DAGP( VIA_REG_GEMODE, dwGEMode);
+    SetReg2DAGP( VIA_REG_FGCOLOR, color);
+    SetReg2DAGP( 0x2C, nMask);
+    SetReg2DAGP( VIA_REG_SRCBASE, (srcBase & ~0x1f) >> 3);
+    SetReg2DAGP( VIA_REG_DSTBASE, (dstBase & ~0x1f) >> 3);
+    SetReg2DAGP( VIA_REG_PITCH, VIA_PITCH_ENABLE |
+              (srcPitch >> 3) | ((dstPitch >> 3) << 16));
+    SetReg2DAGP( VIA_REG_SRCPOS, srcX);
+    SetReg2DAGP( VIA_REG_DSTPOS, dstX);
+    SetReg2DAGP( VIA_REG_DIMENSION, (((h - 1) << 16) | (w - 1)));
+    SetReg2DAGP( VIA_REG_GECMD, cmd);
+    SetReg2DAGP( 0x2C, 0x00000000);
+    ADVANCE_RING();
+}
+
+static void viaFillBuffer(struct via_context *vmesa,
+                         struct via_renderbuffer *buffer,
+                         drm_clip_rect_t *pbox,
+                         int nboxes,
+                         GLuint pixel,
+                         GLuint mask)
+{
+   GLuint bytePerPixel = buffer->bpp >> 3;
+   GLuint i;
+
+   for (i = 0; i < nboxes ; i++) {        
+      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->offset + 
+                   y * buffer->pitch + 
+                   x * bytePerPixel);
+
+      viaBlit(vmesa,
+             buffer->bpp, 
+             offset, buffer->pitch,
+             offset, buffer->pitch, 
+             w, h,
+             VIA_BLIT_FILL, pixel, mask); 
+   }
+}
+
+
+
+static void viaClear(GLcontext *ctx, GLbitfield mask)
+{
+   struct via_context *vmesa = VIA_CONTEXT(ctx);
    __DRIdrawablePrivate *dPriv = vmesa->driDrawable;
-   const GLuint colorMask = *((GLuint *)&ctx->Color.ColorMask);
+   struct via_renderbuffer *const vrb = 
+     (struct via_renderbuffer *) dPriv->driverPrivate;
    int flag = 0;
    GLuint i = 0;
    GLuint clear_depth_mask = 0xf << 28;
@@ -98,257 +215,456 @@ static void viaClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
 
    VIA_FLUSH_DMA(vmesa);
 
-   if ((mask & DD_FRONT_LEFT_BIT) && colorMask == ~0) {
+   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) && colorMask == ~0) {
+   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 {
-           fprintf(stderr, "XXX: Clear stencil writemask %x -- need triangles (or a ROP?)\n", 
-                   ctx->Stencil.WriteMask[0]);
-           /* Fixme - clear with triangles */
+           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;
-      cy += vmesa->drawY;
+      cx += vrb->drawX;
+      cy += vrb->drawY;
         
-      if (vmesa->numClipRects) {
-        int nr = MIN2(i + VIA_NR_SAREA_CLIPRECTS, vmesa->numClipRects);
-        drm_clip_rect_t *box = vmesa->pClipRects;
-        drm_clip_rect_t *b = vmesa->sarea->boxes;
-        int n = 0;
-           
-        if (!all) {
-           for (; i < nr; i++) {
-              GLint x = box[i].x1;
-              GLint y = box[i].y1;
-              GLint w = box[i].x2 - x;
-              GLint h = box[i].y2 - y;
-
-              if (x < cx) w -= cx - x, x = cx;
-              if (y < cy) h -= cy - y, y = cy;
-              if (x + w > cx + cw) w = cx + cw - x;
-              if (y + h > cy + ch) h = cy + ch - y;
-              if (w <= 0) continue;
-              if (h <= 0) continue;
-
-              b->x1 = x;
-              b->y1 = y;
-              b->x2 = x + w;
-              b->y2 = y + h;
-              b++;
-              n++;
-           }
-        }
-        else {
-           for (; i < nr; i++) {
-              *b++ = *(drm_clip_rect_t *)&box[i];
-              n++;
-           }
+      if (!all) {
+        drm_clip_rect_t *b = vmesa->pClipRects;         
+        
+        boxes = tmp_boxes = 
+           (drm_clip_rect_t *)malloc(vmesa->numClipRects * 
+                                     sizeof(drm_clip_rect_t)); 
+        if (!boxes) {
+           UNLOCK_HARDWARE(vmesa);
+           return;
         }
-        vmesa->sarea->nbox = n;                
 
+        for (; i < vmesa->numClipRects; i++) {
+           GLint x = b[i].x1;
+           GLint y = b[i].y1;
+           GLint w = b[i].x2 - x;
+           GLint h = b[i].y2 - y;
+
+           if (x < cx) w -= cx - x, x = cx;
+           if (y < cy) h -= cy - y, y = cy;
+           if (x + w > cx + cw) w = cx + cw - x;
+           if (y + h > cy + ch) h = cy + ch - y;
+           if (w <= 0) continue;
+           if (h <= 0) continue;
+
+           boxes[nr].x1 = x;
+           boxes[nr].y1 = y;
+           boxes[nr].x2 = x + w;
+           boxes[nr].y2 = y + h;
+           nr++;
+        }
+      }
+      else {
+        boxes = vmesa->pClipRects;
+        nr = vmesa->numClipRects;
       }
            
       if (flag & VIA_FRONT) {
-        if (vmesa->drawType == GLX_PBUFFER_BIT)
-           viaFillFrontPBuffer(vmesa);
-        else
-           viaFillFrontBuffer(vmesa);
+        viaFillBuffer(vmesa, &vmesa->front, boxes, nr, vmesa->ClearColor,
+                      vmesa->ClearMask);
       } 
                
       if (flag & VIA_BACK) {
-        viaFillBackBuffer(vmesa);
+        viaFillBuffer(vmesa, &vmesa->back, boxes, nr, vmesa->ClearColor, 
+                      vmesa->ClearMask);
       }
 
       if (flag & VIA_DEPTH) {
-        viaFillDepthBuffer(vmesa, clear_depth, clear_depth_mask);
+        viaFillBuffer(vmesa, &vmesa->depth, boxes, nr, clear_depth,
+                      clear_depth_mask);
       }                
 
+      viaFlushDmaLocked(vmesa, VIA_NO_CLIPRECTS);
       UNLOCK_HARDWARE(vmesa);
+
+      if (tmp_boxes)
+        free(tmp_boxes);
    }
    
    if (mask)
-      _swrast_Clear(ctx, mask, all, cx, cy, cw, ch);
-   if (VIA_DEBUG) fprintf(stderr, "%s out\n", __FUNCTION__);    
+      _swrast_Clear(ctx, mask);
 }
 
-/*
- * Copy the back buffer to the front buffer. 
- */
-void viaCopyBuffer(const __DRIdrawablePrivate *dPriv)
+
+
+
+static void viaDoSwapBuffers(struct via_context *vmesa,
+                            drm_clip_rect_t *b,
+                            GLuint nbox)
+{    
+   GLuint bytePerPixel = vmesa->viaScreen->bitsPerPixel >> 3;
+   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 - back->drawX;
+      GLint y = b->y1 - back->drawY;
+      GLint w = b->x2 - b->x1;
+      GLint h = b->y2 - b->y1;
+       
+      GLuint src = back->offset + y * back->pitch + x * bytePerPixel;
+      GLuint dest = front->offset + y * front->pitch + x * bytePerPixel;
+
+      viaBlit(vmesa, 
+             bytePerPixel << 3, 
+             src, back->pitch,
+             dest, front->pitch,
+             w, h,
+             VIA_BLIT_COPY, 0, 0); 
+   }
+
+   viaFlushDmaLocked(vmesa, VIA_NO_CLIPRECTS); /* redundant */
+}
+
+
+static void viaEmitBreadcrumbLocked( struct via_context *vmesa )
 {
-   viaContextPtr vmesa;
-   drm_clip_rect_t *pbox;
-   int nbox, i;
-   GLboolean missed_target;
-   int64_t ust;
+   struct via_renderbuffer *buffer = &vmesa->breadcrumb;
+   GLuint value = vmesa->lastBreadcrumbWrite + 1;
 
-   if (VIA_DEBUG) fprintf(stderr, "%s in\n", __FUNCTION__);        
-   assert(dPriv);
-   assert(dPriv->driContextPriv);
-   assert(dPriv->driContextPriv->driverPrivate);
+   if (VIA_DEBUG & DEBUG_IOCTL) 
+      fprintf(stderr, "%s %d\n", __FUNCTION__, value);
 
-   vmesa = (viaContextPtr)dPriv->driContextPriv->driverPrivate;
-    
+   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 )
+{
+   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 (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);
+   }
+
+   /* Need to wait?
+    */
+   if (VIA_GEQ_WRAP(vmesa->lastDma, vmesa->lastBreadcrumbRead)) 
+      viaWaitBreadcrumb( vmesa, vmesa->lastDma );
+
+   if (light) return;
+
    LOCK_HARDWARE(vmesa);
-    
-   pbox = vmesa->pClipRects;
-   nbox = vmesa->numClipRects;
+   while(!viaCheckIdle(vmesa))
+      ;
+   UNLOCK_HARDWARE(vmesa);
+   via_release_pending_textures(vmesa);
+}
 
-   if (VIA_DEBUG) fprintf(stderr, "%s %d cliprects (%d)\n", 
-                         __FUNCTION__, nbox, vmesa->drawType);
-    
-       
-   if (vmesa->drawType == GLX_PBUFFER_BIT) {
-      viaDoSwapPBuffers(vmesa);
-      if (VIA_DEBUG) fprintf(stderr, "%s SwapPBuffers\n", __FUNCTION__);    
+
+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 );
    }
-   else {
-      for (i = 0; i < nbox; ) {
-        int nr = MIN2(i + VIA_NR_SAREA_CLIPRECTS, dPriv->numClipRects);
-        drm_clip_rect_t *b = (drm_clip_rect_t *)vmesa->sarea->boxes;
 
-        vmesa->sarea->nbox = nr - i;
+   /* 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(  __DRIdrawablePrivate *dPriv, 
+                              struct via_context *vmesa,
+                              GLuint value )
+{
+   GLboolean missed_target;
+   __DRIscreenPrivate *psp = dPriv->driScreenPriv;
+
+   VIA_FLUSH_DMA(vmesa); 
 
-        for (; i < nr; i++)
-           *b++ = pbox[i];
-        viaDoSwapBuffers(vmesa);
-        if (VIA_DEBUG) fprintf(stderr, "%s SwapBuffers\n", __FUNCTION__);    
+   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();
    }
-   UNLOCK_HARDWARE(vmesa);
 
-   vmesa->swap_count++;
-   (*vmesa->get_ust)( & ust );
-   if ( missed_target ) {
-      vmesa->swap_missed_count++;
-      vmesa->swap_missed_ust = ust - vmesa->swap_ust;
+   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));
    }
-    
-   vmesa->swap_ust = ust;
 
-   if (VIA_DEBUG) fprintf(stderr, "%s out\n", __FUNCTION__);        
+   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(__DRIdrawablePrivate *dPriv)
 {
-    /*=* John Sheng [2003.5.31] flip *=*/
-    viaContextPtr vmesa = (viaContextPtr)dPriv->driContextPriv->driverPrivate;
-    GLcontext *ctx = vmesa->glCtx;
-    GLuint nBackBase;
-    viaBuffer buffer_tmp;
-    GLboolean missed_target;
-    int retcode;
+   struct via_context *vmesa = 
+      (struct via_context *)dPriv->driContextPriv->driverPrivate;
+   __DRIscreenPrivate *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);
 
-    if (VIA_DEBUG) fprintf(stderr, "%s - in\n", __FUNCTION__);        
-    assert(dPriv);
-    assert(dPriv->driContextPriv);
-    assert(dPriv->driContextPriv->driverPrivate);
+   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[1]);
 
-    VIA_FLUSH_DMA(vmesa);
+   LOCK_HARDWARE(vmesa);
 
-    /* Now wait for the vblank:
-     */
-    retcode = driWaitForVBlank( dPriv, &vmesa->vbl_seq, 
-                               vmesa->vblank_flags, &missed_target );
-    if ( missed_target ) {
-       vmesa->swap_missed_count++;
-       (void) (*vmesa->get_ust)( &vmesa->swap_missed_ust );
-    }
+   /* Catch and cleanup situation where we were pageflipping but have
+    * stopped.
+    */
+   if (dPriv->numClipRects && vmesa->sarea->pfCurrentOffset != 0) {
+      viaResetPageFlippingLocked(vmesa);
+      UNLOCK_HARDWARE(vmesa);
+      return;
+   }
 
-    LOCK_HARDWARE(vmesa);
+   viaDoSwapBuffers(vmesa, dPriv->pClipRects, dPriv->numClipRects);
+   vmesa->lastSwap[1] = vmesa->lastSwap[0];
+   vmesa->lastSwap[0] = vmesa->lastBreadcrumbWrite;
+   viaEmitBreadcrumbLocked(vmesa);
+   UNLOCK_HARDWARE(vmesa);
 
-    {
-        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();
-       }
-       nBackBase = (vmesa->back.offset );
-
-       BEGIN_RING(4);
-       OUT_RING( HALCYON_HEADER2 );
-       OUT_RING( 0x00fe0000 );
-       OUT_RING((HC_SubA_HFBBasL << 24) | (nBackBase & 0xFFFFF8) | 0x2);
-       OUT_RING((HC_SubA_HFBDrawFirst << 24) |
-                ((nBackBase & 0xFF000000) >> 24) | 0x0100);
-       ADVANCE_RING();
-
-       viaFlushPrimsLocked(vmesa);
-    }
-    
+   (*psp->systemTime->getUST)( &vmesa->swap_ust );
+}
+
+
+void viaPageFlip(__DRIdrawablePrivate *dPriv)
+{
+    struct via_context *vmesa = 
+       (struct via_context *)dPriv->driContextPriv->driverPrivate;
+    struct via_renderbuffer buffer_tmp;
+    __DRIscreenPrivate *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++;
-    (void) (*vmesa->get_ust)( &vmesa->swap_ust );
-   
-    memcpy(&buffer_tmp, &vmesa->back, sizeof(viaBuffer));
-    memcpy(&vmesa->back, &vmesa->front, sizeof(viaBuffer));
-    memcpy(&vmesa->front, &buffer_tmp, sizeof(viaBuffer));
-    
-    /* KW: BOGUS BOGUS BOGUS: The first time an app calls glDrawBuffer
-     * while pageflipping, this will blow up:  FIXME
+    (*psp->systemTime->getUST)( &vmesa->swap_ust );
+
+
+    /* KW: FIXME: When buffers are freed, could free frontbuffer by
+     * accident:
      */
-    if(vmesa->currentPage) {
-       vmesa->currentPage = 0;
-       if (vmesa->glCtx->Color._DrawDestMask[0] == DD_BACK_LEFT_BIT) {
-               ctx->Driver.DrawBuffer(ctx, GL_BACK);
-       }
-       else {
-               ctx->Driver.DrawBuffer(ctx, GL_FRONT);
-       }
-    }
-    else {
-       vmesa->currentPage = 1;
-       if (vmesa->glCtx->Color._DrawDestMask[0] == DD_BACK_LEFT_BIT) {
-               ctx->Driver.DrawBuffer(ctx, GL_BACK);
-       }
-       else {
-               ctx->Driver.DrawBuffer(ctx, GL_FRONT);
-       }
-    }
-    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));
 }
 
 
@@ -356,16 +672,16 @@ void viaPageFlip(const __DRIdrawablePrivate *dPriv)
 
 #define VIA_CMDBUF_MAX_LAG 50000
 
-static int fire_buffer(viaContextPtr vmesa, drm_via_flush_sys_t *buf)
+static int fire_buffer(struct via_context *vmesa)
 {
-   drmVIACommandBuffer bufI;
+   drm_via_cmdbuffer_t bufI;
    int ret;
 
-   bufI.buf = (char *) (buf->index + buf->offset);
-   bufI.size = buf->size;
+   bufI.buf = (char *)vmesa->dma;
+   bufI.size = vmesa->dmaLow;
 
    if (vmesa->useAgp) {
-      drmVIACmdBufSize bSiz;
+      drm_via_cmdbuf_size_t bSiz;
 
       /* Do the CMDBUF_SIZE ioctl:
        */
@@ -377,19 +693,23 @@ static int fire_buffer(viaContextPtr vmesa, drm_via_flush_sys_t *buf)
                                   &bSiz, sizeof(bSiz));
       } while (ret == -EAGAIN);
       if (ret) {
-        fprintf(stderr, "%s: DRM_VIA_CMDBUF_SIZE returned %d\n", __FUNCTION__, ret);
+        UNLOCK_HARDWARE(vmesa);
+        fprintf(stderr, "%s: DRM_VIA_CMDBUF_SIZE returned %d\n",
+                __FUNCTION__, ret);
         abort();
         return ret;
       }
 
-      /* Acutally fire the buffer:
+      /* Actually fire the buffer:
        */
       do {
         ret = drmCommandWrite(vmesa->driFd, DRM_VIA_CMDBUFFER, 
                               &bufI, sizeof(bufI));
       } while (ret == -EAGAIN);
       if (ret) {
-        fprintf(stderr, "%s: DRM_VIA_CMDBUFFER returned %d\n", __FUNCTION__, ret);
+        UNLOCK_HARDWARE(vmesa);
+        fprintf(stderr, "%s: DRM_VIA_CMDBUFFER returned %d\n",
+                __FUNCTION__, ret);
         abort();
         /* If this fails, the original code fell back to the PCI path. 
          */
@@ -399,12 +719,14 @@ static int fire_buffer(viaContextPtr vmesa, drm_via_flush_sys_t *buf)
 
       /* Fall through to PCI handling?!?
        */
-      WAIT_IDLE(vmesa);
+      viaWaitIdleLocked(vmesa, GL_FALSE);
    }
            
    ret = drmCommandWrite(vmesa->driFd, DRM_VIA_PCICMD, &bufI, sizeof(bufI));
    if (ret) {
-      fprintf(stderr, "%s: DRM_VIA_PCICMD returned %d\n", __FUNCTION__, ret);
+      UNLOCK_HARDWARE(vmesa);
+      dump_dma(vmesa);
+      fprintf(stderr, "%s: DRM_VIA_PCICMD returned %d\n", __FUNCTION__, ret); 
       abort();
    }
 
@@ -416,74 +738,40 @@ static int fire_buffer(viaContextPtr vmesa, drm_via_flush_sys_t *buf)
  * into the head of the DMA buffer being flushed.  Fires the buffer
  * for each cliprect.
  */
-static int via_flush_sys(viaContextPtr vmesa, drm_via_flush_sys_t* buf) 
+static void via_emit_cliprect(struct via_context *vmesa,
+                             drm_clip_rect_t *b) 
 {
-   GLuint *vb = (GLuint *)vmesa->dmaAddr;
+   struct via_renderbuffer *buffer = vmesa->drawBuffer;
+   GLuint *vb = (GLuint *)(vmesa->dma + vmesa->dmaCliprectAddr);
+
    GLuint format = (vmesa->viaScreen->bitsPerPixel == 0x20 
                    ? HC_HDBFM_ARGB8888 
                    : HC_HDBFM_RGB565);
 
-   if (vmesa->glCtx->Color._DrawDestMask[0] == DD_BACK_LEFT_BIT) {
-      GLuint offset = vmesa->back.offset;
-      GLuint pitch = vmesa->back.pitch;
+   GLuint pitch = buffer->pitch;
+   GLuint offset = buffer->offset;
 
-      vb[0] = HC_HEADER2;
-      vb[1] = HC_ParaType_NotTex << 16;
-         
-      if (vmesa->driDrawable->w == 0 || vmesa->driDrawable->h == 0) {
-        vb[2] = (HC_SubA_HClipTB << 24) | 0x0;
-        vb[3] = (HC_SubA_HClipLR << 24) | 0x0;
-      }
-      else {
-        vb[2] = (HC_SubA_HClipTB << 24) | vmesa->driDrawable->h;
-        vb[3] = (HC_SubA_HClipLR << 24) | vmesa->driDrawable->w; 
-      }
-       
-      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[7] = 0xcccccccc;
+   if (0)
+      fprintf(stderr, "emit cliprect for box %d,%d %d,%d\n", 
+             b->x1, b->y1, b->x2, b->y2);
 
-      return fire_buffer( vmesa, buf );
+   vb[0] = HC_HEADER2;
+   vb[1] = (HC_ParaType_NotTex << 16);
+
+   if (vmesa->driDrawable->w == 0 || vmesa->driDrawable->h == 0) {
+      vb[2] = (HC_SubA_HClipTB << 24) | 0x0;
+      vb[3] = (HC_SubA_HClipLR << 24) | 0x0;
    }
    else {
-      GLuint i, ret;
-      drm_clip_rect_t *b = vmesa->sarea->boxes;
-               
-      for (i = 0; i < vmesa->sarea->nbox; i++, b++) {        
-        GLuint bytePerPixel = vmesa->viaScreen->bitsPerPixel >> 3;
-        GLuint pitch = vmesa->front.pitch;
-        GLuint offset = (vmesa->viaScreen->fbOffset + (vmesa->drawY * pitch + vmesa->drawX * bytePerPixel)) & ~0x1f;
-
-        GLuint clipL = b->x1 + vmesa->drawXoff;
-        GLuint clipR = b->x2 + vmesa->drawXoff;
-        GLuint clipT = b->y1;
-        GLuint clipB = b->y2;
-           
-        vb[0] = HC_HEADER2;
-        vb[1] = (HC_ParaType_NotTex << 16);
-
-        if (vmesa->driDrawable->w == 0 || vmesa->driDrawable->h == 0) {
-           vb[2] = (HC_SubA_HClipTB << 24) | 0x0;
-           vb[3] = (HC_SubA_HClipLR << 24) | 0x0;
-        }
-        else {
-           vb[2] = (HC_SubA_HClipTB << 24) | (clipT << 12) | clipB;
-           vb[3] = (HC_SubA_HClipLR << 24) | (clipL << 12) | clipR;
-        }
-           
-        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[7] = 0xcccccccc;
-
-        ret = fire_buffer( vmesa, buf );
-        if (ret)
-           return ret;
-      }
+      vb[2] = (HC_SubA_HClipTB << 24) | (b->y1 << 12) | b->y2;
+      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); 
 
-   return 0;
+   vb[6] = (HC_SubA_HSPXYOS << 24);
+   vb[7] = (HC_SubA_HDBFM << 24) | HC_HDBLoc_Local | format | pitch;
 }
 
 
@@ -493,6 +781,11 @@ static int intersect_rect(drm_clip_rect_t *out,
                           drm_clip_rect_t *b)
 {
     *out = *a;
+    
+    if (0)
+       fprintf(stderr, "intersect %d,%d %d,%d and %d,%d %d,%d\n", 
+              a->x1, a->y1, a->x2, a->y2,
+              b->x1, b->y1, b->x2, b->y2);
 
     if (b->x1 > out->x1) out->x1 = b->x1;
     if (b->x2 < out->x2) out->x2 = b->x2;
@@ -505,22 +798,22 @@ static int intersect_rect(drm_clip_rect_t *out,
     return 1;
 }
 
-void viaFlushPrimsLocked(viaContextPtr vmesa)
+void viaFlushDmaLocked(struct via_context *vmesa, GLuint flags)
 {
-   drm_clip_rect_t *pbox = (drm_clip_rect_t *)vmesa->pClipRects;
-   int nbox = vmesa->numClipRects;
-   drm_via_sarea_t *sarea = vmesa->sarea;
-   drm_via_flush_sys_t sysCmd;
    int i;
    RING_VARS;
 
+   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();
    }
 
-   if (vmesa->dmaLow == DMA_OFFSET) {
+   if (vmesa->dmaLow == 0) {
       return;
    }
 
@@ -569,110 +862,108 @@ void viaFlushPrimsLocked(viaContextPtr vmesa)
    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);
-/*       abort(); */
-/*       goto done; */
    }
 
-/*    assert((vmesa->dmaLow & 0x1f) == 0); */
+   vmesa->lastDma = vmesa->lastBreadcrumbWrite;
 
-   sysCmd.offset = 0x0;
-   sysCmd.size = vmesa->dmaLow;
-   sysCmd.index = (GLuint)vmesa->dma;
-   sysCmd.discard = 0;
-    
-   if (!nbox) {
-      sysCmd.size = 0;         /* KW: FIXME bogus if we ever start emitting partial state */
-      sarea->nbox = 0;
-      sysCmd.discard = 1;
-      via_flush_sys(vmesa, &sysCmd);
+   if (VIA_DEBUG & DEBUG_DMA)
+      dump_dma( vmesa );
+
+   if (flags & VIA_NO_CLIPRECTS) {
+      if (0) fprintf(stderr, "%s VIA_NO_CLIPRECTS\n", __FUNCTION__);
+      assert(vmesa->dmaCliprectAddr == ~0);
+      fire_buffer( vmesa );
    }
-   else {
-      for (i = 0; i < nbox; ) {
-        int nr = MIN2(i + VIA_NR_SAREA_CLIPRECTS, nbox);
-        drm_clip_rect_t *b = sarea->boxes;
-
-        if (vmesa->glCtx->Scissor.Enabled) {
-           sarea->nbox = 0;
-
-           for (; i < nr; i++) {
-              b->x1 = pbox[i].x1 - vmesa->drawX;
-              b->y1 = pbox[i].y1 - vmesa->drawY;
-              b->x2 = pbox[i].x2 - vmesa->drawX;
-              b->y2 = pbox[i].y2 - vmesa->drawY;
-              if (intersect_rect(b, b, &vmesa->scissorRect)) {
-                 sarea->nbox++;
-                 b++;
-              }
-           }
-           if (!sarea->nbox) {
-              if (nr < nbox) continue;
-              sysCmd.size = 0;
-           }
-        }
-        else {
-           sarea->nbox = nr - i;
-           for (; i < nr; i++, b++) {
-              b->x1 = pbox[i].x1 - vmesa->drawX;
-              b->y1 = pbox[i].y1 - vmesa->drawY;
-              b->x2 = pbox[i].x2 - vmesa->drawX;
-              b->y2 = pbox[i].y2 - vmesa->drawY;
-           }
-        }
+   else if (vmesa->dmaCliprectAddr == ~0) {
+      /* Contains only state.  Could just dump the packet?
+       */
+      if (0) fprintf(stderr, "%s: no dmaCliprectAddr\n", __FUNCTION__);
+      if (0) fire_buffer( vmesa );
+   }
+   else if (vmesa->numClipRects) {
+      drm_clip_rect_t *pbox = vmesa->pClipRects;
+      __DRIdrawablePrivate *dPriv = vmesa->driDrawable;
+      struct via_renderbuffer *const vrb = 
+       (struct via_renderbuffer *) dPriv->driverPrivate;
 
-        if (nr == nbox) {
-           sysCmd.discard = 1;
-        }
+      for (i = 0; i < vmesa->numClipRects; i++) {
+        drm_clip_rect_t b;
 
-        via_flush_sys(vmesa, &sysCmd);
-      }
-   }
+        b.x1 = pbox[i].x1;
+        b.x2 = pbox[i].x2;
+        b.y1 = pbox[i].y1;
+        b.y2 = pbox[i].y2;
+
+        if (vmesa->scissor &&
+            !intersect_rect(&b, &b, &vmesa->scissorRect)) 
+           continue;
 
-   if (VIA_DEBUG) {
-      GLuint i;
-      GLuint *data = (GLuint *)vmesa->dmaAddr;
-      for (i = 0; i < vmesa->dmaLow; i += 16) {
-        fprintf(stderr, "%04x:   ", i);
-        fprintf(stderr, "%08x  ", *data++);
-        fprintf(stderr, "%08x  ", *data++);
-        fprintf(stderr, "%08x  ", *data++);
-        fprintf(stderr, "%08x\n", *data++);
+        via_emit_cliprect(vmesa, &b);
+
+        if (fire_buffer(vmesa) != 0) {
+           dump_dma( vmesa );
+           goto done;
+        }
       }
-      fprintf(stderr, "******************************************\n");
-   }  
+   } else {
+      if (0) fprintf(stderr, "%s: no cliprects\n", __FUNCTION__);
+      UNLOCK_HARDWARE(vmesa);
+      sched_yield();
+      LOCK_HARDWARE(vmesa);
+   }
 
  done:
    /* Reset vmesa vars:
     */
-   vmesa->dmaLow = DMA_OFFSET;
-   vmesa->dmaAddr = (unsigned char *)vmesa->dma;
+   vmesa->dmaLow = 0;
+   vmesa->dmaCliprectAddr = ~0;
+   vmesa->newEmitState = ~0;
 }
 
-void viaFlushPrims(viaContextPtr vmesa)
+void viaWrapPrimitive( struct via_context *vmesa )
 {
-   if (VIA_DEBUG) fprintf(stderr, "%s in\n", __FUNCTION__);
+   GLenum renderPrimitive = vmesa->renderPrimitive;
+   GLenum hwPrimitive = vmesa->hwPrimitive;
+
+   if (VIA_DEBUG & DEBUG_PRIMS) fprintf(stderr, "%s\n", __FUNCTION__);
+   
+   if (vmesa->dmaLastPrim)
+      viaFinishPrimitive( vmesa );
+   
+   viaFlushDma(vmesa);
+
+   if (renderPrimitive != GL_POLYGON + 1)
+      viaRasterPrimitive( vmesa->glCtx,
+                         renderPrimitive,
+                         hwPrimitive );
+
+}
+
+void viaFlushDma(struct via_context *vmesa)
+{
+   if (vmesa->dmaLow) {
+      assert(!vmesa->dmaLastPrim);
 
-   if (vmesa->dmaLow != DMA_OFFSET) {
       LOCK_HARDWARE(vmesa); 
-      viaFlushPrimsLocked(vmesa);
+      viaFlushDmaLocked(vmesa, 0);
       UNLOCK_HARDWARE(vmesa);
    }
-   if (VIA_DEBUG) fprintf(stderr, "%s in\n", __FUNCTION__);
 }
 
 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)
@@ -689,315 +980,4 @@ void viaInitIoctlFuncs(GLcontext *ctx)
 }
 
 
-#define SetReg2DAGP(nReg, nData) do {          \
-    OUT_RING( ((nReg) >> 2) | 0xF0000000 );    \
-    OUT_RING( nData );                         \
-} while (0)
-
-
-static void viaBlit(viaContextPtr vmesa, GLuint bpp,GLuint srcBase,
-                   GLuint srcPitch,GLuint dstBase,GLuint dstPitch,
-                   GLuint w,GLuint h,int xdir,int ydir, GLuint blitMode, 
-                   GLuint color, GLuint nMask ) 
-{
-
-    GLuint dwGEMode = 0, srcY=0, srcX, dstY=0, dstX;
-    GLuint cmd;
-    RING_VARS;
-
-    if (VIA_DEBUG)
-       fprintf(stderr, "%s bpp %d src %x/%x dst %x/%x w %d h %d dir %d,%d mode: %x color: 0x%08x mask 0x%08x\n",
-              __FUNCTION__, bpp, srcBase, srcPitch, dstBase, dstPitch, w,h, xdir, ydir, blitMode, color, nMask);
-
-
-    if (!w || !h)
-        return;
-
-    srcX = srcBase & 31;
-    dstX = dstBase & 31;
-    switch (bpp) {
-    case 16:
-        dwGEMode |= VIA_GEM_16bpp;
-       srcX >>= 1;
-       dstX >>= 1;
-        break;
-    case 32:
-        dwGEMode |= VIA_GEM_32bpp;
-       srcX >>= 2;
-       dstX >>= 2;
-       break;
-    default:
-        dwGEMode |= VIA_GEM_8bpp;
-        break;
-    }
-
-
-    cmd = 0; 
-
-    if (xdir < 0) {
-        cmd |= VIA_GEC_DECX;
-        srcX += (w - 1);
-        dstX += (w - 1);
-    }
-    if (ydir < 0) {
-        cmd |= VIA_GEC_DECY;
-        srcY += (h - 1);
-        dstY += (h - 1);
-    }
-
-    switch(blitMode) {
-    case VIA_BLIT_FILL:
-        BEGIN_RING((2 + 9) * 2);
-       SetReg2DAGP(VIA_REG_GEMODE, dwGEMode);
-       SetReg2DAGP( VIA_REG_FGCOLOR, color);
-       cmd |= VIA_GEC_BLT | VIA_GEC_FIXCOLOR_PAT | (VIA_BLIT_FILL << 24);
-       break;
-    case VIA_BLIT_COPY:
-        BEGIN_RING((2 + 9) * 2);
-       SetReg2DAGP(VIA_REG_GEMODE, dwGEMode);
-       SetReg2DAGP( VIA_REG_KEYCONTROL, 0x0);
-       cmd |= VIA_GEC_BLT | (VIA_BLIT_COPY << 24);
-    }  
-
-    SetReg2DAGP( 0x2C, nMask);
-    SetReg2DAGP( VIA_REG_SRCBASE, (srcBase & ~31) >> 3);
-    SetReg2DAGP( VIA_REG_DSTBASE, (dstBase & ~31) >> 3);
-    SetReg2DAGP( VIA_REG_PITCH, VIA_PITCH_ENABLE |
-              (srcPitch >> 3) | (((dstPitch) >> 3) << 16));
-    SetReg2DAGP( VIA_REG_SRCPOS, ((srcY << 16) | srcX));
-    SetReg2DAGP( VIA_REG_DSTPOS, ((dstY << 16) | dstX));
-    SetReg2DAGP( VIA_REG_DIMENSION, (((h - 1) << 16) | (w - 1)));
-    SetReg2DAGP( VIA_REG_GECMD, cmd);
-    SetReg2DAGP( 0x2C, 0x00000000);
-    ADVANCE_RING();
-}
-
-void viaFillFrontBuffer(viaContextPtr vmesa)
-{
-    GLuint nDestBase, nDestPitch, nDestWidth, nDestHeight,i; 
-    drm_clip_rect_t *b = vmesa->sarea->boxes;
-    GLuint pixel = (GLuint)vmesa->ClearColor;
-    GLuint bytePerPixel = vmesa->viaScreen->bitsPerPixel >> 3;
-    nDestPitch = vmesa->front.pitch;
-
-    for (i = 0; i < vmesa->sarea->nbox ; i++) {        
-        nDestWidth = b->x2 - b->x1;
-       nDestHeight = b->y2 - b->y1;
-       nDestBase = vmesa->viaScreen->fbOffset + 
-           (b->y1* nDestPitch + b->x1 * bytePerPixel);
-       viaBlit(vmesa,vmesa->viaScreen->bitsPerPixel, nDestBase, nDestPitch,
-               nDestBase , nDestPitch, nDestWidth, nDestHeight,
-               0,0,VIA_BLIT_FILL, pixel, 0x0); 
-       b++;
-    }
-
-    viaFlushPrimsLocked(vmesa);
-}
-
-void viaFillFrontPBuffer(viaContextPtr vmesa)
-{
-    GLuint nDestBase, nDestPitch, nDestWidth, nDestHeight, offset; 
-    GLuint pixel = (GLuint)vmesa->ClearColor;
-
-    offset = vmesa->front.offset;
-    if (VIA_DEBUG) fprintf(stderr, "Fill PFront offset = %08x\n", offset);
-    nDestBase = offset;
-    nDestPitch = vmesa->front.pitch;
-
-    nDestWidth = vmesa->driDrawable->w;
-    nDestHeight = vmesa->driDrawable->h;
-
-    viaBlit(vmesa,vmesa->viaScreen->bitsPerPixel, nDestBase, nDestPitch,
-           nDestBase , nDestPitch, nDestWidth, nDestHeight,
-           0,0,VIA_BLIT_FILL, pixel, 0x0); 
-       
-    viaFlushPrimsLocked(vmesa);
-}
-
-void viaFillBackBuffer(viaContextPtr vmesa)
-{
-    GLuint nDestBase, nDestPitch, nDestWidth, nDestHeight, offset; 
-    GLcontext *ctx = vmesa->glCtx;
-    GLuint pixel = (GLuint)vmesa->ClearColor;
-    GLuint bytePerPixel = vmesa->viaScreen->bitsPerPixel >> 3;
-
-    offset = vmesa->back.offset;
-    if (VIA_DEBUG) fprintf(stderr, "Fill Back offset = %08x\n", offset);
-    nDestBase = offset;
-    nDestPitch = vmesa->back.pitch;
-    
-    if (!ctx->Scissor.Enabled) {
-       nDestWidth = (vmesa->back.pitch / bytePerPixel);
-       nDestHeight = vmesa->driDrawable->h;
-       viaBlit(vmesa,vmesa->viaScreen->bitsPerPixel, nDestBase, nDestPitch,
-               nDestBase , nDestPitch, nDestWidth, nDestHeight,
-               0,0,VIA_BLIT_FILL, pixel, 0x0); 
-       
-    }
-    /*=* John Sheng [2003.7.18] texenv *=*/
-    else {
-       int i;
-       drm_clip_rect_t *b = vmesa->sarea->boxes;
-       for (i = 0; i < vmesa->sarea->nbox ; i++) {        
-           nDestWidth = b->x2 - b->x1;
-           nDestHeight = b->y2 - b->y1;
-           nDestBase = offset + ((b->y1 - vmesa->drawY) * nDestPitch) + 
-               (b->x1 - vmesa->drawX + vmesa->drawXoff) * bytePerPixel;
-           viaBlit(vmesa,vmesa->viaScreen->bitsPerPixel, nDestBase, nDestPitch,
-                   nDestBase , nDestPitch, nDestWidth, nDestHeight,
-                   0,0,VIA_BLIT_FILL, pixel, 0x0); 
-           b++;
-       }
-    }
-    if (VIA_DEBUG) {
-       fprintf(stderr," width = %08x\n", nDestWidth);  
-       fprintf(stderr," height = %08x\n", nDestHeight);        
-    }       
-}
-
-
-void viaFillDepthBuffer(viaContextPtr vmesa, GLuint pixel, GLuint mask)
-{
-    GLuint nDestBase, nDestPitch, nDestWidth, nDestHeight, offsetX, offset;
-
-    offset = vmesa->depth.offset;
-    if (VIA_DEBUG)
-       fprintf(stderr, "Fill Depth offset = %08x, pixel %x, mask %x\n", offset, pixel, mask);
-    nDestBase = offset;
-    nDestPitch = vmesa->depth.pitch;
-    
-    offsetX = vmesa->drawXoff;
-    nDestWidth = (vmesa->depth.pitch / vmesa->depth.bpp * 8) - offsetX;
-    nDestHeight = vmesa->driDrawable->h;
-
-    viaBlit(vmesa, vmesa->depth.bpp , nDestBase, nDestPitch,
-           nDestBase , nDestPitch, nDestWidth, nDestHeight,
-           0,0,VIA_BLIT_FILL, pixel, mask); 
-
-    
-    if (vmesa->glCtx->Color._DrawDestMask[0] == DD_BACK_LEFT_BIT) {
-       viaFlushPrimsLocked(vmesa);
-    }
-}
-
-void viaDoSwapBuffers(viaContextPtr vmesa)
-{    
-    GLuint nFrontPitch;
-    GLuint nBackPitch;
-    GLuint nFrontWidth, nFrontHeight;
-    GLuint nFrontBase, nBackBase;
-    drm_clip_rect_t *b = vmesa->sarea->boxes;
-    GLuint bytePerPixel = vmesa->viaScreen->bitsPerPixel >> 3;
-    GLuint i;
-    
-    nFrontPitch = vmesa->front.pitch;
-    nBackPitch = vmesa->back.pitch;
-    
-    for (i = 0; i < vmesa->sarea->nbox; i++) {        
-
-       /* Width, Height */
-        nFrontWidth = b->x2 - b->x1;
-       nFrontHeight = b->y2 - b->y1;
-       
-       nFrontBase = vmesa->viaScreen->fbOffset + (b->y1* nFrontPitch + 
-                                                  b->x1 * bytePerPixel);
-       nBackBase = vmesa->back.offset + ((b->y1 - vmesa->drawY) * nBackPitch) + 
-           (b->x1 - vmesa->drawX + vmesa->drawXoff) * bytePerPixel;
-       
-       viaBlit(vmesa, bytePerPixel << 3 , nBackBase, nBackPitch,
-               nFrontBase , nFrontPitch, nFrontWidth, nFrontHeight,
-               0,0,VIA_BLIT_COPY, 0, 0); 
-       b++;
-    }
-
-    viaFlushPrimsLocked(vmesa);
-    if (VIA_DEBUG) fprintf(stderr, "Do Swap Buffer\n");
-}
-
-
-void viaDoSwapPBuffers(viaContextPtr vmesa)
-{    
-    GLuint nFrontPitch;
-    GLuint nBackPitch;
-    GLuint nFrontWidth, nFrontHeight;
-    GLuint nFrontBase, nBackBase;
-    GLuint nFrontOffsetX, nFrontOffsetY, nBackOffsetX, nBackOffsetY;
-    GLuint bytePerPixel = vmesa->viaScreen->bitsPerPixel >> 3;
-    GLuint EngStatus = *(vmesa->pnGEMode);
-    GLuint blitMode; 
-    RING_VARS;
-
-    switch(bytePerPixel) {
-    case 4:
-       blitMode = 0x300;
-       break;
-    case 2:
-       blitMode = 0x100;
-       break;
-    default:
-       blitMode = 0x000;
-       break;
-    }
-
-    nFrontPitch = vmesa->front.pitch;
-    nBackPitch = vmesa->back.pitch;
-    
-    /* Caculate Base */
-    nFrontBase = vmesa->front.offset;
-    nBackBase = vmesa->back.offset;
-    
-    /* Width, Height */
-    nFrontWidth = nFrontPitch / bytePerPixel;
-    nFrontHeight = nBackPitch / bytePerPixel;
-    
-    /* Offset */
-    nFrontOffsetX = 0;
-    nFrontOffsetY = 0;
-    nBackOffsetX = nFrontOffsetX;
-    nBackOffsetY = nFrontOffsetY;
-
-    BEGIN_RING(8 * 2);
-    /* Restore mode */
-    SetReg2DAGP(0x04, (EngStatus & 0xFFFFFCFF) | blitMode);
-    /* GEWD */
-    SetReg2DAGP(0x10, nFrontWidth | (nFrontHeight << 16));
-    /* GEDST */
-    SetReg2DAGP(0x0C, nFrontOffsetX | (nFrontOffsetY << 16));
-    /* GESRC */
-    SetReg2DAGP(0x08, nBackOffsetX | (nBackOffsetY << 16));
-    /* GEDSTBASE */
-    SetReg2DAGP(0x34, (nFrontBase >> 3));
-    /* GESCRBASE */
-    SetReg2DAGP(0x30, (nBackBase >> 3));
-    /* GEPITCH */
-    SetReg2DAGP(0x38, (((nFrontPitch >> 3) << 16) & 0x7FF0000) | 0x80000000 |
-                      ((nBackPitch >> 3) & 0x7FF));
-    /* BITBLT */
-    SetReg2DAGP(0x0, 0x1 | 0xCC000000);
-    ADVANCE_RING();
-
-    viaFlushPrimsLocked(vmesa);
-    if (VIA_DEBUG) fprintf(stderr, "Do Swap PBuffer\n");
-}
-
-
-
-
-GLuint *viaAllocDmaFunc(viaContextPtr vmesa, int bytes, const char *func, int line)
-{
-    if (vmesa->dmaLow + bytes > VIA_DMA_HIGHWATER) {
-       if (VIA_DEBUG) fprintf(stderr, "buffer overflow in check dma = %d + %d = %d\n", 
-                              vmesa->dmaLow, bytes, vmesa->dmaLow + bytes);
-       viaFlushPrims(vmesa);
-    }
-
-    {
-        GLuint *start = (GLuint *)(vmesa->dmaAddr + vmesa->dmaLow);
-       vmesa->dmaLow += bytes;
-       if (VIA_DEBUG && (vmesa->dmaLow & 0x4))
-          fprintf(stderr, "%s/%d: alloc 0x%x --> dmaLow 0x%x\n", func, line, bytes, vmesa->dmaLow);
-        return start;
-    }
-}
-