Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4358 Serge 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
}