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"
47 /* Size 1, 2 and 4 images are packed into the last subtile. Each image
48 * is repeated to fill a 4x4 pixel area. The figure below shows the
49 * layout of those 4x4 pixel areas in the 8x8 subtile.
54 * Yuck! 8-bit texture formats use 4x8 subtiles. See below.
56 static const savageTileInfo tileInfo_pro
[5] = {
57 {64, 64, 8, 8, 8, 8, {0x12, 0x02}}, /* 4-bit */
58 {64, 32, 16, 4, 4, 8, {0x30, 0x20}}, /* 8-bit */
59 {64, 16, 8, 2, 8, 8, {0x48, 0x08}}, /* 16-bit */
60 { 0, 0, 0, 0, 0, 0, {0x00, 0x00}}, /* 24-bit */
61 {32, 16, 4, 2, 8, 8, {0x90, 0x10}}, /* 32-bit */
64 /* Size 1, 2 and 4 images are packed into the last two subtiles. Each
65 * image is repeated to fill a 4x4 pixel area. The figures below show
66 * the layout of those 4x4 pixel areas in the two 4x8 subtiles.
68 * second last subtile: 4 last subtile: 2
71 static const savageTileInfo tileInfo_s3d_s4
[5] = {
72 {64, 64, 16, 8, 4, 8, {0x18, 0x10}}, /* 4-bit */
73 {64, 32, 16, 4, 4, 8, {0x30, 0x20}}, /* 8-bit */
74 {64, 16, 16, 2, 4, 8, {0x60, 0x40}}, /* 16-bit */
75 { 0, 0, 0, 0, 0, 0, {0x00, 0x00}}, /* 24-bit */
76 {32, 16, 8, 2, 4, 8, {0xc0, 0x80}}, /* 32-bit */
79 /** \brief Upload a complete tile from src (srcStride) to dest
81 * \param tileInfo Pointer to tiling information
82 * \param wInSub Width of source/dest image in subtiles
83 * \param hInSub Height of source/dest image in subtiles
84 * \param bpp Bytes per pixel
85 * \param src Pointer to source data
86 * \param srcStride Byte stride of rows in the source data
87 * \param dest Pointer to destination
89 * Writes linearly to the destination memory in order to exploit write
92 * For a complete tile wInSub and hInSub are set to the same values as
93 * in tileInfo. If the source image is smaller than a whole tile in
94 * one or both dimensions then they are set to the values of the
95 * source image. This only works as long as the source image is bigger
98 static void savageUploadTile (const savageTileInfo
*tileInfo
,
99 GLuint wInSub
, GLuint hInSub
, GLuint bpp
,
100 GLubyte
*src
, GLuint srcStride
, GLubyte
*dest
) {
101 GLuint subStride
= tileInfo
->subWidth
* bpp
;
102 GLubyte
*srcSRow
= src
, *srcSTile
= src
;
104 for (sy
= 0; sy
< hInSub
; ++sy
) {
106 for (sx
= 0; sx
< wInSub
; ++sx
) {
108 for (y
= 0; y
< tileInfo
->subHeight
; ++y
) {
109 memcpy (dest
, src
, subStride
);
113 srcSTile
+= subStride
;
115 srcSRow
+= srcStride
* tileInfo
->subHeight
;
119 /** \brief Upload a image that is smaller than 8 pixels in either dimension.
121 * \param tileInfo Pointer to tiling information
122 * \param width Width of the image
123 * \param height Height of the image
124 * \param bpp Bytes per pixel
125 * \param src Pointer to source data
126 * \param dest Pointer to destination
128 * This function handles all the special cases that need to be taken
129 * care off. The caller may need to call this function multiple times
130 * with the destination offset in different ways since small texture
131 * images must be repeated in order to fill a whole tile (or 4x4 for
132 * the last 3 levels).
134 * FIXME: Repeating inside this function would be more efficient.
136 static void savageUploadTiny (const savageTileInfo
*tileInfo
,
137 GLuint width
, GLuint height
, GLuint bpp
,
138 GLubyte
*src
, GLubyte
*dest
) {
139 GLuint size
= MAX2(width
, height
);
141 if (width
> tileInfo
->subWidth
) { /* assert: height <= subtile height */
142 GLuint wInSub
= width
/ tileInfo
->subWidth
;
143 GLuint srcStride
= width
* bpp
;
144 GLuint subStride
= tileInfo
->subWidth
* bpp
;
145 GLuint subSkip
= (tileInfo
->subHeight
- height
) * subStride
;
146 GLubyte
*srcSTile
= src
;
148 for (sx
= 0; sx
< wInSub
; ++sx
) {
150 for (y
= 0; y
< height
; ++y
) {
151 memcpy (dest
, src
, subStride
);
156 srcSTile
+= subStride
;
158 } else if (size
> 4) { /* a tile or less wide, except the last 3 levels */
159 GLuint srcStride
= width
* bpp
;
160 GLuint subStride
= tileInfo
->subWidth
* bpp
;
161 /* if the subtile width is 4 we have to skip every other subtile */
162 GLuint subSkip
= tileInfo
->subWidth
== 4 ?
163 subStride
* tileInfo
->subHeight
: 0;
165 for (y
= 0; y
< height
; ++y
) {
166 memcpy (dest
, src
, srcStride
);
172 } else { /* the last 3 mipmap levels */
173 GLuint offset
= (size
<= 2 ? tileInfo
->tinyOffset
[size
-1] : 0);
174 GLuint subStride
= tileInfo
->subWidth
* bpp
;
177 for (y
= 0; y
< height
; ++y
) {
178 memcpy (dest
, src
, bpp
*width
);
185 /** \brief Upload an image from mesa's internal copy.
187 static void savageUploadTexLevel( savageTextureObjectPtr t
, int level
)
189 const struct gl_texture_image
*image
= t
->image
[level
].image
;
190 const savageTileInfo
*tileInfo
= t
->tileInfo
;
191 GLuint width
= image
->Width2
, height
= image
->Height2
;
192 GLuint bpp
= t
->texelBytes
;
194 /* FIXME: Need triangle (rather than pixel) fallbacks to simulate
195 * this using normal textured triangles.
197 * DO THIS IN DRIVER STATE MANAGMENT, not hardware state.
199 if(image
->Border
!= 0)
200 fprintf (stderr
, "Not supported texture border %d.\n",
201 (int) image
->Border
);
203 if (width
>= 8 && height
>= tileInfo
->subHeight
) {
204 if (width
>= tileInfo
->width
&& height
>= tileInfo
->height
) {
205 GLuint wInTiles
= width
/ tileInfo
->width
;
206 GLuint hInTiles
= height
/ tileInfo
->height
;
207 GLubyte
*srcTRow
= image
->Data
, *src
;
208 GLubyte
*dest
= (GLubyte
*)(t
->BufAddr
+ t
->image
[level
].offset
);
210 for (y
= 0; y
< hInTiles
; ++y
) {
212 for (x
= 0; x
< wInTiles
; ++x
) {
213 savageUploadTile (tileInfo
,
214 tileInfo
->wInSub
, tileInfo
->hInSub
, bpp
,
215 src
, width
* bpp
, dest
);
216 src
+= tileInfo
->width
* bpp
;
217 dest
+= 2048; /* tile size is always 2k */
219 srcTRow
+= width
* tileInfo
->height
* bpp
;
222 savageUploadTile (tileInfo
, width
/ tileInfo
->subWidth
,
223 height
/ tileInfo
->subHeight
, bpp
,
224 image
->Data
, width
* bpp
,
225 (GLubyte
*)(t
->BufAddr
+t
->image
[level
].offset
));
228 GLuint minHeight
, minWidth
, hRepeat
, vRepeat
, x
, y
;
229 if (width
> 4 || height
> 4) {
230 minWidth
= tileInfo
->subWidth
;
231 minHeight
= tileInfo
->subHeight
;
236 hRepeat
= width
>= minWidth
? 1 : minWidth
/ width
;
237 vRepeat
= height
>= minHeight
? 1 : minHeight
/ height
;
238 for (y
= 0; y
< vRepeat
; ++y
) {
239 GLuint offset
= y
* tileInfo
->subWidth
*height
* bpp
;
240 for (x
= 0; x
< hRepeat
; ++x
) {
241 savageUploadTiny (tileInfo
, width
, height
, bpp
, image
->Data
,
242 (GLubyte
*)(t
->BufAddr
+
243 t
->image
[level
].offset
+offset
));
244 offset
+= width
* bpp
;
250 /** \brief Compute the destination size of a texture image
252 static GLuint
savageTexImageSize (GLuint width
, GLuint height
, GLuint bpp
) {
254 if (width
>= 8 && height
>= 8)
255 return width
* height
* bpp
;
256 /* special case for the last three mipmap levels: the hardware computes
257 * the offset internally */
258 else if (width
<= 4 && height
<= 4)
260 /* partially filled sub tiles waste memory
261 * on Savage3D and Savage4 with subtile width 4 every other subtile is
262 * skipped if width < 8 so we can assume a uniform subtile width of 8 */
264 return width
* 8 * bpp
;
265 else if (height
>= 8)
266 return 8 * height
* bpp
;
271 static void savageSetTexWrapping(savageTextureObjectPtr tex
, GLenum s
, GLenum t
)
273 tex
->texParams
.sWrapMode
= s
;
274 tex
->texParams
.tWrapMode
= t
;
277 static void savageSetTexFilter(savageTextureObjectPtr t
,
278 GLenum minf
, GLenum magf
)
280 t
->texParams
.minFilter
= minf
;
281 t
->texParams
.magFilter
= magf
;
287 static void savageSetTexBorderColor(savageTextureObjectPtr t
, GLubyte color
[4])
289 /* t->Setup[SAVAGE_TEXREG_TEXBORDERCOL] = */
290 t
->texParams
.boarderColor
= SAVAGEPACKCOLOR8888(color
[0],color
[1],color
[2],color
[3]);
295 static savageTextureObjectPtr
296 savageAllocTexObj( struct gl_texture_object
*texObj
)
298 savageTextureObjectPtr t
;
300 t
= (savageTextureObjectPtr
) calloc(1,sizeof(*t
));
301 texObj
->DriverData
= t
;
304 /* Initialize non-image-dependent parts of the state:
308 /* FIXME Something here to set initial values for other parts of
312 make_empty_list( t
);
314 savageSetTexWrapping(t
,texObj
->WrapS
,texObj
->WrapT
);
315 savageSetTexFilter(t
,texObj
->MinFilter
,texObj
->MagFilter
);
316 savageSetTexBorderColor(t
,texObj
->_BorderChan
);
322 /* Called by the _mesa_store_teximage[123]d() functions. */
323 static const struct gl_texture_format
*
324 savageChooseTextureFormat( GLcontext
*ctx
, GLint internalFormat
,
325 GLenum format
, GLenum type
)
327 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
328 const GLboolean do32bpt
= GL_FALSE
;
329 const GLboolean force16bpt
= GL_FALSE
;
330 const GLboolean isSavage4
= (imesa
->savageScreen
->chipset
>= S3_SAVAGE4
);
334 switch ( internalFormat
) {
337 case GL_COMPRESSED_RGBA
:
339 case GL_UNSIGNED_INT_10_10_10_2
:
340 case GL_UNSIGNED_INT_2_10_10_10_REV
:
341 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb1555
;
342 case GL_UNSIGNED_SHORT_4_4_4_4
:
343 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
344 return &_mesa_texformat_argb4444
;
345 case GL_UNSIGNED_SHORT_5_5_5_1
:
346 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
347 return &_mesa_texformat_argb1555
;
349 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
;
354 case GL_COMPRESSED_RGB
:
356 case GL_UNSIGNED_SHORT_4_4_4_4
:
357 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
358 return &_mesa_texformat_argb4444
;
359 case GL_UNSIGNED_SHORT_5_5_5_1
:
360 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
361 return &_mesa_texformat_argb1555
;
362 case GL_UNSIGNED_SHORT_5_6_5
:
363 case GL_UNSIGNED_SHORT_5_6_5_REV
:
364 return &_mesa_texformat_rgb565
;
366 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_rgb565
;
373 &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
;
377 &_mesa_texformat_argb8888
: &_mesa_texformat_argb1555
;
381 return &_mesa_texformat_argb4444
;
384 return &_mesa_texformat_argb1555
;
390 return !force16bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_rgb565
;
395 return &_mesa_texformat_rgb565
;
398 case GL_COMPRESSED_ALPHA
:
399 return isSavage4
? &_mesa_texformat_a8
: (
400 do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
);
402 return isSavage4
? &_mesa_texformat_a8
: &_mesa_texformat_argb4444
;
406 return isSavage4
? &_mesa_texformat_a8
: (
407 !force16bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
);
411 case GL_COMPRESSED_LUMINANCE
:
412 /* no alpha, but use argb1555 in 16bit case to get pure grey values */
413 return isSavage4
? &_mesa_texformat_l8
: (
414 do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb1555
);
416 return isSavage4
? &_mesa_texformat_l8
: &_mesa_texformat_argb1555
;
420 return isSavage4
? &_mesa_texformat_l8
: (
421 !force16bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb1555
);
424 case GL_LUMINANCE_ALPHA
:
425 case GL_COMPRESSED_LUMINANCE_ALPHA
:
426 /* Savage4 has a al44 texture format. But it's not supported by Mesa. */
427 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
;
428 case GL_LUMINANCE4_ALPHA4
:
429 case GL_LUMINANCE6_ALPHA2
:
430 return &_mesa_texformat_argb4444
;
431 case GL_LUMINANCE8_ALPHA8
:
432 case GL_LUMINANCE12_ALPHA4
:
433 case GL_LUMINANCE12_ALPHA12
:
434 case GL_LUMINANCE16_ALPHA16
:
435 return !force16bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
;
438 case GL_COMPRESSED_INTENSITY
:
439 return isSavage4
? &_mesa_texformat_i8
: (
440 do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
);
442 return isSavage4
? &_mesa_texformat_i8
: &_mesa_texformat_argb4444
;
446 return isSavage4
? &_mesa_texformat_i8
: (
447 !force16bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
);
450 case GL_COLOR_INDEX1_EXT:
451 case GL_COLOR_INDEX2_EXT:
452 case GL_COLOR_INDEX4_EXT:
453 case GL_COLOR_INDEX8_EXT:
454 case GL_COLOR_INDEX12_EXT:
455 case GL_COLOR_INDEX16_EXT:
456 return &_mesa_texformat_ci8;
459 _mesa_problem(ctx
, "unexpected texture format in %s", __FUNCTION__
);
464 static void savageSetTexImages( savageContextPtr imesa
,
465 const struct gl_texture_object
*tObj
)
467 savageTextureObjectPtr t
= (savageTextureObjectPtr
) tObj
->DriverData
;
468 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
469 GLuint offset
, i
, textureFormat
, size
;
474 switch (image
->TexFormat
->MesaFormat
) {
475 case MESA_FORMAT_ARGB8888
:
476 textureFormat
= TFT_ARGB8888
;
479 case MESA_FORMAT_ARGB1555
:
480 textureFormat
= TFT_ARGB1555
;
483 case MESA_FORMAT_ARGB4444
:
484 textureFormat
= TFT_ARGB4444
;
487 case MESA_FORMAT_RGB565
:
488 textureFormat
= TFT_RGB565
;
492 textureFormat
= TFT_L8
;
496 textureFormat
= TFT_I8
;
500 textureFormat
= TFT_A8
;
504 _mesa_problem(imesa
->glCtx
, "Bad texture format in %s", __FUNCTION__
);
508 /* Select tiling format depending on the chipset and bytes per texel */
509 if (imesa
->savageScreen
->chipset
<= S3_SAVAGE4
)
510 t
->tileInfo
= &tileInfo_s3d_s4
[t
->texelBytes
];
512 t
->tileInfo
= &tileInfo_pro
[t
->texelBytes
];
514 /* Figure out the size now (and count the levels). Upload won't be done
520 for ( i
= 0 ; i
< SAVAGE_TEX_MAXLEVELS
&& tObj
->Image
[0][i
] ; i
++ ) {
521 image
= tObj
->Image
[0][i
];
522 t
->image
[i
].image
= image
;
523 t
->image
[i
].offset
= offset
;
524 t
->image
[i
].internalFormat
= textureFormat
;
525 t
->dirty_images
|= (1<<i
);
526 size
= savageTexImageSize (image
->Width2
, image
->Height2
,
531 t
->totalSize
= offset
;
532 /* the last three mipmap levels don't add to the offset. They are packed
535 t
->totalSize
+= 64 * t
->texelBytes
;
537 t
->totalSize
= (t
->totalSize
+ 2047UL) & ~2047UL;
542 void savageDestroyTexObj(savageContextPtr imesa
, savageTextureObjectPtr t
)
546 /* This is sad - need to sync *in case* we upload a texture
547 * to this newly free memory...
550 mmFreeMem(t
->MemBlock
);
553 if (t
->age
> imesa
->dirtyAge
)
554 imesa
->dirtyAge
= t
->age
;
558 t
->globj
->DriverData
= 0;
565 static void savageSwapOutTexObj(savageContextPtr imesa
, savageTextureObjectPtr t
)
568 mmFreeMem(t
->MemBlock
);
571 if (t
->age
> imesa
->dirtyAge
)
572 imesa
->dirtyAge
= t
->age
;
575 t
->dirty_images
= ~0;
576 move_to_tail(&(imesa
->SwappedOut
), t
);
581 void savagePrintLocalLRU( savageContextPtr imesa
, GLuint heap
)
583 savageTextureObjectPtr t
;
584 int sz
= 1 << (imesa
->savageScreen
->logTextureGranularity
[heap
]);
586 foreach( t
, &imesa
->TexObjList
[heap
] ) {
588 fprintf(stderr
, "Placeholder %d at %x sz %x\n",
589 t
->MemBlock
->ofs
/ sz
,
593 fprintf(stderr
, "Texture (bound %d) at %x sz %x\n",
601 void savagePrintGlobalLRU( savageContextPtr imesa
, GLuint heap
)
605 drm_savage_tex_region_t
*list
= imesa
->sarea
->texList
[heap
];
608 for (i
= 0, j
= SAVAGE_NR_TEX_REGIONS
; i
< SAVAGE_NR_TEX_REGIONS
; i
++) {
609 fprintf(stderr
, "list[%d] age %d next %d prev %d\n",
610 j
, list
[j
].age
, list
[j
].next
, list
[j
].prev
);
612 if (j
== SAVAGE_NR_TEX_REGIONS
) break;
615 if (j
!= SAVAGE_NR_TEX_REGIONS
)
616 fprintf(stderr
, "Loop detected in global LRU\n");
617 for (i
= 0 ; i
< SAVAGE_NR_TEX_REGIONS
; i
++)
619 fprintf(stderr
,"list[%d] age %d next %d prev %d\n",
620 i
, list
[i
].age
, list
[i
].next
, list
[i
].prev
);
625 void savageResetGlobalLRU( savageContextPtr imesa
, GLuint heap
)
627 drm_savage_tex_region_t
*list
= imesa
->sarea
->texList
[heap
];
628 int sz
= 1 << imesa
->savageScreen
->logTextureGranularity
[heap
];
631 /* (Re)initialize the global circular LRU list. The last element
632 * in the array (SAVAGE_NR_TEX_REGIONS) is the sentinal. Keeping it
633 * at the end of the array allows it to be addressed rationally
634 * when looking up objects at a particular location in texture
637 for (i
= 0 ; (i
+1) * sz
<= imesa
->savageScreen
->textureSize
[heap
]; i
++) {
644 list
[0].prev
= SAVAGE_NR_TEX_REGIONS
;
646 list
[i
].next
= SAVAGE_NR_TEX_REGIONS
;
647 list
[SAVAGE_NR_TEX_REGIONS
].prev
= i
;
648 list
[SAVAGE_NR_TEX_REGIONS
].next
= 0;
649 imesa
->sarea
->texAge
[heap
] = 0;
653 static void savageUpdateTexLRU( savageContextPtr imesa
, savageTextureObjectPtr t
)
657 int logsz
= imesa
->savageScreen
->logTextureGranularity
[heap
];
658 int start
= t
->MemBlock
->ofs
>> logsz
;
659 int end
= (t
->MemBlock
->ofs
+ t
->MemBlock
->size
- 1) >> logsz
;
660 drm_savage_tex_region_t
*list
= imesa
->sarea
->texList
[heap
];
662 imesa
->texAge
[heap
] = ++imesa
->sarea
->texAge
[heap
];
664 /* Update our local LRU
666 move_to_head( &(imesa
->TexObjList
[heap
]), t
);
668 /* Update the global LRU
670 for (i
= start
; i
<= end
; i
++) {
673 list
[i
].age
= imesa
->texAge
[heap
];
675 /* remove_from_list(i)
677 list
[(unsigned)list
[i
].next
].prev
= list
[i
].prev
;
678 list
[(unsigned)list
[i
].prev
].next
= list
[i
].next
;
680 /* insert_at_head(list, i)
682 list
[i
].prev
= SAVAGE_NR_TEX_REGIONS
;
683 list
[i
].next
= list
[SAVAGE_NR_TEX_REGIONS
].next
;
684 list
[(unsigned)list
[SAVAGE_NR_TEX_REGIONS
].next
].prev
= i
;
685 list
[SAVAGE_NR_TEX_REGIONS
].next
= i
;
690 /* Called for every shared texture region which has increased in age
691 * since we last held the lock.
693 * Figures out which of our textures have been ejected by other clients,
694 * and pushes a placeholder texture onto the LRU list to represent
695 * the other client's textures.
697 void savageTexturesGone( savageContextPtr imesa
,
703 savageTextureObjectPtr t
, tmp
;
705 foreach_s ( t
, tmp
, &imesa
->TexObjList
[heap
] ) {
707 if (t
->MemBlock
->ofs
>= offset
+ size
||
708 t
->MemBlock
->ofs
+ t
->MemBlock
->size
<= offset
)
711 /* It overlaps - kick it off. Need to hold onto the currently bound
715 savageSwapOutTexObj( imesa
, t
);
717 savageDestroyTexObj( imesa
, t
);
722 t
= (savageTextureObjectPtr
) calloc(1,sizeof(*t
));
726 t
->MemBlock
= mmAllocMem( imesa
->texHeap
[heap
], size
, 0, offset
);
732 insert_at_head( &imesa
->TexObjList
[heap
], t
);
740 /* This is called with the lock held. May have to eject our own and/or
741 * other client's texture objects to make room for the upload.
743 int savageUploadTexImages( savageContextPtr imesa
, savageTextureObjectPtr t
)
749 heap
= t
->heap
= SAVAGE_CARD_HEAP
;
751 /* Do we need to eject LRU texture objects?
756 t
->MemBlock
= mmAllocMem( imesa
->texHeap
[heap
], t
->totalSize
, 12, 0 );
761 heap
= t
->heap
= SAVAGE_AGP_HEAP
;
762 t
->MemBlock
= mmAllocMem( imesa
->texHeap
[heap
], t
->totalSize
, 12, 0 );
768 if (imesa
->TexObjList
[heap
].prev
->bound
) {
769 fprintf(stderr
, "Hit bound texture in upload\n");
770 savagePrintLocalLRU( imesa
,heap
);
774 if (imesa
->TexObjList
[heap
].prev
== &(imesa
->TexObjList
[heap
])) {
775 fprintf(stderr
, "Failed to upload texture, sz %d\n", t
->totalSize
);
776 mmDumpMemInfo( imesa
->texHeap
[heap
] );
780 savageSwapOutTexObj( imesa
, imesa
->TexObjList
[heap
].prev
);
783 ofs
= t
->MemBlock
->ofs
;
784 t
->texParams
.hwPhysAddress
= imesa
->savageScreen
->textureOffset
[heap
] + ofs
;
785 t
->BufAddr
= (char *)((GLuint
) imesa
->savageScreen
->texVirtual
[heap
] + ofs
);
786 imesa
->dirty
|= SAVAGE_UPLOAD_CTX
;
789 /* Let the world know we've used this memory recently.
791 savageUpdateTexLRU( imesa
, t
);
793 if (t
->dirty_images
) {
794 LOCK_HARDWARE(imesa
);
795 savageFlushVerticesLocked (imesa
);
796 savageDmaFinish (imesa
);
797 if (SAVAGE_DEBUG
& DEBUG_VERBOSE_LRU
)
798 fprintf(stderr
, "*");
800 for (i
= t
->min_level
; i
<= t
->max_level
; i
++)
801 if (t
->dirty_images
& (1<<i
))
802 savageUploadTexLevel( t
, i
);
803 UNLOCK_HARDWARE(imesa
);
811 static void savageTexSetUnit( savageTextureObjectPtr t
, GLuint unit
)
813 if (t
->current_unit
== unit
) return;
815 t
->current_unit
= unit
;
821 static void savageUpdateTex0State_s4( GLcontext
*ctx
)
823 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
824 struct gl_texture_object
*tObj
;
825 savageTextureObjectPtr t
;
829 if (ctx
->Texture
.Unit
[0]._ReallyEnabled
== 0) {
830 imesa
->regs
.s4
.texDescr
.ni
.tex0En
= GL_FALSE
;
831 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_NoTexMap
;
832 imesa
->regs
.s4
.texCtrl
[0].ui
= 0x20f040;
833 imesa
->regs
.s4
.texAddr
[0].ui
= 0;
837 tObj
= ctx
->Texture
.Unit
[0]._Current
;
838 if (ctx
->Texture
.Unit
[0]._ReallyEnabled
!= TEXTURE_2D_BIT
||
839 tObj
->Image
[0][tObj
->BaseLevel
]->Border
> 0) {
840 /* 1D or 3D texturing enabled, or texture border - fallback */
841 FALLBACK (ctx
, SAVAGE_FALLBACK_TEXTURE
, GL_TRUE
);
845 /* Do 2D texture setup */
847 t
= tObj
->DriverData
;
849 t
= savageAllocTexObj( tObj
);
854 if (t
->current_unit
!= 0)
855 savageTexSetUnit( t
, 0 );
857 imesa
->CurrentTexObj
[0] = t
;
860 if (t
->dirty_images
) {
861 savageSetTexImages(imesa
, tObj
);
862 savageUploadTexImages(imesa
, imesa
->CurrentTexObj
[0]);
866 savageUpdateTexLRU( imesa
, t
);
868 format
= tObj
->Image
[0][tObj
->BaseLevel
]->Format
;
870 switch (ctx
->Texture
.Unit
[0].EnvMode
) {
872 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_FALSE
;
877 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_Decal
;
880 case GL_LUMINANCE_ALPHA
:
883 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_Copy
;
887 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_CopyAlpha
;
890 __HWEnvCombineSingleUnitScale(imesa
, 0, 0,
891 &imesa
->regs
.s4
.texBlendCtrl
[0]);
895 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_FALSE
;
900 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_Decal
;
905 case GL_LUMINANCE_ALPHA
:
906 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_DecalAlpha
;
910 GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_INTENSITY
911 are undefined with GL_DECAL
915 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_CopyAlpha
;
918 __HWEnvCombineSingleUnitScale(imesa
, 0, 0,
919 &imesa
->regs
.s4
.texBlendCtrl
[0]);
923 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_FALSE
;
924 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_ModulAlpha
;
925 __HWEnvCombineSingleUnitScale(imesa
, 0, 0,
926 &imesa
->regs
.s4
.texBlendCtrl
[0]);
934 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_ModulAlpha
;
935 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_FALSE
;
940 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_Blend0
;
941 imesa
->regs
.s4
.texDescr
.ni
.tex1En
= GL_TRUE
;
942 imesa
->regs
.s4
.texDescr
.ni
.texBLoopEn
= GL_TRUE
;
943 imesa
->regs
.s4
.texDescr
.ni
.tex1Width
=
944 imesa
->regs
.s4
.texDescr
.ni
.tex0Width
;
945 imesa
->regs
.s4
.texDescr
.ni
.tex1Height
=
946 imesa
->regs
.s4
.texDescr
.ni
.tex0Height
;
947 imesa
->regs
.s4
.texDescr
.ni
.tex1Fmt
=
948 imesa
->regs
.s4
.texDescr
.ni
.tex0Fmt
;
950 imesa
->regs
.s4
.texAddr
[1].ui
= imesa
->regs
.s4
.texAddr
[0].ui
;
951 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_Blend1
;
953 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_TRUE
;
954 imesa
->bTexEn1
= GL_TRUE
;
957 case GL_LUMINANCE_ALPHA
:
959 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_BlendAlpha0
;
960 imesa
->regs
.s4
.texDescr
.ni
.tex1En
= GL_TRUE
;
961 imesa
->regs
.s4
.texDescr
.ni
.texBLoopEn
= GL_TRUE
;
962 imesa
->regs
.s4
.texDescr
.ni
.tex1Width
=
963 imesa
->regs
.s4
.texDescr
.ni
.tex0Width
;
964 imesa
->regs
.s4
.texDescr
.ni
.tex1Height
=
965 imesa
->regs
.s4
.texDescr
.ni
.tex0Height
;
966 imesa
->regs
.s4
.texDescr
.ni
.tex1Fmt
=
967 imesa
->regs
.s4
.texDescr
.ni
.tex0Fmt
;
969 imesa
->regs
.s4
.texAddr
[1].ui
= imesa
->regs
.s4
.texAddr
[0].ui
;
970 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_BlendAlpha1
;
972 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_TRUE
;
973 imesa
->bTexEn1
= GL_TRUE
;
977 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_BlendInt0
;
978 imesa
->regs
.s4
.texDescr
.ni
.tex1En
= GL_TRUE
;
979 imesa
->regs
.s4
.texDescr
.ni
.texBLoopEn
= GL_TRUE
;
980 imesa
->regs
.s4
.texDescr
.ni
.tex1Width
=
981 imesa
->regs
.s4
.texDescr
.ni
.tex0Width
;
982 imesa
->regs
.s4
.texDescr
.ni
.tex1Height
=
983 imesa
->regs
.s4
.texDescr
.ni
.tex0Height
;
984 imesa
->regs
.s4
.texDescr
.ni
.tex1Fmt
=
985 imesa
->regs
.s4
.texDescr
.ni
.tex0Fmt
;
987 imesa
->regs
.s4
.texAddr
[1].ui
= imesa
->regs
.s4
.texAddr
[0].ui
;
988 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_BlendInt1
;
990 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_TRUE
;
991 imesa
->regs
.s4
.texCtrl
[0].ni
.alphaArg1Invert
= GL_TRUE
;
992 imesa
->bTexEn1
= GL_TRUE
;
995 __HWEnvCombineSingleUnitScale(imesa
, 0, 0,
996 &imesa
->regs
.s4
.texBlendCtrl
[0]);
1004 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_FALSE
;
1005 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_AddAlpha
;
1006 __HWEnvCombineSingleUnitScale(imesa
, 0, 0,
1007 &imesa
->regs
.s4
.texBlendCtrl
[0]);
1010 #if GL_ARB_texture_env_combine
1011 case GL_COMBINE_ARB
:
1012 __HWParseTexEnvCombine(imesa
, 0, &imesa
->regs
.s4
.texCtrl
[0],
1013 &imesa
->regs
.s4
.texBlendCtrl
[0]);
1018 fprintf(stderr
, "unknown tex env mode");
1023 imesa
->regs
.s4
.texCtrl
[0].ni
.uMode
= !(t
->texParams
.sWrapMode
& 0x01);
1024 imesa
->regs
.s4
.texCtrl
[0].ni
.vMode
= !(t
->texParams
.tWrapMode
& 0x01);
1026 switch (t
->texParams
.minFilter
)
1029 imesa
->regs
.s4
.texCtrl
[0].ni
.filterMode
= TFM_Point
;
1030 imesa
->regs
.s4
.texCtrl
[0].ni
.mipmapEnable
= GL_FALSE
;
1034 imesa
->regs
.s4
.texCtrl
[0].ni
.filterMode
= TFM_Bilin
;
1035 imesa
->regs
.s4
.texCtrl
[0].ni
.mipmapEnable
= GL_FALSE
;
1038 case GL_NEAREST_MIPMAP_NEAREST
:
1039 imesa
->regs
.s4
.texCtrl
[0].ni
.filterMode
= TFM_Point
;
1040 imesa
->regs
.s4
.texCtrl
[0].ni
.mipmapEnable
= GL_TRUE
;
1043 case GL_LINEAR_MIPMAP_NEAREST
:
1044 imesa
->regs
.s4
.texCtrl
[0].ni
.filterMode
= TFM_Bilin
;
1045 imesa
->regs
.s4
.texCtrl
[0].ni
.mipmapEnable
= GL_TRUE
;
1048 case GL_NEAREST_MIPMAP_LINEAR
:
1049 case GL_LINEAR_MIPMAP_LINEAR
:
1050 imesa
->regs
.s4
.texCtrl
[0].ni
.filterMode
= TFM_Trilin
;
1051 imesa
->regs
.s4
.texCtrl
[0].ni
.mipmapEnable
= GL_TRUE
;
1055 if((ctx
->Texture
.Unit
[0].LodBias
!=0.0F
) ||
1056 (imesa
->regs
.s4
.texCtrl
[0].ni
.dBias
!= 0))
1058 int bias
= (int)(ctx
->Texture
.Unit
[0].LodBias
* 32.0);
1061 else if (bias
> 255)
1063 imesa
->regs
.s4
.texCtrl
[0].ni
.dBias
= bias
& 0x1ff;
1066 imesa
->regs
.s4
.texDescr
.ni
.tex0En
= GL_TRUE
;
1067 imesa
->regs
.s4
.texDescr
.ni
.tex0Width
= t
->image
[0].image
->WidthLog2
;
1068 imesa
->regs
.s4
.texDescr
.ni
.tex0Height
= t
->image
[0].image
->HeightLog2
;
1069 imesa
->regs
.s4
.texDescr
.ni
.tex0Fmt
= t
->image
[0].internalFormat
;
1070 imesa
->regs
.s4
.texCtrl
[0].ni
.dMax
= t
->max_level
;
1072 if (imesa
->regs
.s4
.texDescr
.ni
.tex1En
)
1073 imesa
->regs
.s4
.texDescr
.ni
.texBLoopEn
= GL_TRUE
;
1075 imesa
->regs
.s4
.texAddr
[0].ui
= (uint32_t) t
->texParams
.hwPhysAddress
| 0x2;
1076 if(t
->heap
== SAVAGE_AGP_HEAP
)
1077 imesa
->regs
.s4
.texAddr
[0].ui
|= 0x1;
1081 static void savageUpdateTex1State_s4( GLcontext
*ctx
)
1083 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
1084 struct gl_texture_object
*tObj
;
1085 savageTextureObjectPtr t
;
1091 imesa
->bTexEn1
= GL_FALSE
;
1095 if (ctx
->Texture
.Unit
[1]._ReallyEnabled
== 0) {
1096 imesa
->regs
.s4
.texDescr
.ni
.tex1En
= GL_FALSE
;
1097 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_NoTexMap1
;
1098 imesa
->regs
.s4
.texCtrl
[1].ui
= 0x20f040;
1099 imesa
->regs
.s4
.texAddr
[1].ui
= 0;
1100 imesa
->regs
.s4
.texDescr
.ni
.texBLoopEn
= GL_FALSE
;
1104 tObj
= ctx
->Texture
.Unit
[1]._Current
;
1106 if (ctx
->Texture
.Unit
[1]._ReallyEnabled
!= TEXTURE_2D_BIT
||
1107 tObj
->Image
[0][tObj
->BaseLevel
]->Border
> 0) {
1108 /* 1D or 3D texturing enabled, or texture border - fallback */
1109 FALLBACK (ctx
, SAVAGE_FALLBACK_TEXTURE
, GL_TRUE
);
1113 /* Do 2D texture setup */
1115 t
= tObj
->DriverData
;
1117 t
= savageAllocTexObj( tObj
);
1122 if (t
->current_unit
!= 1)
1123 savageTexSetUnit( t
, 1 );
1125 imesa
->CurrentTexObj
[1] = t
;
1129 if (t
->dirty_images
) {
1130 savageSetTexImages(imesa
, tObj
);
1131 savageUploadTexImages(imesa
, imesa
->CurrentTexObj
[1]);
1135 savageUpdateTexLRU( imesa
, t
);
1137 format
= tObj
->Image
[0][tObj
->BaseLevel
]->Format
;
1139 switch (ctx
->Texture
.Unit
[1].EnvMode
) {
1141 imesa
->regs
.s4
.texCtrl
[1].ni
.clrArg1Invert
= GL_FALSE
;
1146 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_Decal
;
1149 case GL_LUMINANCE_ALPHA
:
1152 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_Copy
;
1156 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_CopyAlpha1
;
1159 __HWEnvCombineSingleUnitScale(imesa
, 0, 1, &imesa
->regs
.s4
.texBlendCtrl
);
1162 imesa
->regs
.s4
.texCtrl
[1].ni
.clrArg1Invert
= GL_FALSE
;
1163 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_ModulAlpha1
;
1164 __HWEnvCombineSingleUnitScale(imesa
, 0, 1, &imesa
->regs
.s4
.texBlendCtrl
);
1167 /*#if GL_EXT_texture_env_add*/
1169 imesa
->regs
.s4
.texCtrl
[1].ni
.clrArg1Invert
= GL_FALSE
;
1170 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_AddAlpha1
;
1171 __HWEnvCombineSingleUnitScale(imesa
, 0, 1, &imesa
->regs
.s4
.texBlendCtrl
);
1175 #if GL_ARB_texture_env_combine
1176 case GL_COMBINE_ARB
:
1177 __HWParseTexEnvCombine(imesa
, 1, &texCtrl
, &imesa
->regs
.s4
.texBlendCtrl
);
1182 imesa
->regs
.s4
.texCtrl
[1].ni
.clrArg1Invert
= GL_FALSE
;
1188 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_Decal1
;
1190 case GL_LUMINANCE_ALPHA
:
1193 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_DecalAlpha1
;
1197 // GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_INTENSITY
1198 // are undefined with GL_DECAL
1201 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_CopyAlpha1
;
1204 __HWEnvCombineSingleUnitScale(imesa
, 0, 1, &imesa
->regs
.s4
.texBlendCtrl
);
1208 if (format
== GL_LUMINANCE
)
1211 // This is a hack for GLQuake, invert.
1213 imesa
->regs
.s4
.texCtrl
[1].ni
.clrArg1Invert
= GL_TRUE
;
1214 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= 0;
1216 __HWEnvCombineSingleUnitScale(imesa
, 0, 1, &imesa
->regs
.s4
.texBlendCtrl
);
1220 fprintf(stderr
, "unkown tex 1 env mode\n");
1225 imesa
->regs
.s4
.texCtrl
[1].ni
.uMode
= !(t
->texParams
.sWrapMode
& 0x01);
1226 imesa
->regs
.s4
.texCtrl
[1].ni
.vMode
= !(t
->texParams
.tWrapMode
& 0x01);
1228 switch (t
->texParams
.minFilter
)
1231 imesa
->regs
.s4
.texCtrl
[1].ni
.filterMode
= TFM_Point
;
1232 imesa
->regs
.s4
.texCtrl
[1].ni
.mipmapEnable
= GL_FALSE
;
1236 imesa
->regs
.s4
.texCtrl
[1].ni
.filterMode
= TFM_Bilin
;
1237 imesa
->regs
.s4
.texCtrl
[1].ni
.mipmapEnable
= GL_FALSE
;
1240 case GL_NEAREST_MIPMAP_NEAREST
:
1241 imesa
->regs
.s4
.texCtrl
[1].ni
.filterMode
= TFM_Point
;
1242 imesa
->regs
.s4
.texCtrl
[1].ni
.mipmapEnable
= GL_TRUE
;
1245 case GL_LINEAR_MIPMAP_NEAREST
:
1246 imesa
->regs
.s4
.texCtrl
[1].ni
.filterMode
= TFM_Bilin
;
1247 imesa
->regs
.s4
.texCtrl
[1].ni
.mipmapEnable
= GL_TRUE
;
1250 case GL_NEAREST_MIPMAP_LINEAR
:
1251 case GL_LINEAR_MIPMAP_LINEAR
:
1252 imesa
->regs
.s4
.texCtrl
[1].ni
.filterMode
= TFM_Trilin
;
1253 imesa
->regs
.s4
.texCtrl
[1].ni
.mipmapEnable
= GL_TRUE
;
1257 if((ctx
->Texture
.Unit
[1].LodBias
!=0.0F
) ||
1258 (imesa
->regs
.s4
.texCtrl
[1].ni
.dBias
!= 0))
1260 int bias
= (int)(ctx
->Texture
.Unit
[1].LodBias
* 32.0);
1263 else if (bias
> 255)
1265 imesa
->regs
.s4
.texCtrl
[1].ni
.dBias
= bias
& 0x1ff;
1268 imesa
->regs
.s4
.texDescr
.ni
.tex1En
= GL_TRUE
;
1269 imesa
->regs
.s4
.texDescr
.ni
.tex1Width
= t
->image
[0].image
->WidthLog2
;
1270 imesa
->regs
.s4
.texDescr
.ni
.tex1Height
= t
->image
[0].image
->HeightLog2
;
1271 imesa
->regs
.s4
.texDescr
.ni
.tex1Fmt
= t
->image
[0].internalFormat
;
1272 imesa
->regs
.s4
.texCtrl
[1].ni
.dMax
= t
->max_level
;
1273 imesa
->regs
.s4
.texDescr
.ni
.texBLoopEn
= GL_TRUE
;
1275 imesa
->regs
.s4
.texAddr
[1].ui
= (uint32_t) t
->texParams
.hwPhysAddress
| 2;
1276 if(t
->heap
== SAVAGE_AGP_HEAP
)
1277 imesa
->regs
.s4
.texAddr
[1].ui
|= 0x1;
1279 static void savageUpdateTexState_s3d( GLcontext
*ctx
)
1281 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
1282 struct gl_texture_object
*tObj
;
1283 savageTextureObjectPtr t
;
1287 if (ctx
->Texture
.Unit
[0]._ReallyEnabled
== 0) {
1288 imesa
->regs
.s3d
.texCtrl
.ui
= 0;
1289 imesa
->regs
.s3d
.texCtrl
.ni
.texEn
= GL_FALSE
;
1290 imesa
->regs
.s3d
.texCtrl
.ni
.dBias
= 0x08;
1291 imesa
->regs
.s3d
.texCtrl
.ni
.texXprEn
= GL_TRUE
;
1292 imesa
->regs
.s3d
.texAddr
.ui
= 0;
1296 tObj
= ctx
->Texture
.Unit
[0]._Current
;
1297 if (ctx
->Texture
.Unit
[0]._ReallyEnabled
!= TEXTURE_2D_BIT
||
1298 tObj
->Image
[0][tObj
->BaseLevel
]->Border
> 0) {
1299 /* 1D or 3D texturing enabled, or texture border - fallback */
1300 FALLBACK (ctx
, SAVAGE_FALLBACK_TEXTURE
, GL_TRUE
);
1304 /* Do 2D texture setup */
1305 t
= tObj
->DriverData
;
1307 t
= savageAllocTexObj( tObj
);
1312 if (t
->current_unit
!= 0)
1313 savageTexSetUnit( t
, 0 );
1315 imesa
->CurrentTexObj
[0] = t
;
1318 if (t
->dirty_images
) {
1319 savageSetTexImages(imesa
, tObj
);
1320 savageUploadTexImages(imesa
, imesa
->CurrentTexObj
[0]);
1324 savageUpdateTexLRU( imesa
, t
);
1326 format
= tObj
->Image
[0][tObj
->BaseLevel
]->Format
;
1328 /* FIXME: copied from utah-glx, probably needs some tuning */
1329 switch (ctx
->Texture
.Unit
[0].EnvMode
) {
1331 imesa
->regs
.s3d
.drawCtrl
.ni
.texBlendCtrl
= SAVAGETBC_DECAL_S3D
;
1334 imesa
->regs
.s3d
.drawCtrl
.ni
.texBlendCtrl
= SAVAGETBC_COPY_S3D
;
1336 case GL_BLEND
: /* FIXIT */
1338 imesa
->regs
.s3d
.drawCtrl
.ni
.texBlendCtrl
= SAVAGETBC_MODULATEALPHA_S3D
;
1341 fprintf(stderr
, "unkown tex env mode\n");
1346 imesa
->regs
.s3d
.drawCtrl
.ni
.flushPdDestWrites
= GL_TRUE
;
1347 imesa
->regs
.s3d
.drawCtrl
.ni
.flushPdZbufWrites
= GL_TRUE
;
1349 /* FIXME: this is how the utah-driver works. I doubt it's the ultimate
1351 imesa
->regs
.s3d
.texCtrl
.ni
.uWrapEn
= 0;
1352 imesa
->regs
.s3d
.texCtrl
.ni
.vWrapEn
= 0;
1353 if (t
->texParams
.sWrapMode
== GL_CLAMP
)
1354 imesa
->regs
.s3d
.texCtrl
.ni
.wrapMode
= TAM_Clamp
;
1356 imesa
->regs
.s3d
.texCtrl
.ni
.wrapMode
= TAM_Wrap
;
1358 switch (t
->texParams
.minFilter
) {
1360 imesa
->regs
.s3d
.texCtrl
.ni
.filterMode
= TFM_Point
;
1361 imesa
->regs
.s3d
.texCtrl
.ni
.mipmapDisable
= GL_TRUE
;
1365 imesa
->regs
.s3d
.texCtrl
.ni
.filterMode
= TFM_Bilin
;
1366 imesa
->regs
.s3d
.texCtrl
.ni
.mipmapDisable
= GL_TRUE
;
1369 case GL_NEAREST_MIPMAP_NEAREST
:
1370 imesa
->regs
.s3d
.texCtrl
.ni
.filterMode
= TFM_Point
;
1371 imesa
->regs
.s3d
.texCtrl
.ni
.mipmapDisable
= GL_FALSE
;
1374 case GL_LINEAR_MIPMAP_NEAREST
:
1375 imesa
->regs
.s3d
.texCtrl
.ni
.filterMode
= TFM_Bilin
;
1376 imesa
->regs
.s3d
.texCtrl
.ni
.mipmapDisable
= GL_FALSE
;
1379 case GL_NEAREST_MIPMAP_LINEAR
:
1380 case GL_LINEAR_MIPMAP_LINEAR
:
1381 imesa
->regs
.s3d
.texCtrl
.ni
.filterMode
= TFM_Trilin
;
1382 imesa
->regs
.s3d
.texCtrl
.ni
.mipmapDisable
= GL_FALSE
;
1386 /* There is no way to specify a maximum mipmap level. We may have to
1387 disable mipmapping completely. */
1389 if (t->max_level < t->image[0].image->WidthLog2 ||
1390 t->max_level < t->image[0].image->HeightLog2) {
1391 texCtrl.ni.mipmapEnable = GL_TRUE;
1392 if (texCtrl.ni.filterMode == TFM_Trilin)
1393 texCtrl.ni.filterMode = TFM_Bilin;
1394 texCtrl.ni.filterMode = TFM_Point;
1398 if((ctx
->Texture
.Unit
[0].LodBias
!=0.0F
) ||
1399 (imesa
->regs
.s3d
.texCtrl
.ni
.dBias
!= 0))
1401 int bias
= (int)(ctx
->Texture
.Unit
[0].LodBias
* 16.0);
1404 else if (bias
> 255)
1406 imesa
->regs
.s3d
.texCtrl
.ni
.dBias
= bias
& 0x1ff;
1409 imesa
->regs
.s3d
.texCtrl
.ni
.texEn
= GL_TRUE
;
1410 imesa
->regs
.s3d
.texDescr
.ni
.texWidth
= t
->image
[0].image
->WidthLog2
;
1411 imesa
->regs
.s3d
.texDescr
.ni
.texHeight
= t
->image
[0].image
->HeightLog2
;
1412 assert (t
->image
[0].internalFormat
<= 7);
1413 imesa
->regs
.s3d
.texDescr
.ni
.texFmt
= t
->image
[0].internalFormat
;
1415 imesa
->regs
.s3d
.texAddr
.ui
= (uint32_t) t
->texParams
.hwPhysAddress
| 2;
1416 if(t
->heap
== SAVAGE_AGP_HEAP
)
1417 imesa
->regs
.s3d
.texAddr
.ui
|= 0x1;
1422 static void savageUpdateTextureState_s4( GLcontext
*ctx
)
1424 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
1425 if (imesa
->CurrentTexObj
[0]) imesa
->CurrentTexObj
[0]->bound
&= ~1;
1426 if (imesa
->CurrentTexObj
[1]) imesa
->CurrentTexObj
[1]->bound
&= ~2;
1427 imesa
->CurrentTexObj
[0] = 0;
1428 imesa
->CurrentTexObj
[1] = 0;
1429 FALLBACK (ctx
, SAVAGE_FALLBACK_TEXTURE
, GL_FALSE
);
1430 savageUpdateTex0State_s4( ctx
);
1431 savageUpdateTex1State_s4( ctx
);
1432 imesa
->dirty
|= (SAVAGE_UPLOAD_CTX
|
1433 SAVAGE_UPLOAD_TEX0
|
1434 SAVAGE_UPLOAD_TEX1
);
1436 static void savageUpdateTextureState_s3d( GLcontext
*ctx
)
1438 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
1439 if (imesa
->CurrentTexObj
[0]) imesa
->CurrentTexObj
[0]->bound
&= ~1;
1440 imesa
->CurrentTexObj
[0] = 0;
1441 if (ctx
->Texture
.Unit
[1]._ReallyEnabled
) {
1442 FALLBACK (ctx
, SAVAGE_FALLBACK_TEXTURE
, GL_TRUE
);
1444 FALLBACK (ctx
, SAVAGE_FALLBACK_TEXTURE
, GL_FALSE
);
1445 savageUpdateTexState_s3d( ctx
);
1446 imesa
->dirty
|= (SAVAGE_UPLOAD_CTX
|
1447 SAVAGE_UPLOAD_TEX0
);
1450 void savageUpdateTextureState( GLcontext
*ctx
)
1452 savageContextPtr imesa
= SAVAGE_CONTEXT( ctx
);
1453 if (imesa
->savageScreen
->chipset
>= S3_SAVAGE4
)
1454 savageUpdateTextureState_s4 (ctx
);
1456 savageUpdateTextureState_s3d (ctx
);
1461 /*****************************************
1463 *****************************************/
1465 static void savageTexEnv( GLcontext
*ctx
, GLenum target
,
1466 GLenum pname
, const GLfloat
*param
)
1468 savageContextPtr imesa
= SAVAGE_CONTEXT( ctx
);
1470 if (pname
== GL_TEXTURE_ENV_MODE
) {
1472 imesa
->new_state
|= SAVAGE_NEW_TEXTURE
;
1474 } else if (pname
== GL_TEXTURE_ENV_COLOR
) {
1476 struct gl_texture_unit
*texUnit
=
1477 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1478 const GLfloat
*fc
= texUnit
->EnvColor
;
1479 GLuint r
, g
, b
, a
, col
;
1480 CLAMPED_FLOAT_TO_UBYTE(r
, fc
[0]);
1481 CLAMPED_FLOAT_TO_UBYTE(g
, fc
[1]);
1482 CLAMPED_FLOAT_TO_UBYTE(b
, fc
[2]);
1483 CLAMPED_FLOAT_TO_UBYTE(a
, fc
[3]);
1494 static void savageTexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
1495 GLint internalFormat
,
1496 GLint width
, GLint height
, GLint border
,
1497 GLenum format
, GLenum type
, const GLvoid
*pixels
,
1498 const struct gl_pixelstore_attrib
*packing
,
1499 struct gl_texture_object
*texObj
,
1500 struct gl_texture_image
*texImage
)
1502 savageTextureObjectPtr t
= (savageTextureObjectPtr
) texObj
->DriverData
;
1504 savageSwapOutTexObj( SAVAGE_CONTEXT(ctx
), t
);
1506 t
= savageAllocTexObj(texObj
);
1508 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
1512 _mesa_store_teximage2d( ctx
, target
, level
, internalFormat
,
1513 width
, height
, border
, format
, type
,
1514 pixels
, packing
, texObj
, texImage
);
1515 t
->dirty_images
|= (1 << level
);
1516 SAVAGE_CONTEXT(ctx
)->new_state
|= SAVAGE_NEW_TEXTURE
;
1519 static void savageTexSubImage2D( GLcontext
*ctx
,
1522 GLint xoffset
, GLint yoffset
,
1523 GLsizei width
, GLsizei height
,
1524 GLenum format
, GLenum type
,
1525 const GLvoid
*pixels
,
1526 const struct gl_pixelstore_attrib
*packing
,
1527 struct gl_texture_object
*texObj
,
1528 struct gl_texture_image
*texImage
)
1530 savageTextureObjectPtr t
= (savageTextureObjectPtr
) texObj
->DriverData
;
1531 assert( t
); /* this _should_ be true */
1533 savageSwapOutTexObj( SAVAGE_CONTEXT(ctx
), t
);
1535 t
= savageAllocTexObj(texObj
);
1537 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
1541 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
1542 height
, format
, type
, pixels
, packing
, texObj
,
1544 t
->dirty_images
|= (1 << level
);
1545 SAVAGE_CONTEXT(ctx
)->new_state
|= SAVAGE_NEW_TEXTURE
;
1548 static void savageTexParameter( GLcontext
*ctx
, GLenum target
,
1549 struct gl_texture_object
*tObj
,
1550 GLenum pname
, const GLfloat
*params
)
1552 savageTextureObjectPtr t
= (savageTextureObjectPtr
) tObj
->DriverData
;
1553 savageContextPtr imesa
= SAVAGE_CONTEXT( ctx
);
1555 if (!t
|| target
!= GL_TEXTURE_2D
)
1559 case GL_TEXTURE_MIN_FILTER
:
1560 case GL_TEXTURE_MAG_FILTER
:
1561 savageSetTexFilter(t
,tObj
->MinFilter
,tObj
->MagFilter
);
1564 case GL_TEXTURE_WRAP_S
:
1565 case GL_TEXTURE_WRAP_T
:
1566 savageSetTexWrapping(t
,tObj
->WrapS
,tObj
->WrapT
);
1569 case GL_TEXTURE_BORDER_COLOR
:
1570 savageSetTexBorderColor(t
,tObj
->_BorderChan
);
1577 imesa
->new_state
|= SAVAGE_NEW_TEXTURE
;
1580 static void savageBindTexture( GLcontext
*ctx
, GLenum target
,
1581 struct gl_texture_object
*tObj
)
1583 savageContextPtr imesa
= SAVAGE_CONTEXT( ctx
);
1585 assert( (target
!= GL_TEXTURE_2D
) || (tObj
->DriverData
!= NULL
) );
1587 imesa
->new_state
|= SAVAGE_NEW_TEXTURE
;
1590 static void savageDeleteTexture( GLcontext
*ctx
, struct gl_texture_object
*tObj
)
1592 savageTextureObjectPtr t
= (savageTextureObjectPtr
)tObj
->DriverData
;
1593 savageContextPtr imesa
= SAVAGE_CONTEXT( ctx
);
1598 imesa
->CurrentTexObj
[t
->bound
-1] = 0;
1599 imesa
->new_state
|= SAVAGE_NEW_TEXTURE
;
1602 savageDestroyTexObj(imesa
,t
);
1605 /* Free mipmap images and the texture object itself */
1606 _mesa_delete_texture_object(ctx
, tObj
);
1610 static GLboolean
savageIsTextureResident( GLcontext
*ctx
,
1611 struct gl_texture_object
*t
)
1613 savageTextureObjectPtr mt
;
1615 /* LOCK_HARDWARE; */
1616 mt
= (savageTextureObjectPtr
)t
->DriverData
;
1617 /* UNLOCK_HARDWARE; */
1619 return mt
&& mt
->MemBlock
;
1623 static struct gl_texture_object
*
1624 savageNewTextureObject( GLcontext
*ctx
, GLuint name
, GLenum target
)
1626 struct gl_texture_object
*obj
;
1627 obj
= _mesa_new_texture_object(ctx
, name
, target
);
1628 savageAllocTexObj( obj
);
1633 void savageDDInitTextureFuncs( struct dd_function_table
*functions
)
1635 functions
->TexEnv
= savageTexEnv
;
1636 functions
->ChooseTextureFormat
= savageChooseTextureFormat
;
1637 functions
->TexImage2D
= savageTexImage2D
;
1638 functions
->TexSubImage2D
= savageTexSubImage2D
;
1639 functions
->BindTexture
= savageBindTexture
;
1640 functions
->NewTextureObject
= savageNewTextureObject
;
1641 functions
->DeleteTexture
= savageDeleteTexture
;
1642 functions
->IsTextureResident
= savageIsTextureResident
;
1643 functions
->TexParameter
= savageTexParameter
;