updates from Daniel Borca
[mesa.git] / src / mesa / drivers / glide / fxddtex.c
1 /* $Id: fxddtex.c,v 1.48 2003/10/02 17:36:44 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 4.0
6 *
7 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27 /* Authors:
28 * David Bucciarelli
29 * Brian Paul
30 * Daryll Strauss
31 * Keith Whitwell
32 * Daniel Borca
33 * Hiroshi Morii
34 */
35
36
37 #ifdef HAVE_CONFIG_H
38 #include "conf.h"
39 #endif
40
41 #if defined(FX)
42
43 #include "fxdrv.h"
44 #include "image.h"
45 #include "teximage.h"
46 #include "texformat.h"
47 #include "texstore.h"
48 #include "texutil.h"
49
50
51 void
52 fxPrintTextureData(tfxTexInfo * ti)
53 {
54 fprintf(stderr, "Texture Data:\n");
55 if (ti->tObj) {
56 fprintf(stderr, "\tName: %d\n", ti->tObj->Name);
57 fprintf(stderr, "\tBaseLevel: %d\n", ti->tObj->BaseLevel);
58 fprintf(stderr, "\tSize: %d x %d\n",
59 ti->tObj->Image[ti->tObj->BaseLevel]->Width,
60 ti->tObj->Image[ti->tObj->BaseLevel]->Height);
61 }
62 else
63 fprintf(stderr, "\tName: UNNAMED\n");
64 fprintf(stderr, "\tLast used: %d\n", ti->lastTimeUsed);
65 fprintf(stderr, "\tTMU: %ld\n", ti->whichTMU);
66 fprintf(stderr, "\t%s\n", (ti->isInTM) ? "In TMU" : "Not in TMU");
67 if (ti->tm[0])
68 fprintf(stderr, "\tMem0: %x-%x\n", (unsigned) ti->tm[0]->startAddr,
69 (unsigned) ti->tm[0]->endAddr);
70 if (ti->tm[1])
71 fprintf(stderr, "\tMem1: %x-%x\n", (unsigned) ti->tm[1]->startAddr,
72 (unsigned) ti->tm[1]->endAddr);
73 fprintf(stderr, "\tMipmaps: %d-%d\n", ti->minLevel, ti->maxLevel);
74 fprintf(stderr, "\tFilters: min %d min %d\n",
75 (int) ti->minFilt, (int) ti->maxFilt);
76 fprintf(stderr, "\tClamps: s %d t %d\n", (int) ti->sClamp,
77 (int) ti->tClamp);
78 fprintf(stderr, "\tScales: s %f t %f\n", ti->sScale, ti->tScale);
79 fprintf(stderr, "\t%s\n",
80 (ti->fixedPalette) ? "Fixed palette" : "Non fixed palette");
81 fprintf(stderr, "\t%s\n", (ti->validated) ? "Validated" : "Not validated");
82 }
83
84
85 /************************************************************************/
86 /*************************** Texture Mapping ****************************/
87 /************************************************************************/
88
89 static void
90 fxTexInvalidate(GLcontext * ctx, struct gl_texture_object *tObj)
91 {
92 fxMesaContext fxMesa = FX_CONTEXT(ctx);
93 tfxTexInfo *ti;
94
95 ti = fxTMGetTexInfo(tObj);
96 if (ti->isInTM)
97 fxTMMoveOutTM(fxMesa, tObj); /* TO DO: SLOW but easy to write */
98
99 ti->validated = GL_FALSE;
100 fxMesa->new_state |= FX_NEW_TEXTURING;
101 }
102
103 static tfxTexInfo *
104 fxAllocTexObjData(fxMesaContext fxMesa)
105 {
106 tfxTexInfo *ti;
107
108 if (!(ti = CALLOC(sizeof(tfxTexInfo)))) {
109 fprintf(stderr, "%s: ERROR: out of memory !\n", __FUNCTION__);
110 fxCloseHardware();
111 exit(-1);
112 }
113
114 ti->validated = GL_FALSE;
115 ti->isInTM = GL_FALSE;
116
117 ti->whichTMU = FX_TMU_NONE;
118
119 ti->tm[FX_TMU0] = NULL;
120 ti->tm[FX_TMU1] = NULL;
121
122 ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
123 ti->maxFilt = GR_TEXTUREFILTER_BILINEAR;
124
125 ti->sClamp = GR_TEXTURECLAMP_WRAP;
126 ti->tClamp = GR_TEXTURECLAMP_WRAP;
127
128 ti->mmMode = GR_MIPMAP_NEAREST;
129 ti->LODblend = FXFALSE;
130
131 return ti;
132 }
133
134 void
135 fxDDTexBind(GLcontext * ctx, GLenum target, struct gl_texture_object *tObj)
136 {
137 fxMesaContext fxMesa = FX_CONTEXT(ctx);
138 tfxTexInfo *ti;
139
140 if (TDFX_DEBUG & VERBOSE_DRIVER) {
141 fprintf(stderr, "%s(%d, %x)\n", __FUNCTION__, tObj->Name,
142 (GLuint) tObj->DriverData);
143 }
144
145 if (target != GL_TEXTURE_2D)
146 return;
147
148 if (!tObj->DriverData) {
149 tObj->DriverData = fxAllocTexObjData(fxMesa);
150 }
151
152 ti = fxTMGetTexInfo(tObj);
153
154 fxMesa->texBindNumber++;
155 ti->lastTimeUsed = fxMesa->texBindNumber;
156
157 fxMesa->new_state |= FX_NEW_TEXTURING;
158 }
159
160 void
161 fxDDTexEnv(GLcontext * ctx, GLenum target, GLenum pname,
162 const GLfloat * param)
163 {
164 fxMesaContext fxMesa = FX_CONTEXT(ctx);
165
166 if (TDFX_DEBUG & VERBOSE_DRIVER) {
167 if (param)
168 fprintf(stderr, "%s(%x, %x)\n", __FUNCTION__, pname, (GLint) (*param));
169 else
170 fprintf(stderr, "%s(%x)\n", __FUNCTION__, pname);
171 }
172
173 /* apply any lod biasing right now */
174 if (pname == GL_TEXTURE_LOD_BIAS_EXT) {
175 grTexLodBiasValue(GR_TMU0, *param);
176
177 if (fxMesa->haveTwoTMUs) {
178 grTexLodBiasValue(GR_TMU1, *param);
179 }
180
181 }
182
183 fxMesa->new_state |= FX_NEW_TEXTURING;
184 }
185
186 void
187 fxDDTexParam(GLcontext * ctx, GLenum target, struct gl_texture_object *tObj,
188 GLenum pname, const GLfloat * params)
189 {
190 fxMesaContext fxMesa = FX_CONTEXT(ctx);
191 GLenum param = (GLenum) (GLint) params[0];
192 tfxTexInfo *ti;
193
194 if (TDFX_DEBUG & VERBOSE_DRIVER) {
195 fprintf(stderr, "%s(%d, %x, %x, %x)\n", __FUNCTION__,
196 tObj->Name, (GLuint) tObj->DriverData, pname, param);
197 }
198
199 if (target != GL_TEXTURE_2D)
200 return;
201
202 if (!tObj->DriverData)
203 tObj->DriverData = fxAllocTexObjData(fxMesa);
204
205 ti = fxTMGetTexInfo(tObj);
206
207 switch (pname) {
208
209 case GL_TEXTURE_MIN_FILTER:
210 switch (param) {
211 case GL_NEAREST:
212 ti->mmMode = GR_MIPMAP_DISABLE;
213 ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
214 ti->LODblend = FXFALSE;
215 break;
216 case GL_LINEAR:
217 ti->mmMode = GR_MIPMAP_DISABLE;
218 ti->minFilt = GR_TEXTUREFILTER_BILINEAR;
219 ti->LODblend = FXFALSE;
220 break;
221 case GL_NEAREST_MIPMAP_LINEAR:
222 if (fxMesa->haveTwoTMUs) {
223 ti->mmMode = GR_MIPMAP_NEAREST;
224 ti->LODblend = FXTRUE;
225 }
226 else {
227 ti->mmMode = GR_MIPMAP_NEAREST_DITHER;
228 ti->LODblend = FXFALSE;
229 }
230 ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
231 break; /* ZZZ: we may have to fall through here for V3 */
232 case GL_NEAREST_MIPMAP_NEAREST:
233 ti->mmMode = GR_MIPMAP_NEAREST;
234 ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
235 ti->LODblend = FXFALSE;
236 break;
237 case GL_LINEAR_MIPMAP_LINEAR:
238 /* ZZZ: HACK ALERT! trilinear is bugged! mipmap blending produce
239 incorrect filtered colors for the smallest mipmap levels. */
240 #if 0
241 if (fxMesa->haveTwoTMUs) {
242 ti->mmMode = GR_MIPMAP_NEAREST;
243 ti->LODblend = FXTRUE;
244 }
245 else {
246 ti->mmMode = GR_MIPMAP_NEAREST_DITHER;
247 ti->LODblend = FXFALSE;
248 }
249 ti->minFilt = GR_TEXTUREFILTER_BILINEAR;
250 break; /* ZZZ: we may have to fall through here for V3 */
251 #endif
252 case GL_LINEAR_MIPMAP_NEAREST:
253 ti->mmMode = GR_MIPMAP_NEAREST;
254 ti->minFilt = GR_TEXTUREFILTER_BILINEAR;
255 ti->LODblend = FXFALSE;
256 break;
257 default:
258 break;
259 }
260 fxTexInvalidate(ctx, tObj);
261 break;
262
263 case GL_TEXTURE_MAG_FILTER:
264 switch (param) {
265 case GL_NEAREST:
266 ti->maxFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
267 break;
268 case GL_LINEAR:
269 ti->maxFilt = GR_TEXTUREFILTER_BILINEAR;
270 break;
271 default:
272 break;
273 }
274 fxTexInvalidate(ctx, tObj);
275 break;
276
277 case GL_TEXTURE_WRAP_S:
278 switch (param) {
279 case GL_MIRRORED_REPEAT:
280 ti->sClamp = GR_TEXTURECLAMP_MIRROR_EXT;
281 break;
282 case GL_CLAMP:
283 ti->sClamp = GR_TEXTURECLAMP_CLAMP;
284 break;
285 case GL_REPEAT:
286 ti->sClamp = GR_TEXTURECLAMP_WRAP;
287 break;
288 default:
289 break;
290 }
291 fxMesa->new_state |= FX_NEW_TEXTURING;
292 break;
293
294 case GL_TEXTURE_WRAP_T:
295 switch (param) {
296 case GL_MIRRORED_REPEAT:
297 ti->tClamp = GR_TEXTURECLAMP_MIRROR_EXT;
298 break;
299 case GL_CLAMP:
300 ti->tClamp = GR_TEXTURECLAMP_CLAMP;
301 break;
302 case GL_REPEAT:
303 ti->tClamp = GR_TEXTURECLAMP_WRAP;
304 break;
305 default:
306 break;
307 }
308 fxMesa->new_state |= FX_NEW_TEXTURING;
309 break;
310
311 case GL_TEXTURE_BORDER_COLOR:
312 /* TO DO */
313 break;
314
315 case GL_TEXTURE_MIN_LOD:
316 /* TO DO */
317 break;
318 case GL_TEXTURE_MAX_LOD:
319 /* TO DO */
320 break;
321 case GL_TEXTURE_BASE_LEVEL:
322 fxTexInvalidate(ctx, tObj);
323 break;
324 case GL_TEXTURE_MAX_LEVEL:
325 fxTexInvalidate(ctx, tObj);
326 break;
327
328 default:
329 break;
330 }
331 }
332
333 void
334 fxDDTexDel(GLcontext * ctx, struct gl_texture_object *tObj)
335 {
336 fxMesaContext fxMesa = FX_CONTEXT(ctx);
337 tfxTexInfo *ti = fxTMGetTexInfo(tObj);
338
339 if (TDFX_DEBUG & VERBOSE_DRIVER) {
340 fprintf(stderr, "%s(%d, %p)\n", __FUNCTION__, tObj->Name, (void *) ti);
341 }
342
343 if (!ti)
344 return;
345
346 fxTMFreeTexture(fxMesa, tObj);
347
348 FREE(ti);
349 tObj->DriverData = NULL;
350 }
351
352
353
354 /*
355 * Convert a gl_color_table texture palette to Glide's format.
356 */
357 static void
358 convertPalette(FxU32 data[256], const struct gl_color_table *table)
359 {
360 const GLubyte *tableUB = (const GLubyte *) table->Table;
361 GLint width = table->Size;
362 FxU32 r, g, b, a;
363 GLint i;
364
365 ASSERT(!table->FloatTable);
366
367 switch (table->Format) {
368 case GL_INTENSITY:
369 for (i = 0; i < width; i++) {
370 r = tableUB[i];
371 g = tableUB[i];
372 b = tableUB[i];
373 a = tableUB[i];
374 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
375 }
376 break;
377 case GL_LUMINANCE:
378 for (i = 0; i < width; i++) {
379 r = tableUB[i];
380 g = tableUB[i];
381 b = tableUB[i];
382 a = 255;
383 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
384 }
385 break;
386 case GL_ALPHA:
387 for (i = 0; i < width; i++) {
388 r = g = b = 255;
389 a = tableUB[i];
390 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
391 }
392 break;
393 case GL_LUMINANCE_ALPHA:
394 for (i = 0; i < width; i++) {
395 r = g = b = tableUB[i * 2 + 0];
396 a = tableUB[i * 2 + 1];
397 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
398 }
399 break;
400 case GL_RGB:
401 for (i = 0; i < width; i++) {
402 r = tableUB[i * 3 + 0];
403 g = tableUB[i * 3 + 1];
404 b = tableUB[i * 3 + 2];
405 a = 255;
406 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
407 }
408 break;
409 case GL_RGBA:
410 for (i = 0; i < width; i++) {
411 r = tableUB[i * 4 + 0];
412 g = tableUB[i * 4 + 1];
413 b = tableUB[i * 4 + 2];
414 a = tableUB[i * 4 + 3];
415 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
416 }
417 break;
418 }
419 }
420
421
422 void
423 fxDDTexPalette(GLcontext * ctx, struct gl_texture_object *tObj)
424 {
425 fxMesaContext fxMesa = FX_CONTEXT(ctx);
426
427 if (tObj) {
428 /* per-texture palette */
429 tfxTexInfo *ti;
430 if (TDFX_DEBUG & VERBOSE_DRIVER) {
431 fprintf(stderr, "%s(%d, %x)\n", __FUNCTION__,
432 tObj->Name, (GLuint) tObj->DriverData);
433 }
434 if (!tObj->DriverData)
435 tObj->DriverData = fxAllocTexObjData(fxMesa);
436 ti = fxTMGetTexInfo(tObj);
437 convertPalette(ti->palette.data, &tObj->Palette);
438 fxTexInvalidate(ctx, tObj);
439 }
440 else {
441 /* global texture palette */
442 if (TDFX_DEBUG & VERBOSE_DRIVER) {
443 fprintf(stderr, "%s(global)\n", __FUNCTION__);
444 }
445 convertPalette(fxMesa->glbPalette.data, &ctx->Texture.Palette);
446 fxMesa->new_state |= FX_NEW_TEXTURING;
447 }
448 }
449
450
451 void
452 fxDDTexUseGlbPalette(GLcontext * ctx, GLboolean state)
453 {
454 fxMesaContext fxMesa = FX_CONTEXT(ctx);
455
456 if (TDFX_DEBUG & VERBOSE_DRIVER) {
457 fprintf(stderr, "%s(%d)\n", __FUNCTION__, state);
458 }
459
460 if (state) {
461 fxMesa->haveGlobalPaletteTexture = 1;
462
463 grTexDownloadTable(GR_TEXTABLE_PALETTE, &(fxMesa->glbPalette));
464 }
465 else {
466 fxMesa->haveGlobalPaletteTexture = 0;
467
468 if ((ctx->Texture.Unit[0]._Current == ctx->Texture.Unit[0].Current2D) &&
469 (ctx->Texture.Unit[0]._Current != NULL)) {
470 struct gl_texture_object *tObj = ctx->Texture.Unit[0]._Current;
471
472 if (!tObj->DriverData)
473 tObj->DriverData = fxAllocTexObjData(fxMesa);
474
475 fxTexInvalidate(ctx, tObj);
476 }
477 }
478 }
479
480
481 static int
482 logbase2(int n)
483 {
484 GLint i = 1;
485 GLint log2 = 0;
486
487 if (n < 0) {
488 return -1;
489 }
490
491 while (n > i) {
492 i *= 2;
493 log2++;
494 }
495 if (i != n) {
496 return -1;
497 }
498 else {
499 return log2;
500 }
501 }
502
503
504 int
505 fxTexGetInfo(int w, int h, GrLOD_t * lodlevel, GrAspectRatio_t * ar,
506 float *sscale, float *tscale,
507 int *wscale, int *hscale)
508 {
509 /* [koolsmoky] */
510 static GrLOD_t lod[12] = {
511 GR_LOD_LOG2_1,
512 GR_LOD_LOG2_2,
513 GR_LOD_LOG2_4,
514 GR_LOD_LOG2_8,
515 GR_LOD_LOG2_16,
516 GR_LOD_LOG2_32,
517 GR_LOD_LOG2_64,
518 GR_LOD_LOG2_128,
519 GR_LOD_LOG2_256,
520 GR_LOD_LOG2_512,
521 GR_LOD_LOG2_1024,
522 GR_LOD_LOG2_2048
523 };
524
525 int logw, logh, ws, hs;
526 GrLOD_t l;
527 GrAspectRatio_t aspectratio;
528 float s, t;
529
530 logw = logbase2(w);
531 logh = logbase2(h);
532
533 switch (logw - logh) {
534 case 0:
535 aspectratio = GR_ASPECT_LOG2_1x1;
536 l = lod[logw];
537 s = t = 256.0f;
538 ws = hs = 1;
539 break;
540 case 1:
541 aspectratio = GR_ASPECT_LOG2_2x1;
542 l = lod[logw];
543 s = 256.0f;
544 t = 128.0f;
545 ws = 1;
546 hs = 1;
547 break;
548 case 2:
549 aspectratio = GR_ASPECT_LOG2_4x1;
550 l = lod[logw];
551 s = 256.0f;
552 t = 64.0f;
553 ws = 1;
554 hs = 1;
555 break;
556 case 3:
557 aspectratio = GR_ASPECT_LOG2_8x1;
558 l = lod[logw];
559 s = 256.0f;
560 t = 32.0f;
561 ws = 1;
562 hs = 1;
563 break;
564 case -1:
565 aspectratio = GR_ASPECT_LOG2_1x2;
566 l = lod[logh];
567 s = 128.0f;
568 t = 256.0f;
569 ws = 1;
570 hs = 1;
571 break;
572 case -2:
573 aspectratio = GR_ASPECT_LOG2_1x4;
574 l = lod[logh];
575 s = 64.0f;
576 t = 256.0f;
577 ws = 1;
578 hs = 1;
579 break;
580 case -3:
581 aspectratio = GR_ASPECT_LOG2_1x8;
582 l = lod[logh];
583 s = 32.0f;
584 t = 256.0f;
585 ws = 1;
586 hs = 1;
587 break;
588 default:
589 if ((logw - logh) > 3) {
590 aspectratio = GR_ASPECT_LOG2_8x1;
591 l = lod[logw];
592 s = 256.0f;
593 t = 32.0f;
594 ws = 1;
595 hs = 1 << (logw - logh - 3);
596 } else /*if ((logw - logh) < -3)*/ {
597 aspectratio = GR_ASPECT_LOG2_1x8;
598 l = lod[logh];
599 s = 32.0f;
600 t = 256.0f;
601 ws = 1 << (logh - logw - 3);
602 hs = 1;
603 }
604 }
605
606 if (lodlevel)
607 (*lodlevel) = l;
608
609 if (ar)
610 (*ar) = aspectratio;
611
612 if (sscale)
613 (*sscale) = s;
614
615 if (tscale)
616 (*tscale) = t;
617
618 if (wscale)
619 (*wscale) = ws;
620
621 if (hscale)
622 (*hscale) = hs;
623
624
625 return 1;
626 }
627
628 /*
629 * Given an OpenGL internal texture format, return the corresponding
630 * Glide internal texture format and base texture format.
631 */
632 void
633 fxTexGetFormat(GLcontext *ctx, GLenum glformat, GrTextureFormat_t * tfmt, GLint * ifmt) /* [koolsmoky] */
634 {
635 fxMesaContext fxMesa = FX_CONTEXT(ctx);
636 GLboolean allow32bpt = fxMesa->HaveTexFmt;
637
638 switch (glformat) {
639 case 1:
640 case GL_LUMINANCE:
641 case GL_LUMINANCE4:
642 case GL_LUMINANCE8:
643 case GL_LUMINANCE12:
644 case GL_LUMINANCE16:
645 if (tfmt)
646 (*tfmt) = GR_TEXFMT_INTENSITY_8;
647 if (ifmt)
648 (*ifmt) = GL_LUMINANCE;
649 break;
650 case 2:
651 case GL_LUMINANCE_ALPHA:
652 case GL_LUMINANCE4_ALPHA4:
653 case GL_LUMINANCE6_ALPHA2:
654 case GL_LUMINANCE8_ALPHA8:
655 case GL_LUMINANCE12_ALPHA4:
656 case GL_LUMINANCE12_ALPHA12:
657 case GL_LUMINANCE16_ALPHA16:
658 if (tfmt)
659 (*tfmt) = GR_TEXFMT_ALPHA_INTENSITY_88;
660 if (ifmt)
661 (*ifmt) = GL_LUMINANCE_ALPHA;
662 break;
663 case GL_INTENSITY:
664 case GL_INTENSITY4:
665 case GL_INTENSITY8:
666 case GL_INTENSITY12:
667 case GL_INTENSITY16:
668 if (tfmt)
669 (*tfmt) = GR_TEXFMT_ALPHA_8;
670 if (ifmt)
671 (*ifmt) = GL_INTENSITY;
672 break;
673 case GL_ALPHA:
674 case GL_ALPHA4:
675 case GL_ALPHA8:
676 case GL_ALPHA12:
677 case GL_ALPHA16:
678 if (tfmt)
679 (*tfmt) = GR_TEXFMT_ALPHA_8;
680 if (ifmt)
681 (*ifmt) = GL_ALPHA;
682 break;
683 case GL_R3_G3_B2:
684 case GL_RGB4:
685 case GL_RGB5:
686 if (tfmt)
687 (*tfmt) = GR_TEXFMT_RGB_565;
688 if (ifmt)
689 (*ifmt) = GL_RGB;
690 break;
691 case 3:
692 case GL_RGB:
693 case GL_RGB8:
694 case GL_RGB10:
695 case GL_RGB12:
696 case GL_RGB16:
697 if (tfmt)
698 (*tfmt) = allow32bpt ? GR_TEXFMT_ARGB_8888 : GR_TEXFMT_RGB_565;
699 if (ifmt)
700 (*ifmt) = GL_RGB;
701 break;
702 case GL_RGBA2:
703 case GL_RGBA4:
704 if (tfmt)
705 (*tfmt) = GR_TEXFMT_ARGB_4444;
706 if (ifmt)
707 (*ifmt) = GL_RGBA;
708 break;
709 case 4:
710 case GL_RGBA:
711 case GL_RGBA8:
712 case GL_RGB10_A2:
713 case GL_RGBA12:
714 case GL_RGBA16:
715 if (tfmt)
716 (*tfmt) = allow32bpt ? GR_TEXFMT_ARGB_8888 : GR_TEXFMT_ARGB_4444;
717 if (ifmt)
718 (*ifmt) = GL_RGBA;
719 break;
720 case GL_RGB5_A1:
721 if (tfmt)
722 (*tfmt) = GR_TEXFMT_ARGB_1555;
723 if (ifmt)
724 (*ifmt) = GL_RGBA;
725 break;
726 case GL_COLOR_INDEX:
727 case GL_COLOR_INDEX1_EXT:
728 case GL_COLOR_INDEX2_EXT:
729 case GL_COLOR_INDEX4_EXT:
730 case GL_COLOR_INDEX8_EXT:
731 case GL_COLOR_INDEX12_EXT:
732 case GL_COLOR_INDEX16_EXT:
733 if (tfmt)
734 (*tfmt) = GR_TEXFMT_P_8;
735 if (ifmt)
736 (*ifmt) = GL_RGBA; /* XXX why is this RGBA? */
737 break;
738 default:
739 fprintf(stderr, "%s: ERROR: unsupported internalFormat (0x%x)\n",
740 __FUNCTION__, glformat);
741 fxCloseHardware();
742 exit(-1);
743 break;
744 }
745 }
746
747 static GLboolean
748 fxIsTexSupported(GLenum target, GLint internalFormat,
749 const struct gl_texture_image *image)
750 {
751 if (target != GL_TEXTURE_2D)
752 return GL_FALSE;
753
754 if (!fxTexGetInfo(image->Width, image->Height, NULL, NULL, NULL, NULL, NULL, NULL))
755 return GL_FALSE;
756
757 if (image->Border > 0)
758 return GL_FALSE;
759
760 return GL_TRUE;
761 }
762
763
764 /**********************************************************************/
765 /**** NEW TEXTURE IMAGE FUNCTIONS ****/
766 /**********************************************************************/
767
768 /* Texel-fetch functions for software texturing and glGetTexImage().
769 * We should have been able to use some "standard" fetch functions (which
770 * may get defined in texutil.c) but we have to account for scaled texture
771 * images on tdfx hardware (the 8:1 aspect ratio limit).
772 * Hence, we need special functions here.
773 */
774
775 static void
776 fetch_intensity8(const struct gl_texture_image *texImage,
777 GLint i, GLint j, GLint k, GLvoid * texelOut)
778 {
779 GLchan *rgba = (GLchan *) texelOut;
780 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
781 const GLubyte *texel;
782
783 i = i * mml->wScale;
784 j = j * mml->hScale;
785
786 texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
787 rgba[RCOMP] = *texel;
788 rgba[GCOMP] = *texel;
789 rgba[BCOMP] = *texel;
790 rgba[ACOMP] = *texel;
791 }
792
793
794 static void
795 fetch_luminance8(const struct gl_texture_image *texImage,
796 GLint i, GLint j, GLint k, GLvoid * texelOut)
797 {
798 GLchan *rgba = (GLchan *) texelOut;
799 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
800 const GLubyte *texel;
801
802 i = i * mml->wScale;
803 j = j * mml->hScale;
804
805 texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
806 rgba[RCOMP] = *texel;
807 rgba[GCOMP] = *texel;
808 rgba[BCOMP] = *texel;
809 rgba[ACOMP] = 255;
810 }
811
812
813 static void
814 fetch_alpha8(const struct gl_texture_image *texImage,
815 GLint i, GLint j, GLint k, GLvoid * texelOut)
816 {
817 GLchan *rgba = (GLchan *) texelOut;
818 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
819 const GLubyte *texel;
820
821 i = i * mml->wScale;
822 j = j * mml->hScale;
823 i = i * mml->width / texImage->Width;
824 j = j * mml->height / texImage->Height;
825
826 texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
827 rgba[RCOMP] = 255;
828 rgba[GCOMP] = 255;
829 rgba[BCOMP] = 255;
830 rgba[ACOMP] = *texel;
831 }
832
833
834 static void
835 fetch_index8(const struct gl_texture_image *texImage,
836 GLint i, GLint j, GLint k, GLvoid * texelOut)
837 {
838 GLchan *indexOut = (GLchan *) texelOut;
839 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
840 const GLubyte *texel;
841
842 i = i * mml->wScale;
843 j = j * mml->hScale;
844 i = i * mml->width / texImage->Width;
845 j = j * mml->height / texImage->Height;
846
847 texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
848 *indexOut = *texel;
849 }
850
851
852 static void
853 fetch_luminance8_alpha8(const struct gl_texture_image *texImage,
854 GLint i, GLint j, GLint k, GLvoid * texelOut)
855 {
856 GLchan *rgba = (GLchan *) texelOut;
857 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
858 const GLubyte *texel;
859
860 i = i * mml->wScale;
861 j = j * mml->hScale;
862
863 texel = ((GLubyte *) texImage->Data) + (j * mml->width + i) * 2;
864 rgba[RCOMP] = texel[0];
865 rgba[GCOMP] = texel[0];
866 rgba[BCOMP] = texel[0];
867 rgba[ACOMP] = texel[1];
868 }
869
870
871 static void
872 fetch_r5g6b5(const struct gl_texture_image *texImage,
873 GLint i, GLint j, GLint k, GLvoid * texelOut)
874 {
875 GLchan *rgba = (GLchan *) texelOut;
876 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
877 const GLushort *texel;
878
879 i = i * mml->wScale;
880 j = j * mml->hScale;
881
882 texel = ((GLushort *) texImage->Data) + j * mml->width + i;
883 rgba[RCOMP] = FX_rgb_scale_5[(*texel >> 11) & 0x1F];
884 rgba[GCOMP] = FX_rgb_scale_6[(*texel >> 5) & 0x3F];
885 rgba[BCOMP] = FX_rgb_scale_5[ *texel & 0x1F];
886 rgba[ACOMP] = 255;
887 }
888
889
890 static void
891 fetch_r4g4b4a4(const struct gl_texture_image *texImage,
892 GLint i, GLint j, GLint k, GLvoid * texelOut)
893 {
894 GLchan *rgba = (GLchan *) texelOut;
895 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
896 const GLushort *texel;
897
898 i = i * mml->wScale;
899 j = j * mml->hScale;
900
901 texel = ((GLushort *) texImage->Data) + j * mml->width + i;
902 rgba[RCOMP] = FX_rgb_scale_4[(*texel >> 12) & 0xF];
903 rgba[GCOMP] = FX_rgb_scale_4[(*texel >> 8) & 0xF];
904 rgba[BCOMP] = FX_rgb_scale_4[(*texel >> 4) & 0xF];
905 rgba[ACOMP] = FX_rgb_scale_4[ *texel & 0xF];
906 }
907
908
909 static void
910 fetch_r5g5b5a1(const struct gl_texture_image *texImage,
911 GLint i, GLint j, GLint k, GLvoid * texelOut)
912 {
913 GLchan *rgba = (GLchan *) texelOut;
914 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
915 const GLushort *texel;
916
917 i = i * mml->wScale;
918 j = j * mml->hScale;
919
920 texel = ((GLushort *) texImage->Data) + j * mml->width + i;
921 rgba[RCOMP] = FX_rgb_scale_5[(*texel >> 11) & 0x1F];
922 rgba[GCOMP] = FX_rgb_scale_5[(*texel >> 6) & 0x1F];
923 rgba[BCOMP] = FX_rgb_scale_5[(*texel >> 1) & 0x1F];
924 rgba[ACOMP] = ((*texel) & 0x01) * 255;
925 }
926
927
928 static void
929 fetch_a8r8g8b8(const struct gl_texture_image *texImage,
930 GLint i, GLint j, GLint k, GLvoid * texelOut)
931 {
932 GLchan *rgba = (GLchan *) texelOut;
933 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
934 const GLuint *texel;
935
936 i = i * mml->wScale;
937 j = j * mml->hScale;
938
939 texel = ((GLuint *) texImage->Data) + j * mml->width + i;
940 rgba[RCOMP] = (((*texel) >> 16) & 0xff);
941 rgba[GCOMP] = (((*texel) >> 8) & 0xff);
942 rgba[BCOMP] = (((*texel) ) & 0xff);
943 rgba[ACOMP] = (((*texel) >> 24) & 0xff);
944 }
945
946
947 static void
948 PrintTexture(int w, int h, int c, const GLubyte * data)
949 {
950 int i, j;
951 for (i = 0; i < h; i++) {
952 for (j = 0; j < w; j++) {
953 if (c == 2)
954 fprintf(stderr, "%02x %02x ", data[0], data[1]);
955 else if (c == 3)
956 fprintf(stderr, "%02x %02x %02x ", data[0], data[1], data[2]);
957 data += c;
958 }
959 fprintf(stderr, "\n");
960 }
961 }
962
963
964 const struct gl_texture_format *
965 fxDDChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
966 GLenum srcFormat, GLenum srcType )
967 {
968 fxMesaContext fxMesa = FX_CONTEXT(ctx);
969 GLboolean allow32bpt = fxMesa->HaveTexFmt;
970
971 if (TDFX_DEBUG & VERBOSE_TEXTURE) {
972 fprintf(stderr, "fxDDChooseTextureFormat(...)\n");
973 }
974
975 switch (internalFormat) {
976 case GL_INTENSITY:
977 case GL_INTENSITY4:
978 case GL_INTENSITY8:
979 case GL_INTENSITY12:
980 case GL_INTENSITY16:
981 case GL_COMPRESSED_INTENSITY:
982 return &_mesa_texformat_i8;
983 case 1:
984 case GL_LUMINANCE:
985 case GL_LUMINANCE4:
986 case GL_LUMINANCE8:
987 case GL_LUMINANCE12:
988 case GL_LUMINANCE16:
989 case GL_COMPRESSED_LUMINANCE:
990 return &_mesa_texformat_l8;
991 case GL_ALPHA:
992 case GL_ALPHA4:
993 case GL_ALPHA8:
994 case GL_ALPHA12:
995 case GL_ALPHA16:
996 case GL_COMPRESSED_ALPHA:
997 return &_mesa_texformat_a8;
998 case GL_COLOR_INDEX:
999 case GL_COLOR_INDEX1_EXT:
1000 case GL_COLOR_INDEX2_EXT:
1001 case GL_COLOR_INDEX4_EXT:
1002 case GL_COLOR_INDEX8_EXT:
1003 case GL_COLOR_INDEX12_EXT:
1004 case GL_COLOR_INDEX16_EXT:
1005 return &_mesa_texformat_ci8;
1006 case 2:
1007 case GL_LUMINANCE_ALPHA:
1008 case GL_LUMINANCE4_ALPHA4:
1009 case GL_LUMINANCE6_ALPHA2:
1010 case GL_LUMINANCE8_ALPHA8:
1011 case GL_LUMINANCE12_ALPHA4:
1012 case GL_LUMINANCE12_ALPHA12:
1013 case GL_LUMINANCE16_ALPHA16:
1014 case GL_COMPRESSED_LUMINANCE_ALPHA:
1015 return &_mesa_texformat_al88;
1016 case GL_R3_G3_B2:
1017 case GL_RGB4:
1018 case GL_RGB5:
1019 return &_mesa_texformat_rgb565;
1020 case 3:
1021 case GL_RGB:
1022 case GL_COMPRESSED_RGB:
1023 if ( srcFormat == GL_RGB && srcType == GL_UNSIGNED_SHORT_5_6_5 ) {
1024 return &_mesa_texformat_rgb565;
1025 }
1026 /* intentional fall through */
1027 case GL_RGB8:
1028 case GL_RGB10:
1029 case GL_RGB12:
1030 case GL_RGB16:
1031 return (allow32bpt) ? &_mesa_texformat_argb8888
1032 : &_mesa_texformat_rgb565;
1033 case GL_RGBA2:
1034 case GL_RGBA4:
1035 return &_mesa_texformat_argb4444;
1036 case 4:
1037 case GL_RGBA:
1038 case GL_COMPRESSED_RGBA:
1039 if ( srcFormat == GL_BGRA ) {
1040 if ( srcType == GL_UNSIGNED_INT_8_8_8_8_REV ) {
1041 return &_mesa_texformat_argb8888;
1042 }
1043 else if ( srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV ) {
1044 return &_mesa_texformat_argb4444;
1045 }
1046 else if ( srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV ) {
1047 return &_mesa_texformat_argb1555;
1048 }
1049 }
1050 /* intentional fall through */
1051 case GL_RGBA8:
1052 case GL_RGB10_A2:
1053 case GL_RGBA12:
1054 case GL_RGBA16:
1055 return (allow32bpt) ? &_mesa_texformat_argb8888
1056 : &_mesa_texformat_argb4444;
1057 case GL_RGB5_A1:
1058 return &_mesa_texformat_argb1555;
1059 #if 0
1060 /* GL_EXT_texture_compression_s3tc */
1061 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1062 return &_mesa_texformat_rgb_dxt1;
1063 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1064 return &_mesa_texformat_rgba_dxt1;
1065 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
1066 return &_mesa_texformat_rgba_dxt3;
1067 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
1068 return &_mesa_texformat_rgba_dxt5;
1069 /*case GL_COMPRESSED_RGB_FXT1_3DFX:
1070 case GL_COMPRESSED_RGBA_FXT1_3DFX:
1071 return blah;*/
1072 #endif
1073 default:
1074 _mesa_problem(NULL, "unexpected format in fxDDChooseTextureFormat");
1075 return NULL;
1076 }
1077 }
1078
1079
1080 static GrTextureFormat_t
1081 fxGlideFormat(GLint mesaFormat)
1082 {
1083 switch (mesaFormat) {
1084 case MESA_FORMAT_I8:
1085 return GR_TEXFMT_ALPHA_8;
1086 case MESA_FORMAT_A8:
1087 return GR_TEXFMT_ALPHA_8;
1088 case MESA_FORMAT_L8:
1089 return GR_TEXFMT_INTENSITY_8;
1090 case MESA_FORMAT_CI8:
1091 return GR_TEXFMT_P_8;
1092 case MESA_FORMAT_AL88:
1093 return GR_TEXFMT_ALPHA_INTENSITY_88;
1094 case MESA_FORMAT_RGB565:
1095 return GR_TEXFMT_RGB_565;
1096 case MESA_FORMAT_ARGB4444:
1097 return GR_TEXFMT_ARGB_4444;
1098 case MESA_FORMAT_ARGB1555:
1099 return GR_TEXFMT_ARGB_1555;
1100 #if 1 /* [koolsmoky] getting ready for 32bpp textures */
1101 case MESA_FORMAT_ARGB8888:
1102 return GR_TEXFMT_ARGB_8888;
1103 #endif
1104 #if 0
1105 case MESA_FORMAT_RGB_DXT1:
1106 case MESA_FORMAT_RGBA_DXT1:
1107 return GR_TEXFMT_ARGB_CMP_DXT1;
1108 case MESA_FORMAT_RGBA_DXT3:
1109 return GR_TEXFMT_ARGB_CMP_DXT3;
1110 case MESA_FORMAT_RGBA_DXT5:
1111 return GR_TEXFMT_ARGB_CMP_DXT5;
1112 /*case MESA_FORMAT_ARGB_CMP_FXT1:
1113 return GR_TEXFMT_ARGB_CMP_FXT1;
1114 case MESA_FORMAT_RGB_CMP_FXT1:
1115 return GL_COMPRESSED_RGBA_FXT1_3DFX;*/
1116 #endif
1117 default:
1118 _mesa_problem(NULL, "Unexpected format in fxGlideFormat");
1119 return 0;
1120 }
1121 }
1122
1123
1124 static FetchTexelFunc
1125 fxFetchFunction(GLint mesaFormat)
1126 {
1127 switch (mesaFormat) {
1128 case MESA_FORMAT_I8:
1129 return fetch_intensity8;
1130 case MESA_FORMAT_A8:
1131 return fetch_alpha8;
1132 case MESA_FORMAT_L8:
1133 return fetch_luminance8;
1134 case MESA_FORMAT_CI8:
1135 return fetch_index8;
1136 case MESA_FORMAT_AL88:
1137 return fetch_luminance8_alpha8;
1138 case MESA_FORMAT_RGB565:
1139 return fetch_r5g6b5;
1140 case MESA_FORMAT_ARGB4444:
1141 return fetch_r4g4b4a4;
1142 case MESA_FORMAT_ARGB1555:
1143 return fetch_r5g5b5a1;
1144 #if 1 /* [koolsmoky] getting ready for 32bpp textures */
1145 case MESA_FORMAT_ARGB8888:
1146 return fetch_a8r8g8b8;
1147 #endif
1148 #if 0
1149 case MESA_FORMAT_RGB_DXT1:
1150 case MESA_FORMAT_RGBA_DXT1:
1151 case MESA_FORMAT_RGBA_DXT3:
1152 case MESA_FORMAT_RGBA_DXT5:
1153 return fetch_r4g4b4a4;
1154 #endif
1155 default:
1156 _mesa_problem(NULL, "Unexpected format in fxFetchFunction");
1157 return NULL;
1158 }
1159 }
1160
1161 void
1162 fxDDTexImage2D(GLcontext * ctx, GLenum target, GLint level,
1163 GLint internalFormat, GLint width, GLint height, GLint border,
1164 GLenum format, GLenum type, const GLvoid * pixels,
1165 const struct gl_pixelstore_attrib *packing,
1166 struct gl_texture_object *texObj,
1167 struct gl_texture_image *texImage)
1168 {
1169 fxMesaContext fxMesa = FX_CONTEXT(ctx);
1170 tfxTexInfo *ti;
1171 tfxMipMapLevel *mml;
1172 GLint texelBytes;
1173
1174 if (TDFX_DEBUG & VERBOSE_TEXTURE) {
1175 fprintf(stderr, "fxDDTexImage2D: id=%d int 0x%x format 0x%x type 0x%x %dx%d\n",
1176 texObj->Name, texImage->IntFormat, format, type,
1177 texImage->Width, texImage->Height);
1178 }
1179
1180 if (!fxIsTexSupported(target, internalFormat, texImage)) {
1181 _mesa_problem(NULL, "fx Driver: unsupported texture in fxDDTexImg()\n");
1182 return;
1183 }
1184
1185 if (!texObj->DriverData) {
1186 texObj->DriverData = fxAllocTexObjData(fxMesa);
1187 if (!texObj->DriverData) {
1188 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1189 return;
1190 }
1191 }
1192 ti = fxTMGetTexInfo(texObj);
1193
1194 if (!texImage->DriverData) {
1195 texImage->DriverData = CALLOC(sizeof(tfxMipMapLevel));
1196 if (!texImage->DriverData) {
1197 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1198 return;
1199 }
1200 }
1201 mml = FX_MIPMAP_DATA(texImage);
1202
1203 fxTexGetInfo(width, height, NULL, NULL, NULL, NULL,
1204 &mml->wScale, &mml->hScale);
1205
1206 mml->width = width * mml->wScale;
1207 mml->height = height * mml->hScale;
1208
1209
1210 /* choose the texture format */
1211 assert(ctx->Driver.ChooseTextureFormat);
1212 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
1213 internalFormat, format, type);
1214 assert(texImage->TexFormat);
1215 texelBytes = texImage->TexFormat->TexelBytes;
1216 /*if (!fxMesa->HaveTexFmt) assert(texelBytes == 1 || texelBytes == 2);*/
1217
1218 if (mml->wScale != 1 || mml->hScale != 1) {
1219 /* rescale image to overcome 1:8 aspect limitation */
1220 GLvoid *tempImage;
1221 tempImage = MALLOC(width * height * texelBytes);
1222 if (!tempImage) {
1223 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1224 return;
1225 }
1226 /* unpack image, apply transfer ops and store in tempImage */
1227 _mesa_transfer_teximage(ctx, 2, texImage->Format,
1228 texImage->TexFormat,
1229 tempImage,
1230 width, height, 1, 0, 0, 0,
1231 width * texelBytes,
1232 0, /* dstImageStride */
1233 format, type, pixels, packing);
1234 assert(!texImage->Data);
1235 texImage->Data = MESA_PBUFFER_ALLOC(mml->width * mml->height * texelBytes);
1236 if (!texImage->Data) {
1237 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1238 FREE(tempImage);
1239 return;
1240 }
1241 _mesa_rescale_teximage2d(texelBytes,
1242 mml->width * texelBytes, /* dst stride */
1243 width, height,
1244 mml->width, mml->height,
1245 tempImage /*src*/, texImage->Data /*dst*/ );
1246 FREE(tempImage);
1247 }
1248 else {
1249 /* no rescaling needed */
1250 assert(!texImage->Data);
1251 texImage->Data = MESA_PBUFFER_ALLOC(mml->width * mml->height * texelBytes);
1252 if (!texImage->Data) {
1253 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1254 return;
1255 }
1256 /* unpack image, apply transfer ops and store in texImage->Data */
1257 _mesa_transfer_teximage(ctx, 2, texImage->Format,
1258 texImage->TexFormat, texImage->Data,
1259 width, height, 1, 0, 0, 0,
1260 texImage->Width * texelBytes,
1261 0, /* dstImageStride */
1262 format, type, pixels, packing);
1263 }
1264
1265 mml->glideFormat = fxGlideFormat(texImage->TexFormat->MesaFormat);
1266 ti->info.format = mml->glideFormat;
1267 texImage->FetchTexel = fxFetchFunction(texImage->TexFormat->MesaFormat);
1268
1269 /* [dBorca]
1270 * Hack alert: unsure...
1271 */
1272 if (!(fxMesa->new_state & FX_NEW_TEXTURING) && ti->validated && ti->isInTM) {
1273 /*fprintf(stderr, "reloadmipmaplevels\n"); */
1274 fxTMReloadMipMapLevel(fxMesa, texObj, level);
1275 }
1276 else {
1277 /*fprintf(stderr, "invalidate2\n"); */
1278 fxTexInvalidate(ctx, texObj);
1279 }
1280 }
1281
1282
1283 void
1284 fxDDTexSubImage2D(GLcontext * ctx, GLenum target, GLint level,
1285 GLint xoffset, GLint yoffset,
1286 GLsizei width, GLsizei height,
1287 GLenum format, GLenum type, const GLvoid * pixels,
1288 const struct gl_pixelstore_attrib *packing,
1289 struct gl_texture_object *texObj,
1290 struct gl_texture_image *texImage)
1291 {
1292 fxMesaContext fxMesa = FX_CONTEXT(ctx);
1293 tfxTexInfo *ti;
1294 tfxMipMapLevel *mml;
1295 GLint texelBytes;
1296
1297 if (TDFX_DEBUG & VERBOSE_TEXTURE) {
1298 fprintf(stderr, "fxDDTexSubImage2D: id=%d\n", texObj->Name);
1299 }
1300
1301 if (!texObj->DriverData) {
1302 _mesa_problem(ctx, "problem in fxDDTexSubImage2D");
1303 return;
1304 }
1305
1306 ti = fxTMGetTexInfo(texObj);
1307 assert(ti);
1308 mml = FX_MIPMAP_DATA(texImage);
1309 assert(mml);
1310
1311 assert(texImage->Data); /* must have an existing texture image! */
1312 assert(texImage->Format);
1313
1314 texelBytes = texImage->TexFormat->TexelBytes;
1315
1316 if (mml->wScale != 1 || mml->hScale != 1) {
1317 /* need to rescale subimage to match mipmap level's rescale factors */
1318 const GLint newWidth = width * mml->wScale;
1319 const GLint newHeight = height * mml->hScale;
1320 GLvoid *tempImage;
1321 GLubyte *destAddr;
1322 tempImage = MALLOC(width * height * texelBytes);
1323 if (!tempImage) {
1324 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
1325 return;
1326 }
1327
1328 _mesa_transfer_teximage(ctx, 2, texImage->Format,/* Tex int format */
1329 texImage->TexFormat, /* dest format */
1330 (GLubyte *) tempImage, /* dest */
1331 width, height, 1, /* subimage size */
1332 0, 0, 0, /* subimage pos */
1333 width * texelBytes, /* dest row stride */
1334 0, /* dst image stride */
1335 format, type, pixels, packing);
1336
1337 /* now rescale */
1338 /* compute address of dest subimage within the overal tex image */
1339 destAddr = (GLubyte *) texImage->Data
1340 + (yoffset * mml->hScale * mml->width
1341 + xoffset * mml->wScale) * texelBytes;
1342
1343 _mesa_rescale_teximage2d(texelBytes,
1344 mml->width * texelBytes, /* dst stride */
1345 width, height,
1346 newWidth, newHeight,
1347 tempImage, destAddr);
1348
1349 FREE(tempImage);
1350 }
1351 else {
1352 /* no rescaling needed */
1353 _mesa_transfer_teximage(ctx, 2, texImage->Format, /* Tex int format */
1354 texImage->TexFormat, /* dest format */
1355 (GLubyte *) texImage->Data,/* dest */
1356 width, height, 1, /* subimage size */
1357 xoffset, yoffset, 0, /* subimage pos */
1358 mml->width * texelBytes, /* dest row stride */
1359 0, /* dst image stride */
1360 format, type, pixels, packing);
1361 }
1362
1363 /* [dBorca]
1364 * Hack alert: unsure...
1365 */
1366 if (!(fxMesa->new_state & FX_NEW_TEXTURING) && ti->validated && ti->isInTM)
1367 fxTMReloadMipMapLevel(fxMesa, texObj, level);
1368 else
1369 fxTexInvalidate(ctx, texObj);
1370 }
1371
1372
1373 #else /* FX */
1374
1375 /*
1376 * Need this to provide at least one external definition.
1377 */
1378
1379 extern int gl_fx_dummy_function_ddtex(void);
1380 int
1381 gl_fx_dummy_function_ddtex(void)
1382 {
1383 return 0;
1384 }
1385
1386 #endif /* FX */