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 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=(MemRange *)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,"%s configuration:",(tmu==FX_TMU0) ? "TMU0" : "TMU1");
|
---|
150 | fprintf(stderr," Lower texture memory address (%u)\n",(unsigned int)start);
|
---|
151 | fprintf(stderr," Higher texture memory address (%u)\n",(unsigned int)end);
|
---|
152 | fprintf(stderr," 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," %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].used &&
|
---|
656 | ti->mipmapLevel[i].translated)
|
---|
657 | FREE(ti->mipmapLevel[i].data);
|
---|
658 |
|
---|
659 | (void)ti->mipmapLevel[i].data;
|
---|
660 | }
|
---|
661 | switch (ti->whichTMU) {
|
---|
662 | case FX_TMU0:
|
---|
663 | case FX_TMU1:
|
---|
664 | fxTMDeleteRangeNode(fxMesa, ti->tm[ti->whichTMU]);
|
---|
665 | break;
|
---|
666 | case FX_TMU_SPLIT:
|
---|
667 | case FX_TMU_BOTH:
|
---|
668 | fxTMDeleteRangeNode(fxMesa, ti->tm[FX_TMU0]);
|
---|
669 | fxTMDeleteRangeNode(fxMesa, ti->tm[FX_TMU1]);
|
---|
670 | break;
|
---|
671 | }
|
---|
672 | }
|
---|
673 |
|
---|
674 | void fxTMInit(fxMesaContext fxMesa)
|
---|
675 | {
|
---|
676 | fxMesa->texBindNumber=0;
|
---|
677 | fxMesa->tmPool=0;
|
---|
678 |
|
---|
679 | fxTMUInit(fxMesa,FX_TMU0);
|
---|
680 |
|
---|
681 | if(fxMesa->haveTwoTMUs)
|
---|
682 | fxTMUInit(fxMesa,FX_TMU1);
|
---|
683 | }
|
---|
684 |
|
---|
685 | void fxTMClose(fxMesaContext fxMesa)
|
---|
686 | {
|
---|
687 | MemRange *tmp, *next;
|
---|
688 |
|
---|
689 | tmp=fxMesa->tmPool;
|
---|
690 | while (tmp) {
|
---|
691 | next=tmp->next;
|
---|
692 | FREE(tmp);
|
---|
693 | tmp=next;
|
---|
694 | }
|
---|
695 | tmp=fxMesa->tmFree[FX_TMU0];
|
---|
696 | while (tmp) {
|
---|
697 | next=tmp->next;
|
---|
698 | FREE(tmp);
|
---|
699 | tmp=next;
|
---|
700 | }
|
---|
701 | if (fxMesa->haveTwoTMUs) {
|
---|
702 | tmp=fxMesa->tmFree[FX_TMU1];
|
---|
703 | while (tmp) {
|
---|
704 | next=tmp->next;
|
---|
705 | FREE(tmp);
|
---|
706 | tmp=next;
|
---|
707 | }
|
---|
708 | }
|
---|
709 | }
|
---|
710 |
|
---|
711 | void
|
---|
712 | fxTMRestoreTextures_NoLock(fxMesaContext ctx) {
|
---|
713 | tfxTexInfo *ti;
|
---|
714 | struct gl_texture_object *tObj;
|
---|
715 | int i, where;
|
---|
716 |
|
---|
717 | tObj=ctx->glCtx->Shared->TexObjectList;
|
---|
718 | while (tObj) {
|
---|
719 | ti=fxTMGetTexInfo(tObj);
|
---|
720 | if (ti && ti->isInTM) {
|
---|
721 | for (i=0; i<MAX_TEXTURE_UNITS; i++)
|
---|
722 | if (ctx->glCtx->Texture.Unit[i].Current==tObj) {
|
---|
723 | /* Force the texture onto the board, as it could be in use */
|
---|
724 | where=ti->whichTMU;
|
---|
725 | fxTMMoveOutTM_NoLock(ctx, tObj);
|
---|
726 | fxTMMoveInTM_NoLock(ctx, tObj, where);
|
---|
727 | break;
|
---|
728 | }
|
---|
729 | if (i==MAX_TEXTURE_UNITS) /* Mark the texture as off the board */
|
---|
730 | fxTMMoveOutTM_NoLock(ctx, tObj);
|
---|
731 | }
|
---|
732 | tObj=tObj->Next;
|
---|
733 | }
|
---|
734 | }
|
---|
735 |
|
---|
736 | #else
|
---|
737 |
|
---|
738 |
|
---|
739 | /*
|
---|
740 | * Need this to provide at least one external definition.
|
---|
741 | */
|
---|
742 |
|
---|
743 | int gl_fx_dummy_function_texman(void)
|
---|
744 | {
|
---|
745 | return 0;
|
---|
746 | }
|
---|
747 |
|
---|
748 | #endif /* FX */
|
---|