648649c0328206865f18841a5aeafe8cfa9084f0
1 /* $Id: fxtexman.c,v 1.17 2003/10/02 17:36:44 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 /* fxtexman.c - 3Dfx VooDoo texture memory functions */
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
, "%s: ERROR: out of memory!\n", __FUNCTION__
);
125 result
->startAddr
= start
;
126 result
->endAddr
= end
;
131 fxTMDeleteRangeNode(fxMesaContext fxMesa
, MemRange
* range
)
133 range
->next
= fxMesa
->tmPool
;
134 fxMesa
->tmPool
= range
;
138 fxTMUInit(fxMesaContext fxMesa
, int tmu
)
140 MemRange
*tmn
, *last
;
141 FxU32 start
, end
, blockstart
, blockend
, boundary
;
143 start
= grTexMinAddress(tmu
);
144 end
= grTexMaxAddress(tmu
);
146 boundary
= (fxMesa
->type
>= GR_SSTTYPE_Banshee
) ? (end
- start
) : FX_2MB_SPLIT
;
148 if (fxMesa
->verbose
) {
149 fprintf(stderr
, "Voodoo %s configuration:\n",
150 (tmu
== FX_TMU0
) ? "TMU0" : "TMU1");
151 fprintf(stderr
, "Voodoo Lower texture memory address (%u)\n",
152 (unsigned int) start
);
153 fprintf(stderr
, "Voodoo Higher texture memory address (%u)\n",
155 fprintf(stderr
, "Voodoo Splitting Texture memory in %luMB blocks:\n", boundary
>> 20);
158 fxMesa
->freeTexMem
[tmu
] = end
- start
;
159 fxMesa
->tmFree
[tmu
] = NULL
;
163 while (blockstart
< end
) {
164 if (blockstart
+ boundary
> end
)
167 blockend
= blockstart
+ boundary
;
170 fprintf(stderr
, "Voodoo %07u-%07u\n",
171 (unsigned int) blockstart
, (unsigned int) blockend
);
173 tmn
= fxTMNewRangeNode(fxMesa
, blockstart
, blockend
);
178 fxMesa
->tmFree
[tmu
] = tmn
;
181 blockstart
+= boundary
;
186 fxTMFindStartAddr(fxMesaContext fxMesa
, GLint tmu
, int size
)
188 MemRange
*prev
, *tmp
;
190 struct gl_texture_object
*obj
;
194 tmp
= fxMesa
->tmFree
[tmu
];
196 if (tmp
->endAddr
- tmp
->startAddr
>= size
) { /* Fits here */
197 result
= tmp
->startAddr
;
198 tmp
->startAddr
+= size
;
199 if (tmp
->startAddr
== tmp
->endAddr
) { /* Empty */
201 prev
->next
= tmp
->next
;
204 fxMesa
->tmFree
[tmu
] = tmp
->next
;
206 fxTMDeleteRangeNode(fxMesa
, tmp
);
208 fxMesa
->freeTexMem
[tmu
] -= size
;
214 /* No free space. Discard oldest */
215 if (TDFX_DEBUG
& VERBOSE_TEXTURE
) {
216 fprintf(stderr
, "%s: No free space. Discard oldest\n", __FUNCTION__
);
218 obj
= fxTMFindOldestObject(fxMesa
, tmu
);
220 fprintf(stderr
, "%s: ERROR: No space for texture\n", __FUNCTION__
);
223 fxTMMoveOutTM(fxMesa
, obj
);
229 fxTMRemoveRange(fxMesaContext fxMesa
, GLint tmu
, MemRange
* range
)
231 MemRange
*tmp
, *prev
;
232 FxU32 boundary
= (fxMesa
->type
>= GR_SSTTYPE_Banshee
) ? -1 : (FX_2MB_SPLIT
- 1);
234 if (range
->startAddr
== range
->endAddr
) {
235 fxTMDeleteRangeNode(fxMesa
, range
);
238 fxMesa
->freeTexMem
[tmu
] += range
->endAddr
- range
->startAddr
;
240 tmp
= fxMesa
->tmFree
[tmu
];
242 if (range
->startAddr
> tmp
->startAddr
) {
249 /* When we create the regions, we make a split at the 2MB boundary.
250 Now we have to make sure we don't join those 2MB boundary regions
251 back together again. */
254 if (range
->endAddr
== tmp
->startAddr
255 && tmp
->startAddr
& boundary
) {
257 tmp
->startAddr
= range
->startAddr
;
258 fxTMDeleteRangeNode(fxMesa
, range
);
263 if (prev
->endAddr
== range
->startAddr
264 && range
->startAddr
& boundary
) {
266 prev
->endAddr
= range
->endAddr
;
267 prev
->next
= range
->next
;
268 fxTMDeleteRangeNode(fxMesa
, range
);
274 fxMesa
->tmFree
[tmu
] = range
;
278 static struct gl_texture_object
*
279 fxTMFindOldestObject(fxMesaContext fxMesa
, int tmu
)
281 GLuint age
, old
, lasttime
, bindnumber
;
282 GLfloat lowestPriority
;
284 struct gl_texture_object
*obj
, *tmp
, *lowestPriorityObj
;
286 tmp
= fxMesa
->glCtx
->Shared
->TexObjectList
;
292 lowestPriorityObj
= NULL
;
293 lowestPriority
= 1.0F
;
295 bindnumber
= fxMesa
->texBindNumber
;
297 info
= fxTMGetTexInfo(tmp
);
299 if (info
&& info
->isInTM
&&
300 ((info
->whichTMU
== tmu
) || (info
->whichTMU
== FX_TMU_BOTH
) ||
301 (info
->whichTMU
== FX_TMU_SPLIT
))) {
302 lasttime
= info
->lastTimeUsed
;
304 if (lasttime
> bindnumber
)
305 age
= bindnumber
+ (UINT_MAX
- lasttime
+ 1); /* TO DO: check wrap around */
307 age
= bindnumber
- lasttime
;
314 /* examine priority */
315 if (obj
->Priority
< lowestPriority
) {
316 lowestPriority
= tmp
->Priority
;
317 lowestPriorityObj
= tmp
;
323 if (lowestPriority
< 1.0) {
324 ASSERT(lowestPriorityObj
);
325 if (TDFX_DEBUG
& VERBOSE_TEXTURE
) {
326 fprintf(stderr
, "fxTMFindOldestObject: %d pri=%f\n", lowestPriorityObj
->Name
, lowestPriority
);
328 return lowestPriorityObj
;
331 if (TDFX_DEBUG
& VERBOSE_TEXTURE
) {
332 fprintf(stderr
, "fxTMFindOldestObject: %d age=%d\n", obj
->Name
, old
);
339 fxTMAddObj(fxMesaContext fxMesa
,
340 struct gl_texture_object
*tObj
, GLint tmu
, int texmemsize
)
345 startAddr
= fxTMFindStartAddr(fxMesa
, tmu
, texmemsize
);
348 range
= fxTMNewRangeNode(fxMesa
, startAddr
, startAddr
+ texmemsize
);
352 /* External Functions */
355 fxTMMoveInTM_NoLock(fxMesaContext fxMesa
, struct gl_texture_object
*tObj
,
358 tfxTexInfo
*ti
= fxTMGetTexInfo(tObj
);
362 if (TDFX_DEBUG
& VERBOSE_DRIVER
) {
363 fprintf(stderr
, "%s(%d)\n", __FUNCTION__
, tObj
->Name
);
366 fxMesa
->stats
.reqTexUpload
++;
368 if (!ti
->validated
) {
369 fprintf(stderr
, "%s: INTERNAL ERROR: not validated\n", __FUNCTION__
);
375 if (ti
->whichTMU
== where
)
377 if (where
== FX_TMU_SPLIT
|| ti
->whichTMU
== FX_TMU_SPLIT
)
378 fxTMMoveOutTM_NoLock(fxMesa
, tObj
);
380 if (ti
->whichTMU
== FX_TMU_BOTH
)
386 if (TDFX_DEBUG
& (VERBOSE_DRIVER
| VERBOSE_TEXTURE
)) {
387 fprintf(stderr
, "%s: downloading %p (%d) in texture memory in %d\n",
388 __FUNCTION__
, (void *)tObj
, tObj
->Name
, where
);
391 ti
->whichTMU
= (FxU32
) where
;
396 texmemsize
= (int)grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH
, &(ti
->info
));
397 ti
->tm
[where
] = fxTMAddObj(fxMesa
, tObj
, where
, texmemsize
);
398 fxMesa
->stats
.memTexUpload
+= texmemsize
;
400 for (i
= FX_largeLodValue(ti
->info
), l
= ti
->minLevel
;
401 i
<= FX_smallLodValue(ti
->info
); i
++, l
++) {
402 struct gl_texture_image
*texImage
= tObj
->Image
[l
];
403 grTexDownloadMipMapLevel(where
,
404 ti
->tm
[where
]->startAddr
,
406 FX_largeLodLog2(ti
->info
),
407 FX_aspectRatioLog2(ti
->info
),
409 GR_MIPMAPLEVELMASK_BOTH
,
414 texmemsize
= (int)grTexTextureMemRequired(GR_MIPMAPLEVELMASK_ODD
, &(ti
->info
));
415 ti
->tm
[FX_TMU0
] = fxTMAddObj(fxMesa
, tObj
, FX_TMU0
, texmemsize
);
416 fxMesa
->stats
.memTexUpload
+= texmemsize
;
418 texmemsize
= (int)grTexTextureMemRequired(GR_MIPMAPLEVELMASK_EVEN
, &(ti
->info
));
419 ti
->tm
[FX_TMU1
] = fxTMAddObj(fxMesa
, tObj
, FX_TMU1
, texmemsize
);
420 fxMesa
->stats
.memTexUpload
+= texmemsize
;
422 for (i
= FX_largeLodValue(ti
->info
), l
= ti
->minLevel
;
423 i
<= FX_smallLodValue(ti
->info
); i
++, l
++) {
424 struct gl_texture_image
*texImage
= tObj
->Image
[l
];
426 grTexDownloadMipMapLevel(GR_TMU0
,
427 ti
->tm
[FX_TMU0
]->startAddr
,
429 FX_largeLodLog2(ti
->info
),
430 FX_aspectRatioLog2(ti
->info
),
432 GR_MIPMAPLEVELMASK_ODD
,
435 grTexDownloadMipMapLevel(GR_TMU1
,
436 ti
->tm
[FX_TMU1
]->startAddr
,
438 FX_largeLodLog2(ti
->info
),
439 FX_aspectRatioLog2(ti
->info
),
441 GR_MIPMAPLEVELMASK_EVEN
,
446 texmemsize
= (int)grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH
, &(ti
->info
));
447 ti
->tm
[FX_TMU0
] = fxTMAddObj(fxMesa
, tObj
, FX_TMU0
, texmemsize
);
448 fxMesa
->stats
.memTexUpload
+= texmemsize
;
450 /*texmemsize = (int)grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH, &(ti->info));*/
451 ti
->tm
[FX_TMU1
] = fxTMAddObj(fxMesa
, tObj
, FX_TMU1
, texmemsize
);
452 fxMesa
->stats
.memTexUpload
+= texmemsize
; /* ZZZ: required? */
454 for (i
= FX_largeLodValue(ti
->info
), l
= ti
->minLevel
;
455 i
<= FX_smallLodValue(ti
->info
); i
++, l
++) {
456 struct gl_texture_image
*texImage
= tObj
->Image
[l
];
457 grTexDownloadMipMapLevel(GR_TMU0
,
458 ti
->tm
[FX_TMU0
]->startAddr
,
460 FX_largeLodLog2(ti
->info
),
461 FX_aspectRatioLog2(ti
->info
),
463 GR_MIPMAPLEVELMASK_BOTH
,
466 grTexDownloadMipMapLevel(GR_TMU1
,
467 ti
->tm
[FX_TMU1
]->startAddr
,
469 FX_largeLodLog2(ti
->info
),
470 FX_aspectRatioLog2(ti
->info
),
472 GR_MIPMAPLEVELMASK_BOTH
,
477 fprintf(stderr
, "%s: INTERNAL ERROR: wrong tmu (%d)\n", __FUNCTION__
, where
);
482 fxMesa
->stats
.texUpload
++;
484 ti
->isInTM
= GL_TRUE
;
489 fxTMMoveInTM(fxMesaContext fxMesa
, struct gl_texture_object
*tObj
,
493 fxTMMoveInTM_NoLock(fxMesa
, tObj
, where
);
499 fxTMReloadMipMapLevel(fxMesaContext fxMesa
, struct gl_texture_object
*tObj
,
502 tfxTexInfo
*ti
= fxTMGetTexInfo(tObj
);
505 struct gl_texture_image
*texImage
= tObj
->Image
[level
];
506 tfxMipMapLevel
*mml
= FX_MIPMAP_DATA(texImage
);
508 if (TDFX_DEBUG
& VERBOSE_TEXTURE
) {
509 fprintf(stderr
, "fxTMReloadMipMapLevel(%p (%d), %d)\n", (void *)tObj
, tObj
->Name
, level
);
513 assert(mml
->width
> 0);
514 assert(mml
->height
> 0);
515 assert(mml
->glideFormat
> 0);
517 if (!ti
->validated
) {
518 fprintf(stderr
, "%s: INTERNAL ERROR: not validated\n", __FUNCTION__
);
523 tmu
= (int) ti
->whichTMU
;
524 fxTMMoveInTM(fxMesa
, tObj
, tmu
);
526 lodlevel
= ti
->info
.largeLodLog2
- (level
- ti
->minLevel
);
531 grTexDownloadMipMapLevel(tmu
,
532 ti
->tm
[tmu
]->startAddr
,
534 FX_largeLodLog2(ti
->info
),
535 FX_aspectRatioLog2(ti
->info
),
537 GR_MIPMAPLEVELMASK_BOTH
, texImage
->Data
);
540 grTexDownloadMipMapLevel(GR_TMU0
,
541 ti
->tm
[GR_TMU0
]->startAddr
,
543 FX_largeLodLog2(ti
->info
),
544 FX_aspectRatioLog2(ti
->info
),
546 GR_MIPMAPLEVELMASK_ODD
, texImage
->Data
);
548 grTexDownloadMipMapLevel(GR_TMU1
,
549 ti
->tm
[GR_TMU1
]->startAddr
,
551 FX_largeLodLog2(ti
->info
),
552 FX_aspectRatioLog2(ti
->info
),
554 GR_MIPMAPLEVELMASK_EVEN
, texImage
->Data
);
557 grTexDownloadMipMapLevel(GR_TMU0
,
558 ti
->tm
[GR_TMU0
]->startAddr
,
560 FX_largeLodLog2(ti
->info
),
561 FX_aspectRatioLog2(ti
->info
),
563 GR_MIPMAPLEVELMASK_BOTH
, texImage
->Data
);
565 grTexDownloadMipMapLevel(GR_TMU1
,
566 ti
->tm
[GR_TMU1
]->startAddr
,
568 FX_largeLodLog2(ti
->info
),
569 FX_aspectRatioLog2(ti
->info
),
571 GR_MIPMAPLEVELMASK_BOTH
, texImage
->Data
);
575 fprintf(stderr
, "%s: INTERNAL ERROR: wrong tmu (%d)\n", __FUNCTION__
, tmu
);
582 fxTMReloadSubMipMapLevel(fxMesaContext fxMesa
,
583 struct gl_texture_object
*tObj
,
584 GLint level
, GLint yoffset
, GLint height
)
586 tfxTexInfo
*ti
= fxTMGetTexInfo(tObj
);
588 unsigned short *data
;
590 struct gl_texture_image
*texImage
= tObj
->Image
[level
];
591 tfxMipMapLevel
*mml
= FX_MIPMAP_DATA(texImage
);
595 if (!ti
->validated
) {
596 fprintf(stderr
, "%s: INTERNAL ERROR: not validated\n", __FUNCTION__
);
601 tmu
= (int) ti
->whichTMU
;
602 fxTMMoveInTM(fxMesa
, tObj
, tmu
);
604 fxTexGetInfo(mml
->width
, mml
->height
,
605 &lodlevel
, NULL
, NULL
, NULL
, NULL
, NULL
);
607 if ((ti
->info
.format
== GR_TEXFMT_INTENSITY_8
) ||
608 (ti
->info
.format
== GR_TEXFMT_P_8
) ||
609 (ti
->info
.format
== GR_TEXFMT_ALPHA_8
))
610 data
= (GLushort
*) texImage
->Data
+ ((yoffset
* mml
->width
) >> 1);
612 data
= (GLushort
*) texImage
->Data
+ yoffset
* mml
->width
;
617 grTexDownloadMipMapLevelPartial(tmu
,
618 ti
->tm
[tmu
]->startAddr
,
619 FX_valueToLod(FX_lodToValue(lodlevel
)
621 FX_largeLodLog2(ti
->info
),
622 FX_aspectRatioLog2(ti
->info
),
624 GR_MIPMAPLEVELMASK_BOTH
, data
,
625 yoffset
, yoffset
+ height
- 1);
628 grTexDownloadMipMapLevelPartial(GR_TMU0
,
629 ti
->tm
[FX_TMU0
]->startAddr
,
630 FX_valueToLod(FX_lodToValue(lodlevel
)
632 FX_largeLodLog2(ti
->info
),
633 FX_aspectRatioLog2(ti
->info
),
635 GR_MIPMAPLEVELMASK_ODD
, data
,
636 yoffset
, yoffset
+ height
- 1);
638 grTexDownloadMipMapLevelPartial(GR_TMU1
,
639 ti
->tm
[FX_TMU1
]->startAddr
,
640 FX_valueToLod(FX_lodToValue(lodlevel
)
642 FX_largeLodLog2(ti
->info
),
643 FX_aspectRatioLog2(ti
->info
),
645 GR_MIPMAPLEVELMASK_EVEN
, data
,
646 yoffset
, yoffset
+ height
- 1);
649 grTexDownloadMipMapLevelPartial(GR_TMU0
,
650 ti
->tm
[FX_TMU0
]->startAddr
,
651 FX_valueToLod(FX_lodToValue(lodlevel
)
653 FX_largeLodLog2(ti
->info
),
654 FX_aspectRatioLog2(ti
->info
),
656 GR_MIPMAPLEVELMASK_BOTH
, data
,
657 yoffset
, yoffset
+ height
- 1);
659 grTexDownloadMipMapLevelPartial(GR_TMU1
,
660 ti
->tm
[FX_TMU1
]->startAddr
,
661 FX_valueToLod(FX_lodToValue(lodlevel
)
663 FX_largeLodLog2(ti
->info
),
664 FX_aspectRatioLog2(ti
->info
),
666 GR_MIPMAPLEVELMASK_BOTH
, data
,
667 yoffset
, yoffset
+ height
- 1);
670 fprintf(stderr
, "%s: INTERNAL ERROR: wrong tmu (%d)\n", __FUNCTION__
, tmu
);
677 fxTMMoveOutTM(fxMesaContext fxMesa
, struct gl_texture_object
*tObj
)
679 tfxTexInfo
*ti
= fxTMGetTexInfo(tObj
);
681 if (TDFX_DEBUG
& VERBOSE_DRIVER
) {
682 fprintf(stderr
, "%s(%p (%d))\n", __FUNCTION__
, (void *)tObj
, tObj
->Name
);
688 switch (ti
->whichTMU
) {
691 fxTMRemoveRange(fxMesa
, (int) ti
->whichTMU
, ti
->tm
[ti
->whichTMU
]);
695 fxTMRemoveRange(fxMesa
, FX_TMU0
, ti
->tm
[FX_TMU0
]);
696 fxTMRemoveRange(fxMesa
, FX_TMU1
, ti
->tm
[FX_TMU1
]);
699 fprintf(stderr
, "%s: INTERNAL ERROR: bad TMU (%ld)\n", __FUNCTION__
, ti
->whichTMU
);
704 ti
->isInTM
= GL_FALSE
;
705 ti
->whichTMU
= FX_TMU_NONE
;
709 fxTMFreeTexture(fxMesaContext fxMesa
, struct gl_texture_object
*tObj
)
711 tfxTexInfo
*ti
= fxTMGetTexInfo(tObj
);
714 if (TDFX_DEBUG
& VERBOSE_TEXTURE
) {
715 fprintf(stderr
, "%s(%p (%d))\n", __FUNCTION__
, (void *)tObj
, tObj
->Name
);
718 fxTMMoveOutTM(fxMesa
, tObj
);
720 for (i
= 0; i
< MAX_TEXTURE_LEVELS
; i
++) {
721 struct gl_texture_image
*texImage
= tObj
->Image
[i
];
723 if (texImage
->Data
) {
724 MESA_PBUFFER_FREE(texImage
->Data
);
725 texImage
->Data
= NULL
;
727 if (texImage
->DriverData
) {
728 FREE(texImage
->DriverData
);
729 texImage
->DriverData
= NULL
;
733 switch (ti
->whichTMU
) {
736 fxTMDeleteRangeNode(fxMesa
, ti
->tm
[ti
->whichTMU
]);
740 fxTMDeleteRangeNode(fxMesa
, ti
->tm
[FX_TMU0
]);
741 fxTMDeleteRangeNode(fxMesa
, ti
->tm
[FX_TMU1
]);
747 fxTMInit(fxMesaContext fxMesa
)
749 fxMesa
->texBindNumber
= 0;
752 fxTMUInit(fxMesa
, FX_TMU0
);
754 if (fxMesa
->haveTwoTMUs
)
755 fxTMUInit(fxMesa
, FX_TMU1
);
759 fxTMClose(fxMesaContext fxMesa
)
761 MemRange
*tmp
, *next
;
763 tmp
= fxMesa
->tmPool
;
769 tmp
= fxMesa
->tmFree
[FX_TMU0
];
775 if (fxMesa
->haveTwoTMUs
) {
776 tmp
= fxMesa
->tmFree
[FX_TMU1
];
786 fxTMRestoreTextures_NoLock(fxMesaContext ctx
)
789 struct gl_texture_object
*tObj
;
792 tObj
= ctx
->glCtx
->Shared
->TexObjectList
;
794 ti
= fxTMGetTexInfo(tObj
);
795 if (ti
&& ti
->isInTM
) {
796 for (i
= 0; i
< MAX_TEXTURE_UNITS
; i
++)
797 if (ctx
->glCtx
->Texture
.Unit
[i
]._Current
== tObj
) {
798 /* Force the texture onto the board, as it could be in use */
799 where
= ti
->whichTMU
;
800 fxTMMoveOutTM_NoLock(ctx
, tObj
);
801 fxTMMoveInTM_NoLock(ctx
, tObj
, where
);
804 if (i
== MAX_TEXTURE_UNITS
) /* Mark the texture as off the board */
805 fxTMMoveOutTM_NoLock(ctx
, tObj
);
815 * Need this to provide at least one external definition.
818 extern int gl_fx_dummy_function_texman(void);
820 gl_fx_dummy_function_texman(void)