📄 tdfx_texman.c
字号:
/* -*- mode: c; c-basic-offset: 3 -*- * * Copyright 2000 VA Linux Systems Inc., Fremont, California. * * 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 * the rights to use, copy, modify, merge, publish, distribute, sublicense, * 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 NONINFRINGEMENT. IN NO EVENT SHALL * VA LINUX SYSTEMS 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. *//* $XFree86: xc/lib/GL/mesa/src/drv/tdfx/tdfx_texman.c,v 1.5 2002/02/22 21:45:04 dawes Exp $ *//* * Original rewrite: * Gareth Hughes <gareth@valinux.com>, 29 Sep - 1 Oct 2000 * * Authors: * Gareth Hughes <gareth@valinux.com> * Brian Paul <brianp@valinux.com> * */#include "tdfx_context.h"#include "tdfx_tex.h"#include "tdfx_texman.h"#include "texobj.h"#include "hash.h"#define BAD_ADDRESS ((FxU32) -1)#if 0 /* DEBUG use *//* * Verify the consistancy of the texture memory manager. * This involves: * Traversing all texture objects and computing total memory used. * Traverse the free block list and computing total memory free. * Compare the total free and total used amounts to the total memory size. * Make various assertions about the results. */static voidVerifyFreeList(tdfxContextPtr fxMesa, FxU32 tmu){ struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared; struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData; tdfxMemRange *block; int prevStart = -1, prevEnd = -1; int totalFree = 0; int numObj = 0, numRes = 0; int totalUsed = 0; for (block = shared->tmFree[tmu]; block; block = block->next) { assert( block->endAddr > 0 ); assert( block->startAddr <= shared->totalTexMem[tmu] ); assert( block->endAddr <= shared->totalTexMem[tmu] ); assert( (int) block->startAddr > prevStart ); assert( (int) block->startAddr >= prevEnd ); prevStart = (int) block->startAddr; prevEnd = (int) block->endAddr; totalFree += (block->endAddr - block->startAddr); } assert(totalFree == shared->freeTexMem[tmu]); { struct _mesa_HashTable *textures = fxMesa->glCtx->Shared->TexObjects; GLuint id; for (id = _mesa_HashFirstEntry(textures); id; id = _mesa_HashNextEntry(textures, id)) { struct gl_texture_object *tObj = _mesa_lookup_texture(fxMesa->glCtx, id); tdfxTexInfo *ti = TDFX_TEXTURE_DATA(tObj); if (ti) { if (ti->isInTM) { numRes++; assert(ti->tm[0]); if (ti->tm[tmu]) totalUsed += (ti->tm[tmu]->endAddr - ti->tm[tmu]->startAddr); } else { assert(!ti->tm[0]); } } } } printf("totalFree: %d totalUsed: %d totalMem: %d #objs=%d #res=%d\n", shared->freeTexMem[tmu], totalUsed, shared->totalTexMem[tmu], numObj, numRes); assert(totalUsed + totalFree == shared->totalTexMem[tmu]);}static voiddump_texmem(tdfxContextPtr fxMesa){ struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared; struct _mesa_HashTable *textures = mesaShared->TexObjects; struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData; tdfxMemRange *r; FxU32 prev; GLuint id; printf("DUMP Objects:\n"); for (id = _mesa_HashFirstEntry(textures); id; id = _mesa_HashNextEntry(textures, id)) { struct gl_texture_object *obj = _mesa_lookup_texture(fxMesa->glCtx, id); tdfxTexInfo *info = TDFX_TEXTURE_DATA(obj); if (info && info->isInTM) { printf("Obj %8p: %4d info = %p\n", obj, obj->Name, info); printf(" isInTM=%d whichTMU=%d lastTimeUsed=%d\n", info->isInTM, info->whichTMU, info->lastTimeUsed); printf(" tm[0] = %p", info->tm[0]); assert(info->tm[0]); if (info->tm[0]) { printf(" tm startAddr = %d endAddr = %d", info->tm[0]->startAddr, info->tm[0]->endAddr); } printf("\n"); printf(" tm[1] = %p", info->tm[1]); if (info->tm[1]) { printf(" tm startAddr = %d endAddr = %d", info->tm[1]->startAddr, info->tm[1]->endAddr); } printf("\n"); } } VerifyFreeList(fxMesa, 0); VerifyFreeList(fxMesa, 1); printf("Free memory unit 0: %d bytes\n", shared->freeTexMem[0]); prev = 0; for (r = shared->tmFree[0]; r; r = r->next) { printf("%8p: start %8d end %8d size %8d gap %8d\n", r, r->startAddr, r->endAddr, r->endAddr - r->startAddr, r->startAddr - prev); prev = r->endAddr; } printf("Free memory unit 1: %d bytes\n", shared->freeTexMem[1]); prev = 0; for (r = shared->tmFree[1]; r; r = r->next) { printf("%8p: start %8d end %8d size %8d gap %8d\n", r, r->startAddr, r->endAddr, r->endAddr - r->startAddr, r->startAddr - prev); prev = r->endAddr; }}#endif#ifdef TEXSANITYstatic voidfubar(void){}/* * Sanity Check */static voidsanity(tdfxContextPtr fxMesa){ tdfxMemRange *tmp, *prev, *pos; prev = 0; tmp = fxMesa->tmFree[0]; while (tmp) { if (!tmp->startAddr && !tmp->endAddr) { fprintf(stderr, "Textures fubar\n"); fubar(); } if (tmp->startAddr >= tmp->endAddr) { fprintf(stderr, "Node fubar\n"); fubar(); } if (prev && (prev->startAddr >= tmp->startAddr || prev->endAddr > tmp->startAddr)) { fprintf(stderr, "Sorting fubar\n"); fubar(); } prev = tmp; tmp = tmp->next; } prev = 0; tmp = fxMesa->tmFree[1]; while (tmp) { if (!tmp->startAddr && !tmp->endAddr) { fprintf(stderr, "Textures fubar\n"); fubar(); } if (tmp->startAddr >= tmp->endAddr) { fprintf(stderr, "Node fubar\n"); fubar(); } if (prev && (prev->startAddr >= tmp->startAddr || prev->endAddr > tmp->startAddr)) { fprintf(stderr, "Sorting fubar\n"); fubar(); } prev = tmp; tmp = tmp->next; }}#endif/* * Allocate and initialize a new MemRange struct. * Try to allocate it from the pool of free MemRange nodes rather than malloc. */static tdfxMemRange *NewRangeNode(tdfxContextPtr fxMesa, FxU32 start, FxU32 end){ struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared; struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData; tdfxMemRange *result; _glthread_LOCK_MUTEX(mesaShared->Mutex); if (shared && shared->tmPool) { result = shared->tmPool; shared->tmPool = shared->tmPool->next; } else { result = MALLOC(sizeof(tdfxMemRange)); } _glthread_UNLOCK_MUTEX(mesaShared->Mutex); if (!result) { /*fprintf(stderr, "fxDriver: out of memory!\n");*/ return NULL; } result->startAddr = start; result->endAddr = end; result->next = NULL; return result;}/* * Initialize texture memory. * We take care of one or both TMU's here. */voidtdfxTMInit(tdfxContextPtr fxMesa){ if (!fxMesa->glCtx->Shared->DriverData) { const char *extensions; struct tdfxSharedState *shared = CALLOC_STRUCT(tdfxSharedState); if (!shared) return; LOCK_HARDWARE(fxMesa); extensions = fxMesa->Glide.grGetString(GR_EXTENSION); UNLOCK_HARDWARE(fxMesa); if (strstr(extensions, "TEXUMA")) { FxU32 start, end; shared->umaTexMemory = GL_TRUE; LOCK_HARDWARE(fxMesa); fxMesa->Glide.grEnable(GR_TEXTURE_UMA_EXT); start = fxMesa->Glide.grTexMinAddress(0); end = fxMesa->Glide.grTexMaxAddress(0); UNLOCK_HARDWARE(fxMesa); shared->totalTexMem[0] = end - start; shared->totalTexMem[1] = 0; shared->freeTexMem[0] = end - start; shared->freeTexMem[1] = 0; shared->tmFree[0] = NewRangeNode(fxMesa, start, end); shared->tmFree[1] = NULL; /*printf("UMA tex memory: %d\n", (int) (end - start));*/ } else { const int numTMUs = fxMesa->haveTwoTMUs ? 2 : 1; int tmu; shared->umaTexMemory = GL_FALSE; LOCK_HARDWARE(fxMesa); for (tmu = 0; tmu < numTMUs; tmu++) { FxU32 start = fxMesa->Glide.grTexMinAddress(tmu); FxU32 end = fxMesa->Glide.grTexMaxAddress(tmu); shared->totalTexMem[tmu] = end - start; shared->freeTexMem[tmu] = end - start; shared->tmFree[tmu] = NewRangeNode(fxMesa, start, end); /*printf("Split tex memory: %d\n", (int) (end - start));*/ } UNLOCK_HARDWARE(fxMesa); } shared->tmPool = NULL; fxMesa->glCtx->Shared->DriverData = shared; /*printf("Texture memory init UMA: %d\n", shared->umaTexMemory);*/ }}/* * Clean-up texture memory before destroying context. */voidtdfxTMClose(tdfxContextPtr fxMesa){ if (fxMesa->glCtx->Shared->RefCount == 1 && fxMesa->driDrawable) { /* refcount will soon go to zero, free our 3dfx stuff */ struct tdfxSharedState *shared = (struct tdfxSharedState *) fxMesa->glCtx->Shared->DriverData;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -