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