Massively cleaned up the code that calculates front/back/depth buffer
[mesa.git] / src / mesa / main / texcompress_s3tc.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.1
4 *
5 * Copyright (C) 1999-2004 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_s3tc.c
28 * GL_EXT_texture_compression_s3tc support.
29 */
30
31 #ifndef USE_EXTERNAL_DXTN_LIB
32 #define USE_EXTERNAL_DXTN_LIB 0
33 #endif
34
35 #include "glheader.h"
36 #include "imports.h"
37 #include "colormac.h"
38 #include "context.h"
39 #include "convolve.h"
40 #include "image.h"
41 #include "texcompress.h"
42 #include "texformat.h"
43 #include "texstore.h"
44
45 #if USE_EXTERNAL_DXTN_LIB
46 #include <dlfcn.h>
47 #endif
48
49 typedef void (*dxtFetchTexelFuncExt)( GLint srcRowstride, GLubyte *pixdata, GLint col, GLint row, GLvoid *texelOut );
50 dxtFetchTexelFuncExt fetch_ext_rgb_dxt1;
51 dxtFetchTexelFuncExt fetch_ext_rgba_dxt1;
52 dxtFetchTexelFuncExt fetch_ext_rgba_dxt3;
53 dxtFetchTexelFuncExt fetch_ext_rgba_dxt5;
54
55 typedef void (*dxtCompressTexFuncExt)(GLint srccomps, GLint width, GLint height, const GLubyte *srcPixData, GLenum destformat, GLubyte *dest);
56 dxtCompressTexFuncExt ext_tx_compress_dxtn;
57
58 void *dxtlibhandle = NULL;
59
60 void
61 _mesa_init_texture_s3tc( GLcontext *ctx )
62 {
63 /* called during context initialization */
64 ctx->Mesa_DXTn = GL_FALSE;
65 #if USE_EXTERNAL_DXTN_LIB
66 if (!dxtlibhandle) {
67 char *error;
68
69 dxtlibhandle = dlopen ("libtxc_dxtn.so", RTLD_LAZY | RTLD_GLOBAL);
70 if (!dxtlibhandle) {
71 _mesa_warning(ctx, "couldn't open libtxc_dxtn.so, software DXTn"
72 "compression/decompression unavailable\n");
73 }
74 else {
75 /* the fetch functions are not per context! Might be problematic... */
76 fetch_ext_rgb_dxt1 = dlsym(dxtlibhandle, "fetch_2d_texel_rgb_dxt1");
77 error = dlerror();
78 if (error == NULL) {
79 fetch_ext_rgba_dxt1 = dlsym(dxtlibhandle, "fetch_2d_texel_rgba_dxt1");
80 error = dlerror();
81 }
82 if (error == NULL) {
83 fetch_ext_rgba_dxt3 = dlsym(dxtlibhandle, "fetch_2d_texel_rgba_dxt3");
84 error = dlerror();
85 }
86 if (error == NULL) {
87 fetch_ext_rgba_dxt5 = dlsym(dxtlibhandle, "fetch_2d_texel_rgba_dxt5");
88 error = dlerror();
89 }
90 if (error == NULL) {
91 ext_tx_compress_dxtn = dlsym(dxtlibhandle, "tx_compress_dxtn");
92 error = dlerror();
93 }
94
95 if (error) {
96 _mesa_warning(ctx, "couldn't reference all symbols in "
97 "libtxc_dxtn.so, software DXTn compression/decompression "
98 "unavailable\n");
99 fetch_ext_rgb_dxt1 = NULL;
100 fetch_ext_rgba_dxt1 = NULL;
101 fetch_ext_rgba_dxt3 = NULL;
102 fetch_ext_rgba_dxt5 = NULL;
103 ext_tx_compress_dxtn = NULL;
104 dlclose(dxtlibhandle);
105 dxtlibhandle = NULL;
106 }
107 }
108 }
109 if (dxtlibhandle) {
110 ctx->Mesa_DXTn = GL_TRUE;
111 _mesa_warning(ctx, "software DXTn compression/decompression available\n");
112 }
113 #else
114 (void) ctx;
115 #endif
116 }
117
118 /**
119 * Called via TexFormat->StoreImage to store an RGB_DXT1 texture.
120 */
121 static GLboolean
122 texstore_rgb_dxt1(STORE_PARAMS)
123 {
124 const GLchan *pixels;
125 GLint srcRowStride;
126 GLubyte *dst;
127 const GLint texWidth = dstRowStride * 4 / 8; /* a bit of a hack */
128 const GLchan *tempImage = NULL;
129
130 ASSERT(dstFormat == &_mesa_texformat_rgb_dxt1);
131 ASSERT(dstXoffset % 4 == 0);
132 ASSERT(dstYoffset % 4 == 0);
133 ASSERT(dstZoffset % 4 == 0);
134 (void) dstZoffset; (void) dstImageStride;
135
136 if (srcFormat != GL_RGB ||
137 srcType != CHAN_TYPE ||
138 ctx->_ImageTransferState ||
139 srcPacking->SwapBytes) {
140 /* convert image to RGB/GLchan */
141 tempImage = _mesa_make_temp_chan_image(ctx, dims,
142 baseInternalFormat,
143 dstFormat->BaseFormat,
144 srcWidth, srcHeight, srcDepth,
145 srcFormat, srcType, srcAddr,
146 srcPacking);
147 if (!tempImage)
148 return GL_FALSE; /* out of memory */
149 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
150 pixels = tempImage;
151 srcRowStride = 3 * srcWidth;
152 srcFormat = GL_RGB;
153 }
154 else {
155 pixels = (const GLchan *) srcAddr;
156 srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat,
157 srcType) / sizeof(GLchan);
158 }
159
160 dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0,
161 GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
162 texWidth, (GLubyte *) dstAddr);
163
164 if (ext_tx_compress_dxtn) {
165 (*ext_tx_compress_dxtn)(3, srcWidth, srcHeight, pixels, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, dst);
166 }
167 else {
168 _mesa_problem(ctx, "external dxt library not available");
169 }
170
171 if (tempImage)
172 _mesa_free((void *) tempImage);
173
174 return GL_TRUE;
175 }
176
177
178 /**
179 * Called via TexFormat->StoreImage to store an RGBA_DXT1 texture.
180 */
181 static GLboolean
182 texstore_rgba_dxt1(STORE_PARAMS)
183 {
184 const GLchan *pixels;
185 GLint srcRowStride;
186 GLubyte *dst;
187 const GLint texWidth = dstRowStride * 4 / 8; /* a bit of a hack */
188 const GLchan *tempImage = NULL;
189
190 ASSERT(dstFormat == &_mesa_texformat_rgba_dxt1);
191 ASSERT(dstXoffset % 4 == 0);
192 ASSERT(dstYoffset % 4 == 0);
193 ASSERT(dstZoffset % 4 == 0);
194 (void) dstZoffset; (void) dstImageStride;
195
196 if (srcFormat != GL_RGBA ||
197 srcType != CHAN_TYPE ||
198 ctx->_ImageTransferState ||
199 srcPacking->SwapBytes) {
200 /* convert image to RGBA/GLchan */
201 tempImage = _mesa_make_temp_chan_image(ctx, dims,
202 baseInternalFormat,
203 dstFormat->BaseFormat,
204 srcWidth, srcHeight, srcDepth,
205 srcFormat, srcType, srcAddr,
206 srcPacking);
207 if (!tempImage)
208 return GL_FALSE; /* out of memory */
209 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
210 pixels = tempImage;
211 srcRowStride = 4 * srcWidth;
212 srcFormat = GL_RGBA;
213 }
214 else {
215 pixels = (const GLchan *) srcAddr;
216 srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat,
217 srcType) / sizeof(GLchan);
218 }
219
220 dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0,
221 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
222 texWidth, (GLubyte *) dstAddr);
223 if (ext_tx_compress_dxtn) {
224 (*ext_tx_compress_dxtn)(4, srcWidth, srcHeight, pixels, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, dst);
225 }
226 else {
227 _mesa_problem(ctx, "external dxt library not available");
228 }
229
230 if (tempImage)
231 _mesa_free((void*) tempImage);
232
233 return GL_TRUE;
234 }
235
236
237 /**
238 * Called via TexFormat->StoreImage to store an RGBA_DXT3 texture.
239 */
240 static GLboolean
241 texstore_rgba_dxt3(STORE_PARAMS)
242 {
243 const GLchan *pixels;
244 GLint srcRowStride;
245 GLubyte *dst;
246 const GLint texWidth = dstRowStride * 4 / 16; /* a bit of a hack */
247 const GLchan *tempImage = NULL;
248
249 ASSERT(dstFormat == &_mesa_texformat_rgba_dxt3);
250 ASSERT(dstXoffset % 4 == 0);
251 ASSERT(dstYoffset % 4 == 0);
252 ASSERT(dstZoffset % 4 == 0);
253 (void) dstZoffset; (void) dstImageStride;
254
255 if (srcFormat != GL_RGBA ||
256 srcType != CHAN_TYPE ||
257 ctx->_ImageTransferState ||
258 srcPacking->SwapBytes) {
259 /* convert image to RGBA/GLchan */
260 tempImage = _mesa_make_temp_chan_image(ctx, dims,
261 baseInternalFormat,
262 dstFormat->BaseFormat,
263 srcWidth, srcHeight, srcDepth,
264 srcFormat, srcType, srcAddr,
265 srcPacking);
266 if (!tempImage)
267 return GL_FALSE; /* out of memory */
268 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
269 pixels = tempImage;
270 srcRowStride = 4 * srcWidth;
271 }
272 else {
273 pixels = (const GLchan *) srcAddr;
274 srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat,
275 srcType) / sizeof(GLchan);
276 }
277
278 dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0,
279 GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,
280 texWidth, (GLubyte *) dstAddr);
281 if (ext_tx_compress_dxtn) {
282 (*ext_tx_compress_dxtn)(4, srcWidth, srcHeight, pixels, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, dst);
283 }
284 else {
285 _mesa_problem(ctx, "external dxt library not available");
286 }
287
288 if (tempImage)
289 _mesa_free((void *) tempImage);
290
291 return GL_TRUE;
292 }
293
294
295 /**
296 * Called via TexFormat->StoreImage to store an RGBA_DXT5 texture.
297 */
298 static GLboolean
299 texstore_rgba_dxt5(STORE_PARAMS)
300 {
301 const GLchan *pixels;
302 GLint srcRowStride;
303 GLubyte *dst;
304 const GLint texWidth = dstRowStride * 4 / 16; /* a bit of a hack */
305 const GLchan *tempImage = NULL;
306
307 ASSERT(dstFormat == &_mesa_texformat_rgba_dxt5);
308 ASSERT(dstXoffset % 4 == 0);
309 ASSERT(dstYoffset % 4 == 0);
310 ASSERT(dstZoffset % 4 == 0);
311 (void) dstZoffset; (void) dstImageStride;
312
313 if (srcFormat != GL_RGBA ||
314 srcType != CHAN_TYPE ||
315 ctx->_ImageTransferState ||
316 srcPacking->SwapBytes) {
317 /* convert image to RGBA/GLchan */
318 tempImage = _mesa_make_temp_chan_image(ctx, dims,
319 baseInternalFormat,
320 dstFormat->BaseFormat,
321 srcWidth, srcHeight, srcDepth,
322 srcFormat, srcType, srcAddr,
323 srcPacking);
324 if (!tempImage)
325 return GL_FALSE; /* out of memory */
326 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
327 pixels = tempImage;
328 srcRowStride = 4 * srcWidth;
329 }
330 else {
331 pixels = (const GLchan *) srcAddr;
332 srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat,
333 srcType) / sizeof(GLchan);
334 }
335
336 dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0,
337 GL_COMPRESSED_RGBA_S3TC_DXT5_EXT,
338 texWidth, (GLubyte *) dstAddr);
339 if (ext_tx_compress_dxtn) {
340 (*ext_tx_compress_dxtn)(4, srcWidth, srcHeight, pixels, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, dst);
341 }
342 else {
343 _mesa_problem(ctx, "external dxt library not available");
344 }
345
346 if (tempImage)
347 _mesa_free((void *) tempImage);
348
349 return GL_TRUE;
350 }
351
352
353 static void
354 fetch_texel_2d_rgb_dxt1( const struct gl_texture_image *texImage,
355 GLint i, GLint j, GLint k, GLchan *texel )
356 {
357 (void) k;
358 if (fetch_ext_rgb_dxt1) {
359 ASSERT (sizeof(GLchan) == sizeof(GLubyte));
360 (*fetch_ext_rgb_dxt1)((texImage)->RowStride, (GLubyte *)(texImage)->Data, i, j, texel);
361 }
362 else _mesa_debug(NULL, "attempted to decode s3tc texture without library available\n");
363 }
364
365
366 static void
367 fetch_texel_2d_f_rgb_dxt1( const struct gl_texture_image *texImage,
368 GLint i, GLint j, GLint k, GLfloat *texel )
369 {
370 /* just sample as GLchan and convert to float here */
371 GLchan rgba[4];
372 fetch_texel_2d_rgb_dxt1(texImage, i, j, k, rgba);
373 texel[RCOMP] = CHAN_TO_FLOAT(rgba[RCOMP]);
374 texel[GCOMP] = CHAN_TO_FLOAT(rgba[GCOMP]);
375 texel[BCOMP] = CHAN_TO_FLOAT(rgba[BCOMP]);
376 texel[ACOMP] = CHAN_TO_FLOAT(rgba[ACOMP]);
377 }
378
379
380 static void
381 fetch_texel_2d_rgba_dxt1( const struct gl_texture_image *texImage,
382 GLint i, GLint j, GLint k, GLchan *texel )
383 {
384 (void) k;
385 if (fetch_ext_rgba_dxt1) {
386 (*fetch_ext_rgba_dxt1)((texImage)->RowStride, (GLubyte *)(texImage)->Data, i, j, texel);
387 }
388 else _mesa_debug(NULL, "attempted to decode s3tc texture without library available\n");
389 }
390
391
392 static void
393 fetch_texel_2d_f_rgba_dxt1( const struct gl_texture_image *texImage,
394 GLint i, GLint j, GLint k, GLfloat *texel )
395 {
396 /* just sample as GLchan and convert to float here */
397 GLchan rgba[4];
398 fetch_texel_2d_rgba_dxt1(texImage, i, j, k, rgba);
399 texel[RCOMP] = CHAN_TO_FLOAT(rgba[RCOMP]);
400 texel[GCOMP] = CHAN_TO_FLOAT(rgba[GCOMP]);
401 texel[BCOMP] = CHAN_TO_FLOAT(rgba[BCOMP]);
402 texel[ACOMP] = CHAN_TO_FLOAT(rgba[ACOMP]);
403 }
404
405
406 static void
407 fetch_texel_2d_rgba_dxt3( const struct gl_texture_image *texImage,
408 GLint i, GLint j, GLint k, GLchan *texel )
409 {
410 (void) k;
411 if (fetch_ext_rgba_dxt3) {
412 ASSERT (sizeof(GLchan) == sizeof(GLubyte));
413 (*fetch_ext_rgba_dxt3)((texImage)->RowStride, (GLubyte *)(texImage)->Data, i, j, texel);
414 }
415 else _mesa_debug(NULL, "attempted to decode s3tc texture without library available\n");
416 }
417
418
419 static void
420 fetch_texel_2d_f_rgba_dxt3( const struct gl_texture_image *texImage,
421 GLint i, GLint j, GLint k, GLfloat *texel )
422 {
423 /* just sample as GLchan and convert to float here */
424 GLchan rgba[4];
425 fetch_texel_2d_rgba_dxt3(texImage, i, j, k, rgba);
426 texel[RCOMP] = CHAN_TO_FLOAT(rgba[RCOMP]);
427 texel[GCOMP] = CHAN_TO_FLOAT(rgba[GCOMP]);
428 texel[BCOMP] = CHAN_TO_FLOAT(rgba[BCOMP]);
429 texel[ACOMP] = CHAN_TO_FLOAT(rgba[ACOMP]);
430 }
431
432
433 static void
434 fetch_texel_2d_rgba_dxt5( const struct gl_texture_image *texImage,
435 GLint i, GLint j, GLint k, GLchan *texel )
436 {
437 (void) k;
438 if (fetch_ext_rgba_dxt5) {
439 (*fetch_ext_rgba_dxt5)((texImage)->RowStride, (GLubyte *)(texImage)->Data, i, j, texel);
440 }
441 else _mesa_debug(NULL, "attempted to decode s3tc texture without library available\n");
442 }
443
444
445 static void
446 fetch_texel_2d_f_rgba_dxt5( const struct gl_texture_image *texImage,
447 GLint i, GLint j, GLint k, GLfloat *texel )
448 {
449 /* just sample as GLchan and convert to float here */
450 GLchan rgba[4];
451 fetch_texel_2d_rgba_dxt5(texImage, i, j, k, rgba);
452 texel[RCOMP] = CHAN_TO_FLOAT(rgba[RCOMP]);
453 texel[GCOMP] = CHAN_TO_FLOAT(rgba[GCOMP]);
454 texel[BCOMP] = CHAN_TO_FLOAT(rgba[BCOMP]);
455 texel[ACOMP] = CHAN_TO_FLOAT(rgba[ACOMP]);
456 }
457
458
459 const struct gl_texture_format _mesa_texformat_rgb_dxt1 = {
460 MESA_FORMAT_RGB_DXT1, /* MesaFormat */
461 GL_RGB, /* BaseFormat */
462 GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
463 4, /*approx*/ /* RedBits */
464 4, /*approx*/ /* GreenBits */
465 4, /*approx*/ /* BlueBits */
466 0, /* AlphaBits */
467 0, /* LuminanceBits */
468 0, /* IntensityBits */
469 0, /* IndexBits */
470 0, /* DepthBits */
471 0, /* TexelBytes */
472 texstore_rgb_dxt1, /* StoreTexImageFunc */
473 NULL, /*impossible*/ /* FetchTexel1D */
474 fetch_texel_2d_rgb_dxt1, /* FetchTexel2D */
475 NULL, /*impossible*/ /* FetchTexel3D */
476 NULL, /*impossible*/ /* FetchTexel1Df */
477 fetch_texel_2d_f_rgb_dxt1, /* FetchTexel2Df */
478 NULL, /*impossible*/ /* FetchTexel3Df */
479 };
480
481 const struct gl_texture_format _mesa_texformat_rgba_dxt1 = {
482 MESA_FORMAT_RGBA_DXT1, /* MesaFormat */
483 GL_RGBA, /* BaseFormat */
484 GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
485 4, /*approx*/ /* RedBits */
486 4, /*approx*/ /* GreenBits */
487 4, /*approx*/ /* BlueBits */
488 1, /*approx*/ /* AlphaBits */
489 0, /* LuminanceBits */
490 0, /* IntensityBits */
491 0, /* IndexBits */
492 0, /* DepthBits */
493 0, /* TexelBytes */
494 texstore_rgba_dxt1, /* StoreTexImageFunc */
495 NULL, /*impossible*/ /* FetchTexel1D */
496 fetch_texel_2d_rgba_dxt1, /* FetchTexel2D */
497 NULL, /*impossible*/ /* FetchTexel3D */
498 NULL, /*impossible*/ /* FetchTexel1Df */
499 fetch_texel_2d_f_rgba_dxt1, /* FetchTexel2Df */
500 NULL, /*impossible*/ /* FetchTexel3Df */
501 };
502
503 const struct gl_texture_format _mesa_texformat_rgba_dxt3 = {
504 MESA_FORMAT_RGBA_DXT3, /* MesaFormat */
505 GL_RGBA, /* BaseFormat */
506 GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
507 4, /*approx*/ /* RedBits */
508 4, /*approx*/ /* GreenBits */
509 4, /*approx*/ /* BlueBits */
510 4, /*approx*/ /* AlphaBits */
511 0, /* LuminanceBits */
512 0, /* IntensityBits */
513 0, /* IndexBits */
514 0, /* DepthBits */
515 0, /* TexelBytes */
516 texstore_rgba_dxt3, /* StoreTexImageFunc */
517 NULL, /*impossible*/ /* FetchTexel1D */
518 fetch_texel_2d_rgba_dxt3, /* FetchTexel2D */
519 NULL, /*impossible*/ /* FetchTexel3D */
520 NULL, /*impossible*/ /* FetchTexel1Df */
521 fetch_texel_2d_f_rgba_dxt3, /* FetchTexel2Df */
522 NULL, /*impossible*/ /* FetchTexel3Df */
523 };
524
525 const struct gl_texture_format _mesa_texformat_rgba_dxt5 = {
526 MESA_FORMAT_RGBA_DXT5, /* MesaFormat */
527 GL_RGBA, /* BaseFormat */
528 GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
529 4,/*approx*/ /* RedBits */
530 4,/*approx*/ /* GreenBits */
531 4,/*approx*/ /* BlueBits */
532 4,/*approx*/ /* AlphaBits */
533 0, /* LuminanceBits */
534 0, /* IntensityBits */
535 0, /* IndexBits */
536 0, /* DepthBits */
537 0, /* TexelBytes */
538 texstore_rgba_dxt5, /* StoreTexImageFunc */
539 NULL, /*impossible*/ /* FetchTexel1D */
540 fetch_texel_2d_rgba_dxt5, /* FetchTexel2D */
541 NULL, /*impossible*/ /* FetchTexel3D */
542 NULL, /*impossible*/ /* FetchTexel1Df */
543 fetch_texel_2d_f_rgba_dxt5, /* FetchTexel2Df */
544 NULL, /*impossible*/ /* FetchTexel3Df */
545 };