2 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
4 The Weather Channel (TM) funded Tungsten Graphics to develop the
5 initial release of the Radeon 8500 driver under the XFree86 license.
6 This notice must be preserved.
8 Permission is hereby granted, free of charge, to any person obtaining
9 a copy of this software and associated documentation files (the
10 "Software"), to deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sublicense, and/or sell copies of the Software, and to
13 permit persons to whom the Software is furnished to do so, subject to
14 the following conditions:
16 The above copyright notice and this permission notice (including the
17 next paragraph) shall be included in all copies or substantial
18 portions of the Software.
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
24 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 * Keith Whitwell <keith@tungstengraphics.com>
34 #include "main/glheader.h"
35 #include "main/imports.h"
36 #include "main/colormac.h"
37 #include "main/context.h"
38 #include "main/enums.h"
39 #include "main/image.h"
40 #include "main/simple_list.h"
41 #include "main/texformat.h"
42 #include "main/texstore.h"
43 #include "main/teximage.h"
44 #include "main/texobj.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__
);
106 if (t
->base
.tObj
->Target
!= GL_TEXTURE_1D
) {
109 t
->pp_txfilter
|= R200_CLAMP_T_WRAP
;
112 t
->pp_txfilter
|= R200_CLAMP_T_CLAMP_GL
;
115 case GL_CLAMP_TO_EDGE
:
116 t
->pp_txfilter
|= R200_CLAMP_T_CLAMP_LAST
;
118 case GL_CLAMP_TO_BORDER
:
119 t
->pp_txfilter
|= R200_CLAMP_T_CLAMP_GL
;
120 is_clamp_to_border
= GL_TRUE
;
122 case GL_MIRRORED_REPEAT
:
123 t
->pp_txfilter
|= R200_CLAMP_T_MIRROR
;
125 case GL_MIRROR_CLAMP_EXT
:
126 t
->pp_txfilter
|= R200_CLAMP_T_MIRROR_CLAMP_GL
;
129 case GL_MIRROR_CLAMP_TO_EDGE_EXT
:
130 t
->pp_txfilter
|= R200_CLAMP_T_MIRROR_CLAMP_LAST
;
132 case GL_MIRROR_CLAMP_TO_BORDER_EXT
:
133 t
->pp_txfilter
|= R200_CLAMP_T_MIRROR_CLAMP_GL
;
134 is_clamp_to_border
= GL_TRUE
;
137 _mesa_problem(NULL
, "bad T wrap mode in %s", __FUNCTION__
);
141 t
->pp_txformat_x
&= ~R200_CLAMP_Q_MASK
;
145 t
->pp_txformat_x
|= R200_CLAMP_Q_WRAP
;
148 t
->pp_txformat_x
|= R200_CLAMP_Q_CLAMP_GL
;
151 case GL_CLAMP_TO_EDGE
:
152 t
->pp_txformat_x
|= R200_CLAMP_Q_CLAMP_LAST
;
154 case GL_CLAMP_TO_BORDER
:
155 t
->pp_txformat_x
|= R200_CLAMP_Q_CLAMP_GL
;
156 is_clamp_to_border
= GL_TRUE
;
158 case GL_MIRRORED_REPEAT
:
159 t
->pp_txformat_x
|= R200_CLAMP_Q_MIRROR
;
161 case GL_MIRROR_CLAMP_EXT
:
162 t
->pp_txformat_x
|= R200_CLAMP_Q_MIRROR_CLAMP_GL
;
165 case GL_MIRROR_CLAMP_TO_EDGE_EXT
:
166 t
->pp_txformat_x
|= R200_CLAMP_Q_MIRROR_CLAMP_LAST
;
168 case GL_MIRROR_CLAMP_TO_BORDER_EXT
:
169 t
->pp_txformat_x
|= R200_CLAMP_Q_MIRROR_CLAMP_GL
;
170 is_clamp_to_border
= GL_TRUE
;
173 _mesa_problem(NULL
, "bad R wrap mode in %s", __FUNCTION__
);
176 if ( is_clamp_to_border
) {
177 t
->pp_txfilter
|= R200_BORDER_MODE_D3D
;
180 t
->border_fallback
= (is_clamp
&& is_clamp_to_border
);
183 static void r200SetTexMaxAnisotropy( r200TexObjPtr t
, GLfloat max
)
185 t
->pp_txfilter
&= ~R200_MAX_ANISO_MASK
;
188 t
->pp_txfilter
|= R200_MAX_ANISO_1_TO_1
;
189 } else if ( max
<= 2.0 ) {
190 t
->pp_txfilter
|= R200_MAX_ANISO_2_TO_1
;
191 } else if ( max
<= 4.0 ) {
192 t
->pp_txfilter
|= R200_MAX_ANISO_4_TO_1
;
193 } else if ( max
<= 8.0 ) {
194 t
->pp_txfilter
|= R200_MAX_ANISO_8_TO_1
;
196 t
->pp_txfilter
|= R200_MAX_ANISO_16_TO_1
;
201 * Set the texture magnification and minification modes.
203 * \param t Texture whose filter modes are to be set
204 * \param minf Texture minification mode
205 * \param magf Texture magnification mode
208 static void r200SetTexFilter( r200TexObjPtr t
, GLenum minf
, GLenum magf
)
210 GLuint anisotropy
= (t
->pp_txfilter
& R200_MAX_ANISO_MASK
);
212 t
->pp_txfilter
&= ~(R200_MIN_FILTER_MASK
| R200_MAG_FILTER_MASK
);
213 t
->pp_txformat_x
&= ~R200_VOLUME_FILTER_MASK
;
215 if ( anisotropy
== R200_MAX_ANISO_1_TO_1
) {
218 t
->pp_txfilter
|= R200_MIN_FILTER_NEAREST
;
221 t
->pp_txfilter
|= R200_MIN_FILTER_LINEAR
;
223 case GL_NEAREST_MIPMAP_NEAREST
:
224 t
->pp_txfilter
|= R200_MIN_FILTER_NEAREST_MIP_NEAREST
;
226 case GL_NEAREST_MIPMAP_LINEAR
:
227 t
->pp_txfilter
|= R200_MIN_FILTER_LINEAR_MIP_NEAREST
;
229 case GL_LINEAR_MIPMAP_NEAREST
:
230 t
->pp_txfilter
|= R200_MIN_FILTER_NEAREST_MIP_LINEAR
;
232 case GL_LINEAR_MIPMAP_LINEAR
:
233 t
->pp_txfilter
|= R200_MIN_FILTER_LINEAR_MIP_LINEAR
;
239 t
->pp_txfilter
|= R200_MIN_FILTER_ANISO_NEAREST
;
242 t
->pp_txfilter
|= R200_MIN_FILTER_ANISO_LINEAR
;
244 case GL_NEAREST_MIPMAP_NEAREST
:
245 case GL_LINEAR_MIPMAP_NEAREST
:
246 t
->pp_txfilter
|= R200_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST
;
248 case GL_NEAREST_MIPMAP_LINEAR
:
249 case GL_LINEAR_MIPMAP_LINEAR
:
250 t
->pp_txfilter
|= R200_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR
;
255 /* Note we don't have 3D mipmaps so only use the mag filter setting
256 * to set the 3D texture filter mode.
260 t
->pp_txfilter
|= R200_MAG_FILTER_NEAREST
;
261 t
->pp_txformat_x
|= R200_VOLUME_FILTER_NEAREST
;
264 t
->pp_txfilter
|= R200_MAG_FILTER_LINEAR
;
265 t
->pp_txformat_x
|= R200_VOLUME_FILTER_LINEAR
;
270 static void r200SetTexBorderColor( r200TexObjPtr t
, const GLfloat color
[4] )
273 CLAMPED_FLOAT_TO_UBYTE(c
[0], color
[0]);
274 CLAMPED_FLOAT_TO_UBYTE(c
[1], color
[1]);
275 CLAMPED_FLOAT_TO_UBYTE(c
[2], color
[2]);
276 CLAMPED_FLOAT_TO_UBYTE(c
[3], color
[3]);
277 t
->pp_border_color
= r200PackColor( 4, c
[0], c
[1], c
[2], c
[3] );
282 * Allocate space for and load the mesa images into the texture memory block.
283 * This will happen before drawing with a new texture, or drawing with a
284 * texture after it was swapped out or teximaged again.
287 static r200TexObjPtr
r200AllocTexObj( struct gl_texture_object
*texObj
)
291 t
= CALLOC_STRUCT( r200_tex_obj
);
292 texObj
->DriverData
= t
;
294 if ( R200_DEBUG
& DEBUG_TEXTURE
) {
295 fprintf( stderr
, "%s( %p, %p )\n", __FUNCTION__
, (void *)texObj
,
299 /* Initialize non-image-dependent parts of the state:
301 t
->base
.tObj
= texObj
;
302 t
->border_fallback
= GL_FALSE
;
304 make_empty_list( & t
->base
);
306 r200SetTexWrap( t
, texObj
->WrapS
, texObj
->WrapT
, texObj
->WrapR
);
307 r200SetTexMaxAnisotropy( t
, texObj
->MaxAnisotropy
);
308 r200SetTexFilter( t
, texObj
->MinFilter
, texObj
->MagFilter
);
309 r200SetTexBorderColor( t
, texObj
->BorderColor
);
315 /* try to find a format which will only need a memcopy */
316 static const struct gl_texture_format
*
317 r200Choose8888TexFormat( GLenum srcFormat
, GLenum srcType
)
320 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
322 if ((srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8
) ||
323 (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
) ||
324 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) ||
325 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_BYTE
&& littleEndian
)) {
326 return &_mesa_texformat_rgba8888
;
328 else if ((srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) ||
329 (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
&& littleEndian
) ||
330 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_INT_8_8_8_8
) ||
331 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
)) {
332 return &_mesa_texformat_rgba8888_rev
;
334 else return _dri_texformat_argb8888
;
337 static const struct gl_texture_format
*
338 r200ChooseTextureFormat( GLcontext
*ctx
, GLint internalFormat
,
339 GLenum format
, GLenum type
)
341 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
342 const GLboolean do32bpt
=
343 ( rmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_32
);
344 const GLboolean force16bpt
=
345 ( rmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_FORCE_16
);
348 switch ( internalFormat
) {
351 case GL_COMPRESSED_RGBA
:
353 case GL_UNSIGNED_INT_10_10_10_2
:
354 case GL_UNSIGNED_INT_2_10_10_10_REV
:
355 return do32bpt
? _dri_texformat_argb8888
: _dri_texformat_argb1555
;
356 case GL_UNSIGNED_SHORT_4_4_4_4
:
357 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
358 return _dri_texformat_argb4444
;
359 case GL_UNSIGNED_SHORT_5_5_5_1
:
360 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
361 return _dri_texformat_argb1555
;
364 r200Choose8888TexFormat(format
, type
) : _dri_texformat_argb4444
;
369 case GL_COMPRESSED_RGB
:
371 case GL_UNSIGNED_SHORT_4_4_4_4
:
372 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
373 return _dri_texformat_argb4444
;
374 case GL_UNSIGNED_SHORT_5_5_5_1
:
375 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
376 return _dri_texformat_argb1555
;
377 case GL_UNSIGNED_SHORT_5_6_5
:
378 case GL_UNSIGNED_SHORT_5_6_5_REV
:
379 return _dri_texformat_rgb565
;
381 return do32bpt
? _dri_texformat_argb8888
: _dri_texformat_rgb565
;
389 r200Choose8888TexFormat(format
, type
) : _dri_texformat_argb4444
;
393 return _dri_texformat_argb4444
;
396 return _dri_texformat_argb1555
;
402 return !force16bpt
? _dri_texformat_argb8888
: _dri_texformat_rgb565
;
407 return _dri_texformat_rgb565
;
414 case GL_COMPRESSED_ALPHA
:
415 /* can't use a8 format since interpreting hw I8 as a8 would result
416 in wrong rgb values (same as alpha value instead of 0). */
417 return _dri_texformat_al88
;
425 case GL_COMPRESSED_LUMINANCE
:
426 return _dri_texformat_l8
;
429 case GL_LUMINANCE_ALPHA
:
430 case GL_LUMINANCE4_ALPHA4
:
431 case GL_LUMINANCE6_ALPHA2
:
432 case GL_LUMINANCE8_ALPHA8
:
433 case GL_LUMINANCE12_ALPHA4
:
434 case GL_LUMINANCE12_ALPHA12
:
435 case GL_LUMINANCE16_ALPHA16
:
436 case GL_COMPRESSED_LUMINANCE_ALPHA
:
437 return _dri_texformat_al88
;
444 case GL_COMPRESSED_INTENSITY
:
445 return _dri_texformat_i8
;
448 if (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
449 type
== GL_UNSIGNED_BYTE
)
450 return &_mesa_texformat_ycbcr
;
452 return &_mesa_texformat_ycbcr_rev
;
456 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
457 return &_mesa_texformat_rgb_dxt1
;
459 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
460 return &_mesa_texformat_rgba_dxt1
;
464 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
465 return &_mesa_texformat_rgba_dxt3
;
467 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
468 return &_mesa_texformat_rgba_dxt5
;
472 "unexpected internalFormat 0x%x in r200ChooseTextureFormat",
473 (int) internalFormat
);
477 return NULL
; /* never get here */
482 r200ValidateClientStorage( GLcontext
*ctx
, GLenum target
,
483 GLint internalFormat
,
484 GLint srcWidth
, GLint srcHeight
,
485 GLenum format
, GLenum type
, const void *pixels
,
486 const struct gl_pixelstore_attrib
*packing
,
487 struct gl_texture_object
*texObj
,
488 struct gl_texture_image
*texImage
)
491 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
493 if ( R200_DEBUG
& DEBUG_TEXTURE
)
494 fprintf(stderr
, "intformat %s format %s type %s\n",
495 _mesa_lookup_enum_by_nr( internalFormat
),
496 _mesa_lookup_enum_by_nr( format
),
497 _mesa_lookup_enum_by_nr( type
));
499 if (!ctx
->Unpack
.ClientStorage
)
502 if (ctx
->_ImageTransferState
||
503 texImage
->IsCompressed
||
504 texObj
->GenerateMipmap
)
508 /* This list is incomplete, may be different on ppc???
510 switch ( internalFormat
) {
512 if ( format
== GL_BGRA
&& type
== GL_UNSIGNED_INT_8_8_8_8_REV
) {
513 texImage
->TexFormat
= _dri_texformat_argb8888
;
520 if ( format
== GL_RGB
&& type
== GL_UNSIGNED_SHORT_5_6_5
) {
521 texImage
->TexFormat
= _dri_texformat_rgb565
;
528 if ( format
== GL_YCBCR_MESA
&&
529 type
== GL_UNSIGNED_SHORT_8_8_REV_APPLE
) {
530 texImage
->TexFormat
= &_mesa_texformat_ycbcr_rev
;
532 else if ( format
== GL_YCBCR_MESA
&&
533 (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
534 type
== GL_UNSIGNED_BYTE
)) {
535 texImage
->TexFormat
= &_mesa_texformat_ycbcr
;
545 /* Could deal with these packing issues, but currently don't:
547 if (packing
->SkipPixels
||
549 packing
->SwapBytes
||
555 GLint srcRowStride
= _mesa_image_row_stride(packing
, srcWidth
,
559 if ( R200_DEBUG
& DEBUG_TEXTURE
)
560 fprintf(stderr
, "%s: srcRowStride %d/%x\n",
561 __FUNCTION__
, srcRowStride
, srcRowStride
);
563 /* Could check this later in upload, pitch restrictions could be
564 * relaxed, but would need to store the image pitch somewhere,
565 * as packing details might change before image is uploaded:
567 if (!r200IsGartMemory( rmesa
, pixels
, srcHeight
* srcRowStride
) ||
572 /* Have validated that _mesa_transfer_teximage would be a straight
573 * memcpy at this point. NOTE: future calls to TexSubImage will
574 * overwrite the client data. This is explicitly mentioned in the
577 texImage
->Data
= (void *)pixels
;
578 texImage
->IsClientData
= GL_TRUE
;
579 texImage
->RowStride
= srcRowStride
/ texImage
->TexFormat
->TexelBytes
;
586 static void r200TexImage1D( GLcontext
*ctx
, GLenum target
, GLint level
,
587 GLint internalFormat
,
588 GLint width
, GLint border
,
589 GLenum format
, GLenum type
, 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
;
597 driSwapOutTextureObject( t
);
600 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
602 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
607 /* Note, this will call ChooseTextureFormat */
608 _mesa_store_teximage1d(ctx
, target
, level
, internalFormat
,
609 width
, border
, format
, type
, pixels
,
610 &ctx
->Unpack
, texObj
, texImage
);
612 t
->dirty_images
[0] |= (1 << level
);
616 static void r200TexSubImage1D( GLcontext
*ctx
, GLenum target
, GLint level
,
619 GLenum format
, GLenum type
,
620 const GLvoid
*pixels
,
621 const struct gl_pixelstore_attrib
*packing
,
622 struct gl_texture_object
*texObj
,
623 struct gl_texture_image
*texImage
)
625 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
627 assert( t
); /* this _should_ be true */
629 driSwapOutTextureObject( t
);
632 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
634 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
639 _mesa_store_texsubimage1d(ctx
, target
, level
, xoffset
, width
,
640 format
, type
, pixels
, packing
, texObj
,
643 t
->dirty_images
[0] |= (1 << level
);
647 static void r200TexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
648 GLint internalFormat
,
649 GLint width
, GLint height
, GLint border
,
650 GLenum format
, GLenum type
, const GLvoid
*pixels
,
651 const struct gl_pixelstore_attrib
*packing
,
652 struct gl_texture_object
*texObj
,
653 struct gl_texture_image
*texImage
)
655 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
658 /* which cube face or ordinary 2D image */
660 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
661 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
662 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
663 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
664 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
665 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
666 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
674 driSwapOutTextureObject( t
);
677 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
679 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
684 texImage
->IsClientData
= GL_FALSE
;
686 if (r200ValidateClientStorage( ctx
, target
,
689 format
, type
, pixels
,
690 packing
, texObj
, texImage
)) {
691 if (R200_DEBUG
& DEBUG_TEXTURE
)
692 fprintf(stderr
, "%s: Using client storage\n", __FUNCTION__
);
695 if (R200_DEBUG
& DEBUG_TEXTURE
)
696 fprintf(stderr
, "%s: Using normal storage\n", __FUNCTION__
);
698 /* Normal path: copy (to cached memory) and eventually upload
699 * via another copy to GART memory and then a blit... Could
700 * eliminate one copy by going straight to (permanent) GART.
702 * Note, this will call r200ChooseTextureFormat.
704 _mesa_store_teximage2d(ctx
, target
, level
, internalFormat
,
705 width
, height
, border
, format
, type
, pixels
,
706 &ctx
->Unpack
, texObj
, texImage
);
708 t
->dirty_images
[face
] |= (1 << level
);
713 static void r200TexSubImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
714 GLint xoffset
, GLint yoffset
,
715 GLsizei width
, GLsizei height
,
716 GLenum format
, GLenum type
,
717 const GLvoid
*pixels
,
718 const struct gl_pixelstore_attrib
*packing
,
719 struct gl_texture_object
*texObj
,
720 struct gl_texture_image
*texImage
)
722 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
725 /* which cube face or ordinary 2D image */
727 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
728 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
729 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
730 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
731 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
732 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
733 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
740 assert( t
); /* this _should_ be true */
742 driSwapOutTextureObject( t
);
745 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
747 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
752 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
753 height
, format
, type
, pixels
, packing
, texObj
,
756 t
->dirty_images
[face
] |= (1 << level
);
760 static void r200CompressedTexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
761 GLint internalFormat
,
762 GLint width
, GLint height
, GLint border
,
763 GLsizei imageSize
, const GLvoid
*data
,
764 struct gl_texture_object
*texObj
,
765 struct gl_texture_image
*texImage
)
767 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
770 /* which cube face or ordinary 2D image */
772 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
773 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
774 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
775 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
776 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
777 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
778 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
786 driSwapOutTextureObject( t
);
789 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
791 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2D");
796 texImage
->IsClientData
= GL_FALSE
;
797 /* can't call this, different parameters. Would never evaluate to true anyway currently
798 if (r200ValidateClientStorage( ctx, target,
801 format, type, pixels,
802 packing, texObj, texImage)) {
803 if (R200_DEBUG & DEBUG_TEXTURE)
804 fprintf(stderr, "%s: Using client storage\n", __FUNCTION__);
807 if (R200_DEBUG
& DEBUG_TEXTURE
)
808 fprintf(stderr
, "%s: Using normal storage\n", __FUNCTION__
);
810 /* Normal path: copy (to cached memory) and eventually upload
811 * via another copy to GART memory and then a blit... Could
812 * eliminate one copy by going straight to (permanent) GART.
814 * Note, this will call r200ChooseTextureFormat.
816 _mesa_store_compressed_teximage2d(ctx
, target
, level
, internalFormat
, width
,
817 height
, border
, imageSize
, data
, texObj
, texImage
);
819 t
->dirty_images
[face
] |= (1 << level
);
824 static void r200CompressedTexSubImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
825 GLint xoffset
, GLint yoffset
,
826 GLsizei width
, GLsizei height
,
828 GLsizei imageSize
, const GLvoid
*data
,
829 struct gl_texture_object
*texObj
,
830 struct gl_texture_image
*texImage
)
832 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
836 /* which cube face or ordinary 2D image */
838 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
839 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
840 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
841 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
842 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
843 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
844 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
851 assert( t
); /* this _should_ be true */
853 driSwapOutTextureObject( t
);
856 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
858 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexSubImage2D");
863 _mesa_store_compressed_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
864 height
, format
, imageSize
, data
, texObj
, texImage
);
866 t
->dirty_images
[face
] |= (1 << level
);
870 #if ENABLE_HW_3D_TEXTURE
871 static void r200TexImage3D( GLcontext
*ctx
, GLenum target
, GLint level
,
872 GLint internalFormat
,
873 GLint width
, GLint height
, GLint depth
,
875 GLenum format
, GLenum type
, const GLvoid
*pixels
,
876 const struct gl_pixelstore_attrib
*packing
,
877 struct gl_texture_object
*texObj
,
878 struct gl_texture_image
*texImage
)
880 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
883 driSwapOutTextureObject( t
);
886 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
888 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
893 texImage
->IsClientData
= GL_FALSE
;
896 if (r200ValidateClientStorage( ctx
, target
,
899 format
, type
, pixels
,
900 packing
, texObj
, texImage
)) {
901 if (R200_DEBUG
& DEBUG_TEXTURE
)
902 fprintf(stderr
, "%s: Using client storage\n", __FUNCTION__
);
907 if (R200_DEBUG
& DEBUG_TEXTURE
)
908 fprintf(stderr
, "%s: Using normal storage\n", __FUNCTION__
);
910 /* Normal path: copy (to cached memory) and eventually upload
911 * via another copy to GART memory and then a blit... Could
912 * eliminate one copy by going straight to (permanent) GART.
914 * Note, this will call r200ChooseTextureFormat.
916 _mesa_store_teximage3d(ctx
, target
, level
, internalFormat
,
917 width
, height
, depth
, border
,
918 format
, type
, pixels
,
919 &ctx
->Unpack
, texObj
, texImage
);
921 t
->dirty_images
[0] |= (1 << level
);
927 #if ENABLE_HW_3D_TEXTURE
929 r200TexSubImage3D( GLcontext
*ctx
, GLenum target
, GLint level
,
930 GLint xoffset
, GLint yoffset
, GLint zoffset
,
931 GLsizei width
, GLsizei height
, GLsizei depth
,
932 GLenum format
, GLenum type
,
933 const GLvoid
*pixels
,
934 const struct gl_pixelstore_attrib
*packing
,
935 struct gl_texture_object
*texObj
,
936 struct gl_texture_image
*texImage
)
938 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
940 /* fprintf(stderr, "%s\n", __FUNCTION__); */
942 assert( t
); /* this _should_ be true */
944 driSwapOutTextureObject( t
);
947 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
949 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage3D");
952 texObj
->DriverData
= t
;
955 _mesa_store_texsubimage3d(ctx
, target
, level
, xoffset
, yoffset
, zoffset
,
956 width
, height
, depth
,
957 format
, type
, pixels
, packing
, texObj
, texImage
);
959 t
->dirty_images
[0] |= (1 << level
);
965 static void r200TexEnv( GLcontext
*ctx
, GLenum target
,
966 GLenum pname
, const GLfloat
*param
)
968 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
969 GLuint unit
= ctx
->Texture
.CurrentUnit
;
970 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
972 if ( R200_DEBUG
& DEBUG_STATE
) {
973 fprintf( stderr
, "%s( %s )\n",
974 __FUNCTION__
, _mesa_lookup_enum_by_nr( pname
) );
977 /* This is incorrect: Need to maintain this data for each of
978 * GL_TEXTURE_{123}D, GL_TEXTURE_RECTANGLE_NV, etc, and switch
979 * between them according to _ReallyEnabled.
982 case GL_TEXTURE_ENV_COLOR
: {
985 UNCLAMPED_FLOAT_TO_RGBA_CHAN( c
, texUnit
->EnvColor
);
986 envColor
= r200PackColor( 4, c
[0], c
[1], c
[2], c
[3] );
987 if ( rmesa
->hw
.tf
.cmd
[TF_TFACTOR_0
+ unit
] != envColor
) {
988 R200_STATECHANGE( rmesa
, tf
);
989 rmesa
->hw
.tf
.cmd
[TF_TFACTOR_0
+ unit
] = envColor
;
994 case GL_TEXTURE_LOD_BIAS_EXT
: {
997 const int fixed_one
= 0x8000000;
999 /* The R200's LOD bias is a signed 2's complement value with a
1000 * range of -16.0 <= bias < 16.0.
1002 * NOTE: Add a small bias to the bias for conform mipsel.c test.
1004 bias
= *param
+ .01;
1005 min
= driQueryOptionb (&rmesa
->optionCache
, "no_neg_lod_bias") ?
1007 bias
= CLAMP( bias
, min
, 16.0 );
1008 b
= (int)(bias
* fixed_one
) & R200_LOD_BIAS_MASK
;
1010 if ( (rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT_X
] & R200_LOD_BIAS_MASK
) != b
) {
1011 R200_STATECHANGE( rmesa
, tex
[unit
] );
1012 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT_X
] &= ~R200_LOD_BIAS_MASK
;
1013 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT_X
] |= b
;
1017 case GL_COORD_REPLACE_ARB
:
1018 if (ctx
->Point
.PointSprite
) {
1019 R200_STATECHANGE( rmesa
, spr
);
1020 if ((GLenum
)param
[0]) {
1021 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |= R200_PS_GEN_TEX_0
<< unit
;
1023 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] &= ~(R200_PS_GEN_TEX_0
<< unit
);
1034 * Changes variables and flags for a state update, which will happen at the
1035 * next UpdateTextureState
1038 static void r200TexParameter( GLcontext
*ctx
, GLenum target
,
1039 struct gl_texture_object
*texObj
,
1040 GLenum pname
, const GLfloat
*params
)
1042 r200TexObjPtr t
= (r200TexObjPtr
) texObj
->DriverData
;
1044 if ( R200_DEBUG
& (DEBUG_STATE
|DEBUG_TEXTURE
) ) {
1045 fprintf( stderr
, "%s( %s )\n", __FUNCTION__
,
1046 _mesa_lookup_enum_by_nr( pname
) );
1050 case GL_TEXTURE_MIN_FILTER
:
1051 case GL_TEXTURE_MAG_FILTER
:
1052 case GL_TEXTURE_MAX_ANISOTROPY_EXT
:
1053 r200SetTexMaxAnisotropy( t
, texObj
->MaxAnisotropy
);
1054 r200SetTexFilter( t
, texObj
->MinFilter
, texObj
->MagFilter
);
1057 case GL_TEXTURE_WRAP_S
:
1058 case GL_TEXTURE_WRAP_T
:
1059 case GL_TEXTURE_WRAP_R
:
1060 r200SetTexWrap( t
, texObj
->WrapS
, texObj
->WrapT
, texObj
->WrapR
);
1063 case GL_TEXTURE_BORDER_COLOR
:
1064 r200SetTexBorderColor( t
, texObj
->BorderColor
);
1067 case GL_TEXTURE_BASE_LEVEL
:
1068 case GL_TEXTURE_MAX_LEVEL
:
1069 case GL_TEXTURE_MIN_LOD
:
1070 case GL_TEXTURE_MAX_LOD
:
1071 /* This isn't the most efficient solution but there doesn't appear to
1072 * be a nice alternative. Since there's no LOD clamping,
1073 * we just have to rely on loading the right subset of mipmap levels
1074 * to simulate a clamped LOD.
1076 driSwapOutTextureObject( (driTextureObject
*) t
);
1083 /* Mark this texobj as dirty (one bit per tex unit)
1085 t
->dirty_state
= TEX_ALL
;
1090 static void r200BindTexture( GLcontext
*ctx
, GLenum target
,
1091 struct gl_texture_object
*texObj
)
1093 if ( R200_DEBUG
& (DEBUG_STATE
|DEBUG_TEXTURE
) ) {
1094 fprintf( stderr
, "%s( %p ) unit=%d\n", __FUNCTION__
, (void *)texObj
,
1095 ctx
->Texture
.CurrentUnit
);
1098 if ( (target
== GL_TEXTURE_1D
)
1099 || (target
== GL_TEXTURE_2D
)
1100 #if ENABLE_HW_3D_TEXTURE
1101 || (target
== GL_TEXTURE_3D
)
1103 || (target
== GL_TEXTURE_CUBE_MAP
)
1104 || (target
== GL_TEXTURE_RECTANGLE_NV
) ) {
1105 assert( texObj
->DriverData
!= NULL
);
1110 static void r200DeleteTexture( GLcontext
*ctx
,
1111 struct gl_texture_object
*texObj
)
1113 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1114 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
1116 if ( R200_DEBUG
& (DEBUG_STATE
|DEBUG_TEXTURE
) ) {
1117 fprintf( stderr
, "%s( %p (target = %s) )\n", __FUNCTION__
, (void *)texObj
,
1118 _mesa_lookup_enum_by_nr( texObj
->Target
) );
1123 R200_FIREVERTICES( rmesa
);
1126 driDestroyTextureObject( t
);
1128 /* Free mipmap images and the texture object itself */
1129 _mesa_delete_texture_object(ctx
, texObj
);
1133 * - Same GEN_MODE for all active bits
1134 * - Same EyePlane/ObjPlane for all active bits when using Eye/Obj
1135 * - STRQ presumably all supported (matrix means incoming R values
1136 * can end up in STQ, this has implications for vertex support,
1137 * presumably ok if maos is used, though?)
1139 * Basically impossible to do this on the fly - just collect some
1140 * basic info & do the checks from ValidateState().
1142 static void r200TexGen( GLcontext
*ctx
,
1145 const GLfloat
*params
)
1147 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1148 GLuint unit
= ctx
->Texture
.CurrentUnit
;
1149 rmesa
->recheck_texgen
[unit
] = GL_TRUE
;
1154 * Allocate a new texture object.
1155 * Called via ctx->Driver.NewTextureObject.
1156 * Note: this function will be called during context creation to
1157 * allocate the default texture objects.
1158 * Note: we could use containment here to 'derive' the driver-specific
1159 * texture object from the core mesa gl_texture_object. Not done at this time.
1160 * Fixup MaxAnisotropy according to user preference.
1162 static struct gl_texture_object
*
1163 r200NewTextureObject( GLcontext
*ctx
, GLuint name
, GLenum target
)
1165 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1166 struct gl_texture_object
*obj
;
1167 obj
= _mesa_new_texture_object(ctx
, name
, target
);
1170 obj
->MaxAnisotropy
= rmesa
->initialMaxAnisotropy
;
1171 r200AllocTexObj( obj
);
1176 void r200InitTextureFuncs( struct dd_function_table
*functions
)
1178 /* Note: we only plug in the functions we implement in the driver
1179 * since _mesa_init_driver_functions() was already called.
1181 functions
->ChooseTextureFormat
= r200ChooseTextureFormat
;
1182 functions
->TexImage1D
= r200TexImage1D
;
1183 functions
->TexImage2D
= r200TexImage2D
;
1184 #if ENABLE_HW_3D_TEXTURE
1185 functions
->TexImage3D
= r200TexImage3D
;
1187 functions
->TexImage3D
= _mesa_store_teximage3d
;
1189 functions
->TexSubImage1D
= r200TexSubImage1D
;
1190 functions
->TexSubImage2D
= r200TexSubImage2D
;
1191 #if ENABLE_HW_3D_TEXTURE
1192 functions
->TexSubImage3D
= r200TexSubImage3D
;
1194 functions
->TexSubImage3D
= _mesa_store_texsubimage3d
;
1196 functions
->NewTextureObject
= r200NewTextureObject
;
1197 functions
->BindTexture
= r200BindTexture
;
1198 functions
->DeleteTexture
= r200DeleteTexture
;
1199 functions
->IsTextureResident
= driIsTextureResident
;
1201 functions
->TexEnv
= r200TexEnv
;
1202 functions
->TexParameter
= r200TexParameter
;
1203 functions
->TexGen
= r200TexGen
;
1205 functions
->CompressedTexImage2D
= r200CompressedTexImage2D
;
1206 functions
->CompressedTexSubImage2D
= r200CompressedTexSubImage2D
;
1208 driInitTextureFormats();
1211 /* moved or obsolete code */
1212 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1213 driInitTextureObjects( ctx
, & rmesa
->swapped
,
1214 DRI_TEXMGR_DO_TEXTURE_1D
1215 | DRI_TEXMGR_DO_TEXTURE_2D
);
1217 /* Hack: r200NewTextureObject is not yet installed when the
1218 * default textures are created. Therefore set MaxAnisotropy of the
1219 * default 2D texture now. */
1220 ctx
->Shared
->Default2D
->MaxAnisotropy
= driQueryOptionf (&rmesa
->optionCache
,
1221 "def_max_anisotropy");