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 /* try to find a format which will only need a memcopy */
301 static const struct gl_texture_format
*r300Choose8888TexFormat( GLenum srcFormat
,
305 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
307 if ((srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8
) ||
308 (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
) ||
309 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) ||
310 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_BYTE
&& littleEndian
)) {
311 return &_mesa_texformat_rgba8888
;
313 else if ((srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) ||
314 (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
&& littleEndian
) ||
315 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_INT_8_8_8_8
) ||
316 (srcFormat
== GL_ABGR_EXT
&& srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
)) {
317 return &_mesa_texformat_rgba8888_rev
;
319 else if (srcFormat
== GL_BGRA
&&
320 ((srcType
== GL_UNSIGNED_BYTE
&& !littleEndian
) ||
321 srcType
== GL_UNSIGNED_INT_8_8_8_8
)) {
322 return &_mesa_texformat_argb8888_rev
;
324 else if (srcFormat
== GL_BGRA
&&
325 ((srcType
== GL_UNSIGNED_BYTE
&& littleEndian
) ||
326 srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
)) {
327 return &_mesa_texformat_argb8888
;
329 else return _dri_texformat_argb8888
;
332 static const struct gl_texture_format
*r300ChooseTextureFormat(GLcontext
* ctx
,
338 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
339 const GLboolean do32bpt
=
340 (rmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_32
);
341 const GLboolean force16bpt
=
342 (rmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_FORCE_16
);
346 fprintf(stderr
, "InternalFormat=%s(%d) type=%s format=%s\n",
347 _mesa_lookup_enum_by_nr(internalFormat
), internalFormat
,
348 _mesa_lookup_enum_by_nr(type
),
349 _mesa_lookup_enum_by_nr(format
));
350 fprintf(stderr
, "do32bpt=%d force16bpt=%d\n",
351 do32bpt
, force16bpt
);
354 switch (internalFormat
) {
357 case GL_COMPRESSED_RGBA
:
359 case GL_UNSIGNED_INT_10_10_10_2
:
360 case GL_UNSIGNED_INT_2_10_10_10_REV
:
361 return do32bpt
? _dri_texformat_argb8888
:
362 _dri_texformat_argb1555
;
363 case GL_UNSIGNED_SHORT_4_4_4_4
:
364 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
365 return _dri_texformat_argb4444
;
366 case GL_UNSIGNED_SHORT_5_5_5_1
:
367 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
368 return _dri_texformat_argb1555
;
370 return do32bpt
? r300Choose8888TexFormat(format
, type
) :
371 _dri_texformat_argb4444
;
376 case GL_COMPRESSED_RGB
:
378 case GL_UNSIGNED_SHORT_4_4_4_4
:
379 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
380 return _dri_texformat_argb4444
;
381 case GL_UNSIGNED_SHORT_5_5_5_1
:
382 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
383 return _dri_texformat_argb1555
;
384 case GL_UNSIGNED_SHORT_5_6_5
:
385 case GL_UNSIGNED_SHORT_5_6_5_REV
:
386 return _dri_texformat_rgb565
;
388 return do32bpt
? _dri_texformat_argb8888
:
389 _dri_texformat_rgb565
;
397 r300Choose8888TexFormat(format
, type
) : _dri_texformat_argb4444
;
401 return _dri_texformat_argb4444
;
404 return _dri_texformat_argb1555
;
410 return !force16bpt
? _dri_texformat_argb8888
:
411 _dri_texformat_rgb565
;
416 return _dri_texformat_rgb565
;
423 case GL_COMPRESSED_ALPHA
:
424 return _dri_texformat_a8
;
432 case GL_COMPRESSED_LUMINANCE
:
433 return _dri_texformat_l8
;
436 case GL_LUMINANCE_ALPHA
:
437 case GL_LUMINANCE4_ALPHA4
:
438 case GL_LUMINANCE6_ALPHA2
:
439 case GL_LUMINANCE8_ALPHA8
:
440 case GL_LUMINANCE12_ALPHA4
:
441 case GL_LUMINANCE12_ALPHA12
:
442 case GL_LUMINANCE16_ALPHA16
:
443 case GL_COMPRESSED_LUMINANCE_ALPHA
:
444 return _dri_texformat_al88
;
451 case GL_COMPRESSED_INTENSITY
:
452 return _dri_texformat_i8
;
455 if (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
456 type
== GL_UNSIGNED_BYTE
)
457 return &_mesa_texformat_ycbcr
;
459 return &_mesa_texformat_ycbcr_rev
;
463 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
464 return &_mesa_texformat_rgb_dxt1
;
466 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
467 return &_mesa_texformat_rgba_dxt1
;
471 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
472 return &_mesa_texformat_rgba_dxt3
;
474 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
475 return &_mesa_texformat_rgba_dxt5
;
477 case GL_ALPHA16F_ARB
:
478 return &_mesa_texformat_alpha_float16
;
479 case GL_ALPHA32F_ARB
:
480 return &_mesa_texformat_alpha_float32
;
481 case GL_LUMINANCE16F_ARB
:
482 return &_mesa_texformat_luminance_float16
;
483 case GL_LUMINANCE32F_ARB
:
484 return &_mesa_texformat_luminance_float32
;
485 case GL_LUMINANCE_ALPHA16F_ARB
:
486 return &_mesa_texformat_luminance_alpha_float16
;
487 case GL_LUMINANCE_ALPHA32F_ARB
:
488 return &_mesa_texformat_luminance_alpha_float32
;
489 case GL_INTENSITY16F_ARB
:
490 return &_mesa_texformat_intensity_float16
;
491 case GL_INTENSITY32F_ARB
:
492 return &_mesa_texformat_intensity_float32
;
494 return &_mesa_texformat_rgba_float16
;
496 return &_mesa_texformat_rgba_float32
;
498 return &_mesa_texformat_rgba_float16
;
500 return &_mesa_texformat_rgba_float32
;
504 "unexpected internalFormat 0x%x in r300ChooseTextureFormat",
505 (int)internalFormat
);
509 return NULL
; /* never get here */
513 r300ValidateClientStorage(GLcontext
* ctx
, GLenum target
,
514 GLint internalFormat
,
515 GLint srcWidth
, GLint srcHeight
,
516 GLenum format
, GLenum type
, const void *pixels
,
517 const struct gl_pixelstore_attrib
*packing
,
518 struct gl_texture_object
*texObj
,
519 struct gl_texture_image
*texImage
)
521 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
524 fprintf(stderr
, "intformat %s format %s type %s\n",
525 _mesa_lookup_enum_by_nr(internalFormat
),
526 _mesa_lookup_enum_by_nr(format
),
527 _mesa_lookup_enum_by_nr(type
));
529 if (!ctx
->Unpack
.ClientStorage
)
532 if (ctx
->_ImageTransferState
||
533 texImage
->IsCompressed
|| texObj
->GenerateMipmap
)
536 /* This list is incomplete, may be different on ppc???
538 switch (internalFormat
) {
540 if (format
== GL_BGRA
&& type
== GL_UNSIGNED_INT_8_8_8_8_REV
) {
541 texImage
->TexFormat
= _dri_texformat_argb8888
;
547 if (format
== GL_RGB
&& type
== GL_UNSIGNED_SHORT_5_6_5
) {
548 texImage
->TexFormat
= _dri_texformat_rgb565
;
554 if (format
== GL_YCBCR_MESA
&&
555 type
== GL_UNSIGNED_SHORT_8_8_REV_APPLE
) {
556 texImage
->TexFormat
= &_mesa_texformat_ycbcr_rev
;
557 } else if (format
== GL_YCBCR_MESA
&&
558 (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
559 type
== GL_UNSIGNED_BYTE
)) {
560 texImage
->TexFormat
= &_mesa_texformat_ycbcr
;
569 /* Could deal with these packing issues, but currently don't:
571 if (packing
->SkipPixels
||
572 packing
->SkipRows
|| packing
->SwapBytes
|| packing
->LsbFirst
) {
577 GLint srcRowStride
= _mesa_image_row_stride(packing
, srcWidth
,
581 fprintf(stderr
, "%s: srcRowStride %d/%x\n",
582 __FUNCTION__
, srcRowStride
, srcRowStride
);
584 /* Could check this later in upload, pitch restrictions could be
585 * relaxed, but would need to store the image pitch somewhere,
586 * as packing details might change before image is uploaded:
588 if (!r300IsGartMemory(rmesa
, pixels
, srcHeight
* srcRowStride
)
589 || (srcRowStride
& 63))
592 /* Have validated that _mesa_transfer_teximage would be a straight
593 * memcpy at this point. NOTE: future calls to TexSubImage will
594 * overwrite the client data. This is explicitly mentioned in the
597 texImage
->Data
= (void *)pixels
;
598 texImage
->IsClientData
= GL_TRUE
;
599 texImage
->RowStride
=
600 srcRowStride
/ texImage
->TexFormat
->TexelBytes
;
606 static void r300TexImage1D(GLcontext
* ctx
, GLenum target
, GLint level
,
607 GLint internalFormat
,
608 GLint width
, 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 driSwapOutTextureObject(t
);
619 t
= (driTextureObject
*) r300AllocTexObj(texObj
);
621 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
626 /* Note, this will call ChooseTextureFormat */
627 _mesa_store_teximage1d(ctx
, target
, level
, internalFormat
,
628 width
, border
, format
, type
, pixels
,
629 &ctx
->Unpack
, texObj
, texImage
);
631 t
->dirty_images
[0] |= (1 << level
);
634 static void r300TexSubImage1D(GLcontext
* ctx
, GLenum target
, GLint level
,
637 GLenum format
, GLenum type
,
638 const GLvoid
* pixels
,
639 const struct gl_pixelstore_attrib
*packing
,
640 struct gl_texture_object
*texObj
,
641 struct gl_texture_image
*texImage
)
643 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
645 assert(t
); /* this _should_ be true */
647 driSwapOutTextureObject(t
);
649 t
= (driTextureObject
*) r300AllocTexObj(texObj
);
651 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
656 _mesa_store_texsubimage1d(ctx
, target
, level
, xoffset
, width
,
657 format
, type
, pixels
, packing
, texObj
,
660 t
->dirty_images
[0] |= (1 << level
);
663 static void r300TexImage2D(GLcontext
* ctx
, GLenum target
, GLint level
,
664 GLint internalFormat
,
665 GLint width
, GLint height
, GLint border
,
666 GLenum format
, GLenum type
, const GLvoid
* pixels
,
667 const struct gl_pixelstore_attrib
*packing
,
668 struct gl_texture_object
*texObj
,
669 struct gl_texture_image
*texImage
)
671 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
674 /* which cube face or ordinary 2D image */
676 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
677 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
678 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
679 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
680 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
681 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
683 (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
691 driSwapOutTextureObject(t
);
693 t
= (driTextureObject
*) r300AllocTexObj(texObj
);
695 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
700 texImage
->IsClientData
= GL_FALSE
;
702 if (r300ValidateClientStorage(ctx
, target
,
705 format
, type
, pixels
,
706 packing
, texObj
, texImage
)) {
707 if (RADEON_DEBUG
& DEBUG_TEXTURE
)
708 fprintf(stderr
, "%s: Using client storage\n",
711 if (RADEON_DEBUG
& DEBUG_TEXTURE
)
712 fprintf(stderr
, "%s: Using normal storage\n",
715 /* Normal path: copy (to cached memory) and eventually upload
716 * via another copy to GART memory and then a blit... Could
717 * eliminate one copy by going straight to (permanent) GART.
719 * Note, this will call r300ChooseTextureFormat.
721 _mesa_store_teximage2d(ctx
, target
, level
, internalFormat
,
722 width
, height
, border
, format
, type
,
723 pixels
, &ctx
->Unpack
, texObj
, texImage
);
725 t
->dirty_images
[face
] |= (1 << level
);
729 static void r300TexSubImage2D(GLcontext
* ctx
, GLenum target
, GLint level
,
730 GLint xoffset
, GLint yoffset
,
731 GLsizei width
, GLsizei height
,
732 GLenum format
, GLenum type
,
733 const GLvoid
* pixels
,
734 const struct gl_pixelstore_attrib
*packing
,
735 struct gl_texture_object
*texObj
,
736 struct gl_texture_image
*texImage
)
738 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
741 /* which cube face or ordinary 2D image */
743 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
744 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
745 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
746 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
747 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
748 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
750 (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
757 assert(t
); /* this _should_ be true */
759 driSwapOutTextureObject(t
);
761 t
= (driTextureObject
*) r300AllocTexObj(texObj
);
763 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
768 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
769 height
, format
, type
, pixels
, packing
, texObj
,
772 t
->dirty_images
[face
] |= (1 << level
);
775 static void r300CompressedTexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
776 GLint internalFormat
,
777 GLint width
, GLint height
, GLint border
,
778 GLsizei imageSize
, const GLvoid
*data
,
779 struct gl_texture_object
*texObj
,
780 struct gl_texture_image
*texImage
)
782 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
785 /* which cube face or ordinary 2D image */
787 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
788 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
789 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
790 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
791 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
792 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
793 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
801 driSwapOutTextureObject( t
);
804 t
= (driTextureObject
*) r300AllocTexObj( texObj
);
806 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2D");
811 texImage
->IsClientData
= GL_FALSE
;
812 /* can't call this, different parameters. Would never evaluate to true anyway currently
813 if (r300ValidateClientStorage( ctx, target,
816 format, type, pixels,
817 packing, texObj, texImage)) {
818 if (RADEON_DEBUG & DEBUG_TEXTURE)
819 fprintf(stderr, "%s: Using client storage\n", __FUNCTION__);
822 if (RADEON_DEBUG
& DEBUG_TEXTURE
)
823 fprintf(stderr
, "%s: Using normal storage\n", __FUNCTION__
);
825 /* Normal path: copy (to cached memory) and eventually upload
826 * via another copy to GART memory and then a blit... Could
827 * eliminate one copy by going straight to (permanent) GART.
829 * Note, this will call r300ChooseTextureFormat.
831 _mesa_store_compressed_teximage2d(ctx
, target
, level
, internalFormat
, width
,
832 height
, border
, imageSize
, data
, texObj
, texImage
);
834 t
->dirty_images
[face
] |= (1 << level
);
839 static void r300CompressedTexSubImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
840 GLint xoffset
, GLint yoffset
,
841 GLsizei width
, GLsizei height
,
843 GLsizei imageSize
, const GLvoid
*data
,
844 struct gl_texture_object
*texObj
,
845 struct gl_texture_image
*texImage
)
847 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
851 /* which cube face or ordinary 2D image */
853 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
854 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
855 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
856 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
857 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
858 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
859 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
866 assert( t
); /* this _should_ be true */
868 driSwapOutTextureObject( t
);
871 t
= (driTextureObject
*) r300AllocTexObj( texObj
);
873 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexSubImage3D");
878 _mesa_store_compressed_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
879 height
, format
, imageSize
, data
, texObj
, texImage
);
881 t
->dirty_images
[face
] |= (1 << level
);
884 #if ENABLE_HW_3D_TEXTURE
885 static void r300TexImage3D(GLcontext
* ctx
, GLenum target
, GLint level
,
886 GLint internalFormat
,
887 GLint width
, GLint height
, GLint depth
,
889 GLenum format
, GLenum type
, 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
;
897 driSwapOutTextureObject(t
);
899 t
= (driTextureObject
*) r300AllocTexObj(texObj
);
901 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
906 texImage
->IsClientData
= GL_FALSE
;
909 if (r300ValidateClientStorage(ctx
, target
,
912 format
, type
, pixels
,
913 packing
, texObj
, texImage
)) {
914 if (RADEON_DEBUG
& DEBUG_TEXTURE
)
915 fprintf(stderr
, "%s: Using client storage\n",
920 if (RADEON_DEBUG
& DEBUG_TEXTURE
)
921 fprintf(stderr
, "%s: Using normal storage\n",
924 /* Normal path: copy (to cached memory) and eventually upload
925 * via another copy to GART memory and then a blit... Could
926 * eliminate one copy by going straight to (permanent) GART.
928 * Note, this will call r300ChooseTextureFormat.
930 _mesa_store_teximage3d(ctx
, target
, level
, internalFormat
,
931 width
, height
, depth
, border
,
932 format
, type
, pixels
,
933 &ctx
->Unpack
, texObj
, texImage
);
935 t
->dirty_images
[0] |= (1 << level
);
940 #if ENABLE_HW_3D_TEXTURE
942 r300TexSubImage3D(GLcontext
* ctx
, GLenum target
, GLint level
,
943 GLint xoffset
, GLint yoffset
, GLint zoffset
,
944 GLsizei width
, GLsizei height
, GLsizei depth
,
945 GLenum format
, GLenum type
,
946 const GLvoid
* pixels
,
947 const struct gl_pixelstore_attrib
*packing
,
948 struct gl_texture_object
*texObj
,
949 struct gl_texture_image
*texImage
)
951 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
953 /* fprintf(stderr, "%s\n", __FUNCTION__); */
955 assert(t
); /* this _should_ be true */
957 driSwapOutTextureObject(t
);
959 t
= (driTextureObject
*) r300AllocTexObj(texObj
);
961 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage3D");
964 texObj
->DriverData
= t
;
967 _mesa_store_texsubimage3d(ctx
, target
, level
, xoffset
, yoffset
, zoffset
,
968 width
, height
, depth
,
969 format
, type
, pixels
, packing
, texObj
,
972 t
->dirty_images
[0] |= (1 << level
);
976 static void r300TexEnv(GLcontext
* ctx
, GLenum target
,
977 GLenum pname
, const GLfloat
* param
)
979 if (RADEON_DEBUG
& DEBUG_STATE
) {
980 fprintf(stderr
, "%s( %s )\n",
981 __FUNCTION__
, _mesa_lookup_enum_by_nr(pname
));
984 /* This is incorrect: Need to maintain this data for each of
985 * GL_TEXTURE_{123}D, GL_TEXTURE_RECTANGLE_NV, etc, and switch
986 * between them according to _ReallyEnabled.
989 case GL_TEXTURE_LOD_BIAS_EXT
:{
990 #if 0 /* Needs to be relocated in order to make sure we got the right tmu */
994 /* The R300's LOD bias is a signed 2's complement value with a
995 * range of -16.0 <= bias < 16.0.
997 * NOTE: Add a small bias to the bias for conform mipsel.c test.
1001 driQueryOptionb(&rmesa
->radeon
.optionCache
,
1002 "no_neg_lod_bias") ? 0.0 : -16.0;
1003 bias
= CLAMP(bias
, min
, 16.0);
1005 /* 0.0 - 16.0 == 0x0 - 0x1000 */
1006 /* 0.0 - -16.0 == 0x1001 - 0x1fff */
1007 b
= 0x1000 / 16.0 * bias
;
1008 b
&= R300_LOD_BIAS_MASK
;
1010 if(b
!= (rmesa
->hw
.tex
.unknown1
.cmd
[R300_TEX_VALUE_0
+unit
] & R300_LOD_BIAS_MASK
)){
1011 R300_STATECHANGE(rmesa
, tex
.unknown1
);
1012 rmesa
->hw
.tex
.unknown1
.cmd
[R300_TEX_VALUE_0
+unit
] &= ~R300_LOD_BIAS_MASK
;
1013 rmesa
->hw
.tex
.unknown1
.cmd
[R300_TEX_VALUE_0
+unit
] |= b
;
1025 * Changes variables and flags for a state update, which will happen at the
1026 * next UpdateTextureState
1029 static void r300TexParameter(GLcontext
* ctx
, GLenum target
,
1030 struct gl_texture_object
*texObj
,
1031 GLenum pname
, const GLfloat
* params
)
1033 r300TexObjPtr t
= (r300TexObjPtr
) texObj
->DriverData
;
1035 if (RADEON_DEBUG
& (DEBUG_STATE
| DEBUG_TEXTURE
)) {
1036 fprintf(stderr
, "%s( %s )\n", __FUNCTION__
,
1037 _mesa_lookup_enum_by_nr(pname
));
1041 case GL_TEXTURE_MIN_FILTER
:
1042 case GL_TEXTURE_MAG_FILTER
:
1043 case GL_TEXTURE_MAX_ANISOTROPY_EXT
:
1044 r300SetTexMaxAnisotropy(t
, texObj
->MaxAnisotropy
);
1045 r300SetTexFilter(t
, texObj
->MinFilter
, texObj
->MagFilter
);
1048 case GL_TEXTURE_WRAP_S
:
1049 case GL_TEXTURE_WRAP_T
:
1050 case GL_TEXTURE_WRAP_R
:
1051 r300SetTexWrap(t
, texObj
->WrapS
, texObj
->WrapT
, texObj
->WrapR
);
1054 case GL_TEXTURE_BORDER_COLOR
:
1055 r300SetTexBorderColor(t
, texObj
->_BorderChan
);
1058 case GL_TEXTURE_BASE_LEVEL
:
1059 case GL_TEXTURE_MAX_LEVEL
:
1060 case GL_TEXTURE_MIN_LOD
:
1061 case GL_TEXTURE_MAX_LOD
:
1062 /* This isn't the most efficient solution but there doesn't appear to
1063 * be a nice alternative. Since there's no LOD clamping,
1064 * we just have to rely on loading the right subset of mipmap levels
1065 * to simulate a clamped LOD.
1067 driSwapOutTextureObject((driTextureObject
*) t
);
1074 /* Mark this texobj as dirty (one bit per tex unit)
1076 t
->dirty_state
= TEX_ALL
;
1079 static void r300BindTexture(GLcontext
* ctx
, GLenum target
,
1080 struct gl_texture_object
*texObj
)
1082 if (RADEON_DEBUG
& (DEBUG_STATE
| DEBUG_TEXTURE
)) {
1083 fprintf(stderr
, "%s( %p ) unit=%d\n", __FUNCTION__
,
1084 (void *)texObj
, ctx
->Texture
.CurrentUnit
);
1087 if ((target
== GL_TEXTURE_1D
)
1088 || (target
== GL_TEXTURE_2D
)
1089 #if ENABLE_HW_3D_TEXTURE
1090 || (target
== GL_TEXTURE_3D
)
1092 || (target
== GL_TEXTURE_CUBE_MAP
)
1093 || (target
== GL_TEXTURE_RECTANGLE_NV
)) {
1094 assert(texObj
->DriverData
!= NULL
);
1098 static void r300DeleteTexture(GLcontext
* ctx
, struct gl_texture_object
*texObj
)
1100 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
1101 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
1103 if (RADEON_DEBUG
& (DEBUG_STATE
| DEBUG_TEXTURE
)) {
1104 fprintf(stderr
, "%s( %p (target = %s) )\n", __FUNCTION__
,
1106 _mesa_lookup_enum_by_nr(texObj
->Target
));
1111 R300_FIREVERTICES(rmesa
);
1114 driDestroyTextureObject(t
);
1116 /* Free mipmap images and the texture object itself */
1117 _mesa_delete_texture_object(ctx
, texObj
);
1121 * Allocate a new texture object.
1122 * Called via ctx->Driver.NewTextureObject.
1123 * Note: this function will be called during context creation to
1124 * allocate the default texture objects.
1125 * Note: we could use containment here to 'derive' the driver-specific
1126 * texture object from the core mesa gl_texture_object. Not done at this time.
1127 * Fixup MaxAnisotropy according to user preference.
1129 static struct gl_texture_object
*r300NewTextureObject(GLcontext
* ctx
,
1133 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
1134 struct gl_texture_object
*obj
;
1135 obj
= _mesa_new_texture_object(ctx
, name
, target
);
1138 obj
->MaxAnisotropy
= rmesa
->initialMaxAnisotropy
;
1140 r300AllocTexObj(obj
);
1145 void r300InitTextureFuncs(struct dd_function_table
*functions
)
1147 /* Note: we only plug in the functions we implement in the driver
1148 * since _mesa_init_driver_functions() was already called.
1150 functions
->ChooseTextureFormat
= r300ChooseTextureFormat
;
1151 functions
->TexImage1D
= r300TexImage1D
;
1152 functions
->TexImage2D
= r300TexImage2D
;
1153 #if ENABLE_HW_3D_TEXTURE
1154 functions
->TexImage3D
= r300TexImage3D
;
1156 functions
->TexImage3D
= _mesa_store_teximage3d
;
1158 functions
->TexSubImage1D
= r300TexSubImage1D
;
1159 functions
->TexSubImage2D
= r300TexSubImage2D
;
1160 #if ENABLE_HW_3D_TEXTURE
1161 functions
->TexSubImage3D
= r300TexSubImage3D
;
1163 functions
->TexSubImage3D
= _mesa_store_texsubimage3d
;
1165 functions
->NewTextureObject
= r300NewTextureObject
;
1166 functions
->BindTexture
= r300BindTexture
;
1167 functions
->DeleteTexture
= r300DeleteTexture
;
1168 functions
->IsTextureResident
= driIsTextureResident
;
1170 functions
->TexEnv
= r300TexEnv
;
1171 functions
->TexParameter
= r300TexParameter
;
1173 functions
->CompressedTexImage2D
= r300CompressedTexImage2D
;
1174 functions
->CompressedTexSubImage2D
= r300CompressedTexSubImage2D
;
1176 driInitTextureFormats();
1179 /* moved or obsolete code */
1180 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
1181 driInitTextureObjects(ctx
, &rmesa
->swapped
,
1182 DRI_TEXMGR_DO_TEXTURE_1D
1183 | DRI_TEXMGR_DO_TEXTURE_2D
);
1185 /* Hack: r300NewTextureObject is not yet installed when the
1186 * default textures are created. Therefore set MaxAnisotropy of the
1187 * default 2D texture now. */
1188 ctx
->Shared
->Default2D
->MaxAnisotropy
=
1189 driQueryOptionf(&rmesa
->optionCache
, "def_max_anisotropy");