Path: blob/21.2-virgl/src/gallium/auxiliary/translate/translate_generic.c
4565 views
/**************************************************************************1*2* Copyright 2007 VMware, Inc.3* All Rights Reserved.4*5* Permission is hereby granted, free of charge, to any person obtaining a6* copy of this software and associated documentation files (the7* "Software"), to deal in the Software without restriction, including8* without limitation the rights to use, copy, modify, merge, publish,9* distribute, sub license, and/or sell copies of the Software, and to10* permit persons to whom the Software is furnished to do so, subject to11* the following conditions:12*13* The above copyright notice and this permission notice (including the14* next paragraph) shall be included in all copies or substantial portions15* of the Software.16*17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS18* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF19* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.20* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR21* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,22* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE23* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.24*25**************************************************************************/2627/*28* Authors:29* Keith Whitwell <[email protected]>30*/3132#include "util/u_memory.h"33#include "util/format/u_format.h"34#include "util/half_float.h"35#include "util/u_math.h"36#include "pipe/p_state.h"37#include "translate.h"383940#define DRAW_DBG 04142typedef void (*emit_func)(const void *attrib, void *ptr);43444546struct translate_generic {47struct translate translate;4849struct {50enum translate_element_type type;5152void (*fetch)(void *restrict dst, const uint8_t *restrict src,53unsigned width);54unsigned buffer;55unsigned input_offset;56unsigned instance_divisor;5758emit_func emit;59unsigned output_offset;6061const uint8_t *input_ptr;62unsigned input_stride;63unsigned max_index;6465/* this value is set to -1 if this is a normal element with66* output_format != input_format: in this case, u_format is used67* to do a full conversion68*69* this value is set to the format size in bytes if70* output_format == input_format or for 32-bit instance ids:71* in this case, memcpy is used to copy this amount of bytes72*/73int copy_size;7475} attrib[TRANSLATE_MAX_ATTRIBS];7677unsigned nr_attrib;78};798081static struct translate_generic *82translate_generic(struct translate *translate)83{84return (struct translate_generic *)translate;85}868788/**89* Fetch a dword[4] vertex attribute from memory, doing format/type90* conversion as needed.91*92* This is probably needed/dupliocated elsewhere, eg format93* conversion, texture sampling etc.94*/95#define ATTRIB(NAME, SZ, SRCTYPE, DSTTYPE, TO) \96static void \97emit_##NAME(const void *attrib, void *ptr) \98{ \99unsigned i; \100SRCTYPE *in = (SRCTYPE *)attrib; \101DSTTYPE *out = (DSTTYPE *)ptr; \102\103for (i = 0; i < SZ; i++) { \104out[i] = TO(in[i]); \105} \106}107108109#define TO_64_FLOAT(x) ((double) x)110#define TO_32_FLOAT(x) (x)111#define TO_16_FLOAT(x) _mesa_float_to_half(x)112113#define TO_8_USCALED(x) ((unsigned char) x)114#define TO_16_USCALED(x) ((unsigned short) x)115#define TO_32_USCALED(x) ((unsigned int) x)116117#define TO_8_SSCALED(x) ((char) x)118#define TO_16_SSCALED(x) ((short) x)119#define TO_32_SSCALED(x) ((int) x)120121#define TO_8_UNORM(x) ((unsigned char) (x * 255.0f))122#define TO_16_UNORM(x) ((unsigned short) (x * 65535.0f))123#define TO_32_UNORM(x) ((unsigned int) (x * 4294967295.0f))124125#define TO_8_SNORM(x) ((char) (x * 127.0f))126#define TO_16_SNORM(x) ((short) (x * 32767.0f))127#define TO_32_SNORM(x) ((int) (x * 2147483647.0f))128129#define TO_32_FIXED(x) ((int) (x * 65536.0f))130131#define TO_INT(x) (x)132133134ATTRIB(R64G64B64A64_FLOAT, 4, float, double, TO_64_FLOAT)135ATTRIB(R64G64B64_FLOAT, 3, float, double, TO_64_FLOAT)136ATTRIB(R64G64_FLOAT, 2, float, double, TO_64_FLOAT)137ATTRIB(R64_FLOAT, 1, float, double, TO_64_FLOAT)138139ATTRIB(R32G32B32A32_FLOAT, 4, float, float, TO_32_FLOAT)140ATTRIB(R32G32B32_FLOAT, 3, float, float, TO_32_FLOAT)141ATTRIB(R32G32_FLOAT, 2, float, float, TO_32_FLOAT)142ATTRIB(R32_FLOAT, 1, float, float, TO_32_FLOAT)143144ATTRIB(R16G16B16A16_FLOAT, 4, float, ushort, TO_16_FLOAT)145ATTRIB(R16G16B16_FLOAT, 3, float, ushort, TO_16_FLOAT)146ATTRIB(R16G16_FLOAT, 2, float, ushort, TO_16_FLOAT)147ATTRIB(R16_FLOAT, 1, float, ushort, TO_16_FLOAT)148149ATTRIB(R32G32B32A32_USCALED, 4, float, unsigned, TO_32_USCALED)150ATTRIB(R32G32B32_USCALED, 3, float, unsigned, TO_32_USCALED)151ATTRIB(R32G32_USCALED, 2, float, unsigned, TO_32_USCALED)152ATTRIB(R32_USCALED, 1, float, unsigned, TO_32_USCALED)153154ATTRIB(R32G32B32A32_SSCALED, 4, float, int, TO_32_SSCALED)155ATTRIB(R32G32B32_SSCALED, 3, float, int, TO_32_SSCALED)156ATTRIB(R32G32_SSCALED, 2, float, int, TO_32_SSCALED)157ATTRIB(R32_SSCALED, 1, float, int, TO_32_SSCALED)158159ATTRIB(R32G32B32A32_UNORM, 4, float, unsigned, TO_32_UNORM)160ATTRIB(R32G32B32_UNORM, 3, float, unsigned, TO_32_UNORM)161ATTRIB(R32G32_UNORM, 2, float, unsigned, TO_32_UNORM)162ATTRIB(R32_UNORM, 1, float, unsigned, TO_32_UNORM)163164ATTRIB(R32G32B32A32_SNORM, 4, float, int, TO_32_SNORM)165ATTRIB(R32G32B32_SNORM, 3, float, int, TO_32_SNORM)166ATTRIB(R32G32_SNORM, 2, float, int, TO_32_SNORM)167ATTRIB(R32_SNORM, 1, float, int, TO_32_SNORM)168169ATTRIB(R16G16B16A16_USCALED, 4, float, ushort, TO_16_USCALED)170ATTRIB(R16G16B16_USCALED, 3, float, ushort, TO_16_USCALED)171ATTRIB(R16G16_USCALED, 2, float, ushort, TO_16_USCALED)172ATTRIB(R16_USCALED, 1, float, ushort, TO_16_USCALED)173174ATTRIB(R16G16B16A16_SSCALED, 4, float, short, TO_16_SSCALED)175ATTRIB(R16G16B16_SSCALED, 3, float, short, TO_16_SSCALED)176ATTRIB(R16G16_SSCALED, 2, float, short, TO_16_SSCALED)177ATTRIB(R16_SSCALED, 1, float, short, TO_16_SSCALED)178179ATTRIB(R16G16B16A16_UNORM, 4, float, ushort, TO_16_UNORM)180ATTRIB(R16G16B16_UNORM, 3, float, ushort, TO_16_UNORM)181ATTRIB(R16G16_UNORM, 2, float, ushort, TO_16_UNORM)182ATTRIB(R16_UNORM, 1, float, ushort, TO_16_UNORM)183184ATTRIB(R16G16B16A16_SNORM, 4, float, short, TO_16_SNORM)185ATTRIB(R16G16B16_SNORM, 3, float, short, TO_16_SNORM)186ATTRIB(R16G16_SNORM, 2, float, short, TO_16_SNORM)187ATTRIB(R16_SNORM, 1, float, short, TO_16_SNORM)188189ATTRIB(R8G8B8A8_USCALED, 4, float, ubyte, TO_8_USCALED)190ATTRIB(R8G8B8_USCALED, 3, float, ubyte, TO_8_USCALED)191ATTRIB(R8G8_USCALED, 2, float, ubyte, TO_8_USCALED)192ATTRIB(R8_USCALED, 1, float, ubyte, TO_8_USCALED)193194ATTRIB(R8G8B8A8_SSCALED, 4, float, char, TO_8_SSCALED)195ATTRIB(R8G8B8_SSCALED, 3, float, char, TO_8_SSCALED)196ATTRIB(R8G8_SSCALED, 2, float, char, TO_8_SSCALED)197ATTRIB(R8_SSCALED, 1, float, char, TO_8_SSCALED)198199ATTRIB(R8G8B8A8_UNORM, 4, float, ubyte, TO_8_UNORM)200ATTRIB(R8G8B8_UNORM, 3, float, ubyte, TO_8_UNORM)201ATTRIB(R8G8_UNORM, 2, float, ubyte, TO_8_UNORM)202ATTRIB(R8_UNORM, 1, float, ubyte, TO_8_UNORM)203204ATTRIB(R8G8B8A8_SNORM, 4, float, char, TO_8_SNORM)205ATTRIB(R8G8B8_SNORM, 3, float, char, TO_8_SNORM)206ATTRIB(R8G8_SNORM, 2, float, char, TO_8_SNORM)207ATTRIB(R8_SNORM, 1, float, char, TO_8_SNORM)208209ATTRIB(R32G32B32A32_UINT, 4, uint32_t, unsigned, TO_INT)210ATTRIB(R32G32B32_UINT, 3, uint32_t, unsigned, TO_INT)211ATTRIB(R32G32_UINT, 2, uint32_t, unsigned, TO_INT)212ATTRIB(R32_UINT, 1, uint32_t, unsigned, TO_INT)213214ATTRIB(R16G16B16A16_UINT, 4, uint32_t, ushort, TO_INT)215ATTRIB(R16G16B16_UINT, 3, uint32_t, ushort, TO_INT)216ATTRIB(R16G16_UINT, 2, uint32_t, ushort, TO_INT)217ATTRIB(R16_UINT, 1, uint32_t, ushort, TO_INT)218219ATTRIB(R8G8B8A8_UINT, 4, uint32_t, ubyte, TO_INT)220ATTRIB(R8G8B8_UINT, 3, uint32_t, ubyte, TO_INT)221ATTRIB(R8G8_UINT, 2, uint32_t, ubyte, TO_INT)222ATTRIB(R8_UINT, 1, uint32_t, ubyte, TO_INT)223224ATTRIB(R32G32B32A32_SINT, 4, int32_t, int, TO_INT)225ATTRIB(R32G32B32_SINT, 3, int32_t, int, TO_INT)226ATTRIB(R32G32_SINT, 2, int32_t, int, TO_INT)227ATTRIB(R32_SINT, 1, int32_t, int, TO_INT)228229ATTRIB(R16G16B16A16_SINT, 4, int32_t, short, TO_INT)230ATTRIB(R16G16B16_SINT, 3, int32_t, short, TO_INT)231ATTRIB(R16G16_SINT, 2, int32_t, short, TO_INT)232ATTRIB(R16_SINT, 1, int32_t, short, TO_INT)233234ATTRIB(R8G8B8A8_SINT, 4, int32_t, char, TO_INT)235ATTRIB(R8G8B8_SINT, 3, int32_t, char, TO_INT)236ATTRIB(R8G8_SINT, 2, int32_t, char, TO_INT)237ATTRIB(R8_SINT, 1, int32_t, char, TO_INT)238239static void240emit_A8R8G8B8_UNORM(const void *attrib, void *ptr)241{242float *in = (float *)attrib;243ubyte *out = (ubyte *)ptr;244out[0] = TO_8_UNORM(in[3]);245out[1] = TO_8_UNORM(in[0]);246out[2] = TO_8_UNORM(in[1]);247out[3] = TO_8_UNORM(in[2]);248}249250static void251emit_B8G8R8A8_UNORM(const void *attrib, void *ptr)252{253float *in = (float *)attrib;254ubyte *out = (ubyte *)ptr;255out[2] = TO_8_UNORM(in[0]);256out[1] = TO_8_UNORM(in[1]);257out[0] = TO_8_UNORM(in[2]);258out[3] = TO_8_UNORM(in[3]);259}260261static void262emit_B10G10R10A2_UNORM(const void *attrib, void *ptr)263{264float *src = (float *)ptr;265uint32_t value = 0;266value |= ((uint32_t)(CLAMP(src[2], 0, 1) * 0x3ff)) & 0x3ff;267value |= (((uint32_t)(CLAMP(src[1], 0, 1) * 0x3ff)) & 0x3ff) << 10;268value |= (((uint32_t)(CLAMP(src[0], 0, 1) * 0x3ff)) & 0x3ff) << 20;269value |= ((uint32_t)(CLAMP(src[3], 0, 1) * 0x3)) << 30;270*(uint32_t *)attrib = util_le32_to_cpu(value);271}272273static void274emit_B10G10R10A2_USCALED(const void *attrib, void *ptr)275{276float *src = (float *)ptr;277uint32_t value = 0;278value |= ((uint32_t)CLAMP(src[2], 0, 1023)) & 0x3ff;279value |= (((uint32_t)CLAMP(src[1], 0, 1023)) & 0x3ff) << 10;280value |= (((uint32_t)CLAMP(src[0], 0, 1023)) & 0x3ff) << 20;281value |= ((uint32_t)CLAMP(src[3], 0, 3)) << 30;282*(uint32_t *)attrib = util_le32_to_cpu(value);283}284285static void286emit_B10G10R10A2_SNORM(const void *attrib, void *ptr)287{288float *src = (float *)ptr;289uint32_t value = 0;290value |= (uint32_t)(((uint32_t)(CLAMP(src[2], -1, 1) * 0x1ff)) & 0x3ff) ;291value |= (uint32_t)((((uint32_t)(CLAMP(src[1], -1, 1) * 0x1ff)) & 0x3ff) << 10) ;292value |= (uint32_t)((((uint32_t)(CLAMP(src[0], -1, 1) * 0x1ff)) & 0x3ff) << 20) ;293value |= (uint32_t)(((uint32_t)(CLAMP(src[3], -1, 1) * 0x1)) << 30) ;294*(uint32_t *)attrib = util_le32_to_cpu(value);295}296297static void298emit_B10G10R10A2_SSCALED(const void *attrib, void *ptr)299{300float *src = (float *)ptr;301uint32_t value = 0;302value |= (uint32_t)(((uint32_t)CLAMP(src[2], -512, 511)) & 0x3ff) ;303value |= (uint32_t)((((uint32_t)CLAMP(src[1], -512, 511)) & 0x3ff) << 10) ;304value |= (uint32_t)((((uint32_t)CLAMP(src[0], -512, 511)) & 0x3ff) << 20) ;305value |= (uint32_t)(((uint32_t)CLAMP(src[3], -2, 1)) << 30) ;306*(uint32_t *)attrib = util_le32_to_cpu(value);307}308309static void310emit_R10G10B10A2_UNORM(const void *attrib, void *ptr)311{312float *src = (float *)ptr;313uint32_t value = 0;314value |= ((uint32_t)(CLAMP(src[0], 0, 1) * 0x3ff)) & 0x3ff;315value |= (((uint32_t)(CLAMP(src[1], 0, 1) * 0x3ff)) & 0x3ff) << 10;316value |= (((uint32_t)(CLAMP(src[2], 0, 1) * 0x3ff)) & 0x3ff) << 20;317value |= ((uint32_t)(CLAMP(src[3], 0, 1) * 0x3)) << 30;318*(uint32_t *)attrib = util_le32_to_cpu(value);319}320321static void322emit_R10G10B10A2_USCALED(const void *attrib, void *ptr)323{324float *src = (float *)ptr;325uint32_t value = 0;326value |= ((uint32_t)CLAMP(src[0], 0, 1023)) & 0x3ff;327value |= (((uint32_t)CLAMP(src[1], 0, 1023)) & 0x3ff) << 10;328value |= (((uint32_t)CLAMP(src[2], 0, 1023)) & 0x3ff) << 20;329value |= ((uint32_t)CLAMP(src[3], 0, 3)) << 30;330*(uint32_t *)attrib = util_le32_to_cpu(value);331}332333static void334emit_R10G10B10A2_SNORM(const void *attrib, void *ptr)335{336float *src = (float *)ptr;337uint32_t value = 0;338value |= (uint32_t)(((uint32_t)(CLAMP(src[0], -1, 1) * 0x1ff)) & 0x3ff) ;339value |= (uint32_t)((((uint32_t)(CLAMP(src[1], -1, 1) * 0x1ff)) & 0x3ff) << 10) ;340value |= (uint32_t)((((uint32_t)(CLAMP(src[2], -1, 1) * 0x1ff)) & 0x3ff) << 20) ;341value |= (uint32_t)(((uint32_t)(CLAMP(src[3], -1, 1) * 0x1)) << 30) ;342*(uint32_t *)attrib = util_le32_to_cpu(value);343}344345static void346emit_R10G10B10A2_SSCALED(const void *attrib, void *ptr)347{348float *src = (float *)ptr;349uint32_t value = 0;350value |= (uint32_t)(((uint32_t)CLAMP(src[0], -512, 511)) & 0x3ff) ;351value |= (uint32_t)((((uint32_t)CLAMP(src[1], -512, 511)) & 0x3ff) << 10) ;352value |= (uint32_t)((((uint32_t)CLAMP(src[2], -512, 511)) & 0x3ff) << 20) ;353value |= (uint32_t)(((uint32_t)CLAMP(src[3], -2, 1)) << 30) ;354*(uint32_t *)attrib = util_le32_to_cpu(value);355}356357static void358emit_NULL(const void *attrib, void *ptr)359{360/* do nothing is the only sensible option */361}362363static emit_func364get_emit_func(enum pipe_format format)365{366switch (format) {367case PIPE_FORMAT_R64_FLOAT:368return &emit_R64_FLOAT;369case PIPE_FORMAT_R64G64_FLOAT:370return &emit_R64G64_FLOAT;371case PIPE_FORMAT_R64G64B64_FLOAT:372return &emit_R64G64B64_FLOAT;373case PIPE_FORMAT_R64G64B64A64_FLOAT:374return &emit_R64G64B64A64_FLOAT;375376case PIPE_FORMAT_R32_FLOAT:377return &emit_R32_FLOAT;378case PIPE_FORMAT_R32G32_FLOAT:379return &emit_R32G32_FLOAT;380case PIPE_FORMAT_R32G32B32_FLOAT:381return &emit_R32G32B32_FLOAT;382case PIPE_FORMAT_R32G32B32A32_FLOAT:383return &emit_R32G32B32A32_FLOAT;384385case PIPE_FORMAT_R16_FLOAT:386return &emit_R16_FLOAT;387case PIPE_FORMAT_R16G16_FLOAT:388return &emit_R16G16_FLOAT;389case PIPE_FORMAT_R16G16B16_FLOAT:390return &emit_R16G16B16_FLOAT;391case PIPE_FORMAT_R16G16B16A16_FLOAT:392return &emit_R16G16B16A16_FLOAT;393394case PIPE_FORMAT_R32_UNORM:395return &emit_R32_UNORM;396case PIPE_FORMAT_R32G32_UNORM:397return &emit_R32G32_UNORM;398case PIPE_FORMAT_R32G32B32_UNORM:399return &emit_R32G32B32_UNORM;400case PIPE_FORMAT_R32G32B32A32_UNORM:401return &emit_R32G32B32A32_UNORM;402403case PIPE_FORMAT_R32_USCALED:404return &emit_R32_USCALED;405case PIPE_FORMAT_R32G32_USCALED:406return &emit_R32G32_USCALED;407case PIPE_FORMAT_R32G32B32_USCALED:408return &emit_R32G32B32_USCALED;409case PIPE_FORMAT_R32G32B32A32_USCALED:410return &emit_R32G32B32A32_USCALED;411412case PIPE_FORMAT_R32_SNORM:413return &emit_R32_SNORM;414case PIPE_FORMAT_R32G32_SNORM:415return &emit_R32G32_SNORM;416case PIPE_FORMAT_R32G32B32_SNORM:417return &emit_R32G32B32_SNORM;418case PIPE_FORMAT_R32G32B32A32_SNORM:419return &emit_R32G32B32A32_SNORM;420421case PIPE_FORMAT_R32_SSCALED:422return &emit_R32_SSCALED;423case PIPE_FORMAT_R32G32_SSCALED:424return &emit_R32G32_SSCALED;425case PIPE_FORMAT_R32G32B32_SSCALED:426return &emit_R32G32B32_SSCALED;427case PIPE_FORMAT_R32G32B32A32_SSCALED:428return &emit_R32G32B32A32_SSCALED;429430case PIPE_FORMAT_R16_UNORM:431return &emit_R16_UNORM;432case PIPE_FORMAT_R16G16_UNORM:433return &emit_R16G16_UNORM;434case PIPE_FORMAT_R16G16B16_UNORM:435return &emit_R16G16B16_UNORM;436case PIPE_FORMAT_R16G16B16A16_UNORM:437return &emit_R16G16B16A16_UNORM;438439case PIPE_FORMAT_R16_USCALED:440return &emit_R16_USCALED;441case PIPE_FORMAT_R16G16_USCALED:442return &emit_R16G16_USCALED;443case PIPE_FORMAT_R16G16B16_USCALED:444return &emit_R16G16B16_USCALED;445case PIPE_FORMAT_R16G16B16A16_USCALED:446return &emit_R16G16B16A16_USCALED;447448case PIPE_FORMAT_R16_SNORM:449return &emit_R16_SNORM;450case PIPE_FORMAT_R16G16_SNORM:451return &emit_R16G16_SNORM;452case PIPE_FORMAT_R16G16B16_SNORM:453return &emit_R16G16B16_SNORM;454case PIPE_FORMAT_R16G16B16A16_SNORM:455return &emit_R16G16B16A16_SNORM;456457case PIPE_FORMAT_R16_SSCALED:458return &emit_R16_SSCALED;459case PIPE_FORMAT_R16G16_SSCALED:460return &emit_R16G16_SSCALED;461case PIPE_FORMAT_R16G16B16_SSCALED:462return &emit_R16G16B16_SSCALED;463case PIPE_FORMAT_R16G16B16A16_SSCALED:464return &emit_R16G16B16A16_SSCALED;465466case PIPE_FORMAT_R8_UNORM:467return &emit_R8_UNORM;468case PIPE_FORMAT_R8G8_UNORM:469return &emit_R8G8_UNORM;470case PIPE_FORMAT_R8G8B8_UNORM:471return &emit_R8G8B8_UNORM;472case PIPE_FORMAT_R8G8B8A8_UNORM:473return &emit_R8G8B8A8_UNORM;474475case PIPE_FORMAT_R8_USCALED:476return &emit_R8_USCALED;477case PIPE_FORMAT_R8G8_USCALED:478return &emit_R8G8_USCALED;479case PIPE_FORMAT_R8G8B8_USCALED:480return &emit_R8G8B8_USCALED;481case PIPE_FORMAT_R8G8B8A8_USCALED:482return &emit_R8G8B8A8_USCALED;483484case PIPE_FORMAT_R8_SNORM:485return &emit_R8_SNORM;486case PIPE_FORMAT_R8G8_SNORM:487return &emit_R8G8_SNORM;488case PIPE_FORMAT_R8G8B8_SNORM:489return &emit_R8G8B8_SNORM;490case PIPE_FORMAT_R8G8B8A8_SNORM:491return &emit_R8G8B8A8_SNORM;492493case PIPE_FORMAT_R8_SSCALED:494return &emit_R8_SSCALED;495case PIPE_FORMAT_R8G8_SSCALED:496return &emit_R8G8_SSCALED;497case PIPE_FORMAT_R8G8B8_SSCALED:498return &emit_R8G8B8_SSCALED;499case PIPE_FORMAT_R8G8B8A8_SSCALED:500return &emit_R8G8B8A8_SSCALED;501502case PIPE_FORMAT_B8G8R8A8_UNORM:503return &emit_B8G8R8A8_UNORM;504505case PIPE_FORMAT_A8R8G8B8_UNORM:506return &emit_A8R8G8B8_UNORM;507508case PIPE_FORMAT_R32_UINT:509return &emit_R32_UINT;510case PIPE_FORMAT_R32G32_UINT:511return &emit_R32G32_UINT;512case PIPE_FORMAT_R32G32B32_UINT:513return &emit_R32G32B32_UINT;514case PIPE_FORMAT_R32G32B32A32_UINT:515return &emit_R32G32B32A32_UINT;516517case PIPE_FORMAT_R16_UINT:518return &emit_R16_UINT;519case PIPE_FORMAT_R16G16_UINT:520return &emit_R16G16_UINT;521case PIPE_FORMAT_R16G16B16_UINT:522return &emit_R16G16B16_UINT;523case PIPE_FORMAT_R16G16B16A16_UINT:524return &emit_R16G16B16A16_UINT;525526case PIPE_FORMAT_R8_UINT:527return &emit_R8_UINT;528case PIPE_FORMAT_R8G8_UINT:529return &emit_R8G8_UINT;530case PIPE_FORMAT_R8G8B8_UINT:531return &emit_R8G8B8_UINT;532case PIPE_FORMAT_R8G8B8A8_UINT:533return &emit_R8G8B8A8_UINT;534535case PIPE_FORMAT_R32_SINT:536return &emit_R32_SINT;537case PIPE_FORMAT_R32G32_SINT:538return &emit_R32G32_SINT;539case PIPE_FORMAT_R32G32B32_SINT:540return &emit_R32G32B32_SINT;541case PIPE_FORMAT_R32G32B32A32_SINT:542return &emit_R32G32B32A32_SINT;543544case PIPE_FORMAT_R16_SINT:545return &emit_R16_SINT;546case PIPE_FORMAT_R16G16_SINT:547return &emit_R16G16_SINT;548case PIPE_FORMAT_R16G16B16_SINT:549return &emit_R16G16B16_SINT;550case PIPE_FORMAT_R16G16B16A16_SINT:551return &emit_R16G16B16A16_SINT;552553case PIPE_FORMAT_R8_SINT:554return &emit_R8_SINT;555case PIPE_FORMAT_R8G8_SINT:556return &emit_R8G8_SINT;557case PIPE_FORMAT_R8G8B8_SINT:558return &emit_R8G8B8_SINT;559case PIPE_FORMAT_R8G8B8A8_SINT:560return &emit_R8G8B8A8_SINT;561562case PIPE_FORMAT_B10G10R10A2_UNORM:563return &emit_B10G10R10A2_UNORM;564case PIPE_FORMAT_B10G10R10A2_USCALED:565return &emit_B10G10R10A2_USCALED;566case PIPE_FORMAT_B10G10R10A2_SNORM:567return &emit_B10G10R10A2_SNORM;568case PIPE_FORMAT_B10G10R10A2_SSCALED:569return &emit_B10G10R10A2_SSCALED;570571case PIPE_FORMAT_R10G10B10A2_UNORM:572return &emit_R10G10B10A2_UNORM;573case PIPE_FORMAT_R10G10B10A2_USCALED:574return &emit_R10G10B10A2_USCALED;575case PIPE_FORMAT_R10G10B10A2_SNORM:576return &emit_R10G10B10A2_SNORM;577case PIPE_FORMAT_R10G10B10A2_SSCALED:578return &emit_R10G10B10A2_SSCALED;579580default:581assert(0);582return &emit_NULL;583}584}585586static ALWAYS_INLINE void PIPE_CDECL587generic_run_one(struct translate_generic *tg,588unsigned elt,589unsigned start_instance,590unsigned instance_id,591void *vert)592{593unsigned nr_attrs = tg->nr_attrib;594unsigned attr;595596for (attr = 0; attr < nr_attrs; attr++) {597float data[4];598uint8_t *dst = (uint8_t *)vert + tg->attrib[attr].output_offset;599600if (tg->attrib[attr].type == TRANSLATE_ELEMENT_NORMAL) {601const uint8_t *src;602unsigned index;603int copy_size;604605if (tg->attrib[attr].instance_divisor) {606index = start_instance;607index += (instance_id / tg->attrib[attr].instance_divisor);608/* XXX we need to clamp the index here too, but to a609* per-array max value, not the draw->pt.max_index value610* that's being given to us via translate->set_buffer().611*/612}613else {614index = elt;615/* clamp to avoid going out of bounds */616index = MIN2(index, tg->attrib[attr].max_index);617}618619src = tg->attrib[attr].input_ptr +620(ptrdiff_t)tg->attrib[attr].input_stride * index;621622copy_size = tg->attrib[attr].copy_size;623if (likely(copy_size >= 0)) {624memcpy(dst, src, copy_size);625} else {626tg->attrib[attr].fetch(data, src, 1);627628if (0)629debug_printf("Fetch linear attr %d from %p stride %d index %d: "630" %f, %f, %f, %f \n",631attr,632tg->attrib[attr].input_ptr,633tg->attrib[attr].input_stride,634index,635data[0], data[1],data[2], data[3]);636637tg->attrib[attr].emit(data, dst);638}639} else {640if (likely(tg->attrib[attr].copy_size >= 0)) {641memcpy(data, &instance_id, 4);642} else {643data[0] = (float)instance_id;644tg->attrib[attr].emit(data, dst);645}646}647}648}649650/**651* Fetch vertex attributes for 'count' vertices.652*/653static void PIPE_CDECL654generic_run_elts(struct translate *translate,655const unsigned *elts,656unsigned count,657unsigned start_instance,658unsigned instance_id,659void *output_buffer)660{661struct translate_generic *tg = translate_generic(translate);662char *vert = output_buffer;663unsigned i;664665for (i = 0; i < count; i++) {666generic_run_one(tg, *elts++, start_instance, instance_id, vert);667vert += tg->translate.key.output_stride;668}669}670671static void PIPE_CDECL672generic_run_elts16(struct translate *translate,673const uint16_t *elts,674unsigned count,675unsigned start_instance,676unsigned instance_id,677void *output_buffer)678{679struct translate_generic *tg = translate_generic(translate);680char *vert = output_buffer;681unsigned i;682683for (i = 0; i < count; i++) {684generic_run_one(tg, *elts++, start_instance, instance_id, vert);685vert += tg->translate.key.output_stride;686}687}688689static void PIPE_CDECL690generic_run_elts8(struct translate *translate,691const uint8_t *elts,692unsigned count,693unsigned start_instance,694unsigned instance_id,695void *output_buffer)696{697struct translate_generic *tg = translate_generic(translate);698char *vert = output_buffer;699unsigned i;700701for (i = 0; i < count; i++) {702generic_run_one(tg, *elts++, start_instance, instance_id, vert);703vert += tg->translate.key.output_stride;704}705}706707static void PIPE_CDECL708generic_run(struct translate *translate,709unsigned start,710unsigned count,711unsigned start_instance,712unsigned instance_id,713void *output_buffer)714{715struct translate_generic *tg = translate_generic(translate);716char *vert = output_buffer;717unsigned i;718719for (i = 0; i < count; i++) {720generic_run_one(tg, start + i, start_instance, instance_id, vert);721vert += tg->translate.key.output_stride;722}723}724725726727static void728generic_set_buffer(struct translate *translate,729unsigned buf,730const void *ptr,731unsigned stride,732unsigned max_index)733{734struct translate_generic *tg = translate_generic(translate);735unsigned i;736737for (i = 0; i < tg->nr_attrib; i++) {738if (tg->attrib[i].buffer == buf) {739tg->attrib[i].input_ptr = ((const uint8_t *)ptr +740tg->attrib[i].input_offset);741tg->attrib[i].input_stride = stride;742tg->attrib[i].max_index = max_index;743}744}745}746747748static void749generic_release(struct translate *translate)750{751/* Refcount?752*/753FREE(translate);754}755756static boolean757is_legal_int_format_combo(const struct util_format_description *src,758const struct util_format_description *dst)759{760unsigned i;761unsigned nr = MIN2(src->nr_channels, dst->nr_channels);762763for (i = 0; i < nr; i++) {764/* The signs must match. */765if (src->channel[i].type != dst->channel[i].type) {766return FALSE;767}768769/* Integers must not lose precision at any point in the pipeline. */770if (src->channel[i].size > dst->channel[i].size) {771return FALSE;772}773}774return TRUE;775}776777struct translate *778translate_generic_create(const struct translate_key *key)779{780struct translate_generic *tg = CALLOC_STRUCT(translate_generic);781unsigned i;782783if (!tg)784return NULL;785786assert(key->nr_elements <= TRANSLATE_MAX_ATTRIBS);787788tg->translate.key = *key;789tg->translate.release = generic_release;790tg->translate.set_buffer = generic_set_buffer;791tg->translate.run_elts = generic_run_elts;792tg->translate.run_elts16 = generic_run_elts16;793tg->translate.run_elts8 = generic_run_elts8;794tg->translate.run = generic_run;795796for (i = 0; i < key->nr_elements; i++) {797const struct util_format_description *format_desc =798util_format_description(key->element[i].input_format);799const struct util_format_unpack_description *unpack =800util_format_unpack_description(key->element[i].input_format);801802assert(format_desc);803804tg->attrib[i].type = key->element[i].type;805806if (format_desc->channel[0].pure_integer) {807const struct util_format_description *out_format_desc =808util_format_description(key->element[i].output_format);809810if (!is_legal_int_format_combo(format_desc, out_format_desc)) {811FREE(tg);812return NULL;813}814}815816tg->attrib[i].fetch = unpack->unpack_rgba;817tg->attrib[i].buffer = key->element[i].input_buffer;818tg->attrib[i].input_offset = key->element[i].input_offset;819tg->attrib[i].instance_divisor = key->element[i].instance_divisor;820821tg->attrib[i].output_offset = key->element[i].output_offset;822823tg->attrib[i].copy_size = -1;824if (tg->attrib[i].type == TRANSLATE_ELEMENT_INSTANCE_ID) {825if (key->element[i].output_format == PIPE_FORMAT_R32_USCALED826|| key->element[i].output_format == PIPE_FORMAT_R32_SSCALED)827tg->attrib[i].copy_size = 4;828} else {829if (key->element[i].input_format == key->element[i].output_format830&& format_desc->block.width == 1831&& format_desc->block.height == 1832&& !(format_desc->block.bits & 7))833tg->attrib[i].copy_size = format_desc->block.bits >> 3;834}835836if (tg->attrib[i].copy_size < 0)837tg->attrib[i].emit = get_emit_func(key->element[i].output_format);838else839tg->attrib[i].emit = NULL;840}841842tg->nr_attrib = key->nr_elements;843844return &tg->translate;845}846847boolean848translate_generic_is_output_format_supported(enum pipe_format format)849{850switch(format) {851case PIPE_FORMAT_R64G64B64A64_FLOAT: return TRUE;852case PIPE_FORMAT_R64G64B64_FLOAT: return TRUE;853case PIPE_FORMAT_R64G64_FLOAT: return TRUE;854case PIPE_FORMAT_R64_FLOAT: return TRUE;855856case PIPE_FORMAT_R32G32B32A32_FLOAT: return TRUE;857case PIPE_FORMAT_R32G32B32_FLOAT: return TRUE;858case PIPE_FORMAT_R32G32_FLOAT: return TRUE;859case PIPE_FORMAT_R32_FLOAT: return TRUE;860861case PIPE_FORMAT_R16G16B16A16_FLOAT: return TRUE;862case PIPE_FORMAT_R16G16B16_FLOAT: return TRUE;863case PIPE_FORMAT_R16G16_FLOAT: return TRUE;864case PIPE_FORMAT_R16_FLOAT: return TRUE;865866case PIPE_FORMAT_R32G32B32A32_USCALED: return TRUE;867case PIPE_FORMAT_R32G32B32_USCALED: return TRUE;868case PIPE_FORMAT_R32G32_USCALED: return TRUE;869case PIPE_FORMAT_R32_USCALED: return TRUE;870871case PIPE_FORMAT_R32G32B32A32_SSCALED: return TRUE;872case PIPE_FORMAT_R32G32B32_SSCALED: return TRUE;873case PIPE_FORMAT_R32G32_SSCALED: return TRUE;874case PIPE_FORMAT_R32_SSCALED: return TRUE;875876case PIPE_FORMAT_R32G32B32A32_UNORM: return TRUE;877case PIPE_FORMAT_R32G32B32_UNORM: return TRUE;878case PIPE_FORMAT_R32G32_UNORM: return TRUE;879case PIPE_FORMAT_R32_UNORM: return TRUE;880881case PIPE_FORMAT_R32G32B32A32_SNORM: return TRUE;882case PIPE_FORMAT_R32G32B32_SNORM: return TRUE;883case PIPE_FORMAT_R32G32_SNORM: return TRUE;884case PIPE_FORMAT_R32_SNORM: return TRUE;885886case PIPE_FORMAT_R16G16B16A16_USCALED: return TRUE;887case PIPE_FORMAT_R16G16B16_USCALED: return TRUE;888case PIPE_FORMAT_R16G16_USCALED: return TRUE;889case PIPE_FORMAT_R16_USCALED: return TRUE;890891case PIPE_FORMAT_R16G16B16A16_SSCALED: return TRUE;892case PIPE_FORMAT_R16G16B16_SSCALED: return TRUE;893case PIPE_FORMAT_R16G16_SSCALED: return TRUE;894case PIPE_FORMAT_R16_SSCALED: return TRUE;895896case PIPE_FORMAT_R16G16B16A16_UNORM: return TRUE;897case PIPE_FORMAT_R16G16B16_UNORM: return TRUE;898case PIPE_FORMAT_R16G16_UNORM: return TRUE;899case PIPE_FORMAT_R16_UNORM: return TRUE;900901case PIPE_FORMAT_R16G16B16A16_SNORM: return TRUE;902case PIPE_FORMAT_R16G16B16_SNORM: return TRUE;903case PIPE_FORMAT_R16G16_SNORM: return TRUE;904case PIPE_FORMAT_R16_SNORM: return TRUE;905906case PIPE_FORMAT_R8G8B8A8_USCALED: return TRUE;907case PIPE_FORMAT_R8G8B8_USCALED: return TRUE;908case PIPE_FORMAT_R8G8_USCALED: return TRUE;909case PIPE_FORMAT_R8_USCALED: return TRUE;910911case PIPE_FORMAT_R8G8B8A8_SSCALED: return TRUE;912case PIPE_FORMAT_R8G8B8_SSCALED: return TRUE;913case PIPE_FORMAT_R8G8_SSCALED: return TRUE;914case PIPE_FORMAT_R8_SSCALED: return TRUE;915916case PIPE_FORMAT_R8G8B8A8_UNORM: return TRUE;917case PIPE_FORMAT_R8G8B8_UNORM: return TRUE;918case PIPE_FORMAT_R8G8_UNORM: return TRUE;919case PIPE_FORMAT_R8_UNORM: return TRUE;920921case PIPE_FORMAT_R8G8B8A8_SNORM: return TRUE;922case PIPE_FORMAT_R8G8B8_SNORM: return TRUE;923case PIPE_FORMAT_R8G8_SNORM: return TRUE;924case PIPE_FORMAT_R8_SNORM: return TRUE;925926case PIPE_FORMAT_A8R8G8B8_UNORM: return TRUE;927case PIPE_FORMAT_B8G8R8A8_UNORM: return TRUE;928929case PIPE_FORMAT_R32G32B32A32_UINT: return TRUE;930case PIPE_FORMAT_R32G32B32_UINT: return TRUE;931case PIPE_FORMAT_R32G32_UINT: return TRUE;932case PIPE_FORMAT_R32_UINT: return TRUE;933934case PIPE_FORMAT_R16G16B16A16_UINT: return TRUE;935case PIPE_FORMAT_R16G16B16_UINT: return TRUE;936case PIPE_FORMAT_R16G16_UINT: return TRUE;937case PIPE_FORMAT_R16_UINT: return TRUE;938939case PIPE_FORMAT_R8G8B8A8_UINT: return TRUE;940case PIPE_FORMAT_R8G8B8_UINT: return TRUE;941case PIPE_FORMAT_R8G8_UINT: return TRUE;942case PIPE_FORMAT_R8_UINT: return TRUE;943944case PIPE_FORMAT_R32G32B32A32_SINT: return TRUE;945case PIPE_FORMAT_R32G32B32_SINT: return TRUE;946case PIPE_FORMAT_R32G32_SINT: return TRUE;947case PIPE_FORMAT_R32_SINT: return TRUE;948949case PIPE_FORMAT_R16G16B16A16_SINT: return TRUE;950case PIPE_FORMAT_R16G16B16_SINT: return TRUE;951case PIPE_FORMAT_R16G16_SINT: return TRUE;952case PIPE_FORMAT_R16_SINT: return TRUE;953954case PIPE_FORMAT_R8G8B8A8_SINT: return TRUE;955case PIPE_FORMAT_R8G8B8_SINT: return TRUE;956case PIPE_FORMAT_R8G8_SINT: return TRUE;957case PIPE_FORMAT_R8_SINT: return TRUE;958959case PIPE_FORMAT_B10G10R10A2_UNORM: return TRUE;960case PIPE_FORMAT_B10G10R10A2_USCALED: return TRUE;961case PIPE_FORMAT_B10G10R10A2_SNORM: return TRUE;962case PIPE_FORMAT_B10G10R10A2_SSCALED: return TRUE;963964case PIPE_FORMAT_R10G10B10A2_UNORM: return TRUE;965case PIPE_FORMAT_R10G10B10A2_USCALED: return TRUE;966case PIPE_FORMAT_R10G10B10A2_SNORM: return TRUE;967case PIPE_FORMAT_R10G10B10A2_SSCALED: return TRUE;968969default: return FALSE;970}971}972973974