1
/* -*- mode: c; c-basic-offset: 3 -*-
3
* Copyright 2000 VA Linux Systems Inc., Fremont, California.
7
* Permission is hereby granted, free of charge, to any person obtaining a
8
* copy of this software and associated documentation files (the "Software"),
9
* to deal in the Software without restriction, including without limitation
10
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11
* and/or sell copies of the Software, and to permit persons to whom the
12
* Software is furnished to do so, subject to the following conditions:
14
* The above copyright notice and this permission notice (including the next
15
* paragraph) shall be included in all copies or substantial portions of the
18
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21
* VA LINUX SYSTEMS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
23
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
/* $XFree86: xc/lib/GL/mesa/src/drv/tdfx/tdfx_texman.c,v 1.5 2002/02/22 21:45:04 dawes Exp $ */
30
* Gareth Hughes <gareth@valinux.com>, 29 Sep - 1 Oct 2000
33
* Gareth Hughes <gareth@valinux.com>
34
* Brian Paul <brianp@valinux.com>
38
#include "tdfx_context.h"
40
#include "tdfx_texman.h"
43
#define BAD_ADDRESS ((FxU32) -1)
48
* Verify the consistancy of the texture memory manager.
50
* Traversing all texture objects and computing total memory used.
51
* Traverse the free block list and computing total memory free.
52
* Compare the total free and total used amounts to the total memory size.
53
* Make various assertions about the results.
56
VerifyFreeList(tdfxContextPtr fxMesa, FxU32 tmu)
58
struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared;
59
struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData;
61
int prevStart = -1, prevEnd = -1;
63
int numObj = 0, numRes = 0;
66
for (block = shared->tmFree[tmu]; block; block = block->next) {
67
assert( block->endAddr > 0 );
68
assert( block->startAddr <= shared->totalTexMem[tmu] );
69
assert( block->endAddr <= shared->totalTexMem[tmu] );
70
assert( (int) block->startAddr > prevStart );
71
assert( (int) block->startAddr >= prevEnd );
72
prevStart = (int) block->startAddr;
73
prevEnd = (int) block->endAddr;
74
totalFree += (block->endAddr - block->startAddr);
76
assert(totalFree == shared->freeTexMem[tmu]);
79
struct gl_texture_object *obj;
80
for (obj = mesaShared->TexObjectList; obj; obj = obj->Next) {
81
tdfxTexInfo *ti = TDFX_TEXTURE_DATA(obj);
88
totalUsed += (ti->tm[tmu]->endAddr - ti->tm[tmu]->startAddr);
97
printf("totalFree: %d totalUsed: %d totalMem: %d #objs=%d #res=%d\n",
98
shared->freeTexMem[tmu], totalUsed, shared->totalTexMem[tmu],
101
assert(totalUsed + totalFree == shared->totalTexMem[tmu]);
106
dump_texmem(tdfxContextPtr fxMesa)
108
struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared;
109
struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData;
110
struct gl_texture_object *oldestObj, *obj, *lowestPriorityObj;
114
printf("DUMP Objects:\n");
115
for (obj = mesaShared->TexObjectList; obj; obj = obj->Next) {
116
tdfxTexInfo *info = TDFX_TEXTURE_DATA(obj);
118
if (info && info->isInTM) {
119
printf("Obj %8p: %4d info = %p\n", obj, obj->Name, info);
121
printf(" isInTM=%d whichTMU=%d lastTimeUsed=%d\n",
122
info->isInTM, info->whichTMU, info->lastTimeUsed);
123
printf(" tm[0] = %p", info->tm[0]);
126
printf(" tm startAddr = %d endAddr = %d",
127
info->tm[0]->startAddr,
128
info->tm[0]->endAddr);
131
printf(" tm[1] = %p", info->tm[1]);
133
printf(" tm startAddr = %d endAddr = %d",
134
info->tm[1]->startAddr,
135
info->tm[1]->endAddr);
141
VerifyFreeList(fxMesa, 0);
142
VerifyFreeList(fxMesa, 1);
144
printf("Free memory unit 0: %d bytes\n", shared->freeTexMem[0]);
146
for (r = shared->tmFree[0]; r; r = r->next) {
147
printf("%8p: start %8d end %8d size %8d gap %8d\n", r, r->startAddr, r->endAddr, r->endAddr - r->startAddr, r->startAddr - prev);
151
printf("Free memory unit 1: %d bytes\n", shared->freeTexMem[1]);
153
for (r = shared->tmFree[1]; r; r = r->next) {
154
printf("%8p: start %8d end %8d size %8d gap %8d\n", r, r->startAddr, r->endAddr, r->endAddr - r->startAddr, r->startAddr - prev);
173
sanity(tdfxContextPtr fxMesa)
175
tdfxMemRange *tmp, *prev, *pos;
178
tmp = fxMesa->tmFree[0];
180
if (!tmp->startAddr && !tmp->endAddr) {
181
fprintf(stderr, "Textures fubar\n");
184
if (tmp->startAddr >= tmp->endAddr) {
185
fprintf(stderr, "Node fubar\n");
188
if (prev && (prev->startAddr >= tmp->startAddr ||
189
prev->endAddr > tmp->startAddr)) {
190
fprintf(stderr, "Sorting fubar\n");
197
tmp = fxMesa->tmFree[1];
199
if (!tmp->startAddr && !tmp->endAddr) {
200
fprintf(stderr, "Textures fubar\n");
203
if (tmp->startAddr >= tmp->endAddr) {
204
fprintf(stderr, "Node fubar\n");
207
if (prev && (prev->startAddr >= tmp->startAddr ||
208
prev->endAddr > tmp->startAddr)) {
209
fprintf(stderr, "Sorting fubar\n");
223
* Allocate and initialize a new MemRange struct.
224
* Try to allocate it from the pool of free MemRange nodes rather than malloc.
226
static tdfxMemRange *
227
NewRangeNode(tdfxContextPtr fxMesa, FxU32 start, FxU32 end)
229
struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared;
230
struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData;
231
tdfxMemRange *result;
233
_glthread_LOCK_MUTEX(mesaShared->Mutex);
234
if (shared && shared->tmPool) {
235
result = shared->tmPool;
236
shared->tmPool = shared->tmPool->next;
239
result = MALLOC(sizeof(tdfxMemRange));
242
_glthread_UNLOCK_MUTEX(mesaShared->Mutex);
245
/*fprintf(stderr, "fxDriver: out of memory!\n");*/
249
result->startAddr = start;
250
result->endAddr = end;
258
* Initialize texture memory.
259
* We take care of one or both TMU's here.
262
tdfxTMInit(tdfxContextPtr fxMesa)
264
if (!fxMesa->glCtx->Shared->DriverData) {
265
const char *extensions;
266
struct tdfxSharedState *shared = CALLOC_STRUCT(tdfxSharedState);
270
LOCK_HARDWARE(fxMesa);
271
extensions = fxMesa->Glide.grGetString(GR_EXTENSION);
272
UNLOCK_HARDWARE(fxMesa);
273
if (strstr(extensions, "TEXUMA")) {
275
shared->umaTexMemory = GL_TRUE;
276
LOCK_HARDWARE(fxMesa);
277
fxMesa->Glide.grEnable(GR_TEXTURE_UMA_EXT);
278
start = fxMesa->Glide.grTexMinAddress(0);
279
end = fxMesa->Glide.grTexMaxAddress(0);
280
UNLOCK_HARDWARE(fxMesa);
281
shared->totalTexMem[0] = end - start;
282
shared->totalTexMem[1] = 0;
283
shared->freeTexMem[0] = end - start;
284
shared->freeTexMem[1] = 0;
285
shared->tmFree[0] = NewRangeNode(fxMesa, start, end);
286
shared->tmFree[1] = NULL;
287
/*printf("UMA tex memory: %d\n", (int) (end - start));*/
290
const int numTMUs = fxMesa->haveTwoTMUs ? 2 : 1;
292
shared->umaTexMemory = GL_FALSE;
293
LOCK_HARDWARE(fxMesa);
294
for (tmu = 0; tmu < numTMUs; tmu++) {
295
FxU32 start = fxMesa->Glide.grTexMinAddress(tmu);
296
FxU32 end = fxMesa->Glide.grTexMaxAddress(tmu);
297
shared->totalTexMem[tmu] = end - start;
298
shared->freeTexMem[tmu] = end - start;
299
shared->tmFree[tmu] = NewRangeNode(fxMesa, start, end);
300
/*printf("Split tex memory: %d\n", (int) (end - start));*/
302
UNLOCK_HARDWARE(fxMesa);
305
shared->tmPool = NULL;
306
fxMesa->glCtx->Shared->DriverData = shared;
307
/*printf("Texture memory init UMA: %d\n", shared->umaTexMemory);*/
313
* Clean-up texture memory before destroying context.
316
tdfxTMClose(tdfxContextPtr fxMesa)
318
if (fxMesa->glCtx->Shared->RefCount == 1 && fxMesa->driDrawable) {
319
/* refcount will soon go to zero, free our 3dfx stuff */
320
struct tdfxSharedState *shared = (struct tdfxSharedState *) fxMesa->glCtx->Shared->DriverData;
322
const int numTMUs = fxMesa->haveTwoTMUs ? 2 : 1;
324
tdfxMemRange *tmp, *next;
326
/* Deallocate the pool of free tdfxMemRange nodes */
327
tmp = shared->tmPool;
334
/* Delete the texture memory block tdfxMemRange nodes */
335
for (tmu = 0; tmu < numTMUs; tmu++) {
336
tmp = shared->tmFree[tmu];
345
fxMesa->glCtx->Shared->DriverData = NULL;
352
* Delete a tdfxMemRange struct.
353
* We keep a linked list of free/available tdfxMemRange structs to
354
* avoid extra malloc/free calls.
358
DeleteRangeNode_NoLock(struct TdfxSharedState *shared, tdfxMemRange *range)
360
/* insert at head of list */
361
range->next = shared->tmPool;
362
shared->tmPool = range;
366
#define DELETE_RANGE_NODE(shared, range) \
367
(range)->next = (shared)->tmPool; \
368
(shared)->tmPool = (range)
373
* When we've run out of texture memory we have to throw out an
374
* existing texture to make room for the new one. This function
375
* determins the texture to throw out.
377
static struct gl_texture_object *
378
FindOldestObject(tdfxContextPtr fxMesa, FxU32 tmu)
380
const GLuint bindnumber = fxMesa->texBindNumber;
381
struct gl_texture_object *oldestObj, *obj, *lowestPriorityObj;
382
GLfloat lowestPriority;
388
lowestPriority = 1.0F;
389
lowestPriorityObj = NULL;
391
for (obj = fxMesa->glCtx->Shared->TexObjectList; obj; obj = obj->Next) {
392
tdfxTexInfo *info = TDFX_TEXTURE_DATA(obj);
394
if (info && info->isInTM &&
395
((info->whichTMU == tmu) || (info->whichTMU == TDFX_TMU_BOTH) ||
396
(info->whichTMU == TDFX_TMU_SPLIT))) {
397
GLuint age, lasttime;
400
lasttime = info->lastTimeUsed;
402
if (lasttime > bindnumber)
403
age = bindnumber + (UINT_MAX - lasttime + 1); /* TO DO: check wrap around */
405
age = bindnumber - lasttime;
407
if (age >= oldestAge) {
412
/* examine priority */
413
if (obj->Priority < lowestPriority) {
414
lowestPriority = obj->Priority;
415
lowestPriorityObj = obj;
420
if (lowestPriority < 1.0) {
421
ASSERT(lowestPriorityObj);
423
printf("discard %d pri=%f\n", lowestPriorityObj->Name, lowestPriority);
425
return lowestPriorityObj;
429
printf("discard %d age=%d\n", oldestObj->Name, oldestAge);
438
FlushTexMemory(tdfxContextPtr fxMesa)
440
struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared;
441
struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData;
442
struct gl_texture_object *obj;
444
for (obj = mesaShared->TexObjectList; obj; obj = obj->Next) {
445
if (obj->RefCount < 2) {
446
/* don't flush currently bound textures */
447
tdfxTMMoveOutTM_NoLock(fxMesa, obj);
455
* Find the address (offset?) at which we can store a new texture.
456
* <tmu> is the texture unit.
457
* <size> is the texture size in bytes.
460
FindStartAddr(tdfxContextPtr fxMesa, FxU32 tmu, FxU32 size)
462
struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared;
463
struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData;
464
tdfxMemRange *prev, *block;
467
int discardedCount = 0;
468
#define MAX_DISCARDS 10
471
if (shared->umaTexMemory) {
472
assert(tmu == TDFX_TMU0);
475
_glthread_LOCK_MUTEX(mesaShared->Mutex);
478
block = shared->tmFree[tmu];
480
if (block->endAddr - block->startAddr >= size) {
481
/* The texture will fit here */
482
result = block->startAddr;
483
block->startAddr += size;
484
if (block->startAddr == block->endAddr) {
485
/* Remove this node since it's empty */
487
prev->next = block->next;
490
shared->tmFree[tmu] = block->next;
492
DELETE_RANGE_NODE(shared, block);
494
shared->freeTexMem[tmu] -= size;
495
_glthread_UNLOCK_MUTEX(mesaShared->Mutex);
501
/* We failed to find a block large enough to accomodate <size> bytes.
502
* Find the oldest texObject and free it.
506
if (discardedCount > MAX_DISCARDS + 1) {
507
_mesa_problem(NULL, "tdfx driver: extreme texmem fragmentation");
508
_glthread_UNLOCK_MUTEX(mesaShared->Mutex);
511
else if (discardedCount > MAX_DISCARDS) {
512
/* texture memory is probably really fragmented, flush it */
513
FlushTexMemory(fxMesa);
518
struct gl_texture_object *obj = FindOldestObject(fxMesa, tmu);
520
tdfxTMMoveOutTM_NoLock(fxMesa, obj);
521
fxMesa->stats.texSwaps++;
524
_mesa_problem(NULL, "tdfx driver: extreme texmem fragmentation");
525
_glthread_UNLOCK_MUTEX(mesaShared->Mutex);
531
/* never get here, but play it safe */
532
_glthread_UNLOCK_MUTEX(mesaShared->Mutex);
538
* Remove the given tdfxMemRange node from hardware texture memory.
541
RemoveRange_NoLock(tdfxContextPtr fxMesa, FxU32 tmu, tdfxMemRange *range)
543
struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared;
544
struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData;
545
tdfxMemRange *block, *prev;
547
if (shared->umaTexMemory) {
548
assert(tmu == TDFX_TMU0);
554
if (range->startAddr == range->endAddr) {
555
DELETE_RANGE_NODE(shared, range);
558
shared->freeTexMem[tmu] += range->endAddr - range->startAddr;
560
/* find position in linked list to insert this tdfxMemRange node */
562
block = shared->tmFree[tmu];
564
assert(range->startAddr != block->startAddr);
565
if (range->startAddr > block->startAddr) {
574
/* Insert the free block, combine with adjacent blocks when possible */
577
if (range->endAddr == block->startAddr) {
579
block->startAddr = range->startAddr;
580
DELETE_RANGE_NODE(shared, range);
585
if (prev->endAddr == range->startAddr) {
587
prev->endAddr = range->endAddr;
588
prev->next = range->next;
589
DELETE_RANGE_NODE(shared, range);
596
shared->tmFree[tmu] = range;
603
RemoveRange(tdfxContextPtr fxMesa, FxU32 tmu, tdfxMemRange *range)
605
struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared;
606
_glthread_LOCK_MUTEX(mesaShared->Mutex);
607
RemoveRange_NoLock(fxMesa, tmu, range);
608
_glthread_UNLOCK_MUTEX(mesaShared->Mutex);
614
* Allocate space for a texture image.
615
* <tmu> is the texture unit
616
* <texmemsize> is the number of bytes to allocate
618
static tdfxMemRange *
619
AllocTexMem(tdfxContextPtr fxMesa, FxU32 tmu, FxU32 texmemsize)
622
startAddr = FindStartAddr(fxMesa, tmu, texmemsize);
623
if (startAddr == BAD_ADDRESS) {
625
sprintf(err, "AllocTexMem returned NULL! tmu=%d texmemsize=%d\n",
626
(int) tmu, (int) texmemsize);
627
_mesa_problem(fxMesa->glCtx, err);
632
range = NewRangeNode(fxMesa, startAddr, startAddr + texmemsize);
639
* Download (copy) the given texture data (all mipmap levels) into the
640
* Voodoo's texture memory.
641
* The texture memory must have already been allocated.
644
tdfxTMDownloadTexture(tdfxContextPtr fxMesa, struct gl_texture_object *tObj)
651
ti = TDFX_TEXTURE_DATA(tObj);
653
targetTMU = ti->whichTMU;
658
if (ti->tm[targetTMU]) {
659
for (l = ti->minLevel; l <= ti->maxLevel
660
&& tObj->Image[l]->Data; l++) {
661
GrLOD_t glideLod = ti->info.largeLodLog2 - l + tObj->BaseLevel;
662
fxMesa->Glide.grTexDownloadMipMapLevel(targetTMU,
663
ti->tm[targetTMU]->startAddr,
665
ti->info.largeLodLog2,
666
ti->info.aspectRatioLog2,
668
GR_MIPMAPLEVELMASK_BOTH,
669
tObj->Image[l]->Data);
674
if (ti->tm[TDFX_TMU0] && ti->tm[TDFX_TMU1]) {
675
for (l = ti->minLevel; l <= ti->maxLevel
676
&& tObj->Image[l]->Data; l++) {
677
GrLOD_t glideLod = ti->info.largeLodLog2 - l + tObj->BaseLevel;
678
fxMesa->Glide.grTexDownloadMipMapLevel(GR_TMU0,
679
ti->tm[TDFX_TMU0]->startAddr,
681
ti->info.largeLodLog2,
682
ti->info.aspectRatioLog2,
684
GR_MIPMAPLEVELMASK_ODD,
685
tObj->Image[l]->Data);
687
fxMesa->Glide.grTexDownloadMipMapLevel(GR_TMU1,
688
ti->tm[TDFX_TMU1]->startAddr,
690
ti->info.largeLodLog2,
691
ti->info.aspectRatioLog2,
693
GR_MIPMAPLEVELMASK_EVEN,
694
tObj->Image[l]->Data);
699
if (ti->tm[TDFX_TMU0] && ti->tm[TDFX_TMU1]) {
700
for (l = ti->minLevel; l <= ti->maxLevel
701
&& tObj->Image[l]->Data; l++) {
702
GrLOD_t glideLod = ti->info.largeLodLog2 - l + tObj->BaseLevel;
703
fxMesa->Glide.grTexDownloadMipMapLevel(GR_TMU0,
704
ti->tm[TDFX_TMU0]->startAddr,
706
ti->info.largeLodLog2,
707
ti->info.aspectRatioLog2,
709
GR_MIPMAPLEVELMASK_BOTH,
710
tObj->Image[l]->Data);
712
fxMesa->Glide.grTexDownloadMipMapLevel(GR_TMU1,
713
ti->tm[TDFX_TMU1]->startAddr,
715
ti->info.largeLodLog2,
716
ti->info.aspectRatioLog2,
718
GR_MIPMAPLEVELMASK_BOTH,
719
tObj->Image[l]->Data);
724
_mesa_problem(NULL, "error in tdfxTMDownloadTexture: bad tmu");
731
tdfxTMReloadMipMapLevel(GLcontext *ctx, struct gl_texture_object *tObj,
734
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
735
tdfxTexInfo *ti = TDFX_TEXTURE_DATA(tObj);
740
glideLod = ti->info.largeLodLog2 - level + tObj->BaseLevel;
743
LOCK_HARDWARE(fxMesa);
748
fxMesa->Glide.grTexDownloadMipMapLevel(tmu,
749
ti->tm[tmu]->startAddr,
751
ti->info.largeLodLog2,
752
ti->info.aspectRatioLog2,
754
GR_MIPMAPLEVELMASK_BOTH,
755
tObj->Image[level]->Data);
758
fxMesa->Glide.grTexDownloadMipMapLevel(GR_TMU0,
759
ti->tm[GR_TMU0]->startAddr,
761
ti->info.largeLodLog2,
762
ti->info.aspectRatioLog2,
764
GR_MIPMAPLEVELMASK_ODD,
765
tObj->Image[level]->Data);
767
fxMesa->Glide.grTexDownloadMipMapLevel(GR_TMU1,
768
ti->tm[GR_TMU1]->startAddr,
770
ti->info.largeLodLog2,
771
ti->info.aspectRatioLog2,
773
GR_MIPMAPLEVELMASK_EVEN,
774
tObj->Image[level]->Data);
777
fxMesa->Glide.grTexDownloadMipMapLevel(GR_TMU0,
778
ti->tm[GR_TMU0]->startAddr,
780
ti->info.largeLodLog2,
781
ti->info.aspectRatioLog2,
783
GR_MIPMAPLEVELMASK_BOTH,
784
tObj->Image[level]->Data);
786
fxMesa->Glide.grTexDownloadMipMapLevel(GR_TMU1,
787
ti->tm[GR_TMU1]->startAddr,
789
ti->info.largeLodLog2,
790
ti->info.aspectRatioLog2,
792
GR_MIPMAPLEVELMASK_BOTH,
793
tObj->Image[level]->Data);
797
_mesa_problem(ctx, "error in tdfxTMReloadMipMapLevel(): wrong tmu");
800
UNLOCK_HARDWARE(fxMesa);
805
* Allocate space for the given texture in texture memory then
806
* download (copy) it into that space.
809
tdfxTMMoveInTM_NoLock( tdfxContextPtr fxMesa, struct gl_texture_object *tObj,
812
tdfxTexInfo *ti = TDFX_TEXTURE_DATA(tObj);
815
fxMesa->stats.reqTexUpload++;
818
if (ti->whichTMU == targetTMU)
820
if (targetTMU == TDFX_TMU_SPLIT || ti->whichTMU == TDFX_TMU_SPLIT) {
821
tdfxTMMoveOutTM_NoLock(fxMesa, tObj);
824
if (ti->whichTMU == TDFX_TMU_BOTH)
826
targetTMU = TDFX_TMU_BOTH;
830
ti->whichTMU = targetTMU;
835
texmemsize = fxMesa->Glide.grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH,
837
ti->tm[targetTMU] = AllocTexMem(fxMesa, targetTMU, texmemsize);
840
texmemsize = fxMesa->Glide.grTexTextureMemRequired(GR_MIPMAPLEVELMASK_ODD,
842
ti->tm[TDFX_TMU0] = AllocTexMem(fxMesa, TDFX_TMU0, texmemsize);
843
if (ti->tm[TDFX_TMU0])
844
fxMesa->stats.memTexUpload += texmemsize;
846
texmemsize = fxMesa->Glide.grTexTextureMemRequired(GR_MIPMAPLEVELMASK_EVEN,
848
ti->tm[TDFX_TMU1] = AllocTexMem(fxMesa, TDFX_TMU1, texmemsize);
851
texmemsize = fxMesa->Glide.grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH,
853
ti->tm[TDFX_TMU0] = AllocTexMem(fxMesa, TDFX_TMU0, texmemsize);
854
if (ti->tm[TDFX_TMU0])
855
fxMesa->stats.memTexUpload += texmemsize;
857
texmemsize = fxMesa->Glide.grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH,
859
ti->tm[TDFX_TMU1] = AllocTexMem(fxMesa, TDFX_TMU1, texmemsize);
862
_mesa_problem(NULL, "error in tdfxTMMoveInTM() -> bad tmu (%d)");
866
ti->reloadImages = GL_TRUE;
867
ti->isInTM = GL_TRUE;
869
fxMesa->stats.texUpload++;
874
* Move the given texture out of hardware texture memory.
875
* This deallocates the texture's memory space.
878
tdfxTMMoveOutTM_NoLock( tdfxContextPtr fxMesa, struct gl_texture_object *tObj )
880
struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared;
881
struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData;
882
tdfxTexInfo *ti = TDFX_TEXTURE_DATA(tObj);
884
if (MESA_VERBOSE & VERBOSE_DRIVER) {
885
fprintf(stderr, "fxmesa: fxTMMoveOutTM(%p (%d))\n", tObj, tObj->Name);
889
VerifyFreeList(fxMesa, 0);
890
VerifyFreeList(fxMesa, 1);
893
if (!ti || !ti->isInTM)
896
switch (ti->whichTMU) {
899
RemoveRange_NoLock(fxMesa, ti->whichTMU, ti->tm[ti->whichTMU]);
903
assert(!shared->umaTexMemory);
904
RemoveRange_NoLock(fxMesa, TDFX_TMU0, ti->tm[TDFX_TMU0]);
905
RemoveRange_NoLock(fxMesa, TDFX_TMU1, ti->tm[TDFX_TMU1]);
908
_mesa_problem(NULL, "tdfx driver: bad tmu in tdfxTMMOveOutTM()");
912
ti->isInTM = GL_FALSE;
915
ti->whichTMU = TDFX_TMU_NONE;
918
VerifyFreeList(fxMesa, 0);
919
VerifyFreeList(fxMesa, 1);
925
* Called via glDeleteTexture to delete a texture object.
928
tdfxTMFreeTexture(tdfxContextPtr fxMesa, struct gl_texture_object *tObj)
930
tdfxTexInfo *ti = TDFX_TEXTURE_DATA(tObj);
932
tdfxTMMoveOutTM(fxMesa, tObj);
934
tObj->DriverData = NULL;
937
VerifyFreeList(fxMesa, 0);
938
VerifyFreeList(fxMesa, 1);
945
* After a context switch this function will be called to restore
946
* texture memory for the new context.
948
void tdfxTMRestoreTextures_NoLock( tdfxContextPtr fxMesa )
950
GLcontext *ctx = fxMesa->glCtx;
951
struct gl_texture_object *tObj;
954
for ( tObj = ctx->Shared->TexObjectList ; tObj ; tObj = tObj->Next ) {
955
tdfxTexInfo *ti = TDFX_TEXTURE_DATA( tObj );
956
if ( ti && ti->isInTM ) {
957
for ( i = 0 ; i < MAX_TEXTURE_UNITS ; i++ ) {
958
if ( ctx->Texture.Unit[i]._Current == tObj ) {
959
tdfxTMDownloadTexture( fxMesa, tObj );
963
if ( i == MAX_TEXTURE_UNITS ) {
964
tdfxTMMoveOutTM_NoLock( fxMesa, tObj );
969
VerifyFreeList(fxMesa, 0);
970
VerifyFreeList(fxMesa, 1);