Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / drivers / dri / mga / mgatex.c
1 /*
2  * Copyright 2000-2001 VA Linux Systems, Inc.
3  * All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * on the rights to use, copy, modify, merge, publish, distribute, sub
9  * license, and/or sell copies of the Software, and to permit persons to whom
10  * the Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
19  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22  * OTHER DEALINGS IN THE SOFTWARE.
23  *
24  * Authors:
25  *    Keith Whitwell <keith@tungstengraphics.com>
26  */
27
28 #include "main/glheader.h"
29 #include "main/mm.h"
30 #include "main/colormac.h"
31 #include "main/context.h"
32 #include "main/enums.h"
33 #include "main/simple_list.h"
34 #include "main/imports.h"
35 #include "main/macros.h"
36 #include "main/texstore.h"
37 #include "main/teximage.h"
38 #include "main/texobj.h"
39
40 #include "mgacontext.h"
41 #include "mgatex.h"
42 #include "mgaregs.h"
43 #include "mgaioctl.h"
44
45 #include "xmlpool.h"
46
47 /**
48  * Set the texture wrap modes.
49  * Currently \c GL_REPEAT, \c GL_CLAMP and \c GL_CLAMP_TO_EDGE are supported.
50  * 
51  * \param t Texture object whose wrap modes are to be set
52  * \param swrap Wrap mode for the \a s texture coordinate
53  * \param twrap Wrap mode for the \a t texture coordinate
54  */
55
56 static void 
57 mgaSetTexWrapping( mgaTextureObjectPtr t, GLenum swrap, GLenum twrap )
58 {
59    GLboolean  is_clamp = GL_FALSE;
60    GLboolean  is_clamp_to_edge = GL_FALSE;
61
62    t->setup.texctl &= (TMC_clampu_MASK & TMC_clampv_MASK);
63    t->setup.texctl2 &= (TMC_borderen_MASK);
64
65    switch( swrap ) {
66    case GL_REPEAT:
67       break;
68    case GL_CLAMP:
69       t->setup.texctl |= TMC_clampu_enable;
70       is_clamp = GL_TRUE;
71       break;
72    case GL_CLAMP_TO_EDGE:
73       t->setup.texctl |= TMC_clampu_enable;
74       is_clamp_to_edge = GL_TRUE;
75       break;
76    default:
77       _mesa_problem(NULL, "bad S wrap mode in %s", __FUNCTION__);
78    }
79
80    switch( twrap ) {
81    case GL_REPEAT:
82       break;
83    case GL_CLAMP:
84       t->setup.texctl |= TMC_clampv_enable;
85       is_clamp = GL_TRUE;
86       break;
87    case GL_CLAMP_TO_EDGE:
88       t->setup.texctl |= TMC_clampv_enable;
89       is_clamp_to_edge = GL_TRUE;
90       break;
91    default:
92       _mesa_problem(NULL, "bad T wrap mode in %s", __FUNCTION__);
93    }
94
95    if ( is_clamp ) {
96       t->setup.texctl2 |= TMC_borderen_enable;
97    }
98
99    t->border_fallback = (is_clamp && is_clamp_to_edge);
100 }
101
102
103 /**
104  * Set the texture magnification and minification modes.
105  * 
106  * \param t Texture whose filter modes are to be set
107  * \param minf Texture minification mode
108  * \param magf Texture magnification mode
109  */
110
111 static void
112 mgaSetTexFilter( mgaTextureObjectPtr t, GLenum minf, GLenum magf )
113 {
114    GLuint val = 0;
115
116    switch (minf) {
117    case GL_NEAREST: val = TF_minfilter_nrst; break;
118    case GL_LINEAR: val = TF_minfilter_bilin; break;
119    case GL_NEAREST_MIPMAP_NEAREST: val = TF_minfilter_mm1s; break;
120    case GL_LINEAR_MIPMAP_NEAREST: val = TF_minfilter_mm4s; break;
121    case GL_NEAREST_MIPMAP_LINEAR: val = TF_minfilter_mm2s; break;
122    case GL_LINEAR_MIPMAP_LINEAR: val = TF_minfilter_mm8s; break;
123    default: val = TF_minfilter_nrst; break;
124    }
125
126    switch (magf) {
127    case GL_NEAREST: val |= TF_magfilter_nrst; break;
128    case GL_LINEAR: val |= TF_magfilter_bilin; break;
129    default: val |= TF_magfilter_nrst; break;
130    }
131
132    /* See OpenGL 1.2 specification */
133    if (magf == GL_LINEAR && (minf == GL_NEAREST_MIPMAP_NEAREST ||
134                              minf == GL_NEAREST_MIPMAP_LINEAR)) {
135       val |= MGA_FIELD( TF_fthres, 0x20 ); /* c = 0.5 */
136    } else {
137       val |= MGA_FIELD( TF_fthres, 0x10 ); /* c = 0 */
138    }
139
140
141    /* Mask off the bits for the fields we are setting.  Remember, the MGA mask
142     * defines have 0s for the bits in the named fields.  This is the opposite
143     * of most of the other drivers.
144     */
145
146    t->setup.texfilter &= (TF_minfilter_MASK &
147                           TF_magfilter_MASK &
148                           TF_fthres_MASK);
149    t->setup.texfilter |= val;
150 }
151
152 static void mgaSetTexBorderColor(mgaTextureObjectPtr t, const GLfloat color[4])
153 {
154    GLubyte c[4];
155    CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]);
156    CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]);
157    CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]);
158    CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]);
159    t->setup.texbordercol = PACK_COLOR_8888(c[3], c[0], c[1], c[2] );
160 }
161
162
163 static gl_format
164 mgaChooseTextureFormat( struct gl_context *ctx, GLint internalFormat,
165                         GLenum format, GLenum type )
166 {
167    mgaContextPtr mmesa = MGA_CONTEXT(ctx);
168    const GLboolean do32bpt =
169        ( mmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_32 );
170    const GLboolean force16bpt =
171        ( mmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FORCE_16 );
172    (void) format;
173
174    switch ( internalFormat ) {
175    case 4:
176    case GL_RGBA:
177    case GL_COMPRESSED_RGBA:
178       switch ( type ) {
179       case GL_UNSIGNED_INT_10_10_10_2:
180       case GL_UNSIGNED_INT_2_10_10_10_REV:
181          return do32bpt ? MESA_FORMAT_ARGB8888 : MESA_FORMAT_ARGB1555;
182       case GL_UNSIGNED_SHORT_4_4_4_4:
183       case GL_UNSIGNED_SHORT_4_4_4_4_REV:
184          return MESA_FORMAT_ARGB4444;
185       case GL_UNSIGNED_SHORT_5_5_5_1:
186       case GL_UNSIGNED_SHORT_1_5_5_5_REV:
187          return MESA_FORMAT_ARGB1555;
188       default:
189          return do32bpt ? MESA_FORMAT_ARGB8888 : MESA_FORMAT_ARGB4444;
190       }
191
192    case 3:
193    case GL_RGB:
194    case GL_COMPRESSED_RGB:
195       switch ( type ) {
196       case GL_UNSIGNED_SHORT_4_4_4_4:
197       case GL_UNSIGNED_SHORT_4_4_4_4_REV:
198          return MESA_FORMAT_ARGB4444;
199       case GL_UNSIGNED_SHORT_5_5_5_1:
200       case GL_UNSIGNED_SHORT_1_5_5_5_REV:
201          return MESA_FORMAT_ARGB1555;
202       case GL_UNSIGNED_SHORT_5_6_5:
203       case GL_UNSIGNED_SHORT_5_6_5_REV:
204          return MESA_FORMAT_RGB565;
205       default:
206          return do32bpt ? MESA_FORMAT_ARGB8888 : MESA_FORMAT_RGB565;
207       }
208
209    case GL_RGBA8:
210    case GL_RGB10_A2:
211    case GL_RGBA12:
212    case GL_RGBA16:
213       return !force16bpt ?
214           MESA_FORMAT_ARGB8888 : MESA_FORMAT_ARGB4444;
215
216    case GL_RGBA4:
217    case GL_RGBA2:
218       return MESA_FORMAT_ARGB4444;
219
220    case GL_RGB5_A1:
221       return MESA_FORMAT_ARGB1555;
222
223    case GL_RGB8:
224    case GL_RGB10:
225    case GL_RGB12:
226    case GL_RGB16:
227       return !force16bpt ? MESA_FORMAT_ARGB8888 : MESA_FORMAT_RGB565;
228
229    case GL_RGB5:
230    case GL_RGB4:
231    case GL_R3_G3_B2:
232       return MESA_FORMAT_RGB565;
233
234    case GL_ALPHA:
235    case GL_ALPHA4:
236    case GL_ALPHA8:
237    case GL_ALPHA12:
238    case GL_ALPHA16:
239    case GL_COMPRESSED_ALPHA:
240       /* FIXME: This will report incorrect component sizes... */
241       return MGA_IS_G400(mmesa) ? MESA_FORMAT_AL88 : MESA_FORMAT_ARGB4444;
242
243    case 1:
244    case GL_LUMINANCE:
245    case GL_LUMINANCE4:
246    case GL_LUMINANCE8:
247    case GL_LUMINANCE12:
248    case GL_LUMINANCE16:
249    case GL_COMPRESSED_LUMINANCE:
250       /* FIXME: This will report incorrect component sizes... */
251       return MGA_IS_G400(mmesa) ? MESA_FORMAT_AL88 : MESA_FORMAT_RGB565;
252
253    case 2:
254    case GL_LUMINANCE_ALPHA:
255    case GL_LUMINANCE4_ALPHA4:
256    case GL_LUMINANCE6_ALPHA2:
257    case GL_LUMINANCE8_ALPHA8:
258    case GL_LUMINANCE12_ALPHA4:
259    case GL_LUMINANCE12_ALPHA12:
260    case GL_LUMINANCE16_ALPHA16:
261    case GL_COMPRESSED_LUMINANCE_ALPHA:
262       /* FIXME: This will report incorrect component sizes... */
263       return MGA_IS_G400(mmesa) ? MESA_FORMAT_AL88 : MESA_FORMAT_ARGB4444;
264
265    case GL_INTENSITY:
266    case GL_INTENSITY4:
267    case GL_INTENSITY8:
268    case GL_INTENSITY12:
269    case GL_INTENSITY16:
270    case GL_COMPRESSED_INTENSITY:
271       /* FIXME: This will report incorrect component sizes... */
272       return MGA_IS_G400(mmesa) ? MESA_FORMAT_I8 : MESA_FORMAT_ARGB4444;
273
274    case GL_YCBCR_MESA:
275       if (MGA_IS_G400(mmesa) &&
276           (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
277            type == GL_UNSIGNED_BYTE))
278          return MESA_FORMAT_YCBCR;
279       else
280          return MESA_FORMAT_YCBCR_REV;
281
282    case GL_COLOR_INDEX:
283    case GL_COLOR_INDEX1_EXT:
284    case GL_COLOR_INDEX2_EXT:
285    case GL_COLOR_INDEX4_EXT:
286    case GL_COLOR_INDEX8_EXT:
287    case GL_COLOR_INDEX12_EXT:
288    case GL_COLOR_INDEX16_EXT:
289       return MESA_FORMAT_CI8;
290
291    default:
292       _mesa_problem( ctx, "unexpected texture format in %s", __FUNCTION__ );
293       return MESA_FORMAT_NONE;
294    }
295
296    return MESA_FORMAT_NONE; /* never get here */
297 }
298
299
300
301
302 /**
303  * Allocate space for and load the mesa images into the texture memory block.
304  * This will happen before drawing with a new texture, or drawing with a
305  * texture after it was swapped out or teximaged again.
306  */
307
308 static mgaTextureObjectPtr
309 mgaAllocTexObj( struct gl_texture_object *tObj )
310 {
311    mgaTextureObjectPtr t;
312
313
314    t = CALLOC( sizeof( *t ) );
315    tObj->DriverData = t;
316    if ( t != NULL ) {
317       /* Initialize non-image-dependent parts of the state:
318        */
319       t->base.tObj = tObj;
320
321       t->setup.texctl = TMC_takey_1 | TMC_tamask_0;
322       t->setup.texctl2 = TMC_ckstransdis_enable;
323       t->setup.texfilter = TF_filteralpha_enable | TF_uvoffset_OGL;
324
325       t->border_fallback = GL_FALSE;
326       t->texenv_fallback = GL_FALSE;
327
328       make_empty_list( & t->base );
329
330       mgaSetTexWrapping( t, tObj->Sampler.WrapS, tObj->Sampler.WrapT );
331       mgaSetTexFilter( t, tObj->Sampler.MinFilter, tObj->Sampler.MagFilter );
332       mgaSetTexBorderColor( t, tObj->Sampler.BorderColor.f );
333    }
334
335    return( t );
336 }
337
338
339 static void mgaTexEnv( struct gl_context *ctx, GLenum target,
340                          GLenum pname, const GLfloat *param )
341 {
342    GLuint unit = ctx->Texture.CurrentUnit;
343    struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
344    mgaContextPtr mmesa = MGA_CONTEXT(ctx);
345
346    switch( pname ) {
347    case GL_TEXTURE_ENV_COLOR: {
348       GLubyte c[4];
349
350       UNCLAMPED_FLOAT_TO_RGBA_CHAN( c, texUnit->EnvColor );
351       mmesa->envcolor[unit] = PACK_COLOR_8888( c[3], c[0], c[1], c[2] );
352       break;
353    }
354    }
355 }
356
357
358 static void mgaTexImage2D( struct gl_context *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 != NULL ) {
369       driSwapOutTextureObject( t );
370    } 
371    else {
372       t = (driTextureObject *) mgaAllocTexObj( texObj );
373       if ( t == NULL ) {
374          _mesa_error( ctx, GL_OUT_OF_MEMORY, "glTexImage2D" );
375          return;
376       }
377    }
378
379    _mesa_store_teximage2d( ctx, target, level, internalFormat,
380                            width, height, border, format, type,
381                            pixels, packing, texObj, texImage );
382    level -= t->firstLevel;
383    if (level >= 0)
384       t->dirty_images[0] |= (1UL << level);
385 }
386
387 static void mgaTexSubImage2D( struct gl_context *ctx, 
388                                GLenum target,
389                                GLint level,     
390                                GLint xoffset, GLint yoffset,
391                                GLsizei width, GLsizei height,
392                                GLenum format, GLenum type,
393                                const GLvoid *pixels,
394                                const struct gl_pixelstore_attrib *packing,
395                                struct gl_texture_object *texObj,
396                                struct gl_texture_image *texImage )
397 {
398    driTextureObject * t = (driTextureObject *) texObj->DriverData;
399
400    assert( t ); /* this _should_ be true */
401    if ( t != NULL ) {
402       driSwapOutTextureObject( t );
403    } 
404    else {
405       t = (driTextureObject *) mgaAllocTexObj( texObj );
406       if ( t == NULL ) {
407          _mesa_error( ctx, GL_OUT_OF_MEMORY, "glTexImage2D" );
408          return;
409       }
410    }
411
412    _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width, 
413                              height, format, type, pixels, packing, texObj,
414                              texImage);
415    level -= t->firstLevel;
416    if (level >= 0)
417       t->dirty_images[0] |= (1UL << level);
418 }
419
420
421 /**
422  * Changes variables and flags for a state update, which will happen at the
423  * next UpdateTextureState
424  */
425
426 static void
427 mgaTexParameter( struct gl_context *ctx, GLenum target,
428                    struct gl_texture_object *tObj,
429                    GLenum pname, const GLfloat *params )
430 {
431    mgaContextPtr mmesa = MGA_CONTEXT( ctx );
432    mgaTextureObjectPtr t = (mgaTextureObjectPtr) tObj->DriverData;
433
434    /* If we don't have a hardware texture, it will be automatically
435     * created with current state before it is used, so we don't have
436     * to do anything now 
437     */
438    if ( (t == NULL) ||
439         (target != GL_TEXTURE_2D &&
440          target != GL_TEXTURE_RECTANGLE_NV) ) {
441       return;
442    }
443
444    switch (pname) {
445    case GL_TEXTURE_MIN_FILTER:
446       driSwapOutTextureObject( (driTextureObject *) t );
447       /* FALLTHROUGH */
448    case GL_TEXTURE_MAG_FILTER:
449       FLUSH_BATCH(mmesa);
450       mgaSetTexFilter( t, tObj->Sampler.MinFilter, tObj->Sampler.MagFilter );
451       break;
452
453    case GL_TEXTURE_WRAP_S:
454    case GL_TEXTURE_WRAP_T:
455       FLUSH_BATCH(mmesa);
456       mgaSetTexWrapping(t,tObj->Sampler.WrapS,tObj->Sampler.WrapT);
457       break;
458
459    case GL_TEXTURE_BORDER_COLOR:
460       FLUSH_BATCH(mmesa);
461       mgaSetTexBorderColor(t, tObj->Sampler.BorderColor.f);
462       break;
463
464    case GL_TEXTURE_BASE_LEVEL:
465    case GL_TEXTURE_MAX_LEVEL:
466    case GL_TEXTURE_MIN_LOD:
467    case GL_TEXTURE_MAX_LOD:
468       /* This isn't the most efficient solution but there doesn't appear to
469        * be a nice alternative.  Since there's no LOD clamping,
470        * we just have to rely on loading the right subset of mipmap levels
471        * to simulate a clamped LOD.
472        */
473       driSwapOutTextureObject( (driTextureObject *) t );
474       break;
475
476    default:
477       return;
478    }
479 }
480
481
482 static void
483 mgaBindTexture( struct gl_context *ctx, GLenum target,
484                   struct gl_texture_object *tObj )
485 {
486    assert( (target != GL_TEXTURE_2D && target != GL_TEXTURE_RECTANGLE_NV) ||
487            (tObj->DriverData != NULL) );
488 }
489
490
491 static void
492 mgaDeleteTexture( struct gl_context *ctx, struct gl_texture_object *tObj )
493 {
494    mgaContextPtr mmesa = MGA_CONTEXT( ctx );
495    driTextureObject * t = (driTextureObject *) tObj->DriverData;
496
497    if ( t ) {
498       if ( mmesa ) {
499          FLUSH_BATCH( mmesa );
500       }
501
502       driDestroyTextureObject( t );
503    }
504
505    /* Free mipmap images and the texture object itself */
506    _mesa_delete_texture_object(ctx, tObj);
507 }
508
509
510 /**
511  * Allocate a new texture object.
512  * Called via ctx->Driver.NewTextureObject.
513  * Note: this function will be called during context creation to
514  * allocate the default texture objects.
515  * Note: we could use containment here to 'derive' the driver-specific
516  * texture object from the core mesa gl_texture_object.  Not done at this time.
517  */
518 static struct gl_texture_object *
519 mgaNewTextureObject( struct gl_context *ctx, GLuint name, GLenum target )
520 {
521    struct gl_texture_object *obj;
522    obj = _mesa_new_texture_object(ctx, name, target);
523    mgaAllocTexObj( obj );
524    return obj;
525 }
526
527
528 void
529 mgaInitTextureFuncs( struct dd_function_table *functions )
530 {
531    functions->ChooseTextureFormat       = mgaChooseTextureFormat;
532    functions->TexImage2D                = mgaTexImage2D;
533    functions->TexSubImage2D             = mgaTexSubImage2D;
534    functions->BindTexture               = mgaBindTexture;
535    functions->NewTextureObject          = mgaNewTextureObject;
536    functions->DeleteTexture             = mgaDeleteTexture;
537    functions->IsTextureResident         = driIsTextureResident;
538    functions->TexEnv                    = mgaTexEnv;
539    functions->TexParameter              = mgaTexParameter;
540 }