a88ac0b2d052118423f48dcfe8f86b8aba34a450
[mesa.git] / src / mesa / drivers / glide / fxddtex.c
1
2 /*
3 * Mesa 3-D graphics library
4 * Version: 3.5
5 *
6 * Copyright (C) 1999-2001 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 #ifdef HAVE_CONFIG_H
46 #include "conf.h"
47 #endif
48
49 #if defined(FX)
50
51 #include "fxdrv.h"
52 #include "image.h"
53 #include "teximage.h"
54 #include "texstore.h"
55 #include "texutil.h"
56
57
58 void
59 fxPrintTextureData(tfxTexInfo * ti)
60 {
61 fprintf(stderr, "Texture Data:\n");
62 if (ti->tObj) {
63 fprintf(stderr, "\tName: %d\n", ti->tObj->Name);
64 fprintf(stderr, "\tBaseLevel: %d\n", ti->tObj->BaseLevel);
65 fprintf(stderr, "\tSize: %d x %d\n",
66 ti->tObj->Image[ti->tObj->BaseLevel]->Width,
67 ti->tObj->Image[ti->tObj->BaseLevel]->Height);
68 }
69 else
70 fprintf(stderr, "\tName: UNNAMED\n");
71 fprintf(stderr, "\tLast used: %d\n", ti->lastTimeUsed);
72 fprintf(stderr, "\tTMU: %ld\n", ti->whichTMU);
73 fprintf(stderr, "\t%s\n", (ti->isInTM) ? "In TMU" : "Not in TMU");
74 if (ti->tm[0])
75 fprintf(stderr, "\tMem0: %x-%x\n", (unsigned) ti->tm[0]->startAddr,
76 (unsigned) ti->tm[0]->endAddr);
77 if (ti->tm[1])
78 fprintf(stderr, "\tMem1: %x-%x\n", (unsigned) ti->tm[1]->startAddr,
79 (unsigned) ti->tm[1]->endAddr);
80 fprintf(stderr, "\tMipmaps: %d-%d\n", ti->minLevel, ti->maxLevel);
81 fprintf(stderr, "\tFilters: min %d min %d\n",
82 (int) ti->minFilt, (int) ti->maxFilt);
83 fprintf(stderr, "\tClamps: s %d t %d\n", (int) ti->sClamp,
84 (int) ti->tClamp);
85 fprintf(stderr, "\tScales: s %f t %f\n", ti->sScale, ti->tScale);
86 fprintf(stderr, "\tInt Scales: s %d t %d\n",
87 ti->int_sScale / 0x800000, ti->int_tScale / 0x800000);
88 fprintf(stderr, "\t%s\n",
89 (ti->fixedPalette) ? "Fixed palette" : "Non fixed palette");
90 fprintf(stderr, "\t%s\n", (ti->validated) ? "Validated" : "Not validated");
91 }
92
93
94 /************************************************************************/
95 /*************************** Texture Mapping ****************************/
96 /************************************************************************/
97
98 static void
99 fxTexInvalidate(GLcontext * ctx, struct gl_texture_object *tObj)
100 {
101 fxMesaContext fxMesa = (fxMesaContext) ctx->DriverCtx;
102 tfxTexInfo *ti;
103
104 ti = fxTMGetTexInfo(tObj);
105 if (ti->isInTM)
106 fxTMMoveOutTM(fxMesa, tObj); /* TO DO: SLOW but easy to write */
107
108 ti->validated = GL_FALSE;
109 fxMesa->new_state |= FX_NEW_TEXTURING;
110 }
111
112 static tfxTexInfo *
113 fxAllocTexObjData(fxMesaContext fxMesa)
114 {
115 tfxTexInfo *ti;
116
117 if (!(ti = CALLOC(sizeof(tfxTexInfo)))) {
118 fprintf(stderr, "fx Driver: out of memory !\n");
119 fxCloseHardware();
120 exit(-1);
121 }
122
123 ti->validated = GL_FALSE;
124 ti->isInTM = GL_FALSE;
125
126 ti->whichTMU = FX_TMU_NONE;
127
128 ti->tm[FX_TMU0] = NULL;
129 ti->tm[FX_TMU1] = NULL;
130
131 ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
132 ti->maxFilt = GR_TEXTUREFILTER_BILINEAR;
133
134 ti->sClamp = GR_TEXTURECLAMP_WRAP;
135 ti->tClamp = GR_TEXTURECLAMP_WRAP;
136
137 ti->mmMode = GR_MIPMAP_NEAREST;
138 ti->LODblend = FXFALSE;
139
140 return ti;
141 }
142
143 void
144 fxDDTexBind(GLcontext * ctx, GLenum target, struct gl_texture_object *tObj)
145 {
146 fxMesaContext fxMesa = (fxMesaContext) ctx->DriverCtx;
147 tfxTexInfo *ti;
148
149 if (MESA_VERBOSE & VERBOSE_DRIVER) {
150 fprintf(stderr, "fxmesa: fxDDTexBind(%d,%x)\n", tObj->Name,
151 (GLuint) tObj->DriverData);
152 }
153
154 if (target != GL_TEXTURE_2D)
155 return;
156
157 if (!tObj->DriverData) {
158 tObj->DriverData = fxAllocTexObjData(fxMesa);
159 }
160
161 ti = fxTMGetTexInfo(tObj);
162
163 fxMesa->texBindNumber++;
164 ti->lastTimeUsed = fxMesa->texBindNumber;
165
166 fxMesa->new_state |= FX_NEW_TEXTURING;
167 }
168
169 void
170 fxDDTexEnv(GLcontext * ctx, GLenum target, GLenum pname,
171 const GLfloat * param)
172 {
173 fxMesaContext fxMesa = (fxMesaContext) ctx->DriverCtx;
174
175 if (MESA_VERBOSE & VERBOSE_DRIVER) {
176 if (param)
177 fprintf(stderr, "fxmesa: texenv(%x,%x)\n", pname, (GLint) (*param));
178 else
179 fprintf(stderr, "fxmesa: texenv(%x)\n", pname);
180 }
181
182 /* apply any lod biasing right now */
183 if (pname == GL_TEXTURE_LOD_BIAS_EXT) {
184 FX_grTexLodBiasValue(GR_TMU0, *param);
185
186 if (fxMesa->haveTwoTMUs) {
187 FX_grTexLodBiasValue(GR_TMU1, *param);
188 }
189
190 }
191
192 fxMesa->new_state |= FX_NEW_TEXTURING;
193 }
194
195 void
196 fxDDTexParam(GLcontext * ctx, GLenum target, struct gl_texture_object *tObj,
197 GLenum pname, const GLfloat * params)
198 {
199 fxMesaContext fxMesa = (fxMesaContext) ctx->DriverCtx;
200 GLenum param = (GLenum) (GLint) params[0];
201 tfxTexInfo *ti;
202
203 if (MESA_VERBOSE & VERBOSE_DRIVER) {
204 fprintf(stderr, "fxmesa: fxDDTexParam(%d,%x,%x,%x)\n", tObj->Name,
205 (GLuint) tObj->DriverData, pname, param);
206 }
207
208 if (target != GL_TEXTURE_2D)
209 return;
210
211 if (!tObj->DriverData)
212 tObj->DriverData = fxAllocTexObjData(fxMesa);
213
214 ti = fxTMGetTexInfo(tObj);
215
216 switch (pname) {
217
218 case GL_TEXTURE_MIN_FILTER:
219 switch (param) {
220 case GL_NEAREST:
221 ti->mmMode = GR_MIPMAP_DISABLE;
222 ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
223 ti->LODblend = FXFALSE;
224 break;
225 case GL_LINEAR:
226 ti->mmMode = GR_MIPMAP_DISABLE;
227 ti->minFilt = GR_TEXTUREFILTER_BILINEAR;
228 ti->LODblend = FXFALSE;
229 break;
230 case GL_NEAREST_MIPMAP_NEAREST:
231 ti->mmMode = GR_MIPMAP_NEAREST;
232 ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
233 ti->LODblend = FXFALSE;
234 break;
235 case GL_LINEAR_MIPMAP_NEAREST:
236 ti->mmMode = GR_MIPMAP_NEAREST;
237 ti->minFilt = GR_TEXTUREFILTER_BILINEAR;
238 ti->LODblend = FXFALSE;
239 break;
240 case GL_NEAREST_MIPMAP_LINEAR:
241 if (fxMesa->haveTwoTMUs) {
242 ti->mmMode = GR_MIPMAP_NEAREST;
243 ti->LODblend = FXTRUE;
244 }
245 else {
246 ti->mmMode = GR_MIPMAP_NEAREST_DITHER;
247 ti->LODblend = FXFALSE;
248 }
249 ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
250 break;
251 case GL_LINEAR_MIPMAP_LINEAR:
252 if (fxMesa->haveTwoTMUs) {
253 ti->mmMode = GR_MIPMAP_NEAREST;
254 ti->LODblend = FXTRUE;
255 }
256 else {
257 ti->mmMode = GR_MIPMAP_NEAREST_DITHER;
258 ti->LODblend = FXFALSE;
259 }
260 ti->minFilt = GR_TEXTUREFILTER_BILINEAR;
261 break;
262 default:
263 break;
264 }
265 fxTexInvalidate(ctx, tObj);
266 break;
267
268 case GL_TEXTURE_MAG_FILTER:
269 switch (param) {
270 case GL_NEAREST:
271 ti->maxFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
272 break;
273 case GL_LINEAR:
274 ti->maxFilt = GR_TEXTUREFILTER_BILINEAR;
275 break;
276 default:
277 break;
278 }
279 fxTexInvalidate(ctx, tObj);
280 break;
281
282 case GL_TEXTURE_WRAP_S:
283 switch (param) {
284 case GL_CLAMP:
285 ti->sClamp = GR_TEXTURECLAMP_CLAMP;
286 break;
287 case GL_REPEAT:
288 ti->sClamp = GR_TEXTURECLAMP_WRAP;
289 break;
290 default:
291 break;
292 }
293 fxMesa->new_state |= FX_NEW_TEXTURING;
294 break;
295
296 case GL_TEXTURE_WRAP_T:
297 switch (param) {
298 case GL_CLAMP:
299 ti->tClamp = GR_TEXTURECLAMP_CLAMP;
300 break;
301 case GL_REPEAT:
302 ti->tClamp = GR_TEXTURECLAMP_WRAP;
303 break;
304 default:
305 break;
306 }
307 fxMesa->new_state |= FX_NEW_TEXTURING;
308 break;
309
310 case GL_TEXTURE_BORDER_COLOR:
311 /* TO DO */
312 break;
313
314 case GL_TEXTURE_MIN_LOD:
315 /* TO DO */
316 break;
317 case GL_TEXTURE_MAX_LOD:
318 /* TO DO */
319 break;
320 case GL_TEXTURE_BASE_LEVEL:
321 fxTexInvalidate(ctx, tObj);
322 break;
323 case GL_TEXTURE_MAX_LEVEL:
324 fxTexInvalidate(ctx, tObj);
325 break;
326
327 default:
328 break;
329 }
330 }
331
332 void
333 fxDDTexDel(GLcontext * ctx, struct gl_texture_object *tObj)
334 {
335 fxMesaContext fxMesa = FX_CONTEXT(ctx);
336 tfxTexInfo *ti = fxTMGetTexInfo(tObj);
337
338 if (MESA_VERBOSE & VERBOSE_DRIVER) {
339 fprintf(stderr, "fxmesa: fxDDTexDel(%d,%p)\n", tObj->Name, ti);
340 }
341
342 if (!ti)
343 return;
344
345 fxTMFreeTexture(fxMesa, tObj);
346
347 FREE(ti);
348 tObj->DriverData = NULL;
349 }
350
351
352
353 /*
354 * Convert a gl_color_table texture palette to Glide's format.
355 */
356 static void
357 convertPalette(FxU32 data[256], const struct gl_color_table *table)
358 {
359 const GLubyte *tableUB = (const GLubyte *) table->Table;
360 GLint width = table->Size;
361 FxU32 r, g, b, a;
362 GLint i;
363
364 ASSERT(!table->FloatTable);
365
366 switch (table->Format) {
367 case GL_INTENSITY:
368 for (i = 0; i < width; i++) {
369 r = tableUB[i];
370 g = tableUB[i];
371 b = tableUB[i];
372 a = tableUB[i];
373 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
374 }
375 break;
376 case GL_LUMINANCE:
377 for (i = 0; i < width; i++) {
378 r = tableUB[i];
379 g = tableUB[i];
380 b = tableUB[i];
381 a = 255;
382 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
383 }
384 break;
385 case GL_ALPHA:
386 for (i = 0; i < width; i++) {
387 r = g = b = 255;
388 a = tableUB[i];
389 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
390 }
391 break;
392 case GL_LUMINANCE_ALPHA:
393 for (i = 0; i < width; i++) {
394 r = g = b = tableUB[i * 2 + 0];
395 a = tableUB[i * 2 + 1];
396 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
397 }
398 break;
399 case GL_RGB:
400 for (i = 0; i < width; i++) {
401 r = tableUB[i * 3 + 0];
402 g = tableUB[i * 3 + 1];
403 b = tableUB[i * 3 + 2];
404 a = 255;
405 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
406 }
407 break;
408 case GL_RGBA:
409 for (i = 0; i < width; i++) {
410 r = tableUB[i * 4 + 0];
411 g = tableUB[i * 4 + 1];
412 b = tableUB[i * 4 + 2];
413 a = tableUB[i * 4 + 3];
414 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
415 }
416 break;
417 }
418 }
419
420
421 void
422 fxDDTexPalette(GLcontext * ctx, struct gl_texture_object *tObj)
423 {
424 fxMesaContext fxMesa = FX_CONTEXT(ctx);
425
426 if (tObj) {
427 /* per-texture palette */
428 tfxTexInfo *ti;
429 if (MESA_VERBOSE & VERBOSE_DRIVER) {
430 fprintf(stderr, "fxmesa: fxDDTexPalette(%d,%x)\n",
431 tObj->Name, (GLuint) tObj->DriverData);
432 }
433 if (!tObj->DriverData)
434 tObj->DriverData = fxAllocTexObjData(fxMesa);
435 ti = fxTMGetTexInfo(tObj);
436 convertPalette(ti->palette.data, &tObj->Palette);
437 fxTexInvalidate(ctx, tObj);
438 }
439 else {
440 /* global texture palette */
441 if (MESA_VERBOSE & VERBOSE_DRIVER) {
442 fprintf(stderr, "fxmesa: fxDDTexPalette(global)\n");
443 }
444 convertPalette(fxMesa->glbPalette.data, &ctx->Texture.Palette);
445 fxMesa->new_state |= FX_NEW_TEXTURING;
446 }
447 }
448
449
450 void
451 fxDDTexUseGlbPalette(GLcontext * ctx, GLboolean state)
452 {
453 fxMesaContext fxMesa = FX_CONTEXT(ctx);
454
455 if (MESA_VERBOSE & VERBOSE_DRIVER) {
456 fprintf(stderr, "fxmesa: fxDDTexUseGlbPalette(%d)\n", state);
457 }
458
459 if (state) {
460 fxMesa->haveGlobalPaletteTexture = 1;
461
462 FX_grTexDownloadTable(GR_TMU0, GR_TEXTABLE_PALETTE,
463 &(fxMesa->glbPalette));
464 if (fxMesa->haveTwoTMUs)
465 FX_grTexDownloadTable(GR_TMU1, GR_TEXTABLE_PALETTE,
466 &(fxMesa->glbPalette));
467 }
468 else {
469 fxMesa->haveGlobalPaletteTexture = 0;
470
471 if ((ctx->Texture.Unit[0]._Current == ctx->Texture.Unit[0].Current2D) &&
472 (ctx->Texture.Unit[0]._Current != NULL)) {
473 struct gl_texture_object *tObj = ctx->Texture.Unit[0]._Current;
474
475 if (!tObj->DriverData)
476 tObj->DriverData = fxAllocTexObjData(fxMesa);
477
478 fxTexInvalidate(ctx, tObj);
479 }
480 }
481 }
482
483
484 static int
485 logbase2(int n)
486 {
487 GLint i = 1;
488 GLint log2 = 0;
489
490 if (n < 0) {
491 return -1;
492 }
493
494 while (n > i) {
495 i *= 2;
496 log2++;
497 }
498 if (i != n) {
499 return -1;
500 }
501 else {
502 return log2;
503 }
504 }
505
506 /* Need different versions for different cpus.
507 */
508 #define INT_TRICK(l2) (0x800000 * l2)
509
510
511 int
512 fxTexGetInfo(int w, int h, GrLOD_t * lodlevel, GrAspectRatio_t * ar,
513 float *sscale, float *tscale,
514 int *i_sscale, int *i_tscale, int *wscale, int *hscale)
515 {
516
517 static GrLOD_t lod[9] = { GR_LOD_256, GR_LOD_128, GR_LOD_64, GR_LOD_32,
518 GR_LOD_16, GR_LOD_8, GR_LOD_4, GR_LOD_2, GR_LOD_1
519 };
520
521 int logw, logh, ws, hs;
522 GrLOD_t l;
523 GrAspectRatio_t aspectratio;
524 float s, t;
525 int is, it;
526
527 logw = logbase2(w);
528 logh = logbase2(h);
529
530 switch (logw - logh) {
531 case 0:
532 aspectratio = GR_ASPECT_1x1;
533 l = lod[8 - logw];
534 s = t = 256.0f;
535 is = it = INT_TRICK(8);
536 ws = hs = 1;
537 break;
538 case 1:
539 aspectratio = GR_ASPECT_2x1;
540 l = lod[8 - logw];
541 s = 256.0f;
542 t = 128.0f;
543 is = INT_TRICK(8);
544 it = INT_TRICK(7);
545 ws = 1;
546 hs = 1;
547 break;
548 case 2:
549 aspectratio = GR_ASPECT_4x1;
550 l = lod[8 - logw];
551 s = 256.0f;
552 t = 64.0f;
553 is = INT_TRICK(8);
554 it = INT_TRICK(6);
555 ws = 1;
556 hs = 1;
557 break;
558 case 3:
559 aspectratio = GR_ASPECT_8x1;
560 l = lod[8 - logw];
561 s = 256.0f;
562 t = 32.0f;
563 is = INT_TRICK(8);
564 it = INT_TRICK(5);
565 ws = 1;
566 hs = 1;
567 break;
568 case 4:
569 aspectratio = GR_ASPECT_8x1;
570 l = lod[8 - logw];
571 s = 256.0f;
572 t = 32.0f;
573 is = INT_TRICK(8);
574 it = INT_TRICK(5);
575 ws = 1;
576 hs = 2;
577 break;
578 case 5:
579 aspectratio = GR_ASPECT_8x1;
580 l = lod[8 - logw];
581 s = 256.0f;
582 t = 32.0f;
583 is = INT_TRICK(8);
584 it = INT_TRICK(5);
585 ws = 1;
586 hs = 4;
587 break;
588 case 6:
589 aspectratio = GR_ASPECT_8x1;
590 l = lod[8 - logw];
591 s = 256.0f;
592 t = 32.0f;
593 is = INT_TRICK(8);
594 it = INT_TRICK(5);
595 ws = 1;
596 hs = 8;
597 break;
598 case 7:
599 aspectratio = GR_ASPECT_8x1;
600 l = lod[8 - logw];
601 s = 256.0f;
602 t = 32.0f;
603 is = INT_TRICK(8);
604 it = INT_TRICK(5);
605 ws = 1;
606 hs = 16;
607 break;
608 case 8:
609 aspectratio = GR_ASPECT_8x1;
610 l = lod[8 - logw];
611 s = 256.0f;
612 t = 32.0f;
613 is = INT_TRICK(8);
614 it = INT_TRICK(5);
615 ws = 1;
616 hs = 32;
617 break;
618 case -1:
619 aspectratio = GR_ASPECT_1x2;
620 l = lod[8 - logh];
621 s = 128.0f;
622 t = 256.0f;
623 is = INT_TRICK(7);
624 it = INT_TRICK(8);
625 ws = 1;
626 hs = 1;
627 break;
628 case -2:
629 aspectratio = GR_ASPECT_1x4;
630 l = lod[8 - logh];
631 s = 64.0f;
632 t = 256.0f;
633 is = INT_TRICK(6);
634 it = INT_TRICK(8);
635 ws = 1;
636 hs = 1;
637 break;
638 case -3:
639 aspectratio = GR_ASPECT_1x8;
640 l = lod[8 - logh];
641 s = 32.0f;
642 t = 256.0f;
643 is = INT_TRICK(5);
644 it = INT_TRICK(8);
645 ws = 1;
646 hs = 1;
647 break;
648 case -4:
649 aspectratio = GR_ASPECT_1x8;
650 l = lod[8 - logh];
651 s = 32.0f;
652 t = 256.0f;
653 is = INT_TRICK(5);
654 it = INT_TRICK(8);
655 ws = 2;
656 hs = 1;
657 break;
658 case -5:
659 aspectratio = GR_ASPECT_1x8;
660 l = lod[8 - logh];
661 s = 32.0f;
662 t = 256.0f;
663 is = INT_TRICK(5);
664 it = INT_TRICK(8);
665 ws = 4;
666 hs = 1;
667 break;
668 case -6:
669 aspectratio = GR_ASPECT_1x8;
670 l = lod[8 - logh];
671 s = 32.0f;
672 t = 256.0f;
673 is = INT_TRICK(5);
674 it = INT_TRICK(8);
675 ws = 8;
676 hs = 1;
677 break;
678 case -7:
679 aspectratio = GR_ASPECT_1x8;
680 l = lod[8 - logh];
681 s = 32.0f;
682 t = 256.0f;
683 is = INT_TRICK(5);
684 it = INT_TRICK(8);
685 ws = 16;
686 hs = 1;
687 break;
688 case -8:
689 aspectratio = GR_ASPECT_1x8;
690 l = lod[8 - logh];
691 s = 32.0f;
692 t = 256.0f;
693 is = INT_TRICK(5);
694 it = INT_TRICK(8);
695 ws = 32;
696 hs = 1;
697 break;
698 default:
699 return 0;
700 break;
701 }
702
703 if (lodlevel)
704 (*lodlevel) = l;
705
706 if (ar)
707 (*ar) = aspectratio;
708
709 if (sscale)
710 (*sscale) = s;
711
712 if (tscale)
713 (*tscale) = t;
714
715 if (wscale)
716 (*wscale) = ws;
717
718 if (hscale)
719 (*hscale) = hs;
720
721 if (i_sscale)
722 *i_sscale = is;
723
724 if (i_tscale)
725 *i_tscale = it;
726
727
728 return 1;
729 }
730
731 /*
732 * Given an OpenGL internal texture format, return the corresponding
733 * Glide internal texture format and base texture format.
734 */
735 void
736 fxTexGetFormat(GLenum glformat, GrTextureFormat_t * tfmt, GLint * ifmt)
737 {
738 switch (glformat) {
739 case 1:
740 case GL_LUMINANCE:
741 case GL_LUMINANCE4:
742 case GL_LUMINANCE8:
743 case GL_LUMINANCE12:
744 case GL_LUMINANCE16:
745 if (tfmt)
746 (*tfmt) = GR_TEXFMT_INTENSITY_8;
747 if (ifmt)
748 (*ifmt) = GL_LUMINANCE;
749 break;
750 case 2:
751 case GL_LUMINANCE_ALPHA:
752 case GL_LUMINANCE4_ALPHA4:
753 case GL_LUMINANCE6_ALPHA2:
754 case GL_LUMINANCE8_ALPHA8:
755 case GL_LUMINANCE12_ALPHA4:
756 case GL_LUMINANCE12_ALPHA12:
757 case GL_LUMINANCE16_ALPHA16:
758 if (tfmt)
759 (*tfmt) = GR_TEXFMT_ALPHA_INTENSITY_88;
760 if (ifmt)
761 (*ifmt) = GL_LUMINANCE_ALPHA;
762 break;
763 case GL_INTENSITY:
764 case GL_INTENSITY4:
765 case GL_INTENSITY8:
766 case GL_INTENSITY12:
767 case GL_INTENSITY16:
768 if (tfmt)
769 (*tfmt) = GR_TEXFMT_ALPHA_8;
770 if (ifmt)
771 (*ifmt) = GL_INTENSITY;
772 break;
773 case GL_ALPHA:
774 case GL_ALPHA4:
775 case GL_ALPHA8:
776 case GL_ALPHA12:
777 case GL_ALPHA16:
778 if (tfmt)
779 (*tfmt) = GR_TEXFMT_ALPHA_8;
780 if (ifmt)
781 (*ifmt) = GL_ALPHA;
782 break;
783 case 3:
784 case GL_RGB:
785 case GL_R3_G3_B2:
786 case GL_RGB4:
787 case GL_RGB5:
788 case GL_RGB8:
789 case GL_RGB10:
790 case GL_RGB12:
791 case GL_RGB16:
792 if (tfmt)
793 (*tfmt) = GR_TEXFMT_RGB_565;
794 if (ifmt)
795 (*ifmt) = GL_RGB;
796 break;
797 case 4:
798 case GL_RGBA:
799 case GL_RGBA2:
800 case GL_RGBA4:
801 case GL_RGBA8:
802 case GL_RGB10_A2:
803 case GL_RGBA12:
804 case GL_RGBA16:
805 if (tfmt)
806 (*tfmt) = GR_TEXFMT_ARGB_4444;
807 if (ifmt)
808 (*ifmt) = GL_RGBA;
809 break;
810 case GL_RGB5_A1:
811 if (tfmt)
812 (*tfmt) = GR_TEXFMT_ARGB_1555;
813 if (ifmt)
814 (*ifmt) = GL_RGBA;
815 break;
816 case GL_COLOR_INDEX:
817 case GL_COLOR_INDEX1_EXT:
818 case GL_COLOR_INDEX2_EXT:
819 case GL_COLOR_INDEX4_EXT:
820 case GL_COLOR_INDEX8_EXT:
821 case GL_COLOR_INDEX12_EXT:
822 case GL_COLOR_INDEX16_EXT:
823 if (tfmt)
824 (*tfmt) = GR_TEXFMT_P_8;
825 if (ifmt)
826 (*ifmt) = GL_RGBA; /* XXX why is this RGBA? */
827 break;
828 default:
829 fprintf(stderr,
830 "fx Driver: unsupported internalFormat (0x%x) in fxTexGetFormat()\n",
831 glformat);
832 fxCloseHardware();
833 exit(-1);
834 break;
835 }
836 }
837
838 static GLboolean
839 fxIsTexSupported(GLenum target, GLint internalFormat,
840 const struct gl_texture_image *image)
841 {
842 if (target != GL_TEXTURE_2D)
843 return GL_FALSE;
844
845 if (!fxTexGetInfo
846 (image->Width, image->Height, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
847 NULL)) return GL_FALSE;
848
849 if (image->Border > 0)
850 return GL_FALSE;
851
852 return GL_TRUE;
853 }
854
855
856 /**********************************************************************/
857 /**** NEW TEXTURE IMAGE FUNCTIONS ****/
858 /**********************************************************************/
859
860 /* Texel-fetch functions for software texturing and glGetTexImage().
861 * We should have been able to use some "standard" fetch functions (which
862 * may get defined in texutil.c) but we have to account for scaled texture
863 * images on tdfx hardware (the 8:1 aspect ratio limit).
864 * Hence, we need special functions here.
865 */
866
867 static void
868 fetch_intensity8(const struct gl_texture_image *texImage,
869 GLint i, GLint j, GLint k, GLvoid * texelOut)
870 {
871 GLchan *rgba = (GLchan *) texelOut;
872 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
873 const GLubyte *texel;
874
875 i = i * mml->wScale;
876 j = j * mml->hScale;
877
878 texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
879 rgba[RCOMP] = *texel;
880 rgba[GCOMP] = *texel;
881 rgba[BCOMP] = *texel;
882 rgba[ACOMP] = *texel;
883 }
884
885
886 static void
887 fetch_luminance8(const struct gl_texture_image *texImage,
888 GLint i, GLint j, GLint k, GLvoid * texelOut)
889 {
890 GLchan *rgba = (GLchan *) texelOut;
891 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
892 const GLubyte *texel;
893
894 i = i * mml->wScale;
895 j = j * mml->hScale;
896
897 texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
898 rgba[RCOMP] = *texel;
899 rgba[GCOMP] = *texel;
900 rgba[BCOMP] = *texel;
901 rgba[ACOMP] = 255;
902 }
903
904
905 static void
906 fetch_alpha8(const struct gl_texture_image *texImage,
907 GLint i, GLint j, GLint k, GLvoid * texelOut)
908 {
909 GLchan *rgba = (GLchan *) texelOut;
910 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
911 const GLubyte *texel;
912
913 i = i * mml->wScale;
914 j = j * mml->hScale;
915 i = i * mml->width / texImage->Width;
916 j = j * mml->height / texImage->Height;
917
918 texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
919 rgba[RCOMP] = 255;
920 rgba[GCOMP] = 255;
921 rgba[BCOMP] = 255;
922 rgba[ACOMP] = *texel;
923 }
924
925
926 static void
927 fetch_index8(const struct gl_texture_image *texImage,
928 GLint i, GLint j, GLint k, GLvoid * texelOut)
929 {
930 /* XXX todo */
931 }
932
933
934 static void
935 fetch_luminance8_alpha8(const struct gl_texture_image *texImage,
936 GLint i, GLint j, GLint k, GLvoid * texelOut)
937 {
938 GLchan *rgba = (GLchan *) texelOut;
939 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
940 const GLubyte *texel;
941
942 i = i * mml->wScale;
943 j = j * mml->hScale;
944
945 texel = ((GLubyte *) texImage->Data) + (j * mml->width + i) * 2;
946 rgba[RCOMP] = texel[0];
947 rgba[GCOMP] = texel[0];
948 rgba[BCOMP] = texel[0];
949 rgba[ACOMP] = texel[1];
950 }
951
952
953 static void
954 fetch_r5g6b5(const struct gl_texture_image *texImage,
955 GLint i, GLint j, GLint k, GLvoid * texelOut)
956 {
957 GLchan *rgba = (GLchan *) texelOut;
958 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
959 const GLushort *texel;
960
961 i = i * mml->wScale;
962 j = j * mml->hScale;
963
964 texel = ((GLushort *) texImage->Data) + j * mml->width + i;
965 rgba[RCOMP] = (((*texel) >> 11) & 0x1f) * 255 / 31;
966 rgba[GCOMP] = (((*texel) >> 5) & 0x3f) * 255 / 63;
967 rgba[BCOMP] = (((*texel) >> 0) & 0x1f) * 255 / 31;
968 rgba[ACOMP] = 255;
969 }
970
971
972 static void
973 fetch_r4g4b4a4(const struct gl_texture_image *texImage,
974 GLint i, GLint j, GLint k, GLvoid * texelOut)
975 {
976 GLchan *rgba = (GLchan *) texelOut;
977 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
978 const GLushort *texel;
979
980 i = i * mml->wScale;
981 j = j * mml->hScale;
982
983 texel = ((GLushort *) texImage->Data) + j * mml->width + i;
984 rgba[RCOMP] = (((*texel) >> 12) & 0xf) * 255 / 15;
985 rgba[GCOMP] = (((*texel) >> 8) & 0xf) * 255 / 15;
986 rgba[BCOMP] = (((*texel) >> 4) & 0xf) * 255 / 15;
987 rgba[ACOMP] = (((*texel) >> 0) & 0xf) * 255 / 15;
988 }
989
990
991 static void
992 fetch_r5g5b5a1(const struct gl_texture_image *texImage,
993 GLint i, GLint j, GLint k, GLvoid * texelOut)
994 {
995 GLchan *rgba = (GLchan *) texelOut;
996 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
997 const GLushort *texel;
998
999 i = i * mml->wScale;
1000 j = j * mml->hScale;
1001
1002 texel = ((GLushort *) texImage->Data) + j * mml->width + i;
1003 rgba[RCOMP] = (((*texel) >> 11) & 0x1f) * 255 / 31;
1004 rgba[GCOMP] = (((*texel) >> 6) & 0x1f) * 255 / 31;
1005 rgba[BCOMP] = (((*texel) >> 1) & 0x1f) * 255 / 31;
1006 rgba[ACOMP] = (((*texel) >> 0) & 0x01) * 255;
1007 }
1008
1009
1010 static void
1011 PrintTexture(int w, int h, int c, const GLubyte * data)
1012 {
1013 int i, j;
1014 for (i = 0; i < h; i++) {
1015 for (j = 0; j < w; j++) {
1016 if (c == 2)
1017 printf("%02x %02x ", data[0], data[1]);
1018 else if (c == 3)
1019 printf("%02x %02x %02x ", data[0], data[1], data[2]);
1020 data += c;
1021 }
1022 printf("\n");
1023 }
1024 }
1025
1026
1027 void
1028 fxDDTexImage2D(GLcontext * ctx, GLenum target, GLint level,
1029 GLint internalFormat, GLint width, GLint height, GLint border,
1030 GLenum format, GLenum type, const GLvoid * pixels,
1031 const struct gl_pixelstore_attrib *packing,
1032 struct gl_texture_object *texObj,
1033 struct gl_texture_image *texImage)
1034 {
1035 fxMesaContext fxMesa = (fxMesaContext) ctx->DriverCtx;
1036 GrTextureFormat_t gldformat;
1037 tfxTexInfo *ti;
1038 tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
1039 MesaIntTexFormat mesaFormat;
1040 GLint texelSize;
1041 GLboolean success;
1042
1043 if (!fxIsTexSupported(target, internalFormat, texImage)) {
1044 _mesa_problem(NULL, "fx Driver: unsupported texture in fxDDTexImg()\n");
1045 return;
1046 }
1047
1048 if (!texObj->DriverData)
1049 texObj->DriverData = fxAllocTexObjData(fxMesa);
1050 ti = fxTMGetTexInfo(texObj);
1051
1052 if (!mml) {
1053 texImage->DriverData = MALLOC(sizeof(tfxMipMapLevel));
1054 mml = FX_MIPMAP_DATA(texImage);
1055 }
1056
1057 fxTexGetFormat(internalFormat, &gldformat, NULL);
1058
1059 fxTexGetInfo(width, height, NULL, NULL, NULL, NULL,
1060 NULL, NULL, &mml->wScale, &mml->hScale);
1061
1062 mml->width = width * mml->wScale;
1063 mml->height = height * mml->hScale;
1064
1065 switch (internalFormat) {
1066 case GL_INTENSITY:
1067 case GL_INTENSITY4:
1068 case GL_INTENSITY8:
1069 case GL_INTENSITY12:
1070 case GL_INTENSITY16:
1071 texImage->Format = GL_INTENSITY;
1072 texImage->FetchTexel = fetch_intensity8;
1073 texelSize = 1;
1074 mesaFormat = MESA_I8;
1075 break;
1076 case 1:
1077 case GL_LUMINANCE:
1078 case GL_LUMINANCE4:
1079 case GL_LUMINANCE8:
1080 case GL_LUMINANCE12:
1081 case GL_LUMINANCE16:
1082 texImage->Format = GL_LUMINANCE;
1083 texImage->FetchTexel = fetch_luminance8;
1084 texelSize = 1;
1085 mesaFormat = MESA_L8;
1086 break;
1087 case GL_ALPHA:
1088 case GL_ALPHA4:
1089 case GL_ALPHA8:
1090 case GL_ALPHA12:
1091 case GL_ALPHA16:
1092 texImage->Format = GL_ALPHA;
1093 texImage->FetchTexel = fetch_alpha8;
1094 texelSize = 1;
1095 mesaFormat = MESA_A8;
1096 break;
1097 case GL_COLOR_INDEX:
1098 case GL_COLOR_INDEX1_EXT:
1099 case GL_COLOR_INDEX2_EXT:
1100 case GL_COLOR_INDEX4_EXT:
1101 case GL_COLOR_INDEX8_EXT:
1102 case GL_COLOR_INDEX12_EXT:
1103 case GL_COLOR_INDEX16_EXT:
1104 texImage->Format = GL_COLOR_INDEX;
1105 texImage->FetchTexel = fetch_index8;
1106 texelSize = 1;
1107 mesaFormat = MESA_C8;
1108 break;
1109 case 2:
1110 case GL_LUMINANCE_ALPHA:
1111 case GL_LUMINANCE4_ALPHA4:
1112 case GL_LUMINANCE6_ALPHA2:
1113 case GL_LUMINANCE8_ALPHA8:
1114 case GL_LUMINANCE12_ALPHA4:
1115 case GL_LUMINANCE12_ALPHA12:
1116 case GL_LUMINANCE16_ALPHA16:
1117 texImage->Format = GL_LUMINANCE_ALPHA;
1118 texImage->FetchTexel = fetch_luminance8_alpha8;
1119 texelSize = 2;
1120 mesaFormat = MESA_A8_L8;
1121 break;
1122 case 3:
1123 case GL_RGB:
1124 case GL_R3_G3_B2:
1125 case GL_RGB4:
1126 case GL_RGB5:
1127 case GL_RGB8:
1128 case GL_RGB10:
1129 case GL_RGB12:
1130 case GL_RGB16:
1131 texImage->Format = GL_RGB;
1132 texImage->FetchTexel = fetch_r5g6b5;
1133 texelSize = 2;
1134 mesaFormat = MESA_R5_G6_B5;
1135 break;
1136 case 4:
1137 case GL_RGBA:
1138 case GL_RGBA2:
1139 case GL_RGBA4:
1140 case GL_RGBA8:
1141 case GL_RGB10_A2:
1142 case GL_RGBA12:
1143 case GL_RGBA16:
1144 texImage->Format = GL_RGBA;
1145 texImage->FetchTexel = fetch_r4g4b4a4;
1146 texelSize = 2;
1147 mesaFormat = MESA_A4_R4_G4_B4;
1148 break;
1149 case GL_RGB5_A1:
1150 texImage->Format = GL_RGBA;
1151 texImage->FetchTexel = fetch_r5g5b5a1;
1152 texelSize = 2;
1153 mesaFormat = MESA_A1_R5_G5_B5;
1154 break;
1155 default:
1156 _mesa_problem(NULL, "tdfx driver: texbuildimagemap() bad format");
1157 return;
1158 }
1159
1160 _mesa_set_teximage_component_sizes(mesaFormat, texImage);
1161 texImage->Type = 0; /* indicates a driver-specific format */
1162
1163 /* allocate storage for texture image */
1164 texImage->Data = MALLOC(mml->width * mml->height * texelSize);
1165 if (!texImage->Data)
1166 return;
1167
1168 mml->glideFormat = gldformat;
1169 fxTexInvalidate(ctx, texObj);
1170
1171 /* store the texture image */
1172 if (ctx->_ImageTransferState) {
1173 success = GL_FALSE;
1174 }
1175 else {
1176 success = _mesa_convert_teximage(mesaFormat, mml->width, mml->height,
1177 texImage->Data, mml->width * texelSize,
1178 width, height,
1179 format, type, pixels, packing);
1180 }
1181
1182 if (!success) {
1183 /* First attempt at texture conversion failed. We may need to
1184 * do fancy pixel transfer ops or convert from an obscure texture
1185 * format.
1186 */
1187 GLenum simpleFormat = _mesa_base_tex_format(ctx, internalFormat);
1188 GLint comps = _mesa_components_in_format(simpleFormat);
1189 GLubyte *tempImage;
1190
1191 tempImage = MALLOC(width * height * comps * sizeof(GLubyte));
1192
1193 /* Apply pixel transfer ops and convert image format to something
1194 * simple (format = simpleFormat, type = CHAN_TYPE).
1195 */
1196 _mesa_transfer_teximage(ctx, 2, /* dimensions */
1197 simpleFormat, /* dest format */
1198 tempImage, /* dest addr */
1199 width, height, 1, /* src size */
1200 0, 0, 0, /* dst offsets */
1201 width * comps, /* dstRowStride */
1202 0, /* dstImageStride */
1203 format, type, pixels, packing /* src info */ );
1204
1205 /* this conversion better work! */
1206 success = _mesa_convert_teximage(mesaFormat, mml->width, mml->height,
1207 texImage->Data, mml->width * texelSize,
1208 width, height,
1209 simpleFormat, CHAN_TYPE, tempImage,
1210 &_mesa_native_packing);
1211 assert(success);
1212 FREE(tempImage);
1213 }
1214
1215 if (ti->validated && ti->isInTM) {
1216 /*printf("reloadmipmaplevels\n"); */
1217 fxTMReloadMipMapLevel(fxMesa, texObj, level);
1218 }
1219 else {
1220 /*printf("invalidate2\n"); */
1221 fxTexInvalidate(ctx, texObj);
1222 }
1223 }
1224
1225
1226 void
1227 fxDDTexSubImage2D(GLcontext * ctx, GLenum target, GLint level,
1228 GLint xoffset, GLint yoffset,
1229 GLsizei width, GLsizei height,
1230 GLenum format, GLenum type, const GLvoid * pixels,
1231 const struct gl_pixelstore_attrib *packing,
1232 struct gl_texture_object *texObj,
1233 struct gl_texture_image *texImage)
1234 {
1235 fxMesaContext fxMesa = (fxMesaContext) ctx->DriverCtx;
1236 tfxTexInfo *ti;
1237 GLint texelSize;
1238 tfxMipMapLevel *mml;
1239 GLboolean success;
1240 MesaIntTexFormat mesaFormat;
1241
1242 if (!texObj->DriverData) {
1243 _mesa_problem(ctx, "problem in fxDDTexSubImage2D");
1244 return;
1245 }
1246
1247 ti = fxTMGetTexInfo(texObj);
1248 assert(ti);
1249 mml = FX_MIPMAP_DATA(texImage);
1250 assert(mml);
1251
1252 assert(texImage->Data); /* must have an existing texture image! */
1253
1254 switch (mml->glideFormat) {
1255 case GR_TEXFMT_INTENSITY_8:
1256 texelSize = 1;
1257 mesaFormat = MESA_I8;
1258 break;
1259 case GR_TEXFMT_ALPHA_8:
1260 texelSize = 1;
1261 mesaFormat = MESA_A8;
1262 break;
1263 case GR_TEXFMT_P_8:
1264 texelSize = 1;
1265 mesaFormat = MESA_C8;
1266 break;
1267 case GR_TEXFMT_ALPHA_INTENSITY_88:
1268 texelSize = 2;
1269 mesaFormat = MESA_A8_L8;
1270 break;
1271 case GR_TEXFMT_RGB_565:
1272 texelSize = 2;
1273 mesaFormat = MESA_R5_G6_B5;
1274 break;
1275 case GR_TEXFMT_ARGB_4444:
1276 texelSize = 2;
1277 mesaFormat = MESA_A4_R4_G4_B4;
1278 break;
1279 case GR_TEXFMT_ARGB_1555:
1280 texelSize = 2;
1281 mesaFormat = MESA_A1_R5_G5_B5;
1282 break;
1283 default:
1284 _mesa_problem(NULL, "tdfx driver: fxTexBuildSubImageMap() bad format");
1285 return;
1286 }
1287
1288 if (ctx->_ImageTransferState) {
1289 success = GL_FALSE;
1290 }
1291 else {
1292 success = _mesa_convert_texsubimage(mesaFormat, xoffset, yoffset,
1293 mml->width, mml->height,
1294 texImage->Data,
1295 mml->width * texelSize,
1296 width, height,
1297 texImage->Width, texImage->Height,
1298 format, type, pixels, packing);
1299 }
1300
1301 if (!success) {
1302 /* Incoming image might need scale/bias or is in an uncommon format
1303 * that _mesa_convert_texsubimage() can't deal with. Convert it to
1304 * a simpler format now.
1305 */
1306
1307 GLenum simpleFormat = _mesa_base_tex_format(ctx, texImage->IntFormat);
1308 GLint comps = _mesa_components_in_format(simpleFormat);
1309 GLubyte *tempImage;
1310 GLboolean success;
1311
1312 tempImage = MALLOC(width * height * comps * sizeof(GLubyte));
1313
1314 /* Apply pixel transfer ops and convert image format to something
1315 * simple (format = simpleFormat, type = CHAN_TYPE).
1316 */
1317 _mesa_transfer_teximage(ctx, 2, /* dimensions */
1318 simpleFormat, /* dest format */
1319 tempImage, /* dest addr */
1320 width, height, 1, /* src size */
1321 0, 0, 0, /* dst offsets */
1322 width * comps, /* dstRowStride */
1323 0, /* dstImageStride */
1324 format, type, pixels, packing /* src info */ );
1325
1326 /* this conversion better work! */
1327 success = _mesa_convert_texsubimage(mesaFormat, xoffset, yoffset,
1328 mml->width, mml->height,
1329 texImage->Data, mml->width * texelSize, /* dstRowStride */
1330 width * mml->wScale,
1331 height * mml->hScale,
1332 width, height,
1333 simpleFormat, CHAN_TYPE, tempImage,
1334 &_mesa_native_packing);
1335 assert(success);
1336 FREE(tempImage);
1337 }
1338
1339 if (ti->validated && ti->isInTM)
1340 fxTMReloadMipMapLevel(fxMesa, texObj, level);
1341 else
1342 fxTexInvalidate(ctx, texObj);
1343 }
1344
1345
1346 #else
1347
1348
1349 /*
1350 * Need this to provide at least one external definition.
1351 */
1352
1353 extern int gl_fx_dummy_function_ddtex(void);
1354 int
1355 gl_fx_dummy_function_ddtex(void)
1356 {
1357 return 0;
1358 }
1359
1360 #endif /* FX */