Merge remote branch 'origin/7.8'
[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_A8B8G8R8_UNORM:
61 {
62 uc->ui = (r << 24) | (g << 16) | (b << 8) | a;
63 }
64 return;
65 case PIPE_FORMAT_X8B8G8R8_UNORM:
66 {
67 uc->ui = (r << 24) | (g << 16) | (b << 8) | 0xff;
68 }
69 return;
70 case PIPE_FORMAT_B8G8R8A8_UNORM:
71 {
72 uc->ui = (a << 24) | (r << 16) | (g << 8) | b;
73 }
74 return;
75 case PIPE_FORMAT_B8G8R8X8_UNORM:
76 {
77 uc->ui = (0xff << 24) | (r << 16) | (g << 8) | b;
78 }
79 return;
80 case PIPE_FORMAT_A8R8G8B8_UNORM:
81 {
82 uc->ui = (b << 24) | (g << 16) | (r << 8) | a;
83 }
84 return;
85 case PIPE_FORMAT_X8R8G8B8_UNORM:
86 {
87 uc->ui = (b << 24) | (g << 16) | (r << 8) | 0xff;
88 }
89 return;
90 case PIPE_FORMAT_B5G6R5_UNORM:
91 {
92 uc->us = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3);
93 }
94 return;
95 case PIPE_FORMAT_B5G5R5X1_UNORM:
96 {
97 uc->us = ((0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3);
98 }
99 return;
100 case PIPE_FORMAT_B5G5R5A1_UNORM:
101 {
102 uc->us = ((a & 0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3);
103 }
104 return;
105 case PIPE_FORMAT_B4G4R4A4_UNORM:
106 {
107 uc->us = ((a & 0xf0) << 8) | ((r & 0xf0) << 4) | ((g & 0xf0) << 0) | (b >> 4);
108 }
109 return;
110 case PIPE_FORMAT_A8_UNORM:
111 {
112 uc->ub = a;
113 }
114 return;
115 case PIPE_FORMAT_L8_UNORM:
116 case PIPE_FORMAT_I8_UNORM:
117 {
118 uc->ub = a;
119 }
120 return;
121 case PIPE_FORMAT_R32G32B32A32_FLOAT:
122 {
123 uc->f[0] = (float)r / 255.0f;
124 uc->f[1] = (float)g / 255.0f;
125 uc->f[2] = (float)b / 255.0f;
126 uc->f[3] = (float)a / 255.0f;
127 }
128 return;
129 case PIPE_FORMAT_R32G32B32_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 }
135 return;
136
137 /* Handle other cases with a generic function.
138 */
139 default:
140 {
141 ubyte src[4];
142
143 src[0] = r;
144 src[1] = g;
145 src[2] = b;
146 src[3] = a;
147 util_format_write_4ub(format, src, 0, uc, 0, 0, 0, 1, 1);
148 }
149 }
150 }
151
152
153 /**
154 * Unpack RGBA from a packed pixel, returning values as ubytes in [0,255].
155 */
156 static INLINE void
157 util_unpack_color_ub(enum pipe_format format, union util_color *uc,
158 ubyte *r, ubyte *g, ubyte *b, ubyte *a)
159 {
160 switch (format) {
161 case PIPE_FORMAT_A8B8G8R8_UNORM:
162 {
163 uint p = uc->ui;
164 *r = (ubyte) ((p >> 24) & 0xff);
165 *g = (ubyte) ((p >> 16) & 0xff);
166 *b = (ubyte) ((p >> 8) & 0xff);
167 *a = (ubyte) ((p >> 0) & 0xff);
168 }
169 return;
170 case PIPE_FORMAT_X8B8G8R8_UNORM:
171 {
172 uint p = uc->ui;
173 *r = (ubyte) ((p >> 24) & 0xff);
174 *g = (ubyte) ((p >> 16) & 0xff);
175 *b = (ubyte) ((p >> 8) & 0xff);
176 *a = (ubyte) 0xff;
177 }
178 return;
179 case PIPE_FORMAT_B8G8R8A8_UNORM:
180 {
181 uint p = uc->ui;
182 *r = (ubyte) ((p >> 16) & 0xff);
183 *g = (ubyte) ((p >> 8) & 0xff);
184 *b = (ubyte) ((p >> 0) & 0xff);
185 *a = (ubyte) ((p >> 24) & 0xff);
186 }
187 return;
188 case PIPE_FORMAT_B8G8R8X8_UNORM:
189 {
190 uint p = uc->ui;
191 *r = (ubyte) ((p >> 16) & 0xff);
192 *g = (ubyte) ((p >> 8) & 0xff);
193 *b = (ubyte) ((p >> 0) & 0xff);
194 *a = (ubyte) 0xff;
195 }
196 return;
197 case PIPE_FORMAT_A8R8G8B8_UNORM:
198 {
199 uint p = uc->ui;
200 *r = (ubyte) ((p >> 8) & 0xff);
201 *g = (ubyte) ((p >> 16) & 0xff);
202 *b = (ubyte) ((p >> 24) & 0xff);
203 *a = (ubyte) ((p >> 0) & 0xff);
204 }
205 return;
206 case PIPE_FORMAT_X8R8G8B8_UNORM:
207 {
208 uint p = uc->ui;
209 *r = (ubyte) ((p >> 8) & 0xff);
210 *g = (ubyte) ((p >> 16) & 0xff);
211 *b = (ubyte) ((p >> 24) & 0xff);
212 *a = (ubyte) 0xff;
213 }
214 return;
215 case PIPE_FORMAT_B5G6R5_UNORM:
216 {
217 ushort p = uc->us;
218 *r = (ubyte) (((p >> 8) & 0xf8) | ((p >> 13) & 0x7));
219 *g = (ubyte) (((p >> 3) & 0xfc) | ((p >> 9) & 0x3));
220 *b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7));
221 *a = (ubyte) 0xff;
222 }
223 return;
224 case PIPE_FORMAT_B5G5R5X1_UNORM:
225 {
226 ushort p = uc->us;
227 *r = (ubyte) (((p >> 7) & 0xf8) | ((p >> 12) & 0x7));
228 *g = (ubyte) (((p >> 2) & 0xf8) | ((p >> 7) & 0x7));
229 *b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7));
230 *a = (ubyte) 0xff;
231 }
232 return;
233 case PIPE_FORMAT_B5G5R5A1_UNORM:
234 {
235 ushort p = uc->us;
236 *r = (ubyte) (((p >> 7) & 0xf8) | ((p >> 12) & 0x7));
237 *g = (ubyte) (((p >> 2) & 0xf8) | ((p >> 7) & 0x7));
238 *b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7));
239 *a = (ubyte) (0xff * (p >> 15));
240 }
241 return;
242 case PIPE_FORMAT_B4G4R4A4_UNORM:
243 {
244 ushort p = uc->us;
245 *r = (ubyte) (((p >> 4) & 0xf0) | ((p >> 8) & 0xf));
246 *g = (ubyte) (((p >> 0) & 0xf0) | ((p >> 4) & 0xf));
247 *b = (ubyte) (((p << 4) & 0xf0) | ((p >> 0) & 0xf));
248 *a = (ubyte) (((p >> 8) & 0xf0) | ((p >> 12) & 0xf));
249 }
250 return;
251 case PIPE_FORMAT_A8_UNORM:
252 {
253 ubyte p = uc->ub;
254 *r = *g = *b = (ubyte) 0xff;
255 *a = p;
256 }
257 return;
258 case PIPE_FORMAT_L8_UNORM:
259 {
260 ubyte p = uc->ub;
261 *r = *g = *b = p;
262 *a = (ubyte) 0xff;
263 }
264 return;
265 case PIPE_FORMAT_I8_UNORM:
266 {
267 ubyte p = uc->ub;
268 *r = *g = *b = *a = p;
269 }
270 return;
271 case PIPE_FORMAT_R32G32B32A32_FLOAT:
272 {
273 const float *p = &uc->f[0];
274 *r = float_to_ubyte(p[0]);
275 *g = float_to_ubyte(p[1]);
276 *b = float_to_ubyte(p[2]);
277 *a = float_to_ubyte(p[3]);
278 }
279 return;
280 case PIPE_FORMAT_R32G32B32_FLOAT:
281 {
282 const float *p = &uc->f[0];
283 *r = float_to_ubyte(p[0]);
284 *g = float_to_ubyte(p[1]);
285 *b = float_to_ubyte(p[2]);
286 *a = (ubyte) 0xff;
287 }
288 return;
289
290 case PIPE_FORMAT_R32G32_FLOAT:
291 {
292 const float *p = &uc->f[0];
293 *r = float_to_ubyte(p[0]);
294 *g = float_to_ubyte(p[1]);
295 *b = *a = (ubyte) 0xff;
296 }
297 return;
298
299 case PIPE_FORMAT_R32_FLOAT:
300 {
301 const float *p = &uc->f[0];
302 *r = float_to_ubyte(p[0]);
303 *g = *b = *a = (ubyte) 0xff;
304 }
305 return;
306
307 /* Handle other cases with a generic function.
308 */
309 default:
310 {
311 ubyte dst[4];
312
313 util_format_read_4ub(format, dst, 0, uc, 0, 0, 0, 1, 1);
314 *r = dst[0];
315 *g = dst[1];
316 *b = dst[2];
317 *a = dst[3];
318 }
319 }
320 }
321
322
323 /**
324 * Note rgba outside [0,1] will be clamped for int pixel formats.
325 */
326 static INLINE void
327 util_pack_color(const float rgba[4], enum pipe_format format, union util_color *uc)
328 {
329 ubyte r = 0;
330 ubyte g = 0;
331 ubyte b = 0;
332 ubyte a = 0;
333
334 if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 0) <= 8) {
335 /* format uses 8-bit components or less */
336 r = float_to_ubyte(rgba[0]);
337 g = float_to_ubyte(rgba[1]);
338 b = float_to_ubyte(rgba[2]);
339 a = float_to_ubyte(rgba[3]);
340 }
341
342 switch (format) {
343 case PIPE_FORMAT_A8B8G8R8_UNORM:
344 {
345 uc->ui = (r << 24) | (g << 16) | (b << 8) | a;
346 }
347 return;
348 case PIPE_FORMAT_X8B8G8R8_UNORM:
349 {
350 uc->ui = (r << 24) | (g << 16) | (b << 8) | 0xff;
351 }
352 return;
353 case PIPE_FORMAT_B8G8R8A8_UNORM:
354 {
355 uc->ui = (a << 24) | (r << 16) | (g << 8) | b;
356 }
357 return;
358 case PIPE_FORMAT_B8G8R8X8_UNORM:
359 {
360 uc->ui = (0xff << 24) | (r << 16) | (g << 8) | b;
361 }
362 return;
363 case PIPE_FORMAT_A8R8G8B8_UNORM:
364 {
365 uc->ui = (b << 24) | (g << 16) | (r << 8) | a;
366 }
367 return;
368 case PIPE_FORMAT_X8R8G8B8_UNORM:
369 {
370 uc->ui = (b << 24) | (g << 16) | (r << 8) | 0xff;
371 }
372 return;
373 case PIPE_FORMAT_B5G6R5_UNORM:
374 {
375 uc->us = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3);
376 }
377 return;
378 case PIPE_FORMAT_B5G5R5X1_UNORM:
379 {
380 uc->us = ((0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3);
381 }
382 return;
383 case PIPE_FORMAT_B5G5R5A1_UNORM:
384 {
385 uc->us = ((a & 0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3);
386 }
387 return;
388 case PIPE_FORMAT_B4G4R4A4_UNORM:
389 {
390 uc->ub = ((a & 0xf0) << 8) | ((r & 0xf0) << 4) | ((g & 0xf0) << 0) | (b >> 4);
391 }
392 return;
393 case PIPE_FORMAT_A8_UNORM:
394 {
395 uc->ub = a;
396 }
397 return;
398 case PIPE_FORMAT_L8_UNORM:
399 case PIPE_FORMAT_I8_UNORM:
400 {
401 uc->ub = r;
402 }
403 return;
404 case PIPE_FORMAT_R32G32B32A32_FLOAT:
405 {
406 uc->f[0] = rgba[0];
407 uc->f[1] = rgba[1];
408 uc->f[2] = rgba[2];
409 uc->f[3] = rgba[3];
410 }
411 return;
412 case PIPE_FORMAT_R32G32B32_FLOAT:
413 {
414 uc->f[0] = rgba[0];
415 uc->f[1] = rgba[1];
416 uc->f[2] = rgba[2];
417 }
418 return;
419
420 /* Handle other cases with a generic function.
421 */
422 default:
423 util_format_write_4f(format, rgba, 0, uc, 0, 0, 0, 1, 1);
424 }
425 }
426
427
428 /**
429 * Note: it's assumed that z is in [0,1]
430 */
431 static INLINE uint
432 util_pack_z(enum pipe_format format, double z)
433 {
434 if (z == 0.0)
435 return 0;
436
437 switch (format) {
438 case PIPE_FORMAT_Z16_UNORM:
439 if (z == 1.0)
440 return 0xffff;
441 return (uint) (z * 0xffff);
442 case PIPE_FORMAT_Z32_UNORM:
443 /* special-case to avoid overflow */
444 if (z == 1.0)
445 return 0xffffffff;
446 return (uint) (z * 0xffffffff);
447 case PIPE_FORMAT_Z32_FLOAT:
448 return (uint)z;
449 case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
450 case PIPE_FORMAT_Z24X8_UNORM:
451 if (z == 1.0)
452 return 0xffffff;
453 return (uint) (z * 0xffffff);
454 case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
455 case PIPE_FORMAT_X8Z24_UNORM:
456 if (z == 1.0)
457 return 0xffffff00;
458 return ((uint) (z * 0xffffff)) << 8;
459 case PIPE_FORMAT_S8_USCALED:
460 /* this case can get it via util_pack_z_stencil() */
461 return 0;
462 default:
463 debug_print_format("gallium: unhandled format in util_pack_z()", format);
464 assert(0);
465 return 0;
466 }
467 }
468
469
470 /**
471 * Pack Z and/or stencil values into a 32-bit value described by format.
472 * Note: it's assumed that z is in [0,1] and s in [0,255]
473 */
474 static INLINE uint
475 util_pack_z_stencil(enum pipe_format format, double z, uint s)
476 {
477 unsigned packed = util_pack_z(format, z);
478
479 switch (format) {
480 case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
481 packed |= s << 24;
482 break;
483 case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
484 packed |= s;
485 break;
486 case PIPE_FORMAT_S8_USCALED:
487 packed |= s;
488 break;
489 default:
490 break;
491 }
492
493 return packed;
494 }
495
496
497 /**
498 * Pack 4 ubytes into a 4-byte word
499 */
500 static INLINE unsigned
501 pack_ub4(ubyte b0, ubyte b1, ubyte b2, ubyte b3)
502 {
503 return ((((unsigned int)b0) << 0) |
504 (((unsigned int)b1) << 8) |
505 (((unsigned int)b2) << 16) |
506 (((unsigned int)b3) << 24));
507 }
508
509
510 /**
511 * Pack/convert 4 floats into one 4-byte word.
512 */
513 static INLINE unsigned
514 pack_ui32_float4(float a, float b, float c, float d)
515 {
516 return pack_ub4( float_to_ubyte(a),
517 float_to_ubyte(b),
518 float_to_ubyte(c),
519 float_to_ubyte(d) );
520 }
521
522
523
524 #endif /* U_PACK_COLOR_H */