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"
48 #include "r200_context.h"
49 #include "r200_state.h"
50 #include "r200_ioctl.h"
51 #include "r200_swtcl.h"
59 * Set the texture wrap modes.
61 * \param t Texture object whose wrap modes are to be set
62 * \param swrap Wrap mode for the \a s texture coordinate
63 * \param twrap Wrap mode for the \a t texture coordinate
66 static void r200SetTexWrap( r200TexObjPtr t
, GLenum swrap
, GLenum twrap
, GLenum rwrap
)
68 GLboolean is_clamp
= GL_FALSE
;
69 GLboolean is_clamp_to_border
= GL_FALSE
;
71 t
->pp_txfilter
&= ~(R200_CLAMP_S_MASK
| R200_CLAMP_T_MASK
| R200_BORDER_MODE_D3D
);
75 t
->pp_txfilter
|= R200_CLAMP_S_WRAP
;
78 t
->pp_txfilter
|= R200_CLAMP_S_CLAMP_GL
;
81 case GL_CLAMP_TO_EDGE
:
82 t
->pp_txfilter
|= R200_CLAMP_S_CLAMP_LAST
;
84 case GL_CLAMP_TO_BORDER
:
85 t
->pp_txfilter
|= R200_CLAMP_S_CLAMP_GL
;
86 is_clamp_to_border
= GL_TRUE
;
88 case GL_MIRRORED_REPEAT
:
89 t
->pp_txfilter
|= R200_CLAMP_S_MIRROR
;
91 case GL_MIRROR_CLAMP_EXT
:
92 t
->pp_txfilter
|= R200_CLAMP_S_MIRROR_CLAMP_GL
;
95 case GL_MIRROR_CLAMP_TO_EDGE_EXT
:
96 t
->pp_txfilter
|= R200_CLAMP_S_MIRROR_CLAMP_LAST
;
98 case GL_MIRROR_CLAMP_TO_BORDER_EXT
:
99 t
->pp_txfilter
|= R200_CLAMP_S_MIRROR_CLAMP_GL
;
100 is_clamp_to_border
= GL_TRUE
;
103 _mesa_problem(NULL
, "bad S wrap mode in %s", __FUNCTION__
);
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
| R200_BORDER_MODE_D3D
;
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__
);
139 t
->pp_txformat_x
&= ~R200_CLAMP_Q_MASK
;
143 t
->pp_txformat_x
|= R200_CLAMP_Q_WRAP
;
146 t
->pp_txformat_x
|= R200_CLAMP_Q_CLAMP_GL
;
149 case GL_CLAMP_TO_EDGE
:
150 t
->pp_txformat_x
|= R200_CLAMP_Q_CLAMP_LAST
;
152 case GL_CLAMP_TO_BORDER
:
153 t
->pp_txformat_x
|= R200_CLAMP_Q_CLAMP_GL
;
154 is_clamp_to_border
= GL_TRUE
;
156 case GL_MIRRORED_REPEAT
:
157 t
->pp_txformat_x
|= R200_CLAMP_Q_MIRROR
;
159 case GL_MIRROR_CLAMP_EXT
:
160 t
->pp_txformat_x
|= R200_CLAMP_Q_MIRROR_CLAMP_GL
;
163 case GL_MIRROR_CLAMP_TO_EDGE_EXT
:
164 t
->pp_txformat_x
|= R200_CLAMP_Q_MIRROR_CLAMP_LAST
;
166 case GL_MIRROR_CLAMP_TO_BORDER_EXT
:
167 t
->pp_txformat_x
|= R200_CLAMP_Q_MIRROR_CLAMP_GL
;
168 is_clamp_to_border
= GL_TRUE
;
171 _mesa_problem(NULL
, "bad R wrap mode in %s", __FUNCTION__
);
174 if ( is_clamp_to_border
) {
175 t
->pp_txfilter
|= R200_BORDER_MODE_D3D
;
178 t
->border_fallback
= (is_clamp
&& is_clamp_to_border
);
181 static void r200SetTexMaxAnisotropy( r200TexObjPtr t
, GLfloat max
)
183 t
->pp_txfilter
&= ~R200_MAX_ANISO_MASK
;
186 t
->pp_txfilter
|= R200_MAX_ANISO_1_TO_1
;
187 } else if ( max
<= 2.0 ) {
188 t
->pp_txfilter
|= R200_MAX_ANISO_2_TO_1
;
189 } else if ( max
<= 4.0 ) {
190 t
->pp_txfilter
|= R200_MAX_ANISO_4_TO_1
;
191 } else if ( max
<= 8.0 ) {
192 t
->pp_txfilter
|= R200_MAX_ANISO_8_TO_1
;
194 t
->pp_txfilter
|= R200_MAX_ANISO_16_TO_1
;
199 * Set the texture magnification and minification modes.
201 * \param t Texture whose filter modes are to be set
202 * \param minf Texture minification mode
203 * \param magf Texture magnification mode
206 static void r200SetTexFilter( r200TexObjPtr t
, GLenum minf
, GLenum magf
)
208 GLuint anisotropy
= (t
->pp_txfilter
& R200_MAX_ANISO_MASK
);
210 t
->pp_txfilter
&= ~(R200_MIN_FILTER_MASK
| R200_MAG_FILTER_MASK
);
211 t
->pp_txformat_x
&= ~R200_VOLUME_FILTER_MASK
;
213 if ( anisotropy
== R200_MAX_ANISO_1_TO_1
) {
216 t
->pp_txfilter
|= R200_MIN_FILTER_NEAREST
;
219 t
->pp_txfilter
|= R200_MIN_FILTER_LINEAR
;
221 case GL_NEAREST_MIPMAP_NEAREST
:
222 t
->pp_txfilter
|= R200_MIN_FILTER_NEAREST_MIP_NEAREST
;
224 case GL_NEAREST_MIPMAP_LINEAR
:
225 t
->pp_txfilter
|= R200_MIN_FILTER_LINEAR_MIP_NEAREST
;
227 case GL_LINEAR_MIPMAP_NEAREST
:
228 t
->pp_txfilter
|= R200_MIN_FILTER_NEAREST_MIP_LINEAR
;
230 case GL_LINEAR_MIPMAP_LINEAR
:
231 t
->pp_txfilter
|= R200_MIN_FILTER_LINEAR_MIP_LINEAR
;
237 t
->pp_txfilter
|= R200_MIN_FILTER_ANISO_NEAREST
;
240 t
->pp_txfilter
|= R200_MIN_FILTER_ANISO_LINEAR
;
242 case GL_NEAREST_MIPMAP_NEAREST
:
243 case GL_LINEAR_MIPMAP_NEAREST
:
244 t
->pp_txfilter
|= R200_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST
;
246 case GL_NEAREST_MIPMAP_LINEAR
:
247 case GL_LINEAR_MIPMAP_LINEAR
:
248 t
->pp_txfilter
|= R200_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR
;
253 /* Note we don't have 3D mipmaps so only use the mag filter setting
254 * to set the 3D texture filter mode.
258 t
->pp_txfilter
|= R200_MAG_FILTER_NEAREST
;
259 t
->pp_txformat_x
|= R200_VOLUME_FILTER_NEAREST
;
262 t
->pp_txfilter
|= R200_MAG_FILTER_LINEAR
;
263 t
->pp_txformat_x
|= R200_VOLUME_FILTER_LINEAR
;
268 static void r200SetTexBorderColor( r200TexObjPtr t
, GLubyte c
[4] )
270 t
->pp_border_color
= r200PackColor( 4, c
[0], c
[1], c
[2], c
[3] );
275 * Allocate space for and load the mesa images into the texture memory block.
276 * This will happen before drawing with a new texture, or drawing with a
277 * texture after it was swapped out or teximaged again.
280 static r200TexObjPtr
r200AllocTexObj( struct gl_texture_object
*texObj
)
284 t
= CALLOC_STRUCT( r200_tex_obj
);
285 texObj
->DriverData
= t
;
287 if ( R200_DEBUG
& DEBUG_TEXTURE
) {
288 fprintf( stderr
, "%s( %p, %p )\n", __FUNCTION__
, (void *)texObj
,
292 /* Initialize non-image-dependent parts of the state:
294 t
->base
.tObj
= texObj
;
295 t
->border_fallback
= GL_FALSE
;
297 make_empty_list( & t
->base
);
299 r200SetTexWrap( t
, texObj
->WrapS
, texObj
->WrapT
, texObj
->WrapR
);
300 r200SetTexMaxAnisotropy( t
, texObj
->MaxAnisotropy
);
301 r200SetTexFilter( t
, texObj
->MinFilter
, texObj
->MagFilter
);
302 r200SetTexBorderColor( t
, texObj
->_BorderChan
);
309 static const struct gl_texture_format
*
310 r200ChooseTextureFormat( GLcontext
*ctx
, GLint internalFormat
,
311 GLenum format
, GLenum type
)
313 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
314 const GLboolean do32bpt
=
315 ( rmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_32
);
316 const GLboolean force16bpt
=
317 ( rmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_FORCE_16
);
320 switch ( internalFormat
) {
323 case GL_COMPRESSED_RGBA
:
325 case GL_UNSIGNED_INT_10_10_10_2
:
326 case GL_UNSIGNED_INT_2_10_10_10_REV
:
327 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb1555
;
328 case GL_UNSIGNED_SHORT_4_4_4_4
:
329 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
330 return &_mesa_texformat_argb4444
;
331 case GL_UNSIGNED_SHORT_5_5_5_1
:
332 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
333 return &_mesa_texformat_argb1555
;
335 return do32bpt
? &_mesa_texformat_rgba8888
: &_mesa_texformat_argb4444
;
340 case GL_COMPRESSED_RGB
:
342 case GL_UNSIGNED_SHORT_4_4_4_4
:
343 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
344 return &_mesa_texformat_argb4444
;
345 case GL_UNSIGNED_SHORT_5_5_5_1
:
346 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
347 return &_mesa_texformat_argb1555
;
348 case GL_UNSIGNED_SHORT_5_6_5
:
349 case GL_UNSIGNED_SHORT_5_6_5_REV
:
350 return &_mesa_texformat_rgb565
;
352 return do32bpt
? &_mesa_texformat_rgba8888
: &_mesa_texformat_rgb565
;
360 &_mesa_texformat_rgba8888
: &_mesa_texformat_argb4444
;
364 return &_mesa_texformat_argb4444
;
367 return &_mesa_texformat_argb1555
;
373 return !force16bpt
? &_mesa_texformat_rgba8888
: &_mesa_texformat_rgb565
;
378 return &_mesa_texformat_rgb565
;
385 case GL_COMPRESSED_ALPHA
:
386 return &_mesa_texformat_al88
;
394 case GL_COMPRESSED_LUMINANCE
:
395 return &_mesa_texformat_al88
;
398 case GL_LUMINANCE_ALPHA
:
399 case GL_LUMINANCE4_ALPHA4
:
400 case GL_LUMINANCE6_ALPHA2
:
401 case GL_LUMINANCE8_ALPHA8
:
402 case GL_LUMINANCE12_ALPHA4
:
403 case GL_LUMINANCE12_ALPHA12
:
404 case GL_LUMINANCE16_ALPHA16
:
405 case GL_COMPRESSED_LUMINANCE_ALPHA
:
406 return &_mesa_texformat_al88
;
413 case GL_COMPRESSED_INTENSITY
:
414 /* At the moment, glean & conform both fail using the i8 internal
417 return &_mesa_texformat_al88
;
418 /* return &_mesa_texformat_i8; */
421 if (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
422 type
== GL_UNSIGNED_BYTE
)
423 return &_mesa_texformat_ycbcr
;
425 return &_mesa_texformat_ycbcr_rev
;
428 _mesa_problem(ctx
, "unexpected texture format in %s", __FUNCTION__
);
432 return NULL
; /* never get here */
437 r200ValidateClientStorage( GLcontext
*ctx
, GLenum target
,
438 GLint internalFormat
,
439 GLint srcWidth
, GLint srcHeight
,
440 GLenum format
, GLenum type
, const void *pixels
,
441 const struct gl_pixelstore_attrib
*packing
,
442 struct gl_texture_object
*texObj
,
443 struct gl_texture_image
*texImage
)
446 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
449 fprintf(stderr
, "intformat %s format %s type %s\n",
450 _mesa_lookup_enum_by_nr( internalFormat
),
451 _mesa_lookup_enum_by_nr( format
),
452 _mesa_lookup_enum_by_nr( type
));
454 if (!ctx
->Unpack
.ClientStorage
)
457 if (ctx
->_ImageTransferState
||
458 texImage
->IsCompressed
||
459 texObj
->GenerateMipmap
)
463 /* This list is incomplete, may be different on ppc???
465 switch ( internalFormat
) {
467 if ( format
== GL_BGRA
&& type
== GL_UNSIGNED_INT_8_8_8_8_REV
) {
468 texImage
->TexFormat
= &_mesa_texformat_argb8888
;
475 if ( format
== GL_RGB
&& type
== GL_UNSIGNED_SHORT_5_6_5
) {
476 texImage
->TexFormat
= &_mesa_texformat_rgb565
;
483 if ( format
== GL_YCBCR_MESA
&&
484 type
== GL_UNSIGNED_SHORT_8_8_REV_APPLE
) {
485 texImage
->TexFormat
= &_mesa_texformat_ycbcr_rev
;
487 else if ( format
== GL_YCBCR_MESA
&&
488 (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
489 type
== GL_UNSIGNED_BYTE
)) {
490 texImage
->TexFormat
= &_mesa_texformat_ycbcr
;
500 /* Could deal with these packing issues, but currently don't:
502 if (packing
->SkipPixels
||
504 packing
->SwapBytes
||
510 GLint srcRowStride
= _mesa_image_row_stride(packing
, srcWidth
,
515 fprintf(stderr
, "%s: srcRowStride %d/%x\n",
516 __FUNCTION__
, srcRowStride
, srcRowStride
);
518 /* Could check this later in upload, pitch restrictions could be
519 * relaxed, but would need to store the image pitch somewhere,
520 * as packing details might change before image is uploaded:
522 if (!r200IsGartMemory( rmesa
, pixels
, srcHeight
* srcRowStride
) ||
527 /* Have validated that _mesa_transfer_teximage would be a straight
528 * memcpy at this point. NOTE: future calls to TexSubImage will
529 * overwrite the client data. This is explicitly mentioned in the
532 texImage
->Data
= (void *)pixels
;
533 texImage
->IsClientData
= GL_TRUE
;
534 texImage
->RowStride
= srcRowStride
/ texImage
->TexFormat
->TexelBytes
;
541 static void r200TexImage1D( GLcontext
*ctx
, GLenum target
, GLint level
,
542 GLint internalFormat
,
543 GLint width
, GLint border
,
544 GLenum format
, GLenum type
, const GLvoid
*pixels
,
545 const struct gl_pixelstore_attrib
*packing
,
546 struct gl_texture_object
*texObj
,
547 struct gl_texture_image
*texImage
)
549 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
552 driSwapOutTextureObject( t
);
555 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
557 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
562 /* Note, this will call ChooseTextureFormat */
563 _mesa_store_teximage1d(ctx
, target
, level
, internalFormat
,
564 width
, border
, format
, type
, pixels
,
565 &ctx
->Unpack
, texObj
, texImage
);
567 t
->dirty_images
[0] |= (1 << level
);
571 static void r200TexSubImage1D( GLcontext
*ctx
, GLenum target
, GLint level
,
574 GLenum format
, GLenum type
,
575 const GLvoid
*pixels
,
576 const struct gl_pixelstore_attrib
*packing
,
577 struct gl_texture_object
*texObj
,
578 struct gl_texture_image
*texImage
)
580 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
582 assert( t
); /* this _should_ be true */
584 driSwapOutTextureObject( t
);
587 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
589 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
594 _mesa_store_texsubimage1d(ctx
, target
, level
, xoffset
, width
,
595 format
, type
, pixels
, packing
, texObj
,
598 t
->dirty_images
[0] |= (1 << level
);
602 static void r200TexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
603 GLint internalFormat
,
604 GLint width
, GLint height
, GLint border
,
605 GLenum format
, GLenum type
, const GLvoid
*pixels
,
606 const struct gl_pixelstore_attrib
*packing
,
607 struct gl_texture_object
*texObj
,
608 struct gl_texture_image
*texImage
)
610 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
613 /* which cube face or ordinary 2D image */
615 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
616 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
617 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
618 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
619 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
620 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
621 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
629 driSwapOutTextureObject( t
);
632 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
634 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
639 texImage
->IsClientData
= GL_FALSE
;
641 if (r200ValidateClientStorage( ctx
, target
,
644 format
, type
, pixels
,
645 packing
, texObj
, texImage
)) {
646 if (R200_DEBUG
& DEBUG_TEXTURE
)
647 fprintf(stderr
, "%s: Using client storage\n", __FUNCTION__
);
650 if (R200_DEBUG
& DEBUG_TEXTURE
)
651 fprintf(stderr
, "%s: Using normal storage\n", __FUNCTION__
);
653 /* Normal path: copy (to cached memory) and eventually upload
654 * via another copy to GART memory and then a blit... Could
655 * eliminate one copy by going straight to (permanent) GART.
657 * Note, this will call r200ChooseTextureFormat.
659 _mesa_store_teximage2d(ctx
, target
, level
, internalFormat
,
660 width
, height
, border
, format
, type
, pixels
,
661 &ctx
->Unpack
, texObj
, texImage
);
663 t
->dirty_images
[face
] |= (1 << level
);
668 static void r200TexSubImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
669 GLint xoffset
, GLint yoffset
,
670 GLsizei width
, GLsizei height
,
671 GLenum format
, GLenum type
,
672 const GLvoid
*pixels
,
673 const struct gl_pixelstore_attrib
*packing
,
674 struct gl_texture_object
*texObj
,
675 struct gl_texture_image
*texImage
)
677 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
680 /* which cube face or ordinary 2D image */
682 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
683 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
684 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
685 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
686 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
687 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
688 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
695 assert( t
); /* this _should_ be true */
697 driSwapOutTextureObject( t
);
700 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
702 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
707 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
708 height
, format
, type
, pixels
, packing
, texObj
,
711 t
->dirty_images
[face
] |= (1 << level
);
715 #if ENABLE_HW_3D_TEXTURE
716 static void r200TexImage3D( GLcontext
*ctx
, GLenum target
, GLint level
,
717 GLint internalFormat
,
718 GLint width
, GLint height
, GLint depth
,
720 GLenum format
, GLenum type
, const GLvoid
*pixels
,
721 const struct gl_pixelstore_attrib
*packing
,
722 struct gl_texture_object
*texObj
,
723 struct gl_texture_image
*texImage
)
725 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
728 driSwapOutTextureObject( t
);
731 t
= r200AllocTexObj( texObj
);
733 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
738 texImage
->IsClientData
= GL_FALSE
;
741 if (r200ValidateClientStorage( ctx
, target
,
744 format
, type
, pixels
,
745 packing
, texObj
, texImage
)) {
746 if (R200_DEBUG
& DEBUG_TEXTURE
)
747 fprintf(stderr
, "%s: Using client storage\n", __FUNCTION__
);
752 if (R200_DEBUG
& DEBUG_TEXTURE
)
753 fprintf(stderr
, "%s: Using normal storage\n", __FUNCTION__
);
755 /* Normal path: copy (to cached memory) and eventually upload
756 * via another copy to GART memory and then a blit... Could
757 * eliminate one copy by going straight to (permanent) GART.
759 * Note, this will call r200ChooseTextureFormat.
761 _mesa_store_teximage3d(ctx
, target
, level
, internalFormat
,
762 width
, height
, depth
, border
,
763 format
, type
, pixels
,
764 &ctx
->Unpack
, texObj
, texImage
);
766 t
->dirty_images
[0] |= (1 << level
);
772 #if ENABLE_HW_3D_TEXTURE
774 r200TexSubImage3D( GLcontext
*ctx
, GLenum target
, GLint level
,
775 GLint xoffset
, GLint yoffset
, GLint zoffset
,
776 GLsizei width
, GLsizei height
, GLsizei depth
,
777 GLenum format
, GLenum type
,
778 const GLvoid
*pixels
,
779 const struct gl_pixelstore_attrib
*packing
,
780 struct gl_texture_object
*texObj
,
781 struct gl_texture_image
*texImage
)
783 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
785 /* fprintf(stderr, "%s\n", __FUNCTION__); */
787 assert( t
); /* this _should_ be true */
789 driSwapOutTextureObject( t
);
792 t
= r200AllocTexObj(texObj
);
794 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage3D");
797 texObj
->DriverData
= t
;
800 _mesa_store_texsubimage3d(ctx
, target
, level
, xoffset
, yoffset
, zoffset
,
801 width
, height
, depth
,
802 format
, type
, pixels
, packing
, texObj
, texImage
);
804 t
->dirty_images
[0] |= (1 << level
);
810 static void r200TexEnv( GLcontext
*ctx
, GLenum target
,
811 GLenum pname
, const GLfloat
*param
)
813 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
814 GLuint unit
= ctx
->Texture
.CurrentUnit
;
815 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
817 if ( R200_DEBUG
& DEBUG_STATE
) {
818 fprintf( stderr
, "%s( %s )\n",
819 __FUNCTION__
, _mesa_lookup_enum_by_nr( pname
) );
822 /* This is incorrect: Need to maintain this data for each of
823 * GL_TEXTURE_{123}D, GL_TEXTURE_RECTANGLE_NV, etc, and switch
824 * between them according to _ReallyEnabled.
827 case GL_TEXTURE_ENV_COLOR
: {
830 UNCLAMPED_FLOAT_TO_RGBA_CHAN( c
, texUnit
->EnvColor
);
831 envColor
= r200PackColor( 4, c
[0], c
[1], c
[2], c
[3] );
832 if ( rmesa
->hw
.tf
.cmd
[TF_TFACTOR_0
+ unit
] != envColor
) {
833 R200_STATECHANGE( rmesa
, tf
);
834 rmesa
->hw
.tf
.cmd
[TF_TFACTOR_0
+ unit
] = envColor
;
839 case GL_TEXTURE_LOD_BIAS_EXT
: {
842 const int fixed_one
= 0x8000000;
844 /* The R200's LOD bias is a signed 2's complement value with a
845 * range of -16.0 <= bias < 16.0.
847 * NOTE: Add a small bias to the bias for conform mipsel.c test.
850 min
= driQueryOptionb (&rmesa
->optionCache
, "no_neg_lod_bias") ?
852 bias
= CLAMP( bias
, min
, 16.0 );
853 b
= (int)(bias
* fixed_one
) & R200_LOD_BIAS_MASK
;
855 if ( (rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT_X
] & R200_LOD_BIAS_MASK
) != b
) {
856 R200_STATECHANGE( rmesa
, tex
[unit
] );
857 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT_X
] &= ~R200_LOD_BIAS_MASK
;
858 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT_X
] |= b
;
870 * Changes variables and flags for a state update, which will happen at the
871 * next UpdateTextureState
874 static void r200TexParameter( GLcontext
*ctx
, GLenum target
,
875 struct gl_texture_object
*texObj
,
876 GLenum pname
, const GLfloat
*params
)
878 r200TexObjPtr t
= (r200TexObjPtr
) texObj
->DriverData
;
880 if ( R200_DEBUG
& (DEBUG_STATE
|DEBUG_TEXTURE
) ) {
881 fprintf( stderr
, "%s( %s )\n", __FUNCTION__
,
882 _mesa_lookup_enum_by_nr( pname
) );
886 case GL_TEXTURE_MIN_FILTER
:
887 case GL_TEXTURE_MAG_FILTER
:
888 case GL_TEXTURE_MAX_ANISOTROPY_EXT
:
889 r200SetTexMaxAnisotropy( t
, texObj
->MaxAnisotropy
);
890 r200SetTexFilter( t
, texObj
->MinFilter
, texObj
->MagFilter
);
893 case GL_TEXTURE_WRAP_S
:
894 case GL_TEXTURE_WRAP_T
:
895 case GL_TEXTURE_WRAP_R
:
896 r200SetTexWrap( t
, texObj
->WrapS
, texObj
->WrapT
, texObj
->WrapR
);
899 case GL_TEXTURE_BORDER_COLOR
:
900 r200SetTexBorderColor( t
, texObj
->_BorderChan
);
903 case GL_TEXTURE_BASE_LEVEL
:
904 case GL_TEXTURE_MAX_LEVEL
:
905 case GL_TEXTURE_MIN_LOD
:
906 case GL_TEXTURE_MAX_LOD
:
907 /* This isn't the most efficient solution but there doesn't appear to
908 * be a nice alternative. Since there's no LOD clamping,
909 * we just have to rely on loading the right subset of mipmap levels
910 * to simulate a clamped LOD.
912 driSwapOutTextureObject( (driTextureObject
*) t
);
919 /* Mark this texobj as dirty (one bit per tex unit)
921 t
->dirty_state
= TEX_ALL
;
926 static void r200BindTexture( GLcontext
*ctx
, GLenum target
,
927 struct gl_texture_object
*texObj
)
929 if ( R200_DEBUG
& (DEBUG_STATE
|DEBUG_TEXTURE
) ) {
930 fprintf( stderr
, "%s( %p ) unit=%d\n", __FUNCTION__
, (void *)texObj
,
931 ctx
->Texture
.CurrentUnit
);
934 if ( (target
== GL_TEXTURE_1D
)
935 || (target
== GL_TEXTURE_2D
)
936 #if ENABLE_HW_3D_TEXTURE
937 || (target
== GL_TEXTURE_3D
)
939 || (target
== GL_TEXTURE_CUBE_MAP
)
940 || (target
== GL_TEXTURE_RECTANGLE_NV
) ) {
941 assert( texObj
->DriverData
!= NULL
);
946 static void r200DeleteTexture( GLcontext
*ctx
,
947 struct gl_texture_object
*texObj
)
949 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
950 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
952 if ( R200_DEBUG
& (DEBUG_STATE
|DEBUG_TEXTURE
) ) {
953 fprintf( stderr
, "%s( %p (target = %s) )\n", __FUNCTION__
, (void *)texObj
,
954 _mesa_lookup_enum_by_nr( texObj
->Target
) );
959 R200_FIREVERTICES( rmesa
);
962 driDestroyTextureObject( t
);
964 /* Free mipmap images and the texture object itself */
965 _mesa_delete_texture_object(ctx
, texObj
);
969 * - Same GEN_MODE for all active bits
970 * - Same EyePlane/ObjPlane for all active bits when using Eye/Obj
971 * - STRQ presumably all supported (matrix means incoming R values
972 * can end up in STQ, this has implications for vertex support,
973 * presumably ok if maos is used, though?)
975 * Basically impossible to do this on the fly - just collect some
976 * basic info & do the checks from ValidateState().
978 static void r200TexGen( GLcontext
*ctx
,
981 const GLfloat
*params
)
983 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
984 GLuint unit
= ctx
->Texture
.CurrentUnit
;
985 rmesa
->recheck_texgen
[unit
] = GL_TRUE
;
990 * Allocate a new texture object.
991 * Called via ctx->Driver.NewTextureObject.
992 * Note: this function will be called during context creation to
993 * allocate the default texture objects.
994 * Note: we could use containment here to 'derive' the driver-specific
995 * texture object from the core mesa gl_texture_object. Not done at this time.
996 * Fixup MaxAnisotropy according to user preference.
998 static struct gl_texture_object
*
999 r200NewTextureObject( GLcontext
*ctx
, GLuint name
, GLenum target
)
1001 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1002 struct gl_texture_object
*obj
;
1003 obj
= _mesa_new_texture_object(ctx
, name
, target
);
1006 obj
->MaxAnisotropy
= rmesa
->initialMaxAnisotropy
;
1007 r200AllocTexObj( obj
);
1012 void r200InitTextureFuncs( struct dd_function_table
*functions
)
1014 /* Note: we only plug in the functions we implement in the driver
1015 * since _mesa_init_driver_functions() was already called.
1017 functions
->ChooseTextureFormat
= r200ChooseTextureFormat
;
1018 functions
->TexImage1D
= r200TexImage1D
;
1019 functions
->TexImage2D
= r200TexImage2D
;
1020 #if ENABLE_HW_3D_TEXTURE
1021 functions
->TexImage3D
= r200TexImage3D
;
1023 functions
->TexImage3D
= _mesa_store_teximage3d
;
1025 functions
->TexSubImage1D
= r200TexSubImage1D
;
1026 functions
->TexSubImage2D
= r200TexSubImage2D
;
1027 #if ENABLE_HW_3D_TEXTURE
1028 functions
->TexSubImage3D
= r200TexSubImage3D
;
1030 functions
->TexSubImage3D
= _mesa_store_texsubimage3d
;
1032 functions
->NewTextureObject
= r200NewTextureObject
;
1033 functions
->BindTexture
= r200BindTexture
;
1034 functions
->DeleteTexture
= r200DeleteTexture
;
1035 functions
->IsTextureResident
= driIsTextureResident
;
1037 functions
->TexEnv
= r200TexEnv
;
1038 functions
->TexParameter
= r200TexParameter
;
1039 functions
->TexGen
= r200TexGen
;
1042 /* moved or obsolete code */
1043 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1044 driInitTextureObjects( ctx
, & rmesa
->swapped
,
1045 DRI_TEXMGR_DO_TEXTURE_1D
1046 | DRI_TEXMGR_DO_TEXTURE_2D
);
1048 /* Hack: r200NewTextureObject is not yet installed when the
1049 * default textures are created. Therefore set MaxAnisotropy of the
1050 * default 2D texture now. */
1051 ctx
->Shared
->Default2D
->MaxAnisotropy
= driQueryOptionf (&rmesa
->optionCache
,
1052 "def_max_anisotropy");