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
, 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__
, (void *) 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 _dri_texformat_argb8888
;
203 return _dri_texformat_argb4444
;
205 /* 16-bit formats with alpha */
208 case GL_LUMINANCE4_ALPHA4
:
211 return _dri_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 _dri_texformat_argb8888
;
233 return _dri_texformat_argb4444
;
235 /* non-sized formats without alpha */
238 case GL_COMPRESSED_LUMINANCE
:
241 case GL_COMPRESSED_RGB
:
243 return _dri_texformat_argb8888
;
245 return _dri_texformat_rgb565
;
247 /* 16-bit formats without alpha */
252 return _dri_texformat_rgb565
;
254 /* 32-bit formats without alpha */
263 return _dri_texformat_argb8888
;
265 return _dri_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 _dri_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 r128TexEnv( 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 uint32_t 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
= (uint32_t)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 r128TexParameter( 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 r128BindTexture( 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__
, (void *) tObj
,
560 ctx
->Texture
.CurrentUnit
);
563 assert( (target
!= GL_TEXTURE_2D
&& target
!= GL_TEXTURE_1D
) ||
564 (tObj
->DriverData
!= NULL
) );
568 static void r128DeleteTexture( GLcontext
*ctx
,
569 struct gl_texture_object
*tObj
)
571 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
572 driTextureObject
* t
= (driTextureObject
*) tObj
->DriverData
;
575 if ( t
->bound
&& rmesa
) {
576 FLUSH_BATCH( rmesa
);
579 driDestroyTextureObject( t
);
581 /* Free mipmap images and the texture object itself */
582 _mesa_delete_texture_object(ctx
, tObj
);
586 * Allocate a new texture object.
587 * Called via ctx->Driver.NewTextureObject.
588 * Note: we could use containment here to 'derive' the driver-specific
589 * texture object from the core mesa gl_texture_object. Not done at this time.
591 static struct gl_texture_object
*
592 r128NewTextureObject( GLcontext
*ctx
, GLuint name
, GLenum target
)
594 struct gl_texture_object
*obj
;
595 obj
= _mesa_new_texture_object(ctx
, name
, target
);
596 r128AllocTexObj( obj
);
600 void r128InitTextureFuncs( struct dd_function_table
*functions
)
602 functions
->TexEnv
= r128TexEnv
;
603 functions
->ChooseTextureFormat
= r128ChooseTextureFormat
;
604 functions
->TexImage1D
= r128TexImage1D
;
605 functions
->TexSubImage1D
= r128TexSubImage1D
;
606 functions
->TexImage2D
= r128TexImage2D
;
607 functions
->TexSubImage2D
= r128TexSubImage2D
;
608 functions
->TexParameter
= r128TexParameter
;
609 functions
->BindTexture
= r128BindTexture
;
610 functions
->NewTextureObject
= r128NewTextureObject
;
611 functions
->DeleteTexture
= r128DeleteTexture
;
612 functions
->IsTextureResident
= driIsTextureResident
;
614 driInitTextureFormats();