1848b8605Smrg/* 2848b8605Smrg * Mesa 3-D graphics library 3848b8605Smrg * 4848b8605Smrg * Copyright (C) 2014 Intel Corporation All Rights Reserved. 5848b8605Smrg * 6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 7848b8605Smrg * copy of this software and associated documentation files (the "Software"), 8848b8605Smrg * to deal in the Software without restriction, including without limitation 9848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 11848b8605Smrg * Software is furnished to do so, subject to the following conditions: 12848b8605Smrg * 13848b8605Smrg * The above copyright notice and this permission notice shall be included 14848b8605Smrg * in all copies or substantial portions of the Software. 15848b8605Smrg * 16848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE. 23848b8605Smrg */ 24848b8605Smrg 25b8e80941Smrg#include "errors.h" 26848b8605Smrg#include "format_utils.h" 27848b8605Smrg#include "glformats.h" 28b8e80941Smrg#include "format_pack.h" 29b8e80941Smrg#include "format_unpack.h" 30b8e80941Smrg 31b8e80941Smrgconst mesa_array_format RGBA32_FLOAT = 32b8e80941Smrg MESA_ARRAY_FORMAT(4, 1, 1, 1, 4, 0, 1, 2, 3); 33b8e80941Smrg 34b8e80941Smrgconst mesa_array_format RGBA8_UBYTE = 35b8e80941Smrg MESA_ARRAY_FORMAT(1, 0, 0, 1, 4, 0, 1, 2, 3); 36b8e80941Smrg 37b8e80941Smrgconst mesa_array_format RGBA32_UINT = 38b8e80941Smrg MESA_ARRAY_FORMAT(4, 0, 0, 0, 4, 0, 1, 2, 3); 39b8e80941Smrg 40b8e80941Smrgconst mesa_array_format RGBA32_INT = 41b8e80941Smrg MESA_ARRAY_FORMAT(4, 1, 0, 0, 4, 0, 1, 2, 3); 42b8e80941Smrg 43b8e80941Smrgstatic void 44b8e80941Smrginvert_swizzle(uint8_t dst[4], const uint8_t src[4]) 45b8e80941Smrg{ 46b8e80941Smrg int i, j; 47b8e80941Smrg 48b8e80941Smrg dst[0] = MESA_FORMAT_SWIZZLE_NONE; 49b8e80941Smrg dst[1] = MESA_FORMAT_SWIZZLE_NONE; 50b8e80941Smrg dst[2] = MESA_FORMAT_SWIZZLE_NONE; 51b8e80941Smrg dst[3] = MESA_FORMAT_SWIZZLE_NONE; 52b8e80941Smrg 53b8e80941Smrg for (i = 0; i < 4; ++i) 54b8e80941Smrg for (j = 0; j < 4; ++j) 55b8e80941Smrg if (src[j] == i && dst[i] == MESA_FORMAT_SWIZZLE_NONE) 56b8e80941Smrg dst[i] = j; 57b8e80941Smrg} 58b8e80941Smrg 59b8e80941Smrg/* Takes a src to RGBA swizzle and applies a rebase swizzle to it. This 60b8e80941Smrg * is used when we need to rebase a format to match a different 61b8e80941Smrg * base internal format. 62b8e80941Smrg * 63b8e80941Smrg * The rebase swizzle can be NULL, which means that no rebase is necessary, 64b8e80941Smrg * in which case the src to RGBA swizzle is copied to the output without 65b8e80941Smrg * changes. 66b8e80941Smrg * 67b8e80941Smrg * The resulting rebased swizzle and well as the input swizzles are 68b8e80941Smrg * all 4-element swizzles, but the rebase swizzle can be NULL if no rebase 69b8e80941Smrg * is necessary. 70b8e80941Smrg */ 71b8e80941Smrgstatic void 72b8e80941Smrgcompute_rebased_rgba_component_mapping(uint8_t *src2rgba, 73b8e80941Smrg uint8_t *rebase_swizzle, 74b8e80941Smrg uint8_t *rebased_src2rgba) 75b8e80941Smrg{ 76b8e80941Smrg int i; 77b8e80941Smrg 78b8e80941Smrg if (rebase_swizzle) { 79b8e80941Smrg for (i = 0; i < 4; i++) { 80b8e80941Smrg if (rebase_swizzle[i] > MESA_FORMAT_SWIZZLE_W) 81b8e80941Smrg rebased_src2rgba[i] = rebase_swizzle[i]; 82b8e80941Smrg else 83b8e80941Smrg rebased_src2rgba[i] = src2rgba[rebase_swizzle[i]]; 84b8e80941Smrg } 85b8e80941Smrg } else { 86b8e80941Smrg /* No rebase needed, so src2rgba is all that we need */ 87b8e80941Smrg memcpy(rebased_src2rgba, src2rgba, 4 * sizeof(uint8_t)); 88b8e80941Smrg } 89b8e80941Smrg} 90b8e80941Smrg 91b8e80941Smrg/* Computes the final swizzle transform to apply from src to dst in a 92b8e80941Smrg * conversion that might involve a rebase swizzle. 93b8e80941Smrg * 94b8e80941Smrg * This is used to compute the swizzle transform to apply in conversions 95b8e80941Smrg * between array formats where we have a src2rgba swizzle, a rgba2dst swizzle 96b8e80941Smrg * and possibly, a rebase swizzle. 97b8e80941Smrg * 98b8e80941Smrg * The final swizzle transform to apply (src2dst) when a rebase swizzle is 99b8e80941Smrg * involved is: src -> rgba -> base -> rgba -> dst 100b8e80941Smrg */ 101b8e80941Smrgstatic void 102b8e80941Smrgcompute_src2dst_component_mapping(uint8_t *src2rgba, uint8_t *rgba2dst, 103b8e80941Smrg uint8_t *rebase_swizzle, uint8_t *src2dst) 104b8e80941Smrg{ 105b8e80941Smrg int i; 106b8e80941Smrg 107b8e80941Smrg if (!rebase_swizzle) { 108b8e80941Smrg for (i = 0; i < 4; i++) { 109b8e80941Smrg if (rgba2dst[i] > MESA_FORMAT_SWIZZLE_W) { 110b8e80941Smrg src2dst[i] = rgba2dst[i]; 111b8e80941Smrg } else { 112b8e80941Smrg src2dst[i] = src2rgba[rgba2dst[i]]; 113b8e80941Smrg } 114b8e80941Smrg } 115b8e80941Smrg } else { 116b8e80941Smrg for (i = 0; i < 4; i++) { 117b8e80941Smrg if (rgba2dst[i] > MESA_FORMAT_SWIZZLE_W) { 118b8e80941Smrg src2dst[i] = rgba2dst[i]; 119b8e80941Smrg } else if (rebase_swizzle[rgba2dst[i]] > MESA_FORMAT_SWIZZLE_W) { 120b8e80941Smrg src2dst[i] = rebase_swizzle[rgba2dst[i]]; 121b8e80941Smrg } else { 122b8e80941Smrg src2dst[i] = src2rgba[rebase_swizzle[rgba2dst[i]]]; 123b8e80941Smrg } 124b8e80941Smrg } 125b8e80941Smrg } 126b8e80941Smrg} 127b8e80941Smrg 128b8e80941Smrg/** 129b8e80941Smrg * This function is used by clients of _mesa_format_convert to obtain 130b8e80941Smrg * the rebase swizzle to use in a format conversion based on the base 131b8e80941Smrg * format involved. 132b8e80941Smrg * 133b8e80941Smrg * \param baseFormat the base internal format involved in the conversion. 134b8e80941Smrg * \param map the rebase swizzle to consider 135b8e80941Smrg * 136b8e80941Smrg * This function computes 'map' as rgba -> baseformat -> rgba and returns true 137b8e80941Smrg * if the resulting swizzle transform is not the identity transform (thus, a 138b8e80941Smrg * rebase is needed). If the function returns false then a rebase swizzle 139b8e80941Smrg * is not necessary and the value of 'map' is undefined. In this situation 140b8e80941Smrg * clients of _mesa_format_convert should pass NULL in the 'rebase_swizzle' 141b8e80941Smrg * parameter. 142b8e80941Smrg */ 143b8e80941Smrgbool 144b8e80941Smrg_mesa_compute_rgba2base2rgba_component_mapping(GLenum baseFormat, uint8_t *map) 145b8e80941Smrg{ 146b8e80941Smrg uint8_t rgba2base[6], base2rgba[6]; 147b8e80941Smrg int i; 148b8e80941Smrg 149b8e80941Smrg switch (baseFormat) { 150b8e80941Smrg case GL_ALPHA: 151b8e80941Smrg case GL_RED: 152b8e80941Smrg case GL_GREEN: 153b8e80941Smrg case GL_BLUE: 154b8e80941Smrg case GL_RG: 155b8e80941Smrg case GL_RGB: 156b8e80941Smrg case GL_BGR: 157b8e80941Smrg case GL_RGBA: 158b8e80941Smrg case GL_BGRA: 159b8e80941Smrg case GL_ABGR_EXT: 160b8e80941Smrg case GL_LUMINANCE: 161b8e80941Smrg case GL_INTENSITY: 162b8e80941Smrg case GL_LUMINANCE_ALPHA: 163b8e80941Smrg { 164b8e80941Smrg bool needRebase = false; 165b8e80941Smrg _mesa_compute_component_mapping(GL_RGBA, baseFormat, rgba2base); 166b8e80941Smrg _mesa_compute_component_mapping(baseFormat, GL_RGBA, base2rgba); 167b8e80941Smrg for (i = 0; i < 4; i++) { 168b8e80941Smrg if (base2rgba[i] > MESA_FORMAT_SWIZZLE_W) { 169b8e80941Smrg map[i] = base2rgba[i]; 170b8e80941Smrg } else { 171b8e80941Smrg map[i] = rgba2base[base2rgba[i]]; 172b8e80941Smrg } 173b8e80941Smrg if (map[i] != i) 174b8e80941Smrg needRebase = true; 175b8e80941Smrg } 176b8e80941Smrg return needRebase; 177b8e80941Smrg } 178b8e80941Smrg default: 179b8e80941Smrg unreachable("Unexpected base format"); 180b8e80941Smrg } 181b8e80941Smrg} 182b8e80941Smrg 183b8e80941Smrg 184b8e80941Smrg/** 185b8e80941Smrg * Special case conversion function to swap r/b channels from the source 186b8e80941Smrg * image to the dest image. 187b8e80941Smrg */ 188b8e80941Smrgstatic void 189b8e80941Smrgconvert_ubyte_rgba_to_bgra(size_t width, size_t height, 190b8e80941Smrg const uint8_t *src, size_t src_stride, 191b8e80941Smrg uint8_t *dst, size_t dst_stride) 192b8e80941Smrg{ 193b8e80941Smrg int row; 194b8e80941Smrg 195b8e80941Smrg if (sizeof(void *) == 8 && 196b8e80941Smrg src_stride % 8 == 0 && 197b8e80941Smrg dst_stride % 8 == 0 && 198b8e80941Smrg (GLsizeiptr) src % 8 == 0 && 199b8e80941Smrg (GLsizeiptr) dst % 8 == 0) { 200b8e80941Smrg /* use 64-bit word to swizzle two 32-bit pixels. We need 8-byte 201b8e80941Smrg * alignment for src/dst addresses and strides. 202b8e80941Smrg */ 203b8e80941Smrg for (row = 0; row < height; row++) { 204b8e80941Smrg const GLuint64 *s = (const GLuint64 *) src; 205b8e80941Smrg GLuint64 *d = (GLuint64 *) dst; 206b8e80941Smrg int i; 207b8e80941Smrg for (i = 0; i < width/2; i++) { 208b8e80941Smrg d[i] = ( (s[i] & 0xff00ff00ff00ff00) | 209b8e80941Smrg ((s[i] & 0xff000000ff) << 16) | 210b8e80941Smrg ((s[i] & 0xff000000ff0000) >> 16)); 211b8e80941Smrg } 212b8e80941Smrg if (width & 1) { 213b8e80941Smrg /* handle the case of odd widths */ 214b8e80941Smrg const GLuint s = ((const GLuint *) src)[width - 1]; 215b8e80941Smrg GLuint *d = (GLuint *) dst + width - 1; 216b8e80941Smrg *d = ( (s & 0xff00ff00) | 217b8e80941Smrg ((s & 0xff) << 16) | 218b8e80941Smrg ((s & 0xff0000) >> 16)); 219b8e80941Smrg } 220b8e80941Smrg src += src_stride; 221b8e80941Smrg dst += dst_stride; 222b8e80941Smrg } 223b8e80941Smrg } else { 224b8e80941Smrg for (row = 0; row < height; row++) { 225b8e80941Smrg const GLuint *s = (const GLuint *) src; 226b8e80941Smrg GLuint *d = (GLuint *) dst; 227b8e80941Smrg int i; 228b8e80941Smrg for (i = 0; i < width; i++) { 229b8e80941Smrg d[i] = ( (s[i] & 0xff00ff00) | 230b8e80941Smrg ((s[i] & 0xff) << 16) | 231b8e80941Smrg ((s[i] & 0xff0000) >> 16)); 232b8e80941Smrg } 233b8e80941Smrg src += src_stride; 234b8e80941Smrg dst += dst_stride; 235b8e80941Smrg } 236b8e80941Smrg } 237b8e80941Smrg} 238b8e80941Smrg 239b8e80941Smrg 240b8e80941Smrg/** 241b8e80941Smrg * This can be used to convert between most color formats. 242b8e80941Smrg * 243b8e80941Smrg * Limitations: 244b8e80941Smrg * - This function doesn't handle GL_COLOR_INDEX or YCBCR formats. 245b8e80941Smrg * - This function doesn't handle byte-swapping or transferOps, these should 246b8e80941Smrg * be handled by the caller. 247b8e80941Smrg * 248b8e80941Smrg * \param void_dst The address where converted color data will be stored. 249b8e80941Smrg * The caller must ensure that the buffer is large enough 250b8e80941Smrg * to hold the converted pixel data. 251b8e80941Smrg * \param dst_format The destination color format. It can be a mesa_format 252b8e80941Smrg * or a mesa_array_format represented as an uint32_t. 253b8e80941Smrg * \param dst_stride The stride of the destination format in bytes. 254b8e80941Smrg * \param void_src The address of the source color data to convert. 255b8e80941Smrg * \param src_format The source color format. It can be a mesa_format 256b8e80941Smrg * or a mesa_array_format represented as an uint32_t. 257b8e80941Smrg * \param src_stride The stride of the source format in bytes. 258b8e80941Smrg * \param width The width, in pixels, of the source image to convert. 259b8e80941Smrg * \param height The height, in pixels, of the source image to convert. 260b8e80941Smrg * \param rebase_swizzle A swizzle transform to apply during the conversion, 261b8e80941Smrg * typically used to match a different internal base 262b8e80941Smrg * format involved. NULL if no rebase transform is needed 263b8e80941Smrg * (i.e. the internal base format and the base format of 264b8e80941Smrg * the dst or the src -depending on whether we are doing 265b8e80941Smrg * an upload or a download respectively- are the same). 266b8e80941Smrg */ 267b8e80941Smrgvoid 268b8e80941Smrg_mesa_format_convert(void *void_dst, uint32_t dst_format, size_t dst_stride, 269b8e80941Smrg void *void_src, uint32_t src_format, size_t src_stride, 270b8e80941Smrg size_t width, size_t height, uint8_t *rebase_swizzle) 271b8e80941Smrg{ 272b8e80941Smrg uint8_t *dst = (uint8_t *)void_dst; 273b8e80941Smrg uint8_t *src = (uint8_t *)void_src; 274b8e80941Smrg mesa_array_format src_array_format, dst_array_format; 275b8e80941Smrg bool src_format_is_mesa_array_format, dst_format_is_mesa_array_format; 276b8e80941Smrg uint8_t src2dst[4], src2rgba[4], rgba2dst[4], dst2rgba[4]; 277b8e80941Smrg uint8_t rebased_src2rgba[4]; 278b8e80941Smrg enum mesa_array_format_datatype src_type = 0, dst_type = 0, common_type; 279b8e80941Smrg bool normalized, dst_integer, src_integer, is_signed; 280b8e80941Smrg int src_num_channels = 0, dst_num_channels = 0; 281b8e80941Smrg uint8_t (*tmp_ubyte)[4]; 282b8e80941Smrg float (*tmp_float)[4]; 283b8e80941Smrg uint32_t (*tmp_uint)[4]; 284b8e80941Smrg int bits; 285b8e80941Smrg size_t row; 286b8e80941Smrg 287b8e80941Smrg if (_mesa_format_is_mesa_array_format(src_format)) { 288b8e80941Smrg src_format_is_mesa_array_format = true; 289b8e80941Smrg src_array_format = src_format; 290b8e80941Smrg } else { 291b8e80941Smrg assert(_mesa_is_format_color_format(src_format)); 292b8e80941Smrg src_format_is_mesa_array_format = false; 293b8e80941Smrg src_array_format = _mesa_format_to_array_format(src_format); 294b8e80941Smrg } 295b8e80941Smrg 296b8e80941Smrg if (_mesa_format_is_mesa_array_format(dst_format)) { 297b8e80941Smrg dst_format_is_mesa_array_format = true; 298b8e80941Smrg dst_array_format = dst_format; 299b8e80941Smrg } else { 300b8e80941Smrg assert(_mesa_is_format_color_format(dst_format)); 301b8e80941Smrg dst_format_is_mesa_array_format = false; 302b8e80941Smrg dst_array_format = _mesa_format_to_array_format(dst_format); 303b8e80941Smrg } 304b8e80941Smrg 305b8e80941Smrg /* First we see if we can implement the conversion with a direct pack 306b8e80941Smrg * or unpack. 307b8e80941Smrg * 308b8e80941Smrg * In this case we want to be careful when we need to apply a swizzle to 309b8e80941Smrg * match an internal base format, since in these cases a simple pack/unpack 310b8e80941Smrg * to the dst format from the src format may not match the requirements 311b8e80941Smrg * of the internal base format. For now we decide to be safe and 312b8e80941Smrg * avoid this path in these scenarios but in the future we may want to 313b8e80941Smrg * enable it for specific combinations that are known to work. 314b8e80941Smrg */ 315b8e80941Smrg if (!rebase_swizzle) { 316b8e80941Smrg /* Do a direct memcpy where possible */ 317b8e80941Smrg if ((dst_format_is_mesa_array_format && 318b8e80941Smrg src_format_is_mesa_array_format && 319b8e80941Smrg src_array_format == dst_array_format) || 320b8e80941Smrg src_format == dst_format) { 321b8e80941Smrg int format_size = _mesa_get_format_bytes(src_format); 322b8e80941Smrg for (row = 0; row < height; row++) { 323b8e80941Smrg memcpy(dst, src, width * format_size); 324b8e80941Smrg src += src_stride; 325b8e80941Smrg dst += dst_stride; 326b8e80941Smrg } 327b8e80941Smrg return; 328b8e80941Smrg } 329b8e80941Smrg 330b8e80941Smrg /* Handle the cases where we can directly unpack */ 331b8e80941Smrg if (!src_format_is_mesa_array_format) { 332b8e80941Smrg if (dst_array_format == RGBA32_FLOAT) { 333b8e80941Smrg for (row = 0; row < height; ++row) { 334b8e80941Smrg _mesa_unpack_rgba_row(src_format, width, 335b8e80941Smrg src, (float (*)[4])dst); 336b8e80941Smrg src += src_stride; 337b8e80941Smrg dst += dst_stride; 338b8e80941Smrg } 339b8e80941Smrg return; 340b8e80941Smrg } else if (dst_array_format == RGBA8_UBYTE) { 341b8e80941Smrg assert(!_mesa_is_format_integer_color(src_format)); 342b8e80941Smrg for (row = 0; row < height; ++row) { 343b8e80941Smrg _mesa_unpack_ubyte_rgba_row(src_format, width, 344b8e80941Smrg src, (uint8_t (*)[4])dst); 345b8e80941Smrg src += src_stride; 346b8e80941Smrg dst += dst_stride; 347b8e80941Smrg } 348b8e80941Smrg return; 349b8e80941Smrg } else if (dst_array_format == RGBA32_UINT && 350b8e80941Smrg _mesa_is_format_unsigned(src_format)) { 351b8e80941Smrg assert(_mesa_is_format_integer_color(src_format)); 352b8e80941Smrg for (row = 0; row < height; ++row) { 353b8e80941Smrg _mesa_unpack_uint_rgba_row(src_format, width, 354b8e80941Smrg src, (uint32_t (*)[4])dst); 355b8e80941Smrg src += src_stride; 356b8e80941Smrg dst += dst_stride; 357b8e80941Smrg } 358b8e80941Smrg return; 359b8e80941Smrg } 360b8e80941Smrg } 361b8e80941Smrg 362b8e80941Smrg /* Handle the cases where we can directly pack */ 363b8e80941Smrg if (!dst_format_is_mesa_array_format) { 364b8e80941Smrg if (src_array_format == RGBA32_FLOAT) { 365b8e80941Smrg for (row = 0; row < height; ++row) { 366b8e80941Smrg _mesa_pack_float_rgba_row(dst_format, width, 367b8e80941Smrg (const float (*)[4])src, dst); 368b8e80941Smrg src += src_stride; 369b8e80941Smrg dst += dst_stride; 370b8e80941Smrg } 371b8e80941Smrg return; 372b8e80941Smrg } else if (src_array_format == RGBA8_UBYTE) { 373b8e80941Smrg assert(!_mesa_is_format_integer_color(dst_format)); 374b8e80941Smrg 375b8e80941Smrg if (dst_format == MESA_FORMAT_B8G8R8A8_UNORM) { 376b8e80941Smrg convert_ubyte_rgba_to_bgra(width, height, src, src_stride, 377b8e80941Smrg dst, dst_stride); 378b8e80941Smrg } 379b8e80941Smrg else { 380b8e80941Smrg for (row = 0; row < height; ++row) { 381b8e80941Smrg _mesa_pack_ubyte_rgba_row(dst_format, width, 382b8e80941Smrg (const uint8_t (*)[4])src, dst); 383b8e80941Smrg src += src_stride; 384b8e80941Smrg dst += dst_stride; 385b8e80941Smrg } 386b8e80941Smrg } 387b8e80941Smrg return; 388b8e80941Smrg } else if (src_array_format == RGBA32_UINT && 389b8e80941Smrg _mesa_is_format_unsigned(dst_format)) { 390b8e80941Smrg assert(_mesa_is_format_integer_color(dst_format)); 391b8e80941Smrg for (row = 0; row < height; ++row) { 392b8e80941Smrg _mesa_pack_uint_rgba_row(dst_format, width, 393b8e80941Smrg (const uint32_t (*)[4])src, dst); 394b8e80941Smrg src += src_stride; 395b8e80941Smrg dst += dst_stride; 396b8e80941Smrg } 397b8e80941Smrg return; 398b8e80941Smrg } 399b8e80941Smrg } 400b8e80941Smrg } 401b8e80941Smrg 402b8e80941Smrg /* Handle conversions between array formats */ 403b8e80941Smrg normalized = false; 404b8e80941Smrg if (src_array_format) { 405b8e80941Smrg src_type = _mesa_array_format_get_datatype(src_array_format); 406b8e80941Smrg 407b8e80941Smrg src_num_channels = _mesa_array_format_get_num_channels(src_array_format); 408b8e80941Smrg 409b8e80941Smrg _mesa_array_format_get_swizzle(src_array_format, src2rgba); 410b8e80941Smrg 411b8e80941Smrg normalized = _mesa_array_format_is_normalized(src_array_format); 412b8e80941Smrg } 413b8e80941Smrg 414b8e80941Smrg if (dst_array_format) { 415b8e80941Smrg dst_type = _mesa_array_format_get_datatype(dst_array_format); 416b8e80941Smrg 417b8e80941Smrg dst_num_channels = _mesa_array_format_get_num_channels(dst_array_format); 418b8e80941Smrg 419b8e80941Smrg _mesa_array_format_get_swizzle(dst_array_format, dst2rgba); 420b8e80941Smrg invert_swizzle(rgba2dst, dst2rgba); 421b8e80941Smrg 422b8e80941Smrg normalized |= _mesa_array_format_is_normalized(dst_array_format); 423b8e80941Smrg } 424b8e80941Smrg 425b8e80941Smrg if (src_array_format && dst_array_format) { 426b8e80941Smrg assert(_mesa_array_format_is_normalized(src_array_format) == 427b8e80941Smrg _mesa_array_format_is_normalized(dst_array_format)); 428b8e80941Smrg 429b8e80941Smrg compute_src2dst_component_mapping(src2rgba, rgba2dst, rebase_swizzle, 430b8e80941Smrg src2dst); 431b8e80941Smrg 432b8e80941Smrg for (row = 0; row < height; ++row) { 433b8e80941Smrg _mesa_swizzle_and_convert(dst, dst_type, dst_num_channels, 434b8e80941Smrg src, src_type, src_num_channels, 435b8e80941Smrg src2dst, normalized, width); 436b8e80941Smrg src += src_stride; 437b8e80941Smrg dst += dst_stride; 438b8e80941Smrg } 439b8e80941Smrg return; 440b8e80941Smrg } 441b8e80941Smrg 442b8e80941Smrg /* At this point, we're fresh out of fast-paths and we need to convert 443b8e80941Smrg * to float, uint32, or, if we're lucky, uint8. 444b8e80941Smrg */ 445b8e80941Smrg dst_integer = false; 446b8e80941Smrg src_integer = false; 447b8e80941Smrg 448b8e80941Smrg if (src_array_format) { 449b8e80941Smrg if (!_mesa_array_format_is_float(src_array_format) && 450b8e80941Smrg !_mesa_array_format_is_normalized(src_array_format)) 451b8e80941Smrg src_integer = true; 452b8e80941Smrg } else { 453b8e80941Smrg switch (_mesa_get_format_datatype(src_format)) { 454b8e80941Smrg case GL_UNSIGNED_INT: 455b8e80941Smrg case GL_INT: 456b8e80941Smrg src_integer = true; 457b8e80941Smrg break; 458b8e80941Smrg } 459b8e80941Smrg } 460b8e80941Smrg 461b8e80941Smrg /* If the destination format is signed but the source is unsigned, then we 462b8e80941Smrg * don't loose any data by converting to a signed intermediate format above 463b8e80941Smrg * and beyond the precision that we loose in the conversion itself. If the 464b8e80941Smrg * destination is unsigned then, by using an unsigned intermediate format, 465b8e80941Smrg * we make the conversion function that converts from the source to the 466b8e80941Smrg * intermediate format take care of truncating at zero. The exception here 467b8e80941Smrg * is if the intermediate format is float, in which case the first 468b8e80941Smrg * conversion will leave it signed and the second conversion will truncate 469b8e80941Smrg * at zero. 470b8e80941Smrg */ 471b8e80941Smrg is_signed = false; 472b8e80941Smrg if (dst_array_format) { 473b8e80941Smrg if (!_mesa_array_format_is_float(dst_array_format) && 474b8e80941Smrg !_mesa_array_format_is_normalized(dst_array_format)) 475b8e80941Smrg dst_integer = true; 476b8e80941Smrg is_signed = _mesa_array_format_is_signed(dst_array_format); 477b8e80941Smrg bits = 8 * _mesa_array_format_get_type_size(dst_array_format); 478b8e80941Smrg } else { 479b8e80941Smrg switch (_mesa_get_format_datatype(dst_format)) { 480b8e80941Smrg case GL_UNSIGNED_NORMALIZED: 481b8e80941Smrg is_signed = false; 482b8e80941Smrg break; 483b8e80941Smrg case GL_SIGNED_NORMALIZED: 484b8e80941Smrg is_signed = true; 485b8e80941Smrg break; 486b8e80941Smrg case GL_FLOAT: 487b8e80941Smrg is_signed = true; 488b8e80941Smrg break; 489b8e80941Smrg case GL_UNSIGNED_INT: 490b8e80941Smrg is_signed = false; 491b8e80941Smrg dst_integer = true; 492b8e80941Smrg break; 493b8e80941Smrg case GL_INT: 494b8e80941Smrg is_signed = true; 495b8e80941Smrg dst_integer = true; 496b8e80941Smrg break; 497b8e80941Smrg } 498b8e80941Smrg bits = _mesa_get_format_max_bits(dst_format); 499b8e80941Smrg } 500b8e80941Smrg 501b8e80941Smrg assert(src_integer == dst_integer); 502b8e80941Smrg 503b8e80941Smrg if (src_integer && dst_integer) { 504b8e80941Smrg tmp_uint = malloc(width * height * sizeof(*tmp_uint)); 505b8e80941Smrg 506b8e80941Smrg /* The [un]packing functions for unsigned datatypes treat the 32-bit 507b8e80941Smrg * integer array as signed for signed formats and as unsigned for 508b8e80941Smrg * unsigned formats. This is a bit of a problem if we ever convert from 509b8e80941Smrg * a signed to an unsigned format because the unsigned packing function 510b8e80941Smrg * doesn't know that the input is signed and will treat it as unsigned 511b8e80941Smrg * and not do the trunctation. The thing that saves us here is that all 512b8e80941Smrg * of the packed formats are unsigned, so we can just always use 513b8e80941Smrg * _mesa_swizzle_and_convert for signed formats, which is aware of the 514b8e80941Smrg * truncation problem. 515b8e80941Smrg */ 516b8e80941Smrg common_type = is_signed ? MESA_ARRAY_FORMAT_TYPE_INT : 517b8e80941Smrg MESA_ARRAY_FORMAT_TYPE_UINT; 518b8e80941Smrg if (src_array_format) { 519b8e80941Smrg compute_rebased_rgba_component_mapping(src2rgba, rebase_swizzle, 520b8e80941Smrg rebased_src2rgba); 521b8e80941Smrg for (row = 0; row < height; ++row) { 522b8e80941Smrg _mesa_swizzle_and_convert(tmp_uint + row * width, common_type, 4, 523b8e80941Smrg src, src_type, src_num_channels, 524b8e80941Smrg rebased_src2rgba, normalized, width); 525b8e80941Smrg src += src_stride; 526b8e80941Smrg } 527b8e80941Smrg } else { 528b8e80941Smrg for (row = 0; row < height; ++row) { 529b8e80941Smrg _mesa_unpack_uint_rgba_row(src_format, width, 530b8e80941Smrg src, tmp_uint + row * width); 531b8e80941Smrg if (rebase_swizzle) 532b8e80941Smrg _mesa_swizzle_and_convert(tmp_uint + row * width, common_type, 4, 533b8e80941Smrg tmp_uint + row * width, common_type, 4, 534b8e80941Smrg rebase_swizzle, false, width); 535b8e80941Smrg src += src_stride; 536b8e80941Smrg } 537b8e80941Smrg } 538b8e80941Smrg 539b8e80941Smrg /* At this point, we have already done the truncation if the source is 540b8e80941Smrg * signed but the destination is unsigned, so no need to force the 541b8e80941Smrg * _mesa_swizzle_and_convert path. 542b8e80941Smrg */ 543b8e80941Smrg if (dst_format_is_mesa_array_format) { 544b8e80941Smrg for (row = 0; row < height; ++row) { 545b8e80941Smrg _mesa_swizzle_and_convert(dst, dst_type, dst_num_channels, 546b8e80941Smrg tmp_uint + row * width, common_type, 4, 547b8e80941Smrg rgba2dst, normalized, width); 548b8e80941Smrg dst += dst_stride; 549b8e80941Smrg } 550b8e80941Smrg } else { 551b8e80941Smrg for (row = 0; row < height; ++row) { 552b8e80941Smrg _mesa_pack_uint_rgba_row(dst_format, width, 553b8e80941Smrg (const uint32_t (*)[4])tmp_uint + row * width, dst); 554b8e80941Smrg dst += dst_stride; 555b8e80941Smrg } 556b8e80941Smrg } 557b8e80941Smrg 558b8e80941Smrg free(tmp_uint); 559b8e80941Smrg } else if (is_signed || bits > 8) { 560b8e80941Smrg tmp_float = malloc(width * height * sizeof(*tmp_float)); 561b8e80941Smrg 562b8e80941Smrg if (src_format_is_mesa_array_format) { 563b8e80941Smrg compute_rebased_rgba_component_mapping(src2rgba, rebase_swizzle, 564b8e80941Smrg rebased_src2rgba); 565b8e80941Smrg for (row = 0; row < height; ++row) { 566b8e80941Smrg _mesa_swizzle_and_convert(tmp_float + row * width, 567b8e80941Smrg MESA_ARRAY_FORMAT_TYPE_FLOAT, 4, 568b8e80941Smrg src, src_type, src_num_channels, 569b8e80941Smrg rebased_src2rgba, normalized, width); 570b8e80941Smrg src += src_stride; 571b8e80941Smrg } 572b8e80941Smrg } else { 573b8e80941Smrg for (row = 0; row < height; ++row) { 574b8e80941Smrg _mesa_unpack_rgba_row(src_format, width, 575b8e80941Smrg src, tmp_float + row * width); 576b8e80941Smrg if (rebase_swizzle) 577b8e80941Smrg _mesa_swizzle_and_convert(tmp_float + row * width, 578b8e80941Smrg MESA_ARRAY_FORMAT_TYPE_FLOAT, 4, 579b8e80941Smrg tmp_float + row * width, 580b8e80941Smrg MESA_ARRAY_FORMAT_TYPE_FLOAT, 4, 581b8e80941Smrg rebase_swizzle, normalized, width); 582b8e80941Smrg src += src_stride; 583b8e80941Smrg } 584b8e80941Smrg } 585b8e80941Smrg 586b8e80941Smrg if (dst_format_is_mesa_array_format) { 587b8e80941Smrg for (row = 0; row < height; ++row) { 588b8e80941Smrg _mesa_swizzle_and_convert(dst, dst_type, dst_num_channels, 589b8e80941Smrg tmp_float + row * width, 590b8e80941Smrg MESA_ARRAY_FORMAT_TYPE_FLOAT, 4, 591b8e80941Smrg rgba2dst, normalized, width); 592b8e80941Smrg dst += dst_stride; 593b8e80941Smrg } 594b8e80941Smrg } else { 595b8e80941Smrg for (row = 0; row < height; ++row) { 596b8e80941Smrg _mesa_pack_float_rgba_row(dst_format, width, 597b8e80941Smrg (const float (*)[4])tmp_float + row * width, dst); 598b8e80941Smrg dst += dst_stride; 599b8e80941Smrg } 600b8e80941Smrg } 601b8e80941Smrg 602b8e80941Smrg free(tmp_float); 603b8e80941Smrg } else { 604b8e80941Smrg tmp_ubyte = malloc(width * height * sizeof(*tmp_ubyte)); 605b8e80941Smrg 606b8e80941Smrg if (src_format_is_mesa_array_format) { 607b8e80941Smrg compute_rebased_rgba_component_mapping(src2rgba, rebase_swizzle, 608b8e80941Smrg rebased_src2rgba); 609b8e80941Smrg for (row = 0; row < height; ++row) { 610b8e80941Smrg _mesa_swizzle_and_convert(tmp_ubyte + row * width, 611b8e80941Smrg MESA_ARRAY_FORMAT_TYPE_UBYTE, 4, 612b8e80941Smrg src, src_type, src_num_channels, 613b8e80941Smrg rebased_src2rgba, normalized, width); 614b8e80941Smrg src += src_stride; 615b8e80941Smrg } 616b8e80941Smrg } else { 617b8e80941Smrg for (row = 0; row < height; ++row) { 618b8e80941Smrg _mesa_unpack_ubyte_rgba_row(src_format, width, 619b8e80941Smrg src, tmp_ubyte + row * width); 620b8e80941Smrg if (rebase_swizzle) 621b8e80941Smrg _mesa_swizzle_and_convert(tmp_ubyte + row * width, 622b8e80941Smrg MESA_ARRAY_FORMAT_TYPE_UBYTE, 4, 623b8e80941Smrg tmp_ubyte + row * width, 624b8e80941Smrg MESA_ARRAY_FORMAT_TYPE_UBYTE, 4, 625b8e80941Smrg rebase_swizzle, normalized, width); 626b8e80941Smrg src += src_stride; 627b8e80941Smrg } 628b8e80941Smrg } 629b8e80941Smrg 630b8e80941Smrg if (dst_format_is_mesa_array_format) { 631b8e80941Smrg for (row = 0; row < height; ++row) { 632b8e80941Smrg _mesa_swizzle_and_convert(dst, dst_type, dst_num_channels, 633b8e80941Smrg tmp_ubyte + row * width, 634b8e80941Smrg MESA_ARRAY_FORMAT_TYPE_UBYTE, 4, 635b8e80941Smrg rgba2dst, normalized, width); 636b8e80941Smrg dst += dst_stride; 637b8e80941Smrg } 638b8e80941Smrg } else { 639b8e80941Smrg for (row = 0; row < height; ++row) { 640b8e80941Smrg _mesa_pack_ubyte_rgba_row(dst_format, width, 641b8e80941Smrg (const uint8_t (*)[4])tmp_ubyte + row * width, dst); 642b8e80941Smrg dst += dst_stride; 643b8e80941Smrg } 644b8e80941Smrg } 645b8e80941Smrg 646b8e80941Smrg free(tmp_ubyte); 647b8e80941Smrg } 648b8e80941Smrg} 649848b8605Smrg 650848b8605Smrgstatic const uint8_t map_identity[7] = { 0, 1, 2, 3, 4, 5, 6 }; 651848b8605Smrgstatic const uint8_t map_3210[7] = { 3, 2, 1, 0, 4, 5, 6 }; 652848b8605Smrgstatic const uint8_t map_1032[7] = { 1, 0, 3, 2, 4, 5, 6 }; 653848b8605Smrg 654848b8605Smrg/** 655848b8605Smrg * Describes a format as an array format, if possible 656848b8605Smrg * 657848b8605Smrg * A helper function for figuring out if a (possibly packed) format is 658848b8605Smrg * actually an array format and, if so, what the array parameters are. 659848b8605Smrg * 660848b8605Smrg * \param[in] format the mesa format 661848b8605Smrg * \param[out] type the GL type of the array (GL_BYTE, etc.) 662848b8605Smrg * \param[out] num_components the number of components in the array 663848b8605Smrg * \param[out] swizzle a swizzle describing how to get from the 664848b8605Smrg * given format to RGBA 665848b8605Smrg * \param[out] normalized for integer formats, this represents whether 666848b8605Smrg * the format is a normalized integer or a 667848b8605Smrg * regular integer 668848b8605Smrg * \return true if this format is an array format, false otherwise 669848b8605Smrg */ 670848b8605Smrgbool 671848b8605Smrg_mesa_format_to_array(mesa_format format, GLenum *type, int *num_components, 672848b8605Smrg uint8_t swizzle[4], bool *normalized) 673848b8605Smrg{ 674848b8605Smrg int i; 675848b8605Smrg GLuint format_components; 676848b8605Smrg uint8_t packed_swizzle[4]; 677848b8605Smrg const uint8_t *endian; 678848b8605Smrg 679848b8605Smrg if (_mesa_is_format_compressed(format)) 680848b8605Smrg return false; 681848b8605Smrg 682848b8605Smrg *normalized = !_mesa_is_format_integer(format); 683848b8605Smrg 684b8e80941Smrg _mesa_uncompressed_format_to_type_and_comps(format, type, &format_components); 685848b8605Smrg 686848b8605Smrg switch (_mesa_get_format_layout(format)) { 687848b8605Smrg case MESA_FORMAT_LAYOUT_ARRAY: 688848b8605Smrg *num_components = format_components; 689848b8605Smrg _mesa_get_format_swizzle(format, swizzle); 690848b8605Smrg return true; 691848b8605Smrg case MESA_FORMAT_LAYOUT_PACKED: 692848b8605Smrg switch (*type) { 693848b8605Smrg case GL_UNSIGNED_BYTE: 694848b8605Smrg case GL_BYTE: 695848b8605Smrg if (_mesa_get_format_max_bits(format) != 8) 696848b8605Smrg return false; 697848b8605Smrg *num_components = _mesa_get_format_bytes(format); 698848b8605Smrg switch (*num_components) { 699848b8605Smrg case 1: 700848b8605Smrg endian = map_identity; 701848b8605Smrg break; 702848b8605Smrg case 2: 703848b8605Smrg endian = _mesa_little_endian() ? map_identity : map_1032; 704848b8605Smrg break; 705848b8605Smrg case 4: 706848b8605Smrg endian = _mesa_little_endian() ? map_identity : map_3210; 707848b8605Smrg break; 708848b8605Smrg default: 709848b8605Smrg endian = map_identity; 710848b8605Smrg assert(!"Invalid number of components"); 711848b8605Smrg } 712848b8605Smrg break; 713848b8605Smrg case GL_UNSIGNED_SHORT: 714848b8605Smrg case GL_SHORT: 715848b8605Smrg case GL_HALF_FLOAT: 716848b8605Smrg if (_mesa_get_format_max_bits(format) != 16) 717848b8605Smrg return false; 718848b8605Smrg *num_components = _mesa_get_format_bytes(format) / 2; 719848b8605Smrg switch (*num_components) { 720848b8605Smrg case 1: 721848b8605Smrg endian = map_identity; 722848b8605Smrg break; 723848b8605Smrg case 2: 724848b8605Smrg endian = _mesa_little_endian() ? map_identity : map_1032; 725848b8605Smrg break; 726848b8605Smrg default: 727848b8605Smrg endian = map_identity; 728848b8605Smrg assert(!"Invalid number of components"); 729848b8605Smrg } 730848b8605Smrg break; 731848b8605Smrg case GL_UNSIGNED_INT: 732848b8605Smrg case GL_INT: 733848b8605Smrg case GL_FLOAT: 734848b8605Smrg /* This isn't packed. At least not really. */ 735848b8605Smrg assert(format_components == 1); 736848b8605Smrg if (_mesa_get_format_max_bits(format) != 32) 737848b8605Smrg return false; 738848b8605Smrg *num_components = format_components; 739848b8605Smrg endian = map_identity; 740848b8605Smrg break; 741848b8605Smrg default: 742848b8605Smrg return false; 743848b8605Smrg } 744848b8605Smrg 745848b8605Smrg _mesa_get_format_swizzle(format, packed_swizzle); 746848b8605Smrg 747848b8605Smrg for (i = 0; i < 4; ++i) 748848b8605Smrg swizzle[i] = endian[packed_swizzle[i]]; 749848b8605Smrg 750848b8605Smrg return true; 751848b8605Smrg case MESA_FORMAT_LAYOUT_OTHER: 752848b8605Smrg default: 753848b8605Smrg return false; 754848b8605Smrg } 755848b8605Smrg} 756848b8605Smrg 757848b8605Smrg/** 758848b8605Smrg * Attempts to perform the given swizzle-and-convert operation with memcpy 759848b8605Smrg * 760848b8605Smrg * This function determines if the given swizzle-and-convert operation can 761848b8605Smrg * be done with a simple memcpy and, if so, does the memcpy. If not, it 762848b8605Smrg * returns false and we fall back to the standard version below. 763848b8605Smrg * 764848b8605Smrg * The arguments are exactly the same as for _mesa_swizzle_and_convert 765848b8605Smrg * 766848b8605Smrg * \return true if it successfully performed the swizzle-and-convert 767848b8605Smrg * operation with memcpy, false otherwise 768848b8605Smrg */ 769848b8605Smrgstatic bool 770b8e80941Smrgswizzle_convert_try_memcpy(void *dst, 771b8e80941Smrg enum mesa_array_format_datatype dst_type, 772b8e80941Smrg int num_dst_channels, 773b8e80941Smrg const void *src, 774b8e80941Smrg enum mesa_array_format_datatype src_type, 775b8e80941Smrg int num_src_channels, 776848b8605Smrg const uint8_t swizzle[4], bool normalized, int count) 777848b8605Smrg{ 778848b8605Smrg int i; 779848b8605Smrg 780848b8605Smrg if (src_type != dst_type) 781848b8605Smrg return false; 782848b8605Smrg if (num_src_channels != num_dst_channels) 783848b8605Smrg return false; 784848b8605Smrg 785848b8605Smrg for (i = 0; i < num_dst_channels; ++i) 786848b8605Smrg if (swizzle[i] != i && swizzle[i] != MESA_FORMAT_SWIZZLE_NONE) 787848b8605Smrg return false; 788848b8605Smrg 789b8e80941Smrg memcpy(dst, src, count * num_src_channels * 790b8e80941Smrg _mesa_array_format_datatype_get_size(src_type)); 791848b8605Smrg 792848b8605Smrg return true; 793848b8605Smrg} 794848b8605Smrg 795848b8605Smrg/** 796848b8605Smrg * Represents a single instance of the standard swizzle-and-convert loop 797848b8605Smrg * 798848b8605Smrg * Any swizzle-and-convert operation simply loops through the pixels and 799848b8605Smrg * performs the transformation operation one pixel at a time. This macro 800848b8605Smrg * embodies one instance of the conversion loop. This way we can do all 801848b8605Smrg * control flow outside of the loop and allow the compiler to unroll 802848b8605Smrg * everything inside the loop. 803848b8605Smrg * 804848b8605Smrg * Note: This loop is carefully crafted for performance. Be careful when 805848b8605Smrg * changing it and run some benchmarks to ensure no performance regressions 806848b8605Smrg * if you do. 807848b8605Smrg * 808848b8605Smrg * \param DST_TYPE the C datatype of the destination 809848b8605Smrg * \param DST_CHANS the number of destination channels 810848b8605Smrg * \param SRC_TYPE the C datatype of the source 811848b8605Smrg * \param SRC_CHANS the number of source channels 812848b8605Smrg * \param CONV an expression for converting from the source data, 813848b8605Smrg * storred in the variable "src", to the destination 814848b8605Smrg * format 815848b8605Smrg */ 816848b8605Smrg#define SWIZZLE_CONVERT_LOOP(DST_TYPE, DST_CHANS, SRC_TYPE, SRC_CHANS, CONV) \ 817b8e80941Smrg do { \ 818b8e80941Smrg int s, j; \ 819b8e80941Smrg for (s = 0; s < count; ++s) { \ 820b8e80941Smrg for (j = 0; j < SRC_CHANS; ++j) { \ 821b8e80941Smrg SRC_TYPE src = typed_src[j]; \ 822b8e80941Smrg tmp[j] = CONV; \ 823b8e80941Smrg } \ 824b8e80941Smrg \ 825b8e80941Smrg typed_dst[0] = tmp[swizzle_x]; \ 826b8e80941Smrg if (DST_CHANS > 1) { \ 827b8e80941Smrg typed_dst[1] = tmp[swizzle_y]; \ 828b8e80941Smrg if (DST_CHANS > 2) { \ 829b8e80941Smrg typed_dst[2] = tmp[swizzle_z]; \ 830b8e80941Smrg if (DST_CHANS > 3) { \ 831b8e80941Smrg typed_dst[3] = tmp[swizzle_w]; \ 832b8e80941Smrg } \ 833b8e80941Smrg } \ 834b8e80941Smrg } \ 835b8e80941Smrg typed_src += SRC_CHANS; \ 836b8e80941Smrg typed_dst += DST_CHANS; \ 837b8e80941Smrg } \ 838b8e80941Smrg } while (0) 839848b8605Smrg 840848b8605Smrg/** 841848b8605Smrg * Represents a single swizzle-and-convert operation 842848b8605Smrg * 843848b8605Smrg * This macro represents everything done in a single swizzle-and-convert 844848b8605Smrg * operation. The actual work is done by the SWIZZLE_CONVERT_LOOP macro. 845848b8605Smrg * This macro acts as a wrapper that uses a nested switch to ensure that 846848b8605Smrg * all looping parameters get unrolled. 847848b8605Smrg * 848848b8605Smrg * This macro makes assumptions about variables etc. in the calling 849848b8605Smrg * function. Changes to _mesa_swizzle_and_convert may require changes to 850848b8605Smrg * this macro. 851848b8605Smrg * 852848b8605Smrg * \param DST_TYPE the C datatype of the destination 853848b8605Smrg * \param SRC_TYPE the C datatype of the source 854848b8605Smrg * \param CONV an expression for converting from the source data, 855848b8605Smrg * storred in the variable "src", to the destination 856848b8605Smrg * format 857848b8605Smrg */ 858848b8605Smrg#define SWIZZLE_CONVERT(DST_TYPE, SRC_TYPE, CONV) \ 859848b8605Smrg do { \ 860b8e80941Smrg const uint8_t swizzle_x = swizzle[0]; \ 861b8e80941Smrg const uint8_t swizzle_y = swizzle[1]; \ 862b8e80941Smrg const uint8_t swizzle_z = swizzle[2]; \ 863b8e80941Smrg const uint8_t swizzle_w = swizzle[3]; \ 864848b8605Smrg const SRC_TYPE *typed_src = void_src; \ 865848b8605Smrg DST_TYPE *typed_dst = void_dst; \ 866848b8605Smrg DST_TYPE tmp[7]; \ 867848b8605Smrg tmp[4] = 0; \ 868848b8605Smrg tmp[5] = one; \ 869848b8605Smrg switch (num_dst_channels) { \ 870848b8605Smrg case 1: \ 871848b8605Smrg switch (num_src_channels) { \ 872848b8605Smrg case 1: \ 873b8e80941Smrg SWIZZLE_CONVERT_LOOP(DST_TYPE, 1, SRC_TYPE, 1, CONV); \ 874848b8605Smrg break; \ 875848b8605Smrg case 2: \ 876b8e80941Smrg SWIZZLE_CONVERT_LOOP(DST_TYPE, 1, SRC_TYPE, 2, CONV); \ 877848b8605Smrg break; \ 878848b8605Smrg case 3: \ 879b8e80941Smrg SWIZZLE_CONVERT_LOOP(DST_TYPE, 1, SRC_TYPE, 3, CONV); \ 880848b8605Smrg break; \ 881848b8605Smrg case 4: \ 882b8e80941Smrg SWIZZLE_CONVERT_LOOP(DST_TYPE, 1, SRC_TYPE, 4, CONV); \ 883848b8605Smrg break; \ 884848b8605Smrg } \ 885848b8605Smrg break; \ 886848b8605Smrg case 2: \ 887848b8605Smrg switch (num_src_channels) { \ 888848b8605Smrg case 1: \ 889b8e80941Smrg SWIZZLE_CONVERT_LOOP(DST_TYPE, 2, SRC_TYPE, 1, CONV); \ 890848b8605Smrg break; \ 891848b8605Smrg case 2: \ 892b8e80941Smrg SWIZZLE_CONVERT_LOOP(DST_TYPE, 2, SRC_TYPE, 2, CONV); \ 893848b8605Smrg break; \ 894848b8605Smrg case 3: \ 895b8e80941Smrg SWIZZLE_CONVERT_LOOP(DST_TYPE, 2, SRC_TYPE, 3, CONV); \ 896848b8605Smrg break; \ 897848b8605Smrg case 4: \ 898b8e80941Smrg SWIZZLE_CONVERT_LOOP(DST_TYPE, 2, SRC_TYPE, 4, CONV); \ 899848b8605Smrg break; \ 900848b8605Smrg } \ 901848b8605Smrg break; \ 902848b8605Smrg case 3: \ 903848b8605Smrg switch (num_src_channels) { \ 904848b8605Smrg case 1: \ 905b8e80941Smrg SWIZZLE_CONVERT_LOOP(DST_TYPE, 3, SRC_TYPE, 1, CONV); \ 906848b8605Smrg break; \ 907848b8605Smrg case 2: \ 908b8e80941Smrg SWIZZLE_CONVERT_LOOP(DST_TYPE, 3, SRC_TYPE, 2, CONV); \ 909848b8605Smrg break; \ 910848b8605Smrg case 3: \ 911b8e80941Smrg SWIZZLE_CONVERT_LOOP(DST_TYPE, 3, SRC_TYPE, 3, CONV); \ 912848b8605Smrg break; \ 913848b8605Smrg case 4: \ 914b8e80941Smrg SWIZZLE_CONVERT_LOOP(DST_TYPE, 3, SRC_TYPE, 4, CONV); \ 915848b8605Smrg break; \ 916848b8605Smrg } \ 917848b8605Smrg break; \ 918848b8605Smrg case 4: \ 919848b8605Smrg switch (num_src_channels) { \ 920848b8605Smrg case 1: \ 921b8e80941Smrg SWIZZLE_CONVERT_LOOP(DST_TYPE, 4, SRC_TYPE, 1, CONV); \ 922848b8605Smrg break; \ 923848b8605Smrg case 2: \ 924b8e80941Smrg SWIZZLE_CONVERT_LOOP(DST_TYPE, 4, SRC_TYPE, 2, CONV); \ 925848b8605Smrg break; \ 926848b8605Smrg case 3: \ 927b8e80941Smrg SWIZZLE_CONVERT_LOOP(DST_TYPE, 4, SRC_TYPE, 3, CONV); \ 928848b8605Smrg break; \ 929848b8605Smrg case 4: \ 930b8e80941Smrg SWIZZLE_CONVERT_LOOP(DST_TYPE, 4, SRC_TYPE, 4, CONV); \ 931848b8605Smrg break; \ 932848b8605Smrg } \ 933848b8605Smrg break; \ 934848b8605Smrg } \ 935b8e80941Smrg } while (0) 936b8e80941Smrg 937848b8605Smrg 938848b8605Smrgstatic void 939b8e80941Smrgconvert_float(void *void_dst, int num_dst_channels, 940b8e80941Smrg const void *void_src, GLenum src_type, int num_src_channels, 941b8e80941Smrg const uint8_t swizzle[4], bool normalized, int count) 942848b8605Smrg{ 943b8e80941Smrg const float one = 1.0f; 944848b8605Smrg 945b8e80941Smrg switch (src_type) { 946b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_FLOAT: 947b8e80941Smrg SWIZZLE_CONVERT(float, float, src); 948b8e80941Smrg break; 949b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_HALF: 950b8e80941Smrg SWIZZLE_CONVERT(float, uint16_t, _mesa_half_to_float(src)); 951b8e80941Smrg break; 952b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_UBYTE: 953b8e80941Smrg if (normalized) { 954b8e80941Smrg SWIZZLE_CONVERT(float, uint8_t, _mesa_unorm_to_float(src, 8)); 955b8e80941Smrg } else { 956b8e80941Smrg SWIZZLE_CONVERT(float, uint8_t, src); 957b8e80941Smrg } 958b8e80941Smrg break; 959b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_BYTE: 960b8e80941Smrg if (normalized) { 961b8e80941Smrg SWIZZLE_CONVERT(float, int8_t, _mesa_snorm_to_float(src, 8)); 962b8e80941Smrg } else { 963b8e80941Smrg SWIZZLE_CONVERT(float, int8_t, src); 964848b8605Smrg } 965b8e80941Smrg break; 966b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_USHORT: 967b8e80941Smrg if (normalized) { 968b8e80941Smrg SWIZZLE_CONVERT(float, uint16_t, _mesa_unorm_to_float(src, 16)); 969b8e80941Smrg } else { 970b8e80941Smrg SWIZZLE_CONVERT(float, uint16_t, src); 971b8e80941Smrg } 972b8e80941Smrg break; 973b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_SHORT: 974b8e80941Smrg if (normalized) { 975b8e80941Smrg SWIZZLE_CONVERT(float, int16_t, _mesa_snorm_to_float(src, 16)); 976b8e80941Smrg } else { 977b8e80941Smrg SWIZZLE_CONVERT(float, int16_t, src); 978b8e80941Smrg } 979b8e80941Smrg break; 980b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_UINT: 981b8e80941Smrg if (normalized) { 982b8e80941Smrg SWIZZLE_CONVERT(float, uint32_t, _mesa_unorm_to_float(src, 32)); 983b8e80941Smrg } else { 984b8e80941Smrg SWIZZLE_CONVERT(float, uint32_t, src); 985b8e80941Smrg } 986b8e80941Smrg break; 987b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_INT: 988b8e80941Smrg if (normalized) { 989b8e80941Smrg SWIZZLE_CONVERT(float, int32_t, _mesa_snorm_to_float(src, 32)); 990b8e80941Smrg } else { 991b8e80941Smrg SWIZZLE_CONVERT(float, int32_t, src); 992b8e80941Smrg } 993b8e80941Smrg break; 994b8e80941Smrg default: 995b8e80941Smrg assert(!"Invalid channel type combination"); 996848b8605Smrg } 997848b8605Smrg} 998848b8605Smrg 999b8e80941Smrg 1000848b8605Smrgstatic void 1001b8e80941Smrgconvert_half_float(void *void_dst, int num_dst_channels, 1002b8e80941Smrg const void *void_src, GLenum src_type, int num_src_channels, 1003b8e80941Smrg const uint8_t swizzle[4], bool normalized, int count) 1004848b8605Smrg{ 1005b8e80941Smrg const uint16_t one = _mesa_float_to_half(1.0f); 1006848b8605Smrg 1007b8e80941Smrg switch (src_type) { 1008b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_FLOAT: 1009b8e80941Smrg SWIZZLE_CONVERT(uint16_t, float, _mesa_float_to_half(src)); 1010b8e80941Smrg break; 1011b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_HALF: 1012b8e80941Smrg SWIZZLE_CONVERT(uint16_t, uint16_t, src); 1013b8e80941Smrg break; 1014b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_UBYTE: 1015b8e80941Smrg if (normalized) { 1016b8e80941Smrg SWIZZLE_CONVERT(uint16_t, uint8_t, _mesa_unorm_to_half(src, 8)); 1017b8e80941Smrg } else { 1018b8e80941Smrg SWIZZLE_CONVERT(uint16_t, uint8_t, _mesa_float_to_half(src)); 1019b8e80941Smrg } 1020b8e80941Smrg break; 1021b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_BYTE: 1022b8e80941Smrg if (normalized) { 1023b8e80941Smrg SWIZZLE_CONVERT(uint16_t, int8_t, _mesa_snorm_to_half(src, 8)); 1024b8e80941Smrg } else { 1025b8e80941Smrg SWIZZLE_CONVERT(uint16_t, int8_t, _mesa_float_to_half(src)); 1026848b8605Smrg } 1027b8e80941Smrg break; 1028b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_USHORT: 1029b8e80941Smrg if (normalized) { 1030b8e80941Smrg SWIZZLE_CONVERT(uint16_t, uint16_t, _mesa_unorm_to_half(src, 16)); 1031b8e80941Smrg } else { 1032b8e80941Smrg SWIZZLE_CONVERT(uint16_t, uint16_t, _mesa_float_to_half(src)); 1033b8e80941Smrg } 1034b8e80941Smrg break; 1035b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_SHORT: 1036b8e80941Smrg if (normalized) { 1037b8e80941Smrg SWIZZLE_CONVERT(uint16_t, int16_t, _mesa_snorm_to_half(src, 16)); 1038b8e80941Smrg } else { 1039b8e80941Smrg SWIZZLE_CONVERT(uint16_t, int16_t, _mesa_float_to_half(src)); 1040b8e80941Smrg } 1041b8e80941Smrg break; 1042b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_UINT: 1043b8e80941Smrg if (normalized) { 1044b8e80941Smrg SWIZZLE_CONVERT(uint16_t, uint32_t, _mesa_unorm_to_half(src, 32)); 1045b8e80941Smrg } else { 1046b8e80941Smrg SWIZZLE_CONVERT(uint16_t, uint32_t, _mesa_float_to_half(src)); 1047b8e80941Smrg } 1048b8e80941Smrg break; 1049b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_INT: 1050b8e80941Smrg if (normalized) { 1051b8e80941Smrg SWIZZLE_CONVERT(uint16_t, int32_t, _mesa_snorm_to_half(src, 32)); 1052b8e80941Smrg } else { 1053b8e80941Smrg SWIZZLE_CONVERT(uint16_t, int32_t, _mesa_float_to_half(src)); 1054b8e80941Smrg } 1055b8e80941Smrg break; 1056b8e80941Smrg default: 1057b8e80941Smrg assert(!"Invalid channel type combination"); 1058848b8605Smrg } 1059848b8605Smrg} 1060848b8605Smrg 1061848b8605Smrgstatic void 1062b8e80941Smrgconvert_ubyte(void *void_dst, int num_dst_channels, 1063b8e80941Smrg const void *void_src, GLenum src_type, int num_src_channels, 1064b8e80941Smrg const uint8_t swizzle[4], bool normalized, int count) 1065848b8605Smrg{ 1066b8e80941Smrg const uint8_t one = normalized ? UINT8_MAX : 1; 1067848b8605Smrg 1068b8e80941Smrg switch (src_type) { 1069b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_FLOAT: 1070b8e80941Smrg if (normalized) { 1071b8e80941Smrg SWIZZLE_CONVERT(uint8_t, float, _mesa_float_to_unorm(src, 8)); 1072b8e80941Smrg } else { 1073b8e80941Smrg SWIZZLE_CONVERT(uint8_t, float, _mesa_float_to_unsigned(src, 8)); 1074b8e80941Smrg } 1075b8e80941Smrg break; 1076b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_HALF: 1077b8e80941Smrg if (normalized) { 1078b8e80941Smrg SWIZZLE_CONVERT(uint8_t, uint16_t, _mesa_half_to_unorm(src, 8)); 1079b8e80941Smrg } else { 1080b8e80941Smrg SWIZZLE_CONVERT(uint8_t, uint16_t, _mesa_half_to_unsigned(src, 8)); 1081b8e80941Smrg } 1082b8e80941Smrg break; 1083b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_UBYTE: 1084b8e80941Smrg SWIZZLE_CONVERT(uint8_t, uint8_t, src); 1085b8e80941Smrg break; 1086b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_BYTE: 1087b8e80941Smrg if (normalized) { 1088b8e80941Smrg SWIZZLE_CONVERT(uint8_t, int8_t, _mesa_snorm_to_unorm(src, 8, 8)); 1089b8e80941Smrg } else { 1090b8e80941Smrg SWIZZLE_CONVERT(uint8_t, int8_t, _mesa_signed_to_unsigned(src, 8)); 1091b8e80941Smrg } 1092b8e80941Smrg break; 1093b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_USHORT: 1094b8e80941Smrg if (normalized) { 1095b8e80941Smrg SWIZZLE_CONVERT(uint8_t, uint16_t, _mesa_unorm_to_unorm(src, 16, 8)); 1096b8e80941Smrg } else { 1097b8e80941Smrg SWIZZLE_CONVERT(uint8_t, uint16_t, _mesa_unsigned_to_unsigned(src, 8)); 1098848b8605Smrg } 1099b8e80941Smrg break; 1100b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_SHORT: 1101b8e80941Smrg if (normalized) { 1102b8e80941Smrg SWIZZLE_CONVERT(uint8_t, int16_t, _mesa_snorm_to_unorm(src, 16, 8)); 1103b8e80941Smrg } else { 1104b8e80941Smrg SWIZZLE_CONVERT(uint8_t, int16_t, _mesa_signed_to_unsigned(src, 8)); 1105b8e80941Smrg } 1106b8e80941Smrg break; 1107b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_UINT: 1108b8e80941Smrg if (normalized) { 1109b8e80941Smrg SWIZZLE_CONVERT(uint8_t, uint32_t, _mesa_unorm_to_unorm(src, 32, 8)); 1110b8e80941Smrg } else { 1111b8e80941Smrg SWIZZLE_CONVERT(uint8_t, uint32_t, _mesa_unsigned_to_unsigned(src, 8)); 1112b8e80941Smrg } 1113b8e80941Smrg break; 1114b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_INT: 1115b8e80941Smrg if (normalized) { 1116b8e80941Smrg SWIZZLE_CONVERT(uint8_t, int32_t, _mesa_snorm_to_unorm(src, 32, 8)); 1117b8e80941Smrg } else { 1118b8e80941Smrg SWIZZLE_CONVERT(uint8_t, int32_t, _mesa_signed_to_unsigned(src, 8)); 1119b8e80941Smrg } 1120b8e80941Smrg break; 1121b8e80941Smrg default: 1122b8e80941Smrg assert(!"Invalid channel type combination"); 1123848b8605Smrg } 1124848b8605Smrg} 1125848b8605Smrg 1126b8e80941Smrg 1127848b8605Smrgstatic void 1128b8e80941Smrgconvert_byte(void *void_dst, int num_dst_channels, 1129b8e80941Smrg const void *void_src, GLenum src_type, int num_src_channels, 1130b8e80941Smrg const uint8_t swizzle[4], bool normalized, int count) 1131848b8605Smrg{ 1132b8e80941Smrg const int8_t one = normalized ? INT8_MAX : 1; 1133848b8605Smrg 1134b8e80941Smrg switch (src_type) { 1135b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_FLOAT: 1136b8e80941Smrg if (normalized) { 1137b8e80941Smrg SWIZZLE_CONVERT(uint8_t, float, _mesa_float_to_snorm(src, 8)); 1138b8e80941Smrg } else { 1139b8e80941Smrg SWIZZLE_CONVERT(uint8_t, float, _mesa_float_to_signed(src, 8)); 1140b8e80941Smrg } 1141b8e80941Smrg break; 1142b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_HALF: 1143b8e80941Smrg if (normalized) { 1144b8e80941Smrg SWIZZLE_CONVERT(uint8_t, uint16_t, _mesa_half_to_snorm(src, 8)); 1145b8e80941Smrg } else { 1146b8e80941Smrg SWIZZLE_CONVERT(uint8_t, uint16_t, _mesa_half_to_signed(src, 8)); 1147b8e80941Smrg } 1148b8e80941Smrg break; 1149b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_UBYTE: 1150b8e80941Smrg if (normalized) { 1151b8e80941Smrg SWIZZLE_CONVERT(int8_t, uint8_t, _mesa_unorm_to_snorm(src, 8, 8)); 1152b8e80941Smrg } else { 1153b8e80941Smrg SWIZZLE_CONVERT(int8_t, uint8_t, _mesa_unsigned_to_signed(src, 8)); 1154b8e80941Smrg } 1155b8e80941Smrg break; 1156b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_BYTE: 1157b8e80941Smrg SWIZZLE_CONVERT(int8_t, int8_t, src); 1158b8e80941Smrg break; 1159b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_USHORT: 1160b8e80941Smrg if (normalized) { 1161b8e80941Smrg SWIZZLE_CONVERT(int8_t, uint16_t, _mesa_unorm_to_snorm(src, 16, 8)); 1162b8e80941Smrg } else { 1163b8e80941Smrg SWIZZLE_CONVERT(int8_t, uint16_t, _mesa_unsigned_to_signed(src, 8)); 1164b8e80941Smrg } 1165b8e80941Smrg break; 1166b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_SHORT: 1167b8e80941Smrg if (normalized) { 1168b8e80941Smrg SWIZZLE_CONVERT(int8_t, int16_t, _mesa_snorm_to_snorm(src, 16, 8)); 1169b8e80941Smrg } else { 1170b8e80941Smrg SWIZZLE_CONVERT(int8_t, int16_t, _mesa_signed_to_signed(src, 8)); 1171848b8605Smrg } 1172b8e80941Smrg break; 1173b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_UINT: 1174b8e80941Smrg if (normalized) { 1175b8e80941Smrg SWIZZLE_CONVERT(int8_t, uint32_t, _mesa_unorm_to_snorm(src, 32, 8)); 1176b8e80941Smrg } else { 1177b8e80941Smrg SWIZZLE_CONVERT(int8_t, uint32_t, _mesa_unsigned_to_signed(src, 8)); 1178b8e80941Smrg } 1179b8e80941Smrg break; 1180b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_INT: 1181b8e80941Smrg if (normalized) { 1182b8e80941Smrg SWIZZLE_CONVERT(int8_t, int32_t, _mesa_snorm_to_snorm(src, 32, 8)); 1183b8e80941Smrg } else { 1184b8e80941Smrg SWIZZLE_CONVERT(int8_t, int32_t, _mesa_signed_to_signed(src, 8)); 1185b8e80941Smrg } 1186b8e80941Smrg break; 1187b8e80941Smrg default: 1188b8e80941Smrg assert(!"Invalid channel type combination"); 1189848b8605Smrg } 1190848b8605Smrg} 1191848b8605Smrg 1192b8e80941Smrg 1193848b8605Smrgstatic void 1194b8e80941Smrgconvert_ushort(void *void_dst, int num_dst_channels, 1195b8e80941Smrg const void *void_src, GLenum src_type, int num_src_channels, 1196b8e80941Smrg const uint8_t swizzle[4], bool normalized, int count) 1197848b8605Smrg{ 1198b8e80941Smrg const uint16_t one = normalized ? UINT16_MAX : 1; 1199b8e80941Smrg 1200b8e80941Smrg switch (src_type) { 1201b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_FLOAT: 1202b8e80941Smrg if (normalized) { 1203b8e80941Smrg SWIZZLE_CONVERT(uint16_t, float, _mesa_float_to_unorm(src, 16)); 1204b8e80941Smrg } else { 1205b8e80941Smrg SWIZZLE_CONVERT(uint16_t, float, _mesa_float_to_unsigned(src, 16)); 1206b8e80941Smrg } 1207b8e80941Smrg break; 1208b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_HALF: 1209b8e80941Smrg if (normalized) { 1210b8e80941Smrg SWIZZLE_CONVERT(uint16_t, uint16_t, _mesa_half_to_unorm(src, 16)); 1211b8e80941Smrg } else { 1212b8e80941Smrg SWIZZLE_CONVERT(uint16_t, uint16_t, _mesa_half_to_unsigned(src, 16)); 1213848b8605Smrg } 1214b8e80941Smrg break; 1215b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_UBYTE: 1216b8e80941Smrg if (normalized) { 1217b8e80941Smrg SWIZZLE_CONVERT(uint16_t, uint8_t, _mesa_unorm_to_unorm(src, 8, 16)); 1218b8e80941Smrg } else { 1219b8e80941Smrg SWIZZLE_CONVERT(uint16_t, uint8_t, src); 1220b8e80941Smrg } 1221b8e80941Smrg break; 1222b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_BYTE: 1223b8e80941Smrg if (normalized) { 1224b8e80941Smrg SWIZZLE_CONVERT(uint16_t, int8_t, _mesa_snorm_to_unorm(src, 8, 16)); 1225b8e80941Smrg } else { 1226b8e80941Smrg SWIZZLE_CONVERT(uint16_t, int8_t, _mesa_signed_to_unsigned(src, 16)); 1227b8e80941Smrg } 1228b8e80941Smrg break; 1229b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_USHORT: 1230b8e80941Smrg SWIZZLE_CONVERT(uint16_t, uint16_t, src); 1231b8e80941Smrg break; 1232b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_SHORT: 1233b8e80941Smrg if (normalized) { 1234b8e80941Smrg SWIZZLE_CONVERT(uint16_t, int16_t, _mesa_snorm_to_unorm(src, 16, 16)); 1235b8e80941Smrg } else { 1236b8e80941Smrg SWIZZLE_CONVERT(uint16_t, int16_t, _mesa_signed_to_unsigned(src, 16)); 1237b8e80941Smrg } 1238b8e80941Smrg break; 1239b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_UINT: 1240b8e80941Smrg if (normalized) { 1241b8e80941Smrg SWIZZLE_CONVERT(uint16_t, uint32_t, _mesa_unorm_to_unorm(src, 32, 16)); 1242b8e80941Smrg } else { 1243b8e80941Smrg SWIZZLE_CONVERT(uint16_t, uint32_t, _mesa_unsigned_to_unsigned(src, 16)); 1244b8e80941Smrg } 1245b8e80941Smrg break; 1246b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_INT: 1247b8e80941Smrg if (normalized) { 1248b8e80941Smrg SWIZZLE_CONVERT(uint16_t, int32_t, _mesa_snorm_to_unorm(src, 32, 16)); 1249b8e80941Smrg } else { 1250b8e80941Smrg SWIZZLE_CONVERT(uint16_t, int32_t, _mesa_signed_to_unsigned(src, 16)); 1251b8e80941Smrg } 1252b8e80941Smrg break; 1253b8e80941Smrg default: 1254b8e80941Smrg assert(!"Invalid channel type combination"); 1255848b8605Smrg } 1256848b8605Smrg} 1257848b8605Smrg 1258b8e80941Smrg 1259848b8605Smrgstatic void 1260b8e80941Smrgconvert_short(void *void_dst, int num_dst_channels, 1261b8e80941Smrg const void *void_src, GLenum src_type, int num_src_channels, 1262b8e80941Smrg const uint8_t swizzle[4], bool normalized, int count) 1263848b8605Smrg{ 1264b8e80941Smrg const int16_t one = normalized ? INT16_MAX : 1; 1265848b8605Smrg 1266b8e80941Smrg switch (src_type) { 1267b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_FLOAT: 1268b8e80941Smrg if (normalized) { 1269b8e80941Smrg SWIZZLE_CONVERT(uint16_t, float, _mesa_float_to_snorm(src, 16)); 1270b8e80941Smrg } else { 1271b8e80941Smrg SWIZZLE_CONVERT(uint16_t, float, _mesa_float_to_signed(src, 16)); 1272b8e80941Smrg } 1273b8e80941Smrg break; 1274b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_HALF: 1275b8e80941Smrg if (normalized) { 1276b8e80941Smrg SWIZZLE_CONVERT(uint16_t, uint16_t, _mesa_half_to_snorm(src, 16)); 1277b8e80941Smrg } else { 1278b8e80941Smrg SWIZZLE_CONVERT(uint16_t, uint16_t, _mesa_half_to_signed(src, 16)); 1279b8e80941Smrg } 1280b8e80941Smrg break; 1281b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_UBYTE: 1282b8e80941Smrg if (normalized) { 1283b8e80941Smrg SWIZZLE_CONVERT(int16_t, uint8_t, _mesa_unorm_to_snorm(src, 8, 16)); 1284b8e80941Smrg } else { 1285b8e80941Smrg SWIZZLE_CONVERT(int16_t, uint8_t, src); 1286b8e80941Smrg } 1287b8e80941Smrg break; 1288b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_BYTE: 1289b8e80941Smrg if (normalized) { 1290b8e80941Smrg SWIZZLE_CONVERT(int16_t, int8_t, _mesa_snorm_to_snorm(src, 8, 16)); 1291b8e80941Smrg } else { 1292b8e80941Smrg SWIZZLE_CONVERT(int16_t, int8_t, src); 1293b8e80941Smrg } 1294b8e80941Smrg break; 1295b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_USHORT: 1296b8e80941Smrg if (normalized) { 1297b8e80941Smrg SWIZZLE_CONVERT(int16_t, uint16_t, _mesa_unorm_to_snorm(src, 16, 16)); 1298b8e80941Smrg } else { 1299b8e80941Smrg SWIZZLE_CONVERT(int16_t, uint16_t, _mesa_unsigned_to_signed(src, 16)); 1300b8e80941Smrg } 1301b8e80941Smrg break; 1302b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_SHORT: 1303b8e80941Smrg SWIZZLE_CONVERT(int16_t, int16_t, src); 1304b8e80941Smrg break; 1305b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_UINT: 1306b8e80941Smrg if (normalized) { 1307b8e80941Smrg SWIZZLE_CONVERT(int16_t, uint32_t, _mesa_unorm_to_snorm(src, 32, 16)); 1308b8e80941Smrg } else { 1309b8e80941Smrg SWIZZLE_CONVERT(int16_t, uint32_t, _mesa_unsigned_to_signed(src, 16)); 1310848b8605Smrg } 1311b8e80941Smrg break; 1312b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_INT: 1313b8e80941Smrg if (normalized) { 1314b8e80941Smrg SWIZZLE_CONVERT(int16_t, int32_t, _mesa_snorm_to_snorm(src, 32, 16)); 1315b8e80941Smrg } else { 1316b8e80941Smrg SWIZZLE_CONVERT(int16_t, int32_t, _mesa_signed_to_signed(src, 16)); 1317b8e80941Smrg } 1318b8e80941Smrg break; 1319b8e80941Smrg default: 1320b8e80941Smrg assert(!"Invalid channel type combination"); 1321848b8605Smrg } 1322848b8605Smrg} 1323848b8605Smrg 1324848b8605Smrgstatic void 1325b8e80941Smrgconvert_uint(void *void_dst, int num_dst_channels, 1326b8e80941Smrg const void *void_src, GLenum src_type, int num_src_channels, 1327b8e80941Smrg const uint8_t swizzle[4], bool normalized, int count) 1328848b8605Smrg{ 1329b8e80941Smrg const uint32_t one = normalized ? UINT32_MAX : 1; 1330b8e80941Smrg 1331b8e80941Smrg switch (src_type) { 1332b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_FLOAT: 1333b8e80941Smrg if (normalized) { 1334b8e80941Smrg SWIZZLE_CONVERT(uint32_t, float, _mesa_float_to_unorm(src, 32)); 1335b8e80941Smrg } else { 1336b8e80941Smrg SWIZZLE_CONVERT(uint32_t, float, _mesa_float_to_unsigned(src, 32)); 1337b8e80941Smrg } 1338b8e80941Smrg break; 1339b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_HALF: 1340b8e80941Smrg if (normalized) { 1341b8e80941Smrg SWIZZLE_CONVERT(uint32_t, uint16_t, _mesa_half_to_unorm(src, 32)); 1342b8e80941Smrg } else { 1343b8e80941Smrg SWIZZLE_CONVERT(uint32_t, uint16_t, _mesa_half_to_unsigned(src, 32)); 1344b8e80941Smrg } 1345b8e80941Smrg break; 1346b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_UBYTE: 1347b8e80941Smrg if (normalized) { 1348b8e80941Smrg SWIZZLE_CONVERT(uint32_t, uint8_t, _mesa_unorm_to_unorm(src, 8, 32)); 1349b8e80941Smrg } else { 1350b8e80941Smrg SWIZZLE_CONVERT(uint32_t, uint8_t, src); 1351b8e80941Smrg } 1352b8e80941Smrg break; 1353b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_BYTE: 1354b8e80941Smrg if (normalized) { 1355b8e80941Smrg SWIZZLE_CONVERT(uint32_t, int8_t, _mesa_snorm_to_unorm(src, 8, 32)); 1356b8e80941Smrg } else { 1357b8e80941Smrg SWIZZLE_CONVERT(uint32_t, int8_t, _mesa_signed_to_unsigned(src, 32)); 1358b8e80941Smrg } 1359b8e80941Smrg break; 1360b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_USHORT: 1361b8e80941Smrg if (normalized) { 1362b8e80941Smrg SWIZZLE_CONVERT(uint32_t, uint16_t, _mesa_unorm_to_unorm(src, 16, 32)); 1363b8e80941Smrg } else { 1364b8e80941Smrg SWIZZLE_CONVERT(uint32_t, uint16_t, src); 1365848b8605Smrg } 1366b8e80941Smrg break; 1367b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_SHORT: 1368b8e80941Smrg if (normalized) { 1369b8e80941Smrg SWIZZLE_CONVERT(uint32_t, int16_t, _mesa_snorm_to_unorm(src, 16, 32)); 1370b8e80941Smrg } else { 1371b8e80941Smrg SWIZZLE_CONVERT(uint32_t, int16_t, _mesa_signed_to_unsigned(src, 32)); 1372b8e80941Smrg } 1373b8e80941Smrg break; 1374b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_UINT: 1375b8e80941Smrg SWIZZLE_CONVERT(uint32_t, uint32_t, src); 1376b8e80941Smrg break; 1377b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_INT: 1378b8e80941Smrg if (normalized) { 1379b8e80941Smrg SWIZZLE_CONVERT(uint32_t, int32_t, _mesa_snorm_to_unorm(src, 32, 32)); 1380b8e80941Smrg } else { 1381b8e80941Smrg SWIZZLE_CONVERT(uint32_t, int32_t, _mesa_signed_to_unsigned(src, 32)); 1382b8e80941Smrg } 1383b8e80941Smrg break; 1384b8e80941Smrg default: 1385b8e80941Smrg assert(!"Invalid channel type combination"); 1386848b8605Smrg } 1387848b8605Smrg} 1388848b8605Smrg 1389b8e80941Smrg 1390848b8605Smrgstatic void 1391b8e80941Smrgconvert_int(void *void_dst, int num_dst_channels, 1392b8e80941Smrg const void *void_src, GLenum src_type, int num_src_channels, 1393b8e80941Smrg const uint8_t swizzle[4], bool normalized, int count) 1394848b8605Smrg{ 1395b8e80941Smrg const int32_t one = normalized ? INT32_MAX : 1; 1396848b8605Smrg 1397b8e80941Smrg switch (src_type) { 1398b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_FLOAT: 1399b8e80941Smrg if (normalized) { 1400b8e80941Smrg SWIZZLE_CONVERT(uint32_t, float, _mesa_float_to_snorm(src, 32)); 1401b8e80941Smrg } else { 1402b8e80941Smrg SWIZZLE_CONVERT(uint32_t, float, _mesa_float_to_signed(src, 32)); 1403b8e80941Smrg } 1404b8e80941Smrg break; 1405b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_HALF: 1406b8e80941Smrg if (normalized) { 1407b8e80941Smrg SWIZZLE_CONVERT(uint32_t, uint16_t, _mesa_half_to_snorm(src, 32)); 1408b8e80941Smrg } else { 1409b8e80941Smrg SWIZZLE_CONVERT(uint32_t, uint16_t, _mesa_half_to_signed(src, 32)); 1410b8e80941Smrg } 1411b8e80941Smrg break; 1412b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_UBYTE: 1413b8e80941Smrg if (normalized) { 1414b8e80941Smrg SWIZZLE_CONVERT(int32_t, uint8_t, _mesa_unorm_to_snorm(src, 8, 32)); 1415b8e80941Smrg } else { 1416b8e80941Smrg SWIZZLE_CONVERT(int32_t, uint8_t, src); 1417b8e80941Smrg } 1418b8e80941Smrg break; 1419b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_BYTE: 1420b8e80941Smrg if (normalized) { 1421b8e80941Smrg SWIZZLE_CONVERT(int32_t, int8_t, _mesa_snorm_to_snorm(src, 8, 32)); 1422b8e80941Smrg } else { 1423b8e80941Smrg SWIZZLE_CONVERT(int32_t, int8_t, src); 1424848b8605Smrg } 1425b8e80941Smrg break; 1426b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_USHORT: 1427b8e80941Smrg if (normalized) { 1428b8e80941Smrg SWIZZLE_CONVERT(int32_t, uint16_t, _mesa_unorm_to_snorm(src, 16, 32)); 1429b8e80941Smrg } else { 1430b8e80941Smrg SWIZZLE_CONVERT(int32_t, uint16_t, src); 1431b8e80941Smrg } 1432b8e80941Smrg break; 1433b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_SHORT: 1434b8e80941Smrg if (normalized) { 1435b8e80941Smrg SWIZZLE_CONVERT(int32_t, int16_t, _mesa_snorm_to_snorm(src, 16, 32)); 1436b8e80941Smrg } else { 1437b8e80941Smrg SWIZZLE_CONVERT(int32_t, int16_t, src); 1438b8e80941Smrg } 1439b8e80941Smrg break; 1440b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_UINT: 1441b8e80941Smrg if (normalized) { 1442b8e80941Smrg SWIZZLE_CONVERT(int32_t, uint32_t, _mesa_unorm_to_snorm(src, 32, 32)); 1443b8e80941Smrg } else { 1444b8e80941Smrg SWIZZLE_CONVERT(int32_t, uint32_t, _mesa_unsigned_to_signed(src, 32)); 1445b8e80941Smrg } 1446b8e80941Smrg break; 1447b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_INT: 1448b8e80941Smrg SWIZZLE_CONVERT(int32_t, int32_t, src); 1449b8e80941Smrg break; 1450b8e80941Smrg default: 1451b8e80941Smrg assert(!"Invalid channel type combination"); 1452848b8605Smrg } 1453848b8605Smrg} 1454848b8605Smrg 1455b8e80941Smrg 1456b8e80941Smrg/** 1457b8e80941Smrg * Convert between array-based color formats. 1458b8e80941Smrg * 1459b8e80941Smrg * Most format conversion operations required by GL can be performed by 1460b8e80941Smrg * converting one channel at a time, shuffling the channels around, and 1461b8e80941Smrg * optionally filling missing channels with zeros and ones. This function 1462b8e80941Smrg * does just that in a general, yet efficient, way. 1463b8e80941Smrg * 1464b8e80941Smrg * The swizzle parameter is an array of 4 numbers (see 1465b8e80941Smrg * _mesa_get_format_swizzle) that describes where each channel in the 1466b8e80941Smrg * destination should come from in the source. If swizzle[i] < 4 then it 1467b8e80941Smrg * means that dst[i] = CONVERT(src[swizzle[i]]). If swizzle[i] is 1468b8e80941Smrg * MESA_FORMAT_SWIZZLE_ZERO or MESA_FORMAT_SWIZZLE_ONE, the corresponding 1469b8e80941Smrg * dst[i] will be filled with the appropreate representation of zero or one 1470b8e80941Smrg * respectively. 1471b8e80941Smrg * 1472b8e80941Smrg * Under most circumstances, the source and destination images must be 1473b8e80941Smrg * different as no care is taken not to clobber one with the other. 1474b8e80941Smrg * However, if they have the same number of bits per pixel, it is safe to 1475b8e80941Smrg * do an in-place conversion. 1476b8e80941Smrg * 1477b8e80941Smrg * \param[out] dst pointer to where the converted data should 1478b8e80941Smrg * be stored 1479b8e80941Smrg * 1480b8e80941Smrg * \param[in] dst_type the destination GL type of the converted 1481b8e80941Smrg * data (GL_BYTE, etc.) 1482b8e80941Smrg * 1483b8e80941Smrg * \param[in] num_dst_channels the number of channels in the converted 1484b8e80941Smrg * data 1485b8e80941Smrg * 1486b8e80941Smrg * \param[in] src pointer to the source data 1487b8e80941Smrg * 1488b8e80941Smrg * \param[in] src_type the GL type of the source data (GL_BYTE, 1489b8e80941Smrg * etc.) 1490b8e80941Smrg * 1491b8e80941Smrg * \param[in] num_src_channels the number of channels in the source data 1492b8e80941Smrg * (the number of channels total, not just 1493b8e80941Smrg * the number used) 1494b8e80941Smrg * 1495b8e80941Smrg * \param[in] swizzle describes how to get the destination data 1496b8e80941Smrg * from the source data. 1497b8e80941Smrg * 1498b8e80941Smrg * \param[in] normalized for integer types, this indicates whether 1499b8e80941Smrg * the data should be considered as integers 1500b8e80941Smrg * or as normalized integers; 1501b8e80941Smrg * 1502b8e80941Smrg * \param[in] count the number of pixels to convert 1503b8e80941Smrg */ 1504848b8605Smrgvoid 1505b8e80941Smrg_mesa_swizzle_and_convert(void *void_dst, enum mesa_array_format_datatype dst_type, int num_dst_channels, 1506b8e80941Smrg const void *void_src, enum mesa_array_format_datatype src_type, int num_src_channels, 1507848b8605Smrg const uint8_t swizzle[4], bool normalized, int count) 1508848b8605Smrg{ 1509848b8605Smrg if (swizzle_convert_try_memcpy(void_dst, dst_type, num_dst_channels, 1510848b8605Smrg void_src, src_type, num_src_channels, 1511848b8605Smrg swizzle, normalized, count)) 1512848b8605Smrg return; 1513848b8605Smrg 1514848b8605Smrg switch (dst_type) { 1515b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_FLOAT: 1516b8e80941Smrg convert_float(void_dst, num_dst_channels, void_src, src_type, 1517b8e80941Smrg num_src_channels, swizzle, normalized, count); 1518b8e80941Smrg break; 1519b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_HALF: 1520b8e80941Smrg convert_half_float(void_dst, num_dst_channels, void_src, src_type, 1521b8e80941Smrg num_src_channels, swizzle, normalized, count); 1522b8e80941Smrg break; 1523b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_UBYTE: 1524b8e80941Smrg convert_ubyte(void_dst, num_dst_channels, void_src, src_type, 1525b8e80941Smrg num_src_channels, swizzle, normalized, count); 1526b8e80941Smrg break; 1527b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_BYTE: 1528b8e80941Smrg convert_byte(void_dst, num_dst_channels, void_src, src_type, 1529b8e80941Smrg num_src_channels, swizzle, normalized, count); 1530b8e80941Smrg break; 1531b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_USHORT: 1532b8e80941Smrg convert_ushort(void_dst, num_dst_channels, void_src, src_type, 1533b8e80941Smrg num_src_channels, swizzle, normalized, count); 1534b8e80941Smrg break; 1535b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_SHORT: 1536b8e80941Smrg convert_short(void_dst, num_dst_channels, void_src, src_type, 1537b8e80941Smrg num_src_channels, swizzle, normalized, count); 1538b8e80941Smrg break; 1539b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_UINT: 1540b8e80941Smrg convert_uint(void_dst, num_dst_channels, void_src, src_type, 1541b8e80941Smrg num_src_channels, swizzle, normalized, count); 1542b8e80941Smrg break; 1543b8e80941Smrg case MESA_ARRAY_FORMAT_TYPE_INT: 1544b8e80941Smrg convert_int(void_dst, num_dst_channels, void_src, src_type, 1545b8e80941Smrg num_src_channels, swizzle, normalized, count); 1546848b8605Smrg break; 1547848b8605Smrg default: 1548848b8605Smrg assert(!"Invalid channel type"); 1549848b8605Smrg } 1550848b8605Smrg} 1551