Bug 7260: mach64 texture memory mng cleanup
authorGeorge Sapountzis <gsap7@yahoo.gr>
Thu, 7 Dec 2006 16:01:13 +0000 (18:01 +0200)
committerGeorge Sapountzis <gsap7@yahoo.gr>
Tue, 12 Dec 2006 10:51:37 +0000 (12:51 +0200)
mach64 uses its own set of texture memory management routines which are buggy,
running a second DRI client kills the first one. This patch ports mach64 code
to the stock dri texture managment code.

src/mesa/drivers/dri/mach64/mach64_context.c
src/mesa/drivers/dri/mach64/mach64_context.h
src/mesa/drivers/dri/mach64/mach64_lock.c
src/mesa/drivers/dri/mach64/mach64_screen.c
src/mesa/drivers/dri/mach64/mach64_tex.c
src/mesa/drivers/dri/mach64/mach64_tex.h
src/mesa/drivers/dri/mach64/mach64_texmem.c
src/mesa/drivers/dri/mach64/mach64_texstate.c

index 03ec96a222efe7284896fdc2553d3190862bfa68..2ab1cf2617e81a196e22f28af7b02a72d9eb231d 100644 (file)
@@ -102,6 +102,7 @@ GLboolean mach64CreateContext( const __GLcontextModes *glVisual,
    mach64ContextPtr mmesa;
    mach64ScreenPtr mach64Screen;
    int i, heap;
+   GLuint *c_textureSwapsPtr = NULL;
 
 #if DO_DEBUG
    MACH64_DEBUG = driParseDebugString(getenv("MACH64_DEBUG"), debug_control);
@@ -153,15 +154,28 @@ GLboolean mach64CreateContext( const __GLcontextModes *glVisual,
    mmesa->CurrentTexObj[0] = NULL;
    mmesa->CurrentTexObj[1] = NULL;
 
-   make_empty_list( &mmesa->SwappedOut );
+   (void) memset( mmesa->texture_heaps, 0, sizeof( mmesa->texture_heaps ) );
+   make_empty_list( &mmesa->swapped );
 
    mmesa->firstTexHeap = mach64Screen->firstTexHeap;
    mmesa->lastTexHeap = mach64Screen->firstTexHeap + mach64Screen->numTexHeaps;
 
    for ( i = mmesa->firstTexHeap ; i < mmesa->lastTexHeap ; i++ ) {
-      make_empty_list( &mmesa->TexObjList[i] );
-      mmesa->texHeap[i] = mmInit( 0, mach64Screen->texSize[i] );
-      mmesa->lastTexAge[i] = -1;
+      mmesa->texture_heaps[i] = driCreateTextureHeap( i, mmesa,
+           mach64Screen->texSize[i],
+           6, /* align to 64-byte boundary, use 12 for page-size boundary */
+           MACH64_NR_TEX_REGIONS,
+           (drmTextureRegionPtr)mmesa->sarea->tex_list[i],
+           &mmesa->sarea->tex_age[i],
+           &mmesa->swapped,
+           sizeof( mach64TexObj ),
+           (destroy_texture_object_t *) mach64DestroyTexObj );
+
+#if ENABLE_PERF_BOXES
+      c_textureSwapsPtr = & mmesa->c_textureSwaps;
+#endif
+      driSetTextureSwapCounterLocation( mmesa->texture_heaps[i],
+                                       c_textureSwapsPtr );
    }
 
    mmesa->RenderIndex = -1;            /* Impossible value */
@@ -176,17 +190,25 @@ GLboolean mach64CreateContext( const __GLcontextModes *glVisual,
     * Test for 2 textures * bytes/texel * size * size.  There's no
     * need to account for mipmaps since we only upload one level.
     */
-   heap = mach64Screen->IsPCI ? MACH64_CARD_HEAP : MACH64_AGP_HEAP;
-
-   if ( mach64Screen->texSize[heap] >= 2 * mach64Screen->cpp * 1024*1024 ) {
-      ctx->Const.MaxTextureLevels = 11; /* 1024x1024 */
-   } else if ( mach64Screen->texSize[heap] >= 2 * mach64Screen->cpp * 512*512 ) {
-      ctx->Const.MaxTextureLevels = 10; /* 512x512 */
-   } else {
-      ctx->Const.MaxTextureLevels = 9;  /* 256x256 */
-   }
 
    ctx->Const.MaxTextureUnits = 2;
+   ctx->Const.MaxTextureImageUnits = 2;
+   ctx->Const.MaxTextureCoordUnits = 2;
+
+   heap = mach64Screen->IsPCI ? MACH64_CARD_HEAP : MACH64_AGP_HEAP;
+
+   driCalculateMaxTextureLevels( & mmesa->texture_heaps[heap],
+                                1,
+                                & ctx->Const,
+                                mach64Screen->cpp,
+                                10, /* max 2D texture size is 1024x1024 */
+                                0,  /* 3D textures unsupported. */
+                                0,  /* cube textures unsupported. */
+                                0,  /* texture rectangles unsupported. */
+                                1,  /* mipmapping unsupported. */
+                                GL_TRUE, /* need to have both textures in
+                                            either local or AGP memory */
+                                0 );
 
 #if ENABLE_PERF_BOXES
    mmesa->boxes = ( getenv( "LIBGL_PERFORMANCE_BOXES" ) != NULL );
@@ -250,31 +272,29 @@ void mach64DestroyContext( __DRIcontextPrivate *driContextPriv  )
 
    assert(mmesa);  /* should never be null */
    if ( mmesa ) {
-      if (mmesa->glCtx->Shared->RefCount == 1) {
+      GLboolean   release_texture_heaps;
+
+      release_texture_heaps = (mmesa->glCtx->Shared->RefCount == 1);
+
+      _swsetup_DestroyContext( mmesa->glCtx );
+      _tnl_DestroyContext( mmesa->glCtx );
+      _ac_DestroyContext( mmesa->glCtx );
+      _swrast_DestroyContext( mmesa->glCtx );
+
+      if (release_texture_heaps) {
          /* This share group is about to go away, free our private
           * texture object data.
           */
-         mach64TexObjPtr t, next_t;
          int i;
 
          for ( i = mmesa->firstTexHeap ; i < mmesa->lastTexHeap ; i++ ) {
-            foreach_s ( t, next_t, &mmesa->TexObjList[i] ) {
-               mach64DestroyTexObj( mmesa, t );
-            }
-            mmDestroy( mmesa->texHeap[i] );
-            mmesa->texHeap[i] = NULL;
+           driDestroyTextureHeap( mmesa->texture_heaps[i] );
+           mmesa->texture_heaps[i] = NULL;
          }
 
-         foreach_s ( t, next_t, &mmesa->SwappedOut ) {
-            mach64DestroyTexObj( mmesa, t );
-         }
+        assert( is_empty_list( & mmesa->swapped ) );
       }
 
-      _swsetup_DestroyContext( mmesa->glCtx );
-      _tnl_DestroyContext( mmesa->glCtx );
-      _ac_DestroyContext( mmesa->glCtx );
-      _swrast_DestroyContext( mmesa->glCtx );
-
       mach64FreeVB( mmesa->glCtx );
 
       /* Free the vertex buffer */
index e718b96c18813cbfe6140e3e54ca766322493526..8d89452412bb3f76b6f44492f988db078d772ed3 100644 (file)
@@ -134,46 +134,17 @@ typedef void (*mach64_line_func)( mach64ContextPtr,
 typedef void (*mach64_point_func)( mach64ContextPtr,
                                     mach64Vertex * );
 
-#ifdef TEXMEM
 struct mach64_texture_object {
    driTextureObject   base;
 
-   GLuint offset;
+   GLuint bufAddr;
 
-   GLuint dirty;
-   GLuint age;
+   GLint heap; /* same as base.heap->heapId */
 
-   GLint widthLog2;
-   GLint heightLog2;
-   GLint maxLog2;
-
-   GLint hasAlpha;
-   GLint textureFormat;
-
-   /* Have to keep these separate due to how they are programmed.
-    * FIXME: Why don't we just use the tObj values?
+   /* For communicating values from mach64AllocTexObj(), mach64SetTexImages()
+    * to mach64UpdateTextureUnit(). Alternately, we can use the tObj values or
+    * set the context registers directly.
     */
-   GLboolean BilinearMin;
-   GLboolean BilinearMag;
-   GLboolean ClampS;
-   GLboolean ClampT;
-};
-#else
-struct mach64_texture_object {
-   struct mach64_texture_object *next;
-   struct mach64_texture_object *prev;
-   struct gl_texture_object *tObj;
-
-   struct mem_block *memBlock;
-   GLuint offset;
-   GLuint size;
-
-   GLuint dirty;
-   GLuint age;
-
-   GLint bound;
-   GLint heap;
-
    GLint widthLog2;
    GLint heightLog2;
    GLint maxLog2;
@@ -181,19 +152,14 @@ struct mach64_texture_object {
    GLint hasAlpha;
    GLint textureFormat;
 
-   /* Have to keep these separate due to how they are programmed.
-    * FIXME: Why don't we just use the tObj values?
-    */
    GLboolean BilinearMin;
    GLboolean BilinearMag;
    GLboolean ClampS;
    GLboolean ClampT;
 };
-#endif
 
 typedef struct mach64_texture_object mach64TexObj, *mach64TexObjPtr;
 
-
 struct mach64_context {
    GLcontext *glCtx;
 
@@ -229,17 +195,10 @@ struct mach64_context {
    /* Texture object bookkeeping
     */
    mach64TexObjPtr CurrentTexObj[2];
-#ifdef TEXMEM
-   unsigned nr_heaps;
-   driTexHeap * texture_heaps[ R128_NR_TEX_HEAPS ];
-   driTextureObject swapped;
-#else
-   mach64TexObj TexObjList[MACH64_NR_TEX_HEAPS];
-   mach64TexObj SwappedOut;
-   struct mem_block *texHeap[MACH64_NR_TEX_HEAPS];
-   GLuint lastTexAge[MACH64_NR_TEX_HEAPS];
+
    GLint firstTexHeap, lastTexHeap;
-#endif
+   driTexHeap *texture_heaps[MACH64_NR_TEX_HEAPS];
+   driTextureObject swapped;
 
    /* Fallback rasterization functions
     */
index 26f66f0230961047f042f8c7c72fe23c3b610494..b73e350111fc2fb82a25bae7a9329ff2d52109f0 100644 (file)
@@ -91,8 +91,6 @@ void mach64GetLock( mach64ContextPtr mmesa, GLuint flags )
    }
 
    for ( i = mmesa->firstTexHeap ; i < mmesa->lastTexHeap ; i++ ) {
-      if ( mmesa->texHeap[i] && (sarea->tex_age[i] != mmesa->lastTexAge[i]) ) {
-        mach64AgeTextures( mmesa, i );
-      }
+      DRI_AGE_TEXTURES( mmesa->texture_heaps[i] );
    }
 }
index b17de01acc54b48a5eece88a6bf8119b1d63fe73..1014b8acd525fc1442a3779da9d7f9a42049b524 100644 (file)
@@ -305,7 +305,7 @@ mach64CreateScreen( __DRIscreenPrivate *sPriv )
       mach64Screen->texSize[MACH64_AGP_HEAP] = 0;
       mach64Screen->logTexGranularity[MACH64_AGP_HEAP] = 0;
    } else {
-      if (mach64Screen->texSize[MACH64_CARD_HEAP] > 0) {
+      if (serverInfo->textureSize > 0) {
         mach64Screen->numTexHeaps = MACH64_NR_TEX_HEAPS;
         mach64Screen->firstTexHeap = MACH64_CARD_HEAP;
       } else {
index 6459deef7841ce23f4cf8d97667afd26708e5657..5288d321ceddc49ea8c8f73c5a0fdfadf5d67738 100644 (file)
@@ -116,21 +116,20 @@ mach64AllocTexObj( struct gl_texture_object *texObj )
       fprintf( stderr, "%s( %p )\n", __FUNCTION__, texObj );
 
    t = (mach64TexObjPtr) CALLOC_STRUCT( mach64_texture_object );
+   texObj->DriverData = t;
    if ( !t )
       return NULL;
 
    /* Initialize non-image-dependent parts of the state:
     */
-   t->tObj = texObj;
+   t->base.tObj = texObj;
+   t->base.dirty_images[0] = (1 << 0);
 
-   t->offset = 0;
+   t->bufAddr = 0;
 
-   t->dirty = 1;
-
-   make_empty_list( t );
+   make_empty_list( (driTextureObject *) t );
 
    mach64SetTexWrap( t, texObj->WrapS, texObj->WrapT );
-   /*mach64SetTexMaxAnisotropy( t, texObj->MaxAnisotropy );*/
    mach64SetTexFilter( t, texObj->MinFilter, texObj->MagFilter );
    mach64SetTexBorderColor( t, texObj->_BorderChan );
 
@@ -251,18 +250,17 @@ static void mach64TexImage1D( GLcontext *ctx, GLenum target, GLint level,
                            struct gl_texture_image *texImage )
 {
    mach64ContextPtr mmesa = MACH64_CONTEXT(ctx);
-   mach64TexObjPtr t = (mach64TexObjPtr) texObj->DriverData;
+   driTextureObject * t = (driTextureObject *) texObj->DriverData;
 
    if ( t ) {
-      mach64SwapOutTexObj( mmesa, t );
+      driSwapOutTextureObject( t );
    }
    else {
-      t = mach64AllocTexObj(texObj);
+      t = (driTextureObject *) mach64AllocTexObj(texObj);
       if (!t) {
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
          return;
       }
-      texObj->DriverData = t;
    }
 
    /* Note, this will call mach64ChooseTextureFormat */
@@ -285,19 +283,18 @@ static void mach64TexSubImage1D( GLcontext *ctx,
                                 struct gl_texture_image *texImage )
 {
    mach64ContextPtr mmesa = MACH64_CONTEXT(ctx);
-   mach64TexObjPtr t = (mach64TexObjPtr) texObj->DriverData;
+   driTextureObject * t = (driTextureObject *) texObj->DriverData;
 
    assert( t ); /* this _should_ be true */
    if ( t ) {
-      mach64SwapOutTexObj( mmesa, t );
+      driSwapOutTextureObject( t );
    }
    else {
-      t = mach64AllocTexObj(texObj);
+      t = (driTextureObject *) mach64AllocTexObj(texObj);
       if (!t) {
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
          return;
       }
-      texObj->DriverData = t;
    }
 
    _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
@@ -316,18 +313,17 @@ static void mach64TexImage2D( GLcontext *ctx, GLenum target, GLint level,
                              struct gl_texture_image *texImage )
 {
    mach64ContextPtr mmesa = MACH64_CONTEXT(ctx);
-   mach64TexObjPtr t = (mach64TexObjPtr) texObj->DriverData;
+   driTextureObject * t = (driTextureObject *) texObj->DriverData;
 
    if ( t ) {
-      mach64SwapOutTexObj( mmesa, t );
+      driSwapOutTextureObject( t );
    }
    else {
-      t = mach64AllocTexObj(texObj);
+      t = (driTextureObject *) mach64AllocTexObj(texObj);
       if (!t) {
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
          return;
       }
-      texObj->DriverData = t;
    }
 
    /* Note, this will call mach64ChooseTextureFormat */
@@ -350,19 +346,18 @@ static void mach64TexSubImage2D( GLcontext *ctx,
                                 struct gl_texture_image *texImage )
 {
    mach64ContextPtr mmesa = MACH64_CONTEXT(ctx);
-   mach64TexObjPtr t = (mach64TexObjPtr) texObj->DriverData;
+   driTextureObject * t = (driTextureObject *) texObj->DriverData;
 
    assert( t ); /* this _should_ be true */
    if ( t ) {
-      mach64SwapOutTexObj( mmesa, t );
+      driSwapOutTextureObject( t );
    }
    else {
-      t = mach64AllocTexObj(texObj);
+      t = (driTextureObject *) mach64AllocTexObj(texObj);
       if (!t) {
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
          return;
       }
-      texObj->DriverData = t;
    }
 
    _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
@@ -372,44 +367,6 @@ static void mach64TexSubImage2D( GLcontext *ctx,
    mmesa->new_state |= MACH64_NEW_TEXTURE;
 }
 
-/* Due to the way we must program texture state into the Rage Pro,
- * we must leave these calculations to the absolute last minute.
- */
-void mach64EmitTexStateLocked( mach64ContextPtr mmesa,
-                              mach64TexObjPtr t0,
-                              mach64TexObjPtr t1 )
-{
-   drm_mach64_sarea_t *sarea = mmesa->sarea;
-   drm_mach64_context_regs_t *regs = &(mmesa->setup);
-
-   /* for multitex, both textures must be local or AGP */
-   if ( t0 && t1 )
-      assert(t0->heap == t1->heap);
-
-   if ( t0 ) {
-      if (t0->heap == MACH64_CARD_HEAP) {
-#if ENABLE_PERF_BOXES
-        mmesa->c_texsrc_card++;
-#endif
-        mmesa->setup.tex_cntl &= ~MACH64_TEX_SRC_AGP;
-      } else {
-#if ENABLE_PERF_BOXES
-        mmesa->c_texsrc_agp++;
-#endif
-        mmesa->setup.tex_cntl |= MACH64_TEX_SRC_AGP;
-      }
-      mmesa->setup.tex_offset = t0->offset;
-   }
-
-   if ( t1 ) {
-      mmesa->setup.secondary_tex_off = t1->offset;
-   }
-
-   memcpy( &sarea->context_state.tex_size_pitch, &regs->tex_size_pitch,
-          MACH64_NR_TEXTURE_REGS * sizeof(GLuint) );
-}
-
-
 /* ================================================================
  * Device Driver API texture functions
  */
@@ -491,24 +448,23 @@ static void mach64DDTexParameter( GLcontext *ctx, GLenum target,
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexParameter");
          return;
       }
-      tObj->DriverData = t;
    }
 
    switch ( pname ) {
    case GL_TEXTURE_MIN_FILTER:
    case GL_TEXTURE_MAG_FILTER:
-      if ( t->bound ) FLUSH_BATCH( mmesa );
+      if ( t->base.bound ) FLUSH_BATCH( mmesa );
       mach64SetTexFilter( t, tObj->MinFilter, tObj->MagFilter );
       break;
 
    case GL_TEXTURE_WRAP_S:
    case GL_TEXTURE_WRAP_T:
-      if ( t->bound ) FLUSH_BATCH( mmesa );
+      if ( t->base.bound ) FLUSH_BATCH( mmesa );
       mach64SetTexWrap( t, tObj->WrapS, tObj->WrapT );
       break;
 
    case GL_TEXTURE_BORDER_COLOR:
-      if ( t->bound ) FLUSH_BATCH( mmesa );
+      if ( t->base.bound ) FLUSH_BATCH( mmesa );
       mach64SetTexBorderColor( t, tObj->_BorderChan );
       break;
 
@@ -522,8 +478,8 @@ static void mach64DDTexParameter( GLcontext *ctx, GLenum target,
        * For mach64 we're only concerned with the base level
        * since that's the only texture we upload.
        */
-      if ( t->bound ) FLUSH_BATCH( mmesa );
-      mach64SwapOutTexObj( mmesa, t );
+      if ( t->base.bound ) FLUSH_BATCH( mmesa );
+      driSwapOutTextureObject( (driTextureObject *) t );
       break;
 
    default:
@@ -547,7 +503,7 @@ static void mach64DDBindTexture( GLcontext *ctx, GLenum target,
    FLUSH_BATCH( mmesa );
 
    if ( mmesa->CurrentTexObj[unit] ) {
-      mmesa->CurrentTexObj[unit]->bound &= ~(unit+1);
+      mmesa->CurrentTexObj[unit]->base.bound &= ~(1 << unit);
       mmesa->CurrentTexObj[unit] = NULL;
    }
 
@@ -558,33 +514,37 @@ static void mach64DDDeleteTexture( GLcontext *ctx,
                                   struct gl_texture_object *tObj )
 {
    mach64ContextPtr mmesa = MACH64_CONTEXT(ctx);
-   mach64TexObjPtr t = (mach64TexObjPtr)tObj->DriverData;
+   driTextureObject * t = (driTextureObject *) tObj->DriverData;
 
    if ( t ) {
       if ( t->bound && mmesa ) {
         FLUSH_BATCH( mmesa );
 
-        mmesa->CurrentTexObj[t->bound-1] = 0;
         mmesa->new_state |= MACH64_NEW_TEXTURE;
       }
 
-      mach64DestroyTexObj( mmesa, t );
-      tObj->DriverData = NULL;
+      driDestroyTextureObject( t );
+
       /* Free mipmap images and the texture object itself */
       _mesa_delete_texture_object(ctx, tObj);
-
    }
 }
 
-static GLboolean mach64DDIsTextureResident( GLcontext *ctx,
-                                           struct gl_texture_object *tObj )
+/**
+ * Allocate a new texture object.
+ * Called via ctx->Driver.NewTextureObject.
+ * Note: we could use containment here to 'derive' the driver-specific
+ * texture object from the core mesa gl_texture_object.  Not done at this time.
+ */
+static struct gl_texture_object *
+mach64NewTextureObject( GLcontext *ctx, GLuint name, GLenum target )
 {
-   mach64TexObjPtr t = (mach64TexObjPtr)tObj->DriverData;
-
-   return ( t && t->memBlock );
+   struct gl_texture_object *obj;
+   obj = _mesa_new_texture_object(ctx, name, target);
+   mach64AllocTexObj( obj );
+   return obj;
 }
 
-
 void mach64InitTextureFuncs( struct dd_function_table *functions )
 {
    functions->TexEnv                   = mach64DDTexEnv;
@@ -593,18 +553,15 @@ void mach64InitTextureFuncs( struct dd_function_table *functions )
    functions->TexSubImage1D            = mach64TexSubImage1D;
    functions->TexImage2D               = mach64TexImage2D;
    functions->TexSubImage2D            = mach64TexSubImage2D;
-   functions->TexImage3D               = _mesa_store_teximage3d;
-   functions->TexSubImage3D            = _mesa_store_texsubimage3d;
-   functions->CopyTexImage1D           = _swrast_copy_teximage1d;
-   functions->CopyTexImage2D           = _swrast_copy_teximage2d;
-   functions->CopyTexSubImage1D        = _swrast_copy_texsubimage1d;
-   functions->CopyTexSubImage2D        = _swrast_copy_texsubimage2d;
-   functions->CopyTexSubImage3D        = _swrast_copy_texsubimage3d;
    functions->TexParameter             = mach64DDTexParameter;
    functions->BindTexture              = mach64DDBindTexture;
+   functions->NewTextureObject         = mach64NewTextureObject;
    functions->DeleteTexture            = mach64DDDeleteTexture;
+   functions->IsTextureResident                = driIsTextureResident;
+
    functions->UpdateTexturePalette     = NULL;
    functions->ActiveTexture            = NULL;
-   functions->IsTextureResident        = mach64DDIsTextureResident;
-   functions->PrioritizeTexture        = NULL;
+   functions->PrioritizeTexture                = NULL;
+
+   driInitTextureFormats();
 }
index d950dd12b447b26e1ddbc581c6fdb380da9995db..f6cf1cf80208401da6c7e9c7c50a152b0852fd92 100644 (file)
 
 extern void mach64UpdateTextureState( GLcontext *ctx );
 
-extern void mach64SwapOutTexObj( mach64ContextPtr mach64ctx,
-                                mach64TexObjPtr t );
-
 extern void mach64UploadTexImages( mach64ContextPtr mach64ctx,
                                   mach64TexObjPtr t );
 
 extern void mach64UploadMultiTexImages( mach64ContextPtr mach64ctx,
                                        mach64TexObjPtr t0, mach64TexObjPtr t1 );
 
-extern void mach64AgeTextures( mach64ContextPtr mach64ctx, int heap );
 extern void mach64DestroyTexObj( mach64ContextPtr mach64ctx,
                                 mach64TexObjPtr t );
 
-extern void mach64UpdateTexLRU( mach64ContextPtr mach64ctx,
-                               mach64TexObjPtr t );
-
-extern void mach64PrintLocalLRU( mach64ContextPtr mach64ctx, int heap );
-extern void mach64PrintGlobalLRU( mach64ContextPtr mach64ctx, int heap );
-
 extern void mach64EmitTexStateLocked( mach64ContextPtr mmesa,
                                      mach64TexObjPtr t0,
                                      mach64TexObjPtr t1 );
index 017fd3535d566fcf42ed43a68cdb884571475ed2..3b7b93b98425c4e4e3b7c68ee01a34f77066e3ca 100644 (file)
  */
 void mach64DestroyTexObj( mach64ContextPtr mmesa, mach64TexObjPtr t )
 {
-#if ENABLE_PERF_BOXES
-   /* Bump the performace counter */
-   if (mmesa)
-      mmesa->c_textureSwaps++;
-#endif
-   if ( !t ) return;
-
-#if 0
-   if ( t->tObj && t->memBlock && mmesa ) {
-      /* not a placeholder, so release from global LRU if necessary */
-      int heap = t->heap;
-      drmTextureRegion *list = mmesa->sarea->tex_list[heap];
-      int log2sz = mmesa->mach64Screen->logTexGranularity[heap];
-      int start = t->memBlock->ofs >> log2sz;
-      int end = (t->memBlock->ofs + t->memBlock->size - 1) >> log2sz;
-      int i;
-
-      mmesa->lastTexAge[heap] = ++mmesa->sarea->tex_age[heap];
-
-      /* Update the global LRU */
-      for ( i = start ; i <= end ; i++ ) {
-        /* do we own this block? */
-        if (list[i].in_use == mmesa->hHWContext) {
-           list[i].in_use = 0;
-           list[i].age = mmesa->lastTexAge[heap];
-
-           /* remove_from_list(i) */
-           list[(GLuint)list[i].next].prev = list[i].prev;
-           list[(GLuint)list[i].prev].next = list[i].next;
-        }
-      }
-   }
-#endif
-
-   if ( t->memBlock ) {
-      mmFreeMem( t->memBlock );
-      t->memBlock = NULL;
-   }
-
-   if ( t->tObj ) {
-      t->tObj->DriverData = NULL;
-   }
-
-   if ( t->bound && mmesa )
-      mmesa->CurrentTexObj[t->bound-1] = NULL;
-
-   remove_from_list( t );
-   FREE( t );
-}
-
-/* Keep track of swapped out texture objects.
- */
-void mach64SwapOutTexObj( mach64ContextPtr mmesa,
-                         mach64TexObjPtr t )
-{
-#if ENABLE_PERF_BOXES
-   /* Bump the performace counter */
-   if (mmesa)
-     mmesa->c_textureSwaps++;
-#endif
-
-#if 0
-   if ( t->tObj && t->memBlock && mmesa ) {
-      /* not a placeholder, so release from global LRU if necessary */
-      int heap = t->heap;
-      drmTextureRegion *list = mmesa->sarea->tex_list[heap];
-      int log2sz = mmesa->mach64Screen->logTexGranularity[heap];
-      int start = t->memBlock->ofs >> log2sz;
-      int end = (t->memBlock->ofs + t->memBlock->size - 1) >> log2sz;
-      int i;
-
-      mmesa->lastTexAge[heap] = ++mmesa->sarea->tex_age[heap];
-
-      /* Update the global LRU */
-      for ( i = start ; i <= end ; i++ ) {
-        /* do we own this block? */
-        if (list[i].in_use == mmesa->hHWContext) {
-           list[i].in_use = 0;
-           list[i].age = mmesa->lastTexAge[heap];
-
-           /* remove_from_list(i) */
-           list[(GLuint)list[i].next].prev = list[i].prev;
-           list[(GLuint)list[i].prev].next = list[i].next;
-        }
-      }
-   }
-#endif
-
-   if ( t->memBlock ) {
-      mmFreeMem( t->memBlock );
-      t->memBlock = NULL;
-   }
-
-   t->dirty = ~0;
-   move_to_tail( &mmesa->SwappedOut, t );
-}
-
-/* Print out debugging information about texture LRU.
- */
-void mach64PrintLocalLRU( mach64ContextPtr mmesa, int heap )
-{
-   mach64TexObjPtr t;
-   int sz = 1 << (mmesa->mach64Screen->logTexGranularity[heap]);
-
-   fprintf( stderr, "\nLocal LRU, heap %d:\n", heap );
-
-   foreach( t, &mmesa->TexObjList[heap] ) {
-      if ( !t->tObj ) {
-        fprintf( stderr, "Placeholder %d at 0x%x sz 0x%x\n",
-                 t->memBlock->ofs / sz,
-                 t->memBlock->ofs,
-                 t->memBlock->size );
-      } else {
-        fprintf( stderr, "Texture (bound %d) at 0x%x sz 0x%x\n",
-                 t->bound,
-                 t->memBlock->ofs,
-                 t->memBlock->size );
-      }
-   }
-
-   fprintf( stderr, "\n" );
-}
-
-void mach64PrintGlobalLRU( mach64ContextPtr mmesa, int heap )
-{
-   drm_tex_region_t *list = mmesa->sarea->tex_list[heap];
-   int i, j;
-
-   fprintf( stderr, "\nGlobal LRU, heap %d list %p:\n", heap, list );
-
-   for ( i = 0, j = MACH64_NR_TEX_REGIONS ; i < MACH64_NR_TEX_REGIONS ; i++ ) {
-      fprintf( stderr, "list[%d] age %d in_use %d next %d prev %d\n",
-              j, list[j].age, list[j].in_use, list[j].next, list[j].prev );
-      j = list[j].next;
-      if ( j == MACH64_NR_TEX_REGIONS ) break;
-   }
-
-   if ( j != MACH64_NR_TEX_REGIONS ) {
-      fprintf( stderr, "Loop detected in global LRU\n" );
-      for ( i = 0 ; i < MACH64_NR_TEX_REGIONS ; i++ ) {
-        fprintf( stderr, "list[%d] age %d in_use %d next %d prev %d\n",
-                 i, list[i].age, list[i].in_use, list[i].next, list[i].prev );
-      }
-   }
+   unsigned   i;
 
-   fprintf( stderr, "\n" );
-}
-
-/* Reset the global texture LRU.
- */
-/* NOTE: This function is only called while holding the hardware lock */
-static void mach64ResetGlobalLRU( mach64ContextPtr mmesa, int heap )
-{
-   drm_tex_region_t *list = mmesa->sarea->tex_list[heap];
-   int sz = 1 << mmesa->mach64Screen->logTexGranularity[heap];
-   int i;
-
-   /* (Re)initialize the global circular LRU list.  The last element in
-    * the array (MACH64_NR_TEX_REGIONS) is the sentinal.  Keeping it at
-    * the end of the array allows it to be addressed rationally when
-    * looking up objects at a particular location in texture memory.
+   /* See if it was the driver's current object.
     */
-   for ( i = 0 ; (i+1) * sz <= mmesa->mach64Screen->texSize[heap] ; i++ ) {
-      list[i].prev = i-1;
-      list[i].next = i+1;
-      list[i].age = 0;
-      list[i].in_use = 0;
-   }
-
-   i--;
-   list[0].prev = MACH64_NR_TEX_REGIONS;
-   list[i].prev = i-1;
-   list[i].next = MACH64_NR_TEX_REGIONS;
-   list[MACH64_NR_TEX_REGIONS].prev = i;
-   list[MACH64_NR_TEX_REGIONS].next = 0;
-   mmesa->sarea->tex_age[heap] = 0;
-}
-
-/* Update the local and global texture LRUs.
- */
-/* NOTE: This function is only called while holding the hardware lock */
-void mach64UpdateTexLRU( mach64ContextPtr mmesa,
-                        mach64TexObjPtr t )
-{
-   int heap = t->heap;
-   drm_tex_region_t *list = mmesa->sarea->tex_list[heap];
-   int log2sz = mmesa->mach64Screen->logTexGranularity[heap];
-   int start = t->memBlock->ofs >> log2sz;
-   int end = (t->memBlock->ofs + t->memBlock->size - 1) >> log2sz;
-   int i;
-
-   mmesa->lastTexAge[heap] = ++mmesa->sarea->tex_age[heap];
-
-   if ( !t->memBlock ) {
-      fprintf( stderr, "no memblock\n\n" );
-      return;
-   }
-
-   /* Update our local LRU */
-   move_to_head( &mmesa->TexObjList[heap], t );
-
-   /* Update the global LRU */
-   for ( i = start ; i <= end ; i++ ) {
-      list[i].in_use = mmesa->hHWContext;
-      list[i].age = mmesa->lastTexAge[heap];
-
-#if 0
-      /* if this is the last region, it's not in the list */
-      if ( !(i*(1<<log2sz) > mmesa->mach64Screen->texSize[heap] ) ) {
-#endif
-        /* remove_from_list(i) */
-        list[(GLuint)list[i].next].prev = list[i].prev;
-        list[(GLuint)list[i].prev].next = list[i].next;
-#if 0
-      }
-#endif
-
-      /* insert_at_head(list, i) */
-      list[i].prev = MACH64_NR_TEX_REGIONS;
-      list[i].next = list[MACH64_NR_TEX_REGIONS].next;
-      list[(GLuint)list[MACH64_NR_TEX_REGIONS].next].prev = i;
-      list[MACH64_NR_TEX_REGIONS].next = i;
-   }
-
-   if ( MACH64_DEBUG & DEBUG_VERBOSE_LRU ) {
-      mach64PrintGlobalLRU( mmesa, t->heap );
-      mach64PrintLocalLRU( mmesa, t->heap );
-   }
-}
-
-/* Update our notion of what textures have been changed since we last
- * held the lock.  This pertains to both our local textures and the
- * textures belonging to other clients.  Keep track of other client's
- * textures by pushing a placeholder texture onto the LRU list -- these
- * are denoted by (tObj == NULL).
- */
-/* NOTE: This function is only called while holding the hardware lock */
-static void mach64TexturesGone( mach64ContextPtr mmesa, int heap,
-                               int offset, int size, int in_use )
-{
-   mach64TexObjPtr t, tmp;
-
-   foreach_s ( t, tmp, &mmesa->TexObjList[heap] ) {
-      if ( t->memBlock->ofs >= offset + size ||
-          t->memBlock->ofs + t->memBlock->size <= offset )
-        continue;
-
-      /* It overlaps - kick it out.  Need to hold onto the currently
-       * bound objects, however.
-       */
-      if ( t->bound ) {
-        mach64SwapOutTexObj( mmesa, t );
-      } else {
-        mach64DestroyTexObj( mmesa, t );
-      }
-   }
-
-   if ( in_use > 0 && in_use != mmesa->hHWContext ) {
-      t = (mach64TexObjPtr) CALLOC( sizeof(*t) );
-      if (!t) return;
-
-      t->memBlock = mmAllocMem( mmesa->texHeap[heap], size, 0, offset );
-      if ( !t->memBlock ) {
-        fprintf( stderr, "Couldn't alloc placeholder sz %x ofs %x\n",
-                 (int)size, (int)offset );
-        mmDumpMemInfo( mmesa->texHeap[heap] );
-        return;
-      }
-      insert_at_head( &mmesa->TexObjList[heap], t );
-   }
-}
-
-/* Update our client's shared texture state.  If another client has
- * modified a region in which we have textures, then we need to figure
- * out which of our textures has been removed, and update our global
- * LRU.
- */
-void mach64AgeTextures( mach64ContextPtr mmesa, int heap )
-{
-   drm_mach64_sarea_t *sarea = mmesa->sarea;
-
-   if ( sarea->tex_age[heap] != mmesa->lastTexAge[heap] ) {
-      int sz = 1 << mmesa->mach64Screen->logTexGranularity[heap];
-      int nr = 0;
-      int idx;
-
-      /* Have to go right round from the back to ensure stuff ends up
-       * LRU in our local list...  Fix with a cursor pointer.
-       */
-      for ( idx = sarea->tex_list[heap][MACH64_NR_TEX_REGIONS].prev ;
-           idx != MACH64_NR_TEX_REGIONS && nr < MACH64_NR_TEX_REGIONS ;
-           idx = sarea->tex_list[heap][idx].prev, nr++ )
+   if ( mmesa != NULL )
+   {
+      for ( i = 0 ; i < mmesa->glCtx->Const.MaxTextureUnits ; i++ )
       {
-        /* If switching texturing schemes, then the SAREA might not
-         * have been properly cleared, so we need to reset the
-         * global texture LRU.
-         */
-        if ( idx * sz > mmesa->mach64Screen->texSize[heap] ) {
-           nr = MACH64_NR_TEX_REGIONS;
-           break;
-        }
-
-        if ( sarea->tex_list[heap][idx].age > mmesa->lastTexAge[heap] ) {
-           mach64TexturesGone( mmesa, heap, idx * sz, sz,
-                               sarea->tex_list[heap][idx].in_use );
-        }
-      }
-
-      /* If switching texturing schemes, then the SAREA might not
-       * have been properly cleared, so we need to reset the
-       * global texture LRU.
-       */
-      if ( nr == MACH64_NR_TEX_REGIONS ) {
-        mach64TexturesGone( mmesa, heap, 0,
-                            mmesa->mach64Screen->texSize[heap], 0 );
-        mach64ResetGlobalLRU( mmesa, heap );
+         if ( t == mmesa->CurrentTexObj[ i ] ) {
+            assert( t->base.bound & (1 << i) );
+            mmesa->CurrentTexObj[ i ] = NULL;
+         }
       }
-
-      if ( 0 ) {
-        mach64PrintGlobalLRU( mmesa, heap );
-        mach64PrintLocalLRU( mmesa, heap );
-      }
-
-      mmesa->dirty |= (MACH64_UPLOAD_CONTEXT |
-                      MACH64_UPLOAD_TEX0IMAGE |
-                      MACH64_UPLOAD_TEX1IMAGE);
-      mmesa->lastTexAge[heap] = sarea->tex_age[heap];
    }
 }
 
@@ -395,7 +81,7 @@ static void mach64UploadAGPSubImage( mach64ContextPtr mmesa,
    if ( ( level < 0 ) || ( level > mmesa->glCtx->Const.MaxTextureLevels ) )
      return;
 
-   image = t->tObj->Image[0][level];
+   image = t->base.tObj->Image[0][level];
    if ( !image )
       return;
 
@@ -424,14 +110,13 @@ static void mach64UploadAGPSubImage( mach64ContextPtr mmesa,
       fprintf( stderr, "mach64UploadSubImage: %d,%d of %d,%d at %d,%d\n",
               width, height, image->Width, image->Height, x, y );
       fprintf( stderr, "            blit ofs: 0x%07x pitch: 0x%x dwords: %d\n",
-              (GLuint)t->offset, (GLint)width, dwords );
-      mmDumpMemInfo( mmesa->texHeap[t->heap] );
+              (GLuint)t->bufAddr, (GLint)width, dwords );
    }
 
    assert(image->Data);
 
    {
-      CARD32 *dst = (CARD32 *)((char *)mach64Screen->agpTextures.map + t->memBlock->ofs);
+      CARD32 *dst = (CARD32 *)((char *)mach64Screen->agpTextures.map + t->base.memBlock->ofs);
       const GLubyte *src = (const GLubyte *) image->Data +
         (y * image->Width + x) * image->TexFormat->TexelBytes;
       const GLuint bytes = width * height * image->TexFormat->TexelBytes;
@@ -460,7 +145,7 @@ static void mach64UploadLocalSubImage( mach64ContextPtr mmesa,
    if ( ( level < 0 ) || ( level > mmesa->glCtx->Const.MaxTextureLevels ) )
       return;
 
-   image = t->tObj->Image[0][level];
+   image = t->base.tObj->Image[0][level];
    if ( !image )
       return;
 
@@ -543,7 +228,7 @@ static void mach64UploadLocalSubImage( mach64ContextPtr mmesa,
    }
 
    dwords = width * height / texelsPerDword;
-   offset = t->offset;
+   offset = t->bufAddr;
 
 #if ENABLE_PERF_BOXES
    /* Bump the performance counter */
@@ -555,7 +240,6 @@ static void mach64UploadLocalSubImage( mach64ContextPtr mmesa,
               width, height, image->Width, image->Height, x, y );
       fprintf( stderr, "            blit ofs: 0x%07x pitch: 0x%x dwords: %d\n",
               (GLuint)offset, (GLint)width, dwords );
-      mmDumpMemInfo( mmesa->texHeap[t->heap] );
    }
 
    /* Subdivide the texture if required (account for the registers added by the drm) */
@@ -594,78 +278,32 @@ static void mach64UploadLocalSubImage( mach64ContextPtr mmesa,
  */
 void mach64UploadTexImages( mach64ContextPtr mmesa, mach64TexObjPtr t )
 {
-   GLint heap;
-
    if ( MACH64_DEBUG & DEBUG_VERBOSE_API ) {
       fprintf( stderr, "%s( %p, %p )\n",
               __FUNCTION__, mmesa->glCtx, t );
    }
 
    assert(t);
-   assert(t->tObj);
-
-   /* Choose the heap appropriately */
-   heap = MACH64_CARD_HEAP;
+   assert(t->base.tObj);
 
-   if ( !mmesa->mach64Screen->IsPCI &&
-       t->size > mmesa->mach64Screen->texSize[heap] ) {
-      heap = MACH64_AGP_HEAP;
-   }
-
-   /* Do we need to eject LRU texture objects? */
-   if ( !t->memBlock ) {
-      t->heap = heap;
+   if ( !t->base.memBlock ) {
+      int heap;
 
-      /* Allocate a memory block on a 64-byte boundary */
-      t->memBlock = mmAllocMem( mmesa->texHeap[heap], t->size, 6, 0 );
+      /* NULL heaps are skipped */
+      heap = driAllocateTexture( mmesa->texture_heaps, MACH64_NR_TEX_HEAPS,
+                                (driTextureObject *) t );
 
-      /* Try AGP before kicking anything out of local mem */
-      if ( !mmesa->mach64Screen->IsPCI && !t->memBlock && heap == MACH64_CARD_HEAP ) {
-        t->memBlock = mmAllocMem( mmesa->texHeap[MACH64_AGP_HEAP],
-                                  t->size, 6, 0 );
-
-        if ( t->memBlock )
-           heap = t->heap = MACH64_AGP_HEAP;
+      if ( heap == -1 ) {
+        fprintf( stderr, "%s: upload texture failure, sz=%d\n", __FUNCTION__,
+                 t->base.totalSize );
+        exit(-1);
+        return;
       }
 
-      /* Kick out textures until the requested texture fits */
-      while ( !t->memBlock ) {
-        if ( mmesa->TexObjList[heap].prev->bound ) {
-           fprintf( stderr,
-                    "mach64UploadTexImages: ran into bound texture\n" );
-           return;
-        }
-        if ( mmesa->TexObjList[heap].prev == &mmesa->TexObjList[heap] ) {
-           if ( mmesa->mach64Screen->IsPCI ) {
-              fprintf( stderr, "%s: upload texture failure on "
-                       "local texture heaps, sz=%d\n", __FUNCTION__,
-                       t->size );
-              return;
-           } else if ( heap == MACH64_CARD_HEAP ) {
-              heap = t->heap = MACH64_AGP_HEAP;
-              continue;
-           } else {
-             int i;
-              fprintf( stderr, "%s: upload texture failure on "
-                       "%sAGP texture heaps, sz=%d\n", __FUNCTION__,
-                       mmesa->firstTexHeap == MACH64_CARD_HEAP ? "both local and " : "",
-                       t->size );
-              for ( i = mmesa->firstTexHeap ; i < mmesa->lastTexHeap ; i++ ) {
-                 mach64PrintLocalLRU( mmesa, i );
-                 mmDumpMemInfo( mmesa->texHeap[i] );
-              }
-              exit(-1);
-              return;
-           }
-        }
-
-        mach64SwapOutTexObj( mmesa, mmesa->TexObjList[heap].prev );
-
-        t->memBlock = mmAllocMem( mmesa->texHeap[heap], t->size, 6, 0 );
-      }
+      t->heap = heap;
 
       /* Set the base offset of the texture image */
-      t->offset = mmesa->mach64Screen->texOffset[heap] + t->memBlock->ofs;
+      t->bufAddr = mmesa->mach64Screen->texOffset[heap] + t->base.memBlock->ofs;
 
       /* Force loading the new state into the hardware */
       mmesa->dirty |= (MACH64_UPLOAD_SCALE_3D_CNTL |
@@ -673,142 +311,152 @@ void mach64UploadTexImages( mach64ContextPtr mmesa, mach64TexObjPtr t )
    }
 
    /* Let the world know we've used this memory recently */
-   mach64UpdateTexLRU( mmesa, t );
+   driUpdateTextureLRU( (driTextureObject *) t );
 
    /* Upload any images that are new */
-   if ( t->dirty ) {
+   if ( t->base.dirty_images[0] ) {
+      const GLint j = t->base.tObj->BaseLevel;
       if (t->heap == MACH64_AGP_HEAP) {
         /* Need to make sure any vertex buffers in the queue complete */
         mach64WaitForIdleLocked( mmesa );
-        mach64UploadAGPSubImage( mmesa, t, t->tObj->BaseLevel, 0, 0,
-                                 t->tObj->Image[0][t->tObj->BaseLevel]->Width,
-                                 t->tObj->Image[0][t->tObj->BaseLevel]->Height );
+        mach64UploadAGPSubImage( mmesa, t, j, 0, 0,
+                                 t->base.tObj->Image[0][j]->Width,
+                                 t->base.tObj->Image[0][j]->Height );
       } else {
-        mach64UploadLocalSubImage( mmesa, t, t->tObj->BaseLevel, 0, 0,
-                                   t->tObj->Image[0][t->tObj->BaseLevel]->Width,
-                                   t->tObj->Image[0][t->tObj->BaseLevel]->Height );
+        mach64UploadLocalSubImage( mmesa, t, j, 0, 0,
+                                   t->base.tObj->Image[0][j]->Width,
+                                   t->base.tObj->Image[0][j]->Height );
       }
 
       mmesa->setup.tex_cntl |= MACH64_TEX_CACHE_FLUSH;
+      t->base.dirty_images[0] = 0;
    }
 
    mmesa->dirty |= MACH64_UPLOAD_TEXTURE;
+}
+
+
+/* Allocate memory from the same texture heap `heap' for both textures
+ * `u0' and `u1'.
+ */
+static int mach64AllocateMultiTex( mach64ContextPtr mmesa,
+                                  mach64TexObjPtr u0,
+                                  mach64TexObjPtr u1,
+                                  int heap, GLboolean alloc_u0 )
+{
+   /* Both objects should be bound */
+   assert( u0->base.bound && u1->base.bound );
+
+   if ( alloc_u0 ) {
+      /* Evict u0 from its current heap */
+      if ( u0->base.memBlock ) {
+        assert( u0->heap != heap );
+        driSwapOutTextureObject( (driTextureObject *) u0 );
+      }
+
+      /* Try to allocate u0 in the chosen heap */
+      u0->heap = driAllocateTexture( &mmesa->texture_heaps[heap], 1,
+                                    (driTextureObject *) u0 );
+
+      if ( u0->heap == -1 ) {
+        return -1;
+      }
+   }
+
+   /* Evict u1 from its current heap */
+   if ( u1->base.memBlock ) {
+      assert( u1->heap != heap );
+      driSwapOutTextureObject( (driTextureObject *) u1 );
+   }
+
+   /* Try to allocate u1 in the same heap as u0 */
+   u1->heap = driAllocateTexture( &mmesa->texture_heaps[heap], 1,
+                                 (driTextureObject *) u1 );
+
+   if ( u1->heap == -1 ) {
+      return -1;
+   }
 
-   t->dirty = 0;
+   /* Bound objects are not evicted */
+   assert( u0->base.memBlock && u1->base.memBlock );
+   assert( u0->heap == u1->heap );
+
+   return heap;
 }
 
 /* The mach64 needs to have both primary and secondary textures in either
  * local or AGP memory, so we need a "buddy system" to make sure that allocation
  * succeeds or fails for both textures.
- * FIXME: This needs to be optimized better.
  */
 void mach64UploadMultiTexImages( mach64ContextPtr mmesa, 
                                 mach64TexObjPtr t0,
                                 mach64TexObjPtr t1 )
 {
-   GLint heap;
-
    if ( MACH64_DEBUG & DEBUG_VERBOSE_API ) {
       fprintf( stderr, "%s( %p, %p %p )\n",
               __FUNCTION__, mmesa->glCtx, t0, t1 );
    }
 
    assert(t0 && t1);
-   assert(t0->tObj && t1->tObj);
+   assert(t0->base.tObj && t1->base.tObj);
 
-   /* Choose the heap appropriately */
-   heap = MACH64_CARD_HEAP;
+   if ( !t0->base.memBlock || !t1->base.memBlock || t0->heap != t1->heap ) {
+      mach64TexObjPtr u0 = NULL;
+      mach64TexObjPtr u1 = NULL;
+      unsigned totalSize = t0->base.totalSize + t1->base.totalSize;
 
-   if ( !mmesa->mach64Screen->IsPCI &&
-       ((t0->size + t1->size) > mmesa->mach64Screen->texSize[heap]) ) {
-      heap = MACH64_AGP_HEAP;
-   }
+      int heap, ret;
 
-   /* Do we need to eject LRU texture objects? */
-   if ( !t0->memBlock || !t1->memBlock || t0->heap != t1->heap ) {
-      /* FIXME: starting from scratch for now to keep it simple */
-      if ( t0->memBlock ) {
-        mach64SwapOutTexObj( mmesa, t0 );
-      }
-      if ( t1->memBlock ) {
-        mach64SwapOutTexObj( mmesa, t1 );
-      }
-      t0->heap = t1->heap = heap;
-      /* Allocate a memory block on a 64-byte boundary */
-      t0->memBlock = mmAllocMem( mmesa->texHeap[heap], t0->size, 6, 0 );
-      if ( t0->memBlock ) {
-        t1->memBlock = mmAllocMem( mmesa->texHeap[heap], t1->size, 6, 0 );
-        if ( !t1->memBlock ) {
-           mmFreeMem( t0->memBlock );
-           t0->memBlock = NULL;
-        }
+      /* Check if one of the textures is already swapped in a heap and the
+       * other texture fits in that heap.
+       */
+      if ( t0->base.memBlock && totalSize <= t0->base.heap->size ) {
+        u0 = t0;
+        u1 = t1;
+      } else if ( t1->base.memBlock && totalSize <= t1->base.heap->size ) {
+        u0 = t1;
+        u1 = t0;
       }
-      /* Try AGP before kicking anything out of local mem */
-      if ( (!t0->memBlock || !t1->memBlock) && heap == MACH64_CARD_HEAP ) {
-        t0->memBlock = mmAllocMem( mmesa->texHeap[MACH64_AGP_HEAP], t0->size, 6, 0 );
-        if ( t0->memBlock ) {
-           t1->memBlock = mmAllocMem( mmesa->texHeap[MACH64_AGP_HEAP], t1->size, 6, 0 );
-           if ( !t1->memBlock ) {
-              mmFreeMem( t0->memBlock );
-              t0->memBlock = NULL;
-           }
+
+      if ( u0 ) {
+        heap = u0->heap;
+
+        ret = mach64AllocateMultiTex( mmesa, u0, u1, heap, GL_FALSE );
+      } else {
+        /* Both textures are swapped out or collocation is impossible */
+        u0 = t0;
+        u1 = t1;
+
+        /* Choose the heap appropriately */
+        heap = MACH64_CARD_HEAP;
+
+        if ( totalSize > mmesa->texture_heaps[heap]->size ) {
+           heap = MACH64_AGP_HEAP;
         }
 
-        if ( t0->memBlock && t1->memBlock )
-           heap = t0->heap = t1->heap = MACH64_AGP_HEAP;
+        ret = mach64AllocateMultiTex( mmesa, u0, u1, heap, GL_TRUE );
       }
 
-      /* Kick out textures until the requested texture fits */
-      while ( !t0->memBlock || !t1->memBlock ) {
-        if ( mmesa->TexObjList[heap].prev->bound ) {
-           fprintf( stderr,
-                    "%s: ran into bound texture\n", __FUNCTION__ );
-           return;
-        }
-        if ( mmesa->TexObjList[heap].prev == &mmesa->TexObjList[heap] ) {
-           if ( mmesa->mach64Screen->IsPCI ) {
-              fprintf( stderr, "%s: upload texture failure on local "
-                       "texture heaps, tex0 sz=%d  tex1 sz=%d\n", __FUNCTION__, 
-                       t0->size, t1->size );
-              return;
-           } else if ( heap == MACH64_CARD_HEAP ) {
-              /* If only one allocation succeeded, start over again in AGP */
-              if (t0->memBlock) {
-                 mmFreeMem( t0->memBlock );
-                 t0->memBlock = NULL;
-              }
-              if (t1->memBlock) {
-                 mmFreeMem( t1->memBlock );
-                 t1->memBlock = NULL;
-              }
-              heap = t0->heap = t1->heap = MACH64_AGP_HEAP;
-              continue;
-           } else {
-             int i;
-              fprintf( stderr, "%s: upload texture failure on %s"
-                       "AGP texture heaps, tex0 sz=%d  tex1 sz=%d\n", __FUNCTION__,
-                       mmesa->firstTexHeap == MACH64_CARD_HEAP ? "both local and " : "",
-                       t0->size, t1->size );
-              for ( i = mmesa->firstTexHeap ; i < mmesa->lastTexHeap ; i++ ) {
-                 mach64PrintLocalLRU( mmesa, i );
-                 mmDumpMemInfo( mmesa->texHeap[i] );
-              }
-              exit(-1);
-              return;
-           }
-        }
+      if ( ret == -1 && heap == MACH64_CARD_HEAP ) {
+        /* Try AGP if local memory failed */
+        heap = MACH64_AGP_HEAP;
 
-        mach64SwapOutTexObj( mmesa, mmesa->TexObjList[heap].prev );
-        
-        if (!t0->memBlock)
-           t0->memBlock = mmAllocMem( mmesa->texHeap[heap], t0->size, 6, 0 );
-        if (!t1->memBlock)
-           t1->memBlock = mmAllocMem( mmesa->texHeap[heap], t1->size, 6, 0 );
+        ret = mach64AllocateMultiTex( mmesa, u0, u1, heap, GL_TRUE );
+      }
+
+      if ( ret == -1 ) {
+        /* FIXME:
+         * Swap out all textures from the AGP heap and re-run allocation, this
+         * should succeed in all cases.
+         */
+        fprintf( stderr, "%s: upload multi-texture failure, sz0=%d sz1=%d\n",
+                 __FUNCTION__, t0->base.totalSize, t1->base.totalSize );
+        exit(-1);
       }
 
       /* Set the base offset of the texture image */
-      t0->offset = mmesa->mach64Screen->texOffset[heap] + t0->memBlock->ofs;
-      t1->offset = mmesa->mach64Screen->texOffset[heap] + t1->memBlock->ofs;
+      t0->bufAddr = mmesa->mach64Screen->texOffset[heap] + t0->base.memBlock->ofs;
+      t1->bufAddr = mmesa->mach64Screen->texOffset[heap] + t1->base.memBlock->ofs;
 
       /* Force loading the new state into the hardware */
       mmesa->dirty |= (MACH64_UPLOAD_SCALE_3D_CNTL |
@@ -816,42 +464,43 @@ void mach64UploadMultiTexImages( mach64ContextPtr mmesa,
    }
 
    /* Let the world know we've used this memory recently */
-   mach64UpdateTexLRU( mmesa, t0 );
-   mach64UpdateTexLRU( mmesa, t1 );
+   driUpdateTextureLRU( (driTextureObject *) t0 );
+   driUpdateTextureLRU( (driTextureObject *) t1 );
 
    /* Upload any images that are new */
-   if ( t0->dirty ) {
+   if ( t0->base.dirty_images[0] ) {
+      const GLint j0 = t0->base.tObj->BaseLevel;
       if (t0->heap == MACH64_AGP_HEAP) {
         /* Need to make sure any vertex buffers in the queue complete */
         mach64WaitForIdleLocked( mmesa );
-        mach64UploadAGPSubImage( mmesa, t0, t0->tObj->BaseLevel, 0, 0,
-                                   t0->tObj->Image[0][t0->tObj->BaseLevel]->Width,
-                                   t0->tObj->Image[0][t0->tObj->BaseLevel]->Height );
+        mach64UploadAGPSubImage( mmesa, t0, j0, 0, 0,
+                                   t0->base.tObj->Image[0][j0]->Width,
+                                   t0->base.tObj->Image[0][j0]->Height );
       } else {
-        mach64UploadLocalSubImage( mmesa, t0, t0->tObj->BaseLevel, 0, 0,
-                                   t0->tObj->Image[0][t0->tObj->BaseLevel]->Width,
-                                   t0->tObj->Image[0][t0->tObj->BaseLevel]->Height );
+        mach64UploadLocalSubImage( mmesa, t0, j0, 0, 0,
+                                   t0->base.tObj->Image[0][j0]->Width,
+                                   t0->base.tObj->Image[0][j0]->Height );
       }
       mmesa->setup.tex_cntl |= MACH64_TEX_CACHE_FLUSH;
+      t0->base.dirty_images[0] = 0;
    }
-   if ( t1->dirty ) {
+   if ( t1->base.dirty_images[0] ) {
+      const GLint j1 = t1->base.tObj->BaseLevel;
       if (t1->heap == MACH64_AGP_HEAP) {
         /* Need to make sure any vertex buffers in the queue complete */
         mach64WaitForIdleLocked( mmesa );
-        mach64UploadAGPSubImage( mmesa, t1, t1->tObj->BaseLevel, 0, 0,
-                              t1->tObj->Image[0][t1->tObj->BaseLevel]->Width,
-                              t1->tObj->Image[0][t1->tObj->BaseLevel]->Height );
+        mach64UploadAGPSubImage( mmesa, t1, j1, 0, 0,
+                              t1->base.tObj->Image[0][j1]->Width,
+                              t1->base.tObj->Image[0][j1]->Height );
       } else {
-        mach64UploadLocalSubImage( mmesa, t1, t1->tObj->BaseLevel, 0, 0,
-                              t1->tObj->Image[0][t1->tObj->BaseLevel]->Width,
-                              t1->tObj->Image[0][t1->tObj->BaseLevel]->Height );
+        mach64UploadLocalSubImage( mmesa, t1, j1, 0, 0,
+                              t1->base.tObj->Image[0][j1]->Width,
+                              t1->base.tObj->Image[0][j1]->Height );
       }
       
       mmesa->setup.tex_cntl |= MACH64_TEX_CACHE_FLUSH;
+      t1->base.dirty_images[0] = 0;
    }
 
    mmesa->dirty |= MACH64_UPLOAD_TEXTURE;
-
-   t0->dirty = 0;
-   t1->dirty = 0;
 }
index b6a9e3f931e74eefb44435c496797d729a551cb7..3ace370d70d1c5379b4902ea19ea529901aa3acd 100644 (file)
@@ -47,11 +47,6 @@ static void mach64SetTexImages( mach64ContextPtr mmesa,
 {
    mach64TexObjPtr t = (mach64TexObjPtr) tObj->DriverData;
    struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel];
-#if 0
-   int log2Pitch, log2Height, log2Size, log2MinSize;
-   int i;
-   GLint firstLevel, lastLevel;
-#endif
    int totalSize;
 
    assert(t);
@@ -92,77 +87,17 @@ static void mach64SetTexImages( mach64ContextPtr mmesa,
       _mesa_problem(mmesa->glCtx, "Bad texture format in %s", __FUNCTION__);
    };
 
-#if 0
-   /* Compute which mipmap levels we really want to send to the hardware.
-    * This depends on the base image size, GL_TEXTURE_MIN_LOD,
-    * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
-    * Yes, this looks overly complicated, but it's all needed.
-    */
-   firstLevel = tObj->BaseLevel + (GLint) (tObj->MinLod + 0.5);
-   firstLevel = MAX2(firstLevel, tObj->BaseLevel);
-   lastLevel = tObj->BaseLevel + (GLint) (tObj->MaxLod + 0.5);
-   lastLevel = MAX2(lastLevel, tObj->BaseLevel);
-   lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2);
-   lastLevel = MIN2(lastLevel, tObj->MaxLevel);
-   lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */
-
-   log2Pitch = tObj->Image[firstLevel]->WidthLog2;
-   log2Height = tObj->Image[firstLevel]->HeightLog2;
-   log2Size = MAX2(log2Pitch, log2Height);
-   log2MinSize = log2Size;
-
-   t->dirty = 0;
-   totalSize = 0;
-   for ( i = firstLevel; i <= lastLevel; i++ ) {
-      const struct gl_texture_image *texImage;
-
-      texImage = tObj->Image[i];
-      if ( !texImage || !texImage->Data ) {
-         lastLevel = i - 1;
-        break;
-      }
-
-      log2MinSize = texImage->MaxLog2;
-
-      t->image[i - firstLevel].offset = totalSize;
-      t->image[i - firstLevel].width  = tObj->Image[i]->Width;
-      t->image[i - firstLevel].height = tObj->Image[i]->Height;
+   totalSize = ( baseImage->Height *
+                baseImage->Width *
+                baseImage->TexFormat->TexelBytes );
 
-      t->dirty |= (1 << i);
-
-      totalSize += (tObj->Image[i]->Height *
-                   tObj->Image[i]->Width *
-                   tObj->Image[i]->TexFormat->TexelBytes);
-
-      /* Offsets must be 32-byte aligned for host data blits and tiling */
-      totalSize = (totalSize + 31) & ~31;
-   }
+   totalSize = (totalSize + 31) & ~31;
 
-   t->totalSize = totalSize;
-   t->firstLevel = firstLevel;
-   t->lastLevel = lastLevel;
+   t->base.totalSize = totalSize;
+   t->base.firstLevel = tObj->BaseLevel;
+   t->base.lastLevel = tObj->BaseLevel;
 
    /* Set the texture format */
-   t->setup.tex_cntl &= ~(0xf << 16);
-   t->setup.tex_cntl |= t->textureFormat;
-
-   t->setup.tex_combine_cntl = 0x00000000;  /* XXX is this right? */
-
-   t->setup.tex_size_pitch = ((log2Pitch   << R128_TEX_PITCH_SHIFT) |
-                             (log2Size    << R128_TEX_SIZE_SHIFT) |
-                             (log2Height  << R128_TEX_HEIGHT_SHIFT) |
-                             (log2MinSize << R128_TEX_MIN_SIZE_SHIFT));
-
-   for ( i = 0 ; i < R128_MAX_TEXTURE_LEVELS ; i++ ) {
-      t->setup.tex_offset[i]  = 0x00000000;
-   }
-
-   if (firstLevel == lastLevel)
-      t->setup.tex_cntl |= R128_MIP_MAP_DISABLE;
-   else
-      t->setup.tex_cntl &= ~R128_MIP_MAP_DISABLE;
-
-#else
    if ( ( baseImage->_BaseFormat == GL_RGBA ) ||
        ( baseImage->_BaseFormat == GL_ALPHA ) ||
        ( baseImage->_BaseFormat == GL_LUMINANCE_ALPHA ) ) {
@@ -171,15 +106,9 @@ static void mach64SetTexImages( mach64ContextPtr mmesa,
       t->hasAlpha = 0;
    }
 
-   totalSize = ( baseImage->Width * baseImage->Height * 
-      baseImage->TexFormat->TexelBytes );
-   totalSize = (totalSize + 31) & ~31;
-   t->size = totalSize;
    t->widthLog2 = baseImage->WidthLog2;
    t->heightLog2 = baseImage->HeightLog2;
    t->maxLog2 = baseImage->MaxLog2;
-   
-#endif
 }
 
 static void mach64UpdateTextureEnv( GLcontext *ctx, int unit )
@@ -387,17 +316,17 @@ static void mach64UpdateTextureUnit( GLcontext *ctx, int unit )
       }
 
       /* Upload teximages */
-      if (t->dirty) {
+      if (t->base.dirty_images[0]) {
          mach64SetTexImages( mmesa, tObj );
         mmesa->dirty |= (MACH64_UPLOAD_TEX0IMAGE << unit);
       }
 
       /* Bind to the given texture unit */
       mmesa->CurrentTexObj[unit] = t;
-      t->bound |= (1 << unit);
+      t->base.bound |= (1 << unit);
 
-      if ( t->memBlock )
-         mach64UpdateTexLRU( mmesa, t );
+      if ( t->base.memBlock )
+         driUpdateTextureLRU( (driTextureObject *) t ); /* XXX: should be locked! */
 
       /* register setup */
       if ( unit == 0 ) {
@@ -515,8 +444,8 @@ void mach64UpdateTextureState( GLcontext *ctx )
    FALLBACK( mmesa, MACH64_FALLBACK_TEXTURE, GL_FALSE );
 
    /* Unbind any currently bound textures */
-   if ( mmesa->CurrentTexObj[0] ) mmesa->CurrentTexObj[0]->bound = 0;
-   if ( mmesa->CurrentTexObj[1] ) mmesa->CurrentTexObj[1]->bound = 0;
+   if ( mmesa->CurrentTexObj[0] ) mmesa->CurrentTexObj[0]->base.bound = 0;
+   if ( mmesa->CurrentTexObj[1] ) mmesa->CurrentTexObj[1]->base.bound = 0;
    mmesa->CurrentTexObj[0] = NULL;
    mmesa->CurrentTexObj[1] = NULL;
 
@@ -556,3 +485,41 @@ void mach64UpdateTextureState( GLcontext *ctx )
                    MACH64_UPLOAD_TEXTURE);
 }
 
+
+/* Due to the way we must program texture state into the Rage Pro,
+ * we must leave these calculations to the absolute last minute.
+ */
+void mach64EmitTexStateLocked( mach64ContextPtr mmesa,
+                              mach64TexObjPtr t0,
+                              mach64TexObjPtr t1 )
+{
+   drm_mach64_sarea_t *sarea = mmesa->sarea;
+   drm_mach64_context_regs_t *regs = &(mmesa->setup);
+
+   /* for multitex, both textures must be local or AGP */
+   if ( t0 && t1 )
+      assert(t0->heap == t1->heap);
+
+   if ( t0 ) {
+      if (t0->heap == MACH64_CARD_HEAP) {
+#if ENABLE_PERF_BOXES
+        mmesa->c_texsrc_card++;
+#endif
+        mmesa->setup.tex_cntl &= ~MACH64_TEX_SRC_AGP;
+      } else {
+#if ENABLE_PERF_BOXES
+        mmesa->c_texsrc_agp++;
+#endif
+        mmesa->setup.tex_cntl |= MACH64_TEX_SRC_AGP;
+      }
+      mmesa->setup.tex_offset = t0->bufAddr;
+   }
+
+   if ( t1 ) {
+      mmesa->setup.secondary_tex_off = t1->bufAddr;
+   }
+
+   memcpy( &sarea->context_state.tex_size_pitch, &regs->tex_size_pitch,
+          MACH64_NR_TEXTURE_REGS * sizeof(GLuint) );
+}
+