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

📄 gamma_texmem.c

📁 Mesa is an open-source implementation of the OpenGL specification - a system for rendering interacti
💻 C
字号:
/* $XFree86: xc/lib/GL/mesa/src/drv/gamma/gamma_texmem.c,v 1.5 2002/11/05 17:46:07 tsi Exp $ */#include <stdlib.h>#include <stdio.h>#include "glheader.h"#include "colormac.h"#include "macros.h"#include "mtypes.h"#include "simple_list.h"#include "enums.h"#include "mm.h"#include "glint_dri.h"#include "gamma_context.h"#include "gamma_lock.h"void gammaDestroyTexObj(gammaContextPtr gmesa, gammaTextureObjectPtr t){   if (!t) return;   /* This is sad - need to sync *in case* we upload a texture    * to this newly free memory...    */   if (t->MemBlock) {      mmFreeMem(t->MemBlock);      t->MemBlock = 0;      if (gmesa && t->age > gmesa->dirtyAge)	 gmesa->dirtyAge = t->age;   }   if (t->globj)      t->globj->DriverData = 0;   if (gmesa) {      if (gmesa->CurrentTexObj[0] == t) {         gmesa->CurrentTexObj[0] = 0;         gmesa->dirty &= ~GAMMA_UPLOAD_TEX0;      }#if 0      if (gmesa->CurrentTexObj[1] == t) {         gmesa->CurrentTexObj[1] = 0;         gmesa->dirty &= ~GAMMA_UPLOAD_TEX1;      }#endif   }   remove_from_list(t);   free(t);}void gammaSwapOutTexObj(gammaContextPtr gmesa, gammaTextureObjectPtr t){/*     fprintf(stderr, "%s\n", __FUNCTION__); */   if (t->MemBlock) {      mmFreeMem(t->MemBlock);      t->MemBlock = 0;      if (t->age > gmesa->dirtyAge)	 gmesa->dirtyAge = t->age;   }   t->dirty_images = ~0;   move_to_tail(&(gmesa->SwappedOut), t);}/* Upload an image from mesa's internal copy. */static void gammaUploadTexLevel( gammaContextPtr gmesa, gammaTextureObjectPtr t, int level ){   const struct gl_texture_image *image = t->image[level].image;   int i,j;   int l2d;#if 0   int offset = 0;#endif   int words, depthLog2;   /* fprintf(stderr, "%s\n", __FUNCTION__);  */   l2d = 5; /* 32bits per texel == 1<<5 */   if (level == 0) {      t->TextureAddressMode &= ~(TAM_WidthMask | TAM_HeightMask);      t->TextureAddressMode |= (image->WidthLog2 << 9) | 			       (image->HeightLog2 << 13);      t->TextureReadMode &= ~(TRM_WidthMask | TRM_HeightMask | 			      TRM_DepthMask | TRM_Border |			      TRM_Patch);      t->TextureReadMode |= (image->WidthLog2 << 1) | 			    (image->HeightLog2 << 5) | 			    (l2d << 9);      t->TextureFormat &= ~(TF_CompnentsMask | TF_OneCompFmt_Mask);   }   t->TextureBaseAddr[level] = /* ??? */	(unsigned long)(t->image[level].offset + t->BufAddr) << 5;   CALC_LOG2(depthLog2, 1<<l2d);   words = (image->Width * image->Height) >> (5-depthLog2);   CHECK_DMA_BUFFER(gmesa, 3);   WRITE(gmesa->buf, LBWindowBase, t->TextureBaseAddr[level] >> 5);   WRITE(gmesa->buf, TextureCacheControl, (TCC_Enable | TCC_Invalidate));   WRITE(gmesa->buf, WaitForCompletion, 0);   FLUSH_DMA_BUFFER(gmesa);   switch (t->image[level].internalFormat) {   case GL_RGB:   case 3:   {      GLubyte  *src = (GLubyte *)image->Data;      if (level == 0)         t->TextureFormat |= TF_Compnents_3;      #if 0 /* This is the texture download code we SHOULD be using */      /* In the routines below, but this causes an DMA overrun - WHY ? */      while (offset < words) {         int count = gmesa->bufSize;	 int i;	 count -= 3;         if (count > words-offset) count = words-offset;	 gmesa->buf->i = GlintTextureDownloadOffsetTag;	 gmesa->buf++;	 gmesa->buf->i = offset;	 gmesa->buf++;         gmesa->buf->i = (GlintTextureDataTag | ((count-1) << 16));	 gmesa->buf++;	 for (i = 0; i < count; i++) {		gmesa->buf->i = PACK_COLOR_565(src[0],src[1],src[2]);	 	gmesa->buf++;		src += 3;	 }	 gmesa->bufCount = count+3; /* texture data + 3 values */	 offset += count;         FLUSH_DMA_BUFFER(gmesa);      }   #else	/* The UGLY way, and SLOW !, but the above sometimes causes	 * a DMA overrun error ??? FIXME ! */      CHECK_DMA_BUFFER(gmesa, 1);      WRITE(gmesa->buf, TextureDownloadOffset, 0);      for (i = 0; i < words; i++) { 	unsigned int data;	data = PACK_COLOR_565(src[0],src[1],src[2]); 	CHECK_DMA_BUFFER(gmesa, 1); 	WRITE(gmesa->buf, TextureData, data); 	src += 3;      }      FLUSH_DMA_BUFFER(gmesa);#endif   }   break;   case GL_RGBA:   case 4:   {      GLubyte  *src = (GLubyte *)image->Data;      if (level == 0)         t->TextureFormat |= TF_Compnents_4;	/* The UGLY way, and SLOW !, but the above sometimes causes	 * a DMA overrun error ??? FIXME ! */      CHECK_DMA_BUFFER(gmesa, 1);      WRITE(gmesa->buf, TextureDownloadOffset, 0);      for (i = 0; i < words; i++) { 	unsigned int data;	data = PACK_COLOR_8888(src[0],src[1],src[2],src[3]); 	CHECK_DMA_BUFFER(gmesa, 1); 	WRITE(gmesa->buf, TextureData, data); 	src += 4;      }      FLUSH_DMA_BUFFER(gmesa);   }   break;   case GL_LUMINANCE:   {      GLubyte  *src = (GLubyte *)image->Data;      if (level == 0)         t->TextureFormat |= TF_Compnents_1 | TF_OneCompFmt_Lum;	/* The UGLY way, and SLOW !, but the above sometimes causes	 * a DMA overrun error ??? FIXME ! */      CHECK_DMA_BUFFER(gmesa, 1);      WRITE(gmesa->buf, TextureDownloadOffset, 0);      for (i = 0; i < words; i++) { 	unsigned int data;	data = PACK_COLOR_888(src[0],src[0],src[0]); 	CHECK_DMA_BUFFER(gmesa, 1); 	WRITE(gmesa->buf, TextureData, data); 	src ++;      }      FLUSH_DMA_BUFFER(gmesa);   }   break;   case GL_INTENSITY:   {      GLubyte  *src = (GLubyte *)image->Data;      if (level == 0)         t->TextureFormat |= TF_Compnents_1 | TF_OneCompFmt_Intensity;	/* The UGLY way, and SLOW !, but the above sometimes causes	 * a DMA overrun error ??? FIXME ! */      CHECK_DMA_BUFFER(gmesa, 1);      WRITE(gmesa->buf, TextureDownloadOffset, 0);      for (i = 0; i < words; i++) { 	unsigned int data;	data = PACK_COLOR_8888(src[0],src[0],src[0],src[0]); 	CHECK_DMA_BUFFER(gmesa, 1); 	WRITE(gmesa->buf, TextureData, data); 	src ++;      }      FLUSH_DMA_BUFFER(gmesa);   }   break;   case GL_LUMINANCE_ALPHA:   {      GLubyte  *src = (GLubyte *)image->Data;      if (level == 0)         t->TextureFormat |= TF_Compnents_2;	/* The UGLY way, and SLOW !, but the above sometimes causes	 * a DMA overrun error ??? FIXME ! */      CHECK_DMA_BUFFER(gmesa, 1);      WRITE(gmesa->buf, TextureDownloadOffset, 0);      for (i = 0; i < words; i++) { 	unsigned int data;	data = PACK_COLOR_8888(src[0],src[0],src[0],src[1]); 	CHECK_DMA_BUFFER(gmesa, 1); 	WRITE(gmesa->buf, TextureData, data); 	src += 2;      }      FLUSH_DMA_BUFFER(gmesa);   }   break;   case GL_ALPHA:   {      GLubyte  *src = (GLubyte *)image->Data;      if (level == 0)         t->TextureFormat |= TF_Compnents_1 | TF_OneCompFmt_Alpha;	/* The UGLY way, and SLOW !, but the above sometimes causes	 * a DMA overrun error ??? FIXME ! */      CHECK_DMA_BUFFER(gmesa, 1);      WRITE(gmesa->buf, TextureDownloadOffset, 0);      for (i = 0; i < words; i++) { 	unsigned int data;	data = PACK_COLOR_8888(255,255,255,src[0]); 	CHECK_DMA_BUFFER(gmesa, 1); 	WRITE(gmesa->buf, TextureData, data); 	src += 1;      }      FLUSH_DMA_BUFFER(gmesa);   }   break;   /* TODO: Translate color indices *now*:    */   case GL_COLOR_INDEX:      {	 GLubyte *dst = (GLubyte *)(t->BufAddr + t->image[level].offset);	 GLubyte *src = (GLubyte *)image->Data;	 for (j = 0 ; j < image->Height ; j++, dst += t->Pitch) {	    for (i = 0 ; i < image->Width ; i++) {	       dst[i] = src[0];	       src += 1;	    }	 }      }   break;   default:      fprintf(stderr, "Not supported texture format %s\n",              _mesa_lookup_enum_by_nr(image->Format));   }   CHECK_DMA_BUFFER(gmesa, 2);   WRITE(gmesa->buf, WaitForCompletion, 0);   WRITE(gmesa->buf, LBWindowBase, gmesa->LBWindowBase);}void gammaPrintLocalLRU( gammaContextPtr gmesa ){   gammaTextureObjectPtr t;   int sz = 1 << (gmesa->gammaScreen->logTextureGranularity);   foreach( t, &gmesa->TexObjList ) {      if (!t->globj)	 fprintf(stderr, "Placeholder %d at %x sz %x\n",		 t->MemBlock->ofs / sz,		 t->MemBlock->ofs,		 t->MemBlock->size);      else	 fprintf(stderr, "Texture at %x sz %x\n",		 t->MemBlock->ofs,		 t->MemBlock->size);   }}void gammaPrintGlobalLRU( gammaContextPtr gmesa ){   int i, j;   GAMMATextureRegionPtr list = gmesa->sarea->texList;   for (i = 0, j = GAMMA_NR_TEX_REGIONS ; i < GAMMA_NR_TEX_REGIONS ; i++) {      fprintf(stderr, "list[%d] age %d next %d prev %d\n",	      j, list[j].age, list[j].next, list[j].prev);      j = list[j].next;      if (j == GAMMA_NR_TEX_REGIONS) break;   }   if (j != GAMMA_NR_TEX_REGIONS)      fprintf(stderr, "Loop detected in global LRU\n");}void gammaResetGlobalLRU( gammaContextPtr gmesa ){   GAMMATextureRegionPtr list = gmesa->sarea->texList;   int sz = 1 << gmesa->gammaScreen->logTextureGranularity;   int i;   /* (Re)initialize the global circular LRU list.  The last element    * in the array (GAMMA_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.    */   for (i = 0 ; (i+1) * sz <= gmesa->gammaScreen->textureSize ; i++) {      list[i].prev = i-1;      list[i].next = i+1;      list[i].age = 0;   }   i--;   list[0].prev = GAMMA_NR_TEX_REGIONS;   list[i].prev = i-1;   list[i].next = GAMMA_NR_TEX_REGIONS;   list[GAMMA_NR_TEX_REGIONS].prev = i;   list[GAMMA_NR_TEX_REGIONS].next = 0;   gmesa->sarea->texAge = 0;}void gammaUpdateTexLRU( gammaContextPtr gmesa, gammaTextureObjectPtr t ){   int i;   int logsz = gmesa->gammaScreen->logTextureGranularity;   int start = t->MemBlock->ofs >> logsz;   int end = (t->MemBlock->ofs + t->MemBlock->size - 1) >> logsz;   GAMMATextureRegionPtr list = gmesa->sarea->texList;   gmesa->texAge = ++gmesa->sarea->texAge;   /* Update our local LRU    */   move_to_head( &(gmesa->TexObjList), t );   /* Update the global LRU    */   for (i = start ; i <= end ; i++) {      list[i].in_use = 1;      list[i].age = gmesa->texAge;      /* 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 = GAMMA_NR_TEX_REGIONS;      list[i].next = list[GAMMA_NR_TEX_REGIONS].next;      list[(unsigned)list[GAMMA_NR_TEX_REGIONS].next].prev = i;      list[GAMMA_NR_TEX_REGIONS].next = i;   }}/* Called for every shared texture region which has increased in age * since we last held the lock. * * Figures out which of our textures have been ejected by other clients, * and pushes a placeholder texture onto the LRU list to represent * the other client's textures. */void gammaTexturesGone( gammaContextPtr gmesa,		       GLuint offset,		       GLuint size,		       GLuint in_use ){   gammaTextureObjectPtr t, tmp;   foreach_s ( t, tmp, &gmesa->TexObjList ) {      if (t->MemBlock->ofs >= offset + size ||	  t->MemBlock->ofs + t->MemBlock->size <= offset)	 continue;      /* It overlaps - kick it off.  Need to hold onto the currently bound       * objects, however.       */      gammaSwapOutTexObj( gmesa, t );   }   if (in_use) {      t = (gammaTextureObjectPtr) calloc(1,sizeof(*t));      if (!t) return;      t->MemBlock = mmAllocMem( gmesa->texHeap, size, 0, offset);      insert_at_head( &gmesa->TexObjList, t );   }   /* Reload any lost textures referenced by current vertex buffer.    */#if 0   if (gmesa->vertex_buffer) {      int i, j;      fprintf(stderr, "\n\nreload tex\n");      for (i = 0 ; i < gmesa->statenr ; i++) {	 for (j = 0 ; j < 2 ; j++) {	    gammaTextureObjectPtr t = gmesa->state_tex[j][i];	    if (t) {	       if (t->MemBlock == 0)		  gammaUploadTexImages( gmesa, t );	    }	 }      }      /* Hard to do this with the lock held:       *//*        GAMMA_FIREVERTICES( gmesa ); */   }#endif}/* This is called with the lock held.  May have to eject our own and/or * other client's texture objects to make room for the upload. */void gammaUploadTexImages( gammaContextPtr gmesa, gammaTextureObjectPtr t ){   int i;   int ofs;   int numLevels;   /* /fprintf(stderr, "%s\n", __FUNCTION__); */#if 0   LOCK_HARDWARE( gmesa );#endif   /* Do we need to eject LRU texture objects?    */   if (!t->MemBlock) {      while (1)      {	 t->MemBlock = mmAllocMem( gmesa->texHeap, t->totalSize, 12, 0 );	 if (t->MemBlock)	    break;	 if (gmesa->TexObjList.prev == gmesa->CurrentTexObj[0] ||	     gmesa->TexObjList.prev == gmesa->CurrentTexObj[1]) {  	    fprintf(stderr, "Hit bound texture in upload\n");	    gammaPrintLocalLRU( gmesa );	    return;	 }	 if (gmesa->TexObjList.prev == &(gmesa->TexObjList)) { 	    fprintf(stderr, "Failed to upload texture, sz %d\n", t->totalSize);	    mmDumpMemInfo( gmesa->texHeap );	    return;	 }	 gammaSwapOutTexObj( gmesa, gmesa->TexObjList.prev );      }      ofs = t->MemBlock->ofs;      t->BufAddr = (char *)(unsigned long)(gmesa->LBWindowBase + ofs); /* ??? */      if (t == gmesa->CurrentTexObj[0])	 gmesa->dirty |= GAMMA_UPLOAD_TEX0;#if 0      if (t == gmesa->CurrentTexObj[1])	 gmesa->dirty |= GAMMA_UPLOAD_TEX1;#endif      gammaUpdateTexLRU( gmesa, t );   }#if 0   if (gmesa->dirtyAge >= GET_DISPATCH_AGE(gmesa))      gammaWaitAgeLocked( gmesa, gmesa->dirtyAge );#endif   numLevels = t->lastLevel - t->firstLevel + 1;   for (i = 0 ; i < numLevels ; i++)      if (t->dirty_images & (1<<i))	 gammaUploadTexLevel( gmesa, t, i );   t->dirty_images = 0;#if 0   UNLOCK_HARDWARE( gmesa );#endif}

⌨️ 快捷键说明

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