xref: /aosp_15_r20/external/mesa3d/src/mesa/main/texcompress_rgtc.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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 #include <stdlib.h>
36 
37 #include "config.h"
38 #include "util/glheader.h"
39 
40 #include "image.h"
41 #include "macros.h"
42 #include "mipmap.h"
43 #include "texcompress.h"
44 #include "util/rgtc.h"
45 #include "util/format/u_format_rgtc.h"
46 #include "texcompress_rgtc.h"
47 #include "texstore.h"
48 
extractsrc_u(GLubyte srcpixels[4][4],const GLubyte * srcaddr,GLint srcRowStride,GLint numxpixels,GLint numypixels,GLint comps)49 static void extractsrc_u( GLubyte srcpixels[4][4], const GLubyte *srcaddr,
50 			  GLint srcRowStride, GLint numxpixels, GLint numypixels, GLint comps)
51 {
52    GLubyte i, j;
53    const GLubyte *curaddr;
54    for (j = 0; j < numypixels; j++) {
55       curaddr = srcaddr + j * srcRowStride * comps;
56       for (i = 0; i < numxpixels; i++) {
57          srcpixels[j][i] = *curaddr;
58          curaddr += comps;
59       }
60    }
61 }
62 
extractsrc_s(GLbyte srcpixels[4][4],const GLbyte * srcaddr,GLint srcRowStride,GLint numxpixels,GLint numypixels,GLint comps)63 static void extractsrc_s( GLbyte srcpixels[4][4], const GLbyte *srcaddr,
64 			  GLint srcRowStride, GLint numxpixels, GLint numypixels, GLint comps)
65 {
66    GLubyte i, j;
67    const GLbyte *curaddr;
68    for (j = 0; j < numypixels; j++) {
69       curaddr = srcaddr + j * srcRowStride * comps;
70       for (i = 0; i < numxpixels; i++) {
71          srcpixels[j][i] = *curaddr;
72          curaddr += comps;
73       }
74    }
75 }
76 
77 
78 GLboolean
_mesa_texstore_red_rgtc1(TEXSTORE_PARAMS)79 _mesa_texstore_red_rgtc1(TEXSTORE_PARAMS)
80 {
81    GLubyte *dst;
82    const GLubyte *tempImage = NULL;
83    int i, j;
84    int numxpixels, numypixels;
85    const GLubyte *srcaddr;
86    GLubyte srcpixels[4][4];
87    GLubyte *blkaddr;
88    GLint dstRowDiff, redRowStride;
89    GLubyte *tempImageSlices[1];
90 
91    assert(dstFormat == MESA_FORMAT_R_RGTC1_UNORM ||
92           dstFormat == MESA_FORMAT_L_LATC1_UNORM);
93 
94    tempImage = malloc(srcWidth * srcHeight * 1 * sizeof(GLubyte));
95    if (!tempImage)
96       return GL_FALSE; /* out of memory */
97    redRowStride = 1 * srcWidth * sizeof(GLubyte);
98    tempImageSlices[0] = (GLubyte *) tempImage;
99    _mesa_texstore(ctx, dims,
100                   baseInternalFormat,
101                   MESA_FORMAT_R_UNORM8,
102                   redRowStride, tempImageSlices,
103                   srcWidth, srcHeight, srcDepth,
104                   srcFormat, srcType, srcAddr,
105                   srcPacking);
106 
107    dst = dstSlices[0];
108 
109    blkaddr = dst;
110    dstRowDiff = dstRowStride >= (srcWidth * 2) ? dstRowStride - (((srcWidth + 3) & ~3) * 2) : 0;
111    for (j = 0; j < srcHeight; j+=4) {
112       if (srcHeight > j + 3) numypixels = 4;
113       else numypixels = srcHeight - j;
114       srcaddr = tempImage + j * srcWidth;
115       for (i = 0; i < srcWidth; i += 4) {
116          if (srcWidth > i + 3) numxpixels = 4;
117          else numxpixels = srcWidth - i;
118          extractsrc_u(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 1);
119          util_format_unsigned_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);
120          srcaddr += numxpixels;
121          blkaddr += 8;
122       }
123       blkaddr += dstRowDiff;
124    }
125 
126    free((void *) tempImage);
127 
128    return GL_TRUE;
129 }
130 
131 GLboolean
_mesa_texstore_signed_red_rgtc1(TEXSTORE_PARAMS)132 _mesa_texstore_signed_red_rgtc1(TEXSTORE_PARAMS)
133 {
134    GLbyte *dst;
135    const GLbyte *tempImage = NULL;
136    int i, j;
137    int numxpixels, numypixels;
138    const GLbyte *srcaddr;
139    GLbyte srcpixels[4][4];
140    GLbyte *blkaddr;
141    GLint dstRowDiff, redRowStride;
142    GLbyte *tempImageSlices[1];
143 
144    assert(dstFormat == MESA_FORMAT_R_RGTC1_SNORM ||
145           dstFormat == MESA_FORMAT_L_LATC1_SNORM);
146 
147    redRowStride = 1 * srcWidth * sizeof(GLbyte);
148    tempImage = malloc(srcWidth * srcHeight * 1 * sizeof(GLbyte));
149    if (!tempImage)
150       return GL_FALSE; /* out of memory */
151    tempImageSlices[0] = (GLbyte *) tempImage;
152    _mesa_texstore(ctx, dims,
153                   baseInternalFormat,
154                   MESA_FORMAT_R_SNORM8,
155                   redRowStride, (GLubyte **)tempImageSlices,
156                   srcWidth, srcHeight, srcDepth,
157                   srcFormat, srcType, srcAddr,
158                   srcPacking);
159 
160    dst = (GLbyte *) dstSlices[0];
161 
162    blkaddr = dst;
163    dstRowDiff = dstRowStride >= (srcWidth * 2) ? dstRowStride - (((srcWidth + 3) & ~3) * 2) : 0;
164    for (j = 0; j < srcHeight; j+=4) {
165       if (srcHeight > j + 3) numypixels = 4;
166       else numypixels = srcHeight - j;
167       srcaddr = tempImage + j * srcWidth;
168       for (i = 0; i < srcWidth; i += 4) {
169          if (srcWidth > i + 3) numxpixels = 4;
170          else numxpixels = srcWidth - i;
171          extractsrc_s(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 1);
172          util_format_signed_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);
173          srcaddr += numxpixels;
174          blkaddr += 8;
175       }
176       blkaddr += dstRowDiff;
177    }
178 
179    free((void *) tempImage);
180 
181    return GL_TRUE;
182 }
183 
184 GLboolean
_mesa_texstore_rg_rgtc2(TEXSTORE_PARAMS)185 _mesa_texstore_rg_rgtc2(TEXSTORE_PARAMS)
186 {
187    GLubyte *dst;
188    const GLubyte *tempImage = NULL;
189    int i, j;
190    int numxpixels, numypixels;
191    const GLubyte *srcaddr;
192    GLubyte srcpixels[4][4];
193    GLubyte *blkaddr;
194    GLint dstRowDiff, rgRowStride;
195    mesa_format tempFormat;
196    GLubyte *tempImageSlices[1];
197 
198    assert(dstFormat == MESA_FORMAT_RG_RGTC2_UNORM ||
199           dstFormat == MESA_FORMAT_LA_LATC2_UNORM);
200 
201    if (baseInternalFormat == GL_RG)
202       tempFormat = MESA_FORMAT_RG_UNORM8;
203    else
204       tempFormat = MESA_FORMAT_LA_UNORM8;
205 
206    rgRowStride = 2 * srcWidth * sizeof(GLubyte);
207    tempImage = malloc(srcWidth * srcHeight * 2 * sizeof(GLubyte));
208    if (!tempImage)
209       return GL_FALSE; /* out of memory */
210    tempImageSlices[0] = (GLubyte *) tempImage;
211    _mesa_texstore(ctx, dims,
212                   baseInternalFormat,
213                   tempFormat,
214                   rgRowStride, tempImageSlices,
215                   srcWidth, srcHeight, srcDepth,
216                   srcFormat, srcType, srcAddr,
217                   srcPacking);
218 
219    dst = dstSlices[0];
220 
221    blkaddr = dst;
222    dstRowDiff = dstRowStride >= (srcWidth * 4) ? dstRowStride - (((srcWidth + 3) & ~3) * 4) : 0;
223    for (j = 0; j < srcHeight; j+=4) {
224       if (srcHeight > j + 3) numypixels = 4;
225       else numypixels = srcHeight - j;
226       srcaddr = tempImage + j * srcWidth * 2;
227       for (i = 0; i < srcWidth; i += 4) {
228          if (srcWidth > i + 3) numxpixels = 4;
229          else numxpixels = srcWidth - i;
230          extractsrc_u(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 2);
231          util_format_unsigned_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);
232 
233          blkaddr += 8;
234          extractsrc_u(srcpixels, (GLubyte *)srcaddr + 1, srcWidth, numxpixels, numypixels, 2);
235          util_format_unsigned_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);
236 
237          blkaddr += 8;
238 
239          srcaddr += numxpixels * 2;
240       }
241       blkaddr += dstRowDiff;
242    }
243 
244    free((void *) tempImage);
245 
246    return GL_TRUE;
247 }
248 
249 GLboolean
_mesa_texstore_signed_rg_rgtc2(TEXSTORE_PARAMS)250 _mesa_texstore_signed_rg_rgtc2(TEXSTORE_PARAMS)
251 {
252    GLbyte *dst;
253    const GLbyte *tempImage = NULL;
254    int i, j;
255    int numxpixels, numypixels;
256    const GLbyte *srcaddr;
257    GLbyte srcpixels[4][4];
258    GLbyte *blkaddr;
259    GLint dstRowDiff, rgRowStride;
260    mesa_format tempFormat;
261    GLbyte *tempImageSlices[1];
262 
263    assert(dstFormat == MESA_FORMAT_RG_RGTC2_SNORM ||
264           dstFormat == MESA_FORMAT_LA_LATC2_SNORM);
265 
266    if (baseInternalFormat == GL_RG)
267       tempFormat = MESA_FORMAT_RG_SNORM8;
268    else
269       tempFormat = MESA_FORMAT_LA_SNORM8;
270 
271    rgRowStride = 2 * srcWidth * sizeof(GLbyte);
272    tempImage = malloc(srcWidth * srcHeight * 2 * sizeof(GLbyte));
273    if (!tempImage)
274       return GL_FALSE; /* out of memory */
275    tempImageSlices[0] = (GLbyte *) tempImage;
276    _mesa_texstore(ctx, dims,
277                   baseInternalFormat,
278                   tempFormat,
279                   rgRowStride, (GLubyte **)tempImageSlices,
280                   srcWidth, srcHeight, srcDepth,
281                   srcFormat, srcType, srcAddr,
282                   srcPacking);
283 
284    dst = (GLbyte *) dstSlices[0];
285 
286    blkaddr = dst;
287    dstRowDiff = dstRowStride >= (srcWidth * 4) ? dstRowStride - (((srcWidth + 3) & ~3) * 4) : 0;
288    for (j = 0; j < srcHeight; j += 4) {
289       if (srcHeight > j + 3) numypixels = 4;
290       else numypixels = srcHeight - j;
291       srcaddr = tempImage + j * srcWidth * 2;
292       for (i = 0; i < srcWidth; i += 4) {
293          if (srcWidth > i + 3) numxpixels = 4;
294          else numxpixels = srcWidth - i;
295 
296          extractsrc_s(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 2);
297          util_format_signed_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);
298          blkaddr += 8;
299 
300          extractsrc_s(srcpixels, srcaddr + 1, srcWidth, numxpixels, numypixels, 2);
301          util_format_signed_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);
302          blkaddr += 8;
303 
304          srcaddr += numxpixels * 2;
305       }
306       blkaddr += dstRowDiff;
307    }
308 
309    free((void *) tempImage);
310 
311    return GL_TRUE;
312 }
313 
314 static void
fetch_red_rgtc1(const GLubyte * map,GLint rowStride,GLint i,GLint j,GLfloat * texel)315 fetch_red_rgtc1(const GLubyte *map,
316                 GLint rowStride, GLint i, GLint j, GLfloat *texel)
317 {
318    GLubyte red;
319    util_format_unsigned_fetch_texel_rgtc(rowStride, map, i, j, &red, 1);
320    texel[RCOMP] = UBYTE_TO_FLOAT(red);
321    texel[GCOMP] = 0.0;
322    texel[BCOMP] = 0.0;
323    texel[ACOMP] = 1.0;
324 }
325 
326 static void
fetch_l_latc1(const GLubyte * map,GLint rowStride,GLint i,GLint j,GLfloat * texel)327 fetch_l_latc1(const GLubyte *map,
328               GLint rowStride, GLint i, GLint j, GLfloat *texel)
329 {
330    GLubyte red;
331    util_format_unsigned_fetch_texel_rgtc(rowStride, map, i, j, &red, 1);
332    texel[RCOMP] =
333    texel[GCOMP] =
334    texel[BCOMP] = UBYTE_TO_FLOAT(red);
335    texel[ACOMP] = 1.0;
336 }
337 
338 static void
fetch_signed_red_rgtc1(const GLubyte * map,GLint rowStride,GLint i,GLint j,GLfloat * texel)339 fetch_signed_red_rgtc1(const GLubyte *map,
340                        GLint rowStride, GLint i, GLint j, GLfloat *texel)
341 {
342    GLbyte red;
343    util_format_signed_fetch_texel_rgtc(rowStride, (const GLbyte *) map,
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 
351 static void
fetch_signed_l_latc1(const GLubyte * map,GLint rowStride,GLint i,GLint j,GLfloat * texel)352 fetch_signed_l_latc1(const GLubyte *map,
353                      GLint rowStride, GLint i, GLint j, GLfloat *texel)
354 {
355    GLbyte red;
356    util_format_signed_fetch_texel_rgtc(rowStride, (GLbyte *) map,
357                            i, j, &red, 1);
358    texel[RCOMP] =
359    texel[GCOMP] =
360    texel[BCOMP] = BYTE_TO_FLOAT(red);
361    texel[ACOMP] = 1.0;
362 }
363 
364 static void
fetch_rg_rgtc2(const GLubyte * map,GLint rowStride,GLint i,GLint j,GLfloat * texel)365 fetch_rg_rgtc2(const GLubyte *map,
366                GLint rowStride, GLint i, GLint j, GLfloat *texel)
367 {
368    GLubyte red, green;
369    util_format_unsigned_fetch_texel_rgtc(rowStride,
370                              map,
371                              i, j, &red, 2);
372    util_format_unsigned_fetch_texel_rgtc(rowStride,
373                              map + 8,
374                              i, j, &green, 2);
375    texel[RCOMP] = UBYTE_TO_FLOAT(red);
376    texel[GCOMP] = UBYTE_TO_FLOAT(green);
377    texel[BCOMP] = 0.0;
378    texel[ACOMP] = 1.0;
379 }
380 
381 static void
fetch_la_latc2(const GLubyte * map,GLint rowStride,GLint i,GLint j,GLfloat * texel)382 fetch_la_latc2(const GLubyte *map,
383                GLint rowStride, GLint i, GLint j, GLfloat *texel)
384 {
385    GLubyte red, green;
386    util_format_unsigned_fetch_texel_rgtc(rowStride,
387                              map,
388                              i, j, &red, 2);
389    util_format_unsigned_fetch_texel_rgtc(rowStride,
390                              map + 8,
391                              i, j, &green, 2);
392    texel[RCOMP] =
393    texel[GCOMP] =
394    texel[BCOMP] = UBYTE_TO_FLOAT(red);
395    texel[ACOMP] = UBYTE_TO_FLOAT(green);
396 }
397 
398 
399 static void
fetch_signed_rg_rgtc2(const GLubyte * map,GLint rowStride,GLint i,GLint j,GLfloat * texel)400 fetch_signed_rg_rgtc2(const GLubyte *map,
401                       GLint rowStride, GLint i, GLint j, GLfloat *texel)
402 {
403    GLbyte red, green;
404    util_format_signed_fetch_texel_rgtc(rowStride,
405                            (GLbyte *) map,
406                            i, j, &red, 2);
407    util_format_signed_fetch_texel_rgtc(rowStride,
408                            (GLbyte *) map + 8,
409                            i, j, &green, 2);
410    texel[RCOMP] = BYTE_TO_FLOAT_TEX(red);
411    texel[GCOMP] = BYTE_TO_FLOAT_TEX(green);
412    texel[BCOMP] = 0.0;
413    texel[ACOMP] = 1.0;
414 }
415 
416 
417 static void
fetch_signed_la_latc2(const GLubyte * map,GLint rowStride,GLint i,GLint j,GLfloat * texel)418 fetch_signed_la_latc2(const GLubyte *map,
419                       GLint rowStride, GLint i, GLint j, GLfloat *texel)
420 {
421    GLbyte red, green;
422    util_format_signed_fetch_texel_rgtc(rowStride,
423                            (GLbyte *) map,
424                            i, j, &red, 2);
425    util_format_signed_fetch_texel_rgtc(rowStride,
426                            (GLbyte *) map + 8,
427                            i, j, &green, 2);
428    texel[RCOMP] =
429    texel[GCOMP] =
430    texel[BCOMP] = BYTE_TO_FLOAT_TEX(red);
431    texel[ACOMP] = BYTE_TO_FLOAT_TEX(green);
432 }
433 
434 
435 compressed_fetch_func
_mesa_get_compressed_rgtc_func(mesa_format format)436 _mesa_get_compressed_rgtc_func(mesa_format format)
437 {
438    switch (format) {
439    case MESA_FORMAT_R_RGTC1_UNORM:
440       return fetch_red_rgtc1;
441    case MESA_FORMAT_L_LATC1_UNORM:
442       return fetch_l_latc1;
443    case MESA_FORMAT_R_RGTC1_SNORM:
444       return fetch_signed_red_rgtc1;
445    case MESA_FORMAT_L_LATC1_SNORM:
446       return fetch_signed_l_latc1;
447    case MESA_FORMAT_RG_RGTC2_UNORM:
448       return fetch_rg_rgtc2;
449    case MESA_FORMAT_LA_LATC2_UNORM:
450       return fetch_la_latc2;
451    case MESA_FORMAT_RG_RGTC2_SNORM:
452       return fetch_signed_rg_rgtc2;
453    case MESA_FORMAT_LA_LATC2_SNORM:
454       return fetch_signed_la_latc2;
455    default:
456       return NULL;
457    }
458 }
459 
460 void
_mesa_unpack_rgtc(uint8_t * dst_row,unsigned dst_stride,const uint8_t * src_row,unsigned src_stride,unsigned src_width,unsigned src_height,mesa_format format)461 _mesa_unpack_rgtc(uint8_t *dst_row,
462                   unsigned dst_stride,
463                   const uint8_t *src_row,
464                   unsigned src_stride,
465                   unsigned src_width,
466                   unsigned src_height,
467                   mesa_format format)
468 {
469    switch (format) {
470    case MESA_FORMAT_R_RGTC1_UNORM:
471    case MESA_FORMAT_L_LATC1_UNORM:
472       util_format_rgtc1_unorm_unpack_r_8unorm(dst_row, dst_stride,
473                                               src_row, src_stride,
474                                               src_width, src_height);
475       break;
476 
477    case MESA_FORMAT_R_RGTC1_SNORM:
478    case MESA_FORMAT_L_LATC1_SNORM:
479       util_format_rgtc1_snorm_unpack_r_8snorm((int8_t *)dst_row, dst_stride,
480                                               src_row, src_stride,
481                                               src_width, src_height);
482       break;
483 
484    case MESA_FORMAT_RG_RGTC2_UNORM:
485    case MESA_FORMAT_LA_LATC2_UNORM:
486       util_format_rgtc2_unorm_unpack_rg_8unorm(dst_row, dst_stride,
487                                                src_row, src_stride,
488                                                src_width, src_height);
489       break;
490 
491    case MESA_FORMAT_RG_RGTC2_SNORM:
492    case MESA_FORMAT_LA_LATC2_SNORM:
493       util_format_rgtc2_snorm_unpack_rg_8snorm((int8_t *)dst_row, dst_stride,
494                                                src_row, src_stride,
495                                                src_width, src_height);
496       break;
497 
498    default:
499       unreachable("unexpected format");
500    }
501 }
502