6eea87ef38c34a68010554515af68bd274dbbb3c
[mesa.git] / src / gallium / auxiliary / util / u_pack_color.h
1 /**************************************************************************
2 *
3 * Copyright 2008 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 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 VMWARE 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_debug_gallium.h"
41 #include "util/format/u_format.h"
42 #include "util/u_math.h"
43
44
45 /**
46 * Helper union for packing pixel values.
47 * Will often contain values in formats which are too complex to be described
48 * in simple terms, hence might just effectively contain a number of bytes.
49 * Must be big enough to hold data for all formats (currently 256 bits).
50 */
51 union util_color {
52 ubyte ub;
53 ushort us;
54 uint ui[4];
55 ushort h[4]; /* half float */
56 float f[4];
57 double d[4];
58 };
59
60 /**
61 * Pack ubyte R,G,B,A into dest pixel.
62 */
63 static inline void
64 util_pack_color_ub(ubyte r, ubyte g, ubyte b, ubyte a,
65 enum pipe_format format, union util_color *uc)
66 {
67 switch (format) {
68 case PIPE_FORMAT_ABGR8888_UNORM:
69 {
70 uc->ui[0] = (r << 24) | (g << 16) | (b << 8) | a;
71 }
72 return;
73 case PIPE_FORMAT_XBGR8888_UNORM:
74 {
75 uc->ui[0] = (r << 24) | (g << 16) | (b << 8) | 0xff;
76 }
77 return;
78 case PIPE_FORMAT_BGRA8888_UNORM:
79 {
80 uc->ui[0] = (a << 24) | (r << 16) | (g << 8) | b;
81 }
82 return;
83 case PIPE_FORMAT_BGRX8888_UNORM:
84 {
85 uc->ui[0] = (0xff << 24) | (r << 16) | (g << 8) | b;
86 }
87 return;
88 case PIPE_FORMAT_ARGB8888_UNORM:
89 {
90 uc->ui[0] = (b << 24) | (g << 16) | (r << 8) | a;
91 }
92 return;
93 case PIPE_FORMAT_XRGB8888_UNORM:
94 {
95 uc->ui[0] = (b << 24) | (g << 16) | (r << 8) | 0xff;
96 }
97 return;
98 case PIPE_FORMAT_B5G6R5_UNORM:
99 {
100 uc->us = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3);
101 }
102 return;
103 case PIPE_FORMAT_B5G5R5X1_UNORM:
104 {
105 uc->us = ((0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3);
106 }
107 return;
108 case PIPE_FORMAT_B5G5R5A1_UNORM:
109 {
110 uc->us = ((a & 0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3);
111 }
112 return;
113 case PIPE_FORMAT_B4G4R4A4_UNORM:
114 {
115 uc->us = ((a & 0xf0) << 8) | ((r & 0xf0) << 4) | ((g & 0xf0) << 0) | (b >> 4);
116 }
117 return;
118 case PIPE_FORMAT_A8_UNORM:
119 {
120 uc->ub = a;
121 }
122 return;
123 case PIPE_FORMAT_L8_UNORM:
124 case PIPE_FORMAT_I8_UNORM:
125 {
126 uc->ub = r;
127 }
128 return;
129 case PIPE_FORMAT_R32G32B32A32_FLOAT:
130 {
131 uc->f[0] = (float)r / 255.0f;
132 uc->f[1] = (float)g / 255.0f;
133 uc->f[2] = (float)b / 255.0f;
134 uc->f[3] = (float)a / 255.0f;
135 }
136 return;
137 case PIPE_FORMAT_R32G32B32_FLOAT:
138 {
139 uc->f[0] = (float)r / 255.0f;
140 uc->f[1] = (float)g / 255.0f;
141 uc->f[2] = (float)b / 255.0f;
142 }
143 return;
144
145 /* Handle other cases with a generic function.
146 */
147 default:
148 {
149 ubyte src[4];
150
151 src[0] = r;
152 src[1] = g;
153 src[2] = b;
154 src[3] = a;
155 util_format_write_4ub(format, src, 0, uc, 0, 0, 0, 1, 1);
156 }
157 }
158 }
159
160
161 /**
162 * Unpack RGBA from a packed pixel, returning values as ubytes in [0,255].
163 */
164 static inline void
165 util_unpack_color_ub(enum pipe_format format, union util_color *uc,
166 ubyte *r, ubyte *g, ubyte *b, ubyte *a)
167 {
168 switch (format) {
169 case PIPE_FORMAT_ABGR8888_UNORM:
170 {
171 uint p = uc->ui[0];
172 *r = (ubyte) ((p >> 24) & 0xff);
173 *g = (ubyte) ((p >> 16) & 0xff);
174 *b = (ubyte) ((p >> 8) & 0xff);
175 *a = (ubyte) ((p >> 0) & 0xff);
176 }
177 return;
178 case PIPE_FORMAT_XBGR8888_UNORM:
179 {
180 uint p = uc->ui[0];
181 *r = (ubyte) ((p >> 24) & 0xff);
182 *g = (ubyte) ((p >> 16) & 0xff);
183 *b = (ubyte) ((p >> 8) & 0xff);
184 *a = (ubyte) 0xff;
185 }
186 return;
187 case PIPE_FORMAT_BGRA8888_UNORM:
188 {
189 uint p = uc->ui[0];
190 *r = (ubyte) ((p >> 16) & 0xff);
191 *g = (ubyte) ((p >> 8) & 0xff);
192 *b = (ubyte) ((p >> 0) & 0xff);
193 *a = (ubyte) ((p >> 24) & 0xff);
194 }
195 return;
196 case PIPE_FORMAT_BGRX8888_UNORM:
197 {
198 uint p = uc->ui[0];
199 *r = (ubyte) ((p >> 16) & 0xff);
200 *g = (ubyte) ((p >> 8) & 0xff);
201 *b = (ubyte) ((p >> 0) & 0xff);
202 *a = (ubyte) 0xff;
203 }
204 return;
205 case PIPE_FORMAT_ARGB8888_UNORM:
206 {
207 uint p = uc->ui[0];
208 *r = (ubyte) ((p >> 8) & 0xff);
209 *g = (ubyte) ((p >> 16) & 0xff);
210 *b = (ubyte) ((p >> 24) & 0xff);
211 *a = (ubyte) ((p >> 0) & 0xff);
212 }
213 return;
214 case PIPE_FORMAT_XRGB8888_UNORM:
215 {
216 uint p = uc->ui[0];
217 *r = (ubyte) ((p >> 8) & 0xff);
218 *g = (ubyte) ((p >> 16) & 0xff);
219 *b = (ubyte) ((p >> 24) & 0xff);
220 *a = (ubyte) 0xff;
221 }
222 return;
223 case PIPE_FORMAT_B5G6R5_UNORM:
224 {
225 ushort p = uc->us;
226 *r = (ubyte) (((p >> 8) & 0xf8) | ((p >> 13) & 0x7));
227 *g = (ubyte) (((p >> 3) & 0xfc) | ((p >> 9) & 0x3));
228 *b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7));
229 *a = (ubyte) 0xff;
230 }
231 return;
232 case PIPE_FORMAT_B5G5R5X1_UNORM:
233 {
234 ushort p = uc->us;
235 *r = (ubyte) (((p >> 7) & 0xf8) | ((p >> 12) & 0x7));
236 *g = (ubyte) (((p >> 2) & 0xf8) | ((p >> 7) & 0x7));
237 *b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7));
238 *a = (ubyte) 0xff;
239 }
240 return;
241 case PIPE_FORMAT_B5G5R5A1_UNORM:
242 {
243 ushort p = uc->us;
244 *r = (ubyte) (((p >> 7) & 0xf8) | ((p >> 12) & 0x7));
245 *g = (ubyte) (((p >> 2) & 0xf8) | ((p >> 7) & 0x7));
246 *b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7));
247 *a = (ubyte) (0xff * (p >> 15));
248 }
249 return;
250 case PIPE_FORMAT_B4G4R4A4_UNORM:
251 {
252 ushort p = uc->us;
253 *r = (ubyte) (((p >> 4) & 0xf0) | ((p >> 8) & 0xf));
254 *g = (ubyte) (((p >> 0) & 0xf0) | ((p >> 4) & 0xf));
255 *b = (ubyte) (((p << 4) & 0xf0) | ((p >> 0) & 0xf));
256 *a = (ubyte) (((p >> 8) & 0xf0) | ((p >> 12) & 0xf));
257 }
258 return;
259 case PIPE_FORMAT_A8_UNORM:
260 {
261 ubyte p = uc->ub;
262 *r = *g = *b = (ubyte) 0xff;
263 *a = p;
264 }
265 return;
266 case PIPE_FORMAT_L8_UNORM:
267 {
268 ubyte p = uc->ub;
269 *r = *g = *b = p;
270 *a = (ubyte) 0xff;
271 }
272 return;
273 case PIPE_FORMAT_I8_UNORM:
274 {
275 ubyte p = uc->ub;
276 *r = *g = *b = *a = p;
277 }
278 return;
279 case PIPE_FORMAT_R32G32B32A32_FLOAT:
280 {
281 const float *p = &uc->f[0];
282 *r = float_to_ubyte(p[0]);
283 *g = float_to_ubyte(p[1]);
284 *b = float_to_ubyte(p[2]);
285 *a = float_to_ubyte(p[3]);
286 }
287 return;
288 case PIPE_FORMAT_R32G32B32_FLOAT:
289 {
290 const float *p = &uc->f[0];
291 *r = float_to_ubyte(p[0]);
292 *g = float_to_ubyte(p[1]);
293 *b = float_to_ubyte(p[2]);
294 *a = (ubyte) 0xff;
295 }
296 return;
297
298 case PIPE_FORMAT_R32G32_FLOAT:
299 {
300 const float *p = &uc->f[0];
301 *r = float_to_ubyte(p[0]);
302 *g = float_to_ubyte(p[1]);
303 *b = *a = (ubyte) 0xff;
304 }
305 return;
306
307 case PIPE_FORMAT_R32_FLOAT:
308 {
309 const float *p = &uc->f[0];
310 *r = float_to_ubyte(p[0]);
311 *g = *b = *a = (ubyte) 0xff;
312 }
313 return;
314
315 /* Handle other cases with a generic function.
316 */
317 default:
318 {
319 ubyte dst[4];
320
321 util_format_read_4ub(format, dst, 0, uc, 0, 0, 0, 1, 1);
322 *r = dst[0];
323 *g = dst[1];
324 *b = dst[2];
325 *a = dst[3];
326 }
327 }
328 }
329
330
331 /**
332 * Note rgba outside [0,1] will be clamped for int pixel formats.
333 * This will not work (and might not really be useful with float input)
334 * for pure integer formats (which lack the pack_rgba_float function).
335 */
336 static inline void
337 util_pack_color(const float rgba[4], enum pipe_format format, union util_color *uc)
338 {
339 ubyte r = 0;
340 ubyte g = 0;
341 ubyte b = 0;
342 ubyte a = 0;
343
344 if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 0) <= 8) {
345 /* format uses 8-bit components or less */
346 r = float_to_ubyte(rgba[0]);
347 g = float_to_ubyte(rgba[1]);
348 b = float_to_ubyte(rgba[2]);
349 a = float_to_ubyte(rgba[3]);
350 }
351
352 switch (format) {
353 case PIPE_FORMAT_ABGR8888_UNORM:
354 {
355 uc->ui[0] = (r << 24) | (g << 16) | (b << 8) | a;
356 }
357 return;
358 case PIPE_FORMAT_XBGR8888_UNORM:
359 {
360 uc->ui[0] = (r << 24) | (g << 16) | (b << 8) | 0xff;
361 }
362 return;
363 case PIPE_FORMAT_BGRA8888_UNORM:
364 {
365 uc->ui[0] = (a << 24) | (r << 16) | (g << 8) | b;
366 }
367 return;
368 case PIPE_FORMAT_BGRX8888_UNORM:
369 {
370 uc->ui[0] = (0xffu << 24) | (r << 16) | (g << 8) | b;
371 }
372 return;
373 case PIPE_FORMAT_ARGB8888_UNORM:
374 {
375 uc->ui[0] = (b << 24) | (g << 16) | (r << 8) | a;
376 }
377 return;
378 case PIPE_FORMAT_XRGB8888_UNORM:
379 {
380 uc->ui[0] = (b << 24) | (g << 16) | (r << 8) | 0xff;
381 }
382 return;
383 case PIPE_FORMAT_B5G6R5_UNORM:
384 {
385 uc->us = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3);
386 }
387 return;
388 case PIPE_FORMAT_B5G5R5X1_UNORM:
389 {
390 uc->us = ((0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3);
391 }
392 return;
393 case PIPE_FORMAT_B5G5R5A1_UNORM:
394 {
395 uc->us = ((a & 0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3);
396 }
397 return;
398 case PIPE_FORMAT_B4G4R4A4_UNORM:
399 {
400 uc->us = ((a & 0xf0) << 8) | ((r & 0xf0) << 4) | ((g & 0xf0) << 0) | (b >> 4);
401 }
402 return;
403 case PIPE_FORMAT_A8_UNORM:
404 {
405 uc->ub = a;
406 }
407 return;
408 case PIPE_FORMAT_L8_UNORM:
409 case PIPE_FORMAT_I8_UNORM:
410 {
411 uc->ub = r;
412 }
413 return;
414 case PIPE_FORMAT_R32G32B32A32_FLOAT:
415 {
416 uc->f[0] = rgba[0];
417 uc->f[1] = rgba[1];
418 uc->f[2] = rgba[2];
419 uc->f[3] = rgba[3];
420 }
421 return;
422 case PIPE_FORMAT_R32G32B32_FLOAT:
423 {
424 uc->f[0] = rgba[0];
425 uc->f[1] = rgba[1];
426 uc->f[2] = rgba[2];
427 }
428 return;
429
430 /* Handle other cases with a generic function.
431 */
432 default:
433 util_format_pack_rgba(format, uc, rgba, 1);
434 }
435 }
436
437 static inline void
438 util_pack_color_union(enum pipe_format format,
439 union util_color *dst,
440 const union pipe_color_union *src)
441 {
442 util_format_pack_rgba(format, dst, &src->ui, 1);
443 }
444
445 /* Integer versions of util_pack_z and util_pack_z_stencil - useful for
446 * constructing clear masks.
447 */
448 static inline uint32_t
449 util_pack_mask_z(enum pipe_format format, uint32_t z)
450 {
451 switch (format) {
452 case PIPE_FORMAT_Z16_UNORM:
453 return z & 0xffff;
454 case PIPE_FORMAT_Z32_UNORM:
455 case PIPE_FORMAT_Z32_FLOAT:
456 return z;
457 case PIPE_FORMAT_Z24_UNORM_S8_UINT:
458 case PIPE_FORMAT_Z24X8_UNORM:
459 return z & 0xffffff;
460 case PIPE_FORMAT_S8_UINT_Z24_UNORM:
461 case PIPE_FORMAT_X8Z24_UNORM:
462 return (z & 0xffffff) << 8;
463 case PIPE_FORMAT_S8_UINT:
464 return 0;
465 default:
466 debug_print_format("gallium: unhandled format in util_pack_mask_z()", format);
467 assert(0);
468 return 0;
469 }
470 }
471
472
473 static inline uint64_t
474 util_pack64_mask_z(enum pipe_format format, uint32_t z)
475 {
476 switch (format) {
477 case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
478 return z;
479 default:
480 return util_pack_mask_z(format, z);
481 }
482 }
483
484
485 static inline uint32_t
486 util_pack_mask_z_stencil(enum pipe_format format, uint32_t z, uint8_t s)
487 {
488 uint32_t packed = util_pack_mask_z(format, z);
489
490 switch (format) {
491 case PIPE_FORMAT_Z24_UNORM_S8_UINT:
492 packed |= (uint32_t)s << 24;
493 break;
494 case PIPE_FORMAT_S8_UINT_Z24_UNORM:
495 packed |= s;
496 break;
497 case PIPE_FORMAT_S8_UINT:
498 packed |= s;
499 break;
500 default:
501 break;
502 }
503
504 return packed;
505 }
506
507
508 static inline uint64_t
509 util_pack64_mask_z_stencil(enum pipe_format format, uint32_t z, uint8_t s)
510 {
511 uint64_t packed;
512
513 switch (format) {
514 case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
515 packed = util_pack64_mask_z(format, z);
516 packed |= (uint64_t)s << 32ull;
517 return packed;
518 default:
519 return util_pack_mask_z_stencil(format, z, s);
520 }
521 }
522
523
524 /**
525 * Note: it's assumed that z is in [0,1]
526 */
527 static inline uint32_t
528 util_pack_z(enum pipe_format format, double z)
529 {
530 union fi fui;
531
532 if (z == 0.0)
533 return 0;
534
535 switch (format) {
536 case PIPE_FORMAT_Z16_UNORM:
537 if (z == 1.0)
538 return 0xffff;
539 return (uint32_t) lrint(z * 0xffff);
540 case PIPE_FORMAT_Z32_UNORM:
541 /* special-case to avoid overflow */
542 if (z == 1.0)
543 return 0xffffffff;
544 return (uint32_t) llrint(z * 0xffffffff);
545 case PIPE_FORMAT_Z32_FLOAT:
546 fui.f = (float)z;
547 return fui.ui;
548 case PIPE_FORMAT_Z24_UNORM_S8_UINT:
549 case PIPE_FORMAT_Z24X8_UNORM:
550 if (z == 1.0)
551 return 0xffffff;
552 return (uint32_t) lrint(z * 0xffffff);
553 case PIPE_FORMAT_S8_UINT_Z24_UNORM:
554 case PIPE_FORMAT_X8Z24_UNORM:
555 if (z == 1.0)
556 return 0xffffff00;
557 return ((uint32_t) lrint(z * 0xffffff)) << 8;
558 case PIPE_FORMAT_S8_UINT:
559 /* this case can get it via util_pack_z_stencil() */
560 return 0;
561 default:
562 debug_print_format("gallium: unhandled format in util_pack_z()", format);
563 assert(0);
564 return 0;
565 }
566 }
567
568
569 static inline uint64_t
570 util_pack64_z(enum pipe_format format, double z)
571 {
572 union fi fui;
573
574 if (z == 0)
575 return 0;
576
577 switch (format) {
578 case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
579 fui.f = (float)z;
580 return fui.ui;
581 default:
582 return util_pack_z(format, z);
583 }
584 }
585
586
587 /**
588 * Pack Z and/or stencil values into a 32-bit value described by format.
589 * Note: it's assumed that z is in [0,1] and s in [0,255]
590 */
591 static inline uint32_t
592 util_pack_z_stencil(enum pipe_format format, double z, uint8_t s)
593 {
594 uint32_t packed = util_pack_z(format, z);
595
596 switch (format) {
597 case PIPE_FORMAT_Z24_UNORM_S8_UINT:
598 packed |= (uint32_t)s << 24;
599 break;
600 case PIPE_FORMAT_S8_UINT_Z24_UNORM:
601 packed |= s;
602 break;
603 case PIPE_FORMAT_S8_UINT:
604 packed |= s;
605 break;
606 default:
607 break;
608 }
609
610 return packed;
611 }
612
613
614 static inline uint64_t
615 util_pack64_z_stencil(enum pipe_format format, double z, uint8_t s)
616 {
617 uint64_t packed;
618
619 switch (format) {
620 case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
621 packed = util_pack64_z(format, z);
622 packed |= (uint64_t)s << 32ull;
623 break;
624 default:
625 return util_pack_z_stencil(format, z, s);
626 }
627
628 return packed;
629 }
630
631
632 /**
633 * Pack 4 ubytes into a 4-byte word
634 */
635 static inline unsigned
636 pack_ub4(ubyte b0, ubyte b1, ubyte b2, ubyte b3)
637 {
638 return ((((unsigned int)b0) << 0) |
639 (((unsigned int)b1) << 8) |
640 (((unsigned int)b2) << 16) |
641 (((unsigned int)b3) << 24));
642 }
643
644
645 /**
646 * Pack/convert 4 floats into one 4-byte word.
647 */
648 static inline unsigned
649 pack_ui32_float4(float a, float b, float c, float d)
650 {
651 return pack_ub4( float_to_ubyte(a),
652 float_to_ubyte(b),
653 float_to_ubyte(c),
654 float_to_ubyte(d) );
655 }
656
657
658
659 #endif /* U_PACK_COLOR_H */