From 756f29641b2762aa4b6fe8a718452223642e87cc Mon Sep 17 00:00:00 2001 From: Christian Costa Date: Mon, 26 Mar 2012 22:35:21 +0200 Subject: [PATCH] d3drm: Partial implementation of IDirec3DRM:Load method + tests. --- dlls/d3drm/d3drm.c | 233 +++++++++++++++++++++++++++++++++++++++++++++-- dlls/d3drm/tests/d3drm.c | 56 ++++++++++++ 2 files changed, 283 insertions(+), 6 deletions(-) diff --git a/dlls/d3drm/d3drm.c b/dlls/d3drm/d3drm.c index d140c087f01..afd794e3f76 100644 --- a/dlls/d3drm/d3drm.c +++ b/dlls/d3drm/d3drm.c @@ -25,11 +25,31 @@ #include "winbase.h" #include "wingdi.h" +#include "dxfile.h" +#include "rmxfguid.h" #include "d3drm_private.h" WINE_DEFAULT_DEBUG_CHANNEL(d3drm); +static const char* get_IID_string(const GUID* guid) +{ + if (IsEqualGUID(guid, &IID_IDirect3DRMFrame)) + return "IID_IDirect3DRMFrame"; + else if (IsEqualGUID(guid, &IID_IDirect3DRMFrame2)) + return "IID_IDirect3DRMFrame2"; + else if (IsEqualGUID(guid, &IID_IDirect3DRMFrame3)) + return "IID_IDirect3DRMFrame3"; + else if (IsEqualGUID(guid, &IID_IDirect3DRMMeshBuilder)) + return "IID_IDirect3DRMMeshBuilder"; + else if (IsEqualGUID(guid, &IID_IDirect3DRMMeshBuilder2)) + return "IID_IDirect3DRMMeshBuilder2"; + else if (IsEqualGUID(guid, &IID_IDirect3DRMMeshBuilder3)) + return "IID_IDirect3DRMMeshBuilder3"; + + return "?"; +} + typedef struct { IDirect3DRM IDirect3DRM_iface; IDirect3DRM2 IDirect3DRM2_iface; @@ -387,10 +407,19 @@ static HRESULT WINAPI IDirect3DRMImpl_EnumerateObjects(IDirect3DRM* iface, D3DRM static HRESULT WINAPI IDirect3DRMImpl_Load(IDirect3DRM* iface, LPVOID pObjSource, LPVOID pObjID, LPIID * ppGUIDs, DWORD nb_GUIDs, D3DRMLOADOPTIONS LOFlags, D3DRMLOADCALLBACK LoadProc, LPVOID pArgLP, D3DRMLOADTEXTURECALLBACK LoadTextureProc, LPVOID pArgLTP, LPDIRECT3DRMFRAME pParentFrame) { IDirect3DRMImpl *This = impl_from_IDirect3DRM(iface); + LPDIRECT3DRMFRAME3 pParentFrame3 = NULL; + HRESULT hr = D3DRM_OK; - FIXME("(%p/%p)->(%p,%p,%p,%d,%d,%p,%p,%p,%p,%p): stub\n", iface, This, pObjSource, pObjID, ppGUIDs, nb_GUIDs, LOFlags, LoadProc, pArgLP, LoadTextureProc, pArgLTP, pParentFrame); + TRACE("(%p/%p)->(%p,%p,%p,%d,%d,%p,%p,%p,%p,%p)\n", iface, This, pObjSource, pObjID, ppGUIDs, nb_GUIDs, LOFlags, LoadProc, pArgLP, LoadTextureProc, pArgLTP, pParentFrame); - return E_NOTIMPL; + if (pParentFrame) + hr = IDirect3DRMFrame_QueryInterface(pParentFrame, &IID_IDirect3DRMFrame3, (void**)&pParentFrame3); + if (SUCCEEDED(hr)) + hr = IDirect3DRM3_Load(&This->IDirect3DRM3_iface, pObjSource, pObjID, ppGUIDs, nb_GUIDs, LOFlags, LoadProc, pArgLP, LoadTextureProc, pArgLTP, pParentFrame3); + if (pParentFrame3) + IDirect3DRMFrame3_Release(pParentFrame3); + + return hr; } static HRESULT WINAPI IDirect3DRMImpl_Tick(IDirect3DRM* iface, D3DVALUE tick) @@ -796,11 +825,20 @@ static HRESULT WINAPI IDirect3DRM2Impl_Load(IDirect3DRM2* iface, LPVOID pObjSour LPVOID pArgLTP, LPDIRECT3DRMFRAME pParentFrame) { IDirect3DRMImpl *This = impl_from_IDirect3DRM2(iface); + LPDIRECT3DRMFRAME3 pParentFrame3 = NULL; + HRESULT hr = D3DRM_OK; - FIXME("(%p/%p)->(%p,%p,%p,%d,%d,%p,%p,%p,%p,%p): stub\n", iface, This, pObjSource, pObjID, + TRACE("(%p/%p)->(%p,%p,%p,%d,%d,%p,%p,%p,%p,%p)\n", iface, This, pObjSource, pObjID, ppGUIDs, nb_GUIDs, LOFlags, LoadProc, pArgLP, LoadTextureProc, pArgLTP, pParentFrame); - return E_NOTIMPL; + if (pParentFrame) + hr = IDirect3DRMFrame_QueryInterface(pParentFrame, &IID_IDirect3DRMFrame3, (void**)&pParentFrame3); + if (SUCCEEDED(hr)) + hr = IDirect3DRM3_Load(&This->IDirect3DRM3_iface, pObjSource, pObjID, ppGUIDs, nb_GUIDs, LOFlags, LoadProc, pArgLP, LoadTextureProc, pArgLTP, pParentFrame3); + if (pParentFrame3) + IDirect3DRMFrame3_Release(pParentFrame3); + + return hr; } static HRESULT WINAPI IDirect3DRM2Impl_Tick(IDirect3DRM2* iface, D3DVALUE tick) @@ -1214,10 +1252,193 @@ static HRESULT WINAPI IDirect3DRM3Impl_Load(IDirect3DRM3* iface, LPVOID ObjSourc LPDIRECT3DRMFRAME3 ParentFrame) { IDirect3DRMImpl *This = impl_from_IDirect3DRM3(iface); - - FIXME("(%p/%p)->(%p,%p,%p,%d,%d,%p,%p,%p,%p,%p): stub\n", iface, This, ObjSource, ObjID, GUIDs, + DXFILELOADOPTIONS load_options; + LPDIRECTXFILE pDXFile = NULL; + LPDIRECTXFILEENUMOBJECT pEnumObject = NULL; + LPDIRECTXFILEDATA pData = NULL; + HRESULT hr; + const GUID* pGuid; + DWORD size; + Header* pHeader; + HRESULT ret = D3DRMERR_BADOBJECT; + DWORD i; + + FIXME("(%p/%p)->(%p,%p,%p,%d,%d,%p,%p,%p,%p,%p): partial implementation\n", iface, This, ObjSource, ObjID, GUIDs, nb_GUIDs, LOFlags, LoadProc, ArgLP, LoadTextureProc, ArgLTP, ParentFrame); + TRACE("Looking for GUIDs:\n"); + for (i = 0; i < nb_GUIDs; i++) + TRACE("- %s (%s)\n", debugstr_guid(GUIDs[i]), get_IID_string(GUIDs[i])); + + if (LOFlags == D3DRMLOAD_FROMMEMORY) + { + load_options = DXFILELOAD_FROMMEMORY; + } + else if (LOFlags == D3DRMLOAD_FROMFILE) + { + load_options = DXFILELOAD_FROMFILE; + } + else + { + FIXME("Load options %d not supported yet\n", LOFlags); + return E_NOTIMPL; + } + + hr = DirectXFileCreate(&pDXFile); + if (hr != DXFILE_OK) + goto end; + + hr = IDirectXFile_RegisterTemplates(pDXFile, templates, strlen(templates)); + if (hr != DXFILE_OK) + goto end; + + hr = IDirectXFile_CreateEnumObject(pDXFile, ObjSource, load_options, &pEnumObject); + if (hr != DXFILE_OK) + goto end; + + hr = IDirectXFileEnumObject_GetNextDataObject(pEnumObject, &pData); + if (hr != DXFILE_OK) + goto end; + + hr = IDirectXFileData_GetType(pData, &pGuid); + if (hr != DXFILE_OK) + goto end; + + TRACE("Found object type whose GUID = %s\n", debugstr_guid(pGuid)); + + if (!IsEqualGUID(pGuid, &TID_DXFILEHeader)) + { + ret = D3DRMERR_BADFILE; + goto end; + } + + hr = IDirectXFileData_GetData(pData, NULL, &size, (void**)&pHeader); + if ((hr != DXFILE_OK) || (size != sizeof(Header))) + goto end; + + TRACE("Version is %d %d %d\n", pHeader->major, pHeader->minor, pHeader->flags); + + /* Version must be 1.0.x */ + if ((pHeader->major != 1) || (pHeader->minor != 0)) + { + ret = D3DRMERR_BADFILE; + goto end; + } + + IDirectXFileData_Release(pData); + pData = NULL; + + while (1) + { + hr = IDirectXFileEnumObject_GetNextDataObject(pEnumObject, &pData); + if (hr == DXFILEERR_NOMOREOBJECTS) + { + TRACE("No more object\n"); + break; + } + else if (hr != DXFILE_OK) + { + ret = D3DRMERR_NOTFOUND; + goto end; + } + + hr = IDirectXFileData_GetType(pData, &pGuid); + if (hr != DXFILE_OK) + goto end; + + TRACE("Found object type whose GUID = %s\n", debugstr_guid(pGuid)); + + if (IsEqualGUID(pGuid, &TID_D3DRMMesh)) + { + BOOL requested = FALSE; + HRESULT hr; + LPDIRECT3DRMMESHBUILDER3 pMeshBuilder; + + TRACE("Found TID_D3DRMMesh\n"); + + for (i = 0; i < nb_GUIDs; i++) + if (IsEqualGUID(GUIDs[i], &IID_IDirect3DRMMeshBuilder) || + IsEqualGUID(GUIDs[i], &IID_IDirect3DRMMeshBuilder2) || + IsEqualGUID(GUIDs[i], &IID_IDirect3DRMMeshBuilder3)) + requested = TRUE; + + if (requested) + { + FIXME("Load mesh data and notify application\n"); + + hr = IDirect3DRM3_CreateMeshBuilder(iface, &pMeshBuilder); + if (SUCCEEDED(hr)) + { + LPDIRECT3DRMMESHBUILDER3 pMeshBuilder3; + + hr = IDirect3DRMMeshBuilder3_QueryInterface(pMeshBuilder, &IID_IDirect3DRMMeshBuilder3, (void**)&pMeshBuilder3); + if (SUCCEEDED(hr)) + { + hr = load_mesh_data(pMeshBuilder3, pData); + IDirect3DRMMeshBuilder3_Release(pMeshBuilder3); + } + if (SUCCEEDED(hr)) + LoadProc((LPDIRECT3DRMOBJECT)pMeshBuilder3, &IID_IDirect3DRMMeshBuilder, ArgLP); + IDirect3DRMMeshBuilder_Release(pMeshBuilder3); + } + + if (FAILED(hr)) + ERR("Cannot process mesh\n"); + } + } + else if (IsEqualGUID(pGuid, &TID_D3DRMFrame)) + { + BOOL requested = FALSE; + + TRACE("Found TID_D3DRMFrame\n"); + + for (i = 0; i < nb_GUIDs; i++) + if (IsEqualGUID(GUIDs[i], &IID_IDirect3DRMFrame) || + IsEqualGUID(GUIDs[i], &IID_IDirect3DRMFrame2) || + IsEqualGUID(GUIDs[i], &IID_IDirect3DRMFrame3)) + requested = TRUE; + + if (requested) + { + FIXME("Processing frame not supported yet\n"); + } + } + else if (IsEqualGUID(pGuid, &TID_D3DRMMaterial)) + { + BOOL requested = FALSE; + + TRACE("Found TID_D3DRMMaterial\n"); + + for (i = 0; i < nb_GUIDs; i++) + if (IsEqualGUID(GUIDs[i], &IID_IDirect3DRMMaterial) || + IsEqualGUID(GUIDs[i], &IID_IDirect3DRMMaterial2)) + requested = TRUE; + + if (requested) + { + FIXME("Processing material not supported yet\n"); + } + } + else + { + FIXME("Found unknown TID %s\n", debugstr_guid(pGuid)); + } + IDirectXFileData_Release(pData); + pData = NULL; + } + + ret = D3DRM_OK; + +end: + if (pData) + IDirectXFileData_Release(pData); + if (pEnumObject) + IDirectXFileEnumObject_Release(pEnumObject); + if (pDXFile) + IDirectXFile_Release(pDXFile); + + return ret; + return E_NOTIMPL; } diff --git a/dlls/d3drm/tests/d3drm.c b/dlls/d3drm/tests/d3drm.c index a1dee307988..8d18d3b9032 100644 --- a/dlls/d3drm/tests/d3drm.c +++ b/dlls/d3drm/tests/d3drm.c @@ -134,6 +134,27 @@ static char data_full[] = " }\n" "}\n"; +static char data_d3drm_load[] = +"xof 0302txt 0064\n" +"Header Object\n" +"{\n" +"1; 0; 1;\n" +"}\n" +"Mesh Object1\n" +"{\n" +" 1;\n" +" 0.1; 0.2; 0.3;,\n" +" 1;\n" +" 3; 0, 1, 2;;\n" +"}\n" +"Mesh Object2\n" +"{\n" +" 1;\n" +" 0.1; 0.2; 0.3;,\n" +" 1;\n" +" 3; 0, 1, 2;;\n" +"}\n"; + static void test_MeshBuilder(void) { HRESULT hr; @@ -579,6 +600,40 @@ static void test_Frame(void) IDirect3DRM_Release(pD3DRM); } +static int nb_objects = 0; +static const GUID* refiids[] = +{ + &IID_IDirect3DRMMeshBuilder, + &IID_IDirect3DRMMeshBuilder +}; + +void __cdecl object_load_callback(LPDIRECT3DRMOBJECT object, REFIID objectguid, LPVOID arg) +{ + ok(object != NULL, "Arg 1 should not be null\n"); + ok(IsEqualGUID(objectguid, refiids[nb_objects]), "Arg 2 should is incorrect\n"); + ok(arg == (LPVOID)0xdeadbeef, "Arg 3 should be 0xdeadbeef (got %p)\n", arg); + nb_objects++; +} + +static void test_d3drm_load(void) +{ + HRESULT hr; + LPDIRECT3DRM pD3DRM; + D3DRMLOADMEMORY info; + const GUID* req_refiids[] = { &IID_IDirect3DRMMeshBuilder }; + + hr = pDirect3DRMCreate(&pD3DRM); + ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x)\n", hr); + + info.lpMemory = data_d3drm_load; + info.dSize = strlen(data_d3drm_load); + hr = IDirect3DRM_Load(pD3DRM, &info, NULL, (GUID**)req_refiids, 1, D3DRMLOAD_FROMMEMORY, object_load_callback, (LPVOID)0xdeadbeef, NULL, NULL, NULL); + ok(hr == D3DRM_OK, "Cannot load data (hr = %x)\n", hr); + ok(nb_objects == 2, "Should have loaded 2 objects (got %d)\n", nb_objects); + + IDirect3DRM_Release(pD3DRM); +} + START_TEST(d3drm) { if (!InitFunctionPtrs()) @@ -587,6 +642,7 @@ START_TEST(d3drm) test_MeshBuilder(); test_MeshBuilder3(); test_Frame(); + test_d3drm_load(); FreeLibrary(d3drm_handle); } -- 2.11.4.GIT