[AMSTREAM] We don't need to define WIDL_C_INLINE_WRAPPERS here anymore.
[reactos.git] / dll / directx / wine / d3d9 / vertexdeclaration.c
index 6224614..e9248be 100644 (file)
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#include "config.h"
 #include "d3d9_private.h"
 
-WINE_DEFAULT_DEBUG_CHANNEL(d3d9);
-
-typedef struct _D3DDECLTYPE_INFO {
-    D3DDECLTYPE d3dType;
+static const struct
+{
     enum wined3d_format_id format;
-    int         size;
-    int         typesize;
-} D3DDECLTYPE_INFO;
-
-static D3DDECLTYPE_INFO const d3d_dtype_lookup[D3DDECLTYPE_UNUSED] = {
-   {D3DDECLTYPE_FLOAT1,    WINED3DFMT_R32_FLOAT,          1, sizeof(float)},
-   {D3DDECLTYPE_FLOAT2,    WINED3DFMT_R32G32_FLOAT,       2, sizeof(float)},
-   {D3DDECLTYPE_FLOAT3,    WINED3DFMT_R32G32B32_FLOAT,    3, sizeof(float)},
-   {D3DDECLTYPE_FLOAT4,    WINED3DFMT_R32G32B32A32_FLOAT, 4, sizeof(float)},
-   {D3DDECLTYPE_D3DCOLOR,  WINED3DFMT_B8G8R8A8_UNORM,     4, sizeof(BYTE)},
-   {D3DDECLTYPE_UBYTE4,    WINED3DFMT_R8G8B8A8_UINT,      4, sizeof(BYTE)},
-   {D3DDECLTYPE_SHORT2,    WINED3DFMT_R16G16_SINT,        2, sizeof(short int)},
-   {D3DDECLTYPE_SHORT4,    WINED3DFMT_R16G16B16A16_SINT,  4, sizeof(short int)},
-   {D3DDECLTYPE_UBYTE4N,   WINED3DFMT_R8G8B8A8_UNORM,     4, sizeof(BYTE)},
-   {D3DDECLTYPE_SHORT2N,   WINED3DFMT_R16G16_SNORM,       2, sizeof(short int)},
-   {D3DDECLTYPE_SHORT4N,   WINED3DFMT_R16G16B16A16_SNORM, 4, sizeof(short int)},
-   {D3DDECLTYPE_USHORT2N,  WINED3DFMT_R16G16_UNORM,       2, sizeof(short int)},
-   {D3DDECLTYPE_USHORT4N,  WINED3DFMT_R16G16B16A16_UNORM, 4, sizeof(short int)},
-   {D3DDECLTYPE_UDEC3,     WINED3DFMT_R10G10B10A2_UINT,   3, sizeof(short int)},
-   {D3DDECLTYPE_DEC3N,     WINED3DFMT_R10G10B10A2_SNORM,  3, sizeof(short int)},
-   {D3DDECLTYPE_FLOAT16_2, WINED3DFMT_R16G16_FLOAT,       2, sizeof(short int)},
-   {D3DDECLTYPE_FLOAT16_4, WINED3DFMT_R16G16B16A16_FLOAT, 4, sizeof(short int)}};
-
-#define D3D_DECL_SIZE(type)          d3d_dtype_lookup[type].size
-#define D3D_DECL_TYPESIZE(type)      d3d_dtype_lookup[type].typesize
+    unsigned int component_count;
+    unsigned int component_size;
+}
+d3d_dtype_lookup[] =
+{
+    /* D3DDECLTYPE_FLOAT1    */ {WINED3DFMT_R32_FLOAT,          1, sizeof(float)},
+    /* D3DDECLTYPE_FLOAT2    */ {WINED3DFMT_R32G32_FLOAT,       2, sizeof(float)},
+    /* D3DDECLTYPE_FLOAT3    */ {WINED3DFMT_R32G32B32_FLOAT,    3, sizeof(float)},
+    /* D3DDECLTYPE_FLOAT4    */ {WINED3DFMT_R32G32B32A32_FLOAT, 4, sizeof(float)},
+    /* D3DDECLTYPE_D3DCOLOR  */ {WINED3DFMT_B8G8R8A8_UNORM,     4, sizeof(BYTE)},
+    /* D3DDECLTYPE_UBYTE4    */ {WINED3DFMT_R8G8B8A8_UINT,      4, sizeof(BYTE)},
+    /* D3DDECLTYPE_SHORT2    */ {WINED3DFMT_R16G16_SINT,        2, sizeof(short int)},
+    /* D3DDECLTYPE_SHORT4    */ {WINED3DFMT_R16G16B16A16_SINT,  4, sizeof(short int)},
+    /* D3DDECLTYPE_UBYTE4N   */ {WINED3DFMT_R8G8B8A8_UNORM,     4, sizeof(BYTE)},
+    /* D3DDECLTYPE_SHORT2N   */ {WINED3DFMT_R16G16_SNORM,       2, sizeof(short int)},
+    /* D3DDECLTYPE_SHORT4N   */ {WINED3DFMT_R16G16B16A16_SNORM, 4, sizeof(short int)},
+    /* D3DDECLTYPE_USHORT2N  */ {WINED3DFMT_R16G16_UNORM,       2, sizeof(short int)},
+    /* D3DDECLTYPE_USHORT4N  */ {WINED3DFMT_R16G16B16A16_UNORM, 4, sizeof(short int)},
+    /* D3DDECLTYPE_UDEC3     */ {WINED3DFMT_R10G10B10X2_UINT,   3, sizeof(short int)},
+    /* D3DDECLTYPE_DEC3N     */ {WINED3DFMT_R10G10B10X2_SNORM,  3, sizeof(short int)},
+    /* D3DDECLTYPE_FLOAT16_2 */ {WINED3DFMT_R16G16_FLOAT,       2, sizeof(short int)},
+    /* D3DDECLTYPE_FLOAT16_4 */ {WINED3DFMT_R16G16B16A16_FLOAT, 4, sizeof(short int)}
+};
+
+static inline struct d3d9_vertex_declaration *impl_from_IDirect3DVertexDeclaration9(IDirect3DVertexDeclaration9 *iface)
+{
+    return CONTAINING_RECORD(iface, struct d3d9_vertex_declaration, IDirect3DVertexDeclaration9_iface);
+}
 
 HRESULT vdecl_convert_fvf(
     DWORD fvf,
@@ -186,91 +186,79 @@ HRESULT vdecl_convert_fvf(
         elements[idx].Stream = 0;
         elements[idx].Method = D3DDECLMETHOD_DEFAULT;
         elements[idx].Offset = offset;
-        offset += D3D_DECL_SIZE(elements[idx].Type) * D3D_DECL_TYPESIZE(elements[idx].Type);
+        offset += d3d_dtype_lookup[elements[idx].Type].component_count
+                * d3d_dtype_lookup[elements[idx].Type].component_size;
     }
 
     *ppVertexElements = elements;
     return D3D_OK;
 }
 
-/* IDirect3DVertexDeclaration9 IUnknown parts follow: */
-static HRESULT WINAPI IDirect3DVertexDeclaration9Impl_QueryInterface(LPDIRECT3DVERTEXDECLARATION9 iface, REFIID riid, LPVOID* ppobj) {
-    IDirect3DVertexDeclaration9Impl *This = (IDirect3DVertexDeclaration9Impl *)iface;
-
-    TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), ppobj);
+static HRESULT WINAPI d3d9_vertex_declaration_QueryInterface(IDirect3DVertexDeclaration9 *iface,
+        REFIID riid, void **out)
+{
+    TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
 
-    if (IsEqualGUID(riid, &IID_IUnknown)
-        || IsEqualGUID(riid, &IID_IDirect3DVertexDeclaration9)) {
+    if (IsEqualGUID(riid, &IID_IDirect3DVertexDeclaration9)
+            || IsEqualGUID(riid, &IID_IUnknown))
+    {
         IDirect3DVertexDeclaration9_AddRef(iface);
-        *ppobj = This;
+        *out = iface;
         return S_OK;
     }
 
-    WARN("(%p)->(%s,%p),not found\n", This, debugstr_guid(riid), ppobj);
-    *ppobj = NULL;
+    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+
+    *out = NULL;
     return E_NOINTERFACE;
 }
 
-static ULONG WINAPI IDirect3DVertexDeclaration9Impl_AddRef(LPDIRECT3DVERTEXDECLARATION9 iface) {
-    IDirect3DVertexDeclaration9Impl *This = (IDirect3DVertexDeclaration9Impl *)iface;
-    ULONG ref = InterlockedIncrement(&This->ref);
-
-    TRACE("%p increasing refcount to %u.\n", iface, ref);
-
-    if(ref == 1) {
-        IDirect3DDevice9Ex_AddRef(This->parentDevice);
-        if (!This->convFVF)
-        {
-            wined3d_mutex_lock();
-            wined3d_vertex_declaration_incref(This->wineD3DVertexDeclaration);
-            wined3d_mutex_unlock();
-        }
-    }
-
-    return ref;
-}
+static ULONG WINAPI d3d9_vertex_declaration_AddRef(IDirect3DVertexDeclaration9 *iface)
+{
+    struct d3d9_vertex_declaration *declaration = impl_from_IDirect3DVertexDeclaration9(iface);
+    ULONG refcount = InterlockedIncrement(&declaration->refcount);
 
-void IDirect3DVertexDeclaration9Impl_Destroy(LPDIRECT3DVERTEXDECLARATION9 iface) {
-    IDirect3DVertexDeclaration9Impl *This = (IDirect3DVertexDeclaration9Impl *)iface;
+    TRACE("%p increasing refcount to %u.\n", iface, refcount);
 
-    if(This->ref != 0) {
-        /* Should not happen unless wine has a bug or the application releases references it does not own */
-        ERR("Destroying vdecl with ref != 0\n");
+    if (refcount == 1)
+    {
+        IDirect3DDevice9Ex_AddRef(declaration->parent_device);
+        wined3d_mutex_lock();
+        wined3d_vertex_declaration_incref(declaration->wined3d_declaration);
+        wined3d_mutex_unlock();
     }
 
-    wined3d_mutex_lock();
-    wined3d_vertex_declaration_decref(This->wineD3DVertexDeclaration);
-    wined3d_mutex_unlock();
+    return refcount;
 }
 
-static ULONG WINAPI IDirect3DVertexDeclaration9Impl_Release(LPDIRECT3DVERTEXDECLARATION9 iface) {
-    IDirect3DVertexDeclaration9Impl *This = (IDirect3DVertexDeclaration9Impl *)iface;
-    ULONG ref = InterlockedDecrement(&This->ref);
-
-    TRACE("%p decreasing refcount to %u.\n", iface, ref);
+static ULONG WINAPI d3d9_vertex_declaration_Release(IDirect3DVertexDeclaration9 *iface)
+{
+    struct d3d9_vertex_declaration *declaration = impl_from_IDirect3DVertexDeclaration9(iface);
+    ULONG refcount = InterlockedDecrement(&declaration->refcount);
 
-    if (ref == 0) {
-        IDirect3DDevice9Ex *parentDevice = This->parentDevice;
+    TRACE("%p decreasing refcount to %u.\n", iface, refcount);
 
-        if(!This->convFVF) {
-            IDirect3DVertexDeclaration9Impl_Destroy(iface);
-        }
+    if (!refcount)
+    {
+        IDirect3DDevice9Ex *parent_device = declaration->parent_device;
+        wined3d_mutex_lock();
+        wined3d_vertex_declaration_decref(declaration->wined3d_declaration);
+        wined3d_mutex_unlock();
 
         /* Release the device last, as it may cause the device to be destroyed. */
-        IDirect3DDevice9Ex_Release(parentDevice);
+        IDirect3DDevice9Ex_Release(parent_device);
     }
-    return ref;
+
+    return refcount;
 }
 
-/* IDirect3DVertexDeclaration9 Interface follow: */
-static HRESULT WINAPI IDirect3DVertexDeclaration9Impl_GetDevice(IDirect3DVertexDeclaration9 *iface,
-        IDirect3DDevice9 **device)
+static HRESULT WINAPI d3d9_vertex_declaration_GetDevice(IDirect3DVertexDeclaration9 *iface, IDirect3DDevice9 **device)
 {
-    IDirect3DVertexDeclaration9Impl *This = (IDirect3DVertexDeclaration9Impl *)iface;
+    struct d3d9_vertex_declaration *declaration = impl_from_IDirect3DVertexDeclaration9(iface);
 
     TRACE("iface %p, device %p.\n", iface, device);
 
-    *device = (IDirect3DDevice9 *)This->parentDevice;
+    *device = (IDirect3DDevice9 *)declaration->parent_device;
     IDirect3DDevice9_AddRef(*device);
 
     TRACE("Returning device %p.\n", *device);
@@ -278,39 +266,47 @@ static HRESULT WINAPI IDirect3DVertexDeclaration9Impl_GetDevice(IDirect3DVertexD
     return D3D_OK;
 }
 
-static HRESULT WINAPI IDirect3DVertexDeclaration9Impl_GetDeclaration(LPDIRECT3DVERTEXDECLARATION9 iface, D3DVERTEXELEMENT9* pDecl, UINT* pNumElements) {
-    IDirect3DVertexDeclaration9Impl *This = (IDirect3DVertexDeclaration9Impl *)iface;
+static HRESULT WINAPI d3d9_vertex_declaration_GetDeclaration(IDirect3DVertexDeclaration9 *iface,
+        D3DVERTEXELEMENT9 *elements, UINT *element_count)
+{
+    struct d3d9_vertex_declaration *declaration = impl_from_IDirect3DVertexDeclaration9(iface);
 
-    TRACE("iface %p, elements %p, element_count %p.\n", iface, pDecl, pNumElements);
+    TRACE("iface %p, elements %p, element_count %p.\n", iface, elements, element_count);
 
-    *pNumElements = This->element_count;
+    *element_count = declaration->element_count;
 
-    /* Passing a NULL pDecl is used to just retrieve the number of elements */
-    if (!pDecl) {
-        TRACE("NULL pDecl passed. Returning D3D_OK.\n");
+    /* Passing a NULL elements is used to just retrieve the number of elements */
+    if (!elements)
         return D3D_OK;
-    }
 
-    TRACE("Copying %p to %p\n", This->elements, pDecl);
-    CopyMemory(pDecl, This->elements, This->element_count * sizeof(D3DVERTEXELEMENT9));
+    TRACE("Copying %p to %p.\n", declaration->elements, elements);
+    memcpy(elements, declaration->elements, sizeof(*declaration->elements) * declaration->element_count);
 
     return D3D_OK;
 }
 
-static const IDirect3DVertexDeclaration9Vtbl Direct3DVertexDeclaration9_Vtbl =
+static const struct IDirect3DVertexDeclaration9Vtbl d3d9_vertex_declaration_vtbl =
 {
     /* IUnknown */
-    IDirect3DVertexDeclaration9Impl_QueryInterface,
-    IDirect3DVertexDeclaration9Impl_AddRef,
-    IDirect3DVertexDeclaration9Impl_Release,
+    d3d9_vertex_declaration_QueryInterface,
+    d3d9_vertex_declaration_AddRef,
+    d3d9_vertex_declaration_Release,
     /* IDirect3DVertexDeclaration9 */
-    IDirect3DVertexDeclaration9Impl_GetDevice,
-    IDirect3DVertexDeclaration9Impl_GetDeclaration
+    d3d9_vertex_declaration_GetDevice,
+    d3d9_vertex_declaration_GetDeclaration,
 };
 
+struct d3d9_vertex_declaration *unsafe_impl_from_IDirect3DVertexDeclaration9(IDirect3DVertexDeclaration9 *iface)
+{
+    if (!iface)
+        return NULL;
+    assert(iface->lpVtbl == &d3d9_vertex_declaration_vtbl);
+    return CONTAINING_RECORD(iface, struct d3d9_vertex_declaration, IDirect3DVertexDeclaration9_iface);
+}
+
 static void STDMETHODCALLTYPE d3d9_vertexdeclaration_wined3d_object_destroyed(void *parent)
 {
-    IDirect3DVertexDeclaration9Impl *declaration = parent;
+    struct d3d9_vertex_declaration *declaration = parent;
     HeapFree(GetProcessHeap(), 0, declaration->elements);
     HeapFree(GetProcessHeap(), 0, declaration);
 }
@@ -320,14 +316,14 @@ static const struct wined3d_parent_ops d3d9_vertexdeclaration_wined3d_parent_ops
     d3d9_vertexdeclaration_wined3d_object_destroyed,
 };
 
-static HRESULT convert_to_wined3d_declaration(const D3DVERTEXELEMENT9d3d9_elements,
-        WINED3DVERTEXELEMENT **wined3d_elements, UINT *element_count)
+static HRESULT convert_to_wined3d_declaration(const D3DVERTEXELEMENT9 *d3d9_elements,
+        struct wined3d_vertex_element **wined3d_elements, UINT *element_count)
 {
     const D3DVERTEXELEMENT9* element;
     UINT count = 1;
     UINT i;
 
-    TRACE("d3d9_elements %p, wined3d_elements %p\n", d3d9_elements, wined3d_elements);
+    TRACE("d3d9_elements %p, wined3d_elements %p, element_count %p\n", d3d9_elements, wined3d_elements, element_count);
 
     element = d3d9_elements;
     while (element++->Stream != 0xff && count++ < 128);
@@ -337,7 +333,7 @@ static HRESULT convert_to_wined3d_declaration(const D3DVERTEXELEMENT9* d3d9_elem
     /* Skip the END element */
     --count;
 
-    *wined3d_elements = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WINED3DVERTEXELEMENT));
+    *wined3d_elements = HeapAlloc(GetProcessHeap(), 0, count * sizeof(**wined3d_elements));
     if (!*wined3d_elements) {
         FIXME("Memory allocation failed\n");
         return D3DERR_OUTOFVIDEOMEMORY;
@@ -354,7 +350,9 @@ static HRESULT convert_to_wined3d_declaration(const D3DVERTEXELEMENT9* d3d9_elem
         (*wined3d_elements)[i].format = d3d_dtype_lookup[d3d9_elements[i].Type].format;
         (*wined3d_elements)[i].input_slot = d3d9_elements[i].Stream;
         (*wined3d_elements)[i].offset = d3d9_elements[i].Offset;
-        (*wined3d_elements)[i].output_slot = ~0U;
+        (*wined3d_elements)[i].output_slot = WINED3D_OUTPUT_SLOT_SEMANTIC;
+        (*wined3d_elements)[i].input_slot_class = WINED3D_INPUT_PER_VERTEX_DATA;
+        (*wined3d_elements)[i].instance_data_step_rate = 0;
         (*wined3d_elements)[i].method = d3d9_elements[i].Method;
         (*wined3d_elements)[i].usage = d3d9_elements[i].Usage;
         (*wined3d_elements)[i].usage_idx = d3d9_elements[i].UsageIndex;
@@ -365,10 +363,10 @@ static HRESULT convert_to_wined3d_declaration(const D3DVERTEXELEMENT9* d3d9_elem
     return D3D_OK;
 }
 
-HRESULT vertexdeclaration_init(IDirect3DVertexDeclaration9Impl *declaration,
-        IDirect3DDevice9Impl *device, const D3DVERTEXELEMENT9 *elements)
+static HRESULT vertexdeclaration_init(struct d3d9_vertex_declaration *declaration,
+        struct d3d9_device *device, const D3DVERTEXELEMENT9 *elements)
 {
-    WINED3DVERTEXELEMENT *wined3d_elements;
+    struct wined3d_vertex_element *wined3d_elements;
     UINT wined3d_element_count;
     UINT element_count;
     HRESULT hr;
@@ -380,8 +378,8 @@ HRESULT vertexdeclaration_init(IDirect3DVertexDeclaration9Impl *declaration,
         return hr;
     }
 
-    declaration->lpVtbl = &Direct3DVertexDeclaration9_Vtbl;
-    declaration->ref = 1;
+    declaration->IDirect3DVertexDeclaration9_iface.lpVtbl = &d3d9_vertex_declaration_vtbl;
+    declaration->refcount = 1;
 
     element_count = wined3d_element_count + 1;
     declaration->elements = HeapAlloc(GetProcessHeap(), 0, element_count * sizeof(*declaration->elements));
@@ -396,7 +394,7 @@ HRESULT vertexdeclaration_init(IDirect3DVertexDeclaration9Impl *declaration,
 
     wined3d_mutex_lock();
     hr = wined3d_vertex_declaration_create(device->wined3d_device, wined3d_elements, wined3d_element_count,
-            declaration, &d3d9_vertexdeclaration_wined3d_parent_ops, &declaration->wineD3DVertexDeclaration);
+            declaration, &d3d9_vertexdeclaration_wined3d_parent_ops, &declaration->wined3d_declaration);
     wined3d_mutex_unlock();
     HeapFree(GetProcessHeap(), 0, wined3d_elements);
     if (FAILED(hr))
@@ -406,8 +404,32 @@ HRESULT vertexdeclaration_init(IDirect3DVertexDeclaration9Impl *declaration,
         return hr;
     }
 
-    declaration->parentDevice = &device->IDirect3DDevice9Ex_iface;
-    IDirect3DDevice9Ex_AddRef(declaration->parentDevice);
+    declaration->parent_device = &device->IDirect3DDevice9Ex_iface;
+    IDirect3DDevice9Ex_AddRef(declaration->parent_device);
+
+    return D3D_OK;
+}
+
+HRESULT d3d9_vertex_declaration_create(struct d3d9_device *device,
+        const D3DVERTEXELEMENT9 *elements, struct d3d9_vertex_declaration **declaration)
+{
+    struct d3d9_vertex_declaration *object;
+    HRESULT hr;
+
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+    if (!object)
+        return E_OUTOFMEMORY;
+
+    hr = vertexdeclaration_init(object, device, elements);
+    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);
+    *declaration = object;
 
     return D3D_OK;
 }