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