1 /* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_tex.c,v 1.14 2002/11/05 17:46:08 tsi Exp $ */
2 /**************************************************************************
4 Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
8 Permission is hereby granted, free of charge, to any person obtaining a
9 copy of this software and associated documentation files (the "Software"),
10 to deal in the Software without restriction, including without limitation
11 on the rights to use, copy, modify, merge, publish, distribute, sub
12 license, and/or sell copies of the Software, and to permit persons to whom
13 the Software is furnished to do so, subject to the following conditions:
15 The above copyright notice and this permission notice (including the next
16 paragraph) shall be included in all copies or substantial portions of the
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
22 ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
23 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
25 USE OR OTHER DEALINGS IN THE SOFTWARE.
27 **************************************************************************/
31 * Gareth Hughes <gareth@valinux.com>
32 * Kevin E. Martin <martin@valinux.com>
33 * Brian Paul <brianp@valinux.com>
36 #include "r128_context.h"
37 #include "r128_state.h"
38 #include "r128_ioctl.h"
40 #include "r128_tris.h"
42 #include "r128_texobj.h"
46 #include "simple_list.h"
49 #include "texformat.h"
61 * Set the texture wrap modes. Currently \c GL_REPEAT, \c GL_CLAMP,
62 * \c GL_CLAMP_TO_EDGE, and \c GL_MIRRORED_REPEAT are supported.
64 * \param t Texture object whose wrap modes are to be set
65 * \param swrap Wrap mode for the \a s texture coordinate
66 * \param twrap Wrap mode for the \a t texture coordinate
68 static void r128SetTexWrap( r128TexObjPtr t
, GLenum swrap
, GLenum twrap
)
70 t
->setup
.tex_cntl
&= ~(R128_TEX_CLAMP_S_MASK
| R128_TEX_CLAMP_T_MASK
);
74 t
->setup
.tex_cntl
|= R128_TEX_CLAMP_S_BORDER_COLOR
;
76 case GL_CLAMP_TO_EDGE
:
77 t
->setup
.tex_cntl
|= R128_TEX_CLAMP_S_CLAMP
;
80 t
->setup
.tex_cntl
|= R128_TEX_CLAMP_S_WRAP
;
82 case GL_MIRRORED_REPEAT
:
83 t
->setup
.tex_cntl
|= R128_TEX_CLAMP_S_MIRROR
;
89 t
->setup
.tex_cntl
|= R128_TEX_CLAMP_T_BORDER_COLOR
;
91 case GL_CLAMP_TO_EDGE
:
92 t
->setup
.tex_cntl
|= R128_TEX_CLAMP_T_CLAMP
;
95 t
->setup
.tex_cntl
|= R128_TEX_CLAMP_T_WRAP
;
97 case GL_MIRRORED_REPEAT
:
98 t
->setup
.tex_cntl
|= R128_TEX_CLAMP_T_MIRROR
;
103 static void r128SetTexFilter( r128TexObjPtr t
, GLenum minf
, GLenum magf
)
105 t
->setup
.tex_cntl
&= ~(R128_MIN_BLEND_MASK
| R128_MAG_BLEND_MASK
);
109 t
->setup
.tex_cntl
|= R128_MIN_BLEND_NEAREST
;
112 t
->setup
.tex_cntl
|= R128_MIN_BLEND_LINEAR
;
114 case GL_NEAREST_MIPMAP_NEAREST
:
115 t
->setup
.tex_cntl
|= R128_MIN_BLEND_MIPNEAREST
;
117 case GL_LINEAR_MIPMAP_NEAREST
:
118 t
->setup
.tex_cntl
|= R128_MIN_BLEND_MIPLINEAR
;
120 case GL_NEAREST_MIPMAP_LINEAR
:
121 t
->setup
.tex_cntl
|= R128_MIN_BLEND_LINEARMIPNEAREST
;
123 case GL_LINEAR_MIPMAP_LINEAR
:
124 t
->setup
.tex_cntl
|= R128_MIN_BLEND_LINEARMIPLINEAR
;
130 t
->setup
.tex_cntl
|= R128_MAG_BLEND_NEAREST
;
133 t
->setup
.tex_cntl
|= R128_MAG_BLEND_LINEAR
;
138 static void r128SetTexBorderColor( r128TexObjPtr t
, GLubyte c
[4] )
140 t
->setup
.tex_border_color
= r128PackColor( 4, c
[0], c
[1], c
[2], c
[3] );
144 static r128TexObjPtr
r128AllocTexObj( struct gl_texture_object
*texObj
)
148 if ( R128_DEBUG
& DEBUG_VERBOSE_API
) {
149 fprintf( stderr
, "%s( %p )\n", __FUNCTION__
, texObj
);
152 t
= (r128TexObjPtr
) CALLOC_STRUCT( r128_tex_obj
);
153 texObj
->DriverData
= t
;
156 /* Initialize non-image-dependent parts of the state:
158 t
->base
.tObj
= texObj
;
160 /* FIXME Something here to set initial values for other parts of
164 make_empty_list( (driTextureObject
*) t
);
166 r128SetTexWrap( t
, texObj
->WrapS
, texObj
->WrapT
);
167 r128SetTexFilter( t
, texObj
->MinFilter
, texObj
->MagFilter
);
168 r128SetTexBorderColor( t
, texObj
->_BorderChan
);
175 /* Called by the _mesa_store_teximage[123]d() functions. */
176 static const struct gl_texture_format
*
177 r128ChooseTextureFormat( GLcontext
*ctx
, GLint internalFormat
,
178 GLenum format
, GLenum type
)
180 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
181 const GLboolean do32bpt
=
182 ( rmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_32
);
183 const GLboolean force16bpt
=
184 ( rmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_FORCE_16
);
188 switch ( internalFormat
) {
189 /* non-sized formats with alpha */
191 case GL_COMPRESSED_INTENSITY
:
193 case GL_COMPRESSED_ALPHA
:
195 case GL_LUMINANCE_ALPHA
:
196 case GL_COMPRESSED_LUMINANCE_ALPHA
:
199 case GL_COMPRESSED_RGBA
:
201 return &_mesa_texformat_argb8888
;
203 return &_mesa_texformat_argb4444
;
205 /* 16-bit formats with alpha */
208 case GL_LUMINANCE4_ALPHA4
:
211 return &_mesa_texformat_argb4444
;
213 /* 32-bit formats with alpha */
220 case GL_LUMINANCE6_ALPHA2
:
221 case GL_LUMINANCE8_ALPHA8
:
222 case GL_LUMINANCE12_ALPHA4
:
223 case GL_LUMINANCE12_ALPHA12
:
224 case GL_LUMINANCE16_ALPHA16
:
231 return &_mesa_texformat_argb8888
;
233 return &_mesa_texformat_argb4444
;
235 /* non-sized formats without alpha */
238 case GL_COMPRESSED_LUMINANCE
:
241 case GL_COMPRESSED_RGB
:
243 return &_mesa_texformat_argb8888
;
245 return &_mesa_texformat_rgb565
;
247 /* 16-bit formats without alpha */
252 return &_mesa_texformat_rgb565
;
254 /* 32-bit formats without alpha */
263 return &_mesa_texformat_argb8888
;
265 return &_mesa_texformat_rgb565
;
267 /* color-indexed formats */
269 case GL_COLOR_INDEX1_EXT
:
270 case GL_COLOR_INDEX2_EXT
:
271 case GL_COLOR_INDEX4_EXT
:
272 case GL_COLOR_INDEX8_EXT
:
273 case GL_COLOR_INDEX12_EXT
:
274 case GL_COLOR_INDEX16_EXT
:
275 return &_mesa_texformat_ci8
;
278 if (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
279 type
== GL_UNSIGNED_BYTE
)
280 return &_mesa_texformat_ycbcr
;
282 return &_mesa_texformat_ycbcr_rev
;
285 _mesa_problem( ctx
, "unexpected format in %s", __FUNCTION__
);
291 static void r128TexImage1D( GLcontext
*ctx
, GLenum target
, GLint level
,
292 GLint internalFormat
,
293 GLint width
, GLint border
,
294 GLenum format
, GLenum type
, const GLvoid
*pixels
,
295 const struct gl_pixelstore_attrib
*packing
,
296 struct gl_texture_object
*texObj
,
297 struct gl_texture_image
*texImage
)
299 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
302 driSwapOutTextureObject( t
);
305 t
= (driTextureObject
*) r128AllocTexObj(texObj
);
307 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
312 /* Note, this will call r128ChooseTextureFormat */
313 _mesa_store_teximage1d( ctx
, target
, level
, internalFormat
,
314 width
, border
, format
, type
,
315 pixels
, packing
, texObj
, texImage
);
317 t
->dirty_images
[0] |= (1 << level
);
321 static void r128TexSubImage1D( GLcontext
*ctx
,
326 GLenum format
, GLenum type
,
327 const GLvoid
*pixels
,
328 const struct gl_pixelstore_attrib
*packing
,
329 struct gl_texture_object
*texObj
,
330 struct gl_texture_image
*texImage
)
332 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
334 assert( t
); /* this _should_ be true */
336 driSwapOutTextureObject( t
);
339 t
= (driTextureObject
*) r128AllocTexObj(texObj
);
341 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
346 _mesa_store_texsubimage1d(ctx
, target
, level
, xoffset
, width
,
347 format
, type
, pixels
, packing
, texObj
,
350 t
->dirty_images
[0] |= (1 << level
);
354 static void r128TexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
355 GLint internalFormat
,
356 GLint width
, GLint height
, GLint border
,
357 GLenum format
, GLenum type
, const GLvoid
*pixels
,
358 const struct gl_pixelstore_attrib
*packing
,
359 struct gl_texture_object
*texObj
,
360 struct gl_texture_image
*texImage
)
362 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
365 driSwapOutTextureObject( (driTextureObject
*) t
);
368 t
= (driTextureObject
*) r128AllocTexObj(texObj
);
370 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
375 /* Note, this will call r128ChooseTextureFormat */
376 _mesa_store_teximage2d(ctx
, target
, level
, internalFormat
,
377 width
, height
, border
, format
, type
, pixels
,
378 &ctx
->Unpack
, texObj
, texImage
);
380 t
->dirty_images
[0] |= (1 << level
);
384 static void r128TexSubImage2D( GLcontext
*ctx
,
387 GLint xoffset
, GLint yoffset
,
388 GLsizei width
, GLsizei height
,
389 GLenum format
, GLenum type
,
390 const GLvoid
*pixels
,
391 const struct gl_pixelstore_attrib
*packing
,
392 struct gl_texture_object
*texObj
,
393 struct gl_texture_image
*texImage
)
395 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
397 assert( t
); /* this _should_ be true */
399 driSwapOutTextureObject( t
);
402 t
= (driTextureObject
*) r128AllocTexObj(texObj
);
404 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
409 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
410 height
, format
, type
, pixels
, packing
, texObj
,
412 t
->dirty_images
[0] |= (1 << level
);
416 static void r128DDTexEnv( GLcontext
*ctx
, GLenum target
,
417 GLenum pname
, const GLfloat
*param
)
419 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
420 struct gl_texture_unit
*texUnit
;
423 if ( R128_DEBUG
& DEBUG_VERBOSE_API
) {
424 fprintf( stderr
, "%s( %s )\n",
425 __FUNCTION__
, _mesa_lookup_enum_by_nr( pname
) );
429 case GL_TEXTURE_ENV_MODE
:
430 FLUSH_BATCH( rmesa
);
431 rmesa
->new_state
|= R128_NEW_ALPHA
;
434 case GL_TEXTURE_ENV_COLOR
:
435 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
436 CLAMPED_FLOAT_TO_UBYTE( c
[0], texUnit
->EnvColor
[0] );
437 CLAMPED_FLOAT_TO_UBYTE( c
[1], texUnit
->EnvColor
[1] );
438 CLAMPED_FLOAT_TO_UBYTE( c
[2], texUnit
->EnvColor
[2] );
439 CLAMPED_FLOAT_TO_UBYTE( c
[3], texUnit
->EnvColor
[3] );
440 rmesa
->env_color
= r128PackColor( 4, c
[0], c
[1], c
[2], c
[3] );
441 if ( rmesa
->setup
.constant_color_c
!= rmesa
->env_color
) {
442 FLUSH_BATCH( rmesa
);
443 rmesa
->setup
.constant_color_c
= rmesa
->env_color
;
445 /* More complex multitexture/multipass fallbacks for GL_BLEND
446 * can be done later, but this allows a single pass GL_BLEND
447 * in some cases (ie. Performer town demo). This is only
448 * applicable to the regular Rage 128, as the Pro and M3 can
449 * handle true single-pass GL_BLEND texturing.
451 rmesa
->blend_flags
&= ~R128_BLEND_ENV_COLOR
;
452 if ( R128_IS_PLAIN( rmesa
) &&
453 rmesa
->env_color
!= 0x00000000 &&
454 rmesa
->env_color
!= 0xff000000 &&
455 rmesa
->env_color
!= 0x00ffffff &&
456 rmesa
->env_color
!= 0xffffffff ) {
457 rmesa
->blend_flags
|= R128_BLEND_ENV_COLOR
;
462 case GL_TEXTURE_LOD_BIAS
:
464 CARD32 t
= rmesa
->setup
.tex_cntl_c
;
468 /* GTH: This isn't exactly correct, but gives good results up to a
469 * certain point. It is better than completely ignoring the LOD
470 * bias. Unfortunately there isn't much range in the bias, the
471 * spec mentions strides that vary between 0.5 and 2.0 but these
472 * numbers don't seem to relate the the GL LOD bias value at all.
474 if ( param
[0] >= 1.0 ) {
476 } else if ( param
[0] >= 0.5 ) {
478 } else if ( param
[0] >= 0.25 ) {
480 } else if ( param
[0] >= 0.0 ) {
486 b
= (CARD32
)bias
& 0xff;
487 t
&= ~R128_LOD_BIAS_MASK
;
488 t
|= (b
<< R128_LOD_BIAS_SHIFT
);
490 if ( rmesa
->setup
.tex_cntl_c
!= t
) {
491 FLUSH_BATCH( rmesa
);
492 rmesa
->setup
.tex_cntl_c
= t
;
493 rmesa
->dirty
|= R128_UPLOAD_CONTEXT
;
504 static void r128DDTexParameter( GLcontext
*ctx
, GLenum target
,
505 struct gl_texture_object
*tObj
,
506 GLenum pname
, const GLfloat
*params
)
508 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
509 r128TexObjPtr t
= (r128TexObjPtr
)tObj
->DriverData
;
511 if ( R128_DEBUG
& DEBUG_VERBOSE_API
) {
512 fprintf( stderr
, "%s( %s )\n",
513 __FUNCTION__
, _mesa_lookup_enum_by_nr( pname
) );
516 if ( ( target
!= GL_TEXTURE_2D
) && ( target
!= GL_TEXTURE_1D
) )
520 case GL_TEXTURE_MIN_FILTER
:
521 case GL_TEXTURE_MAG_FILTER
:
522 if ( t
->base
.bound
) FLUSH_BATCH( rmesa
);
523 r128SetTexFilter( t
, tObj
->MinFilter
, tObj
->MagFilter
);
526 case GL_TEXTURE_WRAP_S
:
527 case GL_TEXTURE_WRAP_T
:
528 if ( t
->base
.bound
) FLUSH_BATCH( rmesa
);
529 r128SetTexWrap( t
, tObj
->WrapS
, tObj
->WrapT
);
532 case GL_TEXTURE_BORDER_COLOR
:
533 if ( t
->base
.bound
) FLUSH_BATCH( rmesa
);
534 r128SetTexBorderColor( t
, tObj
->_BorderChan
);
537 case GL_TEXTURE_BASE_LEVEL
:
538 case GL_TEXTURE_MAX_LEVEL
:
539 case GL_TEXTURE_MIN_LOD
:
540 case GL_TEXTURE_MAX_LOD
:
541 /* This isn't the most efficient solution but there doesn't appear to
542 * be a nice alternative for R128. Since there's no LOD clamping,
543 * we just have to rely on loading the right subset of mipmap levels
544 * to simulate a clamped LOD.
546 if ( t
->base
.bound
) FLUSH_BATCH( rmesa
);
547 driSwapOutTextureObject( (driTextureObject
*) t
);
555 static void r128DDBindTexture( GLcontext
*ctx
, GLenum target
,
556 struct gl_texture_object
*tObj
)
558 if ( R128_DEBUG
& DEBUG_VERBOSE_API
) {
559 fprintf( stderr
, "%s( %p ) unit=%d\n", __FUNCTION__
, tObj
,
560 ctx
->Texture
.CurrentUnit
);
563 if ( target
== GL_TEXTURE_2D
|| target
== GL_TEXTURE_1D
) {
564 if ( tObj
->DriverData
== NULL
) {
565 r128AllocTexObj( tObj
);
570 static void r128DDDeleteTexture( GLcontext
*ctx
,
571 struct gl_texture_object
*tObj
)
573 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
574 driTextureObject
* t
= (driTextureObject
*) tObj
->DriverData
;
577 if ( t
->bound
&& rmesa
) {
578 FLUSH_BATCH( rmesa
);
581 driDestroyTextureObject( t
);
583 /* Free mipmap images and the texture object itself */
584 _mesa_delete_texture_object(ctx
, tObj
);
587 void r128DDInitTextureFuncs( GLcontext
*ctx
)
589 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
592 ctx
->Driver
.TexEnv
= r128DDTexEnv
;
593 ctx
->Driver
.ChooseTextureFormat
= r128ChooseTextureFormat
;
594 ctx
->Driver
.TexImage1D
= r128TexImage1D
;
595 ctx
->Driver
.TexSubImage1D
= r128TexSubImage1D
;
596 ctx
->Driver
.TexImage2D
= r128TexImage2D
;
597 ctx
->Driver
.TexSubImage2D
= r128TexSubImage2D
;
598 ctx
->Driver
.TexImage3D
= _mesa_store_teximage3d
;
599 ctx
->Driver
.TexSubImage3D
= _mesa_store_texsubimage3d
;
600 ctx
->Driver
.CopyTexImage1D
= _swrast_copy_teximage1d
;
601 ctx
->Driver
.CopyTexImage2D
= _swrast_copy_teximage2d
;
602 ctx
->Driver
.CopyTexSubImage1D
= _swrast_copy_texsubimage1d
;
603 ctx
->Driver
.CopyTexSubImage2D
= _swrast_copy_texsubimage2d
;
604 ctx
->Driver
.CopyTexSubImage3D
= _swrast_copy_texsubimage3d
;
605 ctx
->Driver
.TestProxyTexImage
= _mesa_test_proxy_teximage
;
606 ctx
->Driver
.TexParameter
= r128DDTexParameter
;
607 ctx
->Driver
.BindTexture
= r128DDBindTexture
;
608 ctx
->Driver
.DeleteTexture
= r128DDDeleteTexture
;
609 ctx
->Driver
.UpdateTexturePalette
= NULL
;
610 ctx
->Driver
.ActiveTexture
= NULL
;
611 ctx
->Driver
.IsTextureResident
= driIsTextureResident
;
612 ctx
->Driver
.PrioritizeTexture
= NULL
;
614 driInitTextureObjects( ctx
, & rmesa
->swapped
,
615 DRI_TEXMGR_DO_TEXTURE_1D
616 | DRI_TEXMGR_DO_TEXTURE_2D
);