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
, GLubyte c
[4] )
272 t
->pp_border_color
= r200PackColor( 4, c
[0], c
[1], c
[2], c
[3] );
277 * Allocate space for and load the mesa images into the texture memory block.
278 * This will happen before drawing with a new texture, or drawing with a
279 * texture after it was swapped out or teximaged again.
282 static r200TexObjPtr
r200AllocTexObj( struct gl_texture_object
*texObj
)
286 t
= CALLOC_STRUCT( r200_tex_obj
);
287 texObj
->DriverData
= t
;
289 if ( R200_DEBUG
& DEBUG_TEXTURE
) {
290 fprintf( stderr
, "%s( %p, %p )\n", __FUNCTION__
, (void *)texObj
,
294 /* Initialize non-image-dependent parts of the state:
296 t
->base
.tObj
= texObj
;
297 t
->border_fallback
= GL_FALSE
;
299 make_empty_list( & t
->base
);
301 r200SetTexWrap( t
, texObj
->WrapS
, texObj
->WrapT
, texObj
->WrapR
);
302 r200SetTexMaxAnisotropy( t
, texObj
->MaxAnisotropy
);
303 r200SetTexFilter( t
, texObj
->MinFilter
, texObj
->MagFilter
);
304 r200SetTexBorderColor( t
, texObj
->_BorderChan
);
310 /* try to find a format which will only need a memcopy */
311 static const struct gl_texture_format
*
312 r200Choose8888TexFormat( GLenum srcFormat
, GLenum srcType
)
315 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
317 if ((srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8
) ||
318 (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
) ||
319 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) ||
320 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_BYTE
&& littleEndian
)) {
321 return &_mesa_texformat_rgba8888
;
323 else if ((srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) ||
324 (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
&& littleEndian
) ||
325 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_INT_8_8_8_8
) ||
326 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
)) {
327 return &_mesa_texformat_rgba8888_rev
;
329 else return _dri_texformat_argb8888
;
332 static const struct gl_texture_format
*
333 r200ChooseTextureFormat( GLcontext
*ctx
, GLint internalFormat
,
334 GLenum format
, GLenum type
)
336 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
337 const GLboolean do32bpt
=
338 ( rmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_32
);
339 const GLboolean force16bpt
=
340 ( rmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_FORCE_16
);
343 switch ( internalFormat
) {
346 case GL_COMPRESSED_RGBA
:
348 case GL_UNSIGNED_INT_10_10_10_2
:
349 case GL_UNSIGNED_INT_2_10_10_10_REV
:
350 return do32bpt
? _dri_texformat_argb8888
: _dri_texformat_argb1555
;
351 case GL_UNSIGNED_SHORT_4_4_4_4
:
352 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
353 return _dri_texformat_argb4444
;
354 case GL_UNSIGNED_SHORT_5_5_5_1
:
355 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
356 return _dri_texformat_argb1555
;
359 r200Choose8888TexFormat(format
, type
) : _dri_texformat_argb4444
;
364 case GL_COMPRESSED_RGB
:
366 case GL_UNSIGNED_SHORT_4_4_4_4
:
367 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
368 return _dri_texformat_argb4444
;
369 case GL_UNSIGNED_SHORT_5_5_5_1
:
370 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
371 return _dri_texformat_argb1555
;
372 case GL_UNSIGNED_SHORT_5_6_5
:
373 case GL_UNSIGNED_SHORT_5_6_5_REV
:
374 return _dri_texformat_rgb565
;
376 return do32bpt
? _dri_texformat_argb8888
: _dri_texformat_rgb565
;
384 r200Choose8888TexFormat(format
, type
) : _dri_texformat_argb4444
;
388 return _dri_texformat_argb4444
;
391 return _dri_texformat_argb1555
;
397 return !force16bpt
? _dri_texformat_argb8888
: _dri_texformat_rgb565
;
402 return _dri_texformat_rgb565
;
409 case GL_COMPRESSED_ALPHA
:
410 /* can't use a8 format since interpreting hw I8 as a8 would result
411 in wrong rgb values (same as alpha value instead of 0). */
412 return _dri_texformat_al88
;
420 case GL_COMPRESSED_LUMINANCE
:
421 return _dri_texformat_l8
;
424 case GL_LUMINANCE_ALPHA
:
425 case GL_LUMINANCE4_ALPHA4
:
426 case GL_LUMINANCE6_ALPHA2
:
427 case GL_LUMINANCE8_ALPHA8
:
428 case GL_LUMINANCE12_ALPHA4
:
429 case GL_LUMINANCE12_ALPHA12
:
430 case GL_LUMINANCE16_ALPHA16
:
431 case GL_COMPRESSED_LUMINANCE_ALPHA
:
432 return _dri_texformat_al88
;
439 case GL_COMPRESSED_INTENSITY
:
440 return _dri_texformat_i8
;
443 if (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
444 type
== GL_UNSIGNED_BYTE
)
445 return &_mesa_texformat_ycbcr
;
447 return &_mesa_texformat_ycbcr_rev
;
451 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
452 return &_mesa_texformat_rgb_dxt1
;
454 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
455 return &_mesa_texformat_rgba_dxt1
;
459 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
460 return &_mesa_texformat_rgba_dxt3
;
462 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
463 return &_mesa_texformat_rgba_dxt5
;
467 "unexpected internalFormat 0x%x in r200ChooseTextureFormat",
468 (int) internalFormat
);
472 return NULL
; /* never get here */
477 r200ValidateClientStorage( GLcontext
*ctx
, GLenum target
,
478 GLint internalFormat
,
479 GLint srcWidth
, GLint srcHeight
,
480 GLenum format
, GLenum type
, const void *pixels
,
481 const struct gl_pixelstore_attrib
*packing
,
482 struct gl_texture_object
*texObj
,
483 struct gl_texture_image
*texImage
)
486 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
488 if ( R200_DEBUG
& DEBUG_TEXTURE
)
489 fprintf(stderr
, "intformat %s format %s type %s\n",
490 _mesa_lookup_enum_by_nr( internalFormat
),
491 _mesa_lookup_enum_by_nr( format
),
492 _mesa_lookup_enum_by_nr( type
));
494 if (!ctx
->Unpack
.ClientStorage
)
497 if (ctx
->_ImageTransferState
||
498 texImage
->IsCompressed
||
499 texObj
->GenerateMipmap
)
503 /* This list is incomplete, may be different on ppc???
505 switch ( internalFormat
) {
507 if ( format
== GL_BGRA
&& type
== GL_UNSIGNED_INT_8_8_8_8_REV
) {
508 texImage
->TexFormat
= _dri_texformat_argb8888
;
515 if ( format
== GL_RGB
&& type
== GL_UNSIGNED_SHORT_5_6_5
) {
516 texImage
->TexFormat
= _dri_texformat_rgb565
;
523 if ( format
== GL_YCBCR_MESA
&&
524 type
== GL_UNSIGNED_SHORT_8_8_REV_APPLE
) {
525 texImage
->TexFormat
= &_mesa_texformat_ycbcr_rev
;
527 else if ( format
== GL_YCBCR_MESA
&&
528 (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
529 type
== GL_UNSIGNED_BYTE
)) {
530 texImage
->TexFormat
= &_mesa_texformat_ycbcr
;
540 /* Could deal with these packing issues, but currently don't:
542 if (packing
->SkipPixels
||
544 packing
->SwapBytes
||
550 GLint srcRowStride
= _mesa_image_row_stride(packing
, srcWidth
,
554 if ( R200_DEBUG
& DEBUG_TEXTURE
)
555 fprintf(stderr
, "%s: srcRowStride %d/%x\n",
556 __FUNCTION__
, srcRowStride
, srcRowStride
);
558 /* Could check this later in upload, pitch restrictions could be
559 * relaxed, but would need to store the image pitch somewhere,
560 * as packing details might change before image is uploaded:
562 if (!r200IsGartMemory( rmesa
, pixels
, srcHeight
* srcRowStride
) ||
567 /* Have validated that _mesa_transfer_teximage would be a straight
568 * memcpy at this point. NOTE: future calls to TexSubImage will
569 * overwrite the client data. This is explicitly mentioned in the
572 texImage
->Data
= (void *)pixels
;
573 texImage
->IsClientData
= GL_TRUE
;
574 texImage
->RowStride
= srcRowStride
/ texImage
->TexFormat
->TexelBytes
;
581 static void r200TexImage1D( GLcontext
*ctx
, GLenum target
, GLint level
,
582 GLint internalFormat
,
583 GLint width
, GLint border
,
584 GLenum format
, GLenum type
, const GLvoid
*pixels
,
585 const struct gl_pixelstore_attrib
*packing
,
586 struct gl_texture_object
*texObj
,
587 struct gl_texture_image
*texImage
)
589 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
592 driSwapOutTextureObject( t
);
595 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
597 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
602 /* Note, this will call ChooseTextureFormat */
603 _mesa_store_teximage1d(ctx
, target
, level
, internalFormat
,
604 width
, border
, format
, type
, pixels
,
605 &ctx
->Unpack
, texObj
, texImage
);
607 t
->dirty_images
[0] |= (1 << level
);
611 static void r200TexSubImage1D( GLcontext
*ctx
, GLenum target
, GLint level
,
614 GLenum format
, GLenum type
,
615 const GLvoid
*pixels
,
616 const struct gl_pixelstore_attrib
*packing
,
617 struct gl_texture_object
*texObj
,
618 struct gl_texture_image
*texImage
)
620 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
622 assert( t
); /* this _should_ be true */
624 driSwapOutTextureObject( t
);
627 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
629 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
634 _mesa_store_texsubimage1d(ctx
, target
, level
, xoffset
, width
,
635 format
, type
, pixels
, packing
, texObj
,
638 t
->dirty_images
[0] |= (1 << level
);
642 static void r200TexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
643 GLint internalFormat
,
644 GLint width
, GLint height
, GLint border
,
645 GLenum format
, GLenum type
, const GLvoid
*pixels
,
646 const struct gl_pixelstore_attrib
*packing
,
647 struct gl_texture_object
*texObj
,
648 struct gl_texture_image
*texImage
)
650 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
653 /* which cube face or ordinary 2D image */
655 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
656 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
657 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
658 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
659 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
660 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
661 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
669 driSwapOutTextureObject( t
);
672 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
674 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
679 texImage
->IsClientData
= GL_FALSE
;
681 if (r200ValidateClientStorage( ctx
, target
,
684 format
, type
, pixels
,
685 packing
, texObj
, texImage
)) {
686 if (R200_DEBUG
& DEBUG_TEXTURE
)
687 fprintf(stderr
, "%s: Using client storage\n", __FUNCTION__
);
690 if (R200_DEBUG
& DEBUG_TEXTURE
)
691 fprintf(stderr
, "%s: Using normal storage\n", __FUNCTION__
);
693 /* Normal path: copy (to cached memory) and eventually upload
694 * via another copy to GART memory and then a blit... Could
695 * eliminate one copy by going straight to (permanent) GART.
697 * Note, this will call r200ChooseTextureFormat.
699 _mesa_store_teximage2d(ctx
, target
, level
, internalFormat
,
700 width
, height
, border
, format
, type
, pixels
,
701 &ctx
->Unpack
, texObj
, texImage
);
703 t
->dirty_images
[face
] |= (1 << level
);
708 static void r200TexSubImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
709 GLint xoffset
, GLint yoffset
,
710 GLsizei width
, GLsizei height
,
711 GLenum format
, GLenum type
,
712 const GLvoid
*pixels
,
713 const struct gl_pixelstore_attrib
*packing
,
714 struct gl_texture_object
*texObj
,
715 struct gl_texture_image
*texImage
)
717 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
720 /* which cube face or ordinary 2D image */
722 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
723 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
724 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
725 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
726 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
727 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
728 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
735 assert( t
); /* this _should_ be true */
737 driSwapOutTextureObject( t
);
740 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
742 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
747 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
748 height
, format
, type
, pixels
, packing
, texObj
,
751 t
->dirty_images
[face
] |= (1 << level
);
755 static void r200CompressedTexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
756 GLint internalFormat
,
757 GLint width
, GLint height
, GLint border
,
758 GLsizei imageSize
, const GLvoid
*data
,
759 struct gl_texture_object
*texObj
,
760 struct gl_texture_image
*texImage
)
762 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
765 /* which cube face or ordinary 2D image */
767 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
768 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
769 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
770 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
771 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
772 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
773 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
781 driSwapOutTextureObject( t
);
784 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
786 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2D");
791 texImage
->IsClientData
= GL_FALSE
;
792 /* can't call this, different parameters. Would never evaluate to true anyway currently
793 if (r200ValidateClientStorage( ctx, target,
796 format, type, pixels,
797 packing, texObj, texImage)) {
798 if (R200_DEBUG & DEBUG_TEXTURE)
799 fprintf(stderr, "%s: Using client storage\n", __FUNCTION__);
802 if (R200_DEBUG
& DEBUG_TEXTURE
)
803 fprintf(stderr
, "%s: Using normal storage\n", __FUNCTION__
);
805 /* Normal path: copy (to cached memory) and eventually upload
806 * via another copy to GART memory and then a blit... Could
807 * eliminate one copy by going straight to (permanent) GART.
809 * Note, this will call r200ChooseTextureFormat.
811 _mesa_store_compressed_teximage2d(ctx
, target
, level
, internalFormat
, width
,
812 height
, border
, imageSize
, data
, texObj
, texImage
);
814 t
->dirty_images
[face
] |= (1 << level
);
819 static void r200CompressedTexSubImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
820 GLint xoffset
, GLint yoffset
,
821 GLsizei width
, GLsizei height
,
823 GLsizei imageSize
, const GLvoid
*data
,
824 struct gl_texture_object
*texObj
,
825 struct gl_texture_image
*texImage
)
827 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
831 /* which cube face or ordinary 2D image */
833 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
834 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
835 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
836 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
837 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
838 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
839 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
846 assert( t
); /* this _should_ be true */
848 driSwapOutTextureObject( t
);
851 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
853 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexSubImage2D");
858 _mesa_store_compressed_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
859 height
, format
, imageSize
, data
, texObj
, texImage
);
861 t
->dirty_images
[face
] |= (1 << level
);
865 #if ENABLE_HW_3D_TEXTURE
866 static void r200TexImage3D( GLcontext
*ctx
, GLenum target
, GLint level
,
867 GLint internalFormat
,
868 GLint width
, GLint height
, GLint depth
,
870 GLenum format
, GLenum type
, const GLvoid
*pixels
,
871 const struct gl_pixelstore_attrib
*packing
,
872 struct gl_texture_object
*texObj
,
873 struct gl_texture_image
*texImage
)
875 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
878 driSwapOutTextureObject( t
);
881 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
883 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
888 texImage
->IsClientData
= GL_FALSE
;
891 if (r200ValidateClientStorage( ctx
, target
,
894 format
, type
, pixels
,
895 packing
, texObj
, texImage
)) {
896 if (R200_DEBUG
& DEBUG_TEXTURE
)
897 fprintf(stderr
, "%s: Using client storage\n", __FUNCTION__
);
902 if (R200_DEBUG
& DEBUG_TEXTURE
)
903 fprintf(stderr
, "%s: Using normal storage\n", __FUNCTION__
);
905 /* Normal path: copy (to cached memory) and eventually upload
906 * via another copy to GART memory and then a blit... Could
907 * eliminate one copy by going straight to (permanent) GART.
909 * Note, this will call r200ChooseTextureFormat.
911 _mesa_store_teximage3d(ctx
, target
, level
, internalFormat
,
912 width
, height
, depth
, border
,
913 format
, type
, pixels
,
914 &ctx
->Unpack
, texObj
, texImage
);
916 t
->dirty_images
[0] |= (1 << level
);
922 #if ENABLE_HW_3D_TEXTURE
924 r200TexSubImage3D( GLcontext
*ctx
, GLenum target
, GLint level
,
925 GLint xoffset
, GLint yoffset
, GLint zoffset
,
926 GLsizei width
, GLsizei height
, GLsizei depth
,
927 GLenum format
, GLenum type
,
928 const GLvoid
*pixels
,
929 const struct gl_pixelstore_attrib
*packing
,
930 struct gl_texture_object
*texObj
,
931 struct gl_texture_image
*texImage
)
933 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
935 /* fprintf(stderr, "%s\n", __FUNCTION__); */
937 assert( t
); /* this _should_ be true */
939 driSwapOutTextureObject( t
);
942 t
= (driTextureObject
*) r200AllocTexObj( texObj
);
944 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage3D");
947 texObj
->DriverData
= t
;
950 _mesa_store_texsubimage3d(ctx
, target
, level
, xoffset
, yoffset
, zoffset
,
951 width
, height
, depth
,
952 format
, type
, pixels
, packing
, texObj
, texImage
);
954 t
->dirty_images
[0] |= (1 << level
);
960 static void r200TexEnv( GLcontext
*ctx
, GLenum target
,
961 GLenum pname
, const GLfloat
*param
)
963 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
964 GLuint unit
= ctx
->Texture
.CurrentUnit
;
965 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
967 if ( R200_DEBUG
& DEBUG_STATE
) {
968 fprintf( stderr
, "%s( %s )\n",
969 __FUNCTION__
, _mesa_lookup_enum_by_nr( pname
) );
972 /* This is incorrect: Need to maintain this data for each of
973 * GL_TEXTURE_{123}D, GL_TEXTURE_RECTANGLE_NV, etc, and switch
974 * between them according to _ReallyEnabled.
977 case GL_TEXTURE_ENV_COLOR
: {
980 UNCLAMPED_FLOAT_TO_RGBA_CHAN( c
, texUnit
->EnvColor
);
981 envColor
= r200PackColor( 4, c
[0], c
[1], c
[2], c
[3] );
982 if ( rmesa
->hw
.tf
.cmd
[TF_TFACTOR_0
+ unit
] != envColor
) {
983 R200_STATECHANGE( rmesa
, tf
);
984 rmesa
->hw
.tf
.cmd
[TF_TFACTOR_0
+ unit
] = envColor
;
989 case GL_TEXTURE_LOD_BIAS_EXT
: {
992 const int fixed_one
= 0x8000000;
994 /* The R200's LOD bias is a signed 2's complement value with a
995 * range of -16.0 <= bias < 16.0.
997 * NOTE: Add a small bias to the bias for conform mipsel.c test.
1000 min
= driQueryOptionb (&rmesa
->optionCache
, "no_neg_lod_bias") ?
1002 bias
= CLAMP( bias
, min
, 16.0 );
1003 b
= (int)(bias
* fixed_one
) & R200_LOD_BIAS_MASK
;
1005 if ( (rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT_X
] & R200_LOD_BIAS_MASK
) != b
) {
1006 R200_STATECHANGE( rmesa
, tex
[unit
] );
1007 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT_X
] &= ~R200_LOD_BIAS_MASK
;
1008 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT_X
] |= b
;
1012 case GL_COORD_REPLACE_ARB
:
1013 if (ctx
->Point
.PointSprite
) {
1014 R200_STATECHANGE( rmesa
, spr
);
1015 if ((GLenum
)param
[0]) {
1016 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |= R200_PS_GEN_TEX_0
<< unit
;
1018 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] &= ~(R200_PS_GEN_TEX_0
<< unit
);
1029 * Changes variables and flags for a state update, which will happen at the
1030 * next UpdateTextureState
1033 static void r200TexParameter( GLcontext
*ctx
, GLenum target
,
1034 struct gl_texture_object
*texObj
,
1035 GLenum pname
, const GLfloat
*params
)
1037 r200TexObjPtr t
= (r200TexObjPtr
) texObj
->DriverData
;
1039 if ( R200_DEBUG
& (DEBUG_STATE
|DEBUG_TEXTURE
) ) {
1040 fprintf( stderr
, "%s( %s )\n", __FUNCTION__
,
1041 _mesa_lookup_enum_by_nr( pname
) );
1045 case GL_TEXTURE_MIN_FILTER
:
1046 case GL_TEXTURE_MAG_FILTER
:
1047 case GL_TEXTURE_MAX_ANISOTROPY_EXT
:
1048 r200SetTexMaxAnisotropy( t
, texObj
->MaxAnisotropy
);
1049 r200SetTexFilter( t
, texObj
->MinFilter
, texObj
->MagFilter
);
1052 case GL_TEXTURE_WRAP_S
:
1053 case GL_TEXTURE_WRAP_T
:
1054 case GL_TEXTURE_WRAP_R
:
1055 r200SetTexWrap( t
, texObj
->WrapS
, texObj
->WrapT
, texObj
->WrapR
);
1058 case GL_TEXTURE_BORDER_COLOR
:
1059 r200SetTexBorderColor( t
, texObj
->_BorderChan
);
1062 case GL_TEXTURE_BASE_LEVEL
:
1063 case GL_TEXTURE_MAX_LEVEL
:
1064 case GL_TEXTURE_MIN_LOD
:
1065 case GL_TEXTURE_MAX_LOD
:
1066 /* This isn't the most efficient solution but there doesn't appear to
1067 * be a nice alternative. Since there's no LOD clamping,
1068 * we just have to rely on loading the right subset of mipmap levels
1069 * to simulate a clamped LOD.
1071 driSwapOutTextureObject( (driTextureObject
*) t
);
1078 /* Mark this texobj as dirty (one bit per tex unit)
1080 t
->dirty_state
= TEX_ALL
;
1085 static void r200BindTexture( GLcontext
*ctx
, GLenum target
,
1086 struct gl_texture_object
*texObj
)
1088 if ( R200_DEBUG
& (DEBUG_STATE
|DEBUG_TEXTURE
) ) {
1089 fprintf( stderr
, "%s( %p ) unit=%d\n", __FUNCTION__
, (void *)texObj
,
1090 ctx
->Texture
.CurrentUnit
);
1093 if ( (target
== GL_TEXTURE_1D
)
1094 || (target
== GL_TEXTURE_2D
)
1095 #if ENABLE_HW_3D_TEXTURE
1096 || (target
== GL_TEXTURE_3D
)
1098 || (target
== GL_TEXTURE_CUBE_MAP
)
1099 || (target
== GL_TEXTURE_RECTANGLE_NV
) ) {
1100 assert( texObj
->DriverData
!= NULL
);
1105 static void r200DeleteTexture( GLcontext
*ctx
,
1106 struct gl_texture_object
*texObj
)
1108 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1109 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
1111 if ( R200_DEBUG
& (DEBUG_STATE
|DEBUG_TEXTURE
) ) {
1112 fprintf( stderr
, "%s( %p (target = %s) )\n", __FUNCTION__
, (void *)texObj
,
1113 _mesa_lookup_enum_by_nr( texObj
->Target
) );
1118 R200_FIREVERTICES( rmesa
);
1121 driDestroyTextureObject( t
);
1123 /* Free mipmap images and the texture object itself */
1124 _mesa_delete_texture_object(ctx
, texObj
);
1128 * - Same GEN_MODE for all active bits
1129 * - Same EyePlane/ObjPlane for all active bits when using Eye/Obj
1130 * - STRQ presumably all supported (matrix means incoming R values
1131 * can end up in STQ, this has implications for vertex support,
1132 * presumably ok if maos is used, though?)
1134 * Basically impossible to do this on the fly - just collect some
1135 * basic info & do the checks from ValidateState().
1137 static void r200TexGen( GLcontext
*ctx
,
1140 const GLfloat
*params
)
1142 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1143 GLuint unit
= ctx
->Texture
.CurrentUnit
;
1144 rmesa
->recheck_texgen
[unit
] = GL_TRUE
;
1149 * Allocate a new texture object.
1150 * Called via ctx->Driver.NewTextureObject.
1151 * Note: this function will be called during context creation to
1152 * allocate the default texture objects.
1153 * Note: we could use containment here to 'derive' the driver-specific
1154 * texture object from the core mesa gl_texture_object. Not done at this time.
1155 * Fixup MaxAnisotropy according to user preference.
1157 static struct gl_texture_object
*
1158 r200NewTextureObject( GLcontext
*ctx
, GLuint name
, GLenum target
)
1160 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1161 struct gl_texture_object
*obj
;
1162 obj
= _mesa_new_texture_object(ctx
, name
, target
);
1165 obj
->MaxAnisotropy
= rmesa
->initialMaxAnisotropy
;
1166 r200AllocTexObj( obj
);
1171 void r200InitTextureFuncs( struct dd_function_table
*functions
)
1173 /* Note: we only plug in the functions we implement in the driver
1174 * since _mesa_init_driver_functions() was already called.
1176 functions
->ChooseTextureFormat
= r200ChooseTextureFormat
;
1177 functions
->TexImage1D
= r200TexImage1D
;
1178 functions
->TexImage2D
= r200TexImage2D
;
1179 #if ENABLE_HW_3D_TEXTURE
1180 functions
->TexImage3D
= r200TexImage3D
;
1182 functions
->TexImage3D
= _mesa_store_teximage3d
;
1184 functions
->TexSubImage1D
= r200TexSubImage1D
;
1185 functions
->TexSubImage2D
= r200TexSubImage2D
;
1186 #if ENABLE_HW_3D_TEXTURE
1187 functions
->TexSubImage3D
= r200TexSubImage3D
;
1189 functions
->TexSubImage3D
= _mesa_store_texsubimage3d
;
1191 functions
->NewTextureObject
= r200NewTextureObject
;
1192 functions
->BindTexture
= r200BindTexture
;
1193 functions
->DeleteTexture
= r200DeleteTexture
;
1194 functions
->IsTextureResident
= driIsTextureResident
;
1196 functions
->TexEnv
= r200TexEnv
;
1197 functions
->TexParameter
= r200TexParameter
;
1198 functions
->TexGen
= r200TexGen
;
1200 functions
->CompressedTexImage2D
= r200CompressedTexImage2D
;
1201 functions
->CompressedTexSubImage2D
= r200CompressedTexSubImage2D
;
1203 driInitTextureFormats();
1206 /* moved or obsolete code */
1207 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1208 driInitTextureObjects( ctx
, & rmesa
->swapped
,
1209 DRI_TEXMGR_DO_TEXTURE_1D
1210 | DRI_TEXMGR_DO_TEXTURE_2D
);
1212 /* Hack: r200NewTextureObject is not yet installed when the
1213 * default textures are created. Therefore set MaxAnisotropy of the
1214 * default 2D texture now. */
1215 ctx
->Shared
->Default2D
->MaxAnisotropy
= driQueryOptionf (&rmesa
->optionCache
,
1216 "def_max_anisotropy");