Big-endian texture fixes from Michel Dänzer.
[mesa.git] / src / mesa / drivers / dri / r128 / r128_tex.c
1 /* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_tex.c,v 1.14 2002/11/05 17:46:08 tsi Exp $ */
2 /**************************************************************************
3
4 Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
5 Cedar Park, Texas.
6 All Rights Reserved.
7
8 Permission is hereby granted, free of charge, to any person obtaining a
9 copy of this software and associated documentation files (the "Software"),
10 to deal in the Software without restriction, including without limitation
11 on the rights to use, copy, modify, merge, publish, distribute, sub
12 license, and/or sell copies of the Software, and to permit persons to whom
13 the Software is furnished to do so, subject to the following conditions:
14
15 The above copyright notice and this permission notice (including the next
16 paragraph) shall be included in all copies or substantial portions of the
17 Software.
18
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
22 ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
23 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
25 USE OR OTHER DEALINGS IN THE SOFTWARE.
26
27 **************************************************************************/
28
29 /*
30 * Authors:
31 * Gareth Hughes <gareth@valinux.com>
32 * Kevin E. Martin <martin@valinux.com>
33 * Brian Paul <brianp@valinux.com>
34 */
35
36 #include "r128_context.h"
37 #include "r128_state.h"
38 #include "r128_ioctl.h"
39 #include "r128_vb.h"
40 #include "r128_tris.h"
41 #include "r128_tex.h"
42 #include "r128_texobj.h"
43
44 #include "context.h"
45 #include "macros.h"
46 #include "simple_list.h"
47 #include "enums.h"
48 #include "texstore.h"
49 #include "texformat.h"
50 #include "teximage.h"
51 #include "texobj.h"
52 #include "imports.h"
53 #include "colormac.h"
54 #include "texobj.h"
55
56 #include "xmlpool.h"
57
58 #define TEX_0 1
59 #define TEX_1 2
60
61
62 /**
63 * Set the texture wrap modes. Currently \c GL_REPEAT, \c GL_CLAMP,
64 * \c GL_CLAMP_TO_EDGE, and \c GL_MIRRORED_REPEAT are supported.
65 *
66 * \param t Texture object whose wrap modes are to be set
67 * \param swrap Wrap mode for the \a s texture coordinate
68 * \param twrap Wrap mode for the \a t texture coordinate
69 */
70 static void r128SetTexWrap( r128TexObjPtr t, GLenum swrap, GLenum twrap )
71 {
72 t->setup.tex_cntl &= ~(R128_TEX_CLAMP_S_MASK | R128_TEX_CLAMP_T_MASK);
73
74 switch ( swrap ) {
75 case GL_CLAMP:
76 t->setup.tex_cntl |= R128_TEX_CLAMP_S_BORDER_COLOR;
77 break;
78 case GL_CLAMP_TO_EDGE:
79 t->setup.tex_cntl |= R128_TEX_CLAMP_S_CLAMP;
80 break;
81 case GL_REPEAT:
82 t->setup.tex_cntl |= R128_TEX_CLAMP_S_WRAP;
83 break;
84 case GL_MIRRORED_REPEAT:
85 t->setup.tex_cntl |= R128_TEX_CLAMP_S_MIRROR;
86 break;
87 }
88
89 switch ( twrap ) {
90 case GL_CLAMP:
91 t->setup.tex_cntl |= R128_TEX_CLAMP_T_BORDER_COLOR;
92 break;
93 case GL_CLAMP_TO_EDGE:
94 t->setup.tex_cntl |= R128_TEX_CLAMP_T_CLAMP;
95 break;
96 case GL_REPEAT:
97 t->setup.tex_cntl |= R128_TEX_CLAMP_T_WRAP;
98 break;
99 case GL_MIRRORED_REPEAT:
100 t->setup.tex_cntl |= R128_TEX_CLAMP_T_MIRROR;
101 break;
102 }
103 }
104
105 static void r128SetTexFilter( r128TexObjPtr t, GLenum minf, GLenum magf )
106 {
107 t->setup.tex_cntl &= ~(R128_MIN_BLEND_MASK | R128_MAG_BLEND_MASK);
108
109 switch ( minf ) {
110 case GL_NEAREST:
111 t->setup.tex_cntl |= R128_MIN_BLEND_NEAREST;
112 break;
113 case GL_LINEAR:
114 t->setup.tex_cntl |= R128_MIN_BLEND_LINEAR;
115 break;
116 case GL_NEAREST_MIPMAP_NEAREST:
117 t->setup.tex_cntl |= R128_MIN_BLEND_MIPNEAREST;
118 break;
119 case GL_LINEAR_MIPMAP_NEAREST:
120 t->setup.tex_cntl |= R128_MIN_BLEND_MIPLINEAR;
121 break;
122 case GL_NEAREST_MIPMAP_LINEAR:
123 t->setup.tex_cntl |= R128_MIN_BLEND_LINEARMIPNEAREST;
124 break;
125 case GL_LINEAR_MIPMAP_LINEAR:
126 t->setup.tex_cntl |= R128_MIN_BLEND_LINEARMIPLINEAR;
127 break;
128 }
129
130 switch ( magf ) {
131 case GL_NEAREST:
132 t->setup.tex_cntl |= R128_MAG_BLEND_NEAREST;
133 break;
134 case GL_LINEAR:
135 t->setup.tex_cntl |= R128_MAG_BLEND_LINEAR;
136 break;
137 }
138 }
139
140 static void r128SetTexBorderColor( r128TexObjPtr t, GLubyte c[4] )
141 {
142 t->setup.tex_border_color = r128PackColor( 4, c[0], c[1], c[2], c[3] );
143 }
144
145
146 static r128TexObjPtr r128AllocTexObj( struct gl_texture_object *texObj )
147 {
148 r128TexObjPtr t;
149
150 if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
151 fprintf( stderr, "%s( %p )\n", __FUNCTION__, (void *) texObj );
152 }
153
154 t = (r128TexObjPtr) CALLOC_STRUCT( r128_tex_obj );
155 texObj->DriverData = t;
156 if ( t != NULL ) {
157
158 /* Initialize non-image-dependent parts of the state:
159 */
160 t->base.tObj = texObj;
161
162 /* FIXME Something here to set initial values for other parts of
163 * FIXME t->setup?
164 */
165
166 make_empty_list( (driTextureObject *) t );
167
168 r128SetTexWrap( t, texObj->WrapS, texObj->WrapT );
169 r128SetTexFilter( t, texObj->MinFilter, texObj->MagFilter );
170 r128SetTexBorderColor( t, texObj->_BorderChan );
171 }
172
173 return t;
174 }
175
176
177 /* Called by the _mesa_store_teximage[123]d() functions. */
178 static const struct gl_texture_format *
179 r128ChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
180 GLenum format, GLenum type )
181 {
182 r128ContextPtr rmesa = R128_CONTEXT(ctx);
183 const GLboolean do32bpt =
184 ( rmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_32 );
185 const GLboolean force16bpt =
186 ( rmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FORCE_16 );
187 (void) format;
188 (void) type;
189
190 switch ( internalFormat ) {
191 /* non-sized formats with alpha */
192 case GL_INTENSITY:
193 case GL_COMPRESSED_INTENSITY:
194 case GL_ALPHA:
195 case GL_COMPRESSED_ALPHA:
196 case 2:
197 case GL_LUMINANCE_ALPHA:
198 case GL_COMPRESSED_LUMINANCE_ALPHA:
199 case 4:
200 case GL_RGBA:
201 case GL_COMPRESSED_RGBA:
202 if (do32bpt)
203 return _dri_texformat_argb8888;
204 else
205 return _dri_texformat_argb4444;
206
207 /* 16-bit formats with alpha */
208 case GL_INTENSITY4:
209 case GL_ALPHA4:
210 case GL_LUMINANCE4_ALPHA4:
211 case GL_RGBA2:
212 case GL_RGBA4:
213 return _dri_texformat_argb4444;
214
215 /* 32-bit formats with alpha */
216 case GL_INTENSITY8:
217 case GL_INTENSITY12:
218 case GL_INTENSITY16:
219 case GL_ALPHA8:
220 case GL_ALPHA12:
221 case GL_ALPHA16:
222 case GL_LUMINANCE6_ALPHA2:
223 case GL_LUMINANCE8_ALPHA8:
224 case GL_LUMINANCE12_ALPHA4:
225 case GL_LUMINANCE12_ALPHA12:
226 case GL_LUMINANCE16_ALPHA16:
227 case GL_RGB5_A1:
228 case GL_RGBA8:
229 case GL_RGB10_A2:
230 case GL_RGBA12:
231 case GL_RGBA16:
232 if (!force16bpt)
233 return _dri_texformat_argb8888;
234 else
235 return _dri_texformat_argb4444;
236
237 /* non-sized formats without alpha */
238 case 1:
239 case GL_LUMINANCE:
240 case GL_COMPRESSED_LUMINANCE:
241 case 3:
242 case GL_RGB:
243 case GL_COMPRESSED_RGB:
244 if (do32bpt)
245 return _dri_texformat_argb8888;
246 else
247 return _dri_texformat_rgb565;
248
249 /* 16-bit formats without alpha */
250 case GL_LUMINANCE4:
251 case GL_R3_G3_B2:
252 case GL_RGB4:
253 case GL_RGB5:
254 return _dri_texformat_rgb565;
255
256 /* 32-bit formats without alpha */
257 case GL_LUMINANCE8:
258 case GL_LUMINANCE12:
259 case GL_LUMINANCE16:
260 case GL_RGB8:
261 case GL_RGB10:
262 case GL_RGB12:
263 case GL_RGB16:
264 if (!force16bpt)
265 return _dri_texformat_argb8888;
266 else
267 return _dri_texformat_rgb565;
268
269 /* color-indexed formats */
270 case GL_COLOR_INDEX:
271 case GL_COLOR_INDEX1_EXT:
272 case GL_COLOR_INDEX2_EXT:
273 case GL_COLOR_INDEX4_EXT:
274 case GL_COLOR_INDEX8_EXT:
275 case GL_COLOR_INDEX12_EXT:
276 case GL_COLOR_INDEX16_EXT:
277 return _dri_texformat_ci8;
278
279 case GL_YCBCR_MESA:
280 if (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
281 type == GL_UNSIGNED_BYTE)
282 return &_mesa_texformat_ycbcr;
283 else
284 return &_mesa_texformat_ycbcr_rev;
285
286 default:
287 _mesa_problem( ctx, "unexpected format in %s", __FUNCTION__ );
288 return NULL;
289 }
290 }
291
292
293 static void r128TexImage1D( GLcontext *ctx, GLenum target, GLint level,
294 GLint internalFormat,
295 GLint width, GLint border,
296 GLenum format, GLenum type, const GLvoid *pixels,
297 const struct gl_pixelstore_attrib *packing,
298 struct gl_texture_object *texObj,
299 struct gl_texture_image *texImage )
300 {
301 driTextureObject * t = (driTextureObject *) texObj->DriverData;
302
303 if ( t ) {
304 driSwapOutTextureObject( t );
305 }
306 else {
307 t = (driTextureObject *) r128AllocTexObj(texObj);
308 if (!t) {
309 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
310 return;
311 }
312 }
313
314 /* Note, this will call r128ChooseTextureFormat */
315 _mesa_store_teximage1d( ctx, target, level, internalFormat,
316 width, border, format, type,
317 pixels, packing, texObj, texImage );
318
319 t->dirty_images[0] |= (1 << level);
320 }
321
322
323 static void r128TexSubImage1D( GLcontext *ctx,
324 GLenum target,
325 GLint level,
326 GLint xoffset,
327 GLsizei width,
328 GLenum format, GLenum type,
329 const GLvoid *pixels,
330 const struct gl_pixelstore_attrib *packing,
331 struct gl_texture_object *texObj,
332 struct gl_texture_image *texImage )
333 {
334 driTextureObject * t = (driTextureObject *) texObj->DriverData;
335
336 assert( t ); /* this _should_ be true */
337 if ( t ) {
338 driSwapOutTextureObject( t );
339 }
340 else {
341 t = (driTextureObject *) r128AllocTexObj(texObj);
342 if (!t) {
343 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
344 return;
345 }
346 }
347
348 _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
349 format, type, pixels, packing, texObj,
350 texImage);
351
352 t->dirty_images[0] |= (1 << level);
353 }
354
355
356 static void r128TexImage2D( GLcontext *ctx, GLenum target, GLint level,
357 GLint internalFormat,
358 GLint width, GLint height, GLint border,
359 GLenum format, GLenum type, const GLvoid *pixels,
360 const struct gl_pixelstore_attrib *packing,
361 struct gl_texture_object *texObj,
362 struct gl_texture_image *texImage )
363 {
364 driTextureObject * t = (driTextureObject *) texObj->DriverData;
365
366 if ( t ) {
367 driSwapOutTextureObject( (driTextureObject *) t );
368 }
369 else {
370 t = (driTextureObject *) r128AllocTexObj(texObj);
371 if (!t) {
372 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
373 return;
374 }
375 }
376
377 /* Note, this will call r128ChooseTextureFormat */
378 _mesa_store_teximage2d(ctx, target, level, internalFormat,
379 width, height, border, format, type, pixels,
380 &ctx->Unpack, texObj, texImage);
381
382 t->dirty_images[0] |= (1 << level);
383 }
384
385
386 static void r128TexSubImage2D( GLcontext *ctx,
387 GLenum target,
388 GLint level,
389 GLint xoffset, GLint yoffset,
390 GLsizei width, GLsizei height,
391 GLenum format, GLenum type,
392 const GLvoid *pixels,
393 const struct gl_pixelstore_attrib *packing,
394 struct gl_texture_object *texObj,
395 struct gl_texture_image *texImage )
396 {
397 driTextureObject * t = (driTextureObject *) texObj->DriverData;
398
399 assert( t ); /* this _should_ be true */
400 if ( t ) {
401 driSwapOutTextureObject( t );
402 }
403 else {
404 t = (driTextureObject *) r128AllocTexObj(texObj);
405 if (!t) {
406 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
407 return;
408 }
409 }
410
411 _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
412 height, format, type, pixels, packing, texObj,
413 texImage);
414 t->dirty_images[0] |= (1 << level);
415 }
416
417
418 static void r128TexEnv( GLcontext *ctx, GLenum target,
419 GLenum pname, const GLfloat *param )
420 {
421 r128ContextPtr rmesa = R128_CONTEXT(ctx);
422 struct gl_texture_unit *texUnit;
423 GLubyte c[4];
424
425 if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
426 fprintf( stderr, "%s( %s )\n",
427 __FUNCTION__, _mesa_lookup_enum_by_nr( pname ) );
428 }
429
430 switch ( pname ) {
431 case GL_TEXTURE_ENV_MODE:
432 FLUSH_BATCH( rmesa );
433 rmesa->new_state |= R128_NEW_ALPHA;
434 break;
435
436 case GL_TEXTURE_ENV_COLOR:
437 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
438 CLAMPED_FLOAT_TO_UBYTE( c[0], texUnit->EnvColor[0] );
439 CLAMPED_FLOAT_TO_UBYTE( c[1], texUnit->EnvColor[1] );
440 CLAMPED_FLOAT_TO_UBYTE( c[2], texUnit->EnvColor[2] );
441 CLAMPED_FLOAT_TO_UBYTE( c[3], texUnit->EnvColor[3] );
442 rmesa->env_color = r128PackColor( 4, c[0], c[1], c[2], c[3] );
443 if ( rmesa->setup.constant_color_c != rmesa->env_color ) {
444 FLUSH_BATCH( rmesa );
445 rmesa->setup.constant_color_c = rmesa->env_color;
446
447 /* More complex multitexture/multipass fallbacks for GL_BLEND
448 * can be done later, but this allows a single pass GL_BLEND
449 * in some cases (ie. Performer town demo). This is only
450 * applicable to the regular Rage 128, as the Pro and M3 can
451 * handle true single-pass GL_BLEND texturing.
452 */
453 rmesa->blend_flags &= ~R128_BLEND_ENV_COLOR;
454 if ( R128_IS_PLAIN( rmesa ) &&
455 rmesa->env_color != 0x00000000 &&
456 rmesa->env_color != 0xff000000 &&
457 rmesa->env_color != 0x00ffffff &&
458 rmesa->env_color != 0xffffffff ) {
459 rmesa->blend_flags |= R128_BLEND_ENV_COLOR;
460 }
461 }
462 break;
463
464 case GL_TEXTURE_LOD_BIAS:
465 {
466 uint32_t t = rmesa->setup.tex_cntl_c;
467 GLint bias;
468 uint32_t b;
469
470 /* GTH: This isn't exactly correct, but gives good results up to a
471 * certain point. It is better than completely ignoring the LOD
472 * bias. Unfortunately there isn't much range in the bias, the
473 * spec mentions strides that vary between 0.5 and 2.0 but these
474 * numbers don't seem to relate the the GL LOD bias value at all.
475 */
476 if ( param[0] >= 1.0 ) {
477 bias = -128;
478 } else if ( param[0] >= 0.5 ) {
479 bias = -64;
480 } else if ( param[0] >= 0.25 ) {
481 bias = 0;
482 } else if ( param[0] >= 0.0 ) {
483 bias = 63;
484 } else {
485 bias = 127;
486 }
487
488 b = (uint32_t)bias & 0xff;
489 t &= ~R128_LOD_BIAS_MASK;
490 t |= (b << R128_LOD_BIAS_SHIFT);
491
492 if ( rmesa->setup.tex_cntl_c != t ) {
493 FLUSH_BATCH( rmesa );
494 rmesa->setup.tex_cntl_c = t;
495 rmesa->dirty |= R128_UPLOAD_CONTEXT;
496 }
497 }
498 break;
499
500 default:
501 return;
502 }
503 }
504
505
506 static void r128TexParameter( GLcontext *ctx, GLenum target,
507 struct gl_texture_object *tObj,
508 GLenum pname, const GLfloat *params )
509 {
510 r128ContextPtr rmesa = R128_CONTEXT(ctx);
511 r128TexObjPtr t = (r128TexObjPtr)tObj->DriverData;
512
513 if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
514 fprintf( stderr, "%s( %s )\n",
515 __FUNCTION__, _mesa_lookup_enum_by_nr( pname ) );
516 }
517
518 if ( ( target != GL_TEXTURE_2D ) && ( target != GL_TEXTURE_1D ) )
519 return;
520
521 switch ( pname ) {
522 case GL_TEXTURE_MIN_FILTER:
523 case GL_TEXTURE_MAG_FILTER:
524 if ( t->base.bound ) FLUSH_BATCH( rmesa );
525 r128SetTexFilter( t, tObj->MinFilter, tObj->MagFilter );
526 break;
527
528 case GL_TEXTURE_WRAP_S:
529 case GL_TEXTURE_WRAP_T:
530 if ( t->base.bound ) FLUSH_BATCH( rmesa );
531 r128SetTexWrap( t, tObj->WrapS, tObj->WrapT );
532 break;
533
534 case GL_TEXTURE_BORDER_COLOR:
535 if ( t->base.bound ) FLUSH_BATCH( rmesa );
536 r128SetTexBorderColor( t, tObj->_BorderChan );
537 break;
538
539 case GL_TEXTURE_BASE_LEVEL:
540 case GL_TEXTURE_MAX_LEVEL:
541 case GL_TEXTURE_MIN_LOD:
542 case GL_TEXTURE_MAX_LOD:
543 /* This isn't the most efficient solution but there doesn't appear to
544 * be a nice alternative for R128. Since there's no LOD clamping,
545 * we just have to rely on loading the right subset of mipmap levels
546 * to simulate a clamped LOD.
547 */
548 if ( t->base.bound ) FLUSH_BATCH( rmesa );
549 driSwapOutTextureObject( (driTextureObject *) t );
550 break;
551
552 default:
553 return;
554 }
555 }
556
557 static void r128BindTexture( GLcontext *ctx, GLenum target,
558 struct gl_texture_object *tObj )
559 {
560 if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
561 fprintf( stderr, "%s( %p ) unit=%d\n", __FUNCTION__, (void *) tObj,
562 ctx->Texture.CurrentUnit );
563 }
564
565 assert( (target != GL_TEXTURE_2D && target != GL_TEXTURE_1D) ||
566 (tObj->DriverData != NULL) );
567 }
568
569
570 static void r128DeleteTexture( GLcontext *ctx,
571 struct gl_texture_object *tObj )
572 {
573 r128ContextPtr rmesa = R128_CONTEXT(ctx);
574 driTextureObject * t = (driTextureObject *) tObj->DriverData;
575
576 if ( t ) {
577 if ( t->bound && rmesa ) {
578 FLUSH_BATCH( rmesa );
579 }
580
581 driDestroyTextureObject( t );
582 }
583 /* Free mipmap images and the texture object itself */
584 _mesa_delete_texture_object(ctx, tObj);
585 }
586
587 /**
588 * Allocate a new texture object.
589 * Called via ctx->Driver.NewTextureObject.
590 * Note: we could use containment here to 'derive' the driver-specific
591 * texture object from the core mesa gl_texture_object. Not done at this time.
592 */
593 static struct gl_texture_object *
594 r128NewTextureObject( GLcontext *ctx, GLuint name, GLenum target )
595 {
596 struct gl_texture_object *obj;
597 obj = _mesa_new_texture_object(ctx, name, target);
598 r128AllocTexObj( obj );
599 return obj;
600 }
601
602 void r128InitTextureFuncs( struct dd_function_table *functions )
603 {
604 functions->TexEnv = r128TexEnv;
605 functions->ChooseTextureFormat = r128ChooseTextureFormat;
606 functions->TexImage1D = r128TexImage1D;
607 functions->TexSubImage1D = r128TexSubImage1D;
608 functions->TexImage2D = r128TexImage2D;
609 functions->TexSubImage2D = r128TexSubImage2D;
610 functions->TexParameter = r128TexParameter;
611 functions->BindTexture = r128BindTexture;
612 functions->NewTextureObject = r128NewTextureObject;
613 functions->DeleteTexture = r128DeleteTexture;
614 functions->IsTextureResident = driIsTextureResident;
615
616 driInitTextureFormats();
617 }
618