| /* | |
| * vertex shaders declaration implementation | |
| * | |
| * Copyright 2002 Raphael Junqueira | |
| * Copyright 2004 Jason Edmeades | |
| * Copyright 2004 Christian Costa | |
| * | |
| * This library is free software; you can redistribute it and/or | |
| * modify it under the terms of the GNU Lesser General Public | |
| * License as published by the Free Software Foundation; either | |
| * version 2.1 of the License, or (at your option) any later version. | |
| * | |
| * This library is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| * Lesser General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU Lesser General Public | |
| * License along with this library; if not, write to the Free Software | |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| */ | |
| #include "config.h" | |
| #include <math.h> | |
| #include <stdarg.h> | |
| #include "windef.h" | |
| #include "winbase.h" | |
| #include "winuser.h" | |
| #include "wingdi.h" | |
| #include "wine/debug.h" | |
| #include "d3d8_private.h" | |
| WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader); | |
| /** | |
| * DirectX9 SDK download | |
| * http://msdn.microsoft.com/library/default.asp?url=/downloads/list/directx.asp | |
| * | |
| * Exploring D3DX | |
| * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndrive/html/directx07162002.asp | |
| * | |
| * Using Vertex Shaders | |
| * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndrive/html/directx02192001.asp | |
| * | |
| * Dx9 New | |
| * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/whatsnew.asp | |
| * | |
| * Dx9 Shaders | |
| * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader2_0/VertexShader2_0.asp | |
| * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader2_0/Instructions/Instructions.asp | |
| * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/GettingStarted/VertexDeclaration/VertexDeclaration.asp | |
| * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader3_0/VertexShader3_0.asp | |
| * | |
| * Dx9 D3DX | |
| * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/VertexPipe/matrixstack/matrixstack.asp | |
| * | |
| * FVF | |
| * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/GettingStarted/VertexFormats/vformats.asp | |
| * | |
| * NVIDIA: DX8 Vertex Shader to NV Vertex Program | |
| * http://developer.nvidia.com/view.asp?IO=vstovp | |
| * | |
| * NVIDIA: Memory Management with VAR | |
| * http://developer.nvidia.com/view.asp?IO=var_memory_management | |
| */ | |
| /** Vertex Shader Declaration data types tokens */ | |
| #define MAX_VSHADER_DECL_TYPES 8 | |
| static CONST char* VertexShaderDeclDataTypes[] = { | |
| "D3DVSDT_FLOAT1", | |
| "D3DVSDT_FLOAT2", | |
| "D3DVSDT_FLOAT3", | |
| "D3DVSDT_FLOAT4", | |
| "D3DVSDT_D3DCOLOR", | |
| "D3DVSDT_UBYTE4", | |
| "D3DVSDT_SHORT2", | |
| "D3DVSDT_SHORT4", | |
| NULL | |
| }; | |
| static CONST char* VertexShaderDeclRegister[] = { | |
| "D3DVSDE_POSITION", | |
| "D3DVSDE_BLENDWEIGHT", | |
| "D3DVSDE_BLENDINDICES", | |
| "D3DVSDE_NORMAL", | |
| "D3DVSDE_PSIZE", | |
| "D3DVSDE_DIFFUSE", | |
| "D3DVSDE_SPECULAR", | |
| "D3DVSDE_TEXCOORD0", | |
| "D3DVSDE_TEXCOORD1", | |
| "D3DVSDE_TEXCOORD2", | |
| "D3DVSDE_TEXCOORD3", | |
| "D3DVSDE_TEXCOORD4", | |
| "D3DVSDE_TEXCOORD5", | |
| "D3DVSDE_TEXCOORD6", | |
| "D3DVSDE_TEXCOORD7", | |
| "D3DVSDE_POSITION2", | |
| "D3DVSDE_NORMAL2", | |
| NULL | |
| }; | |
| /** todo check decl validity */ | |
| /*inline static*/ DWORD Direct3DVextexShaderDeclarationImpl_ParseToken(const DWORD* pToken) { | |
| const DWORD token = *pToken; | |
| DWORD tokenlen = 1; | |
| switch ((token & D3DVSD_TOKENTYPEMASK) >> D3DVSD_TOKENTYPESHIFT) { /* maybe a macro to inverse ... */ | |
| case D3DVSD_TOKEN_NOP: | |
| TRACE(" 0x%08lx NOP()\n", token); | |
| break; | |
| case D3DVSD_TOKEN_STREAM: | |
| if (token & D3DVSD_STREAMTESSMASK) { | |
| TRACE(" 0x%08lx STREAM_TESS()\n", token); | |
| } else { | |
| TRACE(" 0x%08lx STREAM(%lu)\n", token, ((token & D3DVSD_STREAMNUMBERMASK) >> D3DVSD_STREAMNUMBERSHIFT)); | |
| } | |
| break; | |
| case D3DVSD_TOKEN_STREAMDATA: | |
| if (token & 0x10000000) { | |
| TRACE(" 0x%08lx SKIP(%lu)\n", token, ((token & D3DVSD_SKIPCOUNTMASK) >> D3DVSD_SKIPCOUNTSHIFT)); | |
| } else { | |
| DWORD type = ((token & D3DVSD_DATATYPEMASK) >> D3DVSD_DATATYPESHIFT); | |
| DWORD reg = ((token & D3DVSD_VERTEXREGMASK) >> D3DVSD_VERTEXREGSHIFT); | |
| TRACE(" 0x%08lx REG(%s, %s)\n", token, VertexShaderDeclRegister[reg], VertexShaderDeclDataTypes[type]); | |
| } | |
| break; | |
| case D3DVSD_TOKEN_TESSELLATOR: | |
| if (token & 0x10000000) { | |
| DWORD type = ((token & D3DVSD_DATATYPEMASK) >> D3DVSD_DATATYPESHIFT); | |
| DWORD reg = ((token & D3DVSD_VERTEXREGMASK) >> D3DVSD_VERTEXREGSHIFT); | |
| TRACE(" 0x%08lx TESSUV(%s) as %s\n", token, VertexShaderDeclRegister[reg], VertexShaderDeclDataTypes[type]); | |
| } else { | |
| DWORD type = ((token & D3DVSD_DATATYPEMASK) >> D3DVSD_DATATYPESHIFT); | |
| DWORD regout = ((token & D3DVSD_VERTEXREGMASK) >> D3DVSD_VERTEXREGSHIFT); | |
| DWORD regin = ((token & D3DVSD_VERTEXREGINMASK) >> D3DVSD_VERTEXREGINSHIFT); | |
| TRACE(" 0x%08lx TESSNORMAL(%s, %s) as %s\n", token, VertexShaderDeclRegister[regin], VertexShaderDeclRegister[regout], VertexShaderDeclDataTypes[type]); | |
| } | |
| break; | |
| case D3DVSD_TOKEN_CONSTMEM: | |
| { | |
| DWORD i; | |
| DWORD count = ((token & D3DVSD_CONSTCOUNTMASK) >> D3DVSD_CONSTCOUNTSHIFT); | |
| DWORD constaddress = ((token & D3DVSD_CONSTADDRESSMASK) >> D3DVSD_CONSTADDRESSSHIFT); | |
| TRACE(" 0x%08lx CONST(%lu, %lu)\n", token, constaddress, count); | |
| ++pToken; | |
| for (i = 0; i < count; ++i) { | |
| #if 0 | |
| TRACE(" c[%lu] = (0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx)\n", | |
| constaddress, | |
| *pToken, | |
| *(pToken + 1), | |
| *(pToken + 2), | |
| *(pToken + 3)); | |
| #endif | |
| TRACE(" c[%lu] = (%8f, %8f, %8f, %8f)\n", | |
| constaddress, | |
| *(float*) pToken, | |
| *(float*) (pToken + 1), | |
| *(float*) (pToken + 2), | |
| *(float*) (pToken + 3)); | |
| pToken += 4; | |
| ++constaddress; | |
| } | |
| tokenlen = (4 * count) + 1; | |
| } | |
| break; | |
| case D3DVSD_TOKEN_EXT: | |
| { | |
| DWORD count = ((token & D3DVSD_CONSTCOUNTMASK) >> D3DVSD_CONSTCOUNTSHIFT); | |
| DWORD extinfo = ((token & D3DVSD_EXTINFOMASK) >> D3DVSD_EXTINFOSHIFT); | |
| TRACE(" 0x%08lx EXT(%lu, %lu)\n", token, count, extinfo); | |
| /* todo ... print extension */ | |
| tokenlen = count + 1; | |
| } | |
| break; | |
| case D3DVSD_TOKEN_END: | |
| TRACE(" 0x%08lx END()\n", token); | |
| break; | |
| default: | |
| TRACE(" 0x%08lx UNKNOWN\n", token); | |
| /* argg error */ | |
| } | |
| return tokenlen; | |
| } | |
| HRESULT WINAPI IDirect3DDeviceImpl_CreateVertexShaderDeclaration8(IDirect3DDevice8Impl* This, CONST DWORD* pDeclaration8, IDirect3DVertexShaderDeclarationImpl** ppVertexShaderDecl) { | |
| /** parser data */ | |
| const DWORD* pToken = pDeclaration8; | |
| DWORD fvf = 0; | |
| DWORD len = 0; | |
| DWORD stream = 0; | |
| DWORD token; | |
| DWORD tokenlen; | |
| DWORD tokentype; | |
| DWORD tex = D3DFVF_TEX0; | |
| /** TRUE if declaration can be matched by a fvf */ | |
| IDirect3DVertexShaderDeclarationImpl* object; | |
| BOOL invalid_fvf = FALSE; | |
| TRACE("(%p) : pDeclaration8(%p)\n", This, pDeclaration8); | |
| object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVertexShaderDeclarationImpl)); | |
| /*object->lpVtbl = &Direct3DVextexShaderDeclaration8_Vtbl;*/ | |
| object->device = This; /* FIXME: AddRef(This) */ | |
| object->ref = 1; | |
| object->allFVF = 0; | |
| while (D3DVSD_END() != *pToken) { | |
| token = *pToken; | |
| tokenlen = Direct3DVextexShaderDeclarationImpl_ParseToken(pToken); | |
| tokentype = ((token & D3DVSD_TOKENTYPEMASK) >> D3DVSD_TOKENTYPESHIFT); | |
| /** FVF generation block */ | |
| if (D3DVSD_TOKEN_STREAM == tokentype && 0 == (D3DVSD_STREAMTESSMASK & token)) { | |
| /** | |
| * how really works streams, | |
| * in DolphinVS dx8 dsk sample they seems to decal reg numbers !!! | |
| */ | |
| DWORD oldStream = stream; | |
| stream = ((token & D3DVSD_STREAMNUMBERMASK) >> D3DVSD_STREAMNUMBERSHIFT); | |
| /* copy fvf if valid */ | |
| if (FALSE == invalid_fvf) { | |
| fvf |= tex << D3DFVF_TEXCOUNT_SHIFT; | |
| tex = 0; | |
| object->fvf[oldStream] = fvf; | |
| object->allFVF |= fvf; | |
| } else { | |
| object->fvf[oldStream] = 0; | |
| tex = 0; | |
| } | |
| /* reset valid/invalid fvf */ | |
| fvf = 0; | |
| invalid_fvf = FALSE; | |
| } else if (D3DVSD_TOKEN_STREAMDATA == tokentype && 0 == (0x10000000 & tokentype)) { | |
| DWORD type = ((token & D3DVSD_DATATYPEMASK) >> D3DVSD_DATATYPESHIFT); | |
| DWORD reg = ((token & D3DVSD_VERTEXREGMASK) >> D3DVSD_VERTEXREGSHIFT); | |
| switch (reg) { | |
| case D3DVSDE_POSITION: | |
| switch (type) { | |
| case D3DVSDT_FLOAT3: fvf |= D3DFVF_XYZ; break; | |
| case D3DVSDT_FLOAT4: fvf |= D3DFVF_XYZRHW; break; | |
| default: | |
| /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */ | |
| invalid_fvf = TRUE; | |
| if (type >= MAX_VSHADER_DECL_TYPES) { | |
| TRACE("Mismatched use in VertexShader declaration of D3DVSDE_POSITION register: unsupported and unrecognized type %08lx\n", type); | |
| } else { | |
| TRACE("Mismatched use in VertexShader declaration of D3DVSDE_POSITION register: unsupported type %s\n", VertexShaderDeclDataTypes[type]); | |
| } | |
| } | |
| break; | |
| case D3DVSDE_BLENDWEIGHT: | |
| switch (type) { | |
| case D3DVSDT_FLOAT1: fvf |= D3DFVF_XYZB1; break; | |
| case D3DVSDT_FLOAT2: fvf |= D3DFVF_XYZB2; break; | |
| case D3DVSDT_FLOAT3: fvf |= D3DFVF_XYZB3; break; | |
| case D3DVSDT_FLOAT4: fvf |= D3DFVF_XYZB4; break; | |
| default: | |
| /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */ | |
| invalid_fvf = TRUE; | |
| TRACE("Mismatched use in VertexShader declaration of D3DVSDE_BLENDWEIGHT register: unsupported type %s\n", VertexShaderDeclDataTypes[type]); | |
| } | |
| break; | |
| case D3DVSDE_BLENDINDICES: /* seem to be B5 as said in MSDN Dx9SDK ?? */ | |
| switch (type) { | |
| case D3DVSDT_UBYTE4: fvf |= D3DFVF_LASTBETA_UBYTE4; break; | |
| default: | |
| /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */ | |
| invalid_fvf = TRUE; | |
| TRACE("Mismatched use in VertexShader declaration of D3DVSDE_BLENDINDINCES register: unsupported type %s\n", VertexShaderDeclDataTypes[type]); | |
| } | |
| break; | |
| case D3DVSDE_NORMAL: /* TODO: only FLOAT3 supported ... another choice possible ? */ | |
| switch (type) { | |
| case D3DVSDT_FLOAT3: fvf |= D3DFVF_NORMAL; break; | |
| default: | |
| /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */ | |
| invalid_fvf = TRUE; | |
| TRACE("Mismatched use in VertexShader declaration of D3DVSDE_NORMAL register: unsupported type %s\n", VertexShaderDeclDataTypes[type]); | |
| } | |
| break; | |
| case D3DVSDE_PSIZE: /* TODO: only FLOAT1 supported ... another choice possible ? */ | |
| switch (type) { | |
| case D3DVSDT_FLOAT1: fvf |= D3DFVF_PSIZE; break; | |
| default: | |
| /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */ | |
| invalid_fvf = TRUE; | |
| TRACE("Mismatched use in VertexShader declaration of D3DVSDE_PSIZE register: unsupported type %s\n", VertexShaderDeclDataTypes[type]); | |
| } | |
| break; | |
| case D3DVSDE_DIFFUSE: /* TODO: only D3DCOLOR supported */ | |
| switch (type) { | |
| case D3DVSDT_D3DCOLOR: fvf |= D3DFVF_DIFFUSE; break; | |
| default: | |
| /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */ | |
| invalid_fvf = TRUE; | |
| TRACE("Mismatched use in VertexShader declaration of D3DVSDE_DIFFUSE register: unsupported type %s\n", VertexShaderDeclDataTypes[type]); | |
| } | |
| break; | |
| case D3DVSDE_SPECULAR: /* TODO: only D3DCOLOR supported */ | |
| switch (type) { | |
| case D3DVSDT_D3DCOLOR: fvf |= D3DFVF_SPECULAR; break; | |
| default: | |
| /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */ | |
| invalid_fvf = TRUE; | |
| TRACE("Mismatched use in VertexShader declaration of D3DVSDE_SPECULAR register: unsupported type %s\n", VertexShaderDeclDataTypes[type]); | |
| } | |
| break; | |
| case D3DVSDE_TEXCOORD0: | |
| case D3DVSDE_TEXCOORD1: | |
| case D3DVSDE_TEXCOORD2: | |
| case D3DVSDE_TEXCOORD3: | |
| case D3DVSDE_TEXCOORD4: | |
| case D3DVSDE_TEXCOORD5: | |
| case D3DVSDE_TEXCOORD6: | |
| case D3DVSDE_TEXCOORD7: | |
| /* Fixme? - assume all tex coords in same stream */ | |
| { | |
| int texNo = 1 + (reg - D3DVSDE_TEXCOORD0); | |
| tex = max(tex, texNo); | |
| switch (type) { | |
| case D3DVSDT_FLOAT1: fvf |= D3DFVF_TEXCOORDSIZE1(texNo); break; | |
| case D3DVSDT_FLOAT2: fvf |= D3DFVF_TEXCOORDSIZE2(texNo); break; | |
| case D3DVSDT_FLOAT3: fvf |= D3DFVF_TEXCOORDSIZE3(texNo); break; | |
| case D3DVSDT_FLOAT4: fvf |= D3DFVF_TEXCOORDSIZE4(texNo); break; | |
| default: | |
| /** Mismatched use of a register, invalid for fixed function fvf computing (ok for VS) */ | |
| invalid_fvf = TRUE; | |
| TRACE("Mismatched use in VertexShader declaration of D3DVSDE_TEXCOORD? register: unsupported type %s\n", VertexShaderDeclDataTypes[type]); | |
| } | |
| } | |
| break; | |
| case D3DVSDE_POSITION2: /* maybe D3DFVF_XYZRHW instead D3DFVF_XYZ (of D3DVDE_POSITION) ... to see */ | |
| case D3DVSDE_NORMAL2: /* FIXME i don't know what to do here ;( */ | |
| FIXME("[%lu] registers in VertexShader declaration not supported yet (token:0x%08lx)\n", reg, token); | |
| break; | |
| } | |
| TRACE("VertexShader declaration define %lx as current FVF\n", fvf); | |
| } | |
| len += tokenlen; | |
| pToken += tokenlen; | |
| } | |
| /* here D3DVSD_END() */ | |
| len += Direct3DVextexShaderDeclarationImpl_ParseToken(pToken); | |
| /* copy fvf if valid */ | |
| if (FALSE == invalid_fvf) { | |
| fvf |= tex << D3DFVF_TEXCOUNT_SHIFT; | |
| object->fvf[stream] = fvf; | |
| object->allFVF |= fvf; | |
| } else { | |
| object->fvf[stream] = 0; | |
| } | |
| TRACE("Completed, allFVF = %lx\n", object->allFVF); | |
| /* compute size */ | |
| object->declaration8Length = len * sizeof(DWORD); | |
| /* copy the declaration */ | |
| object->pDeclaration8 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->declaration8Length); | |
| memcpy(object->pDeclaration8, pDeclaration8, object->declaration8Length); | |
| /* returns */ | |
| *ppVertexShaderDecl = object; | |
| return D3D_OK; | |
| } | |
| HRESULT WINAPI IDirect3DDeviceImpl_FillVertexShaderInputSW(IDirect3DDevice8Impl* This, | |
| IDirect3DVertexShaderImpl* vshader, | |
| DWORD SkipnStrides) { | |
| /** parser data */ | |
| const DWORD* pToken = This->UpdateStateBlock->vertexShaderDecl->pDeclaration8; | |
| DWORD stream = 0; | |
| DWORD token; | |
| /*DWORD tokenlen;*/ | |
| DWORD tokentype; | |
| /** for input readers */ | |
| const char* curPos = NULL; | |
| FLOAT x, y, z, w; | |
| SHORT u, v, r, t; | |
| DWORD dw; | |
| TRACE("(%p) - This:%p, skipstrides=%lu\n", vshader, This, SkipnStrides); | |
| while (D3DVSD_END() != *pToken) { | |
| token = *pToken; | |
| tokentype = ((token & D3DVSD_TOKENTYPEMASK) >> D3DVSD_TOKENTYPESHIFT); | |
| /** FVF generation block */ | |
| if (D3DVSD_TOKEN_STREAM == tokentype && 0 == (D3DVSD_STREAMTESSMASK & token)) { | |
| IDirect3DVertexBuffer8* pVB; | |
| int skip = 0; | |
| ++pToken; | |
| /** | |
| * how really works streams, | |
| * in DolphinVS dx8 dsk sample use it !!! | |
| */ | |
| stream = ((token & D3DVSD_STREAMNUMBERMASK) >> D3DVSD_STREAMNUMBERSHIFT); | |
| skip = This->StateBlock->stream_stride[stream]; | |
| pVB = This->StateBlock->stream_source[stream]; | |
| if (NULL == pVB) { | |
| ERR("using unitialised stream[%lu]\n", stream); | |
| return D3DERR_INVALIDCALL; | |
| } else { | |
| if (This->StateBlock->streamIsUP == TRUE) { | |
| curPos = ((char *) pVB) + (SkipnStrides * skip); /* Not really a VB */ | |
| } else { | |
| curPos = ((IDirect3DVertexBuffer8Impl*) pVB)->allocatedMemory + (SkipnStrides * skip); | |
| } | |
| TRACE(" using stream[%lu] with %p (%p + (Stride %d * skip %ld))\n", stream, curPos, | |
| ((IDirect3DVertexBuffer8Impl*) pVB)->allocatedMemory, skip, SkipnStrides); | |
| } | |
| } else if (D3DVSD_TOKEN_CONSTMEM == tokentype) { | |
| /** Const decl */ | |
| DWORD i; | |
| DWORD count = ((token & D3DVSD_CONSTCOUNTMASK) >> D3DVSD_CONSTCOUNTSHIFT); | |
| DWORD constaddress = ((token & D3DVSD_CONSTADDRESSMASK) >> D3DVSD_CONSTADDRESSSHIFT); | |
| ++pToken; | |
| for (i = 0; i < count; ++i) { | |
| vshader->data->C[constaddress + i].x = *(float*)pToken; | |
| vshader->data->C[constaddress + i].y = *(float*)(pToken + 1); | |
| vshader->data->C[constaddress + i].z = *(float*)(pToken + 2); | |
| vshader->data->C[constaddress + i].w = *(float*)(pToken + 3); | |
| pToken += 4; | |
| } | |
| } else if (D3DVSD_TOKEN_STREAMDATA == tokentype && 0 != (0x10000000 & tokentype)) { | |
| /** skip datas */ | |
| DWORD skipCount = ((token & D3DVSD_SKIPCOUNTMASK) >> D3DVSD_SKIPCOUNTSHIFT); | |
| TRACE(" skipping %ld dwords\n", skipCount); | |
| curPos = curPos + skipCount * sizeof(DWORD); | |
| ++pToken; | |
| } else if (D3DVSD_TOKEN_STREAMDATA == tokentype && 0 == (0x10000000 & tokentype)) { | |
| DWORD type = ((token & D3DVSD_DATATYPEMASK) >> D3DVSD_DATATYPESHIFT); | |
| DWORD reg = ((token & D3DVSD_VERTEXREGMASK) >> D3DVSD_VERTEXREGSHIFT); | |
| ++pToken; | |
| TRACE(" type : %ld, reg = %ld\n", type, reg); | |
| switch (type) { | |
| case D3DVSDT_FLOAT1: | |
| x = *(float*) curPos; | |
| curPos = curPos + sizeof(float); | |
| /**/ | |
| vshader->input.V[reg].x = x; | |
| vshader->input.V[reg].y = 0.0f; | |
| vshader->input.V[reg].z = 0.0f; | |
| vshader->input.V[reg].w = 1.0f; | |
| break; | |
| case D3DVSDT_FLOAT2: | |
| x = *(float*) curPos; | |
| curPos = curPos + sizeof(float); | |
| y = *(float*) curPos; | |
| curPos = curPos + sizeof(float); | |
| /**/ | |
| vshader->input.V[reg].x = x; | |
| vshader->input.V[reg].y = y; | |
| vshader->input.V[reg].z = 0.0f; | |
| vshader->input.V[reg].w = 1.0f; | |
| break; | |
| case D3DVSDT_FLOAT3: | |
| x = *(float*) curPos; | |
| curPos = curPos + sizeof(float); | |
| y = *(float*) curPos; | |
| curPos = curPos + sizeof(float); | |
| z = *(float*) curPos; | |
| curPos = curPos + sizeof(float); | |
| /**/ | |
| vshader->input.V[reg].x = x; | |
| vshader->input.V[reg].y = y; | |
| vshader->input.V[reg].z = z; | |
| vshader->input.V[reg].w = 1.0f; | |
| break; | |
| case D3DVSDT_FLOAT4: | |
| x = *(float*) curPos; | |
| curPos = curPos + sizeof(float); | |
| y = *(float*) curPos; | |
| curPos = curPos + sizeof(float); | |
| z = *(float*) curPos; | |
| curPos = curPos + sizeof(float); | |
| w = *(float*) curPos; | |
| curPos = curPos + sizeof(float); | |
| /**/ | |
| vshader->input.V[reg].x = x; | |
| vshader->input.V[reg].y = y; | |
| vshader->input.V[reg].z = z; | |
| vshader->input.V[reg].w = w; | |
| break; | |
| case D3DVSDT_D3DCOLOR: | |
| dw = *(DWORD*) curPos; | |
| curPos = curPos + sizeof(DWORD); | |
| /**/ | |
| vshader->input.V[reg].x = (float) (((dw >> 16) & 0xFF) / 255.0f); | |
| vshader->input.V[reg].y = (float) (((dw >> 8) & 0xFF) / 255.0f); | |
| vshader->input.V[reg].z = (float) (((dw >> 0) & 0xFF) / 255.0f); | |
| vshader->input.V[reg].w = (float) (((dw >> 24) & 0xFF) / 255.0f); | |
| break; | |
| case D3DVSDT_SHORT2: | |
| u = *(SHORT*) curPos; | |
| curPos = curPos + sizeof(SHORT); | |
| v = *(SHORT*) curPos; | |
| curPos = curPos + sizeof(SHORT); | |
| /**/ | |
| vshader->input.V[reg].x = (float) u; | |
| vshader->input.V[reg].y = (float) v; | |
| vshader->input.V[reg].z = 0.0f; | |
| vshader->input.V[reg].w = 1.0f; | |
| break; | |
| case D3DVSDT_SHORT4: | |
| u = *(SHORT*) curPos; | |
| curPos = curPos + sizeof(SHORT); | |
| v = *(SHORT*) curPos; | |
| curPos = curPos + sizeof(SHORT); | |
| r = *(SHORT*) curPos; | |
| curPos = curPos + sizeof(SHORT); | |
| t = *(SHORT*) curPos; | |
| curPos = curPos + sizeof(SHORT); | |
| /**/ | |
| vshader->input.V[reg].x = (float) u; | |
| vshader->input.V[reg].y = (float) v; | |
| vshader->input.V[reg].z = (float) r; | |
| vshader->input.V[reg].w = (float) t; | |
| break; | |
| case D3DVSDT_UBYTE4: | |
| dw = *(DWORD*) curPos; | |
| curPos = curPos + sizeof(DWORD); | |
| /**/ | |
| vshader->input.V[reg].x = (float) ((dw & 0x000F) >> 0); | |
| vshader->input.V[reg].y = (float) ((dw & 0x00F0) >> 8); | |
| vshader->input.V[reg].z = (float) ((dw & 0x0F00) >> 16); | |
| vshader->input.V[reg].w = (float) ((dw & 0xF000) >> 24); | |
| break; | |
| default: /** errooooorr what to do ? */ | |
| ERR("Error in VertexShader declaration of %s register: unsupported type %s\n", VertexShaderDeclRegister[reg], VertexShaderDeclDataTypes[type]); | |
| } | |
| } | |
| } | |
| /* here D3DVSD_END() */ | |
| return D3D_OK; | |
| } | |
| HRESULT WINAPI IDirect3DDeviceImpl_FillVertexShaderInputArbHW(IDirect3DDevice8Impl* This, | |
| IDirect3DVertexShaderImpl* vshader, | |
| DWORD SkipnStrides) { | |
| /** parser data */ | |
| const DWORD* pToken = This->UpdateStateBlock->vertexShaderDecl->pDeclaration8; | |
| DWORD stream = 0; | |
| DWORD token; | |
| /*DWORD tokenlen;*/ | |
| DWORD tokentype; | |
| /** for input readers */ | |
| const char* curPos = NULL; | |
| int skip = 0; | |
| TRACE("(%p) - This:%p, skipstrides=%lu\n", vshader, This, SkipnStrides); | |
| while (D3DVSD_END() != *pToken) { | |
| token = *pToken; | |
| tokentype = ((token & D3DVSD_TOKENTYPEMASK) >> D3DVSD_TOKENTYPESHIFT); | |
| /** FVF generation block */ | |
| if (D3DVSD_TOKEN_STREAM == tokentype && 0 == (D3DVSD_STREAMTESSMASK & token)) { | |
| IDirect3DVertexBuffer8* pVB; | |
| ++pToken; | |
| /** | |
| * how really works streams, | |
| * in DolphinVS dx8 dsk sample use it !!! | |
| */ | |
| stream = ((token & D3DVSD_STREAMNUMBERMASK) >> D3DVSD_STREAMNUMBERSHIFT); | |
| skip = This->StateBlock->stream_stride[stream]; | |
| pVB = This->StateBlock->stream_source[stream]; | |
| if (NULL == pVB) { | |
| ERR("using unitialised stream[%lu]\n", stream); | |
| return D3DERR_INVALIDCALL; | |
| } else { | |
| if (This->StateBlock->streamIsUP == TRUE) { | |
| curPos = ((char *) pVB) + (SkipnStrides * skip); /* Not really a VB */ | |
| } else { | |
| curPos = ((IDirect3DVertexBuffer8Impl*) pVB)->allocatedMemory + (SkipnStrides * skip); | |
| } | |
| TRACE(" using stream[%lu] with %p (%p + (Stride %d * skip %ld))\n", stream, curPos, | |
| ((IDirect3DVertexBuffer8Impl*) pVB)->allocatedMemory, skip, SkipnStrides); | |
| } | |
| } else if (D3DVSD_TOKEN_CONSTMEM == tokentype) { | |
| /** Const decl */ | |
| DWORD i; | |
| DWORD count = ((token & D3DVSD_CONSTCOUNTMASK) >> D3DVSD_CONSTCOUNTSHIFT); | |
| DWORD constaddress = ((token & D3DVSD_CONSTADDRESSMASK) >> D3DVSD_CONSTADDRESSSHIFT); | |
| ++pToken; | |
| for (i = 0; i < count; ++i) { | |
| FIXME("Confirm this is correct handling of consts inside the hw vertex shader\n"); | |
| GL_EXTCALL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, constaddress+i, (GLfloat *)pToken)); | |
| vshader->data->C[constaddress + i].x = *(float*)pToken; | |
| vshader->data->C[constaddress + i].y = *(float*)(pToken + 1); | |
| vshader->data->C[constaddress + i].z = *(float*)(pToken + 2); | |
| vshader->data->C[constaddress + i].w = *(float*)(pToken + 3); | |
| pToken += 4; | |
| } | |
| } else if (D3DVSD_TOKEN_STREAMDATA == tokentype && 0 != (0x10000000 & tokentype)) { | |
| /** skip datas */ | |
| DWORD skipCount = ((token & D3DVSD_SKIPCOUNTMASK) >> D3DVSD_SKIPCOUNTSHIFT); | |
| TRACE(" skipping %ld dwords\n", skipCount); | |
| curPos = curPos + skipCount * sizeof(DWORD); | |
| ++pToken; | |
| } else if (D3DVSD_TOKEN_STREAMDATA == tokentype && 0 == (0x10000000 & tokentype)) { | |
| DWORD type = ((token & D3DVSD_DATATYPEMASK) >> D3DVSD_DATATYPESHIFT); | |
| DWORD reg = ((token & D3DVSD_VERTEXREGMASK) >> D3DVSD_VERTEXREGSHIFT); | |
| ++pToken; | |
| TRACE(" type : %ld, reg = %ld\n", type, reg); | |
| switch (type) { | |
| case D3DVSDT_FLOAT1: | |
| TRACE("HW VS glVertexAttribPointerARB(reg=%ld,num=%d,skip=%d,ptr=%p)\n", reg, 1, skip, curPos); | |
| GL_EXTCALL(glVertexAttribPointerARB(reg, 1, GL_FLOAT, GL_FALSE, skip, curPos)); | |
| GL_EXTCALL(glEnableVertexAttribArrayARB(reg)); | |
| curPos = curPos + sizeof(float); | |
| break; | |
| case D3DVSDT_FLOAT2: | |
| TRACE("HW VS glVertexAttribPointerARB(reg=%ld,num=%d,skip=%d,ptr=%p)\n", reg, 2, skip, curPos); | |
| GL_EXTCALL(glVertexAttribPointerARB(reg, 2, GL_FLOAT, GL_FALSE, skip, curPos)); | |
| GL_EXTCALL(glEnableVertexAttribArrayARB(reg)); | |
| curPos = curPos + 2*sizeof(float); | |
| break; | |
| case D3DVSDT_FLOAT3: | |
| TRACE("HW VS glVertexAttribPointerARB(reg=%ld,num=%d,skip=%d,ptr=%p)\n", reg, 3, skip, curPos); | |
| GL_EXTCALL(glVertexAttribPointerARB(reg, 3, GL_FLOAT, GL_FALSE, skip, curPos)); | |
| GL_EXTCALL(glEnableVertexAttribArrayARB(reg)); | |
| curPos = curPos + 3*sizeof(float); | |
| break; | |
| case D3DVSDT_FLOAT4: | |
| TRACE("HW VS glVertexAttribPointerARB(reg=%ld,num=%d,skip=%d,ptr=%p)\n", reg, 4, skip, curPos); | |
| GL_EXTCALL(glVertexAttribPointerARB(reg, 4, GL_FLOAT, GL_FALSE, skip, curPos)); | |
| GL_EXTCALL(glEnableVertexAttribArrayARB(reg)); | |
| curPos = curPos + 4*sizeof(float); | |
| break; | |
| case D3DVSDT_D3DCOLOR: | |
| TRACE("HW VS glVertexAttribPointerARB(reg=%ld,num=%d,skip=%d,ptr=%p)\n", reg, 4, skip, curPos); | |
| FIXME("D3DVSDT_D3DCOLOR in hw shader - To confirm\n"); | |
| GL_EXTCALL(glVertexAttribPointerARB(reg, 4, GL_UNSIGNED_BYTE, GL_TRUE, skip, curPos)); | |
| GL_EXTCALL(glEnableVertexAttribArrayARB(reg)); | |
| curPos = curPos + 4*sizeof(BYTE); | |
| break; | |
| case D3DVSDT_SHORT2: | |
| TRACE("HW VS glVertexAttribPointerARB(reg=%ld,num=%d,skip=%d,ptr=%p)\n", reg, 2, skip, curPos); | |
| GL_EXTCALL(glVertexAttribPointerARB(reg, 2, GL_UNSIGNED_SHORT, GL_FALSE, skip, curPos)); | |
| GL_EXTCALL(glEnableVertexAttribArrayARB(reg)); | |
| curPos = curPos + 2*sizeof(short int); | |
| break; | |
| case D3DVSDT_SHORT4: | |
| TRACE("HW VS glVertexAttribPointerARB(reg=%ld,num=%d,skip=%d,ptr=%p)\n", reg, 1, skip, curPos); | |
| GL_EXTCALL(glVertexAttribPointerARB(reg, 4, GL_UNSIGNED_SHORT, GL_FALSE, skip, curPos)); | |
| GL_EXTCALL(glEnableVertexAttribArrayARB(reg)); | |
| curPos = curPos + 4*sizeof(short int); | |
| break; | |
| case D3DVSDT_UBYTE4: | |
| FIXME("D3DVSDT_UBYTE4 in hw shader - To confirm\n"); | |
| GL_EXTCALL(glVertexAttribPointerARB(reg, 4, GL_UNSIGNED_BYTE, GL_TRUE, skip, curPos)); | |
| GL_EXTCALL(glEnableVertexAttribArrayARB(reg)); | |
| curPos = curPos + 4*sizeof(BYTE); | |
| break; | |
| default: /** errooooorr what to do ? */ | |
| ERR("Error in VertexShader declaration of %s register: unsupported type %s\n", VertexShaderDeclRegister[reg], VertexShaderDeclDataTypes[type]); | |
| } | |
| } | |
| } | |
| /* here D3DVSD_END() */ | |
| return D3D_OK; | |
| } | |
| HRESULT WINAPI IDirect3DVertexShaderDeclarationImpl_GetDeclaration8(IDirect3DVertexShaderDeclarationImpl* This, DWORD* pData, UINT* pSizeOfData) { | |
| if (NULL == pData) { | |
| *pSizeOfData = This->declaration8Length; | |
| return D3D_OK; | |
| } | |
| if (*pSizeOfData < This->declaration8Length) { | |
| *pSizeOfData = This->declaration8Length; | |
| return D3DERR_MOREDATA; | |
| } | |
| TRACE("(%p) : GetVertexShaderDeclaration copying to %p\n", This, pData); | |
| memcpy(pData, This->pDeclaration8, This->declaration8Length); | |
| return D3D_OK; | |
| } |