- sync d3d8 with wine HEAD
[reactos.git] / reactos / dll / directx / wine / d3d8 / device.c
index f9a0150..5ef6311 100644 (file)
@@ -73,6 +73,13 @@ static HRESULT WINAPI IDirect3DDevice8Impl_QueryInterface(LPDIRECT3DDEVICE8 ifac
         return S_OK;
     }
 
+    if (IsEqualGUID(riid, &IID_IWineD3DDeviceParent))
+    {
+        IUnknown_AddRef((IUnknown *)&This->device_parent_vtbl);
+        *ppobj = &This->device_parent_vtbl;
+        return S_OK;
+    }
+
     WARN("(%p)->(%s,%p),not found\n", This, debugstr_guid(riid), ppobj);
     *ppobj = NULL;
     return E_NOINTERFACE;
@@ -104,7 +111,7 @@ static ULONG WINAPI IDirect3DDevice8Impl_Release(LPDIRECT3DDEVICE8 iface) {
         This->inDestruction = TRUE;
 
         for(i = 0; i < This->numConvertedDecls; i++) {
-            IWineD3DVertexDeclaration_Release(This->decls[i].decl);
+            IDirect3DVertexDeclaration8_Release(This->decls[i].decl);
         }
         HeapFree(GetProcessHeap(), 0, This->decls);
 
@@ -308,7 +315,8 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateAdditionalSwapChain(LPDIRECT3DD
     localParameters.AutoRestoreDisplayMode                      = TRUE;
 
     EnterCriticalSection(&d3d8_cs);
-    hrc = IWineD3DDevice_CreateSwapChain(This->WineD3DDevice, &localParameters, &object->wineD3DSwapChain, (IUnknown*)object, D3D8CB_CreateRenderTarget, D3D8CB_CreateDepthStencilSurface, SURFACE_OPENGL);
+    hrc = IWineD3DDevice_CreateSwapChain(This->WineD3DDevice, &localParameters,
+            &object->wineD3DSwapChain, (IUnknown *)object, SURFACE_OPENGL);
     LeaveCriticalSection(&d3d8_cs);
 
     pPresentationParameters->BackBufferWidth                    = localParameters.BackBufferWidth;
@@ -462,7 +470,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateTexture(LPDIRECT3DDEVICE8 iface
     object->ref = 1;
     EnterCriticalSection(&d3d8_cs);
     hrc = IWineD3DDevice_CreateTexture(This->WineD3DDevice, Width, Height, Levels, Usage & WINED3DUSAGE_MASK,
-                                 (WINED3DFORMAT)Format, (WINED3DPOOL) Pool, &object->wineD3DTexture, NULL, (IUnknown *)object, D3D8CB_CreateSurface);
+            Format, Pool, &object->wineD3DTexture, NULL, (IUnknown *)object);
     LeaveCriticalSection(&d3d8_cs);
 
     if (FAILED(hrc)) {
@@ -501,9 +509,8 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateVolumeTexture(LPDIRECT3DDEVICE8
     object->lpVtbl = &Direct3DVolumeTexture8_Vtbl;
     object->ref = 1;
     EnterCriticalSection(&d3d8_cs);
-    hrc = IWineD3DDevice_CreateVolumeTexture(This->WineD3DDevice, Width, Height, Depth, Levels, Usage & WINED3DUSAGE_MASK,
-                                 (WINED3DFORMAT)Format, (WINED3DPOOL) Pool, &object->wineD3DVolumeTexture, NULL,
-                                 (IUnknown *)object, D3D8CB_CreateVolume);
+    hrc = IWineD3DDevice_CreateVolumeTexture(This->WineD3DDevice, Width, Height, Depth, Levels,
+            Usage & WINED3DUSAGE_MASK, Format, Pool, &object->wineD3DVolumeTexture, NULL, (IUnknown *)object);
     LeaveCriticalSection(&d3d8_cs);
 
     if (hrc != D3D_OK) {
@@ -543,8 +550,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateCubeTexture(LPDIRECT3DDEVICE8 i
     object->ref = 1;
     EnterCriticalSection(&d3d8_cs);
     hr = IWineD3DDevice_CreateCubeTexture(This->WineD3DDevice, EdgeLength, Levels, Usage & WINED3DUSAGE_MASK,
-                                 (WINED3DFORMAT)Format, (WINED3DPOOL) Pool, &object->wineD3DCubeTexture, NULL, (IUnknown*)object,
-                                 D3D8CB_CreateSurface);
+            Format, Pool, &object->wineD3DCubeTexture, NULL, (IUnknown *)object);
     LeaveCriticalSection(&d3d8_cs);
 
     if (hr != D3D_OK){
@@ -761,11 +767,11 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CopyRects(LPDIRECT3DDEVICE8 iface, ID
         /* Copy rect by rect */
         if (NULL != pSourceRects && NULL != pDestPoints) {
             for (i = 0; i < cRects; ++i) {
-                IWineD3DSurface_BltFast(Dest->wineD3DSurface, pDestPoints[i].x, pDestPoints[i].y, Source->wineD3DSurface, (RECT *) &pSourceRects[i], WINEDDBLTFAST_NOCOLORKEY);
+                IWineD3DSurface_BltFast(Dest->wineD3DSurface, pDestPoints[i].x, pDestPoints[i].y, Source->wineD3DSurface, &pSourceRects[i], WINEDDBLTFAST_NOCOLORKEY);
             }
         } else {
             for (i = 0; i < cRects; ++i) {
-                IWineD3DSurface_BltFast(Dest->wineD3DSurface, 0, 0, Source->wineD3DSurface, (RECT *) &pSourceRects[i], WINEDDBLTFAST_NOCOLORKEY);
+                IWineD3DSurface_BltFast(Dest->wineD3DSurface, 0, 0, Source->wineD3DSurface, &pSourceRects[i], WINEDDBLTFAST_NOCOLORKEY);
             }
         }
     }
@@ -1110,7 +1116,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_EndStateBlock(LPDIRECT3DDEVICE8 iface
     EnterCriticalSection(&d3d8_cs);
     hr = IWineD3DDevice_EndStateBlock(This->WineD3DDevice , &wineD3DStateBlock);
     if (hr != D3D_OK) {
-        FIXME("IWineD3DDevice_EndStateBlock returned an error\n");
+        WARN("IWineD3DDevice_EndStateBlock returned an error\n");
         LeaveCriticalSection(&d3d8_cs);
         return hr;
     }
@@ -1263,100 +1269,70 @@ static HRESULT WINAPI IDirect3DDevice8Impl_SetTexture(LPDIRECT3DDEVICE8 iface, D
     return hr;
 }
 
+static const struct tss_lookup
+{
+    BOOL sampler_state;
+    DWORD state;
+}
+tss_lookup[] =
+{
+    {FALSE, WINED3DTSS_FORCE_DWORD},            /*  0, unused */
+    {FALSE, WINED3DTSS_COLOROP},                /*  1, D3DTSS_COLOROP */
+    {FALSE, WINED3DTSS_COLORARG1},              /*  2, D3DTSS_COLORARG1 */
+    {FALSE, WINED3DTSS_COLORARG2},              /*  3, D3DTSS_COLORARG2 */
+    {FALSE, WINED3DTSS_ALPHAOP},                /*  4, D3DTSS_ALPHAOP */
+    {FALSE, WINED3DTSS_ALPHAARG1},              /*  5, D3DTSS_ALPHAARG1 */
+    {FALSE, WINED3DTSS_ALPHAARG2},              /*  6, D3DTSS_ALPHAARG2 */
+    {FALSE, WINED3DTSS_BUMPENVMAT00},           /*  7, D3DTSS_BUMPENVMAT00 */
+    {FALSE, WINED3DTSS_BUMPENVMAT01},           /*  8, D3DTSS_BUMPENVMAT01 */
+    {FALSE, WINED3DTSS_BUMPENVMAT10},           /*  9, D3DTSS_BUMPENVMAT10 */
+    {FALSE, WINED3DTSS_BUMPENVMAT11},           /* 10, D3DTSS_BUMPENVMAT11 */
+    {FALSE, WINED3DTSS_TEXCOORDINDEX},          /* 11, D3DTSS_TEXCOORDINDEX */
+    {FALSE, WINED3DTSS_FORCE_DWORD},            /* 12, unused */
+    {TRUE,  WINED3DSAMP_ADDRESSU},              /* 13, D3DTSS_ADDRESSU */
+    {TRUE,  WINED3DSAMP_ADDRESSV},              /* 14, D3DTSS_ADDRESSV */
+    {TRUE,  WINED3DSAMP_BORDERCOLOR},           /* 15, D3DTSS_BORDERCOLOR */
+    {TRUE,  WINED3DSAMP_MAGFILTER},             /* 16, D3DTSS_MAGFILTER */
+    {TRUE,  WINED3DSAMP_MINFILTER},             /* 17, D3DTSS_MINFILTER */
+    {TRUE,  WINED3DSAMP_MIPFILTER},             /* 18, D3DTSS_MIPFILTER */
+    {TRUE,  WINED3DSAMP_MIPMAPLODBIAS},         /* 19, D3DTSS_MIPMAPLODBIAS */
+    {TRUE,  WINED3DSAMP_MAXMIPLEVEL},           /* 20, D3DTSS_MAXMIPLEVEL */
+    {TRUE,  WINED3DSAMP_MAXANISOTROPY},         /* 21, D3DTSS_MAXANISOTROPY */
+    {FALSE, WINED3DTSS_BUMPENVLSCALE},          /* 22, D3DTSS_BUMPENVLSCALE */
+    {FALSE, WINED3DTSS_BUMPENVLOFFSET},         /* 23, D3DTSS_BUMPENVLOFFSET */
+    {FALSE, WINED3DTSS_TEXTURETRANSFORMFLAGS},  /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
+    {TRUE,  WINED3DSAMP_ADDRESSW},              /* 25, D3DTSS_ADDRESSW */
+    {FALSE, WINED3DTSS_COLORARG0},              /* 26, D3DTSS_COLORARG0 */
+    {FALSE, WINED3DTSS_ALPHAARG0},              /* 27, D3DTSS_ALPHAARG0 */
+    {FALSE, WINED3DTSS_RESULTARG},              /* 28, D3DTSS_RESULTARG */
+};
+
 static HRESULT  WINAPI  IDirect3DDevice8Impl_GetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD* pValue) {
     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
+    const struct tss_lookup *l = &tss_lookup[Type];
     HRESULT hr;
     TRACE("(%p) Relay\n" , This);
 
-    switch(Type) {
-    case D3DTSS_ADDRESSU:
-        Type = WINED3DSAMP_ADDRESSU;
-        break;
-    case D3DTSS_ADDRESSV:
-        Type = WINED3DSAMP_ADDRESSV;
-        break;
-    case D3DTSS_ADDRESSW:
-        Type = WINED3DSAMP_ADDRESSW;
-        break;
-    case D3DTSS_BORDERCOLOR:
-        Type = WINED3DSAMP_BORDERCOLOR;
-        break;
-    case D3DTSS_MAGFILTER:
-        Type = WINED3DSAMP_MAGFILTER;
-        break;
-    case D3DTSS_MAXANISOTROPY:
-        Type = WINED3DSAMP_MAXANISOTROPY;
-        break;
-    case D3DTSS_MAXMIPLEVEL:
-        Type = WINED3DSAMP_MAXMIPLEVEL;
-        break;
-    case D3DTSS_MINFILTER:
-        Type = WINED3DSAMP_MINFILTER;
-        break;
-    case D3DTSS_MIPFILTER:
-        Type = WINED3DSAMP_MIPFILTER;
-        break;
-    case D3DTSS_MIPMAPLODBIAS:
-        Type = WINED3DSAMP_MIPMAPLODBIAS;
-        break;
-    default:
-        EnterCriticalSection(&d3d8_cs);
-        hr = IWineD3DDevice_GetTextureStageState(This->WineD3DDevice, Stage, Type, pValue);
-        LeaveCriticalSection(&d3d8_cs);
-        return hr;
-    }
-
     EnterCriticalSection(&d3d8_cs);
-    hr = IWineD3DDevice_GetSamplerState(This->WineD3DDevice, Stage, Type, pValue);
+
+    if (l->sampler_state) hr = IWineD3DDevice_GetSamplerState(This->WineD3DDevice, Stage, l->state, pValue);
+    else hr = IWineD3DDevice_GetTextureStageState(This->WineD3DDevice, Stage, l->state, pValue);
+
     LeaveCriticalSection(&d3d8_cs);
     return hr;
 }
 
 static HRESULT WINAPI IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
+    const struct tss_lookup *l = &tss_lookup[Type];
     HRESULT hr;
     TRACE("(%p) Relay\n" , This);
 
-    switch(Type) {
-    case D3DTSS_ADDRESSU:
-        Type = WINED3DSAMP_ADDRESSU;
-        break;
-    case D3DTSS_ADDRESSV:
-        Type = WINED3DSAMP_ADDRESSV;
-        break;
-    case D3DTSS_ADDRESSW:
-        Type = WINED3DSAMP_ADDRESSW;
-        break;
-    case D3DTSS_BORDERCOLOR:
-        Type = WINED3DSAMP_BORDERCOLOR;
-        break;
-    case D3DTSS_MAGFILTER:
-        Type = WINED3DSAMP_MAGFILTER;
-        break;
-    case D3DTSS_MAXANISOTROPY:
-        Type = WINED3DSAMP_MAXANISOTROPY;
-        break;
-    case D3DTSS_MAXMIPLEVEL:
-        Type = WINED3DSAMP_MAXMIPLEVEL;
-        break;
-    case D3DTSS_MINFILTER:
-        Type = WINED3DSAMP_MINFILTER;
-        break;
-    case D3DTSS_MIPFILTER:
-        Type = WINED3DSAMP_MIPFILTER;
-        break;
-    case D3DTSS_MIPMAPLODBIAS:
-        Type = WINED3DSAMP_MIPMAPLODBIAS;
-        break;
-    default:
-        EnterCriticalSection(&d3d8_cs);
-        hr = IWineD3DDevice_SetTextureStageState(This->WineD3DDevice, Stage, Type, Value);
-        LeaveCriticalSection(&d3d8_cs);
-        return hr;
-    }
-
     EnterCriticalSection(&d3d8_cs);
-    hr = IWineD3DDevice_SetSamplerState(This->WineD3DDevice, Stage, Type, Value);
+
+    if (l->sampler_state) hr = IWineD3DDevice_SetSamplerState(This->WineD3DDevice, Stage, l->state, Value);
+    else hr = IWineD3DDevice_SetTextureStageState(This->WineD3DDevice, Stage, l->state, Value);
+
     LeaveCriticalSection(&d3d8_cs);
     return hr;
 }
@@ -1537,6 +1513,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8
     IDirect3DVertexShader8Impl *object;
     IWineD3DVertexDeclaration *wined3d_vertex_declaration;
     const DWORD *token = pDeclaration;
+    shader_handle *handle;
 
     /* Test if the vertex declaration is valid */
     while (D3DVSD_END() != *token) {
@@ -1575,41 +1552,57 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8
         *ppShader = 0;
         return D3DERR_INVALIDCALL;
     }
-    wined3d_vertex_declaration = ((IDirect3DVertexDeclaration8Impl *)object->vertex_declaration)->wined3d_vertex_declaration;
-
-    /* Usage is missing ... Use SetRenderState to set the sw vp render state in SetVertexShader */
-    hrc = IWineD3DDevice_CreateVertexShader(This->WineD3DDevice, wined3d_vertex_declaration, pFunction, &object->wineD3DVertexShader, (IUnknown *)object);
 
-    if (FAILED(hrc)) {
-        /* free up object */
-        FIXME("Call to IWineD3DDevice_CreateVertexShader failed\n");
+    handle = alloc_shader_handle(This);
+    if (!handle)
+    {
+        ERR("Failed to allocate shader handle\n");
+        LeaveCriticalSection(&d3d8_cs);
+        IDirect3DVertexDeclaration8_Release(object->vertex_declaration);
         HeapFree(GetProcessHeap(), 0, object);
         *ppShader = 0;
-    } else {
-        /* TODO: Store the VS declarations locally so that they can be dereferenced with a value higher than VS_HIGHESTFIXEDFXF */
-        shader_handle *handle = alloc_shader_handle(This);
-        if (!handle) {
-            ERR("Failed to allocate shader handle\n");
-            IDirect3DVertexShader8_Release((IUnknown *)object);
-            hrc = E_OUTOFMEMORY;
-        } else {
-            *handle = object;
-            object->handle = (handle - This->shader_handles) + VS_HIGHESTFIXEDFXF + 1;
-            *ppShader = object->handle;
+        return E_OUTOFMEMORY;
+    }
+    else
+    {
+        DWORD shader_handle = (handle - This->shader_handles) + VS_HIGHESTFIXEDFXF + 1;
+        *handle = object;
+        *ppShader = ((IDirect3DVertexDeclaration8Impl *)object->vertex_declaration)->shader_handle = shader_handle;
+    }
 
+    wined3d_vertex_declaration = ((IDirect3DVertexDeclaration8Impl *)object->vertex_declaration)->wined3d_vertex_declaration;
+
+    if (pFunction)
+    {
+        /* Usage is missing ... Use SetRenderState to set the sw vp render state in SetVertexShader */
+        hrc = IWineD3DDevice_CreateVertexShader(This->WineD3DDevice, wined3d_vertex_declaration,
+                pFunction, &object->wineD3DVertexShader, (IUnknown *)object);
+
+        if (FAILED(hrc))
+        {
+            /* free up object */
+            FIXME("Call to IWineD3DDevice_CreateVertexShader failed\n");
+            free_shader_handle(This, handle);
+            IDirect3DVertexDeclaration8_Release(object->vertex_declaration);
+            HeapFree(GetProcessHeap(), 0, object);
+            *ppShader = 0;
+        }
+        else
+        {
             load_local_constants(pDeclaration, object->wineD3DVertexShader);
             TRACE("(%p) : returning %p (handle %#x)\n", This, object, *ppShader);
         }
     }
+
     LeaveCriticalSection(&d3d8_cs);
 
     return hrc;
 }
 
-static IWineD3DVertexDeclaration *IDirect3DDevice8Impl_FindDecl(IDirect3DDevice8Impl *This, DWORD fvf)
+static IDirect3DVertexDeclaration8Impl *IDirect3DDevice8Impl_FindDecl(IDirect3DDevice8Impl *This, DWORD fvf)
 {
+    IDirect3DVertexDeclaration8Impl *d3d8_declaration;
     HRESULT hr;
-    IWineD3DVertexDeclaration* pDecl = NULL;
     int p, low, high; /* deliberately signed */
     struct FvfToDecl *convertedDecls = This->decls;
 
@@ -1622,7 +1615,7 @@ static IWineD3DVertexDeclaration *IDirect3DDevice8Impl_FindDecl(IDirect3DDevice8
         TRACE("%d ", p);
         if(convertedDecls[p].fvf == fvf) {
             TRACE("found %p\n", convertedDecls[p].decl);
-            return convertedDecls[p].decl;
+            return (IDirect3DVertexDeclaration8Impl *)convertedDecls[p].decl;
         } else if(convertedDecls[p].fvf < fvf) {
             low = p + 1;
         } else {
@@ -1631,11 +1624,27 @@ static IWineD3DVertexDeclaration *IDirect3DDevice8Impl_FindDecl(IDirect3DDevice8
     }
     TRACE("not found. Creating and inserting at position %d.\n", low);
 
+    d3d8_declaration = HeapAlloc(GetProcessHeap(), 0, sizeof(*d3d8_declaration));
+    if (!d3d8_declaration)
+    {
+        ERR("Memory allocation failed.\n");
+        return NULL;
+    }
+
+    d3d8_declaration->ref_count = 1;
+    d3d8_declaration->lpVtbl = &Direct3DVertexDeclaration8_Vtbl;
+    d3d8_declaration->elements = NULL;
+    d3d8_declaration->elements_size = 0;
+    d3d8_declaration->shader_handle = fvf;
+
     hr = IWineD3DDevice_CreateVertexDeclarationFromFVF(This->WineD3DDevice,
-                                                       &pDecl,
-                                                       (IUnknown *) This,
-                                                       fvf);
-    if (FAILED(hr)) return NULL;
+            &d3d8_declaration->wined3d_vertex_declaration, (IUnknown *)d3d8_declaration, fvf);
+    if (FAILED(hr))
+    {
+        ERR("Failed to create wined3d vertex declaration.\n");
+        HeapFree(GetProcessHeap(), 0, d3d8_declaration);
+        return NULL;
+    }
 
     if(This->declArraySize == This->numConvertedDecls) {
         int grow = This->declArraySize / 2;
@@ -1643,7 +1652,7 @@ static IWineD3DVertexDeclaration *IDirect3DDevice8Impl_FindDecl(IDirect3DDevice8
                                      sizeof(convertedDecls[0]) * (This->numConvertedDecls + grow));
         if(!convertedDecls) {
             /* This will destroy it */
-            IWineD3DVertexDeclaration_Release(pDecl);
+            IDirect3DVertexDeclaration8_Release((IDirect3DVertexDeclaration8 *)d3d8_declaration);
             return NULL;
         }
         This->decls = convertedDecls;
@@ -1651,12 +1660,12 @@ static IWineD3DVertexDeclaration *IDirect3DDevice8Impl_FindDecl(IDirect3DDevice8
     }
 
     memmove(convertedDecls + low + 1, convertedDecls + low, sizeof(convertedDecls[0]) * (This->numConvertedDecls - low));
-    convertedDecls[low].decl = pDecl;
+    convertedDecls[low].decl = (IDirect3DVertexDeclaration8 *)d3d8_declaration;
     convertedDecls[low].fvf = fvf;
     This->numConvertedDecls++;
 
-    TRACE("Returning %p. %d decls in array\n", pDecl, This->numConvertedDecls);
-    return pDecl;
+    TRACE("Returning %p. %u decls in array\n", d3d8_declaration, This->numConvertedDecls);
+    return d3d8_declaration;
 }
 
 static HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD pShader) {
@@ -1666,9 +1675,9 @@ static HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 ifa
     TRACE("(%p) : Relay\n", This);
     EnterCriticalSection(&d3d8_cs);
     if (VS_HIGHESTFIXEDFXF >= pShader) {
-        TRACE("Setting FVF, %d %d\n", VS_HIGHESTFIXEDFXF, pShader);
-        IWineD3DDevice_SetFVF(This->WineD3DDevice, pShader);
-        IWineD3DDevice_SetVertexDeclaration(This->WineD3DDevice, IDirect3DDevice8Impl_FindDecl(This, pShader));
+        TRACE("Setting FVF, %#x\n", pShader);
+        IWineD3DDevice_SetVertexDeclaration(This->WineD3DDevice,
+                IDirect3DDevice8Impl_FindDecl(This, pShader)->wined3d_vertex_declaration);
         IWineD3DDevice_SetVertexShader(This->WineD3DDevice, NULL);
     } else {
         TRACE("Setting shader\n");
@@ -1677,9 +1686,19 @@ static HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 ifa
             hrc = D3DERR_INVALIDCALL;
         } else {
             IDirect3DVertexShader8Impl *shader = This->shader_handles[pShader - (VS_HIGHESTFIXEDFXF + 1)];
-            IWineD3DDevice_SetVertexDeclaration(This->WineD3DDevice,
-                    shader ? ((IDirect3DVertexDeclaration8Impl *)shader->vertex_declaration)->wined3d_vertex_declaration : NULL);
-            hrc = IWineD3DDevice_SetVertexShader(This->WineD3DDevice, 0 == shader ? NULL : shader->wineD3DVertexShader);
+
+            if (shader)
+            {
+                hrc = IWineD3DDevice_SetVertexDeclaration(This->WineD3DDevice,
+                        ((IDirect3DVertexDeclaration8Impl *)shader->vertex_declaration)->wined3d_vertex_declaration);
+                if (SUCCEEDED(hrc))
+                    hrc = IWineD3DDevice_SetVertexShader(This->WineD3DDevice, shader->wineD3DVertexShader);
+            }
+            else
+            {
+                hrc = IWineD3DDevice_SetVertexDeclaration(This->WineD3DDevice, NULL);
+                if (SUCCEEDED(hrc)) hrc = IWineD3DDevice_SetVertexShader(This->WineD3DDevice, NULL);
+            }
         }
     }
     TRACE("(%p) : returning hr(%u)\n", This, hrc);
@@ -1690,24 +1709,36 @@ static HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 ifa
 
 static HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD* ppShader) {
     IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
-    IWineD3DVertexShader *pShader;
-    HRESULT hrc = D3D_OK;
+    IWineD3DVertexDeclaration *wined3d_declaration;
+    HRESULT hrc;
 
     TRACE("(%p) : Relay  device@%p\n", This, This->WineD3DDevice);
     EnterCriticalSection(&d3d8_cs);
-    hrc = IWineD3DDevice_GetVertexShader(This->WineD3DDevice, &pShader);
-    if (D3D_OK == hrc) {
-        if(0 != pShader) {
-            IDirect3DVertexShader8Impl *d3d8_shader;
-            hrc = IWineD3DVertexShader_GetParent(pShader, (IUnknown **)&d3d8_shader);
-            IWineD3DVertexShader_Release(pShader);
-            *ppShader = d3d8_shader->handle;
-        } else {
+
+    hrc = IWineD3DDevice_GetVertexDeclaration(This->WineD3DDevice, &wined3d_declaration);
+    if (SUCCEEDED(hrc))
+    {
+        if (wined3d_declaration)
+        {
+            IDirect3DVertexDeclaration8 *d3d8_declaration;
+            hrc = IWineD3DVertexDeclaration_GetParent(wined3d_declaration, (IUnknown **)&d3d8_declaration);
+            IWineD3DVertexDeclaration_Release(wined3d_declaration);
+            if (SUCCEEDED(hrc))
+            {
+                *ppShader = ((IDirect3DVertexDeclaration8Impl *)d3d8_declaration)->shader_handle;
+                IDirect3DVertexDeclaration8_Release(d3d8_declaration);
+            }
+        }
+        else
+        {
             *ppShader = 0;
             hrc = D3D_OK;
         }
-    } else {
-        WARN("(%p) : Call to IWineD3DDevice_GetVertexShader failed %u (device %p)\n", This, hrc, This->WineD3DDevice);
+    }
+    else
+    {
+        WARN("(%p) : Call to IWineD3DDevice_GetVertexDeclaration failed %#x (device %p)\n",
+                This, hrc, This->WineD3DDevice);
     }
     TRACE("(%p) : returning %#x\n", This, *ppShader);
     LeaveCriticalSection(&d3d8_cs);
@@ -1750,7 +1781,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShaderConstant(LPDIRECT3DDEV
     TRACE("(%p) : Relay\n", This);
 
     EnterCriticalSection(&d3d8_cs);
-    hr = IWineD3DDevice_SetVertexShaderConstantF(This->WineD3DDevice, Register, (CONST float *)pConstantData, ConstantCount);
+    hr = IWineD3DDevice_SetVertexShaderConstantF(This->WineD3DDevice, Register, pConstantData, ConstantCount);
     LeaveCriticalSection(&d3d8_cs);
     return hr;
 }
@@ -1761,7 +1792,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderConstant(LPDIRECT3DDEV
     TRACE("(%p) : Relay\n", This);
 
     EnterCriticalSection(&d3d8_cs);
-    hr = IWineD3DDevice_GetVertexShaderConstantF(This->WineD3DDevice, Register, (float *)pConstantData, ConstantCount);
+    hr = IWineD3DDevice_GetVertexShaderConstantF(This->WineD3DDevice, Register, pConstantData, ConstantCount);
     LeaveCriticalSection(&d3d8_cs);
     return hr;
 }
@@ -1819,7 +1850,16 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderFunction(LPDIRECT3DDEV
     }
 
     shader = This->shader_handles[pVertexShader - (VS_HIGHESTFIXEDFXF + 1)];
-    hr = IWineD3DVertexShader_GetFunction(shader->wineD3DVertexShader, pData, pSizeOfData);
+    if (shader->wineD3DVertexShader)
+    {
+        hr = IWineD3DVertexShader_GetFunction(shader->wineD3DVertexShader, pData, pSizeOfData);
+    }
+    else
+    {
+        *pSizeOfData = 0;
+        hr = D3D_OK;
+    }
+
     LeaveCriticalSection(&d3d8_cs);
     return hr;
 }
@@ -1995,7 +2035,7 @@ static HRESULT  WINAPI  IDirect3DDevice8Impl_SetPixelShaderConstant(LPDIRECT3DDE
     TRACE("(%p) Relay\n", This);
 
     EnterCriticalSection(&d3d8_cs);
-    hr = IWineD3DDevice_SetPixelShaderConstantF(This->WineD3DDevice, Register, (CONST float *)pConstantData, ConstantCount);
+    hr = IWineD3DDevice_SetPixelShaderConstantF(This->WineD3DDevice, Register, pConstantData, ConstantCount);
     LeaveCriticalSection(&d3d8_cs);
     return hr;
 }
@@ -2006,7 +2046,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderConstant(LPDIRECT3DDEVI
     TRACE("(%p) Relay\n", This);
 
     EnterCriticalSection(&d3d8_cs);
-    hr = IWineD3DDevice_GetPixelShaderConstantF(This->WineD3DDevice, Register, (float *)pConstantData, ConstantCount);
+    hr = IWineD3DDevice_GetPixelShaderConstantF(This->WineD3DDevice, Register, pConstantData, ConstantCount);
     LeaveCriticalSection(&d3d8_cs);
     return hr;
 }
@@ -2206,34 +2246,6 @@ const IDirect3DDevice8Vtbl Direct3DDevice8_Vtbl =
     IDirect3DDevice8Impl_DeletePatch
 };
 
-/* Internal function called back during the CreateDevice to create a render target  */
-HRESULT WINAPI D3D8CB_CreateSurface(IUnknown *device, IUnknown *pSuperior, UINT Width, UINT Height,
-                                         WINED3DFORMAT Format, DWORD Usage, WINED3DPOOL Pool, UINT Level,
-                                         WINED3DCUBEMAP_FACES Face, IWineD3DSurface **ppSurface,
-                                         HANDLE *pSharedHandle) {
-
-    HRESULT res = D3D_OK;
-    IDirect3DSurface8Impl *d3dSurface = NULL;
-    BOOL Lockable = TRUE;
-
-    if((WINED3DPOOL_DEFAULT == Pool && WINED3DUSAGE_DYNAMIC != Usage))
-        Lockable = FALSE;
-
-    TRACE("relay\n");
-    res = IDirect3DDevice8Impl_CreateSurface((IDirect3DDevice8 *)device, Width, Height, (D3DFORMAT)Format, Lockable, FALSE/*Discard*/, Level,  (IDirect3DSurface8 **)&d3dSurface, D3DRTYPE_SURFACE, Usage, Pool, D3DMULTISAMPLE_NONE, 0 /* MultisampleQuality */);
-
-    if (SUCCEEDED(res)) {
-        *ppSurface = d3dSurface->wineD3DSurface;
-        d3dSurface->container = pSuperior;
-        IUnknown_Release(d3dSurface->parentDevice);
-        d3dSurface->parentDevice = NULL;
-        d3dSurface->forwardReference = pSuperior;
-    } else {
-        FIXME("(%p) IDirect3DDevice8_CreateSurface failed\n", device);
-    }
-    return res;
-}
-
 ULONG WINAPI D3D8CB_DestroySurface(IWineD3DSurface *pSurface) {
     IDirect3DSurface8Impl* surfaceParent;
     TRACE("(%p) call back\n", pSurface);
@@ -2244,3 +2256,234 @@ ULONG WINAPI D3D8CB_DestroySurface(IWineD3DSurface *pSurface) {
     surfaceParent->forwardReference = NULL;
     return IDirect3DSurface8_Release((IDirect3DSurface8*) surfaceParent);
 }
+
+/* IWineD3DDeviceParent IUnknown methods */
+
+static inline struct IDirect3DDevice8Impl *device_from_device_parent(IWineD3DDeviceParent *iface)
+{
+    return (struct IDirect3DDevice8Impl *)((char*)iface
+            - FIELD_OFFSET(struct IDirect3DDevice8Impl, device_parent_vtbl));
+}
+
+HRESULT STDMETHODCALLTYPE device_parent_QueryInterface(IWineD3DDeviceParent *iface, REFIID riid, void **object)
+{
+    struct IDirect3DDevice8Impl *This = device_from_device_parent(iface);
+    return IDirect3DDevice8Impl_QueryInterface((IDirect3DDevice8 *)This, riid, object);
+}
+
+ULONG STDMETHODCALLTYPE device_parent_AddRef(IWineD3DDeviceParent *iface)
+{
+    struct IDirect3DDevice8Impl *This = device_from_device_parent(iface);
+    return IDirect3DDevice8Impl_AddRef((IDirect3DDevice8 *)This);
+}
+
+ULONG STDMETHODCALLTYPE device_parent_Release(IWineD3DDeviceParent *iface)
+{
+    struct IDirect3DDevice8Impl *This = device_from_device_parent(iface);
+    return IDirect3DDevice8Impl_Release((IDirect3DDevice8 *)This);
+}
+
+/* IWineD3DDeviceParent methods */
+
+static HRESULT STDMETHODCALLTYPE device_parent_CreateSurface(IWineD3DDeviceParent *iface,
+        IUnknown *superior, UINT width, UINT height, WINED3DFORMAT format, DWORD usage,
+        WINED3DPOOL pool, UINT level, WINED3DCUBEMAP_FACES face, IWineD3DSurface **surface)
+{
+    struct IDirect3DDevice8Impl *This = device_from_device_parent(iface);
+    IDirect3DSurface8Impl *d3d_surface;
+    BOOL lockable = TRUE;
+    HRESULT hr;
+
+    TRACE("iface %p, superior %p, width %u, height %u, format %#x, usage %#x,\n"
+            "\tpool %#x, level %u, face %u, surface %p\n",
+            iface, superior, width, height, format, usage, pool, level, face, surface);
+
+
+    if (pool == WINED3DPOOL_DEFAULT && !(usage & WINED3DUSAGE_DYNAMIC)) lockable = FALSE;
+
+    hr = IDirect3DDevice8Impl_CreateSurface((IDirect3DDevice8 *)This, width, height,
+            format, lockable, FALSE /* Discard */, level, (IDirect3DSurface8 **)&d3d_surface,
+            D3DRTYPE_SURFACE, usage, pool, D3DMULTISAMPLE_NONE, 0 /* MultisampleQuality */);
+    if (FAILED(hr))
+    {
+        ERR("(%p) CreateSurface failed, returning %#x\n", iface, hr);
+        return hr;
+    }
+
+    *surface = d3d_surface->wineD3DSurface;
+    d3d_surface->container = superior;
+    IUnknown_Release(d3d_surface->parentDevice);
+    d3d_surface->parentDevice = NULL;
+    d3d_surface->forwardReference = superior;
+
+    return hr;
+}
+
+static HRESULT STDMETHODCALLTYPE device_parent_CreateRenderTarget(IWineD3DDeviceParent *iface,
+        IUnknown *superior, UINT width, UINT height, WINED3DFORMAT format, WINED3DMULTISAMPLE_TYPE multisample_type,
+        DWORD multisample_quality, BOOL lockable, IWineD3DSurface **surface)
+{
+    struct IDirect3DDevice8Impl *This = device_from_device_parent(iface);
+    IDirect3DSurface8Impl *d3d_surface;
+    HRESULT hr;
+
+    TRACE("iface %p, superior %p, width %u, height %u, format %#x, multisample_type %#x,\n"
+            "\tmultisample_quality %u, lockable %u, surface %p\n",
+            iface, superior, width, height, format, multisample_type, multisample_quality, lockable, surface);
+
+    hr = IDirect3DDevice8_CreateRenderTarget((IDirect3DDevice8 *)This, width, height, format,
+            multisample_type, lockable, (IDirect3DSurface8 **)&d3d_surface);
+    if (FAILED(hr))
+    {
+        ERR("(%p) CreateRenderTarget failed, returning %#x\n", iface, hr);
+        return hr;
+    }
+
+    *surface = d3d_surface->wineD3DSurface;
+    d3d_surface->container = (IUnknown *)This;
+    d3d_surface->isImplicit = TRUE;
+    /* Implicit surfaces are created with an refcount of 0 */
+    IUnknown_Release((IUnknown *)d3d_surface);
+
+    return hr;
+}
+
+static HRESULT STDMETHODCALLTYPE device_parent_CreateDepthStencilSurface(IWineD3DDeviceParent *iface,
+        IUnknown *superior, UINT width, UINT height, WINED3DFORMAT format, WINED3DMULTISAMPLE_TYPE multisample_type,
+        DWORD multisample_quality, BOOL discard, IWineD3DSurface **surface)
+{
+    struct IDirect3DDevice8Impl *This = device_from_device_parent(iface);
+    IDirect3DSurface8Impl *d3d_surface;
+    HRESULT hr;
+
+    TRACE("iface %p, superior %p, width %u, height %u, format %#x, multisample_type %#x,\n"
+            "\tmultisample_quality %u, discard %u, surface %p\n",
+            iface, superior, width, height, format, multisample_type, multisample_quality, discard, surface);
+
+    hr = IDirect3DDevice8_CreateDepthStencilSurface((IDirect3DDevice8 *)This, width, height, format,
+            multisample_type, (IDirect3DSurface8 **)&d3d_surface);
+    if (FAILED(hr))
+    {
+        ERR("(%p) CreateDepthStencilSurface failed, returning %#x\n", iface, hr);
+        return hr;
+    }
+
+    *surface = d3d_surface->wineD3DSurface;
+    d3d_surface->container = (IUnknown *)This;
+    d3d_surface->isImplicit = TRUE;
+    /* Implicit surfaces are created with an refcount of 0 */
+    IUnknown_Release((IUnknown *)d3d_surface);
+
+    return hr;
+}
+
+static HRESULT STDMETHODCALLTYPE device_parent_CreateVolume(IWineD3DDeviceParent *iface,
+        IUnknown *superior, UINT width, UINT height, UINT depth, WINED3DFORMAT format,
+        WINED3DPOOL pool, DWORD usage, IWineD3DVolume **volume)
+{
+    struct IDirect3DDevice8Impl *This = device_from_device_parent(iface);
+    IDirect3DVolume8Impl *object;
+    HRESULT hr;
+
+    TRACE("iface %p, superior %p, width %u, height %u, depth %u, format %#x, pool %#x, usage %#x, volume %p\n",
+            iface, superior, 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;
+    }
+
+    object->lpVtbl = &Direct3DVolume8_Vtbl;
+    object->ref = 1;
+    hr = IWineD3DDevice_CreateVolume(This->WineD3DDevice, width, height, depth, usage,
+            format, pool, &object->wineD3DVolume, NULL, (IUnknown *)object);
+    if (FAILED(hr))
+    {
+        ERR("(%p) CreateVolume failed, returning %#x\n", iface, hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        *volume = NULL;
+        return hr;
+    }
+
+    *volume = object->wineD3DVolume;
+    object->container = superior;
+    object->forwardReference = superior;
+
+    TRACE("(%p) Created volume %p\n", iface, *volume);
+
+    return hr;
+}
+
+static HRESULT STDMETHODCALLTYPE device_parent_CreateSwapChain(IWineD3DDeviceParent *iface,
+        WINED3DPRESENT_PARAMETERS *present_parameters, IWineD3DSwapChain **swapchain)
+{
+    struct IDirect3DDevice8Impl *This = device_from_device_parent(iface);
+    IDirect3DSwapChain8Impl *d3d_swapchain;
+    D3DPRESENT_PARAMETERS local_parameters;
+    HRESULT hr;
+
+    TRACE("iface %p, present_parameters %p, swapchain %p\n", iface, present_parameters, swapchain);
+
+    /* Copy the presentation parameters */
+    local_parameters.BackBufferWidth = present_parameters->BackBufferWidth;
+    local_parameters.BackBufferHeight = present_parameters->BackBufferHeight;
+    local_parameters.BackBufferFormat = present_parameters->BackBufferFormat;
+    local_parameters.BackBufferCount = present_parameters->BackBufferCount;
+    local_parameters.MultiSampleType = present_parameters->MultiSampleType;
+    local_parameters.SwapEffect = present_parameters->SwapEffect;
+    local_parameters.hDeviceWindow = present_parameters->hDeviceWindow;
+    local_parameters.Windowed = present_parameters->Windowed;
+    local_parameters.EnableAutoDepthStencil = present_parameters->EnableAutoDepthStencil;
+    local_parameters.AutoDepthStencilFormat = present_parameters->AutoDepthStencilFormat;
+    local_parameters.Flags = present_parameters->Flags;
+    local_parameters.FullScreen_RefreshRateInHz = present_parameters->FullScreen_RefreshRateInHz;
+    local_parameters.FullScreen_PresentationInterval = present_parameters->PresentationInterval;
+
+    hr = IDirect3DDevice8_CreateAdditionalSwapChain((IDirect3DDevice8 *)This,
+            &local_parameters, (IDirect3DSwapChain8 **)&d3d_swapchain);
+    if (FAILED(hr))
+    {
+        ERR("(%p) CreateAdditionalSwapChain failed, returning %#x\n", iface, hr);
+        *swapchain = NULL;
+        return hr;
+    }
+
+    *swapchain = d3d_swapchain->wineD3DSwapChain;
+    IUnknown_Release(d3d_swapchain->parentDevice);
+    d3d_swapchain->parentDevice = NULL;
+
+    /* Copy back the presentation parameters */
+    present_parameters->BackBufferWidth = local_parameters.BackBufferWidth;
+    present_parameters->BackBufferHeight = local_parameters.BackBufferHeight;
+    present_parameters->BackBufferFormat = local_parameters.BackBufferFormat;
+    present_parameters->BackBufferCount = local_parameters.BackBufferCount;
+    present_parameters->MultiSampleType = local_parameters.MultiSampleType;
+    present_parameters->SwapEffect = local_parameters.SwapEffect;
+    present_parameters->hDeviceWindow = local_parameters.hDeviceWindow;
+    present_parameters->Windowed = local_parameters.Windowed;
+    present_parameters->EnableAutoDepthStencil = local_parameters.EnableAutoDepthStencil;
+    present_parameters->AutoDepthStencilFormat = local_parameters.AutoDepthStencilFormat;
+    present_parameters->Flags = local_parameters.Flags;
+    present_parameters->FullScreen_RefreshRateInHz = local_parameters.FullScreen_RefreshRateInHz;
+    present_parameters->PresentationInterval = local_parameters.FullScreen_PresentationInterval;
+
+    return hr;
+}
+
+const IWineD3DDeviceParentVtbl d3d8_wined3d_device_parent_vtbl =
+{
+    /* IUnknown methods */
+    device_parent_QueryInterface,
+    device_parent_AddRef,
+    device_parent_Release,
+    /* IWineD3DDeviceParent methods */
+    device_parent_CreateSurface,
+    device_parent_CreateRenderTarget,
+    device_parent_CreateDepthStencilSurface,
+    device_parent_CreateVolume,
+    device_parent_CreateSwapChain,
+};