Merge commit 'origin/gallium-0.1' into gallium-0.2
[mesa.git] / src / mesa / drivers / dri / r200 / r200_tex.c
1 /*
2 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
3
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.
7
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:
15
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.
19
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.
27 */
28
29 /*
30 * Authors:
31 * Keith Whitwell <keith@tungstengraphics.com>
32 */
33
34 #include "glheader.h"
35 #include "imports.h"
36 #include "colormac.h"
37 #include "context.h"
38 #include "enums.h"
39 #include "image.h"
40 #include "simple_list.h"
41 #include "texformat.h"
42 #include "texstore.h"
43 #include "texmem.h"
44 #include "teximage.h"
45 #include "texobj.h"
46
47 #include "r200_context.h"
48 #include "r200_state.h"
49 #include "r200_ioctl.h"
50 #include "r200_swtcl.h"
51 #include "r200_tex.h"
52
53 #include "xmlpool.h"
54
55
56
57 /**
58 * Set the texture wrap modes.
59 *
60 * \param t Texture object whose wrap modes are to be set
61 * \param swrap Wrap mode for the \a s texture coordinate
62 * \param twrap Wrap mode for the \a t texture coordinate
63 */
64
65 static void r200SetTexWrap( r200TexObjPtr t, GLenum swrap, GLenum twrap, GLenum rwrap )
66 {
67 GLboolean is_clamp = GL_FALSE;
68 GLboolean is_clamp_to_border = GL_FALSE;
69
70 t->pp_txfilter &= ~(R200_CLAMP_S_MASK | R200_CLAMP_T_MASK | R200_BORDER_MODE_D3D);
71
72 switch ( swrap ) {
73 case GL_REPEAT:
74 t->pp_txfilter |= R200_CLAMP_S_WRAP;
75 break;
76 case GL_CLAMP:
77 t->pp_txfilter |= R200_CLAMP_S_CLAMP_GL;
78 is_clamp = GL_TRUE;
79 break;
80 case GL_CLAMP_TO_EDGE:
81 t->pp_txfilter |= R200_CLAMP_S_CLAMP_LAST;
82 break;
83 case GL_CLAMP_TO_BORDER:
84 t->pp_txfilter |= R200_CLAMP_S_CLAMP_GL;
85 is_clamp_to_border = GL_TRUE;
86 break;
87 case GL_MIRRORED_REPEAT:
88 t->pp_txfilter |= R200_CLAMP_S_MIRROR;
89 break;
90 case GL_MIRROR_CLAMP_EXT:
91 t->pp_txfilter |= R200_CLAMP_S_MIRROR_CLAMP_GL;
92 is_clamp = GL_TRUE;
93 break;
94 case GL_MIRROR_CLAMP_TO_EDGE_EXT:
95 t->pp_txfilter |= R200_CLAMP_S_MIRROR_CLAMP_LAST;
96 break;
97 case GL_MIRROR_CLAMP_TO_BORDER_EXT:
98 t->pp_txfilter |= R200_CLAMP_S_MIRROR_CLAMP_GL;
99 is_clamp_to_border = GL_TRUE;
100 break;
101 default:
102 _mesa_problem(NULL, "bad S wrap mode in %s", __FUNCTION__);
103 }
104
105 if (t->base.tObj->Target != GL_TEXTURE_1D) {
106 switch ( twrap ) {
107 case GL_REPEAT:
108 t->pp_txfilter |= R200_CLAMP_T_WRAP;
109 break;
110 case GL_CLAMP:
111 t->pp_txfilter |= R200_CLAMP_T_CLAMP_GL;
112 is_clamp = GL_TRUE;
113 break;
114 case GL_CLAMP_TO_EDGE:
115 t->pp_txfilter |= R200_CLAMP_T_CLAMP_LAST;
116 break;
117 case GL_CLAMP_TO_BORDER:
118 t->pp_txfilter |= R200_CLAMP_T_CLAMP_GL;
119 is_clamp_to_border = GL_TRUE;
120 break;
121 case GL_MIRRORED_REPEAT:
122 t->pp_txfilter |= R200_CLAMP_T_MIRROR;
123 break;
124 case GL_MIRROR_CLAMP_EXT:
125 t->pp_txfilter |= R200_CLAMP_T_MIRROR_CLAMP_GL;
126 is_clamp = GL_TRUE;
127 break;
128 case GL_MIRROR_CLAMP_TO_EDGE_EXT:
129 t->pp_txfilter |= R200_CLAMP_T_MIRROR_CLAMP_LAST;
130 break;
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;
134 break;
135 default:
136 _mesa_problem(NULL, "bad T wrap mode in %s", __FUNCTION__);
137 }
138 }
139
140 t->pp_txformat_x &= ~R200_CLAMP_Q_MASK;
141
142 switch ( rwrap ) {
143 case GL_REPEAT:
144 t->pp_txformat_x |= R200_CLAMP_Q_WRAP;
145 break;
146 case GL_CLAMP:
147 t->pp_txformat_x |= R200_CLAMP_Q_CLAMP_GL;
148 is_clamp = GL_TRUE;
149 break;
150 case GL_CLAMP_TO_EDGE:
151 t->pp_txformat_x |= R200_CLAMP_Q_CLAMP_LAST;
152 break;
153 case GL_CLAMP_TO_BORDER:
154 t->pp_txformat_x |= R200_CLAMP_Q_CLAMP_GL;
155 is_clamp_to_border = GL_TRUE;
156 break;
157 case GL_MIRRORED_REPEAT:
158 t->pp_txformat_x |= R200_CLAMP_Q_MIRROR;
159 break;
160 case GL_MIRROR_CLAMP_EXT:
161 t->pp_txformat_x |= R200_CLAMP_Q_MIRROR_CLAMP_GL;
162 is_clamp = GL_TRUE;
163 break;
164 case GL_MIRROR_CLAMP_TO_EDGE_EXT:
165 t->pp_txformat_x |= R200_CLAMP_Q_MIRROR_CLAMP_LAST;
166 break;
167 case GL_MIRROR_CLAMP_TO_BORDER_EXT:
168 t->pp_txformat_x |= R200_CLAMP_Q_MIRROR_CLAMP_GL;
169 is_clamp_to_border = GL_TRUE;
170 break;
171 default:
172 _mesa_problem(NULL, "bad R wrap mode in %s", __FUNCTION__);
173 }
174
175 if ( is_clamp_to_border ) {
176 t->pp_txfilter |= R200_BORDER_MODE_D3D;
177 }
178
179 t->border_fallback = (is_clamp && is_clamp_to_border);
180 }
181
182 static void r200SetTexMaxAnisotropy( r200TexObjPtr t, GLfloat max )
183 {
184 t->pp_txfilter &= ~R200_MAX_ANISO_MASK;
185
186 if ( max <= 1.0 ) {
187 t->pp_txfilter |= R200_MAX_ANISO_1_TO_1;
188 } else if ( max <= 2.0 ) {
189 t->pp_txfilter |= R200_MAX_ANISO_2_TO_1;
190 } else if ( max <= 4.0 ) {
191 t->pp_txfilter |= R200_MAX_ANISO_4_TO_1;
192 } else if ( max <= 8.0 ) {
193 t->pp_txfilter |= R200_MAX_ANISO_8_TO_1;
194 } else {
195 t->pp_txfilter |= R200_MAX_ANISO_16_TO_1;
196 }
197 }
198
199 /**
200 * Set the texture magnification and minification modes.
201 *
202 * \param t Texture whose filter modes are to be set
203 * \param minf Texture minification mode
204 * \param magf Texture magnification mode
205 */
206
207 static void r200SetTexFilter( r200TexObjPtr t, GLenum minf, GLenum magf )
208 {
209 GLuint anisotropy = (t->pp_txfilter & R200_MAX_ANISO_MASK);
210
211 t->pp_txfilter &= ~(R200_MIN_FILTER_MASK | R200_MAG_FILTER_MASK);
212 t->pp_txformat_x &= ~R200_VOLUME_FILTER_MASK;
213
214 if ( anisotropy == R200_MAX_ANISO_1_TO_1 ) {
215 switch ( minf ) {
216 case GL_NEAREST:
217 t->pp_txfilter |= R200_MIN_FILTER_NEAREST;
218 break;
219 case GL_LINEAR:
220 t->pp_txfilter |= R200_MIN_FILTER_LINEAR;
221 break;
222 case GL_NEAREST_MIPMAP_NEAREST:
223 t->pp_txfilter |= R200_MIN_FILTER_NEAREST_MIP_NEAREST;
224 break;
225 case GL_NEAREST_MIPMAP_LINEAR:
226 t->pp_txfilter |= R200_MIN_FILTER_LINEAR_MIP_NEAREST;
227 break;
228 case GL_LINEAR_MIPMAP_NEAREST:
229 t->pp_txfilter |= R200_MIN_FILTER_NEAREST_MIP_LINEAR;
230 break;
231 case GL_LINEAR_MIPMAP_LINEAR:
232 t->pp_txfilter |= R200_MIN_FILTER_LINEAR_MIP_LINEAR;
233 break;
234 }
235 } else {
236 switch ( minf ) {
237 case GL_NEAREST:
238 t->pp_txfilter |= R200_MIN_FILTER_ANISO_NEAREST;
239 break;
240 case GL_LINEAR:
241 t->pp_txfilter |= R200_MIN_FILTER_ANISO_LINEAR;
242 break;
243 case GL_NEAREST_MIPMAP_NEAREST:
244 case GL_LINEAR_MIPMAP_NEAREST:
245 t->pp_txfilter |= R200_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST;
246 break;
247 case GL_NEAREST_MIPMAP_LINEAR:
248 case GL_LINEAR_MIPMAP_LINEAR:
249 t->pp_txfilter |= R200_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR;
250 break;
251 }
252 }
253
254 /* Note we don't have 3D mipmaps so only use the mag filter setting
255 * to set the 3D texture filter mode.
256 */
257 switch ( magf ) {
258 case GL_NEAREST:
259 t->pp_txfilter |= R200_MAG_FILTER_NEAREST;
260 t->pp_txformat_x |= R200_VOLUME_FILTER_NEAREST;
261 break;
262 case GL_LINEAR:
263 t->pp_txfilter |= R200_MAG_FILTER_LINEAR;
264 t->pp_txformat_x |= R200_VOLUME_FILTER_LINEAR;
265 break;
266 }
267 }
268
269 static void r200SetTexBorderColor( r200TexObjPtr t, GLubyte c[4] )
270 {
271 t->pp_border_color = r200PackColor( 4, c[0], c[1], c[2], c[3] );
272 }
273
274
275 /**
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.
279 */
280
281 static r200TexObjPtr r200AllocTexObj( struct gl_texture_object *texObj )
282 {
283 r200TexObjPtr t;
284
285 t = CALLOC_STRUCT( r200_tex_obj );
286 texObj->DriverData = t;
287 if ( t != NULL ) {
288 if ( R200_DEBUG & DEBUG_TEXTURE ) {
289 fprintf( stderr, "%s( %p, %p )\n", __FUNCTION__, (void *)texObj,
290 (void *)t );
291 }
292
293 /* Initialize non-image-dependent parts of the state:
294 */
295 t->base.tObj = texObj;
296 t->border_fallback = GL_FALSE;
297
298 make_empty_list( & t->base );
299
300 r200SetTexWrap( t, texObj->WrapS, texObj->WrapT, texObj->WrapR );
301 r200SetTexMaxAnisotropy( t, texObj->MaxAnisotropy );
302 r200SetTexFilter( t, texObj->MinFilter, texObj->MagFilter );
303 r200SetTexBorderColor( t, texObj->_BorderChan );
304 }
305
306 return t;
307 }
308
309 /* try to find a format which will only need a memcopy */
310 static const struct gl_texture_format *
311 r200Choose8888TexFormat( GLenum srcFormat, GLenum srcType )
312 {
313 const GLuint ui = 1;
314 const GLubyte littleEndian = *((const GLubyte *) &ui);
315
316 if ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8) ||
317 (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE && !littleEndian) ||
318 (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) ||
319 (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && littleEndian)) {
320 return &_mesa_texformat_rgba8888;
321 }
322 else if ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) ||
323 (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE && littleEndian) ||
324 (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8) ||
325 (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && !littleEndian)) {
326 return &_mesa_texformat_rgba8888_rev;
327 }
328 else return _dri_texformat_argb8888;
329 }
330
331 static const struct gl_texture_format *
332 r200ChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
333 GLenum format, GLenum type )
334 {
335 r200ContextPtr rmesa = R200_CONTEXT(ctx);
336 const GLboolean do32bpt =
337 ( rmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_32 );
338 const GLboolean force16bpt =
339 ( rmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FORCE_16 );
340 (void) format;
341
342 switch ( internalFormat ) {
343 case 4:
344 case GL_RGBA:
345 case GL_COMPRESSED_RGBA:
346 switch ( type ) {
347 case GL_UNSIGNED_INT_10_10_10_2:
348 case GL_UNSIGNED_INT_2_10_10_10_REV:
349 return do32bpt ? _dri_texformat_argb8888 : _dri_texformat_argb1555;
350 case GL_UNSIGNED_SHORT_4_4_4_4:
351 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
352 return _dri_texformat_argb4444;
353 case GL_UNSIGNED_SHORT_5_5_5_1:
354 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
355 return _dri_texformat_argb1555;
356 default:
357 return do32bpt ?
358 r200Choose8888TexFormat(format, type) : _dri_texformat_argb4444;
359 }
360
361 case 3:
362 case GL_RGB:
363 case GL_COMPRESSED_RGB:
364 switch ( type ) {
365 case GL_UNSIGNED_SHORT_4_4_4_4:
366 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
367 return _dri_texformat_argb4444;
368 case GL_UNSIGNED_SHORT_5_5_5_1:
369 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
370 return _dri_texformat_argb1555;
371 case GL_UNSIGNED_SHORT_5_6_5:
372 case GL_UNSIGNED_SHORT_5_6_5_REV:
373 return _dri_texformat_rgb565;
374 default:
375 return do32bpt ? _dri_texformat_argb8888 : _dri_texformat_rgb565;
376 }
377
378 case GL_RGBA8:
379 case GL_RGB10_A2:
380 case GL_RGBA12:
381 case GL_RGBA16:
382 return !force16bpt ?
383 r200Choose8888TexFormat(format, type) : _dri_texformat_argb4444;
384
385 case GL_RGBA4:
386 case GL_RGBA2:
387 return _dri_texformat_argb4444;
388
389 case GL_RGB5_A1:
390 return _dri_texformat_argb1555;
391
392 case GL_RGB8:
393 case GL_RGB10:
394 case GL_RGB12:
395 case GL_RGB16:
396 return !force16bpt ? _dri_texformat_argb8888 : _dri_texformat_rgb565;
397
398 case GL_RGB5:
399 case GL_RGB4:
400 case GL_R3_G3_B2:
401 return _dri_texformat_rgb565;
402
403 case GL_ALPHA:
404 case GL_ALPHA4:
405 case GL_ALPHA8:
406 case GL_ALPHA12:
407 case GL_ALPHA16:
408 case GL_COMPRESSED_ALPHA:
409 /* can't use a8 format since interpreting hw I8 as a8 would result
410 in wrong rgb values (same as alpha value instead of 0). */
411 return _dri_texformat_al88;
412
413 case 1:
414 case GL_LUMINANCE:
415 case GL_LUMINANCE4:
416 case GL_LUMINANCE8:
417 case GL_LUMINANCE12:
418 case GL_LUMINANCE16:
419 case GL_COMPRESSED_LUMINANCE:
420 return _dri_texformat_l8;
421
422 case 2:
423 case GL_LUMINANCE_ALPHA:
424 case GL_LUMINANCE4_ALPHA4:
425 case GL_LUMINANCE6_ALPHA2:
426 case GL_LUMINANCE8_ALPHA8:
427 case GL_LUMINANCE12_ALPHA4:
428 case GL_LUMINANCE12_ALPHA12:
429 case GL_LUMINANCE16_ALPHA16:
430 case GL_COMPRESSED_LUMINANCE_ALPHA:
431 return _dri_texformat_al88;
432
433 case GL_INTENSITY:
434 case GL_INTENSITY4:
435 case GL_INTENSITY8:
436 case GL_INTENSITY12:
437 case GL_INTENSITY16:
438 case GL_COMPRESSED_INTENSITY:
439 return _dri_texformat_i8;
440
441 case GL_YCBCR_MESA:
442 if (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
443 type == GL_UNSIGNED_BYTE)
444 return &_mesa_texformat_ycbcr;
445 else
446 return &_mesa_texformat_ycbcr_rev;
447
448 case GL_RGB_S3TC:
449 case GL_RGB4_S3TC:
450 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
451 return &_mesa_texformat_rgb_dxt1;
452
453 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
454 return &_mesa_texformat_rgba_dxt1;
455
456 case GL_RGBA_S3TC:
457 case GL_RGBA4_S3TC:
458 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
459 return &_mesa_texformat_rgba_dxt3;
460
461 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
462 return &_mesa_texformat_rgba_dxt5;
463
464 default:
465 _mesa_problem(ctx,
466 "unexpected internalFormat 0x%x in r200ChooseTextureFormat",
467 (int) internalFormat);
468 return NULL;
469 }
470
471 return NULL; /* never get here */
472 }
473
474
475 static GLboolean
476 r200ValidateClientStorage( GLcontext *ctx, GLenum target,
477 GLint internalFormat,
478 GLint srcWidth, GLint srcHeight,
479 GLenum format, GLenum type, const void *pixels,
480 const struct gl_pixelstore_attrib *packing,
481 struct gl_texture_object *texObj,
482 struct gl_texture_image *texImage)
483
484 {
485 r200ContextPtr rmesa = R200_CONTEXT(ctx);
486
487 if ( R200_DEBUG & DEBUG_TEXTURE )
488 fprintf(stderr, "intformat %s format %s type %s\n",
489 _mesa_lookup_enum_by_nr( internalFormat ),
490 _mesa_lookup_enum_by_nr( format ),
491 _mesa_lookup_enum_by_nr( type ));
492
493 if (!ctx->Unpack.ClientStorage)
494 return 0;
495
496 if (ctx->_ImageTransferState ||
497 texImage->IsCompressed ||
498 texObj->GenerateMipmap)
499 return 0;
500
501
502 /* This list is incomplete, may be different on ppc???
503 */
504 switch ( internalFormat ) {
505 case GL_RGBA:
506 if ( format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8_REV ) {
507 texImage->TexFormat = _dri_texformat_argb8888;
508 }
509 else
510 return 0;
511 break;
512
513 case GL_RGB:
514 if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) {
515 texImage->TexFormat = _dri_texformat_rgb565;
516 }
517 else
518 return 0;
519 break;
520
521 case GL_YCBCR_MESA:
522 if ( format == GL_YCBCR_MESA &&
523 type == GL_UNSIGNED_SHORT_8_8_REV_APPLE ) {
524 texImage->TexFormat = &_mesa_texformat_ycbcr_rev;
525 }
526 else if ( format == GL_YCBCR_MESA &&
527 (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
528 type == GL_UNSIGNED_BYTE)) {
529 texImage->TexFormat = &_mesa_texformat_ycbcr;
530 }
531 else
532 return 0;
533 break;
534
535 default:
536 return 0;
537 }
538
539 /* Could deal with these packing issues, but currently don't:
540 */
541 if (packing->SkipPixels ||
542 packing->SkipRows ||
543 packing->SwapBytes ||
544 packing->LsbFirst) {
545 return 0;
546 }
547
548 {
549 GLint srcRowStride = _mesa_image_row_stride(packing, srcWidth,
550 format, type);
551
552
553 if ( R200_DEBUG & DEBUG_TEXTURE )
554 fprintf(stderr, "%s: srcRowStride %d/%x\n",
555 __FUNCTION__, srcRowStride, srcRowStride);
556
557 /* Could check this later in upload, pitch restrictions could be
558 * relaxed, but would need to store the image pitch somewhere,
559 * as packing details might change before image is uploaded:
560 */
561 if (!r200IsGartMemory( rmesa, pixels, srcHeight * srcRowStride ) ||
562 (srcRowStride & 63))
563 return 0;
564
565
566 /* Have validated that _mesa_transfer_teximage would be a straight
567 * memcpy at this point. NOTE: future calls to TexSubImage will
568 * overwrite the client data. This is explicitly mentioned in the
569 * extension spec.
570 */
571 texImage->Data = (void *)pixels;
572 texImage->IsClientData = GL_TRUE;
573 texImage->RowStride = srcRowStride / texImage->TexFormat->TexelBytes;
574
575 return 1;
576 }
577 }
578
579
580 static void r200TexImage1D( GLcontext *ctx, GLenum target, GLint level,
581 GLint internalFormat,
582 GLint width, GLint border,
583 GLenum format, GLenum type, const GLvoid *pixels,
584 const struct gl_pixelstore_attrib *packing,
585 struct gl_texture_object *texObj,
586 struct gl_texture_image *texImage )
587 {
588 driTextureObject * t = (driTextureObject *) texObj->DriverData;
589
590 if ( t ) {
591 driSwapOutTextureObject( t );
592 }
593 else {
594 t = (driTextureObject *) r200AllocTexObj( texObj );
595 if (!t) {
596 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
597 return;
598 }
599 }
600
601 /* Note, this will call ChooseTextureFormat */
602 _mesa_store_teximage1d(ctx, target, level, internalFormat,
603 width, border, format, type, pixels,
604 &ctx->Unpack, texObj, texImage);
605
606 t->dirty_images[0] |= (1 << level);
607 }
608
609
610 static void r200TexSubImage1D( GLcontext *ctx, GLenum target, GLint level,
611 GLint xoffset,
612 GLsizei width,
613 GLenum format, GLenum type,
614 const GLvoid *pixels,
615 const struct gl_pixelstore_attrib *packing,
616 struct gl_texture_object *texObj,
617 struct gl_texture_image *texImage )
618 {
619 driTextureObject * t = (driTextureObject *) texObj->DriverData;
620
621 assert( t ); /* this _should_ be true */
622 if ( t ) {
623 driSwapOutTextureObject( t );
624 }
625 else {
626 t = (driTextureObject *) r200AllocTexObj( texObj );
627 if (!t) {
628 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
629 return;
630 }
631 }
632
633 _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
634 format, type, pixels, packing, texObj,
635 texImage);
636
637 t->dirty_images[0] |= (1 << level);
638 }
639
640
641 static void r200TexImage2D( GLcontext *ctx, GLenum target, GLint level,
642 GLint internalFormat,
643 GLint width, GLint height, GLint border,
644 GLenum format, GLenum type, const GLvoid *pixels,
645 const struct gl_pixelstore_attrib *packing,
646 struct gl_texture_object *texObj,
647 struct gl_texture_image *texImage )
648 {
649 driTextureObject * t = (driTextureObject *) texObj->DriverData;
650 GLuint face;
651
652 /* which cube face or ordinary 2D image */
653 switch (target) {
654 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
655 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
656 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
657 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
658 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
659 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
660 face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
661 ASSERT(face < 6);
662 break;
663 default:
664 face = 0;
665 }
666
667 if ( t != NULL ) {
668 driSwapOutTextureObject( t );
669 }
670 else {
671 t = (driTextureObject *) r200AllocTexObj( texObj );
672 if (!t) {
673 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
674 return;
675 }
676 }
677
678 texImage->IsClientData = GL_FALSE;
679
680 if (r200ValidateClientStorage( ctx, target,
681 internalFormat,
682 width, height,
683 format, type, pixels,
684 packing, texObj, texImage)) {
685 if (R200_DEBUG & DEBUG_TEXTURE)
686 fprintf(stderr, "%s: Using client storage\n", __FUNCTION__);
687 }
688 else {
689 if (R200_DEBUG & DEBUG_TEXTURE)
690 fprintf(stderr, "%s: Using normal storage\n", __FUNCTION__);
691
692 /* Normal path: copy (to cached memory) and eventually upload
693 * via another copy to GART memory and then a blit... Could
694 * eliminate one copy by going straight to (permanent) GART.
695 *
696 * Note, this will call r200ChooseTextureFormat.
697 */
698 _mesa_store_teximage2d(ctx, target, level, internalFormat,
699 width, height, border, format, type, pixels,
700 &ctx->Unpack, texObj, texImage);
701
702 t->dirty_images[face] |= (1 << level);
703 }
704 }
705
706
707 static void r200TexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
708 GLint xoffset, GLint yoffset,
709 GLsizei width, GLsizei height,
710 GLenum format, GLenum type,
711 const GLvoid *pixels,
712 const struct gl_pixelstore_attrib *packing,
713 struct gl_texture_object *texObj,
714 struct gl_texture_image *texImage )
715 {
716 driTextureObject * t = (driTextureObject *) texObj->DriverData;
717 GLuint face;
718
719 /* which cube face or ordinary 2D image */
720 switch (target) {
721 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
722 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
723 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
724 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
725 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
726 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
727 face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
728 ASSERT(face < 6);
729 break;
730 default:
731 face = 0;
732 }
733
734 assert( t ); /* this _should_ be true */
735 if ( t ) {
736 driSwapOutTextureObject( t );
737 }
738 else {
739 t = (driTextureObject *) r200AllocTexObj( texObj );
740 if (!t) {
741 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
742 return;
743 }
744 }
745
746 _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
747 height, format, type, pixels, packing, texObj,
748 texImage);
749
750 t->dirty_images[face] |= (1 << level);
751 }
752
753
754 static void r200CompressedTexImage2D( GLcontext *ctx, GLenum target, GLint level,
755 GLint internalFormat,
756 GLint width, GLint height, GLint border,
757 GLsizei imageSize, const GLvoid *data,
758 struct gl_texture_object *texObj,
759 struct gl_texture_image *texImage )
760 {
761 driTextureObject * t = (driTextureObject *) texObj->DriverData;
762 GLuint face;
763
764 /* which cube face or ordinary 2D image */
765 switch (target) {
766 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
767 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
768 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
769 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
770 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
771 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
772 face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
773 ASSERT(face < 6);
774 break;
775 default:
776 face = 0;
777 }
778
779 if ( t != NULL ) {
780 driSwapOutTextureObject( t );
781 }
782 else {
783 t = (driTextureObject *) r200AllocTexObj( texObj );
784 if (!t) {
785 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
786 return;
787 }
788 }
789
790 texImage->IsClientData = GL_FALSE;
791 /* can't call this, different parameters. Would never evaluate to true anyway currently
792 if (r200ValidateClientStorage( ctx, target,
793 internalFormat,
794 width, height,
795 format, type, pixels,
796 packing, texObj, texImage)) {
797 if (R200_DEBUG & DEBUG_TEXTURE)
798 fprintf(stderr, "%s: Using client storage\n", __FUNCTION__);
799 }
800 else */{
801 if (R200_DEBUG & DEBUG_TEXTURE)
802 fprintf(stderr, "%s: Using normal storage\n", __FUNCTION__);
803
804 /* Normal path: copy (to cached memory) and eventually upload
805 * via another copy to GART memory and then a blit... Could
806 * eliminate one copy by going straight to (permanent) GART.
807 *
808 * Note, this will call r200ChooseTextureFormat.
809 */
810 _mesa_store_compressed_teximage2d(ctx, target, level, internalFormat, width,
811 height, border, imageSize, data, texObj, texImage);
812
813 t->dirty_images[face] |= (1 << level);
814 }
815 }
816
817
818 static void r200CompressedTexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
819 GLint xoffset, GLint yoffset,
820 GLsizei width, GLsizei height,
821 GLenum format,
822 GLsizei imageSize, const GLvoid *data,
823 struct gl_texture_object *texObj,
824 struct gl_texture_image *texImage )
825 {
826 driTextureObject * t = (driTextureObject *) texObj->DriverData;
827 GLuint face;
828
829
830 /* which cube face or ordinary 2D image */
831 switch (target) {
832 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
833 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
834 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
835 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
836 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
837 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
838 face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
839 ASSERT(face < 6);
840 break;
841 default:
842 face = 0;
843 }
844
845 assert( t ); /* this _should_ be true */
846 if ( t ) {
847 driSwapOutTextureObject( t );
848 }
849 else {
850 t = (driTextureObject *) r200AllocTexObj( texObj );
851 if (!t) {
852 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexSubImage2D");
853 return;
854 }
855 }
856
857 _mesa_store_compressed_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
858 height, format, imageSize, data, texObj, texImage);
859
860 t->dirty_images[face] |= (1 << level);
861 }
862
863
864 #if ENABLE_HW_3D_TEXTURE
865 static void r200TexImage3D( GLcontext *ctx, GLenum target, GLint level,
866 GLint internalFormat,
867 GLint width, GLint height, GLint depth,
868 GLint border,
869 GLenum format, GLenum type, const GLvoid *pixels,
870 const struct gl_pixelstore_attrib *packing,
871 struct gl_texture_object *texObj,
872 struct gl_texture_image *texImage )
873 {
874 driTextureObject * t = (driTextureObject *) texObj->DriverData;
875
876 if ( t ) {
877 driSwapOutTextureObject( t );
878 }
879 else {
880 t = (driTextureObject *) r200AllocTexObj( texObj );
881 if (!t) {
882 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
883 return;
884 }
885 }
886
887 texImage->IsClientData = GL_FALSE;
888
889 #if 0
890 if (r200ValidateClientStorage( ctx, target,
891 internalFormat,
892 width, height,
893 format, type, pixels,
894 packing, texObj, texImage)) {
895 if (R200_DEBUG & DEBUG_TEXTURE)
896 fprintf(stderr, "%s: Using client storage\n", __FUNCTION__);
897 }
898 else
899 #endif
900 {
901 if (R200_DEBUG & DEBUG_TEXTURE)
902 fprintf(stderr, "%s: Using normal storage\n", __FUNCTION__);
903
904 /* Normal path: copy (to cached memory) and eventually upload
905 * via another copy to GART memory and then a blit... Could
906 * eliminate one copy by going straight to (permanent) GART.
907 *
908 * Note, this will call r200ChooseTextureFormat.
909 */
910 _mesa_store_teximage3d(ctx, target, level, internalFormat,
911 width, height, depth, border,
912 format, type, pixels,
913 &ctx->Unpack, texObj, texImage);
914
915 t->dirty_images[0] |= (1 << level);
916 }
917 }
918 #endif
919
920
921 #if ENABLE_HW_3D_TEXTURE
922 static void
923 r200TexSubImage3D( GLcontext *ctx, GLenum target, GLint level,
924 GLint xoffset, GLint yoffset, GLint zoffset,
925 GLsizei width, GLsizei height, GLsizei depth,
926 GLenum format, GLenum type,
927 const GLvoid *pixels,
928 const struct gl_pixelstore_attrib *packing,
929 struct gl_texture_object *texObj,
930 struct gl_texture_image *texImage )
931 {
932 driTextureObject * t = (driTextureObject *) texObj->DriverData;
933
934 /* fprintf(stderr, "%s\n", __FUNCTION__); */
935
936 assert( t ); /* this _should_ be true */
937 if ( t ) {
938 driSwapOutTextureObject( t );
939 }
940 else {
941 t = (driTextureObject *) r200AllocTexObj( texObj );
942 if (!t) {
943 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage3D");
944 return;
945 }
946 texObj->DriverData = t;
947 }
948
949 _mesa_store_texsubimage3d(ctx, target, level, xoffset, yoffset, zoffset,
950 width, height, depth,
951 format, type, pixels, packing, texObj, texImage);
952
953 t->dirty_images[0] |= (1 << level);
954 }
955 #endif
956
957
958
959 static void r200TexEnv( GLcontext *ctx, GLenum target,
960 GLenum pname, const GLfloat *param )
961 {
962 r200ContextPtr rmesa = R200_CONTEXT(ctx);
963 GLuint unit = ctx->Texture.CurrentUnit;
964 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
965
966 if ( R200_DEBUG & DEBUG_STATE ) {
967 fprintf( stderr, "%s( %s )\n",
968 __FUNCTION__, _mesa_lookup_enum_by_nr( pname ) );
969 }
970
971 /* This is incorrect: Need to maintain this data for each of
972 * GL_TEXTURE_{123}D, GL_TEXTURE_RECTANGLE_NV, etc, and switch
973 * between them according to _ReallyEnabled.
974 */
975 switch ( pname ) {
976 case GL_TEXTURE_ENV_COLOR: {
977 GLubyte c[4];
978 GLuint envColor;
979 UNCLAMPED_FLOAT_TO_RGBA_CHAN( c, texUnit->EnvColor );
980 envColor = r200PackColor( 4, c[0], c[1], c[2], c[3] );
981 if ( rmesa->hw.tf.cmd[TF_TFACTOR_0 + unit] != envColor ) {
982 R200_STATECHANGE( rmesa, tf );
983 rmesa->hw.tf.cmd[TF_TFACTOR_0 + unit] = envColor;
984 }
985 break;
986 }
987
988 case GL_TEXTURE_LOD_BIAS_EXT: {
989 GLfloat bias, min;
990 GLuint b;
991 const int fixed_one = 0x8000000;
992
993 /* The R200's LOD bias is a signed 2's complement value with a
994 * range of -16.0 <= bias < 16.0.
995 *
996 * NOTE: Add a small bias to the bias for conform mipsel.c test.
997 */
998 bias = *param + .01;
999 min = driQueryOptionb (&rmesa->optionCache, "no_neg_lod_bias") ?
1000 0.0 : -16.0;
1001 bias = CLAMP( bias, min, 16.0 );
1002 b = (int)(bias * fixed_one) & R200_LOD_BIAS_MASK;
1003
1004 if ( (rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT_X] & R200_LOD_BIAS_MASK) != b ) {
1005 R200_STATECHANGE( rmesa, tex[unit] );
1006 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT_X] &= ~R200_LOD_BIAS_MASK;
1007 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT_X] |= b;
1008 }
1009 break;
1010 }
1011 case GL_COORD_REPLACE_ARB:
1012 if (ctx->Point.PointSprite) {
1013 R200_STATECHANGE( rmesa, spr );
1014 if ((GLenum)param[0]) {
1015 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |= R200_PS_GEN_TEX_0 << unit;
1016 } else {
1017 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] &= ~(R200_PS_GEN_TEX_0 << unit);
1018 }
1019 }
1020 break;
1021 default:
1022 return;
1023 }
1024 }
1025
1026
1027 /**
1028 * Changes variables and flags for a state update, which will happen at the
1029 * next UpdateTextureState
1030 */
1031
1032 static void r200TexParameter( GLcontext *ctx, GLenum target,
1033 struct gl_texture_object *texObj,
1034 GLenum pname, const GLfloat *params )
1035 {
1036 r200TexObjPtr t = (r200TexObjPtr) texObj->DriverData;
1037
1038 if ( R200_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) {
1039 fprintf( stderr, "%s( %s )\n", __FUNCTION__,
1040 _mesa_lookup_enum_by_nr( pname ) );
1041 }
1042
1043 switch ( pname ) {
1044 case GL_TEXTURE_MIN_FILTER:
1045 case GL_TEXTURE_MAG_FILTER:
1046 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1047 r200SetTexMaxAnisotropy( t, texObj->MaxAnisotropy );
1048 r200SetTexFilter( t, texObj->MinFilter, texObj->MagFilter );
1049 break;
1050
1051 case GL_TEXTURE_WRAP_S:
1052 case GL_TEXTURE_WRAP_T:
1053 case GL_TEXTURE_WRAP_R:
1054 r200SetTexWrap( t, texObj->WrapS, texObj->WrapT, texObj->WrapR );
1055 break;
1056
1057 case GL_TEXTURE_BORDER_COLOR:
1058 r200SetTexBorderColor( t, texObj->_BorderChan );
1059 break;
1060
1061 case GL_TEXTURE_BASE_LEVEL:
1062 case GL_TEXTURE_MAX_LEVEL:
1063 case GL_TEXTURE_MIN_LOD:
1064 case GL_TEXTURE_MAX_LOD:
1065 /* This isn't the most efficient solution but there doesn't appear to
1066 * be a nice alternative. Since there's no LOD clamping,
1067 * we just have to rely on loading the right subset of mipmap levels
1068 * to simulate a clamped LOD.
1069 */
1070 driSwapOutTextureObject( (driTextureObject *) t );
1071 break;
1072
1073 default:
1074 return;
1075 }
1076
1077 /* Mark this texobj as dirty (one bit per tex unit)
1078 */
1079 t->dirty_state = TEX_ALL;
1080 }
1081
1082
1083
1084 static void r200BindTexture( GLcontext *ctx, GLenum target,
1085 struct gl_texture_object *texObj )
1086 {
1087 if ( R200_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) {
1088 fprintf( stderr, "%s( %p ) unit=%d\n", __FUNCTION__, (void *)texObj,
1089 ctx->Texture.CurrentUnit );
1090 }
1091
1092 if ( (target == GL_TEXTURE_1D)
1093 || (target == GL_TEXTURE_2D)
1094 #if ENABLE_HW_3D_TEXTURE
1095 || (target == GL_TEXTURE_3D)
1096 #endif
1097 || (target == GL_TEXTURE_CUBE_MAP)
1098 || (target == GL_TEXTURE_RECTANGLE_NV) ) {
1099 assert( texObj->DriverData != NULL );
1100 }
1101 }
1102
1103
1104 static void r200DeleteTexture( GLcontext *ctx,
1105 struct gl_texture_object *texObj )
1106 {
1107 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1108 driTextureObject * t = (driTextureObject *) texObj->DriverData;
1109
1110 if ( R200_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) {
1111 fprintf( stderr, "%s( %p (target = %s) )\n", __FUNCTION__, (void *)texObj,
1112 _mesa_lookup_enum_by_nr( texObj->Target ) );
1113 }
1114
1115 if ( t != NULL ) {
1116 if ( rmesa ) {
1117 R200_FIREVERTICES( rmesa );
1118 }
1119
1120 driDestroyTextureObject( t );
1121 }
1122 /* Free mipmap images and the texture object itself */
1123 _mesa_delete_texture_object(ctx, texObj);
1124 }
1125
1126 /* Need:
1127 * - Same GEN_MODE for all active bits
1128 * - Same EyePlane/ObjPlane for all active bits when using Eye/Obj
1129 * - STRQ presumably all supported (matrix means incoming R values
1130 * can end up in STQ, this has implications for vertex support,
1131 * presumably ok if maos is used, though?)
1132 *
1133 * Basically impossible to do this on the fly - just collect some
1134 * basic info & do the checks from ValidateState().
1135 */
1136 static void r200TexGen( GLcontext *ctx,
1137 GLenum coord,
1138 GLenum pname,
1139 const GLfloat *params )
1140 {
1141 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1142 GLuint unit = ctx->Texture.CurrentUnit;
1143 rmesa->recheck_texgen[unit] = GL_TRUE;
1144 }
1145
1146
1147 /**
1148 * Allocate a new texture object.
1149 * Called via ctx->Driver.NewTextureObject.
1150 * Note: this function will be called during context creation to
1151 * allocate the default texture objects.
1152 * Note: we could use containment here to 'derive' the driver-specific
1153 * texture object from the core mesa gl_texture_object. Not done at this time.
1154 * Fixup MaxAnisotropy according to user preference.
1155 */
1156 static struct gl_texture_object *
1157 r200NewTextureObject( GLcontext *ctx, GLuint name, GLenum target )
1158 {
1159 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1160 struct gl_texture_object *obj;
1161 obj = _mesa_new_texture_object(ctx, name, target);
1162 if (!obj)
1163 return NULL;
1164 obj->MaxAnisotropy = rmesa->initialMaxAnisotropy;
1165 r200AllocTexObj( obj );
1166 return obj;
1167 }
1168
1169
1170 void r200InitTextureFuncs( struct dd_function_table *functions )
1171 {
1172 /* Note: we only plug in the functions we implement in the driver
1173 * since _mesa_init_driver_functions() was already called.
1174 */
1175 functions->ChooseTextureFormat = r200ChooseTextureFormat;
1176 functions->TexImage1D = r200TexImage1D;
1177 functions->TexImage2D = r200TexImage2D;
1178 #if ENABLE_HW_3D_TEXTURE
1179 functions->TexImage3D = r200TexImage3D;
1180 #else
1181 functions->TexImage3D = _mesa_store_teximage3d;
1182 #endif
1183 functions->TexSubImage1D = r200TexSubImage1D;
1184 functions->TexSubImage2D = r200TexSubImage2D;
1185 #if ENABLE_HW_3D_TEXTURE
1186 functions->TexSubImage3D = r200TexSubImage3D;
1187 #else
1188 functions->TexSubImage3D = _mesa_store_texsubimage3d;
1189 #endif
1190 functions->NewTextureObject = r200NewTextureObject;
1191 functions->BindTexture = r200BindTexture;
1192 functions->DeleteTexture = r200DeleteTexture;
1193 functions->IsTextureResident = driIsTextureResident;
1194
1195 functions->TexEnv = r200TexEnv;
1196 functions->TexParameter = r200TexParameter;
1197 functions->TexGen = r200TexGen;
1198
1199 functions->CompressedTexImage2D = r200CompressedTexImage2D;
1200 functions->CompressedTexSubImage2D = r200CompressedTexSubImage2D;
1201
1202 driInitTextureFormats();
1203
1204 #if 000
1205 /* moved or obsolete code */
1206 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1207 driInitTextureObjects( ctx, & rmesa->swapped,
1208 DRI_TEXMGR_DO_TEXTURE_1D
1209 | DRI_TEXMGR_DO_TEXTURE_2D );
1210
1211 /* Hack: r200NewTextureObject is not yet installed when the
1212 * default textures are created. Therefore set MaxAnisotropy of the
1213 * default 2D texture now. */
1214 ctx->Shared->Default2D->MaxAnisotropy = driQueryOptionf (&rmesa->optionCache,
1215 "def_max_anisotropy");
1216 #endif
1217 }