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