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