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/teximage.h"
48 #include "main/texobj.h"
49 #include "main/imports.h"
50 #include "main/colormac.h"
51 #include "main/texobj.h"
60 * Set the texture wrap modes. Currently \c GL_REPEAT, \c GL_CLAMP,
61 * \c GL_CLAMP_TO_EDGE, and \c GL_MIRRORED_REPEAT are supported.
63 * \param t Texture object whose wrap modes are to be set
64 * \param swrap Wrap mode for the \a s texture coordinate
65 * \param twrap Wrap mode for the \a t texture coordinate
67 static void r128SetTexWrap( r128TexObjPtr t
, GLenum swrap
, GLenum twrap
)
69 t
->setup
.tex_cntl
&= ~(R128_TEX_CLAMP_S_MASK
| R128_TEX_CLAMP_T_MASK
);
73 t
->setup
.tex_cntl
|= R128_TEX_CLAMP_S_BORDER_COLOR
;
75 case GL_CLAMP_TO_EDGE
:
76 t
->setup
.tex_cntl
|= R128_TEX_CLAMP_S_CLAMP
;
79 t
->setup
.tex_cntl
|= R128_TEX_CLAMP_S_WRAP
;
81 case GL_MIRRORED_REPEAT
:
82 t
->setup
.tex_cntl
|= R128_TEX_CLAMP_S_MIRROR
;
88 t
->setup
.tex_cntl
|= R128_TEX_CLAMP_T_BORDER_COLOR
;
90 case GL_CLAMP_TO_EDGE
:
91 t
->setup
.tex_cntl
|= R128_TEX_CLAMP_T_CLAMP
;
94 t
->setup
.tex_cntl
|= R128_TEX_CLAMP_T_WRAP
;
96 case GL_MIRRORED_REPEAT
:
97 t
->setup
.tex_cntl
|= R128_TEX_CLAMP_T_MIRROR
;
102 static void r128SetTexFilter( r128TexObjPtr t
, GLenum minf
, GLenum magf
)
104 t
->setup
.tex_cntl
&= ~(R128_MIN_BLEND_MASK
| R128_MAG_BLEND_MASK
);
108 t
->setup
.tex_cntl
|= R128_MIN_BLEND_NEAREST
;
111 t
->setup
.tex_cntl
|= R128_MIN_BLEND_LINEAR
;
113 case GL_NEAREST_MIPMAP_NEAREST
:
114 t
->setup
.tex_cntl
|= R128_MIN_BLEND_MIPNEAREST
;
116 case GL_LINEAR_MIPMAP_NEAREST
:
117 t
->setup
.tex_cntl
|= R128_MIN_BLEND_MIPLINEAR
;
119 case GL_NEAREST_MIPMAP_LINEAR
:
120 t
->setup
.tex_cntl
|= R128_MIN_BLEND_LINEARMIPNEAREST
;
122 case GL_LINEAR_MIPMAP_LINEAR
:
123 t
->setup
.tex_cntl
|= R128_MIN_BLEND_LINEARMIPLINEAR
;
129 t
->setup
.tex_cntl
|= R128_MAG_BLEND_NEAREST
;
132 t
->setup
.tex_cntl
|= R128_MAG_BLEND_LINEAR
;
137 static void r128SetTexBorderColor( r128TexObjPtr t
, const GLfloat color
[4] )
140 CLAMPED_FLOAT_TO_UBYTE(c
[0], color
[0]);
141 CLAMPED_FLOAT_TO_UBYTE(c
[1], color
[1]);
142 CLAMPED_FLOAT_TO_UBYTE(c
[2], color
[2]);
143 CLAMPED_FLOAT_TO_UBYTE(c
[3], color
[3]);
144 t
->setup
.tex_border_color
= r128PackColor( 4, c
[0], c
[1], c
[2], c
[3] );
148 static r128TexObjPtr
r128AllocTexObj( struct gl_texture_object
*texObj
)
152 if ( R128_DEBUG
& DEBUG_VERBOSE_API
) {
153 fprintf( stderr
, "%s( %p )\n", __FUNCTION__
, (void *) texObj
);
156 t
= (r128TexObjPtr
) CALLOC_STRUCT( r128_tex_obj
);
157 texObj
->DriverData
= t
;
160 /* Initialize non-image-dependent parts of the state:
162 t
->base
.tObj
= texObj
;
164 /* FIXME Something here to set initial values for other parts of
168 make_empty_list( (driTextureObject
*) t
);
170 r128SetTexWrap( t
, texObj
->WrapS
, texObj
->WrapT
);
171 r128SetTexFilter( t
, texObj
->MinFilter
, texObj
->MagFilter
);
172 r128SetTexBorderColor( t
, texObj
->BorderColor
);
179 /* Called by the _mesa_store_teximage[123]d() functions. */
181 r128ChooseTextureFormat( GLcontext
*ctx
, GLint internalFormat
,
182 GLenum format
, GLenum type
)
184 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
185 const GLboolean do32bpt
=
186 ( rmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_32
);
187 const GLboolean force16bpt
=
188 ( rmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_FORCE_16
);
192 switch ( internalFormat
) {
193 /* non-sized formats with alpha */
195 case GL_COMPRESSED_INTENSITY
:
197 case GL_COMPRESSED_ALPHA
:
199 case GL_LUMINANCE_ALPHA
:
200 case GL_COMPRESSED_LUMINANCE_ALPHA
:
203 case GL_COMPRESSED_RGBA
:
205 return _dri_texformat_argb8888
;
207 return _dri_texformat_argb4444
;
209 /* 16-bit formats with alpha */
212 case GL_LUMINANCE4_ALPHA4
:
215 return _dri_texformat_argb4444
;
217 /* 32-bit formats with alpha */
224 case GL_LUMINANCE6_ALPHA2
:
225 case GL_LUMINANCE8_ALPHA8
:
226 case GL_LUMINANCE12_ALPHA4
:
227 case GL_LUMINANCE12_ALPHA12
:
228 case GL_LUMINANCE16_ALPHA16
:
235 return _dri_texformat_argb8888
;
237 return _dri_texformat_argb4444
;
239 /* non-sized formats without alpha */
242 case GL_COMPRESSED_LUMINANCE
:
245 case GL_COMPRESSED_RGB
:
247 return _dri_texformat_argb8888
;
249 return _dri_texformat_rgb565
;
251 /* 16-bit formats without alpha */
256 return _dri_texformat_rgb565
;
258 /* 32-bit formats without alpha */
267 return _dri_texformat_argb8888
;
269 return _dri_texformat_rgb565
;
271 /* color-indexed formats */
273 case GL_COLOR_INDEX1_EXT
:
274 case GL_COLOR_INDEX2_EXT
:
275 case GL_COLOR_INDEX4_EXT
:
276 case GL_COLOR_INDEX8_EXT
:
277 case GL_COLOR_INDEX12_EXT
:
278 case GL_COLOR_INDEX16_EXT
:
279 return _dri_texformat_ci8
;
282 if (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
283 type
== GL_UNSIGNED_BYTE
)
284 return MESA_FORMAT_YCBCR
;
286 return MESA_FORMAT_YCBCR_REV
;
289 _mesa_problem( ctx
, "unexpected format in %s", __FUNCTION__
);
290 return MESA_FORMAT_NONE
;
295 static void r128TexImage1D( GLcontext
*ctx
, GLenum target
, GLint level
,
296 GLint internalFormat
,
297 GLint width
, GLint border
,
298 GLenum format
, GLenum type
, const GLvoid
*pixels
,
299 const struct gl_pixelstore_attrib
*packing
,
300 struct gl_texture_object
*texObj
,
301 struct gl_texture_image
*texImage
)
303 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
306 driSwapOutTextureObject( t
);
309 t
= (driTextureObject
*) r128AllocTexObj(texObj
);
311 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
316 /* Note, this will call r128ChooseTextureFormat */
317 _mesa_store_teximage1d( ctx
, target
, level
, internalFormat
,
318 width
, border
, format
, type
,
319 pixels
, packing
, texObj
, texImage
);
321 t
->dirty_images
[0] |= (1 << level
);
325 static void r128TexSubImage1D( GLcontext
*ctx
,
330 GLenum format
, GLenum type
,
331 const GLvoid
*pixels
,
332 const struct gl_pixelstore_attrib
*packing
,
333 struct gl_texture_object
*texObj
,
334 struct gl_texture_image
*texImage
)
336 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
338 assert( t
); /* this _should_ be true */
340 driSwapOutTextureObject( t
);
343 t
= (driTextureObject
*) r128AllocTexObj(texObj
);
345 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
350 _mesa_store_texsubimage1d(ctx
, target
, level
, xoffset
, width
,
351 format
, type
, pixels
, packing
, texObj
,
354 t
->dirty_images
[0] |= (1 << level
);
358 static void r128TexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
359 GLint internalFormat
,
360 GLint width
, GLint height
, GLint border
,
361 GLenum format
, GLenum type
, const GLvoid
*pixels
,
362 const struct gl_pixelstore_attrib
*packing
,
363 struct gl_texture_object
*texObj
,
364 struct gl_texture_image
*texImage
)
366 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
369 driSwapOutTextureObject( (driTextureObject
*) t
);
372 t
= (driTextureObject
*) r128AllocTexObj(texObj
);
374 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
379 /* Note, this will call r128ChooseTextureFormat */
380 _mesa_store_teximage2d(ctx
, target
, level
, internalFormat
,
381 width
, height
, border
, format
, type
, pixels
,
382 &ctx
->Unpack
, texObj
, texImage
);
384 t
->dirty_images
[0] |= (1 << level
);
388 static void r128TexSubImage2D( GLcontext
*ctx
,
391 GLint xoffset
, GLint yoffset
,
392 GLsizei width
, GLsizei height
,
393 GLenum format
, GLenum type
,
394 const GLvoid
*pixels
,
395 const struct gl_pixelstore_attrib
*packing
,
396 struct gl_texture_object
*texObj
,
397 struct gl_texture_image
*texImage
)
399 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
401 assert( t
); /* this _should_ be true */
403 driSwapOutTextureObject( t
);
406 t
= (driTextureObject
*) r128AllocTexObj(texObj
);
408 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
413 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
414 height
, format
, type
, pixels
, packing
, texObj
,
416 t
->dirty_images
[0] |= (1 << level
);
420 static void r128TexEnv( GLcontext
*ctx
, GLenum target
,
421 GLenum pname
, const GLfloat
*param
)
423 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
424 struct gl_texture_unit
*texUnit
;
427 if ( R128_DEBUG
& DEBUG_VERBOSE_API
) {
428 fprintf( stderr
, "%s( %s )\n",
429 __FUNCTION__
, _mesa_lookup_enum_by_nr( pname
) );
433 case GL_TEXTURE_ENV_MODE
:
434 FLUSH_BATCH( rmesa
);
435 rmesa
->new_state
|= R128_NEW_ALPHA
;
438 case GL_TEXTURE_ENV_COLOR
:
439 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
440 CLAMPED_FLOAT_TO_UBYTE( c
[0], texUnit
->EnvColor
[0] );
441 CLAMPED_FLOAT_TO_UBYTE( c
[1], texUnit
->EnvColor
[1] );
442 CLAMPED_FLOAT_TO_UBYTE( c
[2], texUnit
->EnvColor
[2] );
443 CLAMPED_FLOAT_TO_UBYTE( c
[3], texUnit
->EnvColor
[3] );
444 rmesa
->env_color
= r128PackColor( 4, c
[0], c
[1], c
[2], c
[3] );
445 if ( rmesa
->setup
.constant_color_c
!= rmesa
->env_color
) {
446 FLUSH_BATCH( rmesa
);
447 rmesa
->setup
.constant_color_c
= rmesa
->env_color
;
449 /* More complex multitexture/multipass fallbacks for GL_BLEND
450 * can be done later, but this allows a single pass GL_BLEND
451 * in some cases (ie. Performer town demo). This is only
452 * applicable to the regular Rage 128, as the Pro and M3 can
453 * handle true single-pass GL_BLEND texturing.
455 rmesa
->blend_flags
&= ~R128_BLEND_ENV_COLOR
;
456 if ( R128_IS_PLAIN( rmesa
) &&
457 rmesa
->env_color
!= 0x00000000 &&
458 rmesa
->env_color
!= 0xff000000 &&
459 rmesa
->env_color
!= 0x00ffffff &&
460 rmesa
->env_color
!= 0xffffffff ) {
461 rmesa
->blend_flags
|= R128_BLEND_ENV_COLOR
;
466 case GL_TEXTURE_LOD_BIAS
:
468 uint32_t t
= rmesa
->setup
.tex_cntl_c
;
472 /* GTH: This isn't exactly correct, but gives good results up to a
473 * certain point. It is better than completely ignoring the LOD
474 * bias. Unfortunately there isn't much range in the bias, the
475 * spec mentions strides that vary between 0.5 and 2.0 but these
476 * numbers don't seem to relate the the GL LOD bias value at all.
478 if ( param
[0] >= 1.0 ) {
480 } else if ( param
[0] >= 0.5 ) {
482 } else if ( param
[0] >= 0.25 ) {
484 } else if ( param
[0] >= 0.0 ) {
490 b
= (uint32_t)bias
& 0xff;
491 t
&= ~R128_LOD_BIAS_MASK
;
492 t
|= (b
<< R128_LOD_BIAS_SHIFT
);
494 if ( rmesa
->setup
.tex_cntl_c
!= t
) {
495 FLUSH_BATCH( rmesa
);
496 rmesa
->setup
.tex_cntl_c
= t
;
497 rmesa
->dirty
|= R128_UPLOAD_CONTEXT
;
508 static void r128TexParameter( GLcontext
*ctx
, GLenum target
,
509 struct gl_texture_object
*tObj
,
510 GLenum pname
, const GLfloat
*params
)
512 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
513 r128TexObjPtr t
= (r128TexObjPtr
)tObj
->DriverData
;
515 if ( R128_DEBUG
& DEBUG_VERBOSE_API
) {
516 fprintf( stderr
, "%s( %s )\n",
517 __FUNCTION__
, _mesa_lookup_enum_by_nr( pname
) );
520 if ( ( target
!= GL_TEXTURE_2D
) && ( target
!= GL_TEXTURE_1D
) )
524 case GL_TEXTURE_MIN_FILTER
:
525 case GL_TEXTURE_MAG_FILTER
:
526 if ( t
->base
.bound
) FLUSH_BATCH( rmesa
);
527 r128SetTexFilter( t
, tObj
->MinFilter
, tObj
->MagFilter
);
530 case GL_TEXTURE_WRAP_S
:
531 case GL_TEXTURE_WRAP_T
:
532 if ( t
->base
.bound
) FLUSH_BATCH( rmesa
);
533 r128SetTexWrap( t
, tObj
->WrapS
, tObj
->WrapT
);
536 case GL_TEXTURE_BORDER_COLOR
:
537 if ( t
->base
.bound
) FLUSH_BATCH( rmesa
);
538 r128SetTexBorderColor( t
, tObj
->BorderColor
);
541 case GL_TEXTURE_BASE_LEVEL
:
542 case GL_TEXTURE_MAX_LEVEL
:
543 case GL_TEXTURE_MIN_LOD
:
544 case GL_TEXTURE_MAX_LOD
:
545 /* This isn't the most efficient solution but there doesn't appear to
546 * be a nice alternative for R128. Since there's no LOD clamping,
547 * we just have to rely on loading the right subset of mipmap levels
548 * to simulate a clamped LOD.
550 if ( t
->base
.bound
) FLUSH_BATCH( rmesa
);
551 driSwapOutTextureObject( (driTextureObject
*) t
);
559 static void r128BindTexture( GLcontext
*ctx
, GLenum target
,
560 struct gl_texture_object
*tObj
)
562 if ( R128_DEBUG
& DEBUG_VERBOSE_API
) {
563 fprintf( stderr
, "%s( %p ) unit=%d\n", __FUNCTION__
, (void *) tObj
,
564 ctx
->Texture
.CurrentUnit
);
567 assert( (target
!= GL_TEXTURE_2D
&& target
!= GL_TEXTURE_1D
) ||
568 (tObj
->DriverData
!= NULL
) );
572 static void r128DeleteTexture( GLcontext
*ctx
,
573 struct gl_texture_object
*tObj
)
575 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
576 driTextureObject
* t
= (driTextureObject
*) tObj
->DriverData
;
579 if ( t
->bound
&& rmesa
) {
580 FLUSH_BATCH( rmesa
);
583 driDestroyTextureObject( t
);
585 /* Free mipmap images and the texture object itself */
586 _mesa_delete_texture_object(ctx
, tObj
);
590 * Allocate a new texture object.
591 * Called via ctx->Driver.NewTextureObject.
592 * Note: we could use containment here to 'derive' the driver-specific
593 * texture object from the core mesa gl_texture_object. Not done at this time.
595 static struct gl_texture_object
*
596 r128NewTextureObject( GLcontext
*ctx
, GLuint name
, GLenum target
)
598 struct gl_texture_object
*obj
;
599 obj
= _mesa_new_texture_object(ctx
, name
, target
);
600 r128AllocTexObj( obj
);
604 void r128InitTextureFuncs( struct dd_function_table
*functions
)
606 functions
->TexEnv
= r128TexEnv
;
607 functions
->ChooseTextureFormat
= r128ChooseTextureFormat
;
608 functions
->TexImage1D
= r128TexImage1D
;
609 functions
->TexSubImage1D
= r128TexSubImage1D
;
610 functions
->TexImage2D
= r128TexImage2D
;
611 functions
->TexSubImage2D
= r128TexSubImage2D
;
612 functions
->TexParameter
= r128TexParameter
;
613 functions
->BindTexture
= r128BindTexture
;
614 functions
->NewTextureObject
= r128NewTextureObject
;
615 functions
->DeleteTexture
= r128DeleteTexture
;
616 functions
->IsTextureResident
= driIsTextureResident
;
618 driInitTextureFormats();