Merge branch 'pipe-format-simplify'
[mesa.git] / src / gallium / auxiliary / util / u_pack_color.h
1 /**************************************************************************
2 *
3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
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 above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 /**
29 * @file
30 * Functions to produce packed colors/Z from floats.
31 */
32
33
34 #ifndef U_PACK_COLOR_H
35 #define U_PACK_COLOR_H
36
37
38 #include "pipe/p_compiler.h"
39 #include "pipe/p_format.h"
40 #include "util/u_format.h"
41 #include "util/u_math.h"
42
43
44
45 union util_color {
46 ubyte ub;
47 ushort us;
48 uint ui;
49 float f[4];
50 };
51
52 /**
53 * Pack ubyte R,G,B,A into dest pixel.
54 */
55 static INLINE void
56 util_pack_color_ub(ubyte r, ubyte g, ubyte b, ubyte a,
57 enum pipe_format format, union util_color *uc)
58 {
59 switch (format) {
60 case PIPE_FORMAT_R8G8B8A8_UNORM:
61 {
62 uc->ui = (r << 24) | (g << 16) | (b << 8) | a;
63 }
64 return;
65 case PIPE_FORMAT_R8G8B8X8_UNORM:
66 {
67 uc->ui = (r << 24) | (g << 16) | (b << 8) | 0xff;
68 }
69 return;
70 case PIPE_FORMAT_A8R8G8B8_UNORM:
71 {
72 uc->ui = (a << 24) | (r << 16) | (g << 8) | b;
73 }
74 return;
75 case PIPE_FORMAT_X8R8G8B8_UNORM:
76 {
77 uc->ui = (0xff << 24) | (r << 16) | (g << 8) | b;
78 }
79 return;
80 case PIPE_FORMAT_B8G8R8A8_UNORM:
81 {
82 uc->ui = (b << 24) | (g << 16) | (r << 8) | a;
83 }
84 return;
85 case PIPE_FORMAT_B8G8R8X8_UNORM:
86 {
87 uc->ui = (b << 24) | (g << 16) | (r << 8) | 0xff;
88 }
89 return;
90 case PIPE_FORMAT_R5G6B5_UNORM:
91 {
92 uc->us = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3);
93 }
94 return;
95 case PIPE_FORMAT_A1R5G5B5_UNORM:
96 {
97 uc->us = ((a & 0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3);
98 }
99 return;
100 case PIPE_FORMAT_A4R4G4B4_UNORM:
101 {
102 uc->us = ((a & 0xf0) << 8) | ((r & 0xf0) << 4) | ((g & 0xf0) << 0) | (b >> 4);
103 }
104 return;
105 case PIPE_FORMAT_A8_UNORM:
106 {
107 uc->ub = a;
108 }
109 return;
110 case PIPE_FORMAT_L8_UNORM:
111 case PIPE_FORMAT_I8_UNORM:
112 {
113 uc->ub = a;
114 }
115 return;
116 case PIPE_FORMAT_R32G32B32A32_FLOAT:
117 {
118 uc->f[0] = (float)r / 255.0f;
119 uc->f[1] = (float)g / 255.0f;
120 uc->f[2] = (float)b / 255.0f;
121 uc->f[3] = (float)a / 255.0f;
122 }
123 return;
124 case PIPE_FORMAT_R32G32B32_FLOAT:
125 {
126 uc->f[0] = (float)r / 255.0f;
127 uc->f[1] = (float)g / 255.0f;
128 uc->f[2] = (float)b / 255.0f;
129 }
130 return;
131
132 /* XXX lots more cases to add */
133 default:
134 uc->ui = 0; /* keep compiler happy */
135 debug_print_format("gallium: unhandled format in util_pack_color_ub()", format);
136 assert(0);
137 }
138 }
139
140
141 /**
142 * Unpack RGBA from a packed pixel, returning values as ubytes in [0,255].
143 */
144 static INLINE void
145 util_unpack_color_ub(enum pipe_format format, union util_color *uc,
146 ubyte *r, ubyte *g, ubyte *b, ubyte *a)
147 {
148 switch (format) {
149 case PIPE_FORMAT_R8G8B8A8_UNORM:
150 {
151 uint p = uc->ui;
152 *r = (ubyte) ((p >> 24) & 0xff);
153 *g = (ubyte) ((p >> 16) & 0xff);
154 *b = (ubyte) ((p >> 8) & 0xff);
155 *a = (ubyte) ((p >> 0) & 0xff);
156 }
157 return;
158 case PIPE_FORMAT_R8G8B8X8_UNORM:
159 {
160 uint p = uc->ui;
161 *r = (ubyte) ((p >> 24) & 0xff);
162 *g = (ubyte) ((p >> 16) & 0xff);
163 *b = (ubyte) ((p >> 8) & 0xff);
164 *a = (ubyte) 0xff;
165 }
166 return;
167 case PIPE_FORMAT_A8R8G8B8_UNORM:
168 {
169 uint p = uc->ui;
170 *r = (ubyte) ((p >> 16) & 0xff);
171 *g = (ubyte) ((p >> 8) & 0xff);
172 *b = (ubyte) ((p >> 0) & 0xff);
173 *a = (ubyte) ((p >> 24) & 0xff);
174 }
175 return;
176 case PIPE_FORMAT_X8R8G8B8_UNORM:
177 {
178 uint p = uc->ui;
179 *r = (ubyte) ((p >> 16) & 0xff);
180 *g = (ubyte) ((p >> 8) & 0xff);
181 *b = (ubyte) ((p >> 0) & 0xff);
182 *a = (ubyte) 0xff;
183 }
184 return;
185 case PIPE_FORMAT_B8G8R8A8_UNORM:
186 {
187 uint p = uc->ui;
188 *r = (ubyte) ((p >> 8) & 0xff);
189 *g = (ubyte) ((p >> 16) & 0xff);
190 *b = (ubyte) ((p >> 24) & 0xff);
191 *a = (ubyte) ((p >> 0) & 0xff);
192 }
193 return;
194 case PIPE_FORMAT_B8G8R8X8_UNORM:
195 {
196 uint p = uc->ui;
197 *r = (ubyte) ((p >> 8) & 0xff);
198 *g = (ubyte) ((p >> 16) & 0xff);
199 *b = (ubyte) ((p >> 24) & 0xff);
200 *a = (ubyte) 0xff;
201 }
202 return;
203 case PIPE_FORMAT_R5G6B5_UNORM:
204 {
205 ushort p = uc->us;
206 *r = (ubyte) (((p >> 8) & 0xf8) | ((p >> 13) & 0x7));
207 *g = (ubyte) (((p >> 3) & 0xfc) | ((p >> 9) & 0x3));
208 *b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7));
209 *a = (ubyte) 0xff;
210 }
211 return;
212 case PIPE_FORMAT_A1R5G5B5_UNORM:
213 {
214 ushort p = uc->us;
215 *r = (ubyte) (((p >> 7) & 0xf8) | ((p >> 12) & 0x7));
216 *g = (ubyte) (((p >> 2) & 0xf8) | ((p >> 7) & 0x7));
217 *b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7));
218 *a = (ubyte) (0xff * (p >> 15));
219 }
220 return;
221 case PIPE_FORMAT_A4R4G4B4_UNORM:
222 {
223 ushort p = uc->us;
224 *r = (ubyte) (((p >> 4) & 0xf0) | ((p >> 8) & 0xf));
225 *g = (ubyte) (((p >> 0) & 0xf0) | ((p >> 4) & 0xf));
226 *b = (ubyte) (((p << 4) & 0xf0) | ((p >> 0) & 0xf));
227 *a = (ubyte) (((p >> 8) & 0xf0) | ((p >> 12) & 0xf));
228 }
229 return;
230 case PIPE_FORMAT_A8_UNORM:
231 {
232 ubyte p = uc->ub;
233 *r = *g = *b = (ubyte) 0xff;
234 *a = p;
235 }
236 return;
237 case PIPE_FORMAT_L8_UNORM:
238 {
239 ubyte p = uc->ub;
240 *r = *g = *b = p;
241 *a = (ubyte) 0xff;
242 }
243 return;
244 case PIPE_FORMAT_I8_UNORM:
245 {
246 ubyte p = uc->ub;
247 *r = *g = *b = *a = p;
248 }
249 return;
250 case PIPE_FORMAT_R32G32B32A32_FLOAT:
251 {
252 const float *p = &uc->f[0];
253 *r = float_to_ubyte(p[0]);
254 *g = float_to_ubyte(p[1]);
255 *b = float_to_ubyte(p[2]);
256 *a = float_to_ubyte(p[3]);
257 }
258 return;
259 case PIPE_FORMAT_R32G32B32_FLOAT:
260 {
261 const float *p = &uc->f[0];
262 *r = float_to_ubyte(p[0]);
263 *g = float_to_ubyte(p[1]);
264 *b = float_to_ubyte(p[2]);
265 *a = (ubyte) 0xff;
266 }
267 return;
268
269 case PIPE_FORMAT_R32G32_FLOAT:
270 {
271 const float *p = &uc->f[0];
272 *r = float_to_ubyte(p[0]);
273 *g = float_to_ubyte(p[1]);
274 *b = *a = (ubyte) 0xff;
275 }
276 return;
277
278 case PIPE_FORMAT_R32_FLOAT:
279 {
280 const float *p = &uc->f[0];
281 *r = float_to_ubyte(p[0]);
282 *g = *b = *a = (ubyte) 0xff;
283 }
284 return;
285
286 /* XXX lots more cases to add */
287 default:
288 debug_print_format("gallium: unhandled format in util_unpack_color_ub()",
289 format);
290 assert(0);
291 }
292 }
293
294
295 /**
296 * Note rgba outside [0,1] will be clamped for int pixel formats.
297 */
298 static INLINE void
299 util_pack_color(const float rgba[4], enum pipe_format format, union util_color *uc)
300 {
301 ubyte r = 0;
302 ubyte g = 0;
303 ubyte b = 0;
304 ubyte a = 0;
305
306 if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 0) <= 8) {
307 /* format uses 8-bit components or less */
308 r = float_to_ubyte(rgba[0]);
309 g = float_to_ubyte(rgba[1]);
310 b = float_to_ubyte(rgba[2]);
311 a = float_to_ubyte(rgba[3]);
312 }
313
314 switch (format) {
315 case PIPE_FORMAT_R8G8B8A8_UNORM:
316 {
317 uc->ui = (r << 24) | (g << 16) | (b << 8) | a;
318 }
319 return;
320 case PIPE_FORMAT_R8G8B8X8_UNORM:
321 {
322 uc->ui = (r << 24) | (g << 16) | (b << 8) | 0xff;
323 }
324 return;
325 case PIPE_FORMAT_A8R8G8B8_UNORM:
326 {
327 uc->ui = (a << 24) | (r << 16) | (g << 8) | b;
328 }
329 return;
330 case PIPE_FORMAT_X8R8G8B8_UNORM:
331 {
332 uc->ui = (0xff << 24) | (r << 16) | (g << 8) | b;
333 }
334 return;
335 case PIPE_FORMAT_B8G8R8A8_UNORM:
336 {
337 uc->ui = (b << 24) | (g << 16) | (r << 8) | a;
338 }
339 return;
340 case PIPE_FORMAT_B8G8R8X8_UNORM:
341 {
342 uc->ui = (b << 24) | (g << 16) | (r << 8) | 0xff;
343 }
344 return;
345 case PIPE_FORMAT_R5G6B5_UNORM:
346 {
347 uc->us = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3);
348 }
349 return;
350 case PIPE_FORMAT_A1R5G5B5_UNORM:
351 {
352 uc->us = ((a & 0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3);
353 }
354 return;
355 case PIPE_FORMAT_A4R4G4B4_UNORM:
356 {
357 uc->ub = ((a & 0xf0) << 8) | ((r & 0xf0) << 4) | ((g & 0xf0) << 0) | (b >> 4);
358 }
359 return;
360 case PIPE_FORMAT_A8_UNORM:
361 {
362 uc->ub = a;
363 }
364 return;
365 case PIPE_FORMAT_L8_UNORM:
366 case PIPE_FORMAT_I8_UNORM:
367 {
368 uc->ub = r;
369 }
370 return;
371 case PIPE_FORMAT_R32G32B32A32_FLOAT:
372 {
373 uc->f[0] = rgba[0];
374 uc->f[1] = rgba[1];
375 uc->f[2] = rgba[2];
376 uc->f[3] = rgba[3];
377 }
378 return;
379 case PIPE_FORMAT_R32G32B32_FLOAT:
380 {
381 uc->f[0] = rgba[0];
382 uc->f[1] = rgba[1];
383 uc->f[2] = rgba[2];
384 }
385 return;
386 /* XXX lots more cases to add */
387 default:
388 uc->ui = 0; /* keep compiler happy */
389 debug_print_format("gallium: unhandled format in util_pack_color()", format);
390 assert(0);
391 }
392 }
393
394
395 /**
396 * Note: it's assumed that z is in [0,1]
397 */
398 static INLINE uint
399 util_pack_z(enum pipe_format format, double z)
400 {
401 if (z == 0.0)
402 return 0;
403
404 switch (format) {
405 case PIPE_FORMAT_Z16_UNORM:
406 if (z == 1.0)
407 return 0xffff;
408 return (uint) (z * 0xffff);
409 case PIPE_FORMAT_Z32_UNORM:
410 /* special-case to avoid overflow */
411 if (z == 1.0)
412 return 0xffffffff;
413 return (uint) (z * 0xffffffff);
414 case PIPE_FORMAT_S8Z24_UNORM:
415 case PIPE_FORMAT_X8Z24_UNORM:
416 if (z == 1.0)
417 return 0xffffff;
418 return (uint) (z * 0xffffff);
419 case PIPE_FORMAT_Z24S8_UNORM:
420 case PIPE_FORMAT_Z24X8_UNORM:
421 if (z == 1.0)
422 return 0xffffff00;
423 return ((uint) (z * 0xffffff)) << 8;
424 case PIPE_FORMAT_S8_UNORM:
425 /* this case can get it via util_pack_z_stencil() */
426 return 0;
427 default:
428 debug_print_format("gallium: unhandled format in util_pack_z()", format);
429 assert(0);
430 return 0;
431 }
432 }
433
434
435 /**
436 * Pack Z and/or stencil values into a 32-bit value described by format.
437 * Note: it's assumed that z is in [0,1] and s in [0,255]
438 */
439 static INLINE uint
440 util_pack_z_stencil(enum pipe_format format, double z, uint s)
441 {
442 unsigned packed = util_pack_z(format, z);
443
444 switch (format) {
445 case PIPE_FORMAT_S8Z24_UNORM:
446 packed |= s << 24;
447 break;
448 case PIPE_FORMAT_Z24S8_UNORM:
449 packed |= s;
450 break;
451 case PIPE_FORMAT_S8_UNORM:
452 packed |= s;
453 break;
454 default:
455 break;
456 }
457
458 return packed;
459 }
460
461
462 /**
463 * Pack 4 ubytes into a 4-byte word
464 */
465 static INLINE unsigned
466 pack_ub4(ubyte b0, ubyte b1, ubyte b2, ubyte b3)
467 {
468 return ((((unsigned int)b0) << 0) |
469 (((unsigned int)b1) << 8) |
470 (((unsigned int)b2) << 16) |
471 (((unsigned int)b3) << 24));
472 }
473
474
475 /**
476 * Pack/convert 4 floats into one 4-byte word.
477 */
478 static INLINE unsigned
479 pack_ui32_float4(float a, float b, float c, float d)
480 {
481 return pack_ub4( float_to_ubyte(a),
482 float_to_ubyte(b),
483 float_to_ubyte(c),
484 float_to_ubyte(d) );
485 }
486
487
488
489 #endif /* U_PACK_COLOR_H */