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