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