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