u_pack_color.h revision 94abc4b51e134bee1ace2b57400e35c295bda6f8
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
45union 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 */
55static INLINE void
56util_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 */
156static INLINE void
157util_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 */
326static INLINE void
327util_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 */
431static INLINE uint
432util_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_Z24S8_UNORM:
450   case PIPE_FORMAT_Z24X8_UNORM:
451      if (z == 1.0)
452         return 0xffffff;
453      return (uint) (z * 0xffffff);
454   case PIPE_FORMAT_S8Z24_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_UNORM:
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 */
474static INLINE uint
475util_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_Z24S8_UNORM:
481      packed |= s << 24;
482      break;
483   case PIPE_FORMAT_S8Z24_UNORM:
484      packed |= s;
485      break;
486   case PIPE_FORMAT_S8_UNORM:
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 */
500static INLINE unsigned
501pack_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 */
513static INLINE unsigned
514pack_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 */
525