util: implement R9G9B9E5 pack and unpack functions
[mesa.git] / src / gallium / auxiliary / util / u_format_other.c
1 /**************************************************************************
2 *
3 * Copyright 2010 VMware, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
18 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 * USE OR OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * The above copyright notice and this permission notice (including the
23 * next paragraph) shall be included in all copies or substantial portions
24 * of the Software.
25 *
26 **************************************************************************/
27
28
29 #include "u_math.h"
30 #include "u_format_other.h"
31 #include "../../../mesa/main/rgb9e5.h"
32
33
34 void
35 util_format_r9g9b9e5_float_unpack_rgba_float(float *dst_row, unsigned dst_stride,
36 const uint8_t *src_row, unsigned src_stride,
37 unsigned width, unsigned height)
38 {
39 unsigned x, y;
40 for(y = 0; y < height; y += 1) {
41 float *dst = dst_row;
42 const uint8_t *src = src_row;
43 for(x = 0; x < width; x += 1) {
44 uint32_t value = *(const uint32_t *)src;
45 #ifdef PIPE_ARCH_BIG_ENDIAN
46 value = util_bswap32(value);
47 #endif
48 rgb9e5_to_float3(value, dst);
49 dst[3] = 1; /* a */
50 src += 4;
51 dst += 4;
52 }
53 src_row += src_stride;
54 dst_row += dst_stride/sizeof(*dst_row);
55 }
56 }
57
58 void
59 util_format_r9g9b9e5_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
60 const float *src_row, unsigned src_stride,
61 unsigned width, unsigned height)
62 {
63 unsigned x, y;
64 for(y = 0; y < height; y += 1) {
65 const float *src = src_row;
66 uint8_t *dst = dst_row;
67 for(x = 0; x < width; x += 1) {
68 uint32_t value = float3_to_rgb9e5(src);
69 #ifdef PIPE_ARCH_BIG_ENDIAN
70 value = util_bswap32(value);
71 #endif
72 *(uint32_t *)dst = value;
73 src += 4;
74 dst += 4;
75 }
76 dst_row += dst_stride;
77 src_row += src_stride/sizeof(*src_row);
78 }
79 }
80
81 void
82 util_format_r9g9b9e5_float_fetch_rgba_float(float *dst, const uint8_t *src,
83 unsigned i, unsigned j)
84 {
85 uint32_t value = *(const uint32_t *)src;
86 #ifdef PIPE_ARCH_BIG_ENDIAN
87 value = util_bswap32(value);
88 #endif
89 rgb9e5_to_float3(value, dst);
90 dst[3] = 1; /* a */
91 }
92
93
94 void
95 util_format_r9g9b9e5_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
96 const uint8_t *src_row, unsigned src_stride,
97 unsigned width, unsigned height)
98 {
99 unsigned x, y;
100 float p[3];
101 for(y = 0; y < height; y += 1) {
102 uint8_t *dst = dst_row;
103 const uint8_t *src = src_row;
104 for(x = 0; x < width; x += 1) {
105 uint32_t value = *(const uint32_t *)src;
106 #ifdef PIPE_ARCH_BIG_ENDIAN
107 value = util_bswap32(value);
108 #endif
109 rgb9e5_to_float3(value, p);
110 dst[0] = float_to_ubyte(p[0]); /* r */
111 dst[1] = float_to_ubyte(p[1]); /* g */
112 dst[2] = float_to_ubyte(p[2]); /* b */
113 dst[3] = 255; /* a */
114 src += 4;
115 dst += 4;
116 }
117 src_row += src_stride;
118 dst_row += dst_stride/sizeof(*dst_row);
119 }
120 }
121
122
123 void
124 util_format_r9g9b9e5_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
125 const uint8_t *src_row, unsigned src_stride,
126 unsigned width, unsigned height)
127 {
128 unsigned x, y;
129 float p[3];
130 for(y = 0; y < height; y += 1) {
131 const uint8_t *src = src_row;
132 uint8_t *dst = dst_row;
133 for(x = 0; x < width; x += 1) {
134 uint32_t value;
135 p[0] = ubyte_to_float(src[0]);
136 p[1] = ubyte_to_float(src[1]);
137 p[2] = ubyte_to_float(src[2]);
138 value = float3_to_rgb9e5(p);
139 #ifdef PIPE_ARCH_BIG_ENDIAN
140 value = util_bswap32(value);
141 #endif
142 *(uint32_t *)dst = value;
143 src += 4;
144 dst += 4;
145 }
146 dst_row += dst_stride;
147 src_row += src_stride/sizeof(*src_row);
148 }
149 }
150
151
152 void
153 util_format_r1_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride,
154 const uint8_t *src_row, unsigned src_stride,
155 unsigned width, unsigned height)
156 {
157
158 }
159
160
161 void
162 util_format_r1_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
163 const float *src_row, unsigned src_stride,
164 unsigned width, unsigned height)
165 {
166
167 }
168
169
170 void
171 util_format_r1_unorm_fetch_rgba_float(float *dst, const uint8_t *src,
172 unsigned i, unsigned j)
173 {
174
175 }
176
177
178 void
179 util_format_r1_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
180 const uint8_t *src_row, unsigned src_stride,
181 unsigned width, unsigned height)
182 {
183
184 }
185
186
187 void
188 util_format_r1_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
189 const uint8_t *src_row, unsigned src_stride,
190 unsigned width, unsigned height)
191 {
192 }
193
194
195 /*
196 * PIPE_FORMAT_R8G8Bx_SNORM
197 *
198 * A.k.a. D3DFMT_CxV8U8
199 */
200
201 static uint8_t
202 r8g8bx_derive(int16_t r, int16_t g)
203 {
204 /* Derive blue from red and green components.
205 * Apparently, we must always use integers to perform calculations,
206 * otherwise the results won't match D3D's CxV8U8 definition.
207 */
208 return (uint8_t)sqrtf(0x7f * 0x7f - r * r - g * g) * 0xff / 0x7f;
209 }
210
211 void
212 util_format_r8g8bx_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride,
213 const uint8_t *src_row, unsigned src_stride,
214 unsigned width, unsigned height)
215 {
216 unsigned x, y;
217
218 for(y = 0; y < height; y += 1) {
219 float *dst = dst_row;
220 const uint16_t *src = (const uint16_t *)src_row;
221 for(x = 0; x < width; x += 1) {
222 uint16_t value = *src++;
223 int16_t r, g;
224
225 #ifdef PIPE_ARCH_BIG_ENDIAN
226 value = util_bswap32(value);
227 #endif
228
229 r = ((int16_t)(value << 8)) >> 8;
230 g = ((int16_t)(value << 0)) >> 8;
231
232 dst[0] = (float)(r * (1.0f/0x7f)); /* r */
233 dst[1] = (float)(g * (1.0f/0x7f)); /* g */
234 dst[2] = r8g8bx_derive(r, g) * (1.0f/0xff); /* b */
235 dst[3] = 1.0f; /* a */
236 dst += 4;
237 }
238 src_row += src_stride;
239 dst_row += dst_stride/sizeof(*dst_row);
240 }
241 }
242
243
244 void
245 util_format_r8g8bx_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
246 const uint8_t *src_row, unsigned src_stride,
247 unsigned width, unsigned height)
248 {
249 unsigned x, y;
250 for(y = 0; y < height; y += 1) {
251 uint8_t *dst = dst_row;
252 const uint16_t *src = (const uint16_t *)src_row;
253 for(x = 0; x < width; x += 1) {
254 uint16_t value = *src++;
255 int16_t r, g;
256
257 #ifdef PIPE_ARCH_BIG_ENDIAN
258 value = util_bswap32(value);
259 #endif
260
261 r = ((int16_t)(value << 8)) >> 8;
262 g = ((int16_t)(value << 0)) >> 8;
263
264 dst[0] = (uint8_t)(((uint16_t)MAX2(r, 0)) * 0xff / 0x7f); /* r */
265 dst[1] = (uint8_t)(((uint16_t)MAX2(g, 0)) * 0xff / 0x7f); /* g */
266 dst[2] = r8g8bx_derive(r, g); /* b */
267 dst[3] = 255; /* a */
268 dst += 4;
269 }
270 src_row += src_stride;
271 dst_row += dst_stride/sizeof(*dst_row);
272 }
273 }
274
275
276 void
277 util_format_r8g8bx_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
278 const float *src_row, unsigned src_stride,
279 unsigned width, unsigned height)
280 {
281 unsigned x, y;
282 for(y = 0; y < height; y += 1) {
283 const float *src = src_row;
284 uint16_t *dst = (uint16_t *)dst_row;
285 for(x = 0; x < width; x += 1) {
286 uint16_t value = 0;
287
288 value |= (uint16_t)(((int8_t)(CLAMP(src[0], -1, 1) * 0x7f)) & 0xff) ;
289 value |= (uint16_t)((((int8_t)(CLAMP(src[1], -1, 1) * 0x7f)) & 0xff) << 8) ;
290
291 #ifdef PIPE_ARCH_BIG_ENDIAN
292 value = util_bswap32(value);
293 #endif
294
295 *dst++ = value;
296
297 src += 4;
298 }
299 dst_row += dst_stride;
300 src_row += src_stride/sizeof(*src_row);
301 }
302 }
303
304
305 void
306 util_format_r8g8bx_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
307 const uint8_t *src_row, unsigned src_stride,
308 unsigned width, unsigned height)
309 {
310 unsigned x, y;
311
312 for(y = 0; y < height; y += 1) {
313 const uint8_t *src = src_row;
314 uint16_t *dst = (uint16_t *)dst_row;
315 for(x = 0; x < width; x += 1) {
316 uint16_t value = 0;
317
318 value |= src[0] >> 1;
319 value |= (src[1] >> 1) << 8;
320
321 #ifdef PIPE_ARCH_BIG_ENDIAN
322 value = util_bswap32(value);
323 #endif
324
325 *dst++ = value;
326
327 src += 4;
328 }
329 dst_row += dst_stride;
330 src_row += src_stride/sizeof(*src_row);
331 }
332 }
333
334
335 void
336 util_format_r8g8bx_snorm_fetch_rgba_float(float *dst, const uint8_t *src,
337 unsigned i, unsigned j)
338 {
339 uint16_t value = *(const uint16_t *)src;
340 int16_t r, g;
341
342 #ifdef PIPE_ARCH_BIG_ENDIAN
343 value = util_bswap32(value);
344 #endif
345
346 r = ((int16_t)(value << 8)) >> 8;
347 g = ((int16_t)(value << 0)) >> 8;
348
349 dst[0] = r * (1.0f/0x7f); /* r */
350 dst[1] = g * (1.0f/0x7f); /* g */
351 dst[2] = r8g8bx_derive(r, g) * (1.0f/0xff); /* b */
352 dst[3] = 1.0f; /* a */
353 }