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.h"
41 #include "util/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
util_pack_color_ub(ubyte r,ubyte g,ubyte b,ubyte a,enum pipe_format format,union util_color * uc)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
util_unpack_color_ub(enum pipe_format format,union util_color * uc,ubyte * r,ubyte * g,ubyte * b,ubyte * a)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
util_pack_color(const float rgba[4],enum pipe_format format,union util_color * uc)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_write_4f(format, rgba, 0, uc, 0, 0, 0, 1, 1);
434 }
435 }
436
437 /* Integer versions of util_pack_z and util_pack_z_stencil - useful for
438 * constructing clear masks.
439 */
440 static inline uint32_t
util_pack_mask_z(enum pipe_format format,uint32_t z)441 util_pack_mask_z(enum pipe_format format, uint32_t z)
442 {
443 switch (format) {
444 case PIPE_FORMAT_Z16_UNORM:
445 return z & 0xffff;
446 case PIPE_FORMAT_Z32_UNORM:
447 case PIPE_FORMAT_Z32_FLOAT:
448 return z;
449 case PIPE_FORMAT_Z24_UNORM_S8_UINT:
450 case PIPE_FORMAT_Z24X8_UNORM:
451 return z & 0xffffff;
452 case PIPE_FORMAT_S8_UINT_Z24_UNORM:
453 case PIPE_FORMAT_X8Z24_UNORM:
454 return (z & 0xffffff) << 8;
455 case PIPE_FORMAT_S8_UINT:
456 return 0;
457 default:
458 debug_print_format("gallium: unhandled format in util_pack_mask_z()", format);
459 assert(0);
460 return 0;
461 }
462 }
463
464
465 static inline uint64_t
util_pack64_mask_z(enum pipe_format format,uint32_t z)466 util_pack64_mask_z(enum pipe_format format, uint32_t z)
467 {
468 switch (format) {
469 case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
470 return z;
471 default:
472 return util_pack_mask_z(format, z);
473 }
474 }
475
476
477 static inline uint32_t
util_pack_mask_z_stencil(enum pipe_format format,uint32_t z,uint8_t s)478 util_pack_mask_z_stencil(enum pipe_format format, uint32_t z, uint8_t s)
479 {
480 uint32_t packed = util_pack_mask_z(format, z);
481
482 switch (format) {
483 case PIPE_FORMAT_Z24_UNORM_S8_UINT:
484 packed |= (uint32_t)s << 24;
485 break;
486 case PIPE_FORMAT_S8_UINT_Z24_UNORM:
487 packed |= s;
488 break;
489 case PIPE_FORMAT_S8_UINT:
490 packed |= s;
491 break;
492 default:
493 break;
494 }
495
496 return packed;
497 }
498
499
500 static inline uint64_t
util_pack64_mask_z_stencil(enum pipe_format format,uint32_t z,uint8_t s)501 util_pack64_mask_z_stencil(enum pipe_format format, uint32_t z, uint8_t s)
502 {
503 uint64_t packed;
504
505 switch (format) {
506 case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
507 packed = util_pack64_mask_z(format, z);
508 packed |= (uint64_t)s << 32ull;
509 return packed;
510 default:
511 return util_pack_mask_z_stencil(format, z, s);
512 }
513 }
514
515
516 /**
517 * Note: it's assumed that z is in [0,1]
518 */
519 static inline uint32_t
util_pack_z(enum pipe_format format,double z)520 util_pack_z(enum pipe_format format, double z)
521 {
522 union fi fui;
523
524 if (z == 0.0)
525 return 0;
526
527 switch (format) {
528 case PIPE_FORMAT_Z16_UNORM:
529 if (z == 1.0)
530 return 0xffff;
531 return (uint32_t) lrint(z * 0xffff);
532 case PIPE_FORMAT_Z32_UNORM:
533 /* special-case to avoid overflow */
534 if (z == 1.0)
535 return 0xffffffff;
536 return (uint32_t) llrint(z * 0xffffffff);
537 case PIPE_FORMAT_Z32_FLOAT:
538 fui.f = (float)z;
539 return fui.ui;
540 case PIPE_FORMAT_Z24_UNORM_S8_UINT:
541 case PIPE_FORMAT_Z24X8_UNORM:
542 if (z == 1.0)
543 return 0xffffff;
544 return (uint32_t) lrint(z * 0xffffff);
545 case PIPE_FORMAT_S8_UINT_Z24_UNORM:
546 case PIPE_FORMAT_X8Z24_UNORM:
547 if (z == 1.0)
548 return 0xffffff00;
549 return ((uint32_t) lrint(z * 0xffffff)) << 8;
550 case PIPE_FORMAT_S8_UINT:
551 /* this case can get it via util_pack_z_stencil() */
552 return 0;
553 default:
554 debug_print_format("gallium: unhandled format in util_pack_z()", format);
555 assert(0);
556 return 0;
557 }
558 }
559
560
561 static inline uint64_t
util_pack64_z(enum pipe_format format,double z)562 util_pack64_z(enum pipe_format format, double z)
563 {
564 union fi fui;
565
566 if (z == 0)
567 return 0;
568
569 switch (format) {
570 case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
571 fui.f = (float)z;
572 return fui.ui;
573 default:
574 return util_pack_z(format, z);
575 }
576 }
577
578
579 /**
580 * Pack Z and/or stencil values into a 32-bit value described by format.
581 * Note: it's assumed that z is in [0,1] and s in [0,255]
582 */
583 static inline uint32_t
util_pack_z_stencil(enum pipe_format format,double z,uint8_t s)584 util_pack_z_stencil(enum pipe_format format, double z, uint8_t s)
585 {
586 uint32_t packed = util_pack_z(format, z);
587
588 switch (format) {
589 case PIPE_FORMAT_Z24_UNORM_S8_UINT:
590 packed |= (uint32_t)s << 24;
591 break;
592 case PIPE_FORMAT_S8_UINT_Z24_UNORM:
593 packed |= s;
594 break;
595 case PIPE_FORMAT_S8_UINT:
596 packed |= s;
597 break;
598 default:
599 break;
600 }
601
602 return packed;
603 }
604
605
606 static inline uint64_t
util_pack64_z_stencil(enum pipe_format format,double z,uint8_t s)607 util_pack64_z_stencil(enum pipe_format format, double z, uint8_t s)
608 {
609 uint64_t packed;
610
611 switch (format) {
612 case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
613 packed = util_pack64_z(format, z);
614 packed |= (uint64_t)s << 32ull;
615 break;
616 default:
617 return util_pack_z_stencil(format, z, s);
618 }
619
620 return packed;
621 }
622
623
624 /**
625 * Pack 4 ubytes into a 4-byte word
626 */
627 static inline unsigned
pack_ub4(ubyte b0,ubyte b1,ubyte b2,ubyte b3)628 pack_ub4(ubyte b0, ubyte b1, ubyte b2, ubyte b3)
629 {
630 return ((((unsigned int)b0) << 0) |
631 (((unsigned int)b1) << 8) |
632 (((unsigned int)b2) << 16) |
633 (((unsigned int)b3) << 24));
634 }
635
636
637 /**
638 * Pack/convert 4 floats into one 4-byte word.
639 */
640 static inline unsigned
pack_ui32_float4(float a,float b,float c,float d)641 pack_ui32_float4(float a, float b, float c, float d)
642 {
643 return pack_ub4( float_to_ubyte(a),
644 float_to_ubyte(b),
645 float_to_ubyte(c),
646 float_to_ubyte(d) );
647 }
648
649
650
651 #endif /* U_PACK_COLOR_H */
652