1
/* $XFree86: xc/lib/GL/mesa/src/drv/r200/r200_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 "r200_context.h"
49
#include "r200_state.h"
50
#include "r200_ioctl.h"
51
#include "r200_swtcl.h"
59
* Set the texture wrap modes.
61
* \param t Texture object whose wrap modes are to be set
62
* \param swrap Wrap mode for the \a s texture coordinate
63
* \param twrap Wrap mode for the \a t texture coordinate
66
static void r200SetTexWrap( r200TexObjPtr t, GLenum swrap, GLenum twrap, GLenum rwrap )
68
GLboolean is_clamp = GL_FALSE;
69
GLboolean is_clamp_to_border = GL_FALSE;
71
t->pp_txfilter &= ~(R200_CLAMP_S_MASK | R200_CLAMP_T_MASK | R200_BORDER_MODE_D3D);
75
t->pp_txfilter |= R200_CLAMP_S_WRAP;
78
t->pp_txfilter |= R200_CLAMP_S_CLAMP_GL;
81
case GL_CLAMP_TO_EDGE:
82
t->pp_txfilter |= R200_CLAMP_S_CLAMP_LAST;
84
case GL_CLAMP_TO_BORDER:
85
t->pp_txfilter |= R200_CLAMP_S_CLAMP_GL;
86
is_clamp_to_border = GL_TRUE;
88
case GL_MIRRORED_REPEAT:
89
t->pp_txfilter |= R200_CLAMP_S_MIRROR;
91
case GL_MIRROR_CLAMP_EXT:
92
t->pp_txfilter |= R200_CLAMP_S_MIRROR_CLAMP_GL;
95
case GL_MIRROR_CLAMP_TO_EDGE_EXT:
96
t->pp_txfilter |= R200_CLAMP_S_MIRROR_CLAMP_LAST;
98
case GL_MIRROR_CLAMP_TO_BORDER_EXT:
99
t->pp_txfilter |= 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->pp_txfilter |= R200_CLAMP_T_WRAP;
111
t->pp_txfilter |= R200_CLAMP_T_CLAMP_GL;
114
case GL_CLAMP_TO_EDGE:
115
t->pp_txfilter |= R200_CLAMP_T_CLAMP_LAST;
117
case GL_CLAMP_TO_BORDER:
118
t->pp_txfilter |= R200_CLAMP_T_CLAMP_GL;
119
is_clamp_to_border = GL_TRUE;
121
case GL_MIRRORED_REPEAT:
122
t->pp_txfilter |= R200_CLAMP_T_MIRROR;
124
case GL_MIRROR_CLAMP_EXT:
125
t->pp_txfilter |= R200_CLAMP_T_MIRROR_CLAMP_GL;
128
case GL_MIRROR_CLAMP_TO_EDGE_EXT:
129
t->pp_txfilter |= R200_CLAMP_T_MIRROR_CLAMP_LAST;
131
case GL_MIRROR_CLAMP_TO_BORDER_EXT:
132
t->pp_txfilter |= 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->pp_txformat_x &= ~R200_CLAMP_Q_MASK;
143
t->pp_txformat_x |= R200_CLAMP_Q_WRAP;
146
t->pp_txformat_x |= R200_CLAMP_Q_CLAMP_GL;
149
case GL_CLAMP_TO_EDGE:
150
t->pp_txformat_x |= R200_CLAMP_Q_CLAMP_LAST;
152
case GL_CLAMP_TO_BORDER:
153
t->pp_txformat_x |= R200_CLAMP_Q_CLAMP_GL;
154
is_clamp_to_border = GL_TRUE;
156
case GL_MIRRORED_REPEAT:
157
t->pp_txformat_x |= R200_CLAMP_Q_MIRROR;
159
case GL_MIRROR_CLAMP_EXT:
160
t->pp_txformat_x |= R200_CLAMP_Q_MIRROR_CLAMP_GL;
163
case GL_MIRROR_CLAMP_TO_EDGE_EXT:
164
t->pp_txformat_x |= R200_CLAMP_Q_MIRROR_CLAMP_LAST;
166
case GL_MIRROR_CLAMP_TO_BORDER_EXT:
167
t->pp_txformat_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->pp_txfilter |= R200_BORDER_MODE_D3D;
178
t->border_fallback = (is_clamp && is_clamp_to_border);
181
static void r200SetTexMaxAnisotropy( r200TexObjPtr t, GLfloat max )
183
t->pp_txfilter &= ~R200_MAX_ANISO_MASK;
186
t->pp_txfilter |= R200_MAX_ANISO_1_TO_1;
187
} else if ( max <= 2.0 ) {
188
t->pp_txfilter |= R200_MAX_ANISO_2_TO_1;
189
} else if ( max <= 4.0 ) {
190
t->pp_txfilter |= R200_MAX_ANISO_4_TO_1;
191
} else if ( max <= 8.0 ) {
192
t->pp_txfilter |= R200_MAX_ANISO_8_TO_1;
194
t->pp_txfilter |= 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 r200SetTexFilter( r200TexObjPtr t, GLenum minf, GLenum magf )
208
GLuint anisotropy = (t->pp_txfilter & R200_MAX_ANISO_MASK);
210
t->pp_txfilter &= ~(R200_MIN_FILTER_MASK | R200_MAG_FILTER_MASK);
211
t->pp_txformat_x &= ~R200_VOLUME_FILTER_MASK;
213
if ( anisotropy == R200_MAX_ANISO_1_TO_1 ) {
216
t->pp_txfilter |= R200_MIN_FILTER_NEAREST;
219
t->pp_txfilter |= R200_MIN_FILTER_LINEAR;
221
case GL_NEAREST_MIPMAP_NEAREST:
222
t->pp_txfilter |= R200_MIN_FILTER_NEAREST_MIP_NEAREST;
224
case GL_NEAREST_MIPMAP_LINEAR:
225
t->pp_txfilter |= R200_MIN_FILTER_LINEAR_MIP_NEAREST;
227
case GL_LINEAR_MIPMAP_NEAREST:
228
t->pp_txfilter |= R200_MIN_FILTER_NEAREST_MIP_LINEAR;
230
case GL_LINEAR_MIPMAP_LINEAR:
231
t->pp_txfilter |= R200_MIN_FILTER_LINEAR_MIP_LINEAR;
237
t->pp_txfilter |= R200_MIN_FILTER_ANISO_NEAREST;
240
t->pp_txfilter |= R200_MIN_FILTER_ANISO_LINEAR;
242
case GL_NEAREST_MIPMAP_NEAREST:
243
case GL_LINEAR_MIPMAP_NEAREST:
244
t->pp_txfilter |= R200_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST;
246
case GL_NEAREST_MIPMAP_LINEAR:
247
case GL_LINEAR_MIPMAP_LINEAR:
248
t->pp_txfilter |= R200_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->pp_txfilter |= R200_MAG_FILTER_NEAREST;
259
t->pp_txformat_x |= R200_VOLUME_FILTER_NEAREST;
262
t->pp_txfilter |= R200_MAG_FILTER_LINEAR;
263
t->pp_txformat_x |= R200_VOLUME_FILTER_LINEAR;
268
static void r200SetTexBorderColor( r200TexObjPtr t, GLubyte c[4] )
270
t->pp_border_color = r200PackColor( 4, c[0], c[1], c[2], c[3] );
275
* Allocate space for and load the mesa images into the texture memory block.
276
* This will happen before drawing with a new texture, or drawing with a
277
* texture after it was swapped out or teximaged again.
280
static r200TexObjPtr r200AllocTexObj( struct gl_texture_object *texObj )
284
t = CALLOC_STRUCT( r200_tex_obj );
285
texObj->DriverData = t;
287
if ( R200_DEBUG & DEBUG_TEXTURE ) {
288
fprintf( stderr, "%s( %p, %p )\n", __FUNCTION__, (void *)texObj,
292
/* Initialize non-image-dependent parts of the state:
294
t->base.tObj = texObj;
295
t->border_fallback = GL_FALSE;
297
make_empty_list( & t->base );
299
r200SetTexWrap( t, texObj->WrapS, texObj->WrapT, texObj->WrapR );
300
r200SetTexMaxAnisotropy( t, texObj->MaxAnisotropy );
301
r200SetTexFilter( t, texObj->MinFilter, texObj->MagFilter );
302
r200SetTexBorderColor( t, texObj->_BorderChan );
308
/* try to find a format which will only need a memcopy */
309
static const struct gl_texture_format *
310
r200Choose8888TexFormat( GLenum srcFormat, GLenum srcType )
313
const GLubyte littleEndian = *((const GLubyte *) &ui);
315
if ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8) ||
316
(srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE && !littleEndian) ||
317
(srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) ||
318
(srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && littleEndian)) {
319
return &_mesa_texformat_rgba8888;
321
else if ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) ||
322
(srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE && littleEndian) ||
323
(srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8) ||
324
(srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && !littleEndian)) {
325
return &_mesa_texformat_rgba8888_rev;
327
else return _dri_texformat_argb8888;
330
static const struct gl_texture_format *
331
r200ChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
332
GLenum format, GLenum type )
334
r200ContextPtr rmesa = R200_CONTEXT(ctx);
335
const GLboolean do32bpt =
336
( rmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_32 );
337
const GLboolean force16bpt =
338
( rmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FORCE_16 );
341
switch ( internalFormat ) {
344
case GL_COMPRESSED_RGBA:
346
case GL_UNSIGNED_INT_10_10_10_2:
347
case GL_UNSIGNED_INT_2_10_10_10_REV:
348
return do32bpt ? _dri_texformat_argb8888 : _dri_texformat_argb1555;
349
case GL_UNSIGNED_SHORT_4_4_4_4:
350
case GL_UNSIGNED_SHORT_4_4_4_4_REV:
351
return _dri_texformat_argb4444;
352
case GL_UNSIGNED_SHORT_5_5_5_1:
353
case GL_UNSIGNED_SHORT_1_5_5_5_REV:
354
return _dri_texformat_argb1555;
357
r200Choose8888TexFormat(format, type) : _dri_texformat_argb4444;
362
case GL_COMPRESSED_RGB:
364
case GL_UNSIGNED_SHORT_4_4_4_4:
365
case GL_UNSIGNED_SHORT_4_4_4_4_REV:
366
return _dri_texformat_argb4444;
367
case GL_UNSIGNED_SHORT_5_5_5_1:
368
case GL_UNSIGNED_SHORT_1_5_5_5_REV:
369
return _dri_texformat_argb1555;
370
case GL_UNSIGNED_SHORT_5_6_5:
371
case GL_UNSIGNED_SHORT_5_6_5_REV:
372
return _dri_texformat_rgb565;
374
return do32bpt ? _dri_texformat_argb8888 : _dri_texformat_rgb565;
382
r200Choose8888TexFormat(format, type) : _dri_texformat_argb4444;
386
return _dri_texformat_argb4444;
389
return _dri_texformat_argb1555;
395
return !force16bpt ? _dri_texformat_argb8888 : _dri_texformat_rgb565;
400
return _dri_texformat_rgb565;
407
case GL_COMPRESSED_ALPHA:
408
/* can't use a8 format since interpreting hw I8 as a8 would result
409
in wrong rgb values (same as alpha value instead of 0). */
410
return _dri_texformat_al88;
418
case GL_COMPRESSED_LUMINANCE:
419
return _dri_texformat_l8;
422
case GL_LUMINANCE_ALPHA:
423
case GL_LUMINANCE4_ALPHA4:
424
case GL_LUMINANCE6_ALPHA2:
425
case GL_LUMINANCE8_ALPHA8:
426
case GL_LUMINANCE12_ALPHA4:
427
case GL_LUMINANCE12_ALPHA12:
428
case GL_LUMINANCE16_ALPHA16:
429
case GL_COMPRESSED_LUMINANCE_ALPHA:
430
return _dri_texformat_al88;
437
case GL_COMPRESSED_INTENSITY:
438
return _dri_texformat_i8;
441
if (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
442
type == GL_UNSIGNED_BYTE)
443
return &_mesa_texformat_ycbcr;
445
return &_mesa_texformat_ycbcr_rev;
449
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
450
return &_mesa_texformat_rgb_dxt1;
452
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
453
return &_mesa_texformat_rgba_dxt1;
457
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
458
return &_mesa_texformat_rgba_dxt3;
460
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
461
return &_mesa_texformat_rgba_dxt5;
465
"unexpected internalFormat 0x%x in r200ChooseTextureFormat",
466
(int) internalFormat);
470
return NULL; /* never get here */
475
r200ValidateClientStorage( GLcontext *ctx, GLenum target,
476
GLint internalFormat,
477
GLint srcWidth, GLint srcHeight,
478
GLenum format, GLenum type, const void *pixels,
479
const struct gl_pixelstore_attrib *packing,
480
struct gl_texture_object *texObj,
481
struct gl_texture_image *texImage)
484
r200ContextPtr rmesa = R200_CONTEXT(ctx);
487
fprintf(stderr, "intformat %s format %s type %s\n",
488
_mesa_lookup_enum_by_nr( internalFormat ),
489
_mesa_lookup_enum_by_nr( format ),
490
_mesa_lookup_enum_by_nr( type ));
492
if (!ctx->Unpack.ClientStorage)
495
if (ctx->_ImageTransferState ||
496
texImage->IsCompressed ||
497
texObj->GenerateMipmap)
501
/* This list is incomplete, may be different on ppc???
503
switch ( internalFormat ) {
505
if ( format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8_REV ) {
506
texImage->TexFormat = _dri_texformat_argb8888;
513
if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) {
514
texImage->TexFormat = _dri_texformat_rgb565;
521
if ( format == GL_YCBCR_MESA &&
522
type == GL_UNSIGNED_SHORT_8_8_REV_APPLE ) {
523
texImage->TexFormat = &_mesa_texformat_ycbcr_rev;
525
else if ( format == GL_YCBCR_MESA &&
526
(type == GL_UNSIGNED_SHORT_8_8_APPLE ||
527
type == GL_UNSIGNED_BYTE)) {
528
texImage->TexFormat = &_mesa_texformat_ycbcr;
538
/* Could deal with these packing issues, but currently don't:
540
if (packing->SkipPixels ||
542
packing->SwapBytes ||
548
GLint srcRowStride = _mesa_image_row_stride(packing, srcWidth,
553
fprintf(stderr, "%s: srcRowStride %d/%x\n",
554
__FUNCTION__, srcRowStride, srcRowStride);
556
/* Could check this later in upload, pitch restrictions could be
557
* relaxed, but would need to store the image pitch somewhere,
558
* as packing details might change before image is uploaded:
560
if (!r200IsGartMemory( rmesa, pixels, srcHeight * srcRowStride ) ||
565
/* Have validated that _mesa_transfer_teximage would be a straight
566
* memcpy at this point. NOTE: future calls to TexSubImage will
567
* overwrite the client data. This is explicitly mentioned in the
570
texImage->Data = (void *)pixels;
571
texImage->IsClientData = GL_TRUE;
572
texImage->RowStride = srcRowStride / texImage->TexFormat->TexelBytes;
579
static void r200TexImage1D( GLcontext *ctx, GLenum target, GLint level,
580
GLint internalFormat,
581
GLint width, GLint border,
582
GLenum format, GLenum type, const GLvoid *pixels,
583
const struct gl_pixelstore_attrib *packing,
584
struct gl_texture_object *texObj,
585
struct gl_texture_image *texImage )
587
driTextureObject * t = (driTextureObject *) texObj->DriverData;
590
driSwapOutTextureObject( t );
593
t = (driTextureObject *) r200AllocTexObj( texObj );
595
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
600
/* Note, this will call ChooseTextureFormat */
601
_mesa_store_teximage1d(ctx, target, level, internalFormat,
602
width, border, format, type, pixels,
603
&ctx->Unpack, texObj, texImage);
605
t->dirty_images[0] |= (1 << level);
609
static void r200TexSubImage1D( GLcontext *ctx, GLenum target, GLint level,
612
GLenum format, GLenum type,
613
const GLvoid *pixels,
614
const struct gl_pixelstore_attrib *packing,
615
struct gl_texture_object *texObj,
616
struct gl_texture_image *texImage )
618
driTextureObject * t = (driTextureObject *) texObj->DriverData;
620
assert( t ); /* this _should_ be true */
622
driSwapOutTextureObject( t );
625
t = (driTextureObject *) r200AllocTexObj( texObj );
627
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
632
_mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
633
format, type, pixels, packing, texObj,
636
t->dirty_images[0] |= (1 << level);
640
static void r200TexImage2D( GLcontext *ctx, GLenum target, GLint level,
641
GLint internalFormat,
642
GLint width, GLint height, GLint border,
643
GLenum format, GLenum type, const GLvoid *pixels,
644
const struct gl_pixelstore_attrib *packing,
645
struct gl_texture_object *texObj,
646
struct gl_texture_image *texImage )
648
driTextureObject * t = (driTextureObject *) texObj->DriverData;
651
/* which cube face or ordinary 2D image */
653
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
654
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
655
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
656
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
657
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
658
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
659
face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
667
driSwapOutTextureObject( t );
670
t = (driTextureObject *) r200AllocTexObj( texObj );
672
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
677
texImage->IsClientData = GL_FALSE;
679
if (r200ValidateClientStorage( ctx, target,
682
format, type, pixels,
683
packing, texObj, texImage)) {
684
if (R200_DEBUG & DEBUG_TEXTURE)
685
fprintf(stderr, "%s: Using client storage\n", __FUNCTION__);
688
if (R200_DEBUG & DEBUG_TEXTURE)
689
fprintf(stderr, "%s: Using normal storage\n", __FUNCTION__);
691
/* Normal path: copy (to cached memory) and eventually upload
692
* via another copy to GART memory and then a blit... Could
693
* eliminate one copy by going straight to (permanent) GART.
695
* Note, this will call r200ChooseTextureFormat.
697
_mesa_store_teximage2d(ctx, target, level, internalFormat,
698
width, height, border, format, type, pixels,
699
&ctx->Unpack, texObj, texImage);
701
t->dirty_images[face] |= (1 << level);
706
static void r200TexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
707
GLint xoffset, GLint yoffset,
708
GLsizei width, GLsizei height,
709
GLenum format, GLenum type,
710
const GLvoid *pixels,
711
const struct gl_pixelstore_attrib *packing,
712
struct gl_texture_object *texObj,
713
struct gl_texture_image *texImage )
715
driTextureObject * t = (driTextureObject *) texObj->DriverData;
718
/* which cube face or ordinary 2D image */
720
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
721
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
722
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
723
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
724
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
725
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
726
face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
733
assert( t ); /* this _should_ be true */
735
driSwapOutTextureObject( t );
738
t = (driTextureObject *) r200AllocTexObj( texObj );
740
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
745
_mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
746
height, format, type, pixels, packing, texObj,
749
t->dirty_images[face] |= (1 << level);
753
static void r200CompressedTexImage2D( GLcontext *ctx, GLenum target, GLint level,
754
GLint internalFormat,
755
GLint width, GLint height, GLint border,
756
GLsizei imageSize, const GLvoid *data,
757
struct gl_texture_object *texObj,
758
struct gl_texture_image *texImage )
760
driTextureObject * t = (driTextureObject *) texObj->DriverData;
763
/* which cube face or ordinary 2D image */
765
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
766
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
767
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
768
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
769
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
770
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
771
face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
779
driSwapOutTextureObject( t );
782
t = (driTextureObject *) r200AllocTexObj( texObj );
784
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
789
texImage->IsClientData = GL_FALSE;
790
/* can't call this, different parameters. Would never evaluate to true anyway currently
791
if (r200ValidateClientStorage( ctx, target,
794
format, type, pixels,
795
packing, texObj, texImage)) {
796
if (R200_DEBUG & DEBUG_TEXTURE)
797
fprintf(stderr, "%s: Using client storage\n", __FUNCTION__);
800
if (R200_DEBUG & DEBUG_TEXTURE)
801
fprintf(stderr, "%s: Using normal storage\n", __FUNCTION__);
803
/* Normal path: copy (to cached memory) and eventually upload
804
* via another copy to GART memory and then a blit... Could
805
* eliminate one copy by going straight to (permanent) GART.
807
* Note, this will call r200ChooseTextureFormat.
809
_mesa_store_compressed_teximage2d(ctx, target, level, internalFormat, width,
810
height, border, imageSize, data, texObj, texImage);
812
t->dirty_images[face] |= (1 << level);
817
static void r200CompressedTexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
818
GLint xoffset, GLint yoffset,
819
GLsizei width, GLsizei height,
821
GLsizei imageSize, const GLvoid *data,
822
struct gl_texture_object *texObj,
823
struct gl_texture_image *texImage )
825
driTextureObject * t = (driTextureObject *) texObj->DriverData;
829
/* which cube face or ordinary 2D image */
831
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
832
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
833
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
834
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
835
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
836
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
837
face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
844
assert( t ); /* this _should_ be true */
846
driSwapOutTextureObject( t );
849
t = (driTextureObject *) r200AllocTexObj( texObj );
851
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexSubImage2D");
856
_mesa_store_compressed_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
857
height, format, imageSize, data, texObj, texImage);
859
t->dirty_images[face] |= (1 << level);
863
#if ENABLE_HW_3D_TEXTURE
864
static void r200TexImage3D( GLcontext *ctx, GLenum target, GLint level,
865
GLint internalFormat,
866
GLint width, GLint height, GLint depth,
868
GLenum format, GLenum type, const GLvoid *pixels,
869
const struct gl_pixelstore_attrib *packing,
870
struct gl_texture_object *texObj,
871
struct gl_texture_image *texImage )
873
driTextureObject * t = (driTextureObject *) texObj->DriverData;
876
driSwapOutTextureObject( t );
879
t = (driTextureObject *) r200AllocTexObj( texObj );
881
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
886
texImage->IsClientData = GL_FALSE;
889
if (r200ValidateClientStorage( ctx, target,
892
format, type, pixels,
893
packing, texObj, texImage)) {
894
if (R200_DEBUG & DEBUG_TEXTURE)
895
fprintf(stderr, "%s: Using client storage\n", __FUNCTION__);
900
if (R200_DEBUG & DEBUG_TEXTURE)
901
fprintf(stderr, "%s: Using normal storage\n", __FUNCTION__);
903
/* Normal path: copy (to cached memory) and eventually upload
904
* via another copy to GART memory and then a blit... Could
905
* eliminate one copy by going straight to (permanent) GART.
907
* Note, this will call r200ChooseTextureFormat.
909
_mesa_store_teximage3d(ctx, target, level, internalFormat,
910
width, height, depth, border,
911
format, type, pixels,
912
&ctx->Unpack, texObj, texImage);
914
t->dirty_images[0] |= (1 << level);
920
#if ENABLE_HW_3D_TEXTURE
922
r200TexSubImage3D( GLcontext *ctx, GLenum target, GLint level,
923
GLint xoffset, GLint yoffset, GLint zoffset,
924
GLsizei width, GLsizei height, GLsizei depth,
925
GLenum format, GLenum type,
926
const GLvoid *pixels,
927
const struct gl_pixelstore_attrib *packing,
928
struct gl_texture_object *texObj,
929
struct gl_texture_image *texImage )
931
driTextureObject * t = (driTextureObject *) texObj->DriverData;
933
/* fprintf(stderr, "%s\n", __FUNCTION__); */
935
assert( t ); /* this _should_ be true */
937
driSwapOutTextureObject( t );
940
t = (driTextureObject *) r200AllocTexObj( texObj );
942
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage3D");
945
texObj->DriverData = t;
948
_mesa_store_texsubimage3d(ctx, target, level, xoffset, yoffset, zoffset,
949
width, height, depth,
950
format, type, pixels, packing, texObj, texImage);
952
t->dirty_images[0] |= (1 << level);
958
static void r200TexEnv( GLcontext *ctx, GLenum target,
959
GLenum pname, const GLfloat *param )
961
r200ContextPtr rmesa = R200_CONTEXT(ctx);
962
GLuint unit = ctx->Texture.CurrentUnit;
963
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
965
if ( R200_DEBUG & DEBUG_STATE ) {
966
fprintf( stderr, "%s( %s )\n",
967
__FUNCTION__, _mesa_lookup_enum_by_nr( pname ) );
970
/* This is incorrect: Need to maintain this data for each of
971
* GL_TEXTURE_{123}D, GL_TEXTURE_RECTANGLE_NV, etc, and switch
972
* between them according to _ReallyEnabled.
975
case GL_TEXTURE_ENV_COLOR: {
978
UNCLAMPED_FLOAT_TO_RGBA_CHAN( c, texUnit->EnvColor );
979
envColor = r200PackColor( 4, c[0], c[1], c[2], c[3] );
980
if ( rmesa->hw.tf.cmd[TF_TFACTOR_0 + unit] != envColor ) {
981
R200_STATECHANGE( rmesa, tf );
982
rmesa->hw.tf.cmd[TF_TFACTOR_0 + unit] = envColor;
987
case GL_TEXTURE_LOD_BIAS_EXT: {
990
const int fixed_one = 0x8000000;
992
/* The R200's LOD bias is a signed 2's complement value with a
993
* range of -16.0 <= bias < 16.0.
995
* NOTE: Add a small bias to the bias for conform mipsel.c test.
998
min = driQueryOptionb (&rmesa->optionCache, "no_neg_lod_bias") ?
1000
bias = CLAMP( bias, min, 16.0 );
1001
b = (int)(bias * fixed_one) & R200_LOD_BIAS_MASK;
1003
if ( (rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT_X] & R200_LOD_BIAS_MASK) != b ) {
1004
R200_STATECHANGE( rmesa, tex[unit] );
1005
rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT_X] &= ~R200_LOD_BIAS_MASK;
1006
rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT_X] |= b;
1010
case GL_COORD_REPLACE_ARB:
1011
if (ctx->Point.PointSprite) {
1012
R200_STATECHANGE( rmesa, spr );
1013
if ((GLenum)param[0]) {
1014
rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |= R200_PS_GEN_TEX_0 << unit;
1016
rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] &= ~(R200_PS_GEN_TEX_0 << unit);
1027
* Changes variables and flags for a state update, which will happen at the
1028
* next UpdateTextureState
1031
static void r200TexParameter( GLcontext *ctx, GLenum target,
1032
struct gl_texture_object *texObj,
1033
GLenum pname, const GLfloat *params )
1035
r200TexObjPtr t = (r200TexObjPtr) texObj->DriverData;
1037
if ( R200_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) {
1038
fprintf( stderr, "%s( %s )\n", __FUNCTION__,
1039
_mesa_lookup_enum_by_nr( pname ) );
1043
case GL_TEXTURE_MIN_FILTER:
1044
case GL_TEXTURE_MAG_FILTER:
1045
case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1046
r200SetTexMaxAnisotropy( t, texObj->MaxAnisotropy );
1047
r200SetTexFilter( t, texObj->MinFilter, texObj->MagFilter );
1050
case GL_TEXTURE_WRAP_S:
1051
case GL_TEXTURE_WRAP_T:
1052
case GL_TEXTURE_WRAP_R:
1053
r200SetTexWrap( t, texObj->WrapS, texObj->WrapT, texObj->WrapR );
1056
case GL_TEXTURE_BORDER_COLOR:
1057
r200SetTexBorderColor( t, texObj->_BorderChan );
1060
case GL_TEXTURE_BASE_LEVEL:
1061
case GL_TEXTURE_MAX_LEVEL:
1062
case GL_TEXTURE_MIN_LOD:
1063
case GL_TEXTURE_MAX_LOD:
1064
/* This isn't the most efficient solution but there doesn't appear to
1065
* be a nice alternative. Since there's no LOD clamping,
1066
* we just have to rely on loading the right subset of mipmap levels
1067
* to simulate a clamped LOD.
1069
driSwapOutTextureObject( (driTextureObject *) t );
1076
/* Mark this texobj as dirty (one bit per tex unit)
1078
t->dirty_state = TEX_ALL;
1083
static void r200BindTexture( GLcontext *ctx, GLenum target,
1084
struct gl_texture_object *texObj )
1086
if ( R200_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) {
1087
fprintf( stderr, "%s( %p ) unit=%d\n", __FUNCTION__, (void *)texObj,
1088
ctx->Texture.CurrentUnit );
1091
if ( (target == GL_TEXTURE_1D)
1092
|| (target == GL_TEXTURE_2D)
1093
#if ENABLE_HW_3D_TEXTURE
1094
|| (target == GL_TEXTURE_3D)
1096
|| (target == GL_TEXTURE_CUBE_MAP)
1097
|| (target == GL_TEXTURE_RECTANGLE_NV) ) {
1098
assert( texObj->DriverData != NULL );
1103
static void r200DeleteTexture( GLcontext *ctx,
1104
struct gl_texture_object *texObj )
1106
r200ContextPtr rmesa = R200_CONTEXT(ctx);
1107
driTextureObject * t = (driTextureObject *) texObj->DriverData;
1109
if ( R200_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) {
1110
fprintf( stderr, "%s( %p (target = %s) )\n", __FUNCTION__, (void *)texObj,
1111
_mesa_lookup_enum_by_nr( texObj->Target ) );
1116
R200_FIREVERTICES( rmesa );
1119
driDestroyTextureObject( t );
1121
/* Free mipmap images and the texture object itself */
1122
_mesa_delete_texture_object(ctx, texObj);
1126
* - Same GEN_MODE for all active bits
1127
* - Same EyePlane/ObjPlane for all active bits when using Eye/Obj
1128
* - STRQ presumably all supported (matrix means incoming R values
1129
* can end up in STQ, this has implications for vertex support,
1130
* presumably ok if maos is used, though?)
1132
* Basically impossible to do this on the fly - just collect some
1133
* basic info & do the checks from ValidateState().
1135
static void r200TexGen( GLcontext *ctx,
1138
const GLfloat *params )
1140
r200ContextPtr rmesa = R200_CONTEXT(ctx);
1141
GLuint unit = ctx->Texture.CurrentUnit;
1142
rmesa->recheck_texgen[unit] = GL_TRUE;
1147
* Allocate a new texture object.
1148
* Called via ctx->Driver.NewTextureObject.
1149
* Note: this function will be called during context creation to
1150
* allocate the default texture objects.
1151
* Note: we could use containment here to 'derive' the driver-specific
1152
* texture object from the core mesa gl_texture_object. Not done at this time.
1153
* Fixup MaxAnisotropy according to user preference.
1155
static struct gl_texture_object *
1156
r200NewTextureObject( GLcontext *ctx, GLuint name, GLenum target )
1158
r200ContextPtr rmesa = R200_CONTEXT(ctx);
1159
struct gl_texture_object *obj;
1160
obj = _mesa_new_texture_object(ctx, name, target);
1163
obj->MaxAnisotropy = rmesa->initialMaxAnisotropy;
1164
r200AllocTexObj( obj );
1169
void r200InitTextureFuncs( struct dd_function_table *functions )
1171
/* Note: we only plug in the functions we implement in the driver
1172
* since _mesa_init_driver_functions() was already called.
1174
functions->ChooseTextureFormat = r200ChooseTextureFormat;
1175
functions->TexImage1D = r200TexImage1D;
1176
functions->TexImage2D = r200TexImage2D;
1177
#if ENABLE_HW_3D_TEXTURE
1178
functions->TexImage3D = r200TexImage3D;
1180
functions->TexImage3D = _mesa_store_teximage3d;
1182
functions->TexSubImage1D = r200TexSubImage1D;
1183
functions->TexSubImage2D = r200TexSubImage2D;
1184
#if ENABLE_HW_3D_TEXTURE
1185
functions->TexSubImage3D = r200TexSubImage3D;
1187
functions->TexSubImage3D = _mesa_store_texsubimage3d;
1189
functions->NewTextureObject = r200NewTextureObject;
1190
functions->BindTexture = r200BindTexture;
1191
functions->DeleteTexture = r200DeleteTexture;
1192
functions->IsTextureResident = driIsTextureResident;
1194
functions->TexEnv = r200TexEnv;
1195
functions->TexParameter = r200TexParameter;
1196
functions->TexGen = r200TexGen;
1198
functions->CompressedTexImage2D = r200CompressedTexImage2D;
1199
functions->CompressedTexSubImage2D = r200CompressedTexSubImage2D;
1201
driInitTextureFormats();
1204
/* moved or obsolete code */
1205
r200ContextPtr rmesa = R200_CONTEXT(ctx);
1206
driInitTextureObjects( ctx, & rmesa->swapped,
1207
DRI_TEXMGR_DO_TEXTURE_1D
1208
| DRI_TEXMGR_DO_TEXTURE_2D );
1210
/* Hack: r200NewTextureObject is not yet installed when the
1211
* default textures are created. Therefore set MaxAnisotropy of the
1212
* default 2D texture now. */
1213
ctx->Shared->Default2D->MaxAnisotropy = driQueryOptionf (&rmesa->optionCache,
1214
"def_max_anisotropy");