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 static const savageTileInfo tileInfo_pro
[5] = {
55 {64, 64, 8, 8, 8, 8, {0x12, 0x02}}, /* 4-bit */
56 {64, 32, 16, 4, 4, 8, {0x30, 0x20}}, /* 8-bit */
57 {64, 16, 8, 2, 8, 8, {0x48, 0x08}}, /* 16-bit */
58 { 0, 0, 0, 0, 0, 0, {0x00, 0x00}}, /* 24-bit */
59 {32, 16, 4, 2, 8, 8, {0x90, 0x10}}, /* 32-bit */
62 /* Size 1, 2 and 4 images are packed into the last two subtiles. Each
63 * image is repeated to fill a 4x4 pixel area. The figures below show
64 * the layout of those 4x4 pixel areas in the two 4x8 subtiles.
66 * second last subtile: 4 last subtile: 2
69 static const savageTileInfo tileInfo_s3d_s4
[5] = {
70 {64, 64, 16, 8, 4, 8, {0x18, 0x10}}, /* 4-bit */
71 {64, 32, 16, 4, 4, 8, {0x30, 0x20}}, /* 8-bit */
72 {64, 16, 16, 2, 4, 8, {0x60, 0x40}}, /* 16-bit */
73 { 0, 0, 0, 0, 0, 0, {0x00, 0x00}}, /* 24-bit */
74 {32, 16, 8, 2, 4, 8, {0xc0, 0x80}}, /* 32-bit */
77 /** \brief Upload a complete tile from src (srcStride) to dest
79 * \param tileInfo Pointer to tiling information
80 * \param wInSub Width of source/dest image in subtiles
81 * \param hInSub Height of source/dest image in subtiles
82 * \param bpp Bytes per pixel
83 * \param src Pointer to source data
84 * \param srcStride Byte stride of rows in the source data
85 * \param dest Pointer to destination
87 * Processes rows of source data linearly and scatters them into the
90 * For a complete tile wInSub and hInSub are set to the same values as
91 * in tileInfo. If the source image is smaller than a whole tile in
92 * one or both dimensions then they are set to the values of the
93 * source image. This only works as long as the source image is bigger
96 static void savageUploadTile (const savageTileInfo
*tileInfo
,
97 GLuint wInSub
, GLuint hInSub
, GLuint bpp
,
98 GLubyte
*src
, GLuint srcStride
, GLubyte
*dest
) {
99 GLuint destStride
= tileInfo
->subWidth
* tileInfo
->subHeight
* bpp
;
100 GLuint subStride
= tileInfo
->subWidth
* bpp
;
101 GLubyte
*srcRow
= src
, *destSRow
= dest
, *destRow
= dest
;
103 /* iterate over subtile rows */
104 for (sy
= 0; sy
< hInSub
; ++sy
) {
106 /* iterate over pixel rows within the subtile row */
107 for (y
= 0; y
< tileInfo
->subHeight
; ++y
) {
110 /* iterate over subtile columns */
111 for (sx
= 0; sx
< wInSub
; ++sx
) {
112 memcpy (dest
, src
, subStride
);
117 destRow
+= subStride
;
119 destSRow
+= destStride
* wInSub
;
123 /** \brief Upload a texture image that is smaller than 8x8 pixels.
132 static void savageUploadTiny (const savageTileInfo
*tileInfo
,
133 GLuint width
, GLuint height
, GLuint bpp
,
134 GLubyte
*src
, GLubyte
*dest
) {
135 GLuint size
= MAX2(width
, height
);
136 GLuint offset
= (size
<= 2 ? tileInfo
->tinyOffset
[size
-1] : 0);
137 GLuint wInSub
= width
/ tileInfo
->subWidth
;
140 /* Fill the file with a test pattern */
142 GLushort
*sdest
= (GLushort
*)dest
;
145 for (i
= 0; i
< tileInfo
->subWidth
*tileInfo
->subHeight
; ++i
) {
150 case 0: mask
= 1; break;
151 case 1: mask
= 2; break;
152 case 2: mask
= 4; break;
153 case 3: mask
= 7; break;
164 if (wInSub
> 1) { /* several subtiles wide but less than a subtile high */
165 GLuint destStride
= tileInfo
->subWidth
* tileInfo
->subHeight
* bpp
;
166 GLuint subStride
= tileInfo
->subWidth
* bpp
;
167 GLuint srcStride
= width
* bpp
;
168 GLubyte
*srcRow
= src
, *destRow
= dest
;
170 for (y
= 0; y
< height
; ++y
) {
173 /* iterate over subtile columns */
174 for (sx
= 0; sx
< wInSub
; ++sx
) {
175 memcpy (dest
, src
, subStride
);
180 destRow
+= subStride
;
181 /* if the subtile width is 4 skip every other tile */
182 if ((y
& 7) == 7 && tileInfo
->subWidth
== 4)
183 destRow
+= destStride
;
185 } else if (size
> 4) { /* not the last 3 mipmap levels */
187 for (y
= 0; y
< height
; ++y
) {
188 memcpy (dest
, src
, bpp
*width
);
190 dest
+= tileInfo
->subWidth
* bpp
;
191 /* if the subtile width is 4 skip every other tile */
192 if ((y
& 7) == 7 && tileInfo
->subWidth
== 4)
193 dest
+= tileInfo
->subHeight
* tileInfo
->subWidth
* bpp
;
195 } else { /* the last 3 mipmap levels */
198 for (y
= 0; y
< height
; ++y
) {
199 memcpy (dest
, src
, bpp
*width
);
201 dest
+= tileInfo
->subWidth
* bpp
;
207 static GLuint
savageTexImageSize (GLuint width
, GLuint height
, GLuint bpp
) {
209 if (width
>= 8 && height
>= 8)
210 return width
* height
* bpp
;
211 /* special case for the last three mipmap levels: the hardware computes
212 * the offset internally */
213 else if (width
<= 4 && height
<= 4)
215 /* partially filled sub tiles waste memory
216 * on Savage3D and Savage4 with subtile width 4 every other subtile is
217 * skipped if width < 8 so we can assume a uniform subtile width of 8 */
219 return width
* 8 * bpp
;
220 else if (height
>= 8)
221 return 8 * height
* bpp
;
226 static void savageSetTexWrapping(savageTextureObjectPtr tex
, GLenum s
, GLenum t
)
228 tex
->texParams
.sWrapMode
= s
;
229 tex
->texParams
.tWrapMode
= t
;
232 static void savageSetTexFilter(savageTextureObjectPtr t
,
233 GLenum minf
, GLenum magf
)
235 t
->texParams
.minFilter
= minf
;
236 t
->texParams
.magFilter
= magf
;
242 static void savageSetTexBorderColor(savageTextureObjectPtr t
, GLubyte color
[4])
244 /* t->Setup[SAVAGE_TEXREG_TEXBORDERCOL] = */
245 t
->texParams
.boarderColor
= SAVAGEPACKCOLOR8888(color
[0],color
[1],color
[2],color
[3]);
250 static savageTextureObjectPtr
251 savageAllocTexObj( struct gl_texture_object
*texObj
)
253 savageTextureObjectPtr t
;
255 t
= (savageTextureObjectPtr
) calloc(1,sizeof(*t
));
256 texObj
->DriverData
= t
;
259 /* Initialize non-image-dependent parts of the state:
263 /* FIXME Something here to set initial values for other parts of
267 make_empty_list( t
);
269 savageSetTexWrapping(t
,texObj
->WrapS
,texObj
->WrapT
);
270 savageSetTexFilter(t
,texObj
->MinFilter
,texObj
->MagFilter
);
271 savageSetTexBorderColor(t
,texObj
->_BorderChan
);
277 /* Called by the _mesa_store_teximage[123]d() functions. */
278 static const struct gl_texture_format
*
279 savageChooseTextureFormat( GLcontext
*ctx
, GLint internalFormat
,
280 GLenum format
, GLenum type
)
282 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
283 const GLboolean do32bpt
= GL_FALSE
;
284 const GLboolean force16bpt
= GL_FALSE
;
285 const GLboolean isSavage4
= (imesa
->savageScreen
->chipset
>= S3_SAVAGE4
);
289 switch ( internalFormat
) {
292 case GL_COMPRESSED_RGBA
:
294 case GL_UNSIGNED_INT_10_10_10_2
:
295 case GL_UNSIGNED_INT_2_10_10_10_REV
:
296 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb1555
;
297 case GL_UNSIGNED_SHORT_4_4_4_4
:
298 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
299 return &_mesa_texformat_argb4444
;
300 case GL_UNSIGNED_SHORT_5_5_5_1
:
301 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
302 return &_mesa_texformat_argb1555
;
304 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
;
309 case GL_COMPRESSED_RGB
:
311 case GL_UNSIGNED_SHORT_4_4_4_4
:
312 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
313 return &_mesa_texformat_argb4444
;
314 case GL_UNSIGNED_SHORT_5_5_5_1
:
315 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
316 return &_mesa_texformat_argb1555
;
317 case GL_UNSIGNED_SHORT_5_6_5
:
318 case GL_UNSIGNED_SHORT_5_6_5_REV
:
319 return &_mesa_texformat_rgb565
;
321 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_rgb565
;
328 &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
;
332 &_mesa_texformat_argb8888
: &_mesa_texformat_argb1555
;
336 return &_mesa_texformat_argb4444
;
339 return &_mesa_texformat_argb1555
;
345 return !force16bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_rgb565
;
350 return &_mesa_texformat_rgb565
;
353 case GL_COMPRESSED_ALPHA
:
354 return isSavage4
? &_mesa_texformat_a8
: (
355 do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
);
357 return isSavage4
? &_mesa_texformat_a8
: &_mesa_texformat_argb4444
;
361 return isSavage4
? &_mesa_texformat_a8
: (
362 !force16bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
);
366 case GL_COMPRESSED_LUMINANCE
:
367 /* no alpha, but use argb1555 in 16bit case to get pure grey values */
368 return isSavage4
? &_mesa_texformat_l8
: (
369 do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb1555
);
371 return isSavage4
? &_mesa_texformat_l8
: &_mesa_texformat_argb1555
;
375 return isSavage4
? &_mesa_texformat_l8
: (
376 !force16bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb1555
);
379 case GL_LUMINANCE_ALPHA
:
380 case GL_COMPRESSED_LUMINANCE_ALPHA
:
381 /* Savage4 has a al44 texture format. But it's not supported by Mesa. */
382 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
;
383 case GL_LUMINANCE4_ALPHA4
:
384 case GL_LUMINANCE6_ALPHA2
:
385 return &_mesa_texformat_argb4444
;
386 case GL_LUMINANCE8_ALPHA8
:
387 case GL_LUMINANCE12_ALPHA4
:
388 case GL_LUMINANCE12_ALPHA12
:
389 case GL_LUMINANCE16_ALPHA16
:
390 return !force16bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
;
393 case GL_COMPRESSED_INTENSITY
:
394 return isSavage4
? &_mesa_texformat_i8
: (
395 do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
);
397 return isSavage4
? &_mesa_texformat_i8
: &_mesa_texformat_argb4444
;
401 return isSavage4
? &_mesa_texformat_i8
: (
402 !force16bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
);
405 case GL_COLOR_INDEX1_EXT:
406 case GL_COLOR_INDEX2_EXT:
407 case GL_COLOR_INDEX4_EXT:
408 case GL_COLOR_INDEX8_EXT:
409 case GL_COLOR_INDEX12_EXT:
410 case GL_COLOR_INDEX16_EXT:
411 return &_mesa_texformat_ci8;
414 _mesa_problem(ctx
, "unexpected texture format in %s", __FUNCTION__
);
419 static void savageSetTexImages( savageContextPtr imesa
,
420 const struct gl_texture_object
*tObj
)
422 savageTextureObjectPtr t
= (savageTextureObjectPtr
) tObj
->DriverData
;
423 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
424 GLuint offset
, i
, textureFormat
, size
;
429 switch (image
->TexFormat
->MesaFormat
) {
430 case MESA_FORMAT_ARGB8888
:
431 textureFormat
= TFT_ARGB8888
;
434 case MESA_FORMAT_ARGB1555
:
435 textureFormat
= TFT_ARGB1555
;
438 case MESA_FORMAT_ARGB4444
:
439 textureFormat
= TFT_ARGB4444
;
442 case MESA_FORMAT_RGB565
:
443 textureFormat
= TFT_RGB565
;
447 textureFormat
= TFT_L8
;
451 textureFormat
= TFT_I8
;
455 textureFormat
= TFT_A8
;
459 _mesa_problem(imesa
->glCtx
, "Bad texture format in %s", __FUNCTION__
);
463 /* Select tiling format depending on the chipset and bytes per texel */
464 if (imesa
->savageScreen
->chipset
<= S3_SAVAGE4
)
465 t
->tileInfo
= &tileInfo_s3d_s4
[t
->texelBytes
];
467 t
->tileInfo
= &tileInfo_pro
[t
->texelBytes
];
469 /* Figure out the size now (and count the levels). Upload won't be done
475 for ( i
= 0 ; i
< SAVAGE_TEX_MAXLEVELS
&& tObj
->Image
[0][i
] ; i
++ ) {
476 image
= tObj
->Image
[0][i
];
477 t
->image
[i
].image
= image
;
478 t
->image
[i
].offset
= offset
;
479 t
->image
[i
].internalFormat
= textureFormat
;
480 t
->dirty_images
|= (1<<i
);
481 size
= savageTexImageSize (image
->Width2
, image
->Height2
,
486 t
->totalSize
= offset
;
487 /* the last three mipmap levels don't add to the offset. They are packed
490 t
->totalSize
+= 64 * t
->texelBytes
;
492 t
->totalSize
= (t
->totalSize
+ 2047UL) & ~2047UL;
497 void savageDestroyTexObj(savageContextPtr imesa
, savageTextureObjectPtr t
)
501 /* This is sad - need to sync *in case* we upload a texture
502 * to this newly free memory...
505 mmFreeMem(t
->MemBlock
);
508 if (t
->age
> imesa
->dirtyAge
)
509 imesa
->dirtyAge
= t
->age
;
513 t
->globj
->DriverData
= 0;
520 static void savageSwapOutTexObj(savageContextPtr imesa
, savageTextureObjectPtr t
)
523 mmFreeMem(t
->MemBlock
);
526 if (t
->age
> imesa
->dirtyAge
)
527 imesa
->dirtyAge
= t
->age
;
530 t
->dirty_images
= ~0;
531 move_to_tail(&(imesa
->SwappedOut
), t
);
536 /* Upload an image from mesa's internal copy.
538 static void savageUploadTexLevel( savageTextureObjectPtr t
, int level
)
540 const struct gl_texture_image
*image
= t
->image
[level
].image
;
541 const savageTileInfo
*tileInfo
= t
->tileInfo
;
542 GLuint width
= image
->Width2
, height
= image
->Height2
;
543 GLuint bpp
= t
->texelBytes
;
545 /* Need triangle (rather than pixel) fallbacks to simulate this using
546 * normal textured triangles.
548 * DO THIS IN DRIVER STATE MANAGMENT, not hardware state.
552 if(image
->Border
!= 0)
553 fprintf (stderr
, "Not supported texture border %d.\n",
554 (int) image
->Border
);
556 if (width
>= 8 && height
>= tileInfo
->subHeight
) {
557 if (width
>= tileInfo
->width
&& height
>= tileInfo
->height
) {
558 GLuint wInTiles
= width
/ tileInfo
->width
;
559 GLuint hInTiles
= height
/ tileInfo
->height
;
560 GLubyte
*srcTRow
= image
->Data
, *src
;
561 GLubyte
*dest
= (GLubyte
*)(t
->BufAddr
+ t
->image
[level
].offset
);
563 for (y
= 0; y
< hInTiles
; ++y
) {
565 for (x
= 0; x
< wInTiles
; ++x
) {
566 savageUploadTile (tileInfo
,
567 tileInfo
->wInSub
, tileInfo
->hInSub
, bpp
,
568 src
, width
* bpp
, dest
);
569 src
+= tileInfo
->width
* bpp
;
570 dest
+= 2048; /* tile size is always 2k */
572 srcTRow
+= width
* tileInfo
->height
* bpp
;
575 savageUploadTile (tileInfo
, width
/ tileInfo
->subWidth
,
576 height
/ tileInfo
->subHeight
, bpp
,
577 image
->Data
, width
* bpp
,
578 (GLubyte
*)(t
->BufAddr
+ t
->image
[level
].offset
));
581 GLuint minHeight
, minWidth
, hRepeat
, vRepeat
, x
, y
;
582 if (width
> 4 || height
> 4) {
583 minWidth
= tileInfo
->subWidth
;
584 minHeight
= tileInfo
->subHeight
;
589 hRepeat
= width
>= minWidth
? 1 : minWidth
/ width
;
590 vRepeat
= height
>= minHeight
? 1 : minHeight
/ height
;
591 for (y
= 0; y
< vRepeat
; ++y
)
592 for (x
= 0; x
< hRepeat
; ++x
) {
593 GLuint offset
= (y
* tileInfo
->subWidth
*height
+
595 savageUploadTiny (tileInfo
, width
, height
, bpp
, image
->Data
,
596 (GLubyte
*)(t
->BufAddr
+
597 t
->image
[level
].offset
+ offset
));
604 void savagePrintLocalLRU( savageContextPtr imesa
, GLuint heap
)
606 savageTextureObjectPtr t
;
607 int sz
= 1 << (imesa
->savageScreen
->logTextureGranularity
[heap
]);
609 foreach( t
, &imesa
->TexObjList
[heap
] ) {
611 fprintf(stderr
, "Placeholder %d at %x sz %x\n",
612 t
->MemBlock
->ofs
/ sz
,
616 fprintf(stderr
, "Texture (bound %d) at %x sz %x\n",
624 void savagePrintGlobalLRU( savageContextPtr imesa
, GLuint heap
)
628 drm_savage_tex_region_t
*list
= imesa
->sarea
->texList
[heap
];
631 for (i
= 0, j
= SAVAGE_NR_TEX_REGIONS
; i
< SAVAGE_NR_TEX_REGIONS
; i
++) {
632 fprintf(stderr
, "list[%d] age %d next %d prev %d\n",
633 j
, list
[j
].age
, list
[j
].next
, list
[j
].prev
);
635 if (j
== SAVAGE_NR_TEX_REGIONS
) break;
638 if (j
!= SAVAGE_NR_TEX_REGIONS
)
639 fprintf(stderr
, "Loop detected in global LRU\n");
640 for (i
= 0 ; i
< SAVAGE_NR_TEX_REGIONS
; i
++)
642 fprintf(stderr
,"list[%d] age %d next %d prev %d\n",
643 i
, list
[i
].age
, list
[i
].next
, list
[i
].prev
);
648 void savageResetGlobalLRU( savageContextPtr imesa
, GLuint heap
)
650 drm_savage_tex_region_t
*list
= imesa
->sarea
->texList
[heap
];
651 int sz
= 1 << imesa
->savageScreen
->logTextureGranularity
[heap
];
654 /* (Re)initialize the global circular LRU list. The last element
655 * in the array (SAVAGE_NR_TEX_REGIONS) is the sentinal. Keeping it
656 * at the end of the array allows it to be addressed rationally
657 * when looking up objects at a particular location in texture
660 for (i
= 0 ; (i
+1) * sz
<= imesa
->savageScreen
->textureSize
[heap
]; i
++) {
667 list
[0].prev
= SAVAGE_NR_TEX_REGIONS
;
669 list
[i
].next
= SAVAGE_NR_TEX_REGIONS
;
670 list
[SAVAGE_NR_TEX_REGIONS
].prev
= i
;
671 list
[SAVAGE_NR_TEX_REGIONS
].next
= 0;
672 imesa
->sarea
->texAge
[heap
] = 0;
676 static void savageUpdateTexLRU( savageContextPtr imesa
, savageTextureObjectPtr t
)
680 int logsz
= imesa
->savageScreen
->logTextureGranularity
[heap
];
681 int start
= t
->MemBlock
->ofs
>> logsz
;
682 int end
= (t
->MemBlock
->ofs
+ t
->MemBlock
->size
- 1) >> logsz
;
683 drm_savage_tex_region_t
*list
= imesa
->sarea
->texList
[heap
];
685 imesa
->texAge
[heap
] = ++imesa
->sarea
->texAge
[heap
];
687 /* Update our local LRU
689 move_to_head( &(imesa
->TexObjList
[heap
]), t
);
691 /* Update the global LRU
693 for (i
= start
; i
<= end
; i
++) {
696 list
[i
].age
= imesa
->texAge
[heap
];
698 /* remove_from_list(i)
700 list
[(unsigned)list
[i
].next
].prev
= list
[i
].prev
;
701 list
[(unsigned)list
[i
].prev
].next
= list
[i
].next
;
703 /* insert_at_head(list, i)
705 list
[i
].prev
= SAVAGE_NR_TEX_REGIONS
;
706 list
[i
].next
= list
[SAVAGE_NR_TEX_REGIONS
].next
;
707 list
[(unsigned)list
[SAVAGE_NR_TEX_REGIONS
].next
].prev
= i
;
708 list
[SAVAGE_NR_TEX_REGIONS
].next
= i
;
713 /* Called for every shared texture region which has increased in age
714 * since we last held the lock.
716 * Figures out which of our textures have been ejected by other clients,
717 * and pushes a placeholder texture onto the LRU list to represent
718 * the other client's textures.
720 void savageTexturesGone( savageContextPtr imesa
,
726 savageTextureObjectPtr t
, tmp
;
728 foreach_s ( t
, tmp
, &imesa
->TexObjList
[heap
] ) {
730 if (t
->MemBlock
->ofs
>= offset
+ size
||
731 t
->MemBlock
->ofs
+ t
->MemBlock
->size
<= offset
)
734 /* It overlaps - kick it off. Need to hold onto the currently bound
738 savageSwapOutTexObj( imesa
, t
);
740 savageDestroyTexObj( imesa
, t
);
745 t
= (savageTextureObjectPtr
) calloc(1,sizeof(*t
));
749 t
->MemBlock
= mmAllocMem( imesa
->texHeap
[heap
], size
, 0, offset
);
755 insert_at_head( &imesa
->TexObjList
[heap
], t
);
763 /* This is called with the lock held. May have to eject our own and/or
764 * other client's texture objects to make room for the upload.
766 int savageUploadTexImages( savageContextPtr imesa
, savageTextureObjectPtr t
)
772 heap
= t
->heap
= SAVAGE_CARD_HEAP
;
774 /* Do we need to eject LRU texture objects?
779 t
->MemBlock
= mmAllocMem( imesa
->texHeap
[heap
], t
->totalSize
, 12, 0 );
784 heap
= t
->heap
= SAVAGE_AGP_HEAP
;
785 t
->MemBlock
= mmAllocMem( imesa
->texHeap
[heap
], t
->totalSize
, 12, 0 );
791 if (imesa
->TexObjList
[heap
].prev
->bound
) {
792 fprintf(stderr
, "Hit bound texture in upload\n");
793 savagePrintLocalLRU( imesa
,heap
);
797 if (imesa
->TexObjList
[heap
].prev
== &(imesa
->TexObjList
[heap
])) {
798 fprintf(stderr
, "Failed to upload texture, sz %d\n", t
->totalSize
);
799 mmDumpMemInfo( imesa
->texHeap
[heap
] );
803 savageDestroyTexObj( imesa
, imesa
->TexObjList
[heap
].prev
);
806 ofs
= t
->MemBlock
->ofs
;
807 t
->texParams
.hwPhysAddress
= imesa
->savageScreen
->textureOffset
[heap
] + ofs
;
808 t
->BufAddr
= (char *)((GLuint
) imesa
->savageScreen
->texVirtual
[heap
] + ofs
);
809 imesa
->dirty
|= SAVAGE_UPLOAD_CTX
;
812 /* Let the world know we've used this memory recently.
814 savageUpdateTexLRU( imesa
, t
);
816 if (t
->dirty_images
) {
817 if (SAVAGE_DEBUG
& DEBUG_VERBOSE_LRU
)
818 fprintf(stderr
, "*");
820 for (i
= t
->min_level
; i
<= t
->max_level
; i
++)
821 if (t
->dirty_images
& (1<<i
))
822 savageUploadTexLevel( t
, i
);
830 static void savageTexSetUnit( savageTextureObjectPtr t
, GLuint unit
)
832 if (t
->current_unit
== unit
) return;
834 t
->current_unit
= unit
;
840 static void savageUpdateTex0State_s4( GLcontext
*ctx
)
842 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
843 struct gl_texture_object
*tObj
;
844 savageTextureObjectPtr t
;
848 if (ctx
->Texture
.Unit
[0]._ReallyEnabled
== 0) {
849 imesa
->regs
.s4
.texDescr
.ni
.tex0En
= GL_FALSE
;
850 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_NoTexMap
;
851 imesa
->regs
.s4
.texCtrl
[0].ui
= 0x20f040;
852 imesa
->regs
.s4
.texAddr
[0].ui
= 0;
856 tObj
= ctx
->Texture
.Unit
[0]._Current
;
857 if (ctx
->Texture
.Unit
[0]._ReallyEnabled
!= TEXTURE_2D_BIT
||
858 tObj
->Image
[0][tObj
->BaseLevel
]->Border
> 0) {
859 /* 1D or 3D texturing enabled, or texture border - fallback */
860 FALLBACK (ctx
, SAVAGE_FALLBACK_TEXTURE
, GL_TRUE
);
864 /* Do 2D texture setup */
866 t
= tObj
->DriverData
;
868 t
= savageAllocTexObj( tObj
);
873 if (t
->current_unit
!= 0)
874 savageTexSetUnit( t
, 0 );
876 imesa
->CurrentTexObj
[0] = t
;
879 if (t
->dirty_images
) {
880 savageSetTexImages(imesa
, tObj
);
881 savageUploadTexImages(imesa
, imesa
->CurrentTexObj
[0]);
885 savageUpdateTexLRU( imesa
, t
);
887 format
= tObj
->Image
[0][tObj
->BaseLevel
]->Format
;
889 switch (ctx
->Texture
.Unit
[0].EnvMode
) {
891 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_FALSE
;
896 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_Decal
;
899 case GL_LUMINANCE_ALPHA
:
902 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_Copy
;
906 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_CopyAlpha
;
909 __HWEnvCombineSingleUnitScale(imesa
, 0, 0,
910 &imesa
->regs
.s4
.texBlendCtrl
[0]);
914 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_FALSE
;
919 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_Decal
;
924 case GL_LUMINANCE_ALPHA
:
925 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_DecalAlpha
;
929 GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_INTENSITY
930 are undefined with GL_DECAL
934 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_CopyAlpha
;
937 __HWEnvCombineSingleUnitScale(imesa
, 0, 0,
938 &imesa
->regs
.s4
.texBlendCtrl
[0]);
942 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_FALSE
;
943 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_ModulAlpha
;
944 __HWEnvCombineSingleUnitScale(imesa
, 0, 0,
945 &imesa
->regs
.s4
.texBlendCtrl
[0]);
953 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_ModulAlpha
;
954 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_FALSE
;
959 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_Blend0
;
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_Blend1
;
972 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_TRUE
;
973 imesa
->bTexEn1
= GL_TRUE
;
976 case GL_LUMINANCE_ALPHA
:
978 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_BlendAlpha0
;
979 imesa
->regs
.s4
.texDescr
.ni
.tex1En
= GL_TRUE
;
980 imesa
->regs
.s4
.texDescr
.ni
.texBLoopEn
= GL_TRUE
;
981 imesa
->regs
.s4
.texDescr
.ni
.tex1Width
=
982 imesa
->regs
.s4
.texDescr
.ni
.tex0Width
;
983 imesa
->regs
.s4
.texDescr
.ni
.tex1Height
=
984 imesa
->regs
.s4
.texDescr
.ni
.tex0Height
;
985 imesa
->regs
.s4
.texDescr
.ni
.tex1Fmt
=
986 imesa
->regs
.s4
.texDescr
.ni
.tex0Fmt
;
988 imesa
->regs
.s4
.texAddr
[1].ui
= imesa
->regs
.s4
.texAddr
[0].ui
;
989 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_BlendAlpha1
;
991 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_TRUE
;
992 imesa
->bTexEn1
= GL_TRUE
;
996 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_BlendInt0
;
997 imesa
->regs
.s4
.texDescr
.ni
.tex1En
= GL_TRUE
;
998 imesa
->regs
.s4
.texDescr
.ni
.texBLoopEn
= GL_TRUE
;
999 imesa
->regs
.s4
.texDescr
.ni
.tex1Width
=
1000 imesa
->regs
.s4
.texDescr
.ni
.tex0Width
;
1001 imesa
->regs
.s4
.texDescr
.ni
.tex1Height
=
1002 imesa
->regs
.s4
.texDescr
.ni
.tex0Height
;
1003 imesa
->regs
.s4
.texDescr
.ni
.tex1Fmt
=
1004 imesa
->regs
.s4
.texDescr
.ni
.tex0Fmt
;
1006 imesa
->regs
.s4
.texAddr
[1].ui
= imesa
->regs
.s4
.texAddr
[0].ui
;
1007 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_BlendInt1
;
1009 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_TRUE
;
1010 imesa
->regs
.s4
.texCtrl
[0].ni
.alphaArg1Invert
= GL_TRUE
;
1011 imesa
->bTexEn1
= GL_TRUE
;
1014 __HWEnvCombineSingleUnitScale(imesa
, 0, 0,
1015 &imesa
->regs
.s4
.texBlendCtrl
[0]);
1023 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_FALSE
;
1024 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_AddAlpha
;
1025 __HWEnvCombineSingleUnitScale(imesa
, 0, 0,
1026 &imesa
->regs
.s4
.texBlendCtrl
[0]);
1029 #if GL_ARB_texture_env_combine
1030 case GL_COMBINE_ARB
:
1031 __HWParseTexEnvCombine(imesa
, 0, &imesa
->regs
.s4
.texCtrl
[0],
1032 &imesa
->regs
.s4
.texBlendCtrl
[0]);
1037 fprintf(stderr
, "unknown tex env mode");
1042 imesa
->regs
.s4
.texCtrl
[0].ni
.uMode
= !(t
->texParams
.sWrapMode
& 0x01);
1043 imesa
->regs
.s4
.texCtrl
[0].ni
.vMode
= !(t
->texParams
.tWrapMode
& 0x01);
1045 switch (t
->texParams
.minFilter
)
1048 imesa
->regs
.s4
.texCtrl
[0].ni
.filterMode
= TFM_Point
;
1049 imesa
->regs
.s4
.texCtrl
[0].ni
.mipmapEnable
= GL_FALSE
;
1053 imesa
->regs
.s4
.texCtrl
[0].ni
.filterMode
= TFM_Bilin
;
1054 imesa
->regs
.s4
.texCtrl
[0].ni
.mipmapEnable
= GL_FALSE
;
1057 case GL_NEAREST_MIPMAP_NEAREST
:
1058 imesa
->regs
.s4
.texCtrl
[0].ni
.filterMode
= TFM_Point
;
1059 imesa
->regs
.s4
.texCtrl
[0].ni
.mipmapEnable
= GL_TRUE
;
1062 case GL_LINEAR_MIPMAP_NEAREST
:
1063 imesa
->regs
.s4
.texCtrl
[0].ni
.filterMode
= TFM_Bilin
;
1064 imesa
->regs
.s4
.texCtrl
[0].ni
.mipmapEnable
= GL_TRUE
;
1067 case GL_NEAREST_MIPMAP_LINEAR
:
1068 case GL_LINEAR_MIPMAP_LINEAR
:
1069 imesa
->regs
.s4
.texCtrl
[0].ni
.filterMode
= TFM_Trilin
;
1070 imesa
->regs
.s4
.texCtrl
[0].ni
.mipmapEnable
= GL_TRUE
;
1074 if((ctx
->Texture
.Unit
[0].LodBias
!=0.0F
) &&
1075 (imesa
->regs
.s4
.texCtrl
[0].ni
.dBias
!= 0))
1083 bias
.f
= ctx
->Texture
.Unit
[0].LodBias
;
1085 /* if the value is >= 15.9375 determine whether >= 16
1088 if(((bias
.i
) & 0x7FFFFFFF) >= 0x417F0000)
1090 if((bias
.i
) & 0x80000000)
1101 ul
=(GLuint
)(bias
.f
*16.0);
1105 imesa
->regs
.s4
.texCtrl
[0].ni
.dBias
= ul
;
1108 imesa
->regs
.s4
.texDescr
.ni
.tex0En
= GL_TRUE
;
1109 imesa
->regs
.s4
.texDescr
.ni
.tex0Width
= t
->image
[0].image
->WidthLog2
;
1110 imesa
->regs
.s4
.texDescr
.ni
.tex0Height
= t
->image
[0].image
->HeightLog2
;
1111 imesa
->regs
.s4
.texDescr
.ni
.tex0Fmt
= t
->image
[0].internalFormat
;
1112 imesa
->regs
.s4
.texCtrl
[0].ni
.dMax
= t
->max_level
;
1114 if (imesa
->regs
.s4
.texDescr
.ni
.tex1En
)
1115 imesa
->regs
.s4
.texDescr
.ni
.texBLoopEn
= GL_TRUE
;
1117 imesa
->regs
.s4
.texAddr
[0].ui
= (GLuint
) t
->texParams
.hwPhysAddress
| 0x2;
1118 if(t
->heap
== SAVAGE_AGP_HEAP
)
1119 imesa
->regs
.s4
.texAddr
[0].ui
|= 0x1;
1123 static void savageUpdateTex1State_s4( GLcontext
*ctx
)
1125 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
1126 struct gl_texture_object
*tObj
;
1127 savageTextureObjectPtr t
;
1133 imesa
->bTexEn1
= GL_FALSE
;
1137 if (ctx
->Texture
.Unit
[1]._ReallyEnabled
== 0) {
1138 imesa
->regs
.s4
.texDescr
.ni
.tex1En
= GL_FALSE
;
1139 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_NoTexMap1
;
1140 imesa
->regs
.s4
.texCtrl
[1].ui
= 0x20f040;
1141 imesa
->regs
.s4
.texAddr
[1].ui
= 0;
1142 imesa
->regs
.s4
.texDescr
.ni
.texBLoopEn
= GL_FALSE
;
1146 tObj
= ctx
->Texture
.Unit
[1]._Current
;
1148 if (ctx
->Texture
.Unit
[1]._ReallyEnabled
!= TEXTURE_2D_BIT
||
1149 tObj
->Image
[0][tObj
->BaseLevel
]->Border
> 0) {
1150 /* 1D or 3D texturing enabled, or texture border - fallback */
1151 FALLBACK (ctx
, SAVAGE_FALLBACK_TEXTURE
, GL_TRUE
);
1155 /* Do 2D texture setup */
1157 t
= tObj
->DriverData
;
1159 t
= savageAllocTexObj( tObj
);
1164 if (t
->current_unit
!= 1)
1165 savageTexSetUnit( t
, 1 );
1167 imesa
->CurrentTexObj
[1] = t
;
1171 if (t
->dirty_images
) {
1172 savageSetTexImages(imesa
, tObj
);
1173 savageUploadTexImages(imesa
, imesa
->CurrentTexObj
[1]);
1177 savageUpdateTexLRU( imesa
, t
);
1179 format
= tObj
->Image
[0][tObj
->BaseLevel
]->Format
;
1181 switch (ctx
->Texture
.Unit
[1].EnvMode
) {
1183 imesa
->regs
.s4
.texCtrl
[1].ni
.clrArg1Invert
= GL_FALSE
;
1188 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_Decal
;
1191 case GL_LUMINANCE_ALPHA
:
1194 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_Copy
;
1198 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_CopyAlpha1
;
1201 __HWEnvCombineSingleUnitScale(imesa
, 0, 1, &imesa
->regs
.s4
.texBlendCtrl
);
1204 imesa
->regs
.s4
.texCtrl
[1].ni
.clrArg1Invert
= GL_FALSE
;
1205 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_ModulAlpha1
;
1206 __HWEnvCombineSingleUnitScale(imesa
, 0, 1, &imesa
->regs
.s4
.texBlendCtrl
);
1209 /*#if GL_EXT_texture_env_add*/
1211 imesa
->regs
.s4
.texCtrl
[1].ni
.clrArg1Invert
= GL_FALSE
;
1212 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_AddAlpha1
;
1213 __HWEnvCombineSingleUnitScale(imesa
, 0, 1, &imesa
->regs
.s4
.texBlendCtrl
);
1217 #if GL_ARB_texture_env_combine
1218 case GL_COMBINE_ARB
:
1219 __HWParseTexEnvCombine(imesa
, 1, &texCtrl
, &imesa
->regs
.s4
.texBlendCtrl
);
1224 imesa
->regs
.s4
.texCtrl
[1].ni
.clrArg1Invert
= GL_FALSE
;
1230 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_Decal1
;
1232 case GL_LUMINANCE_ALPHA
:
1235 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_DecalAlpha1
;
1239 // GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_INTENSITY
1240 // are undefined with GL_DECAL
1243 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_CopyAlpha1
;
1246 __HWEnvCombineSingleUnitScale(imesa
, 0, 1, &imesa
->regs
.s4
.texBlendCtrl
);
1250 if (format
== GL_LUMINANCE
)
1253 // This is a hack for GLQuake, invert.
1255 imesa
->regs
.s4
.texCtrl
[1].ni
.clrArg1Invert
= GL_TRUE
;
1256 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= 0;
1258 __HWEnvCombineSingleUnitScale(imesa
, 0, 1, &imesa
->regs
.s4
.texBlendCtrl
);
1262 fprintf(stderr
, "unkown tex 1 env mode\n");
1267 imesa
->regs
.s4
.texCtrl
[1].ni
.uMode
= !(t
->texParams
.sWrapMode
& 0x01);
1268 imesa
->regs
.s4
.texCtrl
[1].ni
.vMode
= !(t
->texParams
.tWrapMode
& 0x01);
1270 switch (t
->texParams
.minFilter
)
1273 imesa
->regs
.s4
.texCtrl
[1].ni
.filterMode
= TFM_Point
;
1274 imesa
->regs
.s4
.texCtrl
[1].ni
.mipmapEnable
= GL_FALSE
;
1278 imesa
->regs
.s4
.texCtrl
[1].ni
.filterMode
= TFM_Bilin
;
1279 imesa
->regs
.s4
.texCtrl
[1].ni
.mipmapEnable
= GL_FALSE
;
1282 case GL_NEAREST_MIPMAP_NEAREST
:
1283 imesa
->regs
.s4
.texCtrl
[1].ni
.filterMode
= TFM_Point
;
1284 imesa
->regs
.s4
.texCtrl
[1].ni
.mipmapEnable
= GL_TRUE
;
1287 case GL_LINEAR_MIPMAP_NEAREST
:
1288 imesa
->regs
.s4
.texCtrl
[1].ni
.filterMode
= TFM_Bilin
;
1289 imesa
->regs
.s4
.texCtrl
[1].ni
.mipmapEnable
= GL_TRUE
;
1292 case GL_NEAREST_MIPMAP_LINEAR
:
1293 case GL_LINEAR_MIPMAP_LINEAR
:
1294 imesa
->regs
.s4
.texCtrl
[1].ni
.filterMode
= TFM_Trilin
;
1295 imesa
->regs
.s4
.texCtrl
[1].ni
.mipmapEnable
= GL_TRUE
;
1299 if((ctx
->Texture
.Unit
[1].LodBias
!=0.0F
)&&
1300 (imesa
->regs
.s4
.texCtrl
[1].ni
.dBias
!= 0))
1308 bias
.f
= ctx
->Texture
.Unit
[1].LodBias
;
1310 /* if the value is >= 15.9375 determine whether >= 16
1313 if(((bias
.i
) & 0x7FFFFFFF) >= 0x417F0000)
1315 if((bias
.i
) & 0x80000000)
1326 ul
=(GLuint
)(bias
.f
*16.0);
1330 imesa
->regs
.s4
.texCtrl
[1].ni
.dBias
= ul
;
1333 imesa
->regs
.s4
.texDescr
.ni
.tex1En
= GL_TRUE
;
1334 imesa
->regs
.s4
.texDescr
.ni
.tex1Width
= t
->image
[0].image
->WidthLog2
;
1335 imesa
->regs
.s4
.texDescr
.ni
.tex1Height
= t
->image
[0].image
->HeightLog2
;
1336 imesa
->regs
.s4
.texDescr
.ni
.tex1Fmt
= t
->image
[0].internalFormat
;
1337 imesa
->regs
.s4
.texCtrl
[1].ni
.dMax
= t
->max_level
;
1338 imesa
->regs
.s4
.texDescr
.ni
.texBLoopEn
= GL_TRUE
;
1340 imesa
->regs
.s4
.texAddr
[1].ui
= (GLuint
) t
->texParams
.hwPhysAddress
| 2;
1341 if(t
->heap
== SAVAGE_AGP_HEAP
)
1342 imesa
->regs
.s4
.texAddr
[1].ui
|= 0x1;
1344 static void savageUpdateTexState_s3d( GLcontext
*ctx
)
1346 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
1347 struct gl_texture_object
*tObj
;
1348 savageTextureObjectPtr t
;
1352 if (ctx
->Texture
.Unit
[0]._ReallyEnabled
== 0) {
1353 imesa
->regs
.s3d
.texCtrl
.ui
= 0;
1354 imesa
->regs
.s3d
.texCtrl
.ni
.texEn
= GL_FALSE
;
1355 imesa
->regs
.s3d
.texCtrl
.ni
.dBias
= 0x08;
1356 imesa
->regs
.s3d
.texCtrl
.ni
.texXprEn
= GL_TRUE
;
1357 imesa
->regs
.s3d
.texAddr
.ui
= 0;
1361 tObj
= ctx
->Texture
.Unit
[0]._Current
;
1362 if (ctx
->Texture
.Unit
[0]._ReallyEnabled
!= TEXTURE_2D_BIT
||
1363 tObj
->Image
[0][tObj
->BaseLevel
]->Border
> 0) {
1364 /* 1D or 3D texturing enabled, or texture border - fallback */
1365 FALLBACK (ctx
, SAVAGE_FALLBACK_TEXTURE
, GL_TRUE
);
1369 /* Do 2D texture setup */
1370 t
= tObj
->DriverData
;
1372 t
= savageAllocTexObj( tObj
);
1377 if (t
->current_unit
!= 0)
1378 savageTexSetUnit( t
, 0 );
1380 imesa
->CurrentTexObj
[0] = t
;
1383 if (t
->dirty_images
) {
1384 savageSetTexImages(imesa
, tObj
);
1385 savageUploadTexImages(imesa
, imesa
->CurrentTexObj
[0]);
1389 savageUpdateTexLRU( imesa
, t
);
1391 format
= tObj
->Image
[0][tObj
->BaseLevel
]->Format
;
1393 /* FIXME: copied from utah-glx, probably needs some tuning */
1394 switch (ctx
->Texture
.Unit
[0].EnvMode
) {
1396 imesa
->regs
.s3d
.drawCtrl
.ni
.texBlendCtrl
= SAVAGETBC_DECAL_S3D
;
1399 imesa
->regs
.s3d
.drawCtrl
.ni
.texBlendCtrl
= SAVAGETBC_COPY_S3D
;
1401 case GL_BLEND
: /* FIXIT */
1403 imesa
->regs
.s3d
.drawCtrl
.ni
.texBlendCtrl
= SAVAGETBC_MODULATEALPHA_S3D
;
1406 fprintf(stderr
, "unkown tex env mode\n");
1411 imesa
->regs
.s3d
.drawCtrl
.ni
.flushPdDestWrites
= GL_TRUE
;
1412 imesa
->regs
.s3d
.drawCtrl
.ni
.flushPdZbufWrites
= GL_TRUE
;
1414 /* FIXME: this is how the utah-driver works. I doubt it's the ultimate
1416 imesa
->regs
.s3d
.texCtrl
.ni
.uWrapEn
= 0;
1417 imesa
->regs
.s3d
.texCtrl
.ni
.vWrapEn
= 0;
1418 if (t
->texParams
.sWrapMode
== GL_CLAMP
)
1419 imesa
->regs
.s3d
.texCtrl
.ni
.wrapMode
= TAM_Clamp
;
1421 imesa
->regs
.s3d
.texCtrl
.ni
.wrapMode
= TAM_Wrap
;
1423 switch (t
->texParams
.minFilter
) {
1425 imesa
->regs
.s3d
.texCtrl
.ni
.filterMode
= TFM_Point
;
1426 imesa
->regs
.s3d
.texCtrl
.ni
.mipmapDisable
= GL_TRUE
;
1430 imesa
->regs
.s3d
.texCtrl
.ni
.filterMode
= TFM_Bilin
;
1431 imesa
->regs
.s3d
.texCtrl
.ni
.mipmapDisable
= GL_TRUE
;
1434 case GL_NEAREST_MIPMAP_NEAREST
:
1435 imesa
->regs
.s3d
.texCtrl
.ni
.filterMode
= TFM_Point
;
1436 imesa
->regs
.s3d
.texCtrl
.ni
.mipmapDisable
= GL_FALSE
;
1439 case GL_LINEAR_MIPMAP_NEAREST
:
1440 imesa
->regs
.s3d
.texCtrl
.ni
.filterMode
= TFM_Bilin
;
1441 imesa
->regs
.s3d
.texCtrl
.ni
.mipmapDisable
= GL_FALSE
;
1444 case GL_NEAREST_MIPMAP_LINEAR
:
1445 case GL_LINEAR_MIPMAP_LINEAR
:
1446 imesa
->regs
.s3d
.texCtrl
.ni
.filterMode
= TFM_Trilin
;
1447 imesa
->regs
.s3d
.texCtrl
.ni
.mipmapDisable
= GL_FALSE
;
1451 /* There is no way to specify a maximum mipmap level. We may have to
1452 disable mipmapping completely. */
1454 if (t->max_level < t->image[0].image->WidthLog2 ||
1455 t->max_level < t->image[0].image->HeightLog2) {
1456 texCtrl.ni.mipmapEnable = GL_TRUE;
1457 if (texCtrl.ni.filterMode == TFM_Trilin)
1458 texCtrl.ni.filterMode = TFM_Bilin;
1459 texCtrl.ni.filterMode = TFM_Point;
1463 /* LOD bias makes corruption of small mipmap levels worse on Savage IX
1464 * but doesn't show the desired effect with the lodbias mesa demo. */
1465 imesa
->regs
.s3d
.texCtrl
.ni
.dBias
= 0;
1467 imesa
->regs
.s3d
.texCtrl
.ni
.texEn
= GL_TRUE
;
1468 imesa
->regs
.s3d
.texDescr
.ni
.texWidth
= t
->image
[0].image
->WidthLog2
;
1469 imesa
->regs
.s3d
.texDescr
.ni
.texHeight
= t
->image
[0].image
->HeightLog2
;
1470 assert (t
->image
[0].internalFormat
<= 7);
1471 imesa
->regs
.s3d
.texDescr
.ni
.texFmt
= t
->image
[0].internalFormat
;
1473 imesa
->regs
.s3d
.texAddr
.ni
.addr
= (GLuint
) t
->texParams
.hwPhysAddress
>> 3;
1474 if(t
->heap
== SAVAGE_AGP_HEAP
) {
1475 imesa
->regs
.s3d
.texAddr
.ni
.inSysTex
= 1;
1476 imesa
->regs
.s3d
.texAddr
.ni
.inAGPTex
= 1;
1478 imesa
->regs
.s3d
.texAddr
.ni
.inSysTex
= 0;
1479 imesa
->regs
.s3d
.texAddr
.ni
.inAGPTex
= 1;
1485 static void savageUpdateTextureState_s4( GLcontext
*ctx
)
1487 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
1488 if (imesa
->CurrentTexObj
[0]) imesa
->CurrentTexObj
[0]->bound
&= ~1;
1489 if (imesa
->CurrentTexObj
[1]) imesa
->CurrentTexObj
[1]->bound
&= ~2;
1490 imesa
->CurrentTexObj
[0] = 0;
1491 imesa
->CurrentTexObj
[1] = 0;
1492 FALLBACK (ctx
, SAVAGE_FALLBACK_TEXTURE
, GL_FALSE
);
1493 savageUpdateTex0State_s4( ctx
);
1494 savageUpdateTex1State_s4( ctx
);
1495 imesa
->dirty
|= (SAVAGE_UPLOAD_CTX
|
1496 SAVAGE_UPLOAD_TEX0
|
1497 SAVAGE_UPLOAD_TEX1
);
1499 static void savageUpdateTextureState_s3d( GLcontext
*ctx
)
1501 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
1502 if (imesa
->CurrentTexObj
[0]) imesa
->CurrentTexObj
[0]->bound
&= ~1;
1503 imesa
->CurrentTexObj
[0] = 0;
1504 if (ctx
->Texture
.Unit
[1]._ReallyEnabled
) {
1505 FALLBACK (ctx
, SAVAGE_FALLBACK_TEXTURE
, GL_TRUE
);
1507 FALLBACK (ctx
, SAVAGE_FALLBACK_TEXTURE
, GL_FALSE
);
1508 savageUpdateTexState_s3d( ctx
);
1509 imesa
->dirty
|= (SAVAGE_UPLOAD_CTX
|
1510 SAVAGE_UPLOAD_TEX0
);
1513 void savageUpdateTextureState( GLcontext
*ctx
)
1515 savageContextPtr imesa
= SAVAGE_CONTEXT( ctx
);
1516 if (imesa
->savageScreen
->chipset
>= S3_SAVAGE4
)
1517 savageUpdateTextureState_s4 (ctx
);
1519 savageUpdateTextureState_s3d (ctx
);
1524 /*****************************************
1526 *****************************************/
1528 static void savageTexEnv( GLcontext
*ctx
, GLenum target
,
1529 GLenum pname
, const GLfloat
*param
)
1531 savageContextPtr imesa
= SAVAGE_CONTEXT( ctx
);
1533 if (pname
== GL_TEXTURE_ENV_MODE
) {
1535 imesa
->new_state
|= SAVAGE_NEW_TEXTURE
;
1537 } else if (pname
== GL_TEXTURE_ENV_COLOR
) {
1539 struct gl_texture_unit
*texUnit
=
1540 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1541 const GLfloat
*fc
= texUnit
->EnvColor
;
1542 GLuint r
, g
, b
, a
, col
;
1543 CLAMPED_FLOAT_TO_UBYTE(r
, fc
[0]);
1544 CLAMPED_FLOAT_TO_UBYTE(g
, fc
[1]);
1545 CLAMPED_FLOAT_TO_UBYTE(b
, fc
[2]);
1546 CLAMPED_FLOAT_TO_UBYTE(a
, fc
[3]);
1557 static void savageTexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
1558 GLint internalFormat
,
1559 GLint width
, GLint height
, GLint border
,
1560 GLenum format
, GLenum type
, const GLvoid
*pixels
,
1561 const struct gl_pixelstore_attrib
*packing
,
1562 struct gl_texture_object
*texObj
,
1563 struct gl_texture_image
*texImage
)
1565 savageTextureObjectPtr t
= (savageTextureObjectPtr
) texObj
->DriverData
;
1567 savageSwapOutTexObj( SAVAGE_CONTEXT(ctx
), t
);
1569 t
= savageAllocTexObj(texObj
);
1571 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
1575 _mesa_store_teximage2d( ctx
, target
, level
, internalFormat
,
1576 width
, height
, border
, format
, type
,
1577 pixels
, packing
, texObj
, texImage
);
1578 t
->dirty_images
|= (1 << level
);
1579 SAVAGE_CONTEXT(ctx
)->new_state
|= SAVAGE_NEW_TEXTURE
;
1582 static void savageTexSubImage2D( GLcontext
*ctx
,
1585 GLint xoffset
, GLint yoffset
,
1586 GLsizei width
, GLsizei height
,
1587 GLenum format
, GLenum type
,
1588 const GLvoid
*pixels
,
1589 const struct gl_pixelstore_attrib
*packing
,
1590 struct gl_texture_object
*texObj
,
1591 struct gl_texture_image
*texImage
)
1593 savageTextureObjectPtr t
= (savageTextureObjectPtr
) texObj
->DriverData
;
1594 assert( t
); /* this _should_ be true */
1596 savageSwapOutTexObj( SAVAGE_CONTEXT(ctx
), t
);
1598 t
= savageAllocTexObj(texObj
);
1600 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
1604 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
1605 height
, format
, type
, pixels
, packing
, texObj
,
1607 t
->dirty_images
|= (1 << level
);
1608 SAVAGE_CONTEXT(ctx
)->new_state
|= SAVAGE_NEW_TEXTURE
;
1611 static void savageTexParameter( GLcontext
*ctx
, GLenum target
,
1612 struct gl_texture_object
*tObj
,
1613 GLenum pname
, const GLfloat
*params
)
1615 savageTextureObjectPtr t
= (savageTextureObjectPtr
) tObj
->DriverData
;
1616 savageContextPtr imesa
= SAVAGE_CONTEXT( ctx
);
1618 if (!t
|| target
!= GL_TEXTURE_2D
)
1622 case GL_TEXTURE_MIN_FILTER
:
1623 case GL_TEXTURE_MAG_FILTER
:
1624 savageSetTexFilter(t
,tObj
->MinFilter
,tObj
->MagFilter
);
1627 case GL_TEXTURE_WRAP_S
:
1628 case GL_TEXTURE_WRAP_T
:
1629 savageSetTexWrapping(t
,tObj
->WrapS
,tObj
->WrapT
);
1632 case GL_TEXTURE_BORDER_COLOR
:
1633 savageSetTexBorderColor(t
,tObj
->_BorderChan
);
1640 imesa
->new_state
|= SAVAGE_NEW_TEXTURE
;
1643 static void savageBindTexture( GLcontext
*ctx
, GLenum target
,
1644 struct gl_texture_object
*tObj
)
1646 savageContextPtr imesa
= SAVAGE_CONTEXT( ctx
);
1648 assert( (target
!= GL_TEXTURE_2D
) || (tObj
->DriverData
!= NULL
) );
1650 imesa
->new_state
|= SAVAGE_NEW_TEXTURE
;
1653 static void savageDeleteTexture( GLcontext
*ctx
, struct gl_texture_object
*tObj
)
1655 savageTextureObjectPtr t
= (savageTextureObjectPtr
)tObj
->DriverData
;
1656 savageContextPtr imesa
= SAVAGE_CONTEXT( ctx
);
1661 imesa
->CurrentTexObj
[t
->bound
-1] = 0;
1662 imesa
->new_state
|= SAVAGE_NEW_TEXTURE
;
1665 savageDestroyTexObj(imesa
,t
);
1668 /* Free mipmap images and the texture object itself */
1669 _mesa_delete_texture_object(ctx
, tObj
);
1673 static GLboolean
savageIsTextureResident( GLcontext
*ctx
,
1674 struct gl_texture_object
*t
)
1676 savageTextureObjectPtr mt
;
1678 /* LOCK_HARDWARE; */
1679 mt
= (savageTextureObjectPtr
)t
->DriverData
;
1680 /* UNLOCK_HARDWARE; */
1682 return mt
&& mt
->MemBlock
;
1686 static struct gl_texture_object
*
1687 savageNewTextureObject( GLcontext
*ctx
, GLuint name
, GLenum target
)
1689 struct gl_texture_object
*obj
;
1690 obj
= _mesa_new_texture_object(ctx
, name
, target
);
1691 savageAllocTexObj( obj
);
1696 void savageDDInitTextureFuncs( struct dd_function_table
*functions
)
1698 functions
->TexEnv
= savageTexEnv
;
1699 functions
->ChooseTextureFormat
= savageChooseTextureFormat
;
1700 functions
->TexImage2D
= savageTexImage2D
;
1701 functions
->TexSubImage2D
= savageTexSubImage2D
;
1702 functions
->BindTexture
= savageBindTexture
;
1703 functions
->NewTextureObject
= savageNewTextureObject
;
1704 functions
->DeleteTexture
= savageDeleteTexture
;
1705 functions
->IsTextureResident
= savageIsTextureResident
;
1706 functions
->TexParameter
= savageTexParameter
;