/* * Copyright 2016 Andrey Gusev * * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include "d3d10_1.h" #include "d3dx10.h" #include "d3dcompiler.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(d3dx); struct asyncdataloader { ID3DX10DataLoader ID3DX10DataLoader_iface; union { struct { WCHAR *path; } file; struct { HMODULE module; HRSRC rsrc; } resource; } u; void *data; SIZE_T size; }; static inline struct asyncdataloader *impl_from_ID3DX10DataLoader(ID3DX10DataLoader *iface) { return CONTAINING_RECORD(iface, struct asyncdataloader, ID3DX10DataLoader_iface); } static HRESULT WINAPI memorydataloader_Load(ID3DX10DataLoader *iface) { TRACE("iface %p.\n", iface); return S_OK; } static HRESULT WINAPI memorydataloader_Decompress(ID3DX10DataLoader *iface, void **data, SIZE_T *size) { struct asyncdataloader *loader = impl_from_ID3DX10DataLoader(iface); TRACE("iface %p, data %p, size %p.\n", iface, data, size); *data = loader->data; *size = loader->size; return S_OK; } static HRESULT WINAPI memorydataloader_Destroy(ID3DX10DataLoader *iface) { struct asyncdataloader *loader = impl_from_ID3DX10DataLoader(iface); TRACE("iface %p.\n", iface); HeapFree(GetProcessHeap(), 0, loader); return S_OK; } static const ID3DX10DataLoaderVtbl memorydataloadervtbl = { memorydataloader_Load, memorydataloader_Decompress, memorydataloader_Destroy }; static HRESULT WINAPI filedataloader_Load(ID3DX10DataLoader *iface) { struct asyncdataloader *loader = impl_from_ID3DX10DataLoader(iface); DWORD size, read_len; HANDLE file; void *data; BOOL ret; TRACE("iface %p.\n", iface); /* Always buffer file contents, even if Load() was already called. */ file = CreateFileW(loader->u.file.path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (file == INVALID_HANDLE_VALUE) return D3D10_ERROR_FILE_NOT_FOUND; size = GetFileSize(file, NULL); data = HeapAlloc(GetProcessHeap(), 0, size); if (!data) { CloseHandle(file); return E_OUTOFMEMORY; } ret = ReadFile(file, data, size, &read_len, NULL); CloseHandle(file); if (!ret) { WARN("Failed to read file contents.\n"); HeapFree(GetProcessHeap(), 0, data); return E_FAIL; } HeapFree(GetProcessHeap(), 0, loader->data); loader->data = data; loader->size = size; return S_OK; } static HRESULT WINAPI filedataloader_Decompress(ID3DX10DataLoader *iface, void **data, SIZE_T *size) { struct asyncdataloader *loader = impl_from_ID3DX10DataLoader(iface); TRACE("iface %p, data %p, size %p.\n", iface, data, size); if (!loader->data) return E_FAIL; *data = loader->data; *size = loader->size; return S_OK; } static HRESULT WINAPI filedataloader_Destroy(ID3DX10DataLoader *iface) { struct asyncdataloader *loader = impl_from_ID3DX10DataLoader(iface); TRACE("iface %p.\n", iface); HeapFree(GetProcessHeap(), 0, loader->u.file.path); HeapFree(GetProcessHeap(), 0, loader->data); HeapFree(GetProcessHeap(), 0, loader); return S_OK; } static const ID3DX10DataLoaderVtbl filedataloadervtbl = { filedataloader_Load, filedataloader_Decompress, filedataloader_Destroy }; static HRESULT WINAPI resourcedataloader_Load(ID3DX10DataLoader *iface) { struct asyncdataloader *loader = impl_from_ID3DX10DataLoader(iface); HGLOBAL hglobal; TRACE("iface %p.\n", iface); if (loader->data) return S_OK; hglobal = LoadResource(loader->u.resource.module, loader->u.resource.rsrc); if (!hglobal) { WARN("Failed to load resource.\n"); return E_FAIL; } loader->data = LockResource(hglobal); loader->size = SizeofResource(loader->u.resource.module, loader->u.resource.rsrc); return S_OK; } static HRESULT WINAPI resourcedataloader_Decompress(ID3DX10DataLoader *iface, void **data, SIZE_T *size) { struct asyncdataloader *loader = impl_from_ID3DX10DataLoader(iface); TRACE("iface %p, data %p, size %p.\n", iface, data, size); if (!loader->data) return E_FAIL; *data = loader->data; *size = loader->size; return S_OK; } static HRESULT WINAPI resourcedataloader_Destroy(ID3DX10DataLoader *iface) { struct asyncdataloader *loader = impl_from_ID3DX10DataLoader(iface); TRACE("iface %p.\n", iface); HeapFree(GetProcessHeap(), 0, loader); return S_OK; } static const ID3DX10DataLoaderVtbl resourcedataloadervtbl = { resourcedataloader_Load, resourcedataloader_Decompress, resourcedataloader_Destroy }; HRESULT WINAPI D3DX10CompileFromMemory(const char *data, SIZE_T data_size, const char *filename, const D3D10_SHADER_MACRO *defines, ID3D10Include *include, const char *entry_point, const char *target, UINT sflags, UINT eflags, ID3DX10ThreadPump *pump, ID3D10Blob **shader, ID3D10Blob **error_messages, HRESULT *hresult) { TRACE("data %s, data_size %lu, filename %s, defines %p, include %p, entry_point %s, target %s, " "sflags %#x, eflags %#x, pump %p, shader %p, error_messages %p, hresult %p.\n", debugstr_an(data, data_size), data_size, debugstr_a(filename), defines, include, debugstr_a(entry_point), debugstr_a(target), sflags, eflags, pump, shader, error_messages, hresult); if (pump) FIXME("Unimplemented ID3DX10ThreadPump handling.\n"); return D3DCompile(data, data_size, filename, defines, include, entry_point, target, sflags, eflags, shader, error_messages); } HRESULT WINAPI D3DX10CreateEffectPoolFromFileA(const char *filename, const D3D10_SHADER_MACRO *defines, ID3D10Include *include, const char *profile, UINT hlslflags, UINT fxflags, ID3D10Device *device, ID3DX10ThreadPump *pump, ID3D10EffectPool **effectpool, ID3D10Blob **errors, HRESULT *hresult) { FIXME("filename %s, defines %p, include %p, profile %s, hlslflags %#x, fxflags %#x, device %p, " "pump %p, effectpool %p, errors %p, hresult %p, stub!\n", debugstr_a(filename), defines, include, debugstr_a(profile), hlslflags, fxflags, device, pump, effectpool, errors, hresult); return E_NOTIMPL; } HRESULT WINAPI D3DX10CreateEffectPoolFromFileW(const WCHAR *filename, const D3D10_SHADER_MACRO *defines, ID3D10Include *include, const char *profile, UINT hlslflags, UINT fxflags, ID3D10Device *device, ID3DX10ThreadPump *pump, ID3D10EffectPool **effectpool, ID3D10Blob **errors, HRESULT *hresult) { FIXME("filename %s, defines %p, include %p, profile %s, hlslflags %#x, fxflags %#x, device %p, " "pump %p, effectpool %p, errors %p, hresult %p, stub!\n", debugstr_w(filename), defines, include, debugstr_a(profile), hlslflags, fxflags, device, pump, effectpool, errors, hresult); return E_NOTIMPL; } HRESULT WINAPI D3DX10CreateAsyncMemoryLoader(const void *data, SIZE_T data_size, ID3DX10DataLoader **loader) { struct asyncdataloader *object; TRACE("data %p, data_size %lu, loader %p.\n", data, data_size, loader); if (!data || !loader) return E_FAIL; object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); if (!object) return E_OUTOFMEMORY; object->ID3DX10DataLoader_iface.lpVtbl = &memorydataloadervtbl; object->data = (void *)data; object->size = data_size; *loader = &object->ID3DX10DataLoader_iface; return S_OK; } HRESULT WINAPI D3DX10CreateAsyncFileLoaderA(const char *filename, ID3DX10DataLoader **loader) { WCHAR *filename_w; HRESULT hr; int len; TRACE("filename %s, loader %p.\n", debugstr_a(filename), loader); if (!filename || !loader) return E_FAIL; len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0); filename_w = HeapAlloc(GetProcessHeap(), 0, len * sizeof(*filename_w)); MultiByteToWideChar(CP_ACP, 0, filename, -1, filename_w, len); hr = D3DX10CreateAsyncFileLoaderW(filename_w, loader); HeapFree(GetProcessHeap(), 0, filename_w); return hr; } HRESULT WINAPI D3DX10CreateAsyncFileLoaderW(const WCHAR *filename, ID3DX10DataLoader **loader) { struct asyncdataloader *object; TRACE("filename %s, loader %p.\n", debugstr_w(filename), loader); if (!filename || !loader) return E_FAIL; object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); if (!object) return E_OUTOFMEMORY; object->ID3DX10DataLoader_iface.lpVtbl = &filedataloadervtbl; object->u.file.path = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(filename) + 1) * sizeof(WCHAR)); if (!object->u.file.path) { HeapFree(GetProcessHeap(), 0, object); return E_OUTOFMEMORY; } lstrcpyW(object->u.file.path, filename); object->data = NULL; object->size = 0; *loader = &object->ID3DX10DataLoader_iface; return S_OK; } HRESULT WINAPI D3DX10CreateAsyncResourceLoaderA(HMODULE module, const char *resource, ID3DX10DataLoader **loader) { struct asyncdataloader *object; HRSRC rsrc; TRACE("module %p, resource %s, loader %p.\n", module, debugstr_a(resource), loader); if (!loader) return E_FAIL; object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); if (!object) return E_OUTOFMEMORY; if (!(rsrc = FindResourceA(module, resource, (const char *)RT_RCDATA))) { WARN("Failed to find resource.\n"); HeapFree(GetProcessHeap(), 0, object); return D3DX10_ERR_INVALID_DATA; } object->ID3DX10DataLoader_iface.lpVtbl = &resourcedataloadervtbl; object->u.resource.module = module; object->u.resource.rsrc = rsrc; object->data = NULL; object->size = 0; *loader = &object->ID3DX10DataLoader_iface; return S_OK; } HRESULT WINAPI D3DX10CreateAsyncResourceLoaderW(HMODULE module, const WCHAR *resource, ID3DX10DataLoader **loader) { struct asyncdataloader *object; HRSRC rsrc; TRACE("module %p, resource %s, loader %p.\n", module, debugstr_w(resource), loader); if (!loader) return E_FAIL; object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); if (!object) return E_OUTOFMEMORY; if (!(rsrc = FindResourceW(module, resource, (const WCHAR *)RT_RCDATA))) { WARN("Failed to find resource.\n"); HeapFree(GetProcessHeap(), 0, object); return D3DX10_ERR_INVALID_DATA; } object->ID3DX10DataLoader_iface.lpVtbl = &resourcedataloadervtbl; object->u.resource.module = module; object->u.resource.rsrc = rsrc; object->data = NULL; object->size = 0; *loader = &object->ID3DX10DataLoader_iface; return S_OK; } HRESULT WINAPI D3DX10PreprocessShaderFromMemory(const char *data, SIZE_T data_size, const char *filename, const D3D10_SHADER_MACRO *defines, ID3DInclude *include, ID3DX10ThreadPump *pump, ID3D10Blob **shader_text, ID3D10Blob **errors, HRESULT *hresult) { FIXME("data %s, data_size %lu, filename %s, defines %p, include %p, pump %p, shader_text %p, " "errors %p, hresult %p stub!\n", debugstr_an(data, data_size), data_size, debugstr_a(filename), defines, include, pump, shader_text, errors, hresult); return E_NOTIMPL; }