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 /* declarations of static and inline functions */
48 __inline GLuint
GetTiledCoordinates8(GLuint iBufferWidth
, GLint x
, GLint y
);
49 static GLuint
GetTiledCoordinates16_4( GLint iBufferWidth
,GLint x
,GLint y
);
50 static GLuint
GetTiledCoordinates16_8( GLint iBufferWidth
,GLint x
,GLint y
);
51 static GLuint
GetTiledCoordinates32_4( GLint iBufferWidth
, GLint x
, GLint y
);
52 static GLuint
GetTiledCoordinates32_8( GLint iBufferWidth
, GLint x
, GLint y
);
53 __inline GLuint
GetTiledCoordinates( GLint iDepth
,GLint iBufferWidth
,GLint x
,GLint y
);
54 __inline
void savageUploadImage(savageTextureObjectPtr t
, GLuint level
, GLuint startx
, GLuint starty
, GLuint reloc
);
55 __inline
void savageTileTex(savageTextureObjectPtr tex
, GLuint level
);
57 /* tile sizes depending on texel color depth */
58 GLuint gTileWidth
[5] =
67 GLuint gTileHeight
[5] =
76 __inline GLuint
GetTiledCoordinates8(GLuint iBufferWidth
, GLint x
, GLint y
)
82 uWidthInTiles
= (iBufferWidth
+ 63) >> 6;
84 x52
= (x
& 0x3c) >> 2;
85 x106
= (x
& 0x7c0) >> 6;
88 y43
= (y
& 0x18) >> 3;
89 y105
= (y
& 0x7e0) >> 5;
95 ((y105
* uWidthInTiles
) + x106
) << 11 );
98 /* 4-pixel wide subtiles */
99 static GLuint
GetTiledCoordinates16_4( GLint iBufferWidth
,
109 GLuint uiWidthInTiles
;
112 // calculating tiled address
115 uiWidthInTiles
= (iBufferWidth
+ 63) >> 6;
118 x52
= (x
& 0x3c ) >> 2;
119 x106
= (x
& 0x7c0) >> 6;
123 y104
= (y
& 0x7f0) >> 4;
129 ((y104
* uiWidthInTiles
) + x106
) << 11 );
131 /* 8-pixel wide subtiles */
132 static GLuint
GetTiledCoordinates16_8( GLint iBufferWidth
,
142 GLuint uiWidthInTiles
;
145 // calculating tiled address
148 uiWidthInTiles
= (iBufferWidth
+ 63) >> 6;
151 x53
= (x
& 0x38 ) >> 3;
152 x106
= (x
& 0x7c0) >> 6;
156 y104
= (y
& 0x7f0) >> 4;
162 ((y104
* uiWidthInTiles
) + x106
) << 11 );
164 /* function pointer set to the correct version in savageDDInitTextureFuncs */
165 GLuint (*GetTiledCoordinates16
) (GLint
, GLint
, GLint
);
167 /* 4-pixel wide subtiles */
168 static GLuint
GetTiledCoordinates32_4( GLint iBufferWidth
,
174 GLuint uiWidthInTiles
;
181 // calculating tiled address
184 uiWidthInTiles
= (iBufferWidth
+ 31) >> 5;
187 x42
= (x
& 0x1c ) >> 2;
188 x105
= (x
& 0x7e0) >> 5;
192 y104
= (y
& 0x7f0) >> 4;
198 ((y104
* uiWidthInTiles
) + x105
) << 11 );
200 /* 8-pixel wide subtiles */
201 static GLuint
GetTiledCoordinates32_8( GLint iBufferWidth
,
207 GLuint uiWidthInTiles
;
214 // calculating tiled address
217 uiWidthInTiles
= (iBufferWidth
+ 31) >> 5;
220 x43
= (x
& 0x18 ) >> 3;
221 x105
= (x
& 0x7e0) >> 5;
225 y104
= (y
& 0x7f0) >> 4;
231 ((y104
* uiWidthInTiles
) + x105
) << 11 );
233 /* function pointer set to the correct version in savageDDInitTextureFuncs */
234 GLuint (*GetTiledCoordinates32
) (GLint
, GLint
, GLint
);
236 __inline GLuint
GetTiledCoordinates( GLint iDepth
,
242 // don't check for 4 since we only have 3 types of fb
247 return( GetTiledCoordinates16( iBufferWidth
, x
, y
) );
249 else if (iDepth
== 32)
251 return( GetTiledCoordinates32( iBufferWidth
, x
, y
) );
255 return( GetTiledCoordinates8( iBufferWidth
, x
, y
) );
259 __inline
void savageUploadImage(savageTextureObjectPtr t
, GLuint level
, GLuint startx
, GLuint starty
, GLuint reloc
)
261 GLuint uMaxTileWidth
= gTileWidth
[t
->texelBytes
];
262 GLuint x
, y
, w
, row
, col
;
263 const struct gl_texture_image
*image
= t
->image
[level
].image
;
264 GLubyte
* dst
, * src
, * pBuffer
;
266 GLuint uRowSeparator
, uChunk
= MIN_TILE_CHUNK
, uWrap
;
269 pBuffer
= (GLubyte
*)(t
->BufAddr
+ t
->image
[level
].offset
);
270 src
= (GLubyte
*)image
->Data
;
275 if(image
->Format
== GL_COLOR_INDEX
)
277 if(w
< MIN_TILE_CHUNK
)
283 if((w
> 64 ) && (image
->Height
<= 16))
286 if(image
->Height
== 16)
288 uChunk
= MIN_TILE_CHUNK
<< 1;
293 if(!reloc
& (w
> (64 / 2)))
295 for(row
= 0; row
< image
->Height
; row
++)
297 for(col
= 0; col
< image
->Width
; col
++)
299 dst
= pBuffer
+ GetTiledCoordinates(t
->texelBytes
<< 3, w
, x
+ col
, y
+ row
);
300 memcpy (dst
, src
, t
->texelBytes
);
301 src
+= t
->texelBytes
;
309 uWrap
= ((w
+ 63) >> 6) - 1;
310 for(row
= 0; row
< image
->Height
; row
++)
312 for(col
= 0; col
< image
->Width
; col
++)
314 xAdd
= (col
/ (4 * 64)) * 64 + col
% 64;
315 yAdd
= row
+ ((col
/ 64) & 3) * uChunk
;
316 dst
= pBuffer
+ GetTiledCoordinates(t
->texelBytes
<< 3, 64, x
+ xAdd
, y
+ yAdd
);
317 memcpy (dst
, src
, t
->texelBytes
);
318 src
+= t
->texelBytes
;
324 uRowSeparator
= 64 * MIN_TILE_CHUNK
/ w
;
325 for(row
= 0; row
< image
->Height
; row
++)
327 xAdd
= (w
* (row
/ MIN_TILE_CHUNK
)) % 64;
328 yAdd
= row
% MIN_TILE_CHUNK
+ MIN_TILE_CHUNK
* (row
/ uRowSeparator
);
329 for(col
= 0; col
< image
->Width
; col
++)
331 dst
= pBuffer
+ GetTiledCoordinates(t
->texelBytes
<< 3, w
, x
+ xAdd
, y
+ yAdd
);
332 memcpy (dst
, src
, t
->texelBytes
);
333 src
+= t
->texelBytes
;
341 if(w
< MIN_TILE_CHUNK
)
347 if((w
> uMaxTileWidth
) && (image
->Height
<= 8))
352 if(!reloc
& (w
> uMaxTileWidth
/ 2))
354 for(row
= 0; row
< image
->Height
; row
++)
356 for(col
= 0; col
< image
->Width
; col
++)
358 dst
= pBuffer
+ GetTiledCoordinates(t
->texelBytes
<< 3, w
, x
+ col
, y
+ row
);
359 memcpy (dst
, src
, t
->texelBytes
);
360 src
+= t
->texelBytes
;
366 if(reloc
& (w
> uMaxTileWidth
))
368 for(row
= 0; row
< image
->Height
; row
++)
370 for(col
= 0; col
< image
->Width
; col
++)
372 xAdd
= (col
/ (2 * uMaxTileWidth
)) * uMaxTileWidth
+ col
% uMaxTileWidth
;
373 yAdd
= row
+ ((col
/ uMaxTileWidth
) & 1) * MIN_TILE_CHUNK
;
374 dst
= pBuffer
+ GetTiledCoordinates(t
->texelBytes
<< 3, w
, x
+ xAdd
, y
+ yAdd
);
375 memcpy (dst
, src
, t
->texelBytes
);
376 src
+= t
->texelBytes
;
382 uRowSeparator
= uMaxTileWidth
* MIN_TILE_CHUNK
/ w
;
383 for(row
= 0; row
< image
->Height
; row
++)
385 yAdd
= row
% MIN_TILE_CHUNK
+ MIN_TILE_CHUNK
* (row
/ uRowSeparator
);
386 xAdd
= (w
* (row
/ MIN_TILE_CHUNK
)) % uMaxTileWidth
;
387 for(col
= 0; col
< image
->Width
; col
++)
389 dst
= pBuffer
+ GetTiledCoordinates(t
->texelBytes
<< 3, w
, x
+ col
+ xAdd
, y
+ yAdd
);
390 memcpy (dst
, src
, t
->texelBytes
);
391 src
+= t
->texelBytes
;
401 __inline
void savageTileTex(savageTextureObjectPtr tex
, GLuint level
)
403 GLuint uWidth
, uHeight
;
404 GLint xOffset
, yOffset
;
405 GLint xStart
=0, yStart
=0;
407 GLuint xRepeat
, yRepeat
;
408 GLuint startCol
, startRow
;
411 const struct gl_texture_image
*image
= tex
->image
[level
].image
;
414 uWidth
= image
->Width2
;
415 uHeight
= image
->Height2
;
417 if((uWidth
> 4) || (uHeight
> 4))
418 minSize
= MIN_TILE_CHUNK
;
420 minSize
= MIPMAP_CHUNK
;
422 if(image
->Width
>= minSize
)
425 xRepeat
= minSize
/ image
->Width
;
427 if(image
->Height
>= minSize
)
431 yRepeat
= minSize
/ image
->Height
;
432 if(minSize
== MIN_TILE_CHUNK
)
436 if(((uWidth
< 4) && (uHeight
< 4)) && (tex
->texelBytes
>= 2))
438 if((uWidth
== 2) || (uHeight
== 2))
450 for(xOffset
= 0; xOffset
< xRepeat
; xOffset
++)
452 for(yOffset
= 0; yOffset
< yRepeat
; yOffset
++)
454 startCol
= image
->Width
* xOffset
+ xStart
;
455 startRow
= image
->Height
* yOffset
+ yStart
;
456 savageUploadImage(tex
,level
, startCol
, startRow
, reloc
);
461 static void savageSetTexWrapping(savageTextureObjectPtr tex
, GLenum s
, GLenum t
)
463 tex
->texParams
.sWrapMode
= s
;
464 tex
->texParams
.tWrapMode
= t
;
467 static void savageSetTexFilter(savageTextureObjectPtr t
,
468 GLenum minf
, GLenum magf
)
470 t
->texParams
.minFilter
= minf
;
471 t
->texParams
.magFilter
= magf
;
477 static void savageSetTexBorderColor(savageTextureObjectPtr t
, GLubyte color
[4])
479 /* t->Setup[SAVAGE_TEXREG_TEXBORDERCOL] = */
480 t
->texParams
.boarderColor
= SAVAGEPACKCOLOR8888(color
[0],color
[1],color
[2],color
[3]);
485 static savageTextureObjectPtr
486 savageAllocTexObj( struct gl_texture_object
*texObj
)
488 savageTextureObjectPtr t
;
490 t
= (savageTextureObjectPtr
) calloc(1,sizeof(*t
));
491 texObj
->DriverData
= t
;
494 /* Initialize non-image-dependent parts of the state:
498 /* FIXME Something here to set initial values for other parts of
502 make_empty_list( t
);
504 savageSetTexWrapping(t
,texObj
->WrapS
,texObj
->WrapT
);
505 savageSetTexFilter(t
,texObj
->MinFilter
,texObj
->MagFilter
);
506 savageSetTexBorderColor(t
,texObj
->_BorderChan
);
512 /* Called by the _mesa_store_teximage[123]d() functions. */
513 static const struct gl_texture_format
*
514 savageChooseTextureFormat( GLcontext
*ctx
, GLint internalFormat
,
515 GLenum format
, GLenum type
)
517 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
518 const GLboolean do32bpt
= GL_FALSE
;
519 const GLboolean force16bpt
= GL_FALSE
;
520 const GLboolean isSavage4
= (imesa
->savageScreen
->chipset
>= S3_SAVAGE4
);
524 switch ( internalFormat
) {
527 case GL_COMPRESSED_RGBA
:
529 case GL_UNSIGNED_INT_10_10_10_2
:
530 case GL_UNSIGNED_INT_2_10_10_10_REV
:
531 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb1555
;
532 case GL_UNSIGNED_SHORT_4_4_4_4
:
533 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
534 return &_mesa_texformat_argb4444
;
535 case GL_UNSIGNED_SHORT_5_5_5_1
:
536 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
537 return &_mesa_texformat_argb1555
;
539 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
;
544 case GL_COMPRESSED_RGB
:
546 case GL_UNSIGNED_SHORT_4_4_4_4
:
547 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
548 return &_mesa_texformat_argb4444
;
549 case GL_UNSIGNED_SHORT_5_5_5_1
:
550 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
551 return &_mesa_texformat_argb1555
;
552 case GL_UNSIGNED_SHORT_5_6_5
:
553 case GL_UNSIGNED_SHORT_5_6_5_REV
:
554 return &_mesa_texformat_rgb565
;
556 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_rgb565
;
563 &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
;
567 &_mesa_texformat_argb8888
: &_mesa_texformat_argb1555
;
571 return &_mesa_texformat_argb4444
;
574 return &_mesa_texformat_argb1555
;
580 return !force16bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_rgb565
;
585 return &_mesa_texformat_rgb565
;
588 case GL_COMPRESSED_ALPHA
:
589 return isSavage4
? &_mesa_texformat_a8
: (
590 do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
);
592 return isSavage4
? &_mesa_texformat_a8
: &_mesa_texformat_argb4444
;
596 return isSavage4
? &_mesa_texformat_a8
: (
597 !force16bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
);
601 case GL_COMPRESSED_LUMINANCE
:
602 /* no alpha, but use argb1555 in 16bit case to get pure grey values */
603 return isSavage4
? &_mesa_texformat_l8
: (
604 do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb1555
);
606 return isSavage4
? &_mesa_texformat_l8
: &_mesa_texformat_argb1555
;
610 return isSavage4
? &_mesa_texformat_l8
: (
611 !force16bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb1555
);
614 case GL_LUMINANCE_ALPHA
:
615 case GL_COMPRESSED_LUMINANCE_ALPHA
:
616 /* Savage4 has a al44 texture format. But it's not supported by Mesa. */
617 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
;
618 case GL_LUMINANCE4_ALPHA4
:
619 case GL_LUMINANCE6_ALPHA2
:
620 return &_mesa_texformat_argb4444
;
621 case GL_LUMINANCE8_ALPHA8
:
622 case GL_LUMINANCE12_ALPHA4
:
623 case GL_LUMINANCE12_ALPHA12
:
624 case GL_LUMINANCE16_ALPHA16
:
625 return !force16bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
;
628 case GL_COMPRESSED_INTENSITY
:
629 return isSavage4
? &_mesa_texformat_i8
: (
630 do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
);
632 return isSavage4
? &_mesa_texformat_i8
: &_mesa_texformat_argb4444
;
636 return isSavage4
? &_mesa_texformat_i8
: (
637 !force16bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
);
640 case GL_COLOR_INDEX1_EXT:
641 case GL_COLOR_INDEX2_EXT:
642 case GL_COLOR_INDEX4_EXT:
643 case GL_COLOR_INDEX8_EXT:
644 case GL_COLOR_INDEX12_EXT:
645 case GL_COLOR_INDEX16_EXT:
646 return &_mesa_texformat_ci8;
649 _mesa_problem(ctx
, "unexpected texture format in %s", __FUNCTION__
);
654 static void savageSetTexImages( savageContextPtr imesa
,
655 const struct gl_texture_object
*tObj
)
657 savageTextureObjectPtr t
= (savageTextureObjectPtr
) tObj
->DriverData
;
658 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
659 GLuint offset
, width
, pitch
, i
, textureFormat
, log_pitch
;
664 switch (image
->TexFormat
->MesaFormat
) {
665 case MESA_FORMAT_ARGB8888
:
666 textureFormat
= TFT_ARGB8888
;
669 case MESA_FORMAT_ARGB1555
:
670 textureFormat
= TFT_ARGB1555
;
673 case MESA_FORMAT_ARGB4444
:
674 textureFormat
= TFT_ARGB4444
;
677 case MESA_FORMAT_RGB565
:
678 textureFormat
= TFT_RGB565
;
682 textureFormat
= TFT_L8
;
686 textureFormat
= TFT_I8
;
690 textureFormat
= TFT_A8
;
694 _mesa_problem(imesa
->glCtx
, "Bad texture format in %s", __FUNCTION__
);
697 /* Figure out the size now (and count the levels). Upload won't be done
700 width
= image
->Width
* t
->texelBytes
;
701 for (pitch
= 2, log_pitch
=1 ; pitch
< width
; pitch
*= 2 )
707 for ( i
= 0 ; i
< SAVAGE_TEX_MAXLEVELS
&& tObj
->Image
[0][i
] ; i
++ ) {
708 t
->image
[i
].image
= tObj
->Image
[0][i
];
709 t
->image
[i
].offset
= offset
;
710 t
->image
[i
].internalFormat
= textureFormat
;
711 t
->dirty_images
|= (1<<i
);
712 offset
+= t
->image
[i
].image
->Height
* pitch
;
716 t
->totalSize
= offset
;
721 void savageDestroyTexObj(savageContextPtr imesa
, savageTextureObjectPtr t
)
725 /* This is sad - need to sync *in case* we upload a texture
726 * to this newly free memory...
729 mmFreeMem(t
->MemBlock
);
732 if (t
->age
> imesa
->dirtyAge
)
733 imesa
->dirtyAge
= t
->age
;
737 t
->globj
->DriverData
= 0;
744 static void savageSwapOutTexObj(savageContextPtr imesa
, savageTextureObjectPtr t
)
747 mmFreeMem(t
->MemBlock
);
750 if (t
->age
> imesa
->dirtyAge
)
751 imesa
->dirtyAge
= t
->age
;
754 t
->dirty_images
= ~0;
755 move_to_tail(&(imesa
->SwappedOut
), t
);
760 /* Upload an image from mesa's internal copy.
762 static void savageUploadTexLevel( savageTextureObjectPtr t
, int level
)
764 const struct gl_texture_image
*image
= t
->image
[level
].image
;
767 /* Need triangle (rather than pixel) fallbacks to simulate this using
768 * normal textured triangles.
770 * DO THIS IN DRIVER STATE MANAGMENT, not hardware state.
774 if(image
->Border
!= 0)
775 fprintf (stderr
, "Not supported texture border %d.\n",
776 (int) image
->Border
);
778 savageTileTex(t
, level
);
783 void savagePrintLocalLRU( savageContextPtr imesa
, GLuint heap
)
785 savageTextureObjectPtr t
;
786 int sz
= 1 << (imesa
->savageScreen
->logTextureGranularity
[heap
]);
788 foreach( t
, &imesa
->TexObjList
[heap
] ) {
790 fprintf(stderr
, "Placeholder %d at %x sz %x\n",
791 t
->MemBlock
->ofs
/ sz
,
795 fprintf(stderr
, "Texture (bound %d) at %x sz %x\n",
803 void savagePrintGlobalLRU( savageContextPtr imesa
, GLuint heap
)
807 drm_savage_tex_region_t
*list
= imesa
->sarea
->texList
[heap
];
810 for (i
= 0, j
= SAVAGE_NR_TEX_REGIONS
; i
< SAVAGE_NR_TEX_REGIONS
; i
++) {
811 fprintf(stderr
, "list[%d] age %d next %d prev %d\n",
812 j
, list
[j
].age
, list
[j
].next
, list
[j
].prev
);
814 if (j
== SAVAGE_NR_TEX_REGIONS
) break;
817 if (j
!= SAVAGE_NR_TEX_REGIONS
)
818 fprintf(stderr
, "Loop detected in global LRU\n");
819 for (i
= 0 ; i
< SAVAGE_NR_TEX_REGIONS
; i
++)
821 fprintf(stderr
,"list[%d] age %d next %d prev %d\n",
822 i
, list
[i
].age
, list
[i
].next
, list
[i
].prev
);
827 void savageResetGlobalLRU( savageContextPtr imesa
, GLuint heap
)
829 drm_savage_tex_region_t
*list
= imesa
->sarea
->texList
[heap
];
830 int sz
= 1 << imesa
->savageScreen
->logTextureGranularity
[heap
];
833 /* (Re)initialize the global circular LRU list. The last element
834 * in the array (SAVAGE_NR_TEX_REGIONS) is the sentinal. Keeping it
835 * at the end of the array allows it to be addressed rationally
836 * when looking up objects at a particular location in texture
839 for (i
= 0 ; (i
+1) * sz
<= imesa
->savageScreen
->textureSize
[heap
]; i
++) {
846 list
[0].prev
= SAVAGE_NR_TEX_REGIONS
;
848 list
[i
].next
= SAVAGE_NR_TEX_REGIONS
;
849 list
[SAVAGE_NR_TEX_REGIONS
].prev
= i
;
850 list
[SAVAGE_NR_TEX_REGIONS
].next
= 0;
851 imesa
->sarea
->texAge
[heap
] = 0;
855 static void savageUpdateTexLRU( savageContextPtr imesa
, savageTextureObjectPtr t
)
859 int logsz
= imesa
->savageScreen
->logTextureGranularity
[heap
];
860 int start
= t
->MemBlock
->ofs
>> logsz
;
861 int end
= (t
->MemBlock
->ofs
+ t
->MemBlock
->size
- 1) >> logsz
;
862 drm_savage_tex_region_t
*list
= imesa
->sarea
->texList
[heap
];
864 imesa
->texAge
[heap
] = ++imesa
->sarea
->texAge
[heap
];
866 /* Update our local LRU
868 move_to_head( &(imesa
->TexObjList
[heap
]), t
);
870 /* Update the global LRU
872 for (i
= start
; i
<= end
; i
++) {
875 list
[i
].age
= imesa
->texAge
[heap
];
877 /* remove_from_list(i)
879 list
[(unsigned)list
[i
].next
].prev
= list
[i
].prev
;
880 list
[(unsigned)list
[i
].prev
].next
= list
[i
].next
;
882 /* insert_at_head(list, i)
884 list
[i
].prev
= SAVAGE_NR_TEX_REGIONS
;
885 list
[i
].next
= list
[SAVAGE_NR_TEX_REGIONS
].next
;
886 list
[(unsigned)list
[SAVAGE_NR_TEX_REGIONS
].next
].prev
= i
;
887 list
[SAVAGE_NR_TEX_REGIONS
].next
= i
;
892 /* Called for every shared texture region which has increased in age
893 * since we last held the lock.
895 * Figures out which of our textures have been ejected by other clients,
896 * and pushes a placeholder texture onto the LRU list to represent
897 * the other client's textures.
899 void savageTexturesGone( savageContextPtr imesa
,
905 savageTextureObjectPtr t
, tmp
;
907 foreach_s ( t
, tmp
, &imesa
->TexObjList
[heap
] ) {
909 if (t
->MemBlock
->ofs
>= offset
+ size
||
910 t
->MemBlock
->ofs
+ t
->MemBlock
->size
<= offset
)
913 /* It overlaps - kick it off. Need to hold onto the currently bound
917 savageSwapOutTexObj( imesa
, t
);
919 savageDestroyTexObj( imesa
, t
);
924 t
= (savageTextureObjectPtr
) calloc(1,sizeof(*t
));
928 t
->MemBlock
= mmAllocMem( imesa
->texHeap
[heap
], size
, 0, offset
);
934 insert_at_head( &imesa
->TexObjList
[heap
], t
);
942 /* This is called with the lock held. May have to eject our own and/or
943 * other client's texture objects to make room for the upload.
945 int savageUploadTexImages( savageContextPtr imesa
, savageTextureObjectPtr t
)
951 heap
= t
->heap
= SAVAGE_CARD_HEAP
;
953 /* Do we need to eject LRU texture objects?
958 t
->MemBlock
= mmAllocMem( imesa
->texHeap
[heap
], t
->totalSize
, 12, 0 );
963 heap
= t
->heap
= SAVAGE_AGP_HEAP
;
964 t
->MemBlock
= mmAllocMem( imesa
->texHeap
[heap
], t
->totalSize
, 12, 0 );
970 if (imesa
->TexObjList
[heap
].prev
->bound
) {
971 fprintf(stderr
, "Hit bound texture in upload\n");
972 savagePrintLocalLRU( imesa
,heap
);
976 if (imesa
->TexObjList
[heap
].prev
== &(imesa
->TexObjList
[heap
])) {
977 fprintf(stderr
, "Failed to upload texture, sz %d\n", t
->totalSize
);
978 mmDumpMemInfo( imesa
->texHeap
[heap
] );
982 savageDestroyTexObj( imesa
, imesa
->TexObjList
[heap
].prev
);
985 ofs
= t
->MemBlock
->ofs
;
986 t
->texParams
.hwPhysAddress
= imesa
->savageScreen
->textureOffset
[heap
] + ofs
;
987 t
->BufAddr
= (char *)((GLuint
) imesa
->savageScreen
->texVirtual
[heap
] + ofs
);
988 imesa
->dirty
|= SAVAGE_UPLOAD_CTX
;
991 /* Let the world know we've used this memory recently.
993 savageUpdateTexLRU( imesa
, t
);
995 if (t
->dirty_images
) {
996 if (SAVAGE_DEBUG
& DEBUG_VERBOSE_LRU
)
997 fprintf(stderr
, "*");
999 for (i
= t
->min_level
; i
<= t
->max_level
; i
++)
1000 if (t
->dirty_images
& (1<<i
))
1001 savageUploadTexLevel( t
, i
);
1005 t
->dirty_images
= 0;
1009 static void savageTexSetUnit( savageTextureObjectPtr t
, GLuint unit
)
1011 if (t
->current_unit
== unit
) return;
1013 t
->current_unit
= unit
;
1019 static void savageUpdateTex0State_s4( GLcontext
*ctx
)
1021 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
1022 struct gl_texture_object
*tObj
;
1023 savageTextureObjectPtr t
;
1027 if (ctx
->Texture
.Unit
[0]._ReallyEnabled
== 0) {
1028 imesa
->regs
.s4
.texDescr
.ni
.tex0En
= GL_FALSE
;
1029 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_NoTexMap
;
1030 imesa
->regs
.s4
.texCtrl
[0].ui
= 0x20f040;
1031 imesa
->regs
.s4
.texAddr
[0].ui
= 0;
1035 tObj
= ctx
->Texture
.Unit
[0]._Current
;
1036 if (ctx
->Texture
.Unit
[0]._ReallyEnabled
!= TEXTURE_2D_BIT
||
1037 tObj
->Image
[0][tObj
->BaseLevel
]->Border
> 0) {
1038 /* 1D or 3D texturing enabled, or texture border - fallback */
1039 FALLBACK (ctx
, SAVAGE_FALLBACK_TEXTURE
, GL_TRUE
);
1043 /* Do 2D texture setup */
1045 t
= tObj
->DriverData
;
1047 t
= savageAllocTexObj( tObj
);
1052 if (t
->current_unit
!= 0)
1053 savageTexSetUnit( t
, 0 );
1055 imesa
->CurrentTexObj
[0] = t
;
1058 if (t
->dirty_images
) {
1059 savageSetTexImages(imesa
, tObj
);
1060 savageUploadTexImages(imesa
, imesa
->CurrentTexObj
[0]);
1064 savageUpdateTexLRU( imesa
, t
);
1066 format
= tObj
->Image
[0][tObj
->BaseLevel
]->Format
;
1068 switch (ctx
->Texture
.Unit
[0].EnvMode
) {
1070 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_FALSE
;
1075 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_Decal
;
1078 case GL_LUMINANCE_ALPHA
:
1081 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_Copy
;
1085 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_CopyAlpha
;
1088 __HWEnvCombineSingleUnitScale(imesa
, 0, 0,
1089 &imesa
->regs
.s4
.texBlendCtrl
[0]);
1093 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_FALSE
;
1098 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_Decal
;
1103 case GL_LUMINANCE_ALPHA
:
1104 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_DecalAlpha
;
1108 GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_INTENSITY
1109 are undefined with GL_DECAL
1113 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_CopyAlpha
;
1116 __HWEnvCombineSingleUnitScale(imesa
, 0, 0,
1117 &imesa
->regs
.s4
.texBlendCtrl
[0]);
1121 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_FALSE
;
1122 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_ModulAlpha
;
1123 __HWEnvCombineSingleUnitScale(imesa
, 0, 0,
1124 &imesa
->regs
.s4
.texBlendCtrl
[0]);
1132 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_ModulAlpha
;
1133 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_FALSE
;
1138 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_Blend0
;
1139 imesa
->regs
.s4
.texDescr
.ni
.tex1En
= GL_TRUE
;
1140 imesa
->regs
.s4
.texDescr
.ni
.texBLoopEn
= GL_TRUE
;
1141 imesa
->regs
.s4
.texDescr
.ni
.tex1Width
=
1142 imesa
->regs
.s4
.texDescr
.ni
.tex0Width
;
1143 imesa
->regs
.s4
.texDescr
.ni
.tex1Height
=
1144 imesa
->regs
.s4
.texDescr
.ni
.tex0Height
;
1145 imesa
->regs
.s4
.texDescr
.ni
.tex1Fmt
=
1146 imesa
->regs
.s4
.texDescr
.ni
.tex0Fmt
;
1148 imesa
->regs
.s4
.texAddr
[1].ui
= imesa
->regs
.s4
.texAddr
[0].ui
;
1149 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_Blend1
;
1151 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_TRUE
;
1152 imesa
->bTexEn1
= GL_TRUE
;
1155 case GL_LUMINANCE_ALPHA
:
1157 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_BlendAlpha0
;
1158 imesa
->regs
.s4
.texDescr
.ni
.tex1En
= GL_TRUE
;
1159 imesa
->regs
.s4
.texDescr
.ni
.texBLoopEn
= GL_TRUE
;
1160 imesa
->regs
.s4
.texDescr
.ni
.tex1Width
=
1161 imesa
->regs
.s4
.texDescr
.ni
.tex0Width
;
1162 imesa
->regs
.s4
.texDescr
.ni
.tex1Height
=
1163 imesa
->regs
.s4
.texDescr
.ni
.tex0Height
;
1164 imesa
->regs
.s4
.texDescr
.ni
.tex1Fmt
=
1165 imesa
->regs
.s4
.texDescr
.ni
.tex0Fmt
;
1167 imesa
->regs
.s4
.texAddr
[1].ui
= imesa
->regs
.s4
.texAddr
[0].ui
;
1168 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_BlendAlpha1
;
1170 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_TRUE
;
1171 imesa
->bTexEn1
= GL_TRUE
;
1175 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_BlendInt0
;
1176 imesa
->regs
.s4
.texDescr
.ni
.tex1En
= GL_TRUE
;
1177 imesa
->regs
.s4
.texDescr
.ni
.texBLoopEn
= GL_TRUE
;
1178 imesa
->regs
.s4
.texDescr
.ni
.tex1Width
=
1179 imesa
->regs
.s4
.texDescr
.ni
.tex0Width
;
1180 imesa
->regs
.s4
.texDescr
.ni
.tex1Height
=
1181 imesa
->regs
.s4
.texDescr
.ni
.tex0Height
;
1182 imesa
->regs
.s4
.texDescr
.ni
.tex1Fmt
=
1183 imesa
->regs
.s4
.texDescr
.ni
.tex0Fmt
;
1185 imesa
->regs
.s4
.texAddr
[1].ui
= imesa
->regs
.s4
.texAddr
[0].ui
;
1186 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_BlendInt1
;
1188 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_TRUE
;
1189 imesa
->regs
.s4
.texCtrl
[0].ni
.alphaArg1Invert
= GL_TRUE
;
1190 imesa
->bTexEn1
= GL_TRUE
;
1193 __HWEnvCombineSingleUnitScale(imesa
, 0, 0,
1194 &imesa
->regs
.s4
.texBlendCtrl
[0]);
1202 imesa
->regs
.s4
.texCtrl
[0].ni
.clrArg1Invert
= GL_FALSE
;
1203 imesa
->regs
.s4
.texBlendCtrl
[0].ui
= TBC_AddAlpha
;
1204 __HWEnvCombineSingleUnitScale(imesa
, 0, 0,
1205 &imesa
->regs
.s4
.texBlendCtrl
[0]);
1208 #if GL_ARB_texture_env_combine
1209 case GL_COMBINE_ARB
:
1210 __HWParseTexEnvCombine(imesa
, 0, &imesa
->regs
.s4
.texCtrl
[0],
1211 &imesa
->regs
.s4
.texBlendCtrl
[0]);
1216 fprintf(stderr
, "unknown tex env mode");
1221 imesa
->regs
.s4
.texCtrl
[0].ni
.uMode
= !(t
->texParams
.sWrapMode
& 0x01);
1222 imesa
->regs
.s4
.texCtrl
[0].ni
.vMode
= !(t
->texParams
.tWrapMode
& 0x01);
1224 switch (t
->texParams
.minFilter
)
1227 imesa
->regs
.s4
.texCtrl
[0].ni
.filterMode
= TFM_Point
;
1228 imesa
->regs
.s4
.texCtrl
[0].ni
.mipmapEnable
= GL_FALSE
;
1232 imesa
->regs
.s4
.texCtrl
[0].ni
.filterMode
= TFM_Bilin
;
1233 imesa
->regs
.s4
.texCtrl
[0].ni
.mipmapEnable
= GL_FALSE
;
1236 case GL_NEAREST_MIPMAP_NEAREST
:
1237 imesa
->regs
.s4
.texCtrl
[0].ni
.filterMode
= TFM_Point
;
1238 imesa
->regs
.s4
.texCtrl
[0].ni
.mipmapEnable
= GL_TRUE
;
1241 case GL_LINEAR_MIPMAP_NEAREST
:
1242 imesa
->regs
.s4
.texCtrl
[0].ni
.filterMode
= TFM_Bilin
;
1243 imesa
->regs
.s4
.texCtrl
[0].ni
.mipmapEnable
= GL_TRUE
;
1246 case GL_NEAREST_MIPMAP_LINEAR
:
1247 case GL_LINEAR_MIPMAP_LINEAR
:
1248 imesa
->regs
.s4
.texCtrl
[0].ni
.filterMode
= TFM_Trilin
;
1249 imesa
->regs
.s4
.texCtrl
[0].ni
.mipmapEnable
= GL_TRUE
;
1253 if((ctx
->Texture
.Unit
[0].LodBias
!=0.0F
) &&
1254 (imesa
->regs
.s4
.texCtrl
[0].ni
.dBias
!= 0))
1262 bias
.f
= ctx
->Texture
.Unit
[0].LodBias
;
1264 /* if the value is >= 15.9375 determine whether >= 16
1267 if(((bias
.i
) & 0x7FFFFFFF) >= 0x417F0000)
1269 if((bias
.i
) & 0x80000000)
1280 ul
=(GLuint
)(bias
.f
*16.0);
1284 imesa
->regs
.s4
.texCtrl
[0].ni
.dBias
= ul
;
1287 imesa
->regs
.s4
.texDescr
.ni
.tex0En
= GL_TRUE
;
1288 imesa
->regs
.s4
.texDescr
.ni
.tex0Width
= t
->image
[0].image
->WidthLog2
;
1289 imesa
->regs
.s4
.texDescr
.ni
.tex0Height
= t
->image
[0].image
->HeightLog2
;
1290 imesa
->regs
.s4
.texDescr
.ni
.tex0Fmt
= t
->image
[0].internalFormat
;
1291 imesa
->regs
.s4
.texCtrl
[0].ni
.dMax
= t
->max_level
;
1293 if (imesa
->regs
.s4
.texDescr
.ni
.tex1En
)
1294 imesa
->regs
.s4
.texDescr
.ni
.texBLoopEn
= GL_TRUE
;
1296 imesa
->regs
.s4
.texAddr
[0].ui
= (GLuint
) t
->texParams
.hwPhysAddress
| 0x2;
1297 if(t
->heap
== SAVAGE_AGP_HEAP
)
1298 imesa
->regs
.s4
.texAddr
[0].ui
|= 0x1;
1302 static void savageUpdateTex1State_s4( GLcontext
*ctx
)
1304 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
1305 struct gl_texture_object
*tObj
;
1306 savageTextureObjectPtr t
;
1312 imesa
->bTexEn1
= GL_FALSE
;
1316 if (ctx
->Texture
.Unit
[1]._ReallyEnabled
== 0) {
1317 imesa
->regs
.s4
.texDescr
.ni
.tex1En
= GL_FALSE
;
1318 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_NoTexMap1
;
1319 imesa
->regs
.s4
.texCtrl
[1].ui
= 0x20f040;
1320 imesa
->regs
.s4
.texAddr
[1].ui
= 0;
1321 imesa
->regs
.s4
.texDescr
.ni
.texBLoopEn
= GL_FALSE
;
1325 tObj
= ctx
->Texture
.Unit
[1]._Current
;
1327 if (ctx
->Texture
.Unit
[1]._ReallyEnabled
!= TEXTURE_2D_BIT
||
1328 tObj
->Image
[0][tObj
->BaseLevel
]->Border
> 0) {
1329 /* 1D or 3D texturing enabled, or texture border - fallback */
1330 FALLBACK (ctx
, SAVAGE_FALLBACK_TEXTURE
, GL_TRUE
);
1334 /* Do 2D texture setup */
1336 t
= tObj
->DriverData
;
1338 t
= savageAllocTexObj( tObj
);
1343 if (t
->current_unit
!= 1)
1344 savageTexSetUnit( t
, 1 );
1346 imesa
->CurrentTexObj
[1] = t
;
1350 if (t
->dirty_images
) {
1351 savageSetTexImages(imesa
, tObj
);
1352 savageUploadTexImages(imesa
, imesa
->CurrentTexObj
[1]);
1356 savageUpdateTexLRU( imesa
, t
);
1358 format
= tObj
->Image
[0][tObj
->BaseLevel
]->Format
;
1360 switch (ctx
->Texture
.Unit
[1].EnvMode
) {
1362 imesa
->regs
.s4
.texCtrl
[1].ni
.clrArg1Invert
= GL_FALSE
;
1367 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_Decal
;
1370 case GL_LUMINANCE_ALPHA
:
1373 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_Copy
;
1377 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_CopyAlpha1
;
1380 __HWEnvCombineSingleUnitScale(imesa
, 0, 1, &imesa
->regs
.s4
.texBlendCtrl
);
1383 imesa
->regs
.s4
.texCtrl
[1].ni
.clrArg1Invert
= GL_FALSE
;
1384 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_ModulAlpha1
;
1385 __HWEnvCombineSingleUnitScale(imesa
, 0, 1, &imesa
->regs
.s4
.texBlendCtrl
);
1388 /*#if GL_EXT_texture_env_add*/
1390 imesa
->regs
.s4
.texCtrl
[1].ni
.clrArg1Invert
= GL_FALSE
;
1391 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_AddAlpha1
;
1392 __HWEnvCombineSingleUnitScale(imesa
, 0, 1, &imesa
->regs
.s4
.texBlendCtrl
);
1396 #if GL_ARB_texture_env_combine
1397 case GL_COMBINE_ARB
:
1398 __HWParseTexEnvCombine(imesa
, 1, &texCtrl
, &imesa
->regs
.s4
.texBlendCtrl
);
1403 imesa
->regs
.s4
.texCtrl
[1].ni
.clrArg1Invert
= GL_FALSE
;
1409 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_Decal1
;
1411 case GL_LUMINANCE_ALPHA
:
1414 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_DecalAlpha1
;
1418 // GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_INTENSITY
1419 // are undefined with GL_DECAL
1422 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= TBC_CopyAlpha1
;
1425 __HWEnvCombineSingleUnitScale(imesa
, 0, 1, &imesa
->regs
.s4
.texBlendCtrl
);
1429 if (format
== GL_LUMINANCE
)
1432 // This is a hack for GLQuake, invert.
1434 imesa
->regs
.s4
.texCtrl
[1].ni
.clrArg1Invert
= GL_TRUE
;
1435 imesa
->regs
.s4
.texBlendCtrl
[1].ui
= 0;
1437 __HWEnvCombineSingleUnitScale(imesa
, 0, 1, &imesa
->regs
.s4
.texBlendCtrl
);
1441 fprintf(stderr
, "unkown tex 1 env mode\n");
1446 imesa
->regs
.s4
.texCtrl
[1].ni
.uMode
= !(t
->texParams
.sWrapMode
& 0x01);
1447 imesa
->regs
.s4
.texCtrl
[1].ni
.vMode
= !(t
->texParams
.tWrapMode
& 0x01);
1449 switch (t
->texParams
.minFilter
)
1452 imesa
->regs
.s4
.texCtrl
[1].ni
.filterMode
= TFM_Point
;
1453 imesa
->regs
.s4
.texCtrl
[1].ni
.mipmapEnable
= GL_FALSE
;
1457 imesa
->regs
.s4
.texCtrl
[1].ni
.filterMode
= TFM_Bilin
;
1458 imesa
->regs
.s4
.texCtrl
[1].ni
.mipmapEnable
= GL_FALSE
;
1461 case GL_NEAREST_MIPMAP_NEAREST
:
1462 imesa
->regs
.s4
.texCtrl
[1].ni
.filterMode
= TFM_Point
;
1463 imesa
->regs
.s4
.texCtrl
[1].ni
.mipmapEnable
= GL_TRUE
;
1466 case GL_LINEAR_MIPMAP_NEAREST
:
1467 imesa
->regs
.s4
.texCtrl
[1].ni
.filterMode
= TFM_Bilin
;
1468 imesa
->regs
.s4
.texCtrl
[1].ni
.mipmapEnable
= GL_TRUE
;
1471 case GL_NEAREST_MIPMAP_LINEAR
:
1472 case GL_LINEAR_MIPMAP_LINEAR
:
1473 imesa
->regs
.s4
.texCtrl
[1].ni
.filterMode
= TFM_Trilin
;
1474 imesa
->regs
.s4
.texCtrl
[1].ni
.mipmapEnable
= GL_TRUE
;
1478 if((ctx
->Texture
.Unit
[1].LodBias
!=0.0F
)&&
1479 (imesa
->regs
.s4
.texCtrl
[1].ni
.dBias
!= 0))
1487 bias
.f
= ctx
->Texture
.Unit
[1].LodBias
;
1489 /* if the value is >= 15.9375 determine whether >= 16
1492 if(((bias
.i
) & 0x7FFFFFFF) >= 0x417F0000)
1494 if((bias
.i
) & 0x80000000)
1505 ul
=(GLuint
)(bias
.f
*16.0);
1509 imesa
->regs
.s4
.texCtrl
[1].ni
.dBias
= ul
;
1512 imesa
->regs
.s4
.texDescr
.ni
.tex1En
= GL_TRUE
;
1513 imesa
->regs
.s4
.texDescr
.ni
.tex1Width
= t
->image
[0].image
->WidthLog2
;
1514 imesa
->regs
.s4
.texDescr
.ni
.tex1Height
= t
->image
[0].image
->HeightLog2
;
1515 imesa
->regs
.s4
.texDescr
.ni
.tex1Fmt
= t
->image
[0].internalFormat
;
1516 imesa
->regs
.s4
.texCtrl
[1].ni
.dMax
= t
->max_level
;
1517 imesa
->regs
.s4
.texDescr
.ni
.texBLoopEn
= GL_TRUE
;
1519 imesa
->regs
.s4
.texAddr
[1].ui
= (GLuint
) t
->texParams
.hwPhysAddress
| 2;
1520 if(t
->heap
== SAVAGE_AGP_HEAP
)
1521 imesa
->regs
.s4
.texAddr
[1].ui
|= 0x1;
1523 static void savageUpdateTexState_s3d( GLcontext
*ctx
)
1525 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
1526 struct gl_texture_object
*tObj
;
1527 savageTextureObjectPtr t
;
1531 if (ctx
->Texture
.Unit
[0]._ReallyEnabled
== 0) {
1532 imesa
->regs
.s3d
.texCtrl
.ui
= 0;
1533 imesa
->regs
.s3d
.texCtrl
.ni
.texEn
= GL_FALSE
;
1534 imesa
->regs
.s3d
.texCtrl
.ni
.dBias
= 0x08;
1535 imesa
->regs
.s3d
.texCtrl
.ni
.texXprEn
= GL_TRUE
;
1536 imesa
->regs
.s3d
.texAddr
.ui
= 0;
1540 tObj
= ctx
->Texture
.Unit
[0]._Current
;
1541 if (ctx
->Texture
.Unit
[0]._ReallyEnabled
!= TEXTURE_2D_BIT
||
1542 tObj
->Image
[0][tObj
->BaseLevel
]->Border
> 0) {
1543 /* 1D or 3D texturing enabled, or texture border - fallback */
1544 FALLBACK (ctx
, SAVAGE_FALLBACK_TEXTURE
, GL_TRUE
);
1548 /* Do 2D texture setup */
1549 t
= tObj
->DriverData
;
1551 t
= savageAllocTexObj( tObj
);
1556 if (t
->current_unit
!= 0)
1557 savageTexSetUnit( t
, 0 );
1559 imesa
->CurrentTexObj
[0] = t
;
1562 if (t
->dirty_images
) {
1563 savageSetTexImages(imesa
, tObj
);
1564 savageUploadTexImages(imesa
, imesa
->CurrentTexObj
[0]);
1568 savageUpdateTexLRU( imesa
, t
);
1570 format
= tObj
->Image
[0][tObj
->BaseLevel
]->Format
;
1572 /* FIXME: copied from utah-glx, probably needs some tuning */
1573 switch (ctx
->Texture
.Unit
[0].EnvMode
) {
1575 imesa
->regs
.s3d
.drawCtrl
.ni
.texBlendCtrl
= SAVAGETBC_DECAL_S3D
;
1578 imesa
->regs
.s3d
.drawCtrl
.ni
.texBlendCtrl
= SAVAGETBC_COPY_S3D
;
1580 case GL_BLEND
: /* FIXIT */
1582 imesa
->regs
.s3d
.drawCtrl
.ni
.texBlendCtrl
= SAVAGETBC_MODULATEALPHA_S3D
;
1585 fprintf(stderr
, "unkown tex env mode\n");
1590 imesa
->regs
.s3d
.drawCtrl
.ni
.flushPdDestWrites
= GL_TRUE
;
1591 imesa
->regs
.s3d
.drawCtrl
.ni
.flushPdZbufWrites
= GL_TRUE
;
1593 /* FIXME: this is how the utah-driver works. I doubt it's the ultimate
1595 imesa
->regs
.s3d
.texCtrl
.ni
.uWrapEn
= 0;
1596 imesa
->regs
.s3d
.texCtrl
.ni
.vWrapEn
= 0;
1597 if (t
->texParams
.sWrapMode
== GL_CLAMP
)
1598 imesa
->regs
.s3d
.texCtrl
.ni
.wrapMode
= TAM_Clamp
;
1600 imesa
->regs
.s3d
.texCtrl
.ni
.wrapMode
= TAM_Wrap
;
1602 switch (t
->texParams
.minFilter
) {
1604 imesa
->regs
.s3d
.texCtrl
.ni
.filterMode
= TFM_Point
;
1605 imesa
->regs
.s3d
.texCtrl
.ni
.mipmapDisable
= GL_TRUE
;
1609 imesa
->regs
.s3d
.texCtrl
.ni
.filterMode
= TFM_Bilin
;
1610 imesa
->regs
.s3d
.texCtrl
.ni
.mipmapDisable
= GL_TRUE
;
1613 case GL_NEAREST_MIPMAP_NEAREST
:
1614 imesa
->regs
.s3d
.texCtrl
.ni
.filterMode
= TFM_Point
;
1615 imesa
->regs
.s3d
.texCtrl
.ni
.mipmapDisable
= GL_FALSE
;
1618 case GL_LINEAR_MIPMAP_NEAREST
:
1619 imesa
->regs
.s3d
.texCtrl
.ni
.filterMode
= TFM_Bilin
;
1620 imesa
->regs
.s3d
.texCtrl
.ni
.mipmapDisable
= GL_FALSE
;
1623 case GL_NEAREST_MIPMAP_LINEAR
:
1624 case GL_LINEAR_MIPMAP_LINEAR
:
1625 imesa
->regs
.s3d
.texCtrl
.ni
.filterMode
= TFM_Trilin
;
1626 imesa
->regs
.s3d
.texCtrl
.ni
.mipmapDisable
= GL_FALSE
;
1630 /* There is no way to specify a maximum mipmap level. We may have to
1631 disable mipmapping completely. */
1633 if (t->max_level < t->image[0].image->WidthLog2 ||
1634 t->max_level < t->image[0].image->HeightLog2) {
1635 texCtrl.ni.mipmapEnable = GL_TRUE;
1636 if (texCtrl.ni.filterMode == TFM_Trilin)
1637 texCtrl.ni.filterMode = TFM_Bilin;
1638 texCtrl.ni.filterMode = TFM_Point;
1642 /* LOD bias makes corruption of small mipmap levels worse on Savage IX
1643 * but doesn't show the desired effect with the lodbias mesa demo. */
1644 imesa
->regs
.s3d
.texCtrl
.ni
.dBias
= 0;
1646 imesa
->regs
.s3d
.texCtrl
.ni
.texEn
= GL_TRUE
;
1647 imesa
->regs
.s3d
.texDescr
.ni
.texWidth
= t
->image
[0].image
->WidthLog2
;
1648 imesa
->regs
.s3d
.texDescr
.ni
.texHeight
= t
->image
[0].image
->HeightLog2
;
1649 assert (t
->image
[0].internalFormat
<= 7);
1650 imesa
->regs
.s3d
.texDescr
.ni
.texFmt
= t
->image
[0].internalFormat
;
1652 imesa
->regs
.s3d
.texAddr
.ni
.addr
= (GLuint
) t
->texParams
.hwPhysAddress
>> 3;
1653 if(t
->heap
== SAVAGE_AGP_HEAP
) {
1654 imesa
->regs
.s3d
.texAddr
.ni
.inSysTex
= 1;
1655 imesa
->regs
.s3d
.texAddr
.ni
.inAGPTex
= 1;
1657 imesa
->regs
.s3d
.texAddr
.ni
.inSysTex
= 0;
1658 imesa
->regs
.s3d
.texAddr
.ni
.inAGPTex
= 1;
1664 static void savageUpdateTextureState_s4( GLcontext
*ctx
)
1666 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
1667 if (imesa
->CurrentTexObj
[0]) imesa
->CurrentTexObj
[0]->bound
&= ~1;
1668 if (imesa
->CurrentTexObj
[1]) imesa
->CurrentTexObj
[1]->bound
&= ~2;
1669 imesa
->CurrentTexObj
[0] = 0;
1670 imesa
->CurrentTexObj
[1] = 0;
1671 FALLBACK (ctx
, SAVAGE_FALLBACK_TEXTURE
, GL_FALSE
);
1672 savageUpdateTex0State_s4( ctx
);
1673 savageUpdateTex1State_s4( ctx
);
1674 imesa
->dirty
|= (SAVAGE_UPLOAD_CTX
|
1675 SAVAGE_UPLOAD_TEX0
|
1676 SAVAGE_UPLOAD_TEX1
);
1678 static void savageUpdateTextureState_s3d( GLcontext
*ctx
)
1680 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
1681 if (imesa
->CurrentTexObj
[0]) imesa
->CurrentTexObj
[0]->bound
&= ~1;
1682 imesa
->CurrentTexObj
[0] = 0;
1683 if (ctx
->Texture
.Unit
[1]._ReallyEnabled
) {
1684 FALLBACK (ctx
, SAVAGE_FALLBACK_TEXTURE
, GL_TRUE
);
1686 FALLBACK (ctx
, SAVAGE_FALLBACK_TEXTURE
, GL_FALSE
);
1687 savageUpdateTexState_s3d( ctx
);
1688 imesa
->dirty
|= (SAVAGE_UPLOAD_CTX
|
1689 SAVAGE_UPLOAD_TEX0
);
1692 static void savageUpdateTextureState_first( GLcontext
*ctx
)
1694 savageContextPtr imesa
= SAVAGE_CONTEXT( ctx
);
1695 if (imesa
->savageScreen
->chipset
<= S3_SAVAGE4
) {
1696 GetTiledCoordinates16
= GetTiledCoordinates16_4
;
1697 GetTiledCoordinates32
= GetTiledCoordinates32_4
;
1699 GetTiledCoordinates16
= GetTiledCoordinates16_8
;
1700 GetTiledCoordinates32
= GetTiledCoordinates32_8
;
1702 if (imesa
->savageScreen
->chipset
>= S3_SAVAGE4
)
1703 savageUpdateTextureState
= savageUpdateTextureState_s4
;
1705 savageUpdateTextureState
= savageUpdateTextureState_s3d
;
1706 savageUpdateTextureState (ctx
);
1708 void (*savageUpdateTextureState
)( GLcontext
*ctx
) =
1709 savageUpdateTextureState_first
;
1713 /*****************************************
1715 *****************************************/
1717 static void savageTexEnv( GLcontext
*ctx
, GLenum target
,
1718 GLenum pname
, const GLfloat
*param
)
1720 savageContextPtr imesa
= SAVAGE_CONTEXT( ctx
);
1722 if (pname
== GL_TEXTURE_ENV_MODE
) {
1724 imesa
->new_state
|= SAVAGE_NEW_TEXTURE
;
1726 } else if (pname
== GL_TEXTURE_ENV_COLOR
) {
1728 struct gl_texture_unit
*texUnit
=
1729 &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1730 const GLfloat
*fc
= texUnit
->EnvColor
;
1731 GLuint r
, g
, b
, a
, col
;
1732 CLAMPED_FLOAT_TO_UBYTE(r
, fc
[0]);
1733 CLAMPED_FLOAT_TO_UBYTE(g
, fc
[1]);
1734 CLAMPED_FLOAT_TO_UBYTE(b
, fc
[2]);
1735 CLAMPED_FLOAT_TO_UBYTE(a
, fc
[3]);
1746 static void savageTexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
1747 GLint internalFormat
,
1748 GLint width
, GLint height
, GLint border
,
1749 GLenum format
, GLenum type
, const GLvoid
*pixels
,
1750 const struct gl_pixelstore_attrib
*packing
,
1751 struct gl_texture_object
*texObj
,
1752 struct gl_texture_image
*texImage
)
1754 savageTextureObjectPtr t
= (savageTextureObjectPtr
) texObj
->DriverData
;
1756 savageSwapOutTexObj( SAVAGE_CONTEXT(ctx
), t
);
1758 t
= savageAllocTexObj(texObj
);
1760 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
1764 _mesa_store_teximage2d( ctx
, target
, level
, internalFormat
,
1765 width
, height
, border
, format
, type
,
1766 pixels
, packing
, texObj
, texImage
);
1767 t
->dirty_images
|= (1 << level
);
1768 SAVAGE_CONTEXT(ctx
)->new_state
|= SAVAGE_NEW_TEXTURE
;
1771 static void savageTexSubImage2D( GLcontext
*ctx
,
1774 GLint xoffset
, GLint yoffset
,
1775 GLsizei width
, GLsizei height
,
1776 GLenum format
, GLenum type
,
1777 const GLvoid
*pixels
,
1778 const struct gl_pixelstore_attrib
*packing
,
1779 struct gl_texture_object
*texObj
,
1780 struct gl_texture_image
*texImage
)
1782 savageTextureObjectPtr t
= (savageTextureObjectPtr
) texObj
->DriverData
;
1783 assert( t
); /* this _should_ be true */
1785 savageSwapOutTexObj( SAVAGE_CONTEXT(ctx
), t
);
1787 t
= savageAllocTexObj(texObj
);
1789 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
1793 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
1794 height
, format
, type
, pixels
, packing
, texObj
,
1796 t
->dirty_images
|= (1 << level
);
1797 SAVAGE_CONTEXT(ctx
)->new_state
|= SAVAGE_NEW_TEXTURE
;
1800 static void savageTexParameter( GLcontext
*ctx
, GLenum target
,
1801 struct gl_texture_object
*tObj
,
1802 GLenum pname
, const GLfloat
*params
)
1804 savageTextureObjectPtr t
= (savageTextureObjectPtr
) tObj
->DriverData
;
1805 savageContextPtr imesa
= SAVAGE_CONTEXT( ctx
);
1807 if (!t
|| target
!= GL_TEXTURE_2D
)
1811 case GL_TEXTURE_MIN_FILTER
:
1812 case GL_TEXTURE_MAG_FILTER
:
1813 savageSetTexFilter(t
,tObj
->MinFilter
,tObj
->MagFilter
);
1816 case GL_TEXTURE_WRAP_S
:
1817 case GL_TEXTURE_WRAP_T
:
1818 savageSetTexWrapping(t
,tObj
->WrapS
,tObj
->WrapT
);
1821 case GL_TEXTURE_BORDER_COLOR
:
1822 savageSetTexBorderColor(t
,tObj
->_BorderChan
);
1829 imesa
->new_state
|= SAVAGE_NEW_TEXTURE
;
1832 static void savageBindTexture( GLcontext
*ctx
, GLenum target
,
1833 struct gl_texture_object
*tObj
)
1835 savageContextPtr imesa
= SAVAGE_CONTEXT( ctx
);
1837 assert( (target
!= GL_TEXTURE_2D
) || (tObj
->DriverData
!= NULL
) );
1839 imesa
->new_state
|= SAVAGE_NEW_TEXTURE
;
1842 static void savageDeleteTexture( GLcontext
*ctx
, struct gl_texture_object
*tObj
)
1844 savageTextureObjectPtr t
= (savageTextureObjectPtr
)tObj
->DriverData
;
1845 savageContextPtr imesa
= SAVAGE_CONTEXT( ctx
);
1850 imesa
->CurrentTexObj
[t
->bound
-1] = 0;
1851 imesa
->new_state
|= SAVAGE_NEW_TEXTURE
;
1854 savageDestroyTexObj(imesa
,t
);
1857 /* Free mipmap images and the texture object itself */
1858 _mesa_delete_texture_object(ctx
, tObj
);
1862 static GLboolean
savageIsTextureResident( GLcontext
*ctx
,
1863 struct gl_texture_object
*t
)
1865 savageTextureObjectPtr mt
;
1867 /* LOCK_HARDWARE; */
1868 mt
= (savageTextureObjectPtr
)t
->DriverData
;
1869 /* UNLOCK_HARDWARE; */
1871 return mt
&& mt
->MemBlock
;
1875 static struct gl_texture_object
*
1876 savageNewTextureObject( GLcontext
*ctx
, GLuint name
, GLenum target
)
1878 struct gl_texture_object
*obj
;
1879 obj
= _mesa_new_texture_object(ctx
, name
, target
);
1880 savageAllocTexObj( obj
);
1885 void savageDDInitTextureFuncs( struct dd_function_table
*functions
)
1887 functions
->TexEnv
= savageTexEnv
;
1888 functions
->ChooseTextureFormat
= savageChooseTextureFormat
;
1889 functions
->TexImage2D
= savageTexImage2D
;
1890 functions
->TexSubImage2D
= savageTexSubImage2D
;
1891 functions
->BindTexture
= savageBindTexture
;
1892 functions
->NewTextureObject
= savageNewTextureObject
;
1893 functions
->DeleteTexture
= savageDeleteTexture
;
1894 functions
->IsTextureResident
= savageIsTextureResident
;
1895 functions
->TexParameter
= savageTexParameter
;