mesa: fix potential mem leak in generate_mipmap_compressed()
[mesa.git] / src / mesa / main / texcompress_rgtc.c
1 /*
2 * Copyright (C) 2011 Red Hat Inc.
3 *
4 * block compression parts are:
5 * Copyright (C) 2004 Roland Scheidegger 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 (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
25 *
26 * Author:
27 * Dave Airlie
28 */
29
30 /**
31 * \file texcompress_rgtc.c
32 * GL_EXT_texture_compression_rgtc support.
33 */
34
35
36 #include "glheader.h"
37 #include "imports.h"
38 #include "colormac.h"
39 #include "image.h"
40 #include "macros.h"
41 #include "mfeatures.h"
42 #include "mipmap.h"
43 #include "texcompress.h"
44 #include "texcompress_rgtc.h"
45 #include "texstore.h"
46 #include "swrast/s_context.h"
47
48
49 #define RGTC_DEBUG 0
50
51 static void unsigned_encode_rgtc_ubyte(GLubyte *blkaddr, GLubyte srccolors[4][4],
52 GLint numxpixels, GLint numypixels);
53 static void signed_encode_rgtc_ubyte(GLbyte *blkaddr, GLbyte srccolors[4][4],
54 GLint numxpixels, GLint numypixels);
55
56 static void unsigned_fetch_texel_rgtc(unsigned srcRowStride, const GLubyte *pixdata,
57 unsigned i, unsigned j, GLubyte *value, unsigned comps);
58
59 static void signed_fetch_texel_rgtc(unsigned srcRowStride, const GLbyte *pixdata,
60 unsigned i, unsigned j, GLbyte *value, unsigned comps);
61
62 static void extractsrc_u( GLubyte srcpixels[4][4], const GLubyte *srcaddr,
63 GLint srcRowStride, GLint numxpixels, GLint numypixels, GLint comps)
64 {
65 GLubyte i, j;
66 const GLubyte *curaddr;
67 for (j = 0; j < numypixels; j++) {
68 curaddr = srcaddr + j * srcRowStride * comps;
69 for (i = 0; i < numxpixels; i++) {
70 srcpixels[j][i] = *curaddr;
71 curaddr += comps;
72 }
73 }
74 }
75
76 static void extractsrc_s( GLbyte srcpixels[4][4], const GLfloat *srcaddr,
77 GLint srcRowStride, GLint numxpixels, GLint numypixels, GLint comps)
78 {
79 GLubyte i, j;
80 const GLfloat *curaddr;
81 for (j = 0; j < numypixels; j++) {
82 curaddr = srcaddr + j * srcRowStride * comps;
83 for (i = 0; i < numxpixels; i++) {
84 srcpixels[j][i] = FLOAT_TO_BYTE_TEX(*curaddr);
85 curaddr += comps;
86 }
87 }
88 }
89
90
91 GLboolean
92 _mesa_texstore_red_rgtc1(TEXSTORE_PARAMS)
93 {
94 GLubyte *dst;
95 const GLint texWidth = dstRowStride * 4 / 8; /* a bit of a hack */
96 const GLubyte *tempImage = NULL;
97 int i, j;
98 int numxpixels, numypixels;
99 const GLubyte *srcaddr;
100 GLubyte srcpixels[4][4];
101 GLubyte *blkaddr;
102 GLint dstRowDiff;
103 ASSERT(dstFormat == MESA_FORMAT_RED_RGTC1 ||
104 dstFormat == MESA_FORMAT_L_LATC1);
105 ASSERT(dstXoffset % 4 == 0);
106 ASSERT(dstYoffset % 4 == 0);
107 ASSERT(dstZoffset % 4 == 0);
108 (void) dstZoffset;
109
110
111 tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
112 baseInternalFormat,
113 _mesa_get_format_base_format(dstFormat),
114 srcWidth, srcHeight, srcDepth,
115 srcFormat, srcType, srcAddr,
116 srcPacking);
117 if (!tempImage)
118 return GL_FALSE; /* out of memory */
119
120 dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0,
121 dstFormat,
122 texWidth, dstSlices[0]);
123
124 blkaddr = dst;
125 dstRowDiff = dstRowStride >= (srcWidth * 2) ? dstRowStride - (((srcWidth + 3) & ~3) * 2) : 0;
126 for (j = 0; j < srcHeight; j+=4) {
127 if (srcHeight > j + 3) numypixels = 4;
128 else numypixels = srcHeight - j;
129 srcaddr = tempImage + j * srcWidth;
130 for (i = 0; i < srcWidth; i += 4) {
131 if (srcWidth > i + 3) numxpixels = 4;
132 else numxpixels = srcWidth - i;
133 extractsrc_u(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 1);
134 unsigned_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);
135 srcaddr += numxpixels;
136 blkaddr += 8;
137 }
138 blkaddr += dstRowDiff;
139 }
140 if (tempImage)
141 free((void *) tempImage);
142
143 return GL_TRUE;
144 }
145
146 GLboolean
147 _mesa_texstore_signed_red_rgtc1(TEXSTORE_PARAMS)
148 {
149 GLbyte *dst;
150 const GLint texWidth = dstRowStride * 4 / 8; /* a bit of a hack */
151 const GLfloat *tempImage = NULL;
152 int i, j;
153 int numxpixels, numypixels;
154 const GLfloat *srcaddr;
155 GLbyte srcpixels[4][4];
156 GLbyte *blkaddr;
157 GLint dstRowDiff;
158 ASSERT(dstFormat == MESA_FORMAT_SIGNED_RED_RGTC1 ||
159 dstFormat == MESA_FORMAT_SIGNED_L_LATC1);
160 ASSERT(dstXoffset % 4 == 0);
161 ASSERT(dstYoffset % 4 == 0);
162 ASSERT(dstZoffset % 4 == 0);
163 (void) dstZoffset;
164
165 tempImage = _mesa_make_temp_float_image(ctx, dims,
166 baseInternalFormat,
167 _mesa_get_format_base_format(dstFormat),
168 srcWidth, srcHeight, srcDepth,
169 srcFormat, srcType, srcAddr,
170 srcPacking, 0x0);
171 if (!tempImage)
172 return GL_FALSE; /* out of memory */
173
174 dst = (GLbyte *)_mesa_compressed_image_address(dstXoffset, dstYoffset, 0,
175 dstFormat,
176 texWidth, dstSlices[0]);
177
178 blkaddr = dst;
179 dstRowDiff = dstRowStride >= (srcWidth * 2) ? dstRowStride - (((srcWidth + 3) & ~3) * 2) : 0;
180 for (j = 0; j < srcHeight; j+=4) {
181 if (srcHeight > j + 3) numypixels = 4;
182 else numypixels = srcHeight - j;
183 srcaddr = tempImage + j * srcWidth;
184 for (i = 0; i < srcWidth; i += 4) {
185 if (srcWidth > i + 3) numxpixels = 4;
186 else numxpixels = srcWidth - i;
187 extractsrc_s(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 1);
188 signed_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);
189 srcaddr += numxpixels;
190 blkaddr += 8;
191 }
192 blkaddr += dstRowDiff;
193 }
194 if (tempImage)
195 free((void *) tempImage);
196
197 return GL_TRUE;
198 }
199
200 GLboolean
201 _mesa_texstore_rg_rgtc2(TEXSTORE_PARAMS)
202 {
203 GLubyte *dst;
204 const GLint texWidth = dstRowStride * 4 / 16; /* a bit of a hack */
205 const GLubyte *tempImage = NULL;
206 int i, j;
207 int numxpixels, numypixels;
208 const GLubyte *srcaddr;
209 GLubyte srcpixels[4][4];
210 GLubyte *blkaddr;
211 GLint dstRowDiff;
212
213 ASSERT(dstFormat == MESA_FORMAT_RG_RGTC2 ||
214 dstFormat == MESA_FORMAT_LA_LATC2);
215 ASSERT(dstXoffset % 4 == 0);
216 ASSERT(dstYoffset % 4 == 0);
217 ASSERT(dstZoffset % 4 == 0);
218 (void) dstZoffset;
219
220 tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
221 baseInternalFormat,
222 _mesa_get_format_base_format(dstFormat),
223 srcWidth, srcHeight, srcDepth,
224 srcFormat, srcType, srcAddr,
225 srcPacking);
226 if (!tempImage)
227 return GL_FALSE; /* out of memory */
228
229 dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0,
230 dstFormat,
231 texWidth, dstSlices[0]);
232
233 blkaddr = dst;
234 dstRowDiff = dstRowStride >= (srcWidth * 4) ? dstRowStride - (((srcWidth + 3) & ~3) * 4) : 0;
235 for (j = 0; j < srcHeight; j+=4) {
236 if (srcHeight > j + 3) numypixels = 4;
237 else numypixels = srcHeight - j;
238 srcaddr = tempImage + j * srcWidth * 2;
239 for (i = 0; i < srcWidth; i += 4) {
240 if (srcWidth > i + 3) numxpixels = 4;
241 else numxpixels = srcWidth - i;
242 extractsrc_u(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 2);
243 unsigned_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);
244
245 blkaddr += 8;
246 extractsrc_u(srcpixels, (GLubyte *)srcaddr + 1, srcWidth, numxpixels, numypixels, 2);
247 unsigned_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);
248
249 blkaddr += 8;
250
251 srcaddr += numxpixels * 2;
252 }
253 blkaddr += dstRowDiff;
254 }
255 if (tempImage)
256 free((void *) tempImage);
257
258 return GL_TRUE;
259 }
260
261 GLboolean
262 _mesa_texstore_signed_rg_rgtc2(TEXSTORE_PARAMS)
263 {
264 GLbyte *dst;
265 const GLint texWidth = dstRowStride * 4 / 16; /* a bit of a hack */
266 const GLfloat *tempImage = NULL;
267 int i, j;
268 int numxpixels, numypixels;
269 const GLfloat *srcaddr;
270 GLbyte srcpixels[4][4];
271 GLbyte *blkaddr;
272 GLint dstRowDiff;
273
274 ASSERT(dstFormat == MESA_FORMAT_SIGNED_RG_RGTC2 ||
275 dstFormat == MESA_FORMAT_SIGNED_LA_LATC2);
276 ASSERT(dstXoffset % 4 == 0);
277 ASSERT(dstYoffset % 4 == 0);
278 ASSERT(dstZoffset % 4 == 0);
279 (void) dstZoffset;
280
281 tempImage = _mesa_make_temp_float_image(ctx, dims,
282 baseInternalFormat,
283 _mesa_get_format_base_format(dstFormat),
284 srcWidth, srcHeight, srcDepth,
285 srcFormat, srcType, srcAddr,
286 srcPacking, 0x0);
287 if (!tempImage)
288 return GL_FALSE; /* out of memory */
289
290 dst = (GLbyte *)_mesa_compressed_image_address(dstXoffset, dstYoffset, 0,
291 dstFormat,
292 texWidth, dstSlices[0]);
293
294 blkaddr = dst;
295 dstRowDiff = dstRowStride >= (srcWidth * 4) ? dstRowStride - (((srcWidth + 3) & ~3) * 4) : 0;
296 for (j = 0; j < srcHeight; j += 4) {
297 if (srcHeight > j + 3) numypixels = 4;
298 else numypixels = srcHeight - j;
299 srcaddr = tempImage + j * srcWidth * 2;
300 for (i = 0; i < srcWidth; i += 4) {
301 if (srcWidth > i + 3) numxpixels = 4;
302 else numxpixels = srcWidth - i;
303
304 extractsrc_s(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 2);
305 signed_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);
306 blkaddr += 8;
307
308 extractsrc_s(srcpixels, srcaddr + 1, srcWidth, numxpixels, numypixels, 2);
309 signed_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);
310 blkaddr += 8;
311
312 srcaddr += numxpixels * 2;
313
314 }
315 blkaddr += dstRowDiff;
316 }
317 if (tempImage)
318 free((void *) tempImage);
319
320 return GL_TRUE;
321 }
322
323 void
324 _mesa_fetch_texel_2d_f_red_rgtc1(const struct swrast_texture_image *texImage,
325 GLint i, GLint j, GLint k, GLfloat *texel)
326 {
327 GLubyte red;
328 unsigned_fetch_texel_rgtc(texImage->RowStride, texImage->Data,
329 i, j, &red, 1);
330 texel[RCOMP] = UBYTE_TO_FLOAT(red);
331 texel[GCOMP] = 0.0;
332 texel[BCOMP] = 0.0;
333 texel[ACOMP] = 1.0;
334 }
335
336 void
337 _mesa_fetch_texel_2d_f_signed_red_rgtc1(const struct swrast_texture_image *texImage,
338 GLint i, GLint j, GLint k, GLfloat *texel)
339 {
340 GLbyte red;
341 signed_fetch_texel_rgtc(texImage->RowStride, (GLbyte *)(texImage->Data),
342 i, j, &red, 1);
343 texel[RCOMP] = BYTE_TO_FLOAT_TEX(red);
344 texel[GCOMP] = 0.0;
345 texel[BCOMP] = 0.0;
346 texel[ACOMP] = 1.0;
347 }
348
349 void
350 _mesa_fetch_texel_2d_f_rg_rgtc2(const struct swrast_texture_image *texImage,
351 GLint i, GLint j, GLint k, GLfloat *texel)
352 {
353 GLubyte red, green;
354 unsigned_fetch_texel_rgtc(texImage->RowStride, texImage->Data,
355 i, j, &red, 2);
356 unsigned_fetch_texel_rgtc(texImage->RowStride, texImage->Data + 8,
357 i, j, &green, 2);
358 texel[RCOMP] = UBYTE_TO_FLOAT(red);
359 texel[GCOMP] = UBYTE_TO_FLOAT(green);
360 texel[BCOMP] = 0.0;
361 texel[ACOMP] = 1.0;
362 }
363
364 void
365 _mesa_fetch_texel_2d_f_signed_rg_rgtc2(const struct swrast_texture_image *texImage,
366 GLint i, GLint j, GLint k, GLfloat *texel)
367 {
368 GLbyte red, green;
369 signed_fetch_texel_rgtc(texImage->RowStride, (GLbyte *)(texImage->Data),
370 i, j, &red, 2);
371 signed_fetch_texel_rgtc(texImage->RowStride, (GLbyte *)(texImage->Data) + 8,
372 i, j, &green, 2);
373 texel[RCOMP] = BYTE_TO_FLOAT_TEX(red);
374 texel[GCOMP] = BYTE_TO_FLOAT_TEX(green);
375 texel[BCOMP] = 0.0;
376 texel[ACOMP] = 1.0;
377 }
378
379 void
380 _mesa_fetch_texel_2d_f_l_latc1(const struct swrast_texture_image *texImage,
381 GLint i, GLint j, GLint k, GLfloat *texel)
382 {
383 GLubyte red;
384 unsigned_fetch_texel_rgtc(texImage->RowStride, texImage->Data,
385 i, j, &red, 1);
386 texel[RCOMP] =
387 texel[GCOMP] =
388 texel[BCOMP] = UBYTE_TO_FLOAT(red);
389 texel[ACOMP] = 1.0;
390 }
391
392 void
393 _mesa_fetch_texel_2d_f_signed_l_latc1(const struct swrast_texture_image *texImage,
394 GLint i, GLint j, GLint k, GLfloat *texel)
395 {
396 GLbyte red;
397 signed_fetch_texel_rgtc(texImage->RowStride, (GLbyte *)(texImage->Data),
398 i, j, &red, 1);
399 texel[RCOMP] =
400 texel[GCOMP] =
401 texel[BCOMP] = BYTE_TO_FLOAT_TEX(red);
402 texel[ACOMP] = 1.0;
403 }
404
405 void
406 _mesa_fetch_texel_2d_f_la_latc2(const struct swrast_texture_image *texImage,
407 GLint i, GLint j, GLint k, GLfloat *texel)
408 {
409 GLubyte red, green;
410 unsigned_fetch_texel_rgtc(texImage->RowStride, texImage->Data,
411 i, j, &red, 2);
412 unsigned_fetch_texel_rgtc(texImage->RowStride, texImage->Data + 8,
413 i, j, &green, 2);
414 texel[RCOMP] =
415 texel[GCOMP] =
416 texel[BCOMP] = UBYTE_TO_FLOAT(red);
417 texel[ACOMP] = UBYTE_TO_FLOAT(green);
418 }
419
420 void
421 _mesa_fetch_texel_2d_f_signed_la_latc2(const struct swrast_texture_image *texImage,
422 GLint i, GLint j, GLint k, GLfloat *texel)
423 {
424 GLbyte red, green;
425 signed_fetch_texel_rgtc(texImage->RowStride, (GLbyte *)(texImage->Data),
426 i, j, &red, 2);
427 signed_fetch_texel_rgtc(texImage->RowStride, (GLbyte *)(texImage->Data) + 8,
428 i, j, &green, 2);
429 texel[RCOMP] =
430 texel[GCOMP] =
431 texel[BCOMP] = BYTE_TO_FLOAT_TEX(red);
432 texel[ACOMP] = BYTE_TO_FLOAT_TEX(green);
433 }
434
435 #define TAG(x) unsigned_##x
436
437 #define TYPE GLubyte
438 #define T_MIN 0
439 #define T_MAX 0xff
440
441 #include "texcompress_rgtc_tmp.h"
442
443 #undef TAG
444 #undef TYPE
445 #undef T_MIN
446 #undef T_MAX
447
448 #define TAG(x) signed_##x
449 #define TYPE GLbyte
450 #define T_MIN (GLbyte)-128
451 #define T_MAX (GLbyte)127
452
453 #include "texcompress_rgtc_tmp.h"
454
455 #undef TAG
456 #undef TYPE
457 #undef T_MIN
458 #undef T_MAX