Merge commit 'origin/master' into gallium-0.2
[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, g, b, a;
306
307 if (pf_size_x(format) <= 8) {
308 /* format uses 8-bit components or less */
309 r = float_to_ubyte(rgba[0]);
310 g = float_to_ubyte(rgba[1]);
311 b = float_to_ubyte(rgba[2]);
312 a = float_to_ubyte(rgba[3]);
313 }
314
315 switch (format) {
316 case PIPE_FORMAT_R8G8B8A8_UNORM:
317 {
318 uint *d = (uint *) dest;
319 *d = (r << 24) | (g << 16) | (b << 8) | a;
320 }
321 return;
322 case PIPE_FORMAT_R8G8B8X8_UNORM:
323 {
324 uint *d = (uint *) dest;
325 *d = (r << 24) | (g << 16) | (b << 8) | 0xff;
326 }
327 return;
328 case PIPE_FORMAT_A8R8G8B8_UNORM:
329 {
330 uint *d = (uint *) dest;
331 *d = (a << 24) | (r << 16) | (g << 8) | b;
332 }
333 return;
334 case PIPE_FORMAT_X8R8G8B8_UNORM:
335 {
336 uint *d = (uint *) dest;
337 *d = (0xff << 24) | (r << 16) | (g << 8) | b;
338 }
339 return;
340 case PIPE_FORMAT_B8G8R8A8_UNORM:
341 {
342 uint *d = (uint *) dest;
343 *d = (b << 24) | (g << 16) | (r << 8) | a;
344 }
345 return;
346 case PIPE_FORMAT_B8G8R8X8_UNORM:
347 {
348 uint *d = (uint *) dest;
349 *d = (b << 24) | (g << 16) | (r << 8) | 0xff;
350 }
351 return;
352 case PIPE_FORMAT_R5G6B5_UNORM:
353 {
354 ushort *d = (ushort *) dest;
355 *d = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3);
356 }
357 return;
358 case PIPE_FORMAT_A1R5G5B5_UNORM:
359 {
360 ushort *d = (ushort *) dest;
361 *d = ((a & 0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3);
362 }
363 return;
364 case PIPE_FORMAT_A4R4G4B4_UNORM:
365 {
366 ushort *d = (ushort *) dest;
367 *d = ((a & 0xf0) << 8) | ((r & 0xf0) << 4) | ((g & 0xf0) << 0) | (b >> 4);
368 }
369 return;
370 case PIPE_FORMAT_A8_UNORM:
371 {
372 ubyte *d = (ubyte *) dest;
373 *d = a;
374 }
375 return;
376 case PIPE_FORMAT_L8_UNORM:
377 case PIPE_FORMAT_I8_UNORM:
378 {
379 ubyte *d = (ubyte *) dest;
380 *d = r;
381 }
382 return;
383 case PIPE_FORMAT_R32G32B32A32_FLOAT:
384 {
385 float *d = (float *) dest;
386 d[0] = rgba[0];
387 d[1] = rgba[1];
388 d[2] = rgba[2];
389 d[3] = rgba[3];
390 }
391 return;
392 case PIPE_FORMAT_R32G32B32_FLOAT:
393 {
394 float *d = (float *) dest;
395 d[0] = rgba[0];
396 d[1] = rgba[1];
397 d[2] = rgba[2];
398 }
399 return;
400 /* XXX lots more cases to add */
401 default:
402 debug_print_format("gallium: unhandled format in util_pack_color()", format);
403 assert(0);
404 }
405 }
406
407
408 /**
409 * Note: it's assumed that z is in [0,1]
410 */
411 static INLINE uint
412 util_pack_z(enum pipe_format format, double z)
413 {
414 if (z == 0.0)
415 return 0;
416
417 switch (format) {
418 case PIPE_FORMAT_Z16_UNORM:
419 if (z == 1.0)
420 return 0xffff;
421 return (uint) (z * 0xffff);
422 case PIPE_FORMAT_Z32_UNORM:
423 /* special-case to avoid overflow */
424 if (z == 1.0)
425 return 0xffffffff;
426 return (uint) (z * 0xffffffff);
427 case PIPE_FORMAT_S8Z24_UNORM:
428 case PIPE_FORMAT_X8Z24_UNORM:
429 if (z == 1.0)
430 return 0xffffff;
431 return (uint) (z * 0xffffff);
432 case PIPE_FORMAT_Z24S8_UNORM:
433 case PIPE_FORMAT_Z24X8_UNORM:
434 if (z == 1.0)
435 return 0xffffff00;
436 return ((uint) (z * 0xffffff)) << 8;
437 default:
438 debug_print_format("gallium: unhandled format in util_pack_z()", format);
439 assert(0);
440 return 0;
441 }
442 }
443
444
445 /**
446 * Pack 4 ubytes into a 4-byte word
447 */
448 static INLINE unsigned
449 pack_ub4(ubyte b0, ubyte b1, ubyte b2, ubyte b3)
450 {
451 return ((((unsigned int)b0) << 0) |
452 (((unsigned int)b1) << 8) |
453 (((unsigned int)b2) << 16) |
454 (((unsigned int)b3) << 24));
455 }
456
457
458 /**
459 * Pack/convert 4 floats into one 4-byte word.
460 */
461 static INLINE unsigned
462 pack_ui32_float4(float a, float b, float c, float d)
463 {
464 return pack_ub4( float_to_ubyte(a),
465 float_to_ubyte(b),
466 float_to_ubyte(c),
467 float_to_ubyte(d) );
468 }
469
470
471
472 #endif /* U_PACK_COLOR_H */