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

📄 texmem.c

📁 Mesa is an open-source implementation of the OpenGL specification - a system for rendering interacti
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright 2000-2001 VA Linux Systems, Inc. * (C) Copyright IBM Corporation 2002, 2003 * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * on the rights to use, copy, modify, merge, publish, distribute, sub * license, and/or sell copies of the Software, and to permit persons to whom * the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * USE OR OTHER DEALINGS IN THE SOFTWARE. * * Authors: *    Ian Romanick <idr@us.ibm.com> *    Keith Whitwell <keithw@tungstengraphics.com> *    Kevin E. Martin <kem@users.sourceforge.net> *    Gareth Hughes <gareth@nvidia.com> *//* $XFree86:$ *//** \file texmem.c * Implements all of the device-independent texture memory management. *  * Currently, only a simple LRU texture memory management policy is * implemented.  In the (hopefully very near) future, better policies will be * implemented.  The idea is that the DRI should be able to run in one of two * modes.  In the default mode the DRI will dynamically attempt to discover * the best texture management policy for the running application.  In the * other mode, the user (via some sort of as yet TBD mechanism) will select * a texture management policy that is known to work well with the * application. */#include "texmem.h"#include "simple_list.h"#include "imports.h"#include "macros.h"#include "texformat.h"#include <assert.h>static unsigned dummy_swap_counter;/** * Calculate \f$\log_2\f$ of a value.  This is a particularly poor * implementation of this function.  However, since system performance is in * no way dependent on this function, the slowness of the implementation is * irrelevent. *  * \param n Value whose \f$\log_2\f$ is to be calculated */static GLuintdriLog2( GLuint n ){   GLuint log2;   for ( log2 = 1 ; n > 1 ; log2++ ) {      n >>= 1;   }   return log2;}/** * Determine if a texture is resident in textureable memory.  Depending on * the driver, this may or may not be on-card memory.  It could be AGP memory * or anyother type of memory from which the hardware can directly read * texels. *  * This function is intended to be used as the \c IsTextureResident function * in the device's \c dd_function_table. *  * \param ctx GL context pointer (currently unused) * \param texObj Texture object to be tested */GLbooleandriIsTextureResident( GLcontext * ctx, 		      struct gl_texture_object * texObj ){   driTextureObject * t;   t = (driTextureObject *) texObj->DriverData;   return( (t != NULL) && (t->memBlock != NULL) );}/** * (Re)initialize the global circular LRU list.  The last element * in the array (\a heap->nrRegions) is the sentinal.  Keeping it * at the end of the array allows the other elements of the array * to be addressed rationally when looking up objects at a particular * location in texture memory. *  * \param heap Texture heap to be reset */static void resetGlobalLRU( driTexHeap * heap ){   drmTextureRegionPtr list = heap->global_regions;   unsigned       sz = 1U << heap->logGranularity;   unsigned       i;   for (i = 0 ; (i+1) * sz <= heap->size ; i++) {      list[i].prev = i-1;      list[i].next = i+1;      list[i].age = 0;   }   i--;   list[0].prev = heap->nrRegions;   list[i].prev = i-1;   list[i].next = heap->nrRegions;   list[heap->nrRegions].prev = i;   list[heap->nrRegions].next = 0;   heap->global_age[0] = 0;}/** * Print out debugging information about the local texture LRU. * * \param heap Texture heap to be printed * \param callername Name of calling function */static void printLocalLRU( driTexHeap * heap, const char *callername  ){   driTextureObject *t;   unsigned sz = 1U << heap->logGranularity;   fprintf( stderr, "%s in %s:\nLocal LRU, heap %d:\n", 	    __FUNCTION__, callername, 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",		  (void *)t,		  t->memBlock->ofs / sz,		  t->memBlock->ofs,		  t->memBlock->size );      } else {	 fprintf( stderr, "Texture (%p) at 0x%x sz 0x%x\n",		  (void *)t,		  t->memBlock->ofs,		  t->memBlock->size );      }   }   foreach ( t, heap->swapped_objects ) {      if (!t->tObj) {	 fprintf( stderr, "Swapped Placeholder (%p)\n", (void *)t );      } else {	 fprintf( stderr, "Swapped Texture (%p)\n", (void *)t );      }   }   fprintf( stderr, "\n" );}/** * Print out debugging information about the global texture LRU. * * \param heap Texture heap to be printed * \param callername Name of calling function */static void printGlobalLRU( driTexHeap * heap, const char *callername ){   drmTextureRegionPtr list = heap->global_regions;   unsigned int i, j;   fprintf( stderr, "%s in %s:\nGlobal LRU, heap %d list %p:\n", 	    __FUNCTION__, callername, heap->heapId, (void *)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" );}/** * Called by the client whenever it touches a local texture. *  * \param t Texture object that the client has accessed */void driUpdateTextureLRU( driTextureObject * t ){   driTexHeap   * heap;   drmTextureRegionPtr list;   unsigned   shift;   unsigned   start;   unsigned   end;   unsigned   i;   heap = t->heap;   if ( heap != NULL ) {      shift = heap->logGranularity;      start = t->memBlock->ofs >> shift;      end = (t->memBlock->ofs + t->memBlock->size - 1) >> shift;      heap->local_age = ++heap->global_age[0];      list = heap->global_regions;      /* Update the context's local LRU        */      move_to_head( & heap->texture_objects, t );      for (i = start ; i <= end ; i++) {	 list[i].age = heap->local_age;	 /* remove_from_list(i)	  */	 list[(unsigned)list[i].next].prev = list[i].prev;	 list[(unsigned)list[i].prev].next = list[i].next;	 /* insert_at_head(list, i)	  */	 list[i].prev = heap->nrRegions;	 list[i].next = list[heap->nrRegions].next;	 list[(unsigned)list[heap->nrRegions].next].prev = i;	 list[heap->nrRegions].next = i;      }      if ( 0 ) {	 printGlobalLRU( heap, __FUNCTION__ );	 printLocalLRU( heap, __FUNCTION__ );      }   }}/** * Keep track of swapped out texture objects. *  * \param t Texture object to be "swapped" out of its texture heap */void driSwapOutTextureObject( driTextureObject * t ){   unsigned   face;   if ( t->memBlock != NULL ) {      assert( t->heap != NULL );      mmFreeMem( t->memBlock );      t->memBlock = NULL;      if (t->timestamp > t->heap->timestamp)	 t->heap->timestamp = t->timestamp;      t->heap->texture_swaps[0]++;      move_to_tail( t->heap->swapped_objects, t );      t->heap = NULL;   }   else {      assert( t->heap == NULL );   }   for ( face = 0 ; face < 6 ; face++ ) {      t->dirty_images[face] = ~0;   }}/** * Destroy hardware state associated with texture \a t.  Calls the * \a destroy_texture_object method associated with the heap from which * \a t was allocated. *  * \param t Texture object to be destroyed */void driDestroyTextureObject( driTextureObject * t ){   driTexHeap * heap;   if ( 0 ) {      fprintf( stderr, "[%s:%d] freeing %p (tObj = %p, DriverData = %p)\n",	       __FILE__, __LINE__,	       (void *)t,	       (void *)((t != NULL) ? t->tObj : NULL),	       (void *)((t != NULL && t->tObj != NULL) ? t->tObj->DriverData : NULL ));   }   if ( t != NULL ) {      if ( t->memBlock ) {	 heap = t->heap;	 assert( heap != NULL );	 heap->texture_swaps[0]++;	 mmFreeMem( t->memBlock );	 t->memBlock = NULL;	 if (t->timestamp > t->heap->timestamp)	    t->heap->timestamp = t->timestamp;	 heap->destroy_texture_object( heap->driverContext, t );	 t->heap = NULL;      }      if ( t->tObj != NULL ) {	 assert( t->tObj->DriverData == t );	 t->tObj->DriverData = NULL;      }      remove_from_list( t );      FREE( t );   }   if ( 0 ) {      fprintf( stderr, "[%s:%d] done freeing %p\n", __FILE__, __LINE__, (void *)t );   }}/** * Update the local heap's representation of texture memory based on * data in the SAREA.  This is done each time it is detected that some other * direct rendering client has 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 \a tObj being \a NULL. *  * \param heap Heap whose state is to be updated * \param offset Byte offset in the heap that has been stolen * \param size Size, in bytes, of the stolen block * \param in_use Non-zero if the block is pinned/reserved by the kernel */static void driTexturesGone( driTexHeap * heap, int offset, int size, 			     int in_use ){   driTextureObject * t;   driTextureObject * tmp;   foreach_s ( t, tmp, & heap->texture_objects ) {      if ( (t->memBlock->ofs < (offset + size))	   && ((t->memBlock->ofs + t->memBlock->size) > offset) ) {	 /* It overlaps - kick it out.  If the texture object is just a	  * place holder, then destroy it all together.  Otherwise, mark	  * it as being swapped out.	  */	 if ( t->tObj != NULL ) {	    driSwapOutTextureObject( t );	 }	 else {	    driDestroyTextureObject( t );	 }      }   }   {      t = (driTextureObject *) CALLOC( heap->texture_object_size );      if ( t == NULL ) return;      t->memBlock = mmAllocMem( heap->memory_heap, size, 0, offset );      if ( t->memBlock == NULL ) {	 fprintf( stderr, "Couldn't alloc placeholder: heap %u sz %x ofs %x\n", heap->heapId,		  (int)size, (int)offset );	 mmDumpMemInfo( heap->memory_heap );	 FREE(t);	 return;      }      t->heap = heap;      if (in_use) 	 t->reserved = 1;       insert_at_head( & heap->texture_objects, t );   }}/** * Called by the client on lock contention to determine whether textures have * been stolen.  If another client has modified a region in which we have * textures, then we need to figure out which of our textures have been * removed and update our global LRU. *  * \param heap Texture heap to be updated */void driAgeTextures( driTexHeap * heap ){   drmTextureRegionPtr list = heap->global_regions;   unsigned       sz = 1U << (heap->logGranularity);   unsigned       i, nr = 0;   /* Have to go right round from the back to ensure stuff ends up    * LRU in the local list...  Fix with a cursor pointer.    */   for (i = list[heap->nrRegions].prev ; 	i != heap->nrRegions && nr < heap->nrRegions ; 	i = list[i].prev, nr++) {      /* If switching texturing schemes, then the SAREA might not have been       * properly cleared, so we need to reset the global texture LRU.

⌨️ 快捷键说明

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