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