1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Mesa 3-D graphics library 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Copyright (C) 2014 Intel Corporation All Rights Reserved. 5bf215546Sopenharmony_ci * 6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 8bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 9bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 11bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 12bf215546Sopenharmony_ci * 13bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included 14bf215546Sopenharmony_ci * in all copies or substantial portions of the Software. 15bf215546Sopenharmony_ci * 16bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20bf215546Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21bf215546Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22bf215546Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 23bf215546Sopenharmony_ci */ 24bf215546Sopenharmony_ci 25bf215546Sopenharmony_ci#include <stdlib.h> 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci#include "errors.h" 28bf215546Sopenharmony_ci#include "format_utils.h" 29bf215546Sopenharmony_ci#include "glformats.h" 30bf215546Sopenharmony_ci#include "format_pack.h" 31bf215546Sopenharmony_ci#include "format_unpack.h" 32bf215546Sopenharmony_ci 33bf215546Sopenharmony_ciconst mesa_array_format RGBA32_FLOAT = 34bf215546Sopenharmony_ci MESA_ARRAY_FORMAT(MESA_ARRAY_FORMAT_BASE_FORMAT_RGBA_VARIANTS, 35bf215546Sopenharmony_ci 4, 1, 1, 1, 4, 0, 1, 2, 3); 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_ciconst mesa_array_format RGBA8_UBYTE = 38bf215546Sopenharmony_ci MESA_ARRAY_FORMAT(MESA_ARRAY_FORMAT_BASE_FORMAT_RGBA_VARIANTS, 39bf215546Sopenharmony_ci 1, 0, 0, 1, 4, 0, 1, 2, 3); 40bf215546Sopenharmony_ci 41bf215546Sopenharmony_ciconst mesa_array_format BGRA8_UBYTE = 42bf215546Sopenharmony_ci MESA_ARRAY_FORMAT(MESA_ARRAY_FORMAT_BASE_FORMAT_RGBA_VARIANTS, 43bf215546Sopenharmony_ci 1, 0, 0, 1, 4, 2, 1, 0, 3); 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_ciconst mesa_array_format RGBA32_UINT = 46bf215546Sopenharmony_ci MESA_ARRAY_FORMAT(MESA_ARRAY_FORMAT_BASE_FORMAT_RGBA_VARIANTS, 47bf215546Sopenharmony_ci 4, 0, 0, 0, 4, 0, 1, 2, 3); 48bf215546Sopenharmony_ci 49bf215546Sopenharmony_ciconst mesa_array_format RGBA32_INT = 50bf215546Sopenharmony_ci MESA_ARRAY_FORMAT(MESA_ARRAY_FORMAT_BASE_FORMAT_RGBA_VARIANTS, 51bf215546Sopenharmony_ci 4, 1, 0, 0, 4, 0, 1, 2, 3); 52bf215546Sopenharmony_ci 53bf215546Sopenharmony_cistatic void 54bf215546Sopenharmony_ciinvert_swizzle(uint8_t dst[4], const uint8_t src[4]) 55bf215546Sopenharmony_ci{ 56bf215546Sopenharmony_ci int i, j; 57bf215546Sopenharmony_ci 58bf215546Sopenharmony_ci dst[0] = MESA_FORMAT_SWIZZLE_NONE; 59bf215546Sopenharmony_ci dst[1] = MESA_FORMAT_SWIZZLE_NONE; 60bf215546Sopenharmony_ci dst[2] = MESA_FORMAT_SWIZZLE_NONE; 61bf215546Sopenharmony_ci dst[3] = MESA_FORMAT_SWIZZLE_NONE; 62bf215546Sopenharmony_ci 63bf215546Sopenharmony_ci for (i = 0; i < 4; ++i) 64bf215546Sopenharmony_ci for (j = 0; j < 4; ++j) 65bf215546Sopenharmony_ci if (src[j] == i && dst[i] == MESA_FORMAT_SWIZZLE_NONE) 66bf215546Sopenharmony_ci dst[i] = j; 67bf215546Sopenharmony_ci} 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_ci/* Takes a src to RGBA swizzle and applies a rebase swizzle to it. This 70bf215546Sopenharmony_ci * is used when we need to rebase a format to match a different 71bf215546Sopenharmony_ci * base internal format. 72bf215546Sopenharmony_ci * 73bf215546Sopenharmony_ci * The rebase swizzle can be NULL, which means that no rebase is necessary, 74bf215546Sopenharmony_ci * in which case the src to RGBA swizzle is copied to the output without 75bf215546Sopenharmony_ci * changes. 76bf215546Sopenharmony_ci * 77bf215546Sopenharmony_ci * The resulting rebased swizzle and well as the input swizzles are 78bf215546Sopenharmony_ci * all 4-element swizzles, but the rebase swizzle can be NULL if no rebase 79bf215546Sopenharmony_ci * is necessary. 80bf215546Sopenharmony_ci */ 81bf215546Sopenharmony_cistatic void 82bf215546Sopenharmony_cicompute_rebased_rgba_component_mapping(uint8_t *src2rgba, 83bf215546Sopenharmony_ci uint8_t *rebase_swizzle, 84bf215546Sopenharmony_ci uint8_t *rebased_src2rgba) 85bf215546Sopenharmony_ci{ 86bf215546Sopenharmony_ci int i; 87bf215546Sopenharmony_ci 88bf215546Sopenharmony_ci if (rebase_swizzle) { 89bf215546Sopenharmony_ci for (i = 0; i < 4; i++) { 90bf215546Sopenharmony_ci if (rebase_swizzle[i] > MESA_FORMAT_SWIZZLE_W) 91bf215546Sopenharmony_ci rebased_src2rgba[i] = rebase_swizzle[i]; 92bf215546Sopenharmony_ci else 93bf215546Sopenharmony_ci rebased_src2rgba[i] = src2rgba[rebase_swizzle[i]]; 94bf215546Sopenharmony_ci } 95bf215546Sopenharmony_ci } else { 96bf215546Sopenharmony_ci /* No rebase needed, so src2rgba is all that we need */ 97bf215546Sopenharmony_ci memcpy(rebased_src2rgba, src2rgba, 4 * sizeof(uint8_t)); 98bf215546Sopenharmony_ci } 99bf215546Sopenharmony_ci} 100bf215546Sopenharmony_ci 101bf215546Sopenharmony_ci/* Computes the final swizzle transform to apply from src to dst in a 102bf215546Sopenharmony_ci * conversion that might involve a rebase swizzle. 103bf215546Sopenharmony_ci * 104bf215546Sopenharmony_ci * This is used to compute the swizzle transform to apply in conversions 105bf215546Sopenharmony_ci * between array formats where we have a src2rgba swizzle, a rgba2dst swizzle 106bf215546Sopenharmony_ci * and possibly, a rebase swizzle. 107bf215546Sopenharmony_ci * 108bf215546Sopenharmony_ci * The final swizzle transform to apply (src2dst) when a rebase swizzle is 109bf215546Sopenharmony_ci * involved is: src -> rgba -> base -> rgba -> dst 110bf215546Sopenharmony_ci */ 111bf215546Sopenharmony_cistatic void 112bf215546Sopenharmony_cicompute_src2dst_component_mapping(uint8_t *src2rgba, uint8_t *rgba2dst, 113bf215546Sopenharmony_ci uint8_t *rebase_swizzle, uint8_t *src2dst) 114bf215546Sopenharmony_ci{ 115bf215546Sopenharmony_ci int i; 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_ci if (!rebase_swizzle) { 118bf215546Sopenharmony_ci for (i = 0; i < 4; i++) { 119bf215546Sopenharmony_ci if (rgba2dst[i] > MESA_FORMAT_SWIZZLE_W) { 120bf215546Sopenharmony_ci src2dst[i] = rgba2dst[i]; 121bf215546Sopenharmony_ci } else { 122bf215546Sopenharmony_ci src2dst[i] = src2rgba[rgba2dst[i]]; 123bf215546Sopenharmony_ci } 124bf215546Sopenharmony_ci } 125bf215546Sopenharmony_ci } else { 126bf215546Sopenharmony_ci for (i = 0; i < 4; i++) { 127bf215546Sopenharmony_ci if (rgba2dst[i] > MESA_FORMAT_SWIZZLE_W) { 128bf215546Sopenharmony_ci src2dst[i] = rgba2dst[i]; 129bf215546Sopenharmony_ci } else if (rebase_swizzle[rgba2dst[i]] > MESA_FORMAT_SWIZZLE_W) { 130bf215546Sopenharmony_ci src2dst[i] = rebase_swizzle[rgba2dst[i]]; 131bf215546Sopenharmony_ci } else { 132bf215546Sopenharmony_ci src2dst[i] = src2rgba[rebase_swizzle[rgba2dst[i]]]; 133bf215546Sopenharmony_ci } 134bf215546Sopenharmony_ci } 135bf215546Sopenharmony_ci } 136bf215546Sopenharmony_ci} 137bf215546Sopenharmony_ci 138bf215546Sopenharmony_ci/** 139bf215546Sopenharmony_ci * This function is used by clients of _mesa_format_convert to obtain 140bf215546Sopenharmony_ci * the rebase swizzle to use in a format conversion based on the base 141bf215546Sopenharmony_ci * format involved. 142bf215546Sopenharmony_ci * 143bf215546Sopenharmony_ci * \param baseFormat the base internal format involved in the conversion. 144bf215546Sopenharmony_ci * \param map the rebase swizzle to consider 145bf215546Sopenharmony_ci * 146bf215546Sopenharmony_ci * This function computes 'map' as rgba -> baseformat -> rgba and returns true 147bf215546Sopenharmony_ci * if the resulting swizzle transform is not the identity transform (thus, a 148bf215546Sopenharmony_ci * rebase is needed). If the function returns false then a rebase swizzle 149bf215546Sopenharmony_ci * is not necessary and the value of 'map' is undefined. In this situation 150bf215546Sopenharmony_ci * clients of _mesa_format_convert should pass NULL in the 'rebase_swizzle' 151bf215546Sopenharmony_ci * parameter. 152bf215546Sopenharmony_ci */ 153bf215546Sopenharmony_cibool 154bf215546Sopenharmony_ci_mesa_compute_rgba2base2rgba_component_mapping(GLenum baseFormat, uint8_t *map) 155bf215546Sopenharmony_ci{ 156bf215546Sopenharmony_ci uint8_t rgba2base[6], base2rgba[6]; 157bf215546Sopenharmony_ci int i; 158bf215546Sopenharmony_ci 159bf215546Sopenharmony_ci switch (baseFormat) { 160bf215546Sopenharmony_ci case GL_ALPHA: 161bf215546Sopenharmony_ci case GL_RED: 162bf215546Sopenharmony_ci case GL_GREEN: 163bf215546Sopenharmony_ci case GL_BLUE: 164bf215546Sopenharmony_ci case GL_RG: 165bf215546Sopenharmony_ci case GL_RGB: 166bf215546Sopenharmony_ci case GL_BGR: 167bf215546Sopenharmony_ci case GL_RGBA: 168bf215546Sopenharmony_ci case GL_BGRA: 169bf215546Sopenharmony_ci case GL_ABGR_EXT: 170bf215546Sopenharmony_ci case GL_LUMINANCE: 171bf215546Sopenharmony_ci case GL_INTENSITY: 172bf215546Sopenharmony_ci case GL_LUMINANCE_ALPHA: 173bf215546Sopenharmony_ci { 174bf215546Sopenharmony_ci bool needRebase = false; 175bf215546Sopenharmony_ci _mesa_compute_component_mapping(GL_RGBA, baseFormat, rgba2base); 176bf215546Sopenharmony_ci _mesa_compute_component_mapping(baseFormat, GL_RGBA, base2rgba); 177bf215546Sopenharmony_ci for (i = 0; i < 4; i++) { 178bf215546Sopenharmony_ci if (base2rgba[i] > MESA_FORMAT_SWIZZLE_W) { 179bf215546Sopenharmony_ci map[i] = base2rgba[i]; 180bf215546Sopenharmony_ci } else { 181bf215546Sopenharmony_ci map[i] = rgba2base[base2rgba[i]]; 182bf215546Sopenharmony_ci } 183bf215546Sopenharmony_ci if (map[i] != i) 184bf215546Sopenharmony_ci needRebase = true; 185bf215546Sopenharmony_ci } 186bf215546Sopenharmony_ci return needRebase; 187bf215546Sopenharmony_ci } 188bf215546Sopenharmony_ci default: 189bf215546Sopenharmony_ci unreachable("Unexpected base format"); 190bf215546Sopenharmony_ci } 191bf215546Sopenharmony_ci} 192bf215546Sopenharmony_ci 193bf215546Sopenharmony_ci 194bf215546Sopenharmony_ci/** 195bf215546Sopenharmony_ci * Special case conversion function to swap r/b channels from the source 196bf215546Sopenharmony_ci * image to the dest image. 197bf215546Sopenharmony_ci */ 198bf215546Sopenharmony_cistatic void 199bf215546Sopenharmony_ciconvert_ubyte_rgba_to_bgra(size_t width, size_t height, 200bf215546Sopenharmony_ci const uint8_t *src, size_t src_stride, 201bf215546Sopenharmony_ci uint8_t *dst, size_t dst_stride) 202bf215546Sopenharmony_ci{ 203bf215546Sopenharmony_ci int row; 204bf215546Sopenharmony_ci 205bf215546Sopenharmony_ci if (sizeof(void *) == 8 && 206bf215546Sopenharmony_ci src_stride % 8 == 0 && 207bf215546Sopenharmony_ci dst_stride % 8 == 0 && 208bf215546Sopenharmony_ci (GLsizeiptr) src % 8 == 0 && 209bf215546Sopenharmony_ci (GLsizeiptr) dst % 8 == 0) { 210bf215546Sopenharmony_ci /* use 64-bit word to swizzle two 32-bit pixels. We need 8-byte 211bf215546Sopenharmony_ci * alignment for src/dst addresses and strides. 212bf215546Sopenharmony_ci */ 213bf215546Sopenharmony_ci for (row = 0; row < height; row++) { 214bf215546Sopenharmony_ci const GLuint64 *s = (const GLuint64 *) src; 215bf215546Sopenharmony_ci GLuint64 *d = (GLuint64 *) dst; 216bf215546Sopenharmony_ci int i; 217bf215546Sopenharmony_ci for (i = 0; i < width/2; i++) { 218bf215546Sopenharmony_ci d[i] = ( (s[i] & 0xff00ff00ff00ff00) | 219bf215546Sopenharmony_ci ((s[i] & 0xff000000ff) << 16) | 220bf215546Sopenharmony_ci ((s[i] & 0xff000000ff0000) >> 16)); 221bf215546Sopenharmony_ci } 222bf215546Sopenharmony_ci if (width & 1) { 223bf215546Sopenharmony_ci /* handle the case of odd widths */ 224bf215546Sopenharmony_ci const GLuint s = ((const GLuint *) src)[width - 1]; 225bf215546Sopenharmony_ci GLuint *d = (GLuint *) dst + width - 1; 226bf215546Sopenharmony_ci *d = ( (s & 0xff00ff00) | 227bf215546Sopenharmony_ci ((s & 0xff) << 16) | 228bf215546Sopenharmony_ci ((s & 0xff0000) >> 16)); 229bf215546Sopenharmony_ci } 230bf215546Sopenharmony_ci src += src_stride; 231bf215546Sopenharmony_ci dst += dst_stride; 232bf215546Sopenharmony_ci } 233bf215546Sopenharmony_ci } else { 234bf215546Sopenharmony_ci for (row = 0; row < height; row++) { 235bf215546Sopenharmony_ci const GLuint *s = (const GLuint *) src; 236bf215546Sopenharmony_ci GLuint *d = (GLuint *) dst; 237bf215546Sopenharmony_ci int i; 238bf215546Sopenharmony_ci for (i = 0; i < width; i++) { 239bf215546Sopenharmony_ci d[i] = ( (s[i] & 0xff00ff00) | 240bf215546Sopenharmony_ci ((s[i] & 0xff) << 16) | 241bf215546Sopenharmony_ci ((s[i] & 0xff0000) >> 16)); 242bf215546Sopenharmony_ci } 243bf215546Sopenharmony_ci src += src_stride; 244bf215546Sopenharmony_ci dst += dst_stride; 245bf215546Sopenharmony_ci } 246bf215546Sopenharmony_ci } 247bf215546Sopenharmony_ci} 248bf215546Sopenharmony_ci 249bf215546Sopenharmony_ci 250bf215546Sopenharmony_ci/** 251bf215546Sopenharmony_ci * This can be used to convert between most color formats. 252bf215546Sopenharmony_ci * 253bf215546Sopenharmony_ci * Limitations: 254bf215546Sopenharmony_ci * - This function doesn't handle GL_COLOR_INDEX or YCBCR formats. 255bf215546Sopenharmony_ci * - This function doesn't handle byte-swapping or transferOps, these should 256bf215546Sopenharmony_ci * be handled by the caller. 257bf215546Sopenharmony_ci * 258bf215546Sopenharmony_ci * \param void_dst The address where converted color data will be stored. 259bf215546Sopenharmony_ci * The caller must ensure that the buffer is large enough 260bf215546Sopenharmony_ci * to hold the converted pixel data. 261bf215546Sopenharmony_ci * \param dst_format The destination color format. It can be a mesa_format 262bf215546Sopenharmony_ci * or a mesa_array_format represented as an uint32_t. 263bf215546Sopenharmony_ci * \param dst_stride The stride of the destination format in bytes. 264bf215546Sopenharmony_ci * \param void_src The address of the source color data to convert. 265bf215546Sopenharmony_ci * \param src_format The source color format. It can be a mesa_format 266bf215546Sopenharmony_ci * or a mesa_array_format represented as an uint32_t. 267bf215546Sopenharmony_ci * \param src_stride The stride of the source format in bytes. 268bf215546Sopenharmony_ci * \param width The width, in pixels, of the source image to convert. 269bf215546Sopenharmony_ci * \param height The height, in pixels, of the source image to convert. 270bf215546Sopenharmony_ci * \param rebase_swizzle A swizzle transform to apply during the conversion, 271bf215546Sopenharmony_ci * typically used to match a different internal base 272bf215546Sopenharmony_ci * format involved. NULL if no rebase transform is needed 273bf215546Sopenharmony_ci * (i.e. the internal base format and the base format of 274bf215546Sopenharmony_ci * the dst or the src -depending on whether we are doing 275bf215546Sopenharmony_ci * an upload or a download respectively- are the same). 276bf215546Sopenharmony_ci */ 277bf215546Sopenharmony_civoid 278bf215546Sopenharmony_ci_mesa_format_convert(void *void_dst, uint32_t dst_format, size_t dst_stride, 279bf215546Sopenharmony_ci void *void_src, uint32_t src_format, size_t src_stride, 280bf215546Sopenharmony_ci size_t width, size_t height, uint8_t *rebase_swizzle) 281bf215546Sopenharmony_ci{ 282bf215546Sopenharmony_ci uint8_t *dst = (uint8_t *)void_dst; 283bf215546Sopenharmony_ci uint8_t *src = (uint8_t *)void_src; 284bf215546Sopenharmony_ci mesa_array_format src_array_format, dst_array_format; 285bf215546Sopenharmony_ci bool src_format_is_mesa_array_format, dst_format_is_mesa_array_format; 286bf215546Sopenharmony_ci uint8_t src2dst[4], src2rgba[4], rgba2dst[4], dst2rgba[4]; 287bf215546Sopenharmony_ci uint8_t rebased_src2rgba[4]; 288bf215546Sopenharmony_ci enum mesa_array_format_datatype src_type = 0, dst_type = 0, common_type; 289bf215546Sopenharmony_ci bool normalized, dst_integer, src_integer, is_signed; 290bf215546Sopenharmony_ci int src_num_channels = 0, dst_num_channels = 0; 291bf215546Sopenharmony_ci uint8_t (*tmp_ubyte)[4]; 292bf215546Sopenharmony_ci float (*tmp_float)[4]; 293bf215546Sopenharmony_ci uint32_t (*tmp_uint)[4]; 294bf215546Sopenharmony_ci int bits; 295bf215546Sopenharmony_ci size_t row; 296bf215546Sopenharmony_ci 297bf215546Sopenharmony_ci if (_mesa_format_is_mesa_array_format(src_format)) { 298bf215546Sopenharmony_ci src_format_is_mesa_array_format = true; 299bf215546Sopenharmony_ci src_array_format = src_format; 300bf215546Sopenharmony_ci } else { 301bf215546Sopenharmony_ci assert(_mesa_is_format_color_format(src_format)); 302bf215546Sopenharmony_ci src_format_is_mesa_array_format = false; 303bf215546Sopenharmony_ci src_array_format = _mesa_format_to_array_format(src_format); 304bf215546Sopenharmony_ci } 305bf215546Sopenharmony_ci 306bf215546Sopenharmony_ci if (_mesa_format_is_mesa_array_format(dst_format)) { 307bf215546Sopenharmony_ci dst_format_is_mesa_array_format = true; 308bf215546Sopenharmony_ci dst_array_format = dst_format; 309bf215546Sopenharmony_ci } else { 310bf215546Sopenharmony_ci assert(_mesa_is_format_color_format(dst_format)); 311bf215546Sopenharmony_ci dst_format_is_mesa_array_format = false; 312bf215546Sopenharmony_ci dst_array_format = _mesa_format_to_array_format(dst_format); 313bf215546Sopenharmony_ci } 314bf215546Sopenharmony_ci 315bf215546Sopenharmony_ci /* First we see if we can implement the conversion with a direct pack 316bf215546Sopenharmony_ci * or unpack. 317bf215546Sopenharmony_ci * 318bf215546Sopenharmony_ci * In this case we want to be careful when we need to apply a swizzle to 319bf215546Sopenharmony_ci * match an internal base format, since in these cases a simple pack/unpack 320bf215546Sopenharmony_ci * to the dst format from the src format may not match the requirements 321bf215546Sopenharmony_ci * of the internal base format. For now we decide to be safe and 322bf215546Sopenharmony_ci * avoid this path in these scenarios but in the future we may want to 323bf215546Sopenharmony_ci * enable it for specific combinations that are known to work. 324bf215546Sopenharmony_ci */ 325bf215546Sopenharmony_ci if (!rebase_swizzle) { 326bf215546Sopenharmony_ci /* Do a direct memcpy where possible */ 327bf215546Sopenharmony_ci if ((dst_format_is_mesa_array_format && 328bf215546Sopenharmony_ci src_format_is_mesa_array_format && 329bf215546Sopenharmony_ci src_array_format == dst_array_format) || 330bf215546Sopenharmony_ci src_format == dst_format) { 331bf215546Sopenharmony_ci int format_size = _mesa_get_format_bytes(src_format); 332bf215546Sopenharmony_ci for (row = 0; row < height; row++) { 333bf215546Sopenharmony_ci memcpy(dst, src, width * format_size); 334bf215546Sopenharmony_ci src += src_stride; 335bf215546Sopenharmony_ci dst += dst_stride; 336bf215546Sopenharmony_ci } 337bf215546Sopenharmony_ci return; 338bf215546Sopenharmony_ci } 339bf215546Sopenharmony_ci 340bf215546Sopenharmony_ci /* Handle the cases where we can directly unpack */ 341bf215546Sopenharmony_ci if (!src_format_is_mesa_array_format) { 342bf215546Sopenharmony_ci if (dst_array_format == RGBA32_FLOAT) { 343bf215546Sopenharmony_ci for (row = 0; row < height; ++row) { 344bf215546Sopenharmony_ci _mesa_unpack_rgba_row(src_format, width, 345bf215546Sopenharmony_ci src, (float (*)[4])dst); 346bf215546Sopenharmony_ci src += src_stride; 347bf215546Sopenharmony_ci dst += dst_stride; 348bf215546Sopenharmony_ci } 349bf215546Sopenharmony_ci return; 350bf215546Sopenharmony_ci } else if (dst_array_format == RGBA8_UBYTE) { 351bf215546Sopenharmony_ci assert(!_mesa_is_format_integer_color(src_format)); 352bf215546Sopenharmony_ci for (row = 0; row < height; ++row) { 353bf215546Sopenharmony_ci _mesa_unpack_ubyte_rgba_row(src_format, width, 354bf215546Sopenharmony_ci src, (uint8_t (*)[4])dst); 355bf215546Sopenharmony_ci src += src_stride; 356bf215546Sopenharmony_ci dst += dst_stride; 357bf215546Sopenharmony_ci } 358bf215546Sopenharmony_ci return; 359bf215546Sopenharmony_ci } else if (dst_array_format == BGRA8_UBYTE && 360bf215546Sopenharmony_ci src_format == MESA_FORMAT_R8G8B8A8_UNORM) { 361bf215546Sopenharmony_ci convert_ubyte_rgba_to_bgra(width, height, src, src_stride, 362bf215546Sopenharmony_ci dst, dst_stride); 363bf215546Sopenharmony_ci return; 364bf215546Sopenharmony_ci } else if (dst_array_format == RGBA32_UINT && 365bf215546Sopenharmony_ci _mesa_is_format_unsigned(src_format)) { 366bf215546Sopenharmony_ci assert(_mesa_is_format_integer_color(src_format)); 367bf215546Sopenharmony_ci for (row = 0; row < height; ++row) { 368bf215546Sopenharmony_ci _mesa_unpack_uint_rgba_row(src_format, width, 369bf215546Sopenharmony_ci src, (uint32_t (*)[4])dst); 370bf215546Sopenharmony_ci src += src_stride; 371bf215546Sopenharmony_ci dst += dst_stride; 372bf215546Sopenharmony_ci } 373bf215546Sopenharmony_ci return; 374bf215546Sopenharmony_ci } 375bf215546Sopenharmony_ci } 376bf215546Sopenharmony_ci 377bf215546Sopenharmony_ci /* Handle the cases where we can directly pack */ 378bf215546Sopenharmony_ci if (!dst_format_is_mesa_array_format) { 379bf215546Sopenharmony_ci if (src_array_format == RGBA32_FLOAT) { 380bf215546Sopenharmony_ci for (row = 0; row < height; ++row) { 381bf215546Sopenharmony_ci _mesa_pack_float_rgba_row(dst_format, width, 382bf215546Sopenharmony_ci (const float (*)[4])src, dst); 383bf215546Sopenharmony_ci src += src_stride; 384bf215546Sopenharmony_ci dst += dst_stride; 385bf215546Sopenharmony_ci } 386bf215546Sopenharmony_ci return; 387bf215546Sopenharmony_ci } else if (src_array_format == RGBA8_UBYTE) { 388bf215546Sopenharmony_ci assert(!_mesa_is_format_integer_color(dst_format)); 389bf215546Sopenharmony_ci 390bf215546Sopenharmony_ci if (dst_format == MESA_FORMAT_B8G8R8A8_UNORM) { 391bf215546Sopenharmony_ci convert_ubyte_rgba_to_bgra(width, height, src, src_stride, 392bf215546Sopenharmony_ci dst, dst_stride); 393bf215546Sopenharmony_ci } 394bf215546Sopenharmony_ci else { 395bf215546Sopenharmony_ci for (row = 0; row < height; ++row) { 396bf215546Sopenharmony_ci _mesa_pack_ubyte_rgba_row(dst_format, width, src, dst); 397bf215546Sopenharmony_ci src += src_stride; 398bf215546Sopenharmony_ci dst += dst_stride; 399bf215546Sopenharmony_ci } 400bf215546Sopenharmony_ci } 401bf215546Sopenharmony_ci return; 402bf215546Sopenharmony_ci } else if (src_array_format == RGBA32_UINT && 403bf215546Sopenharmony_ci _mesa_is_format_unsigned(dst_format)) { 404bf215546Sopenharmony_ci assert(_mesa_is_format_integer_color(dst_format)); 405bf215546Sopenharmony_ci for (row = 0; row < height; ++row) { 406bf215546Sopenharmony_ci _mesa_pack_uint_rgba_row(dst_format, width, 407bf215546Sopenharmony_ci (const uint32_t (*)[4])src, dst); 408bf215546Sopenharmony_ci src += src_stride; 409bf215546Sopenharmony_ci dst += dst_stride; 410bf215546Sopenharmony_ci } 411bf215546Sopenharmony_ci return; 412bf215546Sopenharmony_ci } 413bf215546Sopenharmony_ci } 414bf215546Sopenharmony_ci } 415bf215546Sopenharmony_ci 416bf215546Sopenharmony_ci /* Handle conversions between array formats */ 417bf215546Sopenharmony_ci normalized = false; 418bf215546Sopenharmony_ci if (src_array_format) { 419bf215546Sopenharmony_ci src_type = _mesa_array_format_get_datatype(src_array_format); 420bf215546Sopenharmony_ci 421bf215546Sopenharmony_ci src_num_channels = _mesa_array_format_get_num_channels(src_array_format); 422bf215546Sopenharmony_ci 423bf215546Sopenharmony_ci _mesa_array_format_get_swizzle(src_array_format, src2rgba); 424bf215546Sopenharmony_ci 425bf215546Sopenharmony_ci normalized = _mesa_array_format_is_normalized(src_array_format); 426bf215546Sopenharmony_ci } 427bf215546Sopenharmony_ci 428bf215546Sopenharmony_ci if (dst_array_format) { 429bf215546Sopenharmony_ci dst_type = _mesa_array_format_get_datatype(dst_array_format); 430bf215546Sopenharmony_ci 431bf215546Sopenharmony_ci dst_num_channels = _mesa_array_format_get_num_channels(dst_array_format); 432bf215546Sopenharmony_ci 433bf215546Sopenharmony_ci _mesa_array_format_get_swizzle(dst_array_format, dst2rgba); 434bf215546Sopenharmony_ci invert_swizzle(rgba2dst, dst2rgba); 435bf215546Sopenharmony_ci 436bf215546Sopenharmony_ci normalized |= _mesa_array_format_is_normalized(dst_array_format); 437bf215546Sopenharmony_ci } 438bf215546Sopenharmony_ci 439bf215546Sopenharmony_ci if (src_array_format && dst_array_format) { 440bf215546Sopenharmony_ci assert(_mesa_array_format_is_normalized(src_array_format) == 441bf215546Sopenharmony_ci _mesa_array_format_is_normalized(dst_array_format)); 442bf215546Sopenharmony_ci 443bf215546Sopenharmony_ci compute_src2dst_component_mapping(src2rgba, rgba2dst, rebase_swizzle, 444bf215546Sopenharmony_ci src2dst); 445bf215546Sopenharmony_ci 446bf215546Sopenharmony_ci for (row = 0; row < height; ++row) { 447bf215546Sopenharmony_ci _mesa_swizzle_and_convert(dst, dst_type, dst_num_channels, 448bf215546Sopenharmony_ci src, src_type, src_num_channels, 449bf215546Sopenharmony_ci src2dst, normalized, width); 450bf215546Sopenharmony_ci src += src_stride; 451bf215546Sopenharmony_ci dst += dst_stride; 452bf215546Sopenharmony_ci } 453bf215546Sopenharmony_ci return; 454bf215546Sopenharmony_ci } 455bf215546Sopenharmony_ci 456bf215546Sopenharmony_ci /* At this point, we're fresh out of fast-paths and we need to convert 457bf215546Sopenharmony_ci * to float, uint32, or, if we're lucky, uint8. 458bf215546Sopenharmony_ci */ 459bf215546Sopenharmony_ci dst_integer = false; 460bf215546Sopenharmony_ci src_integer = false; 461bf215546Sopenharmony_ci 462bf215546Sopenharmony_ci if (src_array_format) { 463bf215546Sopenharmony_ci if (!_mesa_array_format_is_float(src_array_format) && 464bf215546Sopenharmony_ci !_mesa_array_format_is_normalized(src_array_format)) 465bf215546Sopenharmony_ci src_integer = true; 466bf215546Sopenharmony_ci } else { 467bf215546Sopenharmony_ci switch (_mesa_get_format_datatype(src_format)) { 468bf215546Sopenharmony_ci case GL_UNSIGNED_INT: 469bf215546Sopenharmony_ci case GL_INT: 470bf215546Sopenharmony_ci src_integer = true; 471bf215546Sopenharmony_ci break; 472bf215546Sopenharmony_ci } 473bf215546Sopenharmony_ci } 474bf215546Sopenharmony_ci 475bf215546Sopenharmony_ci /* If the destination format is signed but the source is unsigned, then we 476bf215546Sopenharmony_ci * don't loose any data by converting to a signed intermediate format above 477bf215546Sopenharmony_ci * and beyond the precision that we loose in the conversion itself. If the 478bf215546Sopenharmony_ci * destination is unsigned then, by using an unsigned intermediate format, 479bf215546Sopenharmony_ci * we make the conversion function that converts from the source to the 480bf215546Sopenharmony_ci * intermediate format take care of truncating at zero. The exception here 481bf215546Sopenharmony_ci * is if the intermediate format is float, in which case the first 482bf215546Sopenharmony_ci * conversion will leave it signed and the second conversion will truncate 483bf215546Sopenharmony_ci * at zero. 484bf215546Sopenharmony_ci */ 485bf215546Sopenharmony_ci is_signed = false; 486bf215546Sopenharmony_ci if (dst_array_format) { 487bf215546Sopenharmony_ci if (!_mesa_array_format_is_float(dst_array_format) && 488bf215546Sopenharmony_ci !_mesa_array_format_is_normalized(dst_array_format)) 489bf215546Sopenharmony_ci dst_integer = true; 490bf215546Sopenharmony_ci is_signed = _mesa_array_format_is_signed(dst_array_format); 491bf215546Sopenharmony_ci bits = 8 * _mesa_array_format_get_type_size(dst_array_format); 492bf215546Sopenharmony_ci } else { 493bf215546Sopenharmony_ci switch (_mesa_get_format_datatype(dst_format)) { 494bf215546Sopenharmony_ci case GL_UNSIGNED_NORMALIZED: 495bf215546Sopenharmony_ci is_signed = false; 496bf215546Sopenharmony_ci break; 497bf215546Sopenharmony_ci case GL_SIGNED_NORMALIZED: 498bf215546Sopenharmony_ci is_signed = true; 499bf215546Sopenharmony_ci break; 500bf215546Sopenharmony_ci case GL_FLOAT: 501bf215546Sopenharmony_ci is_signed = true; 502bf215546Sopenharmony_ci break; 503bf215546Sopenharmony_ci case GL_UNSIGNED_INT: 504bf215546Sopenharmony_ci is_signed = false; 505bf215546Sopenharmony_ci dst_integer = true; 506bf215546Sopenharmony_ci break; 507bf215546Sopenharmony_ci case GL_INT: 508bf215546Sopenharmony_ci is_signed = true; 509bf215546Sopenharmony_ci dst_integer = true; 510bf215546Sopenharmony_ci break; 511bf215546Sopenharmony_ci } 512bf215546Sopenharmony_ci bits = _mesa_get_format_max_bits(dst_format); 513bf215546Sopenharmony_ci } 514bf215546Sopenharmony_ci 515bf215546Sopenharmony_ci assert(src_integer == dst_integer); 516bf215546Sopenharmony_ci 517bf215546Sopenharmony_ci if (src_integer && dst_integer) { 518bf215546Sopenharmony_ci tmp_uint = malloc(width * height * sizeof(*tmp_uint)); 519bf215546Sopenharmony_ci 520bf215546Sopenharmony_ci /* The [un]packing functions for unsigned datatypes treat the 32-bit 521bf215546Sopenharmony_ci * integer array as signed for signed formats and as unsigned for 522bf215546Sopenharmony_ci * unsigned formats. This is a bit of a problem if we ever convert from 523bf215546Sopenharmony_ci * a signed to an unsigned format because the unsigned packing function 524bf215546Sopenharmony_ci * doesn't know that the input is signed and will treat it as unsigned 525bf215546Sopenharmony_ci * and not do the trunctation. The thing that saves us here is that all 526bf215546Sopenharmony_ci * of the packed formats are unsigned, so we can just always use 527bf215546Sopenharmony_ci * _mesa_swizzle_and_convert for signed formats, which is aware of the 528bf215546Sopenharmony_ci * truncation problem. 529bf215546Sopenharmony_ci */ 530bf215546Sopenharmony_ci common_type = is_signed ? MESA_ARRAY_FORMAT_TYPE_INT : 531bf215546Sopenharmony_ci MESA_ARRAY_FORMAT_TYPE_UINT; 532bf215546Sopenharmony_ci if (src_array_format) { 533bf215546Sopenharmony_ci compute_rebased_rgba_component_mapping(src2rgba, rebase_swizzle, 534bf215546Sopenharmony_ci rebased_src2rgba); 535bf215546Sopenharmony_ci for (row = 0; row < height; ++row) { 536bf215546Sopenharmony_ci _mesa_swizzle_and_convert(tmp_uint + row * width, common_type, 4, 537bf215546Sopenharmony_ci src, src_type, src_num_channels, 538bf215546Sopenharmony_ci rebased_src2rgba, normalized, width); 539bf215546Sopenharmony_ci src += src_stride; 540bf215546Sopenharmony_ci } 541bf215546Sopenharmony_ci } else { 542bf215546Sopenharmony_ci for (row = 0; row < height; ++row) { 543bf215546Sopenharmony_ci _mesa_unpack_uint_rgba_row(src_format, width, 544bf215546Sopenharmony_ci src, tmp_uint + row * width); 545bf215546Sopenharmony_ci if (rebase_swizzle) 546bf215546Sopenharmony_ci _mesa_swizzle_and_convert(tmp_uint + row * width, common_type, 4, 547bf215546Sopenharmony_ci tmp_uint + row * width, common_type, 4, 548bf215546Sopenharmony_ci rebase_swizzle, false, width); 549bf215546Sopenharmony_ci src += src_stride; 550bf215546Sopenharmony_ci } 551bf215546Sopenharmony_ci } 552bf215546Sopenharmony_ci 553bf215546Sopenharmony_ci /* At this point, we have already done the truncation if the source is 554bf215546Sopenharmony_ci * signed but the destination is unsigned, so no need to force the 555bf215546Sopenharmony_ci * _mesa_swizzle_and_convert path. 556bf215546Sopenharmony_ci */ 557bf215546Sopenharmony_ci if (dst_format_is_mesa_array_format) { 558bf215546Sopenharmony_ci for (row = 0; row < height; ++row) { 559bf215546Sopenharmony_ci _mesa_swizzle_and_convert(dst, dst_type, dst_num_channels, 560bf215546Sopenharmony_ci tmp_uint + row * width, common_type, 4, 561bf215546Sopenharmony_ci rgba2dst, normalized, width); 562bf215546Sopenharmony_ci dst += dst_stride; 563bf215546Sopenharmony_ci } 564bf215546Sopenharmony_ci } else { 565bf215546Sopenharmony_ci for (row = 0; row < height; ++row) { 566bf215546Sopenharmony_ci _mesa_pack_uint_rgba_row(dst_format, width, 567bf215546Sopenharmony_ci (const uint32_t (*)[4])tmp_uint + row * width, dst); 568bf215546Sopenharmony_ci dst += dst_stride; 569bf215546Sopenharmony_ci } 570bf215546Sopenharmony_ci } 571bf215546Sopenharmony_ci 572bf215546Sopenharmony_ci free(tmp_uint); 573bf215546Sopenharmony_ci } else if (is_signed || bits > 8) { 574bf215546Sopenharmony_ci tmp_float = malloc(width * height * sizeof(*tmp_float)); 575bf215546Sopenharmony_ci 576bf215546Sopenharmony_ci if (src_format_is_mesa_array_format) { 577bf215546Sopenharmony_ci compute_rebased_rgba_component_mapping(src2rgba, rebase_swizzle, 578bf215546Sopenharmony_ci rebased_src2rgba); 579bf215546Sopenharmony_ci for (row = 0; row < height; ++row) { 580bf215546Sopenharmony_ci _mesa_swizzle_and_convert(tmp_float + row * width, 581bf215546Sopenharmony_ci MESA_ARRAY_FORMAT_TYPE_FLOAT, 4, 582bf215546Sopenharmony_ci src, src_type, src_num_channels, 583bf215546Sopenharmony_ci rebased_src2rgba, normalized, width); 584bf215546Sopenharmony_ci src += src_stride; 585bf215546Sopenharmony_ci } 586bf215546Sopenharmony_ci } else { 587bf215546Sopenharmony_ci for (row = 0; row < height; ++row) { 588bf215546Sopenharmony_ci _mesa_unpack_rgba_row(src_format, width, 589bf215546Sopenharmony_ci src, tmp_float + row * width); 590bf215546Sopenharmony_ci if (rebase_swizzle) 591bf215546Sopenharmony_ci _mesa_swizzle_and_convert(tmp_float + row * width, 592bf215546Sopenharmony_ci MESA_ARRAY_FORMAT_TYPE_FLOAT, 4, 593bf215546Sopenharmony_ci tmp_float + row * width, 594bf215546Sopenharmony_ci MESA_ARRAY_FORMAT_TYPE_FLOAT, 4, 595bf215546Sopenharmony_ci rebase_swizzle, normalized, width); 596bf215546Sopenharmony_ci src += src_stride; 597bf215546Sopenharmony_ci } 598bf215546Sopenharmony_ci } 599bf215546Sopenharmony_ci 600bf215546Sopenharmony_ci if (dst_format_is_mesa_array_format) { 601bf215546Sopenharmony_ci for (row = 0; row < height; ++row) { 602bf215546Sopenharmony_ci _mesa_swizzle_and_convert(dst, dst_type, dst_num_channels, 603bf215546Sopenharmony_ci tmp_float + row * width, 604bf215546Sopenharmony_ci MESA_ARRAY_FORMAT_TYPE_FLOAT, 4, 605bf215546Sopenharmony_ci rgba2dst, normalized, width); 606bf215546Sopenharmony_ci dst += dst_stride; 607bf215546Sopenharmony_ci } 608bf215546Sopenharmony_ci } else { 609bf215546Sopenharmony_ci for (row = 0; row < height; ++row) { 610bf215546Sopenharmony_ci _mesa_pack_float_rgba_row(dst_format, width, 611bf215546Sopenharmony_ci (const float (*)[4])tmp_float + row * width, dst); 612bf215546Sopenharmony_ci dst += dst_stride; 613bf215546Sopenharmony_ci } 614bf215546Sopenharmony_ci } 615bf215546Sopenharmony_ci 616bf215546Sopenharmony_ci free(tmp_float); 617bf215546Sopenharmony_ci } else { 618bf215546Sopenharmony_ci tmp_ubyte = malloc(width * height * sizeof(*tmp_ubyte)); 619bf215546Sopenharmony_ci 620bf215546Sopenharmony_ci if (src_format_is_mesa_array_format) { 621bf215546Sopenharmony_ci compute_rebased_rgba_component_mapping(src2rgba, rebase_swizzle, 622bf215546Sopenharmony_ci rebased_src2rgba); 623bf215546Sopenharmony_ci for (row = 0; row < height; ++row) { 624bf215546Sopenharmony_ci _mesa_swizzle_and_convert(tmp_ubyte + row * width, 625bf215546Sopenharmony_ci MESA_ARRAY_FORMAT_TYPE_UBYTE, 4, 626bf215546Sopenharmony_ci src, src_type, src_num_channels, 627bf215546Sopenharmony_ci rebased_src2rgba, normalized, width); 628bf215546Sopenharmony_ci src += src_stride; 629bf215546Sopenharmony_ci } 630bf215546Sopenharmony_ci } else { 631bf215546Sopenharmony_ci for (row = 0; row < height; ++row) { 632bf215546Sopenharmony_ci _mesa_unpack_ubyte_rgba_row(src_format, width, 633bf215546Sopenharmony_ci src, tmp_ubyte + row * width); 634bf215546Sopenharmony_ci if (rebase_swizzle) 635bf215546Sopenharmony_ci _mesa_swizzle_and_convert(tmp_ubyte + row * width, 636bf215546Sopenharmony_ci MESA_ARRAY_FORMAT_TYPE_UBYTE, 4, 637bf215546Sopenharmony_ci tmp_ubyte + row * width, 638bf215546Sopenharmony_ci MESA_ARRAY_FORMAT_TYPE_UBYTE, 4, 639bf215546Sopenharmony_ci rebase_swizzle, normalized, width); 640bf215546Sopenharmony_ci src += src_stride; 641bf215546Sopenharmony_ci } 642bf215546Sopenharmony_ci } 643bf215546Sopenharmony_ci 644bf215546Sopenharmony_ci if (dst_format_is_mesa_array_format) { 645bf215546Sopenharmony_ci for (row = 0; row < height; ++row) { 646bf215546Sopenharmony_ci _mesa_swizzle_and_convert(dst, dst_type, dst_num_channels, 647bf215546Sopenharmony_ci tmp_ubyte + row * width, 648bf215546Sopenharmony_ci MESA_ARRAY_FORMAT_TYPE_UBYTE, 4, 649bf215546Sopenharmony_ci rgba2dst, normalized, width); 650bf215546Sopenharmony_ci dst += dst_stride; 651bf215546Sopenharmony_ci } 652bf215546Sopenharmony_ci } else { 653bf215546Sopenharmony_ci for (row = 0; row < height; ++row) { 654bf215546Sopenharmony_ci _mesa_pack_ubyte_rgba_row(dst_format, width, 655bf215546Sopenharmony_ci (const uint8_t *)(tmp_ubyte + row * width), dst); 656bf215546Sopenharmony_ci dst += dst_stride; 657bf215546Sopenharmony_ci } 658bf215546Sopenharmony_ci } 659bf215546Sopenharmony_ci 660bf215546Sopenharmony_ci free(tmp_ubyte); 661bf215546Sopenharmony_ci } 662bf215546Sopenharmony_ci} 663bf215546Sopenharmony_ci 664bf215546Sopenharmony_cistatic const uint8_t map_identity[7] = { 0, 1, 2, 3, 4, 5, 6 }; 665bf215546Sopenharmony_ci#if UTIL_ARCH_BIG_ENDIAN 666bf215546Sopenharmony_cistatic const uint8_t map_3210[7] = { 3, 2, 1, 0, 4, 5, 6 }; 667bf215546Sopenharmony_cistatic const uint8_t map_1032[7] = { 1, 0, 3, 2, 4, 5, 6 }; 668bf215546Sopenharmony_ci#endif 669bf215546Sopenharmony_ci 670bf215546Sopenharmony_ci/** 671bf215546Sopenharmony_ci * Describes a format as an array format, if possible 672bf215546Sopenharmony_ci * 673bf215546Sopenharmony_ci * A helper function for figuring out if a (possibly packed) format is 674bf215546Sopenharmony_ci * actually an array format and, if so, what the array parameters are. 675bf215546Sopenharmony_ci * 676bf215546Sopenharmony_ci * \param[in] format the mesa format 677bf215546Sopenharmony_ci * \param[out] type the GL type of the array (GL_BYTE, etc.) 678bf215546Sopenharmony_ci * \param[out] num_components the number of components in the array 679bf215546Sopenharmony_ci * \param[out] swizzle a swizzle describing how to get from the 680bf215546Sopenharmony_ci * given format to RGBA 681bf215546Sopenharmony_ci * \param[out] normalized for integer formats, this represents whether 682bf215546Sopenharmony_ci * the format is a normalized integer or a 683bf215546Sopenharmony_ci * regular integer 684bf215546Sopenharmony_ci * \return true if this format is an array format, false otherwise 685bf215546Sopenharmony_ci */ 686bf215546Sopenharmony_cibool 687bf215546Sopenharmony_ci_mesa_format_to_array(mesa_format format, GLenum *type, int *num_components, 688bf215546Sopenharmony_ci uint8_t swizzle[4], bool *normalized) 689bf215546Sopenharmony_ci{ 690bf215546Sopenharmony_ci int i; 691bf215546Sopenharmony_ci GLuint format_components; 692bf215546Sopenharmony_ci uint8_t packed_swizzle[4]; 693bf215546Sopenharmony_ci const uint8_t *endian; 694bf215546Sopenharmony_ci 695bf215546Sopenharmony_ci if (_mesa_is_format_compressed(format)) 696bf215546Sopenharmony_ci return false; 697bf215546Sopenharmony_ci 698bf215546Sopenharmony_ci *normalized = !_mesa_is_format_integer(format); 699bf215546Sopenharmony_ci 700bf215546Sopenharmony_ci _mesa_uncompressed_format_to_type_and_comps(format, type, &format_components); 701bf215546Sopenharmony_ci 702bf215546Sopenharmony_ci switch (_mesa_get_format_layout(format)) { 703bf215546Sopenharmony_ci case MESA_FORMAT_LAYOUT_ARRAY: 704bf215546Sopenharmony_ci *num_components = format_components; 705bf215546Sopenharmony_ci _mesa_get_format_swizzle(format, swizzle); 706bf215546Sopenharmony_ci return true; 707bf215546Sopenharmony_ci case MESA_FORMAT_LAYOUT_PACKED: 708bf215546Sopenharmony_ci switch (*type) { 709bf215546Sopenharmony_ci case GL_UNSIGNED_BYTE: 710bf215546Sopenharmony_ci case GL_BYTE: 711bf215546Sopenharmony_ci if (_mesa_get_format_max_bits(format) != 8) 712bf215546Sopenharmony_ci return false; 713bf215546Sopenharmony_ci *num_components = _mesa_get_format_bytes(format); 714bf215546Sopenharmony_ci switch (*num_components) { 715bf215546Sopenharmony_ci case 1: 716bf215546Sopenharmony_ci endian = map_identity; 717bf215546Sopenharmony_ci break; 718bf215546Sopenharmony_ci case 2: 719bf215546Sopenharmony_ci#if UTIL_ARCH_LITTLE_ENDIAN 720bf215546Sopenharmony_ci endian = map_identity; 721bf215546Sopenharmony_ci#else 722bf215546Sopenharmony_ci endian = map_1032; 723bf215546Sopenharmony_ci#endif 724bf215546Sopenharmony_ci break; 725bf215546Sopenharmony_ci case 4: 726bf215546Sopenharmony_ci#if UTIL_ARCH_LITTLE_ENDIAN 727bf215546Sopenharmony_ci endian = map_identity; 728bf215546Sopenharmony_ci#else 729bf215546Sopenharmony_ci endian = map_3210; 730bf215546Sopenharmony_ci#endif 731bf215546Sopenharmony_ci break; 732bf215546Sopenharmony_ci default: 733bf215546Sopenharmony_ci endian = map_identity; 734bf215546Sopenharmony_ci assert(!"Invalid number of components"); 735bf215546Sopenharmony_ci } 736bf215546Sopenharmony_ci break; 737bf215546Sopenharmony_ci case GL_UNSIGNED_SHORT: 738bf215546Sopenharmony_ci case GL_SHORT: 739bf215546Sopenharmony_ci case GL_HALF_FLOAT: 740bf215546Sopenharmony_ci if (_mesa_get_format_max_bits(format) != 16) 741bf215546Sopenharmony_ci return false; 742bf215546Sopenharmony_ci *num_components = _mesa_get_format_bytes(format) / 2; 743bf215546Sopenharmony_ci switch (*num_components) { 744bf215546Sopenharmony_ci case 1: 745bf215546Sopenharmony_ci endian = map_identity; 746bf215546Sopenharmony_ci break; 747bf215546Sopenharmony_ci case 2: 748bf215546Sopenharmony_ci#if UTIL_ARCH_LITTLE_ENDIAN 749bf215546Sopenharmony_ci endian = map_identity; 750bf215546Sopenharmony_ci#else 751bf215546Sopenharmony_ci endian = map_1032; 752bf215546Sopenharmony_ci#endif 753bf215546Sopenharmony_ci break; 754bf215546Sopenharmony_ci default: 755bf215546Sopenharmony_ci endian = map_identity; 756bf215546Sopenharmony_ci assert(!"Invalid number of components"); 757bf215546Sopenharmony_ci } 758bf215546Sopenharmony_ci break; 759bf215546Sopenharmony_ci case GL_UNSIGNED_INT: 760bf215546Sopenharmony_ci case GL_INT: 761bf215546Sopenharmony_ci case GL_FLOAT: 762bf215546Sopenharmony_ci /* This isn't packed. At least not really. */ 763bf215546Sopenharmony_ci assert(format_components == 1); 764bf215546Sopenharmony_ci if (_mesa_get_format_max_bits(format) != 32) 765bf215546Sopenharmony_ci return false; 766bf215546Sopenharmony_ci *num_components = format_components; 767bf215546Sopenharmony_ci endian = map_identity; 768bf215546Sopenharmony_ci break; 769bf215546Sopenharmony_ci default: 770bf215546Sopenharmony_ci return false; 771bf215546Sopenharmony_ci } 772bf215546Sopenharmony_ci 773bf215546Sopenharmony_ci _mesa_get_format_swizzle(format, packed_swizzle); 774bf215546Sopenharmony_ci 775bf215546Sopenharmony_ci for (i = 0; i < 4; ++i) 776bf215546Sopenharmony_ci swizzle[i] = endian[packed_swizzle[i]]; 777bf215546Sopenharmony_ci 778bf215546Sopenharmony_ci return true; 779bf215546Sopenharmony_ci case MESA_FORMAT_LAYOUT_OTHER: 780bf215546Sopenharmony_ci default: 781bf215546Sopenharmony_ci return false; 782bf215546Sopenharmony_ci } 783bf215546Sopenharmony_ci} 784bf215546Sopenharmony_ci 785bf215546Sopenharmony_ci/** 786bf215546Sopenharmony_ci * Attempts to perform the given swizzle-and-convert operation with memcpy 787bf215546Sopenharmony_ci * 788bf215546Sopenharmony_ci * This function determines if the given swizzle-and-convert operation can 789bf215546Sopenharmony_ci * be done with a simple memcpy and, if so, does the memcpy. If not, it 790bf215546Sopenharmony_ci * returns false and we fall back to the standard version below. 791bf215546Sopenharmony_ci * 792bf215546Sopenharmony_ci * The arguments are exactly the same as for _mesa_swizzle_and_convert 793bf215546Sopenharmony_ci * 794bf215546Sopenharmony_ci * \return true if it successfully performed the swizzle-and-convert 795bf215546Sopenharmony_ci * operation with memcpy, false otherwise 796bf215546Sopenharmony_ci */ 797bf215546Sopenharmony_cistatic bool 798bf215546Sopenharmony_ciswizzle_convert_try_memcpy(void *dst, 799bf215546Sopenharmony_ci enum mesa_array_format_datatype dst_type, 800bf215546Sopenharmony_ci int num_dst_channels, 801bf215546Sopenharmony_ci const void *src, 802bf215546Sopenharmony_ci enum mesa_array_format_datatype src_type, 803bf215546Sopenharmony_ci int num_src_channels, 804bf215546Sopenharmony_ci const uint8_t swizzle[4], bool normalized, int count) 805bf215546Sopenharmony_ci{ 806bf215546Sopenharmony_ci int i; 807bf215546Sopenharmony_ci 808bf215546Sopenharmony_ci if (src_type != dst_type) 809bf215546Sopenharmony_ci return false; 810bf215546Sopenharmony_ci if (num_src_channels != num_dst_channels) 811bf215546Sopenharmony_ci return false; 812bf215546Sopenharmony_ci 813bf215546Sopenharmony_ci for (i = 0; i < num_dst_channels; ++i) 814bf215546Sopenharmony_ci if (swizzle[i] != i && swizzle[i] != MESA_FORMAT_SWIZZLE_NONE) 815bf215546Sopenharmony_ci return false; 816bf215546Sopenharmony_ci 817bf215546Sopenharmony_ci memcpy(dst, src, count * num_src_channels * 818bf215546Sopenharmony_ci _mesa_array_format_datatype_get_size(src_type)); 819bf215546Sopenharmony_ci 820bf215546Sopenharmony_ci return true; 821bf215546Sopenharmony_ci} 822bf215546Sopenharmony_ci 823bf215546Sopenharmony_ci/** 824bf215546Sopenharmony_ci * Represents a single instance of the standard swizzle-and-convert loop 825bf215546Sopenharmony_ci * 826bf215546Sopenharmony_ci * Any swizzle-and-convert operation simply loops through the pixels and 827bf215546Sopenharmony_ci * performs the transformation operation one pixel at a time. This macro 828bf215546Sopenharmony_ci * embodies one instance of the conversion loop. This way we can do all 829bf215546Sopenharmony_ci * control flow outside of the loop and allow the compiler to unroll 830bf215546Sopenharmony_ci * everything inside the loop. 831bf215546Sopenharmony_ci * 832bf215546Sopenharmony_ci * Note: This loop is carefully crafted for performance. Be careful when 833bf215546Sopenharmony_ci * changing it and run some benchmarks to ensure no performance regressions 834bf215546Sopenharmony_ci * if you do. 835bf215546Sopenharmony_ci * 836bf215546Sopenharmony_ci * \param DST_TYPE the C datatype of the destination 837bf215546Sopenharmony_ci * \param DST_CHANS the number of destination channels 838bf215546Sopenharmony_ci * \param SRC_TYPE the C datatype of the source 839bf215546Sopenharmony_ci * \param SRC_CHANS the number of source channels 840bf215546Sopenharmony_ci * \param CONV an expression for converting from the source data, 841bf215546Sopenharmony_ci * storred in the variable "src", to the destination 842bf215546Sopenharmony_ci * format 843bf215546Sopenharmony_ci */ 844bf215546Sopenharmony_ci#define SWIZZLE_CONVERT_LOOP(DST_TYPE, DST_CHANS, SRC_TYPE, SRC_CHANS, CONV) \ 845bf215546Sopenharmony_ci do { \ 846bf215546Sopenharmony_ci int s, j; \ 847bf215546Sopenharmony_ci for (s = 0; s < count; ++s) { \ 848bf215546Sopenharmony_ci for (j = 0; j < SRC_CHANS; ++j) { \ 849bf215546Sopenharmony_ci SRC_TYPE src = typed_src[j]; \ 850bf215546Sopenharmony_ci tmp[j] = CONV; \ 851bf215546Sopenharmony_ci } \ 852bf215546Sopenharmony_ci \ 853bf215546Sopenharmony_ci typed_dst[0] = tmp[swizzle_x]; \ 854bf215546Sopenharmony_ci if (DST_CHANS > 1) { \ 855bf215546Sopenharmony_ci typed_dst[1] = tmp[swizzle_y]; \ 856bf215546Sopenharmony_ci if (DST_CHANS > 2) { \ 857bf215546Sopenharmony_ci typed_dst[2] = tmp[swizzle_z]; \ 858bf215546Sopenharmony_ci if (DST_CHANS > 3) { \ 859bf215546Sopenharmony_ci typed_dst[3] = tmp[swizzle_w]; \ 860bf215546Sopenharmony_ci } \ 861bf215546Sopenharmony_ci } \ 862bf215546Sopenharmony_ci } \ 863bf215546Sopenharmony_ci typed_src += SRC_CHANS; \ 864bf215546Sopenharmony_ci typed_dst += DST_CHANS; \ 865bf215546Sopenharmony_ci } \ 866bf215546Sopenharmony_ci } while (0) 867bf215546Sopenharmony_ci 868bf215546Sopenharmony_ci/** 869bf215546Sopenharmony_ci * Represents a single swizzle-and-convert operation 870bf215546Sopenharmony_ci * 871bf215546Sopenharmony_ci * This macro represents everything done in a single swizzle-and-convert 872bf215546Sopenharmony_ci * operation. The actual work is done by the SWIZZLE_CONVERT_LOOP macro. 873bf215546Sopenharmony_ci * This macro acts as a wrapper that uses a nested switch to ensure that 874bf215546Sopenharmony_ci * all looping parameters get unrolled. 875bf215546Sopenharmony_ci * 876bf215546Sopenharmony_ci * This macro makes assumptions about variables etc. in the calling 877bf215546Sopenharmony_ci * function. Changes to _mesa_swizzle_and_convert may require changes to 878bf215546Sopenharmony_ci * this macro. 879bf215546Sopenharmony_ci * 880bf215546Sopenharmony_ci * \param DST_TYPE the C datatype of the destination 881bf215546Sopenharmony_ci * \param SRC_TYPE the C datatype of the source 882bf215546Sopenharmony_ci * \param CONV an expression for converting from the source data, 883bf215546Sopenharmony_ci * storred in the variable "src", to the destination 884bf215546Sopenharmony_ci * format 885bf215546Sopenharmony_ci */ 886bf215546Sopenharmony_ci#define SWIZZLE_CONVERT(DST_TYPE, SRC_TYPE, CONV) \ 887bf215546Sopenharmony_ci do { \ 888bf215546Sopenharmony_ci const uint8_t swizzle_x = swizzle[0]; \ 889bf215546Sopenharmony_ci const uint8_t swizzle_y = swizzle[1]; \ 890bf215546Sopenharmony_ci const uint8_t swizzle_z = swizzle[2]; \ 891bf215546Sopenharmony_ci const uint8_t swizzle_w = swizzle[3]; \ 892bf215546Sopenharmony_ci const SRC_TYPE *typed_src = void_src; \ 893bf215546Sopenharmony_ci DST_TYPE *typed_dst = void_dst; \ 894bf215546Sopenharmony_ci DST_TYPE tmp[7]; \ 895bf215546Sopenharmony_ci tmp[4] = 0; \ 896bf215546Sopenharmony_ci tmp[5] = one; \ 897bf215546Sopenharmony_ci switch (num_dst_channels) { \ 898bf215546Sopenharmony_ci case 1: \ 899bf215546Sopenharmony_ci switch (num_src_channels) { \ 900bf215546Sopenharmony_ci case 1: \ 901bf215546Sopenharmony_ci SWIZZLE_CONVERT_LOOP(DST_TYPE, 1, SRC_TYPE, 1, CONV); \ 902bf215546Sopenharmony_ci break; \ 903bf215546Sopenharmony_ci case 2: \ 904bf215546Sopenharmony_ci SWIZZLE_CONVERT_LOOP(DST_TYPE, 1, SRC_TYPE, 2, CONV); \ 905bf215546Sopenharmony_ci break; \ 906bf215546Sopenharmony_ci case 3: \ 907bf215546Sopenharmony_ci SWIZZLE_CONVERT_LOOP(DST_TYPE, 1, SRC_TYPE, 3, CONV); \ 908bf215546Sopenharmony_ci break; \ 909bf215546Sopenharmony_ci case 4: \ 910bf215546Sopenharmony_ci SWIZZLE_CONVERT_LOOP(DST_TYPE, 1, SRC_TYPE, 4, CONV); \ 911bf215546Sopenharmony_ci break; \ 912bf215546Sopenharmony_ci } \ 913bf215546Sopenharmony_ci break; \ 914bf215546Sopenharmony_ci case 2: \ 915bf215546Sopenharmony_ci switch (num_src_channels) { \ 916bf215546Sopenharmony_ci case 1: \ 917bf215546Sopenharmony_ci SWIZZLE_CONVERT_LOOP(DST_TYPE, 2, SRC_TYPE, 1, CONV); \ 918bf215546Sopenharmony_ci break; \ 919bf215546Sopenharmony_ci case 2: \ 920bf215546Sopenharmony_ci SWIZZLE_CONVERT_LOOP(DST_TYPE, 2, SRC_TYPE, 2, CONV); \ 921bf215546Sopenharmony_ci break; \ 922bf215546Sopenharmony_ci case 3: \ 923bf215546Sopenharmony_ci SWIZZLE_CONVERT_LOOP(DST_TYPE, 2, SRC_TYPE, 3, CONV); \ 924bf215546Sopenharmony_ci break; \ 925bf215546Sopenharmony_ci case 4: \ 926bf215546Sopenharmony_ci SWIZZLE_CONVERT_LOOP(DST_TYPE, 2, SRC_TYPE, 4, CONV); \ 927bf215546Sopenharmony_ci break; \ 928bf215546Sopenharmony_ci } \ 929bf215546Sopenharmony_ci break; \ 930bf215546Sopenharmony_ci case 3: \ 931bf215546Sopenharmony_ci switch (num_src_channels) { \ 932bf215546Sopenharmony_ci case 1: \ 933bf215546Sopenharmony_ci SWIZZLE_CONVERT_LOOP(DST_TYPE, 3, SRC_TYPE, 1, CONV); \ 934bf215546Sopenharmony_ci break; \ 935bf215546Sopenharmony_ci case 2: \ 936bf215546Sopenharmony_ci SWIZZLE_CONVERT_LOOP(DST_TYPE, 3, SRC_TYPE, 2, CONV); \ 937bf215546Sopenharmony_ci break; \ 938bf215546Sopenharmony_ci case 3: \ 939bf215546Sopenharmony_ci SWIZZLE_CONVERT_LOOP(DST_TYPE, 3, SRC_TYPE, 3, CONV); \ 940bf215546Sopenharmony_ci break; \ 941bf215546Sopenharmony_ci case 4: \ 942bf215546Sopenharmony_ci SWIZZLE_CONVERT_LOOP(DST_TYPE, 3, SRC_TYPE, 4, CONV); \ 943bf215546Sopenharmony_ci break; \ 944bf215546Sopenharmony_ci } \ 945bf215546Sopenharmony_ci break; \ 946bf215546Sopenharmony_ci case 4: \ 947bf215546Sopenharmony_ci switch (num_src_channels) { \ 948bf215546Sopenharmony_ci case 1: \ 949bf215546Sopenharmony_ci SWIZZLE_CONVERT_LOOP(DST_TYPE, 4, SRC_TYPE, 1, CONV); \ 950bf215546Sopenharmony_ci break; \ 951bf215546Sopenharmony_ci case 2: \ 952bf215546Sopenharmony_ci SWIZZLE_CONVERT_LOOP(DST_TYPE, 4, SRC_TYPE, 2, CONV); \ 953bf215546Sopenharmony_ci break; \ 954bf215546Sopenharmony_ci case 3: \ 955bf215546Sopenharmony_ci SWIZZLE_CONVERT_LOOP(DST_TYPE, 4, SRC_TYPE, 3, CONV); \ 956bf215546Sopenharmony_ci break; \ 957bf215546Sopenharmony_ci case 4: \ 958bf215546Sopenharmony_ci SWIZZLE_CONVERT_LOOP(DST_TYPE, 4, SRC_TYPE, 4, CONV); \ 959bf215546Sopenharmony_ci break; \ 960bf215546Sopenharmony_ci } \ 961bf215546Sopenharmony_ci break; \ 962bf215546Sopenharmony_ci } \ 963bf215546Sopenharmony_ci } while (0) 964bf215546Sopenharmony_ci 965bf215546Sopenharmony_ci 966bf215546Sopenharmony_cistatic void 967bf215546Sopenharmony_ciconvert_float(void *void_dst, int num_dst_channels, 968bf215546Sopenharmony_ci const void *void_src, GLenum src_type, int num_src_channels, 969bf215546Sopenharmony_ci const uint8_t swizzle[4], bool normalized, int count) 970bf215546Sopenharmony_ci{ 971bf215546Sopenharmony_ci const float one = 1.0f; 972bf215546Sopenharmony_ci 973bf215546Sopenharmony_ci switch (src_type) { 974bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_FLOAT: 975bf215546Sopenharmony_ci SWIZZLE_CONVERT(float, float, src); 976bf215546Sopenharmony_ci break; 977bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_HALF: 978bf215546Sopenharmony_ci SWIZZLE_CONVERT(float, uint16_t, _mesa_half_to_float(src)); 979bf215546Sopenharmony_ci break; 980bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_UBYTE: 981bf215546Sopenharmony_ci if (normalized) { 982bf215546Sopenharmony_ci SWIZZLE_CONVERT(float, uint8_t, _mesa_unorm_to_float(src, 8)); 983bf215546Sopenharmony_ci } else { 984bf215546Sopenharmony_ci SWIZZLE_CONVERT(float, uint8_t, src); 985bf215546Sopenharmony_ci } 986bf215546Sopenharmony_ci break; 987bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_BYTE: 988bf215546Sopenharmony_ci if (normalized) { 989bf215546Sopenharmony_ci SWIZZLE_CONVERT(float, int8_t, _mesa_snorm_to_float(src, 8)); 990bf215546Sopenharmony_ci } else { 991bf215546Sopenharmony_ci SWIZZLE_CONVERT(float, int8_t, src); 992bf215546Sopenharmony_ci } 993bf215546Sopenharmony_ci break; 994bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_USHORT: 995bf215546Sopenharmony_ci if (normalized) { 996bf215546Sopenharmony_ci SWIZZLE_CONVERT(float, uint16_t, _mesa_unorm_to_float(src, 16)); 997bf215546Sopenharmony_ci } else { 998bf215546Sopenharmony_ci SWIZZLE_CONVERT(float, uint16_t, src); 999bf215546Sopenharmony_ci } 1000bf215546Sopenharmony_ci break; 1001bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_SHORT: 1002bf215546Sopenharmony_ci if (normalized) { 1003bf215546Sopenharmony_ci SWIZZLE_CONVERT(float, int16_t, _mesa_snorm_to_float(src, 16)); 1004bf215546Sopenharmony_ci } else { 1005bf215546Sopenharmony_ci SWIZZLE_CONVERT(float, int16_t, src); 1006bf215546Sopenharmony_ci } 1007bf215546Sopenharmony_ci break; 1008bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_UINT: 1009bf215546Sopenharmony_ci if (normalized) { 1010bf215546Sopenharmony_ci SWIZZLE_CONVERT(float, uint32_t, _mesa_unorm_to_float(src, 32)); 1011bf215546Sopenharmony_ci } else { 1012bf215546Sopenharmony_ci SWIZZLE_CONVERT(float, uint32_t, src); 1013bf215546Sopenharmony_ci } 1014bf215546Sopenharmony_ci break; 1015bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_INT: 1016bf215546Sopenharmony_ci if (normalized) { 1017bf215546Sopenharmony_ci SWIZZLE_CONVERT(float, int32_t, _mesa_snorm_to_float(src, 32)); 1018bf215546Sopenharmony_ci } else { 1019bf215546Sopenharmony_ci SWIZZLE_CONVERT(float, int32_t, src); 1020bf215546Sopenharmony_ci } 1021bf215546Sopenharmony_ci break; 1022bf215546Sopenharmony_ci default: 1023bf215546Sopenharmony_ci assert(!"Invalid channel type combination"); 1024bf215546Sopenharmony_ci } 1025bf215546Sopenharmony_ci} 1026bf215546Sopenharmony_ci 1027bf215546Sopenharmony_ci 1028bf215546Sopenharmony_cistatic void 1029bf215546Sopenharmony_ciconvert_half_float(void *void_dst, int num_dst_channels, 1030bf215546Sopenharmony_ci const void *void_src, GLenum src_type, int num_src_channels, 1031bf215546Sopenharmony_ci const uint8_t swizzle[4], bool normalized, int count) 1032bf215546Sopenharmony_ci{ 1033bf215546Sopenharmony_ci const uint16_t one = _mesa_float_to_half(1.0f); 1034bf215546Sopenharmony_ci 1035bf215546Sopenharmony_ci switch (src_type) { 1036bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_FLOAT: 1037bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint16_t, float, _mesa_float_to_half(src)); 1038bf215546Sopenharmony_ci break; 1039bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_HALF: 1040bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint16_t, uint16_t, src); 1041bf215546Sopenharmony_ci break; 1042bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_UBYTE: 1043bf215546Sopenharmony_ci if (normalized) { 1044bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint16_t, uint8_t, _mesa_unorm_to_half(src, 8)); 1045bf215546Sopenharmony_ci } else { 1046bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint16_t, uint8_t, _mesa_float_to_half(src)); 1047bf215546Sopenharmony_ci } 1048bf215546Sopenharmony_ci break; 1049bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_BYTE: 1050bf215546Sopenharmony_ci if (normalized) { 1051bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint16_t, int8_t, _mesa_snorm_to_half(src, 8)); 1052bf215546Sopenharmony_ci } else { 1053bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint16_t, int8_t, _mesa_float_to_half(src)); 1054bf215546Sopenharmony_ci } 1055bf215546Sopenharmony_ci break; 1056bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_USHORT: 1057bf215546Sopenharmony_ci if (normalized) { 1058bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint16_t, uint16_t, _mesa_unorm_to_half(src, 16)); 1059bf215546Sopenharmony_ci } else { 1060bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint16_t, uint16_t, _mesa_float_to_half(src)); 1061bf215546Sopenharmony_ci } 1062bf215546Sopenharmony_ci break; 1063bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_SHORT: 1064bf215546Sopenharmony_ci if (normalized) { 1065bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint16_t, int16_t, _mesa_snorm_to_half(src, 16)); 1066bf215546Sopenharmony_ci } else { 1067bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint16_t, int16_t, _mesa_float_to_half(src)); 1068bf215546Sopenharmony_ci } 1069bf215546Sopenharmony_ci break; 1070bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_UINT: 1071bf215546Sopenharmony_ci if (normalized) { 1072bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint16_t, uint32_t, _mesa_unorm_to_half(src, 32)); 1073bf215546Sopenharmony_ci } else { 1074bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint16_t, uint32_t, _mesa_float_to_half(src)); 1075bf215546Sopenharmony_ci } 1076bf215546Sopenharmony_ci break; 1077bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_INT: 1078bf215546Sopenharmony_ci if (normalized) { 1079bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint16_t, int32_t, _mesa_snorm_to_half(src, 32)); 1080bf215546Sopenharmony_ci } else { 1081bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint16_t, int32_t, _mesa_float_to_half(src)); 1082bf215546Sopenharmony_ci } 1083bf215546Sopenharmony_ci break; 1084bf215546Sopenharmony_ci default: 1085bf215546Sopenharmony_ci assert(!"Invalid channel type combination"); 1086bf215546Sopenharmony_ci } 1087bf215546Sopenharmony_ci} 1088bf215546Sopenharmony_ci 1089bf215546Sopenharmony_cistatic void 1090bf215546Sopenharmony_ciconvert_ubyte(void *void_dst, int num_dst_channels, 1091bf215546Sopenharmony_ci const void *void_src, GLenum src_type, int num_src_channels, 1092bf215546Sopenharmony_ci const uint8_t swizzle[4], bool normalized, int count) 1093bf215546Sopenharmony_ci{ 1094bf215546Sopenharmony_ci const uint8_t one = normalized ? UINT8_MAX : 1; 1095bf215546Sopenharmony_ci 1096bf215546Sopenharmony_ci switch (src_type) { 1097bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_FLOAT: 1098bf215546Sopenharmony_ci if (normalized) { 1099bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint8_t, float, _mesa_float_to_unorm(src, 8)); 1100bf215546Sopenharmony_ci } else { 1101bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint8_t, float, _mesa_float_to_unsigned(src, 8)); 1102bf215546Sopenharmony_ci } 1103bf215546Sopenharmony_ci break; 1104bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_HALF: 1105bf215546Sopenharmony_ci if (normalized) { 1106bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint8_t, uint16_t, _mesa_half_to_unorm(src, 8)); 1107bf215546Sopenharmony_ci } else { 1108bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint8_t, uint16_t, _mesa_half_to_unsigned(src, 8)); 1109bf215546Sopenharmony_ci } 1110bf215546Sopenharmony_ci break; 1111bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_UBYTE: 1112bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint8_t, uint8_t, src); 1113bf215546Sopenharmony_ci break; 1114bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_BYTE: 1115bf215546Sopenharmony_ci if (normalized) { 1116bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint8_t, int8_t, _mesa_snorm_to_unorm(src, 8, 8)); 1117bf215546Sopenharmony_ci } else { 1118bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint8_t, int8_t, _mesa_signed_to_unsigned(src, 8)); 1119bf215546Sopenharmony_ci } 1120bf215546Sopenharmony_ci break; 1121bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_USHORT: 1122bf215546Sopenharmony_ci if (normalized) { 1123bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint8_t, uint16_t, _mesa_unorm_to_unorm(src, 16, 8)); 1124bf215546Sopenharmony_ci } else { 1125bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint8_t, uint16_t, _mesa_unsigned_to_unsigned(src, 8)); 1126bf215546Sopenharmony_ci } 1127bf215546Sopenharmony_ci break; 1128bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_SHORT: 1129bf215546Sopenharmony_ci if (normalized) { 1130bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint8_t, int16_t, _mesa_snorm_to_unorm(src, 16, 8)); 1131bf215546Sopenharmony_ci } else { 1132bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint8_t, int16_t, _mesa_signed_to_unsigned(src, 8)); 1133bf215546Sopenharmony_ci } 1134bf215546Sopenharmony_ci break; 1135bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_UINT: 1136bf215546Sopenharmony_ci if (normalized) { 1137bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint8_t, uint32_t, _mesa_unorm_to_unorm(src, 32, 8)); 1138bf215546Sopenharmony_ci } else { 1139bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint8_t, uint32_t, _mesa_unsigned_to_unsigned(src, 8)); 1140bf215546Sopenharmony_ci } 1141bf215546Sopenharmony_ci break; 1142bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_INT: 1143bf215546Sopenharmony_ci if (normalized) { 1144bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint8_t, int32_t, _mesa_snorm_to_unorm(src, 32, 8)); 1145bf215546Sopenharmony_ci } else { 1146bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint8_t, int32_t, _mesa_signed_to_unsigned(src, 8)); 1147bf215546Sopenharmony_ci } 1148bf215546Sopenharmony_ci break; 1149bf215546Sopenharmony_ci default: 1150bf215546Sopenharmony_ci assert(!"Invalid channel type combination"); 1151bf215546Sopenharmony_ci } 1152bf215546Sopenharmony_ci} 1153bf215546Sopenharmony_ci 1154bf215546Sopenharmony_ci 1155bf215546Sopenharmony_cistatic void 1156bf215546Sopenharmony_ciconvert_byte(void *void_dst, int num_dst_channels, 1157bf215546Sopenharmony_ci const void *void_src, GLenum src_type, int num_src_channels, 1158bf215546Sopenharmony_ci const uint8_t swizzle[4], bool normalized, int count) 1159bf215546Sopenharmony_ci{ 1160bf215546Sopenharmony_ci const int8_t one = normalized ? INT8_MAX : 1; 1161bf215546Sopenharmony_ci 1162bf215546Sopenharmony_ci switch (src_type) { 1163bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_FLOAT: 1164bf215546Sopenharmony_ci if (normalized) { 1165bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint8_t, float, _mesa_float_to_snorm(src, 8)); 1166bf215546Sopenharmony_ci } else { 1167bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint8_t, float, _mesa_float_to_signed(src, 8)); 1168bf215546Sopenharmony_ci } 1169bf215546Sopenharmony_ci break; 1170bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_HALF: 1171bf215546Sopenharmony_ci if (normalized) { 1172bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint8_t, uint16_t, _mesa_half_to_snorm(src, 8)); 1173bf215546Sopenharmony_ci } else { 1174bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint8_t, uint16_t, _mesa_half_to_signed(src, 8)); 1175bf215546Sopenharmony_ci } 1176bf215546Sopenharmony_ci break; 1177bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_UBYTE: 1178bf215546Sopenharmony_ci if (normalized) { 1179bf215546Sopenharmony_ci SWIZZLE_CONVERT(int8_t, uint8_t, _mesa_unorm_to_snorm(src, 8, 8)); 1180bf215546Sopenharmony_ci } else { 1181bf215546Sopenharmony_ci SWIZZLE_CONVERT(int8_t, uint8_t, _mesa_unsigned_to_signed(src, 8)); 1182bf215546Sopenharmony_ci } 1183bf215546Sopenharmony_ci break; 1184bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_BYTE: 1185bf215546Sopenharmony_ci SWIZZLE_CONVERT(int8_t, int8_t, src); 1186bf215546Sopenharmony_ci break; 1187bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_USHORT: 1188bf215546Sopenharmony_ci if (normalized) { 1189bf215546Sopenharmony_ci SWIZZLE_CONVERT(int8_t, uint16_t, _mesa_unorm_to_snorm(src, 16, 8)); 1190bf215546Sopenharmony_ci } else { 1191bf215546Sopenharmony_ci SWIZZLE_CONVERT(int8_t, uint16_t, _mesa_unsigned_to_signed(src, 8)); 1192bf215546Sopenharmony_ci } 1193bf215546Sopenharmony_ci break; 1194bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_SHORT: 1195bf215546Sopenharmony_ci if (normalized) { 1196bf215546Sopenharmony_ci SWIZZLE_CONVERT(int8_t, int16_t, _mesa_snorm_to_snorm(src, 16, 8)); 1197bf215546Sopenharmony_ci } else { 1198bf215546Sopenharmony_ci SWIZZLE_CONVERT(int8_t, int16_t, _mesa_signed_to_signed(src, 8)); 1199bf215546Sopenharmony_ci } 1200bf215546Sopenharmony_ci break; 1201bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_UINT: 1202bf215546Sopenharmony_ci if (normalized) { 1203bf215546Sopenharmony_ci SWIZZLE_CONVERT(int8_t, uint32_t, _mesa_unorm_to_snorm(src, 32, 8)); 1204bf215546Sopenharmony_ci } else { 1205bf215546Sopenharmony_ci SWIZZLE_CONVERT(int8_t, uint32_t, _mesa_unsigned_to_signed(src, 8)); 1206bf215546Sopenharmony_ci } 1207bf215546Sopenharmony_ci break; 1208bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_INT: 1209bf215546Sopenharmony_ci if (normalized) { 1210bf215546Sopenharmony_ci SWIZZLE_CONVERT(int8_t, int32_t, _mesa_snorm_to_snorm(src, 32, 8)); 1211bf215546Sopenharmony_ci } else { 1212bf215546Sopenharmony_ci SWIZZLE_CONVERT(int8_t, int32_t, _mesa_signed_to_signed(src, 8)); 1213bf215546Sopenharmony_ci } 1214bf215546Sopenharmony_ci break; 1215bf215546Sopenharmony_ci default: 1216bf215546Sopenharmony_ci assert(!"Invalid channel type combination"); 1217bf215546Sopenharmony_ci } 1218bf215546Sopenharmony_ci} 1219bf215546Sopenharmony_ci 1220bf215546Sopenharmony_ci 1221bf215546Sopenharmony_cistatic void 1222bf215546Sopenharmony_ciconvert_ushort(void *void_dst, int num_dst_channels, 1223bf215546Sopenharmony_ci const void *void_src, GLenum src_type, int num_src_channels, 1224bf215546Sopenharmony_ci const uint8_t swizzle[4], bool normalized, int count) 1225bf215546Sopenharmony_ci{ 1226bf215546Sopenharmony_ci const uint16_t one = normalized ? UINT16_MAX : 1; 1227bf215546Sopenharmony_ci 1228bf215546Sopenharmony_ci switch (src_type) { 1229bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_FLOAT: 1230bf215546Sopenharmony_ci if (normalized) { 1231bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint16_t, float, _mesa_float_to_unorm(src, 16)); 1232bf215546Sopenharmony_ci } else { 1233bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint16_t, float, _mesa_float_to_unsigned(src, 16)); 1234bf215546Sopenharmony_ci } 1235bf215546Sopenharmony_ci break; 1236bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_HALF: 1237bf215546Sopenharmony_ci if (normalized) { 1238bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint16_t, uint16_t, _mesa_half_to_unorm(src, 16)); 1239bf215546Sopenharmony_ci } else { 1240bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint16_t, uint16_t, _mesa_half_to_unsigned(src, 16)); 1241bf215546Sopenharmony_ci } 1242bf215546Sopenharmony_ci break; 1243bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_UBYTE: 1244bf215546Sopenharmony_ci if (normalized) { 1245bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint16_t, uint8_t, _mesa_unorm_to_unorm(src, 8, 16)); 1246bf215546Sopenharmony_ci } else { 1247bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint16_t, uint8_t, src); 1248bf215546Sopenharmony_ci } 1249bf215546Sopenharmony_ci break; 1250bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_BYTE: 1251bf215546Sopenharmony_ci if (normalized) { 1252bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint16_t, int8_t, _mesa_snorm_to_unorm(src, 8, 16)); 1253bf215546Sopenharmony_ci } else { 1254bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint16_t, int8_t, _mesa_signed_to_unsigned(src, 16)); 1255bf215546Sopenharmony_ci } 1256bf215546Sopenharmony_ci break; 1257bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_USHORT: 1258bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint16_t, uint16_t, src); 1259bf215546Sopenharmony_ci break; 1260bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_SHORT: 1261bf215546Sopenharmony_ci if (normalized) { 1262bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint16_t, int16_t, _mesa_snorm_to_unorm(src, 16, 16)); 1263bf215546Sopenharmony_ci } else { 1264bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint16_t, int16_t, _mesa_signed_to_unsigned(src, 16)); 1265bf215546Sopenharmony_ci } 1266bf215546Sopenharmony_ci break; 1267bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_UINT: 1268bf215546Sopenharmony_ci if (normalized) { 1269bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint16_t, uint32_t, _mesa_unorm_to_unorm(src, 32, 16)); 1270bf215546Sopenharmony_ci } else { 1271bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint16_t, uint32_t, _mesa_unsigned_to_unsigned(src, 16)); 1272bf215546Sopenharmony_ci } 1273bf215546Sopenharmony_ci break; 1274bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_INT: 1275bf215546Sopenharmony_ci if (normalized) { 1276bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint16_t, int32_t, _mesa_snorm_to_unorm(src, 32, 16)); 1277bf215546Sopenharmony_ci } else { 1278bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint16_t, int32_t, _mesa_signed_to_unsigned(src, 16)); 1279bf215546Sopenharmony_ci } 1280bf215546Sopenharmony_ci break; 1281bf215546Sopenharmony_ci default: 1282bf215546Sopenharmony_ci assert(!"Invalid channel type combination"); 1283bf215546Sopenharmony_ci } 1284bf215546Sopenharmony_ci} 1285bf215546Sopenharmony_ci 1286bf215546Sopenharmony_ci 1287bf215546Sopenharmony_cistatic void 1288bf215546Sopenharmony_ciconvert_short(void *void_dst, int num_dst_channels, 1289bf215546Sopenharmony_ci const void *void_src, GLenum src_type, int num_src_channels, 1290bf215546Sopenharmony_ci const uint8_t swizzle[4], bool normalized, int count) 1291bf215546Sopenharmony_ci{ 1292bf215546Sopenharmony_ci const int16_t one = normalized ? INT16_MAX : 1; 1293bf215546Sopenharmony_ci 1294bf215546Sopenharmony_ci switch (src_type) { 1295bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_FLOAT: 1296bf215546Sopenharmony_ci if (normalized) { 1297bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint16_t, float, _mesa_float_to_snorm(src, 16)); 1298bf215546Sopenharmony_ci } else { 1299bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint16_t, float, _mesa_float_to_signed(src, 16)); 1300bf215546Sopenharmony_ci } 1301bf215546Sopenharmony_ci break; 1302bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_HALF: 1303bf215546Sopenharmony_ci if (normalized) { 1304bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint16_t, uint16_t, _mesa_half_to_snorm(src, 16)); 1305bf215546Sopenharmony_ci } else { 1306bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint16_t, uint16_t, _mesa_half_to_signed(src, 16)); 1307bf215546Sopenharmony_ci } 1308bf215546Sopenharmony_ci break; 1309bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_UBYTE: 1310bf215546Sopenharmony_ci if (normalized) { 1311bf215546Sopenharmony_ci SWIZZLE_CONVERT(int16_t, uint8_t, _mesa_unorm_to_snorm(src, 8, 16)); 1312bf215546Sopenharmony_ci } else { 1313bf215546Sopenharmony_ci SWIZZLE_CONVERT(int16_t, uint8_t, src); 1314bf215546Sopenharmony_ci } 1315bf215546Sopenharmony_ci break; 1316bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_BYTE: 1317bf215546Sopenharmony_ci if (normalized) { 1318bf215546Sopenharmony_ci SWIZZLE_CONVERT(int16_t, int8_t, _mesa_snorm_to_snorm(src, 8, 16)); 1319bf215546Sopenharmony_ci } else { 1320bf215546Sopenharmony_ci SWIZZLE_CONVERT(int16_t, int8_t, src); 1321bf215546Sopenharmony_ci } 1322bf215546Sopenharmony_ci break; 1323bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_USHORT: 1324bf215546Sopenharmony_ci if (normalized) { 1325bf215546Sopenharmony_ci SWIZZLE_CONVERT(int16_t, uint16_t, _mesa_unorm_to_snorm(src, 16, 16)); 1326bf215546Sopenharmony_ci } else { 1327bf215546Sopenharmony_ci SWIZZLE_CONVERT(int16_t, uint16_t, _mesa_unsigned_to_signed(src, 16)); 1328bf215546Sopenharmony_ci } 1329bf215546Sopenharmony_ci break; 1330bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_SHORT: 1331bf215546Sopenharmony_ci SWIZZLE_CONVERT(int16_t, int16_t, src); 1332bf215546Sopenharmony_ci break; 1333bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_UINT: 1334bf215546Sopenharmony_ci if (normalized) { 1335bf215546Sopenharmony_ci SWIZZLE_CONVERT(int16_t, uint32_t, _mesa_unorm_to_snorm(src, 32, 16)); 1336bf215546Sopenharmony_ci } else { 1337bf215546Sopenharmony_ci SWIZZLE_CONVERT(int16_t, uint32_t, _mesa_unsigned_to_signed(src, 16)); 1338bf215546Sopenharmony_ci } 1339bf215546Sopenharmony_ci break; 1340bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_INT: 1341bf215546Sopenharmony_ci if (normalized) { 1342bf215546Sopenharmony_ci SWIZZLE_CONVERT(int16_t, int32_t, _mesa_snorm_to_snorm(src, 32, 16)); 1343bf215546Sopenharmony_ci } else { 1344bf215546Sopenharmony_ci SWIZZLE_CONVERT(int16_t, int32_t, _mesa_signed_to_signed(src, 16)); 1345bf215546Sopenharmony_ci } 1346bf215546Sopenharmony_ci break; 1347bf215546Sopenharmony_ci default: 1348bf215546Sopenharmony_ci assert(!"Invalid channel type combination"); 1349bf215546Sopenharmony_ci } 1350bf215546Sopenharmony_ci} 1351bf215546Sopenharmony_ci 1352bf215546Sopenharmony_cistatic void 1353bf215546Sopenharmony_ciconvert_uint(void *void_dst, int num_dst_channels, 1354bf215546Sopenharmony_ci const void *void_src, GLenum src_type, int num_src_channels, 1355bf215546Sopenharmony_ci const uint8_t swizzle[4], bool normalized, int count) 1356bf215546Sopenharmony_ci{ 1357bf215546Sopenharmony_ci const uint32_t one = normalized ? UINT32_MAX : 1; 1358bf215546Sopenharmony_ci 1359bf215546Sopenharmony_ci switch (src_type) { 1360bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_FLOAT: 1361bf215546Sopenharmony_ci if (normalized) { 1362bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint32_t, float, _mesa_float_to_unorm(src, 32)); 1363bf215546Sopenharmony_ci } else { 1364bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint32_t, float, _mesa_float_to_unsigned(src, 32)); 1365bf215546Sopenharmony_ci } 1366bf215546Sopenharmony_ci break; 1367bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_HALF: 1368bf215546Sopenharmony_ci if (normalized) { 1369bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint32_t, uint16_t, _mesa_half_to_unorm(src, 32)); 1370bf215546Sopenharmony_ci } else { 1371bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint32_t, uint16_t, _mesa_half_to_unsigned(src, 32)); 1372bf215546Sopenharmony_ci } 1373bf215546Sopenharmony_ci break; 1374bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_UBYTE: 1375bf215546Sopenharmony_ci if (normalized) { 1376bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint32_t, uint8_t, _mesa_unorm_to_unorm(src, 8, 32)); 1377bf215546Sopenharmony_ci } else { 1378bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint32_t, uint8_t, src); 1379bf215546Sopenharmony_ci } 1380bf215546Sopenharmony_ci break; 1381bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_BYTE: 1382bf215546Sopenharmony_ci if (normalized) { 1383bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint32_t, int8_t, _mesa_snorm_to_unorm(src, 8, 32)); 1384bf215546Sopenharmony_ci } else { 1385bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint32_t, int8_t, _mesa_signed_to_unsigned(src, 32)); 1386bf215546Sopenharmony_ci } 1387bf215546Sopenharmony_ci break; 1388bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_USHORT: 1389bf215546Sopenharmony_ci if (normalized) { 1390bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint32_t, uint16_t, _mesa_unorm_to_unorm(src, 16, 32)); 1391bf215546Sopenharmony_ci } else { 1392bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint32_t, uint16_t, src); 1393bf215546Sopenharmony_ci } 1394bf215546Sopenharmony_ci break; 1395bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_SHORT: 1396bf215546Sopenharmony_ci if (normalized) { 1397bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint32_t, int16_t, _mesa_snorm_to_unorm(src, 16, 32)); 1398bf215546Sopenharmony_ci } else { 1399bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint32_t, int16_t, _mesa_signed_to_unsigned(src, 32)); 1400bf215546Sopenharmony_ci } 1401bf215546Sopenharmony_ci break; 1402bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_UINT: 1403bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint32_t, uint32_t, src); 1404bf215546Sopenharmony_ci break; 1405bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_INT: 1406bf215546Sopenharmony_ci if (normalized) { 1407bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint32_t, int32_t, _mesa_snorm_to_unorm(src, 32, 32)); 1408bf215546Sopenharmony_ci } else { 1409bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint32_t, int32_t, _mesa_signed_to_unsigned(src, 32)); 1410bf215546Sopenharmony_ci } 1411bf215546Sopenharmony_ci break; 1412bf215546Sopenharmony_ci default: 1413bf215546Sopenharmony_ci assert(!"Invalid channel type combination"); 1414bf215546Sopenharmony_ci } 1415bf215546Sopenharmony_ci} 1416bf215546Sopenharmony_ci 1417bf215546Sopenharmony_ci 1418bf215546Sopenharmony_cistatic void 1419bf215546Sopenharmony_ciconvert_int(void *void_dst, int num_dst_channels, 1420bf215546Sopenharmony_ci const void *void_src, GLenum src_type, int num_src_channels, 1421bf215546Sopenharmony_ci const uint8_t swizzle[4], bool normalized, int count) 1422bf215546Sopenharmony_ci{ 1423bf215546Sopenharmony_ci const int32_t one = normalized ? INT32_MAX : 1; 1424bf215546Sopenharmony_ci 1425bf215546Sopenharmony_ci switch (src_type) { 1426bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_FLOAT: 1427bf215546Sopenharmony_ci if (normalized) { 1428bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint32_t, float, _mesa_float_to_snorm(src, 32)); 1429bf215546Sopenharmony_ci } else { 1430bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint32_t, float, _mesa_float_to_signed(src, 32)); 1431bf215546Sopenharmony_ci } 1432bf215546Sopenharmony_ci break; 1433bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_HALF: 1434bf215546Sopenharmony_ci if (normalized) { 1435bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint32_t, uint16_t, _mesa_half_to_snorm(src, 32)); 1436bf215546Sopenharmony_ci } else { 1437bf215546Sopenharmony_ci SWIZZLE_CONVERT(uint32_t, uint16_t, _mesa_half_to_signed(src, 32)); 1438bf215546Sopenharmony_ci } 1439bf215546Sopenharmony_ci break; 1440bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_UBYTE: 1441bf215546Sopenharmony_ci if (normalized) { 1442bf215546Sopenharmony_ci SWIZZLE_CONVERT(int32_t, uint8_t, _mesa_unorm_to_snorm(src, 8, 32)); 1443bf215546Sopenharmony_ci } else { 1444bf215546Sopenharmony_ci SWIZZLE_CONVERT(int32_t, uint8_t, src); 1445bf215546Sopenharmony_ci } 1446bf215546Sopenharmony_ci break; 1447bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_BYTE: 1448bf215546Sopenharmony_ci if (normalized) { 1449bf215546Sopenharmony_ci SWIZZLE_CONVERT(int32_t, int8_t, _mesa_snorm_to_snorm(src, 8, 32)); 1450bf215546Sopenharmony_ci } else { 1451bf215546Sopenharmony_ci SWIZZLE_CONVERT(int32_t, int8_t, src); 1452bf215546Sopenharmony_ci } 1453bf215546Sopenharmony_ci break; 1454bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_USHORT: 1455bf215546Sopenharmony_ci if (normalized) { 1456bf215546Sopenharmony_ci SWIZZLE_CONVERT(int32_t, uint16_t, _mesa_unorm_to_snorm(src, 16, 32)); 1457bf215546Sopenharmony_ci } else { 1458bf215546Sopenharmony_ci SWIZZLE_CONVERT(int32_t, uint16_t, src); 1459bf215546Sopenharmony_ci } 1460bf215546Sopenharmony_ci break; 1461bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_SHORT: 1462bf215546Sopenharmony_ci if (normalized) { 1463bf215546Sopenharmony_ci SWIZZLE_CONVERT(int32_t, int16_t, _mesa_snorm_to_snorm(src, 16, 32)); 1464bf215546Sopenharmony_ci } else { 1465bf215546Sopenharmony_ci SWIZZLE_CONVERT(int32_t, int16_t, src); 1466bf215546Sopenharmony_ci } 1467bf215546Sopenharmony_ci break; 1468bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_UINT: 1469bf215546Sopenharmony_ci if (normalized) { 1470bf215546Sopenharmony_ci SWIZZLE_CONVERT(int32_t, uint32_t, _mesa_unorm_to_snorm(src, 32, 32)); 1471bf215546Sopenharmony_ci } else { 1472bf215546Sopenharmony_ci SWIZZLE_CONVERT(int32_t, uint32_t, _mesa_unsigned_to_signed(src, 32)); 1473bf215546Sopenharmony_ci } 1474bf215546Sopenharmony_ci break; 1475bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_INT: 1476bf215546Sopenharmony_ci SWIZZLE_CONVERT(int32_t, int32_t, src); 1477bf215546Sopenharmony_ci break; 1478bf215546Sopenharmony_ci default: 1479bf215546Sopenharmony_ci assert(!"Invalid channel type combination"); 1480bf215546Sopenharmony_ci } 1481bf215546Sopenharmony_ci} 1482bf215546Sopenharmony_ci 1483bf215546Sopenharmony_ci 1484bf215546Sopenharmony_ci/** 1485bf215546Sopenharmony_ci * Convert between array-based color formats. 1486bf215546Sopenharmony_ci * 1487bf215546Sopenharmony_ci * Most format conversion operations required by GL can be performed by 1488bf215546Sopenharmony_ci * converting one channel at a time, shuffling the channels around, and 1489bf215546Sopenharmony_ci * optionally filling missing channels with zeros and ones. This function 1490bf215546Sopenharmony_ci * does just that in a general, yet efficient, way. 1491bf215546Sopenharmony_ci * 1492bf215546Sopenharmony_ci * The swizzle parameter is an array of 4 numbers (see 1493bf215546Sopenharmony_ci * _mesa_get_format_swizzle) that describes where each channel in the 1494bf215546Sopenharmony_ci * destination should come from in the source. If swizzle[i] < 4 then it 1495bf215546Sopenharmony_ci * means that dst[i] = CONVERT(src[swizzle[i]]). If swizzle[i] is 1496bf215546Sopenharmony_ci * MESA_FORMAT_SWIZZLE_ZERO or MESA_FORMAT_SWIZZLE_ONE, the corresponding 1497bf215546Sopenharmony_ci * dst[i] will be filled with the appropreate representation of zero or one 1498bf215546Sopenharmony_ci * respectively. 1499bf215546Sopenharmony_ci * 1500bf215546Sopenharmony_ci * Under most circumstances, the source and destination images must be 1501bf215546Sopenharmony_ci * different as no care is taken not to clobber one with the other. 1502bf215546Sopenharmony_ci * However, if they have the same number of bits per pixel, it is safe to 1503bf215546Sopenharmony_ci * do an in-place conversion. 1504bf215546Sopenharmony_ci * 1505bf215546Sopenharmony_ci * \param[out] dst pointer to where the converted data should 1506bf215546Sopenharmony_ci * be stored 1507bf215546Sopenharmony_ci * 1508bf215546Sopenharmony_ci * \param[in] dst_type the destination GL type of the converted 1509bf215546Sopenharmony_ci * data (GL_BYTE, etc.) 1510bf215546Sopenharmony_ci * 1511bf215546Sopenharmony_ci * \param[in] num_dst_channels the number of channels in the converted 1512bf215546Sopenharmony_ci * data 1513bf215546Sopenharmony_ci * 1514bf215546Sopenharmony_ci * \param[in] src pointer to the source data 1515bf215546Sopenharmony_ci * 1516bf215546Sopenharmony_ci * \param[in] src_type the GL type of the source data (GL_BYTE, 1517bf215546Sopenharmony_ci * etc.) 1518bf215546Sopenharmony_ci * 1519bf215546Sopenharmony_ci * \param[in] num_src_channels the number of channels in the source data 1520bf215546Sopenharmony_ci * (the number of channels total, not just 1521bf215546Sopenharmony_ci * the number used) 1522bf215546Sopenharmony_ci * 1523bf215546Sopenharmony_ci * \param[in] swizzle describes how to get the destination data 1524bf215546Sopenharmony_ci * from the source data. 1525bf215546Sopenharmony_ci * 1526bf215546Sopenharmony_ci * \param[in] normalized for integer types, this indicates whether 1527bf215546Sopenharmony_ci * the data should be considered as integers 1528bf215546Sopenharmony_ci * or as normalized integers; 1529bf215546Sopenharmony_ci * 1530bf215546Sopenharmony_ci * \param[in] count the number of pixels to convert 1531bf215546Sopenharmony_ci */ 1532bf215546Sopenharmony_civoid 1533bf215546Sopenharmony_ci_mesa_swizzle_and_convert(void *void_dst, enum mesa_array_format_datatype dst_type, int num_dst_channels, 1534bf215546Sopenharmony_ci const void *void_src, enum mesa_array_format_datatype src_type, int num_src_channels, 1535bf215546Sopenharmony_ci const uint8_t swizzle[4], bool normalized, int count) 1536bf215546Sopenharmony_ci{ 1537bf215546Sopenharmony_ci if (swizzle_convert_try_memcpy(void_dst, dst_type, num_dst_channels, 1538bf215546Sopenharmony_ci void_src, src_type, num_src_channels, 1539bf215546Sopenharmony_ci swizzle, normalized, count)) 1540bf215546Sopenharmony_ci return; 1541bf215546Sopenharmony_ci 1542bf215546Sopenharmony_ci switch (dst_type) { 1543bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_FLOAT: 1544bf215546Sopenharmony_ci convert_float(void_dst, num_dst_channels, void_src, src_type, 1545bf215546Sopenharmony_ci num_src_channels, swizzle, normalized, count); 1546bf215546Sopenharmony_ci break; 1547bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_HALF: 1548bf215546Sopenharmony_ci convert_half_float(void_dst, num_dst_channels, void_src, src_type, 1549bf215546Sopenharmony_ci num_src_channels, swizzle, normalized, count); 1550bf215546Sopenharmony_ci break; 1551bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_UBYTE: 1552bf215546Sopenharmony_ci convert_ubyte(void_dst, num_dst_channels, void_src, src_type, 1553bf215546Sopenharmony_ci num_src_channels, swizzle, normalized, count); 1554bf215546Sopenharmony_ci break; 1555bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_BYTE: 1556bf215546Sopenharmony_ci convert_byte(void_dst, num_dst_channels, void_src, src_type, 1557bf215546Sopenharmony_ci num_src_channels, swizzle, normalized, count); 1558bf215546Sopenharmony_ci break; 1559bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_USHORT: 1560bf215546Sopenharmony_ci convert_ushort(void_dst, num_dst_channels, void_src, src_type, 1561bf215546Sopenharmony_ci num_src_channels, swizzle, normalized, count); 1562bf215546Sopenharmony_ci break; 1563bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_SHORT: 1564bf215546Sopenharmony_ci convert_short(void_dst, num_dst_channels, void_src, src_type, 1565bf215546Sopenharmony_ci num_src_channels, swizzle, normalized, count); 1566bf215546Sopenharmony_ci break; 1567bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_UINT: 1568bf215546Sopenharmony_ci convert_uint(void_dst, num_dst_channels, void_src, src_type, 1569bf215546Sopenharmony_ci num_src_channels, swizzle, normalized, count); 1570bf215546Sopenharmony_ci break; 1571bf215546Sopenharmony_ci case MESA_ARRAY_FORMAT_TYPE_INT: 1572bf215546Sopenharmony_ci convert_int(void_dst, num_dst_channels, void_src, src_type, 1573bf215546Sopenharmony_ci num_src_channels, swizzle, normalized, count); 1574bf215546Sopenharmony_ci break; 1575bf215546Sopenharmony_ci default: 1576bf215546Sopenharmony_ci assert(!"Invalid channel type"); 1577bf215546Sopenharmony_ci } 1578bf215546Sopenharmony_ci} 1579