Merge commit 'origin/master' into gallium-0.2
[profile/ivi/mesa.git] / src / mesa / main / texcompress.c
1 /*
2  * Mesa 3-D graphics library
3  * Version:  6.5.1
4  *
5  * Copyright (C) 1999-2006  Brian Paul   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  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11  * and/or sell copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included
15  * in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20  * BRIAN PAUL 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  * \file texcompress.c
28  * Helper functions for texture compression.
29  */
30
31
32 #include "glheader.h"
33 #include "imports.h"
34 #include "colormac.h"
35 #include "context.h"
36 #include "image.h"
37 #include "mipmap.h"
38 #include "texcompress.h"
39 #include "texformat.h"
40 #include "texstore.h"
41
42
43 /**
44  * Return list of (and count of) all specific texture compression
45  * formats that are supported.
46  *
47  * \param ctx  the GL context
48  * \param formats  the resulting format list (may be NULL).
49  * \param all  if true return all formats, even those with  some kind
50  *             of restrictions/limitations (See GL_ARB_texture_compression
51  *             spec for more info).
52  *
53  * \return number of formats.
54  */
55 GLuint
56 _mesa_get_compressed_formats(GLcontext *ctx, GLint *formats, GLboolean all)
57 {
58    GLuint n = 0;
59    if (ctx->Extensions.ARB_texture_compression) {
60       if (ctx->Extensions.TDFX_texture_compression_FXT1) {
61          if (formats) {
62             formats[n++] = GL_COMPRESSED_RGB_FXT1_3DFX;
63             formats[n++] = GL_COMPRESSED_RGBA_FXT1_3DFX;
64          }
65          else {
66             n += 2;
67          }
68       }
69       if (ctx->Extensions.EXT_texture_compression_s3tc) {
70          if (formats) {
71             formats[n++] = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
72             /* This format has some restrictions/limitations and so should
73              * not be returned via the GL_COMPRESSED_TEXTURE_FORMATS query.
74              * Specifically, all transparent pixels become black.  NVIDIA
75              * omits this format too.
76              */
77             if (all)
78                formats[n++] = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
79             formats[n++] = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
80             formats[n++] = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
81          }
82          else {
83             n += 3;
84             if (all)
85                n += 1;
86          }
87       }
88       if (ctx->Extensions.S3_s3tc) {
89          if (formats) {
90             formats[n++] = GL_RGB_S3TC;
91             formats[n++] = GL_RGB4_S3TC;
92             formats[n++] = GL_RGBA_S3TC;
93             formats[n++] = GL_RGBA4_S3TC;
94          }
95          else {
96             n += 4;
97          }
98       }
99 #if FEATURE_EXT_texture_sRGB
100       if (ctx->Extensions.EXT_texture_sRGB) {
101          if (formats) {
102             formats[n++] = GL_COMPRESSED_SRGB_S3TC_DXT1_EXT;
103             formats[n++] = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;
104             formats[n++] = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;
105             formats[n++] = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
106          }
107          else {
108             n += 4;
109          }
110       }
111 #endif /* FEATURE_EXT_texture_sRGB */
112    }
113    return n;
114 }
115
116
117
118 /**
119  * Return number of bytes needed to store a texture of the given size
120  * using the specified compressed format.
121  * This is called via the ctx->Driver.CompressedTextureSize function,
122  * unless a device driver overrides it.
123  *
124  * \param width texture width in texels.
125  * \param height texture height in texels.
126  * \param depth texture depth in texels.
127  * \param mesaFormat  one of the MESA_FORMAT_* compressed formats
128  *
129  * \return size in bytes, or zero if bad format
130  */
131 GLuint
132 _mesa_compressed_texture_size( GLcontext *ctx,
133                                GLsizei width, GLsizei height, GLsizei depth,
134                                GLuint mesaFormat )
135 {
136    GLuint size;
137
138    ASSERT(depth == 1);
139    (void) depth;
140    (void) size;
141
142    switch (mesaFormat) {
143 #if FEATURE_texture_fxt1
144    case MESA_FORMAT_RGB_FXT1:
145    case MESA_FORMAT_RGBA_FXT1:
146       /* round up width to next multiple of 8, height to next multiple of 4 */
147       width = (width + 7) & ~7;
148       height = (height + 3) & ~3;
149       /* 16 bytes per 8x4 tile of RGB[A] texels */
150       size = width * height / 2;
151       /* Textures smaller than 8x4 will effectively be made into 8x4 and
152        * take 16 bytes.
153        */
154       if (size < 16)
155          size = 16;
156       return size;
157 #endif
158 #if FEATURE_texture_s3tc
159    case MESA_FORMAT_RGB_DXT1:
160    case MESA_FORMAT_RGBA_DXT1:
161       /* round up width, height to next multiple of 4 */
162       width = (width + 3) & ~3;
163       height = (height + 3) & ~3;
164       /* 8 bytes per 4x4 tile of RGB[A] texels */
165       size = width * height / 2;
166       /* Textures smaller than 4x4 will effectively be made into 4x4 and
167        * take 8 bytes.
168        */
169       if (size < 8)
170          size = 8;
171       return size;
172    case MESA_FORMAT_RGBA_DXT3:
173    case MESA_FORMAT_RGBA_DXT5:
174       /* round up width, height to next multiple of 4 */
175       width = (width + 3) & ~3;
176       height = (height + 3) & ~3;
177       /* 16 bytes per 4x4 tile of RGBA texels */
178       size = width * height; /* simple! */
179       /* Textures smaller than 4x4 will effectively be made into 4x4 and
180        * take 16 bytes.
181        */
182       if (size < 16)
183          size = 16;
184       return size;
185 #endif
186    default:
187       _mesa_problem(ctx, "bad mesaFormat in _mesa_compressed_texture_size");
188       return 0;
189    }
190 }
191
192
193 /**
194  * As above, but format is specified by a GLenum (GL_COMPRESSED_*) token.
195  *
196  * Note: This function CAN NOT return a padded hardware texture size.
197  * That's why we don't call the ctx->Driver.CompressedTextureSize() function.
198  *
199  * We use this function to validate the <imageSize> parameter
200  * of glCompressedTex[Sub]Image1/2/3D(), which must be an exact match.
201  */
202 GLuint
203 _mesa_compressed_texture_size_glenum(GLcontext *ctx,
204                                      GLsizei width, GLsizei height,
205                                      GLsizei depth, GLenum glformat)
206 {
207    GLuint mesaFormat;
208
209    switch (glformat) {
210 #if FEATURE_texture_fxt1
211    case GL_COMPRESSED_RGB_FXT1_3DFX:
212       mesaFormat = MESA_FORMAT_RGB_FXT1;
213       break;
214    case GL_COMPRESSED_RGBA_FXT1_3DFX:
215       mesaFormat = MESA_FORMAT_RGBA_FXT1;
216       break;
217 #endif
218 #if FEATURE_texture_s3tc
219    case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
220    case GL_RGB_S3TC:
221       mesaFormat = MESA_FORMAT_RGB_DXT1;
222       break;
223    case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
224    case GL_RGB4_S3TC:
225       mesaFormat = MESA_FORMAT_RGBA_DXT1;
226       break;
227    case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
228    case GL_RGBA_S3TC:
229       mesaFormat = MESA_FORMAT_RGBA_DXT3;
230       break;
231    case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
232    case GL_RGBA4_S3TC:
233       mesaFormat = MESA_FORMAT_RGBA_DXT5;
234       break;
235 #endif
236    default:
237       return 0;
238    }
239
240    return _mesa_compressed_texture_size(ctx, width, height, depth, mesaFormat);
241 }
242
243
244 /*
245  * Compute the bytes per row in a compressed texture image.
246  * We use this for computing the destination address for sub-texture updates.
247  * \param mesaFormat  one of the MESA_FORMAT_* compressed formats
248  * \param width  image width in pixels
249  * \return stride, in bytes, between rows for compressed image
250  */
251 GLint
252 _mesa_compressed_row_stride(GLuint mesaFormat, GLsizei width)
253 {
254    GLint stride;
255
256    switch (mesaFormat) {
257 #if FEATURE_texture_fxt1
258    case MESA_FORMAT_RGB_FXT1:
259    case MESA_FORMAT_RGBA_FXT1:
260       stride = ((width + 7) / 8) * 16; /* 16 bytes per 8x4 tile */
261       break;
262 #endif
263 #if FEATURE_texture_s3tc
264    case MESA_FORMAT_RGB_DXT1:
265    case MESA_FORMAT_RGBA_DXT1:
266       stride = ((width + 3) / 4) * 8; /* 8 bytes per 4x4 tile */
267       break;
268    case MESA_FORMAT_RGBA_DXT3:
269    case MESA_FORMAT_RGBA_DXT5:
270       stride = ((width + 3) / 4) * 16; /* 16 bytes per 4x4 tile */
271       break;
272 #endif
273    default:
274       _mesa_problem(NULL, "bad mesaFormat in _mesa_compressed_row_stride");
275       return 0;
276    }
277
278    return stride;
279 }
280
281
282 /*
283  * Return the address of the pixel at (col, row, img) in a
284  * compressed texture image.
285  * \param col, row, img - image position (3D)
286  * \param format - compressed image format
287  * \param width - image width
288  * \param image - the image address
289  * \return address of pixel at (row, col)
290  */
291 GLubyte *
292 _mesa_compressed_image_address(GLint col, GLint row, GLint img,
293                                GLuint mesaFormat,
294                                GLsizei width, const GLubyte *image)
295 {
296    GLubyte *addr;
297
298    (void) img;
299
300    /* We try to spot a "complete" subtexture "above" ROW, COL;
301     * this texture is given by appropriate rounding of WIDTH x ROW.
302     * Then we just add the amount left (usually on the left).
303     *
304     * Example for X*Y microtiles (Z bytes each)
305     * offset = Z * (((width + X - 1) / X) * (row / Y) + col / X);
306     */
307
308    switch (mesaFormat) {
309 #if FEATURE_texture_fxt1
310    case MESA_FORMAT_RGB_FXT1:
311    case MESA_FORMAT_RGBA_FXT1:
312       addr = (GLubyte *) image + 16 * (((width + 7) / 8) * (row / 4) + col / 8);
313       break;
314 #endif
315 #if FEATURE_texture_s3tc
316    case MESA_FORMAT_RGB_DXT1:
317    case MESA_FORMAT_RGBA_DXT1:
318       addr = (GLubyte *) image + 8 * (((width + 3) / 4) * (row / 4) + col / 4);
319       break;
320    case MESA_FORMAT_RGBA_DXT3:
321    case MESA_FORMAT_RGBA_DXT5:
322       addr = (GLubyte *) image + 16 * (((width + 3) / 4) * (row / 4) + col / 4);
323       break;
324 #endif
325    default:
326       _mesa_problem(NULL, "bad mesaFormat in _mesa_compressed_image_address");
327       addr = NULL;
328    }
329
330    return addr;
331 }