⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 texmem.c

📁 Mesa is an open-source implementation of the OpenGL specification - a system for rendering interacti
💻 C
📖 第 1 页 / 共 3 页
字号:
       */      if ( (i * sz) > heap->size ) {	 nr = heap->nrRegions;	 break;      }      if (list[i].age > heap->local_age) 	  driTexturesGone( heap, i * sz, sz, list[i].in_use);    }   /* Loop or uninitialized heap detected.  Reset.    */   if (nr == heap->nrRegions) {      driTexturesGone( heap, 0, heap->size, 0);      resetGlobalLRU( heap );   }   if ( 0 ) {      printGlobalLRU( heap, __FUNCTION__ );      printLocalLRU( heap, __FUNCTION__ );   }   heap->local_age = heap->global_age[0];}#define INDEX_ARRAY_SIZE 6 /* I'm not aware of driver with more than 2 heaps *//** * Allocate memory from a texture heap to hold a texture object.  This * routine will attempt to allocate memory for the texture from the heaps * specified by \c heap_array in order.  That is, first it will try to * allocate from \c heap_array[0], then \c heap_array[1], and so on. * * \param heap_array Array of pointers to texture heaps to use * \param nr_heaps Number of heap pointer in \a heap_array * \param t Texture object for which space is needed * \return The ID of the heap from which memory was allocated, or -1 if *         memory could not be allocated. * * \bug The replacement policy implemented by this function is horrible. */intdriAllocateTexture( driTexHeap * const * heap_array, unsigned nr_heaps,		    driTextureObject * t ){   driTexHeap       * heap;   driTextureObject * temp;   driTextureObject * cursor;   unsigned           id;   /* In case it already has texture space, initialize heap.  This also    * prevents GCC from issuing a warning that heap might be used    * uninitialized.    */   heap = t->heap;   /* Run through each of the existing heaps and try to allocate a buffer    * to hold the texture.    */   for ( id = 0 ; (t->memBlock == NULL) && (id < nr_heaps) ; id++ ) {      heap = heap_array[ id ];      if ( heap != NULL ) {	 t->memBlock = mmAllocMem( heap->memory_heap, t->totalSize, 				   heap->alignmentShift, 0 );      }   }   /* Kick textures out until the requested texture fits.    */   if ( t->memBlock == NULL ) {      unsigned index[INDEX_ARRAY_SIZE];      unsigned nrGoodHeaps = 0;      /* Trying to avoid dynamic memory allocation. If you have more       * heaps, increase INDEX_ARRAY_SIZE. I'm not aware of any       * drivers with more than 2 tex heaps. */      assert( nr_heaps < INDEX_ARRAY_SIZE );      /* Sort large enough heaps by duty. Insertion sort should be       * fast enough for such a short array. */      for ( id = 0 ; id < nr_heaps ; id++ ) {	 heap = heap_array[ id ];	 if ( heap != NULL && t->totalSize <= heap->size ) {	    unsigned j;	    for ( j = 0 ; j < nrGoodHeaps; j++ ) {	       if ( heap->duty > heap_array[ index[ j ] ]->duty )		  break;	    }	    if ( j < nrGoodHeaps ) {	       memmove( &index[ j+1 ], &index[ j ],			sizeof(index[ 0 ]) * (nrGoodHeaps - j) );	    }	    index[ j ] = id;	    nrGoodHeaps++;	 }      }      for ( id = 0 ; (t->memBlock == NULL) && (id < nrGoodHeaps) ; id++ ) {	 heap = heap_array[ index[ id ] ];	 for ( cursor = heap->texture_objects.prev, temp = cursor->prev;	       cursor != &heap->texture_objects ; 	       cursor = temp, temp = cursor->prev ) {	       	    /* The the LRU element.  If the texture is bound to one of	     * the texture units, then we cannot kick it out.	     */	    if ( cursor->bound || cursor->reserved ) {	       continue;	    }	    if ( cursor->memBlock )	       heap->duty -= cursor->memBlock->size;	    /* If this is a placeholder, there's no need to keep it */	    if (cursor->tObj)	       driSwapOutTextureObject( cursor );	    else	       driDestroyTextureObject( cursor );	    t->memBlock = mmAllocMem( heap->memory_heap, t->totalSize, 				      heap->alignmentShift, 0 );	    if (t->memBlock)	       break;	 }      }      /* Rebalance duties. If a heap kicked more data than its duty,       * then all other heaps get that amount multiplied with their       * relative weight added to their duty. The negative duty is       * reset to 0. In the end all heaps have a duty >= 0.       *       * CAUTION: we must not change the heap pointer here, because it       * is used below to update the texture object.       */      for ( id = 0 ; id < nr_heaps ; id++ )	 if ( heap_array[ id ] != NULL && heap_array[ id ]->duty < 0) {	    int duty = -heap_array[ id ]->duty;	    double weight = heap_array[ id ]->weight;	    unsigned j;	    for ( j = 0 ; j < nr_heaps ; j++ )	       if ( j != id && heap_array[ j ] != NULL ) {		  heap_array[ j ]->duty += (double) duty *		     heap_array[ j ]->weight / weight;	       }	    heap_array[ id ]->duty = 0;	 }   }   if ( t->memBlock != NULL ) {      /* id and heap->heapId may or may not be the same value here.       */      assert( heap != NULL );      assert( (t->heap == NULL) || (t->heap == heap) );      t->heap = heap;      return heap->heapId;   }   else {      assert( t->heap == NULL );      fprintf( stderr, "[%s:%d] unable to allocate texture\n",	       __FUNCTION__, __LINE__ );      return -1;   }}/** * Set the location where the texture-swap counter is stored. */voiddriSetTextureSwapCounterLocation( driTexHeap * heap, unsigned * counter ){   heap->texture_swaps = (counter == NULL) ? & dummy_swap_counter : counter;}/** * Create a new heap for texture data. *  * \param heap_id             Device-dependent heap identifier.  This value *                            will returned by driAllocateTexture when memory *                            is allocated from this heap. * \param context             Device-dependent driver context.  This is *                            supplied as the first parameter to the *                            \c destroy_tex_obj function. * \param size                Size, in bytes, of the texture region * \param alignmentShift      Alignment requirement for textures.  If textures  *                            must be allocated on a 4096 byte boundry, this *                            would be 12. * \param nr_regions          Number of regions into which this texture space *                            should be partitioned * \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 *                            out). * \param texture_object_size Size, in bytes, of a device-dependent texture *                            object * \param destroy_tex_obj     Function used to destroy a device-dependent *                            texture object * * \sa driDestroyTextureHeap */driTexHeap *driCreateTextureHeap( unsigned heap_id, void * context, unsigned size,		      unsigned alignmentShift, unsigned nr_regions,		      drmTextureRegionPtr global_regions, unsigned * global_age,		      driTextureObject * swapped_objects, 		      unsigned texture_object_size,		      destroy_texture_object_t * destroy_tex_obj		    ){   driTexHeap * heap;   unsigned     l;           if ( 0 )       fprintf( stderr, "%s( %u, %p, %u, %u, %u )\n",		__FUNCTION__,		heap_id, (void *)context, size, alignmentShift, nr_regions );   heap = (driTexHeap *) CALLOC( sizeof( driTexHeap ) );   if ( heap != NULL ) {      l = driLog2( (size - 1) / nr_regions );      if ( l < alignmentShift )      {	 l = alignmentShift;      }      heap->logGranularity = l;      heap->size = size & ~((1L << l) - 1);      heap->memory_heap = mmInit( 0, heap->size );      if ( heap->memory_heap != NULL ) {	 heap->heapId = heap_id;	 heap->driverContext = context;	 heap->alignmentShift = alignmentShift;	 heap->nrRegions = nr_regions;	 heap->global_regions = global_regions;	 heap->global_age = global_age;	 heap->swapped_objects = swapped_objects;	 heap->texture_object_size = texture_object_size;	 heap->destroy_texture_object = destroy_tex_obj;	 /* Force global heap init */	 if (heap->global_age[0] == 0)	     heap->local_age = ~0;	 else	     heap->local_age = 0;	 make_empty_list( & heap->texture_objects );	 driSetTextureSwapCounterLocation( heap, NULL );	 heap->weight = heap->size;	 heap->duty = 0;      }      else {	 FREE( heap );	 heap = NULL;      }   }   if ( 0 )       fprintf( stderr, "%s returning %p\n", __FUNCTION__, (void *)heap );   return heap;}/** Destroys a texture heap *  * \param heap Texture heap to be destroyed */voiddriDestroyTextureHeap( driTexHeap * heap ){   driTextureObject * t;   driTextureObject * temp;   if ( heap != NULL ) {      foreach_s( t, temp, & heap->texture_objects ) {	 driDestroyTextureObject( t );      }      foreach_s( t, temp, heap->swapped_objects ) {	 driDestroyTextureObject( t );      }      mmDestroy( heap->memory_heap );      FREE( heap );   }}/****************************************************************************//** * Determine how many texels (including all mipmap levels) would be required * for a texture map of size \f$2^^\c base_size_log2\f$ would require. * * \param base_size_log2 \f$log_2\f$ of the size of a side of the texture * \param dimensions Number of dimensions of the texture.  Either 2 or 3. * \param faces Number of faces of the texture.  Either 1 or 6 (for cube maps). * \return Number of texels */static unsignedtexels_this_map_size( int base_size_log2, unsigned dimensions, unsigned faces ){   unsigned  texels;   assert( (faces == 1) || (faces == 6) );   assert( (dimensions == 2) || (dimensions == 3) );   texels = 0;   if ( base_size_log2 >= 0 ) {      texels = (1U << (dimensions * base_size_log2));      /* See http://www.mail-archive.com/dri-devel@lists.sourceforge.net/msg03636.html       * for the complete explaination of why this formulation is used.       * Basically, the smaller mipmap levels sum to 0.333 the size of the       * level 0 map.  The total size is therefore the size of the map       * multipled by 1.333.  The +2 is there to round up.       */      texels = (texels * 4 * faces + 2) / 3;   }   return texels;}struct maps_per_heap {   unsigned  c[32];};static voidfill_in_maximums( driTexHeap * const * heaps, unsigned nr_heaps,		  unsigned max_bytes_per_texel, unsigned max_size,		  unsigned mipmaps_at_once, unsigned dimensions,		  unsigned faces, struct maps_per_heap * max_textures ){   unsigned   heap;   unsigned   log2_size;   unsigned   mask;   /* Determine how many textures of each size can be stored in each    * texture heap.    */   for ( heap = 0 ; heap < nr_heaps ; heap++ ) {      if ( heaps[ heap ] == NULL ) {	 (void) memset( max_textures[ heap ].c, 0, 			sizeof( max_textures[ heap ].c ) );	 continue;      }      mask = (1U << heaps[ heap ]->logGranularity) - 1;      if ( 0 ) {	 fprintf( stderr, "[%s:%d] heap[%u] = %u bytes, mask = 0x%08x\n",		  __FILE__, __LINE__,		  heap, heaps[ heap ]->size, mask );      }      for ( log2_size = max_size ; log2_size > 0 ; log2_size-- ) {	 unsigned   total;	 /* Determine the total number of bytes required by a texture of	  * size log2_size.	  */	 total = texels_this_map_size( log2_size, dimensions, faces )	     - texels_this_map_size( log2_size - mipmaps_at_once,				     dimensions, faces );	 total *= max_bytes_per_texel;	 total = (total + mask) & ~mask;	 /* The number of textures of a given size that will fit in a heap	  * is equal to the size of the heap divided by the size of the	  * texture.	  */	 max_textures[ heap ].c[ log2_size ] = heaps[ heap ]->size / total;	 if ( 0 ) {	    fprintf( stderr, "[%s:%d] max_textures[%u].c[%02u] "		     "= 0x%08x / 0x%08x "		     "= %u (%u)\n",		     __FILE__, __LINE__,		     heap, log2_size,		     heaps[ heap ]->size, total,		     heaps[ heap ]->size / total,		     max_textures[ heap ].c[ log2_size ] );	 }      }   }}static unsignedget_max_size( unsigned nr_heaps,	      unsigned texture_units,	      unsigned max_size,	      int all_textures_one_heap,	      struct maps_per_heap * max_textures )

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -