OSDN Git Service

mesa: remove outdated version lines in comments
[android-x86/external-mesa.git] / src / mesa / main / texcompress_s3tc.c
1 /*
2  * Mesa 3-D graphics library
3  *
4  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
5  * Copyright (c) 2008 VMware, Inc.
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  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23  * OTHER DEALINGS IN THE SOFTWARE.
24  */
25
26
27 /**
28  * \file texcompress_s3tc.c
29  * GL_EXT_texture_compression_s3tc support.
30  */
31
32 #ifndef USE_EXTERNAL_DXTN_LIB
33 #define USE_EXTERNAL_DXTN_LIB 1
34 #endif
35
36 #include "glheader.h"
37 #include "imports.h"
38 #include "colormac.h"
39 #include "dlopen.h"
40 #include "image.h"
41 #include "macros.h"
42 #include "mtypes.h"
43 #include "texcompress.h"
44 #include "texcompress_s3tc.h"
45 #include "texstore.h"
46 #include "format_unpack.h"
47
48
49 #if defined(_WIN32) || defined(WIN32)
50 #define DXTN_LIBNAME "dxtn.dll"
51 #define RTLD_LAZY 0
52 #define RTLD_GLOBAL 0
53 #elif defined(__DJGPP__)
54 #define DXTN_LIBNAME "dxtn.dxe"
55 #else
56 #define DXTN_LIBNAME "libtxc_dxtn.so"
57 #endif
58
59 typedef void (*dxtFetchTexelFuncExt)( GLint srcRowstride, const GLubyte *pixdata, GLint col, GLint row, GLvoid *texelOut );
60
61 static dxtFetchTexelFuncExt fetch_ext_rgb_dxt1 = NULL;
62 static dxtFetchTexelFuncExt fetch_ext_rgba_dxt1 = NULL;
63 static dxtFetchTexelFuncExt fetch_ext_rgba_dxt3 = NULL;
64 static dxtFetchTexelFuncExt fetch_ext_rgba_dxt5 = NULL;
65
66 typedef void (*dxtCompressTexFuncExt)(GLint srccomps, GLint width,
67                                       GLint height, const GLubyte *srcPixData,
68                                       GLenum destformat, GLubyte *dest,
69                                       GLint dstRowStride);
70
71 static dxtCompressTexFuncExt ext_tx_compress_dxtn = NULL;
72
73 static void *dxtlibhandle = NULL;
74
75
76 void
77 _mesa_init_texture_s3tc( struct gl_context *ctx )
78 {
79    /* called during context initialization */
80    ctx->Mesa_DXTn = GL_FALSE;
81 #if USE_EXTERNAL_DXTN_LIB
82    if (!dxtlibhandle) {
83       dxtlibhandle = _mesa_dlopen(DXTN_LIBNAME, 0);
84       if (!dxtlibhandle) {
85          _mesa_warning(ctx, "couldn't open " DXTN_LIBNAME ", software DXTn "
86             "compression/decompression unavailable");
87       }
88       else {
89          /* the fetch functions are not per context! Might be problematic... */
90          fetch_ext_rgb_dxt1 = (dxtFetchTexelFuncExt)
91             _mesa_dlsym(dxtlibhandle, "fetch_2d_texel_rgb_dxt1");
92          fetch_ext_rgba_dxt1 = (dxtFetchTexelFuncExt)
93             _mesa_dlsym(dxtlibhandle, "fetch_2d_texel_rgba_dxt1");
94          fetch_ext_rgba_dxt3 = (dxtFetchTexelFuncExt)
95             _mesa_dlsym(dxtlibhandle, "fetch_2d_texel_rgba_dxt3");
96          fetch_ext_rgba_dxt5 = (dxtFetchTexelFuncExt)
97             _mesa_dlsym(dxtlibhandle, "fetch_2d_texel_rgba_dxt5");
98          ext_tx_compress_dxtn = (dxtCompressTexFuncExt)
99             _mesa_dlsym(dxtlibhandle, "tx_compress_dxtn");
100
101          if (!fetch_ext_rgb_dxt1 ||
102              !fetch_ext_rgba_dxt1 ||
103              !fetch_ext_rgba_dxt3 ||
104              !fetch_ext_rgba_dxt5 ||
105              !ext_tx_compress_dxtn) {
106             _mesa_warning(ctx, "couldn't reference all symbols in "
107                DXTN_LIBNAME ", software DXTn compression/decompression "
108                "unavailable");
109             fetch_ext_rgb_dxt1 = NULL;
110             fetch_ext_rgba_dxt1 = NULL;
111             fetch_ext_rgba_dxt3 = NULL;
112             fetch_ext_rgba_dxt5 = NULL;
113             ext_tx_compress_dxtn = NULL;
114             _mesa_dlclose(dxtlibhandle);
115             dxtlibhandle = NULL;
116          }
117       }
118    }
119    if (dxtlibhandle) {
120       ctx->Mesa_DXTn = GL_TRUE;
121    }
122 #else
123    (void) ctx;
124 #endif
125 }
126
127 /**
128  * Store user's image in rgb_dxt1 format.
129  */
130 GLboolean
131 _mesa_texstore_rgb_dxt1(TEXSTORE_PARAMS)
132 {
133    const GLubyte *pixels;
134    GLubyte *dst;
135    const GLubyte *tempImage = NULL;
136
137    ASSERT(dstFormat == MESA_FORMAT_RGB_DXT1 ||
138           dstFormat == MESA_FORMAT_SRGB_DXT1);
139
140    if (srcFormat != GL_RGB ||
141        srcType != GL_UNSIGNED_BYTE ||
142        ctx->_ImageTransferState ||
143        srcPacking->RowLength != srcWidth ||
144        srcPacking->SwapBytes) {
145       /* convert image to RGB/GLubyte */
146       tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
147                                              baseInternalFormat,
148                                              _mesa_get_format_base_format(dstFormat),
149                                              srcWidth, srcHeight, srcDepth,
150                                              srcFormat, srcType, srcAddr,
151                                              srcPacking);
152       if (!tempImage)
153          return GL_FALSE; /* out of memory */
154       pixels = tempImage;
155       srcFormat = GL_RGB;
156    }
157    else {
158       pixels = _mesa_image_address2d(srcPacking, srcAddr, srcWidth, srcHeight,
159                                      srcFormat, srcType, 0, 0);
160    }
161
162    dst = dstSlices[0];
163
164    if (ext_tx_compress_dxtn) {
165       (*ext_tx_compress_dxtn)(3, srcWidth, srcHeight, pixels,
166                               GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
167                               dst, dstRowStride);
168    }
169    else {
170       _mesa_warning(ctx, "external dxt library not available: texstore_rgb_dxt1");
171    }
172
173    free((void *) tempImage);
174
175    return GL_TRUE;
176 }
177
178
179 /**
180  * Store user's image in rgba_dxt1 format.
181  */
182 GLboolean
183 _mesa_texstore_rgba_dxt1(TEXSTORE_PARAMS)
184 {
185    const GLubyte *pixels;
186    GLubyte *dst;
187    const GLubyte *tempImage = NULL;
188
189    ASSERT(dstFormat == MESA_FORMAT_RGBA_DXT1 ||
190           dstFormat == MESA_FORMAT_SRGBA_DXT1);
191
192    if (srcFormat != GL_RGBA ||
193        srcType != GL_UNSIGNED_BYTE ||
194        ctx->_ImageTransferState ||
195        srcPacking->RowLength != srcWidth ||
196        srcPacking->SwapBytes) {
197       /* convert image to RGBA/GLubyte */
198       tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
199                                              baseInternalFormat,
200                                              _mesa_get_format_base_format(dstFormat),
201                                              srcWidth, srcHeight, srcDepth,
202                                              srcFormat, srcType, srcAddr,
203                                              srcPacking);
204       if (!tempImage)
205          return GL_FALSE; /* out of memory */
206       pixels = tempImage;
207       srcFormat = GL_RGBA;
208    }
209    else {
210       pixels = _mesa_image_address2d(srcPacking, srcAddr, srcWidth, srcHeight,
211                                      srcFormat, srcType, 0, 0);
212    }
213
214    dst = dstSlices[0];
215
216    if (ext_tx_compress_dxtn) {
217       (*ext_tx_compress_dxtn)(4, srcWidth, srcHeight, pixels,
218                               GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
219                               dst, dstRowStride);
220    }
221    else {
222       _mesa_warning(ctx, "external dxt library not available: texstore_rgba_dxt1");
223    }
224
225    free((void*) tempImage);
226
227    return GL_TRUE;
228 }
229
230
231 /**
232  * Store user's image in rgba_dxt3 format.
233  */
234 GLboolean
235 _mesa_texstore_rgba_dxt3(TEXSTORE_PARAMS)
236 {
237    const GLubyte *pixels;
238    GLubyte *dst;
239    const GLubyte *tempImage = NULL;
240
241    ASSERT(dstFormat == MESA_FORMAT_RGBA_DXT3 ||
242           dstFormat == MESA_FORMAT_SRGBA_DXT3);
243
244    if (srcFormat != GL_RGBA ||
245        srcType != GL_UNSIGNED_BYTE ||
246        ctx->_ImageTransferState ||
247        srcPacking->RowLength != srcWidth ||
248        srcPacking->SwapBytes) {
249       /* convert image to RGBA/GLubyte */
250       tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
251                                              baseInternalFormat,
252                                              _mesa_get_format_base_format(dstFormat),
253                                              srcWidth, srcHeight, srcDepth,
254                                              srcFormat, srcType, srcAddr,
255                                              srcPacking);
256       if (!tempImage)
257          return GL_FALSE; /* out of memory */
258       pixels = tempImage;
259    }
260    else {
261       pixels = _mesa_image_address2d(srcPacking, srcAddr, srcWidth, srcHeight,
262                                      srcFormat, srcType, 0, 0);
263    }
264
265    dst = dstSlices[0];
266
267    if (ext_tx_compress_dxtn) {
268       (*ext_tx_compress_dxtn)(4, srcWidth, srcHeight, pixels,
269                               GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,
270                               dst, dstRowStride);
271    }
272    else {
273       _mesa_warning(ctx, "external dxt library not available: texstore_rgba_dxt3");
274    }
275
276    free((void *) tempImage);
277
278    return GL_TRUE;
279 }
280
281
282 /**
283  * Store user's image in rgba_dxt5 format.
284  */
285 GLboolean
286 _mesa_texstore_rgba_dxt5(TEXSTORE_PARAMS)
287 {
288    const GLubyte *pixels;
289    GLubyte *dst;
290    const GLubyte *tempImage = NULL;
291
292    ASSERT(dstFormat == MESA_FORMAT_RGBA_DXT5 ||
293           dstFormat == MESA_FORMAT_SRGBA_DXT5);
294
295    if (srcFormat != GL_RGBA ||
296        srcType != GL_UNSIGNED_BYTE ||
297        ctx->_ImageTransferState ||
298        srcPacking->RowLength != srcWidth ||
299        srcPacking->SwapBytes) {
300       /* convert image to RGBA/GLubyte */
301       tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
302                                              baseInternalFormat,
303                                              _mesa_get_format_base_format(dstFormat),
304                                              srcWidth, srcHeight, srcDepth,
305                                              srcFormat, srcType, srcAddr,
306                                              srcPacking);
307       if (!tempImage)
308          return GL_FALSE; /* out of memory */
309       pixels = tempImage;
310    }
311    else {
312       pixels = _mesa_image_address2d(srcPacking, srcAddr, srcWidth, srcHeight,
313                                      srcFormat, srcType, 0, 0);
314    }
315
316    dst = dstSlices[0];
317
318    if (ext_tx_compress_dxtn) {
319       (*ext_tx_compress_dxtn)(4, srcWidth, srcHeight, pixels,
320                               GL_COMPRESSED_RGBA_S3TC_DXT5_EXT,
321                               dst, dstRowStride);
322    }
323    else {
324       _mesa_warning(ctx, "external dxt library not available: texstore_rgba_dxt5");
325    }
326
327    free((void *) tempImage);
328
329    return GL_TRUE;
330 }
331
332
333 /** Report problem with dxt texture decompression, once */
334 static void
335 problem(const char *func)
336 {
337    static GLboolean warned = GL_FALSE;
338    if (!warned) {
339       _mesa_debug(NULL, "attempted to decode DXT texture without "
340                   "library available: %s\n", func);
341       warned = GL_TRUE;
342    }
343 }
344
345
346 static void
347 fetch_rgb_dxt1(const GLubyte *map,
348                GLint rowStride, GLint i, GLint j, GLfloat *texel)
349 {
350    if (fetch_ext_rgb_dxt1) {
351       GLubyte tex[4];
352       fetch_ext_rgb_dxt1(rowStride, map, i, j, tex);
353       texel[RCOMP] = UBYTE_TO_FLOAT(tex[RCOMP]);
354       texel[GCOMP] = UBYTE_TO_FLOAT(tex[GCOMP]);
355       texel[BCOMP] = UBYTE_TO_FLOAT(tex[BCOMP]);
356       texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]);
357    }
358    else {
359       problem("rgb_dxt1");
360    }
361 }
362
363 static void
364 fetch_rgba_dxt1(const GLubyte *map,
365                 GLint rowStride, GLint i, GLint j, GLfloat *texel)
366 {
367    if (fetch_ext_rgba_dxt1) {
368       GLubyte tex[4];
369       fetch_ext_rgba_dxt1(rowStride, map, i, j, tex);
370       texel[RCOMP] = UBYTE_TO_FLOAT(tex[RCOMP]);
371       texel[GCOMP] = UBYTE_TO_FLOAT(tex[GCOMP]);
372       texel[BCOMP] = UBYTE_TO_FLOAT(tex[BCOMP]);
373       texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]);
374    }
375    else {
376       problem("rgba_dxt1");
377    }
378 }
379
380 static void
381 fetch_rgba_dxt3(const GLubyte *map,
382                 GLint rowStride, GLint i, GLint j, GLfloat *texel)
383 {
384    if (fetch_ext_rgba_dxt3) {
385       GLubyte tex[4];
386       fetch_ext_rgba_dxt3(rowStride, map, i, j, tex);
387       texel[RCOMP] = UBYTE_TO_FLOAT(tex[RCOMP]);
388       texel[GCOMP] = UBYTE_TO_FLOAT(tex[GCOMP]);
389       texel[BCOMP] = UBYTE_TO_FLOAT(tex[BCOMP]);
390       texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]);
391    }
392    else {
393       problem("rgba_dxt3");
394    }
395 }
396
397 static void
398 fetch_rgba_dxt5(const GLubyte *map,
399                 GLint rowStride, GLint i, GLint j, GLfloat *texel)
400 {
401    if (fetch_ext_rgba_dxt5) {
402       GLubyte tex[4];
403       fetch_ext_rgba_dxt5(rowStride, map, i, j, tex);
404       texel[RCOMP] = UBYTE_TO_FLOAT(tex[RCOMP]);
405       texel[GCOMP] = UBYTE_TO_FLOAT(tex[GCOMP]);
406       texel[BCOMP] = UBYTE_TO_FLOAT(tex[BCOMP]);
407       texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]);
408    }
409    else {
410       problem("rgba_dxt5");
411    }
412 }
413
414
415 static void
416 fetch_srgb_dxt1(const GLubyte *map,
417                 GLint rowStride, GLint i, GLint j, GLfloat *texel)
418 {
419    if (fetch_ext_rgb_dxt1) {
420       GLubyte tex[4];
421       fetch_ext_rgb_dxt1(rowStride, map, i, j, tex);
422       texel[RCOMP] = _mesa_nonlinear_to_linear(tex[RCOMP]);
423       texel[GCOMP] = _mesa_nonlinear_to_linear(tex[GCOMP]);
424       texel[BCOMP] = _mesa_nonlinear_to_linear(tex[BCOMP]);
425       texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]);
426    }
427    else {
428       problem("srgb_dxt1");
429    }
430 }
431
432 static void
433 fetch_srgba_dxt1(const GLubyte *map,
434                  GLint rowStride, GLint i, GLint j, GLfloat *texel)
435 {
436    if (fetch_ext_rgba_dxt1) {
437       GLubyte tex[4];
438       fetch_ext_rgba_dxt1(rowStride, map, i, j, tex);
439       texel[RCOMP] = _mesa_nonlinear_to_linear(tex[RCOMP]);
440       texel[GCOMP] = _mesa_nonlinear_to_linear(tex[GCOMP]);
441       texel[BCOMP] = _mesa_nonlinear_to_linear(tex[BCOMP]);
442       texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]);
443    }
444    else {
445       problem("srgba_dxt1");
446    }
447 }
448
449 static void
450 fetch_srgba_dxt3(const GLubyte *map,
451                  GLint rowStride, GLint i, GLint j, GLfloat *texel)
452 {
453    if (fetch_ext_rgba_dxt3) {
454       GLubyte tex[4];
455       fetch_ext_rgba_dxt3(rowStride, map, i, j, tex);
456       texel[RCOMP] = _mesa_nonlinear_to_linear(tex[RCOMP]);
457       texel[GCOMP] = _mesa_nonlinear_to_linear(tex[GCOMP]);
458       texel[BCOMP] = _mesa_nonlinear_to_linear(tex[BCOMP]);
459       texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]);
460    }
461    else {
462       problem("srgba_dxt3");
463    }
464 }
465
466 static void
467 fetch_srgba_dxt5(const GLubyte *map,
468                  GLint rowStride, GLint i, GLint j, GLfloat *texel)
469 {
470    if (fetch_ext_rgba_dxt5) {
471       GLubyte tex[4];
472       fetch_ext_rgba_dxt5(rowStride, map, i, j, tex);
473       texel[RCOMP] = _mesa_nonlinear_to_linear(tex[RCOMP]);
474       texel[GCOMP] = _mesa_nonlinear_to_linear(tex[GCOMP]);
475       texel[BCOMP] = _mesa_nonlinear_to_linear(tex[BCOMP]);
476       texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]);
477    }
478    else {
479       problem("srgba_dxt5");
480    }
481 }
482
483
484
485 compressed_fetch_func
486 _mesa_get_dxt_fetch_func(gl_format format)
487 {
488    switch (format) {
489    case MESA_FORMAT_RGB_DXT1:
490       return fetch_rgb_dxt1;
491    case MESA_FORMAT_RGBA_DXT1:
492       return fetch_rgba_dxt1;
493    case MESA_FORMAT_RGBA_DXT3:
494       return fetch_rgba_dxt3;
495    case MESA_FORMAT_RGBA_DXT5:
496       return fetch_rgba_dxt5;
497    case MESA_FORMAT_SRGB_DXT1:
498       return fetch_srgb_dxt1;
499    case MESA_FORMAT_SRGBA_DXT1:
500       return fetch_srgba_dxt1;
501    case MESA_FORMAT_SRGBA_DXT3:
502       return fetch_srgba_dxt3;
503    case MESA_FORMAT_SRGBA_DXT5:
504       return fetch_srgba_dxt5;
505    default:
506       return NULL;
507    }
508 }