Home | History | Annotate | Download | only in util
      1 /**************************************************************************
      2  *
      3  * Copyright 2008 VMware, Inc.
      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 VMWARE 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[4];
     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[0] = (r << 24) | (g << 16) | (b << 8) | a;
     71       }
     72       return;
     73    case PIPE_FORMAT_XBGR8888_UNORM:
     74       {
     75          uc->ui[0] = (r << 24) | (g << 16) | (b << 8) | 0xff;
     76       }
     77       return;
     78    case PIPE_FORMAT_BGRA8888_UNORM:
     79       {
     80          uc->ui[0] = (a << 24) | (r << 16) | (g << 8) | b;
     81       }
     82       return;
     83    case PIPE_FORMAT_BGRX8888_UNORM:
     84       {
     85          uc->ui[0] = (0xff << 24) | (r << 16) | (g << 8) | b;
     86       }
     87       return;
     88    case PIPE_FORMAT_ARGB8888_UNORM:
     89       {
     90          uc->ui[0] = (b << 24) | (g << 16) | (r << 8) | a;
     91       }
     92       return;
     93    case PIPE_FORMAT_XRGB8888_UNORM:
     94       {
     95          uc->ui[0] = (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[0];
    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[0];
    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[0];
    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[0];
    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[0];
    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[0];
    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[0] = (r << 24) | (g << 16) | (b << 8) | a;
    356       }
    357       return;
    358    case PIPE_FORMAT_XBGR8888_UNORM:
    359       {
    360          uc->ui[0] = (r << 24) | (g << 16) | (b << 8) | 0xff;
    361       }
    362       return;
    363    case PIPE_FORMAT_BGRA8888_UNORM:
    364       {
    365          uc->ui[0] = (a << 24) | (r << 16) | (g << 8) | b;
    366       }
    367       return;
    368    case PIPE_FORMAT_BGRX8888_UNORM:
    369       {
    370          uc->ui[0] = (0xffu << 24) | (r << 16) | (g << 8) | b;
    371       }
    372       return;
    373    case PIPE_FORMAT_ARGB8888_UNORM:
    374       {
    375          uc->ui[0] = (b << 24) | (g << 16) | (r << 8) | a;
    376       }
    377       return;
    378    case PIPE_FORMAT_XRGB8888_UNORM:
    379       {
    380          uc->ui[0] = (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) lrint(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) llrint(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) lrint(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) lrint(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 */
    652