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_ioctl.h"
38 #include "r128_texobj.h"
40 #include "main/simple_list.h"
41 #include "main/enums.h"
42 #include "main/texstore.h"
43 #include "main/teximage.h"
44 #include "main/texobj.h"
45 #include "main/imports.h"
46 #include "main/texobj.h"
55 * Set the texture wrap modes. Currently \c GL_REPEAT, \c GL_CLAMP,
56 * \c GL_CLAMP_TO_EDGE, and \c GL_MIRRORED_REPEAT are supported.
58 * \param t Texture object whose wrap modes are to be set
59 * \param swrap Wrap mode for the \a s texture coordinate
60 * \param twrap Wrap mode for the \a t texture coordinate
62 static void r128SetTexWrap( r128TexObjPtr t
, GLenum swrap
, GLenum twrap
)
64 t
->setup
.tex_cntl
&= ~(R128_TEX_CLAMP_S_MASK
| R128_TEX_CLAMP_T_MASK
);
68 t
->setup
.tex_cntl
|= R128_TEX_CLAMP_S_BORDER_COLOR
;
70 case GL_CLAMP_TO_EDGE
:
71 t
->setup
.tex_cntl
|= R128_TEX_CLAMP_S_CLAMP
;
74 t
->setup
.tex_cntl
|= R128_TEX_CLAMP_S_WRAP
;
76 case GL_MIRRORED_REPEAT
:
77 t
->setup
.tex_cntl
|= R128_TEX_CLAMP_S_MIRROR
;
83 t
->setup
.tex_cntl
|= R128_TEX_CLAMP_T_BORDER_COLOR
;
85 case GL_CLAMP_TO_EDGE
:
86 t
->setup
.tex_cntl
|= R128_TEX_CLAMP_T_CLAMP
;
89 t
->setup
.tex_cntl
|= R128_TEX_CLAMP_T_WRAP
;
91 case GL_MIRRORED_REPEAT
:
92 t
->setup
.tex_cntl
|= R128_TEX_CLAMP_T_MIRROR
;
97 static void r128SetTexFilter( r128TexObjPtr t
, GLenum minf
, GLenum magf
)
99 t
->setup
.tex_cntl
&= ~(R128_MIN_BLEND_MASK
| R128_MAG_BLEND_MASK
);
103 t
->setup
.tex_cntl
|= R128_MIN_BLEND_NEAREST
;
106 t
->setup
.tex_cntl
|= R128_MIN_BLEND_LINEAR
;
108 case GL_NEAREST_MIPMAP_NEAREST
:
109 t
->setup
.tex_cntl
|= R128_MIN_BLEND_MIPNEAREST
;
111 case GL_LINEAR_MIPMAP_NEAREST
:
112 t
->setup
.tex_cntl
|= R128_MIN_BLEND_MIPLINEAR
;
114 case GL_NEAREST_MIPMAP_LINEAR
:
115 t
->setup
.tex_cntl
|= R128_MIN_BLEND_LINEARMIPNEAREST
;
117 case GL_LINEAR_MIPMAP_LINEAR
:
118 t
->setup
.tex_cntl
|= R128_MIN_BLEND_LINEARMIPLINEAR
;
124 t
->setup
.tex_cntl
|= R128_MAG_BLEND_NEAREST
;
127 t
->setup
.tex_cntl
|= R128_MAG_BLEND_LINEAR
;
132 static void r128SetTexBorderColor( r128TexObjPtr t
, const GLfloat color
[4] )
135 CLAMPED_FLOAT_TO_UBYTE(c
[0], color
[0]);
136 CLAMPED_FLOAT_TO_UBYTE(c
[1], color
[1]);
137 CLAMPED_FLOAT_TO_UBYTE(c
[2], color
[2]);
138 CLAMPED_FLOAT_TO_UBYTE(c
[3], color
[3]);
139 t
->setup
.tex_border_color
= r128PackColor( 4, c
[0], c
[1], c
[2], c
[3] );
143 static r128TexObjPtr
r128AllocTexObj( struct gl_texture_object
*texObj
)
147 if ( R128_DEBUG
& DEBUG_VERBOSE_API
) {
148 fprintf( stderr
, "%s( %p )\n", __FUNCTION__
, (void *) texObj
);
151 t
= (r128TexObjPtr
) CALLOC_STRUCT( r128_tex_obj
);
152 texObj
->DriverData
= t
;
155 /* Initialize non-image-dependent parts of the state:
157 t
->base
.tObj
= texObj
;
159 /* FIXME Something here to set initial values for other parts of
163 make_empty_list( (driTextureObject
*) t
);
165 r128SetTexWrap( t
, texObj
->WrapS
, texObj
->WrapT
);
166 r128SetTexFilter( t
, texObj
->MinFilter
, texObj
->MagFilter
);
167 r128SetTexBorderColor( t
, texObj
->BorderColor
.f
);
174 /* Called by the _mesa_store_teximage[123]d() functions. */
176 r128ChooseTextureFormat( GLcontext
*ctx
, GLint internalFormat
,
177 GLenum format
, GLenum type
)
179 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
180 const GLboolean do32bpt
=
181 ( rmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_32
);
182 const GLboolean force16bpt
=
183 ( rmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_FORCE_16
);
187 switch ( internalFormat
) {
188 /* non-sized formats with alpha */
190 case GL_COMPRESSED_INTENSITY
:
192 case GL_COMPRESSED_ALPHA
:
194 case GL_LUMINANCE_ALPHA
:
195 case GL_COMPRESSED_LUMINANCE_ALPHA
:
198 case GL_COMPRESSED_RGBA
:
200 return _dri_texformat_argb8888
;
202 return _dri_texformat_argb4444
;
204 /* 16-bit formats with alpha */
207 case GL_LUMINANCE4_ALPHA4
:
210 return _dri_texformat_argb4444
;
212 /* 32-bit formats with alpha */
219 case GL_LUMINANCE6_ALPHA2
:
220 case GL_LUMINANCE8_ALPHA8
:
221 case GL_LUMINANCE12_ALPHA4
:
222 case GL_LUMINANCE12_ALPHA12
:
223 case GL_LUMINANCE16_ALPHA16
:
230 return _dri_texformat_argb8888
;
232 return _dri_texformat_argb4444
;
234 /* non-sized formats without alpha */
237 case GL_COMPRESSED_LUMINANCE
:
240 case GL_COMPRESSED_RGB
:
242 return _dri_texformat_argb8888
;
244 return _dri_texformat_rgb565
;
246 /* 16-bit formats without alpha */
251 return _dri_texformat_rgb565
;
253 /* 32-bit formats without alpha */
262 return _dri_texformat_argb8888
;
264 return _dri_texformat_rgb565
;
266 /* color-indexed formats */
268 case GL_COLOR_INDEX1_EXT
:
269 case GL_COLOR_INDEX2_EXT
:
270 case GL_COLOR_INDEX4_EXT
:
271 case GL_COLOR_INDEX8_EXT
:
272 case GL_COLOR_INDEX12_EXT
:
273 case GL_COLOR_INDEX16_EXT
:
274 return _dri_texformat_ci8
;
277 if (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
278 type
== GL_UNSIGNED_BYTE
)
279 return MESA_FORMAT_YCBCR
;
281 return MESA_FORMAT_YCBCR_REV
;
284 _mesa_problem( ctx
, "unexpected format in %s", __FUNCTION__
);
285 return MESA_FORMAT_NONE
;
290 static void r128TexImage1D( GLcontext
*ctx
, GLenum target
, GLint level
,
291 GLint internalFormat
,
292 GLint width
, GLint border
,
293 GLenum format
, GLenum type
, const GLvoid
*pixels
,
294 const struct gl_pixelstore_attrib
*packing
,
295 struct gl_texture_object
*texObj
,
296 struct gl_texture_image
*texImage
)
298 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
301 driSwapOutTextureObject( t
);
304 t
= (driTextureObject
*) r128AllocTexObj(texObj
);
306 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
311 /* Note, this will call r128ChooseTextureFormat */
312 _mesa_store_teximage1d( ctx
, target
, level
, internalFormat
,
313 width
, border
, format
, type
,
314 pixels
, packing
, texObj
, texImage
);
316 t
->dirty_images
[0] |= (1 << level
);
320 static void r128TexSubImage1D( GLcontext
*ctx
,
325 GLenum format
, GLenum type
,
326 const GLvoid
*pixels
,
327 const struct gl_pixelstore_attrib
*packing
,
328 struct gl_texture_object
*texObj
,
329 struct gl_texture_image
*texImage
)
331 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
333 assert( t
); /* this _should_ be true */
335 driSwapOutTextureObject( t
);
338 t
= (driTextureObject
*) r128AllocTexObj(texObj
);
340 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
345 _mesa_store_texsubimage1d(ctx
, target
, level
, xoffset
, width
,
346 format
, type
, pixels
, packing
, texObj
,
349 t
->dirty_images
[0] |= (1 << level
);
353 static void r128TexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
354 GLint internalFormat
,
355 GLint width
, GLint height
, GLint border
,
356 GLenum format
, GLenum type
, const GLvoid
*pixels
,
357 const struct gl_pixelstore_attrib
*packing
,
358 struct gl_texture_object
*texObj
,
359 struct gl_texture_image
*texImage
)
361 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
364 driSwapOutTextureObject( (driTextureObject
*) t
);
367 t
= (driTextureObject
*) r128AllocTexObj(texObj
);
369 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
374 /* Note, this will call r128ChooseTextureFormat */
375 _mesa_store_teximage2d(ctx
, target
, level
, internalFormat
,
376 width
, height
, border
, format
, type
, pixels
,
377 &ctx
->Unpack
, texObj
, texImage
);
379 t
->dirty_images
[0] |= (1 << level
);
383 static void r128TexSubImage2D( GLcontext
*ctx
,
386 GLint xoffset
, GLint yoffset
,
387 GLsizei width
, GLsizei height
,
388 GLenum format
, GLenum type
,
389 const GLvoid
*pixels
,
390 const struct gl_pixelstore_attrib
*packing
,
391 struct gl_texture_object
*texObj
,
392 struct gl_texture_image
*texImage
)
394 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
396 assert( t
); /* this _should_ be true */
398 driSwapOutTextureObject( t
);
401 t
= (driTextureObject
*) r128AllocTexObj(texObj
);
403 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
408 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
409 height
, format
, type
, pixels
, packing
, texObj
,
411 t
->dirty_images
[0] |= (1 << level
);
415 static void r128TexEnv( GLcontext
*ctx
, GLenum target
,
416 GLenum pname
, const GLfloat
*param
)
418 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
419 struct gl_texture_unit
*texUnit
;
422 if ( R128_DEBUG
& DEBUG_VERBOSE_API
) {
423 fprintf( stderr
, "%s( %s )\n",
424 __FUNCTION__
, _mesa_lookup_enum_by_nr( pname
) );
428 case GL_TEXTURE_ENV_MODE
:
429 FLUSH_BATCH( rmesa
);
430 rmesa
->new_state
|= R128_NEW_ALPHA
;
433 case GL_TEXTURE_ENV_COLOR
:
434 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
435 CLAMPED_FLOAT_TO_UBYTE( c
[0], texUnit
->EnvColor
[0] );
436 CLAMPED_FLOAT_TO_UBYTE( c
[1], texUnit
->EnvColor
[1] );
437 CLAMPED_FLOAT_TO_UBYTE( c
[2], texUnit
->EnvColor
[2] );
438 CLAMPED_FLOAT_TO_UBYTE( c
[3], texUnit
->EnvColor
[3] );
439 rmesa
->env_color
= r128PackColor( 4, c
[0], c
[1], c
[2], c
[3] );
440 if ( rmesa
->setup
.constant_color_c
!= rmesa
->env_color
) {
441 FLUSH_BATCH( rmesa
);
442 rmesa
->setup
.constant_color_c
= rmesa
->env_color
;
444 /* More complex multitexture/multipass fallbacks for GL_BLEND
445 * can be done later, but this allows a single pass GL_BLEND
446 * in some cases (ie. Performer town demo). This is only
447 * applicable to the regular Rage 128, as the Pro and M3 can
448 * handle true single-pass GL_BLEND texturing.
450 rmesa
->blend_flags
&= ~R128_BLEND_ENV_COLOR
;
451 if ( R128_IS_PLAIN( rmesa
) &&
452 rmesa
->env_color
!= 0x00000000 &&
453 rmesa
->env_color
!= 0xff000000 &&
454 rmesa
->env_color
!= 0x00ffffff &&
455 rmesa
->env_color
!= 0xffffffff ) {
456 rmesa
->blend_flags
|= R128_BLEND_ENV_COLOR
;
461 case GL_TEXTURE_LOD_BIAS
:
463 uint32_t t
= rmesa
->setup
.tex_cntl_c
;
467 /* GTH: This isn't exactly correct, but gives good results up to a
468 * certain point. It is better than completely ignoring the LOD
469 * bias. Unfortunately there isn't much range in the bias, the
470 * spec mentions strides that vary between 0.5 and 2.0 but these
471 * numbers don't seem to relate the the GL LOD bias value at all.
473 if ( param
[0] >= 1.0 ) {
475 } else if ( param
[0] >= 0.5 ) {
477 } else if ( param
[0] >= 0.25 ) {
479 } else if ( param
[0] >= 0.0 ) {
485 b
= (uint32_t)bias
& 0xff;
486 t
&= ~R128_LOD_BIAS_MASK
;
487 t
|= (b
<< R128_LOD_BIAS_SHIFT
);
489 if ( rmesa
->setup
.tex_cntl_c
!= t
) {
490 FLUSH_BATCH( rmesa
);
491 rmesa
->setup
.tex_cntl_c
= t
;
492 rmesa
->dirty
|= R128_UPLOAD_CONTEXT
;
503 static void r128TexParameter( GLcontext
*ctx
, GLenum target
,
504 struct gl_texture_object
*tObj
,
505 GLenum pname
, const GLfloat
*params
)
507 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
508 r128TexObjPtr t
= (r128TexObjPtr
)tObj
->DriverData
;
510 if ( R128_DEBUG
& DEBUG_VERBOSE_API
) {
511 fprintf( stderr
, "%s( %s )\n",
512 __FUNCTION__
, _mesa_lookup_enum_by_nr( pname
) );
515 if ( ( target
!= GL_TEXTURE_2D
) && ( target
!= GL_TEXTURE_1D
) )
519 case GL_TEXTURE_MIN_FILTER
:
520 case GL_TEXTURE_MAG_FILTER
:
521 if ( t
->base
.bound
) FLUSH_BATCH( rmesa
);
522 r128SetTexFilter( t
, tObj
->MinFilter
, tObj
->MagFilter
);
525 case GL_TEXTURE_WRAP_S
:
526 case GL_TEXTURE_WRAP_T
:
527 if ( t
->base
.bound
) FLUSH_BATCH( rmesa
);
528 r128SetTexWrap( t
, tObj
->WrapS
, tObj
->WrapT
);
531 case GL_TEXTURE_BORDER_COLOR
:
532 if ( t
->base
.bound
) FLUSH_BATCH( rmesa
);
533 r128SetTexBorderColor( t
, tObj
->BorderColor
.f
);
536 case GL_TEXTURE_BASE_LEVEL
:
537 case GL_TEXTURE_MAX_LEVEL
:
538 case GL_TEXTURE_MIN_LOD
:
539 case GL_TEXTURE_MAX_LOD
:
540 /* This isn't the most efficient solution but there doesn't appear to
541 * be a nice alternative for R128. Since there's no LOD clamping,
542 * we just have to rely on loading the right subset of mipmap levels
543 * to simulate a clamped LOD.
545 if ( t
->base
.bound
) FLUSH_BATCH( rmesa
);
546 driSwapOutTextureObject( (driTextureObject
*) t
);
554 static void r128BindTexture( GLcontext
*ctx
, GLenum target
,
555 struct gl_texture_object
*tObj
)
557 if ( R128_DEBUG
& DEBUG_VERBOSE_API
) {
558 fprintf( stderr
, "%s( %p ) unit=%d\n", __FUNCTION__
, (void *) tObj
,
559 ctx
->Texture
.CurrentUnit
);
562 assert( (target
!= GL_TEXTURE_2D
&& target
!= GL_TEXTURE_1D
) ||
563 (tObj
->DriverData
!= NULL
) );
567 static void r128DeleteTexture( GLcontext
*ctx
,
568 struct gl_texture_object
*tObj
)
570 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
571 driTextureObject
* t
= (driTextureObject
*) tObj
->DriverData
;
574 if ( t
->bound
&& rmesa
) {
575 FLUSH_BATCH( rmesa
);
578 driDestroyTextureObject( t
);
580 /* Free mipmap images and the texture object itself */
581 _mesa_delete_texture_object(ctx
, tObj
);
585 * Allocate a new texture object.
586 * Called via ctx->Driver.NewTextureObject.
587 * Note: we could use containment here to 'derive' the driver-specific
588 * texture object from the core mesa gl_texture_object. Not done at this time.
590 static struct gl_texture_object
*
591 r128NewTextureObject( GLcontext
*ctx
, GLuint name
, GLenum target
)
593 struct gl_texture_object
*obj
;
594 obj
= _mesa_new_texture_object(ctx
, name
, target
);
595 r128AllocTexObj( obj
);
599 void r128InitTextureFuncs( struct dd_function_table
*functions
)
601 functions
->TexEnv
= r128TexEnv
;
602 functions
->ChooseTextureFormat
= r128ChooseTextureFormat
;
603 functions
->TexImage1D
= r128TexImage1D
;
604 functions
->TexSubImage1D
= r128TexSubImage1D
;
605 functions
->TexImage2D
= r128TexImage2D
;
606 functions
->TexSubImage2D
= r128TexSubImage2D
;
607 functions
->TexParameter
= r128TexParameter
;
608 functions
->BindTexture
= r128BindTexture
;
609 functions
->NewTextureObject
= r128NewTextureObject
;
610 functions
->DeleteTexture
= r128DeleteTexture
;
611 functions
->IsTextureResident
= driIsTextureResident
;
613 driInitTextureFormats();