Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  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@vmware.com>
  33.  */
  34.  
  35. #include "u_math.h"
  36. #include "u_memory.h"
  37. #include "u_rect.h"
  38. #include "u_format.h"
  39. #include "u_format_s3tc.h"
  40.  
  41. #include "pipe/p_defines.h"
  42.  
  43.  
  44. boolean
  45. util_format_is_float(enum pipe_format format)
  46. {
  47.    const struct util_format_description *desc = util_format_description(format);
  48.    unsigned i;
  49.  
  50.    assert(desc);
  51.    if (!desc) {
  52.       return FALSE;
  53.    }
  54.  
  55.    i = util_format_get_first_non_void_channel(format);
  56.    if (i == -1) {
  57.       return FALSE;
  58.    }
  59.  
  60.    return desc->channel[i].type == UTIL_FORMAT_TYPE_FLOAT ? TRUE : FALSE;
  61. }
  62.  
  63.  
  64. /** Test if the format contains RGB, but not alpha */
  65. boolean
  66. util_format_has_alpha(enum pipe_format format)
  67. {
  68.    const struct util_format_description *desc =
  69.       util_format_description(format);
  70.  
  71.    return (desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
  72.            desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
  73.           desc->swizzle[3] != UTIL_FORMAT_SWIZZLE_1;
  74. }
  75.  
  76.  
  77. boolean
  78. util_format_is_luminance(enum pipe_format format)
  79. {
  80.    const struct util_format_description *desc =
  81.       util_format_description(format);
  82.  
  83.    if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
  84.         desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
  85.        desc->swizzle[0] == UTIL_FORMAT_SWIZZLE_X &&
  86.        desc->swizzle[1] == UTIL_FORMAT_SWIZZLE_X &&
  87.        desc->swizzle[2] == UTIL_FORMAT_SWIZZLE_X &&
  88.        desc->swizzle[3] == UTIL_FORMAT_SWIZZLE_1) {
  89.       return TRUE;
  90.    }
  91.    return FALSE;
  92. }
  93.  
  94. boolean
  95. util_format_is_pure_integer(enum pipe_format format)
  96. {
  97.    const struct util_format_description *desc = util_format_description(format);
  98.    int i;
  99.  
  100.    /* Find the first non-void channel. */
  101.    i = util_format_get_first_non_void_channel(format);
  102.    if (i == -1)
  103.       return FALSE;
  104.  
  105.    return desc->channel[i].pure_integer ? TRUE : FALSE;
  106. }
  107.  
  108. boolean
  109. util_format_is_pure_sint(enum pipe_format format)
  110. {
  111.    const struct util_format_description *desc = util_format_description(format);
  112.    int i;
  113.  
  114.    i = util_format_get_first_non_void_channel(format);
  115.    if (i == -1)
  116.       return FALSE;
  117.  
  118.    return (desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED && desc->channel[i].pure_integer) ? TRUE : FALSE;
  119. }
  120.  
  121. boolean
  122. util_format_is_pure_uint(enum pipe_format format)
  123. {
  124.    const struct util_format_description *desc = util_format_description(format);
  125.    int i;
  126.  
  127.    i = util_format_get_first_non_void_channel(format);
  128.    if (i == -1)
  129.       return FALSE;
  130.  
  131.    return (desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED && desc->channel[i].pure_integer) ? TRUE : FALSE;
  132. }
  133.  
  134. /**
  135.  * Returns true if all non-void channels are normalized signed.
  136.  */
  137. boolean
  138. util_format_is_snorm(enum pipe_format format)
  139. {
  140.    const struct util_format_description *desc = util_format_description(format);
  141.    int i;
  142.  
  143.    if (desc->is_mixed)
  144.       return FALSE;
  145.  
  146.    i = util_format_get_first_non_void_channel(format);
  147.    if (i == -1)
  148.       return FALSE;
  149.  
  150.    return desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED &&
  151.           !desc->channel[i].pure_integer &&
  152.           desc->channel[i].normalized;
  153. }
  154.  
  155. boolean
  156. util_format_is_luminance_alpha(enum pipe_format format)
  157. {
  158.    const struct util_format_description *desc =
  159.       util_format_description(format);
  160.  
  161.    if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
  162.         desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
  163.        desc->swizzle[0] == UTIL_FORMAT_SWIZZLE_X &&
  164.        desc->swizzle[1] == UTIL_FORMAT_SWIZZLE_X &&
  165.        desc->swizzle[2] == UTIL_FORMAT_SWIZZLE_X &&
  166.        desc->swizzle[3] == UTIL_FORMAT_SWIZZLE_Y) {
  167.       return TRUE;
  168.    }
  169.    return FALSE;
  170. }
  171.  
  172.  
  173. boolean
  174. util_format_is_intensity(enum pipe_format format)
  175. {
  176.    const struct util_format_description *desc =
  177.       util_format_description(format);
  178.  
  179.    if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
  180.         desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
  181.        desc->swizzle[0] == UTIL_FORMAT_SWIZZLE_X &&
  182.        desc->swizzle[1] == UTIL_FORMAT_SWIZZLE_X &&
  183.        desc->swizzle[2] == UTIL_FORMAT_SWIZZLE_X &&
  184.        desc->swizzle[3] == UTIL_FORMAT_SWIZZLE_X) {
  185.       return TRUE;
  186.    }
  187.    return FALSE;
  188. }
  189.  
  190.  
  191. boolean
  192. util_format_is_supported(enum pipe_format format, unsigned bind)
  193. {
  194.    if (util_format_is_s3tc(format) && !util_format_s3tc_enabled) {
  195.       return FALSE;
  196.    }
  197.  
  198. #ifndef TEXTURE_FLOAT_ENABLED
  199.    if ((bind & PIPE_BIND_RENDER_TARGET) &&
  200.        format != PIPE_FORMAT_R9G9B9E5_FLOAT &&
  201.        format != PIPE_FORMAT_R11G11B10_FLOAT &&
  202.        util_format_is_float(format)) {
  203.       return FALSE;
  204.    }
  205. #endif
  206.  
  207.    return TRUE;
  208. }
  209.  
  210.  
  211. void
  212. util_format_read_4f(enum pipe_format format,
  213.                     float *dst, unsigned dst_stride,
  214.                     const void *src, unsigned src_stride,
  215.                     unsigned x, unsigned y, unsigned w, unsigned h)
  216. {
  217.    const struct util_format_description *format_desc;
  218.    const uint8_t *src_row;
  219.    float *dst_row;
  220.  
  221.    format_desc = util_format_description(format);
  222.  
  223.    assert(x % format_desc->block.width == 0);
  224.    assert(y % format_desc->block.height == 0);
  225.  
  226.    src_row = (const uint8_t *)src + y*src_stride + x*(format_desc->block.bits/8);
  227.    dst_row = dst;
  228.  
  229.    format_desc->unpack_rgba_float(dst_row, dst_stride, src_row, src_stride, w, h);
  230. }
  231.  
  232.  
  233. void
  234. util_format_write_4f(enum pipe_format format,
  235.                      const float *src, unsigned src_stride,
  236.                      void *dst, unsigned dst_stride,
  237.                      unsigned x, unsigned y, unsigned w, unsigned h)
  238. {
  239.    const struct util_format_description *format_desc;
  240.    uint8_t *dst_row;
  241.    const float *src_row;
  242.  
  243.    format_desc = util_format_description(format);
  244.  
  245.    assert(x % format_desc->block.width == 0);
  246.    assert(y % format_desc->block.height == 0);
  247.  
  248.    dst_row = (uint8_t *)dst + y*dst_stride + x*(format_desc->block.bits/8);
  249.    src_row = src;
  250.  
  251.    format_desc->pack_rgba_float(dst_row, dst_stride, src_row, src_stride, w, h);
  252. }
  253.  
  254.  
  255. void
  256. 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)
  257. {
  258.    const struct util_format_description *format_desc;
  259.    const uint8_t *src_row;
  260.    uint8_t *dst_row;
  261.  
  262.    format_desc = util_format_description(format);
  263.  
  264.    assert(x % format_desc->block.width == 0);
  265.    assert(y % format_desc->block.height == 0);
  266.  
  267.    src_row = (const uint8_t *)src + y*src_stride + x*(format_desc->block.bits/8);
  268.    dst_row = dst;
  269.  
  270.    format_desc->unpack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, w, h);
  271. }
  272.  
  273.  
  274. void
  275. 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)
  276. {
  277.    const struct util_format_description *format_desc;
  278.    uint8_t *dst_row;
  279.    const uint8_t *src_row;
  280.  
  281.    format_desc = util_format_description(format);
  282.  
  283.    assert(x % format_desc->block.width == 0);
  284.    assert(y % format_desc->block.height == 0);
  285.  
  286.    dst_row = (uint8_t *)dst + y*dst_stride + x*(format_desc->block.bits/8);
  287.    src_row = src;
  288.  
  289.    format_desc->pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, w, h);
  290. }
  291.  
  292. void
  293. util_format_read_4ui(enum pipe_format format,
  294.                      unsigned *dst, unsigned dst_stride,
  295.                      const void *src, unsigned src_stride,
  296.                      unsigned x, unsigned y, unsigned w, unsigned h)
  297. {
  298.    const struct util_format_description *format_desc;
  299.    const uint8_t *src_row;
  300.    uint32_t *dst_row;
  301.  
  302.    format_desc = util_format_description(format);
  303.  
  304.    assert(x % format_desc->block.width == 0);
  305.    assert(y % format_desc->block.height == 0);
  306.  
  307.    src_row = (const uint8_t *)src + y*src_stride + x*(format_desc->block.bits/8);
  308.    dst_row = dst;
  309.  
  310.    format_desc->unpack_rgba_uint(dst_row, dst_stride, src_row, src_stride, w, h);
  311. }
  312.  
  313. void
  314. util_format_write_4ui(enum pipe_format format,
  315.                       const unsigned int *src, unsigned src_stride,
  316.                       void *dst, unsigned dst_stride,
  317.                       unsigned x, unsigned y, unsigned w, unsigned h)
  318. {
  319.    const struct util_format_description *format_desc;
  320.    uint8_t *dst_row;
  321.    const uint32_t *src_row;
  322.  
  323.    format_desc = util_format_description(format);
  324.  
  325.    assert(x % format_desc->block.width == 0);
  326.    assert(y % format_desc->block.height == 0);
  327.  
  328.    dst_row = (uint8_t *)dst + y*dst_stride + x*(format_desc->block.bits/8);
  329.    src_row = src;
  330.  
  331.    format_desc->pack_rgba_uint(dst_row, dst_stride, src_row, src_stride, w, h);
  332. }
  333.  
  334. void
  335. util_format_read_4i(enum pipe_format format,
  336.                     int *dst, unsigned dst_stride,
  337.                     const void *src, unsigned src_stride,
  338.                     unsigned x, unsigned y, unsigned w, unsigned h)
  339. {
  340.    const struct util_format_description *format_desc;
  341.    const uint8_t *src_row;
  342.    int32_t *dst_row;
  343.  
  344.    format_desc = util_format_description(format);
  345.  
  346.    assert(x % format_desc->block.width == 0);
  347.    assert(y % format_desc->block.height == 0);
  348.  
  349.    src_row = (const uint8_t *)src + y*src_stride + x*(format_desc->block.bits/8);
  350.    dst_row = dst;
  351.  
  352.    format_desc->unpack_rgba_sint(dst_row, dst_stride, src_row, src_stride, w, h);
  353. }
  354.  
  355. void
  356. util_format_write_4i(enum pipe_format format,
  357.                       const int *src, unsigned src_stride,
  358.                       void *dst, unsigned dst_stride,
  359.                       unsigned x, unsigned y, unsigned w, unsigned h)
  360. {
  361.    const struct util_format_description *format_desc;
  362.    uint8_t *dst_row;
  363.    const int32_t *src_row;
  364.  
  365.    format_desc = util_format_description(format);
  366.  
  367.    assert(x % format_desc->block.width == 0);
  368.    assert(y % format_desc->block.height == 0);
  369.  
  370.    dst_row = (uint8_t *)dst + y*dst_stride + x*(format_desc->block.bits/8);
  371.    src_row = src;
  372.  
  373.    format_desc->pack_rgba_sint(dst_row, dst_stride, src_row, src_stride, w, h);
  374. }
  375.  
  376. boolean
  377. util_is_format_compatible(const struct util_format_description *src_desc,
  378.                           const struct util_format_description *dst_desc)
  379. {
  380.    unsigned chan;
  381.  
  382.    if (src_desc->format == dst_desc->format) {
  383.       return TRUE;
  384.    }
  385.  
  386.    if (src_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN ||
  387.        dst_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN) {
  388.       return FALSE;
  389.    }
  390.  
  391.    if (src_desc->block.bits != dst_desc->block.bits ||
  392.        src_desc->nr_channels != dst_desc->nr_channels ||
  393.        src_desc->colorspace != dst_desc->colorspace) {
  394.       return FALSE;
  395.    }
  396.  
  397.    for (chan = 0; chan < 4; ++chan) {
  398.       if (src_desc->channel[chan].size !=
  399.           dst_desc->channel[chan].size) {
  400.          return FALSE;
  401.       }
  402.    }
  403.  
  404.    for (chan = 0; chan < 4; ++chan) {
  405.       enum util_format_swizzle swizzle = dst_desc->swizzle[chan];
  406.  
  407.       if (swizzle < 4) {
  408.          if (src_desc->swizzle[chan] != swizzle) {
  409.             return FALSE;
  410.          }
  411.          if ((src_desc->channel[swizzle].type !=
  412.               dst_desc->channel[swizzle].type) ||
  413.              (src_desc->channel[swizzle].normalized !=
  414.               dst_desc->channel[swizzle].normalized)) {
  415.             return FALSE;
  416.          }
  417.       }
  418.    }
  419.  
  420.    return TRUE;
  421. }
  422.  
  423.  
  424. boolean
  425. util_format_fits_8unorm(const struct util_format_description *format_desc)
  426. {
  427.    unsigned chan;
  428.  
  429.    /*
  430.     * After linearized sRGB values require more than 8bits.
  431.     */
  432.  
  433.    if (format_desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) {
  434.       return FALSE;
  435.    }
  436.  
  437.    switch (format_desc->layout) {
  438.  
  439.    case UTIL_FORMAT_LAYOUT_S3TC:
  440.       /*
  441.        * These are straight forward.
  442.        */
  443.       return TRUE;
  444.    case UTIL_FORMAT_LAYOUT_RGTC:
  445.       if (format_desc->format == PIPE_FORMAT_RGTC1_SNORM ||
  446.           format_desc->format == PIPE_FORMAT_RGTC2_SNORM ||
  447.           format_desc->format == PIPE_FORMAT_LATC1_SNORM ||
  448.           format_desc->format == PIPE_FORMAT_LATC2_SNORM)
  449.          return FALSE;
  450.       return TRUE;
  451.  
  452.    case UTIL_FORMAT_LAYOUT_PLAIN:
  453.       /*
  454.        * For these we can find a generic rule.
  455.        */
  456.  
  457.       for (chan = 0; chan < format_desc->nr_channels; ++chan) {
  458.          switch (format_desc->channel[chan].type) {
  459.          case UTIL_FORMAT_TYPE_VOID:
  460.             break;
  461.          case UTIL_FORMAT_TYPE_UNSIGNED:
  462.             if (!format_desc->channel[chan].normalized ||
  463.                 format_desc->channel[chan].size > 8) {
  464.                return FALSE;
  465.             }
  466.             break;
  467.          default:
  468.             return FALSE;
  469.          }
  470.       }
  471.       return TRUE;
  472.  
  473.    default:
  474.       /*
  475.        * Handle all others on a case by case basis.
  476.        */
  477.  
  478.       switch (format_desc->format) {
  479.       case PIPE_FORMAT_R1_UNORM:
  480.       case PIPE_FORMAT_UYVY:
  481.       case PIPE_FORMAT_YUYV:
  482.       case PIPE_FORMAT_R8G8_B8G8_UNORM:
  483.       case PIPE_FORMAT_G8R8_G8B8_UNORM:
  484.          return TRUE;
  485.  
  486.       default:
  487.          return FALSE;
  488.       }
  489.    }
  490. }
  491.  
  492.  
  493. void
  494. util_format_translate(enum pipe_format dst_format,
  495.                       void *dst, unsigned dst_stride,
  496.                       unsigned dst_x, unsigned dst_y,
  497.                       enum pipe_format src_format,
  498.                       const void *src, unsigned src_stride,
  499.                       unsigned src_x, unsigned src_y,
  500.                       unsigned width, unsigned height)
  501. {
  502.    const struct util_format_description *dst_format_desc;
  503.    const struct util_format_description *src_format_desc;
  504.    uint8_t *dst_row;
  505.    const uint8_t *src_row;
  506.    unsigned x_step, y_step;
  507.    unsigned dst_step;
  508.    unsigned src_step;
  509.  
  510.    dst_format_desc = util_format_description(dst_format);
  511.    src_format_desc = util_format_description(src_format);
  512.  
  513.    if (util_is_format_compatible(src_format_desc, dst_format_desc)) {
  514.       /*
  515.        * Trivial case.
  516.        */
  517.  
  518.       util_copy_rect(dst, dst_format, dst_stride,  dst_x, dst_y,
  519.                      width, height, src, (int)src_stride,
  520.                      src_x, src_y);
  521.       return;
  522.    }
  523.  
  524.    assert(dst_x % dst_format_desc->block.width == 0);
  525.    assert(dst_y % dst_format_desc->block.height == 0);
  526.    assert(src_x % src_format_desc->block.width == 0);
  527.    assert(src_y % src_format_desc->block.height == 0);
  528.  
  529.    dst_row = (uint8_t *)dst + dst_y*dst_stride + dst_x*(dst_format_desc->block.bits/8);
  530.    src_row = (const uint8_t *)src + src_y*src_stride + src_x*(src_format_desc->block.bits/8);
  531.  
  532.    /*
  533.     * This works because all pixel formats have pixel blocks with power of two
  534.     * sizes.
  535.     */
  536.  
  537.    y_step = MAX2(dst_format_desc->block.height, src_format_desc->block.height);
  538.    x_step = MAX2(dst_format_desc->block.width, src_format_desc->block.width);
  539.    assert(y_step % dst_format_desc->block.height == 0);
  540.    assert(y_step % src_format_desc->block.height == 0);
  541.  
  542.    dst_step = y_step / dst_format_desc->block.height * dst_stride;
  543.    src_step = y_step / src_format_desc->block.height * src_stride;
  544.  
  545.    /*
  546.     * TODO: double formats will loose precision
  547.     * TODO: Add a special case for formats that are mere swizzles of each other
  548.     */
  549.  
  550.    if (src_format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS ||
  551.        dst_format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) {
  552.       float *tmp_z = NULL;
  553.       uint8_t *tmp_s = NULL;
  554.  
  555.       assert(x_step == 1);
  556.       assert(y_step == 1);
  557.  
  558.       if (src_format_desc->unpack_z_float &&
  559.           dst_format_desc->pack_z_float) {
  560.          tmp_z = MALLOC(width * sizeof *tmp_z);
  561.       }
  562.  
  563.       if (src_format_desc->unpack_s_8uint &&
  564.           dst_format_desc->pack_s_8uint) {
  565.          tmp_s = MALLOC(width * sizeof *tmp_s);
  566.       }
  567.  
  568.       while (height--) {
  569.          if (tmp_z) {
  570.             src_format_desc->unpack_z_float(tmp_z, 0, src_row, src_stride, width, 1);
  571.             dst_format_desc->pack_z_float(dst_row, dst_stride, tmp_z, 0, width, 1);
  572.          }
  573.  
  574.          if (tmp_s) {
  575.             src_format_desc->unpack_s_8uint(tmp_s, 0, src_row, src_stride, width, 1);
  576.             dst_format_desc->pack_s_8uint(dst_row, dst_stride, tmp_s, 0, width, 1);
  577.          }
  578.  
  579.          dst_row += dst_step;
  580.          src_row += src_step;
  581.       }
  582.  
  583.       FREE(tmp_s);
  584.  
  585.       FREE(tmp_z);
  586.  
  587.       return;
  588.    }
  589.  
  590.    if (util_format_fits_8unorm(src_format_desc) ||
  591.        util_format_fits_8unorm(dst_format_desc)) {
  592.       unsigned tmp_stride;
  593.       uint8_t *tmp_row;
  594.  
  595.       tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row;
  596.       tmp_row = MALLOC(y_step * tmp_stride);
  597.       if (!tmp_row)
  598.          return;
  599.  
  600.       while (height >= y_step) {
  601.          src_format_desc->unpack_rgba_8unorm(tmp_row, tmp_stride, src_row, src_stride, width, y_step);
  602.          dst_format_desc->pack_rgba_8unorm(dst_row, dst_stride, tmp_row, tmp_stride, width, y_step);
  603.  
  604.          dst_row += dst_step;
  605.          src_row += src_step;
  606.          height -= y_step;
  607.       }
  608.  
  609.       if (height) {
  610.          src_format_desc->unpack_rgba_8unorm(tmp_row, tmp_stride, src_row, src_stride, width, height);
  611.          dst_format_desc->pack_rgba_8unorm(dst_row, dst_stride, tmp_row, tmp_stride, width, height);
  612.       }
  613.  
  614.       FREE(tmp_row);
  615.    }
  616.    else {
  617.       unsigned tmp_stride;
  618.       float *tmp_row;
  619.  
  620.       tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row;
  621.       tmp_row = MALLOC(y_step * tmp_stride);
  622.       if (!tmp_row)
  623.          return;
  624.  
  625.       while (height >= y_step) {
  626.          src_format_desc->unpack_rgba_float(tmp_row, tmp_stride, src_row, src_stride, width, y_step);
  627.          dst_format_desc->pack_rgba_float(dst_row, dst_stride, tmp_row, tmp_stride, width, y_step);
  628.  
  629.          dst_row += dst_step;
  630.          src_row += src_step;
  631.          height -= y_step;
  632.       }
  633.  
  634.       if (height) {
  635.          src_format_desc->unpack_rgba_float(tmp_row, tmp_stride, src_row, src_stride, width, height);
  636.          dst_format_desc->pack_rgba_float(dst_row, dst_stride, tmp_row, tmp_stride, width, height);
  637.       }
  638.  
  639.       FREE(tmp_row);
  640.    }
  641. }
  642.  
  643. void util_format_compose_swizzles(const unsigned char swz1[4],
  644.                                   const unsigned char swz2[4],
  645.                                   unsigned char dst[4])
  646. {
  647.    unsigned i;
  648.  
  649.    for (i = 0; i < 4; i++) {
  650.       dst[i] = swz2[i] <= UTIL_FORMAT_SWIZZLE_W ?
  651.                swz1[swz2[i]] : swz2[i];
  652.    }
  653. }
  654.  
  655. void util_format_apply_color_swizzle(union pipe_color_union *dst,
  656.                                      const union pipe_color_union *src,
  657.                                      const unsigned char swz[4],
  658.                                      const boolean is_integer)
  659. {
  660.    unsigned c;
  661.  
  662.    if (is_integer) {
  663.       for (c = 0; c < 4; ++c) {
  664.          switch (swz[c]) {
  665.          case PIPE_SWIZZLE_RED:   dst->ui[c] = src->ui[0]; break;
  666.          case PIPE_SWIZZLE_GREEN: dst->ui[c] = src->ui[1]; break;
  667.          case PIPE_SWIZZLE_BLUE:  dst->ui[c] = src->ui[2]; break;
  668.          case PIPE_SWIZZLE_ALPHA: dst->ui[c] = src->ui[3]; break;
  669.          default:
  670.             dst->ui[c] = (swz[c] == PIPE_SWIZZLE_ONE) ? 1 : 0;
  671.             break;
  672.          }
  673.       }
  674.    } else {
  675.       for (c = 0; c < 4; ++c) {
  676.          switch (swz[c]) {
  677.          case PIPE_SWIZZLE_RED:   dst->f[c] = src->f[0]; break;
  678.          case PIPE_SWIZZLE_GREEN: dst->f[c] = src->f[1]; break;
  679.          case PIPE_SWIZZLE_BLUE:  dst->f[c] = src->f[2]; break;
  680.          case PIPE_SWIZZLE_ALPHA: dst->f[c] = src->f[3]; break;
  681.          default:
  682.             dst->f[c] = (swz[c] == PIPE_SWIZZLE_ONE) ? 1.0f : 0.0f;
  683.             break;
  684.          }
  685.       }
  686.    }
  687. }
  688.  
  689. void util_format_swizzle_4f(float *dst, const float *src,
  690.                             const unsigned char swz[4])
  691. {
  692.    unsigned i;
  693.  
  694.    for (i = 0; i < 4; i++) {
  695.       if (swz[i] <= UTIL_FORMAT_SWIZZLE_W)
  696.          dst[i] = src[swz[i]];
  697.       else if (swz[i] == UTIL_FORMAT_SWIZZLE_0)
  698.          dst[i] = 0;
  699.       else if (swz[i] == UTIL_FORMAT_SWIZZLE_1)
  700.          dst[i] = 1;
  701.    }
  702. }
  703.  
  704. void util_format_unswizzle_4f(float *dst, const float *src,
  705.                               const unsigned char swz[4])
  706. {
  707.    unsigned i;
  708.  
  709.    for (i = 0; i < 4; i++) {
  710.       switch (swz[i]) {
  711.       case UTIL_FORMAT_SWIZZLE_X:
  712.          dst[0] = src[i];
  713.          break;
  714.       case UTIL_FORMAT_SWIZZLE_Y:
  715.          dst[1] = src[i];
  716.          break;
  717.       case UTIL_FORMAT_SWIZZLE_Z:
  718.          dst[2] = src[i];
  719.          break;
  720.       case UTIL_FORMAT_SWIZZLE_W:
  721.          dst[3] = src[i];
  722.          break;
  723.       }
  724.    }
  725. }
  726.