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