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_NEAREST_MIP_LINEAR
;
225 case GL_LINEAR_MIPMAP_NEAREST
:
226 t
->filter
|= R300_TX_MIN_FILTER_LINEAR_MIP_NEAREST
;
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 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
439 return &_mesa_texformat_rgb_dxt1
;
441 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
442 return &_mesa_texformat_rgba_dxt1
;
446 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
447 return &_mesa_texformat_rgba_dxt3
;
449 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
450 return &_mesa_texformat_rgba_dxt5
;
454 "unexpected internalFormat 0x%x in r300ChooseTextureFormat",
455 (int)internalFormat
);
459 return NULL
; /* never get here */
463 r300ValidateClientStorage(GLcontext
* ctx
, GLenum target
,
464 GLint internalFormat
,
465 GLint srcWidth
, GLint srcHeight
,
466 GLenum format
, GLenum type
, const void *pixels
,
467 const struct gl_pixelstore_attrib
*packing
,
468 struct gl_texture_object
*texObj
,
469 struct gl_texture_image
*texImage
)
471 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
474 fprintf(stderr
, "intformat %s format %s type %s\n",
475 _mesa_lookup_enum_by_nr(internalFormat
),
476 _mesa_lookup_enum_by_nr(format
),
477 _mesa_lookup_enum_by_nr(type
));
479 if (!ctx
->Unpack
.ClientStorage
)
482 if (ctx
->_ImageTransferState
||
483 texImage
->IsCompressed
|| texObj
->GenerateMipmap
)
486 /* This list is incomplete, may be different on ppc???
488 switch (internalFormat
) {
490 if (format
== GL_BGRA
&& type
== GL_UNSIGNED_INT_8_8_8_8_REV
) {
491 texImage
->TexFormat
= _dri_texformat_argb8888
;
497 if (format
== GL_RGB
&& type
== GL_UNSIGNED_SHORT_5_6_5
) {
498 texImage
->TexFormat
= _dri_texformat_rgb565
;
504 if (format
== GL_YCBCR_MESA
&&
505 type
== GL_UNSIGNED_SHORT_8_8_REV_APPLE
) {
506 texImage
->TexFormat
= &_mesa_texformat_ycbcr_rev
;
507 } else if (format
== GL_YCBCR_MESA
&&
508 (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
509 type
== GL_UNSIGNED_BYTE
)) {
510 texImage
->TexFormat
= &_mesa_texformat_ycbcr
;
519 /* Could deal with these packing issues, but currently don't:
521 if (packing
->SkipPixels
||
522 packing
->SkipRows
|| packing
->SwapBytes
|| packing
->LsbFirst
) {
527 GLint srcRowStride
= _mesa_image_row_stride(packing
, srcWidth
,
531 fprintf(stderr
, "%s: srcRowStride %d/%x\n",
532 __FUNCTION__
, srcRowStride
, srcRowStride
);
534 /* Could check this later in upload, pitch restrictions could be
535 * relaxed, but would need to store the image pitch somewhere,
536 * as packing details might change before image is uploaded:
538 if (!r300IsGartMemory(rmesa
, pixels
, srcHeight
* srcRowStride
)
539 || (srcRowStride
& 63))
542 /* Have validated that _mesa_transfer_teximage would be a straight
543 * memcpy at this point. NOTE: future calls to TexSubImage will
544 * overwrite the client data. This is explicitly mentioned in the
547 texImage
->Data
= (void *)pixels
;
548 texImage
->IsClientData
= GL_TRUE
;
549 texImage
->RowStride
=
550 srcRowStride
/ texImage
->TexFormat
->TexelBytes
;
556 static void r300TexImage1D(GLcontext
* ctx
, GLenum target
, GLint level
,
557 GLint internalFormat
,
558 GLint width
, GLint border
,
559 GLenum format
, GLenum type
, const GLvoid
* pixels
,
560 const struct gl_pixelstore_attrib
*packing
,
561 struct gl_texture_object
*texObj
,
562 struct gl_texture_image
*texImage
)
564 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
567 driSwapOutTextureObject(t
);
569 t
= (driTextureObject
*) r300AllocTexObj(texObj
);
571 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
576 /* Note, this will call ChooseTextureFormat */
577 _mesa_store_teximage1d(ctx
, target
, level
, internalFormat
,
578 width
, border
, format
, type
, pixels
,
579 &ctx
->Unpack
, texObj
, texImage
);
581 t
->dirty_images
[0] |= (1 << level
);
584 static void r300TexSubImage1D(GLcontext
* ctx
, GLenum target
, GLint level
,
587 GLenum format
, GLenum type
,
588 const GLvoid
* pixels
,
589 const struct gl_pixelstore_attrib
*packing
,
590 struct gl_texture_object
*texObj
,
591 struct gl_texture_image
*texImage
)
593 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
595 assert(t
); /* this _should_ be true */
597 driSwapOutTextureObject(t
);
599 t
= (driTextureObject
*) r300AllocTexObj(texObj
);
601 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
606 _mesa_store_texsubimage1d(ctx
, target
, level
, xoffset
, width
,
607 format
, type
, pixels
, packing
, texObj
,
610 t
->dirty_images
[0] |= (1 << level
);
613 static void r300TexImage2D(GLcontext
* ctx
, GLenum target
, GLint level
,
614 GLint internalFormat
,
615 GLint width
, GLint height
, GLint border
,
616 GLenum format
, GLenum type
, const GLvoid
* pixels
,
617 const struct gl_pixelstore_attrib
*packing
,
618 struct gl_texture_object
*texObj
,
619 struct gl_texture_image
*texImage
)
621 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
624 /* which cube face or ordinary 2D image */
626 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
627 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
628 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
629 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
630 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
631 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
633 (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
641 driSwapOutTextureObject(t
);
643 t
= (driTextureObject
*) r300AllocTexObj(texObj
);
645 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
650 texImage
->IsClientData
= GL_FALSE
;
652 if (r300ValidateClientStorage(ctx
, target
,
655 format
, type
, pixels
,
656 packing
, texObj
, texImage
)) {
657 if (RADEON_DEBUG
& DEBUG_TEXTURE
)
658 fprintf(stderr
, "%s: Using client storage\n",
661 if (RADEON_DEBUG
& DEBUG_TEXTURE
)
662 fprintf(stderr
, "%s: Using normal storage\n",
665 /* Normal path: copy (to cached memory) and eventually upload
666 * via another copy to GART memory and then a blit... Could
667 * eliminate one copy by going straight to (permanent) GART.
669 * Note, this will call r300ChooseTextureFormat.
671 _mesa_store_teximage2d(ctx
, target
, level
, internalFormat
,
672 width
, height
, border
, format
, type
,
673 pixels
, &ctx
->Unpack
, texObj
, texImage
);
675 t
->dirty_images
[face
] |= (1 << level
);
679 static void r300TexSubImage2D(GLcontext
* ctx
, GLenum target
, GLint level
,
680 GLint xoffset
, GLint yoffset
,
681 GLsizei width
, GLsizei height
,
682 GLenum format
, GLenum type
,
683 const GLvoid
* pixels
,
684 const struct gl_pixelstore_attrib
*packing
,
685 struct gl_texture_object
*texObj
,
686 struct gl_texture_image
*texImage
)
688 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
691 /* which cube face or ordinary 2D image */
693 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
694 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
695 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
696 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
697 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
698 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
700 (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
707 assert(t
); /* this _should_ be true */
709 driSwapOutTextureObject(t
);
711 t
= (driTextureObject
*) r300AllocTexObj(texObj
);
713 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
718 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
719 height
, format
, type
, pixels
, packing
, texObj
,
722 t
->dirty_images
[face
] |= (1 << level
);
725 static void r300CompressedTexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
726 GLint internalFormat
,
727 GLint width
, GLint height
, GLint border
,
728 GLsizei imageSize
, const GLvoid
*data
,
729 struct gl_texture_object
*texObj
,
730 struct gl_texture_image
*texImage
)
732 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
735 /* which cube face or ordinary 2D image */
737 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
738 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
739 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
740 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
741 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
742 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
743 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
751 driSwapOutTextureObject( t
);
754 t
= (driTextureObject
*) r300AllocTexObj( texObj
);
756 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2D");
761 texImage
->IsClientData
= GL_FALSE
;
762 /* can't call this, different parameters. Would never evaluate to true anyway currently
763 if (r300ValidateClientStorage( ctx, target,
766 format, type, pixels,
767 packing, texObj, texImage)) {
768 if (RADEON_DEBUG & DEBUG_TEXTURE)
769 fprintf(stderr, "%s: Using client storage\n", __FUNCTION__);
772 if (RADEON_DEBUG
& DEBUG_TEXTURE
)
773 fprintf(stderr
, "%s: Using normal storage\n", __FUNCTION__
);
775 /* Normal path: copy (to cached memory) and eventually upload
776 * via another copy to GART memory and then a blit... Could
777 * eliminate one copy by going straight to (permanent) GART.
779 * Note, this will call r300ChooseTextureFormat.
781 _mesa_store_compressed_teximage2d(ctx
, target
, level
, internalFormat
, width
,
782 height
, border
, imageSize
, data
, texObj
, texImage
);
784 t
->dirty_images
[face
] |= (1 << level
);
789 static void r300CompressedTexSubImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
790 GLint xoffset
, GLint yoffset
,
791 GLsizei width
, GLsizei height
,
793 GLsizei imageSize
, const GLvoid
*data
,
794 struct gl_texture_object
*texObj
,
795 struct gl_texture_image
*texImage
)
797 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
801 /* which cube face or ordinary 2D image */
803 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
804 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
805 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
806 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
807 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
808 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
809 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
816 assert( t
); /* this _should_ be true */
818 driSwapOutTextureObject( t
);
821 t
= (driTextureObject
*) r300AllocTexObj( texObj
);
823 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexSubImage3D");
828 _mesa_store_compressed_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
829 height
, format
, imageSize
, data
, texObj
, texImage
);
831 t
->dirty_images
[face
] |= (1 << level
);
834 #if ENABLE_HW_3D_TEXTURE
835 static void r300TexImage3D(GLcontext
* ctx
, GLenum target
, GLint level
,
836 GLint internalFormat
,
837 GLint width
, GLint height
, GLint depth
,
839 GLenum format
, GLenum type
, const GLvoid
* pixels
,
840 const struct gl_pixelstore_attrib
*packing
,
841 struct gl_texture_object
*texObj
,
842 struct gl_texture_image
*texImage
)
844 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
847 driSwapOutTextureObject(t
);
849 t
= (driTextureObject
*) r300AllocTexObj(texObj
);
851 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
856 texImage
->IsClientData
= GL_FALSE
;
859 if (r300ValidateClientStorage(ctx
, target
,
862 format
, type
, pixels
,
863 packing
, texObj
, texImage
)) {
864 if (RADEON_DEBUG
& DEBUG_TEXTURE
)
865 fprintf(stderr
, "%s: Using client storage\n",
870 if (RADEON_DEBUG
& DEBUG_TEXTURE
)
871 fprintf(stderr
, "%s: Using normal storage\n",
874 /* Normal path: copy (to cached memory) and eventually upload
875 * via another copy to GART memory and then a blit... Could
876 * eliminate one copy by going straight to (permanent) GART.
878 * Note, this will call r300ChooseTextureFormat.
880 _mesa_store_teximage3d(ctx
, target
, level
, internalFormat
,
881 width
, height
, depth
, border
,
882 format
, type
, pixels
,
883 &ctx
->Unpack
, texObj
, texImage
);
885 t
->dirty_images
[0] |= (1 << level
);
890 #if ENABLE_HW_3D_TEXTURE
892 r300TexSubImage3D(GLcontext
* ctx
, GLenum target
, GLint level
,
893 GLint xoffset
, GLint yoffset
, GLint zoffset
,
894 GLsizei width
, GLsizei height
, GLsizei depth
,
895 GLenum format
, GLenum type
,
896 const GLvoid
* pixels
,
897 const struct gl_pixelstore_attrib
*packing
,
898 struct gl_texture_object
*texObj
,
899 struct gl_texture_image
*texImage
)
901 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
903 /* fprintf(stderr, "%s\n", __FUNCTION__); */
905 assert(t
); /* this _should_ be true */
907 driSwapOutTextureObject(t
);
909 t
= (driTextureObject
*) r300AllocTexObj(texObj
);
911 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage3D");
914 texObj
->DriverData
= t
;
917 _mesa_store_texsubimage3d(ctx
, target
, level
, xoffset
, yoffset
, zoffset
,
918 width
, height
, depth
,
919 format
, type
, pixels
, packing
, texObj
,
922 t
->dirty_images
[0] |= (1 << level
);
926 static void r300TexEnv(GLcontext
* ctx
, GLenum target
,
927 GLenum pname
, const GLfloat
* param
)
929 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
930 GLuint unit
= ctx
->Texture
.CurrentUnit
;
932 if (RADEON_DEBUG
& DEBUG_STATE
) {
933 fprintf(stderr
, "%s( %s )\n",
934 __FUNCTION__
, _mesa_lookup_enum_by_nr(pname
));
937 /* This is incorrect: Need to maintain this data for each of
938 * GL_TEXTURE_{123}D, GL_TEXTURE_RECTANGLE_NV, etc, and switch
939 * between them according to _ReallyEnabled.
942 case GL_TEXTURE_ENV_COLOR
:{
943 WARN_ONCE("I am broken - Fixme !\n");
947 UNCLAMPED_FLOAT_TO_RGBA_CHAN(c, texUnit->EnvColor);
948 envColor = radeonPackColor(4, c[0], c[1], c[2], c[3]);
949 if (rmesa->hw.tf.cmd[TF_TFACTOR_0 + unit] != envColor) {
950 R200_STATECHANGE(rmesa, tf);
951 rmesa->hw.tf.cmd[TF_TFACTOR_0 + unit] =
957 case GL_TEXTURE_LOD_BIAS_EXT
:{
961 /* The R300's LOD bias is a signed 2's complement value with a
962 * range of -16.0 <= bias < 16.0.
964 * NOTE: Add a small bias to the bias for conform mipsel.c test.
968 driQueryOptionb(&rmesa
->radeon
.optionCache
,
969 "no_neg_lod_bias") ? 0.0 : -16.0;
970 bias
= CLAMP(bias
, min
, 16.0);
972 /* 0.0 - 16.0 == 0x0 - 0x1000 */
973 /* 0.0 - -16.0 == 0x1001 - 0x1fff */
974 b
= 0x1000 / 16.0 * bias
;
975 b
&= R300_LOD_BIAS_MASK
;
977 if(b
!= (rmesa
->hw
.tex
.unknown1
.cmd
[R300_TEX_VALUE_0
+unit
] & R300_LOD_BIAS_MASK
)){
978 R300_STATECHANGE(rmesa
, tex
.unknown1
);
979 rmesa
->hw
.tex
.unknown1
.cmd
[R300_TEX_VALUE_0
+unit
] &= ~R300_LOD_BIAS_MASK
;
980 rmesa
->hw
.tex
.unknown1
.cmd
[R300_TEX_VALUE_0
+unit
] |= b
;
991 * Changes variables and flags for a state update, which will happen at the
992 * next UpdateTextureState
995 static void r300TexParameter(GLcontext
* ctx
, GLenum target
,
996 struct gl_texture_object
*texObj
,
997 GLenum pname
, const GLfloat
* params
)
999 r300TexObjPtr t
= (r300TexObjPtr
) texObj
->DriverData
;
1001 if (RADEON_DEBUG
& (DEBUG_STATE
| DEBUG_TEXTURE
)) {
1002 fprintf(stderr
, "%s( %s )\n", __FUNCTION__
,
1003 _mesa_lookup_enum_by_nr(pname
));
1007 case GL_TEXTURE_MIN_FILTER
:
1008 case GL_TEXTURE_MAG_FILTER
:
1009 case GL_TEXTURE_MAX_ANISOTROPY_EXT
:
1010 r300SetTexMaxAnisotropy(t
, texObj
->MaxAnisotropy
);
1011 r300SetTexFilter(t
, texObj
->MinFilter
, texObj
->MagFilter
);
1014 case GL_TEXTURE_WRAP_S
:
1015 case GL_TEXTURE_WRAP_T
:
1016 case GL_TEXTURE_WRAP_R
:
1017 r300SetTexWrap(t
, texObj
->WrapS
, texObj
->WrapT
, texObj
->WrapR
);
1020 case GL_TEXTURE_BORDER_COLOR
:
1021 r300SetTexBorderColor(t
, texObj
->_BorderChan
);
1024 case GL_TEXTURE_BASE_LEVEL
:
1025 case GL_TEXTURE_MAX_LEVEL
:
1026 case GL_TEXTURE_MIN_LOD
:
1027 case GL_TEXTURE_MAX_LOD
:
1028 /* This isn't the most efficient solution but there doesn't appear to
1029 * be a nice alternative. Since there's no LOD clamping,
1030 * we just have to rely on loading the right subset of mipmap levels
1031 * to simulate a clamped LOD.
1033 driSwapOutTextureObject((driTextureObject
*) t
);
1040 /* Mark this texobj as dirty (one bit per tex unit)
1042 t
->dirty_state
= TEX_ALL
;
1045 static void r300BindTexture(GLcontext
* ctx
, GLenum target
,
1046 struct gl_texture_object
*texObj
)
1048 if (RADEON_DEBUG
& (DEBUG_STATE
| DEBUG_TEXTURE
)) {
1049 fprintf(stderr
, "%s( %p ) unit=%d\n", __FUNCTION__
,
1050 (void *)texObj
, ctx
->Texture
.CurrentUnit
);
1053 if ((target
== GL_TEXTURE_1D
)
1054 || (target
== GL_TEXTURE_2D
)
1055 #if ENABLE_HW_3D_TEXTURE
1056 || (target
== GL_TEXTURE_3D
)
1058 || (target
== GL_TEXTURE_CUBE_MAP
)
1059 || (target
== GL_TEXTURE_RECTANGLE_NV
)) {
1060 assert(texObj
->DriverData
!= NULL
);
1064 static void r300DeleteTexture(GLcontext
* ctx
, struct gl_texture_object
*texObj
)
1066 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
1067 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
1069 if (RADEON_DEBUG
& (DEBUG_STATE
| DEBUG_TEXTURE
)) {
1070 fprintf(stderr
, "%s( %p (target = %s) )\n", __FUNCTION__
,
1072 _mesa_lookup_enum_by_nr(texObj
->Target
));
1077 R300_FIREVERTICES(rmesa
);
1080 driDestroyTextureObject(t
);
1082 /* Free mipmap images and the texture object itself */
1083 _mesa_delete_texture_object(ctx
, texObj
);
1087 * Allocate a new texture object.
1088 * Called via ctx->Driver.NewTextureObject.
1089 * Note: this function will be called during context creation to
1090 * allocate the default texture objects.
1091 * Note: we could use containment here to 'derive' the driver-specific
1092 * texture object from the core mesa gl_texture_object. Not done at this time.
1093 * Fixup MaxAnisotropy according to user preference.
1095 static struct gl_texture_object
*r300NewTextureObject(GLcontext
* ctx
,
1099 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
1100 struct gl_texture_object
*obj
;
1101 obj
= _mesa_new_texture_object(ctx
, name
, target
);
1104 obj
->MaxAnisotropy
= rmesa
->initialMaxAnisotropy
;
1106 r300AllocTexObj(obj
);
1110 void r300InitTextureFuncs(struct dd_function_table
*functions
)
1112 /* Note: we only plug in the functions we implement in the driver
1113 * since _mesa_init_driver_functions() was already called.
1115 functions
->ChooseTextureFormat
= r300ChooseTextureFormat
;
1116 functions
->TexImage1D
= r300TexImage1D
;
1117 functions
->TexImage2D
= r300TexImage2D
;
1118 #if ENABLE_HW_3D_TEXTURE
1119 functions
->TexImage3D
= r300TexImage3D
;
1121 functions
->TexImage3D
= _mesa_store_teximage3d
;
1123 functions
->TexSubImage1D
= r300TexSubImage1D
;
1124 functions
->TexSubImage2D
= r300TexSubImage2D
;
1125 #if ENABLE_HW_3D_TEXTURE
1126 functions
->TexSubImage3D
= r300TexSubImage3D
;
1128 functions
->TexSubImage3D
= _mesa_store_texsubimage3d
;
1130 functions
->NewTextureObject
= r300NewTextureObject
;
1131 functions
->BindTexture
= r300BindTexture
;
1132 functions
->DeleteTexture
= r300DeleteTexture
;
1133 functions
->IsTextureResident
= driIsTextureResident
;
1135 functions
->TexEnv
= r300TexEnv
;
1136 functions
->TexParameter
= r300TexParameter
;
1138 functions
->CompressedTexImage2D
= r300CompressedTexImage2D
;
1139 functions
->CompressedTexSubImage2D
= r300CompressedTexSubImage2D
;
1141 driInitTextureFormats();
1144 /* moved or obsolete code */
1145 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
1146 driInitTextureObjects(ctx
, &rmesa
->swapped
,
1147 DRI_TEXMGR_DO_TEXTURE_1D
1148 | DRI_TEXMGR_DO_TEXTURE_2D
);
1150 /* Hack: r300NewTextureObject is not yet installed when the
1151 * default textures are created. Therefore set MaxAnisotropy of the
1152 * default 2D texture now. */
1153 ctx
->Shared
->Default2D
->MaxAnisotropy
=
1154 driQueryOptionf(&rmesa
->optionCache
, "def_max_anisotropy");