1af69d88dSmrg/* 2af69d88dSmrg * Mesa 3-D graphics library 3af69d88dSmrg * 4af69d88dSmrg * Copyright (C) 2014 Intel Corporation All Rights Reserved. 5af69d88dSmrg * 6af69d88dSmrg * Permission is hereby granted, free of charge, to any person obtaining a 7af69d88dSmrg * copy of this software and associated documentation files (the "Software"), 8af69d88dSmrg * to deal in the Software without restriction, including without limitation 9af69d88dSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10af69d88dSmrg * and/or sell copies of the Software, and to permit persons to whom the 11af69d88dSmrg * Software is furnished to do so, subject to the following conditions: 12af69d88dSmrg * 13af69d88dSmrg * The above copyright notice and this permission notice shall be included 14af69d88dSmrg * in all copies or substantial portions of the Software. 15af69d88dSmrg * 16af69d88dSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17af69d88dSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18af69d88dSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20af69d88dSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21af69d88dSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22af69d88dSmrg * OTHER DEALINGS IN THE SOFTWARE. 23af69d88dSmrg */ 24af69d88dSmrg 251463c08dSmrg#include <stdlib.h> 261463c08dSmrg 277e995a2eSmrg#include "errors.h" 28af69d88dSmrg#include "format_utils.h" 29af69d88dSmrg#include "glformats.h" 307e995a2eSmrg#include "format_pack.h" 317e995a2eSmrg#include "format_unpack.h" 327e995a2eSmrg 337e995a2eSmrgconst mesa_array_format RGBA32_FLOAT = 341463c08dSmrg MESA_ARRAY_FORMAT(MESA_ARRAY_FORMAT_BASE_FORMAT_RGBA_VARIANTS, 351463c08dSmrg 4, 1, 1, 1, 4, 0, 1, 2, 3); 367e995a2eSmrg 377e995a2eSmrgconst mesa_array_format RGBA8_UBYTE = 381463c08dSmrg MESA_ARRAY_FORMAT(MESA_ARRAY_FORMAT_BASE_FORMAT_RGBA_VARIANTS, 391463c08dSmrg 1, 0, 0, 1, 4, 0, 1, 2, 3); 401463c08dSmrg 411463c08dSmrgconst mesa_array_format BGRA8_UBYTE = 421463c08dSmrg MESA_ARRAY_FORMAT(MESA_ARRAY_FORMAT_BASE_FORMAT_RGBA_VARIANTS, 431463c08dSmrg 1, 0, 0, 1, 4, 2, 1, 0, 3); 447e995a2eSmrg 457e995a2eSmrgconst mesa_array_format RGBA32_UINT = 461463c08dSmrg MESA_ARRAY_FORMAT(MESA_ARRAY_FORMAT_BASE_FORMAT_RGBA_VARIANTS, 471463c08dSmrg 4, 0, 0, 0, 4, 0, 1, 2, 3); 487e995a2eSmrg 497e995a2eSmrgconst mesa_array_format RGBA32_INT = 501463c08dSmrg MESA_ARRAY_FORMAT(MESA_ARRAY_FORMAT_BASE_FORMAT_RGBA_VARIANTS, 511463c08dSmrg 4, 1, 0, 0, 4, 0, 1, 2, 3); 527e995a2eSmrg 537e995a2eSmrgstatic void 547e995a2eSmrginvert_swizzle(uint8_t dst[4], const uint8_t src[4]) 557e995a2eSmrg{ 567e995a2eSmrg int i, j; 577e995a2eSmrg 587e995a2eSmrg dst[0] = MESA_FORMAT_SWIZZLE_NONE; 597e995a2eSmrg dst[1] = MESA_FORMAT_SWIZZLE_NONE; 607e995a2eSmrg dst[2] = MESA_FORMAT_SWIZZLE_NONE; 617e995a2eSmrg dst[3] = MESA_FORMAT_SWIZZLE_NONE; 627e995a2eSmrg 637e995a2eSmrg for (i = 0; i < 4; ++i) 647e995a2eSmrg for (j = 0; j < 4; ++j) 657e995a2eSmrg if (src[j] == i && dst[i] == MESA_FORMAT_SWIZZLE_NONE) 667e995a2eSmrg dst[i] = j; 677e995a2eSmrg} 687e995a2eSmrg 697e995a2eSmrg/* Takes a src to RGBA swizzle and applies a rebase swizzle to it. This 707e995a2eSmrg * is used when we need to rebase a format to match a different 717e995a2eSmrg * base internal format. 727e995a2eSmrg * 737e995a2eSmrg * The rebase swizzle can be NULL, which means that no rebase is necessary, 747e995a2eSmrg * in which case the src to RGBA swizzle is copied to the output without 757e995a2eSmrg * changes. 767e995a2eSmrg * 777e995a2eSmrg * The resulting rebased swizzle and well as the input swizzles are 787e995a2eSmrg * all 4-element swizzles, but the rebase swizzle can be NULL if no rebase 797e995a2eSmrg * is necessary. 807e995a2eSmrg */ 817e995a2eSmrgstatic void 827e995a2eSmrgcompute_rebased_rgba_component_mapping(uint8_t *src2rgba, 837e995a2eSmrg uint8_t *rebase_swizzle, 847e995a2eSmrg uint8_t *rebased_src2rgba) 857e995a2eSmrg{ 867e995a2eSmrg int i; 877e995a2eSmrg 887e995a2eSmrg if (rebase_swizzle) { 897e995a2eSmrg for (i = 0; i < 4; i++) { 907e995a2eSmrg if (rebase_swizzle[i] > MESA_FORMAT_SWIZZLE_W) 917e995a2eSmrg rebased_src2rgba[i] = rebase_swizzle[i]; 927e995a2eSmrg else 937e995a2eSmrg rebased_src2rgba[i] = src2rgba[rebase_swizzle[i]]; 947e995a2eSmrg } 957e995a2eSmrg } else { 967e995a2eSmrg /* No rebase needed, so src2rgba is all that we need */ 977e995a2eSmrg memcpy(rebased_src2rgba, src2rgba, 4 * sizeof(uint8_t)); 987e995a2eSmrg } 997e995a2eSmrg} 1007e995a2eSmrg 1017e995a2eSmrg/* Computes the final swizzle transform to apply from src to dst in a 1027e995a2eSmrg * conversion that might involve a rebase swizzle. 1037e995a2eSmrg * 1047e995a2eSmrg * This is used to compute the swizzle transform to apply in conversions 1057e995a2eSmrg * between array formats where we have a src2rgba swizzle, a rgba2dst swizzle 1067e995a2eSmrg * and possibly, a rebase swizzle. 1077e995a2eSmrg * 1087e995a2eSmrg * The final swizzle transform to apply (src2dst) when a rebase swizzle is 1097e995a2eSmrg * involved is: src -> rgba -> base -> rgba -> dst 1107e995a2eSmrg */ 1117e995a2eSmrgstatic void 1127e995a2eSmrgcompute_src2dst_component_mapping(uint8_t *src2rgba, uint8_t *rgba2dst, 1137e995a2eSmrg uint8_t *rebase_swizzle, uint8_t *src2dst) 1147e995a2eSmrg{ 1157e995a2eSmrg int i; 1167e995a2eSmrg 1177e995a2eSmrg if (!rebase_swizzle) { 1187e995a2eSmrg for (i = 0; i < 4; i++) { 1197e995a2eSmrg if (rgba2dst[i] > MESA_FORMAT_SWIZZLE_W) { 1207e995a2eSmrg src2dst[i] = rgba2dst[i]; 1217e995a2eSmrg } else { 1227e995a2eSmrg src2dst[i] = src2rgba[rgba2dst[i]]; 1237e995a2eSmrg } 1247e995a2eSmrg } 1257e995a2eSmrg } else { 1267e995a2eSmrg for (i = 0; i < 4; i++) { 1277e995a2eSmrg if (rgba2dst[i] > MESA_FORMAT_SWIZZLE_W) { 1287e995a2eSmrg src2dst[i] = rgba2dst[i]; 1297e995a2eSmrg } else if (rebase_swizzle[rgba2dst[i]] > MESA_FORMAT_SWIZZLE_W) { 1307e995a2eSmrg src2dst[i] = rebase_swizzle[rgba2dst[i]]; 1317e995a2eSmrg } else { 1327e995a2eSmrg src2dst[i] = src2rgba[rebase_swizzle[rgba2dst[i]]]; 1337e995a2eSmrg } 1347e995a2eSmrg } 1357e995a2eSmrg } 1367e995a2eSmrg} 1377e995a2eSmrg 1387e995a2eSmrg/** 1397e995a2eSmrg * This function is used by clients of _mesa_format_convert to obtain 1407e995a2eSmrg * the rebase swizzle to use in a format conversion based on the base 1417e995a2eSmrg * format involved. 1427e995a2eSmrg * 1437e995a2eSmrg * \param baseFormat the base internal format involved in the conversion. 1447e995a2eSmrg * \param map the rebase swizzle to consider 1457e995a2eSmrg * 1467e995a2eSmrg * This function computes 'map' as rgba -> baseformat -> rgba and returns true 1477e995a2eSmrg * if the resulting swizzle transform is not the identity transform (thus, a 1487e995a2eSmrg * rebase is needed). If the function returns false then a rebase swizzle 1497e995a2eSmrg * is not necessary and the value of 'map' is undefined. In this situation 1507e995a2eSmrg * clients of _mesa_format_convert should pass NULL in the 'rebase_swizzle' 1517e995a2eSmrg * parameter. 1527e995a2eSmrg */ 1537e995a2eSmrgbool 1547e995a2eSmrg_mesa_compute_rgba2base2rgba_component_mapping(GLenum baseFormat, uint8_t *map) 1557e995a2eSmrg{ 1567e995a2eSmrg uint8_t rgba2base[6], base2rgba[6]; 1577e995a2eSmrg int i; 1587e995a2eSmrg 1597e995a2eSmrg switch (baseFormat) { 1607e995a2eSmrg case GL_ALPHA: 1617e995a2eSmrg case GL_RED: 1627e995a2eSmrg case GL_GREEN: 1637e995a2eSmrg case GL_BLUE: 1647e995a2eSmrg case GL_RG: 1657e995a2eSmrg case GL_RGB: 1667e995a2eSmrg case GL_BGR: 1677e995a2eSmrg case GL_RGBA: 1687e995a2eSmrg case GL_BGRA: 1697e995a2eSmrg case GL_ABGR_EXT: 1707e995a2eSmrg case GL_LUMINANCE: 1717e995a2eSmrg case GL_INTENSITY: 1727e995a2eSmrg case GL_LUMINANCE_ALPHA: 1737e995a2eSmrg { 1747e995a2eSmrg bool needRebase = false; 1757e995a2eSmrg _mesa_compute_component_mapping(GL_RGBA, baseFormat, rgba2base); 1767e995a2eSmrg _mesa_compute_component_mapping(baseFormat, GL_RGBA, base2rgba); 1777e995a2eSmrg for (i = 0; i < 4; i++) { 1787e995a2eSmrg if (base2rgba[i] > MESA_FORMAT_SWIZZLE_W) { 1797e995a2eSmrg map[i] = base2rgba[i]; 1807e995a2eSmrg } else { 1817e995a2eSmrg map[i] = rgba2base[base2rgba[i]]; 1827e995a2eSmrg } 1837e995a2eSmrg if (map[i] != i) 1847e995a2eSmrg needRebase = true; 1857e995a2eSmrg } 1867e995a2eSmrg return needRebase; 1877e995a2eSmrg } 1887e995a2eSmrg default: 1897e995a2eSmrg unreachable("Unexpected base format"); 1907e995a2eSmrg } 1917e995a2eSmrg} 1927e995a2eSmrg 1937e995a2eSmrg 1947e995a2eSmrg/** 1957e995a2eSmrg * Special case conversion function to swap r/b channels from the source 1967e995a2eSmrg * image to the dest image. 1977e995a2eSmrg */ 1987e995a2eSmrgstatic void 1997e995a2eSmrgconvert_ubyte_rgba_to_bgra(size_t width, size_t height, 2007e995a2eSmrg const uint8_t *src, size_t src_stride, 2017e995a2eSmrg uint8_t *dst, size_t dst_stride) 2027e995a2eSmrg{ 2037e995a2eSmrg int row; 2047e995a2eSmrg 2057e995a2eSmrg if (sizeof(void *) == 8 && 2067e995a2eSmrg src_stride % 8 == 0 && 2077e995a2eSmrg dst_stride % 8 == 0 && 2087e995a2eSmrg (GLsizeiptr) src % 8 == 0 && 2097e995a2eSmrg (GLsizeiptr) dst % 8 == 0) { 2107e995a2eSmrg /* use 64-bit word to swizzle two 32-bit pixels. We need 8-byte 2117e995a2eSmrg * alignment for src/dst addresses and strides. 2127e995a2eSmrg */ 2137e995a2eSmrg for (row = 0; row < height; row++) { 2147e995a2eSmrg const GLuint64 *s = (const GLuint64 *) src; 2157e995a2eSmrg GLuint64 *d = (GLuint64 *) dst; 2167e995a2eSmrg int i; 2177e995a2eSmrg for (i = 0; i < width/2; i++) { 2187e995a2eSmrg d[i] = ( (s[i] & 0xff00ff00ff00ff00) | 2197e995a2eSmrg ((s[i] & 0xff000000ff) << 16) | 2207e995a2eSmrg ((s[i] & 0xff000000ff0000) >> 16)); 2217e995a2eSmrg } 2227e995a2eSmrg if (width & 1) { 2237e995a2eSmrg /* handle the case of odd widths */ 2247e995a2eSmrg const GLuint s = ((const GLuint *) src)[width - 1]; 2257e995a2eSmrg GLuint *d = (GLuint *) dst + width - 1; 2267e995a2eSmrg *d = ( (s & 0xff00ff00) | 2277e995a2eSmrg ((s & 0xff) << 16) | 2287e995a2eSmrg ((s & 0xff0000) >> 16)); 2297e995a2eSmrg } 2307e995a2eSmrg src += src_stride; 2317e995a2eSmrg dst += dst_stride; 2327e995a2eSmrg } 2337e995a2eSmrg } else { 2347e995a2eSmrg for (row = 0; row < height; row++) { 2357e995a2eSmrg const GLuint *s = (const GLuint *) src; 2367e995a2eSmrg GLuint *d = (GLuint *) dst; 2377e995a2eSmrg int i; 2387e995a2eSmrg for (i = 0; i < width; i++) { 2397e995a2eSmrg d[i] = ( (s[i] & 0xff00ff00) | 2407e995a2eSmrg ((s[i] & 0xff) << 16) | 2417e995a2eSmrg ((s[i] & 0xff0000) >> 16)); 2427e995a2eSmrg } 2437e995a2eSmrg src += src_stride; 2447e995a2eSmrg dst += dst_stride; 2457e995a2eSmrg } 2467e995a2eSmrg } 2477e995a2eSmrg} 2487e995a2eSmrg 2497e995a2eSmrg 2507e995a2eSmrg/** 2517e995a2eSmrg * This can be used to convert between most color formats. 2527e995a2eSmrg * 2537e995a2eSmrg * Limitations: 2547e995a2eSmrg * - This function doesn't handle GL_COLOR_INDEX or YCBCR formats. 2557e995a2eSmrg * - This function doesn't handle byte-swapping or transferOps, these should 2567e995a2eSmrg * be handled by the caller. 2577e995a2eSmrg * 2587e995a2eSmrg * \param void_dst The address where converted color data will be stored. 2597e995a2eSmrg * The caller must ensure that the buffer is large enough 2607e995a2eSmrg * to hold the converted pixel data. 2617e995a2eSmrg * \param dst_format The destination color format. It can be a mesa_format 2627e995a2eSmrg * or a mesa_array_format represented as an uint32_t. 2637e995a2eSmrg * \param dst_stride The stride of the destination format in bytes. 2647e995a2eSmrg * \param void_src The address of the source color data to convert. 2657e995a2eSmrg * \param src_format The source color format. It can be a mesa_format 2667e995a2eSmrg * or a mesa_array_format represented as an uint32_t. 2677e995a2eSmrg * \param src_stride The stride of the source format in bytes. 2687e995a2eSmrg * \param width The width, in pixels, of the source image to convert. 2697e995a2eSmrg * \param height The height, in pixels, of the source image to convert. 2707e995a2eSmrg * \param rebase_swizzle A swizzle transform to apply during the conversion, 2717e995a2eSmrg * typically used to match a different internal base 2727e995a2eSmrg * format involved. NULL if no rebase transform is needed 2737e995a2eSmrg * (i.e. the internal base format and the base format of 2747e995a2eSmrg * the dst or the src -depending on whether we are doing 2757e995a2eSmrg * an upload or a download respectively- are the same). 2767e995a2eSmrg */ 2777e995a2eSmrgvoid 2787e995a2eSmrg_mesa_format_convert(void *void_dst, uint32_t dst_format, size_t dst_stride, 2797e995a2eSmrg void *void_src, uint32_t src_format, size_t src_stride, 2807e995a2eSmrg size_t width, size_t height, uint8_t *rebase_swizzle) 2817e995a2eSmrg{ 2827e995a2eSmrg uint8_t *dst = (uint8_t *)void_dst; 2837e995a2eSmrg uint8_t *src = (uint8_t *)void_src; 2847e995a2eSmrg mesa_array_format src_array_format, dst_array_format; 2857e995a2eSmrg bool src_format_is_mesa_array_format, dst_format_is_mesa_array_format; 2867e995a2eSmrg uint8_t src2dst[4], src2rgba[4], rgba2dst[4], dst2rgba[4]; 2877e995a2eSmrg uint8_t rebased_src2rgba[4]; 2887e995a2eSmrg enum mesa_array_format_datatype src_type = 0, dst_type = 0, common_type; 2897e995a2eSmrg bool normalized, dst_integer, src_integer, is_signed; 2907e995a2eSmrg int src_num_channels = 0, dst_num_channels = 0; 2917e995a2eSmrg uint8_t (*tmp_ubyte)[4]; 2927e995a2eSmrg float (*tmp_float)[4]; 2937e995a2eSmrg uint32_t (*tmp_uint)[4]; 2947e995a2eSmrg int bits; 2957e995a2eSmrg size_t row; 2967e995a2eSmrg 2977e995a2eSmrg if (_mesa_format_is_mesa_array_format(src_format)) { 2987e995a2eSmrg src_format_is_mesa_array_format = true; 2997e995a2eSmrg src_array_format = src_format; 3007e995a2eSmrg } else { 3017e995a2eSmrg assert(_mesa_is_format_color_format(src_format)); 3027e995a2eSmrg src_format_is_mesa_array_format = false; 3037e995a2eSmrg src_array_format = _mesa_format_to_array_format(src_format); 3047e995a2eSmrg } 3057e995a2eSmrg 3067e995a2eSmrg if (_mesa_format_is_mesa_array_format(dst_format)) { 3077e995a2eSmrg dst_format_is_mesa_array_format = true; 3087e995a2eSmrg dst_array_format = dst_format; 3097e995a2eSmrg } else { 3107e995a2eSmrg assert(_mesa_is_format_color_format(dst_format)); 3117e995a2eSmrg dst_format_is_mesa_array_format = false; 3127e995a2eSmrg dst_array_format = _mesa_format_to_array_format(dst_format); 3137e995a2eSmrg } 3147e995a2eSmrg 3157e995a2eSmrg /* First we see if we can implement the conversion with a direct pack 3167e995a2eSmrg * or unpack. 3177e995a2eSmrg * 3187e995a2eSmrg * In this case we want to be careful when we need to apply a swizzle to 3197e995a2eSmrg * match an internal base format, since in these cases a simple pack/unpack 3207e995a2eSmrg * to the dst format from the src format may not match the requirements 3217e995a2eSmrg * of the internal base format. For now we decide to be safe and 3227e995a2eSmrg * avoid this path in these scenarios but in the future we may want to 3237e995a2eSmrg * enable it for specific combinations that are known to work. 3247e995a2eSmrg */ 3257e995a2eSmrg if (!rebase_swizzle) { 3267e995a2eSmrg /* Do a direct memcpy where possible */ 3277e995a2eSmrg if ((dst_format_is_mesa_array_format && 3287e995a2eSmrg src_format_is_mesa_array_format && 3297e995a2eSmrg src_array_format == dst_array_format) || 3307e995a2eSmrg src_format == dst_format) { 3317e995a2eSmrg int format_size = _mesa_get_format_bytes(src_format); 3327e995a2eSmrg for (row = 0; row < height; row++) { 3337e995a2eSmrg memcpy(dst, src, width * format_size); 3347e995a2eSmrg src += src_stride; 3357e995a2eSmrg dst += dst_stride; 3367e995a2eSmrg } 3377e995a2eSmrg return; 3387e995a2eSmrg } 3397e995a2eSmrg 3407e995a2eSmrg /* Handle the cases where we can directly unpack */ 3417e995a2eSmrg if (!src_format_is_mesa_array_format) { 3427e995a2eSmrg if (dst_array_format == RGBA32_FLOAT) { 3437e995a2eSmrg for (row = 0; row < height; ++row) { 3447e995a2eSmrg _mesa_unpack_rgba_row(src_format, width, 3457e995a2eSmrg src, (float (*)[4])dst); 3467e995a2eSmrg src += src_stride; 3477e995a2eSmrg dst += dst_stride; 3487e995a2eSmrg } 3497e995a2eSmrg return; 3507e995a2eSmrg } else if (dst_array_format == RGBA8_UBYTE) { 3517e995a2eSmrg assert(!_mesa_is_format_integer_color(src_format)); 3527e995a2eSmrg for (row = 0; row < height; ++row) { 3537e995a2eSmrg _mesa_unpack_ubyte_rgba_row(src_format, width, 3547e995a2eSmrg src, (uint8_t (*)[4])dst); 3557e995a2eSmrg src += src_stride; 3567e995a2eSmrg dst += dst_stride; 3577e995a2eSmrg } 3587e995a2eSmrg return; 3591463c08dSmrg } else if (dst_array_format == BGRA8_UBYTE && 3601463c08dSmrg src_format == MESA_FORMAT_R8G8B8A8_UNORM) { 3611463c08dSmrg convert_ubyte_rgba_to_bgra(width, height, src, src_stride, 3621463c08dSmrg dst, dst_stride); 3631463c08dSmrg return; 3647e995a2eSmrg } else if (dst_array_format == RGBA32_UINT && 3657e995a2eSmrg _mesa_is_format_unsigned(src_format)) { 3667e995a2eSmrg assert(_mesa_is_format_integer_color(src_format)); 3677e995a2eSmrg for (row = 0; row < height; ++row) { 3687e995a2eSmrg _mesa_unpack_uint_rgba_row(src_format, width, 3697e995a2eSmrg src, (uint32_t (*)[4])dst); 3707e995a2eSmrg src += src_stride; 3717e995a2eSmrg dst += dst_stride; 3727e995a2eSmrg } 3737e995a2eSmrg return; 3747e995a2eSmrg } 3757e995a2eSmrg } 3767e995a2eSmrg 3777e995a2eSmrg /* Handle the cases where we can directly pack */ 3787e995a2eSmrg if (!dst_format_is_mesa_array_format) { 3797e995a2eSmrg if (src_array_format == RGBA32_FLOAT) { 3807e995a2eSmrg for (row = 0; row < height; ++row) { 3817e995a2eSmrg _mesa_pack_float_rgba_row(dst_format, width, 3827e995a2eSmrg (const float (*)[4])src, dst); 3837e995a2eSmrg src += src_stride; 3847e995a2eSmrg dst += dst_stride; 3857e995a2eSmrg } 3867e995a2eSmrg return; 3877e995a2eSmrg } else if (src_array_format == RGBA8_UBYTE) { 3887e995a2eSmrg assert(!_mesa_is_format_integer_color(dst_format)); 3897e995a2eSmrg 3907e995a2eSmrg if (dst_format == MESA_FORMAT_B8G8R8A8_UNORM) { 3917e995a2eSmrg convert_ubyte_rgba_to_bgra(width, height, src, src_stride, 3927e995a2eSmrg dst, dst_stride); 3937e995a2eSmrg } 3947e995a2eSmrg else { 3957e995a2eSmrg for (row = 0; row < height; ++row) { 3961463c08dSmrg _mesa_pack_ubyte_rgba_row(dst_format, width, src, dst); 3977e995a2eSmrg src += src_stride; 3987e995a2eSmrg dst += dst_stride; 3997e995a2eSmrg } 4007e995a2eSmrg } 4017e995a2eSmrg return; 4027e995a2eSmrg } else if (src_array_format == RGBA32_UINT && 4037e995a2eSmrg _mesa_is_format_unsigned(dst_format)) { 4047e995a2eSmrg assert(_mesa_is_format_integer_color(dst_format)); 4057e995a2eSmrg for (row = 0; row < height; ++row) { 4067e995a2eSmrg _mesa_pack_uint_rgba_row(dst_format, width, 4077e995a2eSmrg (const uint32_t (*)[4])src, dst); 4087e995a2eSmrg src += src_stride; 4097e995a2eSmrg dst += dst_stride; 4107e995a2eSmrg } 4117e995a2eSmrg return; 4127e995a2eSmrg } 4137e995a2eSmrg } 4147e995a2eSmrg } 4157e995a2eSmrg 4167e995a2eSmrg /* Handle conversions between array formats */ 4177e995a2eSmrg normalized = false; 4187e995a2eSmrg if (src_array_format) { 4197e995a2eSmrg src_type = _mesa_array_format_get_datatype(src_array_format); 4207e995a2eSmrg 4217e995a2eSmrg src_num_channels = _mesa_array_format_get_num_channels(src_array_format); 4227e995a2eSmrg 4237e995a2eSmrg _mesa_array_format_get_swizzle(src_array_format, src2rgba); 4247e995a2eSmrg 4257e995a2eSmrg normalized = _mesa_array_format_is_normalized(src_array_format); 4267e995a2eSmrg } 4277e995a2eSmrg 4287e995a2eSmrg if (dst_array_format) { 4297e995a2eSmrg dst_type = _mesa_array_format_get_datatype(dst_array_format); 4307e995a2eSmrg 4317e995a2eSmrg dst_num_channels = _mesa_array_format_get_num_channels(dst_array_format); 4327e995a2eSmrg 4337e995a2eSmrg _mesa_array_format_get_swizzle(dst_array_format, dst2rgba); 4347e995a2eSmrg invert_swizzle(rgba2dst, dst2rgba); 4357e995a2eSmrg 4367e995a2eSmrg normalized |= _mesa_array_format_is_normalized(dst_array_format); 4377e995a2eSmrg } 4387e995a2eSmrg 4397e995a2eSmrg if (src_array_format && dst_array_format) { 4407e995a2eSmrg assert(_mesa_array_format_is_normalized(src_array_format) == 4417e995a2eSmrg _mesa_array_format_is_normalized(dst_array_format)); 4427e995a2eSmrg 4437e995a2eSmrg compute_src2dst_component_mapping(src2rgba, rgba2dst, rebase_swizzle, 4447e995a2eSmrg src2dst); 4457e995a2eSmrg 4467e995a2eSmrg for (row = 0; row < height; ++row) { 4477e995a2eSmrg _mesa_swizzle_and_convert(dst, dst_type, dst_num_channels, 4487e995a2eSmrg src, src_type, src_num_channels, 4497e995a2eSmrg src2dst, normalized, width); 4507e995a2eSmrg src += src_stride; 4517e995a2eSmrg dst += dst_stride; 4527e995a2eSmrg } 4537e995a2eSmrg return; 4547e995a2eSmrg } 4557e995a2eSmrg 4567e995a2eSmrg /* At this point, we're fresh out of fast-paths and we need to convert 4577e995a2eSmrg * to float, uint32, or, if we're lucky, uint8. 4587e995a2eSmrg */ 4597e995a2eSmrg dst_integer = false; 4607e995a2eSmrg src_integer = false; 4617e995a2eSmrg 4627e995a2eSmrg if (src_array_format) { 4637e995a2eSmrg if (!_mesa_array_format_is_float(src_array_format) && 4647e995a2eSmrg !_mesa_array_format_is_normalized(src_array_format)) 4657e995a2eSmrg src_integer = true; 4667e995a2eSmrg } else { 4677e995a2eSmrg switch (_mesa_get_format_datatype(src_format)) { 4687e995a2eSmrg case GL_UNSIGNED_INT: 4697e995a2eSmrg case GL_INT: 4707e995a2eSmrg src_integer = true; 4717e995a2eSmrg break; 4727e995a2eSmrg } 4737e995a2eSmrg } 4747e995a2eSmrg 4757e995a2eSmrg /* If the destination format is signed but the source is unsigned, then we 4767e995a2eSmrg * don't loose any data by converting to a signed intermediate format above 4777e995a2eSmrg * and beyond the precision that we loose in the conversion itself. If the 4787e995a2eSmrg * destination is unsigned then, by using an unsigned intermediate format, 4797e995a2eSmrg * we make the conversion function that converts from the source to the 4807e995a2eSmrg * intermediate format take care of truncating at zero. The exception here 4817e995a2eSmrg * is if the intermediate format is float, in which case the first 4827e995a2eSmrg * conversion will leave it signed and the second conversion will truncate 4837e995a2eSmrg * at zero. 4847e995a2eSmrg */ 4857e995a2eSmrg is_signed = false; 4867e995a2eSmrg if (dst_array_format) { 4877e995a2eSmrg if (!_mesa_array_format_is_float(dst_array_format) && 4887e995a2eSmrg !_mesa_array_format_is_normalized(dst_array_format)) 4897e995a2eSmrg dst_integer = true; 4907e995a2eSmrg is_signed = _mesa_array_format_is_signed(dst_array_format); 4917e995a2eSmrg bits = 8 * _mesa_array_format_get_type_size(dst_array_format); 4927e995a2eSmrg } else { 4937e995a2eSmrg switch (_mesa_get_format_datatype(dst_format)) { 4947e995a2eSmrg case GL_UNSIGNED_NORMALIZED: 4957e995a2eSmrg is_signed = false; 4967e995a2eSmrg break; 4977e995a2eSmrg case GL_SIGNED_NORMALIZED: 4987e995a2eSmrg is_signed = true; 4997e995a2eSmrg break; 5007e995a2eSmrg case GL_FLOAT: 5017e995a2eSmrg is_signed = true; 5027e995a2eSmrg break; 5037e995a2eSmrg case GL_UNSIGNED_INT: 5047e995a2eSmrg is_signed = false; 5057e995a2eSmrg dst_integer = true; 5067e995a2eSmrg break; 5077e995a2eSmrg case GL_INT: 5087e995a2eSmrg is_signed = true; 5097e995a2eSmrg dst_integer = true; 5107e995a2eSmrg break; 5117e995a2eSmrg } 5127e995a2eSmrg bits = _mesa_get_format_max_bits(dst_format); 5137e995a2eSmrg } 5147e995a2eSmrg 5157e995a2eSmrg assert(src_integer == dst_integer); 5167e995a2eSmrg 5177e995a2eSmrg if (src_integer && dst_integer) { 5187e995a2eSmrg tmp_uint = malloc(width * height * sizeof(*tmp_uint)); 5197e995a2eSmrg 5207e995a2eSmrg /* The [un]packing functions for unsigned datatypes treat the 32-bit 5217e995a2eSmrg * integer array as signed for signed formats and as unsigned for 5227e995a2eSmrg * unsigned formats. This is a bit of a problem if we ever convert from 5237e995a2eSmrg * a signed to an unsigned format because the unsigned packing function 5247e995a2eSmrg * doesn't know that the input is signed and will treat it as unsigned 5257e995a2eSmrg * and not do the trunctation. The thing that saves us here is that all 5267e995a2eSmrg * of the packed formats are unsigned, so we can just always use 5277e995a2eSmrg * _mesa_swizzle_and_convert for signed formats, which is aware of the 5287e995a2eSmrg * truncation problem. 5297e995a2eSmrg */ 5307e995a2eSmrg common_type = is_signed ? MESA_ARRAY_FORMAT_TYPE_INT : 5317e995a2eSmrg MESA_ARRAY_FORMAT_TYPE_UINT; 5327e995a2eSmrg if (src_array_format) { 5337e995a2eSmrg compute_rebased_rgba_component_mapping(src2rgba, rebase_swizzle, 5347e995a2eSmrg rebased_src2rgba); 5357e995a2eSmrg for (row = 0; row < height; ++row) { 5367e995a2eSmrg _mesa_swizzle_and_convert(tmp_uint + row * width, common_type, 4, 5377e995a2eSmrg src, src_type, src_num_channels, 5387e995a2eSmrg rebased_src2rgba, normalized, width); 5397e995a2eSmrg src += src_stride; 5407e995a2eSmrg } 5417e995a2eSmrg } else { 5427e995a2eSmrg for (row = 0; row < height; ++row) { 5437e995a2eSmrg _mesa_unpack_uint_rgba_row(src_format, width, 5447e995a2eSmrg src, tmp_uint + row * width); 5457e995a2eSmrg if (rebase_swizzle) 5467e995a2eSmrg _mesa_swizzle_and_convert(tmp_uint + row * width, common_type, 4, 5477e995a2eSmrg tmp_uint + row * width, common_type, 4, 5487e995a2eSmrg rebase_swizzle, false, width); 5497e995a2eSmrg src += src_stride; 5507e995a2eSmrg } 5517e995a2eSmrg } 5527e995a2eSmrg 5537e995a2eSmrg /* At this point, we have already done the truncation if the source is 5547e995a2eSmrg * signed but the destination is unsigned, so no need to force the 5557e995a2eSmrg * _mesa_swizzle_and_convert path. 5567e995a2eSmrg */ 5577e995a2eSmrg if (dst_format_is_mesa_array_format) { 5587e995a2eSmrg for (row = 0; row < height; ++row) { 5597e995a2eSmrg _mesa_swizzle_and_convert(dst, dst_type, dst_num_channels, 5607e995a2eSmrg tmp_uint + row * width, common_type, 4, 5617e995a2eSmrg rgba2dst, normalized, width); 5627e995a2eSmrg dst += dst_stride; 5637e995a2eSmrg } 5647e995a2eSmrg } else { 5657e995a2eSmrg for (row = 0; row < height; ++row) { 5667e995a2eSmrg _mesa_pack_uint_rgba_row(dst_format, width, 5677e995a2eSmrg (const uint32_t (*)[4])tmp_uint + row * width, dst); 5687e995a2eSmrg dst += dst_stride; 5697e995a2eSmrg } 5707e995a2eSmrg } 5717e995a2eSmrg 5727e995a2eSmrg free(tmp_uint); 5737e995a2eSmrg } else if (is_signed || bits > 8) { 5747e995a2eSmrg tmp_float = malloc(width * height * sizeof(*tmp_float)); 5757e995a2eSmrg 5767e995a2eSmrg if (src_format_is_mesa_array_format) { 5777e995a2eSmrg compute_rebased_rgba_component_mapping(src2rgba, rebase_swizzle, 5787e995a2eSmrg rebased_src2rgba); 5797e995a2eSmrg for (row = 0; row < height; ++row) { 5807e995a2eSmrg _mesa_swizzle_and_convert(tmp_float + row * width, 5817e995a2eSmrg MESA_ARRAY_FORMAT_TYPE_FLOAT, 4, 5827e995a2eSmrg src, src_type, src_num_channels, 5837e995a2eSmrg rebased_src2rgba, normalized, width); 5847e995a2eSmrg src += src_stride; 5857e995a2eSmrg } 5867e995a2eSmrg } else { 5877e995a2eSmrg for (row = 0; row < height; ++row) { 5887e995a2eSmrg _mesa_unpack_rgba_row(src_format, width, 5897e995a2eSmrg src, tmp_float + row * width); 5907e995a2eSmrg if (rebase_swizzle) 5917e995a2eSmrg _mesa_swizzle_and_convert(tmp_float + row * width, 5927e995a2eSmrg MESA_ARRAY_FORMAT_TYPE_FLOAT, 4, 5937e995a2eSmrg tmp_float + row * width, 5947e995a2eSmrg MESA_ARRAY_FORMAT_TYPE_FLOAT, 4, 5957e995a2eSmrg rebase_swizzle, normalized, width); 5967e995a2eSmrg src += src_stride; 5977e995a2eSmrg } 5987e995a2eSmrg } 5997e995a2eSmrg 6007e995a2eSmrg if (dst_format_is_mesa_array_format) { 6017e995a2eSmrg for (row = 0; row < height; ++row) { 6027e995a2eSmrg _mesa_swizzle_and_convert(dst, dst_type, dst_num_channels, 6037e995a2eSmrg tmp_float + row * width, 6047e995a2eSmrg MESA_ARRAY_FORMAT_TYPE_FLOAT, 4, 6057e995a2eSmrg rgba2dst, normalized, width); 6067e995a2eSmrg dst += dst_stride; 6077e995a2eSmrg } 6087e995a2eSmrg } else { 6097e995a2eSmrg for (row = 0; row < height; ++row) { 6107e995a2eSmrg _mesa_pack_float_rgba_row(dst_format, width, 6117e995a2eSmrg (const float (*)[4])tmp_float + row * width, dst); 6127e995a2eSmrg dst += dst_stride; 6137e995a2eSmrg } 6147e995a2eSmrg } 6157e995a2eSmrg 6167e995a2eSmrg free(tmp_float); 6177e995a2eSmrg } else { 6187e995a2eSmrg tmp_ubyte = malloc(width * height * sizeof(*tmp_ubyte)); 6197e995a2eSmrg 6207e995a2eSmrg if (src_format_is_mesa_array_format) { 6217e995a2eSmrg compute_rebased_rgba_component_mapping(src2rgba, rebase_swizzle, 6227e995a2eSmrg rebased_src2rgba); 6237e995a2eSmrg for (row = 0; row < height; ++row) { 6247e995a2eSmrg _mesa_swizzle_and_convert(tmp_ubyte + row * width, 6257e995a2eSmrg MESA_ARRAY_FORMAT_TYPE_UBYTE, 4, 6267e995a2eSmrg src, src_type, src_num_channels, 6277e995a2eSmrg rebased_src2rgba, normalized, width); 6287e995a2eSmrg src += src_stride; 6297e995a2eSmrg } 6307e995a2eSmrg } else { 6317e995a2eSmrg for (row = 0; row < height; ++row) { 6327e995a2eSmrg _mesa_unpack_ubyte_rgba_row(src_format, width, 6337e995a2eSmrg src, tmp_ubyte + row * width); 6347e995a2eSmrg if (rebase_swizzle) 6357e995a2eSmrg _mesa_swizzle_and_convert(tmp_ubyte + row * width, 6367e995a2eSmrg MESA_ARRAY_FORMAT_TYPE_UBYTE, 4, 6377e995a2eSmrg tmp_ubyte + row * width, 6387e995a2eSmrg MESA_ARRAY_FORMAT_TYPE_UBYTE, 4, 6397e995a2eSmrg rebase_swizzle, normalized, width); 6407e995a2eSmrg src += src_stride; 6417e995a2eSmrg } 6427e995a2eSmrg } 6437e995a2eSmrg 6447e995a2eSmrg if (dst_format_is_mesa_array_format) { 6457e995a2eSmrg for (row = 0; row < height; ++row) { 6467e995a2eSmrg _mesa_swizzle_and_convert(dst, dst_type, dst_num_channels, 6477e995a2eSmrg tmp_ubyte + row * width, 6487e995a2eSmrg MESA_ARRAY_FORMAT_TYPE_UBYTE, 4, 6497e995a2eSmrg rgba2dst, normalized, width); 6507e995a2eSmrg dst += dst_stride; 6517e995a2eSmrg } 6527e995a2eSmrg } else { 6537e995a2eSmrg for (row = 0; row < height; ++row) { 6547e995a2eSmrg _mesa_pack_ubyte_rgba_row(dst_format, width, 6551463c08dSmrg (const uint8_t *)(tmp_ubyte + row * width), dst); 6567e995a2eSmrg dst += dst_stride; 6577e995a2eSmrg } 6587e995a2eSmrg } 6597e995a2eSmrg 6607e995a2eSmrg free(tmp_ubyte); 6617e995a2eSmrg } 6627e995a2eSmrg} 663af69d88dSmrg 664af69d88dSmrgstatic const uint8_t map_identity[7] = { 0, 1, 2, 3, 4, 5, 6 }; 6651463c08dSmrg#if UTIL_ARCH_BIG_ENDIAN 666af69d88dSmrgstatic const uint8_t map_3210[7] = { 3, 2, 1, 0, 4, 5, 6 }; 667af69d88dSmrgstatic const uint8_t map_1032[7] = { 1, 0, 3, 2, 4, 5, 6 }; 6681463c08dSmrg#endif 669af69d88dSmrg 670af69d88dSmrg/** 671af69d88dSmrg * Describes a format as an array format, if possible 672af69d88dSmrg * 673af69d88dSmrg * A helper function for figuring out if a (possibly packed) format is 674af69d88dSmrg * actually an array format and, if so, what the array parameters are. 675af69d88dSmrg * 676af69d88dSmrg * \param[in] format the mesa format 677af69d88dSmrg * \param[out] type the GL type of the array (GL_BYTE, etc.) 678af69d88dSmrg * \param[out] num_components the number of components in the array 679af69d88dSmrg * \param[out] swizzle a swizzle describing how to get from the 680af69d88dSmrg * given format to RGBA 681af69d88dSmrg * \param[out] normalized for integer formats, this represents whether 682af69d88dSmrg * the format is a normalized integer or a 683af69d88dSmrg * regular integer 684af69d88dSmrg * \return true if this format is an array format, false otherwise 685af69d88dSmrg */ 686af69d88dSmrgbool 687af69d88dSmrg_mesa_format_to_array(mesa_format format, GLenum *type, int *num_components, 688af69d88dSmrg uint8_t swizzle[4], bool *normalized) 689af69d88dSmrg{ 690af69d88dSmrg int i; 691af69d88dSmrg GLuint format_components; 692af69d88dSmrg uint8_t packed_swizzle[4]; 693af69d88dSmrg const uint8_t *endian; 694af69d88dSmrg 695af69d88dSmrg if (_mesa_is_format_compressed(format)) 696af69d88dSmrg return false; 697af69d88dSmrg 698af69d88dSmrg *normalized = !_mesa_is_format_integer(format); 699af69d88dSmrg 7007e995a2eSmrg _mesa_uncompressed_format_to_type_and_comps(format, type, &format_components); 701af69d88dSmrg 702af69d88dSmrg switch (_mesa_get_format_layout(format)) { 703af69d88dSmrg case MESA_FORMAT_LAYOUT_ARRAY: 704af69d88dSmrg *num_components = format_components; 705af69d88dSmrg _mesa_get_format_swizzle(format, swizzle); 706af69d88dSmrg return true; 707af69d88dSmrg case MESA_FORMAT_LAYOUT_PACKED: 708af69d88dSmrg switch (*type) { 709af69d88dSmrg case GL_UNSIGNED_BYTE: 710af69d88dSmrg case GL_BYTE: 711af69d88dSmrg if (_mesa_get_format_max_bits(format) != 8) 712af69d88dSmrg return false; 713af69d88dSmrg *num_components = _mesa_get_format_bytes(format); 714af69d88dSmrg switch (*num_components) { 715af69d88dSmrg case 1: 716af69d88dSmrg endian = map_identity; 717af69d88dSmrg break; 718af69d88dSmrg case 2: 7191463c08dSmrg#if UTIL_ARCH_LITTLE_ENDIAN 7201463c08dSmrg endian = map_identity; 7211463c08dSmrg#else 7221463c08dSmrg endian = map_1032; 7231463c08dSmrg#endif 724af69d88dSmrg break; 725af69d88dSmrg case 4: 7261463c08dSmrg#if UTIL_ARCH_LITTLE_ENDIAN 7271463c08dSmrg endian = map_identity; 7281463c08dSmrg#else 7291463c08dSmrg endian = map_3210; 7301463c08dSmrg#endif 731af69d88dSmrg break; 732af69d88dSmrg default: 733af69d88dSmrg endian = map_identity; 734af69d88dSmrg assert(!"Invalid number of components"); 735af69d88dSmrg } 736af69d88dSmrg break; 737af69d88dSmrg case GL_UNSIGNED_SHORT: 738af69d88dSmrg case GL_SHORT: 739af69d88dSmrg case GL_HALF_FLOAT: 740af69d88dSmrg if (_mesa_get_format_max_bits(format) != 16) 741af69d88dSmrg return false; 742af69d88dSmrg *num_components = _mesa_get_format_bytes(format) / 2; 743af69d88dSmrg switch (*num_components) { 744af69d88dSmrg case 1: 745af69d88dSmrg endian = map_identity; 746af69d88dSmrg break; 747af69d88dSmrg case 2: 7481463c08dSmrg#if UTIL_ARCH_LITTLE_ENDIAN 7491463c08dSmrg endian = map_identity; 7501463c08dSmrg#else 7511463c08dSmrg endian = map_1032; 7521463c08dSmrg#endif 753af69d88dSmrg break; 754af69d88dSmrg default: 755af69d88dSmrg endian = map_identity; 756af69d88dSmrg assert(!"Invalid number of components"); 757af69d88dSmrg } 758af69d88dSmrg break; 759af69d88dSmrg case GL_UNSIGNED_INT: 760af69d88dSmrg case GL_INT: 761af69d88dSmrg case GL_FLOAT: 762af69d88dSmrg /* This isn't packed. At least not really. */ 763af69d88dSmrg assert(format_components == 1); 764af69d88dSmrg if (_mesa_get_format_max_bits(format) != 32) 765af69d88dSmrg return false; 766af69d88dSmrg *num_components = format_components; 767af69d88dSmrg endian = map_identity; 768af69d88dSmrg break; 769af69d88dSmrg default: 770af69d88dSmrg return false; 771af69d88dSmrg } 772af69d88dSmrg 773af69d88dSmrg _mesa_get_format_swizzle(format, packed_swizzle); 774af69d88dSmrg 775af69d88dSmrg for (i = 0; i < 4; ++i) 776af69d88dSmrg swizzle[i] = endian[packed_swizzle[i]]; 777af69d88dSmrg 778af69d88dSmrg return true; 779af69d88dSmrg case MESA_FORMAT_LAYOUT_OTHER: 780af69d88dSmrg default: 781af69d88dSmrg return false; 782af69d88dSmrg } 783af69d88dSmrg} 784af69d88dSmrg 785af69d88dSmrg/** 786af69d88dSmrg * Attempts to perform the given swizzle-and-convert operation with memcpy 787af69d88dSmrg * 788af69d88dSmrg * This function determines if the given swizzle-and-convert operation can 789af69d88dSmrg * be done with a simple memcpy and, if so, does the memcpy. If not, it 790af69d88dSmrg * returns false and we fall back to the standard version below. 791af69d88dSmrg * 792af69d88dSmrg * The arguments are exactly the same as for _mesa_swizzle_and_convert 793af69d88dSmrg * 794af69d88dSmrg * \return true if it successfully performed the swizzle-and-convert 795af69d88dSmrg * operation with memcpy, false otherwise 796af69d88dSmrg */ 797af69d88dSmrgstatic bool 7987e995a2eSmrgswizzle_convert_try_memcpy(void *dst, 7997e995a2eSmrg enum mesa_array_format_datatype dst_type, 8007e995a2eSmrg int num_dst_channels, 8017e995a2eSmrg const void *src, 8027e995a2eSmrg enum mesa_array_format_datatype src_type, 8037e995a2eSmrg int num_src_channels, 804af69d88dSmrg const uint8_t swizzle[4], bool normalized, int count) 805af69d88dSmrg{ 806af69d88dSmrg int i; 807af69d88dSmrg 808af69d88dSmrg if (src_type != dst_type) 809af69d88dSmrg return false; 810af69d88dSmrg if (num_src_channels != num_dst_channels) 811af69d88dSmrg return false; 812af69d88dSmrg 813af69d88dSmrg for (i = 0; i < num_dst_channels; ++i) 814af69d88dSmrg if (swizzle[i] != i && swizzle[i] != MESA_FORMAT_SWIZZLE_NONE) 815af69d88dSmrg return false; 816af69d88dSmrg 8177e995a2eSmrg memcpy(dst, src, count * num_src_channels * 8187e995a2eSmrg _mesa_array_format_datatype_get_size(src_type)); 819af69d88dSmrg 820af69d88dSmrg return true; 821af69d88dSmrg} 822af69d88dSmrg 823af69d88dSmrg/** 824af69d88dSmrg * Represents a single instance of the standard swizzle-and-convert loop 825af69d88dSmrg * 826af69d88dSmrg * Any swizzle-and-convert operation simply loops through the pixels and 827af69d88dSmrg * performs the transformation operation one pixel at a time. This macro 828af69d88dSmrg * embodies one instance of the conversion loop. This way we can do all 829af69d88dSmrg * control flow outside of the loop and allow the compiler to unroll 830af69d88dSmrg * everything inside the loop. 831af69d88dSmrg * 832af69d88dSmrg * Note: This loop is carefully crafted for performance. Be careful when 833af69d88dSmrg * changing it and run some benchmarks to ensure no performance regressions 834af69d88dSmrg * if you do. 835af69d88dSmrg * 836af69d88dSmrg * \param DST_TYPE the C datatype of the destination 837af69d88dSmrg * \param DST_CHANS the number of destination channels 838af69d88dSmrg * \param SRC_TYPE the C datatype of the source 839af69d88dSmrg * \param SRC_CHANS the number of source channels 840af69d88dSmrg * \param CONV an expression for converting from the source data, 841af69d88dSmrg * storred in the variable "src", to the destination 842af69d88dSmrg * format 843af69d88dSmrg */ 844af69d88dSmrg#define SWIZZLE_CONVERT_LOOP(DST_TYPE, DST_CHANS, SRC_TYPE, SRC_CHANS, CONV) \ 8457e995a2eSmrg do { \ 8467e995a2eSmrg int s, j; \ 8477e995a2eSmrg for (s = 0; s < count; ++s) { \ 8487e995a2eSmrg for (j = 0; j < SRC_CHANS; ++j) { \ 8497e995a2eSmrg SRC_TYPE src = typed_src[j]; \ 8507e995a2eSmrg tmp[j] = CONV; \ 8517e995a2eSmrg } \ 8527e995a2eSmrg \ 8537e995a2eSmrg typed_dst[0] = tmp[swizzle_x]; \ 8547e995a2eSmrg if (DST_CHANS > 1) { \ 8557e995a2eSmrg typed_dst[1] = tmp[swizzle_y]; \ 8567e995a2eSmrg if (DST_CHANS > 2) { \ 8577e995a2eSmrg typed_dst[2] = tmp[swizzle_z]; \ 8587e995a2eSmrg if (DST_CHANS > 3) { \ 8597e995a2eSmrg typed_dst[3] = tmp[swizzle_w]; \ 8607e995a2eSmrg } \ 8617e995a2eSmrg } \ 8627e995a2eSmrg } \ 8637e995a2eSmrg typed_src += SRC_CHANS; \ 8647e995a2eSmrg typed_dst += DST_CHANS; \ 8657e995a2eSmrg } \ 8667e995a2eSmrg } while (0) 867af69d88dSmrg 868af69d88dSmrg/** 869af69d88dSmrg * Represents a single swizzle-and-convert operation 870af69d88dSmrg * 871af69d88dSmrg * This macro represents everything done in a single swizzle-and-convert 872af69d88dSmrg * operation. The actual work is done by the SWIZZLE_CONVERT_LOOP macro. 873af69d88dSmrg * This macro acts as a wrapper that uses a nested switch to ensure that 874af69d88dSmrg * all looping parameters get unrolled. 875af69d88dSmrg * 876af69d88dSmrg * This macro makes assumptions about variables etc. in the calling 877af69d88dSmrg * function. Changes to _mesa_swizzle_and_convert may require changes to 878af69d88dSmrg * this macro. 879af69d88dSmrg * 880af69d88dSmrg * \param DST_TYPE the C datatype of the destination 881af69d88dSmrg * \param SRC_TYPE the C datatype of the source 882af69d88dSmrg * \param CONV an expression for converting from the source data, 883af69d88dSmrg * storred in the variable "src", to the destination 884af69d88dSmrg * format 885af69d88dSmrg */ 886af69d88dSmrg#define SWIZZLE_CONVERT(DST_TYPE, SRC_TYPE, CONV) \ 887af69d88dSmrg do { \ 8887e995a2eSmrg const uint8_t swizzle_x = swizzle[0]; \ 8897e995a2eSmrg const uint8_t swizzle_y = swizzle[1]; \ 8907e995a2eSmrg const uint8_t swizzle_z = swizzle[2]; \ 8917e995a2eSmrg const uint8_t swizzle_w = swizzle[3]; \ 892af69d88dSmrg const SRC_TYPE *typed_src = void_src; \ 893af69d88dSmrg DST_TYPE *typed_dst = void_dst; \ 894af69d88dSmrg DST_TYPE tmp[7]; \ 895af69d88dSmrg tmp[4] = 0; \ 896af69d88dSmrg tmp[5] = one; \ 897af69d88dSmrg switch (num_dst_channels) { \ 898af69d88dSmrg case 1: \ 899af69d88dSmrg switch (num_src_channels) { \ 900af69d88dSmrg case 1: \ 9017e995a2eSmrg SWIZZLE_CONVERT_LOOP(DST_TYPE, 1, SRC_TYPE, 1, CONV); \ 902af69d88dSmrg break; \ 903af69d88dSmrg case 2: \ 9047e995a2eSmrg SWIZZLE_CONVERT_LOOP(DST_TYPE, 1, SRC_TYPE, 2, CONV); \ 905af69d88dSmrg break; \ 906af69d88dSmrg case 3: \ 9077e995a2eSmrg SWIZZLE_CONVERT_LOOP(DST_TYPE, 1, SRC_TYPE, 3, CONV); \ 908af69d88dSmrg break; \ 909af69d88dSmrg case 4: \ 9107e995a2eSmrg SWIZZLE_CONVERT_LOOP(DST_TYPE, 1, SRC_TYPE, 4, CONV); \ 911af69d88dSmrg break; \ 912af69d88dSmrg } \ 913af69d88dSmrg break; \ 914af69d88dSmrg case 2: \ 915af69d88dSmrg switch (num_src_channels) { \ 916af69d88dSmrg case 1: \ 9177e995a2eSmrg SWIZZLE_CONVERT_LOOP(DST_TYPE, 2, SRC_TYPE, 1, CONV); \ 918af69d88dSmrg break; \ 919af69d88dSmrg case 2: \ 9207e995a2eSmrg SWIZZLE_CONVERT_LOOP(DST_TYPE, 2, SRC_TYPE, 2, CONV); \ 921af69d88dSmrg break; \ 922af69d88dSmrg case 3: \ 9237e995a2eSmrg SWIZZLE_CONVERT_LOOP(DST_TYPE, 2, SRC_TYPE, 3, CONV); \ 924af69d88dSmrg break; \ 925af69d88dSmrg case 4: \ 9267e995a2eSmrg SWIZZLE_CONVERT_LOOP(DST_TYPE, 2, SRC_TYPE, 4, CONV); \ 927af69d88dSmrg break; \ 928af69d88dSmrg } \ 929af69d88dSmrg break; \ 930af69d88dSmrg case 3: \ 931af69d88dSmrg switch (num_src_channels) { \ 932af69d88dSmrg case 1: \ 9337e995a2eSmrg SWIZZLE_CONVERT_LOOP(DST_TYPE, 3, SRC_TYPE, 1, CONV); \ 934af69d88dSmrg break; \ 935af69d88dSmrg case 2: \ 9367e995a2eSmrg SWIZZLE_CONVERT_LOOP(DST_TYPE, 3, SRC_TYPE, 2, CONV); \ 937af69d88dSmrg break; \ 938af69d88dSmrg case 3: \ 9397e995a2eSmrg SWIZZLE_CONVERT_LOOP(DST_TYPE, 3, SRC_TYPE, 3, CONV); \ 940af69d88dSmrg break; \ 941af69d88dSmrg case 4: \ 9427e995a2eSmrg SWIZZLE_CONVERT_LOOP(DST_TYPE, 3, SRC_TYPE, 4, CONV); \ 943af69d88dSmrg break; \ 944af69d88dSmrg } \ 945af69d88dSmrg break; \ 946af69d88dSmrg case 4: \ 947af69d88dSmrg switch (num_src_channels) { \ 948af69d88dSmrg case 1: \ 9497e995a2eSmrg SWIZZLE_CONVERT_LOOP(DST_TYPE, 4, SRC_TYPE, 1, CONV); \ 950af69d88dSmrg break; \ 951af69d88dSmrg case 2: \ 9527e995a2eSmrg SWIZZLE_CONVERT_LOOP(DST_TYPE, 4, SRC_TYPE, 2, CONV); \ 953af69d88dSmrg break; \ 954af69d88dSmrg case 3: \ 9557e995a2eSmrg SWIZZLE_CONVERT_LOOP(DST_TYPE, 4, SRC_TYPE, 3, CONV); \ 956af69d88dSmrg break; \ 957af69d88dSmrg case 4: \ 9587e995a2eSmrg SWIZZLE_CONVERT_LOOP(DST_TYPE, 4, SRC_TYPE, 4, CONV); \ 959af69d88dSmrg break; \ 960af69d88dSmrg } \ 961af69d88dSmrg break; \ 962af69d88dSmrg } \ 9637e995a2eSmrg } while (0) 9647e995a2eSmrg 965af69d88dSmrg 966427dc834Schristosstatic void 9677e995a2eSmrgconvert_float(void *void_dst, int num_dst_channels, 9687e995a2eSmrg const void *void_src, GLenum src_type, int num_src_channels, 9697e995a2eSmrg const uint8_t swizzle[4], bool normalized, int count) 970af69d88dSmrg{ 9717e995a2eSmrg const float one = 1.0f; 972af69d88dSmrg 9737e995a2eSmrg switch (src_type) { 9747e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_FLOAT: 9757e995a2eSmrg SWIZZLE_CONVERT(float, float, src); 9767e995a2eSmrg break; 9777e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_HALF: 9787e995a2eSmrg SWIZZLE_CONVERT(float, uint16_t, _mesa_half_to_float(src)); 9797e995a2eSmrg break; 9807e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_UBYTE: 9817e995a2eSmrg if (normalized) { 9827e995a2eSmrg SWIZZLE_CONVERT(float, uint8_t, _mesa_unorm_to_float(src, 8)); 9837e995a2eSmrg } else { 9847e995a2eSmrg SWIZZLE_CONVERT(float, uint8_t, src); 9857e995a2eSmrg } 9867e995a2eSmrg break; 9877e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_BYTE: 9887e995a2eSmrg if (normalized) { 9897e995a2eSmrg SWIZZLE_CONVERT(float, int8_t, _mesa_snorm_to_float(src, 8)); 9907e995a2eSmrg } else { 9917e995a2eSmrg SWIZZLE_CONVERT(float, int8_t, src); 992af69d88dSmrg } 9937e995a2eSmrg break; 9947e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_USHORT: 9957e995a2eSmrg if (normalized) { 9967e995a2eSmrg SWIZZLE_CONVERT(float, uint16_t, _mesa_unorm_to_float(src, 16)); 9977e995a2eSmrg } else { 9987e995a2eSmrg SWIZZLE_CONVERT(float, uint16_t, src); 9997e995a2eSmrg } 10007e995a2eSmrg break; 10017e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_SHORT: 10027e995a2eSmrg if (normalized) { 10037e995a2eSmrg SWIZZLE_CONVERT(float, int16_t, _mesa_snorm_to_float(src, 16)); 10047e995a2eSmrg } else { 10057e995a2eSmrg SWIZZLE_CONVERT(float, int16_t, src); 10067e995a2eSmrg } 10077e995a2eSmrg break; 10087e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_UINT: 10097e995a2eSmrg if (normalized) { 10107e995a2eSmrg SWIZZLE_CONVERT(float, uint32_t, _mesa_unorm_to_float(src, 32)); 10117e995a2eSmrg } else { 10127e995a2eSmrg SWIZZLE_CONVERT(float, uint32_t, src); 10137e995a2eSmrg } 10147e995a2eSmrg break; 10157e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_INT: 10167e995a2eSmrg if (normalized) { 10177e995a2eSmrg SWIZZLE_CONVERT(float, int32_t, _mesa_snorm_to_float(src, 32)); 10187e995a2eSmrg } else { 10197e995a2eSmrg SWIZZLE_CONVERT(float, int32_t, src); 10207e995a2eSmrg } 10217e995a2eSmrg break; 10227e995a2eSmrg default: 10237e995a2eSmrg assert(!"Invalid channel type combination"); 1024af69d88dSmrg } 1025427dc834Schristos} 1026427dc834Schristos 10277e995a2eSmrg 1028427dc834Schristosstatic void 10297e995a2eSmrgconvert_half_float(void *void_dst, int num_dst_channels, 10307e995a2eSmrg const void *void_src, GLenum src_type, int num_src_channels, 10317e995a2eSmrg const uint8_t swizzle[4], bool normalized, int count) 1032427dc834Schristos{ 10337e995a2eSmrg const uint16_t one = _mesa_float_to_half(1.0f); 1034427dc834Schristos 10357e995a2eSmrg switch (src_type) { 10367e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_FLOAT: 10377e995a2eSmrg SWIZZLE_CONVERT(uint16_t, float, _mesa_float_to_half(src)); 10387e995a2eSmrg break; 10397e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_HALF: 10407e995a2eSmrg SWIZZLE_CONVERT(uint16_t, uint16_t, src); 10417e995a2eSmrg break; 10427e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_UBYTE: 10437e995a2eSmrg if (normalized) { 10447e995a2eSmrg SWIZZLE_CONVERT(uint16_t, uint8_t, _mesa_unorm_to_half(src, 8)); 10457e995a2eSmrg } else { 10467e995a2eSmrg SWIZZLE_CONVERT(uint16_t, uint8_t, _mesa_float_to_half(src)); 10477e995a2eSmrg } 10487e995a2eSmrg break; 10497e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_BYTE: 10507e995a2eSmrg if (normalized) { 10517e995a2eSmrg SWIZZLE_CONVERT(uint16_t, int8_t, _mesa_snorm_to_half(src, 8)); 10527e995a2eSmrg } else { 10537e995a2eSmrg SWIZZLE_CONVERT(uint16_t, int8_t, _mesa_float_to_half(src)); 1054af69d88dSmrg } 10557e995a2eSmrg break; 10567e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_USHORT: 10577e995a2eSmrg if (normalized) { 10587e995a2eSmrg SWIZZLE_CONVERT(uint16_t, uint16_t, _mesa_unorm_to_half(src, 16)); 10597e995a2eSmrg } else { 10607e995a2eSmrg SWIZZLE_CONVERT(uint16_t, uint16_t, _mesa_float_to_half(src)); 10617e995a2eSmrg } 10627e995a2eSmrg break; 10637e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_SHORT: 10647e995a2eSmrg if (normalized) { 10657e995a2eSmrg SWIZZLE_CONVERT(uint16_t, int16_t, _mesa_snorm_to_half(src, 16)); 10667e995a2eSmrg } else { 10677e995a2eSmrg SWIZZLE_CONVERT(uint16_t, int16_t, _mesa_float_to_half(src)); 10687e995a2eSmrg } 10697e995a2eSmrg break; 10707e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_UINT: 10717e995a2eSmrg if (normalized) { 10727e995a2eSmrg SWIZZLE_CONVERT(uint16_t, uint32_t, _mesa_unorm_to_half(src, 32)); 10737e995a2eSmrg } else { 10747e995a2eSmrg SWIZZLE_CONVERT(uint16_t, uint32_t, _mesa_float_to_half(src)); 10757e995a2eSmrg } 10767e995a2eSmrg break; 10777e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_INT: 10787e995a2eSmrg if (normalized) { 10797e995a2eSmrg SWIZZLE_CONVERT(uint16_t, int32_t, _mesa_snorm_to_half(src, 32)); 10807e995a2eSmrg } else { 10817e995a2eSmrg SWIZZLE_CONVERT(uint16_t, int32_t, _mesa_float_to_half(src)); 10827e995a2eSmrg } 10837e995a2eSmrg break; 10847e995a2eSmrg default: 10857e995a2eSmrg assert(!"Invalid channel type combination"); 1086af69d88dSmrg } 1087427dc834Schristos} 1088427dc834Schristos 1089427dc834Schristosstatic void 10907e995a2eSmrgconvert_ubyte(void *void_dst, int num_dst_channels, 10917e995a2eSmrg const void *void_src, GLenum src_type, int num_src_channels, 10927e995a2eSmrg const uint8_t swizzle[4], bool normalized, int count) 1093427dc834Schristos{ 10947e995a2eSmrg const uint8_t one = normalized ? UINT8_MAX : 1; 1095427dc834Schristos 10967e995a2eSmrg switch (src_type) { 10977e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_FLOAT: 10987e995a2eSmrg if (normalized) { 10997e995a2eSmrg SWIZZLE_CONVERT(uint8_t, float, _mesa_float_to_unorm(src, 8)); 11007e995a2eSmrg } else { 11017e995a2eSmrg SWIZZLE_CONVERT(uint8_t, float, _mesa_float_to_unsigned(src, 8)); 11027e995a2eSmrg } 11037e995a2eSmrg break; 11047e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_HALF: 11057e995a2eSmrg if (normalized) { 11067e995a2eSmrg SWIZZLE_CONVERT(uint8_t, uint16_t, _mesa_half_to_unorm(src, 8)); 11077e995a2eSmrg } else { 11087e995a2eSmrg SWIZZLE_CONVERT(uint8_t, uint16_t, _mesa_half_to_unsigned(src, 8)); 11097e995a2eSmrg } 11107e995a2eSmrg break; 11117e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_UBYTE: 11127e995a2eSmrg SWIZZLE_CONVERT(uint8_t, uint8_t, src); 11137e995a2eSmrg break; 11147e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_BYTE: 11157e995a2eSmrg if (normalized) { 11167e995a2eSmrg SWIZZLE_CONVERT(uint8_t, int8_t, _mesa_snorm_to_unorm(src, 8, 8)); 11177e995a2eSmrg } else { 11187e995a2eSmrg SWIZZLE_CONVERT(uint8_t, int8_t, _mesa_signed_to_unsigned(src, 8)); 11197e995a2eSmrg } 11207e995a2eSmrg break; 11217e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_USHORT: 11227e995a2eSmrg if (normalized) { 11237e995a2eSmrg SWIZZLE_CONVERT(uint8_t, uint16_t, _mesa_unorm_to_unorm(src, 16, 8)); 11247e995a2eSmrg } else { 11257e995a2eSmrg SWIZZLE_CONVERT(uint8_t, uint16_t, _mesa_unsigned_to_unsigned(src, 8)); 1126af69d88dSmrg } 11277e995a2eSmrg break; 11287e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_SHORT: 11297e995a2eSmrg if (normalized) { 11307e995a2eSmrg SWIZZLE_CONVERT(uint8_t, int16_t, _mesa_snorm_to_unorm(src, 16, 8)); 11317e995a2eSmrg } else { 11327e995a2eSmrg SWIZZLE_CONVERT(uint8_t, int16_t, _mesa_signed_to_unsigned(src, 8)); 11337e995a2eSmrg } 11347e995a2eSmrg break; 11357e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_UINT: 11367e995a2eSmrg if (normalized) { 11377e995a2eSmrg SWIZZLE_CONVERT(uint8_t, uint32_t, _mesa_unorm_to_unorm(src, 32, 8)); 11387e995a2eSmrg } else { 11397e995a2eSmrg SWIZZLE_CONVERT(uint8_t, uint32_t, _mesa_unsigned_to_unsigned(src, 8)); 11407e995a2eSmrg } 11417e995a2eSmrg break; 11427e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_INT: 11437e995a2eSmrg if (normalized) { 11447e995a2eSmrg SWIZZLE_CONVERT(uint8_t, int32_t, _mesa_snorm_to_unorm(src, 32, 8)); 11457e995a2eSmrg } else { 11467e995a2eSmrg SWIZZLE_CONVERT(uint8_t, int32_t, _mesa_signed_to_unsigned(src, 8)); 11477e995a2eSmrg } 11487e995a2eSmrg break; 11497e995a2eSmrg default: 11507e995a2eSmrg assert(!"Invalid channel type combination"); 1151af69d88dSmrg } 1152427dc834Schristos} 1153427dc834Schristos 11547e995a2eSmrg 1155427dc834Schristosstatic void 11567e995a2eSmrgconvert_byte(void *void_dst, int num_dst_channels, 11577e995a2eSmrg const void *void_src, GLenum src_type, int num_src_channels, 11587e995a2eSmrg const uint8_t swizzle[4], bool normalized, int count) 1159427dc834Schristos{ 11607e995a2eSmrg const int8_t one = normalized ? INT8_MAX : 1; 1161427dc834Schristos 11627e995a2eSmrg switch (src_type) { 11637e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_FLOAT: 11647e995a2eSmrg if (normalized) { 11657e995a2eSmrg SWIZZLE_CONVERT(uint8_t, float, _mesa_float_to_snorm(src, 8)); 11667e995a2eSmrg } else { 11677e995a2eSmrg SWIZZLE_CONVERT(uint8_t, float, _mesa_float_to_signed(src, 8)); 11687e995a2eSmrg } 11697e995a2eSmrg break; 11707e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_HALF: 11717e995a2eSmrg if (normalized) { 11727e995a2eSmrg SWIZZLE_CONVERT(uint8_t, uint16_t, _mesa_half_to_snorm(src, 8)); 11737e995a2eSmrg } else { 11747e995a2eSmrg SWIZZLE_CONVERT(uint8_t, uint16_t, _mesa_half_to_signed(src, 8)); 11757e995a2eSmrg } 11767e995a2eSmrg break; 11777e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_UBYTE: 11787e995a2eSmrg if (normalized) { 11797e995a2eSmrg SWIZZLE_CONVERT(int8_t, uint8_t, _mesa_unorm_to_snorm(src, 8, 8)); 11807e995a2eSmrg } else { 11817e995a2eSmrg SWIZZLE_CONVERT(int8_t, uint8_t, _mesa_unsigned_to_signed(src, 8)); 11827e995a2eSmrg } 11837e995a2eSmrg break; 11847e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_BYTE: 11857e995a2eSmrg SWIZZLE_CONVERT(int8_t, int8_t, src); 11867e995a2eSmrg break; 11877e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_USHORT: 11887e995a2eSmrg if (normalized) { 11897e995a2eSmrg SWIZZLE_CONVERT(int8_t, uint16_t, _mesa_unorm_to_snorm(src, 16, 8)); 11907e995a2eSmrg } else { 11917e995a2eSmrg SWIZZLE_CONVERT(int8_t, uint16_t, _mesa_unsigned_to_signed(src, 8)); 11927e995a2eSmrg } 11937e995a2eSmrg break; 11947e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_SHORT: 11957e995a2eSmrg if (normalized) { 11967e995a2eSmrg SWIZZLE_CONVERT(int8_t, int16_t, _mesa_snorm_to_snorm(src, 16, 8)); 11977e995a2eSmrg } else { 11987e995a2eSmrg SWIZZLE_CONVERT(int8_t, int16_t, _mesa_signed_to_signed(src, 8)); 1199af69d88dSmrg } 12007e995a2eSmrg break; 12017e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_UINT: 12027e995a2eSmrg if (normalized) { 12037e995a2eSmrg SWIZZLE_CONVERT(int8_t, uint32_t, _mesa_unorm_to_snorm(src, 32, 8)); 12047e995a2eSmrg } else { 12057e995a2eSmrg SWIZZLE_CONVERT(int8_t, uint32_t, _mesa_unsigned_to_signed(src, 8)); 12067e995a2eSmrg } 12077e995a2eSmrg break; 12087e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_INT: 12097e995a2eSmrg if (normalized) { 12107e995a2eSmrg SWIZZLE_CONVERT(int8_t, int32_t, _mesa_snorm_to_snorm(src, 32, 8)); 12117e995a2eSmrg } else { 12127e995a2eSmrg SWIZZLE_CONVERT(int8_t, int32_t, _mesa_signed_to_signed(src, 8)); 12137e995a2eSmrg } 12147e995a2eSmrg break; 12157e995a2eSmrg default: 12167e995a2eSmrg assert(!"Invalid channel type combination"); 1217af69d88dSmrg } 1218427dc834Schristos} 1219427dc834Schristos 12207e995a2eSmrg 1221427dc834Schristosstatic void 12227e995a2eSmrgconvert_ushort(void *void_dst, int num_dst_channels, 12237e995a2eSmrg const void *void_src, GLenum src_type, int num_src_channels, 12247e995a2eSmrg const uint8_t swizzle[4], bool normalized, int count) 1225427dc834Schristos{ 12267e995a2eSmrg const uint16_t one = normalized ? UINT16_MAX : 1; 12277e995a2eSmrg 12287e995a2eSmrg switch (src_type) { 12297e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_FLOAT: 12307e995a2eSmrg if (normalized) { 12317e995a2eSmrg SWIZZLE_CONVERT(uint16_t, float, _mesa_float_to_unorm(src, 16)); 12327e995a2eSmrg } else { 12337e995a2eSmrg SWIZZLE_CONVERT(uint16_t, float, _mesa_float_to_unsigned(src, 16)); 12347e995a2eSmrg } 12357e995a2eSmrg break; 12367e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_HALF: 12377e995a2eSmrg if (normalized) { 12387e995a2eSmrg SWIZZLE_CONVERT(uint16_t, uint16_t, _mesa_half_to_unorm(src, 16)); 12397e995a2eSmrg } else { 12407e995a2eSmrg SWIZZLE_CONVERT(uint16_t, uint16_t, _mesa_half_to_unsigned(src, 16)); 1241af69d88dSmrg } 12427e995a2eSmrg break; 12437e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_UBYTE: 12447e995a2eSmrg if (normalized) { 12457e995a2eSmrg SWIZZLE_CONVERT(uint16_t, uint8_t, _mesa_unorm_to_unorm(src, 8, 16)); 12467e995a2eSmrg } else { 12477e995a2eSmrg SWIZZLE_CONVERT(uint16_t, uint8_t, src); 12487e995a2eSmrg } 12497e995a2eSmrg break; 12507e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_BYTE: 12517e995a2eSmrg if (normalized) { 12527e995a2eSmrg SWIZZLE_CONVERT(uint16_t, int8_t, _mesa_snorm_to_unorm(src, 8, 16)); 12537e995a2eSmrg } else { 12547e995a2eSmrg SWIZZLE_CONVERT(uint16_t, int8_t, _mesa_signed_to_unsigned(src, 16)); 12557e995a2eSmrg } 12567e995a2eSmrg break; 12577e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_USHORT: 12587e995a2eSmrg SWIZZLE_CONVERT(uint16_t, uint16_t, src); 12597e995a2eSmrg break; 12607e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_SHORT: 12617e995a2eSmrg if (normalized) { 12627e995a2eSmrg SWIZZLE_CONVERT(uint16_t, int16_t, _mesa_snorm_to_unorm(src, 16, 16)); 12637e995a2eSmrg } else { 12647e995a2eSmrg SWIZZLE_CONVERT(uint16_t, int16_t, _mesa_signed_to_unsigned(src, 16)); 12657e995a2eSmrg } 12667e995a2eSmrg break; 12677e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_UINT: 12687e995a2eSmrg if (normalized) { 12697e995a2eSmrg SWIZZLE_CONVERT(uint16_t, uint32_t, _mesa_unorm_to_unorm(src, 32, 16)); 12707e995a2eSmrg } else { 12717e995a2eSmrg SWIZZLE_CONVERT(uint16_t, uint32_t, _mesa_unsigned_to_unsigned(src, 16)); 12727e995a2eSmrg } 12737e995a2eSmrg break; 12747e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_INT: 12757e995a2eSmrg if (normalized) { 12767e995a2eSmrg SWIZZLE_CONVERT(uint16_t, int32_t, _mesa_snorm_to_unorm(src, 32, 16)); 12777e995a2eSmrg } else { 12787e995a2eSmrg SWIZZLE_CONVERT(uint16_t, int32_t, _mesa_signed_to_unsigned(src, 16)); 12797e995a2eSmrg } 12807e995a2eSmrg break; 12817e995a2eSmrg default: 12827e995a2eSmrg assert(!"Invalid channel type combination"); 1283af69d88dSmrg } 1284427dc834Schristos} 1285427dc834Schristos 12867e995a2eSmrg 1287427dc834Schristosstatic void 12887e995a2eSmrgconvert_short(void *void_dst, int num_dst_channels, 12897e995a2eSmrg const void *void_src, GLenum src_type, int num_src_channels, 12907e995a2eSmrg const uint8_t swizzle[4], bool normalized, int count) 1291427dc834Schristos{ 12927e995a2eSmrg const int16_t one = normalized ? INT16_MAX : 1; 1293427dc834Schristos 12947e995a2eSmrg switch (src_type) { 12957e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_FLOAT: 12967e995a2eSmrg if (normalized) { 12977e995a2eSmrg SWIZZLE_CONVERT(uint16_t, float, _mesa_float_to_snorm(src, 16)); 12987e995a2eSmrg } else { 12997e995a2eSmrg SWIZZLE_CONVERT(uint16_t, float, _mesa_float_to_signed(src, 16)); 13007e995a2eSmrg } 13017e995a2eSmrg break; 13027e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_HALF: 13037e995a2eSmrg if (normalized) { 13047e995a2eSmrg SWIZZLE_CONVERT(uint16_t, uint16_t, _mesa_half_to_snorm(src, 16)); 13057e995a2eSmrg } else { 13067e995a2eSmrg SWIZZLE_CONVERT(uint16_t, uint16_t, _mesa_half_to_signed(src, 16)); 13077e995a2eSmrg } 13087e995a2eSmrg break; 13097e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_UBYTE: 13107e995a2eSmrg if (normalized) { 13117e995a2eSmrg SWIZZLE_CONVERT(int16_t, uint8_t, _mesa_unorm_to_snorm(src, 8, 16)); 13127e995a2eSmrg } else { 13137e995a2eSmrg SWIZZLE_CONVERT(int16_t, uint8_t, src); 13147e995a2eSmrg } 13157e995a2eSmrg break; 13167e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_BYTE: 13177e995a2eSmrg if (normalized) { 13187e995a2eSmrg SWIZZLE_CONVERT(int16_t, int8_t, _mesa_snorm_to_snorm(src, 8, 16)); 13197e995a2eSmrg } else { 13207e995a2eSmrg SWIZZLE_CONVERT(int16_t, int8_t, src); 13217e995a2eSmrg } 13227e995a2eSmrg break; 13237e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_USHORT: 13247e995a2eSmrg if (normalized) { 13257e995a2eSmrg SWIZZLE_CONVERT(int16_t, uint16_t, _mesa_unorm_to_snorm(src, 16, 16)); 13267e995a2eSmrg } else { 13277e995a2eSmrg SWIZZLE_CONVERT(int16_t, uint16_t, _mesa_unsigned_to_signed(src, 16)); 13287e995a2eSmrg } 13297e995a2eSmrg break; 13307e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_SHORT: 13317e995a2eSmrg SWIZZLE_CONVERT(int16_t, int16_t, src); 13327e995a2eSmrg break; 13337e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_UINT: 13347e995a2eSmrg if (normalized) { 13357e995a2eSmrg SWIZZLE_CONVERT(int16_t, uint32_t, _mesa_unorm_to_snorm(src, 32, 16)); 13367e995a2eSmrg } else { 13377e995a2eSmrg SWIZZLE_CONVERT(int16_t, uint32_t, _mesa_unsigned_to_signed(src, 16)); 1338af69d88dSmrg } 13397e995a2eSmrg break; 13407e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_INT: 13417e995a2eSmrg if (normalized) { 13427e995a2eSmrg SWIZZLE_CONVERT(int16_t, int32_t, _mesa_snorm_to_snorm(src, 32, 16)); 13437e995a2eSmrg } else { 13447e995a2eSmrg SWIZZLE_CONVERT(int16_t, int32_t, _mesa_signed_to_signed(src, 16)); 13457e995a2eSmrg } 13467e995a2eSmrg break; 13477e995a2eSmrg default: 13487e995a2eSmrg assert(!"Invalid channel type combination"); 1349af69d88dSmrg } 1350427dc834Schristos} 1351427dc834Schristos 1352427dc834Schristosstatic void 13537e995a2eSmrgconvert_uint(void *void_dst, int num_dst_channels, 13547e995a2eSmrg const void *void_src, GLenum src_type, int num_src_channels, 13557e995a2eSmrg const uint8_t swizzle[4], bool normalized, int count) 1356427dc834Schristos{ 13577e995a2eSmrg const uint32_t one = normalized ? UINT32_MAX : 1; 13587e995a2eSmrg 13597e995a2eSmrg switch (src_type) { 13607e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_FLOAT: 13617e995a2eSmrg if (normalized) { 13627e995a2eSmrg SWIZZLE_CONVERT(uint32_t, float, _mesa_float_to_unorm(src, 32)); 13637e995a2eSmrg } else { 13647e995a2eSmrg SWIZZLE_CONVERT(uint32_t, float, _mesa_float_to_unsigned(src, 32)); 13657e995a2eSmrg } 13667e995a2eSmrg break; 13677e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_HALF: 13687e995a2eSmrg if (normalized) { 13697e995a2eSmrg SWIZZLE_CONVERT(uint32_t, uint16_t, _mesa_half_to_unorm(src, 32)); 13707e995a2eSmrg } else { 13717e995a2eSmrg SWIZZLE_CONVERT(uint32_t, uint16_t, _mesa_half_to_unsigned(src, 32)); 13727e995a2eSmrg } 13737e995a2eSmrg break; 13747e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_UBYTE: 13757e995a2eSmrg if (normalized) { 13767e995a2eSmrg SWIZZLE_CONVERT(uint32_t, uint8_t, _mesa_unorm_to_unorm(src, 8, 32)); 13777e995a2eSmrg } else { 13787e995a2eSmrg SWIZZLE_CONVERT(uint32_t, uint8_t, src); 13797e995a2eSmrg } 13807e995a2eSmrg break; 13817e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_BYTE: 13827e995a2eSmrg if (normalized) { 13837e995a2eSmrg SWIZZLE_CONVERT(uint32_t, int8_t, _mesa_snorm_to_unorm(src, 8, 32)); 13847e995a2eSmrg } else { 13857e995a2eSmrg SWIZZLE_CONVERT(uint32_t, int8_t, _mesa_signed_to_unsigned(src, 32)); 13867e995a2eSmrg } 13877e995a2eSmrg break; 13887e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_USHORT: 13897e995a2eSmrg if (normalized) { 13907e995a2eSmrg SWIZZLE_CONVERT(uint32_t, uint16_t, _mesa_unorm_to_unorm(src, 16, 32)); 13917e995a2eSmrg } else { 13927e995a2eSmrg SWIZZLE_CONVERT(uint32_t, uint16_t, src); 1393af69d88dSmrg } 13947e995a2eSmrg break; 13957e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_SHORT: 13967e995a2eSmrg if (normalized) { 13977e995a2eSmrg SWIZZLE_CONVERT(uint32_t, int16_t, _mesa_snorm_to_unorm(src, 16, 32)); 13987e995a2eSmrg } else { 13997e995a2eSmrg SWIZZLE_CONVERT(uint32_t, int16_t, _mesa_signed_to_unsigned(src, 32)); 14007e995a2eSmrg } 14017e995a2eSmrg break; 14027e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_UINT: 14037e995a2eSmrg SWIZZLE_CONVERT(uint32_t, uint32_t, src); 14047e995a2eSmrg break; 14057e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_INT: 14067e995a2eSmrg if (normalized) { 14077e995a2eSmrg SWIZZLE_CONVERT(uint32_t, int32_t, _mesa_snorm_to_unorm(src, 32, 32)); 14087e995a2eSmrg } else { 14097e995a2eSmrg SWIZZLE_CONVERT(uint32_t, int32_t, _mesa_signed_to_unsigned(src, 32)); 14107e995a2eSmrg } 14117e995a2eSmrg break; 14127e995a2eSmrg default: 14137e995a2eSmrg assert(!"Invalid channel type combination"); 1414af69d88dSmrg } 1415427dc834Schristos} 1416427dc834Schristos 14177e995a2eSmrg 1418427dc834Schristosstatic void 14197e995a2eSmrgconvert_int(void *void_dst, int num_dst_channels, 14207e995a2eSmrg const void *void_src, GLenum src_type, int num_src_channels, 14217e995a2eSmrg const uint8_t swizzle[4], bool normalized, int count) 1422427dc834Schristos{ 14237e995a2eSmrg const int32_t one = normalized ? INT32_MAX : 1; 1424427dc834Schristos 14257e995a2eSmrg switch (src_type) { 14267e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_FLOAT: 14277e995a2eSmrg if (normalized) { 14287e995a2eSmrg SWIZZLE_CONVERT(uint32_t, float, _mesa_float_to_snorm(src, 32)); 14297e995a2eSmrg } else { 14307e995a2eSmrg SWIZZLE_CONVERT(uint32_t, float, _mesa_float_to_signed(src, 32)); 14317e995a2eSmrg } 14327e995a2eSmrg break; 14337e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_HALF: 14347e995a2eSmrg if (normalized) { 14357e995a2eSmrg SWIZZLE_CONVERT(uint32_t, uint16_t, _mesa_half_to_snorm(src, 32)); 14367e995a2eSmrg } else { 14377e995a2eSmrg SWIZZLE_CONVERT(uint32_t, uint16_t, _mesa_half_to_signed(src, 32)); 14387e995a2eSmrg } 14397e995a2eSmrg break; 14407e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_UBYTE: 14417e995a2eSmrg if (normalized) { 14427e995a2eSmrg SWIZZLE_CONVERT(int32_t, uint8_t, _mesa_unorm_to_snorm(src, 8, 32)); 14437e995a2eSmrg } else { 14447e995a2eSmrg SWIZZLE_CONVERT(int32_t, uint8_t, src); 14457e995a2eSmrg } 14467e995a2eSmrg break; 14477e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_BYTE: 14487e995a2eSmrg if (normalized) { 14497e995a2eSmrg SWIZZLE_CONVERT(int32_t, int8_t, _mesa_snorm_to_snorm(src, 8, 32)); 14507e995a2eSmrg } else { 14517e995a2eSmrg SWIZZLE_CONVERT(int32_t, int8_t, src); 1452af69d88dSmrg } 14537e995a2eSmrg break; 14547e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_USHORT: 14557e995a2eSmrg if (normalized) { 14567e995a2eSmrg SWIZZLE_CONVERT(int32_t, uint16_t, _mesa_unorm_to_snorm(src, 16, 32)); 14577e995a2eSmrg } else { 14587e995a2eSmrg SWIZZLE_CONVERT(int32_t, uint16_t, src); 14597e995a2eSmrg } 14607e995a2eSmrg break; 14617e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_SHORT: 14627e995a2eSmrg if (normalized) { 14637e995a2eSmrg SWIZZLE_CONVERT(int32_t, int16_t, _mesa_snorm_to_snorm(src, 16, 32)); 14647e995a2eSmrg } else { 14657e995a2eSmrg SWIZZLE_CONVERT(int32_t, int16_t, src); 14667e995a2eSmrg } 14677e995a2eSmrg break; 14687e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_UINT: 14697e995a2eSmrg if (normalized) { 14707e995a2eSmrg SWIZZLE_CONVERT(int32_t, uint32_t, _mesa_unorm_to_snorm(src, 32, 32)); 14717e995a2eSmrg } else { 14727e995a2eSmrg SWIZZLE_CONVERT(int32_t, uint32_t, _mesa_unsigned_to_signed(src, 32)); 14737e995a2eSmrg } 14747e995a2eSmrg break; 14757e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_INT: 14767e995a2eSmrg SWIZZLE_CONVERT(int32_t, int32_t, src); 14777e995a2eSmrg break; 14787e995a2eSmrg default: 14797e995a2eSmrg assert(!"Invalid channel type combination"); 1480af69d88dSmrg } 1481427dc834Schristos} 1482427dc834Schristos 14837e995a2eSmrg 14847e995a2eSmrg/** 14857e995a2eSmrg * Convert between array-based color formats. 14867e995a2eSmrg * 14877e995a2eSmrg * Most format conversion operations required by GL can be performed by 14887e995a2eSmrg * converting one channel at a time, shuffling the channels around, and 14897e995a2eSmrg * optionally filling missing channels with zeros and ones. This function 14907e995a2eSmrg * does just that in a general, yet efficient, way. 14917e995a2eSmrg * 14927e995a2eSmrg * The swizzle parameter is an array of 4 numbers (see 14937e995a2eSmrg * _mesa_get_format_swizzle) that describes where each channel in the 14947e995a2eSmrg * destination should come from in the source. If swizzle[i] < 4 then it 14957e995a2eSmrg * means that dst[i] = CONVERT(src[swizzle[i]]). If swizzle[i] is 14967e995a2eSmrg * MESA_FORMAT_SWIZZLE_ZERO or MESA_FORMAT_SWIZZLE_ONE, the corresponding 14977e995a2eSmrg * dst[i] will be filled with the appropreate representation of zero or one 14987e995a2eSmrg * respectively. 14997e995a2eSmrg * 15007e995a2eSmrg * Under most circumstances, the source and destination images must be 15017e995a2eSmrg * different as no care is taken not to clobber one with the other. 15027e995a2eSmrg * However, if they have the same number of bits per pixel, it is safe to 15037e995a2eSmrg * do an in-place conversion. 15047e995a2eSmrg * 15057e995a2eSmrg * \param[out] dst pointer to where the converted data should 15067e995a2eSmrg * be stored 15077e995a2eSmrg * 15087e995a2eSmrg * \param[in] dst_type the destination GL type of the converted 15097e995a2eSmrg * data (GL_BYTE, etc.) 15107e995a2eSmrg * 15117e995a2eSmrg * \param[in] num_dst_channels the number of channels in the converted 15127e995a2eSmrg * data 15137e995a2eSmrg * 15147e995a2eSmrg * \param[in] src pointer to the source data 15157e995a2eSmrg * 15167e995a2eSmrg * \param[in] src_type the GL type of the source data (GL_BYTE, 15177e995a2eSmrg * etc.) 15187e995a2eSmrg * 15197e995a2eSmrg * \param[in] num_src_channels the number of channels in the source data 15207e995a2eSmrg * (the number of channels total, not just 15217e995a2eSmrg * the number used) 15227e995a2eSmrg * 15237e995a2eSmrg * \param[in] swizzle describes how to get the destination data 15247e995a2eSmrg * from the source data. 15257e995a2eSmrg * 15267e995a2eSmrg * \param[in] normalized for integer types, this indicates whether 15277e995a2eSmrg * the data should be considered as integers 15287e995a2eSmrg * or as normalized integers; 15297e995a2eSmrg * 15307e995a2eSmrg * \param[in] count the number of pixels to convert 15317e995a2eSmrg */ 1532427dc834Schristosvoid 15337e995a2eSmrg_mesa_swizzle_and_convert(void *void_dst, enum mesa_array_format_datatype dst_type, int num_dst_channels, 15347e995a2eSmrg const void *void_src, enum mesa_array_format_datatype src_type, int num_src_channels, 1535427dc834Schristos const uint8_t swizzle[4], bool normalized, int count) 1536427dc834Schristos{ 1537427dc834Schristos if (swizzle_convert_try_memcpy(void_dst, dst_type, num_dst_channels, 1538427dc834Schristos void_src, src_type, num_src_channels, 1539427dc834Schristos swizzle, normalized, count)) 1540427dc834Schristos return; 1541427dc834Schristos 1542427dc834Schristos switch (dst_type) { 15437e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_FLOAT: 15447e995a2eSmrg convert_float(void_dst, num_dst_channels, void_src, src_type, 15457e995a2eSmrg num_src_channels, swizzle, normalized, count); 15467e995a2eSmrg break; 15477e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_HALF: 15487e995a2eSmrg convert_half_float(void_dst, num_dst_channels, void_src, src_type, 15497e995a2eSmrg num_src_channels, swizzle, normalized, count); 15507e995a2eSmrg break; 15517e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_UBYTE: 15527e995a2eSmrg convert_ubyte(void_dst, num_dst_channels, void_src, src_type, 15537e995a2eSmrg num_src_channels, swizzle, normalized, count); 15547e995a2eSmrg break; 15557e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_BYTE: 15567e995a2eSmrg convert_byte(void_dst, num_dst_channels, void_src, src_type, 15577e995a2eSmrg num_src_channels, swizzle, normalized, count); 15587e995a2eSmrg break; 15597e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_USHORT: 15607e995a2eSmrg convert_ushort(void_dst, num_dst_channels, void_src, src_type, 15617e995a2eSmrg num_src_channels, swizzle, normalized, count); 15627e995a2eSmrg break; 15637e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_SHORT: 15647e995a2eSmrg convert_short(void_dst, num_dst_channels, void_src, src_type, 15657e995a2eSmrg num_src_channels, swizzle, normalized, count); 15667e995a2eSmrg break; 15677e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_UINT: 15687e995a2eSmrg convert_uint(void_dst, num_dst_channels, void_src, src_type, 15697e995a2eSmrg num_src_channels, swizzle, normalized, count); 15707e995a2eSmrg break; 15717e995a2eSmrg case MESA_ARRAY_FORMAT_TYPE_INT: 15727e995a2eSmrg convert_int(void_dst, num_dst_channels, void_src, src_type, 15737e995a2eSmrg num_src_channels, swizzle, normalized, count); 1574427dc834Schristos break; 1575af69d88dSmrg default: 1576af69d88dSmrg assert(!"Invalid channel type"); 1577af69d88dSmrg } 1578af69d88dSmrg} 1579