d3dx8: Implement D3DXPlaneColorLerp.
[wine] / dlls / d3d9 / directx.c
1 /*
2  * IDirect3D9 implementation
3  *
4  * Copyright 2002 Jason Edmeades
5  * Copyright 2005 Oliver Stieber
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include "config.h"
23 #include "d3d9_private.h"
24
25 WINE_DEFAULT_DEBUG_CHANNEL(d3d9);
26
27 /* IDirect3D9 IUnknown parts follow: */
28 static HRESULT WINAPI IDirect3D9Impl_QueryInterface(LPDIRECT3D9 iface, REFIID riid, LPVOID* ppobj)
29 {
30     IDirect3D9Impl *This = (IDirect3D9Impl *)iface;
31
32     if (IsEqualGUID(riid, &IID_IUnknown)
33         || IsEqualGUID(riid, &IID_IDirect3D9)) {
34         IUnknown_AddRef(iface);
35         *ppobj = This;
36         return S_OK;
37     }
38
39     WARN("(%p)->(%s,%p),not found\n", This, debugstr_guid(riid), ppobj);
40     *ppobj = NULL;
41     return E_NOINTERFACE;
42 }
43
44 static ULONG WINAPI IDirect3D9Impl_AddRef(LPDIRECT3D9 iface) {
45     IDirect3D9Impl *This = (IDirect3D9Impl *)iface;
46     ULONG ref = InterlockedIncrement(&This->ref);
47
48     TRACE("(%p) : AddRef from %d\n", This, ref - 1);
49
50     return ref;
51 }
52
53 static ULONG WINAPI IDirect3D9Impl_Release(LPDIRECT3D9 iface) {
54     IDirect3D9Impl *This = (IDirect3D9Impl *)iface;
55     ULONG ref = InterlockedDecrement(&This->ref);
56
57     TRACE("(%p) : ReleaseRef to %d\n", This, ref);
58
59     if (ref == 0) {
60         EnterCriticalSection(&d3d9_cs);
61         IWineD3D_Release(This->WineD3D);
62         LeaveCriticalSection(&d3d9_cs);
63         HeapFree(GetProcessHeap(), 0, This);
64     }
65
66     return ref;
67 }
68
69 /* IDirect3D9 Interface follow: */
70 static HRESULT  WINAPI  IDirect3D9Impl_RegisterSoftwareDevice(LPDIRECT3D9 iface, void* pInitializeFunction) {
71     IDirect3D9Impl *This = (IDirect3D9Impl *)iface;
72     HRESULT hr;
73     TRACE("(%p)->(%p)\n", This, pInitializeFunction);
74
75     EnterCriticalSection(&d3d9_cs);
76     hr = IWineD3D_RegisterSoftwareDevice(This->WineD3D, pInitializeFunction);
77     LeaveCriticalSection(&d3d9_cs);
78     return hr;
79 }
80
81 static UINT     WINAPI  IDirect3D9Impl_GetAdapterCount(LPDIRECT3D9 iface) {
82     IDirect3D9Impl *This = (IDirect3D9Impl *)iface;
83     HRESULT hr;
84     TRACE("%p\n", This);
85
86     EnterCriticalSection(&d3d9_cs);
87     hr = IWineD3D_GetAdapterCount(This->WineD3D);
88     LeaveCriticalSection(&d3d9_cs);
89     return hr;
90 }
91
92 static HRESULT WINAPI IDirect3D9Impl_GetAdapterIdentifier(LPDIRECT3D9 iface, UINT Adapter, DWORD Flags, D3DADAPTER_IDENTIFIER9* pIdentifier) {
93     IDirect3D9Impl *This = (IDirect3D9Impl *)iface;
94     WINED3DADAPTER_IDENTIFIER adapter_id;
95     HRESULT hr;
96
97     /* dx8 and dx9 have different structures to be filled in, with incompatible 
98        layouts so pass in pointers to the places to be filled via an internal 
99        structure                                                                */
100     adapter_id.Driver           = pIdentifier->Driver;          
101     adapter_id.Description      = pIdentifier->Description;     
102     adapter_id.DeviceName       = pIdentifier->DeviceName;      
103     adapter_id.DriverVersion    = &pIdentifier->DriverVersion;   
104     adapter_id.VendorId         = &pIdentifier->VendorId;        
105     adapter_id.DeviceId         = &pIdentifier->DeviceId;        
106     adapter_id.SubSysId         = &pIdentifier->SubSysId;        
107     adapter_id.Revision         = &pIdentifier->Revision;        
108     adapter_id.DeviceIdentifier = &pIdentifier->DeviceIdentifier;
109     adapter_id.WHQLLevel        = &pIdentifier->WHQLLevel;       
110
111     EnterCriticalSection(&d3d9_cs);
112     hr = IWineD3D_GetAdapterIdentifier(This->WineD3D, Adapter, Flags, &adapter_id);
113     LeaveCriticalSection(&d3d9_cs);
114     return hr;
115 }
116
117 static UINT WINAPI IDirect3D9Impl_GetAdapterModeCount(LPDIRECT3D9 iface, UINT Adapter, D3DFORMAT Format) {
118     IDirect3D9Impl *This = (IDirect3D9Impl *)iface;
119     HRESULT hr;
120     TRACE("(%p)->(%d, %d\n", This, Adapter, Format);
121
122     /* Others than that not supported by d3d9, but reported by wined3d for ddraw. Filter them out */
123     if(Format != D3DFMT_X8R8G8B8 && Format != D3DFMT_R5G6B5) {
124         return 0;
125     }
126
127     EnterCriticalSection(&d3d9_cs);
128     hr = IWineD3D_GetAdapterModeCount(This->WineD3D, Adapter, Format);
129     LeaveCriticalSection(&d3d9_cs);
130     return hr;
131 }
132
133 static HRESULT WINAPI IDirect3D9Impl_EnumAdapterModes(LPDIRECT3D9 iface, UINT Adapter, D3DFORMAT Format, UINT Mode, D3DDISPLAYMODE* pMode) {
134     IDirect3D9Impl *This = (IDirect3D9Impl *)iface;
135     HRESULT hr;
136     TRACE("(%p)->(%d, %d, %d, %p)\n", This, Adapter, Format, Mode, pMode);
137     /* We can't pass this to WineD3D, otherwise it'll think it came from D3D8 or DDraw.
138        It's supposed to fail anyway, so no harm returning failure. */
139     if(Format != WINED3DFMT_X8R8G8B8 && Format != WINED3DFMT_R5G6B5)
140         return D3DERR_INVALIDCALL;
141
142     EnterCriticalSection(&d3d9_cs);
143     hr = IWineD3D_EnumAdapterModes(This->WineD3D, Adapter, Format, Mode, (WINED3DDISPLAYMODE *) pMode);
144     LeaveCriticalSection(&d3d9_cs);
145     return hr;
146 }
147
148 static HRESULT WINAPI IDirect3D9Impl_GetAdapterDisplayMode(LPDIRECT3D9 iface, UINT Adapter, D3DDISPLAYMODE* pMode) {
149     IDirect3D9Impl *This = (IDirect3D9Impl *)iface;
150     return IWineD3D_GetAdapterDisplayMode(This->WineD3D, Adapter, (WINED3DDISPLAYMODE *) pMode);
151 }
152
153 static HRESULT WINAPI IDirect3D9Impl_CheckDeviceType(LPDIRECT3D9 iface,
154                                               UINT Adapter, D3DDEVTYPE CheckType, D3DFORMAT DisplayFormat,
155                                               D3DFORMAT BackBufferFormat, BOOL Windowed) {
156     IDirect3D9Impl *This = (IDirect3D9Impl *)iface;
157     HRESULT hr;
158     TRACE("(%p)->(%d, %d, %d, %d, %s\n", This, Adapter, CheckType, DisplayFormat,
159           BackBufferFormat, Windowed ? "true" : "false");
160
161     EnterCriticalSection(&d3d9_cs);
162     hr = IWineD3D_CheckDeviceType(This->WineD3D, Adapter, CheckType, DisplayFormat,
163                                     BackBufferFormat, Windowed);
164     LeaveCriticalSection(&d3d9_cs);
165     return hr;
166 }
167
168 static HRESULT WINAPI IDirect3D9Impl_CheckDeviceFormat(LPDIRECT3D9 iface,
169                                                   UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat,
170                                                   DWORD Usage, D3DRESOURCETYPE RType, D3DFORMAT CheckFormat) {
171     IDirect3D9Impl *This = (IDirect3D9Impl *)iface;
172     HRESULT hr;
173     TRACE("%p\n", This);
174
175     EnterCriticalSection(&d3d9_cs);
176     hr = IWineD3D_CheckDeviceFormat(This->WineD3D, Adapter, DeviceType, AdapterFormat,
177                                     Usage, RType, CheckFormat);
178     LeaveCriticalSection(&d3d9_cs);
179     return hr;
180 }
181
182 static HRESULT WINAPI IDirect3D9Impl_CheckDeviceMultiSampleType(LPDIRECT3D9 iface,
183                                                            UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT SurfaceFormat,
184                                                            BOOL Windowed, D3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
185     IDirect3D9Impl *This = (IDirect3D9Impl *)iface;
186     HRESULT hr;
187     TRACE("%p\n", This);
188
189     EnterCriticalSection(&d3d9_cs);
190     hr = IWineD3D_CheckDeviceMultiSampleType(This->WineD3D, Adapter, DeviceType, SurfaceFormat,
191                                                Windowed, MultiSampleType, pQualityLevels);
192     LeaveCriticalSection(&d3d9_cs);
193     return hr;
194 }
195
196 static HRESULT WINAPI IDirect3D9Impl_CheckDepthStencilMatch(LPDIRECT3D9 iface, 
197                                                        UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat,
198                                                        D3DFORMAT RenderTargetFormat, D3DFORMAT DepthStencilFormat) {
199     IDirect3D9Impl *This = (IDirect3D9Impl *)iface;
200     HRESULT hr;
201     TRACE("%p\n", This);
202
203     EnterCriticalSection(&d3d9_cs);
204     hr = IWineD3D_CheckDepthStencilMatch(This->WineD3D, Adapter, DeviceType, AdapterFormat,
205                                            RenderTargetFormat, DepthStencilFormat);
206     LeaveCriticalSection(&d3d9_cs);
207     return hr;
208 }
209
210 static HRESULT WINAPI IDirect3D9Impl_CheckDeviceFormatConversion(LPDIRECT3D9 iface, UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT SourceFormat, D3DFORMAT TargetFormat) {
211     IDirect3D9Impl *This = (IDirect3D9Impl *)iface;
212     HRESULT hr;
213     TRACE("%p\n", This);
214
215     EnterCriticalSection(&d3d9_cs);
216     hr = IWineD3D_CheckDeviceFormatConversion(This->WineD3D, Adapter, DeviceType, SourceFormat,
217                                                 TargetFormat);
218     LeaveCriticalSection(&d3d9_cs);
219     return hr;
220 }
221
222 void filter_caps(D3DCAPS9* pCaps)
223 {
224
225     DWORD textureFilterCaps =
226         D3DPTFILTERCAPS_MINFPOINT      | D3DPTFILTERCAPS_MINFLINEAR    | D3DPTFILTERCAPS_MINFANISOTROPIC |
227         D3DPTFILTERCAPS_MINFPYRAMIDALQUAD                              | D3DPTFILTERCAPS_MINFGAUSSIANQUAD|
228         D3DPTFILTERCAPS_MIPFPOINT      | D3DPTFILTERCAPS_MIPFLINEAR    | D3DPTFILTERCAPS_MAGFPOINT       |
229         D3DPTFILTERCAPS_MAGFLINEAR     |D3DPTFILTERCAPS_MAGFANISOTROPIC|D3DPTFILTERCAPS_MAGFPYRAMIDALQUAD|
230         D3DPTFILTERCAPS_MAGFGAUSSIANQUAD;
231     pCaps->TextureFilterCaps &= textureFilterCaps;
232     pCaps->CubeTextureFilterCaps &= textureFilterCaps;
233     pCaps->VolumeTextureFilterCaps &= textureFilterCaps;
234
235     pCaps->DevCaps &=
236         D3DDEVCAPS_EXECUTESYSTEMMEMORY | D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY |
237         D3DDEVCAPS_TLVERTEXVIDEOMEMORY | D3DDEVCAPS_TEXTURESYSTEMMEMORY| D3DDEVCAPS_TEXTUREVIDEOMEMORY   |
238         D3DDEVCAPS_DRAWPRIMTLVERTEX    | D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_TEXTURENONLOCALVIDMEM|
239         D3DDEVCAPS_DRAWPRIMITIVES2     | D3DDEVCAPS_SEPARATETEXTUREMEMORIES                              |
240         D3DDEVCAPS_DRAWPRIMITIVES2EX   | D3DDEVCAPS_HWTRANSFORMANDLIGHT| D3DDEVCAPS_CANBLTSYSTONONLOCAL  |
241         D3DDEVCAPS_HWRASTERIZATION     | D3DDEVCAPS_PUREDEVICE         | D3DDEVCAPS_QUINTICRTPATCHES     |
242         D3DDEVCAPS_RTPATCHES           | D3DDEVCAPS_RTPATCHHANDLEZERO  | D3DDEVCAPS_NPATCHES;
243
244     pCaps->ShadeCaps &=
245         D3DPSHADECAPS_COLORGOURAUDRGB  | D3DPSHADECAPS_SPECULARGOURAUDRGB |
246         D3DPSHADECAPS_ALPHAGOURAUDBLEND | D3DPSHADECAPS_FOGGOURAUD;
247
248     pCaps->RasterCaps &=
249         D3DPRASTERCAPS_DITHER          | D3DPRASTERCAPS_ZTEST          | D3DPRASTERCAPS_FOGVERTEX        |
250         D3DPRASTERCAPS_FOGTABLE        | D3DPRASTERCAPS_MIPMAPLODBIAS  | D3DPRASTERCAPS_ZBUFFERLESSHSR   |
251         D3DPRASTERCAPS_FOGRANGE        | D3DPRASTERCAPS_ANISOTROPY     | D3DPRASTERCAPS_WBUFFER          |
252         D3DPRASTERCAPS_WFOG            | D3DPRASTERCAPS_ZFOG           | D3DPRASTERCAPS_COLORPERSPECTIVE |
253         D3DPRASTERCAPS_SCISSORTEST     | D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS                              |
254         D3DPRASTERCAPS_DEPTHBIAS       | D3DPRASTERCAPS_MULTISAMPLE_TOGGLE;
255
256     pCaps->DevCaps2 &=
257         D3DDEVCAPS2_STREAMOFFSET       | D3DDEVCAPS2_DMAPNPATCH        | D3DDEVCAPS2_ADAPTIVETESSRTPATCH |
258         D3DDEVCAPS2_ADAPTIVETESSNPATCH | D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES                       |
259         D3DDEVCAPS2_PRESAMPLEDDMAPNPATCH| D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET;
260
261     pCaps->Caps2 &=
262         D3DCAPS2_FULLSCREENGAMMA       | D3DCAPS2_CANCALIBRATEGAMMA    | D3DCAPS2_RESERVED               |
263         D3DCAPS2_CANMANAGERESOURCE     | D3DCAPS2_DYNAMICTEXTURES      | D3DCAPS2_CANAUTOGENMIPMAP;
264
265     pCaps->VertexProcessingCaps &=
266         D3DVTXPCAPS_TEXGEN             | D3DVTXPCAPS_MATERIALSOURCE7   | D3DVTXPCAPS_DIRECTIONALLIGHTS   |
267         D3DVTXPCAPS_POSITIONALLIGHTS   | D3DVTXPCAPS_LOCALVIEWER       | D3DVTXPCAPS_TWEENING            |
268         D3DVTXPCAPS_TEXGEN_SPHEREMAP   | D3DVTXPCAPS_NO_TEXGEN_NONLOCALVIEWER;
269
270     pCaps->TextureCaps &=
271         D3DPTEXTURECAPS_PERSPECTIVE    | D3DPTEXTURECAPS_POW2          | D3DPTEXTURECAPS_ALPHA           |
272         D3DPTEXTURECAPS_SQUAREONLY     | D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE                        |
273         D3DPTEXTURECAPS_ALPHAPALETTE   | D3DPTEXTURECAPS_NONPOW2CONDITIONAL                              |
274         D3DPTEXTURECAPS_PROJECTED      | D3DPTEXTURECAPS_CUBEMAP       | D3DPTEXTURECAPS_VOLUMEMAP       |
275         D3DPTEXTURECAPS_MIPMAP         | D3DPTEXTURECAPS_MIPVOLUMEMAP  | D3DPTEXTURECAPS_MIPCUBEMAP      |
276         D3DPTEXTURECAPS_CUBEMAP_POW2   | D3DPTEXTURECAPS_VOLUMEMAP_POW2| D3DPTEXTURECAPS_NOPROJECTEDBUMPENV;
277 }
278
279 static HRESULT WINAPI IDirect3D9Impl_GetDeviceCaps(LPDIRECT3D9 iface, UINT Adapter, D3DDEVTYPE DeviceType, D3DCAPS9* pCaps) {
280     IDirect3D9Impl *This = (IDirect3D9Impl *)iface;
281     HRESULT hrc = D3D_OK;
282     WINED3DCAPS *pWineCaps;
283
284     TRACE("(%p) Relay %d %u %p\n", This, Adapter, DeviceType, pCaps);
285
286     if(NULL == pCaps){
287         return D3DERR_INVALIDCALL;
288     }
289     pWineCaps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WINED3DCAPS));
290     if(pWineCaps == NULL){
291         return D3DERR_INVALIDCALL; /*well this is what MSDN says to return*/
292     }
293     memset(pCaps, 0, sizeof(*pCaps));
294     D3D9CAPSTOWINECAPS(pCaps, pWineCaps)
295     EnterCriticalSection(&d3d9_cs);
296     hrc = IWineD3D_GetDeviceCaps(This->WineD3D, Adapter, DeviceType, pWineCaps);
297     LeaveCriticalSection(&d3d9_cs);
298     HeapFree(GetProcessHeap(), 0, pWineCaps);
299
300     /* Some functionality is implemented in d3d9.dll, not wined3d.dll. Add the needed caps */
301     pCaps->DevCaps2 |= D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES;
302
303     filter_caps(pCaps);
304
305     TRACE("(%p) returning %p\n", This, pCaps);
306     return hrc;
307 }
308
309 static HMONITOR WINAPI IDirect3D9Impl_GetAdapterMonitor(LPDIRECT3D9 iface, UINT Adapter) {
310     IDirect3D9Impl *This = (IDirect3D9Impl *)iface;
311     HMONITOR ret;
312     TRACE("%p\n", This);
313
314     EnterCriticalSection(&d3d9_cs);
315     ret = IWineD3D_GetAdapterMonitor(This->WineD3D, Adapter);
316     LeaveCriticalSection(&d3d9_cs);
317     return ret;
318 }
319
320 /* Internal function called back during the CreateDevice to create a render target */
321 HRESULT WINAPI D3D9CB_CreateRenderTarget(IUnknown *device, IUnknown *pSuperior, UINT Width, UINT Height,
322                                          WINED3DFORMAT Format, WINED3DMULTISAMPLE_TYPE MultiSample,
323                                          DWORD MultisampleQuality, BOOL Lockable,
324                                          IWineD3DSurface** ppSurface, HANDLE* pSharedHandle) {
325     HRESULT res = D3D_OK;
326     IDirect3DSurface9Impl *d3dSurface = NULL;
327     TRACE("(%p) call back\n", device);
328     res = IDirect3DDevice9_CreateRenderTarget((IDirect3DDevice9 *)device, Width, Height, 
329                                          (D3DFORMAT)Format, MultiSample, MultisampleQuality, Lockable,
330                                          (IDirect3DSurface9 **)&d3dSurface, pSharedHandle);
331
332     if (SUCCEEDED(res)) {
333         *ppSurface = d3dSurface->wineD3DSurface;
334         d3dSurface->container = pSuperior;
335         d3dSurface->isImplicit = TRUE;
336         /* Implicit surfaces are created with an refcount of 0 */
337         IUnknown_Release((IUnknown *)d3dSurface);
338     } else {
339         *ppSurface = NULL;
340     }
341     return res;
342 }
343
344 ULONG WINAPI D3D9CB_DestroyRenderTarget(IWineD3DSurface *pSurface) {
345     IDirect3DSurface9Impl* surfaceParent;
346     TRACE("(%p) call back\n", pSurface);
347
348     IWineD3DSurface_GetParent(pSurface, (IUnknown **) &surfaceParent);
349     surfaceParent->isImplicit = FALSE;
350     /* Surface had refcount of 0 GetParent addrefed to 1, so 1 Release is enough */
351     return IDirect3DSurface9_Release((IDirect3DSurface9*) surfaceParent);
352 }
353
354 static HRESULT WINAPI D3D9CB_CreateAdditionalSwapChain(IUnknown *device,
355                                                        WINED3DPRESENT_PARAMETERS* pPresentationParameters,
356                                                        IWineD3DSwapChain ** ppSwapChain) {
357     HRESULT res = D3D_OK;
358     IDirect3DSwapChain9Impl *d3dSwapChain = NULL;
359     D3DPRESENT_PARAMETERS localParameters;
360     TRACE("(%p) call back\n", device);
361
362     /* Copy the presentation parameters */
363     localParameters.BackBufferWidth                     = pPresentationParameters->BackBufferWidth;
364     localParameters.BackBufferHeight                    = pPresentationParameters->BackBufferHeight;
365     localParameters.BackBufferFormat                    = pPresentationParameters->BackBufferFormat;
366     localParameters.BackBufferCount                     = pPresentationParameters->BackBufferCount;
367     localParameters.MultiSampleType                     = pPresentationParameters->MultiSampleType;
368     localParameters.MultiSampleQuality                  = pPresentationParameters->MultiSampleQuality;
369     localParameters.SwapEffect                          = pPresentationParameters->SwapEffect;
370     localParameters.hDeviceWindow                       = pPresentationParameters->hDeviceWindow;
371     localParameters.Windowed                            = pPresentationParameters->Windowed;
372     localParameters.EnableAutoDepthStencil              = pPresentationParameters->EnableAutoDepthStencil;
373     localParameters.AutoDepthStencilFormat              = pPresentationParameters->AutoDepthStencilFormat;
374     localParameters.Flags                               = pPresentationParameters->Flags;
375     localParameters.FullScreen_RefreshRateInHz          = pPresentationParameters->FullScreen_RefreshRateInHz;
376     localParameters.PresentationInterval                = pPresentationParameters->PresentationInterval;
377
378     res = IDirect3DDevice9_CreateAdditionalSwapChain((IDirect3DDevice9 *)device, &localParameters, (IDirect3DSwapChain9 **)&d3dSwapChain);
379
380     if (SUCCEEDED(res)) {
381         *ppSwapChain = d3dSwapChain->wineD3DSwapChain;
382         d3dSwapChain->isImplicit = TRUE;
383         /* Implicit swap chains are created with an refcount of 0 */
384         IUnknown_Release((IUnknown *)d3dSwapChain);
385     } else {
386         *ppSwapChain = NULL;
387     }
388
389     /* Copy back the presentation parameters */
390     pPresentationParameters->BackBufferWidth            = localParameters.BackBufferWidth;
391     pPresentationParameters->BackBufferHeight           = localParameters.BackBufferHeight;
392     pPresentationParameters->BackBufferFormat           = localParameters.BackBufferFormat;
393     pPresentationParameters->BackBufferCount            = localParameters.BackBufferCount;
394     pPresentationParameters->MultiSampleType            = localParameters.MultiSampleType;
395     pPresentationParameters->MultiSampleQuality         = localParameters.MultiSampleQuality;
396     pPresentationParameters->SwapEffect                 = localParameters.SwapEffect;
397     pPresentationParameters->hDeviceWindow              = localParameters.hDeviceWindow;
398     pPresentationParameters->Windowed                   = localParameters.Windowed;
399     pPresentationParameters->EnableAutoDepthStencil     = localParameters.EnableAutoDepthStencil;
400     pPresentationParameters->AutoDepthStencilFormat     = localParameters.AutoDepthStencilFormat;
401     pPresentationParameters->Flags                      = localParameters.Flags;
402     pPresentationParameters->FullScreen_RefreshRateInHz = localParameters.FullScreen_RefreshRateInHz;
403     pPresentationParameters->PresentationInterval       = localParameters.PresentationInterval;
404
405     return res;
406 }
407
408 ULONG WINAPI D3D9CB_DestroySwapChain(IWineD3DSwapChain *pSwapChain) {
409     IDirect3DSwapChain9Impl* swapChainParent;
410     TRACE("(%p) call back\n", pSwapChain);
411
412     IWineD3DSwapChain_GetParent(pSwapChain,(IUnknown **) &swapChainParent);
413     swapChainParent->isImplicit = FALSE;
414     /* Swap chain had refcount of 0 GetParent addrefed to 1, so 1 Release is enough */
415     return IDirect3DSwapChain9_Release((IDirect3DSwapChain9*) swapChainParent);
416 }
417
418 /* Internal function called back during the CreateDevice to create a render target */
419 HRESULT WINAPI D3D9CB_CreateDepthStencilSurface(IUnknown *device, IUnknown *pSuperior, UINT Width, UINT Height,
420                                          WINED3DFORMAT Format, WINED3DMULTISAMPLE_TYPE MultiSample,
421                                          DWORD MultisampleQuality, BOOL Discard,
422                                          IWineD3DSurface** ppSurface, HANDLE* pSharedHandle) {
423     HRESULT res = D3D_OK;
424     IDirect3DSurface9Impl *d3dSurface = NULL;
425     TRACE("(%p) call back\n", device);
426
427     res = IDirect3DDevice9_CreateDepthStencilSurface((IDirect3DDevice9 *)device, Width, Height, 
428                                          (D3DFORMAT)Format, MultiSample, MultisampleQuality, Discard, 
429                                          (IDirect3DSurface9 **)&d3dSurface, pSharedHandle);
430     if (SUCCEEDED(res)) {
431         *ppSurface = d3dSurface->wineD3DSurface;
432         d3dSurface->container = device;
433         d3dSurface->isImplicit = TRUE;
434         /* Implicit surfaces are created with an refcount of 0 */
435         IUnknown_Release((IUnknown *)d3dSurface);
436     }
437     return res;
438 }
439
440 ULONG WINAPI D3D9CB_DestroyDepthStencilSurface(IWineD3DSurface *pSurface) {
441     IDirect3DSurface9Impl* surfaceParent;
442     TRACE("(%p) call back\n", pSurface);
443
444     IWineD3DSurface_GetParent(pSurface, (IUnknown **) &surfaceParent);
445     surfaceParent->isImplicit = FALSE;
446     /* Surface had refcount of 0 GetParent addrefed to 1, so 1 Release is enough */
447     return IDirect3DSurface9_Release((IDirect3DSurface9*) surfaceParent);
448 }
449
450 static HRESULT WINAPI IDirect3D9Impl_CreateDevice(LPDIRECT3D9 iface, UINT Adapter, D3DDEVTYPE DeviceType,
451                                                   HWND hFocusWindow, DWORD BehaviourFlags,
452                                                   D3DPRESENT_PARAMETERS* pPresentationParameters,
453                                                   IDirect3DDevice9** ppReturnedDeviceInterface) {
454
455     IDirect3D9Impl       *This   = (IDirect3D9Impl *)iface;
456     IDirect3DDevice9Impl *object = NULL;
457     WINED3DPRESENT_PARAMETERS localParameters;
458     HRESULT hr;
459     TRACE("(%p) Relay\n", This);
460
461     /* Check the validity range of the adapter parameter */
462     if (Adapter >= IDirect3D9Impl_GetAdapterCount(iface)) {
463         *ppReturnedDeviceInterface = NULL;
464         return D3DERR_INVALIDCALL;
465     }
466
467     /* Allocate the storage for the device object */
468     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDevice9Impl));
469     if (NULL == object) {
470         FIXME("Allocation of memory failed\n");
471         *ppReturnedDeviceInterface = NULL;
472         return D3DERR_OUTOFVIDEOMEMORY;
473     }
474
475     object->lpVtbl = &Direct3DDevice9_Vtbl;
476     object->ref = 1;
477     *ppReturnedDeviceInterface = (IDirect3DDevice9 *)object;
478
479     /* Allocate an associated WineD3DDevice object */
480     EnterCriticalSection(&d3d9_cs);
481     hr =IWineD3D_CreateDevice(This->WineD3D, Adapter, DeviceType, hFocusWindow, BehaviourFlags, &object->WineD3DDevice, (IUnknown *)object);
482
483     if (hr != D3D_OK) {
484         HeapFree(GetProcessHeap(), 0, object);
485         *ppReturnedDeviceInterface = NULL;
486         LeaveCriticalSection(&d3d9_cs);
487         return hr;
488     }
489
490     TRACE("(%p) : Created Device %p\n", This, object);
491
492     localParameters.BackBufferWidth                     = pPresentationParameters->BackBufferWidth;
493     localParameters.BackBufferHeight                    = pPresentationParameters->BackBufferHeight;
494     localParameters.BackBufferFormat                    = pPresentationParameters->BackBufferFormat;
495     localParameters.BackBufferCount                     = pPresentationParameters->BackBufferCount;
496     localParameters.MultiSampleType                     = pPresentationParameters->MultiSampleType;
497     localParameters.MultiSampleQuality                  = pPresentationParameters->MultiSampleQuality;
498     localParameters.SwapEffect                          = pPresentationParameters->SwapEffect;
499     localParameters.hDeviceWindow                       = pPresentationParameters->hDeviceWindow;
500     localParameters.Windowed                            = pPresentationParameters->Windowed;
501     localParameters.EnableAutoDepthStencil              = pPresentationParameters->EnableAutoDepthStencil;
502     localParameters.AutoDepthStencilFormat              = pPresentationParameters->AutoDepthStencilFormat;
503     localParameters.Flags                               = pPresentationParameters->Flags;
504     localParameters.FullScreen_RefreshRateInHz          = pPresentationParameters->FullScreen_RefreshRateInHz;
505     localParameters.PresentationInterval                = pPresentationParameters->PresentationInterval;
506
507     if(BehaviourFlags & D3DCREATE_MULTITHREADED) {
508         IWineD3DDevice_SetMultithreaded(object->WineD3DDevice);
509     }
510
511     hr = IWineD3DDevice_Init3D(object->WineD3DDevice, &localParameters, D3D9CB_CreateAdditionalSwapChain);
512
513     pPresentationParameters->BackBufferWidth            = localParameters.BackBufferWidth;
514     pPresentationParameters->BackBufferHeight           = localParameters.BackBufferHeight;
515     pPresentationParameters->BackBufferFormat           = localParameters.BackBufferFormat;
516     pPresentationParameters->BackBufferCount            = localParameters.BackBufferCount;
517     pPresentationParameters->MultiSampleType            = localParameters.MultiSampleType;
518     pPresentationParameters->MultiSampleQuality         = localParameters.MultiSampleQuality;
519     pPresentationParameters->SwapEffect                 = localParameters.SwapEffect;
520     pPresentationParameters->hDeviceWindow              = localParameters.hDeviceWindow;
521     pPresentationParameters->Windowed                   = localParameters.Windowed;
522     pPresentationParameters->EnableAutoDepthStencil     = localParameters.EnableAutoDepthStencil;
523     pPresentationParameters->AutoDepthStencilFormat     = localParameters.AutoDepthStencilFormat;
524     pPresentationParameters->Flags                      = localParameters.Flags;
525     pPresentationParameters->FullScreen_RefreshRateInHz = localParameters.FullScreen_RefreshRateInHz;
526     pPresentationParameters->PresentationInterval       = localParameters.PresentationInterval;
527
528     if (hr != D3D_OK) {
529         FIXME("(%p) D3D Initialization failed for WineD3DDevice %p\n", This, object->WineD3DDevice);
530         HeapFree(GetProcessHeap(), 0, object);
531         *ppReturnedDeviceInterface = NULL;
532     }
533
534     /* Initialize the converted declaration array. This creates a valid pointer and when adding decls HeapReAlloc
535      * can be used without further checking
536      */
537     object->convertedDecls = HeapAlloc(GetProcessHeap(), 0, 0);
538     LeaveCriticalSection(&d3d9_cs);
539
540     return hr;
541 }
542
543
544
545 const IDirect3D9Vtbl Direct3D9_Vtbl =
546 {
547     /* IUnknown */
548     IDirect3D9Impl_QueryInterface,
549     IDirect3D9Impl_AddRef,
550     IDirect3D9Impl_Release,
551     /* IDirect3D9 */
552     IDirect3D9Impl_RegisterSoftwareDevice,
553     IDirect3D9Impl_GetAdapterCount,
554     IDirect3D9Impl_GetAdapterIdentifier,
555     IDirect3D9Impl_GetAdapterModeCount,
556     IDirect3D9Impl_EnumAdapterModes,
557     IDirect3D9Impl_GetAdapterDisplayMode,
558     IDirect3D9Impl_CheckDeviceType,
559     IDirect3D9Impl_CheckDeviceFormat,
560     IDirect3D9Impl_CheckDeviceMultiSampleType,
561     IDirect3D9Impl_CheckDepthStencilMatch,
562     IDirect3D9Impl_CheckDeviceFormatConversion,
563     IDirect3D9Impl_GetDeviceCaps,
564     IDirect3D9Impl_GetAdapterMonitor,
565     IDirect3D9Impl_CreateDevice
566 };