08697f46c4294f94cee941fb2260582e2171429a
[mesa.git] / src / mesa / main / texcompress_s3tc.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.1
4 *
5 * Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
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 * 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.
23 */
24
25
26 /**
27 * \file texcompress_s3tc.c
28 * GL_EXT_texture_compression_s3tc support.
29 */
30
31
32 #include "glheader.h"
33 #include "imports.h"
34 #include "colormac.h"
35 #include "context.h"
36 #include "convolve.h"
37 #include "image.h"
38 #include "texcompress.h"
39 #include "texformat.h"
40 #include "texstore.h"
41
42
43
44 void
45 _mesa_init_texture_s3tc( GLcontext *ctx )
46 {
47 /* called during context initialization */
48 }
49
50
51 /**
52 * Called via TexFormat->StoreImage to store an RGB_DXT1 texture.
53 */
54 static GLboolean
55 texstore_rgb_dxt1(STORE_PARAMS)
56 {
57 const GLchan *pixels;
58 GLint srcRowStride;
59 GLubyte *dst;
60 const GLint texWidth = dstRowStride * 4 / 8; /* a bit of a hack */
61 const GLchan *tempImage = NULL;
62
63 ASSERT(dstFormat == &_mesa_texformat_rgb_dxt1);
64 ASSERT(dstXoffset % 4 == 0);
65 ASSERT(dstYoffset % 4 == 0);
66 ASSERT(dstZoffset % 4 == 0);
67
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,
74 baseInternalFormat,
75 dstFormat->BaseFormat,
76 srcWidth, srcHeight, srcDepth,
77 srcFormat, srcType, srcAddr,
78 srcPacking);
79 if (!tempImage)
80 return GL_FALSE; /* out of memory */
81 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
82 pixels = tempImage;
83 srcRowStride = 3 * srcWidth;
84 srcFormat = GL_RGB;
85 }
86 else {
87 pixels = (const GLchan *) srcAddr;
88 srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat,
89 srcType) / sizeof(GLchan);
90 }
91
92 dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0,
93 GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
94 texWidth, (GLubyte *) dstAddr);
95
96 #if 0
97 compress_dxt1(ctx, srcWidth, srcHeight, srcFormat, pixels, srcRowStride,
98 dst, dstRowStride);
99 #endif
100
101 if (tempImage)
102 _mesa_free((void *) tempImage);
103
104 return GL_TRUE;
105 }
106
107
108 /**
109 * Called via TexFormat->StoreImage to store an RGBA_DXT1 texture.
110 */
111 static GLboolean
112 texstore_rgba_dxt1(STORE_PARAMS)
113 {
114 const GLchan *pixels;
115 GLint srcRowStride;
116 GLubyte *dst;
117 const GLint texWidth = dstRowStride * 4 / 8; /* a bit of a hack */
118 const GLchan *tempImage = NULL;
119
120 ASSERT(dstFormat == &_mesa_texformat_rgba_dxt1);
121 ASSERT(dstXoffset % 4 == 0);
122 ASSERT(dstYoffset % 4 == 0);
123 ASSERT(dstZoffset % 4 == 0);
124
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,
131 baseInternalFormat,
132 dstFormat->BaseFormat,
133 srcWidth, srcHeight, srcDepth,
134 srcFormat, srcType, srcAddr,
135 srcPacking);
136 if (!tempImage)
137 return GL_FALSE; /* out of memory */
138 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
139 pixels = tempImage;
140 srcRowStride = 4 * srcWidth;
141 srcFormat = GL_RGBA;
142 }
143 else {
144 pixels = (const GLchan *) srcAddr;
145 srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat,
146 srcType) / sizeof(GLchan);
147 }
148
149 dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0,
150 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
151 texWidth, (GLubyte *) dstAddr);
152 #if 0
153 compress_dxt1(ctx, srcWidth, srcHeight, srcFormat, pixels, srcRowStride,
154 dst, dstRowStride);
155 #endif
156 if (tempImage)
157 _mesa_free((void*) tempImage);
158
159 return GL_TRUE;
160 }
161
162
163 /**
164 * Called via TexFormat->StoreImage to store an RGBA_DXT3 texture.
165 */
166 static GLboolean
167 texstore_rgba_dxt3(STORE_PARAMS)
168 {
169 const GLchan *pixels;
170 GLint srcRowStride;
171 GLubyte *dst;
172 const GLint texWidth = dstRowStride * 4 / 16; /* a bit of a hack */
173 const GLchan *tempImage = NULL;
174
175 ASSERT(dstFormat == &_mesa_texformat_rgba_dxt3);
176 ASSERT(dstXoffset % 4 == 0);
177 ASSERT(dstYoffset % 4 == 0);
178 ASSERT(dstZoffset % 4 == 0);
179
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,
186 baseInternalFormat,
187 dstFormat->BaseFormat,
188 srcWidth, srcHeight, srcDepth,
189 srcFormat, srcType, srcAddr,
190 srcPacking);
191 if (!tempImage)
192 return GL_FALSE; /* out of memory */
193 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
194 pixels = tempImage;
195 srcRowStride = 4 * srcWidth;
196 }
197 else {
198 pixels = (const GLchan *) srcAddr;
199 srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat,
200 srcType) / sizeof(GLchan);
201 }
202
203 dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0,
204 GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,
205 texWidth, (GLubyte *) dstAddr);
206 #if 0
207 compress_rgba_dxt3(ctx, srcWidth, srcHeight, pixels,
208 srcRowStride, dst, dstRowStride);
209 #endif
210 if (tempImage)
211 _mesa_free((void *) tempImage);
212
213 return GL_TRUE;
214 }
215
216
217 /**
218 * Called via TexFormat->StoreImage to store an RGBA_DXT5 texture.
219 */
220 static GLboolean
221 texstore_rgba_dxt5(STORE_PARAMS)
222 {
223 const GLchan *pixels;
224 GLint srcRowStride;
225 GLubyte *dst;
226 const GLint texWidth = dstRowStride * 4 / 16; /* a bit of a hack */
227 const GLchan *tempImage = NULL;
228
229 ASSERT(dstFormat == &_mesa_texformat_rgba_dxt5);
230 ASSERT(dstXoffset % 4 == 0);
231 ASSERT(dstYoffset % 4 == 0);
232 ASSERT(dstZoffset % 4 == 0);
233
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,
240 baseInternalFormat,
241 dstFormat->BaseFormat,
242 srcWidth, srcHeight, srcDepth,
243 srcFormat, srcType, srcAddr,
244 srcPacking);
245 if (!tempImage)
246 return GL_FALSE; /* out of memory */
247 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
248 pixels = tempImage;
249 srcRowStride = 4 * srcWidth;
250 }
251 else {
252 pixels = (const GLchan *) srcAddr;
253 srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat,
254 srcType) / sizeof(GLchan);
255 }
256
257 dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0,
258 GL_COMPRESSED_RGBA_S3TC_DXT5_EXT,
259 texWidth, (GLubyte *) dstAddr);
260 #if 0
261 compress_rgba_dxt5(ctx, srcWidth, srcHeight, pixels,
262 srcRowStride, dst, dstRowStride);
263 #endif
264 if (tempImage)
265 _mesa_free((void *) tempImage);
266
267 return GL_TRUE;
268 }
269
270
271 static void
272 fetch_texel_2d_rgb_dxt1( const struct gl_texture_image *texImage,
273 GLint i, GLint j, GLint k, GLchan *texel )
274 {
275 }
276
277
278 static void
279 fetch_texel_2d_f_rgb_dxt1( const struct gl_texture_image *texImage,
280 GLint i, GLint j, GLint k, GLfloat *texel )
281 {
282 /* just sample as GLchan and convert to float here */
283 GLchan rgba[4];
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]);
289 }
290
291
292 static void
293 fetch_texel_2d_rgba_dxt1( const struct gl_texture_image *texImage,
294 GLint i, GLint j, GLint k, GLchan *texel )
295 {
296 }
297
298
299 static void
300 fetch_texel_2d_f_rgba_dxt1( const struct gl_texture_image *texImage,
301 GLint i, GLint j, GLint k, GLfloat *texel )
302 {
303 /* just sample as GLchan and convert to float here */
304 GLchan rgba[4];
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]);
310 }
311
312
313 static void
314 fetch_texel_2d_rgba_dxt3( const struct gl_texture_image *texImage,
315 GLint i, GLint j, GLint k, GLchan *texel )
316 {
317 }
318
319
320 static void
321 fetch_texel_2d_f_rgba_dxt3( const struct gl_texture_image *texImage,
322 GLint i, GLint j, GLint k, GLfloat *texel )
323 {
324 /* just sample as GLchan and convert to float here */
325 GLchan rgba[4];
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]);
331 }
332
333
334 static void
335 fetch_texel_2d_rgba_dxt5( const struct gl_texture_image *texImage,
336 GLint i, GLint j, GLint k, GLchan *texel )
337 {
338 }
339
340
341 static void
342 fetch_texel_2d_f_rgba_dxt5( const struct gl_texture_image *texImage,
343 GLint i, GLint j, GLint k, GLfloat *texel )
344 {
345 /* just sample as GLchan and convert to float here */
346 GLchan rgba[4];
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]);
352 }
353
354
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 */
362 0, /* AlphaBits */
363 0, /* LuminanceBits */
364 0, /* IntensityBits */
365 0, /* IndexBits */
366 0, /* DepthBits */
367 0, /* TexelBytes */
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 */
375 };
376
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 */
387 0, /* IndexBits */
388 0, /* DepthBits */
389 0, /* TexelBytes */
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 */
397 };
398
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 */
409 0, /* IndexBits */
410 0, /* DepthBits */
411 0, /* TexelBytes */
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 */
419 };
420
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 */
431 0, /* IndexBits */
432 0, /* DepthBits */
433 0, /* TexelBytes */
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 */
441 };