wined3d: Unbind resources inside wined3d_device_reset().
[wine] / dlls / d3d9 / device.c
1 /*
2  * IDirect3DDevice9 implementation
3  *
4  * Copyright 2002-2005 Jason Edmeades
5  * Copyright 2002-2005 Raphael Junqueira
6  * Copyright 2005 Oliver Stieber
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22
23 #include "config.h"
24 #include "d3d9_private.h"
25
26 WINE_DEFAULT_DEBUG_CHANNEL(d3d9);
27
28 D3DFORMAT d3dformat_from_wined3dformat(enum wined3d_format_id format)
29 {
30     BYTE *c = (BYTE *)&format;
31
32     /* Don't translate FOURCC formats */
33     if (isprint(c[0]) && isprint(c[1]) && isprint(c[2]) && isprint(c[3])) return format;
34
35     switch(format)
36     {
37         case WINED3DFMT_UNKNOWN: return D3DFMT_UNKNOWN;
38         case WINED3DFMT_B8G8R8_UNORM: return D3DFMT_R8G8B8;
39         case WINED3DFMT_B8G8R8A8_UNORM: return D3DFMT_A8R8G8B8;
40         case WINED3DFMT_B8G8R8X8_UNORM: return D3DFMT_X8R8G8B8;
41         case WINED3DFMT_B5G6R5_UNORM: return D3DFMT_R5G6B5;
42         case WINED3DFMT_B5G5R5X1_UNORM: return D3DFMT_X1R5G5B5;
43         case WINED3DFMT_B5G5R5A1_UNORM: return D3DFMT_A1R5G5B5;
44         case WINED3DFMT_B4G4R4A4_UNORM: return D3DFMT_A4R4G4B4;
45         case WINED3DFMT_B2G3R3_UNORM: return D3DFMT_R3G3B2;
46         case WINED3DFMT_A8_UNORM: return D3DFMT_A8;
47         case WINED3DFMT_B2G3R3A8_UNORM: return D3DFMT_A8R3G3B2;
48         case WINED3DFMT_B4G4R4X4_UNORM: return D3DFMT_X4R4G4B4;
49         case WINED3DFMT_R10G10B10A2_UNORM: return D3DFMT_A2B10G10R10;
50         case WINED3DFMT_R8G8B8A8_UNORM: return D3DFMT_A8B8G8R8;
51         case WINED3DFMT_R8G8B8X8_UNORM: return D3DFMT_X8B8G8R8;
52         case WINED3DFMT_R16G16_UNORM: return D3DFMT_G16R16;
53         case WINED3DFMT_B10G10R10A2_UNORM: return D3DFMT_A2R10G10B10;
54         case WINED3DFMT_R16G16B16A16_UNORM: return D3DFMT_A16B16G16R16;
55         case WINED3DFMT_P8_UINT_A8_UNORM: return D3DFMT_A8P8;
56         case WINED3DFMT_P8_UINT: return D3DFMT_P8;
57         case WINED3DFMT_L8_UNORM: return D3DFMT_L8;
58         case WINED3DFMT_L8A8_UNORM: return D3DFMT_A8L8;
59         case WINED3DFMT_L4A4_UNORM: return D3DFMT_A4L4;
60         case WINED3DFMT_R8G8_SNORM: return D3DFMT_V8U8;
61         case WINED3DFMT_R5G5_SNORM_L6_UNORM: return D3DFMT_L6V5U5;
62         case WINED3DFMT_R8G8_SNORM_L8X8_UNORM: return D3DFMT_X8L8V8U8;
63         case WINED3DFMT_R8G8B8A8_SNORM: return D3DFMT_Q8W8V8U8;
64         case WINED3DFMT_R16G16_SNORM: return D3DFMT_V16U16;
65         case WINED3DFMT_R10G10B10_SNORM_A2_UNORM: return D3DFMT_A2W10V10U10;
66         case WINED3DFMT_D16_LOCKABLE: return D3DFMT_D16_LOCKABLE;
67         case WINED3DFMT_D32_UNORM: return D3DFMT_D32;
68         case WINED3DFMT_S1_UINT_D15_UNORM: return D3DFMT_D15S1;
69         case WINED3DFMT_D24_UNORM_S8_UINT: return D3DFMT_D24S8;
70         case WINED3DFMT_X8D24_UNORM: return D3DFMT_D24X8;
71         case WINED3DFMT_S4X4_UINT_D24_UNORM: return D3DFMT_D24X4S4;
72         case WINED3DFMT_D16_UNORM: return D3DFMT_D16;
73         case WINED3DFMT_L16_UNORM: return D3DFMT_L16;
74         case WINED3DFMT_D32_FLOAT: return D3DFMT_D32F_LOCKABLE;
75         case WINED3DFMT_S8_UINT_D24_FLOAT: return D3DFMT_D24FS8;
76         case WINED3DFMT_VERTEXDATA: return D3DFMT_VERTEXDATA;
77         case WINED3DFMT_R16_UINT: return D3DFMT_INDEX16;
78         case WINED3DFMT_R32_UINT: return D3DFMT_INDEX32;
79         case WINED3DFMT_R16G16B16A16_SNORM: return D3DFMT_Q16W16V16U16;
80         case WINED3DFMT_R16_FLOAT: return D3DFMT_R16F;
81         case WINED3DFMT_R16G16_FLOAT: return D3DFMT_G16R16F;
82         case WINED3DFMT_R16G16B16A16_FLOAT: return D3DFMT_A16B16G16R16F;
83         case WINED3DFMT_R32_FLOAT: return D3DFMT_R32F;
84         case WINED3DFMT_R32G32_FLOAT: return D3DFMT_G32R32F;
85         case WINED3DFMT_R32G32B32A32_FLOAT: return D3DFMT_A32B32G32R32F;
86         case WINED3DFMT_R8G8_SNORM_Cx: return D3DFMT_CxV8U8;
87         default:
88             FIXME("Unhandled wined3d format %#x.\n", format);
89             return D3DFMT_UNKNOWN;
90     }
91 }
92
93 enum wined3d_format_id wined3dformat_from_d3dformat(D3DFORMAT format)
94 {
95     BYTE *c = (BYTE *)&format;
96
97     /* Don't translate FOURCC formats */
98     if (isprint(c[0]) && isprint(c[1]) && isprint(c[2]) && isprint(c[3])) return format;
99
100     switch(format)
101     {
102         case D3DFMT_UNKNOWN: return WINED3DFMT_UNKNOWN;
103         case D3DFMT_R8G8B8: return WINED3DFMT_B8G8R8_UNORM;
104         case D3DFMT_A8R8G8B8: return WINED3DFMT_B8G8R8A8_UNORM;
105         case D3DFMT_X8R8G8B8: return WINED3DFMT_B8G8R8X8_UNORM;
106         case D3DFMT_R5G6B5: return WINED3DFMT_B5G6R5_UNORM;
107         case D3DFMT_X1R5G5B5: return WINED3DFMT_B5G5R5X1_UNORM;
108         case D3DFMT_A1R5G5B5: return WINED3DFMT_B5G5R5A1_UNORM;
109         case D3DFMT_A4R4G4B4: return WINED3DFMT_B4G4R4A4_UNORM;
110         case D3DFMT_R3G3B2: return WINED3DFMT_B2G3R3_UNORM;
111         case D3DFMT_A8: return WINED3DFMT_A8_UNORM;
112         case D3DFMT_A8R3G3B2: return WINED3DFMT_B2G3R3A8_UNORM;
113         case D3DFMT_X4R4G4B4: return WINED3DFMT_B4G4R4X4_UNORM;
114         case D3DFMT_A2B10G10R10: return WINED3DFMT_R10G10B10A2_UNORM;
115         case D3DFMT_A8B8G8R8: return WINED3DFMT_R8G8B8A8_UNORM;
116         case D3DFMT_X8B8G8R8: return WINED3DFMT_R8G8B8X8_UNORM;
117         case D3DFMT_G16R16: return WINED3DFMT_R16G16_UNORM;
118         case D3DFMT_A2R10G10B10: return WINED3DFMT_B10G10R10A2_UNORM;
119         case D3DFMT_A16B16G16R16: return WINED3DFMT_R16G16B16A16_UNORM;
120         case D3DFMT_A8P8: return WINED3DFMT_P8_UINT_A8_UNORM;
121         case D3DFMT_P8: return WINED3DFMT_P8_UINT;
122         case D3DFMT_L8: return WINED3DFMT_L8_UNORM;
123         case D3DFMT_A8L8: return WINED3DFMT_L8A8_UNORM;
124         case D3DFMT_A4L4: return WINED3DFMT_L4A4_UNORM;
125         case D3DFMT_V8U8: return WINED3DFMT_R8G8_SNORM;
126         case D3DFMT_L6V5U5: return WINED3DFMT_R5G5_SNORM_L6_UNORM;
127         case D3DFMT_X8L8V8U8: return WINED3DFMT_R8G8_SNORM_L8X8_UNORM;
128         case D3DFMT_Q8W8V8U8: return WINED3DFMT_R8G8B8A8_SNORM;
129         case D3DFMT_V16U16: return WINED3DFMT_R16G16_SNORM;
130         case D3DFMT_A2W10V10U10: return WINED3DFMT_R10G10B10_SNORM_A2_UNORM;
131         case D3DFMT_D16_LOCKABLE: return WINED3DFMT_D16_LOCKABLE;
132         case D3DFMT_D32: return WINED3DFMT_D32_UNORM;
133         case D3DFMT_D15S1: return WINED3DFMT_S1_UINT_D15_UNORM;
134         case D3DFMT_D24S8: return WINED3DFMT_D24_UNORM_S8_UINT;
135         case D3DFMT_D24X8: return WINED3DFMT_X8D24_UNORM;
136         case D3DFMT_D24X4S4: return WINED3DFMT_S4X4_UINT_D24_UNORM;
137         case D3DFMT_D16: return WINED3DFMT_D16_UNORM;
138         case D3DFMT_L16: return WINED3DFMT_L16_UNORM;
139         case D3DFMT_D32F_LOCKABLE: return WINED3DFMT_D32_FLOAT;
140         case D3DFMT_D24FS8: return WINED3DFMT_S8_UINT_D24_FLOAT;
141         case D3DFMT_VERTEXDATA: return WINED3DFMT_VERTEXDATA;
142         case D3DFMT_INDEX16: return WINED3DFMT_R16_UINT;
143         case D3DFMT_INDEX32: return WINED3DFMT_R32_UINT;
144         case D3DFMT_Q16W16V16U16: return WINED3DFMT_R16G16B16A16_SNORM;
145         case D3DFMT_R16F: return WINED3DFMT_R16_FLOAT;
146         case D3DFMT_G16R16F: return WINED3DFMT_R16G16_FLOAT;
147         case D3DFMT_A16B16G16R16F: return WINED3DFMT_R16G16B16A16_FLOAT;
148         case D3DFMT_R32F: return WINED3DFMT_R32_FLOAT;
149         case D3DFMT_G32R32F: return WINED3DFMT_R32G32_FLOAT;
150         case D3DFMT_A32B32G32R32F: return WINED3DFMT_R32G32B32A32_FLOAT;
151         case D3DFMT_CxV8U8: return WINED3DFMT_R8G8_SNORM_Cx;
152         default:
153             FIXME("Unhandled D3DFORMAT %#x\n", format);
154             return WINED3DFMT_UNKNOWN;
155     }
156 }
157
158 static UINT vertex_count_from_primitive_count(D3DPRIMITIVETYPE primitive_type, UINT primitive_count)
159 {
160     switch(primitive_type)
161     {
162         case D3DPT_POINTLIST:
163             return primitive_count;
164
165         case D3DPT_LINELIST:
166             return primitive_count * 2;
167
168         case D3DPT_LINESTRIP:
169             return primitive_count + 1;
170
171         case D3DPT_TRIANGLELIST:
172             return primitive_count * 3;
173
174         case D3DPT_TRIANGLESTRIP:
175         case D3DPT_TRIANGLEFAN:
176             return primitive_count + 2;
177
178         default:
179             FIXME("Unhandled primitive type %#x\n", primitive_type);
180             return 0;
181     }
182 }
183
184 static inline IDirect3DDevice9Impl *impl_from_IDirect3DDevice9Ex(IDirect3DDevice9Ex *iface)
185 {
186     return CONTAINING_RECORD(iface, IDirect3DDevice9Impl, IDirect3DDevice9Ex_iface);
187 }
188
189 static HRESULT WINAPI IDirect3DDevice9Impl_QueryInterface(IDirect3DDevice9Ex *iface, REFIID riid,
190         void **ppobj)
191 {
192     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
193     IDirect3D9 *d3d;
194     IDirect3D9Impl *d3dimpl;
195
196     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), ppobj);
197
198     if (IsEqualGUID(riid, &IID_IUnknown)
199         || IsEqualGUID(riid, &IID_IDirect3DDevice9)) {
200         IDirect3DDevice9Ex_AddRef(iface);
201         *ppobj = This;
202         TRACE("Returning IDirect3DDevice9 interface at %p\n", *ppobj);
203         return S_OK;
204     } else if(IsEqualGUID(riid, &IID_IDirect3DDevice9Ex)) {
205         /* Find out if the creating d3d9 interface was created with Direct3DCreate9Ex.
206          * It doesn't matter with which function the device was created.
207          */
208         IDirect3DDevice9_GetDirect3D(iface, &d3d);
209         d3dimpl = (IDirect3D9Impl *) d3d;
210
211         if(d3dimpl->extended) {
212             *ppobj = iface;
213             IDirect3DDevice9Ex_AddRef((IDirect3DDevice9Ex *) *ppobj);
214             IDirect3D9_Release(d3d);
215             TRACE("Returning IDirect3DDevice9Ex interface at %p\n", *ppobj);
216             return S_OK;
217         } else {
218             WARN("IDirect3D9 instance wasn't created with CreateDirect3D9Ex, returning E_NOINTERFACE\n");
219             IDirect3D9_Release(d3d);
220             *ppobj = NULL;
221             return E_NOINTERFACE;
222         }
223     }
224
225     WARN("(%p)->(%s,%p),not found\n", This, debugstr_guid(riid), ppobj);
226     *ppobj = NULL;
227     return E_NOINTERFACE;
228 }
229
230 static ULONG WINAPI IDirect3DDevice9Impl_AddRef(IDirect3DDevice9Ex *iface)
231 {
232     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
233     ULONG ref = InterlockedIncrement(&This->ref);
234
235     TRACE("%p increasing refcount to %u.\n", iface, ref);
236
237     return ref;
238 }
239
240 static ULONG WINAPI DECLSPEC_HOTPATCH IDirect3DDevice9Impl_Release(IDirect3DDevice9Ex *iface)
241 {
242     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
243     ULONG ref;
244
245     if (This->inDestruction) return 0;
246     ref = InterlockedDecrement(&This->ref);
247
248     TRACE("%p decreasing refcount to %u.\n", iface, ref);
249
250     if (ref == 0) {
251       unsigned i;
252       This->inDestruction = TRUE;
253
254       wined3d_mutex_lock();
255       for(i = 0; i < This->numConvertedDecls; i++) {
256           /* Unless Wine is buggy or the app has a bug the refcount will be 0, because decls hold a reference to the
257            * device
258            */
259           IDirect3DVertexDeclaration9Impl_Destroy(This->convertedDecls[i]);
260       }
261       HeapFree(GetProcessHeap(), 0, This->convertedDecls);
262
263       wined3d_device_uninit_3d(This->wined3d_device);
264       wined3d_device_release_focus_window(This->wined3d_device);
265       wined3d_device_decref(This->wined3d_device);
266       wined3d_mutex_unlock();
267
268       IDirect3D9_Release(This->d3d_parent);
269
270       HeapFree(GetProcessHeap(), 0, This);
271     }
272     return ref;
273 }
274
275 static HRESULT WINAPI IDirect3DDevice9Impl_TestCooperativeLevel(IDirect3DDevice9Ex *iface)
276 {
277     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
278
279     TRACE("iface %p.\n", iface);
280
281     if (This->notreset)
282     {
283         TRACE("D3D9 device is marked not reset.\n");
284         return D3DERR_DEVICENOTRESET;
285     }
286
287     return D3D_OK;
288 }
289
290 static UINT WINAPI IDirect3DDevice9Impl_GetAvailableTextureMem(IDirect3DDevice9Ex *iface)
291 {
292     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
293     HRESULT hr;
294
295     TRACE("iface %p.\n", iface);
296
297     wined3d_mutex_lock();
298     hr = wined3d_device_get_available_texture_mem(This->wined3d_device);
299     wined3d_mutex_unlock();
300
301     return hr;
302 }
303
304 static HRESULT WINAPI IDirect3DDevice9Impl_EvictManagedResources(IDirect3DDevice9Ex *iface)
305 {
306     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
307     HRESULT hr;
308
309     TRACE("iface %p.\n", iface);
310
311     wined3d_mutex_lock();
312     hr = wined3d_device_evict_managed_resources(This->wined3d_device);
313     wined3d_mutex_unlock();
314
315     return hr;
316 }
317
318 static HRESULT WINAPI IDirect3DDevice9Impl_GetDirect3D(IDirect3DDevice9Ex *iface,
319         IDirect3D9 **ppD3D9)
320 {
321     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
322
323     TRACE("iface %p, d3d9 %p.\n", iface, ppD3D9);
324
325     if (NULL == ppD3D9) {
326         return D3DERR_INVALIDCALL;
327     }
328
329     return IDirect3D9Ex_QueryInterface(This->d3d_parent, &IID_IDirect3D9, (void **)ppD3D9);
330 }
331
332 static HRESULT WINAPI IDirect3DDevice9Impl_GetDeviceCaps(IDirect3DDevice9Ex *iface, D3DCAPS9 *pCaps)
333 {
334     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
335     HRESULT hrc = D3D_OK;
336     WINED3DCAPS *pWineCaps;
337
338     TRACE("iface %p, caps %p.\n", iface, pCaps);
339
340     if(NULL == pCaps){
341         return D3DERR_INVALIDCALL;
342     }
343     pWineCaps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WINED3DCAPS));
344     if(pWineCaps == NULL){
345         return D3DERR_INVALIDCALL; /* well this is what MSDN says to return */
346     }
347
348     memset(pCaps, 0, sizeof(*pCaps));
349
350     wined3d_mutex_lock();
351     hrc = wined3d_device_get_device_caps(This->wined3d_device, pWineCaps);
352     wined3d_mutex_unlock();
353
354     WINECAPSTOD3D9CAPS(pCaps, pWineCaps)
355     HeapFree(GetProcessHeap(), 0, pWineCaps);
356
357     /* Some functionality is implemented in d3d9.dll, not wined3d.dll. Add the needed caps */
358     pCaps->DevCaps2 |= D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES;
359
360     filter_caps(pCaps);
361
362     TRACE("Returning %p %p\n", This, pCaps);
363     return hrc;
364 }
365
366 static HRESULT WINAPI IDirect3DDevice9Impl_GetDisplayMode(IDirect3DDevice9Ex *iface,
367         UINT iSwapChain, D3DDISPLAYMODE *pMode)
368 {
369     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
370     HRESULT hr;
371
372     TRACE("iface %p, swapchain %u, mode %p.\n", iface, iSwapChain, pMode);
373
374     wined3d_mutex_lock();
375     hr = wined3d_device_get_display_mode(This->wined3d_device, iSwapChain, (WINED3DDISPLAYMODE *)pMode);
376     wined3d_mutex_unlock();
377
378     if (SUCCEEDED(hr)) pMode->Format = d3dformat_from_wined3dformat(pMode->Format);
379
380     return hr;
381 }
382
383 static HRESULT WINAPI IDirect3DDevice9Impl_GetCreationParameters(IDirect3DDevice9Ex *iface,
384         D3DDEVICE_CREATION_PARAMETERS *pParameters)
385 {
386     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
387     HRESULT hr;
388
389     TRACE("iface %p, parameters %p.\n", iface, pParameters);
390
391     wined3d_mutex_lock();
392     hr = wined3d_device_get_creation_parameters(This->wined3d_device,
393             (WINED3DDEVICE_CREATION_PARAMETERS *)pParameters);
394     wined3d_mutex_unlock();
395
396     return hr;
397 }
398
399 static HRESULT WINAPI IDirect3DDevice9Impl_SetCursorProperties(IDirect3DDevice9Ex *iface,
400         UINT XHotSpot, UINT YHotSpot, IDirect3DSurface9 *pCursorBitmap)
401 {
402     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
403     IDirect3DSurface9Impl *pSurface = unsafe_impl_from_IDirect3DSurface9(pCursorBitmap);
404     HRESULT hr;
405
406     TRACE("iface %p, hotspot_x %u, hotspot_y %u, bitmap %p.\n",
407             iface, XHotSpot, YHotSpot, pCursorBitmap);
408
409     if (!pCursorBitmap)
410     {
411         WARN("No cursor bitmap, returning D3DERR_INVALIDCALL.\n");
412         return D3DERR_INVALIDCALL;
413     }
414
415     wined3d_mutex_lock();
416     hr = wined3d_device_set_cursor_properties(This->wined3d_device, XHotSpot, YHotSpot, pSurface->wined3d_surface);
417     wined3d_mutex_unlock();
418
419     return hr;
420 }
421
422 static void WINAPI IDirect3DDevice9Impl_SetCursorPosition(IDirect3DDevice9Ex *iface,
423         int XScreenSpace, int YScreenSpace, DWORD Flags)
424 {
425     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
426
427     TRACE("iface %p, x %u, y %u, flags %#x.\n", iface, XScreenSpace, YScreenSpace, Flags);
428
429     wined3d_mutex_lock();
430     wined3d_device_set_cursor_position(This->wined3d_device, XScreenSpace, YScreenSpace, Flags);
431     wined3d_mutex_unlock();
432 }
433
434 static BOOL WINAPI IDirect3DDevice9Impl_ShowCursor(IDirect3DDevice9Ex *iface, BOOL bShow)
435 {
436     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
437     BOOL ret;
438
439     TRACE("iface %p, show %#x.\n", iface, bShow);
440
441     wined3d_mutex_lock();
442     ret = wined3d_device_show_cursor(This->wined3d_device, bShow);
443     wined3d_mutex_unlock();
444
445     return ret;
446 }
447
448 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDevice9Impl_CreateAdditionalSwapChain(IDirect3DDevice9Ex *iface,
449         D3DPRESENT_PARAMETERS *present_parameters, IDirect3DSwapChain9 **swapchain)
450 {
451     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
452     IDirect3DSwapChain9Impl *object;
453     HRESULT hr;
454
455     TRACE("iface %p, present_parameters %p, swapchain %p.\n",
456             iface, present_parameters, swapchain);
457
458     object = HeapAlloc(GetProcessHeap(),  HEAP_ZERO_MEMORY, sizeof(*object));
459     if (!object)
460     {
461         ERR("Failed to allocate swapchain memory.\n");
462         return E_OUTOFMEMORY;
463     }
464
465     hr = swapchain_init(object, This, present_parameters);
466     if (FAILED(hr))
467     {
468         WARN("Failed to initialize swapchain, hr %#x.\n", hr);
469         HeapFree(GetProcessHeap(), 0, object);
470         return hr;
471     }
472
473     TRACE("Created swapchain %p.\n", object);
474     *swapchain = (IDirect3DSwapChain9 *)object;
475
476     return D3D_OK;
477 }
478
479 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDevice9Impl_GetSwapChain(IDirect3DDevice9Ex *iface,
480         UINT swapchain_idx, IDirect3DSwapChain9 **swapchain)
481 {
482     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
483     struct wined3d_swapchain *wined3d_swapchain = NULL;
484     HRESULT hr;
485
486     TRACE("iface %p, swapchain_idx %u, swapchain %p.\n", iface, swapchain_idx, swapchain);
487
488     wined3d_mutex_lock();
489     hr = wined3d_device_get_swapchain(This->wined3d_device, swapchain_idx, &wined3d_swapchain);
490     if (SUCCEEDED(hr) && wined3d_swapchain)
491     {
492        *swapchain = wined3d_swapchain_get_parent(wined3d_swapchain);
493        IDirect3DSwapChain9_AddRef(*swapchain);
494        wined3d_swapchain_decref(wined3d_swapchain);
495     }
496     else
497     {
498         *swapchain = NULL;
499     }
500     wined3d_mutex_unlock();
501
502     return hr;
503 }
504
505 static UINT WINAPI IDirect3DDevice9Impl_GetNumberOfSwapChains(IDirect3DDevice9Ex *iface)
506 {
507     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
508     UINT count;
509
510     TRACE("iface %p.\n", iface);
511
512     wined3d_mutex_lock();
513     count = wined3d_device_get_swapchain_count(This->wined3d_device);
514     wined3d_mutex_unlock();
515
516     return count;
517 }
518
519 static HRESULT CDECL reset_enum_callback(struct wined3d_resource *resource)
520 {
521     struct wined3d_resource_desc desc;
522
523     wined3d_resource_get_desc(resource, &desc);
524     if (desc.pool == WINED3DPOOL_DEFAULT)
525     {
526         IDirect3DSurface9 *surface;
527
528         if (desc.resource_type != WINED3DRTYPE_SURFACE)
529         {
530             WARN("Resource %p in pool D3DPOOL_DEFAULT blocks the Reset call.\n", resource);
531             return D3DERR_INVALIDCALL;
532         }
533
534         surface = wined3d_resource_get_parent(resource);
535
536         IDirect3DSurface9_AddRef(surface);
537         if (IDirect3DSurface9_Release(surface))
538         {
539             WARN("Surface %p (resource %p) in pool D3DPOOL_DEFAULT blocks the Reset call.\n", surface, resource);
540             return D3DERR_INVALIDCALL;
541         }
542
543         WARN("Surface %p (resource %p) is an implicit resource with ref 0.\n", surface, resource);
544     }
545
546     return D3D_OK;
547 }
548
549 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDevice9Impl_Reset(IDirect3DDevice9Ex *iface,
550         D3DPRESENT_PARAMETERS *pPresentationParameters)
551 {
552     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
553     WINED3DPRESENT_PARAMETERS localParameters;
554     HRESULT hr;
555
556     TRACE("iface %p, present_parameters %p.\n", iface, pPresentationParameters);
557
558     /* Reset states that hold a COM object. WineD3D holds an internal reference to set objects, because
559      * such objects can still be used for rendering after their external d3d9 object has been destroyed.
560      * These objects must not be enumerated. Unsetting them tells WineD3D that the application will not
561      * make use of the hidden reference and destroys the objects.
562      *
563      * Unsetting them is no problem, because the states are supposed to be reset anyway. If the validation
564      * below fails, the device is considered "lost", and _Reset and _Release are the only allowed calls
565      */
566     wined3d_mutex_lock();
567
568     localParameters.BackBufferWidth                     = pPresentationParameters->BackBufferWidth;
569     localParameters.BackBufferHeight                    = pPresentationParameters->BackBufferHeight;
570     localParameters.BackBufferFormat                    = wined3dformat_from_d3dformat(pPresentationParameters->BackBufferFormat);
571     localParameters.BackBufferCount                     = pPresentationParameters->BackBufferCount;
572     localParameters.MultiSampleType                     = pPresentationParameters->MultiSampleType;
573     localParameters.MultiSampleQuality                  = pPresentationParameters->MultiSampleQuality;
574     localParameters.SwapEffect                          = pPresentationParameters->SwapEffect;
575     localParameters.hDeviceWindow                       = pPresentationParameters->hDeviceWindow;
576     localParameters.Windowed                            = pPresentationParameters->Windowed;
577     localParameters.EnableAutoDepthStencil              = pPresentationParameters->EnableAutoDepthStencil;
578     localParameters.AutoDepthStencilFormat              = wined3dformat_from_d3dformat(pPresentationParameters->AutoDepthStencilFormat);
579     localParameters.Flags                               = pPresentationParameters->Flags;
580     localParameters.FullScreen_RefreshRateInHz          = pPresentationParameters->FullScreen_RefreshRateInHz;
581     localParameters.PresentationInterval                = pPresentationParameters->PresentationInterval;
582     localParameters.AutoRestoreDisplayMode              = TRUE;
583
584     hr = wined3d_device_reset(This->wined3d_device, &localParameters, reset_enum_callback);
585     if (FAILED(hr))
586     {
587         This->notreset = TRUE;
588
589         pPresentationParameters->BackBufferWidth            = localParameters.BackBufferWidth;
590         pPresentationParameters->BackBufferHeight           = localParameters.BackBufferHeight;
591         pPresentationParameters->BackBufferFormat           = d3dformat_from_wined3dformat(localParameters.BackBufferFormat);
592         pPresentationParameters->BackBufferCount            = localParameters.BackBufferCount;
593         pPresentationParameters->MultiSampleType            = localParameters.MultiSampleType;
594         pPresentationParameters->MultiSampleQuality         = localParameters.MultiSampleQuality;
595         pPresentationParameters->SwapEffect                 = localParameters.SwapEffect;
596         pPresentationParameters->hDeviceWindow              = localParameters.hDeviceWindow;
597         pPresentationParameters->Windowed                   = localParameters.Windowed;
598         pPresentationParameters->EnableAutoDepthStencil     = localParameters.EnableAutoDepthStencil;
599         pPresentationParameters->AutoDepthStencilFormat     = d3dformat_from_wined3dformat(localParameters.AutoDepthStencilFormat);
600         pPresentationParameters->Flags                      = localParameters.Flags;
601         pPresentationParameters->FullScreen_RefreshRateInHz = localParameters.FullScreen_RefreshRateInHz;
602         pPresentationParameters->PresentationInterval       = localParameters.PresentationInterval;
603     } else {
604         This->notreset = FALSE;
605     }
606
607     wined3d_mutex_unlock();
608
609     return hr;
610 }
611
612 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDevice9Impl_Present(IDirect3DDevice9Ex *iface,
613         const RECT *pSourceRect, const RECT *pDestRect, HWND hDestWindowOverride,
614         const RGNDATA *pDirtyRegion)
615 {
616     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
617     HRESULT hr;
618
619     TRACE("iface %p, src_rect %p, dst_rect %p, dst_window_override %p, dirty_region %p.\n",
620             iface, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion);
621
622     wined3d_mutex_lock();
623     hr = wined3d_device_present(This->wined3d_device, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion);
624     wined3d_mutex_unlock();
625
626     return hr;
627  }
628
629 static HRESULT WINAPI IDirect3DDevice9Impl_GetBackBuffer(IDirect3DDevice9Ex *iface,
630         UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface9 **ppBackBuffer)
631 {
632     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
633     struct wined3d_surface *wined3d_surface = NULL;
634     HRESULT hr;
635
636     TRACE("iface %p, swapchain %u, backbuffer_idx %u, backbuffer_type %#x, backbuffer %p.\n",
637             iface, iSwapChain, BackBuffer, Type, ppBackBuffer);
638
639     wined3d_mutex_lock();
640     hr = wined3d_device_get_back_buffer(This->wined3d_device, iSwapChain,
641             BackBuffer, (WINED3DBACKBUFFER_TYPE) Type, &wined3d_surface);
642     if (SUCCEEDED(hr) && wined3d_surface && ppBackBuffer)
643     {
644         *ppBackBuffer = wined3d_surface_get_parent(wined3d_surface);
645         IDirect3DSurface9_AddRef(*ppBackBuffer);
646         wined3d_surface_decref(wined3d_surface);
647     }
648     wined3d_mutex_unlock();
649
650     return hr;
651 }
652 static HRESULT WINAPI IDirect3DDevice9Impl_GetRasterStatus(IDirect3DDevice9Ex *iface,
653         UINT iSwapChain, D3DRASTER_STATUS *pRasterStatus)
654 {
655     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
656     HRESULT hr;
657
658     TRACE("iface %p, swapchain %u, raster_status %p.\n", iface, iSwapChain, pRasterStatus);
659
660     wined3d_mutex_lock();
661     hr = wined3d_device_get_raster_status(This->wined3d_device, iSwapChain, (WINED3DRASTER_STATUS *)pRasterStatus);
662     wined3d_mutex_unlock();
663
664     return hr;
665 }
666
667 static HRESULT WINAPI IDirect3DDevice9Impl_SetDialogBoxMode(IDirect3DDevice9Ex *iface,
668         BOOL bEnableDialogs)
669 {
670     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
671     HRESULT hr;
672
673     TRACE("iface %p, enable %#x.\n", iface, bEnableDialogs);
674
675     wined3d_mutex_lock();
676     hr = wined3d_device_set_dialog_box_mode(This->wined3d_device, bEnableDialogs);
677     wined3d_mutex_unlock();
678
679     return hr;
680 }
681
682 static void WINAPI IDirect3DDevice9Impl_SetGammaRamp(IDirect3DDevice9Ex *iface, UINT iSwapChain,
683         DWORD Flags, const D3DGAMMARAMP *pRamp)
684 {
685     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
686
687     TRACE("iface %p, swapchain %u, flags %#x, ramp %p.\n", iface, iSwapChain, Flags, pRamp);
688
689     /* Note: D3DGAMMARAMP is compatible with WINED3DGAMMARAMP */
690     wined3d_mutex_lock();
691     wined3d_device_set_gamma_ramp(This->wined3d_device, iSwapChain, Flags, (const WINED3DGAMMARAMP *)pRamp);
692     wined3d_mutex_unlock();
693 }
694
695 static void WINAPI IDirect3DDevice9Impl_GetGammaRamp(IDirect3DDevice9Ex *iface, UINT iSwapChain,
696         D3DGAMMARAMP *pRamp)
697 {
698     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
699
700     TRACE("iface %p, swapchain %u, ramp %p.\n", iface, iSwapChain, pRamp);
701
702     /* Note: D3DGAMMARAMP is compatible with WINED3DGAMMARAMP */
703     wined3d_mutex_lock();
704     wined3d_device_get_gamma_ramp(This->wined3d_device, iSwapChain, (WINED3DGAMMARAMP *)pRamp);
705     wined3d_mutex_unlock();
706 }
707
708 static HRESULT WINAPI IDirect3DDevice9Impl_CreateTexture(IDirect3DDevice9Ex *iface,
709         UINT width, UINT height, UINT levels, DWORD usage, D3DFORMAT format,
710         D3DPOOL pool, IDirect3DTexture9 **texture, HANDLE *shared_handle)
711 {
712     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
713     IDirect3DTexture9Impl *object;
714     HRESULT hr;
715
716     TRACE("iface %p, width %u, height %u, levels %u, usage %#x, format %#x, pool %#x, texture %p, shared_handle %p.\n",
717             iface, width, height, levels, usage, format, pool, texture, shared_handle);
718
719     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
720     if (!object)
721     {
722         ERR("Failed to allocate texture memory.\n");
723         return D3DERR_OUTOFVIDEOMEMORY;
724     }
725
726     hr = texture_init(object, This, width, height, levels, usage, format, pool);
727     if (FAILED(hr))
728     {
729         WARN("Failed to initialize texture, hr %#x.\n", hr);
730         HeapFree(GetProcessHeap(), 0, object);
731         return hr;
732     }
733
734     TRACE("Created texture %p.\n", object);
735     *texture = &object->IDirect3DTexture9_iface;
736
737     return D3D_OK;
738 }
739
740 static HRESULT WINAPI IDirect3DDevice9Impl_CreateVolumeTexture(IDirect3DDevice9Ex *iface,
741         UINT width, UINT height, UINT depth, UINT levels, DWORD usage, D3DFORMAT format,
742         D3DPOOL pool, IDirect3DVolumeTexture9 **texture, HANDLE *shared_handle)
743 {
744     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
745     IDirect3DVolumeTexture9Impl *object;
746     HRESULT hr;
747
748     TRACE("iface %p, width %u, height %u, depth %u, levels %u\n",
749             iface, width, height, depth, levels);
750     TRACE("usage %#x, format %#x, pool %#x, texture %p, shared_handle %p.\n",
751             usage, format, pool, texture, shared_handle);
752
753     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
754     if (!object)
755     {
756         ERR("Failed to allocate volume texture memory.\n");
757         return D3DERR_OUTOFVIDEOMEMORY;
758     }
759
760     hr = volumetexture_init(object, This, width, height, depth, levels, usage, format, pool);
761     if (FAILED(hr))
762     {
763         WARN("Failed to initialize volume texture, hr %#x.\n", hr);
764         HeapFree(GetProcessHeap(), 0, object);
765         return hr;
766     }
767
768     TRACE("Created volume texture %p.\n", object);
769     *texture = &object->IDirect3DVolumeTexture9_iface;
770
771     return D3D_OK;
772 }
773
774 static HRESULT WINAPI IDirect3DDevice9Impl_CreateCubeTexture(IDirect3DDevice9Ex *iface,
775         UINT edge_length, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool,
776         IDirect3DCubeTexture9 **texture, HANDLE *shared_handle)
777 {
778     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
779     IDirect3DCubeTexture9Impl *object;
780     HRESULT hr;
781
782     TRACE("iface %p, edge_length %u, levels %u, usage %#x, format %#x, pool %#x, texture %p, shared_handle %p.\n",
783             iface, edge_length, levels, usage, format, pool, texture, shared_handle);
784
785     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
786     if (!object)
787     {
788         ERR("Failed to allocate cube texture memory.\n");
789         return D3DERR_OUTOFVIDEOMEMORY;
790     }
791
792     hr = cubetexture_init(object, This, edge_length, levels, usage, format, pool);
793     if (FAILED(hr))
794     {
795         WARN("Failed to initialize cube texture, hr %#x.\n", hr);
796         HeapFree(GetProcessHeap(), 0, object);
797         return hr;
798     }
799
800     TRACE("Created cube texture %p.\n", object);
801     *texture = &object->IDirect3DCubeTexture9_iface;
802
803     return D3D_OK;
804 }
805
806 static HRESULT WINAPI IDirect3DDevice9Impl_CreateVertexBuffer(IDirect3DDevice9Ex *iface, UINT size,
807         DWORD usage, DWORD fvf, D3DPOOL pool, IDirect3DVertexBuffer9 **buffer,
808         HANDLE *shared_handle)
809 {
810     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
811     IDirect3DVertexBuffer9Impl *object;
812     HRESULT hr;
813
814     TRACE("iface %p, size %u, usage %#x, fvf %#x, pool %#x, buffer %p, shared_handle %p.\n",
815             iface, size, usage, fvf, pool, buffer, shared_handle);
816
817     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
818     if (!object)
819     {
820         ERR("Failed to allocate buffer memory.\n");
821         return D3DERR_OUTOFVIDEOMEMORY;
822     }
823
824     hr = vertexbuffer_init(object, This, size, usage, fvf, pool);
825     if (FAILED(hr))
826     {
827         WARN("Failed to initialize vertex buffer, hr %#x.\n", hr);
828         HeapFree(GetProcessHeap(), 0, object);
829         return hr;
830     }
831
832     TRACE("Created vertex buffer %p.\n", object);
833     *buffer = &object->IDirect3DVertexBuffer9_iface;
834
835     return D3D_OK;
836 }
837
838 static HRESULT WINAPI IDirect3DDevice9Impl_CreateIndexBuffer(IDirect3DDevice9Ex *iface, UINT size,
839         DWORD usage, D3DFORMAT format, D3DPOOL pool, IDirect3DIndexBuffer9 **buffer,
840         HANDLE *shared_handle)
841 {
842     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
843     IDirect3DIndexBuffer9Impl *object;
844     HRESULT hr;
845
846     TRACE("iface %p, size %u, usage %#x, format %#x, pool %#x, buffer %p, shared_handle %p.\n",
847             iface, size, usage, format, pool, buffer, shared_handle);
848
849     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
850     if (!object)
851     {
852         ERR("Failed to allocate buffer memory.\n");
853         return D3DERR_OUTOFVIDEOMEMORY;
854     }
855
856     hr = indexbuffer_init(object, This, size, usage, format, pool);
857     if (FAILED(hr))
858     {
859         WARN("Failed to initialize index buffer, hr %#x.\n", hr);
860         HeapFree(GetProcessHeap(), 0, object);
861         return hr;
862     }
863
864     TRACE("Created index buffer %p.\n", object);
865     *buffer = &object->IDirect3DIndexBuffer9_iface;
866
867     return D3D_OK;
868 }
869
870 static HRESULT IDirect3DDevice9Impl_CreateSurface(IDirect3DDevice9Impl *device, UINT Width,
871         UINT Height, D3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level,
872         IDirect3DSurface9 **ppSurface, UINT Usage, D3DPOOL Pool, D3DMULTISAMPLE_TYPE MultiSample,
873         DWORD MultisampleQuality)
874 {
875     IDirect3DSurface9Impl *object;
876     HRESULT hr;
877
878     TRACE("device %p, width %u, height %u, format %#x, lockable %#x, discard %#x, level %u, surface %p.\n"
879             "usage %#x, pool %#x, multisample_type %#x, multisample_quality %u.\n",
880             device, Width, Height, Format, Lockable, Discard, Level, ppSurface, Usage, Pool,
881             MultiSample, MultisampleQuality);
882
883     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface9Impl));
884     if (!object)
885     {
886         FIXME("Failed to allocate surface memory.\n");
887         return D3DERR_OUTOFVIDEOMEMORY;
888     }
889
890     hr = surface_init(object, device, Width, Height, Format, Lockable, Discard, Level, Usage, Pool,
891             MultiSample, MultisampleQuality);
892     if (FAILED(hr))
893     {
894         WARN("Failed to initialize surface, hr %#x.\n", hr);
895         HeapFree(GetProcessHeap(), 0, object);
896         return hr;
897     }
898
899     TRACE("Created surface %p.\n", object);
900     *ppSurface = &object->IDirect3DSurface9_iface;
901
902     return D3D_OK;
903 }
904
905 static HRESULT WINAPI IDirect3DDevice9Impl_CreateRenderTarget(IDirect3DDevice9Ex *iface, UINT Width,
906         UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality,
907         BOOL Lockable, IDirect3DSurface9 **ppSurface, HANDLE *pSharedHandle)
908 {
909     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
910     HRESULT hr;
911
912     TRACE("iface %p, width %u, height %u, format %#x, multisample_type %#x, multisample_quality %u.\n"
913             "lockable %#x, surface %p, shared_handle %p.\n",
914             iface, Width, Height, Format, MultiSample, MultisampleQuality,
915             Lockable, ppSurface, pSharedHandle);
916
917     hr = IDirect3DDevice9Impl_CreateSurface(This, Width, Height, Format, Lockable,
918             FALSE /* Discard */, 0 /* Level */, ppSurface, D3DUSAGE_RENDERTARGET, D3DPOOL_DEFAULT,
919             MultiSample, MultisampleQuality);
920
921     return hr;
922 }
923
924 static HRESULT WINAPI IDirect3DDevice9Impl_CreateDepthStencilSurface(IDirect3DDevice9Ex *iface,
925         UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample,
926         DWORD MultisampleQuality, BOOL Discard, IDirect3DSurface9 **ppSurface,
927         HANDLE *pSharedHandle)
928 {
929     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
930     HRESULT hr;
931
932     TRACE("iface %p, width %u, height %u, format %#x, multisample_type %#x, multisample_quality %u.\n"
933             "discard %#x, surface %p, shared_handle %p.\n",
934             iface, Width, Height, Format, MultiSample, MultisampleQuality,
935             Discard, ppSurface, pSharedHandle);
936
937     hr = IDirect3DDevice9Impl_CreateSurface(This, Width, Height, Format, TRUE /* Lockable */,
938             Discard, 0 /* Level */, ppSurface, D3DUSAGE_DEPTHSTENCIL, D3DPOOL_DEFAULT, MultiSample,
939             MultisampleQuality);
940
941     return hr;
942 }
943
944
945 static HRESULT WINAPI IDirect3DDevice9Impl_UpdateSurface(IDirect3DDevice9Ex *iface,
946         IDirect3DSurface9 *pSourceSurface, const RECT *pSourceRect,
947         IDirect3DSurface9 *pDestinationSurface, const POINT *pDestPoint)
948 {
949     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
950     IDirect3DSurface9Impl *src = unsafe_impl_from_IDirect3DSurface9(pSourceSurface);
951     IDirect3DSurface9Impl *dst = unsafe_impl_from_IDirect3DSurface9(pDestinationSurface);
952     HRESULT hr;
953
954     TRACE("iface %p, src_surface %p, src_rect %p, dst_surface %p, dst_point %p.\n",
955             iface, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
956
957     wined3d_mutex_lock();
958     hr = wined3d_device_update_surface(This->wined3d_device, src->wined3d_surface, pSourceRect,
959             dst->wined3d_surface, pDestPoint);
960     wined3d_mutex_unlock();
961
962     return hr;
963 }
964
965 static HRESULT WINAPI IDirect3DDevice9Impl_UpdateTexture(IDirect3DDevice9Ex *iface,
966         IDirect3DBaseTexture9 *src_texture, IDirect3DBaseTexture9 *dst_texture)
967 {
968     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
969     HRESULT hr;
970
971     TRACE("iface %p, src_texture %p, dst_texture %p.\n", iface, src_texture, dst_texture);
972
973     wined3d_mutex_lock();
974     hr = wined3d_device_update_texture(This->wined3d_device,
975             ((IDirect3DBaseTexture9Impl *)src_texture)->wined3d_texture,
976             ((IDirect3DBaseTexture9Impl *)dst_texture)->wined3d_texture);
977     wined3d_mutex_unlock();
978
979     return hr;
980 }
981
982 static HRESULT WINAPI IDirect3DDevice9Impl_GetRenderTargetData(IDirect3DDevice9Ex *iface,
983         IDirect3DSurface9 *pRenderTarget, IDirect3DSurface9 *pDestSurface)
984 {
985     IDirect3DSurface9Impl *renderTarget = unsafe_impl_from_IDirect3DSurface9(pRenderTarget);
986     IDirect3DSurface9Impl *destSurface = unsafe_impl_from_IDirect3DSurface9(pDestSurface);
987     HRESULT hr;
988
989     TRACE("iface %p, render_target %p, dst_surface %p.\n", iface, pRenderTarget, pDestSurface);
990
991     wined3d_mutex_lock();
992     hr = wined3d_surface_bltfast(destSurface->wined3d_surface, 0, 0,
993             renderTarget->wined3d_surface, NULL, WINEDDBLTFAST_NOCOLORKEY);
994     wined3d_mutex_unlock();
995
996     return hr;
997 }
998
999 static HRESULT WINAPI IDirect3DDevice9Impl_GetFrontBufferData(IDirect3DDevice9Ex *iface,
1000         UINT iSwapChain, IDirect3DSurface9 *pDestSurface)
1001 {
1002     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1003     IDirect3DSurface9Impl *destSurface = unsafe_impl_from_IDirect3DSurface9(pDestSurface);
1004     HRESULT hr;
1005
1006     TRACE("iface %p, swapchain %u, dst_surface %p.\n", iface, iSwapChain, pDestSurface);
1007
1008     wined3d_mutex_lock();
1009     hr = wined3d_device_get_front_buffer_data(This->wined3d_device, iSwapChain, destSurface->wined3d_surface);
1010     wined3d_mutex_unlock();
1011
1012     return hr;
1013 }
1014
1015 static HRESULT WINAPI IDirect3DDevice9Impl_StretchRect(IDirect3DDevice9Ex *iface, IDirect3DSurface9 *pSourceSurface,
1016         const RECT *pSourceRect, IDirect3DSurface9 *pDestSurface, const RECT *pDestRect, D3DTEXTUREFILTERTYPE Filter)
1017 {
1018     IDirect3DSurface9Impl *src = unsafe_impl_from_IDirect3DSurface9(pSourceSurface);
1019     IDirect3DSurface9Impl *dst = unsafe_impl_from_IDirect3DSurface9(pDestSurface);
1020     HRESULT hr;
1021
1022     TRACE("iface %p, src_surface %p, src_rect %p, dst_surface %p, dst_rect %p, filter %#x.\n",
1023             iface, pSourceSurface, pSourceRect, pDestSurface, pDestRect, Filter);
1024
1025     wined3d_mutex_lock();
1026     hr = wined3d_surface_blt(dst->wined3d_surface, pDestRect, src->wined3d_surface, pSourceRect, 0, NULL, Filter);
1027     wined3d_mutex_unlock();
1028
1029     return hr;
1030 }
1031
1032 static HRESULT WINAPI IDirect3DDevice9Impl_ColorFill(IDirect3DDevice9Ex *iface,
1033         IDirect3DSurface9 *pSurface, const RECT *pRect, D3DCOLOR color)
1034 {
1035     const WINED3DCOLORVALUE c =
1036     {
1037         ((color >> 16) & 0xff) / 255.0f,
1038         ((color >>  8) & 0xff) / 255.0f,
1039         (color & 0xff) / 255.0f,
1040         ((color >> 24) & 0xff) / 255.0f,
1041     };
1042     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1043     IDirect3DSurface9Impl *surface = unsafe_impl_from_IDirect3DSurface9(pSurface);
1044     struct wined3d_resource *wined3d_resource;
1045     struct wined3d_resource_desc desc;
1046     HRESULT hr;
1047
1048     TRACE("iface %p, surface %p, rect %p, color 0x%08x.\n", iface, pSurface, pRect, color);
1049
1050     wined3d_mutex_lock();
1051
1052     wined3d_resource = wined3d_surface_get_resource(surface->wined3d_surface);
1053     wined3d_resource_get_desc(wined3d_resource, &desc);
1054
1055     /* This method is only allowed with surfaces that are render targets, or
1056      * offscreen plain surfaces in D3DPOOL_DEFAULT. */
1057     if (!(desc.usage & WINED3DUSAGE_RENDERTARGET) && desc.pool != WINED3DPOOL_DEFAULT)
1058     {
1059         wined3d_mutex_unlock();
1060         WARN("Surface is not a render target, or not a stand-alone D3DPOOL_DEFAULT surface\n");
1061         return D3DERR_INVALIDCALL;
1062     }
1063
1064     /* Colorfill can only be used on rendertarget surfaces, or offscreen plain surfaces in D3DPOOL_DEFAULT */
1065     hr = wined3d_device_color_fill(This->wined3d_device, surface->wined3d_surface, pRect, &c);
1066
1067     wined3d_mutex_unlock();
1068
1069     return hr;
1070 }
1071
1072 static HRESULT  WINAPI  IDirect3DDevice9Impl_CreateOffscreenPlainSurface(IDirect3DDevice9Ex *iface,
1073         UINT Width, UINT Height, D3DFORMAT Format, D3DPOOL Pool, IDirect3DSurface9 **ppSurface,
1074         HANDLE *pSharedHandle)
1075 {
1076     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1077     HRESULT hr;
1078
1079     TRACE("iface %p, width %u, height %u, format %#x, pool %#x, surface %p, shared_handle %p.\n",
1080             iface, Width, Height, Format, Pool, ppSurface, pSharedHandle);
1081
1082     if(Pool == D3DPOOL_MANAGED ){
1083         FIXME("Attempting to create a managed offscreen plain surface\n");
1084         return D3DERR_INVALIDCALL;
1085     }
1086         /*
1087         'Off-screen plain surfaces are always lockable, regardless of their pool types.'
1088         but then...
1089         D3DPOOL_DEFAULT is the appropriate pool for use with the IDirect3DDevice9::StretchRect and IDirect3DDevice9::ColorFill.
1090         Why, their always lockable?
1091         should I change the usage to dynamic?
1092         */
1093     hr = IDirect3DDevice9Impl_CreateSurface(This, Width, Height, Format, TRUE /* Lockable */,
1094             FALSE /* Discard */, 0 /* Level */, ppSurface, 0 /* Usage (undefined/none) */,
1095             Pool, D3DMULTISAMPLE_NONE, 0 /* MultisampleQuality */);
1096
1097     return hr;
1098 }
1099
1100 /* TODO: move to wineD3D */
1101 static HRESULT WINAPI IDirect3DDevice9Impl_SetRenderTarget(IDirect3DDevice9Ex *iface,
1102         DWORD RenderTargetIndex, IDirect3DSurface9 *pRenderTarget)
1103 {
1104     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1105     IDirect3DSurface9Impl *pSurface = unsafe_impl_from_IDirect3DSurface9(pRenderTarget);
1106     HRESULT hr;
1107
1108     TRACE("iface %p, idx %u, surface %p.\n", iface, RenderTargetIndex, pRenderTarget);
1109
1110     if (RenderTargetIndex >= D3D9_MAX_SIMULTANEOUS_RENDERTARGETS)
1111     {
1112         WARN("Invalid index %u specified.\n", RenderTargetIndex);
1113         return D3DERR_INVALIDCALL;
1114     }
1115
1116     wined3d_mutex_lock();
1117     hr = wined3d_device_set_render_target(This->wined3d_device, RenderTargetIndex,
1118             pSurface ? pSurface->wined3d_surface : NULL, TRUE);
1119     wined3d_mutex_unlock();
1120
1121     return hr;
1122 }
1123
1124 static HRESULT WINAPI IDirect3DDevice9Impl_GetRenderTarget(IDirect3DDevice9Ex *iface,
1125         DWORD RenderTargetIndex, IDirect3DSurface9 **ppRenderTarget)
1126 {
1127     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1128     struct wined3d_surface *wined3d_surface;
1129     HRESULT hr;
1130
1131     TRACE("iface %p, idx %u, surface %p.\n", iface, RenderTargetIndex, ppRenderTarget);
1132
1133     if (ppRenderTarget == NULL) {
1134         return D3DERR_INVALIDCALL;
1135     }
1136
1137     if (RenderTargetIndex >= D3D9_MAX_SIMULTANEOUS_RENDERTARGETS)
1138     {
1139         WARN("Invalid index %u specified.\n", RenderTargetIndex);
1140         return D3DERR_INVALIDCALL;
1141     }
1142
1143     wined3d_mutex_lock();
1144
1145     hr = wined3d_device_get_render_target(This->wined3d_device, RenderTargetIndex, &wined3d_surface);
1146
1147     if (FAILED(hr))
1148     {
1149         FIXME("Call to IWineD3DDevice_GetRenderTarget failed, hr %#x\n", hr);
1150     }
1151     else if (!wined3d_surface)
1152     {
1153         *ppRenderTarget = NULL;
1154     }
1155     else
1156     {
1157         *ppRenderTarget = wined3d_surface_get_parent(wined3d_surface);
1158         IDirect3DSurface9_AddRef(*ppRenderTarget);
1159         wined3d_surface_decref(wined3d_surface);
1160     }
1161
1162     wined3d_mutex_unlock();
1163
1164     return hr;
1165 }
1166
1167 static HRESULT WINAPI IDirect3DDevice9Impl_SetDepthStencilSurface(IDirect3DDevice9Ex *iface,
1168         IDirect3DSurface9 *pZStencilSurface)
1169 {
1170     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1171     IDirect3DSurface9Impl *pSurface = unsafe_impl_from_IDirect3DSurface9(pZStencilSurface);
1172     HRESULT hr;
1173
1174     TRACE("iface %p, depth_stencil %p.\n", iface, pZStencilSurface);
1175
1176     wined3d_mutex_lock();
1177     hr = wined3d_device_set_depth_stencil(This->wined3d_device, pSurface ? pSurface->wined3d_surface : NULL);
1178     wined3d_mutex_unlock();
1179
1180     return hr;
1181 }
1182
1183 static HRESULT WINAPI IDirect3DDevice9Impl_GetDepthStencilSurface(IDirect3DDevice9Ex *iface,
1184         IDirect3DSurface9 **ppZStencilSurface)
1185 {
1186     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1187     struct wined3d_surface *wined3d_surface;
1188     HRESULT hr;
1189
1190     TRACE("iface %p, depth_stencil %p.\n", iface, ppZStencilSurface);
1191
1192     if(ppZStencilSurface == NULL){
1193         return D3DERR_INVALIDCALL;
1194     }
1195
1196     wined3d_mutex_lock();
1197     hr = wined3d_device_get_depth_stencil(This->wined3d_device, &wined3d_surface);
1198     if (SUCCEEDED(hr))
1199     {
1200         *ppZStencilSurface = wined3d_surface_get_parent(wined3d_surface);
1201         IDirect3DSurface9_AddRef(*ppZStencilSurface);
1202         wined3d_surface_decref(wined3d_surface);
1203     }
1204     else
1205     {
1206         if (hr != WINED3DERR_NOTFOUND)
1207                 WARN("Call to IWineD3DDevice_GetDepthStencilSurface failed with 0x%08x\n", hr);
1208         *ppZStencilSurface = NULL;
1209     }
1210     wined3d_mutex_unlock();
1211
1212     return hr;
1213 }
1214
1215 static HRESULT WINAPI IDirect3DDevice9Impl_BeginScene(IDirect3DDevice9Ex *iface)
1216 {
1217     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1218     HRESULT hr;
1219
1220     TRACE("iface %p.\n", iface);
1221
1222     wined3d_mutex_lock();
1223     hr = wined3d_device_begin_scene(This->wined3d_device);
1224     wined3d_mutex_unlock();
1225
1226     return hr;
1227 }
1228
1229 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDevice9Impl_EndScene(IDirect3DDevice9Ex *iface)
1230 {
1231     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1232     HRESULT hr;
1233
1234     TRACE("iface %p.\n", iface);
1235
1236     wined3d_mutex_lock();
1237     hr = wined3d_device_end_scene(This->wined3d_device);
1238     wined3d_mutex_unlock();
1239
1240     return hr;
1241 }
1242
1243 static HRESULT WINAPI IDirect3DDevice9Impl_Clear(IDirect3DDevice9Ex *iface, DWORD Count,
1244         const D3DRECT *pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil)
1245 {
1246     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1247     HRESULT hr;
1248
1249     TRACE("iface %p, rect_count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %u.\n",
1250             iface, Count, pRects, Flags, Color, Z, Stencil);
1251
1252     /* Note: D3DRECT is compatible with WINED3DRECT */
1253     wined3d_mutex_lock();
1254     hr = wined3d_device_clear(This->wined3d_device, Count, (const RECT *)pRects, Flags, Color, Z, Stencil);
1255     wined3d_mutex_unlock();
1256
1257     return hr;
1258 }
1259
1260 static HRESULT WINAPI IDirect3DDevice9Impl_SetTransform(IDirect3DDevice9Ex *iface,
1261         D3DTRANSFORMSTATETYPE State, const D3DMATRIX *lpMatrix)
1262 {
1263     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1264     HRESULT hr;
1265
1266     TRACE("iface %p, state %#x, matrix %p.\n", iface, State, lpMatrix);
1267
1268     /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
1269     wined3d_mutex_lock();
1270     hr = wined3d_device_set_transform(This->wined3d_device, State, (const WINED3DMATRIX *)lpMatrix);
1271     wined3d_mutex_unlock();
1272
1273     return hr;
1274 }
1275
1276 static HRESULT WINAPI IDirect3DDevice9Impl_GetTransform(IDirect3DDevice9Ex *iface,
1277         D3DTRANSFORMSTATETYPE State, D3DMATRIX *pMatrix)
1278 {
1279     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1280     HRESULT hr;
1281
1282     TRACE("iface %p, state %#x, matrix %p.\n", iface, State, pMatrix);
1283
1284     /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
1285     wined3d_mutex_lock();
1286     hr = wined3d_device_get_transform(This->wined3d_device, State, (WINED3DMATRIX *)pMatrix);
1287     wined3d_mutex_unlock();
1288
1289     return hr;
1290 }
1291
1292 static HRESULT WINAPI IDirect3DDevice9Impl_MultiplyTransform(IDirect3DDevice9Ex *iface,
1293         D3DTRANSFORMSTATETYPE State, const D3DMATRIX *pMatrix)
1294 {
1295     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1296     HRESULT hr;
1297
1298     TRACE("iface %p, state %#x, matrix %p.\n", iface, State, pMatrix);
1299
1300     /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
1301     wined3d_mutex_lock();
1302     hr = wined3d_device_multiply_transform(This->wined3d_device, State, (const WINED3DMATRIX *)pMatrix);
1303     wined3d_mutex_unlock();
1304
1305     return hr;
1306 }
1307
1308 static HRESULT WINAPI IDirect3DDevice9Impl_SetViewport(IDirect3DDevice9Ex *iface,
1309         const D3DVIEWPORT9 *pViewport)
1310 {
1311     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1312     HRESULT hr;
1313
1314     TRACE("iface %p, viewport %p.\n", iface, pViewport);
1315
1316     /* Note: D3DVIEWPORT9 is compatible with WINED3DVIEWPORT */
1317     wined3d_mutex_lock();
1318     hr = wined3d_device_set_viewport(This->wined3d_device, (const WINED3DVIEWPORT *)pViewport);
1319     wined3d_mutex_unlock();
1320
1321     return hr;
1322 }
1323
1324 static HRESULT WINAPI IDirect3DDevice9Impl_GetViewport(IDirect3DDevice9Ex *iface,
1325         D3DVIEWPORT9 *pViewport)
1326 {
1327     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1328     HRESULT hr;
1329
1330     TRACE("iface %p, viewport %p.\n", iface, pViewport);
1331
1332     /* Note: D3DVIEWPORT9 is compatible with WINED3DVIEWPORT */
1333     wined3d_mutex_lock();
1334     hr = wined3d_device_get_viewport(This->wined3d_device, (WINED3DVIEWPORT *)pViewport);
1335     wined3d_mutex_unlock();
1336
1337     return hr;
1338 }
1339
1340 static HRESULT WINAPI IDirect3DDevice9Impl_SetMaterial(IDirect3DDevice9Ex *iface,
1341         const D3DMATERIAL9 *pMaterial)
1342 {
1343     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1344     HRESULT hr;
1345
1346     TRACE("iface %p, material %p.\n", iface, pMaterial);
1347
1348     /* Note: D3DMATERIAL9 is compatible with WINED3DMATERIAL */
1349     wined3d_mutex_lock();
1350     hr = wined3d_device_set_material(This->wined3d_device, (const WINED3DMATERIAL *)pMaterial);
1351     wined3d_mutex_unlock();
1352
1353     return hr;
1354 }
1355
1356 static HRESULT WINAPI IDirect3DDevice9Impl_GetMaterial(IDirect3DDevice9Ex *iface,
1357         D3DMATERIAL9 *pMaterial)
1358 {
1359     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1360     HRESULT hr;
1361
1362     TRACE("iface %p, material %p.\n", iface, pMaterial);
1363
1364     /* Note: D3DMATERIAL9 is compatible with WINED3DMATERIAL */
1365     wined3d_mutex_lock();
1366     hr = wined3d_device_get_material(This->wined3d_device, (WINED3DMATERIAL *)pMaterial);
1367     wined3d_mutex_unlock();
1368
1369     return hr;
1370 }
1371
1372 static HRESULT WINAPI IDirect3DDevice9Impl_SetLight(IDirect3DDevice9Ex *iface, DWORD Index,
1373         const D3DLIGHT9 *pLight)
1374 {
1375     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1376     HRESULT hr;
1377
1378     TRACE("iface %p, index %u, light %p.\n", iface, Index, pLight);
1379
1380     /* Note: D3DLIGHT9 is compatible with WINED3DLIGHT */
1381     wined3d_mutex_lock();
1382     hr = wined3d_device_set_light(This->wined3d_device, Index, (const WINED3DLIGHT *)pLight);
1383     wined3d_mutex_unlock();
1384
1385     return hr;
1386 }
1387
1388 static HRESULT WINAPI IDirect3DDevice9Impl_GetLight(IDirect3DDevice9Ex *iface, DWORD Index,
1389         D3DLIGHT9 *pLight)
1390 {
1391     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1392     HRESULT hr;
1393
1394     TRACE("iface %p, index %u, light %p.\n", iface, Index, pLight);
1395
1396     /* Note: D3DLIGHT9 is compatible with WINED3DLIGHT */
1397     wined3d_mutex_lock();
1398     hr = wined3d_device_get_light(This->wined3d_device, Index, (WINED3DLIGHT *)pLight);
1399     wined3d_mutex_unlock();
1400
1401     return hr;
1402 }
1403
1404 static HRESULT WINAPI IDirect3DDevice9Impl_LightEnable(IDirect3DDevice9Ex *iface, DWORD Index,
1405         BOOL Enable)
1406 {
1407     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1408     HRESULT hr;
1409
1410     TRACE("iface %p, index %u, enable %#x.\n", iface, Index, Enable);
1411
1412     wined3d_mutex_lock();
1413     hr = wined3d_device_set_light_enable(This->wined3d_device, Index, Enable);
1414     wined3d_mutex_unlock();
1415
1416     return hr;
1417 }
1418
1419 static HRESULT WINAPI IDirect3DDevice9Impl_GetLightEnable(IDirect3DDevice9Ex *iface, DWORD Index,
1420         BOOL *pEnable)
1421 {
1422     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1423     HRESULT hr;
1424
1425     TRACE("iface %p, index %u, enable %p.\n", iface, Index, pEnable);
1426
1427     wined3d_mutex_lock();
1428     hr = wined3d_device_get_light_enable(This->wined3d_device, Index, pEnable);
1429     wined3d_mutex_unlock();
1430
1431     return hr;
1432 }
1433
1434 static HRESULT WINAPI IDirect3DDevice9Impl_SetClipPlane(IDirect3DDevice9Ex *iface, DWORD Index,
1435         const float *pPlane)
1436 {
1437     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1438     HRESULT hr;
1439
1440     TRACE("iface %p, index %u, plane %p.\n", iface, Index, pPlane);
1441
1442     wined3d_mutex_lock();
1443     hr = wined3d_device_set_clip_plane(This->wined3d_device, Index, pPlane);
1444     wined3d_mutex_unlock();
1445
1446     return hr;
1447 }
1448
1449 static HRESULT WINAPI IDirect3DDevice9Impl_GetClipPlane(IDirect3DDevice9Ex *iface, DWORD Index,
1450         float *pPlane)
1451 {
1452     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1453     HRESULT hr;
1454
1455     TRACE("iface %p, index %u, plane %p.\n", iface, Index, pPlane);
1456
1457     wined3d_mutex_lock();
1458     hr = wined3d_device_get_clip_plane(This->wined3d_device, Index, pPlane);
1459     wined3d_mutex_unlock();
1460
1461     return hr;
1462 }
1463
1464 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDevice9Impl_SetRenderState(IDirect3DDevice9Ex *iface,
1465         D3DRENDERSTATETYPE State, DWORD Value)
1466 {
1467     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1468     HRESULT hr;
1469
1470     TRACE("iface %p, state %#x, value %#x.\n", iface, State, Value);
1471
1472     wined3d_mutex_lock();
1473     hr = wined3d_device_set_render_state(This->wined3d_device, State, Value);
1474     wined3d_mutex_unlock();
1475
1476     return hr;
1477 }
1478
1479 static HRESULT WINAPI IDirect3DDevice9Impl_GetRenderState(IDirect3DDevice9Ex *iface,
1480         D3DRENDERSTATETYPE State, DWORD *pValue)
1481 {
1482     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1483     HRESULT hr;
1484
1485     TRACE("iface %p, state %#x, value %p.\n", iface, State, pValue);
1486
1487     wined3d_mutex_lock();
1488     hr = wined3d_device_get_render_state(This->wined3d_device, State, pValue);
1489     wined3d_mutex_unlock();
1490
1491     return hr;
1492 }
1493
1494 static HRESULT WINAPI IDirect3DDevice9Impl_CreateStateBlock(IDirect3DDevice9Ex *iface,
1495         D3DSTATEBLOCKTYPE type, IDirect3DStateBlock9 **stateblock)
1496 {
1497     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1498     IDirect3DStateBlock9Impl *object;
1499     HRESULT hr;
1500
1501     TRACE("iface %p, type %#x, stateblock %p.\n", iface, type, stateblock);
1502
1503     if (type != D3DSBT_ALL && type != D3DSBT_PIXELSTATE && type != D3DSBT_VERTEXSTATE)
1504     {
1505         WARN("Unexpected stateblock type, returning D3DERR_INVALIDCALL.\n");
1506         return D3DERR_INVALIDCALL;
1507     }
1508
1509     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1510     if (!object)
1511     {
1512         ERR("Failed to allocate stateblock memory.\n");
1513         return E_OUTOFMEMORY;
1514     }
1515
1516     hr = stateblock_init(object, This, type, NULL);
1517     if (FAILED(hr))
1518     {
1519         WARN("Failed to initialize stateblock, hr %#x.\n", hr);
1520         HeapFree(GetProcessHeap(), 0, object);
1521         return hr;
1522     }
1523
1524     TRACE("Created stateblock %p.\n", object);
1525     *stateblock = &object->IDirect3DStateBlock9_iface;
1526
1527     return D3D_OK;
1528 }
1529
1530 static HRESULT WINAPI IDirect3DDevice9Impl_BeginStateBlock(IDirect3DDevice9Ex *iface)
1531 {
1532     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1533     HRESULT hr;
1534
1535     TRACE("iface %p.\n", iface);
1536
1537     wined3d_mutex_lock();
1538     hr = wined3d_device_begin_stateblock(This->wined3d_device);
1539     wined3d_mutex_unlock();
1540
1541     return hr;
1542 }
1543
1544 static HRESULT WINAPI IDirect3DDevice9Impl_EndStateBlock(IDirect3DDevice9Ex *iface,
1545         IDirect3DStateBlock9 **stateblock)
1546 {
1547     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1548     struct wined3d_stateblock *wined3d_stateblock;
1549     IDirect3DStateBlock9Impl *object;
1550     HRESULT hr;
1551
1552     TRACE("iface %p, stateblock %p.\n", iface, stateblock);
1553
1554     wined3d_mutex_lock();
1555     hr = wined3d_device_end_stateblock(This->wined3d_device, &wined3d_stateblock);
1556     wined3d_mutex_unlock();
1557     if (FAILED(hr))
1558     {
1559        WARN("IWineD3DDevice_EndStateBlock() failed, hr %#x.\n", hr);
1560        return hr;
1561     }
1562
1563     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1564     if (!object)
1565     {
1566         ERR("Failed to allocate stateblock memory.\n");
1567         wined3d_mutex_lock();
1568         wined3d_stateblock_decref(wined3d_stateblock);
1569         wined3d_mutex_unlock();
1570         return E_OUTOFMEMORY;
1571     }
1572
1573     hr = stateblock_init(object, This, 0, wined3d_stateblock);
1574     if (FAILED(hr))
1575     {
1576         WARN("Failed to initialize stateblock, hr %#x.\n", hr);
1577         wined3d_mutex_lock();
1578         wined3d_stateblock_decref(wined3d_stateblock);
1579         wined3d_mutex_unlock();
1580         HeapFree(GetProcessHeap(), 0, object);
1581         return hr;
1582     }
1583
1584     TRACE("Created stateblock %p.\n", object);
1585     *stateblock = &object->IDirect3DStateBlock9_iface;
1586
1587     return D3D_OK;
1588 }
1589
1590 static HRESULT WINAPI IDirect3DDevice9Impl_SetClipStatus(IDirect3DDevice9Ex *iface,
1591         const D3DCLIPSTATUS9 *pClipStatus)
1592 {
1593     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1594     HRESULT hr;
1595
1596     TRACE("iface %p, clip_status %p.\n", iface, pClipStatus);
1597
1598     wined3d_mutex_lock();
1599     hr = wined3d_device_set_clip_status(This->wined3d_device, (const WINED3DCLIPSTATUS *)pClipStatus);
1600     wined3d_mutex_unlock();
1601
1602     return hr;
1603 }
1604
1605 static HRESULT WINAPI IDirect3DDevice9Impl_GetClipStatus(IDirect3DDevice9Ex *iface,
1606         D3DCLIPSTATUS9 *pClipStatus)
1607 {
1608     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1609     HRESULT hr;
1610
1611     TRACE("iface %p, clip_status %p.\n", iface, pClipStatus);
1612
1613     wined3d_mutex_lock();
1614     hr = wined3d_device_get_clip_status(This->wined3d_device, (WINED3DCLIPSTATUS *)pClipStatus);
1615     wined3d_mutex_unlock();
1616
1617     return hr;
1618 }
1619
1620 static HRESULT WINAPI IDirect3DDevice9Impl_GetTexture(IDirect3DDevice9Ex *iface, DWORD Stage,
1621         IDirect3DBaseTexture9 **ppTexture)
1622 {
1623     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1624     struct wined3d_texture *wined3d_texture = NULL;
1625     HRESULT hr;
1626
1627     TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, ppTexture);
1628
1629     if(ppTexture == NULL){
1630         return D3DERR_INVALIDCALL;
1631     }
1632
1633     wined3d_mutex_lock();
1634     hr = wined3d_device_get_texture(This->wined3d_device, Stage, &wined3d_texture);
1635     if (SUCCEEDED(hr) && wined3d_texture)
1636     {
1637         *ppTexture = wined3d_texture_get_parent(wined3d_texture);
1638         IDirect3DBaseTexture9_AddRef(*ppTexture);
1639         wined3d_texture_decref(wined3d_texture);
1640     }
1641     else
1642     {
1643         if (FAILED(hr))
1644         {
1645             WARN("Call to get texture (%u) failed (%p).\n", Stage, wined3d_texture);
1646         }
1647         *ppTexture = NULL;
1648     }
1649     wined3d_mutex_unlock();
1650
1651     return hr;
1652 }
1653
1654 static HRESULT WINAPI IDirect3DDevice9Impl_SetTexture(IDirect3DDevice9Ex *iface, DWORD stage,
1655         IDirect3DBaseTexture9 *texture)
1656 {
1657     IDirect3DDevice9Impl *device = impl_from_IDirect3DDevice9Ex(iface);
1658     HRESULT hr;
1659
1660     TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
1661
1662     wined3d_mutex_lock();
1663     hr = wined3d_device_set_texture(device->wined3d_device, stage,
1664             texture ? ((IDirect3DBaseTexture9Impl *)texture)->wined3d_texture : NULL);
1665     wined3d_mutex_unlock();
1666
1667     return hr;
1668 }
1669
1670 static const WINED3DTEXTURESTAGESTATETYPE tss_lookup[] =
1671 {
1672     WINED3DTSS_FORCE_DWORD,             /*  0, unused */
1673     WINED3DTSS_COLOROP,                 /*  1, D3DTSS_COLOROP */
1674     WINED3DTSS_COLORARG1,               /*  2, D3DTSS_COLORARG1 */
1675     WINED3DTSS_COLORARG2,               /*  3, D3DTSS_COLORARG2 */
1676     WINED3DTSS_ALPHAOP,                 /*  4, D3DTSS_ALPHAOP */
1677     WINED3DTSS_ALPHAARG1,               /*  5, D3DTSS_ALPHAARG1 */
1678     WINED3DTSS_ALPHAARG2,               /*  6, D3DTSS_ALPHAARG2 */
1679     WINED3DTSS_BUMPENVMAT00,            /*  7, D3DTSS_BUMPENVMAT00 */
1680     WINED3DTSS_BUMPENVMAT01,            /*  8, D3DTSS_BUMPENVMAT01 */
1681     WINED3DTSS_BUMPENVMAT10,            /*  9, D3DTSS_BUMPENVMAT10 */
1682     WINED3DTSS_BUMPENVMAT11,            /* 10, D3DTSS_BUMPENVMAT11 */
1683     WINED3DTSS_TEXCOORDINDEX,           /* 11, D3DTSS_TEXCOORDINDEX */
1684     WINED3DTSS_FORCE_DWORD,             /* 12, unused */
1685     WINED3DTSS_FORCE_DWORD,             /* 13, unused */
1686     WINED3DTSS_FORCE_DWORD,             /* 14, unused */
1687     WINED3DTSS_FORCE_DWORD,             /* 15, unused */
1688     WINED3DTSS_FORCE_DWORD,             /* 16, unused */
1689     WINED3DTSS_FORCE_DWORD,             /* 17, unused */
1690     WINED3DTSS_FORCE_DWORD,             /* 18, unused */
1691     WINED3DTSS_FORCE_DWORD,             /* 19, unused */
1692     WINED3DTSS_FORCE_DWORD,             /* 20, unused */
1693     WINED3DTSS_FORCE_DWORD,             /* 21, unused */
1694     WINED3DTSS_BUMPENVLSCALE,           /* 22, D3DTSS_BUMPENVLSCALE */
1695     WINED3DTSS_BUMPENVLOFFSET,          /* 23, D3DTSS_BUMPENVLOFFSET */
1696     WINED3DTSS_TEXTURETRANSFORMFLAGS,   /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
1697     WINED3DTSS_FORCE_DWORD,             /* 25, unused */
1698     WINED3DTSS_COLORARG0,               /* 26, D3DTSS_COLORARG0 */
1699     WINED3DTSS_ALPHAARG0,               /* 27, D3DTSS_ALPHAARG0 */
1700     WINED3DTSS_RESULTARG,               /* 28, D3DTSS_RESULTARG */
1701     WINED3DTSS_FORCE_DWORD,             /* 29, unused */
1702     WINED3DTSS_FORCE_DWORD,             /* 30, unused */
1703     WINED3DTSS_FORCE_DWORD,             /* 31, unused */
1704     WINED3DTSS_CONSTANT,                /* 32, D3DTSS_CONSTANT */
1705 };
1706
1707 static HRESULT WINAPI IDirect3DDevice9Impl_GetTextureStageState(IDirect3DDevice9Ex *iface,
1708         DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD *pValue)
1709 {
1710     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1711     HRESULT hr;
1712
1713     TRACE("iface %p, stage %u, state %#x, value %p.\n", iface, Stage, Type, pValue);
1714
1715     if (Type >= sizeof(tss_lookup) / sizeof(*tss_lookup))
1716     {
1717         WARN("Invalid Type %#x passed.\n", Type);
1718         return D3D_OK;
1719     }
1720
1721     wined3d_mutex_lock();
1722     hr = wined3d_device_get_texture_stage_state(This->wined3d_device, Stage, tss_lookup[Type], pValue);
1723     wined3d_mutex_unlock();
1724
1725     return hr;
1726 }
1727
1728 static HRESULT WINAPI IDirect3DDevice9Impl_SetTextureStageState(IDirect3DDevice9Ex *iface,
1729         DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value)
1730 {
1731     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1732     HRESULT hr;
1733
1734     TRACE("iface %p, stage %u, state %#x, value %#x.\n", iface, Stage, Type, Value);
1735
1736     if (Type >= sizeof(tss_lookup) / sizeof(*tss_lookup))
1737     {
1738         WARN("Invalid Type %#x passed.\n", Type);
1739         return D3D_OK;
1740     }
1741
1742     wined3d_mutex_lock();
1743     hr = wined3d_device_set_texture_stage_state(This->wined3d_device, Stage, tss_lookup[Type], Value);
1744     wined3d_mutex_unlock();
1745
1746     return hr;
1747 }
1748
1749 static HRESULT WINAPI IDirect3DDevice9Impl_GetSamplerState(IDirect3DDevice9Ex *iface, DWORD Sampler,
1750         D3DSAMPLERSTATETYPE Type, DWORD *pValue)
1751 {
1752     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1753     HRESULT hr;
1754
1755     TRACE("iface %p, sampler %u, state %#x, value %p.\n", iface, Sampler, Type, pValue);
1756
1757     wined3d_mutex_lock();
1758     hr = wined3d_device_get_sampler_state(This->wined3d_device, Sampler, Type, pValue);
1759     wined3d_mutex_unlock();
1760
1761     return hr;
1762 }
1763
1764 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDevice9Impl_SetSamplerState(IDirect3DDevice9Ex *iface,
1765         DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value)
1766 {
1767     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1768     HRESULT hr;
1769
1770     TRACE("iface %p, sampler %u, state %#x, value %#x.\n", iface, Sampler, Type, Value);
1771
1772     wined3d_mutex_lock();
1773     hr = wined3d_device_set_sampler_state(This->wined3d_device, Sampler, Type, Value);
1774     wined3d_mutex_unlock();
1775
1776     return hr;
1777 }
1778
1779 static HRESULT WINAPI IDirect3DDevice9Impl_ValidateDevice(IDirect3DDevice9Ex *iface,
1780         DWORD *pNumPasses)
1781 {
1782     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1783     HRESULT hr;
1784
1785     TRACE("iface %p, pass_count %p.\n", iface, pNumPasses);
1786
1787     wined3d_mutex_lock();
1788     hr = wined3d_device_validate_device(This->wined3d_device, pNumPasses);
1789     wined3d_mutex_unlock();
1790
1791     return hr;
1792 }
1793
1794 static HRESULT WINAPI IDirect3DDevice9Impl_SetPaletteEntries(IDirect3DDevice9Ex *iface,
1795         UINT PaletteNumber, const PALETTEENTRY *pEntries)
1796 {
1797     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1798     HRESULT hr;
1799
1800     TRACE("iface %p, palette_idx %u, entries %p.\n", iface, PaletteNumber, pEntries);
1801
1802     wined3d_mutex_lock();
1803     hr = wined3d_device_set_palette_entries(This->wined3d_device, PaletteNumber, pEntries);
1804     wined3d_mutex_unlock();
1805
1806     return hr;
1807 }
1808
1809 static HRESULT WINAPI IDirect3DDevice9Impl_GetPaletteEntries(IDirect3DDevice9Ex *iface,
1810         UINT PaletteNumber, PALETTEENTRY *pEntries)
1811 {
1812     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1813     HRESULT hr;
1814
1815     TRACE("iface %p, palette_idx %u, entries %p.\n", iface, PaletteNumber, pEntries);
1816
1817     wined3d_mutex_lock();
1818     hr = wined3d_device_get_palette_entries(This->wined3d_device, PaletteNumber, pEntries);
1819     wined3d_mutex_unlock();
1820
1821     return hr;
1822 }
1823
1824 static HRESULT WINAPI IDirect3DDevice9Impl_SetCurrentTexturePalette(IDirect3DDevice9Ex *iface,
1825         UINT PaletteNumber)
1826 {
1827     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1828     HRESULT hr;
1829
1830     TRACE("iface %p, palette_idx %u.\n", iface, PaletteNumber);
1831
1832     wined3d_mutex_lock();
1833     hr = wined3d_device_set_current_texture_palette(This->wined3d_device, PaletteNumber);
1834     wined3d_mutex_unlock();
1835
1836     return hr;
1837 }
1838
1839 static HRESULT WINAPI IDirect3DDevice9Impl_GetCurrentTexturePalette(IDirect3DDevice9Ex *iface,
1840         UINT *PaletteNumber)
1841 {
1842     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1843     HRESULT hr;
1844
1845     TRACE("iface %p, palette_idx %p.\n", iface, PaletteNumber);
1846
1847     wined3d_mutex_lock();
1848     hr = wined3d_device_get_current_texture_palette(This->wined3d_device, PaletteNumber);
1849     wined3d_mutex_unlock();
1850
1851     return hr;
1852 }
1853
1854 static HRESULT WINAPI IDirect3DDevice9Impl_SetScissorRect(IDirect3DDevice9Ex *iface,
1855         const RECT *pRect)
1856 {
1857     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1858     HRESULT hr;
1859
1860     TRACE("iface %p, rect %p.\n", iface, pRect);
1861
1862     wined3d_mutex_lock();
1863     hr = wined3d_device_set_scissor_rect(This->wined3d_device, pRect);
1864     wined3d_mutex_unlock();
1865
1866     return hr;
1867 }
1868
1869 static HRESULT WINAPI IDirect3DDevice9Impl_GetScissorRect(IDirect3DDevice9Ex *iface, RECT *pRect)
1870 {
1871     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1872     HRESULT hr;
1873
1874     TRACE("iface %p, rect %p.\n", iface, pRect);
1875
1876     wined3d_mutex_lock();
1877     hr = wined3d_device_get_scissor_rect(This->wined3d_device, pRect);
1878     wined3d_mutex_unlock();
1879
1880     return hr;
1881 }
1882
1883 static HRESULT WINAPI IDirect3DDevice9Impl_SetSoftwareVertexProcessing(IDirect3DDevice9Ex *iface,
1884         BOOL bSoftware)
1885 {
1886     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1887     HRESULT hr;
1888
1889     TRACE("iface %p, software %#x.\n", iface, bSoftware);
1890
1891     wined3d_mutex_lock();
1892     hr = wined3d_device_set_software_vertex_processing(This->wined3d_device, bSoftware);
1893     wined3d_mutex_unlock();
1894
1895     return hr;
1896 }
1897
1898 static BOOL WINAPI IDirect3DDevice9Impl_GetSoftwareVertexProcessing(IDirect3DDevice9Ex *iface)
1899 {
1900     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1901     BOOL ret;
1902
1903     TRACE("iface %p.\n", iface);
1904
1905     wined3d_mutex_lock();
1906     ret = wined3d_device_get_software_vertex_processing(This->wined3d_device);
1907     wined3d_mutex_unlock();
1908
1909     return ret;
1910 }
1911
1912 static HRESULT WINAPI IDirect3DDevice9Impl_SetNPatchMode(IDirect3DDevice9Ex *iface, float nSegments)
1913 {
1914     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1915     HRESULT hr;
1916
1917     TRACE("iface %p, segment_count %.8e.\n", iface, nSegments);
1918
1919     wined3d_mutex_lock();
1920     hr = wined3d_device_set_npatch_mode(This->wined3d_device, nSegments);
1921     wined3d_mutex_unlock();
1922
1923     return hr;
1924 }
1925
1926 static float WINAPI IDirect3DDevice9Impl_GetNPatchMode(IDirect3DDevice9Ex *iface)
1927 {
1928     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1929     float ret;
1930
1931     TRACE("iface %p.\n", iface);
1932
1933     wined3d_mutex_lock();
1934     ret = wined3d_device_get_npatch_mode(This->wined3d_device);
1935     wined3d_mutex_unlock();
1936
1937     return ret;
1938 }
1939
1940 static HRESULT WINAPI IDirect3DDevice9Impl_DrawPrimitive(IDirect3DDevice9Ex *iface,
1941         D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount)
1942 {
1943     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1944     HRESULT hr;
1945
1946     TRACE("iface %p, primitive_type %#x, start_vertex %u, primitive_count %u.\n",
1947             iface, PrimitiveType, StartVertex, PrimitiveCount);
1948
1949     wined3d_mutex_lock();
1950     wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
1951     hr = wined3d_device_draw_primitive(This->wined3d_device, StartVertex,
1952             vertex_count_from_primitive_count(PrimitiveType, PrimitiveCount));
1953     wined3d_mutex_unlock();
1954
1955     return hr;
1956 }
1957
1958 static HRESULT WINAPI IDirect3DDevice9Impl_DrawIndexedPrimitive(IDirect3DDevice9Ex *iface,
1959         D3DPRIMITIVETYPE PrimitiveType, INT BaseVertexIndex, UINT MinVertexIndex, UINT NumVertices,
1960         UINT startIndex, UINT primCount)
1961 {
1962     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1963     HRESULT hr;
1964
1965     TRACE("iface %p, primitive_type %#x, base_vertex_idx %u, min_vertex_idx %u,\n"
1966             "vertex_count %u, start_idx %u, primitive_count %u.\n",
1967             iface, PrimitiveType, BaseVertexIndex, MinVertexIndex,
1968             NumVertices, startIndex, primCount);
1969
1970     wined3d_mutex_lock();
1971     wined3d_device_set_base_vertex_index(This->wined3d_device, BaseVertexIndex);
1972     wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
1973     hr = wined3d_device_draw_indexed_primitive(This->wined3d_device, startIndex,
1974             vertex_count_from_primitive_count(PrimitiveType, primCount));
1975     wined3d_mutex_unlock();
1976
1977     return hr;
1978 }
1979
1980 static HRESULT WINAPI IDirect3DDevice9Impl_DrawPrimitiveUP(IDirect3DDevice9Ex *iface,
1981         D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, const void *pVertexStreamZeroData,
1982         UINT VertexStreamZeroStride)
1983 {
1984     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
1985     HRESULT hr;
1986
1987     TRACE("iface %p, primitive_type %#x, primitive_count %u, data %p, stride %u.\n",
1988             iface, PrimitiveType, PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
1989
1990     wined3d_mutex_lock();
1991     wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
1992     hr = wined3d_device_draw_primitive_up(This->wined3d_device,
1993             vertex_count_from_primitive_count(PrimitiveType, PrimitiveCount),
1994             pVertexStreamZeroData, VertexStreamZeroStride);
1995     wined3d_mutex_unlock();
1996
1997     return hr;
1998 }
1999
2000 static HRESULT WINAPI IDirect3DDevice9Impl_DrawIndexedPrimitiveUP(IDirect3DDevice9Ex *iface,
2001         D3DPRIMITIVETYPE PrimitiveType, UINT MinVertexIndex, UINT NumVertexIndices,
2002         UINT PrimitiveCount, const void *pIndexData, D3DFORMAT IndexDataFormat,
2003         const void *pVertexStreamZeroData, UINT VertexStreamZeroStride)
2004 {
2005     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2006     HRESULT hr;
2007
2008     TRACE("iface %p, primitive_type %#x, min_vertex_idx %u, index_count %u, primitive_count %u,\n"
2009             "index_data %p, index_format %#x, vertex_data %p, vertex_stride %u.\n",
2010             iface, PrimitiveType, MinVertexIndex, NumVertexIndices, PrimitiveCount,
2011             pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
2012
2013     wined3d_mutex_lock();
2014     wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
2015     hr = wined3d_device_draw_indexed_primitive_up(This->wined3d_device,
2016             vertex_count_from_primitive_count(PrimitiveType, PrimitiveCount), pIndexData,
2017             wined3dformat_from_d3dformat(IndexDataFormat), pVertexStreamZeroData, VertexStreamZeroStride);
2018     wined3d_mutex_unlock();
2019
2020     return hr;
2021 }
2022
2023 static HRESULT WINAPI IDirect3DDevice9Impl_ProcessVertices(IDirect3DDevice9Ex *iface,
2024         UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IDirect3DVertexBuffer9 *pDestBuffer,
2025         IDirect3DVertexDeclaration9 *pVertexDecl, DWORD Flags)
2026 {
2027     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2028     IDirect3DVertexBuffer9Impl *dest = unsafe_impl_from_IDirect3DVertexBuffer9(pDestBuffer);
2029     IDirect3DVertexDeclaration9Impl *Decl = (IDirect3DVertexDeclaration9Impl *) pVertexDecl;
2030     HRESULT hr;
2031
2032     TRACE("iface %p, src_start_idx %u, dst_idx %u, vertex_count %u, dst_buffer %p, declaration %p, flags %#x.\n",
2033             iface, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
2034
2035     wined3d_mutex_lock();
2036     hr = wined3d_device_process_vertices(This->wined3d_device, SrcStartIndex, DestIndex, VertexCount,
2037             dest->wineD3DVertexBuffer, Decl ? Decl->wineD3DVertexDeclaration : NULL, Flags, dest->fvf);
2038     wined3d_mutex_unlock();
2039
2040     return hr;
2041 }
2042
2043 static HRESULT WINAPI IDirect3DDevice9Impl_CreateVertexDeclaration(IDirect3DDevice9Ex *iface,
2044         const D3DVERTEXELEMENT9 *elements, IDirect3DVertexDeclaration9 **declaration)
2045 {
2046     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2047     IDirect3DVertexDeclaration9Impl *object;
2048     HRESULT hr;
2049
2050     TRACE("iface %p, elements %p, declaration %p.\n", iface, elements, declaration);
2051
2052     if (!declaration)
2053     {
2054         WARN("Caller passed a NULL declaration, returning D3DERR_INVALIDCALL.\n");
2055         return D3DERR_INVALIDCALL;
2056     }
2057
2058     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
2059     if (!object)
2060     {
2061         ERR("Failed to allocate vertex declaration memory.\n");
2062         return E_OUTOFMEMORY;
2063     }
2064
2065     hr = vertexdeclaration_init(object, This, elements);
2066     if (FAILED(hr))
2067     {
2068         WARN("Failed to initialize vertex declaration, hr %#x.\n", hr);
2069         HeapFree(GetProcessHeap(), 0, object);
2070         return hr;
2071     }
2072
2073     TRACE("Created vertex declaration %p.\n", object);
2074     *declaration = (IDirect3DVertexDeclaration9 *)object;
2075
2076     return D3D_OK;
2077 }
2078
2079 static HRESULT WINAPI IDirect3DDevice9Impl_SetVertexDeclaration(IDirect3DDevice9Ex *iface,
2080         IDirect3DVertexDeclaration9 *declaration)
2081 {
2082     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2083     HRESULT hr;
2084
2085     TRACE("iface %p, declaration %p.\n", iface, declaration);
2086
2087     wined3d_mutex_lock();
2088     hr = wined3d_device_set_vertex_declaration(This->wined3d_device,
2089             declaration ? ((IDirect3DVertexDeclaration9Impl *)declaration)->wineD3DVertexDeclaration : NULL);
2090     wined3d_mutex_unlock();
2091
2092     return hr;
2093 }
2094
2095 static HRESULT WINAPI IDirect3DDevice9Impl_GetVertexDeclaration(IDirect3DDevice9Ex *iface,
2096         IDirect3DVertexDeclaration9 **declaration)
2097 {
2098     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2099     struct wined3d_vertex_declaration *wined3d_declaration = NULL;
2100     HRESULT hr;
2101
2102     TRACE("iface %p, declaration %p.\n", iface, declaration);
2103
2104     if (!declaration) return D3DERR_INVALIDCALL;
2105
2106     wined3d_mutex_lock();
2107     hr = wined3d_device_get_vertex_declaration(This->wined3d_device, &wined3d_declaration);
2108     if (SUCCEEDED(hr) && wined3d_declaration)
2109     {
2110         *declaration = wined3d_vertex_declaration_get_parent(wined3d_declaration);
2111         IDirect3DVertexDeclaration9_AddRef(*declaration);
2112         wined3d_vertex_declaration_decref(wined3d_declaration);
2113     }
2114     else
2115     {
2116         *declaration = NULL;
2117     }
2118     wined3d_mutex_unlock();
2119
2120     TRACE("Returning %p.\n", *declaration);
2121     return hr;
2122 }
2123
2124 static IDirect3DVertexDeclaration9 *getConvertedDecl(IDirect3DDevice9Impl *This, DWORD fvf) {
2125     HRESULT hr;
2126     D3DVERTEXELEMENT9* elements = NULL;
2127     IDirect3DVertexDeclaration9* pDecl = NULL;
2128     int p, low, high; /* deliberately signed */
2129     IDirect3DVertexDeclaration9  **convertedDecls = This->convertedDecls;
2130
2131     TRACE("Searching for declaration for fvf %08x... ", fvf);
2132
2133     low = 0;
2134     high = This->numConvertedDecls - 1;
2135     while(low <= high) {
2136         p = (low + high) >> 1;
2137         TRACE("%d ", p);
2138         if(((IDirect3DVertexDeclaration9Impl *) convertedDecls[p])->convFVF == fvf) {
2139             TRACE("found %p\n", convertedDecls[p]);
2140             return convertedDecls[p];
2141         } else if(((IDirect3DVertexDeclaration9Impl *) convertedDecls[p])->convFVF < fvf) {
2142             low = p + 1;
2143         } else {
2144             high = p - 1;
2145         }
2146     }
2147     TRACE("not found. Creating and inserting at position %d.\n", low);
2148
2149     hr = vdecl_convert_fvf(fvf, &elements);
2150     if (hr != S_OK) return NULL;
2151
2152     hr = IDirect3DDevice9Impl_CreateVertexDeclaration(&This->IDirect3DDevice9Ex_iface, elements,
2153             &pDecl);
2154     HeapFree(GetProcessHeap(), 0, elements); /* CreateVertexDeclaration makes a copy */
2155     if (hr != S_OK) return NULL;
2156
2157     if(This->declArraySize == This->numConvertedDecls) {
2158         int grow = max(This->declArraySize / 2, 8);
2159         convertedDecls = HeapReAlloc(GetProcessHeap(), 0, convertedDecls,
2160                                      sizeof(convertedDecls[0]) * (This->numConvertedDecls + grow));
2161         if(!convertedDecls) {
2162             /* This will destroy it */
2163             IDirect3DVertexDeclaration9_Release(pDecl);
2164             return NULL;
2165         }
2166         This->convertedDecls = convertedDecls;
2167         This->declArraySize += grow;
2168     }
2169
2170     memmove(convertedDecls + low + 1, convertedDecls + low, sizeof(IDirect3DVertexDeclaration9Impl *) * (This->numConvertedDecls - low));
2171     convertedDecls[low] = pDecl;
2172     This->numConvertedDecls++;
2173
2174     /* Will prevent the decl from being destroyed */
2175     ((IDirect3DVertexDeclaration9Impl *) pDecl)->convFVF = fvf;
2176     IDirect3DVertexDeclaration9_Release(pDecl); /* Does not destroy now */
2177
2178     TRACE("Returning %p. %d decls in array\n", pDecl, This->numConvertedDecls);
2179     return pDecl;
2180 }
2181
2182 static HRESULT WINAPI IDirect3DDevice9Impl_SetFVF(IDirect3DDevice9Ex *iface, DWORD FVF)
2183 {
2184     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2185     IDirect3DVertexDeclaration9 *decl;
2186     HRESULT hr;
2187
2188     TRACE("iface %p, fvf %#x.\n", iface, FVF);
2189
2190     if (!FVF)
2191     {
2192         WARN("%#x is not a valid FVF\n", FVF);
2193         return D3D_OK;
2194     }
2195
2196     wined3d_mutex_lock();
2197     decl = getConvertedDecl(This, FVF);
2198     wined3d_mutex_unlock();
2199
2200     if (!decl)
2201     {
2202          /* Any situation when this should happen, except out of memory? */
2203          ERR("Failed to create a converted vertex declaration\n");
2204          return D3DERR_DRIVERINTERNALERROR;
2205     }
2206
2207     hr = IDirect3DDevice9Impl_SetVertexDeclaration(iface, decl);
2208     if (FAILED(hr)) ERR("Failed to set vertex declaration\n");
2209
2210     return hr;
2211 }
2212
2213 static HRESULT WINAPI IDirect3DDevice9Impl_GetFVF(IDirect3DDevice9Ex *iface, DWORD *pFVF)
2214 {
2215     IDirect3DVertexDeclaration9 *decl;
2216     HRESULT hr;
2217
2218     TRACE("iface %p, fvf %p.\n", iface, pFVF);
2219
2220     hr = IDirect3DDevice9_GetVertexDeclaration(iface, &decl);
2221     if (FAILED(hr))
2222     {
2223         WARN("Failed to get vertex declaration, %#x\n", hr);
2224         *pFVF = 0;
2225         return hr;
2226     }
2227
2228     if (decl)
2229     {
2230         *pFVF = ((IDirect3DVertexDeclaration9Impl *)decl)->convFVF;
2231         IDirect3DVertexDeclaration9_Release(decl);
2232     }
2233     else
2234     {
2235         *pFVF = 0;
2236     }
2237
2238     TRACE("Returning FVF %#x\n", *pFVF);
2239
2240     return hr;
2241 }
2242
2243 static HRESULT WINAPI IDirect3DDevice9Impl_CreateVertexShader(IDirect3DDevice9Ex *iface,
2244         const DWORD *byte_code, IDirect3DVertexShader9 **shader)
2245 {
2246     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2247     IDirect3DVertexShader9Impl *object;
2248     HRESULT hr;
2249
2250     TRACE("iface %p, byte_code %p, shader %p.\n", iface, byte_code, shader);
2251
2252     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
2253     if (!object)
2254     {
2255         ERR("Failed to allocate vertex shader memory.\n");
2256         return E_OUTOFMEMORY;
2257     }
2258
2259     hr = vertexshader_init(object, This, byte_code);
2260     if (FAILED(hr))
2261     {
2262         WARN("Failed to initialize vertex shader, hr %#x.\n", hr);
2263         HeapFree(GetProcessHeap(), 0, object);
2264         return hr;
2265     }
2266
2267     TRACE("Created vertex shader %p.\n", object);
2268     *shader = &object->IDirect3DVertexShader9_iface;
2269
2270     return D3D_OK;
2271 }
2272
2273 static HRESULT WINAPI IDirect3DDevice9Impl_SetVertexShader(IDirect3DDevice9Ex *iface,
2274         IDirect3DVertexShader9 *shader)
2275 {
2276     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2277     IDirect3DVertexShader9Impl *shader_obj = unsafe_impl_from_IDirect3DVertexShader9(shader);
2278     HRESULT hr;
2279
2280     TRACE("iface %p, shader %p.\n", iface, shader);
2281
2282     wined3d_mutex_lock();
2283     hr =  wined3d_device_set_vertex_shader(This->wined3d_device,
2284             shader_obj ? shader_obj->wined3d_shader : NULL);
2285     wined3d_mutex_unlock();
2286
2287     return hr;
2288 }
2289
2290 static HRESULT WINAPI IDirect3DDevice9Impl_GetVertexShader(IDirect3DDevice9Ex *iface,
2291         IDirect3DVertexShader9 **shader)
2292 {
2293     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2294     struct wined3d_shader *wined3d_shader;
2295
2296     TRACE("iface %p, shader %p.\n", iface, shader);
2297
2298     wined3d_mutex_lock();
2299     wined3d_shader = wined3d_device_get_vertex_shader(This->wined3d_device);
2300     if (wined3d_shader)
2301     {
2302         *shader = wined3d_shader_get_parent(wined3d_shader);
2303         IDirect3DVertexShader9_AddRef(*shader);
2304         wined3d_shader_decref(wined3d_shader);
2305     }
2306     else
2307     {
2308         *shader = NULL;
2309     }
2310     wined3d_mutex_unlock();
2311
2312     TRACE("Returning %p.\n", *shader);
2313
2314     return D3D_OK;
2315 }
2316
2317 static HRESULT WINAPI IDirect3DDevice9Impl_SetVertexShaderConstantF(IDirect3DDevice9Ex *iface,
2318         UINT reg_idx, const float *data, UINT count)
2319 {
2320     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2321     HRESULT hr;
2322
2323     TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
2324
2325     if (reg_idx + count > D3D9_MAX_VERTEX_SHADER_CONSTANTF)
2326     {
2327         WARN("Trying to access %u constants, but d3d9 only supports %u\n",
2328              reg_idx + count, D3D9_MAX_VERTEX_SHADER_CONSTANTF);
2329         return D3DERR_INVALIDCALL;
2330     }
2331
2332     wined3d_mutex_lock();
2333     hr = wined3d_device_set_vs_consts_f(This->wined3d_device, reg_idx, data, count);
2334     wined3d_mutex_unlock();
2335
2336     return hr;
2337 }
2338
2339 static HRESULT WINAPI IDirect3DDevice9Impl_GetVertexShaderConstantF(IDirect3DDevice9Ex *iface,
2340         UINT reg_idx, float *data, UINT count)
2341 {
2342     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2343     HRESULT hr;
2344
2345     TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
2346
2347     if (reg_idx + count > D3D9_MAX_VERTEX_SHADER_CONSTANTF)
2348     {
2349         WARN("Trying to access %u constants, but d3d9 only supports %u\n",
2350              reg_idx + count, D3D9_MAX_VERTEX_SHADER_CONSTANTF);
2351         return D3DERR_INVALIDCALL;
2352     }
2353
2354     wined3d_mutex_lock();
2355     hr = wined3d_device_get_vs_consts_f(This->wined3d_device, reg_idx, data, count);
2356     wined3d_mutex_unlock();
2357
2358     return hr;
2359 }
2360
2361 static HRESULT WINAPI IDirect3DDevice9Impl_SetVertexShaderConstantI(IDirect3DDevice9Ex *iface,
2362         UINT reg_idx, const int *data, UINT count)
2363 {
2364     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2365     HRESULT hr;
2366
2367     TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
2368
2369     wined3d_mutex_lock();
2370     hr = wined3d_device_set_vs_consts_i(This->wined3d_device, reg_idx, data, count);
2371     wined3d_mutex_unlock();
2372
2373     return hr;
2374 }
2375
2376 static HRESULT WINAPI IDirect3DDevice9Impl_GetVertexShaderConstantI(IDirect3DDevice9Ex *iface,
2377         UINT reg_idx, int *data, UINT count)
2378 {
2379     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2380     HRESULT hr;
2381
2382     TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
2383
2384     wined3d_mutex_lock();
2385     hr = wined3d_device_get_vs_consts_i(This->wined3d_device, reg_idx, data, count);
2386     wined3d_mutex_unlock();
2387
2388     return hr;
2389 }
2390
2391 static HRESULT WINAPI IDirect3DDevice9Impl_SetVertexShaderConstantB(IDirect3DDevice9Ex *iface,
2392         UINT reg_idx, const BOOL *data, UINT count)
2393 {
2394     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2395     HRESULT hr;
2396
2397     TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
2398
2399     wined3d_mutex_lock();
2400     hr = wined3d_device_set_vs_consts_b(This->wined3d_device, reg_idx, data, count);
2401     wined3d_mutex_unlock();
2402
2403     return hr;
2404 }
2405
2406 static HRESULT WINAPI IDirect3DDevice9Impl_GetVertexShaderConstantB(IDirect3DDevice9Ex *iface,
2407         UINT reg_idx, BOOL *data, UINT count)
2408 {
2409     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2410     HRESULT hr;
2411
2412     TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
2413
2414     wined3d_mutex_lock();
2415     hr = wined3d_device_get_vs_consts_b(This->wined3d_device, reg_idx, data, count);
2416     wined3d_mutex_unlock();
2417
2418     return hr;
2419 }
2420
2421 static HRESULT WINAPI IDirect3DDevice9Impl_SetStreamSource(IDirect3DDevice9Ex *iface,
2422         UINT StreamNumber, IDirect3DVertexBuffer9 *pStreamData, UINT OffsetInBytes, UINT Stride)
2423 {
2424     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2425     IDirect3DVertexBuffer9Impl *streamdata = unsafe_impl_from_IDirect3DVertexBuffer9(pStreamData);
2426     HRESULT hr;
2427
2428     TRACE("iface %p, stream_idx %u, buffer %p, offset %u, stride %u.\n",
2429             iface, StreamNumber, pStreamData, OffsetInBytes, Stride);
2430
2431     wined3d_mutex_lock();
2432     hr = wined3d_device_set_stream_source(This->wined3d_device, StreamNumber,
2433             streamdata ? streamdata->wineD3DVertexBuffer : NULL,
2434             OffsetInBytes, Stride);
2435     wined3d_mutex_unlock();
2436
2437     return hr;
2438 }
2439
2440 static HRESULT WINAPI IDirect3DDevice9Impl_GetStreamSource(IDirect3DDevice9Ex *iface,
2441         UINT StreamNumber, IDirect3DVertexBuffer9 **pStream, UINT *OffsetInBytes, UINT *pStride)
2442 {
2443     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2444     struct wined3d_buffer *retStream = NULL;
2445     HRESULT hr;
2446
2447     TRACE("iface %p, stream_idx %u, buffer %p, offset %p, stride %p.\n",
2448             iface, StreamNumber, pStream, OffsetInBytes, pStride);
2449
2450     if(pStream == NULL){
2451         return D3DERR_INVALIDCALL;
2452     }
2453
2454     wined3d_mutex_lock();
2455     hr = wined3d_device_get_stream_source(This->wined3d_device, StreamNumber, &retStream, OffsetInBytes, pStride);
2456     if (SUCCEEDED(hr) && retStream)
2457     {
2458         *pStream = wined3d_buffer_get_parent(retStream);
2459         IDirect3DVertexBuffer9_AddRef(*pStream);
2460         wined3d_buffer_decref(retStream);
2461     }
2462     else
2463     {
2464         if (FAILED(hr))
2465         {
2466             FIXME("Call to GetStreamSource failed %p %p\n", OffsetInBytes, pStride);
2467         }
2468         *pStream = NULL;
2469     }
2470     wined3d_mutex_unlock();
2471
2472     return hr;
2473 }
2474
2475 static HRESULT WINAPI IDirect3DDevice9Impl_SetStreamSourceFreq(IDirect3DDevice9Ex *iface,
2476         UINT StreamNumber, UINT Divider)
2477 {
2478     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2479     HRESULT hr;
2480
2481     TRACE("iface %p, stream_idx %u, freq %u.\n", iface, StreamNumber, Divider);
2482
2483     wined3d_mutex_lock();
2484     hr = wined3d_device_set_stream_source_freq(This->wined3d_device, StreamNumber, Divider);
2485     wined3d_mutex_unlock();
2486
2487     return hr;
2488 }
2489
2490 static HRESULT WINAPI IDirect3DDevice9Impl_GetStreamSourceFreq(IDirect3DDevice9Ex *iface,
2491         UINT StreamNumber, UINT *Divider)
2492 {
2493     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2494     HRESULT hr;
2495
2496     TRACE("iface %p, stream_idx %u, freq %p.\n", iface, StreamNumber, Divider);
2497
2498     wined3d_mutex_lock();
2499     hr = wined3d_device_get_stream_source_freq(This->wined3d_device, StreamNumber, Divider);
2500     wined3d_mutex_unlock();
2501
2502     return hr;
2503 }
2504
2505 static HRESULT WINAPI IDirect3DDevice9Impl_SetIndices(IDirect3DDevice9Ex *iface,
2506         IDirect3DIndexBuffer9 *pIndexData)
2507 {
2508     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2509     IDirect3DIndexBuffer9Impl *ib = unsafe_impl_from_IDirect3DIndexBuffer9(pIndexData);
2510     HRESULT hr;
2511
2512     TRACE("iface %p, buffer %p.\n", iface, pIndexData);
2513
2514     wined3d_mutex_lock();
2515     hr = wined3d_device_set_index_buffer(This->wined3d_device,
2516             ib ? ib->wineD3DIndexBuffer : NULL,
2517             ib ? ib->format : WINED3DFMT_UNKNOWN);
2518     wined3d_mutex_unlock();
2519
2520     return hr;
2521 }
2522
2523 static HRESULT WINAPI IDirect3DDevice9Impl_GetIndices(IDirect3DDevice9Ex *iface,
2524         IDirect3DIndexBuffer9 **ppIndexData)
2525 {
2526     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2527     struct wined3d_buffer *retIndexData = NULL;
2528     HRESULT hr;
2529
2530     TRACE("iface %p, buffer %p.\n", iface, ppIndexData);
2531
2532     if(ppIndexData == NULL){
2533         return D3DERR_INVALIDCALL;
2534     }
2535
2536     wined3d_mutex_lock();
2537     hr = wined3d_device_get_index_buffer(This->wined3d_device, &retIndexData);
2538     if (SUCCEEDED(hr) && retIndexData)
2539     {
2540         *ppIndexData = wined3d_buffer_get_parent(retIndexData);
2541         IDirect3DIndexBuffer9_AddRef(*ppIndexData);
2542         wined3d_buffer_decref(retIndexData);
2543     }
2544     else
2545     {
2546         if (FAILED(hr)) FIXME("Call to GetIndices failed\n");
2547         *ppIndexData = NULL;
2548     }
2549     wined3d_mutex_unlock();
2550
2551     return hr;
2552 }
2553
2554 static HRESULT WINAPI IDirect3DDevice9Impl_CreatePixelShader(IDirect3DDevice9Ex *iface,
2555         const DWORD *byte_code, IDirect3DPixelShader9 **shader)
2556 {
2557     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2558     IDirect3DPixelShader9Impl *object;
2559     HRESULT hr;
2560
2561     TRACE("iface %p, byte_code %p, shader %p.\n", iface, byte_code, shader);
2562
2563     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
2564     if (!object)
2565     {
2566         FIXME("Failed to allocate pixel shader memory.\n");
2567         return E_OUTOFMEMORY;
2568     }
2569
2570     hr = pixelshader_init(object, This, byte_code);
2571     if (FAILED(hr))
2572     {
2573         WARN("Failed to initialize pixel shader, hr %#x.\n", hr);
2574         HeapFree(GetProcessHeap(), 0, object);
2575         return hr;
2576     }
2577
2578     TRACE("Created pixel shader %p.\n", object);
2579     *shader = &object->IDirect3DPixelShader9_iface;
2580
2581     return D3D_OK;
2582 }
2583
2584 static HRESULT WINAPI IDirect3DDevice9Impl_SetPixelShader(IDirect3DDevice9Ex *iface,
2585         IDirect3DPixelShader9 *shader)
2586 {
2587     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2588     IDirect3DPixelShader9Impl *shader_obj = unsafe_impl_from_IDirect3DPixelShader9(shader);
2589     HRESULT hr;
2590
2591     TRACE("iface %p, shader %p.\n", iface, shader);
2592
2593     wined3d_mutex_lock();
2594     hr = wined3d_device_set_pixel_shader(This->wined3d_device,
2595             shader_obj ? shader_obj->wined3d_shader : NULL);
2596     wined3d_mutex_unlock();
2597
2598     return hr;
2599 }
2600
2601 static HRESULT WINAPI IDirect3DDevice9Impl_GetPixelShader(IDirect3DDevice9Ex *iface,
2602         IDirect3DPixelShader9 **shader)
2603 {
2604     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2605     struct wined3d_shader *wined3d_shader;
2606
2607     TRACE("iface %p, shader %p.\n", iface, shader);
2608
2609     if (!shader) return D3DERR_INVALIDCALL;
2610
2611     wined3d_mutex_lock();
2612     wined3d_shader = wined3d_device_get_pixel_shader(This->wined3d_device);
2613     if (wined3d_shader)
2614     {
2615         *shader = wined3d_shader_get_parent(wined3d_shader);
2616         IDirect3DPixelShader9_AddRef(*shader);
2617         wined3d_shader_decref(wined3d_shader);
2618     }
2619     else
2620     {
2621         *shader = NULL;
2622     }
2623     wined3d_mutex_unlock();
2624
2625     TRACE("Returning %p.\n", *shader);
2626
2627     return D3D_OK;
2628 }
2629
2630 static HRESULT WINAPI IDirect3DDevice9Impl_SetPixelShaderConstantF(IDirect3DDevice9Ex *iface,
2631         UINT reg_idx, const float *data, UINT count)
2632 {
2633     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2634     HRESULT hr;
2635
2636     TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
2637
2638     wined3d_mutex_lock();
2639     hr = wined3d_device_set_ps_consts_f(This->wined3d_device, reg_idx, data, count);
2640     wined3d_mutex_unlock();
2641
2642     return hr;
2643 }
2644
2645 static HRESULT WINAPI IDirect3DDevice9Impl_GetPixelShaderConstantF(IDirect3DDevice9Ex *iface,
2646         UINT reg_idx, float *data, UINT count)
2647 {
2648     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2649     HRESULT hr;
2650
2651     TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
2652
2653     wined3d_mutex_lock();
2654     hr = wined3d_device_get_ps_consts_f(This->wined3d_device, reg_idx, data, count);
2655     wined3d_mutex_unlock();
2656
2657     return hr;
2658 }
2659
2660 static HRESULT WINAPI IDirect3DDevice9Impl_SetPixelShaderConstantI(IDirect3DDevice9Ex *iface,
2661         UINT reg_idx, const int *data, UINT count)
2662 {
2663     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2664     HRESULT hr;
2665
2666     TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
2667
2668     wined3d_mutex_lock();
2669     hr = wined3d_device_set_ps_consts_i(This->wined3d_device, reg_idx, data, count);
2670     wined3d_mutex_unlock();
2671
2672     return hr;
2673 }
2674
2675 static HRESULT WINAPI IDirect3DDevice9Impl_GetPixelShaderConstantI(IDirect3DDevice9Ex *iface,
2676         UINT reg_idx, int *data, UINT count)
2677 {
2678     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2679     HRESULT hr;
2680
2681     TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
2682
2683     wined3d_mutex_lock();
2684     hr = wined3d_device_get_ps_consts_i(This->wined3d_device, reg_idx, data, count);
2685     wined3d_mutex_unlock();
2686
2687     return hr;
2688 }
2689
2690 static HRESULT WINAPI IDirect3DDevice9Impl_SetPixelShaderConstantB(IDirect3DDevice9Ex *iface,
2691         UINT reg_idx, const BOOL *data, UINT count)
2692 {
2693     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2694     HRESULT hr;
2695
2696     TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
2697
2698     wined3d_mutex_lock();
2699     hr = wined3d_device_set_ps_consts_b(This->wined3d_device, reg_idx, data, count);
2700     wined3d_mutex_unlock();
2701
2702     return hr;
2703 }
2704
2705 static HRESULT WINAPI IDirect3DDevice9Impl_GetPixelShaderConstantB(IDirect3DDevice9Ex *iface,
2706         UINT reg_idx, BOOL *data, UINT count)
2707 {
2708     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2709     HRESULT hr;
2710
2711     TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
2712
2713     wined3d_mutex_lock();
2714     hr = wined3d_device_get_ps_consts_b(This->wined3d_device, reg_idx, data, count);
2715     wined3d_mutex_unlock();
2716
2717     return hr;
2718 }
2719
2720 static HRESULT WINAPI IDirect3DDevice9Impl_DrawRectPatch(IDirect3DDevice9Ex *iface, UINT Handle,
2721         const float *pNumSegs, const D3DRECTPATCH_INFO *pRectPatchInfo)
2722 {
2723     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2724     HRESULT hr;
2725
2726     TRACE("iface %p, handle %#x, segment_count %p, patch_info %p.\n",
2727             iface, Handle, pNumSegs, pRectPatchInfo);
2728
2729     wined3d_mutex_lock();
2730     hr = wined3d_device_draw_rect_patch(This->wined3d_device, Handle,
2731             pNumSegs, (const WINED3DRECTPATCH_INFO *)pRectPatchInfo);
2732     wined3d_mutex_unlock();
2733
2734     return hr;
2735 }
2736
2737 static HRESULT WINAPI IDirect3DDevice9Impl_DrawTriPatch(IDirect3DDevice9Ex *iface, UINT Handle,
2738         const float *pNumSegs, const D3DTRIPATCH_INFO *pTriPatchInfo)
2739 {
2740     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2741     HRESULT hr;
2742
2743     TRACE("iface %p, handle %#x, segment_count %p, patch_info %p.\n",
2744             iface, Handle, pNumSegs, pTriPatchInfo);
2745
2746     wined3d_mutex_lock();
2747     hr = wined3d_device_draw_tri_patch(This->wined3d_device, Handle,
2748             pNumSegs, (const WINED3DTRIPATCH_INFO *)pTriPatchInfo);
2749     wined3d_mutex_unlock();
2750
2751     return hr;
2752 }
2753
2754 static HRESULT WINAPI IDirect3DDevice9Impl_DeletePatch(IDirect3DDevice9Ex *iface, UINT Handle)
2755 {
2756     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2757     HRESULT hr;
2758
2759     TRACE("iface %p, handle %#x.\n", iface, Handle);
2760
2761     wined3d_mutex_lock();
2762     hr = wined3d_device_delete_patch(This->wined3d_device, Handle);
2763     wined3d_mutex_unlock();
2764
2765     return hr;
2766 }
2767
2768 static HRESULT WINAPI IDirect3DDevice9Impl_CreateQuery(IDirect3DDevice9Ex *iface, D3DQUERYTYPE type,
2769         IDirect3DQuery9 **query)
2770 {
2771     IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
2772     IDirect3DQuery9Impl *object;
2773     HRESULT hr;
2774
2775     TRACE("iface %p, type %#x, query %p.\n", iface, type, query);
2776
2777     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
2778     if (!object)
2779     {
2780         ERR("Failed to allocate query memory.\n");
2781         return E_OUTOFMEMORY;
2782     }
2783
2784     hr = query_init(object, This, type);
2785     if (FAILED(hr))
2786     {
2787         WARN("Failed to initialize query, hr %#x.\n", hr);
2788         HeapFree(GetProcessHeap(), 0, object);
2789         return hr;
2790     }
2791
2792     TRACE("Created query %p.\n", object);
2793     if (query) *query = &object->IDirect3DQuery9_iface;
2794     else IDirect3DQuery9_Release(&object->IDirect3DQuery9_iface);
2795
2796     return D3D_OK;
2797 }
2798
2799 static HRESULT WINAPI IDirect3DDevice9ExImpl_SetConvolutionMonoKernel(IDirect3DDevice9Ex *iface,
2800         UINT width, UINT height, float *rows, float *columns)
2801 {
2802     FIXME("iface %p, width %u, height %u, rows %p, columns %p stub!\n",
2803             iface, width, height, rows, columns);
2804
2805     return E_NOTIMPL;
2806 }
2807
2808 static HRESULT WINAPI IDirect3DDevice9ExImpl_ComposeRects(IDirect3DDevice9Ex *iface,
2809         IDirect3DSurface9 *src_surface, IDirect3DSurface9 *dst_surface, IDirect3DVertexBuffer9 *src_descs,
2810         UINT rect_count, IDirect3DVertexBuffer9 *dst_descs, D3DCOMPOSERECTSOP operation, INT offset_x, INT offset_y)
2811 {
2812     FIXME("iface %p, src_surface %p, dst_surface %p, src_descs %p, rect_count %u,\n"
2813             "dst_descs %p, operation %#x, offset_x %u, offset_y %u stub!\n",
2814             iface, src_surface, dst_surface, src_descs, rect_count,
2815             dst_descs, operation, offset_x, offset_y);
2816
2817     return E_NOTIMPL;
2818 }
2819
2820 static HRESULT WINAPI IDirect3DDevice9ExImpl_PresentEx(IDirect3DDevice9Ex *iface,
2821         const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override,
2822         const RGNDATA *dirty_region, DWORD flags)
2823 {
2824     FIXME("iface %p, src_rect %p, dst_rect %p, dst_window_override %p, dirty_region %p, flags %#x stub!\n",
2825             iface, src_rect, dst_rect, dst_window_override, dirty_region, flags);
2826
2827     return E_NOTIMPL;
2828 }
2829
2830 static HRESULT WINAPI IDirect3DDevice9ExImpl_GetGPUThreadPriority(IDirect3DDevice9Ex *iface, INT *priority)
2831 {
2832     FIXME("iface %p, priority %p stub!\n", iface, priority);
2833
2834     return E_NOTIMPL;
2835 }
2836
2837 static HRESULT WINAPI IDirect3DDevice9ExImpl_SetGPUThreadPriority(IDirect3DDevice9Ex *iface, INT priority)
2838 {
2839     FIXME("iface %p, priority %d stub!\n", iface, priority);
2840
2841     return E_NOTIMPL;
2842 }
2843
2844 static HRESULT WINAPI IDirect3DDevice9ExImpl_WaitForVBlank(IDirect3DDevice9Ex *iface, UINT swapchain_idx)
2845 {
2846     FIXME("iface %p, swapchain_idx %u stub!\n", iface, swapchain_idx);
2847
2848     return E_NOTIMPL;
2849 }
2850
2851 static HRESULT WINAPI IDirect3DDevice9ExImpl_CheckResourceResidency(IDirect3DDevice9Ex *iface,
2852         IDirect3DResource9 **resources, UINT32 resource_count)
2853 {
2854     FIXME("iface %p, resources %p, resource_count %u stub!\n",
2855             iface, resources, resource_count);
2856
2857     return E_NOTIMPL;
2858 }
2859
2860 static HRESULT WINAPI IDirect3DDevice9ExImpl_SetMaximumFrameLatency(IDirect3DDevice9Ex *iface, UINT max_latency)
2861 {
2862     FIXME("iface %p, max_latency %u stub!\n", iface, max_latency);
2863
2864     return E_NOTIMPL;
2865 }
2866
2867 static HRESULT WINAPI IDirect3DDevice9ExImpl_GetMaximumFrameLatency(IDirect3DDevice9Ex *iface, UINT *max_latency)
2868 {
2869     FIXME("iface %p, max_latency %p stub!\n", iface, max_latency);
2870
2871     *max_latency = 2;
2872
2873     return E_NOTIMPL;
2874 }
2875
2876 static HRESULT WINAPI IDirect3DDevice9ExImpl_CheckDeviceState(IDirect3DDevice9Ex *iface, HWND dst_window)
2877 {
2878     static int i;
2879
2880     TRACE("iface %p, dst_window %p stub!\n", iface, dst_window);
2881
2882     if (!i++)
2883         FIXME("iface %p, dst_window %p stub!\n", iface, dst_window);
2884
2885     return D3D_OK;
2886 }
2887
2888 static HRESULT WINAPI IDirect3DDevice9ExImpl_CreateRenderTargetEx(IDirect3DDevice9Ex *iface,
2889         UINT width, UINT height, D3DFORMAT format, D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality,
2890         BOOL lockable, IDirect3DSurface9 **surface, HANDLE *shared_handle, DWORD usage)
2891 {
2892     FIXME("iface %p, width %u, height %u, format %#x, multisample_type %#x, multisample_quality %u,\n"
2893             "lockable %#x, surface %p, shared_handle %p, usage %#x stub!\n",
2894             iface, width, height, format, multisample_type, multisample_quality,
2895             lockable, surface, shared_handle, usage);
2896
2897     return E_NOTIMPL;
2898 }
2899
2900 static HRESULT WINAPI IDirect3DDevice9ExImpl_CreateOffscreenPlainSurfaceEx(IDirect3DDevice9Ex *iface,
2901         UINT width, UINT height, D3DFORMAT format, D3DPOOL pool, IDirect3DSurface9 **surface,
2902         HANDLE *shared_handle, DWORD usage)
2903 {
2904     FIXME("iface %p, width %u, height %u, format %#x, pool %#x, surface %p, shared_handle %p, usage %#x stub!\n",
2905             iface, width, height, format, pool, surface, shared_handle, usage);
2906
2907     return E_NOTIMPL;
2908 }
2909
2910 static HRESULT WINAPI IDirect3DDevice9ExImpl_CreateDepthStencilSurfaceEx(IDirect3DDevice9Ex *iface,
2911         UINT width, UINT height, D3DFORMAT format, D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality,
2912         BOOL discard, IDirect3DSurface9 **surface, HANDLE *shared_handle, DWORD usage)
2913 {
2914     FIXME("iface %p, width %u, height %u, format %#x, multisample_type %#x, multisample_quality %u,\n"
2915             "discard %#x, surface %p, shared_handle %p, usage %#x stub!\n",
2916             iface, width, height, format, multisample_type, multisample_quality,
2917             discard, surface, shared_handle, usage);
2918
2919     return E_NOTIMPL;
2920 }
2921
2922 static HRESULT WINAPI IDirect3DDevice9ExImpl_ResetEx(IDirect3DDevice9Ex *iface,
2923         D3DPRESENT_PARAMETERS *present_parameters, D3DDISPLAYMODEEX *mode)
2924 {
2925     FIXME("iface %p, present_parameters %p, mode %p stub!\n", iface, present_parameters, mode);
2926
2927     return E_NOTIMPL;
2928 }
2929
2930 static HRESULT  WINAPI  IDirect3DDevice9ExImpl_GetDisplayModeEx(IDirect3DDevice9Ex *iface,
2931         UINT swapchain_idx, D3DDISPLAYMODEEX *mode, D3DDISPLAYROTATION *rotation)
2932 {
2933     FIXME("iface %p, swapchain_idx %u, mode %p, rotation %p stub!\n", iface, swapchain_idx, mode, rotation);
2934
2935     return E_NOTIMPL;
2936 }
2937
2938 static const IDirect3DDevice9ExVtbl Direct3DDevice9_Vtbl =
2939 {
2940     /* IUnknown */
2941     IDirect3DDevice9Impl_QueryInterface,
2942     IDirect3DDevice9Impl_AddRef,
2943     IDirect3DDevice9Impl_Release,
2944     /* IDirect3DDevice9 */
2945     IDirect3DDevice9Impl_TestCooperativeLevel,
2946     IDirect3DDevice9Impl_GetAvailableTextureMem,
2947     IDirect3DDevice9Impl_EvictManagedResources,
2948     IDirect3DDevice9Impl_GetDirect3D,
2949     IDirect3DDevice9Impl_GetDeviceCaps,
2950     IDirect3DDevice9Impl_GetDisplayMode,
2951     IDirect3DDevice9Impl_GetCreationParameters,
2952     IDirect3DDevice9Impl_SetCursorProperties,
2953     IDirect3DDevice9Impl_SetCursorPosition,
2954     IDirect3DDevice9Impl_ShowCursor,
2955     IDirect3DDevice9Impl_CreateAdditionalSwapChain,
2956     IDirect3DDevice9Impl_GetSwapChain,
2957     IDirect3DDevice9Impl_GetNumberOfSwapChains,
2958     IDirect3DDevice9Impl_Reset,
2959     IDirect3DDevice9Impl_Present,
2960     IDirect3DDevice9Impl_GetBackBuffer,
2961     IDirect3DDevice9Impl_GetRasterStatus,
2962     IDirect3DDevice9Impl_SetDialogBoxMode,
2963     IDirect3DDevice9Impl_SetGammaRamp,
2964     IDirect3DDevice9Impl_GetGammaRamp,
2965     IDirect3DDevice9Impl_CreateTexture,
2966     IDirect3DDevice9Impl_CreateVolumeTexture,
2967     IDirect3DDevice9Impl_CreateCubeTexture,
2968     IDirect3DDevice9Impl_CreateVertexBuffer,
2969     IDirect3DDevice9Impl_CreateIndexBuffer,
2970     IDirect3DDevice9Impl_CreateRenderTarget,
2971     IDirect3DDevice9Impl_CreateDepthStencilSurface,
2972     IDirect3DDevice9Impl_UpdateSurface,
2973     IDirect3DDevice9Impl_UpdateTexture,
2974     IDirect3DDevice9Impl_GetRenderTargetData,
2975     IDirect3DDevice9Impl_GetFrontBufferData,
2976     IDirect3DDevice9Impl_StretchRect,
2977     IDirect3DDevice9Impl_ColorFill,
2978     IDirect3DDevice9Impl_CreateOffscreenPlainSurface,
2979     IDirect3DDevice9Impl_SetRenderTarget,
2980     IDirect3DDevice9Impl_GetRenderTarget,
2981     IDirect3DDevice9Impl_SetDepthStencilSurface,
2982     IDirect3DDevice9Impl_GetDepthStencilSurface,
2983     IDirect3DDevice9Impl_BeginScene,
2984     IDirect3DDevice9Impl_EndScene,
2985     IDirect3DDevice9Impl_Clear,
2986     IDirect3DDevice9Impl_SetTransform,
2987     IDirect3DDevice9Impl_GetTransform,
2988     IDirect3DDevice9Impl_MultiplyTransform,
2989     IDirect3DDevice9Impl_SetViewport,
2990     IDirect3DDevice9Impl_GetViewport,
2991     IDirect3DDevice9Impl_SetMaterial,
2992     IDirect3DDevice9Impl_GetMaterial,
2993     IDirect3DDevice9Impl_SetLight,
2994     IDirect3DDevice9Impl_GetLight,
2995     IDirect3DDevice9Impl_LightEnable,
2996     IDirect3DDevice9Impl_GetLightEnable,
2997     IDirect3DDevice9Impl_SetClipPlane,
2998     IDirect3DDevice9Impl_GetClipPlane,
2999     IDirect3DDevice9Impl_SetRenderState,
3000     IDirect3DDevice9Impl_GetRenderState,
3001     IDirect3DDevice9Impl_CreateStateBlock,
3002     IDirect3DDevice9Impl_BeginStateBlock,
3003     IDirect3DDevice9Impl_EndStateBlock,
3004     IDirect3DDevice9Impl_SetClipStatus,
3005     IDirect3DDevice9Impl_GetClipStatus,
3006     IDirect3DDevice9Impl_GetTexture,
3007     IDirect3DDevice9Impl_SetTexture,
3008     IDirect3DDevice9Impl_GetTextureStageState,
3009     IDirect3DDevice9Impl_SetTextureStageState,
3010     IDirect3DDevice9Impl_GetSamplerState,
3011     IDirect3DDevice9Impl_SetSamplerState,
3012     IDirect3DDevice9Impl_ValidateDevice,
3013     IDirect3DDevice9Impl_SetPaletteEntries,
3014     IDirect3DDevice9Impl_GetPaletteEntries,
3015     IDirect3DDevice9Impl_SetCurrentTexturePalette,
3016     IDirect3DDevice9Impl_GetCurrentTexturePalette,
3017     IDirect3DDevice9Impl_SetScissorRect,
3018     IDirect3DDevice9Impl_GetScissorRect,
3019     IDirect3DDevice9Impl_SetSoftwareVertexProcessing,
3020     IDirect3DDevice9Impl_GetSoftwareVertexProcessing,
3021     IDirect3DDevice9Impl_SetNPatchMode,
3022     IDirect3DDevice9Impl_GetNPatchMode,
3023     IDirect3DDevice9Impl_DrawPrimitive,
3024     IDirect3DDevice9Impl_DrawIndexedPrimitive,
3025     IDirect3DDevice9Impl_DrawPrimitiveUP,
3026     IDirect3DDevice9Impl_DrawIndexedPrimitiveUP,
3027     IDirect3DDevice9Impl_ProcessVertices,
3028     IDirect3DDevice9Impl_CreateVertexDeclaration,
3029     IDirect3DDevice9Impl_SetVertexDeclaration,
3030     IDirect3DDevice9Impl_GetVertexDeclaration,
3031     IDirect3DDevice9Impl_SetFVF,
3032     IDirect3DDevice9Impl_GetFVF,
3033     IDirect3DDevice9Impl_CreateVertexShader,
3034     IDirect3DDevice9Impl_SetVertexShader,
3035     IDirect3DDevice9Impl_GetVertexShader,
3036     IDirect3DDevice9Impl_SetVertexShaderConstantF,
3037     IDirect3DDevice9Impl_GetVertexShaderConstantF,
3038     IDirect3DDevice9Impl_SetVertexShaderConstantI,
3039     IDirect3DDevice9Impl_GetVertexShaderConstantI,
3040     IDirect3DDevice9Impl_SetVertexShaderConstantB,
3041     IDirect3DDevice9Impl_GetVertexShaderConstantB,
3042     IDirect3DDevice9Impl_SetStreamSource,
3043     IDirect3DDevice9Impl_GetStreamSource,
3044     IDirect3DDevice9Impl_SetStreamSourceFreq,
3045     IDirect3DDevice9Impl_GetStreamSourceFreq,
3046     IDirect3DDevice9Impl_SetIndices,
3047     IDirect3DDevice9Impl_GetIndices,
3048     IDirect3DDevice9Impl_CreatePixelShader,
3049     IDirect3DDevice9Impl_SetPixelShader,
3050     IDirect3DDevice9Impl_GetPixelShader,
3051     IDirect3DDevice9Impl_SetPixelShaderConstantF,
3052     IDirect3DDevice9Impl_GetPixelShaderConstantF,
3053     IDirect3DDevice9Impl_SetPixelShaderConstantI,
3054     IDirect3DDevice9Impl_GetPixelShaderConstantI,
3055     IDirect3DDevice9Impl_SetPixelShaderConstantB,
3056     IDirect3DDevice9Impl_GetPixelShaderConstantB,
3057     IDirect3DDevice9Impl_DrawRectPatch,
3058     IDirect3DDevice9Impl_DrawTriPatch,
3059     IDirect3DDevice9Impl_DeletePatch,
3060     IDirect3DDevice9Impl_CreateQuery,
3061     /* IDirect3DDevice9Ex */
3062     IDirect3DDevice9ExImpl_SetConvolutionMonoKernel,
3063     IDirect3DDevice9ExImpl_ComposeRects,
3064     IDirect3DDevice9ExImpl_PresentEx,
3065     IDirect3DDevice9ExImpl_GetGPUThreadPriority,
3066     IDirect3DDevice9ExImpl_SetGPUThreadPriority,
3067     IDirect3DDevice9ExImpl_WaitForVBlank,
3068     IDirect3DDevice9ExImpl_CheckResourceResidency,
3069     IDirect3DDevice9ExImpl_SetMaximumFrameLatency,
3070     IDirect3DDevice9ExImpl_GetMaximumFrameLatency,
3071     IDirect3DDevice9ExImpl_CheckDeviceState,
3072     IDirect3DDevice9ExImpl_CreateRenderTargetEx,
3073     IDirect3DDevice9ExImpl_CreateOffscreenPlainSurfaceEx,
3074     IDirect3DDevice9ExImpl_CreateDepthStencilSurfaceEx,
3075     IDirect3DDevice9ExImpl_ResetEx,
3076     IDirect3DDevice9ExImpl_GetDisplayModeEx
3077 };
3078
3079 static inline struct IDirect3DDevice9Impl *device_from_device_parent(struct wined3d_device_parent *device_parent)
3080 {
3081     return CONTAINING_RECORD(device_parent, struct IDirect3DDevice9Impl, device_parent);
3082 }
3083
3084 static void CDECL device_parent_wined3d_device_created(struct wined3d_device_parent *device_parent,
3085         struct wined3d_device *device)
3086 {
3087     TRACE("device_parent %p, device %p.\n", device_parent, device);
3088 }
3089
3090 static HRESULT CDECL device_parent_create_surface(struct wined3d_device_parent *device_parent,
3091         void *container_parent, UINT width, UINT height, enum wined3d_format_id format, DWORD usage,
3092         WINED3DPOOL pool, UINT level, WINED3DCUBEMAP_FACES face, struct wined3d_surface **surface)
3093 {
3094     struct IDirect3DDevice9Impl *device = device_from_device_parent(device_parent);
3095     IDirect3DSurface9Impl *d3d_surface;
3096     BOOL lockable = TRUE;
3097     HRESULT hr;
3098
3099     TRACE("device_parent %p, container_parent %p, width %u, height %u, format %#x, usage %#x,\n"
3100             "\tpool %#x, level %u, face %u, surface %p.\n",
3101             device_parent, container_parent, width, height, format, usage, pool, level, face, surface);
3102
3103     if (pool == WINED3DPOOL_DEFAULT && !(usage & D3DUSAGE_DYNAMIC))
3104         lockable = FALSE;
3105
3106     hr = IDirect3DDevice9Impl_CreateSurface(device, width, height,
3107             d3dformat_from_wined3dformat(format), lockable, FALSE /* Discard */, level,
3108             (IDirect3DSurface9 **)&d3d_surface, usage, pool, D3DMULTISAMPLE_NONE, 0 /* MultisampleQuality */);
3109     if (FAILED(hr))
3110     {
3111         WARN("Failed to create surface, hr %#x.\n", hr);
3112         return hr;
3113     }
3114
3115     *surface = d3d_surface->wined3d_surface;
3116     wined3d_surface_incref(*surface);
3117
3118     d3d_surface->container = container_parent;
3119     IDirect3DDevice9Ex_Release(d3d_surface->parentDevice);
3120     d3d_surface->parentDevice = NULL;
3121
3122     IDirect3DSurface9_Release(&d3d_surface->IDirect3DSurface9_iface);
3123     d3d_surface->forwardReference = container_parent;
3124
3125     return hr;
3126 }
3127
3128 static HRESULT CDECL device_parent_create_rendertarget(struct wined3d_device_parent *device_parent,
3129         void *container_parent, UINT width, UINT height, enum wined3d_format_id format,
3130         WINED3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality, BOOL lockable,
3131         struct wined3d_surface **surface)
3132 {
3133     struct IDirect3DDevice9Impl *device = device_from_device_parent(device_parent);
3134     IDirect3DSurface9Impl *d3d_surface;
3135     HRESULT hr;
3136
3137     TRACE("device_parent %p, container_parent %p, width %u, height %u, format %#x, multisample_type %#x,\n"
3138             "\tmultisample_quality %u, lockable %u, surface %p.\n",
3139             device_parent, container_parent, width, height, format, multisample_type,
3140             multisample_quality, lockable, surface);
3141
3142     hr = IDirect3DDevice9Impl_CreateRenderTarget(&device->IDirect3DDevice9Ex_iface, width, height,
3143             d3dformat_from_wined3dformat(format), multisample_type, multisample_quality, lockable,
3144             (IDirect3DSurface9 **)&d3d_surface, NULL);
3145     if (FAILED(hr))
3146     {
3147         WARN("Failed to create rendertarget, hr %#x.\n", hr);
3148         return hr;
3149     }
3150
3151     *surface = d3d_surface->wined3d_surface;
3152     wined3d_surface_incref(*surface);
3153
3154     d3d_surface->container = container_parent;
3155     /* Implicit surfaces are created with an refcount of 0 */
3156     IDirect3DSurface9_Release(&d3d_surface->IDirect3DSurface9_iface);
3157
3158     return hr;
3159 }
3160
3161 static HRESULT CDECL device_parent_create_depth_stencil(struct wined3d_device_parent *device_parent,
3162         UINT width, UINT height, enum wined3d_format_id format, WINED3DMULTISAMPLE_TYPE multisample_type,
3163         DWORD multisample_quality, BOOL discard, struct wined3d_surface **surface)
3164 {
3165     struct IDirect3DDevice9Impl *device = device_from_device_parent(device_parent);
3166     IDirect3DSurface9Impl *d3d_surface;
3167     HRESULT hr;
3168
3169     TRACE("device_parent %p, width %u, height %u, format %#x, multisample_type %#x,\n"
3170             "\tmultisample_quality %u, discard %u, surface %p.\n",
3171             device_parent, width, height, format, multisample_type, multisample_quality, discard, surface);
3172
3173     hr = IDirect3DDevice9Impl_CreateDepthStencilSurface(&device->IDirect3DDevice9Ex_iface, width,
3174             height, d3dformat_from_wined3dformat(format), multisample_type, multisample_quality,
3175             discard, (IDirect3DSurface9 **)&d3d_surface, NULL);
3176     if (FAILED(hr))
3177     {
3178         WARN("Failed to create depth/stencil surface, hr %#x.\n", hr);
3179         return hr;
3180     }
3181
3182     *surface = d3d_surface->wined3d_surface;
3183     wined3d_surface_incref(*surface);
3184     d3d_surface->container = (IUnknown *)&device->IDirect3DDevice9Ex_iface;
3185     /* Implicit surfaces are created with an refcount of 0 */
3186     IDirect3DSurface9_Release(&d3d_surface->IDirect3DSurface9_iface);
3187
3188     return hr;
3189 }
3190
3191 static HRESULT CDECL device_parent_create_volume(struct wined3d_device_parent *device_parent,
3192         void *container_parent, UINT width, UINT height, UINT depth, enum wined3d_format_id format,
3193         WINED3DPOOL pool, DWORD usage, struct wined3d_volume **volume)
3194 {
3195     struct IDirect3DDevice9Impl *device = device_from_device_parent(device_parent);
3196     IDirect3DVolume9Impl *object;
3197     HRESULT hr;
3198
3199     TRACE("device_parent %p, container_parent %p, width %u, height %u, depth %u, "
3200             "format %#x, pool %#x, usage %#x, volume %p\n",
3201             device_parent, container_parent, width, height, depth,
3202             format, pool, usage, volume);
3203
3204     /* Allocate the storage for the device */
3205     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
3206     if (!object)
3207     {
3208         FIXME("Allocation of memory failed\n");
3209         *volume = NULL;
3210         return D3DERR_OUTOFVIDEOMEMORY;
3211     }
3212
3213     hr = volume_init(object, device, width, height, depth, usage, format, pool);
3214     if (FAILED(hr))
3215     {
3216         WARN("Failed to initialize volume, hr %#x.\n", hr);
3217         HeapFree(GetProcessHeap(), 0, object);
3218         return hr;
3219     }
3220
3221     *volume = object->wined3d_volume;
3222     wined3d_volume_incref(*volume);
3223     IDirect3DVolume9_Release(&object->IDirect3DVolume9_iface);
3224
3225     object->container = container_parent;
3226     object->forwardReference = container_parent;
3227
3228     TRACE("Created volume %p.\n", object);
3229
3230     return hr;
3231 }
3232
3233 static HRESULT CDECL device_parent_create_swapchain(struct wined3d_device_parent *device_parent,
3234         WINED3DPRESENT_PARAMETERS *present_parameters, struct wined3d_swapchain **swapchain)
3235 {
3236     struct IDirect3DDevice9Impl *device = device_from_device_parent(device_parent);
3237     D3DPRESENT_PARAMETERS local_parameters;
3238     IDirect3DSwapChain9 *d3d_swapchain;
3239     HRESULT hr;
3240
3241     TRACE("device_parent %p, present_parameters %p, swapchain %p\n", device_parent, present_parameters, swapchain);
3242
3243     /* Copy the presentation parameters */
3244     local_parameters.BackBufferWidth = present_parameters->BackBufferWidth;
3245     local_parameters.BackBufferHeight = present_parameters->BackBufferHeight;
3246     local_parameters.BackBufferFormat = d3dformat_from_wined3dformat(present_parameters->BackBufferFormat);
3247     local_parameters.BackBufferCount = present_parameters->BackBufferCount;
3248     local_parameters.MultiSampleType = present_parameters->MultiSampleType;
3249     local_parameters.MultiSampleQuality = present_parameters->MultiSampleQuality;
3250     local_parameters.SwapEffect = present_parameters->SwapEffect;
3251     local_parameters.hDeviceWindow = present_parameters->hDeviceWindow;
3252     local_parameters.Windowed = present_parameters->Windowed;
3253     local_parameters.EnableAutoDepthStencil = present_parameters->EnableAutoDepthStencil;
3254     local_parameters.AutoDepthStencilFormat = d3dformat_from_wined3dformat(present_parameters->AutoDepthStencilFormat);
3255     local_parameters.Flags = present_parameters->Flags;
3256     local_parameters.FullScreen_RefreshRateInHz = present_parameters->FullScreen_RefreshRateInHz;
3257     local_parameters.PresentationInterval = present_parameters->PresentationInterval;
3258
3259     hr = IDirect3DDevice9Impl_CreateAdditionalSwapChain(&device->IDirect3DDevice9Ex_iface,
3260             &local_parameters, &d3d_swapchain);
3261     if (FAILED(hr))
3262     {
3263         WARN("Failed to create swapchain, hr %#x.\n", hr);
3264         *swapchain = NULL;
3265         return hr;
3266     }
3267
3268     *swapchain = ((IDirect3DSwapChain9Impl *)d3d_swapchain)->wined3d_swapchain;
3269     wined3d_swapchain_incref(*swapchain);
3270     IDirect3DSwapChain9_Release((IDirect3DSwapChain9 *)d3d_swapchain);
3271
3272     /* Copy back the presentation parameters */
3273     present_parameters->BackBufferWidth = local_parameters.BackBufferWidth;
3274     present_parameters->BackBufferHeight = local_parameters.BackBufferHeight;
3275     present_parameters->BackBufferFormat = wined3dformat_from_d3dformat(local_parameters.BackBufferFormat);
3276     present_parameters->BackBufferCount = local_parameters.BackBufferCount;
3277     present_parameters->MultiSampleType = local_parameters.MultiSampleType;
3278     present_parameters->MultiSampleQuality = local_parameters.MultiSampleQuality;
3279     present_parameters->SwapEffect = local_parameters.SwapEffect;
3280     present_parameters->hDeviceWindow = local_parameters.hDeviceWindow;
3281     present_parameters->Windowed = local_parameters.Windowed;
3282     present_parameters->EnableAutoDepthStencil = local_parameters.EnableAutoDepthStencil;
3283     present_parameters->AutoDepthStencilFormat = wined3dformat_from_d3dformat(local_parameters.AutoDepthStencilFormat);
3284     present_parameters->Flags = local_parameters.Flags;
3285     present_parameters->FullScreen_RefreshRateInHz = local_parameters.FullScreen_RefreshRateInHz;
3286     present_parameters->PresentationInterval = local_parameters.PresentationInterval;
3287
3288     return hr;
3289 }
3290
3291 static const struct wined3d_device_parent_ops d3d9_wined3d_device_parent_ops =
3292 {
3293     device_parent_wined3d_device_created,
3294     device_parent_create_surface,
3295     device_parent_create_rendertarget,
3296     device_parent_create_depth_stencil,
3297     device_parent_create_volume,
3298     device_parent_create_swapchain,
3299 };
3300
3301 static void setup_fpu(void)
3302 {
3303 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3304     WORD cw;
3305     __asm__ volatile ("fnstcw %0" : "=m" (cw));
3306     cw = (cw & ~0xf3f) | 0x3f;
3307     __asm__ volatile ("fldcw %0" : : "m" (cw));
3308 #else
3309     FIXME("FPU setup not implemented for this platform.\n");
3310 #endif
3311 }
3312
3313 HRESULT device_init(IDirect3DDevice9Impl *device, IDirect3D9Impl *parent, struct wined3d *wined3d, UINT adapter, D3DDEVTYPE device_type,
3314         HWND focus_window, DWORD flags, D3DPRESENT_PARAMETERS *parameters, D3DDISPLAYMODEEX *mode)
3315 {
3316     WINED3DPRESENT_PARAMETERS *wined3d_parameters;
3317     UINT i, count = 1;
3318     HRESULT hr;
3319
3320     if (mode)
3321         FIXME("Ignoring display mode.\n");
3322
3323     device->IDirect3DDevice9Ex_iface.lpVtbl = &Direct3DDevice9_Vtbl;
3324     device->device_parent.ops = &d3d9_wined3d_device_parent_ops;
3325     device->ref = 1;
3326
3327     if (!(flags & D3DCREATE_FPU_PRESERVE)) setup_fpu();
3328
3329     wined3d_mutex_lock();
3330     hr = wined3d_device_create(wined3d, adapter, device_type, focus_window, flags, 4,
3331             &device->device_parent, &device->wined3d_device);
3332     if (FAILED(hr))
3333     {
3334         WARN("Failed to create wined3d device, hr %#x.\n", hr);
3335         wined3d_mutex_unlock();
3336         return hr;
3337     }
3338
3339     if (flags & D3DCREATE_ADAPTERGROUP_DEVICE)
3340     {
3341         WINED3DCAPS caps;
3342
3343         wined3d_get_device_caps(wined3d, adapter, device_type, &caps);
3344         count = caps.NumberOfAdaptersInGroup;
3345     }
3346
3347     if (flags & D3DCREATE_MULTITHREADED)
3348         wined3d_device_set_multithreaded(device->wined3d_device);
3349
3350     if (!parameters->Windowed)
3351     {
3352         if (!focus_window)
3353             focus_window = parameters->hDeviceWindow;
3354         if (FAILED(hr = wined3d_device_acquire_focus_window(device->wined3d_device, focus_window)))
3355         {
3356             ERR("Failed to acquire focus window, hr %#x.\n", hr);
3357             wined3d_device_decref(device->wined3d_device);
3358             wined3d_mutex_unlock();
3359             return hr;
3360         }
3361
3362         for (i = 0; i < count; ++i)
3363         {
3364             HWND device_window = parameters[i].hDeviceWindow;
3365
3366             if (!device_window) device_window = focus_window;
3367             wined3d_device_setup_fullscreen_window(device->wined3d_device, device_window,
3368                     parameters[i].BackBufferWidth,
3369                     parameters[i].BackBufferHeight);
3370         }
3371     }
3372
3373     wined3d_parameters = HeapAlloc(GetProcessHeap(), 0, sizeof(*wined3d_parameters) * count);
3374     if (!wined3d_parameters)
3375     {
3376         ERR("Failed to allocate wined3d parameters.\n");
3377         wined3d_device_decref(device->wined3d_device);
3378         wined3d_mutex_unlock();
3379         return E_OUTOFMEMORY;
3380     }
3381
3382     for (i = 0; i < count; ++i)
3383     {
3384         wined3d_parameters[i].BackBufferWidth = parameters[i].BackBufferWidth;
3385         wined3d_parameters[i].BackBufferHeight = parameters[i].BackBufferHeight;
3386         wined3d_parameters[i].BackBufferFormat = wined3dformat_from_d3dformat(parameters[i].BackBufferFormat);
3387         wined3d_parameters[i].BackBufferCount = parameters[i].BackBufferCount;
3388         wined3d_parameters[i].MultiSampleType = parameters[i].MultiSampleType;
3389         wined3d_parameters[i].MultiSampleQuality = parameters[i].MultiSampleQuality;
3390         wined3d_parameters[i].SwapEffect = parameters[i].SwapEffect;
3391         wined3d_parameters[i].hDeviceWindow = parameters[i].hDeviceWindow;
3392         wined3d_parameters[i].Windowed = parameters[i].Windowed;
3393         wined3d_parameters[i].EnableAutoDepthStencil = parameters[i].EnableAutoDepthStencil;
3394         wined3d_parameters[i].AutoDepthStencilFormat =
3395                 wined3dformat_from_d3dformat(parameters[i].AutoDepthStencilFormat);
3396         wined3d_parameters[i].Flags = parameters[i].Flags;
3397         wined3d_parameters[i].FullScreen_RefreshRateInHz = parameters[i].FullScreen_RefreshRateInHz;
3398         wined3d_parameters[i].PresentationInterval = parameters[i].PresentationInterval;
3399         wined3d_parameters[i].AutoRestoreDisplayMode = TRUE;
3400     }
3401
3402     hr = wined3d_device_init_3d(device->wined3d_device, wined3d_parameters);
3403     if (FAILED(hr))
3404     {
3405         WARN("Failed to initialize 3D, hr %#x.\n", hr);
3406         wined3d_device_release_focus_window(device->wined3d_device);
3407         HeapFree(GetProcessHeap(), 0, wined3d_parameters);
3408         wined3d_device_decref(device->wined3d_device);
3409         wined3d_mutex_unlock();
3410         return hr;
3411     }
3412
3413     wined3d_mutex_unlock();
3414
3415     for (i = 0; i < count; ++i)
3416     {
3417         parameters[i].BackBufferWidth = wined3d_parameters[i].BackBufferWidth;
3418         parameters[i].BackBufferHeight = wined3d_parameters[i].BackBufferHeight;
3419         parameters[i].BackBufferFormat = d3dformat_from_wined3dformat(wined3d_parameters[i].BackBufferFormat);
3420         parameters[i].BackBufferCount = wined3d_parameters[i].BackBufferCount;
3421         parameters[i].MultiSampleType = wined3d_parameters[i].MultiSampleType;
3422         parameters[i].MultiSampleQuality = wined3d_parameters[i].MultiSampleQuality;
3423         parameters[i].SwapEffect = wined3d_parameters[i].SwapEffect;
3424         parameters[i].hDeviceWindow = wined3d_parameters[i].hDeviceWindow;
3425         parameters[i].Windowed = wined3d_parameters[i].Windowed;
3426         parameters[i].EnableAutoDepthStencil = wined3d_parameters[i].EnableAutoDepthStencil;
3427         parameters[i].AutoDepthStencilFormat =
3428                 d3dformat_from_wined3dformat(wined3d_parameters[i].AutoDepthStencilFormat);
3429         parameters[i].Flags = wined3d_parameters[i].Flags;
3430         parameters[i].FullScreen_RefreshRateInHz = wined3d_parameters[i].FullScreen_RefreshRateInHz;
3431         parameters[i].PresentationInterval = wined3d_parameters[i].PresentationInterval;
3432     }
3433     HeapFree(GetProcessHeap(), 0, wined3d_parameters);
3434
3435     /* Initialize the converted declaration array. This creates a valid pointer
3436      * and when adding decls HeapReAlloc() can be used without further checking. */
3437     device->convertedDecls = HeapAlloc(GetProcessHeap(), 0, 0);
3438     if (!device->convertedDecls)
3439     {
3440         ERR("Failed to allocate FVF vertex declaration map memory.\n");
3441         wined3d_mutex_lock();
3442         wined3d_device_uninit_3d(device->wined3d_device);
3443         wined3d_device_release_focus_window(device->wined3d_device);
3444         wined3d_device_decref(device->wined3d_device);
3445         wined3d_mutex_unlock();
3446         return E_OUTOFMEMORY;
3447     }
3448
3449     device->d3d_parent = &parent->IDirect3D9Ex_iface;
3450     IDirect3D9_AddRef(device->d3d_parent);
3451
3452     return D3D_OK;
3453 }