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 Template for subtile uploads.
82 * \param h height in pixels
83 * \param w width in bytes
85 #define SUBTILE_FUNC(w,h) \
86 static __inline GLubyte *savageUploadSubtile_##w##x##h \
87 (GLubyte *dest, GLubyte *src, GLuint srcStride) \
90 for (y = 0; y < h; ++y) { \
91 memcpy (dest, src, w); \
98 SUBTILE_FUNC(2, 8) /* 4 bits per pixel, 4 pixels wide */
102 SUBTILE_FUNC(32, 8) /* 4 bytes per pixel, 8 pixels wide */
104 /** \brief Table of subtile upload functions
106 * Indexed by the binary logarithm of the width in bytes.
108 static GLubyte
*(*savageSubtileTab
[]) (GLubyte
*, GLubyte
*, GLuint
) = {
110 savageUploadSubtile_2x8
,
111 savageUploadSubtile_4x8
,
112 savageUploadSubtile_8x8
,
113 savageUploadSubtile_16x8
,
114 savageUploadSubtile_32x8
117 /** \brief Upload a complete tile from src (srcStride) to dest
119 * \param tileInfo Pointer to tiling information
120 * \param wInSub Width of source/dest image in subtiles
121 * \param hInSub Height of source/dest image in subtiles
122 * \param bpp Bytes per pixel
123 * \param src Pointer to source data
124 * \param srcStride Byte stride of rows in the source data
125 * \param dest Pointer to destination
127 * Writes linearly to the destination memory in order to exploit write
130 * For a complete tile wInSub and hInSub are set to the same values as
131 * in tileInfo. If the source image is smaller than a whole tile in
132 * one or both dimensions then they are set to the values of the
133 * source image. This only works as long as the source image is bigger
136 static void savageUploadTile (const savageTileInfo
*tileInfo
,
137 GLuint wInSub
, GLuint hInSub
, GLuint bpp
,
138 GLubyte
*src
, GLuint srcStride
, GLubyte
*dest
) {
139 GLuint subStride
= tileInfo
->subWidth
* bpp
;
140 GLubyte
*srcSRow
= src
, *srcSTile
= src
;
141 GLubyte
*(*subtileFunc
) (GLubyte
*, GLubyte
*, GLuint
) =
142 savageSubtileTab
[(tileInfo
->subWidth
== 4 ? 2 : 3) +
143 ((bpp
== 1) ? 0 : (bpp
== 2) ? 1 : 2)];
145 for (sy
= 0; sy
< hInSub
; ++sy
) {
147 for (sx
= 0; sx
< wInSub
; ++sx
) {
149 dest
= subtileFunc (dest
, src
, srcStride
);
150 srcSTile
+= subStride
;
152 srcSRow
+= srcStride
* tileInfo
->subHeight
;
156 /** \brief Upload a image that is smaller than 8 pixels in either dimension.
158 * \param tileInfo Pointer to tiling information
159 * \param width Width of the image
160 * \param height Height of the image
161 * \param bpp Bytes per pixel
162 * \param src Pointer to source data
163 * \param dest Pointer to destination
165 * This function handles all the special cases that need to be taken
166 * care off. The caller may need to call this function multiple times
167 * with the destination offset in different ways since small texture
168 * images must be repeated in order to fill a whole tile (or 4x4 for
169 * the last 3 levels).
171 * FIXME: Repeating inside this function would be more efficient.
173 static void savageUploadTiny (const savageTileInfo
*tileInfo
,
174 GLuint width
, GLuint height
, GLuint bpp
,
175 GLubyte
*src
, GLubyte
*dest
) {
176 GLuint size
= MAX2(width
, height
);
178 if (width
> tileInfo
->subWidth
) { /* assert: height <= subtile height */
179 GLuint wInSub
= width
/ tileInfo
->subWidth
;
180 GLuint srcStride
= width
* bpp
;
181 GLuint subStride
= tileInfo
->subWidth
* bpp
;
182 GLuint subSkip
= (tileInfo
->subHeight
- height
) * subStride
;
183 GLubyte
*srcSTile
= src
;
185 for (sx
= 0; sx
< wInSub
; ++sx
) {
187 for (y
= 0; y
< height
; ++y
) {
188 memcpy (dest
, src
, subStride
);
193 srcSTile
+= subStride
;
195 } else if (size
> 4) { /* a tile or less wide, except the last 3 levels */
196 GLuint srcStride
= width
* bpp
;
197 GLuint subStride
= tileInfo
->subWidth
* bpp
;
198 /* if the subtile width is 4 we have to skip every other subtile */
199 GLuint subSkip
= tileInfo
->subWidth
== 4 ?
200 subStride
* tileInfo
->subHeight
: 0;
202 for (y
= 0; y
< height
; ++y
) {
203 memcpy (dest
, src
, srcStride
);
209 } else { /* the last 3 mipmap levels */
210 GLuint offset
= (size
<= 2 ? tileInfo
->tinyOffset
[size
-1] : 0);
211 GLuint subStride
= tileInfo
->subWidth
* bpp
;
214 for (y
= 0; y
< height
; ++y
) {
215 memcpy (dest
, src
, bpp
*width
);
222 /** \brief Upload an image from mesa's internal copy.
224 static void savageUploadTexLevel( savageTexObjPtr t
, int level
)
226 const struct gl_texture_image
*image
= t
->base
.tObj
->Image
[0][level
];
227 const savageTileInfo
*tileInfo
= t
->tileInfo
;
228 GLuint width
= image
->Width2
, height
= image
->Height2
;
229 GLuint bpp
= t
->texelBytes
;
231 /* FIXME: Need triangle (rather than pixel) fallbacks to simulate
232 * this using normal textured triangles.
234 * DO THIS IN DRIVER STATE MANAGMENT, not hardware state.
236 if(image
->Border
!= 0)
237 fprintf (stderr
, "Not supported texture border %d.\n",
238 (int) image
->Border
);
240 if (width
>= 8 && height
>= tileInfo
->subHeight
) {
241 GLuint
*dirtyPtr
= t
->image
[level
].dirtyTiles
;
242 GLuint dirtyMask
= 1;
244 if (width
>= tileInfo
->width
&& height
>= tileInfo
->height
) {
245 GLuint wInTiles
= width
/ tileInfo
->width
;
246 GLuint hInTiles
= height
/ tileInfo
->height
;
247 GLubyte
*srcTRow
= image
->Data
, *src
;
248 GLubyte
*dest
= (GLubyte
*)(t
->bufAddr
+ t
->image
[level
].offset
);
250 for (y
= 0; y
< hInTiles
; ++y
) {
252 for (x
= 0; x
< wInTiles
; ++x
) {
253 if (*dirtyPtr
& dirtyMask
) {
254 savageUploadTile (tileInfo
,
255 tileInfo
->wInSub
, tileInfo
->hInSub
,
256 bpp
, src
, width
* bpp
, dest
);
258 src
+= tileInfo
->width
* bpp
;
259 dest
+= 2048; /* tile size is always 2k */
260 if (dirtyMask
== 1<<31) {
266 srcTRow
+= width
* tileInfo
->height
* bpp
;
268 } else if (width
>= tileInfo
->width
) {
269 GLuint wInTiles
= width
/ tileInfo
->width
;
270 GLubyte
*src
= image
->Data
;
271 GLubyte
*dest
= (GLubyte
*)(t
->bufAddr
+ t
->image
[level
].offset
);
272 GLuint tileStride
= tileInfo
->width
* bpp
* height
;
273 savageContextPtr imesa
= (savageContextPtr
)t
->base
.heap
->driverContext
;
275 /* Savage3D-based chips seem so use a constant tile stride
276 * of 2048 for vertically incomplete tiles, but only if
277 * the color depth is 32bpp. Nobody said this was supposed
280 if (bpp
== 4 && imesa
->savageScreen
->chipset
< S3_SAVAGE4
)
282 for (x
= 0; x
< wInTiles
; ++x
) {
283 if (*dirtyPtr
& dirtyMask
) {
284 savageUploadTile (tileInfo
,
286 height
/ tileInfo
->subHeight
,
287 bpp
, src
, width
* bpp
, dest
);
289 src
+= tileInfo
->width
* bpp
;
291 if (dirtyMask
== 1<<31) {
298 savageUploadTile (tileInfo
, width
/ tileInfo
->subWidth
,
299 height
/ tileInfo
->subHeight
, bpp
,
300 image
->Data
, width
* bpp
,
301 (GLubyte
*)(t
->bufAddr
+t
->image
[level
].offset
));
304 GLuint minHeight
, minWidth
, hRepeat
, vRepeat
, x
, y
;
305 if (width
> 4 || height
> 4) {
306 minWidth
= tileInfo
->subWidth
;
307 minHeight
= tileInfo
->subHeight
;
312 hRepeat
= width
>= minWidth
? 1 : minWidth
/ width
;
313 vRepeat
= height
>= minHeight
? 1 : minHeight
/ height
;
314 for (y
= 0; y
< vRepeat
; ++y
) {
315 GLuint offset
= y
* tileInfo
->subWidth
*height
* bpp
;
316 for (x
= 0; x
< hRepeat
; ++x
) {
317 savageUploadTiny (tileInfo
, width
, height
, bpp
, image
->Data
,
318 (GLubyte
*)(t
->bufAddr
+
319 t
->image
[level
].offset
+offset
));
320 offset
+= width
* bpp
;
326 /** \brief Compute the destination size of a texture image
328 static GLuint
savageTexImageSize (GLuint width
, GLuint height
, GLuint bpp
) {
330 if (width
>= 8 && height
>= 8)
331 return width
* height
* bpp
;
332 /* special case for the last three mipmap levels: the hardware computes
333 * the offset internally */
334 else if (width
<= 4 && height
<= 4)
336 /* partially filled sub tiles waste memory
337 * on Savage3D and Savage4 with subtile width 4 every other subtile is
338 * skipped if width < 8 so we can assume a uniform subtile width of 8 */
340 return width
* 8 * bpp
;
341 else if (height
>= 8)
342 return 8 * height
* bpp
;
347 /** \brief Compute the number of (partial) tiles of a texture image
349 static GLuint
savageTexImageTiles (GLuint width
, GLuint height
,
350 const savageTileInfo
*tileInfo
)
352 return (width
+ tileInfo
->width
- 1) / tileInfo
->width
*
353 (height
+ tileInfo
->height
- 1) / tileInfo
->height
;
356 /** \brief Mark dirty tiles
358 * Some care must be taken because tileInfo may not be set or not
359 * up-to-date. So we check if tileInfo is initialized and if the number
360 * of tiles in the bit vector matches the number of tiles computed from
361 * the current tileInfo.
363 static void savageMarkDirtyTiles (savageTexObjPtr t
, GLuint level
,
364 GLuint totalWidth
, GLuint totalHeight
,
365 GLint xoffset
, GLint yoffset
,
366 GLsizei width
, GLsizei height
)
368 GLuint wInTiles
, hInTiles
;
369 GLuint x0
, y0
, x1
, y1
;
373 wInTiles
= (totalWidth
+ t
->tileInfo
->width
- 1) / t
->tileInfo
->width
;
374 hInTiles
= (totalHeight
+ t
->tileInfo
->height
- 1) / t
->tileInfo
->height
;
375 if (wInTiles
* hInTiles
!= t
->image
[level
].nTiles
)
378 x0
= xoffset
/ t
->tileInfo
->width
;
379 y0
= yoffset
/ t
->tileInfo
->height
;
380 x1
= (xoffset
+ width
- 1) / t
->tileInfo
->width
;
381 y1
= (yoffset
+ height
- 1) / t
->tileInfo
->height
;
383 for (y
= y0
; y
<= y1
; ++y
) {
384 GLuint
*ptr
= t
->image
[level
].dirtyTiles
+ (y
* wInTiles
+ x0
) / 32;
385 GLuint mask
= 1 << (y
* wInTiles
+ x0
) % 32;
386 for (x
= x0
; x
<= x1
; ++x
) {
388 if (mask
== (1<<31)) {
398 /** \brief Mark all tiles as dirty
400 static void savageMarkAllTiles (savageTexObjPtr t
, GLuint level
)
402 GLuint words
= (t
->image
[level
].nTiles
+ 31) / 32;
404 memset(t
->image
[level
].dirtyTiles
, ~0, words
*sizeof(GLuint
));
408 static void savageSetTexWrapping(savageTexObjPtr tex
, GLenum s
, GLenum t
)
410 tex
->setup
.sWrapMode
= s
;
411 tex
->setup
.tWrapMode
= t
;
414 static void savageSetTexFilter(savageTexObjPtr t
, GLenum minf
, GLenum magf
)
416 t
->setup
.minFilter
= minf
;
417 t
->setup
.magFilter
= magf
;
423 static void savageSetTexBorderColor(savageTexObjPtr t
, GLubyte color
[4])
425 /* t->Setup[SAVAGE_TEXREG_TEXBORDERCOL] = */
426 /*t->setup.borderColor = SAVAGEPACKCOLOR8888(color[0],color[1],color[2],color[3]); */
431 static savageTexObjPtr
432 savageAllocTexObj( struct gl_texture_object
*texObj
)
436 t
= (savageTexObjPtr
) calloc(1,sizeof(*t
));
437 texObj
->DriverData
= t
;
441 /* Initialize non-image-dependent parts of the state:
443 t
->base
.tObj
= texObj
;
444 t
->base
.dirty_images
[0] = 0;
445 t
->dirtySubImages
= 0;
448 /* Initialize dirty tiles bit vectors
450 for (i
= 0; i
< SAVAGE_TEX_MAXLEVELS
; ++i
)
451 t
->image
[i
].nTiles
= 0;
453 /* FIXME Something here to set initial values for other parts of
457 make_empty_list( &t
->base
);
459 savageSetTexWrapping(t
,texObj
->WrapS
,texObj
->WrapT
);
460 savageSetTexFilter(t
,texObj
->MinFilter
,texObj
->MagFilter
);
461 savageSetTexBorderColor(t
,texObj
->_BorderChan
);
467 /* Called by the _mesa_store_teximage[123]d() functions. */
468 static const struct gl_texture_format
*
469 savageChooseTextureFormat( GLcontext
*ctx
, GLint internalFormat
,
470 GLenum format
, GLenum type
)
472 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
473 const GLboolean do32bpt
=
474 ( imesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_32
);
475 const GLboolean force16bpt
=
476 ( imesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_FORCE_16
);
477 const GLboolean isSavage4
= (imesa
->savageScreen
->chipset
>= S3_SAVAGE4
);
480 switch ( internalFormat
) {
483 case GL_COMPRESSED_RGBA
:
485 case GL_UNSIGNED_INT_10_10_10_2
:
486 case GL_UNSIGNED_INT_2_10_10_10_REV
:
487 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb1555
;
488 case GL_UNSIGNED_SHORT_4_4_4_4
:
489 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
490 return &_mesa_texformat_argb4444
;
491 case GL_UNSIGNED_SHORT_5_5_5_1
:
492 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
493 return &_mesa_texformat_argb1555
;
495 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
;
500 case GL_COMPRESSED_RGB
:
502 case GL_UNSIGNED_SHORT_4_4_4_4
:
503 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
504 return &_mesa_texformat_argb4444
;
505 case GL_UNSIGNED_SHORT_5_5_5_1
:
506 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
507 return &_mesa_texformat_argb1555
;
508 case GL_UNSIGNED_SHORT_5_6_5
:
509 case GL_UNSIGNED_SHORT_5_6_5_REV
:
510 return &_mesa_texformat_rgb565
;
512 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_rgb565
;
519 &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
;
523 &_mesa_texformat_argb8888
: &_mesa_texformat_argb1555
;
527 return &_mesa_texformat_argb4444
;
530 return &_mesa_texformat_argb1555
;
536 return !force16bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_rgb565
;
541 return &_mesa_texformat_rgb565
;
544 case GL_COMPRESSED_ALPHA
:
545 return isSavage4
? &_mesa_texformat_a8
: (
546 do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
);
548 return isSavage4
? &_mesa_texformat_a8
: &_mesa_texformat_argb4444
;
552 return isSavage4
? &_mesa_texformat_a8
: (
553 !force16bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
);
557 case GL_COMPRESSED_LUMINANCE
:
558 /* no alpha, but use argb1555 in 16bit case to get pure grey values */
559 return isSavage4
? &_mesa_texformat_l8
: (
560 do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb1555
);
562 return isSavage4
? &_mesa_texformat_l8
: &_mesa_texformat_argb1555
;
566 return isSavage4
? &_mesa_texformat_l8
: (
567 !force16bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb1555
);
570 case GL_LUMINANCE_ALPHA
:
571 case GL_COMPRESSED_LUMINANCE_ALPHA
:
572 /* Savage4 has a al44 texture format. But it's not supported by Mesa. */
573 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
;
574 case GL_LUMINANCE4_ALPHA4
:
575 case GL_LUMINANCE6_ALPHA2
:
576 return &_mesa_texformat_argb4444
;
577 case GL_LUMINANCE8_ALPHA8
:
578 case GL_LUMINANCE12_ALPHA4
:
579 case GL_LUMINANCE12_ALPHA12
:
580 case GL_LUMINANCE16_ALPHA16
:
581 return !force16bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
;
584 case GL_COMPRESSED_INTENSITY
:
585 return isSavage4
? &_mesa_texformat_i8
: (
586 do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
);
588 return isSavage4
? &_mesa_texformat_i8
: &_mesa_texformat_argb4444
;
592 return isSavage4
? &_mesa_texformat_i8
: (
593 !force16bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
);
596 case GL_COLOR_INDEX1_EXT:
597 case GL_COLOR_INDEX2_EXT:
598 case GL_COLOR_INDEX4_EXT:
599 case GL_COLOR_INDEX8_EXT:
600 case GL_COLOR_INDEX12_EXT:
601 case GL_COLOR_INDEX16_EXT:
602 return &_mesa_texformat_ci8;
605 _mesa_problem(ctx
, "unexpected texture format in %s", __FUNCTION__
);
610 static void savageSetTexImages( savageContextPtr imesa
,
611 const struct gl_texture_object
*tObj
)
613 savageTexObjPtr t
= (savageTexObjPtr
) tObj
->DriverData
;
614 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
615 GLuint offset
, i
, textureFormat
, size
;
616 GLint firstLevel
, lastLevel
;
621 switch (image
->TexFormat
->MesaFormat
) {
622 case MESA_FORMAT_ARGB8888
:
623 textureFormat
= TFT_ARGB8888
;
626 case MESA_FORMAT_ARGB1555
:
627 textureFormat
= TFT_ARGB1555
;
630 case MESA_FORMAT_ARGB4444
:
631 textureFormat
= TFT_ARGB4444
;
634 case MESA_FORMAT_RGB565
:
635 textureFormat
= TFT_RGB565
;
639 textureFormat
= TFT_L8
;
643 textureFormat
= TFT_I8
;
647 textureFormat
= TFT_A8
;
651 _mesa_problem(imesa
->glCtx
, "Bad texture format in %s", __FUNCTION__
);
654 t
->hwFormat
= textureFormat
;
656 /* Select tiling format depending on the chipset and bytes per texel */
657 if (imesa
->savageScreen
->chipset
<= S3_SAVAGE4
)
658 t
->tileInfo
= &tileInfo_s3d_s4
[t
->texelBytes
];
660 t
->tileInfo
= &tileInfo_pro
[t
->texelBytes
];
662 /* Compute which mipmap levels we really want to send to the hardware.
664 driCalculateTextureFirstLastLevel( &t
->base
);
665 firstLevel
= t
->base
.firstLevel
;
666 lastLevel
= t
->base
.lastLevel
;
668 /* Figure out the size now (and count the levels). Upload won't be
669 * done until later. If the number of tiles changes, it means that
670 * this function is called for the first time on this tex object or
671 * the image or the destination color format changed. So all tiles
672 * are marked as dirty.
676 for ( i
= firstLevel
; i
<= lastLevel
&& tObj
->Image
[0][i
] ; i
++ ) {
678 nTiles
= savageTexImageTiles (image
->Width2
, image
->Height2
, t
->tileInfo
);
679 if (t
->image
[i
].nTiles
!= nTiles
) {
680 GLuint words
= (nTiles
+ 31) / 32;
681 if (t
->image
[i
].nTiles
!= 0) {
682 free(t
->image
[i
].dirtyTiles
);
684 t
->image
[i
].dirtyTiles
= malloc(words
*sizeof(GLuint
));
685 memset(t
->image
[i
].dirtyTiles
, ~0, words
*sizeof(GLuint
));
687 t
->image
[i
].nTiles
= nTiles
;
689 t
->image
[i
].offset
= offset
;
691 image
= tObj
->Image
[0][i
];
692 size
= savageTexImageSize (image
->Width2
, image
->Height2
,
697 t
->base
.lastLevel
= i
-1;
698 t
->base
.totalSize
= offset
;
699 /* the last three mipmap levels don't add to the offset. They are packed
702 t
->base
.totalSize
+= 64 * t
->texelBytes
;
703 /* 2k-aligned (really needed?) */
704 t
->base
.totalSize
= (t
->base
.totalSize
+ 2047UL) & ~2047UL;
707 void savageDestroyTexObj(savageContextPtr imesa
, savageTexObjPtr t
)
711 /* Free dirty tiles bit vectors */
712 for (i
= 0; i
< SAVAGE_TEX_MAXLEVELS
; ++i
) {
713 if (t
->image
[i
].nTiles
)
714 free (t
->image
[i
].dirtyTiles
);
717 /* See if it was the driver's current object.
721 for ( i
= 0 ; i
< imesa
->glCtx
->Const
.MaxTextureUnits
; i
++ )
723 if ( &t
->base
== imesa
->CurrentTexObj
[ i
] ) {
724 assert( t
->base
.bound
& (1 << i
) );
725 imesa
->CurrentTexObj
[ i
] = NULL
;
731 /* Upload a texture's images to one of the texture heaps. May have to
732 * eject our own and/or other client's texture objects to make room
735 static void savageUploadTexImages( savageContextPtr imesa
, savageTexObjPtr t
)
737 const GLint numLevels
= t
->base
.lastLevel
- t
->base
.firstLevel
+ 1;
742 LOCK_HARDWARE(imesa
);
744 /* Do we need to eject LRU texture objects?
746 if (!t
->base
.memBlock
) {
750 heap
= driAllocateTexture(imesa
->textureHeaps
, imesa
->lastTexHeap
,
751 (driTextureObject
*)t
);
753 UNLOCK_HARDWARE(imesa
);
757 ofs
= t
->base
.memBlock
->ofs
;
758 t
->setup
.physAddr
= imesa
->savageScreen
->textureOffset
[heap
] + ofs
;
759 t
->bufAddr
= (char *)((GLuint
) imesa
->savageScreen
->texVirtual
[heap
] + ofs
);
760 imesa
->dirty
|= SAVAGE_UPLOAD_GLOBAL
; /* FIXME: really needed? */
763 /* Let the world know we've used this memory recently.
765 driUpdateTextureLRU( &t
->base
);
766 UNLOCK_HARDWARE(imesa
);
768 if (t
->base
.dirty_images
[0] || t
->dirtySubImages
) {
769 if (SAVAGE_DEBUG
& DEBUG_VERBOSE_TEX
)
770 fprintf(stderr
, "Texture upload: |");
772 savageFlushVertices (imesa
);
773 LOCK_HARDWARE(imesa
);
774 savageFlushCmdBufLocked (imesa
, GL_FALSE
);
775 WAIT_IDLE_EMPTY_LOCKED(imesa
);
777 for (i
= 0 ; i
< numLevels
; i
++) {
778 const GLint j
= t
->base
.firstLevel
+ i
; /* the texObj's level */
779 if (t
->base
.dirty_images
[0] & (1 << j
)) {
780 savageMarkAllTiles(t
, j
);
781 if (SAVAGE_DEBUG
& DEBUG_VERBOSE_TEX
)
782 fprintf (stderr
, "*");
783 } else if (SAVAGE_DEBUG
& DEBUG_VERBOSE_TEX
) {
784 if (t
->dirtySubImages
& (1 << j
))
785 fprintf (stderr
, ".");
787 fprintf (stderr
, " ");
789 if ((t
->base
.dirty_images
[0] | t
->dirtySubImages
) & (1 << j
))
790 savageUploadTexLevel( t
, j
);
793 UNLOCK_HARDWARE(imesa
);
794 t
->base
.dirty_images
[0] = 0;
795 t
->dirtySubImages
= 0;
797 if (SAVAGE_DEBUG
& DEBUG_VERBOSE_TEX
)
798 fprintf(stderr
, "|\n");
805 static void savageUpdateTex0State_s4( GLcontext
*ctx
)
807 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
808 struct gl_texture_object
*tObj
;
809 struct gl_texture_image
*image
;
814 if (ctx
->Texture
.Unit
[0]._ReallyEnabled
== 0) {
815 imesa
->regs
.s4
.texDescr
.ni
.tex0En
= GL_FALSE
;
816 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_NoTexMap
;
817 imesa
->regs
.s4
.texCtrl
[0].ui
= 0x20f040;
821 tObj
= ctx
->Texture
.Unit
[0]._Current
;
822 if ((ctx
->Texture
.Unit
[0]._ReallyEnabled
& ~(TEXTURE_1D_BIT
|TEXTURE_2D_BIT
))
823 || tObj
->Image
[0][tObj
->BaseLevel
]->Border
> 0) {
824 /* 3D texturing enabled, or texture border - fallback */
825 FALLBACK (ctx
, SAVAGE_FALLBACK_TEXTURE
, GL_TRUE
);
829 /* Do 2D texture setup */
831 t
= tObj
->DriverData
;
833 t
= savageAllocTexObj( tObj
);
838 imesa
->CurrentTexObj
[0] = &t
->base
;
841 if (t
->base
.dirty_images
[0] || t
->dirtySubImages
) {
842 savageSetTexImages(imesa
, tObj
);
843 savageUploadTexImages(imesa
, t
);
846 driUpdateTextureLRU( &t
->base
);
848 format
= tObj
->Image
[0][tObj
->BaseLevel
]->Format
;
850 switch (ctx
->Texture
.Unit
[0].EnvMode
) {
852 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_FALSE
;
857 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_Decal
;
860 case GL_LUMINANCE_ALPHA
:
863 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_Copy
;
867 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_CopyAlpha
;
870 __HWEnvCombineSingleUnitScale(imesa
, 0, 0,
871 &imesa
->regs
.s4
.texBlendCtrl
[0]);
875 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_FALSE
;
880 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_Decal
;
885 case GL_LUMINANCE_ALPHA
:
886 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_DecalAlpha
;
890 GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_INTENSITY
891 are undefined with GL_DECAL
895 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_CopyAlpha
;
898 __HWEnvCombineSingleUnitScale(imesa
, 0, 0,
899 &imesa
->regs
.s4
.texBlendCtrl
[0]);
903 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_FALSE
;
904 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_ModulAlpha
;
905 __HWEnvCombineSingleUnitScale(imesa
, 0, 0,
906 &imesa
->regs
.s4
.texBlendCtrl
[0]);
914 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_ModulAlpha
;
915 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_FALSE
;
920 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_Blend0
;
921 imesa
->regs
.s4
.texDescr
.ni
.tex1En
= GL_TRUE
;
922 imesa
->regs
.s4
.texDescr
.ni
.texBLoopEn
= GL_TRUE
;
923 imesa
->regs
.s4
.texDescr
.ni
.tex1Width
=
924 imesa
->regs
.s4
.texDescr
.ni
.tex0Width
;
925 imesa
->regs
.s4
.texDescr
.ni
.tex1Height
=
926 imesa
->regs
.s4
.texDescr
.ni
.tex0Height
;
927 imesa
->regs
.s4
.texDescr
.ni
.tex1Fmt
=
928 imesa
->regs
.s4
.texDescr
.ni
.tex0Fmt
;
930 imesa
->regs
.s4
.texAddr
[1].ui
= imesa
->regs
.s4
.texAddr
[0].ui
;
931 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_Blend1
;
933 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_TRUE
;
934 imesa
->bTexEn1
= GL_TRUE
;
937 case GL_LUMINANCE_ALPHA
:
939 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_BlendAlpha0
;
940 imesa
->regs
.s4
.texDescr
.ni
.tex1En
= GL_TRUE
;
941 imesa
->regs
.s4
.texDescr
.ni
.texBLoopEn
= GL_TRUE
;
942 imesa
->regs
.s4
.texDescr
.ni
.tex1Width
=
943 imesa
->regs
.s4
.texDescr
.ni
.tex0Width
;
944 imesa
->regs
.s4
.texDescr
.ni
.tex1Height
=
945 imesa
->regs
.s4
.texDescr
.ni
.tex0Height
;
946 imesa
->regs
.s4
.texDescr
.ni
.tex1Fmt
=
947 imesa
->regs
.s4
.texDescr
.ni
.tex0Fmt
;
949 imesa
->regs
.s4
.texAddr
[1].ui
= imesa
->regs
.s4
.texAddr
[0].ui
;
950 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_BlendAlpha1
;
952 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_TRUE
;
953 imesa
->bTexEn1
= GL_TRUE
;
957 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_BlendInt0
;
958 imesa
->regs
.s4
.texDescr
.ni
.tex1En
= GL_TRUE
;
959 imesa
->regs
.s4
.texDescr
.ni
.texBLoopEn
= GL_TRUE
;
960 imesa
->regs
.s4
.texDescr
.ni
.tex1Width
=
961 imesa
->regs
.s4
.texDescr
.ni
.tex0Width
;
962 imesa
->regs
.s4
.texDescr
.ni
.tex1Height
=
963 imesa
->regs
.s4
.texDescr
.ni
.tex0Height
;
964 imesa
->regs
.s4
.texDescr
.ni
.tex1Fmt
=
965 imesa
->regs
.s4
.texDescr
.ni
.tex0Fmt
;
967 imesa
->regs
.s4
.texAddr
[1].ui
= imesa
->regs
.s4
.texAddr
[0].ui
;
968 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_BlendInt1
;
970 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_TRUE
;
971 imesa
->regs
.s4
.texCtrl
[0].ni
.alphaArg1Invert
= GL_TRUE
;
972 imesa
->bTexEn1
= GL_TRUE
;
975 __HWEnvCombineSingleUnitScale(imesa
, 0, 0,
976 &imesa
->regs
.s4
.texBlendCtrl
[0]);
983 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_FALSE
;
984 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_AddAlpha
;
985 __HWEnvCombineSingleUnitScale(imesa
, 0, 0,
986 &imesa
->regs
.s4
.texBlendCtrl
[0]);
989 #if GL_ARB_texture_env_combine
991 __HWParseTexEnvCombine(imesa
, 0, &imesa
->regs
.s4
.texCtrl
[0],
992 &imesa
->regs
.s4
.texBlendCtrl
[0]);
997 fprintf(stderr
, "unknown tex env mode");
1002 imesa
->regs
.s4
.texCtrl
[0].ni
.uMode
=
1003 t
->setup
.sWrapMode
== GL_REPEAT
? 0 : 1;
1004 imesa
->regs
.s4
.texCtrl
[0].ni
.vMode
=
1005 t
->setup
.tWrapMode
== GL_REPEAT
? 0 : 1;
1007 switch (t
->setup
.minFilter
)
1010 imesa
->regs
.s4
.texCtrl
[0].ni
.filterMode
= TFM_Point
;
1011 imesa
->regs
.s4
.texCtrl
[0].ni
.mipmapEnable
= GL_FALSE
;
1015 imesa
->regs
.s4
.texCtrl
[0].ni
.filterMode
= TFM_Bilin
;
1016 imesa
->regs
.s4
.texCtrl
[0].ni
.mipmapEnable
= GL_FALSE
;
1019 case GL_NEAREST_MIPMAP_NEAREST
:
1020 imesa
->regs
.s4
.texCtrl
[0].ni
.filterMode
= TFM_Point
;
1021 imesa
->regs
.s4
.texCtrl
[0].ni
.mipmapEnable
= GL_TRUE
;
1024 case GL_LINEAR_MIPMAP_NEAREST
:
1025 imesa
->regs
.s4
.texCtrl
[0].ni
.filterMode
= TFM_Bilin
;
1026 imesa
->regs
.s4
.texCtrl
[0].ni
.mipmapEnable
= GL_TRUE
;
1029 case GL_NEAREST_MIPMAP_LINEAR
:
1030 case GL_LINEAR_MIPMAP_LINEAR
:
1031 imesa
->regs
.s4
.texCtrl
[0].ni
.filterMode
= TFM_Trilin
;
1032 imesa
->regs
.s4
.texCtrl
[0].ni
.mipmapEnable
= GL_TRUE
;
1036 if((ctx
->Texture
.Unit
[0].LodBias
!=0.0F
) ||
1037 (imesa
->regs
.s4
.texCtrl
[0].ni
.dBias
!= 0))
1039 int bias
= (int)(ctx
->Texture
.Unit
[0].LodBias
* 32.0);
1042 else if (bias
> 255)
1044 imesa
->regs
.s4
.texCtrl
[0].ni
.dBias
= bias
& 0x1ff;
1047 image
= tObj
->Image
[0][tObj
->BaseLevel
];
1048 imesa
->regs
.s4
.texDescr
.ni
.tex0En
= GL_TRUE
;
1049 imesa
->regs
.s4
.texDescr
.ni
.tex0Width
= image
->WidthLog2
;
1050 imesa
->regs
.s4
.texDescr
.ni
.tex0Height
= image
->HeightLog2
;
1051 imesa
->regs
.s4
.texDescr
.ni
.tex0Fmt
= t
->hwFormat
;
1052 imesa
->regs
.s4
.texCtrl
[0].ni
.dMax
= t
->base
.lastLevel
- t
->base
.firstLevel
;
1054 if (imesa
->regs
.s4
.texDescr
.ni
.tex1En
)
1055 imesa
->regs
.s4
.texDescr
.ni
.texBLoopEn
= GL_TRUE
;
1057 imesa
->regs
.s4
.texAddr
[0].ui
= (u_int32_t
) t
->setup
.physAddr
| 0x2;
1058 if(t
->base
.heap
->heapId
== SAVAGE_AGP_HEAP
)
1059 imesa
->regs
.s4
.texAddr
[0].ui
|= 0x1;
1063 static void savageUpdateTex1State_s4( GLcontext
*ctx
)
1065 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
1066 struct gl_texture_object
*tObj
;
1067 struct gl_texture_image
*image
;
1074 imesa
->bTexEn1
= GL_FALSE
;
1078 if (ctx
->Texture
.Unit
[1]._ReallyEnabled
== 0) {
1079 imesa
->regs
.s4
.texDescr
.ni
.tex1En
= GL_FALSE
;
1080 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_NoTexMap1
;
1081 imesa
->regs
.s4
.texCtrl
[1].ui
= 0x20f040;
1082 imesa
->regs
.s4
.texDescr
.ni
.texBLoopEn
= GL_FALSE
;
1086 tObj
= ctx
->Texture
.Unit
[1]._Current
;
1088 if ((ctx
->Texture
.Unit
[1]._ReallyEnabled
& ~(TEXTURE_1D_BIT
|TEXTURE_2D_BIT
))
1089 || tObj
->Image
[0][tObj
->BaseLevel
]->Border
> 0) {
1090 /* 3D texturing enabled, or texture border - fallback */
1091 FALLBACK (ctx
, SAVAGE_FALLBACK_TEXTURE
, GL_TRUE
);
1095 /* Do 2D texture setup */
1097 t
= tObj
->DriverData
;
1099 t
= savageAllocTexObj( tObj
);
1104 imesa
->CurrentTexObj
[1] = &t
->base
;
1108 if (t
->base
.dirty_images
[0] || t
->dirtySubImages
) {
1109 savageSetTexImages(imesa
, tObj
);
1110 savageUploadTexImages(imesa
, t
);
1113 driUpdateTextureLRU( &t
->base
);
1115 format
= tObj
->Image
[0][tObj
->BaseLevel
]->Format
;
1117 switch (ctx
->Texture
.Unit
[1].EnvMode
) {
1119 imesa
->regs
.s4
.texCtrl
[1].ni
.clrArg1Invert
= GL_FALSE
;
1124 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_Decal
;
1127 case GL_LUMINANCE_ALPHA
:
1130 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_Copy
;
1134 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_CopyAlpha1
;
1137 __HWEnvCombineSingleUnitScale(imesa
, 0, 1, &imesa
->regs
.s4
.texBlendCtrl
);
1140 imesa
->regs
.s4
.texCtrl
[1].ni
.clrArg1Invert
= GL_FALSE
;
1141 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_ModulAlpha1
;
1142 __HWEnvCombineSingleUnitScale(imesa
, 0, 1, &imesa
->regs
.s4
.texBlendCtrl
);
1145 /*#if GL_EXT_texture_env_add*/
1147 imesa
->regs
.s4
.texCtrl
[1].ni
.clrArg1Invert
= GL_FALSE
;
1148 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_AddAlpha1
;
1149 __HWEnvCombineSingleUnitScale(imesa
, 0, 1, &imesa
->regs
.s4
.texBlendCtrl
);
1153 #if GL_ARB_texture_env_combine
1154 case GL_COMBINE_ARB
:
1155 __HWParseTexEnvCombine(imesa
, 1, &texCtrl
, &imesa
->regs
.s4
.texBlendCtrl
);
1160 imesa
->regs
.s4
.texCtrl
[1].ni
.clrArg1Invert
= GL_FALSE
;
1166 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_Decal1
;
1168 case GL_LUMINANCE_ALPHA
:
1171 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_DecalAlpha1
;
1175 // GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_INTENSITY
1176 // are undefined with GL_DECAL
1179 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_CopyAlpha1
;
1182 __HWEnvCombineSingleUnitScale(imesa
, 0, 1, &imesa
->regs
.s4
.texBlendCtrl
);
1186 if (format
== GL_LUMINANCE
)
1189 // This is a hack for GLQuake, invert.
1191 imesa
->regs
.s4
.texCtrl
[1].ni
.clrArg1Invert
= GL_TRUE
;
1192 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= 0;
1194 __HWEnvCombineSingleUnitScale(imesa
, 0, 1, &imesa
->regs
.s4
.texBlendCtrl
);
1198 fprintf(stderr
, "unkown tex 1 env mode\n");
1203 imesa
->regs
.s4
.texCtrl
[1].ni
.uMode
=
1204 t
->setup
.sWrapMode
== GL_REPEAT
? 0 : 1;
1205 imesa
->regs
.s4
.texCtrl
[1].ni
.vMode
=
1206 t
->setup
.tWrapMode
== GL_REPEAT
? 0 : 1;
1208 switch (t
->setup
.minFilter
)
1211 imesa
->regs
.s4
.texCtrl
[1].ni
.filterMode
= TFM_Point
;
1212 imesa
->regs
.s4
.texCtrl
[1].ni
.mipmapEnable
= GL_FALSE
;
1216 imesa
->regs
.s4
.texCtrl
[1].ni
.filterMode
= TFM_Bilin
;
1217 imesa
->regs
.s4
.texCtrl
[1].ni
.mipmapEnable
= GL_FALSE
;
1220 case GL_NEAREST_MIPMAP_NEAREST
:
1221 imesa
->regs
.s4
.texCtrl
[1].ni
.filterMode
= TFM_Point
;
1222 imesa
->regs
.s4
.texCtrl
[1].ni
.mipmapEnable
= GL_TRUE
;
1225 case GL_LINEAR_MIPMAP_NEAREST
:
1226 imesa
->regs
.s4
.texCtrl
[1].ni
.filterMode
= TFM_Bilin
;
1227 imesa
->regs
.s4
.texCtrl
[1].ni
.mipmapEnable
= GL_TRUE
;
1230 case GL_NEAREST_MIPMAP_LINEAR
:
1231 case GL_LINEAR_MIPMAP_LINEAR
:
1232 imesa
->regs
.s4
.texCtrl
[1].ni
.filterMode
= TFM_Trilin
;
1233 imesa
->regs
.s4
.texCtrl
[1].ni
.mipmapEnable
= GL_TRUE
;
1237 if((ctx
->Texture
.Unit
[1].LodBias
!=0.0F
) ||
1238 (imesa
->regs
.s4
.texCtrl
[1].ni
.dBias
!= 0))
1240 int bias
= (int)(ctx
->Texture
.Unit
[1].LodBias
* 32.0);
1243 else if (bias
> 255)
1245 imesa
->regs
.s4
.texCtrl
[1].ni
.dBias
= bias
& 0x1ff;
1248 image
= tObj
->Image
[0][tObj
->BaseLevel
];
1249 imesa
->regs
.s4
.texDescr
.ni
.tex1En
= GL_TRUE
;
1250 imesa
->regs
.s4
.texDescr
.ni
.tex1Width
= image
->WidthLog2
;
1251 imesa
->regs
.s4
.texDescr
.ni
.tex1Height
= image
->HeightLog2
;
1252 imesa
->regs
.s4
.texDescr
.ni
.tex1Fmt
= t
->hwFormat
;
1253 imesa
->regs
.s4
.texCtrl
[1].ni
.dMax
= t
->base
.lastLevel
- t
->base
.firstLevel
;
1254 imesa
->regs
.s4
.texDescr
.ni
.texBLoopEn
= GL_TRUE
;
1256 imesa
->regs
.s4
.texAddr
[1].ui
= (u_int32_t
) t
->setup
.physAddr
| 2;
1257 if(t
->base
.heap
->heapId
== SAVAGE_AGP_HEAP
)
1258 imesa
->regs
.s4
.texAddr
[1].ui
|= 0x1;
1260 static void savageUpdateTexState_s3d( GLcontext
*ctx
)
1262 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
1263 struct gl_texture_object
*tObj
;
1264 struct gl_texture_image
*image
;
1269 if (ctx
->Texture
.Unit
[0]._ReallyEnabled
== 0) {
1270 imesa
->regs
.s3d
.texCtrl
.ui
= 0;
1271 imesa
->regs
.s3d
.texCtrl
.ni
.texEn
= GL_FALSE
;
1272 imesa
->regs
.s3d
.texCtrl
.ni
.dBias
= 0x08;
1273 imesa
->regs
.s3d
.texCtrl
.ni
.texXprEn
= GL_TRUE
;
1277 tObj
= ctx
->Texture
.Unit
[0]._Current
;
1278 if ((ctx
->Texture
.Unit
[0]._ReallyEnabled
& ~(TEXTURE_1D_BIT
|TEXTURE_2D_BIT
))
1279 || tObj
->Image
[0][tObj
->BaseLevel
]->Border
> 0) {
1280 /* 3D texturing enabled, or texture border - fallback */
1281 FALLBACK (ctx
, SAVAGE_FALLBACK_TEXTURE
, GL_TRUE
);
1285 /* Do 2D texture setup */
1286 t
= tObj
->DriverData
;
1288 t
= savageAllocTexObj( tObj
);
1293 imesa
->CurrentTexObj
[0] = &t
->base
;
1296 if (t
->base
.dirty_images
[0] || t
->dirtySubImages
) {
1297 savageSetTexImages(imesa
, tObj
);
1298 savageUploadTexImages(imesa
, t
);
1301 driUpdateTextureLRU( &t
->base
);
1303 format
= tObj
->Image
[0][tObj
->BaseLevel
]->Format
;
1305 /* FIXME: copied from utah-glx, probably needs some tuning */
1306 switch (ctx
->Texture
.Unit
[0].EnvMode
) {
1308 imesa
->regs
.s3d
.drawCtrl
.ni
.texBlendCtrl
= SAVAGETBC_DECAL_S3D
;
1311 imesa
->regs
.s3d
.drawCtrl
.ni
.texBlendCtrl
= SAVAGETBC_COPY_S3D
;
1313 case GL_BLEND
: /* FIXIT */
1315 imesa
->regs
.s3d
.drawCtrl
.ni
.texBlendCtrl
= SAVAGETBC_MODULATEALPHA_S3D
;
1318 fprintf(stderr
, "unkown tex env mode\n");
1323 imesa
->regs
.s3d
.drawCtrl
.ni
.flushPdDestWrites
= GL_TRUE
;
1324 imesa
->regs
.s3d
.drawCtrl
.ni
.flushPdZbufWrites
= GL_TRUE
;
1326 /* FIXME: this is how the utah-driver works. I doubt it's the ultimate
1328 imesa
->regs
.s3d
.texCtrl
.ni
.uWrapEn
= 0;
1329 imesa
->regs
.s3d
.texCtrl
.ni
.vWrapEn
= 0;
1330 if (t
->setup
.sWrapMode
== GL_CLAMP
)
1331 imesa
->regs
.s3d
.texCtrl
.ni
.wrapMode
= TAM_Clamp
;
1333 imesa
->regs
.s3d
.texCtrl
.ni
.wrapMode
= TAM_Wrap
;
1335 switch (t
->setup
.minFilter
) {
1337 imesa
->regs
.s3d
.texCtrl
.ni
.filterMode
= TFM_Point
;
1338 imesa
->regs
.s3d
.texCtrl
.ni
.mipmapDisable
= GL_TRUE
;
1342 imesa
->regs
.s3d
.texCtrl
.ni
.filterMode
= TFM_Bilin
;
1343 imesa
->regs
.s3d
.texCtrl
.ni
.mipmapDisable
= GL_TRUE
;
1346 case GL_NEAREST_MIPMAP_NEAREST
:
1347 imesa
->regs
.s3d
.texCtrl
.ni
.filterMode
= TFM_Point
;
1348 imesa
->regs
.s3d
.texCtrl
.ni
.mipmapDisable
= GL_FALSE
;
1351 case GL_LINEAR_MIPMAP_NEAREST
:
1352 imesa
->regs
.s3d
.texCtrl
.ni
.filterMode
= TFM_Bilin
;
1353 imesa
->regs
.s3d
.texCtrl
.ni
.mipmapDisable
= GL_FALSE
;
1356 case GL_NEAREST_MIPMAP_LINEAR
:
1357 case GL_LINEAR_MIPMAP_LINEAR
:
1358 imesa
->regs
.s3d
.texCtrl
.ni
.filterMode
= TFM_Trilin
;
1359 imesa
->regs
.s3d
.texCtrl
.ni
.mipmapDisable
= GL_FALSE
;
1363 /* There is no way to specify a maximum mipmap level. We may have to
1364 disable mipmapping completely. */
1366 if (t->max_level < t->image[0].image->WidthLog2 ||
1367 t->max_level < t->image[0].image->HeightLog2) {
1368 texCtrl.ni.mipmapEnable = GL_TRUE;
1369 if (texCtrl.ni.filterMode == TFM_Trilin)
1370 texCtrl.ni.filterMode = TFM_Bilin;
1371 texCtrl.ni.filterMode = TFM_Point;
1375 if((ctx
->Texture
.Unit
[0].LodBias
!=0.0F
) ||
1376 (imesa
->regs
.s3d
.texCtrl
.ni
.dBias
!= 0))
1378 int bias
= (int)(ctx
->Texture
.Unit
[0].LodBias
* 16.0);
1381 else if (bias
> 255)
1383 imesa
->regs
.s3d
.texCtrl
.ni
.dBias
= bias
& 0x1ff;
1386 image
= tObj
->Image
[0][tObj
->BaseLevel
];
1387 imesa
->regs
.s3d
.texCtrl
.ni
.texEn
= GL_TRUE
;
1388 imesa
->regs
.s3d
.texDescr
.ni
.texWidth
= image
->WidthLog2
;
1389 imesa
->regs
.s3d
.texDescr
.ni
.texHeight
= image
->HeightLog2
;
1390 assert (t
->hwFormat
<= 7);
1391 imesa
->regs
.s3d
.texDescr
.ni
.texFmt
= t
->hwFormat
;
1393 imesa
->regs
.s3d
.texAddr
.ui
= (u_int32_t
) t
->setup
.physAddr
| 2;
1394 if(t
->base
.heap
->heapId
== SAVAGE_AGP_HEAP
)
1395 imesa
->regs
.s3d
.texAddr
.ui
|= 0x1;
1400 static void savageUpdateTextureState_s4( GLcontext
*ctx
)
1402 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
1403 if (imesa
->CurrentTexObj
[0]) imesa
->CurrentTexObj
[0]->bound
&= ~1;
1404 if (imesa
->CurrentTexObj
[1]) imesa
->CurrentTexObj
[1]->bound
&= ~2;
1405 imesa
->CurrentTexObj
[0] = 0;
1406 imesa
->CurrentTexObj
[1] = 0;
1407 savageUpdateTex0State_s4( ctx
);
1408 savageUpdateTex1State_s4( ctx
);
1409 imesa
->dirty
|= (SAVAGE_UPLOAD_TEX0
|
1410 SAVAGE_UPLOAD_TEX1
);
1412 static void savageUpdateTextureState_s3d( GLcontext
*ctx
)
1414 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
1415 if (imesa
->CurrentTexObj
[0]) imesa
->CurrentTexObj
[0]->bound
&= ~1;
1416 imesa
->CurrentTexObj
[0] = 0;
1417 savageUpdateTexState_s3d( ctx
);
1418 imesa
->dirty
|= (SAVAGE_UPLOAD_TEX0
);
1420 void savageUpdateTextureState( GLcontext
*ctx
)
1422 savageContextPtr imesa
= SAVAGE_CONTEXT( ctx
);
1423 FALLBACK (ctx
, SAVAGE_FALLBACK_TEXTURE
, GL_FALSE
);
1424 FALLBACK(ctx
, SAVAGE_FALLBACK_PROJ_TEXTURE
, GL_FALSE
);
1425 if (imesa
->savageScreen
->chipset
>= S3_SAVAGE4
)
1426 savageUpdateTextureState_s4 (ctx
);
1428 savageUpdateTextureState_s3d (ctx
);
1433 /*****************************************
1435 *****************************************/
1437 static void savageTexEnv( GLcontext
*ctx
, GLenum target
,
1438 GLenum pname
, const GLfloat
*param
)
1440 savageContextPtr imesa
= SAVAGE_CONTEXT( ctx
);
1442 if (pname
== GL_TEXTURE_ENV_MODE
) {
1444 imesa
->new_state
|= SAVAGE_NEW_TEXTURE
;
1446 } else if (pname
== GL_TEXTURE_ENV_COLOR
) {
1448 struct gl_texture_unit
*texUnit
=
1449 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1450 const GLfloat
*fc
= texUnit
->EnvColor
;
1451 GLuint r
, g
, b
, a
, col
;
1452 CLAMPED_FLOAT_TO_UBYTE(r
, fc
[0]);
1453 CLAMPED_FLOAT_TO_UBYTE(g
, fc
[1]);
1454 CLAMPED_FLOAT_TO_UBYTE(b
, fc
[2]);
1455 CLAMPED_FLOAT_TO_UBYTE(a
, fc
[3]);
1466 static void savageTexImage1D( GLcontext
*ctx
, GLenum target
, GLint level
,
1467 GLint internalFormat
,
1468 GLint width
, GLint border
,
1469 GLenum format
, GLenum type
, const GLvoid
*pixels
,
1470 const struct gl_pixelstore_attrib
*packing
,
1471 struct gl_texture_object
*texObj
,
1472 struct gl_texture_image
*texImage
)
1474 savageTexObjPtr t
= (savageTexObjPtr
) texObj
->DriverData
;
1476 /* Do nothing. Marking the image as dirty below is sufficient. */
1478 t
= savageAllocTexObj(texObj
);
1480 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
1484 _mesa_store_teximage1d( ctx
, target
, level
, internalFormat
,
1485 width
, border
, format
, type
,
1486 pixels
, packing
, texObj
, texImage
);
1487 t
->base
.dirty_images
[0] |= (1 << level
);
1488 SAVAGE_CONTEXT(ctx
)->new_state
|= SAVAGE_NEW_TEXTURE
;
1491 static void savageTexSubImage1D( GLcontext
*ctx
,
1496 GLenum format
, GLenum type
,
1497 const GLvoid
*pixels
,
1498 const struct gl_pixelstore_attrib
*packing
,
1499 struct gl_texture_object
*texObj
,
1500 struct gl_texture_image
*texImage
)
1502 savageTexObjPtr t
= (savageTexObjPtr
) texObj
->DriverData
;
1503 assert( t
); /* this _should_ be true */
1505 savageMarkDirtyTiles(t
, level
, texImage
->Width2
, 1,
1506 xoffset
, 0, width
, 1);
1508 t
= savageAllocTexObj(texObj
);
1510 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
1513 t
->base
.dirty_images
[0] |= (1 << level
);
1515 _mesa_store_texsubimage1d(ctx
, target
, level
, xoffset
, width
,
1516 format
, type
, pixels
, packing
, texObj
,
1518 t
->dirtySubImages
|= (1 << level
);
1519 SAVAGE_CONTEXT(ctx
)->new_state
|= SAVAGE_NEW_TEXTURE
;
1522 static void savageTexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
1523 GLint internalFormat
,
1524 GLint width
, GLint height
, GLint border
,
1525 GLenum format
, GLenum type
, const GLvoid
*pixels
,
1526 const struct gl_pixelstore_attrib
*packing
,
1527 struct gl_texture_object
*texObj
,
1528 struct gl_texture_image
*texImage
)
1530 savageTexObjPtr t
= (savageTexObjPtr
) texObj
->DriverData
;
1532 /* Do nothing. Marking the image as dirty below is sufficient. */
1534 t
= savageAllocTexObj(texObj
);
1536 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
1540 _mesa_store_teximage2d( ctx
, target
, level
, internalFormat
,
1541 width
, height
, border
, format
, type
,
1542 pixels
, packing
, texObj
, texImage
);
1543 t
->base
.dirty_images
[0] |= (1 << level
);
1544 SAVAGE_CONTEXT(ctx
)->new_state
|= SAVAGE_NEW_TEXTURE
;
1547 static void savageTexSubImage2D( GLcontext
*ctx
,
1550 GLint xoffset
, GLint yoffset
,
1551 GLsizei width
, GLsizei height
,
1552 GLenum format
, GLenum type
,
1553 const GLvoid
*pixels
,
1554 const struct gl_pixelstore_attrib
*packing
,
1555 struct gl_texture_object
*texObj
,
1556 struct gl_texture_image
*texImage
)
1558 savageTexObjPtr t
= (savageTexObjPtr
) texObj
->DriverData
;
1559 assert( t
); /* this _should_ be true */
1561 savageMarkDirtyTiles(t
, level
, texImage
->Width2
, texImage
->Height2
,
1562 xoffset
, yoffset
, width
, height
);
1564 t
= savageAllocTexObj(texObj
);
1566 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
1569 t
->base
.dirty_images
[0] |= (1 << level
);
1571 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
1572 height
, format
, type
, pixels
, packing
, texObj
,
1574 t
->dirtySubImages
|= (1 << level
);
1575 SAVAGE_CONTEXT(ctx
)->new_state
|= SAVAGE_NEW_TEXTURE
;
1578 static void savageTexParameter( GLcontext
*ctx
, GLenum target
,
1579 struct gl_texture_object
*tObj
,
1580 GLenum pname
, const GLfloat
*params
)
1582 savageTexObjPtr t
= (savageTexObjPtr
) tObj
->DriverData
;
1583 savageContextPtr imesa
= SAVAGE_CONTEXT( ctx
);
1585 if (!t
|| (target
!= GL_TEXTURE_1D
&& target
!= GL_TEXTURE_2D
))
1589 case GL_TEXTURE_MIN_FILTER
:
1590 case GL_TEXTURE_MAG_FILTER
:
1591 savageSetTexFilter(t
,tObj
->MinFilter
,tObj
->MagFilter
);
1594 case GL_TEXTURE_WRAP_S
:
1595 case GL_TEXTURE_WRAP_T
:
1596 savageSetTexWrapping(t
,tObj
->WrapS
,tObj
->WrapT
);
1599 case GL_TEXTURE_BORDER_COLOR
:
1600 savageSetTexBorderColor(t
,tObj
->_BorderChan
);
1607 imesa
->new_state
|= SAVAGE_NEW_TEXTURE
;
1610 static void savageBindTexture( GLcontext
*ctx
, GLenum target
,
1611 struct gl_texture_object
*tObj
)
1613 savageContextPtr imesa
= SAVAGE_CONTEXT( ctx
);
1615 assert( (target
!= GL_TEXTURE_1D
&& target
!= GL_TEXTURE_2D
) ||
1616 (tObj
->DriverData
!= NULL
) );
1618 imesa
->new_state
|= SAVAGE_NEW_TEXTURE
;
1621 static void savageDeleteTexture( GLcontext
*ctx
, struct gl_texture_object
*tObj
)
1623 driTextureObject
*t
= (driTextureObject
*)tObj
->DriverData
;
1624 savageContextPtr imesa
= SAVAGE_CONTEXT( ctx
);
1631 driDestroyTextureObject(t
);
1633 /* Free mipmap images and the texture object itself */
1634 _mesa_delete_texture_object(ctx
, tObj
);
1638 static struct gl_texture_object
*
1639 savageNewTextureObject( GLcontext
*ctx
, GLuint name
, GLenum target
)
1641 struct gl_texture_object
*obj
;
1642 obj
= _mesa_new_texture_object(ctx
, name
, target
);
1643 savageAllocTexObj( obj
);
1648 void savageDDInitTextureFuncs( struct dd_function_table
*functions
)
1650 functions
->TexEnv
= savageTexEnv
;
1651 functions
->ChooseTextureFormat
= savageChooseTextureFormat
;
1652 functions
->TexImage1D
= savageTexImage1D
;
1653 functions
->TexSubImage1D
= savageTexSubImage1D
;
1654 functions
->TexImage2D
= savageTexImage2D
;
1655 functions
->TexSubImage2D
= savageTexSubImage2D
;
1656 functions
->BindTexture
= savageBindTexture
;
1657 functions
->NewTextureObject
= savageNewTextureObject
;
1658 functions
->DeleteTexture
= savageDeleteTexture
;
1659 functions
->IsTextureResident
= driIsTextureResident
;
1660 functions
->TexParameter
= savageTexParameter
;