texcompress_rgtc.c revision 6eff8479af1a137d81d7bffc0c55a39910c28ce9
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
47#define RGTC_DEBUG 0
48
49static void unsigned_encode_rgtc_chan(GLubyte *blkaddr, GLubyte srccolors[4][4],
50					GLint numxpixels, GLint numypixels);
51static void signed_encode_rgtc_chan(GLbyte *blkaddr, GLbyte srccolors[4][4],
52			     GLint numxpixels, GLint numypixels);
53
54static void unsigned_fetch_texel_rgtc(unsigned srcRowStride, const GLubyte *pixdata,
55				      unsigned i, unsigned j, GLubyte *value, unsigned comps);
56
57static void signed_fetch_texel_rgtc(unsigned srcRowStride, const GLbyte *pixdata,
58				      unsigned i, unsigned j, GLbyte *value, unsigned comps);
59
60static void extractsrc_u( GLubyte srcpixels[4][4], const GLchan *srcaddr,
61			  GLint srcRowStride, GLint numxpixels, GLint numypixels, GLint comps)
62{
63   GLubyte i, j;
64   const GLchan *curaddr;
65   for (j = 0; j < numypixels; j++) {
66      curaddr = srcaddr + j * srcRowStride * comps;
67      for (i = 0; i < numxpixels; i++) {
68	 srcpixels[j][i] = *curaddr / (CHAN_MAX / 255);
69	 curaddr += comps;
70      }
71   }
72}
73
74static void extractsrc_s( GLbyte srcpixels[4][4], const GLfloat *srcaddr,
75			  GLint srcRowStride, GLint numxpixels, GLint numypixels, GLint comps)
76{
77   GLubyte i, j;
78   const GLfloat *curaddr;
79   for (j = 0; j < numypixels; j++) {
80      curaddr = srcaddr + j * srcRowStride * comps;
81      for (i = 0; i < numxpixels; i++) {
82	 srcpixels[j][i] = FLOAT_TO_BYTE_TEX(*curaddr);
83	 curaddr += comps;
84      }
85   }
86}
87
88
89GLboolean
90_mesa_texstore_red_rgtc1(TEXSTORE_PARAMS)
91{
92   GLubyte *dst;
93   const GLint texWidth = dstRowStride * 4 / 8; /* a bit of a hack */
94   const GLchan *tempImage = NULL;
95   int i, j;
96   int numxpixels, numypixels;
97   const GLchan *srcaddr;
98   GLubyte srcpixels[4][4];
99   GLubyte *blkaddr;
100   GLint dstRowDiff;
101   ASSERT(dstFormat == MESA_FORMAT_RED_RGTC1 ||
102          dstFormat == MESA_FORMAT_L_LATC1);
103   ASSERT(dstXoffset % 4 == 0);
104   ASSERT(dstYoffset % 4 == 0);
105   ASSERT(dstZoffset % 4 == 0);
106   (void) dstZoffset;
107   (void) dstImageOffsets;
108
109
110   tempImage = _mesa_make_temp_chan_image(ctx, dims,
111					  baseInternalFormat,
112					  _mesa_get_format_base_format(dstFormat),
113					  srcWidth, srcHeight, srcDepth,
114					  srcFormat, srcType, srcAddr,
115					  srcPacking);
116   if (!tempImage)
117      return GL_FALSE; /* out of memory */
118
119   dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0,
120                                        dstFormat,
121                                        texWidth, (GLubyte *) dstAddr);
122
123   blkaddr = dst;
124   dstRowDiff = dstRowStride >= (srcWidth * 2) ? dstRowStride - (((srcWidth + 3) & ~3) * 2) : 0;
125   for (j = 0; j < srcHeight; j+=4) {
126      if (srcHeight > j + 3) numypixels = 4;
127      else numypixels = srcHeight - j;
128      srcaddr = tempImage + j * srcWidth;
129      for (i = 0; i < srcWidth; i += 4) {
130	 if (srcWidth > i + 3) numxpixels = 4;
131	 else numxpixels = srcWidth - i;
132	 extractsrc_u(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 1);
133	 unsigned_encode_rgtc_chan(blkaddr, srcpixels, numxpixels, numypixels);
134	 srcaddr += numxpixels;
135	 blkaddr += 8;
136      }
137      blkaddr += dstRowDiff;
138   }
139   if (tempImage)
140      free((void *) tempImage);
141
142   return GL_TRUE;
143}
144
145GLboolean
146_mesa_texstore_signed_red_rgtc1(TEXSTORE_PARAMS)
147{
148   GLbyte *dst;
149   const GLint texWidth = dstRowStride * 4 / 8; /* a bit of a hack */
150   const GLfloat *tempImage = NULL;
151   int i, j;
152   int numxpixels, numypixels;
153   const GLfloat *srcaddr;
154   GLbyte srcpixels[4][4];
155   GLbyte *blkaddr;
156   GLint dstRowDiff;
157   ASSERT(dstFormat == MESA_FORMAT_SIGNED_RED_RGTC1 ||
158          dstFormat == MESA_FORMAT_SIGNED_L_LATC1);
159   ASSERT(dstXoffset % 4 == 0);
160   ASSERT(dstYoffset % 4 == 0);
161   ASSERT(dstZoffset % 4 == 0);
162   (void) dstZoffset;
163   (void) dstImageOffsets;
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, (GLubyte *) dstAddr);
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_chan(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
200GLboolean
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 GLchan *tempImage = NULL;
206   int i, j;
207   int numxpixels, numypixels;
208   const GLchan *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   (void) dstImageOffsets;
220
221   tempImage = _mesa_make_temp_chan_image(ctx, dims,
222					  baseInternalFormat,
223					  _mesa_get_format_base_format(dstFormat),
224					  srcWidth, srcHeight, srcDepth,
225					  srcFormat, srcType, srcAddr,
226					  srcPacking);
227   if (!tempImage)
228      return GL_FALSE; /* out of memory */
229
230   dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0,
231                                        dstFormat,
232                                        texWidth, (GLubyte *) dstAddr);
233
234   blkaddr = dst;
235   dstRowDiff = dstRowStride >= (srcWidth * 4) ? dstRowStride - (((srcWidth + 3) & ~3) * 4) : 0;
236   for (j = 0; j < srcHeight; j+=4) {
237      if (srcHeight > j + 3) numypixels = 4;
238      else numypixels = srcHeight - j;
239      srcaddr = tempImage + j * srcWidth * 2;
240      for (i = 0; i < srcWidth; i += 4) {
241	 if (srcWidth > i + 3) numxpixels = 4;
242	 else numxpixels = srcWidth - i;
243	 extractsrc_u(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 2);
244	 unsigned_encode_rgtc_chan(blkaddr, srcpixels, numxpixels, numypixels);
245
246	 blkaddr += 8;
247	 extractsrc_u(srcpixels, (GLchan *)srcaddr + 1, srcWidth, numxpixels, numypixels, 2);
248	 unsigned_encode_rgtc_chan(blkaddr, srcpixels, numxpixels, numypixels);
249
250	 blkaddr += 8;
251
252	 srcaddr += numxpixels * 2;
253      }
254      blkaddr += dstRowDiff;
255   }
256   if (tempImage)
257      free((void *) tempImage);
258
259   return GL_TRUE;
260}
261
262GLboolean
263_mesa_texstore_signed_rg_rgtc2(TEXSTORE_PARAMS)
264{
265   GLbyte *dst;
266   const GLint texWidth = dstRowStride * 4 / 16; /* a bit of a hack */
267   const GLfloat *tempImage = NULL;
268   int i, j;
269   int numxpixels, numypixels;
270   const GLfloat *srcaddr;
271   GLbyte srcpixels[4][4];
272   GLbyte *blkaddr;
273   GLint dstRowDiff;
274
275   ASSERT(dstFormat == MESA_FORMAT_SIGNED_RG_RGTC2 ||
276          dstFormat == MESA_FORMAT_SIGNED_LA_LATC2);
277   ASSERT(dstXoffset % 4 == 0);
278   ASSERT(dstYoffset % 4 == 0);
279   ASSERT(dstZoffset % 4 == 0);
280   (void) dstZoffset;
281   (void) dstImageOffsets;
282
283   tempImage = _mesa_make_temp_float_image(ctx, dims,
284					   baseInternalFormat,
285					   _mesa_get_format_base_format(dstFormat),
286					   srcWidth, srcHeight, srcDepth,
287					   srcFormat, srcType, srcAddr,
288					   srcPacking, 0x0);
289   if (!tempImage)
290      return GL_FALSE; /* out of memory */
291
292   dst = (GLbyte *)_mesa_compressed_image_address(dstXoffset, dstYoffset, 0,
293						  dstFormat,
294						  texWidth, (GLubyte *) dstAddr);
295
296   blkaddr = dst;
297   dstRowDiff = dstRowStride >= (srcWidth * 4) ? dstRowStride - (((srcWidth + 3) & ~3) * 4) : 0;
298   for (j = 0; j < srcHeight; j += 4) {
299      if (srcHeight > j + 3) numypixels = 4;
300      else numypixels = srcHeight - j;
301      srcaddr = tempImage + j * srcWidth * 2;
302      for (i = 0; i < srcWidth; i += 4) {
303	 if (srcWidth > i + 3) numxpixels = 4;
304	 else numxpixels = srcWidth - i;
305
306	 extractsrc_s(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 2);
307	 signed_encode_rgtc_chan(blkaddr, srcpixels, numxpixels, numypixels);
308	 blkaddr += 8;
309
310	 extractsrc_s(srcpixels, srcaddr + 1, srcWidth, numxpixels, numypixels, 2);
311	 signed_encode_rgtc_chan(blkaddr, srcpixels, numxpixels, numypixels);
312	 blkaddr += 8;
313
314	 srcaddr += numxpixels * 2;
315
316      }
317      blkaddr += dstRowDiff;
318   }
319   if (tempImage)
320      free((void *) tempImage);
321
322   return GL_TRUE;
323}
324
325void
326_mesa_fetch_texel_2d_f_red_rgtc1(const struct gl_texture_image *texImage,
327				 GLint i, GLint j, GLint k, GLfloat *texel)
328{
329   GLubyte red;
330   unsigned_fetch_texel_rgtc(texImage->RowStride, (GLubyte *)(texImage->Data),
331		       i, j, &red, 1);
332   texel[RCOMP] = UBYTE_TO_FLOAT(red);
333   texel[GCOMP] = 0.0;
334   texel[BCOMP] = 0.0;
335   texel[ACOMP] = 1.0;
336}
337
338void
339_mesa_fetch_texel_2d_f_signed_red_rgtc1(const struct gl_texture_image *texImage,
340					GLint i, GLint j, GLint k, GLfloat *texel)
341{
342   GLbyte red;
343   signed_fetch_texel_rgtc(texImage->RowStride, (GLbyte *)(texImage->Data),
344		       i, j, &red, 1);
345   texel[RCOMP] = BYTE_TO_FLOAT_TEX(red);
346   texel[GCOMP] = 0.0;
347   texel[BCOMP] = 0.0;
348   texel[ACOMP] = 1.0;
349}
350
351void
352_mesa_fetch_texel_2d_f_rg_rgtc2(const struct gl_texture_image *texImage,
353				 GLint i, GLint j, GLint k, GLfloat *texel)
354{
355   GLubyte red, green;
356   unsigned_fetch_texel_rgtc(texImage->RowStride, (GLubyte *)(texImage->Data),
357		     i, j, &red, 2);
358   unsigned_fetch_texel_rgtc(texImage->RowStride, (GLubyte *)(texImage->Data) + 8,
359		     i, j, &green, 2);
360   texel[RCOMP] = UBYTE_TO_FLOAT(red);
361   texel[GCOMP] = UBYTE_TO_FLOAT(green);
362   texel[BCOMP] = 0.0;
363   texel[ACOMP] = 1.0;
364}
365
366void
367_mesa_fetch_texel_2d_f_signed_rg_rgtc2(const struct gl_texture_image *texImage,
368				       GLint i, GLint j, GLint k, GLfloat *texel)
369{
370   GLbyte red, green;
371   signed_fetch_texel_rgtc(texImage->RowStride, (GLbyte *)(texImage->Data),
372		     i, j, &red, 2);
373   signed_fetch_texel_rgtc(texImage->RowStride, (GLbyte *)(texImage->Data) + 8,
374		     i, j, &green, 2);
375   texel[RCOMP] = BYTE_TO_FLOAT_TEX(red);
376   texel[GCOMP] = BYTE_TO_FLOAT_TEX(green);
377   texel[BCOMP] = 0.0;
378   texel[ACOMP] = 1.0;
379}
380
381void
382_mesa_fetch_texel_2d_f_l_latc1(const struct gl_texture_image *texImage,
383                                 GLint i, GLint j, GLint k, GLfloat *texel)
384{
385   GLubyte red;
386   unsigned_fetch_texel_rgtc(texImage->RowStride, (GLubyte *)(texImage->Data),
387                       i, j, &red, 1);
388   texel[RCOMP] =
389   texel[GCOMP] =
390   texel[BCOMP] = UBYTE_TO_FLOAT(red);
391   texel[ACOMP] = 1.0;
392}
393
394void
395_mesa_fetch_texel_2d_f_signed_l_latc1(const struct gl_texture_image *texImage,
396                                        GLint i, GLint j, GLint k, GLfloat *texel)
397{
398   GLbyte red;
399   signed_fetch_texel_rgtc(texImage->RowStride, (GLbyte *)(texImage->Data),
400                       i, j, &red, 1);
401   texel[RCOMP] =
402   texel[GCOMP] =
403   texel[BCOMP] = BYTE_TO_FLOAT_TEX(red);
404   texel[ACOMP] = 1.0;
405}
406
407void
408_mesa_fetch_texel_2d_f_la_latc2(const struct gl_texture_image *texImage,
409                                 GLint i, GLint j, GLint k, GLfloat *texel)
410{
411   GLubyte red, green;
412   unsigned_fetch_texel_rgtc(texImage->RowStride, (GLubyte *)(texImage->Data),
413                     i, j, &red, 2);
414   unsigned_fetch_texel_rgtc(texImage->RowStride, (GLubyte *)(texImage->Data) + 8,
415                     i, j, &green, 2);
416   texel[RCOMP] =
417   texel[GCOMP] =
418   texel[BCOMP] = UBYTE_TO_FLOAT(red);
419   texel[ACOMP] = UBYTE_TO_FLOAT(green);
420}
421
422void
423_mesa_fetch_texel_2d_f_signed_la_latc2(const struct gl_texture_image *texImage,
424                                       GLint i, GLint j, GLint k, GLfloat *texel)
425{
426   GLbyte red, green;
427   signed_fetch_texel_rgtc(texImage->RowStride, (GLbyte *)(texImage->Data),
428                     i, j, &red, 2);
429   signed_fetch_texel_rgtc(texImage->RowStride, (GLbyte *)(texImage->Data) + 8,
430                     i, j, &green, 2);
431   texel[RCOMP] =
432   texel[GCOMP] =
433   texel[BCOMP] = BYTE_TO_FLOAT_TEX(red);
434   texel[ACOMP] = BYTE_TO_FLOAT_TEX(green);
435}
436
437#define TAG(x) unsigned_##x
438
439#define TYPE GLubyte
440#define T_MIN 0
441#define T_MAX 0xff
442
443#include "texcompress_rgtc_tmp.h"
444
445#undef TAG
446#undef TYPE
447#undef T_MIN
448#undef T_MAX
449
450#define TAG(x) signed_##x
451#define TYPE GLbyte
452#define T_MIN (GLbyte)-128
453#define T_MAX (GLbyte)127
454
455#include "texcompress_rgtc_tmp.h"
456
457#undef TAG
458#undef TYPE
459#undef T_MIN
460#undef T_MAX
461