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.
32 * \author 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"
56 static unsigned int translate_wrap_mode(GLenum wrapmode
)
59 case GL_REPEAT
: return R300_TX_REPEAT
;
60 case GL_CLAMP
: return R300_TX_CLAMP
;
61 case GL_CLAMP_TO_EDGE
: return R300_TX_CLAMP_TO_EDGE
;
62 case GL_CLAMP_TO_BORDER
: return R300_TX_CLAMP_TO_BORDER
;
63 case GL_MIRRORED_REPEAT
: return R300_TX_REPEAT
| R300_TX_MIRRORED
;
64 case GL_MIRROR_CLAMP_EXT
: return R300_TX_CLAMP
| R300_TX_MIRRORED
;
65 case GL_MIRROR_CLAMP_TO_EDGE_EXT
: return R300_TX_CLAMP_TO_EDGE
| R300_TX_MIRRORED
;
66 case GL_MIRROR_CLAMP_TO_BORDER_EXT
: return R300_TX_CLAMP_TO_BORDER
| R300_TX_MIRRORED
;
68 _mesa_problem(NULL
, "bad wrap mode in %s", __FUNCTION__
);
75 * Update the cached hardware registers based on the current texture wrap modes.
77 * \param t Texture object whose wrap modes are to be set
79 static void r300UpdateTexWrap(r300TexObjPtr t
)
81 struct gl_texture_object
*tObj
= t
->base
.tObj
;
84 ~(R300_TX_WRAP_S_MASK
| R300_TX_WRAP_T_MASK
| R300_TX_WRAP_R_MASK
);
86 t
->filter
|= translate_wrap_mode(tObj
->WrapS
) << R300_TX_WRAP_S_SHIFT
;
88 if (tObj
->Target
!= GL_TEXTURE_1D
) {
89 t
->filter
|= translate_wrap_mode(tObj
->WrapT
) << R300_TX_WRAP_T_SHIFT
;
91 if (tObj
->Target
== GL_TEXTURE_3D
)
92 t
->filter
|= translate_wrap_mode(tObj
->WrapR
) << R300_TX_WRAP_R_SHIFT
;
96 static GLuint
aniso_filter(GLfloat anisotropy
)
98 if (anisotropy
>= 16.0) {
99 return R300_TX_MAX_ANISO_16_TO_1
;
100 } else if (anisotropy
>= 8.0) {
101 return R300_TX_MAX_ANISO_8_TO_1
;
102 } else if (anisotropy
>= 4.0) {
103 return R300_TX_MAX_ANISO_4_TO_1
;
104 } else if (anisotropy
>= 2.0) {
105 return R300_TX_MAX_ANISO_2_TO_1
;
107 return R300_TX_MAX_ANISO_1_TO_1
;
112 * Set the texture magnification and minification modes.
114 * \param t Texture whose filter modes are to be set
115 * \param minf Texture minification mode
116 * \param magf Texture magnification mode
117 * \param anisotropy Maximum anisotropy level
119 static void r300SetTexFilter(r300TexObjPtr t
, GLenum minf
, GLenum magf
, GLfloat anisotropy
)
121 t
->filter
&= ~(R300_TX_MIN_FILTER_MASK
| R300_TX_MIN_FILTER_MIP_MASK
| R300_TX_MAG_FILTER_MASK
| R300_TX_MAX_ANISO_MASK
);
122 t
->filter_1
&= ~R300_EDGE_ANISO_EDGE_ONLY
;
124 /* Note that EXT_texture_filter_anisotropic is extremely vague about
125 * how anisotropic filtering interacts with the "normal" filter modes.
126 * When anisotropic filtering is enabled, we override min and mag
127 * filter settings completely. This includes driconf's settings.
129 if (anisotropy
>= 2.0 && (minf
!= GL_NEAREST
) && (magf
!= GL_NEAREST
)) {
130 t
->filter
|= R300_TX_MAG_FILTER_ANISO
131 | R300_TX_MIN_FILTER_ANISO
132 | R300_TX_MIN_FILTER_MIP_LINEAR
133 | aniso_filter(anisotropy
);
134 if (RADEON_DEBUG
& DEBUG_TEXTURE
)
135 fprintf(stderr
, "Using maximum anisotropy of %f\n", anisotropy
);
141 t
->filter
|= R300_TX_MIN_FILTER_NEAREST
;
144 t
->filter
|= R300_TX_MIN_FILTER_LINEAR
;
146 case GL_NEAREST_MIPMAP_NEAREST
:
147 t
->filter
|= R300_TX_MIN_FILTER_NEAREST
|R300_TX_MIN_FILTER_MIP_NEAREST
;
149 case GL_NEAREST_MIPMAP_LINEAR
:
150 t
->filter
|= R300_TX_MIN_FILTER_NEAREST
|R300_TX_MIN_FILTER_MIP_LINEAR
;
152 case GL_LINEAR_MIPMAP_NEAREST
:
153 t
->filter
|= R300_TX_MIN_FILTER_LINEAR
|R300_TX_MIN_FILTER_MIP_NEAREST
;
155 case GL_LINEAR_MIPMAP_LINEAR
:
156 t
->filter
|= R300_TX_MIN_FILTER_LINEAR
|R300_TX_MIN_FILTER_MIP_LINEAR
;
160 /* Note we don't have 3D mipmaps so only use the mag filter setting
161 * to set the 3D texture filter mode.
165 t
->filter
|= R300_TX_MAG_FILTER_NEAREST
;
168 t
->filter
|= R300_TX_MAG_FILTER_LINEAR
;
173 static void r300SetTexBorderColor(r300TexObjPtr t
, GLubyte c
[4])
175 t
->pp_border_color
= PACK_COLOR_8888(c
[3], c
[0], c
[1], c
[2]);
178 static void r300SetTexLodBias(r300TexObjPtr t
, GLfloat bias
)
181 b
= (unsigned int)fabsf(ceilf(bias
*31));
183 b
^= 0x3ff; /* 10 bits */
186 b
&= R300_LOD_BIAS_MASK
;
188 t
->filter_1
&= ~R300_LOD_BIAS_MASK
;
193 * Allocate space for and load the mesa images into the texture memory block.
194 * This will happen before drawing with a new texture, or drawing with a
195 * texture after it was swapped out or teximaged again.
198 static r300TexObjPtr
r300AllocTexObj(struct gl_texture_object
*texObj
)
202 t
= CALLOC_STRUCT(r300_tex_obj
);
203 texObj
->DriverData
= t
;
205 if (RADEON_DEBUG
& DEBUG_TEXTURE
) {
206 fprintf(stderr
, "%s( %p, %p )\n", __FUNCTION__
,
207 (void *)texObj
, (void *)t
);
210 /* Initialize non-image-dependent parts of the state:
212 t
->base
.tObj
= texObj
;
213 t
->border_fallback
= GL_FALSE
;
215 make_empty_list(&t
->base
);
217 r300UpdateTexWrap(t
);
218 r300SetTexFilter(t
, texObj
->MinFilter
, texObj
->MagFilter
, texObj
->MaxAnisotropy
);
219 r300SetTexBorderColor(t
, texObj
->_BorderChan
);
225 /* try to find a format which will only need a memcopy */
226 static const struct gl_texture_format
*r300Choose8888TexFormat(GLenum srcFormat
,
230 const GLubyte littleEndian
= *((const GLubyte
*)&ui
);
232 if ((srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8
) ||
233 (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
) ||
234 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) ||
235 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_BYTE
&& littleEndian
)) {
236 return &_mesa_texformat_rgba8888
;
237 } else if ((srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) ||
238 (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
&& littleEndian
) ||
239 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_INT_8_8_8_8
) ||
240 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
)) {
241 return &_mesa_texformat_rgba8888_rev
;
242 } else if (srcFormat
== GL_BGRA
&& ((srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
) ||
243 srcType
== GL_UNSIGNED_INT_8_8_8_8
)) {
244 return &_mesa_texformat_argb8888_rev
;
245 } else if (srcFormat
== GL_BGRA
&& ((srcType
== GL_UNSIGNED_BYTE
&& littleEndian
) ||
246 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
)) {
247 return &_mesa_texformat_argb8888
;
249 return _dri_texformat_argb8888
;
252 static const struct gl_texture_format
*r300ChooseTextureFormat(GLcontext
* ctx
,
258 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
259 const GLboolean do32bpt
=
260 (rmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_32
);
261 const GLboolean force16bpt
=
262 (rmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_FORCE_16
);
266 fprintf(stderr
, "InternalFormat=%s(%d) type=%s format=%s\n",
267 _mesa_lookup_enum_by_nr(internalFormat
), internalFormat
,
268 _mesa_lookup_enum_by_nr(type
), _mesa_lookup_enum_by_nr(format
));
269 fprintf(stderr
, "do32bpt=%d force16bpt=%d\n", do32bpt
, force16bpt
);
272 switch (internalFormat
) {
275 case GL_COMPRESSED_RGBA
:
277 case GL_UNSIGNED_INT_10_10_10_2
:
278 case GL_UNSIGNED_INT_2_10_10_10_REV
:
279 return do32bpt
? _dri_texformat_argb8888
:
280 _dri_texformat_argb1555
;
281 case GL_UNSIGNED_SHORT_4_4_4_4
:
282 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
283 return _dri_texformat_argb4444
;
284 case GL_UNSIGNED_SHORT_5_5_5_1
:
285 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
286 return _dri_texformat_argb1555
;
288 return do32bpt
? r300Choose8888TexFormat(format
, type
) :
289 _dri_texformat_argb4444
;
294 case GL_COMPRESSED_RGB
:
296 case GL_UNSIGNED_SHORT_4_4_4_4
:
297 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
298 return _dri_texformat_argb4444
;
299 case GL_UNSIGNED_SHORT_5_5_5_1
:
300 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
301 return _dri_texformat_argb1555
;
302 case GL_UNSIGNED_SHORT_5_6_5
:
303 case GL_UNSIGNED_SHORT_5_6_5_REV
:
304 return _dri_texformat_rgb565
;
306 return do32bpt
? _dri_texformat_argb8888
:
307 _dri_texformat_rgb565
;
315 r300Choose8888TexFormat(format
,
316 type
) : _dri_texformat_argb4444
;
320 return _dri_texformat_argb4444
;
323 return _dri_texformat_argb1555
;
329 return !force16bpt
? _dri_texformat_argb8888
:
330 _dri_texformat_rgb565
;
335 return _dri_texformat_rgb565
;
342 case GL_COMPRESSED_ALPHA
:
343 return _dri_texformat_a8
;
351 case GL_COMPRESSED_LUMINANCE
:
352 return _dri_texformat_l8
;
355 case GL_LUMINANCE_ALPHA
:
356 case GL_LUMINANCE4_ALPHA4
:
357 case GL_LUMINANCE6_ALPHA2
:
358 case GL_LUMINANCE8_ALPHA8
:
359 case GL_LUMINANCE12_ALPHA4
:
360 case GL_LUMINANCE12_ALPHA12
:
361 case GL_LUMINANCE16_ALPHA16
:
362 case GL_COMPRESSED_LUMINANCE_ALPHA
:
363 return _dri_texformat_al88
;
370 case GL_COMPRESSED_INTENSITY
:
371 return _dri_texformat_i8
;
374 if (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
375 type
== GL_UNSIGNED_BYTE
)
376 return &_mesa_texformat_ycbcr
;
378 return &_mesa_texformat_ycbcr_rev
;
382 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
383 return &_mesa_texformat_rgb_dxt1
;
385 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
386 return &_mesa_texformat_rgba_dxt1
;
390 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
391 return &_mesa_texformat_rgba_dxt3
;
393 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
394 return &_mesa_texformat_rgba_dxt5
;
396 case GL_ALPHA16F_ARB
:
397 return &_mesa_texformat_alpha_float16
;
398 case GL_ALPHA32F_ARB
:
399 return &_mesa_texformat_alpha_float32
;
400 case GL_LUMINANCE16F_ARB
:
401 return &_mesa_texformat_luminance_float16
;
402 case GL_LUMINANCE32F_ARB
:
403 return &_mesa_texformat_luminance_float32
;
404 case GL_LUMINANCE_ALPHA16F_ARB
:
405 return &_mesa_texformat_luminance_alpha_float16
;
406 case GL_LUMINANCE_ALPHA32F_ARB
:
407 return &_mesa_texformat_luminance_alpha_float32
;
408 case GL_INTENSITY16F_ARB
:
409 return &_mesa_texformat_intensity_float16
;
410 case GL_INTENSITY32F_ARB
:
411 return &_mesa_texformat_intensity_float32
;
413 return &_mesa_texformat_rgba_float16
;
415 return &_mesa_texformat_rgba_float32
;
417 return &_mesa_texformat_rgba_float16
;
419 return &_mesa_texformat_rgba_float32
;
421 case GL_DEPTH_COMPONENT
:
422 case GL_DEPTH_COMPONENT16
:
423 case GL_DEPTH_COMPONENT24
:
424 case GL_DEPTH_COMPONENT32
:
427 case GL_UNSIGNED_BYTE
:
428 case GL_UNSIGNED_SHORT
:
429 return &_mesa_texformat_z16
;
430 case GL_UNSIGNED_INT
:
431 return &_mesa_texformat_z32
;
432 case GL_UNSIGNED_INT_24_8_EXT
:
434 return &_mesa_texformat_z24_s8
;
437 return &_mesa_texformat_z16
;
442 "unexpected internalFormat 0x%x in r300ChooseTextureFormat",
443 (int)internalFormat
);
447 return NULL
; /* never get here */
451 r300ValidateClientStorage(GLcontext
* ctx
, GLenum target
,
452 GLint internalFormat
,
453 GLint srcWidth
, GLint srcHeight
,
454 GLenum format
, GLenum type
, const void *pixels
,
455 const struct gl_pixelstore_attrib
*packing
,
456 struct gl_texture_object
*texObj
,
457 struct gl_texture_image
*texImage
)
459 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
461 if (RADEON_DEBUG
& DEBUG_TEXTURE
)
462 fprintf(stderr
, "intformat %s format %s type %s\n",
463 _mesa_lookup_enum_by_nr(internalFormat
),
464 _mesa_lookup_enum_by_nr(format
),
465 _mesa_lookup_enum_by_nr(type
));
467 if (!ctx
->Unpack
.ClientStorage
)
470 if (ctx
->_ImageTransferState
||
471 texImage
->IsCompressed
|| texObj
->GenerateMipmap
)
474 /* This list is incomplete, may be different on ppc???
476 switch (internalFormat
) {
478 if (format
== GL_BGRA
&& type
== GL_UNSIGNED_INT_8_8_8_8_REV
) {
479 texImage
->TexFormat
= _dri_texformat_argb8888
;
485 if (format
== GL_RGB
&& type
== GL_UNSIGNED_SHORT_5_6_5
) {
486 texImage
->TexFormat
= _dri_texformat_rgb565
;
492 if (format
== GL_YCBCR_MESA
&&
493 type
== GL_UNSIGNED_SHORT_8_8_REV_APPLE
) {
494 texImage
->TexFormat
= &_mesa_texformat_ycbcr_rev
;
495 } else if (format
== GL_YCBCR_MESA
&&
496 (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
497 type
== GL_UNSIGNED_BYTE
)) {
498 texImage
->TexFormat
= &_mesa_texformat_ycbcr
;
507 /* Could deal with these packing issues, but currently don't:
509 if (packing
->SkipPixels
||
510 packing
->SkipRows
|| packing
->SwapBytes
|| packing
->LsbFirst
) {
514 GLint srcRowStride
= _mesa_image_row_stride(packing
, srcWidth
,
517 if (RADEON_DEBUG
& DEBUG_TEXTURE
)
518 fprintf(stderr
, "%s: srcRowStride %d/%x\n",
519 __FUNCTION__
, srcRowStride
, srcRowStride
);
521 /* Could check this later in upload, pitch restrictions could be
522 * relaxed, but would need to store the image pitch somewhere,
523 * as packing details might change before image is uploaded:
525 if (!r300IsGartMemory(rmesa
, pixels
, srcHeight
* srcRowStride
)
526 || (srcRowStride
& 63))
529 /* Have validated that _mesa_transfer_teximage would be a straight
530 * memcpy at this point. NOTE: future calls to TexSubImage will
531 * overwrite the client data. This is explicitly mentioned in the
534 texImage
->Data
= (void *)pixels
;
535 texImage
->IsClientData
= GL_TRUE
;
536 texImage
->RowStride
= srcRowStride
/ texImage
->TexFormat
->TexelBytes
;
541 static void r300TexImage1D(GLcontext
* ctx
, GLenum target
, GLint level
,
542 GLint internalFormat
,
543 GLint width
, GLint border
,
544 GLenum format
, GLenum type
, const GLvoid
* pixels
,
545 const struct gl_pixelstore_attrib
*packing
,
546 struct gl_texture_object
*texObj
,
547 struct gl_texture_image
*texImage
)
549 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
552 driSwapOutTextureObject(t
);
554 t
= (driTextureObject
*) r300AllocTexObj(texObj
);
556 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
561 /* Note, this will call ChooseTextureFormat */
562 _mesa_store_teximage1d(ctx
, target
, level
, internalFormat
,
563 width
, border
, format
, type
, pixels
,
564 &ctx
->Unpack
, texObj
, texImage
);
566 t
->dirty_images
[0] |= (1 << level
);
569 static void r300TexSubImage1D(GLcontext
* ctx
, GLenum target
, GLint level
,
572 GLenum format
, GLenum type
,
573 const GLvoid
* pixels
,
574 const struct gl_pixelstore_attrib
*packing
,
575 struct gl_texture_object
*texObj
,
576 struct gl_texture_image
*texImage
)
578 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
580 assert(t
); /* this _should_ be true */
582 driSwapOutTextureObject(t
);
584 t
= (driTextureObject
*) r300AllocTexObj(texObj
);
586 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
591 _mesa_store_texsubimage1d(ctx
, target
, level
, xoffset
, width
,
592 format
, type
, pixels
, packing
, texObj
,
595 t
->dirty_images
[0] |= (1 << level
);
598 static void r300TexImage2D(GLcontext
* ctx
, GLenum target
, GLint level
,
599 GLint internalFormat
,
600 GLint width
, GLint height
, GLint border
,
601 GLenum format
, GLenum type
, const GLvoid
* pixels
,
602 const struct gl_pixelstore_attrib
*packing
,
603 struct gl_texture_object
*texObj
,
604 struct gl_texture_image
*texImage
)
606 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
609 /* which cube face or ordinary 2D image */
611 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
612 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
613 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
614 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
615 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
616 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
618 (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
626 driSwapOutTextureObject(t
);
628 t
= (driTextureObject
*) r300AllocTexObj(texObj
);
630 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
635 texImage
->IsClientData
= GL_FALSE
;
637 if (r300ValidateClientStorage(ctx
, target
,
640 format
, type
, pixels
,
641 packing
, texObj
, texImage
)) {
642 if (RADEON_DEBUG
& DEBUG_TEXTURE
)
643 fprintf(stderr
, "%s: Using client storage\n",
646 if (RADEON_DEBUG
& DEBUG_TEXTURE
)
647 fprintf(stderr
, "%s: Using normal storage\n",
650 /* Normal path: copy (to cached memory) and eventually upload
651 * via another copy to GART memory and then a blit... Could
652 * eliminate one copy by going straight to (permanent) GART.
654 * Note, this will call r300ChooseTextureFormat.
656 _mesa_store_teximage2d(ctx
, target
, level
, internalFormat
,
657 width
, height
, border
, format
, type
,
658 pixels
, &ctx
->Unpack
, texObj
, texImage
);
660 t
->dirty_images
[face
] |= (1 << level
);
664 static void r300TexSubImage2D(GLcontext
* ctx
, GLenum target
, GLint level
,
665 GLint xoffset
, GLint yoffset
,
666 GLsizei width
, GLsizei height
,
667 GLenum format
, GLenum type
,
668 const GLvoid
* pixels
,
669 const struct gl_pixelstore_attrib
*packing
,
670 struct gl_texture_object
*texObj
,
671 struct gl_texture_image
*texImage
)
673 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
676 /* which cube face or ordinary 2D image */
678 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
679 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
680 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
681 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
682 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
683 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
685 (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
692 assert(t
); /* this _should_ be true */
694 driSwapOutTextureObject(t
);
696 t
= (driTextureObject
*) r300AllocTexObj(texObj
);
698 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
703 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
704 height
, format
, type
, pixels
, packing
, texObj
,
707 t
->dirty_images
[face
] |= (1 << level
);
710 static void r300CompressedTexImage2D(GLcontext
* ctx
, GLenum target
,
711 GLint level
, GLint internalFormat
,
712 GLint width
, GLint height
, GLint border
,
713 GLsizei imageSize
, const GLvoid
* data
,
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
:
729 (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
737 driSwapOutTextureObject(t
);
739 t
= (driTextureObject
*) r300AllocTexObj(texObj
);
741 _mesa_error(ctx
, GL_OUT_OF_MEMORY
,
742 "glCompressedTexImage2D");
747 texImage
->IsClientData
= GL_FALSE
;
749 /* can't call this, different parameters. Would never evaluate to true anyway currently */
751 if (r300ValidateClientStorage(ctx
, target
,
754 format
, type
, pixels
,
755 packing
, texObj
, texImage
)) {
756 if (RADEON_DEBUG
& DEBUG_TEXTURE
)
757 fprintf(stderr
, "%s: Using client storage\n",
762 if (RADEON_DEBUG
& DEBUG_TEXTURE
)
763 fprintf(stderr
, "%s: Using normal storage\n",
766 /* Normal path: copy (to cached memory) and eventually upload
767 * via another copy to GART memory and then a blit... Could
768 * eliminate one copy by going straight to (permanent) GART.
770 * Note, this will call r300ChooseTextureFormat.
772 _mesa_store_compressed_teximage2d(ctx
, target
, level
,
773 internalFormat
, width
, height
,
774 border
, imageSize
, data
,
777 t
->dirty_images
[face
] |= (1 << level
);
781 static void r300CompressedTexSubImage2D(GLcontext
* ctx
, GLenum target
,
782 GLint level
, GLint xoffset
,
783 GLint yoffset
, GLsizei width
,
784 GLsizei height
, GLenum format
,
785 GLsizei imageSize
, const GLvoid
* data
,
786 struct gl_texture_object
*texObj
,
787 struct gl_texture_image
*texImage
)
789 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
792 /* which cube face or ordinary 2D image */
794 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
795 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
796 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
797 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
798 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
799 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
801 (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
808 assert(t
); /* this _should_ be true */
810 driSwapOutTextureObject(t
);
812 t
= (driTextureObject
*) r300AllocTexObj(texObj
);
814 _mesa_error(ctx
, GL_OUT_OF_MEMORY
,
815 "glCompressedTexSubImage3D");
820 _mesa_store_compressed_texsubimage2d(ctx
, target
, level
, xoffset
,
821 yoffset
, width
, height
, format
,
822 imageSize
, data
, texObj
, texImage
);
824 t
->dirty_images
[face
] |= (1 << level
);
827 static void r300TexImage3D(GLcontext
* ctx
, GLenum target
, GLint level
,
828 GLint internalFormat
,
829 GLint width
, GLint height
, GLint depth
,
831 GLenum format
, GLenum type
, const GLvoid
* pixels
,
832 const struct gl_pixelstore_attrib
*packing
,
833 struct gl_texture_object
*texObj
,
834 struct gl_texture_image
*texImage
)
836 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
839 driSwapOutTextureObject(t
);
841 t
= (driTextureObject
*) r300AllocTexObj(texObj
);
843 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
848 texImage
->IsClientData
= GL_FALSE
;
851 if (r300ValidateClientStorage(ctx
, target
,
854 format
, type
, pixels
,
855 packing
, texObj
, texImage
)) {
856 if (RADEON_DEBUG
& DEBUG_TEXTURE
)
857 fprintf(stderr
, "%s: Using client storage\n",
862 if (RADEON_DEBUG
& DEBUG_TEXTURE
)
863 fprintf(stderr
, "%s: Using normal storage\n",
866 /* Normal path: copy (to cached memory) and eventually upload
867 * via another copy to GART memory and then a blit... Could
868 * eliminate one copy by going straight to (permanent) GART.
870 * Note, this will call r300ChooseTextureFormat.
872 _mesa_store_teximage3d(ctx
, target
, level
, internalFormat
,
873 width
, height
, depth
, border
,
874 format
, type
, pixels
,
875 &ctx
->Unpack
, texObj
, texImage
);
877 t
->dirty_images
[0] |= (1 << level
);
882 r300TexSubImage3D(GLcontext
* ctx
, GLenum target
, GLint level
,
883 GLint xoffset
, GLint yoffset
, GLint zoffset
,
884 GLsizei width
, GLsizei height
, GLsizei depth
,
885 GLenum format
, GLenum type
,
886 const GLvoid
* pixels
,
887 const struct gl_pixelstore_attrib
*packing
,
888 struct gl_texture_object
*texObj
,
889 struct gl_texture_image
*texImage
)
891 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
893 /* fprintf(stderr, "%s\n", __FUNCTION__); */
895 assert(t
); /* this _should_ be true */
897 driSwapOutTextureObject(t
);
899 t
= (driTextureObject
*) r300AllocTexObj(texObj
);
901 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage3D");
904 texObj
->DriverData
= t
;
907 _mesa_store_texsubimage3d(ctx
, target
, level
, xoffset
, yoffset
, zoffset
,
908 width
, height
, depth
,
909 format
, type
, pixels
, packing
, texObj
,
912 t
->dirty_images
[0] |= (1 << level
);
915 /* This feels like a prime target for code reuse, so I'm putting it here
916 * instead of inlining it in TexEnv. */
917 static GLenum
r300TexUnitTarget(struct gl_texture_unit
*unit
) {
918 if (unit
->_ReallyEnabled
& (TEXTURE_RECT_BIT
)) {
919 return GL_TEXTURE_RECTANGLE_NV
;
920 } else if (unit
->_ReallyEnabled
& (TEXTURE_1D_BIT
)) {
921 return GL_TEXTURE_1D
;
922 } else if (unit
->_ReallyEnabled
& (TEXTURE_2D_BIT
)) {
923 return GL_TEXTURE_2D
;
924 } else if (unit
->_ReallyEnabled
& (TEXTURE_3D_BIT
)) {
925 return GL_TEXTURE_3D
;
926 } else if (unit
->_ReallyEnabled
& (TEXTURE_CUBE_BIT
)) {
927 return GL_TEXTURE_CUBE_MAP
;
929 if (unit
->Enabled
& (TEXTURE_RECT_BIT
)) {
930 return GL_TEXTURE_RECTANGLE_NV
;
931 } else if (unit
->Enabled
& (TEXTURE_1D_BIT
)) {
932 return GL_TEXTURE_1D
;
933 } else if (unit
->Enabled
& (TEXTURE_2D_BIT
)) {
934 return GL_TEXTURE_2D
;
935 } else if (unit
->Enabled
& (TEXTURE_3D_BIT
)) {
936 return GL_TEXTURE_3D
;
937 } else if (unit
->Enabled
& (TEXTURE_CUBE_BIT
)) {
938 return GL_TEXTURE_CUBE_MAP
;
943 static void r300TexEnv(GLcontext
* ctx
, GLenum target
,
944 GLenum pname
, const GLfloat
* param
)
946 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
947 if (RADEON_DEBUG
& DEBUG_STATE
) {
948 fprintf(stderr
, "%s( %s )\n",
949 __FUNCTION__
, _mesa_lookup_enum_by_nr(pname
));
952 /* This is incorrect: Need to maintain this data for each of
953 * GL_TEXTURE_{123}D, GL_TEXTURE_RECTANGLE_NV, etc, and switch
954 * between them according to _ReallyEnabled.
957 case GL_TEXTURE_LOD_BIAS_EXT
: {
960 /* The R300's LOD bias is a signed 2's complement value with a
961 * range of -16.0 <= bias < 16.0.
963 * NOTE: Add a small bias to the bias for conform mipsel.c test.
966 min
= driQueryOptionb(&rmesa
->radeon
.optionCache
,
967 "no_neg_lod_bias") ? 0.0 : -16.0;
968 bias
= CLAMP(bias
, min
, 16.0);
970 /* There's probably a magic Mesa method for finding the REAL
971 * texture unit. I don't know it, though. */
972 if (!(ctx
->Texture
._EnabledUnits
& (1 << ctx
->Texture
.CurrentUnit
))) {
976 /* Save our newly clamped LOD bias. */
977 ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
].LodBias
= bias
;
988 * Changes variables and flags for a state update, which will happen at the
989 * next UpdateTextureState
992 static void r300TexParameter(GLcontext
* ctx
, GLenum target
,
993 struct gl_texture_object
*texObj
,
994 GLenum pname
, const GLfloat
* params
)
996 r300TexObjPtr t
= (r300TexObjPtr
) texObj
->DriverData
;
998 if (RADEON_DEBUG
& (DEBUG_STATE
| DEBUG_TEXTURE
)) {
999 fprintf(stderr
, "%s( %s )\n", __FUNCTION__
,
1000 _mesa_lookup_enum_by_nr(pname
));
1004 case GL_TEXTURE_MIN_FILTER
:
1005 case GL_TEXTURE_MAG_FILTER
:
1006 case GL_TEXTURE_MAX_ANISOTROPY_EXT
:
1007 r300SetTexFilter(t
, texObj
->MinFilter
, texObj
->MagFilter
, texObj
->MaxAnisotropy
);
1010 case GL_TEXTURE_WRAP_S
:
1011 case GL_TEXTURE_WRAP_T
:
1012 case GL_TEXTURE_WRAP_R
:
1013 r300UpdateTexWrap(t
);
1016 case GL_TEXTURE_BORDER_COLOR
:
1017 r300SetTexBorderColor(t
, texObj
->_BorderChan
);
1020 case GL_TEXTURE_BASE_LEVEL
:
1021 case GL_TEXTURE_MAX_LEVEL
:
1022 case GL_TEXTURE_MIN_LOD
:
1023 case GL_TEXTURE_MAX_LOD
:
1024 /* This isn't the most efficient solution but there doesn't appear to
1025 * be a nice alternative. Since there's no LOD clamping,
1026 * we just have to rely on loading the right subset of mipmap levels
1027 * to simulate a clamped LOD.
1029 driSwapOutTextureObject((driTextureObject
*) t
);
1032 case GL_DEPTH_TEXTURE_MODE
:
1033 if (texObj
->Image
[0][texObj
->BaseLevel
]->TexFormat
->BaseFormat
1034 == GL_DEPTH_COMPONENT
) {
1035 r300SetDepthTexMode(texObj
);
1038 /* If the texture isn't a depth texture, changing this
1039 * state won't cause any changes to the hardware.
1040 * Don't force a flush of texture state.
1050 static void r300BindTexture(GLcontext
* ctx
, GLenum target
,
1051 struct gl_texture_object
*texObj
)
1053 if (RADEON_DEBUG
& (DEBUG_STATE
| DEBUG_TEXTURE
)) {
1054 fprintf(stderr
, "%s( %p ) unit=%d\n", __FUNCTION__
,
1055 (void *)texObj
, ctx
->Texture
.CurrentUnit
);
1058 if ((target
== GL_TEXTURE_1D
)
1059 || (target
== GL_TEXTURE_2D
)
1060 || (target
== GL_TEXTURE_3D
)
1061 || (target
== GL_TEXTURE_CUBE_MAP
)
1062 || (target
== GL_TEXTURE_RECTANGLE_NV
)) {
1063 assert(texObj
->DriverData
!= NULL
);
1067 static void r300DeleteTexture(GLcontext
* ctx
, struct gl_texture_object
*texObj
)
1069 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
1070 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
1072 if (RADEON_DEBUG
& (DEBUG_STATE
| DEBUG_TEXTURE
)) {
1073 fprintf(stderr
, "%s( %p (target = %s) )\n", __FUNCTION__
,
1075 _mesa_lookup_enum_by_nr(texObj
->Target
));
1080 R300_FIREVERTICES(rmesa
);
1083 driDestroyTextureObject(t
);
1085 /* Free mipmap images and the texture object itself */
1086 _mesa_delete_texture_object(ctx
, texObj
);
1090 * Allocate a new texture object.
1091 * Called via ctx->Driver.NewTextureObject.
1092 * Note: this function will be called during context creation to
1093 * allocate the default texture objects.
1094 * Note: we could use containment here to 'derive' the driver-specific
1095 * texture object from the core mesa gl_texture_object. Not done at this time.
1096 * Fixup MaxAnisotropy according to user preference.
1098 static struct gl_texture_object
*r300NewTextureObject(GLcontext
* ctx
,
1102 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
1103 struct gl_texture_object
*obj
;
1104 obj
= _mesa_new_texture_object(ctx
, name
, target
);
1107 obj
->MaxAnisotropy
= rmesa
->initialMaxAnisotropy
;
1109 /* Attempt to fill LOD bias, if previously set.
1110 * Should start at 0.0, which won't affect the HW. */
1111 obj
->LodBias
= rmesa
->LODBias
;
1113 r300AllocTexObj(obj
);
1117 void r300InitTextureFuncs(struct dd_function_table
*functions
)
1119 /* Note: we only plug in the functions we implement in the driver
1120 * since _mesa_init_driver_functions() was already called.
1122 functions
->ChooseTextureFormat
= r300ChooseTextureFormat
;
1123 functions
->TexImage1D
= r300TexImage1D
;
1124 functions
->TexImage2D
= r300TexImage2D
;
1125 functions
->TexImage3D
= r300TexImage3D
;
1126 functions
->TexSubImage1D
= r300TexSubImage1D
;
1127 functions
->TexSubImage2D
= r300TexSubImage2D
;
1128 functions
->TexSubImage3D
= r300TexSubImage3D
;
1129 functions
->NewTextureObject
= r300NewTextureObject
;
1130 functions
->BindTexture
= r300BindTexture
;
1131 functions
->DeleteTexture
= r300DeleteTexture
;
1132 functions
->IsTextureResident
= driIsTextureResident
;
1134 functions
->TexEnv
= r300TexEnv
;
1135 functions
->TexParameter
= r300TexParameter
;
1137 functions
->CompressedTexImage2D
= r300CompressedTexImage2D
;
1138 functions
->CompressedTexSubImage2D
= r300CompressedTexSubImage2D
;
1140 driInitTextureFormats();