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