1 /**************************************************************************
3 Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
7 Permission is hereby granted, free of charge, to any person obtaining a
8 copy of this software and associated documentation files (the "Software"),
9 to deal in the Software without restriction, including without limitation
10 on the rights to use, copy, modify, merge, publish, distribute, sub
11 license, and/or sell copies of the Software, and to permit persons to whom
12 the Software is furnished to do so, subject to the following conditions:
14 The above copyright notice and this permission notice (including the next
15 paragraph) shall be included in all copies or substantial portions of the
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
30 * Gareth Hughes <gareth@valinux.com>
31 * Kevin E. Martin <martin@valinux.com>
32 * Brian Paul <brianp@valinux.com>
35 #include "r128_context.h"
36 #include "r128_state.h"
37 #include "r128_ioctl.h"
38 #include "r128_tris.h"
40 #include "r128_texobj.h"
42 #include "main/context.h"
43 #include "main/macros.h"
44 #include "main/simple_list.h"
45 #include "main/enums.h"
46 #include "main/texstore.h"
47 #include "main/texformat.h"
48 #include "main/teximage.h"
49 #include "main/texobj.h"
50 #include "main/imports.h"
51 #include "main/colormac.h"
52 #include "main/texobj.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
, const GLfloat color
[4] )
141 CLAMPED_FLOAT_TO_UBYTE(c
[0], color
[0]);
142 CLAMPED_FLOAT_TO_UBYTE(c
[1], color
[1]);
143 CLAMPED_FLOAT_TO_UBYTE(c
[2], color
[2]);
144 CLAMPED_FLOAT_TO_UBYTE(c
[3], color
[3]);
145 t
->setup
.tex_border_color
= r128PackColor( 4, c
[0], c
[1], c
[2], c
[3] );
149 static r128TexObjPtr
r128AllocTexObj( struct gl_texture_object
*texObj
)
153 if ( R128_DEBUG
& DEBUG_VERBOSE_API
) {
154 fprintf( stderr
, "%s( %p )\n", __FUNCTION__
, (void *) texObj
);
157 t
= (r128TexObjPtr
) CALLOC_STRUCT( r128_tex_obj
);
158 texObj
->DriverData
= t
;
161 /* Initialize non-image-dependent parts of the state:
163 t
->base
.tObj
= texObj
;
165 /* FIXME Something here to set initial values for other parts of
169 make_empty_list( (driTextureObject
*) t
);
171 r128SetTexWrap( t
, texObj
->WrapS
, texObj
->WrapT
);
172 r128SetTexFilter( t
, texObj
->MinFilter
, texObj
->MagFilter
);
173 r128SetTexBorderColor( t
, texObj
->BorderColor
);
180 /* Called by the _mesa_store_teximage[123]d() functions. */
182 r128ChooseTextureFormat( GLcontext
*ctx
, GLint internalFormat
,
183 GLenum format
, GLenum type
)
185 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
186 const GLboolean do32bpt
=
187 ( rmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_32
);
188 const GLboolean force16bpt
=
189 ( rmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_FORCE_16
);
193 switch ( internalFormat
) {
194 /* non-sized formats with alpha */
196 case GL_COMPRESSED_INTENSITY
:
198 case GL_COMPRESSED_ALPHA
:
200 case GL_LUMINANCE_ALPHA
:
201 case GL_COMPRESSED_LUMINANCE_ALPHA
:
204 case GL_COMPRESSED_RGBA
:
206 return _dri_texformat_argb8888
;
208 return _dri_texformat_argb4444
;
210 /* 16-bit formats with alpha */
213 case GL_LUMINANCE4_ALPHA4
:
216 return _dri_texformat_argb4444
;
218 /* 32-bit formats with alpha */
225 case GL_LUMINANCE6_ALPHA2
:
226 case GL_LUMINANCE8_ALPHA8
:
227 case GL_LUMINANCE12_ALPHA4
:
228 case GL_LUMINANCE12_ALPHA12
:
229 case GL_LUMINANCE16_ALPHA16
:
236 return _dri_texformat_argb8888
;
238 return _dri_texformat_argb4444
;
240 /* non-sized formats without alpha */
243 case GL_COMPRESSED_LUMINANCE
:
246 case GL_COMPRESSED_RGB
:
248 return _dri_texformat_argb8888
;
250 return _dri_texformat_rgb565
;
252 /* 16-bit formats without alpha */
257 return _dri_texformat_rgb565
;
259 /* 32-bit formats without alpha */
268 return _dri_texformat_argb8888
;
270 return _dri_texformat_rgb565
;
272 /* color-indexed formats */
274 case GL_COLOR_INDEX1_EXT
:
275 case GL_COLOR_INDEX2_EXT
:
276 case GL_COLOR_INDEX4_EXT
:
277 case GL_COLOR_INDEX8_EXT
:
278 case GL_COLOR_INDEX12_EXT
:
279 case GL_COLOR_INDEX16_EXT
:
280 return _dri_texformat_ci8
;
283 if (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
284 type
== GL_UNSIGNED_BYTE
)
285 return MESA_FORMAT_YCBCR
;
287 return MESA_FORMAT_YCBCR_REV
;
290 _mesa_problem( ctx
, "unexpected format in %s", __FUNCTION__
);
291 return MESA_FORMAT_NONE
;
296 static void r128TexImage1D( GLcontext
*ctx
, GLenum target
, GLint level
,
297 GLint internalFormat
,
298 GLint width
, GLint border
,
299 GLenum format
, GLenum type
, const GLvoid
*pixels
,
300 const struct gl_pixelstore_attrib
*packing
,
301 struct gl_texture_object
*texObj
,
302 struct gl_texture_image
*texImage
)
304 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
307 driSwapOutTextureObject( t
);
310 t
= (driTextureObject
*) r128AllocTexObj(texObj
);
312 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
317 /* Note, this will call r128ChooseTextureFormat */
318 _mesa_store_teximage1d( ctx
, target
, level
, internalFormat
,
319 width
, border
, format
, type
,
320 pixels
, packing
, texObj
, texImage
);
322 t
->dirty_images
[0] |= (1 << level
);
326 static void r128TexSubImage1D( GLcontext
*ctx
,
331 GLenum format
, GLenum type
,
332 const GLvoid
*pixels
,
333 const struct gl_pixelstore_attrib
*packing
,
334 struct gl_texture_object
*texObj
,
335 struct gl_texture_image
*texImage
)
337 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
339 assert( t
); /* this _should_ be true */
341 driSwapOutTextureObject( t
);
344 t
= (driTextureObject
*) r128AllocTexObj(texObj
);
346 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
351 _mesa_store_texsubimage1d(ctx
, target
, level
, xoffset
, width
,
352 format
, type
, pixels
, packing
, texObj
,
355 t
->dirty_images
[0] |= (1 << level
);
359 static void r128TexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
360 GLint internalFormat
,
361 GLint width
, GLint height
, GLint border
,
362 GLenum format
, GLenum type
, const GLvoid
*pixels
,
363 const struct gl_pixelstore_attrib
*packing
,
364 struct gl_texture_object
*texObj
,
365 struct gl_texture_image
*texImage
)
367 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
370 driSwapOutTextureObject( (driTextureObject
*) t
);
373 t
= (driTextureObject
*) r128AllocTexObj(texObj
);
375 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
380 /* Note, this will call r128ChooseTextureFormat */
381 _mesa_store_teximage2d(ctx
, target
, level
, internalFormat
,
382 width
, height
, border
, format
, type
, pixels
,
383 &ctx
->Unpack
, texObj
, texImage
);
385 t
->dirty_images
[0] |= (1 << level
);
389 static void r128TexSubImage2D( GLcontext
*ctx
,
392 GLint xoffset
, GLint yoffset
,
393 GLsizei width
, GLsizei height
,
394 GLenum format
, GLenum type
,
395 const GLvoid
*pixels
,
396 const struct gl_pixelstore_attrib
*packing
,
397 struct gl_texture_object
*texObj
,
398 struct gl_texture_image
*texImage
)
400 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
402 assert( t
); /* this _should_ be true */
404 driSwapOutTextureObject( t
);
407 t
= (driTextureObject
*) r128AllocTexObj(texObj
);
409 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
414 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
415 height
, format
, type
, pixels
, packing
, texObj
,
417 t
->dirty_images
[0] |= (1 << level
);
421 static void r128TexEnv( GLcontext
*ctx
, GLenum target
,
422 GLenum pname
, const GLfloat
*param
)
424 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
425 struct gl_texture_unit
*texUnit
;
428 if ( R128_DEBUG
& DEBUG_VERBOSE_API
) {
429 fprintf( stderr
, "%s( %s )\n",
430 __FUNCTION__
, _mesa_lookup_enum_by_nr( pname
) );
434 case GL_TEXTURE_ENV_MODE
:
435 FLUSH_BATCH( rmesa
);
436 rmesa
->new_state
|= R128_NEW_ALPHA
;
439 case GL_TEXTURE_ENV_COLOR
:
440 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
441 CLAMPED_FLOAT_TO_UBYTE( c
[0], texUnit
->EnvColor
[0] );
442 CLAMPED_FLOAT_TO_UBYTE( c
[1], texUnit
->EnvColor
[1] );
443 CLAMPED_FLOAT_TO_UBYTE( c
[2], texUnit
->EnvColor
[2] );
444 CLAMPED_FLOAT_TO_UBYTE( c
[3], texUnit
->EnvColor
[3] );
445 rmesa
->env_color
= r128PackColor( 4, c
[0], c
[1], c
[2], c
[3] );
446 if ( rmesa
->setup
.constant_color_c
!= rmesa
->env_color
) {
447 FLUSH_BATCH( rmesa
);
448 rmesa
->setup
.constant_color_c
= rmesa
->env_color
;
450 /* More complex multitexture/multipass fallbacks for GL_BLEND
451 * can be done later, but this allows a single pass GL_BLEND
452 * in some cases (ie. Performer town demo). This is only
453 * applicable to the regular Rage 128, as the Pro and M3 can
454 * handle true single-pass GL_BLEND texturing.
456 rmesa
->blend_flags
&= ~R128_BLEND_ENV_COLOR
;
457 if ( R128_IS_PLAIN( rmesa
) &&
458 rmesa
->env_color
!= 0x00000000 &&
459 rmesa
->env_color
!= 0xff000000 &&
460 rmesa
->env_color
!= 0x00ffffff &&
461 rmesa
->env_color
!= 0xffffffff ) {
462 rmesa
->blend_flags
|= R128_BLEND_ENV_COLOR
;
467 case GL_TEXTURE_LOD_BIAS
:
469 uint32_t t
= rmesa
->setup
.tex_cntl_c
;
473 /* GTH: This isn't exactly correct, but gives good results up to a
474 * certain point. It is better than completely ignoring the LOD
475 * bias. Unfortunately there isn't much range in the bias, the
476 * spec mentions strides that vary between 0.5 and 2.0 but these
477 * numbers don't seem to relate the the GL LOD bias value at all.
479 if ( param
[0] >= 1.0 ) {
481 } else if ( param
[0] >= 0.5 ) {
483 } else if ( param
[0] >= 0.25 ) {
485 } else if ( param
[0] >= 0.0 ) {
491 b
= (uint32_t)bias
& 0xff;
492 t
&= ~R128_LOD_BIAS_MASK
;
493 t
|= (b
<< R128_LOD_BIAS_SHIFT
);
495 if ( rmesa
->setup
.tex_cntl_c
!= t
) {
496 FLUSH_BATCH( rmesa
);
497 rmesa
->setup
.tex_cntl_c
= t
;
498 rmesa
->dirty
|= R128_UPLOAD_CONTEXT
;
509 static void r128TexParameter( GLcontext
*ctx
, GLenum target
,
510 struct gl_texture_object
*tObj
,
511 GLenum pname
, const GLfloat
*params
)
513 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
514 r128TexObjPtr t
= (r128TexObjPtr
)tObj
->DriverData
;
516 if ( R128_DEBUG
& DEBUG_VERBOSE_API
) {
517 fprintf( stderr
, "%s( %s )\n",
518 __FUNCTION__
, _mesa_lookup_enum_by_nr( pname
) );
521 if ( ( target
!= GL_TEXTURE_2D
) && ( target
!= GL_TEXTURE_1D
) )
525 case GL_TEXTURE_MIN_FILTER
:
526 case GL_TEXTURE_MAG_FILTER
:
527 if ( t
->base
.bound
) FLUSH_BATCH( rmesa
);
528 r128SetTexFilter( t
, tObj
->MinFilter
, tObj
->MagFilter
);
531 case GL_TEXTURE_WRAP_S
:
532 case GL_TEXTURE_WRAP_T
:
533 if ( t
->base
.bound
) FLUSH_BATCH( rmesa
);
534 r128SetTexWrap( t
, tObj
->WrapS
, tObj
->WrapT
);
537 case GL_TEXTURE_BORDER_COLOR
:
538 if ( t
->base
.bound
) FLUSH_BATCH( rmesa
);
539 r128SetTexBorderColor( t
, tObj
->BorderColor
);
542 case GL_TEXTURE_BASE_LEVEL
:
543 case GL_TEXTURE_MAX_LEVEL
:
544 case GL_TEXTURE_MIN_LOD
:
545 case GL_TEXTURE_MAX_LOD
:
546 /* This isn't the most efficient solution but there doesn't appear to
547 * be a nice alternative for R128. Since there's no LOD clamping,
548 * we just have to rely on loading the right subset of mipmap levels
549 * to simulate a clamped LOD.
551 if ( t
->base
.bound
) FLUSH_BATCH( rmesa
);
552 driSwapOutTextureObject( (driTextureObject
*) t
);
560 static void r128BindTexture( GLcontext
*ctx
, GLenum target
,
561 struct gl_texture_object
*tObj
)
563 if ( R128_DEBUG
& DEBUG_VERBOSE_API
) {
564 fprintf( stderr
, "%s( %p ) unit=%d\n", __FUNCTION__
, (void *) tObj
,
565 ctx
->Texture
.CurrentUnit
);
568 assert( (target
!= GL_TEXTURE_2D
&& target
!= GL_TEXTURE_1D
) ||
569 (tObj
->DriverData
!= NULL
) );
573 static void r128DeleteTexture( GLcontext
*ctx
,
574 struct gl_texture_object
*tObj
)
576 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
577 driTextureObject
* t
= (driTextureObject
*) tObj
->DriverData
;
580 if ( t
->bound
&& rmesa
) {
581 FLUSH_BATCH( rmesa
);
584 driDestroyTextureObject( t
);
586 /* Free mipmap images and the texture object itself */
587 _mesa_delete_texture_object(ctx
, tObj
);
591 * Allocate a new texture object.
592 * Called via ctx->Driver.NewTextureObject.
593 * Note: we could use containment here to 'derive' the driver-specific
594 * texture object from the core mesa gl_texture_object. Not done at this time.
596 static struct gl_texture_object
*
597 r128NewTextureObject( GLcontext
*ctx
, GLuint name
, GLenum target
)
599 struct gl_texture_object
*obj
;
600 obj
= _mesa_new_texture_object(ctx
, name
, target
);
601 r128AllocTexObj( obj
);
605 void r128InitTextureFuncs( struct dd_function_table
*functions
)
607 functions
->TexEnv
= r128TexEnv
;
608 functions
->ChooseTextureFormat
= r128ChooseTextureFormat
;
609 functions
->TexImage1D
= r128TexImage1D
;
610 functions
->TexSubImage1D
= r128TexSubImage1D
;
611 functions
->TexImage2D
= r128TexImage2D
;
612 functions
->TexSubImage2D
= r128TexSubImage2D
;
613 functions
->TexParameter
= r128TexParameter
;
614 functions
->BindTexture
= r128BindTexture
;
615 functions
->NewTextureObject
= r128NewTextureObject
;
616 functions
->DeleteTexture
= r128DeleteTexture
;
617 functions
->IsTextureResident
= driIsTextureResident
;
619 driInitTextureFormats();