1 /* $XFree86: xc/lib/GL/mesa/src/drv/r200/r200_tex.c,v 1.2 2002/11/05 17:46:08 tsi Exp $ */
3 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
5 The Weather Channel (TM) funded Tungsten Graphics to develop the
6 initial release of the Radeon 8500 driver under the XFree86 license.
7 This notice must be preserved.
9 Permission is hereby granted, free of charge, to any person obtaining
10 a copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sublicense, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial
19 portions of the Software.
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
25 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 * Keith Whitwell <keith@tungstengraphics.com>
41 #include "simple_list.h"
42 #include "texformat.h"
49 #include "r200_context.h"
50 #include "r200_state.h"
51 #include "r200_ioctl.h"
52 #include "r200_swtcl.h"
60 * Set the texture wrap modes.
62 * \param t Texture object whose wrap modes are to be set
63 * \param swrap Wrap mode for the \a s texture coordinate
64 * \param twrap Wrap mode for the \a t texture coordinate
67 static void r200SetTexWrap( r200TexObjPtr t
, GLenum swrap
, GLenum twrap
, GLenum rwrap
)
69 GLboolean is_clamp
= GL_FALSE
;
70 GLboolean is_clamp_to_border
= GL_FALSE
;
72 t
->pp_txfilter
&= ~(R200_CLAMP_S_MASK
| R200_CLAMP_T_MASK
| R200_BORDER_MODE_D3D
);
76 t
->pp_txfilter
|= R200_CLAMP_S_WRAP
;
79 t
->pp_txfilter
|= R200_CLAMP_S_CLAMP_GL
;
82 case GL_CLAMP_TO_EDGE
:
83 t
->pp_txfilter
|= R200_CLAMP_S_CLAMP_LAST
;
85 case GL_CLAMP_TO_BORDER
:
86 t
->pp_txfilter
|= R200_CLAMP_S_CLAMP_GL
;
87 is_clamp_to_border
= GL_TRUE
;
89 case GL_MIRRORED_REPEAT
:
90 t
->pp_txfilter
|= R200_CLAMP_S_MIRROR
;
92 case GL_MIRROR_CLAMP_EXT
:
93 t
->pp_txfilter
|= R200_CLAMP_S_MIRROR_CLAMP_GL
;
96 case GL_MIRROR_CLAMP_TO_EDGE_EXT
:
97 t
->pp_txfilter
|= R200_CLAMP_S_MIRROR_CLAMP_LAST
;
99 case GL_MIRROR_CLAMP_TO_BORDER_EXT
:
100 t
->pp_txfilter
|= R200_CLAMP_S_MIRROR_CLAMP_GL
;
101 is_clamp_to_border
= GL_TRUE
;
104 _mesa_problem(NULL
, "bad S wrap mode in %s", __FUNCTION__
);
109 t
->pp_txfilter
|= R200_CLAMP_T_WRAP
;
112 t
->pp_txfilter
|= R200_CLAMP_T_CLAMP_GL
;
115 case GL_CLAMP_TO_EDGE
:
116 t
->pp_txfilter
|= R200_CLAMP_T_CLAMP_LAST
;
118 case GL_CLAMP_TO_BORDER
:
119 t
->pp_txfilter
|= R200_CLAMP_T_CLAMP_GL
| R200_BORDER_MODE_D3D
;
120 is_clamp_to_border
= GL_TRUE
;
122 case GL_MIRRORED_REPEAT
:
123 t
->pp_txfilter
|= R200_CLAMP_T_MIRROR
;
125 case GL_MIRROR_CLAMP_EXT
:
126 t
->pp_txfilter
|= R200_CLAMP_T_MIRROR_CLAMP_GL
;
129 case GL_MIRROR_CLAMP_TO_EDGE_EXT
:
130 t
->pp_txfilter
|= R200_CLAMP_T_MIRROR_CLAMP_LAST
;
132 case GL_MIRROR_CLAMP_TO_BORDER_EXT
:
133 t
->pp_txfilter
|= R200_CLAMP_T_MIRROR_CLAMP_GL
;
134 is_clamp_to_border
= GL_TRUE
;
137 _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
);
310 static const struct gl_texture_format
*
311 r200ChooseTextureFormat( GLcontext
*ctx
, GLint internalFormat
,
312 GLenum format
, GLenum type
)
314 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
315 const GLboolean do32bpt
=
316 ( rmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_32
);
317 const GLboolean force16bpt
=
318 ( rmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_FORCE_16
);
321 switch ( internalFormat
) {
324 case GL_COMPRESSED_RGBA
:
326 case GL_UNSIGNED_INT_10_10_10_2
:
327 case GL_UNSIGNED_INT_2_10_10_10_REV
:
328 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb1555
;
329 case GL_UNSIGNED_SHORT_4_4_4_4
:
330 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
331 return &_mesa_texformat_argb4444
;
332 case GL_UNSIGNED_SHORT_5_5_5_1
:
333 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
334 return &_mesa_texformat_argb1555
;
336 return do32bpt
? &_mesa_texformat_rgba8888
: &_mesa_texformat_argb4444
;
341 case GL_COMPRESSED_RGB
:
343 case GL_UNSIGNED_SHORT_4_4_4_4
:
344 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
345 return &_mesa_texformat_argb4444
;
346 case GL_UNSIGNED_SHORT_5_5_5_1
:
347 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
348 return &_mesa_texformat_argb1555
;
349 case GL_UNSIGNED_SHORT_5_6_5
:
350 case GL_UNSIGNED_SHORT_5_6_5_REV
:
351 return &_mesa_texformat_rgb565
;
353 return do32bpt
? &_mesa_texformat_rgba8888
: &_mesa_texformat_rgb565
;
361 &_mesa_texformat_rgba8888
: &_mesa_texformat_argb4444
;
365 return &_mesa_texformat_argb4444
;
368 return &_mesa_texformat_argb1555
;
374 return !force16bpt
? &_mesa_texformat_rgba8888
: &_mesa_texformat_rgb565
;
379 return &_mesa_texformat_rgb565
;
386 case GL_COMPRESSED_ALPHA
:
387 return &_mesa_texformat_al88
;
395 case GL_COMPRESSED_LUMINANCE
:
396 return &_mesa_texformat_al88
;
399 case GL_LUMINANCE_ALPHA
:
400 case GL_LUMINANCE4_ALPHA4
:
401 case GL_LUMINANCE6_ALPHA2
:
402 case GL_LUMINANCE8_ALPHA8
:
403 case GL_LUMINANCE12_ALPHA4
:
404 case GL_LUMINANCE12_ALPHA12
:
405 case GL_LUMINANCE16_ALPHA16
:
406 case GL_COMPRESSED_LUMINANCE_ALPHA
:
407 return &_mesa_texformat_al88
;
414 case GL_COMPRESSED_INTENSITY
:
415 /* At the moment, glean & conform both fail using the i8 internal
418 return &_mesa_texformat_al88
;
419 /* return &_mesa_texformat_i8; */
422 if (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
423 type
== GL_UNSIGNED_BYTE
)
424 return &_mesa_texformat_ycbcr
;
426 return &_mesa_texformat_ycbcr_rev
;
429 _mesa_problem(ctx
, "unexpected texture format in %s", __FUNCTION__
);
433 return NULL
; /* never get here */
438 r200ValidateClientStorage( GLcontext
*ctx
, GLenum target
,
439 GLint internalFormat
,
440 GLint srcWidth
, GLint srcHeight
,
441 GLenum format
, GLenum type
, const void *pixels
,
442 const struct gl_pixelstore_attrib
*packing
,
443 struct gl_texture_object
*texObj
,
444 struct gl_texture_image
*texImage
)
447 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
451 fprintf(stderr
, "intformat %s format %s type %s\n",
452 _mesa_lookup_enum_by_nr( internalFormat
),
453 _mesa_lookup_enum_by_nr( format
),
454 _mesa_lookup_enum_by_nr( type
));
456 if (!ctx
->Unpack
.ClientStorage
)
459 if (ctx
->_ImageTransferState
||
460 texImage
->IsCompressed
||
461 texObj
->GenerateMipmap
)
465 /* This list is incomplete, may be different on ppc???
467 switch ( internalFormat
) {
469 if ( format
== GL_BGRA
&& type
== GL_UNSIGNED_INT_8_8_8_8_REV
) {
470 texImage
->TexFormat
= &_mesa_texformat_argb8888
;
478 if ( format
== GL_RGB
&& type
== GL_UNSIGNED_SHORT_5_6_5
) {
479 texImage
->TexFormat
= &_mesa_texformat_rgb565
;
487 if ( format
== GL_YCBCR_MESA
&&
488 type
== GL_UNSIGNED_SHORT_8_8_REV_APPLE
) {
489 texImage
->TexFormat
= &_mesa_texformat_ycbcr_rev
;
492 else if ( format
== GL_YCBCR_MESA
&&
493 (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
494 type
== GL_UNSIGNED_BYTE
)) {
495 texImage
->TexFormat
= &_mesa_texformat_ycbcr
;
507 /* Could deal with these packing issues, but currently don't:
509 if (packing
->SkipPixels
||
511 packing
->SwapBytes
||
517 GLint srcRowStride
= _mesa_image_row_stride(packing
, srcWidth
,
522 fprintf(stderr
, "%s: srcRowStride %d/%x\n",
523 __FUNCTION__
, srcRowStride
, srcRowStride
);
525 /* Could check this later in upload, pitch restrictions could be
526 * relaxed, but would need to store the image pitch somewhere,
527 * as packing details might change before image is uploaded:
529 if (!r200IsGartMemory( rmesa
, pixels
, srcHeight
* srcRowStride
) ||
534 /* Have validated that _mesa_transfer_teximage would be a straight
535 * memcpy at this point. NOTE: future calls to TexSubImage will
536 * overwrite the client data. This is explicitly mentioned in the
539 texImage
->Data
= (void *)pixels
;
540 texImage
->IsClientData
= GL_TRUE
;
541 texImage
->RowStride
= srcRowStride
/ texelBytes
;
547 static void r200TexImage1D( GLcontext
*ctx
, GLenum target
, GLint level
,
548 GLint internalFormat
,
549 GLint width
, GLint border
,
550 GLenum format
, GLenum type
, const GLvoid
*pixels
,
551 const struct gl_pixelstore_attrib
*packing
,
552 struct gl_texture_object
*texObj
,
553 struct gl_texture_image
*texImage
)
555 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
558 driSwapOutTextureObject( t
);
561 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
563 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
568 /* Note, this will call ChooseTextureFormat */
569 _mesa_store_teximage1d(ctx
, target
, level
, internalFormat
,
570 width
, border
, format
, type
, pixels
,
571 &ctx
->Unpack
, texObj
, texImage
);
573 t
->dirty_images
[0] |= (1 << level
);
577 static void r200TexSubImage1D( GLcontext
*ctx
, GLenum target
, GLint level
,
580 GLenum format
, GLenum type
,
581 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
;
588 assert( t
); /* this _should_ be true */
590 driSwapOutTextureObject( t
);
593 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
595 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
600 _mesa_store_texsubimage1d(ctx
, target
, level
, xoffset
, width
,
601 format
, type
, pixels
, packing
, texObj
,
604 t
->dirty_images
[0] |= (1 << level
);
608 static void r200TexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
609 GLint internalFormat
,
610 GLint width
, GLint height
, GLint border
,
611 GLenum format
, GLenum type
, const GLvoid
*pixels
,
612 const struct gl_pixelstore_attrib
*packing
,
613 struct gl_texture_object
*texObj
,
614 struct gl_texture_image
*texImage
)
616 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
619 /* which cube face or ordinary 2D image */
621 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
622 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
623 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
624 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
625 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
626 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
627 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
635 driSwapOutTextureObject( t
);
638 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
640 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
645 texImage
->IsClientData
= GL_FALSE
;
647 if (r200ValidateClientStorage( ctx
, target
,
650 format
, type
, pixels
,
651 packing
, texObj
, texImage
)) {
652 if (R200_DEBUG
& DEBUG_TEXTURE
)
653 fprintf(stderr
, "%s: Using client storage\n", __FUNCTION__
);
656 if (R200_DEBUG
& DEBUG_TEXTURE
)
657 fprintf(stderr
, "%s: Using normal storage\n", __FUNCTION__
);
659 /* Normal path: copy (to cached memory) and eventually upload
660 * via another copy to GART memory and then a blit... Could
661 * eliminate one copy by going straight to (permanent) GART.
663 * Note, this will call r200ChooseTextureFormat.
665 _mesa_store_teximage2d(ctx
, target
, level
, internalFormat
,
666 width
, height
, border
, format
, type
, pixels
,
667 &ctx
->Unpack
, texObj
, texImage
);
669 t
->dirty_images
[face
] |= (1 << level
);
674 static void r200TexSubImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
675 GLint xoffset
, GLint yoffset
,
676 GLsizei width
, GLsizei height
,
677 GLenum format
, GLenum type
,
678 const GLvoid
*pixels
,
679 const struct gl_pixelstore_attrib
*packing
,
680 struct gl_texture_object
*texObj
,
681 struct gl_texture_image
*texImage
)
683 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
686 /* which cube face or ordinary 2D image */
688 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
689 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
690 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
691 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
692 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
693 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
694 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
701 assert( t
); /* this _should_ be true */
703 driSwapOutTextureObject( t
);
706 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
708 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
713 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
714 height
, format
, type
, pixels
, packing
, texObj
,
717 t
->dirty_images
[face
] |= (1 << level
);
721 #if ENABLE_HW_3D_TEXTURE
722 static void r200TexImage3D( GLcontext
*ctx
, GLenum target
, GLint level
,
723 GLint internalFormat
,
724 GLint width
, GLint height
, GLint depth
,
726 GLenum format
, GLenum type
, const GLvoid
*pixels
,
727 const struct gl_pixelstore_attrib
*packing
,
728 struct gl_texture_object
*texObj
,
729 struct gl_texture_image
*texImage
)
731 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
734 driSwapOutTextureObject( t
);
737 t
= r200AllocTexObj( texObj
);
739 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
744 texImage
->IsClientData
= GL_FALSE
;
747 if (r200ValidateClientStorage( ctx
, target
,
750 format
, type
, pixels
,
751 packing
, texObj
, texImage
)) {
752 if (R200_DEBUG
& DEBUG_TEXTURE
)
753 fprintf(stderr
, "%s: Using client storage\n", __FUNCTION__
);
758 if (R200_DEBUG
& DEBUG_TEXTURE
)
759 fprintf(stderr
, "%s: Using normal storage\n", __FUNCTION__
);
761 /* Normal path: copy (to cached memory) and eventually upload
762 * via another copy to GART memory and then a blit... Could
763 * eliminate one copy by going straight to (permanent) GART.
765 * Note, this will call r200ChooseTextureFormat.
767 _mesa_store_teximage3d(ctx
, target
, level
, internalFormat
,
768 width
, height
, depth
, border
,
769 format
, type
, pixels
,
770 &ctx
->Unpack
, texObj
, texImage
);
772 t
->dirty_images
[0] |= (1 << level
);
778 #if ENABLE_HW_3D_TEXTURE
780 r200TexSubImage3D( GLcontext
*ctx
, GLenum target
, GLint level
,
781 GLint xoffset
, GLint yoffset
, GLint zoffset
,
782 GLsizei width
, GLsizei height
, GLsizei depth
,
783 GLenum format
, GLenum type
,
784 const GLvoid
*pixels
,
785 const struct gl_pixelstore_attrib
*packing
,
786 struct gl_texture_object
*texObj
,
787 struct gl_texture_image
*texImage
)
789 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
791 /* fprintf(stderr, "%s\n", __FUNCTION__); */
793 assert( t
); /* this _should_ be true */
795 driSwapOutTextureObject( t
);
798 t
= r200AllocTexObj(texObj
);
800 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage3D");
803 texObj
->DriverData
= t
;
806 _mesa_store_texsubimage3d(ctx
, target
, level
, xoffset
, yoffset
, zoffset
,
807 width
, height
, depth
,
808 format
, type
, pixels
, packing
, texObj
, texImage
);
810 t
->dirty_images
[0] |= (1 << level
);
816 static void r200TexEnv( GLcontext
*ctx
, GLenum target
,
817 GLenum pname
, const GLfloat
*param
)
819 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
820 GLuint unit
= ctx
->Texture
.CurrentUnit
;
821 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
823 if ( R200_DEBUG
& DEBUG_STATE
) {
824 fprintf( stderr
, "%s( %s )\n",
825 __FUNCTION__
, _mesa_lookup_enum_by_nr( pname
) );
828 /* This is incorrect: Need to maintain this data for each of
829 * GL_TEXTURE_{123}D, GL_TEXTURE_RECTANGLE_NV, etc, and switch
830 * between them according to _ReallyEnabled.
833 case GL_TEXTURE_ENV_COLOR
: {
836 UNCLAMPED_FLOAT_TO_RGBA_CHAN( c
, texUnit
->EnvColor
);
837 envColor
= r200PackColor( 4, c
[0], c
[1], c
[2], c
[3] );
838 if ( rmesa
->hw
.tf
.cmd
[TF_TFACTOR_0
+ unit
] != envColor
) {
839 R200_STATECHANGE( rmesa
, tf
);
840 rmesa
->hw
.tf
.cmd
[TF_TFACTOR_0
+ unit
] = envColor
;
845 case GL_TEXTURE_LOD_BIAS_EXT
: {
848 const int fixed_one
= 0x8000000;
850 /* The R200's LOD bias is a signed 2's complement value with a
851 * range of -16.0 <= bias < 16.0.
853 * NOTE: Add a small bias to the bias for conform mipsel.c test.
856 min
= driQueryOptionb (&rmesa
->optionCache
, "no_neg_lod_bias") ?
858 bias
= CLAMP( bias
, min
, 16.0 );
859 b
= (int)(bias
* fixed_one
) & R200_LOD_BIAS_MASK
;
861 if ( (rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT_X
] & R200_LOD_BIAS_MASK
) != b
) {
862 R200_STATECHANGE( rmesa
, tex
[unit
] );
863 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT_X
] &= ~R200_LOD_BIAS_MASK
;
864 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT_X
] |= b
;
876 * Changes variables and flags for a state update, which will happen at the
877 * next UpdateTextureState
880 static void r200TexParameter( GLcontext
*ctx
, GLenum target
,
881 struct gl_texture_object
*texObj
,
882 GLenum pname
, const GLfloat
*params
)
884 r200TexObjPtr t
= (r200TexObjPtr
) texObj
->DriverData
;
886 if ( R200_DEBUG
& (DEBUG_STATE
|DEBUG_TEXTURE
) ) {
887 fprintf( stderr
, "%s( %s )\n", __FUNCTION__
,
888 _mesa_lookup_enum_by_nr( pname
) );
892 case GL_TEXTURE_MIN_FILTER
:
893 case GL_TEXTURE_MAG_FILTER
:
894 case GL_TEXTURE_MAX_ANISOTROPY_EXT
:
895 r200SetTexMaxAnisotropy( t
, texObj
->MaxAnisotropy
);
896 r200SetTexFilter( t
, texObj
->MinFilter
, texObj
->MagFilter
);
899 case GL_TEXTURE_WRAP_S
:
900 case GL_TEXTURE_WRAP_T
:
901 case GL_TEXTURE_WRAP_R
:
902 r200SetTexWrap( t
, texObj
->WrapS
, texObj
->WrapT
, texObj
->WrapR
);
905 case GL_TEXTURE_BORDER_COLOR
:
906 r200SetTexBorderColor( t
, texObj
->_BorderChan
);
909 case GL_TEXTURE_BASE_LEVEL
:
910 case GL_TEXTURE_MAX_LEVEL
:
911 case GL_TEXTURE_MIN_LOD
:
912 case GL_TEXTURE_MAX_LOD
:
913 /* This isn't the most efficient solution but there doesn't appear to
914 * be a nice alternative. Since there's no LOD clamping,
915 * we just have to rely on loading the right subset of mipmap levels
916 * to simulate a clamped LOD.
918 driSwapOutTextureObject( (driTextureObject
*) t
);
925 /* Mark this texobj as dirty (one bit per tex unit)
927 t
->dirty_state
= TEX_ALL
;
932 static void r200BindTexture( GLcontext
*ctx
, GLenum target
,
933 struct gl_texture_object
*texObj
)
935 if ( R200_DEBUG
& (DEBUG_STATE
|DEBUG_TEXTURE
) ) {
936 fprintf( stderr
, "%s( %p ) unit=%d\n", __FUNCTION__
, (void *)texObj
,
937 ctx
->Texture
.CurrentUnit
);
940 if ( (target
== GL_TEXTURE_1D
)
941 || (target
== GL_TEXTURE_2D
)
942 #if ENABLE_HW_3D_TEXTURE
943 || (target
== GL_TEXTURE_3D
)
945 || (target
== GL_TEXTURE_CUBE_MAP
)
946 || (target
== GL_TEXTURE_RECTANGLE_NV
) ) {
947 assert( texObj
->DriverData
!= NULL
);
952 static void r200DeleteTexture( GLcontext
*ctx
,
953 struct gl_texture_object
*texObj
)
955 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
956 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
958 if ( R200_DEBUG
& (DEBUG_STATE
|DEBUG_TEXTURE
) ) {
959 fprintf( stderr
, "%s( %p (target = %s) )\n", __FUNCTION__
, (void *)texObj
,
960 _mesa_lookup_enum_by_nr( texObj
->Target
) );
965 R200_FIREVERTICES( rmesa
);
968 driDestroyTextureObject( t
);
970 /* Free mipmap images and the texture object itself */
971 _mesa_delete_texture_object(ctx
, texObj
);
975 * - Same GEN_MODE for all active bits
976 * - Same EyePlane/ObjPlane for all active bits when using Eye/Obj
977 * - STRQ presumably all supported (matrix means incoming R values
978 * can end up in STQ, this has implications for vertex support,
979 * presumably ok if maos is used, though?)
981 * Basically impossible to do this on the fly - just collect some
982 * basic info & do the checks from ValidateState().
984 static void r200TexGen( GLcontext
*ctx
,
987 const GLfloat
*params
)
989 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
990 GLuint unit
= ctx
->Texture
.CurrentUnit
;
991 rmesa
->recheck_texgen
[unit
] = GL_TRUE
;
996 * Allocate a new texture object.
997 * Called via ctx->Driver.NewTextureObject.
998 * Note: this function will be called during context creation to
999 * allocate the default texture objects.
1000 * Note: we could use containment here to 'derive' the driver-specific
1001 * texture object from the core mesa gl_texture_object. Not done at this time.
1002 * Fixup MaxAnisotropy according to user preference.
1004 static struct gl_texture_object
*
1005 r200NewTextureObject( GLcontext
*ctx
, GLuint name
, GLenum target
)
1007 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1008 struct gl_texture_object
*obj
;
1009 obj
= _mesa_new_texture_object(ctx
, name
, target
);
1012 obj
->MaxAnisotropy
= rmesa
->initialMaxAnisotropy
;
1013 r200AllocTexObj( obj
);
1018 void r200InitTextureFuncs( struct dd_function_table
*functions
)
1020 /* Note: we only plug in the functions we implement in the driver
1021 * since _mesa_init_driver_functions() was already called.
1023 functions
->ChooseTextureFormat
= r200ChooseTextureFormat
;
1024 functions
->TexImage1D
= r200TexImage1D
;
1025 functions
->TexImage2D
= r200TexImage2D
;
1026 #if ENABLE_HW_3D_TEXTURE
1027 functions
->TexImage3D
= r200TexImage3D
;
1029 functions
->TexImage3D
= _mesa_store_teximage3d
;
1031 functions
->TexSubImage1D
= r200TexSubImage1D
;
1032 functions
->TexSubImage2D
= r200TexSubImage2D
;
1033 #if ENABLE_HW_3D_TEXTURE
1034 functions
->TexSubImage3D
= r200TexSubImage3D
;
1036 functions
->TexSubImage3D
= _mesa_store_texsubimage3d
;
1038 functions
->NewTextureObject
= r200NewTextureObject
;
1039 functions
->BindTexture
= r200BindTexture
;
1040 functions
->DeleteTexture
= r200DeleteTexture
;
1041 functions
->IsTextureResident
= driIsTextureResident
;
1043 functions
->TexEnv
= r200TexEnv
;
1044 functions
->TexParameter
= r200TexParameter
;
1045 functions
->TexGen
= r200TexGen
;
1048 /* moved or obsolete code */
1049 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1050 driInitTextureObjects( ctx
, & rmesa
->swapped
,
1051 DRI_TEXMGR_DO_TEXTURE_1D
1052 | DRI_TEXMGR_DO_TEXTURE_2D
);
1054 /* Hack: r200NewTextureObject is not yet installed when the
1055 * default textures are created. Therefore set MaxAnisotropy of the
1056 * default 2D texture now. */
1057 ctx
->Shared
->Default2D
->MaxAnisotropy
= driQueryOptionf (&rmesa
->optionCache
,
1058 "def_max_anisotropy");