Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / drivers / dri / sis / sis_tex.c
1 /**************************************************************************
2
3 Copyright 2003 Eric Anholt
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 on the rights to use, copy, modify, merge, publish, distribute, sub
10 license, and/or sell copies of the Software, and to permit persons to whom
11 the 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 NON-INFRINGEMENT. IN NO EVENT SHALL
20 ERIC ANHOLT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 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 /*
27  * Authors:
28  *    Eric Anholt <anholt@FreeBSD.org>
29  */
30
31 #include "swrast/swrast.h"
32 #include "main/imports.h"
33 #include "main/texstore.h"
34 #include "main/texobj.h"
35
36 #include "sis_context.h"
37 #include "sis_alloc.h"
38 #include "sis_tex.h"
39 #include "xmlpool.h"
40
41 #define ALIGN(value, align) (GLubyte *)((long)(value + align - 1) & ~(align - 1))
42
43 #define TEXTURE_HW_ALIGNMENT 4
44 #define TEXTURE_HW_PLUS (4 + 4)
45
46 static sisTexObjPtr
47 sisAllocTexObj( struct gl_texture_object *texObj )
48 {
49    sisTexObjPtr t;
50
51    t = (sisTexObjPtr) CALLOC_STRUCT( sis_tex_obj );
52    texObj->DriverData = t;
53    return t;
54 }
55
56 static void
57 sisAllocTexImage( sisContextPtr smesa, sisTexObjPtr t, int level,
58                   const struct gl_texture_image *image )
59 {
60    char *addr;
61    int size, texel_size;
62
63    if (t->format == 0) {
64       t->format = image->_BaseFormat;
65       switch (image->TexFormat)
66       {
67       case MESA_FORMAT_ARGB8888:
68          t->hwformat = TEXEL_ARGB_8888_32;
69          break;
70       case MESA_FORMAT_ARGB4444:
71          t->hwformat = TEXEL_ARGB_4444_16;
72          break;
73       case MESA_FORMAT_ARGB1555:
74          t->hwformat = TEXEL_ARGB_1555_16;
75          break;
76       case MESA_FORMAT_RGB565:
77          t->hwformat = TEXEL_RGB_565_16;
78          break;
79       case MESA_FORMAT_RGB332:
80          t->hwformat = TEXEL_RGB_332_8;
81          break;
82       case MESA_FORMAT_I8:
83          t->hwformat = TEXEL_I8;
84          break;
85       case MESA_FORMAT_A8:
86          t->hwformat = TEXEL_A8;
87          break;
88       case MESA_FORMAT_L8:
89          t->hwformat = TEXEL_L8;
90          break;
91       case MESA_FORMAT_AL88:
92          t->hwformat = TEXEL_AL88;
93          break;
94       case MESA_FORMAT_YCBCR:
95          t->hwformat = TEXEL_YUV422;
96          break;
97       case MESA_FORMAT_YCBCR_REV:
98          t->hwformat = TEXEL_VUY422;
99          break;
100       default:
101          sis_fatal_error("Bad texture format 0x%x.\n", image->TexFormat);
102       }
103    }
104    assert(t->format == image->_BaseFormat);
105
106    texel_size = _mesa_get_format_bytes(image->TexFormat);
107    size = image->Width * image->Height * texel_size + TEXTURE_HW_PLUS;
108
109    addr = sisAllocFB( smesa, size, &t->image[level].handle );
110    if (addr == NULL) {
111       addr = sisAllocAGP( smesa, size, &t->image[level].handle );
112       if (addr == NULL)
113          sis_fatal_error("Failure to allocate texture memory.\n");
114       t->image[level].memType = AGP_TYPE;
115    }
116    else
117       t->image[level].memType = VIDEO_TYPE;
118    
119    t->image[level].Data = ALIGN(addr, TEXTURE_HW_ALIGNMENT);
120    t->image[level].pitch = image->Width * texel_size;
121    t->image[level].size = image->Width * image->Height * texel_size;
122    t->numImages++;
123 }
124
125 static void
126 sisFreeTexImage( sisContextPtr smesa, sisTexObjPtr t, int level )
127 {
128    assert(level >= 0);
129    assert(level < SIS_MAX_TEXTURE_LEVELS);
130    if (t->image[level].Data == NULL)
131       return;
132
133    switch (t->image[level].memType)
134    {
135    case VIDEO_TYPE:
136       sisFreeFB( smesa, t->image[level].handle );
137       break;
138    case AGP_TYPE:
139       sisFreeAGP( smesa, t->image[level].handle );
140       break;
141    }
142    t->image[level].Data = NULL;
143    t->image[level].handle = NULL;
144    /* If there are no textures loaded any more, reset the hw format so the 
145     * object can be reused for new formats
146     */
147    t->numImages--;
148    if (t->numImages == 0) {
149       t->format = 0;
150       t->hwformat = 0;
151    }
152 }
153
154 static void 
155 sisTexEnv( struct gl_context *ctx, GLenum target, GLenum pname, const GLfloat *param )
156 {
157   sisContextPtr smesa = SIS_CONTEXT(ctx);
158
159   smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURE_ENV;
160 }
161
162 static void
163 sisTexParameter( struct gl_context *ctx, GLenum target,
164                  struct gl_texture_object *texObj, GLenum pname,
165                  const GLfloat *params )
166 {
167    sisContextPtr smesa = SIS_CONTEXT(ctx);
168
169    smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURING;
170 }
171
172 static void
173 sisBindTexture( struct gl_context *ctx, GLenum target,
174                 struct gl_texture_object *texObj )
175 {
176    sisContextPtr smesa = SIS_CONTEXT(ctx);
177    sisTexObjPtr t;
178
179    if ( target == GL_TEXTURE_2D || target == GL_TEXTURE_1D ) {
180       if ( texObj->DriverData == NULL ) {
181          sisAllocTexObj( texObj );
182       }
183    }
184
185    t = texObj->DriverData;
186    if (!t)
187       return;
188
189    if (smesa->PrevTexFormat[ctx->Texture.CurrentUnit] != t->format) {
190       smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURE_ENV;
191       smesa->PrevTexFormat[ctx->Texture.CurrentUnit] = t->format;
192    }
193    smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURING;
194 }
195
196 static void
197 sisDeleteTexture( struct gl_context * ctx, struct gl_texture_object *texObj )
198 {
199    sisContextPtr smesa = SIS_CONTEXT(ctx);
200    sisTexObjPtr t;
201    int i;
202
203    smesa->clearTexCache = GL_TRUE;
204
205    t = texObj->DriverData;
206    if (t == NULL) {
207       /* 
208        * this shows the texture is default object and never be a 
209        * argument of sisTexImage*
210        */
211       return;
212    }
213    for (i = 0; i < SIS_MAX_TEXTURE_LEVELS; i++) {
214       sisFreeTexImage( smesa, t, i );
215    }
216
217    FREE(t);
218    texObj->DriverData = NULL;
219    /* Free mipmap images and the texture object itself */
220    _mesa_delete_texture_object(ctx, texObj);
221 }
222
223 static GLboolean sisIsTextureResident( struct gl_context * ctx,
224                                          struct gl_texture_object *texObj )
225 {
226   return (texObj->DriverData != NULL);
227 }
228
229 static gl_format
230 sisChooseTextureFormat( struct gl_context *ctx, GLint internalFormat,
231                           GLenum format, GLenum type )
232 {
233    sisContextPtr smesa = SIS_CONTEXT(ctx);
234
235    const GLboolean do32bpt =
236        (smesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_32);
237    const GLboolean force16bpt =
238        (smesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FORCE_16);
239
240    switch ( internalFormat ) {
241    case 4:
242    case GL_RGBA:
243    case GL_COMPRESSED_RGBA:
244       switch ( type ) {
245       case GL_UNSIGNED_INT_10_10_10_2:
246       case GL_UNSIGNED_INT_2_10_10_10_REV:
247          return do32bpt ? MESA_FORMAT_ARGB8888 : MESA_FORMAT_ARGB1555;
248       case GL_UNSIGNED_SHORT_4_4_4_4:
249       case GL_UNSIGNED_SHORT_4_4_4_4_REV:
250          return MESA_FORMAT_ARGB4444;
251       case GL_UNSIGNED_SHORT_5_5_5_1:
252       case GL_UNSIGNED_SHORT_1_5_5_5_REV:
253          return MESA_FORMAT_ARGB1555;
254       default:
255          return do32bpt ? MESA_FORMAT_ARGB8888 : MESA_FORMAT_ARGB4444;
256       }
257
258    case 3:
259    case GL_RGB:
260    case GL_COMPRESSED_RGB:
261       switch ( type ) {
262       case GL_UNSIGNED_SHORT_4_4_4_4:
263       case GL_UNSIGNED_SHORT_4_4_4_4_REV:
264          return MESA_FORMAT_ARGB4444;
265       case GL_UNSIGNED_SHORT_5_5_5_1:
266       case GL_UNSIGNED_SHORT_1_5_5_5_REV:
267          return MESA_FORMAT_ARGB1555;
268       case GL_UNSIGNED_SHORT_5_6_5:
269       case GL_UNSIGNED_SHORT_5_6_5_REV:
270          return MESA_FORMAT_RGB565;
271       default:
272          return do32bpt ? MESA_FORMAT_ARGB8888 : MESA_FORMAT_RGB565;
273       }
274
275    case GL_RGBA8:
276    case GL_RGBA12:
277    case GL_RGBA16:
278       return !force16bpt ?
279           MESA_FORMAT_ARGB8888 : MESA_FORMAT_ARGB4444;
280
281    case GL_RGB10_A2:
282       return !force16bpt ?
283           MESA_FORMAT_ARGB8888 : MESA_FORMAT_ARGB1555;
284
285    case GL_RGBA4:
286    case GL_RGBA2:
287       return MESA_FORMAT_ARGB4444;
288
289    case GL_RGB5_A1:
290       return MESA_FORMAT_ARGB1555;
291
292    case GL_RGB8:
293    case GL_RGB10:
294    case GL_RGB12:
295    case GL_RGB16:
296       return !force16bpt ? MESA_FORMAT_ARGB8888 : MESA_FORMAT_RGB565;
297
298    case GL_RGB5:
299    case GL_RGB4:
300       return MESA_FORMAT_RGB565;
301
302    case GL_R3_G3_B2:
303       return MESA_FORMAT_RGB332;
304
305    case GL_ALPHA:
306    case GL_ALPHA4:              /* FIXME: This could use its own texstore */
307    case GL_ALPHA8:
308    case GL_ALPHA12:
309    case GL_ALPHA16:
310    case GL_COMPRESSED_ALPHA:
311       return MESA_FORMAT_A8;
312
313    case 1:
314    case GL_LUMINANCE:
315    case GL_LUMINANCE4:          /* FIXME: This could use its own texstore */
316    case GL_LUMINANCE8:
317    case GL_LUMINANCE12:
318    case GL_LUMINANCE16:
319    case GL_COMPRESSED_LUMINANCE:
320       return MESA_FORMAT_L8;
321
322    case 2:
323    case GL_LUMINANCE_ALPHA:
324    case GL_LUMINANCE4_ALPHA4:   /* FIXME: This could use its own texstore */
325    case GL_LUMINANCE6_ALPHA2:   /* FIXME: This could use its own texstore */
326    case GL_LUMINANCE8_ALPHA8:
327    case GL_LUMINANCE12_ALPHA4:  /* FIXME: This could use its own texstore */
328    case GL_LUMINANCE12_ALPHA12:
329    case GL_LUMINANCE16_ALPHA16:
330    case GL_COMPRESSED_LUMINANCE_ALPHA:
331       return MESA_FORMAT_AL88;
332
333    case GL_INTENSITY:
334    case GL_INTENSITY4:
335    case GL_INTENSITY8:
336    case GL_INTENSITY12:
337    case GL_INTENSITY16:
338    case GL_COMPRESSED_INTENSITY:
339       return MESA_FORMAT_I8;
340
341    case GL_YCBCR_MESA:
342       if (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
343           type == GL_UNSIGNED_BYTE)
344          return MESA_FORMAT_YCBCR;
345       else
346          return MESA_FORMAT_YCBCR_REV;
347
348    default:
349       _mesa_problem(ctx, "unexpected format in sisDDChooseTextureFormat: %d",
350          internalFormat);
351       return MESA_FORMAT_NONE;
352    }
353 }
354
355 static void sisTexImage1D( struct gl_context *ctx, GLenum target, GLint level,
356                              GLint internalFormat,
357                              GLint width, GLint border,
358                              GLenum format, GLenum type, const GLvoid *pixels,
359                              const struct gl_pixelstore_attrib *packing,
360                              struct gl_texture_object *texObj,
361                              struct gl_texture_image *texImage )
362 {
363    sisContextPtr smesa = SIS_CONTEXT(ctx);
364    sisTexObjPtr t;
365
366    if ( texObj->DriverData == NULL )
367       sisAllocTexObj( texObj );
368    t = texObj->DriverData;
369
370    /* Note, this will call sisChooseTextureFormat */
371    _mesa_store_teximage1d( ctx, target, level, internalFormat,
372                            width, border, format, type,
373                            pixels, packing, texObj, texImage );
374
375    /* Allocate offscreen space for the texture */
376    sisFreeTexImage(smesa, t, level);
377    sisAllocTexImage(smesa, t, level, texImage);
378
379    /* Upload the texture */
380    WaitEngIdle(smesa);
381    memcpy(t->image[level].Data, texImage->Data, t->image[level].size);
382    
383    if (smesa->PrevTexFormat[ctx->Texture.CurrentUnit] != t->format)
384    {
385       smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURE_ENV;
386       smesa->PrevTexFormat[ctx->Texture.CurrentUnit] = t->format;
387    }
388    smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURING;
389 }
390
391
392 static void sisTexSubImage1D( struct gl_context *ctx,
393                                 GLenum target,
394                                 GLint level,
395                                 GLint xoffset,
396                                 GLsizei width,
397                                 GLenum format, GLenum type,
398                                 const GLvoid *pixels,
399                                 const struct gl_pixelstore_attrib *packing,
400                                 struct gl_texture_object *texObj,
401                                 struct gl_texture_image *texImage )
402 {
403    sisContextPtr smesa = SIS_CONTEXT(ctx);
404    sisTexObjPtr t;
405    GLuint copySize;
406    GLint texelBytes;
407    const char *src;
408    GLubyte *dst;
409
410    if ( texObj->DriverData == NULL )
411       sisAllocTexObj( texObj );
412    t = texObj->DriverData;
413
414    _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
415                              format, type, pixels, packing, texObj,
416                              texImage);
417
418    /* Allocate offscreen space for the texture */
419    sisFreeTexImage(smesa, t, level);
420    sisAllocTexImage(smesa, t, level, texImage);
421
422    /* Upload the texture */
423    WaitEngIdle(smesa);
424    texelBytes = _mesa_get_format_bytes(texImage->TexFormat);
425
426    copySize = width * texelBytes;
427    src = (char *)texImage->Data + xoffset * texelBytes;
428    dst = t->image[level].Data + xoffset * texelBytes;
429
430    memcpy( dst, src, copySize );
431
432    smesa->clearTexCache = GL_TRUE;
433
434    if (smesa->PrevTexFormat[ctx->Texture.CurrentUnit] != t->format)
435    {
436       smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURE_ENV;
437       smesa->PrevTexFormat[ctx->Texture.CurrentUnit] = t->format;
438    }
439    smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURING;
440 }
441
442 static void sisTexImage2D( struct gl_context *ctx, GLenum target, GLint level,
443                              GLint internalFormat,
444                              GLint width, GLint height, GLint border,
445                              GLenum format, GLenum type, const GLvoid *pixels,
446                              const struct gl_pixelstore_attrib *packing,
447                              struct gl_texture_object *texObj,
448                              struct gl_texture_image *texImage )
449 {
450    sisContextPtr smesa = SIS_CONTEXT(ctx);
451    sisTexObjPtr t;
452
453    if ( texObj->DriverData == NULL )
454       sisAllocTexObj( texObj );
455    t = texObj->DriverData;
456
457    /* Note, this will call sisChooseTextureFormat */
458    _mesa_store_teximage2d(ctx, target, level, internalFormat,
459                           width, height, border, format, type, pixels,
460                           &ctx->Unpack, texObj, texImage);
461
462    /* Allocate offscreen space for the texture */
463    sisFreeTexImage(smesa, t, level);
464    sisAllocTexImage(smesa, t, level, texImage);
465
466    /* Upload the texture */
467    WaitEngIdle(smesa);
468    memcpy(t->image[level].Data, texImage->Data, t->image[level].size);
469    
470    if (smesa->PrevTexFormat[ctx->Texture.CurrentUnit] != t->format)
471    {
472       smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURE_ENV;
473       smesa->PrevTexFormat[ctx->Texture.CurrentUnit] = t->format;
474    }
475    smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURING;
476 }
477
478 static void sisTexSubImage2D( struct gl_context *ctx,
479                                 GLenum target,
480                                 GLint level,
481                                 GLint xoffset, GLint yoffset,
482                                 GLsizei width, GLsizei height,
483                                 GLenum format, GLenum type,
484                                 const GLvoid *pixels,
485                                 const struct gl_pixelstore_attrib *packing,
486                                 struct gl_texture_object *texObj,
487                                 struct gl_texture_image *texImage )
488 {
489    sisContextPtr smesa = SIS_CONTEXT(ctx);
490    sisTexObjPtr t;
491    GLuint copySize;
492    GLint texelBytes;
493    const char *src;
494    GLubyte *dst;
495    int j;
496    GLuint soffset;
497
498    if ( texObj->DriverData == NULL )
499       sisAllocTexObj( texObj );
500    t = texObj->DriverData;
501
502    _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
503                              height, format, type, pixels, packing, texObj,
504                              texImage);
505
506    /* Allocate offscreen space for the texture */
507    sisFreeTexImage(smesa, t, level);
508    sisAllocTexImage(smesa, t, level, texImage);
509
510    /* Upload the texture */
511    WaitEngIdle(smesa);
512    texelBytes = _mesa_get_format_bytes(texImage->TexFormat);
513
514    copySize = width * texelBytes;
515    src = (char *)texImage->Data + (xoffset + yoffset * texImage->Width) *
516       texelBytes;
517    dst = t->image[level].Data + (xoffset + yoffset * texImage->Width) *
518       texelBytes;
519    soffset = texImage->Width * texelBytes;
520
521    for (j = yoffset; j < yoffset + height; j++) {
522       memcpy( dst, src, copySize );
523       src += soffset;
524       dst += soffset;
525    }
526
527    smesa->clearTexCache = GL_TRUE;
528
529    if (smesa->PrevTexFormat[ctx->Texture.CurrentUnit] != t->format)
530    {
531       smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURE_ENV;
532       smesa->PrevTexFormat[ctx->Texture.CurrentUnit] = t->format;
533    }
534    smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURING;
535 }
536
537
538 /**
539  * Allocate a new texture object.
540  * Called via ctx->Driver.NewTextureObject.
541  * Note: this function will be called during context creation to
542  * allocate the default texture objects.
543  * Note: we could use containment here to 'derive' the driver-specific
544  * texture object from the core mesa gl_texture_object.  Not done at this time.
545  */
546 static struct gl_texture_object *
547 sisNewTextureObject( struct gl_context *ctx, GLuint name, GLenum target )
548 {
549    struct gl_texture_object *obj;
550    obj = _mesa_new_texture_object(ctx, name, target);
551    return obj;
552 }
553
554
555 void sisInitTextureFuncs( struct dd_function_table *functions )
556 {
557    functions->TexEnv                    = sisTexEnv;
558    functions->ChooseTextureFormat       = sisChooseTextureFormat;
559    functions->TexImage1D                = sisTexImage1D;
560    functions->TexSubImage1D             = sisTexSubImage1D;
561    functions->TexImage2D                = sisTexImage2D;
562    functions->TexSubImage2D             = sisTexSubImage2D;
563    functions->TexParameter              = sisTexParameter;
564    functions->BindTexture               = sisBindTexture;
565    functions->NewTextureObject          = sisNewTextureObject;
566    functions->DeleteTexture             = sisDeleteTexture;
567    functions->IsTextureResident = sisIsTextureResident;
568 }