fix up radeon span functions using latest r200 code from Brian,
[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 ? _dri_texformat_argb8888 : _dri_texformat_argb1555;
328 case GL_UNSIGNED_SHORT_4_4_4_4:
329 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
330 return _dri_texformat_argb4444;
331 case GL_UNSIGNED_SHORT_5_5_5_1:
332 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
333 return _dri_texformat_argb1555;
334 default:
335 return do32bpt ? _dri_texformat_rgba8888 : _dri_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 _dri_texformat_argb4444;
345 case GL_UNSIGNED_SHORT_5_5_5_1:
346 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
347 return _dri_texformat_argb1555;
348 case GL_UNSIGNED_SHORT_5_6_5:
349 case GL_UNSIGNED_SHORT_5_6_5_REV:
350 return _dri_texformat_rgb565;
351 default:
352 return do32bpt ? _dri_texformat_rgba8888 : _dri_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 _dri_texformat_rgba8888 : _dri_texformat_argb4444;
361
362 case GL_RGBA4:
363 case GL_RGBA2:
364 return _dri_texformat_argb4444;
365
366 case GL_RGB5_A1:
367 return _dri_texformat_argb1555;
368
369 case GL_RGB8:
370 case GL_RGB10:
371 case GL_RGB12:
372 case GL_RGB16:
373 return !force16bpt ? _dri_texformat_rgba8888 : _dri_texformat_rgb565;
374
375 case GL_RGB5:
376 case GL_RGB4:
377 case GL_R3_G3_B2:
378 return _dri_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 _dri_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 _dri_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 _dri_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 _dri_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 case GL_RGB_S3TC:
424 case GL_RGB4_S3TC:
425 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
426 return &_mesa_texformat_rgb_dxt1;
427
428 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
429 return &_mesa_texformat_rgba_dxt1;
430
431 case GL_RGBA_S3TC:
432 case GL_RGBA4_S3TC:
433 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
434 return &_mesa_texformat_rgba_dxt3;
435
436 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
437 return &_mesa_texformat_rgba_dxt5;
438
439 default:
440 _mesa_problem(ctx,
441 "unexpected internalFormat 0x%x in r200ChooseTextureFormat",
442 (int) internalFormat);
443 return NULL;
444 }
445
446 return NULL; /* never get here */
447 }
448
449
450 static GLboolean
451 r200ValidateClientStorage( GLcontext *ctx, GLenum target,
452 GLint internalFormat,
453 GLint srcWidth, GLint srcHeight,
454 GLenum format, GLenum type, const void *pixels,
455 const struct gl_pixelstore_attrib *packing,
456 struct gl_texture_object *texObj,
457 struct gl_texture_image *texImage)
458
459 {
460 r200ContextPtr rmesa = R200_CONTEXT(ctx);
461
462 if (0)
463 fprintf(stderr, "intformat %s format %s type %s\n",
464 _mesa_lookup_enum_by_nr( internalFormat ),
465 _mesa_lookup_enum_by_nr( format ),
466 _mesa_lookup_enum_by_nr( type ));
467
468 if (!ctx->Unpack.ClientStorage)
469 return 0;
470
471 if (ctx->_ImageTransferState ||
472 texImage->IsCompressed ||
473 texObj->GenerateMipmap)
474 return 0;
475
476
477 /* This list is incomplete, may be different on ppc???
478 */
479 switch ( internalFormat ) {
480 case GL_RGBA:
481 if ( format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8_REV ) {
482 texImage->TexFormat = _dri_texformat_argb8888;
483 }
484 else
485 return 0;
486 break;
487
488 case GL_RGB:
489 if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) {
490 texImage->TexFormat = _dri_texformat_rgb565;
491 }
492 else
493 return 0;
494 break;
495
496 case GL_YCBCR_MESA:
497 if ( format == GL_YCBCR_MESA &&
498 type == GL_UNSIGNED_SHORT_8_8_REV_APPLE ) {
499 texImage->TexFormat = &_mesa_texformat_ycbcr_rev;
500 }
501 else if ( format == GL_YCBCR_MESA &&
502 (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
503 type == GL_UNSIGNED_BYTE)) {
504 texImage->TexFormat = &_mesa_texformat_ycbcr;
505 }
506 else
507 return 0;
508 break;
509
510 default:
511 return 0;
512 }
513
514 /* Could deal with these packing issues, but currently don't:
515 */
516 if (packing->SkipPixels ||
517 packing->SkipRows ||
518 packing->SwapBytes ||
519 packing->LsbFirst) {
520 return 0;
521 }
522
523 {
524 GLint srcRowStride = _mesa_image_row_stride(packing, srcWidth,
525 format, type);
526
527
528 if (0)
529 fprintf(stderr, "%s: srcRowStride %d/%x\n",
530 __FUNCTION__, srcRowStride, srcRowStride);
531
532 /* Could check this later in upload, pitch restrictions could be
533 * relaxed, but would need to store the image pitch somewhere,
534 * as packing details might change before image is uploaded:
535 */
536 if (!r200IsGartMemory( rmesa, pixels, srcHeight * srcRowStride ) ||
537 (srcRowStride & 63))
538 return 0;
539
540
541 /* Have validated that _mesa_transfer_teximage would be a straight
542 * memcpy at this point. NOTE: future calls to TexSubImage will
543 * overwrite the client data. This is explicitly mentioned in the
544 * extension spec.
545 */
546 texImage->Data = (void *)pixels;
547 texImage->IsClientData = GL_TRUE;
548 texImage->RowStride = srcRowStride / texImage->TexFormat->TexelBytes;
549
550 return 1;
551 }
552 }
553
554
555 static void r200TexImage1D( GLcontext *ctx, GLenum target, GLint level,
556 GLint internalFormat,
557 GLint width, GLint border,
558 GLenum format, GLenum type, const GLvoid *pixels,
559 const struct gl_pixelstore_attrib *packing,
560 struct gl_texture_object *texObj,
561 struct gl_texture_image *texImage )
562 {
563 driTextureObject * t = (driTextureObject *) texObj->DriverData;
564
565 if ( t ) {
566 driSwapOutTextureObject( t );
567 }
568 else {
569 t = (driTextureObject *) r200AllocTexObj( texObj );
570 if (!t) {
571 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
572 return;
573 }
574 }
575
576 /* Note, this will call ChooseTextureFormat */
577 _mesa_store_teximage1d(ctx, target, level, internalFormat,
578 width, border, format, type, pixels,
579 &ctx->Unpack, texObj, texImage);
580
581 t->dirty_images[0] |= (1 << level);
582 }
583
584
585 static void r200TexSubImage1D( GLcontext *ctx, GLenum target, GLint level,
586 GLint xoffset,
587 GLsizei width,
588 GLenum format, GLenum type,
589 const GLvoid *pixels,
590 const struct gl_pixelstore_attrib *packing,
591 struct gl_texture_object *texObj,
592 struct gl_texture_image *texImage )
593 {
594 driTextureObject * t = (driTextureObject *) texObj->DriverData;
595
596 assert( t ); /* this _should_ be true */
597 if ( t ) {
598 driSwapOutTextureObject( t );
599 }
600 else {
601 t = (driTextureObject *) r200AllocTexObj( texObj );
602 if (!t) {
603 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
604 return;
605 }
606 }
607
608 _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
609 format, type, pixels, packing, texObj,
610 texImage);
611
612 t->dirty_images[0] |= (1 << level);
613 }
614
615
616 static void r200TexImage2D( GLcontext *ctx, GLenum target, GLint level,
617 GLint internalFormat,
618 GLint width, GLint height, GLint border,
619 GLenum format, GLenum type, const GLvoid *pixels,
620 const struct gl_pixelstore_attrib *packing,
621 struct gl_texture_object *texObj,
622 struct gl_texture_image *texImage )
623 {
624 driTextureObject * t = (driTextureObject *) texObj->DriverData;
625 GLuint face;
626
627 /* which cube face or ordinary 2D image */
628 switch (target) {
629 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
630 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
631 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
632 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
633 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
634 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
635 face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
636 ASSERT(face < 6);
637 break;
638 default:
639 face = 0;
640 }
641
642 if ( t != NULL ) {
643 driSwapOutTextureObject( t );
644 }
645 else {
646 t = (driTextureObject *) r200AllocTexObj( texObj );
647 if (!t) {
648 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
649 return;
650 }
651 }
652
653 texImage->IsClientData = GL_FALSE;
654
655 if (r200ValidateClientStorage( ctx, target,
656 internalFormat,
657 width, height,
658 format, type, pixels,
659 packing, texObj, texImage)) {
660 if (R200_DEBUG & DEBUG_TEXTURE)
661 fprintf(stderr, "%s: Using client storage\n", __FUNCTION__);
662 }
663 else {
664 if (R200_DEBUG & DEBUG_TEXTURE)
665 fprintf(stderr, "%s: Using normal storage\n", __FUNCTION__);
666
667 /* Normal path: copy (to cached memory) and eventually upload
668 * via another copy to GART memory and then a blit... Could
669 * eliminate one copy by going straight to (permanent) GART.
670 *
671 * Note, this will call r200ChooseTextureFormat.
672 */
673 _mesa_store_teximage2d(ctx, target, level, internalFormat,
674 width, height, border, format, type, pixels,
675 &ctx->Unpack, texObj, texImage);
676
677 t->dirty_images[face] |= (1 << level);
678 }
679 }
680
681
682 static void r200TexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
683 GLint xoffset, GLint yoffset,
684 GLsizei width, GLsizei height,
685 GLenum format, GLenum type,
686 const GLvoid *pixels,
687 const struct gl_pixelstore_attrib *packing,
688 struct gl_texture_object *texObj,
689 struct gl_texture_image *texImage )
690 {
691 driTextureObject * t = (driTextureObject *) texObj->DriverData;
692 GLuint face;
693
694 /* which cube face or ordinary 2D image */
695 switch (target) {
696 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
697 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
698 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
699 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
700 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
701 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
702 face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
703 ASSERT(face < 6);
704 break;
705 default:
706 face = 0;
707 }
708
709 assert( t ); /* this _should_ be true */
710 if ( t ) {
711 driSwapOutTextureObject( t );
712 }
713 else {
714 t = (driTextureObject *) r200AllocTexObj( texObj );
715 if (!t) {
716 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
717 return;
718 }
719 }
720
721 _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
722 height, format, type, pixels, packing, texObj,
723 texImage);
724
725 t->dirty_images[face] |= (1 << level);
726 }
727
728
729 static void r200CompressedTexImage2D( GLcontext *ctx, GLenum target, GLint level,
730 GLint internalFormat,
731 GLint width, GLint height, GLint border,
732 GLsizei imageSize, const GLvoid *data,
733 struct gl_texture_object *texObj,
734 struct gl_texture_image *texImage )
735 {
736 driTextureObject * t = (driTextureObject *) texObj->DriverData;
737 GLuint face;
738
739 /* which cube face or ordinary 2D image */
740 switch (target) {
741 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
742 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
743 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
744 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
745 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
746 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
747 face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
748 ASSERT(face < 6);
749 break;
750 default:
751 face = 0;
752 }
753
754 if ( t != NULL ) {
755 driSwapOutTextureObject( t );
756 }
757 else {
758 t = (driTextureObject *) r200AllocTexObj( texObj );
759 if (!t) {
760 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
761 return;
762 }
763 }
764
765 texImage->IsClientData = GL_FALSE;
766 /* can't call this, different parameters. Would never evaluate to true anyway currently
767 if (r200ValidateClientStorage( ctx, target,
768 internalFormat,
769 width, height,
770 format, type, pixels,
771 packing, texObj, texImage)) {
772 if (R200_DEBUG & DEBUG_TEXTURE)
773 fprintf(stderr, "%s: Using client storage\n", __FUNCTION__);
774 }
775 else */{
776 if (R200_DEBUG & DEBUG_TEXTURE)
777 fprintf(stderr, "%s: Using normal storage\n", __FUNCTION__);
778
779 /* Normal path: copy (to cached memory) and eventually upload
780 * via another copy to GART memory and then a blit... Could
781 * eliminate one copy by going straight to (permanent) GART.
782 *
783 * Note, this will call r200ChooseTextureFormat.
784 */
785 _mesa_store_compressed_teximage2d(ctx, target, level, internalFormat, width,
786 height, border, imageSize, data, texObj, texImage);
787
788 t->dirty_images[face] |= (1 << level);
789 }
790 }
791
792
793 static void r200CompressedTexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
794 GLint xoffset, GLint yoffset,
795 GLsizei width, GLsizei height,
796 GLenum format,
797 GLsizei imageSize, const GLvoid *data,
798 struct gl_texture_object *texObj,
799 struct gl_texture_image *texImage )
800 {
801 driTextureObject * t = (driTextureObject *) texObj->DriverData;
802 GLuint face;
803
804
805 /* which cube face or ordinary 2D image */
806 switch (target) {
807 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
808 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
809 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
810 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
811 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
812 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
813 face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
814 ASSERT(face < 6);
815 break;
816 default:
817 face = 0;
818 }
819
820 assert( t ); /* this _should_ be true */
821 if ( t ) {
822 driSwapOutTextureObject( t );
823 }
824 else {
825 t = (driTextureObject *) r200AllocTexObj( texObj );
826 if (!t) {
827 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexSubImage2D");
828 return;
829 }
830 }
831
832 _mesa_store_compressed_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
833 height, format, imageSize, data, texObj, texImage);
834
835 t->dirty_images[face] |= (1 << level);
836 }
837
838
839 #if ENABLE_HW_3D_TEXTURE
840 static void r200TexImage3D( GLcontext *ctx, GLenum target, GLint level,
841 GLint internalFormat,
842 GLint width, GLint height, GLint depth,
843 GLint border,
844 GLenum format, GLenum type, const GLvoid *pixels,
845 const struct gl_pixelstore_attrib *packing,
846 struct gl_texture_object *texObj,
847 struct gl_texture_image *texImage )
848 {
849 driTextureObject * t = (driTextureObject *) texObj->DriverData;
850
851 if ( t ) {
852 driSwapOutTextureObject( t );
853 }
854 else {
855 t = (driTextureObject *) r200AllocTexObj( texObj );
856 if (!t) {
857 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
858 return;
859 }
860 }
861
862 texImage->IsClientData = GL_FALSE;
863
864 #if 0
865 if (r200ValidateClientStorage( ctx, target,
866 internalFormat,
867 width, height,
868 format, type, pixels,
869 packing, texObj, texImage)) {
870 if (R200_DEBUG & DEBUG_TEXTURE)
871 fprintf(stderr, "%s: Using client storage\n", __FUNCTION__);
872 }
873 else
874 #endif
875 {
876 if (R200_DEBUG & DEBUG_TEXTURE)
877 fprintf(stderr, "%s: Using normal storage\n", __FUNCTION__);
878
879 /* Normal path: copy (to cached memory) and eventually upload
880 * via another copy to GART memory and then a blit... Could
881 * eliminate one copy by going straight to (permanent) GART.
882 *
883 * Note, this will call r200ChooseTextureFormat.
884 */
885 _mesa_store_teximage3d(ctx, target, level, internalFormat,
886 width, height, depth, border,
887 format, type, pixels,
888 &ctx->Unpack, texObj, texImage);
889
890 t->dirty_images[0] |= (1 << level);
891 }
892 }
893 #endif
894
895
896 #if ENABLE_HW_3D_TEXTURE
897 static void
898 r200TexSubImage3D( GLcontext *ctx, GLenum target, GLint level,
899 GLint xoffset, GLint yoffset, GLint zoffset,
900 GLsizei width, GLsizei height, GLsizei depth,
901 GLenum format, GLenum type,
902 const GLvoid *pixels,
903 const struct gl_pixelstore_attrib *packing,
904 struct gl_texture_object *texObj,
905 struct gl_texture_image *texImage )
906 {
907 driTextureObject * t = (driTextureObject *) texObj->DriverData;
908
909 /* fprintf(stderr, "%s\n", __FUNCTION__); */
910
911 assert( t ); /* this _should_ be true */
912 if ( t ) {
913 driSwapOutTextureObject( t );
914 }
915 else {
916 t = (driTextureObject *) r200AllocTexObj( texObj );
917 if (!t) {
918 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage3D");
919 return;
920 }
921 texObj->DriverData = t;
922 }
923
924 _mesa_store_texsubimage3d(ctx, target, level, xoffset, yoffset, zoffset,
925 width, height, depth,
926 format, type, pixels, packing, texObj, texImage);
927
928 t->dirty_images[0] |= (1 << level);
929 }
930 #endif
931
932
933
934 static void r200TexEnv( GLcontext *ctx, GLenum target,
935 GLenum pname, const GLfloat *param )
936 {
937 r200ContextPtr rmesa = R200_CONTEXT(ctx);
938 GLuint unit = ctx->Texture.CurrentUnit;
939 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
940
941 if ( R200_DEBUG & DEBUG_STATE ) {
942 fprintf( stderr, "%s( %s )\n",
943 __FUNCTION__, _mesa_lookup_enum_by_nr( pname ) );
944 }
945
946 /* This is incorrect: Need to maintain this data for each of
947 * GL_TEXTURE_{123}D, GL_TEXTURE_RECTANGLE_NV, etc, and switch
948 * between them according to _ReallyEnabled.
949 */
950 switch ( pname ) {
951 case GL_TEXTURE_ENV_COLOR: {
952 GLubyte c[4];
953 GLuint envColor;
954 UNCLAMPED_FLOAT_TO_RGBA_CHAN( c, texUnit->EnvColor );
955 envColor = r200PackColor( 4, c[0], c[1], c[2], c[3] );
956 if ( rmesa->hw.tf.cmd[TF_TFACTOR_0 + unit] != envColor ) {
957 R200_STATECHANGE( rmesa, tf );
958 rmesa->hw.tf.cmd[TF_TFACTOR_0 + unit] = envColor;
959 }
960 break;
961 }
962
963 case GL_TEXTURE_LOD_BIAS_EXT: {
964 GLfloat bias, min;
965 GLuint b;
966 const int fixed_one = 0x8000000;
967
968 /* The R200's LOD bias is a signed 2's complement value with a
969 * range of -16.0 <= bias < 16.0.
970 *
971 * NOTE: Add a small bias to the bias for conform mipsel.c test.
972 */
973 bias = *param + .01;
974 min = driQueryOptionb (&rmesa->optionCache, "no_neg_lod_bias") ?
975 0.0 : -16.0;
976 bias = CLAMP( bias, min, 16.0 );
977 b = (int)(bias * fixed_one) & R200_LOD_BIAS_MASK;
978
979 if ( (rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT_X] & R200_LOD_BIAS_MASK) != b ) {
980 R200_STATECHANGE( rmesa, tex[unit] );
981 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT_X] &= ~R200_LOD_BIAS_MASK;
982 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT_X] |= b;
983 }
984 break;
985 }
986
987 default:
988 return;
989 }
990 }
991
992
993 /**
994 * Changes variables and flags for a state update, which will happen at the
995 * next UpdateTextureState
996 */
997
998 static void r200TexParameter( GLcontext *ctx, GLenum target,
999 struct gl_texture_object *texObj,
1000 GLenum pname, const GLfloat *params )
1001 {
1002 r200TexObjPtr t = (r200TexObjPtr) texObj->DriverData;
1003
1004 if ( R200_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) {
1005 fprintf( stderr, "%s( %s )\n", __FUNCTION__,
1006 _mesa_lookup_enum_by_nr( pname ) );
1007 }
1008
1009 switch ( pname ) {
1010 case GL_TEXTURE_MIN_FILTER:
1011 case GL_TEXTURE_MAG_FILTER:
1012 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1013 r200SetTexMaxAnisotropy( t, texObj->MaxAnisotropy );
1014 r200SetTexFilter( t, texObj->MinFilter, texObj->MagFilter );
1015 break;
1016
1017 case GL_TEXTURE_WRAP_S:
1018 case GL_TEXTURE_WRAP_T:
1019 case GL_TEXTURE_WRAP_R:
1020 r200SetTexWrap( t, texObj->WrapS, texObj->WrapT, texObj->WrapR );
1021 break;
1022
1023 case GL_TEXTURE_BORDER_COLOR:
1024 r200SetTexBorderColor( t, texObj->_BorderChan );
1025 break;
1026
1027 case GL_TEXTURE_BASE_LEVEL:
1028 case GL_TEXTURE_MAX_LEVEL:
1029 case GL_TEXTURE_MIN_LOD:
1030 case GL_TEXTURE_MAX_LOD:
1031 /* This isn't the most efficient solution but there doesn't appear to
1032 * be a nice alternative. Since there's no LOD clamping,
1033 * we just have to rely on loading the right subset of mipmap levels
1034 * to simulate a clamped LOD.
1035 */
1036 driSwapOutTextureObject( (driTextureObject *) t );
1037 break;
1038
1039 default:
1040 return;
1041 }
1042
1043 /* Mark this texobj as dirty (one bit per tex unit)
1044 */
1045 t->dirty_state = TEX_ALL;
1046 }
1047
1048
1049
1050 static void r200BindTexture( GLcontext *ctx, GLenum target,
1051 struct gl_texture_object *texObj )
1052 {
1053 if ( R200_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) {
1054 fprintf( stderr, "%s( %p ) unit=%d\n", __FUNCTION__, (void *)texObj,
1055 ctx->Texture.CurrentUnit );
1056 }
1057
1058 if ( (target == GL_TEXTURE_1D)
1059 || (target == GL_TEXTURE_2D)
1060 #if ENABLE_HW_3D_TEXTURE
1061 || (target == GL_TEXTURE_3D)
1062 #endif
1063 || (target == GL_TEXTURE_CUBE_MAP)
1064 || (target == GL_TEXTURE_RECTANGLE_NV) ) {
1065 assert( texObj->DriverData != NULL );
1066 }
1067 }
1068
1069
1070 static void r200DeleteTexture( GLcontext *ctx,
1071 struct gl_texture_object *texObj )
1072 {
1073 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1074 driTextureObject * t = (driTextureObject *) texObj->DriverData;
1075
1076 if ( R200_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) {
1077 fprintf( stderr, "%s( %p (target = %s) )\n", __FUNCTION__, (void *)texObj,
1078 _mesa_lookup_enum_by_nr( texObj->Target ) );
1079 }
1080
1081 if ( t != NULL ) {
1082 if ( rmesa ) {
1083 R200_FIREVERTICES( rmesa );
1084 }
1085
1086 driDestroyTextureObject( t );
1087 }
1088 /* Free mipmap images and the texture object itself */
1089 _mesa_delete_texture_object(ctx, texObj);
1090 }
1091
1092 /* Need:
1093 * - Same GEN_MODE for all active bits
1094 * - Same EyePlane/ObjPlane for all active bits when using Eye/Obj
1095 * - STRQ presumably all supported (matrix means incoming R values
1096 * can end up in STQ, this has implications for vertex support,
1097 * presumably ok if maos is used, though?)
1098 *
1099 * Basically impossible to do this on the fly - just collect some
1100 * basic info & do the checks from ValidateState().
1101 */
1102 static void r200TexGen( GLcontext *ctx,
1103 GLenum coord,
1104 GLenum pname,
1105 const GLfloat *params )
1106 {
1107 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1108 GLuint unit = ctx->Texture.CurrentUnit;
1109 rmesa->recheck_texgen[unit] = GL_TRUE;
1110 }
1111
1112
1113 /**
1114 * Allocate a new texture object.
1115 * Called via ctx->Driver.NewTextureObject.
1116 * Note: this function will be called during context creation to
1117 * allocate the default texture objects.
1118 * Note: we could use containment here to 'derive' the driver-specific
1119 * texture object from the core mesa gl_texture_object. Not done at this time.
1120 * Fixup MaxAnisotropy according to user preference.
1121 */
1122 static struct gl_texture_object *
1123 r200NewTextureObject( GLcontext *ctx, GLuint name, GLenum target )
1124 {
1125 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1126 struct gl_texture_object *obj;
1127 obj = _mesa_new_texture_object(ctx, name, target);
1128 if (!obj)
1129 return NULL;
1130 obj->MaxAnisotropy = rmesa->initialMaxAnisotropy;
1131 r200AllocTexObj( obj );
1132 return obj;
1133 }
1134
1135
1136 void r200InitTextureFuncs( struct dd_function_table *functions )
1137 {
1138 /* Note: we only plug in the functions we implement in the driver
1139 * since _mesa_init_driver_functions() was already called.
1140 */
1141 functions->ChooseTextureFormat = r200ChooseTextureFormat;
1142 functions->TexImage1D = r200TexImage1D;
1143 functions->TexImage2D = r200TexImage2D;
1144 #if ENABLE_HW_3D_TEXTURE
1145 functions->TexImage3D = r200TexImage3D;
1146 #else
1147 functions->TexImage3D = _mesa_store_teximage3d;
1148 #endif
1149 functions->TexSubImage1D = r200TexSubImage1D;
1150 functions->TexSubImage2D = r200TexSubImage2D;
1151 #if ENABLE_HW_3D_TEXTURE
1152 functions->TexSubImage3D = r200TexSubImage3D;
1153 #else
1154 functions->TexSubImage3D = _mesa_store_texsubimage3d;
1155 #endif
1156 functions->NewTextureObject = r200NewTextureObject;
1157 functions->BindTexture = r200BindTexture;
1158 functions->DeleteTexture = r200DeleteTexture;
1159 functions->IsTextureResident = driIsTextureResident;
1160
1161 functions->TexEnv = r200TexEnv;
1162 functions->TexParameter = r200TexParameter;
1163 functions->TexGen = r200TexGen;
1164
1165 functions->CompressedTexImage2D = r200CompressedTexImage2D;
1166 functions->CompressedTexSubImage2D = r200CompressedTexSubImage2D;
1167
1168 driInitTextureFormats();
1169
1170 #if 000
1171 /* moved or obsolete code */
1172 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1173 driInitTextureObjects( ctx, & rmesa->swapped,
1174 DRI_TEXMGR_DO_TEXTURE_1D
1175 | DRI_TEXMGR_DO_TEXTURE_2D );
1176
1177 /* Hack: r200NewTextureObject is not yet installed when the
1178 * default textures are created. Therefore set MaxAnisotropy of the
1179 * default 2D texture now. */
1180 ctx->Shared->Default2D->MaxAnisotropy = driQueryOptionf (&rmesa->optionCache,
1181 "def_max_anisotropy");
1182 #endif
1183 }