1 /*
2 * Copyright (C) 2014 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24 /**
25 * \file texcompress_bptc.c
26 * GL_ARB_texture_compression_bptc support.
27 */
28
29 #include <stdbool.h>
30 #include "texcompress.h"
31 #include "texcompress_bptc.h"
32 #include "texcompress_bptc_tmp.h"
33 #include "texstore.h"
34 #include "image.h"
35 #include "mtypes.h"
36
37 static void
fetch_bptc_rgb_float(const GLubyte * map,GLint rowStride,GLint i,GLint j,GLfloat * texel,bool is_signed)38 fetch_bptc_rgb_float(const GLubyte *map,
39 GLint rowStride, GLint i, GLint j,
40 GLfloat *texel,
41 bool is_signed)
42 {
43 const GLubyte *block;
44
45 block = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 16;
46
47 fetch_rgb_float_from_block(block, texel, (i % 4) + (j % 4) * 4, is_signed);
48 }
49
50 static void
fetch_bptc_rgb_signed_float(const GLubyte * map,GLint rowStride,GLint i,GLint j,GLfloat * texel)51 fetch_bptc_rgb_signed_float(const GLubyte *map,
52 GLint rowStride, GLint i, GLint j,
53 GLfloat *texel)
54 {
55 fetch_bptc_rgb_float(map, rowStride, i, j, texel, true);
56 }
57
58 static void
fetch_bptc_rgb_unsigned_float(const GLubyte * map,GLint rowStride,GLint i,GLint j,GLfloat * texel)59 fetch_bptc_rgb_unsigned_float(const GLubyte *map,
60 GLint rowStride, GLint i, GLint j,
61 GLfloat *texel)
62 {
63 fetch_bptc_rgb_float(map, rowStride, i, j, texel, false);
64 }
65
66 static void
fetch_bptc_rgba_unorm_bytes(const GLubyte * map,GLint rowStride,GLint i,GLint j,GLubyte * texel)67 fetch_bptc_rgba_unorm_bytes(const GLubyte *map,
68 GLint rowStride, GLint i, GLint j,
69 GLubyte *texel)
70 {
71 const GLubyte *block;
72
73 block = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 16;
74
75 fetch_rgba_unorm_from_block(block, texel, (i % 4) + (j % 4) * 4);
76 }
77
78 static void
fetch_bptc_rgba_unorm(const GLubyte * map,GLint rowStride,GLint i,GLint j,GLfloat * texel)79 fetch_bptc_rgba_unorm(const GLubyte *map,
80 GLint rowStride, GLint i, GLint j,
81 GLfloat *texel)
82 {
83 GLubyte texel_bytes[4];
84
85 fetch_bptc_rgba_unorm_bytes(map, rowStride, i, j, texel_bytes);
86
87 texel[RCOMP] = UBYTE_TO_FLOAT(texel_bytes[0]);
88 texel[GCOMP] = UBYTE_TO_FLOAT(texel_bytes[1]);
89 texel[BCOMP] = UBYTE_TO_FLOAT(texel_bytes[2]);
90 texel[ACOMP] = UBYTE_TO_FLOAT(texel_bytes[3]);
91 }
92
93 static void
fetch_bptc_srgb_alpha_unorm(const GLubyte * map,GLint rowStride,GLint i,GLint j,GLfloat * texel)94 fetch_bptc_srgb_alpha_unorm(const GLubyte *map,
95 GLint rowStride, GLint i, GLint j,
96 GLfloat *texel)
97 {
98 GLubyte texel_bytes[4];
99
100 fetch_bptc_rgba_unorm_bytes(map, rowStride, i, j, texel_bytes);
101
102 texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(texel_bytes[0]);
103 texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(texel_bytes[1]);
104 texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(texel_bytes[2]);
105 texel[ACOMP] = UBYTE_TO_FLOAT(texel_bytes[3]);
106 }
107
108 compressed_fetch_func
_mesa_get_bptc_fetch_func(mesa_format format)109 _mesa_get_bptc_fetch_func(mesa_format format)
110 {
111 switch (format) {
112 case MESA_FORMAT_BPTC_RGBA_UNORM:
113 return fetch_bptc_rgba_unorm;
114 case MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM:
115 return fetch_bptc_srgb_alpha_unorm;
116 case MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT:
117 return fetch_bptc_rgb_signed_float;
118 case MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT:
119 return fetch_bptc_rgb_unsigned_float;
120 default:
121 return NULL;
122 }
123 }
124
125 GLboolean
_mesa_texstore_bptc_rgba_unorm(TEXSTORE_PARAMS)126 _mesa_texstore_bptc_rgba_unorm(TEXSTORE_PARAMS)
127 {
128 const GLubyte *pixels;
129 const GLubyte *tempImage = NULL;
130 int rowstride;
131
132 if (srcFormat != GL_RGBA ||
133 srcType != GL_UNSIGNED_BYTE ||
134 ctx->_ImageTransferState ||
135 srcPacking->SwapBytes) {
136 /* convert image to RGBA/ubyte */
137 GLubyte *tempImageSlices[1];
138 int rgbaRowStride = 4 * srcWidth * sizeof(GLubyte);
139 tempImage = malloc(srcWidth * srcHeight * 4 * sizeof(GLubyte));
140 if (!tempImage)
141 return GL_FALSE; /* out of memory */
142 tempImageSlices[0] = (GLubyte *) tempImage;
143 _mesa_texstore(ctx, dims,
144 baseInternalFormat,
145 #if UTIL_ARCH_LITTLE_ENDIAN
146 MESA_FORMAT_R8G8B8A8_UNORM,
147 #else
148 MESA_FORMAT_A8B8G8R8_UNORM,
149 #endif
150 rgbaRowStride, tempImageSlices,
151 srcWidth, srcHeight, srcDepth,
152 srcFormat, srcType, srcAddr,
153 srcPacking);
154
155 pixels = tempImage;
156 rowstride = srcWidth * 4;
157 } else {
158 pixels = _mesa_image_address2d(srcPacking, srcAddr, srcWidth, srcHeight,
159 srcFormat, srcType, 0, 0);
160 rowstride = _mesa_image_row_stride(srcPacking, srcWidth,
161 srcFormat, srcType);
162 }
163
164 compress_rgba_unorm(srcWidth, srcHeight,
165 pixels, rowstride,
166 dstSlices[0], dstRowStride);
167
168 free((void *) tempImage);
169
170 return GL_TRUE;
171 }
172
173 static GLboolean
texstore_bptc_rgb_float(TEXSTORE_PARAMS,bool is_signed)174 texstore_bptc_rgb_float(TEXSTORE_PARAMS,
175 bool is_signed)
176 {
177 const float *pixels;
178 const float *tempImage = NULL;
179 int rowstride;
180
181 if (srcFormat != GL_RGB ||
182 srcType != GL_FLOAT ||
183 ctx->_ImageTransferState ||
184 srcPacking->SwapBytes) {
185 /* convert image to RGB/float */
186 GLfloat *tempImageSlices[1];
187 int rgbRowStride = 3 * srcWidth * sizeof(GLfloat);
188 tempImage = malloc(srcWidth * srcHeight * 3 * sizeof(GLfloat));
189 if (!tempImage)
190 return GL_FALSE; /* out of memory */
191 tempImageSlices[0] = (GLfloat *) tempImage;
192 _mesa_texstore(ctx, dims,
193 baseInternalFormat,
194 MESA_FORMAT_RGB_FLOAT32,
195 rgbRowStride, (GLubyte **)tempImageSlices,
196 srcWidth, srcHeight, srcDepth,
197 srcFormat, srcType, srcAddr,
198 srcPacking);
199
200 pixels = tempImage;
201 rowstride = srcWidth * sizeof(float) * 3;
202 } else {
203 pixels = _mesa_image_address2d(srcPacking, srcAddr, srcWidth, srcHeight,
204 srcFormat, srcType, 0, 0);
205 rowstride = _mesa_image_row_stride(srcPacking, srcWidth,
206 srcFormat, srcType);
207 }
208
209 compress_rgb_float(srcWidth, srcHeight,
210 pixels, rowstride,
211 dstSlices[0], dstRowStride,
212 is_signed);
213
214 free((void *) tempImage);
215
216 return GL_TRUE;
217 }
218
219 GLboolean
_mesa_texstore_bptc_rgb_signed_float(TEXSTORE_PARAMS)220 _mesa_texstore_bptc_rgb_signed_float(TEXSTORE_PARAMS)
221 {
222 assert(dstFormat == MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT);
223
224 return texstore_bptc_rgb_float(ctx, dims, baseInternalFormat,
225 dstFormat, dstRowStride, dstSlices,
226 srcWidth, srcHeight, srcDepth,
227 srcFormat, srcType,
228 srcAddr, srcPacking,
229 true /* signed */);
230 }
231
232 GLboolean
_mesa_texstore_bptc_rgb_unsigned_float(TEXSTORE_PARAMS)233 _mesa_texstore_bptc_rgb_unsigned_float(TEXSTORE_PARAMS)
234 {
235 assert(dstFormat == MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT);
236
237 return texstore_bptc_rgb_float(ctx, dims, baseInternalFormat,
238 dstFormat, dstRowStride, dstSlices,
239 srcWidth, srcHeight, srcDepth,
240 srcFormat, srcType,
241 srcAddr, srcPacking,
242 false /* unsigned */);
243 }
244