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
? _dri_texformat_argb8888
: _dri_texformat_argb1555
;
328 case GL_UNSIGNED_SHORT_4_4_4_4
:
329 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
330 return _dri_texformat_argb4444
;
331 case GL_UNSIGNED_SHORT_5_5_5_1
:
332 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
333 return _dri_texformat_argb1555
;
335 return do32bpt
? _dri_texformat_rgba8888
: _dri_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 _dri_texformat_argb4444
;
345 case GL_UNSIGNED_SHORT_5_5_5_1
:
346 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
347 return _dri_texformat_argb1555
;
348 case GL_UNSIGNED_SHORT_5_6_5
:
349 case GL_UNSIGNED_SHORT_5_6_5_REV
:
350 return _dri_texformat_rgb565
;
352 return do32bpt
? _dri_texformat_rgba8888
: _dri_texformat_rgb565
;
360 _dri_texformat_rgba8888
: _dri_texformat_argb4444
;
364 return _dri_texformat_argb4444
;
367 return _dri_texformat_argb1555
;
373 return !force16bpt
? _dri_texformat_rgba8888
: _dri_texformat_rgb565
;
378 return _dri_texformat_rgb565
;
385 case GL_COMPRESSED_ALPHA
:
386 return _dri_texformat_a8
;
394 case GL_COMPRESSED_LUMINANCE
:
395 return _dri_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 _dri_texformat_al88
;
413 case GL_COMPRESSED_INTENSITY
:
414 return _dri_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
;
425 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
426 return &_mesa_texformat_rgb_dxt1
;
428 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
429 return &_mesa_texformat_rgba_dxt1
;
433 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
434 return &_mesa_texformat_rgba_dxt3
;
436 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
437 return &_mesa_texformat_rgba_dxt5
;
441 "unexpected internalFormat 0x%x in r200ChooseTextureFormat",
442 (int) internalFormat
);
446 return NULL
; /* never get here */
451 r200ValidateClientStorage( GLcontext
*ctx
, GLenum target
,
452 GLint internalFormat
,
453 GLint srcWidth
, GLint srcHeight
,
454 GLenum format
, GLenum type
, const void *pixels
,
455 const struct gl_pixelstore_attrib
*packing
,
456 struct gl_texture_object
*texObj
,
457 struct gl_texture_image
*texImage
)
460 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
463 fprintf(stderr
, "intformat %s format %s type %s\n",
464 _mesa_lookup_enum_by_nr( internalFormat
),
465 _mesa_lookup_enum_by_nr( format
),
466 _mesa_lookup_enum_by_nr( type
));
468 if (!ctx
->Unpack
.ClientStorage
)
471 if (ctx
->_ImageTransferState
||
472 texImage
->IsCompressed
||
473 texObj
->GenerateMipmap
)
477 /* This list is incomplete, may be different on ppc???
479 switch ( internalFormat
) {
481 if ( format
== GL_BGRA
&& type
== GL_UNSIGNED_INT_8_8_8_8_REV
) {
482 texImage
->TexFormat
= _dri_texformat_argb8888
;
489 if ( format
== GL_RGB
&& type
== GL_UNSIGNED_SHORT_5_6_5
) {
490 texImage
->TexFormat
= _dri_texformat_rgb565
;
497 if ( format
== GL_YCBCR_MESA
&&
498 type
== GL_UNSIGNED_SHORT_8_8_REV_APPLE
) {
499 texImage
->TexFormat
= &_mesa_texformat_ycbcr_rev
;
501 else if ( format
== GL_YCBCR_MESA
&&
502 (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
503 type
== GL_UNSIGNED_BYTE
)) {
504 texImage
->TexFormat
= &_mesa_texformat_ycbcr
;
514 /* Could deal with these packing issues, but currently don't:
516 if (packing
->SkipPixels
||
518 packing
->SwapBytes
||
524 GLint srcRowStride
= _mesa_image_row_stride(packing
, srcWidth
,
529 fprintf(stderr
, "%s: srcRowStride %d/%x\n",
530 __FUNCTION__
, srcRowStride
, srcRowStride
);
532 /* Could check this later in upload, pitch restrictions could be
533 * relaxed, but would need to store the image pitch somewhere,
534 * as packing details might change before image is uploaded:
536 if (!r200IsGartMemory( rmesa
, pixels
, srcHeight
* srcRowStride
) ||
541 /* Have validated that _mesa_transfer_teximage would be a straight
542 * memcpy at this point. NOTE: future calls to TexSubImage will
543 * overwrite the client data. This is explicitly mentioned in the
546 texImage
->Data
= (void *)pixels
;
547 texImage
->IsClientData
= GL_TRUE
;
548 texImage
->RowStride
= srcRowStride
/ texImage
->TexFormat
->TexelBytes
;
555 static void r200TexImage1D( GLcontext
*ctx
, GLenum target
, GLint level
,
556 GLint internalFormat
,
557 GLint width
, GLint border
,
558 GLenum format
, GLenum type
, const GLvoid
*pixels
,
559 const struct gl_pixelstore_attrib
*packing
,
560 struct gl_texture_object
*texObj
,
561 struct gl_texture_image
*texImage
)
563 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
566 driSwapOutTextureObject( t
);
569 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
571 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
576 /* Note, this will call ChooseTextureFormat */
577 _mesa_store_teximage1d(ctx
, target
, level
, internalFormat
,
578 width
, border
, format
, type
, pixels
,
579 &ctx
->Unpack
, texObj
, texImage
);
581 t
->dirty_images
[0] |= (1 << level
);
585 static void r200TexSubImage1D( GLcontext
*ctx
, GLenum target
, GLint level
,
588 GLenum format
, GLenum type
,
589 const GLvoid
*pixels
,
590 const struct gl_pixelstore_attrib
*packing
,
591 struct gl_texture_object
*texObj
,
592 struct gl_texture_image
*texImage
)
594 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
596 assert( t
); /* this _should_ be true */
598 driSwapOutTextureObject( t
);
601 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
603 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
608 _mesa_store_texsubimage1d(ctx
, target
, level
, xoffset
, width
,
609 format
, type
, pixels
, packing
, texObj
,
612 t
->dirty_images
[0] |= (1 << level
);
616 static void r200TexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
617 GLint internalFormat
,
618 GLint width
, GLint height
, GLint border
,
619 GLenum format
, GLenum type
, const GLvoid
*pixels
,
620 const struct gl_pixelstore_attrib
*packing
,
621 struct gl_texture_object
*texObj
,
622 struct gl_texture_image
*texImage
)
624 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
627 /* which cube face or ordinary 2D image */
629 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
630 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
631 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
632 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
633 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
634 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
635 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
643 driSwapOutTextureObject( t
);
646 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
648 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
653 texImage
->IsClientData
= GL_FALSE
;
655 if (r200ValidateClientStorage( ctx
, target
,
658 format
, type
, pixels
,
659 packing
, texObj
, texImage
)) {
660 if (R200_DEBUG
& DEBUG_TEXTURE
)
661 fprintf(stderr
, "%s: Using client storage\n", __FUNCTION__
);
664 if (R200_DEBUG
& DEBUG_TEXTURE
)
665 fprintf(stderr
, "%s: Using normal storage\n", __FUNCTION__
);
667 /* Normal path: copy (to cached memory) and eventually upload
668 * via another copy to GART memory and then a blit... Could
669 * eliminate one copy by going straight to (permanent) GART.
671 * Note, this will call r200ChooseTextureFormat.
673 _mesa_store_teximage2d(ctx
, target
, level
, internalFormat
,
674 width
, height
, border
, format
, type
, pixels
,
675 &ctx
->Unpack
, texObj
, texImage
);
677 t
->dirty_images
[face
] |= (1 << level
);
682 static void r200TexSubImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
683 GLint xoffset
, GLint yoffset
,
684 GLsizei width
, GLsizei height
,
685 GLenum format
, GLenum type
,
686 const GLvoid
*pixels
,
687 const struct gl_pixelstore_attrib
*packing
,
688 struct gl_texture_object
*texObj
,
689 struct gl_texture_image
*texImage
)
691 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
694 /* which cube face or ordinary 2D image */
696 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
697 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
698 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
699 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
700 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
701 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
702 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
709 assert( t
); /* this _should_ be true */
711 driSwapOutTextureObject( t
);
714 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
716 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
721 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
722 height
, format
, type
, pixels
, packing
, texObj
,
725 t
->dirty_images
[face
] |= (1 << level
);
729 static void r200CompressedTexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
730 GLint internalFormat
,
731 GLint width
, GLint height
, GLint border
,
732 GLsizei imageSize
, const GLvoid
*data
,
733 struct gl_texture_object
*texObj
,
734 struct gl_texture_image
*texImage
)
736 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
739 /* which cube face or ordinary 2D image */
741 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
742 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
743 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
744 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
745 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
746 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
747 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
755 driSwapOutTextureObject( t
);
758 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
760 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2D");
765 texImage
->IsClientData
= GL_FALSE
;
766 /* can't call this, different parameters. Would never evaluate to true anyway currently
767 if (r200ValidateClientStorage( ctx, target,
770 format, type, pixels,
771 packing, texObj, texImage)) {
772 if (R200_DEBUG & DEBUG_TEXTURE)
773 fprintf(stderr, "%s: Using client storage\n", __FUNCTION__);
776 if (R200_DEBUG
& DEBUG_TEXTURE
)
777 fprintf(stderr
, "%s: Using normal storage\n", __FUNCTION__
);
779 /* Normal path: copy (to cached memory) and eventually upload
780 * via another copy to GART memory and then a blit... Could
781 * eliminate one copy by going straight to (permanent) GART.
783 * Note, this will call r200ChooseTextureFormat.
785 _mesa_store_compressed_teximage2d(ctx
, target
, level
, internalFormat
, width
,
786 height
, border
, imageSize
, data
, texObj
, texImage
);
788 t
->dirty_images
[face
] |= (1 << level
);
793 static void r200CompressedTexSubImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
794 GLint xoffset
, GLint yoffset
,
795 GLsizei width
, GLsizei height
,
797 GLsizei imageSize
, const GLvoid
*data
,
798 struct gl_texture_object
*texObj
,
799 struct gl_texture_image
*texImage
)
801 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
805 /* which cube face or ordinary 2D image */
807 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
808 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
809 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
810 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
811 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
812 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
813 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
820 assert( t
); /* this _should_ be true */
822 driSwapOutTextureObject( t
);
825 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
827 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexSubImage2D");
832 _mesa_store_compressed_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
833 height
, format
, imageSize
, data
, texObj
, texImage
);
835 t
->dirty_images
[face
] |= (1 << level
);
839 #if ENABLE_HW_3D_TEXTURE
840 static void r200TexImage3D( GLcontext
*ctx
, GLenum target
, GLint level
,
841 GLint internalFormat
,
842 GLint width
, GLint height
, GLint depth
,
844 GLenum format
, GLenum type
, const GLvoid
*pixels
,
845 const struct gl_pixelstore_attrib
*packing
,
846 struct gl_texture_object
*texObj
,
847 struct gl_texture_image
*texImage
)
849 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
852 driSwapOutTextureObject( t
);
855 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
857 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
862 texImage
->IsClientData
= GL_FALSE
;
865 if (r200ValidateClientStorage( ctx
, target
,
868 format
, type
, pixels
,
869 packing
, texObj
, texImage
)) {
870 if (R200_DEBUG
& DEBUG_TEXTURE
)
871 fprintf(stderr
, "%s: Using client storage\n", __FUNCTION__
);
876 if (R200_DEBUG
& DEBUG_TEXTURE
)
877 fprintf(stderr
, "%s: Using normal storage\n", __FUNCTION__
);
879 /* Normal path: copy (to cached memory) and eventually upload
880 * via another copy to GART memory and then a blit... Could
881 * eliminate one copy by going straight to (permanent) GART.
883 * Note, this will call r200ChooseTextureFormat.
885 _mesa_store_teximage3d(ctx
, target
, level
, internalFormat
,
886 width
, height
, depth
, border
,
887 format
, type
, pixels
,
888 &ctx
->Unpack
, texObj
, texImage
);
890 t
->dirty_images
[0] |= (1 << level
);
896 #if ENABLE_HW_3D_TEXTURE
898 r200TexSubImage3D( GLcontext
*ctx
, GLenum target
, GLint level
,
899 GLint xoffset
, GLint yoffset
, GLint zoffset
,
900 GLsizei width
, GLsizei height
, GLsizei depth
,
901 GLenum format
, GLenum type
,
902 const GLvoid
*pixels
,
903 const struct gl_pixelstore_attrib
*packing
,
904 struct gl_texture_object
*texObj
,
905 struct gl_texture_image
*texImage
)
907 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
909 /* fprintf(stderr, "%s\n", __FUNCTION__); */
911 assert( t
); /* this _should_ be true */
913 driSwapOutTextureObject( t
);
916 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
918 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage3D");
921 texObj
->DriverData
= t
;
924 _mesa_store_texsubimage3d(ctx
, target
, level
, xoffset
, yoffset
, zoffset
,
925 width
, height
, depth
,
926 format
, type
, pixels
, packing
, texObj
, texImage
);
928 t
->dirty_images
[0] |= (1 << level
);
934 static void r200TexEnv( GLcontext
*ctx
, GLenum target
,
935 GLenum pname
, const GLfloat
*param
)
937 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
938 GLuint unit
= ctx
->Texture
.CurrentUnit
;
939 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
941 if ( R200_DEBUG
& DEBUG_STATE
) {
942 fprintf( stderr
, "%s( %s )\n",
943 __FUNCTION__
, _mesa_lookup_enum_by_nr( pname
) );
946 /* This is incorrect: Need to maintain this data for each of
947 * GL_TEXTURE_{123}D, GL_TEXTURE_RECTANGLE_NV, etc, and switch
948 * between them according to _ReallyEnabled.
951 case GL_TEXTURE_ENV_COLOR
: {
954 UNCLAMPED_FLOAT_TO_RGBA_CHAN( c
, texUnit
->EnvColor
);
955 envColor
= r200PackColor( 4, c
[0], c
[1], c
[2], c
[3] );
956 if ( rmesa
->hw
.tf
.cmd
[TF_TFACTOR_0
+ unit
] != envColor
) {
957 R200_STATECHANGE( rmesa
, tf
);
958 rmesa
->hw
.tf
.cmd
[TF_TFACTOR_0
+ unit
] = envColor
;
963 case GL_TEXTURE_LOD_BIAS_EXT
: {
966 const int fixed_one
= 0x8000000;
968 /* The R200's LOD bias is a signed 2's complement value with a
969 * range of -16.0 <= bias < 16.0.
971 * NOTE: Add a small bias to the bias for conform mipsel.c test.
974 min
= driQueryOptionb (&rmesa
->optionCache
, "no_neg_lod_bias") ?
976 bias
= CLAMP( bias
, min
, 16.0 );
977 b
= (int)(bias
* fixed_one
) & R200_LOD_BIAS_MASK
;
979 if ( (rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT_X
] & R200_LOD_BIAS_MASK
) != b
) {
980 R200_STATECHANGE( rmesa
, tex
[unit
] );
981 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT_X
] &= ~R200_LOD_BIAS_MASK
;
982 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT_X
] |= b
;
994 * Changes variables and flags for a state update, which will happen at the
995 * next UpdateTextureState
998 static void r200TexParameter( GLcontext
*ctx
, GLenum target
,
999 struct gl_texture_object
*texObj
,
1000 GLenum pname
, const GLfloat
*params
)
1002 r200TexObjPtr t
= (r200TexObjPtr
) texObj
->DriverData
;
1004 if ( R200_DEBUG
& (DEBUG_STATE
|DEBUG_TEXTURE
) ) {
1005 fprintf( stderr
, "%s( %s )\n", __FUNCTION__
,
1006 _mesa_lookup_enum_by_nr( pname
) );
1010 case GL_TEXTURE_MIN_FILTER
:
1011 case GL_TEXTURE_MAG_FILTER
:
1012 case GL_TEXTURE_MAX_ANISOTROPY_EXT
:
1013 r200SetTexMaxAnisotropy( t
, texObj
->MaxAnisotropy
);
1014 r200SetTexFilter( t
, texObj
->MinFilter
, texObj
->MagFilter
);
1017 case GL_TEXTURE_WRAP_S
:
1018 case GL_TEXTURE_WRAP_T
:
1019 case GL_TEXTURE_WRAP_R
:
1020 r200SetTexWrap( t
, texObj
->WrapS
, texObj
->WrapT
, texObj
->WrapR
);
1023 case GL_TEXTURE_BORDER_COLOR
:
1024 r200SetTexBorderColor( t
, texObj
->_BorderChan
);
1027 case GL_TEXTURE_BASE_LEVEL
:
1028 case GL_TEXTURE_MAX_LEVEL
:
1029 case GL_TEXTURE_MIN_LOD
:
1030 case GL_TEXTURE_MAX_LOD
:
1031 /* This isn't the most efficient solution but there doesn't appear to
1032 * be a nice alternative. Since there's no LOD clamping,
1033 * we just have to rely on loading the right subset of mipmap levels
1034 * to simulate a clamped LOD.
1036 driSwapOutTextureObject( (driTextureObject
*) t
);
1043 /* Mark this texobj as dirty (one bit per tex unit)
1045 t
->dirty_state
= TEX_ALL
;
1050 static void r200BindTexture( GLcontext
*ctx
, GLenum target
,
1051 struct gl_texture_object
*texObj
)
1053 if ( R200_DEBUG
& (DEBUG_STATE
|DEBUG_TEXTURE
) ) {
1054 fprintf( stderr
, "%s( %p ) unit=%d\n", __FUNCTION__
, (void *)texObj
,
1055 ctx
->Texture
.CurrentUnit
);
1058 if ( (target
== GL_TEXTURE_1D
)
1059 || (target
== GL_TEXTURE_2D
)
1060 #if ENABLE_HW_3D_TEXTURE
1061 || (target
== GL_TEXTURE_3D
)
1063 || (target
== GL_TEXTURE_CUBE_MAP
)
1064 || (target
== GL_TEXTURE_RECTANGLE_NV
) ) {
1065 assert( texObj
->DriverData
!= NULL
);
1070 static void r200DeleteTexture( GLcontext
*ctx
,
1071 struct gl_texture_object
*texObj
)
1073 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1074 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
1076 if ( R200_DEBUG
& (DEBUG_STATE
|DEBUG_TEXTURE
) ) {
1077 fprintf( stderr
, "%s( %p (target = %s) )\n", __FUNCTION__
, (void *)texObj
,
1078 _mesa_lookup_enum_by_nr( texObj
->Target
) );
1083 R200_FIREVERTICES( rmesa
);
1086 driDestroyTextureObject( t
);
1088 /* Free mipmap images and the texture object itself */
1089 _mesa_delete_texture_object(ctx
, texObj
);
1093 * - Same GEN_MODE for all active bits
1094 * - Same EyePlane/ObjPlane for all active bits when using Eye/Obj
1095 * - STRQ presumably all supported (matrix means incoming R values
1096 * can end up in STQ, this has implications for vertex support,
1097 * presumably ok if maos is used, though?)
1099 * Basically impossible to do this on the fly - just collect some
1100 * basic info & do the checks from ValidateState().
1102 static void r200TexGen( GLcontext
*ctx
,
1105 const GLfloat
*params
)
1107 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1108 GLuint unit
= ctx
->Texture
.CurrentUnit
;
1109 rmesa
->recheck_texgen
[unit
] = GL_TRUE
;
1114 * Allocate a new texture object.
1115 * Called via ctx->Driver.NewTextureObject.
1116 * Note: this function will be called during context creation to
1117 * allocate the default texture objects.
1118 * Note: we could use containment here to 'derive' the driver-specific
1119 * texture object from the core mesa gl_texture_object. Not done at this time.
1120 * Fixup MaxAnisotropy according to user preference.
1122 static struct gl_texture_object
*
1123 r200NewTextureObject( GLcontext
*ctx
, GLuint name
, GLenum target
)
1125 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1126 struct gl_texture_object
*obj
;
1127 obj
= _mesa_new_texture_object(ctx
, name
, target
);
1130 obj
->MaxAnisotropy
= rmesa
->initialMaxAnisotropy
;
1131 r200AllocTexObj( obj
);
1136 void r200InitTextureFuncs( struct dd_function_table
*functions
)
1138 /* Note: we only plug in the functions we implement in the driver
1139 * since _mesa_init_driver_functions() was already called.
1141 functions
->ChooseTextureFormat
= r200ChooseTextureFormat
;
1142 functions
->TexImage1D
= r200TexImage1D
;
1143 functions
->TexImage2D
= r200TexImage2D
;
1144 #if ENABLE_HW_3D_TEXTURE
1145 functions
->TexImage3D
= r200TexImage3D
;
1147 functions
->TexImage3D
= _mesa_store_teximage3d
;
1149 functions
->TexSubImage1D
= r200TexSubImage1D
;
1150 functions
->TexSubImage2D
= r200TexSubImage2D
;
1151 #if ENABLE_HW_3D_TEXTURE
1152 functions
->TexSubImage3D
= r200TexSubImage3D
;
1154 functions
->TexSubImage3D
= _mesa_store_texsubimage3d
;
1156 functions
->NewTextureObject
= r200NewTextureObject
;
1157 functions
->BindTexture
= r200BindTexture
;
1158 functions
->DeleteTexture
= r200DeleteTexture
;
1159 functions
->IsTextureResident
= driIsTextureResident
;
1161 functions
->TexEnv
= r200TexEnv
;
1162 functions
->TexParameter
= r200TexParameter
;
1163 functions
->TexGen
= r200TexGen
;
1165 functions
->CompressedTexImage2D
= r200CompressedTexImage2D
;
1166 functions
->CompressedTexSubImage2D
= r200CompressedTexSubImage2D
;
1168 driInitTextureFormats();
1171 /* moved or obsolete code */
1172 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1173 driInitTextureObjects( ctx
, & rmesa
->swapped
,
1174 DRI_TEXMGR_DO_TEXTURE_1D
1175 | DRI_TEXMGR_DO_TEXTURE_2D
);
1177 /* Hack: r200NewTextureObject is not yet installed when the
1178 * default textures are created. Therefore set MaxAnisotropy of the
1179 * default 2D texture now. */
1180 ctx
->Shared
->Default2D
->MaxAnisotropy
= driQueryOptionf (&rmesa
->optionCache
,
1181 "def_max_anisotropy");