1 /* $XFree86: xc/lib/GL/mesa/src/drv/r300/r300_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 "r300_context.h"
49 #include "r300_state.h"
50 #include "r300_ioctl.h"
51 //#include "r300_swtcl.h"
57 * Set the texture wrap modes.
59 * \param t Texture object whose wrap modes are to be set
60 * \param swrap Wrap mode for the \a s texture coordinate
61 * \param twrap Wrap mode for the \a t texture coordinate
64 static void r300SetTexWrap(r300TexObjPtr t
, GLenum swrap
, GLenum twrap
,
67 unsigned long hw_swrap
=0, hw_twrap
=0, hw_qwrap
=0;
70 ~(R300_TX_WRAP_S_MASK
| R300_TX_WRAP_T_MASK
| R300_TX_WRAP_Q_MASK
);
74 hw_swrap
|= R300_TX_REPEAT
;
77 hw_swrap
|= R300_TX_CLAMP
;
79 case GL_CLAMP_TO_EDGE
:
80 hw_swrap
|= R300_TX_CLAMP_TO_EDGE
;
82 case GL_CLAMP_TO_BORDER
:
83 hw_swrap
|= R300_TX_CLAMP_TO_BORDER
;
85 case GL_MIRRORED_REPEAT
:
86 hw_swrap
|= R300_TX_REPEAT
| R300_TX_MIRRORED
;
88 case GL_MIRROR_CLAMP_EXT
:
89 hw_swrap
|= R300_TX_CLAMP
| R300_TX_MIRRORED
;
91 case GL_MIRROR_CLAMP_TO_EDGE_EXT
:
92 hw_swrap
|= R300_TX_CLAMP_TO_EDGE
| R300_TX_MIRRORED
;
94 case GL_MIRROR_CLAMP_TO_BORDER_EXT
:
95 hw_swrap
|= R300_TX_CLAMP_TO_BORDER
| R300_TX_MIRRORED
;
98 _mesa_problem(NULL
, "bad S wrap mode in %s", __FUNCTION__
);
103 hw_twrap
|= R300_TX_REPEAT
;
106 hw_twrap
|= R300_TX_CLAMP
;
108 case GL_CLAMP_TO_EDGE
:
109 hw_twrap
|= R300_TX_CLAMP_TO_EDGE
;
111 case GL_CLAMP_TO_BORDER
:
112 hw_twrap
|= R300_TX_CLAMP_TO_BORDER
;
114 case GL_MIRRORED_REPEAT
:
115 hw_twrap
|= R300_TX_REPEAT
| R300_TX_MIRRORED
;
117 case GL_MIRROR_CLAMP_EXT
:
118 hw_twrap
|= R300_TX_CLAMP
| R300_TX_MIRRORED
;
120 case GL_MIRROR_CLAMP_TO_EDGE_EXT
:
121 hw_twrap
|= R300_TX_CLAMP_TO_EDGE
| R300_TX_MIRRORED
;
123 case GL_MIRROR_CLAMP_TO_BORDER_EXT
:
124 hw_twrap
|= R300_TX_CLAMP_TO_BORDER
| R300_TX_MIRRORED
;
127 _mesa_problem(NULL
, "bad T wrap mode in %s", __FUNCTION__
);
132 hw_qwrap
|= R300_TX_REPEAT
;
135 hw_qwrap
|= R300_TX_CLAMP
;
137 case GL_CLAMP_TO_EDGE
:
138 hw_qwrap
|= R300_TX_CLAMP_TO_EDGE
;
140 case GL_CLAMP_TO_BORDER
:
141 hw_qwrap
|= R300_TX_CLAMP_TO_BORDER
;
143 case GL_MIRRORED_REPEAT
:
144 hw_qwrap
|= R300_TX_REPEAT
| R300_TX_MIRRORED
;
146 case GL_MIRROR_CLAMP_EXT
:
147 hw_qwrap
|= R300_TX_CLAMP
| R300_TX_MIRRORED
;
149 case GL_MIRROR_CLAMP_TO_EDGE_EXT
:
150 hw_qwrap
|= R300_TX_CLAMP_TO_EDGE
| R300_TX_MIRRORED
;
152 case GL_MIRROR_CLAMP_TO_BORDER_EXT
:
153 hw_qwrap
|= R300_TX_CLAMP_TO_BORDER
| R300_TX_MIRRORED
;
156 _mesa_problem(NULL
, "bad R wrap mode in %s", __FUNCTION__
);
159 t
->filter
|= hw_swrap
<< R300_TX_WRAP_S_SHIFT
;
160 t
->filter
|= hw_twrap
<< R300_TX_WRAP_T_SHIFT
;
161 t
->filter
|= hw_qwrap
<< R300_TX_WRAP_Q_SHIFT
;
164 t
->format_x
&= ~R200_CLAMP_Q_MASK
;
165 t
->border_fallback
= (is_clamp
&& is_clamp_to_border
);
169 static void r300SetTexMaxAnisotropy(r300TexObjPtr t
, GLfloat max
)
172 t
->filter
&= ~R300_TX_MAX_ANISO_MASK
;
175 t
->filter
|= R300_TX_MAX_ANISO_1_TO_1
;
176 } else if (max
<= 2.0) {
177 t
->filter
|= R300_TX_MAX_ANISO_2_TO_1
;
178 } else if (max
<= 4.0) {
179 t
->filter
|= R300_TX_MAX_ANISO_4_TO_1
;
180 } else if (max
<= 8.0) {
181 t
->filter
|= R300_TX_MAX_ANISO_8_TO_1
;
183 t
->filter
|= R300_TX_MAX_ANISO_16_TO_1
;
188 * Set the texture magnification and minification modes.
190 * \param t Texture whose filter modes are to be set
191 * \param minf Texture minification mode
192 * \param magf Texture magnification mode
195 static void r300SetTexFilter(r300TexObjPtr t
, GLenum minf
, GLenum magf
)
197 GLuint anisotropy
= (t
->filter
& R300_TX_MAX_ANISO_MASK
);
199 t
->filter
&= ~(R300_TX_MIN_FILTER_MASK
| R300_TX_MAG_FILTER_MASK
);
201 //t->format_x &= ~R200_VOLUME_FILTER_MASK;
204 if (anisotropy
== R300_TX_MAX_ANISO_1_TO_1
) {
207 t
->filter
|= R300_TX_MIN_FILTER_NEAREST
;
210 t
->filter
|= R300_TX_MIN_FILTER_LINEAR
;
212 case GL_NEAREST_MIPMAP_NEAREST
:
213 t
->filter
|= R300_TX_MIN_FILTER_NEAREST_MIP_NEAREST
;
215 case GL_NEAREST_MIPMAP_LINEAR
:
216 t
->filter
|= R300_TX_MIN_FILTER_NEAREST_MIP_LINEAR
;
218 case GL_LINEAR_MIPMAP_NEAREST
:
219 t
->filter
|= R300_TX_MIN_FILTER_LINEAR_MIP_NEAREST
;
221 case GL_LINEAR_MIPMAP_LINEAR
:
222 t
->filter
|= R300_TX_MIN_FILTER_LINEAR_MIP_LINEAR
;
228 t
->filter
|= R300_TX_MIN_FILTER_ANISO_NEAREST
;
231 t
->filter
|= R300_TX_MIN_FILTER_ANISO_LINEAR
;
233 case GL_NEAREST_MIPMAP_NEAREST
:
234 case GL_LINEAR_MIPMAP_NEAREST
:
236 R300_TX_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST
;
238 case GL_NEAREST_MIPMAP_LINEAR
:
239 case GL_LINEAR_MIPMAP_LINEAR
:
241 R300_TX_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR
;
246 /* Note we don't have 3D mipmaps so only use the mag filter setting
247 * to set the 3D texture filter mode.
251 t
->filter
|= R300_TX_MAG_FILTER_NEAREST
;
252 /*t->format_x |= R200_VOLUME_FILTER_NEAREST;*/
255 t
->filter
|= R300_TX_MAG_FILTER_LINEAR
;
256 /*t->format_x |= R200_VOLUME_FILTER_LINEAR;*/
261 static void r300SetTexBorderColor(r300TexObjPtr t
, GLubyte c
[4])
263 t
->pp_border_color
= r300PackColor(4, c
[0], c
[1], c
[2], c
[3]);
267 * Allocate space for and load the mesa images into the texture memory block.
268 * This will happen before drawing with a new texture, or drawing with a
269 * texture after it was swapped out or teximaged again.
272 static r300TexObjPtr
r300AllocTexObj(struct gl_texture_object
*texObj
)
276 t
= CALLOC_STRUCT(r300_tex_obj
);
277 texObj
->DriverData
= t
;
279 if (RADEON_DEBUG
& DEBUG_TEXTURE
) {
280 fprintf(stderr
, "%s( %p, %p )\n", __FUNCTION__
,
281 (void *)texObj
, (void *)t
);
284 /* Initialize non-image-dependent parts of the state:
286 t
->base
.tObj
= texObj
;
287 t
->border_fallback
= GL_FALSE
;
289 make_empty_list(&t
->base
);
291 r300SetTexWrap(t
, texObj
->WrapS
, texObj
->WrapT
, texObj
->WrapR
);
292 r300SetTexMaxAnisotropy(t
, texObj
->MaxAnisotropy
);
293 r300SetTexFilter(t
, texObj
->MinFilter
, texObj
->MagFilter
);
294 r300SetTexBorderColor(t
, texObj
->_BorderChan
);
300 static const struct gl_texture_format
*r300ChooseTextureFormat(GLcontext
* ctx
,
306 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
307 const GLboolean do32bpt
=
308 (rmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_32
);
309 const GLboolean force16bpt
=
310 (rmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_FORCE_16
);
314 fprintf(stderr
, "InternalFormat=%s(%d) type=%s format=%s\n",
315 _mesa_lookup_enum_by_nr(internalFormat
), internalFormat
,
316 _mesa_lookup_enum_by_nr(type
),
317 _mesa_lookup_enum_by_nr(format
));
318 fprintf(stderr
, "do32bpt=%d force16bpt=%d\n",
319 do32bpt
, force16bpt
);
322 switch (internalFormat
) {
325 case GL_COMPRESSED_RGBA
:
327 case GL_UNSIGNED_INT_10_10_10_2
:
328 case GL_UNSIGNED_INT_2_10_10_10_REV
:
329 return do32bpt
? _dri_texformat_argb8888
:
330 _dri_texformat_argb1555
;
331 case GL_UNSIGNED_SHORT_4_4_4_4
:
332 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
333 return _dri_texformat_argb4444
;
334 case GL_UNSIGNED_SHORT_5_5_5_1
:
335 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
336 return _dri_texformat_argb1555
;
338 return do32bpt
? _dri_texformat_rgba8888
:
339 _dri_texformat_argb4444
;
344 case GL_COMPRESSED_RGB
:
346 case GL_UNSIGNED_SHORT_4_4_4_4
:
347 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
348 return _dri_texformat_argb4444
;
349 case GL_UNSIGNED_SHORT_5_5_5_1
:
350 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
351 return _dri_texformat_argb1555
;
352 case GL_UNSIGNED_SHORT_5_6_5
:
353 case GL_UNSIGNED_SHORT_5_6_5_REV
:
354 return _dri_texformat_rgb565
;
356 return do32bpt
? _dri_texformat_rgba8888
:
357 _dri_texformat_rgb565
;
365 _dri_texformat_rgba8888
: _dri_texformat_argb4444
;
369 return _dri_texformat_argb4444
;
372 return _dri_texformat_argb1555
;
378 return !force16bpt
? _dri_texformat_rgba8888
:
379 _dri_texformat_rgb565
;
384 return _dri_texformat_rgb565
;
391 case GL_COMPRESSED_ALPHA
:
392 return _dri_texformat_a8
;
400 case GL_COMPRESSED_LUMINANCE
:
401 return _dri_texformat_l8
;
404 case GL_LUMINANCE_ALPHA
:
405 case GL_LUMINANCE4_ALPHA4
:
406 case GL_LUMINANCE6_ALPHA2
:
407 case GL_LUMINANCE8_ALPHA8
:
408 case GL_LUMINANCE12_ALPHA4
:
409 case GL_LUMINANCE12_ALPHA12
:
410 case GL_LUMINANCE16_ALPHA16
:
411 case GL_COMPRESSED_LUMINANCE_ALPHA
:
412 return _dri_texformat_al88
;
419 case GL_COMPRESSED_INTENSITY
:
420 return _dri_texformat_i8
;
423 if (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
424 type
== GL_UNSIGNED_BYTE
)
425 return &_mesa_texformat_ycbcr
;
427 return &_mesa_texformat_ycbcr_rev
;
431 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
432 return &_mesa_texformat_rgb_dxt1
;
434 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
435 return &_mesa_texformat_rgba_dxt1
;
439 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
440 return &_mesa_texformat_rgba_dxt3
;
442 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
443 return &_mesa_texformat_rgba_dxt5
;
447 "unexpected internalFormat 0x%x in r300ChooseTextureFormat",
448 (int)internalFormat
);
452 return NULL
; /* never get here */
456 r300ValidateClientStorage(GLcontext
* ctx
, GLenum target
,
457 GLint internalFormat
,
458 GLint srcWidth
, GLint srcHeight
,
459 GLenum format
, GLenum type
, const void *pixels
,
460 const struct gl_pixelstore_attrib
*packing
,
461 struct gl_texture_object
*texObj
,
462 struct gl_texture_image
*texImage
)
464 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
467 fprintf(stderr
, "intformat %s format %s type %s\n",
468 _mesa_lookup_enum_by_nr(internalFormat
),
469 _mesa_lookup_enum_by_nr(format
),
470 _mesa_lookup_enum_by_nr(type
));
472 if (!ctx
->Unpack
.ClientStorage
)
475 if (ctx
->_ImageTransferState
||
476 texImage
->IsCompressed
|| texObj
->GenerateMipmap
)
479 /* This list is incomplete, may be different on ppc???
481 switch (internalFormat
) {
483 if (format
== GL_BGRA
&& type
== GL_UNSIGNED_INT_8_8_8_8_REV
) {
484 texImage
->TexFormat
= _dri_texformat_argb8888
;
490 if (format
== GL_RGB
&& type
== GL_UNSIGNED_SHORT_5_6_5
) {
491 texImage
->TexFormat
= _dri_texformat_rgb565
;
497 if (format
== GL_YCBCR_MESA
&&
498 type
== GL_UNSIGNED_SHORT_8_8_REV_APPLE
) {
499 texImage
->TexFormat
= &_mesa_texformat_ycbcr_rev
;
500 } else if (format
== GL_YCBCR_MESA
&&
501 (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
502 type
== GL_UNSIGNED_BYTE
)) {
503 texImage
->TexFormat
= &_mesa_texformat_ycbcr
;
512 /* Could deal with these packing issues, but currently don't:
514 if (packing
->SkipPixels
||
515 packing
->SkipRows
|| packing
->SwapBytes
|| packing
->LsbFirst
) {
520 GLint srcRowStride
= _mesa_image_row_stride(packing
, srcWidth
,
524 fprintf(stderr
, "%s: srcRowStride %d/%x\n",
525 __FUNCTION__
, srcRowStride
, srcRowStride
);
527 /* Could check this later in upload, pitch restrictions could be
528 * relaxed, but would need to store the image pitch somewhere,
529 * as packing details might change before image is uploaded:
531 if (!r300IsGartMemory(rmesa
, pixels
, srcHeight
* srcRowStride
)
532 || (srcRowStride
& 63))
535 /* Have validated that _mesa_transfer_teximage would be a straight
536 * memcpy at this point. NOTE: future calls to TexSubImage will
537 * overwrite the client data. This is explicitly mentioned in the
540 texImage
->Data
= (void *)pixels
;
541 texImage
->IsClientData
= GL_TRUE
;
542 texImage
->RowStride
=
543 srcRowStride
/ texImage
->TexFormat
->TexelBytes
;
549 static void r300TexImage1D(GLcontext
* ctx
, GLenum target
, GLint level
,
550 GLint internalFormat
,
551 GLint width
, GLint border
,
552 GLenum format
, GLenum type
, const GLvoid
* pixels
,
553 const struct gl_pixelstore_attrib
*packing
,
554 struct gl_texture_object
*texObj
,
555 struct gl_texture_image
*texImage
)
557 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
560 driSwapOutTextureObject(t
);
562 t
= (driTextureObject
*) r300AllocTexObj(texObj
);
564 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
569 /* Note, this will call ChooseTextureFormat */
570 _mesa_store_teximage1d(ctx
, target
, level
, internalFormat
,
571 width
, border
, format
, type
, pixels
,
572 &ctx
->Unpack
, texObj
, texImage
);
574 t
->dirty_images
[0] |= (1 << level
);
577 static void r300TexSubImage1D(GLcontext
* ctx
, GLenum target
, GLint level
,
580 GLenum format
, GLenum type
,
581 const GLvoid
* pixels
,
582 const struct gl_pixelstore_attrib
*packing
,
583 struct gl_texture_object
*texObj
,
584 struct gl_texture_image
*texImage
)
586 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
588 assert(t
); /* this _should_ be true */
590 driSwapOutTextureObject(t
);
592 t
= (driTextureObject
*) r300AllocTexObj(texObj
);
594 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
599 _mesa_store_texsubimage1d(ctx
, target
, level
, xoffset
, width
,
600 format
, type
, pixels
, packing
, texObj
,
603 t
->dirty_images
[0] |= (1 << level
);
606 static void r300TexImage2D(GLcontext
* ctx
, GLenum target
, GLint level
,
607 GLint internalFormat
,
608 GLint width
, GLint height
, GLint border
,
609 GLenum format
, GLenum type
, const GLvoid
* pixels
,
610 const struct gl_pixelstore_attrib
*packing
,
611 struct gl_texture_object
*texObj
,
612 struct gl_texture_image
*texImage
)
614 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
617 /* which cube face or ordinary 2D image */
619 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
620 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
621 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
622 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
623 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
624 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
626 (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
634 driSwapOutTextureObject(t
);
636 t
= (driTextureObject
*) r300AllocTexObj(texObj
);
638 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
643 texImage
->IsClientData
= GL_FALSE
;
645 if (r300ValidateClientStorage(ctx
, target
,
648 format
, type
, pixels
,
649 packing
, texObj
, texImage
)) {
650 if (RADEON_DEBUG
& DEBUG_TEXTURE
)
651 fprintf(stderr
, "%s: Using client storage\n",
654 if (RADEON_DEBUG
& DEBUG_TEXTURE
)
655 fprintf(stderr
, "%s: Using normal storage\n",
658 /* Normal path: copy (to cached memory) and eventually upload
659 * via another copy to GART memory and then a blit... Could
660 * eliminate one copy by going straight to (permanent) GART.
662 * Note, this will call r300ChooseTextureFormat.
664 _mesa_store_teximage2d(ctx
, target
, level
, internalFormat
,
665 width
, height
, border
, format
, type
,
666 pixels
, &ctx
->Unpack
, texObj
, texImage
);
668 t
->dirty_images
[face
] |= (1 << level
);
672 static void r300TexSubImage2D(GLcontext
* ctx
, GLenum target
, GLint level
,
673 GLint xoffset
, GLint yoffset
,
674 GLsizei width
, GLsizei height
,
675 GLenum format
, GLenum type
,
676 const GLvoid
* pixels
,
677 const struct gl_pixelstore_attrib
*packing
,
678 struct gl_texture_object
*texObj
,
679 struct gl_texture_image
*texImage
)
681 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
684 /* which cube face or ordinary 2D image */
686 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
687 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
688 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
689 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
690 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
691 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
693 (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
700 assert(t
); /* this _should_ be true */
702 driSwapOutTextureObject(t
);
704 t
= (driTextureObject
*) r300AllocTexObj(texObj
);
706 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
711 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
712 height
, format
, type
, pixels
, packing
, texObj
,
715 t
->dirty_images
[face
] |= (1 << level
);
718 static void r300CompressedTexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
719 GLint internalFormat
,
720 GLint width
, GLint height
, GLint border
,
721 GLsizei imageSize
, const GLvoid
*data
,
722 struct gl_texture_object
*texObj
,
723 struct gl_texture_image
*texImage
)
725 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
728 /* which cube face or ordinary 2D image */
730 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
731 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
732 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
733 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
734 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
735 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
736 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
744 driSwapOutTextureObject( t
);
747 t
= (driTextureObject
*) r300AllocTexObj( texObj
);
749 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2D");
754 texImage
->IsClientData
= GL_FALSE
;
755 /* can't call this, different parameters. Would never evaluate to true anyway currently
756 if (r300ValidateClientStorage( ctx, target,
759 format, type, pixels,
760 packing, texObj, texImage)) {
761 if (RADEON_DEBUG & DEBUG_TEXTURE)
762 fprintf(stderr, "%s: Using client storage\n", __FUNCTION__);
765 if (RADEON_DEBUG
& DEBUG_TEXTURE
)
766 fprintf(stderr
, "%s: Using normal storage\n", __FUNCTION__
);
768 /* Normal path: copy (to cached memory) and eventually upload
769 * via another copy to GART memory and then a blit... Could
770 * eliminate one copy by going straight to (permanent) GART.
772 * Note, this will call r300ChooseTextureFormat.
774 _mesa_store_compressed_teximage2d(ctx
, target
, level
, internalFormat
, width
,
775 height
, border
, imageSize
, data
, texObj
, texImage
);
777 t
->dirty_images
[face
] |= (1 << level
);
782 static void r300CompressedTexSubImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
783 GLint xoffset
, GLint yoffset
,
784 GLsizei width
, GLsizei height
,
786 GLsizei imageSize
, const GLvoid
*data
,
787 struct gl_texture_object
*texObj
,
788 struct gl_texture_image
*texImage
)
790 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
794 /* which cube face or ordinary 2D image */
796 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
797 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
798 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
799 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
800 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
801 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
802 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
809 assert( t
); /* this _should_ be true */
811 driSwapOutTextureObject( t
);
814 t
= (driTextureObject
*) r300AllocTexObj( texObj
);
816 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexSubImage3D");
821 _mesa_store_compressed_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
822 height
, format
, imageSize
, data
, texObj
, texImage
);
824 t
->dirty_images
[face
] |= (1 << level
);
827 #if ENABLE_HW_3D_TEXTURE
828 static void r300TexImage3D(GLcontext
* ctx
, GLenum target
, GLint level
,
829 GLint internalFormat
,
830 GLint width
, GLint height
, GLint depth
,
832 GLenum format
, GLenum type
, const GLvoid
* pixels
,
833 const struct gl_pixelstore_attrib
*packing
,
834 struct gl_texture_object
*texObj
,
835 struct gl_texture_image
*texImage
)
837 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
840 driSwapOutTextureObject(t
);
842 t
= (driTextureObject
*) r300AllocTexObj(texObj
);
844 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
849 texImage
->IsClientData
= GL_FALSE
;
852 if (r300ValidateClientStorage(ctx
, target
,
855 format
, type
, pixels
,
856 packing
, texObj
, texImage
)) {
857 if (RADEON_DEBUG
& DEBUG_TEXTURE
)
858 fprintf(stderr
, "%s: Using client storage\n",
863 if (RADEON_DEBUG
& DEBUG_TEXTURE
)
864 fprintf(stderr
, "%s: Using normal storage\n",
867 /* Normal path: copy (to cached memory) and eventually upload
868 * via another copy to GART memory and then a blit... Could
869 * eliminate one copy by going straight to (permanent) GART.
871 * Note, this will call r300ChooseTextureFormat.
873 _mesa_store_teximage3d(ctx
, target
, level
, internalFormat
,
874 width
, height
, depth
, border
,
875 format
, type
, pixels
,
876 &ctx
->Unpack
, texObj
, texImage
);
878 t
->dirty_images
[0] |= (1 << level
);
883 #if ENABLE_HW_3D_TEXTURE
885 r300TexSubImage3D(GLcontext
* ctx
, GLenum target
, GLint level
,
886 GLint xoffset
, GLint yoffset
, GLint zoffset
,
887 GLsizei width
, GLsizei height
, GLsizei depth
,
888 GLenum format
, GLenum type
,
889 const GLvoid
* pixels
,
890 const struct gl_pixelstore_attrib
*packing
,
891 struct gl_texture_object
*texObj
,
892 struct gl_texture_image
*texImage
)
894 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
896 /* fprintf(stderr, "%s\n", __FUNCTION__); */
898 assert(t
); /* this _should_ be true */
900 driSwapOutTextureObject(t
);
902 t
= (driTextureObject
*) r300AllocTexObj(texObj
);
904 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage3D");
907 texObj
->DriverData
= t
;
910 _mesa_store_texsubimage3d(ctx
, target
, level
, xoffset
, yoffset
, zoffset
,
911 width
, height
, depth
,
912 format
, type
, pixels
, packing
, texObj
,
915 t
->dirty_images
[0] |= (1 << level
);
919 static void r300TexEnv(GLcontext
* ctx
, GLenum target
,
920 GLenum pname
, const GLfloat
* param
)
922 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
923 GLuint unit
= ctx
->Texture
.CurrentUnit
;
925 if (RADEON_DEBUG
& DEBUG_STATE
) {
926 fprintf(stderr
, "%s( %s )\n",
927 __FUNCTION__
, _mesa_lookup_enum_by_nr(pname
));
930 /* This is incorrect: Need to maintain this data for each of
931 * GL_TEXTURE_{123}D, GL_TEXTURE_RECTANGLE_NV, etc, and switch
932 * between them according to _ReallyEnabled.
935 case GL_TEXTURE_ENV_COLOR
:{
936 WARN_ONCE("I am broken - Fixme !\n");
940 UNCLAMPED_FLOAT_TO_RGBA_CHAN(c, texUnit->EnvColor);
941 envColor = radeonPackColor(4, c[0], c[1], c[2], c[3]);
942 if (rmesa->hw.tf.cmd[TF_TFACTOR_0 + unit] != envColor) {
943 R200_STATECHANGE(rmesa, tf);
944 rmesa->hw.tf.cmd[TF_TFACTOR_0 + unit] =
950 case GL_TEXTURE_LOD_BIAS_EXT
:{
954 /* The R300's LOD bias is a signed 2's complement value with a
955 * range of -16.0 <= bias < 16.0.
957 * NOTE: Add a small bias to the bias for conform mipsel.c test.
961 driQueryOptionb(&rmesa
->radeon
.optionCache
,
962 "no_neg_lod_bias") ? 0.0 : -16.0;
963 bias
= CLAMP(bias
, min
, 16.0);
965 /* 0.0 - 16.0 == 0x0 - 0x1000 */
966 /* 0.0 - -16.0 == 0x1001 - 0x1fff */
967 b
= 0x1000 / 16.0 * bias
;
968 b
&= R300_LOD_BIAS_MASK
;
970 if(b
!= (rmesa
->hw
.tex
.unknown1
.cmd
[R300_TEX_VALUE_0
+unit
] & R300_LOD_BIAS_MASK
)){
971 R300_STATECHANGE(rmesa
, tex
.unknown1
);
972 rmesa
->hw
.tex
.unknown1
.cmd
[R300_TEX_VALUE_0
+unit
] &= ~R300_LOD_BIAS_MASK
;
973 rmesa
->hw
.tex
.unknown1
.cmd
[R300_TEX_VALUE_0
+unit
] |= b
;
984 * Changes variables and flags for a state update, which will happen at the
985 * next UpdateTextureState
988 static void r300TexParameter(GLcontext
* ctx
, GLenum target
,
989 struct gl_texture_object
*texObj
,
990 GLenum pname
, const GLfloat
* params
)
992 r300TexObjPtr t
= (r300TexObjPtr
) texObj
->DriverData
;
994 if (RADEON_DEBUG
& (DEBUG_STATE
| DEBUG_TEXTURE
)) {
995 fprintf(stderr
, "%s( %s )\n", __FUNCTION__
,
996 _mesa_lookup_enum_by_nr(pname
));
1000 case GL_TEXTURE_MIN_FILTER
:
1001 case GL_TEXTURE_MAG_FILTER
:
1002 case GL_TEXTURE_MAX_ANISOTROPY_EXT
:
1003 r300SetTexMaxAnisotropy(t
, texObj
->MaxAnisotropy
);
1004 r300SetTexFilter(t
, texObj
->MinFilter
, texObj
->MagFilter
);
1007 case GL_TEXTURE_WRAP_S
:
1008 case GL_TEXTURE_WRAP_T
:
1009 case GL_TEXTURE_WRAP_R
:
1010 r300SetTexWrap(t
, texObj
->WrapS
, texObj
->WrapT
, texObj
->WrapR
);
1013 case GL_TEXTURE_BORDER_COLOR
:
1014 r300SetTexBorderColor(t
, texObj
->_BorderChan
);
1017 case GL_TEXTURE_BASE_LEVEL
:
1018 case GL_TEXTURE_MAX_LEVEL
:
1019 case GL_TEXTURE_MIN_LOD
:
1020 case GL_TEXTURE_MAX_LOD
:
1021 /* This isn't the most efficient solution but there doesn't appear to
1022 * be a nice alternative. Since there's no LOD clamping,
1023 * we just have to rely on loading the right subset of mipmap levels
1024 * to simulate a clamped LOD.
1026 driSwapOutTextureObject((driTextureObject
*) t
);
1033 /* Mark this texobj as dirty (one bit per tex unit)
1035 t
->dirty_state
= TEX_ALL
;
1038 static void r300BindTexture(GLcontext
* ctx
, GLenum target
,
1039 struct gl_texture_object
*texObj
)
1041 if (RADEON_DEBUG
& (DEBUG_STATE
| DEBUG_TEXTURE
)) {
1042 fprintf(stderr
, "%s( %p ) unit=%d\n", __FUNCTION__
,
1043 (void *)texObj
, ctx
->Texture
.CurrentUnit
);
1046 if ((target
== GL_TEXTURE_1D
)
1047 || (target
== GL_TEXTURE_2D
)
1048 #if ENABLE_HW_3D_TEXTURE
1049 || (target
== GL_TEXTURE_3D
)
1051 || (target
== GL_TEXTURE_CUBE_MAP
)
1052 || (target
== GL_TEXTURE_RECTANGLE_NV
)) {
1053 assert(texObj
->DriverData
!= NULL
);
1057 static void r300DeleteTexture(GLcontext
* ctx
, struct gl_texture_object
*texObj
)
1059 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
1060 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
1062 if (RADEON_DEBUG
& (DEBUG_STATE
| DEBUG_TEXTURE
)) {
1063 fprintf(stderr
, "%s( %p (target = %s) )\n", __FUNCTION__
,
1065 _mesa_lookup_enum_by_nr(texObj
->Target
));
1070 R300_FIREVERTICES(rmesa
);
1073 driDestroyTextureObject(t
);
1075 /* Free mipmap images and the texture object itself */
1076 _mesa_delete_texture_object(ctx
, texObj
);
1080 * Allocate a new texture object.
1081 * Called via ctx->Driver.NewTextureObject.
1082 * Note: this function will be called during context creation to
1083 * allocate the default texture objects.
1084 * Note: we could use containment here to 'derive' the driver-specific
1085 * texture object from the core mesa gl_texture_object. Not done at this time.
1086 * Fixup MaxAnisotropy according to user preference.
1088 static struct gl_texture_object
*r300NewTextureObject(GLcontext
* ctx
,
1092 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
1093 struct gl_texture_object
*obj
;
1094 obj
= _mesa_new_texture_object(ctx
, name
, target
);
1097 obj
->MaxAnisotropy
= rmesa
->initialMaxAnisotropy
;
1099 r300AllocTexObj(obj
);
1103 void r300InitTextureFuncs(struct dd_function_table
*functions
)
1105 /* Note: we only plug in the functions we implement in the driver
1106 * since _mesa_init_driver_functions() was already called.
1108 functions
->ChooseTextureFormat
= r300ChooseTextureFormat
;
1109 functions
->TexImage1D
= r300TexImage1D
;
1110 functions
->TexImage2D
= r300TexImage2D
;
1111 #if ENABLE_HW_3D_TEXTURE
1112 functions
->TexImage3D
= r300TexImage3D
;
1114 functions
->TexImage3D
= _mesa_store_teximage3d
;
1116 functions
->TexSubImage1D
= r300TexSubImage1D
;
1117 functions
->TexSubImage2D
= r300TexSubImage2D
;
1118 #if ENABLE_HW_3D_TEXTURE
1119 functions
->TexSubImage3D
= r300TexSubImage3D
;
1121 functions
->TexSubImage3D
= _mesa_store_texsubimage3d
;
1123 functions
->NewTextureObject
= r300NewTextureObject
;
1124 functions
->BindTexture
= r300BindTexture
;
1125 functions
->DeleteTexture
= r300DeleteTexture
;
1126 functions
->IsTextureResident
= driIsTextureResident
;
1128 functions
->TexEnv
= r300TexEnv
;
1129 functions
->TexParameter
= r300TexParameter
;
1131 functions
->CompressedTexImage2D
= r300CompressedTexImage2D
;
1132 functions
->CompressedTexSubImage2D
= r300CompressedTexSubImage2D
;
1134 driInitTextureFormats();
1137 /* moved or obsolete code */
1138 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
1139 driInitTextureObjects(ctx
, &rmesa
->swapped
,
1140 DRI_TEXMGR_DO_TEXTURE_1D
1141 | DRI_TEXMGR_DO_TEXTURE_2D
);
1143 /* Hack: r300NewTextureObject is not yet installed when the
1144 * default textures are created. Therefore set MaxAnisotropy of the
1145 * default 2D texture now. */
1146 ctx
->Shared
->Default2D
->MaxAnisotropy
=
1147 driQueryOptionf(&rmesa
->optionCache
, "def_max_anisotropy");