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__
);
107 t
->pp_txfilter
|= R200_CLAMP_T_WRAP
;
110 t
->pp_txfilter
|= R200_CLAMP_T_CLAMP_GL
;
113 case GL_CLAMP_TO_EDGE
:
114 t
->pp_txfilter
|= R200_CLAMP_T_CLAMP_LAST
;
116 case GL_CLAMP_TO_BORDER
:
117 t
->pp_txfilter
|= R200_CLAMP_T_CLAMP_GL
;
118 is_clamp_to_border
= GL_TRUE
;
120 case GL_MIRRORED_REPEAT
:
121 t
->pp_txfilter
|= R200_CLAMP_T_MIRROR
;
123 case GL_MIRROR_CLAMP_EXT
:
124 t
->pp_txfilter
|= R200_CLAMP_T_MIRROR_CLAMP_GL
;
127 case GL_MIRROR_CLAMP_TO_EDGE_EXT
:
128 t
->pp_txfilter
|= R200_CLAMP_T_MIRROR_CLAMP_LAST
;
130 case GL_MIRROR_CLAMP_TO_BORDER_EXT
:
131 t
->pp_txfilter
|= R200_CLAMP_T_MIRROR_CLAMP_GL
;
132 is_clamp_to_border
= GL_TRUE
;
135 _mesa_problem(NULL
, "bad T wrap mode in %s", __FUNCTION__
);
138 t
->pp_txformat_x
&= ~R200_CLAMP_Q_MASK
;
142 t
->pp_txformat_x
|= R200_CLAMP_Q_WRAP
;
145 t
->pp_txformat_x
|= R200_CLAMP_Q_CLAMP_GL
;
148 case GL_CLAMP_TO_EDGE
:
149 t
->pp_txformat_x
|= R200_CLAMP_Q_CLAMP_LAST
;
151 case GL_CLAMP_TO_BORDER
:
152 t
->pp_txformat_x
|= R200_CLAMP_Q_CLAMP_GL
;
153 is_clamp_to_border
= GL_TRUE
;
155 case GL_MIRRORED_REPEAT
:
156 t
->pp_txformat_x
|= R200_CLAMP_Q_MIRROR
;
158 case GL_MIRROR_CLAMP_EXT
:
159 t
->pp_txformat_x
|= R200_CLAMP_Q_MIRROR_CLAMP_GL
;
162 case GL_MIRROR_CLAMP_TO_EDGE_EXT
:
163 t
->pp_txformat_x
|= R200_CLAMP_Q_MIRROR_CLAMP_LAST
;
165 case GL_MIRROR_CLAMP_TO_BORDER_EXT
:
166 t
->pp_txformat_x
|= R200_CLAMP_Q_MIRROR_CLAMP_GL
;
167 is_clamp_to_border
= GL_TRUE
;
170 _mesa_problem(NULL
, "bad R wrap mode in %s", __FUNCTION__
);
173 if ( is_clamp_to_border
) {
174 t
->pp_txfilter
|= R200_BORDER_MODE_D3D
;
177 t
->border_fallback
= (is_clamp
&& is_clamp_to_border
);
180 static void r200SetTexMaxAnisotropy( r200TexObjPtr t
, GLfloat max
)
182 t
->pp_txfilter
&= ~R200_MAX_ANISO_MASK
;
185 t
->pp_txfilter
|= R200_MAX_ANISO_1_TO_1
;
186 } else if ( max
<= 2.0 ) {
187 t
->pp_txfilter
|= R200_MAX_ANISO_2_TO_1
;
188 } else if ( max
<= 4.0 ) {
189 t
->pp_txfilter
|= R200_MAX_ANISO_4_TO_1
;
190 } else if ( max
<= 8.0 ) {
191 t
->pp_txfilter
|= R200_MAX_ANISO_8_TO_1
;
193 t
->pp_txfilter
|= R200_MAX_ANISO_16_TO_1
;
198 * Set the texture magnification and minification modes.
200 * \param t Texture whose filter modes are to be set
201 * \param minf Texture minification mode
202 * \param magf Texture magnification mode
205 static void r200SetTexFilter( r200TexObjPtr t
, GLenum minf
, GLenum magf
)
207 GLuint anisotropy
= (t
->pp_txfilter
& R200_MAX_ANISO_MASK
);
209 t
->pp_txfilter
&= ~(R200_MIN_FILTER_MASK
| R200_MAG_FILTER_MASK
);
210 t
->pp_txformat_x
&= ~R200_VOLUME_FILTER_MASK
;
212 if ( anisotropy
== R200_MAX_ANISO_1_TO_1
) {
215 t
->pp_txfilter
|= R200_MIN_FILTER_NEAREST
;
218 t
->pp_txfilter
|= R200_MIN_FILTER_LINEAR
;
220 case GL_NEAREST_MIPMAP_NEAREST
:
221 t
->pp_txfilter
|= R200_MIN_FILTER_NEAREST_MIP_NEAREST
;
223 case GL_NEAREST_MIPMAP_LINEAR
:
224 t
->pp_txfilter
|= R200_MIN_FILTER_LINEAR_MIP_NEAREST
;
226 case GL_LINEAR_MIPMAP_NEAREST
:
227 t
->pp_txfilter
|= R200_MIN_FILTER_NEAREST_MIP_LINEAR
;
229 case GL_LINEAR_MIPMAP_LINEAR
:
230 t
->pp_txfilter
|= R200_MIN_FILTER_LINEAR_MIP_LINEAR
;
236 t
->pp_txfilter
|= R200_MIN_FILTER_ANISO_NEAREST
;
239 t
->pp_txfilter
|= R200_MIN_FILTER_ANISO_LINEAR
;
241 case GL_NEAREST_MIPMAP_NEAREST
:
242 case GL_LINEAR_MIPMAP_NEAREST
:
243 t
->pp_txfilter
|= R200_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST
;
245 case GL_NEAREST_MIPMAP_LINEAR
:
246 case GL_LINEAR_MIPMAP_LINEAR
:
247 t
->pp_txfilter
|= R200_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR
;
252 /* Note we don't have 3D mipmaps so only use the mag filter setting
253 * to set the 3D texture filter mode.
257 t
->pp_txfilter
|= R200_MAG_FILTER_NEAREST
;
258 t
->pp_txformat_x
|= R200_VOLUME_FILTER_NEAREST
;
261 t
->pp_txfilter
|= R200_MAG_FILTER_LINEAR
;
262 t
->pp_txformat_x
|= R200_VOLUME_FILTER_LINEAR
;
267 static void r200SetTexBorderColor( r200TexObjPtr t
, GLubyte c
[4] )
269 t
->pp_border_color
= r200PackColor( 4, c
[0], c
[1], c
[2], c
[3] );
274 * Allocate space for and load the mesa images into the texture memory block.
275 * This will happen before drawing with a new texture, or drawing with a
276 * texture after it was swapped out or teximaged again.
279 static r200TexObjPtr
r200AllocTexObj( struct gl_texture_object
*texObj
)
283 t
= CALLOC_STRUCT( r200_tex_obj
);
284 texObj
->DriverData
= t
;
286 if ( R200_DEBUG
& DEBUG_TEXTURE
) {
287 fprintf( stderr
, "%s( %p, %p )\n", __FUNCTION__
, (void *)texObj
,
291 /* Initialize non-image-dependent parts of the state:
293 t
->base
.tObj
= texObj
;
294 t
->border_fallback
= GL_FALSE
;
296 make_empty_list( & t
->base
);
298 r200SetTexWrap( t
, texObj
->WrapS
, texObj
->WrapT
, texObj
->WrapR
);
299 r200SetTexMaxAnisotropy( t
, texObj
->MaxAnisotropy
);
300 r200SetTexFilter( t
, texObj
->MinFilter
, texObj
->MagFilter
);
301 r200SetTexBorderColor( t
, texObj
->_BorderChan
);
307 /* try to find a format which will only need a memcopy */
308 static const struct gl_texture_format
*
309 r200Choose8888TexFormat( GLenum srcFormat
, GLenum srcType
)
312 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
314 if ((srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8
) ||
315 (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
) ||
316 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) ||
317 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_BYTE
&& littleEndian
)) {
318 return &_mesa_texformat_rgba8888
;
320 else if ((srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) ||
321 (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
&& littleEndian
) ||
322 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_INT_8_8_8_8
) ||
323 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
)) {
324 return &_mesa_texformat_rgba8888_rev
;
326 else return _dri_texformat_argb8888
;
329 static const struct gl_texture_format
*
330 r200ChooseTextureFormat( GLcontext
*ctx
, GLint internalFormat
,
331 GLenum format
, GLenum type
)
333 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
334 const GLboolean do32bpt
=
335 ( rmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_32
);
336 const GLboolean force16bpt
=
337 ( rmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_FORCE_16
);
340 switch ( internalFormat
) {
343 case GL_COMPRESSED_RGBA
:
345 case GL_UNSIGNED_INT_10_10_10_2
:
346 case GL_UNSIGNED_INT_2_10_10_10_REV
:
347 return do32bpt
? _dri_texformat_argb8888
: _dri_texformat_argb1555
;
348 case GL_UNSIGNED_SHORT_4_4_4_4
:
349 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
350 return _dri_texformat_argb4444
;
351 case GL_UNSIGNED_SHORT_5_5_5_1
:
352 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
353 return _dri_texformat_argb1555
;
356 r200Choose8888TexFormat(format
, type
) : _dri_texformat_argb4444
;
361 case GL_COMPRESSED_RGB
:
363 case GL_UNSIGNED_SHORT_4_4_4_4
:
364 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
365 return _dri_texformat_argb4444
;
366 case GL_UNSIGNED_SHORT_5_5_5_1
:
367 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
368 return _dri_texformat_argb1555
;
369 case GL_UNSIGNED_SHORT_5_6_5
:
370 case GL_UNSIGNED_SHORT_5_6_5_REV
:
371 return _dri_texformat_rgb565
;
373 return do32bpt
? _dri_texformat_argb8888
: _dri_texformat_rgb565
;
381 r200Choose8888TexFormat(format
, type
) : _dri_texformat_argb4444
;
385 return _dri_texformat_argb4444
;
388 return _dri_texformat_argb1555
;
394 return !force16bpt
? _dri_texformat_argb8888
: _dri_texformat_rgb565
;
399 return _dri_texformat_rgb565
;
406 case GL_COMPRESSED_ALPHA
:
407 /* can't use a8 format since interpreting hw I8 as a8 would result
408 in wrong rgb values (same as alpha value instead of 0). */
409 return _dri_texformat_al88
;
417 case GL_COMPRESSED_LUMINANCE
:
418 return _dri_texformat_l8
;
421 case GL_LUMINANCE_ALPHA
:
422 case GL_LUMINANCE4_ALPHA4
:
423 case GL_LUMINANCE6_ALPHA2
:
424 case GL_LUMINANCE8_ALPHA8
:
425 case GL_LUMINANCE12_ALPHA4
:
426 case GL_LUMINANCE12_ALPHA12
:
427 case GL_LUMINANCE16_ALPHA16
:
428 case GL_COMPRESSED_LUMINANCE_ALPHA
:
429 return _dri_texformat_al88
;
436 case GL_COMPRESSED_INTENSITY
:
437 return _dri_texformat_i8
;
440 if (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
441 type
== GL_UNSIGNED_BYTE
)
442 return &_mesa_texformat_ycbcr
;
444 return &_mesa_texformat_ycbcr_rev
;
448 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
449 return &_mesa_texformat_rgb_dxt1
;
451 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
452 return &_mesa_texformat_rgba_dxt1
;
456 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
457 return &_mesa_texformat_rgba_dxt3
;
459 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
460 return &_mesa_texformat_rgba_dxt5
;
464 "unexpected internalFormat 0x%x in r200ChooseTextureFormat",
465 (int) internalFormat
);
469 return NULL
; /* never get here */
474 r200ValidateClientStorage( GLcontext
*ctx
, GLenum target
,
475 GLint internalFormat
,
476 GLint srcWidth
, GLint srcHeight
,
477 GLenum format
, GLenum type
, const void *pixels
,
478 const struct gl_pixelstore_attrib
*packing
,
479 struct gl_texture_object
*texObj
,
480 struct gl_texture_image
*texImage
)
483 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
485 if ( R200_DEBUG
& DEBUG_TEXTURE
)
486 fprintf(stderr
, "intformat %s format %s type %s\n",
487 _mesa_lookup_enum_by_nr( internalFormat
),
488 _mesa_lookup_enum_by_nr( format
),
489 _mesa_lookup_enum_by_nr( type
));
491 if (!ctx
->Unpack
.ClientStorage
)
494 if (ctx
->_ImageTransferState
||
495 texImage
->IsCompressed
||
496 texObj
->GenerateMipmap
)
500 /* This list is incomplete, may be different on ppc???
502 switch ( internalFormat
) {
504 if ( format
== GL_BGRA
&& type
== GL_UNSIGNED_INT_8_8_8_8_REV
) {
505 texImage
->TexFormat
= _dri_texformat_argb8888
;
512 if ( format
== GL_RGB
&& type
== GL_UNSIGNED_SHORT_5_6_5
) {
513 texImage
->TexFormat
= _dri_texformat_rgb565
;
520 if ( format
== GL_YCBCR_MESA
&&
521 type
== GL_UNSIGNED_SHORT_8_8_REV_APPLE
) {
522 texImage
->TexFormat
= &_mesa_texformat_ycbcr_rev
;
524 else if ( format
== GL_YCBCR_MESA
&&
525 (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
526 type
== GL_UNSIGNED_BYTE
)) {
527 texImage
->TexFormat
= &_mesa_texformat_ycbcr
;
537 /* Could deal with these packing issues, but currently don't:
539 if (packing
->SkipPixels
||
541 packing
->SwapBytes
||
547 GLint srcRowStride
= _mesa_image_row_stride(packing
, srcWidth
,
551 if ( R200_DEBUG
& DEBUG_TEXTURE
)
552 fprintf(stderr
, "%s: srcRowStride %d/%x\n",
553 __FUNCTION__
, srcRowStride
, srcRowStride
);
555 /* Could check this later in upload, pitch restrictions could be
556 * relaxed, but would need to store the image pitch somewhere,
557 * as packing details might change before image is uploaded:
559 if (!r200IsGartMemory( rmesa
, pixels
, srcHeight
* srcRowStride
) ||
564 /* Have validated that _mesa_transfer_teximage would be a straight
565 * memcpy at this point. NOTE: future calls to TexSubImage will
566 * overwrite the client data. This is explicitly mentioned in the
569 texImage
->Data
= (void *)pixels
;
570 texImage
->IsClientData
= GL_TRUE
;
571 texImage
->RowStride
= srcRowStride
/ texImage
->TexFormat
->TexelBytes
;
578 static void r200TexImage1D( GLcontext
*ctx
, GLenum target
, GLint level
,
579 GLint internalFormat
,
580 GLint width
, GLint border
,
581 GLenum format
, GLenum type
, const GLvoid
*pixels
,
582 const struct gl_pixelstore_attrib
*packing
,
583 struct gl_texture_object
*texObj
,
584 struct gl_texture_image
*texImage
)
586 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
589 driSwapOutTextureObject( t
);
592 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
594 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
599 /* Note, this will call ChooseTextureFormat */
600 _mesa_store_teximage1d(ctx
, target
, level
, internalFormat
,
601 width
, border
, format
, type
, pixels
,
602 &ctx
->Unpack
, texObj
, texImage
);
604 t
->dirty_images
[0] |= (1 << level
);
608 static void r200TexSubImage1D( GLcontext
*ctx
, GLenum target
, GLint level
,
611 GLenum format
, GLenum type
,
612 const GLvoid
*pixels
,
613 const struct gl_pixelstore_attrib
*packing
,
614 struct gl_texture_object
*texObj
,
615 struct gl_texture_image
*texImage
)
617 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
619 assert( t
); /* this _should_ be true */
621 driSwapOutTextureObject( t
);
624 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
626 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
631 _mesa_store_texsubimage1d(ctx
, target
, level
, xoffset
, width
,
632 format
, type
, pixels
, packing
, texObj
,
635 t
->dirty_images
[0] |= (1 << level
);
639 static void r200TexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
640 GLint internalFormat
,
641 GLint width
, GLint height
, GLint border
,
642 GLenum format
, GLenum type
, const GLvoid
*pixels
,
643 const struct gl_pixelstore_attrib
*packing
,
644 struct gl_texture_object
*texObj
,
645 struct gl_texture_image
*texImage
)
647 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
650 /* which cube face or ordinary 2D image */
652 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
653 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
654 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
655 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
656 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
657 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
658 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
666 driSwapOutTextureObject( t
);
669 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
671 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
676 texImage
->IsClientData
= GL_FALSE
;
678 if (r200ValidateClientStorage( ctx
, target
,
681 format
, type
, pixels
,
682 packing
, texObj
, texImage
)) {
683 if (R200_DEBUG
& DEBUG_TEXTURE
)
684 fprintf(stderr
, "%s: Using client storage\n", __FUNCTION__
);
687 if (R200_DEBUG
& DEBUG_TEXTURE
)
688 fprintf(stderr
, "%s: Using normal storage\n", __FUNCTION__
);
690 /* Normal path: copy (to cached memory) and eventually upload
691 * via another copy to GART memory and then a blit... Could
692 * eliminate one copy by going straight to (permanent) GART.
694 * Note, this will call r200ChooseTextureFormat.
696 _mesa_store_teximage2d(ctx
, target
, level
, internalFormat
,
697 width
, height
, border
, format
, type
, pixels
,
698 &ctx
->Unpack
, texObj
, texImage
);
700 t
->dirty_images
[face
] |= (1 << level
);
705 static void r200TexSubImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
706 GLint xoffset
, GLint yoffset
,
707 GLsizei width
, GLsizei height
,
708 GLenum format
, GLenum type
,
709 const GLvoid
*pixels
,
710 const struct gl_pixelstore_attrib
*packing
,
711 struct gl_texture_object
*texObj
,
712 struct gl_texture_image
*texImage
)
714 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
717 /* which cube face or ordinary 2D image */
719 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
720 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
721 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
722 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
723 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
724 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
725 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
732 assert( t
); /* this _should_ be true */
734 driSwapOutTextureObject( t
);
737 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
739 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
744 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
745 height
, format
, type
, pixels
, packing
, texObj
,
748 t
->dirty_images
[face
] |= (1 << level
);
752 static void r200CompressedTexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
753 GLint internalFormat
,
754 GLint width
, GLint height
, GLint border
,
755 GLsizei imageSize
, const GLvoid
*data
,
756 struct gl_texture_object
*texObj
,
757 struct gl_texture_image
*texImage
)
759 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
762 /* which cube face or ordinary 2D image */
764 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
765 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
766 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
767 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
768 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
769 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
770 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
778 driSwapOutTextureObject( t
);
781 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
783 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2D");
788 texImage
->IsClientData
= GL_FALSE
;
789 /* can't call this, different parameters. Would never evaluate to true anyway currently
790 if (r200ValidateClientStorage( ctx, target,
793 format, type, pixels,
794 packing, texObj, texImage)) {
795 if (R200_DEBUG & DEBUG_TEXTURE)
796 fprintf(stderr, "%s: Using client storage\n", __FUNCTION__);
799 if (R200_DEBUG
& DEBUG_TEXTURE
)
800 fprintf(stderr
, "%s: Using normal storage\n", __FUNCTION__
);
802 /* Normal path: copy (to cached memory) and eventually upload
803 * via another copy to GART memory and then a blit... Could
804 * eliminate one copy by going straight to (permanent) GART.
806 * Note, this will call r200ChooseTextureFormat.
808 _mesa_store_compressed_teximage2d(ctx
, target
, level
, internalFormat
, width
,
809 height
, border
, imageSize
, data
, texObj
, texImage
);
811 t
->dirty_images
[face
] |= (1 << level
);
816 static void r200CompressedTexSubImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
817 GLint xoffset
, GLint yoffset
,
818 GLsizei width
, GLsizei height
,
820 GLsizei imageSize
, const GLvoid
*data
,
821 struct gl_texture_object
*texObj
,
822 struct gl_texture_image
*texImage
)
824 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
828 /* which cube face or ordinary 2D image */
830 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
831 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
832 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
833 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
834 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
835 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
836 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
843 assert( t
); /* this _should_ be true */
845 driSwapOutTextureObject( t
);
848 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
850 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexSubImage2D");
855 _mesa_store_compressed_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
856 height
, format
, imageSize
, data
, texObj
, texImage
);
858 t
->dirty_images
[face
] |= (1 << level
);
862 #if ENABLE_HW_3D_TEXTURE
863 static void r200TexImage3D( GLcontext
*ctx
, GLenum target
, GLint level
,
864 GLint internalFormat
,
865 GLint width
, GLint height
, GLint depth
,
867 GLenum format
, GLenum type
, const GLvoid
*pixels
,
868 const struct gl_pixelstore_attrib
*packing
,
869 struct gl_texture_object
*texObj
,
870 struct gl_texture_image
*texImage
)
872 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
875 driSwapOutTextureObject( t
);
878 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
880 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
885 texImage
->IsClientData
= GL_FALSE
;
888 if (r200ValidateClientStorage( ctx
, target
,
891 format
, type
, pixels
,
892 packing
, texObj
, texImage
)) {
893 if (R200_DEBUG
& DEBUG_TEXTURE
)
894 fprintf(stderr
, "%s: Using client storage\n", __FUNCTION__
);
899 if (R200_DEBUG
& DEBUG_TEXTURE
)
900 fprintf(stderr
, "%s: Using normal storage\n", __FUNCTION__
);
902 /* Normal path: copy (to cached memory) and eventually upload
903 * via another copy to GART memory and then a blit... Could
904 * eliminate one copy by going straight to (permanent) GART.
906 * Note, this will call r200ChooseTextureFormat.
908 _mesa_store_teximage3d(ctx
, target
, level
, internalFormat
,
909 width
, height
, depth
, border
,
910 format
, type
, pixels
,
911 &ctx
->Unpack
, texObj
, texImage
);
913 t
->dirty_images
[0] |= (1 << level
);
919 #if ENABLE_HW_3D_TEXTURE
921 r200TexSubImage3D( GLcontext
*ctx
, GLenum target
, GLint level
,
922 GLint xoffset
, GLint yoffset
, GLint zoffset
,
923 GLsizei width
, GLsizei height
, GLsizei depth
,
924 GLenum format
, GLenum type
,
925 const GLvoid
*pixels
,
926 const struct gl_pixelstore_attrib
*packing
,
927 struct gl_texture_object
*texObj
,
928 struct gl_texture_image
*texImage
)
930 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
932 /* fprintf(stderr, "%s\n", __FUNCTION__); */
934 assert( t
); /* this _should_ be true */
936 driSwapOutTextureObject( t
);
939 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
941 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage3D");
944 texObj
->DriverData
= t
;
947 _mesa_store_texsubimage3d(ctx
, target
, level
, xoffset
, yoffset
, zoffset
,
948 width
, height
, depth
,
949 format
, type
, pixels
, packing
, texObj
, texImage
);
951 t
->dirty_images
[0] |= (1 << level
);
957 static void r200TexEnv( GLcontext
*ctx
, GLenum target
,
958 GLenum pname
, const GLfloat
*param
)
960 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
961 GLuint unit
= ctx
->Texture
.CurrentUnit
;
962 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
964 if ( R200_DEBUG
& DEBUG_STATE
) {
965 fprintf( stderr
, "%s( %s )\n",
966 __FUNCTION__
, _mesa_lookup_enum_by_nr( pname
) );
969 /* This is incorrect: Need to maintain this data for each of
970 * GL_TEXTURE_{123}D, GL_TEXTURE_RECTANGLE_NV, etc, and switch
971 * between them according to _ReallyEnabled.
974 case GL_TEXTURE_ENV_COLOR
: {
977 UNCLAMPED_FLOAT_TO_RGBA_CHAN( c
, texUnit
->EnvColor
);
978 envColor
= r200PackColor( 4, c
[0], c
[1], c
[2], c
[3] );
979 if ( rmesa
->hw
.tf
.cmd
[TF_TFACTOR_0
+ unit
] != envColor
) {
980 R200_STATECHANGE( rmesa
, tf
);
981 rmesa
->hw
.tf
.cmd
[TF_TFACTOR_0
+ unit
] = envColor
;
986 case GL_TEXTURE_LOD_BIAS_EXT
: {
989 const int fixed_one
= 0x8000000;
991 /* The R200's LOD bias is a signed 2's complement value with a
992 * range of -16.0 <= bias < 16.0.
994 * NOTE: Add a small bias to the bias for conform mipsel.c test.
997 min
= driQueryOptionb (&rmesa
->optionCache
, "no_neg_lod_bias") ?
999 bias
= CLAMP( bias
, min
, 16.0 );
1000 b
= (int)(bias
* fixed_one
) & R200_LOD_BIAS_MASK
;
1002 if ( (rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT_X
] & R200_LOD_BIAS_MASK
) != b
) {
1003 R200_STATECHANGE( rmesa
, tex
[unit
] );
1004 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT_X
] &= ~R200_LOD_BIAS_MASK
;
1005 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT_X
] |= b
;
1009 case GL_COORD_REPLACE_ARB
:
1010 if (ctx
->Point
.PointSprite
) {
1011 R200_STATECHANGE( rmesa
, spr
);
1012 if ((GLenum
)param
[0]) {
1013 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |= R200_PS_GEN_TEX_0
<< unit
;
1015 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] &= ~(R200_PS_GEN_TEX_0
<< unit
);
1026 * Changes variables and flags for a state update, which will happen at the
1027 * next UpdateTextureState
1030 static void r200TexParameter( GLcontext
*ctx
, GLenum target
,
1031 struct gl_texture_object
*texObj
,
1032 GLenum pname
, const GLfloat
*params
)
1034 r200TexObjPtr t
= (r200TexObjPtr
) texObj
->DriverData
;
1036 if ( R200_DEBUG
& (DEBUG_STATE
|DEBUG_TEXTURE
) ) {
1037 fprintf( stderr
, "%s( %s )\n", __FUNCTION__
,
1038 _mesa_lookup_enum_by_nr( pname
) );
1042 case GL_TEXTURE_MIN_FILTER
:
1043 case GL_TEXTURE_MAG_FILTER
:
1044 case GL_TEXTURE_MAX_ANISOTROPY_EXT
:
1045 r200SetTexMaxAnisotropy( t
, texObj
->MaxAnisotropy
);
1046 r200SetTexFilter( t
, texObj
->MinFilter
, texObj
->MagFilter
);
1049 case GL_TEXTURE_WRAP_S
:
1050 case GL_TEXTURE_WRAP_T
:
1051 case GL_TEXTURE_WRAP_R
:
1052 r200SetTexWrap( t
, texObj
->WrapS
, texObj
->WrapT
, texObj
->WrapR
);
1055 case GL_TEXTURE_BORDER_COLOR
:
1056 r200SetTexBorderColor( t
, texObj
->_BorderChan
);
1059 case GL_TEXTURE_BASE_LEVEL
:
1060 case GL_TEXTURE_MAX_LEVEL
:
1061 case GL_TEXTURE_MIN_LOD
:
1062 case GL_TEXTURE_MAX_LOD
:
1063 /* This isn't the most efficient solution but there doesn't appear to
1064 * be a nice alternative. Since there's no LOD clamping,
1065 * we just have to rely on loading the right subset of mipmap levels
1066 * to simulate a clamped LOD.
1068 driSwapOutTextureObject( (driTextureObject
*) t
);
1075 /* Mark this texobj as dirty (one bit per tex unit)
1077 t
->dirty_state
= TEX_ALL
;
1082 static void r200BindTexture( GLcontext
*ctx
, GLenum target
,
1083 struct gl_texture_object
*texObj
)
1085 if ( R200_DEBUG
& (DEBUG_STATE
|DEBUG_TEXTURE
) ) {
1086 fprintf( stderr
, "%s( %p ) unit=%d\n", __FUNCTION__
, (void *)texObj
,
1087 ctx
->Texture
.CurrentUnit
);
1090 if ( (target
== GL_TEXTURE_1D
)
1091 || (target
== GL_TEXTURE_2D
)
1092 #if ENABLE_HW_3D_TEXTURE
1093 || (target
== GL_TEXTURE_3D
)
1095 || (target
== GL_TEXTURE_CUBE_MAP
)
1096 || (target
== GL_TEXTURE_RECTANGLE_NV
) ) {
1097 assert( texObj
->DriverData
!= NULL
);
1102 static void r200DeleteTexture( GLcontext
*ctx
,
1103 struct gl_texture_object
*texObj
)
1105 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1106 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
1108 if ( R200_DEBUG
& (DEBUG_STATE
|DEBUG_TEXTURE
) ) {
1109 fprintf( stderr
, "%s( %p (target = %s) )\n", __FUNCTION__
, (void *)texObj
,
1110 _mesa_lookup_enum_by_nr( texObj
->Target
) );
1115 R200_FIREVERTICES( rmesa
);
1118 driDestroyTextureObject( t
);
1120 /* Free mipmap images and the texture object itself */
1121 _mesa_delete_texture_object(ctx
, texObj
);
1125 * - Same GEN_MODE for all active bits
1126 * - Same EyePlane/ObjPlane for all active bits when using Eye/Obj
1127 * - STRQ presumably all supported (matrix means incoming R values
1128 * can end up in STQ, this has implications for vertex support,
1129 * presumably ok if maos is used, though?)
1131 * Basically impossible to do this on the fly - just collect some
1132 * basic info & do the checks from ValidateState().
1134 static void r200TexGen( GLcontext
*ctx
,
1137 const GLfloat
*params
)
1139 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1140 GLuint unit
= ctx
->Texture
.CurrentUnit
;
1141 rmesa
->recheck_texgen
[unit
] = GL_TRUE
;
1146 * Allocate a new texture object.
1147 * Called via ctx->Driver.NewTextureObject.
1148 * Note: this function will be called during context creation to
1149 * allocate the default texture objects.
1150 * Note: we could use containment here to 'derive' the driver-specific
1151 * texture object from the core mesa gl_texture_object. Not done at this time.
1152 * Fixup MaxAnisotropy according to user preference.
1154 static struct gl_texture_object
*
1155 r200NewTextureObject( GLcontext
*ctx
, GLuint name
, GLenum target
)
1157 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1158 struct gl_texture_object
*obj
;
1159 obj
= _mesa_new_texture_object(ctx
, name
, target
);
1162 obj
->MaxAnisotropy
= rmesa
->initialMaxAnisotropy
;
1163 r200AllocTexObj( obj
);
1168 void r200InitTextureFuncs( struct dd_function_table
*functions
)
1170 /* Note: we only plug in the functions we implement in the driver
1171 * since _mesa_init_driver_functions() was already called.
1173 functions
->ChooseTextureFormat
= r200ChooseTextureFormat
;
1174 functions
->TexImage1D
= r200TexImage1D
;
1175 functions
->TexImage2D
= r200TexImage2D
;
1176 #if ENABLE_HW_3D_TEXTURE
1177 functions
->TexImage3D
= r200TexImage3D
;
1179 functions
->TexImage3D
= _mesa_store_teximage3d
;
1181 functions
->TexSubImage1D
= r200TexSubImage1D
;
1182 functions
->TexSubImage2D
= r200TexSubImage2D
;
1183 #if ENABLE_HW_3D_TEXTURE
1184 functions
->TexSubImage3D
= r200TexSubImage3D
;
1186 functions
->TexSubImage3D
= _mesa_store_texsubimage3d
;
1188 functions
->NewTextureObject
= r200NewTextureObject
;
1189 functions
->BindTexture
= r200BindTexture
;
1190 functions
->DeleteTexture
= r200DeleteTexture
;
1191 functions
->IsTextureResident
= driIsTextureResident
;
1193 functions
->TexEnv
= r200TexEnv
;
1194 functions
->TexParameter
= r200TexParameter
;
1195 functions
->TexGen
= r200TexGen
;
1197 functions
->CompressedTexImage2D
= r200CompressedTexImage2D
;
1198 functions
->CompressedTexSubImage2D
= r200CompressedTexSubImage2D
;
1200 driInitTextureFormats();
1203 /* moved or obsolete code */
1204 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1205 driInitTextureObjects( ctx
, & rmesa
->swapped
,
1206 DRI_TEXMGR_DO_TEXTURE_1D
1207 | DRI_TEXMGR_DO_TEXTURE_2D
);
1209 /* Hack: r200NewTextureObject is not yet installed when the
1210 * default textures are created. Therefore set MaxAnisotropy of the
1211 * default 2D texture now. */
1212 ctx
->Shared
->Default2D
->MaxAnisotropy
= driQueryOptionf (&rmesa
->optionCache
,
1213 "def_max_anisotropy");