14a49301eSmrg/**************************************************************************
201e04c3fSmrg *
3af69d88dSmrg * Copyright 2007 VMware, Inc.
44a49301eSmrg * All Rights Reserved.
501e04c3fSmrg *
64a49301eSmrg * Permission is hereby granted, free of charge, to any person obtaining a
74a49301eSmrg * copy of this software and associated documentation files (the
84a49301eSmrg * "Software"), to deal in the Software without restriction, including
94a49301eSmrg * without limitation the rights to use, copy, modify, merge, publish,
104a49301eSmrg * distribute, sub license, and/or sell copies of the Software, and to
114a49301eSmrg * permit persons to whom the Software is furnished to do so, subject to
124a49301eSmrg * the following conditions:
1301e04c3fSmrg *
144a49301eSmrg * The above copyright notice and this permission notice (including the
154a49301eSmrg * next paragraph) shall be included in all copies or substantial portions
164a49301eSmrg * of the Software.
1701e04c3fSmrg *
184a49301eSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
194a49301eSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
204a49301eSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21af69d88dSmrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
224a49301eSmrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
234a49301eSmrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
244a49301eSmrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2501e04c3fSmrg *
264a49301eSmrg **************************************************************************/
274a49301eSmrg
284a49301eSmrg /*
294a49301eSmrg  * Authors:
30af69d88dSmrg  *   Keith Whitwell <keithw@vmware.com>
314a49301eSmrg  */
324a49301eSmrg
334a49301eSmrg#include "util/u_memory.h"
347ec681f3Smrg#include "util/format/u_format.h"
357ec681f3Smrg#include "util/half_float.h"
363464ebd5Sriastradh#include "util/u_math.h"
374a49301eSmrg#include "pipe/p_state.h"
384a49301eSmrg#include "translate.h"
394a49301eSmrg
404a49301eSmrg
414a49301eSmrg#define DRAW_DBG 0
424a49301eSmrg
43af69d88dSmrgtypedef void (*emit_func)(const void *attrib, void *ptr);
444a49301eSmrg
454a49301eSmrg
464a49301eSmrg
474a49301eSmrgstruct translate_generic {
484a49301eSmrg   struct translate translate;
494a49301eSmrg
504a49301eSmrg   struct {
51cdc920a0Smrg      enum translate_element_type type;
52cdc920a0Smrg
537ec681f3Smrg      void (*fetch)(void *restrict dst, const uint8_t *restrict src,
547ec681f3Smrg                    unsigned width);
554a49301eSmrg      unsigned buffer;
564a49301eSmrg      unsigned input_offset;
57cdc920a0Smrg      unsigned instance_divisor;
584a49301eSmrg
594a49301eSmrg      emit_func emit;
604a49301eSmrg      unsigned output_offset;
6101e04c3fSmrg
623464ebd5Sriastradh      const uint8_t *input_ptr;
634a49301eSmrg      unsigned input_stride;
643464ebd5Sriastradh      unsigned max_index;
653464ebd5Sriastradh
6601e04c3fSmrg      /* this value is set to -1 if this is a normal element with
6701e04c3fSmrg       * output_format != input_format: in this case, u_format is used
6801e04c3fSmrg       * to do a full conversion
693464ebd5Sriastradh       *
7001e04c3fSmrg       * this value is set to the format size in bytes if
7101e04c3fSmrg       * output_format == input_format or for 32-bit instance ids:
723464ebd5Sriastradh       * in this case, memcpy is used to copy this amount of bytes
733464ebd5Sriastradh       */
743464ebd5Sriastradh      int copy_size;
754a49301eSmrg
76af69d88dSmrg   } attrib[TRANSLATE_MAX_ATTRIBS];
774a49301eSmrg
784a49301eSmrg   unsigned nr_attrib;
794a49301eSmrg};
804a49301eSmrg
814a49301eSmrg
8201e04c3fSmrgstatic struct translate_generic *
8301e04c3fSmrgtranslate_generic(struct translate *translate)
844a49301eSmrg{
854a49301eSmrg   return (struct translate_generic *)translate;
864a49301eSmrg}
874a49301eSmrg
8801e04c3fSmrg
894a49301eSmrg/**
90af69d88dSmrg * Fetch a dword[4] vertex attribute from memory, doing format/type
914a49301eSmrg * conversion as needed.
924a49301eSmrg *
934a49301eSmrg * This is probably needed/dupliocated elsewhere, eg format
944a49301eSmrg * conversion, texture sampling etc.
954a49301eSmrg */
9601e04c3fSmrg#define ATTRIB(NAME, SZ, SRCTYPE, DSTTYPE, TO)  	\
974a49301eSmrgstatic void						\
98af69d88dSmrgemit_##NAME(const void *attrib, void *ptr)		\
994a49301eSmrg{  \
1004a49301eSmrg   unsigned i;						\
101af69d88dSmrg   SRCTYPE *in = (SRCTYPE *)attrib;                     \
102af69d88dSmrg   DSTTYPE *out = (DSTTYPE *)ptr;			\
1034a49301eSmrg							\
1044a49301eSmrg   for (i = 0; i < SZ; i++) {				\
105af69d88dSmrg      out[i] = TO(in[i]);				\
1064a49301eSmrg   }							\
1074a49301eSmrg}
1084a49301eSmrg
1094a49301eSmrg
1104a49301eSmrg#define TO_64_FLOAT(x)   ((double) x)
1114a49301eSmrg#define TO_32_FLOAT(x)   (x)
1127ec681f3Smrg#define TO_16_FLOAT(x)   _mesa_float_to_half(x)
1134a49301eSmrg
1144a49301eSmrg#define TO_8_USCALED(x)  ((unsigned char) x)
1154a49301eSmrg#define TO_16_USCALED(x) ((unsigned short) x)
1164a49301eSmrg#define TO_32_USCALED(x) ((unsigned int) x)
1174a49301eSmrg
1184a49301eSmrg#define TO_8_SSCALED(x)  ((char) x)
1194a49301eSmrg#define TO_16_SSCALED(x) ((short) x)
1204a49301eSmrg#define TO_32_SSCALED(x) ((int) x)
1214a49301eSmrg
1224a49301eSmrg#define TO_8_UNORM(x)    ((unsigned char) (x * 255.0f))
1234a49301eSmrg#define TO_16_UNORM(x)   ((unsigned short) (x * 65535.0f))
1244a49301eSmrg#define TO_32_UNORM(x)   ((unsigned int) (x * 4294967295.0f))
1254a49301eSmrg
1264a49301eSmrg#define TO_8_SNORM(x)    ((char) (x * 127.0f))
1274a49301eSmrg#define TO_16_SNORM(x)   ((short) (x * 32767.0f))
1284a49301eSmrg#define TO_32_SNORM(x)   ((int) (x * 2147483647.0f))
1294a49301eSmrg
1304a49301eSmrg#define TO_32_FIXED(x)   ((int) (x * 65536.0f))
1314a49301eSmrg
132af69d88dSmrg#define TO_INT(x)        (x)
133af69d88dSmrg
134af69d88dSmrg
13501e04c3fSmrgATTRIB(R64G64B64A64_FLOAT,   4, float, double, TO_64_FLOAT)
13601e04c3fSmrgATTRIB(R64G64B64_FLOAT,      3, float, double, TO_64_FLOAT)
13701e04c3fSmrgATTRIB(R64G64_FLOAT,         2, float, double, TO_64_FLOAT)
13801e04c3fSmrgATTRIB(R64_FLOAT,            1, float, double, TO_64_FLOAT)
13901e04c3fSmrg
14001e04c3fSmrgATTRIB(R32G32B32A32_FLOAT,   4, float, float, TO_32_FLOAT)
14101e04c3fSmrgATTRIB(R32G32B32_FLOAT,      3, float, float, TO_32_FLOAT)
14201e04c3fSmrgATTRIB(R32G32_FLOAT,         2, float, float, TO_32_FLOAT)
14301e04c3fSmrgATTRIB(R32_FLOAT,            1, float, float, TO_32_FLOAT)
14401e04c3fSmrg
14501e04c3fSmrgATTRIB(R16G16B16A16_FLOAT,   4, float, ushort, TO_16_FLOAT)
14601e04c3fSmrgATTRIB(R16G16B16_FLOAT,      3, float, ushort, TO_16_FLOAT)
14701e04c3fSmrgATTRIB(R16G16_FLOAT,         2, float, ushort, TO_16_FLOAT)
14801e04c3fSmrgATTRIB(R16_FLOAT,            1, float, ushort, TO_16_FLOAT)
14901e04c3fSmrg
15001e04c3fSmrgATTRIB(R32G32B32A32_USCALED, 4, float, unsigned, TO_32_USCALED)
15101e04c3fSmrgATTRIB(R32G32B32_USCALED,    3, float, unsigned, TO_32_USCALED)
15201e04c3fSmrgATTRIB(R32G32_USCALED,       2, float, unsigned, TO_32_USCALED)
15301e04c3fSmrgATTRIB(R32_USCALED,          1, float, unsigned, TO_32_USCALED)
15401e04c3fSmrg
15501e04c3fSmrgATTRIB(R32G32B32A32_SSCALED, 4, float, int, TO_32_SSCALED)
15601e04c3fSmrgATTRIB(R32G32B32_SSCALED,    3, float, int, TO_32_SSCALED)
15701e04c3fSmrgATTRIB(R32G32_SSCALED,       2, float, int, TO_32_SSCALED)
15801e04c3fSmrgATTRIB(R32_SSCALED,          1, float, int, TO_32_SSCALED)
15901e04c3fSmrg
16001e04c3fSmrgATTRIB(R32G32B32A32_UNORM, 4, float, unsigned, TO_32_UNORM)
16101e04c3fSmrgATTRIB(R32G32B32_UNORM,    3, float, unsigned, TO_32_UNORM)
16201e04c3fSmrgATTRIB(R32G32_UNORM,       2, float, unsigned, TO_32_UNORM)
16301e04c3fSmrgATTRIB(R32_UNORM,          1, float, unsigned, TO_32_UNORM)
16401e04c3fSmrg
16501e04c3fSmrgATTRIB(R32G32B32A32_SNORM, 4, float, int, TO_32_SNORM)
16601e04c3fSmrgATTRIB(R32G32B32_SNORM,    3, float, int, TO_32_SNORM)
16701e04c3fSmrgATTRIB(R32G32_SNORM,       2, float, int, TO_32_SNORM)
16801e04c3fSmrgATTRIB(R32_SNORM,          1, float, int, TO_32_SNORM)
16901e04c3fSmrg
17001e04c3fSmrgATTRIB(R16G16B16A16_USCALED, 4, float, ushort, TO_16_USCALED)
17101e04c3fSmrgATTRIB(R16G16B16_USCALED,    3, float, ushort, TO_16_USCALED)
17201e04c3fSmrgATTRIB(R16G16_USCALED,       2, float, ushort, TO_16_USCALED)
17301e04c3fSmrgATTRIB(R16_USCALED,          1, float, ushort, TO_16_USCALED)
17401e04c3fSmrg
17501e04c3fSmrgATTRIB(R16G16B16A16_SSCALED, 4, float, short, TO_16_SSCALED)
17601e04c3fSmrgATTRIB(R16G16B16_SSCALED,    3, float, short, TO_16_SSCALED)
17701e04c3fSmrgATTRIB(R16G16_SSCALED,       2, float, short, TO_16_SSCALED)
17801e04c3fSmrgATTRIB(R16_SSCALED,          1, float, short, TO_16_SSCALED)
17901e04c3fSmrg
18001e04c3fSmrgATTRIB(R16G16B16A16_UNORM, 4, float, ushort, TO_16_UNORM)
18101e04c3fSmrgATTRIB(R16G16B16_UNORM,    3, float, ushort, TO_16_UNORM)
18201e04c3fSmrgATTRIB(R16G16_UNORM,       2, float, ushort, TO_16_UNORM)
18301e04c3fSmrgATTRIB(R16_UNORM,          1, float, ushort, TO_16_UNORM)
18401e04c3fSmrg
18501e04c3fSmrgATTRIB(R16G16B16A16_SNORM, 4, float, short, TO_16_SNORM)
18601e04c3fSmrgATTRIB(R16G16B16_SNORM,    3, float, short, TO_16_SNORM)
18701e04c3fSmrgATTRIB(R16G16_SNORM,       2, float, short, TO_16_SNORM)
18801e04c3fSmrgATTRIB(R16_SNORM,          1, float, short, TO_16_SNORM)
18901e04c3fSmrg
19001e04c3fSmrgATTRIB(R8G8B8A8_USCALED,   4, float, ubyte, TO_8_USCALED)
19101e04c3fSmrgATTRIB(R8G8B8_USCALED,     3, float, ubyte, TO_8_USCALED)
19201e04c3fSmrgATTRIB(R8G8_USCALED,       2, float, ubyte, TO_8_USCALED)
19301e04c3fSmrgATTRIB(R8_USCALED,         1, float, ubyte, TO_8_USCALED)
19401e04c3fSmrg
19501e04c3fSmrgATTRIB(R8G8B8A8_SSCALED,  4, float, char, TO_8_SSCALED)
19601e04c3fSmrgATTRIB(R8G8B8_SSCALED,    3, float, char, TO_8_SSCALED)
19701e04c3fSmrgATTRIB(R8G8_SSCALED,      2, float, char, TO_8_SSCALED)
19801e04c3fSmrgATTRIB(R8_SSCALED,        1, float, char, TO_8_SSCALED)
19901e04c3fSmrg
20001e04c3fSmrgATTRIB(R8G8B8A8_UNORM,  4, float, ubyte, TO_8_UNORM)
20101e04c3fSmrgATTRIB(R8G8B8_UNORM,    3, float, ubyte, TO_8_UNORM)
20201e04c3fSmrgATTRIB(R8G8_UNORM,      2, float, ubyte, TO_8_UNORM)
20301e04c3fSmrgATTRIB(R8_UNORM,        1, float, ubyte, TO_8_UNORM)
20401e04c3fSmrg
20501e04c3fSmrgATTRIB(R8G8B8A8_SNORM,  4, float, char, TO_8_SNORM)
20601e04c3fSmrgATTRIB(R8G8B8_SNORM,    3, float, char, TO_8_SNORM)
20701e04c3fSmrgATTRIB(R8G8_SNORM,      2, float, char, TO_8_SNORM)
20801e04c3fSmrgATTRIB(R8_SNORM,        1, float, char, TO_8_SNORM)
20901e04c3fSmrg
21001e04c3fSmrgATTRIB(R32G32B32A32_UINT, 4, uint32_t, unsigned, TO_INT)
21101e04c3fSmrgATTRIB(R32G32B32_UINT,    3, uint32_t, unsigned, TO_INT)
21201e04c3fSmrgATTRIB(R32G32_UINT,       2, uint32_t, unsigned, TO_INT)
21301e04c3fSmrgATTRIB(R32_UINT,          1, uint32_t, unsigned, TO_INT)
21401e04c3fSmrg
21501e04c3fSmrgATTRIB(R16G16B16A16_UINT, 4, uint32_t, ushort, TO_INT)
21601e04c3fSmrgATTRIB(R16G16B16_UINT,    3, uint32_t, ushort, TO_INT)
21701e04c3fSmrgATTRIB(R16G16_UINT,       2, uint32_t, ushort, TO_INT)
21801e04c3fSmrgATTRIB(R16_UINT,          1, uint32_t, ushort, TO_INT)
21901e04c3fSmrg
22001e04c3fSmrgATTRIB(R8G8B8A8_UINT,   4, uint32_t, ubyte, TO_INT)
22101e04c3fSmrgATTRIB(R8G8B8_UINT,     3, uint32_t, ubyte, TO_INT)
22201e04c3fSmrgATTRIB(R8G8_UINT,       2, uint32_t, ubyte, TO_INT)
22301e04c3fSmrgATTRIB(R8_UINT,         1, uint32_t, ubyte, TO_INT)
22401e04c3fSmrg
22501e04c3fSmrgATTRIB(R32G32B32A32_SINT, 4, int32_t, int, TO_INT)
22601e04c3fSmrgATTRIB(R32G32B32_SINT,    3, int32_t, int, TO_INT)
22701e04c3fSmrgATTRIB(R32G32_SINT,       2, int32_t, int, TO_INT)
22801e04c3fSmrgATTRIB(R32_SINT,          1, int32_t, int, TO_INT)
22901e04c3fSmrg
23001e04c3fSmrgATTRIB(R16G16B16A16_SINT, 4, int32_t, short, TO_INT)
23101e04c3fSmrgATTRIB(R16G16B16_SINT,    3, int32_t, short, TO_INT)
23201e04c3fSmrgATTRIB(R16G16_SINT,       2, int32_t, short, TO_INT)
23301e04c3fSmrgATTRIB(R16_SINT,          1, int32_t, short, TO_INT)
23401e04c3fSmrg
23501e04c3fSmrgATTRIB(R8G8B8A8_SINT,   4, int32_t, char, TO_INT)
23601e04c3fSmrgATTRIB(R8G8B8_SINT,     3, int32_t, char, TO_INT)
23701e04c3fSmrgATTRIB(R8G8_SINT,       2, int32_t, char, TO_INT)
23801e04c3fSmrgATTRIB(R8_SINT,         1, int32_t, char, TO_INT)
2394a49301eSmrg
2404a49301eSmrgstatic void
24101e04c3fSmrgemit_A8R8G8B8_UNORM(const void *attrib, void *ptr)
2424a49301eSmrg{
243af69d88dSmrg   float *in = (float *)attrib;
2443464ebd5Sriastradh   ubyte *out = (ubyte *)ptr;
245af69d88dSmrg   out[0] = TO_8_UNORM(in[3]);
246af69d88dSmrg   out[1] = TO_8_UNORM(in[0]);
247af69d88dSmrg   out[2] = TO_8_UNORM(in[1]);
248af69d88dSmrg   out[3] = TO_8_UNORM(in[2]);
2494a49301eSmrg}
2504a49301eSmrg
2514a49301eSmrgstatic void
25201e04c3fSmrgemit_B8G8R8A8_UNORM(const void *attrib, void *ptr)
2534a49301eSmrg{
254af69d88dSmrg   float *in = (float *)attrib;
2554a49301eSmrg   ubyte *out = (ubyte *)ptr;
256af69d88dSmrg   out[2] = TO_8_UNORM(in[0]);
257af69d88dSmrg   out[1] = TO_8_UNORM(in[1]);
258af69d88dSmrg   out[0] = TO_8_UNORM(in[2]);
259af69d88dSmrg   out[3] = TO_8_UNORM(in[3]);
260af69d88dSmrg}
261af69d88dSmrg
262af69d88dSmrgstatic void
26301e04c3fSmrgemit_B10G10R10A2_UNORM(const void *attrib, void *ptr)
264af69d88dSmrg{
265af69d88dSmrg   float *src = (float *)ptr;
266af69d88dSmrg   uint32_t value = 0;
267af69d88dSmrg   value |= ((uint32_t)(CLAMP(src[2], 0, 1) * 0x3ff)) & 0x3ff;
268af69d88dSmrg   value |= (((uint32_t)(CLAMP(src[1], 0, 1) * 0x3ff)) & 0x3ff) << 10;
269af69d88dSmrg   value |= (((uint32_t)(CLAMP(src[0], 0, 1) * 0x3ff)) & 0x3ff) << 20;
270af69d88dSmrg   value |= ((uint32_t)(CLAMP(src[3], 0, 1) * 0x3)) << 30;
27101e04c3fSmrg   *(uint32_t *)attrib = util_le32_to_cpu(value);
272af69d88dSmrg}
273af69d88dSmrg
274af69d88dSmrgstatic void
27501e04c3fSmrgemit_B10G10R10A2_USCALED(const void *attrib, void *ptr)
276af69d88dSmrg{
277af69d88dSmrg   float *src = (float *)ptr;
278af69d88dSmrg   uint32_t value = 0;
279af69d88dSmrg   value |= ((uint32_t)CLAMP(src[2], 0, 1023)) & 0x3ff;
280af69d88dSmrg   value |= (((uint32_t)CLAMP(src[1], 0, 1023)) & 0x3ff) << 10;
281af69d88dSmrg   value |= (((uint32_t)CLAMP(src[0], 0, 1023)) & 0x3ff) << 20;
282af69d88dSmrg   value |= ((uint32_t)CLAMP(src[3], 0, 3)) << 30;
28301e04c3fSmrg   *(uint32_t *)attrib = util_le32_to_cpu(value);
284af69d88dSmrg}
285af69d88dSmrg
286af69d88dSmrgstatic void
28701e04c3fSmrgemit_B10G10R10A2_SNORM(const void *attrib, void *ptr)
288af69d88dSmrg{
289af69d88dSmrg   float *src = (float *)ptr;
290af69d88dSmrg   uint32_t value = 0;
291af69d88dSmrg   value |= (uint32_t)(((uint32_t)(CLAMP(src[2], -1, 1) * 0x1ff)) & 0x3ff) ;
292af69d88dSmrg   value |= (uint32_t)((((uint32_t)(CLAMP(src[1], -1, 1) * 0x1ff)) & 0x3ff) << 10) ;
293af69d88dSmrg   value |= (uint32_t)((((uint32_t)(CLAMP(src[0], -1, 1) * 0x1ff)) & 0x3ff) << 20) ;
294af69d88dSmrg   value |= (uint32_t)(((uint32_t)(CLAMP(src[3], -1, 1) * 0x1)) << 30) ;
29501e04c3fSmrg   *(uint32_t *)attrib = util_le32_to_cpu(value);
296af69d88dSmrg}
297af69d88dSmrg
298af69d88dSmrgstatic void
29901e04c3fSmrgemit_B10G10R10A2_SSCALED(const void *attrib, void *ptr)
300af69d88dSmrg{
301af69d88dSmrg   float *src = (float *)ptr;
302af69d88dSmrg   uint32_t value = 0;
303af69d88dSmrg   value |= (uint32_t)(((uint32_t)CLAMP(src[2], -512, 511)) & 0x3ff) ;
304af69d88dSmrg   value |= (uint32_t)((((uint32_t)CLAMP(src[1], -512, 511)) & 0x3ff) << 10) ;
305af69d88dSmrg   value |= (uint32_t)((((uint32_t)CLAMP(src[0], -512, 511)) & 0x3ff) << 20) ;
306af69d88dSmrg   value |= (uint32_t)(((uint32_t)CLAMP(src[3], -2, 1)) << 30) ;
30701e04c3fSmrg   *(uint32_t *)attrib = util_le32_to_cpu(value);
308af69d88dSmrg}
309af69d88dSmrg
310af69d88dSmrgstatic void
31101e04c3fSmrgemit_R10G10B10A2_UNORM(const void *attrib, void *ptr)
312af69d88dSmrg{
313af69d88dSmrg   float *src = (float *)ptr;
314af69d88dSmrg   uint32_t value = 0;
315af69d88dSmrg   value |= ((uint32_t)(CLAMP(src[0], 0, 1) * 0x3ff)) & 0x3ff;
316af69d88dSmrg   value |= (((uint32_t)(CLAMP(src[1], 0, 1) * 0x3ff)) & 0x3ff) << 10;
317af69d88dSmrg   value |= (((uint32_t)(CLAMP(src[2], 0, 1) * 0x3ff)) & 0x3ff) << 20;
318af69d88dSmrg   value |= ((uint32_t)(CLAMP(src[3], 0, 1) * 0x3)) << 30;
31901e04c3fSmrg   *(uint32_t *)attrib = util_le32_to_cpu(value);
320af69d88dSmrg}
321af69d88dSmrg
322af69d88dSmrgstatic void
32301e04c3fSmrgemit_R10G10B10A2_USCALED(const void *attrib, void *ptr)
324af69d88dSmrg{
325af69d88dSmrg   float *src = (float *)ptr;
326af69d88dSmrg   uint32_t value = 0;
327af69d88dSmrg   value |= ((uint32_t)CLAMP(src[0], 0, 1023)) & 0x3ff;
328af69d88dSmrg   value |= (((uint32_t)CLAMP(src[1], 0, 1023)) & 0x3ff) << 10;
329af69d88dSmrg   value |= (((uint32_t)CLAMP(src[2], 0, 1023)) & 0x3ff) << 20;
330af69d88dSmrg   value |= ((uint32_t)CLAMP(src[3], 0, 3)) << 30;
33101e04c3fSmrg   *(uint32_t *)attrib = util_le32_to_cpu(value);
332af69d88dSmrg}
333af69d88dSmrg
334af69d88dSmrgstatic void
33501e04c3fSmrgemit_R10G10B10A2_SNORM(const void *attrib, void *ptr)
336af69d88dSmrg{
337af69d88dSmrg   float *src = (float *)ptr;
338af69d88dSmrg   uint32_t value = 0;
339af69d88dSmrg   value |= (uint32_t)(((uint32_t)(CLAMP(src[0], -1, 1) * 0x1ff)) & 0x3ff) ;
340af69d88dSmrg   value |= (uint32_t)((((uint32_t)(CLAMP(src[1], -1, 1) * 0x1ff)) & 0x3ff) << 10) ;
341af69d88dSmrg   value |= (uint32_t)((((uint32_t)(CLAMP(src[2], -1, 1) * 0x1ff)) & 0x3ff) << 20) ;
342af69d88dSmrg   value |= (uint32_t)(((uint32_t)(CLAMP(src[3], -1, 1) * 0x1)) << 30) ;
34301e04c3fSmrg   *(uint32_t *)attrib = util_le32_to_cpu(value);
344af69d88dSmrg}
345af69d88dSmrg
346af69d88dSmrgstatic void
34701e04c3fSmrgemit_R10G10B10A2_SSCALED(const void *attrib, void *ptr)
348af69d88dSmrg{
349af69d88dSmrg   float *src = (float *)ptr;
350af69d88dSmrg   uint32_t value = 0;
351af69d88dSmrg   value |= (uint32_t)(((uint32_t)CLAMP(src[0], -512, 511)) & 0x3ff) ;
352af69d88dSmrg   value |= (uint32_t)((((uint32_t)CLAMP(src[1], -512, 511)) & 0x3ff) << 10) ;
353af69d88dSmrg   value |= (uint32_t)((((uint32_t)CLAMP(src[2], -512, 511)) & 0x3ff) << 20) ;
354af69d88dSmrg   value |= (uint32_t)(((uint32_t)CLAMP(src[3], -2, 1)) << 30) ;
35501e04c3fSmrg   *(uint32_t *)attrib = util_le32_to_cpu(value);
3564a49301eSmrg}
3574a49301eSmrg
35801e04c3fSmrgstatic void
35901e04c3fSmrgemit_NULL(const void *attrib, void *ptr)
3604a49301eSmrg{
3614a49301eSmrg   /* do nothing is the only sensible option */
3624a49301eSmrg}
3634a49301eSmrg
36401e04c3fSmrgstatic emit_func
36501e04c3fSmrgget_emit_func(enum pipe_format format)
3664a49301eSmrg{
3674a49301eSmrg   switch (format) {
3684a49301eSmrg   case PIPE_FORMAT_R64_FLOAT:
3694a49301eSmrg      return &emit_R64_FLOAT;
3704a49301eSmrg   case PIPE_FORMAT_R64G64_FLOAT:
3714a49301eSmrg      return &emit_R64G64_FLOAT;
3724a49301eSmrg   case PIPE_FORMAT_R64G64B64_FLOAT:
3734a49301eSmrg      return &emit_R64G64B64_FLOAT;
3744a49301eSmrg   case PIPE_FORMAT_R64G64B64A64_FLOAT:
3754a49301eSmrg      return &emit_R64G64B64A64_FLOAT;
3764a49301eSmrg
3774a49301eSmrg   case PIPE_FORMAT_R32_FLOAT:
3784a49301eSmrg      return &emit_R32_FLOAT;
3794a49301eSmrg   case PIPE_FORMAT_R32G32_FLOAT:
3804a49301eSmrg      return &emit_R32G32_FLOAT;
3814a49301eSmrg   case PIPE_FORMAT_R32G32B32_FLOAT:
3824a49301eSmrg      return &emit_R32G32B32_FLOAT;
3834a49301eSmrg   case PIPE_FORMAT_R32G32B32A32_FLOAT:
3844a49301eSmrg      return &emit_R32G32B32A32_FLOAT;
3854a49301eSmrg
386af69d88dSmrg   case PIPE_FORMAT_R16_FLOAT:
387af69d88dSmrg      return &emit_R16_FLOAT;
388af69d88dSmrg   case PIPE_FORMAT_R16G16_FLOAT:
389af69d88dSmrg      return &emit_R16G16_FLOAT;
390af69d88dSmrg   case PIPE_FORMAT_R16G16B16_FLOAT:
391af69d88dSmrg      return &emit_R16G16B16_FLOAT;
392af69d88dSmrg   case PIPE_FORMAT_R16G16B16A16_FLOAT:
393af69d88dSmrg      return &emit_R16G16B16A16_FLOAT;
394af69d88dSmrg
3954a49301eSmrg   case PIPE_FORMAT_R32_UNORM:
3964a49301eSmrg      return &emit_R32_UNORM;
3974a49301eSmrg   case PIPE_FORMAT_R32G32_UNORM:
3984a49301eSmrg      return &emit_R32G32_UNORM;
3994a49301eSmrg   case PIPE_FORMAT_R32G32B32_UNORM:
4004a49301eSmrg      return &emit_R32G32B32_UNORM;
4014a49301eSmrg   case PIPE_FORMAT_R32G32B32A32_UNORM:
4024a49301eSmrg      return &emit_R32G32B32A32_UNORM;
4034a49301eSmrg
4044a49301eSmrg   case PIPE_FORMAT_R32_USCALED:
4054a49301eSmrg      return &emit_R32_USCALED;
4064a49301eSmrg   case PIPE_FORMAT_R32G32_USCALED:
4074a49301eSmrg      return &emit_R32G32_USCALED;
4084a49301eSmrg   case PIPE_FORMAT_R32G32B32_USCALED:
4094a49301eSmrg      return &emit_R32G32B32_USCALED;
4104a49301eSmrg   case PIPE_FORMAT_R32G32B32A32_USCALED:
4114a49301eSmrg      return &emit_R32G32B32A32_USCALED;
4124a49301eSmrg
4134a49301eSmrg   case PIPE_FORMAT_R32_SNORM:
4144a49301eSmrg      return &emit_R32_SNORM;
4154a49301eSmrg   case PIPE_FORMAT_R32G32_SNORM:
4164a49301eSmrg      return &emit_R32G32_SNORM;
4174a49301eSmrg   case PIPE_FORMAT_R32G32B32_SNORM:
4184a49301eSmrg      return &emit_R32G32B32_SNORM;
4194a49301eSmrg   case PIPE_FORMAT_R32G32B32A32_SNORM:
4204a49301eSmrg      return &emit_R32G32B32A32_SNORM;
4214a49301eSmrg
4224a49301eSmrg   case PIPE_FORMAT_R32_SSCALED:
4234a49301eSmrg      return &emit_R32_SSCALED;
4244a49301eSmrg   case PIPE_FORMAT_R32G32_SSCALED:
4254a49301eSmrg      return &emit_R32G32_SSCALED;
4264a49301eSmrg   case PIPE_FORMAT_R32G32B32_SSCALED:
4274a49301eSmrg      return &emit_R32G32B32_SSCALED;
4284a49301eSmrg   case PIPE_FORMAT_R32G32B32A32_SSCALED:
4294a49301eSmrg      return &emit_R32G32B32A32_SSCALED;
4304a49301eSmrg
4314a49301eSmrg   case PIPE_FORMAT_R16_UNORM:
4324a49301eSmrg      return &emit_R16_UNORM;
4334a49301eSmrg   case PIPE_FORMAT_R16G16_UNORM:
4344a49301eSmrg      return &emit_R16G16_UNORM;
4354a49301eSmrg   case PIPE_FORMAT_R16G16B16_UNORM:
4364a49301eSmrg      return &emit_R16G16B16_UNORM;
4374a49301eSmrg   case PIPE_FORMAT_R16G16B16A16_UNORM:
4384a49301eSmrg      return &emit_R16G16B16A16_UNORM;
4394a49301eSmrg
4404a49301eSmrg   case PIPE_FORMAT_R16_USCALED:
4414a49301eSmrg      return &emit_R16_USCALED;
4424a49301eSmrg   case PIPE_FORMAT_R16G16_USCALED:
4434a49301eSmrg      return &emit_R16G16_USCALED;
4444a49301eSmrg   case PIPE_FORMAT_R16G16B16_USCALED:
4454a49301eSmrg      return &emit_R16G16B16_USCALED;
4464a49301eSmrg   case PIPE_FORMAT_R16G16B16A16_USCALED:
4474a49301eSmrg      return &emit_R16G16B16A16_USCALED;
4484a49301eSmrg
4494a49301eSmrg   case PIPE_FORMAT_R16_SNORM:
4504a49301eSmrg      return &emit_R16_SNORM;
4514a49301eSmrg   case PIPE_FORMAT_R16G16_SNORM:
4524a49301eSmrg      return &emit_R16G16_SNORM;
4534a49301eSmrg   case PIPE_FORMAT_R16G16B16_SNORM:
4544a49301eSmrg      return &emit_R16G16B16_SNORM;
4554a49301eSmrg   case PIPE_FORMAT_R16G16B16A16_SNORM:
4564a49301eSmrg      return &emit_R16G16B16A16_SNORM;
4574a49301eSmrg
4584a49301eSmrg   case PIPE_FORMAT_R16_SSCALED:
4594a49301eSmrg      return &emit_R16_SSCALED;
4604a49301eSmrg   case PIPE_FORMAT_R16G16_SSCALED:
4614a49301eSmrg      return &emit_R16G16_SSCALED;
4624a49301eSmrg   case PIPE_FORMAT_R16G16B16_SSCALED:
4634a49301eSmrg      return &emit_R16G16B16_SSCALED;
4644a49301eSmrg   case PIPE_FORMAT_R16G16B16A16_SSCALED:
4654a49301eSmrg      return &emit_R16G16B16A16_SSCALED;
4664a49301eSmrg
4674a49301eSmrg   case PIPE_FORMAT_R8_UNORM:
4684a49301eSmrg      return &emit_R8_UNORM;
4694a49301eSmrg   case PIPE_FORMAT_R8G8_UNORM:
4704a49301eSmrg      return &emit_R8G8_UNORM;
4714a49301eSmrg   case PIPE_FORMAT_R8G8B8_UNORM:
4724a49301eSmrg      return &emit_R8G8B8_UNORM;
4734a49301eSmrg   case PIPE_FORMAT_R8G8B8A8_UNORM:
4744a49301eSmrg      return &emit_R8G8B8A8_UNORM;
4754a49301eSmrg
4764a49301eSmrg   case PIPE_FORMAT_R8_USCALED:
4774a49301eSmrg      return &emit_R8_USCALED;
4784a49301eSmrg   case PIPE_FORMAT_R8G8_USCALED:
4794a49301eSmrg      return &emit_R8G8_USCALED;
4804a49301eSmrg   case PIPE_FORMAT_R8G8B8_USCALED:
4814a49301eSmrg      return &emit_R8G8B8_USCALED;
4824a49301eSmrg   case PIPE_FORMAT_R8G8B8A8_USCALED:
4834a49301eSmrg      return &emit_R8G8B8A8_USCALED;
4844a49301eSmrg
4854a49301eSmrg   case PIPE_FORMAT_R8_SNORM:
4864a49301eSmrg      return &emit_R8_SNORM;
4874a49301eSmrg   case PIPE_FORMAT_R8G8_SNORM:
4884a49301eSmrg      return &emit_R8G8_SNORM;
4894a49301eSmrg   case PIPE_FORMAT_R8G8B8_SNORM:
4904a49301eSmrg      return &emit_R8G8B8_SNORM;
4914a49301eSmrg   case PIPE_FORMAT_R8G8B8A8_SNORM:
4924a49301eSmrg      return &emit_R8G8B8A8_SNORM;
4934a49301eSmrg
4944a49301eSmrg   case PIPE_FORMAT_R8_SSCALED:
4954a49301eSmrg      return &emit_R8_SSCALED;
4964a49301eSmrg   case PIPE_FORMAT_R8G8_SSCALED:
4974a49301eSmrg      return &emit_R8G8_SSCALED;
4984a49301eSmrg   case PIPE_FORMAT_R8G8B8_SSCALED:
4994a49301eSmrg      return &emit_R8G8B8_SSCALED;
5004a49301eSmrg   case PIPE_FORMAT_R8G8B8A8_SSCALED:
5014a49301eSmrg      return &emit_R8G8B8A8_SSCALED;
5024a49301eSmrg
503cdc920a0Smrg   case PIPE_FORMAT_B8G8R8A8_UNORM:
5043464ebd5Sriastradh      return &emit_B8G8R8A8_UNORM;
5054a49301eSmrg
506cdc920a0Smrg   case PIPE_FORMAT_A8R8G8B8_UNORM:
5073464ebd5Sriastradh      return &emit_A8R8G8B8_UNORM;
5084a49301eSmrg
509af69d88dSmrg   case PIPE_FORMAT_R32_UINT:
510af69d88dSmrg      return &emit_R32_UINT;
511af69d88dSmrg   case PIPE_FORMAT_R32G32_UINT:
512af69d88dSmrg      return &emit_R32G32_UINT;
513af69d88dSmrg   case PIPE_FORMAT_R32G32B32_UINT:
514af69d88dSmrg      return &emit_R32G32B32_UINT;
515af69d88dSmrg   case PIPE_FORMAT_R32G32B32A32_UINT:
516af69d88dSmrg      return &emit_R32G32B32A32_UINT;
517af69d88dSmrg
518af69d88dSmrg   case PIPE_FORMAT_R16_UINT:
519af69d88dSmrg      return &emit_R16_UINT;
520af69d88dSmrg   case PIPE_FORMAT_R16G16_UINT:
521af69d88dSmrg      return &emit_R16G16_UINT;
522af69d88dSmrg   case PIPE_FORMAT_R16G16B16_UINT:
523af69d88dSmrg      return &emit_R16G16B16_UINT;
524af69d88dSmrg   case PIPE_FORMAT_R16G16B16A16_UINT:
525af69d88dSmrg      return &emit_R16G16B16A16_UINT;
526af69d88dSmrg
527af69d88dSmrg   case PIPE_FORMAT_R8_UINT:
528af69d88dSmrg      return &emit_R8_UINT;
529af69d88dSmrg   case PIPE_FORMAT_R8G8_UINT:
530af69d88dSmrg      return &emit_R8G8_UINT;
531af69d88dSmrg   case PIPE_FORMAT_R8G8B8_UINT:
532af69d88dSmrg      return &emit_R8G8B8_UINT;
533af69d88dSmrg   case PIPE_FORMAT_R8G8B8A8_UINT:
534af69d88dSmrg      return &emit_R8G8B8A8_UINT;
535af69d88dSmrg
536af69d88dSmrg   case PIPE_FORMAT_R32_SINT:
537af69d88dSmrg      return &emit_R32_SINT;
538af69d88dSmrg   case PIPE_FORMAT_R32G32_SINT:
539af69d88dSmrg      return &emit_R32G32_SINT;
540af69d88dSmrg   case PIPE_FORMAT_R32G32B32_SINT:
541af69d88dSmrg      return &emit_R32G32B32_SINT;
542af69d88dSmrg   case PIPE_FORMAT_R32G32B32A32_SINT:
543af69d88dSmrg      return &emit_R32G32B32A32_SINT;
544af69d88dSmrg
545af69d88dSmrg   case PIPE_FORMAT_R16_SINT:
546af69d88dSmrg      return &emit_R16_SINT;
547af69d88dSmrg   case PIPE_FORMAT_R16G16_SINT:
548af69d88dSmrg      return &emit_R16G16_SINT;
549af69d88dSmrg   case PIPE_FORMAT_R16G16B16_SINT:
550af69d88dSmrg      return &emit_R16G16B16_SINT;
551af69d88dSmrg   case PIPE_FORMAT_R16G16B16A16_SINT:
552af69d88dSmrg      return &emit_R16G16B16A16_SINT;
553af69d88dSmrg
554af69d88dSmrg   case PIPE_FORMAT_R8_SINT:
555af69d88dSmrg      return &emit_R8_SINT;
556af69d88dSmrg   case PIPE_FORMAT_R8G8_SINT:
557af69d88dSmrg      return &emit_R8G8_SINT;
558af69d88dSmrg   case PIPE_FORMAT_R8G8B8_SINT:
559af69d88dSmrg      return &emit_R8G8B8_SINT;
560af69d88dSmrg   case PIPE_FORMAT_R8G8B8A8_SINT:
561af69d88dSmrg      return &emit_R8G8B8A8_SINT;
562af69d88dSmrg
563af69d88dSmrg   case PIPE_FORMAT_B10G10R10A2_UNORM:
564af69d88dSmrg      return &emit_B10G10R10A2_UNORM;
565af69d88dSmrg   case PIPE_FORMAT_B10G10R10A2_USCALED:
566af69d88dSmrg      return &emit_B10G10R10A2_USCALED;
567af69d88dSmrg   case PIPE_FORMAT_B10G10R10A2_SNORM:
568af69d88dSmrg      return &emit_B10G10R10A2_SNORM;
569af69d88dSmrg   case PIPE_FORMAT_B10G10R10A2_SSCALED:
570af69d88dSmrg      return &emit_B10G10R10A2_SSCALED;
571af69d88dSmrg
572af69d88dSmrg   case PIPE_FORMAT_R10G10B10A2_UNORM:
573af69d88dSmrg      return &emit_R10G10B10A2_UNORM;
574af69d88dSmrg   case PIPE_FORMAT_R10G10B10A2_USCALED:
575af69d88dSmrg      return &emit_R10G10B10A2_USCALED;
576af69d88dSmrg   case PIPE_FORMAT_R10G10B10A2_SNORM:
577af69d88dSmrg      return &emit_R10G10B10A2_SNORM;
578af69d88dSmrg   case PIPE_FORMAT_R10G10B10A2_SSCALED:
579af69d88dSmrg      return &emit_R10G10B10A2_SSCALED;
580af69d88dSmrg
5814a49301eSmrg   default:
58201e04c3fSmrg      assert(0);
5834a49301eSmrg      return &emit_NULL;
5844a49301eSmrg   }
5854a49301eSmrg}
5864a49301eSmrg
58701e04c3fSmrgstatic ALWAYS_INLINE void PIPE_CDECL
58801e04c3fSmrggeneric_run_one(struct translate_generic *tg,
58901e04c3fSmrg                unsigned elt,
59001e04c3fSmrg                unsigned start_instance,
59101e04c3fSmrg                unsigned instance_id,
59201e04c3fSmrg                void *vert)
5933464ebd5Sriastradh{
5943464ebd5Sriastradh   unsigned nr_attrs = tg->nr_attrib;
5953464ebd5Sriastradh   unsigned attr;
5964a49301eSmrg
5973464ebd5Sriastradh   for (attr = 0; attr < nr_attrs; attr++) {
5983464ebd5Sriastradh      float data[4];
5993464ebd5Sriastradh      uint8_t *dst = (uint8_t *)vert + tg->attrib[attr].output_offset;
6003464ebd5Sriastradh
6013464ebd5Sriastradh      if (tg->attrib[attr].type == TRANSLATE_ELEMENT_NORMAL) {
6023464ebd5Sriastradh         const uint8_t *src;
6033464ebd5Sriastradh         unsigned index;
6043464ebd5Sriastradh         int copy_size;
6053464ebd5Sriastradh
6063464ebd5Sriastradh         if (tg->attrib[attr].instance_divisor) {
607af69d88dSmrg            index = start_instance;
608af69d88dSmrg            index += (instance_id  / tg->attrib[attr].instance_divisor);
6093464ebd5Sriastradh            /* XXX we need to clamp the index here too, but to a
6103464ebd5Sriastradh             * per-array max value, not the draw->pt.max_index value
6113464ebd5Sriastradh             * that's being given to us via translate->set_buffer().
6123464ebd5Sriastradh             */
6133464ebd5Sriastradh         }
6143464ebd5Sriastradh         else {
6153464ebd5Sriastradh            index = elt;
6163464ebd5Sriastradh            /* clamp to avoid going out of bounds */
6173464ebd5Sriastradh            index = MIN2(index, tg->attrib[attr].max_index);
6183464ebd5Sriastradh         }
6193464ebd5Sriastradh
6203464ebd5Sriastradh         src = tg->attrib[attr].input_ptr +
621af69d88dSmrg               (ptrdiff_t)tg->attrib[attr].input_stride * index;
6223464ebd5Sriastradh
6233464ebd5Sriastradh         copy_size = tg->attrib[attr].copy_size;
62401e04c3fSmrg         if (likely(copy_size >= 0)) {
6253464ebd5Sriastradh            memcpy(dst, src, copy_size);
62601e04c3fSmrg         } else {
6277ec681f3Smrg            tg->attrib[attr].fetch(data, src, 1);
6283464ebd5Sriastradh
6293464ebd5Sriastradh            if (0)
6303464ebd5Sriastradh               debug_printf("Fetch linear attr %d  from %p  stride %d  index %d: "
6313464ebd5Sriastradh                         " %f, %f, %f, %f \n",
6323464ebd5Sriastradh                         attr,
6333464ebd5Sriastradh                         tg->attrib[attr].input_ptr,
6343464ebd5Sriastradh                         tg->attrib[attr].input_stride,
6353464ebd5Sriastradh                         index,
6363464ebd5Sriastradh                         data[0], data[1],data[2], data[3]);
6373464ebd5Sriastradh
63801e04c3fSmrg            tg->attrib[attr].emit(data, dst);
6393464ebd5Sriastradh         }
6403464ebd5Sriastradh      } else {
64101e04c3fSmrg         if (likely(tg->attrib[attr].copy_size >= 0)) {
6423464ebd5Sriastradh            memcpy(data, &instance_id, 4);
64301e04c3fSmrg         } else {
6443464ebd5Sriastradh            data[0] = (float)instance_id;
64501e04c3fSmrg            tg->attrib[attr].emit(data, dst);
6463464ebd5Sriastradh         }
6473464ebd5Sriastradh      }
6483464ebd5Sriastradh   }
6493464ebd5Sriastradh}
6504a49301eSmrg
6514a49301eSmrg/**
6524a49301eSmrg * Fetch vertex attributes for 'count' vertices.
6534a49301eSmrg */
65401e04c3fSmrgstatic void PIPE_CDECL
65501e04c3fSmrggeneric_run_elts(struct translate *translate,
65601e04c3fSmrg                 const unsigned *elts,
65701e04c3fSmrg                 unsigned count,
65801e04c3fSmrg                 unsigned start_instance,
65901e04c3fSmrg                 unsigned instance_id,
66001e04c3fSmrg                 void *output_buffer)
6614a49301eSmrg{
6624a49301eSmrg   struct translate_generic *tg = translate_generic(translate);
6634a49301eSmrg   char *vert = output_buffer;
6644a49301eSmrg   unsigned i;
6654a49301eSmrg
6664a49301eSmrg   for (i = 0; i < count; i++) {
667af69d88dSmrg      generic_run_one(tg, *elts++, start_instance, instance_id, vert);
6683464ebd5Sriastradh      vert += tg->translate.key.output_stride;
6693464ebd5Sriastradh   }
6703464ebd5Sriastradh}
6714a49301eSmrg
67201e04c3fSmrgstatic void PIPE_CDECL
67301e04c3fSmrggeneric_run_elts16(struct translate *translate,
67401e04c3fSmrg                   const uint16_t *elts,
67501e04c3fSmrg                   unsigned count,
67601e04c3fSmrg                   unsigned start_instance,
67701e04c3fSmrg                   unsigned instance_id,
67801e04c3fSmrg                   void *output_buffer)
6793464ebd5Sriastradh{
6803464ebd5Sriastradh   struct translate_generic *tg = translate_generic(translate);
6813464ebd5Sriastradh   char *vert = output_buffer;
6823464ebd5Sriastradh   unsigned i;
6834a49301eSmrg
6843464ebd5Sriastradh   for (i = 0; i < count; i++) {
685af69d88dSmrg      generic_run_one(tg, *elts++, start_instance, instance_id, vert);
6864a49301eSmrg      vert += tg->translate.key.output_stride;
6874a49301eSmrg   }
6884a49301eSmrg}
6894a49301eSmrg
69001e04c3fSmrgstatic void PIPE_CDECL
69101e04c3fSmrggeneric_run_elts8(struct translate *translate,
69201e04c3fSmrg                  const uint8_t *elts,
69301e04c3fSmrg                  unsigned count,
69401e04c3fSmrg                  unsigned start_instance,
69501e04c3fSmrg                  unsigned instance_id,
69601e04c3fSmrg                  void *output_buffer)
6973464ebd5Sriastradh{
6983464ebd5Sriastradh   struct translate_generic *tg = translate_generic(translate);
6993464ebd5Sriastradh   char *vert = output_buffer;
7003464ebd5Sriastradh   unsigned i;
7014a49301eSmrg
7023464ebd5Sriastradh   for (i = 0; i < count; i++) {
703af69d88dSmrg      generic_run_one(tg, *elts++, start_instance, instance_id, vert);
7043464ebd5Sriastradh      vert += tg->translate.key.output_stride;
7053464ebd5Sriastradh   }
7063464ebd5Sriastradh}
7074a49301eSmrg
70801e04c3fSmrgstatic void PIPE_CDECL
70901e04c3fSmrggeneric_run(struct translate *translate,
71001e04c3fSmrg            unsigned start,
71101e04c3fSmrg            unsigned count,
71201e04c3fSmrg            unsigned start_instance,
71301e04c3fSmrg            unsigned instance_id,
71401e04c3fSmrg            void *output_buffer)
7154a49301eSmrg{
7164a49301eSmrg   struct translate_generic *tg = translate_generic(translate);
7174a49301eSmrg   char *vert = output_buffer;
7184a49301eSmrg   unsigned i;
7194a49301eSmrg
7204a49301eSmrg   for (i = 0; i < count; i++) {
721af69d88dSmrg      generic_run_one(tg, start + i, start_instance, instance_id, vert);
7224a49301eSmrg      vert += tg->translate.key.output_stride;
7234a49301eSmrg   }
7244a49301eSmrg}
7254a49301eSmrg
7264a49301eSmrg
72701e04c3fSmrg
72801e04c3fSmrgstatic void
72901e04c3fSmrggeneric_set_buffer(struct translate *translate,
73001e04c3fSmrg                   unsigned buf,
73101e04c3fSmrg                   const void *ptr,
73201e04c3fSmrg                   unsigned stride,
73301e04c3fSmrg                   unsigned max_index)
7344a49301eSmrg{
7354a49301eSmrg   struct translate_generic *tg = translate_generic(translate);
7364a49301eSmrg   unsigned i;
7374a49301eSmrg
7384a49301eSmrg   for (i = 0; i < tg->nr_attrib; i++) {
7394a49301eSmrg      if (tg->attrib[i].buffer == buf) {
74001e04c3fSmrg         tg->attrib[i].input_ptr = ((const uint8_t *)ptr +
74101e04c3fSmrg                                    tg->attrib[i].input_offset);
74201e04c3fSmrg         tg->attrib[i].input_stride = stride;
7433464ebd5Sriastradh         tg->attrib[i].max_index = max_index;
7444a49301eSmrg      }
7454a49301eSmrg   }
7464a49301eSmrg}
7474a49301eSmrg
7484a49301eSmrg
74901e04c3fSmrgstatic void
75001e04c3fSmrggeneric_release(struct translate *translate)
7514a49301eSmrg{
7524a49301eSmrg   /* Refcount?
7534a49301eSmrg    */
7544a49301eSmrg   FREE(translate);
7554a49301eSmrg}
7564a49301eSmrg
757af69d88dSmrgstatic boolean
75801e04c3fSmrgis_legal_int_format_combo(const struct util_format_description *src,
75901e04c3fSmrg                          const struct util_format_description *dst)
760af69d88dSmrg{
761af69d88dSmrg   unsigned i;
762af69d88dSmrg   unsigned nr = MIN2(src->nr_channels, dst->nr_channels);
763af69d88dSmrg
764af69d88dSmrg   for (i = 0; i < nr; i++) {
765af69d88dSmrg      /* The signs must match. */
766af69d88dSmrg      if (src->channel[i].type != dst->channel[i].type) {
767af69d88dSmrg         return FALSE;
768af69d88dSmrg      }
769af69d88dSmrg
770af69d88dSmrg      /* Integers must not lose precision at any point in the pipeline. */
771af69d88dSmrg      if (src->channel[i].size > dst->channel[i].size) {
772af69d88dSmrg         return FALSE;
773af69d88dSmrg      }
774af69d88dSmrg   }
775af69d88dSmrg   return TRUE;
776af69d88dSmrg}
777af69d88dSmrg
77801e04c3fSmrgstruct translate *
77901e04c3fSmrgtranslate_generic_create(const struct translate_key *key)
7804a49301eSmrg{
7814a49301eSmrg   struct translate_generic *tg = CALLOC_STRUCT(translate_generic);
7824a49301eSmrg   unsigned i;
7834a49301eSmrg
78401e04c3fSmrg   if (!tg)
7854a49301eSmrg      return NULL;
7864a49301eSmrg
787af69d88dSmrg   assert(key->nr_elements <= TRANSLATE_MAX_ATTRIBS);
788af69d88dSmrg
7894a49301eSmrg   tg->translate.key = *key;
7904a49301eSmrg   tg->translate.release = generic_release;
7914a49301eSmrg   tg->translate.set_buffer = generic_set_buffer;
7924a49301eSmrg   tg->translate.run_elts = generic_run_elts;
7933464ebd5Sriastradh   tg->translate.run_elts16 = generic_run_elts16;
7943464ebd5Sriastradh   tg->translate.run_elts8 = generic_run_elts8;
7954a49301eSmrg   tg->translate.run = generic_run;
7964a49301eSmrg
7974a49301eSmrg   for (i = 0; i < key->nr_elements; i++) {
7983464ebd5Sriastradh      const struct util_format_description *format_desc =
7993464ebd5Sriastradh            util_format_description(key->element[i].input_format);
8007ec681f3Smrg      const struct util_format_unpack_description *unpack =
8017ec681f3Smrg         util_format_unpack_description(key->element[i].input_format);
8023464ebd5Sriastradh
8033464ebd5Sriastradh      assert(format_desc);
8043464ebd5Sriastradh
805cdc920a0Smrg      tg->attrib[i].type = key->element[i].type;
8064a49301eSmrg
807af69d88dSmrg      if (format_desc->channel[0].pure_integer) {
808af69d88dSmrg         const struct util_format_description *out_format_desc =
809af69d88dSmrg               util_format_description(key->element[i].output_format);
810af69d88dSmrg
811af69d88dSmrg         if (!is_legal_int_format_combo(format_desc, out_format_desc)) {
812af69d88dSmrg            FREE(tg);
813af69d88dSmrg            return NULL;
814af69d88dSmrg         }
815af69d88dSmrg      }
816af69d88dSmrg
8177ec681f3Smrg      tg->attrib[i].fetch = unpack->unpack_rgba;
8184a49301eSmrg      tg->attrib[i].buffer = key->element[i].input_buffer;
8194a49301eSmrg      tg->attrib[i].input_offset = key->element[i].input_offset;
820cdc920a0Smrg      tg->attrib[i].instance_divisor = key->element[i].instance_divisor;
8214a49301eSmrg
8224a49301eSmrg      tg->attrib[i].output_offset = key->element[i].output_offset;
8234a49301eSmrg
8243464ebd5Sriastradh      tg->attrib[i].copy_size = -1;
82501e04c3fSmrg      if (tg->attrib[i].type == TRANSLATE_ELEMENT_INSTANCE_ID) {
82601e04c3fSmrg         if (key->element[i].output_format == PIPE_FORMAT_R32_USCALED
82701e04c3fSmrg             || key->element[i].output_format == PIPE_FORMAT_R32_SSCALED)
82801e04c3fSmrg            tg->attrib[i].copy_size = 4;
82901e04c3fSmrg      } else {
83001e04c3fSmrg         if (key->element[i].input_format == key->element[i].output_format
83101e04c3fSmrg             && format_desc->block.width == 1
83201e04c3fSmrg             && format_desc->block.height == 1
83301e04c3fSmrg             && !(format_desc->block.bits & 7))
8343464ebd5Sriastradh            tg->attrib[i].copy_size = format_desc->block.bits >> 3;
8353464ebd5Sriastradh      }
8363464ebd5Sriastradh
83701e04c3fSmrg      if (tg->attrib[i].copy_size < 0)
83801e04c3fSmrg         tg->attrib[i].emit = get_emit_func(key->element[i].output_format);
8393464ebd5Sriastradh      else
84001e04c3fSmrg         tg->attrib[i].emit  = NULL;
8414a49301eSmrg   }
8424a49301eSmrg
8434a49301eSmrg   tg->nr_attrib = key->nr_elements;
8444a49301eSmrg
8454a49301eSmrg   return &tg->translate;
8464a49301eSmrg}
8473464ebd5Sriastradh
84801e04c3fSmrgboolean
84901e04c3fSmrgtranslate_generic_is_output_format_supported(enum pipe_format format)
8503464ebd5Sriastradh{
85101e04c3fSmrg   switch(format) {
8523464ebd5Sriastradh   case PIPE_FORMAT_R64G64B64A64_FLOAT: return TRUE;
8533464ebd5Sriastradh   case PIPE_FORMAT_R64G64B64_FLOAT: return TRUE;
8543464ebd5Sriastradh   case PIPE_FORMAT_R64G64_FLOAT: return TRUE;
8553464ebd5Sriastradh   case PIPE_FORMAT_R64_FLOAT: return TRUE;
8563464ebd5Sriastradh
8573464ebd5Sriastradh   case PIPE_FORMAT_R32G32B32A32_FLOAT: return TRUE;
8583464ebd5Sriastradh   case PIPE_FORMAT_R32G32B32_FLOAT: return TRUE;
8593464ebd5Sriastradh   case PIPE_FORMAT_R32G32_FLOAT: return TRUE;
8603464ebd5Sriastradh   case PIPE_FORMAT_R32_FLOAT: return TRUE;
8613464ebd5Sriastradh
862af69d88dSmrg   case PIPE_FORMAT_R16G16B16A16_FLOAT: return TRUE;
863af69d88dSmrg   case PIPE_FORMAT_R16G16B16_FLOAT: return TRUE;
864af69d88dSmrg   case PIPE_FORMAT_R16G16_FLOAT: return TRUE;
865af69d88dSmrg   case PIPE_FORMAT_R16_FLOAT: return TRUE;
866af69d88dSmrg
8673464ebd5Sriastradh   case PIPE_FORMAT_R32G32B32A32_USCALED: return TRUE;
8683464ebd5Sriastradh   case PIPE_FORMAT_R32G32B32_USCALED: return TRUE;
8693464ebd5Sriastradh   case PIPE_FORMAT_R32G32_USCALED: return TRUE;
8703464ebd5Sriastradh   case PIPE_FORMAT_R32_USCALED: return TRUE;
8713464ebd5Sriastradh
8723464ebd5Sriastradh   case PIPE_FORMAT_R32G32B32A32_SSCALED: return TRUE;
8733464ebd5Sriastradh   case PIPE_FORMAT_R32G32B32_SSCALED: return TRUE;
8743464ebd5Sriastradh   case PIPE_FORMAT_R32G32_SSCALED: return TRUE;
8753464ebd5Sriastradh   case PIPE_FORMAT_R32_SSCALED: return TRUE;
8763464ebd5Sriastradh
8773464ebd5Sriastradh   case PIPE_FORMAT_R32G32B32A32_UNORM: return TRUE;
8783464ebd5Sriastradh   case PIPE_FORMAT_R32G32B32_UNORM: return TRUE;
8793464ebd5Sriastradh   case PIPE_FORMAT_R32G32_UNORM: return TRUE;
8803464ebd5Sriastradh   case PIPE_FORMAT_R32_UNORM: return TRUE;
8813464ebd5Sriastradh
8823464ebd5Sriastradh   case PIPE_FORMAT_R32G32B32A32_SNORM: return TRUE;
8833464ebd5Sriastradh   case PIPE_FORMAT_R32G32B32_SNORM: return TRUE;
8843464ebd5Sriastradh   case PIPE_FORMAT_R32G32_SNORM: return TRUE;
8853464ebd5Sriastradh   case PIPE_FORMAT_R32_SNORM: return TRUE;
8863464ebd5Sriastradh
8873464ebd5Sriastradh   case PIPE_FORMAT_R16G16B16A16_USCALED: return TRUE;
8883464ebd5Sriastradh   case PIPE_FORMAT_R16G16B16_USCALED: return TRUE;
8893464ebd5Sriastradh   case PIPE_FORMAT_R16G16_USCALED: return TRUE;
8903464ebd5Sriastradh   case PIPE_FORMAT_R16_USCALED: return TRUE;
8913464ebd5Sriastradh
8923464ebd5Sriastradh   case PIPE_FORMAT_R16G16B16A16_SSCALED: return TRUE;
8933464ebd5Sriastradh   case PIPE_FORMAT_R16G16B16_SSCALED: return TRUE;
8943464ebd5Sriastradh   case PIPE_FORMAT_R16G16_SSCALED: return TRUE;
8953464ebd5Sriastradh   case PIPE_FORMAT_R16_SSCALED: return TRUE;
8963464ebd5Sriastradh
8973464ebd5Sriastradh   case PIPE_FORMAT_R16G16B16A16_UNORM: return TRUE;
8983464ebd5Sriastradh   case PIPE_FORMAT_R16G16B16_UNORM: return TRUE;
8993464ebd5Sriastradh   case PIPE_FORMAT_R16G16_UNORM: return TRUE;
9003464ebd5Sriastradh   case PIPE_FORMAT_R16_UNORM: return TRUE;
9013464ebd5Sriastradh
9023464ebd5Sriastradh   case PIPE_FORMAT_R16G16B16A16_SNORM: return TRUE;
9033464ebd5Sriastradh   case PIPE_FORMAT_R16G16B16_SNORM: return TRUE;
9043464ebd5Sriastradh   case PIPE_FORMAT_R16G16_SNORM: return TRUE;
9053464ebd5Sriastradh   case PIPE_FORMAT_R16_SNORM: return TRUE;
9063464ebd5Sriastradh
9073464ebd5Sriastradh   case PIPE_FORMAT_R8G8B8A8_USCALED: return TRUE;
9083464ebd5Sriastradh   case PIPE_FORMAT_R8G8B8_USCALED: return TRUE;
9093464ebd5Sriastradh   case PIPE_FORMAT_R8G8_USCALED: return TRUE;
9103464ebd5Sriastradh   case PIPE_FORMAT_R8_USCALED: return TRUE;
9113464ebd5Sriastradh
9123464ebd5Sriastradh   case PIPE_FORMAT_R8G8B8A8_SSCALED: return TRUE;
9133464ebd5Sriastradh   case PIPE_FORMAT_R8G8B8_SSCALED: return TRUE;
9143464ebd5Sriastradh   case PIPE_FORMAT_R8G8_SSCALED: return TRUE;
9153464ebd5Sriastradh   case PIPE_FORMAT_R8_SSCALED: return TRUE;
9163464ebd5Sriastradh
9173464ebd5Sriastradh   case PIPE_FORMAT_R8G8B8A8_UNORM: return TRUE;
9183464ebd5Sriastradh   case PIPE_FORMAT_R8G8B8_UNORM: return TRUE;
9193464ebd5Sriastradh   case PIPE_FORMAT_R8G8_UNORM: return TRUE;
9203464ebd5Sriastradh   case PIPE_FORMAT_R8_UNORM: return TRUE;
9213464ebd5Sriastradh
9223464ebd5Sriastradh   case PIPE_FORMAT_R8G8B8A8_SNORM: return TRUE;
9233464ebd5Sriastradh   case PIPE_FORMAT_R8G8B8_SNORM: return TRUE;
9243464ebd5Sriastradh   case PIPE_FORMAT_R8G8_SNORM: return TRUE;
9253464ebd5Sriastradh   case PIPE_FORMAT_R8_SNORM: return TRUE;
9263464ebd5Sriastradh
9273464ebd5Sriastradh   case PIPE_FORMAT_A8R8G8B8_UNORM: return TRUE;
9283464ebd5Sriastradh   case PIPE_FORMAT_B8G8R8A8_UNORM: return TRUE;
929af69d88dSmrg
930af69d88dSmrg   case PIPE_FORMAT_R32G32B32A32_UINT: return TRUE;
931af69d88dSmrg   case PIPE_FORMAT_R32G32B32_UINT: return TRUE;
932af69d88dSmrg   case PIPE_FORMAT_R32G32_UINT: return TRUE;
933af69d88dSmrg   case PIPE_FORMAT_R32_UINT: return TRUE;
934af69d88dSmrg
935af69d88dSmrg   case PIPE_FORMAT_R16G16B16A16_UINT: return TRUE;
936af69d88dSmrg   case PIPE_FORMAT_R16G16B16_UINT: return TRUE;
937af69d88dSmrg   case PIPE_FORMAT_R16G16_UINT: return TRUE;
938af69d88dSmrg   case PIPE_FORMAT_R16_UINT: return TRUE;
939af69d88dSmrg
940af69d88dSmrg   case PIPE_FORMAT_R8G8B8A8_UINT: return TRUE;
941af69d88dSmrg   case PIPE_FORMAT_R8G8B8_UINT: return TRUE;
942af69d88dSmrg   case PIPE_FORMAT_R8G8_UINT: return TRUE;
943af69d88dSmrg   case PIPE_FORMAT_R8_UINT: return TRUE;
944af69d88dSmrg
945af69d88dSmrg   case PIPE_FORMAT_R32G32B32A32_SINT: return TRUE;
946af69d88dSmrg   case PIPE_FORMAT_R32G32B32_SINT: return TRUE;
947af69d88dSmrg   case PIPE_FORMAT_R32G32_SINT: return TRUE;
948af69d88dSmrg   case PIPE_FORMAT_R32_SINT: return TRUE;
949af69d88dSmrg
950af69d88dSmrg   case PIPE_FORMAT_R16G16B16A16_SINT: return TRUE;
951af69d88dSmrg   case PIPE_FORMAT_R16G16B16_SINT: return TRUE;
952af69d88dSmrg   case PIPE_FORMAT_R16G16_SINT: return TRUE;
953af69d88dSmrg   case PIPE_FORMAT_R16_SINT: return TRUE;
954af69d88dSmrg
955af69d88dSmrg   case PIPE_FORMAT_R8G8B8A8_SINT: return TRUE;
956af69d88dSmrg   case PIPE_FORMAT_R8G8B8_SINT: return TRUE;
957af69d88dSmrg   case PIPE_FORMAT_R8G8_SINT: return TRUE;
958af69d88dSmrg   case PIPE_FORMAT_R8_SINT: return TRUE;
959af69d88dSmrg
960af69d88dSmrg   case PIPE_FORMAT_B10G10R10A2_UNORM: return TRUE;
961af69d88dSmrg   case PIPE_FORMAT_B10G10R10A2_USCALED: return TRUE;
962af69d88dSmrg   case PIPE_FORMAT_B10G10R10A2_SNORM: return TRUE;
963af69d88dSmrg   case PIPE_FORMAT_B10G10R10A2_SSCALED: return TRUE;
964af69d88dSmrg
965af69d88dSmrg   case PIPE_FORMAT_R10G10B10A2_UNORM: return TRUE;
966af69d88dSmrg   case PIPE_FORMAT_R10G10B10A2_USCALED: return TRUE;
967af69d88dSmrg   case PIPE_FORMAT_R10G10B10A2_SNORM: return TRUE;
968af69d88dSmrg   case PIPE_FORMAT_R10G10B10A2_SSCALED: return TRUE;
969af69d88dSmrg
9703464ebd5Sriastradh   default: return FALSE;
9713464ebd5Sriastradh   }
9723464ebd5Sriastradh}
973