DOS and glide driver updates from Daniel Borca
[mesa.git] / src / mesa / drivers / glide / fxtexman.c
1 /* $Id: fxtexman.c,v 1.16 2003/08/19 15:52:53 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 4.0
6 *
7 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
8 *
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:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
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.
25 */
26
27 /* Authors:
28 * David Bucciarelli
29 * Brian Paul
30 * Daryll Strauss
31 * Keith Whitwell
32 * Daniel Borca
33 * Hiroshi Morii
34 */
35
36 /* fxtexman.c - 3Dfx VooDoo texture memory functions */
37
38
39 #ifdef HAVE_CONFIG_H
40 #include "conf.h"
41 #endif
42
43 #if defined(FX)
44
45 #include "fxdrv.h"
46
47 int texSwaps = 0;
48
49 #define FX_2MB_SPLIT 0x200000
50
51 static struct gl_texture_object *fxTMFindOldestObject(fxMesaContext fxMesa,
52 int tmu);
53
54
55 #ifdef TEXSANITY
56 static void
57 fubar()
58 {
59 }
60
61 /* Sanity Check */
62 static void
63 sanity(fxMesaContext fxMesa)
64 {
65 MemRange *tmp, *prev, *pos;
66
67 prev = 0;
68 tmp = fxMesa->tmFree[0];
69 while (tmp) {
70 if (!tmp->startAddr && !tmp->endAddr) {
71 fprintf(stderr, "Textures fubar\n");
72 fubar();
73 }
74 if (tmp->startAddr >= tmp->endAddr) {
75 fprintf(stderr, "Node fubar\n");
76 fubar();
77 }
78 if (prev && (prev->startAddr >= tmp->startAddr ||
79 prev->endAddr > tmp->startAddr)) {
80 fprintf(stderr, "Sorting fubar\n");
81 fubar();
82 }
83 prev = tmp;
84 tmp = tmp->next;
85 }
86 prev = 0;
87 tmp = fxMesa->tmFree[1];
88 while (tmp) {
89 if (!tmp->startAddr && !tmp->endAddr) {
90 fprintf(stderr, "Textures fubar\n");
91 fubar();
92 }
93 if (tmp->startAddr >= tmp->endAddr) {
94 fprintf(stderr, "Node fubar\n");
95 fubar();
96 }
97 if (prev && (prev->startAddr >= tmp->startAddr ||
98 prev->endAddr > tmp->startAddr)) {
99 fprintf(stderr, "Sorting fubar\n");
100 fubar();
101 }
102 prev = tmp;
103 tmp = tmp->next;
104 }
105 }
106 #endif
107
108 static MemRange *
109 fxTMNewRangeNode(fxMesaContext fxMesa, FxU32 start, FxU32 end)
110 {
111 MemRange *result = 0;
112
113 if (fxMesa->tmPool) {
114 result = fxMesa->tmPool;
115 fxMesa->tmPool = fxMesa->tmPool->next;
116 }
117 else {
118 if (!(result = MALLOC(sizeof(MemRange)))) {
119 fprintf(stderr, "fxDriver: out of memory!\n");
120 fxCloseHardware();
121 exit(-1);
122 }
123 }
124 result->startAddr = start;
125 result->endAddr = end;
126 return result;
127 }
128
129 static void
130 fxTMDeleteRangeNode(fxMesaContext fxMesa, MemRange * range)
131 {
132 range->next = fxMesa->tmPool;
133 fxMesa->tmPool = range;
134 }
135
136 static void
137 fxTMUInit(fxMesaContext fxMesa, int tmu)
138 {
139 MemRange *tmn, *last;
140 FxU32 start, end, blockstart, blockend;
141
142 start = grTexMinAddress(tmu);
143 end = grTexMaxAddress(tmu);
144
145 if (fxMesa->verbose) {
146 fprintf(stderr, "Voodoo %s configuration:\n",
147 (tmu == FX_TMU0) ? "TMU0" : "TMU1");
148 fprintf(stderr, "Voodoo Lower texture memory address (%u)\n",
149 (unsigned int) start);
150 fprintf(stderr, "Voodoo Higher texture memory address (%u)\n",
151 (unsigned int) end);
152 fprintf(stderr, "Voodoo Splitting Texture memory in 2b blocks:\n");
153 }
154
155 fxMesa->freeTexMem[tmu] = end - start;
156 fxMesa->tmFree[tmu] = NULL;
157
158 last = 0;
159 blockstart = start;
160 while (blockstart < end) {
161 if (blockstart + FX_2MB_SPLIT > end)
162 blockend = end;
163 else
164 blockend = blockstart + FX_2MB_SPLIT;
165
166 if (fxMesa->verbose)
167 fprintf(stderr, "Voodoo %07u-%07u\n",
168 (unsigned int) blockstart, (unsigned int) blockend);
169
170 tmn = fxTMNewRangeNode(fxMesa, blockstart, blockend);
171 tmn->next = 0;
172
173 if (last)
174 last->next = tmn;
175 else
176 fxMesa->tmFree[tmu] = tmn;
177 last = tmn;
178
179 blockstart += FX_2MB_SPLIT;
180 }
181 }
182
183 static int
184 fxTMFindStartAddr(fxMesaContext fxMesa, GLint tmu, int size)
185 {
186 MemRange *prev, *tmp;
187 int result;
188 struct gl_texture_object *obj;
189
190 while (1) {
191 prev = 0;
192 tmp = fxMesa->tmFree[tmu];
193 while (tmp) {
194 if (tmp->endAddr - tmp->startAddr >= size) { /* Fits here */
195 result = tmp->startAddr;
196 tmp->startAddr += size;
197 if (tmp->startAddr == tmp->endAddr) { /* Empty */
198 if (prev) {
199 prev->next = tmp->next;
200 }
201 else {
202 fxMesa->tmFree[tmu] = tmp->next;
203 }
204 fxTMDeleteRangeNode(fxMesa, tmp);
205 }
206 fxMesa->freeTexMem[tmu] -= size;
207 return result;
208 }
209 prev = tmp;
210 tmp = tmp->next;
211 }
212 /* No free space. Discard oldest */
213 obj = fxTMFindOldestObject(fxMesa, tmu);
214 if (!obj) {
215 fprintf(stderr, "fx Driver: No space for texture\n");
216 return -1;
217 }
218 fxTMMoveOutTM(fxMesa, obj);
219 texSwaps++;
220 }
221 }
222
223 static void
224 fxTMRemoveRange(fxMesaContext fxMesa, GLint tmu, MemRange * range)
225 {
226 MemRange *tmp, *prev;
227
228 if (range->startAddr == range->endAddr) {
229 fxTMDeleteRangeNode(fxMesa, range);
230 return;
231 }
232 fxMesa->freeTexMem[tmu] += range->endAddr - range->startAddr;
233 prev = 0;
234 tmp = fxMesa->tmFree[tmu];
235 while (tmp) {
236 if (range->startAddr > tmp->startAddr) {
237 prev = tmp;
238 tmp = tmp->next;
239 }
240 else
241 break;
242 }
243 /* When we create the regions, we make a split at the 2MB boundary.
244 Now we have to make sure we don't join those 2MB boundary regions
245 back together again. */
246 range->next = tmp;
247 if (tmp) {
248 if (range->endAddr == tmp->startAddr
249 && tmp->startAddr & (FX_2MB_SPLIT - 1)) {
250 /* Combine */
251 tmp->startAddr = range->startAddr;
252 fxTMDeleteRangeNode(fxMesa, range);
253 range = tmp;
254 }
255 }
256 if (prev) {
257 if (prev->endAddr == range->startAddr
258 && range->startAddr & (FX_2MB_SPLIT - 1)) {
259 /* Combine */
260 prev->endAddr = range->endAddr;
261 prev->next = range->next;
262 fxTMDeleteRangeNode(fxMesa, range);
263 }
264 else
265 prev->next = range;
266 }
267 else {
268 fxMesa->tmFree[tmu] = range;
269 }
270 }
271
272 static struct gl_texture_object *
273 fxTMFindOldestObject(fxMesaContext fxMesa, int tmu)
274 {
275 GLuint age, old, lasttime, bindnumber;
276 tfxTexInfo *info;
277 struct gl_texture_object *obj, *tmp;
278
279 tmp = fxMesa->glCtx->Shared->TexObjectList;
280 if (!tmp)
281 return 0;
282 obj = 0;
283 old = 0;
284
285 bindnumber = fxMesa->texBindNumber;
286 while (tmp) {
287 info = fxTMGetTexInfo(tmp);
288
289 if (info && info->isInTM &&
290 ((info->whichTMU == tmu) || (info->whichTMU == FX_TMU_BOTH) ||
291 (info->whichTMU == FX_TMU_SPLIT))) {
292 lasttime = info->lastTimeUsed;
293
294 if (lasttime > bindnumber)
295 age = bindnumber + (UINT_MAX - lasttime + 1); /* TO DO: check wrap around */
296 else
297 age = bindnumber - lasttime;
298
299 if (age >= old) {
300 old = age;
301 obj = tmp;
302 }
303 }
304 tmp = tmp->Next;
305 }
306 return obj;
307 }
308
309 static MemRange *
310 fxTMAddObj(fxMesaContext fxMesa,
311 struct gl_texture_object *tObj, GLint tmu, int texmemsize)
312 {
313 FxI32 startAddr;
314 MemRange *range;
315
316 startAddr = fxTMFindStartAddr(fxMesa, tmu, texmemsize);
317 if (startAddr < 0)
318 return 0;
319 range = fxTMNewRangeNode(fxMesa, startAddr, startAddr + texmemsize);
320 return range;
321 }
322
323 /* External Functions */
324
325 void
326 fxTMMoveInTM_NoLock(fxMesaContext fxMesa, struct gl_texture_object *tObj,
327 GLint where)
328 {
329 tfxTexInfo *ti = fxTMGetTexInfo(tObj);
330 int i, l;
331 int texmemsize;
332
333 if (MESA_VERBOSE & VERBOSE_DRIVER) {
334 fprintf(stderr, "fxmesa: fxTMMoveInTM(%d)\n", tObj->Name);
335 }
336
337 fxMesa->stats.reqTexUpload++;
338
339 if (!ti->validated) {
340 fprintf(stderr,
341 "fx Driver: internal error in fxTMMoveInTM() -> not validated\n");
342 fxCloseHardware();
343 exit(-1);
344 }
345
346 if (ti->isInTM) {
347 if (ti->whichTMU == where)
348 return;
349 if (where == FX_TMU_SPLIT || ti->whichTMU == FX_TMU_SPLIT)
350 fxTMMoveOutTM_NoLock(fxMesa, tObj);
351 else {
352 if (ti->whichTMU == FX_TMU_BOTH)
353 return;
354 where = FX_TMU_BOTH;
355 }
356 }
357
358 if (MESA_VERBOSE & (VERBOSE_DRIVER | VERBOSE_TEXTURE)) {
359 fprintf(stderr, "fxmesa: downloading %x (%d) in texture memory in %d\n",
360 (GLuint) tObj, tObj->Name, where);
361 }
362
363 ti->whichTMU = (FxU32) where;
364
365 switch (where) {
366 case FX_TMU0:
367 case FX_TMU1:
368 texmemsize = (int)grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH, &(ti->info));
369 ti->tm[where] = fxTMAddObj(fxMesa, tObj, where, texmemsize);
370 fxMesa->stats.memTexUpload += texmemsize;
371
372 for (i = FX_largeLodValue(ti->info), l = ti->minLevel;
373 i <= FX_smallLodValue(ti->info); i++, l++) {
374 struct gl_texture_image *texImage = tObj->Image[l];
375 grTexDownloadMipMapLevel(where,
376 ti->tm[where]->startAddr,
377 FX_valueToLod(i),
378 FX_largeLodLog2(ti->info),
379 FX_aspectRatioLog2(ti->info),
380 ti->info.format,
381 GR_MIPMAPLEVELMASK_BOTH,
382 texImage->Data);
383 }
384 break;
385 case FX_TMU_SPLIT:
386 texmemsize = (int)grTexTextureMemRequired(GR_MIPMAPLEVELMASK_ODD, &(ti->info));
387 ti->tm[FX_TMU0] = fxTMAddObj(fxMesa, tObj, FX_TMU0, texmemsize);
388 fxMesa->stats.memTexUpload += texmemsize;
389
390 texmemsize = (int)grTexTextureMemRequired(GR_MIPMAPLEVELMASK_EVEN, &(ti->info));
391 ti->tm[FX_TMU1] = fxTMAddObj(fxMesa, tObj, FX_TMU1, texmemsize);
392 fxMesa->stats.memTexUpload += texmemsize;
393
394 for (i = FX_largeLodValue(ti->info), l = ti->minLevel;
395 i <= FX_smallLodValue(ti->info); i++, l++) {
396 struct gl_texture_image *texImage = tObj->Image[l];
397
398 grTexDownloadMipMapLevel(GR_TMU0,
399 ti->tm[FX_TMU0]->startAddr,
400 FX_valueToLod(i),
401 FX_largeLodLog2(ti->info),
402 FX_aspectRatioLog2(ti->info),
403 ti->info.format,
404 GR_MIPMAPLEVELMASK_ODD,
405 texImage->Data);
406
407 grTexDownloadMipMapLevel(GR_TMU1,
408 ti->tm[FX_TMU1]->startAddr,
409 FX_valueToLod(i),
410 FX_largeLodLog2(ti->info),
411 FX_aspectRatioLog2(ti->info),
412 ti->info.format,
413 GR_MIPMAPLEVELMASK_EVEN,
414 texImage->Data);
415 }
416 break;
417 case FX_TMU_BOTH:
418 texmemsize = (int)grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH, &(ti->info));
419 ti->tm[FX_TMU0] = fxTMAddObj(fxMesa, tObj, FX_TMU0, texmemsize);
420 fxMesa->stats.memTexUpload += texmemsize;
421
422 texmemsize = (int)grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH, &(ti->info));
423 ti->tm[FX_TMU1] = fxTMAddObj(fxMesa, tObj, FX_TMU1, texmemsize);
424 fxMesa->stats.memTexUpload += texmemsize;
425
426 for (i = FX_largeLodValue(ti->info), l = ti->minLevel;
427 i <= FX_smallLodValue(ti->info); i++, l++) {
428 struct gl_texture_image *texImage = tObj->Image[l];
429 grTexDownloadMipMapLevel(GR_TMU0,
430 ti->tm[FX_TMU0]->startAddr,
431 FX_valueToLod(i),
432 FX_largeLodLog2(ti->info),
433 FX_aspectRatioLog2(ti->info),
434 ti->info.format,
435 GR_MIPMAPLEVELMASK_BOTH,
436 texImage->Data);
437
438 grTexDownloadMipMapLevel(GR_TMU1,
439 ti->tm[FX_TMU1]->startAddr,
440 FX_valueToLod(i),
441 FX_largeLodLog2(ti->info),
442 FX_aspectRatioLog2(ti->info),
443 ti->info.format,
444 GR_MIPMAPLEVELMASK_BOTH,
445 texImage->Data);
446 }
447 break;
448 default:
449 fprintf(stderr,
450 "fx Driver: internal error in fxTMMoveInTM() -> wrong tmu (%d)\n",
451 where);
452 fxCloseHardware();
453 exit(-1);
454 }
455
456 fxMesa->stats.texUpload++;
457
458 ti->isInTM = GL_TRUE;
459 }
460
461
462 void
463 fxTMMoveInTM(fxMesaContext fxMesa, struct gl_texture_object *tObj,
464 GLint where)
465 {
466 BEGIN_BOARD_LOCK();
467 fxTMMoveInTM_NoLock(fxMesa, tObj, where);
468 END_BOARD_LOCK();
469 }
470
471
472 void
473 fxTMReloadMipMapLevel(fxMesaContext fxMesa, struct gl_texture_object *tObj,
474 GLint level)
475 {
476 tfxTexInfo *ti = fxTMGetTexInfo(tObj);
477 GrLOD_t lodlevel;
478 GLint tmu;
479 struct gl_texture_image *texImage = tObj->Image[level];
480 tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
481
482 assert(mml);
483 assert(mml->width > 0);
484 assert(mml->height > 0);
485 assert(mml->glideFormat > 0);
486
487 if (!ti->validated) {
488 fprintf(stderr,
489 "fx Driver: internal error in fxTMReloadMipMapLevel() -> not validated\n");
490 fxCloseHardware();
491 exit(-1);
492 }
493
494 tmu = (int) ti->whichTMU;
495 fxTMMoveInTM(fxMesa, tObj, tmu);
496
497 fxTexGetInfo(mml->width, mml->height,
498 &lodlevel, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
499
500 lodlevel -= level;
501 switch (tmu) {
502 case FX_TMU0:
503 case FX_TMU1:
504 grTexDownloadMipMapLevel(tmu,
505 ti->tm[tmu]->startAddr,
506 FX_valueToLod(FX_lodToValue(lodlevel)),
507 FX_largeLodLog2(ti->info),
508 FX_aspectRatioLog2(ti->info),
509 ti->info.format,
510 GR_MIPMAPLEVELMASK_BOTH, texImage->Data);
511 break;
512 case FX_TMU_SPLIT:
513 grTexDownloadMipMapLevel(GR_TMU0,
514 ti->tm[GR_TMU0]->startAddr,
515 FX_valueToLod(FX_lodToValue(lodlevel)),
516 FX_largeLodLog2(ti->info),
517 FX_aspectRatioLog2(ti->info),
518 ti->info.format,
519 GR_MIPMAPLEVELMASK_ODD, texImage->Data);
520
521 grTexDownloadMipMapLevel(GR_TMU1,
522 ti->tm[GR_TMU1]->startAddr,
523 FX_valueToLod(FX_lodToValue(lodlevel)),
524 FX_largeLodLog2(ti->info),
525 FX_aspectRatioLog2(ti->info),
526 ti->info.format,
527 GR_MIPMAPLEVELMASK_EVEN, texImage->Data);
528 break;
529 case FX_TMU_BOTH:
530 grTexDownloadMipMapLevel(GR_TMU0,
531 ti->tm[GR_TMU0]->startAddr,
532 FX_valueToLod(FX_lodToValue(lodlevel)),
533 FX_largeLodLog2(ti->info),
534 FX_aspectRatioLog2(ti->info),
535 ti->info.format,
536 GR_MIPMAPLEVELMASK_BOTH, texImage->Data);
537
538 grTexDownloadMipMapLevel(GR_TMU1,
539 ti->tm[GR_TMU1]->startAddr,
540 FX_valueToLod(FX_lodToValue(lodlevel)),
541 FX_largeLodLog2(ti->info),
542 FX_aspectRatioLog2(ti->info),
543 ti->info.format,
544 GR_MIPMAPLEVELMASK_BOTH, texImage->Data);
545 break;
546
547 default:
548 fprintf(stderr,
549 "fx Driver: internal error in fxTMReloadMipMapLevel() -> wrong tmu (%d)\n",
550 tmu);
551 fxCloseHardware();
552 exit(-1);
553 }
554 }
555
556 void
557 fxTMReloadSubMipMapLevel(fxMesaContext fxMesa,
558 struct gl_texture_object *tObj,
559 GLint level, GLint yoffset, GLint height)
560 {
561 tfxTexInfo *ti = fxTMGetTexInfo(tObj);
562 GrLOD_t lodlevel;
563 unsigned short *data;
564 GLint tmu;
565 struct gl_texture_image *texImage = tObj->Image[level];
566 tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
567
568 assert(mml);
569
570 if (!ti->validated) {
571 fprintf(stderr,
572 "fx Driver: internal error in fxTMReloadSubMipMapLevel() -> not validated\n");
573 fxCloseHardware();
574 exit(-1);
575 }
576
577 tmu = (int) ti->whichTMU;
578 fxTMMoveInTM(fxMesa, tObj, tmu);
579
580 fxTexGetInfo(mml->width, mml->height,
581 &lodlevel, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
582
583 if ((ti->info.format == GR_TEXFMT_INTENSITY_8) ||
584 (ti->info.format == GR_TEXFMT_P_8) ||
585 (ti->info.format == GR_TEXFMT_ALPHA_8))
586 data = (GLushort *) texImage->Data + ((yoffset * mml->width) >> 1);
587 else
588 data = (GLushort *) texImage->Data + yoffset * mml->width;
589
590 switch (tmu) {
591 case FX_TMU0:
592 case FX_TMU1:
593 grTexDownloadMipMapLevelPartial(tmu,
594 ti->tm[tmu]->startAddr,
595 FX_valueToLod(FX_lodToValue(lodlevel)
596 + level),
597 FX_largeLodLog2(ti->info),
598 FX_aspectRatioLog2(ti->info),
599 ti->info.format,
600 GR_MIPMAPLEVELMASK_BOTH, data,
601 yoffset, yoffset + height - 1);
602 break;
603 case FX_TMU_SPLIT:
604 grTexDownloadMipMapLevelPartial(GR_TMU0,
605 ti->tm[FX_TMU0]->startAddr,
606 FX_valueToLod(FX_lodToValue(lodlevel)
607 + level),
608 FX_largeLodLog2(ti->info),
609 FX_aspectRatioLog2(ti->info),
610 ti->info.format,
611 GR_MIPMAPLEVELMASK_ODD, data,
612 yoffset, yoffset + height - 1);
613
614 grTexDownloadMipMapLevelPartial(GR_TMU1,
615 ti->tm[FX_TMU1]->startAddr,
616 FX_valueToLod(FX_lodToValue(lodlevel)
617 + level),
618 FX_largeLodLog2(ti->info),
619 FX_aspectRatioLog2(ti->info),
620 ti->info.format,
621 GR_MIPMAPLEVELMASK_EVEN, data,
622 yoffset, yoffset + height - 1);
623 break;
624 case FX_TMU_BOTH:
625 grTexDownloadMipMapLevelPartial(GR_TMU0,
626 ti->tm[FX_TMU0]->startAddr,
627 FX_valueToLod(FX_lodToValue(lodlevel)
628 + level),
629 FX_largeLodLog2(ti->info),
630 FX_aspectRatioLog2(ti->info),
631 ti->info.format,
632 GR_MIPMAPLEVELMASK_BOTH, data,
633 yoffset, yoffset + height - 1);
634
635 grTexDownloadMipMapLevelPartial(GR_TMU1,
636 ti->tm[FX_TMU1]->startAddr,
637 FX_valueToLod(FX_lodToValue(lodlevel)
638 + level),
639 FX_largeLodLog2(ti->info),
640 FX_aspectRatioLog2(ti->info),
641 ti->info.format,
642 GR_MIPMAPLEVELMASK_BOTH, data,
643 yoffset, yoffset + height - 1);
644 break;
645 default:
646 fprintf(stderr,
647 "fx Driver: internal error in fxTMReloadSubMipMapLevel() -> wrong tmu (%d)\n",
648 tmu);
649 fxCloseHardware();
650 exit(-1);
651 }
652 }
653
654 void
655 fxTMMoveOutTM(fxMesaContext fxMesa, struct gl_texture_object *tObj)
656 {
657 tfxTexInfo *ti = fxTMGetTexInfo(tObj);
658
659 if (MESA_VERBOSE & VERBOSE_DRIVER) {
660 fprintf(stderr, "fxmesa: fxTMMoveOutTM(%x (%d))\n", (GLuint) tObj,
661 tObj->Name);
662 }
663
664 if (!ti->isInTM)
665 return;
666
667 switch (ti->whichTMU) {
668 case FX_TMU0:
669 case FX_TMU1:
670 fxTMRemoveRange(fxMesa, (int) ti->whichTMU, ti->tm[ti->whichTMU]);
671 break;
672 case FX_TMU_SPLIT:
673 case FX_TMU_BOTH:
674 fxTMRemoveRange(fxMesa, FX_TMU0, ti->tm[FX_TMU0]);
675 fxTMRemoveRange(fxMesa, FX_TMU1, ti->tm[FX_TMU1]);
676 break;
677 default:
678 fprintf(stderr, "fx Driver: internal error in fxTMMoveOutTM()\n");
679 fxCloseHardware();
680 exit(-1);
681 }
682
683 ti->isInTM = GL_FALSE;
684 ti->whichTMU = FX_TMU_NONE;
685 }
686
687 void
688 fxTMFreeTexture(fxMesaContext fxMesa, struct gl_texture_object *tObj)
689 {
690 tfxTexInfo *ti = fxTMGetTexInfo(tObj);
691 int i;
692
693 fxTMMoveOutTM(fxMesa, tObj);
694
695 for (i = 0; i < MAX_TEXTURE_LEVELS; i++) {
696 struct gl_texture_image *texImage = tObj->Image[i];
697 if (texImage) {
698 if (texImage->Data) {
699 FREE(texImage->Data);
700 texImage->Data = NULL;
701 }
702 if (texImage->DriverData) {
703 FREE(texImage->DriverData);
704 texImage->DriverData = NULL;
705 }
706 }
707 }
708 switch (ti->whichTMU) {
709 case FX_TMU0:
710 case FX_TMU1:
711 fxTMDeleteRangeNode(fxMesa, ti->tm[ti->whichTMU]);
712 break;
713 case FX_TMU_SPLIT:
714 case FX_TMU_BOTH:
715 fxTMDeleteRangeNode(fxMesa, ti->tm[FX_TMU0]);
716 fxTMDeleteRangeNode(fxMesa, ti->tm[FX_TMU1]);
717 break;
718 }
719 }
720
721 void
722 fxTMInit(fxMesaContext fxMesa)
723 {
724 fxMesa->texBindNumber = 0;
725 fxMesa->tmPool = 0;
726
727 fxTMUInit(fxMesa, FX_TMU0);
728
729 if (fxMesa->haveTwoTMUs)
730 fxTMUInit(fxMesa, FX_TMU1);
731 }
732
733 void
734 fxTMClose(fxMesaContext fxMesa)
735 {
736 MemRange *tmp, *next;
737
738 tmp = fxMesa->tmPool;
739 while (tmp) {
740 next = tmp->next;
741 FREE(tmp);
742 tmp = next;
743 }
744 tmp = fxMesa->tmFree[FX_TMU0];
745 while (tmp) {
746 next = tmp->next;
747 FREE(tmp);
748 tmp = next;
749 }
750 if (fxMesa->haveTwoTMUs) {
751 tmp = fxMesa->tmFree[FX_TMU1];
752 while (tmp) {
753 next = tmp->next;
754 FREE(tmp);
755 tmp = next;
756 }
757 }
758 }
759
760 void
761 fxTMRestoreTextures_NoLock(fxMesaContext ctx)
762 {
763 tfxTexInfo *ti;
764 struct gl_texture_object *tObj;
765 int i, where;
766
767 tObj = ctx->glCtx->Shared->TexObjectList;
768 while (tObj) {
769 ti = fxTMGetTexInfo(tObj);
770 if (ti && ti->isInTM) {
771 for (i = 0; i < MAX_TEXTURE_UNITS; i++)
772 if (ctx->glCtx->Texture.Unit[i]._Current == tObj) {
773 /* Force the texture onto the board, as it could be in use */
774 where = ti->whichTMU;
775 fxTMMoveOutTM_NoLock(ctx, tObj);
776 fxTMMoveInTM_NoLock(ctx, tObj, where);
777 break;
778 }
779 if (i == MAX_TEXTURE_UNITS) /* Mark the texture as off the board */
780 fxTMMoveOutTM_NoLock(ctx, tObj);
781 }
782 tObj = tObj->Next;
783 }
784 }
785
786 #else
787
788
789 /*
790 * Need this to provide at least one external definition.
791 */
792
793 extern int gl_fx_dummy_function_texman(void);
794 int
795 gl_fx_dummy_function_texman(void)
796 {
797 return 0;
798 }
799
800 #endif /* FX */