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
;
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
);
308 /* try to find a format which will only need a memcopy */
309 static const struct gl_texture_format
*
310 r200Choose8888TexFormat( GLenum srcFormat
, GLenum srcType
)
313 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
315 if ((srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8
) ||
316 (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
) ||
317 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) ||
318 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_BYTE
&& littleEndian
)) {
319 return &_mesa_texformat_rgba8888
;
321 else if ((srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) ||
322 (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
&& littleEndian
) ||
323 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_INT_8_8_8_8
) ||
324 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
)) {
325 return &_mesa_texformat_rgba8888_rev
;
327 else return _dri_texformat_argb8888
;
330 static const struct gl_texture_format
*
331 r200ChooseTextureFormat( GLcontext
*ctx
, GLint internalFormat
,
332 GLenum format
, GLenum type
)
334 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
335 const GLboolean do32bpt
=
336 ( rmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_32
);
337 const GLboolean force16bpt
=
338 ( rmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_FORCE_16
);
341 switch ( internalFormat
) {
344 case GL_COMPRESSED_RGBA
:
346 case GL_UNSIGNED_INT_10_10_10_2
:
347 case GL_UNSIGNED_INT_2_10_10_10_REV
:
348 return do32bpt
? _dri_texformat_argb8888
: _dri_texformat_argb1555
;
349 case GL_UNSIGNED_SHORT_4_4_4_4
:
350 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
351 return _dri_texformat_argb4444
;
352 case GL_UNSIGNED_SHORT_5_5_5_1
:
353 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
354 return _dri_texformat_argb1555
;
357 r200Choose8888TexFormat(format
, type
) : _dri_texformat_argb4444
;
362 case GL_COMPRESSED_RGB
:
364 case GL_UNSIGNED_SHORT_4_4_4_4
:
365 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
366 return _dri_texformat_argb4444
;
367 case GL_UNSIGNED_SHORT_5_5_5_1
:
368 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
369 return _dri_texformat_argb1555
;
370 case GL_UNSIGNED_SHORT_5_6_5
:
371 case GL_UNSIGNED_SHORT_5_6_5_REV
:
372 return _dri_texformat_rgb565
;
374 return do32bpt
? _dri_texformat_argb8888
: _dri_texformat_rgb565
;
382 r200Choose8888TexFormat(format
, type
) : _dri_texformat_argb4444
;
386 return _dri_texformat_argb4444
;
389 return _dri_texformat_argb1555
;
395 return !force16bpt
? _dri_texformat_argb8888
: _dri_texformat_rgb565
;
400 return _dri_texformat_rgb565
;
407 case GL_COMPRESSED_ALPHA
:
408 /* can't use a8 format since interpreting hw I8 as a8 would result
409 in wrong rgb values (same as alpha value instead of 0). */
410 return _dri_texformat_al88
;
418 case GL_COMPRESSED_LUMINANCE
:
419 return _dri_texformat_l8
;
422 case GL_LUMINANCE_ALPHA
:
423 case GL_LUMINANCE4_ALPHA4
:
424 case GL_LUMINANCE6_ALPHA2
:
425 case GL_LUMINANCE8_ALPHA8
:
426 case GL_LUMINANCE12_ALPHA4
:
427 case GL_LUMINANCE12_ALPHA12
:
428 case GL_LUMINANCE16_ALPHA16
:
429 case GL_COMPRESSED_LUMINANCE_ALPHA
:
430 return _dri_texformat_al88
;
437 case GL_COMPRESSED_INTENSITY
:
438 return _dri_texformat_i8
;
441 if (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
442 type
== GL_UNSIGNED_BYTE
)
443 return &_mesa_texformat_ycbcr
;
445 return &_mesa_texformat_ycbcr_rev
;
449 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
450 return &_mesa_texformat_rgb_dxt1
;
452 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
453 return &_mesa_texformat_rgba_dxt1
;
457 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
458 return &_mesa_texformat_rgba_dxt3
;
460 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
461 return &_mesa_texformat_rgba_dxt5
;
465 "unexpected internalFormat 0x%x in r200ChooseTextureFormat",
466 (int) internalFormat
);
470 return NULL
; /* never get here */
475 r200ValidateClientStorage( GLcontext
*ctx
, GLenum target
,
476 GLint internalFormat
,
477 GLint srcWidth
, GLint srcHeight
,
478 GLenum format
, GLenum type
, const void *pixels
,
479 const struct gl_pixelstore_attrib
*packing
,
480 struct gl_texture_object
*texObj
,
481 struct gl_texture_image
*texImage
)
484 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
487 fprintf(stderr
, "intformat %s format %s type %s\n",
488 _mesa_lookup_enum_by_nr( internalFormat
),
489 _mesa_lookup_enum_by_nr( format
),
490 _mesa_lookup_enum_by_nr( type
));
492 if (!ctx
->Unpack
.ClientStorage
)
495 if (ctx
->_ImageTransferState
||
496 texImage
->IsCompressed
||
497 texObj
->GenerateMipmap
)
501 /* This list is incomplete, may be different on ppc???
503 switch ( internalFormat
) {
505 if ( format
== GL_BGRA
&& type
== GL_UNSIGNED_INT_8_8_8_8_REV
) {
506 texImage
->TexFormat
= _dri_texformat_argb8888
;
513 if ( format
== GL_RGB
&& type
== GL_UNSIGNED_SHORT_5_6_5
) {
514 texImage
->TexFormat
= _dri_texformat_rgb565
;
521 if ( format
== GL_YCBCR_MESA
&&
522 type
== GL_UNSIGNED_SHORT_8_8_REV_APPLE
) {
523 texImage
->TexFormat
= &_mesa_texformat_ycbcr_rev
;
525 else if ( format
== GL_YCBCR_MESA
&&
526 (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
527 type
== GL_UNSIGNED_BYTE
)) {
528 texImage
->TexFormat
= &_mesa_texformat_ycbcr
;
538 /* Could deal with these packing issues, but currently don't:
540 if (packing
->SkipPixels
||
542 packing
->SwapBytes
||
548 GLint srcRowStride
= _mesa_image_row_stride(packing
, srcWidth
,
553 fprintf(stderr
, "%s: srcRowStride %d/%x\n",
554 __FUNCTION__
, srcRowStride
, srcRowStride
);
556 /* Could check this later in upload, pitch restrictions could be
557 * relaxed, but would need to store the image pitch somewhere,
558 * as packing details might change before image is uploaded:
560 if (!r200IsGartMemory( rmesa
, pixels
, srcHeight
* srcRowStride
) ||
565 /* Have validated that _mesa_transfer_teximage would be a straight
566 * memcpy at this point. NOTE: future calls to TexSubImage will
567 * overwrite the client data. This is explicitly mentioned in the
570 texImage
->Data
= (void *)pixels
;
571 texImage
->IsClientData
= GL_TRUE
;
572 texImage
->RowStride
= srcRowStride
/ texImage
->TexFormat
->TexelBytes
;
579 static void r200TexImage1D( GLcontext
*ctx
, GLenum target
, GLint level
,
580 GLint internalFormat
,
581 GLint width
, GLint border
,
582 GLenum format
, GLenum type
, const GLvoid
*pixels
,
583 const struct gl_pixelstore_attrib
*packing
,
584 struct gl_texture_object
*texObj
,
585 struct gl_texture_image
*texImage
)
587 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
590 driSwapOutTextureObject( t
);
593 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
595 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
600 /* Note, this will call ChooseTextureFormat */
601 _mesa_store_teximage1d(ctx
, target
, level
, internalFormat
,
602 width
, border
, format
, type
, pixels
,
603 &ctx
->Unpack
, texObj
, texImage
);
605 t
->dirty_images
[0] |= (1 << level
);
609 static void r200TexSubImage1D( GLcontext
*ctx
, GLenum target
, GLint level
,
612 GLenum format
, GLenum type
,
613 const GLvoid
*pixels
,
614 const struct gl_pixelstore_attrib
*packing
,
615 struct gl_texture_object
*texObj
,
616 struct gl_texture_image
*texImage
)
618 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
620 assert( t
); /* this _should_ be true */
622 driSwapOutTextureObject( t
);
625 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
627 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
632 _mesa_store_texsubimage1d(ctx
, target
, level
, xoffset
, width
,
633 format
, type
, pixels
, packing
, texObj
,
636 t
->dirty_images
[0] |= (1 << level
);
640 static void r200TexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
641 GLint internalFormat
,
642 GLint width
, GLint height
, GLint border
,
643 GLenum format
, GLenum type
, const GLvoid
*pixels
,
644 const struct gl_pixelstore_attrib
*packing
,
645 struct gl_texture_object
*texObj
,
646 struct gl_texture_image
*texImage
)
648 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
651 /* which cube face or ordinary 2D image */
653 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
654 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
655 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
656 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
657 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
658 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
659 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
667 driSwapOutTextureObject( t
);
670 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
672 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
677 texImage
->IsClientData
= GL_FALSE
;
679 if (r200ValidateClientStorage( ctx
, target
,
682 format
, type
, pixels
,
683 packing
, texObj
, texImage
)) {
684 if (R200_DEBUG
& DEBUG_TEXTURE
)
685 fprintf(stderr
, "%s: Using client storage\n", __FUNCTION__
);
688 if (R200_DEBUG
& DEBUG_TEXTURE
)
689 fprintf(stderr
, "%s: Using normal storage\n", __FUNCTION__
);
691 /* Normal path: copy (to cached memory) and eventually upload
692 * via another copy to GART memory and then a blit... Could
693 * eliminate one copy by going straight to (permanent) GART.
695 * Note, this will call r200ChooseTextureFormat.
697 _mesa_store_teximage2d(ctx
, target
, level
, internalFormat
,
698 width
, height
, border
, format
, type
, pixels
,
699 &ctx
->Unpack
, texObj
, texImage
);
701 t
->dirty_images
[face
] |= (1 << level
);
706 static void r200TexSubImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
707 GLint xoffset
, GLint yoffset
,
708 GLsizei width
, GLsizei height
,
709 GLenum format
, GLenum type
,
710 const GLvoid
*pixels
,
711 const struct gl_pixelstore_attrib
*packing
,
712 struct gl_texture_object
*texObj
,
713 struct gl_texture_image
*texImage
)
715 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
718 /* which cube face or ordinary 2D image */
720 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
721 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
722 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
723 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
724 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
725 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
726 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
733 assert( t
); /* this _should_ be true */
735 driSwapOutTextureObject( t
);
738 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
740 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
745 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
746 height
, format
, type
, pixels
, packing
, texObj
,
749 t
->dirty_images
[face
] |= (1 << level
);
753 static void r200CompressedTexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
754 GLint internalFormat
,
755 GLint width
, GLint height
, GLint border
,
756 GLsizei imageSize
, const GLvoid
*data
,
757 struct gl_texture_object
*texObj
,
758 struct gl_texture_image
*texImage
)
760 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
763 /* which cube face or ordinary 2D image */
765 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
766 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
767 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
768 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
769 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
770 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
771 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
779 driSwapOutTextureObject( t
);
782 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
784 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2D");
789 texImage
->IsClientData
= GL_FALSE
;
790 /* can't call this, different parameters. Would never evaluate to true anyway currently
791 if (r200ValidateClientStorage( ctx, target,
794 format, type, pixels,
795 packing, texObj, texImage)) {
796 if (R200_DEBUG & DEBUG_TEXTURE)
797 fprintf(stderr, "%s: Using client storage\n", __FUNCTION__);
800 if (R200_DEBUG
& DEBUG_TEXTURE
)
801 fprintf(stderr
, "%s: Using normal storage\n", __FUNCTION__
);
803 /* Normal path: copy (to cached memory) and eventually upload
804 * via another copy to GART memory and then a blit... Could
805 * eliminate one copy by going straight to (permanent) GART.
807 * Note, this will call r200ChooseTextureFormat.
809 _mesa_store_compressed_teximage2d(ctx
, target
, level
, internalFormat
, width
,
810 height
, border
, imageSize
, data
, texObj
, texImage
);
812 t
->dirty_images
[face
] |= (1 << level
);
817 static void r200CompressedTexSubImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
818 GLint xoffset
, GLint yoffset
,
819 GLsizei width
, GLsizei height
,
821 GLsizei imageSize
, const GLvoid
*data
,
822 struct gl_texture_object
*texObj
,
823 struct gl_texture_image
*texImage
)
825 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
829 /* which cube face or ordinary 2D image */
831 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
832 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
833 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
834 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
835 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
836 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
837 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
844 assert( t
); /* this _should_ be true */
846 driSwapOutTextureObject( t
);
849 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
851 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexSubImage2D");
856 _mesa_store_compressed_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
857 height
, format
, imageSize
, data
, texObj
, texImage
);
859 t
->dirty_images
[face
] |= (1 << level
);
863 #if ENABLE_HW_3D_TEXTURE
864 static void r200TexImage3D( GLcontext
*ctx
, GLenum target
, GLint level
,
865 GLint internalFormat
,
866 GLint width
, GLint height
, GLint depth
,
868 GLenum format
, GLenum type
, const GLvoid
*pixels
,
869 const struct gl_pixelstore_attrib
*packing
,
870 struct gl_texture_object
*texObj
,
871 struct gl_texture_image
*texImage
)
873 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
876 driSwapOutTextureObject( t
);
879 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
881 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
886 texImage
->IsClientData
= GL_FALSE
;
889 if (r200ValidateClientStorage( ctx
, target
,
892 format
, type
, pixels
,
893 packing
, texObj
, texImage
)) {
894 if (R200_DEBUG
& DEBUG_TEXTURE
)
895 fprintf(stderr
, "%s: Using client storage\n", __FUNCTION__
);
900 if (R200_DEBUG
& DEBUG_TEXTURE
)
901 fprintf(stderr
, "%s: Using normal storage\n", __FUNCTION__
);
903 /* Normal path: copy (to cached memory) and eventually upload
904 * via another copy to GART memory and then a blit... Could
905 * eliminate one copy by going straight to (permanent) GART.
907 * Note, this will call r200ChooseTextureFormat.
909 _mesa_store_teximage3d(ctx
, target
, level
, internalFormat
,
910 width
, height
, depth
, border
,
911 format
, type
, pixels
,
912 &ctx
->Unpack
, texObj
, texImage
);
914 t
->dirty_images
[0] |= (1 << level
);
920 #if ENABLE_HW_3D_TEXTURE
922 r200TexSubImage3D( GLcontext
*ctx
, GLenum target
, GLint level
,
923 GLint xoffset
, GLint yoffset
, GLint zoffset
,
924 GLsizei width
, GLsizei height
, GLsizei depth
,
925 GLenum format
, GLenum type
,
926 const GLvoid
*pixels
,
927 const struct gl_pixelstore_attrib
*packing
,
928 struct gl_texture_object
*texObj
,
929 struct gl_texture_image
*texImage
)
931 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
933 /* fprintf(stderr, "%s\n", __FUNCTION__); */
935 assert( t
); /* this _should_ be true */
937 driSwapOutTextureObject( t
);
940 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
942 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage3D");
945 texObj
->DriverData
= t
;
948 _mesa_store_texsubimage3d(ctx
, target
, level
, xoffset
, yoffset
, zoffset
,
949 width
, height
, depth
,
950 format
, type
, pixels
, packing
, texObj
, texImage
);
952 t
->dirty_images
[0] |= (1 << level
);
958 static void r200TexEnv( GLcontext
*ctx
, GLenum target
,
959 GLenum pname
, const GLfloat
*param
)
961 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
962 GLuint unit
= ctx
->Texture
.CurrentUnit
;
963 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
965 if ( R200_DEBUG
& DEBUG_STATE
) {
966 fprintf( stderr
, "%s( %s )\n",
967 __FUNCTION__
, _mesa_lookup_enum_by_nr( pname
) );
970 /* This is incorrect: Need to maintain this data for each of
971 * GL_TEXTURE_{123}D, GL_TEXTURE_RECTANGLE_NV, etc, and switch
972 * between them according to _ReallyEnabled.
975 case GL_TEXTURE_ENV_COLOR
: {
978 UNCLAMPED_FLOAT_TO_RGBA_CHAN( c
, texUnit
->EnvColor
);
979 envColor
= r200PackColor( 4, c
[0], c
[1], c
[2], c
[3] );
980 if ( rmesa
->hw
.tf
.cmd
[TF_TFACTOR_0
+ unit
] != envColor
) {
981 R200_STATECHANGE( rmesa
, tf
);
982 rmesa
->hw
.tf
.cmd
[TF_TFACTOR_0
+ unit
] = envColor
;
987 case GL_TEXTURE_LOD_BIAS_EXT
: {
990 const int fixed_one
= 0x8000000;
992 /* The R200's LOD bias is a signed 2's complement value with a
993 * range of -16.0 <= bias < 16.0.
995 * NOTE: Add a small bias to the bias for conform mipsel.c test.
998 min
= driQueryOptionb (&rmesa
->optionCache
, "no_neg_lod_bias") ?
1000 bias
= CLAMP( bias
, min
, 16.0 );
1001 b
= (int)(bias
* fixed_one
) & R200_LOD_BIAS_MASK
;
1003 if ( (rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT_X
] & R200_LOD_BIAS_MASK
) != b
) {
1004 R200_STATECHANGE( rmesa
, tex
[unit
] );
1005 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT_X
] &= ~R200_LOD_BIAS_MASK
;
1006 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT_X
] |= b
;
1010 case GL_COORD_REPLACE_ARB
:
1011 if (ctx
->Point
.PointSprite
) {
1012 R200_STATECHANGE( rmesa
, spr
);
1013 if ((GLenum
)param
[0]) {
1014 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |= R200_PS_GEN_TEX_0
<< unit
;
1016 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] &= ~(R200_PS_GEN_TEX_0
<< unit
);
1027 * Changes variables and flags for a state update, which will happen at the
1028 * next UpdateTextureState
1031 static void r200TexParameter( GLcontext
*ctx
, GLenum target
,
1032 struct gl_texture_object
*texObj
,
1033 GLenum pname
, const GLfloat
*params
)
1035 r200TexObjPtr t
= (r200TexObjPtr
) texObj
->DriverData
;
1037 if ( R200_DEBUG
& (DEBUG_STATE
|DEBUG_TEXTURE
) ) {
1038 fprintf( stderr
, "%s( %s )\n", __FUNCTION__
,
1039 _mesa_lookup_enum_by_nr( pname
) );
1043 case GL_TEXTURE_MIN_FILTER
:
1044 case GL_TEXTURE_MAG_FILTER
:
1045 case GL_TEXTURE_MAX_ANISOTROPY_EXT
:
1046 r200SetTexMaxAnisotropy( t
, texObj
->MaxAnisotropy
);
1047 r200SetTexFilter( t
, texObj
->MinFilter
, texObj
->MagFilter
);
1050 case GL_TEXTURE_WRAP_S
:
1051 case GL_TEXTURE_WRAP_T
:
1052 case GL_TEXTURE_WRAP_R
:
1053 r200SetTexWrap( t
, texObj
->WrapS
, texObj
->WrapT
, texObj
->WrapR
);
1056 case GL_TEXTURE_BORDER_COLOR
:
1057 r200SetTexBorderColor( t
, texObj
->_BorderChan
);
1060 case GL_TEXTURE_BASE_LEVEL
:
1061 case GL_TEXTURE_MAX_LEVEL
:
1062 case GL_TEXTURE_MIN_LOD
:
1063 case GL_TEXTURE_MAX_LOD
:
1064 /* This isn't the most efficient solution but there doesn't appear to
1065 * be a nice alternative. Since there's no LOD clamping,
1066 * we just have to rely on loading the right subset of mipmap levels
1067 * to simulate a clamped LOD.
1069 driSwapOutTextureObject( (driTextureObject
*) t
);
1076 /* Mark this texobj as dirty (one bit per tex unit)
1078 t
->dirty_state
= TEX_ALL
;
1083 static void r200BindTexture( GLcontext
*ctx
, GLenum target
,
1084 struct gl_texture_object
*texObj
)
1086 if ( R200_DEBUG
& (DEBUG_STATE
|DEBUG_TEXTURE
) ) {
1087 fprintf( stderr
, "%s( %p ) unit=%d\n", __FUNCTION__
, (void *)texObj
,
1088 ctx
->Texture
.CurrentUnit
);
1091 if ( (target
== GL_TEXTURE_1D
)
1092 || (target
== GL_TEXTURE_2D
)
1093 #if ENABLE_HW_3D_TEXTURE
1094 || (target
== GL_TEXTURE_3D
)
1096 || (target
== GL_TEXTURE_CUBE_MAP
)
1097 || (target
== GL_TEXTURE_RECTANGLE_NV
) ) {
1098 assert( texObj
->DriverData
!= NULL
);
1103 static void r200DeleteTexture( GLcontext
*ctx
,
1104 struct gl_texture_object
*texObj
)
1106 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1107 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
1109 if ( R200_DEBUG
& (DEBUG_STATE
|DEBUG_TEXTURE
) ) {
1110 fprintf( stderr
, "%s( %p (target = %s) )\n", __FUNCTION__
, (void *)texObj
,
1111 _mesa_lookup_enum_by_nr( texObj
->Target
) );
1116 R200_FIREVERTICES( rmesa
);
1119 driDestroyTextureObject( t
);
1121 /* Free mipmap images and the texture object itself */
1122 _mesa_delete_texture_object(ctx
, texObj
);
1126 * - Same GEN_MODE for all active bits
1127 * - Same EyePlane/ObjPlane for all active bits when using Eye/Obj
1128 * - STRQ presumably all supported (matrix means incoming R values
1129 * can end up in STQ, this has implications for vertex support,
1130 * presumably ok if maos is used, though?)
1132 * Basically impossible to do this on the fly - just collect some
1133 * basic info & do the checks from ValidateState().
1135 static void r200TexGen( GLcontext
*ctx
,
1138 const GLfloat
*params
)
1140 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1141 GLuint unit
= ctx
->Texture
.CurrentUnit
;
1142 rmesa
->recheck_texgen
[unit
] = GL_TRUE
;
1147 * Allocate a new texture object.
1148 * Called via ctx->Driver.NewTextureObject.
1149 * Note: this function will be called during context creation to
1150 * allocate the default texture objects.
1151 * Note: we could use containment here to 'derive' the driver-specific
1152 * texture object from the core mesa gl_texture_object. Not done at this time.
1153 * Fixup MaxAnisotropy according to user preference.
1155 static struct gl_texture_object
*
1156 r200NewTextureObject( GLcontext
*ctx
, GLuint name
, GLenum target
)
1158 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1159 struct gl_texture_object
*obj
;
1160 obj
= _mesa_new_texture_object(ctx
, name
, target
);
1163 obj
->MaxAnisotropy
= rmesa
->initialMaxAnisotropy
;
1164 r200AllocTexObj( obj
);
1169 void r200InitTextureFuncs( struct dd_function_table
*functions
)
1171 /* Note: we only plug in the functions we implement in the driver
1172 * since _mesa_init_driver_functions() was already called.
1174 functions
->ChooseTextureFormat
= r200ChooseTextureFormat
;
1175 functions
->TexImage1D
= r200TexImage1D
;
1176 functions
->TexImage2D
= r200TexImage2D
;
1177 #if ENABLE_HW_3D_TEXTURE
1178 functions
->TexImage3D
= r200TexImage3D
;
1180 functions
->TexImage3D
= _mesa_store_teximage3d
;
1182 functions
->TexSubImage1D
= r200TexSubImage1D
;
1183 functions
->TexSubImage2D
= r200TexSubImage2D
;
1184 #if ENABLE_HW_3D_TEXTURE
1185 functions
->TexSubImage3D
= r200TexSubImage3D
;
1187 functions
->TexSubImage3D
= _mesa_store_texsubimage3d
;
1189 functions
->NewTextureObject
= r200NewTextureObject
;
1190 functions
->BindTexture
= r200BindTexture
;
1191 functions
->DeleteTexture
= r200DeleteTexture
;
1192 functions
->IsTextureResident
= driIsTextureResident
;
1194 functions
->TexEnv
= r200TexEnv
;
1195 functions
->TexParameter
= r200TexParameter
;
1196 functions
->TexGen
= r200TexGen
;
1198 functions
->CompressedTexImage2D
= r200CompressedTexImage2D
;
1199 functions
->CompressedTexSubImage2D
= r200CompressedTexSubImage2D
;
1201 driInitTextureFormats();
1204 /* moved or obsolete code */
1205 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1206 driInitTextureObjects( ctx
, & rmesa
->swapped
,
1207 DRI_TEXMGR_DO_TEXTURE_1D
1208 | DRI_TEXMGR_DO_TEXTURE_2D
);
1210 /* Hack: r200NewTextureObject is not yet installed when the
1211 * default textures are created. Therefore set MaxAnisotropy of the
1212 * default 2D texture now. */
1213 ctx
->Shared
->Default2D
->MaxAnisotropy
= driQueryOptionf (&rmesa
->optionCache
,
1214 "def_max_anisotropy");