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