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 return _dri_texformat_a8
;
416 case GL_COMPRESSED_LUMINANCE
:
417 return _dri_texformat_l8
;
420 case GL_LUMINANCE_ALPHA
:
421 case GL_LUMINANCE4_ALPHA4
:
422 case GL_LUMINANCE6_ALPHA2
:
423 case GL_LUMINANCE8_ALPHA8
:
424 case GL_LUMINANCE12_ALPHA4
:
425 case GL_LUMINANCE12_ALPHA12
:
426 case GL_LUMINANCE16_ALPHA16
:
427 case GL_COMPRESSED_LUMINANCE_ALPHA
:
428 return _dri_texformat_al88
;
435 case GL_COMPRESSED_INTENSITY
:
436 return _dri_texformat_i8
;
439 if (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
440 type
== GL_UNSIGNED_BYTE
)
441 return &_mesa_texformat_ycbcr
;
443 return &_mesa_texformat_ycbcr_rev
;
447 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
448 return &_mesa_texformat_rgb_dxt1
;
450 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
451 return &_mesa_texformat_rgba_dxt1
;
455 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
456 return &_mesa_texformat_rgba_dxt3
;
458 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
459 return &_mesa_texformat_rgba_dxt5
;
463 "unexpected internalFormat 0x%x in r200ChooseTextureFormat",
464 (int) internalFormat
);
468 return NULL
; /* never get here */
473 r200ValidateClientStorage( GLcontext
*ctx
, GLenum target
,
474 GLint internalFormat
,
475 GLint srcWidth
, GLint srcHeight
,
476 GLenum format
, GLenum type
, const void *pixels
,
477 const struct gl_pixelstore_attrib
*packing
,
478 struct gl_texture_object
*texObj
,
479 struct gl_texture_image
*texImage
)
482 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
485 fprintf(stderr
, "intformat %s format %s type %s\n",
486 _mesa_lookup_enum_by_nr( internalFormat
),
487 _mesa_lookup_enum_by_nr( format
),
488 _mesa_lookup_enum_by_nr( type
));
490 if (!ctx
->Unpack
.ClientStorage
)
493 if (ctx
->_ImageTransferState
||
494 texImage
->IsCompressed
||
495 texObj
->GenerateMipmap
)
499 /* This list is incomplete, may be different on ppc???
501 switch ( internalFormat
) {
503 if ( format
== GL_BGRA
&& type
== GL_UNSIGNED_INT_8_8_8_8_REV
) {
504 texImage
->TexFormat
= _dri_texformat_argb8888
;
511 if ( format
== GL_RGB
&& type
== GL_UNSIGNED_SHORT_5_6_5
) {
512 texImage
->TexFormat
= _dri_texformat_rgb565
;
519 if ( format
== GL_YCBCR_MESA
&&
520 type
== GL_UNSIGNED_SHORT_8_8_REV_APPLE
) {
521 texImage
->TexFormat
= &_mesa_texformat_ycbcr_rev
;
523 else if ( format
== GL_YCBCR_MESA
&&
524 (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
525 type
== GL_UNSIGNED_BYTE
)) {
526 texImage
->TexFormat
= &_mesa_texformat_ycbcr
;
536 /* Could deal with these packing issues, but currently don't:
538 if (packing
->SkipPixels
||
540 packing
->SwapBytes
||
546 GLint srcRowStride
= _mesa_image_row_stride(packing
, srcWidth
,
551 fprintf(stderr
, "%s: srcRowStride %d/%x\n",
552 __FUNCTION__
, srcRowStride
, srcRowStride
);
554 /* Could check this later in upload, pitch restrictions could be
555 * relaxed, but would need to store the image pitch somewhere,
556 * as packing details might change before image is uploaded:
558 if (!r200IsGartMemory( rmesa
, pixels
, srcHeight
* srcRowStride
) ||
563 /* Have validated that _mesa_transfer_teximage would be a straight
564 * memcpy at this point. NOTE: future calls to TexSubImage will
565 * overwrite the client data. This is explicitly mentioned in the
568 texImage
->Data
= (void *)pixels
;
569 texImage
->IsClientData
= GL_TRUE
;
570 texImage
->RowStride
= srcRowStride
/ texImage
->TexFormat
->TexelBytes
;
577 static void r200TexImage1D( GLcontext
*ctx
, GLenum target
, GLint level
,
578 GLint internalFormat
,
579 GLint width
, GLint border
,
580 GLenum format
, GLenum type
, const GLvoid
*pixels
,
581 const struct gl_pixelstore_attrib
*packing
,
582 struct gl_texture_object
*texObj
,
583 struct gl_texture_image
*texImage
)
585 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
588 driSwapOutTextureObject( t
);
591 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
593 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
598 /* Note, this will call ChooseTextureFormat */
599 _mesa_store_teximage1d(ctx
, target
, level
, internalFormat
,
600 width
, border
, format
, type
, pixels
,
601 &ctx
->Unpack
, texObj
, texImage
);
603 t
->dirty_images
[0] |= (1 << level
);
607 static void r200TexSubImage1D( GLcontext
*ctx
, GLenum target
, GLint level
,
610 GLenum format
, GLenum type
,
611 const GLvoid
*pixels
,
612 const struct gl_pixelstore_attrib
*packing
,
613 struct gl_texture_object
*texObj
,
614 struct gl_texture_image
*texImage
)
616 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
618 assert( t
); /* this _should_ be true */
620 driSwapOutTextureObject( t
);
623 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
625 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
630 _mesa_store_texsubimage1d(ctx
, target
, level
, xoffset
, width
,
631 format
, type
, pixels
, packing
, texObj
,
634 t
->dirty_images
[0] |= (1 << level
);
638 static void r200TexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
639 GLint internalFormat
,
640 GLint width
, GLint height
, GLint border
,
641 GLenum format
, GLenum type
, const GLvoid
*pixels
,
642 const struct gl_pixelstore_attrib
*packing
,
643 struct gl_texture_object
*texObj
,
644 struct gl_texture_image
*texImage
)
646 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
649 /* which cube face or ordinary 2D image */
651 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
652 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
653 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
654 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
655 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
656 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
657 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
665 driSwapOutTextureObject( t
);
668 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
670 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
675 texImage
->IsClientData
= GL_FALSE
;
677 if (r200ValidateClientStorage( ctx
, target
,
680 format
, type
, pixels
,
681 packing
, texObj
, texImage
)) {
682 if (R200_DEBUG
& DEBUG_TEXTURE
)
683 fprintf(stderr
, "%s: Using client storage\n", __FUNCTION__
);
686 if (R200_DEBUG
& DEBUG_TEXTURE
)
687 fprintf(stderr
, "%s: Using normal storage\n", __FUNCTION__
);
689 /* Normal path: copy (to cached memory) and eventually upload
690 * via another copy to GART memory and then a blit... Could
691 * eliminate one copy by going straight to (permanent) GART.
693 * Note, this will call r200ChooseTextureFormat.
695 _mesa_store_teximage2d(ctx
, target
, level
, internalFormat
,
696 width
, height
, border
, format
, type
, pixels
,
697 &ctx
->Unpack
, texObj
, texImage
);
699 t
->dirty_images
[face
] |= (1 << level
);
704 static void r200TexSubImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
705 GLint xoffset
, GLint yoffset
,
706 GLsizei width
, GLsizei height
,
707 GLenum format
, GLenum type
,
708 const GLvoid
*pixels
,
709 const struct gl_pixelstore_attrib
*packing
,
710 struct gl_texture_object
*texObj
,
711 struct gl_texture_image
*texImage
)
713 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
716 /* which cube face or ordinary 2D image */
718 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
719 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
720 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
721 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
722 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
723 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
724 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
731 assert( t
); /* this _should_ be true */
733 driSwapOutTextureObject( t
);
736 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
738 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
743 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
744 height
, format
, type
, pixels
, packing
, texObj
,
747 t
->dirty_images
[face
] |= (1 << level
);
751 static void r200CompressedTexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
752 GLint internalFormat
,
753 GLint width
, GLint height
, GLint border
,
754 GLsizei imageSize
, const GLvoid
*data
,
755 struct gl_texture_object
*texObj
,
756 struct gl_texture_image
*texImage
)
758 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
761 /* which cube face or ordinary 2D image */
763 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
764 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
765 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
766 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
767 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
768 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
769 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
777 driSwapOutTextureObject( t
);
780 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
782 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2D");
787 texImage
->IsClientData
= GL_FALSE
;
788 /* can't call this, different parameters. Would never evaluate to true anyway currently
789 if (r200ValidateClientStorage( ctx, target,
792 format, type, pixels,
793 packing, texObj, texImage)) {
794 if (R200_DEBUG & DEBUG_TEXTURE)
795 fprintf(stderr, "%s: Using client storage\n", __FUNCTION__);
798 if (R200_DEBUG
& DEBUG_TEXTURE
)
799 fprintf(stderr
, "%s: Using normal storage\n", __FUNCTION__
);
801 /* Normal path: copy (to cached memory) and eventually upload
802 * via another copy to GART memory and then a blit... Could
803 * eliminate one copy by going straight to (permanent) GART.
805 * Note, this will call r200ChooseTextureFormat.
807 _mesa_store_compressed_teximage2d(ctx
, target
, level
, internalFormat
, width
,
808 height
, border
, imageSize
, data
, texObj
, texImage
);
810 t
->dirty_images
[face
] |= (1 << level
);
815 static void r200CompressedTexSubImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
816 GLint xoffset
, GLint yoffset
,
817 GLsizei width
, GLsizei height
,
819 GLsizei imageSize
, const GLvoid
*data
,
820 struct gl_texture_object
*texObj
,
821 struct gl_texture_image
*texImage
)
823 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
827 /* which cube face or ordinary 2D image */
829 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
830 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
831 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
832 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
833 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
834 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
835 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
842 assert( t
); /* this _should_ be true */
844 driSwapOutTextureObject( t
);
847 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
849 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexSubImage2D");
854 _mesa_store_compressed_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
855 height
, format
, imageSize
, data
, texObj
, texImage
);
857 t
->dirty_images
[face
] |= (1 << level
);
861 #if ENABLE_HW_3D_TEXTURE
862 static void r200TexImage3D( GLcontext
*ctx
, GLenum target
, GLint level
,
863 GLint internalFormat
,
864 GLint width
, GLint height
, GLint depth
,
866 GLenum format
, GLenum type
, const GLvoid
*pixels
,
867 const struct gl_pixelstore_attrib
*packing
,
868 struct gl_texture_object
*texObj
,
869 struct gl_texture_image
*texImage
)
871 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
874 driSwapOutTextureObject( t
);
877 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
879 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
884 texImage
->IsClientData
= GL_FALSE
;
887 if (r200ValidateClientStorage( ctx
, target
,
890 format
, type
, pixels
,
891 packing
, texObj
, texImage
)) {
892 if (R200_DEBUG
& DEBUG_TEXTURE
)
893 fprintf(stderr
, "%s: Using client storage\n", __FUNCTION__
);
898 if (R200_DEBUG
& DEBUG_TEXTURE
)
899 fprintf(stderr
, "%s: Using normal storage\n", __FUNCTION__
);
901 /* Normal path: copy (to cached memory) and eventually upload
902 * via another copy to GART memory and then a blit... Could
903 * eliminate one copy by going straight to (permanent) GART.
905 * Note, this will call r200ChooseTextureFormat.
907 _mesa_store_teximage3d(ctx
, target
, level
, internalFormat
,
908 width
, height
, depth
, border
,
909 format
, type
, pixels
,
910 &ctx
->Unpack
, texObj
, texImage
);
912 t
->dirty_images
[0] |= (1 << level
);
918 #if ENABLE_HW_3D_TEXTURE
920 r200TexSubImage3D( GLcontext
*ctx
, GLenum target
, GLint level
,
921 GLint xoffset
, GLint yoffset
, GLint zoffset
,
922 GLsizei width
, GLsizei height
, GLsizei depth
,
923 GLenum format
, GLenum type
,
924 const GLvoid
*pixels
,
925 const struct gl_pixelstore_attrib
*packing
,
926 struct gl_texture_object
*texObj
,
927 struct gl_texture_image
*texImage
)
929 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
931 /* fprintf(stderr, "%s\n", __FUNCTION__); */
933 assert( t
); /* this _should_ be true */
935 driSwapOutTextureObject( t
);
938 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
940 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage3D");
943 texObj
->DriverData
= t
;
946 _mesa_store_texsubimage3d(ctx
, target
, level
, xoffset
, yoffset
, zoffset
,
947 width
, height
, depth
,
948 format
, type
, pixels
, packing
, texObj
, texImage
);
950 t
->dirty_images
[0] |= (1 << level
);
956 static void r200TexEnv( GLcontext
*ctx
, GLenum target
,
957 GLenum pname
, const GLfloat
*param
)
959 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
960 GLuint unit
= ctx
->Texture
.CurrentUnit
;
961 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
963 if ( R200_DEBUG
& DEBUG_STATE
) {
964 fprintf( stderr
, "%s( %s )\n",
965 __FUNCTION__
, _mesa_lookup_enum_by_nr( pname
) );
968 /* This is incorrect: Need to maintain this data for each of
969 * GL_TEXTURE_{123}D, GL_TEXTURE_RECTANGLE_NV, etc, and switch
970 * between them according to _ReallyEnabled.
973 case GL_TEXTURE_ENV_COLOR
: {
976 UNCLAMPED_FLOAT_TO_RGBA_CHAN( c
, texUnit
->EnvColor
);
977 envColor
= r200PackColor( 4, c
[0], c
[1], c
[2], c
[3] );
978 if ( rmesa
->hw
.tf
.cmd
[TF_TFACTOR_0
+ unit
] != envColor
) {
979 R200_STATECHANGE( rmesa
, tf
);
980 rmesa
->hw
.tf
.cmd
[TF_TFACTOR_0
+ unit
] = envColor
;
985 case GL_TEXTURE_LOD_BIAS_EXT
: {
988 const int fixed_one
= 0x8000000;
990 /* The R200's LOD bias is a signed 2's complement value with a
991 * range of -16.0 <= bias < 16.0.
993 * NOTE: Add a small bias to the bias for conform mipsel.c test.
996 min
= driQueryOptionb (&rmesa
->optionCache
, "no_neg_lod_bias") ?
998 bias
= CLAMP( bias
, min
, 16.0 );
999 b
= (int)(bias
* fixed_one
) & R200_LOD_BIAS_MASK
;
1001 if ( (rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT_X
] & R200_LOD_BIAS_MASK
) != b
) {
1002 R200_STATECHANGE( rmesa
, tex
[unit
] );
1003 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT_X
] &= ~R200_LOD_BIAS_MASK
;
1004 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT_X
] |= b
;
1008 case GL_COORD_REPLACE_ARB
:
1009 if (ctx
->Point
.PointSprite
) {
1010 R200_STATECHANGE( rmesa
, spr
);
1011 if ((GLenum
)param
[0]) {
1012 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |= R200_PS_GEN_TEX_0
<< unit
;
1014 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] &= ~(R200_PS_GEN_TEX_0
<< unit
);
1025 * Changes variables and flags for a state update, which will happen at the
1026 * next UpdateTextureState
1029 static void r200TexParameter( GLcontext
*ctx
, GLenum target
,
1030 struct gl_texture_object
*texObj
,
1031 GLenum pname
, const GLfloat
*params
)
1033 r200TexObjPtr t
= (r200TexObjPtr
) texObj
->DriverData
;
1035 if ( R200_DEBUG
& (DEBUG_STATE
|DEBUG_TEXTURE
) ) {
1036 fprintf( stderr
, "%s( %s )\n", __FUNCTION__
,
1037 _mesa_lookup_enum_by_nr( pname
) );
1041 case GL_TEXTURE_MIN_FILTER
:
1042 case GL_TEXTURE_MAG_FILTER
:
1043 case GL_TEXTURE_MAX_ANISOTROPY_EXT
:
1044 r200SetTexMaxAnisotropy( t
, texObj
->MaxAnisotropy
);
1045 r200SetTexFilter( t
, texObj
->MinFilter
, texObj
->MagFilter
);
1048 case GL_TEXTURE_WRAP_S
:
1049 case GL_TEXTURE_WRAP_T
:
1050 case GL_TEXTURE_WRAP_R
:
1051 r200SetTexWrap( t
, texObj
->WrapS
, texObj
->WrapT
, texObj
->WrapR
);
1054 case GL_TEXTURE_BORDER_COLOR
:
1055 r200SetTexBorderColor( t
, texObj
->_BorderChan
);
1058 case GL_TEXTURE_BASE_LEVEL
:
1059 case GL_TEXTURE_MAX_LEVEL
:
1060 case GL_TEXTURE_MIN_LOD
:
1061 case GL_TEXTURE_MAX_LOD
:
1062 /* This isn't the most efficient solution but there doesn't appear to
1063 * be a nice alternative. Since there's no LOD clamping,
1064 * we just have to rely on loading the right subset of mipmap levels
1065 * to simulate a clamped LOD.
1067 driSwapOutTextureObject( (driTextureObject
*) t
);
1074 /* Mark this texobj as dirty (one bit per tex unit)
1076 t
->dirty_state
= TEX_ALL
;
1081 static void r200BindTexture( GLcontext
*ctx
, GLenum target
,
1082 struct gl_texture_object
*texObj
)
1084 if ( R200_DEBUG
& (DEBUG_STATE
|DEBUG_TEXTURE
) ) {
1085 fprintf( stderr
, "%s( %p ) unit=%d\n", __FUNCTION__
, (void *)texObj
,
1086 ctx
->Texture
.CurrentUnit
);
1089 if ( (target
== GL_TEXTURE_1D
)
1090 || (target
== GL_TEXTURE_2D
)
1091 #if ENABLE_HW_3D_TEXTURE
1092 || (target
== GL_TEXTURE_3D
)
1094 || (target
== GL_TEXTURE_CUBE_MAP
)
1095 || (target
== GL_TEXTURE_RECTANGLE_NV
) ) {
1096 assert( texObj
->DriverData
!= NULL
);
1101 static void r200DeleteTexture( GLcontext
*ctx
,
1102 struct gl_texture_object
*texObj
)
1104 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1105 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
1107 if ( R200_DEBUG
& (DEBUG_STATE
|DEBUG_TEXTURE
) ) {
1108 fprintf( stderr
, "%s( %p (target = %s) )\n", __FUNCTION__
, (void *)texObj
,
1109 _mesa_lookup_enum_by_nr( texObj
->Target
) );
1114 R200_FIREVERTICES( rmesa
);
1117 driDestroyTextureObject( t
);
1119 /* Free mipmap images and the texture object itself */
1120 _mesa_delete_texture_object(ctx
, texObj
);
1124 * - Same GEN_MODE for all active bits
1125 * - Same EyePlane/ObjPlane for all active bits when using Eye/Obj
1126 * - STRQ presumably all supported (matrix means incoming R values
1127 * can end up in STQ, this has implications for vertex support,
1128 * presumably ok if maos is used, though?)
1130 * Basically impossible to do this on the fly - just collect some
1131 * basic info & do the checks from ValidateState().
1133 static void r200TexGen( GLcontext
*ctx
,
1136 const GLfloat
*params
)
1138 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1139 GLuint unit
= ctx
->Texture
.CurrentUnit
;
1140 rmesa
->recheck_texgen
[unit
] = GL_TRUE
;
1145 * Allocate a new texture object.
1146 * Called via ctx->Driver.NewTextureObject.
1147 * Note: this function will be called during context creation to
1148 * allocate the default texture objects.
1149 * Note: we could use containment here to 'derive' the driver-specific
1150 * texture object from the core mesa gl_texture_object. Not done at this time.
1151 * Fixup MaxAnisotropy according to user preference.
1153 static struct gl_texture_object
*
1154 r200NewTextureObject( GLcontext
*ctx
, GLuint name
, GLenum target
)
1156 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1157 struct gl_texture_object
*obj
;
1158 obj
= _mesa_new_texture_object(ctx
, name
, target
);
1161 obj
->MaxAnisotropy
= rmesa
->initialMaxAnisotropy
;
1162 r200AllocTexObj( obj
);
1167 void r200InitTextureFuncs( struct dd_function_table
*functions
)
1169 /* Note: we only plug in the functions we implement in the driver
1170 * since _mesa_init_driver_functions() was already called.
1172 functions
->ChooseTextureFormat
= r200ChooseTextureFormat
;
1173 functions
->TexImage1D
= r200TexImage1D
;
1174 functions
->TexImage2D
= r200TexImage2D
;
1175 #if ENABLE_HW_3D_TEXTURE
1176 functions
->TexImage3D
= r200TexImage3D
;
1178 functions
->TexImage3D
= _mesa_store_teximage3d
;
1180 functions
->TexSubImage1D
= r200TexSubImage1D
;
1181 functions
->TexSubImage2D
= r200TexSubImage2D
;
1182 #if ENABLE_HW_3D_TEXTURE
1183 functions
->TexSubImage3D
= r200TexSubImage3D
;
1185 functions
->TexSubImage3D
= _mesa_store_texsubimage3d
;
1187 functions
->NewTextureObject
= r200NewTextureObject
;
1188 functions
->BindTexture
= r200BindTexture
;
1189 functions
->DeleteTexture
= r200DeleteTexture
;
1190 functions
->IsTextureResident
= driIsTextureResident
;
1192 functions
->TexEnv
= r200TexEnv
;
1193 functions
->TexParameter
= r200TexParameter
;
1194 functions
->TexGen
= r200TexGen
;
1196 functions
->CompressedTexImage2D
= r200CompressedTexImage2D
;
1197 functions
->CompressedTexSubImage2D
= r200CompressedTexSubImage2D
;
1199 driInitTextureFormats();
1202 /* moved or obsolete code */
1203 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1204 driInitTextureObjects( ctx
, & rmesa
->swapped
,
1205 DRI_TEXMGR_DO_TEXTURE_1D
1206 | DRI_TEXMGR_DO_TEXTURE_2D
);
1208 /* Hack: r200NewTextureObject is not yet installed when the
1209 * default textures are created. Therefore set MaxAnisotropy of the
1210 * default 2D texture now. */
1211 ctx
->Shared
->Default2D
->MaxAnisotropy
= driQueryOptionf (&rmesa
->optionCache
,
1212 "def_max_anisotropy");