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