• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
34 #include "image.h"
35 #include "macros.h"
36 #include "mtypes.h"
37 #include "texcompress.h"
38 #include "texcompress_s3tc.h"
39 #include "texcompress_s3tc_tmp.h"
40 #include "texstore.h"
41 #include "format_unpack.h"
42 #include "util/format_srgb.h"
43 
44 
45 /**
46  * Store user's image in rgb_dxt1 format.
47  */
48 GLboolean
_mesa_texstore_rgb_dxt1(TEXSTORE_PARAMS)49 _mesa_texstore_rgb_dxt1(TEXSTORE_PARAMS)
50 {
51    const GLubyte *pixels;
52    GLubyte *dst;
53    const GLubyte *tempImage = NULL;
54    int srccomps = srcFormat == GL_RGB ? 3 : 4;
55 
56    assert(dstFormat == MESA_FORMAT_RGB_DXT1 ||
57           dstFormat == MESA_FORMAT_SRGB_DXT1);
58 
59    if (!(srcFormat == GL_RGB || srcFormat == GL_RGBA) ||
60        srcType != GL_UNSIGNED_BYTE ||
61        ctx->_ImageTransferState ||
62        _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType) != srccomps * srcWidth * sizeof(GLubyte) ||
63        srcPacking->SkipImages ||
64        srcPacking->SwapBytes) {
65       /* convert image to RGB/GLubyte */
66       GLubyte *tempImageSlices[1];
67       int rgbRowStride = 3 * srcWidth * sizeof(GLubyte);
68       tempImage = malloc(srcWidth * srcHeight * 3 * sizeof(GLubyte));
69       if (!tempImage)
70          return GL_FALSE; /* out of memory */
71       tempImageSlices[0] = (GLubyte *) tempImage;
72       _mesa_texstore(ctx, dims,
73                      baseInternalFormat,
74                      MESA_FORMAT_RGB_UNORM8,
75                      rgbRowStride, tempImageSlices,
76                      srcWidth, srcHeight, srcDepth,
77                      srcFormat, srcType, srcAddr,
78                      srcPacking);
79       pixels = tempImage;
80       srcFormat = GL_RGB;
81       srccomps = 3;
82    }
83    else {
84       pixels = _mesa_image_address2d(srcPacking, srcAddr, srcWidth, srcHeight,
85                                      srcFormat, srcType, 0, 0);
86    }
87 
88    dst = dstSlices[0];
89 
90    tx_compress_dxt1(srccomps, srcWidth, srcHeight, pixels,
91                     dst, dstRowStride, 3);
92 
93    free((void *) tempImage);
94 
95    return GL_TRUE;
96 }
97 
98 
99 /**
100  * Store user's image in rgba_dxt1 format.
101  */
102 GLboolean
_mesa_texstore_rgba_dxt1(TEXSTORE_PARAMS)103 _mesa_texstore_rgba_dxt1(TEXSTORE_PARAMS)
104 {
105    const GLubyte *pixels;
106    GLubyte *dst;
107    const GLubyte *tempImage = NULL;
108    int rgbaRowStride = 4 * srcWidth * sizeof(GLubyte);
109 
110    assert(dstFormat == MESA_FORMAT_RGBA_DXT1 ||
111           dstFormat == MESA_FORMAT_SRGBA_DXT1);
112 
113    if (srcFormat != GL_RGBA ||
114        srcType != GL_UNSIGNED_BYTE ||
115        ctx->_ImageTransferState ||
116        _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType) != rgbaRowStride ||
117        srcPacking->SkipImages ||
118        srcPacking->SwapBytes) {
119       /* convert image to RGBA/GLubyte */
120       GLubyte *tempImageSlices[1];
121       tempImage = malloc(srcWidth * srcHeight * 4 * sizeof(GLubyte));
122       if (!tempImage)
123          return GL_FALSE; /* out of memory */
124       tempImageSlices[0] = (GLubyte *) tempImage;
125       _mesa_texstore(ctx, dims,
126                      baseInternalFormat,
127 #if UTIL_ARCH_LITTLE_ENDIAN
128                      MESA_FORMAT_R8G8B8A8_UNORM,
129 #else
130                      MESA_FORMAT_A8B8G8R8_UNORM,
131 #endif
132                      rgbaRowStride, tempImageSlices,
133                      srcWidth, srcHeight, srcDepth,
134                      srcFormat, srcType, srcAddr,
135                      srcPacking);
136       pixels = tempImage;
137       srcFormat = GL_RGBA;
138    }
139    else {
140       pixels = _mesa_image_address2d(srcPacking, srcAddr, srcWidth, srcHeight,
141                                      srcFormat, srcType, 0, 0);
142    }
143 
144    dst = dstSlices[0];
145 
146    tx_compress_dxt1(4, srcWidth, srcHeight, pixels, dst, dstRowStride, 4);
147 
148    free((void*) tempImage);
149 
150    return GL_TRUE;
151 }
152 
153 
154 /**
155  * Store user's image in rgba_dxt3 format.
156  */
157 GLboolean
_mesa_texstore_rgba_dxt3(TEXSTORE_PARAMS)158 _mesa_texstore_rgba_dxt3(TEXSTORE_PARAMS)
159 {
160    const GLubyte *pixels;
161    GLubyte *dst;
162    const GLubyte *tempImage = NULL;
163    int rgbaRowStride = 4 * srcWidth * sizeof(GLubyte);
164 
165    assert(dstFormat == MESA_FORMAT_RGBA_DXT3 ||
166           dstFormat == MESA_FORMAT_SRGBA_DXT3);
167 
168    if (srcFormat != GL_RGBA ||
169        srcType != GL_UNSIGNED_BYTE ||
170        ctx->_ImageTransferState ||
171        _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType) != rgbaRowStride ||
172        srcPacking->SkipImages ||
173        srcPacking->SwapBytes) {
174       /* convert image to RGBA/GLubyte */
175       GLubyte *tempImageSlices[1];
176       tempImage = malloc(srcWidth * srcHeight * 4 * sizeof(GLubyte));
177       if (!tempImage)
178          return GL_FALSE; /* out of memory */
179       tempImageSlices[0] = (GLubyte *) tempImage;
180       _mesa_texstore(ctx, dims,
181                      baseInternalFormat,
182 #if UTIL_ARCH_LITTLE_ENDIAN
183                      MESA_FORMAT_R8G8B8A8_UNORM,
184 #else
185                      MESA_FORMAT_A8B8G8R8_UNORM,
186 #endif
187                      rgbaRowStride, tempImageSlices,
188                      srcWidth, srcHeight, srcDepth,
189                      srcFormat, srcType, srcAddr,
190                      srcPacking);
191       pixels = tempImage;
192    }
193    else {
194       pixels = _mesa_image_address2d(srcPacking, srcAddr, srcWidth, srcHeight,
195                                      srcFormat, srcType, 0, 0);
196    }
197 
198    dst = dstSlices[0];
199 
200    tx_compress_dxt3(4, srcWidth, srcHeight, pixels, dst, dstRowStride);
201 
202    free((void *) tempImage);
203 
204    return GL_TRUE;
205 }
206 
207 
208 /**
209  * Store user's image in rgba_dxt5 format.
210  */
211 GLboolean
_mesa_texstore_rgba_dxt5(TEXSTORE_PARAMS)212 _mesa_texstore_rgba_dxt5(TEXSTORE_PARAMS)
213 {
214    const GLubyte *pixels;
215    GLubyte *dst;
216    const GLubyte *tempImage = NULL;
217    int rgbaRowStride = 4 * srcWidth * sizeof(GLubyte);
218 
219    assert(dstFormat == MESA_FORMAT_RGBA_DXT5 ||
220           dstFormat == MESA_FORMAT_SRGBA_DXT5);
221 
222    if (srcFormat != GL_RGBA ||
223        srcType != GL_UNSIGNED_BYTE ||
224        ctx->_ImageTransferState ||
225        _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType) != rgbaRowStride ||
226        srcPacking->SkipImages ||
227        srcPacking->SwapBytes) {
228       /* convert image to RGBA/GLubyte */
229       GLubyte *tempImageSlices[1];
230       tempImage = malloc(srcWidth * srcHeight * 4 * sizeof(GLubyte));
231       if (!tempImage)
232          return GL_FALSE; /* out of memory */
233       tempImageSlices[0] = (GLubyte *) tempImage;
234       _mesa_texstore(ctx, dims,
235                      baseInternalFormat,
236 #if UTIL_ARCH_LITTLE_ENDIAN
237                      MESA_FORMAT_R8G8B8A8_UNORM,
238 #else
239                      MESA_FORMAT_A8B8G8R8_UNORM,
240 #endif
241                      rgbaRowStride, tempImageSlices,
242                      srcWidth, srcHeight, srcDepth,
243                      srcFormat, srcType, srcAddr,
244                      srcPacking);
245       pixels = tempImage;
246    }
247    else {
248       pixels = _mesa_image_address2d(srcPacking, srcAddr, srcWidth, srcHeight,
249                                      srcFormat, srcType, 0, 0);
250    }
251 
252    dst = dstSlices[0];
253 
254    tx_compress_dxt5(4, srcWidth, srcHeight, pixels, dst, dstRowStride);
255 
256    free((void *) tempImage);
257 
258    return GL_TRUE;
259 }
260 
261 
262 static void
fetch_rgb_dxt1(const GLubyte * map,GLint rowStride,GLint i,GLint j,GLfloat * texel)263 fetch_rgb_dxt1(const GLubyte *map,
264                GLint rowStride, GLint i, GLint j, GLfloat *texel)
265 {
266    GLubyte tex[4];
267    fetch_2d_texel_rgb_dxt1(rowStride, map, i, j, tex);
268    texel[RCOMP] = UBYTE_TO_FLOAT(tex[RCOMP]);
269    texel[GCOMP] = UBYTE_TO_FLOAT(tex[GCOMP]);
270    texel[BCOMP] = UBYTE_TO_FLOAT(tex[BCOMP]);
271    texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]);
272 }
273 
274 static void
fetch_rgba_dxt1(const GLubyte * map,GLint rowStride,GLint i,GLint j,GLfloat * texel)275 fetch_rgba_dxt1(const GLubyte *map,
276                 GLint rowStride, GLint i, GLint j, GLfloat *texel)
277 {
278    GLubyte tex[4];
279    fetch_2d_texel_rgba_dxt1(rowStride, map, i, j, tex);
280    texel[RCOMP] = UBYTE_TO_FLOAT(tex[RCOMP]);
281    texel[GCOMP] = UBYTE_TO_FLOAT(tex[GCOMP]);
282    texel[BCOMP] = UBYTE_TO_FLOAT(tex[BCOMP]);
283    texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]);
284 }
285 
286 static void
fetch_rgba_dxt3(const GLubyte * map,GLint rowStride,GLint i,GLint j,GLfloat * texel)287 fetch_rgba_dxt3(const GLubyte *map,
288                 GLint rowStride, GLint i, GLint j, GLfloat *texel)
289 {
290    GLubyte tex[4];
291    fetch_2d_texel_rgba_dxt3(rowStride, map, i, j, tex);
292    texel[RCOMP] = UBYTE_TO_FLOAT(tex[RCOMP]);
293    texel[GCOMP] = UBYTE_TO_FLOAT(tex[GCOMP]);
294    texel[BCOMP] = UBYTE_TO_FLOAT(tex[BCOMP]);
295    texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]);
296 }
297 
298 static void
fetch_rgba_dxt5(const GLubyte * map,GLint rowStride,GLint i,GLint j,GLfloat * texel)299 fetch_rgba_dxt5(const GLubyte *map,
300                 GLint rowStride, GLint i, GLint j, GLfloat *texel)
301 {
302    GLubyte tex[4];
303    fetch_2d_texel_rgba_dxt5(rowStride, map, i, j, tex);
304    texel[RCOMP] = UBYTE_TO_FLOAT(tex[RCOMP]);
305    texel[GCOMP] = UBYTE_TO_FLOAT(tex[GCOMP]);
306    texel[BCOMP] = UBYTE_TO_FLOAT(tex[BCOMP]);
307    texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]);
308 }
309 
310 
311 static void
fetch_srgb_dxt1(const GLubyte * map,GLint rowStride,GLint i,GLint j,GLfloat * texel)312 fetch_srgb_dxt1(const GLubyte *map,
313                 GLint rowStride, GLint i, GLint j, GLfloat *texel)
314 {
315    GLubyte tex[4];
316    fetch_2d_texel_rgb_dxt1(rowStride, map, i, j, tex);
317    texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(tex[RCOMP]);
318    texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(tex[GCOMP]);
319    texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(tex[BCOMP]);
320    texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]);
321 }
322 
323 static void
fetch_srgba_dxt1(const GLubyte * map,GLint rowStride,GLint i,GLint j,GLfloat * texel)324 fetch_srgba_dxt1(const GLubyte *map,
325                  GLint rowStride, GLint i, GLint j, GLfloat *texel)
326 {
327    GLubyte tex[4];
328    fetch_2d_texel_rgba_dxt1(rowStride, map, i, j, tex);
329    texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(tex[RCOMP]);
330    texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(tex[GCOMP]);
331    texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(tex[BCOMP]);
332    texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]);
333 }
334 
335 static void
fetch_srgba_dxt3(const GLubyte * map,GLint rowStride,GLint i,GLint j,GLfloat * texel)336 fetch_srgba_dxt3(const GLubyte *map,
337                  GLint rowStride, GLint i, GLint j, GLfloat *texel)
338 {
339    GLubyte tex[4];
340    fetch_2d_texel_rgba_dxt3(rowStride, map, i, j, tex);
341    texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(tex[RCOMP]);
342    texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(tex[GCOMP]);
343    texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(tex[BCOMP]);
344    texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]);
345 }
346 
347 static void
fetch_srgba_dxt5(const GLubyte * map,GLint rowStride,GLint i,GLint j,GLfloat * texel)348 fetch_srgba_dxt5(const GLubyte *map,
349                  GLint rowStride, GLint i, GLint j, GLfloat *texel)
350 {
351    GLubyte tex[4];
352    fetch_2d_texel_rgba_dxt5(rowStride, map, i, j, tex);
353    texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(tex[RCOMP]);
354    texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(tex[GCOMP]);
355    texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(tex[BCOMP]);
356    texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]);
357 }
358 
359 
360 
361 compressed_fetch_func
_mesa_get_dxt_fetch_func(mesa_format format)362 _mesa_get_dxt_fetch_func(mesa_format format)
363 {
364    switch (format) {
365    case MESA_FORMAT_RGB_DXT1:
366       return fetch_rgb_dxt1;
367    case MESA_FORMAT_RGBA_DXT1:
368       return fetch_rgba_dxt1;
369    case MESA_FORMAT_RGBA_DXT3:
370       return fetch_rgba_dxt3;
371    case MESA_FORMAT_RGBA_DXT5:
372       return fetch_rgba_dxt5;
373    case MESA_FORMAT_SRGB_DXT1:
374       return fetch_srgb_dxt1;
375    case MESA_FORMAT_SRGBA_DXT1:
376       return fetch_srgba_dxt1;
377    case MESA_FORMAT_SRGBA_DXT3:
378       return fetch_srgba_dxt3;
379    case MESA_FORMAT_SRGBA_DXT5:
380       return fetch_srgba_dxt5;
381    default:
382       return NULL;
383    }
384 }
385