Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3770 Serge 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_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;
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
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 = (r << 24) | (g << 16) | (b << 8) | a;
71
      }
72
      return;
73
   case PIPE_FORMAT_XBGR8888_UNORM:
74
      {
75
         uc->ui = (r << 24) | (g << 16) | (b << 8) | 0xff;
76
      }
77
      return;
78
   case PIPE_FORMAT_BGRA8888_UNORM:
79
      {
80
         uc->ui = (a << 24) | (r << 16) | (g << 8) | b;
81
      }
82
      return;
83
   case PIPE_FORMAT_BGRX8888_UNORM:
84
      {
85
         uc->ui = (0xff << 24) | (r << 16) | (g << 8) | b;
86
      }
87
      return;
88
   case PIPE_FORMAT_ARGB8888_UNORM:
89
      {
90
         uc->ui = (b << 24) | (g << 16) | (r << 8) | a;
91
      }
92
      return;
93
   case PIPE_FORMAT_XRGB8888_UNORM:
94
      {
95
         uc->ui = (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
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;
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;
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;
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;
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;
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;
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
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 = (r << 24) | (g << 16) | (b << 8) | a;
356
      }
357
      return;
358
   case PIPE_FORMAT_XBGR8888_UNORM:
359
      {
360
         uc->ui = (r << 24) | (g << 16) | (b << 8) | 0xff;
361
      }
362
      return;
363
   case PIPE_FORMAT_BGRA8888_UNORM:
364
      {
365
         uc->ui = (a << 24) | (r << 16) | (g << 8) | b;
366
      }
367
      return;
368
   case PIPE_FORMAT_BGRX8888_UNORM:
369
      {
370
         uc->ui = (0xff << 24) | (r << 16) | (g << 8) | b;
371
      }
372
      return;
373
   case PIPE_FORMAT_ARGB8888_UNORM:
374
      {
375
         uc->ui = (b << 24) | (g << 16) | (r << 8) | a;
376
      }
377
      return;
378
   case PIPE_FORMAT_XRGB8888_UNORM:
379
      {
380
         uc->ui = (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
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
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
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
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
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) (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) (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) (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) (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
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
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
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
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
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 */