2 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
4 The Weather Channel (TM) funded Tungsten Graphics to develop the
5 initial release of the Radeon 8500 driver under the XFree86 license.
6 This notice must be preserved.
8 Permission is hereby granted, free of charge, to any person obtaining
9 a copy of this software and associated documentation files (the
10 "Software"), to deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sublicense, and/or sell copies of the Software, and to
13 permit persons to whom the Software is furnished to do so, subject to
14 the following conditions:
16 The above copyright notice and this permission notice (including the
17 next paragraph) shall be included in all copies or substantial
18 portions of the Software.
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
24 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 * Keith Whitwell <keith@tungstengraphics.com>
40 #include "simple_list.h"
41 #include "texformat.h"
47 #include "r200_context.h"
48 #include "r200_state.h"
49 #include "r200_ioctl.h"
50 #include "r200_swtcl.h"
58 * Set the texture wrap modes.
60 * \param t Texture object whose wrap modes are to be set
61 * \param swrap Wrap mode for the \a s texture coordinate
62 * \param twrap Wrap mode for the \a t texture coordinate
65 static void r200SetTexWrap( r200TexObjPtr t
, GLenum swrap
, GLenum twrap
, GLenum rwrap
)
67 GLboolean is_clamp
= GL_FALSE
;
68 GLboolean is_clamp_to_border
= GL_FALSE
;
70 t
->pp_txfilter
&= ~(R200_CLAMP_S_MASK
| R200_CLAMP_T_MASK
| R200_BORDER_MODE_D3D
);
74 t
->pp_txfilter
|= R200_CLAMP_S_WRAP
;
77 t
->pp_txfilter
|= R200_CLAMP_S_CLAMP_GL
;
80 case GL_CLAMP_TO_EDGE
:
81 t
->pp_txfilter
|= R200_CLAMP_S_CLAMP_LAST
;
83 case GL_CLAMP_TO_BORDER
:
84 t
->pp_txfilter
|= R200_CLAMP_S_CLAMP_GL
;
85 is_clamp_to_border
= GL_TRUE
;
87 case GL_MIRRORED_REPEAT
:
88 t
->pp_txfilter
|= R200_CLAMP_S_MIRROR
;
90 case GL_MIRROR_CLAMP_EXT
:
91 t
->pp_txfilter
|= R200_CLAMP_S_MIRROR_CLAMP_GL
;
94 case GL_MIRROR_CLAMP_TO_EDGE_EXT
:
95 t
->pp_txfilter
|= R200_CLAMP_S_MIRROR_CLAMP_LAST
;
97 case GL_MIRROR_CLAMP_TO_BORDER_EXT
:
98 t
->pp_txfilter
|= R200_CLAMP_S_MIRROR_CLAMP_GL
;
99 is_clamp_to_border
= GL_TRUE
;
102 _mesa_problem(NULL
, "bad S wrap mode in %s", __FUNCTION__
);
105 if (t
->base
.tObj
->Target
!= GL_TEXTURE_1D
) {
108 t
->pp_txfilter
|= R200_CLAMP_T_WRAP
;
111 t
->pp_txfilter
|= R200_CLAMP_T_CLAMP_GL
;
114 case GL_CLAMP_TO_EDGE
:
115 t
->pp_txfilter
|= R200_CLAMP_T_CLAMP_LAST
;
117 case GL_CLAMP_TO_BORDER
:
118 t
->pp_txfilter
|= R200_CLAMP_T_CLAMP_GL
;
119 is_clamp_to_border
= GL_TRUE
;
121 case GL_MIRRORED_REPEAT
:
122 t
->pp_txfilter
|= R200_CLAMP_T_MIRROR
;
124 case GL_MIRROR_CLAMP_EXT
:
125 t
->pp_txfilter
|= R200_CLAMP_T_MIRROR_CLAMP_GL
;
128 case GL_MIRROR_CLAMP_TO_EDGE_EXT
:
129 t
->pp_txfilter
|= R200_CLAMP_T_MIRROR_CLAMP_LAST
;
131 case GL_MIRROR_CLAMP_TO_BORDER_EXT
:
132 t
->pp_txfilter
|= R200_CLAMP_T_MIRROR_CLAMP_GL
;
133 is_clamp_to_border
= GL_TRUE
;
136 _mesa_problem(NULL
, "bad T wrap mode in %s", __FUNCTION__
);
140 t
->pp_txformat_x
&= ~R200_CLAMP_Q_MASK
;
144 t
->pp_txformat_x
|= R200_CLAMP_Q_WRAP
;
147 t
->pp_txformat_x
|= R200_CLAMP_Q_CLAMP_GL
;
150 case GL_CLAMP_TO_EDGE
:
151 t
->pp_txformat_x
|= R200_CLAMP_Q_CLAMP_LAST
;
153 case GL_CLAMP_TO_BORDER
:
154 t
->pp_txformat_x
|= R200_CLAMP_Q_CLAMP_GL
;
155 is_clamp_to_border
= GL_TRUE
;
157 case GL_MIRRORED_REPEAT
:
158 t
->pp_txformat_x
|= R200_CLAMP_Q_MIRROR
;
160 case GL_MIRROR_CLAMP_EXT
:
161 t
->pp_txformat_x
|= R200_CLAMP_Q_MIRROR_CLAMP_GL
;
164 case GL_MIRROR_CLAMP_TO_EDGE_EXT
:
165 t
->pp_txformat_x
|= R200_CLAMP_Q_MIRROR_CLAMP_LAST
;
167 case GL_MIRROR_CLAMP_TO_BORDER_EXT
:
168 t
->pp_txformat_x
|= R200_CLAMP_Q_MIRROR_CLAMP_GL
;
169 is_clamp_to_border
= GL_TRUE
;
172 _mesa_problem(NULL
, "bad R wrap mode in %s", __FUNCTION__
);
175 if ( is_clamp_to_border
) {
176 t
->pp_txfilter
|= R200_BORDER_MODE_D3D
;
179 t
->border_fallback
= (is_clamp
&& is_clamp_to_border
);
182 static void r200SetTexMaxAnisotropy( r200TexObjPtr t
, GLfloat max
)
184 t
->pp_txfilter
&= ~R200_MAX_ANISO_MASK
;
187 t
->pp_txfilter
|= R200_MAX_ANISO_1_TO_1
;
188 } else if ( max
<= 2.0 ) {
189 t
->pp_txfilter
|= R200_MAX_ANISO_2_TO_1
;
190 } else if ( max
<= 4.0 ) {
191 t
->pp_txfilter
|= R200_MAX_ANISO_4_TO_1
;
192 } else if ( max
<= 8.0 ) {
193 t
->pp_txfilter
|= R200_MAX_ANISO_8_TO_1
;
195 t
->pp_txfilter
|= R200_MAX_ANISO_16_TO_1
;
200 * Set the texture magnification and minification modes.
202 * \param t Texture whose filter modes are to be set
203 * \param minf Texture minification mode
204 * \param magf Texture magnification mode
207 static void r200SetTexFilter( r200TexObjPtr t
, GLenum minf
, GLenum magf
)
209 GLuint anisotropy
= (t
->pp_txfilter
& R200_MAX_ANISO_MASK
);
211 t
->pp_txfilter
&= ~(R200_MIN_FILTER_MASK
| R200_MAG_FILTER_MASK
);
212 t
->pp_txformat_x
&= ~R200_VOLUME_FILTER_MASK
;
214 if ( anisotropy
== R200_MAX_ANISO_1_TO_1
) {
217 t
->pp_txfilter
|= R200_MIN_FILTER_NEAREST
;
220 t
->pp_txfilter
|= R200_MIN_FILTER_LINEAR
;
222 case GL_NEAREST_MIPMAP_NEAREST
:
223 t
->pp_txfilter
|= R200_MIN_FILTER_NEAREST_MIP_NEAREST
;
225 case GL_NEAREST_MIPMAP_LINEAR
:
226 t
->pp_txfilter
|= R200_MIN_FILTER_LINEAR_MIP_NEAREST
;
228 case GL_LINEAR_MIPMAP_NEAREST
:
229 t
->pp_txfilter
|= R200_MIN_FILTER_NEAREST_MIP_LINEAR
;
231 case GL_LINEAR_MIPMAP_LINEAR
:
232 t
->pp_txfilter
|= R200_MIN_FILTER_LINEAR_MIP_LINEAR
;
238 t
->pp_txfilter
|= R200_MIN_FILTER_ANISO_NEAREST
;
241 t
->pp_txfilter
|= R200_MIN_FILTER_ANISO_LINEAR
;
243 case GL_NEAREST_MIPMAP_NEAREST
:
244 case GL_LINEAR_MIPMAP_NEAREST
:
245 t
->pp_txfilter
|= R200_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST
;
247 case GL_NEAREST_MIPMAP_LINEAR
:
248 case GL_LINEAR_MIPMAP_LINEAR
:
249 t
->pp_txfilter
|= R200_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR
;
254 /* Note we don't have 3D mipmaps so only use the mag filter setting
255 * to set the 3D texture filter mode.
259 t
->pp_txfilter
|= R200_MAG_FILTER_NEAREST
;
260 t
->pp_txformat_x
|= R200_VOLUME_FILTER_NEAREST
;
263 t
->pp_txfilter
|= R200_MAG_FILTER_LINEAR
;
264 t
->pp_txformat_x
|= R200_VOLUME_FILTER_LINEAR
;
269 static void r200SetTexBorderColor( r200TexObjPtr t
, GLubyte c
[4] )
271 t
->pp_border_color
= r200PackColor( 4, c
[0], c
[1], c
[2], c
[3] );
276 * Allocate space for and load the mesa images into the texture memory block.
277 * This will happen before drawing with a new texture, or drawing with a
278 * texture after it was swapped out or teximaged again.
281 static r200TexObjPtr
r200AllocTexObj( struct gl_texture_object
*texObj
)
285 t
= CALLOC_STRUCT( r200_tex_obj
);
286 texObj
->DriverData
= t
;
288 if ( R200_DEBUG
& DEBUG_TEXTURE
) {
289 fprintf( stderr
, "%s( %p, %p )\n", __FUNCTION__
, (void *)texObj
,
293 /* Initialize non-image-dependent parts of the state:
295 t
->base
.tObj
= texObj
;
296 t
->border_fallback
= GL_FALSE
;
298 make_empty_list( & t
->base
);
300 r200SetTexWrap( t
, texObj
->WrapS
, texObj
->WrapT
, texObj
->WrapR
);
301 r200SetTexMaxAnisotropy( t
, texObj
->MaxAnisotropy
);
302 r200SetTexFilter( t
, texObj
->MinFilter
, texObj
->MagFilter
);
303 r200SetTexBorderColor( t
, texObj
->_BorderChan
);
309 /* try to find a format which will only need a memcopy */
310 static const struct gl_texture_format
*
311 r200Choose8888TexFormat( GLenum srcFormat
, GLenum srcType
)
314 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
316 if ((srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8
) ||
317 (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
) ||
318 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) ||
319 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_BYTE
&& littleEndian
)) {
320 return &_mesa_texformat_rgba8888
;
322 else if ((srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) ||
323 (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
&& littleEndian
) ||
324 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_INT_8_8_8_8
) ||
325 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
)) {
326 return &_mesa_texformat_rgba8888_rev
;
328 else return _dri_texformat_argb8888
;
331 static const struct gl_texture_format
*
332 r200ChooseTextureFormat( GLcontext
*ctx
, GLint internalFormat
,
333 GLenum format
, GLenum type
)
335 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
336 const GLboolean do32bpt
=
337 ( rmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_32
);
338 const GLboolean force16bpt
=
339 ( rmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_FORCE_16
);
342 switch ( internalFormat
) {
345 case GL_COMPRESSED_RGBA
:
347 case GL_UNSIGNED_INT_10_10_10_2
:
348 case GL_UNSIGNED_INT_2_10_10_10_REV
:
349 return do32bpt
? _dri_texformat_argb8888
: _dri_texformat_argb1555
;
350 case GL_UNSIGNED_SHORT_4_4_4_4
:
351 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
352 return _dri_texformat_argb4444
;
353 case GL_UNSIGNED_SHORT_5_5_5_1
:
354 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
355 return _dri_texformat_argb1555
;
358 r200Choose8888TexFormat(format
, type
) : _dri_texformat_argb4444
;
363 case GL_COMPRESSED_RGB
:
365 case GL_UNSIGNED_SHORT_4_4_4_4
:
366 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
367 return _dri_texformat_argb4444
;
368 case GL_UNSIGNED_SHORT_5_5_5_1
:
369 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
370 return _dri_texformat_argb1555
;
371 case GL_UNSIGNED_SHORT_5_6_5
:
372 case GL_UNSIGNED_SHORT_5_6_5_REV
:
373 return _dri_texformat_rgb565
;
375 return do32bpt
? _dri_texformat_argb8888
: _dri_texformat_rgb565
;
383 r200Choose8888TexFormat(format
, type
) : _dri_texformat_argb4444
;
387 return _dri_texformat_argb4444
;
390 return _dri_texformat_argb1555
;
396 return !force16bpt
? _dri_texformat_argb8888
: _dri_texformat_rgb565
;
401 return _dri_texformat_rgb565
;
408 case GL_COMPRESSED_ALPHA
:
409 /* can't use a8 format since interpreting hw I8 as a8 would result
410 in wrong rgb values (same as alpha value instead of 0). */
411 return _dri_texformat_al88
;
419 case GL_COMPRESSED_LUMINANCE
:
420 return _dri_texformat_l8
;
423 case GL_LUMINANCE_ALPHA
:
424 case GL_LUMINANCE4_ALPHA4
:
425 case GL_LUMINANCE6_ALPHA2
:
426 case GL_LUMINANCE8_ALPHA8
:
427 case GL_LUMINANCE12_ALPHA4
:
428 case GL_LUMINANCE12_ALPHA12
:
429 case GL_LUMINANCE16_ALPHA16
:
430 case GL_COMPRESSED_LUMINANCE_ALPHA
:
431 return _dri_texformat_al88
;
438 case GL_COMPRESSED_INTENSITY
:
439 return _dri_texformat_i8
;
442 if (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
443 type
== GL_UNSIGNED_BYTE
)
444 return &_mesa_texformat_ycbcr
;
446 return &_mesa_texformat_ycbcr_rev
;
450 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
451 return &_mesa_texformat_rgb_dxt1
;
453 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
454 return &_mesa_texformat_rgba_dxt1
;
458 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
459 return &_mesa_texformat_rgba_dxt3
;
461 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
462 return &_mesa_texformat_rgba_dxt5
;
466 "unexpected internalFormat 0x%x in r200ChooseTextureFormat",
467 (int) internalFormat
);
471 return NULL
; /* never get here */
476 r200ValidateClientStorage( GLcontext
*ctx
, GLenum target
,
477 GLint internalFormat
,
478 GLint srcWidth
, GLint srcHeight
,
479 GLenum format
, GLenum type
, const void *pixels
,
480 const struct gl_pixelstore_attrib
*packing
,
481 struct gl_texture_object
*texObj
,
482 struct gl_texture_image
*texImage
)
485 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
487 if ( R200_DEBUG
& DEBUG_TEXTURE
)
488 fprintf(stderr
, "intformat %s format %s type %s\n",
489 _mesa_lookup_enum_by_nr( internalFormat
),
490 _mesa_lookup_enum_by_nr( format
),
491 _mesa_lookup_enum_by_nr( type
));
493 if (!ctx
->Unpack
.ClientStorage
)
496 if (ctx
->_ImageTransferState
||
497 texImage
->IsCompressed
||
498 texObj
->GenerateMipmap
)
502 /* This list is incomplete, may be different on ppc???
504 switch ( internalFormat
) {
506 if ( format
== GL_BGRA
&& type
== GL_UNSIGNED_INT_8_8_8_8_REV
) {
507 texImage
->TexFormat
= _dri_texformat_argb8888
;
514 if ( format
== GL_RGB
&& type
== GL_UNSIGNED_SHORT_5_6_5
) {
515 texImage
->TexFormat
= _dri_texformat_rgb565
;
522 if ( format
== GL_YCBCR_MESA
&&
523 type
== GL_UNSIGNED_SHORT_8_8_REV_APPLE
) {
524 texImage
->TexFormat
= &_mesa_texformat_ycbcr_rev
;
526 else if ( format
== GL_YCBCR_MESA
&&
527 (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
528 type
== GL_UNSIGNED_BYTE
)) {
529 texImage
->TexFormat
= &_mesa_texformat_ycbcr
;
539 /* Could deal with these packing issues, but currently don't:
541 if (packing
->SkipPixels
||
543 packing
->SwapBytes
||
549 GLint srcRowStride
= _mesa_image_row_stride(packing
, srcWidth
,
553 if ( R200_DEBUG
& DEBUG_TEXTURE
)
554 fprintf(stderr
, "%s: srcRowStride %d/%x\n",
555 __FUNCTION__
, srcRowStride
, srcRowStride
);
557 /* Could check this later in upload, pitch restrictions could be
558 * relaxed, but would need to store the image pitch somewhere,
559 * as packing details might change before image is uploaded:
561 if (!r200IsGartMemory( rmesa
, pixels
, srcHeight
* srcRowStride
) ||
566 /* Have validated that _mesa_transfer_teximage would be a straight
567 * memcpy at this point. NOTE: future calls to TexSubImage will
568 * overwrite the client data. This is explicitly mentioned in the
571 texImage
->Data
= (void *)pixels
;
572 texImage
->IsClientData
= GL_TRUE
;
573 texImage
->RowStride
= srcRowStride
/ texImage
->TexFormat
->TexelBytes
;
580 static void r200TexImage1D( GLcontext
*ctx
, GLenum target
, GLint level
,
581 GLint internalFormat
,
582 GLint width
, GLint border
,
583 GLenum format
, GLenum type
, const GLvoid
*pixels
,
584 const struct gl_pixelstore_attrib
*packing
,
585 struct gl_texture_object
*texObj
,
586 struct gl_texture_image
*texImage
)
588 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
591 driSwapOutTextureObject( t
);
594 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
596 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
601 /* Note, this will call ChooseTextureFormat */
602 _mesa_store_teximage1d(ctx
, target
, level
, internalFormat
,
603 width
, border
, format
, type
, pixels
,
604 &ctx
->Unpack
, texObj
, texImage
);
606 t
->dirty_images
[0] |= (1 << level
);
610 static void r200TexSubImage1D( GLcontext
*ctx
, GLenum target
, GLint level
,
613 GLenum format
, GLenum type
,
614 const GLvoid
*pixels
,
615 const struct gl_pixelstore_attrib
*packing
,
616 struct gl_texture_object
*texObj
,
617 struct gl_texture_image
*texImage
)
619 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
621 assert( t
); /* this _should_ be true */
623 driSwapOutTextureObject( t
);
626 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
628 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
633 _mesa_store_texsubimage1d(ctx
, target
, level
, xoffset
, width
,
634 format
, type
, pixels
, packing
, texObj
,
637 t
->dirty_images
[0] |= (1 << level
);
641 static void r200TexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
642 GLint internalFormat
,
643 GLint width
, GLint height
, GLint border
,
644 GLenum format
, GLenum type
, const GLvoid
*pixels
,
645 const struct gl_pixelstore_attrib
*packing
,
646 struct gl_texture_object
*texObj
,
647 struct gl_texture_image
*texImage
)
649 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
652 /* which cube face or ordinary 2D image */
654 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
655 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
656 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
657 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
658 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
659 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
660 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
668 driSwapOutTextureObject( t
);
671 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
673 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
678 texImage
->IsClientData
= GL_FALSE
;
680 if (r200ValidateClientStorage( ctx
, target
,
683 format
, type
, pixels
,
684 packing
, texObj
, texImage
)) {
685 if (R200_DEBUG
& DEBUG_TEXTURE
)
686 fprintf(stderr
, "%s: Using client storage\n", __FUNCTION__
);
689 if (R200_DEBUG
& DEBUG_TEXTURE
)
690 fprintf(stderr
, "%s: Using normal storage\n", __FUNCTION__
);
692 /* Normal path: copy (to cached memory) and eventually upload
693 * via another copy to GART memory and then a blit... Could
694 * eliminate one copy by going straight to (permanent) GART.
696 * Note, this will call r200ChooseTextureFormat.
698 _mesa_store_teximage2d(ctx
, target
, level
, internalFormat
,
699 width
, height
, border
, format
, type
, pixels
,
700 &ctx
->Unpack
, texObj
, texImage
);
702 t
->dirty_images
[face
] |= (1 << level
);
707 static void r200TexSubImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
708 GLint xoffset
, GLint yoffset
,
709 GLsizei width
, GLsizei height
,
710 GLenum format
, GLenum type
,
711 const GLvoid
*pixels
,
712 const struct gl_pixelstore_attrib
*packing
,
713 struct gl_texture_object
*texObj
,
714 struct gl_texture_image
*texImage
)
716 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
719 /* which cube face or ordinary 2D image */
721 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
722 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
723 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
724 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
725 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
726 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
727 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
734 assert( t
); /* this _should_ be true */
736 driSwapOutTextureObject( t
);
739 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
741 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
746 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
747 height
, format
, type
, pixels
, packing
, texObj
,
750 t
->dirty_images
[face
] |= (1 << level
);
754 static void r200CompressedTexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
755 GLint internalFormat
,
756 GLint width
, GLint height
, GLint border
,
757 GLsizei imageSize
, const GLvoid
*data
,
758 struct gl_texture_object
*texObj
,
759 struct gl_texture_image
*texImage
)
761 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
764 /* which cube face or ordinary 2D image */
766 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
767 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
768 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
769 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
770 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
771 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
772 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
780 driSwapOutTextureObject( t
);
783 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
785 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2D");
790 texImage
->IsClientData
= GL_FALSE
;
791 /* can't call this, different parameters. Would never evaluate to true anyway currently
792 if (r200ValidateClientStorage( ctx, target,
795 format, type, pixels,
796 packing, texObj, texImage)) {
797 if (R200_DEBUG & DEBUG_TEXTURE)
798 fprintf(stderr, "%s: Using client storage\n", __FUNCTION__);
801 if (R200_DEBUG
& DEBUG_TEXTURE
)
802 fprintf(stderr
, "%s: Using normal storage\n", __FUNCTION__
);
804 /* Normal path: copy (to cached memory) and eventually upload
805 * via another copy to GART memory and then a blit... Could
806 * eliminate one copy by going straight to (permanent) GART.
808 * Note, this will call r200ChooseTextureFormat.
810 _mesa_store_compressed_teximage2d(ctx
, target
, level
, internalFormat
, width
,
811 height
, border
, imageSize
, data
, texObj
, texImage
);
813 t
->dirty_images
[face
] |= (1 << level
);
818 static void r200CompressedTexSubImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
819 GLint xoffset
, GLint yoffset
,
820 GLsizei width
, GLsizei height
,
822 GLsizei imageSize
, const GLvoid
*data
,
823 struct gl_texture_object
*texObj
,
824 struct gl_texture_image
*texImage
)
826 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
830 /* which cube face or ordinary 2D image */
832 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
833 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
834 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
835 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
836 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
837 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
838 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
845 assert( t
); /* this _should_ be true */
847 driSwapOutTextureObject( t
);
850 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
852 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexSubImage2D");
857 _mesa_store_compressed_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
858 height
, format
, imageSize
, data
, texObj
, texImage
);
860 t
->dirty_images
[face
] |= (1 << level
);
864 #if ENABLE_HW_3D_TEXTURE
865 static void r200TexImage3D( GLcontext
*ctx
, GLenum target
, GLint level
,
866 GLint internalFormat
,
867 GLint width
, GLint height
, GLint depth
,
869 GLenum format
, GLenum type
, const GLvoid
*pixels
,
870 const struct gl_pixelstore_attrib
*packing
,
871 struct gl_texture_object
*texObj
,
872 struct gl_texture_image
*texImage
)
874 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
877 driSwapOutTextureObject( t
);
880 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
882 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
887 texImage
->IsClientData
= GL_FALSE
;
890 if (r200ValidateClientStorage( ctx
, target
,
893 format
, type
, pixels
,
894 packing
, texObj
, texImage
)) {
895 if (R200_DEBUG
& DEBUG_TEXTURE
)
896 fprintf(stderr
, "%s: Using client storage\n", __FUNCTION__
);
901 if (R200_DEBUG
& DEBUG_TEXTURE
)
902 fprintf(stderr
, "%s: Using normal storage\n", __FUNCTION__
);
904 /* Normal path: copy (to cached memory) and eventually upload
905 * via another copy to GART memory and then a blit... Could
906 * eliminate one copy by going straight to (permanent) GART.
908 * Note, this will call r200ChooseTextureFormat.
910 _mesa_store_teximage3d(ctx
, target
, level
, internalFormat
,
911 width
, height
, depth
, border
,
912 format
, type
, pixels
,
913 &ctx
->Unpack
, texObj
, texImage
);
915 t
->dirty_images
[0] |= (1 << level
);
921 #if ENABLE_HW_3D_TEXTURE
923 r200TexSubImage3D( GLcontext
*ctx
, GLenum target
, GLint level
,
924 GLint xoffset
, GLint yoffset
, GLint zoffset
,
925 GLsizei width
, GLsizei height
, GLsizei depth
,
926 GLenum format
, GLenum type
,
927 const GLvoid
*pixels
,
928 const struct gl_pixelstore_attrib
*packing
,
929 struct gl_texture_object
*texObj
,
930 struct gl_texture_image
*texImage
)
932 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
934 /* fprintf(stderr, "%s\n", __FUNCTION__); */
936 assert( t
); /* this _should_ be true */
938 driSwapOutTextureObject( t
);
941 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
943 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage3D");
946 texObj
->DriverData
= t
;
949 _mesa_store_texsubimage3d(ctx
, target
, level
, xoffset
, yoffset
, zoffset
,
950 width
, height
, depth
,
951 format
, type
, pixels
, packing
, texObj
, texImage
);
953 t
->dirty_images
[0] |= (1 << level
);
959 static void r200TexEnv( GLcontext
*ctx
, GLenum target
,
960 GLenum pname
, const GLfloat
*param
)
962 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
963 GLuint unit
= ctx
->Texture
.CurrentUnit
;
964 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
966 if ( R200_DEBUG
& DEBUG_STATE
) {
967 fprintf( stderr
, "%s( %s )\n",
968 __FUNCTION__
, _mesa_lookup_enum_by_nr( pname
) );
971 /* This is incorrect: Need to maintain this data for each of
972 * GL_TEXTURE_{123}D, GL_TEXTURE_RECTANGLE_NV, etc, and switch
973 * between them according to _ReallyEnabled.
976 case GL_TEXTURE_ENV_COLOR
: {
979 UNCLAMPED_FLOAT_TO_RGBA_CHAN( c
, texUnit
->EnvColor
);
980 envColor
= r200PackColor( 4, c
[0], c
[1], c
[2], c
[3] );
981 if ( rmesa
->hw
.tf
.cmd
[TF_TFACTOR_0
+ unit
] != envColor
) {
982 R200_STATECHANGE( rmesa
, tf
);
983 rmesa
->hw
.tf
.cmd
[TF_TFACTOR_0
+ unit
] = envColor
;
988 case GL_TEXTURE_LOD_BIAS_EXT
: {
991 const int fixed_one
= 0x8000000;
993 /* The R200's LOD bias is a signed 2's complement value with a
994 * range of -16.0 <= bias < 16.0.
996 * NOTE: Add a small bias to the bias for conform mipsel.c test.
999 min
= driQueryOptionb (&rmesa
->optionCache
, "no_neg_lod_bias") ?
1001 bias
= CLAMP( bias
, min
, 16.0 );
1002 b
= (int)(bias
* fixed_one
) & R200_LOD_BIAS_MASK
;
1004 if ( (rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT_X
] & R200_LOD_BIAS_MASK
) != b
) {
1005 R200_STATECHANGE( rmesa
, tex
[unit
] );
1006 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT_X
] &= ~R200_LOD_BIAS_MASK
;
1007 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT_X
] |= b
;
1011 case GL_COORD_REPLACE_ARB
:
1012 if (ctx
->Point
.PointSprite
) {
1013 R200_STATECHANGE( rmesa
, spr
);
1014 if ((GLenum
)param
[0]) {
1015 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |= R200_PS_GEN_TEX_0
<< unit
;
1017 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] &= ~(R200_PS_GEN_TEX_0
<< unit
);
1028 * Changes variables and flags for a state update, which will happen at the
1029 * next UpdateTextureState
1032 static void r200TexParameter( GLcontext
*ctx
, GLenum target
,
1033 struct gl_texture_object
*texObj
,
1034 GLenum pname
, const GLfloat
*params
)
1036 r200TexObjPtr t
= (r200TexObjPtr
) texObj
->DriverData
;
1038 if ( R200_DEBUG
& (DEBUG_STATE
|DEBUG_TEXTURE
) ) {
1039 fprintf( stderr
, "%s( %s )\n", __FUNCTION__
,
1040 _mesa_lookup_enum_by_nr( pname
) );
1044 case GL_TEXTURE_MIN_FILTER
:
1045 case GL_TEXTURE_MAG_FILTER
:
1046 case GL_TEXTURE_MAX_ANISOTROPY_EXT
:
1047 r200SetTexMaxAnisotropy( t
, texObj
->MaxAnisotropy
);
1048 r200SetTexFilter( t
, texObj
->MinFilter
, texObj
->MagFilter
);
1051 case GL_TEXTURE_WRAP_S
:
1052 case GL_TEXTURE_WRAP_T
:
1053 case GL_TEXTURE_WRAP_R
:
1054 r200SetTexWrap( t
, texObj
->WrapS
, texObj
->WrapT
, texObj
->WrapR
);
1057 case GL_TEXTURE_BORDER_COLOR
:
1058 r200SetTexBorderColor( t
, texObj
->_BorderChan
);
1061 case GL_TEXTURE_BASE_LEVEL
:
1062 case GL_TEXTURE_MAX_LEVEL
:
1063 case GL_TEXTURE_MIN_LOD
:
1064 case GL_TEXTURE_MAX_LOD
:
1065 /* This isn't the most efficient solution but there doesn't appear to
1066 * be a nice alternative. Since there's no LOD clamping,
1067 * we just have to rely on loading the right subset of mipmap levels
1068 * to simulate a clamped LOD.
1070 driSwapOutTextureObject( (driTextureObject
*) t
);
1077 /* Mark this texobj as dirty (one bit per tex unit)
1079 t
->dirty_state
= TEX_ALL
;
1084 static void r200BindTexture( GLcontext
*ctx
, GLenum target
,
1085 struct gl_texture_object
*texObj
)
1087 if ( R200_DEBUG
& (DEBUG_STATE
|DEBUG_TEXTURE
) ) {
1088 fprintf( stderr
, "%s( %p ) unit=%d\n", __FUNCTION__
, (void *)texObj
,
1089 ctx
->Texture
.CurrentUnit
);
1092 if ( (target
== GL_TEXTURE_1D
)
1093 || (target
== GL_TEXTURE_2D
)
1094 #if ENABLE_HW_3D_TEXTURE
1095 || (target
== GL_TEXTURE_3D
)
1097 || (target
== GL_TEXTURE_CUBE_MAP
)
1098 || (target
== GL_TEXTURE_RECTANGLE_NV
) ) {
1099 assert( texObj
->DriverData
!= NULL
);
1104 static void r200DeleteTexture( GLcontext
*ctx
,
1105 struct gl_texture_object
*texObj
)
1107 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1108 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
1110 if ( R200_DEBUG
& (DEBUG_STATE
|DEBUG_TEXTURE
) ) {
1111 fprintf( stderr
, "%s( %p (target = %s) )\n", __FUNCTION__
, (void *)texObj
,
1112 _mesa_lookup_enum_by_nr( texObj
->Target
) );
1117 R200_FIREVERTICES( rmesa
);
1120 driDestroyTextureObject( t
);
1122 /* Free mipmap images and the texture object itself */
1123 _mesa_delete_texture_object(ctx
, texObj
);
1127 * - Same GEN_MODE for all active bits
1128 * - Same EyePlane/ObjPlane for all active bits when using Eye/Obj
1129 * - STRQ presumably all supported (matrix means incoming R values
1130 * can end up in STQ, this has implications for vertex support,
1131 * presumably ok if maos is used, though?)
1133 * Basically impossible to do this on the fly - just collect some
1134 * basic info & do the checks from ValidateState().
1136 static void r200TexGen( GLcontext
*ctx
,
1139 const GLfloat
*params
)
1141 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1142 GLuint unit
= ctx
->Texture
.CurrentUnit
;
1143 rmesa
->recheck_texgen
[unit
] = GL_TRUE
;
1148 * Allocate a new texture object.
1149 * Called via ctx->Driver.NewTextureObject.
1150 * Note: this function will be called during context creation to
1151 * allocate the default texture objects.
1152 * Note: we could use containment here to 'derive' the driver-specific
1153 * texture object from the core mesa gl_texture_object. Not done at this time.
1154 * Fixup MaxAnisotropy according to user preference.
1156 static struct gl_texture_object
*
1157 r200NewTextureObject( GLcontext
*ctx
, GLuint name
, GLenum target
)
1159 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1160 struct gl_texture_object
*obj
;
1161 obj
= _mesa_new_texture_object(ctx
, name
, target
);
1164 obj
->MaxAnisotropy
= rmesa
->initialMaxAnisotropy
;
1165 r200AllocTexObj( obj
);
1170 void r200InitTextureFuncs( struct dd_function_table
*functions
)
1172 /* Note: we only plug in the functions we implement in the driver
1173 * since _mesa_init_driver_functions() was already called.
1175 functions
->ChooseTextureFormat
= r200ChooseTextureFormat
;
1176 functions
->TexImage1D
= r200TexImage1D
;
1177 functions
->TexImage2D
= r200TexImage2D
;
1178 #if ENABLE_HW_3D_TEXTURE
1179 functions
->TexImage3D
= r200TexImage3D
;
1181 functions
->TexImage3D
= _mesa_store_teximage3d
;
1183 functions
->TexSubImage1D
= r200TexSubImage1D
;
1184 functions
->TexSubImage2D
= r200TexSubImage2D
;
1185 #if ENABLE_HW_3D_TEXTURE
1186 functions
->TexSubImage3D
= r200TexSubImage3D
;
1188 functions
->TexSubImage3D
= _mesa_store_texsubimage3d
;
1190 functions
->NewTextureObject
= r200NewTextureObject
;
1191 functions
->BindTexture
= r200BindTexture
;
1192 functions
->DeleteTexture
= r200DeleteTexture
;
1193 functions
->IsTextureResident
= driIsTextureResident
;
1195 functions
->TexEnv
= r200TexEnv
;
1196 functions
->TexParameter
= r200TexParameter
;
1197 functions
->TexGen
= r200TexGen
;
1199 functions
->CompressedTexImage2D
= r200CompressedTexImage2D
;
1200 functions
->CompressedTexSubImage2D
= r200CompressedTexSubImage2D
;
1202 driInitTextureFormats();
1205 /* moved or obsolete code */
1206 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1207 driInitTextureObjects( ctx
, & rmesa
->swapped
,
1208 DRI_TEXMGR_DO_TEXTURE_1D
1209 | DRI_TEXMGR_DO_TEXTURE_2D
);
1211 /* Hack: r200NewTextureObject is not yet installed when the
1212 * default textures are created. Therefore set MaxAnisotropy of the
1213 * default 2D texture now. */
1214 ctx
->Shared
->Default2D
->MaxAnisotropy
= driQueryOptionf (&rmesa
->optionCache
,
1215 "def_max_anisotropy");