Removed all direct hardware access (MMIO, BCI) from the Savage DRI
authorFelix Kuehling <fxkuehl@gmx.de>
Sat, 1 Jan 2005 20:40:14 +0000 (20:40 +0000)
committerFelix Kuehling <fxkuehl@gmx.de>
Sat, 1 Jan 2005 20:40:14 +0000 (20:40 +0000)
driver. It uses the new DRM version 2.0.x now, which has just been
committed to DRM CVS.

15 files changed:
src/mesa/drivers/dri/savage/Makefile
src/mesa/drivers/dri/savage/savage_bci.h
src/mesa/drivers/dri/savage/savage_init.h
src/mesa/drivers/dri/savage/savage_xmesa.c
src/mesa/drivers/dri/savage/savagecontext.h
src/mesa/drivers/dri/savage/savagedd.c
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/savagestate.h
src/mesa/drivers/dri/savage/savagetex.c
src/mesa/drivers/dri/savage/savagetris.c
src/mesa/drivers/dri/savage/server/savage_dri.h

index d662cb06d8dbaa80c7610f685f03ceaed1e160b7..181556318fbc4e7285dc885b9b9a54ade972079c 100644 (file)
@@ -25,8 +25,7 @@ DRIVER_SOURCES = \
        savagetex.c \
        savagetris.c \
        savageioctl.c \
-       savagespan.c \
-       savagedma.c
+       savagespan.c
 
 C_SOURCES = \
        $(COMMON_SOURCES) \
index 3c91e01f210c589afa614b22733a1dd1f9121a28..0928b3ca74e079394eaf598540529b3567c3a25f 100644 (file)
@@ -341,8 +341,8 @@ typedef enum
     TPS_256
 } TexPaletteSize;
 
-    #define MAX_MIPMAP_LOD_BIAS             255
-    #define MIN_MIPMAP_LOD_BIAS             -255
+#define MAX_MIPMAP_LOD_BIAS 255
+#define MIN_MIPMAP_LOD_BIAS -255
 
 typedef enum
 {
@@ -627,107 +627,6 @@ typedef union {
 #define SAVAGE_HW_NO_UV1        ((1<<6) | (1<<7))
 #define SAVAGE_HW_SKIPFLAGS     0x000000ff
 
-#define SAVAGE_HW_TRIANGLE_TYPE     (3UL<<25)
-#define SAVAGE_HW_TRIANGLE_CONT     (1UL<<24)
-#define SAVAGE_HW_TRIANGLE_LIST     (0<<25) 
-#define SAVAGE_HW_TRIANGLE_STRIP    (1<<25) 
-#define SAVAGE_HW_TRIANGLE_FAN      (2<<25) 
-#define SAVAGE_HW_QUAD              (3<<25) 
-
-#define __HW_TEXTURE_CHANGED       0x00002FE
-#define __HW_HAS_SCISSORS_CHANGED  0x00001800
-#define __HW_ALL_CHANGED           0x1FFFFFF           
-/*Frank 2001/11/14 Wait commands*/
-#define WAIT_3D_IDLE    0xC0010000
-#define WAIT_3D_2D_IDLE 0xC0030000
-
-#define SET_REGISTER(index, count) \
-    ((CMD_SetRegister << 27) | (0x6000000) | ((count) << 16) | (index))
-
-/*frank 2001/11/20 */
-#define MAXLOOP 0xFFFFFF
-/*#define MAXFIFO 0x7F00*/
-#define MAXFIFO 0x1FF00
-
-/* get eventtag from shadow status */
-/* here we use eventTag1 because eventTag0 is used by HWXvMC*/
-#define GET_EVENTTAG \
-    (((*(volatile GLuint *)(imesa->MMIO_BASE+0x48c04)) & 0xffff0000L)>>16)
-
-#define SHADOW_WAIT(imesa ) do \
-{ \
-    int loop=0; \
-    imesa->shadowCounter = (imesa->shadowCounter + 1) & 0xffff;\
-    if(imesa->shadowCounter == 0)\
-      imesa->shadowCounter = MAX_SHADOWCOUNTER;\
-    *(volatile GLuint *)imesa->BCIBase = imesa->shadowCounter | 0x98400000L;\
-    while(\
-         (GET_EVENTTAG) != imesa->shadowCounter  &&\
-         (loop++ < MAXLOOP));\
-}while(0);
-
-#define SHADOW_WAIT_IDLE(imesa ) do \
-{ \
-    int loop=0; \
-    imesa->shadowCounter = (imesa->shadowCounter + 1) & 0xffff;\
-    if(imesa->shadowCounter == 0)\
-      imesa->shadowCounter = MAX_SHADOWCOUNTER;\
-/*    *(volatile GLuint *)imesa->BCIBase = WAIT_3D_IDLE;\*/\
-    *(volatile GLuint *)imesa->BCIBase = imesa->shadowCounter | 0x98400000L;\
-    while ( \
-    (GET_EVENTTAG) != imesa->shadowCounter && \
-    (loop++ < MAXLOOP)); \
-}while(0);
-
-#if 0
-#define ALT_STATUS_WORD0 (* (volatile GLuint *)(imesa->MMIO_BASE+0x48c60))
-
-#define PAGE_PENDING(result) do{\
-result=((ALT_STATUS_WORD0 & 0x08000000)?GL_TRUE:GL_FALSE);\
-}while(0)
-
-#define WAIT_FOR_FIFO(count) do{\
-int loop = 0; \
-int slots = MAXFIFO-count; \
-while(((ALT_STATUS_WORD0 &0x001fffff)>slots)&&(loop++<MAXLOOP)); \
-}while(0)
-
-
-#define WAIT_IDLE_EMPTY do{\
-int loop = 0; \
- if (/*imesa->shadowStatus*/0)\
-   {\
-     SHADOW_WAIT_IDLE(imesa);\
-   }\
- else\
-   { \
-     while(((ALT_STATUS_WORD0 &0x00ffffff)!=0x00E00000L)&&(loop++<MAXLOOP));\
-   }\
-}while(0)
-
-#define WAIT_IDLE do{\
-int loop = 0; \
-if (imesa->shadowStatus)\
- while((((*imesa->shadowPointer) & 0x0E000000L)!=0x0E000000L)&&(loop++<MAXLOOP));\
-else\
-while(((ALT_STATUS_WORD0 &0x00E00000)!=0x00E00000L)&&(loop++<MAXLOOP)); \
-}while(0)
-#endif /* 0 */
-
-#define SAVAGE_DRAW_PRIMITIVE(count, typeandvertexSkip, isCont)  \
-        ( ((count)<<16) | (typeandvertexSkip) | (isCont | (1<<31)));
-
-static __inline volatile GLuint * SAVAGE_GET_BCI_POINTER(savageContextPtr imesa, GLuint count)   
-{ 
-  WAIT_FOR_FIFO(count);                                
-  return (volatile GLuint *)(imesa->BCIBase);      
-}
-
-/*use this set bci cmd now!*/
-#define WRITE_CMD(buf,cmd,type) do {\
-    *((type*)buf)=cmd;\
-    buf++;\
-  }while(0)
 #endif
 
 
index 1454b6b36c851399fc94dc41f3a6eec1f063a11e..27539bea1633e7d4a6df3b585110350e5a3dbbc2 100644 (file)
@@ -41,11 +41,6 @@ typedef struct {
 } savageRegion, *savageRegionPtr;
 
 typedef struct {
-   savageRegion front;
-   savageRegion back;
-   savageRegion depth;
-   savageRegion aperture;
-
    int chipset;
    int width;
    int height;
@@ -53,31 +48,34 @@ typedef struct {
 
    int cpp;                    /* for front and back buffers */
    int zpp;
+
+   int agpMode;
+
+   unsigned int bufferSize;
+
 #if 0 
    int bitsPerPixel;
 #endif
    unsigned int frontFormat;
    unsigned int frontOffset;
-   unsigned int frontPitch;
-   unsigned int frontBitmapDesc;
-
    unsigned int backOffset;
-   unsigned int backBitmapDesc;
    unsigned int depthOffset;
-   unsigned int depthBitmapDesc;
 
-   unsigned int backPitch;
-   unsigned int backPitchBits;
+   unsigned int aperturePitch;
 
    unsigned int textureOffset[SAVAGE_NR_TEX_HEAPS];
    unsigned int textureSize[SAVAGE_NR_TEX_HEAPS];
    unsigned int logTextureGranularity[SAVAGE_NR_TEX_HEAPS];
    drmAddress texVirtual[SAVAGE_NR_TEX_HEAPS];
   
-  __DRIscreenPrivate *driScrnPriv;
-  drmBufMapPtr  bufs;
-  int use_copy_buf;
-  unsigned int sarea_priv_offset;
+   __DRIscreenPrivate *driScrnPriv;
+
+   savageRegion aperture;
+   savageRegion agpTextures;
+
+   drmBufMapPtr bufs;
+
+   unsigned int sarea_priv_offset;
 
    /* Configuration cache with default values for all contexts */
    driOptionCache optionCache;
@@ -87,7 +85,6 @@ typedef struct {
 #include "savagecontext.h"
 
 extern void savageGetLock( savageContextPtr imesa, GLuint flags );
-extern void savageEmitHwStateLocked( savageContextPtr imesa );
 extern void savageEmitScissorValues( savageContextPtr imesa, int box_nr, int emit );
 extern void savageEmitDrawingRectangle( savageContextPtr imesa );
 extern void savageXMesaSetBackClipRects( savageContextPtr imesa );
index bcbc9d69ed4f89d0173a5067e7ebf35b9e0d30fc..f1798de134dae465d3e138abff19aa1bd4918bb3 100644 (file)
@@ -55,8 +55,6 @@
 
 #include "savage_dri.h"
 
-#include "savagedma.h"
-
 #include "xmlpool.h"
 
 /* Configuration
@@ -85,6 +83,8 @@ static const struct dri_debug_control debug_control[] =
     { "fall",  DEBUG_FALLBACKS },
     { "api",   DEBUG_VERBOSE_API },
     { "lru",   DEBUG_VERBOSE_LRU },
+    { "verb",  DEBUG_VERBOSE_MSG },
+    { "dma",   DEBUG_DMA },
     { NULL,    0 }
 };
 #ifndef SAVAGE_DEBUG
@@ -131,7 +131,6 @@ savageInitDriver(__DRIscreenPrivate *sPriv)
   savageScreenPrivate *savageScreen;
   SAVAGEDRIPtr         gDRIPriv = (SAVAGEDRIPtr)sPriv->pDevPriv;
 
-
    /* Allocate the private area */
    savageScreen = (savageScreenPrivate *)Xmalloc(sizeof(savageScreenPrivate));
    if (!savageScreen)
@@ -146,23 +145,19 @@ savageInitDriver(__DRIscreenPrivate *sPriv)
    savageScreen->mem=gDRIPriv->mem;
    savageScreen->cpp=gDRIPriv->cpp;
    savageScreen->zpp=gDRIPriv->zpp;
-   savageScreen->frontPitch=gDRIPriv->frontPitch;
-   savageScreen->frontOffset=gDRIPriv->frontOffset;
-   savageScreen->frontBitmapDesc = gDRIPriv->frontBitmapDesc;
-   
+
+   savageScreen->agpMode=gDRIPriv->agpMode;
+
+   savageScreen->bufferSize=gDRIPriv->bufferSize;
+
    if (gDRIPriv->cpp == 4) 
        savageScreen->frontFormat = DV_PF_8888;
    else
        savageScreen->frontFormat = DV_PF_565;
-
+   savageScreen->frontOffset=gDRIPriv->frontOffset;
    savageScreen->backOffset = gDRIPriv->backOffset; 
-   savageScreen->backBitmapDesc = gDRIPriv->backBitmapDesc; 
    savageScreen->depthOffset=gDRIPriv->depthOffset;
-   savageScreen->depthBitmapDesc = gDRIPriv->depthBitmapDesc; 
-#if 0   
-   savageScreen->backPitch = gDRIPriv->auxPitch;
-   savageScreen->backPitchBits = gDRIPriv->auxPitchBits;
-#endif   
+
    savageScreen->textureOffset[SAVAGE_CARD_HEAP] = 
                                    gDRIPriv->textureOffset;
    savageScreen->textureSize[SAVAGE_CARD_HEAP] = 
@@ -171,57 +166,32 @@ savageInitDriver(__DRIscreenPrivate *sPriv)
                                    gDRIPriv->logTextureGranularity;
 
    savageScreen->textureOffset[SAVAGE_AGP_HEAP] = 
-                                   gDRIPriv->agpTextures.handle;
+                                   gDRIPriv->agpTextureHandle;
    savageScreen->textureSize[SAVAGE_AGP_HEAP] = 
-                                   gDRIPriv->agpTextures.size;
+                                   gDRIPriv->agpTextureSize;
    savageScreen->logTextureGranularity[SAVAGE_AGP_HEAP] =
                                    gDRIPriv->logAgpTextureGranularity;
-   
-   savageScreen->back.handle = gDRIPriv->backbuffer;
-   savageScreen->back.size = gDRIPriv->backbufferSize;
-   savageScreen->back.map = 
-       (drmAddress)(((unsigned int)sPriv->pFB)+gDRIPriv->backOffset);
-   
-   savageScreen->depth.handle = gDRIPriv->depthbuffer;
-   savageScreen->depth.size = gDRIPriv->depthbufferSize;
-
-   savageScreen->depth.map = 
-              (drmAddress)(((unsigned int)sPriv->pFB)+gDRIPriv->depthOffset);
-   
-   savageScreen->sarea_priv_offset = gDRIPriv->sarea_priv_offset;
 
-   savageScreen->texVirtual[SAVAGE_CARD_HEAP] = 
-             (drmAddress)(((unsigned int)sPriv->pFB)+gDRIPriv->textureOffset);
-
-   if (drmMap(sPriv->fd, 
-             gDRIPriv->registers.handle, 
-             gDRIPriv->registers.size, 
-             (drmAddress *)&(gDRIPriv->registers.map)) != 0) 
-   {
-      Xfree(savageScreen);
-      sPriv->private = NULL;
-      return GL_FALSE;
-   }
-   
+   savageScreen->agpTextures.handle = gDRIPriv->agpTextureHandle;
+   savageScreen->agpTextures.size   = gDRIPriv->agpTextureSize;
    if (drmMap(sPriv->fd, 
-             gDRIPriv->agpTextures.handle, 
-             gDRIPriv->agpTextures.size, 
-             (drmAddress *)&(gDRIPriv->agpTextures.map)) != 0) 
+             savageScreen->agpTextures.handle,
+             savageScreen->agpTextures.size,
+             (drmAddress *)&(savageScreen->agpTextures.map)) != 0) 
    {
       Xfree(savageScreen);
       sPriv->private = NULL;
       return GL_FALSE;
    }
 
-/* agp texture*/
+   savageScreen->texVirtual[SAVAGE_CARD_HEAP] = 
+             (drmAddress)(((unsigned int)sPriv->pFB)+gDRIPriv->textureOffset);
    savageScreen->texVirtual[SAVAGE_AGP_HEAP] = 
-                        (drmAddress)(gDRIPriv->agpTextures.map);
-
-   gDRIPriv->BCIcmdBuf.map = (drmAddress *)
-                           ((unsigned int)gDRIPriv->registers.map+0x00010000);
+                        (drmAddress)(savageScreen->agpTextures.map);
 
-   savageScreen->aperture.handle = gDRIPriv->aperture.handle;
-   savageScreen->aperture.size   = gDRIPriv->aperture.size;
+   savageScreen->aperture.handle = gDRIPriv->apertureHandle;
+   savageScreen->aperture.size   = gDRIPriv->apertureSize;
+   savageScreen->aperturePitch   = gDRIPriv->aperturePitch;
    if (drmMap(sPriv->fd, 
              savageScreen->aperture.handle, 
              savageScreen->aperture.size, 
@@ -230,8 +200,12 @@ savageInitDriver(__DRIscreenPrivate *sPriv)
       Xfree(savageScreen);
       sPriv->private = NULL;
       return GL_FALSE;
-   } 
-      
+   }
+
+   savageScreen->bufs = drmMapBufs(sPriv->fd);
+
+   savageScreen->sarea_priv_offset = gDRIPriv->sarea_priv_offset;
+
    /* parse information in __driConfigOptions */
    driParseOptionInfo (&savageScreen->optionCache,
                       __driConfigOptions, __driNConfigOptions);
@@ -251,6 +225,8 @@ savageDestroyScreen(__DRIscreenPrivate *sPriv)
 {
    savageScreenPrivate *savageScreen = (savageScreenPrivate *)sPriv->private;
 
+   drmUnmapBufs(savageScreen->bufs);
+
    /* free all option information */
    driDestroyOptionInfo (&savageScreen->optionCache);
 
@@ -295,7 +271,6 @@ savageCreateContext( const __GLcontextModes *mesaVis,
    savageContextPtr imesa;
    __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
    struct dd_function_table functions;
-   SAVAGEDRIPtr         gDRIPriv = (SAVAGEDRIPtr)sPriv->pDevPriv;
    savageScreenPrivate *savageScreen = (savageScreenPrivate *)sPriv->private;
    drm_savage_sarea_t *saPriv=(drm_savage_sarea_t *)(((char*)sPriv->pSAREA)+
                                                 savageScreen->sarea_priv_offset);
@@ -323,6 +298,12 @@ savageCreateContext( const __GLcontextModes *mesaVis,
    }
    driContextPriv->driverPrivate = imesa;
 
+   imesa->cmdBuf.size = SAVAGE_CMDBUF_SIZE;
+   imesa->cmdBuf.base = imesa->cmdBuf.write =
+       malloc(SAVAGE_CMDBUF_SIZE * sizeof(drm_savage_cmd_header_t));
+   if (!imesa->cmdBuf.base)
+       return GL_FALSE;
+
    /* Parse configuration files */
    driParseConfigFiles (&imesa->optionCache, &savageScreen->optionCache,
                         sPriv->myNum, "savage");
@@ -398,26 +379,14 @@ savageCreateContext( const __GLcontextModes *mesaVis,
    
    /* DMA buffer */
 
-   /*The shadow pointer*/
-   imesa->shadowPointer = 
-     (volatile GLuint *)((((GLuint)(&saPriv->shadow_status)) + 31) & 0xffffffe0L) ;
-   /* here we use eventTag1 because eventTag0 is used by HWXvMC*/
-   imesa->eventTag1 = (volatile GLuint *)(imesa->shadowPointer + 6);
-   /*   imesa->eventTag1=(volatile GLuint *)(imesa->MMIO_BASE+0x48c04);*/
-   imesa->shadowCounter = MAX_SHADOWCOUNTER;
-   imesa->shadowStatus = GL_TRUE;/*Will judge by 2d message */
-
-   imesa->MMIO_BASE = (GLuint)gDRIPriv->registers.map;
-   imesa->BCIBase= (GLuint)gDRIPriv->BCIcmdBuf.map;
    for(i=0;i<5;i++)
    {
        imesa->apertureBase[i] = ((GLuint)savageScreen->aperture.map + 
                                  0x01000000 * i );
    }
    
-   imesa->aperturePitch = gDRIPriv->aperturePitch;
-   
-   
+   imesa->aperturePitch = savageScreen->aperturePitch;
+
    /* change texHeap initialize to support two kind of texture heap*/
    /* here is some parts of initialization, others in InitDriver() */
     
@@ -440,7 +409,17 @@ savageCreateContext( const __GLcontextModes *mesaVis,
    imesa->depth_scale = (imesa->savageScreen->zpp == 2) ?
        (1.0F/0x10000):(1.0F/0x1000000);
 
-   imesa->vertex_dma_buffer = NULL;
+   imesa->bufferSize = savageScreen->bufferSize;
+   imesa->dmaVtxBuf.total = 0;
+   imesa->dmaVtxBuf.used = 0;
+   imesa->dmaVtxBuf.flushed = 0;
+
+   imesa->clientVtxBuf.total = 16384;
+   imesa->clientVtxBuf.used = 0;
+   imesa->clientVtxBuf.flushed = 0;
+   imesa->clientVtxBuf.buf = (u_int32_t *)malloc(16384*4);
+
+   imesa->vtxBuf = &imesa->clientVtxBuf;
 
    /* Uninitialized vertex format. Force setting the vertex state in
     * savageRenderStart.
@@ -450,6 +429,7 @@ savageCreateContext( const __GLcontextModes *mesaVis,
    /* Utah stuff
     */
    imesa->new_state = ~0;
+   imesa->new_gl_state = ~0;
    imesa->RenderIndex = ~0;
    imesa->dirty = ~0;
    imesa->lostContext = GL_TRUE;
@@ -483,8 +463,6 @@ savageCreateContext( const __GLcontextModes *mesaVis,
 
    ctx->DriverCtx = (void *) imesa;
    imesa->glCtx = ctx;
-   if (savageDMAInit(imesa) == GL_FALSE)
-       return GL_FALSE;  
 
 #ifndef SAVAGE_DEBUG
    SAVAGE_DEBUG = driParseDebugString( getenv( "SAVAGE_DEBUG" ),
@@ -501,8 +479,7 @@ savageCreateContext( const __GLcontextModes *mesaVis,
 
    savageDDInitState( imesa );
 
-   if (driQueryOptionb(&imesa->optionCache, "no_rast"))
-       FALLBACK(ctx, SAVAGE_FALLBACK_NORAST, GL_TRUE);
+   imesa->no_rast = driQueryOptionb(&imesa->optionCache, "no_rast");
 
    driContextPriv->driverPrivate = (void *) imesa;
 
@@ -529,8 +506,10 @@ savageDestroyContext(__DRIcontextPrivate *driContextPriv)
       }
       foreach_s (t, next_t, &(imesa->SwappedOut))
         savageDestroyTexObj(imesa, t);
-      /*free the dma buffer*/
-      savageDMAClose(imesa);
+
+      free(imesa->cmdBuf.base);
+      free(imesa->clientVtxBuf.buf);
+
       _swsetup_DestroyContext(imesa->glCtx );
       _tnl_DestroyContext( imesa->glCtx );
       _ac_DestroyContext( imesa->glCtx );
@@ -753,10 +732,13 @@ void savageGetLock( savageContextPtr imesa, GLuint flags )
     * more broken than usual.
     */
    if (sarea->ctxOwner != me) {
-      imesa->dirty |= (SAVAGE_UPLOAD_CTX |
-                      SAVAGE_UPLOAD_CLIPRECTS |
+      imesa->dirty |= (SAVAGE_UPLOAD_LOCAL |
+                      SAVAGE_UPLOAD_GLOBAL |
+                      SAVAGE_UPLOAD_FOGTBL |
                       SAVAGE_UPLOAD_TEX0 |
-                      SAVAGE_UPLOAD_TEX1);
+                      SAVAGE_UPLOAD_TEX1 |
+                      SAVAGE_UPLOAD_TEXGLOBAL |
+                      SAVAGE_UPLOAD_CLIPRECTS);
       imesa->lostContext = GL_TRUE;
       sarea->ctxOwner = me;
    }
@@ -794,8 +776,6 @@ void savageGetLock( savageContextPtr imesa, GLuint flags )
              savageResetGlobalLRU( imesa , heap );
            }
 
-           imesa->dirty |= SAVAGE_UPLOAD_TEX0IMAGE;
-           imesa->dirty |= SAVAGE_UPLOAD_TEX1IMAGE;
            imesa->texAge[heap] = sarea->texAge[heap];
        }
    } /* end of for loop */ 
@@ -948,10 +928,9 @@ void * __driCreateNewScreen( __DRInativeDisplay *dpy, int scrn, __DRIscreen *psc
                             
 {
    __DRIscreenPrivate *psp;
-   static const __DRIversion ddx_expected = { 1, 0, 0 };
+   static const __DRIversion ddx_expected = { 2, 0, 0 };
    static const __DRIversion dri_expected = { 4, 0, 0 };
-   static const __DRIversion drm_expected = { 1, 0, 0 };
-
+   static const __DRIversion drm_expected = { 2, 0, 0 };
 
    if ( ! driCheckDriDdxDrmVersions2( "Savage",
                                      dri_version, & dri_expected,
index f41b73e0de53f5973800a97745af32c476abaf6d..8978f9247cf44bc944f73b6f40e46241ccdc4c8d 100644 (file)
@@ -42,7 +42,6 @@ typedef struct savage_texture_object_t *savageTextureObjectPtr;
 #include "tnl/t_vertex.h"
 
 #include "savagetex.h"
-#include "savagedma.h"
 
 #include "xmlconfig.h"
 
@@ -69,10 +68,26 @@ typedef struct savage_texture_object_t *savageTextureObjectPtr;
 #define SAVAGE_NEW_TEXTURE 0x1
 #define SAVAGE_NEW_CULL    0x2
 
+/* What needs to be changed for the current vertex dma buffer?
+ * This will go away!
+ */
+#define SAVAGE_UPLOAD_LOCAL    0x1  /* DrawLocalCtrl (S4) or 
+                                       DrawCtrl and ZBufCtrl (S3D) */
+#define SAVAGE_UPLOAD_TEX0     0x2  /* texture unit 0 */
+#define SAVAGE_UPLOAD_TEX1     0x4  /* texture unit 1 (S4 only) */
+#define SAVAGE_UPLOAD_FOGTBL   0x8  /* fog table */
+#define SAVAGE_UPLOAD_GLOBAL   0x10 /* most global regs */
+#define SAVAGE_UPLOAD_TEXGLOBAL 0x20 /* TexBlendColor (S4 only) */
+#define SAVAGE_UPLOAD_CLIPRECTS 0x1000 /* FIXME: get rid of this */
 
 /*define the max numer of vertex in vertex buf*/
 #define SAVAGE_MAX_VERTEXS 0x10000
 
+/* Don't make it too big. We don't want to buffer up a whole frame
+ * that would force the application to wait later. */
+#define SAVAGE_CMDBUF_SIZE 1024
+#define SAVAGE_MAX_VERTS_PENDING 1024
+
 /* Use the templated vertex formats:
  */
 #define TAG(x) savage##x
@@ -113,6 +128,18 @@ typedef void (*savage_point_func)( savageContextPtr, savageVertex * );
                        imesa->savageScreen->deviceID == CHIP_S3TRISTAR64CDDR )
 
 
+struct savage_vtxbuf_t {
+    GLuint total, used, flushed; /* in 32 bit units */
+    GLuint idx;                /* for DMA buffers */
+    u_int32_t *buf;
+};
+
+struct savage_cmdbuf_t {
+    GLuint size; /* size in qwords */
+    drm_savage_cmd_header_t *base;  /* initial state starts here */
+    drm_savage_cmd_header_t *start; /* drawing/state commands start here */
+    drm_savage_cmd_header_t *write; /* append stuff here */
+};
 
 
 struct savage_context_t {
@@ -143,11 +170,12 @@ struct savage_context_t {
     GLuint new_gl_state;
     GLboolean ptexHack;
 
-    GLuint BCIBase;  
-    GLuint MMIO_BASE;
+    /* Command buffer */
+    struct savage_cmdbuf_t cmdBuf;
 
-    /* DMA command buffer */
-    DMABuffer_t DMABuf;
+    /* Vertex buffers */
+    struct savage_vtxbuf_t dmaVtxBuf, clientVtxBuf;
+    struct savage_vtxbuf_t *vtxBuf;
 
     /* aperture base */
     GLuint apertureBase[5];
@@ -179,7 +207,8 @@ struct savage_context_t {
    GLenum raster_primitive;
    GLenum render_primitive;
 
-   GLuint DrawPrimitiveCmd;
+   GLuint skip;
+   GLubyte HwPrim;
    GLuint HwVertexSize;
 
    /* Fallback rasterization functions 
@@ -194,8 +223,9 @@ struct savage_context_t {
     GLuint ClearColor;
     GLfloat depth_scale;
     GLfloat hw_viewport[16];
-    /* DRI stuff */  
-    drmBufPtr  vertex_dma_buffer;
+    /* DRI stuff */
+    GLuint bufferSize;
+    GLuint vertsPending;
 
     GLframebuffer *glBuffer;
    
@@ -225,8 +255,8 @@ struct savage_context_t {
     GLuint backup_streamFIFO;
     GLuint NotFirstFrame;
    
+    GLboolean inSwap;
     GLuint lastSwap;
-    GLuint secondLastSwap;
     GLuint ctxAge;
     GLuint dirtyAge;
     GLuint any_contend;                /* throttle me harder */
@@ -235,7 +265,7 @@ struct savage_context_t {
     GLboolean scissorChanged;
     drm_clip_rect_t draw_rect;
     drm_clip_rect_t scissor_rect;
-    drm_clip_rect_t tmp_boxes[2][SAVAGE_NR_SAREA_CLIPRECTS];
+
     /*Texture aging and DMA based aging*/
     unsigned int texAge[SAVAGE_NR_TEX_HEAPS]; 
 
@@ -259,16 +289,11 @@ struct savage_context_t {
 
     GLboolean hw_stencil;
 
-    /*shadow pointer*/
-    volatile GLuint  *shadowPointer;
-    volatile GLuint *eventTag1;
-    GLuint shadowCounter;
-    GLboolean shadowStatus;
-
     /* Configuration cache
      */
     driOptionCache optionCache;
-    int texture_depth;
+    GLint texture_depth;
+    GLboolean no_rast;
 };
 
 #define SAVAGE_CONTEXT(ctx) ((savageContextPtr)(ctx->DriverCtx))
@@ -283,6 +308,8 @@ extern int SAVAGE_DEBUG;
 #define DEBUG_FALLBACKS      0x001
 #define DEBUG_VERBOSE_API    0x002
 #define DEBUG_VERBOSE_LRU    0x004
+#define DEBUG_VERBOSE_MSG    0x008
+#define DEBUG_DMA            0x010
 
 #define TARGET_FRONT    0x0
 #define TARGET_BACK     0x1
index dddc6d9a650ed4d778cec737c4a629857d4579c7..312f6f62f48363ec3a88e48f92faeee1a1f22670 100644 (file)
 #include "savagecontext.h"
 #include "extensions.h"
 
+#include "utils.h"
+
+
+#define DRIVER_DATE "20050101"
 
 /***************************************
  * Mesa's Driver Functions
 
 static const GLubyte *savageDDGetString( GLcontext *ctx, GLenum name )
 {
+   static char *cardNames[S3_LAST] = {
+       "Unknown",
+       "Savage3D",
+       "Savage/MX/IX",
+       "Savage4",
+       "ProSavage",
+       "Twister",
+       "ProSavageDDR",
+       "SuperSavage",
+       "Savage2000"
+   };
+   static char buffer[128];
+   savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+   savageScreenPrivate *screen = imesa->savageScreen;
+   enum S3CHIPTAGS chipset = screen->chipset;
+   unsigned offset;
+
+   if (chipset < S3_SAVAGE3D || chipset >= S3_LAST)
+      chipset = S3_UNKNOWN; /* should not happen */
+
    switch (name) {
    case GL_VENDOR:
       return (GLubyte *)"S3 Graphics Inc.";
    case GL_RENDERER:
-      return (GLubyte *)"Mesa DRI SAVAGE Linux_1.1.18";
+      offset = driGetRendererString( buffer, cardNames[chipset], DRIVER_DATE,
+                                    screen->agpMode );
+      return (GLubyte *)buffer;
    default:
       return 0;
    }
index 86ee763a31fb9b06bbfecc0f706c774e8f458995..51a1e6d2bd1b4fa2461d73a18e3d87d39c298369 100644 (file)
 #include <time.h>
 #include <unistd.h>
 
-/* Commit does not depend on whether we use real DMA or fake it via the BCI */
-void savageDMACommit (savageContextPtr imesa, void *endPtr) {
-    DMABufferPtr dmaBuff = &imesa->DMABuf;
-    GLuint end = (GLuint)endPtr;
-
-    /* make sure that enough space was allocated */
-    assert (end <= dmaBuff->allocEnd);
-
-    dmaBuff->allocEnd = dmaBuff->end = end;
-
-    /* TODO: check commands, either here or in flush */
-}
-
-#if SAVAGE_CMD_DMA
+#if 0
 /* flag =
          0  return -1 if no available page
         1  wait until a page be available */
@@ -219,139 +206,4 @@ int savageDMAClose (savageContextPtr imesa)
 
     return GL_TRUE;
 }
-#else
-/* Allocate space in faked DMA buffer */
-void *savageDMAAlloc (savageContextPtr imesa, GLuint size) {
-    DMABufferPtr dmaBuff = &imesa->DMABuf;
-
-    /* make sure that everything has been filled in and committed */
-    assert (dmaBuff->end == dmaBuff->allocEnd);
-
-    size *= sizeof (u_int32_t); /* size in bytes */
-    if (dmaBuff->end + size >= dmaBuff->buf->linear + DMA_PAGE_SIZE) {
-       /* need kick off */
-       savageDMAFlush (imesa);
-    }
-    dmaBuff->allocEnd = dmaBuff->end + size;
-    return (void *)dmaBuff->end;
-}
-
-/* Flush DMA buffer via BCI (faked DMA) */
-void savageDMAFlush(savageContextPtr imesa) {
-    volatile u_int32_t* BCIbase;
-    DMABufferPtr dmaBuff = &imesa->DMABuf;
-    u_int32_t *entry;
-
-    /* make sure that everything has been filled in and committed */
-    assert (dmaBuff->allocEnd == dmaBuff->end);
-
-    if (dmaBuff->start == dmaBuff->end) /* no command? */
-      return;
-
-    /* get bci base */
-    BCIbase = (volatile u_int32_t *)SAVAGE_GET_BCI_POINTER(
-       imesa, (dmaBuff->end - dmaBuff->start) / sizeof (u_int32_t));
-
-    for (entry = (u_int32_t *)dmaBuff->start;
-        entry < (u_int32_t *)dmaBuff->end; ++entry)
-       *BCIbase = *entry;
-
-    dmaBuff->end = dmaBuff->allocEnd = dmaBuff->start;
-}
-
-/* Init faked DMA */
-int savageDMAInit (savageContextPtr imesa) {
-    DMABufferPtr dmaBuff = &imesa->DMABuf;
-    drm_savage_alloc_cont_mem_t * req;
-
-    req = (drm_savage_alloc_cont_mem_t *)
-       malloc (sizeof(drm_savage_alloc_cont_mem_t));
-    if (!req)
-       return GL_FALSE;
-
-    req->linear = (GLuint)malloc (DMA_PAGE_SIZE);
-    if (!req->linear) {
-       free (req);
-       return GL_FALSE;
-    }
-
-    dmaBuff->buf = req;
-
-    dmaBuff->start = dmaBuff->end = dmaBuff->allocEnd = req->linear;
-    dmaBuff->usingPage = 0;
-    dmaBuff->kickFlag = GL_FALSE;
-
-    return GL_TRUE;
-}
-
-/* Close faked DMA */
-int savageDMAClose (savageContextPtr imesa) {
-    DMABufferPtr dmaBuff = &imesa->DMABuf;
-    drm_savage_alloc_cont_mem_t * req = dmaBuff->buf;
-
-    free ((void *)req->linear);
-    free (req);
-
-    return GL_TRUE;
-}
-
 #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 u_int32_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->HwVertexSize; /* stride in dwords */
-    GLuint vertexSize = imesa->HwVertexSize; /* the real vertex size in dwords */
-    GLuint nVertices = buffer->used / (vertexStride*4);
-    u_int32_t *data = (u_int32_t*)buffer->address;
-    u_int32_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 u_int32_t *vb = SAVAGE_GET_BCI_POINTER(imesa,
-                                                      count*vertexSize + 1);
-
-       WRITE_CMD (vb, SAVAGE_DRAW_PRIMITIVE(
-                      count, SAVAGE_HW_TRIANGLE_LIST | vertexFormat, 0),
-                  u_int32_t);
-       for (i = 0; i < count; ++i) {
-           for (j = 0; j < vertexSize; ++j)
-               WRITE_CMD (vb, data[j], u_int32_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 0896ca148d5e5becb19529ffcbd0e3fd3a02acf2..09f0c46e95f9a753b1668fe892dfc4d49be82019 100644 (file)
@@ -49,8 +49,4 @@ 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 ac9e055e93174754453f3e14ccef7cf00abcd945..dd7a84e2e720585f6008da0fd9b4bddc0f155823 100644 (file)
 #include "savagecontext.h"
 #include "savageioctl.h"
 #include "savage_bci.h"
-#include "savagedma.h"
+#include "savagestate.h"
 
 #include "drm.h"
 #include <sys/ioctl.h>
 #include <sys/timeb.h>
 
-extern GLuint bcicount;
 #define DEPTH_SCALE_16 ((1<<16)-1)
 #define DEPTH_SCALE_24 ((1<<24)-1)
 
+
+void savageGetDMABuffer( savageContextPtr imesa )
+{
+   int idx = 0;
+   int size = 0;
+   drmDMAReq dma;
+   int retcode;
+   drmBufPtr buf;
+
+   if (SAVAGE_DEBUG & DEBUG_DMA)
+      fprintf(stderr,  "Getting dma buffer\n");
+
+   dma.context = imesa->hHWContext;
+   dma.send_count = 0;
+   dma.send_list = NULL;
+   dma.send_sizes = NULL;
+   dma.flags = 0;
+   dma.request_count = 1;
+   dma.request_size = imesa->bufferSize;
+   dma.request_list = &idx;
+   dma.request_sizes = &size;
+   dma.granted_count = 0;
+
+
+   if (SAVAGE_DEBUG & DEBUG_DMA)
+      fprintf(stderr, "drmDMA (get) ctx %d count %d size 0x%x\n",
+          dma.context, dma.request_count,
+          dma.request_size);
+
+   while (1) {
+      retcode = drmDMA(imesa->driFd, &dma);
+
+      if (SAVAGE_DEBUG & DEBUG_DMA)
+        fprintf(stderr, "retcode %d sz %d idx %d count %d\n",
+                retcode,
+                dma.request_sizes[0],
+                dma.request_list[0],
+                dma.granted_count);
+
+      if (retcode == 0 &&
+         dma.request_sizes[0] &&
+         dma.granted_count)
+        break;
+
+      if (SAVAGE_DEBUG & DEBUG_DMA)
+        fprintf(stderr, "\n\nflush");
+   }
+
+   buf = &(imesa->savageScreen->bufs->list[idx]);
+
+   if (SAVAGE_DEBUG & DEBUG_DMA)
+      fprintf(stderr,
+          "drmDMA (get) returns size[0] 0x%x idx[0] %d\n"
+          "dma_buffer now: buf idx: %d size: %d used: %d addr %p\n",
+          dma.request_sizes[0], dma.request_list[0],
+          buf->idx, buf->total,
+          buf->used, buf->address);
+
+   imesa->dmaVtxBuf.total = buf->total / 4;
+   imesa->dmaVtxBuf.used = 0;
+   imesa->dmaVtxBuf.flushed = 0;
+   imesa->dmaVtxBuf.idx = buf->idx;
+   imesa->dmaVtxBuf.buf = (u_int32_t *)buf->address;
+
+   if (SAVAGE_DEBUG & DEBUG_DMA)
+      fprintf(stderr, "finished getbuffer\n");
+}
+
+#if 0
+/* Still keeping this around because it demonstrates page flipping and
+ * automatic z-clear. */
 static void savage_BCI_clear(GLcontext *ctx, drm_savage_clear_t *pclear)
 {
        savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
@@ -113,7 +183,7 @@ static void savage_BCI_clear(GLcontext *ctx, drm_savage_clear_t *pclear)
                             imesa->regs.s4.zBufCtrl.ni.frameID =
                                ~imesa->regs.s4.zBufCtrl.ni.frameID;
                             
-                            imesa->dirty |= SAVAGE_UPLOAD_CTX;
+                            imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
                        }
                        else
                        {
@@ -157,8 +227,6 @@ static void savage_BCI_clear(GLcontext *ctx, drm_savage_clear_t *pclear)
        savageDMAFlush (imesa);
 }
 
-struct timeb a,b;
-
 static void savage_BCI_swap(savageContextPtr imesa)
 {
     int nbox = imesa->sarea->nbox;
@@ -186,7 +254,7 @@ static void savage_BCI_swap(savageContextPtr imesa)
         imesa->readMap = (char *)imesa->apertureBase[imesa->toggle];
         
         imesa->regs.s4.destCtrl.ni.offset = imesa->savageScreen->backOffset>>11;
-        imesa->dirty |= SAVAGE_UPLOAD_CTX;
+        imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
         bciptr = SAVAGE_GET_BCI_POINTER(imesa,3);
         *(bciptr) = 0x960100B0;
         *(bciptr) = (imesa->savageScreen->frontOffset); 
@@ -220,97 +288,113 @@ static void savage_BCI_swap(savageContextPtr imesa)
         
     }
 }
+#endif
+
+
+static GLboolean intersect_rect( drm_clip_rect_t *out,
+                                const drm_clip_rect_t *a,
+                                const drm_clip_rect_t *b )
+{
+   *out = *a;
+   if (b->x1 > out->x1) out->x1 = b->x1;
+   if (b->y1 > out->y1) out->y1 = b->y1;
+   if (b->x2 < out->x2) out->x2 = b->x2;
+   if (b->y2 < out->y2) out->y2 = b->y2;
+
+   return ((out->x1 < out->x2) && (out->y1 < out->y2));
+}
+
+
+static GLuint savageIntersectClipRects(drm_clip_rect_t *dest,
+                                      const drm_clip_rect_t *src,
+                                      GLuint nsrc,
+                                      const drm_clip_rect_t *clip)
+{
+    GLuint i, ndest;
+
+    for (i = 0, ndest = 0; i < nsrc; ++i, ++src) {
+       if (intersect_rect(dest, src, clip)) {
+           dest++;
+           ndest++;
+       }
+    }
+
+    return ndest;
+}
 
 
 static void savageDDClear( GLcontext *ctx, GLbitfield mask, GLboolean all,
                           GLint cx, GLint cy, GLint cw, GLint ch ) 
 {
   savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
-   __DRIdrawablePrivate *dPriv = imesa->driDrawable;
-   const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask);
-   drm_savage_clear_t clear;
-   int i;
+   GLuint colorMask, depthMask, clearColor, clearDepth, flags;
 
-   clear.flags = 0;
-   clear.clear_color = imesa->ClearColor;
+   if (SAVAGE_DEBUG & DEBUG_VERBOSE_MSG)
+       fprintf (stderr, "%s\n", __FUNCTION__);
 
+   clearColor = imesa->ClearColor;
    if(imesa->savageScreen->zpp == 2)
-       clear.clear_depth = (GLuint) (ctx->Depth.Clear * DEPTH_SCALE_16);
+       clearDepth = (GLuint) (ctx->Depth.Clear * DEPTH_SCALE_16);
    else
-       clear.clear_depth = (GLuint) (ctx->Depth.Clear * DEPTH_SCALE_24);
+       clearDepth = (GLuint) (ctx->Depth.Clear * DEPTH_SCALE_24);
 
-   FLUSH_BATCH( imesa );
+   colorMask = *((GLuint *) &ctx->Color.ColorMask);
+   depthMask = 0;
 
-   if ((mask & DD_FRONT_LEFT_BIT) && ((colorMask&0xffffffUL)==0xffffffUL) ){
-      clear.flags |= SAVAGE_FRONT;
+   flags = 0;
+
+   if (mask & DD_FRONT_LEFT_BIT) {
+      flags |= SAVAGE_FRONT;
       mask &= ~DD_FRONT_LEFT_BIT;
    }
 
-   if ((mask & DD_BACK_LEFT_BIT) && ((colorMask&0xffffffUL)==0xffffffUL) ) {
-      clear.flags |= SAVAGE_BACK;
+   if (mask & DD_BACK_LEFT_BIT) {
+      flags |= SAVAGE_BACK;
       mask &= ~DD_BACK_LEFT_BIT;
    }
 
    if ((mask & DD_DEPTH_BIT) && ctx->Depth.Mask) {
-      clear.flags |= SAVAGE_DEPTH;
+      flags |= SAVAGE_DEPTH;
+      depthMask |=
+         (imesa->savageScreen->zpp == 2) ? 0xffffffff : 0x00ffffff;
       mask &= ~DD_DEPTH_BIT;
    }
    
    if((mask & DD_STENCIL_BIT) && imesa->hw_stencil)
    {
-       clear.flags |= SAVAGE_STENCIL;
-       mask &= ~DD_STENCIL_BIT;
+      flags |= SAVAGE_DEPTH;
+      depthMask |= 0xff000000;
+      mask &= ~DD_STENCIL_BIT;
    }
 
-   if (clear.flags) {
-       LOCK_HARDWARE( imesa );
-
-       /* flip top to bottom */
-       cy = dPriv->h-cy-ch;
-       cx += imesa->drawX;
-       cy += imesa->drawY;
-
-       for (i = 0 ; i < imesa->numClipRects ; ) {       
-          int nr = MIN2(i + SAVAGE_NR_SAREA_CLIPRECTS, imesa->numClipRects);
-          drm_clip_rect_t *box = imesa->pClipRects;     
-          drm_clip_rect_t *b = imesa->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++;
-              }
-          }
-
-          imesa->sarea->nbox = n;
-
-          savage_BCI_clear(ctx,&clear);
+   savageFlushVertices(imesa);
+
+   if (flags) {
+       GLboolean depthCleared = GL_FALSE;
+       if (flags & (SAVAGE_FRONT|SAVAGE_BACK)) {
+          drm_savage_cmd_header_t *cmd;
+          cmd = savageAllocCmdBuf(imesa, sizeof(drm_savage_cmd_header_t));
+          cmd[0].clear0.cmd = SAVAGE_CMD_CLEAR;
+          if ((flags & SAVAGE_DEPTH) &&
+              clearDepth == clearColor && depthMask == colorMask) {
+              cmd[0].clear0.flags = flags;
+              depthCleared = GL_TRUE;
+          } else
+              cmd[0].clear0.flags = flags & (SAVAGE_FRONT|SAVAGE_BACK);
+          cmd[1].clear1.mask = colorMask;
+          cmd[1].clear1.value = clearColor;
+       }
+
+       if ((flags & SAVAGE_DEPTH) && !depthCleared) {
+          drm_savage_cmd_header_t *cmd;
+          cmd = savageAllocCmdBuf(imesa, sizeof(drm_savage_cmd_header_t));
+          cmd[0].clear0.cmd = SAVAGE_CMD_CLEAR;
+          cmd[0].clear0.flags = SAVAGE_DEPTH;
+          cmd[1].clear1.mask = depthMask;
+          cmd[1].clear1.value = clearDepth;
        }
 
-       UNLOCK_HARDWARE( imesa );
-       imesa->dirty |= SAVAGE_UPLOAD_CLIPRECTS|SAVAGE_UPLOAD_CTX;
+       imesa->dirty |= SAVAGE_UPLOAD_CLIPRECTS;
    }
 
    if (mask) 
@@ -318,7 +402,11 @@ static void savageDDClear( GLcontext *ctx, GLbitfield mask, GLboolean all,
 }
 
 
-
+/* This is necessary as to prevent annyoing stuttering effects with
+ * some games, though it does reduce the frame rate (glxgears)
+ * slightly. I believe this is due to texture uploads which do not go
+ * through the Savage command pipeline yet. */
+#define SYNC_FRAMES 1
 
 /*
  * Copy the back buffer to the front buffer. 
@@ -326,11 +414,9 @@ static void savageDDClear( GLcontext *ctx, GLbitfield mask, GLboolean all,
 void savageSwapBuffers( __DRIdrawablePrivate *dPriv )
 {
    savageContextPtr imesa;
-   drm_clip_rect_t *pbox;
-   int nbox;
-   int i;
 
-   GLboolean pending;
+   if (SAVAGE_DEBUG & DEBUG_VERBOSE_MSG)
+       fprintf (stderr, "%s\n================================\n", __FUNCTION__);
 
    assert(dPriv);
    assert(dPriv->driContextPriv);
@@ -342,38 +428,30 @@ void savageSwapBuffers( __DRIdrawablePrivate *dPriv )
 
    FLUSH_BATCH(imesa);
 
-   LOCK_HARDWARE( imesa );
-   WAIT_IDLE_EMPTY;
-   PAGE_PENDING(pending);
-
-   if(!pending)
-   {
-   pbox = dPriv->pClipRects;
-   nbox = dPriv->numClipRects;
+#if SYNC_FRAMES
+   imesa->lastSwap = savageEmitEvent( imesa, 0 );
+#endif
+   if (imesa->lastSwap != 0)
+       savageWaitEvent( imesa, imesa->lastSwap );
 
-   for (i = 0 ; i < nbox ; )
    {
-      int nr = MIN2(i + SAVAGE_NR_SAREA_CLIPRECTS, dPriv->numClipRects);
-      drm_clip_rect_t *b = (drm_clip_rect_t *)imesa->sarea->boxes;
-
-      imesa->sarea->nbox = nr - i;
-
-      for ( ; i < nr ; i++) 
-        *b++ = pbox[i];
-     savage_BCI_swap(imesa) ;
+       drm_savage_cmd_header_t *cmd = savageAllocCmdBuf(imesa, 0);
+       cmd->cmd.cmd = SAVAGE_CMD_SWAP;
+       imesa->inSwap = GL_TRUE; /* ignore scissors in savageFlushCmdBuf */
+       savageFlushCmdBuf(imesa, GL_FALSE);
+       imesa->inSwap = GL_FALSE;
    }
-   }
-   UNLOCK_HARDWARE( imesa );
-   
 
+#if !SYNC_FRAMES
+   imesa->lastSwap = savageEmitEvent( imesa, 0 );
+#endif
 }
 
 /* This waits for *everybody* to finish rendering -- overkill.
  */
 void savageDmaFinish( savageContextPtr imesa  ) 
 {
-    savageDMAFlush(imesa);
-    WAIT_IDLE_EMPTY;
+    savageWaitEvent( imesa, savageEmitEventLocked( imesa, SAVAGE_WAIT_3D ) );
 }
 
 
@@ -393,152 +471,189 @@ void savageWaitAge( savageContextPtr imesa, int age  )
 }
 
 
+unsigned int savageEmitEventLocked( savageContextPtr imesa, unsigned int flags )
+{
+    drm_savage_event_emit_t event;
+    int ret;
+    event.count = 0;
+    event.flags = flags;
+    ret = drmCommandWriteRead( imesa->driFd, DRM_SAVAGE_BCI_EVENT_EMIT,
+                              &event, sizeof(event) );
+    if (ret) {
+       fprintf (stderr, "emit event returned %d\n", ret);
+       exit (1);
+    }
+    return event.count;
+}
+unsigned int savageEmitEvent( savageContextPtr imesa, unsigned int flags )
+{
+    unsigned int ret;
+    LOCK_HARDWARE( imesa );
+    ret = savageEmitEventLocked( imesa, flags );
+    UNLOCK_HARDWARE( imesa );
+    return ret;
+}
 
-void savageFlushVerticesLocked( savageContextPtr imesa )
+
+void savageWaitEvent( savageContextPtr imesa, unsigned int count )
 {
-    drmBufPtr buffer = imesa->vertex_dma_buffer;
+    drm_savage_event_wait_t event;
+    int ret;
+    event.count = count;
+    event.flags = 0;
+    ret = drmCommandWriteRead( imesa->driFd, DRM_SAVAGE_BCI_EVENT_WAIT,
+                              &event, sizeof(event) );
+    if (ret) {
+       fprintf (stderr, "wait event returned %d\n", ret);
+       exit (1);
+    }
+}
 
-    if (!buffer)
-       return;
 
-    imesa->vertex_dma_buffer = NULL;
+void savageFlushVertices( savageContextPtr imesa )
+{
+    struct savage_vtxbuf_t *buffer = imesa->vtxBuf;
+
+    if (SAVAGE_DEBUG & DEBUG_VERBOSE_MSG)
+       fprintf (stderr, "%s\n", __FUNCTION__);
 
-    /* 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) {
+    if (!buffer->total)
+       return;
+
+    if (buffer->used > buffer->flushed) {
+       drm_savage_cmd_header_t *cmd;
        /* State must be updated "per primitive" because hardware
         * culling must be disabled for unfilled primitives, points
         * and lines. */
-       savageEmitHwStateLocked (imesa);
-       savageFakeVertices (imesa, buffer);
+       savageEmitChangedState (imesa);
+       cmd = savageAllocCmdBuf(imesa, 0);
+       cmd->prim.cmd = buffer == &imesa->dmaVtxBuf ?
+           SAVAGE_CMD_DMA_PRIM : SAVAGE_CMD_VB_PRIM;
+       cmd->prim.prim = imesa->HwPrim;
+       cmd->prim.skip = imesa->skip;
+       cmd->prim.start = buffer->flushed / imesa->HwVertexSize;
+       cmd->prim.count = buffer->used / imesa->HwVertexSize - cmd->prim.start;
+       buffer->flushed = buffer->used;
+       /* Make sure we don't buffer too many vertices without
+        * telling the hardware. */
+       imesa->vertsPending += cmd->prim.count;
+       if (imesa->vertsPending > SAVAGE_MAX_VERTS_PENDING) {
+           savageFlushCmdBuf(imesa, GL_FALSE);
+           imesa->vertsPending = 0;
+       }
     }
 }
 
-
-void savageFlushVertices( savageContextPtr imesa ) 
+void savageFlushCmdBufLocked( savageContextPtr imesa, GLboolean discard )
 {
-    LOCK_HARDWARE(imesa);
-    savageFlushVerticesLocked (imesa);
-    UNLOCK_HARDWARE(imesa);
+    __DRIdrawablePrivate *dPriv = imesa->driDrawable;
+    drm_savage_cmdbuf_t cmdbuf;
+    drm_savage_cmd_header_t *start;
+    int ret;
+
+    /* If we lost the context we must restore the initial state (at
+     * the start of the command buffer). */
+    if (imesa->lostContext) {
+       start = imesa->cmdBuf.base;
+       imesa->lostContext = GL_FALSE;
+    } else
+       start = imesa->cmdBuf.start;
+
+    if (!imesa->dmaVtxBuf.total)
+       discard = GL_FALSE;
+
+    if ((SAVAGE_DEBUG & DEBUG_DMA) && discard)
+       fprintf (stderr, "Discarding DMA buffer, used=%u\n",
+                imesa->dmaVtxBuf.used);
+
+    cmdbuf.dma_idx = imesa->dmaVtxBuf.idx;
+    cmdbuf.discard = discard;
+    cmdbuf.vb_addr = imesa->clientVtxBuf.buf;
+    cmdbuf.vb_size = imesa->clientVtxBuf.total*4;
+    cmdbuf.vb_stride = imesa->HwVertexSize;
+    cmdbuf.cmd_addr = start;
+    cmdbuf.size = (imesa->cmdBuf.write - start);
+    if (!imesa->inSwap && imesa->glCtx->Scissor.Enabled) {
+       drm_clip_rect_t *box = dPriv->pClipRects, *ibox;
+       GLuint nbox = dPriv->numClipRects, nibox;
+       ibox = malloc(dPriv->numClipRects*sizeof(drm_clip_rect_t));
+       if (!ibox) {
+           fprintf(stderr, "Out of memory.\n");
+           exit(1);
+       }
+       nibox = savageIntersectClipRects(ibox, box, nbox, &imesa->scissor_rect);
+       cmdbuf.nbox = nibox;
+       cmdbuf.box_addr = ibox;
+    } else {
+       cmdbuf.nbox = dPriv->numClipRects;
+       cmdbuf.box_addr = dPriv->pClipRects;
+    }
+
+    ret = drmCommandWrite( imesa->driFd, DRM_SAVAGE_BCI_CMDBUF,
+                          &cmdbuf, sizeof(cmdbuf) );
+    if (ret) {
+       fprintf (stderr, "cmdbuf ioctl returned %d\n", ret);
+       exit(1);
+    }
+
+    if (cmdbuf.box_addr != dPriv->pClipRects) {
+       free(cmdbuf.box_addr);
+    }
+
+    if (discard) {
+       imesa->dmaVtxBuf.total = 0;
+       imesa->dmaVtxBuf.used = 0;
+       imesa->dmaVtxBuf.flushed = 0;
+    }
+    imesa->clientVtxBuf.used = 0;
+    imesa->clientVtxBuf.flushed = 0;
+
+    imesa->cmdBuf.write = imesa->cmdBuf.base;
+
+    /* Save the current state at the start of the command buffer. That
+     * state will only be emitted, if the context was lost since the
+     * last command buffer. */
+    savageEmitOldState(imesa);
+    imesa->cmdBuf.start = imesa->cmdBuf.write;
 }
 
 
-int savage_check_copy(int fd)
+void savageFlushCmdBuf( savageContextPtr imesa, GLboolean discard ) 
 {
-    return 0;
+    if (SAVAGE_DEBUG & DEBUG_VERBOSE_MSG)
+       fprintf (stderr, "%s\n", __FUNCTION__);
+    LOCK_HARDWARE(imesa);
+    savageFlushCmdBufLocked (imesa, discard);
+    UNLOCK_HARDWARE(imesa);
 }
 
+
 static void savageDDFlush( GLcontext *ctx )
 {
+    if (SAVAGE_DEBUG & DEBUG_VERBOSE_MSG)
+       fprintf (stderr, "%s\n", __FUNCTION__);
     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+    savageFlushVertices (imesa);
     LOCK_HARDWARE(imesa);
-    savageFlushVerticesLocked (imesa);
-    savageDMAFlush (imesa);
+    savageFlushCmdBufLocked(imesa, GL_FALSE);
     UNLOCK_HARDWARE(imesa);
 }
 
 static void savageDDFinish( GLcontext *ctx  ) 
 {
+    if (SAVAGE_DEBUG & DEBUG_VERBOSE_MSG)
+       fprintf (stderr, "%s\n", __FUNCTION__);
     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+    savageFlushVertices (imesa);
     LOCK_HARDWARE(imesa);
-    savageFlushVerticesLocked (imesa);
+    savageFlushCmdBufLocked(imesa, GL_FALSE);
     savageDmaFinish (imesa);
     UNLOCK_HARDWARE(imesa);
 }
 
-#define ALT_STATUS_WORD0 (* (volatile GLuint *)(imesa->MMIO_BASE+0x48c60))
-#define STATUS_WORD0 (* (volatile GLuint *)(imesa->MMIO_BASE+0x48c00))
-#define MAXFIFO_S4  0x7F00
-#define MAXFIFO_S3D 0x7F00
-
-static GLboolean savagePagePending_s4( savageContextPtr imesa ) {
-    return (ALT_STATUS_WORD0 & 0x08000000) ? GL_TRUE : GL_FALSE;
-}
-static GLboolean savagePagePending_s3d( savageContextPtr imesa ) {
-    return GL_FALSE;
-}
-static void savageWaitForFIFO_s4( savageContextPtr imesa, unsigned count ) {
-    int loop = 0;
-    int slots = MAXFIFO_S4-count;
-    while((ALT_STATUS_WORD0 & 0x001fffff) > slots && loop++ < MAXLOOP);
-}
-static void savageWaitForFIFO_s3d( savageContextPtr imesa, unsigned count ) {
-    int loop = 0;
-    int slots = MAXFIFO_S3D-count;
-    while((STATUS_WORD0 & 0x0001ffff) > slots && loop++ < MAXLOOP);
-}
-static void savageWaitIdleEmpty_s4( savageContextPtr imesa ) {
-    int loop = 0;
-    while((ALT_STATUS_WORD0 & 0x00ffffff) != 0x00E00000L && loop++ < MAXLOOP);
-}
-static void savageWaitIdleEmpty_s3d( savageContextPtr imesa ) {
-    int loop = 0;
-    while((STATUS_WORD0 & 0x000fffff) != 0x000E0000L && loop++ < MAXLOOP);
-}
-
-GLboolean (*savagePagePending)( savageContextPtr imesa ) = NULL;
-void (*savageWaitForFIFO)( savageContextPtr imesa, unsigned count ) = NULL;
-void (*savageWaitIdleEmpty)( savageContextPtr imesa ) = NULL;
-
-
 void savageDDInitIoctlFuncs( GLcontext *ctx )
 {
    ctx->Driver.Clear = savageDDClear;
    ctx->Driver.Flush = savageDDFlush;
    ctx->Driver.Finish = savageDDFinish;
-   if (SAVAGE_CONTEXT( ctx )->savageScreen->chipset >= S3_SAVAGE4) {
-       savagePagePending = savagePagePending_s4;
-       savageWaitForFIFO = savageWaitForFIFO_s4;
-       savageWaitIdleEmpty = savageWaitIdleEmpty_s4;
-   } else {
-       savagePagePending = savagePagePending_s3d;
-       savageWaitForFIFO = savageWaitForFIFO_s3d;
-       savageWaitIdleEmpty = savageWaitIdleEmpty_s3d;
-   }
-}
-
-#if SAVAGE_CMD_DMA
-/* Alloc a continuous memory */
-/* return: 0 error when kernel alloc pages(can try a half memory size) 
-           >0 sucess
-          <0 Other error*/
-int  savageAllocDMABuffer(savageContextPtr imesa,  drm_savage_alloc_cont_mem_t *req)
-{
-  int ret;
-  if (req ==NULL)
-    return 0;
-
-  if ((ret=ioctl(imesa->driFd, DRM_IOCTL_SAVAGE_ALLOC_CONTINUOUS_MEM, req)) <=0)    
-    return ret;
-  
-  return 1;
-  
 }
-
-/* get the physics address*/
-GLuint savageGetPhyAddress(savageContextPtr imesa,void * pointer)
-{
-
-  drm_savage_get_physcis_address_t req;
-  int ret;
-
-  req.v_address = (GLuint )pointer;
-  ret = ioctl(imesa->driFd, DRM_IOCTL_SAVAGE_GET_PHYSICS_ADDRESS,&req);
-
-  return req.p_address;
-}
-
-/* free the buffer got by savageAllocDMABuffe*/
-int  savageFreeDMABuffer(savageContextPtr imesa,  drm_savage_alloc_cont_mem_t *req)
-{
-  GLuint ret;
-  if (req ==NULL)
-    return 0;
-  
-  if ((ret=ioctl(imesa->driFd, DRM_IOCTL_SAVAGE_FREE_CONTINUOUS_MEM, req)) <=0)    
-    return ret;
-  return 1;
-  
-}
-#endif
index acf398b9a6bfa40298c21553be15d6d63b572590..941e74e56b5b37a7a26b02749f166a71f47b2009 100644 (file)
 #define SAVAGE_IOCTL_H
 
 #include "savagecontext.h"
-#include "savagedma.h"
 
 void savageGetGeneralDmaBufferLocked( savageContextPtr mmesa ); 
 
 void savageFlushVertices( savageContextPtr mmesa ); 
-void savageFlushVerticesLocked( savageContextPtr mmesa );
 
 void savageFlushGeneralLocked( savageContextPtr imesa );
 void savageWaitAgeLocked( savageContextPtr imesa, int age );
 void savageWaitAge( savageContextPtr imesa, int age );
 
+unsigned int savageEmitEventLocked( savageContextPtr imesa, unsigned int flags );
+unsigned int savageEmitEvent( savageContextPtr imesa, unsigned int flags );
+void savageWaitEvent( savageContextPtr imesa, unsigned int event);
+
+void savageFlushCmdBufLocked( savageContextPtr imesa, GLboolean discard );
+void savageFlushCmdBuf( savageContextPtr imesa, GLboolean discard );
+
 void savageDmaFinish( savageContextPtr imesa );
 
 void savageRegetLockQuiescent( savageContextPtr imesa );
@@ -46,54 +51,69 @@ void savageDDInitIoctlFuncs( GLcontext *ctx );
 
 void savageSwapBuffers( __DRIdrawablePrivate *dPriv );
 
-int savage_check_copy(int fd);
-
-extern GLboolean (*savagePagePending)( savageContextPtr imesa );
-extern void (*savageWaitForFIFO)( savageContextPtr imesa, unsigned count );
-extern void (*savageWaitIdleEmpty)( savageContextPtr imesa );
-
-#define PAGE_PENDING(result) do { \
-    result = savagePagePending(imesa); \
-} while (0)
-#define WAIT_FOR_FIFO(count) do { \
-    savageWaitForFIFO(imesa, count); \
-} while (0)
 #define WAIT_IDLE_EMPTY do { \
-    savageWaitIdleEmpty(imesa); \
+    savageWaitEvent(imesa, \
+                   savageEmitEvent(imesa, SAVAGE_WAIT_3D|SAVAGE_WAIT_2D)); \
 } while (0)
 
-#if SAVAGE_CMD_DMA
-int  savageAllocDMABuffer(savageContextPtr imesa,  drm_savage_alloc_cont_mem_t *req);
-GLuint savageGetPhyAddress(savageContextPtr imesa,void * pointer);
-int  savageFreeDMABuffer(savageContextPtr, drm_savage_alloc_cont_mem_t*);
-#endif
-
 #define FLUSH_BATCH(imesa) do { \
-    if (imesa->vertex_dma_buffer) savageFlushVertices(imesa); \
+    if (SAVAGE_DEBUG & DEBUG_VERBOSE_MSG) \
+        fprintf (stderr, "FLUSH_BATCH in %s\n", __FUNCTION__); \
+    savageFlushVertices(imesa); \
+    savageFlushCmdBuf(imesa, GL_FALSE); \
 } while (0)
 
+extern void savageGetDMABuffer( savageContextPtr imesa );
+
 static __inline
-u_int32_t *savageAllocDmaLow( savageContextPtr imesa, GLuint bytes )
+u_int32_t *savageAllocVtxBuf( savageContextPtr imesa, GLuint words )
 {
+   struct savage_vtxbuf_t *buffer = imesa->vtxBuf;
    u_int32_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);
+   if (buffer == &imesa->dmaVtxBuf) {
+       if (!buffer->total) {
+          LOCK_HARDWARE(imesa);
+          savageGetDMABuffer(imesa);
+          UNLOCK_HARDWARE(imesa);
+       } else if (buffer->used + words > buffer->total) {
+          if (SAVAGE_DEBUG & DEBUG_VERBOSE_MSG)
+              fprintf (stderr, "... flushing DMA buffer in %s\n",
+                       __FUNCTION__);
+          savageFlushVertices( imesa );
+          LOCK_HARDWARE(imesa);
+          savageFlushCmdBufLocked(imesa, GL_TRUE); /* discard DMA buffer */
+          savageGetDMABuffer(imesa);
+          UNLOCK_HARDWARE(imesa);
+       }
+   } else if (buffer->used + words > buffer->total) {
+       if (SAVAGE_DEBUG & DEBUG_VERBOSE_MSG)
+          fprintf (stderr, "... flushing client vertex buffer in %s\n",
+                   __FUNCTION__);
+       savageFlushVertices( imesa );
+       LOCK_HARDWARE(imesa);
+       savageFlushCmdBufLocked(imesa, GL_FALSE); /* free clientVtxBuf */
+       UNLOCK_HARDWARE(imesa);
    }
 
-   head = (u_int32_t *)((u_int8_t *)imesa->vertex_dma_buffer->address +
-                      imesa->vertex_dma_buffer->used);
+   head = &buffer->buf[buffer->used];
 
-   imesa->vertex_dma_buffer->used += bytes;
+   buffer->used += words;
    return head;
 }
 
+static __inline
+drm_savage_cmd_header_t *savageAllocCmdBuf( savageContextPtr imesa, GLuint bytes )
+{
+    drm_savage_cmd_header_t *ret;
+    GLuint qwords = ((bytes + 7) >> 3) + 1; /* round up */
+    assert (qwords < imesa->cmdBuf.size);
+    if (imesa->cmdBuf.write - imesa->cmdBuf.base + qwords > imesa->cmdBuf.size) {
+       savageFlushCmdBuf(imesa, GL_FALSE);
+    }
+    ret = (drm_savage_cmd_header_t *)imesa->cmdBuf.write;
+    imesa->cmdBuf.write += qwords;
+    return ret;
+}
+
 #endif
index f4f22602d8d5cb388801b122a396d0a030f6b1f0..d6048291bee7c668fa5c2424fdd239be06ff20ac 100644 (file)
@@ -69,16 +69,10 @@ static __inline__ GLuint savagePackColor(GLuint format,
 
 static void savageDDAlphaFunc_s4(GLcontext *ctx, GLenum func, GLfloat ref)
 {
-    /* This can be done in BlendFunc*/
-    savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
-    imesa->dirty |= SAVAGE_UPLOAD_CTX;
     savageBlendFunc_s4(ctx);
 }
 static void savageDDAlphaFunc_s3d(GLcontext *ctx, GLenum func, GLfloat ref)
 {
-    /* This can be done in BlendFunc*/
-    savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
-    imesa->dirty |= SAVAGE_UPLOAD_CTX;
     savageBlendFunc_s3d(ctx);
 }
 
@@ -103,6 +97,9 @@ static void savageDDBlendEquationSeparate(GLcontext *ctx,
 static void savageBlendFunc_s4(GLcontext *ctx)
 {
     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+    u_int32_t drawLocalCtrl = imesa->regs.s4.drawLocalCtrl.ui;
+    u_int32_t drawCtrl0 = imesa->regs.s4.drawCtrl0.ui;
+    u_int32_t drawCtrl1 = imesa->regs.s4.drawCtrl1.ui;
 
     /* set up draw control register (including blending, alpha
      * test, and shading model)
@@ -266,11 +263,17 @@ static void savageBlendFunc_s4(GLcontext *ctx)
     /*imesa->regs.s4.drawLocalCtrl.ni.zUpdateEn =
         ~drawLocalCtrl.ni.wrZafterAlphaTst;*/
 
-    imesa->dirty |= SAVAGE_UPLOAD_CTX;
+    if (drawLocalCtrl != imesa->regs.s4.drawLocalCtrl.ui)
+       imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
+    if (drawCtrl0 != imesa->regs.s4.drawCtrl0.ui ||
+       drawCtrl1 != imesa->regs.s4.drawCtrl1.ui)
+       imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
 }
 static void savageBlendFunc_s3d(GLcontext *ctx)
 {
     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+    u_int32_t drawCtrl = imesa->regs.s3d.drawCtrl.ui;
+    u_int32_t zBufCtrl = imesa->regs.s3d.zBufCtrl.ui;
 
     /* set up draw control register (including blending, alpha
      * test, dithering, and shading model)
@@ -432,7 +435,9 @@ static void savageBlendFunc_s3d(GLcontext *ctx)
     imesa->regs.s3d.zBufCtrl.ni.wrZafterAlphaTst =
        imesa->regs.s3d.drawCtrl.ni.alphaTestEn;
 
-    imesa->dirty |= SAVAGE_UPLOAD_CTX;
+    if (drawCtrl != imesa->regs.s3d.drawCtrl.ui ||
+       zBufCtrl != imesa->regs.s3d.zBufCtrl.ui)
+       imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
 }
 
 static void savageDDBlendFuncSeparate_s4( GLcontext *ctx, GLenum sfactorRGB, 
@@ -456,7 +461,9 @@ static void savageDDDepthFunc_s4(GLcontext *ctx, GLenum func)
 {
     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
     ZCmpFunc zmode;
-#define depthIndex 0
+    u_int32_t drawLocalCtrl = imesa->regs.s4.drawLocalCtrl.ui;
+    u_int32_t zBufCtrl = imesa->regs.s4.zBufCtrl.ui;
+    u_int32_t zWatermarks = imesa->regs.s4.zWatermarks.ui; /* FIXME: in DRM */
 
     /* set up z-buffer control register (global)
      * set up z-buffer offset register (global)
@@ -513,14 +520,20 @@ static void savageDDDepthFunc_s4(GLcontext *ctx, GLenum func)
        imesa->regs.s4.drawLocalCtrl.ni.flushPdZbufWrites = GL_FALSE;
        imesa->regs.s4.zWatermarks.ni.wLow        = 8;
     }
-  
-    imesa->dirty |= SAVAGE_UPLOAD_CTX;
+
+    if (drawLocalCtrl != imesa->regs.s4.drawLocalCtrl.ui)
+       imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
+    if (zBufCtrl != imesa->regs.s4.zBufCtrl.ui ||
+       zWatermarks != imesa->regs.s4.zWatermarks.ui)
+       imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
 }
 static void savageDDDepthFunc_s3d(GLcontext *ctx, GLenum func)
 {
     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
     ZCmpFunc zmode;
-#define depthIndex 0
+    u_int32_t drawCtrl = imesa->regs.s3d.drawCtrl.ui;
+    u_int32_t zBufCtrl = imesa->regs.s3d.zBufCtrl.ui;
+    u_int32_t zWatermarks = imesa->regs.s3d.zWatermarks.ui; /* FIXME: in DRM */
 
     /* set up z-buffer control register (global)
      * set up z-buffer offset register (global)
@@ -565,14 +578,18 @@ static void savageDDDepthFunc_s3d(GLcontext *ctx, GLenum func)
        imesa->regs.s3d.zWatermarks.ni.wLow = 8;
     }
   
-    imesa->dirty |= SAVAGE_UPLOAD_CTX;
+    if (drawCtrl != imesa->regs.s3d.drawCtrl.ui ||
+       zBufCtrl != imesa->regs.s3d.zBufCtrl.ui)
+       imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
+    if (zWatermarks != imesa->regs.s3d.zWatermarks.ui)
+       imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
 }
 
 static void savageDDDepthMask_s4(GLcontext *ctx, GLboolean flag)
 {
     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+    u_int32_t drawLocalCtrl = imesa->regs.s4.drawLocalCtrl.ui;
 
-    imesa->dirty |= SAVAGE_UPLOAD_CTX;
     if (flag)
     {
        imesa->regs.s4.drawLocalCtrl.ni.flushPdZbufWrites = GL_TRUE;
@@ -582,12 +599,15 @@ static void savageDDDepthMask_s4(GLcontext *ctx, GLboolean flag)
        imesa->regs.s4.drawLocalCtrl.ni.flushPdZbufWrites = GL_FALSE;
     }
     savageDDDepthFunc_s4(ctx,ctx->Depth.Func);
+
+    if (drawLocalCtrl != imesa->regs.s4.drawLocalCtrl.ui)
+       imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
 }
 static void savageDDDepthMask_s3d(GLcontext *ctx, GLboolean flag)
 {
     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+    u_int32_t drawCtrl = imesa->regs.s3d.drawCtrl.ui;
 
-    imesa->dirty |= SAVAGE_UPLOAD_CTX;
     if (flag)
     {
        imesa->regs.s3d.drawCtrl.ni.flushPdZbufWrites = GL_TRUE;
@@ -597,6 +617,9 @@ static void savageDDDepthMask_s3d(GLcontext *ctx, GLboolean flag)
        imesa->regs.s3d.drawCtrl.ni.flushPdZbufWrites = GL_FALSE;
     }
     savageDDDepthFunc_s3d(ctx,ctx->Depth.Func);
+
+    if (drawCtrl != imesa->regs.s3d.drawCtrl.ui)
+       imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
 }
 
 
@@ -629,6 +652,7 @@ static void savageDDScissor( GLcontext *ctx, GLint x, GLint y,
 static void savageDDDrawBuffer(GLcontext *ctx, GLenum mode )
 {
     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+    u_int32_t destCtrl = imesa->regs.s4.destCtrl.ui;
 
     /*
      * _DrawDestMask is easier to cope with than <mode>.
@@ -641,7 +665,6 @@ static void savageDDDrawBuffer(GLcontext *ctx, GLenum mode )
        imesa->readMap = (char *)imesa->apertureBase[TARGET_FRONT];
        imesa->regs.s4.destCtrl.ni.offset = imesa->savageScreen->frontOffset>>11;
         imesa->NotFirstFrame = GL_FALSE;
-        imesa->dirty |= SAVAGE_UPLOAD_BUFFERS | SAVAGE_UPLOAD_CTX;
         savageXMesaSetFrontClipRects( imesa );
        FALLBACK( ctx, SAVAGE_FALLBACK_DRAW_BUFFER, GL_FALSE );
        break;
@@ -651,7 +674,6 @@ static void savageDDDrawBuffer(GLcontext *ctx, GLenum mode )
         imesa->readMap = (char *)imesa->apertureBase[TARGET_BACK];
        imesa->regs.s4.destCtrl.ni.offset = imesa->savageScreen->backOffset>>11;
         imesa->NotFirstFrame = GL_FALSE;
-        imesa->dirty |= SAVAGE_UPLOAD_BUFFERS | SAVAGE_UPLOAD_CTX;
         savageXMesaSetBackClipRects( imesa );
        FALLBACK( ctx, SAVAGE_FALLBACK_DRAW_BUFFER, GL_FALSE );
        break;
@@ -664,6 +686,9 @@ static void savageDDDrawBuffer(GLcontext *ctx, GLenum mode )
      * gets called.
      */
     _swrast_DrawBuffer(ctx, mode);
+
+    if (destCtrl != imesa->regs.s4.destCtrl.ui)
+        imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
 }
 
 static void savageDDReadBuffer(GLcontext *ctx, GLenum mode )
@@ -800,12 +825,12 @@ static void savageUpdateCull( GLcontext *ctx )
     if (imesa->savageScreen->chipset >= S3_SAVAGE4) {
        if (imesa->regs.s4.drawCtrl1.ni.cullMode != cullMode) {
            imesa->regs.s4.drawCtrl1.ni.cullMode = cullMode;
-           imesa->dirty |= SAVAGE_UPLOAD_CTX;
+           imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
        }
     } else {
        if (imesa->regs.s3d.drawCtrl.ni.cullMode != cullMode) {
            imesa->regs.s3d.drawCtrl.ni.cullMode = cullMode;
-           imesa->dirty |= SAVAGE_UPLOAD_CTX;
+           imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
        }
     }
 #endif /* end  #if HW_CULL */
@@ -846,7 +871,7 @@ static void savageDDColorMask_s4(GLcontext *ctx,
     {
        imesa->regs.s4.drawLocalCtrl.ni.drawUpdateEn = GL_FALSE;
     }
-    imesa->dirty |= SAVAGE_UPLOAD_CTX;
+    imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
     /* TODO: need a software fallback */
 }
 static void savageDDColorMask_s3d(GLcontext *ctx, 
@@ -873,7 +898,7 @@ static void savageDDColorMask_s3d(GLcontext *ctx,
     {
        imesa->regs.s3d.zBufCtrl.ni.drawUpdateEn = GL_FALSE;
     }
-    imesa->dirty |= SAVAGE_UPLOAD_CTX;
+    imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
     /* TODO: need a software fallback */
 }
 
@@ -886,6 +911,7 @@ static void savageDDColorMask_s3d(GLcontext *ctx,
  */
 static void savageUpdateSpecular_s4(GLcontext *ctx) {
     savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
+    u_int32_t drawLocalCtrl = imesa->regs.s4.drawLocalCtrl.ui;
 
     if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR &&
        ctx->Light.Enabled) {
@@ -895,10 +921,13 @@ static void savageUpdateSpecular_s4(GLcontext *ctx) {
        imesa->regs.s4.drawLocalCtrl.ni.specShadeEn = GL_FALSE;
        /*FALLBACK (ctx, SAVAGE_FALLBACK_SPECULAR, GL_FALSE);*/
     }
-    imesa->dirty |= SAVAGE_UPLOAD_CTX;
+
+    if (drawLocalCtrl != imesa->regs.s4.drawLocalCtrl.ui)
+       imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
 }
 static void savageUpdateSpecular_s3d(GLcontext *ctx) {
     savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
+    u_int32_t drawCtrl = imesa->regs.s3d.drawCtrl.ui;
 
     if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR &&
        ctx->Light.Enabled) {
@@ -908,7 +937,9 @@ static void savageUpdateSpecular_s3d(GLcontext *ctx) {
        imesa->regs.s3d.drawCtrl.ni.specShadeEn = GL_FALSE;
        /*FALLBACK (ctx, SAVAGE_FALLBACK_SPECULAR, GL_FALSE);*/
     }
-    imesa->dirty |= SAVAGE_UPLOAD_CTX;
+
+    if (drawCtrl != imesa->regs.s3d.drawCtrl.ui)
+       imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
 }
 
 static void savageDDLightModelfv_s4(GLcontext *ctx, GLenum pname, 
@@ -925,6 +956,7 @@ static void savageDDLightModelfv_s3d(GLcontext *ctx, GLenum pname,
 static void savageDDShadeModel_s4(GLcontext *ctx, GLuint mod)
 {
     savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
+    u_int32_t drawLocalCtrl = imesa->regs.s4.drawLocalCtrl.ui;
 
     if (mod == GL_SMOOTH)  
     {    
@@ -934,11 +966,14 @@ static void savageDDShadeModel_s4(GLcontext *ctx, GLuint mod)
     {
        imesa->regs.s4.drawLocalCtrl.ni.flatShadeEn = GL_TRUE;
     }
-    imesa->dirty |= SAVAGE_UPLOAD_CTX;
+
+    if (drawLocalCtrl != imesa->regs.s4.drawLocalCtrl.ui)
+       imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
 }
 static void savageDDShadeModel_s3d(GLcontext *ctx, GLuint mod)
 {
     savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
+    u_int32_t drawCtrl = imesa->regs.s3d.drawCtrl.ui;
 
     if (mod == GL_SMOOTH)  
     {    
@@ -948,7 +983,9 @@ static void savageDDShadeModel_s3d(GLcontext *ctx, GLuint mod)
     {
        imesa->regs.s3d.drawCtrl.ni.flatShadeEn = GL_TRUE;
     }
-    imesa->dirty |= SAVAGE_UPLOAD_CTX;
+
+    if (drawCtrl != imesa->regs.s3d.drawCtrl.ui)
+       imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
 }
 
 
@@ -962,6 +999,7 @@ static void savageDDFogfv(GLcontext *ctx, GLenum pname, const GLfloat *param)
 {
     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
     GLuint  fogClr;
+    u_int32_t fogCtrl = imesa->regs.s4.fogCtrl.ui;
 
     /*if ((ctx->Fog.Enabled) &&(pname == GL_FOG_COLOR))*/
     if (ctx->Fog.Enabled)
@@ -981,17 +1019,19 @@ static void savageDDFogfv(GLcontext *ctx, GLenum pname, const GLfloat *param)
        imesa->regs.s4.fogCtrl.ni.fogEn     = 0;
        imesa->regs.s4.fogCtrl.ni.fogMode   = 0;
     }
-    imesa->dirty |= SAVAGE_UPLOAD_CTX;      
-}
 
+    if (fogCtrl != imesa->regs.s4.fogCtrl.ui)
+       imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
+}
 
-static void savageStencilFunc(GLcontext *);
 
 static void savageDDStencilFunc(GLcontext *ctx, GLenum func, GLint ref,
                                 GLuint mask)
 {
     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
     SCmpFunc a=0;
+    u_int32_t zBufCtrl = imesa->regs.s4.zBufCtrl.ui;
+    u_int32_t stencilCtrl = imesa->regs.s4.stencilCtrl.ui;
 
     imesa->regs.s4.zBufCtrl.ni.stencilRefVal = ctx->Stencil.Ref[0];
     imesa->regs.s4.stencilCtrl.ni.readMask  = ctx->Stencil.ValueMask[0];
@@ -1012,22 +1052,26 @@ static void savageDDStencilFunc(GLcontext *ctx, GLenum func, GLint ref,
 
     imesa->regs.s4.stencilCtrl.ni.cmpFunc = a;
 
-    imesa->dirty |= SAVAGE_UPLOAD_CTX;
+    if (zBufCtrl != imesa->regs.s4.zBufCtrl.ui ||
+       stencilCtrl != imesa->regs.s4.stencilCtrl.ui)
+       imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
 }
 
 static void savageDDStencilMask(GLcontext *ctx, GLuint mask)
 {
     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
 
-    imesa->regs.s4.stencilCtrl.ni.writeMask = ctx->Stencil.WriteMask[0];
-
-    imesa->dirty |= SAVAGE_UPLOAD_CTX;
+    if (imesa->regs.s4.stencilCtrl.ni.writeMask != ctx->Stencil.WriteMask[0]) {
+       imesa->regs.s4.stencilCtrl.ni.writeMask = ctx->Stencil.WriteMask[0];
+       imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
+    }
 }
 
 static void savageDDStencilOp(GLcontext *ctx, GLenum fail, GLenum zfail,
                               GLenum zpass)
 {
     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
+    u_int32_t stencilCtrl = imesa->regs.s4.stencilCtrl.ui;
 
     switch (ctx->Stencil.FailFunc[0])
     {
@@ -1114,7 +1158,8 @@ static void savageDDStencilOp(GLcontext *ctx, GLenum fail, GLenum zfail,
        break;
     }
 
-    imesa->dirty |= SAVAGE_UPLOAD_CTX;
+    if (stencilCtrl != imesa->regs.s4.stencilCtrl.ui)
+       imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
 }
 
 
@@ -1128,11 +1173,9 @@ static void savageDDEnable_s4(GLcontext *ctx, GLenum cap, GLboolean state)
     switch(cap) {
         case GL_ALPHA_TEST:
             /* we should consider the disable case*/
-            imesa->dirty |= SAVAGE_UPLOAD_CTX;
             savageBlendFunc_s4(ctx);
             break;
         case GL_BLEND:
-            imesa->dirty |= SAVAGE_UPLOAD_CTX;
             /*Can't find Enable bit in the 3D registers.*/ 
             /* For some reason enable(GL_BLEND) affects ColorLogicOpEnabled.
              */
@@ -1146,7 +1189,6 @@ static void savageDDEnable_s4(GLcontext *ctx, GLenum cap, GLboolean state)
             savageBlendFunc_s4(ctx);
             break;
         case GL_DEPTH_TEST:
-            imesa->dirty |= SAVAGE_UPLOAD_CTX;
             savageDDDepthFunc_s4(ctx,ctx->Depth.Func);
             break;
         case GL_SCISSOR_TEST:
@@ -1154,7 +1196,6 @@ static void savageDDEnable_s4(GLcontext *ctx, GLenum cap, GLboolean state)
             imesa->dirty |= SAVAGE_UPLOAD_CLIPRECTS;
             break;
         case GL_STENCIL_TEST:
-            imesa->dirty |= SAVAGE_UPLOAD_CTX;
            if (!imesa->hw_stencil)
                FALLBACK (ctx, SAVAGE_FALLBACK_STENCIL, state);
            else {
@@ -1167,11 +1208,10 @@ static void savageDDEnable_s4(GLcontext *ctx, GLenum cap, GLboolean state)
                    imesa->regs.s4.zBufCtrl.ni.zBufEn         = GL_TRUE;
                    imesa->regs.s4.drawLocalCtrl.ni.zUpdateEn = GL_FALSE;
                }
-               imesa->dirty |= SAVAGE_UPLOAD_CTX;
+               imesa->dirty |= SAVAGE_UPLOAD_GLOBAL | SAVAGE_UPLOAD_LOCAL;
            }
             break;
         case GL_FOG:
-            imesa->dirty |= SAVAGE_UPLOAD_CTX;
             savageDDFogfv(ctx,0,0);    
             break;
         case GL_CULL_FACE:
@@ -1188,7 +1228,6 @@ static void savageDDEnable_s4(GLcontext *ctx, GLenum cap, GLboolean state)
 #endif
             break;
         case GL_DITHER:
-            imesa->dirty |= SAVAGE_UPLOAD_CTX;
             if (state)
             {
                 if ( ctx->Color.DitherFlag )
@@ -1200,6 +1239,7 @@ static void savageDDEnable_s4(GLcontext *ctx, GLenum cap, GLboolean state)
             {
                 imesa->regs.s4.drawCtrl1.ni.ditherEn=GL_FALSE;
             }
+            imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
             break;
  
         case GL_LIGHTING:
@@ -1223,11 +1263,9 @@ static void savageDDEnable_s3d(GLcontext *ctx, GLenum cap, GLboolean state)
     switch(cap) {
         case GL_ALPHA_TEST:
             /* we should consider the disable case*/
-            imesa->dirty |= SAVAGE_UPLOAD_CTX;
             savageBlendFunc_s3d(ctx);
             break;
         case GL_BLEND:
-            imesa->dirty |= SAVAGE_UPLOAD_CTX;
             /*Can't find Enable bit in the 3D registers.*/ 
             /* For some reason enable(GL_BLEND) affects ColorLogicOpEnabled.
              */
@@ -1241,7 +1279,6 @@ static void savageDDEnable_s3d(GLcontext *ctx, GLenum cap, GLboolean state)
             savageBlendFunc_s3d(ctx);
             break;
         case GL_DEPTH_TEST:
-            imesa->dirty |= SAVAGE_UPLOAD_CTX;
             savageDDDepthFunc_s3d(ctx,ctx->Depth.Func);
             break;
         case GL_SCISSOR_TEST:
@@ -1252,7 +1289,6 @@ static void savageDDEnable_s3d(GLcontext *ctx, GLenum cap, GLboolean state)
            FALLBACK (ctx, SAVAGE_FALLBACK_STENCIL, state);
            break;
         case GL_FOG:
-            imesa->dirty |= SAVAGE_UPLOAD_CTX;
             savageDDFogfv(ctx,0,0);    
             break;
         case GL_CULL_FACE:
@@ -1269,7 +1305,6 @@ static void savageDDEnable_s3d(GLcontext *ctx, GLenum cap, GLboolean state)
 #endif
             break;
         case GL_DITHER:
-            imesa->dirty |= SAVAGE_UPLOAD_CTX;
             if (state)
             {
                 if ( ctx->Color.DitherFlag )
@@ -1281,6 +1316,7 @@ static void savageDDEnable_s3d(GLcontext *ctx, GLenum cap, GLboolean state)
             {
                 imesa->regs.s3d.drawCtrl.ni.ditherEn=GL_FALSE;
             }
+            imesa->dirty |= SAVAGE_UPLOAD_LOCAL;
             break;
  
         case GL_LIGHTING:
@@ -1303,8 +1339,7 @@ void savageDDUpdateHwState( GLcontext *ctx )
     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
 
     if (imesa->new_state) {
-       FLUSH_BATCH(imesa);
-
+       savageFlushVertices(imesa);
        if (imesa->new_state & SAVAGE_NEW_TEXTURE) {
            savageUpdateTextureState( ctx );
        }
@@ -1368,20 +1403,20 @@ void savageEmitDrawingRectangle( savageContextPtr imesa )
          imesa->regs.ni.changed.ni.fDrawCtrl1Changed=GL_TRUE;*/
 
     savageCalcViewport (imesa->glCtx);
-
-    imesa->dirty |= SAVAGE_UPLOAD_BUFFERS;
 }
 
 
 static void savageDDPrintDirty( const char *msg, GLuint state )
 {
-    fprintf(stderr, "%s (0x%x): %s%s%s%s%s\n",    
+    fprintf(stderr, "%s (0x%x): %s%s%s%s%s%s%s\n",        
             msg,
             (unsigned int) state,
-            (state & SAVAGE_UPLOAD_TEX0IMAGE)  ? "upload-tex0, " : "",
-            (state & SAVAGE_UPLOAD_TEX1IMAGE)  ? "upload-tex1, " : "",
-            (state & SAVAGE_UPLOAD_CTX)        ? "upload-ctx, " : "",
-            (state & SAVAGE_UPLOAD_BUFFERS)    ? "upload-bufs, " : "",
+            (state & SAVAGE_UPLOAD_LOCAL)      ? "upload-local, " : "",
+            (state & SAVAGE_UPLOAD_TEX0)       ? "upload-tex0, " : "",
+            (state & SAVAGE_UPLOAD_TEX1)       ? "upload-tex1, " : "",
+            (state & SAVAGE_UPLOAD_FOGTBL)     ? "upload-fogtbl, " : "",
+            (state & SAVAGE_UPLOAD_GLOBAL)     ? "upload-global, " : "",
+            (state & SAVAGE_UPLOAD_TEXGLOBAL)  ? "upload-texglobal, " : "",
             (state & SAVAGE_UPLOAD_CLIPRECTS)  ? "upload-cliprects, " : ""
             );
 }
@@ -1400,18 +1435,32 @@ static GLboolean savageGlobalRegChanged (savageContextPtr imesa,
     }
     return GL_FALSE;
 }
+static void savageEmitOldRegs (savageContextPtr imesa,
+                              GLuint first, GLuint last, GLboolean global) {
+    GLuint n = last-first+1;
+    drm_savage_cmd_header_t *cmd = savageAllocCmdBuf(imesa, n*4);
+    cmd->state.cmd = SAVAGE_CMD_STATE;
+    cmd->state.global = global;
+    cmd->state.count = n;
+    cmd->state.start = first;
+    memcpy(cmd+1, &imesa->oldRegs.ui[first-SAVAGE_FIRST_REG], n*4);
+}
 static void savageEmitContiguousRegs (savageContextPtr imesa,
                                      GLuint first, GLuint last) {
     GLuint i;
-    u_int32_t *pBCIBase;
-    pBCIBase = savageDMAAlloc (imesa, last - first + 2);
-    WRITE_CMD (pBCIBase, SET_REGISTER(first, last - first + 1), u_int32_t);
-
-    for (i = first - SAVAGE_FIRST_REG; i <= last - SAVAGE_FIRST_REG; ++i) {
-       WRITE_CMD (pBCIBase, imesa->regs.ui[i], u_int32_t);
+    GLuint n = last-first+1;
+    drm_savage_cmd_header_t *cmd = savageAllocCmdBuf(imesa, n*4);
+    cmd->state.cmd = SAVAGE_CMD_STATE;
+    cmd->state.global = savageGlobalRegChanged(imesa, first, last);
+    cmd->state.count = n;
+    cmd->state.start = first;
+    memcpy(cmd+1, &imesa->regs.ui[first-SAVAGE_FIRST_REG], n*4);
+    /* savageAllocCmdBuf may need to flush the cmd buffer and backup
+     * the current hardware state. It should see the "old" (current)
+     * state that has actually been emitted to the hardware. Therefore
+     * this update is done *after* savageAllocCmdBuf. */
+    for (i = first - SAVAGE_FIRST_REG; i <= last - SAVAGE_FIRST_REG; ++i)
        imesa->oldRegs.ui[i] = imesa->regs.ui[i];
-    }
-    savageDMACommit (imesa, pBCIBase);
 }
 static void savageEmitChangedRegs (savageContextPtr imesa,
                                   GLuint first, GLuint last) {
@@ -1445,8 +1494,6 @@ static void savageEmitChangedRegChunk (savageContextPtr imesa,
 }
 static void savageUpdateRegister_s4(savageContextPtr imesa)
 {
-    u_int32_t *pBCIBase;
-
     /*
      * Scissors updates drawctrl0 and drawctrl 1
      */
@@ -1470,23 +1517,12 @@ static void savageUpdateRegister_s4(savageContextPtr imesa)
 
     /* the savage4 uses the contiguous range of BCI registers 0x1e-0x39
      * 0x1e-0x27 are local, no need to check them for global changes */
-    if (imesa->lostContext || savageGlobalRegChanged (imesa, 0x28, 0x39)) {
-       pBCIBase = savageDMAAlloc (imesa, 1);
-        WRITE_CMD (pBCIBase, WAIT_3D_IDLE, u_int32_t);
-       savageDMACommit (imesa, pBCIBase);
-    }
-    if (imesa->lostContext)
-       savageEmitContiguousRegs (imesa, 0x1e, 0x39);
-    else
-       savageEmitChangedRegs (imesa, 0x1e, 0x39);
+    savageEmitContiguousRegs (imesa, 0x1e, 0x39);
 
     imesa->dirty=0;
-    imesa->lostContext = GL_FALSE;
 }
 static void savageUpdateRegister_s3d(savageContextPtr imesa)
 {
-    u_int32_t *pBCIBase;
-
     if (imesa->scissorChanged)
     {
         if(imesa->scissor)
@@ -1519,63 +1555,55 @@ static void savageUpdateRegister_s3d(savageContextPtr imesa)
     imesa->regs.s3d.drawCtrl.ni.flushPdZbufWrites = GL_TRUE;
 
     /* the savage3d uses two contiguous ranges of BCI registers:
-     * 0x18-0x1c and 0x20-0x38. The first range is local. */
-    if (imesa->lostContext || savageGlobalRegChanged (imesa, 0x20, 0x38)) {
-       pBCIBase = savageDMAAlloc (imesa, 1);
-        WRITE_CMD (pBCIBase, WAIT_3D_IDLE, u_int32_t);
-       savageDMACommit (imesa, pBCIBase);
-    }
+     * 0x18-0x1c and 0x20-0x38. Some texture registers need to be
+     * emitted in one chunk or we get some funky rendering errors. */
     /* FIXME: watermark registers aren't programmed correctly ATM */
-    if (imesa->lostContext) {
-       savageEmitContiguousRegs (imesa, 0x18, 0x1c);
-       savageEmitContiguousRegs (imesa, 0x20, 0x36);
-    } else {
-       /* On the Savage IX texture registers (at least some of them)
-        * have to be emitted as one chunk. */
-       savageEmitChangedRegs (imesa, 0x18, 0x19);
-       savageEmitChangedRegChunk (imesa, 0x1a, 0x1c);
-       savageEmitChangedRegs (imesa, 0x20, 0x36);
-    }
+    savageEmitChangedRegs (imesa, 0x18, 0x19);
+    savageEmitChangedRegChunk (imesa, 0x1a, 0x1c);
+    savageEmitChangedRegs (imesa, 0x20, 0x36);
 
     imesa->dirty=0;
-    imesa->lostContext = GL_FALSE;
 }
 
 
+void savageEmitOldState( savageContextPtr imesa )
+{
+    assert(imesa->cmdBuf.write == imesa->cmdBuf.base);
+    if (imesa->savageScreen->chipset >= S3_SAVAGE4) {
+       savageEmitOldRegs (imesa, 0x1e, 0x39, GL_TRUE);
+    } else {
+       savageEmitOldRegs (imesa, 0x18, 0x1c, GL_TRUE);
+       savageEmitOldRegs (imesa, 0x20, 0x36, GL_FALSE);
+    }
+}
+
 
 /* Push the state into the sarea and/or texture memory.
  */
-void savageEmitHwStateLocked( savageContextPtr imesa )
+void savageEmitChangedState( savageContextPtr imesa )
 {
     if (SAVAGE_DEBUG & DEBUG_VERBOSE_API)
         savageDDPrintDirty( "\n\n\nsavageEmitHwStateLocked", imesa->dirty );
 
     if (imesa->dirty & ~SAVAGE_UPLOAD_CLIPRECTS)
     {
-        if (imesa->dirty & (SAVAGE_UPLOAD_CTX | SAVAGE_UPLOAD_TEX0  | \
-                            SAVAGE_UPLOAD_TEX1 | SAVAGE_UPLOAD_BUFFERS))
+        if (imesa->dirty & (SAVAGE_UPLOAD_GLOBAL | SAVAGE_UPLOAD_LOCAL |
+                            SAVAGE_UPLOAD_TEX0   | SAVAGE_UPLOAD_TEX1  |
+                           SAVAGE_UPLOAD_FOGTBL | SAVAGE_UPLOAD_TEXGLOBAL))
         {
-   
-            /*SAVAGE_STATE_COPY(imesa);*/
-            /* update state to hw*/
-            if (imesa->driDrawable &&imesa->driDrawable->numClipRects ==0 )
-            {
-                return ;
-            }
+           if (SAVAGE_DEBUG & DEBUG_VERBOSE_MSG)
+               fprintf (stderr, "... emitting state\n");
            if (imesa->savageScreen->chipset >= S3_SAVAGE4)
                savageUpdateRegister_s4(imesa);
            else
                savageUpdateRegister_s3d(imesa);
         }
 
-        imesa->sarea->dirty |= (imesa->dirty & 
-                                ~(SAVAGE_UPLOAD_TEX1|SAVAGE_UPLOAD_TEX0));
         imesa->dirty &= SAVAGE_UPLOAD_CLIPRECTS;
     }
 }
 
 
-
 static void savageDDInitState_s4( savageContextPtr imesa )
 {
 #if 1
@@ -1719,7 +1747,6 @@ static void savageDDInitState_s3d( savageContextPtr imesa )
 }
 void savageDDInitState( savageContextPtr imesa ) {
     memset (imesa->regs.ui, 0, SAVAGE_NR_REGS*sizeof(u_int32_t));
-    memset (imesa->oldRegs.ui, 0, SAVAGE_NR_REGS*sizeof(u_int32_t));
     memset (imesa->globalRegMask.ui, 0xff, SAVAGE_NR_REGS*sizeof(u_int32_t));
     if (imesa->savageScreen->chipset >= S3_SAVAGE4)
        savageDDInitState_s4 (imesa);
@@ -1789,6 +1816,13 @@ void savageDDInitState( savageContextPtr imesa ) {
             imesa->readMap = (char *)imesa->apertureBase[TARGET_BACK];
         }
     }
+
+    memcpy (imesa->oldRegs.ui, imesa->regs.ui, SAVAGE_NR_REGS*sizeof(u_int32_t));
+
+    /* Emit the initial state to the (empty) command buffer. */
+    assert (imesa->cmdBuf.write == imesa->cmdBuf.base);
+    savageEmitOldState(imesa);
+    imesa->cmdBuf.start = imesa->cmdBuf.write;
 }
 
 
index 2cbdb81de58bf7d9150a9ded333653e69dc59adf..b1b402a18431274d418506d49d582fb79d8e1bfd 100644 (file)
 
 #include "savagecontext.h"
 
+void savageEmitOldState( savageContextPtr imesa );
+void savageEmitChangedState( savageContextPtr imesa );
+
 extern void savageDDUpdateHwState( GLcontext *ctx );
 extern void savageDDInitState( savageContextPtr imesa );
 extern void savageDDInitStateFuncs( GLcontext *ctx );
 extern void savageDDRenderStart(GLcontext *ctx);
 extern void savageDDRenderEnd(GLcontext *ctx);
 
-/*frank 2001/11/13 add macro for sarea state copy*/
-#if 0
-#define SAVAGE_STATE_COPY(ctx) { \
-ctx->sarea->setup[0]=ctx->Registers.DrawLocalCtrl.ui; \
-ctx->sarea->setup[1]=ctx->Registers.TexPalAddr.ui; \
-ctx->sarea->setup[2]=ctx->Registers.TexCtrl[0].ui; \
-ctx->sarea->setup[3]=ctx->Registers.TexCtrl[1].ui; \
-ctx->sarea->setup[4]=ctx->Registers.TexAddr[0].ui; \
-ctx->sarea->setup[5]=ctx->Registers.TexAddr[1].ui; \
-ctx->sarea->setup[6]=ctx->Registers.TexBlendCtrl[0].ui; \
-ctx->sarea->setup[7]=ctx->Registers.TexBlendCtrl[1].ui; \
-ctx->sarea->setup[8]=ctx->Registers.TexXprClr.ui; \
-ctx->sarea->setup[9]=ctx->Registers.TexDescr.ui; \
-ctx->sarea->setup[10]=ctx->Registers.FogTable.ni.ulEntry[0]; \
-ctx->sarea->setup[11]=ctx->Registers.FogTable.ni.ulEntry[1]; \
-ctx->sarea->setup[12]=ctx->Registers.FogTable.ni.ulEntry[2]; \
-ctx->sarea->setup[13]=ctx->Registers.FogTable.ni.ulEntry[3]; \
-ctx->sarea->setup[14]=ctx->Registers.FogTable.ni.ulEntry[4]; \
-ctx->sarea->setup[15]=ctx->Registers.FogTable.ni.ulEntry[5]; \
-ctx->sarea->setup[16]=ctx->Registers.FogTable.ni.ulEntry[6]; \
-ctx->sarea->setup[17]=ctx->Registers.FogTable.ni.ulEntry[7]; \
-ctx->sarea->setup[18]=ctx->Registers.FogCtrl.ui; \
-ctx->sarea->setup[19]=ctx->Registers.StencilCtrl.ui; \
-ctx->sarea->setup[20]=ctx->Registers.ZBufCtrl.ui; \
-ctx->sarea->setup[21]=ctx->Registers.ZBufOffset.ui; \
-ctx->sarea->setup[22]=ctx->Registers.DestCtrl.ui; \
-ctx->sarea->setup[23]=ctx->Registers.DrawCtrl0.ui; \
-ctx->sarea->setup[24]=ctx->Registers.DrawCtrl1.ui; \
-ctx->sarea->setup[25]=ctx->Registers.ZWatermarks.ui; \
-ctx->sarea->setup[26]=ctx->Registers.DestTexWatermarks.ui; \
-ctx->sarea->setup[27]=ctx->Registers.TexBlendColor.ui; \
-}
-#endif
 #endif
index c6143baabdd6aa3a0a2c1440c4d880c9e0fb6db1..924f06187b44ddb28f41bfb198b8e39d695a23c0 100644 (file)
@@ -606,7 +606,7 @@ void savagePrintGlobalLRU( savageContextPtr imesa , GLuint heap)
 {
    int i, j;
 
-   drm_savage_tex_region_t *list = imesa->sarea->texList[heap];
+   drm_tex_region_t *list = imesa->sarea->texList[heap];
    
 
    for (i = 0, j = SAVAGE_NR_TEX_REGIONS ; i < SAVAGE_NR_TEX_REGIONS ; i++) {
@@ -628,7 +628,7 @@ void savagePrintGlobalLRU( savageContextPtr imesa , GLuint heap)
 
 void savageResetGlobalLRU( savageContextPtr imesa, GLuint heap )
 {
-    drm_savage_tex_region_t *list = imesa->sarea->texList[heap];
+    drm_tex_region_t *list = imesa->sarea->texList[heap];
    int sz = 1 << imesa->savageScreen->logTextureGranularity[heap];
    int i;
 
@@ -661,7 +661,7 @@ static void savageUpdateTexLRU( savageContextPtr imesa, savageTextureObjectPtr t
    int logsz = imesa->savageScreen->logTextureGranularity[heap];
    int start = t->MemBlock->ofs >> logsz;
    int end = (t->MemBlock->ofs + t->MemBlock->size - 1) >> logsz;
-   drm_savage_tex_region_t *list = imesa->sarea->texList[heap];
+   drm_tex_region_t *list = imesa->sarea->texList[heap];
    
    imesa->texAge[heap] = ++imesa->sarea->texAge[heap];
 
@@ -787,16 +787,19 @@ int savageUploadTexImages( savageContextPtr imesa, savageTextureObjectPtr t )
       ofs = t->MemBlock->ofs;
       t->texParams.hwPhysAddress = imesa->savageScreen->textureOffset[heap] + ofs;
       t->BufAddr = (char *)((GLuint) imesa->savageScreen->texVirtual[heap] + ofs);
-      imesa->dirty |= SAVAGE_UPLOAD_CTX;
+      imesa->dirty |= SAVAGE_UPLOAD_GLOBAL; /* FIXME: really needed? */
    }
 
    /* Let the world know we've used this memory recently.
     */
+   LOCK_HARDWARE(imesa);
    savageUpdateTexLRU( imesa, t );
+   UNLOCK_HARDWARE(imesa);
 
    if (t->dirty_images) {
+      savageFlushVertices (imesa);
       LOCK_HARDWARE(imesa);
-      savageFlushVerticesLocked (imesa);
+      savageFlushCmdBufLocked (imesa, GL_FALSE);
       savageDmaFinish (imesa);
       if (SAVAGE_DEBUG & DEBUG_VERBOSE_LRU)
         fprintf(stderr, "*");
@@ -1436,8 +1439,7 @@ static void savageUpdateTextureState_s4( GLcontext *ctx )
    imesa->CurrentTexObj[1] = 0;   
    savageUpdateTex0State_s4( ctx );
    savageUpdateTex1State_s4( ctx );
-   imesa->dirty |= (SAVAGE_UPLOAD_CTX |
-                   SAVAGE_UPLOAD_TEX0 | 
+   imesa->dirty |= (SAVAGE_UPLOAD_TEX0 | 
                    SAVAGE_UPLOAD_TEX1);
 }
 static void savageUpdateTextureState_s3d( GLcontext *ctx )
@@ -1446,8 +1448,7 @@ static void savageUpdateTextureState_s3d( GLcontext *ctx )
     if (imesa->CurrentTexObj[0]) imesa->CurrentTexObj[0]->bound &= ~1;
     imesa->CurrentTexObj[0] = 0;
     savageUpdateTexState_s3d( ctx );
-    imesa->dirty |= (SAVAGE_UPLOAD_CTX |
-                    SAVAGE_UPLOAD_TEX0);
+    imesa->dirty |= (SAVAGE_UPLOAD_TEX0);
 }
 void savageUpdateTextureState( GLcontext *ctx)
 {
index 69633ecae75ec4a35b26aad8d1be12a88505155c..1732dc50740e3f315e982bde937aea212769a9be 100644 (file)
@@ -100,7 +100,7 @@ static void __inline__ savage_draw_triangle (savageContextPtr imesa,
                                             savageVertexPtr v1,
                                             savageVertexPtr v2) {
    GLuint vertsize = imesa->HwVertexSize;
-   u_int32_t *vb = savageAllocDmaLow (imesa, 3*4*vertsize);
+   u_int32_t *vb = savageAllocVtxBuf (imesa, 3*vertsize);
    GLuint j;
 
    EMIT_VERT (j, vb, vertsize, 0, v0);
@@ -114,7 +114,7 @@ static void __inline__ savage_draw_quad (savageContextPtr imesa,
                                         savageVertexPtr v2,
                                         savageVertexPtr v3) {
    GLuint vertsize = imesa->HwVertexSize;
-   u_int32_t *vb = savageAllocDmaLow (imesa, 6*4*vertsize);
+   u_int32_t *vb = savageAllocVtxBuf (imesa, 6*vertsize);
    GLuint j;
 
    EMIT_VERT (j, vb, vertsize, 0, v0);
@@ -128,7 +128,7 @@ static void __inline__ savage_draw_quad (savageContextPtr imesa,
 static __inline__ void savage_draw_point (savageContextPtr imesa,
                                          savageVertexPtr tmp) {
    GLuint vertsize = imesa->HwVertexSize;
-   u_int32_t *vb = savageAllocDmaLow (imesa, 6*4*vertsize);
+   u_int32_t *vb = savageAllocVtxBuf (imesa, 6*vertsize);
    const GLfloat x = tmp->v.x;
    const GLfloat y = tmp->v.y;
    const GLfloat sz = imesa->glCtx->Point._Size * .5;
@@ -163,7 +163,7 @@ static __inline__ void savage_draw_line (savageContextPtr imesa,
                                         savageVertexPtr v0,
                                         savageVertexPtr v1 ) {
    GLuint vertsize = imesa->HwVertexSize;
-   u_int32_t *vb = savageAllocDmaLow (imesa, 6*4*vertsize);
+   u_int32_t *vb = savageAllocVtxBuf (imesa, 6*vertsize);
    GLfloat width = imesa->glCtx->Line._Width;
    GLfloat dx, dy, ix, iy;
    GLuint j;
@@ -220,7 +220,7 @@ static void __inline__ savage_ptex_tri (savageContextPtr imesa,
                                        savageVertexPtr v1,
                                        savageVertexPtr v2) {
    GLuint vertsize = imesa->HwVertexSize;
-   u_int32_t *vb = savageAllocDmaLow (imesa, 3*4*vertsize);
+   u_int32_t *vb = savageAllocVtxBuf (imesa, 3*vertsize);
    savageVertex tmp;
    GLuint j;
 
@@ -233,7 +233,7 @@ static __inline__ void savage_ptex_line (savageContextPtr imesa,
                                         savageVertexPtr v0,
                                         savageVertexPtr v1 ) {
    GLuint vertsize = imesa->HwVertexSize;
-   u_int32_t *vb = savageAllocDmaLow (imesa, 6*4*vertsize);
+   u_int32_t *vb = savageAllocVtxBuf (imesa, 6*vertsize);
    GLfloat width = imesa->glCtx->Line._Width;
    GLfloat dx, dy, ix, iy;
    savageVertex tmp0, tmp1;
@@ -278,7 +278,7 @@ static __inline__ void savage_ptex_line (savageContextPtr imesa,
 static __inline__ void savage_ptex_point (savageContextPtr imesa,
                                          savageVertexPtr v0) {
    GLuint vertsize = imesa->HwVertexSize;
-   u_int32_t *vb = savageAllocDmaLow (imesa, 6*4*vertsize);
+   u_int32_t *vb = savageAllocVtxBuf (imesa, 6*vertsize);
    const GLfloat x = v0->v.x;
    const GLfloat y = v0->v.y;
    const GLfloat sz = imesa->glCtx->Point._Size * .5;
@@ -428,9 +428,9 @@ do {                                                                \
    savageContextPtr imesa = SAVAGE_CONTEXT(ctx);               \
    GLuint color[n], spec[n];                                   \
    GLuint coloroffset =                                                \
-      ((imesa->DrawPrimitiveCmd & SAVAGE_HW_NO_W) ? 3 : 4);    \
+      ((imesa->skip & SAVAGE_SKIP_W) ? 3 : 4);                 \
    GLboolean specoffset =                                      \
-      ((imesa->DrawPrimitiveCmd & SAVAGE_HW_NO_CS) ? 0 : coloroffset+1);\
+      ((imesa->skip & SAVAGE_SKIP_C1) ? 0 : coloroffset+1);    \
    (void) color; (void) spec; (void) coloroffset; (void) specoffset;
 
 /***********************************************************************
@@ -756,6 +756,16 @@ static void savageChooseRenderState(GLcontext *ctx)
 
       imesa->RenderIndex = index;
    }
+
+   if (imesa->savageScreen->chipset < S3_SAVAGE4 && (flags & DD_FLATSHADE)) {
+      if (imesa->HwPrim != SAVAGE_PRIM_TRILIST_201)
+        savageFlushVertices(imesa);
+      imesa->HwPrim = SAVAGE_PRIM_TRILIST_201;
+   } else {
+      if (imesa->HwPrim != SAVAGE_PRIM_TRILIST)
+        savageFlushVertices(imesa);
+      imesa->HwPrim = SAVAGE_PRIM_TRILIST;
+   }
 }
 
 /**********************************************************************/
@@ -766,6 +776,9 @@ static void savageRunPipeline( GLcontext *ctx )
 {
    savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
 
+   if (imesa->no_rast)
+      FALLBACK(ctx, SAVAGE_FALLBACK_NORAST, GL_TRUE);
+
    if (imesa->new_state)
       savageDDUpdateHwState( ctx );
 
@@ -777,6 +790,9 @@ static void savageRunPipeline( GLcontext *ctx )
    }
 
    _tnl_run_pipeline( ctx );
+
+   if (imesa->no_rast)
+      FALLBACK(ctx, SAVAGE_FALLBACK_NORAST, GL_FALSE);
 }
 
 /**********************************************************************/
@@ -858,7 +874,7 @@ do {                                                                        \
    imesa->vertex_attrs[imesa->vertex_attr_count].format = (STYLE);     \
    imesa->vertex_attr_count++;                                         \
    setupIndex |= (INDEX);                                              \
-   drawCmd &= ~(SKIP);                                                 \
+   skip &= ~(SKIP);                                                    \
 } while (0)
 
 #define EMIT_PAD( N )                                                  \
@@ -891,11 +907,8 @@ static void savageRenderStart( GLcontext *ctx )
    struct vertex_buffer *VB = &tnl->vb;
    GLuint index = tnl->render_inputs;
    GLuint setupIndex = SAVAGE_EMIT_XYZ;
-   GLuint drawCmd = SAVAGE_HW_SKIPFLAGS;
+   GLubyte skip;
    GLboolean ptexHack;
-   if (imesa->savageScreen->chipset < S3_SAVAGE4)
-      drawCmd &= ~SAVAGE_HW_NO_UV1;
-   drawCmd &= ~SAVAGE_HW_NO_Z; /* all mesa vertices have a z coordinate */
 
    /* Check if we need to apply the ptex hack. Choose a new render
     * state if necessary. (Note: this can't be done in
@@ -917,66 +930,115 @@ static void savageRenderStart( GLcontext *ctx )
    VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
    imesa->vertex_attr_count = 0;
  
-   /* EMIT_ATTR's must be in order as they tell t_vertex.c how to
-    * build up a hardware vertex.
-    */
-   if ((index & _TNL_BITS_TEX_ANY) || !(ctx->_TriangleCaps & DD_FLATSHADE)) {
-      EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, SAVAGE_EMIT_W, SAVAGE_HW_NO_W );
-   }
-   else {
-      EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F_VIEWPORT, 0, 0 );
-   }
+   if (imesa->savageScreen->chipset < S3_SAVAGE4) {
+      skip = SAVAGE_SKIP_ALL_S3D;
+      skip &= ~SAVAGE_SKIP_Z; /* all mesa vertices have a z coordinate */
 
-   /* t_context.c always includes a diffuse color */
-   EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA, SAVAGE_EMIT_C0, SAVAGE_HW_NO_CD );
+      /* EMIT_ATTR's must be in order as they tell t_vertex.c how to
+       * build up a hardware vertex.
+       */
+      if ((index & _TNL_BITS_TEX_ANY) || !(ctx->_TriangleCaps & DD_FLATSHADE)) {
+        EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, SAVAGE_EMIT_W, SAVAGE_SKIP_W );
+      }
+      else {
+        EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F_VIEWPORT, 0, 0 );
+        EMIT_PAD( 4 );
+        skip &= ~SAVAGE_SKIP_W;
+      }
+
+      /* t_context.c always includes a diffuse color */
+      EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA, SAVAGE_EMIT_C0, SAVAGE_SKIP_C0 );
       
-   if (index & (_TNL_BIT_COLOR1|_TNL_BIT_FOG)) {
       if ((index & _TNL_BIT_COLOR1))
-        EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, SAVAGE_EMIT_C1, SAVAGE_HW_NO_CS );
+        EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, SAVAGE_EMIT_C1, SAVAGE_SKIP_C1 );
       else
         EMIT_PAD( 3 );
       if ((index & _TNL_BIT_FOG))
-        EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, SAVAGE_EMIT_FOG, SAVAGE_HW_NO_CS );
+        EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, SAVAGE_EMIT_FOG, SAVAGE_SKIP_C1 );
       else
         EMIT_PAD( 1 );
-   }
-
-   if (index & _TNL_BIT_TEX(0)) {
-      if (ptexHack)
-        EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_3F_XYW, SAVAGE_EMIT_STQ0, SAVAGE_HW_NO_UV0);
-      else if (VB->TexCoordPtr[0]->size == 4)
-        assert (0); /* should be caught by savageCheckPTexHack */
-      else if (VB->TexCoordPtr[0]->size >= 2)
-        /* The chromium menu emits some 3D tex coords even though no
-         * 3D texture is enabled. Ignore the 3rd coordinate. */
-        EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_2F, SAVAGE_EMIT_ST0, SAVAGE_HW_NO_UV0 );
-      else
-        EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_1F, SAVAGE_EMIT_S0, SAVAGE_HW_NO_U0 );
-   }
-   if (index & _TNL_BIT_TEX(1)) {
-      if (VB->TexCoordPtr[1]->size == 4)
-        /* Projective textures are not supported by the hardware */
-        assert (0); /* should be caught by savageCheckPTexHack */
-      else if (VB->TexCoordPtr[1]->size >= 2)
-        EMIT_ATTR( _TNL_ATTRIB_TEX1, EMIT_2F, SAVAGE_EMIT_ST1, SAVAGE_HW_NO_UV1 );
+      skip &= ~SAVAGE_SKIP_C1;
+
+      if (index & _TNL_BIT_TEX(0)) {
+        if (ptexHack)
+           EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_3F_XYW, SAVAGE_EMIT_STQ0, SAVAGE_SKIP_ST0);
+        else if (VB->TexCoordPtr[0]->size == 4)
+           assert (0); /* should be caught by savageCheckPTexHack */
+        else if (VB->TexCoordPtr[0]->size >= 2)
+           /* The chromium menu emits some 3D tex coords even though no
+            * 3D texture is enabled. Ignore the 3rd coordinate. */
+           EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_2F, SAVAGE_EMIT_ST0, SAVAGE_SKIP_ST0 );
+        else if (VB->TexCoordPtr[0]->size == 1) {
+           EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_1F, SAVAGE_EMIT_S0, SAVAGE_SKIP_S0 );
+           EMIT_PAD( 4 );
+        } else
+           EMIT_PAD( 8 );
+      } else
+        EMIT_PAD( 8 );
+      skip &= ~SAVAGE_SKIP_ST0;
+   } else {
+      skip = SAVAGE_SKIP_ALL_S4;
+      skip &= ~SAVAGE_SKIP_Z; /* all mesa vertices have a z coordinate */
+
+      /* EMIT_ATTR's must be in order as they tell t_vertex.c how to
+       * build up a hardware vertex.
+       */
+      if ((index & _TNL_BITS_TEX_ANY) || !(ctx->_TriangleCaps & DD_FLATSHADE))
+        EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, SAVAGE_EMIT_W, SAVAGE_SKIP_W );
       else
-        EMIT_ATTR( _TNL_ATTRIB_TEX1, EMIT_1F, SAVAGE_EMIT_S1, SAVAGE_HW_NO_U1 );
+        EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F_VIEWPORT, 0, 0 );
+
+      /* t_context.c always includes a diffuse color */
+      EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA, SAVAGE_EMIT_C0, SAVAGE_SKIP_C0 );
+      
+      if (index & (_TNL_BIT_COLOR1|_TNL_BIT_FOG)) {
+        if ((index & _TNL_BIT_COLOR1))
+           EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, SAVAGE_EMIT_C1, SAVAGE_SKIP_C1 );
+        else
+           EMIT_PAD( 3 );
+        if ((index & _TNL_BIT_FOG))
+           EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, SAVAGE_EMIT_FOG, SAVAGE_SKIP_C1 );
+        else
+           EMIT_PAD( 1 );
+      }
+
+      if (index & _TNL_BIT_TEX(0)) {
+        if (ptexHack)
+           EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_3F_XYW, SAVAGE_EMIT_STQ0, SAVAGE_SKIP_ST0);
+        else if (VB->TexCoordPtr[0]->size == 4)
+           assert (0); /* should be caught by savageCheckPTexHack */
+        else if (VB->TexCoordPtr[0]->size >= 2)
+           /* The chromium menu emits some 3D tex coords even though no
+            * 3D texture is enabled. Ignore the 3rd coordinate. */
+           EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_2F, SAVAGE_EMIT_ST0, SAVAGE_SKIP_ST0 );
+        else
+           EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_1F, SAVAGE_EMIT_S0, SAVAGE_SKIP_S0 );
+      }
+      if (index & _TNL_BIT_TEX(1)) {
+        if (VB->TexCoordPtr[1]->size == 4)
+           /* projective textures are not supported by the hardware */
+           assert (0); /* should be caught by savageCheckPTexHack */
+        else if (VB->TexCoordPtr[1]->size >= 2)
+           EMIT_ATTR( _TNL_ATTRIB_TEX1, EMIT_2F, SAVAGE_EMIT_ST1, SAVAGE_SKIP_ST1 );
+        else
+           EMIT_ATTR( _TNL_ATTRIB_TEX1, EMIT_1F, SAVAGE_EMIT_S1, SAVAGE_SKIP_S1 );
+      }
    }
 
    /* Need to change the vertex emit code if the SetupIndex changed or
     * is set for the first time (indicated by vertex_size == 0). */
    if (setupIndex != imesa->SetupIndex || imesa->vertex_size == 0) {
-      imesa->vertex_size = 
+      GLuint hwVertexSize;
+      imesa->vertex_size =
         _tnl_install_attrs( ctx, 
                             imesa->vertex_attrs, 
                             imesa->vertex_attr_count,
                             imesa->hw_viewport, 0 );
       imesa->vertex_size >>= 2;
       imesa->SetupIndex = setupIndex;
+      imesa->skip = skip;
 
-      imesa->DrawPrimitiveCmd = drawCmd;
-      imesa->HwVertexSize = imesa->vertex_size;
-
+      hwVertexSize = imesa->vertex_size;
       if (setupIndex & SAVAGE_EMIT_Q0) {
         /* The vertex setup code emits homogenous texture
          * coordinates. They are converted to normal 2D coords by
@@ -984,10 +1046,28 @@ static void savageRenderStart( GLcontext *ctx )
          * vertex sizes. Functions that emit vertices to the hardware
          * need to use HwVertexSize, anything that manipulates the
          * vertices generated by t_vertex uses vertex_size. */
-        imesa->HwVertexSize--;
+        hwVertexSize--;
         assert (imesa->ptexHack);
       } else
         assert (!imesa->ptexHack);
+
+      if (hwVertexSize != imesa->HwVertexSize) {
+        /* Changing the vertex size: flush vertex and command buffer and
+         * discard the DMA buffer, if we were using one. */
+        savageFlushVertices(imesa);
+        savageFlushCmdBuf(imesa, GL_TRUE);
+        if (hwVertexSize == 8) {
+           if (SAVAGE_DEBUG & DEBUG_DMA)
+              fprintf (stderr, "Using DMA, skip=0x%02x\n", skip);
+           /* we can use vertex dma */
+           imesa->vtxBuf = &imesa->dmaVtxBuf;
+        } else {
+           if (SAVAGE_DEBUG & DEBUG_DMA)
+              fprintf (stderr, "Not using DMA, skip=0x%02x\n", skip);
+           imesa->vtxBuf = &imesa->clientVtxBuf;
+        }
+        imesa->HwVertexSize = hwVertexSize;
+      }
    }
 
    /* Update hardware state and get the lock */
index af62e761c4398af038f1d38e4e29ad690101d9d9..39b6564fc38a5bcc2e29bc28941c730298c36599 100644 (file)
 #include "xf86drm.h"
 #include "drm.h"
 
+/* Totals 2 Mbytes which equals 2^16 32-byte vertices divided among up
+ * to 32 clients. */
+#define SAVAGE_NUM_BUFFERS 32
+#define SAVAGE_BUFFER_SIZE (1 << 16) /* 64k */
+
 #define SAVAGE_DEFAULT_AGP_MODE     1
 #define SAVAGE_MAX_AGP_MODE         4
 
@@ -68,14 +73,17 @@ typedef struct _server{
    unsigned int frontOffset;
    unsigned int frontPitch;
    unsigned int frontbufferSize;
+   unsigned int frontBitmapDesc;
    
    unsigned int backOffset;
    unsigned int backPitch;
    unsigned int backbufferSize;
+   unsigned int backBitmapDesc;
 
    unsigned int depthOffset;
    unsigned int depthPitch;
    unsigned int depthbufferSize;
+   unsigned int depthBitmapDesc;
 
    unsigned int textureOffset;
    int textureSize;
@@ -89,12 +97,7 @@ typedef struct _server{
    drmRegion status;
 
    /* AGP mappings */
-#if 0
-   drmRegion warp;
-   drmRegion primary;
    drmRegion buffers;
-#endif
-
    drmRegion agpTextures;
    int logAgpTextureGranularity;
 
@@ -114,71 +117,41 @@ typedef struct {
    int cpp;
    int zpp;
 
-   int agpMode;
+   int agpMode; /* 0 for PCI cards */
+
+   unsigned int sarea_priv_offset;
+
+   unsigned int bufferSize; /* size of DMA buffers */
    
-   drm_handle_t frontbuffer;
    unsigned int frontbufferSize;
    unsigned int frontOffset;
-   unsigned int frontPitch;
-   unsigned int frontBitmapDesc;   /*Bitmap Descriptior*/ 
-   unsigned int IsfrontTiled;
 
-   drm_handle_t backbuffer;
    unsigned int backbufferSize;
    unsigned int backOffset;
-   unsigned int backPitch;
-   unsigned int backBitmapDesc;   /*Bitmap Descriptior*/
 
-   drm_handle_t depthbuffer;
    unsigned int depthbufferSize;
    unsigned int depthOffset;
-   unsigned int depthPitch;
-   unsigned int depthBitmapDesc;   /*Bitmap Descriptior*/
-
-
 
-   drm_handle_t textures;
-   drm_handle_t xvmcSurfHandle;
    unsigned int textureOffset;
    unsigned int textureSize;
    int logTextureGranularity;
 
-   /* Allow calculation of setup dma addresses.
-    */
-   unsigned int agpBufferOffset;
-
-   unsigned int agpTextureOffset;
-   unsigned int agpTextureSize;
-   drmRegion agpTextures;
-   int logAgpTextureGranularity;
-
-/*   unsigned int mAccess;*/
-
-   drmRegion aperture;
+   /* Linear aperture */
+   drm_handle_t apertureHandle;
+   unsigned int apertureSize;
    unsigned int aperturePitch;    /* in byte */
 
+   /* Status page (probably not needed, but no harm, read-only) */
+   drm_handle_t statusHandle;
+   unsigned int statusSize;
 
-   drmRegion registers;
-   drmRegion BCIcmdBuf;
-   drmRegion status;
-
-#if 0
-   drmRegion primary;
-   drmRegion buffers;
-#endif
-  /*For shadow status*/
-  unsigned long sareaPhysAddr;
+   /* AGP textures */
+   drm_handle_t agpTextureHandle;
+   unsigned int agpTextureSize;
+   int logAgpTextureGranularity;
 
-   unsigned int sarea_priv_offset;
-  int shadowStatus;
+   /* Not sure about this one */
+   drm_handle_t xvmcSurfHandle; /* ? */
 } SAVAGEDRIRec, *SAVAGEDRIPtr;
 
 #endif
-
-
-
-
-
-
-
-