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