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