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 GLboolean is_clamp
= GL_FALSE
;
68 unsigned long hw_swrap
=0, hw_twrap
=0, hw_qwrap
=0;
71 ~(R300_TX_WRAP_S_MASK
| R300_TX_WRAP_T_MASK
| R300_TX_WRAP_Q_MASK
);
75 hw_swrap
|= R300_TX_REPEAT
;
78 hw_swrap
|= R300_TX_CLAMP
;
81 case GL_CLAMP_TO_EDGE
:
82 hw_swrap
|= R300_TX_CLAMP_TO_EDGE
;
84 case GL_CLAMP_TO_BORDER
:
85 hw_swrap
|= R300_TX_CLAMP_TO_BORDER
;
87 case GL_MIRRORED_REPEAT
:
88 hw_swrap
|= R300_TX_REPEAT
| R300_TX_MIRRORED
;
90 case GL_MIRROR_CLAMP_EXT
:
91 hw_swrap
|= R300_TX_CLAMP
| R300_TX_MIRRORED
;
94 case GL_MIRROR_CLAMP_TO_EDGE_EXT
:
95 hw_swrap
|= R300_TX_CLAMP_TO_EDGE
| R300_TX_MIRRORED
;
97 case GL_MIRROR_CLAMP_TO_BORDER_EXT
:
98 hw_swrap
|= R300_TX_CLAMP_TO_BORDER
| R300_TX_MIRRORED
;
101 _mesa_problem(NULL
, "bad S wrap mode in %s", __FUNCTION__
);
106 hw_twrap
|= R300_TX_REPEAT
;
109 hw_twrap
|= R300_TX_CLAMP
;
112 case GL_CLAMP_TO_EDGE
:
113 hw_twrap
|= R300_TX_CLAMP_TO_EDGE
;
115 case GL_CLAMP_TO_BORDER
:
116 hw_twrap
|= R300_TX_CLAMP_TO_BORDER
;
118 case GL_MIRRORED_REPEAT
:
119 hw_twrap
|= R300_TX_REPEAT
| R300_TX_MIRRORED
;
121 case GL_MIRROR_CLAMP_EXT
:
122 hw_twrap
|= R300_TX_CLAMP
| R300_TX_MIRRORED
;
125 case GL_MIRROR_CLAMP_TO_EDGE_EXT
:
126 hw_twrap
|= R300_TX_CLAMP_TO_EDGE
| R300_TX_MIRRORED
;
128 case GL_MIRROR_CLAMP_TO_BORDER_EXT
:
129 hw_twrap
|= R300_TX_CLAMP_TO_BORDER
| R300_TX_MIRRORED
;
132 _mesa_problem(NULL
, "bad T wrap mode in %s", __FUNCTION__
);
137 hw_qwrap
|= R300_TX_REPEAT
;
140 hw_qwrap
|= R300_TX_CLAMP
;
143 case GL_CLAMP_TO_EDGE
:
144 hw_qwrap
|= R300_TX_CLAMP_TO_EDGE
;
146 case GL_CLAMP_TO_BORDER
:
147 hw_qwrap
|= R300_TX_CLAMP_TO_BORDER
;
149 case GL_MIRRORED_REPEAT
:
150 hw_qwrap
|= R300_TX_REPEAT
| R300_TX_MIRRORED
;
152 case GL_MIRROR_CLAMP_EXT
:
153 hw_qwrap
|= R300_TX_CLAMP
| R300_TX_MIRRORED
;
156 case GL_MIRROR_CLAMP_TO_EDGE_EXT
:
157 hw_qwrap
|= R300_TX_CLAMP_TO_EDGE
| R300_TX_MIRRORED
;
159 case GL_MIRROR_CLAMP_TO_BORDER_EXT
:
160 hw_qwrap
|= R300_TX_CLAMP_TO_BORDER
| R300_TX_MIRRORED
;
163 _mesa_problem(NULL
, "bad R wrap mode in %s", __FUNCTION__
);
166 t
->filter
|= hw_swrap
<< R300_TX_WRAP_S_SHIFT
;
167 t
->filter
|= hw_twrap
<< R300_TX_WRAP_T_SHIFT
;
168 t
->filter
|= hw_qwrap
<< R300_TX_WRAP_Q_SHIFT
;
171 t
->format_x
&= ~R200_CLAMP_Q_MASK
;
172 t
->border_fallback
= (is_clamp
&& is_clamp_to_border
);
176 static void r300SetTexMaxAnisotropy(r300TexObjPtr t
, GLfloat max
)
179 t
->filter
&= ~R300_TX_MAX_ANISO_MASK
;
182 t
->filter
|= R300_TX_MAX_ANISO_1_TO_1
;
183 } else if (max
<= 2.0) {
184 t
->filter
|= R300_TX_MAX_ANISO_2_TO_1
;
185 } else if (max
<= 4.0) {
186 t
->filter
|= R300_TX_MAX_ANISO_4_TO_1
;
187 } else if (max
<= 8.0) {
188 t
->filter
|= R300_TX_MAX_ANISO_8_TO_1
;
190 t
->filter
|= R300_TX_MAX_ANISO_16_TO_1
;
195 * Set the texture magnification and minification modes.
197 * \param t Texture whose filter modes are to be set
198 * \param minf Texture minification mode
199 * \param magf Texture magnification mode
202 static void r300SetTexFilter(r300TexObjPtr t
, GLenum minf
, GLenum magf
)
204 GLuint anisotropy
= (t
->filter
& R300_TX_MAX_ANISO_MASK
);
206 t
->filter
&= ~(R300_TX_MIN_FILTER_MASK
| R300_TX_MAG_FILTER_MASK
);
208 //t->format_x &= ~R200_VOLUME_FILTER_MASK;
211 if (anisotropy
== R300_TX_MAX_ANISO_1_TO_1
) {
214 t
->filter
|= R300_TX_MIN_FILTER_NEAREST
;
217 t
->filter
|= R300_TX_MIN_FILTER_LINEAR
;
219 case GL_NEAREST_MIPMAP_NEAREST
:
220 t
->filter
|= R300_TX_MIN_FILTER_NEAREST_MIP_NEAREST
;
222 case GL_NEAREST_MIPMAP_LINEAR
:
223 t
->filter
|= R300_TX_MIN_FILTER_LINEAR_MIP_NEAREST
;
225 case GL_LINEAR_MIPMAP_NEAREST
:
226 t
->filter
|= R300_TX_MIN_FILTER_NEAREST_MIP_LINEAR
;
228 case GL_LINEAR_MIPMAP_LINEAR
:
229 t
->filter
|= R300_TX_MIN_FILTER_LINEAR_MIP_LINEAR
;
235 t
->filter
|= R300_TX_MIN_FILTER_ANISO_NEAREST
;
238 t
->filter
|= R300_TX_MIN_FILTER_ANISO_LINEAR
;
240 case GL_NEAREST_MIPMAP_NEAREST
:
241 case GL_LINEAR_MIPMAP_NEAREST
:
243 R300_TX_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST
;
245 case GL_NEAREST_MIPMAP_LINEAR
:
246 case GL_LINEAR_MIPMAP_LINEAR
:
248 R300_TX_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
->filter
|= R300_TX_MAG_FILTER_NEAREST
;
259 /*t->format_x |= R200_VOLUME_FILTER_NEAREST;*/
262 t
->filter
|= R300_TX_MAG_FILTER_LINEAR
;
263 /*t->format_x |= R200_VOLUME_FILTER_LINEAR;*/
268 static void r300SetTexBorderColor(r300TexObjPtr t
, GLubyte c
[4])
270 t
->pp_border_color
= r300PackColor(4, c
[0], c
[1], c
[2], c
[3]);
274 * Allocate space for and load the mesa images into the texture memory block.
275 * This will happen before drawing with a new texture, or drawing with a
276 * texture after it was swapped out or teximaged again.
279 static r300TexObjPtr
r300AllocTexObj(struct gl_texture_object
*texObj
)
283 t
= CALLOC_STRUCT(r300_tex_obj
);
284 texObj
->DriverData
= t
;
286 if (RADEON_DEBUG
& DEBUG_TEXTURE
) {
287 fprintf(stderr
, "%s( %p, %p )\n", __FUNCTION__
,
288 (void *)texObj
, (void *)t
);
291 /* Initialize non-image-dependent parts of the state:
293 t
->base
.tObj
= texObj
;
294 t
->border_fallback
= GL_FALSE
;
296 make_empty_list(&t
->base
);
298 r300SetTexWrap(t
, texObj
->WrapS
, texObj
->WrapT
, texObj
->WrapR
);
299 r300SetTexMaxAnisotropy(t
, texObj
->MaxAnisotropy
);
300 r300SetTexFilter(t
, texObj
->MinFilter
, texObj
->MagFilter
);
301 r300SetTexBorderColor(t
, texObj
->_BorderChan
);
307 static const struct gl_texture_format
*r300ChooseTextureFormat(GLcontext
* ctx
,
313 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
314 const GLboolean do32bpt
=
315 (rmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_32
);
316 const GLboolean force16bpt
=
317 (rmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_FORCE_16
);
321 fprintf(stderr
, "InternalFormat=%s(%d) type=%s format=%s\n",
322 _mesa_lookup_enum_by_nr(internalFormat
), internalFormat
,
323 _mesa_lookup_enum_by_nr(type
),
324 _mesa_lookup_enum_by_nr(format
));
325 fprintf(stderr
, "do32bpt=%d force16bpt=%d\n",
326 do32bpt
, force16bpt
);
329 switch (internalFormat
) {
332 case GL_COMPRESSED_RGBA
:
334 case GL_UNSIGNED_INT_10_10_10_2
:
335 case GL_UNSIGNED_INT_2_10_10_10_REV
:
336 return do32bpt
? _dri_texformat_argb8888
:
337 _dri_texformat_argb1555
;
338 case GL_UNSIGNED_SHORT_4_4_4_4
:
339 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
340 return _dri_texformat_argb4444
;
341 case GL_UNSIGNED_SHORT_5_5_5_1
:
342 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
343 return _dri_texformat_argb1555
;
345 return do32bpt
? _dri_texformat_rgba8888
:
346 _dri_texformat_argb4444
;
351 case GL_COMPRESSED_RGB
:
353 case GL_UNSIGNED_SHORT_4_4_4_4
:
354 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
355 return _dri_texformat_argb4444
;
356 case GL_UNSIGNED_SHORT_5_5_5_1
:
357 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
358 return _dri_texformat_argb1555
;
359 case GL_UNSIGNED_SHORT_5_6_5
:
360 case GL_UNSIGNED_SHORT_5_6_5_REV
:
361 return _dri_texformat_rgb565
;
363 return do32bpt
? _dri_texformat_rgba8888
:
364 _dri_texformat_rgb565
;
372 _dri_texformat_rgba8888
: _dri_texformat_argb4444
;
376 return _dri_texformat_argb4444
;
379 return _dri_texformat_argb1555
;
385 return !force16bpt
? _dri_texformat_rgba8888
:
386 _dri_texformat_rgb565
;
391 return _dri_texformat_rgb565
;
398 case GL_COMPRESSED_ALPHA
:
399 return _dri_texformat_a8
;
407 case GL_COMPRESSED_LUMINANCE
:
408 return _dri_texformat_l8
;
411 case GL_LUMINANCE_ALPHA
:
412 case GL_LUMINANCE4_ALPHA4
:
413 case GL_LUMINANCE6_ALPHA2
:
414 case GL_LUMINANCE8_ALPHA8
:
415 case GL_LUMINANCE12_ALPHA4
:
416 case GL_LUMINANCE12_ALPHA12
:
417 case GL_LUMINANCE16_ALPHA16
:
418 case GL_COMPRESSED_LUMINANCE_ALPHA
:
419 return _dri_texformat_al88
;
426 case GL_COMPRESSED_INTENSITY
:
427 return _dri_texformat_i8
;
430 if (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
431 type
== GL_UNSIGNED_BYTE
)
432 return &_mesa_texformat_ycbcr
;
434 return &_mesa_texformat_ycbcr_rev
;
438 "unexpected internalFormat 0x%x in r300ChooseTextureFormat",
439 (int)internalFormat
);
443 return NULL
; /* never get here */
447 r300ValidateClientStorage(GLcontext
* ctx
, GLenum target
,
448 GLint internalFormat
,
449 GLint srcWidth
, GLint srcHeight
,
450 GLenum format
, GLenum type
, const void *pixels
,
451 const struct gl_pixelstore_attrib
*packing
,
452 struct gl_texture_object
*texObj
,
453 struct gl_texture_image
*texImage
)
455 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
458 fprintf(stderr
, "intformat %s format %s type %s\n",
459 _mesa_lookup_enum_by_nr(internalFormat
),
460 _mesa_lookup_enum_by_nr(format
),
461 _mesa_lookup_enum_by_nr(type
));
463 if (!ctx
->Unpack
.ClientStorage
)
466 if (ctx
->_ImageTransferState
||
467 texImage
->IsCompressed
|| texObj
->GenerateMipmap
)
470 /* This list is incomplete, may be different on ppc???
472 switch (internalFormat
) {
474 if (format
== GL_BGRA
&& type
== GL_UNSIGNED_INT_8_8_8_8_REV
) {
475 texImage
->TexFormat
= _dri_texformat_argb8888
;
481 if (format
== GL_RGB
&& type
== GL_UNSIGNED_SHORT_5_6_5
) {
482 texImage
->TexFormat
= _dri_texformat_rgb565
;
488 if (format
== GL_YCBCR_MESA
&&
489 type
== GL_UNSIGNED_SHORT_8_8_REV_APPLE
) {
490 texImage
->TexFormat
= &_mesa_texformat_ycbcr_rev
;
491 } else if (format
== GL_YCBCR_MESA
&&
492 (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
493 type
== GL_UNSIGNED_BYTE
)) {
494 texImage
->TexFormat
= &_mesa_texformat_ycbcr
;
503 /* Could deal with these packing issues, but currently don't:
505 if (packing
->SkipPixels
||
506 packing
->SkipRows
|| packing
->SwapBytes
|| packing
->LsbFirst
) {
511 GLint srcRowStride
= _mesa_image_row_stride(packing
, srcWidth
,
515 fprintf(stderr
, "%s: srcRowStride %d/%x\n",
516 __FUNCTION__
, srcRowStride
, srcRowStride
);
518 /* Could check this later in upload, pitch restrictions could be
519 * relaxed, but would need to store the image pitch somewhere,
520 * as packing details might change before image is uploaded:
522 if (!r300IsGartMemory(rmesa
, pixels
, srcHeight
* srcRowStride
)
523 || (srcRowStride
& 63))
526 /* Have validated that _mesa_transfer_teximage would be a straight
527 * memcpy at this point. NOTE: future calls to TexSubImage will
528 * overwrite the client data. This is explicitly mentioned in the
531 texImage
->Data
= (void *)pixels
;
532 texImage
->IsClientData
= GL_TRUE
;
533 texImage
->RowStride
=
534 srcRowStride
/ texImage
->TexFormat
->TexelBytes
;
540 static void r300TexImage1D(GLcontext
* ctx
, GLenum target
, GLint level
,
541 GLint internalFormat
,
542 GLint width
, GLint border
,
543 GLenum format
, GLenum type
, const GLvoid
* pixels
,
544 const struct gl_pixelstore_attrib
*packing
,
545 struct gl_texture_object
*texObj
,
546 struct gl_texture_image
*texImage
)
548 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
551 driSwapOutTextureObject(t
);
553 t
= (driTextureObject
*) r300AllocTexObj(texObj
);
555 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
560 /* Note, this will call ChooseTextureFormat */
561 _mesa_store_teximage1d(ctx
, target
, level
, internalFormat
,
562 width
, border
, format
, type
, pixels
,
563 &ctx
->Unpack
, texObj
, texImage
);
565 t
->dirty_images
[0] |= (1 << level
);
568 static void r300TexSubImage1D(GLcontext
* ctx
, GLenum target
, GLint level
,
571 GLenum format
, GLenum type
,
572 const GLvoid
* pixels
,
573 const struct gl_pixelstore_attrib
*packing
,
574 struct gl_texture_object
*texObj
,
575 struct gl_texture_image
*texImage
)
577 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
579 assert(t
); /* this _should_ be true */
581 driSwapOutTextureObject(t
);
583 t
= (driTextureObject
*) r300AllocTexObj(texObj
);
585 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
590 _mesa_store_texsubimage1d(ctx
, target
, level
, xoffset
, width
,
591 format
, type
, pixels
, packing
, texObj
,
594 t
->dirty_images
[0] |= (1 << level
);
597 static void r300TexImage2D(GLcontext
* ctx
, GLenum target
, GLint level
,
598 GLint internalFormat
,
599 GLint width
, GLint height
, GLint border
,
600 GLenum format
, GLenum type
, const GLvoid
* pixels
,
601 const struct gl_pixelstore_attrib
*packing
,
602 struct gl_texture_object
*texObj
,
603 struct gl_texture_image
*texImage
)
605 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
608 /* which cube face or ordinary 2D image */
610 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
611 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
612 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
613 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
614 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
615 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
617 (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
625 driSwapOutTextureObject(t
);
627 t
= (driTextureObject
*) r300AllocTexObj(texObj
);
629 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
634 texImage
->IsClientData
= GL_FALSE
;
636 if (r300ValidateClientStorage(ctx
, target
,
639 format
, type
, pixels
,
640 packing
, texObj
, texImage
)) {
641 if (RADEON_DEBUG
& DEBUG_TEXTURE
)
642 fprintf(stderr
, "%s: Using client storage\n",
645 if (RADEON_DEBUG
& DEBUG_TEXTURE
)
646 fprintf(stderr
, "%s: Using normal storage\n",
649 /* Normal path: copy (to cached memory) and eventually upload
650 * via another copy to GART memory and then a blit... Could
651 * eliminate one copy by going straight to (permanent) GART.
653 * Note, this will call r300ChooseTextureFormat.
655 _mesa_store_teximage2d(ctx
, target
, level
, internalFormat
,
656 width
, height
, border
, format
, type
,
657 pixels
, &ctx
->Unpack
, texObj
, texImage
);
659 t
->dirty_images
[face
] |= (1 << level
);
663 static void r300TexSubImage2D(GLcontext
* ctx
, GLenum target
, GLint level
,
664 GLint xoffset
, GLint yoffset
,
665 GLsizei width
, GLsizei height
,
666 GLenum format
, GLenum type
,
667 const GLvoid
* pixels
,
668 const struct gl_pixelstore_attrib
*packing
,
669 struct gl_texture_object
*texObj
,
670 struct gl_texture_image
*texImage
)
672 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
675 /* which cube face or ordinary 2D image */
677 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
678 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
679 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
680 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
681 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
682 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
684 (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
691 assert(t
); /* this _should_ be true */
693 driSwapOutTextureObject(t
);
695 t
= (driTextureObject
*) r300AllocTexObj(texObj
);
697 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
702 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
703 height
, format
, type
, pixels
, packing
, texObj
,
706 t
->dirty_images
[face
] |= (1 << level
);
709 #if ENABLE_HW_3D_TEXTURE
710 static void r300TexImage3D(GLcontext
* ctx
, GLenum target
, GLint level
,
711 GLint internalFormat
,
712 GLint width
, GLint height
, GLint depth
,
714 GLenum format
, GLenum type
, const GLvoid
* pixels
,
715 const struct gl_pixelstore_attrib
*packing
,
716 struct gl_texture_object
*texObj
,
717 struct gl_texture_image
*texImage
)
719 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
722 driSwapOutTextureObject(t
);
724 t
= (driTextureObject
*) r300AllocTexObj(texObj
);
726 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
731 texImage
->IsClientData
= GL_FALSE
;
734 if (r300ValidateClientStorage(ctx
, target
,
737 format
, type
, pixels
,
738 packing
, texObj
, texImage
)) {
739 if (RADEON_DEBUG
& DEBUG_TEXTURE
)
740 fprintf(stderr
, "%s: Using client storage\n",
745 if (RADEON_DEBUG
& DEBUG_TEXTURE
)
746 fprintf(stderr
, "%s: Using normal storage\n",
749 /* Normal path: copy (to cached memory) and eventually upload
750 * via another copy to GART memory and then a blit... Could
751 * eliminate one copy by going straight to (permanent) GART.
753 * Note, this will call r300ChooseTextureFormat.
755 _mesa_store_teximage3d(ctx
, target
, level
, internalFormat
,
756 width
, height
, depth
, border
,
757 format
, type
, pixels
,
758 &ctx
->Unpack
, texObj
, texImage
);
760 t
->dirty_images
[0] |= (1 << level
);
765 #if ENABLE_HW_3D_TEXTURE
767 r300TexSubImage3D(GLcontext
* ctx
, GLenum target
, GLint level
,
768 GLint xoffset
, GLint yoffset
, GLint zoffset
,
769 GLsizei width
, GLsizei height
, GLsizei depth
,
770 GLenum format
, GLenum type
,
771 const GLvoid
* pixels
,
772 const struct gl_pixelstore_attrib
*packing
,
773 struct gl_texture_object
*texObj
,
774 struct gl_texture_image
*texImage
)
776 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
778 /* fprintf(stderr, "%s\n", __FUNCTION__); */
780 assert(t
); /* this _should_ be true */
782 driSwapOutTextureObject(t
);
784 t
= (driTextureObject
*) r300AllocTexObj(texObj
);
786 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage3D");
789 texObj
->DriverData
= t
;
792 _mesa_store_texsubimage3d(ctx
, target
, level
, xoffset
, yoffset
, zoffset
,
793 width
, height
, depth
,
794 format
, type
, pixels
, packing
, texObj
,
797 t
->dirty_images
[0] |= (1 << level
);
801 static void r300TexEnv(GLcontext
* ctx
, GLenum target
,
802 GLenum pname
, const GLfloat
* param
)
804 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
805 GLuint unit
= ctx
->Texture
.CurrentUnit
;
806 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
808 if (RADEON_DEBUG
& DEBUG_STATE
) {
809 fprintf(stderr
, "%s( %s )\n",
810 __FUNCTION__
, _mesa_lookup_enum_by_nr(pname
));
813 /* This is incorrect: Need to maintain this data for each of
814 * GL_TEXTURE_{123}D, GL_TEXTURE_RECTANGLE_NV, etc, and switch
815 * between them according to _ReallyEnabled.
818 case GL_TEXTURE_ENV_COLOR
:{
819 fprintf(stderr
, "%s:%s I am broken - Fixme !\n", __FILE__
, __FUNCTION__
);
823 UNCLAMPED_FLOAT_TO_RGBA_CHAN(c, texUnit->EnvColor);
824 envColor = radeonPackColor(4, c[0], c[1], c[2], c[3]);
825 if (rmesa->hw.tf.cmd[TF_TFACTOR_0 + unit] != envColor) {
826 R200_STATECHANGE(rmesa, tf);
827 rmesa->hw.tf.cmd[TF_TFACTOR_0 + unit] =
833 case GL_TEXTURE_LOD_BIAS_EXT
:{
837 /* The R300's LOD bias is a signed 2's complement value with a
838 * range of -16.0 <= bias < 16.0.
840 * NOTE: Add a small bias to the bias for conform mipsel.c test.
844 driQueryOptionb(&rmesa
->radeon
.optionCache
,
845 "no_neg_lod_bias") ? 0.0 : -16.0;
846 bias
= CLAMP(bias
, min
, 16.0);
848 /* 0.0 - 16.0 == 0x0 - 0x1000 */
849 /* 0.0 - -16.0 == 0x1001 - 0x1fff */
850 b
= 0x1000 / 16.0 * bias
;
851 b
&= R300_LOD_BIAS_MASK
;
853 if(b
!= (rmesa
->hw
.tex
.unknown1
.cmd
[R300_TEX_VALUE_0
+unit
] & R300_LOD_BIAS_MASK
)){
854 R300_STATECHANGE(rmesa
, tex
.unknown1
);
855 rmesa
->hw
.tex
.unknown1
.cmd
[R300_TEX_VALUE_0
+unit
] &= ~R300_LOD_BIAS_MASK
;
856 rmesa
->hw
.tex
.unknown1
.cmd
[R300_TEX_VALUE_0
+unit
] |= b
;
867 * Changes variables and flags for a state update, which will happen at the
868 * next UpdateTextureState
871 static void r300TexParameter(GLcontext
* ctx
, GLenum target
,
872 struct gl_texture_object
*texObj
,
873 GLenum pname
, const GLfloat
* params
)
875 r300TexObjPtr t
= (r300TexObjPtr
) texObj
->DriverData
;
877 if (RADEON_DEBUG
& (DEBUG_STATE
| DEBUG_TEXTURE
)) {
878 fprintf(stderr
, "%s( %s )\n", __FUNCTION__
,
879 _mesa_lookup_enum_by_nr(pname
));
883 case GL_TEXTURE_MIN_FILTER
:
884 case GL_TEXTURE_MAG_FILTER
:
885 case GL_TEXTURE_MAX_ANISOTROPY_EXT
:
886 r300SetTexMaxAnisotropy(t
, texObj
->MaxAnisotropy
);
887 r300SetTexFilter(t
, texObj
->MinFilter
, texObj
->MagFilter
);
890 case GL_TEXTURE_WRAP_S
:
891 case GL_TEXTURE_WRAP_T
:
892 case GL_TEXTURE_WRAP_R
:
893 r300SetTexWrap(t
, texObj
->WrapS
, texObj
->WrapT
, texObj
->WrapR
);
896 case GL_TEXTURE_BORDER_COLOR
:
897 r300SetTexBorderColor(t
, texObj
->_BorderChan
);
900 case GL_TEXTURE_BASE_LEVEL
:
901 case GL_TEXTURE_MAX_LEVEL
:
902 case GL_TEXTURE_MIN_LOD
:
903 case GL_TEXTURE_MAX_LOD
:
904 /* This isn't the most efficient solution but there doesn't appear to
905 * be a nice alternative. Since there's no LOD clamping,
906 * we just have to rely on loading the right subset of mipmap levels
907 * to simulate a clamped LOD.
909 driSwapOutTextureObject((driTextureObject
*) t
);
916 /* Mark this texobj as dirty (one bit per tex unit)
918 t
->dirty_state
= TEX_ALL
;
921 static void r300BindTexture(GLcontext
* ctx
, GLenum target
,
922 struct gl_texture_object
*texObj
)
924 if (RADEON_DEBUG
& (DEBUG_STATE
| DEBUG_TEXTURE
)) {
925 fprintf(stderr
, "%s( %p ) unit=%d\n", __FUNCTION__
,
926 (void *)texObj
, ctx
->Texture
.CurrentUnit
);
929 if ((target
== GL_TEXTURE_1D
)
930 || (target
== GL_TEXTURE_2D
)
931 #if ENABLE_HW_3D_TEXTURE
932 || (target
== GL_TEXTURE_3D
)
934 || (target
== GL_TEXTURE_CUBE_MAP
)
935 || (target
== GL_TEXTURE_RECTANGLE_NV
)) {
936 assert(texObj
->DriverData
!= NULL
);
940 static void r300DeleteTexture(GLcontext
* ctx
, struct gl_texture_object
*texObj
)
942 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
943 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
945 if (RADEON_DEBUG
& (DEBUG_STATE
| DEBUG_TEXTURE
)) {
946 fprintf(stderr
, "%s( %p (target = %s) )\n", __FUNCTION__
,
948 _mesa_lookup_enum_by_nr(texObj
->Target
));
953 R300_FIREVERTICES(rmesa
);
956 driDestroyTextureObject(t
);
958 /* Free mipmap images and the texture object itself */
959 _mesa_delete_texture_object(ctx
, texObj
);
963 * - Same GEN_MODE for all active bits
964 * - Same EyePlane/ObjPlane for all active bits when using Eye/Obj
965 * - STRQ presumably all supported (matrix means incoming R values
966 * can end up in STQ, this has implications for vertex support,
967 * presumably ok if maos is used, though?)
969 * Basically impossible to do this on the fly - just collect some
970 * basic info & do the checks from ValidateState().
972 static void r300TexGen(GLcontext
* ctx
,
973 GLenum coord
, GLenum pname
, const GLfloat
* params
)
975 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
976 GLuint unit
= ctx
->Texture
.CurrentUnit
;
977 #if 0 /* Disable this for now - looks like we will be recalculating everything
979 rmesa
->recheck_texgen
[unit
] = GL_TRUE
;
984 * Allocate a new texture object.
985 * Called via ctx->Driver.NewTextureObject.
986 * Note: this function will be called during context creation to
987 * allocate the default texture objects.
988 * Note: we could use containment here to 'derive' the driver-specific
989 * texture object from the core mesa gl_texture_object. Not done at this time.
990 * Fixup MaxAnisotropy according to user preference.
992 static struct gl_texture_object
*r300NewTextureObject(GLcontext
* ctx
,
996 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
997 struct gl_texture_object
*obj
;
998 obj
= _mesa_new_texture_object(ctx
, name
, target
);
1001 obj
->MaxAnisotropy
= rmesa
->initialMaxAnisotropy
;
1003 r300AllocTexObj(obj
);
1007 void r300InitTextureFuncs(struct dd_function_table
*functions
)
1009 /* Note: we only plug in the functions we implement in the driver
1010 * since _mesa_init_driver_functions() was already called.
1012 functions
->ChooseTextureFormat
= r300ChooseTextureFormat
;
1013 functions
->TexImage1D
= r300TexImage1D
;
1014 functions
->TexImage2D
= r300TexImage2D
;
1015 #if ENABLE_HW_3D_TEXTURE
1016 functions
->TexImage3D
= r300TexImage3D
;
1018 functions
->TexImage3D
= _mesa_store_teximage3d
;
1020 functions
->TexSubImage1D
= r300TexSubImage1D
;
1021 functions
->TexSubImage2D
= r300TexSubImage2D
;
1022 #if ENABLE_HW_3D_TEXTURE
1023 functions
->TexSubImage3D
= r300TexSubImage3D
;
1025 functions
->TexSubImage3D
= _mesa_store_texsubimage3d
;
1027 functions
->NewTextureObject
= r300NewTextureObject
;
1028 functions
->BindTexture
= r300BindTexture
;
1029 functions
->DeleteTexture
= r300DeleteTexture
;
1030 functions
->IsTextureResident
= driIsTextureResident
;
1032 functions
->TexEnv
= r300TexEnv
;
1033 functions
->TexParameter
= r300TexParameter
;
1034 functions
->TexGen
= r300TexGen
;
1036 driInitTextureFormats();
1039 /* moved or obsolete code */
1040 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
1041 driInitTextureObjects(ctx
, &rmesa
->swapped
,
1042 DRI_TEXMGR_DO_TEXTURE_1D
1043 | DRI_TEXMGR_DO_TEXTURE_2D
);
1045 /* Hack: r300NewTextureObject is not yet installed when the
1046 * default textures are created. Therefore set MaxAnisotropy of the
1047 * default 2D texture now. */
1048 ctx
->Shared
->Default2D
->MaxAnisotropy
=
1049 driQueryOptionf(&rmesa
->optionCache
, "def_max_anisotropy");