17ec681f3Smrg/* 27ec681f3Smrg * Copyright 2011 Joakim Sindholt <opensource@zhasha.com> 37ec681f3Smrg * 47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 57ec681f3Smrg * copy of this software and associated documentation files (the "Software"), 67ec681f3Smrg * to deal in the Software without restriction, including without limitation 77ec681f3Smrg * on the rights to use, copy, modify, merge, publish, distribute, sub 87ec681f3Smrg * license, and/or sell copies of the Software, and to permit persons to whom 97ec681f3Smrg * the Software is furnished to do so, subject to the following conditions: 107ec681f3Smrg * 117ec681f3Smrg * The above copyright notice and this permission notice (including the next 127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the 137ec681f3Smrg * Software. 147ec681f3Smrg * 157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 187ec681f3Smrg * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 197ec681f3Smrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 207ec681f3Smrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 217ec681f3Smrg * USE OR OTHER DEALINGS IN THE SOFTWARE. */ 227ec681f3Smrg 237ec681f3Smrg#include "vertexdeclaration9.h" 247ec681f3Smrg#include "vertexbuffer9.h" 257ec681f3Smrg#include "device9.h" 267ec681f3Smrg#include "nine_helpers.h" 277ec681f3Smrg#include "nine_shader.h" 287ec681f3Smrg 297ec681f3Smrg#include "pipe/p_format.h" 307ec681f3Smrg#include "pipe/p_context.h" 317ec681f3Smrg#include "util/u_math.h" 327ec681f3Smrg#include "util/format/u_format.h" 337ec681f3Smrg#include "translate/translate.h" 347ec681f3Smrg 357ec681f3Smrg#define DBG_CHANNEL DBG_VERTEXDECLARATION 367ec681f3Smrg 377ec681f3Smrgstatic inline enum pipe_format decltype_format(BYTE type) 387ec681f3Smrg{ 397ec681f3Smrg switch (type) { 407ec681f3Smrg case D3DDECLTYPE_FLOAT1: return PIPE_FORMAT_R32_FLOAT; 417ec681f3Smrg case D3DDECLTYPE_FLOAT2: return PIPE_FORMAT_R32G32_FLOAT; 427ec681f3Smrg case D3DDECLTYPE_FLOAT3: return PIPE_FORMAT_R32G32B32_FLOAT; 437ec681f3Smrg case D3DDECLTYPE_FLOAT4: return PIPE_FORMAT_R32G32B32A32_FLOAT; 447ec681f3Smrg case D3DDECLTYPE_D3DCOLOR: return PIPE_FORMAT_B8G8R8A8_UNORM; 457ec681f3Smrg case D3DDECLTYPE_UBYTE4: return PIPE_FORMAT_R8G8B8A8_USCALED; 467ec681f3Smrg case D3DDECLTYPE_SHORT2: return PIPE_FORMAT_R16G16_SSCALED; 477ec681f3Smrg case D3DDECLTYPE_SHORT4: return PIPE_FORMAT_R16G16B16A16_SSCALED; 487ec681f3Smrg case D3DDECLTYPE_UBYTE4N: return PIPE_FORMAT_R8G8B8A8_UNORM; 497ec681f3Smrg case D3DDECLTYPE_SHORT2N: return PIPE_FORMAT_R16G16_SNORM; 507ec681f3Smrg case D3DDECLTYPE_SHORT4N: return PIPE_FORMAT_R16G16B16A16_SNORM; 517ec681f3Smrg case D3DDECLTYPE_USHORT2N: return PIPE_FORMAT_R16G16_UNORM; 527ec681f3Smrg case D3DDECLTYPE_USHORT4N: return PIPE_FORMAT_R16G16B16A16_UNORM; 537ec681f3Smrg case D3DDECLTYPE_UDEC3: return PIPE_FORMAT_R10G10B10X2_USCALED; 547ec681f3Smrg case D3DDECLTYPE_DEC3N: return PIPE_FORMAT_R10G10B10X2_SNORM; 557ec681f3Smrg case D3DDECLTYPE_FLOAT16_2: return PIPE_FORMAT_R16G16_FLOAT; 567ec681f3Smrg case D3DDECLTYPE_FLOAT16_4: return PIPE_FORMAT_R16G16B16A16_FLOAT; 577ec681f3Smrg default: 587ec681f3Smrg assert(!"Implementation error !"); 597ec681f3Smrg } 607ec681f3Smrg return PIPE_FORMAT_NONE; 617ec681f3Smrg} 627ec681f3Smrg 637ec681f3Smrgstatic inline unsigned decltype_size(BYTE type) 647ec681f3Smrg{ 657ec681f3Smrg switch (type) { 667ec681f3Smrg case D3DDECLTYPE_FLOAT1: return 1 * sizeof(float); 677ec681f3Smrg case D3DDECLTYPE_FLOAT2: return 2 * sizeof(float); 687ec681f3Smrg case D3DDECLTYPE_FLOAT3: return 3 * sizeof(float); 697ec681f3Smrg case D3DDECLTYPE_FLOAT4: return 4 * sizeof(float); 707ec681f3Smrg case D3DDECLTYPE_D3DCOLOR: return 1 * sizeof(DWORD); 717ec681f3Smrg case D3DDECLTYPE_UBYTE4: return 4 * sizeof(BYTE); 727ec681f3Smrg case D3DDECLTYPE_SHORT2: return 2 * sizeof(short); 737ec681f3Smrg case D3DDECLTYPE_SHORT4: return 4 * sizeof(short); 747ec681f3Smrg case D3DDECLTYPE_UBYTE4N: return 4 * sizeof(BYTE); 757ec681f3Smrg case D3DDECLTYPE_SHORT2N: return 2 * sizeof(short); 767ec681f3Smrg case D3DDECLTYPE_SHORT4N: return 4 * sizeof(short); 777ec681f3Smrg case D3DDECLTYPE_USHORT2N: return 2 * sizeof(short); 787ec681f3Smrg case D3DDECLTYPE_USHORT4N: return 4 * sizeof(short); 797ec681f3Smrg case D3DDECLTYPE_UDEC3: return 4; 807ec681f3Smrg case D3DDECLTYPE_DEC3N: return 4; 817ec681f3Smrg case D3DDECLTYPE_FLOAT16_2: return 2 * 2; 827ec681f3Smrg case D3DDECLTYPE_FLOAT16_4: return 4 * 2; 837ec681f3Smrg default: 847ec681f3Smrg assert(!"Implementation error !"); 857ec681f3Smrg } 867ec681f3Smrg return 0; 877ec681f3Smrg} 887ec681f3Smrg 897ec681f3Smrg/* Actually, arbitrary usage index values are permitted, but a 907ec681f3Smrg * simple lookup table won't work in that case. Let's just wait 917ec681f3Smrg * with making this more generic until we need it. 927ec681f3Smrg */ 937ec681f3Smrgstatic inline boolean 947ec681f3Smrgnine_d3ddeclusage_check(unsigned usage, unsigned usage_idx) 957ec681f3Smrg{ 967ec681f3Smrg switch (usage) { 977ec681f3Smrg case D3DDECLUSAGE_POSITIONT: 987ec681f3Smrg case D3DDECLUSAGE_TESSFACTOR: 997ec681f3Smrg case D3DDECLUSAGE_DEPTH: 1007ec681f3Smrg case D3DDECLUSAGE_NORMAL: 1017ec681f3Smrg case D3DDECLUSAGE_TANGENT: 1027ec681f3Smrg case D3DDECLUSAGE_BINORMAL: 1037ec681f3Smrg case D3DDECLUSAGE_POSITION: 1047ec681f3Smrg case D3DDECLUSAGE_BLENDWEIGHT: 1057ec681f3Smrg case D3DDECLUSAGE_BLENDINDICES: 1067ec681f3Smrg case D3DDECLUSAGE_COLOR: 1077ec681f3Smrg return TRUE; 1087ec681f3Smrg case D3DDECLUSAGE_PSIZE: 1097ec681f3Smrg case D3DDECLUSAGE_FOG: 1107ec681f3Smrg case D3DDECLUSAGE_SAMPLE: 1117ec681f3Smrg return usage_idx <= 0; 1127ec681f3Smrg case D3DDECLUSAGE_TEXCOORD: 1137ec681f3Smrg return usage_idx <= 15; 1147ec681f3Smrg default: 1157ec681f3Smrg return FALSE; 1167ec681f3Smrg } 1177ec681f3Smrg} 1187ec681f3Smrg 1197ec681f3Smrg#define NINE_DECLUSAGE_CASE0(n) case D3DDECLUSAGE_##n: return NINE_DECLUSAGE_##n 1207ec681f3Smrg#define NINE_DECLUSAGE_CASEi(n) case D3DDECLUSAGE_##n: return NINE_DECLUSAGE_i(n, usage_idx) 1217ec681f3Smrguint16_t 1227ec681f3Smrgnine_d3d9_to_nine_declusage(unsigned usage, unsigned usage_idx) 1237ec681f3Smrg{ 1247ec681f3Smrg if (!nine_d3ddeclusage_check(usage, usage_idx)) 1257ec681f3Smrg ERR("D3DDECLUSAGE_%u[%u]\n",usage,usage_idx); 1267ec681f3Smrg assert(nine_d3ddeclusage_check(usage, usage_idx)); 1277ec681f3Smrg switch (usage) { 1287ec681f3Smrg NINE_DECLUSAGE_CASEi(POSITION); 1297ec681f3Smrg NINE_DECLUSAGE_CASEi(BLENDWEIGHT); 1307ec681f3Smrg NINE_DECLUSAGE_CASEi(BLENDINDICES); 1317ec681f3Smrg NINE_DECLUSAGE_CASEi(NORMAL); 1327ec681f3Smrg NINE_DECLUSAGE_CASE0(PSIZE); 1337ec681f3Smrg NINE_DECLUSAGE_CASEi(TEXCOORD); 1347ec681f3Smrg NINE_DECLUSAGE_CASEi(TANGENT); 1357ec681f3Smrg NINE_DECLUSAGE_CASEi(BINORMAL); 1367ec681f3Smrg NINE_DECLUSAGE_CASE0(TESSFACTOR); 1377ec681f3Smrg NINE_DECLUSAGE_CASEi(POSITIONT); 1387ec681f3Smrg NINE_DECLUSAGE_CASEi(COLOR); 1397ec681f3Smrg NINE_DECLUSAGE_CASE0(DEPTH); 1407ec681f3Smrg NINE_DECLUSAGE_CASE0(FOG); 1417ec681f3Smrg NINE_DECLUSAGE_CASE0(SAMPLE); 1427ec681f3Smrg default: 1437ec681f3Smrg assert(!"Invalid DECLUSAGE."); 1447ec681f3Smrg return NINE_DECLUSAGE_NONE; 1457ec681f3Smrg } 1467ec681f3Smrg} 1477ec681f3Smrg 1487ec681f3Smrgstatic const char *nine_declusage_names[] = 1497ec681f3Smrg{ 1507ec681f3Smrg [NINE_DECLUSAGE_POSITION] = "POSITION", 1517ec681f3Smrg [NINE_DECLUSAGE_BLENDWEIGHT] = "BLENDWEIGHT", 1527ec681f3Smrg [NINE_DECLUSAGE_BLENDINDICES] = "BLENDINDICES", 1537ec681f3Smrg [NINE_DECLUSAGE_NORMAL] = "NORMAL", 1547ec681f3Smrg [NINE_DECLUSAGE_PSIZE] = "PSIZE", 1557ec681f3Smrg [NINE_DECLUSAGE_TEXCOORD] = "TEXCOORD", 1567ec681f3Smrg [NINE_DECLUSAGE_TANGENT] = "TANGENT", 1577ec681f3Smrg [NINE_DECLUSAGE_BINORMAL] = "BINORMAL", 1587ec681f3Smrg [NINE_DECLUSAGE_TESSFACTOR] = "TESSFACTOR", 1597ec681f3Smrg [NINE_DECLUSAGE_POSITIONT] = "POSITIONT", 1607ec681f3Smrg [NINE_DECLUSAGE_COLOR] = "DIFFUSE", 1617ec681f3Smrg [NINE_DECLUSAGE_DEPTH] = "DEPTH", 1627ec681f3Smrg [NINE_DECLUSAGE_FOG] = "FOG", 1637ec681f3Smrg [NINE_DECLUSAGE_NONE] = "(NONE)", 1647ec681f3Smrg}; 1657ec681f3Smrgstatic inline const char * 1667ec681f3Smrgnine_declusage_name(unsigned ndcl) 1677ec681f3Smrg{ 1687ec681f3Smrg return nine_declusage_names[ndcl % NINE_DECLUSAGE_COUNT]; 1697ec681f3Smrg} 1707ec681f3Smrg 1717ec681f3SmrgHRESULT 1727ec681f3SmrgNineVertexDeclaration9_ctor( struct NineVertexDeclaration9 *This, 1737ec681f3Smrg struct NineUnknownParams *pParams, 1747ec681f3Smrg const D3DVERTEXELEMENT9 *pElements ) 1757ec681f3Smrg{ 1767ec681f3Smrg const D3DCAPS9 *caps; 1777ec681f3Smrg unsigned i, nelems; 1787ec681f3Smrg DBG("This=%p pParams=%p pElements=%p\n", This, pParams, pElements); 1797ec681f3Smrg 1807ec681f3Smrg /* wine */ 1817ec681f3Smrg for (nelems = 0; 1827ec681f3Smrg pElements[nelems].Stream != 0xFF; 1837ec681f3Smrg ++nelems) { 1847ec681f3Smrg user_assert(pElements[nelems].Type != D3DDECLTYPE_UNUSED, E_FAIL); 1857ec681f3Smrg user_assert(!(pElements[nelems].Offset & 3), E_FAIL); 1867ec681f3Smrg } 1877ec681f3Smrg 1887ec681f3Smrg caps = NineDevice9_GetCaps(pParams->device); 1897ec681f3Smrg user_assert(nelems <= caps->MaxStreams, D3DERR_INVALIDCALL); 1907ec681f3Smrg 1917ec681f3Smrg HRESULT hr = NineUnknown_ctor(&This->base, pParams); 1927ec681f3Smrg if (FAILED(hr)) { return hr; } 1937ec681f3Smrg 1947ec681f3Smrg This->nelems = nelems; 1957ec681f3Smrg This->decls = CALLOC(This->nelems+1, sizeof(D3DVERTEXELEMENT9)); 1967ec681f3Smrg This->elems = CALLOC(This->nelems, sizeof(struct pipe_vertex_element)); 1977ec681f3Smrg This->usage_map = CALLOC(This->nelems, sizeof(uint16_t)); 1987ec681f3Smrg if (!This->decls || !This->elems || !This->usage_map) { return E_OUTOFMEMORY; } 1997ec681f3Smrg memcpy(This->decls, pElements, sizeof(D3DVERTEXELEMENT9)*(This->nelems+1)); 2007ec681f3Smrg 2017ec681f3Smrg for (i = 0; i < This->nelems; ++i) { 2027ec681f3Smrg uint16_t usage = nine_d3d9_to_nine_declusage(This->decls[i].Usage, 2037ec681f3Smrg This->decls[i].UsageIndex); 2047ec681f3Smrg This->usage_map[i] = usage; 2057ec681f3Smrg 2067ec681f3Smrg if (This->decls[i].Usage == D3DDECLUSAGE_POSITIONT) 2077ec681f3Smrg This->position_t = TRUE; 2087ec681f3Smrg 2097ec681f3Smrg This->elems[i].src_offset = This->decls[i].Offset; 2107ec681f3Smrg This->elems[i].instance_divisor = 0; 2117ec681f3Smrg This->elems[i].vertex_buffer_index = This->decls[i].Stream; 2127ec681f3Smrg This->elems[i].src_format = decltype_format(This->decls[i].Type); 2137ec681f3Smrg This->elems[i].dual_slot = false; 2147ec681f3Smrg /* XXX Remember Method (tesselation), Usage, UsageIndex */ 2157ec681f3Smrg 2167ec681f3Smrg DBG("VERTEXELEMENT[%u]: Stream=%u Offset=%u Type=%s DeclUsage=%s%d\n", i, 2177ec681f3Smrg This->decls[i].Stream, 2187ec681f3Smrg This->decls[i].Offset, 2197ec681f3Smrg util_format_name(This->elems[i].src_format), 2207ec681f3Smrg nine_declusage_name(usage), 2217ec681f3Smrg usage / NINE_DECLUSAGE_COUNT); 2227ec681f3Smrg } 2237ec681f3Smrg 2247ec681f3Smrg return D3D_OK; 2257ec681f3Smrg} 2267ec681f3Smrg 2277ec681f3Smrgvoid 2287ec681f3SmrgNineVertexDeclaration9_dtor( struct NineVertexDeclaration9 *This ) 2297ec681f3Smrg{ 2307ec681f3Smrg DBG("This=%p\n", This); 2317ec681f3Smrg 2327ec681f3Smrg FREE(This->decls); 2337ec681f3Smrg FREE(This->elems); 2347ec681f3Smrg FREE(This->usage_map); 2357ec681f3Smrg 2367ec681f3Smrg NineUnknown_dtor(&This->base); 2377ec681f3Smrg} 2387ec681f3Smrg 2397ec681f3SmrgHRESULT NINE_WINAPI 2407ec681f3SmrgNineVertexDeclaration9_GetDeclaration( struct NineVertexDeclaration9 *This, 2417ec681f3Smrg D3DVERTEXELEMENT9 *pElement, 2427ec681f3Smrg UINT *pNumElements ) 2437ec681f3Smrg{ 2447ec681f3Smrg if (!pElement) { 2457ec681f3Smrg user_assert(pNumElements, D3DERR_INVALIDCALL); 2467ec681f3Smrg *pNumElements = This->nelems+1; 2477ec681f3Smrg return D3D_OK; 2487ec681f3Smrg } 2497ec681f3Smrg if (pNumElements) { *pNumElements = This->nelems+1; } 2507ec681f3Smrg memcpy(pElement, This->decls, sizeof(D3DVERTEXELEMENT9)*(This->nelems+1)); 2517ec681f3Smrg return D3D_OK; 2527ec681f3Smrg} 2537ec681f3Smrg 2547ec681f3SmrgIDirect3DVertexDeclaration9Vtbl NineVertexDeclaration9_vtable = { 2557ec681f3Smrg (void *)NineUnknown_QueryInterface, 2567ec681f3Smrg (void *)NineUnknown_AddRef, 2577ec681f3Smrg (void *)NineUnknown_Release, 2587ec681f3Smrg (void *)NineUnknown_GetDevice, /* actually part of VertexDecl9 iface */ 2597ec681f3Smrg (void *)NineVertexDeclaration9_GetDeclaration 2607ec681f3Smrg}; 2617ec681f3Smrg 2627ec681f3Smrgstatic const GUID *NineVertexDeclaration9_IIDs[] = { 2637ec681f3Smrg &IID_IDirect3DVertexDeclaration9, 2647ec681f3Smrg &IID_IUnknown, 2657ec681f3Smrg NULL 2667ec681f3Smrg}; 2677ec681f3Smrg 2687ec681f3SmrgHRESULT 2697ec681f3SmrgNineVertexDeclaration9_new( struct NineDevice9 *pDevice, 2707ec681f3Smrg const D3DVERTEXELEMENT9 *pElements, 2717ec681f3Smrg struct NineVertexDeclaration9 **ppOut ) 2727ec681f3Smrg{ 2737ec681f3Smrg NINE_DEVICE_CHILD_NEW(VertexDeclaration9, ppOut, /* args */ pDevice, pElements); 2747ec681f3Smrg} 2757ec681f3Smrg 2767ec681f3SmrgHRESULT 2777ec681f3SmrgNineVertexDeclaration9_new_from_fvf( struct NineDevice9 *pDevice, 2787ec681f3Smrg DWORD FVF, 2797ec681f3Smrg struct NineVertexDeclaration9 **ppOut ) 2807ec681f3Smrg{ 2817ec681f3Smrg D3DVERTEXELEMENT9 elems[16], decl_end = D3DDECL_END(); 2827ec681f3Smrg unsigned texcount, i, betas, nelems = 0; 2837ec681f3Smrg BYTE beta_index = 0xFF; 2847ec681f3Smrg 2857ec681f3Smrg switch (FVF & D3DFVF_POSITION_MASK) { 2867ec681f3Smrg case D3DFVF_XYZ: /* simple XYZ */ 2877ec681f3Smrg case D3DFVF_XYZB1: 2887ec681f3Smrg case D3DFVF_XYZB2: 2897ec681f3Smrg case D3DFVF_XYZB3: 2907ec681f3Smrg case D3DFVF_XYZB4: 2917ec681f3Smrg case D3DFVF_XYZB5: /* XYZ with beta values */ 2927ec681f3Smrg elems[nelems].Type = D3DDECLTYPE_FLOAT3; 2937ec681f3Smrg elems[nelems].Usage = D3DDECLUSAGE_POSITION; 2947ec681f3Smrg elems[nelems].UsageIndex = 0; 2957ec681f3Smrg ++nelems; 2967ec681f3Smrg /* simple XYZ has no beta values. break. */ 2977ec681f3Smrg if ((FVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) { break; } 2987ec681f3Smrg 2997ec681f3Smrg betas = (((FVF & D3DFVF_XYZB5)-D3DFVF_XYZB1)>>1)+1; 3007ec681f3Smrg if (FVF & D3DFVF_LASTBETA_D3DCOLOR) { 3017ec681f3Smrg beta_index = D3DDECLTYPE_D3DCOLOR; 3027ec681f3Smrg } else if (FVF & D3DFVF_LASTBETA_UBYTE4) { 3037ec681f3Smrg beta_index = D3DDECLTYPE_UBYTE4; 3047ec681f3Smrg } else if ((FVF & D3DFVF_XYZB5) == D3DFVF_XYZB5) { 3057ec681f3Smrg beta_index = D3DDECLTYPE_FLOAT1; 3067ec681f3Smrg } 3077ec681f3Smrg if (beta_index != 0xFF) { --betas; } 3087ec681f3Smrg 3097ec681f3Smrg if (betas > 0) { 3107ec681f3Smrg switch (betas) { 3117ec681f3Smrg case 1: elems[nelems].Type = D3DDECLTYPE_FLOAT1; break; 3127ec681f3Smrg case 2: elems[nelems].Type = D3DDECLTYPE_FLOAT2; break; 3137ec681f3Smrg case 3: elems[nelems].Type = D3DDECLTYPE_FLOAT3; break; 3147ec681f3Smrg case 4: elems[nelems].Type = D3DDECLTYPE_FLOAT4; break; 3157ec681f3Smrg default: 3167ec681f3Smrg assert(!"Implementation error!"); 3177ec681f3Smrg } 3187ec681f3Smrg elems[nelems].Usage = D3DDECLUSAGE_BLENDWEIGHT; 3197ec681f3Smrg elems[nelems].UsageIndex = 0; 3207ec681f3Smrg ++nelems; 3217ec681f3Smrg } 3227ec681f3Smrg 3237ec681f3Smrg if (beta_index != 0xFF) { 3247ec681f3Smrg elems[nelems].Type = beta_index; 3257ec681f3Smrg elems[nelems].Usage = D3DDECLUSAGE_BLENDINDICES; 3267ec681f3Smrg elems[nelems].UsageIndex = 0; 3277ec681f3Smrg ++nelems; 3287ec681f3Smrg } 3297ec681f3Smrg break; 3307ec681f3Smrg 3317ec681f3Smrg case D3DFVF_XYZW: /* simple XYZW */ 3327ec681f3Smrg case D3DFVF_XYZRHW: /* pretransformed XYZW */ 3337ec681f3Smrg elems[nelems].Type = D3DDECLTYPE_FLOAT4; 3347ec681f3Smrg elems[nelems].Usage = 3357ec681f3Smrg ((FVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZW) ? 3367ec681f3Smrg D3DDECLUSAGE_POSITION : D3DDECLUSAGE_POSITIONT; 3377ec681f3Smrg elems[nelems].UsageIndex = 0; 3387ec681f3Smrg ++nelems; 3397ec681f3Smrg break; 3407ec681f3Smrg 3417ec681f3Smrg default: 3427ec681f3Smrg (void)user_error(!"Position doesn't match any known combination"); 3437ec681f3Smrg } 3447ec681f3Smrg 3457ec681f3Smrg /* normals, psize and colors */ 3467ec681f3Smrg if (FVF & D3DFVF_NORMAL) { 3477ec681f3Smrg elems[nelems].Type = D3DDECLTYPE_FLOAT3; 3487ec681f3Smrg elems[nelems].Usage = D3DDECLUSAGE_NORMAL; 3497ec681f3Smrg elems[nelems].UsageIndex = 0; 3507ec681f3Smrg ++nelems; 3517ec681f3Smrg } 3527ec681f3Smrg if (FVF & D3DFVF_PSIZE) { 3537ec681f3Smrg elems[nelems].Type = D3DDECLTYPE_FLOAT1; 3547ec681f3Smrg elems[nelems].Usage = D3DDECLUSAGE_PSIZE; 3557ec681f3Smrg elems[nelems].UsageIndex = 0; 3567ec681f3Smrg ++nelems; 3577ec681f3Smrg } 3587ec681f3Smrg if (FVF & D3DFVF_DIFFUSE) { 3597ec681f3Smrg elems[nelems].Type = D3DDECLTYPE_D3DCOLOR; 3607ec681f3Smrg elems[nelems].Usage = D3DDECLUSAGE_COLOR; 3617ec681f3Smrg elems[nelems].UsageIndex = 0; 3627ec681f3Smrg ++nelems; 3637ec681f3Smrg } 3647ec681f3Smrg if (FVF & D3DFVF_SPECULAR) { 3657ec681f3Smrg elems[nelems].Type = D3DDECLTYPE_D3DCOLOR; 3667ec681f3Smrg elems[nelems].Usage = D3DDECLUSAGE_COLOR; 3677ec681f3Smrg elems[nelems].UsageIndex = 1; 3687ec681f3Smrg ++nelems; 3697ec681f3Smrg } 3707ec681f3Smrg 3717ec681f3Smrg /* textures */ 3727ec681f3Smrg texcount = (FVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT; 3737ec681f3Smrg if (user_error(texcount <= 8)) { texcount = 8; } 3747ec681f3Smrg 3757ec681f3Smrg for (i = 0; i < texcount; ++i) { 3767ec681f3Smrg switch ((FVF >> (16+i*2)) & 0x3) { 3777ec681f3Smrg case D3DFVF_TEXTUREFORMAT1: 3787ec681f3Smrg elems[nelems].Type = D3DDECLTYPE_FLOAT1; 3797ec681f3Smrg break; 3807ec681f3Smrg 3817ec681f3Smrg case D3DFVF_TEXTUREFORMAT2: 3827ec681f3Smrg elems[nelems].Type = D3DDECLTYPE_FLOAT2; 3837ec681f3Smrg break; 3847ec681f3Smrg 3857ec681f3Smrg case D3DFVF_TEXTUREFORMAT3: 3867ec681f3Smrg elems[nelems].Type = D3DDECLTYPE_FLOAT3; 3877ec681f3Smrg break; 3887ec681f3Smrg 3897ec681f3Smrg case D3DFVF_TEXTUREFORMAT4: 3907ec681f3Smrg elems[nelems].Type = D3DDECLTYPE_FLOAT4; 3917ec681f3Smrg break; 3927ec681f3Smrg 3937ec681f3Smrg default: 3947ec681f3Smrg assert(!"Implementation error!"); 3957ec681f3Smrg } 3967ec681f3Smrg elems[nelems].Usage = D3DDECLUSAGE_TEXCOORD; 3977ec681f3Smrg elems[nelems].UsageIndex = i; 3987ec681f3Smrg ++nelems; 3997ec681f3Smrg } 4007ec681f3Smrg 4017ec681f3Smrg /* fill out remaining data */ 4027ec681f3Smrg for (i = 0; i < nelems; ++i) { 4037ec681f3Smrg elems[i].Stream = 0; 4047ec681f3Smrg elems[i].Offset = (i == 0) ? 0 : (elems[i-1].Offset + 4057ec681f3Smrg decltype_size(elems[i-1].Type)); 4067ec681f3Smrg elems[i].Method = D3DDECLMETHOD_DEFAULT; 4077ec681f3Smrg } 4087ec681f3Smrg elems[nelems++] = decl_end; 4097ec681f3Smrg 4107ec681f3Smrg NINE_DEVICE_CHILD_NEW(VertexDeclaration9, ppOut, /* args */ pDevice, elems); 4117ec681f3Smrg} 4127ec681f3Smrg 4137ec681f3Smrgvoid 4147ec681f3SmrgNineVertexDeclaration9_FillStreamOutputInfo( 4157ec681f3Smrg struct NineVertexDeclaration9 *This, 4167ec681f3Smrg struct nine_vs_output_info *ShaderOutputsInfo, 4177ec681f3Smrg unsigned numOutputs, 4187ec681f3Smrg struct pipe_stream_output_info *so ) 4197ec681f3Smrg{ 4207ec681f3Smrg unsigned so_outputs = 0; 4217ec681f3Smrg int i, j; 4227ec681f3Smrg 4237ec681f3Smrg memset(so, 0, sizeof(struct pipe_stream_output_info)); 4247ec681f3Smrg 4257ec681f3Smrg for (i = 0; i < numOutputs; i++) { 4267ec681f3Smrg BYTE output_semantic = ShaderOutputsInfo[i].output_semantic; 4277ec681f3Smrg unsigned output_semantic_index = ShaderOutputsInfo[i].output_semantic_index; 4287ec681f3Smrg 4297ec681f3Smrg for (j = 0; j < This->nelems; j++) { 4307ec681f3Smrg if ((This->decls[j].Usage == output_semantic || 4317ec681f3Smrg (output_semantic == D3DDECLUSAGE_POSITION && 4327ec681f3Smrg This->decls[j].Usage == D3DDECLUSAGE_POSITIONT)) && 4337ec681f3Smrg This->decls[j].UsageIndex == output_semantic_index) { 4347ec681f3Smrg DBG("Matching %s %d: o%d -> %d\n", 4357ec681f3Smrg nine_declusage_name(nine_d3d9_to_nine_declusage(This->decls[j].Usage, 0)), 4367ec681f3Smrg This->decls[j].UsageIndex, i, j); 4377ec681f3Smrg so->output[so_outputs].register_index = ShaderOutputsInfo[i].output_index; 4387ec681f3Smrg so->output[so_outputs].start_component = 0; 4397ec681f3Smrg if (ShaderOutputsInfo[i].mask & 8) 4407ec681f3Smrg so->output[so_outputs].num_components = 4; 4417ec681f3Smrg else if (ShaderOutputsInfo[i].mask & 4) 4427ec681f3Smrg so->output[so_outputs].num_components = 3; 4437ec681f3Smrg else if (ShaderOutputsInfo[i].mask & 2) 4447ec681f3Smrg so->output[so_outputs].num_components = 2; 4457ec681f3Smrg else 4467ec681f3Smrg so->output[so_outputs].num_components = 1; 4477ec681f3Smrg so->output[so_outputs].output_buffer = 0; 4487ec681f3Smrg so->output[so_outputs].dst_offset = so_outputs * sizeof(float[4])/4; 4497ec681f3Smrg so->output[so_outputs].stream = 0; 4507ec681f3Smrg so_outputs++; 4517ec681f3Smrg break; 4527ec681f3Smrg } 4537ec681f3Smrg } 4547ec681f3Smrg } 4557ec681f3Smrg 4567ec681f3Smrg so->num_outputs = so_outputs; 4577ec681f3Smrg so->stride[0] = so_outputs * sizeof(float[4])/4; 4587ec681f3Smrg} 4597ec681f3Smrg 4607ec681f3Smrg/* ProcessVertices runs stream output into a temporary buffer to capture 4617ec681f3Smrg * all outputs. 4627ec681f3Smrg * Now we have to convert them to the format and order set by the vertex 4637ec681f3Smrg * declaration, for which we use u_translate. 4647ec681f3Smrg * This is necessary if the vertex declaration contains elements using a 4657ec681f3Smrg * non float32 format, because stream output only supports f32/u32/s32. 4667ec681f3Smrg */ 4677ec681f3SmrgHRESULT 4687ec681f3SmrgNineVertexDeclaration9_ConvertStreamOutput( 4697ec681f3Smrg struct NineVertexDeclaration9 *This, 4707ec681f3Smrg struct NineVertexBuffer9 *pDstBuf, 4717ec681f3Smrg UINT DestIndex, 4727ec681f3Smrg UINT VertexCount, 4737ec681f3Smrg void *pSrcBuf, 4747ec681f3Smrg const struct pipe_stream_output_info *so ) 4757ec681f3Smrg{ 4767ec681f3Smrg struct translate *translate; 4777ec681f3Smrg struct translate_key transkey; 4787ec681f3Smrg HRESULT hr; 4797ec681f3Smrg unsigned i; 4807ec681f3Smrg void *dst_map; 4817ec681f3Smrg 4827ec681f3Smrg DBG("This=%p pDstBuf=%p DestIndex=%u VertexCount=%u pSrcBuf=%p so=%p\n", 4837ec681f3Smrg This, pDstBuf, DestIndex, VertexCount, pSrcBuf, so); 4847ec681f3Smrg 4857ec681f3Smrg transkey.output_stride = 0; 4867ec681f3Smrg for (i = 0; i < This->nelems; ++i) { 4877ec681f3Smrg enum pipe_format format; 4887ec681f3Smrg 4897ec681f3Smrg switch (so->output[i].num_components) { 4907ec681f3Smrg case 1: format = PIPE_FORMAT_R32_FLOAT; break; 4917ec681f3Smrg case 2: format = PIPE_FORMAT_R32G32_FLOAT; break; 4927ec681f3Smrg case 3: format = PIPE_FORMAT_R32G32B32_FLOAT; break; 4937ec681f3Smrg default: 4947ec681f3Smrg assert(so->output[i].num_components == 4); 4957ec681f3Smrg format = PIPE_FORMAT_R32G32B32A32_FLOAT; 4967ec681f3Smrg break; 4977ec681f3Smrg } 4987ec681f3Smrg transkey.element[i].type = TRANSLATE_ELEMENT_NORMAL; 4997ec681f3Smrg transkey.element[i].input_format = format; 5007ec681f3Smrg transkey.element[i].input_buffer = 0; 5017ec681f3Smrg transkey.element[i].input_offset = so->output[i].dst_offset * 4; 5027ec681f3Smrg transkey.element[i].instance_divisor = 0; 5037ec681f3Smrg 5047ec681f3Smrg transkey.element[i].output_format = This->elems[i].src_format; 5057ec681f3Smrg transkey.element[i].output_offset = This->elems[i].src_offset; 5067ec681f3Smrg transkey.output_stride += 5077ec681f3Smrg util_format_get_blocksize(This->elems[i].src_format); 5087ec681f3Smrg 5097ec681f3Smrg assert(!(transkey.output_stride & 3)); 5107ec681f3Smrg } 5117ec681f3Smrg transkey.nr_elements = This->nelems; 5127ec681f3Smrg 5137ec681f3Smrg translate = translate_create(&transkey); 5147ec681f3Smrg if (!translate) 5157ec681f3Smrg return E_OUTOFMEMORY; 5167ec681f3Smrg 5177ec681f3Smrg hr = NineVertexBuffer9_Lock(pDstBuf, 5187ec681f3Smrg transkey.output_stride * DestIndex, 5197ec681f3Smrg transkey.output_stride * VertexCount, 5207ec681f3Smrg &dst_map, D3DLOCK_DISCARD); 5217ec681f3Smrg if (FAILED(hr)) 5227ec681f3Smrg goto out; 5237ec681f3Smrg 5247ec681f3Smrg translate->set_buffer(translate, 0, pSrcBuf, so->stride[0] * 4, ~0); 5257ec681f3Smrg 5267ec681f3Smrg translate->run(translate, 0, VertexCount, 0, 0, dst_map); 5277ec681f3Smrg 5287ec681f3Smrg NineVertexBuffer9_Unlock(pDstBuf); 5297ec681f3Smrgout: 5307ec681f3Smrg translate->release(translate); /* TODO: cache these */ 5317ec681f3Smrg return hr; 5327ec681f3Smrg} 533