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"
63 * Set the texture wrap modes. Currently \c GL_REPEAT, \c GL_CLAMP,
64 * \c GL_CLAMP_TO_EDGE, and \c GL_MIRRORED_REPEAT are supported.
66 * \param t Texture object whose wrap modes are to be set
67 * \param swrap Wrap mode for the \a s texture coordinate
68 * \param twrap Wrap mode for the \a t texture coordinate
70 static void r128SetTexWrap( r128TexObjPtr t
, GLenum swrap
, GLenum twrap
)
72 t
->setup
.tex_cntl
&= ~(R128_TEX_CLAMP_S_MASK
| R128_TEX_CLAMP_T_MASK
);
76 t
->setup
.tex_cntl
|= R128_TEX_CLAMP_S_BORDER_COLOR
;
78 case GL_CLAMP_TO_EDGE
:
79 t
->setup
.tex_cntl
|= R128_TEX_CLAMP_S_CLAMP
;
82 t
->setup
.tex_cntl
|= R128_TEX_CLAMP_S_WRAP
;
84 case GL_MIRRORED_REPEAT
:
85 t
->setup
.tex_cntl
|= R128_TEX_CLAMP_S_MIRROR
;
91 t
->setup
.tex_cntl
|= R128_TEX_CLAMP_T_BORDER_COLOR
;
93 case GL_CLAMP_TO_EDGE
:
94 t
->setup
.tex_cntl
|= R128_TEX_CLAMP_T_CLAMP
;
97 t
->setup
.tex_cntl
|= R128_TEX_CLAMP_T_WRAP
;
99 case GL_MIRRORED_REPEAT
:
100 t
->setup
.tex_cntl
|= R128_TEX_CLAMP_T_MIRROR
;
105 static void r128SetTexFilter( r128TexObjPtr t
, GLenum minf
, GLenum magf
)
107 t
->setup
.tex_cntl
&= ~(R128_MIN_BLEND_MASK
| R128_MAG_BLEND_MASK
);
111 t
->setup
.tex_cntl
|= R128_MIN_BLEND_NEAREST
;
114 t
->setup
.tex_cntl
|= R128_MIN_BLEND_LINEAR
;
116 case GL_NEAREST_MIPMAP_NEAREST
:
117 t
->setup
.tex_cntl
|= R128_MIN_BLEND_MIPNEAREST
;
119 case GL_LINEAR_MIPMAP_NEAREST
:
120 t
->setup
.tex_cntl
|= R128_MIN_BLEND_MIPLINEAR
;
122 case GL_NEAREST_MIPMAP_LINEAR
:
123 t
->setup
.tex_cntl
|= R128_MIN_BLEND_LINEARMIPNEAREST
;
125 case GL_LINEAR_MIPMAP_LINEAR
:
126 t
->setup
.tex_cntl
|= R128_MIN_BLEND_LINEARMIPLINEAR
;
132 t
->setup
.tex_cntl
|= R128_MAG_BLEND_NEAREST
;
135 t
->setup
.tex_cntl
|= R128_MAG_BLEND_LINEAR
;
140 static void r128SetTexBorderColor( r128TexObjPtr t
, GLubyte c
[4] )
142 t
->setup
.tex_border_color
= r128PackColor( 4, c
[0], c
[1], c
[2], c
[3] );
146 static r128TexObjPtr
r128AllocTexObj( struct gl_texture_object
*texObj
)
150 if ( R128_DEBUG
& DEBUG_VERBOSE_API
) {
151 fprintf( stderr
, "%s( %p )\n", __FUNCTION__
, (void *) texObj
);
154 t
= (r128TexObjPtr
) CALLOC_STRUCT( r128_tex_obj
);
155 texObj
->DriverData
= t
;
158 /* Initialize non-image-dependent parts of the state:
160 t
->base
.tObj
= texObj
;
162 /* FIXME Something here to set initial values for other parts of
166 make_empty_list( (driTextureObject
*) t
);
168 r128SetTexWrap( t
, texObj
->WrapS
, texObj
->WrapT
);
169 r128SetTexFilter( t
, texObj
->MinFilter
, texObj
->MagFilter
);
170 r128SetTexBorderColor( t
, texObj
->_BorderChan
);
177 /* Called by the _mesa_store_teximage[123]d() functions. */
178 static const struct gl_texture_format
*
179 r128ChooseTextureFormat( GLcontext
*ctx
, GLint internalFormat
,
180 GLenum format
, GLenum type
)
182 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
183 const GLboolean do32bpt
=
184 ( rmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_32
);
185 const GLboolean force16bpt
=
186 ( rmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_FORCE_16
);
190 switch ( internalFormat
) {
191 /* non-sized formats with alpha */
193 case GL_COMPRESSED_INTENSITY
:
195 case GL_COMPRESSED_ALPHA
:
197 case GL_LUMINANCE_ALPHA
:
198 case GL_COMPRESSED_LUMINANCE_ALPHA
:
201 case GL_COMPRESSED_RGBA
:
203 return _dri_texformat_argb8888
;
205 return _dri_texformat_argb4444
;
207 /* 16-bit formats with alpha */
210 case GL_LUMINANCE4_ALPHA4
:
213 return _dri_texformat_argb4444
;
215 /* 32-bit formats with alpha */
222 case GL_LUMINANCE6_ALPHA2
:
223 case GL_LUMINANCE8_ALPHA8
:
224 case GL_LUMINANCE12_ALPHA4
:
225 case GL_LUMINANCE12_ALPHA12
:
226 case GL_LUMINANCE16_ALPHA16
:
233 return _dri_texformat_argb8888
;
235 return _dri_texformat_argb4444
;
237 /* non-sized formats without alpha */
240 case GL_COMPRESSED_LUMINANCE
:
243 case GL_COMPRESSED_RGB
:
245 return _dri_texformat_argb8888
;
247 return _dri_texformat_rgb565
;
249 /* 16-bit formats without alpha */
254 return _dri_texformat_rgb565
;
256 /* 32-bit formats without alpha */
265 return _dri_texformat_argb8888
;
267 return _dri_texformat_rgb565
;
269 /* color-indexed formats */
271 case GL_COLOR_INDEX1_EXT
:
272 case GL_COLOR_INDEX2_EXT
:
273 case GL_COLOR_INDEX4_EXT
:
274 case GL_COLOR_INDEX8_EXT
:
275 case GL_COLOR_INDEX12_EXT
:
276 case GL_COLOR_INDEX16_EXT
:
277 return _dri_texformat_ci8
;
280 if (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
281 type
== GL_UNSIGNED_BYTE
)
282 return &_mesa_texformat_ycbcr
;
284 return &_mesa_texformat_ycbcr_rev
;
287 _mesa_problem( ctx
, "unexpected format in %s", __FUNCTION__
);
293 static void r128TexImage1D( GLcontext
*ctx
, GLenum target
, GLint level
,
294 GLint internalFormat
,
295 GLint width
, GLint border
,
296 GLenum format
, GLenum type
, const GLvoid
*pixels
,
297 const struct gl_pixelstore_attrib
*packing
,
298 struct gl_texture_object
*texObj
,
299 struct gl_texture_image
*texImage
)
301 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
304 driSwapOutTextureObject( t
);
307 t
= (driTextureObject
*) r128AllocTexObj(texObj
);
309 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
314 /* Note, this will call r128ChooseTextureFormat */
315 _mesa_store_teximage1d( ctx
, target
, level
, internalFormat
,
316 width
, border
, format
, type
,
317 pixels
, packing
, texObj
, texImage
);
319 t
->dirty_images
[0] |= (1 << level
);
323 static void r128TexSubImage1D( GLcontext
*ctx
,
328 GLenum format
, GLenum type
,
329 const GLvoid
*pixels
,
330 const struct gl_pixelstore_attrib
*packing
,
331 struct gl_texture_object
*texObj
,
332 struct gl_texture_image
*texImage
)
334 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
336 assert( t
); /* this _should_ be true */
338 driSwapOutTextureObject( t
);
341 t
= (driTextureObject
*) r128AllocTexObj(texObj
);
343 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
348 _mesa_store_texsubimage1d(ctx
, target
, level
, xoffset
, width
,
349 format
, type
, pixels
, packing
, texObj
,
352 t
->dirty_images
[0] |= (1 << level
);
356 static void r128TexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
357 GLint internalFormat
,
358 GLint width
, GLint height
, GLint border
,
359 GLenum format
, GLenum type
, const GLvoid
*pixels
,
360 const struct gl_pixelstore_attrib
*packing
,
361 struct gl_texture_object
*texObj
,
362 struct gl_texture_image
*texImage
)
364 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
367 driSwapOutTextureObject( (driTextureObject
*) t
);
370 t
= (driTextureObject
*) r128AllocTexObj(texObj
);
372 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
377 /* Note, this will call r128ChooseTextureFormat */
378 _mesa_store_teximage2d(ctx
, target
, level
, internalFormat
,
379 width
, height
, border
, format
, type
, pixels
,
380 &ctx
->Unpack
, texObj
, texImage
);
382 t
->dirty_images
[0] |= (1 << level
);
386 static void r128TexSubImage2D( GLcontext
*ctx
,
389 GLint xoffset
, GLint yoffset
,
390 GLsizei width
, GLsizei height
,
391 GLenum format
, GLenum type
,
392 const GLvoid
*pixels
,
393 const struct gl_pixelstore_attrib
*packing
,
394 struct gl_texture_object
*texObj
,
395 struct gl_texture_image
*texImage
)
397 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
399 assert( t
); /* this _should_ be true */
401 driSwapOutTextureObject( t
);
404 t
= (driTextureObject
*) r128AllocTexObj(texObj
);
406 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
411 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
412 height
, format
, type
, pixels
, packing
, texObj
,
414 t
->dirty_images
[0] |= (1 << level
);
418 static void r128TexEnv( GLcontext
*ctx
, GLenum target
,
419 GLenum pname
, const GLfloat
*param
)
421 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
422 struct gl_texture_unit
*texUnit
;
425 if ( R128_DEBUG
& DEBUG_VERBOSE_API
) {
426 fprintf( stderr
, "%s( %s )\n",
427 __FUNCTION__
, _mesa_lookup_enum_by_nr( pname
) );
431 case GL_TEXTURE_ENV_MODE
:
432 FLUSH_BATCH( rmesa
);
433 rmesa
->new_state
|= R128_NEW_ALPHA
;
436 case GL_TEXTURE_ENV_COLOR
:
437 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
438 CLAMPED_FLOAT_TO_UBYTE( c
[0], texUnit
->EnvColor
[0] );
439 CLAMPED_FLOAT_TO_UBYTE( c
[1], texUnit
->EnvColor
[1] );
440 CLAMPED_FLOAT_TO_UBYTE( c
[2], texUnit
->EnvColor
[2] );
441 CLAMPED_FLOAT_TO_UBYTE( c
[3], texUnit
->EnvColor
[3] );
442 rmesa
->env_color
= r128PackColor( 4, c
[0], c
[1], c
[2], c
[3] );
443 if ( rmesa
->setup
.constant_color_c
!= rmesa
->env_color
) {
444 FLUSH_BATCH( rmesa
);
445 rmesa
->setup
.constant_color_c
= rmesa
->env_color
;
447 /* More complex multitexture/multipass fallbacks for GL_BLEND
448 * can be done later, but this allows a single pass GL_BLEND
449 * in some cases (ie. Performer town demo). This is only
450 * applicable to the regular Rage 128, as the Pro and M3 can
451 * handle true single-pass GL_BLEND texturing.
453 rmesa
->blend_flags
&= ~R128_BLEND_ENV_COLOR
;
454 if ( R128_IS_PLAIN( rmesa
) &&
455 rmesa
->env_color
!= 0x00000000 &&
456 rmesa
->env_color
!= 0xff000000 &&
457 rmesa
->env_color
!= 0x00ffffff &&
458 rmesa
->env_color
!= 0xffffffff ) {
459 rmesa
->blend_flags
|= R128_BLEND_ENV_COLOR
;
464 case GL_TEXTURE_LOD_BIAS
:
466 uint32_t t
= rmesa
->setup
.tex_cntl_c
;
470 /* GTH: This isn't exactly correct, but gives good results up to a
471 * certain point. It is better than completely ignoring the LOD
472 * bias. Unfortunately there isn't much range in the bias, the
473 * spec mentions strides that vary between 0.5 and 2.0 but these
474 * numbers don't seem to relate the the GL LOD bias value at all.
476 if ( param
[0] >= 1.0 ) {
478 } else if ( param
[0] >= 0.5 ) {
480 } else if ( param
[0] >= 0.25 ) {
482 } else if ( param
[0] >= 0.0 ) {
488 b
= (uint32_t)bias
& 0xff;
489 t
&= ~R128_LOD_BIAS_MASK
;
490 t
|= (b
<< R128_LOD_BIAS_SHIFT
);
492 if ( rmesa
->setup
.tex_cntl_c
!= t
) {
493 FLUSH_BATCH( rmesa
);
494 rmesa
->setup
.tex_cntl_c
= t
;
495 rmesa
->dirty
|= R128_UPLOAD_CONTEXT
;
506 static void r128TexParameter( GLcontext
*ctx
, GLenum target
,
507 struct gl_texture_object
*tObj
,
508 GLenum pname
, const GLfloat
*params
)
510 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
511 r128TexObjPtr t
= (r128TexObjPtr
)tObj
->DriverData
;
513 if ( R128_DEBUG
& DEBUG_VERBOSE_API
) {
514 fprintf( stderr
, "%s( %s )\n",
515 __FUNCTION__
, _mesa_lookup_enum_by_nr( pname
) );
518 if ( ( target
!= GL_TEXTURE_2D
) && ( target
!= GL_TEXTURE_1D
) )
522 case GL_TEXTURE_MIN_FILTER
:
523 case GL_TEXTURE_MAG_FILTER
:
524 if ( t
->base
.bound
) FLUSH_BATCH( rmesa
);
525 r128SetTexFilter( t
, tObj
->MinFilter
, tObj
->MagFilter
);
528 case GL_TEXTURE_WRAP_S
:
529 case GL_TEXTURE_WRAP_T
:
530 if ( t
->base
.bound
) FLUSH_BATCH( rmesa
);
531 r128SetTexWrap( t
, tObj
->WrapS
, tObj
->WrapT
);
534 case GL_TEXTURE_BORDER_COLOR
:
535 if ( t
->base
.bound
) FLUSH_BATCH( rmesa
);
536 r128SetTexBorderColor( t
, tObj
->_BorderChan
);
539 case GL_TEXTURE_BASE_LEVEL
:
540 case GL_TEXTURE_MAX_LEVEL
:
541 case GL_TEXTURE_MIN_LOD
:
542 case GL_TEXTURE_MAX_LOD
:
543 /* This isn't the most efficient solution but there doesn't appear to
544 * be a nice alternative for R128. Since there's no LOD clamping,
545 * we just have to rely on loading the right subset of mipmap levels
546 * to simulate a clamped LOD.
548 if ( t
->base
.bound
) FLUSH_BATCH( rmesa
);
549 driSwapOutTextureObject( (driTextureObject
*) t
);
557 static void r128BindTexture( GLcontext
*ctx
, GLenum target
,
558 struct gl_texture_object
*tObj
)
560 if ( R128_DEBUG
& DEBUG_VERBOSE_API
) {
561 fprintf( stderr
, "%s( %p ) unit=%d\n", __FUNCTION__
, (void *) tObj
,
562 ctx
->Texture
.CurrentUnit
);
565 assert( (target
!= GL_TEXTURE_2D
&& target
!= GL_TEXTURE_1D
) ||
566 (tObj
->DriverData
!= NULL
) );
570 static void r128DeleteTexture( 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
);
588 * Allocate a new texture object.
589 * Called via ctx->Driver.NewTextureObject.
590 * Note: we could use containment here to 'derive' the driver-specific
591 * texture object from the core mesa gl_texture_object. Not done at this time.
593 static struct gl_texture_object
*
594 r128NewTextureObject( GLcontext
*ctx
, GLuint name
, GLenum target
)
596 struct gl_texture_object
*obj
;
597 obj
= _mesa_new_texture_object(ctx
, name
, target
);
598 r128AllocTexObj( obj
);
602 void r128InitTextureFuncs( struct dd_function_table
*functions
)
604 functions
->TexEnv
= r128TexEnv
;
605 functions
->ChooseTextureFormat
= r128ChooseTextureFormat
;
606 functions
->TexImage1D
= r128TexImage1D
;
607 functions
->TexSubImage1D
= r128TexSubImage1D
;
608 functions
->TexImage2D
= r128TexImage2D
;
609 functions
->TexSubImage2D
= r128TexSubImage2D
;
610 functions
->TexParameter
= r128TexParameter
;
611 functions
->BindTexture
= r128BindTexture
;
612 functions
->NewTextureObject
= r128NewTextureObject
;
613 functions
->DeleteTexture
= r128DeleteTexture
;
614 functions
->IsTextureResident
= driIsTextureResident
;
616 driInitTextureFormats();