2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
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 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 * \file texcompress_s3tc.c
28 * GL_EXT_texture_compression_s3tc support.
38 #include "texcompress.h"
39 #include "texformat.h"
45 _mesa_init_texture_s3tc( GLcontext
*ctx
)
47 /* called during context initialization */
52 * Called via TexFormat->StoreImage to store an RGB_DXT1 texture.
55 texstore_rgb_dxt1(STORE_PARAMS
)
60 const GLint texWidth
= dstRowStride
* 4 / 8; /* a bit of a hack */
61 const GLchan
*tempImage
= NULL
;
63 ASSERT(dstFormat
== &_mesa_texformat_rgb_dxt1
);
64 ASSERT(dstXoffset
% 4 == 0);
65 ASSERT(dstYoffset
% 4 == 0);
66 ASSERT(dstZoffset
% 4 == 0);
68 if (srcFormat
!= GL_RGB
||
69 srcType
!= CHAN_TYPE
||
70 ctx
->_ImageTransferState
||
71 srcPacking
->SwapBytes
) {
72 /* convert image to RGB/GLchan */
73 tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
75 dstFormat
->BaseFormat
,
76 srcWidth
, srcHeight
, srcDepth
,
77 srcFormat
, srcType
, srcAddr
,
80 return GL_FALSE
; /* out of memory */
81 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
83 srcRowStride
= 3 * srcWidth
;
87 pixels
= (const GLchan
*) srcAddr
;
88 srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
, srcFormat
,
89 srcType
) / sizeof(GLchan
);
92 dst
= _mesa_compressed_image_address(dstXoffset
, dstYoffset
, 0,
93 GL_COMPRESSED_RGB_S3TC_DXT1_EXT
,
94 texWidth
, (GLubyte
*) dstAddr
);
97 compress_dxt1(ctx
, srcWidth
, srcHeight
, srcFormat
, pixels
, srcRowStride
,
102 _mesa_free((void *) tempImage
);
109 * Called via TexFormat->StoreImage to store an RGBA_DXT1 texture.
112 texstore_rgba_dxt1(STORE_PARAMS
)
114 const GLchan
*pixels
;
117 const GLint texWidth
= dstRowStride
* 4 / 8; /* a bit of a hack */
118 const GLchan
*tempImage
= NULL
;
120 ASSERT(dstFormat
== &_mesa_texformat_rgba_dxt1
);
121 ASSERT(dstXoffset
% 4 == 0);
122 ASSERT(dstYoffset
% 4 == 0);
123 ASSERT(dstZoffset
% 4 == 0);
125 if (srcFormat
!= GL_RGBA
||
126 srcType
!= CHAN_TYPE
||
127 ctx
->_ImageTransferState
||
128 srcPacking
->SwapBytes
) {
129 /* convert image to RGBA/GLchan */
130 tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
132 dstFormat
->BaseFormat
,
133 srcWidth
, srcHeight
, srcDepth
,
134 srcFormat
, srcType
, srcAddr
,
137 return GL_FALSE
; /* out of memory */
138 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
140 srcRowStride
= 4 * srcWidth
;
144 pixels
= (const GLchan
*) srcAddr
;
145 srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
, srcFormat
,
146 srcType
) / sizeof(GLchan
);
149 dst
= _mesa_compressed_image_address(dstXoffset
, dstYoffset
, 0,
150 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
,
151 texWidth
, (GLubyte
*) dstAddr
);
153 compress_dxt1(ctx
, srcWidth
, srcHeight
, srcFormat
, pixels
, srcRowStride
,
157 _mesa_free((void*) tempImage
);
164 * Called via TexFormat->StoreImage to store an RGBA_DXT3 texture.
167 texstore_rgba_dxt3(STORE_PARAMS
)
169 const GLchan
*pixels
;
172 const GLint texWidth
= dstRowStride
* 4 / 16; /* a bit of a hack */
173 const GLchan
*tempImage
= NULL
;
175 ASSERT(dstFormat
== &_mesa_texformat_rgba_dxt3
);
176 ASSERT(dstXoffset
% 4 == 0);
177 ASSERT(dstYoffset
% 4 == 0);
178 ASSERT(dstZoffset
% 4 == 0);
180 if (srcFormat
!= GL_RGBA
||
181 srcType
!= CHAN_TYPE
||
182 ctx
->_ImageTransferState
||
183 srcPacking
->SwapBytes
) {
184 /* convert image to RGBA/GLchan */
185 tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
187 dstFormat
->BaseFormat
,
188 srcWidth
, srcHeight
, srcDepth
,
189 srcFormat
, srcType
, srcAddr
,
192 return GL_FALSE
; /* out of memory */
193 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
195 srcRowStride
= 4 * srcWidth
;
198 pixels
= (const GLchan
*) srcAddr
;
199 srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
, srcFormat
,
200 srcType
) / sizeof(GLchan
);
203 dst
= _mesa_compressed_image_address(dstXoffset
, dstYoffset
, 0,
204 GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
,
205 texWidth
, (GLubyte
*) dstAddr
);
207 compress_rgba_dxt3(ctx
, srcWidth
, srcHeight
, pixels
,
208 srcRowStride
, dst
, dstRowStride
);
211 _mesa_free((void *) tempImage
);
218 * Called via TexFormat->StoreImage to store an RGBA_DXT5 texture.
221 texstore_rgba_dxt5(STORE_PARAMS
)
223 const GLchan
*pixels
;
226 const GLint texWidth
= dstRowStride
* 4 / 16; /* a bit of a hack */
227 const GLchan
*tempImage
= NULL
;
229 ASSERT(dstFormat
== &_mesa_texformat_rgba_dxt5
);
230 ASSERT(dstXoffset
% 4 == 0);
231 ASSERT(dstYoffset
% 4 == 0);
232 ASSERT(dstZoffset
% 4 == 0);
234 if (srcFormat
!= GL_RGBA
||
235 srcType
!= CHAN_TYPE
||
236 ctx
->_ImageTransferState
||
237 srcPacking
->SwapBytes
) {
238 /* convert image to RGBA/GLchan */
239 tempImage
= _mesa_make_temp_chan_image(ctx
, dims
,
241 dstFormat
->BaseFormat
,
242 srcWidth
, srcHeight
, srcDepth
,
243 srcFormat
, srcType
, srcAddr
,
246 return GL_FALSE
; /* out of memory */
247 _mesa_adjust_image_for_convolution(ctx
, dims
, &srcWidth
, &srcHeight
);
249 srcRowStride
= 4 * srcWidth
;
252 pixels
= (const GLchan
*) srcAddr
;
253 srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
, srcFormat
,
254 srcType
) / sizeof(GLchan
);
257 dst
= _mesa_compressed_image_address(dstXoffset
, dstYoffset
, 0,
258 GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
,
259 texWidth
, (GLubyte
*) dstAddr
);
261 compress_rgba_dxt5(ctx
, srcWidth
, srcHeight
, pixels
,
262 srcRowStride
, dst
, dstRowStride
);
265 _mesa_free((void *) tempImage
);
272 fetch_texel_2d_rgb_dxt1( const struct gl_texture_image
*texImage
,
273 GLint i
, GLint j
, GLint k
, GLchan
*texel
)
279 fetch_texel_2d_f_rgb_dxt1( const struct gl_texture_image
*texImage
,
280 GLint i
, GLint j
, GLint k
, GLfloat
*texel
)
282 /* just sample as GLchan and convert to float here */
284 fetch_texel_2d_rgb_dxt1(texImage
, i
, j
, k
, rgba
);
285 texel
[RCOMP
] = CHAN_TO_FLOAT(rgba
[RCOMP
]);
286 texel
[GCOMP
] = CHAN_TO_FLOAT(rgba
[GCOMP
]);
287 texel
[BCOMP
] = CHAN_TO_FLOAT(rgba
[BCOMP
]);
288 texel
[ACOMP
] = CHAN_TO_FLOAT(rgba
[ACOMP
]);
293 fetch_texel_2d_rgba_dxt1( const struct gl_texture_image
*texImage
,
294 GLint i
, GLint j
, GLint k
, GLchan
*texel
)
300 fetch_texel_2d_f_rgba_dxt1( const struct gl_texture_image
*texImage
,
301 GLint i
, GLint j
, GLint k
, GLfloat
*texel
)
303 /* just sample as GLchan and convert to float here */
305 fetch_texel_2d_rgba_dxt1(texImage
, i
, j
, k
, rgba
);
306 texel
[RCOMP
] = CHAN_TO_FLOAT(rgba
[RCOMP
]);
307 texel
[GCOMP
] = CHAN_TO_FLOAT(rgba
[GCOMP
]);
308 texel
[BCOMP
] = CHAN_TO_FLOAT(rgba
[BCOMP
]);
309 texel
[ACOMP
] = CHAN_TO_FLOAT(rgba
[ACOMP
]);
314 fetch_texel_2d_rgba_dxt3( const struct gl_texture_image
*texImage
,
315 GLint i
, GLint j
, GLint k
, GLchan
*texel
)
321 fetch_texel_2d_f_rgba_dxt3( const struct gl_texture_image
*texImage
,
322 GLint i
, GLint j
, GLint k
, GLfloat
*texel
)
324 /* just sample as GLchan and convert to float here */
326 fetch_texel_2d_rgba_dxt3(texImage
, i
, j
, k
, rgba
);
327 texel
[RCOMP
] = CHAN_TO_FLOAT(rgba
[RCOMP
]);
328 texel
[GCOMP
] = CHAN_TO_FLOAT(rgba
[GCOMP
]);
329 texel
[BCOMP
] = CHAN_TO_FLOAT(rgba
[BCOMP
]);
330 texel
[ACOMP
] = CHAN_TO_FLOAT(rgba
[ACOMP
]);
335 fetch_texel_2d_rgba_dxt5( const struct gl_texture_image
*texImage
,
336 GLint i
, GLint j
, GLint k
, GLchan
*texel
)
342 fetch_texel_2d_f_rgba_dxt5( const struct gl_texture_image
*texImage
,
343 GLint i
, GLint j
, GLint k
, GLfloat
*texel
)
345 /* just sample as GLchan and convert to float here */
347 fetch_texel_2d_rgba_dxt5(texImage
, i
, j
, k
, rgba
);
348 texel
[RCOMP
] = CHAN_TO_FLOAT(rgba
[RCOMP
]);
349 texel
[GCOMP
] = CHAN_TO_FLOAT(rgba
[GCOMP
]);
350 texel
[BCOMP
] = CHAN_TO_FLOAT(rgba
[BCOMP
]);
351 texel
[ACOMP
] = CHAN_TO_FLOAT(rgba
[ACOMP
]);
355 const struct gl_texture_format _mesa_texformat_rgb_dxt1
= {
356 MESA_FORMAT_RGB_DXT1
, /* MesaFormat */
357 GL_RGB
, /* BaseFormat */
358 GL_UNSIGNED_NORMALIZED_ARB
, /* DataType */
359 4, /*approx*/ /* RedBits */
360 4, /*approx*/ /* GreenBits */
361 4, /*approx*/ /* BlueBits */
363 0, /* LuminanceBits */
364 0, /* IntensityBits */
368 texstore_rgb_dxt1
, /* StoreTexImageFunc */
369 NULL
, /*impossible*/ /* FetchTexel1D */
370 fetch_texel_2d_rgb_dxt1
, /* FetchTexel2D */
371 NULL
, /*impossible*/ /* FetchTexel3D */
372 NULL
, /*impossible*/ /* FetchTexel1Df */
373 fetch_texel_2d_f_rgb_dxt1
, /* FetchTexel2Df */
374 NULL
, /*impossible*/ /* FetchTexel3Df */
377 const struct gl_texture_format _mesa_texformat_rgba_dxt1
= {
378 MESA_FORMAT_RGBA_DXT1
, /* MesaFormat */
379 GL_RGBA
, /* BaseFormat */
380 GL_UNSIGNED_NORMALIZED_ARB
, /* DataType */
381 4, /*approx*/ /* RedBits */
382 4, /*approx*/ /* GreenBits */
383 4, /*approx*/ /* BlueBits */
384 1, /*approx*/ /* AlphaBits */
385 0, /* LuminanceBits */
386 0, /* IntensityBits */
390 texstore_rgba_dxt1
, /* StoreTexImageFunc */
391 NULL
, /*impossible*/ /* FetchTexel1D */
392 fetch_texel_2d_rgba_dxt1
, /* FetchTexel2D */
393 NULL
, /*impossible*/ /* FetchTexel3D */
394 NULL
, /*impossible*/ /* FetchTexel1Df */
395 fetch_texel_2d_f_rgba_dxt1
, /* FetchTexel2Df */
396 NULL
, /*impossible*/ /* FetchTexel3Df */
399 const struct gl_texture_format _mesa_texformat_rgba_dxt3
= {
400 MESA_FORMAT_RGBA_DXT3
, /* MesaFormat */
401 GL_RGBA
, /* BaseFormat */
402 GL_UNSIGNED_NORMALIZED_ARB
, /* DataType */
403 4, /*approx*/ /* RedBits */
404 4, /*approx*/ /* GreenBits */
405 4, /*approx*/ /* BlueBits */
406 4, /*approx*/ /* AlphaBits */
407 0, /* LuminanceBits */
408 0, /* IntensityBits */
412 texstore_rgba_dxt3
, /* StoreTexImageFunc */
413 NULL
, /*impossible*/ /* FetchTexel1D */
414 fetch_texel_2d_rgba_dxt3
, /* FetchTexel2D */
415 NULL
, /*impossible*/ /* FetchTexel3D */
416 NULL
, /*impossible*/ /* FetchTexel1Df */
417 fetch_texel_2d_f_rgba_dxt3
, /* FetchTexel2Df */
418 NULL
, /*impossible*/ /* FetchTexel3Df */
421 const struct gl_texture_format _mesa_texformat_rgba_dxt5
= {
422 MESA_FORMAT_RGBA_DXT5
, /* MesaFormat */
423 GL_RGBA
, /* BaseFormat */
424 GL_UNSIGNED_NORMALIZED_ARB
, /* DataType */
425 4,/*approx*/ /* RedBits */
426 4,/*approx*/ /* GreenBits */
427 4,/*approx*/ /* BlueBits */
428 4,/*approx*/ /* AlphaBits */
429 0, /* LuminanceBits */
430 0, /* IntensityBits */
434 texstore_rgba_dxt5
, /* StoreTexImageFunc */
435 NULL
, /*impossible*/ /* FetchTexel1D */
436 fetch_texel_2d_rgba_dxt5
, /* FetchTexel2D */
437 NULL
, /*impossible*/ /* FetchTexel3D */
438 NULL
, /*impossible*/ /* FetchTexel1Df */
439 fetch_texel_2d_f_rgba_dxt5
, /* FetchTexel2Df */
440 NULL
, /*impossible*/ /* FetchTexel3Df */