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