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_a8
;
394 case GL_COMPRESSED_LUMINANCE
:
395 return &_mesa_texformat_l8
;
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 return &_mesa_texformat_i8
;
417 if (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
418 type
== GL_UNSIGNED_BYTE
)
419 return &_mesa_texformat_ycbcr
;
421 return &_mesa_texformat_ycbcr_rev
;
424 _mesa_problem(ctx
, "unexpected texture format in %s", __FUNCTION__
);
428 return NULL
; /* never get here */
433 r200ValidateClientStorage( GLcontext
*ctx
, GLenum target
,
434 GLint internalFormat
,
435 GLint srcWidth
, GLint srcHeight
,
436 GLenum format
, GLenum type
, const void *pixels
,
437 const struct gl_pixelstore_attrib
*packing
,
438 struct gl_texture_object
*texObj
,
439 struct gl_texture_image
*texImage
)
442 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
445 fprintf(stderr
, "intformat %s format %s type %s\n",
446 _mesa_lookup_enum_by_nr( internalFormat
),
447 _mesa_lookup_enum_by_nr( format
),
448 _mesa_lookup_enum_by_nr( type
));
450 if (!ctx
->Unpack
.ClientStorage
)
453 if (ctx
->_ImageTransferState
||
454 texImage
->IsCompressed
||
455 texObj
->GenerateMipmap
)
459 /* This list is incomplete, may be different on ppc???
461 switch ( internalFormat
) {
463 if ( format
== GL_BGRA
&& type
== GL_UNSIGNED_INT_8_8_8_8_REV
) {
464 texImage
->TexFormat
= &_mesa_texformat_argb8888
;
471 if ( format
== GL_RGB
&& type
== GL_UNSIGNED_SHORT_5_6_5
) {
472 texImage
->TexFormat
= &_mesa_texformat_rgb565
;
479 if ( format
== GL_YCBCR_MESA
&&
480 type
== GL_UNSIGNED_SHORT_8_8_REV_APPLE
) {
481 texImage
->TexFormat
= &_mesa_texformat_ycbcr_rev
;
483 else if ( format
== GL_YCBCR_MESA
&&
484 (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
485 type
== GL_UNSIGNED_BYTE
)) {
486 texImage
->TexFormat
= &_mesa_texformat_ycbcr
;
496 /* Could deal with these packing issues, but currently don't:
498 if (packing
->SkipPixels
||
500 packing
->SwapBytes
||
506 GLint srcRowStride
= _mesa_image_row_stride(packing
, srcWidth
,
511 fprintf(stderr
, "%s: srcRowStride %d/%x\n",
512 __FUNCTION__
, srcRowStride
, srcRowStride
);
514 /* Could check this later in upload, pitch restrictions could be
515 * relaxed, but would need to store the image pitch somewhere,
516 * as packing details might change before image is uploaded:
518 if (!r200IsGartMemory( rmesa
, pixels
, srcHeight
* srcRowStride
) ||
523 /* Have validated that _mesa_transfer_teximage would be a straight
524 * memcpy at this point. NOTE: future calls to TexSubImage will
525 * overwrite the client data. This is explicitly mentioned in the
528 texImage
->Data
= (void *)pixels
;
529 texImage
->IsClientData
= GL_TRUE
;
530 texImage
->RowStride
= srcRowStride
/ texImage
->TexFormat
->TexelBytes
;
537 static void r200TexImage1D( GLcontext
*ctx
, GLenum target
, GLint level
,
538 GLint internalFormat
,
539 GLint width
, GLint border
,
540 GLenum format
, GLenum type
, const GLvoid
*pixels
,
541 const struct gl_pixelstore_attrib
*packing
,
542 struct gl_texture_object
*texObj
,
543 struct gl_texture_image
*texImage
)
545 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
548 driSwapOutTextureObject( t
);
551 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
553 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
558 /* Note, this will call ChooseTextureFormat */
559 _mesa_store_teximage1d(ctx
, target
, level
, internalFormat
,
560 width
, border
, format
, type
, pixels
,
561 &ctx
->Unpack
, texObj
, texImage
);
563 t
->dirty_images
[0] |= (1 << level
);
567 static void r200TexSubImage1D( GLcontext
*ctx
, GLenum target
, GLint level
,
570 GLenum format
, GLenum type
,
571 const GLvoid
*pixels
,
572 const struct gl_pixelstore_attrib
*packing
,
573 struct gl_texture_object
*texObj
,
574 struct gl_texture_image
*texImage
)
576 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
578 assert( t
); /* this _should_ be true */
580 driSwapOutTextureObject( t
);
583 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
585 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
590 _mesa_store_texsubimage1d(ctx
, target
, level
, xoffset
, width
,
591 format
, type
, pixels
, packing
, texObj
,
594 t
->dirty_images
[0] |= (1 << level
);
598 static void r200TexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
599 GLint internalFormat
,
600 GLint width
, GLint height
, GLint border
,
601 GLenum format
, GLenum type
, const GLvoid
*pixels
,
602 const struct gl_pixelstore_attrib
*packing
,
603 struct gl_texture_object
*texObj
,
604 struct gl_texture_image
*texImage
)
606 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
609 /* which cube face or ordinary 2D image */
611 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
612 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
613 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
614 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
615 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
616 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
617 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
625 driSwapOutTextureObject( t
);
628 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
630 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
635 texImage
->IsClientData
= GL_FALSE
;
637 if (r200ValidateClientStorage( ctx
, target
,
640 format
, type
, pixels
,
641 packing
, texObj
, texImage
)) {
642 if (R200_DEBUG
& DEBUG_TEXTURE
)
643 fprintf(stderr
, "%s: Using client storage\n", __FUNCTION__
);
646 if (R200_DEBUG
& DEBUG_TEXTURE
)
647 fprintf(stderr
, "%s: Using normal storage\n", __FUNCTION__
);
649 /* Normal path: copy (to cached memory) and eventually upload
650 * via another copy to GART memory and then a blit... Could
651 * eliminate one copy by going straight to (permanent) GART.
653 * Note, this will call r200ChooseTextureFormat.
655 _mesa_store_teximage2d(ctx
, target
, level
, internalFormat
,
656 width
, height
, border
, format
, type
, pixels
,
657 &ctx
->Unpack
, texObj
, texImage
);
659 t
->dirty_images
[face
] |= (1 << level
);
664 static void r200TexSubImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
665 GLint xoffset
, GLint yoffset
,
666 GLsizei width
, GLsizei height
,
667 GLenum format
, GLenum type
,
668 const GLvoid
*pixels
,
669 const struct gl_pixelstore_attrib
*packing
,
670 struct gl_texture_object
*texObj
,
671 struct gl_texture_image
*texImage
)
673 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
676 /* which cube face or ordinary 2D image */
678 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
679 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
680 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
681 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
682 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
683 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
684 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
691 assert( t
); /* this _should_ be true */
693 driSwapOutTextureObject( t
);
696 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
698 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
703 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
704 height
, format
, type
, pixels
, packing
, texObj
,
707 t
->dirty_images
[face
] |= (1 << level
);
711 #if ENABLE_HW_3D_TEXTURE
712 static void r200TexImage3D( GLcontext
*ctx
, GLenum target
, GLint level
,
713 GLint internalFormat
,
714 GLint width
, GLint height
, GLint depth
,
716 GLenum format
, GLenum type
, const GLvoid
*pixels
,
717 const struct gl_pixelstore_attrib
*packing
,
718 struct gl_texture_object
*texObj
,
719 struct gl_texture_image
*texImage
)
721 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
724 driSwapOutTextureObject( t
);
727 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
729 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
734 texImage
->IsClientData
= GL_FALSE
;
737 if (r200ValidateClientStorage( ctx
, target
,
740 format
, type
, pixels
,
741 packing
, texObj
, texImage
)) {
742 if (R200_DEBUG
& DEBUG_TEXTURE
)
743 fprintf(stderr
, "%s: Using client storage\n", __FUNCTION__
);
748 if (R200_DEBUG
& DEBUG_TEXTURE
)
749 fprintf(stderr
, "%s: Using normal storage\n", __FUNCTION__
);
751 /* Normal path: copy (to cached memory) and eventually upload
752 * via another copy to GART memory and then a blit... Could
753 * eliminate one copy by going straight to (permanent) GART.
755 * Note, this will call r200ChooseTextureFormat.
757 _mesa_store_teximage3d(ctx
, target
, level
, internalFormat
,
758 width
, height
, depth
, border
,
759 format
, type
, pixels
,
760 &ctx
->Unpack
, texObj
, texImage
);
762 t
->dirty_images
[0] |= (1 << level
);
768 #if ENABLE_HW_3D_TEXTURE
770 r200TexSubImage3D( GLcontext
*ctx
, GLenum target
, GLint level
,
771 GLint xoffset
, GLint yoffset
, GLint zoffset
,
772 GLsizei width
, GLsizei height
, GLsizei depth
,
773 GLenum format
, GLenum type
,
774 const GLvoid
*pixels
,
775 const struct gl_pixelstore_attrib
*packing
,
776 struct gl_texture_object
*texObj
,
777 struct gl_texture_image
*texImage
)
779 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
781 /* fprintf(stderr, "%s\n", __FUNCTION__); */
783 assert( t
); /* this _should_ be true */
785 driSwapOutTextureObject( t
);
788 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
790 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage3D");
793 texObj
->DriverData
= t
;
796 _mesa_store_texsubimage3d(ctx
, target
, level
, xoffset
, yoffset
, zoffset
,
797 width
, height
, depth
,
798 format
, type
, pixels
, packing
, texObj
, texImage
);
800 t
->dirty_images
[0] |= (1 << level
);
806 static void r200TexEnv( GLcontext
*ctx
, GLenum target
,
807 GLenum pname
, const GLfloat
*param
)
809 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
810 GLuint unit
= ctx
->Texture
.CurrentUnit
;
811 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
813 if ( R200_DEBUG
& DEBUG_STATE
) {
814 fprintf( stderr
, "%s( %s )\n",
815 __FUNCTION__
, _mesa_lookup_enum_by_nr( pname
) );
818 /* This is incorrect: Need to maintain this data for each of
819 * GL_TEXTURE_{123}D, GL_TEXTURE_RECTANGLE_NV, etc, and switch
820 * between them according to _ReallyEnabled.
823 case GL_TEXTURE_ENV_COLOR
: {
826 UNCLAMPED_FLOAT_TO_RGBA_CHAN( c
, texUnit
->EnvColor
);
827 envColor
= r200PackColor( 4, c
[0], c
[1], c
[2], c
[3] );
828 if ( rmesa
->hw
.tf
.cmd
[TF_TFACTOR_0
+ unit
] != envColor
) {
829 R200_STATECHANGE( rmesa
, tf
);
830 rmesa
->hw
.tf
.cmd
[TF_TFACTOR_0
+ unit
] = envColor
;
835 case GL_TEXTURE_LOD_BIAS_EXT
: {
838 const int fixed_one
= 0x8000000;
840 /* The R200's LOD bias is a signed 2's complement value with a
841 * range of -16.0 <= bias < 16.0.
843 * NOTE: Add a small bias to the bias for conform mipsel.c test.
846 min
= driQueryOptionb (&rmesa
->optionCache
, "no_neg_lod_bias") ?
848 bias
= CLAMP( bias
, min
, 16.0 );
849 b
= (int)(bias
* fixed_one
) & R200_LOD_BIAS_MASK
;
851 if ( (rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT_X
] & R200_LOD_BIAS_MASK
) != b
) {
852 R200_STATECHANGE( rmesa
, tex
[unit
] );
853 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT_X
] &= ~R200_LOD_BIAS_MASK
;
854 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT_X
] |= b
;
866 * Changes variables and flags for a state update, which will happen at the
867 * next UpdateTextureState
870 static void r200TexParameter( GLcontext
*ctx
, GLenum target
,
871 struct gl_texture_object
*texObj
,
872 GLenum pname
, const GLfloat
*params
)
874 r200TexObjPtr t
= (r200TexObjPtr
) texObj
->DriverData
;
876 if ( R200_DEBUG
& (DEBUG_STATE
|DEBUG_TEXTURE
) ) {
877 fprintf( stderr
, "%s( %s )\n", __FUNCTION__
,
878 _mesa_lookup_enum_by_nr( pname
) );
882 case GL_TEXTURE_MIN_FILTER
:
883 case GL_TEXTURE_MAG_FILTER
:
884 case GL_TEXTURE_MAX_ANISOTROPY_EXT
:
885 r200SetTexMaxAnisotropy( t
, texObj
->MaxAnisotropy
);
886 r200SetTexFilter( t
, texObj
->MinFilter
, texObj
->MagFilter
);
889 case GL_TEXTURE_WRAP_S
:
890 case GL_TEXTURE_WRAP_T
:
891 case GL_TEXTURE_WRAP_R
:
892 r200SetTexWrap( t
, texObj
->WrapS
, texObj
->WrapT
, texObj
->WrapR
);
895 case GL_TEXTURE_BORDER_COLOR
:
896 r200SetTexBorderColor( t
, texObj
->_BorderChan
);
899 case GL_TEXTURE_BASE_LEVEL
:
900 case GL_TEXTURE_MAX_LEVEL
:
901 case GL_TEXTURE_MIN_LOD
:
902 case GL_TEXTURE_MAX_LOD
:
903 /* This isn't the most efficient solution but there doesn't appear to
904 * be a nice alternative. Since there's no LOD clamping,
905 * we just have to rely on loading the right subset of mipmap levels
906 * to simulate a clamped LOD.
908 driSwapOutTextureObject( (driTextureObject
*) t
);
915 /* Mark this texobj as dirty (one bit per tex unit)
917 t
->dirty_state
= TEX_ALL
;
922 static void r200BindTexture( GLcontext
*ctx
, GLenum target
,
923 struct gl_texture_object
*texObj
)
925 if ( R200_DEBUG
& (DEBUG_STATE
|DEBUG_TEXTURE
) ) {
926 fprintf( stderr
, "%s( %p ) unit=%d\n", __FUNCTION__
, (void *)texObj
,
927 ctx
->Texture
.CurrentUnit
);
930 if ( (target
== GL_TEXTURE_1D
)
931 || (target
== GL_TEXTURE_2D
)
932 #if ENABLE_HW_3D_TEXTURE
933 || (target
== GL_TEXTURE_3D
)
935 || (target
== GL_TEXTURE_CUBE_MAP
)
936 || (target
== GL_TEXTURE_RECTANGLE_NV
) ) {
937 assert( texObj
->DriverData
!= NULL
);
942 static void r200DeleteTexture( GLcontext
*ctx
,
943 struct gl_texture_object
*texObj
)
945 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
946 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
948 if ( R200_DEBUG
& (DEBUG_STATE
|DEBUG_TEXTURE
) ) {
949 fprintf( stderr
, "%s( %p (target = %s) )\n", __FUNCTION__
, (void *)texObj
,
950 _mesa_lookup_enum_by_nr( texObj
->Target
) );
955 R200_FIREVERTICES( rmesa
);
958 driDestroyTextureObject( t
);
960 /* Free mipmap images and the texture object itself */
961 _mesa_delete_texture_object(ctx
, texObj
);
965 * - Same GEN_MODE for all active bits
966 * - Same EyePlane/ObjPlane for all active bits when using Eye/Obj
967 * - STRQ presumably all supported (matrix means incoming R values
968 * can end up in STQ, this has implications for vertex support,
969 * presumably ok if maos is used, though?)
971 * Basically impossible to do this on the fly - just collect some
972 * basic info & do the checks from ValidateState().
974 static void r200TexGen( GLcontext
*ctx
,
977 const GLfloat
*params
)
979 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
980 GLuint unit
= ctx
->Texture
.CurrentUnit
;
981 rmesa
->recheck_texgen
[unit
] = GL_TRUE
;
986 * Allocate a new texture object.
987 * Called via ctx->Driver.NewTextureObject.
988 * Note: this function will be called during context creation to
989 * allocate the default texture objects.
990 * Note: we could use containment here to 'derive' the driver-specific
991 * texture object from the core mesa gl_texture_object. Not done at this time.
992 * Fixup MaxAnisotropy according to user preference.
994 static struct gl_texture_object
*
995 r200NewTextureObject( GLcontext
*ctx
, GLuint name
, GLenum target
)
997 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
998 struct gl_texture_object
*obj
;
999 obj
= _mesa_new_texture_object(ctx
, name
, target
);
1002 obj
->MaxAnisotropy
= rmesa
->initialMaxAnisotropy
;
1003 r200AllocTexObj( obj
);
1008 void r200InitTextureFuncs( struct dd_function_table
*functions
)
1010 /* Note: we only plug in the functions we implement in the driver
1011 * since _mesa_init_driver_functions() was already called.
1013 functions
->ChooseTextureFormat
= r200ChooseTextureFormat
;
1014 functions
->TexImage1D
= r200TexImage1D
;
1015 functions
->TexImage2D
= r200TexImage2D
;
1016 #if ENABLE_HW_3D_TEXTURE
1017 functions
->TexImage3D
= r200TexImage3D
;
1019 functions
->TexImage3D
= _mesa_store_teximage3d
;
1021 functions
->TexSubImage1D
= r200TexSubImage1D
;
1022 functions
->TexSubImage2D
= r200TexSubImage2D
;
1023 #if ENABLE_HW_3D_TEXTURE
1024 functions
->TexSubImage3D
= r200TexSubImage3D
;
1026 functions
->TexSubImage3D
= _mesa_store_texsubimage3d
;
1028 functions
->NewTextureObject
= r200NewTextureObject
;
1029 functions
->BindTexture
= r200BindTexture
;
1030 functions
->DeleteTexture
= r200DeleteTexture
;
1031 functions
->IsTextureResident
= driIsTextureResident
;
1033 functions
->TexEnv
= r200TexEnv
;
1034 functions
->TexParameter
= r200TexParameter
;
1035 functions
->TexGen
= r200TexGen
;
1038 /* moved or obsolete code */
1039 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1040 driInitTextureObjects( ctx
, & rmesa
->swapped
,
1041 DRI_TEXMGR_DO_TEXTURE_1D
1042 | DRI_TEXMGR_DO_TEXTURE_2D
);
1044 /* Hack: r200NewTextureObject is not yet installed when the
1045 * default textures are created. Therefore set MaxAnisotropy of the
1046 * default 2D texture now. */
1047 ctx
->Shared
->Default2D
->MaxAnisotropy
= driQueryOptionf (&rmesa
->optionCache
,
1048 "def_max_anisotropy");