Attached is a patch to the texmem branch with the changes we've been
discussing.  I'd still like to take a closer look at the global heap, but
I've included the code to force initializing the global heap on the first
lock contention for now.  I've changed the drm/ddx/texmem code to use the
drmTextureRegion/drm_tex_region_t struct for the SAREA and heap
structures, but only for the drivers converted to the texmem interface. I
also added a test to driAllocateTexture that deletes a placeholder (using
t->tObj == NULL to detect a placeholder) instead of swapping it out.  An
explicit flag for detecting a placeholder might make the code more clear,
but using t->tObj should work too.  Since placeholders should never be on
the swapped list now, I left in the assert for the swapped list being
empty in the drivers' DestroyContext, though I added code to delete 
anything on the swapped list in driDestroyTextureHeap just in case that 
assertion would need to be removed for some reason.

I've also included the optimization in driTexturesGone to keep an existing 
placeholder if the global region is in use and matches the size and offset 
of the existing placeholder.

It this looks OK, I will apply it to the branch.

I need to do some more testing on the Rage 128 driver, but so far things 
seem to be working except for the problem in the fire Mesa demo, which is 
still there.  It kind of looks like a texture coordinate problem, but I'm 
not sure yet.

-- 
Leif Delgass 
http://www.retinalburn.net
Index: lib/GL/mesa/src/drv/common/texmem.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/common/Attic/texmem.c,v
retrieving revision 1.1.2.8
diff -u -r1.1.2.8 texmem.c
--- lib/GL/mesa/src/drv/common/texmem.c 27 Jan 2003 23:43:31 -0000      1.1.2.8
+++ lib/GL/mesa/src/drv/common/texmem.c 1 Feb 2003 21:39:55 -0000
@@ -119,12 +119,10 @@
 
 static void resetGlobalLRU( driTexHeap * heap )
 {
-   driTexRegion * list = heap->global_regions;
+   drmTextureRegionPtr list = heap->global_regions;
    unsigned       sz = 1U << heap->logGranularity;
    unsigned       i;
 
-   heap->local_age = ++heap->global_age[0];
-
    for (i = 0 ; (i+1) * sz <= heap->size ; i++) {
       list[i].prev = i-1;
       list[i].next = i+1;
@@ -140,7 +138,74 @@
    heap->global_age[0] = 0;
 }
 
+/**
+ * Print out debugging information about the local texture LRU.
+ *
+ * \param heap Texture heap to be printed
+ */
+static void printLocalLRU( driTexHeap * heap )
+{
+   driTextureObject *t;
+   unsigned sz = 1U << heap->logGranularity;
 
+   fprintf( stderr, "Local LRU, heap %d:\n", heap->heapId );
+
+   foreach ( t, &heap->texture_objects ) {
+      if (!t->memBlock)
+        continue;
+      if (!t->tObj) {
+        fprintf( stderr, "Placeholder (%p) %d at 0x%x sz 0x%x\n",
+                 t,
+                 t->memBlock->ofs / sz,
+                 t->memBlock->ofs,
+                 t->memBlock->size );
+      } else {
+        fprintf( stderr, "Texture (%p) at 0x%x sz 0x%x\n",
+                 t,
+                 t->memBlock->ofs,
+                 t->memBlock->size );
+      }
+   }
+   foreach ( t, heap->swapped_objects ) {
+      if (!t->tObj) {
+        fprintf( stderr, "Swapped Placeholder (%p)\n", t );
+      } else {
+        fprintf( stderr, "Swapped Texture (%p)\n", t );
+      }
+   }
+
+   fprintf( stderr, "\n" );
+}
+
+/**
+ * Print out debugging information about the global texture LRU.
+ *
+ * \param heap Texture heap to be printed
+ */
+static void printGlobalLRU( driTexHeap * heap )
+{
+   drmTextureRegionPtr list = heap->global_regions;
+   int i, j;
+
+   fprintf( stderr, "Global LRU, heap %d list %p:\n", heap->heapId, list );
+
+   for ( i = 0, j = heap->nrRegions ; i < heap->nrRegions ; i++ ) {
+      fprintf( stderr, "list[%d] age %d next %d prev %d in_use %d\n",
+              j, list[j].age, list[j].next, list[j].prev, list[j].in_use );
+      j = list[j].next;
+      if ( j == heap->nrRegions ) break;
+   }
+
+   if ( j != heap->nrRegions ) {
+      fprintf( stderr, "Loop detected in global LRU\n" );
+      for ( i = 0 ; i < heap->nrRegions ; i++ ) {
+        fprintf( stderr, "list[%d] age %d next %d prev %d in_use %d\n",
+                 i, list[i].age, list[i].next, list[i].prev, list[i].in_use );
+      }
+   }
+
+   fprintf( stderr, "\n" );
+}
 
 
 /**
@@ -152,7 +217,7 @@
 void driUpdateTextureLRU( driTextureObject * t )
 {
     driTexHeap   * heap;
-    driTexRegion * list;
+    drmTextureRegionPtr list;
     unsigned   shift;
     unsigned   start;
     unsigned   end;
@@ -194,6 +259,12 @@
            list[(unsigned)list[heap->nrRegions].next].prev = i;
            list[heap->nrRegions].next = i;
        }
+
+       if ( 0 ) {
+           printGlobalLRU( heap );
+           printLocalLRU( heap );
+       }
+
     }
 }
 
@@ -326,7 +397,13 @@
            }
            else
            {
-               driDestroyTextureObject( t );
+               if ( in_use && 
+                    offset == t->memBlock->ofs && size == t->memBlock->size ) {
+                   /* Matching placeholder already exists */
+                   return;
+               } else {
+                   driDestroyTextureObject( t );
+               }
            }
        }
     }
@@ -338,11 +415,12 @@
 
        t->memBlock = mmAllocMem( heap->memory_heap, size, 0, offset );
        if ( t->memBlock == NULL ) {
-           fprintf( stderr, "Couldn't alloc placeholder sz %x ofs %x\n",
+           fprintf( stderr, "Couldn't alloc placeholder: heap %u sz %x ofs %x\n", 
+heap->heapId,
                    (int)size, (int)offset );
            mmDumpMemInfo( heap->memory_heap );
            return;
        }
+       t->heap = heap;
        insert_at_head( & heap->texture_objects, t );
     }
 }
@@ -361,7 +439,7 @@
 
 void driAgeTextures( driTexHeap * heap )
 {
-    driTexRegion * list = heap->global_regions;
+    drmTextureRegionPtr list = heap->global_regions;
     unsigned       sz = 1U << (heap->logGranularity);
     unsigned       i, nr = 0;
 
@@ -384,10 +462,9 @@
        }
 
        if (list[i].age > heap->local_age) 
-           driTexturesGone( heap, i * sz, sz, 1); 
+           driTexturesGone( heap, i * sz, sz, list[i].in_use); 
     }
 
-
     /* Loop or uninitialized heap detected.  Reset.
      */
 
@@ -396,6 +473,11 @@
        resetGlobalLRU( heap );
     }
 
+    if ( 0 ) {
+       printGlobalLRU( heap );
+       printLocalLRU( heap );
+    }
+
     heap->local_age = heap->global_age[0];
 }
 
@@ -473,7 +555,12 @@
                        break;
                    }
 
-                   driSwapOutTextureObject( temp );
+                   /* If this is a placeholder, there's no need to keep it */
+                   if (temp->tObj)
+                       driSwapOutTextureObject( temp );
+                   else
+                       driDestroyTextureObject( temp );
+
                    t->memBlock = mmAllocMem( heap->memory_heap, t->totalSize, 
                                              heap->alignmentShift, 0 );
                }
@@ -534,7 +621,7 @@
  *                            would be 12.
  * \param nr_regions          Number of regions into which this texture space
  *                            should be partitioned
- * \param global_regions      Array of \c driTexRegion structures in the SAREA
+ * \param global_regions      Array of \c drmTextureRegion structures in the SAREA
  * \param global_age          Pointer to the global texture age in the SAREA
  * \param swapped_objects     Pointer to the list of texture objects that are
  *                            not in texture memory (i.e., have been swapped
@@ -550,7 +637,7 @@
 driTexHeap *
 driCreateTextureHeap( unsigned heap_id, void * context, unsigned size,
                      unsigned alignmentShift, unsigned nr_regions,
-                     driTexRegion * global_regions, unsigned * global_age,
+                     drmTextureRegionPtr global_regions, unsigned * global_age,
                      driTextureObject * swapped_objects, 
                      unsigned texture_object_size,
                      destroy_texture_object_t * destroy_tex_obj
@@ -591,7 +678,12 @@
            heap->texture_object_size = texture_object_size;
            heap->destroy_texture_object = destroy_tex_obj;
 
-           heap->local_age = 0;
+           /* Force global heap init */
+           if (heap->global_age == 0)
+               heap->local_age = ~0;
+           else
+               heap->local_age = 0;
+
            make_empty_list( & heap->texture_objects );
            driSetTextureSwapCounterLocation( heap, NULL );
        }
@@ -627,6 +719,10 @@
     if ( heap != NULL )
     {
        foreach_s( t, temp, & heap->texture_objects )
+       {
+           driDestroyTextureObject( t );
+       }
+       foreach_s( t, temp, heap->swapped_objects )
        {
            driDestroyTextureObject( t );
        }
Index: lib/GL/mesa/src/drv/common/texmem.h
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/common/Attic/texmem.h,v
retrieving revision 1.1.2.6
diff -u -r1.1.2.6 texmem.h
--- lib/GL/mesa/src/drv/common/texmem.h 26 Jan 2003 07:43:46 -0000      1.1.2.6
+++ lib/GL/mesa/src/drv/common/texmem.h 1 Feb 2003 21:39:55 -0000
@@ -41,6 +41,7 @@
 
 #include "mtypes.h"
 #include "mm.h"
+#include "xf86drm.h"
 
 struct dri_tex_heap;
 typedef struct dri_tex_heap driTexHeap;
@@ -48,8 +49,6 @@
 struct dri_texture_object;
 typedef struct dri_texture_object driTextureObject;
 
-struct dri_texture_region;
-typedef struct dri_texture_region driTexRegion;
 
 /**
  * Base texture object type.  Each driver will extend this type with its own
@@ -78,23 +77,6 @@
 };
 
 
-/**
- * Inter-context texture memory management structure.
- * 
- * Each driver will have an array of driTexRegion structures in its SAREA.
- * Each element in the array corresponds to a specific block of texture
- * memory.
- */
-struct dri_texture_region {
-       unsigned char next;     /**< indices to form a circular LRU  */
-       unsigned char prev;     /**< indices to form a circular LRU  */
-       unsigned char in_use;   /**< owned by a client, or free? */
-       unsigned      age;      /**< tracked by clients to update local LRU's */
-};
-
-
-
-
 typedef void (destroy_texture_object_t)( void * driverContext,
                                        driTextureObject * t );
 
@@ -148,8 +130,8 @@
 
        /** Pointer to SAREA \a driTexRegion array
         */
-       driTexRegion * global_regions;
-    
+       drmTextureRegionPtr global_regions;
+
        /** Pointer to the texture state age (generation number) in the SAREA
         */
        unsigned     * global_age;
@@ -218,7 +200,7 @@
 #define DRI_AGE_TEXTURES( heap )                               \
    do {                                                                \
        if ( ((heap) != NULL)                                   \
-           && ((heap)->local_age > (heap)->global_age[0]) )    \
+           && ((heap)->local_age != (heap)->global_age[0]) )   \
           driAgeTextures( heap );                              \
    } while( 0 )
 
@@ -243,7 +225,7 @@
 
 driTexHeap * driCreateTextureHeap( unsigned heap_id, void * context,
     unsigned size, unsigned alignmentShift, unsigned nr_regions,
-    driTexRegion * global_regions, unsigned * global_age,
+    drmTextureRegionPtr global_regions, unsigned * global_age,
     driTextureObject * swapped_objects, unsigned texture_object_size,
     destroy_texture_object_t * destroy_tex_obj );
 void driDestroyTextureHeap( driTexHeap * heap );
Index: lib/GL/mesa/src/drv/mga/mga_xmesa.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/mga/mga_xmesa.c,v
retrieving revision 1.38.10.7
diff -u -r1.38.10.7 mga_xmesa.c
--- lib/GL/mesa/src/drv/mga/mga_xmesa.c 26 Jan 2003 07:43:46 -0000      1.38.10.7
+++ lib/GL/mesa/src/drv/mga/mga_xmesa.c 1 Feb 2003 21:39:55 -0000
@@ -329,8 +329,8 @@
            mgaScreen->textureSize[i],
            6,
            MGA_NR_TEX_REGIONS,
-           (driTexRegion *) & mmesa->sarea->texList,
-           (unsigned *) & mmesa->sarea->texAge,
+           mmesa->sarea->texList[i],
+           & mmesa->sarea->texAge[i],
            & mmesa->swapped,
            sizeof( mgaTextureObject_t ),
            (destroy_texture_object_t *) mgaDestroyTexObj );
@@ -479,11 +479,9 @@
           */
          int i;
 
-
         assert( is_empty_list( & mmesa->swapped ) );
 
          for ( i = 0 ; i < mmesa->nr_heaps ; i++ ) {
-           assert( is_empty_list( & mmesa->texture_heaps[ i ]->texture_objects ) );
            driDestroyTextureHeap( mmesa->texture_heaps[ i ] );
            mmesa->texture_heaps[ i ] = NULL;
          }
Index: lib/GL/mesa/src/drv/r128/r128_context.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/r128/r128_context.c,v
retrieving revision 1.18.36.4
diff -u -r1.18.36.4 r128_context.c
--- lib/GL/mesa/src/drv/r128/r128_context.c     5 Dec 2002 15:26:13 -0000       
1.18.36.4
+++ lib/GL/mesa/src/drv/r128/r128_context.c     1 Feb 2003 21:39:56 -0000
@@ -138,8 +138,8 @@
            r128scrn->texSize[i],
            12,
            R128_NR_TEX_REGIONS,
-           (driTexRegion *) & rmesa->sarea->texList,
-           (unsigned *) & rmesa->sarea->texAge,
+           rmesa->sarea->texList[i],
+           & rmesa->sarea->texAge[i],
            & rmesa->swapped,
            sizeof( r128TexObj ),
            (destroy_texture_object_t *) r128DestroyTexObj );
@@ -257,11 +257,9 @@
           */
          int i;
 
-
         assert( is_empty_list( & rmesa->swapped ) );
 
          for ( i = 0 ; i < rmesa->nr_heaps ; i++ ) {
-           assert( is_empty_list( & rmesa->texture_heaps[ i ]->texture_objects ) );
            driDestroyTextureHeap( rmesa->texture_heaps[ i ] );
            rmesa->texture_heaps[ i ] = NULL;
          }
Index: lib/GL/mesa/src/drv/r200/r200_context.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/r200/r200_context.c,v
retrieving revision 1.9.2.4
diff -u -r1.9.2.4 r200_context.c
--- lib/GL/mesa/src/drv/r200/r200_context.c     26 Jan 2003 07:43:46 -0000      
1.9.2.4
+++ lib/GL/mesa/src/drv/r200/r200_context.c     1 Feb 2003 21:39:58 -0000
@@ -281,8 +281,8 @@
            screen->texSize[i],
            12,
            RADEON_NR_TEX_REGIONS,
-           (driTexRegion *) & rmesa->sarea->texList,
-           (unsigned *) & rmesa->sarea->texAge,
+           rmesa->sarea->texList[i],
+           (unsigned *) & rmesa->sarea->texAge[i],
            & rmesa->swapped,
            sizeof( r200TexObj ),
            (destroy_texture_object_t *) r200DestroyTexObj );
@@ -472,11 +472,9 @@
           */
          int i;
 
-
         assert( is_empty_list( & rmesa->swapped ) );
 
          for ( i = 0 ; i < rmesa->nr_heaps ; i++ ) {
-           assert( is_empty_list( & rmesa->texture_heaps[ i ]->texture_objects ) );
            driDestroyTextureHeap( rmesa->texture_heaps[ i ] );
            rmesa->texture_heaps[ i ] = NULL;
          }
Index: lib/GL/mesa/src/drv/radeon/radeon_context.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/radeon/radeon_context.c,v
retrieving revision 1.20.2.7
diff -u -r1.20.2.7 radeon_context.c
--- lib/GL/mesa/src/drv/radeon/radeon_context.c 5 Dec 2002 15:26:34 -0000       
1.20.2.7
+++ lib/GL/mesa/src/drv/radeon/radeon_context.c 1 Feb 2003 21:40:02 -0000
@@ -279,8 +279,8 @@
            screen->texSize[i],
            12,
            RADEON_NR_TEX_REGIONS,
-           (driTexRegion *) & rmesa->sarea->texList,
-           (unsigned *) & rmesa->sarea->texAge,
+           rmesa->sarea->texList[i],
+           & rmesa->sarea->texAge[i],
            & rmesa->swapped,
            sizeof( radeonTexObj ),
            (destroy_texture_object_t *) radeonDestroyTexObj );
@@ -460,11 +460,9 @@
           */
          int i;
 
-
         assert( is_empty_list( & rmesa->swapped ) );
 
          for ( i = 0 ; i < rmesa->nr_heaps ; i++ ) {
-           assert( is_empty_list( & rmesa->texture_heaps[ i ]->texture_objects ) );
            driDestroyTextureHeap( rmesa->texture_heaps[ i ] );
            rmesa->texture_heaps[ i ] = NULL;
          }
Index: programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/r128_drm.h
===================================================================
RCS file: 
/cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/r128_drm.h,v

retrieving revision 1.2.12.1
diff -u -r1.2.12.1 r128_drm.h
--- programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/r128_drm.h 6 Nov 2002 
00:53:07 -0000       1.2.12.1
+++ programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/r128_drm.h 1 Feb 2003 
+21:40:07 -0000
@@ -162,7 +162,7 @@
        unsigned int last_dispatch;
 
        drm_tex_region_t tex_list[R128_NR_TEX_HEAPS][R128_NR_TEX_REGIONS+1];
-       int tex_age[R128_NR_TEX_HEAPS];
+       unsigned int tex_age[R128_NR_TEX_HEAPS];
        int ctx_owner;
 } drm_r128_sarea_t;
 
Index: programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_drm.h
===================================================================
RCS file: 
/cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_drm.h,v

retrieving revision 1.6.2.1
diff -u -r1.6.2.1 radeon_drm.h
--- programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_drm.h       6 Nov 
2002 00:53:07 -0000       1.6.2.1
+++ programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_drm.h       1 Feb 
+2003 21:40:07 -0000
@@ -323,12 +323,6 @@
 
 
 typedef struct {
-       unsigned char next, prev;
-       unsigned char in_use;
-       int age;
-} drm_radeon_tex_region_t;
-
-typedef struct {
        /* The channel for communication of state information to the
         * kernel on firing a vertex buffer with either of the
         * obsoleted vertex/index ioctls.
@@ -350,8 +344,8 @@
        unsigned int last_dispatch;
        unsigned int last_clear;
 
-       drm_radeon_tex_region_t 
tex_list[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS+1];
-       int tex_age[RADEON_NR_TEX_HEAPS];
+       drm_tex_region_t tex_list[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS+1];
+       unsigned int tex_age[RADEON_NR_TEX_HEAPS];
        int ctx_owner;
         int pfState;                /* number of 3d windows (0,1,2ormore) */
         int pfCurrentPage;         /* which buffer is being displayed? */
Index: programs/Xserver/hw/xfree86/drivers/ati/r128_sarea.h
===================================================================
RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/drivers/ati/r128_sarea.h,v
retrieving revision 1.10.48.1
diff -u -r1.10.48.1 r128_sarea.h
--- programs/Xserver/hw/xfree86/drivers/ati/r128_sarea.h        11 Nov 2002 23:32:30 
-0000      1.10.48.1
+++ programs/Xserver/hw/xfree86/drivers/ati/r128_sarea.h        1 Feb 2003 21:40:09 
+-0000
@@ -149,12 +149,6 @@
 } r128_texture_regs_t;
 
 typedef struct {
-    unsigned char next, prev;  /* indices to form a circular LRU  */
-    unsigned char in_use;      /* owned by a client, or free? */
-    int age;                   /* tracked by clients to update local LRU's */
-} r128_tex_region_t;
-
-typedef struct {
     /* The channel for communication of state information to the kernel
      * on firing a vertex buffer.
      */
@@ -191,9 +185,9 @@
      * else's - simply eject them all in LRU order.
      */
                                /* Last elt is sentinal */
-    r128_tex_region_t texList[R128_NR_TEX_HEAPS][R128_NR_TEX_REGIONS+1];
+    drmTextureRegion texList[R128_NR_TEX_HEAPS][R128_NR_TEX_REGIONS+1];
                                /* last time texture was uploaded */
-    int texAge[R128_NR_TEX_HEAPS];
+    unsigned int texAge[R128_NR_TEX_HEAPS];
 
     int ctxOwner;              /* last context to upload state */
 } R128SAREAPriv, *R128SAREAPrivPtr;
Index: programs/Xserver/hw/xfree86/drivers/ati/radeon_sarea.h
===================================================================
RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_sarea.h,v
retrieving revision 1.6.14.1
diff -u -r1.6.14.1 radeon_sarea.h
--- programs/Xserver/hw/xfree86/drivers/ati/radeon_sarea.h      11 Nov 2002 23:32:31 
-0000      1.6.14.1
+++ programs/Xserver/hw/xfree86/drivers/ati/radeon_sarea.h      1 Feb 2003 21:40:14 
+-0000
@@ -185,12 +185,6 @@
 } radeon_texture_regs_t;
 
 typedef struct {
-    unsigned char next, prev;  /* indices to form a circular LRU  */
-    unsigned char in_use;      /* owned by a client, or free? */
-    int age;                   /* tracked by clients to update local LRU's */
-} radeon_tex_region_t;
-
-typedef struct {
     /* The channel for communication of state information to the kernel
      * on firing a vertex buffer.
      */
@@ -224,9 +218,9 @@
      * else's - simply eject them all in LRU order.
      */
                                /* Last elt is sentinal */
-    radeon_tex_region_t texList[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS+1];
+    drmTextureRegion texList[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS+1];
                                /* last time texture was uploaded */
-    int texAge[RADEON_NR_TEX_HEAPS];
+    unsigned int texAge[RADEON_NR_TEX_HEAPS];
 
     int ctxOwner;              /* last context to upload state */
     int pfAllowPageFlip;       /* set by the 2d driver, read by the client */

Reply via email to