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