Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / drivers / dri / mach64 / mach64_tex.c
1 /* -*- mode: c; c-basic-offset: 3 -*- */
2 /*
3  * Copyright 2000 Gareth Hughes
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice (including the next
14  * paragraph) shall be included in all copies or substantial portions of the
15  * Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20  * GARETH HUGHES BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24
25 /*
26  * Authors:
27  *      Gareth Hughes <gareth@valinux.com>
28  *      Leif Delgass <ldelgass@retinalburn.net>
29  *      José Fonseca <j_r_fonseca@yahoo.co.uk>
30  */
31
32 #include "mach64_context.h"
33 #include "mach64_ioctl.h"
34 #include "mach64_tex.h"
35
36 #include "main/simple_list.h"
37 #include "main/enums.h"
38 #include "main/texstore.h"
39 #include "main/teximage.h"
40 #include "main/texobj.h"
41 #include "main/imports.h"
42
43
44 static void mach64SetTexWrap( mach64TexObjPtr t,
45                               GLenum swrap, GLenum twrap )
46 {
47    switch ( swrap ) {
48    case GL_CLAMP:
49    case GL_CLAMP_TO_EDGE:
50    case GL_CLAMP_TO_BORDER:
51       t->ClampS = GL_TRUE;
52       break;
53    case GL_REPEAT:
54       t->ClampS = GL_FALSE;
55       break;
56    }
57
58    switch ( twrap ) {
59    case GL_CLAMP:
60    case GL_CLAMP_TO_EDGE:
61    case GL_CLAMP_TO_BORDER:
62       t->ClampT = GL_TRUE;
63       break;
64    case GL_REPEAT:
65       t->ClampT = GL_FALSE;
66       break;
67    }
68 }
69
70 static void mach64SetTexFilter( mach64TexObjPtr t,
71                                 GLenum minf, GLenum magf )
72 {
73    switch ( minf ) {
74    case GL_NEAREST:
75    case GL_NEAREST_MIPMAP_NEAREST:
76    case GL_NEAREST_MIPMAP_LINEAR:
77       t->BilinearMin = GL_FALSE;
78       break;
79    case GL_LINEAR:
80    case GL_LINEAR_MIPMAP_NEAREST:
81    case GL_LINEAR_MIPMAP_LINEAR:
82       t->BilinearMin = GL_TRUE;
83       break;
84    }
85
86    switch ( magf ) {
87    case GL_NEAREST:
88       t->BilinearMag = GL_FALSE;
89       break;
90    case GL_LINEAR:
91       t->BilinearMag = GL_TRUE;
92       break;
93    }
94 }
95
96 static void mach64SetTexBorderColor( mach64TexObjPtr t, const GLfloat c[4] )
97 {
98 #if 0
99    GLuint border = mach64PackColor( 4, c[0], c[1], c[2], c[3] );
100 #endif
101 }
102
103
104 static mach64TexObjPtr
105 mach64AllocTexObj( struct gl_texture_object *texObj )
106 {
107    mach64TexObjPtr t;
108
109    if ( MACH64_DEBUG & DEBUG_VERBOSE_API )
110       fprintf( stderr, "%s( %p )\n", __FUNCTION__, texObj );
111
112    t = (mach64TexObjPtr) CALLOC_STRUCT( mach64_texture_object );
113    texObj->DriverData = t;
114    if ( !t )
115       return NULL;
116
117    /* Initialize non-image-dependent parts of the state:
118     */
119    t->base.tObj = texObj;
120    t->base.dirty_images[0] = (1 << 0);
121
122    t->bufAddr = 0;
123
124    make_empty_list( (driTextureObject *) t );
125
126    mach64SetTexWrap( t, texObj->Sampler.WrapS, texObj->Sampler.WrapT );
127    mach64SetTexFilter( t, texObj->Sampler.MinFilter, texObj->Sampler.MagFilter );
128    mach64SetTexBorderColor( t, texObj->Sampler.BorderColor.f );
129
130    return t;
131 }
132
133
134 /* Called by the _mesa_store_teximage[123]d() functions. */
135 static gl_format
136 mach64ChooseTextureFormat( struct gl_context *ctx, GLint internalFormat,
137                            GLenum format, GLenum type )
138 {
139    mach64ContextPtr mmesa = MACH64_CONTEXT(ctx);
140    (void) format;
141    (void) type;
142
143    switch ( internalFormat ) {
144    case GL_ALPHA:
145    case GL_ALPHA4:
146    case GL_ALPHA8:
147    case GL_ALPHA12:
148    case GL_ALPHA16:
149    case GL_COMPRESSED_ALPHA:
150    case 2:
151    case GL_LUMINANCE_ALPHA:
152    case GL_LUMINANCE4_ALPHA4:
153    case GL_LUMINANCE6_ALPHA2:
154    case GL_LUMINANCE8_ALPHA8:
155    case GL_LUMINANCE12_ALPHA4:
156    case GL_LUMINANCE12_ALPHA12:
157    case GL_LUMINANCE16_ALPHA16:
158    case GL_COMPRESSED_LUMINANCE_ALPHA:
159    case 4:
160    case GL_RGBA:
161    case GL_RGBA2:
162    case GL_COMPRESSED_RGBA:
163       if (mmesa->mach64Screen->cpp == 4)
164          return MESA_FORMAT_ARGB8888;
165       else
166          return MESA_FORMAT_ARGB4444;
167
168    case GL_RGB5_A1:
169       if (mmesa->mach64Screen->cpp == 4)
170          return MESA_FORMAT_ARGB8888;
171       else
172          return MESA_FORMAT_ARGB1555;
173
174    case GL_RGBA8:
175    case GL_RGB10_A2:
176    case GL_RGBA12:
177    case GL_RGBA16:
178    case GL_RGBA4:
179       if (mmesa->mach64Screen->cpp == 4)
180          return MESA_FORMAT_ARGB8888;
181       else
182          return MESA_FORMAT_ARGB4444;
183
184    case 3:
185    case GL_RGB:
186    case GL_R3_G3_B2:
187    case GL_RGB4:
188    case GL_RGB5:
189    case GL_RGB8:
190    case GL_RGB10:
191    case GL_RGB12:
192    case GL_RGB16:
193    case GL_COMPRESSED_RGB:
194       if (mmesa->mach64Screen->cpp == 4)
195          return MESA_FORMAT_ARGB8888;
196       else
197          return MESA_FORMAT_RGB565;
198
199    case 1:
200    case GL_LUMINANCE:
201    case GL_LUMINANCE4:
202    case GL_LUMINANCE8:
203    case GL_LUMINANCE12:
204    case GL_LUMINANCE16:
205    case GL_COMPRESSED_LUMINANCE:
206       if (mmesa->mach64Screen->cpp == 4)
207          return MESA_FORMAT_ARGB8888; /* inefficient but accurate */
208       else
209          return MESA_FORMAT_ARGB1555;
210
211    case GL_INTENSITY4:
212    case GL_INTENSITY:
213    case GL_INTENSITY8:
214    case GL_INTENSITY12:
215    case GL_INTENSITY16:
216    case GL_COMPRESSED_INTENSITY:
217       if (mmesa->mach64Screen->cpp == 4)
218          return MESA_FORMAT_ARGB8888; /* inefficient but accurate */
219       else
220          return MESA_FORMAT_ARGB4444;
221
222    case GL_COLOR_INDEX:
223    case GL_COLOR_INDEX1_EXT:
224    case GL_COLOR_INDEX2_EXT:
225    case GL_COLOR_INDEX4_EXT:
226    case GL_COLOR_INDEX8_EXT:
227    case GL_COLOR_INDEX12_EXT:
228    case GL_COLOR_INDEX16_EXT:
229       return MESA_FORMAT_CI8;
230
231    case GL_YCBCR_MESA:
232       if (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
233           type == GL_UNSIGNED_BYTE)
234          return MESA_FORMAT_YCBCR;
235       else
236          return MESA_FORMAT_YCBCR_REV;
237
238    default:
239       _mesa_problem( ctx, "unexpected format in %s", __FUNCTION__ );
240       return MESA_FORMAT_NONE;
241    }
242 }
243
244 static void mach64TexImage1D( struct gl_context *ctx, GLenum target, GLint level,
245                             GLint internalFormat,
246                             GLint width, GLint border,
247                             GLenum format, GLenum type, const GLvoid *pixels,
248                             const struct gl_pixelstore_attrib *packing,
249                             struct gl_texture_object *texObj,
250                             struct gl_texture_image *texImage )
251 {
252    mach64ContextPtr mmesa = MACH64_CONTEXT(ctx);
253    driTextureObject * t = (driTextureObject *) texObj->DriverData;
254
255    if ( t ) {
256       driSwapOutTextureObject( t );
257    }
258    else {
259       t = (driTextureObject *) mach64AllocTexObj(texObj);
260       if (!t) {
261          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
262          return;
263       }
264    }
265
266    /* Note, this will call mach64ChooseTextureFormat */
267    _mesa_store_teximage1d( ctx, target, level, internalFormat,
268                            width, border, format, type,
269                            pixels, packing, texObj, texImage );
270
271    mmesa->new_state |= MACH64_NEW_TEXTURE;
272 }
273
274 static void mach64TexSubImage1D( struct gl_context *ctx,
275                                  GLenum target,
276                                  GLint level,
277                                  GLint xoffset,
278                                  GLsizei width,
279                                  GLenum format, GLenum type,
280                                  const GLvoid *pixels,
281                                  const struct gl_pixelstore_attrib *packing,
282                                  struct gl_texture_object *texObj,
283                                  struct gl_texture_image *texImage )
284 {
285    mach64ContextPtr mmesa = MACH64_CONTEXT(ctx);
286    driTextureObject * t = (driTextureObject *) texObj->DriverData;
287
288    assert( t ); /* this _should_ be true */
289    if ( t ) {
290       driSwapOutTextureObject( t );
291    }
292    else {
293       t = (driTextureObject *) mach64AllocTexObj(texObj);
294       if (!t) {
295          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
296          return;
297       }
298    }
299
300    _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
301                              format, type, pixels, packing, texObj,
302                              texImage);
303
304    mmesa->new_state |= MACH64_NEW_TEXTURE;
305 }
306
307 static void mach64TexImage2D( struct gl_context *ctx, GLenum target, GLint level,
308                               GLint internalFormat,
309                               GLint width, GLint height, GLint border,
310                               GLenum format, GLenum type, const GLvoid *pixels,
311                               const struct gl_pixelstore_attrib *packing,
312                               struct gl_texture_object *texObj,
313                               struct gl_texture_image *texImage )
314 {
315    mach64ContextPtr mmesa = MACH64_CONTEXT(ctx);
316    driTextureObject * t = (driTextureObject *) texObj->DriverData;
317
318    if ( t ) {
319       driSwapOutTextureObject( t );
320    }
321    else {
322       t = (driTextureObject *) mach64AllocTexObj(texObj);
323       if (!t) {
324          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
325          return;
326       }
327    }
328
329    /* Note, this will call mach64ChooseTextureFormat */
330    _mesa_store_teximage2d( ctx, target, level, internalFormat,
331                            width, height, border, format, type, pixels,
332                            &ctx->Unpack, texObj, texImage );
333
334    mmesa->new_state |= MACH64_NEW_TEXTURE;
335 }
336
337 static void mach64TexSubImage2D( struct gl_context *ctx,
338                                  GLenum target,
339                                  GLint level,
340                                  GLint xoffset, GLint yoffset,
341                                  GLsizei width, GLsizei height,
342                                  GLenum format, GLenum type,
343                                  const GLvoid *pixels,
344                                  const struct gl_pixelstore_attrib *packing,
345                                  struct gl_texture_object *texObj,
346                                  struct gl_texture_image *texImage )
347 {
348    mach64ContextPtr mmesa = MACH64_CONTEXT(ctx);
349    driTextureObject * t = (driTextureObject *) texObj->DriverData;
350
351    assert( t ); /* this _should_ be true */
352    if ( t ) {
353       driSwapOutTextureObject( t );
354    }
355    else {
356       t = (driTextureObject *) mach64AllocTexObj(texObj);
357       if (!t) {
358          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
359          return;
360       }
361    }
362
363    _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
364                              height, format, type, pixels, packing, texObj,
365                              texImage);
366
367    mmesa->new_state |= MACH64_NEW_TEXTURE;
368 }
369
370 /* ================================================================
371  * Device Driver API texture functions
372  */
373
374 static void mach64DDTexEnv( struct gl_context *ctx, GLenum target,
375                             GLenum pname, const GLfloat *param )
376 {
377    mach64ContextPtr mmesa = MACH64_CONTEXT(ctx);
378 #if 0
379    struct gl_texture_unit *texUnit;
380    GLubyte c[4];
381 #endif
382
383    if ( MACH64_DEBUG & DEBUG_VERBOSE_API ) {
384       fprintf( stderr, "%s( %s )\n",
385                __FUNCTION__, _mesa_lookup_enum_by_nr( pname ) );
386    }
387
388    switch ( pname ) {
389    case GL_TEXTURE_ENV_MODE:
390       FLUSH_BATCH( mmesa );
391       mmesa->new_state |= MACH64_NEW_TEXTURE | MACH64_NEW_ALPHA;
392       break;
393
394 #if 0
395    case GL_TEXTURE_ENV_COLOR:
396       texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
397       CLAMPED_FLOAT_TO_UBYTE( c[0], texUnit->EnvColor[0] );
398       CLAMPED_FLOAT_TO_UBYTE( c[1], texUnit->EnvColor[1] );
399       CLAMPED_FLOAT_TO_UBYTE( c[2], texUnit->EnvColor[2] );
400       CLAMPED_FLOAT_TO_UBYTE( c[3], texUnit->EnvColor[3] );
401       mmesa->env_color = mach64PackColor( 32, c[0], c[1], c[2], c[3] );
402       if ( mmesa->setup.constant_color_c != mmesa->env_color ) {
403          FLUSH_BATCH( mmesa );
404          mmesa->setup.constant_color_c = mmesa->env_color;
405
406          mmesa->new_state |= MACH64_NEW_TEXTURE;
407
408          /* More complex multitexture/multipass fallbacks for GL_BLEND
409           * can be done later, but this allows a single pass GL_BLEND
410           * in some cases (ie. Performer town demo).
411           */
412          mmesa->blend_flags &= ~MACH64_BLEND_ENV_COLOR;
413          if ( mmesa->env_color != 0x00000000 &&
414               mmesa->env_color != 0xff000000 &&
415               mmesa->env_color != 0x00ffffff &&
416               mmesa->env_color != 0xffffffff )) {       
417             mmesa->blend_flags |= MACH64_BLEND_ENV_COLOR;
418          }
419       }
420       break;
421 #endif
422
423    default:
424       return;
425    }
426 }
427
428 static void mach64DDTexParameter( struct gl_context *ctx, GLenum target,
429                                   struct gl_texture_object *tObj,
430                                   GLenum pname, const GLfloat *params )
431 {
432    mach64ContextPtr mmesa = MACH64_CONTEXT(ctx);
433    mach64TexObjPtr t = (mach64TexObjPtr)tObj->DriverData;
434
435    if ( MACH64_DEBUG & DEBUG_VERBOSE_API ) {
436       fprintf( stderr, "%s( %s )\n",
437                __FUNCTION__, _mesa_lookup_enum_by_nr( pname ) );
438    }
439
440    if ( ( target != GL_TEXTURE_2D ) &&
441         ( target != GL_TEXTURE_1D ) ) {
442       return;
443    }
444
445    if (!t) {
446       t = mach64AllocTexObj(tObj);
447       if (!t) {
448          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexParameter");
449          return;
450       }
451    }
452
453    switch ( pname ) {
454    case GL_TEXTURE_MIN_FILTER:
455    case GL_TEXTURE_MAG_FILTER:
456       if ( t->base.bound ) FLUSH_BATCH( mmesa );
457       mach64SetTexFilter( t, tObj->Sampler.MinFilter, tObj->Sampler.MagFilter );
458       break;
459
460    case GL_TEXTURE_WRAP_S:
461    case GL_TEXTURE_WRAP_T:
462       if ( t->base.bound ) FLUSH_BATCH( mmesa );
463       mach64SetTexWrap( t, tObj->Sampler.WrapS, tObj->Sampler.WrapT );
464       break;
465
466    case GL_TEXTURE_BORDER_COLOR:
467       if ( t->base.bound ) FLUSH_BATCH( mmesa );
468       mach64SetTexBorderColor( t, tObj->Sampler.BorderColor.f );
469       break;
470
471    case GL_TEXTURE_BASE_LEVEL:
472       /* From Radeon/Rage128:
473        * This isn't the most efficient solution but there doesn't appear to
474        * be a nice alternative.  Since there's no LOD clamping,
475        * we just have to rely on loading the right subset of mipmap levels
476        * to simulate a clamped LOD.  
477        *
478        * For mach64 we're only concerned with the base level
479        * since that's the only texture we upload.
480        */
481       if ( t->base.bound ) FLUSH_BATCH( mmesa );
482       driSwapOutTextureObject( (driTextureObject *) t );
483       break;
484
485    default:
486       return;
487    }
488
489    mmesa->new_state |= MACH64_NEW_TEXTURE;
490 }
491
492 static void mach64DDBindTexture( struct gl_context *ctx, GLenum target,
493                                  struct gl_texture_object *tObj )
494 {
495    mach64ContextPtr mmesa = MACH64_CONTEXT(ctx);
496    GLint unit = ctx->Texture.CurrentUnit;
497
498    if ( MACH64_DEBUG & DEBUG_VERBOSE_API ) {
499       fprintf( stderr, "%s( %p ) unit=%d\n",
500                __FUNCTION__, tObj, unit );
501    }
502
503    FLUSH_BATCH( mmesa );
504
505    if ( mmesa->CurrentTexObj[unit] ) {
506       mmesa->CurrentTexObj[unit]->base.bound &= ~(1 << unit);
507       mmesa->CurrentTexObj[unit] = NULL;
508    }
509
510    mmesa->new_state |= MACH64_NEW_TEXTURE;
511 }
512
513 static void mach64DDDeleteTexture( struct gl_context *ctx,
514                                    struct gl_texture_object *tObj )
515 {
516    mach64ContextPtr mmesa = MACH64_CONTEXT(ctx);
517    driTextureObject * t = (driTextureObject *) tObj->DriverData;
518
519    if ( t ) {
520       if ( t->bound && mmesa ) {
521          FLUSH_BATCH( mmesa );
522
523          mmesa->new_state |= MACH64_NEW_TEXTURE;
524       }
525
526       driDestroyTextureObject( t );
527
528       /* Free mipmap images and the texture object itself */
529       _mesa_delete_texture_object(ctx, tObj);
530    }
531 }
532
533 /**
534  * Allocate a new texture object.
535  * Called via ctx->Driver.NewTextureObject.
536  * Note: we could use containment here to 'derive' the driver-specific
537  * texture object from the core mesa gl_texture_object.  Not done at this time.
538  */
539 static struct gl_texture_object *
540 mach64NewTextureObject( struct gl_context *ctx, GLuint name, GLenum target )
541 {
542    struct gl_texture_object *obj;
543    obj = _mesa_new_texture_object(ctx, name, target);
544    mach64AllocTexObj( obj );
545    return obj;
546 }
547
548 void mach64InitTextureFuncs( struct dd_function_table *functions )
549 {
550    functions->TexEnv                    = mach64DDTexEnv;
551    functions->ChooseTextureFormat       = mach64ChooseTextureFormat;
552    functions->TexImage1D                = mach64TexImage1D;
553    functions->TexSubImage1D             = mach64TexSubImage1D;
554    functions->TexImage2D                = mach64TexImage2D;
555    functions->TexSubImage2D             = mach64TexSubImage2D;
556    functions->TexParameter              = mach64DDTexParameter;
557    functions->BindTexture               = mach64DDBindTexture;
558    functions->NewTextureObject          = mach64NewTextureObject;
559    functions->DeleteTexture             = mach64DDDeleteTexture;
560    functions->IsTextureResident         = driIsTextureResident;
561
562    driInitTextureFormats();
563 }