Add a big nasty fallback for AlphaTest -- seems to always be wrong
[mesa.git] / src / mesa / drivers / dri / unichrome / via_ioctl.c
index 256349a12f27a5a00a29a7b27cc5559db1769952..30ca7f67553525be80b44fa36aef38943f2e298d 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
@@ -73,7 +73,22 @@ v * copy of this software and associated documentation files (the "Software"),
 #define VIA_BLIT_FILL 0xF0
 #define VIA_BLIT_SET 0xFF
 
+static void dump_dma( viaContextPtr 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)
 {
     VIA_FINISH_PRIM( vmesa );
@@ -90,77 +105,61 @@ void viaCheckDma(viaContextPtr vmesa, GLuint bytes)
 } 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, 
+static void viaBlit(viaContextPtr vmesa, GLuint bpp,
+                   GLuint srcBase, GLuint srcPitch, 
+                   GLuint dstBase, GLuint dstPitch,
+                   GLuint w, GLuint h, 
+                   GLuint blitMode, 
                    GLuint color, GLuint nMask ) 
 {
 
-    GLuint dwGEMode = 0, srcY=0, srcX, dstY=0, dstX;
-    GLuint cmd;
+    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 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);
+       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;
 
-    srcX = srcBase & 31;
-    dstX = dstBase & 31;
     switch (bpp) {
     case 16:
-        dwGEMode |= VIA_GEM_16bpp;
-       srcX >>= 1;
-       dstX >>= 1;
+        dwGEMode = VIA_GEM_16bpp;
+       srcX = (srcBase & 0x1f) >> 1;
+       dstX = (dstBase & 0x1f) >> 1;
         break;
     case 32:
-        dwGEMode |= VIA_GEM_32bpp;
-       srcX >>= 2;
-       dstX >>= 2;
+        dwGEMode = VIA_GEM_32bpp;
+       srcX = (srcBase & 0x1f) >> 2;
+       dstX = (dstBase & 0x1f) >> 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);
+        return;
     }
 
     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);
+       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);
+       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 & ~31) >> 3);
-    SetReg2DAGP( VIA_REG_DSTBASE, (dstBase & ~31) >> 3);
+    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, ((srcY << 16) | srcX));
-    SetReg2DAGP( VIA_REG_DSTPOS, ((dstY << 16) | dstX));
+              (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);
@@ -192,7 +191,6 @@ static void viaFillBuffer(viaContextPtr vmesa,
              offset, buffer->pitch,
              offset, buffer->pitch, 
              w, h,
-             0, 0, 
              VIA_BLIT_FILL, pixel, mask); 
    }
 }
@@ -204,7 +202,6 @@ static void viaClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
 {
    viaContextPtr vmesa = VIA_CONTEXT(ctx);
    __DRIdrawablePrivate *dPriv = vmesa->driDrawable;
-   const GLuint colorMask = *((GLuint *)&ctx->Color.ColorMask);
    int flag = 0;
    GLuint i = 0;
    GLuint clear_depth_mask = 0xf << 28;
@@ -212,12 +209,12 @@ static void viaClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
 
    VIA_FLUSH_DMA(vmesa);
 
-   if ((mask & DD_FRONT_LEFT_BIT) && colorMask == ~0) {
+   if (mask & DD_FRONT_LEFT_BIT) {
       flag |= VIA_FRONT;
       mask &= ~DD_FRONT_LEFT_BIT;
    }
 
-   if ((mask & DD_BACK_LEFT_BIT) && colorMask == ~0) {
+   if (mask & DD_BACK_LEFT_BIT) {
       flag |= VIA_BACK;        
       mask &= ~DD_BACK_LEFT_BIT;
    }
@@ -239,9 +236,9 @@ static void viaClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
            mask &= ~DD_STENCIL_BIT;
         }
         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)
+              fprintf(stderr, "XXX: Clear stencil writemask %x -- need triangles (or a ROP?)\n", 
+                      ctx->Stencil.WriteMask[0]);
         }
       }
    }
@@ -293,11 +290,11 @@ static void viaClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
       }
            
       if (flag & VIA_FRONT) {
-        viaFillBuffer(vmesa, &vmesa->front, boxes, nr, vmesa->ClearColor, 0);
+        viaFillBuffer(vmesa, &vmesa->front, boxes, nr, vmesa->ClearColor, vmesa->ClearMask);
       } 
                
       if (flag & VIA_BACK) {
-        viaFillBuffer(vmesa, &vmesa->back, boxes, nr, vmesa->ClearColor, 0); /* FIXME: masks */
+        viaFillBuffer(vmesa, &vmesa->back, boxes, nr, vmesa->ClearColor, vmesa->ClearMask);
       }
 
       if (flag & VIA_DEPTH) {
@@ -341,7 +338,7 @@ static void viaDoSwapBuffers(viaContextPtr vmesa,
              src, back->pitch,
              dest, front->pitch,
              w, h,
-             0,0,VIA_BLIT_COPY, 0, 0); 
+             VIA_BLIT_COPY, 0, 0); 
    }
 }
 
@@ -442,14 +439,14 @@ void viaPageFlip(const __DRIdrawablePrivate *dPriv)
 
 static int fire_buffer(viaContextPtr vmesa)
 {
-   drmVIACommandBuffer bufI;
+   drm_via_cmdbuffer_t bufI;
    int ret;
 
    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:
        */
@@ -461,18 +458,20 @@ static int fire_buffer(viaContextPtr vmesa)
                                   &bSiz, sizeof(bSiz));
       } while (ret == -EAGAIN);
       if (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) {
+        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. 
@@ -488,7 +487,9 @@ static int fire_buffer(viaContextPtr vmesa)
            
    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();
    }
 
@@ -513,11 +514,9 @@ static void via_emit_cliprect(viaContextPtr vmesa,
    GLuint pitch = buffer->pitch;
    GLuint offset = buffer->orig;
 
-   GLuint clipL = b->x1 - vmesa->drawX;
-   GLuint clipR = b->x2 - vmesa->drawX;
-   GLuint clipT = b->y1 - vmesa->drawY;
-   GLuint clipB = b->y2 - vmesa->drawY;
-           
+   if (0)
+      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);
 
@@ -526,14 +525,17 @@ static void via_emit_cliprect(viaContextPtr vmesa,
       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[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); 
-   vb[6] = ((HC_SubA_HDBFM << 24) | HC_HDBLoc_Local | format | pitch);            
-   vb[7] = 0xcccccccc;
+   vb[6] = ((HC_SubA_HDBFM << 24) | HC_HDBLoc_Local | format | pitch);     
+
+   /* Seems to be ignored on CLE266:
+    */
+   vb[7] = ((HC_SubA_HSPXYOS << 24) | ((32 - vmesa->drawXoff) << HC_HSPXOS_SHIFT));
 }
 
 
@@ -543,6 +545,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;
@@ -555,26 +562,14 @@ static int intersect_rect(drm_clip_rect_t *out,
     return 1;
 }
 
-static void dump_dma( viaContextPtr 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 viaFlushDmaLocked(viaContextPtr vmesa, GLuint flags)
 {
    int i;
    RING_VARS;
 
+   if (VIA_DEBUG)
+      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)) {
       fprintf(stderr, "%s called without lock held\n", __FUNCTION__);
@@ -640,35 +635,44 @@ void viaFlushDmaLocked(viaContextPtr vmesa, GLuint flags)
       dump_dma( vmesa );
 
    if (flags & VIA_NO_CLIPRECTS) {
-      assert(vmesa->dmaCliprectAddr == 0);
+      if (0) fprintf(stderr, "%s VIA_NO_CLIPRECTS\n", __FUNCTION__);
+      assert(vmesa->dmaCliprectAddr == ~0);
       fire_buffer( vmesa );
    }
-   else if (!vmesa->dmaCliprectAddr) {
+   else if (vmesa->dmaCliprectAddr == ~0) {
       /* Contains only state.  Could just dump the packet?
        */
-      if (0) fprintf(stderr, "no dmaCliprectAddr\n");
+      if (0) fprintf(stderr, "%s: no dmaCliprectAddr\n", __FUNCTION__);
       if (0) fire_buffer( vmesa );
    }
    else if (vmesa->numClipRects) {
-      int ret;
       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++) {
-        if (vmesa->glCtx->Scissor.Enabled) {
-           drm_clip_rect_t b;
-           if (!intersect_rect(&b, &pbox[i], &vmesa->scissorRect)) 
-              continue;
-           via_emit_cliprect(vmesa, &b);        
-        }
-        else {
-           via_emit_cliprect(vmesa, &pbox[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;
+
+        if (vmesa->glCtx->Scissor.Enabled &&
+            !intersect_rect(&b, &b, &vmesa->scissorRect)) 
+           continue;
         
-        ret = fire_buffer(vmesa);
-        if (ret)
+        b.x1 += vmesa->drawXoff;
+        b.x2 += vmesa->drawXoff;
+
+        via_emit_cliprect(vmesa, &b);
+
+        if (fire_buffer(vmesa) != 0) {
+           dump_dma( vmesa );
            goto done;
+        }
       }
    } else {
+      if (0) fprintf(stderr, "%s: no cliprects\n", __FUNCTION__);
       UNLOCK_HARDWARE(vmesa);
       sched_yield();
       LOCK_HARDWARE(vmesa);
@@ -678,11 +682,11 @@ void viaFlushDmaLocked(viaContextPtr vmesa, GLuint flags)
    /* Reset vmesa vars:
     */
    vmesa->dmaLow = 0;
-   vmesa->dmaCliprectAddr = 0;
+   vmesa->dmaCliprectAddr = ~0;
    vmesa->newEmitState = ~0;
 }
 
-static void viaWrapPrimitive( viaContextPtr vmesa )
+void viaWrapPrimitive( viaContextPtr vmesa )
 {
    GLenum renderPrimitive = vmesa->renderPrimitive;
    GLenum hwPrimitive = vmesa->hwPrimitive;
@@ -740,36 +744,3 @@ void viaInitIoctlFuncs(GLcontext *ctx)
 
 
 
-
-GLuint *viaAllocDmaFunc(viaContextPtr vmesa, int bytes, const char *func, int line)
-{
-   assert(!vmesa->dmaLastPrim);
-   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);
-      viaFlushDma(vmesa);
-   }
-
-   {
-      GLuint *start = (GLuint *)(vmesa->dma + vmesa->dmaLow);
-      vmesa->dmaLow += bytes;
-      return start;
-   }
-}
-
-
-GLuint *viaExtendPrimitive(viaContextPtr vmesa, int bytes)
-{
-   assert(vmesa->dmaLastPrim);
-   if (vmesa->dmaLow + bytes > VIA_DMA_HIGHWATER) {
-      viaWrapPrimitive(vmesa);
-   }
-
-   {
-      GLuint *start = (GLuint *)(vmesa->dma + vmesa->dmaLow);
-      vmesa->dmaLow += bytes;
-      return start;
-   }
-}
-
-