b2802904bdadaefd702f6a542eb502baabbc945b
[mesa.git] / src / mesa / drivers / dri / savage / savagetex.c
1 /*
2 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sub license,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
14 * of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25
26 #include <stdlib.h>
27 #include <stdio.h>
28
29 #include <GL/gl.h>
30
31 #include "mm.h"
32 #include "savagecontext.h"
33 #include "savagetex.h"
34 #include "savagetris.h"
35 #include "savageioctl.h"
36 #include "simple_list.h"
37 #include "enums.h"
38 #include "savage_bci.h"
39
40 #include "macros.h"
41 #include "texformat.h"
42 #include "texstore.h"
43 #include "texobj.h"
44
45 #include "convolve.h"
46 #include "colormac.h"
47
48 #include "swrast/swrast.h"
49
50 #include "xmlpool.h"
51
52 #define TILE_INDEX_DXT1 0
53 #define TILE_INDEX_8 1
54 #define TILE_INDEX_16 2
55 #define TILE_INDEX_DXTn 3
56 #define TILE_INDEX_32 4
57
58 /* On Savage4 the texure LOD-bias needs an offset of ~ 0.3 to get
59 * somewhere close to software rendering.
60 */
61 #define SAVAGE4_LOD_OFFSET 10
62
63 /* Tile info for S3TC formats counts in 4x4 blocks instead of texels.
64 * In DXT1 each block is encoded in 64 bits. In DXT3 and 5 each block is
65 * encoded in 128 bits. */
66
67 /* Size 1, 2 and 4 images are packed into the last subtile. Each image
68 * is repeated to fill a 4x4 pixel area. The figure below shows the
69 * layout of those 4x4 pixel areas in the 8x8 subtile.
70 *
71 * 4 2
72 * x 1
73 *
74 * Yuck! 8-bit texture formats use 4x8 subtiles. See below.
75 */
76 static const savageTileInfo tileInfo_pro[5] = {
77 {16, 16, 16, 8, 1, 2, {0x18, 0x10}}, /* DXT1 */
78 {64, 32, 16, 4, 4, 8, {0x30, 0x20}}, /* 8-bit */
79 {64, 16, 8, 2, 8, 8, {0x48, 0x08}}, /* 16-bit */
80 {16, 8, 16, 4, 1, 2, {0x30, 0x20}}, /* DXT3, DXT5 */
81 {32, 16, 4, 2, 8, 8, {0x90, 0x10}}, /* 32-bit */
82 };
83
84 /* Size 1, 2 and 4 images are packed into the last two subtiles. Each
85 * image is repeated to fill a 4x4 pixel area. The figures below show
86 * the layout of those 4x4 pixel areas in the two 4x8 subtiles.
87 *
88 * second last subtile: 4 last subtile: 2
89 * x 1
90 */
91 static const savageTileInfo tileInfo_s3d_s4[5] = {
92 {16, 16, 16, 8, 1, 2, {0x18, 0x10}}, /* DXT1 */
93 {64, 32, 16, 4, 4, 8, {0x30, 0x20}}, /* 8-bit */
94 {64, 16, 16, 2, 4, 8, {0x60, 0x40}}, /* 16-bit */
95 {16, 8, 16, 4, 1, 2, {0x30, 0x20}}, /* DXT3, DXT5 */
96 {32, 16, 8, 2, 4, 8, {0xc0, 0x80}}, /* 32-bit */
97 };
98
99 /** \brief Template for subtile uploads.
100 * \param h height in pixels
101 * \param w width in bytes
102 */
103 #define SUBTILE_FUNC(w,h) \
104 static __inline GLubyte *savageUploadSubtile_##w##x##h \
105 (GLubyte *dest, GLubyte *src, GLuint srcStride) \
106 { \
107 GLuint y; \
108 for (y = 0; y < h; ++y) { \
109 memcpy (dest, src, w); \
110 src += srcStride; \
111 dest += w; \
112 } \
113 return dest; \
114 }
115
116 SUBTILE_FUNC(2, 8) /* 4 bits per pixel, 4 pixels wide */
117 SUBTILE_FUNC(4, 8)
118 SUBTILE_FUNC(8, 8)
119 SUBTILE_FUNC(16, 8)
120 SUBTILE_FUNC(32, 8) /* 4 bytes per pixel, 8 pixels wide */
121
122 SUBTILE_FUNC(8, 2) /* DXT1 */
123 SUBTILE_FUNC(16, 2) /* DXT3 and DXT5 */
124
125 /** \brief Upload a complete tile from src (srcStride) to dest
126 *
127 * \param tileInfo Pointer to tiling information
128 * \param wInSub Width of source/dest image in subtiles
129 * \param hInSub Height of source/dest image in subtiles
130 * \param bpp Bytes per pixel
131 * \param src Pointer to source data
132 * \param srcStride Byte stride of rows in the source data
133 * \param dest Pointer to destination
134 *
135 * Writes linearly to the destination memory in order to exploit write
136 * combining.
137 *
138 * For a complete tile wInSub and hInSub are set to the same values as
139 * in tileInfo. If the source image is smaller than a whole tile in
140 * one or both dimensions then they are set to the values of the
141 * source image. This only works as long as the source image is bigger
142 * than 8x8 pixels.
143 */
144 static void savageUploadTile (const savageTileInfo *tileInfo,
145 GLuint wInSub, GLuint hInSub, GLuint bpp,
146 GLubyte *src, GLuint srcStride, GLubyte *dest) {
147 GLuint subStride = tileInfo->subWidth * bpp;
148 GLubyte *srcSRow = src, *srcSTile = src;
149 GLubyte *(*subtileFunc) (GLubyte *, GLubyte *, GLuint);
150 GLuint sx, sy;
151 switch (subStride) {
152 case 2: subtileFunc = savageUploadSubtile_2x8; break;
153 case 4: subtileFunc = savageUploadSubtile_4x8; break;
154 case 8: subtileFunc = tileInfo->subHeight == 8 ?
155 savageUploadSubtile_8x8 : savageUploadSubtile_8x2; break;
156 case 16: subtileFunc = tileInfo->subHeight == 8 ?
157 savageUploadSubtile_16x8 : savageUploadSubtile_16x2; break;
158 case 32: subtileFunc = savageUploadSubtile_32x8; break;
159 default: assert(0);
160 }
161 for (sy = 0; sy < hInSub; ++sy) {
162 srcSTile = srcSRow;
163 for (sx = 0; sx < wInSub; ++sx) {
164 src = srcSTile;
165 dest = subtileFunc (dest, src, srcStride);
166 srcSTile += subStride;
167 }
168 srcSRow += srcStride * tileInfo->subHeight;
169 }
170 }
171
172 /** \brief Upload a image that is smaller than 8 pixels in either dimension.
173 *
174 * \param tileInfo Pointer to tiling information
175 * \param width Width of the image
176 * \param height Height of the image
177 * \param bpp Bytes per pixel
178 * \param src Pointer to source data
179 * \param dest Pointer to destination
180 *
181 * This function handles all the special cases that need to be taken
182 * care off. The caller may need to call this function multiple times
183 * with the destination offset in different ways since small texture
184 * images must be repeated in order to fill a whole tile (or 4x4 for
185 * the last 3 levels).
186 *
187 * FIXME: Repeating inside this function would be more efficient.
188 */
189 static void savageUploadTiny (const savageTileInfo *tileInfo,
190 GLuint pixWidth, GLuint pixHeight,
191 GLuint width, GLuint height, GLuint bpp,
192 GLubyte *src, GLubyte *dest) {
193 GLuint size = MAX2(pixWidth, pixHeight);
194
195 if (width > tileInfo->subWidth) { /* assert: height <= subtile height */
196 GLuint wInSub = width / tileInfo->subWidth;
197 GLuint srcStride = width * bpp;
198 GLuint subStride = tileInfo->subWidth * bpp;
199 GLuint subSkip = (tileInfo->subHeight - height) * subStride;
200 GLubyte *srcSTile = src;
201 GLuint sx, y;
202 for (sx = 0; sx < wInSub; ++sx) {
203 src = srcSTile;
204 for (y = 0; y < height; ++y) {
205 memcpy (dest, src, subStride);
206 src += srcStride;
207 dest += subStride;
208 }
209 dest += subSkip;
210 srcSTile += subStride;
211 }
212 } else if (size > 4) { /* a tile or less wide, except the last 3 levels */
213 GLuint srcStride = width * bpp;
214 GLuint subStride = tileInfo->subWidth * bpp;
215 /* if the subtile width is 4 we have to skip every other subtile */
216 GLuint subSkip = tileInfo->subWidth <= 4 ?
217 subStride * tileInfo->subHeight : 0;
218 GLuint skipRemainder = tileInfo->subHeight - 1;
219 GLuint y;
220 for (y = 0; y < height; ++y) {
221 memcpy (dest, src, srcStride);
222 src += srcStride;
223 dest += subStride;
224 if ((y & skipRemainder) == skipRemainder)
225 dest += subSkip;
226 }
227 } else { /* the last 3 mipmap levels */
228 GLuint offset = (size <= 2 ? tileInfo->tinyOffset[size-1] : 0);
229 GLuint subStride = tileInfo->subWidth * bpp;
230 GLuint y;
231 dest += offset;
232 for (y = 0; y < height; ++y) {
233 memcpy (dest, src, bpp*width);
234 src += width * bpp;
235 dest += subStride;
236 }
237 }
238 }
239
240 /** \brief Upload an image from mesa's internal copy.
241 */
242 static void savageUploadTexLevel( savageTexObjPtr t, int level )
243 {
244 const struct gl_texture_image *image = t->base.tObj->Image[0][level];
245 const savageTileInfo *tileInfo = t->tileInfo;
246 GLuint pixWidth = image->Width2, pixHeight = image->Height2;
247 GLuint bpp = t->texelBytes;
248 GLuint width, height;
249
250 /* FIXME: Need triangle (rather than pixel) fallbacks to simulate
251 * this using normal textured triangles.
252 *
253 * DO THIS IN DRIVER STATE MANAGMENT, not hardware state.
254 */
255 if(image->Border != 0)
256 fprintf (stderr, "Not supported texture border %d.\n",
257 (int) image->Border);
258
259 if (t->hwFormat == TFT_S3TC4A4Bit || t->hwFormat == TFT_S3TC4CA4Bit ||
260 t->hwFormat == TFT_S3TC4Bit) {
261 width = (pixWidth+3) / 4;
262 height = (pixHeight+3) / 4;
263 } else {
264 width = pixWidth;
265 height = pixHeight;
266 }
267
268 if (pixWidth >= 8 && pixHeight >= 8) {
269 GLuint *dirtyPtr = t->image[level].dirtyTiles;
270 GLuint dirtyMask = 1;
271
272 if (width >= tileInfo->width && height >= tileInfo->height) {
273 GLuint wInTiles = width / tileInfo->width;
274 GLuint hInTiles = height / tileInfo->height;
275 GLubyte *srcTRow = image->Data, *src;
276 GLubyte *dest = (GLubyte *)(t->bufAddr + t->image[level].offset);
277 GLuint x, y;
278 for (y = 0; y < hInTiles; ++y) {
279 src = srcTRow;
280 for (x = 0; x < wInTiles; ++x) {
281 if (*dirtyPtr & dirtyMask) {
282 savageUploadTile (tileInfo,
283 tileInfo->wInSub, tileInfo->hInSub,
284 bpp, src, width * bpp, dest);
285 }
286 src += tileInfo->width * bpp;
287 dest += 2048; /* tile size is always 2k */
288 if (dirtyMask == 1<<31) {
289 dirtyMask = 1;
290 dirtyPtr++;
291 } else
292 dirtyMask <<= 1;
293 }
294 srcTRow += width * tileInfo->height * bpp;
295 }
296 } else if (width >= tileInfo->width) {
297 GLuint wInTiles = width / tileInfo->width;
298 GLubyte *src = image->Data;
299 GLubyte *dest = (GLubyte *)(t->bufAddr + t->image[level].offset);
300 GLuint tileStride = tileInfo->width * bpp * height;
301 savageContextPtr imesa = (savageContextPtr)t->base.heap->driverContext;
302 GLuint x;
303 /* Savage3D-based chips seem so use a constant tile stride
304 * of 2048 for vertically incomplete tiles, but only if
305 * the color depth is 32bpp. Nobody said this was supposed
306 * to be logical!
307 */
308 if (bpp == 4 && imesa->savageScreen->chipset < S3_SAVAGE4)
309 tileStride = 2048;
310 for (x = 0; x < wInTiles; ++x) {
311 if (*dirtyPtr & dirtyMask) {
312 savageUploadTile (tileInfo,
313 tileInfo->wInSub,
314 height / tileInfo->subHeight,
315 bpp, src, width * bpp, dest);
316 }
317 src += tileInfo->width * bpp;
318 dest += tileStride;
319 if (dirtyMask == 1<<31) {
320 dirtyMask = 1;
321 dirtyPtr++;
322 } else
323 dirtyMask <<= 1;
324 }
325 } else {
326 savageUploadTile (tileInfo, width / tileInfo->subWidth,
327 height / tileInfo->subHeight, bpp,
328 image->Data, width * bpp,
329 (GLubyte *)(t->bufAddr+t->image[level].offset));
330 }
331 } else {
332 GLuint minHeight, minWidth, hRepeat, vRepeat, x, y;
333 if (t->hwFormat == TFT_S3TC4A4Bit || t->hwFormat == TFT_S3TC4CA4Bit ||
334 t->hwFormat == TFT_S3TC4Bit)
335 minWidth = minHeight = 1;
336 else
337 minWidth = minHeight = 4;
338 if (width > minWidth || height > minHeight) {
339 minWidth = tileInfo->subWidth;
340 minHeight = tileInfo->subHeight;
341 }
342 hRepeat = width >= minWidth ? 1 : minWidth / width;
343 vRepeat = height >= minHeight ? 1 : minHeight / height;
344 for (y = 0; y < vRepeat; ++y) {
345 GLuint offset = y * tileInfo->subWidth*height * bpp;
346 for (x = 0; x < hRepeat; ++x) {
347 savageUploadTiny (tileInfo, pixWidth, pixHeight,
348 width, height, bpp, image->Data,
349 (GLubyte *)(t->bufAddr +
350 t->image[level].offset+offset));
351 offset += width * bpp;
352 }
353 }
354 }
355 }
356
357 /** \brief Compute the destination size of a texture image
358 */
359 static GLuint savageTexImageSize (GLuint width, GLuint height, GLuint bpp) {
360 /* full subtiles */
361 if (width >= 8 && height >= 8)
362 return width * height * bpp;
363 /* special case for the last three mipmap levels: the hardware computes
364 * the offset internally */
365 else if (width <= 4 && height <= 4)
366 return 0;
367 /* partially filled sub tiles waste memory
368 * on Savage3D and Savage4 with subtile width 4 every other subtile is
369 * skipped if width < 8 so we can assume a uniform subtile width of 8 */
370 else if (width >= 8)
371 return width * 8 * bpp;
372 else if (height >= 8)
373 return 8 * height * bpp;
374 else
375 return 64 * bpp;
376 }
377
378 /** \brief Compute the destination size of a compressed texture image
379 */
380 static GLuint savageCompressedTexImageSize (GLuint width, GLuint height,
381 GLuint bpp) {
382 width = (width+3) / 4;
383 height = (height+3) / 4;
384 /* full subtiles */
385 if (width >= 2 && height >= 2)
386 return width * height * bpp;
387 /* special case for the last three mipmap levels: the hardware computes
388 * the offset internally */
389 else if (width <= 1 && height <= 1)
390 return 0;
391 /* partially filled sub tiles waste memory
392 * on Savage3D and Savage4 with subtile width 4 every other subtile is
393 * skipped if width < 8 so we can assume a uniform subtile width of 8 */
394 else if (width >= 2)
395 return width * 2 * bpp;
396 else if (height >= 2)
397 return 2 * height * bpp;
398 else
399 return 4 * bpp;
400 }
401
402 /** \brief Compute the number of (partial) tiles of a texture image
403 */
404 static GLuint savageTexImageTiles (GLuint width, GLuint height,
405 const savageTileInfo *tileInfo)
406 {
407 return (width + tileInfo->width - 1) / tileInfo->width *
408 (height + tileInfo->height - 1) / tileInfo->height;
409 }
410
411 /** \brief Mark dirty tiles
412 *
413 * Some care must be taken because tileInfo may not be set or not
414 * up-to-date. So we check if tileInfo is initialized and if the number
415 * of tiles in the bit vector matches the number of tiles computed from
416 * the current tileInfo.
417 */
418 static void savageMarkDirtyTiles (savageTexObjPtr t, GLuint level,
419 GLuint totalWidth, GLuint totalHeight,
420 GLint xoffset, GLint yoffset,
421 GLsizei width, GLsizei height)
422 {
423 GLuint wInTiles, hInTiles;
424 GLuint x0, y0, x1, y1;
425 GLuint x, y;
426 if (!t->tileInfo)
427 return;
428 wInTiles = (totalWidth + t->tileInfo->width - 1) / t->tileInfo->width;
429 hInTiles = (totalHeight + t->tileInfo->height - 1) / t->tileInfo->height;
430 if (wInTiles * hInTiles != t->image[level].nTiles)
431 return;
432
433 x0 = xoffset / t->tileInfo->width;
434 y0 = yoffset / t->tileInfo->height;
435 x1 = (xoffset + width - 1) / t->tileInfo->width;
436 y1 = (yoffset + height - 1) / t->tileInfo->height;
437
438 for (y = y0; y <= y1; ++y) {
439 GLuint *ptr = t->image[level].dirtyTiles + (y * wInTiles + x0) / 32;
440 GLuint mask = 1 << (y * wInTiles + x0) % 32;
441 for (x = x0; x <= x1; ++x) {
442 *ptr |= mask;
443 if (mask == (1<<31)) {
444 ptr++;
445 mask = 1;
446 } else {
447 mask <<= 1;
448 }
449 }
450 }
451 }
452
453 /** \brief Mark all tiles as dirty
454 */
455 static void savageMarkAllTiles (savageTexObjPtr t, GLuint level)
456 {
457 GLuint words = (t->image[level].nTiles + 31) / 32;
458 if (words)
459 memset(t->image[level].dirtyTiles, ~0, words*sizeof(GLuint));
460 }
461
462
463 static void savageSetTexWrapping(savageTexObjPtr tex, GLenum s, GLenum t)
464 {
465 tex->setup.sWrapMode = s;
466 tex->setup.tWrapMode = t;
467 }
468
469 static void savageSetTexFilter(savageTexObjPtr t, GLenum minf, GLenum magf)
470 {
471 t->setup.minFilter = minf;
472 t->setup.magFilter = magf;
473 }
474
475
476 /* Need a fallback ?
477 */
478 static void savageSetTexBorderColor(savageTexObjPtr t, GLubyte color[4])
479 {
480 /* t->Setup[SAVAGE_TEXREG_TEXBORDERCOL] = */
481 /*t->setup.borderColor = SAVAGEPACKCOLOR8888(color[0],color[1],color[2],color[3]); */
482 }
483
484
485
486 static savageTexObjPtr
487 savageAllocTexObj( struct gl_texture_object *texObj )
488 {
489 savageTexObjPtr t;
490
491 t = (savageTexObjPtr) calloc(1,sizeof(*t));
492 texObj->DriverData = t;
493 if ( t != NULL ) {
494 GLuint i;
495
496 /* Initialize non-image-dependent parts of the state:
497 */
498 t->base.tObj = texObj;
499 t->base.dirty_images[0] = 0;
500 t->dirtySubImages = 0;
501 t->tileInfo = NULL;
502
503 /* Initialize dirty tiles bit vectors
504 */
505 for (i = 0; i < SAVAGE_TEX_MAXLEVELS; ++i)
506 t->image[i].nTiles = 0;
507
508 /* FIXME Something here to set initial values for other parts of
509 * FIXME t->setup?
510 */
511
512 make_empty_list( &t->base );
513
514 savageSetTexWrapping(t,texObj->WrapS,texObj->WrapT);
515 savageSetTexFilter(t,texObj->MinFilter,texObj->MagFilter);
516 savageSetTexBorderColor(t,texObj->_BorderChan);
517 }
518
519 return t;
520 }
521
522 /* Mesa texture formats for alpha-images on Savage3D/IX/MX
523 *
524 * Promoting texture images to ARGB888 or ARGB4444 doesn't work
525 * because we can't tell the hardware to ignore the color components
526 * and only use the alpha component. So we define our own texture
527 * formats that promote to ARGB8888 or ARGB4444 and set the color
528 * components to white. This way we get the correct result. */
529 static GLboolean
530 _savage_texstore_a1114444 (GLcontext *ctx, GLuint dims,
531 GLenum baseInternalFormat,
532 const struct gl_texture_format *dstFormat,
533 GLvoid *dstAddr,
534 GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
535 GLint dstRowStride, GLint dstImageStride,
536 GLint srcWidth, GLint srcHeight, GLint srcDepth,
537 GLenum srcFormat, GLenum srcType,
538 const GLvoid *srcAddr,
539 const struct gl_pixelstore_attrib *srcPacking);
540 static GLboolean
541 _savage_texstore_a1118888 (GLcontext *ctx, GLuint dims,
542 GLenum baseInternalFormat,
543 const struct gl_texture_format *dstFormat,
544 GLvoid *dstAddr,
545 GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
546 GLint dstRowStride, GLint dstImageStride,
547 GLint srcWidth, GLint srcHeight, GLint srcDepth,
548 GLenum srcFormat, GLenum srcType,
549 const GLvoid *srcAddr,
550 const struct gl_pixelstore_attrib *srcPacking);
551
552 static struct gl_texture_format _savage_texformat_a1114444 = {
553 MESA_FORMAT_ARGB4444, /* MesaFormat */
554 GL_RGBA, /* BaseFormat */
555 GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
556 4, /* RedBits */
557 4, /* GreenBits */
558 4, /* BlueBits */
559 4, /* AlphaBits */
560 0, /* LuminanceBits */
561 0, /* IntensityBits */
562 0, /* IndexBits */
563 0, /* DepthBits */
564 0, /* StencilBits */
565 2, /* TexelBytes */
566 _savage_texstore_a1114444, /* StoreTexImageFunc */
567 NULL, NULL, NULL, NULL, NULL, NULL /* FetchTexel* filled in by
568 * savageDDInitTextureFuncs */
569 };
570 static struct gl_texture_format _savage_texformat_a1118888 = {
571 MESA_FORMAT_ARGB8888, /* MesaFormat */
572 GL_RGBA, /* BaseFormat */
573 GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
574 8, /* RedBits */
575 8, /* GreenBits */
576 8, /* BlueBits */
577 8, /* AlphaBits */
578 0, /* LuminanceBits */
579 0, /* IntensityBits */
580 0, /* IndexBits */
581 0, /* DepthBits */
582 0, /* StencilBits */
583 4, /* TexelBytes */
584 _savage_texstore_a1118888, /* StoreTexImageFunc */
585 NULL, NULL, NULL, NULL, NULL, NULL /* FetchTexel* filled in by
586 * savageDDInitTextureFuncs */
587 };
588
589 static GLboolean
590 _savage_texstore_a1114444 (GLcontext *ctx, GLuint dims,
591 GLenum baseInternalFormat,
592 const struct gl_texture_format *dstFormat,
593 GLvoid *dstAddr,
594 GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
595 GLint dstRowStride, GLint dstImageStride,
596 GLint srcWidth, GLint srcHeight, GLint srcDepth,
597 GLenum srcFormat, GLenum srcType,
598 const GLvoid *srcAddr,
599 const struct gl_pixelstore_attrib *srcPacking)
600 {
601 /* general path */
602 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
603 baseInternalFormat,
604 baseInternalFormat,
605 srcWidth, srcHeight, srcDepth,
606 srcFormat, srcType, srcAddr,
607 srcPacking);
608 const GLchan *src = tempImage;
609 GLubyte *dstImage = (GLubyte *) dstAddr
610 + dstZoffset * dstImageStride
611 + dstYoffset * dstRowStride
612 + dstXoffset * dstFormat->TexelBytes;
613 GLint img, row, col;
614
615 ASSERT(dstFormat == &_savage_texformat_a1114444);
616 ASSERT(baseInternalFormat == GL_ALPHA);
617
618 if (!tempImage)
619 return GL_FALSE;
620 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
621 for (img = 0; img < srcDepth; img++) {
622 GLubyte *dstRow = dstImage;
623 for (row = 0; row < srcHeight; row++) {
624 GLushort *dstUI = (GLushort *) dstRow;
625 for (col = 0; col < srcWidth; col++) {
626 dstUI[col] = PACK_COLOR_4444( CHAN_TO_UBYTE(src[0]),
627 255, 255, 255 );
628 src += 1;
629 }
630 dstRow += dstRowStride;
631 }
632 dstImage += dstImageStride;
633 }
634 _mesa_free((void *) tempImage);
635
636 return GL_TRUE;
637 }
638 static GLboolean
639 _savage_texstore_a1118888 (GLcontext *ctx, GLuint dims,
640 GLenum baseInternalFormat,
641 const struct gl_texture_format *dstFormat,
642 GLvoid *dstAddr,
643 GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
644 GLint dstRowStride, GLint dstImageStride,
645 GLint srcWidth, GLint srcHeight, GLint srcDepth,
646 GLenum srcFormat, GLenum srcType,
647 const GLvoid *srcAddr,
648 const struct gl_pixelstore_attrib *srcPacking)
649 {
650 /* general path */
651 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
652 baseInternalFormat,
653 baseInternalFormat,
654 srcWidth, srcHeight, srcDepth,
655 srcFormat, srcType, srcAddr,
656 srcPacking);
657 const GLchan *src = tempImage;
658 GLubyte *dstImage = (GLubyte *) dstAddr
659 + dstZoffset * dstImageStride
660 + dstYoffset * dstRowStride
661 + dstXoffset * dstFormat->TexelBytes;
662 GLint img, row, col;
663
664 ASSERT(dstFormat == &_savage_texformat_a1118888);
665 ASSERT(baseInternalFormat == GL_ALPHA);
666
667 if (!tempImage)
668 return GL_FALSE;
669 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
670 for (img = 0; img < srcDepth; img++) {
671 GLubyte *dstRow = dstImage;
672 for (row = 0; row < srcHeight; row++) {
673 GLuint *dstUI = (GLuint *) dstRow;
674 for (col = 0; col < srcWidth; col++) {
675 dstUI[col] = PACK_COLOR_8888( CHAN_TO_UBYTE(src[0]),
676 255, 255, 255 );
677 src += 1;
678 }
679 dstRow += dstRowStride;
680 }
681 dstImage += dstImageStride;
682 }
683 _mesa_free((void *) tempImage);
684
685 return GL_TRUE;
686 }
687
688 /* Called by the _mesa_store_teximage[123]d() functions. */
689 static const struct gl_texture_format *
690 savageChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
691 GLenum format, GLenum type )
692 {
693 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
694 const GLboolean do32bpt =
695 ( imesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_32 );
696 const GLboolean force16bpt =
697 ( imesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FORCE_16 );
698 const GLboolean isSavage4 = (imesa->savageScreen->chipset >= S3_SAVAGE4);
699 (void) format;
700
701 switch ( internalFormat ) {
702 case 4:
703 case GL_RGBA:
704 case GL_COMPRESSED_RGBA:
705 switch ( type ) {
706 case GL_UNSIGNED_INT_10_10_10_2:
707 case GL_UNSIGNED_INT_2_10_10_10_REV:
708 return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb1555;
709 case GL_UNSIGNED_SHORT_4_4_4_4:
710 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
711 return &_mesa_texformat_argb4444;
712 case GL_UNSIGNED_SHORT_5_5_5_1:
713 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
714 return &_mesa_texformat_argb1555;
715 default:
716 return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
717 }
718
719 case 3:
720 case GL_RGB:
721 case GL_COMPRESSED_RGB:
722 switch ( type ) {
723 case GL_UNSIGNED_SHORT_4_4_4_4:
724 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
725 return &_mesa_texformat_argb4444;
726 case GL_UNSIGNED_SHORT_5_5_5_1:
727 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
728 return &_mesa_texformat_argb1555;
729 case GL_UNSIGNED_SHORT_5_6_5:
730 case GL_UNSIGNED_SHORT_5_6_5_REV:
731 return &_mesa_texformat_rgb565;
732 default:
733 return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565;
734 }
735
736 case GL_RGBA8:
737 case GL_RGBA12:
738 case GL_RGBA16:
739 return !force16bpt ?
740 &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
741
742 case GL_RGB10_A2:
743 return !force16bpt ?
744 &_mesa_texformat_argb8888 : &_mesa_texformat_argb1555;
745
746 case GL_RGBA4:
747 case GL_RGBA2:
748 return &_mesa_texformat_argb4444;
749
750 case GL_RGB5_A1:
751 return &_mesa_texformat_argb1555;
752
753 case GL_RGB8:
754 case GL_RGB10:
755 case GL_RGB12:
756 case GL_RGB16:
757 return !force16bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565;
758
759 case GL_RGB5:
760 case GL_RGB4:
761 case GL_R3_G3_B2:
762 return &_mesa_texformat_rgb565;
763
764 case GL_ALPHA:
765 case GL_COMPRESSED_ALPHA:
766 return isSavage4 ? &_mesa_texformat_a8 : (
767 do32bpt ? &_savage_texformat_a1118888 : &_savage_texformat_a1114444);
768 case GL_ALPHA4:
769 return isSavage4 ? &_mesa_texformat_a8 : &_savage_texformat_a1114444;
770 case GL_ALPHA8:
771 case GL_ALPHA12:
772 case GL_ALPHA16:
773 return isSavage4 ? &_mesa_texformat_a8 : (
774 !force16bpt ? &_savage_texformat_a1118888 : &_savage_texformat_a1114444);
775
776 case 1:
777 case GL_LUMINANCE:
778 case GL_COMPRESSED_LUMINANCE:
779 /* no alpha, but use argb1555 in 16bit case to get pure grey values */
780 return isSavage4 ? &_mesa_texformat_l8 : (
781 do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb1555);
782 case GL_LUMINANCE4:
783 return isSavage4 ? &_mesa_texformat_l8 : &_mesa_texformat_argb1555;
784 case GL_LUMINANCE8:
785 case GL_LUMINANCE12:
786 case GL_LUMINANCE16:
787 return isSavage4 ? &_mesa_texformat_l8 : (
788 !force16bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb1555);
789
790 case 2:
791 case GL_LUMINANCE_ALPHA:
792 case GL_COMPRESSED_LUMINANCE_ALPHA:
793 /* Savage4 has a al44 texture format. But it's not supported by Mesa. */
794 return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
795 case GL_LUMINANCE4_ALPHA4:
796 case GL_LUMINANCE6_ALPHA2:
797 return &_mesa_texformat_argb4444;
798 case GL_LUMINANCE8_ALPHA8:
799 case GL_LUMINANCE12_ALPHA4:
800 case GL_LUMINANCE12_ALPHA12:
801 case GL_LUMINANCE16_ALPHA16:
802 return !force16bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
803 #if 0
804 /* TFT_I8 produces garbage on ProSavageDDR and subsequent texture
805 * disable keeps rendering garbage. Disabled for now. */
806 case GL_INTENSITY:
807 case GL_COMPRESSED_INTENSITY:
808 return isSavage4 ? &_mesa_texformat_i8 : (
809 do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444);
810 case GL_INTENSITY4:
811 return isSavage4 ? &_mesa_texformat_i8 : &_mesa_texformat_argb4444;
812 case GL_INTENSITY8:
813 case GL_INTENSITY12:
814 case GL_INTENSITY16:
815 return isSavage4 ? &_mesa_texformat_i8 : (
816 !force16bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444);
817 #else
818 case GL_INTENSITY:
819 case GL_COMPRESSED_INTENSITY:
820 return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
821 case GL_INTENSITY4:
822 return &_mesa_texformat_argb4444;
823 case GL_INTENSITY8:
824 case GL_INTENSITY12:
825 case GL_INTENSITY16:
826 return !force16bpt ? &_mesa_texformat_argb8888 :
827 &_mesa_texformat_argb4444;
828 #endif
829
830 case GL_RGB_S3TC:
831 case GL_RGB4_S3TC:
832 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
833 return &_mesa_texformat_rgb_dxt1;
834 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
835 return &_mesa_texformat_rgba_dxt1;
836
837 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
838 return &_mesa_texformat_rgba_dxt3;
839
840 case GL_RGBA_S3TC:
841 case GL_RGBA4_S3TC:
842 if (!isSavage4)
843 /* Not the best choice but Savage3D/MX/IX don't support DXT3 or DXT5. */
844 return &_mesa_texformat_rgba_dxt1;
845 /* fall through */
846 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
847 return &_mesa_texformat_rgba_dxt5;
848
849 /*
850 case GL_COLOR_INDEX:
851 case GL_COLOR_INDEX1_EXT:
852 case GL_COLOR_INDEX2_EXT:
853 case GL_COLOR_INDEX4_EXT:
854 case GL_COLOR_INDEX8_EXT:
855 case GL_COLOR_INDEX12_EXT:
856 case GL_COLOR_INDEX16_EXT:
857 return &_mesa_texformat_ci8;
858 */
859 default:
860 _mesa_problem(ctx, "unexpected texture format in %s", __FUNCTION__);
861 return NULL;
862 }
863 }
864
865 static void savageSetTexImages( savageContextPtr imesa,
866 const struct gl_texture_object *tObj )
867 {
868 savageTexObjPtr t = (savageTexObjPtr) tObj->DriverData;
869 struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
870 GLuint offset, i, textureFormat, tileIndex, size;
871 GLint firstLevel, lastLevel;
872
873 assert(t);
874 assert(image);
875
876 switch (image->TexFormat->MesaFormat) {
877 case MESA_FORMAT_ARGB8888:
878 textureFormat = TFT_ARGB8888;
879 t->texelBytes = tileIndex = 4;
880 break;
881 case MESA_FORMAT_ARGB1555:
882 textureFormat = TFT_ARGB1555;
883 t->texelBytes = tileIndex = 2;
884 break;
885 case MESA_FORMAT_ARGB4444:
886 textureFormat = TFT_ARGB4444;
887 t->texelBytes = tileIndex = 2;
888 break;
889 case MESA_FORMAT_RGB565:
890 textureFormat = TFT_RGB565;
891 t->texelBytes = tileIndex = 2;
892 break;
893 case MESA_FORMAT_L8:
894 textureFormat = TFT_L8;
895 t->texelBytes = tileIndex = 1;
896 break;
897 case MESA_FORMAT_I8:
898 textureFormat = TFT_I8;
899 t->texelBytes = tileIndex = 1;
900 break;
901 case MESA_FORMAT_A8:
902 textureFormat = TFT_A8;
903 t->texelBytes = tileIndex = 1;
904 break;
905 case MESA_FORMAT_RGB_DXT1:
906 textureFormat = TFT_S3TC4Bit;
907 tileIndex = TILE_INDEX_DXT1;
908 t->texelBytes = 8;
909 break;
910 case MESA_FORMAT_RGBA_DXT1:
911 textureFormat = TFT_S3TC4Bit;
912 tileIndex = TILE_INDEX_DXT1;
913 t->texelBytes = 8;
914 break;
915 case MESA_FORMAT_RGBA_DXT3:
916 textureFormat = TFT_S3TC4A4Bit;
917 tileIndex = TILE_INDEX_DXTn;
918 t->texelBytes = 16;
919 break;
920 case MESA_FORMAT_RGBA_DXT5:
921 textureFormat = TFT_S3TC4CA4Bit;
922 tileIndex = TILE_INDEX_DXTn;
923 t->texelBytes = 16;
924 break;
925 default:
926 _mesa_problem(imesa->glCtx, "Bad texture format in %s", __FUNCTION__);
927 return;
928 }
929 t->hwFormat = textureFormat;
930
931 /* Select tiling format depending on the chipset and texture format */
932 if (imesa->savageScreen->chipset <= S3_SAVAGE4)
933 t->tileInfo = &tileInfo_s3d_s4[tileIndex];
934 else
935 t->tileInfo = &tileInfo_pro[tileIndex];
936
937 /* Compute which mipmap levels we really want to send to the hardware.
938 */
939 driCalculateTextureFirstLastLevel( &t->base );
940 firstLevel = t->base.firstLevel;
941 lastLevel = t->base.lastLevel;
942
943 /* Figure out the size now (and count the levels). Upload won't be
944 * done until later. If the number of tiles changes, it means that
945 * this function is called for the first time on this tex object or
946 * the image or the destination color format changed. So all tiles
947 * are marked as dirty.
948 */
949 offset = 0;
950 size = 1;
951 for ( i = firstLevel ; i <= lastLevel && tObj->Image[0][i] ; i++ ) {
952 GLuint nTiles;
953 nTiles = savageTexImageTiles (image->Width2, image->Height2, t->tileInfo);
954 if (t->image[i].nTiles != nTiles) {
955 GLuint words = (nTiles + 31) / 32;
956 if (t->image[i].nTiles != 0) {
957 free(t->image[i].dirtyTiles);
958 }
959 t->image[i].dirtyTiles = malloc(words*sizeof(GLuint));
960 memset(t->image[i].dirtyTiles, ~0, words*sizeof(GLuint));
961 }
962 t->image[i].nTiles = nTiles;
963
964 t->image[i].offset = offset;
965
966 image = tObj->Image[0][i];
967 if (t->texelBytes >= 8)
968 size = savageCompressedTexImageSize (image->Width2, image->Height2,
969 t->texelBytes);
970 else
971 size = savageTexImageSize (image->Width2, image->Height2,
972 t->texelBytes);
973 offset += size;
974 }
975
976 t->base.lastLevel = i-1;
977 t->base.totalSize = offset;
978 /* the last three mipmap levels don't add to the offset. They are packed
979 * into 64 pixels. */
980 if (size == 0)
981 t->base.totalSize += (t->texelBytes >= 8 ? 4 : 64) * t->texelBytes;
982 /* 2k-aligned (really needed?) */
983 t->base.totalSize = (t->base.totalSize + 2047UL) & ~2047UL;
984 }
985
986 void savageDestroyTexObj(savageContextPtr imesa, savageTexObjPtr t)
987 {
988 GLuint i;
989
990 /* Free dirty tiles bit vectors */
991 for (i = 0; i < SAVAGE_TEX_MAXLEVELS; ++i) {
992 if (t->image[i].nTiles)
993 free (t->image[i].dirtyTiles);
994 }
995
996 /* See if it was the driver's current object.
997 */
998 if ( imesa != NULL )
999 {
1000 for ( i = 0 ; i < imesa->glCtx->Const.MaxTextureUnits ; i++ )
1001 {
1002 if ( &t->base == imesa->CurrentTexObj[ i ] ) {
1003 assert( t->base.bound & (1 << i) );
1004 imesa->CurrentTexObj[ i ] = NULL;
1005 }
1006 }
1007 }
1008 }
1009
1010 /* Upload a texture's images to one of the texture heaps. May have to
1011 * eject our own and/or other client's texture objects to make room
1012 * for the upload.
1013 */
1014 static void savageUploadTexImages( savageContextPtr imesa, savageTexObjPtr t )
1015 {
1016 const GLint numLevels = t->base.lastLevel - t->base.firstLevel + 1;
1017 GLuint i;
1018
1019 assert(t);
1020
1021 LOCK_HARDWARE(imesa);
1022
1023 /* Do we need to eject LRU texture objects?
1024 */
1025 if (!t->base.memBlock) {
1026 GLint heap;
1027 GLuint ofs;
1028
1029 heap = driAllocateTexture(imesa->textureHeaps, imesa->lastTexHeap,
1030 (driTextureObject *)t);
1031 if (heap == -1) {
1032 UNLOCK_HARDWARE(imesa);
1033 return;
1034 }
1035
1036 ofs = t->base.memBlock->ofs;
1037 t->setup.physAddr = imesa->savageScreen->textureOffset[heap] + ofs;
1038 t->bufAddr = (GLubyte *)imesa->savageScreen->texVirtual[heap] + ofs;
1039 imesa->dirty |= SAVAGE_UPLOAD_GLOBAL; /* FIXME: really needed? */
1040 }
1041
1042 /* Let the world know we've used this memory recently.
1043 */
1044 driUpdateTextureLRU( &t->base );
1045 UNLOCK_HARDWARE(imesa);
1046
1047 if (t->base.dirty_images[0] || t->dirtySubImages) {
1048 if (SAVAGE_DEBUG & DEBUG_VERBOSE_TEX)
1049 fprintf(stderr, "Texture upload: |");
1050
1051 /* Heap timestamps are only reliable with Savage DRM 2.3.x or
1052 * later. Earlier versions had only 16 bit time stamps which
1053 * would wrap too frequently. */
1054 if (imesa->savageScreen->driScrnPriv->drmMinor >= 3) {
1055 unsigned int heap = t->base.heap->heapId;
1056 LOCK_HARDWARE(imesa);
1057 savageWaitEvent (imesa, imesa->textureHeaps[heap]->timestamp);
1058 } else {
1059 savageFlushVertices (imesa);
1060 LOCK_HARDWARE(imesa);
1061 savageFlushCmdBufLocked (imesa, GL_FALSE);
1062 WAIT_IDLE_EMPTY_LOCKED(imesa);
1063 }
1064
1065 for (i = 0 ; i < numLevels ; i++) {
1066 const GLint j = t->base.firstLevel + i; /* the texObj's level */
1067 if (t->base.dirty_images[0] & (1 << j)) {
1068 savageMarkAllTiles(t, j);
1069 if (SAVAGE_DEBUG & DEBUG_VERBOSE_TEX)
1070 fprintf (stderr, "*");
1071 } else if (SAVAGE_DEBUG & DEBUG_VERBOSE_TEX) {
1072 if (t->dirtySubImages & (1 << j))
1073 fprintf (stderr, ".");
1074 else
1075 fprintf (stderr, " ");
1076 }
1077 if ((t->base.dirty_images[0] | t->dirtySubImages) & (1 << j))
1078 savageUploadTexLevel( t, j );
1079 }
1080
1081 UNLOCK_HARDWARE(imesa);
1082 t->base.dirty_images[0] = 0;
1083 t->dirtySubImages = 0;
1084
1085 if (SAVAGE_DEBUG & DEBUG_VERBOSE_TEX)
1086 fprintf(stderr, "|\n");
1087 }
1088 }
1089
1090
1091 static void
1092 savage4_set_wrap_mode( savageContextPtr imesa, unsigned unit,
1093 GLenum s_mode, GLenum t_mode )
1094 {
1095 switch( s_mode ) {
1096 case GL_REPEAT:
1097 imesa->regs.s4.texCtrl[ unit ].ni.uMode = TAM_Wrap;
1098 break;
1099 case GL_CLAMP:
1100 case GL_CLAMP_TO_EDGE:
1101 imesa->regs.s4.texCtrl[ unit ].ni.uMode = TAM_Clamp;
1102 break;
1103 case GL_MIRRORED_REPEAT:
1104 imesa->regs.s4.texCtrl[ unit ].ni.uMode = TAM_Mirror;
1105 break;
1106 }
1107
1108 switch( t_mode ) {
1109 case GL_REPEAT:
1110 imesa->regs.s4.texCtrl[ unit ].ni.vMode = TAM_Wrap;
1111 break;
1112 case GL_CLAMP:
1113 case GL_CLAMP_TO_EDGE:
1114 imesa->regs.s4.texCtrl[ unit ].ni.vMode = TAM_Clamp;
1115 break;
1116 case GL_MIRRORED_REPEAT:
1117 imesa->regs.s4.texCtrl[ unit ].ni.vMode = TAM_Mirror;
1118 break;
1119 }
1120 }
1121
1122
1123 /**
1124 * Sets the hardware bits for the specified GL texture filter modes.
1125 *
1126 * \todo
1127 * Does the Savage4 have the ability to select the magnification filter?
1128 */
1129 static void
1130 savage4_set_filter_mode( savageContextPtr imesa, unsigned unit,
1131 GLenum minFilter, GLenum magFilter )
1132 {
1133 (void) magFilter;
1134
1135 switch (minFilter) {
1136 case GL_NEAREST:
1137 imesa->regs.s4.texCtrl[ unit ].ni.filterMode = TFM_Point;
1138 imesa->regs.s4.texCtrl[ unit ].ni.mipmapEnable = GL_FALSE;
1139 break;
1140
1141 case GL_LINEAR:
1142 imesa->regs.s4.texCtrl[ unit ].ni.filterMode = TFM_Bilin;
1143 imesa->regs.s4.texCtrl[ unit ].ni.mipmapEnable = GL_FALSE;
1144 break;
1145
1146 case GL_NEAREST_MIPMAP_NEAREST:
1147 imesa->regs.s4.texCtrl[ unit ].ni.filterMode = TFM_Point;
1148 imesa->regs.s4.texCtrl[ unit ].ni.mipmapEnable = GL_TRUE;
1149 break;
1150
1151 case GL_LINEAR_MIPMAP_NEAREST:
1152 imesa->regs.s4.texCtrl[ unit ].ni.filterMode = TFM_Bilin;
1153 imesa->regs.s4.texCtrl[ unit ].ni.mipmapEnable = GL_TRUE;
1154 break;
1155
1156 case GL_NEAREST_MIPMAP_LINEAR:
1157 case GL_LINEAR_MIPMAP_LINEAR:
1158 imesa->regs.s4.texCtrl[ unit ].ni.filterMode = TFM_Trilin;
1159 imesa->regs.s4.texCtrl[ unit ].ni.mipmapEnable = GL_TRUE;
1160 break;
1161 }
1162 }
1163
1164
1165 static void savageUpdateTex0State_s4( GLcontext *ctx )
1166 {
1167 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
1168 struct gl_texture_object *tObj;
1169 struct gl_texture_image *image;
1170 savageTexObjPtr t;
1171 GLuint format;
1172
1173 /* disable */
1174 imesa->regs.s4.texDescr.ni.tex0En = GL_FALSE;
1175 imesa->regs.s4.texBlendCtrl[0].ui = TBC_NoTexMap;
1176 imesa->regs.s4.texCtrl[0].ui = 0x20f040;
1177 if (ctx->Texture.Unit[0]._ReallyEnabled == 0)
1178 return;
1179
1180 tObj = ctx->Texture.Unit[0]._Current;
1181 if ((ctx->Texture.Unit[0]._ReallyEnabled & ~(TEXTURE_1D_BIT|TEXTURE_2D_BIT))
1182 || tObj->Image[0][tObj->BaseLevel]->Border > 0) {
1183 /* 3D texturing enabled, or texture border - fallback */
1184 FALLBACK (ctx, SAVAGE_FALLBACK_TEXTURE, GL_TRUE);
1185 return;
1186 }
1187
1188 /* Do 2D texture setup */
1189
1190 t = tObj->DriverData;
1191 if (!t) {
1192 t = savageAllocTexObj( tObj );
1193 if (!t)
1194 return;
1195 }
1196
1197 imesa->CurrentTexObj[0] = &t->base;
1198 t->base.bound |= 1;
1199
1200 if (t->base.dirty_images[0] || t->dirtySubImages) {
1201 savageSetTexImages(imesa, tObj);
1202 savageUploadTexImages(imesa, t);
1203 }
1204
1205 driUpdateTextureLRU( &t->base );
1206
1207 format = tObj->Image[0][tObj->BaseLevel]->_BaseFormat;
1208
1209 switch (ctx->Texture.Unit[0].EnvMode) {
1210 case GL_REPLACE:
1211 imesa->regs.s4.texCtrl[0].ni.clrArg1Invert = GL_FALSE;
1212 switch(format)
1213 {
1214 case GL_LUMINANCE:
1215 case GL_RGB:
1216 imesa->regs.s4.texBlendCtrl[0].ui = TBC_Decal;
1217 break;
1218
1219 case GL_LUMINANCE_ALPHA:
1220 case GL_RGBA:
1221 case GL_INTENSITY:
1222 imesa->regs.s4.texBlendCtrl[0].ui = TBC_Copy;
1223 break;
1224
1225 case GL_ALPHA:
1226 imesa->regs.s4.texBlendCtrl[0].ui = TBC_CopyAlpha;
1227 break;
1228 }
1229 __HWEnvCombineSingleUnitScale(imesa, 0, 0,
1230 &imesa->regs.s4.texBlendCtrl[0]);
1231 break;
1232
1233 case GL_DECAL:
1234 imesa->regs.s4.texCtrl[0].ni.clrArg1Invert = GL_FALSE;
1235 switch (format)
1236 {
1237 case GL_RGB:
1238 case GL_LUMINANCE:
1239 imesa->regs.s4.texBlendCtrl[0].ui = TBC_Decal;
1240 break;
1241
1242 case GL_RGBA:
1243 case GL_INTENSITY:
1244 case GL_LUMINANCE_ALPHA:
1245 imesa->regs.s4.texBlendCtrl[0].ui = TBC_DecalAlpha;
1246 break;
1247
1248 /*
1249 GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_INTENSITY
1250 are undefined with GL_DECAL
1251 */
1252
1253 case GL_ALPHA:
1254 imesa->regs.s4.texBlendCtrl[0].ui = TBC_CopyAlpha;
1255 break;
1256 }
1257 __HWEnvCombineSingleUnitScale(imesa, 0, 0,
1258 &imesa->regs.s4.texBlendCtrl[0]);
1259 break;
1260
1261 case GL_MODULATE:
1262 imesa->regs.s4.texCtrl[0].ni.clrArg1Invert = GL_FALSE;
1263 imesa->regs.s4.texBlendCtrl[0].ui = TBC_ModulAlpha;
1264 __HWEnvCombineSingleUnitScale(imesa, 0, 0,
1265 &imesa->regs.s4.texBlendCtrl[0]);
1266 break;
1267
1268 case GL_BLEND:
1269 imesa->regs.s4.texBlendColor.ui = imesa->texEnvColor;
1270
1271 switch (format)
1272 {
1273 case GL_ALPHA:
1274 imesa->regs.s4.texBlendCtrl[0].ui = TBC_ModulAlpha;
1275 imesa->regs.s4.texCtrl[0].ni.clrArg1Invert = GL_FALSE;
1276 break;
1277
1278 case GL_LUMINANCE:
1279 case GL_RGB:
1280 imesa->regs.s4.texBlendCtrl[0].ui = TBC_Blend0;
1281 imesa->regs.s4.texDescr.ni.tex1En = GL_TRUE;
1282 imesa->regs.s4.texDescr.ni.texBLoopEn = GL_TRUE;
1283 imesa->regs.s4.texDescr.ni.tex1Width =
1284 imesa->regs.s4.texDescr.ni.tex0Width;
1285 imesa->regs.s4.texDescr.ni.tex1Height =
1286 imesa->regs.s4.texDescr.ni.tex0Height;
1287 imesa->regs.s4.texDescr.ni.tex1Fmt =
1288 imesa->regs.s4.texDescr.ni.tex0Fmt;
1289
1290 imesa->regs.s4.texAddr[1].ui = imesa->regs.s4.texAddr[0].ui;
1291 imesa->regs.s4.texBlendCtrl[1].ui = TBC_Blend1;
1292
1293 imesa->regs.s4.texCtrl[0].ni.clrArg1Invert = GL_TRUE;
1294 imesa->bTexEn1 = GL_TRUE;
1295 break;
1296
1297 case GL_LUMINANCE_ALPHA:
1298 case GL_RGBA:
1299 imesa->regs.s4.texBlendCtrl[0].ui = TBC_BlendAlpha0;
1300 imesa->regs.s4.texDescr.ni.tex1En = GL_TRUE;
1301 imesa->regs.s4.texDescr.ni.texBLoopEn = GL_TRUE;
1302 imesa->regs.s4.texDescr.ni.tex1Width =
1303 imesa->regs.s4.texDescr.ni.tex0Width;
1304 imesa->regs.s4.texDescr.ni.tex1Height =
1305 imesa->regs.s4.texDescr.ni.tex0Height;
1306 imesa->regs.s4.texDescr.ni.tex1Fmt =
1307 imesa->regs.s4.texDescr.ni.tex0Fmt;
1308
1309 imesa->regs.s4.texAddr[1].ui = imesa->regs.s4.texAddr[0].ui;
1310 imesa->regs.s4.texBlendCtrl[1].ui = TBC_BlendAlpha1;
1311
1312 imesa->regs.s4.texCtrl[0].ni.clrArg1Invert = GL_TRUE;
1313 imesa->bTexEn1 = GL_TRUE;
1314 break;
1315
1316 case GL_INTENSITY:
1317 imesa->regs.s4.texBlendCtrl[0].ui = TBC_BlendInt0;
1318 imesa->regs.s4.texDescr.ni.tex1En = GL_TRUE;
1319 imesa->regs.s4.texDescr.ni.texBLoopEn = GL_TRUE;
1320 imesa->regs.s4.texDescr.ni.tex1Width =
1321 imesa->regs.s4.texDescr.ni.tex0Width;
1322 imesa->regs.s4.texDescr.ni.tex1Height =
1323 imesa->regs.s4.texDescr.ni.tex0Height;
1324 imesa->regs.s4.texDescr.ni.tex1Fmt =
1325 imesa->regs.s4.texDescr.ni.tex0Fmt;
1326
1327 imesa->regs.s4.texAddr[1].ui = imesa->regs.s4.texAddr[0].ui;
1328 imesa->regs.s4.texBlendCtrl[1].ui = TBC_BlendInt1;
1329
1330 imesa->regs.s4.texCtrl[0].ni.clrArg1Invert = GL_TRUE;
1331 imesa->regs.s4.texCtrl[0].ni.alphaArg1Invert = GL_TRUE;
1332 imesa->bTexEn1 = GL_TRUE;
1333 break;
1334 }
1335 __HWEnvCombineSingleUnitScale(imesa, 0, 0,
1336 &imesa->regs.s4.texBlendCtrl[0]);
1337 break;
1338
1339 case GL_ADD:
1340 imesa->regs.s4.texCtrl[0].ni.clrArg1Invert = GL_FALSE;
1341 switch (format)
1342 {
1343 case GL_ALPHA:
1344 imesa->regs.s4.texBlendCtrl[0].ui = TBC_ModulAlpha;
1345 break;
1346
1347 case GL_LUMINANCE:
1348 case GL_RGB:
1349 imesa->regs.s4.texBlendCtrl[0].ui = TBC_Add;
1350 break;
1351
1352 case GL_LUMINANCE_ALPHA:
1353 case GL_RGBA:
1354 imesa->regs.s4.texBlendCtrl[0].ui = TBC_Add;
1355 break;
1356
1357 case GL_INTENSITY:
1358 imesa->regs.s4.texBlendCtrl[0].ui = TBC_AddAlpha;
1359 break;
1360 }
1361 __HWEnvCombineSingleUnitScale(imesa, 0, 0,
1362 &imesa->regs.s4.texBlendCtrl[0]);
1363 break;
1364
1365 #if GL_ARB_texture_env_combine
1366 case GL_COMBINE_ARB:
1367 __HWParseTexEnvCombine(imesa, 0, &imesa->regs.s4.texCtrl[0],
1368 &imesa->regs.s4.texBlendCtrl[0]);
1369 break;
1370 #endif
1371
1372 default:
1373 fprintf(stderr, "unknown tex env mode");
1374 exit(1);
1375 break;
1376 }
1377
1378 savage4_set_wrap_mode( imesa, 0, t->setup.sWrapMode, t->setup.tWrapMode );
1379 savage4_set_filter_mode( imesa, 0, t->setup.minFilter, t->setup.magFilter );
1380
1381 if((ctx->Texture.Unit[0].LodBias !=0.0F) ||
1382 (imesa->regs.s4.texCtrl[0].ni.dBias != 0))
1383 {
1384 int bias = (int)(ctx->Texture.Unit[0].LodBias * 32.0) +
1385 SAVAGE4_LOD_OFFSET;
1386 if (bias < -256)
1387 bias = -256;
1388 else if (bias > 255)
1389 bias = 255;
1390 imesa->regs.s4.texCtrl[0].ni.dBias = bias & 0x1ff;
1391 }
1392
1393 image = tObj->Image[0][tObj->BaseLevel];
1394 imesa->regs.s4.texDescr.ni.tex0En = GL_TRUE;
1395 imesa->regs.s4.texDescr.ni.tex0Width = image->WidthLog2;
1396 imesa->regs.s4.texDescr.ni.tex0Height = image->HeightLog2;
1397 imesa->regs.s4.texDescr.ni.tex0Fmt = t->hwFormat;
1398 imesa->regs.s4.texCtrl[0].ni.dMax = t->base.lastLevel - t->base.firstLevel;
1399
1400 if (imesa->regs.s4.texDescr.ni.tex1En)
1401 imesa->regs.s4.texDescr.ni.texBLoopEn = GL_TRUE;
1402
1403 imesa->regs.s4.texAddr[0].ui = (u_int32_t) t->setup.physAddr | 0x2;
1404 if(t->base.heap->heapId == SAVAGE_AGP_HEAP)
1405 imesa->regs.s4.texAddr[0].ui |= 0x1;
1406
1407 return;
1408 }
1409 static void savageUpdateTex1State_s4( GLcontext *ctx )
1410 {
1411 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
1412 struct gl_texture_object *tObj;
1413 struct gl_texture_image *image;
1414 savageTexObjPtr t;
1415 GLuint format;
1416
1417 /* disable */
1418 if(imesa->bTexEn1)
1419 {
1420 imesa->bTexEn1 = GL_FALSE;
1421 return;
1422 }
1423
1424 imesa->regs.s4.texDescr.ni.tex1En = GL_FALSE;
1425 imesa->regs.s4.texBlendCtrl[1].ui = TBC_NoTexMap1;
1426 imesa->regs.s4.texCtrl[1].ui = 0x20f040;
1427 imesa->regs.s4.texDescr.ni.texBLoopEn = GL_FALSE;
1428 if (ctx->Texture.Unit[1]._ReallyEnabled == 0)
1429 return;
1430
1431 tObj = ctx->Texture.Unit[1]._Current;
1432
1433 if ((ctx->Texture.Unit[1]._ReallyEnabled & ~(TEXTURE_1D_BIT|TEXTURE_2D_BIT))
1434 || tObj->Image[0][tObj->BaseLevel]->Border > 0) {
1435 /* 3D texturing enabled, or texture border - fallback */
1436 FALLBACK (ctx, SAVAGE_FALLBACK_TEXTURE, GL_TRUE);
1437 return;
1438 }
1439
1440 /* Do 2D texture setup */
1441
1442 t = tObj->DriverData;
1443 if (!t) {
1444 t = savageAllocTexObj( tObj );
1445 if (!t)
1446 return;
1447 }
1448
1449 imesa->CurrentTexObj[1] = &t->base;
1450
1451 t->base.bound |= 2;
1452
1453 if (t->base.dirty_images[0] || t->dirtySubImages) {
1454 savageSetTexImages(imesa, tObj);
1455 savageUploadTexImages(imesa, t);
1456 }
1457
1458 driUpdateTextureLRU( &t->base );
1459
1460 format = tObj->Image[0][tObj->BaseLevel]->_BaseFormat;
1461
1462 switch (ctx->Texture.Unit[1].EnvMode) {
1463 case GL_REPLACE:
1464 imesa->regs.s4.texCtrl[1].ni.clrArg1Invert = GL_FALSE;
1465 switch (format)
1466 {
1467 case GL_LUMINANCE:
1468 case GL_RGB:
1469 imesa->regs.s4.texBlendCtrl[1].ui = TBC_Decal;
1470 break;
1471
1472 case GL_LUMINANCE_ALPHA:
1473 case GL_INTENSITY:
1474 case GL_RGBA:
1475 imesa->regs.s4.texBlendCtrl[1].ui = TBC_Copy;
1476 break;
1477
1478 case GL_ALPHA:
1479 imesa->regs.s4.texBlendCtrl[1].ui = TBC_CopyAlpha1;
1480 break;
1481 }
1482 __HWEnvCombineSingleUnitScale(imesa, 0, 1, &imesa->regs.s4.texBlendCtrl);
1483 break;
1484 case GL_MODULATE:
1485 imesa->regs.s4.texCtrl[1].ni.clrArg1Invert = GL_FALSE;
1486 imesa->regs.s4.texBlendCtrl[1].ui = TBC_ModulAlpha1;
1487 __HWEnvCombineSingleUnitScale(imesa, 0, 1, &imesa->regs.s4.texBlendCtrl);
1488 break;
1489
1490 case GL_ADD:
1491 imesa->regs.s4.texCtrl[1].ni.clrArg1Invert = GL_FALSE;
1492 switch (format)
1493 {
1494 case GL_ALPHA:
1495 imesa->regs.s4.texBlendCtrl[1].ui = TBC_ModulAlpha1;
1496 break;
1497
1498 case GL_LUMINANCE:
1499 case GL_RGB:
1500 imesa->regs.s4.texBlendCtrl[1].ui = TBC_Add1;
1501 break;
1502
1503 case GL_LUMINANCE_ALPHA:
1504 case GL_RGBA:
1505 imesa->regs.s4.texBlendCtrl[1].ui = TBC_Add1;
1506 break;
1507
1508 case GL_INTENSITY:
1509 imesa->regs.s4.texBlendCtrl[1].ui = TBC_AddAlpha1;
1510 break;
1511 }
1512 __HWEnvCombineSingleUnitScale(imesa, 0, 1, &imesa->regs.s4.texBlendCtrl);
1513 break;
1514
1515 #if GL_ARB_texture_env_combine
1516 case GL_COMBINE_ARB:
1517 __HWParseTexEnvCombine(imesa, 1, &texCtrl, &imesa->regs.s4.texBlendCtrl);
1518 break;
1519 #endif
1520
1521 case GL_DECAL:
1522 imesa->regs.s4.texCtrl[1].ni.clrArg1Invert = GL_FALSE;
1523
1524 switch (format)
1525 {
1526 case GL_LUMINANCE:
1527 case GL_RGB:
1528 imesa->regs.s4.texBlendCtrl[1].ui = TBC_Decal1;
1529 break;
1530 case GL_LUMINANCE_ALPHA:
1531 case GL_INTENSITY:
1532 case GL_RGBA:
1533 imesa->regs.s4.texBlendCtrl[1].ui = TBC_DecalAlpha1;
1534 break;
1535
1536 /*
1537 // GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_INTENSITY
1538 // are undefined with GL_DECAL
1539 */
1540 case GL_ALPHA:
1541 imesa->regs.s4.texBlendCtrl[1].ui = TBC_CopyAlpha1;
1542 break;
1543 }
1544 __HWEnvCombineSingleUnitScale(imesa, 0, 1, &imesa->regs.s4.texBlendCtrl);
1545 break;
1546
1547 case GL_BLEND:
1548 if (format == GL_LUMINANCE)
1549 {
1550 /*
1551 // This is a hack for GLQuake, invert.
1552 */
1553 imesa->regs.s4.texCtrl[1].ni.clrArg1Invert = GL_TRUE;
1554 imesa->regs.s4.texBlendCtrl[1].ui = 0;
1555 }
1556 __HWEnvCombineSingleUnitScale(imesa, 0, 1, &imesa->regs.s4.texBlendCtrl);
1557 break;
1558
1559 default:
1560 fprintf(stderr, "unknown tex 1 env mode\n");
1561 exit(1);
1562 break;
1563 }
1564
1565 savage4_set_wrap_mode( imesa, 1, t->setup.sWrapMode, t->setup.tWrapMode );
1566 savage4_set_filter_mode( imesa, 1, t->setup.minFilter, t->setup.magFilter );
1567
1568 if((ctx->Texture.Unit[1].LodBias !=0.0F) ||
1569 (imesa->regs.s4.texCtrl[1].ni.dBias != 0))
1570 {
1571 int bias = (int)(ctx->Texture.Unit[1].LodBias * 32.0) +
1572 SAVAGE4_LOD_OFFSET;
1573 if (bias < -256)
1574 bias = -256;
1575 else if (bias > 255)
1576 bias = 255;
1577 imesa->regs.s4.texCtrl[1].ni.dBias = bias & 0x1ff;
1578 }
1579
1580 image = tObj->Image[0][tObj->BaseLevel];
1581 imesa->regs.s4.texDescr.ni.tex1En = GL_TRUE;
1582 imesa->regs.s4.texDescr.ni.tex1Width = image->WidthLog2;
1583 imesa->regs.s4.texDescr.ni.tex1Height = image->HeightLog2;
1584 imesa->regs.s4.texDescr.ni.tex1Fmt = t->hwFormat;
1585 imesa->regs.s4.texCtrl[1].ni.dMax = t->base.lastLevel - t->base.firstLevel;
1586 imesa->regs.s4.texDescr.ni.texBLoopEn = GL_TRUE;
1587
1588 imesa->regs.s4.texAddr[1].ui = (u_int32_t) t->setup.physAddr | 2;
1589 if(t->base.heap->heapId == SAVAGE_AGP_HEAP)
1590 imesa->regs.s4.texAddr[1].ui |= 0x1;
1591 }
1592 static void savageUpdateTexState_s3d( GLcontext *ctx )
1593 {
1594 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
1595 struct gl_texture_object *tObj;
1596 struct gl_texture_image *image;
1597 savageTexObjPtr t;
1598 GLuint format;
1599
1600 /* disable */
1601 imesa->regs.s3d.texCtrl.ui = 0;
1602 imesa->regs.s3d.texCtrl.ni.texEn = GL_FALSE;
1603 imesa->regs.s3d.texCtrl.ni.dBias = 0x08;
1604 imesa->regs.s3d.texCtrl.ni.texXprEn = GL_TRUE;
1605 if (ctx->Texture.Unit[0]._ReallyEnabled == 0)
1606 return;
1607
1608 tObj = ctx->Texture.Unit[0]._Current;
1609 if ((ctx->Texture.Unit[0]._ReallyEnabled & ~(TEXTURE_1D_BIT|TEXTURE_2D_BIT))
1610 || tObj->Image[0][tObj->BaseLevel]->Border > 0) {
1611 /* 3D texturing enabled, or texture border - fallback */
1612 FALLBACK (ctx, SAVAGE_FALLBACK_TEXTURE, GL_TRUE);
1613 return;
1614 }
1615
1616 /* Do 2D texture setup */
1617 t = tObj->DriverData;
1618 if (!t) {
1619 t = savageAllocTexObj( tObj );
1620 if (!t)
1621 return;
1622 }
1623
1624 imesa->CurrentTexObj[0] = &t->base;
1625 t->base.bound |= 1;
1626
1627 if (t->base.dirty_images[0] || t->dirtySubImages) {
1628 savageSetTexImages(imesa, tObj);
1629 savageUploadTexImages(imesa, t);
1630 }
1631
1632 driUpdateTextureLRU( &t->base );
1633
1634 format = tObj->Image[0][tObj->BaseLevel]->_BaseFormat;
1635
1636 /* FIXME: copied from utah-glx, probably needs some tuning */
1637 switch (ctx->Texture.Unit[0].EnvMode) {
1638 case GL_DECAL:
1639 imesa->regs.s3d.drawCtrl.ni.texBlendCtrl = SAVAGETBC_DECALALPHA_S3D;
1640 break;
1641 case GL_REPLACE:
1642 switch (format) {
1643 case GL_ALPHA: /* FIXME */
1644 imesa->regs.s3d.drawCtrl.ni.texBlendCtrl = 1;
1645 break;
1646 case GL_LUMINANCE_ALPHA:
1647 case GL_RGBA:
1648 imesa->regs.s3d.drawCtrl.ni.texBlendCtrl = 4;
1649 break;
1650 case GL_RGB:
1651 case GL_LUMINANCE:
1652 imesa->regs.s3d.drawCtrl.ni.texBlendCtrl = SAVAGETBC_DECAL_S3D;
1653 break;
1654 case GL_INTENSITY:
1655 imesa->regs.s3d.drawCtrl.ni.texBlendCtrl = SAVAGETBC_COPY_S3D;
1656 }
1657 break;
1658 case GL_BLEND: /* hardware can't do GL_BLEND */
1659 FALLBACK (ctx, SAVAGE_FALLBACK_TEXTURE, GL_TRUE);
1660 return;
1661 case GL_MODULATE:
1662 imesa->regs.s3d.drawCtrl.ni.texBlendCtrl = SAVAGETBC_MODULATEALPHA_S3D;
1663 break;
1664 default:
1665 fprintf(stderr, "unknown tex env mode\n");
1666 /*exit(1);*/
1667 break;
1668 }
1669
1670 /* The Savage3D can't handle different wrapping modes in s and t.
1671 * If they are not the same, fall back to software. */
1672 if (t->setup.sWrapMode != t->setup.tWrapMode) {
1673 FALLBACK (ctx, SAVAGE_FALLBACK_TEXTURE, GL_TRUE);
1674 return;
1675 }
1676 imesa->regs.s3d.texCtrl.ni.uWrapEn = 0;
1677 imesa->regs.s3d.texCtrl.ni.vWrapEn = 0;
1678 imesa->regs.s3d.texCtrl.ni.wrapMode =
1679 (t->setup.sWrapMode == GL_REPEAT) ? TAM_Wrap : TAM_Clamp;
1680
1681 switch (t->setup.minFilter) {
1682 case GL_NEAREST:
1683 imesa->regs.s3d.texCtrl.ni.filterMode = TFM_Point;
1684 imesa->regs.s3d.texCtrl.ni.mipmapDisable = GL_TRUE;
1685 break;
1686
1687 case GL_LINEAR:
1688 imesa->regs.s3d.texCtrl.ni.filterMode = TFM_Bilin;
1689 imesa->regs.s3d.texCtrl.ni.mipmapDisable = GL_TRUE;
1690 break;
1691
1692 case GL_NEAREST_MIPMAP_NEAREST:
1693 imesa->regs.s3d.texCtrl.ni.filterMode = TFM_Point;
1694 imesa->regs.s3d.texCtrl.ni.mipmapDisable = GL_FALSE;
1695 break;
1696
1697 case GL_LINEAR_MIPMAP_NEAREST:
1698 imesa->regs.s3d.texCtrl.ni.filterMode = TFM_Bilin;
1699 imesa->regs.s3d.texCtrl.ni.mipmapDisable = GL_FALSE;
1700 break;
1701
1702 case GL_NEAREST_MIPMAP_LINEAR:
1703 case GL_LINEAR_MIPMAP_LINEAR:
1704 imesa->regs.s3d.texCtrl.ni.filterMode = TFM_Trilin;
1705 imesa->regs.s3d.texCtrl.ni.mipmapDisable = GL_FALSE;
1706 break;
1707 }
1708
1709 /* There is no way to specify a maximum mipmap level. We may have to
1710 disable mipmapping completely. */
1711 /*
1712 if (t->max_level < t->image[0].image->WidthLog2 ||
1713 t->max_level < t->image[0].image->HeightLog2) {
1714 texCtrl.ni.mipmapEnable = GL_TRUE;
1715 if (texCtrl.ni.filterMode == TFM_Trilin)
1716 texCtrl.ni.filterMode = TFM_Bilin;
1717 texCtrl.ni.filterMode = TFM_Point;
1718 }
1719 */
1720
1721 if((ctx->Texture.Unit[0].LodBias !=0.0F) ||
1722 (imesa->regs.s3d.texCtrl.ni.dBias != 0))
1723 {
1724 int bias = (int)(ctx->Texture.Unit[0].LodBias * 16.0);
1725 if (bias < -256)
1726 bias = -256;
1727 else if (bias > 255)
1728 bias = 255;
1729 imesa->regs.s3d.texCtrl.ni.dBias = bias & 0x1ff;
1730 }
1731
1732 image = tObj->Image[0][tObj->BaseLevel];
1733 imesa->regs.s3d.texCtrl.ni.texEn = GL_TRUE;
1734 imesa->regs.s3d.texDescr.ni.texWidth = image->WidthLog2;
1735 imesa->regs.s3d.texDescr.ni.texHeight = image->HeightLog2;
1736 assert (t->hwFormat <= 7);
1737 imesa->regs.s3d.texDescr.ni.texFmt = t->hwFormat;
1738
1739 imesa->regs.s3d.texAddr.ui = (u_int32_t) t->setup.physAddr | 2;
1740 if(t->base.heap->heapId == SAVAGE_AGP_HEAP)
1741 imesa->regs.s3d.texAddr.ui |= 0x1;
1742 }
1743
1744
1745 static void savageTimestampTextures( savageContextPtr imesa )
1746 {
1747 /* Timestamp current texture objects for texture heap aging.
1748 * Only useful with long-lived 32-bit event tags available
1749 * with Savage DRM 2.3.x or later. */
1750 if ((imesa->CurrentTexObj[0] || imesa->CurrentTexObj[1]) &&
1751 imesa->savageScreen->driScrnPriv->drmMinor >= 3) {
1752 unsigned int e;
1753 FLUSH_BATCH(imesa);
1754 e = savageEmitEvent(imesa, SAVAGE_WAIT_3D);
1755 if (imesa->CurrentTexObj[0])
1756 imesa->CurrentTexObj[0]->timestamp = e;
1757 if (imesa->CurrentTexObj[1])
1758 imesa->CurrentTexObj[1]->timestamp = e;
1759 }
1760 }
1761
1762
1763 static void savageUpdateTextureState_s4( GLcontext *ctx )
1764 {
1765 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
1766
1767 /* When a texture is about to change or be disabled, timestamp the
1768 * old texture(s). We'll have to wait for this time stamp before
1769 * uploading anything to the same texture heap.
1770 */
1771 if ((imesa->CurrentTexObj[0] && ctx->Texture.Unit[0]._ReallyEnabled &&
1772 ctx->Texture.Unit[0]._Current->DriverData != imesa->CurrentTexObj[0]) ||
1773 (imesa->CurrentTexObj[1] && ctx->Texture.Unit[1]._ReallyEnabled &&
1774 ctx->Texture.Unit[1]._Current->DriverData != imesa->CurrentTexObj[1]) ||
1775 (imesa->CurrentTexObj[0] && !ctx->Texture.Unit[0]._ReallyEnabled) ||
1776 (imesa->CurrentTexObj[1] && !ctx->Texture.Unit[1]._ReallyEnabled))
1777 savageTimestampTextures(imesa);
1778
1779 if (imesa->CurrentTexObj[0]) imesa->CurrentTexObj[0]->bound &= ~1;
1780 if (imesa->CurrentTexObj[1]) imesa->CurrentTexObj[1]->bound &= ~2;
1781 imesa->CurrentTexObj[0] = 0;
1782 imesa->CurrentTexObj[1] = 0;
1783 savageUpdateTex0State_s4( ctx );
1784 savageUpdateTex1State_s4( ctx );
1785 imesa->dirty |= (SAVAGE_UPLOAD_TEX0 |
1786 SAVAGE_UPLOAD_TEX1);
1787 }
1788 static void savageUpdateTextureState_s3d( GLcontext *ctx )
1789 {
1790 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
1791
1792 /* When a texture is about to change or be disabled, timestamp the
1793 * old texture(s). We'll have to wait for this time stamp before
1794 * uploading anything to the same texture heap.
1795 */
1796 if ((imesa->CurrentTexObj[0] && ctx->Texture.Unit[0]._ReallyEnabled &&
1797 ctx->Texture.Unit[0]._Current->DriverData != imesa->CurrentTexObj[0]) ||
1798 (imesa->CurrentTexObj[0] && !ctx->Texture.Unit[0]._ReallyEnabled))
1799 savageTimestampTextures(imesa);
1800
1801 if (imesa->CurrentTexObj[0]) imesa->CurrentTexObj[0]->bound &= ~1;
1802 imesa->CurrentTexObj[0] = 0;
1803 savageUpdateTexState_s3d( ctx );
1804 imesa->dirty |= (SAVAGE_UPLOAD_TEX0);
1805 }
1806 void savageUpdateTextureState( GLcontext *ctx)
1807 {
1808 savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
1809 FALLBACK (ctx, SAVAGE_FALLBACK_TEXTURE, GL_FALSE);
1810 FALLBACK(ctx, SAVAGE_FALLBACK_PROJ_TEXTURE, GL_FALSE);
1811 if (imesa->savageScreen->chipset >= S3_SAVAGE4)
1812 savageUpdateTextureState_s4 (ctx);
1813 else
1814 savageUpdateTextureState_s3d (ctx);
1815 }
1816
1817
1818
1819 /*****************************************
1820 * DRIVER functions
1821 *****************************************/
1822
1823 static void savageTexEnv( GLcontext *ctx, GLenum target,
1824 GLenum pname, const GLfloat *param )
1825 {
1826 savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
1827
1828 if (pname == GL_TEXTURE_ENV_MODE) {
1829
1830 imesa->new_state |= SAVAGE_NEW_TEXTURE;
1831
1832 } else if (pname == GL_TEXTURE_ENV_COLOR) {
1833
1834 struct gl_texture_unit *texUnit =
1835 &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1836 const GLfloat *fc = texUnit->EnvColor;
1837 GLuint r, g, b, a;
1838 CLAMPED_FLOAT_TO_UBYTE(r, fc[0]);
1839 CLAMPED_FLOAT_TO_UBYTE(g, fc[1]);
1840 CLAMPED_FLOAT_TO_UBYTE(b, fc[2]);
1841 CLAMPED_FLOAT_TO_UBYTE(a, fc[3]);
1842
1843 imesa->texEnvColor = ((a << 24) | (r << 16) |
1844 (g << 8) | (b << 0));
1845
1846
1847 }
1848 }
1849
1850 /* Update the heap's time stamp, so the new image is not uploaded
1851 * while the old one is still in use. If the texture that is going to
1852 * be changed is currently bound, we need to timestamp the texture
1853 * first. */
1854 static void savageTexImageChanged (savageTexObjPtr t) {
1855 if (t->base.heap) {
1856 if (t->base.bound)
1857 savageTimestampTextures(
1858 (savageContextPtr)t->base.heap->driverContext);
1859 if (t->base.timestamp > t->base.heap->timestamp)
1860 t->base.heap->timestamp = t->base.timestamp;
1861 }
1862 }
1863
1864 static void savageTexImage1D( GLcontext *ctx, GLenum target, GLint level,
1865 GLint internalFormat,
1866 GLint width, GLint border,
1867 GLenum format, GLenum type, const GLvoid *pixels,
1868 const struct gl_pixelstore_attrib *packing,
1869 struct gl_texture_object *texObj,
1870 struct gl_texture_image *texImage )
1871 {
1872 savageTexObjPtr t = (savageTexObjPtr) texObj->DriverData;
1873 if (t) {
1874 savageTexImageChanged (t);
1875 } else {
1876 t = savageAllocTexObj(texObj);
1877 if (!t) {
1878 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
1879 return;
1880 }
1881 }
1882 _mesa_store_teximage1d( ctx, target, level, internalFormat,
1883 width, border, format, type,
1884 pixels, packing, texObj, texImage );
1885 t->base.dirty_images[0] |= (1 << level);
1886 SAVAGE_CONTEXT(ctx)->new_state |= SAVAGE_NEW_TEXTURE;
1887 }
1888
1889 static void savageTexSubImage1D( GLcontext *ctx,
1890 GLenum target,
1891 GLint level,
1892 GLint xoffset,
1893 GLsizei width,
1894 GLenum format, GLenum type,
1895 const GLvoid *pixels,
1896 const struct gl_pixelstore_attrib *packing,
1897 struct gl_texture_object *texObj,
1898 struct gl_texture_image *texImage )
1899 {
1900 savageTexObjPtr t = (savageTexObjPtr) texObj->DriverData;
1901 assert( t ); /* this _should_ be true */
1902 if (t) {
1903 savageTexImageChanged (t);
1904 savageMarkDirtyTiles(t, level, texImage->Width2, 1,
1905 xoffset, 0, width, 1);
1906 } else {
1907 t = savageAllocTexObj(texObj);
1908 if (!t) {
1909 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
1910 return;
1911 }
1912 t->base.dirty_images[0] |= (1 << level);
1913 }
1914 _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
1915 format, type, pixels, packing, texObj,
1916 texImage);
1917 t->dirtySubImages |= (1 << level);
1918 SAVAGE_CONTEXT(ctx)->new_state |= SAVAGE_NEW_TEXTURE;
1919 }
1920
1921 static void savageTexImage2D( GLcontext *ctx, GLenum target, GLint level,
1922 GLint internalFormat,
1923 GLint width, GLint height, GLint border,
1924 GLenum format, GLenum type, const GLvoid *pixels,
1925 const struct gl_pixelstore_attrib *packing,
1926 struct gl_texture_object *texObj,
1927 struct gl_texture_image *texImage )
1928 {
1929 savageTexObjPtr t = (savageTexObjPtr) texObj->DriverData;
1930 if (t) {
1931 savageTexImageChanged (t);
1932 } else {
1933 t = savageAllocTexObj(texObj);
1934 if (!t) {
1935 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1936 return;
1937 }
1938 }
1939 _mesa_store_teximage2d( ctx, target, level, internalFormat,
1940 width, height, border, format, type,
1941 pixels, packing, texObj, texImage );
1942 t->base.dirty_images[0] |= (1 << level);
1943 SAVAGE_CONTEXT(ctx)->new_state |= SAVAGE_NEW_TEXTURE;
1944 }
1945
1946 static void savageTexSubImage2D( GLcontext *ctx,
1947 GLenum target,
1948 GLint level,
1949 GLint xoffset, GLint yoffset,
1950 GLsizei width, GLsizei height,
1951 GLenum format, GLenum type,
1952 const GLvoid *pixels,
1953 const struct gl_pixelstore_attrib *packing,
1954 struct gl_texture_object *texObj,
1955 struct gl_texture_image *texImage )
1956 {
1957 savageTexObjPtr t = (savageTexObjPtr) texObj->DriverData;
1958 assert( t ); /* this _should_ be true */
1959 if (t) {
1960 savageTexImageChanged (t);
1961 savageMarkDirtyTiles(t, level, texImage->Width2, texImage->Height2,
1962 xoffset, yoffset, width, height);
1963 } else {
1964 t = savageAllocTexObj(texObj);
1965 if (!t) {
1966 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
1967 return;
1968 }
1969 t->base.dirty_images[0] |= (1 << level);
1970 }
1971 _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
1972 height, format, type, pixels, packing, texObj,
1973 texImage);
1974 t->dirtySubImages |= (1 << level);
1975 SAVAGE_CONTEXT(ctx)->new_state |= SAVAGE_NEW_TEXTURE;
1976 }
1977
1978 static void
1979 savageCompressedTexImage2D( GLcontext *ctx, GLenum target, GLint level,
1980 GLint internalFormat,
1981 GLint width, GLint height, GLint border,
1982 GLsizei imageSize, const GLvoid *data,
1983 struct gl_texture_object *texObj,
1984 struct gl_texture_image *texImage )
1985 {
1986 savageTexObjPtr t = (savageTexObjPtr) texObj->DriverData;
1987 if (t) {
1988 savageTexImageChanged (t);
1989 } else {
1990 t = savageAllocTexObj(texObj);
1991 if (!t) {
1992 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
1993 return;
1994 }
1995 }
1996 _mesa_store_compressed_teximage2d( ctx, target, level, internalFormat,
1997 width, height, border, imageSize,
1998 data, texObj, texImage );
1999 t->base.dirty_images[0] |= (1 << level);
2000 SAVAGE_CONTEXT(ctx)->new_state |= SAVAGE_NEW_TEXTURE;
2001 }
2002
2003 static void
2004 savageCompressedTexSubImage2D( GLcontext *ctx,
2005 GLenum target,
2006 GLint level,
2007 GLint xoffset, GLint yoffset,
2008 GLsizei width, GLsizei height,
2009 GLenum format, GLsizei imageSize,
2010 const GLvoid *data,
2011 struct gl_texture_object *texObj,
2012 struct gl_texture_image *texImage )
2013 {
2014 savageTexObjPtr t = (savageTexObjPtr) texObj->DriverData;
2015 assert( t ); /* this _should_ be true */
2016 if (t) {
2017 savageTexImageChanged (t);
2018 savageMarkDirtyTiles(t, level, texImage->Width2, texImage->Height2,
2019 xoffset, yoffset, width, height);
2020 } else {
2021 t = savageAllocTexObj(texObj);
2022 if (!t) {
2023 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
2024 return;
2025 }
2026 t->base.dirty_images[0] |= (1 << level);
2027 }
2028 _mesa_store_compressed_texsubimage2d(ctx, target, level, xoffset, yoffset,
2029 width, height, format, imageSize,
2030 data, texObj, texImage);
2031 t->dirtySubImages |= (1 << level);
2032 SAVAGE_CONTEXT(ctx)->new_state |= SAVAGE_NEW_TEXTURE;
2033 }
2034
2035 static void savageTexParameter( GLcontext *ctx, GLenum target,
2036 struct gl_texture_object *tObj,
2037 GLenum pname, const GLfloat *params )
2038 {
2039 savageTexObjPtr t = (savageTexObjPtr) tObj->DriverData;
2040 savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
2041
2042 if (!t || (target != GL_TEXTURE_1D && target != GL_TEXTURE_2D))
2043 return;
2044
2045 switch (pname) {
2046 case GL_TEXTURE_MIN_FILTER:
2047 case GL_TEXTURE_MAG_FILTER:
2048 savageSetTexFilter(t,tObj->MinFilter,tObj->MagFilter);
2049 break;
2050
2051 case GL_TEXTURE_WRAP_S:
2052 case GL_TEXTURE_WRAP_T:
2053 savageSetTexWrapping(t,tObj->WrapS,tObj->WrapT);
2054 break;
2055
2056 case GL_TEXTURE_BORDER_COLOR:
2057 savageSetTexBorderColor(t,tObj->_BorderChan);
2058 break;
2059
2060 default:
2061 return;
2062 }
2063
2064 imesa->new_state |= SAVAGE_NEW_TEXTURE;
2065 }
2066
2067 static void savageBindTexture( GLcontext *ctx, GLenum target,
2068 struct gl_texture_object *tObj )
2069 {
2070 savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
2071
2072 assert( (target != GL_TEXTURE_1D && target != GL_TEXTURE_2D) ||
2073 (tObj->DriverData != NULL) );
2074
2075 imesa->new_state |= SAVAGE_NEW_TEXTURE;
2076 }
2077
2078 static void savageDeleteTexture( GLcontext *ctx, struct gl_texture_object *tObj )
2079 {
2080 driTextureObject *t = (driTextureObject *)tObj->DriverData;
2081 savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
2082
2083 if (t) {
2084 if (t->bound)
2085 savageTimestampTextures(imesa);
2086
2087 driDestroyTextureObject(t);
2088 }
2089 /* Free mipmap images and the texture object itself */
2090 _mesa_delete_texture_object(ctx, tObj);
2091 }
2092
2093
2094 static struct gl_texture_object *
2095 savageNewTextureObject( GLcontext *ctx, GLuint name, GLenum target )
2096 {
2097 struct gl_texture_object *obj;
2098 obj = _mesa_new_texture_object(ctx, name, target);
2099 savageAllocTexObj( obj );
2100
2101 return obj;
2102 }
2103
2104 void savageDDInitTextureFuncs( struct dd_function_table *functions )
2105 {
2106 functions->TexEnv = savageTexEnv;
2107 functions->ChooseTextureFormat = savageChooseTextureFormat;
2108 functions->TexImage1D = savageTexImage1D;
2109 functions->TexSubImage1D = savageTexSubImage1D;
2110 functions->TexImage2D = savageTexImage2D;
2111 functions->TexSubImage2D = savageTexSubImage2D;
2112 functions->CompressedTexImage2D = savageCompressedTexImage2D;
2113 functions->CompressedTexSubImage2D = savageCompressedTexSubImage2D;
2114 functions->BindTexture = savageBindTexture;
2115 functions->NewTextureObject = savageNewTextureObject;
2116 functions->DeleteTexture = savageDeleteTexture;
2117 functions->IsTextureResident = driIsTextureResident;
2118 functions->TexParameter = savageTexParameter;
2119
2120 /* Texel fetching with our custom texture formats works just like
2121 * the standard argb formats. */
2122 _savage_texformat_a1114444.FetchTexel1D = _mesa_texformat_argb4444.FetchTexel1D;
2123 _savage_texformat_a1114444.FetchTexel2D = _mesa_texformat_argb4444.FetchTexel2D;
2124 _savage_texformat_a1114444.FetchTexel3D = _mesa_texformat_argb4444.FetchTexel3D;
2125 _savage_texformat_a1114444.FetchTexel1Df= _mesa_texformat_argb4444.FetchTexel1Df;
2126 _savage_texformat_a1114444.FetchTexel2Df= _mesa_texformat_argb4444.FetchTexel2Df;
2127 _savage_texformat_a1114444.FetchTexel3Df= _mesa_texformat_argb4444.FetchTexel3Df;
2128
2129 _savage_texformat_a1118888.FetchTexel1D = _mesa_texformat_argb8888.FetchTexel1D;
2130 _savage_texformat_a1118888.FetchTexel2D = _mesa_texformat_argb8888.FetchTexel2D;
2131 _savage_texformat_a1118888.FetchTexel3D = _mesa_texformat_argb8888.FetchTexel3D;
2132 _savage_texformat_a1118888.FetchTexel1Df= _mesa_texformat_argb8888.FetchTexel1Df;
2133 _savage_texformat_a1118888.FetchTexel2Df= _mesa_texformat_argb8888.FetchTexel2Df;
2134 _savage_texformat_a1118888.FetchTexel3Df= _mesa_texformat_argb8888.FetchTexel3Df;
2135 }