fixed pixelpiped DrawBitmap / DrawPixels (clipping was upside-down)
[mesa.git] / src / mesa / drivers / glide / fxddtex.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 4.0
4 *
5 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 /* Authors:
26 * David Bucciarelli
27 * Brian Paul
28 * Daryll Strauss
29 * Keith Whitwell
30 * Daniel Borca
31 * Hiroshi Morii
32 */
33
34
35 #ifdef HAVE_CONFIG_H
36 #include "conf.h"
37 #endif
38
39 #if defined(FX)
40
41 #include "fxdrv.h"
42 #include "enums.h"
43 #include "image.h"
44 #include "teximage.h"
45 #include "texformat.h"
46 #include "texcompress.h"
47 #include "texobj.h"
48 #include "texstore.h"
49
50
51 void
52 _mesa_halve2x2_teximage2d ( GLuint bytesPerPixel,
53 GLint srcWidth, GLint srcHeight,
54 const GLvoid *srcImage, GLvoid *dstImage )
55 {
56 GLint i, j, k;
57 const GLint dstWidth = srcWidth / 2;
58 const GLint dstHeight = srcHeight / 2;
59 const GLint srcRowStride = srcWidth * bytesPerPixel;
60 const GLubyte *src = srcImage;
61 GLubyte *dst = dstImage;
62
63 /* no borders! can't halve 1x1! (stride > width * comp) not allowed */
64 if (srcHeight == 1) {
65 for (i = 0; i < dstWidth; i++) {
66 for (k = 0; k < bytesPerPixel; k++) {
67 dst[0] = (src[0] + src[bytesPerPixel] + 1) / 2;
68 src++;
69 dst++;
70 }
71 src += bytesPerPixel;
72 }
73 } else if (srcWidth == 1) {
74 for (j = 0; j < dstHeight; j++) {
75 for (k = 0; k < bytesPerPixel; k++) {
76 dst[0] = (src[0] + src[srcRowStride] + 1) / 2;
77 src++;
78 dst++;
79 }
80 src += srcRowStride;
81 }
82 } else {
83 for (j = 0; j < dstHeight; j++) {
84 for (i = 0; i < dstWidth; i++) {
85 for (k = 0; k < bytesPerPixel; k++) {
86 dst[0] = (src[0] +
87 src[bytesPerPixel] +
88 src[srcRowStride] +
89 src[srcRowStride + bytesPerPixel] + 2) / 4;
90 src++;
91 dst++;
92 }
93 src += bytesPerPixel;
94 }
95 src += srcRowStride;
96 }
97 }
98 }
99
100
101 void
102 fxPrintTextureData(tfxTexInfo * ti)
103 {
104 fprintf(stderr, "Texture Data:\n");
105 if (ti->tObj) {
106 fprintf(stderr, "\tName: %d\n", ti->tObj->Name);
107 fprintf(stderr, "\tBaseLevel: %d\n", ti->tObj->BaseLevel);
108 fprintf(stderr, "\tSize: %d x %d\n",
109 ti->tObj->Image[0][ti->tObj->BaseLevel]->Width,
110 ti->tObj->Image[0][ti->tObj->BaseLevel]->Height);
111 }
112 else
113 fprintf(stderr, "\tName: UNNAMED\n");
114 fprintf(stderr, "\tLast used: %d\n", ti->lastTimeUsed);
115 fprintf(stderr, "\tTMU: %ld\n", ti->whichTMU);
116 fprintf(stderr, "\t%s\n", (ti->isInTM) ? "In TMU" : "Not in TMU");
117 if (ti->tm[0])
118 fprintf(stderr, "\tMem0: %x-%x\n", (unsigned) ti->tm[0]->startAddr,
119 (unsigned) ti->tm[0]->endAddr);
120 if (ti->tm[1])
121 fprintf(stderr, "\tMem1: %x-%x\n", (unsigned) ti->tm[1]->startAddr,
122 (unsigned) ti->tm[1]->endAddr);
123 fprintf(stderr, "\tMipmaps: %d-%d\n", ti->minLevel, ti->maxLevel);
124 fprintf(stderr, "\tFilters: min %d max %d\n",
125 (int) ti->minFilt, (int) ti->maxFilt);
126 fprintf(stderr, "\tClamps: s %d t %d\n", (int) ti->sClamp,
127 (int) ti->tClamp);
128 fprintf(stderr, "\tScales: s %f t %f\n", ti->sScale, ti->tScale);
129 fprintf(stderr, "\t%s\n",
130 (ti->fixedPalette) ? "Fixed palette" : "Non fixed palette");
131 fprintf(stderr, "\t%s\n", (ti->validated) ? "Validated" : "Not validated");
132 }
133
134
135 /************************************************************************/
136 /*************************** Texture Mapping ****************************/
137 /************************************************************************/
138
139 static void
140 fxTexInvalidate(GLcontext * ctx, struct gl_texture_object *tObj)
141 {
142 fxMesaContext fxMesa = FX_CONTEXT(ctx);
143 tfxTexInfo *ti;
144
145 ti = fxTMGetTexInfo(tObj);
146 if (ti->isInTM)
147 fxTMMoveOutTM(fxMesa, tObj); /* TO DO: SLOW but easy to write */
148
149 ti->validated = GL_FALSE;
150 fxMesa->new_state |= FX_NEW_TEXTURING;
151 }
152
153 static tfxTexInfo *
154 fxAllocTexObjData(fxMesaContext fxMesa)
155 {
156 tfxTexInfo *ti;
157
158 if (!(ti = CALLOC(sizeof(tfxTexInfo)))) {
159 fprintf(stderr, "fxAllocTexObjData: ERROR: out of memory !\n");
160 fxCloseHardware();
161 exit(-1);
162 }
163
164 ti->validated = GL_FALSE;
165 ti->isInTM = GL_FALSE;
166
167 ti->whichTMU = FX_TMU_NONE;
168
169 ti->tm[FX_TMU0] = NULL;
170 ti->tm[FX_TMU1] = NULL;
171
172 ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
173 ti->maxFilt = GR_TEXTUREFILTER_BILINEAR;
174
175 ti->sClamp = GR_TEXTURECLAMP_WRAP;
176 ti->tClamp = GR_TEXTURECLAMP_WRAP;
177
178 ti->mmMode = GR_MIPMAP_NEAREST;
179 ti->LODblend = FXFALSE;
180
181 return ti;
182 }
183
184 void
185 fxDDTexBind(GLcontext * ctx, GLenum target, struct gl_texture_object *tObj)
186 {
187 fxMesaContext fxMesa = FX_CONTEXT(ctx);
188 tfxTexInfo *ti;
189
190 if (TDFX_DEBUG & VERBOSE_DRIVER) {
191 fprintf(stderr, "fxDDTexBind(%d, %x)\n", tObj->Name, (GLuint)tObj->DriverData);
192 }
193
194 if ((target != GL_TEXTURE_1D) && (target != GL_TEXTURE_2D))
195 return;
196
197 if (!tObj->DriverData) {
198 tObj->DriverData = fxAllocTexObjData(fxMesa);
199 }
200 ti = fxTMGetTexInfo(tObj);
201
202 fxMesa->texBindNumber++;
203 ti->lastTimeUsed = fxMesa->texBindNumber;
204
205 fxMesa->new_state |= FX_NEW_TEXTURING;
206 }
207
208 void
209 fxDDTexEnv(GLcontext * ctx, GLenum target, GLenum pname,
210 const GLfloat * param)
211 {
212 fxMesaContext fxMesa = FX_CONTEXT(ctx);
213
214 if (TDFX_DEBUG & VERBOSE_DRIVER) {
215 if (param)
216 fprintf(stderr, "fxDDTexEnv(%x, %x)\n", pname, (GLint) (*param));
217 else
218 fprintf(stderr, "fxDDTexEnv(%x)\n", pname);
219 }
220
221 /* apply any lod biasing right now */
222 if (pname == GL_TEXTURE_LOD_BIAS_EXT) {
223 GLfloat bias = *param;
224 CLAMP_SELF(bias, -ctx->Const.MaxTextureLodBias,
225 ctx->Const.MaxTextureLodBias - 0.25);
226
227 grTexLodBiasValue(GR_TMU0, bias);
228
229 if (fxMesa->haveTwoTMUs) {
230 grTexLodBiasValue(GR_TMU1, bias);
231 }
232
233 }
234
235 fxMesa->new_state |= FX_NEW_TEXTURING;
236 }
237
238 void
239 fxDDTexParam(GLcontext * ctx, GLenum target, struct gl_texture_object *tObj,
240 GLenum pname, const GLfloat * params)
241 {
242 fxMesaContext fxMesa = FX_CONTEXT(ctx);
243 GLenum param = (GLenum) (GLint) params[0];
244 tfxTexInfo *ti;
245
246 if (TDFX_DEBUG & VERBOSE_DRIVER) {
247 fprintf(stderr, "fxDDTexParam(%d, %x, %s, %s)\n",
248 tObj->Name, (GLuint) tObj->DriverData,
249 _mesa_lookup_enum_by_nr(pname),
250 _mesa_lookup_enum_by_nr(param));
251 }
252
253 if ((target != GL_TEXTURE_1D) && (target != GL_TEXTURE_2D))
254 return;
255
256 if (!tObj->DriverData)
257 tObj->DriverData = fxAllocTexObjData(fxMesa);
258 ti = fxTMGetTexInfo(tObj);
259
260 switch (pname) {
261 case GL_TEXTURE_MIN_FILTER:
262 switch (param) {
263 case GL_NEAREST:
264 ti->mmMode = GR_MIPMAP_DISABLE;
265 ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
266 ti->LODblend = FXFALSE;
267 break;
268 case GL_LINEAR:
269 ti->mmMode = GR_MIPMAP_DISABLE;
270 ti->minFilt = GR_TEXTUREFILTER_BILINEAR;
271 ti->LODblend = FXFALSE;
272 break;
273 case GL_NEAREST_MIPMAP_LINEAR:
274 /* [koolsmoky]
275 * trilinear is bugged! mipmap blending produce
276 * incorrect filtered colors for the smallest mipmap levels.
277 * [dBorca]
278 * currently Napalm can't do single-pass trilinear,
279 * because the way its combiners are set. So we fall back
280 * to GL_NEAREST_MIPMAP_NEAREST. We'll let true trilinear
281 * enabled for V2, V3. If user shoots foot, not our problem!
282 */
283 if (!fxMesa->HaveCmbExt) {
284 if (fxMesa->haveTwoTMUs) {
285 ti->mmMode = GR_MIPMAP_NEAREST;
286 ti->LODblend = FXTRUE;
287 } else {
288 ti->mmMode = GR_MIPMAP_NEAREST_DITHER;
289 ti->LODblend = FXFALSE;
290 }
291 ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
292 break;
293 }
294 case GL_NEAREST_MIPMAP_NEAREST:
295 ti->mmMode = GR_MIPMAP_NEAREST;
296 ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
297 ti->LODblend = FXFALSE;
298 break;
299 case GL_LINEAR_MIPMAP_LINEAR:
300 /* [koolsmoky]
301 * trilinear is bugged! mipmap blending produce
302 * incorrect filtered colors for the smallest mipmap levels.
303 * [dBorca]
304 * currently Napalm can't do single-pass trilinear,
305 * because the way its combiners are set. So we fall back
306 * to GL_LINEAR_MIPMAP_NEAREST. We'll let true trilinear
307 * enabled for V2, V3. If user shoots foot, not our problem!
308 */
309 if (!fxMesa->HaveCmbExt) {
310 if (fxMesa->haveTwoTMUs) {
311 ti->mmMode = GR_MIPMAP_NEAREST;
312 ti->LODblend = FXTRUE;
313 } else {
314 ti->mmMode = GR_MIPMAP_NEAREST_DITHER;
315 ti->LODblend = FXFALSE;
316 }
317 ti->minFilt = GR_TEXTUREFILTER_BILINEAR;
318 break;
319 }
320 case GL_LINEAR_MIPMAP_NEAREST:
321 ti->mmMode = GR_MIPMAP_NEAREST;
322 ti->minFilt = GR_TEXTUREFILTER_BILINEAR;
323 ti->LODblend = FXFALSE;
324 break;
325 default:
326 break;
327 }
328 fxTexInvalidate(ctx, tObj);
329 break;
330
331 case GL_TEXTURE_MAG_FILTER:
332 switch (param) {
333 case GL_NEAREST:
334 ti->maxFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
335 break;
336 case GL_LINEAR:
337 ti->maxFilt = GR_TEXTUREFILTER_BILINEAR;
338 break;
339 default:
340 break;
341 }
342 fxMesa->new_state |= FX_NEW_TEXTURING;
343 break;
344
345 case GL_TEXTURE_WRAP_S:
346 switch (param) {
347 case GL_MIRRORED_REPEAT:
348 ti->sClamp = GR_TEXTURECLAMP_MIRROR_EXT;
349 break;
350 case GL_CLAMP_TO_BORDER: /* no-no, but don't REPEAT, either */
351 case GL_CLAMP_TO_EDGE: /* CLAMP discarding border */
352 case GL_CLAMP:
353 ti->sClamp = GR_TEXTURECLAMP_CLAMP;
354 break;
355 case GL_REPEAT:
356 ti->sClamp = GR_TEXTURECLAMP_WRAP;
357 break;
358 default:
359 break;
360 }
361 fxMesa->new_state |= FX_NEW_TEXTURING;
362 break;
363
364 case GL_TEXTURE_WRAP_T:
365 switch (param) {
366 case GL_MIRRORED_REPEAT:
367 ti->tClamp = GR_TEXTURECLAMP_MIRROR_EXT;
368 break;
369 case GL_CLAMP_TO_BORDER: /* no-no, but don't REPEAT, either */
370 case GL_CLAMP_TO_EDGE: /* CLAMP discarding border */
371 case GL_CLAMP:
372 ti->tClamp = GR_TEXTURECLAMP_CLAMP;
373 break;
374 case GL_REPEAT:
375 ti->tClamp = GR_TEXTURECLAMP_WRAP;
376 break;
377 default:
378 break;
379 }
380 fxMesa->new_state |= FX_NEW_TEXTURING;
381 break;
382
383 case GL_TEXTURE_BORDER_COLOR:
384 /* TO DO */
385 break;
386
387 case GL_TEXTURE_MIN_LOD:
388 /* TO DO */
389 break;
390 case GL_TEXTURE_MAX_LOD:
391 /* TO DO */
392 break;
393 case GL_TEXTURE_BASE_LEVEL:
394 fxTexInvalidate(ctx, tObj);
395 break;
396 case GL_TEXTURE_MAX_LEVEL:
397 fxTexInvalidate(ctx, tObj);
398 break;
399
400 default:
401 break;
402 }
403 }
404
405 void
406 fxDDTexDel(GLcontext * ctx, struct gl_texture_object *tObj)
407 {
408 fxMesaContext fxMesa = FX_CONTEXT(ctx);
409 tfxTexInfo *ti = fxTMGetTexInfo(tObj);
410
411 if (TDFX_DEBUG & VERBOSE_DRIVER) {
412 fprintf(stderr, "fxDDTexDel(%d, %p)\n", tObj->Name, (void *) ti);
413 }
414
415 if (!ti)
416 return;
417
418 fxTMFreeTexture(fxMesa, tObj);
419
420 FREE(ti);
421 tObj->DriverData = NULL;
422
423 /* Free mipmap images and the texture object itself */
424 _mesa_delete_texture_object(ctx, tObj);
425 }
426
427
428 /**
429 * Allocate a new texture object.
430 * Called via ctx->Driver.NewTextureObject.
431 * Note: this function will be called during context creation to
432 * allocate the default texture objects.
433 */
434 struct gl_texture_object *
435 fxDDNewTextureObject( GLcontext *ctx, GLuint name, GLenum target )
436 {
437 struct gl_texture_object *obj;
438 obj = _mesa_new_texture_object(ctx, name, target);
439 return obj;
440 }
441
442
443 /*
444 * Return true if texture is resident, false otherwise.
445 */
446 GLboolean
447 fxDDIsTextureResident(GLcontext *ctx, struct gl_texture_object *tObj)
448 {
449 tfxTexInfo *ti = fxTMGetTexInfo(tObj);
450 return (ti && ti->isInTM);
451 }
452
453
454
455 /*
456 * Convert a gl_color_table texture palette to Glide's format.
457 */
458 static GrTexTable_t
459 convertPalette(const fxMesaContext fxMesa, FxU32 data[256], const struct gl_color_table *table)
460 {
461 const GLubyte *tableUB = (const GLubyte *) table->Table;
462 GLint width = table->Size;
463 FxU32 r, g, b, a;
464 GLint i;
465
466 ASSERT(table->Type == GL_UNSIGNED_BYTE);
467
468 switch (table->Format) {
469 case GL_INTENSITY:
470 for (i = 0; i < width; i++) {
471 r = tableUB[i];
472 g = tableUB[i];
473 b = tableUB[i];
474 a = tableUB[i];
475 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
476 }
477 return fxMesa->HavePalExt ? GR_TEXTABLE_PALETTE_6666_EXT : GR_TEXTABLE_PALETTE;
478 case GL_LUMINANCE:
479 for (i = 0; i < width; i++) {
480 r = tableUB[i];
481 g = tableUB[i];
482 b = tableUB[i];
483 a = 255;
484 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
485 }
486 return GR_TEXTABLE_PALETTE;
487 case GL_ALPHA:
488 for (i = 0; i < width; i++) {
489 r = g = b = 255;
490 a = tableUB[i];
491 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
492 }
493 return fxMesa->HavePalExt ? GR_TEXTABLE_PALETTE_6666_EXT : GR_TEXTABLE_PALETTE;
494 case GL_LUMINANCE_ALPHA:
495 for (i = 0; i < width; i++) {
496 r = g = b = tableUB[i * 2 + 0];
497 a = tableUB[i * 2 + 1];
498 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
499 }
500 return fxMesa->HavePalExt ? GR_TEXTABLE_PALETTE_6666_EXT : GR_TEXTABLE_PALETTE;
501 default:
502 case GL_RGB:
503 for (i = 0; i < width; i++) {
504 r = tableUB[i * 3 + 0];
505 g = tableUB[i * 3 + 1];
506 b = tableUB[i * 3 + 2];
507 a = 255;
508 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
509 }
510 return GR_TEXTABLE_PALETTE;
511 case GL_RGBA:
512 for (i = 0; i < width; i++) {
513 r = tableUB[i * 4 + 0];
514 g = tableUB[i * 4 + 1];
515 b = tableUB[i * 4 + 2];
516 a = tableUB[i * 4 + 3];
517 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
518 }
519 return fxMesa->HavePalExt ? GR_TEXTABLE_PALETTE_6666_EXT : GR_TEXTABLE_PALETTE;
520 }
521 }
522
523
524 void
525 fxDDTexPalette(GLcontext * ctx, struct gl_texture_object *tObj)
526 {
527 fxMesaContext fxMesa = FX_CONTEXT(ctx);
528
529 if (tObj) {
530 /* per-texture palette */
531 tfxTexInfo *ti;
532 if (TDFX_DEBUG & VERBOSE_DRIVER) {
533 fprintf(stderr, "fxDDTexPalette(%d, %x)\n",
534 tObj->Name, (GLuint) tObj->DriverData);
535 }
536 /* This might be a proxy texture. */
537 if (!tObj->Palette.Table)
538 return;
539 if (!tObj->DriverData)
540 tObj->DriverData = fxAllocTexObjData(fxMesa);
541 ti = fxTMGetTexInfo(tObj);
542 ti->paltype = convertPalette(fxMesa, ti->palette.data, &tObj->Palette);
543 fxTexInvalidate(ctx, tObj);
544 }
545 else {
546 /* global texture palette */
547 if (TDFX_DEBUG & VERBOSE_DRIVER) {
548 fprintf(stderr, "fxDDTexPalette(global)\n");
549 }
550 fxMesa->glbPalType = convertPalette(fxMesa, fxMesa->glbPalette.data, &ctx->Texture.Palette);
551 fxMesa->new_state |= FX_NEW_TEXTURING;
552
553 grTexDownloadTable(fxMesa->glbPalType, &(fxMesa->glbPalette));
554 }
555 }
556
557
558 void
559 fxDDTexUseGlbPalette(GLcontext * ctx, GLboolean state)
560 {
561 fxMesaContext fxMesa = FX_CONTEXT(ctx);
562
563 if (TDFX_DEBUG & VERBOSE_DRIVER) {
564 fprintf(stderr, "fxDDTexUseGlbPalette(%d)\n", state);
565 }
566
567 if (state) {
568 fxMesa->haveGlobalPaletteTexture = 1;
569 }
570 else {
571 fxMesa->haveGlobalPaletteTexture = 0;
572
573 /* [dBorca] tis beyond my comprehension */
574 if ((ctx->Texture.Unit[0]._Current == ctx->Texture.Unit[0].Current2D) &&
575 (ctx->Texture.Unit[0]._Current != NULL)) {
576 struct gl_texture_object *tObj = ctx->Texture.Unit[0]._Current;
577 if (!tObj->DriverData)
578 tObj->DriverData = fxAllocTexObjData(fxMesa);
579 fxTexInvalidate(ctx, tObj);
580 }
581 }
582 }
583
584
585 static int
586 logbase2(int n)
587 {
588 GLint i = 1;
589 GLint log2 = 0;
590
591 if (n < 0) {
592 return -1;
593 }
594
595 while (n > i) {
596 i *= 2;
597 log2++;
598 }
599 if (i != n) {
600 return -1;
601 }
602 else {
603 return log2;
604 }
605 }
606
607
608 /* fxTexGetInfo
609 * w, h - source texture width and height
610 * lodlevel - Glide lod level token for the larger texture dimension
611 * ar - Glide aspect ratio token
612 * sscale - S scale factor used during triangle setup
613 * tscale - T scale factor used during triangle setup
614 * wscale - OpenGL -> Glide image width scale factor
615 * hscale - OpenGL -> Glide image height scale factor
616 */
617 int
618 fxTexGetInfo(int w, int h, GrLOD_t * lodlevel, GrAspectRatio_t * ar,
619 float *sscale, float *tscale,
620 int *wscale, int *hscale)
621 {
622 int logw, logh, ws, hs;
623 GrLOD_t l;
624 GrAspectRatio_t aspectratio;
625 float s, t;
626
627 logw = logbase2(w);
628 logh = logbase2(h);
629
630 l = MAX2(logw, logh);
631 aspectratio = logw - logh;
632 ws = hs = 1;
633 s = t = 256.0f;
634
635 /* hardware only allows a maximum aspect ratio of 8x1, so handle
636 * |aspectratio| > 3 by scaling the image and using an 8x1 aspect
637 * ratio
638 */
639 switch (aspectratio) {
640 case 0:
641 break;
642 case 1:
643 t = 128.0f;
644 break;
645 case 2:
646 t = 64.0f;
647 break;
648 case 3:
649 t = 32.0f;
650 break;
651 case -1:
652 s = 128.0f;
653 break;
654 case -2:
655 s = 64.0f;
656 break;
657 case -3:
658 s = 32.0f;
659 break;
660 default:
661 if (aspectratio > 3) {
662 t = 32.0f;
663 hs = 1 << (aspectratio - 3);
664 aspectratio = GR_ASPECT_LOG2_8x1;
665 } else /*if (aspectratio < -3)*/ {
666 s = 32.0f;
667 ws = 1 << (-aspectratio - 3);
668 aspectratio = GR_ASPECT_LOG2_1x8;
669 }
670 }
671
672 if (lodlevel)
673 (*lodlevel) = l;
674
675 if (ar)
676 (*ar) = aspectratio;
677
678 if (sscale)
679 (*sscale) = s;
680
681 if (tscale)
682 (*tscale) = t;
683
684 if (wscale)
685 (*wscale) = ws;
686
687 if (hscale)
688 (*hscale) = hs;
689
690
691 return 1;
692 }
693
694 static GLboolean
695 fxIsTexSupported(GLenum target, GLint internalFormat,
696 const struct gl_texture_image *image)
697 {
698 if ((target != GL_TEXTURE_1D) && (target != GL_TEXTURE_2D))
699 return GL_FALSE;
700
701 #if 0
702 if (!fxTexGetInfo(image->Width, image->Height, NULL, NULL, NULL, NULL, NULL, NULL))
703 return GL_FALSE;
704 #endif
705
706 if (image->Border > 0)
707 return GL_FALSE;
708
709 return GL_TRUE;
710 }
711
712
713 /**********************************************************************/
714 /**** NEW TEXTURE IMAGE FUNCTIONS ****/
715 /**********************************************************************/
716 extern void
717 fxt1_decode_1 (const void *texture, int width,
718 int i, int j, unsigned char *rgba);
719
720 /* Texel-fetch functions for software texturing and glGetTexImage().
721 * We should have been able to use some "standard" fetch functions (which
722 * may get defined in texutil.c) but we have to account for scaled texture
723 * images on tdfx hardware (the 8:1 aspect ratio limit).
724 * Hence, we need special functions here.
725 */
726
727 static void
728 fetch_intensity8(const struct gl_texture_image *texImage,
729 GLint i, GLint j, GLint k, GLchan *rgba)
730 {
731 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
732 const GLubyte *texel;
733
734 i = i * mml->wScale;
735 j = j * mml->hScale;
736
737 texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
738 rgba[RCOMP] = *texel;
739 rgba[GCOMP] = *texel;
740 rgba[BCOMP] = *texel;
741 rgba[ACOMP] = *texel;
742 }
743
744
745 static void
746 fetch_luminance8(const struct gl_texture_image *texImage,
747 GLint i, GLint j, GLint k, GLchan *rgba)
748 {
749 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
750 const GLubyte *texel;
751
752 i = i * mml->wScale;
753 j = j * mml->hScale;
754
755 texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
756 rgba[RCOMP] = *texel;
757 rgba[GCOMP] = *texel;
758 rgba[BCOMP] = *texel;
759 rgba[ACOMP] = 255;
760 }
761
762
763 static void
764 fetch_alpha8(const struct gl_texture_image *texImage,
765 GLint i, GLint j, GLint k, GLchan *rgba)
766 {
767 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
768 const GLubyte *texel;
769
770 i = i * mml->wScale;
771 j = j * mml->hScale;
772
773 texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
774 rgba[RCOMP] = 255;
775 rgba[GCOMP] = 255;
776 rgba[BCOMP] = 255;
777 rgba[ACOMP] = *texel;
778 }
779
780
781 static void
782 fetch_index8(const struct gl_texture_image *texImage,
783 GLint i, GLint j, GLint k, GLchan *indexOut)
784 {
785 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
786 const GLubyte *texel;
787
788 i = i * mml->wScale;
789 j = j * mml->hScale;
790
791 texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
792 *indexOut = *texel;
793 }
794
795
796 static void
797 fetch_luminance8_alpha8(const struct gl_texture_image *texImage,
798 GLint i, GLint j, GLint k, GLchan *rgba)
799 {
800 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
801 const GLubyte *texel;
802
803 i = i * mml->wScale;
804 j = j * mml->hScale;
805
806 texel = ((GLubyte *) texImage->Data) + (j * mml->width + i) * 2;
807 rgba[RCOMP] = texel[0];
808 rgba[GCOMP] = texel[0];
809 rgba[BCOMP] = texel[0];
810 rgba[ACOMP] = texel[1];
811 }
812
813
814 static void
815 fetch_r5g6b5(const struct gl_texture_image *texImage,
816 GLint i, GLint j, GLint k, GLchan *rgba)
817 {
818 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
819 const GLushort *texel;
820
821 i = i * mml->wScale;
822 j = j * mml->hScale;
823
824 texel = ((GLushort *) texImage->Data) + j * mml->width + i;
825 rgba[RCOMP] = FX_rgb_scale_5[(*texel >> 11) & 0x1F];
826 rgba[GCOMP] = FX_rgb_scale_6[(*texel >> 5) & 0x3F];
827 rgba[BCOMP] = FX_rgb_scale_5[ *texel & 0x1F];
828 rgba[ACOMP] = 255;
829 }
830
831
832 static void
833 fetch_r4g4b4a4(const struct gl_texture_image *texImage,
834 GLint i, GLint j, GLint k, GLchan *rgba)
835 {
836 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
837 const GLushort *texel;
838
839 i = i * mml->wScale;
840 j = j * mml->hScale;
841
842 texel = ((GLushort *) texImage->Data) + j * mml->width + i;
843 rgba[RCOMP] = FX_rgb_scale_4[(*texel >> 12) & 0xF];
844 rgba[GCOMP] = FX_rgb_scale_4[(*texel >> 8) & 0xF];
845 rgba[BCOMP] = FX_rgb_scale_4[(*texel >> 4) & 0xF];
846 rgba[ACOMP] = FX_rgb_scale_4[ *texel & 0xF];
847 }
848
849
850 static void
851 fetch_r5g5b5a1(const struct gl_texture_image *texImage,
852 GLint i, GLint j, GLint k, GLchan *rgba)
853 {
854 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
855 const GLushort *texel;
856
857 i = i * mml->wScale;
858 j = j * mml->hScale;
859
860 texel = ((GLushort *) texImage->Data) + j * mml->width + i;
861 rgba[RCOMP] = FX_rgb_scale_5[(*texel >> 11) & 0x1F];
862 rgba[GCOMP] = FX_rgb_scale_5[(*texel >> 6) & 0x1F];
863 rgba[BCOMP] = FX_rgb_scale_5[(*texel >> 1) & 0x1F];
864 rgba[ACOMP] = ((*texel) & 0x01) * 255;
865 }
866
867
868 static void
869 fetch_a8r8g8b8(const struct gl_texture_image *texImage,
870 GLint i, GLint j, GLint k, GLchan *rgba)
871 {
872 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
873 const GLuint *texel;
874
875 i = i * mml->wScale;
876 j = j * mml->hScale;
877
878 texel = ((GLuint *) texImage->Data) + j * mml->width + i;
879 rgba[RCOMP] = (((*texel) >> 16) & 0xff);
880 rgba[GCOMP] = (((*texel) >> 8) & 0xff);
881 rgba[BCOMP] = (((*texel) ) & 0xff);
882 rgba[ACOMP] = (((*texel) >> 24) & 0xff);
883 }
884
885
886 static void
887 fetch_rgb_fxt1(const struct gl_texture_image *texImage,
888 GLint i, GLint j, GLint k, GLchan *rgba)
889 {
890 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
891
892 i = i * mml->wScale;
893 j = j * mml->hScale;
894
895 fxt1_decode_1(texImage->Data, mml->width, i, j, rgba);
896 rgba[ACOMP] = 255;
897 }
898
899
900 static void
901 fetch_rgba_fxt1(const struct gl_texture_image *texImage,
902 GLint i, GLint j, GLint k, GLchan *rgba)
903 {
904 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
905
906 i = i * mml->wScale;
907 j = j * mml->hScale;
908
909 fxt1_decode_1(texImage->Data, mml->width, i, j, rgba);
910 }
911
912
913 static void
914 fetch_rgb_dxt1(const struct gl_texture_image *texImage,
915 GLint i, GLint j, GLint k, GLchan *rgba)
916 {
917 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
918
919 i = i * mml->wScale;
920 j = j * mml->hScale;
921
922 _mesa_texformat_rgb_dxt1.FetchTexel2D(texImage, i, j, k, rgba);
923 }
924
925
926 static void
927 fetch_rgba_dxt1(const struct gl_texture_image *texImage,
928 GLint i, GLint j, GLint k, GLchan *rgba)
929 {
930 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
931
932 i = i * mml->wScale;
933 j = j * mml->hScale;
934
935 _mesa_texformat_rgba_dxt1.FetchTexel2D(texImage, i, j, k, rgba);
936 }
937
938
939 static void
940 fetch_rgba_dxt3(const struct gl_texture_image *texImage,
941 GLint i, GLint j, GLint k, GLchan *rgba)
942 {
943 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
944
945 i = i * mml->wScale;
946 j = j * mml->hScale;
947
948 _mesa_texformat_rgba_dxt3.FetchTexel2D(texImage, i, j, k, rgba);
949 }
950
951
952 static void
953 fetch_rgba_dxt5(const struct gl_texture_image *texImage,
954 GLint i, GLint j, GLint k, GLchan *rgba)
955 {
956 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
957
958 i = i * mml->wScale;
959 j = j * mml->hScale;
960
961 _mesa_texformat_rgba_dxt5.FetchTexel2D(texImage, i, j, k, rgba);
962 }
963
964
965 static void
966 PrintTexture(int w, int h, int c, const GLubyte * data)
967 {
968 int i, j;
969 for (i = 0; i < h; i++) {
970 for (j = 0; j < w; j++) {
971 if (c == 2)
972 fprintf(stderr, "%02x %02x ", data[0], data[1]);
973 else if (c == 3)
974 fprintf(stderr, "%02x %02x %02x ", data[0], data[1], data[2]);
975 data += c;
976 }
977 fprintf(stderr, "\n");
978 }
979 }
980
981
982 const struct gl_texture_format *
983 fxDDChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
984 GLenum srcFormat, GLenum srcType )
985 {
986 fxMesaContext fxMesa = FX_CONTEXT(ctx);
987 GLboolean allow32bpt = fxMesa->HaveTexFmt;
988
989 if (TDFX_DEBUG & VERBOSE_TEXTURE) {
990 fprintf(stderr, "fxDDChooseTextureFormat(...)\n");
991 }
992
993 switch (internalFormat) {
994 case GL_COMPRESSED_RGB:
995 #if FX_TC_NCC
996 if (fxMesa->HaveTexus2) {
997 return &_mesa_texformat_argb8888;
998 }
999 #endif
1000 /* intentional fall through */
1001 case 3:
1002 case GL_RGB:
1003 if ( srcFormat == GL_RGB && srcType == GL_UNSIGNED_SHORT_5_6_5 ) {
1004 return &_mesa_texformat_rgb565;
1005 }
1006 /* intentional fall through */
1007 case GL_RGB8:
1008 case GL_RGB10:
1009 case GL_RGB12:
1010 case GL_RGB16:
1011 return (allow32bpt) ? &_mesa_texformat_argb8888
1012 : &_mesa_texformat_rgb565;
1013 case GL_RGBA2:
1014 case GL_RGBA4:
1015 return &_mesa_texformat_argb4444;
1016 case GL_COMPRESSED_RGBA:
1017 #if FX_TC_NCC
1018 if (fxMesa->HaveTexus2) {
1019 return &_mesa_texformat_argb8888;
1020 }
1021 #endif
1022 /* intentional fall through */
1023 case 4:
1024 case GL_RGBA:
1025 if ( srcFormat == GL_BGRA ) {
1026 if ( srcType == GL_UNSIGNED_INT_8_8_8_8_REV ) {
1027 return &_mesa_texformat_argb8888;
1028 }
1029 else if ( srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV ) {
1030 return &_mesa_texformat_argb4444;
1031 }
1032 else if ( srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV ) {
1033 return &_mesa_texformat_argb1555;
1034 }
1035 }
1036 /* intentional fall through */
1037 case GL_RGBA8:
1038 case GL_RGB10_A2:
1039 case GL_RGBA12:
1040 case GL_RGBA16:
1041 return (allow32bpt) ? &_mesa_texformat_argb8888
1042 : &_mesa_texformat_argb4444;
1043 case GL_INTENSITY:
1044 case GL_INTENSITY4:
1045 case GL_INTENSITY8:
1046 case GL_INTENSITY12:
1047 case GL_INTENSITY16:
1048 case GL_COMPRESSED_INTENSITY:
1049 return &_mesa_texformat_i8;
1050 case 1:
1051 case GL_LUMINANCE:
1052 case GL_LUMINANCE4:
1053 case GL_LUMINANCE8:
1054 case GL_LUMINANCE12:
1055 case GL_LUMINANCE16:
1056 case GL_COMPRESSED_LUMINANCE:
1057 return &_mesa_texformat_l8;
1058 case GL_ALPHA:
1059 case GL_ALPHA4:
1060 case GL_ALPHA8:
1061 case GL_ALPHA12:
1062 case GL_ALPHA16:
1063 case GL_COMPRESSED_ALPHA:
1064 return &_mesa_texformat_a8;
1065 case GL_COLOR_INDEX:
1066 case GL_COLOR_INDEX1_EXT:
1067 case GL_COLOR_INDEX2_EXT:
1068 case GL_COLOR_INDEX4_EXT:
1069 case GL_COLOR_INDEX8_EXT:
1070 case GL_COLOR_INDEX12_EXT:
1071 case GL_COLOR_INDEX16_EXT:
1072 return &_mesa_texformat_ci8;
1073 case 2:
1074 case GL_LUMINANCE_ALPHA:
1075 case GL_LUMINANCE4_ALPHA4:
1076 case GL_LUMINANCE6_ALPHA2:
1077 case GL_LUMINANCE8_ALPHA8:
1078 case GL_LUMINANCE12_ALPHA4:
1079 case GL_LUMINANCE12_ALPHA12:
1080 case GL_LUMINANCE16_ALPHA16:
1081 case GL_COMPRESSED_LUMINANCE_ALPHA:
1082 return &_mesa_texformat_al88;
1083 case GL_R3_G3_B2:
1084 case GL_RGB4:
1085 case GL_RGB5:
1086 return &_mesa_texformat_rgb565;
1087 case GL_RGB5_A1:
1088 return &_mesa_texformat_argb1555;
1089 /* GL_EXT_texture_compression_s3tc */
1090 /* GL_S3_s3tc */
1091 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1092 case GL_RGB_S3TC:
1093 case GL_RGB4_S3TC:
1094 return &_mesa_texformat_rgb_dxt1;
1095 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1096 return &_mesa_texformat_rgba_dxt1;
1097 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
1098 case GL_RGBA_S3TC:
1099 case GL_RGBA4_S3TC:
1100 return &_mesa_texformat_rgba_dxt3;
1101 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
1102 return &_mesa_texformat_rgba_dxt5;
1103 /* GL_3DFX_texture_compression_FXT1 */
1104 case GL_COMPRESSED_RGB_FXT1_3DFX:
1105 return &_mesa_texformat_rgb_fxt1;
1106 case GL_COMPRESSED_RGBA_FXT1_3DFX:
1107 return &_mesa_texformat_rgba_fxt1;
1108 default:
1109 _mesa_problem(NULL, "unexpected format in fxDDChooseTextureFormat");
1110 return NULL;
1111 }
1112 }
1113
1114
1115 static GrTextureFormat_t
1116 fxGlideFormat(GLint mesaFormat)
1117 {
1118 switch (mesaFormat) {
1119 case MESA_FORMAT_I8:
1120 return GR_TEXFMT_ALPHA_8;
1121 case MESA_FORMAT_A8:
1122 return GR_TEXFMT_ALPHA_8;
1123 case MESA_FORMAT_L8:
1124 return GR_TEXFMT_INTENSITY_8;
1125 case MESA_FORMAT_CI8:
1126 return GR_TEXFMT_P_8;
1127 case MESA_FORMAT_AL88:
1128 return GR_TEXFMT_ALPHA_INTENSITY_88;
1129 case MESA_FORMAT_RGB565:
1130 return GR_TEXFMT_RGB_565;
1131 case MESA_FORMAT_ARGB4444:
1132 return GR_TEXFMT_ARGB_4444;
1133 case MESA_FORMAT_ARGB1555:
1134 return GR_TEXFMT_ARGB_1555;
1135 case MESA_FORMAT_ARGB8888:
1136 return GR_TEXFMT_ARGB_8888;
1137 case MESA_FORMAT_RGB_FXT1:
1138 case MESA_FORMAT_RGBA_FXT1:
1139 return GR_TEXFMT_ARGB_CMP_FXT1;
1140 case MESA_FORMAT_RGB_DXT1:
1141 case MESA_FORMAT_RGBA_DXT1:
1142 return GR_TEXFMT_ARGB_CMP_DXT1;
1143 case MESA_FORMAT_RGBA_DXT3:
1144 return GR_TEXFMT_ARGB_CMP_DXT3;
1145 case MESA_FORMAT_RGBA_DXT5:
1146 return GR_TEXFMT_ARGB_CMP_DXT5;
1147 default:
1148 _mesa_problem(NULL, "Unexpected format in fxGlideFormat");
1149 return 0;
1150 }
1151 }
1152
1153
1154 static FetchTexelFuncC
1155 fxFetchFunction(GLint mesaFormat)
1156 {
1157 switch (mesaFormat) {
1158 case MESA_FORMAT_I8:
1159 return &fetch_intensity8;
1160 case MESA_FORMAT_A8:
1161 return &fetch_alpha8;
1162 case MESA_FORMAT_L8:
1163 return &fetch_luminance8;
1164 case MESA_FORMAT_CI8:
1165 return &fetch_index8;
1166 case MESA_FORMAT_AL88:
1167 return &fetch_luminance8_alpha8;
1168 case MESA_FORMAT_RGB565:
1169 return &fetch_r5g6b5;
1170 case MESA_FORMAT_ARGB4444:
1171 return &fetch_r4g4b4a4;
1172 case MESA_FORMAT_ARGB1555:
1173 return &fetch_r5g5b5a1;
1174 case MESA_FORMAT_ARGB8888:
1175 return &fetch_a8r8g8b8;
1176 case MESA_FORMAT_RGB_FXT1:
1177 return &fetch_rgb_fxt1;
1178 case MESA_FORMAT_RGBA_FXT1:
1179 return &fetch_rgba_fxt1;
1180 case MESA_FORMAT_RGB_DXT1:
1181 return &fetch_rgb_dxt1;
1182 case MESA_FORMAT_RGBA_DXT1:
1183 return &fetch_rgba_dxt1;
1184 case MESA_FORMAT_RGBA_DXT3:
1185 return &fetch_rgba_dxt3;
1186 case MESA_FORMAT_RGBA_DXT5:
1187 return &fetch_rgba_dxt5;
1188 default:
1189 _mesa_problem(NULL, "Unexpected format in fxFetchFunction");
1190 return NULL;
1191 }
1192 }
1193
1194
1195 static GLboolean
1196 adjust2DRatio (GLcontext *ctx,
1197 GLint xoffset, GLint yoffset,
1198 GLint width, GLint height,
1199 GLenum format, GLenum type, const GLvoid *pixels,
1200 const struct gl_pixelstore_attrib *packing,
1201 tfxMipMapLevel *mml,
1202 struct gl_texture_image *texImage,
1203 GLint texelBytes,
1204 GLint dstRowStride)
1205 {
1206 const GLint newWidth = width * mml->wScale;
1207 const GLint newHeight = height * mml->hScale;
1208 GLvoid *tempImage;
1209
1210 if (!texImage->IsCompressed) {
1211 GLubyte *destAddr;
1212 tempImage = MALLOC(width * height * texelBytes);
1213 if (!tempImage) {
1214 return GL_FALSE;
1215 }
1216
1217 texImage->TexFormat->StoreImage(ctx, 2, texImage->Format,
1218 texImage->TexFormat, tempImage,
1219 0, 0, 0, /* dstX/Y/Zoffset */
1220 width * texelBytes, /* dstRowStride */
1221 0, /* dstImageStride */
1222 width, height, 1,
1223 format, type, pixels, packing);
1224
1225 /* now rescale */
1226 /* compute address of dest subimage within the overal tex image */
1227 destAddr = (GLubyte *) texImage->Data
1228 + (yoffset * mml->hScale * mml->width
1229 + xoffset * mml->wScale) * texelBytes;
1230
1231 _mesa_rescale_teximage2d(texelBytes,
1232 dstRowStride, /* dst stride */
1233 width, height,
1234 newWidth, newHeight,
1235 tempImage, destAddr);
1236 } else {
1237 const GLint rawBytes = 4;
1238 GLvoid *rawImage = MALLOC(width * height * rawBytes);
1239 if (!rawImage) {
1240 return GL_FALSE;
1241 }
1242 tempImage = MALLOC(newWidth * newHeight * rawBytes);
1243 if (!tempImage) {
1244 return GL_FALSE;
1245 }
1246 /* unpack image, apply transfer ops and store in rawImage */
1247 _mesa_texstore_rgba8888(ctx, 2, GL_RGBA,
1248 &_mesa_texformat_rgba8888_rev, rawImage,
1249 0, 0, 0, /* dstX/Y/Zoffset */
1250 width * rawBytes, /* dstRowStride */
1251 0, /* dstImageStride */
1252 width, height, 1,
1253 format, type, pixels, packing);
1254 _mesa_rescale_teximage2d(rawBytes,
1255 newWidth * rawBytes, /* dst stride */
1256 width, height, /* src */
1257 newWidth, newHeight, /* dst */
1258 rawImage /*src*/, tempImage /*dst*/ );
1259 texImage->TexFormat->StoreImage(ctx, 2, texImage->Format,
1260 texImage->TexFormat, texImage->Data,
1261 xoffset * mml->wScale, yoffset * mml->hScale, 0, /* dstX/Y/Zoffset */
1262 dstRowStride,
1263 0, /* dstImageStride */
1264 newWidth, newHeight, 1,
1265 GL_RGBA, CHAN_TYPE, tempImage, &ctx->DefaultPacking);
1266 FREE(rawImage);
1267 }
1268
1269 FREE(tempImage);
1270
1271 return GL_TRUE;
1272 }
1273
1274
1275 void
1276 fxDDTexImage2D(GLcontext * ctx, GLenum target, GLint level,
1277 GLint internalFormat, GLint width, GLint height, GLint border,
1278 GLenum format, GLenum type, const GLvoid * pixels,
1279 const struct gl_pixelstore_attrib *packing,
1280 struct gl_texture_object *texObj,
1281 struct gl_texture_image *texImage)
1282 {
1283 fxMesaContext fxMesa = FX_CONTEXT(ctx);
1284 tfxTexInfo *ti;
1285 tfxMipMapLevel *mml;
1286 GLint texelBytes, dstRowStride;
1287
1288 if (TDFX_DEBUG & VERBOSE_TEXTURE) {
1289 fprintf(stderr, "fxDDTexImage2D: id=%d int 0x%x format 0x%x type 0x%x %dx%d\n",
1290 texObj->Name, texImage->IntFormat, format, type,
1291 texImage->Width, texImage->Height);
1292 }
1293
1294 if (!fxIsTexSupported(target, internalFormat, texImage)) {
1295 _mesa_problem(NULL, "fx Driver: unsupported texture in fxDDTexImg()\n");
1296 return;
1297 }
1298
1299 if (!texObj->DriverData) {
1300 texObj->DriverData = fxAllocTexObjData(fxMesa);
1301 if (!texObj->DriverData) {
1302 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1303 return;
1304 }
1305 }
1306 ti = fxTMGetTexInfo(texObj);
1307
1308 if (!texImage->DriverData) {
1309 texImage->DriverData = CALLOC(sizeof(tfxMipMapLevel));
1310 if (!texImage->DriverData) {
1311 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1312 return;
1313 }
1314 }
1315 mml = FX_MIPMAP_DATA(texImage);
1316
1317 fxTexGetInfo(width, height, NULL, NULL, NULL, NULL,
1318 &mml->wScale, &mml->hScale);
1319
1320 mml->width = width * mml->wScale;
1321 mml->height = height * mml->hScale;
1322
1323 #if FX_COMPRESS_S3TC_AS_FXT1_HACK
1324 /* [koolsmoky] substitute FXT1 for DXTn and Legacy S3TC */
1325 /* [dBorca] we should update texture's attribute, then,
1326 * because if the application asks us to decompress, we
1327 * have to know the REAL format! Also, DXT3/5 might not
1328 * be correct, since it would mess with "compressedSize".
1329 * Ditto for GL_RGBA[4]_S3TC, which is always mapped to DXT3.
1330 */
1331 if (texImage->IsCompressed) {
1332 switch (internalFormat) {
1333 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1334 case GL_RGB_S3TC:
1335 case GL_RGB4_S3TC:
1336 internalFormat = GL_COMPRESSED_RGB_FXT1_3DFX;
1337 break;
1338 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1339 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
1340 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
1341 case GL_RGBA_S3TC:
1342 case GL_RGBA4_S3TC:
1343 internalFormat = GL_COMPRESSED_RGBA_FXT1_3DFX;
1344 }
1345 texImage->IntFormat = internalFormat;
1346 }
1347 #endif
1348 #if FX_TC_NAPALM
1349 if (fxMesa->type >= GR_SSTTYPE_Voodoo4) {
1350 GLenum texNapalm = 0;
1351 if (internalFormat == GL_COMPRESSED_RGB) {
1352 texNapalm = GL_COMPRESSED_RGB_FXT1_3DFX;
1353 } else if (internalFormat == GL_COMPRESSED_RGBA) {
1354 texNapalm = GL_COMPRESSED_RGBA_FXT1_3DFX;
1355 }
1356 if (texNapalm) {
1357 texImage->IntFormat = internalFormat = texNapalm;
1358 texImage->IsCompressed = GL_TRUE;
1359 }
1360 }
1361 #endif
1362
1363 /* choose the texture format */
1364 assert(ctx->Driver.ChooseTextureFormat);
1365 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
1366 internalFormat, format, type);
1367 assert(texImage->TexFormat);
1368 texelBytes = texImage->TexFormat->TexelBytes;
1369 /*if (!fxMesa->HaveTexFmt) assert(texelBytes == 1 || texelBytes == 2);*/
1370
1371 mml->glideFormat = fxGlideFormat(texImage->TexFormat->MesaFormat);
1372
1373 /* allocate mipmap buffer */
1374 assert(!texImage->Data);
1375 if (texImage->IsCompressed) {
1376 texImage->CompressedSize = _mesa_compressed_texture_size(ctx,
1377 mml->width,
1378 mml->height,
1379 1,
1380 internalFormat);
1381 dstRowStride = _mesa_compressed_row_stride(internalFormat, mml->width);
1382 texImage->Data = MESA_PBUFFER_ALLOC(texImage->CompressedSize);
1383 } else {
1384 dstRowStride = mml->width * texelBytes;
1385 texImage->Data = MESA_PBUFFER_ALLOC(mml->width * mml->height * texelBytes);
1386 }
1387 if (!texImage->Data) {
1388 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1389 return;
1390 }
1391
1392 if (pixels != NULL) {
1393 if (mml->wScale != 1 || mml->hScale != 1) {
1394 /* rescale image to overcome 1:8 aspect limitation */
1395 if (!adjust2DRatio(ctx,
1396 0, 0,
1397 width, height,
1398 format, type, pixels,
1399 packing,
1400 mml,
1401 texImage,
1402 texelBytes,
1403 dstRowStride)
1404 ) {
1405 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1406 return;
1407 }
1408 }
1409 else {
1410 /* no rescaling needed */
1411 /* unpack image, apply transfer ops and store in texImage->Data */
1412 texImage->TexFormat->StoreImage(ctx, 2, texImage->Format,
1413 texImage->TexFormat, texImage->Data,
1414 0, 0, 0, /* dstX/Y/Zoffset */
1415 dstRowStride,
1416 0, /* dstImageStride */
1417 width, height, 1,
1418 format, type, pixels, packing);
1419 }
1420 #if FX_TC_NCC
1421 if (fxMesa->HaveTexus2) {
1422 GLenum texNCC = 0;
1423 GLuint texSize = mml->width * mml->height;
1424 if (internalFormat == GL_COMPRESSED_RGB) {
1425 texNCC = GR_TEXFMT_YIQ_422;
1426 } else if (internalFormat == GL_COMPRESSED_RGBA) {
1427 texNCC = GR_TEXFMT_AYIQ_8422;
1428 texSize <<= 1;
1429 }
1430 if (texNCC) {
1431 TxMip txMip, pxMip;
1432 GLubyte *tempImage = MESA_PBUFFER_ALLOC(texSize);
1433 if (!tempImage) {
1434 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1435 return;
1436 }
1437 txMip.width = mml->width;
1438 txMip.height = mml->height;
1439 txMip.depth = 1;
1440 txMip.data[0] = texImage->Data;
1441 pxMip.data[0] = tempImage;
1442 fxMesa->Glide.txMipQuantize(&pxMip, &txMip, texNCC, TX_DITHER_ERR, TX_COMPRESSION_HEURISTIC);
1443 if (level == 0) {
1444 fxMesa->Glide.txPalToNcc((GuNccTable *)(&(ti->palette)), pxMip.pal);
1445 }
1446 MESA_PBUFFER_FREE(texImage->Data);
1447 texImage->Data = tempImage;
1448 mml->glideFormat = texNCC;
1449 }
1450 }
1451 #endif
1452
1453 /* GL_SGIS_generate_mipmap */
1454 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
1455 GLint mipWidth, mipHeight;
1456 tfxMipMapLevel *mip;
1457 struct gl_texture_image *mipImage;
1458 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1459 const GLint maxLevels = _mesa_max_texture_levels(ctx, texObj->Target);
1460
1461 assert(!texImage->IsCompressed);
1462
1463 while (level < texObj->MaxLevel && level < maxLevels - 1) {
1464 mipWidth = width / 2;
1465 if (!mipWidth) {
1466 mipWidth = 1;
1467 }
1468 mipHeight = height / 2;
1469 if (!mipHeight) {
1470 mipHeight = 1;
1471 }
1472 if ((mipWidth == width) && (mipHeight == height)) {
1473 break;
1474 }
1475 _mesa_TexImage2D(target, ++level, internalFormat,
1476 mipWidth, mipHeight, border,
1477 format, type,
1478 NULL);
1479 mipImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1480 mip = FX_MIPMAP_DATA(mipImage);
1481 _mesa_halve2x2_teximage2d(texelBytes,
1482 mml->width, mml->height,
1483 texImage->Data, mipImage->Data);
1484 texImage = mipImage;
1485 mml = mip;
1486 width = mipWidth;
1487 height = mipHeight;
1488 }
1489 }
1490 }
1491
1492 ti->info.format = mml->glideFormat;
1493 texImage->FetchTexelc = fxFetchFunction(texImage->TexFormat->MesaFormat);
1494
1495 /* [dBorca]
1496 * Hack alert: unsure...
1497 */
1498 if (0 && ti->validated && ti->isInTM) {
1499 /*fprintf(stderr, "reloadmipmaplevels\n"); */
1500 fxTMReloadMipMapLevel(fxMesa, texObj, level);
1501 }
1502 else {
1503 /*fprintf(stderr, "invalidate2\n"); */
1504 fxTexInvalidate(ctx, texObj);
1505 }
1506 }
1507
1508
1509 void
1510 fxDDTexSubImage2D(GLcontext * ctx, GLenum target, GLint level,
1511 GLint xoffset, GLint yoffset,
1512 GLsizei width, GLsizei height,
1513 GLenum format, GLenum type, const GLvoid * pixels,
1514 const struct gl_pixelstore_attrib *packing,
1515 struct gl_texture_object *texObj,
1516 struct gl_texture_image *texImage)
1517 {
1518 fxMesaContext fxMesa = FX_CONTEXT(ctx);
1519 tfxTexInfo *ti;
1520 tfxMipMapLevel *mml;
1521 GLint texelBytes, dstRowStride;
1522
1523 /* [dBorca] Hack alert:
1524 * FX_TC_NCC not supported
1525 */
1526
1527 if (TDFX_DEBUG & VERBOSE_TEXTURE) {
1528 fprintf(stderr, "fxDDTexSubImage2D: id=%d\n", texObj->Name);
1529 }
1530
1531 if (!texObj->DriverData) {
1532 _mesa_problem(ctx, "problem in fxDDTexSubImage2D");
1533 return;
1534 }
1535
1536 ti = fxTMGetTexInfo(texObj);
1537 assert(ti);
1538 mml = FX_MIPMAP_DATA(texImage);
1539 assert(mml);
1540
1541 assert(texImage->Data); /* must have an existing texture image! */
1542 assert(texImage->Format);
1543
1544 texelBytes = texImage->TexFormat->TexelBytes;
1545 if (texImage->IsCompressed) {
1546 dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat, mml->width);
1547 } else {
1548 dstRowStride = mml->width * texelBytes;
1549 }
1550
1551 if (mml->wScale != 1 || mml->hScale != 1) {
1552 /* need to rescale subimage to match mipmap level's rescale factors */
1553 if (!adjust2DRatio(ctx,
1554 xoffset, yoffset,
1555 width, height,
1556 format, type, pixels,
1557 packing,
1558 mml,
1559 texImage,
1560 texelBytes,
1561 dstRowStride)
1562 ) {
1563 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
1564 return;
1565 }
1566 }
1567 else {
1568 /* no rescaling needed */
1569 texImage->TexFormat->StoreImage(ctx, 2, texImage->Format,
1570 texImage->TexFormat, (GLubyte *) texImage->Data,
1571 xoffset, yoffset, 0, /* dstX/Y/Zoffset */
1572 dstRowStride,
1573 0, /* dstImageStride */
1574 width, height, 1,
1575 format, type, pixels, packing);
1576 }
1577
1578 /* GL_SGIS_generate_mipmap */
1579 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
1580 GLint mipWidth, mipHeight;
1581 tfxMipMapLevel *mip;
1582 struct gl_texture_image *mipImage;
1583 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1584 const GLint maxLevels = _mesa_max_texture_levels(ctx, texObj->Target);
1585
1586 assert(!texImage->IsCompressed);
1587
1588 width = texImage->Width;
1589 height = texImage->Height;
1590 while (level < texObj->MaxLevel && level < maxLevels - 1) {
1591 mipWidth = width / 2;
1592 if (!mipWidth) {
1593 mipWidth = 1;
1594 }
1595 mipHeight = height / 2;
1596 if (!mipHeight) {
1597 mipHeight = 1;
1598 }
1599 if ((mipWidth == width) && (mipHeight == height)) {
1600 break;
1601 }
1602 ++level;
1603 mipImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1604 mip = FX_MIPMAP_DATA(mipImage);
1605 _mesa_halve2x2_teximage2d(texelBytes,
1606 mml->width, mml->height,
1607 texImage->Data, mipImage->Data);
1608 texImage = mipImage;
1609 mml = mip;
1610 width = mipWidth;
1611 height = mipHeight;
1612 }
1613 }
1614
1615 if (ti->validated && ti->isInTM && !texObj->GenerateMipmap)
1616 fxTMReloadMipMapLevel(fxMesa, texObj, level);
1617 else
1618 fxTexInvalidate(ctx, texObj);
1619 }
1620
1621
1622 void
1623 fxDDCompressedTexImage2D (GLcontext *ctx, GLenum target,
1624 GLint level, GLint internalFormat,
1625 GLsizei width, GLsizei height, GLint border,
1626 GLsizei imageSize, const GLvoid *data,
1627 struct gl_texture_object *texObj,
1628 struct gl_texture_image *texImage)
1629 {
1630 fxMesaContext fxMesa = FX_CONTEXT(ctx);
1631 tfxTexInfo *ti;
1632 tfxMipMapLevel *mml;
1633
1634 if (TDFX_DEBUG & VERBOSE_TEXTURE) {
1635 fprintf(stderr, "fxDDCompressedTexImage2D: id=%d int 0x%x %dx%d\n",
1636 texObj->Name, internalFormat,
1637 width, height);
1638 }
1639
1640 assert(texImage->IsCompressed);
1641
1642 if (!fxIsTexSupported(target, internalFormat, texImage)) {
1643 _mesa_problem(NULL, "fx Driver: unsupported texture in fxDDCompressedTexImg()\n");
1644 return;
1645 }
1646
1647 if (!texObj->DriverData) {
1648 texObj->DriverData = fxAllocTexObjData(fxMesa);
1649 if (!texObj->DriverData) {
1650 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
1651 return;
1652 }
1653 }
1654 ti = fxTMGetTexInfo(texObj);
1655
1656 if (!texImage->DriverData) {
1657 texImage->DriverData = CALLOC(sizeof(tfxMipMapLevel));
1658 if (!texImage->DriverData) {
1659 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
1660 return;
1661 }
1662 }
1663 mml = FX_MIPMAP_DATA(texImage);
1664
1665 fxTexGetInfo(width, height, NULL, NULL, NULL, NULL,
1666 &mml->wScale, &mml->hScale);
1667
1668 mml->width = width * mml->wScale;
1669 mml->height = height * mml->hScale;
1670
1671
1672 /* choose the texture format */
1673 assert(ctx->Driver.ChooseTextureFormat);
1674 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
1675 internalFormat, -1/*format*/, -1/*type*/);
1676 assert(texImage->TexFormat);
1677
1678 /* Determine the appropriate Glide texel format,
1679 * given the user's internal texture format hint.
1680 */
1681 mml->glideFormat = fxGlideFormat(texImage->TexFormat->MesaFormat);
1682
1683 /* allocate new storage for texture image, if needed */
1684 if (!texImage->Data) {
1685 texImage->CompressedSize = _mesa_compressed_texture_size(ctx,
1686 mml->width,
1687 mml->height,
1688 1,
1689 internalFormat);
1690 texImage->Data = MESA_PBUFFER_ALLOC(texImage->CompressedSize);
1691 if (!texImage->Data) {
1692 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
1693 return;
1694 }
1695 }
1696
1697 /* save the texture data */
1698 if (mml->wScale != 1 || mml->hScale != 1) {
1699 /* [dBorca] Hack alert:
1700 * now we're screwed. We can't decompress,
1701 * unless we do it in HW (via textureBuffer).
1702 * We still have some chances:
1703 * 1) we got FXT1 textures - we CAN decompress, rescale for
1704 * aspectratio, then compress back.
1705 * 2) there is a chance that MIN("s", "t") won't be overflowed.
1706 * Thus, we don't care about textureclamp and we could lower
1707 * MIN("uscale", "vscale") below 32. We still have to have
1708 * our data aligned inside a 8:1 rectangle.
1709 * 3) just in case if MIN("s", "t") gets overflowed with GL_REPEAT,
1710 * we replicate the data over the padded area.
1711 * For now, we take 2) + 3) but texelfetchers will be wrong!
1712 */
1713 GLuint srcRowStride = _mesa_compressed_row_stride(internalFormat, width);
1714
1715 GLuint destRowStride = _mesa_compressed_row_stride(internalFormat,
1716 mml->width);
1717
1718 _mesa_upscale_teximage2d(srcRowStride, (height+3) / 4,
1719 destRowStride, (mml->height+3) / 4,
1720 1, data, srcRowStride,
1721 texImage->Data);
1722 ti->padded = GL_TRUE;
1723 } else {
1724 MEMCPY(texImage->Data, data, texImage->CompressedSize);
1725 }
1726
1727 ti->info.format = mml->glideFormat;
1728 texImage->FetchTexelc = fxFetchFunction(texImage->TexFormat->MesaFormat);
1729
1730 /* GL_SGIS_generate_mipmap */
1731 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
1732 assert(!texImage->IsCompressed);
1733 }
1734
1735 /* [dBorca]
1736 * Hack alert: unsure...
1737 */
1738 if (0 && ti->validated && ti->isInTM) {
1739 /*fprintf(stderr, "reloadmipmaplevels\n"); */
1740 fxTMReloadMipMapLevel(fxMesa, texObj, level);
1741 }
1742 else {
1743 /*fprintf(stderr, "invalidate2\n"); */
1744 fxTexInvalidate(ctx, texObj);
1745 }
1746 }
1747
1748
1749 void
1750 fxDDCompressedTexSubImage2D( GLcontext *ctx, GLenum target,
1751 GLint level, GLint xoffset,
1752 GLint yoffset, GLsizei width,
1753 GLint height, GLenum format,
1754 GLsizei imageSize, const GLvoid *data,
1755 struct gl_texture_object *texObj,
1756 struct gl_texture_image *texImage )
1757 {
1758 fxMesaContext fxMesa = FX_CONTEXT(ctx);
1759 tfxTexInfo *ti;
1760 tfxMipMapLevel *mml;
1761 GLint destRowStride, srcRowStride;
1762 GLint i, rows;
1763 GLubyte *dest;
1764
1765 if (TDFX_DEBUG & VERBOSE_TEXTURE) {
1766 fprintf(stderr, "fxDDCompressedTexSubImage2D: id=%d\n", texObj->Name);
1767 }
1768
1769 ti = fxTMGetTexInfo(texObj);
1770 assert(ti);
1771 mml = FX_MIPMAP_DATA(texImage);
1772 assert(mml);
1773
1774 srcRowStride = _mesa_compressed_row_stride(texImage->IntFormat, width);
1775
1776 destRowStride = _mesa_compressed_row_stride(texImage->IntFormat,
1777 mml->width);
1778 dest = _mesa_compressed_image_address(xoffset, yoffset, 0,
1779 texImage->IntFormat,
1780 mml->width,
1781 (GLubyte*) texImage->Data);
1782
1783 rows = height / 4; /* [dBorca] hardcoded 4, but works for FXT1/DXTC */
1784
1785 for (i = 0; i < rows; i++) {
1786 MEMCPY(dest, data, srcRowStride);
1787 dest += destRowStride;
1788 data = (GLvoid *)((GLuint)data + (GLuint)srcRowStride);
1789 }
1790
1791 /* [dBorca] Hack alert:
1792 * see fxDDCompressedTexImage2D for caveats
1793 */
1794 if (mml->wScale != 1 || mml->hScale != 1) {
1795 srcRowStride = _mesa_compressed_row_stride(texImage->IntFormat, texImage->Width);
1796
1797 destRowStride = _mesa_compressed_row_stride(texImage->IntFormat,
1798 mml->width);
1799 _mesa_upscale_teximage2d(srcRowStride, texImage->Height / 4,
1800 destRowStride, mml->height / 4,
1801 1, texImage->Data, destRowStride,
1802 texImage->Data);
1803 }
1804
1805 /* GL_SGIS_generate_mipmap */
1806 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
1807 assert(!texImage->IsCompressed);
1808 }
1809
1810 if (ti->validated && ti->isInTM)
1811 fxTMReloadMipMapLevel(fxMesa, texObj, level);
1812 else
1813 fxTexInvalidate(ctx, texObj);
1814 }
1815
1816
1817 void
1818 fxDDTexImage1D (GLcontext *ctx, GLenum target, GLint level,
1819 GLint internalFormat, GLint width, GLint border,
1820 GLenum format, GLenum type, const GLvoid *pixels,
1821 const struct gl_pixelstore_attrib *packing,
1822 struct gl_texture_object *texObj,
1823 struct gl_texture_image *texImage)
1824 {
1825 fxDDTexImage2D(ctx, target, level,
1826 internalFormat, width, 1, border,
1827 format, type, pixels,
1828 packing,
1829 texObj,
1830 texImage);
1831 }
1832
1833
1834 void
1835 fxDDTexSubImage1D(GLcontext * ctx, GLenum target, GLint level,
1836 GLint xoffset,
1837 GLsizei width,
1838 GLenum format, GLenum type, const GLvoid * pixels,
1839 const struct gl_pixelstore_attrib *packing,
1840 struct gl_texture_object *texObj,
1841 struct gl_texture_image *texImage)
1842 {
1843 fxDDTexSubImage2D(ctx, target, level,
1844 xoffset, 0, width, 1,
1845 format, type, pixels,
1846 packing,
1847 texObj,
1848 texImage);
1849 }
1850
1851
1852 GLboolean
1853 fxDDTestProxyTexImage (GLcontext *ctx, GLenum target,
1854 GLint level, GLint internalFormat,
1855 GLenum format, GLenum type,
1856 GLint width, GLint height,
1857 GLint depth, GLint border)
1858 {
1859 /* [dBorca]
1860 * TODO - maybe through fxTexValidate()
1861 */
1862 return _mesa_test_proxy_teximage(ctx, target,
1863 level, internalFormat,
1864 format, type,
1865 width, height,
1866 depth, border);
1867 }
1868
1869
1870 #else /* FX */
1871
1872 /*
1873 * Need this to provide at least one external definition.
1874 */
1875
1876 extern int gl_fx_dummy_function_ddtex(void);
1877 int
1878 gl_fx_dummy_function_ddtex(void)
1879 {
1880 return 0;
1881 }
1882
1883 #endif /* FX */