Buffer vertices and emit them in batches. Still using conventional drawing
authorFelix Kuehling <fxkuehl@gmx.de>
Wed, 24 Mar 2004 16:15:28 +0000 (16:15 +0000)
committerFelix Kuehling <fxkuehl@gmx.de>
Wed, 24 Mar 2004 16:15:28 +0000 (16:15 +0000)
commands, no vertex DMA.

src/mesa/drivers/dri/savage/savagedma.c
src/mesa/drivers/dri/savage/savagedma.h
src/mesa/drivers/dri/savage/savageioctl.c
src/mesa/drivers/dri/savage/savageioctl.h
src/mesa/drivers/dri/savage/savagestate.c
src/mesa/drivers/dri/savage/savagetex.c
src/mesa/drivers/dri/savage/savagetris.c

index fb0ec8790363024a72be8f06634719d89f8f1e47..caaeeaa104e77d1e5af489b9c2380d5a6e62a8c5 100644 (file)
@@ -296,3 +296,62 @@ int savageDMAClose (savageContextPtr imesa) {
 }
 
 #endif
+
+/* Faked vertex buffers
+ *
+ * This is a dirty hack, knowing that it will go away soon when real
+ * vertex DMA is implemented and eventually moved to the DRM.
+ */
+
+static uint32_t vertex_data[16384]; /* 64KB */
+static drmBuf vertex_buffer = {
+    0,                       /* idx */
+    65536,                   /* total = 64KB */
+    0,                       /* used */
+    (drmAddress)vertex_data  /* address */
+};
+
+void savageFakeVertices (savageContextPtr imesa, drmBufPtr buffer) {
+    GLuint vertexStride = imesa->vertex_size; /* stride in dwords */
+    GLuint vertexSize = imesa->vertex_size; /* the real vertex size in dwords */
+    GLuint nVertices = buffer->used / (vertexStride*4);
+    uint32_t *data = (uint32_t*)buffer->address;
+    uint32_t vertexFormat = imesa->DrawPrimitiveCmd & SAVAGE_HW_SKIPFLAGS;
+    GLuint i, j, left;
+
+    /* we have the monopoly on vertex buffers ;-) */
+    assert (buffer == &vertex_buffer);
+    assert (buffer->used % (vertexStride*4) == 0); /* whole vertices */
+    assert (nVertices % 3 == 0);                   /* triangle lists */
+
+    /* Flush (pseodo) DMA before accessing the BCI directly. */
+    savageDMAFlush(imesa);
+
+    left = nVertices;
+    while (left != 0) {
+       /* Can emit up to 255 vertices (85 triangles) with one command. */
+       GLuint count = left > 255 ? 255 : left;
+       /* Don't go through another buffering mechanism, copy to BCI
+        * directly. */
+       volatile uint32_t *vb = SAVAGE_GET_BCI_POINTER(imesa,
+                                                      count*vertexSize + 1);
+
+       WRITE_CMD (vb, SAVAGE_DRAW_PRIMITIVE(
+                      count, SAVAGE_HW_TRIANGLE_LIST | vertexFormat, 0),
+                  uint32_t);
+       for (i = 0; i < count; ++i) {
+           for (j = 0; j < vertexSize; ++j)
+               WRITE_CMD (vb, data[j], uint32_t);
+           data += vertexStride;
+       }
+       left -= count;
+    }
+
+    /* clear the vertex buffer for the next set of vertices */
+    vertex_buffer.used = 0;
+}
+
+drmBufPtr savageFakeGetBuffer (savageContextPtr imesa) {
+    assert (vertex_buffer.used == 0); /* has been flushed */
+    return &vertex_buffer;
+}
index 294568584646919c508d4db6417f82d9108b0710..ad8e2c771b3dd55258472773235a7eb1fae6675e 100644 (file)
@@ -47,4 +47,9 @@ void savageDMACommit (savageContextPtr imesa, void *end);
 void savageDMAFlush (savageContextPtr imesa);
 int savageDMAInit (savageContextPtr imesa);
 int savageDMAClose (savageContextPtr);
+
+/* faked implementation of vertex buffers */
+void savageFakeVertices (savageContextPtr imesa, drmBufPtr buffer);
+drmBufPtr savageFakeGetBuffer (savageContextPtr imesa);
+
 #endif
index 95cbeecbfa2341bae06d901e6088b8b0861dcfb7..8b946195c3bd236790a28f32c88322bc7854e966 100644 (file)
@@ -244,9 +244,9 @@ static void savageDDClear( GLcontext *ctx, GLbitfield mask, GLboolean all,
        clear.clear_depth = (GLuint) (ctx->Depth.Clear * DEPTH_SCALE_16);
    else
        clear.clear_depth = (GLuint) (ctx->Depth.Clear * DEPTH_SCALE_24);
-#if 0
+
    FLUSH_BATCH( imesa );
-#endif 
+
    if ((mask & DD_FRONT_LEFT_BIT) && ((colorMask&0xffffffUL)==0xffffffUL) ){
       clear.flags |= SAVAGE_FRONT;
       mask &= ~DD_FRONT_LEFT_BIT;
@@ -346,6 +346,8 @@ void savageSwapBuffers( __DRIdrawablePrivate *dPriv )
    if (imesa->IsDouble)
        _mesa_notifySwapBuffers( imesa->glCtx );
 
+   FLUSH_BATCH(imesa);
+
    LOCK_HARDWARE( imesa );
    PAGE_PENDING(pending);
 
@@ -397,15 +399,29 @@ void savageWaitAge( savageContextPtr imesa, int age  )
 
 
 
-void savageFlushVertices( savageContextPtr imesa ) 
+void savageFlushVerticesLocked( savageContextPtr imesa )
 {
+    drmBufPtr buffer = imesa->vertex_dma_buffer;
+
+    if (!buffer)
+       return;
+
+    imesa->vertex_dma_buffer = NULL;
 
+    /* Lot's of stuff to do here. For now there is a fake DMA implementation
+     * in savagedma.c that emits drawing commands. Cliprects are not handled
+     * yet. */
+    if (buffer->used) {
+       savageFakeVertices (imesa, buffer);
+    }
 }
 
 
-void savageFlushVerticesLocked( savageContextPtr imesa )
+void savageFlushVertices( savageContextPtr imesa ) 
 {
-
+    LOCK_HARDWARE(imesa);
+    savageFlushVerticesLocked (imesa);
+    UNLOCK_HARDWARE(imesa);
 }
 
 
@@ -416,11 +432,20 @@ int savage_check_copy(int fd)
 
 static void savageDDFlush( GLcontext *ctx )
 {
-
+    savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+    LOCK_HARDWARE(imesa);
+    savageFlushVerticesLocked (imesa);
+    savageDMAFlush (imesa);
+    UNLOCK_HARDWARE(imesa);
 }
 
 static void savageDDFinish( GLcontext *ctx  ) 
 {
+    savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+    LOCK_HARDWARE(imesa);
+    savageFlushVerticesLocked (imesa);
+    savageDmaFinish (imesa);
+    UNLOCK_HARDWARE(imesa);
 }
 
 #define ALT_STATUS_WORD0 (* (volatile GLuint *)(imesa->MMIO_BASE+0x48c60))
index 94b02e3319780c6975a5dd10b5364e83d6bac313..92f42950e133711201bc15da63b226584be17f07 100644 (file)
@@ -68,5 +68,32 @@ GLuint savageGetPhyAddress(savageContextPtr imesa,void * pointer);
 int  savageFreeDMABuffer(savageContextPtr, drm_savage_alloc_cont_mem_t*);
 #endif
 
-#define FLUSH_BATCH(imesa) savageDMAFlush(imesa)
+#define FLUSH_BATCH(imesa) do { \
+    if (imesa->vertex_dma_buffer) savageFlushVertices(imesa); \
+} while (0)
+
+static __inline
+uint32_t *savageAllocDmaLow( savageContextPtr imesa, GLuint bytes )
+{
+   uint32_t *head;
+
+   if (!imesa->vertex_dma_buffer) {
+      LOCK_HARDWARE(imesa);
+      imesa->vertex_dma_buffer = savageFakeGetBuffer (imesa);
+      UNLOCK_HARDWARE(imesa);
+   } else if (imesa->vertex_dma_buffer->used + bytes >
+             imesa->vertex_dma_buffer->total) {
+      LOCK_HARDWARE(imesa);
+      savageFlushVerticesLocked( imesa );
+      imesa->vertex_dma_buffer = savageFakeGetBuffer (imesa);
+      UNLOCK_HARDWARE(imesa);
+   }
+
+   head = (uint32_t *)((uint8_t *)imesa->vertex_dma_buffer->address +
+                      imesa->vertex_dma_buffer->used);
+
+   imesa->vertex_dma_buffer->used += bytes;
+   return head;
+}
+
 #endif
index b32b58ab878a2b01f1adad1699edac8e2758b92f..2542b1d29d1581ad92839e67f5f904d98dcaad42 100644 (file)
@@ -1327,6 +1327,8 @@ void savageDDUpdateHwState( GLcontext *ctx )
 {
     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
    
+    /*FLUSH_BATCH(imesa);*/
+
     if(imesa->driDrawable)
     {
         LOCK_HARDWARE(imesa);
@@ -1837,7 +1839,6 @@ void savageDDRenderStart(GLcontext *ctx)
     {
         /*ctx->VB->CopyStart = ctx->VB->Count;*/
     }
-    LOCK_HARDWARE(SAVAGE_CONTEXT(ctx));
 }
 
 
@@ -1845,7 +1846,6 @@ void savageDDRenderEnd(GLcontext *ctx)
 {
     savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
        
-    UNLOCK_HARDWARE(SAVAGE_CONTEXT(ctx));
     if(!imesa->IsDouble)
     {
         savageSwapBuffers(imesa->driDrawable);
@@ -1855,6 +1855,8 @@ void savageDDRenderEnd(GLcontext *ctx)
 
 static void savageDDInvalidateState( GLcontext *ctx, GLuint new_state )
 {
+   FLUSH_BATCH(SAVAGE_CONTEXT(ctx));
+
    _swrast_InvalidateState( ctx, new_state );
    _swsetup_InvalidateState( ctx, new_state );
    _ac_InvalidateState( ctx, new_state );
index 541de5bf8658fc480479b1a5d745a142061acd33..69cb5b88664c22e897a650a129fa5fa903b0bc51 100644 (file)
@@ -791,8 +791,8 @@ int savageUploadTexImages( savageContextPtr imesa, savageTextureObjectPtr t )
    savageUpdateTexLRU( imesa, t );
 
    if (t->dirty_images) {
-      FLUSH_BATCH( imesa );
-      WAIT_IDLE_EMPTY;
+      savageFlushVerticesLocked (imesa);
+      savageDmaFinish (imesa);
       if (SAVAGE_DEBUG & DEBUG_VERBOSE_LRU)
         fprintf(stderr, "*");
 
index 8347580e8602ad19f8139c94996b7d116dfbb830..c8bd5762ea3b799cc5c1e68a5a8f533cc73f0d0b 100644 (file)
@@ -61,109 +61,97 @@ static void savageRenderPrimitive( GLcontext *ctx, GLenum prim );
  *                    Emit primitives                                  *
  ***********************************************************************/
 
-static  __inline__ GLuint * savage_send_one_vertex(savageContextPtr imesa, savageVertexPtr v, uint32_t * vb, GLuint start, GLuint size)
-{ 
-    GLuint j; 
-    for (j = start ; j < size ; j++) 
-    { 
-        WRITE_CMD(vb, v->ui[j],uint32_t);
-    }
-    return vb; 
-} 
-static void __inline__ savage_draw_triangle( savageContextPtr imesa, 
-                                          savageVertexPtr v0, 
-                                          savageVertexPtr v1, 
-                                          savageVertexPtr v2 ) 
-{ 
-   GLuint vertsize = imesa->vertex_size; 
-#if SAVAGEDEBUG
-   uint32_t *vb = savageDMAAlloc (imesa, 3 * vertsize + 1 + 8); 
+#if defined (USE_X86_ASM)
+#define EMIT_VERT( j, vb, vertex_size, start, v )      \
+do {   int __tmp;                                      \
+        vb += start;                                   \
+       __asm__ __volatile__( "rep ; movsl"             \
+                        : "=%c" (j), "=D" (vb), "=S" (__tmp)           \
+                        : "0" (vertex_size-start),     \
+                          "D" ((long)vb),              \
+                          "S" ((long)&v->ui[start]));  \
+} while (0)
 #else
-   uint32_t *vb = savageDMAAlloc (imesa, 4 * vertsize + 1); 
+#define EMIT_VERT( j, vb, vertex_size, start, v )      \
+do {                                           \
+   for ( j = start ; j < vertex_size ; j++ )   \
+      vb[j] = (v)->ui[j];                      \
+   vb += vertex_size;                          \
+} while (0)
 #endif
 
-   imesa->DrawPrimitiveCmd &=
-       ~(SAVAGE_HW_TRIANGLE_TYPE| SAVAGE_HW_TRIANGLE_CONT);
-   WRITE_CMD(vb,SAVAGE_DRAW_PRIMITIVE(3, imesa->DrawPrimitiveCmd, 0),uint32_t);
+static void __inline__ savage_draw_triangle (savageContextPtr imesa,
+                                            savageVertexPtr v0,
+                                            savageVertexPtr v1,
+                                            savageVertexPtr v2) {
+   GLuint vertsize = imesa->vertex_size;
+   uint32_t *vb = savageAllocDmaLow (imesa, 3*4*vertsize);
+   GLuint j;
+
+   EMIT_VERT (j, vb, vertsize, 0, v0);
+   EMIT_VERT (j, vb, vertsize, 0, v1);
+   EMIT_VERT (j, vb, vertsize, 0, v2);
+}
 
-   vb = savage_send_one_vertex(imesa, v0, vb, 0, vertsize);
-   vb = savage_send_one_vertex(imesa, v1, vb, 0, vertsize);
-   vb = savage_send_one_vertex(imesa, v2, vb, 0, vertsize);
-#if SAVAGEDEBUG
-   {
-        GLuint x0,y0,w,h;
-        x0 = (GLuint)imesa->drawX;
-        y0 = (GLuint)imesa->drawY;
-        w  = (GLuint)imesa->driDrawable->w;
-        h  = (GLuint)imesa->driDrawable->h;
-
-       (*vb) = 0x4BCC00C0;
-       vb++;
-       (*vb) = imesa->savageScreen->backOffset;
-       vb++;
-       (*vb) = imesa->savageScreen->backBitmapDesc;
-       vb++;
-       (*vb) = (y0<<16)|x0;
-       vb++;
-       (*vb) = 0x0;
-       vb++;
-       (*vb) = (h<<16)|w;
-       vb++;
-   }
-#endif
-   savageDMACommit (imesa, vb);
-} 
-static __inline__ void savage_draw_point( savageContextPtr imesa, 
-                                         savageVertexPtr tmp ) 
-{ 
-   GLfloat sz = imesa->glCtx->Point._Size * .5;
-   GLuint vertsize = imesa->vertex_size; 
-   uint32_t *vb = savageDMAAlloc (imesa, 4 * vertsize + 1); 
-   const GLfloat x = tmp->v.x; 
-   const GLfloat y = tmp->v.y; 
-   
-   imesa->DrawPrimitiveCmd &=
-       ~(SAVAGE_HW_TRIANGLE_TYPE | SAVAGE_HW_TRIANGLE_CONT);   
-   imesa->DrawPrimitiveCmd |= SAVAGE_HW_TRIANGLE_FAN; 
-     
-   WRITE_CMD(vb, SAVAGE_DRAW_PRIMITIVE(4, imesa->DrawPrimitiveCmd, 0),uint32_t);
-
-   WRITE_CMD(vb, x - sz, GLfloat);
-   WRITE_CMD(vb, y - sz, GLfloat);
-   vb = savage_send_one_vertex(imesa, tmp, vb, 2, vertsize);
-
-   WRITE_CMD(vb, x + sz, GLfloat);
-   WRITE_CMD(vb, y - sz, GLfloat);
-   vb = savage_send_one_vertex(imesa, tmp, vb, 2, vertsize);
-
-   WRITE_CMD(vb, x + sz, GLfloat);
-   WRITE_CMD(vb, y + sz, GLfloat);
-   vb = savage_send_one_vertex(imesa, tmp, vb, 2, vertsize);
-   WRITE_CMD(vb, x - sz, GLfloat);
-   WRITE_CMD(vb, y + sz, GLfloat);
-   vb = savage_send_one_vertex(imesa, tmp, vb, 2, vertsize);
+static void __inline__ savage_draw_quad (savageContextPtr imesa,
+                                        savageVertexPtr v0,
+                                        savageVertexPtr v1,
+                                        savageVertexPtr v2,
+                                        savageVertexPtr v3) {
+   GLuint vertsize = imesa->vertex_size;
+   uint32_t *vb = savageAllocDmaLow (imesa, 6*4*vertsize);
+   GLuint j;
+
+   EMIT_VERT (j, vb, vertsize, 0, v0);
+   EMIT_VERT (j, vb, vertsize, 0, v1);
+   EMIT_VERT (j, vb, vertsize, 0, v3);
+   EMIT_VERT (j, vb, vertsize, 0, v1);
+   EMIT_VERT (j, vb, vertsize, 0, v2);
+   EMIT_VERT (j, vb, vertsize, 0, v3);
+}
 
-   savageDMACommit (imesa, vb);
-} 
-static __inline__ void savage_draw_line( savageContextPtr imesa, 
-                                      savageVertexPtr v0, 
-                                      savageVertexPtr v1 ) 
-{  
-   GLuint vertsize = imesa->vertex_size; 
-   uint32_t *vb = savageDMAAlloc (imesa, 4 * vertsize + 1); 
-   GLfloat dx, dy, ix, iy; 
-   GLfloat width = imesa->glCtx->Line._Width;
+static __inline__ void savage_draw_point (savageContextPtr imesa,
+                                         savageVertexPtr tmp) {
+   GLuint vertsize = imesa->vertex_size;
+   uint32_t *vb = savageAllocDmaLow (imesa, 6*4*vertsize);
+   const GLfloat x = tmp->v.x;
+   const GLfloat y = tmp->v.y;
+   const GLfloat sz = imesa->glCtx->Point._Size * .5;
+   GLuint j;
+
+   *(float *)&vb[0] = x - sz;
+   *(float *)&vb[1] = y - sz;
+   EMIT_VERT (j, vb, vertsize, 2, tmp);
+
+   *(float *)&vb[0] = x + sz;
+   *(float *)&vb[1] = y - sz;
+   EMIT_VERT (j, vb, vertsize, 2, tmp);
+
+   *(float *)&vb[0] = x + sz;
+   *(float *)&vb[1] = y + sz;
+   EMIT_VERT (j, vb, vertsize, 2, tmp);
+
+   *(float *)&vb[0] = x + sz;
+   *(float *)&vb[1] = y + sz;
+   EMIT_VERT (j, vb, vertsize, 2, tmp);
+
+   *(float *)&vb[0] = x - sz;
+   *(float *)&vb[1] = y + sz;
+   EMIT_VERT (j, vb, vertsize, 2, tmp);
+
+   *(float *)&vb[0] = x - sz;
+   *(float *)&vb[1] = y - sz;
+   EMIT_VERT (j, vb, vertsize, 2, tmp);
+}
 
-   imesa->DrawPrimitiveCmd &=
-       ~(SAVAGE_HW_TRIANGLE_TYPE | SAVAGE_HW_TRIANGLE_CONT);
-   imesa->DrawPrimitiveCmd |= SAVAGE_HW_TRIANGLE_FAN; 
-   WRITE_CMD(vb, SAVAGE_DRAW_PRIMITIVE(4, imesa->DrawPrimitiveCmd, 0),uint32_t);
+static __inline__ void savage_draw_line (savageContextPtr imesa,
+                                        savageVertexPtr v0,
+                                        savageVertexPtr v1 ) {
+   GLuint vertsize = imesa->vertex_size;
+   uint32_t *vb = savageAllocDmaLow (imesa, 6*4*vertsize);
+   GLfloat width = imesa->glCtx->Line._Width;
+   GLfloat dx, dy, ix, iy;
+   GLuint j;
 
    dx = v0->v.x - v1->v.x;
    dy = v0->v.y - v1->v.y;
@@ -173,48 +161,31 @@ static __inline__ void savage_draw_line( savageContextPtr imesa,
       iy = ix; ix = 0;
    }
 
-   WRITE_CMD(vb, (v0->v.x - ix), GLfloat);
-   WRITE_CMD(vb, (v0->v.y - iy), GLfloat);
-   vb = savage_send_one_vertex(imesa, v0, vb, 2, vertsize);
+   *(float *)&vb[0] = v0->v.x - ix;
+   *(float *)&vb[1] = v0->v.y - iy;
+   EMIT_VERT (j, vb, vertsize, 2, v0);
+
+   *(float *)&vb[0] = v1->v.x + ix;
+   *(float *)&vb[1] = v1->v.y + iy;
+   EMIT_VERT (j, vb, vertsize, 2, v1);
 
-   WRITE_CMD(vb, (v1->v.x - ix), GLfloat);
-   WRITE_CMD(vb, (v1->v.y - iy), GLfloat);     
-   vb = savage_send_one_vertex(imesa, v1, vb, 2, vertsize);
+   *(float *)&vb[0] = v0->v.x + ix;
+   *(float *)&vb[1] = v0->v.y + iy;
+   EMIT_VERT (j, vb, vertsize, 2, v0);
 
-   WRITE_CMD(vb, (v1->v.x + ix), GLfloat);
-   WRITE_CMD(vb, (v1->v.y + iy), GLfloat);
-   vb = savage_send_one_vertex(imesa, v1, vb, 2, vertsize);
+   *(float *)&vb[0] = v0->v.x - ix;
+   *(float *)&vb[1] = v0->v.y - iy;
+   EMIT_VERT (j, vb, vertsize, 2, v0);
 
-   WRITE_CMD(vb, (v0->v.x + ix), GLfloat);
-   WRITE_CMD(vb, (v0->v.y + iy), GLfloat);
-   vb = savage_send_one_vertex(imesa, v0, vb, 2, vertsize);
+   *(float *)&vb[0] = v1->v.x - ix;
+   *(float *)&vb[1] = v1->v.y - iy;
+   EMIT_VERT (j, vb, vertsize, 2, v1);
 
-   savageDMACommit (imesa, vb);
+   *(float *)&vb[0] = v1->v.x + ix;
+   *(float *)&vb[1] = v1->v.y + iy;
+   EMIT_VERT (j, vb, vertsize, 2, v1);
 } 
  
-static void __inline__ savage_draw_quad( savageContextPtr imesa, 
-                                        savageVertexPtr v0, 
-                                        savageVertexPtr v1, 
-                                        savageVertexPtr v2, 
-                                        savageVertexPtr v3 ) 
-{ 
-   GLuint vertsize = imesa->vertex_size; 
-   uint32_t *vb = savageDMAAlloc (imesa, 6 * vertsize + 1); 
-
-   imesa->DrawPrimitiveCmd &=
-       ~(SAVAGE_HW_TRIANGLE_TYPE | SAVAGE_HW_TRIANGLE_CONT);
-   WRITE_CMD(vb, SAVAGE_DRAW_PRIMITIVE(6, imesa->DrawPrimitiveCmd, 0),uint32_t);
-   vb = savage_send_one_vertex(imesa, v0, vb, 0, vertsize);
-   vb = savage_send_one_vertex(imesa, v1, vb, 0, vertsize);
-   vb = savage_send_one_vertex(imesa, v3, vb, 0, vertsize);
-   vb = savage_send_one_vertex(imesa, v1, vb, 0, vertsize);
-   vb = savage_send_one_vertex(imesa, v2, vb, 0, vertsize);
-   vb = savage_send_one_vertex(imesa, v3, vb, 0, vertsize);
-
-   savageDMACommit (imesa, vb);
-} 
-
 /***********************************************************************
  *          Macros for t_dd_tritmp.h to draw basic primitives          *
  ***********************************************************************/
@@ -699,8 +670,6 @@ static void savageRasterPrimitive( GLcontext *ctx, GLuint prim )
 {
    savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
 
-   FLUSH_BATCH( imesa );
-
    /* Update culling */
    if (imesa->raster_primitive != prim)
       imesa->dirty |= SAVAGE_UPLOAD_CTX;
@@ -845,9 +814,7 @@ void savageFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
       imesa->Fallback |= bit;
       if (oldfallback == 0) {
         /* the first fallback */
-        LOCK_HARDWARE(SAVAGE_CONTEXT(ctx));
         FLUSH_BATCH( imesa );
-        UNLOCK_HARDWARE(SAVAGE_CONTEXT(ctx));
         _swsetup_Wakeup( ctx );
         imesa->RenderIndex = ~0;
       }