2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
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 shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 /* fxtexman.c - 3Dfx VooDoo texture memory functions */
47 static FxU32 texBoundMask
;
49 #define FX_2MB_SPLIT 0x200000
51 static struct gl_texture_object
*fxTMFindOldestObject(fxMesaContext fxMesa
,
63 sanity(fxMesaContext fxMesa
)
65 MemRange
*tmp
, *prev
, *pos
;
68 tmp
= fxMesa
->tmFree
[0];
70 if (!tmp
->startAddr
&& !tmp
->endAddr
) {
71 fprintf(stderr
, "Textures fubar\n");
74 if (tmp
->startAddr
>= tmp
->endAddr
) {
75 fprintf(stderr
, "Node fubar\n");
78 if (prev
&& (prev
->startAddr
>= tmp
->startAddr
||
79 prev
->endAddr
> tmp
->startAddr
)) {
80 fprintf(stderr
, "Sorting fubar\n");
87 tmp
= fxMesa
->tmFree
[1];
89 if (!tmp
->startAddr
&& !tmp
->endAddr
) {
90 fprintf(stderr
, "Textures fubar\n");
93 if (tmp
->startAddr
>= tmp
->endAddr
) {
94 fprintf(stderr
, "Node fubar\n");
97 if (prev
&& (prev
->startAddr
>= tmp
->startAddr
||
98 prev
->endAddr
> tmp
->startAddr
)) {
99 fprintf(stderr
, "Sorting fubar\n");
109 fxTMNewRangeNode(fxMesaContext fxMesa
, FxU32 start
, FxU32 end
)
111 MemRange
*result
= 0;
113 if (fxMesa
->tmPool
) {
114 result
= fxMesa
->tmPool
;
115 fxMesa
->tmPool
= fxMesa
->tmPool
->next
;
118 if (!(result
= MALLOC(sizeof(MemRange
)))) {
119 fprintf(stderr
, "fxTMNewRangeNode: ERROR: out of memory!\n");
124 result
->startAddr
= start
;
125 result
->endAddr
= end
;
130 #define fxTMDeleteRangeNode(fxMesa, range) \
132 range->next = fxMesa->tmPool; \
133 fxMesa->tmPool = range; \
137 fxTMDeleteRangeNode(fxMesaContext fxMesa
, MemRange
* range
)
139 range
->next
= fxMesa
->tmPool
;
140 fxMesa
->tmPool
= range
;
145 fxTMUInit(fxMesaContext fxMesa
, int tmu
)
147 MemRange
*tmn
, *last
;
148 FxU32 start
, end
, blockstart
, blockend
, chunk
;
150 start
= grTexMinAddress(tmu
);
151 end
= grTexMaxAddress(tmu
);
153 chunk
= (fxMesa
->type
>= GR_SSTTYPE_Banshee
) ? (end
- start
) : FX_2MB_SPLIT
;
155 if (fxMesa
->verbose
) {
156 fprintf(stderr
, "Voodoo TMU%d configuration:\n", tmu
);
159 fxMesa
->freeTexMem
[tmu
] = end
- start
;
160 fxMesa
->tmFree
[tmu
] = NULL
;
164 while (blockstart
< end
) {
165 if (blockstart
+ chunk
> end
)
168 blockend
= blockstart
+ chunk
;
171 fprintf(stderr
, "Voodoo %08u-%08u\n",
172 (unsigned int) blockstart
, (unsigned int) blockend
);
174 tmn
= fxTMNewRangeNode(fxMesa
, blockstart
, blockend
);
181 fxMesa
->tmFree
[tmu
] = tmn
;
189 fxTMFindStartAddr(fxMesaContext fxMesa
, GLint tmu
, int size
)
191 MemRange
*prev
, *tmp
;
193 struct gl_texture_object
*obj
;
195 if (fxMesa
->HaveTexUma
) {
201 tmp
= fxMesa
->tmFree
[tmu
];
203 if (tmp
->endAddr
- tmp
->startAddr
>= size
) { /* Fits here */
204 result
= tmp
->startAddr
;
205 tmp
->startAddr
+= size
;
206 if (tmp
->startAddr
== tmp
->endAddr
) { /* Empty */
208 prev
->next
= tmp
->next
;
211 fxMesa
->tmFree
[tmu
] = tmp
->next
;
213 fxTMDeleteRangeNode(fxMesa
, tmp
);
215 fxMesa
->freeTexMem
[tmu
] -= size
;
221 /* No free space. Discard oldest */
222 if (TDFX_DEBUG
& VERBOSE_TEXTURE
) {
223 fprintf(stderr
, "fxTMFindStartAddr: No free space. Discard oldest\n");
225 obj
= fxTMFindOldestObject(fxMesa
, tmu
);
227 fprintf(stderr
, "fxTMFindStartAddr: ERROR: No space for texture\n");
230 fxTMMoveOutTM(fxMesa
, obj
);
235 int fxTMCheckStartAddr (fxMesaContext fxMesa
, GLint tmu
, tfxTexInfo
*ti
)
240 if (fxMesa
->HaveTexUma
) {
244 size
= grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH
, &(ti
->info
));
246 tmp
= fxMesa
->tmFree
[tmu
];
248 if (tmp
->endAddr
- tmp
->startAddr
>= size
) { /* Fits here */
258 fxTMRemoveRange(fxMesaContext fxMesa
, GLint tmu
, MemRange
* range
)
260 MemRange
*tmp
, *prev
;
262 if (fxMesa
->HaveTexUma
) {
266 if (range
->startAddr
== range
->endAddr
) {
267 fxTMDeleteRangeNode(fxMesa
, range
);
270 fxMesa
->freeTexMem
[tmu
] += range
->endAddr
- range
->startAddr
;
272 tmp
= fxMesa
->tmFree
[tmu
];
274 if (range
->startAddr
> tmp
->startAddr
) {
281 /* When we create the regions, we make a split at the 2MB boundary.
282 Now we have to make sure we don't join those 2MB boundary regions
283 back together again. */
286 if (range
->endAddr
== tmp
->startAddr
287 && tmp
->startAddr
& texBoundMask
) {
289 tmp
->startAddr
= range
->startAddr
;
290 fxTMDeleteRangeNode(fxMesa
, range
);
295 if (prev
->endAddr
== range
->startAddr
296 && range
->startAddr
& texBoundMask
) {
298 prev
->endAddr
= range
->endAddr
;
299 prev
->next
= range
->next
;
300 fxTMDeleteRangeNode(fxMesa
, range
);
306 fxMesa
->tmFree
[tmu
] = range
;
310 static struct gl_texture_object
*
311 fxTMFindOldestObject(fxMesaContext fxMesa
, int tmu
)
313 GLuint age
, old
, lasttime
, bindnumber
;
314 GLfloat lowestPriority
;
315 struct gl_texture_object
*obj
, *lowestPriorityObj
;
316 struct _mesa_HashTable
*textures
= fxMesa
->glCtx
->Shared
->TexObjects
;
319 if (!_mesa_HashFirstEntry(textures
))
325 lowestPriorityObj
= NULL
;
326 lowestPriority
= 1.0F
;
328 bindnumber
= fxMesa
->texBindNumber
;
330 for (id
= _mesa_HashFirstEntry(textures
);
332 id
= _mesa_HashNextEntry(textures
, id
)) {
333 struct gl_texture_object
*tmp
334 = (struct gl_texture_object
*) _mesa_HashLookup(textures
, id
);
335 tfxTexInfo
*info
= fxTMGetTexInfo(tmp
);
337 if (info
&& info
->isInTM
&&
338 ((info
->whichTMU
== tmu
) ||
339 (info
->whichTMU
== FX_TMU_BOTH
) ||
340 (info
->whichTMU
== FX_TMU_SPLIT
) ||
344 lasttime
= info
->lastTimeUsed
;
346 if (lasttime
> bindnumber
)
347 age
= bindnumber
+ (UINT_MAX
- lasttime
+ 1); /* TO DO: check wrap around */
349 age
= bindnumber
- lasttime
;
356 /* examine priority */
357 if (tmp
->Priority
< lowestPriority
) {
358 lowestPriority
= tmp
->Priority
;
359 lowestPriorityObj
= tmp
;
364 if (lowestPriorityObj
!= NULL
) {
365 if (TDFX_DEBUG
& VERBOSE_TEXTURE
) {
366 fprintf(stderr
, "fxTMFindOldestObject: %d pri=%f\n", lowestPriorityObj
->Name
, lowestPriority
);
368 return lowestPriorityObj
;
371 if (TDFX_DEBUG
& VERBOSE_TEXTURE
) {
373 fprintf(stderr
, "fxTMFindOldestObject: %d age=%d\n", obj
->Name
, old
);
381 fxTMAddObj(fxMesaContext fxMesa
,
382 struct gl_texture_object
*tObj
, GLint tmu
, int texmemsize
)
387 startAddr
= fxTMFindStartAddr(fxMesa
, tmu
, texmemsize
);
390 range
= fxTMNewRangeNode(fxMesa
, startAddr
, startAddr
+ texmemsize
);
394 /* External Functions */
397 fxTMMoveInTM_NoLock(fxMesaContext fxMesa
, struct gl_texture_object
*tObj
,
400 tfxTexInfo
*ti
= fxTMGetTexInfo(tObj
);
404 if (TDFX_DEBUG
& VERBOSE_DRIVER
) {
405 fprintf(stderr
, "fxTMMoveInTM_NoLock(%d)\n", tObj
->Name
);
408 fxMesa
->stats
.reqTexUpload
++;
410 if (!ti
->validated
) {
411 fprintf(stderr
, "fxTMMoveInTM_NoLock: INTERNAL ERROR: not validated\n");
417 if (ti
->whichTMU
== where
)
419 if (where
== FX_TMU_SPLIT
|| ti
->whichTMU
== FX_TMU_SPLIT
)
420 fxTMMoveOutTM_NoLock(fxMesa
, tObj
);
422 if (ti
->whichTMU
== FX_TMU_BOTH
)
428 if (TDFX_DEBUG
& (VERBOSE_DRIVER
| VERBOSE_TEXTURE
)) {
429 fprintf(stderr
, "fxTMMoveInTM_NoLock: downloading %p (%d) in texture memory in %d\n",
430 (void *)tObj
, tObj
->Name
, where
);
433 ti
->whichTMU
= (FxU32
) where
;
438 texmemsize
= (int)grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH
, &(ti
->info
));
439 ti
->tm
[where
] = fxTMAddObj(fxMesa
, tObj
, where
, texmemsize
);
440 fxMesa
->stats
.memTexUpload
+= texmemsize
;
442 for (i
= FX_largeLodValue(ti
->info
), l
= ti
->minLevel
;
443 i
<= FX_smallLodValue(ti
->info
); i
++, l
++) {
444 struct gl_texture_image
*texImage
= tObj
->Image
[0][l
];
445 grTexDownloadMipMapLevel(where
,
446 ti
->tm
[where
]->startAddr
,
448 FX_largeLodLog2(ti
->info
),
449 FX_aspectRatioLog2(ti
->info
),
451 GR_MIPMAPLEVELMASK_BOTH
,
456 texmemsize
= (int)grTexTextureMemRequired(GR_MIPMAPLEVELMASK_ODD
, &(ti
->info
));
457 ti
->tm
[FX_TMU0
] = fxTMAddObj(fxMesa
, tObj
, FX_TMU0
, texmemsize
);
458 fxMesa
->stats
.memTexUpload
+= texmemsize
;
460 texmemsize
= (int)grTexTextureMemRequired(GR_MIPMAPLEVELMASK_EVEN
, &(ti
->info
));
461 ti
->tm
[FX_TMU1
] = fxTMAddObj(fxMesa
, tObj
, FX_TMU1
, texmemsize
);
462 fxMesa
->stats
.memTexUpload
+= texmemsize
;
464 for (i
= FX_largeLodValue(ti
->info
), l
= ti
->minLevel
;
465 i
<= FX_smallLodValue(ti
->info
); i
++, l
++) {
466 struct gl_texture_image
*texImage
= tObj
->Image
[0][l
];
468 grTexDownloadMipMapLevel(GR_TMU0
,
469 ti
->tm
[FX_TMU0
]->startAddr
,
471 FX_largeLodLog2(ti
->info
),
472 FX_aspectRatioLog2(ti
->info
),
474 GR_MIPMAPLEVELMASK_ODD
,
477 grTexDownloadMipMapLevel(GR_TMU1
,
478 ti
->tm
[FX_TMU1
]->startAddr
,
480 FX_largeLodLog2(ti
->info
),
481 FX_aspectRatioLog2(ti
->info
),
483 GR_MIPMAPLEVELMASK_EVEN
,
488 texmemsize
= (int)grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH
, &(ti
->info
));
489 ti
->tm
[FX_TMU0
] = fxTMAddObj(fxMesa
, tObj
, FX_TMU0
, texmemsize
);
490 fxMesa
->stats
.memTexUpload
+= texmemsize
;
492 /*texmemsize = (int)grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH, &(ti->info));*/
493 ti
->tm
[FX_TMU1
] = fxTMAddObj(fxMesa
, tObj
, FX_TMU1
, texmemsize
);
494 fxMesa
->stats
.memTexUpload
+= texmemsize
;
496 for (i
= FX_largeLodValue(ti
->info
), l
= ti
->minLevel
;
497 i
<= FX_smallLodValue(ti
->info
); i
++, l
++) {
498 struct gl_texture_image
*texImage
= tObj
->Image
[0][l
];
499 grTexDownloadMipMapLevel(GR_TMU0
,
500 ti
->tm
[FX_TMU0
]->startAddr
,
502 FX_largeLodLog2(ti
->info
),
503 FX_aspectRatioLog2(ti
->info
),
505 GR_MIPMAPLEVELMASK_BOTH
,
508 grTexDownloadMipMapLevel(GR_TMU1
,
509 ti
->tm
[FX_TMU1
]->startAddr
,
511 FX_largeLodLog2(ti
->info
),
512 FX_aspectRatioLog2(ti
->info
),
514 GR_MIPMAPLEVELMASK_BOTH
,
519 fprintf(stderr
, "fxTMMoveInTM_NoLock: INTERNAL ERROR: wrong tmu (%d)\n", where
);
524 fxMesa
->stats
.texUpload
++;
526 ti
->isInTM
= GL_TRUE
;
531 fxTMMoveInTM(fxMesaContext fxMesa
, struct gl_texture_object
*tObj
,
535 fxTMMoveInTM_NoLock(fxMesa
, tObj
, where
);
541 fxTMReloadMipMapLevel(fxMesaContext fxMesa
, struct gl_texture_object
*tObj
,
544 tfxTexInfo
*ti
= fxTMGetTexInfo(tObj
);
547 struct gl_texture_image
*texImage
= tObj
->Image
[0][level
];
548 tfxMipMapLevel
*mml
= FX_MIPMAP_DATA(texImage
);
550 if (TDFX_DEBUG
& VERBOSE_TEXTURE
) {
551 fprintf(stderr
, "fxTMReloadMipMapLevel(%p (%d), %d)\n", (void *)tObj
, tObj
->Name
, level
);
555 assert(mml
->width
> 0);
556 assert(mml
->height
> 0);
557 assert(mml
->glideFormat
> 0);
560 if (!ti
->validated
) {
561 fprintf(stderr
, "fxTMReloadMipMapLevel: INTERNAL ERROR: not validated\n");
566 tmu
= (int) ti
->whichTMU
;
567 fxMesa
->stats
.reqTexUpload
++;
568 fxMesa
->stats
.texUpload
++;
570 lodlevel
= ti
->info
.largeLodLog2
- (level
- ti
->minLevel
);
575 grTexDownloadMipMapLevel(tmu
,
576 ti
->tm
[tmu
]->startAddr
,
578 FX_largeLodLog2(ti
->info
),
579 FX_aspectRatioLog2(ti
->info
),
581 GR_MIPMAPLEVELMASK_BOTH
, texImage
->Data
);
584 grTexDownloadMipMapLevel(GR_TMU0
,
585 ti
->tm
[GR_TMU0
]->startAddr
,
587 FX_largeLodLog2(ti
->info
),
588 FX_aspectRatioLog2(ti
->info
),
590 GR_MIPMAPLEVELMASK_ODD
, texImage
->Data
);
592 grTexDownloadMipMapLevel(GR_TMU1
,
593 ti
->tm
[GR_TMU1
]->startAddr
,
595 FX_largeLodLog2(ti
->info
),
596 FX_aspectRatioLog2(ti
->info
),
598 GR_MIPMAPLEVELMASK_EVEN
, texImage
->Data
);
601 grTexDownloadMipMapLevel(GR_TMU0
,
602 ti
->tm
[GR_TMU0
]->startAddr
,
604 FX_largeLodLog2(ti
->info
),
605 FX_aspectRatioLog2(ti
->info
),
607 GR_MIPMAPLEVELMASK_BOTH
, texImage
->Data
);
609 grTexDownloadMipMapLevel(GR_TMU1
,
610 ti
->tm
[GR_TMU1
]->startAddr
,
612 FX_largeLodLog2(ti
->info
),
613 FX_aspectRatioLog2(ti
->info
),
615 GR_MIPMAPLEVELMASK_BOTH
, texImage
->Data
);
619 fprintf(stderr
, "fxTMReloadMipMapLevel: INTERNAL ERROR: wrong tmu (%d)\n", tmu
);
626 fxTMReloadSubMipMapLevel(fxMesaContext fxMesa
,
627 struct gl_texture_object
*tObj
,
628 GLint level
, GLint yoffset
, GLint height
)
630 tfxTexInfo
*ti
= fxTMGetTexInfo(tObj
);
632 unsigned short *data
;
634 struct gl_texture_image
*texImage
= tObj
->Image
[0][level
];
635 tfxMipMapLevel
*mml
= FX_MIPMAP_DATA(texImage
);
639 if (!ti
->validated
) {
640 fprintf(stderr
, "fxTMReloadSubMipMapLevel: INTERNAL ERROR: not validated\n");
645 tmu
= (int) ti
->whichTMU
;
646 fxTMMoveInTM(fxMesa
, tObj
, tmu
);
648 fxTexGetInfo(mml
->width
, mml
->height
,
649 &lodlevel
, NULL
, NULL
, NULL
, NULL
, NULL
);
651 if ((ti
->info
.format
== GR_TEXFMT_INTENSITY_8
) ||
652 (ti
->info
.format
== GR_TEXFMT_P_8
) ||
653 (ti
->info
.format
== GR_TEXFMT_ALPHA_8
))
654 data
= (GLushort
*) texImage
->Data
+ ((yoffset
* mml
->width
) >> 1);
656 data
= (GLushort
*) texImage
->Data
+ yoffset
* mml
->width
;
661 grTexDownloadMipMapLevelPartial(tmu
,
662 ti
->tm
[tmu
]->startAddr
,
663 FX_valueToLod(FX_lodToValue(lodlevel
)
665 FX_largeLodLog2(ti
->info
),
666 FX_aspectRatioLog2(ti
->info
),
668 GR_MIPMAPLEVELMASK_BOTH
, data
,
669 yoffset
, yoffset
+ height
- 1);
672 grTexDownloadMipMapLevelPartial(GR_TMU0
,
673 ti
->tm
[FX_TMU0
]->startAddr
,
674 FX_valueToLod(FX_lodToValue(lodlevel
)
676 FX_largeLodLog2(ti
->info
),
677 FX_aspectRatioLog2(ti
->info
),
679 GR_MIPMAPLEVELMASK_ODD
, data
,
680 yoffset
, yoffset
+ height
- 1);
682 grTexDownloadMipMapLevelPartial(GR_TMU1
,
683 ti
->tm
[FX_TMU1
]->startAddr
,
684 FX_valueToLod(FX_lodToValue(lodlevel
)
686 FX_largeLodLog2(ti
->info
),
687 FX_aspectRatioLog2(ti
->info
),
689 GR_MIPMAPLEVELMASK_EVEN
, data
,
690 yoffset
, yoffset
+ height
- 1);
693 grTexDownloadMipMapLevelPartial(GR_TMU0
,
694 ti
->tm
[FX_TMU0
]->startAddr
,
695 FX_valueToLod(FX_lodToValue(lodlevel
)
697 FX_largeLodLog2(ti
->info
),
698 FX_aspectRatioLog2(ti
->info
),
700 GR_MIPMAPLEVELMASK_BOTH
, data
,
701 yoffset
, yoffset
+ height
- 1);
703 grTexDownloadMipMapLevelPartial(GR_TMU1
,
704 ti
->tm
[FX_TMU1
]->startAddr
,
705 FX_valueToLod(FX_lodToValue(lodlevel
)
707 FX_largeLodLog2(ti
->info
),
708 FX_aspectRatioLog2(ti
->info
),
710 GR_MIPMAPLEVELMASK_BOTH
, data
,
711 yoffset
, yoffset
+ height
- 1);
714 fprintf(stderr
, "fxTMReloadSubMipMapLevel: INTERNAL ERROR: wrong tmu (%d)\n", tmu
);
721 fxTMMoveOutTM(fxMesaContext fxMesa
, struct gl_texture_object
*tObj
)
723 tfxTexInfo
*ti
= fxTMGetTexInfo(tObj
);
725 if (TDFX_DEBUG
& VERBOSE_DRIVER
) {
726 fprintf(stderr
, "fxTMMoveOutTM(%p (%d))\n", (void *)tObj
, tObj
->Name
);
732 switch (ti
->whichTMU
) {
735 fxTMRemoveRange(fxMesa
, (int) ti
->whichTMU
, ti
->tm
[ti
->whichTMU
]);
739 fxTMRemoveRange(fxMesa
, FX_TMU0
, ti
->tm
[FX_TMU0
]);
740 fxTMRemoveRange(fxMesa
, FX_TMU1
, ti
->tm
[FX_TMU1
]);
743 fprintf(stderr
, "fxTMMoveOutTM: INTERNAL ERROR: bad TMU (%ld)\n", ti
->whichTMU
);
748 ti
->isInTM
= GL_FALSE
;
749 ti
->whichTMU
= FX_TMU_NONE
;
753 fxTMFreeTexture(fxMesaContext fxMesa
, struct gl_texture_object
*tObj
)
755 tfxTexInfo
*ti
= fxTMGetTexInfo(tObj
);
758 if (TDFX_DEBUG
& VERBOSE_TEXTURE
) {
759 fprintf(stderr
, "fxTMFreeTexture(%p (%d))\n", (void *)tObj
, tObj
->Name
);
762 fxTMMoveOutTM(fxMesa
, tObj
);
764 for (i
= 0; i
< MAX_TEXTURE_LEVELS
; i
++) {
765 struct gl_texture_image
*texImage
= tObj
->Image
[0][i
];
767 if (texImage
->DriverData
) {
768 FREE(texImage
->DriverData
);
769 texImage
->DriverData
= NULL
;
773 switch (ti
->whichTMU
) {
776 fxTMDeleteRangeNode(fxMesa
, ti
->tm
[ti
->whichTMU
]);
780 fxTMDeleteRangeNode(fxMesa
, ti
->tm
[FX_TMU0
]);
781 fxTMDeleteRangeNode(fxMesa
, ti
->tm
[FX_TMU1
]);
787 fxTMInit(fxMesaContext fxMesa
)
789 fxMesa
->texBindNumber
= 0;
792 if (fxMesa
->HaveTexUma
) {
793 grEnable(GR_TEXTURE_UMA_EXT
);
796 fxTMUInit(fxMesa
, FX_TMU0
);
798 if (!fxMesa
->HaveTexUma
&& fxMesa
->haveTwoTMUs
)
799 fxTMUInit(fxMesa
, FX_TMU1
);
801 texBoundMask
= (fxMesa
->type
>= GR_SSTTYPE_Banshee
) ? -1 : (FX_2MB_SPLIT
- 1);
805 fxTMClose(fxMesaContext fxMesa
)
807 MemRange
*tmp
, *next
;
809 tmp
= fxMesa
->tmPool
;
815 tmp
= fxMesa
->tmFree
[FX_TMU0
];
821 if (fxMesa
->haveTwoTMUs
) {
822 tmp
= fxMesa
->tmFree
[FX_TMU1
];
832 fxTMRestoreTextures_NoLock(fxMesaContext ctx
)
834 struct _mesa_HashTable
*textures
= ctx
->glCtx
->Shared
->TexObjects
;
837 for (id
= _mesa_HashFirstEntry(textures
);
839 id
= _mesa_HashNextEntry(textures
, id
)) {
840 struct gl_texture_object
*tObj
841 = (struct gl_texture_object
*) _mesa_HashLookup(textures
, id
);
842 tfxTexInfo
*ti
= fxTMGetTexInfo(tObj
);
843 if (ti
&& ti
->isInTM
) {
845 for (i
= 0; i
< MAX_TEXTURE_UNITS
; i
++) {
846 if (ctx
->glCtx
->Texture
.Unit
[i
]._Current
== tObj
) {
847 /* Force the texture onto the board, as it could be in use */
848 int where
= ti
->whichTMU
;
849 fxTMMoveOutTM_NoLock(ctx
, tObj
);
850 fxTMMoveInTM_NoLock(ctx
, tObj
, where
);
854 if (i
== MAX_TEXTURE_UNITS
) /* Mark the texture as off the board */
855 fxTMMoveOutTM_NoLock(ctx
, tObj
);
864 * Need this to provide at least one external definition.
867 extern int gl_fx_dummy_function_texman(void);
869 gl_fx_dummy_function_texman(void)