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"
45 #include "swrast/swrast.h"
49 /* Size 1, 2 and 4 images are packed into the last subtile. Each image
50 * is repeated to fill a 4x4 pixel area. The figure below shows the
51 * layout of those 4x4 pixel areas in the 8x8 subtile.
56 * Yuck! 8-bit texture formats use 4x8 subtiles. See below.
58 static const savageTileInfo tileInfo_pro
[5] = {
59 {64, 64, 8, 8, 8, 8, {0x12, 0x02}}, /* 4-bit */
60 {64, 32, 16, 4, 4, 8, {0x30, 0x20}}, /* 8-bit */
61 {64, 16, 8, 2, 8, 8, {0x48, 0x08}}, /* 16-bit */
62 { 0, 0, 0, 0, 0, 0, {0x00, 0x00}}, /* 24-bit */
63 {32, 16, 4, 2, 8, 8, {0x90, 0x10}}, /* 32-bit */
66 /* Size 1, 2 and 4 images are packed into the last two subtiles. Each
67 * image is repeated to fill a 4x4 pixel area. The figures below show
68 * the layout of those 4x4 pixel areas in the two 4x8 subtiles.
70 * second last subtile: 4 last subtile: 2
73 static const savageTileInfo tileInfo_s3d_s4
[5] = {
74 {64, 64, 16, 8, 4, 8, {0x18, 0x10}}, /* 4-bit */
75 {64, 32, 16, 4, 4, 8, {0x30, 0x20}}, /* 8-bit */
76 {64, 16, 16, 2, 4, 8, {0x60, 0x40}}, /* 16-bit */
77 { 0, 0, 0, 0, 0, 0, {0x00, 0x00}}, /* 24-bit */
78 {32, 16, 8, 2, 4, 8, {0xc0, 0x80}}, /* 32-bit */
81 /** \brief Upload a complete tile from src (srcStride) to dest
83 * \param tileInfo Pointer to tiling information
84 * \param wInSub Width of source/dest image in subtiles
85 * \param hInSub Height of source/dest image in subtiles
86 * \param bpp Bytes per pixel
87 * \param src Pointer to source data
88 * \param srcStride Byte stride of rows in the source data
89 * \param dest Pointer to destination
91 * Writes linearly to the destination memory in order to exploit write
94 * For a complete tile wInSub and hInSub are set to the same values as
95 * in tileInfo. If the source image is smaller than a whole tile in
96 * one or both dimensions then they are set to the values of the
97 * source image. This only works as long as the source image is bigger
100 static void savageUploadTile (const savageTileInfo
*tileInfo
,
101 GLuint wInSub
, GLuint hInSub
, GLuint bpp
,
102 GLubyte
*src
, GLuint srcStride
, GLubyte
*dest
) {
103 GLuint subStride
= tileInfo
->subWidth
* bpp
;
104 GLubyte
*srcSRow
= src
, *srcSTile
= src
;
106 for (sy
= 0; sy
< hInSub
; ++sy
) {
108 for (sx
= 0; sx
< wInSub
; ++sx
) {
110 for (y
= 0; y
< tileInfo
->subHeight
; ++y
) {
111 memcpy (dest
, src
, subStride
);
115 srcSTile
+= subStride
;
117 srcSRow
+= srcStride
* tileInfo
->subHeight
;
121 /** \brief Upload a image that is smaller than 8 pixels in either dimension.
123 * \param tileInfo Pointer to tiling information
124 * \param width Width of the image
125 * \param height Height of the image
126 * \param bpp Bytes per pixel
127 * \param src Pointer to source data
128 * \param dest Pointer to destination
130 * This function handles all the special cases that need to be taken
131 * care off. The caller may need to call this function multiple times
132 * with the destination offset in different ways since small texture
133 * images must be repeated in order to fill a whole tile (or 4x4 for
134 * the last 3 levels).
136 * FIXME: Repeating inside this function would be more efficient.
138 static void savageUploadTiny (const savageTileInfo
*tileInfo
,
139 GLuint width
, GLuint height
, GLuint bpp
,
140 GLubyte
*src
, GLubyte
*dest
) {
141 GLuint size
= MAX2(width
, height
);
143 if (width
> tileInfo
->subWidth
) { /* assert: height <= subtile height */
144 GLuint wInSub
= width
/ tileInfo
->subWidth
;
145 GLuint srcStride
= width
* bpp
;
146 GLuint subStride
= tileInfo
->subWidth
* bpp
;
147 GLuint subSkip
= (tileInfo
->subHeight
- height
) * subStride
;
148 GLubyte
*srcSTile
= src
;
150 for (sx
= 0; sx
< wInSub
; ++sx
) {
152 for (y
= 0; y
< height
; ++y
) {
153 memcpy (dest
, src
, subStride
);
158 srcSTile
+= subStride
;
160 } else if (size
> 4) { /* a tile or less wide, except the last 3 levels */
161 GLuint srcStride
= width
* bpp
;
162 GLuint subStride
= tileInfo
->subWidth
* bpp
;
163 /* if the subtile width is 4 we have to skip every other subtile */
164 GLuint subSkip
= tileInfo
->subWidth
== 4 ?
165 subStride
* tileInfo
->subHeight
: 0;
167 for (y
= 0; y
< height
; ++y
) {
168 memcpy (dest
, src
, srcStride
);
174 } else { /* the last 3 mipmap levels */
175 GLuint offset
= (size
<= 2 ? tileInfo
->tinyOffset
[size
-1] : 0);
176 GLuint subStride
= tileInfo
->subWidth
* bpp
;
179 for (y
= 0; y
< height
; ++y
) {
180 memcpy (dest
, src
, bpp
*width
);
187 /** \brief Upload an image from mesa's internal copy.
189 static void savageUploadTexLevel( savageTexObjPtr t
, int level
)
191 const struct gl_texture_image
*image
= t
->base
.tObj
->Image
[0][level
];
192 const savageTileInfo
*tileInfo
= t
->tileInfo
;
193 GLuint width
= image
->Width2
, height
= image
->Height2
;
194 GLuint bpp
= t
->texelBytes
;
196 /* FIXME: Need triangle (rather than pixel) fallbacks to simulate
197 * this using normal textured triangles.
199 * DO THIS IN DRIVER STATE MANAGMENT, not hardware state.
201 if(image
->Border
!= 0)
202 fprintf (stderr
, "Not supported texture border %d.\n",
203 (int) image
->Border
);
205 if (width
>= 8 && height
>= tileInfo
->subHeight
) {
206 GLuint
*dirtyPtr
= t
->image
[level
].dirtyTiles
;
207 GLuint dirtyMask
= 1;
209 if (width
>= tileInfo
->width
&& height
>= tileInfo
->height
) {
210 GLuint wInTiles
= width
/ tileInfo
->width
;
211 GLuint hInTiles
= height
/ tileInfo
->height
;
212 GLubyte
*srcTRow
= image
->Data
, *src
;
213 GLubyte
*dest
= (GLubyte
*)(t
->bufAddr
+ t
->image
[level
].offset
);
215 for (y
= 0; y
< hInTiles
; ++y
) {
217 for (x
= 0; x
< wInTiles
; ++x
) {
218 if (*dirtyPtr
& dirtyMask
) {
219 savageUploadTile (tileInfo
,
220 tileInfo
->wInSub
, tileInfo
->hInSub
,
221 bpp
, src
, width
* bpp
, dest
);
223 src
+= tileInfo
->width
* bpp
;
224 dest
+= 2048; /* tile size is always 2k */
225 if (dirtyMask
== 1<<31) {
231 srcTRow
+= width
* tileInfo
->height
* bpp
;
233 } else if (width
>= tileInfo
->width
) {
234 GLuint wInTiles
= width
/ tileInfo
->width
;
235 GLubyte
*src
= image
->Data
;
236 GLubyte
*dest
= (GLubyte
*)(t
->bufAddr
+ t
->image
[level
].offset
);
238 for (x
= 0; x
< wInTiles
; ++x
) {
239 if (*dirtyPtr
& dirtyMask
) {
240 savageUploadTile (tileInfo
,
242 height
/ tileInfo
->subHeight
,
243 bpp
, src
, width
* bpp
, dest
);
245 src
+= tileInfo
->width
* bpp
;
246 dest
+= 2048; /* tile size is always 2k */
247 if (dirtyMask
== 1<<31) {
254 savageUploadTile (tileInfo
, width
/ tileInfo
->subWidth
,
255 height
/ tileInfo
->subHeight
, bpp
,
256 image
->Data
, width
* bpp
,
257 (GLubyte
*)(t
->bufAddr
+t
->image
[level
].offset
));
260 GLuint minHeight
, minWidth
, hRepeat
, vRepeat
, x
, y
;
261 if (width
> 4 || height
> 4) {
262 minWidth
= tileInfo
->subWidth
;
263 minHeight
= tileInfo
->subHeight
;
268 hRepeat
= width
>= minWidth
? 1 : minWidth
/ width
;
269 vRepeat
= height
>= minHeight
? 1 : minHeight
/ height
;
270 for (y
= 0; y
< vRepeat
; ++y
) {
271 GLuint offset
= y
* tileInfo
->subWidth
*height
* bpp
;
272 for (x
= 0; x
< hRepeat
; ++x
) {
273 savageUploadTiny (tileInfo
, width
, height
, bpp
, image
->Data
,
274 (GLubyte
*)(t
->bufAddr
+
275 t
->image
[level
].offset
+offset
));
276 offset
+= width
* bpp
;
282 /** \brief Compute the destination size of a texture image
284 static GLuint
savageTexImageSize (GLuint width
, GLuint height
, GLuint bpp
) {
286 if (width
>= 8 && height
>= 8)
287 return width
* height
* bpp
;
288 /* special case for the last three mipmap levels: the hardware computes
289 * the offset internally */
290 else if (width
<= 4 && height
<= 4)
292 /* partially filled sub tiles waste memory
293 * on Savage3D and Savage4 with subtile width 4 every other subtile is
294 * skipped if width < 8 so we can assume a uniform subtile width of 8 */
296 return width
* 8 * bpp
;
297 else if (height
>= 8)
298 return 8 * height
* bpp
;
303 /** \brief Compute the number of (partial) tiles of a texture image
305 static GLuint
savageTexImageTiles (GLuint width
, GLuint height
,
306 const savageTileInfo
*tileInfo
)
308 return (width
+ tileInfo
->width
- 1) / tileInfo
->width
*
309 (height
+ tileInfo
->height
- 1) / tileInfo
->height
;
312 /** \brief Mark dirty tiles
314 * Some care must be taken because tileInfo may not be set or not
315 * up-to-date. So we check if tileInfo is initialized and if the number
316 * of tiles in the bit vector matches the number of tiles computed from
317 * the current tileInfo.
319 static void savageMarkDirtyTiles (savageTexObjPtr t
, GLuint level
,
320 GLuint totalWidth
, GLuint totalHeight
,
321 GLint xoffset
, GLint yoffset
,
322 GLsizei width
, GLsizei height
)
324 GLuint wInTiles
, hInTiles
;
325 GLuint x0
, y0
, x1
, y1
;
329 wInTiles
= (totalWidth
+ t
->tileInfo
->width
- 1) / t
->tileInfo
->width
;
330 hInTiles
= (totalHeight
+ t
->tileInfo
->height
- 1) / t
->tileInfo
->height
;
331 if (wInTiles
* hInTiles
!= t
->image
[level
].nTiles
)
334 x0
= xoffset
/ t
->tileInfo
->width
;
335 y0
= yoffset
/ t
->tileInfo
->height
;
336 x1
= (xoffset
+ width
- 1) / t
->tileInfo
->width
;
337 y1
= (yoffset
+ height
- 1) / t
->tileInfo
->height
;
339 for (y
= y0
; y
<= y1
; ++y
) {
340 GLuint
*ptr
= t
->image
[level
].dirtyTiles
+ (y
* wInTiles
+ x0
) / 32;
341 GLuint mask
= 1 << (y
* wInTiles
+ x0
) % 32;
342 for (x
= x0
; x
<= x1
; ++x
) {
344 if (mask
== (1<<31)) {
354 /** \brief Mark all tiles as dirty
356 static void savageMarkAllTiles (savageTexObjPtr t
, GLuint level
)
358 GLuint words
= (t
->image
[level
].nTiles
+ 31) / 32;
360 memset(t
->image
[level
].dirtyTiles
, ~0, words
*sizeof(GLuint
));
364 static void savageSetTexWrapping(savageTexObjPtr tex
, GLenum s
, GLenum t
)
366 tex
->setup
.sWrapMode
= s
;
367 tex
->setup
.tWrapMode
= t
;
370 static void savageSetTexFilter(savageTexObjPtr t
, GLenum minf
, GLenum magf
)
372 t
->setup
.minFilter
= minf
;
373 t
->setup
.magFilter
= magf
;
379 static void savageSetTexBorderColor(savageTexObjPtr t
, GLubyte color
[4])
381 /* t->Setup[SAVAGE_TEXREG_TEXBORDERCOL] = */
382 /*t->setup.borderColor = SAVAGEPACKCOLOR8888(color[0],color[1],color[2],color[3]); */
387 static savageTexObjPtr
388 savageAllocTexObj( struct gl_texture_object
*texObj
)
392 t
= (savageTexObjPtr
) calloc(1,sizeof(*t
));
393 texObj
->DriverData
= t
;
397 /* Initialize non-image-dependent parts of the state:
399 t
->base
.tObj
= texObj
;
400 t
->base
.dirty_images
[0] = 0;
401 t
->dirtySubImages
= 0;
404 /* Initialize dirty tiles bit vectors
406 for (i
= 0; i
< SAVAGE_TEX_MAXLEVELS
; ++i
)
407 t
->image
[i
].nTiles
= 0;
409 /* FIXME Something here to set initial values for other parts of
413 make_empty_list( &t
->base
);
415 savageSetTexWrapping(t
,texObj
->WrapS
,texObj
->WrapT
);
416 savageSetTexFilter(t
,texObj
->MinFilter
,texObj
->MagFilter
);
417 savageSetTexBorderColor(t
,texObj
->_BorderChan
);
423 /* Called by the _mesa_store_teximage[123]d() functions. */
424 static const struct gl_texture_format
*
425 savageChooseTextureFormat( GLcontext
*ctx
, GLint internalFormat
,
426 GLenum format
, GLenum type
)
428 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
429 const GLboolean do32bpt
=
430 ( imesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_32
);
431 const GLboolean force16bpt
=
432 ( imesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_FORCE_16
);
433 const GLboolean isSavage4
= (imesa
->savageScreen
->chipset
>= S3_SAVAGE4
);
436 switch ( internalFormat
) {
439 case GL_COMPRESSED_RGBA
:
441 case GL_UNSIGNED_INT_10_10_10_2
:
442 case GL_UNSIGNED_INT_2_10_10_10_REV
:
443 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb1555
;
444 case GL_UNSIGNED_SHORT_4_4_4_4
:
445 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
446 return &_mesa_texformat_argb4444
;
447 case GL_UNSIGNED_SHORT_5_5_5_1
:
448 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
449 return &_mesa_texformat_argb1555
;
451 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
;
456 case GL_COMPRESSED_RGB
:
458 case GL_UNSIGNED_SHORT_4_4_4_4
:
459 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
460 return &_mesa_texformat_argb4444
;
461 case GL_UNSIGNED_SHORT_5_5_5_1
:
462 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
463 return &_mesa_texformat_argb1555
;
464 case GL_UNSIGNED_SHORT_5_6_5
:
465 case GL_UNSIGNED_SHORT_5_6_5_REV
:
466 return &_mesa_texformat_rgb565
;
468 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_rgb565
;
475 &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
;
479 &_mesa_texformat_argb8888
: &_mesa_texformat_argb1555
;
483 return &_mesa_texformat_argb4444
;
486 return &_mesa_texformat_argb1555
;
492 return !force16bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_rgb565
;
497 return &_mesa_texformat_rgb565
;
500 case GL_COMPRESSED_ALPHA
:
501 return isSavage4
? &_mesa_texformat_a8
: (
502 do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
);
504 return isSavage4
? &_mesa_texformat_a8
: &_mesa_texformat_argb4444
;
508 return isSavage4
? &_mesa_texformat_a8
: (
509 !force16bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
);
513 case GL_COMPRESSED_LUMINANCE
:
514 /* no alpha, but use argb1555 in 16bit case to get pure grey values */
515 return isSavage4
? &_mesa_texformat_l8
: (
516 do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb1555
);
518 return isSavage4
? &_mesa_texformat_l8
: &_mesa_texformat_argb1555
;
522 return isSavage4
? &_mesa_texformat_l8
: (
523 !force16bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb1555
);
526 case GL_LUMINANCE_ALPHA
:
527 case GL_COMPRESSED_LUMINANCE_ALPHA
:
528 /* Savage4 has a al44 texture format. But it's not supported by Mesa. */
529 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
;
530 case GL_LUMINANCE4_ALPHA4
:
531 case GL_LUMINANCE6_ALPHA2
:
532 return &_mesa_texformat_argb4444
;
533 case GL_LUMINANCE8_ALPHA8
:
534 case GL_LUMINANCE12_ALPHA4
:
535 case GL_LUMINANCE12_ALPHA12
:
536 case GL_LUMINANCE16_ALPHA16
:
537 return !force16bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
;
540 case GL_COMPRESSED_INTENSITY
:
541 return isSavage4
? &_mesa_texformat_i8
: (
542 do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
);
544 return isSavage4
? &_mesa_texformat_i8
: &_mesa_texformat_argb4444
;
548 return isSavage4
? &_mesa_texformat_i8
: (
549 !force16bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
);
552 case GL_COLOR_INDEX1_EXT:
553 case GL_COLOR_INDEX2_EXT:
554 case GL_COLOR_INDEX4_EXT:
555 case GL_COLOR_INDEX8_EXT:
556 case GL_COLOR_INDEX12_EXT:
557 case GL_COLOR_INDEX16_EXT:
558 return &_mesa_texformat_ci8;
561 _mesa_problem(ctx
, "unexpected texture format in %s", __FUNCTION__
);
566 static void savageSetTexImages( savageContextPtr imesa
,
567 const struct gl_texture_object
*tObj
)
569 savageTexObjPtr t
= (savageTexObjPtr
) tObj
->DriverData
;
570 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
571 GLuint offset
, i
, textureFormat
, size
;
572 GLint firstLevel
, lastLevel
;
577 switch (image
->TexFormat
->MesaFormat
) {
578 case MESA_FORMAT_ARGB8888
:
579 textureFormat
= TFT_ARGB8888
;
582 case MESA_FORMAT_ARGB1555
:
583 textureFormat
= TFT_ARGB1555
;
586 case MESA_FORMAT_ARGB4444
:
587 textureFormat
= TFT_ARGB4444
;
590 case MESA_FORMAT_RGB565
:
591 textureFormat
= TFT_RGB565
;
595 textureFormat
= TFT_L8
;
599 textureFormat
= TFT_I8
;
603 textureFormat
= TFT_A8
;
607 _mesa_problem(imesa
->glCtx
, "Bad texture format in %s", __FUNCTION__
);
610 t
->hwFormat
= textureFormat
;
612 /* Select tiling format depending on the chipset and bytes per texel */
613 if (imesa
->savageScreen
->chipset
<= S3_SAVAGE4
)
614 t
->tileInfo
= &tileInfo_s3d_s4
[t
->texelBytes
];
616 t
->tileInfo
= &tileInfo_pro
[t
->texelBytes
];
618 /* Compute which mipmap levels we really want to send to the hardware.
620 driCalculateTextureFirstLastLevel( &t
->base
);
621 firstLevel
= t
->base
.firstLevel
;
622 lastLevel
= t
->base
.lastLevel
;
624 /* Figure out the size now (and count the levels). Upload won't be
625 * done until later. If the number of tiles changes, it means that
626 * this function is called for the first time on this tex object or
627 * the image or the destination color format changed. So all tiles
628 * are marked as dirty.
632 for ( i
= firstLevel
; i
<= lastLevel
&& tObj
->Image
[0][i
] ; i
++ ) {
634 nTiles
= savageTexImageTiles (image
->Width2
, image
->Height2
, t
->tileInfo
);
635 if (t
->image
[i
].nTiles
!= nTiles
) {
636 GLuint words
= (nTiles
+ 31) / 32;
637 if (t
->image
[i
].nTiles
!= 0) {
638 free(t
->image
[i
].dirtyTiles
);
640 t
->image
[i
].dirtyTiles
= malloc(words
*sizeof(GLuint
));
641 memset(t
->image
[i
].dirtyTiles
, ~0, words
*sizeof(GLuint
));
643 t
->image
[i
].nTiles
= nTiles
;
645 t
->image
[i
].offset
= offset
;
647 image
= tObj
->Image
[0][i
];
648 size
= savageTexImageSize (image
->Width2
, image
->Height2
,
653 t
->base
.lastLevel
= i
-1;
654 t
->base
.totalSize
= offset
;
655 /* the last three mipmap levels don't add to the offset. They are packed
658 t
->base
.totalSize
+= 64 * t
->texelBytes
;
659 /* 2k-aligned (really needed?) */
660 t
->base
.totalSize
= (t
->base
.totalSize
+ 2047UL) & ~2047UL;
663 void savageDestroyTexObj(savageContextPtr imesa
, savageTexObjPtr t
)
667 /* Free dirty tiles bit vectors */
668 for (i
= 0; i
< SAVAGE_TEX_MAXLEVELS
; ++i
) {
669 if (t
->image
[i
].nTiles
)
670 free (t
->image
[i
].dirtyTiles
);
673 /* See if it was the driver's current object.
677 for ( i
= 0 ; i
< imesa
->glCtx
->Const
.MaxTextureUnits
; i
++ )
679 if ( &t
->base
== imesa
->CurrentTexObj
[ i
] ) {
680 assert( t
->base
.bound
& (1 << i
) );
681 imesa
->CurrentTexObj
[ i
] = NULL
;
687 /* Upload a texture's images to one of the texture heaps. May have to
688 * eject our own and/or other client's texture objects to make room
691 static void savageUploadTexImages( savageContextPtr imesa
, savageTexObjPtr t
)
693 const GLint numLevels
= t
->base
.lastLevel
- t
->base
.firstLevel
+ 1;
698 LOCK_HARDWARE(imesa
);
700 /* Do we need to eject LRU texture objects?
702 if (!t
->base
.memBlock
) {
706 heap
= driAllocateTexture(imesa
->textureHeaps
, imesa
->lastTexHeap
,
707 (driTextureObject
*)t
);
709 UNLOCK_HARDWARE(imesa
);
713 ofs
= t
->base
.memBlock
->ofs
;
714 t
->setup
.physAddr
= imesa
->savageScreen
->textureOffset
[heap
] + ofs
;
715 t
->bufAddr
= (char *)((GLuint
) imesa
->savageScreen
->texVirtual
[heap
] + ofs
);
716 imesa
->dirty
|= SAVAGE_UPLOAD_GLOBAL
; /* FIXME: really needed? */
719 /* Let the world know we've used this memory recently.
721 driUpdateTextureLRU( &t
->base
);
722 UNLOCK_HARDWARE(imesa
);
724 if (t
->base
.dirty_images
[0] || t
->dirtySubImages
) {
725 if (SAVAGE_DEBUG
& DEBUG_VERBOSE_TEX
)
726 fprintf(stderr
, "Texture upload: |");
728 savageFlushVertices (imesa
);
729 LOCK_HARDWARE(imesa
);
730 savageFlushCmdBufLocked (imesa
, GL_FALSE
);
731 WAIT_IDLE_EMPTY_LOCKED(imesa
);
733 for (i
= 0 ; i
< numLevels
; i
++) {
734 const GLint j
= t
->base
.firstLevel
+ i
; /* the texObj's level */
735 if (t
->base
.dirty_images
[0] & (1 << j
)) {
736 savageMarkAllTiles(t
, j
);
737 if (SAVAGE_DEBUG
& DEBUG_VERBOSE_TEX
)
738 fprintf (stderr
, "*");
739 } else if (SAVAGE_DEBUG
& DEBUG_VERBOSE_TEX
) {
740 if (t
->dirtySubImages
& (1 << j
))
741 fprintf (stderr
, ".");
743 fprintf (stderr
, " ");
745 if ((t
->base
.dirty_images
[0] | t
->dirtySubImages
) & (1 << j
))
746 savageUploadTexLevel( t
, j
);
749 UNLOCK_HARDWARE(imesa
);
750 t
->base
.dirty_images
[0] = 0;
751 t
->dirtySubImages
= 0;
753 if (SAVAGE_DEBUG
& DEBUG_VERBOSE_TEX
)
754 fprintf(stderr
, "|\n");
761 static void savageUpdateTex0State_s4( GLcontext
*ctx
)
763 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
764 struct gl_texture_object
*tObj
;
765 struct gl_texture_image
*image
;
770 if (ctx
->Texture
.Unit
[0]._ReallyEnabled
== 0) {
771 imesa
->regs
.s4
.texDescr
.ni
.tex0En
= GL_FALSE
;
772 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_NoTexMap
;
773 imesa
->regs
.s4
.texCtrl
[0].ui
= 0x20f040;
777 tObj
= ctx
->Texture
.Unit
[0]._Current
;
778 if ((ctx
->Texture
.Unit
[0]._ReallyEnabled
& ~(TEXTURE_1D_BIT
|TEXTURE_2D_BIT
))
779 || tObj
->Image
[0][tObj
->BaseLevel
]->Border
> 0) {
780 /* 3D texturing enabled, or texture border - fallback */
781 FALLBACK (ctx
, SAVAGE_FALLBACK_TEXTURE
, GL_TRUE
);
785 /* Do 2D texture setup */
787 t
= tObj
->DriverData
;
789 t
= savageAllocTexObj( tObj
);
794 imesa
->CurrentTexObj
[0] = &t
->base
;
797 if (t
->base
.dirty_images
[0] || t
->dirtySubImages
) {
798 savageSetTexImages(imesa
, tObj
);
799 savageUploadTexImages(imesa
, t
);
802 driUpdateTextureLRU( &t
->base
);
804 format
= tObj
->Image
[0][tObj
->BaseLevel
]->Format
;
806 switch (ctx
->Texture
.Unit
[0].EnvMode
) {
808 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_FALSE
;
813 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_Decal
;
816 case GL_LUMINANCE_ALPHA
:
819 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_Copy
;
823 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_CopyAlpha
;
826 __HWEnvCombineSingleUnitScale(imesa
, 0, 0,
827 &imesa
->regs
.s4
.texBlendCtrl
[0]);
831 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_FALSE
;
836 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_Decal
;
841 case GL_LUMINANCE_ALPHA
:
842 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_DecalAlpha
;
846 GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_INTENSITY
847 are undefined with GL_DECAL
851 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_CopyAlpha
;
854 __HWEnvCombineSingleUnitScale(imesa
, 0, 0,
855 &imesa
->regs
.s4
.texBlendCtrl
[0]);
859 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_FALSE
;
860 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_ModulAlpha
;
861 __HWEnvCombineSingleUnitScale(imesa
, 0, 0,
862 &imesa
->regs
.s4
.texBlendCtrl
[0]);
870 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_ModulAlpha
;
871 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_FALSE
;
876 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_Blend0
;
877 imesa
->regs
.s4
.texDescr
.ni
.tex1En
= GL_TRUE
;
878 imesa
->regs
.s4
.texDescr
.ni
.texBLoopEn
= GL_TRUE
;
879 imesa
->regs
.s4
.texDescr
.ni
.tex1Width
=
880 imesa
->regs
.s4
.texDescr
.ni
.tex0Width
;
881 imesa
->regs
.s4
.texDescr
.ni
.tex1Height
=
882 imesa
->regs
.s4
.texDescr
.ni
.tex0Height
;
883 imesa
->regs
.s4
.texDescr
.ni
.tex1Fmt
=
884 imesa
->regs
.s4
.texDescr
.ni
.tex0Fmt
;
886 imesa
->regs
.s4
.texAddr
[1].ui
= imesa
->regs
.s4
.texAddr
[0].ui
;
887 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_Blend1
;
889 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_TRUE
;
890 imesa
->bTexEn1
= GL_TRUE
;
893 case GL_LUMINANCE_ALPHA
:
895 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_BlendAlpha0
;
896 imesa
->regs
.s4
.texDescr
.ni
.tex1En
= GL_TRUE
;
897 imesa
->regs
.s4
.texDescr
.ni
.texBLoopEn
= GL_TRUE
;
898 imesa
->regs
.s4
.texDescr
.ni
.tex1Width
=
899 imesa
->regs
.s4
.texDescr
.ni
.tex0Width
;
900 imesa
->regs
.s4
.texDescr
.ni
.tex1Height
=
901 imesa
->regs
.s4
.texDescr
.ni
.tex0Height
;
902 imesa
->regs
.s4
.texDescr
.ni
.tex1Fmt
=
903 imesa
->regs
.s4
.texDescr
.ni
.tex0Fmt
;
905 imesa
->regs
.s4
.texAddr
[1].ui
= imesa
->regs
.s4
.texAddr
[0].ui
;
906 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_BlendAlpha1
;
908 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_TRUE
;
909 imesa
->bTexEn1
= GL_TRUE
;
913 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_BlendInt0
;
914 imesa
->regs
.s4
.texDescr
.ni
.tex1En
= GL_TRUE
;
915 imesa
->regs
.s4
.texDescr
.ni
.texBLoopEn
= GL_TRUE
;
916 imesa
->regs
.s4
.texDescr
.ni
.tex1Width
=
917 imesa
->regs
.s4
.texDescr
.ni
.tex0Width
;
918 imesa
->regs
.s4
.texDescr
.ni
.tex1Height
=
919 imesa
->regs
.s4
.texDescr
.ni
.tex0Height
;
920 imesa
->regs
.s4
.texDescr
.ni
.tex1Fmt
=
921 imesa
->regs
.s4
.texDescr
.ni
.tex0Fmt
;
923 imesa
->regs
.s4
.texAddr
[1].ui
= imesa
->regs
.s4
.texAddr
[0].ui
;
924 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_BlendInt1
;
926 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_TRUE
;
927 imesa
->regs
.s4
.texCtrl
[0].ni
.alphaArg1Invert
= GL_TRUE
;
928 imesa
->bTexEn1
= GL_TRUE
;
931 __HWEnvCombineSingleUnitScale(imesa
, 0, 0,
932 &imesa
->regs
.s4
.texBlendCtrl
[0]);
939 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_FALSE
;
940 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_AddAlpha
;
941 __HWEnvCombineSingleUnitScale(imesa
, 0, 0,
942 &imesa
->regs
.s4
.texBlendCtrl
[0]);
945 #if GL_ARB_texture_env_combine
947 __HWParseTexEnvCombine(imesa
, 0, &imesa
->regs
.s4
.texCtrl
[0],
948 &imesa
->regs
.s4
.texBlendCtrl
[0]);
953 fprintf(stderr
, "unknown tex env mode");
958 imesa
->regs
.s4
.texCtrl
[0].ni
.uMode
=
959 t
->setup
.sWrapMode
== GL_REPEAT
? 0 : 1;
960 imesa
->regs
.s4
.texCtrl
[0].ni
.vMode
=
961 t
->setup
.tWrapMode
== GL_REPEAT
? 0 : 1;
963 switch (t
->setup
.minFilter
)
966 imesa
->regs
.s4
.texCtrl
[0].ni
.filterMode
= TFM_Point
;
967 imesa
->regs
.s4
.texCtrl
[0].ni
.mipmapEnable
= GL_FALSE
;
971 imesa
->regs
.s4
.texCtrl
[0].ni
.filterMode
= TFM_Bilin
;
972 imesa
->regs
.s4
.texCtrl
[0].ni
.mipmapEnable
= GL_FALSE
;
975 case GL_NEAREST_MIPMAP_NEAREST
:
976 imesa
->regs
.s4
.texCtrl
[0].ni
.filterMode
= TFM_Point
;
977 imesa
->regs
.s4
.texCtrl
[0].ni
.mipmapEnable
= GL_TRUE
;
980 case GL_LINEAR_MIPMAP_NEAREST
:
981 imesa
->regs
.s4
.texCtrl
[0].ni
.filterMode
= TFM_Bilin
;
982 imesa
->regs
.s4
.texCtrl
[0].ni
.mipmapEnable
= GL_TRUE
;
985 case GL_NEAREST_MIPMAP_LINEAR
:
986 case GL_LINEAR_MIPMAP_LINEAR
:
987 imesa
->regs
.s4
.texCtrl
[0].ni
.filterMode
= TFM_Trilin
;
988 imesa
->regs
.s4
.texCtrl
[0].ni
.mipmapEnable
= GL_TRUE
;
992 if((ctx
->Texture
.Unit
[0].LodBias
!=0.0F
) ||
993 (imesa
->regs
.s4
.texCtrl
[0].ni
.dBias
!= 0))
995 int bias
= (int)(ctx
->Texture
.Unit
[0].LodBias
* 32.0);
1000 imesa
->regs
.s4
.texCtrl
[0].ni
.dBias
= bias
& 0x1ff;
1003 image
= tObj
->Image
[0][tObj
->BaseLevel
];
1004 imesa
->regs
.s4
.texDescr
.ni
.tex0En
= GL_TRUE
;
1005 imesa
->regs
.s4
.texDescr
.ni
.tex0Width
= image
->WidthLog2
;
1006 imesa
->regs
.s4
.texDescr
.ni
.tex0Height
= image
->HeightLog2
;
1007 imesa
->regs
.s4
.texDescr
.ni
.tex0Fmt
= t
->hwFormat
;
1008 imesa
->regs
.s4
.texCtrl
[0].ni
.dMax
= t
->base
.lastLevel
- t
->base
.firstLevel
;
1010 if (imesa
->regs
.s4
.texDescr
.ni
.tex1En
)
1011 imesa
->regs
.s4
.texDescr
.ni
.texBLoopEn
= GL_TRUE
;
1013 imesa
->regs
.s4
.texAddr
[0].ui
= (u_int32_t
) t
->setup
.physAddr
| 0x2;
1014 if(t
->base
.heap
->heapId
== SAVAGE_AGP_HEAP
)
1015 imesa
->regs
.s4
.texAddr
[0].ui
|= 0x1;
1019 static void savageUpdateTex1State_s4( GLcontext
*ctx
)
1021 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
1022 struct gl_texture_object
*tObj
;
1023 struct gl_texture_image
*image
;
1030 imesa
->bTexEn1
= GL_FALSE
;
1034 if (ctx
->Texture
.Unit
[1]._ReallyEnabled
== 0) {
1035 imesa
->regs
.s4
.texDescr
.ni
.tex1En
= GL_FALSE
;
1036 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_NoTexMap1
;
1037 imesa
->regs
.s4
.texCtrl
[1].ui
= 0x20f040;
1038 imesa
->regs
.s4
.texDescr
.ni
.texBLoopEn
= GL_FALSE
;
1042 tObj
= ctx
->Texture
.Unit
[1]._Current
;
1044 if ((ctx
->Texture
.Unit
[1]._ReallyEnabled
& ~(TEXTURE_1D_BIT
|TEXTURE_2D_BIT
))
1045 || tObj
->Image
[0][tObj
->BaseLevel
]->Border
> 0) {
1046 /* 3D texturing enabled, or texture border - fallback */
1047 FALLBACK (ctx
, SAVAGE_FALLBACK_TEXTURE
, GL_TRUE
);
1051 /* Do 2D texture setup */
1053 t
= tObj
->DriverData
;
1055 t
= savageAllocTexObj( tObj
);
1060 imesa
->CurrentTexObj
[1] = &t
->base
;
1064 if (t
->base
.dirty_images
[0] || t
->dirtySubImages
) {
1065 savageSetTexImages(imesa
, tObj
);
1066 savageUploadTexImages(imesa
, t
);
1069 driUpdateTextureLRU( &t
->base
);
1071 format
= tObj
->Image
[0][tObj
->BaseLevel
]->Format
;
1073 switch (ctx
->Texture
.Unit
[1].EnvMode
) {
1075 imesa
->regs
.s4
.texCtrl
[1].ni
.clrArg1Invert
= GL_FALSE
;
1080 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_Decal
;
1083 case GL_LUMINANCE_ALPHA
:
1086 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_Copy
;
1090 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_CopyAlpha1
;
1093 __HWEnvCombineSingleUnitScale(imesa
, 0, 1, &imesa
->regs
.s4
.texBlendCtrl
);
1096 imesa
->regs
.s4
.texCtrl
[1].ni
.clrArg1Invert
= GL_FALSE
;
1097 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_ModulAlpha1
;
1098 __HWEnvCombineSingleUnitScale(imesa
, 0, 1, &imesa
->regs
.s4
.texBlendCtrl
);
1101 /*#if GL_EXT_texture_env_add*/
1103 imesa
->regs
.s4
.texCtrl
[1].ni
.clrArg1Invert
= GL_FALSE
;
1104 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_AddAlpha1
;
1105 __HWEnvCombineSingleUnitScale(imesa
, 0, 1, &imesa
->regs
.s4
.texBlendCtrl
);
1109 #if GL_ARB_texture_env_combine
1110 case GL_COMBINE_ARB
:
1111 __HWParseTexEnvCombine(imesa
, 1, &texCtrl
, &imesa
->regs
.s4
.texBlendCtrl
);
1116 imesa
->regs
.s4
.texCtrl
[1].ni
.clrArg1Invert
= GL_FALSE
;
1122 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_Decal1
;
1124 case GL_LUMINANCE_ALPHA
:
1127 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_DecalAlpha1
;
1131 // GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_INTENSITY
1132 // are undefined with GL_DECAL
1135 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_CopyAlpha1
;
1138 __HWEnvCombineSingleUnitScale(imesa
, 0, 1, &imesa
->regs
.s4
.texBlendCtrl
);
1142 if (format
== GL_LUMINANCE
)
1145 // This is a hack for GLQuake, invert.
1147 imesa
->regs
.s4
.texCtrl
[1].ni
.clrArg1Invert
= GL_TRUE
;
1148 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= 0;
1150 __HWEnvCombineSingleUnitScale(imesa
, 0, 1, &imesa
->regs
.s4
.texBlendCtrl
);
1154 fprintf(stderr
, "unkown tex 1 env mode\n");
1159 imesa
->regs
.s4
.texCtrl
[1].ni
.uMode
=
1160 t
->setup
.sWrapMode
== GL_REPEAT
? 0 : 1;
1161 imesa
->regs
.s4
.texCtrl
[1].ni
.vMode
=
1162 t
->setup
.tWrapMode
== GL_REPEAT
? 0 : 1;
1164 switch (t
->setup
.minFilter
)
1167 imesa
->regs
.s4
.texCtrl
[1].ni
.filterMode
= TFM_Point
;
1168 imesa
->regs
.s4
.texCtrl
[1].ni
.mipmapEnable
= GL_FALSE
;
1172 imesa
->regs
.s4
.texCtrl
[1].ni
.filterMode
= TFM_Bilin
;
1173 imesa
->regs
.s4
.texCtrl
[1].ni
.mipmapEnable
= GL_FALSE
;
1176 case GL_NEAREST_MIPMAP_NEAREST
:
1177 imesa
->regs
.s4
.texCtrl
[1].ni
.filterMode
= TFM_Point
;
1178 imesa
->regs
.s4
.texCtrl
[1].ni
.mipmapEnable
= GL_TRUE
;
1181 case GL_LINEAR_MIPMAP_NEAREST
:
1182 imesa
->regs
.s4
.texCtrl
[1].ni
.filterMode
= TFM_Bilin
;
1183 imesa
->regs
.s4
.texCtrl
[1].ni
.mipmapEnable
= GL_TRUE
;
1186 case GL_NEAREST_MIPMAP_LINEAR
:
1187 case GL_LINEAR_MIPMAP_LINEAR
:
1188 imesa
->regs
.s4
.texCtrl
[1].ni
.filterMode
= TFM_Trilin
;
1189 imesa
->regs
.s4
.texCtrl
[1].ni
.mipmapEnable
= GL_TRUE
;
1193 if((ctx
->Texture
.Unit
[1].LodBias
!=0.0F
) ||
1194 (imesa
->regs
.s4
.texCtrl
[1].ni
.dBias
!= 0))
1196 int bias
= (int)(ctx
->Texture
.Unit
[1].LodBias
* 32.0);
1199 else if (bias
> 255)
1201 imesa
->regs
.s4
.texCtrl
[1].ni
.dBias
= bias
& 0x1ff;
1204 image
= tObj
->Image
[0][tObj
->BaseLevel
];
1205 imesa
->regs
.s4
.texDescr
.ni
.tex1En
= GL_TRUE
;
1206 imesa
->regs
.s4
.texDescr
.ni
.tex1Width
= image
->WidthLog2
;
1207 imesa
->regs
.s4
.texDescr
.ni
.tex1Height
= image
->HeightLog2
;
1208 imesa
->regs
.s4
.texDescr
.ni
.tex1Fmt
= t
->hwFormat
;
1209 imesa
->regs
.s4
.texCtrl
[1].ni
.dMax
= t
->base
.lastLevel
- t
->base
.firstLevel
;
1210 imesa
->regs
.s4
.texDescr
.ni
.texBLoopEn
= GL_TRUE
;
1212 imesa
->regs
.s4
.texAddr
[1].ui
= (u_int32_t
) t
->setup
.physAddr
| 2;
1213 if(t
->base
.heap
->heapId
== SAVAGE_AGP_HEAP
)
1214 imesa
->regs
.s4
.texAddr
[1].ui
|= 0x1;
1216 static void savageUpdateTexState_s3d( GLcontext
*ctx
)
1218 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
1219 struct gl_texture_object
*tObj
;
1220 struct gl_texture_image
*image
;
1225 if (ctx
->Texture
.Unit
[0]._ReallyEnabled
== 0) {
1226 imesa
->regs
.s3d
.texCtrl
.ui
= 0;
1227 imesa
->regs
.s3d
.texCtrl
.ni
.texEn
= GL_FALSE
;
1228 imesa
->regs
.s3d
.texCtrl
.ni
.dBias
= 0x08;
1229 imesa
->regs
.s3d
.texCtrl
.ni
.texXprEn
= GL_TRUE
;
1233 tObj
= ctx
->Texture
.Unit
[0]._Current
;
1234 if ((ctx
->Texture
.Unit
[0]._ReallyEnabled
& ~(TEXTURE_1D_BIT
|TEXTURE_2D_BIT
))
1235 || tObj
->Image
[0][tObj
->BaseLevel
]->Border
> 0) {
1236 /* 3D texturing enabled, or texture border - fallback */
1237 FALLBACK (ctx
, SAVAGE_FALLBACK_TEXTURE
, GL_TRUE
);
1241 /* Do 2D texture setup */
1242 t
= tObj
->DriverData
;
1244 t
= savageAllocTexObj( tObj
);
1249 imesa
->CurrentTexObj
[0] = &t
->base
;
1252 if (t
->base
.dirty_images
[0] || t
->dirtySubImages
) {
1253 savageSetTexImages(imesa
, tObj
);
1254 savageUploadTexImages(imesa
, t
);
1257 driUpdateTextureLRU( &t
->base
);
1259 format
= tObj
->Image
[0][tObj
->BaseLevel
]->Format
;
1261 /* FIXME: copied from utah-glx, probably needs some tuning */
1262 switch (ctx
->Texture
.Unit
[0].EnvMode
) {
1264 imesa
->regs
.s3d
.drawCtrl
.ni
.texBlendCtrl
= SAVAGETBC_DECAL_S3D
;
1267 imesa
->regs
.s3d
.drawCtrl
.ni
.texBlendCtrl
= SAVAGETBC_COPY_S3D
;
1269 case GL_BLEND
: /* FIXIT */
1271 imesa
->regs
.s3d
.drawCtrl
.ni
.texBlendCtrl
= SAVAGETBC_MODULATEALPHA_S3D
;
1274 fprintf(stderr
, "unkown tex env mode\n");
1279 imesa
->regs
.s3d
.drawCtrl
.ni
.flushPdDestWrites
= GL_TRUE
;
1280 imesa
->regs
.s3d
.drawCtrl
.ni
.flushPdZbufWrites
= GL_TRUE
;
1282 /* FIXME: this is how the utah-driver works. I doubt it's the ultimate
1284 imesa
->regs
.s3d
.texCtrl
.ni
.uWrapEn
= 0;
1285 imesa
->regs
.s3d
.texCtrl
.ni
.vWrapEn
= 0;
1286 if (t
->setup
.sWrapMode
== GL_CLAMP
)
1287 imesa
->regs
.s3d
.texCtrl
.ni
.wrapMode
= TAM_Clamp
;
1289 imesa
->regs
.s3d
.texCtrl
.ni
.wrapMode
= TAM_Wrap
;
1291 switch (t
->setup
.minFilter
) {
1293 imesa
->regs
.s3d
.texCtrl
.ni
.filterMode
= TFM_Point
;
1294 imesa
->regs
.s3d
.texCtrl
.ni
.mipmapDisable
= GL_TRUE
;
1298 imesa
->regs
.s3d
.texCtrl
.ni
.filterMode
= TFM_Bilin
;
1299 imesa
->regs
.s3d
.texCtrl
.ni
.mipmapDisable
= GL_TRUE
;
1302 case GL_NEAREST_MIPMAP_NEAREST
:
1303 imesa
->regs
.s3d
.texCtrl
.ni
.filterMode
= TFM_Point
;
1304 imesa
->regs
.s3d
.texCtrl
.ni
.mipmapDisable
= GL_FALSE
;
1307 case GL_LINEAR_MIPMAP_NEAREST
:
1308 imesa
->regs
.s3d
.texCtrl
.ni
.filterMode
= TFM_Bilin
;
1309 imesa
->regs
.s3d
.texCtrl
.ni
.mipmapDisable
= GL_FALSE
;
1312 case GL_NEAREST_MIPMAP_LINEAR
:
1313 case GL_LINEAR_MIPMAP_LINEAR
:
1314 imesa
->regs
.s3d
.texCtrl
.ni
.filterMode
= TFM_Trilin
;
1315 imesa
->regs
.s3d
.texCtrl
.ni
.mipmapDisable
= GL_FALSE
;
1319 /* There is no way to specify a maximum mipmap level. We may have to
1320 disable mipmapping completely. */
1322 if (t->max_level < t->image[0].image->WidthLog2 ||
1323 t->max_level < t->image[0].image->HeightLog2) {
1324 texCtrl.ni.mipmapEnable = GL_TRUE;
1325 if (texCtrl.ni.filterMode == TFM_Trilin)
1326 texCtrl.ni.filterMode = TFM_Bilin;
1327 texCtrl.ni.filterMode = TFM_Point;
1331 if((ctx
->Texture
.Unit
[0].LodBias
!=0.0F
) ||
1332 (imesa
->regs
.s3d
.texCtrl
.ni
.dBias
!= 0))
1334 int bias
= (int)(ctx
->Texture
.Unit
[0].LodBias
* 16.0);
1337 else if (bias
> 255)
1339 imesa
->regs
.s3d
.texCtrl
.ni
.dBias
= bias
& 0x1ff;
1342 image
= tObj
->Image
[0][tObj
->BaseLevel
];
1343 imesa
->regs
.s3d
.texCtrl
.ni
.texEn
= GL_TRUE
;
1344 imesa
->regs
.s3d
.texDescr
.ni
.texWidth
= image
->WidthLog2
;
1345 imesa
->regs
.s3d
.texDescr
.ni
.texHeight
= image
->HeightLog2
;
1346 assert (t
->hwFormat
<= 7);
1347 imesa
->regs
.s3d
.texDescr
.ni
.texFmt
= t
->hwFormat
;
1349 imesa
->regs
.s3d
.texAddr
.ui
= (u_int32_t
) t
->setup
.physAddr
| 2;
1350 if(t
->base
.heap
->heapId
== SAVAGE_AGP_HEAP
)
1351 imesa
->regs
.s3d
.texAddr
.ui
|= 0x1;
1356 static void savageUpdateTextureState_s4( GLcontext
*ctx
)
1358 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
1359 if (imesa
->CurrentTexObj
[0]) imesa
->CurrentTexObj
[0]->bound
&= ~1;
1360 if (imesa
->CurrentTexObj
[1]) imesa
->CurrentTexObj
[1]->bound
&= ~2;
1361 imesa
->CurrentTexObj
[0] = 0;
1362 imesa
->CurrentTexObj
[1] = 0;
1363 savageUpdateTex0State_s4( ctx
);
1364 savageUpdateTex1State_s4( ctx
);
1365 imesa
->dirty
|= (SAVAGE_UPLOAD_TEX0
|
1366 SAVAGE_UPLOAD_TEX1
);
1368 static void savageUpdateTextureState_s3d( GLcontext
*ctx
)
1370 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
1371 if (imesa
->CurrentTexObj
[0]) imesa
->CurrentTexObj
[0]->bound
&= ~1;
1372 imesa
->CurrentTexObj
[0] = 0;
1373 savageUpdateTexState_s3d( ctx
);
1374 imesa
->dirty
|= (SAVAGE_UPLOAD_TEX0
);
1376 void savageUpdateTextureState( GLcontext
*ctx
)
1378 savageContextPtr imesa
= SAVAGE_CONTEXT( ctx
);
1379 FALLBACK (ctx
, SAVAGE_FALLBACK_TEXTURE
, GL_FALSE
);
1380 FALLBACK(ctx
, SAVAGE_FALLBACK_PROJ_TEXTURE
, GL_FALSE
);
1381 if (imesa
->savageScreen
->chipset
>= S3_SAVAGE4
)
1382 savageUpdateTextureState_s4 (ctx
);
1384 savageUpdateTextureState_s3d (ctx
);
1389 /*****************************************
1391 *****************************************/
1393 static void savageTexEnv( GLcontext
*ctx
, GLenum target
,
1394 GLenum pname
, const GLfloat
*param
)
1396 savageContextPtr imesa
= SAVAGE_CONTEXT( ctx
);
1398 if (pname
== GL_TEXTURE_ENV_MODE
) {
1400 imesa
->new_state
|= SAVAGE_NEW_TEXTURE
;
1402 } else if (pname
== GL_TEXTURE_ENV_COLOR
) {
1404 struct gl_texture_unit
*texUnit
=
1405 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1406 const GLfloat
*fc
= texUnit
->EnvColor
;
1407 GLuint r
, g
, b
, a
, col
;
1408 CLAMPED_FLOAT_TO_UBYTE(r
, fc
[0]);
1409 CLAMPED_FLOAT_TO_UBYTE(g
, fc
[1]);
1410 CLAMPED_FLOAT_TO_UBYTE(b
, fc
[2]);
1411 CLAMPED_FLOAT_TO_UBYTE(a
, fc
[3]);
1422 static void savageTexImage1D( GLcontext
*ctx
, GLenum target
, GLint level
,
1423 GLint internalFormat
,
1424 GLint width
, GLint border
,
1425 GLenum format
, GLenum type
, const GLvoid
*pixels
,
1426 const struct gl_pixelstore_attrib
*packing
,
1427 struct gl_texture_object
*texObj
,
1428 struct gl_texture_image
*texImage
)
1430 savageTexObjPtr t
= (savageTexObjPtr
) texObj
->DriverData
;
1432 /* Do nothing. Marking the image as dirty below is sufficient. */
1434 t
= savageAllocTexObj(texObj
);
1436 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
1440 _mesa_store_teximage1d( ctx
, target
, level
, internalFormat
,
1441 width
, border
, format
, type
,
1442 pixels
, packing
, texObj
, texImage
);
1443 t
->base
.dirty_images
[0] |= (1 << level
);
1444 SAVAGE_CONTEXT(ctx
)->new_state
|= SAVAGE_NEW_TEXTURE
;
1447 static void savageTexSubImage1D( GLcontext
*ctx
,
1452 GLenum format
, GLenum type
,
1453 const GLvoid
*pixels
,
1454 const struct gl_pixelstore_attrib
*packing
,
1455 struct gl_texture_object
*texObj
,
1456 struct gl_texture_image
*texImage
)
1458 savageTexObjPtr t
= (savageTexObjPtr
) texObj
->DriverData
;
1459 assert( t
); /* this _should_ be true */
1461 savageMarkDirtyTiles(t
, level
, texImage
->Width2
, 1,
1462 xoffset
, 0, width
, 1);
1464 t
= savageAllocTexObj(texObj
);
1466 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
1469 t
->base
.dirty_images
[0] |= (1 << level
);
1471 _mesa_store_texsubimage1d(ctx
, target
, level
, xoffset
, width
,
1472 format
, type
, pixels
, packing
, texObj
,
1474 t
->dirtySubImages
|= (1 << level
);
1475 SAVAGE_CONTEXT(ctx
)->new_state
|= SAVAGE_NEW_TEXTURE
;
1478 static void savageTexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
1479 GLint internalFormat
,
1480 GLint width
, GLint height
, GLint border
,
1481 GLenum format
, GLenum type
, const GLvoid
*pixels
,
1482 const struct gl_pixelstore_attrib
*packing
,
1483 struct gl_texture_object
*texObj
,
1484 struct gl_texture_image
*texImage
)
1486 savageTexObjPtr t
= (savageTexObjPtr
) texObj
->DriverData
;
1488 /* Do nothing. Marking the image as dirty below is sufficient. */
1490 t
= savageAllocTexObj(texObj
);
1492 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
1496 _mesa_store_teximage2d( ctx
, target
, level
, internalFormat
,
1497 width
, height
, border
, format
, type
,
1498 pixels
, packing
, texObj
, texImage
);
1499 t
->base
.dirty_images
[0] |= (1 << level
);
1500 SAVAGE_CONTEXT(ctx
)->new_state
|= SAVAGE_NEW_TEXTURE
;
1503 static void savageTexSubImage2D( GLcontext
*ctx
,
1506 GLint xoffset
, GLint yoffset
,
1507 GLsizei width
, GLsizei height
,
1508 GLenum format
, GLenum type
,
1509 const GLvoid
*pixels
,
1510 const struct gl_pixelstore_attrib
*packing
,
1511 struct gl_texture_object
*texObj
,
1512 struct gl_texture_image
*texImage
)
1514 savageTexObjPtr t
= (savageTexObjPtr
) texObj
->DriverData
;
1515 assert( t
); /* this _should_ be true */
1517 savageMarkDirtyTiles(t
, level
, texImage
->Width2
, texImage
->Height2
,
1518 xoffset
, yoffset
, width
, height
);
1520 t
= savageAllocTexObj(texObj
);
1522 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
1525 t
->base
.dirty_images
[0] |= (1 << level
);
1527 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
1528 height
, format
, type
, pixels
, packing
, texObj
,
1530 t
->dirtySubImages
|= (1 << level
);
1531 SAVAGE_CONTEXT(ctx
)->new_state
|= SAVAGE_NEW_TEXTURE
;
1534 static void savageTexParameter( GLcontext
*ctx
, GLenum target
,
1535 struct gl_texture_object
*tObj
,
1536 GLenum pname
, const GLfloat
*params
)
1538 savageTexObjPtr t
= (savageTexObjPtr
) tObj
->DriverData
;
1539 savageContextPtr imesa
= SAVAGE_CONTEXT( ctx
);
1541 if (!t
|| (target
!= GL_TEXTURE_1D
&& target
!= GL_TEXTURE_2D
))
1545 case GL_TEXTURE_MIN_FILTER
:
1546 case GL_TEXTURE_MAG_FILTER
:
1547 savageSetTexFilter(t
,tObj
->MinFilter
,tObj
->MagFilter
);
1550 case GL_TEXTURE_WRAP_S
:
1551 case GL_TEXTURE_WRAP_T
:
1552 savageSetTexWrapping(t
,tObj
->WrapS
,tObj
->WrapT
);
1555 case GL_TEXTURE_BORDER_COLOR
:
1556 savageSetTexBorderColor(t
,tObj
->_BorderChan
);
1563 imesa
->new_state
|= SAVAGE_NEW_TEXTURE
;
1566 static void savageBindTexture( GLcontext
*ctx
, GLenum target
,
1567 struct gl_texture_object
*tObj
)
1569 savageContextPtr imesa
= SAVAGE_CONTEXT( ctx
);
1571 assert( (target
!= GL_TEXTURE_1D
&& target
!= GL_TEXTURE_2D
) ||
1572 (tObj
->DriverData
!= NULL
) );
1574 imesa
->new_state
|= SAVAGE_NEW_TEXTURE
;
1577 static void savageDeleteTexture( GLcontext
*ctx
, struct gl_texture_object
*tObj
)
1579 driTextureObject
*t
= (driTextureObject
*)tObj
->DriverData
;
1580 savageContextPtr imesa
= SAVAGE_CONTEXT( ctx
);
1587 driDestroyTextureObject(t
);
1589 /* Free mipmap images and the texture object itself */
1590 _mesa_delete_texture_object(ctx
, tObj
);
1594 static struct gl_texture_object
*
1595 savageNewTextureObject( GLcontext
*ctx
, GLuint name
, GLenum target
)
1597 struct gl_texture_object
*obj
;
1598 obj
= _mesa_new_texture_object(ctx
, name
, target
);
1599 savageAllocTexObj( obj
);
1604 void savageDDInitTextureFuncs( struct dd_function_table
*functions
)
1606 functions
->TexEnv
= savageTexEnv
;
1607 functions
->ChooseTextureFormat
= savageChooseTextureFormat
;
1608 functions
->TexImage1D
= savageTexImage1D
;
1609 functions
->TexSubImage1D
= savageTexSubImage1D
;
1610 functions
->TexImage2D
= savageTexImage2D
;
1611 functions
->TexSubImage2D
= savageTexSubImage2D
;
1612 functions
->BindTexture
= savageBindTexture
;
1613 functions
->NewTextureObject
= savageNewTextureObject
;
1614 functions
->DeleteTexture
= savageDeleteTexture
;
1615 functions
->IsTextureResident
= driIsTextureResident
;
1616 functions
->TexParameter
= savageTexParameter
;