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 GLboolean is_clamp_to_border
= GL_FALSE
;
71 ~(R200_CLAMP_S_MASK
| R200_CLAMP_T_MASK
| R200_BORDER_MODE_D3D
);
75 t
->filter
|= R200_CLAMP_S_WRAP
;
78 t
->filter
|= R200_CLAMP_S_CLAMP_GL
;
81 case GL_CLAMP_TO_EDGE
:
82 t
->filter
|= R200_CLAMP_S_CLAMP_LAST
;
84 case GL_CLAMP_TO_BORDER
:
85 t
->filter
|= R200_CLAMP_S_CLAMP_GL
;
86 is_clamp_to_border
= GL_TRUE
;
88 case GL_MIRRORED_REPEAT
:
89 t
->filter
|= R200_CLAMP_S_MIRROR
;
91 case GL_MIRROR_CLAMP_EXT
:
92 t
->filter
|= R200_CLAMP_S_MIRROR_CLAMP_GL
;
95 case GL_MIRROR_CLAMP_TO_EDGE_EXT
:
96 t
->filter
|= R200_CLAMP_S_MIRROR_CLAMP_LAST
;
98 case GL_MIRROR_CLAMP_TO_BORDER_EXT
:
99 t
->filter
|= R200_CLAMP_S_MIRROR_CLAMP_GL
;
100 is_clamp_to_border
= GL_TRUE
;
103 _mesa_problem(NULL
, "bad S wrap mode in %s", __FUNCTION__
);
108 t
->filter
|= R200_CLAMP_T_WRAP
;
111 t
->filter
|= R200_CLAMP_T_CLAMP_GL
;
114 case GL_CLAMP_TO_EDGE
:
115 t
->filter
|= R200_CLAMP_T_CLAMP_LAST
;
117 case GL_CLAMP_TO_BORDER
:
118 t
->filter
|= R200_CLAMP_T_CLAMP_GL
| R200_BORDER_MODE_D3D
;
119 is_clamp_to_border
= GL_TRUE
;
121 case GL_MIRRORED_REPEAT
:
122 t
->filter
|= R200_CLAMP_T_MIRROR
;
124 case GL_MIRROR_CLAMP_EXT
:
125 t
->filter
|= R200_CLAMP_T_MIRROR_CLAMP_GL
;
128 case GL_MIRROR_CLAMP_TO_EDGE_EXT
:
129 t
->filter
|= R200_CLAMP_T_MIRROR_CLAMP_LAST
;
131 case GL_MIRROR_CLAMP_TO_BORDER_EXT
:
132 t
->filter
|= R200_CLAMP_T_MIRROR_CLAMP_GL
;
133 is_clamp_to_border
= GL_TRUE
;
136 _mesa_problem(NULL
, "bad T wrap mode in %s", __FUNCTION__
);
139 t
->format_x
&= ~R200_CLAMP_Q_MASK
;
143 t
->format_x
|= R200_CLAMP_Q_WRAP
;
146 t
->format_x
|= R200_CLAMP_Q_CLAMP_GL
;
149 case GL_CLAMP_TO_EDGE
:
150 t
->format_x
|= R200_CLAMP_Q_CLAMP_LAST
;
152 case GL_CLAMP_TO_BORDER
:
153 t
->format_x
|= R200_CLAMP_Q_CLAMP_GL
;
154 is_clamp_to_border
= GL_TRUE
;
156 case GL_MIRRORED_REPEAT
:
157 t
->format_x
|= R200_CLAMP_Q_MIRROR
;
159 case GL_MIRROR_CLAMP_EXT
:
160 t
->format_x
|= R200_CLAMP_Q_MIRROR_CLAMP_GL
;
163 case GL_MIRROR_CLAMP_TO_EDGE_EXT
:
164 t
->format_x
|= R200_CLAMP_Q_MIRROR_CLAMP_LAST
;
166 case GL_MIRROR_CLAMP_TO_BORDER_EXT
:
167 t
->format_x
|= R200_CLAMP_Q_MIRROR_CLAMP_GL
;
168 is_clamp_to_border
= GL_TRUE
;
171 _mesa_problem(NULL
, "bad R wrap mode in %s", __FUNCTION__
);
174 if (is_clamp_to_border
) {
175 t
->filter
|= R200_BORDER_MODE_D3D
;
178 t
->border_fallback
= (is_clamp
&& is_clamp_to_border
);
181 static void r300SetTexMaxAnisotropy(r300TexObjPtr t
, GLfloat max
)
183 t
->filter
&= ~R200_MAX_ANISO_MASK
;
186 t
->filter
|= R200_MAX_ANISO_1_TO_1
;
187 } else if (max
<= 2.0) {
188 t
->filter
|= R200_MAX_ANISO_2_TO_1
;
189 } else if (max
<= 4.0) {
190 t
->filter
|= R200_MAX_ANISO_4_TO_1
;
191 } else if (max
<= 8.0) {
192 t
->filter
|= R200_MAX_ANISO_8_TO_1
;
194 t
->filter
|= R200_MAX_ANISO_16_TO_1
;
199 * Set the texture magnification and minification modes.
201 * \param t Texture whose filter modes are to be set
202 * \param minf Texture minification mode
203 * \param magf Texture magnification mode
206 static void r300SetTexFilter(r300TexObjPtr t
, GLenum minf
, GLenum magf
)
208 GLuint anisotropy
= (t
->filter
& R200_MAX_ANISO_MASK
);
210 t
->filter
&= ~(R200_MIN_FILTER_MASK
| R200_MAG_FILTER_MASK
);
211 t
->format_x
&= ~R200_VOLUME_FILTER_MASK
;
213 if (anisotropy
== R200_MAX_ANISO_1_TO_1
) {
216 t
->filter
|= R200_MIN_FILTER_NEAREST
;
219 t
->filter
|= R200_MIN_FILTER_LINEAR
;
221 case GL_NEAREST_MIPMAP_NEAREST
:
222 t
->filter
|= R200_MIN_FILTER_NEAREST_MIP_NEAREST
;
224 case GL_NEAREST_MIPMAP_LINEAR
:
225 t
->filter
|= R200_MIN_FILTER_LINEAR_MIP_NEAREST
;
227 case GL_LINEAR_MIPMAP_NEAREST
:
228 t
->filter
|= R200_MIN_FILTER_NEAREST_MIP_LINEAR
;
230 case GL_LINEAR_MIPMAP_LINEAR
:
231 t
->filter
|= R200_MIN_FILTER_LINEAR_MIP_LINEAR
;
237 t
->filter
|= R200_MIN_FILTER_ANISO_NEAREST
;
240 t
->filter
|= R200_MIN_FILTER_ANISO_LINEAR
;
242 case GL_NEAREST_MIPMAP_NEAREST
:
243 case GL_LINEAR_MIPMAP_NEAREST
:
245 R200_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST
;
247 case GL_NEAREST_MIPMAP_LINEAR
:
248 case GL_LINEAR_MIPMAP_LINEAR
:
250 R200_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR
;
255 /* Note we don't have 3D mipmaps so only use the mag filter setting
256 * to set the 3D texture filter mode.
260 t
->filter
|= R200_MAG_FILTER_NEAREST
;
261 t
->format_x
|= R200_VOLUME_FILTER_NEAREST
;
264 t
->filter
|= R200_MAG_FILTER_LINEAR
;
265 t
->format_x
|= R200_VOLUME_FILTER_LINEAR
;
270 static void r300SetTexBorderColor(r300TexObjPtr t
, GLubyte c
[4])
272 t
->pp_border_color
= radeonPackColor(4, c
[0], c
[1], c
[2], c
[3]);
276 * Allocate space for and load the mesa images into the texture memory block.
277 * This will happen before drawing with a new texture, or drawing with a
278 * texture after it was swapped out or teximaged again.
281 static r300TexObjPtr
r300AllocTexObj(struct gl_texture_object
*texObj
)
285 t
= CALLOC_STRUCT(r300_tex_obj
);
286 texObj
->DriverData
= t
;
288 if (RADEON_DEBUG
& DEBUG_TEXTURE
) {
289 fprintf(stderr
, "%s( %p, %p )\n", __FUNCTION__
,
290 (void *)texObj
, (void *)t
);
293 /* Initialize non-image-dependent parts of the state:
295 t
->base
.tObj
= texObj
;
296 t
->border_fallback
= GL_FALSE
;
298 make_empty_list(&t
->base
);
300 r300SetTexWrap(t
, texObj
->WrapS
, texObj
->WrapT
, texObj
->WrapR
);
301 r300SetTexMaxAnisotropy(t
, texObj
->MaxAnisotropy
);
302 r300SetTexFilter(t
, texObj
->MinFilter
, texObj
->MagFilter
);
303 r300SetTexBorderColor(t
, texObj
->_BorderChan
);
309 static const struct gl_texture_format
*r300ChooseTextureFormat(GLcontext
* ctx
,
315 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
316 const GLboolean do32bpt
=
317 (rmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_32
);
318 const GLboolean force16bpt
=
319 (rmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_FORCE_16
);
322 switch (internalFormat
) {
325 case GL_COMPRESSED_RGBA
:
327 case GL_UNSIGNED_INT_10_10_10_2
:
328 case GL_UNSIGNED_INT_2_10_10_10_REV
:
329 return do32bpt
? _dri_texformat_argb8888
:
330 _dri_texformat_argb1555
;
331 case GL_UNSIGNED_SHORT_4_4_4_4
:
332 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
333 return _dri_texformat_argb4444
;
334 case GL_UNSIGNED_SHORT_5_5_5_1
:
335 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
336 return _dri_texformat_argb1555
;
338 return do32bpt
? _dri_texformat_rgba8888
:
339 _dri_texformat_argb4444
;
344 case GL_COMPRESSED_RGB
:
346 case GL_UNSIGNED_SHORT_4_4_4_4
:
347 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
348 return _dri_texformat_argb4444
;
349 case GL_UNSIGNED_SHORT_5_5_5_1
:
350 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
351 return _dri_texformat_argb1555
;
352 case GL_UNSIGNED_SHORT_5_6_5
:
353 case GL_UNSIGNED_SHORT_5_6_5_REV
:
354 return _dri_texformat_rgb565
;
356 return do32bpt
? _dri_texformat_rgba8888
:
357 _dri_texformat_rgb565
;
365 _dri_texformat_rgba8888
: _dri_texformat_argb4444
;
369 return _dri_texformat_argb4444
;
372 return _dri_texformat_argb1555
;
378 return !force16bpt
? _dri_texformat_rgba8888
:
379 _dri_texformat_rgb565
;
384 return _dri_texformat_rgb565
;
391 case GL_COMPRESSED_ALPHA
:
392 return _dri_texformat_a8
;
400 case GL_COMPRESSED_LUMINANCE
:
401 return _dri_texformat_l8
;
404 case GL_LUMINANCE_ALPHA
:
405 case GL_LUMINANCE4_ALPHA4
:
406 case GL_LUMINANCE6_ALPHA2
:
407 case GL_LUMINANCE8_ALPHA8
:
408 case GL_LUMINANCE12_ALPHA4
:
409 case GL_LUMINANCE12_ALPHA12
:
410 case GL_LUMINANCE16_ALPHA16
:
411 case GL_COMPRESSED_LUMINANCE_ALPHA
:
412 return _dri_texformat_al88
;
419 case GL_COMPRESSED_INTENSITY
:
420 return _dri_texformat_i8
;
423 if (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
424 type
== GL_UNSIGNED_BYTE
)
425 return &_mesa_texformat_ycbcr
;
427 return &_mesa_texformat_ycbcr_rev
;
431 "unexpected internalFormat 0x%x in r300ChooseTextureFormat",
432 (int)internalFormat
);
436 return NULL
; /* never get here */
440 r300ValidateClientStorage(GLcontext
* ctx
, GLenum target
,
441 GLint internalFormat
,
442 GLint srcWidth
, GLint srcHeight
,
443 GLenum format
, GLenum type
, const void *pixels
,
444 const struct gl_pixelstore_attrib
*packing
,
445 struct gl_texture_object
*texObj
,
446 struct gl_texture_image
*texImage
)
448 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
451 fprintf(stderr
, "intformat %s format %s type %s\n",
452 _mesa_lookup_enum_by_nr(internalFormat
),
453 _mesa_lookup_enum_by_nr(format
),
454 _mesa_lookup_enum_by_nr(type
));
456 if (!ctx
->Unpack
.ClientStorage
)
459 if (ctx
->_ImageTransferState
||
460 texImage
->IsCompressed
|| texObj
->GenerateMipmap
)
463 /* This list is incomplete, may be different on ppc???
465 switch (internalFormat
) {
467 if (format
== GL_BGRA
&& type
== GL_UNSIGNED_INT_8_8_8_8_REV
) {
468 texImage
->TexFormat
= _dri_texformat_argb8888
;
474 if (format
== GL_RGB
&& type
== GL_UNSIGNED_SHORT_5_6_5
) {
475 texImage
->TexFormat
= _dri_texformat_rgb565
;
481 if (format
== GL_YCBCR_MESA
&&
482 type
== GL_UNSIGNED_SHORT_8_8_REV_APPLE
) {
483 texImage
->TexFormat
= &_mesa_texformat_ycbcr_rev
;
484 } else if (format
== GL_YCBCR_MESA
&&
485 (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
486 type
== GL_UNSIGNED_BYTE
)) {
487 texImage
->TexFormat
= &_mesa_texformat_ycbcr
;
496 /* Could deal with these packing issues, but currently don't:
498 if (packing
->SkipPixels
||
499 packing
->SkipRows
|| packing
->SwapBytes
|| packing
->LsbFirst
) {
504 GLint srcRowStride
= _mesa_image_row_stride(packing
, srcWidth
,
508 fprintf(stderr
, "%s: srcRowStride %d/%x\n",
509 __FUNCTION__
, srcRowStride
, srcRowStride
);
511 /* Could check this later in upload, pitch restrictions could be
512 * relaxed, but would need to store the image pitch somewhere,
513 * as packing details might change before image is uploaded:
515 if (!r300IsGartMemory(rmesa
, pixels
, srcHeight
* srcRowStride
)
516 || (srcRowStride
& 63))
519 /* Have validated that _mesa_transfer_teximage would be a straight
520 * memcpy at this point. NOTE: future calls to TexSubImage will
521 * overwrite the client data. This is explicitly mentioned in the
524 texImage
->Data
= (void *)pixels
;
525 texImage
->IsClientData
= GL_TRUE
;
526 texImage
->RowStride
=
527 srcRowStride
/ texImage
->TexFormat
->TexelBytes
;
533 static void r300TexImage1D(GLcontext
* ctx
, GLenum target
, GLint level
,
534 GLint internalFormat
,
535 GLint width
, GLint border
,
536 GLenum format
, GLenum type
, const GLvoid
* pixels
,
537 const struct gl_pixelstore_attrib
*packing
,
538 struct gl_texture_object
*texObj
,
539 struct gl_texture_image
*texImage
)
541 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
544 driSwapOutTextureObject(t
);
546 t
= (driTextureObject
*) r300AllocTexObj(texObj
);
548 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
553 /* Note, this will call ChooseTextureFormat */
554 _mesa_store_teximage1d(ctx
, target
, level
, internalFormat
,
555 width
, border
, format
, type
, pixels
,
556 &ctx
->Unpack
, texObj
, texImage
);
558 t
->dirty_images
[0] |= (1 << level
);
561 static void r300TexSubImage1D(GLcontext
* ctx
, GLenum target
, GLint level
,
564 GLenum format
, GLenum type
,
565 const GLvoid
* pixels
,
566 const struct gl_pixelstore_attrib
*packing
,
567 struct gl_texture_object
*texObj
,
568 struct gl_texture_image
*texImage
)
570 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
572 assert(t
); /* this _should_ be true */
574 driSwapOutTextureObject(t
);
576 t
= (driTextureObject
*) r300AllocTexObj(texObj
);
578 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
583 _mesa_store_texsubimage1d(ctx
, target
, level
, xoffset
, width
,
584 format
, type
, pixels
, packing
, texObj
,
587 t
->dirty_images
[0] |= (1 << level
);
590 static void r300TexImage2D(GLcontext
* ctx
, GLenum target
, GLint level
,
591 GLint internalFormat
,
592 GLint width
, GLint height
, GLint border
,
593 GLenum format
, GLenum type
, const GLvoid
* pixels
,
594 const struct gl_pixelstore_attrib
*packing
,
595 struct gl_texture_object
*texObj
,
596 struct gl_texture_image
*texImage
)
598 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
601 /* which cube face or ordinary 2D image */
603 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
604 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
605 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
606 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
607 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
608 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
610 (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
618 driSwapOutTextureObject(t
);
620 t
= (driTextureObject
*) r300AllocTexObj(texObj
);
622 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
627 texImage
->IsClientData
= GL_FALSE
;
629 if (r300ValidateClientStorage(ctx
, target
,
632 format
, type
, pixels
,
633 packing
, texObj
, texImage
)) {
634 if (RADEON_DEBUG
& DEBUG_TEXTURE
)
635 fprintf(stderr
, "%s: Using client storage\n",
638 if (RADEON_DEBUG
& DEBUG_TEXTURE
)
639 fprintf(stderr
, "%s: Using normal storage\n",
642 /* Normal path: copy (to cached memory) and eventually upload
643 * via another copy to GART memory and then a blit... Could
644 * eliminate one copy by going straight to (permanent) GART.
646 * Note, this will call r300ChooseTextureFormat.
648 _mesa_store_teximage2d(ctx
, target
, level
, internalFormat
,
649 width
, height
, border
, format
, type
,
650 pixels
, &ctx
->Unpack
, texObj
, texImage
);
652 t
->dirty_images
[face
] |= (1 << level
);
656 static void r300TexSubImage2D(GLcontext
* ctx
, GLenum target
, GLint level
,
657 GLint xoffset
, GLint yoffset
,
658 GLsizei width
, GLsizei height
,
659 GLenum format
, GLenum type
,
660 const GLvoid
* pixels
,
661 const struct gl_pixelstore_attrib
*packing
,
662 struct gl_texture_object
*texObj
,
663 struct gl_texture_image
*texImage
)
665 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
668 /* which cube face or ordinary 2D image */
670 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
671 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
672 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
673 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
674 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
675 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
677 (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
684 assert(t
); /* this _should_ be true */
686 driSwapOutTextureObject(t
);
688 t
= (driTextureObject
*) r300AllocTexObj(texObj
);
690 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
695 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
696 height
, format
, type
, pixels
, packing
, texObj
,
699 t
->dirty_images
[face
] |= (1 << level
);
702 #if ENABLE_HW_3D_TEXTURE
703 static void r300TexImage3D(GLcontext
* ctx
, GLenum target
, GLint level
,
704 GLint internalFormat
,
705 GLint width
, GLint height
, GLint depth
,
707 GLenum format
, GLenum type
, const GLvoid
* pixels
,
708 const struct gl_pixelstore_attrib
*packing
,
709 struct gl_texture_object
*texObj
,
710 struct gl_texture_image
*texImage
)
712 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
715 driSwapOutTextureObject(t
);
717 t
= (driTextureObject
*) r300AllocTexObj(texObj
);
719 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage3D");
724 texImage
->IsClientData
= GL_FALSE
;
727 if (r300ValidateClientStorage(ctx
, target
,
730 format
, type
, pixels
,
731 packing
, texObj
, texImage
)) {
732 if (RADEON_DEBUG
& DEBUG_TEXTURE
)
733 fprintf(stderr
, "%s: Using client storage\n",
738 if (RADEON_DEBUG
& DEBUG_TEXTURE
)
739 fprintf(stderr
, "%s: Using normal storage\n",
742 /* Normal path: copy (to cached memory) and eventually upload
743 * via another copy to GART memory and then a blit... Could
744 * eliminate one copy by going straight to (permanent) GART.
746 * Note, this will call r300ChooseTextureFormat.
748 _mesa_store_teximage3d(ctx
, target
, level
, internalFormat
,
749 width
, height
, depth
, border
,
750 format
, type
, pixels
,
751 &ctx
->Unpack
, texObj
, texImage
);
753 t
->dirty_images
[0] |= (1 << level
);
758 #if ENABLE_HW_3D_TEXTURE
760 r300TexSubImage3D(GLcontext
* ctx
, GLenum target
, GLint level
,
761 GLint xoffset
, GLint yoffset
, GLint zoffset
,
762 GLsizei width
, GLsizei height
, GLsizei depth
,
763 GLenum format
, GLenum type
,
764 const GLvoid
* pixels
,
765 const struct gl_pixelstore_attrib
*packing
,
766 struct gl_texture_object
*texObj
,
767 struct gl_texture_image
*texImage
)
769 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
771 /* fprintf(stderr, "%s\n", __FUNCTION__); */
773 assert(t
); /* this _should_ be true */
775 driSwapOutTextureObject(t
);
777 t
= (driTextureObject
*) r300AllocTexObj(texObj
);
779 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage3D");
782 texObj
->DriverData
= t
;
785 _mesa_store_texsubimage3d(ctx
, target
, level
, xoffset
, yoffset
, zoffset
,
786 width
, height
, depth
,
787 format
, type
, pixels
, packing
, texObj
,
790 t
->dirty_images
[0] |= (1 << level
);
794 static void r300TexEnv(GLcontext
* ctx
, GLenum target
,
795 GLenum pname
, const GLfloat
* param
)
797 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
798 GLuint unit
= ctx
->Texture
.CurrentUnit
;
799 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
801 if (RADEON_DEBUG
& DEBUG_STATE
) {
802 fprintf(stderr
, "%s( %s )\n",
803 __FUNCTION__
, _mesa_lookup_enum_by_nr(pname
));
806 fprintf(stderr
, "%s:%s I am broken - Fixme !\n", __FILE__
, __FUNCTION__
);
809 /* This is incorrect: Need to maintain this data for each of
810 * GL_TEXTURE_{123}D, GL_TEXTURE_RECTANGLE_NV, etc, and switch
811 * between them according to _ReallyEnabled.
814 case GL_TEXTURE_ENV_COLOR
:{
817 UNCLAMPED_FLOAT_TO_RGBA_CHAN(c
, texUnit
->EnvColor
);
818 envColor
= radeonPackColor(4, c
[0], c
[1], c
[2], c
[3]);
819 if (rmesa
->hw
.tf
.cmd
[TF_TFACTOR_0
+ unit
] != envColor
) {
820 R200_STATECHANGE(rmesa
, tf
);
821 rmesa
->hw
.tf
.cmd
[TF_TFACTOR_0
+ unit
] =
827 case GL_TEXTURE_LOD_BIAS_EXT
:{
830 const int fixed_one
= 0x8000000;
832 /* The R200's LOD bias is a signed 2's complement value with a
833 * range of -16.0 <= bias < 16.0.
835 * NOTE: Add a small bias to the bias for conform mipsel.c test.
839 driQueryOptionb(&rmesa
->radeon
.optionCache
,
840 "no_neg_lod_bias") ? 0.0 : -16.0;
841 bias
= CLAMP(bias
, min
, 16.0);
842 b
= (int)(bias
* fixed_one
) & R200_LOD_BIAS_MASK
;
844 if ((rmesa
->hw
.tex
[unit
].
845 cmd
[TEX_PP_TXFORMAT_X
] & R200_LOD_BIAS_MASK
) !=
847 R200_STATECHANGE(rmesa
, tex
[unit
]);
848 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT_X
] &=
850 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT_X
] |= b
;
862 * Changes variables and flags for a state update, which will happen at the
863 * next UpdateTextureState
866 static void r300TexParameter(GLcontext
* ctx
, GLenum target
,
867 struct gl_texture_object
*texObj
,
868 GLenum pname
, const GLfloat
* params
)
870 r300TexObjPtr t
= (r300TexObjPtr
) texObj
->DriverData
;
872 if (RADEON_DEBUG
& (DEBUG_STATE
| DEBUG_TEXTURE
)) {
873 fprintf(stderr
, "%s( %s )\n", __FUNCTION__
,
874 _mesa_lookup_enum_by_nr(pname
));
878 case GL_TEXTURE_MIN_FILTER
:
879 case GL_TEXTURE_MAG_FILTER
:
880 case GL_TEXTURE_MAX_ANISOTROPY_EXT
:
881 r300SetTexMaxAnisotropy(t
, texObj
->MaxAnisotropy
);
882 r300SetTexFilter(t
, texObj
->MinFilter
, texObj
->MagFilter
);
885 case GL_TEXTURE_WRAP_S
:
886 case GL_TEXTURE_WRAP_T
:
887 case GL_TEXTURE_WRAP_R
:
888 r300SetTexWrap(t
, texObj
->WrapS
, texObj
->WrapT
, texObj
->WrapR
);
891 case GL_TEXTURE_BORDER_COLOR
:
892 r300SetTexBorderColor(t
, texObj
->_BorderChan
);
895 case GL_TEXTURE_BASE_LEVEL
:
896 case GL_TEXTURE_MAX_LEVEL
:
897 case GL_TEXTURE_MIN_LOD
:
898 case GL_TEXTURE_MAX_LOD
:
899 /* This isn't the most efficient solution but there doesn't appear to
900 * be a nice alternative. Since there's no LOD clamping,
901 * we just have to rely on loading the right subset of mipmap levels
902 * to simulate a clamped LOD.
904 driSwapOutTextureObject((driTextureObject
*) t
);
911 /* Mark this texobj as dirty (one bit per tex unit)
913 t
->dirty_state
= TEX_ALL
;
916 static void r300BindTexture(GLcontext
* ctx
, GLenum target
,
917 struct gl_texture_object
*texObj
)
919 if (RADEON_DEBUG
& (DEBUG_STATE
| DEBUG_TEXTURE
)) {
920 fprintf(stderr
, "%s( %p ) unit=%d\n", __FUNCTION__
,
921 (void *)texObj
, ctx
->Texture
.CurrentUnit
);
924 if ((target
== GL_TEXTURE_1D
)
925 || (target
== GL_TEXTURE_2D
)
926 #if ENABLE_HW_3D_TEXTURE
927 || (target
== GL_TEXTURE_3D
)
929 || (target
== GL_TEXTURE_CUBE_MAP
)
930 || (target
== GL_TEXTURE_RECTANGLE_NV
)) {
931 assert(texObj
->DriverData
!= NULL
);
935 static void r300DeleteTexture(GLcontext
* ctx
, struct gl_texture_object
*texObj
)
937 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
938 driTextureObject
*t
= (driTextureObject
*) texObj
->DriverData
;
940 if (RADEON_DEBUG
& (DEBUG_STATE
| DEBUG_TEXTURE
)) {
941 fprintf(stderr
, "%s( %p (target = %s) )\n", __FUNCTION__
,
943 _mesa_lookup_enum_by_nr(texObj
->Target
));
948 R300_FIREVERTICES(rmesa
);
951 driDestroyTextureObject(t
);
953 /* Free mipmap images and the texture object itself */
954 _mesa_delete_texture_object(ctx
, texObj
);
958 * - Same GEN_MODE for all active bits
959 * - Same EyePlane/ObjPlane for all active bits when using Eye/Obj
960 * - STRQ presumably all supported (matrix means incoming R values
961 * can end up in STQ, this has implications for vertex support,
962 * presumably ok if maos is used, though?)
964 * Basically impossible to do this on the fly - just collect some
965 * basic info & do the checks from ValidateState().
967 static void r300TexGen(GLcontext
* ctx
,
968 GLenum coord
, GLenum pname
, const GLfloat
* params
)
970 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
971 GLuint unit
= ctx
->Texture
.CurrentUnit
;
972 #if 0 /* Disable this for now - looks like we will be recalculating everything
974 rmesa
->recheck_texgen
[unit
] = GL_TRUE
;
979 * Allocate a new texture object.
980 * Called via ctx->Driver.NewTextureObject.
981 * Note: this function will be called during context creation to
982 * allocate the default texture objects.
983 * Note: we could use containment here to 'derive' the driver-specific
984 * texture object from the core mesa gl_texture_object. Not done at this time.
985 * Fixup MaxAnisotropy according to user preference.
987 static struct gl_texture_object
*r300NewTextureObject(GLcontext
* ctx
,
991 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
992 struct gl_texture_object
*obj
;
993 obj
= _mesa_new_texture_object(ctx
, name
, target
);
996 obj
->MaxAnisotropy
= rmesa
->initialMaxAnisotropy
;
997 r300AllocTexObj(obj
);
1001 void r300InitTextureFuncs(struct dd_function_table
*functions
)
1003 /* Note: we only plug in the functions we implement in the driver
1004 * since _mesa_init_driver_functions() was already called.
1006 functions
->ChooseTextureFormat
= r300ChooseTextureFormat
;
1007 functions
->TexImage1D
= r300TexImage1D
;
1008 functions
->TexImage2D
= r300TexImage2D
;
1009 #if ENABLE_HW_3D_TEXTURE
1010 functions
->TexImage3D
= r300TexImage3D
;
1012 functions
->TexImage3D
= _mesa_store_teximage3d
;
1014 functions
->TexSubImage1D
= r300TexSubImage1D
;
1015 functions
->TexSubImage2D
= r300TexSubImage2D
;
1016 #if ENABLE_HW_3D_TEXTURE
1017 functions
->TexSubImage3D
= r300TexSubImage3D
;
1019 functions
->TexSubImage3D
= _mesa_store_texsubimage3d
;
1021 functions
->NewTextureObject
= r300NewTextureObject
;
1022 functions
->BindTexture
= r300BindTexture
;
1023 functions
->DeleteTexture
= r300DeleteTexture
;
1024 functions
->IsTextureResident
= driIsTextureResident
;
1026 functions
->TexEnv
= r300TexEnv
;
1027 functions
->TexParameter
= r300TexParameter
;
1028 functions
->TexGen
= r300TexGen
;
1030 driInitTextureFormats();
1033 /* moved or obsolete code */
1034 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
1035 driInitTextureObjects(ctx
, &rmesa
->swapped
,
1036 DRI_TEXMGR_DO_TEXTURE_1D
1037 | DRI_TEXMGR_DO_TEXTURE_2D
);
1039 /* Hack: r300NewTextureObject is not yet installed when the
1040 * default textures are created. Therefore set MaxAnisotropy of the
1041 * default 2D texture now. */
1042 ctx
->Shared
->Default2D
->MaxAnisotropy
=
1043 driQueryOptionf(&rmesa
->optionCache
, "def_max_anisotropy");