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