2 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
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:
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
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.
32 #include "savagecontext.h"
33 #include "savagetex.h"
34 #include "savagetris.h"
35 #include "savageioctl.h"
36 #include "simple_list.h"
38 #include "savage_bci.h"
41 #include "texformat.h"
48 #include "swrast/swrast.h"
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
58 /* On Savage4 the texure LOD-bias needs an offset of ~ 0.3 to get
59 * somewhere close to software rendering.
61 #define SAVAGE4_LOD_OFFSET 10
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. */
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.
74 * Yuck! 8-bit texture formats use 4x8 subtiles. See below.
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 */
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.
88 * second last subtile: 4 last subtile: 2
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 */
99 /** \brief Template for subtile uploads.
100 * \param h height in pixels
101 * \param w width in bytes
103 #define SUBTILE_FUNC(w,h) \
104 static __inline GLubyte *savageUploadSubtile_##w##x##h \
105 (GLubyte *dest, GLubyte *src, GLuint srcStride) \
108 for (y = 0; y < h; ++y) { \
109 memcpy (dest, src, w); \
116 SUBTILE_FUNC(2, 8) /* 4 bits per pixel, 4 pixels wide */
120 SUBTILE_FUNC(32, 8) /* 4 bytes per pixel, 8 pixels wide */
122 SUBTILE_FUNC(8, 2) /* DXT1 */
123 SUBTILE_FUNC(16, 2) /* DXT3 and DXT5 */
125 /** \brief Upload a complete tile from src (srcStride) to dest
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
135 * Writes linearly to the destination memory in order to exploit write
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
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
);
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;
161 for (sy
= 0; sy
< hInSub
; ++sy
) {
163 for (sx
= 0; sx
< wInSub
; ++sx
) {
165 dest
= subtileFunc (dest
, src
, srcStride
);
166 srcSTile
+= subStride
;
168 srcSRow
+= srcStride
* tileInfo
->subHeight
;
172 /** \brief Upload a image that is smaller than 8 pixels in either dimension.
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
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).
187 * FIXME: Repeating inside this function would be more efficient.
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
);
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
;
202 for (sx
= 0; sx
< wInSub
; ++sx
) {
204 for (y
= 0; y
< height
; ++y
) {
205 memcpy (dest
, src
, subStride
);
210 srcSTile
+= subStride
;
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;
220 for (y
= 0; y
< height
; ++y
) {
221 memcpy (dest
, src
, srcStride
);
224 if ((y
& skipRemainder
) == skipRemainder
)
227 } else { /* the last 3 mipmap levels */
228 GLuint offset
= (size
<= 2 ? tileInfo
->tinyOffset
[size
-1] : 0);
229 GLuint subStride
= tileInfo
->subWidth
* bpp
;
232 for (y
= 0; y
< height
; ++y
) {
233 memcpy (dest
, src
, bpp
*width
);
240 /** \brief Upload an image from mesa's internal copy.
242 static void savageUploadTexLevel( savageTexObjPtr t
, int level
)
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
;
250 /* FIXME: Need triangle (rather than pixel) fallbacks to simulate
251 * this using normal textured triangles.
253 * DO THIS IN DRIVER STATE MANAGMENT, not hardware state.
255 if(image
->Border
!= 0)
256 fprintf (stderr
, "Not supported texture border %d.\n",
257 (int) image
->Border
);
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;
268 if (pixWidth
>= 8 && pixHeight
>= 8) {
269 GLuint
*dirtyPtr
= t
->image
[level
].dirtyTiles
;
270 GLuint dirtyMask
= 1;
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
);
278 for (y
= 0; y
< hInTiles
; ++y
) {
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
);
286 src
+= tileInfo
->width
* bpp
;
287 dest
+= 2048; /* tile size is always 2k */
288 if (dirtyMask
== 1<<31) {
294 srcTRow
+= width
* tileInfo
->height
* bpp
;
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
;
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
308 if (bpp
== 4 && imesa
->savageScreen
->chipset
< S3_SAVAGE4
)
310 for (x
= 0; x
< wInTiles
; ++x
) {
311 if (*dirtyPtr
& dirtyMask
) {
312 savageUploadTile (tileInfo
,
314 height
/ tileInfo
->subHeight
,
315 bpp
, src
, width
* bpp
, dest
);
317 src
+= tileInfo
->width
* bpp
;
319 if (dirtyMask
== 1<<31) {
326 savageUploadTile (tileInfo
, width
/ tileInfo
->subWidth
,
327 height
/ tileInfo
->subHeight
, bpp
,
328 image
->Data
, width
* bpp
,
329 (GLubyte
*)(t
->bufAddr
+t
->image
[level
].offset
));
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;
337 minWidth
= minHeight
= 4;
338 if (width
> minWidth
|| height
> minHeight
) {
339 minWidth
= tileInfo
->subWidth
;
340 minHeight
= tileInfo
->subHeight
;
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
;
357 /** \brief Compute the destination size of a texture image
359 static GLuint
savageTexImageSize (GLuint width
, GLuint height
, GLuint bpp
) {
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)
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 */
371 return width
* 8 * bpp
;
372 else if (height
>= 8)
373 return 8 * height
* bpp
;
378 /** \brief Compute the destination size of a compressed texture image
380 static GLuint
savageCompressedTexImageSize (GLuint width
, GLuint height
,
382 width
= (width
+3) / 4;
383 height
= (height
+3) / 4;
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)
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 */
395 return width
* 2 * bpp
;
396 else if (height
>= 2)
397 return 2 * height
* bpp
;
402 /** \brief Compute the number of (partial) tiles of a texture image
404 static GLuint
savageTexImageTiles (GLuint width
, GLuint height
,
405 const savageTileInfo
*tileInfo
)
407 return (width
+ tileInfo
->width
- 1) / tileInfo
->width
*
408 (height
+ tileInfo
->height
- 1) / tileInfo
->height
;
411 /** \brief Mark dirty tiles
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.
418 static void savageMarkDirtyTiles (savageTexObjPtr t
, GLuint level
,
419 GLuint totalWidth
, GLuint totalHeight
,
420 GLint xoffset
, GLint yoffset
,
421 GLsizei width
, GLsizei height
)
423 GLuint wInTiles
, hInTiles
;
424 GLuint x0
, y0
, x1
, y1
;
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
)
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
;
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
) {
443 if (mask
== (1<<31)) {
453 /** \brief Mark all tiles as dirty
455 static void savageMarkAllTiles (savageTexObjPtr t
, GLuint level
)
457 GLuint words
= (t
->image
[level
].nTiles
+ 31) / 32;
459 memset(t
->image
[level
].dirtyTiles
, ~0, words
*sizeof(GLuint
));
463 static void savageSetTexWrapping(savageTexObjPtr tex
, GLenum s
, GLenum t
)
465 tex
->setup
.sWrapMode
= s
;
466 tex
->setup
.tWrapMode
= t
;
469 static void savageSetTexFilter(savageTexObjPtr t
, GLenum minf
, GLenum magf
)
471 t
->setup
.minFilter
= minf
;
472 t
->setup
.magFilter
= magf
;
478 static void savageSetTexBorderColor(savageTexObjPtr t
, GLubyte color
[4])
480 /* t->Setup[SAVAGE_TEXREG_TEXBORDERCOL] = */
481 /*t->setup.borderColor = SAVAGEPACKCOLOR8888(color[0],color[1],color[2],color[3]); */
486 static savageTexObjPtr
487 savageAllocTexObj( struct gl_texture_object
*texObj
)
491 t
= (savageTexObjPtr
) calloc(1,sizeof(*t
));
492 texObj
->DriverData
= t
;
496 /* Initialize non-image-dependent parts of the state:
498 t
->base
.tObj
= texObj
;
499 t
->base
.dirty_images
[0] = 0;
500 t
->dirtySubImages
= 0;
503 /* Initialize dirty tiles bit vectors
505 for (i
= 0; i
< SAVAGE_TEX_MAXLEVELS
; ++i
)
506 t
->image
[i
].nTiles
= 0;
508 /* FIXME Something here to set initial values for other parts of
512 make_empty_list( &t
->base
);
514 savageSetTexWrapping(t
,texObj
->WrapS
,texObj
->WrapT
);
515 savageSetTexFilter(t
,texObj
->MinFilter
,texObj
->MagFilter
);
516 savageSetTexBorderColor(t
,texObj
->_BorderChan
);
522 /* Mesa texture formats for alpha-images on Savage3D/IX/MX
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. */
530 _savage_texstore_a1114444 (GLcontext
*ctx
, GLuint dims
,
531 GLenum baseInternalFormat
,
532 const struct gl_texture_format
*dstFormat
,
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
);
541 _savage_texstore_a1118888 (GLcontext
*ctx
, GLuint dims
,
542 GLenum baseInternalFormat
,
543 const struct gl_texture_format
*dstFormat
,
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
);
552 static struct gl_texture_format _savage_texformat_a1114444
= {
553 MESA_FORMAT_ARGB4444
, /* MesaFormat */
554 GL_RGBA
, /* BaseFormat */
555 GL_UNSIGNED_NORMALIZED_ARB
, /* DataType */
560 0, /* LuminanceBits */
561 0, /* IntensityBits */
566 _savage_texstore_a1114444
, /* StoreTexImageFunc */
567 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
/* FetchTexel* filled in by
568 * savageDDInitTextureFuncs */
570 static struct gl_texture_format _savage_texformat_a1118888
= {
571 MESA_FORMAT_ARGB8888
, /* MesaFormat */
572 GL_RGBA
, /* BaseFormat */
573 GL_UNSIGNED_NORMALIZED_ARB
, /* DataType */
578 0, /* LuminanceBits */
579 0, /* IntensityBits */
584 _savage_texstore_a1118888
, /* StoreTexImageFunc */
585 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
/* FetchTexel* filled in by
586 * savageDDInitTextureFuncs */
590 _savage_texstore_a1114444 (GLcontext
*ctx
, GLuint dims
,
591 GLenum baseInternalFormat
,
592 const struct gl_texture_format
*dstFormat
,
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
)
602 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
605 srcWidth
, srcHeight
, srcDepth
,
606 srcFormat
, srcType
, srcAddr
,
608 const GLchan
*src
= tempImage
;
609 GLubyte
*dstImage
= (GLubyte
*) dstAddr
610 + dstZoffset
* dstImageStride
611 + dstYoffset
* dstRowStride
612 + dstXoffset
* dstFormat
->TexelBytes
;
615 ASSERT(dstFormat
== &_savage_texformat_a1114444
);
616 ASSERT(baseInternalFormat
== GL_ALPHA
);
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]),
630 dstRow
+= dstRowStride
;
632 dstImage
+= dstImageStride
;
634 _mesa_free((void *) tempImage
);
639 _savage_texstore_a1118888 (GLcontext
*ctx
, GLuint dims
,
640 GLenum baseInternalFormat
,
641 const struct gl_texture_format
*dstFormat
,
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
)
651 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
654 srcWidth
, srcHeight
, srcDepth
,
655 srcFormat
, srcType
, srcAddr
,
657 const GLchan
*src
= tempImage
;
658 GLubyte
*dstImage
= (GLubyte
*) dstAddr
659 + dstZoffset
* dstImageStride
660 + dstYoffset
* dstRowStride
661 + dstXoffset
* dstFormat
->TexelBytes
;
664 ASSERT(dstFormat
== &_savage_texformat_a1118888
);
665 ASSERT(baseInternalFormat
== GL_ALPHA
);
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]),
679 dstRow
+= dstRowStride
;
681 dstImage
+= dstImageStride
;
683 _mesa_free((void *) tempImage
);
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
)
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
);
701 switch ( internalFormat
) {
704 case GL_COMPRESSED_RGBA
:
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
;
716 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
;
721 case GL_COMPRESSED_RGB
:
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
;
733 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_rgb565
;
740 &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
;
744 &_mesa_texformat_argb8888
: &_mesa_texformat_argb1555
;
748 return &_mesa_texformat_argb4444
;
751 return &_mesa_texformat_argb1555
;
757 return !force16bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_rgb565
;
762 return &_mesa_texformat_rgb565
;
765 case GL_COMPRESSED_ALPHA
:
766 return isSavage4
? &_mesa_texformat_a8
: (
767 do32bpt
? &_savage_texformat_a1118888
: &_savage_texformat_a1114444
);
769 return isSavage4
? &_mesa_texformat_a8
: &_savage_texformat_a1114444
;
773 return isSavage4
? &_mesa_texformat_a8
: (
774 !force16bpt
? &_savage_texformat_a1118888
: &_savage_texformat_a1114444
);
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
);
783 return isSavage4
? &_mesa_texformat_l8
: &_mesa_texformat_argb1555
;
787 return isSavage4
? &_mesa_texformat_l8
: (
788 !force16bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb1555
);
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
;
804 /* TFT_I8 produces garbage on ProSavageDDR and subsequent texture
805 * disable keeps rendering garbage. Disabled for now. */
807 case GL_COMPRESSED_INTENSITY
:
808 return isSavage4
? &_mesa_texformat_i8
: (
809 do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
);
811 return isSavage4
? &_mesa_texformat_i8
: &_mesa_texformat_argb4444
;
815 return isSavage4
? &_mesa_texformat_i8
: (
816 !force16bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
);
819 case GL_COMPRESSED_INTENSITY
:
820 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
;
822 return &_mesa_texformat_argb4444
;
826 return !force16bpt
? &_mesa_texformat_argb8888
:
827 &_mesa_texformat_argb4444
;
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
;
837 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
838 return &_mesa_texformat_rgba_dxt3
;
843 /* Not the best choice but Savage3D/MX/IX don't support DXT3 or DXT5. */
844 return &_mesa_texformat_rgba_dxt1
;
846 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
847 return &_mesa_texformat_rgba_dxt5
;
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;
860 _mesa_problem(ctx
, "unexpected texture format in %s", __FUNCTION__
);
865 static void savageSetTexImages( savageContextPtr imesa
,
866 const struct gl_texture_object
*tObj
)
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
;
876 switch (image
->TexFormat
->MesaFormat
) {
877 case MESA_FORMAT_ARGB8888
:
878 textureFormat
= TFT_ARGB8888
;
879 t
->texelBytes
= tileIndex
= 4;
881 case MESA_FORMAT_ARGB1555
:
882 textureFormat
= TFT_ARGB1555
;
883 t
->texelBytes
= tileIndex
= 2;
885 case MESA_FORMAT_ARGB4444
:
886 textureFormat
= TFT_ARGB4444
;
887 t
->texelBytes
= tileIndex
= 2;
889 case MESA_FORMAT_RGB565
:
890 textureFormat
= TFT_RGB565
;
891 t
->texelBytes
= tileIndex
= 2;
894 textureFormat
= TFT_L8
;
895 t
->texelBytes
= tileIndex
= 1;
898 textureFormat
= TFT_I8
;
899 t
->texelBytes
= tileIndex
= 1;
902 textureFormat
= TFT_A8
;
903 t
->texelBytes
= tileIndex
= 1;
905 case MESA_FORMAT_RGB_DXT1
:
906 textureFormat
= TFT_S3TC4Bit
;
907 tileIndex
= TILE_INDEX_DXT1
;
910 case MESA_FORMAT_RGBA_DXT1
:
911 textureFormat
= TFT_S3TC4Bit
;
912 tileIndex
= TILE_INDEX_DXT1
;
915 case MESA_FORMAT_RGBA_DXT3
:
916 textureFormat
= TFT_S3TC4A4Bit
;
917 tileIndex
= TILE_INDEX_DXTn
;
920 case MESA_FORMAT_RGBA_DXT5
:
921 textureFormat
= TFT_S3TC4CA4Bit
;
922 tileIndex
= TILE_INDEX_DXTn
;
926 _mesa_problem(imesa
->glCtx
, "Bad texture format in %s", __FUNCTION__
);
929 t
->hwFormat
= textureFormat
;
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
];
935 t
->tileInfo
= &tileInfo_pro
[tileIndex
];
937 /* Compute which mipmap levels we really want to send to the hardware.
939 driCalculateTextureFirstLastLevel( &t
->base
);
940 firstLevel
= t
->base
.firstLevel
;
941 lastLevel
= t
->base
.lastLevel
;
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.
951 for ( i
= firstLevel
; i
<= lastLevel
&& tObj
->Image
[0][i
] ; i
++ ) {
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
);
959 t
->image
[i
].dirtyTiles
= malloc(words
*sizeof(GLuint
));
960 memset(t
->image
[i
].dirtyTiles
, ~0, words
*sizeof(GLuint
));
962 t
->image
[i
].nTiles
= nTiles
;
964 t
->image
[i
].offset
= offset
;
966 image
= tObj
->Image
[0][i
];
967 if (t
->texelBytes
>= 8)
968 size
= savageCompressedTexImageSize (image
->Width2
, image
->Height2
,
971 size
= savageTexImageSize (image
->Width2
, image
->Height2
,
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
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;
986 void savageDestroyTexObj(savageContextPtr imesa
, savageTexObjPtr t
)
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
);
996 /* See if it was the driver's current object.
1000 for ( i
= 0 ; i
< imesa
->glCtx
->Const
.MaxTextureUnits
; i
++ )
1002 if ( &t
->base
== imesa
->CurrentTexObj
[ i
] ) {
1003 assert( t
->base
.bound
& (1 << i
) );
1004 imesa
->CurrentTexObj
[ i
] = NULL
;
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
1014 static void savageUploadTexImages( savageContextPtr imesa
, savageTexObjPtr t
)
1016 const GLint numLevels
= t
->base
.lastLevel
- t
->base
.firstLevel
+ 1;
1021 LOCK_HARDWARE(imesa
);
1023 /* Do we need to eject LRU texture objects?
1025 if (!t
->base
.memBlock
) {
1029 heap
= driAllocateTexture(imesa
->textureHeaps
, imesa
->lastTexHeap
,
1030 (driTextureObject
*)t
);
1032 UNLOCK_HARDWARE(imesa
);
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? */
1042 /* Let the world know we've used this memory recently.
1044 driUpdateTextureLRU( &t
->base
);
1045 UNLOCK_HARDWARE(imesa
);
1047 if (t
->base
.dirty_images
[0] || t
->dirtySubImages
) {
1048 if (SAVAGE_DEBUG
& DEBUG_VERBOSE_TEX
)
1049 fprintf(stderr
, "Texture upload: |");
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
);
1059 savageFlushVertices (imesa
);
1060 LOCK_HARDWARE(imesa
);
1061 savageFlushCmdBufLocked (imesa
, GL_FALSE
);
1062 WAIT_IDLE_EMPTY_LOCKED(imesa
);
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
, ".");
1075 fprintf (stderr
, " ");
1077 if ((t
->base
.dirty_images
[0] | t
->dirtySubImages
) & (1 << j
))
1078 savageUploadTexLevel( t
, j
);
1081 UNLOCK_HARDWARE(imesa
);
1082 t
->base
.dirty_images
[0] = 0;
1083 t
->dirtySubImages
= 0;
1085 if (SAVAGE_DEBUG
& DEBUG_VERBOSE_TEX
)
1086 fprintf(stderr
, "|\n");
1092 savage4_set_wrap_mode( savageContextPtr imesa
, unsigned unit
,
1093 GLenum s_mode
, GLenum t_mode
)
1097 imesa
->regs
.s4
.texCtrl
[ unit
].ni
.uMode
= TAM_Wrap
;
1100 case GL_CLAMP_TO_EDGE
:
1101 imesa
->regs
.s4
.texCtrl
[ unit
].ni
.uMode
= TAM_Clamp
;
1103 case GL_MIRRORED_REPEAT
:
1104 imesa
->regs
.s4
.texCtrl
[ unit
].ni
.uMode
= TAM_Mirror
;
1110 imesa
->regs
.s4
.texCtrl
[ unit
].ni
.vMode
= TAM_Wrap
;
1113 case GL_CLAMP_TO_EDGE
:
1114 imesa
->regs
.s4
.texCtrl
[ unit
].ni
.vMode
= TAM_Clamp
;
1116 case GL_MIRRORED_REPEAT
:
1117 imesa
->regs
.s4
.texCtrl
[ unit
].ni
.vMode
= TAM_Mirror
;
1124 * Sets the hardware bits for the specified GL texture filter modes.
1127 * Does the Savage4 have the ability to select the magnification filter?
1130 savage4_set_filter_mode( savageContextPtr imesa
, unsigned unit
,
1131 GLenum minFilter
, GLenum magFilter
)
1135 switch (minFilter
) {
1137 imesa
->regs
.s4
.texCtrl
[ unit
].ni
.filterMode
= TFM_Point
;
1138 imesa
->regs
.s4
.texCtrl
[ unit
].ni
.mipmapEnable
= GL_FALSE
;
1142 imesa
->regs
.s4
.texCtrl
[ unit
].ni
.filterMode
= TFM_Bilin
;
1143 imesa
->regs
.s4
.texCtrl
[ unit
].ni
.mipmapEnable
= GL_FALSE
;
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
;
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
;
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
;
1165 static void savageUpdateTex0State_s4( GLcontext
*ctx
)
1167 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
1168 struct gl_texture_object
*tObj
;
1169 struct gl_texture_image
*image
;
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)
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
);
1188 /* Do 2D texture setup */
1190 t
= tObj
->DriverData
;
1192 t
= savageAllocTexObj( tObj
);
1197 imesa
->CurrentTexObj
[0] = &t
->base
;
1200 if (t
->base
.dirty_images
[0] || t
->dirtySubImages
) {
1201 savageSetTexImages(imesa
, tObj
);
1202 savageUploadTexImages(imesa
, t
);
1205 driUpdateTextureLRU( &t
->base
);
1207 format
= tObj
->Image
[0][tObj
->BaseLevel
]->_BaseFormat
;
1209 switch (ctx
->Texture
.Unit
[0].EnvMode
) {
1211 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_FALSE
;
1216 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_Decal
;
1219 case GL_LUMINANCE_ALPHA
:
1222 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_Copy
;
1226 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_CopyAlpha
;
1229 __HWEnvCombineSingleUnitScale(imesa
, 0, 0,
1230 &imesa
->regs
.s4
.texBlendCtrl
[0]);
1234 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_FALSE
;
1239 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_Decal
;
1244 case GL_LUMINANCE_ALPHA
:
1245 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_DecalAlpha
;
1249 GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_INTENSITY
1250 are undefined with GL_DECAL
1254 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_CopyAlpha
;
1257 __HWEnvCombineSingleUnitScale(imesa
, 0, 0,
1258 &imesa
->regs
.s4
.texBlendCtrl
[0]);
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]);
1269 imesa
->regs
.s4
.texBlendColor
.ui
= imesa
->texEnvColor
;
1274 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_ModulAlpha
;
1275 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_FALSE
;
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
;
1290 imesa
->regs
.s4
.texAddr
[1].ui
= imesa
->regs
.s4
.texAddr
[0].ui
;
1291 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_Blend1
;
1293 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_TRUE
;
1294 imesa
->bTexEn1
= GL_TRUE
;
1297 case GL_LUMINANCE_ALPHA
:
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
;
1309 imesa
->regs
.s4
.texAddr
[1].ui
= imesa
->regs
.s4
.texAddr
[0].ui
;
1310 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_BlendAlpha1
;
1312 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_TRUE
;
1313 imesa
->bTexEn1
= GL_TRUE
;
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
;
1327 imesa
->regs
.s4
.texAddr
[1].ui
= imesa
->regs
.s4
.texAddr
[0].ui
;
1328 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_BlendInt1
;
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
;
1335 __HWEnvCombineSingleUnitScale(imesa
, 0, 0,
1336 &imesa
->regs
.s4
.texBlendCtrl
[0]);
1340 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_FALSE
;
1344 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_ModulAlpha
;
1349 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_Add
;
1352 case GL_LUMINANCE_ALPHA
:
1354 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_Add
;
1358 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_AddAlpha
;
1361 __HWEnvCombineSingleUnitScale(imesa
, 0, 0,
1362 &imesa
->regs
.s4
.texBlendCtrl
[0]);
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]);
1373 fprintf(stderr
, "unknown tex env mode");
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
);
1381 if((ctx
->Texture
.Unit
[0].LodBias
!=0.0F
) ||
1382 (imesa
->regs
.s4
.texCtrl
[0].ni
.dBias
!= 0))
1384 int bias
= (int)(ctx
->Texture
.Unit
[0].LodBias
* 32.0) +
1388 else if (bias
> 255)
1390 imesa
->regs
.s4
.texCtrl
[0].ni
.dBias
= bias
& 0x1ff;
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
;
1400 if (imesa
->regs
.s4
.texDescr
.ni
.tex1En
)
1401 imesa
->regs
.s4
.texDescr
.ni
.texBLoopEn
= GL_TRUE
;
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;
1409 static void savageUpdateTex1State_s4( GLcontext
*ctx
)
1411 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
1412 struct gl_texture_object
*tObj
;
1413 struct gl_texture_image
*image
;
1420 imesa
->bTexEn1
= GL_FALSE
;
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)
1431 tObj
= ctx
->Texture
.Unit
[1]._Current
;
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
);
1440 /* Do 2D texture setup */
1442 t
= tObj
->DriverData
;
1444 t
= savageAllocTexObj( tObj
);
1449 imesa
->CurrentTexObj
[1] = &t
->base
;
1453 if (t
->base
.dirty_images
[0] || t
->dirtySubImages
) {
1454 savageSetTexImages(imesa
, tObj
);
1455 savageUploadTexImages(imesa
, t
);
1458 driUpdateTextureLRU( &t
->base
);
1460 format
= tObj
->Image
[0][tObj
->BaseLevel
]->_BaseFormat
;
1462 switch (ctx
->Texture
.Unit
[1].EnvMode
) {
1464 imesa
->regs
.s4
.texCtrl
[1].ni
.clrArg1Invert
= GL_FALSE
;
1469 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_Decal
;
1472 case GL_LUMINANCE_ALPHA
:
1475 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_Copy
;
1479 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_CopyAlpha1
;
1482 __HWEnvCombineSingleUnitScale(imesa
, 0, 1, &imesa
->regs
.s4
.texBlendCtrl
);
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
);
1491 imesa
->regs
.s4
.texCtrl
[1].ni
.clrArg1Invert
= GL_FALSE
;
1495 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_ModulAlpha1
;
1500 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_Add1
;
1503 case GL_LUMINANCE_ALPHA
:
1505 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_Add1
;
1509 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_AddAlpha1
;
1512 __HWEnvCombineSingleUnitScale(imesa
, 0, 1, &imesa
->regs
.s4
.texBlendCtrl
);
1515 #if GL_ARB_texture_env_combine
1516 case GL_COMBINE_ARB
:
1517 __HWParseTexEnvCombine(imesa
, 1, &texCtrl
, &imesa
->regs
.s4
.texBlendCtrl
);
1522 imesa
->regs
.s4
.texCtrl
[1].ni
.clrArg1Invert
= GL_FALSE
;
1528 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_Decal1
;
1530 case GL_LUMINANCE_ALPHA
:
1533 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_DecalAlpha1
;
1537 // GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_INTENSITY
1538 // are undefined with GL_DECAL
1541 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_CopyAlpha1
;
1544 __HWEnvCombineSingleUnitScale(imesa
, 0, 1, &imesa
->regs
.s4
.texBlendCtrl
);
1548 if (format
== GL_LUMINANCE
)
1551 // This is a hack for GLQuake, invert.
1553 imesa
->regs
.s4
.texCtrl
[1].ni
.clrArg1Invert
= GL_TRUE
;
1554 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= 0;
1556 __HWEnvCombineSingleUnitScale(imesa
, 0, 1, &imesa
->regs
.s4
.texBlendCtrl
);
1560 fprintf(stderr
, "unknown tex 1 env mode\n");
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
);
1568 if((ctx
->Texture
.Unit
[1].LodBias
!=0.0F
) ||
1569 (imesa
->regs
.s4
.texCtrl
[1].ni
.dBias
!= 0))
1571 int bias
= (int)(ctx
->Texture
.Unit
[1].LodBias
* 32.0) +
1575 else if (bias
> 255)
1577 imesa
->regs
.s4
.texCtrl
[1].ni
.dBias
= bias
& 0x1ff;
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
;
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;
1592 static void savageUpdateTexState_s3d( GLcontext
*ctx
)
1594 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
1595 struct gl_texture_object
*tObj
;
1596 struct gl_texture_image
*image
;
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)
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
);
1616 /* Do 2D texture setup */
1617 t
= tObj
->DriverData
;
1619 t
= savageAllocTexObj( tObj
);
1624 imesa
->CurrentTexObj
[0] = &t
->base
;
1627 if (t
->base
.dirty_images
[0] || t
->dirtySubImages
) {
1628 savageSetTexImages(imesa
, tObj
);
1629 savageUploadTexImages(imesa
, t
);
1632 driUpdateTextureLRU( &t
->base
);
1634 format
= tObj
->Image
[0][tObj
->BaseLevel
]->_BaseFormat
;
1636 /* FIXME: copied from utah-glx, probably needs some tuning */
1637 switch (ctx
->Texture
.Unit
[0].EnvMode
) {
1639 imesa
->regs
.s3d
.drawCtrl
.ni
.texBlendCtrl
= SAVAGETBC_DECALALPHA_S3D
;
1643 case GL_ALPHA
: /* FIXME */
1644 imesa
->regs
.s3d
.drawCtrl
.ni
.texBlendCtrl
= 1;
1646 case GL_LUMINANCE_ALPHA
:
1648 imesa
->regs
.s3d
.drawCtrl
.ni
.texBlendCtrl
= 4;
1652 imesa
->regs
.s3d
.drawCtrl
.ni
.texBlendCtrl
= SAVAGETBC_DECAL_S3D
;
1655 imesa
->regs
.s3d
.drawCtrl
.ni
.texBlendCtrl
= SAVAGETBC_COPY_S3D
;
1658 case GL_BLEND
: /* hardware can't do GL_BLEND */
1659 FALLBACK (ctx
, SAVAGE_FALLBACK_TEXTURE
, GL_TRUE
);
1662 imesa
->regs
.s3d
.drawCtrl
.ni
.texBlendCtrl
= SAVAGETBC_MODULATEALPHA_S3D
;
1665 fprintf(stderr
, "unknown tex env mode\n");
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
);
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
;
1681 switch (t
->setup
.minFilter
) {
1683 imesa
->regs
.s3d
.texCtrl
.ni
.filterMode
= TFM_Point
;
1684 imesa
->regs
.s3d
.texCtrl
.ni
.mipmapDisable
= GL_TRUE
;
1688 imesa
->regs
.s3d
.texCtrl
.ni
.filterMode
= TFM_Bilin
;
1689 imesa
->regs
.s3d
.texCtrl
.ni
.mipmapDisable
= GL_TRUE
;
1692 case GL_NEAREST_MIPMAP_NEAREST
:
1693 imesa
->regs
.s3d
.texCtrl
.ni
.filterMode
= TFM_Point
;
1694 imesa
->regs
.s3d
.texCtrl
.ni
.mipmapDisable
= GL_FALSE
;
1697 case GL_LINEAR_MIPMAP_NEAREST
:
1698 imesa
->regs
.s3d
.texCtrl
.ni
.filterMode
= TFM_Bilin
;
1699 imesa
->regs
.s3d
.texCtrl
.ni
.mipmapDisable
= GL_FALSE
;
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
;
1709 /* There is no way to specify a maximum mipmap level. We may have to
1710 disable mipmapping completely. */
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;
1721 if((ctx
->Texture
.Unit
[0].LodBias
!=0.0F
) ||
1722 (imesa
->regs
.s3d
.texCtrl
.ni
.dBias
!= 0))
1724 int bias
= (int)(ctx
->Texture
.Unit
[0].LodBias
* 16.0);
1727 else if (bias
> 255)
1729 imesa
->regs
.s3d
.texCtrl
.ni
.dBias
= bias
& 0x1ff;
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
;
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;
1745 static void savageTimestampTextures( savageContextPtr imesa
)
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) {
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
;
1763 static void savageUpdateTextureState_s4( GLcontext
*ctx
)
1765 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
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.
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
);
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
);
1788 static void savageUpdateTextureState_s3d( GLcontext
*ctx
)
1790 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
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.
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
);
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
);
1806 void savageUpdateTextureState( GLcontext
*ctx
)
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
);
1814 savageUpdateTextureState_s3d (ctx
);
1819 /*****************************************
1821 *****************************************/
1823 static void savageTexEnv( GLcontext
*ctx
, GLenum target
,
1824 GLenum pname
, const GLfloat
*param
)
1826 savageContextPtr imesa
= SAVAGE_CONTEXT( ctx
);
1828 if (pname
== GL_TEXTURE_ENV_MODE
) {
1830 imesa
->new_state
|= SAVAGE_NEW_TEXTURE
;
1832 } else if (pname
== GL_TEXTURE_ENV_COLOR
) {
1834 struct gl_texture_unit
*texUnit
=
1835 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1836 const GLfloat
*fc
= texUnit
->EnvColor
;
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]);
1843 imesa
->texEnvColor
= ((a
<< 24) | (r
<< 16) |
1844 (g
<< 8) | (b
<< 0));
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
1854 static void savageTexImageChanged (savageTexObjPtr t
) {
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
;
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
)
1872 savageTexObjPtr t
= (savageTexObjPtr
) texObj
->DriverData
;
1874 savageTexImageChanged (t
);
1876 t
= savageAllocTexObj(texObj
);
1878 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
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
;
1889 static void savageTexSubImage1D( GLcontext
*ctx
,
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
)
1900 savageTexObjPtr t
= (savageTexObjPtr
) texObj
->DriverData
;
1901 assert( t
); /* this _should_ be true */
1903 savageTexImageChanged (t
);
1904 savageMarkDirtyTiles(t
, level
, texImage
->Width2
, 1,
1905 xoffset
, 0, width
, 1);
1907 t
= savageAllocTexObj(texObj
);
1909 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
1912 t
->base
.dirty_images
[0] |= (1 << level
);
1914 _mesa_store_texsubimage1d(ctx
, target
, level
, xoffset
, width
,
1915 format
, type
, pixels
, packing
, texObj
,
1917 t
->dirtySubImages
|= (1 << level
);
1918 SAVAGE_CONTEXT(ctx
)->new_state
|= SAVAGE_NEW_TEXTURE
;
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
)
1929 savageTexObjPtr t
= (savageTexObjPtr
) texObj
->DriverData
;
1931 savageTexImageChanged (t
);
1933 t
= savageAllocTexObj(texObj
);
1935 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
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
;
1946 static void savageTexSubImage2D( GLcontext
*ctx
,
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
)
1957 savageTexObjPtr t
= (savageTexObjPtr
) texObj
->DriverData
;
1958 assert( t
); /* this _should_ be true */
1960 savageTexImageChanged (t
);
1961 savageMarkDirtyTiles(t
, level
, texImage
->Width2
, texImage
->Height2
,
1962 xoffset
, yoffset
, width
, height
);
1964 t
= savageAllocTexObj(texObj
);
1966 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
1969 t
->base
.dirty_images
[0] |= (1 << level
);
1971 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
1972 height
, format
, type
, pixels
, packing
, texObj
,
1974 t
->dirtySubImages
|= (1 << level
);
1975 SAVAGE_CONTEXT(ctx
)->new_state
|= SAVAGE_NEW_TEXTURE
;
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
)
1986 savageTexObjPtr t
= (savageTexObjPtr
) texObj
->DriverData
;
1988 savageTexImageChanged (t
);
1990 t
= savageAllocTexObj(texObj
);
1992 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2D");
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
;
2004 savageCompressedTexSubImage2D( GLcontext
*ctx
,
2007 GLint xoffset
, GLint yoffset
,
2008 GLsizei width
, GLsizei height
,
2009 GLenum format
, GLsizei imageSize
,
2011 struct gl_texture_object
*texObj
,
2012 struct gl_texture_image
*texImage
)
2014 savageTexObjPtr t
= (savageTexObjPtr
) texObj
->DriverData
;
2015 assert( t
); /* this _should_ be true */
2017 savageTexImageChanged (t
);
2018 savageMarkDirtyTiles(t
, level
, texImage
->Width2
, texImage
->Height2
,
2019 xoffset
, yoffset
, width
, height
);
2021 t
= savageAllocTexObj(texObj
);
2023 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
2026 t
->base
.dirty_images
[0] |= (1 << level
);
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
;
2035 static void savageTexParameter( GLcontext
*ctx
, GLenum target
,
2036 struct gl_texture_object
*tObj
,
2037 GLenum pname
, const GLfloat
*params
)
2039 savageTexObjPtr t
= (savageTexObjPtr
) tObj
->DriverData
;
2040 savageContextPtr imesa
= SAVAGE_CONTEXT( ctx
);
2042 if (!t
|| (target
!= GL_TEXTURE_1D
&& target
!= GL_TEXTURE_2D
))
2046 case GL_TEXTURE_MIN_FILTER
:
2047 case GL_TEXTURE_MAG_FILTER
:
2048 savageSetTexFilter(t
,tObj
->MinFilter
,tObj
->MagFilter
);
2051 case GL_TEXTURE_WRAP_S
:
2052 case GL_TEXTURE_WRAP_T
:
2053 savageSetTexWrapping(t
,tObj
->WrapS
,tObj
->WrapT
);
2056 case GL_TEXTURE_BORDER_COLOR
:
2057 savageSetTexBorderColor(t
,tObj
->_BorderChan
);
2064 imesa
->new_state
|= SAVAGE_NEW_TEXTURE
;
2067 static void savageBindTexture( GLcontext
*ctx
, GLenum target
,
2068 struct gl_texture_object
*tObj
)
2070 savageContextPtr imesa
= SAVAGE_CONTEXT( ctx
);
2072 assert( (target
!= GL_TEXTURE_1D
&& target
!= GL_TEXTURE_2D
) ||
2073 (tObj
->DriverData
!= NULL
) );
2075 imesa
->new_state
|= SAVAGE_NEW_TEXTURE
;
2078 static void savageDeleteTexture( GLcontext
*ctx
, struct gl_texture_object
*tObj
)
2080 driTextureObject
*t
= (driTextureObject
*)tObj
->DriverData
;
2081 savageContextPtr imesa
= SAVAGE_CONTEXT( ctx
);
2085 savageTimestampTextures(imesa
);
2087 driDestroyTextureObject(t
);
2089 /* Free mipmap images and the texture object itself */
2090 _mesa_delete_texture_object(ctx
, tObj
);
2094 static struct gl_texture_object
*
2095 savageNewTextureObject( GLcontext
*ctx
, GLuint name
, GLenum target
)
2097 struct gl_texture_object
*obj
;
2098 obj
= _mesa_new_texture_object(ctx
, name
, target
);
2099 savageAllocTexObj( obj
);
2104 void savageDDInitTextureFuncs( struct dd_function_table
*functions
)
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
;
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
;
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
;