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"
39 #include "r128_tris.h"
41 #include "r128_texobj.h"
45 #include "simple_list.h"
48 #include "texformat.h"
62 * Set the texture wrap modes. Currently \c GL_REPEAT, \c GL_CLAMP,
63 * \c GL_CLAMP_TO_EDGE, and \c GL_MIRRORED_REPEAT are supported.
65 * \param t Texture object whose wrap modes are to be set
66 * \param swrap Wrap mode for the \a s texture coordinate
67 * \param twrap Wrap mode for the \a t texture coordinate
69 static void r128SetTexWrap( r128TexObjPtr t
, GLenum swrap
, GLenum twrap
)
71 t
->setup
.tex_cntl
&= ~(R128_TEX_CLAMP_S_MASK
| R128_TEX_CLAMP_T_MASK
);
75 t
->setup
.tex_cntl
|= R128_TEX_CLAMP_S_BORDER_COLOR
;
77 case GL_CLAMP_TO_EDGE
:
78 t
->setup
.tex_cntl
|= R128_TEX_CLAMP_S_CLAMP
;
81 t
->setup
.tex_cntl
|= R128_TEX_CLAMP_S_WRAP
;
83 case GL_MIRRORED_REPEAT
:
84 t
->setup
.tex_cntl
|= R128_TEX_CLAMP_S_MIRROR
;
90 t
->setup
.tex_cntl
|= R128_TEX_CLAMP_T_BORDER_COLOR
;
92 case GL_CLAMP_TO_EDGE
:
93 t
->setup
.tex_cntl
|= R128_TEX_CLAMP_T_CLAMP
;
96 t
->setup
.tex_cntl
|= R128_TEX_CLAMP_T_WRAP
;
98 case GL_MIRRORED_REPEAT
:
99 t
->setup
.tex_cntl
|= R128_TEX_CLAMP_T_MIRROR
;
104 static void r128SetTexFilter( r128TexObjPtr t
, GLenum minf
, GLenum magf
)
106 t
->setup
.tex_cntl
&= ~(R128_MIN_BLEND_MASK
| R128_MAG_BLEND_MASK
);
110 t
->setup
.tex_cntl
|= R128_MIN_BLEND_NEAREST
;
113 t
->setup
.tex_cntl
|= R128_MIN_BLEND_LINEAR
;
115 case GL_NEAREST_MIPMAP_NEAREST
:
116 t
->setup
.tex_cntl
|= R128_MIN_BLEND_MIPNEAREST
;
118 case GL_LINEAR_MIPMAP_NEAREST
:
119 t
->setup
.tex_cntl
|= R128_MIN_BLEND_MIPLINEAR
;
121 case GL_NEAREST_MIPMAP_LINEAR
:
122 t
->setup
.tex_cntl
|= R128_MIN_BLEND_LINEARMIPNEAREST
;
124 case GL_LINEAR_MIPMAP_LINEAR
:
125 t
->setup
.tex_cntl
|= R128_MIN_BLEND_LINEARMIPLINEAR
;
131 t
->setup
.tex_cntl
|= R128_MAG_BLEND_NEAREST
;
134 t
->setup
.tex_cntl
|= R128_MAG_BLEND_LINEAR
;
139 static void r128SetTexBorderColor( r128TexObjPtr t
, GLubyte c
[4] )
141 t
->setup
.tex_border_color
= r128PackColor( 4, c
[0], c
[1], c
[2], c
[3] );
145 static r128TexObjPtr
r128AllocTexObj( struct gl_texture_object
*texObj
)
149 if ( R128_DEBUG
& DEBUG_VERBOSE_API
) {
150 fprintf( stderr
, "%s( %p )\n", __FUNCTION__
, (void *) texObj
);
153 t
= (r128TexObjPtr
) CALLOC_STRUCT( r128_tex_obj
);
154 texObj
->DriverData
= t
;
157 /* Initialize non-image-dependent parts of the state:
159 t
->base
.tObj
= texObj
;
161 /* FIXME Something here to set initial values for other parts of
165 make_empty_list( (driTextureObject
*) t
);
167 r128SetTexWrap( t
, texObj
->WrapS
, texObj
->WrapT
);
168 r128SetTexFilter( t
, texObj
->MinFilter
, texObj
->MagFilter
);
169 r128SetTexBorderColor( t
, texObj
->_BorderChan
);
176 /* Called by the _mesa_store_teximage[123]d() functions. */
177 static const struct gl_texture_format
*
178 r128ChooseTextureFormat( GLcontext
*ctx
, GLint internalFormat
,
179 GLenum format
, GLenum type
)
181 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
182 const GLboolean do32bpt
=
183 ( rmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_32
);
184 const GLboolean force16bpt
=
185 ( rmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_FORCE_16
);
189 switch ( internalFormat
) {
190 /* non-sized formats with alpha */
192 case GL_COMPRESSED_INTENSITY
:
194 case GL_COMPRESSED_ALPHA
:
196 case GL_LUMINANCE_ALPHA
:
197 case GL_COMPRESSED_LUMINANCE_ALPHA
:
200 case GL_COMPRESSED_RGBA
:
202 return _dri_texformat_argb8888
;
204 return _dri_texformat_argb4444
;
206 /* 16-bit formats with alpha */
209 case GL_LUMINANCE4_ALPHA4
:
212 return _dri_texformat_argb4444
;
214 /* 32-bit formats with alpha */
221 case GL_LUMINANCE6_ALPHA2
:
222 case GL_LUMINANCE8_ALPHA8
:
223 case GL_LUMINANCE12_ALPHA4
:
224 case GL_LUMINANCE12_ALPHA12
:
225 case GL_LUMINANCE16_ALPHA16
:
232 return _dri_texformat_argb8888
;
234 return _dri_texformat_argb4444
;
236 /* non-sized formats without alpha */
239 case GL_COMPRESSED_LUMINANCE
:
242 case GL_COMPRESSED_RGB
:
244 return _dri_texformat_argb8888
;
246 return _dri_texformat_rgb565
;
248 /* 16-bit formats without alpha */
253 return _dri_texformat_rgb565
;
255 /* 32-bit formats without alpha */
264 return _dri_texformat_argb8888
;
266 return _dri_texformat_rgb565
;
268 /* color-indexed formats */
270 case GL_COLOR_INDEX1_EXT
:
271 case GL_COLOR_INDEX2_EXT
:
272 case GL_COLOR_INDEX4_EXT
:
273 case GL_COLOR_INDEX8_EXT
:
274 case GL_COLOR_INDEX12_EXT
:
275 case GL_COLOR_INDEX16_EXT
:
276 return _dri_texformat_ci8
;
279 if (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
280 type
== GL_UNSIGNED_BYTE
)
281 return &_mesa_texformat_ycbcr
;
283 return &_mesa_texformat_ycbcr_rev
;
286 _mesa_problem( ctx
, "unexpected format in %s", __FUNCTION__
);
292 static void r128TexImage1D( GLcontext
*ctx
, GLenum target
, GLint level
,
293 GLint internalFormat
,
294 GLint width
, GLint border
,
295 GLenum format
, GLenum type
, const GLvoid
*pixels
,
296 const struct gl_pixelstore_attrib
*packing
,
297 struct gl_texture_object
*texObj
,
298 struct gl_texture_image
*texImage
)
300 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
303 driSwapOutTextureObject( t
);
306 t
= (driTextureObject
*) r128AllocTexObj(texObj
);
308 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
313 /* Note, this will call r128ChooseTextureFormat */
314 _mesa_store_teximage1d( ctx
, target
, level
, internalFormat
,
315 width
, border
, format
, type
,
316 pixels
, packing
, texObj
, texImage
);
318 t
->dirty_images
[0] |= (1 << level
);
322 static void r128TexSubImage1D( GLcontext
*ctx
,
327 GLenum format
, GLenum type
,
328 const GLvoid
*pixels
,
329 const struct gl_pixelstore_attrib
*packing
,
330 struct gl_texture_object
*texObj
,
331 struct gl_texture_image
*texImage
)
333 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
335 assert( t
); /* this _should_ be true */
337 driSwapOutTextureObject( t
);
340 t
= (driTextureObject
*) r128AllocTexObj(texObj
);
342 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
347 _mesa_store_texsubimage1d(ctx
, target
, level
, xoffset
, width
,
348 format
, type
, pixels
, packing
, texObj
,
351 t
->dirty_images
[0] |= (1 << level
);
355 static void r128TexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
356 GLint internalFormat
,
357 GLint width
, GLint height
, GLint border
,
358 GLenum format
, GLenum type
, const GLvoid
*pixels
,
359 const struct gl_pixelstore_attrib
*packing
,
360 struct gl_texture_object
*texObj
,
361 struct gl_texture_image
*texImage
)
363 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
366 driSwapOutTextureObject( (driTextureObject
*) t
);
369 t
= (driTextureObject
*) r128AllocTexObj(texObj
);
371 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
376 /* Note, this will call r128ChooseTextureFormat */
377 _mesa_store_teximage2d(ctx
, target
, level
, internalFormat
,
378 width
, height
, border
, format
, type
, pixels
,
379 &ctx
->Unpack
, texObj
, texImage
);
381 t
->dirty_images
[0] |= (1 << level
);
385 static void r128TexSubImage2D( GLcontext
*ctx
,
388 GLint xoffset
, GLint yoffset
,
389 GLsizei width
, GLsizei height
,
390 GLenum format
, GLenum type
,
391 const GLvoid
*pixels
,
392 const struct gl_pixelstore_attrib
*packing
,
393 struct gl_texture_object
*texObj
,
394 struct gl_texture_image
*texImage
)
396 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
398 assert( t
); /* this _should_ be true */
400 driSwapOutTextureObject( t
);
403 t
= (driTextureObject
*) r128AllocTexObj(texObj
);
405 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
410 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
411 height
, format
, type
, pixels
, packing
, texObj
,
413 t
->dirty_images
[0] |= (1 << level
);
417 static void r128TexEnv( GLcontext
*ctx
, GLenum target
,
418 GLenum pname
, const GLfloat
*param
)
420 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
421 struct gl_texture_unit
*texUnit
;
424 if ( R128_DEBUG
& DEBUG_VERBOSE_API
) {
425 fprintf( stderr
, "%s( %s )\n",
426 __FUNCTION__
, _mesa_lookup_enum_by_nr( pname
) );
430 case GL_TEXTURE_ENV_MODE
:
431 FLUSH_BATCH( rmesa
);
432 rmesa
->new_state
|= R128_NEW_ALPHA
;
435 case GL_TEXTURE_ENV_COLOR
:
436 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
437 CLAMPED_FLOAT_TO_UBYTE( c
[0], texUnit
->EnvColor
[0] );
438 CLAMPED_FLOAT_TO_UBYTE( c
[1], texUnit
->EnvColor
[1] );
439 CLAMPED_FLOAT_TO_UBYTE( c
[2], texUnit
->EnvColor
[2] );
440 CLAMPED_FLOAT_TO_UBYTE( c
[3], texUnit
->EnvColor
[3] );
441 rmesa
->env_color
= r128PackColor( 4, c
[0], c
[1], c
[2], c
[3] );
442 if ( rmesa
->setup
.constant_color_c
!= rmesa
->env_color
) {
443 FLUSH_BATCH( rmesa
);
444 rmesa
->setup
.constant_color_c
= rmesa
->env_color
;
446 /* More complex multitexture/multipass fallbacks for GL_BLEND
447 * can be done later, but this allows a single pass GL_BLEND
448 * in some cases (ie. Performer town demo). This is only
449 * applicable to the regular Rage 128, as the Pro and M3 can
450 * handle true single-pass GL_BLEND texturing.
452 rmesa
->blend_flags
&= ~R128_BLEND_ENV_COLOR
;
453 if ( R128_IS_PLAIN( rmesa
) &&
454 rmesa
->env_color
!= 0x00000000 &&
455 rmesa
->env_color
!= 0xff000000 &&
456 rmesa
->env_color
!= 0x00ffffff &&
457 rmesa
->env_color
!= 0xffffffff ) {
458 rmesa
->blend_flags
|= R128_BLEND_ENV_COLOR
;
463 case GL_TEXTURE_LOD_BIAS
:
465 u_int32_t t
= rmesa
->setup
.tex_cntl_c
;
469 /* GTH: This isn't exactly correct, but gives good results up to a
470 * certain point. It is better than completely ignoring the LOD
471 * bias. Unfortunately there isn't much range in the bias, the
472 * spec mentions strides that vary between 0.5 and 2.0 but these
473 * numbers don't seem to relate the the GL LOD bias value at all.
475 if ( param
[0] >= 1.0 ) {
477 } else if ( param
[0] >= 0.5 ) {
479 } else if ( param
[0] >= 0.25 ) {
481 } else if ( param
[0] >= 0.0 ) {
487 b
= (u_int32_t
)bias
& 0xff;
488 t
&= ~R128_LOD_BIAS_MASK
;
489 t
|= (b
<< R128_LOD_BIAS_SHIFT
);
491 if ( rmesa
->setup
.tex_cntl_c
!= t
) {
492 FLUSH_BATCH( rmesa
);
493 rmesa
->setup
.tex_cntl_c
= t
;
494 rmesa
->dirty
|= R128_UPLOAD_CONTEXT
;
505 static void r128TexParameter( GLcontext
*ctx
, GLenum target
,
506 struct gl_texture_object
*tObj
,
507 GLenum pname
, const GLfloat
*params
)
509 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
510 r128TexObjPtr t
= (r128TexObjPtr
)tObj
->DriverData
;
512 if ( R128_DEBUG
& DEBUG_VERBOSE_API
) {
513 fprintf( stderr
, "%s( %s )\n",
514 __FUNCTION__
, _mesa_lookup_enum_by_nr( pname
) );
517 if ( ( target
!= GL_TEXTURE_2D
) && ( target
!= GL_TEXTURE_1D
) )
521 case GL_TEXTURE_MIN_FILTER
:
522 case GL_TEXTURE_MAG_FILTER
:
523 if ( t
->base
.bound
) FLUSH_BATCH( rmesa
);
524 r128SetTexFilter( t
, tObj
->MinFilter
, tObj
->MagFilter
);
527 case GL_TEXTURE_WRAP_S
:
528 case GL_TEXTURE_WRAP_T
:
529 if ( t
->base
.bound
) FLUSH_BATCH( rmesa
);
530 r128SetTexWrap( t
, tObj
->WrapS
, tObj
->WrapT
);
533 case GL_TEXTURE_BORDER_COLOR
:
534 if ( t
->base
.bound
) FLUSH_BATCH( rmesa
);
535 r128SetTexBorderColor( t
, tObj
->_BorderChan
);
538 case GL_TEXTURE_BASE_LEVEL
:
539 case GL_TEXTURE_MAX_LEVEL
:
540 case GL_TEXTURE_MIN_LOD
:
541 case GL_TEXTURE_MAX_LOD
:
542 /* This isn't the most efficient solution but there doesn't appear to
543 * be a nice alternative for R128. Since there's no LOD clamping,
544 * we just have to rely on loading the right subset of mipmap levels
545 * to simulate a clamped LOD.
547 if ( t
->base
.bound
) FLUSH_BATCH( rmesa
);
548 driSwapOutTextureObject( (driTextureObject
*) t
);
556 static void r128BindTexture( GLcontext
*ctx
, GLenum target
,
557 struct gl_texture_object
*tObj
)
559 if ( R128_DEBUG
& DEBUG_VERBOSE_API
) {
560 fprintf( stderr
, "%s( %p ) unit=%d\n", __FUNCTION__
, (void *) tObj
,
561 ctx
->Texture
.CurrentUnit
);
564 assert( (target
!= GL_TEXTURE_2D
&& target
!= GL_TEXTURE_1D
) ||
565 (tObj
->DriverData
!= NULL
) );
569 static void r128DeleteTexture( GLcontext
*ctx
,
570 struct gl_texture_object
*tObj
)
572 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
573 driTextureObject
* t
= (driTextureObject
*) tObj
->DriverData
;
576 if ( t
->bound
&& rmesa
) {
577 FLUSH_BATCH( rmesa
);
580 driDestroyTextureObject( t
);
582 /* Free mipmap images and the texture object itself */
583 _mesa_delete_texture_object(ctx
, tObj
);
587 * Allocate a new texture object.
588 * Called via ctx->Driver.NewTextureObject.
589 * Note: we could use containment here to 'derive' the driver-specific
590 * texture object from the core mesa gl_texture_object. Not done at this time.
592 static struct gl_texture_object
*
593 r128NewTextureObject( GLcontext
*ctx
, GLuint name
, GLenum target
)
595 struct gl_texture_object
*obj
;
596 obj
= _mesa_new_texture_object(ctx
, name
, target
);
597 r128AllocTexObj( obj
);
601 void r128InitTextureFuncs( struct dd_function_table
*functions
)
603 functions
->TexEnv
= r128TexEnv
;
604 functions
->ChooseTextureFormat
= r128ChooseTextureFormat
;
605 functions
->TexImage1D
= r128TexImage1D
;
606 functions
->TexSubImage1D
= r128TexSubImage1D
;
607 functions
->TexImage2D
= r128TexImage2D
;
608 functions
->TexSubImage2D
= r128TexSubImage2D
;
609 functions
->TexParameter
= r128TexParameter
;
610 functions
->BindTexture
= r128BindTexture
;
611 functions
->NewTextureObject
= r128NewTextureObject
;
612 functions
->DeleteTexture
= r128DeleteTexture
;
613 functions
->IsTextureResident
= driIsTextureResident
;
615 driInitTextureFormats();