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.
26 #include "main/context.h"
28 #include "main/macros.h"
29 #include "main/texstore.h"
30 #include "main/texobj.h"
31 #include "main/colormac.h"
32 #include "main/simple_list.h"
33 #include "main/enums.h"
35 #include "savagecontext.h"
36 #include "savagetex.h"
37 #include "savagetris.h"
38 #include "savageioctl.h"
39 #include "savage_bci.h"
43 #define TILE_INDEX_DXT1 0
44 #define TILE_INDEX_8 1
45 #define TILE_INDEX_16 2
46 #define TILE_INDEX_DXTn 3
47 #define TILE_INDEX_32 4
49 /* On Savage4 the texure LOD-bias needs an offset of ~ 0.3 to get
50 * somewhere close to software rendering.
52 #define SAVAGE4_LOD_OFFSET 10
54 /* Tile info for S3TC formats counts in 4x4 blocks instead of texels.
55 * In DXT1 each block is encoded in 64 bits. In DXT3 and 5 each block is
56 * encoded in 128 bits. */
58 /* Size 1, 2 and 4 images are packed into the last subtile. Each image
59 * is repeated to fill a 4x4 pixel area. The figure below shows the
60 * layout of those 4x4 pixel areas in the 8x8 subtile.
65 * Yuck! 8-bit texture formats use 4x8 subtiles. See below.
67 static const savageTileInfo tileInfo_pro
[5] = {
68 {16, 16, 16, 8, 1, 2, {0x18, 0x10}}, /* DXT1 */
69 {64, 32, 16, 4, 4, 8, {0x30, 0x20}}, /* 8-bit */
70 {64, 16, 8, 2, 8, 8, {0x48, 0x08}}, /* 16-bit */
71 {16, 8, 16, 4, 1, 2, {0x30, 0x20}}, /* DXT3, DXT5 */
72 {32, 16, 4, 2, 8, 8, {0x90, 0x10}}, /* 32-bit */
75 /* Size 1, 2 and 4 images are packed into the last two subtiles. Each
76 * image is repeated to fill a 4x4 pixel area. The figures below show
77 * the layout of those 4x4 pixel areas in the two 4x8 subtiles.
79 * second last subtile: 4 last subtile: 2
82 static const savageTileInfo tileInfo_s3d_s4
[5] = {
83 {16, 16, 16, 8, 1, 2, {0x18, 0x10}}, /* DXT1 */
84 {64, 32, 16, 4, 4, 8, {0x30, 0x20}}, /* 8-bit */
85 {64, 16, 16, 2, 4, 8, {0x60, 0x40}}, /* 16-bit */
86 {16, 8, 16, 4, 1, 2, {0x30, 0x20}}, /* DXT3, DXT5 */
87 {32, 16, 8, 2, 4, 8, {0xc0, 0x80}}, /* 32-bit */
90 /** \brief Template for subtile uploads.
91 * \param h height in pixels
92 * \param w width in bytes
94 #define SUBTILE_FUNC(w,h) \
95 static INLINE GLubyte *savageUploadSubtile_##w##x##h \
96 (GLubyte *dest, GLubyte *src, GLuint srcStride) \
99 for (y = 0; y < h; ++y) { \
100 memcpy (dest, src, w); \
107 SUBTILE_FUNC(2, 8) /* 4 bits per pixel, 4 pixels wide */
111 SUBTILE_FUNC(32, 8) /* 4 bytes per pixel, 8 pixels wide */
113 SUBTILE_FUNC(8, 2) /* DXT1 */
114 SUBTILE_FUNC(16, 2) /* DXT3 and DXT5 */
116 /** \brief Upload a complete tile from src (srcStride) to dest
118 * \param tileInfo Pointer to tiling information
119 * \param wInSub Width of source/dest image in subtiles
120 * \param hInSub Height of source/dest image in subtiles
121 * \param bpp Bytes per pixel
122 * \param src Pointer to source data
123 * \param srcStride Byte stride of rows in the source data
124 * \param dest Pointer to destination
126 * Writes linearly to the destination memory in order to exploit write
129 * For a complete tile wInSub and hInSub are set to the same values as
130 * in tileInfo. If the source image is smaller than a whole tile in
131 * one or both dimensions then they are set to the values of the
132 * source image. This only works as long as the source image is bigger
135 static void savageUploadTile (const savageTileInfo
*tileInfo
,
136 GLuint wInSub
, GLuint hInSub
, GLuint bpp
,
137 GLubyte
*src
, GLuint srcStride
, GLubyte
*dest
) {
138 GLuint subStride
= tileInfo
->subWidth
* bpp
;
139 GLubyte
*srcSRow
= src
, *srcSTile
= src
;
140 GLubyte
*(*subtileFunc
) (GLubyte
*, GLubyte
*, GLuint
);
143 case 2: subtileFunc
= savageUploadSubtile_2x8
; break;
144 case 4: subtileFunc
= savageUploadSubtile_4x8
; break;
145 case 8: subtileFunc
= tileInfo
->subHeight
== 8 ?
146 savageUploadSubtile_8x8
: savageUploadSubtile_8x2
; break;
147 case 16: subtileFunc
= tileInfo
->subHeight
== 8 ?
148 savageUploadSubtile_16x8
: savageUploadSubtile_16x2
; break;
149 case 32: subtileFunc
= savageUploadSubtile_32x8
; break;
152 for (sy
= 0; sy
< hInSub
; ++sy
) {
154 for (sx
= 0; sx
< wInSub
; ++sx
) {
156 dest
= subtileFunc (dest
, src
, srcStride
);
157 srcSTile
+= subStride
;
159 srcSRow
+= srcStride
* tileInfo
->subHeight
;
163 /** \brief Upload a image that is smaller than 8 pixels in either dimension.
165 * \param tileInfo Pointer to tiling information
166 * \param width Width of the image
167 * \param height Height of the image
168 * \param bpp Bytes per pixel
169 * \param src Pointer to source data
170 * \param dest Pointer to destination
172 * This function handles all the special cases that need to be taken
173 * care off. The caller may need to call this function multiple times
174 * with the destination offset in different ways since small texture
175 * images must be repeated in order to fill a whole tile (or 4x4 for
176 * the last 3 levels).
178 * FIXME: Repeating inside this function would be more efficient.
180 static void savageUploadTiny (const savageTileInfo
*tileInfo
,
181 GLuint pixWidth
, GLuint pixHeight
,
182 GLuint width
, GLuint height
, GLuint bpp
,
183 GLubyte
*src
, GLubyte
*dest
) {
184 GLuint size
= MAX2(pixWidth
, pixHeight
);
186 if (width
> tileInfo
->subWidth
) { /* assert: height <= subtile height */
187 GLuint wInSub
= width
/ tileInfo
->subWidth
;
188 GLuint srcStride
= width
* bpp
;
189 GLuint subStride
= tileInfo
->subWidth
* bpp
;
190 GLuint subSkip
= (tileInfo
->subHeight
- height
) * subStride
;
191 GLubyte
*srcSTile
= src
;
193 for (sx
= 0; sx
< wInSub
; ++sx
) {
195 for (y
= 0; y
< height
; ++y
) {
196 memcpy (dest
, src
, subStride
);
201 srcSTile
+= subStride
;
203 } else if (size
> 4) { /* a tile or less wide, except the last 3 levels */
204 GLuint srcStride
= width
* bpp
;
205 GLuint subStride
= tileInfo
->subWidth
* bpp
;
206 /* if the subtile width is 4 we have to skip every other subtile */
207 GLuint subSkip
= tileInfo
->subWidth
<= 4 ?
208 subStride
* tileInfo
->subHeight
: 0;
209 GLuint skipRemainder
= tileInfo
->subHeight
- 1;
211 for (y
= 0; y
< height
; ++y
) {
212 memcpy (dest
, src
, srcStride
);
215 if ((y
& skipRemainder
) == skipRemainder
)
218 } else { /* the last 3 mipmap levels */
219 GLuint offset
= (size
<= 2 ? tileInfo
->tinyOffset
[size
-1] : 0);
220 GLuint subStride
= tileInfo
->subWidth
* bpp
;
223 for (y
= 0; y
< height
; ++y
) {
224 memcpy (dest
, src
, bpp
*width
);
231 /** \brief Upload an image from mesa's internal copy.
233 static void savageUploadTexLevel( savageTexObjPtr t
, int level
)
235 const struct gl_texture_image
*image
= t
->base
.tObj
->Image
[0][level
];
236 const savageTileInfo
*tileInfo
= t
->tileInfo
;
237 GLuint pixWidth
= image
->Width2
, pixHeight
= image
->Height2
;
238 GLuint bpp
= t
->texelBytes
;
239 GLuint width
, height
;
241 /* FIXME: Need triangle (rather than pixel) fallbacks to simulate
242 * this using normal textured triangles.
244 * DO THIS IN DRIVER STATE MANAGMENT, not hardware state.
246 if(image
->Border
!= 0)
247 fprintf (stderr
, "Not supported texture border %d.\n",
248 (int) image
->Border
);
250 if (t
->hwFormat
== TFT_S3TC4A4Bit
|| t
->hwFormat
== TFT_S3TC4CA4Bit
||
251 t
->hwFormat
== TFT_S3TC4Bit
) {
252 width
= (pixWidth
+3) / 4;
253 height
= (pixHeight
+3) / 4;
259 if (pixWidth
>= 8 && pixHeight
>= 8) {
260 GLuint
*dirtyPtr
= t
->image
[level
].dirtyTiles
;
261 GLuint dirtyMask
= 1;
263 if (width
>= tileInfo
->width
&& height
>= tileInfo
->height
) {
264 GLuint wInTiles
= width
/ tileInfo
->width
;
265 GLuint hInTiles
= height
/ tileInfo
->height
;
266 GLubyte
*srcTRow
= image
->Data
, *src
;
267 GLubyte
*dest
= (GLubyte
*)(t
->bufAddr
+ t
->image
[level
].offset
);
269 for (y
= 0; y
< hInTiles
; ++y
) {
271 for (x
= 0; x
< wInTiles
; ++x
) {
272 if (*dirtyPtr
& dirtyMask
) {
273 savageUploadTile (tileInfo
,
274 tileInfo
->wInSub
, tileInfo
->hInSub
,
275 bpp
, src
, width
* bpp
, dest
);
277 src
+= tileInfo
->width
* bpp
;
278 dest
+= 2048; /* tile size is always 2k */
279 if (dirtyMask
== 1<<31) {
285 srcTRow
+= width
* tileInfo
->height
* bpp
;
287 } else if (width
>= tileInfo
->width
) {
288 GLuint wInTiles
= width
/ tileInfo
->width
;
289 GLubyte
*src
= image
->Data
;
290 GLubyte
*dest
= (GLubyte
*)(t
->bufAddr
+ t
->image
[level
].offset
);
291 GLuint tileStride
= tileInfo
->width
* bpp
* height
;
292 savageContextPtr imesa
= (savageContextPtr
)t
->base
.heap
->driverContext
;
294 /* Savage3D-based chips seem so use a constant tile stride
295 * of 2048 for vertically incomplete tiles, but only if
296 * the color depth is 32bpp. Nobody said this was supposed
299 if (bpp
== 4 && imesa
->savageScreen
->chipset
< S3_SAVAGE4
)
301 for (x
= 0; x
< wInTiles
; ++x
) {
302 if (*dirtyPtr
& dirtyMask
) {
303 savageUploadTile (tileInfo
,
305 height
/ tileInfo
->subHeight
,
306 bpp
, src
, width
* bpp
, dest
);
308 src
+= tileInfo
->width
* bpp
;
310 if (dirtyMask
== 1<<31) {
317 savageUploadTile (tileInfo
, width
/ tileInfo
->subWidth
,
318 height
/ tileInfo
->subHeight
, bpp
,
319 image
->Data
, width
* bpp
,
320 (GLubyte
*)(t
->bufAddr
+t
->image
[level
].offset
));
323 GLuint minHeight
, minWidth
, hRepeat
, vRepeat
, x
, y
;
324 if (t
->hwFormat
== TFT_S3TC4A4Bit
|| t
->hwFormat
== TFT_S3TC4CA4Bit
||
325 t
->hwFormat
== TFT_S3TC4Bit
)
326 minWidth
= minHeight
= 1;
328 minWidth
= minHeight
= 4;
329 if (width
> minWidth
|| height
> minHeight
) {
330 minWidth
= tileInfo
->subWidth
;
331 minHeight
= tileInfo
->subHeight
;
333 hRepeat
= width
>= minWidth
? 1 : minWidth
/ width
;
334 vRepeat
= height
>= minHeight
? 1 : minHeight
/ height
;
335 for (y
= 0; y
< vRepeat
; ++y
) {
336 GLuint offset
= y
* tileInfo
->subWidth
*height
* bpp
;
337 for (x
= 0; x
< hRepeat
; ++x
) {
338 savageUploadTiny (tileInfo
, pixWidth
, pixHeight
,
339 width
, height
, bpp
, image
->Data
,
340 (GLubyte
*)(t
->bufAddr
+
341 t
->image
[level
].offset
+offset
));
342 offset
+= width
* bpp
;
348 /** \brief Compute the destination size of a texture image
350 static GLuint
savageTexImageSize (GLuint width
, GLuint height
, GLuint bpp
) {
352 if (width
>= 8 && height
>= 8)
353 return width
* height
* bpp
;
354 /* special case for the last three mipmap levels: the hardware computes
355 * the offset internally */
356 else if (width
<= 4 && height
<= 4)
358 /* partially filled sub tiles waste memory
359 * on Savage3D and Savage4 with subtile width 4 every other subtile is
360 * skipped if width < 8 so we can assume a uniform subtile width of 8 */
362 return width
* 8 * bpp
;
363 else if (height
>= 8)
364 return 8 * height
* bpp
;
369 /** \brief Compute the destination size of a compressed texture image
371 static GLuint
savageCompressedTexImageSize (GLuint width
, GLuint height
,
373 width
= (width
+3) / 4;
374 height
= (height
+3) / 4;
376 if (width
>= 2 && height
>= 2)
377 return width
* height
* bpp
;
378 /* special case for the last three mipmap levels: the hardware computes
379 * the offset internally */
380 else if (width
<= 1 && height
<= 1)
382 /* partially filled sub tiles waste memory
383 * on Savage3D and Savage4 with subtile width 4 every other subtile is
384 * skipped if width < 8 so we can assume a uniform subtile width of 8 */
386 return width
* 2 * bpp
;
387 else if (height
>= 2)
388 return 2 * height
* bpp
;
393 /** \brief Compute the number of (partial) tiles of a texture image
395 static GLuint
savageTexImageTiles (GLuint width
, GLuint height
,
396 const savageTileInfo
*tileInfo
)
398 return (width
+ tileInfo
->width
- 1) / tileInfo
->width
*
399 (height
+ tileInfo
->height
- 1) / tileInfo
->height
;
402 /** \brief Mark dirty tiles
404 * Some care must be taken because tileInfo may not be set or not
405 * up-to-date. So we check if tileInfo is initialized and if the number
406 * of tiles in the bit vector matches the number of tiles computed from
407 * the current tileInfo.
409 static void savageMarkDirtyTiles (savageTexObjPtr t
, GLuint level
,
410 GLuint totalWidth
, GLuint totalHeight
,
411 GLint xoffset
, GLint yoffset
,
412 GLsizei width
, GLsizei height
)
414 GLuint wInTiles
, hInTiles
;
415 GLuint x0
, y0
, x1
, y1
;
419 wInTiles
= (totalWidth
+ t
->tileInfo
->width
- 1) / t
->tileInfo
->width
;
420 hInTiles
= (totalHeight
+ t
->tileInfo
->height
- 1) / t
->tileInfo
->height
;
421 if (wInTiles
* hInTiles
!= t
->image
[level
].nTiles
)
424 x0
= xoffset
/ t
->tileInfo
->width
;
425 y0
= yoffset
/ t
->tileInfo
->height
;
426 x1
= (xoffset
+ width
- 1) / t
->tileInfo
->width
;
427 y1
= (yoffset
+ height
- 1) / t
->tileInfo
->height
;
429 for (y
= y0
; y
<= y1
; ++y
) {
430 GLuint
*ptr
= t
->image
[level
].dirtyTiles
+ (y
* wInTiles
+ x0
) / 32;
431 GLuint mask
= 1 << (y
* wInTiles
+ x0
) % 32;
432 for (x
= x0
; x
<= x1
; ++x
) {
434 if (mask
== (1<<31)) {
444 /** \brief Mark all tiles as dirty
446 static void savageMarkAllTiles (savageTexObjPtr t
, GLuint level
)
448 GLuint words
= (t
->image
[level
].nTiles
+ 31) / 32;
450 memset(t
->image
[level
].dirtyTiles
, ~0, words
*sizeof(GLuint
));
454 static void savageSetTexWrapping(savageTexObjPtr tex
, GLenum s
, GLenum t
)
456 tex
->setup
.sWrapMode
= s
;
457 tex
->setup
.tWrapMode
= t
;
460 static void savageSetTexFilter(savageTexObjPtr t
, GLenum minf
, GLenum magf
)
462 t
->setup
.minFilter
= minf
;
463 t
->setup
.magFilter
= magf
;
469 static void savageSetTexBorderColor(savageTexObjPtr t
, const GLfloat color
[4])
471 /* t->Setup[SAVAGE_TEXREG_TEXBORDERCOL] = */
472 /*t->setup.borderColor = SAVAGEPACKCOLOR8888(color[0],color[1],color[2],color[3]); */
477 static savageTexObjPtr
478 savageAllocTexObj( struct gl_texture_object
*texObj
)
482 t
= (savageTexObjPtr
) calloc(1,sizeof(*t
));
483 texObj
->DriverData
= t
;
487 /* Initialize non-image-dependent parts of the state:
489 t
->base
.tObj
= texObj
;
490 t
->base
.dirty_images
[0] = 0;
491 t
->dirtySubImages
= 0;
494 /* Initialize dirty tiles bit vectors
496 for (i
= 0; i
< SAVAGE_TEX_MAXLEVELS
; ++i
)
497 t
->image
[i
].nTiles
= 0;
499 /* FIXME Something here to set initial values for other parts of
503 make_empty_list( &t
->base
);
505 savageSetTexWrapping(t
,texObj
->WrapS
,texObj
->WrapT
);
506 savageSetTexFilter(t
,texObj
->MinFilter
,texObj
->MagFilter
);
507 savageSetTexBorderColor(t
,texObj
->BorderColor
.f
);
513 /* Mesa texture formats for alpha-images on Savage3D/IX/MX
515 * Promoting texture images to ARGB888 or ARGB4444 doesn't work
516 * because we can't tell the hardware to ignore the color components
517 * and only use the alpha component. So we define our own texture
518 * formats that promote to ARGB8888 or ARGB4444 and set the color
519 * components to white. This way we get the correct result.
523 /* Using MESA_FORMAT_RGBA8888 to store alpha-only textures should
524 * work but is space inefficient.
528 _savage_texstore_a1114444(TEXSTORE_PARAMS
);
531 _savage_texstore_a1118888(TEXSTORE_PARAMS
);
533 static struct gl_texture_format _savage_texformat_a1114444
= {
534 MESA_FORMAT_ARGB4444
, /* MesaFormat */
535 GL_RGBA
, /* BaseFormat */
536 GL_UNSIGNED_NORMALIZED_ARB
, /* DataType */
541 0, /* LuminanceBits */
542 0, /* IntensityBits */
547 _savage_texstore_a1114444
, /* StoreTexImageFunc */
548 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
/* FetchTexel* filled in by
549 * savageDDInitTextureFuncs */
551 static struct gl_texture_format _savage_texformat_a1118888
= {
552 MESA_FORMAT_ARGB8888
, /* MesaFormat */
553 GL_RGBA
, /* BaseFormat */
554 GL_UNSIGNED_NORMALIZED_ARB
, /* DataType */
559 0, /* LuminanceBits */
560 0, /* IntensityBits */
565 _savage_texstore_a1118888
, /* StoreTexImageFunc */
566 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
/* FetchTexel* filled in by
567 * savageDDInitTextureFuncs */
572 _savage_texstore_a1114444(TEXSTORE_PARAMS
)
574 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
577 srcWidth
, srcHeight
, srcDepth
,
578 srcFormat
, srcType
, srcAddr
,
580 const GLchan
*src
= tempImage
;
583 ASSERT(dstFormat
== &_savage_texformat_a1114444
);
584 ASSERT(baseInternalFormat
== GL_ALPHA
);
588 for (img
= 0; img
< srcDepth
; img
++) {
589 GLuint texelBytes
= _mesa_get_format_bytes(dstFormat
);
590 GLubyte
*dstRow
= (GLubyte
*) dstAddr
591 + dstImageOffsets
[dstZoffset
+ img
] * texelBytes
592 + dstYoffset
* dstRowStride
593 + dstXoffset
* texelBytes
;
594 for (row
= 0; row
< srcHeight
; row
++) {
595 GLushort
*dstUI
= (GLushort
*) dstRow
;
596 for (col
= 0; col
< srcWidth
; col
++) {
597 dstUI
[col
] = PACK_COLOR_4444( CHAN_TO_UBYTE(src
[0]),
601 dstRow
+= dstRowStride
;
604 free((void *) tempImage
);
611 _savage_texstore_a1118888(TEXSTORE_PARAMS
)
613 const GLchan
*tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
616 srcWidth
, srcHeight
, srcDepth
,
617 srcFormat
, srcType
, srcAddr
,
619 const GLchan
*src
= tempImage
;
622 ASSERT(dstFormat
== &_savage_texformat_a1118888
);
623 ASSERT(baseInternalFormat
== GL_ALPHA
);
627 for (img
= 0; img
< srcDepth
; img
++) {
628 GLuint texelBytes
= _mesa_get_format_bytes(dstFormat
);
629 GLubyte
*dstRow
= (GLubyte
*) dstAddr
630 + dstImageOffsets
[dstZoffset
+ img
] * texelBytes
631 + dstYoffset
* dstRowStride
632 + dstXoffset
* texelBytes
;
633 for (row
= 0; row
< srcHeight
; row
++) {
634 GLuint
*dstUI
= (GLuint
*) dstRow
;
635 for (col
= 0; col
< srcWidth
; col
++) {
636 dstUI
[col
] = PACK_COLOR_8888( CHAN_TO_UBYTE(src
[0]),
640 dstRow
+= dstRowStride
;
643 free((void *) tempImage
);
650 /* Called by the _mesa_store_teximage[123]d() functions. */
652 savageChooseTextureFormat( GLcontext
*ctx
, GLint internalFormat
,
653 GLenum format
, GLenum type
)
655 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
656 const GLboolean do32bpt
=
657 ( imesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_32
);
658 const GLboolean force16bpt
=
659 ( imesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_FORCE_16
);
660 const GLboolean isSavage4
= (imesa
->savageScreen
->chipset
>= S3_SAVAGE4
);
663 switch ( internalFormat
) {
666 case GL_COMPRESSED_RGBA
:
668 case GL_UNSIGNED_INT_10_10_10_2
:
669 case GL_UNSIGNED_INT_2_10_10_10_REV
:
670 return do32bpt
? MESA_FORMAT_ARGB8888
: MESA_FORMAT_ARGB1555
;
671 case GL_UNSIGNED_SHORT_4_4_4_4
:
672 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
673 return MESA_FORMAT_ARGB4444
;
674 case GL_UNSIGNED_SHORT_5_5_5_1
:
675 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
676 return MESA_FORMAT_ARGB1555
;
678 return do32bpt
? MESA_FORMAT_ARGB8888
: MESA_FORMAT_ARGB4444
;
683 case GL_COMPRESSED_RGB
:
685 case GL_UNSIGNED_SHORT_4_4_4_4
:
686 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
687 return MESA_FORMAT_ARGB4444
;
688 case GL_UNSIGNED_SHORT_5_5_5_1
:
689 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
690 return MESA_FORMAT_ARGB1555
;
691 case GL_UNSIGNED_SHORT_5_6_5
:
692 case GL_UNSIGNED_SHORT_5_6_5_REV
:
693 return MESA_FORMAT_RGB565
;
695 return do32bpt
? MESA_FORMAT_ARGB8888
: MESA_FORMAT_RGB565
;
702 MESA_FORMAT_ARGB8888
: MESA_FORMAT_ARGB4444
;
706 MESA_FORMAT_ARGB8888
: MESA_FORMAT_ARGB1555
;
710 return MESA_FORMAT_ARGB4444
;
713 return MESA_FORMAT_ARGB1555
;
719 return !force16bpt
? MESA_FORMAT_ARGB8888
: MESA_FORMAT_RGB565
;
724 return MESA_FORMAT_RGB565
;
727 case GL_COMPRESSED_ALPHA
:
729 return isSavage4
? MESA_FORMAT_a8
: (
730 do32bpt
? &_savage_texformat_a1118888
: &_savage_texformat_a1114444
);
733 return MESA_FORMAT_A8
;
735 return MESA_FORMAT_ARGB8888
;
737 return MESA_FORMAT_ARGB4444
;
741 return isSavage4
? MESA_FORMAT_a8
: &_savage_texformat_a1114444
;
744 return MESA_FORMAT_A8
;
746 return MESA_FORMAT_ARGB4444
;
752 return isSavage4
? MESA_FORMAT_a8
: (
753 !force16bpt
? &_savage_texformat_a1118888
: &_savage_texformat_a1114444
);
756 return MESA_FORMAT_A8
;
758 return MESA_FORMAT_ARGB4444
;
760 return MESA_FORMAT_ARGB8888
;
764 case GL_COMPRESSED_LUMINANCE
:
765 /* no alpha, but use argb1555 in 16bit case to get pure grey values */
766 return isSavage4
? MESA_FORMAT_L8
: (
767 do32bpt
? MESA_FORMAT_ARGB8888
: MESA_FORMAT_ARGB1555
);
769 return isSavage4
? MESA_FORMAT_L8
: MESA_FORMAT_ARGB1555
;
773 return isSavage4
? MESA_FORMAT_L8
: (
774 !force16bpt
? MESA_FORMAT_ARGB8888
: MESA_FORMAT_ARGB1555
);
777 case GL_LUMINANCE_ALPHA
:
778 case GL_COMPRESSED_LUMINANCE_ALPHA
:
779 /* Savage4 has a al44 texture format. But it's not supported by Mesa. */
780 return do32bpt
? MESA_FORMAT_ARGB8888
: MESA_FORMAT_ARGB4444
;
781 case GL_LUMINANCE4_ALPHA4
:
782 case GL_LUMINANCE6_ALPHA2
:
783 return MESA_FORMAT_ARGB4444
;
784 case GL_LUMINANCE8_ALPHA8
:
785 case GL_LUMINANCE12_ALPHA4
:
786 case GL_LUMINANCE12_ALPHA12
:
787 case GL_LUMINANCE16_ALPHA16
:
788 return !force16bpt
? MESA_FORMAT_ARGB8888
: MESA_FORMAT_ARGB4444
;
790 /* TFT_I8 produces garbage on ProSavageDDR and subsequent texture
791 * disable keeps rendering garbage. Disabled for now. */
793 case GL_COMPRESSED_INTENSITY
:
794 return isSavage4
? MESA_FORMAT_i8
: (
795 do32bpt
? MESA_FORMAT_ARGB8888
: MESA_FORMAT_ARGB4444
);
797 return isSavage4
? MESA_FORMAT_i8
: MESA_FORMAT_ARGB4444
;
801 return isSavage4
? MESA_FORMAT_i8
: (
802 !force16bpt
? MESA_FORMAT_ARGB8888
: MESA_FORMAT_ARGB4444
);
805 case GL_COMPRESSED_INTENSITY
:
806 return do32bpt
? MESA_FORMAT_ARGB8888
: MESA_FORMAT_ARGB4444
;
808 return MESA_FORMAT_ARGB4444
;
812 return !force16bpt
? MESA_FORMAT_ARGB8888
: MESA_FORMAT_ARGB4444
;
817 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
818 return MESA_FORMAT_RGB_DXT1
;
819 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
820 return MESA_FORMAT_RGBA_DXT1
;
822 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
823 return MESA_FORMAT_RGBA_DXT3
;
828 /* Not the best choice but Savage3D/MX/IX don't support DXT3 or DXT5. */
829 return MESA_FORMAT_RGBA_DXT1
;
831 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
832 return MESA_FORMAT_RGBA_DXT5
;
836 case GL_COLOR_INDEX1_EXT:
837 case GL_COLOR_INDEX2_EXT:
838 case GL_COLOR_INDEX4_EXT:
839 case GL_COLOR_INDEX8_EXT:
840 case GL_COLOR_INDEX12_EXT:
841 case GL_COLOR_INDEX16_EXT:
842 return &_mesa_texformat_ci8;
845 _mesa_problem(ctx
, "unexpected texture format in %s", __FUNCTION__
);
846 return MESA_FORMAT_NONE
;
850 static void savageSetTexImages( savageContextPtr imesa
,
851 const struct gl_texture_object
*tObj
)
853 savageTexObjPtr t
= (savageTexObjPtr
) tObj
->DriverData
;
854 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
855 GLuint offset
, i
, textureFormat
, tileIndex
, size
;
856 GLint firstLevel
, lastLevel
;
861 switch (image
->TexFormat
) {
862 case MESA_FORMAT_ARGB8888
:
863 textureFormat
= TFT_ARGB8888
;
864 t
->texelBytes
= tileIndex
= 4;
866 case MESA_FORMAT_ARGB1555
:
867 textureFormat
= TFT_ARGB1555
;
868 t
->texelBytes
= tileIndex
= 2;
870 case MESA_FORMAT_ARGB4444
:
871 textureFormat
= TFT_ARGB4444
;
872 t
->texelBytes
= tileIndex
= 2;
874 case MESA_FORMAT_RGB565
:
875 textureFormat
= TFT_RGB565
;
876 t
->texelBytes
= tileIndex
= 2;
879 textureFormat
= TFT_L8
;
880 t
->texelBytes
= tileIndex
= 1;
883 textureFormat
= TFT_I8
;
884 t
->texelBytes
= tileIndex
= 1;
887 textureFormat
= TFT_A8
;
888 t
->texelBytes
= tileIndex
= 1;
890 case MESA_FORMAT_RGB_DXT1
:
891 textureFormat
= TFT_S3TC4Bit
;
892 tileIndex
= TILE_INDEX_DXT1
;
895 case MESA_FORMAT_RGBA_DXT1
:
896 textureFormat
= TFT_S3TC4Bit
;
897 tileIndex
= TILE_INDEX_DXT1
;
900 case MESA_FORMAT_RGBA_DXT3
:
901 textureFormat
= TFT_S3TC4A4Bit
;
902 tileIndex
= TILE_INDEX_DXTn
;
905 case MESA_FORMAT_RGBA_DXT5
:
906 textureFormat
= TFT_S3TC4CA4Bit
;
907 tileIndex
= TILE_INDEX_DXTn
;
911 _mesa_problem(imesa
->glCtx
, "Bad texture format in %s", __FUNCTION__
);
914 t
->hwFormat
= textureFormat
;
916 /* Select tiling format depending on the chipset and texture format */
917 if (imesa
->savageScreen
->chipset
<= S3_SAVAGE4
)
918 t
->tileInfo
= &tileInfo_s3d_s4
[tileIndex
];
920 t
->tileInfo
= &tileInfo_pro
[tileIndex
];
922 /* Compute which mipmap levels we really want to send to the hardware.
924 driCalculateTextureFirstLastLevel( &t
->base
);
925 firstLevel
= t
->base
.firstLevel
;
926 lastLevel
= t
->base
.lastLevel
;
928 /* Figure out the size now (and count the levels). Upload won't be
929 * done until later. If the number of tiles changes, it means that
930 * this function is called for the first time on this tex object or
931 * the image or the destination color format changed. So all tiles
932 * are marked as dirty.
936 for ( i
= firstLevel
; i
<= lastLevel
&& tObj
->Image
[0][i
] ; i
++ ) {
938 nTiles
= savageTexImageTiles (image
->Width2
, image
->Height2
, t
->tileInfo
);
939 if (t
->image
[i
].nTiles
!= nTiles
) {
940 GLuint words
= (nTiles
+ 31) / 32;
941 if (t
->image
[i
].nTiles
!= 0) {
942 free(t
->image
[i
].dirtyTiles
);
944 t
->image
[i
].dirtyTiles
= malloc(words
*sizeof(GLuint
));
945 memset(t
->image
[i
].dirtyTiles
, ~0, words
*sizeof(GLuint
));
947 t
->image
[i
].nTiles
= nTiles
;
949 t
->image
[i
].offset
= offset
;
951 image
= tObj
->Image
[0][i
];
952 if (t
->texelBytes
>= 8)
953 size
= savageCompressedTexImageSize (image
->Width2
, image
->Height2
,
956 size
= savageTexImageSize (image
->Width2
, image
->Height2
,
961 t
->base
.lastLevel
= i
-1;
962 t
->base
.totalSize
= offset
;
963 /* the last three mipmap levels don't add to the offset. They are packed
966 t
->base
.totalSize
+= (t
->texelBytes
>= 8 ? 4 : 64) * t
->texelBytes
;
967 /* 2k-aligned (really needed?) */
968 t
->base
.totalSize
= (t
->base
.totalSize
+ 2047UL) & ~2047UL;
971 void savageDestroyTexObj(savageContextPtr imesa
, savageTexObjPtr t
)
975 /* Free dirty tiles bit vectors */
976 for (i
= 0; i
< SAVAGE_TEX_MAXLEVELS
; ++i
) {
977 if (t
->image
[i
].nTiles
)
978 free (t
->image
[i
].dirtyTiles
);
981 /* See if it was the driver's current object.
985 for ( i
= 0 ; i
< imesa
->glCtx
->Const
.MaxTextureUnits
; i
++ )
987 if ( &t
->base
== imesa
->CurrentTexObj
[ i
] ) {
988 assert( t
->base
.bound
& (1 << i
) );
989 imesa
->CurrentTexObj
[ i
] = NULL
;
995 /* Upload a texture's images to one of the texture heaps. May have to
996 * eject our own and/or other client's texture objects to make room
999 static void savageUploadTexImages( savageContextPtr imesa
, savageTexObjPtr t
)
1001 const GLint numLevels
= t
->base
.lastLevel
- t
->base
.firstLevel
+ 1;
1006 LOCK_HARDWARE(imesa
);
1008 /* Do we need to eject LRU texture objects?
1010 if (!t
->base
.memBlock
) {
1014 heap
= driAllocateTexture(imesa
->textureHeaps
, imesa
->lastTexHeap
,
1015 (driTextureObject
*)t
);
1017 UNLOCK_HARDWARE(imesa
);
1021 assert(t
->base
.memBlock
);
1022 ofs
= t
->base
.memBlock
->ofs
;
1023 t
->setup
.physAddr
= imesa
->savageScreen
->textureOffset
[heap
] + ofs
;
1024 t
->bufAddr
= (GLubyte
*)imesa
->savageScreen
->texVirtual
[heap
] + ofs
;
1025 imesa
->dirty
|= SAVAGE_UPLOAD_GLOBAL
; /* FIXME: really needed? */
1028 /* Let the world know we've used this memory recently.
1030 driUpdateTextureLRU( &t
->base
);
1031 UNLOCK_HARDWARE(imesa
);
1033 if (t
->base
.dirty_images
[0] || t
->dirtySubImages
) {
1034 if (SAVAGE_DEBUG
& DEBUG_VERBOSE_TEX
)
1035 fprintf(stderr
, "Texture upload: |");
1037 /* Heap timestamps are only reliable with Savage DRM 2.3.x or
1038 * later. Earlier versions had only 16 bit time stamps which
1039 * would wrap too frequently. */
1040 if (imesa
->savageScreen
->driScrnPriv
->drm_version
.minor
>= 3) {
1041 unsigned int heap
= t
->base
.heap
->heapId
;
1042 LOCK_HARDWARE(imesa
);
1043 savageWaitEvent (imesa
, imesa
->textureHeaps
[heap
]->timestamp
);
1045 savageFlushVertices (imesa
);
1046 LOCK_HARDWARE(imesa
);
1047 savageFlushCmdBufLocked (imesa
, GL_FALSE
);
1048 WAIT_IDLE_EMPTY_LOCKED(imesa
);
1051 for (i
= 0 ; i
< numLevels
; i
++) {
1052 const GLint j
= t
->base
.firstLevel
+ i
; /* the texObj's level */
1053 if (t
->base
.dirty_images
[0] & (1 << j
)) {
1054 savageMarkAllTiles(t
, j
);
1055 if (SAVAGE_DEBUG
& DEBUG_VERBOSE_TEX
)
1056 fprintf (stderr
, "*");
1057 } else if (SAVAGE_DEBUG
& DEBUG_VERBOSE_TEX
) {
1058 if (t
->dirtySubImages
& (1 << j
))
1059 fprintf (stderr
, ".");
1061 fprintf (stderr
, " ");
1063 if ((t
->base
.dirty_images
[0] | t
->dirtySubImages
) & (1 << j
))
1064 savageUploadTexLevel( t
, j
);
1067 UNLOCK_HARDWARE(imesa
);
1068 t
->base
.dirty_images
[0] = 0;
1069 t
->dirtySubImages
= 0;
1071 if (SAVAGE_DEBUG
& DEBUG_VERBOSE_TEX
)
1072 fprintf(stderr
, "|\n");
1078 savage4_set_wrap_mode( savageContextPtr imesa
, unsigned unit
,
1079 GLenum s_mode
, GLenum t_mode
)
1083 imesa
->regs
.s4
.texCtrl
[ unit
].ni
.uMode
= TAM_Wrap
;
1086 case GL_CLAMP_TO_EDGE
:
1087 imesa
->regs
.s4
.texCtrl
[ unit
].ni
.uMode
= TAM_Clamp
;
1089 case GL_MIRRORED_REPEAT
:
1090 imesa
->regs
.s4
.texCtrl
[ unit
].ni
.uMode
= TAM_Mirror
;
1096 imesa
->regs
.s4
.texCtrl
[ unit
].ni
.vMode
= TAM_Wrap
;
1099 case GL_CLAMP_TO_EDGE
:
1100 imesa
->regs
.s4
.texCtrl
[ unit
].ni
.vMode
= TAM_Clamp
;
1102 case GL_MIRRORED_REPEAT
:
1103 imesa
->regs
.s4
.texCtrl
[ unit
].ni
.vMode
= TAM_Mirror
;
1110 * Sets the hardware bits for the specified GL texture filter modes.
1113 * Does the Savage4 have the ability to select the magnification filter?
1116 savage4_set_filter_mode( savageContextPtr imesa
, unsigned unit
,
1117 GLenum minFilter
, GLenum magFilter
)
1121 switch (minFilter
) {
1123 imesa
->regs
.s4
.texCtrl
[ unit
].ni
.filterMode
= TFM_Point
;
1124 imesa
->regs
.s4
.texCtrl
[ unit
].ni
.mipmapEnable
= GL_FALSE
;
1128 imesa
->regs
.s4
.texCtrl
[ unit
].ni
.filterMode
= TFM_Bilin
;
1129 imesa
->regs
.s4
.texCtrl
[ unit
].ni
.mipmapEnable
= GL_FALSE
;
1132 case GL_NEAREST_MIPMAP_NEAREST
:
1133 imesa
->regs
.s4
.texCtrl
[ unit
].ni
.filterMode
= TFM_Point
;
1134 imesa
->regs
.s4
.texCtrl
[ unit
].ni
.mipmapEnable
= GL_TRUE
;
1137 case GL_LINEAR_MIPMAP_NEAREST
:
1138 imesa
->regs
.s4
.texCtrl
[ unit
].ni
.filterMode
= TFM_Bilin
;
1139 imesa
->regs
.s4
.texCtrl
[ unit
].ni
.mipmapEnable
= GL_TRUE
;
1142 case GL_NEAREST_MIPMAP_LINEAR
:
1143 case GL_LINEAR_MIPMAP_LINEAR
:
1144 imesa
->regs
.s4
.texCtrl
[ unit
].ni
.filterMode
= TFM_Trilin
;
1145 imesa
->regs
.s4
.texCtrl
[ unit
].ni
.mipmapEnable
= GL_TRUE
;
1151 static void savageUpdateTex0State_s4( GLcontext
*ctx
)
1153 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
1154 struct gl_texture_object
*tObj
;
1155 struct gl_texture_image
*image
;
1160 imesa
->regs
.s4
.texDescr
.ni
.tex0En
= GL_FALSE
;
1161 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_NoTexMap
;
1162 imesa
->regs
.s4
.texCtrl
[0].ui
= 0x20f040;
1163 if (ctx
->Texture
.Unit
[0]._ReallyEnabled
== 0)
1166 tObj
= ctx
->Texture
.Unit
[0]._Current
;
1167 if ((ctx
->Texture
.Unit
[0]._ReallyEnabled
& ~(TEXTURE_1D_BIT
|TEXTURE_2D_BIT
))
1168 || tObj
->Image
[0][tObj
->BaseLevel
]->Border
> 0) {
1169 /* 3D texturing enabled, or texture border - fallback */
1170 FALLBACK (ctx
, SAVAGE_FALLBACK_TEXTURE
, GL_TRUE
);
1174 /* Do 2D texture setup */
1176 t
= tObj
->DriverData
;
1178 t
= savageAllocTexObj( tObj
);
1183 imesa
->CurrentTexObj
[0] = &t
->base
;
1186 if (t
->base
.dirty_images
[0] || t
->dirtySubImages
) {
1187 savageSetTexImages(imesa
, tObj
);
1188 savageUploadTexImages(imesa
, t
);
1191 driUpdateTextureLRU( &t
->base
);
1193 format
= tObj
->Image
[0][tObj
->BaseLevel
]->_BaseFormat
;
1195 switch (ctx
->Texture
.Unit
[0].EnvMode
) {
1197 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_FALSE
;
1202 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_Decal
;
1205 case GL_LUMINANCE_ALPHA
:
1208 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_Copy
;
1212 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_CopyAlpha
;
1215 __HWEnvCombineSingleUnitScale(imesa
, 0, 0,
1216 &imesa
->regs
.s4
.texBlendCtrl
[0]);
1220 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_FALSE
;
1225 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_Decal
;
1230 case GL_LUMINANCE_ALPHA
:
1231 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_DecalAlpha
;
1235 GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_INTENSITY
1236 are undefined with GL_DECAL
1240 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_CopyAlpha
;
1243 __HWEnvCombineSingleUnitScale(imesa
, 0, 0,
1244 &imesa
->regs
.s4
.texBlendCtrl
[0]);
1248 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_FALSE
;
1249 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_ModulAlpha
;
1250 __HWEnvCombineSingleUnitScale(imesa
, 0, 0,
1251 &imesa
->regs
.s4
.texBlendCtrl
[0]);
1255 imesa
->regs
.s4
.texBlendColor
.ui
= imesa
->texEnvColor
;
1260 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_ModulAlpha
;
1261 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_FALSE
;
1266 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_Blend0
;
1267 imesa
->regs
.s4
.texDescr
.ni
.tex1En
= GL_TRUE
;
1268 imesa
->regs
.s4
.texDescr
.ni
.texBLoopEn
= GL_TRUE
;
1269 imesa
->regs
.s4
.texDescr
.ni
.tex1Width
=
1270 imesa
->regs
.s4
.texDescr
.ni
.tex0Width
;
1271 imesa
->regs
.s4
.texDescr
.ni
.tex1Height
=
1272 imesa
->regs
.s4
.texDescr
.ni
.tex0Height
;
1273 imesa
->regs
.s4
.texDescr
.ni
.tex1Fmt
=
1274 imesa
->regs
.s4
.texDescr
.ni
.tex0Fmt
;
1276 imesa
->regs
.s4
.texAddr
[1].ui
= imesa
->regs
.s4
.texAddr
[0].ui
;
1277 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_Blend1
;
1279 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_TRUE
;
1280 imesa
->bTexEn1
= GL_TRUE
;
1283 case GL_LUMINANCE_ALPHA
:
1285 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_BlendAlpha0
;
1286 imesa
->regs
.s4
.texDescr
.ni
.tex1En
= GL_TRUE
;
1287 imesa
->regs
.s4
.texDescr
.ni
.texBLoopEn
= GL_TRUE
;
1288 imesa
->regs
.s4
.texDescr
.ni
.tex1Width
=
1289 imesa
->regs
.s4
.texDescr
.ni
.tex0Width
;
1290 imesa
->regs
.s4
.texDescr
.ni
.tex1Height
=
1291 imesa
->regs
.s4
.texDescr
.ni
.tex0Height
;
1292 imesa
->regs
.s4
.texDescr
.ni
.tex1Fmt
=
1293 imesa
->regs
.s4
.texDescr
.ni
.tex0Fmt
;
1295 imesa
->regs
.s4
.texAddr
[1].ui
= imesa
->regs
.s4
.texAddr
[0].ui
;
1296 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_BlendAlpha1
;
1298 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_TRUE
;
1299 imesa
->bTexEn1
= GL_TRUE
;
1303 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_BlendInt0
;
1304 imesa
->regs
.s4
.texDescr
.ni
.tex1En
= GL_TRUE
;
1305 imesa
->regs
.s4
.texDescr
.ni
.texBLoopEn
= GL_TRUE
;
1306 imesa
->regs
.s4
.texDescr
.ni
.tex1Width
=
1307 imesa
->regs
.s4
.texDescr
.ni
.tex0Width
;
1308 imesa
->regs
.s4
.texDescr
.ni
.tex1Height
=
1309 imesa
->regs
.s4
.texDescr
.ni
.tex0Height
;
1310 imesa
->regs
.s4
.texDescr
.ni
.tex1Fmt
=
1311 imesa
->regs
.s4
.texDescr
.ni
.tex0Fmt
;
1313 imesa
->regs
.s4
.texAddr
[1].ui
= imesa
->regs
.s4
.texAddr
[0].ui
;
1314 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_BlendInt1
;
1316 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_TRUE
;
1317 imesa
->regs
.s4
.texCtrl
[0].ni
.alphaArg1Invert
= GL_TRUE
;
1318 imesa
->bTexEn1
= GL_TRUE
;
1321 __HWEnvCombineSingleUnitScale(imesa
, 0, 0,
1322 &imesa
->regs
.s4
.texBlendCtrl
[0]);
1326 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_FALSE
;
1330 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_ModulAlpha
;
1335 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_Add
;
1338 case GL_LUMINANCE_ALPHA
:
1340 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_Add
;
1344 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_AddAlpha
;
1347 __HWEnvCombineSingleUnitScale(imesa
, 0, 0,
1348 &imesa
->regs
.s4
.texBlendCtrl
[0]);
1351 #if GL_ARB_texture_env_combine
1352 case GL_COMBINE_ARB
:
1353 __HWParseTexEnvCombine(imesa
, 0, &imesa
->regs
.s4
.texCtrl
[0],
1354 &imesa
->regs
.s4
.texBlendCtrl
[0]);
1359 fprintf(stderr
, "unknown tex env mode");
1364 savage4_set_wrap_mode( imesa
, 0, t
->setup
.sWrapMode
, t
->setup
.tWrapMode
);
1365 savage4_set_filter_mode( imesa
, 0, t
->setup
.minFilter
, t
->setup
.magFilter
);
1367 if((ctx
->Texture
.Unit
[0].LodBias
!=0.0F
) ||
1368 (imesa
->regs
.s4
.texCtrl
[0].ni
.dBias
!= 0))
1370 int bias
= (int)(ctx
->Texture
.Unit
[0].LodBias
* 32.0) +
1374 else if (bias
> 255)
1376 imesa
->regs
.s4
.texCtrl
[0].ni
.dBias
= bias
& 0x1ff;
1379 image
= tObj
->Image
[0][tObj
->BaseLevel
];
1380 imesa
->regs
.s4
.texDescr
.ni
.tex0En
= GL_TRUE
;
1381 imesa
->regs
.s4
.texDescr
.ni
.tex0Width
= image
->WidthLog2
;
1382 imesa
->regs
.s4
.texDescr
.ni
.tex0Height
= image
->HeightLog2
;
1383 imesa
->regs
.s4
.texDescr
.ni
.tex0Fmt
= t
->hwFormat
;
1384 imesa
->regs
.s4
.texCtrl
[0].ni
.dMax
= t
->base
.lastLevel
- t
->base
.firstLevel
;
1386 if (imesa
->regs
.s4
.texDescr
.ni
.tex1En
)
1387 imesa
->regs
.s4
.texDescr
.ni
.texBLoopEn
= GL_TRUE
;
1389 imesa
->regs
.s4
.texAddr
[0].ui
= (uint32_t) t
->setup
.physAddr
| 0x2;
1390 if(t
->base
.heap
->heapId
== SAVAGE_AGP_HEAP
)
1391 imesa
->regs
.s4
.texAddr
[0].ui
|= 0x1;
1395 static void savageUpdateTex1State_s4( GLcontext
*ctx
)
1397 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
1398 struct gl_texture_object
*tObj
;
1399 struct gl_texture_image
*image
;
1406 imesa
->bTexEn1
= GL_FALSE
;
1410 imesa
->regs
.s4
.texDescr
.ni
.tex1En
= GL_FALSE
;
1411 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_NoTexMap1
;
1412 imesa
->regs
.s4
.texCtrl
[1].ui
= 0x20f040;
1413 imesa
->regs
.s4
.texDescr
.ni
.texBLoopEn
= GL_FALSE
;
1414 if (ctx
->Texture
.Unit
[1]._ReallyEnabled
== 0)
1417 tObj
= ctx
->Texture
.Unit
[1]._Current
;
1419 if ((ctx
->Texture
.Unit
[1]._ReallyEnabled
& ~(TEXTURE_1D_BIT
|TEXTURE_2D_BIT
))
1420 || tObj
->Image
[0][tObj
->BaseLevel
]->Border
> 0) {
1421 /* 3D texturing enabled, or texture border - fallback */
1422 FALLBACK (ctx
, SAVAGE_FALLBACK_TEXTURE
, GL_TRUE
);
1426 /* Do 2D texture setup */
1428 t
= tObj
->DriverData
;
1430 t
= savageAllocTexObj( tObj
);
1435 imesa
->CurrentTexObj
[1] = &t
->base
;
1439 if (t
->base
.dirty_images
[0] || t
->dirtySubImages
) {
1440 savageSetTexImages(imesa
, tObj
);
1441 savageUploadTexImages(imesa
, t
);
1444 driUpdateTextureLRU( &t
->base
);
1446 format
= tObj
->Image
[0][tObj
->BaseLevel
]->_BaseFormat
;
1448 switch (ctx
->Texture
.Unit
[1].EnvMode
) {
1450 imesa
->regs
.s4
.texCtrl
[1].ni
.clrArg1Invert
= GL_FALSE
;
1455 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_Decal
;
1458 case GL_LUMINANCE_ALPHA
:
1461 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_Copy
;
1465 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_CopyAlpha1
;
1468 __HWEnvCombineSingleUnitScale(imesa
, 0, 1, &imesa
->regs
.s4
.texBlendCtrl
);
1471 imesa
->regs
.s4
.texCtrl
[1].ni
.clrArg1Invert
= GL_FALSE
;
1472 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_ModulAlpha1
;
1473 __HWEnvCombineSingleUnitScale(imesa
, 0, 1, &imesa
->regs
.s4
.texBlendCtrl
);
1477 imesa
->regs
.s4
.texCtrl
[1].ni
.clrArg1Invert
= GL_FALSE
;
1481 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_ModulAlpha1
;
1486 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_Add1
;
1489 case GL_LUMINANCE_ALPHA
:
1491 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_Add1
;
1495 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_AddAlpha1
;
1498 __HWEnvCombineSingleUnitScale(imesa
, 0, 1, &imesa
->regs
.s4
.texBlendCtrl
);
1501 #if GL_ARB_texture_env_combine
1502 case GL_COMBINE_ARB
:
1503 __HWParseTexEnvCombine(imesa
, 1, &texCtrl
, &imesa
->regs
.s4
.texBlendCtrl
);
1508 imesa
->regs
.s4
.texCtrl
[1].ni
.clrArg1Invert
= GL_FALSE
;
1514 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_Decal1
;
1516 case GL_LUMINANCE_ALPHA
:
1519 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_DecalAlpha1
;
1523 // GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_INTENSITY
1524 // are undefined with GL_DECAL
1527 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_CopyAlpha1
;
1530 __HWEnvCombineSingleUnitScale(imesa
, 0, 1, &imesa
->regs
.s4
.texBlendCtrl
);
1534 if (format
== GL_LUMINANCE
)
1537 // This is a hack for GLQuake, invert.
1539 imesa
->regs
.s4
.texCtrl
[1].ni
.clrArg1Invert
= GL_TRUE
;
1540 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= 0;
1542 __HWEnvCombineSingleUnitScale(imesa
, 0, 1, &imesa
->regs
.s4
.texBlendCtrl
);
1546 fprintf(stderr
, "unknown tex 1 env mode\n");
1551 savage4_set_wrap_mode( imesa
, 1, t
->setup
.sWrapMode
, t
->setup
.tWrapMode
);
1552 savage4_set_filter_mode( imesa
, 1, t
->setup
.minFilter
, t
->setup
.magFilter
);
1554 if((ctx
->Texture
.Unit
[1].LodBias
!=0.0F
) ||
1555 (imesa
->regs
.s4
.texCtrl
[1].ni
.dBias
!= 0))
1557 int bias
= (int)(ctx
->Texture
.Unit
[1].LodBias
* 32.0) +
1561 else if (bias
> 255)
1563 imesa
->regs
.s4
.texCtrl
[1].ni
.dBias
= bias
& 0x1ff;
1566 image
= tObj
->Image
[0][tObj
->BaseLevel
];
1567 imesa
->regs
.s4
.texDescr
.ni
.tex1En
= GL_TRUE
;
1568 imesa
->regs
.s4
.texDescr
.ni
.tex1Width
= image
->WidthLog2
;
1569 imesa
->regs
.s4
.texDescr
.ni
.tex1Height
= image
->HeightLog2
;
1570 imesa
->regs
.s4
.texDescr
.ni
.tex1Fmt
= t
->hwFormat
;
1571 imesa
->regs
.s4
.texCtrl
[1].ni
.dMax
= t
->base
.lastLevel
- t
->base
.firstLevel
;
1572 imesa
->regs
.s4
.texDescr
.ni
.texBLoopEn
= GL_TRUE
;
1574 imesa
->regs
.s4
.texAddr
[1].ui
= (uint32_t) t
->setup
.physAddr
| 2;
1575 if(t
->base
.heap
->heapId
== SAVAGE_AGP_HEAP
)
1576 imesa
->regs
.s4
.texAddr
[1].ui
|= 0x1;
1578 static void savageUpdateTexState_s3d( GLcontext
*ctx
)
1580 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
1581 struct gl_texture_object
*tObj
;
1582 struct gl_texture_image
*image
;
1587 imesa
->regs
.s3d
.texCtrl
.ui
= 0;
1588 imesa
->regs
.s3d
.texCtrl
.ni
.texEn
= GL_FALSE
;
1589 imesa
->regs
.s3d
.texCtrl
.ni
.dBias
= 0x08;
1590 imesa
->regs
.s3d
.texCtrl
.ni
.texXprEn
= GL_TRUE
;
1591 if (ctx
->Texture
.Unit
[0]._ReallyEnabled
== 0)
1594 tObj
= ctx
->Texture
.Unit
[0]._Current
;
1595 if ((ctx
->Texture
.Unit
[0]._ReallyEnabled
& ~(TEXTURE_1D_BIT
|TEXTURE_2D_BIT
))
1596 || tObj
->Image
[0][tObj
->BaseLevel
]->Border
> 0) {
1597 /* 3D texturing enabled, or texture border - fallback */
1598 FALLBACK (ctx
, SAVAGE_FALLBACK_TEXTURE
, GL_TRUE
);
1602 /* Do 2D texture setup */
1603 t
= tObj
->DriverData
;
1605 t
= savageAllocTexObj( tObj
);
1610 imesa
->CurrentTexObj
[0] = &t
->base
;
1613 if (t
->base
.dirty_images
[0] || t
->dirtySubImages
) {
1614 savageSetTexImages(imesa
, tObj
);
1615 savageUploadTexImages(imesa
, t
);
1618 driUpdateTextureLRU( &t
->base
);
1620 format
= tObj
->Image
[0][tObj
->BaseLevel
]->_BaseFormat
;
1622 /* FIXME: copied from utah-glx, probably needs some tuning */
1623 switch (ctx
->Texture
.Unit
[0].EnvMode
) {
1625 imesa
->regs
.s3d
.drawCtrl
.ni
.texBlendCtrl
= SAVAGETBC_DECALALPHA_S3D
;
1629 case GL_ALPHA
: /* FIXME */
1630 imesa
->regs
.s3d
.drawCtrl
.ni
.texBlendCtrl
= 1;
1632 case GL_LUMINANCE_ALPHA
:
1634 imesa
->regs
.s3d
.drawCtrl
.ni
.texBlendCtrl
= 4;
1638 imesa
->regs
.s3d
.drawCtrl
.ni
.texBlendCtrl
= SAVAGETBC_DECAL_S3D
;
1641 imesa
->regs
.s3d
.drawCtrl
.ni
.texBlendCtrl
= SAVAGETBC_COPY_S3D
;
1644 case GL_BLEND
: /* hardware can't do GL_BLEND */
1645 FALLBACK (ctx
, SAVAGE_FALLBACK_TEXTURE
, GL_TRUE
);
1648 imesa
->regs
.s3d
.drawCtrl
.ni
.texBlendCtrl
= SAVAGETBC_MODULATEALPHA_S3D
;
1651 fprintf(stderr
, "unknown tex env mode\n");
1656 /* The Savage3D can't handle different wrapping modes in s and t.
1657 * If they are not the same, fall back to software. */
1658 if (t
->setup
.sWrapMode
!= t
->setup
.tWrapMode
) {
1659 FALLBACK (ctx
, SAVAGE_FALLBACK_TEXTURE
, GL_TRUE
);
1662 imesa
->regs
.s3d
.texCtrl
.ni
.uWrapEn
= 0;
1663 imesa
->regs
.s3d
.texCtrl
.ni
.vWrapEn
= 0;
1664 imesa
->regs
.s3d
.texCtrl
.ni
.wrapMode
=
1665 (t
->setup
.sWrapMode
== GL_REPEAT
) ? TAM_Wrap
: TAM_Clamp
;
1667 switch (t
->setup
.minFilter
) {
1669 imesa
->regs
.s3d
.texCtrl
.ni
.filterMode
= TFM_Point
;
1670 imesa
->regs
.s3d
.texCtrl
.ni
.mipmapDisable
= GL_TRUE
;
1674 imesa
->regs
.s3d
.texCtrl
.ni
.filterMode
= TFM_Bilin
;
1675 imesa
->regs
.s3d
.texCtrl
.ni
.mipmapDisable
= GL_TRUE
;
1678 case GL_NEAREST_MIPMAP_NEAREST
:
1679 imesa
->regs
.s3d
.texCtrl
.ni
.filterMode
= TFM_Point
;
1680 imesa
->regs
.s3d
.texCtrl
.ni
.mipmapDisable
= GL_FALSE
;
1683 case GL_LINEAR_MIPMAP_NEAREST
:
1684 imesa
->regs
.s3d
.texCtrl
.ni
.filterMode
= TFM_Bilin
;
1685 imesa
->regs
.s3d
.texCtrl
.ni
.mipmapDisable
= GL_FALSE
;
1688 case GL_NEAREST_MIPMAP_LINEAR
:
1689 case GL_LINEAR_MIPMAP_LINEAR
:
1690 imesa
->regs
.s3d
.texCtrl
.ni
.filterMode
= TFM_Trilin
;
1691 imesa
->regs
.s3d
.texCtrl
.ni
.mipmapDisable
= GL_FALSE
;
1695 /* There is no way to specify a maximum mipmap level. We may have to
1696 disable mipmapping completely. */
1698 if (t->max_level < t->image[0].image->WidthLog2 ||
1699 t->max_level < t->image[0].image->HeightLog2) {
1700 texCtrl.ni.mipmapEnable = GL_TRUE;
1701 if (texCtrl.ni.filterMode == TFM_Trilin)
1702 texCtrl.ni.filterMode = TFM_Bilin;
1703 texCtrl.ni.filterMode = TFM_Point;
1707 if((ctx
->Texture
.Unit
[0].LodBias
!=0.0F
) ||
1708 (imesa
->regs
.s3d
.texCtrl
.ni
.dBias
!= 0))
1710 int bias
= (int)(ctx
->Texture
.Unit
[0].LodBias
* 16.0);
1713 else if (bias
> 255)
1715 imesa
->regs
.s3d
.texCtrl
.ni
.dBias
= bias
& 0x1ff;
1718 image
= tObj
->Image
[0][tObj
->BaseLevel
];
1719 imesa
->regs
.s3d
.texCtrl
.ni
.texEn
= GL_TRUE
;
1720 imesa
->regs
.s3d
.texDescr
.ni
.texWidth
= image
->WidthLog2
;
1721 imesa
->regs
.s3d
.texDescr
.ni
.texHeight
= image
->HeightLog2
;
1722 assert (t
->hwFormat
<= 7);
1723 imesa
->regs
.s3d
.texDescr
.ni
.texFmt
= t
->hwFormat
;
1725 imesa
->regs
.s3d
.texAddr
.ui
= (uint32_t) t
->setup
.physAddr
| 2;
1726 if(t
->base
.heap
->heapId
== SAVAGE_AGP_HEAP
)
1727 imesa
->regs
.s3d
.texAddr
.ui
|= 0x1;
1731 static void savageTimestampTextures( savageContextPtr imesa
)
1733 /* Timestamp current texture objects for texture heap aging.
1734 * Only useful with long-lived 32-bit event tags available
1735 * with Savage DRM 2.3.x or later. */
1736 if ((imesa
->CurrentTexObj
[0] || imesa
->CurrentTexObj
[1]) &&
1737 imesa
->savageScreen
->driScrnPriv
->drm_version
.minor
>= 3) {
1740 e
= savageEmitEvent(imesa
, SAVAGE_WAIT_3D
);
1741 if (imesa
->CurrentTexObj
[0])
1742 imesa
->CurrentTexObj
[0]->timestamp
= e
;
1743 if (imesa
->CurrentTexObj
[1])
1744 imesa
->CurrentTexObj
[1]->timestamp
= e
;
1749 static void savageUpdateTextureState_s4( GLcontext
*ctx
)
1751 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
1753 /* When a texture is about to change or be disabled, timestamp the
1754 * old texture(s). We'll have to wait for this time stamp before
1755 * uploading anything to the same texture heap.
1757 if ((imesa
->CurrentTexObj
[0] && ctx
->Texture
.Unit
[0]._ReallyEnabled
&&
1758 ctx
->Texture
.Unit
[0]._Current
->DriverData
!= imesa
->CurrentTexObj
[0]) ||
1759 (imesa
->CurrentTexObj
[1] && ctx
->Texture
.Unit
[1]._ReallyEnabled
&&
1760 ctx
->Texture
.Unit
[1]._Current
->DriverData
!= imesa
->CurrentTexObj
[1]) ||
1761 (imesa
->CurrentTexObj
[0] && !ctx
->Texture
.Unit
[0]._ReallyEnabled
) ||
1762 (imesa
->CurrentTexObj
[1] && !ctx
->Texture
.Unit
[1]._ReallyEnabled
))
1763 savageTimestampTextures(imesa
);
1765 if (imesa
->CurrentTexObj
[0]) imesa
->CurrentTexObj
[0]->bound
&= ~1;
1766 if (imesa
->CurrentTexObj
[1]) imesa
->CurrentTexObj
[1]->bound
&= ~2;
1767 imesa
->CurrentTexObj
[0] = 0;
1768 imesa
->CurrentTexObj
[1] = 0;
1769 savageUpdateTex0State_s4( ctx
);
1770 savageUpdateTex1State_s4( ctx
);
1771 imesa
->dirty
|= (SAVAGE_UPLOAD_TEX0
|
1772 SAVAGE_UPLOAD_TEX1
);
1774 static void savageUpdateTextureState_s3d( GLcontext
*ctx
)
1776 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
1778 /* When a texture is about to change or be disabled, timestamp the
1779 * old texture(s). We'll have to wait for this time stamp before
1780 * uploading anything to the same texture heap.
1782 if ((imesa
->CurrentTexObj
[0] && ctx
->Texture
.Unit
[0]._ReallyEnabled
&&
1783 ctx
->Texture
.Unit
[0]._Current
->DriverData
!= imesa
->CurrentTexObj
[0]) ||
1784 (imesa
->CurrentTexObj
[0] && !ctx
->Texture
.Unit
[0]._ReallyEnabled
))
1785 savageTimestampTextures(imesa
);
1787 if (imesa
->CurrentTexObj
[0]) imesa
->CurrentTexObj
[0]->bound
&= ~1;
1788 imesa
->CurrentTexObj
[0] = 0;
1789 savageUpdateTexState_s3d( ctx
);
1790 imesa
->dirty
|= (SAVAGE_UPLOAD_TEX0
);
1792 void savageUpdateTextureState( GLcontext
*ctx
)
1794 savageContextPtr imesa
= SAVAGE_CONTEXT( ctx
);
1795 FALLBACK (ctx
, SAVAGE_FALLBACK_TEXTURE
, GL_FALSE
);
1796 FALLBACK(ctx
, SAVAGE_FALLBACK_PROJ_TEXTURE
, GL_FALSE
);
1797 if (imesa
->savageScreen
->chipset
>= S3_SAVAGE4
)
1798 savageUpdateTextureState_s4 (ctx
);
1800 savageUpdateTextureState_s3d (ctx
);
1805 /*****************************************
1807 *****************************************/
1809 static void savageTexEnv( GLcontext
*ctx
, GLenum target
,
1810 GLenum pname
, const GLfloat
*param
)
1812 savageContextPtr imesa
= SAVAGE_CONTEXT( ctx
);
1814 if (pname
== GL_TEXTURE_ENV_MODE
) {
1816 imesa
->new_state
|= SAVAGE_NEW_TEXTURE
;
1818 } else if (pname
== GL_TEXTURE_ENV_COLOR
) {
1820 struct gl_texture_unit
*texUnit
=
1821 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1822 const GLfloat
*fc
= texUnit
->EnvColor
;
1824 CLAMPED_FLOAT_TO_UBYTE(r
, fc
[0]);
1825 CLAMPED_FLOAT_TO_UBYTE(g
, fc
[1]);
1826 CLAMPED_FLOAT_TO_UBYTE(b
, fc
[2]);
1827 CLAMPED_FLOAT_TO_UBYTE(a
, fc
[3]);
1829 imesa
->texEnvColor
= ((a
<< 24) | (r
<< 16) |
1830 (g
<< 8) | (b
<< 0));
1836 /* Update the heap's time stamp, so the new image is not uploaded
1837 * while the old one is still in use. If the texture that is going to
1838 * be changed is currently bound, we need to timestamp the texture
1840 static void savageTexImageChanged (savageTexObjPtr t
) {
1843 savageTimestampTextures(
1844 (savageContextPtr
)t
->base
.heap
->driverContext
);
1845 if (t
->base
.timestamp
> t
->base
.heap
->timestamp
)
1846 t
->base
.heap
->timestamp
= t
->base
.timestamp
;
1850 static void savageTexImage1D( GLcontext
*ctx
, GLenum target
, GLint level
,
1851 GLint internalFormat
,
1852 GLint width
, GLint border
,
1853 GLenum format
, GLenum type
, const GLvoid
*pixels
,
1854 const struct gl_pixelstore_attrib
*packing
,
1855 struct gl_texture_object
*texObj
,
1856 struct gl_texture_image
*texImage
)
1858 savageTexObjPtr t
= (savageTexObjPtr
) texObj
->DriverData
;
1860 savageTexImageChanged (t
);
1862 t
= savageAllocTexObj(texObj
);
1864 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
1868 _mesa_store_teximage1d( ctx
, target
, level
, internalFormat
,
1869 width
, border
, format
, type
,
1870 pixels
, packing
, texObj
, texImage
);
1871 t
->base
.dirty_images
[0] |= (1 << level
);
1872 SAVAGE_CONTEXT(ctx
)->new_state
|= SAVAGE_NEW_TEXTURE
;
1875 static void savageTexSubImage1D( GLcontext
*ctx
,
1880 GLenum format
, GLenum type
,
1881 const GLvoid
*pixels
,
1882 const struct gl_pixelstore_attrib
*packing
,
1883 struct gl_texture_object
*texObj
,
1884 struct gl_texture_image
*texImage
)
1886 savageTexObjPtr t
= (savageTexObjPtr
) texObj
->DriverData
;
1887 assert( t
); /* this _should_ be true */
1889 savageTexImageChanged (t
);
1890 savageMarkDirtyTiles(t
, level
, texImage
->Width2
, 1,
1891 xoffset
, 0, width
, 1);
1893 t
= savageAllocTexObj(texObj
);
1895 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
1898 t
->base
.dirty_images
[0] |= (1 << level
);
1900 _mesa_store_texsubimage1d(ctx
, target
, level
, xoffset
, width
,
1901 format
, type
, pixels
, packing
, texObj
,
1903 t
->dirtySubImages
|= (1 << level
);
1904 SAVAGE_CONTEXT(ctx
)->new_state
|= SAVAGE_NEW_TEXTURE
;
1907 static void savageTexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
1908 GLint internalFormat
,
1909 GLint width
, GLint height
, GLint border
,
1910 GLenum format
, GLenum type
, const GLvoid
*pixels
,
1911 const struct gl_pixelstore_attrib
*packing
,
1912 struct gl_texture_object
*texObj
,
1913 struct gl_texture_image
*texImage
)
1915 savageTexObjPtr t
= (savageTexObjPtr
) texObj
->DriverData
;
1917 savageTexImageChanged (t
);
1919 t
= savageAllocTexObj(texObj
);
1921 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
1925 _mesa_store_teximage2d( ctx
, target
, level
, internalFormat
,
1926 width
, height
, border
, format
, type
,
1927 pixels
, packing
, texObj
, texImage
);
1928 t
->base
.dirty_images
[0] |= (1 << level
);
1929 SAVAGE_CONTEXT(ctx
)->new_state
|= SAVAGE_NEW_TEXTURE
;
1932 static void savageTexSubImage2D( GLcontext
*ctx
,
1935 GLint xoffset
, GLint yoffset
,
1936 GLsizei width
, GLsizei height
,
1937 GLenum format
, GLenum type
,
1938 const GLvoid
*pixels
,
1939 const struct gl_pixelstore_attrib
*packing
,
1940 struct gl_texture_object
*texObj
,
1941 struct gl_texture_image
*texImage
)
1943 savageTexObjPtr t
= (savageTexObjPtr
) texObj
->DriverData
;
1944 assert( t
); /* this _should_ be true */
1946 savageTexImageChanged (t
);
1947 savageMarkDirtyTiles(t
, level
, texImage
->Width2
, texImage
->Height2
,
1948 xoffset
, yoffset
, width
, height
);
1950 t
= savageAllocTexObj(texObj
);
1952 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
1955 t
->base
.dirty_images
[0] |= (1 << level
);
1957 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
1958 height
, format
, type
, pixels
, packing
, texObj
,
1960 t
->dirtySubImages
|= (1 << level
);
1961 SAVAGE_CONTEXT(ctx
)->new_state
|= SAVAGE_NEW_TEXTURE
;
1965 savageCompressedTexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
1966 GLint internalFormat
,
1967 GLint width
, GLint height
, GLint border
,
1968 GLsizei imageSize
, const GLvoid
*data
,
1969 struct gl_texture_object
*texObj
,
1970 struct gl_texture_image
*texImage
)
1972 savageTexObjPtr t
= (savageTexObjPtr
) texObj
->DriverData
;
1974 savageTexImageChanged (t
);
1976 t
= savageAllocTexObj(texObj
);
1978 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2D");
1982 _mesa_store_compressed_teximage2d( ctx
, target
, level
, internalFormat
,
1983 width
, height
, border
, imageSize
,
1984 data
, texObj
, texImage
);
1985 t
->base
.dirty_images
[0] |= (1 << level
);
1986 SAVAGE_CONTEXT(ctx
)->new_state
|= SAVAGE_NEW_TEXTURE
;
1990 savageCompressedTexSubImage2D( GLcontext
*ctx
,
1993 GLint xoffset
, GLint yoffset
,
1994 GLsizei width
, GLsizei height
,
1995 GLenum format
, GLsizei imageSize
,
1997 struct gl_texture_object
*texObj
,
1998 struct gl_texture_image
*texImage
)
2000 savageTexObjPtr t
= (savageTexObjPtr
) texObj
->DriverData
;
2001 assert( t
); /* this _should_ be true */
2003 savageTexImageChanged (t
);
2004 savageMarkDirtyTiles(t
, level
, texImage
->Width2
, texImage
->Height2
,
2005 xoffset
, yoffset
, width
, height
);
2007 t
= savageAllocTexObj(texObj
);
2009 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
2012 t
->base
.dirty_images
[0] |= (1 << level
);
2014 _mesa_store_compressed_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
,
2015 width
, height
, format
, imageSize
,
2016 data
, texObj
, texImage
);
2017 t
->dirtySubImages
|= (1 << level
);
2018 SAVAGE_CONTEXT(ctx
)->new_state
|= SAVAGE_NEW_TEXTURE
;
2021 static void savageTexParameter( GLcontext
*ctx
, GLenum target
,
2022 struct gl_texture_object
*tObj
,
2023 GLenum pname
, const GLfloat
*params
)
2025 savageTexObjPtr t
= (savageTexObjPtr
) tObj
->DriverData
;
2026 savageContextPtr imesa
= SAVAGE_CONTEXT( ctx
);
2028 if (!t
|| (target
!= GL_TEXTURE_1D
&& target
!= GL_TEXTURE_2D
))
2032 case GL_TEXTURE_MIN_FILTER
:
2033 case GL_TEXTURE_MAG_FILTER
:
2034 savageSetTexFilter(t
,tObj
->MinFilter
,tObj
->MagFilter
);
2037 case GL_TEXTURE_WRAP_S
:
2038 case GL_TEXTURE_WRAP_T
:
2039 savageSetTexWrapping(t
,tObj
->WrapS
,tObj
->WrapT
);
2042 case GL_TEXTURE_BORDER_COLOR
:
2043 savageSetTexBorderColor(t
,tObj
->BorderColor
.f
);
2050 imesa
->new_state
|= SAVAGE_NEW_TEXTURE
;
2053 static void savageBindTexture( GLcontext
*ctx
, GLenum target
,
2054 struct gl_texture_object
*tObj
)
2056 savageContextPtr imesa
= SAVAGE_CONTEXT( ctx
);
2058 assert( (target
!= GL_TEXTURE_1D
&& target
!= GL_TEXTURE_2D
) ||
2059 (tObj
->DriverData
!= NULL
) );
2061 imesa
->new_state
|= SAVAGE_NEW_TEXTURE
;
2064 static void savageDeleteTexture( GLcontext
*ctx
, struct gl_texture_object
*tObj
)
2066 driTextureObject
*t
= (driTextureObject
*)tObj
->DriverData
;
2067 savageContextPtr imesa
= SAVAGE_CONTEXT( ctx
);
2071 savageTimestampTextures(imesa
);
2073 driDestroyTextureObject(t
);
2075 /* Free mipmap images and the texture object itself */
2076 _mesa_delete_texture_object(ctx
, tObj
);
2080 static struct gl_texture_object
*
2081 savageNewTextureObject( GLcontext
*ctx
, GLuint name
, GLenum target
)
2083 struct gl_texture_object
*obj
;
2084 obj
= _mesa_new_texture_object(ctx
, name
, target
);
2085 savageAllocTexObj( obj
);
2090 void savageDDInitTextureFuncs( struct dd_function_table
*functions
)
2092 functions
->TexEnv
= savageTexEnv
;
2093 functions
->ChooseTextureFormat
= savageChooseTextureFormat
;
2094 functions
->TexImage1D
= savageTexImage1D
;
2095 functions
->TexSubImage1D
= savageTexSubImage1D
;
2096 functions
->TexImage2D
= savageTexImage2D
;
2097 functions
->TexSubImage2D
= savageTexSubImage2D
;
2098 functions
->CompressedTexImage2D
= savageCompressedTexImage2D
;
2099 functions
->CompressedTexSubImage2D
= savageCompressedTexSubImage2D
;
2100 functions
->BindTexture
= savageBindTexture
;
2101 functions
->NewTextureObject
= savageNewTextureObject
;
2102 functions
->DeleteTexture
= savageDeleteTexture
;
2103 functions
->IsTextureResident
= driIsTextureResident
;
2104 functions
->TexParameter
= savageTexParameter
;
2106 /* Texel fetching with our custom texture formats works just like
2107 * the standard argb formats. */
2109 _savage_texformat_a1114444
.FetchTexel1D
= _mesa_texformat_argb4444
.FetchTexel1D
;
2110 _savage_texformat_a1114444
.FetchTexel2D
= _mesa_texformat_argb4444
.FetchTexel2D
;
2111 _savage_texformat_a1114444
.FetchTexel3D
= _mesa_texformat_argb4444
.FetchTexel3D
;
2112 _savage_texformat_a1114444
.FetchTexel1Df
= _mesa_texformat_argb4444
.FetchTexel1Df
;
2113 _savage_texformat_a1114444
.FetchTexel2Df
= _mesa_texformat_argb4444
.FetchTexel2Df
;
2114 _savage_texformat_a1114444
.FetchTexel3Df
= _mesa_texformat_argb4444
.FetchTexel3Df
;
2116 _savage_texformat_a1118888
.FetchTexel1D
= _mesa_texformat_argb8888
.FetchTexel1D
;
2117 _savage_texformat_a1118888
.FetchTexel2D
= _mesa_texformat_argb8888
.FetchTexel2D
;
2118 _savage_texformat_a1118888
.FetchTexel3D
= _mesa_texformat_argb8888
.FetchTexel3D
;
2119 _savage_texformat_a1118888
.FetchTexel1Df
= _mesa_texformat_argb8888
.FetchTexel1Df
;
2120 _savage_texformat_a1118888
.FetchTexel2Df
= _mesa_texformat_argb8888
.FetchTexel2Df
;
2121 _savage_texformat_a1118888
.FetchTexel3Df
= _mesa_texformat_argb8888
.FetchTexel3Df
;