diff options
| author | Lorry Tar Creator <lorry-tar-importer@baserock.org> | 2014-03-26 19:21:20 +0000 |
|---|---|---|
| committer | <> | 2014-05-08 15:03:54 +0000 |
| commit | fb123f93f9f5ce42c8e5785d2f8e0edaf951740e (patch) | |
| tree | c2103d76aec5f1f10892cd1d3a38e24f665ae5db /src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8 | |
| parent | 58ed4748338f9466599adfc8a9171280ed99e23f (diff) | |
| download | VirtualBox-master.tar.gz | |
Imported from /home/lorry/working-area/delta_VirtualBox/VirtualBox-4.3.10.tar.bz2.HEADVirtualBox-4.3.10master
Diffstat (limited to 'src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8')
14 files changed, 7497 insertions, 0 deletions
diff --git a/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/Makefile.kup b/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/Makefile.kup new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/Makefile.kup diff --git a/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/buffer.c b/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/buffer.c new file mode 100644 index 00000000..9599c9af --- /dev/null +++ b/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/buffer.c @@ -0,0 +1,620 @@ +/* + * Copyright 2005 Oliver Stieber + * + * 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 + */ + +/* + * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice + * other than GPL or LGPL is available it will apply instead, Oracle elects to use only + * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where + * a choice of LGPL license versions is made available with the language indicating + * that LGPLv2 or any later version may be used, or where a choice of which version + * of the LGPL is applied is otherwise unspecified. + */ + +#include "config.h" +#include "d3d8_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(d3d8); + +static inline struct d3d8_vertexbuffer *impl_from_IDirect3DVertexBuffer8(IDirect3DVertexBuffer8 *iface) +{ + return CONTAINING_RECORD(iface, struct d3d8_vertexbuffer, IDirect3DVertexBuffer8_iface); +} + +static HRESULT WINAPI d3d8_vertexbuffer_QueryInterface(IDirect3DVertexBuffer8 *iface, REFIID riid, void **object) +{ + TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object); + + if (IsEqualGUID(riid, &IID_IDirect3DVertexBuffer8) + || IsEqualGUID(riid, &IID_IDirect3DResource8) + || IsEqualGUID(riid, &IID_IUnknown)) + { + IDirect3DVertexBuffer8_AddRef(iface); + *object = iface; + return S_OK; + } + + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid)); + + *object = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI d3d8_vertexbuffer_AddRef(IDirect3DVertexBuffer8 *iface) +{ + struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface); + ULONG refcount = InterlockedIncrement(&buffer->refcount); + + TRACE("%p increasing refcount to %u.\n", iface, refcount); + + if (refcount == 1) + { + IDirect3DDevice8_AddRef(buffer->parent_device); + wined3d_mutex_lock(); + wined3d_buffer_incref(buffer->wined3d_buffer); + wined3d_mutex_unlock(); + } + + return refcount; +} + +static ULONG WINAPI d3d8_vertexbuffer_Release(IDirect3DVertexBuffer8 *iface) +{ + struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface); + ULONG refcount = InterlockedDecrement(&buffer->refcount); + + TRACE("%p decreasing refcount to %u.\n", iface, refcount); + + if (!refcount) + { + IDirect3DDevice8 *device = buffer->parent_device; + + wined3d_mutex_lock(); + wined3d_buffer_decref(buffer->wined3d_buffer); + wined3d_mutex_unlock(); + + /* Release the device last, as it may cause the device to be destroyed. */ + IDirect3DDevice8_Release(device); + } + + return refcount; +} + +static HRESULT WINAPI d3d8_vertexbuffer_GetDevice(IDirect3DVertexBuffer8 *iface, + IDirect3DDevice8 **device) +{ + struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface); + + TRACE("iface %p, device %p.\n", iface, device); + + *device = buffer->parent_device; + IDirect3DDevice8_AddRef(*device); + + TRACE("Returning device %p.\n", *device); + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_vertexbuffer_SetPrivateData(IDirect3DVertexBuffer8 *iface, + REFGUID guid, const void *data, DWORD data_size, DWORD flags) +{ + struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface); + struct wined3d_resource *resource; + HRESULT hr; + + TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n", + iface, debugstr_guid(guid), data, data_size, flags); + + wined3d_mutex_lock(); + resource = wined3d_buffer_get_resource(buffer->wined3d_buffer); + hr = wined3d_resource_set_private_data(resource, guid, data, data_size, flags); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_vertexbuffer_GetPrivateData(IDirect3DVertexBuffer8 *iface, + REFGUID guid, void *data, DWORD *data_size) +{ + struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface); + struct wined3d_resource *resource; + HRESULT hr; + + TRACE("iface %p, guid %s, data %p, data_size %p.\n", + iface, debugstr_guid(guid), data, data_size); + + wined3d_mutex_lock(); + resource = wined3d_buffer_get_resource(buffer->wined3d_buffer); + hr = wined3d_resource_get_private_data(resource, guid, data, data_size); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_vertexbuffer_FreePrivateData(IDirect3DVertexBuffer8 *iface, REFGUID guid) +{ + struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface); + struct wined3d_resource *resource; + HRESULT hr; + + TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid)); + + wined3d_mutex_lock(); + resource = wined3d_buffer_get_resource(buffer->wined3d_buffer); + hr = wined3d_resource_free_private_data(resource, guid); + wined3d_mutex_unlock(); + + return hr; +} + +static DWORD WINAPI d3d8_vertexbuffer_SetPriority(IDirect3DVertexBuffer8 *iface, DWORD priority) +{ + struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface); + DWORD previous; + + TRACE("iface %p, priority %u.\n", iface, priority); + + wined3d_mutex_lock(); + previous = wined3d_buffer_set_priority(buffer->wined3d_buffer, priority); + wined3d_mutex_unlock(); + + return previous; +} + +static DWORD WINAPI d3d8_vertexbuffer_GetPriority(IDirect3DVertexBuffer8 *iface) +{ + struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface); + DWORD priority; + + TRACE("iface %p.\n", iface); + + wined3d_mutex_lock(); + priority = wined3d_buffer_get_priority(buffer->wined3d_buffer); + wined3d_mutex_unlock(); + + return priority; +} + +static void WINAPI d3d8_vertexbuffer_PreLoad(IDirect3DVertexBuffer8 *iface) +{ + struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface); + + TRACE("iface %p.\n", iface); + + wined3d_mutex_lock(); + wined3d_buffer_preload(buffer->wined3d_buffer); + wined3d_mutex_unlock(); +} + +static D3DRESOURCETYPE WINAPI d3d8_vertexbuffer_GetType(IDirect3DVertexBuffer8 *iface) +{ + TRACE("iface %p.\n", iface); + + return D3DRTYPE_VERTEXBUFFER; +} + +static HRESULT WINAPI d3d8_vertexbuffer_Lock(IDirect3DVertexBuffer8 *iface, UINT offset, UINT size, + BYTE **data, DWORD flags) +{ + struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface); + HRESULT hr; + + TRACE("iface %p, offset %u, size %u, data %p, flags %#x.\n", + iface, offset, size, data, flags); + + wined3d_mutex_lock(); + hr = wined3d_buffer_map(buffer->wined3d_buffer, offset, size, data, flags); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_vertexbuffer_Unlock(IDirect3DVertexBuffer8 *iface) +{ + struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface); + + TRACE("iface %p.\n", iface); + + wined3d_mutex_lock(); + wined3d_buffer_unmap(buffer->wined3d_buffer); + wined3d_mutex_unlock(); + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_vertexbuffer_GetDesc(IDirect3DVertexBuffer8 *iface, + D3DVERTEXBUFFER_DESC *desc) +{ + struct d3d8_vertexbuffer *buffer = impl_from_IDirect3DVertexBuffer8(iface); + struct wined3d_resource_desc wined3d_desc; + struct wined3d_resource *wined3d_resource; + + TRACE("iface %p, desc %p.\n", iface, desc); + + wined3d_mutex_lock(); + wined3d_resource = wined3d_buffer_get_resource(buffer->wined3d_buffer); + wined3d_resource_get_desc(wined3d_resource, &wined3d_desc); + wined3d_mutex_unlock(); + + desc->Type = D3DRTYPE_VERTEXBUFFER; + desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK; + desc->Pool = wined3d_desc.pool; + desc->Size = wined3d_desc.size; + desc->FVF = buffer->fvf; + desc->Format = D3DFMT_VERTEXDATA; + + return D3D_OK; +} + +static const IDirect3DVertexBuffer8Vtbl Direct3DVertexBuffer8_Vtbl = +{ + /* IUnknown */ + d3d8_vertexbuffer_QueryInterface, + d3d8_vertexbuffer_AddRef, + d3d8_vertexbuffer_Release, + /* IDirect3DResource8 */ + d3d8_vertexbuffer_GetDevice, + d3d8_vertexbuffer_SetPrivateData, + d3d8_vertexbuffer_GetPrivateData, + d3d8_vertexbuffer_FreePrivateData, + d3d8_vertexbuffer_SetPriority, + d3d8_vertexbuffer_GetPriority, + d3d8_vertexbuffer_PreLoad, + d3d8_vertexbuffer_GetType, + /* IDirect3DVertexBuffer8 */ + d3d8_vertexbuffer_Lock, + d3d8_vertexbuffer_Unlock, + d3d8_vertexbuffer_GetDesc, +}; + +static void STDMETHODCALLTYPE d3d8_vertexbuffer_wined3d_object_destroyed(void *parent) +{ + HeapFree(GetProcessHeap(), 0, parent); +} + +static const struct wined3d_parent_ops d3d8_vertexbuffer_wined3d_parent_ops = +{ + d3d8_vertexbuffer_wined3d_object_destroyed, +}; + +HRESULT vertexbuffer_init(struct d3d8_vertexbuffer *buffer, struct d3d8_device *device, + UINT size, DWORD usage, DWORD fvf, D3DPOOL pool) +{ + HRESULT hr; + + buffer->IDirect3DVertexBuffer8_iface.lpVtbl = &Direct3DVertexBuffer8_Vtbl; + buffer->refcount = 1; + buffer->fvf = fvf; + + wined3d_mutex_lock(); + hr = wined3d_buffer_create_vb(device->wined3d_device, size, usage & WINED3DUSAGE_MASK, + (enum wined3d_pool)pool, buffer, &d3d8_vertexbuffer_wined3d_parent_ops, &buffer->wined3d_buffer); + wined3d_mutex_unlock(); + if (FAILED(hr)) + { + WARN("Failed to create wined3d buffer, hr %#x.\n", hr); + return hr; + } + + buffer->parent_device = &device->IDirect3DDevice8_iface; + IDirect3DDevice8_AddRef(buffer->parent_device); + + return D3D_OK; +} + +struct d3d8_vertexbuffer *unsafe_impl_from_IDirect3DVertexBuffer8(IDirect3DVertexBuffer8 *iface) +{ + if (!iface) + return NULL; + assert(iface->lpVtbl == &Direct3DVertexBuffer8_Vtbl); + + return impl_from_IDirect3DVertexBuffer8(iface); +} + +static inline struct d3d8_indexbuffer *impl_from_IDirect3DIndexBuffer8(IDirect3DIndexBuffer8 *iface) +{ + return CONTAINING_RECORD(iface, struct d3d8_indexbuffer, IDirect3DIndexBuffer8_iface); +} + +static HRESULT WINAPI d3d8_indexbuffer_QueryInterface(IDirect3DIndexBuffer8 *iface, REFIID riid, void **object) +{ + TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object); + + if (IsEqualGUID(riid, &IID_IDirect3DIndexBuffer8) + || IsEqualGUID(riid, &IID_IDirect3DResource8) + || IsEqualGUID(riid, &IID_IUnknown)) + { + IDirect3DIndexBuffer8_AddRef(iface); + *object = iface; + return S_OK; + } + + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid)); + + *object = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI d3d8_indexbuffer_AddRef(IDirect3DIndexBuffer8 *iface) +{ + struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface); + ULONG refcount = InterlockedIncrement(&buffer->refcount); + + TRACE("%p increasing refcount to %u.\n", iface, refcount); + + if (refcount == 1) + { + IDirect3DDevice8_AddRef(buffer->parent_device); + wined3d_mutex_lock(); + wined3d_buffer_incref(buffer->wined3d_buffer); + wined3d_mutex_unlock(); + } + + return refcount; +} + +static ULONG WINAPI d3d8_indexbuffer_Release(IDirect3DIndexBuffer8 *iface) +{ + struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface); + ULONG refcount = InterlockedDecrement(&buffer->refcount); + + TRACE("%p decreasing refcount to %u.\n", iface, refcount); + + if (!refcount) + { + IDirect3DDevice8 *device = buffer->parent_device; + + wined3d_mutex_lock(); + wined3d_buffer_decref(buffer->wined3d_buffer); + wined3d_mutex_unlock(); + + /* Release the device last, as it may cause the device to be destroyed. */ + IDirect3DDevice8_Release(device); + } + + return refcount; +} + +static HRESULT WINAPI d3d8_indexbuffer_GetDevice(IDirect3DIndexBuffer8 *iface, + IDirect3DDevice8 **device) +{ + struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface); + + TRACE("iface %p, device %p.\n", iface, device); + + *device = buffer->parent_device; + IDirect3DDevice8_AddRef(*device); + + TRACE("Returning device %p.\n", *device); + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_indexbuffer_SetPrivateData(IDirect3DIndexBuffer8 *iface, + REFGUID guid, const void *data, DWORD data_size, DWORD flags) +{ + struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface); + struct wined3d_resource *resource; + HRESULT hr; + + TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n", + iface, debugstr_guid(guid), data, data_size, flags); + + wined3d_mutex_lock(); + resource = wined3d_buffer_get_resource(buffer->wined3d_buffer); + hr = wined3d_resource_set_private_data(resource, guid, data, data_size, flags); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_indexbuffer_GetPrivateData(IDirect3DIndexBuffer8 *iface, + REFGUID guid, void *data, DWORD *data_size) +{ + struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface); + struct wined3d_resource *resource; + HRESULT hr; + + TRACE("iface %p, guid %s, data %p, data_size %p.\n", + iface, debugstr_guid(guid), data, data_size); + + wined3d_mutex_lock(); + resource = wined3d_buffer_get_resource(buffer->wined3d_buffer); + hr = wined3d_resource_get_private_data(resource, guid, data, data_size); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_indexbuffer_FreePrivateData(IDirect3DIndexBuffer8 *iface, REFGUID guid) +{ + struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface); + struct wined3d_resource *resource; + HRESULT hr; + + TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid)); + + wined3d_mutex_lock(); + resource = wined3d_buffer_get_resource(buffer->wined3d_buffer); + hr = wined3d_resource_free_private_data(resource, guid); + wined3d_mutex_unlock(); + + return hr; +} + +static DWORD WINAPI d3d8_indexbuffer_SetPriority(IDirect3DIndexBuffer8 *iface, DWORD priority) +{ + struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface); + DWORD previous; + + TRACE("iface %p, priority %u.\n", iface, priority); + + wined3d_mutex_lock(); + previous = wined3d_buffer_set_priority(buffer->wined3d_buffer, priority); + wined3d_mutex_unlock(); + + return previous; +} + +static DWORD WINAPI d3d8_indexbuffer_GetPriority(IDirect3DIndexBuffer8 *iface) +{ + struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface); + DWORD priority; + + TRACE("iface %p.\n", iface); + + wined3d_mutex_lock(); + priority = wined3d_buffer_get_priority(buffer->wined3d_buffer); + wined3d_mutex_unlock(); + + return priority; +} + +static void WINAPI d3d8_indexbuffer_PreLoad(IDirect3DIndexBuffer8 *iface) +{ + struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface); + + TRACE("iface %p.\n", iface); + + wined3d_mutex_lock(); + wined3d_buffer_preload(buffer->wined3d_buffer); + wined3d_mutex_unlock(); +} + +static D3DRESOURCETYPE WINAPI d3d8_indexbuffer_GetType(IDirect3DIndexBuffer8 *iface) +{ + TRACE("iface %p.\n", iface); + + return D3DRTYPE_INDEXBUFFER; +} + +static HRESULT WINAPI d3d8_indexbuffer_Lock(IDirect3DIndexBuffer8 *iface, UINT offset, UINT size, + BYTE **data, DWORD flags) +{ + struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface); + HRESULT hr; + + TRACE("iface %p, offset %u, size %u, data %p, flags %#x.\n", + iface, offset, size, data, flags); + + wined3d_mutex_lock(); + hr = wined3d_buffer_map(buffer->wined3d_buffer, offset, size, data, flags); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_indexbuffer_Unlock(IDirect3DIndexBuffer8 *iface) +{ + struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface); + + TRACE("iface %p.\n", iface); + + wined3d_mutex_lock(); + wined3d_buffer_unmap(buffer->wined3d_buffer); + wined3d_mutex_unlock(); + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_indexbuffer_GetDesc(IDirect3DIndexBuffer8 *iface, + D3DINDEXBUFFER_DESC *desc) +{ + struct d3d8_indexbuffer *buffer = impl_from_IDirect3DIndexBuffer8(iface); + struct wined3d_resource_desc wined3d_desc; + struct wined3d_resource *wined3d_resource; + + TRACE("iface %p, desc %p.\n", iface, desc); + + wined3d_mutex_lock(); + wined3d_resource = wined3d_buffer_get_resource(buffer->wined3d_buffer); + wined3d_resource_get_desc(wined3d_resource, &wined3d_desc); + wined3d_mutex_unlock(); + + desc->Format = d3dformat_from_wined3dformat(buffer->format); + desc->Type = D3DRTYPE_INDEXBUFFER; + desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK; + desc->Pool = wined3d_desc.pool; + desc->Size = wined3d_desc.size; + + return D3D_OK; +} + +static const IDirect3DIndexBuffer8Vtbl d3d8_indexbuffer_vtbl = +{ + /* IUnknown */ + d3d8_indexbuffer_QueryInterface, + d3d8_indexbuffer_AddRef, + d3d8_indexbuffer_Release, + /* IDirect3DResource8 */ + d3d8_indexbuffer_GetDevice, + d3d8_indexbuffer_SetPrivateData, + d3d8_indexbuffer_GetPrivateData, + d3d8_indexbuffer_FreePrivateData, + d3d8_indexbuffer_SetPriority, + d3d8_indexbuffer_GetPriority, + d3d8_indexbuffer_PreLoad, + d3d8_indexbuffer_GetType, + /* IDirect3DIndexBuffer8 */ + d3d8_indexbuffer_Lock, + d3d8_indexbuffer_Unlock, + d3d8_indexbuffer_GetDesc, +}; + +static void STDMETHODCALLTYPE d3d8_indexbuffer_wined3d_object_destroyed(void *parent) +{ + HeapFree(GetProcessHeap(), 0, parent); +} + +static const struct wined3d_parent_ops d3d8_indexbuffer_wined3d_parent_ops = +{ + d3d8_indexbuffer_wined3d_object_destroyed, +}; + +HRESULT indexbuffer_init(struct d3d8_indexbuffer *buffer, struct d3d8_device *device, + UINT size, DWORD usage, D3DFORMAT format, D3DPOOL pool) +{ + HRESULT hr; + + buffer->IDirect3DIndexBuffer8_iface.lpVtbl = &d3d8_indexbuffer_vtbl; + buffer->refcount = 1; + buffer->format = wined3dformat_from_d3dformat(format); + + wined3d_mutex_lock(); + hr = wined3d_buffer_create_ib(device->wined3d_device, size, usage & WINED3DUSAGE_MASK, + (enum wined3d_pool)pool, buffer, &d3d8_indexbuffer_wined3d_parent_ops, &buffer->wined3d_buffer); + wined3d_mutex_unlock(); + if (FAILED(hr)) + { + WARN("Failed to create wined3d buffer, hr %#x.\n", hr); + return hr; + } + + buffer->parent_device = &device->IDirect3DDevice8_iface; + IDirect3DDevice8_AddRef(buffer->parent_device); + + return D3D_OK; +} + +struct d3d8_indexbuffer *unsafe_impl_from_IDirect3DIndexBuffer8(IDirect3DIndexBuffer8 *iface) +{ + if (!iface) + return NULL; + assert(iface->lpVtbl == &d3d8_indexbuffer_vtbl); + + return impl_from_IDirect3DIndexBuffer8(iface); +} diff --git a/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/d3d8.def b/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/d3d8.def new file mode 100644 index 00000000..0a250b56 --- /dev/null +++ b/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/d3d8.def @@ -0,0 +1,7 @@ + +EXPORTS + D3D8GetSWInfo + DebugSetMute + Direct3DCreate8 + ValidatePixelShader + ValidateVertexShader diff --git a/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/d3d8_main.c b/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/d3d8_main.c new file mode 100644 index 00000000..dd562520 --- /dev/null +++ b/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/d3d8_main.c @@ -0,0 +1,149 @@ +/* + * Direct3D 8 + * + * Copyright 2005 Oliver Stieber + * + * 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 + * + */ + +/* + * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice + * other than GPL or LGPL is available it will apply instead, Oracle elects to use only + * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where + * a choice of LGPL license versions is made available with the language indicating + * that LGPLv2 or any later version may be used, or where a choice of which version + * of the LGPL is applied is otherwise unspecified. + */ + +#include "config.h" +#include "initguid.h" +#include "d3d8_private.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(d3d8); + +HRESULT WINAPI D3D8GetSWInfo(void) { + FIXME("(void): stub\n"); + return 0; +} + +void WINAPI DebugSetMute(void) { + /* nothing to do */ +} + +IDirect3D8 * WINAPI DECLSPEC_HOTPATCH Direct3DCreate8(UINT sdk_version) +{ + struct d3d8 *object; + + TRACE("sdk_version %#x.\n", sdk_version); + + if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)))) + return NULL; + + if (!d3d8_init(object)) + { + WARN("Failed to initialize d3d8.\n"); + HeapFree(GetProcessHeap(), 0, object); + return NULL; + } + + TRACE("Created d3d8 object %p.\n", object); + + return &object->IDirect3D8_iface; +} + +/* At process attach */ +BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv) +{ + TRACE("fdwReason=%d\n", fdwReason); + if (fdwReason == DLL_PROCESS_ATTACH) + DisableThreadLibraryCalls(hInstDLL); + + return TRUE; +} + +/*********************************************************************** + * ValidateVertexShader (D3D8.@) + * + * I've seen reserved1 and reserved2 always passed as 0's + * bool seems always passed as 0 or 1, but other values work as well... + * toto result? + */ +HRESULT WINAPI ValidateVertexShader(DWORD* vertexshader, DWORD* reserved1, DWORD* reserved2, BOOL bool, DWORD* toto) +{ + HRESULT ret; + static BOOL warned; + + if (TRACE_ON(d3d8) || !warned) { + FIXME("(%p %p %p %d %p): stub\n", vertexshader, reserved1, reserved2, bool, toto); + warned = TRUE; + } + + if (!vertexshader) + return E_FAIL; + + if (reserved1 || reserved2) + return E_FAIL; + + switch(*vertexshader) { + case 0xFFFE0101: + case 0xFFFE0100: + ret=S_OK; + break; + default: + WARN("Invalid shader version token %#x.\n", *vertexshader); + ret=E_FAIL; + } + + return ret; +} + +/*********************************************************************** + * ValidatePixelShader (D3D8.@) + * + * PARAMS + * toto result? + */ +HRESULT WINAPI ValidatePixelShader(DWORD* pixelshader, DWORD* reserved1, BOOL bool, DWORD* toto) +{ + HRESULT ret; + static BOOL warned; + + if (TRACE_ON(d3d8) || !warned) { + FIXME("(%p %p %d %p): stub\n", pixelshader, reserved1, bool, toto); + warned = TRUE; + } + + if (!pixelshader) + return E_FAIL; + + if (reserved1) + return E_FAIL; + + switch(*pixelshader) { + case 0xFFFF0100: + case 0xFFFF0101: + case 0xFFFF0102: + case 0xFFFF0103: + case 0xFFFF0104: + ret=S_OK; + break; + default: + WARN("Invalid shader version token %#x.\n", *pixelshader); + ret=E_FAIL; + } + return ret; +} diff --git a/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/d3d8_private.h b/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/d3d8_private.h new file mode 100644 index 00000000..4d17a1dc --- /dev/null +++ b/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/d3d8_private.h @@ -0,0 +1,311 @@ +/* + * Direct3D 8 private include file + * + * Copyright 2002-2004 Jason Edmeades + * Copyright 2003-2004 Raphael Junqueira + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* + * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice + * other than GPL or LGPL is available it will apply instead, Oracle elects to use only + * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where + * a choice of LGPL license versions is made available with the language indicating + * that LGPLv2 or any later version may be used, or where a choice of which version + * of the LGPL is applied is otherwise unspecified. + */ + +#ifndef __WINE_D3D8_PRIVATE_H +#define __WINE_D3D8_PRIVATE_H + +#include <assert.h> +#include <stdarg.h> + +#define NONAMELESSUNION +#define NONAMELESSSTRUCT +#define COBJMACROS +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "wine/debug.h" +#include "d3d8.h" +#include "wine/wined3d.h" + +/* CreateVertexShader can return > 0xFFFF */ +#define VS_HIGHESTFIXEDFXF 0xF0000000 + +/* =========================================================================== + Macros + =========================================================================== */ +/* Not nice, but it lets wined3d support different versions of directx */ +#define WINECAPSTOD3D8CAPS(_pD3D8Caps, _pWineCaps) \ + _pD3D8Caps->DeviceType = (D3DDEVTYPE) _pWineCaps->DeviceType; \ + _pD3D8Caps->AdapterOrdinal = _pWineCaps->AdapterOrdinal; \ + _pD3D8Caps->Caps = _pWineCaps->Caps; \ + _pD3D8Caps->Caps2 = _pWineCaps->Caps2; \ + _pD3D8Caps->Caps3 = _pWineCaps->Caps3; \ + _pD3D8Caps->PresentationIntervals = _pWineCaps->PresentationIntervals; \ + _pD3D8Caps->CursorCaps = _pWineCaps->CursorCaps; \ + _pD3D8Caps->DevCaps = _pWineCaps->DevCaps; \ + _pD3D8Caps->PrimitiveMiscCaps = _pWineCaps->PrimitiveMiscCaps; \ + _pD3D8Caps->RasterCaps = _pWineCaps->RasterCaps; \ + _pD3D8Caps->ZCmpCaps = _pWineCaps->ZCmpCaps; \ + _pD3D8Caps->SrcBlendCaps = _pWineCaps->SrcBlendCaps; \ + _pD3D8Caps->DestBlendCaps = _pWineCaps->DestBlendCaps; \ + _pD3D8Caps->AlphaCmpCaps = _pWineCaps->AlphaCmpCaps; \ + _pD3D8Caps->ShadeCaps = _pWineCaps->ShadeCaps; \ + _pD3D8Caps->TextureCaps = _pWineCaps->TextureCaps; \ + _pD3D8Caps->TextureFilterCaps = _pWineCaps->TextureFilterCaps; \ + _pD3D8Caps->CubeTextureFilterCaps = _pWineCaps->CubeTextureFilterCaps; \ + _pD3D8Caps->VolumeTextureFilterCaps = _pWineCaps->VolumeTextureFilterCaps; \ + _pD3D8Caps->TextureAddressCaps = _pWineCaps->TextureAddressCaps; \ + _pD3D8Caps->VolumeTextureAddressCaps = _pWineCaps->VolumeTextureAddressCaps; \ + _pD3D8Caps->LineCaps = _pWineCaps->LineCaps; \ + _pD3D8Caps->MaxTextureWidth = _pWineCaps->MaxTextureWidth; \ + _pD3D8Caps->MaxTextureHeight = _pWineCaps->MaxTextureHeight; \ + _pD3D8Caps->MaxVolumeExtent = _pWineCaps->MaxVolumeExtent; \ + _pD3D8Caps->MaxTextureRepeat = _pWineCaps->MaxTextureRepeat; \ + _pD3D8Caps->MaxTextureAspectRatio = _pWineCaps->MaxTextureAspectRatio; \ + _pD3D8Caps->MaxAnisotropy = _pWineCaps->MaxAnisotropy; \ + _pD3D8Caps->MaxVertexW = _pWineCaps->MaxVertexW; \ + _pD3D8Caps->GuardBandLeft = _pWineCaps->GuardBandLeft; \ + _pD3D8Caps->GuardBandTop = _pWineCaps->GuardBandTop; \ + _pD3D8Caps->GuardBandRight = _pWineCaps->GuardBandRight; \ + _pD3D8Caps->GuardBandBottom = _pWineCaps->GuardBandBottom; \ + _pD3D8Caps->ExtentsAdjust = _pWineCaps->ExtentsAdjust; \ + _pD3D8Caps->StencilCaps = _pWineCaps->StencilCaps; \ + _pD3D8Caps->FVFCaps = _pWineCaps->FVFCaps; \ + _pD3D8Caps->TextureOpCaps = _pWineCaps->TextureOpCaps; \ + _pD3D8Caps->MaxTextureBlendStages = _pWineCaps->MaxTextureBlendStages; \ + _pD3D8Caps->MaxSimultaneousTextures = _pWineCaps->MaxSimultaneousTextures; \ + _pD3D8Caps->VertexProcessingCaps = _pWineCaps->VertexProcessingCaps; \ + _pD3D8Caps->MaxActiveLights = _pWineCaps->MaxActiveLights; \ + _pD3D8Caps->MaxUserClipPlanes = _pWineCaps->MaxUserClipPlanes; \ + _pD3D8Caps->MaxVertexBlendMatrices = _pWineCaps->MaxVertexBlendMatrices; \ + _pD3D8Caps->MaxVertexBlendMatrixIndex = _pWineCaps->MaxVertexBlendMatrixIndex; \ + _pD3D8Caps->MaxPointSize = _pWineCaps->MaxPointSize; \ + _pD3D8Caps->MaxPrimitiveCount = _pWineCaps->MaxPrimitiveCount; \ + _pD3D8Caps->MaxVertexIndex = _pWineCaps->MaxVertexIndex; \ + _pD3D8Caps->MaxStreams = _pWineCaps->MaxStreams; \ + _pD3D8Caps->MaxStreamStride = _pWineCaps->MaxStreamStride; \ + _pD3D8Caps->VertexShaderVersion = _pWineCaps->VertexShaderVersion; \ + _pD3D8Caps->MaxVertexShaderConst = _pWineCaps->MaxVertexShaderConst; \ + _pD3D8Caps->PixelShaderVersion = _pWineCaps->PixelShaderVersion; \ + _pD3D8Caps->MaxPixelShaderValue = _pWineCaps->PixelShader1xMaxValue; + +void fixup_caps(WINED3DCAPS *pWineCaps) DECLSPEC_HIDDEN; + +struct d3d8 +{ + IDirect3D8 IDirect3D8_iface; + LONG refcount; + struct wined3d *wined3d; +}; + +BOOL d3d8_init(struct d3d8 *d3d8) DECLSPEC_HIDDEN; + +/***************************************************************************** + * IDirect3DDevice8 implementation structure + */ + +#define D3D8_INITIAL_HANDLE_TABLE_SIZE 64 +#define D3D8_INVALID_HANDLE ~0U + +enum d3d8_handle_type +{ + D3D8_HANDLE_FREE, + D3D8_HANDLE_VS, + D3D8_HANDLE_PS, + D3D8_HANDLE_SB, +}; + +struct d3d8_handle_entry +{ + void *object; + enum d3d8_handle_type type; +}; + +struct d3d8_handle_table +{ + struct d3d8_handle_entry *entries; + struct d3d8_handle_entry *free_entries; + UINT table_size; + UINT entry_count; +}; + +struct FvfToDecl +{ + DWORD fvf; + struct d3d8_vertex_declaration *declaration; +}; + +struct d3d8_device +{ + /* IUnknown fields */ + IDirect3DDevice8 IDirect3DDevice8_iface; + struct wined3d_device_parent device_parent; + LONG ref; + struct wined3d_device *wined3d_device; + IDirect3D8 *d3d_parent; + struct d3d8_handle_table handle_table; + + /* FVF management */ + struct FvfToDecl *decls; + UINT numConvertedDecls, declArraySize; + + /* User data draws */ + struct wined3d_buffer *vertex_buffer; + UINT vertex_buffer_size; + UINT vertex_buffer_pos; + struct wined3d_buffer *index_buffer; + UINT index_buffer_size; + UINT index_buffer_pos; + + /* Avoids recursion with nested ReleaseRef to 0 */ + BOOL inDestruction; + BOOL lost; +}; + +HRESULT device_init(struct d3d8_device *device, struct d3d8 *parent, struct wined3d *wined3d, UINT adapter, + D3DDEVTYPE device_type, HWND focus_window, DWORD flags, D3DPRESENT_PARAMETERS *parameters) DECLSPEC_HIDDEN; + +struct d3d8_volume +{ + IDirect3DVolume8 IDirect3DVolume8_iface; + LONG refcount; + struct wined3d_volume *wined3d_volume; + IUnknown *container; + IUnknown *forwardReference; +}; + +HRESULT volume_init(struct d3d8_volume *volume, struct d3d8_device *device, UINT width, UINT height, + UINT depth, DWORD usage, enum wined3d_format_id format, enum wined3d_pool pool) DECLSPEC_HIDDEN; + +struct d3d8_swapchain +{ + IDirect3DSwapChain8 IDirect3DSwapChain8_iface; + LONG refcount; + struct wined3d_swapchain *wined3d_swapchain; + IDirect3DDevice8 *parent_device; +}; + +HRESULT d3d8_swapchain_create(struct d3d8_device *device, struct wined3d_swapchain_desc *desc, + struct d3d8_swapchain **swapchain) DECLSPEC_HIDDEN; + +struct d3d8_surface +{ + IDirect3DSurface8 IDirect3DSurface8_iface; + LONG refcount; + struct wined3d_surface *wined3d_surface; + IDirect3DDevice8 *parent_device; + + /* The surface container */ + IUnknown *container; + + /* If set forward refcounting to this object */ + IUnknown *forwardReference; +}; + +HRESULT surface_init(struct d3d8_surface *surface, struct d3d8_device *device, UINT width, UINT height, + D3DFORMAT format, DWORD flags, DWORD usage, D3DPOOL pool, D3DMULTISAMPLE_TYPE multisample_type, + DWORD multisample_quality) DECLSPEC_HIDDEN; +struct d3d8_surface *unsafe_impl_from_IDirect3DSurface8(IDirect3DSurface8 *iface) DECLSPEC_HIDDEN; + +struct d3d8_vertexbuffer +{ + IDirect3DVertexBuffer8 IDirect3DVertexBuffer8_iface; + LONG refcount; + struct wined3d_buffer *wined3d_buffer; + IDirect3DDevice8 *parent_device; + DWORD fvf; +}; + +HRESULT vertexbuffer_init(struct d3d8_vertexbuffer *buffer, struct d3d8_device *device, + UINT size, DWORD usage, DWORD fvf, D3DPOOL pool) DECLSPEC_HIDDEN; +struct d3d8_vertexbuffer *unsafe_impl_from_IDirect3DVertexBuffer8(IDirect3DVertexBuffer8 *iface) DECLSPEC_HIDDEN; + +struct d3d8_indexbuffer +{ + IDirect3DIndexBuffer8 IDirect3DIndexBuffer8_iface; + LONG refcount; + struct wined3d_buffer *wined3d_buffer; + IDirect3DDevice8 *parent_device; + enum wined3d_format_id format; +}; + +HRESULT indexbuffer_init(struct d3d8_indexbuffer *buffer, struct d3d8_device *device, + UINT size, DWORD usage, D3DFORMAT format, D3DPOOL pool) DECLSPEC_HIDDEN; +struct d3d8_indexbuffer *unsafe_impl_from_IDirect3DIndexBuffer8(IDirect3DIndexBuffer8 *iface) DECLSPEC_HIDDEN; + +struct d3d8_texture +{ + IDirect3DBaseTexture8 IDirect3DBaseTexture8_iface; + LONG refcount; + struct wined3d_texture *wined3d_texture; + IDirect3DDevice8 *parent_device; +}; + +HRESULT cubetexture_init(struct d3d8_texture *texture, struct d3d8_device *device, + UINT edge_length, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool) DECLSPEC_HIDDEN; +HRESULT texture_init(struct d3d8_texture *texture, struct d3d8_device *device, + UINT width, UINT height, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool) DECLSPEC_HIDDEN; +HRESULT volumetexture_init(struct d3d8_texture *texture, struct d3d8_device *device, + UINT width, UINT height, UINT depth, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool) DECLSPEC_HIDDEN; +struct d3d8_texture *unsafe_impl_from_IDirect3DBaseTexture8(IDirect3DBaseTexture8 *iface) DECLSPEC_HIDDEN; + +struct d3d8_vertex_declaration +{ + DWORD *elements; + DWORD elements_size; /* Size of elements, in bytes */ + struct wined3d_vertex_declaration *wined3d_vertex_declaration; + DWORD shader_handle; +}; + +void d3d8_vertex_declaration_destroy(struct d3d8_vertex_declaration *declaration) DECLSPEC_HIDDEN; +HRESULT d3d8_vertex_declaration_init(struct d3d8_vertex_declaration *declaration, + struct d3d8_device *device, const DWORD *elements, DWORD shader_handle) DECLSPEC_HIDDEN; +HRESULT d3d8_vertex_declaration_init_fvf(struct d3d8_vertex_declaration *declaration, + struct d3d8_device *device, DWORD fvf) DECLSPEC_HIDDEN; + +struct d3d8_vertex_shader +{ + struct d3d8_vertex_declaration *vertex_declaration; + struct wined3d_shader *wined3d_shader; +}; + +void d3d8_vertex_shader_destroy(struct d3d8_vertex_shader *shader) DECLSPEC_HIDDEN; +HRESULT d3d8_vertex_shader_init(struct d3d8_vertex_shader *shader, struct d3d8_device *device, + const DWORD *declaration, const DWORD *byte_code, DWORD shader_handle, DWORD usage) DECLSPEC_HIDDEN; + +#define D3D8_MAX_VERTEX_SHADER_CONSTANTF 256 + +struct d3d8_pixel_shader +{ + DWORD handle; + struct wined3d_shader *wined3d_shader; +}; + +void d3d8_pixel_shader_destroy(struct d3d8_pixel_shader *shader) DECLSPEC_HIDDEN; +HRESULT d3d8_pixel_shader_init(struct d3d8_pixel_shader *shader, struct d3d8_device *device, + const DWORD *byte_code, DWORD shader_handle) DECLSPEC_HIDDEN; + +D3DFORMAT d3dformat_from_wined3dformat(enum wined3d_format_id format) DECLSPEC_HIDDEN; +enum wined3d_format_id wined3dformat_from_d3dformat(D3DFORMAT format) DECLSPEC_HIDDEN; +void load_local_constants(const DWORD *d3d8_elements, struct wined3d_shader *wined3d_vertex_shader) DECLSPEC_HIDDEN; +size_t parse_token(const DWORD *pToken) DECLSPEC_HIDDEN; + +#endif /* __WINE_D3DX8_PRIVATE_H */ diff --git a/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/device.c b/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/device.c new file mode 100644 index 00000000..f1599ccd --- /dev/null +++ b/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/device.c @@ -0,0 +1,3163 @@ +/* + * IDirect3DDevice8 implementation + * + * Copyright 2002-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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* + * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice + * other than GPL or LGPL is available it will apply instead, Oracle elects to use only + * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where + * a choice of LGPL license versions is made available with the language indicating + * that LGPLv2 or any later version may be used, or where a choice of which version + * of the LGPL is applied is otherwise unspecified. + */ + +#include "config.h" + +#include <math.h> +#include <stdarg.h> + +#define NONAMELESSUNION +#define NONAMELESSSTRUCT +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "wingdi.h" +#include "wine/debug.h" + +#include "d3d8_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(d3d8); + +D3DFORMAT d3dformat_from_wined3dformat(enum wined3d_format_id format) +{ + BYTE *c = (BYTE *)&format; + + /* Don't translate FOURCC formats */ + if (isprint(c[0]) && isprint(c[1]) && isprint(c[2]) && isprint(c[3])) return format; + + switch(format) + { + case WINED3DFMT_UNKNOWN: return D3DFMT_UNKNOWN; + case WINED3DFMT_B8G8R8_UNORM: return D3DFMT_R8G8B8; + case WINED3DFMT_B8G8R8A8_UNORM: return D3DFMT_A8R8G8B8; + case WINED3DFMT_B8G8R8X8_UNORM: return D3DFMT_X8R8G8B8; + case WINED3DFMT_B5G6R5_UNORM: return D3DFMT_R5G6B5; + case WINED3DFMT_B5G5R5X1_UNORM: return D3DFMT_X1R5G5B5; + case WINED3DFMT_B5G5R5A1_UNORM: return D3DFMT_A1R5G5B5; + case WINED3DFMT_B4G4R4A4_UNORM: return D3DFMT_A4R4G4B4; + case WINED3DFMT_B2G3R3_UNORM: return D3DFMT_R3G3B2; + case WINED3DFMT_A8_UNORM: return D3DFMT_A8; + case WINED3DFMT_B2G3R3A8_UNORM: return D3DFMT_A8R3G3B2; + case WINED3DFMT_B4G4R4X4_UNORM: return D3DFMT_X4R4G4B4; + case WINED3DFMT_R10G10B10A2_UNORM: return D3DFMT_A2B10G10R10; + case WINED3DFMT_R16G16_UNORM: return D3DFMT_G16R16; + case WINED3DFMT_P8_UINT_A8_UNORM: return D3DFMT_A8P8; + case WINED3DFMT_P8_UINT: return D3DFMT_P8; + case WINED3DFMT_L8_UNORM: return D3DFMT_L8; + case WINED3DFMT_L8A8_UNORM: return D3DFMT_A8L8; + case WINED3DFMT_L4A4_UNORM: return D3DFMT_A4L4; + case WINED3DFMT_R8G8_SNORM: return D3DFMT_V8U8; + case WINED3DFMT_R5G5_SNORM_L6_UNORM: return D3DFMT_L6V5U5; + case WINED3DFMT_R8G8_SNORM_L8X8_UNORM: return D3DFMT_X8L8V8U8; + case WINED3DFMT_R8G8B8A8_SNORM: return D3DFMT_Q8W8V8U8; + case WINED3DFMT_R16G16_SNORM: return D3DFMT_V16U16; + case WINED3DFMT_R10G11B11_SNORM: return D3DFMT_W11V11U10; + case WINED3DFMT_R10G10B10_SNORM_A2_UNORM: return D3DFMT_A2W10V10U10; + case WINED3DFMT_D16_LOCKABLE: return D3DFMT_D16_LOCKABLE; + case WINED3DFMT_D32_UNORM: return D3DFMT_D32; + case WINED3DFMT_S1_UINT_D15_UNORM: return D3DFMT_D15S1; + case WINED3DFMT_D24_UNORM_S8_UINT: return D3DFMT_D24S8; + case WINED3DFMT_X8D24_UNORM: return D3DFMT_D24X8; + case WINED3DFMT_S4X4_UINT_D24_UNORM: return D3DFMT_D24X4S4; + case WINED3DFMT_D16_UNORM: return D3DFMT_D16; + case WINED3DFMT_VERTEXDATA: return D3DFMT_VERTEXDATA; + case WINED3DFMT_R16_UINT: return D3DFMT_INDEX16; + case WINED3DFMT_R32_UINT: return D3DFMT_INDEX32; + default: + FIXME("Unhandled wined3d format %#x.\n", format); + return D3DFMT_UNKNOWN; + } +} + +enum wined3d_format_id wined3dformat_from_d3dformat(D3DFORMAT format) +{ + BYTE *c = (BYTE *)&format; + + /* Don't translate FOURCC formats */ + if (isprint(c[0]) && isprint(c[1]) && isprint(c[2]) && isprint(c[3])) return format; + + switch(format) + { + case D3DFMT_UNKNOWN: return WINED3DFMT_UNKNOWN; + case D3DFMT_R8G8B8: return WINED3DFMT_B8G8R8_UNORM; + case D3DFMT_A8R8G8B8: return WINED3DFMT_B8G8R8A8_UNORM; + case D3DFMT_X8R8G8B8: return WINED3DFMT_B8G8R8X8_UNORM; + case D3DFMT_R5G6B5: return WINED3DFMT_B5G6R5_UNORM; + case D3DFMT_X1R5G5B5: return WINED3DFMT_B5G5R5X1_UNORM; + case D3DFMT_A1R5G5B5: return WINED3DFMT_B5G5R5A1_UNORM; + case D3DFMT_A4R4G4B4: return WINED3DFMT_B4G4R4A4_UNORM; + case D3DFMT_R3G3B2: return WINED3DFMT_B2G3R3_UNORM; + case D3DFMT_A8: return WINED3DFMT_A8_UNORM; + case D3DFMT_A8R3G3B2: return WINED3DFMT_B2G3R3A8_UNORM; + case D3DFMT_X4R4G4B4: return WINED3DFMT_B4G4R4X4_UNORM; + case D3DFMT_A2B10G10R10: return WINED3DFMT_R10G10B10A2_UNORM; + case D3DFMT_G16R16: return WINED3DFMT_R16G16_UNORM; + case D3DFMT_A8P8: return WINED3DFMT_P8_UINT_A8_UNORM; + case D3DFMT_P8: return WINED3DFMT_P8_UINT; + case D3DFMT_L8: return WINED3DFMT_L8_UNORM; + case D3DFMT_A8L8: return WINED3DFMT_L8A8_UNORM; + case D3DFMT_A4L4: return WINED3DFMT_L4A4_UNORM; + case D3DFMT_V8U8: return WINED3DFMT_R8G8_SNORM; + case D3DFMT_L6V5U5: return WINED3DFMT_R5G5_SNORM_L6_UNORM; + case D3DFMT_X8L8V8U8: return WINED3DFMT_R8G8_SNORM_L8X8_UNORM; + case D3DFMT_Q8W8V8U8: return WINED3DFMT_R8G8B8A8_SNORM; + case D3DFMT_V16U16: return WINED3DFMT_R16G16_SNORM; + case D3DFMT_W11V11U10: return WINED3DFMT_R10G11B11_SNORM; + case D3DFMT_A2W10V10U10: return WINED3DFMT_R10G10B10_SNORM_A2_UNORM; + case D3DFMT_D16_LOCKABLE: return WINED3DFMT_D16_LOCKABLE; + case D3DFMT_D32: return WINED3DFMT_D32_UNORM; + case D3DFMT_D15S1: return WINED3DFMT_S1_UINT_D15_UNORM; + case D3DFMT_D24S8: return WINED3DFMT_D24_UNORM_S8_UINT; + case D3DFMT_D24X8: return WINED3DFMT_X8D24_UNORM; + case D3DFMT_D24X4S4: return WINED3DFMT_S4X4_UINT_D24_UNORM; + case D3DFMT_D16: return WINED3DFMT_D16_UNORM; + case D3DFMT_VERTEXDATA: return WINED3DFMT_VERTEXDATA; + case D3DFMT_INDEX16: return WINED3DFMT_R16_UINT; + case D3DFMT_INDEX32: return WINED3DFMT_R32_UINT; + default: + FIXME("Unhandled D3DFORMAT %#x\n", format); + return WINED3DFMT_UNKNOWN; + } +} + +static UINT vertex_count_from_primitive_count(D3DPRIMITIVETYPE primitive_type, UINT primitive_count) +{ + switch(primitive_type) + { + case D3DPT_POINTLIST: + return primitive_count; + + case D3DPT_LINELIST: + return primitive_count * 2; + + case D3DPT_LINESTRIP: + return primitive_count + 1; + + case D3DPT_TRIANGLELIST: + return primitive_count * 3; + + case D3DPT_TRIANGLESTRIP: + case D3DPT_TRIANGLEFAN: + return primitive_count + 2; + + default: + FIXME("Unhandled primitive type %#x\n", primitive_type); + return 0; + } +} + +static void present_parameters_from_wined3d_swapchain_desc(D3DPRESENT_PARAMETERS *present_parameters, + const struct wined3d_swapchain_desc *swapchain_desc) +{ + present_parameters->BackBufferWidth = swapchain_desc->backbuffer_width; + present_parameters->BackBufferHeight = swapchain_desc->backbuffer_height; + present_parameters->BackBufferFormat = d3dformat_from_wined3dformat(swapchain_desc->backbuffer_format); + present_parameters->BackBufferCount = swapchain_desc->backbuffer_count; + present_parameters->MultiSampleType = swapchain_desc->multisample_type; + present_parameters->SwapEffect = swapchain_desc->swap_effect; + present_parameters->hDeviceWindow = swapchain_desc->device_window; + present_parameters->Windowed = swapchain_desc->windowed; + present_parameters->EnableAutoDepthStencil = swapchain_desc->enable_auto_depth_stencil; + present_parameters->AutoDepthStencilFormat + = d3dformat_from_wined3dformat(swapchain_desc->auto_depth_stencil_format); + present_parameters->Flags = swapchain_desc->flags; + present_parameters->FullScreen_RefreshRateInHz = swapchain_desc->refresh_rate; + present_parameters->FullScreen_PresentationInterval = swapchain_desc->swap_interval; +} + +static void wined3d_swapchain_desc_from_present_parameters(struct wined3d_swapchain_desc *swapchain_desc, + const D3DPRESENT_PARAMETERS *present_parameters) +{ + swapchain_desc->backbuffer_width = present_parameters->BackBufferWidth; + swapchain_desc->backbuffer_height = present_parameters->BackBufferHeight; + swapchain_desc->backbuffer_format = wined3dformat_from_d3dformat(present_parameters->BackBufferFormat); + swapchain_desc->backbuffer_count = max(1, present_parameters->BackBufferCount); + swapchain_desc->multisample_type = present_parameters->MultiSampleType; + swapchain_desc->multisample_quality = 0; /* d3d9 only */ + swapchain_desc->swap_effect = present_parameters->SwapEffect; + swapchain_desc->device_window = present_parameters->hDeviceWindow; + swapchain_desc->windowed = present_parameters->Windowed; + swapchain_desc->enable_auto_depth_stencil = present_parameters->EnableAutoDepthStencil; + swapchain_desc->auto_depth_stencil_format + = wined3dformat_from_d3dformat(present_parameters->AutoDepthStencilFormat); + swapchain_desc->flags = present_parameters->Flags; + swapchain_desc->refresh_rate = present_parameters->FullScreen_RefreshRateInHz; + swapchain_desc->swap_interval = present_parameters->FullScreen_PresentationInterval; + swapchain_desc->auto_restore_display_mode = TRUE; +} + +/* Handle table functions */ +static DWORD d3d8_allocate_handle(struct d3d8_handle_table *t, void *object, enum d3d8_handle_type type) +{ + struct d3d8_handle_entry *entry; + + if (t->free_entries) + { + DWORD index = t->free_entries - t->entries; + /* Use a free handle */ + entry = t->free_entries; + if (entry->type != D3D8_HANDLE_FREE) + { + ERR("Handle %u(%p) is in the free list, but has type %#x.\n", index, entry, entry->type); + return D3D8_INVALID_HANDLE; + } + t->free_entries = entry->object; + entry->object = object; + entry->type = type; + + return index; + } + + if (!(t->entry_count < t->table_size)) + { + /* Grow the table */ + UINT new_size = t->table_size + (t->table_size >> 1); + struct d3d8_handle_entry *new_entries = HeapReAlloc(GetProcessHeap(), + 0, t->entries, new_size * sizeof(*t->entries)); + if (!new_entries) + { + ERR("Failed to grow the handle table.\n"); + return D3D8_INVALID_HANDLE; + } + t->entries = new_entries; + t->table_size = new_size; + } + + entry = &t->entries[t->entry_count]; + entry->object = object; + entry->type = type; + + return t->entry_count++; +} + +static void *d3d8_free_handle(struct d3d8_handle_table *t, DWORD handle, enum d3d8_handle_type type) +{ + struct d3d8_handle_entry *entry; + void *object; + + if (handle == D3D8_INVALID_HANDLE || handle >= t->entry_count) + { + WARN("Invalid handle %u passed.\n", handle); + return NULL; + } + + entry = &t->entries[handle]; + if (entry->type != type) + { + WARN("Handle %u(%p) is not of type %#x.\n", handle, entry, type); + return NULL; + } + + object = entry->object; + entry->object = t->free_entries; + entry->type = D3D8_HANDLE_FREE; + t->free_entries = entry; + + return object; +} + +static void *d3d8_get_object(struct d3d8_handle_table *t, DWORD handle, enum d3d8_handle_type type) +{ + struct d3d8_handle_entry *entry; + + if (handle == D3D8_INVALID_HANDLE || handle >= t->entry_count) + { + WARN("Invalid handle %u passed.\n", handle); + return NULL; + } + + entry = &t->entries[handle]; + if (entry->type != type) + { + WARN("Handle %u(%p) is not of type %#x.\n", handle, entry, type); + return NULL; + } + + return entry->object; +} + +static inline struct d3d8_device *impl_from_IDirect3DDevice8(IDirect3DDevice8 *iface) +{ + return CONTAINING_RECORD(iface, struct d3d8_device, IDirect3DDevice8_iface); +} + +static HRESULT WINAPI d3d8_device_QueryInterface(IDirect3DDevice8 *iface, REFIID riid, void **out) +{ + TRACE("iface %p, riid %s, out %p.\n", + iface, debugstr_guid(riid), out); + + if (IsEqualGUID(riid, &IID_IDirect3DDevice8) + || IsEqualGUID(riid, &IID_IUnknown)) + { + IDirect3DDevice8_AddRef(iface); + *out = iface; + return S_OK; + } + + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid)); + + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI d3d8_device_AddRef(IDirect3DDevice8 *iface) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + ULONG ref = InterlockedIncrement(&device->ref); + + TRACE("%p increasing refcount to %u.\n", iface, ref); + + return ref; +} + +static ULONG WINAPI d3d8_device_Release(IDirect3DDevice8 *iface) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + ULONG ref; + + if (device->inDestruction) + return 0; + + ref = InterlockedDecrement(&device->ref); + + TRACE("%p decreasing refcount to %u.\n", iface, ref); + + if (!ref) + { + IDirect3D8 *parent = device->d3d_parent; + unsigned i; + + TRACE("Releasing wined3d device %p.\n", device->wined3d_device); + + wined3d_mutex_lock(); + + device->inDestruction = TRUE; + + for (i = 0; i < device->numConvertedDecls; ++i) + { + d3d8_vertex_declaration_destroy(device->decls[i].declaration); + } + HeapFree(GetProcessHeap(), 0, device->decls); + + if (device->vertex_buffer) + wined3d_buffer_decref(device->vertex_buffer); + if (device->index_buffer) + wined3d_buffer_decref(device->index_buffer); + + wined3d_device_uninit_3d(device->wined3d_device); + wined3d_device_release_focus_window(device->wined3d_device); + wined3d_device_decref(device->wined3d_device); + HeapFree(GetProcessHeap(), 0, device->handle_table.entries); + HeapFree(GetProcessHeap(), 0, device); + + wined3d_mutex_unlock(); + + IDirect3D8_Release(parent); + } + return ref; +} + +static HRESULT WINAPI d3d8_device_TestCooperativeLevel(IDirect3DDevice8 *iface) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + + TRACE("iface %p.\n", iface); + + if (device->lost) + { + TRACE("Device is lost.\n"); + return D3DERR_DEVICENOTRESET; + } + + return D3D_OK; +} + +static UINT WINAPI d3d8_device_GetAvailableTextureMem(IDirect3DDevice8 *iface) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + HRESULT hr; + + TRACE("iface %p.\n", iface); + + wined3d_mutex_lock(); + hr = wined3d_device_get_available_texture_mem(device->wined3d_device); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_device_ResourceManagerDiscardBytes(IDirect3DDevice8 *iface, DWORD byte_count) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + + TRACE("iface %p, byte_count %u.\n", iface, byte_count); + + if (byte_count) + FIXME("Byte count ignored.\n"); + + wined3d_mutex_lock(); + wined3d_device_evict_managed_resources(device->wined3d_device); + wined3d_mutex_unlock(); + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_device_GetDirect3D(IDirect3DDevice8 *iface, IDirect3D8 **d3d8) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + + TRACE("iface %p, d3d8 %p.\n", iface, d3d8); + + if (!d3d8) + return D3DERR_INVALIDCALL; + + return IDirect3D8_QueryInterface(device->d3d_parent, &IID_IDirect3D8, (void **)d3d8); +} + +static HRESULT WINAPI d3d8_device_GetDeviceCaps(IDirect3DDevice8 *iface, D3DCAPS8 *caps) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + WINED3DCAPS *wined3d_caps; + HRESULT hr; + + TRACE("iface %p, caps %p.\n", iface, caps); + + if (!caps) + return D3DERR_INVALIDCALL; + + if (!(wined3d_caps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*wined3d_caps)))) + return D3DERR_INVALIDCALL; /* well this is what MSDN says to return */ + + wined3d_mutex_lock(); + hr = wined3d_device_get_device_caps(device->wined3d_device, wined3d_caps); + wined3d_mutex_unlock(); + + fixup_caps(wined3d_caps); + WINECAPSTOD3D8CAPS(caps, wined3d_caps) + HeapFree(GetProcessHeap(), 0, wined3d_caps); + + return hr; +} + +static HRESULT WINAPI d3d8_device_GetDisplayMode(IDirect3DDevice8 *iface, D3DDISPLAYMODE *mode) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + struct wined3d_display_mode wined3d_mode; + HRESULT hr; + + TRACE("iface %p, mode %p.\n", iface, mode); + + wined3d_mutex_lock(); + hr = wined3d_device_get_display_mode(device->wined3d_device, 0, &wined3d_mode, NULL); + wined3d_mutex_unlock(); + + if (SUCCEEDED(hr)) + { + mode->Width = wined3d_mode.width; + mode->Height = wined3d_mode.height; + mode->RefreshRate = wined3d_mode.refresh_rate; + mode->Format = d3dformat_from_wined3dformat(wined3d_mode.format_id); + } + + return hr; +} + +static HRESULT WINAPI d3d8_device_GetCreationParameters(IDirect3DDevice8 *iface, + D3DDEVICE_CREATION_PARAMETERS *parameters) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + + TRACE("iface %p, parameters %p.\n", iface, parameters); + + wined3d_mutex_lock(); + wined3d_device_get_creation_parameters(device->wined3d_device, + (struct wined3d_device_creation_parameters *)parameters); + wined3d_mutex_unlock(); + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_device_SetCursorProperties(IDirect3DDevice8 *iface, + UINT hotspot_x, UINT hotspot_y, IDirect3DSurface8 *bitmap) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + struct d3d8_surface *bitmap_impl = unsafe_impl_from_IDirect3DSurface8(bitmap); + HRESULT hr; + + TRACE("iface %p, hotspot_x %u, hotspot_y %u, bitmap %p.\n", + iface, hotspot_x, hotspot_y, bitmap); + + if (!bitmap) + { + WARN("No cursor bitmap, returning D3DERR_INVALIDCALL.\n"); + return D3DERR_INVALIDCALL; + } + + wined3d_mutex_lock(); + hr = wined3d_device_set_cursor_properties(device->wined3d_device, + hotspot_x, hotspot_y, bitmap_impl->wined3d_surface); + wined3d_mutex_unlock(); + + return hr; +} + +static void WINAPI d3d8_device_SetCursorPosition(IDirect3DDevice8 *iface, UINT x, UINT y, DWORD flags) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + + TRACE("iface %p, x %u, y %u, flags %#x.\n", iface, x, y, flags); + + wined3d_mutex_lock(); + wined3d_device_set_cursor_position(device->wined3d_device, x, y, flags); + wined3d_mutex_unlock(); +} + +static BOOL WINAPI d3d8_device_ShowCursor(IDirect3DDevice8 *iface, BOOL show) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + BOOL ret; + + TRACE("iface %p, show %#x.\n", iface, show); + + wined3d_mutex_lock(); + ret = wined3d_device_show_cursor(device->wined3d_device, show); + wined3d_mutex_unlock(); + + return ret; +} + +static HRESULT WINAPI d3d8_device_CreateAdditionalSwapChain(IDirect3DDevice8 *iface, + D3DPRESENT_PARAMETERS *present_parameters, IDirect3DSwapChain8 **swapchain) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + struct wined3d_swapchain_desc desc; + struct d3d8_swapchain *object; + + TRACE("iface %p, present_parameters %p, swapchain %p.\n", + iface, present_parameters, swapchain); + + wined3d_swapchain_desc_from_present_parameters(&desc, present_parameters); + if (SUCCEEDED(d3d8_swapchain_create(device, &desc, &object))) + *swapchain = &object->IDirect3DSwapChain8_iface; + present_parameters_from_wined3d_swapchain_desc(present_parameters, &desc); + + return D3D_OK; +} + +static HRESULT CDECL reset_enum_callback(struct wined3d_resource *resource) +{ + struct wined3d_resource_desc desc; + + wined3d_resource_get_desc(resource, &desc); + if (desc.pool == WINED3D_POOL_DEFAULT) + { + struct d3d8_surface *surface; + + if (desc.resource_type == WINED3D_RTYPE_TEXTURE) + { + IUnknown *parent = wined3d_resource_get_parent(resource); + IDirect3DBaseTexture8 *texture; + + if (SUCCEEDED(IUnknown_QueryInterface(parent, &IID_IDirect3DBaseTexture8, (void **)&texture))) + { + IDirect3DBaseTexture8_Release(texture); + WARN("Texture %p (resource %p) in pool D3DPOOL_DEFAULT blocks the Reset call.\n", texture, resource); + return D3DERR_DEVICELOST; + } + + return D3D_OK; + } + + if (desc.resource_type != WINED3D_RTYPE_SURFACE) + { + WARN("Resource %p in pool D3DPOOL_DEFAULT blocks the Reset call.\n", resource); + return D3DERR_DEVICELOST; + } + + surface = wined3d_resource_get_parent(resource); + if (surface->refcount) + { + WARN("Surface %p (resource %p) in pool D3DPOOL_DEFAULT blocks the Reset call.\n", surface, resource); + return D3DERR_DEVICELOST; + } + + WARN("Surface %p (resource %p) is an implicit resource with ref 0.\n", surface, resource); + } + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_device_Reset(IDirect3DDevice8 *iface, + D3DPRESENT_PARAMETERS *present_parameters) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + struct wined3d_swapchain_desc swapchain_desc; + HRESULT hr; + + TRACE("iface %p, present_parameters %p.\n", iface, present_parameters); + + wined3d_mutex_lock(); + + if (device->vertex_buffer) + { + wined3d_buffer_decref(device->vertex_buffer); + device->vertex_buffer = NULL; + device->vertex_buffer_size = 0; + } + if (device->index_buffer) + { + wined3d_buffer_decref(device->index_buffer); + device->index_buffer = NULL; + device->index_buffer_size = 0; + } + + wined3d_swapchain_desc_from_present_parameters(&swapchain_desc, present_parameters); + if (SUCCEEDED(hr = wined3d_device_reset(device->wined3d_device, &swapchain_desc, + NULL, reset_enum_callback, TRUE))) + { + wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_POINTSIZE_MIN, 0); + device->lost = FALSE; + } + else + { + device->lost = TRUE; + } + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_device_Present(IDirect3DDevice8 *iface, const RECT *src_rect, + const RECT *dst_rect, HWND dst_window_override, const RGNDATA *dirty_region) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + HRESULT hr; + + TRACE("iface %p, src_rect %s, dst_rect %s, dst_window_override %p, dirty_region %p.\n", + iface, wine_dbgstr_rect(src_rect), wine_dbgstr_rect(dst_rect), dst_window_override, dirty_region); + + wined3d_mutex_lock(); + hr = wined3d_device_present(device->wined3d_device, src_rect, dst_rect, + dst_window_override, dirty_region, 0); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_device_GetBackBuffer(IDirect3DDevice8 *iface, + UINT backbuffer_idx, D3DBACKBUFFER_TYPE backbuffer_type, IDirect3DSurface8 **backbuffer) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + struct wined3d_surface *wined3d_surface = NULL; + struct d3d8_surface *surface_impl; + HRESULT hr; + + TRACE("iface %p, backbuffer_idx %u, backbuffer_type %#x, backbuffer %p.\n", + iface, backbuffer_idx, backbuffer_type, backbuffer); + + wined3d_mutex_lock(); + hr = wined3d_device_get_back_buffer(device->wined3d_device, 0, backbuffer_idx, + (enum wined3d_backbuffer_type)backbuffer_type, &wined3d_surface); + if (SUCCEEDED(hr) && wined3d_surface && backbuffer) + { + surface_impl = wined3d_surface_get_parent(wined3d_surface); + *backbuffer = &surface_impl->IDirect3DSurface8_iface; + IDirect3DSurface8_AddRef(*backbuffer); + } + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_device_GetRasterStatus(IDirect3DDevice8 *iface, D3DRASTER_STATUS *raster_status) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + HRESULT hr; + + TRACE("iface %p, raster_status %p.\n", iface, raster_status); + + wined3d_mutex_lock(); + hr = wined3d_device_get_raster_status(device->wined3d_device, 0, (struct wined3d_raster_status *)raster_status); + wined3d_mutex_unlock(); + + return hr; +} + +static void WINAPI d3d8_device_SetGammaRamp(IDirect3DDevice8 *iface, DWORD flags, const D3DGAMMARAMP *ramp) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + + TRACE("iface %p, flags %#x, ramp %p.\n", iface, flags, ramp); + + /* Note: D3DGAMMARAMP is compatible with struct wined3d_gamma_ramp. */ + wined3d_mutex_lock(); + wined3d_device_set_gamma_ramp(device->wined3d_device, 0, flags, (const struct wined3d_gamma_ramp *)ramp); + wined3d_mutex_unlock(); +} + +static void WINAPI d3d8_device_GetGammaRamp(IDirect3DDevice8 *iface, D3DGAMMARAMP *ramp) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + + TRACE("iface %p, ramp %p.\n", iface, ramp); + + /* Note: D3DGAMMARAMP is compatible with struct wined3d_gamma_ramp. */ + wined3d_mutex_lock(); + wined3d_device_get_gamma_ramp(device->wined3d_device, 0, (struct wined3d_gamma_ramp *)ramp); + wined3d_mutex_unlock(); +} + +static HRESULT WINAPI d3d8_device_CreateTexture(IDirect3DDevice8 *iface, + UINT width, UINT height, UINT levels, DWORD usage, D3DFORMAT format, + D3DPOOL pool, IDirect3DTexture8 **texture) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + struct d3d8_texture *object; + HRESULT hr; + + TRACE("iface %p, width %u, height %u, levels %u, usage %#x, format %#x, pool %#x, texture %p.\n", + iface, width, height, levels, usage, format, pool, texture); + + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); + if (!object) + return D3DERR_OUTOFVIDEOMEMORY; + + hr = texture_init(object, device, width, height, levels, usage, format, pool); + if (FAILED(hr)) + { + WARN("Failed to initialize texture, hr %#x.\n", hr); + HeapFree(GetProcessHeap(), 0, object); + return hr; + } + + TRACE("Created texture %p.\n", object); + *texture = (IDirect3DTexture8 *)&object->IDirect3DBaseTexture8_iface; + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_device_CreateVolumeTexture(IDirect3DDevice8 *iface, + UINT width, UINT height, UINT depth, UINT levels, DWORD usage, D3DFORMAT format, + D3DPOOL pool, IDirect3DVolumeTexture8 **texture) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + struct d3d8_texture *object; + HRESULT hr; + + TRACE("iface %p, width %u, height %u, depth %u, levels %u, usage %#x, format %#x, pool %#x, texture %p.\n", + iface, width, height, depth, levels, usage, format, pool, texture); + + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); + if (!object) + return D3DERR_OUTOFVIDEOMEMORY; + + hr = volumetexture_init(object, device, width, height, depth, levels, usage, format, pool); + if (FAILED(hr)) + { + WARN("Failed to initialize volume texture, hr %#x.\n", hr); + HeapFree(GetProcessHeap(), 0, object); + return hr; + } + + TRACE("Created volume texture %p.\n", object); + *texture = (IDirect3DVolumeTexture8 *)&object->IDirect3DBaseTexture8_iface; + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_device_CreateCubeTexture(IDirect3DDevice8 *iface, UINT edge_length, + UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool, IDirect3DCubeTexture8 **texture) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + struct d3d8_texture *object; + HRESULT hr; + + TRACE("iface %p, edge_length %u, levels %u, usage %#x, format %#x, pool %#x, texture %p.\n", + iface, edge_length, levels, usage, format, pool, texture); + + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); + if (!object) + return D3DERR_OUTOFVIDEOMEMORY; + + hr = cubetexture_init(object, device, edge_length, levels, usage, format, pool); + if (FAILED(hr)) + { + WARN("Failed to initialize cube texture, hr %#x.\n", hr); + HeapFree(GetProcessHeap(), 0, object); + return hr; + } + + TRACE("Created cube texture %p.\n", object); + *texture = (IDirect3DCubeTexture8 *)&object->IDirect3DBaseTexture8_iface; + + return hr; +} + +static HRESULT WINAPI d3d8_device_CreateVertexBuffer(IDirect3DDevice8 *iface, UINT size, + DWORD usage, DWORD fvf, D3DPOOL pool, IDirect3DVertexBuffer8 **buffer) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + struct d3d8_vertexbuffer *object; + HRESULT hr; + + TRACE("iface %p, size %u, usage %#x, fvf %#x, pool %#x, buffer %p.\n", + iface, size, usage, fvf, pool, buffer); + + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); + if (!object) + return D3DERR_OUTOFVIDEOMEMORY; + + hr = vertexbuffer_init(object, device, size, usage, fvf, pool); + if (FAILED(hr)) + { + WARN("Failed to initialize vertex buffer, hr %#x.\n", hr); + HeapFree(GetProcessHeap(), 0, object); + return hr; + } + + TRACE("Created vertex buffer %p.\n", object); + *buffer = &object->IDirect3DVertexBuffer8_iface; + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_device_CreateIndexBuffer(IDirect3DDevice8 *iface, UINT size, + DWORD usage, D3DFORMAT format, D3DPOOL pool, IDirect3DIndexBuffer8 **buffer) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + struct d3d8_indexbuffer *object; + HRESULT hr; + + TRACE("iface %p, size %u, usage %#x, format %#x, pool %#x, buffer %p.\n", + iface, size, usage, format, pool, buffer); + + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); + if (!object) + return D3DERR_OUTOFVIDEOMEMORY; + + hr = indexbuffer_init(object, device, size, usage, format, pool); + if (FAILED(hr)) + { + WARN("Failed to initialize index buffer, hr %#x.\n", hr); + HeapFree(GetProcessHeap(), 0, object); + return hr; + } + + TRACE("Created index buffer %p.\n", object); + *buffer = &object->IDirect3DIndexBuffer8_iface; + + return D3D_OK; +} + +static HRESULT d3d8_device_create_surface(struct d3d8_device *device, UINT width, UINT height, + D3DFORMAT format, DWORD flags, IDirect3DSurface8 **surface, UINT usage, D3DPOOL pool, + D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality) +{ + struct d3d8_surface *object; + HRESULT hr; + + TRACE("device %p, width %u, height %u, format %#x, flags %#x, surface %p,\n" + "\tusage %#x, pool %#x, multisample_type %#x, multisample_quality %u.\n", + device, width, height, format, flags, surface, + usage, pool, multisample_type, multisample_quality); + + if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)))) + { + FIXME("Failed to allocate surface memory.\n"); + return D3DERR_OUTOFVIDEOMEMORY; + } + + if (FAILED(hr = surface_init(object, device, width, height, format, + flags, usage, pool, multisample_type, multisample_quality))) + { + WARN("Failed to initialize surface, hr %#x.\n", hr); + HeapFree(GetProcessHeap(), 0, object); + return hr; + } + + TRACE("Created surface %p.\n", object); + *surface = &object->IDirect3DSurface8_iface; + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_device_CreateRenderTarget(IDirect3DDevice8 *iface, UINT width, + UINT height, D3DFORMAT format, D3DMULTISAMPLE_TYPE multisample_type, BOOL lockable, + IDirect3DSurface8 **surface) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + DWORD flags = 0; + + TRACE("iface %p, width %u, height %u, format %#x, multisample_type %#x, lockable %#x, surface %p.\n", + iface, width, height, format, multisample_type, lockable, surface); + + if (lockable) + flags |= WINED3D_SURFACE_MAPPABLE; + + return d3d8_device_create_surface(device, width, height, format, flags, surface, + D3DUSAGE_RENDERTARGET, D3DPOOL_DEFAULT, multisample_type, 0); +} + +static HRESULT WINAPI d3d8_device_CreateDepthStencilSurface(IDirect3DDevice8 *iface, + UINT width, UINT height, D3DFORMAT format, D3DMULTISAMPLE_TYPE multisample_type, + IDirect3DSurface8 **surface) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + + TRACE("iface %p, width %u, height %u, format %#x, multisample_type %#x, surface %p.\n", + iface, width, height, format, multisample_type, surface); + + /* TODO: Verify that Discard is false */ + return d3d8_device_create_surface(device, width, height, format, WINED3D_SURFACE_MAPPABLE, + surface, D3DUSAGE_DEPTHSTENCIL, D3DPOOL_DEFAULT, multisample_type, 0); +} + +/* IDirect3DDevice8Impl::CreateImageSurface returns surface with pool type SYSTEMMEM */ +static HRESULT WINAPI d3d8_device_CreateImageSurface(IDirect3DDevice8 *iface, UINT width, + UINT height, D3DFORMAT format, IDirect3DSurface8 **surface) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + + TRACE("iface %p, width %u, height %u, format %#x, surface %p.\n", + iface, width, height, format, surface); + + return d3d8_device_create_surface(device, width, height, format, WINED3D_SURFACE_MAPPABLE, + surface, 0, D3DPOOL_SYSTEMMEM, D3DMULTISAMPLE_NONE, 0); +} + +static HRESULT WINAPI d3d8_device_CopyRects(IDirect3DDevice8 *iface, + IDirect3DSurface8 *src_surface, const RECT *src_rects, UINT rect_count, + IDirect3DSurface8 *dst_surface, const POINT *dst_points) +{ + struct d3d8_surface *src = unsafe_impl_from_IDirect3DSurface8(src_surface); + struct d3d8_surface *dst = unsafe_impl_from_IDirect3DSurface8(dst_surface); + enum wined3d_format_id src_format, dst_format; + struct wined3d_resource_desc wined3d_desc; + struct wined3d_resource *wined3d_resource; + UINT src_w, src_h; + HRESULT hr; + + TRACE("iface %p, src_surface %p, src_rects %p, rect_count %u, dst_surface %p, dst_points %p.\n", + iface, src_surface, src_rects, rect_count, dst_surface, dst_points); + + /* Check that the source texture is in WINED3D_POOL_SYSTEM_MEM and the + * destination texture is in WINED3D_POOL_DEFAULT. */ + + wined3d_mutex_lock(); + wined3d_resource = wined3d_surface_get_resource(src->wined3d_surface); + wined3d_resource_get_desc(wined3d_resource, &wined3d_desc); + if (wined3d_desc.usage & WINED3DUSAGE_DEPTHSTENCIL) + { + WARN("Source %p is a depth stencil surface, returning D3DERR_INVALIDCALL.\n", src_surface); + wined3d_mutex_unlock(); + return D3DERR_INVALIDCALL; + } + src_format = wined3d_desc.format; + src_w = wined3d_desc.width; + src_h = wined3d_desc.height; + + wined3d_resource = wined3d_surface_get_resource(dst->wined3d_surface); + wined3d_resource_get_desc(wined3d_resource, &wined3d_desc); + if (wined3d_desc.usage & WINED3DUSAGE_DEPTHSTENCIL) + { + WARN("Destination %p is a depth stencil surface, returning D3DERR_INVALIDCALL.\n", dst_surface); + wined3d_mutex_unlock(); + return D3DERR_INVALIDCALL; + } + dst_format = wined3d_desc.format; + + /* Check that the source and destination formats match */ + if (src_format != dst_format && WINED3DFMT_UNKNOWN != dst_format) + { + WARN("Source %p format must match the destination %p format, returning D3DERR_INVALIDCALL.\n", + src_surface, dst_surface); + wined3d_mutex_unlock(); + return D3DERR_INVALIDCALL; + } + else if (WINED3DFMT_UNKNOWN == dst_format) + { + TRACE("Converting destination surface from WINED3DFMT_UNKNOWN to the source format.\n"); + if (FAILED(hr = wined3d_surface_update_desc(dst->wined3d_surface, wined3d_desc.width, wined3d_desc.height, + src_format, wined3d_desc.multisample_type, wined3d_desc.multisample_quality))) + { + WARN("Failed to update surface desc, hr %#x.\n", hr); + wined3d_mutex_unlock(); + return hr; + } + } + + /* Quick if complete copy ... */ + if (!rect_count && !src_rects && !dst_points) + { + RECT rect = {0, 0, src_w, src_h}; + wined3d_surface_blt(dst->wined3d_surface, &rect, + src->wined3d_surface, &rect, 0, NULL, WINED3D_TEXF_POINT); + } + else + { + unsigned int i; + /* Copy rect by rect */ + if (src_rects && dst_points) + { + for (i = 0; i < rect_count; ++i) + { + UINT w = src_rects[i].right - src_rects[i].left; + UINT h = src_rects[i].bottom - src_rects[i].top; + RECT dst_rect = {dst_points[i].x, dst_points[i].y, + dst_points[i].x + w, dst_points[i].y + h}; + + wined3d_surface_blt(dst->wined3d_surface, &dst_rect, + src->wined3d_surface, &src_rects[i], 0, NULL, WINED3D_TEXF_POINT); + } + } + else + { + for (i = 0; i < rect_count; ++i) + { + UINT w = src_rects[i].right - src_rects[i].left; + UINT h = src_rects[i].bottom - src_rects[i].top; + RECT dst_rect = {0, 0, w, h}; + + wined3d_surface_blt(dst->wined3d_surface, &dst_rect, + src->wined3d_surface, &src_rects[i], 0, NULL, WINED3D_TEXF_POINT); + } + } + } + wined3d_mutex_unlock(); + + return WINED3D_OK; +} + +static HRESULT WINAPI d3d8_device_UpdateTexture(IDirect3DDevice8 *iface, + IDirect3DBaseTexture8 *src_texture, IDirect3DBaseTexture8 *dst_texture) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + struct d3d8_texture *src_impl, *dst_impl; + HRESULT hr; + + TRACE("iface %p, src_texture %p, dst_texture %p.\n", iface, src_texture, dst_texture); + + src_impl = unsafe_impl_from_IDirect3DBaseTexture8(src_texture); + dst_impl = unsafe_impl_from_IDirect3DBaseTexture8(dst_texture); + + wined3d_mutex_lock(); + hr = wined3d_device_update_texture(device->wined3d_device, + src_impl->wined3d_texture, dst_impl->wined3d_texture); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_device_GetFrontBuffer(IDirect3DDevice8 *iface, IDirect3DSurface8 *dst_surface) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + struct d3d8_surface *dst_impl = unsafe_impl_from_IDirect3DSurface8(dst_surface); + HRESULT hr; + + TRACE("iface %p, dst_surface %p.\n", iface, dst_surface); + + if (!dst_surface) + { + WARN("Invalid destination surface passed.\n"); + return D3DERR_INVALIDCALL; + } + + wined3d_mutex_lock(); + hr = wined3d_device_get_front_buffer_data(device->wined3d_device, 0, dst_impl->wined3d_surface); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_device_SetRenderTarget(IDirect3DDevice8 *iface, + IDirect3DSurface8 *render_target, IDirect3DSurface8 *depth_stencil) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + struct d3d8_surface *rt_impl = unsafe_impl_from_IDirect3DSurface8(render_target); + struct d3d8_surface *ds_impl = unsafe_impl_from_IDirect3DSurface8(depth_stencil); + struct wined3d_surface *original_ds = NULL; + HRESULT hr = D3D_OK; + + TRACE("iface %p, render_target %p, depth_stencil %p.\n", iface, render_target, depth_stencil); + + wined3d_mutex_lock(); + + if (ds_impl) + { + struct wined3d_resource_desc ds_desc, rt_desc; + struct wined3d_resource *wined3d_resource; + struct wined3d_surface *original_rt = NULL; + + /* If no render target is passed in check the size against the current RT */ + if (!render_target) + { + if (!(original_rt = wined3d_device_get_render_target(device->wined3d_device, 0))) + { + wined3d_mutex_unlock(); + return D3DERR_NOTFOUND; + } + wined3d_resource = wined3d_surface_get_resource(original_rt); + } + else + wined3d_resource = wined3d_surface_get_resource(rt_impl->wined3d_surface); + wined3d_resource_get_desc(wined3d_resource, &rt_desc); + + wined3d_resource = wined3d_surface_get_resource(ds_impl->wined3d_surface); + wined3d_resource_get_desc(wined3d_resource, &ds_desc); + + if (ds_desc.width < rt_desc.width || ds_desc.height < rt_desc.height) + { + WARN("Depth stencil is smaller than the render target, returning D3DERR_INVALIDCALL\n"); + wined3d_mutex_unlock(); + return D3DERR_INVALIDCALL; + } + } + + original_ds = wined3d_device_get_depth_stencil(device->wined3d_device); + wined3d_device_set_depth_stencil(device->wined3d_device, ds_impl ? ds_impl->wined3d_surface : NULL); + if (render_target) + { + hr = wined3d_device_set_render_target(device->wined3d_device, 0, rt_impl->wined3d_surface, TRUE); + if (FAILED(hr)) + wined3d_device_set_depth_stencil(device->wined3d_device, original_ds); + } + + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_device_GetRenderTarget(IDirect3DDevice8 *iface, IDirect3DSurface8 **render_target) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + struct wined3d_surface *wined3d_surface; + struct d3d8_surface *surface_impl; + HRESULT hr; + + TRACE("iface %p, render_target %p.\n", iface, render_target); + + if (!render_target) + return D3DERR_INVALIDCALL; + + wined3d_mutex_lock(); + if ((wined3d_surface = wined3d_device_get_render_target(device->wined3d_device, 0))) + { + surface_impl = wined3d_surface_get_parent(wined3d_surface); + *render_target = &surface_impl->IDirect3DSurface8_iface; + IDirect3DSurface8_AddRef(*render_target); + hr = D3D_OK; + } + else + { + ERR("Failed to get wined3d render target.\n"); + *render_target = NULL; + hr = D3DERR_NOTFOUND; + } + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_device_GetDepthStencilSurface(IDirect3DDevice8 *iface, IDirect3DSurface8 **depth_stencil) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + struct wined3d_surface *wined3d_surface; + struct d3d8_surface *surface_impl; + HRESULT hr = D3D_OK; + + TRACE("iface %p, depth_stencil %p.\n", iface, depth_stencil); + + if (!depth_stencil) + return D3DERR_INVALIDCALL; + + wined3d_mutex_lock(); + if ((wined3d_surface = wined3d_device_get_depth_stencil(device->wined3d_device))) + { + surface_impl = wined3d_surface_get_parent(wined3d_surface); + *depth_stencil = &surface_impl->IDirect3DSurface8_iface; + IDirect3DSurface8_AddRef(*depth_stencil); + } + else + { + hr = WINED3DERR_NOTFOUND; + *depth_stencil = NULL; + } + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_device_BeginScene(IDirect3DDevice8 *iface) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + HRESULT hr; + + TRACE("iface %p.\n", iface); + + wined3d_mutex_lock(); + hr = wined3d_device_begin_scene(device->wined3d_device); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI DECLSPEC_HOTPATCH d3d8_device_EndScene(IDirect3DDevice8 *iface) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + HRESULT hr; + + TRACE("iface %p.\n", iface); + + wined3d_mutex_lock(); + hr = wined3d_device_end_scene(device->wined3d_device); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_device_Clear(IDirect3DDevice8 *iface, DWORD rect_count, + const D3DRECT *rects, DWORD flags, D3DCOLOR color, float z, DWORD stencil) +{ + const struct wined3d_color c = + { + ((color >> 16) & 0xff) / 255.0f, + ((color >> 8) & 0xff) / 255.0f, + (color & 0xff) / 255.0f, + ((color >> 24) & 0xff) / 255.0f, + }; + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + HRESULT hr; + + TRACE("iface %p, rect_count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %u.\n", + iface, rect_count, rects, flags, color, z, stencil); + + wined3d_mutex_lock(); + hr = wined3d_device_clear(device->wined3d_device, rect_count, (const RECT *)rects, flags, &c, z, stencil); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_device_SetTransform(IDirect3DDevice8 *iface, + D3DTRANSFORMSTATETYPE state, const D3DMATRIX *matrix) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + + TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix); + + /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */ + wined3d_mutex_lock(); + wined3d_device_set_transform(device->wined3d_device, state, (const struct wined3d_matrix *)matrix); + wined3d_mutex_unlock(); + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_device_GetTransform(IDirect3DDevice8 *iface, + D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + + TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix); + + /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */ + wined3d_mutex_lock(); + wined3d_device_get_transform(device->wined3d_device, state, (struct wined3d_matrix *)matrix); + wined3d_mutex_unlock(); + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_device_MultiplyTransform(IDirect3DDevice8 *iface, + D3DTRANSFORMSTATETYPE state, const D3DMATRIX *matrix) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + + TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix); + + /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */ + wined3d_mutex_lock(); + wined3d_device_multiply_transform(device->wined3d_device, state, (const struct wined3d_matrix *)matrix); + wined3d_mutex_unlock(); + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_device_SetViewport(IDirect3DDevice8 *iface, const D3DVIEWPORT8 *viewport) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + + TRACE("iface %p, viewport %p.\n", iface, viewport); + + /* Note: D3DVIEWPORT8 is compatible with struct wined3d_viewport. */ + wined3d_mutex_lock(); + wined3d_device_set_viewport(device->wined3d_device, (const struct wined3d_viewport *)viewport); + wined3d_mutex_unlock(); + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_device_GetViewport(IDirect3DDevice8 *iface, D3DVIEWPORT8 *viewport) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + + TRACE("iface %p, viewport %p.\n", iface, viewport); + + /* Note: D3DVIEWPORT8 is compatible with struct wined3d_viewport. */ + wined3d_mutex_lock(); + wined3d_device_get_viewport(device->wined3d_device, (struct wined3d_viewport *)viewport); + wined3d_mutex_unlock(); + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_device_SetMaterial(IDirect3DDevice8 *iface, const D3DMATERIAL8 *material) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + + TRACE("iface %p, material %p.\n", iface, material); + + /* Note: D3DMATERIAL8 is compatible with struct wined3d_material. */ + wined3d_mutex_lock(); + wined3d_device_set_material(device->wined3d_device, (const struct wined3d_material *)material); + wined3d_mutex_unlock(); + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_device_GetMaterial(IDirect3DDevice8 *iface, D3DMATERIAL8 *material) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + + TRACE("iface %p, material %p.\n", iface, material); + + /* Note: D3DMATERIAL8 is compatible with struct wined3d_material. */ + wined3d_mutex_lock(); + wined3d_device_get_material(device->wined3d_device, (struct wined3d_material *)material); + wined3d_mutex_unlock(); + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_device_SetLight(IDirect3DDevice8 *iface, DWORD index, const D3DLIGHT8 *light) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + HRESULT hr; + + TRACE("iface %p, index %u, light %p.\n", iface, index, light); + + /* Note: D3DLIGHT8 is compatible with struct wined3d_light. */ + wined3d_mutex_lock(); + hr = wined3d_device_set_light(device->wined3d_device, index, (const struct wined3d_light *)light); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_device_GetLight(IDirect3DDevice8 *iface, DWORD index, D3DLIGHT8 *light) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + HRESULT hr; + + TRACE("iface %p, index %u, light %p.\n", iface, index, light); + + /* Note: D3DLIGHT8 is compatible with struct wined3d_light. */ + wined3d_mutex_lock(); + hr = wined3d_device_get_light(device->wined3d_device, index, (struct wined3d_light *)light); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_device_LightEnable(IDirect3DDevice8 *iface, DWORD index, BOOL enable) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + HRESULT hr; + + TRACE("iface %p, index %u, enable %#x.\n", iface, index, enable); + + wined3d_mutex_lock(); + hr = wined3d_device_set_light_enable(device->wined3d_device, index, enable); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_device_GetLightEnable(IDirect3DDevice8 *iface, DWORD index, BOOL *enable) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + HRESULT hr; + + TRACE("iface %p, index %u, enable %p.\n", iface, index, enable); + + wined3d_mutex_lock(); + hr = wined3d_device_get_light_enable(device->wined3d_device, index, enable); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_device_SetClipPlane(IDirect3DDevice8 *iface, DWORD index, const float *plane) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + HRESULT hr; + + TRACE("iface %p, index %u, plane %p.\n", iface, index, plane); + + wined3d_mutex_lock(); + hr = wined3d_device_set_clip_plane(device->wined3d_device, index, (const struct wined3d_vec4 *)plane); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_device_GetClipPlane(IDirect3DDevice8 *iface, DWORD index, float *plane) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + HRESULT hr; + + TRACE("iface %p, index %u, plane %p.\n", iface, index, plane); + + wined3d_mutex_lock(); + hr = wined3d_device_get_clip_plane(device->wined3d_device, index, (struct wined3d_vec4 *)plane); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_device_SetRenderState(IDirect3DDevice8 *iface, + D3DRENDERSTATETYPE state, DWORD value) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + + TRACE("iface %p, state %#x, value %#x.\n", iface, state, value); + + wined3d_mutex_lock(); + switch (state) + { + case D3DRS_ZBIAS: + wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS, value); + break; + + default: + wined3d_device_set_render_state(device->wined3d_device, state, value); + } + wined3d_mutex_unlock(); + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_device_GetRenderState(IDirect3DDevice8 *iface, + D3DRENDERSTATETYPE state, DWORD *value) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + + TRACE("iface %p, state %#x, value %p.\n", iface, state, value); + + wined3d_mutex_lock(); + switch (state) + { + case D3DRS_ZBIAS: + *value = wined3d_device_get_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS); + break; + + default: + *value = wined3d_device_get_render_state(device->wined3d_device, state); + } + wined3d_mutex_unlock(); + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_device_BeginStateBlock(IDirect3DDevice8 *iface) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + HRESULT hr; + + TRACE("iface %p.\n", iface); + + wined3d_mutex_lock(); + hr = wined3d_device_begin_stateblock(device->wined3d_device); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_device_EndStateBlock(IDirect3DDevice8 *iface, DWORD *token) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + struct wined3d_stateblock *stateblock; + HRESULT hr; + + TRACE("iface %p, token %p.\n", iface, token); + + /* Tell wineD3D to endstateblock before anything else (in case we run out + * of memory later and cause locking problems) + */ + wined3d_mutex_lock(); + hr = wined3d_device_end_stateblock(device->wined3d_device, &stateblock); + if (FAILED(hr)) + { + WARN("IWineD3DDevice_EndStateBlock returned an error\n"); + wined3d_mutex_unlock(); + return hr; + } + + *token = d3d8_allocate_handle(&device->handle_table, stateblock, D3D8_HANDLE_SB); + wined3d_mutex_unlock(); + + if (*token == D3D8_INVALID_HANDLE) + { + ERR("Failed to create a handle\n"); + wined3d_mutex_lock(); + wined3d_stateblock_decref(stateblock); + wined3d_mutex_unlock(); + return E_FAIL; + } + ++*token; + + TRACE("Returning %#x (%p).\n", *token, stateblock); + + return hr; +} + +static HRESULT WINAPI d3d8_device_ApplyStateBlock(IDirect3DDevice8 *iface, DWORD token) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + struct wined3d_stateblock *stateblock; + + TRACE("iface %p, token %#x.\n", iface, token); + + if (!token) + return D3D_OK; + + wined3d_mutex_lock(); + stateblock = d3d8_get_object(&device->handle_table, token - 1, D3D8_HANDLE_SB); + if (!stateblock) + { + WARN("Invalid handle (%#x) passed.\n", token); + wined3d_mutex_unlock(); + return D3DERR_INVALIDCALL; + } + wined3d_stateblock_apply(stateblock); + wined3d_mutex_unlock(); + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_device_CaptureStateBlock(IDirect3DDevice8 *iface, DWORD token) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + struct wined3d_stateblock *stateblock; + + TRACE("iface %p, token %#x.\n", iface, token); + + wined3d_mutex_lock(); + stateblock = d3d8_get_object(&device->handle_table, token - 1, D3D8_HANDLE_SB); + if (!stateblock) + { + WARN("Invalid handle (%#x) passed.\n", token); + wined3d_mutex_unlock(); + return D3DERR_INVALIDCALL; + } + wined3d_stateblock_capture(stateblock); + wined3d_mutex_unlock(); + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_device_DeleteStateBlock(IDirect3DDevice8 *iface, DWORD token) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + struct wined3d_stateblock *stateblock; + + TRACE("iface %p, token %#x.\n", iface, token); + + wined3d_mutex_lock(); + stateblock = d3d8_free_handle(&device->handle_table, token - 1, D3D8_HANDLE_SB); + + if (!stateblock) + { + WARN("Invalid handle (%#x) passed.\n", token); + wined3d_mutex_unlock(); + return D3DERR_INVALIDCALL; + } + + if (wined3d_stateblock_decref(stateblock)) + { + ERR("Stateblock %p has references left, this shouldn't happen.\n", stateblock); + } + wined3d_mutex_unlock(); + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_device_CreateStateBlock(IDirect3DDevice8 *iface, + D3DSTATEBLOCKTYPE type, DWORD *handle) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + struct wined3d_stateblock *stateblock; + HRESULT hr; + + TRACE("iface %p, type %#x, handle %p.\n", iface, type, handle); + + if (type != D3DSBT_ALL + && type != D3DSBT_PIXELSTATE + && type != D3DSBT_VERTEXSTATE) + { + WARN("Unexpected stateblock type, returning D3DERR_INVALIDCALL\n"); + return D3DERR_INVALIDCALL; + } + + wined3d_mutex_lock(); + hr = wined3d_stateblock_create(device->wined3d_device, (enum wined3d_stateblock_type)type, &stateblock); + if (FAILED(hr)) + { + wined3d_mutex_unlock(); + ERR("IWineD3DDevice_CreateStateBlock failed, hr %#x\n", hr); + return hr; + } + + *handle = d3d8_allocate_handle(&device->handle_table, stateblock, D3D8_HANDLE_SB); + wined3d_mutex_unlock(); + + if (*handle == D3D8_INVALID_HANDLE) + { + ERR("Failed to allocate a handle.\n"); + wined3d_mutex_lock(); + wined3d_stateblock_decref(stateblock); + wined3d_mutex_unlock(); + return E_FAIL; + } + ++*handle; + + TRACE("Returning %#x (%p).\n", *handle, stateblock); + + return hr; +} + +static HRESULT WINAPI d3d8_device_SetClipStatus(IDirect3DDevice8 *iface, const D3DCLIPSTATUS8 *clip_status) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + HRESULT hr; + + TRACE("iface %p, clip_status %p.\n", iface, clip_status); + /* FIXME: Verify that D3DCLIPSTATUS8 ~= struct wined3d_clip_status. */ + + wined3d_mutex_lock(); + hr = wined3d_device_set_clip_status(device->wined3d_device, (const struct wined3d_clip_status *)clip_status); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_device_GetClipStatus(IDirect3DDevice8 *iface, D3DCLIPSTATUS8 *clip_status) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + HRESULT hr; + + TRACE("iface %p, clip_status %p.\n", iface, clip_status); + + wined3d_mutex_lock(); + hr = wined3d_device_get_clip_status(device->wined3d_device, (struct wined3d_clip_status *)clip_status); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_device_GetTexture(IDirect3DDevice8 *iface, DWORD stage, IDirect3DBaseTexture8 **texture) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + struct wined3d_texture *wined3d_texture; + struct d3d8_texture *texture_impl; + + TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture); + + if (!texture) + return D3DERR_INVALIDCALL; + + wined3d_mutex_lock(); + if ((wined3d_texture = wined3d_device_get_texture(device->wined3d_device, stage))) + { + texture_impl = wined3d_texture_get_parent(wined3d_texture); + *texture = &texture_impl->IDirect3DBaseTexture8_iface; + IDirect3DBaseTexture8_AddRef(*texture); + } + else + { + *texture = NULL; + } + wined3d_mutex_unlock(); + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_device_SetTexture(IDirect3DDevice8 *iface, DWORD stage, IDirect3DBaseTexture8 *texture) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + struct d3d8_texture *texture_impl; + HRESULT hr; + + TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture); + + texture_impl = unsafe_impl_from_IDirect3DBaseTexture8(texture); + + wined3d_mutex_lock(); + hr = wined3d_device_set_texture(device->wined3d_device, stage, + texture_impl ? texture_impl->wined3d_texture : NULL); + wined3d_mutex_unlock(); + + return hr; +} + +static const struct tss_lookup +{ + BOOL sampler_state; + enum wined3d_texture_stage_state state; +} +tss_lookup[] = +{ + {FALSE, WINED3D_TSS_INVALID}, /* 0, unused */ + {FALSE, WINED3D_TSS_COLOR_OP}, /* 1, D3DTSS_COLOROP */ + {FALSE, WINED3D_TSS_COLOR_ARG1}, /* 2, D3DTSS_COLORARG1 */ + {FALSE, WINED3D_TSS_COLOR_ARG2}, /* 3, D3DTSS_COLORARG2 */ + {FALSE, WINED3D_TSS_ALPHA_OP}, /* 4, D3DTSS_ALPHAOP */ + {FALSE, WINED3D_TSS_ALPHA_ARG1}, /* 5, D3DTSS_ALPHAARG1 */ + {FALSE, WINED3D_TSS_ALPHA_ARG2}, /* 6, D3DTSS_ALPHAARG2 */ + {FALSE, WINED3D_TSS_BUMPENV_MAT00}, /* 7, D3DTSS_BUMPENVMAT00 */ + {FALSE, WINED3D_TSS_BUMPENV_MAT01}, /* 8, D3DTSS_BUMPENVMAT01 */ + {FALSE, WINED3D_TSS_BUMPENV_MAT10}, /* 9, D3DTSS_BUMPENVMAT10 */ + {FALSE, WINED3D_TSS_BUMPENV_MAT11}, /* 10, D3DTSS_BUMPENVMAT11 */ + {FALSE, WINED3D_TSS_TEXCOORD_INDEX}, /* 11, D3DTSS_TEXCOORDINDEX */ + {FALSE, WINED3D_TSS_INVALID}, /* 12, unused */ + {TRUE, WINED3D_SAMP_ADDRESS_U}, /* 13, D3DTSS_ADDRESSU */ + {TRUE, WINED3D_SAMP_ADDRESS_V}, /* 14, D3DTSS_ADDRESSV */ + {TRUE, WINED3D_SAMP_BORDER_COLOR}, /* 15, D3DTSS_BORDERCOLOR */ + {TRUE, WINED3D_SAMP_MAG_FILTER}, /* 16, D3DTSS_MAGFILTER */ + {TRUE, WINED3D_SAMP_MIN_FILTER}, /* 17, D3DTSS_MINFILTER */ + {TRUE, WINED3D_SAMP_MIP_FILTER}, /* 18, D3DTSS_MIPFILTER */ + {TRUE, WINED3D_SAMP_MIPMAP_LOD_BIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */ + {TRUE, WINED3D_SAMP_MAX_MIP_LEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */ + {TRUE, WINED3D_SAMP_MAX_ANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */ + {FALSE, WINED3D_TSS_BUMPENV_LSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */ + {FALSE, WINED3D_TSS_BUMPENV_LOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */ + {FALSE, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */ + {TRUE, WINED3D_SAMP_ADDRESS_W}, /* 25, D3DTSS_ADDRESSW */ + {FALSE, WINED3D_TSS_COLOR_ARG0}, /* 26, D3DTSS_COLORARG0 */ + {FALSE, WINED3D_TSS_ALPHA_ARG0}, /* 27, D3DTSS_ALPHAARG0 */ + {FALSE, WINED3D_TSS_RESULT_ARG}, /* 28, D3DTSS_RESULTARG */ +}; + +static HRESULT WINAPI d3d8_device_GetTextureStageState(IDirect3DDevice8 *iface, + DWORD stage, D3DTEXTURESTAGESTATETYPE Type, DWORD *value) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + const struct tss_lookup *l; + + TRACE("iface %p, stage %u, state %#x, value %p.\n", iface, stage, Type, value); + + if (Type >= sizeof(tss_lookup) / sizeof(*tss_lookup)) + { + WARN("Invalid Type %#x passed.\n", Type); + return D3D_OK; + } + + l = &tss_lookup[Type]; + + wined3d_mutex_lock(); + if (l->sampler_state) + *value = wined3d_device_get_sampler_state(device->wined3d_device, stage, l->state); + else + *value = wined3d_device_get_texture_stage_state(device->wined3d_device, stage, l->state); + wined3d_mutex_unlock(); + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_device_SetTextureStageState(IDirect3DDevice8 *iface, + DWORD stage, D3DTEXTURESTAGESTATETYPE type, DWORD value) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + const struct tss_lookup *l; + + TRACE("iface %p, stage %u, state %#x, value %#x.\n", iface, stage, type, value); + + if (type >= sizeof(tss_lookup) / sizeof(*tss_lookup)) + { + WARN("Invalid type %#x passed.\n", type); + return D3D_OK; + } + + l = &tss_lookup[type]; + + wined3d_mutex_lock(); + if (l->sampler_state) + wined3d_device_set_sampler_state(device->wined3d_device, stage, l->state, value); + else + wined3d_device_set_texture_stage_state(device->wined3d_device, stage, l->state, value); + wined3d_mutex_unlock(); + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_device_ValidateDevice(IDirect3DDevice8 *iface, DWORD *pass_count) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + HRESULT hr; + + TRACE("iface %p, pass_count %p.\n", iface, pass_count); + + wined3d_mutex_lock(); + hr = wined3d_device_validate_device(device->wined3d_device, pass_count); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_device_GetInfo(IDirect3DDevice8 *iface, + DWORD info_id, void *info, DWORD info_size) +{ + FIXME("iface %p, info_id %#x, info %p, info_size %u stub!\n", iface, info_id, info, info_size); + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_device_SetPaletteEntries(IDirect3DDevice8 *iface, + UINT palette_idx, const PALETTEENTRY *entries) +{ + WARN("iface %p, palette_idx %u, entries %p unimplemented\n", iface, palette_idx, entries); + + /* GPUs stopped supporting palettized textures with the Shader Model 1 generation. Wined3d + * does not have a d3d8/9-style palette API */ + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_device_GetPaletteEntries(IDirect3DDevice8 *iface, + UINT palette_idx, PALETTEENTRY *entries) +{ + FIXME("iface %p, palette_idx %u, entries %p unimplemented.\n", iface, palette_idx, entries); + + return D3DERR_INVALIDCALL; +} + +static HRESULT WINAPI d3d8_device_SetCurrentTexturePalette(IDirect3DDevice8 *iface, UINT palette_idx) +{ + WARN("iface %p, palette_idx %u unimplemented.\n", iface, palette_idx); + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_device_GetCurrentTexturePalette(IDirect3DDevice8 *iface, UINT *palette_idx) +{ + FIXME("iface %p, palette_idx %p unimplemented.\n", iface, palette_idx); + + return D3DERR_INVALIDCALL; +} + +static HRESULT WINAPI d3d8_device_DrawPrimitive(IDirect3DDevice8 *iface, + D3DPRIMITIVETYPE primitive_type, UINT start_vertex, UINT primitive_count) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + HRESULT hr; + + TRACE("iface %p, primitive_type %#x, start_vertex %u, primitive_count %u.\n", + iface, primitive_type, start_vertex, primitive_count); + + wined3d_mutex_lock(); + wined3d_device_set_primitive_type(device->wined3d_device, primitive_type); + hr = wined3d_device_draw_primitive(device->wined3d_device, start_vertex, + vertex_count_from_primitive_count(primitive_type, primitive_count)); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_device_DrawIndexedPrimitive(IDirect3DDevice8 *iface, + D3DPRIMITIVETYPE primitive_type, UINT min_vertex_idx, UINT vertex_count, + UINT start_idx, UINT primitive_count) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + HRESULT hr; + + TRACE("iface %p, primitive_type %#x, min_vertex_idx %u, vertex_count %u, start_idx %u, primitive_count %u.\n", + iface, primitive_type, min_vertex_idx, vertex_count, start_idx, primitive_count); + + wined3d_mutex_lock(); + wined3d_device_set_primitive_type(device->wined3d_device, primitive_type); + hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, start_idx, + vertex_count_from_primitive_count(primitive_type, primitive_count)); + wined3d_mutex_unlock(); + + return hr; +} + +static void STDMETHODCALLTYPE d3d8_null_wined3d_object_destroyed(void *parent) {} + +static const struct wined3d_parent_ops d3d8_null_wined3d_parent_ops = +{ + d3d8_null_wined3d_object_destroyed, +}; + +/* The caller is responsible for wined3d locking */ +static HRESULT d3d8_device_prepare_vertex_buffer(struct d3d8_device *device, UINT min_size) +{ + HRESULT hr; + + if (device->vertex_buffer_size < min_size || !device->vertex_buffer) + { + UINT size = max(device->vertex_buffer_size * 2, min_size); + struct wined3d_buffer *buffer; + + TRACE("Growing vertex buffer to %u bytes\n", size); + + hr = wined3d_buffer_create_vb(device->wined3d_device, size, WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY, + WINED3D_POOL_DEFAULT, NULL, &d3d8_null_wined3d_parent_ops, &buffer); + if (FAILED(hr)) + { + ERR("(%p) wined3d_buffer_create_vb failed with hr = %08x\n", device, hr); + return hr; + } + + if (device->vertex_buffer) + wined3d_buffer_decref(device->vertex_buffer); + + device->vertex_buffer = buffer; + device->vertex_buffer_size = size; + device->vertex_buffer_pos = 0; + } + return D3D_OK; +} + +static HRESULT WINAPI d3d8_device_DrawPrimitiveUP(IDirect3DDevice8 *iface, + D3DPRIMITIVETYPE primitive_type, UINT primitive_count, const void *data, + UINT stride) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + HRESULT hr; + UINT vtx_count = vertex_count_from_primitive_count(primitive_type, primitive_count); + UINT size = vtx_count * stride; + UINT vb_pos, align; + BYTE *buffer_data; + + TRACE("iface %p, primitive_type %#x, primitive_count %u, data %p, stride %u.\n", + iface, primitive_type, primitive_count, data, stride); + + if (!primitive_count) + { + WARN("primitive_count is 0, returning D3D_OK\n"); + return D3D_OK; + } + + wined3d_mutex_lock(); + hr = d3d8_device_prepare_vertex_buffer(device, size); + if (FAILED(hr)) + goto done; + + vb_pos = device->vertex_buffer_pos; + align = vb_pos % stride; + if (align) align = stride - align; + if (vb_pos + size + align > device->vertex_buffer_size) + vb_pos = 0; + else + vb_pos += align; + + hr = wined3d_buffer_map(device->vertex_buffer, vb_pos, size, &buffer_data, + vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD); + if (FAILED(hr)) + goto done; + memcpy(buffer_data, data, size); + wined3d_buffer_unmap(device->vertex_buffer); + device->vertex_buffer_pos = vb_pos + size; + + hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, stride); + if (FAILED(hr)) + goto done; + + wined3d_device_set_primitive_type(device->wined3d_device, primitive_type); + hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / stride, vtx_count); + wined3d_device_set_stream_source(device->wined3d_device, 0, NULL, 0, 0); + +done: + wined3d_mutex_unlock(); + return hr; +} + +/* The caller is responsible for wined3d locking */ +static HRESULT d3d8_device_prepare_index_buffer(struct d3d8_device *device, UINT min_size) +{ + HRESULT hr; + + if (device->index_buffer_size < min_size || !device->index_buffer) + { + UINT size = max(device->index_buffer_size * 2, min_size); + struct wined3d_buffer *buffer; + + TRACE("Growing index buffer to %u bytes\n", size); + + hr = wined3d_buffer_create_ib(device->wined3d_device, size, WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY, + WINED3D_POOL_DEFAULT, NULL, &d3d8_null_wined3d_parent_ops, &buffer); + if (FAILED(hr)) + { + ERR("(%p) wined3d_buffer_create_ib failed with hr = %08x\n", device, hr); + return hr; + } + + if (device->index_buffer) + wined3d_buffer_decref(device->index_buffer); + + device->index_buffer = buffer; + device->index_buffer_size = size; + device->index_buffer_pos = 0; + } + return D3D_OK; +} + +static HRESULT WINAPI d3d8_device_DrawIndexedPrimitiveUP(IDirect3DDevice8 *iface, + D3DPRIMITIVETYPE primitive_type, UINT min_vertex_idx, UINT vertex_count, + UINT primitive_count, const void *index_data, D3DFORMAT index_format, + const void *vertex_data, UINT vertex_stride) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + HRESULT hr; + BYTE *buffer_data; + + UINT idx_count = vertex_count_from_primitive_count(primitive_type, primitive_count); + UINT idx_fmt_size = index_format == D3DFMT_INDEX16 ? 2 : 4; + UINT idx_size = idx_count * idx_fmt_size; + UINT ib_pos; + + UINT vtx_size = vertex_count * vertex_stride; + UINT vb_pos, align; + + TRACE("iface %p, primitive_type %#x, min_vertex_idx %u, vertex_count %u, primitive_count %u,\n" + "index_data %p, index_format %#x, vertex_data %p, vertex_stride %u.\n", + iface, primitive_type, min_vertex_idx, vertex_count, primitive_count, + index_data, index_format, vertex_data, vertex_stride); + + if (!primitive_count) + { + WARN("primitive_count is 0, returning D3D_OK\n"); + return D3D_OK; + } + + wined3d_mutex_lock(); + + hr = d3d8_device_prepare_vertex_buffer(device, vtx_size); + if (FAILED(hr)) + goto done; + + vb_pos = device->vertex_buffer_pos; + align = vb_pos % vertex_stride; + if (align) align = vertex_stride - align; + if (vb_pos + vtx_size + align > device->vertex_buffer_size) + vb_pos = 0; + else + vb_pos += align; + + hr = wined3d_buffer_map(device->vertex_buffer, vb_pos, vtx_size, &buffer_data, + vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD); + if (FAILED(hr)) + goto done; + memcpy(buffer_data, vertex_data, vtx_size); + wined3d_buffer_unmap(device->vertex_buffer); + device->vertex_buffer_pos = vb_pos + vtx_size; + + hr = d3d8_device_prepare_index_buffer(device, idx_size); + if (FAILED(hr)) + goto done; + + ib_pos = device->index_buffer_pos; + align = ib_pos % idx_fmt_size; + if (align) align = idx_fmt_size - align; + if (ib_pos + idx_size + align > device->index_buffer_size) + ib_pos = 0; + else + ib_pos += align; + + hr = wined3d_buffer_map(device->index_buffer, ib_pos, idx_size, &buffer_data, + ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD); + if (FAILED(hr)) + goto done; + memcpy(buffer_data, index_data, idx_size); + wined3d_buffer_unmap(device->index_buffer); + device->index_buffer_pos = ib_pos + idx_size; + + hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, vertex_stride); + if (FAILED(hr)) + goto done; + + wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer, + wined3dformat_from_d3dformat(index_format)); + wined3d_device_set_base_vertex_index(device->wined3d_device, vb_pos / vertex_stride); + + wined3d_device_set_primitive_type(device->wined3d_device, primitive_type); + hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / idx_fmt_size, idx_count); + + wined3d_device_set_stream_source(device->wined3d_device, 0, NULL, 0, 0); + wined3d_device_set_index_buffer(device->wined3d_device, NULL, WINED3DFMT_UNKNOWN); + wined3d_device_set_base_vertex_index(device->wined3d_device, 0); + +done: + wined3d_mutex_unlock(); + return hr; +} + +static HRESULT WINAPI d3d8_device_ProcessVertices(IDirect3DDevice8 *iface, UINT src_start_idx, + UINT dst_idx, UINT vertex_count, IDirect3DVertexBuffer8 *dst_buffer, DWORD flags) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + struct d3d8_vertexbuffer *dst = unsafe_impl_from_IDirect3DVertexBuffer8(dst_buffer); + HRESULT hr; + + TRACE("iface %p, src_start_idx %u, dst_idx %u, vertex_count %u, dst_buffer %p, flags %#x.\n", + iface, src_start_idx, dst_idx, vertex_count, dst_buffer, flags); + + wined3d_mutex_lock(); + hr = wined3d_device_process_vertices(device->wined3d_device, src_start_idx, dst_idx, + vertex_count, dst->wined3d_buffer, NULL, flags, dst->fvf); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_device_CreateVertexShader(IDirect3DDevice8 *iface, + const DWORD *declaration, const DWORD *byte_code, DWORD *shader, DWORD usage) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + struct d3d8_vertex_shader *object; + DWORD shader_handle; + DWORD handle; + HRESULT hr; + + TRACE("iface %p, declaration %p, byte_code %p, shader %p, usage %#x.\n", + iface, declaration, byte_code, shader, usage); + + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); + if (!object) + { + *shader = 0; + return E_OUTOFMEMORY; + } + + wined3d_mutex_lock(); + handle = d3d8_allocate_handle(&device->handle_table, object, D3D8_HANDLE_VS); + wined3d_mutex_unlock(); + if (handle == D3D8_INVALID_HANDLE) + { + ERR("Failed to allocate vertex shader handle.\n"); + HeapFree(GetProcessHeap(), 0, object); + *shader = 0; + return E_OUTOFMEMORY; + } + + shader_handle = handle + VS_HIGHESTFIXEDFXF + 1; + + hr = d3d8_vertex_shader_init(object, device, declaration, byte_code, shader_handle, usage); + if (FAILED(hr)) + { + WARN("Failed to initialize vertex shader, hr %#x.\n", hr); + wined3d_mutex_lock(); + d3d8_free_handle(&device->handle_table, handle, D3D8_HANDLE_VS); + wined3d_mutex_unlock(); + HeapFree(GetProcessHeap(), 0, object); + *shader = 0; + return hr; + } + + TRACE("Created vertex shader %p (handle %#x).\n", object, shader_handle); + *shader = shader_handle; + + return D3D_OK; +} + +static struct d3d8_vertex_declaration *d3d8_device_get_fvf_declaration(struct d3d8_device *device, DWORD fvf) +{ + struct d3d8_vertex_declaration *d3d8_declaration; + struct FvfToDecl *convertedDecls = device->decls; + int p, low, high; /* deliberately signed */ + HRESULT hr; + + TRACE("Searching for declaration for fvf %08x... ", fvf); + + low = 0; + high = device->numConvertedDecls - 1; + while (low <= high) + { + p = (low + high) >> 1; + TRACE("%d ", p); + + if (convertedDecls[p].fvf == fvf) + { + TRACE("found %p\n", convertedDecls[p].declaration); + return convertedDecls[p].declaration; + } + + if (convertedDecls[p].fvf < fvf) + low = p + 1; + else + high = p - 1; + } + TRACE("not found. Creating and inserting at position %d.\n", low); + + if (!(d3d8_declaration = HeapAlloc(GetProcessHeap(), 0, sizeof(*d3d8_declaration)))) + return NULL; + + if (FAILED(hr = d3d8_vertex_declaration_init_fvf(d3d8_declaration, device, fvf))) + { + WARN("Failed to initialize vertex declaration, hr %#x.\n", hr); + HeapFree(GetProcessHeap(), 0, d3d8_declaration); + return NULL; + } + + if (device->declArraySize == device->numConvertedDecls) + { + UINT grow = device->declArraySize / 2; + + convertedDecls = HeapReAlloc(GetProcessHeap(), 0, convertedDecls, + sizeof(*convertedDecls) * (device->numConvertedDecls + grow)); + if (!convertedDecls) + { + d3d8_vertex_declaration_destroy(d3d8_declaration); + return NULL; + } + device->decls = convertedDecls; + device->declArraySize += grow; + } + + memmove(convertedDecls + low + 1, convertedDecls + low, + sizeof(*convertedDecls) * (device->numConvertedDecls - low)); + convertedDecls[low].declaration = d3d8_declaration; + convertedDecls[low].fvf = fvf; + ++device->numConvertedDecls; + + TRACE("Returning %p. %u decls in array.\n", d3d8_declaration, device->numConvertedDecls); + + return d3d8_declaration; +} + +static HRESULT WINAPI d3d8_device_SetVertexShader(IDirect3DDevice8 *iface, DWORD shader) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + struct d3d8_vertex_shader *shader_impl; + + TRACE("iface %p, shader %#x.\n", iface, shader); + + if (VS_HIGHESTFIXEDFXF >= shader) + { + TRACE("Setting FVF, %#x\n", shader); + + wined3d_mutex_lock(); + wined3d_device_set_vertex_declaration(device->wined3d_device, + d3d8_device_get_fvf_declaration(device, shader)->wined3d_vertex_declaration); + wined3d_device_set_vertex_shader(device->wined3d_device, NULL); + wined3d_mutex_unlock(); + + return D3D_OK; + } + + TRACE("Setting shader\n"); + + wined3d_mutex_lock(); + if (!(shader_impl = d3d8_get_object(&device->handle_table, shader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_VS))) + { + WARN("Invalid handle (%#x) passed.\n", shader); + wined3d_mutex_unlock(); + + return D3DERR_INVALIDCALL; + } + + wined3d_device_set_vertex_declaration(device->wined3d_device, + shader_impl->vertex_declaration->wined3d_vertex_declaration); + wined3d_device_set_vertex_shader(device->wined3d_device, shader_impl->wined3d_shader); + wined3d_mutex_unlock(); + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_device_GetVertexShader(IDirect3DDevice8 *iface, DWORD *shader) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + struct wined3d_vertex_declaration *wined3d_declaration; + struct d3d8_vertex_declaration *d3d8_declaration; + + TRACE("iface %p, shader %p.\n", iface, shader); + + wined3d_mutex_lock(); + if ((wined3d_declaration = wined3d_device_get_vertex_declaration(device->wined3d_device))) + { + d3d8_declaration = wined3d_vertex_declaration_get_parent(wined3d_declaration); + *shader = d3d8_declaration->shader_handle; + } + else + { + *shader = 0; + } + wined3d_mutex_unlock(); + + TRACE("Returning %#x.\n", *shader); + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_device_DeleteVertexShader(IDirect3DDevice8 *iface, DWORD shader) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + struct d3d8_vertex_shader *shader_impl; + + TRACE("iface %p, shader %#x.\n", iface, shader); + + wined3d_mutex_lock(); + if (!(shader_impl = d3d8_free_handle(&device->handle_table, shader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_VS))) + { + WARN("Invalid handle (%#x) passed.\n", shader); + wined3d_mutex_unlock(); + + return D3DERR_INVALIDCALL; + } + + if (shader_impl->wined3d_shader + && wined3d_device_get_vertex_shader(device->wined3d_device) == shader_impl->wined3d_shader) + IDirect3DDevice8_SetVertexShader(iface, 0); + + wined3d_mutex_unlock(); + + d3d8_vertex_shader_destroy(shader_impl); + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_device_SetVertexShaderConstant(IDirect3DDevice8 *iface, + DWORD start_register, const void *data, DWORD count) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + HRESULT hr; + + TRACE("iface %p, start_register %u, data %p, count %u.\n", + iface, start_register, data, count); + + if (start_register + count > D3D8_MAX_VERTEX_SHADER_CONSTANTF) + { + WARN("Trying to access %u constants, but d3d8 only supports %u\n", + start_register + count, D3D8_MAX_VERTEX_SHADER_CONSTANTF); + return D3DERR_INVALIDCALL; + } + + wined3d_mutex_lock(); + hr = wined3d_device_set_vs_consts_f(device->wined3d_device, start_register, data, count); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_device_GetVertexShaderConstant(IDirect3DDevice8 *iface, + DWORD start_register, void *data, DWORD count) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + HRESULT hr; + + TRACE("iface %p, start_register %u, data %p, count %u.\n", + iface, start_register, data, count); + + if (start_register + count > D3D8_MAX_VERTEX_SHADER_CONSTANTF) + { + WARN("Trying to access %u constants, but d3d8 only supports %u\n", + start_register + count, D3D8_MAX_VERTEX_SHADER_CONSTANTF); + return D3DERR_INVALIDCALL; + } + + wined3d_mutex_lock(); + hr = wined3d_device_get_vs_consts_f(device->wined3d_device, start_register, data, count); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_device_GetVertexShaderDeclaration(IDirect3DDevice8 *iface, + DWORD shader, void *data, DWORD *data_size) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + struct d3d8_vertex_declaration *declaration; + struct d3d8_vertex_shader *shader_impl; + + TRACE("iface %p, shader %#x, data %p, data_size %p.\n", + iface, shader, data, data_size); + + wined3d_mutex_lock(); + shader_impl = d3d8_get_object(&device->handle_table, shader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_VS); + wined3d_mutex_unlock(); + + if (!shader_impl) + { + WARN("Invalid handle (%#x) passed.\n", shader); + return D3DERR_INVALIDCALL; + } + declaration = shader_impl->vertex_declaration; + + if (!data) + { + *data_size = declaration->elements_size; + return D3D_OK; + } + + /* MSDN claims that if *data_size is smaller than the required size + * we should write the required size and return D3DERR_MOREDATA. + * That's not actually true. */ + if (*data_size < declaration->elements_size) + return D3DERR_INVALIDCALL; + + memcpy(data, declaration->elements, declaration->elements_size); + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_device_GetVertexShaderFunction(IDirect3DDevice8 *iface, + DWORD shader, void *data, DWORD *data_size) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + struct d3d8_vertex_shader *shader_impl = NULL; + HRESULT hr; + + TRACE("iface %p, shader %#x, data %p, data_size %p.\n", + iface, shader, data, data_size); + + wined3d_mutex_lock(); + if (!(shader_impl = d3d8_get_object(&device->handle_table, shader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_VS))) + { + WARN("Invalid handle (%#x) passed.\n", shader); + wined3d_mutex_unlock(); + + return D3DERR_INVALIDCALL; + } + + if (!shader_impl->wined3d_shader) + { + wined3d_mutex_unlock(); + *data_size = 0; + return D3D_OK; + } + + hr = wined3d_shader_get_byte_code(shader_impl->wined3d_shader, data, data_size); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_device_SetIndices(IDirect3DDevice8 *iface, + IDirect3DIndexBuffer8 *buffer, UINT base_vertex_idx) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + struct d3d8_indexbuffer *ib = unsafe_impl_from_IDirect3DIndexBuffer8(buffer); + + TRACE("iface %p, buffer %p, base_vertex_idx %u.\n", iface, buffer, base_vertex_idx); + + /* WineD3D takes an INT(due to d3d9), but d3d8 uses UINTs. Do I have to add a check here that + * the UINT doesn't cause an overflow in the INT? It seems rather unlikely because such large + * vertex buffers can't be created to address them with an index that requires the 32nd bit + * (4 Byte minimum vertex size * 2^31-1 -> 8 gb buffer. The index sign would be the least + * problem) + */ + wined3d_mutex_lock(); + wined3d_device_set_base_vertex_index(device->wined3d_device, base_vertex_idx); + wined3d_device_set_index_buffer(device->wined3d_device, + ib ? ib->wined3d_buffer : NULL, + ib ? ib->format : WINED3DFMT_UNKNOWN); + wined3d_mutex_unlock(); + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_device_GetIndices(IDirect3DDevice8 *iface, + IDirect3DIndexBuffer8 **buffer, UINT *base_vertex_index) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + enum wined3d_format_id wined3d_format; + struct wined3d_buffer *wined3d_buffer; + struct d3d8_indexbuffer *buffer_impl; + + TRACE("iface %p, buffer %p, base_vertex_index %p.\n", iface, buffer, base_vertex_index); + + if (!buffer) + return D3DERR_INVALIDCALL; + + /* The case from UINT to INT is safe because d3d8 will never set negative values */ + wined3d_mutex_lock(); + *base_vertex_index = wined3d_device_get_base_vertex_index(device->wined3d_device); + if ((wined3d_buffer = wined3d_device_get_index_buffer(device->wined3d_device, &wined3d_format))) + { + buffer_impl = wined3d_buffer_get_parent(wined3d_buffer); + *buffer = &buffer_impl->IDirect3DIndexBuffer8_iface; + IDirect3DIndexBuffer8_AddRef(*buffer); + } + else + { + *buffer = NULL; + } + wined3d_mutex_unlock(); + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_device_CreatePixelShader(IDirect3DDevice8 *iface, + const DWORD *byte_code, DWORD *shader) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + struct d3d8_pixel_shader *object; + DWORD shader_handle; + DWORD handle; + HRESULT hr; + + TRACE("iface %p, byte_code %p, shader %p.\n", iface, byte_code, shader); + + if (!shader) + return D3DERR_INVALIDCALL; + + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); + if (!object) + return E_OUTOFMEMORY; + + wined3d_mutex_lock(); + handle = d3d8_allocate_handle(&device->handle_table, object, D3D8_HANDLE_PS); + wined3d_mutex_unlock(); + if (handle == D3D8_INVALID_HANDLE) + { + ERR("Failed to allocate pixel shader handle.\n"); + HeapFree(GetProcessHeap(), 0, object); + return E_OUTOFMEMORY; + } + + shader_handle = handle + VS_HIGHESTFIXEDFXF + 1; + + hr = d3d8_pixel_shader_init(object, device, byte_code, shader_handle); + if (FAILED(hr)) + { + WARN("Failed to initialize pixel shader, hr %#x.\n", hr); + wined3d_mutex_lock(); + d3d8_free_handle(&device->handle_table, handle, D3D8_HANDLE_PS); + wined3d_mutex_unlock(); + HeapFree(GetProcessHeap(), 0, object); + *shader = 0; + return hr; + } + + TRACE("Created pixel shader %p (handle %#x).\n", object, shader_handle); + *shader = shader_handle; + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_device_SetPixelShader(IDirect3DDevice8 *iface, DWORD shader) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + struct d3d8_pixel_shader *shader_impl; + + TRACE("iface %p, shader %#x.\n", iface, shader); + + wined3d_mutex_lock(); + + if (!shader) + { + wined3d_device_set_pixel_shader(device->wined3d_device, NULL); + wined3d_mutex_unlock(); + return D3D_OK; + } + + if (!(shader_impl = d3d8_get_object(&device->handle_table, shader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_PS))) + { + WARN("Invalid handle (%#x) passed.\n", shader); + wined3d_mutex_unlock(); + return D3DERR_INVALIDCALL; + } + + TRACE("Setting shader %p.\n", shader_impl); + wined3d_device_set_pixel_shader(device->wined3d_device, shader_impl->wined3d_shader); + wined3d_mutex_unlock(); + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_device_GetPixelShader(IDirect3DDevice8 *iface, DWORD *shader) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + struct wined3d_shader *object; + + TRACE("iface %p, shader %p.\n", iface, shader); + + if (!shader) + return D3DERR_INVALIDCALL; + + wined3d_mutex_lock(); + if ((object = wined3d_device_get_pixel_shader(device->wined3d_device))) + { + struct d3d8_pixel_shader *d3d8_shader; + d3d8_shader = wined3d_shader_get_parent(object); + *shader = d3d8_shader->handle; + } + else + { + *shader = 0; + } + wined3d_mutex_unlock(); + + TRACE("Returning %#x.\n", *shader); + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_device_DeletePixelShader(IDirect3DDevice8 *iface, DWORD shader) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + struct d3d8_pixel_shader *shader_impl; + + TRACE("iface %p, shader %#x.\n", iface, shader); + + wined3d_mutex_lock(); + + if (!(shader_impl = d3d8_free_handle(&device->handle_table, shader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_PS))) + { + WARN("Invalid handle (%#x) passed.\n", shader); + wined3d_mutex_unlock(); + return D3DERR_INVALIDCALL; + } + + if (wined3d_device_get_pixel_shader(device->wined3d_device) == shader_impl->wined3d_shader) + IDirect3DDevice8_SetPixelShader(iface, 0); + + wined3d_mutex_unlock(); + + d3d8_pixel_shader_destroy(shader_impl); + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_device_SetPixelShaderConstant(IDirect3DDevice8 *iface, + DWORD start_register, const void *data, DWORD count) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + HRESULT hr; + + TRACE("iface %p, start_register %u, data %p, count %u.\n", + iface, start_register, data, count); + + wined3d_mutex_lock(); + hr = wined3d_device_set_ps_consts_f(device->wined3d_device, start_register, data, count); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_device_GetPixelShaderConstant(IDirect3DDevice8 *iface, + DWORD start_register, void *data, DWORD count) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + HRESULT hr; + + TRACE("iface %p, start_register %u, data %p, count %u.\n", + iface, start_register, data, count); + + wined3d_mutex_lock(); + hr = wined3d_device_get_ps_consts_f(device->wined3d_device, start_register, data, count); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_device_GetPixelShaderFunction(IDirect3DDevice8 *iface, + DWORD shader, void *data, DWORD *data_size) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + struct d3d8_pixel_shader *shader_impl = NULL; + HRESULT hr; + + TRACE("iface %p, shader %#x, data %p, data_size %p.\n", + iface, shader, data, data_size); + + wined3d_mutex_lock(); + if (!(shader_impl = d3d8_get_object(&device->handle_table, shader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_PS))) + { + WARN("Invalid handle (%#x) passed.\n", shader); + wined3d_mutex_unlock(); + + return D3DERR_INVALIDCALL; + } + + hr = wined3d_shader_get_byte_code(shader_impl->wined3d_shader, data, data_size); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_device_DrawRectPatch(IDirect3DDevice8 *iface, UINT handle, + const float *segment_count, const D3DRECTPATCH_INFO *patch_info) +{ + FIXME("iface %p, handle %#x, segment_count %p, patch_info %p unimplemented.\n", + iface, handle, segment_count, patch_info); + return D3D_OK; +} + +static HRESULT WINAPI d3d8_device_DrawTriPatch(IDirect3DDevice8 *iface, UINT handle, + const float *segment_count, const D3DTRIPATCH_INFO *patch_info) +{ + FIXME("iface %p, handle %#x, segment_count %p, patch_info %p unimplemented.\n", + iface, handle, segment_count, patch_info); + return D3D_OK; +} + +static HRESULT WINAPI d3d8_device_DeletePatch(IDirect3DDevice8 *iface, UINT handle) +{ + FIXME("iface %p, handle %#x unimplemented.\n", iface, handle); + return D3DERR_INVALIDCALL; +} + +static HRESULT WINAPI d3d8_device_SetStreamSource(IDirect3DDevice8 *iface, + UINT stream_idx, IDirect3DVertexBuffer8 *buffer, UINT stride) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + struct d3d8_vertexbuffer *buffer_impl = unsafe_impl_from_IDirect3DVertexBuffer8(buffer); + HRESULT hr; + + TRACE("iface %p, stream_idx %u, buffer %p, stride %u.\n", + iface, stream_idx, buffer, stride); + + wined3d_mutex_lock(); + hr = wined3d_device_set_stream_source(device->wined3d_device, stream_idx, + buffer_impl ? buffer_impl->wined3d_buffer : NULL, 0, stride); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_device_GetStreamSource(IDirect3DDevice8 *iface, + UINT stream_idx, IDirect3DVertexBuffer8 **buffer, UINT *stride) +{ + struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + struct d3d8_vertexbuffer *buffer_impl; + struct wined3d_buffer *wined3d_buffer = NULL; + HRESULT hr; + + TRACE("iface %p, stream_idx %u, buffer %p, stride %p.\n", + iface, stream_idx, buffer, stride); + + if (!buffer) + return D3DERR_INVALIDCALL; + + wined3d_mutex_lock(); + hr = wined3d_device_get_stream_source(device->wined3d_device, stream_idx, &wined3d_buffer, 0, stride); + if (SUCCEEDED(hr) && wined3d_buffer) + { + buffer_impl = wined3d_buffer_get_parent(wined3d_buffer); + *buffer = &buffer_impl->IDirect3DVertexBuffer8_iface; + IDirect3DVertexBuffer8_AddRef(*buffer); + wined3d_buffer_decref(wined3d_buffer); + } + else + { + if (FAILED(hr)) + ERR("Failed to get wined3d stream source, hr %#x.\n", hr); + *buffer = NULL; + } + wined3d_mutex_unlock(); + + return hr; +} + +static const struct IDirect3DDevice8Vtbl d3d8_device_vtbl = +{ + d3d8_device_QueryInterface, + d3d8_device_AddRef, + d3d8_device_Release, + d3d8_device_TestCooperativeLevel, + d3d8_device_GetAvailableTextureMem, + d3d8_device_ResourceManagerDiscardBytes, + d3d8_device_GetDirect3D, + d3d8_device_GetDeviceCaps, + d3d8_device_GetDisplayMode, + d3d8_device_GetCreationParameters, + d3d8_device_SetCursorProperties, + d3d8_device_SetCursorPosition, + d3d8_device_ShowCursor, + d3d8_device_CreateAdditionalSwapChain, + d3d8_device_Reset, + d3d8_device_Present, + d3d8_device_GetBackBuffer, + d3d8_device_GetRasterStatus, + d3d8_device_SetGammaRamp, + d3d8_device_GetGammaRamp, + d3d8_device_CreateTexture, + d3d8_device_CreateVolumeTexture, + d3d8_device_CreateCubeTexture, + d3d8_device_CreateVertexBuffer, + d3d8_device_CreateIndexBuffer, + d3d8_device_CreateRenderTarget, + d3d8_device_CreateDepthStencilSurface, + d3d8_device_CreateImageSurface, + d3d8_device_CopyRects, + d3d8_device_UpdateTexture, + d3d8_device_GetFrontBuffer, + d3d8_device_SetRenderTarget, + d3d8_device_GetRenderTarget, + d3d8_device_GetDepthStencilSurface, + d3d8_device_BeginScene, + d3d8_device_EndScene, + d3d8_device_Clear, + d3d8_device_SetTransform, + d3d8_device_GetTransform, + d3d8_device_MultiplyTransform, + d3d8_device_SetViewport, + d3d8_device_GetViewport, + d3d8_device_SetMaterial, + d3d8_device_GetMaterial, + d3d8_device_SetLight, + d3d8_device_GetLight, + d3d8_device_LightEnable, + d3d8_device_GetLightEnable, + d3d8_device_SetClipPlane, + d3d8_device_GetClipPlane, + d3d8_device_SetRenderState, + d3d8_device_GetRenderState, + d3d8_device_BeginStateBlock, + d3d8_device_EndStateBlock, + d3d8_device_ApplyStateBlock, + d3d8_device_CaptureStateBlock, + d3d8_device_DeleteStateBlock, + d3d8_device_CreateStateBlock, + d3d8_device_SetClipStatus, + d3d8_device_GetClipStatus, + d3d8_device_GetTexture, + d3d8_device_SetTexture, + d3d8_device_GetTextureStageState, + d3d8_device_SetTextureStageState, + d3d8_device_ValidateDevice, + d3d8_device_GetInfo, + d3d8_device_SetPaletteEntries, + d3d8_device_GetPaletteEntries, + d3d8_device_SetCurrentTexturePalette, + d3d8_device_GetCurrentTexturePalette, + d3d8_device_DrawPrimitive, + d3d8_device_DrawIndexedPrimitive, + d3d8_device_DrawPrimitiveUP, + d3d8_device_DrawIndexedPrimitiveUP, + d3d8_device_ProcessVertices, + d3d8_device_CreateVertexShader, + d3d8_device_SetVertexShader, + d3d8_device_GetVertexShader, + d3d8_device_DeleteVertexShader, + d3d8_device_SetVertexShaderConstant, + d3d8_device_GetVertexShaderConstant, + d3d8_device_GetVertexShaderDeclaration, + d3d8_device_GetVertexShaderFunction, + d3d8_device_SetStreamSource, + d3d8_device_GetStreamSource, + d3d8_device_SetIndices, + d3d8_device_GetIndices, + d3d8_device_CreatePixelShader, + d3d8_device_SetPixelShader, + d3d8_device_GetPixelShader, + d3d8_device_DeletePixelShader, + d3d8_device_SetPixelShaderConstant, + d3d8_device_GetPixelShaderConstant, + d3d8_device_GetPixelShaderFunction, + d3d8_device_DrawRectPatch, + d3d8_device_DrawTriPatch, + d3d8_device_DeletePatch, +}; + +static inline struct d3d8_device *device_from_device_parent(struct wined3d_device_parent *device_parent) +{ + return CONTAINING_RECORD(device_parent, struct d3d8_device, device_parent); +} + +static void CDECL device_parent_wined3d_device_created(struct wined3d_device_parent *device_parent, + struct wined3d_device *device) +{ + TRACE("device_parent %p, device %p\n", device_parent, device); +} + +static void CDECL device_parent_mode_changed(struct wined3d_device_parent *device_parent) +{ + TRACE("device_parent %p.\n", device_parent); +} + +static HRESULT CDECL device_parent_create_texture_surface(struct wined3d_device_parent *device_parent, + void *container_parent, const struct wined3d_resource_desc *desc, UINT sub_resource_idx, + DWORD flags, struct wined3d_surface **surface) +{ + struct d3d8_device *device = device_from_device_parent(device_parent); + struct d3d8_surface *d3d_surface; + HRESULT hr; + + TRACE("device_parent %p, container_parent %p, desc %p, sub_resource_idx %u, flags %#x, surface %p.\n", + device_parent, container_parent, desc, sub_resource_idx, flags, surface); + + if (FAILED(hr = d3d8_device_create_surface(device, desc->width, desc->height, + d3dformat_from_wined3dformat(desc->format), flags, (IDirect3DSurface8 **)&d3d_surface, + desc->usage, desc->pool, desc->multisample_type, desc->multisample_quality))) + { + WARN("Failed to create surface, hr %#x.\n", hr); + return hr; + } + + *surface = d3d_surface->wined3d_surface; + wined3d_surface_incref(*surface); + + d3d_surface->container = container_parent; + IDirect3DDevice8_Release(d3d_surface->parent_device); + d3d_surface->parent_device = NULL; + + IDirect3DSurface8_Release(&d3d_surface->IDirect3DSurface8_iface); + d3d_surface->forwardReference = container_parent; + + return hr; +} + +static HRESULT CDECL device_parent_create_swapchain_surface(struct wined3d_device_parent *device_parent, + void *container_parent, const struct wined3d_resource_desc *desc, struct wined3d_surface **surface) +{ + struct d3d8_device *device = device_from_device_parent(device_parent); + struct wined3d_resource_desc texture_desc; + struct d3d8_surface *d3d_surface; + struct wined3d_texture *texture; + HRESULT hr; + + TRACE("device_parent %p, container_parent %p, desc %p, surface %p.\n", + device_parent, container_parent, desc, surface); + + texture_desc = *desc; + texture_desc.resource_type = WINED3D_RTYPE_TEXTURE; + if (FAILED(hr = wined3d_texture_create_2d(device->wined3d_device, &texture_desc, 1, + WINED3D_SURFACE_MAPPABLE, &device->IDirect3DDevice8_iface, &d3d8_null_wined3d_parent_ops, &texture))) + { + WARN("Failed to create texture, hr %#x.\n", hr); + return hr; + } + + *surface = wined3d_surface_from_resource(wined3d_texture_get_sub_resource(texture, 0)); + wined3d_surface_incref(*surface); + wined3d_texture_decref(texture); + + d3d_surface = wined3d_surface_get_parent(*surface); + d3d_surface->forwardReference = NULL; + d3d_surface->parent_device = &device->IDirect3DDevice8_iface; + + return hr; +} + +static HRESULT CDECL device_parent_create_volume(struct wined3d_device_parent *device_parent, + void *container_parent, UINT width, UINT height, UINT depth, enum wined3d_format_id format, + enum wined3d_pool pool, DWORD usage, struct wined3d_volume **volume) +{ + struct d3d8_device *device = device_from_device_parent(device_parent); + struct d3d8_volume *object; + HRESULT hr; + + TRACE("device_parent %p, container_parent %p, width %u, height %u, depth %u, " + "format %#x, pool %#x, usage %#x, volume %p.\n", + device_parent, container_parent, width, height, depth, + format, pool, usage, volume); + + /* Allocate the storage for the device */ + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); + if (!object) + { + FIXME("Allocation of memory failed\n"); + *volume = NULL; + return D3DERR_OUTOFVIDEOMEMORY; + } + + hr = volume_init(object, device, width, height, depth, usage, format, pool); + if (FAILED(hr)) + { + WARN("Failed to initialize volume, hr %#x.\n", hr); + HeapFree(GetProcessHeap(), 0, object); + return hr; + } + + *volume = object->wined3d_volume; + wined3d_volume_incref(*volume); + IDirect3DVolume8_Release(&object->IDirect3DVolume8_iface); + + object->container = container_parent; + object->forwardReference = container_parent; + + TRACE("Created volume %p.\n", object); + + return hr; +} + +static HRESULT CDECL device_parent_create_swapchain(struct wined3d_device_parent *device_parent, + struct wined3d_swapchain_desc *desc, struct wined3d_swapchain **swapchain) +{ + struct d3d8_device *device = device_from_device_parent(device_parent); + struct d3d8_swapchain *d3d_swapchain; + HRESULT hr; + + TRACE("device_parent %p, desc %p, swapchain %p.\n", device_parent, desc, swapchain); + + if (FAILED(hr = d3d8_swapchain_create(device, desc, &d3d_swapchain))) + { + WARN("Failed to create swapchain, hr %#x.\n", hr); + *swapchain = NULL; + return hr; + } + + *swapchain = d3d_swapchain->wined3d_swapchain; + wined3d_swapchain_incref(*swapchain); + IDirect3DSwapChain8_Release(&d3d_swapchain->IDirect3DSwapChain8_iface); + + return hr; +} + +static const struct wined3d_device_parent_ops d3d8_wined3d_device_parent_ops = +{ + device_parent_wined3d_device_created, + device_parent_mode_changed, + device_parent_create_swapchain_surface, + device_parent_create_texture_surface, + device_parent_create_volume, + device_parent_create_swapchain, +}; + +static void setup_fpu(void) +{ +#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) + WORD cw; + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xf3f) | 0x3f; + __asm__ volatile ("fldcw %0" : : "m" (cw)); +#elif defined(__i386__) && defined(_MSC_VER) + WORD cw; + __asm fnstcw cw; + cw = (cw & ~0xf3f) | 0x3f; + __asm fldcw cw; +#elif defined(RT_ARCH_AMD64) + unsigned int currentControl = 0; + _controlfp_s(¤tControl, 0x3f, 0xf3f); +#else + FIXME("FPU setup not implemented for this platform.\n"); +#endif +} + +HRESULT device_init(struct d3d8_device *device, struct d3d8 *parent, struct wined3d *wined3d, UINT adapter, + D3DDEVTYPE device_type, HWND focus_window, DWORD flags, D3DPRESENT_PARAMETERS *parameters) +{ + struct wined3d_swapchain_desc swapchain_desc; + HRESULT hr; + + device->IDirect3DDevice8_iface.lpVtbl = &d3d8_device_vtbl; + device->device_parent.ops = &d3d8_wined3d_device_parent_ops; + device->ref = 1; + device->handle_table.entries = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + D3D8_INITIAL_HANDLE_TABLE_SIZE * sizeof(*device->handle_table.entries)); + if (!device->handle_table.entries) + { + ERR("Failed to allocate handle table memory.\n"); + return E_OUTOFMEMORY; + } + device->handle_table.table_size = D3D8_INITIAL_HANDLE_TABLE_SIZE; + + if (!(flags & D3DCREATE_FPU_PRESERVE)) setup_fpu(); + + wined3d_mutex_lock(); + hr = wined3d_device_create(wined3d, adapter, device_type, focus_window, flags, 4, + &device->device_parent, &device->wined3d_device); + if (FAILED(hr)) + { + WARN("Failed to create wined3d device, hr %#x.\n", hr); + wined3d_mutex_unlock(); + HeapFree(GetProcessHeap(), 0, device->handle_table.entries); + return hr; + } + + if (!parameters->Windowed) + { + HWND device_window = parameters->hDeviceWindow; + + if (!focus_window) + focus_window = device_window; + if (FAILED(hr = wined3d_device_acquire_focus_window(device->wined3d_device, focus_window))) + { + ERR("Failed to acquire focus window, hr %#x.\n", hr); + wined3d_device_decref(device->wined3d_device); + wined3d_mutex_unlock(); + HeapFree(GetProcessHeap(), 0, device->handle_table.entries); + return hr; + } + + if (!device_window) + device_window = focus_window; + wined3d_device_setup_fullscreen_window(device->wined3d_device, device_window, + parameters->BackBufferWidth, + parameters->BackBufferHeight); + } + + if (flags & D3DCREATE_MULTITHREADED) + wined3d_device_set_multithreaded(device->wined3d_device); + + wined3d_swapchain_desc_from_present_parameters(&swapchain_desc, parameters); + + hr = wined3d_device_init_3d(device->wined3d_device, &swapchain_desc); + if (FAILED(hr)) + { + WARN("Failed to initialize 3D, hr %#x.\n", hr); + wined3d_device_release_focus_window(device->wined3d_device); + wined3d_device_decref(device->wined3d_device); + wined3d_mutex_unlock(); + HeapFree(GetProcessHeap(), 0, device->handle_table.entries); + return hr; + } + + wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_POINTSIZE_MIN, 0); + wined3d_mutex_unlock(); + + present_parameters_from_wined3d_swapchain_desc(parameters, &swapchain_desc); + + device->declArraySize = 16; + device->decls = HeapAlloc(GetProcessHeap(), 0, device->declArraySize * sizeof(*device->decls)); + if (!device->decls) + { + ERR("Failed to allocate FVF vertex declaration map memory.\n"); + hr = E_OUTOFMEMORY; + goto err; + } + + device->d3d_parent = &parent->IDirect3D8_iface; + IDirect3D8_AddRef(device->d3d_parent); + + return D3D_OK; + +err: + wined3d_mutex_lock(); + wined3d_device_uninit_3d(device->wined3d_device); + wined3d_device_release_focus_window(device->wined3d_device); + wined3d_device_decref(device->wined3d_device); + wined3d_mutex_unlock(); + HeapFree(GetProcessHeap(), 0, device->handle_table.entries); + return hr; +} diff --git a/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/directx.c b/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/directx.c new file mode 100644 index 00000000..4e3175e4 --- /dev/null +++ b/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/directx.c @@ -0,0 +1,428 @@ +/* + * IDirect3D8 implementation + * + * Copyright 2002-2004 Jason Edmeades + * Copyright 2003-2004 Raphael Junqueira + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* + * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice + * other than GPL or LGPL is available it will apply instead, Oracle elects to use only + * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where + * a choice of LGPL license versions is made available with the language indicating + * that LGPLv2 or any later version may be used, or where a choice of which version + * of the LGPL is applied is otherwise unspecified. + */ + +#include "config.h" + +#include <stdarg.h> + +#define NONAMELESSUNION +#define NONAMELESSSTRUCT +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winuser.h" +#include "wine/debug.h" +#include "wine/unicode.h" + +#include "d3d8_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(d3d8); + +static inline struct d3d8 *impl_from_IDirect3D8(IDirect3D8 *iface) +{ + return CONTAINING_RECORD(iface, struct d3d8, IDirect3D8_iface); +} + +static HRESULT WINAPI d3d8_QueryInterface(IDirect3D8 *iface, REFIID riid, void **out) +{ + TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out); + + if (IsEqualGUID(riid, &IID_IDirect3D8) + || IsEqualGUID(riid, &IID_IUnknown)) + { + IDirect3D8_AddRef(iface); + *out = iface; + return S_OK; + } + + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid)); + + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI d3d8_AddRef(IDirect3D8 *iface) +{ + struct d3d8 *d3d8 = impl_from_IDirect3D8(iface); + ULONG refcount = InterlockedIncrement(&d3d8->refcount); + + TRACE("%p increasing refcount to %u.\n", iface, refcount); + + return refcount; +} + +static ULONG WINAPI d3d8_Release(IDirect3D8 *iface) +{ + struct d3d8 *d3d8 = impl_from_IDirect3D8(iface); + ULONG refcount = InterlockedDecrement(&d3d8->refcount); + + TRACE("%p decreasing refcount to %u.\n", iface, refcount); + + if (!refcount) + { + wined3d_mutex_lock(); + wined3d_decref(d3d8->wined3d); + wined3d_mutex_unlock(); + + HeapFree(GetProcessHeap(), 0, d3d8); + } + + return refcount; +} + +static HRESULT WINAPI d3d8_RegisterSoftwareDevice(IDirect3D8 *iface, void *init_function) +{ + struct d3d8 *d3d8 = impl_from_IDirect3D8(iface); + HRESULT hr; + + TRACE("iface %p, init_function %p.\n", iface, init_function); + + wined3d_mutex_lock(); + hr = wined3d_register_software_device(d3d8->wined3d, init_function); + wined3d_mutex_unlock(); + + return hr; +} + +static UINT WINAPI d3d8_GetAdapterCount(IDirect3D8 *iface) +{ + struct d3d8 *d3d8 = impl_from_IDirect3D8(iface); + HRESULT hr; + + TRACE("iface %p.\n", iface); + + wined3d_mutex_lock(); + hr = wined3d_get_adapter_count(d3d8->wined3d); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_GetAdapterIdentifier(IDirect3D8 *iface, UINT adapter, + DWORD flags, D3DADAPTER_IDENTIFIER8 *identifier) +{ + struct d3d8 *d3d8 = impl_from_IDirect3D8(iface); + struct wined3d_adapter_identifier adapter_id; + HRESULT hr; + + TRACE("iface %p, adapter %u, flags %#x, identifier %p.\n", + iface, adapter, flags, identifier); + + adapter_id.driver = identifier->Driver; + adapter_id.driver_size = sizeof(identifier->Driver); + adapter_id.description = identifier->Description; + adapter_id.description_size = sizeof(identifier->Description); + adapter_id.device_name = NULL; /* d3d9 only */ + adapter_id.device_name_size = 0; /* d3d9 only */ + + wined3d_mutex_lock(); + hr = wined3d_get_adapter_identifier(d3d8->wined3d, adapter, flags, &adapter_id); + wined3d_mutex_unlock(); + + identifier->DriverVersion = adapter_id.driver_version; + identifier->VendorId = adapter_id.vendor_id; + identifier->DeviceId = adapter_id.device_id; + identifier->SubSysId = adapter_id.subsystem_id; + identifier->Revision = adapter_id.revision; + memcpy(&identifier->DeviceIdentifier, &adapter_id.device_identifier, sizeof(identifier->DeviceIdentifier)); + identifier->WHQLLevel = adapter_id.whql_level; + + return hr; +} + +static UINT WINAPI d3d8_GetAdapterModeCount(IDirect3D8 *iface, UINT adapter) +{ + struct d3d8 *d3d8 = impl_from_IDirect3D8(iface); + HRESULT hr; + + TRACE("iface %p, adapter %u.\n", iface, adapter); + + wined3d_mutex_lock(); + hr = wined3d_get_adapter_mode_count(d3d8->wined3d, adapter, + WINED3DFMT_UNKNOWN, WINED3D_SCANLINE_ORDERING_UNKNOWN); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_EnumAdapterModes(IDirect3D8 *iface, UINT adapter, UINT mode_idx, D3DDISPLAYMODE *mode) +{ + struct d3d8 *d3d8 = impl_from_IDirect3D8(iface); + struct wined3d_display_mode wined3d_mode; + HRESULT hr; + + TRACE("iface %p, adapter %u, mode_idx %u, mode %p.\n", + iface, adapter, mode_idx, mode); + + wined3d_mutex_lock(); + hr = wined3d_enum_adapter_modes(d3d8->wined3d, adapter, WINED3DFMT_UNKNOWN, + WINED3D_SCANLINE_ORDERING_UNKNOWN, mode_idx, &wined3d_mode); + wined3d_mutex_unlock(); + + if (SUCCEEDED(hr)) + { + mode->Width = wined3d_mode.width; + mode->Height = wined3d_mode.height; + mode->RefreshRate = wined3d_mode.refresh_rate; + mode->Format = d3dformat_from_wined3dformat(wined3d_mode.format_id); + } + + return hr; +} + +static HRESULT WINAPI d3d8_GetAdapterDisplayMode(IDirect3D8 *iface, UINT adapter, D3DDISPLAYMODE *mode) +{ + struct d3d8 *d3d8 = impl_from_IDirect3D8(iface); + struct wined3d_display_mode wined3d_mode; + HRESULT hr; + + TRACE("iface %p, adapter %u, mode %p.\n", + iface, adapter, mode); + + wined3d_mutex_lock(); + hr = wined3d_get_adapter_display_mode(d3d8->wined3d, adapter, &wined3d_mode, NULL); + wined3d_mutex_unlock(); + + if (SUCCEEDED(hr)) + { + mode->Width = wined3d_mode.width; + mode->Height = wined3d_mode.height; + mode->RefreshRate = wined3d_mode.refresh_rate; + mode->Format = d3dformat_from_wined3dformat(wined3d_mode.format_id); + } + + return hr; +} + +static HRESULT WINAPI d3d8_CheckDeviceType(IDirect3D8 *iface, UINT adapter, D3DDEVTYPE device_type, + D3DFORMAT display_format, D3DFORMAT backbuffer_format, BOOL windowed) +{ + struct d3d8 *d3d8 = impl_from_IDirect3D8(iface); + HRESULT hr; + + TRACE("iface %p, adapter %u, device_type %#x, display_format %#x, backbuffer_format %#x, windowed %#x.\n", + iface, adapter, device_type, display_format, backbuffer_format, windowed); + + wined3d_mutex_lock(); + hr = wined3d_check_device_type(d3d8->wined3d, adapter, device_type, wined3dformat_from_d3dformat(display_format), + wined3dformat_from_d3dformat(backbuffer_format), windowed); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_CheckDeviceFormat(IDirect3D8 *iface, UINT adapter, D3DDEVTYPE device_type, + D3DFORMAT adapter_format, DWORD usage, D3DRESOURCETYPE resource_type, D3DFORMAT format) +{ + struct d3d8 *d3d8 = impl_from_IDirect3D8(iface); + enum wined3d_resource_type wined3d_rtype; + HRESULT hr; + + TRACE("iface %p, adapter %u, device_type %#x, adapter_format %#x, usage %#x, resource_type %#x, format %#x.\n", + iface, adapter, device_type, adapter_format, usage, resource_type, format); + + switch (resource_type) + { + case D3DRTYPE_VERTEXBUFFER: + case D3DRTYPE_INDEXBUFFER: + wined3d_rtype = WINED3D_RTYPE_BUFFER; + break; + + default: + wined3d_rtype = resource_type; + break; + } + + wined3d_mutex_lock(); + hr = wined3d_check_device_format(d3d8->wined3d, adapter, device_type, wined3dformat_from_d3dformat(adapter_format), + usage, wined3d_rtype, wined3dformat_from_d3dformat(format)); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_CheckDeviceMultiSampleType(IDirect3D8 *iface, UINT adapter, D3DDEVTYPE device_type, + D3DFORMAT format, BOOL windowed, D3DMULTISAMPLE_TYPE multisample_type) +{ + struct d3d8 *d3d8 = impl_from_IDirect3D8(iface); + HRESULT hr; + + TRACE("iface %p, adapter %u, device_type %#x, format %#x, windowed %#x, multisample_type %#x.\n", + iface, adapter, device_type, format, windowed, multisample_type); + + wined3d_mutex_lock(); + hr = wined3d_check_device_multisample_type(d3d8->wined3d, adapter, device_type, + wined3dformat_from_d3dformat(format), windowed, + (enum wined3d_multisample_type)multisample_type, NULL); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_CheckDepthStencilMatch(IDirect3D8 *iface, UINT adapter, D3DDEVTYPE device_type, + D3DFORMAT adapter_format, D3DFORMAT rt_format, D3DFORMAT ds_format) +{ + struct d3d8 *d3d8 = impl_from_IDirect3D8(iface); + HRESULT hr; + + TRACE("iface %p, adapter %u, device_type %#x, adapter_format %#x, rt_format %#x, ds_format %#x.\n", + iface, adapter, device_type, adapter_format, rt_format, ds_format); + + wined3d_mutex_lock(); + hr = wined3d_check_depth_stencil_match(d3d8->wined3d, adapter, device_type, + wined3dformat_from_d3dformat(adapter_format), wined3dformat_from_d3dformat(rt_format), + wined3dformat_from_d3dformat(ds_format)); + wined3d_mutex_unlock(); + + return hr; +} + +void fixup_caps(WINED3DCAPS *caps) +{ + /* D3D8 doesn't support SM 2.0 or higher, so clamp to 1.x */ + if (caps->PixelShaderVersion) + caps->PixelShaderVersion = D3DPS_VERSION(1,4); + else + caps->PixelShaderVersion = D3DPS_VERSION(0,0); + if (caps->VertexShaderVersion) + caps->VertexShaderVersion = D3DVS_VERSION(1,1); + else + caps->VertexShaderVersion = D3DVS_VERSION(0,0); + caps->MaxVertexShaderConst = min(D3D8_MAX_VERTEX_SHADER_CONSTANTF, caps->MaxVertexShaderConst); + + caps->StencilCaps &= ~WINED3DSTENCILCAPS_TWOSIDED; +} + +static HRESULT WINAPI d3d8_GetDeviceCaps(IDirect3D8 *iface, UINT adapter, D3DDEVTYPE device_type, D3DCAPS8 *caps) +{ + struct d3d8 *d3d8 = impl_from_IDirect3D8(iface); + WINED3DCAPS *wined3d_caps; + HRESULT hr; + + TRACE("iface %p, adapter %u, device_type %#x, caps %p.\n", iface, adapter, device_type, caps); + + if (!caps) + return D3DERR_INVALIDCALL; + + if (!(wined3d_caps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*wined3d_caps)))) + return D3DERR_INVALIDCALL; + + wined3d_mutex_lock(); + hr = wined3d_get_device_caps(d3d8->wined3d, adapter, device_type, wined3d_caps); + wined3d_mutex_unlock(); + + fixup_caps(wined3d_caps); + WINECAPSTOD3D8CAPS(caps, wined3d_caps) + HeapFree(GetProcessHeap(), 0, wined3d_caps); + + return hr; +} + +static HMONITOR WINAPI d3d8_GetAdapterMonitor(IDirect3D8 *iface, UINT adapter) +{ + struct d3d8 *d3d8 = impl_from_IDirect3D8(iface); + HMONITOR ret; + + TRACE("iface %p, adapter %u.\n", iface, adapter); + + wined3d_mutex_lock(); + ret = wined3d_get_adapter_monitor(d3d8->wined3d, adapter); + wined3d_mutex_unlock(); + + return ret; +} + +static HRESULT WINAPI d3d8_CreateDevice(IDirect3D8 *iface, UINT adapter, + D3DDEVTYPE device_type, HWND focus_window, DWORD flags, D3DPRESENT_PARAMETERS *parameters, + IDirect3DDevice8 **device) +{ + struct d3d8 *d3d8 = impl_from_IDirect3D8(iface); + struct d3d8_device *object; + HRESULT hr; + + TRACE("iface %p, adapter %u, device_type %#x, focus_window %p, flags %#x, parameters %p, device %p.\n", + iface, adapter, device_type, focus_window, flags, parameters, device); + + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); + if (!object) + return E_OUTOFMEMORY; + + hr = device_init(object, d3d8, d3d8->wined3d, adapter, device_type, focus_window, flags, parameters); + if (FAILED(hr)) + { + WARN("Failed to initialize device, hr %#x.\n", hr); + HeapFree(GetProcessHeap(), 0, object); + return hr; + } + + TRACE("Created device %p.\n", object); + *device = &object->IDirect3DDevice8_iface; + + return D3D_OK; +} + +static const struct IDirect3D8Vtbl d3d8_vtbl = +{ + /* IUnknown */ + d3d8_QueryInterface, + d3d8_AddRef, + d3d8_Release, + /* IDirect3D8 */ + d3d8_RegisterSoftwareDevice, + d3d8_GetAdapterCount, + d3d8_GetAdapterIdentifier, + d3d8_GetAdapterModeCount, + d3d8_EnumAdapterModes, + d3d8_GetAdapterDisplayMode, + d3d8_CheckDeviceType, + d3d8_CheckDeviceFormat, + d3d8_CheckDeviceMultiSampleType, + d3d8_CheckDepthStencilMatch, + d3d8_GetDeviceCaps, + d3d8_GetAdapterMonitor, + d3d8_CreateDevice, +}; + +BOOL d3d8_init(struct d3d8 *d3d8) +{ + DWORD flags = WINED3D_LEGACY_DEPTH_BIAS | WINED3D_VIDMEM_ACCOUNTING; + + d3d8->IDirect3D8_iface.lpVtbl = &d3d8_vtbl; + d3d8->refcount = 1; + + wined3d_mutex_lock(); + d3d8->wined3d = wined3d_create(8, flags); + wined3d_mutex_unlock(); + if (!d3d8->wined3d) + return FALSE; + + return TRUE; +} diff --git a/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/shader.c b/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/shader.c new file mode 100644 index 00000000..e9c5340b --- /dev/null +++ b/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/shader.c @@ -0,0 +1,179 @@ +/* + * Copyright 2002-2003 Jason Edmeades + * Raphael Junqueira + * + * 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 + */ + +/* + * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice + * other than GPL or LGPL is available it will apply instead, Oracle elects to use only + * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where + * a choice of LGPL license versions is made available with the language indicating + * that LGPLv2 or any later version may be used, or where a choice of which version + * of the LGPL is applied is otherwise unspecified. + */ + +#include "config.h" +#include "d3d8_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(d3d8); + +static void STDMETHODCALLTYPE d3d8_vertexshader_wined3d_object_destroyed(void *parent) +{ + struct d3d8_vertex_shader *shader = parent; + d3d8_vertex_declaration_destroy(shader->vertex_declaration); + HeapFree(GetProcessHeap(), 0, shader); +} + +void d3d8_vertex_shader_destroy(struct d3d8_vertex_shader *shader) +{ + TRACE("shader %p.\n", shader); + + if (shader->wined3d_shader) + { + wined3d_mutex_lock(); + wined3d_shader_decref(shader->wined3d_shader); + wined3d_mutex_unlock(); + } + else + { + d3d8_vertexshader_wined3d_object_destroyed(shader); + } +} + +static const struct wined3d_parent_ops d3d8_vertexshader_wined3d_parent_ops = +{ + d3d8_vertexshader_wined3d_object_destroyed, +}; + +static HRESULT d3d8_vertexshader_create_vertexdeclaration(struct d3d8_device *device, + const DWORD *declaration, DWORD shader_handle, struct d3d8_vertex_declaration **decl_ptr) +{ + struct d3d8_vertex_declaration *object; + HRESULT hr; + + TRACE("device %p, declaration %p, shader_handle %#x, decl_ptr %p.\n", + device, declaration, shader_handle, decl_ptr); + + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); + if (!object) + return E_OUTOFMEMORY; + + hr = d3d8_vertex_declaration_init(object, device, declaration, shader_handle); + if (FAILED(hr)) + { + WARN("Failed to initialize vertex declaration, hr %#x.\n", hr); + HeapFree(GetProcessHeap(), 0, object); + return hr; + } + + TRACE("Created vertex declaration %p.\n", object); + *decl_ptr = object; + + return D3D_OK; +} + +HRESULT d3d8_vertex_shader_init(struct d3d8_vertex_shader *shader, struct d3d8_device *device, + const DWORD *declaration, const DWORD *byte_code, DWORD shader_handle, DWORD usage) +{ + const DWORD *token = declaration; + HRESULT hr; + + /* Test if the vertex declaration is valid. */ + while (D3DVSD_END() != *token) + { + D3DVSD_TOKENTYPE token_type = ((*token & D3DVSD_TOKENTYPEMASK) >> D3DVSD_TOKENTYPESHIFT); + + if (token_type == D3DVSD_TOKEN_STREAMDATA && !(token_type & 0x10000000)) + { + DWORD type = ((*token & D3DVSD_DATATYPEMASK) >> D3DVSD_DATATYPESHIFT); + DWORD reg = ((*token & D3DVSD_VERTEXREGMASK) >> D3DVSD_VERTEXREGSHIFT); + + if (reg == D3DVSDE_NORMAL && type != D3DVSDT_FLOAT3 && !byte_code) + { + WARN("Attempt to use a non-FLOAT3 normal with the fixed function function\n"); + return D3DERR_INVALIDCALL; + } + } + token += parse_token(token); + } + + hr = d3d8_vertexshader_create_vertexdeclaration(device, declaration, shader_handle, &shader->vertex_declaration); + if (FAILED(hr)) + { + WARN("Failed to create vertex declaration, hr %#x.\n", hr); + return hr; + } + + if (byte_code) + { + if (usage) FIXME("Usage %#x not implemented.\n", usage); + + wined3d_mutex_lock(); + hr = wined3d_shader_create_vs(device->wined3d_device, byte_code, NULL /* output signature */, + shader, &d3d8_vertexshader_wined3d_parent_ops, &shader->wined3d_shader, 1); + wined3d_mutex_unlock(); + if (FAILED(hr)) + { + WARN("Failed to create wined3d vertex shader, hr %#x.\n", hr); + d3d8_vertex_declaration_destroy(shader->vertex_declaration); + return hr; + } + + load_local_constants(declaration, shader->wined3d_shader); + } + + return D3D_OK; +} + +static void STDMETHODCALLTYPE d3d8_pixelshader_wined3d_object_destroyed(void *parent) +{ + HeapFree(GetProcessHeap(), 0, parent); +} + +void d3d8_pixel_shader_destroy(struct d3d8_pixel_shader *shader) +{ + TRACE("shader %p.\n", shader); + + wined3d_mutex_lock(); + wined3d_shader_decref(shader->wined3d_shader); + wined3d_mutex_unlock(); +} + +static const struct wined3d_parent_ops d3d8_pixelshader_wined3d_parent_ops = +{ + d3d8_pixelshader_wined3d_object_destroyed, +}; + +HRESULT d3d8_pixel_shader_init(struct d3d8_pixel_shader *shader, struct d3d8_device *device, + const DWORD *byte_code, DWORD shader_handle) +{ + HRESULT hr; + + shader->handle = shader_handle; + + wined3d_mutex_lock(); + hr = wined3d_shader_create_ps(device->wined3d_device, byte_code, NULL, shader, + &d3d8_pixelshader_wined3d_parent_ops, &shader->wined3d_shader, 1); + wined3d_mutex_unlock(); + if (FAILED(hr)) + { + WARN("Failed to create wined3d pixel shader, hr %#x.\n", hr); + return hr; + } + + return D3D_OK; +} diff --git a/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/surface.c b/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/surface.c new file mode 100644 index 00000000..1a36e04e --- /dev/null +++ b/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/surface.c @@ -0,0 +1,377 @@ +/* + * IDirect3DSurface8 implementation + * + * Copyright 2005 Oliver Stieber + * + * 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 + */ + +/* + * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice + * other than GPL or LGPL is available it will apply instead, Oracle elects to use only + * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where + * a choice of LGPL license versions is made available with the language indicating + * that LGPLv2 or any later version may be used, or where a choice of which version + * of the LGPL is applied is otherwise unspecified. + */ + +#include "config.h" +#include "d3d8_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(d3d8); + +static inline struct d3d8_surface *impl_from_IDirect3DSurface8(IDirect3DSurface8 *iface) +{ + return CONTAINING_RECORD(iface, struct d3d8_surface, IDirect3DSurface8_iface); +} + +static HRESULT WINAPI d3d8_surface_QueryInterface(IDirect3DSurface8 *iface, REFIID riid, void **out) +{ + TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), out); + + if (IsEqualGUID(riid, &IID_IDirect3DSurface8) + || IsEqualGUID(riid, &IID_IDirect3DResource8) + || IsEqualGUID(riid, &IID_IUnknown)) + { + IDirect3DSurface8_AddRef(iface); + *out = iface; + return S_OK; + } + + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid)); + + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI d3d8_surface_AddRef(IDirect3DSurface8 *iface) +{ + struct d3d8_surface *surface = impl_from_IDirect3DSurface8(iface); + + TRACE("iface %p.\n", iface); + + if (surface->forwardReference) + { + /* Forward refcounting */ + TRACE("Forwarding to %p.\n", surface->forwardReference); + return IUnknown_AddRef(surface->forwardReference); + } + else + { + /* No container, handle our own refcounting */ + ULONG ref = InterlockedIncrement(&surface->refcount); + + TRACE("%p increasing refcount to %u.\n", iface, ref); + + if (ref == 1) + { + if (surface->parent_device) + IDirect3DDevice8_AddRef(surface->parent_device); + wined3d_mutex_lock(); + wined3d_surface_incref(surface->wined3d_surface); + wined3d_mutex_unlock(); + } + + return ref; + } +} + +static ULONG WINAPI d3d8_surface_Release(IDirect3DSurface8 *iface) +{ + struct d3d8_surface *surface = impl_from_IDirect3DSurface8(iface); + + TRACE("iface %p.\n", iface); + + if (surface->forwardReference) + { + /* Forward refcounting */ + TRACE("Forwarding to %p.\n", surface->forwardReference); + return IUnknown_Release(surface->forwardReference); + } + else + { + /* No container, handle our own refcounting */ + ULONG ref = InterlockedDecrement(&surface->refcount); + + TRACE("%p decreasing refcount to %u.\n", iface, ref); + + if (!ref) + { + IDirect3DDevice8 *parent_device = surface->parent_device; + + /* Implicit surfaces are destroyed with the device, not if refcount reaches 0. */ + wined3d_mutex_lock(); + wined3d_surface_decref(surface->wined3d_surface); + wined3d_mutex_unlock(); + + if (parent_device) + IDirect3DDevice8_Release(parent_device); + } + + return ref; + } +} + +static HRESULT WINAPI d3d8_surface_GetDevice(IDirect3DSurface8 *iface, IDirect3DDevice8 **device) +{ + struct d3d8_surface *surface = impl_from_IDirect3DSurface8(iface); + + TRACE("iface %p, device %p.\n", iface, device); + + if (surface->forwardReference) + { + IDirect3DResource8 *resource; + HRESULT hr; + + hr = IUnknown_QueryInterface(surface->forwardReference, &IID_IDirect3DResource8, (void **)&resource); + if (SUCCEEDED(hr)) + { + hr = IDirect3DResource8_GetDevice(resource, device); + IDirect3DResource8_Release(resource); + + TRACE("Returning device %p.\n", *device); + } + + return hr; + } + + *device = surface->parent_device; + IDirect3DDevice8_AddRef(*device); + + TRACE("Returning device %p.\n", *device); + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_surface_SetPrivateData(IDirect3DSurface8 *iface, REFGUID guid, + const void *data, DWORD data_size, DWORD flags) +{ + struct d3d8_surface *surface = impl_from_IDirect3DSurface8(iface); + struct wined3d_resource *resource; + HRESULT hr; + + TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n", + iface, debugstr_guid(guid), data, data_size, flags); + + wined3d_mutex_lock(); + resource = wined3d_surface_get_resource(surface->wined3d_surface); + hr = wined3d_resource_set_private_data(resource, guid, data, data_size, flags); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_surface_GetPrivateData(IDirect3DSurface8 *iface, REFGUID guid, + void *data, DWORD *data_size) +{ + struct d3d8_surface *surface = impl_from_IDirect3DSurface8(iface); + struct wined3d_resource *resource; + HRESULT hr; + + TRACE("iface %p, guid %s, data %p, data_size %p.\n", + iface, debugstr_guid(guid), data, data_size); + + wined3d_mutex_lock(); + resource = wined3d_surface_get_resource(surface->wined3d_surface); + hr = wined3d_resource_get_private_data(resource, guid, data, data_size); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_surface_FreePrivateData(IDirect3DSurface8 *iface, REFGUID guid) +{ + struct d3d8_surface *surface = impl_from_IDirect3DSurface8(iface); + struct wined3d_resource *resource; + HRESULT hr; + + TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid)); + + wined3d_mutex_lock(); + resource = wined3d_surface_get_resource(surface->wined3d_surface); + hr = wined3d_resource_free_private_data(resource, guid); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_surface_GetContainer(IDirect3DSurface8 *iface, REFIID riid, void **container) +{ + struct d3d8_surface *surface = impl_from_IDirect3DSurface8(iface); + HRESULT hr; + + TRACE("iface %p, riid %s, container %p.\n", iface, debugstr_guid(riid), container); + + if (!surface->container) + return E_NOINTERFACE; + + hr = IUnknown_QueryInterface(surface->container, riid, container); + + TRACE("Returning %p.\n", *container); + + return hr; +} + +static HRESULT WINAPI d3d8_surface_GetDesc(IDirect3DSurface8 *iface, D3DSURFACE_DESC *desc) +{ + struct d3d8_surface *surface = impl_from_IDirect3DSurface8(iface); + struct wined3d_resource_desc wined3d_desc; + struct wined3d_resource *wined3d_resource; + + TRACE("iface %p, desc %p.\n", iface, desc); + + wined3d_mutex_lock(); + wined3d_resource = wined3d_surface_get_resource(surface->wined3d_surface); + wined3d_resource_get_desc(wined3d_resource, &wined3d_desc); + wined3d_mutex_unlock(); + + desc->Format = d3dformat_from_wined3dformat(wined3d_desc.format); + desc->Type = wined3d_desc.resource_type; + desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK; + desc->Pool = wined3d_desc.pool; + desc->Size = wined3d_desc.size; + desc->MultiSampleType = wined3d_desc.multisample_type; + desc->Width = wined3d_desc.width; + desc->Height = wined3d_desc.height; + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_surface_LockRect(IDirect3DSurface8 *iface, + D3DLOCKED_RECT *locked_rect, const RECT *rect, DWORD flags) +{ + struct d3d8_surface *surface = impl_from_IDirect3DSurface8(iface); + struct wined3d_map_desc map_desc; + HRESULT hr; + + TRACE("iface %p, locked_rect %p, rect %s, flags %#x.\n", + iface, locked_rect, wine_dbgstr_rect(rect), flags); + + wined3d_mutex_lock(); + if (rect) + { + D3DSURFACE_DESC desc; + IDirect3DSurface8_GetDesc(iface, &desc); + + if ((rect->left < 0) + || (rect->top < 0) + || (rect->left >= rect->right) + || (rect->top >= rect->bottom) + || (rect->right > desc.Width) + || (rect->bottom > desc.Height)) + { + WARN("Trying to lock an invalid rectangle, returning D3DERR_INVALIDCALL\n"); + wined3d_mutex_unlock(); + + return D3DERR_INVALIDCALL; + } + } + + hr = wined3d_surface_map(surface->wined3d_surface, &map_desc, rect, flags); + wined3d_mutex_unlock(); + + locked_rect->Pitch = map_desc.row_pitch; + locked_rect->pBits = map_desc.data; + + return hr; +} + +static HRESULT WINAPI d3d8_surface_UnlockRect(IDirect3DSurface8 *iface) +{ + struct d3d8_surface *surface = impl_from_IDirect3DSurface8(iface); + HRESULT hr; + + TRACE("iface %p.\n", iface); + + wined3d_mutex_lock(); + hr = wined3d_surface_unmap(surface->wined3d_surface); + wined3d_mutex_unlock(); + + switch(hr) + { + case WINEDDERR_NOTLOCKED: return D3DERR_INVALIDCALL; + default: return hr; + } +} + +static const IDirect3DSurface8Vtbl d3d8_surface_vtbl = +{ + /* IUnknown */ + d3d8_surface_QueryInterface, + d3d8_surface_AddRef, + d3d8_surface_Release, + /* IDirect3DResource8 */ + d3d8_surface_GetDevice, + d3d8_surface_SetPrivateData, + d3d8_surface_GetPrivateData, + d3d8_surface_FreePrivateData, + /* IDirect3DSurface8 */ + d3d8_surface_GetContainer, + d3d8_surface_GetDesc, + d3d8_surface_LockRect, + d3d8_surface_UnlockRect, +}; + +static void STDMETHODCALLTYPE surface_wined3d_object_destroyed(void *parent) +{ + HeapFree(GetProcessHeap(), 0, parent); +} + +static const struct wined3d_parent_ops d3d8_surface_wined3d_parent_ops = +{ + surface_wined3d_object_destroyed, +}; + +HRESULT surface_init(struct d3d8_surface *surface, struct d3d8_device *device, UINT width, UINT height, + D3DFORMAT format, DWORD flags, DWORD usage, D3DPOOL pool, D3DMULTISAMPLE_TYPE multisample_type, + DWORD multisample_quality) +{ + HRESULT hr; + + surface->IDirect3DSurface8_iface.lpVtbl = &d3d8_surface_vtbl; + surface->refcount = 1; + + /* FIXME: Check MAX bounds of MultisampleQuality. */ + if (multisample_quality > 0) + { + FIXME("Multisample quality set to %u, substituting 0.\n", multisample_quality); + multisample_quality = 0; + } + + wined3d_mutex_lock(); + hr = wined3d_surface_create(device->wined3d_device, width, height, wined3dformat_from_d3dformat(format), + usage & WINED3DUSAGE_MASK, (enum wined3d_pool)pool, multisample_type, multisample_quality, + flags, surface, &d3d8_surface_wined3d_parent_ops, &surface->wined3d_surface); + wined3d_mutex_unlock(); + if (FAILED(hr)) + { + WARN("Failed to create wined3d surface, hr %#x.\n", hr); + return hr; + } + + surface->parent_device = &device->IDirect3DDevice8_iface; + IDirect3DDevice8_AddRef(surface->parent_device); + + return D3D_OK; +} + +struct d3d8_surface *unsafe_impl_from_IDirect3DSurface8(IDirect3DSurface8 *iface) +{ + if (!iface) + return NULL; + assert(iface->lpVtbl == &d3d8_surface_vtbl); + + return impl_from_IDirect3DSurface8(iface); +} diff --git a/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/swapchain.c b/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/swapchain.c new file mode 100644 index 00000000..c172d5c1 --- /dev/null +++ b/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/swapchain.c @@ -0,0 +1,208 @@ +/* + * IDirect3DSwapChain8 implementation + * + * Copyright 2005 Oliver Stieber + * + * 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 + */ + +/* + * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice + * other than GPL or LGPL is available it will apply instead, Oracle elects to use only + * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where + * a choice of LGPL license versions is made available with the language indicating + * that LGPLv2 or any later version may be used, or where a choice of which version + * of the LGPL is applied is otherwise unspecified. + */ + +#include "config.h" +#include "d3d8_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(d3d8); + +static inline struct d3d8_swapchain *impl_from_IDirect3DSwapChain8(IDirect3DSwapChain8 *iface) +{ + return CONTAINING_RECORD(iface, struct d3d8_swapchain, IDirect3DSwapChain8_iface); +} + +static HRESULT WINAPI d3d8_swapchain_QueryInterface(IDirect3DSwapChain8 *iface, REFIID riid, void **out) +{ + TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out); + + if (IsEqualGUID(riid, &IID_IDirect3DSwapChain8) + || IsEqualGUID(riid, &IID_IUnknown)) + { + IDirect3DSwapChain8_AddRef(iface); + *out = iface; + return S_OK; + } + + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid)); + + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI d3d8_swapchain_AddRef(IDirect3DSwapChain8 *iface) +{ + struct d3d8_swapchain *swapchain = impl_from_IDirect3DSwapChain8(iface); + ULONG ref = InterlockedIncrement(&swapchain->refcount); + + TRACE("%p increasing refcount to %u.\n", iface, ref); + + if (ref == 1) + { + if (swapchain->parent_device) + IDirect3DDevice8_AddRef(swapchain->parent_device); + wined3d_mutex_lock(); + wined3d_swapchain_incref(swapchain->wined3d_swapchain); + wined3d_mutex_unlock(); + } + + return ref; +} + +static ULONG WINAPI d3d8_swapchain_Release(IDirect3DSwapChain8 *iface) +{ + struct d3d8_swapchain *swapchain = impl_from_IDirect3DSwapChain8(iface); + ULONG ref = InterlockedDecrement(&swapchain->refcount); + + TRACE("%p decreasing refcount to %u.\n", iface, ref); + + if (!ref) + { + IDirect3DDevice8 *parent_device = swapchain->parent_device; + + wined3d_mutex_lock(); + wined3d_swapchain_decref(swapchain->wined3d_swapchain); + wined3d_mutex_unlock(); + + if (parent_device) + IDirect3DDevice8_Release(parent_device); + } + return ref; +} + +static HRESULT WINAPI d3d8_swapchain_Present(IDirect3DSwapChain8 *iface, + const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override, + const RGNDATA *dirty_region) +{ + struct d3d8_swapchain *swapchain = impl_from_IDirect3DSwapChain8(iface); + HRESULT hr; + + TRACE("iface %p, src_rect %s, dst_rect %s, dst_window_override %p, dirty_region %p.\n", + iface, wine_dbgstr_rect(src_rect), wine_dbgstr_rect(dst_rect), dst_window_override, dirty_region); + + wined3d_mutex_lock(); + hr = wined3d_swapchain_present(swapchain->wined3d_swapchain, src_rect, + dst_rect, dst_window_override, dirty_region, 0); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_swapchain_GetBackBuffer(IDirect3DSwapChain8 *iface, + UINT backbuffer_idx, D3DBACKBUFFER_TYPE backbuffer_type, IDirect3DSurface8 **backbuffer) +{ + struct d3d8_swapchain *swapchain = impl_from_IDirect3DSwapChain8(iface); + struct wined3d_surface *wined3d_surface = NULL; + struct d3d8_surface *surface_impl; + HRESULT hr = D3D_OK; + + TRACE("iface %p, backbuffer_idx %u, backbuffer_type %#x, backbuffer %p.\n", + iface, backbuffer_idx, backbuffer_type, backbuffer); + + wined3d_mutex_lock(); + if ((wined3d_surface = wined3d_swapchain_get_back_buffer(swapchain->wined3d_swapchain, + backbuffer_idx, (enum wined3d_backbuffer_type)backbuffer_type))) + { + surface_impl = wined3d_surface_get_parent(wined3d_surface); + *backbuffer = &surface_impl->IDirect3DSurface8_iface; + IDirect3DSurface8_AddRef(*backbuffer); + } + else + { + hr = D3DERR_INVALIDCALL; + } + wined3d_mutex_unlock(); + + return hr; +} + +static const IDirect3DSwapChain8Vtbl d3d8_swapchain_vtbl = +{ + d3d8_swapchain_QueryInterface, + d3d8_swapchain_AddRef, + d3d8_swapchain_Release, + d3d8_swapchain_Present, + d3d8_swapchain_GetBackBuffer +}; + +static void STDMETHODCALLTYPE d3d8_swapchain_wined3d_object_released(void *parent) +{ + HeapFree(GetProcessHeap(), 0, parent); +} + +static const struct wined3d_parent_ops d3d8_swapchain_wined3d_parent_ops = +{ + d3d8_swapchain_wined3d_object_released, +}; + +static HRESULT swapchain_init(struct d3d8_swapchain *swapchain, struct d3d8_device *device, + struct wined3d_swapchain_desc *desc) +{ + HRESULT hr; + + swapchain->refcount = 1; + swapchain->IDirect3DSwapChain8_iface.lpVtbl = &d3d8_swapchain_vtbl; + + wined3d_mutex_lock(); + hr = wined3d_swapchain_create(device->wined3d_device, desc, swapchain, + &d3d8_swapchain_wined3d_parent_ops, &swapchain->wined3d_swapchain); + wined3d_mutex_unlock(); + + if (FAILED(hr)) + { + WARN("Failed to create wined3d swapchain, hr %#x.\n", hr); + return hr; + } + + swapchain->parent_device = &device->IDirect3DDevice8_iface; + IDirect3DDevice8_AddRef(swapchain->parent_device); + + return D3D_OK; +} + +HRESULT d3d8_swapchain_create(struct d3d8_device *device, struct wined3d_swapchain_desc *desc, + struct d3d8_swapchain **swapchain) +{ + struct d3d8_swapchain *object; + HRESULT hr; + + if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)))) + return E_OUTOFMEMORY; + + if (FAILED(hr = swapchain_init(object, device, desc))) + { + WARN("Failed to initialize swapchain, hr %#x.\n", hr); + HeapFree(GetProcessHeap(), 0, object); + return hr; + } + + TRACE("Created swapchain %p.\n", object); + *swapchain = object; + + return D3D_OK; +} diff --git a/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/texture.c b/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/texture.c new file mode 100644 index 00000000..1a87636e --- /dev/null +++ b/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/texture.c @@ -0,0 +1,1308 @@ +/* + * Copyright 2005 Oliver Stieber + * + * 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 + */ + +/* + * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice + * other than GPL or LGPL is available it will apply instead, Oracle elects to use only + * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where + * a choice of LGPL license versions is made available with the language indicating + * that LGPLv2 or any later version may be used, or where a choice of which version + * of the LGPL is applied is otherwise unspecified. + */ + +#include "config.h" +#include "d3d8_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(d3d8); + +static inline struct d3d8_texture *impl_from_IDirect3DTexture8(IDirect3DTexture8 *iface) +{ + return CONTAINING_RECORD(iface, struct d3d8_texture, IDirect3DBaseTexture8_iface); +} + +static inline struct d3d8_texture *impl_from_IDirect3DCubeTexture8(IDirect3DCubeTexture8 *iface) +{ + return CONTAINING_RECORD(iface, struct d3d8_texture, IDirect3DBaseTexture8_iface); +} + +static inline struct d3d8_texture *impl_from_IDirect3DVolumeTexture8(IDirect3DVolumeTexture8 *iface) +{ + return CONTAINING_RECORD(iface, struct d3d8_texture, IDirect3DBaseTexture8_iface); +} + +static HRESULT WINAPI d3d8_texture_2d_QueryInterface(IDirect3DTexture8 *iface, REFIID riid, void **out) +{ + TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out); + + if (IsEqualGUID(riid, &IID_IDirect3DTexture8) + || IsEqualGUID(riid, &IID_IDirect3DBaseTexture8) + || IsEqualGUID(riid, &IID_IDirect3DResource8) + || IsEqualGUID(riid, &IID_IUnknown)) + { + IDirect3DTexture8_AddRef(iface); + *out = iface; + return S_OK; + } + + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid)); + + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI d3d8_texture_2d_AddRef(IDirect3DTexture8 *iface) +{ + struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface); + ULONG ref = InterlockedIncrement(&texture->refcount); + + TRACE("%p increasing refcount to %u.\n", iface, ref); + + if (ref == 1) + { + IDirect3DDevice8_AddRef(texture->parent_device); + wined3d_mutex_lock(); + wined3d_texture_incref(texture->wined3d_texture); + wined3d_mutex_unlock(); + } + + return ref; +} + +static ULONG WINAPI d3d8_texture_2d_Release(IDirect3DTexture8 *iface) +{ + struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface); + ULONG ref = InterlockedDecrement(&texture->refcount); + + TRACE("%p decreasing refcount to %u.\n", iface, ref); + + if (!ref) + { + IDirect3DDevice8 *parent_device = texture->parent_device; + + wined3d_mutex_lock(); + wined3d_texture_decref(texture->wined3d_texture); + wined3d_mutex_unlock(); + + /* Release the device last, as it may cause the device to be destroyed. */ + IDirect3DDevice8_Release(parent_device); + } + return ref; +} + +static HRESULT WINAPI d3d8_texture_2d_GetDevice(IDirect3DTexture8 *iface, IDirect3DDevice8 **device) +{ + struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface); + + TRACE("iface %p, device %p.\n", iface, device); + + *device = texture->parent_device; + IDirect3DDevice8_AddRef(*device); + + TRACE("Returning device %p.\n", *device); + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_texture_2d_SetPrivateData(IDirect3DTexture8 *iface, + REFGUID guid, const void *data, DWORD data_size, DWORD flags) +{ + struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface); + struct wined3d_resource *resource; + HRESULT hr; + + TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n", + iface, debugstr_guid(guid), data, data_size, flags); + + wined3d_mutex_lock(); + resource = wined3d_texture_get_resource(texture->wined3d_texture); + hr = wined3d_resource_set_private_data(resource, guid, data, data_size, flags); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_texture_2d_GetPrivateData(IDirect3DTexture8 *iface, + REFGUID guid, void *data, DWORD *data_size) +{ + struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface); + struct wined3d_resource *resource; + HRESULT hr; + + TRACE("iface %p, guid %s, data %p, data_size %p.\n", + iface, debugstr_guid(guid), data, data_size); + + wined3d_mutex_lock(); + resource = wined3d_texture_get_resource(texture->wined3d_texture); + hr = wined3d_resource_get_private_data(resource, guid, data, data_size); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_texture_2d_FreePrivateData(IDirect3DTexture8 *iface, REFGUID guid) +{ + struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface); + struct wined3d_resource *resource; + HRESULT hr; + + TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid)); + + wined3d_mutex_lock(); + resource = wined3d_texture_get_resource(texture->wined3d_texture); + hr = wined3d_resource_free_private_data(resource, guid); + wined3d_mutex_unlock(); + + return hr; +} + +static DWORD WINAPI d3d8_texture_2d_SetPriority(IDirect3DTexture8 *iface, DWORD priority) +{ + struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface); + DWORD ret; + + TRACE("iface %p, priority %u.\n", iface, priority); + + wined3d_mutex_lock(); + ret = wined3d_texture_set_priority(texture->wined3d_texture, priority); + wined3d_mutex_unlock(); + + return ret; +} + +static DWORD WINAPI d3d8_texture_2d_GetPriority(IDirect3DTexture8 *iface) +{ + struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface); + DWORD ret; + + TRACE("iface %p.\n", iface); + + wined3d_mutex_lock(); + ret = wined3d_texture_get_priority(texture->wined3d_texture); + wined3d_mutex_unlock(); + + return ret; +} + +static void WINAPI d3d8_texture_2d_PreLoad(IDirect3DTexture8 *iface) +{ + struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface); + + TRACE("iface %p.\n", iface); + + wined3d_mutex_lock(); + wined3d_texture_preload(texture->wined3d_texture); + wined3d_mutex_unlock(); +} + +static D3DRESOURCETYPE WINAPI d3d8_texture_2d_GetType(IDirect3DTexture8 *iface) +{ + TRACE("iface %p.\n", iface); + + return D3DRTYPE_TEXTURE; +} + +static DWORD WINAPI d3d8_texture_2d_SetLOD(IDirect3DTexture8 *iface, DWORD lod) +{ + struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface); + DWORD ret; + + TRACE("iface %p, lod %u.\n", iface, lod); + + wined3d_mutex_lock(); + ret = wined3d_texture_set_lod(texture->wined3d_texture, lod); + wined3d_mutex_unlock(); + + return ret; +} + +static DWORD WINAPI d3d8_texture_2d_GetLOD(IDirect3DTexture8 *iface) +{ + struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface); + DWORD ret; + + TRACE("iface %p.\n", iface); + + wined3d_mutex_lock(); + ret = wined3d_texture_get_lod(texture->wined3d_texture); + wined3d_mutex_unlock(); + + return ret; +} + +static DWORD WINAPI d3d8_texture_2d_GetLevelCount(IDirect3DTexture8 *iface) +{ + struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface); + DWORD ret; + + TRACE("iface %p.\n", iface); + + wined3d_mutex_lock(); + ret = wined3d_texture_get_level_count(texture->wined3d_texture); + wined3d_mutex_unlock(); + + return ret; +} + +static HRESULT WINAPI d3d8_texture_2d_GetLevelDesc(IDirect3DTexture8 *iface, UINT level, D3DSURFACE_DESC *desc) +{ + struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface); + struct wined3d_resource *sub_resource; + HRESULT hr = D3D_OK; + + TRACE("iface %p, level %u, desc %p.\n", iface, level, desc); + + wined3d_mutex_lock(); + if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level))) + hr = D3DERR_INVALIDCALL; + else + { + struct wined3d_resource_desc wined3d_desc; + + wined3d_resource_get_desc(sub_resource, &wined3d_desc); + desc->Format = d3dformat_from_wined3dformat(wined3d_desc.format); + desc->Type = wined3d_desc.resource_type; + desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK; + desc->Pool = wined3d_desc.pool; + desc->Size = wined3d_desc.size; + desc->MultiSampleType = wined3d_desc.multisample_type; + desc->Width = wined3d_desc.width; + desc->Height = wined3d_desc.height; + } + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_texture_2d_GetSurfaceLevel(IDirect3DTexture8 *iface, + UINT level, IDirect3DSurface8 **surface) +{ + struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface); + struct wined3d_resource *sub_resource; + struct d3d8_surface *surface_impl; + + TRACE("iface %p, level %u, surface %p.\n", iface, level, surface); + + wined3d_mutex_lock(); + if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level))) + { + wined3d_mutex_unlock(); + return D3DERR_INVALIDCALL; + } + + surface_impl = wined3d_resource_get_parent(sub_resource); + *surface = &surface_impl->IDirect3DSurface8_iface; + IDirect3DSurface8_AddRef(*surface); + wined3d_mutex_unlock(); + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_texture_2d_LockRect(IDirect3DTexture8 *iface, UINT level, + D3DLOCKED_RECT *locked_rect, const RECT *rect, DWORD flags) +{ + struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface); + struct wined3d_resource *sub_resource; + struct d3d8_surface *surface_impl; + HRESULT hr; + + TRACE("iface %p, level %u, locked_rect %p, rect %p, flags %#x.\n", + iface, level, locked_rect, rect, flags); + + wined3d_mutex_lock(); + if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level))) + hr = D3DERR_INVALIDCALL; + else + { + surface_impl = wined3d_resource_get_parent(sub_resource); + hr = IDirect3DSurface8_LockRect(&surface_impl->IDirect3DSurface8_iface, locked_rect, rect, flags); + } + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_texture_2d_UnlockRect(IDirect3DTexture8 *iface, UINT level) +{ + struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface); + struct wined3d_resource *sub_resource; + struct d3d8_surface *surface_impl; + HRESULT hr; + + TRACE("iface %p, level %u.\n", iface, level); + + wined3d_mutex_lock(); + if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level))) + hr = D3DERR_INVALIDCALL; + else + { + surface_impl = wined3d_resource_get_parent(sub_resource); + hr = IDirect3DSurface8_UnlockRect(&surface_impl->IDirect3DSurface8_iface); + } + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_texture_2d_AddDirtyRect(IDirect3DTexture8 *iface, const RECT *dirty_rect) +{ + struct d3d8_texture *texture = impl_from_IDirect3DTexture8(iface); + HRESULT hr; + + TRACE("iface %p, dirty_rect %s.\n", + iface, wine_dbgstr_rect(dirty_rect)); + + wined3d_mutex_lock(); + if (!dirty_rect) + hr = wined3d_texture_add_dirty_region(texture->wined3d_texture, 0, NULL); + else + { + struct wined3d_box dirty_region; + + dirty_region.left = dirty_rect->left; + dirty_region.top = dirty_rect->top; + dirty_region.right = dirty_rect->right; + dirty_region.bottom = dirty_rect->bottom; + dirty_region.front = 0; + dirty_region.back = 1; + hr = wined3d_texture_add_dirty_region(texture->wined3d_texture, 0, &dirty_region); + } + wined3d_mutex_unlock(); + + return hr; +} + +static const IDirect3DTexture8Vtbl Direct3DTexture8_Vtbl = +{ + /* IUnknown */ + d3d8_texture_2d_QueryInterface, + d3d8_texture_2d_AddRef, + d3d8_texture_2d_Release, + /* IDirect3DResource8 */ + d3d8_texture_2d_GetDevice, + d3d8_texture_2d_SetPrivateData, + d3d8_texture_2d_GetPrivateData, + d3d8_texture_2d_FreePrivateData, + d3d8_texture_2d_SetPriority, + d3d8_texture_2d_GetPriority, + d3d8_texture_2d_PreLoad, + d3d8_texture_2d_GetType, + /* IDirect3dBaseTexture8 */ + d3d8_texture_2d_SetLOD, + d3d8_texture_2d_GetLOD, + d3d8_texture_2d_GetLevelCount, + /* IDirect3DTexture8 */ + d3d8_texture_2d_GetLevelDesc, + d3d8_texture_2d_GetSurfaceLevel, + d3d8_texture_2d_LockRect, + d3d8_texture_2d_UnlockRect, + d3d8_texture_2d_AddDirtyRect, +}; + +static HRESULT WINAPI d3d8_texture_cube_QueryInterface(IDirect3DCubeTexture8 *iface, REFIID riid, void **out) +{ + TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out); + + if (IsEqualGUID(riid, &IID_IDirect3DCubeTexture8) + || IsEqualGUID(riid, &IID_IDirect3DBaseTexture8) + || IsEqualGUID(riid, &IID_IDirect3DResource8) + || IsEqualGUID(riid, &IID_IUnknown)) + { + IDirect3DCubeTexture8_AddRef(iface); + *out = iface; + return S_OK; + } + + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid)); + + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI d3d8_texture_cube_AddRef(IDirect3DCubeTexture8 *iface) +{ + struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface); + ULONG ref = InterlockedIncrement(&texture->refcount); + + TRACE("%p increasing refcount to %u.\n", iface, ref); + + if (ref == 1) + { + IDirect3DDevice8_AddRef(texture->parent_device); + wined3d_mutex_lock(); + wined3d_texture_incref(texture->wined3d_texture); + wined3d_mutex_unlock(); + } + + return ref; +} + +static ULONG WINAPI d3d8_texture_cube_Release(IDirect3DCubeTexture8 *iface) +{ + struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface); + ULONG ref = InterlockedDecrement(&texture->refcount); + + TRACE("%p decreasing refcount to %u.\n", iface, ref); + + if (!ref) + { + IDirect3DDevice8 *parent_device = texture->parent_device; + + TRACE("Releasing child %p.\n", texture->wined3d_texture); + + wined3d_mutex_lock(); + wined3d_texture_decref(texture->wined3d_texture); + wined3d_mutex_unlock(); + + /* Release the device last, as it may cause the device to be destroyed. */ + IDirect3DDevice8_Release(parent_device); + } + return ref; +} + +static HRESULT WINAPI d3d8_texture_cube_GetDevice(IDirect3DCubeTexture8 *iface, IDirect3DDevice8 **device) +{ + struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface); + + TRACE("iface %p, device %p.\n", iface, device); + + *device = texture->parent_device; + IDirect3DDevice8_AddRef(*device); + + TRACE("Returning device %p.\n", *device); + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_texture_cube_SetPrivateData(IDirect3DCubeTexture8 *iface, + REFGUID guid, const void *data, DWORD data_size, DWORD flags) +{ + struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface); + struct wined3d_resource *resource; + HRESULT hr; + + TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n", + iface, debugstr_guid(guid), data, data_size, flags); + + wined3d_mutex_lock(); + resource = wined3d_texture_get_resource(texture->wined3d_texture); + hr = wined3d_resource_set_private_data(resource, guid, data, data_size, flags); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_texture_cube_GetPrivateData(IDirect3DCubeTexture8 *iface, + REFGUID guid, void *data, DWORD *data_size) +{ + struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface); + struct wined3d_resource *resource; + HRESULT hr; + + TRACE("iface %p, guid %s, data %p, data_size %p.\n", + iface, debugstr_guid(guid), data, data_size); + + wined3d_mutex_lock(); + resource = wined3d_texture_get_resource(texture->wined3d_texture); + hr = wined3d_resource_get_private_data(resource, guid, data, data_size); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_texture_cube_FreePrivateData(IDirect3DCubeTexture8 *iface, REFGUID guid) +{ + struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface); + struct wined3d_resource *resource; + HRESULT hr; + + TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid)); + + wined3d_mutex_lock(); + resource = wined3d_texture_get_resource(texture->wined3d_texture); + hr = wined3d_resource_free_private_data(resource, guid); + wined3d_mutex_unlock(); + + return hr; +} + +static DWORD WINAPI d3d8_texture_cube_SetPriority(IDirect3DCubeTexture8 *iface, DWORD priority) +{ + struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface); + DWORD ret; + + TRACE("iface %p, priority %u.\n", iface, priority); + + wined3d_mutex_lock(); + ret = wined3d_texture_set_priority(texture->wined3d_texture, priority); + wined3d_mutex_unlock(); + + return ret; +} + +static DWORD WINAPI d3d8_texture_cube_GetPriority(IDirect3DCubeTexture8 *iface) +{ + struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface); + DWORD ret; + + TRACE("iface %p.\n", iface); + + wined3d_mutex_lock(); + ret = wined3d_texture_get_priority(texture->wined3d_texture); + wined3d_mutex_unlock(); + + return ret; +} + +static void WINAPI d3d8_texture_cube_PreLoad(IDirect3DCubeTexture8 *iface) +{ + struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface); + + TRACE("iface %p.\n", iface); + + wined3d_mutex_lock(); + wined3d_texture_preload(texture->wined3d_texture); + wined3d_mutex_unlock(); +} + +static D3DRESOURCETYPE WINAPI d3d8_texture_cube_GetType(IDirect3DCubeTexture8 *iface) +{ + TRACE("iface %p.\n", iface); + + return D3DRTYPE_CUBETEXTURE; +} + +static DWORD WINAPI d3d8_texture_cube_SetLOD(IDirect3DCubeTexture8 *iface, DWORD lod) +{ + struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface); + DWORD ret; + + TRACE("iface %p, lod %u.\n", iface, lod); + + wined3d_mutex_lock(); + ret = wined3d_texture_set_lod(texture->wined3d_texture, lod); + wined3d_mutex_unlock(); + + return ret; +} + +static DWORD WINAPI d3d8_texture_cube_GetLOD(IDirect3DCubeTexture8 *iface) +{ + struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface); + DWORD ret; + + TRACE("iface %p.\n", iface); + + wined3d_mutex_lock(); + ret = wined3d_texture_get_lod(texture->wined3d_texture); + wined3d_mutex_unlock(); + + return ret; +} + +static DWORD WINAPI d3d8_texture_cube_GetLevelCount(IDirect3DCubeTexture8 *iface) +{ + struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface); + DWORD ret; + + TRACE("iface %p.\n", iface); + + wined3d_mutex_lock(); + ret = wined3d_texture_get_level_count(texture->wined3d_texture); + wined3d_mutex_unlock(); + + return ret; +} + +static HRESULT WINAPI d3d8_texture_cube_GetLevelDesc(IDirect3DCubeTexture8 *iface, UINT level, D3DSURFACE_DESC *desc) +{ + struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface); + struct wined3d_resource *sub_resource; + HRESULT hr = D3D_OK; + + TRACE("iface %p, level %u, desc %p.\n", iface, level, desc); + + wined3d_mutex_lock(); + if (level >= wined3d_texture_get_level_count(texture->wined3d_texture)) + { + wined3d_mutex_unlock(); + return D3DERR_INVALIDCALL; + } + + if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level))) + hr = D3DERR_INVALIDCALL; + else + { + struct wined3d_resource_desc wined3d_desc; + + wined3d_resource_get_desc(sub_resource, &wined3d_desc); + desc->Format = d3dformat_from_wined3dformat(wined3d_desc.format); + desc->Type = wined3d_desc.resource_type; + desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK; + desc->Pool = wined3d_desc.pool; + desc->Size = wined3d_desc.size; + desc->MultiSampleType = wined3d_desc.multisample_type; + desc->Width = wined3d_desc.width; + desc->Height = wined3d_desc.height; + } + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_texture_cube_GetCubeMapSurface(IDirect3DCubeTexture8 *iface, + D3DCUBEMAP_FACES face, UINT level, IDirect3DSurface8 **surface) +{ + struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface); + struct wined3d_resource *sub_resource; + struct d3d8_surface *surface_impl; + UINT sub_resource_idx; + DWORD level_count; + + TRACE("iface %p, face %#x, level %u, surface %p.\n", iface, face, level, surface); + + wined3d_mutex_lock(); + level_count = wined3d_texture_get_level_count(texture->wined3d_texture); + if (level >= level_count) + { + wined3d_mutex_unlock(); + return D3DERR_INVALIDCALL; + } + + sub_resource_idx = level_count * face + level; + if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, sub_resource_idx))) + { + wined3d_mutex_unlock(); + return D3DERR_INVALIDCALL; + } + + surface_impl = wined3d_resource_get_parent(sub_resource); + *surface = &surface_impl->IDirect3DSurface8_iface; + IDirect3DSurface8_AddRef(*surface); + wined3d_mutex_unlock(); + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_texture_cube_LockRect(IDirect3DCubeTexture8 *iface, + D3DCUBEMAP_FACES face, UINT level, D3DLOCKED_RECT *locked_rect, const RECT *rect, + DWORD flags) +{ + struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface); + struct wined3d_resource *sub_resource; + struct d3d8_surface *surface_impl; + UINT sub_resource_idx; + HRESULT hr; + + TRACE("iface %p, face %#x, level %u, locked_rect %p, rect %p, flags %#x.\n", + iface, face, level, locked_rect, rect, flags); + + wined3d_mutex_lock(); + sub_resource_idx = wined3d_texture_get_level_count(texture->wined3d_texture) * face + level; + if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, sub_resource_idx))) + hr = D3DERR_INVALIDCALL; + else + { + surface_impl = wined3d_resource_get_parent(sub_resource); + hr = IDirect3DSurface8_LockRect(&surface_impl->IDirect3DSurface8_iface, locked_rect, rect, flags); + } + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_texture_cube_UnlockRect(IDirect3DCubeTexture8 *iface, + D3DCUBEMAP_FACES face, UINT level) +{ + struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface); + struct wined3d_resource *sub_resource; + struct d3d8_surface *surface_impl; + UINT sub_resource_idx; + HRESULT hr; + + TRACE("iface %p, face %#x, level %u.\n", iface, face, level); + + wined3d_mutex_lock(); + sub_resource_idx = wined3d_texture_get_level_count(texture->wined3d_texture) * face + level; + if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, sub_resource_idx))) + hr = D3DERR_INVALIDCALL; + else + { + surface_impl = wined3d_resource_get_parent(sub_resource); + hr = IDirect3DSurface8_UnlockRect(&surface_impl->IDirect3DSurface8_iface); + } + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_texture_cube_AddDirtyRect(IDirect3DCubeTexture8 *iface, + D3DCUBEMAP_FACES face, const RECT *dirty_rect) +{ + struct d3d8_texture *texture = impl_from_IDirect3DCubeTexture8(iface); + HRESULT hr; + + TRACE("iface %p, face %#x, dirty_rect %s.\n", + iface, face, wine_dbgstr_rect(dirty_rect)); + + wined3d_mutex_lock(); + if (!dirty_rect) + hr = wined3d_texture_add_dirty_region(texture->wined3d_texture, face, NULL); + else + { + struct wined3d_box dirty_region; + + dirty_region.left = dirty_rect->left; + dirty_region.top = dirty_rect->top; + dirty_region.right = dirty_rect->right; + dirty_region.bottom = dirty_rect->bottom; + dirty_region.front = 0; + dirty_region.back = 1; + hr = wined3d_texture_add_dirty_region(texture->wined3d_texture, face, &dirty_region); + } + wined3d_mutex_unlock(); + + return hr; +} + +static const IDirect3DCubeTexture8Vtbl Direct3DCubeTexture8_Vtbl = +{ + /* IUnknown */ + d3d8_texture_cube_QueryInterface, + d3d8_texture_cube_AddRef, + d3d8_texture_cube_Release, + /* IDirect3DResource8 */ + d3d8_texture_cube_GetDevice, + d3d8_texture_cube_SetPrivateData, + d3d8_texture_cube_GetPrivateData, + d3d8_texture_cube_FreePrivateData, + d3d8_texture_cube_SetPriority, + d3d8_texture_cube_GetPriority, + d3d8_texture_cube_PreLoad, + d3d8_texture_cube_GetType, + /* IDirect3DBaseTexture8 */ + d3d8_texture_cube_SetLOD, + d3d8_texture_cube_GetLOD, + d3d8_texture_cube_GetLevelCount, + /* IDirect3DCubeTexture8 */ + d3d8_texture_cube_GetLevelDesc, + d3d8_texture_cube_GetCubeMapSurface, + d3d8_texture_cube_LockRect, + d3d8_texture_cube_UnlockRect, + d3d8_texture_cube_AddDirtyRect, +}; + +static HRESULT WINAPI d3d8_texture_3d_QueryInterface(IDirect3DVolumeTexture8 *iface, REFIID riid, void **out) +{ + TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out); + + if (IsEqualGUID(riid, &IID_IDirect3DVolumeTexture8) + || IsEqualGUID(riid, &IID_IDirect3DBaseTexture8) + || IsEqualGUID(riid, &IID_IDirect3DResource8) + || IsEqualGUID(riid, &IID_IUnknown)) + { + IDirect3DVolumeTexture8_AddRef(iface); + *out = iface; + return S_OK; + } + + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid)); + + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI d3d8_texture_3d_AddRef(IDirect3DVolumeTexture8 *iface) +{ + struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface); + ULONG ref = InterlockedIncrement(&texture->refcount); + + TRACE("%p increasing refcount to %u.\n", iface, ref); + + if (ref == 1) + { + IDirect3DDevice8_AddRef(texture->parent_device); + wined3d_mutex_lock(); + wined3d_texture_incref(texture->wined3d_texture); + wined3d_mutex_unlock(); + } + + return ref; +} + +static ULONG WINAPI d3d8_texture_3d_Release(IDirect3DVolumeTexture8 *iface) +{ + struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface); + ULONG ref = InterlockedDecrement(&texture->refcount); + + TRACE("%p decreasing refcount to %u.\n", iface, ref); + + if (!ref) + { + IDirect3DDevice8 *parent_device = texture->parent_device; + + wined3d_mutex_lock(); + wined3d_texture_decref(texture->wined3d_texture); + wined3d_mutex_unlock(); + + /* Release the device last, as it may cause the device to be destroyed. */ + IDirect3DDevice8_Release(parent_device); + } + return ref; +} + +static HRESULT WINAPI d3d8_texture_3d_GetDevice(IDirect3DVolumeTexture8 *iface, IDirect3DDevice8 **device) +{ + struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface); + + TRACE("iface %p, device %p.\n", iface, device); + + *device = texture->parent_device; + IDirect3DDevice8_AddRef(*device); + + TRACE("Returning device %p.\n", *device); + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_texture_3d_SetPrivateData(IDirect3DVolumeTexture8 *iface, + REFGUID guid, const void *data, DWORD data_size, DWORD flags) +{ + struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface); + struct wined3d_resource *resource; + HRESULT hr; + + TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n", + iface, debugstr_guid(guid), data, data_size, flags); + + wined3d_mutex_lock(); + resource = wined3d_texture_get_resource(texture->wined3d_texture); + hr = wined3d_resource_set_private_data(resource, guid, data, data_size, flags); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_texture_3d_GetPrivateData(IDirect3DVolumeTexture8 *iface, + REFGUID guid, void *data, DWORD *data_size) +{ + struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface); + struct wined3d_resource *resource; + HRESULT hr; + + TRACE("iface %p, guid %s, data %p, data_size %p.\n", + iface, debugstr_guid(guid), data, data_size); + + wined3d_mutex_lock(); + resource = wined3d_texture_get_resource(texture->wined3d_texture); + hr = wined3d_resource_get_private_data(resource, guid, data, data_size); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_texture_3d_FreePrivateData(IDirect3DVolumeTexture8 *iface, REFGUID guid) +{ + struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface); + struct wined3d_resource *resource; + HRESULT hr; + + TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid)); + + wined3d_mutex_lock(); + resource = wined3d_texture_get_resource(texture->wined3d_texture); + hr = wined3d_resource_free_private_data(resource, guid); + wined3d_mutex_unlock(); + + return hr; +} + +static DWORD WINAPI d3d8_texture_3d_SetPriority(IDirect3DVolumeTexture8 *iface, DWORD priority) +{ + struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface); + DWORD ret; + + TRACE("iface %p, priority %u.\n", iface, priority); + + wined3d_mutex_lock(); + ret = wined3d_texture_set_priority(texture->wined3d_texture, priority); + wined3d_mutex_unlock(); + + return ret; +} + +static DWORD WINAPI d3d8_texture_3d_GetPriority(IDirect3DVolumeTexture8 *iface) +{ + struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface); + DWORD ret; + + TRACE("iface %p.\n", iface); + + wined3d_mutex_lock(); + ret = wined3d_texture_get_priority(texture->wined3d_texture); + wined3d_mutex_unlock(); + + return ret; +} + +static void WINAPI d3d8_texture_3d_PreLoad(IDirect3DVolumeTexture8 *iface) +{ + struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface); + + TRACE("iface %p.\n", iface); + + wined3d_mutex_lock(); + wined3d_texture_preload(texture->wined3d_texture); + wined3d_mutex_unlock(); +} + +static D3DRESOURCETYPE WINAPI d3d8_texture_3d_GetType(IDirect3DVolumeTexture8 *iface) +{ + TRACE("iface %p.\n", iface); + + return D3DRTYPE_VOLUMETEXTURE; +} + +static DWORD WINAPI d3d8_texture_3d_SetLOD(IDirect3DVolumeTexture8 *iface, DWORD lod) +{ + struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface); + DWORD ret; + + TRACE("iface %p, lod %u.\n", iface, lod); + + wined3d_mutex_lock(); + ret = wined3d_texture_set_lod(texture->wined3d_texture, lod); + wined3d_mutex_unlock(); + + return ret; +} + +static DWORD WINAPI d3d8_texture_3d_GetLOD(IDirect3DVolumeTexture8 *iface) +{ + struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface); + DWORD ret; + + TRACE("iface %p.\n", iface); + + wined3d_mutex_lock(); + ret = wined3d_texture_get_lod(texture->wined3d_texture); + wined3d_mutex_unlock(); + + return ret; +} + +static DWORD WINAPI d3d8_texture_3d_GetLevelCount(IDirect3DVolumeTexture8 *iface) +{ + struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface); + DWORD ret; + + TRACE("iface %p.\n", iface); + + wined3d_mutex_lock(); + ret = wined3d_texture_get_level_count(texture->wined3d_texture); + wined3d_mutex_unlock(); + + return ret; +} + +static HRESULT WINAPI d3d8_texture_3d_GetLevelDesc(IDirect3DVolumeTexture8 *iface, UINT level, D3DVOLUME_DESC *desc) +{ + struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface); + struct wined3d_resource *sub_resource; + HRESULT hr = D3D_OK; + + TRACE("iface %p, level %u, desc %p.\n", iface, level, desc); + + wined3d_mutex_lock(); + if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level))) + hr = D3DERR_INVALIDCALL; + else + { + struct wined3d_resource_desc wined3d_desc; + + wined3d_resource_get_desc(sub_resource, &wined3d_desc); + desc->Format = d3dformat_from_wined3dformat(wined3d_desc.format); + desc->Type = wined3d_desc.resource_type; + desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK; + desc->Pool = wined3d_desc.pool; + desc->Size = wined3d_desc.size; + desc->Width = wined3d_desc.width; + desc->Height = wined3d_desc.height; + desc->Depth = wined3d_desc.depth; + } + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_texture_3d_GetVolumeLevel(IDirect3DVolumeTexture8 *iface, + UINT level, IDirect3DVolume8 **volume) +{ + struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface); + struct wined3d_resource *sub_resource; + struct d3d8_volume *volume_impl; + + TRACE("iface %p, level %u, volume %p.\n", iface, level, volume); + + wined3d_mutex_lock(); + if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level))) + { + wined3d_mutex_unlock(); + return D3DERR_INVALIDCALL; + } + + volume_impl = wined3d_resource_get_parent(sub_resource); + *volume = &volume_impl->IDirect3DVolume8_iface; + IDirect3DVolume8_AddRef(*volume); + wined3d_mutex_unlock(); + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_texture_3d_LockBox(IDirect3DVolumeTexture8 *iface, + UINT level, D3DLOCKED_BOX *locked_box, const D3DBOX *box, DWORD flags) +{ + struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface); + struct wined3d_resource *sub_resource; + struct d3d8_volume *volume_impl; + HRESULT hr; + + TRACE("iface %p, level %u, locked_box %p, box %p, flags %#x.\n", + iface, level, locked_box, box, flags); + + wined3d_mutex_lock(); + if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level))) + hr = D3DERR_INVALIDCALL; + else + { + volume_impl = wined3d_resource_get_parent(sub_resource); + hr = IDirect3DVolume8_LockBox(&volume_impl->IDirect3DVolume8_iface, locked_box, box, flags); + } + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_texture_3d_UnlockBox(IDirect3DVolumeTexture8 *iface, UINT level) +{ + struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface); + struct wined3d_resource *sub_resource; + struct d3d8_volume *volume_impl; + HRESULT hr; + + TRACE("iface %p, level %u.\n", iface, level); + + wined3d_mutex_lock(); + if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level))) + hr = D3DERR_INVALIDCALL; + else + { + volume_impl = wined3d_resource_get_parent(sub_resource); + hr = IDirect3DVolume8_UnlockBox(&volume_impl->IDirect3DVolume8_iface); + } + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_texture_3d_AddDirtyBox(IDirect3DVolumeTexture8 *iface, const D3DBOX *dirty_box) +{ + struct d3d8_texture *texture = impl_from_IDirect3DVolumeTexture8(iface); + HRESULT hr; + + TRACE("iface %p, dirty_box %p.\n", iface, dirty_box); + + wined3d_mutex_lock(); + hr = wined3d_texture_add_dirty_region(texture->wined3d_texture, 0, (const struct wined3d_box *)dirty_box); + wined3d_mutex_unlock(); + + return hr; +} + +static const IDirect3DVolumeTexture8Vtbl Direct3DVolumeTexture8_Vtbl = +{ + /* IUnknown */ + d3d8_texture_3d_QueryInterface, + d3d8_texture_3d_AddRef, + d3d8_texture_3d_Release, + /* IDirect3DResource8 */ + d3d8_texture_3d_GetDevice, + d3d8_texture_3d_SetPrivateData, + d3d8_texture_3d_GetPrivateData, + d3d8_texture_3d_FreePrivateData, + d3d8_texture_3d_SetPriority, + d3d8_texture_3d_GetPriority, + d3d8_texture_3d_PreLoad, + d3d8_texture_3d_GetType, + /* IDirect3DBaseTexture8 */ + d3d8_texture_3d_SetLOD, + d3d8_texture_3d_GetLOD, + d3d8_texture_3d_GetLevelCount, + /* IDirect3DVolumeTexture8 */ + d3d8_texture_3d_GetLevelDesc, + d3d8_texture_3d_GetVolumeLevel, + d3d8_texture_3d_LockBox, + d3d8_texture_3d_UnlockBox, + d3d8_texture_3d_AddDirtyBox +}; + +struct d3d8_texture *unsafe_impl_from_IDirect3DBaseTexture8(IDirect3DBaseTexture8 *iface) +{ + if (!iface) + return NULL; + + /* SetTexture() in particular doesn't do a lot of validation on the pointer + * that gets passed in, and passing an invalid pointer works as long as the + * application doesn't try to actually render anything with it, so we print + * a WARN and return NULL instead of having the usual assert() here. + * One application affected by this is Fishdom 2. */ + if (iface->lpVtbl != (const IDirect3DBaseTexture8Vtbl *)&Direct3DTexture8_Vtbl + && iface->lpVtbl != (const IDirect3DBaseTexture8Vtbl *)&Direct3DCubeTexture8_Vtbl + && iface->lpVtbl != (const IDirect3DBaseTexture8Vtbl *)&Direct3DVolumeTexture8_Vtbl) + { + WARN("%p is not a valid IDirect3DBaseTexture8 interface.\n", iface); + return NULL; + } + + return CONTAINING_RECORD(iface, struct d3d8_texture, IDirect3DBaseTexture8_iface); +} + +static void STDMETHODCALLTYPE d3d8_texture_wined3d_object_destroyed(void *parent) +{ + HeapFree(GetProcessHeap(), 0, parent); +} + +static const struct wined3d_parent_ops d3d8_texture_wined3d_parent_ops = +{ + d3d8_texture_wined3d_object_destroyed, +}; + +HRESULT texture_init(struct d3d8_texture *texture, struct d3d8_device *device, + UINT width, UINT height, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool) +{ + struct wined3d_resource_desc desc; + DWORD surface_flags = 0; + HRESULT hr; + + texture->IDirect3DBaseTexture8_iface.lpVtbl = (const IDirect3DBaseTexture8Vtbl *)&Direct3DTexture8_Vtbl; + texture->refcount = 1; + + desc.resource_type = WINED3D_RTYPE_TEXTURE; + desc.format = wined3dformat_from_d3dformat(format); + desc.multisample_type = WINED3D_MULTISAMPLE_NONE; + desc.multisample_quality = 0; + desc.usage = usage & WINED3DUSAGE_MASK; + desc.pool = pool; + desc.width = width; + desc.height = height; + desc.depth = 1; + desc.size = 0; + + if (pool != D3DPOOL_DEFAULT || (usage & D3DUSAGE_DYNAMIC)) + surface_flags |= WINED3D_SURFACE_MAPPABLE; + + wined3d_mutex_lock(); + hr = wined3d_texture_create_2d(device->wined3d_device, &desc, levels, surface_flags, + texture, &d3d8_texture_wined3d_parent_ops, &texture->wined3d_texture); + wined3d_mutex_unlock(); + if (FAILED(hr)) + { + WARN("Failed to create wined3d texture, hr %#x.\n", hr); + return hr; + } + + texture->parent_device = &device->IDirect3DDevice8_iface; + IDirect3DDevice8_AddRef(texture->parent_device); + + return D3D_OK; +} + +HRESULT cubetexture_init(struct d3d8_texture *texture, struct d3d8_device *device, + UINT edge_length, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool) +{ + struct wined3d_resource_desc desc; + DWORD surface_flags = 0; + HRESULT hr; + + texture->IDirect3DBaseTexture8_iface.lpVtbl = (const IDirect3DBaseTexture8Vtbl *)&Direct3DCubeTexture8_Vtbl; + texture->refcount = 1; + + desc.resource_type = WINED3D_RTYPE_CUBE_TEXTURE; + desc.format = wined3dformat_from_d3dformat(format); + desc.multisample_type = WINED3D_MULTISAMPLE_NONE; + desc.multisample_quality = 0; + desc.usage = usage & WINED3DUSAGE_MASK; + desc.pool = pool; + desc.width = edge_length; + desc.height = edge_length; + desc.depth = 1; + desc.size = 0; + + if (pool != D3DPOOL_DEFAULT || (usage & D3DUSAGE_DYNAMIC)) + surface_flags |= WINED3D_SURFACE_MAPPABLE; + + wined3d_mutex_lock(); + hr = wined3d_texture_create_cube(device->wined3d_device, &desc, levels, surface_flags, + texture, &d3d8_texture_wined3d_parent_ops, &texture->wined3d_texture); + wined3d_mutex_unlock(); + if (FAILED(hr)) + { + WARN("Failed to create wined3d cube texture, hr %#x.\n", hr); + return hr; + } + + texture->parent_device = &device->IDirect3DDevice8_iface; + IDirect3DDevice8_AddRef(texture->parent_device); + + return D3D_OK; +} + +HRESULT volumetexture_init(struct d3d8_texture *texture, struct d3d8_device *device, + UINT width, UINT height, UINT depth, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool) +{ + struct wined3d_resource_desc desc; + HRESULT hr; + + texture->IDirect3DBaseTexture8_iface.lpVtbl = (const IDirect3DBaseTexture8Vtbl *)&Direct3DVolumeTexture8_Vtbl; + texture->refcount = 1; + + desc.resource_type = WINED3D_RTYPE_VOLUME_TEXTURE; + desc.format = wined3dformat_from_d3dformat(format); + desc.multisample_type = WINED3D_MULTISAMPLE_NONE; + desc.multisample_quality = 0; + desc.usage = usage & WINED3DUSAGE_MASK; + desc.pool = pool; + desc.width = width; + desc.height = height; + desc.depth = depth; + desc.size = 0; + + wined3d_mutex_lock(); + hr = wined3d_texture_create_3d(device->wined3d_device, &desc, levels, + texture, &d3d8_texture_wined3d_parent_ops, &texture->wined3d_texture); + wined3d_mutex_unlock(); + if (FAILED(hr)) + { + WARN("Failed to create wined3d volume texture, hr %#x.\n", hr); + return hr; + } + + texture->parent_device = &device->IDirect3DDevice8_iface; + IDirect3DDevice8_AddRef(texture->parent_device); + + return D3D_OK; +} diff --git a/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/version.rc b/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/version.rc new file mode 100644 index 00000000..c30a7b17 --- /dev/null +++ b/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/version.rc @@ -0,0 +1,35 @@ +/* + * Copyright 2001 Ove Kaaven + * + * 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 + */ + +/* + * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice + * other than GPL or LGPL is available it will apply instead, Oracle elects to use only + * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where + * a choice of LGPL license versions is made available with the language indicating + * that LGPLv2 or any later version may be used, or where a choice of which version + * of the LGPL is applied is otherwise unspecified. + */ + +#define WINE_FILEDESCRIPTION_STR "Wine Direct3D" +#define WINE_FILENAME_STR "d3d8.dll" +#define WINE_FILEVERSION 5,3,1,904 +#define WINE_FILEVERSION_STR "5.3.1.904" +#define WINE_PRODUCTVERSION 5,3,1,904 +#define WINE_PRODUCTVERSION_STR "5.3.1.904" + +#include "wine/wine_common_ver.rc" diff --git a/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/vertexdeclaration.c b/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/vertexdeclaration.c new file mode 100644 index 00000000..9934ca39 --- /dev/null +++ b/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/vertexdeclaration.c @@ -0,0 +1,400 @@ +/* + * IDirect3DVertexDeclaration8 implementation + * + * Copyright 2007 Henri Verbeet + * + * 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 + */ + +/* + * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice + * other than GPL or LGPL is available it will apply instead, Oracle elects to use only + * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where + * a choice of LGPL license versions is made available with the language indicating + * that LGPLv2 or any later version may be used, or where a choice of which version + * of the LGPL is applied is otherwise unspecified. + */ + +/* IDirect3DVertexDeclaration8 is internal to our implementation. + * It's not visible in the API. */ + +#include "config.h" +#include "d3d8_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(d3d8); + +#ifdef VBOX_WINE_WITHOUT_LIBWINE +typedef DWORD D3DVSDT_TYPE; +typedef DWORD D3DVSDE_REGISTER; +#endif + +static const char *debug_d3dvsdt_type(D3DVSDT_TYPE d3dvsdt_type) +{ + switch (d3dvsdt_type) + { +#define D3DVSDT_TYPE_TO_STR(u) case u: return #u + D3DVSDT_TYPE_TO_STR(D3DVSDT_FLOAT1); + D3DVSDT_TYPE_TO_STR(D3DVSDT_FLOAT2); + D3DVSDT_TYPE_TO_STR(D3DVSDT_FLOAT3); + D3DVSDT_TYPE_TO_STR(D3DVSDT_FLOAT4); + D3DVSDT_TYPE_TO_STR(D3DVSDT_D3DCOLOR); + D3DVSDT_TYPE_TO_STR(D3DVSDT_UBYTE4); + D3DVSDT_TYPE_TO_STR(D3DVSDT_SHORT2); + D3DVSDT_TYPE_TO_STR(D3DVSDT_SHORT4); +#undef D3DVSDT_TYPE_TO_STR + default: + FIXME("Unrecognized D3DVSDT_TYPE %#x\n", d3dvsdt_type); + return "unrecognized"; + } +} + +static const char *debug_d3dvsde_register(D3DVSDE_REGISTER d3dvsde_register) +{ + switch (d3dvsde_register) + { +#define D3DVSDE_REGISTER_TO_STR(u) case u: return #u + D3DVSDE_REGISTER_TO_STR(D3DVSDE_POSITION); + D3DVSDE_REGISTER_TO_STR(D3DVSDE_BLENDWEIGHT); + D3DVSDE_REGISTER_TO_STR(D3DVSDE_BLENDINDICES); + D3DVSDE_REGISTER_TO_STR(D3DVSDE_NORMAL); + D3DVSDE_REGISTER_TO_STR(D3DVSDE_PSIZE); + D3DVSDE_REGISTER_TO_STR(D3DVSDE_DIFFUSE); + D3DVSDE_REGISTER_TO_STR(D3DVSDE_SPECULAR); + D3DVSDE_REGISTER_TO_STR(D3DVSDE_TEXCOORD0); + D3DVSDE_REGISTER_TO_STR(D3DVSDE_TEXCOORD1); + D3DVSDE_REGISTER_TO_STR(D3DVSDE_TEXCOORD2); + D3DVSDE_REGISTER_TO_STR(D3DVSDE_TEXCOORD3); + D3DVSDE_REGISTER_TO_STR(D3DVSDE_TEXCOORD4); + D3DVSDE_REGISTER_TO_STR(D3DVSDE_TEXCOORD5); + D3DVSDE_REGISTER_TO_STR(D3DVSDE_TEXCOORD6); + D3DVSDE_REGISTER_TO_STR(D3DVSDE_TEXCOORD7); + D3DVSDE_REGISTER_TO_STR(D3DVSDE_POSITION2); + D3DVSDE_REGISTER_TO_STR(D3DVSDE_NORMAL2); +#undef D3DVSDE_REGISTER_TO_STR + default: + FIXME("Unrecognized D3DVSDE_REGISTER %#x\n", d3dvsde_register); + return "unrecognized"; + } +} + +size_t parse_token(const DWORD* pToken) +{ + const DWORD token = *pToken; + size_t tokenlen = 1; + + switch ((token & D3DVSD_TOKENTYPEMASK) >> D3DVSD_TOKENTYPESHIFT) { /* maybe a macro to inverse ... */ + case D3DVSD_TOKEN_NOP: + TRACE(" 0x%08x NOP()\n", token); + break; + + case D3DVSD_TOKEN_STREAM: + if (token & D3DVSD_STREAMTESSMASK) + { + TRACE(" 0x%08x STREAM_TESS()\n", token); + } else { + TRACE(" 0x%08x STREAM(%u)\n", token, ((token & D3DVSD_STREAMNUMBERMASK) >> D3DVSD_STREAMNUMBERSHIFT)); + } + break; + + case D3DVSD_TOKEN_STREAMDATA: + if (token & 0x10000000) + { + TRACE(" 0x%08x SKIP(%u)\n", token, ((token & D3DVSD_SKIPCOUNTMASK) >> D3DVSD_SKIPCOUNTSHIFT)); + } else { + DWORD type = ((token & D3DVSD_DATATYPEMASK) >> D3DVSD_DATATYPESHIFT); + DWORD reg = ((token & D3DVSD_VERTEXREGMASK) >> D3DVSD_VERTEXREGSHIFT); + TRACE(" 0x%08x REG(%s, %s)\n", token, debug_d3dvsde_register(reg), debug_d3dvsdt_type(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%08x TESSUV(%s) as %s\n", token, debug_d3dvsde_register(reg), debug_d3dvsdt_type(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%08x TESSNORMAL(%s, %s) as %s\n", token, debug_d3dvsde_register(regin), + debug_d3dvsde_register(regout), debug_d3dvsdt_type(type)); + } + break; + + case D3DVSD_TOKEN_CONSTMEM: + { + DWORD count = ((token & D3DVSD_CONSTCOUNTMASK) >> D3DVSD_CONSTCOUNTSHIFT); + 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%08x EXT(%u, %u)\n", token, count, extinfo); + /* todo ... print extension */ + tokenlen = count + 1; + } + break; + + case D3DVSD_TOKEN_END: + TRACE(" 0x%08x END()\n", token); + break; + + default: + TRACE(" 0x%08x UNKNOWN\n", token); + /* arg error */ + } + + return tokenlen; +} + +void load_local_constants(const DWORD *d3d8_elements, struct wined3d_shader *wined3d_vertex_shader) +{ + const DWORD *token = d3d8_elements; + + while (*token != D3DVSD_END()) + { + if (((*token & D3DVSD_TOKENTYPEMASK) >> D3DVSD_TOKENTYPESHIFT) == D3DVSD_TOKEN_CONSTMEM) + { + DWORD count = ((*token & D3DVSD_CONSTCOUNTMASK) >> D3DVSD_CONSTCOUNTSHIFT); + DWORD constant_idx = ((*token & D3DVSD_CONSTADDRESSMASK) >> D3DVSD_CONSTADDRESSSHIFT); + HRESULT hr; + + if (TRACE_ON(d3d8)) + { + DWORD i; + for (i = 0; i < count; ++i) + { + TRACE("c[%u] = (%8f, %8f, %8f, %8f)\n", + constant_idx, + *(const float *)(token + i * 4 + 1), + *(const float *)(token + i * 4 + 2), + *(const float *)(token + i * 4 + 3), + *(const float *)(token + i * 4 + 4)); + } + } + hr = wined3d_shader_set_local_constants_float(wined3d_vertex_shader, + constant_idx, (const float *)token + 1, count); + if (FAILED(hr)) ERR("Failed setting shader constants\n"); + } + + token += parse_token(token); + } +} + +/* NOTE: Make sure these are in the correct numerical order. (see /include/wined3d_types.h) */ +static const size_t wined3d_type_sizes[] = +{ + /*WINED3DDECLTYPE_FLOAT1*/ 1 * sizeof(float), + /*WINED3DDECLTYPE_FLOAT2*/ 2 * sizeof(float), + /*WINED3DDECLTYPE_FLOAT3*/ 3 * sizeof(float), + /*WINED3DDECLTYPE_FLOAT4*/ 4 * sizeof(float), + /*WINED3DDECLTYPE_D3DCOLOR*/ 4 * sizeof(BYTE), + /*WINED3DDECLTYPE_UBYTE4*/ 4 * sizeof(BYTE), + /*WINED3DDECLTYPE_SHORT2*/ 2 * sizeof(short int), + /*WINED3DDECLTYPE_SHORT4*/ 4 * sizeof(short int), + /*WINED3DDECLTYPE_UBYTE4N*/ 4 * sizeof(BYTE), + /*WINED3DDECLTYPE_SHORT2N*/ 2 * sizeof(short int), + /*WINED3DDECLTYPE_SHORT4N*/ 4 * sizeof(short int), + /*WINED3DDECLTYPE_USHORT2N*/ 2 * sizeof(short int), + /*WINED3DDECLTYPE_USHORT4N*/ 4 * sizeof(short int), + /*WINED3DDECLTYPE_UDEC3*/ 3 * sizeof(short int), + /*WINED3DDECLTYPE_DEC3N*/ 3 * sizeof(short int), + /*WINED3DDECLTYPE_FLOAT16_2*/ 2 * sizeof(short int), + /*WINED3DDECLTYPE_FLOAT16_4*/ 4 * sizeof(short int) +}; + +static const enum wined3d_format_id wined3d_format_lookup[] = +{ + /*WINED3DDECLTYPE_FLOAT1*/ WINED3DFMT_R32_FLOAT, + /*WINED3DDECLTYPE_FLOAT2*/ WINED3DFMT_R32G32_FLOAT, + /*WINED3DDECLTYPE_FLOAT3*/ WINED3DFMT_R32G32B32_FLOAT, + /*WINED3DDECLTYPE_FLOAT4*/ WINED3DFMT_R32G32B32A32_FLOAT, + /*WINED3DDECLTYPE_D3DCOLOR*/ WINED3DFMT_B8G8R8A8_UNORM, + /*WINED3DDECLTYPE_UBYTE4*/ WINED3DFMT_R8G8B8A8_UINT, + /*WINED3DDECLTYPE_SHORT2*/ WINED3DFMT_R16G16_SINT, + /*WINED3DDECLTYPE_SHORT4*/ WINED3DFMT_R16G16B16A16_SINT, + /*WINED3DDECLTYPE_UBYTE4N*/ WINED3DFMT_R8G8B8A8_UNORM, + /*WINED3DDECLTYPE_SHORT2N*/ WINED3DFMT_R16G16_SNORM, + /*WINED3DDECLTYPE_SHORT4N*/ WINED3DFMT_R16G16B16A16_SNORM, + /*WINED3DDECLTYPE_USHORT2N*/ WINED3DFMT_R16G16_UNORM, + /*WINED3DDECLTYPE_USHORT4N*/ WINED3DFMT_R16G16B16A16_UNORM, + /*WINED3DDECLTYPE_UDEC3*/ WINED3DFMT_R10G10B10A2_UINT, + /*WINED3DDECLTYPE_DEC3N*/ WINED3DFMT_R10G10B10A2_SNORM, + /*WINED3DDECLTYPE_FLOAT16_2*/ WINED3DFMT_R16G16_FLOAT, + /*WINED3DDECLTYPE_FLOAT16_4*/ WINED3DFMT_R16G16B16A16_FLOAT, +}; + +static const struct +{ + BYTE usage; + BYTE usage_idx; +} +wined3d_usage_lookup[] = +{ + /* D3DVSDE_POSITION */ {WINED3D_DECL_USAGE_POSITION, 0}, + /* D3DVSDE_BLENDWEIGHT */ {WINED3D_DECL_USAGE_BLEND_WEIGHT, 0}, + /* D3DVSDE_BLENDINDICES */ {WINED3D_DECL_USAGE_BLEND_INDICES, 0}, + /* D3DVSDE_NORMAL */ {WINED3D_DECL_USAGE_NORMAL, 0}, + /* D3DVSDE_PSIZE */ {WINED3D_DECL_USAGE_PSIZE, 0}, + /* D3DVSDE_DIFFUSE */ {WINED3D_DECL_USAGE_COLOR, 0}, + /* D3DVSDE_SPECULAR */ {WINED3D_DECL_USAGE_COLOR, 1}, + /* D3DVSDE_TEXCOORD0 */ {WINED3D_DECL_USAGE_TEXCOORD, 0}, + /* D3DVSDE_TEXCOORD1 */ {WINED3D_DECL_USAGE_TEXCOORD, 1}, + /* D3DVSDE_TEXCOORD2 */ {WINED3D_DECL_USAGE_TEXCOORD, 2}, + /* D3DVSDE_TEXCOORD3 */ {WINED3D_DECL_USAGE_TEXCOORD, 3}, + /* D3DVSDE_TEXCOORD4 */ {WINED3D_DECL_USAGE_TEXCOORD, 4}, + /* D3DVSDE_TEXCOORD5 */ {WINED3D_DECL_USAGE_TEXCOORD, 5}, + /* D3DVSDE_TEXCOORD6 */ {WINED3D_DECL_USAGE_TEXCOORD, 6}, + /* D3DVSDE_TEXCOORD7 */ {WINED3D_DECL_USAGE_TEXCOORD, 7}, + /* D3DVSDE_POSITION2 */ {WINED3D_DECL_USAGE_POSITION, 1}, + /* D3DVSDE_NORMAL2 */ {WINED3D_DECL_USAGE_NORMAL, 1}, +}; + +/* TODO: find out where rhw (or positionT) is for declaration8 */ +static UINT convert_to_wined3d_declaration(const DWORD *d3d8_elements, DWORD *d3d8_elements_size, + struct wined3d_vertex_element **wined3d_elements) +{ + struct wined3d_vertex_element *element; + const DWORD *token = d3d8_elements; + D3DVSD_TOKENTYPE token_type; + unsigned int element_count = 0; + WORD stream = 0; + int offset = 0; + + TRACE("d3d8_elements %p, wined3d_elements %p\n", d3d8_elements, wined3d_elements); + + /* 128 should be enough for anyone... */ + *wined3d_elements = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 128 * sizeof(**wined3d_elements)); + while (D3DVSD_END() != *token) + { + token_type = ((*token & D3DVSD_TOKENTYPEMASK) >> D3DVSD_TOKENTYPESHIFT); + + if (token_type == D3DVSD_TOKEN_STREAM && !(*token & D3DVSD_STREAMTESSMASK)) + { + stream = ((*token & D3DVSD_STREAMNUMBERMASK) >> D3DVSD_STREAMNUMBERSHIFT); + offset = 0; + } else if (token_type == D3DVSD_TOKEN_STREAMDATA && !(token_type & 0x10000000)) { + DWORD type = ((*token & D3DVSD_DATATYPEMASK) >> D3DVSD_DATATYPESHIFT); + DWORD reg = ((*token & D3DVSD_VERTEXREGMASK) >> D3DVSD_VERTEXREGSHIFT); + + TRACE("Adding element %d:\n", element_count); + + element = *wined3d_elements + element_count++; + element->format = wined3d_format_lookup[type]; + element->input_slot = stream; + element->offset = offset; + element->output_slot = reg; + element->method = WINED3D_DECL_METHOD_DEFAULT; + element->usage = wined3d_usage_lookup[reg].usage; + element->usage_idx = wined3d_usage_lookup[reg].usage_idx; + + offset += wined3d_type_sizes[type]; + } else if (token_type == D3DVSD_TOKEN_STREAMDATA && (token_type & 0x10000000)) { + TRACE(" 0x%08x SKIP(%u)\n", token_type, ((token_type & D3DVSD_SKIPCOUNTMASK) >> D3DVSD_SKIPCOUNTSHIFT)); + offset += sizeof(DWORD) * ((token_type & D3DVSD_SKIPCOUNTMASK) >> D3DVSD_SKIPCOUNTSHIFT); + } + + if (element_count >= 127) { + ERR("More than 127 elements?\n"); + break; + } + + token += parse_token(token); + } + + *d3d8_elements_size = (++token - d3d8_elements) * sizeof(DWORD); + + return element_count; +} + +static void STDMETHODCALLTYPE d3d8_vertexdeclaration_wined3d_object_destroyed(void *parent) +{ + struct d3d8_vertex_declaration *declaration = parent; + HeapFree(GetProcessHeap(), 0, declaration->elements); + HeapFree(GetProcessHeap(), 0, declaration); +} + +void d3d8_vertex_declaration_destroy(struct d3d8_vertex_declaration *declaration) +{ + TRACE("declaration %p.\n", declaration); + + wined3d_mutex_lock(); + wined3d_vertex_declaration_decref(declaration->wined3d_vertex_declaration); + wined3d_mutex_unlock(); +} + +static const struct wined3d_parent_ops d3d8_vertexdeclaration_wined3d_parent_ops = +{ + d3d8_vertexdeclaration_wined3d_object_destroyed, +}; + +HRESULT d3d8_vertex_declaration_init(struct d3d8_vertex_declaration *declaration, + struct d3d8_device *device, const DWORD *elements, DWORD shader_handle) +{ + struct wined3d_vertex_element *wined3d_elements; + UINT wined3d_element_count; + HRESULT hr; + + declaration->shader_handle = shader_handle; + + wined3d_element_count = convert_to_wined3d_declaration(elements, &declaration->elements_size, &wined3d_elements); + declaration->elements = HeapAlloc(GetProcessHeap(), 0, declaration->elements_size); + if (!declaration->elements) + { + ERR("Failed to allocate vertex declaration elements memory.\n"); + HeapFree(GetProcessHeap(), 0, wined3d_elements); + return E_OUTOFMEMORY; + } + + memcpy(declaration->elements, elements, declaration->elements_size); + + wined3d_mutex_lock(); + hr = wined3d_vertex_declaration_create(device->wined3d_device, wined3d_elements, wined3d_element_count, + declaration, &d3d8_vertexdeclaration_wined3d_parent_ops, &declaration->wined3d_vertex_declaration); + wined3d_mutex_unlock(); + HeapFree(GetProcessHeap(), 0, wined3d_elements); + if (FAILED(hr)) + { + WARN("Failed to create wined3d vertex declaration, hr %#x.\n", hr); + HeapFree(GetProcessHeap(), 0, declaration->elements); + return hr; + } + + return D3D_OK; +} + +HRESULT d3d8_vertex_declaration_init_fvf(struct d3d8_vertex_declaration *declaration, + struct d3d8_device *device, DWORD fvf) +{ + HRESULT hr; + + declaration->elements = NULL; + declaration->elements_size = 0; + declaration->shader_handle = fvf; + + hr = wined3d_vertex_declaration_create_from_fvf(device->wined3d_device, fvf, declaration, + &d3d8_vertexdeclaration_wined3d_parent_ops, &declaration->wined3d_vertex_declaration); + if (FAILED(hr)) + { + WARN("Failed to create wined3d vertex declaration, hr %#x.\n", hr); + return hr; + } + + return D3D_OK; +} diff --git a/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/volume.c b/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/volume.c new file mode 100644 index 00000000..6955d5ca --- /dev/null +++ b/src/VBox/Additions/WINNT/Graphics/Wine_new/d3d8/volume.c @@ -0,0 +1,312 @@ +/* + * IDirect3DVolume8 implementation + * + * Copyright 2005 Oliver Stieber + * + * 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 + */ + +/* + * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice + * other than GPL or LGPL is available it will apply instead, Oracle elects to use only + * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where + * a choice of LGPL license versions is made available with the language indicating + * that LGPLv2 or any later version may be used, or where a choice of which version + * of the LGPL is applied is otherwise unspecified. + */ + +#include "config.h" +#include "d3d8_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(d3d8); + +static inline struct d3d8_volume *impl_from_IDirect3DVolume8(IDirect3DVolume8 *iface) +{ + return CONTAINING_RECORD(iface, struct d3d8_volume, IDirect3DVolume8_iface); +} + +static HRESULT WINAPI d3d8_volume_QueryInterface(IDirect3DVolume8 *iface, REFIID riid, void **out) +{ + TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), out); + + if (IsEqualGUID(riid, &IID_IDirect3DVolume8) + || IsEqualGUID(riid, &IID_IUnknown)) + { + IDirect3DVolume8_AddRef(iface); + *out = iface; + return S_OK; + } + + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid)); + + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI d3d8_volume_AddRef(IDirect3DVolume8 *iface) +{ + struct d3d8_volume *volume = impl_from_IDirect3DVolume8(iface); + + TRACE("iface %p.\n", iface); + + if (volume->forwardReference) + { + /* Forward to the containerParent */ + TRACE("Forwarding to %p,\n", volume->forwardReference); + return IUnknown_AddRef(volume->forwardReference); + } + else + { + /* No container, handle our own refcounting */ + ULONG ref = InterlockedIncrement(&volume->refcount); + + TRACE("%p increasing refcount to %u.\n", iface, ref); + + if (ref == 1) + { + wined3d_mutex_lock(); + wined3d_volume_incref(volume->wined3d_volume); + wined3d_mutex_unlock(); + } + + return ref; + } +} + +static ULONG WINAPI d3d8_volume_Release(IDirect3DVolume8 *iface) +{ + struct d3d8_volume *volume = impl_from_IDirect3DVolume8(iface); + + TRACE("iface %p.\n", iface); + + if (volume->forwardReference) + { + /* Forward to the containerParent */ + TRACE("Forwarding to %p.\n", volume->forwardReference); + return IUnknown_Release(volume->forwardReference); + } + else + { + /* No container, handle our own refcounting */ + ULONG ref = InterlockedDecrement(&volume->refcount); + + TRACE("%p decreasing refcount to %u.\n", iface, ref); + + if (!ref) + { + wined3d_mutex_lock(); + wined3d_volume_decref(volume->wined3d_volume); + wined3d_mutex_unlock(); + } + + return ref; + } +} + +static HRESULT WINAPI d3d8_volume_GetDevice(IDirect3DVolume8 *iface, IDirect3DDevice8 **device) +{ + struct d3d8_volume *volume = impl_from_IDirect3DVolume8(iface); + IDirect3DResource8 *resource; + HRESULT hr; + + TRACE("iface %p, device %p.\n", iface, device); + + hr = IUnknown_QueryInterface(volume->forwardReference, &IID_IDirect3DResource8, (void **)&resource); + if (SUCCEEDED(hr)) + { + hr = IDirect3DResource8_GetDevice(resource, device); + IDirect3DResource8_Release(resource); + + TRACE("Returning device %p.\n", *device); + } + + return hr; +} + +static HRESULT WINAPI d3d8_volume_SetPrivateData(IDirect3DVolume8 *iface, REFGUID guid, + const void *data, DWORD data_size, DWORD flags) +{ + struct d3d8_volume *volume = impl_from_IDirect3DVolume8(iface); + struct wined3d_resource *resource; + HRESULT hr; + + TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n", + iface, debugstr_guid(guid), data, data_size, flags); + + wined3d_mutex_lock(); + resource = wined3d_volume_get_resource(volume->wined3d_volume); + hr = wined3d_resource_set_private_data(resource, guid, data, data_size, flags); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_volume_GetPrivateData(IDirect3DVolume8 *iface, REFGUID guid, + void *data, DWORD *data_size) +{ + struct d3d8_volume *volume = impl_from_IDirect3DVolume8(iface); + struct wined3d_resource *resource; + HRESULT hr; + + TRACE("iface %p, guid %s, data %p, data_size %p.\n", + iface, debugstr_guid(guid), data, data_size); + + wined3d_mutex_lock(); + resource = wined3d_volume_get_resource(volume->wined3d_volume); + hr = wined3d_resource_get_private_data(resource, guid, data, data_size); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_volume_FreePrivateData(IDirect3DVolume8 *iface, REFGUID guid) +{ + struct d3d8_volume *volume = impl_from_IDirect3DVolume8(iface); + struct wined3d_resource *resource; + HRESULT hr; + + TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid)); + + wined3d_mutex_lock(); + resource = wined3d_volume_get_resource(volume->wined3d_volume); + hr = wined3d_resource_free_private_data(resource, guid); + wined3d_mutex_unlock(); + + return hr; +} + +static HRESULT WINAPI d3d8_volume_GetContainer(IDirect3DVolume8 *iface, REFIID riid, void **container) +{ + struct d3d8_volume *volume = impl_from_IDirect3DVolume8(iface); + HRESULT res; + + TRACE("iface %p, riid %s, container %p.\n", + iface, debugstr_guid(riid), container); + + if (!volume->container) + return E_NOINTERFACE; + + res = IUnknown_QueryInterface(volume->container, riid, container); + + TRACE("Returning %p.\n", *container); + + return res; +} + +static HRESULT WINAPI d3d8_volume_GetDesc(IDirect3DVolume8 *iface, D3DVOLUME_DESC *desc) +{ + struct d3d8_volume *volume = impl_from_IDirect3DVolume8(iface); + struct wined3d_resource_desc wined3d_desc; + struct wined3d_resource *wined3d_resource; + + TRACE("iface %p, desc %p.\n", iface, desc); + + wined3d_mutex_lock(); + wined3d_resource = wined3d_volume_get_resource(volume->wined3d_volume); + wined3d_resource_get_desc(wined3d_resource, &wined3d_desc); + wined3d_mutex_unlock(); + + desc->Format = d3dformat_from_wined3dformat(wined3d_desc.format); + desc->Type = wined3d_desc.resource_type; + desc->Usage = wined3d_desc.usage & WINED3DUSAGE_MASK; + desc->Pool = wined3d_desc.pool; + desc->Size = wined3d_desc.size; + desc->Width = wined3d_desc.width; + desc->Height = wined3d_desc.height; + desc->Depth = wined3d_desc.depth; + + return D3D_OK; +} + +static HRESULT WINAPI d3d8_volume_LockBox(IDirect3DVolume8 *iface, + D3DLOCKED_BOX *locked_box, const D3DBOX *box, DWORD flags) +{ + struct d3d8_volume *volume = impl_from_IDirect3DVolume8(iface); + struct wined3d_map_desc map_desc; + HRESULT hr; + + TRACE("iface %p, locked_box %p, box %p, flags %#x.\n", + iface, locked_box, box, flags); + + wined3d_mutex_lock(); + hr = wined3d_volume_map(volume->wined3d_volume, &map_desc, (const struct wined3d_box *)box, flags); + wined3d_mutex_unlock(); + + locked_box->RowPitch = map_desc.row_pitch; + locked_box->SlicePitch = map_desc.slice_pitch; + locked_box->pBits = map_desc.data; + + return hr; +} + +static HRESULT WINAPI d3d8_volume_UnlockBox(IDirect3DVolume8 *iface) +{ + struct d3d8_volume *volume = impl_from_IDirect3DVolume8(iface); + HRESULT hr; + + TRACE("iface %p.\n", iface); + + wined3d_mutex_lock(); + hr = wined3d_volume_unmap(volume->wined3d_volume); + wined3d_mutex_unlock(); + + return hr; +} + +static const IDirect3DVolume8Vtbl d3d8_volume_vtbl = +{ + /* IUnknown */ + d3d8_volume_QueryInterface, + d3d8_volume_AddRef, + d3d8_volume_Release, + /* IDirect3DVolume8 */ + d3d8_volume_GetDevice, + d3d8_volume_SetPrivateData, + d3d8_volume_GetPrivateData, + d3d8_volume_FreePrivateData, + d3d8_volume_GetContainer, + d3d8_volume_GetDesc, + d3d8_volume_LockBox, + d3d8_volume_UnlockBox, +}; + +static void STDMETHODCALLTYPE volume_wined3d_object_destroyed(void *parent) +{ + HeapFree(GetProcessHeap(), 0, parent); +} + +static const struct wined3d_parent_ops d3d8_volume_wined3d_parent_ops = +{ + volume_wined3d_object_destroyed, +}; + +HRESULT volume_init(struct d3d8_volume *volume, struct d3d8_device *device, UINT width, UINT height, + UINT depth, DWORD usage, enum wined3d_format_id format, enum wined3d_pool pool) +{ + HRESULT hr; + + volume->IDirect3DVolume8_iface.lpVtbl = &d3d8_volume_vtbl; + volume->refcount = 1; + + hr = wined3d_volume_create(device->wined3d_device, width, height, depth, usage, + format, pool, volume, &d3d8_volume_wined3d_parent_ops, &volume->wined3d_volume); + if (FAILED(hr)) + { + WARN("Failed to create wined3d volume, hr %#x.\n", hr); + return hr; + } + + return D3D_OK; +} |
