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