2 * Mesa 3-D graphics library
4 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
5 * Copyright (c) 2008 VMware, Inc.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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.
28 * \file texcompress_s3tc.c
29 * GL_EXT_texture_compression_s3tc support.
33 #include "util/imports.h"
37 #include "texcompress.h"
38 #include "texcompress_s3tc.h"
39 #include "texcompress_s3tc_tmp.h"
41 #include "format_unpack.h"
42 #include "util/format_srgb.h"
46 * Store user's image in rgb_dxt1 format.
49 _mesa_texstore_rgb_dxt1(TEXSTORE_PARAMS
)
51 const GLubyte
*pixels
;
53 const GLubyte
*tempImage
= NULL
;
55 assert(dstFormat
== MESA_FORMAT_RGB_DXT1
||
56 dstFormat
== MESA_FORMAT_SRGB_DXT1
);
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
));
68 return GL_FALSE
; /* out of memory */
69 tempImageSlices
[0] = (GLubyte
*) tempImage
;
70 _mesa_texstore(ctx
, dims
,
72 MESA_FORMAT_RGB_UNORM8
,
73 rgbRowStride
, tempImageSlices
,
74 srcWidth
, srcHeight
, srcDepth
,
75 srcFormat
, srcType
, srcAddr
,
81 pixels
= _mesa_image_address2d(srcPacking
, srcAddr
, srcWidth
, srcHeight
,
82 srcFormat
, srcType
, 0, 0);
87 tx_compress_dxtn(3, srcWidth
, srcHeight
, pixels
,
88 GL_COMPRESSED_RGB_S3TC_DXT1_EXT
,
91 free((void *) tempImage
);
98 * Store user's image in rgba_dxt1 format.
101 _mesa_texstore_rgba_dxt1(TEXSTORE_PARAMS
)
103 const GLubyte
*pixels
;
105 const GLubyte
*tempImage
= NULL
;
107 assert(dstFormat
== MESA_FORMAT_RGBA_DXT1
||
108 dstFormat
== MESA_FORMAT_SRGBA_DXT1
);
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
));
120 return GL_FALSE
; /* out of memory */
121 tempImageSlices
[0] = (GLubyte
*) tempImage
;
122 _mesa_texstore(ctx
, dims
,
124 #if UTIL_ARCH_LITTLE_ENDIAN
125 MESA_FORMAT_R8G8B8A8_UNORM
,
127 MESA_FORMAT_A8B8G8R8_UNORM
,
129 rgbaRowStride
, tempImageSlices
,
130 srcWidth
, srcHeight
, srcDepth
,
131 srcFormat
, srcType
, srcAddr
,
137 pixels
= _mesa_image_address2d(srcPacking
, srcAddr
, srcWidth
, srcHeight
,
138 srcFormat
, srcType
, 0, 0);
143 tx_compress_dxtn(4, srcWidth
, srcHeight
, pixels
,
144 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
,
147 free((void*) tempImage
);
154 * Store user's image in rgba_dxt3 format.
157 _mesa_texstore_rgba_dxt3(TEXSTORE_PARAMS
)
159 const GLubyte
*pixels
;
161 const GLubyte
*tempImage
= NULL
;
163 assert(dstFormat
== MESA_FORMAT_RGBA_DXT3
||
164 dstFormat
== MESA_FORMAT_SRGBA_DXT3
);
166 if (srcFormat
!= GL_RGBA
||
167 srcType
!= GL_UNSIGNED_BYTE
||
168 ctx
->_ImageTransferState
||
169 ALIGN(srcPacking
->RowLength
, srcPacking
->Alignment
) != srcWidth
||
170 srcPacking
->SwapBytes
) {
171 /* convert image to RGBA/GLubyte */
172 GLubyte
*tempImageSlices
[1];
173 int rgbaRowStride
= 4 * srcWidth
* sizeof(GLubyte
);
174 tempImage
= malloc(srcWidth
* srcHeight
* 4 * sizeof(GLubyte
));
176 return GL_FALSE
; /* out of memory */
177 tempImageSlices
[0] = (GLubyte
*) tempImage
;
178 _mesa_texstore(ctx
, dims
,
180 #if UTIL_ARCH_LITTLE_ENDIAN
181 MESA_FORMAT_R8G8B8A8_UNORM
,
183 MESA_FORMAT_A8B8G8R8_UNORM
,
185 rgbaRowStride
, tempImageSlices
,
186 srcWidth
, srcHeight
, srcDepth
,
187 srcFormat
, srcType
, srcAddr
,
192 pixels
= _mesa_image_address2d(srcPacking
, srcAddr
, srcWidth
, srcHeight
,
193 srcFormat
, srcType
, 0, 0);
198 tx_compress_dxtn(4, srcWidth
, srcHeight
, pixels
,
199 GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
,
202 free((void *) tempImage
);
209 * Store user's image in rgba_dxt5 format.
212 _mesa_texstore_rgba_dxt5(TEXSTORE_PARAMS
)
214 const GLubyte
*pixels
;
216 const GLubyte
*tempImage
= NULL
;
218 assert(dstFormat
== MESA_FORMAT_RGBA_DXT5
||
219 dstFormat
== MESA_FORMAT_SRGBA_DXT5
);
221 if (srcFormat
!= GL_RGBA
||
222 srcType
!= GL_UNSIGNED_BYTE
||
223 ctx
->_ImageTransferState
||
224 ALIGN(srcPacking
->RowLength
, srcPacking
->Alignment
) != srcWidth
||
225 srcPacking
->SwapBytes
) {
226 /* convert image to RGBA/GLubyte */
227 GLubyte
*tempImageSlices
[1];
228 int rgbaRowStride
= 4 * srcWidth
* sizeof(GLubyte
);
229 tempImage
= malloc(srcWidth
* srcHeight
* 4 * sizeof(GLubyte
));
231 return GL_FALSE
; /* out of memory */
232 tempImageSlices
[0] = (GLubyte
*) tempImage
;
233 _mesa_texstore(ctx
, dims
,
235 #if UTIL_ARCH_LITTLE_ENDIAN
236 MESA_FORMAT_R8G8B8A8_UNORM
,
238 MESA_FORMAT_A8B8G8R8_UNORM
,
240 rgbaRowStride
, tempImageSlices
,
241 srcWidth
, srcHeight
, srcDepth
,
242 srcFormat
, srcType
, srcAddr
,
247 pixels
= _mesa_image_address2d(srcPacking
, srcAddr
, srcWidth
, srcHeight
,
248 srcFormat
, srcType
, 0, 0);
253 tx_compress_dxtn(4, srcWidth
, srcHeight
, pixels
,
254 GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
,
257 free((void *) tempImage
);
264 fetch_rgb_dxt1(const GLubyte
*map
,
265 GLint rowStride
, GLint i
, GLint j
, GLfloat
*texel
)
268 fetch_2d_texel_rgb_dxt1(rowStride
, map
, i
, j
, tex
);
269 texel
[RCOMP
] = UBYTE_TO_FLOAT(tex
[RCOMP
]);
270 texel
[GCOMP
] = UBYTE_TO_FLOAT(tex
[GCOMP
]);
271 texel
[BCOMP
] = UBYTE_TO_FLOAT(tex
[BCOMP
]);
272 texel
[ACOMP
] = UBYTE_TO_FLOAT(tex
[ACOMP
]);
276 fetch_rgba_dxt1(const GLubyte
*map
,
277 GLint rowStride
, GLint i
, GLint j
, GLfloat
*texel
)
280 fetch_2d_texel_rgba_dxt1(rowStride
, map
, i
, j
, tex
);
281 texel
[RCOMP
] = UBYTE_TO_FLOAT(tex
[RCOMP
]);
282 texel
[GCOMP
] = UBYTE_TO_FLOAT(tex
[GCOMP
]);
283 texel
[BCOMP
] = UBYTE_TO_FLOAT(tex
[BCOMP
]);
284 texel
[ACOMP
] = UBYTE_TO_FLOAT(tex
[ACOMP
]);
288 fetch_rgba_dxt3(const GLubyte
*map
,
289 GLint rowStride
, GLint i
, GLint j
, GLfloat
*texel
)
292 fetch_2d_texel_rgba_dxt3(rowStride
, map
, i
, j
, tex
);
293 texel
[RCOMP
] = UBYTE_TO_FLOAT(tex
[RCOMP
]);
294 texel
[GCOMP
] = UBYTE_TO_FLOAT(tex
[GCOMP
]);
295 texel
[BCOMP
] = UBYTE_TO_FLOAT(tex
[BCOMP
]);
296 texel
[ACOMP
] = UBYTE_TO_FLOAT(tex
[ACOMP
]);
300 fetch_rgba_dxt5(const GLubyte
*map
,
301 GLint rowStride
, GLint i
, GLint j
, GLfloat
*texel
)
304 fetch_2d_texel_rgba_dxt5(rowStride
, map
, i
, j
, tex
);
305 texel
[RCOMP
] = UBYTE_TO_FLOAT(tex
[RCOMP
]);
306 texel
[GCOMP
] = UBYTE_TO_FLOAT(tex
[GCOMP
]);
307 texel
[BCOMP
] = UBYTE_TO_FLOAT(tex
[BCOMP
]);
308 texel
[ACOMP
] = UBYTE_TO_FLOAT(tex
[ACOMP
]);
313 fetch_srgb_dxt1(const GLubyte
*map
,
314 GLint rowStride
, GLint i
, GLint j
, GLfloat
*texel
)
317 fetch_2d_texel_rgb_dxt1(rowStride
, map
, i
, j
, tex
);
318 texel
[RCOMP
] = util_format_srgb_8unorm_to_linear_float(tex
[RCOMP
]);
319 texel
[GCOMP
] = util_format_srgb_8unorm_to_linear_float(tex
[GCOMP
]);
320 texel
[BCOMP
] = util_format_srgb_8unorm_to_linear_float(tex
[BCOMP
]);
321 texel
[ACOMP
] = UBYTE_TO_FLOAT(tex
[ACOMP
]);
325 fetch_srgba_dxt1(const GLubyte
*map
,
326 GLint rowStride
, GLint i
, GLint j
, GLfloat
*texel
)
329 fetch_2d_texel_rgba_dxt1(rowStride
, map
, i
, j
, tex
);
330 texel
[RCOMP
] = util_format_srgb_8unorm_to_linear_float(tex
[RCOMP
]);
331 texel
[GCOMP
] = util_format_srgb_8unorm_to_linear_float(tex
[GCOMP
]);
332 texel
[BCOMP
] = util_format_srgb_8unorm_to_linear_float(tex
[BCOMP
]);
333 texel
[ACOMP
] = UBYTE_TO_FLOAT(tex
[ACOMP
]);
337 fetch_srgba_dxt3(const GLubyte
*map
,
338 GLint rowStride
, GLint i
, GLint j
, GLfloat
*texel
)
341 fetch_2d_texel_rgba_dxt3(rowStride
, map
, i
, j
, tex
);
342 texel
[RCOMP
] = util_format_srgb_8unorm_to_linear_float(tex
[RCOMP
]);
343 texel
[GCOMP
] = util_format_srgb_8unorm_to_linear_float(tex
[GCOMP
]);
344 texel
[BCOMP
] = util_format_srgb_8unorm_to_linear_float(tex
[BCOMP
]);
345 texel
[ACOMP
] = UBYTE_TO_FLOAT(tex
[ACOMP
]);
349 fetch_srgba_dxt5(const GLubyte
*map
,
350 GLint rowStride
, GLint i
, GLint j
, GLfloat
*texel
)
353 fetch_2d_texel_rgba_dxt5(rowStride
, map
, i
, j
, tex
);
354 texel
[RCOMP
] = util_format_srgb_8unorm_to_linear_float(tex
[RCOMP
]);
355 texel
[GCOMP
] = util_format_srgb_8unorm_to_linear_float(tex
[GCOMP
]);
356 texel
[BCOMP
] = util_format_srgb_8unorm_to_linear_float(tex
[BCOMP
]);
357 texel
[ACOMP
] = UBYTE_TO_FLOAT(tex
[ACOMP
]);
362 compressed_fetch_func
363 _mesa_get_dxt_fetch_func(mesa_format format
)
366 case MESA_FORMAT_RGB_DXT1
:
367 return fetch_rgb_dxt1
;
368 case MESA_FORMAT_RGBA_DXT1
:
369 return fetch_rgba_dxt1
;
370 case MESA_FORMAT_RGBA_DXT3
:
371 return fetch_rgba_dxt3
;
372 case MESA_FORMAT_RGBA_DXT5
:
373 return fetch_rgba_dxt5
;
374 case MESA_FORMAT_SRGB_DXT1
:
375 return fetch_srgb_dxt1
;
376 case MESA_FORMAT_SRGBA_DXT1
:
377 return fetch_srgba_dxt1
;
378 case MESA_FORMAT_SRGBA_DXT3
:
379 return fetch_srgba_dxt3
;
380 case MESA_FORMAT_SRGBA_DXT5
:
381 return fetch_srgba_dxt5
;