d3dx9: Constant table parsing foundations.
Matteo Bruni
matteo.mystral at gmail.com
Fri Sep 17 09:14:40 CDT 2010
Hello, I'm sending this patch on behalf of Christian Costa. It's
essentially a resend of
http://www.winehq.org/pipermail/wine-patches/2010-April/087624.html
with small changes.
The patch is based on code by Luis Busquets. Hope this is acceptable,
let me know otherwise...
-------------- next part --------------
From cc2075ef3fa766d41343acf7ab8e2023bf69d1c8 Mon Sep 17 00:00:00 2001
From: Christian Costa <titan.costa at wanadoo.fr>
Date: Fri, 10 Sep 2010 18:42:45 +0200
Subject: d3dx9: Constant table parsing foundations.
---
dlls/d3dx9_36/shader.c | 139 ++++++++++++++++++++++++++++++++++++++---
dlls/d3dx9_36/tests/shader.c | 109 ++++++++++++++++++++++++++++++++-
2 files changed, 235 insertions(+), 13 deletions(-)
diff --git a/dlls/d3dx9_36/shader.c b/dlls/d3dx9_36/shader.c
index 8c4580a..9dc13ce 100644
--- a/dlls/d3dx9_36/shader.c
+++ b/dlls/d3dx9_36/shader.c
@@ -609,14 +609,19 @@ HRESULT WINAPI D3DXPreprocessShaderFromResourceW(HMODULE module,
}
+typedef struct ctab_constant {
+ D3DXCONSTANT_DESC desc;
+} ctab_constant;
+
static const struct ID3DXConstantTableVtbl ID3DXConstantTable_Vtbl;
typedef struct ID3DXConstantTableImpl {
const ID3DXConstantTableVtbl *lpVtbl;
LONG ref;
- LPVOID ctab;
+ LPSTR ctab;
DWORD size;
D3DXCONSTANTTABLE_DESC desc;
+ ctab_constant* constants;
} ID3DXConstantTableImpl;
/*** IUnknown methods ***/
@@ -658,6 +663,7 @@ static ULONG WINAPI ID3DXConstantTableImpl_Release(ID3DXConstantTable* iface)
if (!ref)
{
+ HeapFree(GetProcessHeap(), 0, This->constants);
HeapFree(GetProcessHeap(), 0, This->ctab);
HeapFree(GetProcessHeap(), 0, This);
}
@@ -703,10 +709,31 @@ static HRESULT WINAPI ID3DXConstantTableImpl_GetConstantDesc(ID3DXConstantTable*
D3DXCONSTANT_DESC *desc, UINT *count)
{
ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
+ ctab_constant* constant_info;
- FIXME("(%p)->(%p, %p, %p): stub\n", This, constant, desc, count);
+ TRACE("(%p)->(%p, %p, %p)\n", This, constant, desc, count);
- return E_NOTIMPL;
+ if (!constant)
+ return D3DERR_INVALIDCALL;
+
+ /* Applications can pass the name of the constant in place of the handle */
+ if (!((UINT_PTR)constant >> 16))
+ constant_info = &This->constants[((UINT_PTR)constant) - 1];
+ else
+ {
+ D3DXHANDLE c = ID3DXConstantTable_GetConstantByName(iface, NULL, constant);
+ if (!c)
+ return D3DERR_INVALIDCALL;
+
+ constant_info = &This->constants[((UINT_PTR)c) - 1];
+ }
+
+ if (desc)
+ *desc = constant_info->desc;
+ if (count)
+ *count = 1;
+
+ return D3D_OK;
}
static UINT WINAPI ID3DXConstantTableImpl_GetSamplerIndex(LPD3DXCONSTANTTABLE iface, D3DXHANDLE constant)
@@ -722,16 +749,39 @@ static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstant(ID3DXConstantTable*
{
ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
- FIXME("(%p)->(%p, %d): stub\n", This, constant, index);
+ TRACE("(%p)->(%p, %d)\n", This, constant, index);
- return NULL;
+ if (constant)
+ {
+ FIXME("Only top level constants supported\n");
+ return NULL;
+ }
+
+ if (index >= This->desc.Constants)
+ return NULL;
+
+ return (D3DXHANDLE)(index + 1);
}
static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstantByName(ID3DXConstantTable* iface, D3DXHANDLE constant, LPCSTR name)
{
ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
+ UINT i;
+
+ TRACE("(%p)->(%p, %s)\n", This, constant, name);
- FIXME("(%p)->(%p, %s): stub\n", This, constant, name);
+ if (!name)
+ return NULL;
+
+ if (constant)
+ {
+ FIXME("Only top level constants supported\n");
+ return NULL;
+ }
+
+ for (i = 0; i < This->desc.Constants; i++)
+ if (!strcmp(This->constants[i].desc.Name, name))
+ return (D3DXHANDLE)(i + 1);
return NULL;
}
@@ -937,6 +987,28 @@ static const struct ID3DXConstantTableVtbl ID3DXConstantTable_Vtbl =
ID3DXConstantTableImpl_SetMatrixTransposePointerArray
};
+HRESULT parse_ctab_constant_type(LPD3DXSHADER_TYPEINFO type,
+ ctab_constant* constant)
+{
+ constant->desc.Class = (D3DXPARAMETER_CLASS)type->Class;
+ constant->desc.Type = (D3DXPARAMETER_TYPE)type->Type;
+ constant->desc.Rows = type->Rows;
+ constant->desc.Columns = type->Columns;
+ constant->desc.StructMembers = type->StructMembers;
+
+ TRACE("class = %d, type = %d, rows = %d, columns = %d, struct_members = %d\n",
+ constant->desc.Class, constant->desc.Type,
+ constant->desc.Rows, constant->desc.Columns, constant->desc.StructMembers);
+
+ if ((constant->desc.Class == D3DXPC_STRUCT) && constant->desc.StructMembers)
+ {
+ FIXME("Struct not supported yet\n");
+ return E_NOTIMPL;
+ }
+
+ return D3D_OK;
+}
+
HRESULT WINAPI D3DXGetShaderConstantTableEx(CONST DWORD* byte_code,
DWORD flags,
LPD3DXCONSTANTTABLE* constant_table)
@@ -946,8 +1018,10 @@ HRESULT WINAPI D3DXGetShaderConstantTableEx(CONST DWORD* byte_code,
LPCVOID data;
UINT size;
const D3DXSHADER_CONSTANTTABLE* ctab_header;
+ LPD3DXSHADER_CONSTANTINFO constant_info;
+ DWORD i;
- FIXME("(%p, %x, %p): semi-stub\n", byte_code, flags, constant_table);
+ TRACE("(%p, %x, %p)\n", byte_code, flags, constant_table);
if (!byte_code || !constant_table)
return D3DERR_INVALIDCALL;
@@ -956,7 +1030,7 @@ HRESULT WINAPI D3DXGetShaderConstantTableEx(CONST DWORD* byte_code,
if (hr != D3D_OK)
return D3DXERR_INVALIDDATA;
- object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ID3DXConstantTableImpl));
+ object = HeapAlloc(GetProcessHeap(), 0, sizeof(*object));
if (!object)
{
ERR("Out of memory\n");
@@ -967,24 +1041,66 @@ HRESULT WINAPI D3DXGetShaderConstantTableEx(CONST DWORD* byte_code,
object->ref = 1;
if (size < sizeof(D3DXSHADER_CONSTANTTABLE))
+ {
+ hr = D3DXERR_INVALIDDATA;
goto error;
+ }
object->ctab = HeapAlloc(GetProcessHeap(), 0, size);
if (!object->ctab)
{
- HeapFree(GetProcessHeap(), 0, object);
ERR("Out of memory\n");
- return E_OUTOFMEMORY;
+ hr = E_OUTOFMEMORY;
+ goto error;
}
object->size = size;
memcpy(object->ctab, data, object->size);
ctab_header = (const D3DXSHADER_CONSTANTTABLE*)data;
if (ctab_header->Size != sizeof(D3DXSHADER_CONSTANTTABLE))
+ {
+ hr = D3DXERR_INVALIDDATA;
goto error;
+ }
object->desc.Creator = ctab_header->Creator ? (LPCSTR)object->ctab + ctab_header->Creator : NULL;
object->desc.Version = ctab_header->Version;
object->desc.Constants = ctab_header->Constants;
+ if (object->desc.Creator)
+ TRACE("Creator = %s\n", object->desc.Creator);
+ TRACE("Version = %x\n", object->desc.Version);
+ TRACE("Constants = %d\n", ctab_header->Constants);
+ if (ctab_header->Target)
+ TRACE("Target = %s\n", (LPCSTR)object->ctab + ctab_header->Target);
+
+ if (object->desc.Constants > 65535)
+ {
+ FIXME("Too many constants (%u)\n", object->desc.Constants);
+ hr = E_NOTIMPL;
+ goto error;
+ }
+
+ object->constants = HeapAlloc(GetProcessHeap(), 0,
+ sizeof(*object->constants) * object->desc.Constants);
+ if (!object->constants)
+ {
+ ERR("Out of memory\n");
+ hr = E_OUTOFMEMORY;
+ goto error;
+ }
+
+ constant_info = (LPD3DXSHADER_CONSTANTINFO)(object->ctab + ctab_header->ConstantInfo);
+ for (i = 0; i < ctab_header->Constants; i++)
+ {
+ TRACE("name = %s\n", object->ctab + constant_info[i].Name);
+ object->constants[i].desc.Name = object->ctab + constant_info[i].Name;
+ object->constants[i].desc.RegisterSet = (D3DXREGISTER_SET)constant_info[i].RegisterSet;
+ object->constants[i].desc.RegisterIndex = constant_info[i].RegisterIndex;
+ object->constants[i].desc.RegisterCount = 0;
+ hr = parse_ctab_constant_type((LPD3DXSHADER_TYPEINFO)(object->ctab + constant_info[i].TypeInfo),
+ &object->constants[i]);
+ if (hr != D3D_OK)
+ goto error;
+ }
*constant_table = (LPD3DXCONSTANTTABLE)object;
@@ -992,10 +1108,11 @@ HRESULT WINAPI D3DXGetShaderConstantTableEx(CONST DWORD* byte_code,
error:
+ HeapFree(GetProcessHeap(), 0, object->constants);
HeapFree(GetProcessHeap(), 0, object->ctab);
HeapFree(GetProcessHeap(), 0, object);
- return D3DXERR_INVALIDDATA;
+ return hr;
}
HRESULT WINAPI D3DXGetShaderConstantTable(CONST DWORD* byte_code,
diff --git a/dlls/d3dx9_36/tests/shader.c b/dlls/d3dx9_36/tests/shader.c
index 6bf0de3..171f12b 100644
--- a/dlls/d3dx9_36/tests/shader.c
+++ b/dlls/d3dx9_36/tests/shader.c
@@ -55,6 +55,23 @@ static const DWORD shader_with_invalid_ctab[] = {
0x00000000, 0x00000000,
0x0000ffff}; /* END */
+static const DWORD shader_with_ctab_constants[] = {
+ 0xfffe0300, /* vs_3_0 */
+ 0x002efffe, FCC_CTAB, /* CTAB comment */
+ 0x0000001c, 0x000000a4, 0xfffe0300, 0x00000003, 0x0000001c, 0x20008100, /* Header */
+ 0x0000009c,
+ 0x00000058, 0x00070002, 0x00000001, 0x00000064, 0x00000000, /* Constant 1 desc */
+ 0x00000074, 0x00000002, 0x00000004, 0x00000080, 0x00000000, /* Constant 2 desc */
+ 0x00000090, 0x00040002, 0x00000003, 0x00000080, 0x00000000, /* Constant 3 desc */
+ 0x736e6f43, 0x746e6174, 0xabab0031, /* Constant 1 name string */
+ 0x00030001, 0x00040001, 0x00000001, 0x00000000, /* Constant 1 type desc */
+ 0x736e6f43, 0x746e6174, 0xabab0032, /* Constant 2 name string */
+ 0x00030003, 0x00040004, 0x00000001, 0x00000000, /* Constant 2 & 3 type desc */
+ 0x736e6f43, 0x746e6174, 0xabab0033, /* Constant 3 name string */
+ 0x335f7376, 0xab00305f, /* Target name string */
+ 0x656e6957, 0x6f727020, 0x7463656a, 0xababab00, /* Creator name string */
+ 0x0000ffff}; /* END */
+
static void test_get_shader_size(void)
{
UINT shader_size, expected;
@@ -118,7 +135,7 @@ static void test_get_shader_constant_table_ex(void)
{
LPD3DXCONSTANTTABLE constant_table = NULL;
HRESULT hr;
- LPVOID data;
+ LPCSTR data;
DWORD size;
D3DXCONSTANTTABLE_DESC desc;
@@ -150,12 +167,100 @@ static void test_get_shader_constant_table_ex(void)
hr = ID3DXConstantTable_GetDesc(constant_table, &desc);
ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
- ok(desc.Creator == (LPCSTR)data + 0x10, "Got result %p, expected %p\n", desc.Creator, (LPCSTR)data + 0x10);
+ ok(desc.Creator == data + 0x10, "Got result %p, expected %p\n", desc.Creator, data + 0x10);
ok(desc.Version == D3DVS_VERSION(3, 0), "Got result %x, expected %x\n", desc.Version, D3DVS_VERSION(3, 0));
ok(desc.Constants == 0, "Got result %x, expected 0\n", desc.Constants);
ID3DXConstantTable_Release(constant_table);
}
+
+ hr = D3DXGetShaderConstantTableEx(shader_with_ctab_constants, 0, &constant_table);
+ ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
+
+ if (hr == D3D_OK)
+ {
+ D3DXHANDLE constant;
+ D3DXCONSTANT_DESC constant_desc;
+ D3DXCONSTANT_DESC constant_desc_save;
+ UINT nb;
+
+ /* Test GetDesc */
+ hr = ID3DXConstantTable_GetDesc(constant_table, &desc);
+ ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
+ ok(!strcmp(desc.Creator, "Wine project"), "Got result '%s', expected 'Wine project'\n", desc.Creator);
+ ok(desc.Version == D3DVS_VERSION(3, 0), "Got result %x, expected %x\n", desc.Version, D3DVS_VERSION(3, 0));
+ ok(desc.Constants == 3, "Got result %x, expected 3\n", desc.Constants);
+
+ /* Test GetConstant */
+ constant = ID3DXConstantTable_GetConstant(constant_table, NULL, 0);
+ ok(constant != NULL, "No constant found\n");
+ hr = ID3DXConstantTable_GetConstantDesc(constant_table, constant, &constant_desc, &nb);
+ ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
+ ok(!strcmp(constant_desc.Name, "Constant1"), "Got result '%s', expected 'Constant1'\n",
+ constant_desc.Name);
+ ok(constant_desc.Class == D3DXPC_VECTOR, "Got result %x, expected %u (D3DXPC_VECTOR)\n",
+ constant_desc.Class, D3DXPC_VECTOR);
+ ok(constant_desc.Type == D3DXPT_FLOAT, "Got result %x, expected %u (D3DXPT_FLOAT)\n",
+ constant_desc.Type, D3DXPT_FLOAT);
+ ok(constant_desc.Rows == 1, "Got result %x, expected 1\n", constant_desc.Rows);
+ ok(constant_desc.Columns == 4, "Got result %x, expected 4\n", constant_desc.Columns);
+
+ constant = ID3DXConstantTable_GetConstant(constant_table, NULL, 1);
+ ok(constant != NULL, "No constant found\n");
+ hr = ID3DXConstantTable_GetConstantDesc(constant_table, constant, &constant_desc, &nb);
+ ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
+ ok(!strcmp(constant_desc.Name, "Constant2"), "Got result '%s', expected 'Constant2'\n",
+ constant_desc.Name);
+ ok(constant_desc.Class == D3DXPC_MATRIX_COLUMNS, "Got result %x, expected %u (D3DXPC_MATRIX_COLUMNS)\n",
+ constant_desc.Class, D3DXPC_MATRIX_COLUMNS);
+ ok(constant_desc.Type == D3DXPT_FLOAT, "Got result %x, expected %u (D3DXPT_FLOAT)\n",
+ constant_desc.Type, D3DXPT_FLOAT);
+ ok(constant_desc.Rows == 4, "Got result %x, expected 1\n", constant_desc.Rows);
+ ok(constant_desc.Columns == 4, "Got result %x, expected 4\n", constant_desc.Columns);
+
+ constant = ID3DXConstantTable_GetConstant(constant_table, NULL, 2);
+ ok(constant != NULL, "No constant found\n");
+ hr = ID3DXConstantTable_GetConstantDesc(constant_table, constant, &constant_desc, &nb);
+ ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
+ ok(!strcmp(constant_desc.Name, "Constant3"), "Got result '%s', expected 'Constant3'\n",
+ constant_desc.Name);
+ ok(constant_desc.Class == D3DXPC_MATRIX_COLUMNS, "Got result %x, expected %u (D3DXPC_MATRIX_COLUMNS)\n",
+ constant_desc.Class, D3DXPC_MATRIX_COLUMNS);
+ ok(constant_desc.Type == D3DXPT_FLOAT, "Got result %x, expected %u (D3DXPT_FLOAT)\n",
+ constant_desc.Type, D3DXPT_FLOAT);
+ ok(constant_desc.Rows == 4, "Got result %x, expected 1\n", constant_desc.Rows);
+ ok(constant_desc.Columns == 4, "Got result %x, expected 4\n", constant_desc.Columns);
+ constant_desc_save = constant_desc; /* For GetConstantDesc test */
+
+ constant = ID3DXConstantTable_GetConstant(constant_table, NULL, 3);
+ ok(constant == NULL, "Got result %p, expected NULL\n", constant);
+
+ /* Test GetConstantByName */
+ constant = ID3DXConstantTable_GetConstantByName(constant_table, NULL, "Constant unknown");
+ ok(constant == NULL, "Got result %p, expected NULL\n", constant);
+ constant = ID3DXConstantTable_GetConstantByName(constant_table, NULL, "Constant3");
+ ok(constant != NULL, "No constant found\n");
+ hr = ID3DXConstantTable_GetConstantDesc(constant_table, constant, &constant_desc, &nb);
+ ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
+ ok(!memcmp(&constant_desc, &constant_desc_save, sizeof(D3DXCONSTANT_DESC)), "Got different constant data\n");
+
+ /* Test GetConstantDesc */
+ constant = ID3DXConstantTable_GetConstant(constant_table, NULL, 0);
+ ok(constant != NULL, "No constant found\n");
+ hr = ID3DXConstantTable_GetConstantDesc(constant_table, NULL, &constant_desc, &nb);
+ ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
+ hr = ID3DXConstantTable_GetConstantDesc(constant_table, constant, NULL, &nb);
+ ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
+ hr = ID3DXConstantTable_GetConstantDesc(constant_table, constant, &constant_desc, NULL);
+ ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
+ hr = ID3DXConstantTable_GetConstantDesc(constant_table, "Constant unknow", &constant_desc, &nb);
+ ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
+ hr = ID3DXConstantTable_GetConstantDesc(constant_table, "Constant3", &constant_desc, &nb);
+ ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
+ ok(!memcmp(&constant_desc, &constant_desc_save, sizeof(D3DXCONSTANT_DESC)), "Got different constant data\n");
+
+ ID3DXConstantTable_Release(constant_table);
+ }
}
START_TEST(shader)
--
1.7.2.2
More information about the wine-patches
mailing list