texcompress_rgtc.c revision af69d88d
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 "mipmap.h"
42#include "texcompress.h"
43#include "texcompress_rgtc.h"
44#include "texstore.h"
45
46
47#define RGTC_DEBUG 0
48
49static void unsigned_encode_rgtc_ubyte(GLubyte *blkaddr, GLubyte srccolors[4][4],
50					GLint numxpixels, GLint numypixels);
51static void signed_encode_rgtc_ubyte(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 GLubyte *srcaddr,
61			  GLint srcRowStride, GLint numxpixels, GLint numypixels, GLint comps)
62{
63   GLubyte i, j;
64   const GLubyte *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;
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 GLubyte *tempImage = NULL;
94   int i, j;
95   int numxpixels, numypixels;
96   const GLubyte *srcaddr;
97   GLubyte srcpixels[4][4];
98   GLubyte *blkaddr;
99   GLint dstRowDiff;
100   ASSERT(dstFormat == MESA_FORMAT_R_RGTC1_UNORM ||
101          dstFormat == MESA_FORMAT_L_LATC1_UNORM);
102
103   tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
104					  baseInternalFormat,
105					  _mesa_get_format_base_format(dstFormat),
106					  srcWidth, srcHeight, srcDepth,
107					  srcFormat, srcType, srcAddr,
108					  srcPacking);
109   if (!tempImage)
110      return GL_FALSE; /* out of memory */
111
112   dst = dstSlices[0];
113
114   blkaddr = dst;
115   dstRowDiff = dstRowStride >= (srcWidth * 2) ? dstRowStride - (((srcWidth + 3) & ~3) * 2) : 0;
116   for (j = 0; j < srcHeight; j+=4) {
117      if (srcHeight > j + 3) numypixels = 4;
118      else numypixels = srcHeight - j;
119      srcaddr = tempImage + j * srcWidth;
120      for (i = 0; i < srcWidth; i += 4) {
121	 if (srcWidth > i + 3) numxpixels = 4;
122	 else numxpixels = srcWidth - i;
123	 extractsrc_u(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 1);
124	 unsigned_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);
125	 srcaddr += numxpixels;
126	 blkaddr += 8;
127      }
128      blkaddr += dstRowDiff;
129   }
130
131   free((void *) tempImage);
132
133   return GL_TRUE;
134}
135
136GLboolean
137_mesa_texstore_signed_red_rgtc1(TEXSTORE_PARAMS)
138{
139   GLbyte *dst;
140   const GLfloat *tempImage = NULL;
141   int i, j;
142   int numxpixels, numypixels;
143   const GLfloat *srcaddr;
144   GLbyte srcpixels[4][4];
145   GLbyte *blkaddr;
146   GLint dstRowDiff;
147   ASSERT(dstFormat == MESA_FORMAT_R_RGTC1_SNORM ||
148          dstFormat == MESA_FORMAT_L_LATC1_SNORM);
149
150   tempImage = _mesa_make_temp_float_image(ctx, dims,
151					   baseInternalFormat,
152					   _mesa_get_format_base_format(dstFormat),
153					   srcWidth, srcHeight, srcDepth,
154					   srcFormat, srcType, srcAddr,
155					   srcPacking, 0x0);
156   if (!tempImage)
157      return GL_FALSE; /* out of memory */
158
159   dst = (GLbyte *) dstSlices[0];
160
161   blkaddr = dst;
162   dstRowDiff = dstRowStride >= (srcWidth * 2) ? dstRowStride - (((srcWidth + 3) & ~3) * 2) : 0;
163   for (j = 0; j < srcHeight; j+=4) {
164      if (srcHeight > j + 3) numypixels = 4;
165      else numypixels = srcHeight - j;
166      srcaddr = tempImage + j * srcWidth;
167      for (i = 0; i < srcWidth; i += 4) {
168	 if (srcWidth > i + 3) numxpixels = 4;
169	 else numxpixels = srcWidth - i;
170	 extractsrc_s(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 1);
171	 signed_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);
172	 srcaddr += numxpixels;
173	 blkaddr += 8;
174      }
175      blkaddr += dstRowDiff;
176   }
177
178   free((void *) tempImage);
179
180   return GL_TRUE;
181}
182
183GLboolean
184_mesa_texstore_rg_rgtc2(TEXSTORE_PARAMS)
185{
186   GLubyte *dst;
187   const GLubyte *tempImage = NULL;
188   int i, j;
189   int numxpixels, numypixels;
190   const GLubyte *srcaddr;
191   GLubyte srcpixels[4][4];
192   GLubyte *blkaddr;
193   GLint dstRowDiff;
194
195   ASSERT(dstFormat == MESA_FORMAT_RG_RGTC2_UNORM ||
196          dstFormat == MESA_FORMAT_LA_LATC2_UNORM);
197
198   tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
199					  baseInternalFormat,
200					  _mesa_get_format_base_format(dstFormat),
201					  srcWidth, srcHeight, srcDepth,
202					  srcFormat, srcType, srcAddr,
203					  srcPacking);
204   if (!tempImage)
205      return GL_FALSE; /* out of memory */
206
207   dst = dstSlices[0];
208
209   blkaddr = dst;
210   dstRowDiff = dstRowStride >= (srcWidth * 4) ? dstRowStride - (((srcWidth + 3) & ~3) * 4) : 0;
211   for (j = 0; j < srcHeight; j+=4) {
212      if (srcHeight > j + 3) numypixels = 4;
213      else numypixels = srcHeight - j;
214      srcaddr = tempImage + j * srcWidth * 2;
215      for (i = 0; i < srcWidth; i += 4) {
216	 if (srcWidth > i + 3) numxpixels = 4;
217	 else numxpixels = srcWidth - i;
218	 extractsrc_u(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 2);
219	 unsigned_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);
220
221	 blkaddr += 8;
222	 extractsrc_u(srcpixels, (GLubyte *)srcaddr + 1, srcWidth, numxpixels, numypixels, 2);
223	 unsigned_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);
224
225	 blkaddr += 8;
226
227	 srcaddr += numxpixels * 2;
228      }
229      blkaddr += dstRowDiff;
230   }
231
232   free((void *) tempImage);
233
234   return GL_TRUE;
235}
236
237GLboolean
238_mesa_texstore_signed_rg_rgtc2(TEXSTORE_PARAMS)
239{
240   GLbyte *dst;
241   const GLfloat *tempImage = NULL;
242   int i, j;
243   int numxpixels, numypixels;
244   const GLfloat *srcaddr;
245   GLbyte srcpixels[4][4];
246   GLbyte *blkaddr;
247   GLint dstRowDiff;
248
249   ASSERT(dstFormat == MESA_FORMAT_RG_RGTC2_SNORM ||
250          dstFormat == MESA_FORMAT_LA_LATC2_SNORM);
251
252   tempImage = _mesa_make_temp_float_image(ctx, dims,
253					   baseInternalFormat,
254					   _mesa_get_format_base_format(dstFormat),
255					   srcWidth, srcHeight, srcDepth,
256					   srcFormat, srcType, srcAddr,
257					   srcPacking, 0x0);
258   if (!tempImage)
259      return GL_FALSE; /* out of memory */
260
261   dst = (GLbyte *) dstSlices[0];
262
263   blkaddr = dst;
264   dstRowDiff = dstRowStride >= (srcWidth * 4) ? dstRowStride - (((srcWidth + 3) & ~3) * 4) : 0;
265   for (j = 0; j < srcHeight; j += 4) {
266      if (srcHeight > j + 3) numypixels = 4;
267      else numypixels = srcHeight - j;
268      srcaddr = tempImage + j * srcWidth * 2;
269      for (i = 0; i < srcWidth; i += 4) {
270	 if (srcWidth > i + 3) numxpixels = 4;
271	 else numxpixels = srcWidth - i;
272
273	 extractsrc_s(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 2);
274	 signed_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);
275	 blkaddr += 8;
276
277	 extractsrc_s(srcpixels, srcaddr + 1, srcWidth, numxpixels, numypixels, 2);
278	 signed_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);
279	 blkaddr += 8;
280
281	 srcaddr += numxpixels * 2;
282
283      }
284      blkaddr += dstRowDiff;
285   }
286
287   free((void *) tempImage);
288
289   return GL_TRUE;
290}
291
292
293#define TAG(x) unsigned_##x
294
295#define TYPE GLubyte
296#define T_MIN 0
297#define T_MAX 0xff
298
299#include "texcompress_rgtc_tmp.h"
300
301#undef TAG
302#undef TYPE
303#undef T_MIN
304#undef T_MAX
305
306#define TAG(x) signed_##x
307#define TYPE GLbyte
308#define T_MIN (GLbyte)-128
309#define T_MAX (GLbyte)127
310
311#include "texcompress_rgtc_tmp.h"
312
313#undef TAG
314#undef TYPE
315#undef T_MIN
316#undef T_MAX
317
318
319
320static void
321fetch_red_rgtc1(const GLubyte *map,
322                GLint rowStride, GLint i, GLint j, GLfloat *texel)
323{
324   GLubyte red;
325   unsigned_fetch_texel_rgtc(rowStride, map, i, j, &red, 1);
326   texel[RCOMP] = UBYTE_TO_FLOAT(red);
327   texel[GCOMP] = 0.0;
328   texel[BCOMP] = 0.0;
329   texel[ACOMP] = 1.0;
330}
331
332static void
333fetch_l_latc1(const GLubyte *map,
334              GLint rowStride, GLint i, GLint j, GLfloat *texel)
335{
336   GLubyte red;
337   unsigned_fetch_texel_rgtc(rowStride, map, i, j, &red, 1);
338   texel[RCOMP] =
339   texel[GCOMP] =
340   texel[BCOMP] = UBYTE_TO_FLOAT(red);
341   texel[ACOMP] = 1.0;
342}
343
344static void
345fetch_signed_red_rgtc1(const GLubyte *map,
346                       GLint rowStride, GLint i, GLint j, GLfloat *texel)
347{
348   GLbyte red;
349   signed_fetch_texel_rgtc(rowStride, (const GLbyte *) map,
350                           i, j, &red, 1);
351   texel[RCOMP] = BYTE_TO_FLOAT_TEX(red);
352   texel[GCOMP] = 0.0;
353   texel[BCOMP] = 0.0;
354   texel[ACOMP] = 1.0;
355}
356
357static void
358fetch_signed_l_latc1(const GLubyte *map,
359                     GLint rowStride, GLint i, GLint j, GLfloat *texel)
360{
361   GLbyte red;
362   signed_fetch_texel_rgtc(rowStride, (GLbyte *) map,
363                           i, j, &red, 1);
364   texel[RCOMP] =
365   texel[GCOMP] =
366   texel[BCOMP] = BYTE_TO_FLOAT(red);
367   texel[ACOMP] = 1.0;
368}
369
370static void
371fetch_rg_rgtc2(const GLubyte *map,
372               GLint rowStride, GLint i, GLint j, GLfloat *texel)
373{
374   GLubyte red, green;
375   unsigned_fetch_texel_rgtc(rowStride,
376                             map,
377                             i, j, &red, 2);
378   unsigned_fetch_texel_rgtc(rowStride,
379                             map + 8,
380                             i, j, &green, 2);
381   texel[RCOMP] = UBYTE_TO_FLOAT(red);
382   texel[GCOMP] = UBYTE_TO_FLOAT(green);
383   texel[BCOMP] = 0.0;
384   texel[ACOMP] = 1.0;
385}
386
387static void
388fetch_la_latc2(const GLubyte *map,
389               GLint rowStride, GLint i, GLint j, GLfloat *texel)
390{
391   GLubyte red, green;
392   unsigned_fetch_texel_rgtc(rowStride,
393                             map,
394                             i, j, &red, 2);
395   unsigned_fetch_texel_rgtc(rowStride,
396                             map + 8,
397                             i, j, &green, 2);
398   texel[RCOMP] =
399   texel[GCOMP] =
400   texel[BCOMP] = UBYTE_TO_FLOAT(red);
401   texel[ACOMP] = UBYTE_TO_FLOAT(green);
402}
403
404
405static void
406fetch_signed_rg_rgtc2(const GLubyte *map,
407                      GLint rowStride, GLint i, GLint j, GLfloat *texel)
408{
409   GLbyte red, green;
410   signed_fetch_texel_rgtc(rowStride,
411                           (GLbyte *) map,
412                           i, j, &red, 2);
413   signed_fetch_texel_rgtc(rowStride,
414                           (GLbyte *) map + 8,
415                           i, j, &green, 2);
416   texel[RCOMP] = BYTE_TO_FLOAT_TEX(red);
417   texel[GCOMP] = BYTE_TO_FLOAT_TEX(green);
418   texel[BCOMP] = 0.0;
419   texel[ACOMP] = 1.0;
420}
421
422
423static void
424fetch_signed_la_latc2(const GLubyte *map,
425                      GLint rowStride, GLint i, GLint j, GLfloat *texel)
426{
427   GLbyte red, green;
428   signed_fetch_texel_rgtc(rowStride,
429                           (GLbyte *) map,
430                           i, j, &red, 2);
431   signed_fetch_texel_rgtc(rowStride,
432                           (GLbyte *) map + 8,
433                           i, j, &green, 2);
434   texel[RCOMP] =
435   texel[GCOMP] =
436   texel[BCOMP] = BYTE_TO_FLOAT_TEX(red);
437   texel[ACOMP] = BYTE_TO_FLOAT_TEX(green);
438}
439
440
441compressed_fetch_func
442_mesa_get_compressed_rgtc_func(mesa_format format)
443{
444   switch (format) {
445   case MESA_FORMAT_R_RGTC1_UNORM:
446      return fetch_red_rgtc1;
447   case MESA_FORMAT_L_LATC1_UNORM:
448      return fetch_l_latc1;
449   case MESA_FORMAT_R_RGTC1_SNORM:
450      return fetch_signed_red_rgtc1;
451   case MESA_FORMAT_L_LATC1_SNORM:
452      return fetch_signed_l_latc1;
453   case MESA_FORMAT_RG_RGTC2_UNORM:
454      return fetch_rg_rgtc2;
455   case MESA_FORMAT_LA_LATC2_UNORM:
456      return fetch_la_latc2;
457   case MESA_FORMAT_RG_RGTC2_SNORM:
458      return fetch_signed_rg_rgtc2;
459   case MESA_FORMAT_LA_LATC2_SNORM:
460      return fetch_signed_la_latc2;
461   default:
462      return NULL;
463   }
464}
465