Home | History | Annotate | Line # | Download | only in format
      1 /**************************************************************************
      2  *
      3  * Copyright 2010 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  * Pixel format accessor functions.
     31  *
     32  * @author Jose Fonseca <jfonseca (at) vmware.com>
     33  */
     34 
     35 #include "util/format/u_format.h"
     36 #include "util/format/u_format_s3tc.h"
     37 #include "util/u_cpu_detect.h"
     38 #include "util/u_math.h"
     39 
     40 #include "pipe/p_defines.h"
     41 #include "pipe/p_screen.h"
     42 
     43 
     44 /**
     45  * Copy 2D rect from one place to another.
     46  * Position and sizes are in pixels.
     47  * src_stride may be negative to do vertical flip of pixels from source.
     48  */
     49 void
     50 util_copy_rect(ubyte * dst,
     51                enum pipe_format format,
     52                unsigned dst_stride,
     53                unsigned dst_x,
     54                unsigned dst_y,
     55                unsigned width,
     56                unsigned height,
     57                const ubyte * src,
     58                int src_stride,
     59                unsigned src_x,
     60                unsigned src_y)
     61 {
     62    unsigned i;
     63    int src_stride_pos = src_stride < 0 ? -src_stride : src_stride;
     64    int blocksize = util_format_get_blocksize(format);
     65    int blockwidth = util_format_get_blockwidth(format);
     66    int blockheight = util_format_get_blockheight(format);
     67 
     68    assert(blocksize > 0);
     69    assert(blockwidth > 0);
     70    assert(blockheight > 0);
     71 
     72    dst_x /= blockwidth;
     73    dst_y /= blockheight;
     74    width = (width + blockwidth - 1)/blockwidth;
     75    height = (height + blockheight - 1)/blockheight;
     76    src_x /= blockwidth;
     77    src_y /= blockheight;
     78 
     79    dst += dst_x * blocksize;
     80    src += src_x * blocksize;
     81    dst += dst_y * dst_stride;
     82    src += src_y * src_stride_pos;
     83    width *= blocksize;
     84 
     85    if (width == dst_stride && width == (unsigned)src_stride)
     86       memcpy(dst, src, height * width);
     87    else {
     88       for (i = 0; i < height; i++) {
     89          memcpy(dst, src, width);
     90          dst += dst_stride;
     91          src += src_stride;
     92       }
     93    }
     94 }
     95 
     96 
     97 boolean
     98 util_format_is_float(enum pipe_format format)
     99 {
    100    const struct util_format_description *desc = util_format_description(format);
    101    int i;
    102 
    103    assert(desc);
    104    if (!desc) {
    105       return FALSE;
    106    }
    107 
    108    i = util_format_get_first_non_void_channel(format);
    109    if (i < 0) {
    110       return FALSE;
    111    }
    112 
    113    return desc->channel[i].type == UTIL_FORMAT_TYPE_FLOAT ? TRUE : FALSE;
    114 }
    115 
    116 
    117 /** Test if the format contains RGB, but not alpha */
    118 boolean
    119 util_format_has_alpha(enum pipe_format format)
    120 {
    121    const struct util_format_description *desc =
    122       util_format_description(format);
    123 
    124    return (desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
    125            desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
    126           desc->swizzle[3] != PIPE_SWIZZLE_1;
    127 }
    128 
    129 /** Test if format has alpha as 1 (like RGBX) */
    130 boolean
    131 util_format_has_alpha1(enum pipe_format format)
    132 {
    133    const struct util_format_description *desc =
    134       util_format_description(format);
    135 
    136    return (desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
    137            desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
    138            desc->nr_channels == 4 &&
    139            desc->swizzle[3] == PIPE_SWIZZLE_1;
    140 }
    141 
    142 boolean
    143 util_format_is_luminance(enum pipe_format format)
    144 {
    145    const struct util_format_description *desc =
    146       util_format_description(format);
    147 
    148    if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
    149         desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
    150        desc->swizzle[0] == PIPE_SWIZZLE_X &&
    151        desc->swizzle[1] == PIPE_SWIZZLE_X &&
    152        desc->swizzle[2] == PIPE_SWIZZLE_X &&
    153        desc->swizzle[3] == PIPE_SWIZZLE_1) {
    154       return TRUE;
    155    }
    156    return FALSE;
    157 }
    158 
    159 boolean
    160 util_format_is_alpha(enum pipe_format format)
    161 {
    162    const struct util_format_description *desc =
    163       util_format_description(format);
    164 
    165    if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
    166         desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
    167        desc->swizzle[0] == PIPE_SWIZZLE_0 &&
    168        desc->swizzle[1] == PIPE_SWIZZLE_0 &&
    169        desc->swizzle[2] == PIPE_SWIZZLE_0 &&
    170        desc->swizzle[3] == PIPE_SWIZZLE_X) {
    171       return TRUE;
    172    }
    173    return FALSE;
    174 }
    175 
    176 boolean
    177 util_format_is_pure_integer(enum pipe_format format)
    178 {
    179    const struct util_format_description *desc = util_format_description(format);
    180    int i;
    181 
    182    /* Find the first non-void channel. */
    183    i = util_format_get_first_non_void_channel(format);
    184    if (i == -1)
    185       return FALSE;
    186 
    187    return desc->channel[i].pure_integer ? TRUE : FALSE;
    188 }
    189 
    190 boolean
    191 util_format_is_pure_sint(enum pipe_format format)
    192 {
    193    const struct util_format_description *desc = util_format_description(format);
    194    int i;
    195 
    196    i = util_format_get_first_non_void_channel(format);
    197    if (i == -1)
    198       return FALSE;
    199 
    200    return (desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED && desc->channel[i].pure_integer) ? TRUE : FALSE;
    201 }
    202 
    203 boolean
    204 util_format_is_pure_uint(enum pipe_format format)
    205 {
    206    const struct util_format_description *desc = util_format_description(format);
    207    int i;
    208 
    209    i = util_format_get_first_non_void_channel(format);
    210    if (i == -1)
    211       return FALSE;
    212 
    213    return (desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED && desc->channel[i].pure_integer) ? TRUE : FALSE;
    214 }
    215 
    216 /**
    217  * Returns true if the format contains normalized signed channels.
    218  */
    219 boolean
    220 util_format_is_snorm(enum pipe_format format)
    221 {
    222    const struct util_format_description *desc = util_format_description(format);
    223 
    224    return desc->is_snorm;
    225 }
    226 
    227 /**
    228  * Returns true if the format contains normalized unsigned channels.
    229  */
    230 boolean
    231 util_format_is_unorm(enum pipe_format format)
    232 {
    233    const struct util_format_description *desc = util_format_description(format);
    234 
    235    return desc->is_unorm;
    236 }
    237 
    238 /**
    239  * Returns true if the format contains scaled integer format channels.
    240  */
    241 boolean
    242 util_format_is_scaled(enum pipe_format format)
    243 {
    244    const struct util_format_description *desc = util_format_description(format);
    245    int i;
    246 
    247    /* format none is described as scaled but not for this check */
    248    if (format == PIPE_FORMAT_NONE)
    249       return FALSE;
    250 
    251    /* Find the first non-void channel. */
    252    i = util_format_get_first_non_void_channel(format);
    253    if (i == -1)
    254       return FALSE;
    255 
    256    return !desc->channel[i].pure_integer && !desc->channel[i].normalized &&
    257       (desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED ||
    258        desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED);
    259 }
    260 
    261 boolean
    262 util_format_is_snorm8(enum pipe_format format)
    263 {
    264    const struct util_format_description *desc = util_format_description(format);
    265    int i;
    266 
    267    if (desc->is_mixed)
    268       return FALSE;
    269 
    270    i = util_format_get_first_non_void_channel(format);
    271    if (i == -1)
    272       return FALSE;
    273 
    274    return desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED &&
    275           !desc->channel[i].pure_integer &&
    276           desc->channel[i].normalized &&
    277           desc->channel[i].size == 8;
    278 }
    279 
    280 boolean
    281 util_format_is_luminance_alpha(enum pipe_format format)
    282 {
    283    const struct util_format_description *desc =
    284       util_format_description(format);
    285 
    286    if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
    287         desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
    288        desc->swizzle[0] == PIPE_SWIZZLE_X &&
    289        desc->swizzle[1] == PIPE_SWIZZLE_X &&
    290        desc->swizzle[2] == PIPE_SWIZZLE_X &&
    291        desc->swizzle[3] == PIPE_SWIZZLE_Y) {
    292       return TRUE;
    293    }
    294    return FALSE;
    295 }
    296 
    297 
    298 boolean
    299 util_format_is_intensity(enum pipe_format format)
    300 {
    301    const struct util_format_description *desc =
    302       util_format_description(format);
    303 
    304    if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
    305         desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
    306        desc->swizzle[0] == PIPE_SWIZZLE_X &&
    307        desc->swizzle[1] == PIPE_SWIZZLE_X &&
    308        desc->swizzle[2] == PIPE_SWIZZLE_X &&
    309        desc->swizzle[3] == PIPE_SWIZZLE_X) {
    310       return TRUE;
    311    }
    312    return FALSE;
    313 }
    314 
    315 boolean
    316 util_format_is_subsampled_422(enum pipe_format format)
    317 {
    318    const struct util_format_description *desc =
    319       util_format_description(format);
    320 
    321    return desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED &&
    322       desc->block.width == 2 &&
    323       desc->block.height == 1 &&
    324       desc->block.bits == 32;
    325 }
    326 
    327 /**
    328  * Calculates the MRD for the depth format. MRD is used in depth bias
    329  * for UNORM and unbound depth buffers. When the depth buffer is floating
    330  * point, the depth bias calculation does not use the MRD. However, the
    331  * default MRD will be 1.0 / ((1 << 24) - 1).
    332  */
    333 double
    334 util_get_depth_format_mrd(const struct util_format_description *desc)
    335 {
    336    /*
    337     * Depth buffer formats without a depth component OR scenarios
    338     * without a bound depth buffer default to D24.
    339     */
    340    double mrd = 1.0 / ((1 << 24) - 1);
    341    unsigned depth_channel;
    342 
    343    assert(desc);
    344 
    345    /*
    346     * Some depth formats do not store the depth component in the first
    347     * channel, detect the format and adjust the depth channel. Get the
    348     * swizzled depth component channel.
    349     */
    350    depth_channel = desc->swizzle[0];
    351 
    352    if (desc->channel[depth_channel].type == UTIL_FORMAT_TYPE_UNSIGNED &&
    353        desc->channel[depth_channel].normalized) {
    354       int depth_bits;
    355 
    356       depth_bits = desc->channel[depth_channel].size;
    357       mrd = 1.0 / ((1ULL << depth_bits) - 1);
    358    }
    359 
    360    return mrd;
    361 }
    362 
    363 void
    364 util_format_unpack_rgba_rect(enum pipe_format format,
    365                    void *dst, unsigned dst_stride,
    366                    const void *src, unsigned src_stride,
    367                    unsigned w, unsigned h)
    368 {
    369    const struct util_format_unpack_description *unpack =
    370       util_format_unpack_description(format);
    371 
    372    /* Optimized function for block-compressed formats */
    373    if (unpack->unpack_rgba_rect) {
    374       unpack->unpack_rgba_rect(dst, dst_stride, src, src_stride, w, h);
    375    } else {
    376      for (unsigned y = 0; y < h; y++) {
    377         unpack->unpack_rgba(dst, src, w);
    378         src = (const char *)src + src_stride;
    379         dst = (char *)dst + dst_stride;
    380      }
    381   }
    382 }
    383 
    384 void
    385 util_format_unpack_rgba_8unorm_rect(enum pipe_format format,
    386                    void *dst, unsigned dst_stride,
    387                    const void *src, unsigned src_stride,
    388                    unsigned w, unsigned h)
    389 {
    390    const struct util_format_unpack_description *unpack =
    391       util_format_unpack_description(format);
    392 
    393    /* Optimized function for block-compressed formats */
    394    if (unpack->unpack_rgba_8unorm_rect) {
    395       unpack->unpack_rgba_8unorm_rect(dst, dst_stride, src, src_stride, w, h);
    396    } else {
    397      for (unsigned y = 0; y < h; y++) {
    398         unpack->unpack_rgba_8unorm(dst, src, w);
    399         src = (const char *)src + src_stride;
    400         dst = (char *)dst + dst_stride;
    401      }
    402   }
    403 }
    404 
    405 void
    406 util_format_read_4(enum pipe_format format,
    407                    void *dst, unsigned dst_stride,
    408                    const void *src, unsigned src_stride,
    409                    unsigned x, unsigned y, unsigned w, unsigned h)
    410 {
    411    const struct util_format_description *format_desc;
    412    const uint8_t *src_row;
    413 
    414    format_desc = util_format_description(format);
    415 
    416    assert(x % format_desc->block.width == 0);
    417    assert(y % format_desc->block.height == 0);
    418 
    419    src_row = (const uint8_t *)src + y*src_stride + x*(format_desc->block.bits/8);
    420 
    421    util_format_unpack_rgba_rect(format, dst, dst_stride, src_row, src_stride, w, h);
    422 }
    423 
    424 
    425 void
    426 util_format_write_4(enum pipe_format format,
    427                      const void *src, unsigned src_stride,
    428                      void *dst, unsigned dst_stride,
    429                      unsigned x, unsigned y, unsigned w, unsigned h)
    430 {
    431    const struct util_format_description *format_desc;
    432    const struct util_format_pack_description *pack =
    433       util_format_pack_description(format);
    434    uint8_t *dst_row;
    435 
    436    format_desc = util_format_description(format);
    437 
    438    assert(x % format_desc->block.width == 0);
    439    assert(y % format_desc->block.height == 0);
    440 
    441    dst_row = (uint8_t *)dst + y*dst_stride + x*(format_desc->block.bits/8);
    442 
    443    if (util_format_is_pure_uint(format))
    444       pack->pack_rgba_uint(dst_row, dst_stride, src, src_stride, w, h);
    445    else if (util_format_is_pure_sint(format))
    446       pack->pack_rgba_sint(dst_row, dst_stride, src, src_stride, w, h);
    447    else
    448       pack->pack_rgba_float(dst_row, dst_stride, src, src_stride, w, h);
    449 }
    450 
    451 
    452 void
    453 util_format_read_4ub(enum pipe_format format, uint8_t *dst, unsigned dst_stride, const void *src, unsigned src_stride, unsigned x, unsigned y, unsigned w, unsigned h)
    454 {
    455    const struct util_format_description *format_desc;
    456    const uint8_t *src_row;
    457 
    458    format_desc = util_format_description(format);
    459 
    460    assert(x % format_desc->block.width == 0);
    461    assert(y % format_desc->block.height == 0);
    462 
    463    src_row = (const uint8_t *)src + y*src_stride + x*(format_desc->block.bits/8);
    464 
    465    util_format_unpack_rgba_8unorm_rect(format, dst, dst_stride, src_row, src_stride, w, h);
    466 }
    467 
    468 
    469 void
    470 util_format_write_4ub(enum pipe_format format, const uint8_t *src, unsigned src_stride, void *dst, unsigned dst_stride, unsigned x, unsigned y, unsigned w, unsigned h)
    471 {
    472    const struct util_format_description *format_desc;
    473    const struct util_format_pack_description *pack =
    474       util_format_pack_description(format);
    475    uint8_t *dst_row;
    476    const uint8_t *src_row;
    477 
    478    format_desc = util_format_description(format);
    479 
    480    assert(x % format_desc->block.width == 0);
    481    assert(y % format_desc->block.height == 0);
    482 
    483    dst_row = (uint8_t *)dst + y*dst_stride + x*(format_desc->block.bits/8);
    484    src_row = src;
    485 
    486    pack->pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, w, h);
    487 }
    488 
    489 /**
    490  * Check if we can safely memcopy from the source format to the dest format.
    491  * This basically covers the cases of a "used" channel copied to a typeless
    492  * channel, plus some 1-channel cases.
    493  * Examples of compatible copy formats include:
    494  *    b8g8r8a8_unorm -> b8g8r8x8_unorm
    495  *    a8r8g8b8_unorm -> x8r8g8b8_unorm
    496  *    b5g5r5a1_unorm -> b5g5r5x1_unorm
    497  *    b4g4r4a4_unorm -> b4g4r4x4_unorm
    498  *    l8_unorm -> r8_unorm
    499  *    i8_unorm -> l8_unorm
    500  *    i8_unorm -> a8_unorm
    501  *    i8_unorm -> r8_unorm
    502  *    l16_unorm -> r16_unorm
    503  *    z24_unorm_s8_uint -> z24x8_unorm
    504  *    s8_uint_z24_unorm -> x8z24_unorm
    505  *    r8g8b8a8_unorm -> r8g8b8x8_unorm
    506  *    a8b8g8r8_srgb -> x8b8g8r8_srgb
    507  *    b8g8r8a8_srgb -> b8g8r8x8_srgb
    508  *    a8r8g8b8_srgb -> x8r8g8b8_srgb
    509  *    a8b8g8r8_unorm -> x8b8g8r8_unorm
    510  *    r10g10b10a2_uscaled -> r10g10b10x2_uscaled
    511  *    r10sg10sb10sa2u_norm -> r10g10b10x2_snorm
    512  */
    513 boolean
    514 util_is_format_compatible(const struct util_format_description *src_desc,
    515                           const struct util_format_description *dst_desc)
    516 {
    517    unsigned chan;
    518 
    519    if (src_desc->format == dst_desc->format) {
    520       return TRUE;
    521    }
    522 
    523    if (src_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN ||
    524        dst_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN) {
    525       return FALSE;
    526    }
    527 
    528    if (src_desc->block.bits != dst_desc->block.bits ||
    529        src_desc->nr_channels != dst_desc->nr_channels ||
    530        src_desc->colorspace != dst_desc->colorspace) {
    531       return FALSE;
    532    }
    533 
    534    for (chan = 0; chan < 4; ++chan) {
    535       if (src_desc->channel[chan].size !=
    536           dst_desc->channel[chan].size) {
    537          return FALSE;
    538       }
    539    }
    540 
    541    for (chan = 0; chan < 4; ++chan) {
    542       enum pipe_swizzle swizzle = dst_desc->swizzle[chan];
    543 
    544       if (swizzle < 4) {
    545          if (src_desc->swizzle[chan] != swizzle) {
    546             return FALSE;
    547          }
    548          if ((src_desc->channel[swizzle].type !=
    549               dst_desc->channel[swizzle].type) ||
    550              (src_desc->channel[swizzle].normalized !=
    551               dst_desc->channel[swizzle].normalized)) {
    552             return FALSE;
    553          }
    554       }
    555    }
    556 
    557    return TRUE;
    558 }
    559 
    560 
    561 boolean
    562 util_format_fits_8unorm(const struct util_format_description *format_desc)
    563 {
    564    unsigned chan;
    565 
    566    /*
    567     * After linearized sRGB values require more than 8bits.
    568     */
    569 
    570    if (format_desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) {
    571       return FALSE;
    572    }
    573 
    574    switch (format_desc->layout) {
    575 
    576    case UTIL_FORMAT_LAYOUT_S3TC:
    577       /*
    578        * These are straight forward.
    579        */
    580       return TRUE;
    581    case UTIL_FORMAT_LAYOUT_RGTC:
    582       if (format_desc->format == PIPE_FORMAT_RGTC1_SNORM ||
    583           format_desc->format == PIPE_FORMAT_RGTC2_SNORM ||
    584           format_desc->format == PIPE_FORMAT_LATC1_SNORM ||
    585           format_desc->format == PIPE_FORMAT_LATC2_SNORM)
    586          return FALSE;
    587       return TRUE;
    588    case UTIL_FORMAT_LAYOUT_BPTC:
    589       if (format_desc->format == PIPE_FORMAT_BPTC_RGBA_UNORM)
    590          return TRUE;
    591       return FALSE;
    592 
    593    case UTIL_FORMAT_LAYOUT_ETC:
    594       if (format_desc->format == PIPE_FORMAT_ETC1_RGB8)
    595          return TRUE;
    596       return FALSE;
    597 
    598    case UTIL_FORMAT_LAYOUT_PLAIN:
    599       /*
    600        * For these we can find a generic rule.
    601        */
    602 
    603       for (chan = 0; chan < format_desc->nr_channels; ++chan) {
    604          switch (format_desc->channel[chan].type) {
    605          case UTIL_FORMAT_TYPE_VOID:
    606             break;
    607          case UTIL_FORMAT_TYPE_UNSIGNED:
    608             if (!format_desc->channel[chan].normalized ||
    609                 format_desc->channel[chan].size > 8) {
    610                return FALSE;
    611             }
    612             break;
    613          default:
    614             return FALSE;
    615          }
    616       }
    617       return TRUE;
    618 
    619    default:
    620       /*
    621        * Handle all others on a case by case basis.
    622        */
    623 
    624       switch (format_desc->format) {
    625       case PIPE_FORMAT_R1_UNORM:
    626       case PIPE_FORMAT_UYVY:
    627       case PIPE_FORMAT_YUYV:
    628       case PIPE_FORMAT_R8G8_B8G8_UNORM:
    629       case PIPE_FORMAT_G8R8_G8B8_UNORM:
    630          return TRUE;
    631 
    632       default:
    633          return FALSE;
    634       }
    635    }
    636 }
    637 
    638 
    639 boolean
    640 util_format_translate(enum pipe_format dst_format,
    641                       void *dst, unsigned dst_stride,
    642                       unsigned dst_x, unsigned dst_y,
    643                       enum pipe_format src_format,
    644                       const void *src, unsigned src_stride,
    645                       unsigned src_x, unsigned src_y,
    646                       unsigned width, unsigned height)
    647 {
    648    const struct util_format_description *dst_format_desc;
    649    const struct util_format_description *src_format_desc;
    650    const struct util_format_pack_description *pack =
    651       util_format_pack_description(dst_format);
    652    const struct util_format_unpack_description *unpack =
    653       util_format_unpack_description(src_format);
    654    uint8_t *dst_row;
    655    const uint8_t *src_row;
    656    unsigned x_step, y_step;
    657    unsigned dst_step;
    658    unsigned src_step;
    659 
    660    dst_format_desc = util_format_description(dst_format);
    661    src_format_desc = util_format_description(src_format);
    662 
    663    if (util_is_format_compatible(src_format_desc, dst_format_desc)) {
    664       /*
    665        * Trivial case.
    666        */
    667 
    668       util_copy_rect(dst, dst_format, dst_stride,  dst_x, dst_y,
    669                      width, height, src, (int)src_stride,
    670                      src_x, src_y);
    671       return TRUE;
    672    }
    673 
    674    assert(dst_x % dst_format_desc->block.width == 0);
    675    assert(dst_y % dst_format_desc->block.height == 0);
    676    assert(src_x % src_format_desc->block.width == 0);
    677    assert(src_y % src_format_desc->block.height == 0);
    678 
    679    dst_row = (uint8_t *)dst + dst_y*dst_stride + dst_x*(dst_format_desc->block.bits/8);
    680    src_row = (const uint8_t *)src + src_y*src_stride + src_x*(src_format_desc->block.bits/8);
    681 
    682    /*
    683     * This works because all pixel formats have pixel blocks with power of two
    684     * sizes.
    685     */
    686 
    687    y_step = MAX2(dst_format_desc->block.height, src_format_desc->block.height);
    688    x_step = MAX2(dst_format_desc->block.width, src_format_desc->block.width);
    689    assert(y_step % dst_format_desc->block.height == 0);
    690    assert(y_step % src_format_desc->block.height == 0);
    691 
    692    dst_step = y_step / dst_format_desc->block.height * dst_stride;
    693    src_step = y_step / src_format_desc->block.height * src_stride;
    694 
    695    /*
    696     * TODO: double formats will loose precision
    697     * TODO: Add a special case for formats that are mere swizzles of each other
    698     */
    699 
    700    if (src_format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS ||
    701        dst_format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) {
    702       float *tmp_z = NULL;
    703       uint8_t *tmp_s = NULL;
    704 
    705       assert(x_step == 1);
    706       assert(y_step == 1);
    707 
    708       if (unpack->unpack_z_float && pack->pack_z_float) {
    709          tmp_z = malloc(width * sizeof *tmp_z);
    710       }
    711 
    712       if (unpack->unpack_s_8uint && pack->pack_s_8uint) {
    713          tmp_s = malloc(width * sizeof *tmp_s);
    714       }
    715 
    716       while (height--) {
    717          if (tmp_z) {
    718             util_format_unpack_z_float(src_format, tmp_z, src_row, width);
    719             util_format_pack_z_float(dst_format, dst_row, tmp_z, width);
    720          }
    721 
    722          if (tmp_s) {
    723             util_format_unpack_s_8uint(src_format, tmp_s, src_row, width);
    724             util_format_pack_s_8uint(dst_format, dst_row, tmp_s, width);
    725          }
    726 
    727          dst_row += dst_step;
    728          src_row += src_step;
    729       }
    730 
    731       free(tmp_s);
    732 
    733       free(tmp_z);
    734 
    735       return TRUE;
    736    }
    737 
    738    if (util_format_fits_8unorm(src_format_desc) ||
    739        util_format_fits_8unorm(dst_format_desc)) {
    740       unsigned tmp_stride;
    741       uint8_t *tmp_row;
    742 
    743       if ((!unpack->unpack_rgba_8unorm && !unpack->unpack_rgba_8unorm_rect) ||
    744           !pack->pack_rgba_8unorm) {
    745          return FALSE;
    746       }
    747 
    748       tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row;
    749       tmp_row = malloc(y_step * tmp_stride);
    750       if (!tmp_row)
    751          return FALSE;
    752 
    753       while (height >= y_step) {
    754          util_format_unpack_rgba_8unorm_rect(src_format, tmp_row, tmp_stride, src_row, src_stride, width, y_step);
    755          pack->pack_rgba_8unorm(dst_row, dst_stride, tmp_row, tmp_stride, width, y_step);
    756 
    757          dst_row += dst_step;
    758          src_row += src_step;
    759          height -= y_step;
    760       }
    761 
    762       if (height) {
    763          util_format_unpack_rgba_8unorm_rect(src_format, tmp_row, tmp_stride, src_row, src_stride, width, height);
    764          pack->pack_rgba_8unorm(dst_row, dst_stride, tmp_row, tmp_stride, width, height);
    765       }
    766 
    767       free(tmp_row);
    768    }
    769    else if (util_format_is_pure_sint(src_format) ||
    770             util_format_is_pure_sint(dst_format)) {
    771       unsigned tmp_stride;
    772       int *tmp_row;
    773 
    774       if (util_format_is_pure_sint(src_format) !=
    775           util_format_is_pure_sint(dst_format)) {
    776          return FALSE;
    777       }
    778 
    779       tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row;
    780       tmp_row = malloc(y_step * tmp_stride);
    781       if (!tmp_row)
    782          return FALSE;
    783 
    784       while (height >= y_step) {
    785          util_format_unpack_rgba_rect(src_format, tmp_row, tmp_stride, src_row, src_stride, width, y_step);
    786          pack->pack_rgba_sint(dst_row, dst_stride, tmp_row, tmp_stride, width, y_step);
    787 
    788          dst_row += dst_step;
    789          src_row += src_step;
    790          height -= y_step;
    791       }
    792 
    793       if (height) {
    794          util_format_unpack_rgba_rect(src_format, tmp_row, tmp_stride, src_row, src_stride, width, height);
    795          pack->pack_rgba_sint(dst_row, dst_stride, tmp_row, tmp_stride, width, height);
    796       }
    797 
    798       free(tmp_row);
    799    }
    800    else if (util_format_is_pure_uint(src_format) ||
    801             util_format_is_pure_uint(dst_format)) {
    802       unsigned tmp_stride;
    803       unsigned int *tmp_row;
    804 
    805       if ((!unpack->unpack_rgba && !unpack->unpack_rgba_rect) ||
    806           !pack->pack_rgba_uint) {
    807          return FALSE;
    808       }
    809 
    810       tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row;
    811       tmp_row = malloc(y_step * tmp_stride);
    812       if (!tmp_row)
    813          return FALSE;
    814 
    815       while (height >= y_step) {
    816          util_format_unpack_rgba_rect(src_format, tmp_row, tmp_stride, src_row, src_stride, width, y_step);
    817          pack->pack_rgba_uint(dst_row, dst_stride, tmp_row, tmp_stride, width, y_step);
    818 
    819          dst_row += dst_step;
    820          src_row += src_step;
    821          height -= y_step;
    822       }
    823 
    824       if (height) {
    825          util_format_unpack_rgba_rect(src_format, tmp_row, tmp_stride, src_row, src_stride, width, height);
    826          pack->pack_rgba_uint(dst_row, dst_stride, tmp_row, tmp_stride, width, height);
    827       }
    828 
    829       free(tmp_row);
    830    }
    831    else {
    832       unsigned tmp_stride;
    833       float *tmp_row;
    834 
    835       if ((!unpack->unpack_rgba && !unpack->unpack_rgba_rect) ||
    836           !pack->pack_rgba_float) {
    837          return FALSE;
    838       }
    839 
    840       tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row;
    841       tmp_row = malloc(y_step * tmp_stride);
    842       if (!tmp_row)
    843          return FALSE;
    844 
    845       while (height >= y_step) {
    846          util_format_unpack_rgba_rect(src_format, tmp_row, tmp_stride, src_row, src_stride, width, y_step);
    847          pack->pack_rgba_float(dst_row, dst_stride, tmp_row, tmp_stride, width, y_step);
    848 
    849          dst_row += dst_step;
    850          src_row += src_step;
    851          height -= y_step;
    852       }
    853 
    854       if (height) {
    855          util_format_unpack_rgba_rect(src_format, tmp_row, tmp_stride, src_row, src_stride, width, height);
    856          pack->pack_rgba_float(dst_row, dst_stride, tmp_row, tmp_stride, width, height);
    857       }
    858 
    859       free(tmp_row);
    860    }
    861    return TRUE;
    862 }
    863 
    864 boolean
    865 util_format_translate_3d(enum pipe_format dst_format,
    866                          void *dst, unsigned dst_stride,
    867                          unsigned dst_slice_stride,
    868                          unsigned dst_x, unsigned dst_y,
    869                          unsigned dst_z,
    870                          enum pipe_format src_format,
    871                          const void *src, unsigned src_stride,
    872                          unsigned src_slice_stride,
    873                          unsigned src_x, unsigned src_y,
    874                          unsigned src_z, unsigned width,
    875                          unsigned height, unsigned depth)
    876 {
    877    uint8_t *dst_layer;
    878    const uint8_t *src_layer;
    879    unsigned z;
    880    dst_layer = dst;
    881    src_layer = src;
    882    dst_layer += dst_z * dst_slice_stride;
    883    src_layer += src_z * src_slice_stride;
    884    for (z = 0; z < depth; ++z) {
    885       if (!util_format_translate(dst_format, dst_layer, dst_stride,
    886                                  dst_x, dst_y,
    887                                  src_format, src_layer, src_stride,
    888                                  src_x, src_y,
    889                                  width, height))
    890           return FALSE;
    891 
    892       dst_layer += dst_slice_stride;
    893       src_layer += src_slice_stride;
    894    }
    895    return TRUE;
    896 }
    897 
    898 void util_format_compose_swizzles(const unsigned char swz1[4],
    899                                   const unsigned char swz2[4],
    900                                   unsigned char dst[4])
    901 {
    902    unsigned i;
    903 
    904    for (i = 0; i < 4; i++) {
    905       dst[i] = swz2[i] <= PIPE_SWIZZLE_W ?
    906                swz1[swz2[i]] : swz2[i];
    907    }
    908 }
    909 
    910 void util_format_apply_color_swizzle(union pipe_color_union *dst,
    911                                      const union pipe_color_union *src,
    912                                      const unsigned char swz[4],
    913                                      const boolean is_integer)
    914 {
    915    unsigned c;
    916 
    917    if (is_integer) {
    918       for (c = 0; c < 4; ++c) {
    919          switch (swz[c]) {
    920          case PIPE_SWIZZLE_X:   dst->ui[c] = src->ui[0]; break;
    921          case PIPE_SWIZZLE_Y: dst->ui[c] = src->ui[1]; break;
    922          case PIPE_SWIZZLE_Z:  dst->ui[c] = src->ui[2]; break;
    923          case PIPE_SWIZZLE_W: dst->ui[c] = src->ui[3]; break;
    924          default:
    925             dst->ui[c] = (swz[c] == PIPE_SWIZZLE_1) ? 1 : 0;
    926             break;
    927          }
    928       }
    929    } else {
    930       for (c = 0; c < 4; ++c) {
    931          switch (swz[c]) {
    932          case PIPE_SWIZZLE_X:   dst->f[c] = src->f[0]; break;
    933          case PIPE_SWIZZLE_Y: dst->f[c] = src->f[1]; break;
    934          case PIPE_SWIZZLE_Z:  dst->f[c] = src->f[2]; break;
    935          case PIPE_SWIZZLE_W: dst->f[c] = src->f[3]; break;
    936          default:
    937             dst->f[c] = (swz[c] == PIPE_SWIZZLE_1) ? 1.0f : 0.0f;
    938             break;
    939          }
    940       }
    941    }
    942 }
    943 
    944 void pipe_swizzle_4f(float *dst, const float *src,
    945                             const unsigned char swz[4])
    946 {
    947    unsigned i;
    948 
    949    for (i = 0; i < 4; i++) {
    950       if (swz[i] <= PIPE_SWIZZLE_W)
    951          dst[i] = src[swz[i]];
    952       else if (swz[i] == PIPE_SWIZZLE_0)
    953          dst[i] = 0;
    954       else if (swz[i] == PIPE_SWIZZLE_1)
    955          dst[i] = 1;
    956    }
    957 }
    958 
    959 void util_format_unswizzle_4f(float *dst, const float *src,
    960                               const unsigned char swz[4])
    961 {
    962    unsigned i;
    963 
    964    for (i = 0; i < 4; i++) {
    965       switch (swz[i]) {
    966       case PIPE_SWIZZLE_X:
    967          dst[0] = src[i];
    968          break;
    969       case PIPE_SWIZZLE_Y:
    970          dst[1] = src[i];
    971          break;
    972       case PIPE_SWIZZLE_Z:
    973          dst[2] = src[i];
    974          break;
    975       case PIPE_SWIZZLE_W:
    976          dst[3] = src[i];
    977          break;
    978       }
    979    }
    980 }
    981 
    982 enum pipe_format
    983 util_format_snorm8_to_sint8(enum pipe_format format)
    984 {
    985    switch (format) {
    986    case PIPE_FORMAT_R8_SNORM:
    987       return PIPE_FORMAT_R8_SINT;
    988    case PIPE_FORMAT_R8G8_SNORM:
    989       return PIPE_FORMAT_R8G8_SINT;
    990    case PIPE_FORMAT_R8G8B8_SNORM:
    991       return PIPE_FORMAT_R8G8B8_SINT;
    992    case PIPE_FORMAT_R8G8B8A8_SNORM:
    993       return PIPE_FORMAT_R8G8B8A8_SINT;
    994 
    995    case PIPE_FORMAT_A8_SNORM:
    996       return PIPE_FORMAT_A8_SINT;
    997    case PIPE_FORMAT_L8_SNORM:
    998       return PIPE_FORMAT_L8_SINT;
    999    case PIPE_FORMAT_L8A8_SNORM:
   1000       return PIPE_FORMAT_L8A8_SINT;
   1001    case PIPE_FORMAT_I8_SNORM:
   1002       return PIPE_FORMAT_I8_SINT;
   1003 
   1004    case PIPE_FORMAT_R8G8B8X8_SNORM:
   1005       return PIPE_FORMAT_R8G8B8X8_SINT;
   1006    case PIPE_FORMAT_B8G8R8X8_SNORM:
   1007       return PIPE_FORMAT_B8G8R8X8_SINT;
   1008 
   1009    case PIPE_FORMAT_R8A8_SNORM:
   1010       return PIPE_FORMAT_R8A8_SINT;
   1011    case PIPE_FORMAT_G8R8_SNORM:
   1012       return PIPE_FORMAT_G8R8_SINT;
   1013 
   1014    case PIPE_FORMAT_A8R8G8B8_SNORM:
   1015       return PIPE_FORMAT_A8R8G8B8_SINT;
   1016    case PIPE_FORMAT_X8R8G8B8_SNORM:
   1017       return PIPE_FORMAT_X8R8G8B8_SINT;
   1018 
   1019    case PIPE_FORMAT_A8B8G8R8_SNORM:
   1020       return PIPE_FORMAT_A8B8G8R8_SINT;
   1021    case PIPE_FORMAT_X8B8G8R8_SNORM:
   1022       return PIPE_FORMAT_X8B8G8R8_SINT;
   1023 
   1024    case PIPE_FORMAT_R10G10B10A2_SNORM:
   1025       return PIPE_FORMAT_R10G10B10A2_SINT;
   1026    case PIPE_FORMAT_B10G10R10A2_SNORM:
   1027       return PIPE_FORMAT_B10G10R10A2_SINT;
   1028 
   1029    default:
   1030       return format;
   1031    }
   1032 }
   1033 
   1034 /**
   1035  * If the format is RGB, return BGR. If the format is BGR, return RGB.
   1036  * This may fail by returning PIPE_FORMAT_NONE.
   1037  */
   1038 enum pipe_format
   1039 util_format_rgb_to_bgr(enum pipe_format format)
   1040 {
   1041 #define REMAP_RGB_ONE(r, rs, g, gs, b, bs, type) \
   1042    case PIPE_FORMAT_##r##rs##g##gs##b##bs##_##type: \
   1043       return PIPE_FORMAT_##b##bs##g##gs##r##rs##_##type;
   1044 
   1045 #define REMAP_RGB(rs, gs, bs, type) \
   1046    REMAP_RGB_ONE(R, rs, G, gs, B, bs, type) \
   1047    REMAP_RGB_ONE(B, bs, G, gs, R, rs, type) \
   1048 
   1049 #define REMAP_RGBA_ONE(r, rs, g, gs, b, bs, a, as, type) \
   1050    case PIPE_FORMAT_##r##rs##g##gs##b##bs##a##as##_##type: \
   1051       return PIPE_FORMAT_##b##bs##g##gs##r##rs##a##as##_##type;
   1052 
   1053 #define REMAP_ARGB_ONE(a, as, r, rs, g, gs, b, bs, type) \
   1054    case PIPE_FORMAT_##a##as##r##rs##g##gs##b##bs##_##type: \
   1055       return PIPE_FORMAT_##a##as##b##bs##g##gs##r##rs##_##type;
   1056 
   1057 #define REMAP_RGB_AX(A, rs, gs, bs, as, type) \
   1058    REMAP_RGBA_ONE(R, rs, G, gs, B, bs, A, as, type) \
   1059    REMAP_RGBA_ONE(B, bs, G, gs, R, rs, A, as, type) \
   1060 
   1061 #define REMAP_AX_RGB(A, rs, gs, bs, as, type) \
   1062    REMAP_ARGB_ONE(A, as, R, rs, G, gs, B, bs, type) \
   1063    REMAP_ARGB_ONE(A, as, B, bs, G, gs, R, rs, type) \
   1064 
   1065 #define REMAP_RGBA(rs, gs, bs, as, type) REMAP_RGB_AX(A, rs, gs, bs, as, type)
   1066 #define REMAP_RGBX(rs, gs, bs, as, type) REMAP_RGB_AX(X, rs, gs, bs, as, type)
   1067 #define REMAP_ARGB(rs, gs, bs, as, type) REMAP_AX_RGB(A, rs, gs, bs, as, type)
   1068 #define REMAP_XRGB(rs, gs, bs, as, type) REMAP_AX_RGB(X, rs, gs, bs, as, type)
   1069 
   1070 #define REMAP_RGBA_ALL(rs, gs, bs, as, type) \
   1071    REMAP_RGBA(rs, gs, bs, as, type) \
   1072    REMAP_RGBX(rs, gs, bs, as, type) \
   1073    REMAP_ARGB(rs, gs, bs, as, type) \
   1074    REMAP_XRGB(rs, gs, bs, as, type)
   1075 
   1076    switch (format) {
   1077    REMAP_RGB(3, 3, 2, UNORM);
   1078    REMAP_RGB(3, 3, 2, UINT);
   1079    REMAP_RGB(5, 6, 5, SRGB);
   1080    REMAP_RGB(5, 6, 5, UNORM);
   1081    REMAP_RGB(5, 6, 5, UINT);
   1082    REMAP_RGB(8, 8, 8, SRGB);
   1083    REMAP_RGB(8, 8, 8, UNORM);
   1084    REMAP_RGB(8, 8, 8, SNORM);
   1085    REMAP_RGB(8, 8, 8, UINT);
   1086    REMAP_RGB(8, 8, 8, SINT);
   1087    REMAP_RGB(8, 8, 8, USCALED);
   1088    REMAP_RGB(8, 8, 8, SSCALED);
   1089 
   1090    /* Complete format sets. */
   1091    REMAP_RGBA_ALL(5, 5, 5, 1, UNORM);
   1092    REMAP_RGBA_ALL(8, 8, 8, 8, SRGB);
   1093    REMAP_RGBA_ALL(8, 8, 8, 8, UNORM);
   1094    REMAP_RGBA_ALL(8, 8, 8, 8, SNORM);
   1095    REMAP_RGBA_ALL(8, 8, 8, 8, SINT);
   1096 
   1097    /* Format sets missing XRGB/XBGR. */
   1098    REMAP_RGBA(4, 4, 4, 4, UNORM);
   1099    REMAP_RGBX(4, 4, 4, 4, UNORM);
   1100    REMAP_ARGB(4, 4, 4, 4, UNORM);
   1101 
   1102    REMAP_RGBA(8, 8, 8, 8, UINT);
   1103    REMAP_RGBX(8, 8, 8, 8, UINT);
   1104    REMAP_ARGB(8, 8, 8, 8, UINT);
   1105 
   1106    REMAP_RGBA(10, 10, 10, 2, UNORM);
   1107    REMAP_RGBX(10, 10, 10, 2, UNORM);
   1108    REMAP_ARGB(10, 10, 10, 2, UNORM);
   1109 
   1110    /* Format sets missing a half of combinations. */
   1111    REMAP_RGBA(4, 4, 4, 4, UINT);
   1112    REMAP_ARGB(4, 4, 4, 4, UINT);
   1113 
   1114    REMAP_RGBA(5, 5, 5, 1, UINT);
   1115    REMAP_ARGB(5, 5, 5, 1, UINT);
   1116 
   1117    REMAP_RGBA(10, 10, 10, 2, SNORM);
   1118    REMAP_RGBX(10, 10, 10, 2, SNORM);
   1119 
   1120    REMAP_RGBA(10, 10, 10, 2, UINT);
   1121    REMAP_ARGB(10, 10, 10, 2, UINT);
   1122 
   1123    /* Format sets having only RGBA/BGRA. */
   1124    REMAP_RGBA(8, 8, 8, 8, USCALED);
   1125    REMAP_RGBA(8, 8, 8, 8, SSCALED);
   1126    REMAP_RGBA(10, 10, 10, 2, SINT);
   1127    REMAP_RGBA(10, 10, 10, 2, USCALED);
   1128    REMAP_RGBA(10, 10, 10, 2, SSCALED);
   1129 
   1130    default:
   1131       return PIPE_FORMAT_NONE;
   1132    }
   1133 }
   1134 
   1135 static const struct util_format_unpack_description *util_format_unpack_table[PIPE_FORMAT_COUNT];
   1136 
   1137 static void
   1138 util_format_unpack_table_init(void)
   1139 {
   1140    for (enum pipe_format format = PIPE_FORMAT_NONE; format < PIPE_FORMAT_COUNT; format++) {
   1141 #if (defined(PIPE_ARCH_AARCH64) || defined(PIPE_ARCH_ARM)) && !defined(NO_FORMAT_ASM) && !defined(__SOFTFP__)
   1142       const struct util_format_unpack_description *unpack = util_format_unpack_description_neon(format);
   1143       if (unpack) {
   1144          util_format_unpack_table[format] = unpack;
   1145          continue;
   1146       }
   1147 #endif
   1148 
   1149       util_format_unpack_table[format] = util_format_unpack_description_generic(format);
   1150    }
   1151 }
   1152 
   1153 const struct util_format_unpack_description *
   1154 util_format_unpack_description(enum pipe_format format)
   1155 {
   1156    static once_flag flag = ONCE_FLAG_INIT;
   1157    call_once(&flag, util_format_unpack_table_init);
   1158 
   1159    return util_format_unpack_table[format];
   1160 }
   1161