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.
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 _mesa_little_endian() ? MESA_FORMAT_R8G8B8A8_UNORM
125 : MESA_FORMAT_A8B8G8R8_UNORM
,
126 rgbaRowStride
, tempImageSlices
,
127 srcWidth
, srcHeight
, srcDepth
,
128 srcFormat
, srcType
, srcAddr
,
134 pixels
= _mesa_image_address2d(srcPacking
, srcAddr
, srcWidth
, srcHeight
,
135 srcFormat
, srcType
, 0, 0);
140 tx_compress_dxtn(4, srcWidth
, srcHeight
, pixels
,
141 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
,
144 free((void*) tempImage
);
151 * Store user's image in rgba_dxt3 format.
154 _mesa_texstore_rgba_dxt3(TEXSTORE_PARAMS
)
156 const GLubyte
*pixels
;
158 const GLubyte
*tempImage
= NULL
;
160 assert(dstFormat
== MESA_FORMAT_RGBA_DXT3
||
161 dstFormat
== MESA_FORMAT_SRGBA_DXT3
);
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
));
173 return GL_FALSE
; /* out of memory */
174 tempImageSlices
[0] = (GLubyte
*) tempImage
;
175 _mesa_texstore(ctx
, dims
,
177 _mesa_little_endian() ? MESA_FORMAT_R8G8B8A8_UNORM
178 : MESA_FORMAT_A8B8G8R8_UNORM
,
179 rgbaRowStride
, tempImageSlices
,
180 srcWidth
, srcHeight
, srcDepth
,
181 srcFormat
, srcType
, srcAddr
,
186 pixels
= _mesa_image_address2d(srcPacking
, srcAddr
, srcWidth
, srcHeight
,
187 srcFormat
, srcType
, 0, 0);
192 tx_compress_dxtn(4, srcWidth
, srcHeight
, pixels
,
193 GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
,
196 free((void *) tempImage
);
203 * Store user's image in rgba_dxt5 format.
206 _mesa_texstore_rgba_dxt5(TEXSTORE_PARAMS
)
208 const GLubyte
*pixels
;
210 const GLubyte
*tempImage
= NULL
;
212 assert(dstFormat
== MESA_FORMAT_RGBA_DXT5
||
213 dstFormat
== MESA_FORMAT_SRGBA_DXT5
);
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
));
225 return GL_FALSE
; /* out of memory */
226 tempImageSlices
[0] = (GLubyte
*) tempImage
;
227 _mesa_texstore(ctx
, dims
,
229 _mesa_little_endian() ? MESA_FORMAT_R8G8B8A8_UNORM
230 : MESA_FORMAT_A8B8G8R8_UNORM
,
231 rgbaRowStride
, tempImageSlices
,
232 srcWidth
, srcHeight
, srcDepth
,
233 srcFormat
, srcType
, srcAddr
,
238 pixels
= _mesa_image_address2d(srcPacking
, srcAddr
, srcWidth
, srcHeight
,
239 srcFormat
, srcType
, 0, 0);
244 tx_compress_dxtn(4, srcWidth
, srcHeight
, pixels
,
245 GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
,
248 free((void *) tempImage
);
255 fetch_rgb_dxt1(const GLubyte
*map
,
256 GLint rowStride
, GLint i
, GLint j
, GLfloat
*texel
)
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
]);
267 fetch_rgba_dxt1(const GLubyte
*map
,
268 GLint rowStride
, GLint i
, GLint j
, GLfloat
*texel
)
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
]);
279 fetch_rgba_dxt3(const GLubyte
*map
,
280 GLint rowStride
, GLint i
, GLint j
, GLfloat
*texel
)
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
]);
291 fetch_rgba_dxt5(const GLubyte
*map
,
292 GLint rowStride
, GLint i
, GLint j
, GLfloat
*texel
)
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
]);
304 fetch_srgb_dxt1(const GLubyte
*map
,
305 GLint rowStride
, GLint i
, GLint j
, GLfloat
*texel
)
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
]);
316 fetch_srgba_dxt1(const GLubyte
*map
,
317 GLint rowStride
, GLint i
, GLint j
, GLfloat
*texel
)
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
]);
328 fetch_srgba_dxt3(const GLubyte
*map
,
329 GLint rowStride
, GLint i
, GLint j
, GLfloat
*texel
)
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
]);
340 fetch_srgba_dxt5(const GLubyte
*map
,
341 GLint rowStride
, GLint i
, GLint j
, GLfloat
*texel
)
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
]);
353 compressed_fetch_func
354 _mesa_get_dxt_fetch_func(mesa_format 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
;