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