1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2011 Joakim Sindholt <opensource@zhasha.com> 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub 8bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom 9bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 19bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 20bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 21bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. */ 22bf215546Sopenharmony_ci 23bf215546Sopenharmony_ci#include "vertexdeclaration9.h" 24bf215546Sopenharmony_ci#include "vertexbuffer9.h" 25bf215546Sopenharmony_ci#include "device9.h" 26bf215546Sopenharmony_ci#include "nine_helpers.h" 27bf215546Sopenharmony_ci#include "nine_shader.h" 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_ci#include "pipe/p_format.h" 30bf215546Sopenharmony_ci#include "pipe/p_context.h" 31bf215546Sopenharmony_ci#include "util/u_math.h" 32bf215546Sopenharmony_ci#include "util/format/u_format.h" 33bf215546Sopenharmony_ci#include "translate/translate.h" 34bf215546Sopenharmony_ci 35bf215546Sopenharmony_ci#define DBG_CHANNEL DBG_VERTEXDECLARATION 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_cistatic inline enum pipe_format decltype_format(BYTE type) 38bf215546Sopenharmony_ci{ 39bf215546Sopenharmony_ci switch (type) { 40bf215546Sopenharmony_ci case D3DDECLTYPE_FLOAT1: return PIPE_FORMAT_R32_FLOAT; 41bf215546Sopenharmony_ci case D3DDECLTYPE_FLOAT2: return PIPE_FORMAT_R32G32_FLOAT; 42bf215546Sopenharmony_ci case D3DDECLTYPE_FLOAT3: return PIPE_FORMAT_R32G32B32_FLOAT; 43bf215546Sopenharmony_ci case D3DDECLTYPE_FLOAT4: return PIPE_FORMAT_R32G32B32A32_FLOAT; 44bf215546Sopenharmony_ci case D3DDECLTYPE_D3DCOLOR: return PIPE_FORMAT_B8G8R8A8_UNORM; 45bf215546Sopenharmony_ci case D3DDECLTYPE_UBYTE4: return PIPE_FORMAT_R8G8B8A8_USCALED; 46bf215546Sopenharmony_ci case D3DDECLTYPE_SHORT2: return PIPE_FORMAT_R16G16_SSCALED; 47bf215546Sopenharmony_ci case D3DDECLTYPE_SHORT4: return PIPE_FORMAT_R16G16B16A16_SSCALED; 48bf215546Sopenharmony_ci case D3DDECLTYPE_UBYTE4N: return PIPE_FORMAT_R8G8B8A8_UNORM; 49bf215546Sopenharmony_ci case D3DDECLTYPE_SHORT2N: return PIPE_FORMAT_R16G16_SNORM; 50bf215546Sopenharmony_ci case D3DDECLTYPE_SHORT4N: return PIPE_FORMAT_R16G16B16A16_SNORM; 51bf215546Sopenharmony_ci case D3DDECLTYPE_USHORT2N: return PIPE_FORMAT_R16G16_UNORM; 52bf215546Sopenharmony_ci case D3DDECLTYPE_USHORT4N: return PIPE_FORMAT_R16G16B16A16_UNORM; 53bf215546Sopenharmony_ci case D3DDECLTYPE_UDEC3: return PIPE_FORMAT_R10G10B10X2_USCALED; 54bf215546Sopenharmony_ci case D3DDECLTYPE_DEC3N: return PIPE_FORMAT_R10G10B10X2_SNORM; 55bf215546Sopenharmony_ci case D3DDECLTYPE_FLOAT16_2: return PIPE_FORMAT_R16G16_FLOAT; 56bf215546Sopenharmony_ci case D3DDECLTYPE_FLOAT16_4: return PIPE_FORMAT_R16G16B16A16_FLOAT; 57bf215546Sopenharmony_ci default: 58bf215546Sopenharmony_ci assert(!"Implementation error !"); 59bf215546Sopenharmony_ci } 60bf215546Sopenharmony_ci return PIPE_FORMAT_NONE; 61bf215546Sopenharmony_ci} 62bf215546Sopenharmony_ci 63bf215546Sopenharmony_cistatic inline unsigned decltype_size(BYTE type) 64bf215546Sopenharmony_ci{ 65bf215546Sopenharmony_ci switch (type) { 66bf215546Sopenharmony_ci case D3DDECLTYPE_FLOAT1: return 1 * sizeof(float); 67bf215546Sopenharmony_ci case D3DDECLTYPE_FLOAT2: return 2 * sizeof(float); 68bf215546Sopenharmony_ci case D3DDECLTYPE_FLOAT3: return 3 * sizeof(float); 69bf215546Sopenharmony_ci case D3DDECLTYPE_FLOAT4: return 4 * sizeof(float); 70bf215546Sopenharmony_ci case D3DDECLTYPE_D3DCOLOR: return 1 * sizeof(DWORD); 71bf215546Sopenharmony_ci case D3DDECLTYPE_UBYTE4: return 4 * sizeof(BYTE); 72bf215546Sopenharmony_ci case D3DDECLTYPE_SHORT2: return 2 * sizeof(short); 73bf215546Sopenharmony_ci case D3DDECLTYPE_SHORT4: return 4 * sizeof(short); 74bf215546Sopenharmony_ci case D3DDECLTYPE_UBYTE4N: return 4 * sizeof(BYTE); 75bf215546Sopenharmony_ci case D3DDECLTYPE_SHORT2N: return 2 * sizeof(short); 76bf215546Sopenharmony_ci case D3DDECLTYPE_SHORT4N: return 4 * sizeof(short); 77bf215546Sopenharmony_ci case D3DDECLTYPE_USHORT2N: return 2 * sizeof(short); 78bf215546Sopenharmony_ci case D3DDECLTYPE_USHORT4N: return 4 * sizeof(short); 79bf215546Sopenharmony_ci case D3DDECLTYPE_UDEC3: return 4; 80bf215546Sopenharmony_ci case D3DDECLTYPE_DEC3N: return 4; 81bf215546Sopenharmony_ci case D3DDECLTYPE_FLOAT16_2: return 2 * 2; 82bf215546Sopenharmony_ci case D3DDECLTYPE_FLOAT16_4: return 4 * 2; 83bf215546Sopenharmony_ci default: 84bf215546Sopenharmony_ci assert(!"Implementation error !"); 85bf215546Sopenharmony_ci } 86bf215546Sopenharmony_ci return 0; 87bf215546Sopenharmony_ci} 88bf215546Sopenharmony_ci 89bf215546Sopenharmony_ci/* Actually, arbitrary usage index values are permitted, but a 90bf215546Sopenharmony_ci * simple lookup table won't work in that case. Let's just wait 91bf215546Sopenharmony_ci * with making this more generic until we need it. 92bf215546Sopenharmony_ci */ 93bf215546Sopenharmony_cistatic inline boolean 94bf215546Sopenharmony_cinine_d3ddeclusage_check(unsigned usage, unsigned usage_idx) 95bf215546Sopenharmony_ci{ 96bf215546Sopenharmony_ci switch (usage) { 97bf215546Sopenharmony_ci case D3DDECLUSAGE_POSITIONT: 98bf215546Sopenharmony_ci case D3DDECLUSAGE_TESSFACTOR: 99bf215546Sopenharmony_ci case D3DDECLUSAGE_DEPTH: 100bf215546Sopenharmony_ci case D3DDECLUSAGE_NORMAL: 101bf215546Sopenharmony_ci case D3DDECLUSAGE_TANGENT: 102bf215546Sopenharmony_ci case D3DDECLUSAGE_BINORMAL: 103bf215546Sopenharmony_ci case D3DDECLUSAGE_POSITION: 104bf215546Sopenharmony_ci case D3DDECLUSAGE_BLENDWEIGHT: 105bf215546Sopenharmony_ci case D3DDECLUSAGE_BLENDINDICES: 106bf215546Sopenharmony_ci case D3DDECLUSAGE_COLOR: 107bf215546Sopenharmony_ci return TRUE; 108bf215546Sopenharmony_ci case D3DDECLUSAGE_PSIZE: 109bf215546Sopenharmony_ci case D3DDECLUSAGE_FOG: 110bf215546Sopenharmony_ci case D3DDECLUSAGE_SAMPLE: 111bf215546Sopenharmony_ci return usage_idx <= 0; 112bf215546Sopenharmony_ci case D3DDECLUSAGE_TEXCOORD: 113bf215546Sopenharmony_ci return usage_idx <= 15; 114bf215546Sopenharmony_ci default: 115bf215546Sopenharmony_ci return FALSE; 116bf215546Sopenharmony_ci } 117bf215546Sopenharmony_ci} 118bf215546Sopenharmony_ci 119bf215546Sopenharmony_ci#define NINE_DECLUSAGE_CASE0(n) case D3DDECLUSAGE_##n: return NINE_DECLUSAGE_##n 120bf215546Sopenharmony_ci#define NINE_DECLUSAGE_CASEi(n) case D3DDECLUSAGE_##n: return NINE_DECLUSAGE_i(n, usage_idx) 121bf215546Sopenharmony_ciuint16_t 122bf215546Sopenharmony_cinine_d3d9_to_nine_declusage(unsigned usage, unsigned usage_idx) 123bf215546Sopenharmony_ci{ 124bf215546Sopenharmony_ci if (!nine_d3ddeclusage_check(usage, usage_idx)) 125bf215546Sopenharmony_ci ERR("D3DDECLUSAGE_%u[%u]\n",usage,usage_idx); 126bf215546Sopenharmony_ci assert(nine_d3ddeclusage_check(usage, usage_idx)); 127bf215546Sopenharmony_ci switch (usage) { 128bf215546Sopenharmony_ci NINE_DECLUSAGE_CASEi(POSITION); 129bf215546Sopenharmony_ci NINE_DECLUSAGE_CASEi(BLENDWEIGHT); 130bf215546Sopenharmony_ci NINE_DECLUSAGE_CASEi(BLENDINDICES); 131bf215546Sopenharmony_ci NINE_DECLUSAGE_CASEi(NORMAL); 132bf215546Sopenharmony_ci NINE_DECLUSAGE_CASE0(PSIZE); 133bf215546Sopenharmony_ci NINE_DECLUSAGE_CASEi(TEXCOORD); 134bf215546Sopenharmony_ci NINE_DECLUSAGE_CASEi(TANGENT); 135bf215546Sopenharmony_ci NINE_DECLUSAGE_CASEi(BINORMAL); 136bf215546Sopenharmony_ci NINE_DECLUSAGE_CASE0(TESSFACTOR); 137bf215546Sopenharmony_ci NINE_DECLUSAGE_CASEi(POSITIONT); 138bf215546Sopenharmony_ci NINE_DECLUSAGE_CASEi(COLOR); 139bf215546Sopenharmony_ci NINE_DECLUSAGE_CASE0(DEPTH); 140bf215546Sopenharmony_ci NINE_DECLUSAGE_CASE0(FOG); 141bf215546Sopenharmony_ci NINE_DECLUSAGE_CASE0(SAMPLE); 142bf215546Sopenharmony_ci default: 143bf215546Sopenharmony_ci assert(!"Invalid DECLUSAGE."); 144bf215546Sopenharmony_ci return NINE_DECLUSAGE_NONE; 145bf215546Sopenharmony_ci } 146bf215546Sopenharmony_ci} 147bf215546Sopenharmony_ci 148bf215546Sopenharmony_cistatic const char *nine_declusage_names[] = 149bf215546Sopenharmony_ci{ 150bf215546Sopenharmony_ci [NINE_DECLUSAGE_POSITION] = "POSITION", 151bf215546Sopenharmony_ci [NINE_DECLUSAGE_BLENDWEIGHT] = "BLENDWEIGHT", 152bf215546Sopenharmony_ci [NINE_DECLUSAGE_BLENDINDICES] = "BLENDINDICES", 153bf215546Sopenharmony_ci [NINE_DECLUSAGE_NORMAL] = "NORMAL", 154bf215546Sopenharmony_ci [NINE_DECLUSAGE_PSIZE] = "PSIZE", 155bf215546Sopenharmony_ci [NINE_DECLUSAGE_TEXCOORD] = "TEXCOORD", 156bf215546Sopenharmony_ci [NINE_DECLUSAGE_TANGENT] = "TANGENT", 157bf215546Sopenharmony_ci [NINE_DECLUSAGE_BINORMAL] = "BINORMAL", 158bf215546Sopenharmony_ci [NINE_DECLUSAGE_TESSFACTOR] = "TESSFACTOR", 159bf215546Sopenharmony_ci [NINE_DECLUSAGE_POSITIONT] = "POSITIONT", 160bf215546Sopenharmony_ci [NINE_DECLUSAGE_COLOR] = "DIFFUSE", 161bf215546Sopenharmony_ci [NINE_DECLUSAGE_DEPTH] = "DEPTH", 162bf215546Sopenharmony_ci [NINE_DECLUSAGE_FOG] = "FOG", 163bf215546Sopenharmony_ci [NINE_DECLUSAGE_NONE] = "(NONE)", 164bf215546Sopenharmony_ci}; 165bf215546Sopenharmony_cistatic inline const char * 166bf215546Sopenharmony_cinine_declusage_name(unsigned ndcl) 167bf215546Sopenharmony_ci{ 168bf215546Sopenharmony_ci return nine_declusage_names[ndcl % NINE_DECLUSAGE_COUNT]; 169bf215546Sopenharmony_ci} 170bf215546Sopenharmony_ci 171bf215546Sopenharmony_ciHRESULT 172bf215546Sopenharmony_ciNineVertexDeclaration9_ctor( struct NineVertexDeclaration9 *This, 173bf215546Sopenharmony_ci struct NineUnknownParams *pParams, 174bf215546Sopenharmony_ci const D3DVERTEXELEMENT9 *pElements ) 175bf215546Sopenharmony_ci{ 176bf215546Sopenharmony_ci const D3DCAPS9 *caps; 177bf215546Sopenharmony_ci unsigned i, nelems; 178bf215546Sopenharmony_ci DBG("This=%p pParams=%p pElements=%p\n", This, pParams, pElements); 179bf215546Sopenharmony_ci 180bf215546Sopenharmony_ci /* wine */ 181bf215546Sopenharmony_ci for (nelems = 0; 182bf215546Sopenharmony_ci pElements[nelems].Stream != 0xFF; 183bf215546Sopenharmony_ci ++nelems) { 184bf215546Sopenharmony_ci user_assert(pElements[nelems].Type != D3DDECLTYPE_UNUSED, E_FAIL); 185bf215546Sopenharmony_ci user_assert(!(pElements[nelems].Offset & 3), E_FAIL); 186bf215546Sopenharmony_ci } 187bf215546Sopenharmony_ci 188bf215546Sopenharmony_ci caps = NineDevice9_GetCaps(pParams->device); 189bf215546Sopenharmony_ci user_assert(nelems <= caps->MaxStreams, D3DERR_INVALIDCALL); 190bf215546Sopenharmony_ci 191bf215546Sopenharmony_ci HRESULT hr = NineUnknown_ctor(&This->base, pParams); 192bf215546Sopenharmony_ci if (FAILED(hr)) { return hr; } 193bf215546Sopenharmony_ci 194bf215546Sopenharmony_ci This->nelems = nelems; 195bf215546Sopenharmony_ci This->decls = CALLOC(This->nelems+1, sizeof(D3DVERTEXELEMENT9)); 196bf215546Sopenharmony_ci This->elems = CALLOC(This->nelems, sizeof(struct pipe_vertex_element)); 197bf215546Sopenharmony_ci This->usage_map = CALLOC(This->nelems, sizeof(uint16_t)); 198bf215546Sopenharmony_ci if (!This->decls || !This->elems || !This->usage_map) { return E_OUTOFMEMORY; } 199bf215546Sopenharmony_ci memcpy(This->decls, pElements, sizeof(D3DVERTEXELEMENT9)*(This->nelems+1)); 200bf215546Sopenharmony_ci 201bf215546Sopenharmony_ci for (i = 0; i < This->nelems; ++i) { 202bf215546Sopenharmony_ci uint16_t usage = nine_d3d9_to_nine_declusage(This->decls[i].Usage, 203bf215546Sopenharmony_ci This->decls[i].UsageIndex); 204bf215546Sopenharmony_ci This->usage_map[i] = usage; 205bf215546Sopenharmony_ci 206bf215546Sopenharmony_ci if (This->decls[i].Usage == D3DDECLUSAGE_POSITIONT) 207bf215546Sopenharmony_ci This->position_t = TRUE; 208bf215546Sopenharmony_ci 209bf215546Sopenharmony_ci This->elems[i].src_offset = This->decls[i].Offset; 210bf215546Sopenharmony_ci This->elems[i].instance_divisor = 0; 211bf215546Sopenharmony_ci This->elems[i].vertex_buffer_index = This->decls[i].Stream; 212bf215546Sopenharmony_ci This->elems[i].src_format = decltype_format(This->decls[i].Type); 213bf215546Sopenharmony_ci This->elems[i].dual_slot = false; 214bf215546Sopenharmony_ci /* XXX Remember Method (tesselation), Usage, UsageIndex */ 215bf215546Sopenharmony_ci 216bf215546Sopenharmony_ci DBG("VERTEXELEMENT[%u]: Stream=%u Offset=%u Type=%s DeclUsage=%s%d\n", i, 217bf215546Sopenharmony_ci This->decls[i].Stream, 218bf215546Sopenharmony_ci This->decls[i].Offset, 219bf215546Sopenharmony_ci util_format_name(This->elems[i].src_format), 220bf215546Sopenharmony_ci nine_declusage_name(usage), 221bf215546Sopenharmony_ci usage / NINE_DECLUSAGE_COUNT); 222bf215546Sopenharmony_ci } 223bf215546Sopenharmony_ci 224bf215546Sopenharmony_ci return D3D_OK; 225bf215546Sopenharmony_ci} 226bf215546Sopenharmony_ci 227bf215546Sopenharmony_civoid 228bf215546Sopenharmony_ciNineVertexDeclaration9_dtor( struct NineVertexDeclaration9 *This ) 229bf215546Sopenharmony_ci{ 230bf215546Sopenharmony_ci DBG("This=%p\n", This); 231bf215546Sopenharmony_ci 232bf215546Sopenharmony_ci FREE(This->decls); 233bf215546Sopenharmony_ci FREE(This->elems); 234bf215546Sopenharmony_ci FREE(This->usage_map); 235bf215546Sopenharmony_ci 236bf215546Sopenharmony_ci NineUnknown_dtor(&This->base); 237bf215546Sopenharmony_ci} 238bf215546Sopenharmony_ci 239bf215546Sopenharmony_ciHRESULT NINE_WINAPI 240bf215546Sopenharmony_ciNineVertexDeclaration9_GetDeclaration( struct NineVertexDeclaration9 *This, 241bf215546Sopenharmony_ci D3DVERTEXELEMENT9 *pElement, 242bf215546Sopenharmony_ci UINT *pNumElements ) 243bf215546Sopenharmony_ci{ 244bf215546Sopenharmony_ci if (!pElement) { 245bf215546Sopenharmony_ci user_assert(pNumElements, D3DERR_INVALIDCALL); 246bf215546Sopenharmony_ci *pNumElements = This->nelems+1; 247bf215546Sopenharmony_ci return D3D_OK; 248bf215546Sopenharmony_ci } 249bf215546Sopenharmony_ci if (pNumElements) { *pNumElements = This->nelems+1; } 250bf215546Sopenharmony_ci memcpy(pElement, This->decls, sizeof(D3DVERTEXELEMENT9)*(This->nelems+1)); 251bf215546Sopenharmony_ci return D3D_OK; 252bf215546Sopenharmony_ci} 253bf215546Sopenharmony_ci 254bf215546Sopenharmony_ciIDirect3DVertexDeclaration9Vtbl NineVertexDeclaration9_vtable = { 255bf215546Sopenharmony_ci (void *)NineUnknown_QueryInterface, 256bf215546Sopenharmony_ci (void *)NineUnknown_AddRef, 257bf215546Sopenharmony_ci (void *)NineUnknown_Release, 258bf215546Sopenharmony_ci (void *)NineUnknown_GetDevice, /* actually part of VertexDecl9 iface */ 259bf215546Sopenharmony_ci (void *)NineVertexDeclaration9_GetDeclaration 260bf215546Sopenharmony_ci}; 261bf215546Sopenharmony_ci 262bf215546Sopenharmony_cistatic const GUID *NineVertexDeclaration9_IIDs[] = { 263bf215546Sopenharmony_ci &IID_IDirect3DVertexDeclaration9, 264bf215546Sopenharmony_ci &IID_IUnknown, 265bf215546Sopenharmony_ci NULL 266bf215546Sopenharmony_ci}; 267bf215546Sopenharmony_ci 268bf215546Sopenharmony_ciHRESULT 269bf215546Sopenharmony_ciNineVertexDeclaration9_new( struct NineDevice9 *pDevice, 270bf215546Sopenharmony_ci const D3DVERTEXELEMENT9 *pElements, 271bf215546Sopenharmony_ci struct NineVertexDeclaration9 **ppOut ) 272bf215546Sopenharmony_ci{ 273bf215546Sopenharmony_ci NINE_DEVICE_CHILD_NEW(VertexDeclaration9, ppOut, /* args */ pDevice, pElements); 274bf215546Sopenharmony_ci} 275bf215546Sopenharmony_ci 276bf215546Sopenharmony_ciHRESULT 277bf215546Sopenharmony_ciNineVertexDeclaration9_new_from_fvf( struct NineDevice9 *pDevice, 278bf215546Sopenharmony_ci DWORD FVF, 279bf215546Sopenharmony_ci struct NineVertexDeclaration9 **ppOut ) 280bf215546Sopenharmony_ci{ 281bf215546Sopenharmony_ci D3DVERTEXELEMENT9 elems[16], decl_end = D3DDECL_END(); 282bf215546Sopenharmony_ci unsigned texcount, i, betas, nelems = 0; 283bf215546Sopenharmony_ci BYTE beta_index = 0xFF; 284bf215546Sopenharmony_ci 285bf215546Sopenharmony_ci switch (FVF & D3DFVF_POSITION_MASK) { 286bf215546Sopenharmony_ci case D3DFVF_XYZ: /* simple XYZ */ 287bf215546Sopenharmony_ci case D3DFVF_XYZB1: 288bf215546Sopenharmony_ci case D3DFVF_XYZB2: 289bf215546Sopenharmony_ci case D3DFVF_XYZB3: 290bf215546Sopenharmony_ci case D3DFVF_XYZB4: 291bf215546Sopenharmony_ci case D3DFVF_XYZB5: /* XYZ with beta values */ 292bf215546Sopenharmony_ci elems[nelems].Type = D3DDECLTYPE_FLOAT3; 293bf215546Sopenharmony_ci elems[nelems].Usage = D3DDECLUSAGE_POSITION; 294bf215546Sopenharmony_ci elems[nelems].UsageIndex = 0; 295bf215546Sopenharmony_ci ++nelems; 296bf215546Sopenharmony_ci /* simple XYZ has no beta values. break. */ 297bf215546Sopenharmony_ci if ((FVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) { break; } 298bf215546Sopenharmony_ci 299bf215546Sopenharmony_ci betas = (((FVF & D3DFVF_XYZB5)-D3DFVF_XYZB1)>>1)+1; 300bf215546Sopenharmony_ci if (FVF & D3DFVF_LASTBETA_D3DCOLOR) { 301bf215546Sopenharmony_ci beta_index = D3DDECLTYPE_D3DCOLOR; 302bf215546Sopenharmony_ci } else if (FVF & D3DFVF_LASTBETA_UBYTE4) { 303bf215546Sopenharmony_ci beta_index = D3DDECLTYPE_UBYTE4; 304bf215546Sopenharmony_ci } else if ((FVF & D3DFVF_XYZB5) == D3DFVF_XYZB5) { 305bf215546Sopenharmony_ci beta_index = D3DDECLTYPE_FLOAT1; 306bf215546Sopenharmony_ci } 307bf215546Sopenharmony_ci if (beta_index != 0xFF) { --betas; } 308bf215546Sopenharmony_ci 309bf215546Sopenharmony_ci if (betas > 0) { 310bf215546Sopenharmony_ci switch (betas) { 311bf215546Sopenharmony_ci case 1: elems[nelems].Type = D3DDECLTYPE_FLOAT1; break; 312bf215546Sopenharmony_ci case 2: elems[nelems].Type = D3DDECLTYPE_FLOAT2; break; 313bf215546Sopenharmony_ci case 3: elems[nelems].Type = D3DDECLTYPE_FLOAT3; break; 314bf215546Sopenharmony_ci case 4: elems[nelems].Type = D3DDECLTYPE_FLOAT4; break; 315bf215546Sopenharmony_ci default: 316bf215546Sopenharmony_ci assert(!"Implementation error!"); 317bf215546Sopenharmony_ci } 318bf215546Sopenharmony_ci elems[nelems].Usage = D3DDECLUSAGE_BLENDWEIGHT; 319bf215546Sopenharmony_ci elems[nelems].UsageIndex = 0; 320bf215546Sopenharmony_ci ++nelems; 321bf215546Sopenharmony_ci } 322bf215546Sopenharmony_ci 323bf215546Sopenharmony_ci if (beta_index != 0xFF) { 324bf215546Sopenharmony_ci elems[nelems].Type = beta_index; 325bf215546Sopenharmony_ci elems[nelems].Usage = D3DDECLUSAGE_BLENDINDICES; 326bf215546Sopenharmony_ci elems[nelems].UsageIndex = 0; 327bf215546Sopenharmony_ci ++nelems; 328bf215546Sopenharmony_ci } 329bf215546Sopenharmony_ci break; 330bf215546Sopenharmony_ci 331bf215546Sopenharmony_ci case D3DFVF_XYZW: /* simple XYZW */ 332bf215546Sopenharmony_ci case D3DFVF_XYZRHW: /* pretransformed XYZW */ 333bf215546Sopenharmony_ci elems[nelems].Type = D3DDECLTYPE_FLOAT4; 334bf215546Sopenharmony_ci elems[nelems].Usage = 335bf215546Sopenharmony_ci ((FVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZW) ? 336bf215546Sopenharmony_ci D3DDECLUSAGE_POSITION : D3DDECLUSAGE_POSITIONT; 337bf215546Sopenharmony_ci elems[nelems].UsageIndex = 0; 338bf215546Sopenharmony_ci ++nelems; 339bf215546Sopenharmony_ci break; 340bf215546Sopenharmony_ci 341bf215546Sopenharmony_ci default: 342bf215546Sopenharmony_ci (void)user_error(!"Position doesn't match any known combination"); 343bf215546Sopenharmony_ci } 344bf215546Sopenharmony_ci 345bf215546Sopenharmony_ci /* normals, psize and colors */ 346bf215546Sopenharmony_ci if (FVF & D3DFVF_NORMAL) { 347bf215546Sopenharmony_ci elems[nelems].Type = D3DDECLTYPE_FLOAT3; 348bf215546Sopenharmony_ci elems[nelems].Usage = D3DDECLUSAGE_NORMAL; 349bf215546Sopenharmony_ci elems[nelems].UsageIndex = 0; 350bf215546Sopenharmony_ci ++nelems; 351bf215546Sopenharmony_ci } 352bf215546Sopenharmony_ci if (FVF & D3DFVF_PSIZE) { 353bf215546Sopenharmony_ci elems[nelems].Type = D3DDECLTYPE_FLOAT1; 354bf215546Sopenharmony_ci elems[nelems].Usage = D3DDECLUSAGE_PSIZE; 355bf215546Sopenharmony_ci elems[nelems].UsageIndex = 0; 356bf215546Sopenharmony_ci ++nelems; 357bf215546Sopenharmony_ci } 358bf215546Sopenharmony_ci if (FVF & D3DFVF_DIFFUSE) { 359bf215546Sopenharmony_ci elems[nelems].Type = D3DDECLTYPE_D3DCOLOR; 360bf215546Sopenharmony_ci elems[nelems].Usage = D3DDECLUSAGE_COLOR; 361bf215546Sopenharmony_ci elems[nelems].UsageIndex = 0; 362bf215546Sopenharmony_ci ++nelems; 363bf215546Sopenharmony_ci } 364bf215546Sopenharmony_ci if (FVF & D3DFVF_SPECULAR) { 365bf215546Sopenharmony_ci elems[nelems].Type = D3DDECLTYPE_D3DCOLOR; 366bf215546Sopenharmony_ci elems[nelems].Usage = D3DDECLUSAGE_COLOR; 367bf215546Sopenharmony_ci elems[nelems].UsageIndex = 1; 368bf215546Sopenharmony_ci ++nelems; 369bf215546Sopenharmony_ci } 370bf215546Sopenharmony_ci 371bf215546Sopenharmony_ci /* textures */ 372bf215546Sopenharmony_ci texcount = (FVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT; 373bf215546Sopenharmony_ci if (user_error(texcount <= 8)) { texcount = 8; } 374bf215546Sopenharmony_ci 375bf215546Sopenharmony_ci for (i = 0; i < texcount; ++i) { 376bf215546Sopenharmony_ci switch ((FVF >> (16+i*2)) & 0x3) { 377bf215546Sopenharmony_ci case D3DFVF_TEXTUREFORMAT1: 378bf215546Sopenharmony_ci elems[nelems].Type = D3DDECLTYPE_FLOAT1; 379bf215546Sopenharmony_ci break; 380bf215546Sopenharmony_ci 381bf215546Sopenharmony_ci case D3DFVF_TEXTUREFORMAT2: 382bf215546Sopenharmony_ci elems[nelems].Type = D3DDECLTYPE_FLOAT2; 383bf215546Sopenharmony_ci break; 384bf215546Sopenharmony_ci 385bf215546Sopenharmony_ci case D3DFVF_TEXTUREFORMAT3: 386bf215546Sopenharmony_ci elems[nelems].Type = D3DDECLTYPE_FLOAT3; 387bf215546Sopenharmony_ci break; 388bf215546Sopenharmony_ci 389bf215546Sopenharmony_ci case D3DFVF_TEXTUREFORMAT4: 390bf215546Sopenharmony_ci elems[nelems].Type = D3DDECLTYPE_FLOAT4; 391bf215546Sopenharmony_ci break; 392bf215546Sopenharmony_ci 393bf215546Sopenharmony_ci default: 394bf215546Sopenharmony_ci assert(!"Implementation error!"); 395bf215546Sopenharmony_ci } 396bf215546Sopenharmony_ci elems[nelems].Usage = D3DDECLUSAGE_TEXCOORD; 397bf215546Sopenharmony_ci elems[nelems].UsageIndex = i; 398bf215546Sopenharmony_ci ++nelems; 399bf215546Sopenharmony_ci } 400bf215546Sopenharmony_ci 401bf215546Sopenharmony_ci /* fill out remaining data */ 402bf215546Sopenharmony_ci for (i = 0; i < nelems; ++i) { 403bf215546Sopenharmony_ci elems[i].Stream = 0; 404bf215546Sopenharmony_ci elems[i].Offset = (i == 0) ? 0 : (elems[i-1].Offset + 405bf215546Sopenharmony_ci decltype_size(elems[i-1].Type)); 406bf215546Sopenharmony_ci elems[i].Method = D3DDECLMETHOD_DEFAULT; 407bf215546Sopenharmony_ci } 408bf215546Sopenharmony_ci elems[nelems++] = decl_end; 409bf215546Sopenharmony_ci 410bf215546Sopenharmony_ci NINE_DEVICE_CHILD_NEW(VertexDeclaration9, ppOut, /* args */ pDevice, elems); 411bf215546Sopenharmony_ci} 412bf215546Sopenharmony_ci 413bf215546Sopenharmony_civoid 414bf215546Sopenharmony_ciNineVertexDeclaration9_FillStreamOutputInfo( 415bf215546Sopenharmony_ci struct NineVertexDeclaration9 *This, 416bf215546Sopenharmony_ci struct nine_vs_output_info *ShaderOutputsInfo, 417bf215546Sopenharmony_ci unsigned numOutputs, 418bf215546Sopenharmony_ci struct pipe_stream_output_info *so ) 419bf215546Sopenharmony_ci{ 420bf215546Sopenharmony_ci unsigned so_outputs = 0; 421bf215546Sopenharmony_ci int i, j; 422bf215546Sopenharmony_ci 423bf215546Sopenharmony_ci memset(so, 0, sizeof(struct pipe_stream_output_info)); 424bf215546Sopenharmony_ci 425bf215546Sopenharmony_ci for (i = 0; i < numOutputs; i++) { 426bf215546Sopenharmony_ci BYTE output_semantic = ShaderOutputsInfo[i].output_semantic; 427bf215546Sopenharmony_ci unsigned output_semantic_index = ShaderOutputsInfo[i].output_semantic_index; 428bf215546Sopenharmony_ci 429bf215546Sopenharmony_ci for (j = 0; j < This->nelems; j++) { 430bf215546Sopenharmony_ci if ((This->decls[j].Usage == output_semantic || 431bf215546Sopenharmony_ci (output_semantic == D3DDECLUSAGE_POSITION && 432bf215546Sopenharmony_ci This->decls[j].Usage == D3DDECLUSAGE_POSITIONT)) && 433bf215546Sopenharmony_ci This->decls[j].UsageIndex == output_semantic_index) { 434bf215546Sopenharmony_ci DBG("Matching %s %d: o%d -> %d\n", 435bf215546Sopenharmony_ci nine_declusage_name(nine_d3d9_to_nine_declusage(This->decls[j].Usage, 0)), 436bf215546Sopenharmony_ci This->decls[j].UsageIndex, i, j); 437bf215546Sopenharmony_ci so->output[so_outputs].register_index = ShaderOutputsInfo[i].output_index; 438bf215546Sopenharmony_ci so->output[so_outputs].start_component = 0; 439bf215546Sopenharmony_ci if (ShaderOutputsInfo[i].mask & 8) 440bf215546Sopenharmony_ci so->output[so_outputs].num_components = 4; 441bf215546Sopenharmony_ci else if (ShaderOutputsInfo[i].mask & 4) 442bf215546Sopenharmony_ci so->output[so_outputs].num_components = 3; 443bf215546Sopenharmony_ci else if (ShaderOutputsInfo[i].mask & 2) 444bf215546Sopenharmony_ci so->output[so_outputs].num_components = 2; 445bf215546Sopenharmony_ci else 446bf215546Sopenharmony_ci so->output[so_outputs].num_components = 1; 447bf215546Sopenharmony_ci so->output[so_outputs].output_buffer = 0; 448bf215546Sopenharmony_ci so->output[so_outputs].dst_offset = so_outputs * sizeof(float[4])/4; 449bf215546Sopenharmony_ci so->output[so_outputs].stream = 0; 450bf215546Sopenharmony_ci so_outputs++; 451bf215546Sopenharmony_ci break; 452bf215546Sopenharmony_ci } 453bf215546Sopenharmony_ci } 454bf215546Sopenharmony_ci } 455bf215546Sopenharmony_ci 456bf215546Sopenharmony_ci so->num_outputs = so_outputs; 457bf215546Sopenharmony_ci so->stride[0] = so_outputs * sizeof(float[4])/4; 458bf215546Sopenharmony_ci} 459bf215546Sopenharmony_ci 460bf215546Sopenharmony_ci/* ProcessVertices runs stream output into a temporary buffer to capture 461bf215546Sopenharmony_ci * all outputs. 462bf215546Sopenharmony_ci * Now we have to convert them to the format and order set by the vertex 463bf215546Sopenharmony_ci * declaration, for which we use u_translate. 464bf215546Sopenharmony_ci * This is necessary if the vertex declaration contains elements using a 465bf215546Sopenharmony_ci * non float32 format, because stream output only supports f32/u32/s32. 466bf215546Sopenharmony_ci */ 467bf215546Sopenharmony_ciHRESULT 468bf215546Sopenharmony_ciNineVertexDeclaration9_ConvertStreamOutput( 469bf215546Sopenharmony_ci struct NineVertexDeclaration9 *This, 470bf215546Sopenharmony_ci struct NineVertexBuffer9 *pDstBuf, 471bf215546Sopenharmony_ci UINT DestIndex, 472bf215546Sopenharmony_ci UINT VertexCount, 473bf215546Sopenharmony_ci void *pSrcBuf, 474bf215546Sopenharmony_ci const struct pipe_stream_output_info *so ) 475bf215546Sopenharmony_ci{ 476bf215546Sopenharmony_ci struct translate *translate; 477bf215546Sopenharmony_ci struct translate_key transkey; 478bf215546Sopenharmony_ci HRESULT hr; 479bf215546Sopenharmony_ci unsigned i; 480bf215546Sopenharmony_ci void *dst_map; 481bf215546Sopenharmony_ci 482bf215546Sopenharmony_ci DBG("This=%p pDstBuf=%p DestIndex=%u VertexCount=%u pSrcBuf=%p so=%p\n", 483bf215546Sopenharmony_ci This, pDstBuf, DestIndex, VertexCount, pSrcBuf, so); 484bf215546Sopenharmony_ci 485bf215546Sopenharmony_ci transkey.output_stride = 0; 486bf215546Sopenharmony_ci for (i = 0; i < This->nelems; ++i) { 487bf215546Sopenharmony_ci enum pipe_format format; 488bf215546Sopenharmony_ci 489bf215546Sopenharmony_ci switch (so->output[i].num_components) { 490bf215546Sopenharmony_ci case 1: format = PIPE_FORMAT_R32_FLOAT; break; 491bf215546Sopenharmony_ci case 2: format = PIPE_FORMAT_R32G32_FLOAT; break; 492bf215546Sopenharmony_ci case 3: format = PIPE_FORMAT_R32G32B32_FLOAT; break; 493bf215546Sopenharmony_ci default: 494bf215546Sopenharmony_ci assert(so->output[i].num_components == 4); 495bf215546Sopenharmony_ci format = PIPE_FORMAT_R32G32B32A32_FLOAT; 496bf215546Sopenharmony_ci break; 497bf215546Sopenharmony_ci } 498bf215546Sopenharmony_ci transkey.element[i].type = TRANSLATE_ELEMENT_NORMAL; 499bf215546Sopenharmony_ci transkey.element[i].input_format = format; 500bf215546Sopenharmony_ci transkey.element[i].input_buffer = 0; 501bf215546Sopenharmony_ci transkey.element[i].input_offset = so->output[i].dst_offset * 4; 502bf215546Sopenharmony_ci transkey.element[i].instance_divisor = 0; 503bf215546Sopenharmony_ci 504bf215546Sopenharmony_ci transkey.element[i].output_format = This->elems[i].src_format; 505bf215546Sopenharmony_ci transkey.element[i].output_offset = This->elems[i].src_offset; 506bf215546Sopenharmony_ci transkey.output_stride += 507bf215546Sopenharmony_ci util_format_get_blocksize(This->elems[i].src_format); 508bf215546Sopenharmony_ci 509bf215546Sopenharmony_ci assert(!(transkey.output_stride & 3)); 510bf215546Sopenharmony_ci } 511bf215546Sopenharmony_ci transkey.nr_elements = This->nelems; 512bf215546Sopenharmony_ci 513bf215546Sopenharmony_ci translate = translate_create(&transkey); 514bf215546Sopenharmony_ci if (!translate) 515bf215546Sopenharmony_ci return E_OUTOFMEMORY; 516bf215546Sopenharmony_ci 517bf215546Sopenharmony_ci hr = NineVertexBuffer9_Lock(pDstBuf, 518bf215546Sopenharmony_ci transkey.output_stride * DestIndex, 519bf215546Sopenharmony_ci transkey.output_stride * VertexCount, 520bf215546Sopenharmony_ci &dst_map, D3DLOCK_DISCARD); 521bf215546Sopenharmony_ci if (FAILED(hr)) 522bf215546Sopenharmony_ci goto out; 523bf215546Sopenharmony_ci 524bf215546Sopenharmony_ci translate->set_buffer(translate, 0, pSrcBuf, so->stride[0] * 4, ~0); 525bf215546Sopenharmony_ci 526bf215546Sopenharmony_ci translate->run(translate, 0, VertexCount, 0, 0, dst_map); 527bf215546Sopenharmony_ci 528bf215546Sopenharmony_ci NineVertexBuffer9_Unlock(pDstBuf); 529bf215546Sopenharmony_ciout: 530bf215546Sopenharmony_ci translate->release(translate); /* TODO: cache these */ 531bf215546Sopenharmony_ci return hr; 532bf215546Sopenharmony_ci} 533