wined3d: Make the context parameter to the get_drawable_size() callback const.
[wine] / dlls / d3d8 / device.c
1 /*
2  * IDirect3DDevice8 implementation
3  *
4  * Copyright 2002-2004 Jason Edmeades
5  * Copyright 2004 Christian Costa
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include "config.h"
23
24 #include <math.h>
25 #include <stdarg.h>
26
27 #define NONAMELESSUNION
28 #define NONAMELESSSTRUCT
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winuser.h"
32 #include "wingdi.h"
33 #include "wine/debug.h"
34
35 #include "d3d8_private.h"
36
37 WINE_DEFAULT_DEBUG_CHANNEL(d3d8);
38
39 D3DFORMAT d3dformat_from_wined3dformat(enum wined3d_format_id format)
40 {
41     BYTE *c = (BYTE *)&format;
42
43     /* Don't translate FOURCC formats */
44     if (isprint(c[0]) && isprint(c[1]) && isprint(c[2]) && isprint(c[3])) return format;
45
46     switch(format)
47     {
48         case WINED3DFMT_UNKNOWN: return D3DFMT_UNKNOWN;
49         case WINED3DFMT_B8G8R8_UNORM: return D3DFMT_R8G8B8;
50         case WINED3DFMT_B8G8R8A8_UNORM: return D3DFMT_A8R8G8B8;
51         case WINED3DFMT_B8G8R8X8_UNORM: return D3DFMT_X8R8G8B8;
52         case WINED3DFMT_B5G6R5_UNORM: return D3DFMT_R5G6B5;
53         case WINED3DFMT_B5G5R5X1_UNORM: return D3DFMT_X1R5G5B5;
54         case WINED3DFMT_B5G5R5A1_UNORM: return D3DFMT_A1R5G5B5;
55         case WINED3DFMT_B4G4R4A4_UNORM: return D3DFMT_A4R4G4B4;
56         case WINED3DFMT_B2G3R3_UNORM: return D3DFMT_R3G3B2;
57         case WINED3DFMT_A8_UNORM: return D3DFMT_A8;
58         case WINED3DFMT_B2G3R3A8_UNORM: return D3DFMT_A8R3G3B2;
59         case WINED3DFMT_B4G4R4X4_UNORM: return D3DFMT_X4R4G4B4;
60         case WINED3DFMT_R10G10B10A2_UNORM: return D3DFMT_A2B10G10R10;
61         case WINED3DFMT_R16G16_UNORM: return D3DFMT_G16R16;
62         case WINED3DFMT_P8_UINT_A8_UNORM: return D3DFMT_A8P8;
63         case WINED3DFMT_P8_UINT: return D3DFMT_P8;
64         case WINED3DFMT_L8_UNORM: return D3DFMT_L8;
65         case WINED3DFMT_L8A8_UNORM: return D3DFMT_A8L8;
66         case WINED3DFMT_L4A4_UNORM: return D3DFMT_A4L4;
67         case WINED3DFMT_R8G8_SNORM: return D3DFMT_V8U8;
68         case WINED3DFMT_R5G5_SNORM_L6_UNORM: return D3DFMT_L6V5U5;
69         case WINED3DFMT_R8G8_SNORM_L8X8_UNORM: return D3DFMT_X8L8V8U8;
70         case WINED3DFMT_R8G8B8A8_SNORM: return D3DFMT_Q8W8V8U8;
71         case WINED3DFMT_R16G16_SNORM: return D3DFMT_V16U16;
72         case WINED3DFMT_R10G11B11_SNORM: return D3DFMT_W11V11U10;
73         case WINED3DFMT_R10G10B10_SNORM_A2_UNORM: return D3DFMT_A2W10V10U10;
74         case WINED3DFMT_D16_LOCKABLE: return D3DFMT_D16_LOCKABLE;
75         case WINED3DFMT_D32_UNORM: return D3DFMT_D32;
76         case WINED3DFMT_S1_UINT_D15_UNORM: return D3DFMT_D15S1;
77         case WINED3DFMT_D24_UNORM_S8_UINT: return D3DFMT_D24S8;
78         case WINED3DFMT_X8D24_UNORM: return D3DFMT_D24X8;
79         case WINED3DFMT_S4X4_UINT_D24_UNORM: return D3DFMT_D24X4S4;
80         case WINED3DFMT_D16_UNORM: return D3DFMT_D16;
81         case WINED3DFMT_VERTEXDATA: return D3DFMT_VERTEXDATA;
82         case WINED3DFMT_R16_UINT: return D3DFMT_INDEX16;
83         case WINED3DFMT_R32_UINT: return D3DFMT_INDEX32;
84         default:
85             FIXME("Unhandled wined3d format %#x.\n", format);
86             return D3DFMT_UNKNOWN;
87     }
88 }
89
90 enum wined3d_format_id wined3dformat_from_d3dformat(D3DFORMAT format)
91 {
92     BYTE *c = (BYTE *)&format;
93
94     /* Don't translate FOURCC formats */
95     if (isprint(c[0]) && isprint(c[1]) && isprint(c[2]) && isprint(c[3])) return format;
96
97     switch(format)
98     {
99         case D3DFMT_UNKNOWN: return WINED3DFMT_UNKNOWN;
100         case D3DFMT_R8G8B8: return WINED3DFMT_B8G8R8_UNORM;
101         case D3DFMT_A8R8G8B8: return WINED3DFMT_B8G8R8A8_UNORM;
102         case D3DFMT_X8R8G8B8: return WINED3DFMT_B8G8R8X8_UNORM;
103         case D3DFMT_R5G6B5: return WINED3DFMT_B5G6R5_UNORM;
104         case D3DFMT_X1R5G5B5: return WINED3DFMT_B5G5R5X1_UNORM;
105         case D3DFMT_A1R5G5B5: return WINED3DFMT_B5G5R5A1_UNORM;
106         case D3DFMT_A4R4G4B4: return WINED3DFMT_B4G4R4A4_UNORM;
107         case D3DFMT_R3G3B2: return WINED3DFMT_B2G3R3_UNORM;
108         case D3DFMT_A8: return WINED3DFMT_A8_UNORM;
109         case D3DFMT_A8R3G3B2: return WINED3DFMT_B2G3R3A8_UNORM;
110         case D3DFMT_X4R4G4B4: return WINED3DFMT_B4G4R4X4_UNORM;
111         case D3DFMT_A2B10G10R10: return WINED3DFMT_R10G10B10A2_UNORM;
112         case D3DFMT_G16R16: return WINED3DFMT_R16G16_UNORM;
113         case D3DFMT_A8P8: return WINED3DFMT_P8_UINT_A8_UNORM;
114         case D3DFMT_P8: return WINED3DFMT_P8_UINT;
115         case D3DFMT_L8: return WINED3DFMT_L8_UNORM;
116         case D3DFMT_A8L8: return WINED3DFMT_L8A8_UNORM;
117         case D3DFMT_A4L4: return WINED3DFMT_L4A4_UNORM;
118         case D3DFMT_V8U8: return WINED3DFMT_R8G8_SNORM;
119         case D3DFMT_L6V5U5: return WINED3DFMT_R5G5_SNORM_L6_UNORM;
120         case D3DFMT_X8L8V8U8: return WINED3DFMT_R8G8_SNORM_L8X8_UNORM;
121         case D3DFMT_Q8W8V8U8: return WINED3DFMT_R8G8B8A8_SNORM;
122         case D3DFMT_V16U16: return WINED3DFMT_R16G16_SNORM;
123         case D3DFMT_W11V11U10: return WINED3DFMT_R10G11B11_SNORM;
124         case D3DFMT_A2W10V10U10: return WINED3DFMT_R10G10B10_SNORM_A2_UNORM;
125         case D3DFMT_D16_LOCKABLE: return WINED3DFMT_D16_LOCKABLE;
126         case D3DFMT_D32: return WINED3DFMT_D32_UNORM;
127         case D3DFMT_D15S1: return WINED3DFMT_S1_UINT_D15_UNORM;
128         case D3DFMT_D24S8: return WINED3DFMT_D24_UNORM_S8_UINT;
129         case D3DFMT_D24X8: return WINED3DFMT_X8D24_UNORM;
130         case D3DFMT_D24X4S4: return WINED3DFMT_S4X4_UINT_D24_UNORM;
131         case D3DFMT_D16: return WINED3DFMT_D16_UNORM;
132         case D3DFMT_VERTEXDATA: return WINED3DFMT_VERTEXDATA;
133         case D3DFMT_INDEX16: return WINED3DFMT_R16_UINT;
134         case D3DFMT_INDEX32: return WINED3DFMT_R32_UINT;
135         default:
136             FIXME("Unhandled D3DFORMAT %#x\n", format);
137             return WINED3DFMT_UNKNOWN;
138     }
139 }
140
141 static UINT vertex_count_from_primitive_count(D3DPRIMITIVETYPE primitive_type, UINT primitive_count)
142 {
143     switch(primitive_type)
144     {
145         case D3DPT_POINTLIST:
146             return primitive_count;
147
148         case D3DPT_LINELIST:
149             return primitive_count * 2;
150
151         case D3DPT_LINESTRIP:
152             return primitive_count + 1;
153
154         case D3DPT_TRIANGLELIST:
155             return primitive_count * 3;
156
157         case D3DPT_TRIANGLESTRIP:
158         case D3DPT_TRIANGLEFAN:
159             return primitive_count + 2;
160
161         default:
162             FIXME("Unhandled primitive type %#x\n", primitive_type);
163             return 0;
164     }
165 }
166
167 /* Handle table functions */
168 static DWORD d3d8_allocate_handle(struct d3d8_handle_table *t, void *object, enum d3d8_handle_type type)
169 {
170     struct d3d8_handle_entry *entry;
171
172     if (t->free_entries)
173     {
174         DWORD index = t->free_entries - t->entries;
175         /* Use a free handle */
176         entry = t->free_entries;
177         if (entry->type != D3D8_HANDLE_FREE)
178         {
179             ERR("Handle %u(%p) is in the free list, but has type %#x.\n", index, entry, entry->type);
180             return D3D8_INVALID_HANDLE;
181         }
182         t->free_entries = entry->object;
183         entry->object = object;
184         entry->type = type;
185
186         return index;
187     }
188
189     if (!(t->entry_count < t->table_size))
190     {
191         /* Grow the table */
192         UINT new_size = t->table_size + (t->table_size >> 1);
193         struct d3d8_handle_entry *new_entries = HeapReAlloc(GetProcessHeap(),
194                 0, t->entries, new_size * sizeof(*t->entries));
195         if (!new_entries)
196         {
197             ERR("Failed to grow the handle table.\n");
198             return D3D8_INVALID_HANDLE;
199         }
200         t->entries = new_entries;
201         t->table_size = new_size;
202     }
203
204     entry = &t->entries[t->entry_count];
205     entry->object = object;
206     entry->type = type;
207
208     return t->entry_count++;
209 }
210
211 static void *d3d8_free_handle(struct d3d8_handle_table *t, DWORD handle, enum d3d8_handle_type type)
212 {
213     struct d3d8_handle_entry *entry;
214     void *object;
215
216     if (handle == D3D8_INVALID_HANDLE || handle >= t->entry_count)
217     {
218         WARN("Invalid handle %u passed.\n", handle);
219         return NULL;
220     }
221
222     entry = &t->entries[handle];
223     if (entry->type != type)
224     {
225         WARN("Handle %u(%p) is not of type %#x.\n", handle, entry, type);
226         return NULL;
227     }
228
229     object = entry->object;
230     entry->object = t->free_entries;
231     entry->type = D3D8_HANDLE_FREE;
232     t->free_entries = entry;
233
234     return object;
235 }
236
237 static void *d3d8_get_object(struct d3d8_handle_table *t, DWORD handle, enum d3d8_handle_type type)
238 {
239     struct d3d8_handle_entry *entry;
240
241     if (handle == D3D8_INVALID_HANDLE || handle >= t->entry_count)
242     {
243         WARN("Invalid handle %u passed.\n", handle);
244         return NULL;
245     }
246
247     entry = &t->entries[handle];
248     if (entry->type != type)
249     {
250         WARN("Handle %u(%p) is not of type %#x.\n", handle, entry, type);
251         return NULL;
252     }
253
254     return entry->object;
255 }
256
257 static inline IDirect3DDevice8Impl *impl_from_IDirect3DDevice8(IDirect3DDevice8 *iface)
258 {
259     return CONTAINING_RECORD(iface, IDirect3DDevice8Impl, IDirect3DDevice8_iface);
260 }
261
262 static HRESULT WINAPI IDirect3DDevice8Impl_QueryInterface(IDirect3DDevice8 *iface, REFIID riid,
263         void **ppobj)
264 {
265     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
266
267     TRACE("iface %p, riid %s, object %p.\n",
268             iface, debugstr_guid(riid), ppobj);
269
270     if (IsEqualGUID(riid, &IID_IUnknown)
271         || IsEqualGUID(riid, &IID_IDirect3DDevice8)) {
272         IUnknown_AddRef(iface);
273         *ppobj = This;
274         return S_OK;
275     }
276
277     WARN("(%p)->(%s,%p),not found\n", This, debugstr_guid(riid), ppobj);
278     *ppobj = NULL;
279     return E_NOINTERFACE;
280 }
281
282 static ULONG WINAPI IDirect3DDevice8Impl_AddRef(IDirect3DDevice8 *iface)
283 {
284     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
285     ULONG ref = InterlockedIncrement(&This->ref);
286
287     TRACE("%p increasing refcount to %u.\n", iface, ref);
288
289     return ref;
290 }
291
292 static ULONG WINAPI IDirect3DDevice8Impl_Release(IDirect3DDevice8 *iface)
293 {
294     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
295     ULONG ref;
296
297     if (This->inDestruction) return 0;
298     ref = InterlockedDecrement(&This->ref);
299
300     TRACE("%p decreasing refcount to %u.\n", iface, ref);
301
302     if (ref == 0) {
303         unsigned i;
304         IDirect3D8 *parent = This->d3d_parent;
305
306         TRACE("Releasing wined3d device %p.\n", This->wined3d_device);
307
308         wined3d_mutex_lock();
309
310         This->inDestruction = TRUE;
311
312         for(i = 0; i < This->numConvertedDecls; i++) {
313             IDirect3DVertexDeclaration8_Release(This->decls[i].decl);
314         }
315         HeapFree(GetProcessHeap(), 0, This->decls);
316
317         wined3d_device_uninit_3d(This->wined3d_device);
318         wined3d_device_release_focus_window(This->wined3d_device);
319         wined3d_device_decref(This->wined3d_device);
320         HeapFree(GetProcessHeap(), 0, This->handle_table.entries);
321         HeapFree(GetProcessHeap(), 0, This);
322
323         wined3d_mutex_unlock();
324
325         IDirect3D8_Release(parent);
326     }
327     return ref;
328 }
329
330 /* IDirect3DDevice Interface follow: */
331 static HRESULT WINAPI IDirect3DDevice8Impl_TestCooperativeLevel(IDirect3DDevice8 *iface)
332 {
333     IDirect3DDevice8Impl *device = impl_from_IDirect3DDevice8(iface);
334
335     TRACE("iface %p.\n", iface);
336
337     if (device->lost)
338     {
339         TRACE("Device is lost.\n");
340         return D3DERR_DEVICENOTRESET;
341     }
342
343     return D3D_OK;
344 }
345
346 static UINT WINAPI  IDirect3DDevice8Impl_GetAvailableTextureMem(IDirect3DDevice8 *iface)
347 {
348     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
349     HRESULT hr;
350
351     TRACE("iface %p.\n", iface);
352
353     wined3d_mutex_lock();
354     hr = wined3d_device_get_available_texture_mem(This->wined3d_device);
355     wined3d_mutex_unlock();
356
357     return hr;
358 }
359
360 static HRESULT WINAPI IDirect3DDevice8Impl_ResourceManagerDiscardBytes(IDirect3DDevice8 *iface,
361         DWORD Bytes)
362 {
363     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
364     HRESULT hr;
365
366     TRACE("iface %p, byte_count %u.\n", iface, Bytes);
367     if (Bytes) FIXME("Byte count ignored.\n");
368
369     wined3d_mutex_lock();
370     hr = wined3d_device_evict_managed_resources(This->wined3d_device);
371     wined3d_mutex_unlock();
372
373     return hr;
374 }
375
376 static HRESULT WINAPI IDirect3DDevice8Impl_GetDirect3D(IDirect3DDevice8 *iface, IDirect3D8 **ppD3D8)
377 {
378     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
379
380     TRACE("iface %p, d3d8 %p.\n", iface, ppD3D8);
381
382     if (NULL == ppD3D8) {
383         return D3DERR_INVALIDCALL;
384     }
385
386     return IDirect3D8_QueryInterface(This->d3d_parent, &IID_IDirect3D8, (void **)ppD3D8);
387 }
388
389 static HRESULT WINAPI IDirect3DDevice8Impl_GetDeviceCaps(IDirect3DDevice8 *iface, D3DCAPS8 *pCaps)
390 {
391     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
392     HRESULT hrc = D3D_OK;
393     WINED3DCAPS *pWineCaps;
394
395     TRACE("iface %p, caps %p.\n", iface, pCaps);
396
397     if(NULL == pCaps){
398         return D3DERR_INVALIDCALL;
399     }
400     pWineCaps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WINED3DCAPS));
401     if(pWineCaps == NULL){
402         return D3DERR_INVALIDCALL; /* well this is what MSDN says to return */
403     }
404
405     wined3d_mutex_lock();
406     hrc = wined3d_device_get_device_caps(This->wined3d_device, pWineCaps);
407     wined3d_mutex_unlock();
408
409     fixup_caps(pWineCaps);
410     WINECAPSTOD3D8CAPS(pCaps, pWineCaps)
411     HeapFree(GetProcessHeap(), 0, pWineCaps);
412
413     TRACE("Returning %p %p\n", This, pCaps);
414     return hrc;
415 }
416
417 static HRESULT WINAPI IDirect3DDevice8Impl_GetDisplayMode(IDirect3DDevice8 *iface,
418         D3DDISPLAYMODE *pMode)
419 {
420     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
421     HRESULT hr;
422
423     TRACE("iface %p, mode %p.\n", iface, pMode);
424
425     wined3d_mutex_lock();
426     hr = wined3d_device_get_display_mode(This->wined3d_device, 0, (WINED3DDISPLAYMODE *)pMode);
427     wined3d_mutex_unlock();
428
429     if (SUCCEEDED(hr)) pMode->Format = d3dformat_from_wined3dformat(pMode->Format);
430
431     return hr;
432 }
433
434 static HRESULT WINAPI IDirect3DDevice8Impl_GetCreationParameters(IDirect3DDevice8 *iface,
435         D3DDEVICE_CREATION_PARAMETERS *pParameters)
436 {
437     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
438     HRESULT hr;
439
440     TRACE("iface %p, parameters %p.\n", iface, pParameters);
441
442     wined3d_mutex_lock();
443     hr = wined3d_device_get_creation_parameters(This->wined3d_device,
444             (WINED3DDEVICE_CREATION_PARAMETERS *)pParameters);
445     wined3d_mutex_unlock();
446
447     return hr;
448 }
449
450 static HRESULT WINAPI IDirect3DDevice8Impl_SetCursorProperties(IDirect3DDevice8 *iface,
451         UINT XHotSpot, UINT YHotSpot, IDirect3DSurface8 *pCursorBitmap)
452 {
453     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
454     IDirect3DSurface8Impl *pSurface = unsafe_impl_from_IDirect3DSurface8(pCursorBitmap);
455     HRESULT hr;
456
457     TRACE("iface %p, hotspot_x %u, hotspot_y %u, bitmap %p.\n",
458             iface, XHotSpot, YHotSpot, pCursorBitmap);
459
460     if (!pCursorBitmap)
461     {
462         WARN("No cursor bitmap, returning D3DERR_INVALIDCALL.\n");
463         return D3DERR_INVALIDCALL;
464     }
465
466     wined3d_mutex_lock();
467     hr = wined3d_device_set_cursor_properties(This->wined3d_device, XHotSpot, YHotSpot, pSurface->wined3d_surface);
468     wined3d_mutex_unlock();
469
470     return hr;
471 }
472
473 static void WINAPI IDirect3DDevice8Impl_SetCursorPosition(IDirect3DDevice8 *iface,
474         UINT XScreenSpace, UINT YScreenSpace, DWORD Flags)
475 {
476     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
477
478     TRACE("iface %p, x %u, y %u, flags %#x.\n",
479             iface, XScreenSpace, YScreenSpace, Flags);
480
481     wined3d_mutex_lock();
482     wined3d_device_set_cursor_position(This->wined3d_device, XScreenSpace, YScreenSpace, Flags);
483     wined3d_mutex_unlock();
484 }
485
486 static BOOL WINAPI IDirect3DDevice8Impl_ShowCursor(IDirect3DDevice8 *iface, BOOL bShow)
487 {
488     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
489     BOOL ret;
490
491     TRACE("iface %p, show %#x.\n", iface, bShow);
492
493     wined3d_mutex_lock();
494     ret = wined3d_device_show_cursor(This->wined3d_device, bShow);
495     wined3d_mutex_unlock();
496
497     return ret;
498 }
499
500 static HRESULT WINAPI IDirect3DDevice8Impl_CreateAdditionalSwapChain(IDirect3DDevice8 *iface,
501         D3DPRESENT_PARAMETERS *present_parameters, IDirect3DSwapChain8 **swapchain)
502 {
503     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
504     IDirect3DSwapChain8Impl *object;
505     HRESULT hr;
506
507     TRACE("iface %p, present_parameters %p, swapchain %p.\n",
508             iface, present_parameters, swapchain);
509
510     object = HeapAlloc(GetProcessHeap(),  HEAP_ZERO_MEMORY, sizeof(*object));
511     if (!object)
512     {
513         ERR("Failed to allocate swapchain memory.\n");
514         return E_OUTOFMEMORY;
515     }
516
517     hr = swapchain_init(object, This, present_parameters);
518     if (FAILED(hr))
519     {
520         WARN("Failed to initialize swapchain, hr %#x.\n", hr);
521         HeapFree(GetProcessHeap(), 0, object);
522         return hr;
523     }
524
525     TRACE("Created swapchain %p.\n", object);
526     *swapchain = &object->IDirect3DSwapChain8_iface;
527
528     return D3D_OK;
529 }
530
531 static HRESULT WINAPI reset_enum_callback(struct wined3d_resource *resource, void *data)
532 {
533     struct wined3d_resource_desc desc;
534     BOOL *resources_ok = data;
535
536     wined3d_resource_get_desc(resource, &desc);
537     if (desc.pool == WINED3DPOOL_DEFAULT)
538     {
539         IDirect3DSurface8 *surface;
540
541         if (desc.resource_type != WINED3DRTYPE_SURFACE)
542         {
543             WARN("Resource %p in pool D3DPOOL_DEFAULT blocks the Reset call.\n", resource);
544             *resources_ok = FALSE;
545             return S_FALSE;
546         }
547
548         surface = wined3d_resource_get_parent(resource);
549
550         IDirect3DSurface8_AddRef(surface);
551         if (IDirect3DSurface8_Release(surface))
552         {
553             WARN("Surface %p (resource %p) in pool D3DPOOL_DEFAULT blocks the Reset call.\n", surface, resource);
554             *resources_ok = FALSE;
555             return S_FALSE;
556         }
557
558         WARN("Surface %p (resource %p) is an implicit resource with ref 0.\n", surface, resource);
559     }
560
561     return S_OK;
562 }
563
564 static HRESULT WINAPI IDirect3DDevice8Impl_Reset(IDirect3DDevice8 *iface,
565         D3DPRESENT_PARAMETERS *pPresentationParameters)
566 {
567     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
568     WINED3DPRESENT_PARAMETERS localParameters;
569     BOOL resources_ok = TRUE;
570     HRESULT hr;
571     UINT i;
572
573     TRACE("iface %p, present_parameters %p.\n", iface, pPresentationParameters);
574
575     wined3d_mutex_lock();
576     wined3d_device_set_index_buffer(This->wined3d_device, NULL, WINED3DFMT_UNKNOWN);
577     for (i = 0; i < 16; ++i)
578     {
579         wined3d_device_set_stream_source(This->wined3d_device, i, NULL, 0, 0);
580     }
581     for (i = 0; i < 16; ++i)
582     {
583         wined3d_device_set_texture(This->wined3d_device, i, NULL);
584     }
585
586     wined3d_device_enum_resources(This->wined3d_device, reset_enum_callback, &resources_ok);
587     if (!resources_ok)
588     {
589         WARN("The application is holding D3DPOOL_DEFAULT resources, rejecting reset.\n");
590         This->lost = TRUE;
591         wined3d_mutex_unlock();
592
593         return D3DERR_DEVICELOST;
594     }
595
596     localParameters.BackBufferWidth                             = pPresentationParameters->BackBufferWidth;
597     localParameters.BackBufferHeight                            = pPresentationParameters->BackBufferHeight;
598     localParameters.BackBufferFormat                            = wined3dformat_from_d3dformat(pPresentationParameters->BackBufferFormat);
599     localParameters.BackBufferCount                             = pPresentationParameters->BackBufferCount;
600     localParameters.MultiSampleType                             = pPresentationParameters->MultiSampleType;
601     localParameters.MultiSampleQuality                          = 0; /* d3d9 only */
602     localParameters.SwapEffect                                  = pPresentationParameters->SwapEffect;
603     localParameters.hDeviceWindow                               = pPresentationParameters->hDeviceWindow;
604     localParameters.Windowed                                    = pPresentationParameters->Windowed;
605     localParameters.EnableAutoDepthStencil                      = pPresentationParameters->EnableAutoDepthStencil;
606     localParameters.AutoDepthStencilFormat                      = wined3dformat_from_d3dformat(pPresentationParameters->AutoDepthStencilFormat);
607     localParameters.Flags                                       = pPresentationParameters->Flags;
608     localParameters.FullScreen_RefreshRateInHz                  = pPresentationParameters->FullScreen_RefreshRateInHz;
609     localParameters.PresentationInterval                        = pPresentationParameters->FullScreen_PresentationInterval;
610     localParameters.AutoRestoreDisplayMode                      = TRUE;
611
612     hr = wined3d_device_reset(This->wined3d_device, &localParameters);
613     if (SUCCEEDED(hr))
614     {
615         hr = wined3d_device_set_render_state(This->wined3d_device, WINED3DRS_POINTSIZE_MIN, 0);
616         This->lost = FALSE;
617     }
618     else
619     {
620         This->lost = TRUE;
621     }
622     wined3d_mutex_unlock();
623
624     pPresentationParameters->BackBufferWidth                    = localParameters.BackBufferWidth;
625     pPresentationParameters->BackBufferHeight                   = localParameters.BackBufferHeight;
626     pPresentationParameters->BackBufferFormat                   = d3dformat_from_wined3dformat(localParameters.BackBufferFormat);
627     pPresentationParameters->BackBufferCount                    = localParameters.BackBufferCount;
628     pPresentationParameters->MultiSampleType                    = localParameters.MultiSampleType;
629     pPresentationParameters->SwapEffect                         = localParameters.SwapEffect;
630     pPresentationParameters->hDeviceWindow                      = localParameters.hDeviceWindow;
631     pPresentationParameters->Windowed                           = localParameters.Windowed;
632     pPresentationParameters->EnableAutoDepthStencil             = localParameters.EnableAutoDepthStencil;
633     pPresentationParameters->AutoDepthStencilFormat             = d3dformat_from_wined3dformat(localParameters.AutoDepthStencilFormat);
634     pPresentationParameters->Flags                              = localParameters.Flags;
635     pPresentationParameters->FullScreen_RefreshRateInHz         = localParameters.FullScreen_RefreshRateInHz;
636     pPresentationParameters->FullScreen_PresentationInterval    = localParameters.PresentationInterval;
637
638     return hr;
639 }
640
641 static HRESULT WINAPI IDirect3DDevice8Impl_Present(IDirect3DDevice8 *iface, const RECT *pSourceRect,
642         const RECT *pDestRect, HWND hDestWindowOverride, const RGNDATA *pDirtyRegion)
643 {
644     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
645     HRESULT hr;
646
647     TRACE("iface %p, src_rect %p, dst_rect %p, dst_window_override %p, dirty_region %p.\n",
648             iface, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion);
649
650     wined3d_mutex_lock();
651     hr = wined3d_device_present(This->wined3d_device, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion);
652     wined3d_mutex_unlock();
653
654     return hr;
655 }
656
657 static HRESULT WINAPI IDirect3DDevice8Impl_GetBackBuffer(IDirect3DDevice8 *iface,
658         UINT BackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface8 **ppBackBuffer)
659 {
660     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
661     struct wined3d_surface *wined3d_surface = NULL;
662     HRESULT hr;
663
664     TRACE("iface %p, backbuffer_idx %u, backbuffer_type %#x, backbuffer %p.\n",
665             iface, BackBuffer, Type, ppBackBuffer);
666
667     wined3d_mutex_lock();
668     hr = wined3d_device_get_back_buffer(This->wined3d_device, 0,
669             BackBuffer, (WINED3DBACKBUFFER_TYPE)Type, &wined3d_surface);
670     if (SUCCEEDED(hr) && wined3d_surface && ppBackBuffer)
671     {
672         *ppBackBuffer = wined3d_surface_get_parent(wined3d_surface);
673         IDirect3DSurface8_AddRef(*ppBackBuffer);
674         wined3d_surface_decref(wined3d_surface);
675     }
676     wined3d_mutex_unlock();
677
678     return hr;
679 }
680
681 static HRESULT WINAPI IDirect3DDevice8Impl_GetRasterStatus(IDirect3DDevice8 *iface,
682         D3DRASTER_STATUS *pRasterStatus)
683 {
684     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
685     HRESULT hr;
686
687     TRACE("iface %p, raster_status %p.\n", iface, pRasterStatus);
688
689     wined3d_mutex_lock();
690     hr = wined3d_device_get_raster_status(This->wined3d_device, 0, (WINED3DRASTER_STATUS *)pRasterStatus);
691     wined3d_mutex_unlock();
692
693     return hr;
694 }
695
696 static void WINAPI IDirect3DDevice8Impl_SetGammaRamp(IDirect3DDevice8 *iface, DWORD Flags,
697         const D3DGAMMARAMP *pRamp)
698 {
699     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
700
701     TRACE("iface %p, flags %#x, ramp %p.\n", iface, Flags, pRamp);
702
703     /* Note: D3DGAMMARAMP is compatible with WINED3DGAMMARAMP */
704     wined3d_mutex_lock();
705     wined3d_device_set_gamma_ramp(This->wined3d_device, 0, Flags, (const WINED3DGAMMARAMP *)pRamp);
706     wined3d_mutex_unlock();
707 }
708
709 static void WINAPI IDirect3DDevice8Impl_GetGammaRamp(IDirect3DDevice8 *iface, D3DGAMMARAMP *pRamp)
710 {
711     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
712
713     TRACE("iface %p, ramp %p.\n", iface, pRamp);
714
715     /* Note: D3DGAMMARAMP is compatible with WINED3DGAMMARAMP */
716     wined3d_mutex_lock();
717     wined3d_device_get_gamma_ramp(This->wined3d_device, 0, (WINED3DGAMMARAMP *)pRamp);
718     wined3d_mutex_unlock();
719 }
720
721 static HRESULT WINAPI IDirect3DDevice8Impl_CreateTexture(IDirect3DDevice8 *iface,
722         UINT width, UINT height, UINT levels, DWORD usage, D3DFORMAT format,
723         D3DPOOL pool, IDirect3DTexture8 **texture)
724 {
725     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
726     IDirect3DTexture8Impl *object;
727     HRESULT hr;
728
729     TRACE("iface %p, width %u, height %u, levels %u, usage %#x, format %#x, pool %#x, texture %p.\n",
730             iface, width, height, levels, usage, format, pool, texture);
731
732     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
733     if (!object)
734     {
735         ERR("Failed to allocate texture memory.\n");
736         return D3DERR_OUTOFVIDEOMEMORY;
737     }
738
739     hr = texture_init(object, This, width, height, levels, usage, format, pool);
740     if (FAILED(hr))
741     {
742         WARN("Failed to initialize texture, hr %#x.\n", hr);
743         HeapFree(GetProcessHeap(), 0, object);
744         return hr;
745     }
746
747     TRACE("Created texture %p.\n", object);
748     *texture = &object->IDirect3DTexture8_iface;
749
750     return D3D_OK;
751 }
752
753 static HRESULT WINAPI IDirect3DDevice8Impl_CreateVolumeTexture(IDirect3DDevice8 *iface,
754         UINT width, UINT height, UINT depth, UINT levels, DWORD usage, D3DFORMAT format,
755         D3DPOOL pool, IDirect3DVolumeTexture8 **texture)
756 {
757     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
758     IDirect3DVolumeTexture8Impl *object;
759     HRESULT hr;
760
761     TRACE("iface %p, width %u, height %u, depth %u, levels %u, usage %#x, format %#x, pool %#x, texture %p.\n",
762             iface, width, height, depth, levels, usage, format, pool, texture);
763
764     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
765     if (!object)
766     {
767         ERR("Failed to allocate volume texture memory.\n");
768         return D3DERR_OUTOFVIDEOMEMORY;
769     }
770
771     hr = volumetexture_init(object, This, width, height, depth, levels, usage, format, pool);
772     if (FAILED(hr))
773     {
774         WARN("Failed to initialize volume texture, hr %#x.\n", hr);
775         HeapFree(GetProcessHeap(), 0, object);
776         return hr;
777     }
778
779     TRACE("Created volume texture %p.\n", object);
780     *texture = &object->IDirect3DVolumeTexture8_iface;
781
782     return D3D_OK;
783 }
784
785 static HRESULT WINAPI IDirect3DDevice8Impl_CreateCubeTexture(IDirect3DDevice8 *iface, UINT edge_length,
786         UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool, IDirect3DCubeTexture8 **texture)
787 {
788     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
789     IDirect3DCubeTexture8Impl *object;
790     HRESULT hr;
791
792     TRACE("iface %p, edge_length %u, levels %u, usage %#x, format %#x, pool %#x, texture %p.\n",
793             iface, edge_length, levels, usage, format, pool, texture);
794
795     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
796     if (!object)
797     {
798         ERR("Failed to allocate cube texture memory.\n");
799         return D3DERR_OUTOFVIDEOMEMORY;
800     }
801
802     hr = cubetexture_init(object, This, edge_length, levels, usage, format, pool);
803     if (FAILED(hr))
804     {
805         WARN("Failed to initialize cube texture, hr %#x.\n", hr);
806         HeapFree(GetProcessHeap(), 0, object);
807         return hr;
808     }
809
810     TRACE("Created cube texture %p.\n", object);
811     *texture = &object->IDirect3DCubeTexture8_iface;
812
813     return hr;
814 }
815
816 static HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexBuffer(IDirect3DDevice8 *iface, UINT size,
817         DWORD usage, DWORD fvf, D3DPOOL pool, IDirect3DVertexBuffer8 **buffer)
818 {
819     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
820     IDirect3DVertexBuffer8Impl *object;
821     HRESULT hr;
822
823     TRACE("iface %p, size %u, usage %#x, fvf %#x, pool %#x, buffer %p.\n",
824             iface, size, usage, fvf, pool, buffer);
825
826     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
827     if (!object)
828     {
829         ERR("Failed to allocate buffer memory.\n");
830         return D3DERR_OUTOFVIDEOMEMORY;
831     }
832
833     hr = vertexbuffer_init(object, This, size, usage, fvf, pool);
834     if (FAILED(hr))
835     {
836         WARN("Failed to initialize vertex buffer, hr %#x.\n", hr);
837         HeapFree(GetProcessHeap(), 0, object);
838         return hr;
839     }
840
841     TRACE("Created vertex buffer %p.\n", object);
842     *buffer = (IDirect3DVertexBuffer8 *)object;
843
844     return D3D_OK;
845 }
846
847 static HRESULT WINAPI IDirect3DDevice8Impl_CreateIndexBuffer(IDirect3DDevice8 *iface, UINT size,
848         DWORD usage, D3DFORMAT format, D3DPOOL pool, IDirect3DIndexBuffer8 **buffer)
849 {
850     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
851     IDirect3DIndexBuffer8Impl *object;
852     HRESULT hr;
853
854     TRACE("iface %p, size %u, usage %#x, format %#x, pool %#x, buffer %p.\n",
855             iface, size, usage, format, pool, buffer);
856
857     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
858     if (!object)
859     {
860         ERR("Failed to allocate buffer memory.\n");
861         return D3DERR_OUTOFVIDEOMEMORY;
862     }
863
864     hr = indexbuffer_init(object, This, size, usage, format, pool);
865     if (FAILED(hr))
866     {
867         WARN("Failed to initialize index buffer, hr %#x.\n", hr);
868         HeapFree(GetProcessHeap(), 0, object);
869         return hr;
870     }
871
872     TRACE("Created index buffer %p.\n", object);
873     *buffer = &object->IDirect3DIndexBuffer8_iface;
874
875     return D3D_OK;
876 }
877
878 static HRESULT IDirect3DDevice8Impl_CreateSurface(IDirect3DDevice8Impl *device, UINT Width,
879         UINT Height, D3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level,
880         IDirect3DSurface8 **ppSurface, UINT Usage, D3DPOOL Pool, D3DMULTISAMPLE_TYPE MultiSample,
881         DWORD MultisampleQuality)
882 {
883     IDirect3DSurface8Impl *object;
884     HRESULT hr;
885
886     TRACE("device %p, width %u, height %u, format %#x, lockable %#x, discard %#x, level %u, surface %p,\n"
887             "\tusage %#x, pool %#x, multisample_type %#x, multisample_quality %u.\n",
888             device, Width, Height, Format, Lockable, Discard, Level, ppSurface,
889             Usage, Pool, MultiSample, MultisampleQuality);
890
891     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
892     if (!object)
893     {
894         FIXME("Failed to allocate surface memory.\n");
895         return D3DERR_OUTOFVIDEOMEMORY;
896     }
897
898     hr = surface_init(object, device, Width, Height, Format, Lockable, Discard, Level, Usage,
899             Pool, MultiSample, MultisampleQuality);
900     if (FAILED(hr))
901     {
902         WARN("Failed to initialize surface, hr %#x.\n", hr);
903         HeapFree(GetProcessHeap(), 0, object);
904         return hr;
905     }
906
907     TRACE("Created surface %p.\n", object);
908     *ppSurface = &object->IDirect3DSurface8_iface;
909
910     return D3D_OK;
911 }
912
913 static HRESULT WINAPI IDirect3DDevice8Impl_CreateRenderTarget(IDirect3DDevice8 *iface, UINT Width,
914         UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, BOOL Lockable,
915         IDirect3DSurface8 **ppSurface)
916 {
917     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
918     HRESULT hr;
919
920     TRACE("iface %p, width %u, height %u, format %#x, multisample_type %#x, lockable %#x, surface %p.\n",
921             iface, Width, Height, Format, MultiSample, Lockable, ppSurface);
922
923     hr = IDirect3DDevice8Impl_CreateSurface(This, Width, Height, Format, Lockable,
924             FALSE /* Discard */, 0 /* Level */, ppSurface, D3DUSAGE_RENDERTARGET, D3DPOOL_DEFAULT,
925             MultiSample, 0);
926
927     return hr;
928 }
929
930 static HRESULT WINAPI IDirect3DDevice8Impl_CreateDepthStencilSurface(IDirect3DDevice8 *iface,
931         UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample,
932         IDirect3DSurface8 **ppSurface)
933 {
934     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
935     HRESULT hr;
936
937     TRACE("iface %p, width %u, height %u, format %#x, multisample_type %#x, surface %p.\n",
938             iface, Width, Height, Format, MultiSample, ppSurface);
939
940     /* TODO: Verify that Discard is false */
941     hr = IDirect3DDevice8Impl_CreateSurface(This, Width, Height, Format, TRUE /* Lockable */, FALSE,
942             0 /* Level */, ppSurface, D3DUSAGE_DEPTHSTENCIL, D3DPOOL_DEFAULT, MultiSample, 0);
943
944     return hr;
945 }
946
947 /*  IDirect3DDevice8Impl::CreateImageSurface returns surface with pool type SYSTEMMEM */
948 static HRESULT WINAPI IDirect3DDevice8Impl_CreateImageSurface(IDirect3DDevice8 *iface, UINT Width,
949         UINT Height, D3DFORMAT Format, IDirect3DSurface8 **ppSurface)
950 {
951     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
952     HRESULT hr;
953
954     TRACE("iface %p, width %u, height %u, format %#x, surface %p.\n",
955             iface, Width, Height, Format, ppSurface);
956
957     hr = IDirect3DDevice8Impl_CreateSurface(This, Width, Height, Format, TRUE /* Lockable */,
958             FALSE /* Discard */, 0 /* Level */, ppSurface, 0 /* Usage (undefined/none) */,
959             D3DPOOL_SYSTEMMEM, D3DMULTISAMPLE_NONE, 0 /* MultisampleQuality */);
960
961     return hr;
962 }
963
964 static HRESULT WINAPI IDirect3DDevice8Impl_CopyRects(IDirect3DDevice8 *iface,
965         IDirect3DSurface8 *pSourceSurface, const RECT *pSourceRects, UINT cRects,
966         IDirect3DSurface8 *pDestinationSurface, const POINT *pDestPoints)
967 {
968     IDirect3DSurface8Impl *Source = unsafe_impl_from_IDirect3DSurface8(pSourceSurface);
969     IDirect3DSurface8Impl *Dest = unsafe_impl_from_IDirect3DSurface8(pDestinationSurface);
970     enum wined3d_format_id srcFormat, destFormat;
971     struct wined3d_resource_desc wined3d_desc;
972     struct wined3d_resource *wined3d_resource;
973
974     TRACE("iface %p, src_surface %p, src_rects %p, rect_count %u, dst_surface %p, dst_points %p.\n",
975             iface, pSourceSurface, pSourceRects, cRects, pDestinationSurface, pDestPoints);
976
977     /* Check that the source texture is in WINED3DPOOL_SYSTEMMEM and the
978      * destination texture is in WINED3DPOOL_DEFAULT. */
979
980     wined3d_mutex_lock();
981     wined3d_resource = wined3d_surface_get_resource(Source->wined3d_surface);
982     wined3d_resource_get_desc(wined3d_resource, &wined3d_desc);
983     srcFormat = wined3d_desc.format;
984
985     wined3d_resource = wined3d_surface_get_resource(Dest->wined3d_surface);
986     wined3d_resource_get_desc(wined3d_resource, &wined3d_desc);
987     destFormat = wined3d_desc.format;
988
989     /* Check that the source and destination formats match */
990     if (srcFormat != destFormat && WINED3DFMT_UNKNOWN != destFormat)
991     {
992         WARN("Source %p format must match the dest %p format, returning D3DERR_INVALIDCALL.\n",
993                 pSourceSurface, pDestinationSurface);
994         wined3d_mutex_unlock();
995         return D3DERR_INVALIDCALL;
996     }
997     else if (WINED3DFMT_UNKNOWN == destFormat)
998     {
999         TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", iface);
1000         wined3d_surface_set_format(Dest->wined3d_surface, srcFormat);
1001     }
1002
1003     /* Quick if complete copy ... */
1004     if (!cRects && !pSourceRects && !pDestPoints)
1005     {
1006         wined3d_surface_bltfast(Dest->wined3d_surface, 0, 0,
1007                 Source->wined3d_surface, NULL, WINEDDBLTFAST_NOCOLORKEY);
1008     }
1009     else
1010     {
1011         unsigned int i;
1012         /* Copy rect by rect */
1013         if (pSourceRects && pDestPoints)
1014         {
1015             for (i = 0; i < cRects; ++i)
1016             {
1017                 wined3d_surface_bltfast(Dest->wined3d_surface, pDestPoints[i].x, pDestPoints[i].y,
1018                         Source->wined3d_surface, &pSourceRects[i], WINEDDBLTFAST_NOCOLORKEY);
1019             }
1020         }
1021         else
1022         {
1023             for (i = 0; i < cRects; ++i)
1024             {
1025                 wined3d_surface_bltfast(Dest->wined3d_surface, 0, 0,
1026                         Source->wined3d_surface, &pSourceRects[i], WINEDDBLTFAST_NOCOLORKEY);
1027             }
1028         }
1029     }
1030     wined3d_mutex_unlock();
1031
1032     return WINED3D_OK;
1033 }
1034
1035 static HRESULT WINAPI IDirect3DDevice8Impl_UpdateTexture(IDirect3DDevice8 *iface,
1036         IDirect3DBaseTexture8 *src_texture, IDirect3DBaseTexture8 *dst_texture)
1037 {
1038     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1039     HRESULT hr;
1040
1041     TRACE("iface %p, src_texture %p, dst_texture %p.\n", iface, src_texture, dst_texture);
1042
1043     wined3d_mutex_lock();
1044     hr = wined3d_device_update_texture(This->wined3d_device,
1045             ((IDirect3DBaseTexture8Impl *)src_texture)->wined3d_texture,
1046             ((IDirect3DBaseTexture8Impl *)dst_texture)->wined3d_texture);
1047     wined3d_mutex_unlock();
1048
1049     return hr;
1050 }
1051
1052 static HRESULT WINAPI IDirect3DDevice8Impl_GetFrontBuffer(IDirect3DDevice8 *iface,
1053         IDirect3DSurface8 *pDestSurface)
1054 {
1055     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1056     IDirect3DSurface8Impl *destSurface = unsafe_impl_from_IDirect3DSurface8(pDestSurface);
1057     HRESULT hr;
1058
1059     TRACE("iface %p, dst_surface %p.\n", iface, pDestSurface);
1060
1061     if (pDestSurface == NULL) {
1062         WARN("(%p) : Caller passed NULL as pDestSurface returning D3DERR_INVALIDCALL\n", This);
1063         return D3DERR_INVALIDCALL;
1064     }
1065
1066     wined3d_mutex_lock();
1067     hr = wined3d_device_get_front_buffer_data(This->wined3d_device, 0, destSurface->wined3d_surface);
1068     wined3d_mutex_unlock();
1069
1070     return hr;
1071 }
1072
1073 static HRESULT WINAPI IDirect3DDevice8Impl_SetRenderTarget(IDirect3DDevice8 *iface,
1074         IDirect3DSurface8 *pRenderTarget, IDirect3DSurface8 *pNewZStencil)
1075 {
1076     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1077     IDirect3DSurface8Impl *pSurface = unsafe_impl_from_IDirect3DSurface8(pRenderTarget);
1078     IDirect3DSurface8Impl *pZSurface = unsafe_impl_from_IDirect3DSurface8(pNewZStencil);
1079     struct wined3d_surface *original_ds = NULL;
1080     HRESULT hr;
1081
1082     TRACE("iface %p, render_target %p, depth_stencil %p.\n", iface, pRenderTarget, pNewZStencil);
1083
1084     wined3d_mutex_lock();
1085
1086     if (pZSurface)
1087     {
1088         struct wined3d_resource_desc ds_desc, rt_desc;
1089         struct wined3d_resource *wined3d_resource;
1090         struct wined3d_surface *original_rt = NULL;
1091
1092         /* If no render target is passed in check the size against the current RT */
1093         if (!pRenderTarget)
1094         {
1095             hr = wined3d_device_get_render_target(This->wined3d_device, 0, &original_rt);
1096             if (FAILED(hr) || !original_rt)
1097             {
1098                 wined3d_mutex_unlock();
1099                 return hr;
1100             }
1101             wined3d_resource = wined3d_surface_get_resource(original_rt);
1102             wined3d_surface_decref(original_rt);
1103         }
1104         else
1105             wined3d_resource = wined3d_surface_get_resource(pSurface->wined3d_surface);
1106         wined3d_resource_get_desc(wined3d_resource, &rt_desc);
1107
1108         wined3d_resource = wined3d_surface_get_resource(pZSurface->wined3d_surface);
1109         wined3d_resource_get_desc(wined3d_resource, &ds_desc);
1110
1111         if (ds_desc.width < rt_desc.width || ds_desc.height < rt_desc.height)
1112         {
1113             WARN("Depth stencil is smaller than the render target, returning D3DERR_INVALIDCALL\n");
1114             wined3d_mutex_unlock();
1115             return D3DERR_INVALIDCALL;
1116         }
1117     }
1118
1119     hr = wined3d_device_get_depth_stencil(This->wined3d_device, &original_ds);
1120     if (hr == WINED3D_OK || hr == WINED3DERR_NOTFOUND)
1121     {
1122         hr = wined3d_device_set_depth_stencil(This->wined3d_device, pZSurface ? pZSurface->wined3d_surface : NULL);
1123         if (SUCCEEDED(hr) && pRenderTarget)
1124         {
1125             hr = wined3d_device_set_render_target(This->wined3d_device, 0, pSurface->wined3d_surface, TRUE);
1126             if (FAILED(hr))
1127                 wined3d_device_set_depth_stencil(This->wined3d_device, original_ds);
1128         }
1129     }
1130     if (original_ds)
1131         wined3d_surface_decref(original_ds);
1132
1133     wined3d_mutex_unlock();
1134
1135     return hr;
1136 }
1137
1138 static HRESULT WINAPI IDirect3DDevice8Impl_GetRenderTarget(IDirect3DDevice8 *iface,
1139         IDirect3DSurface8 **ppRenderTarget)
1140 {
1141     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1142     struct wined3d_surface *wined3d_surface;
1143     HRESULT hr;
1144
1145     TRACE("iface %p, render_target %p.\n", iface, ppRenderTarget);
1146
1147     if (ppRenderTarget == NULL) {
1148         return D3DERR_INVALIDCALL;
1149     }
1150
1151     wined3d_mutex_lock();
1152     hr = wined3d_device_get_render_target(This->wined3d_device, 0, &wined3d_surface);
1153     if (SUCCEEDED(hr) && wined3d_surface)
1154     {
1155         *ppRenderTarget = wined3d_surface_get_parent(wined3d_surface);
1156         IDirect3DSurface8_AddRef(*ppRenderTarget);
1157         wined3d_surface_decref(wined3d_surface);
1158     }
1159     else
1160     {
1161         FIXME("Call to IWineD3DDevice_GetRenderTarget failed\n");
1162         *ppRenderTarget = NULL;
1163     }
1164     wined3d_mutex_unlock();
1165
1166     return hr;
1167 }
1168
1169 static HRESULT WINAPI IDirect3DDevice8Impl_GetDepthStencilSurface(IDirect3DDevice8 *iface,
1170         IDirect3DSurface8 **ppZStencilSurface)
1171 {
1172     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1173     struct wined3d_surface *wined3d_surface;
1174     HRESULT hr;
1175
1176     TRACE("iface %p, depth_stencil %p.\n", iface, ppZStencilSurface);
1177
1178     if(ppZStencilSurface == NULL){
1179         return D3DERR_INVALIDCALL;
1180     }
1181
1182     wined3d_mutex_lock();
1183     hr = wined3d_device_get_depth_stencil(This->wined3d_device, &wined3d_surface);
1184     if (SUCCEEDED(hr))
1185     {
1186         *ppZStencilSurface = wined3d_surface_get_parent(wined3d_surface);
1187         IDirect3DSurface8_AddRef(*ppZStencilSurface);
1188         wined3d_surface_decref(wined3d_surface);
1189     }
1190     else
1191     {
1192         if (hr != WINED3DERR_NOTFOUND)
1193                 FIXME("Call to IWineD3DDevice_GetDepthStencilSurface failed with 0x%08x\n", hr);
1194         *ppZStencilSurface = NULL;
1195     }
1196     wined3d_mutex_unlock();
1197
1198     return hr;
1199 }
1200
1201 static HRESULT WINAPI IDirect3DDevice8Impl_BeginScene(IDirect3DDevice8 *iface)
1202 {
1203     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1204     HRESULT hr;
1205
1206     TRACE("iface %p.\n", iface);
1207
1208     wined3d_mutex_lock();
1209     hr = wined3d_device_begin_scene(This->wined3d_device);
1210     wined3d_mutex_unlock();
1211
1212     return hr;
1213 }
1214
1215 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDevice8Impl_EndScene(IDirect3DDevice8 *iface)
1216 {
1217     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1218     HRESULT hr;
1219
1220     TRACE("iface %p.\n", iface);
1221
1222     wined3d_mutex_lock();
1223     hr = wined3d_device_end_scene(This->wined3d_device);
1224     wined3d_mutex_unlock();
1225
1226     return hr;
1227 }
1228
1229 static HRESULT WINAPI IDirect3DDevice8Impl_Clear(IDirect3DDevice8 *iface, DWORD Count,
1230         const D3DRECT *pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil)
1231 {
1232     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1233     HRESULT hr;
1234
1235     TRACE("iface %p, rect_count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %u.\n",
1236             iface, Count, pRects, Flags, Color, Z, Stencil);
1237
1238     wined3d_mutex_lock();
1239     hr = wined3d_device_clear(This->wined3d_device, Count, (const RECT *)pRects, Flags, Color, Z, Stencil);
1240     wined3d_mutex_unlock();
1241
1242     return hr;
1243 }
1244
1245 static HRESULT WINAPI IDirect3DDevice8Impl_SetTransform(IDirect3DDevice8 *iface,
1246         D3DTRANSFORMSTATETYPE State, const D3DMATRIX *lpMatrix)
1247 {
1248     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1249     HRESULT hr;
1250
1251     TRACE("iface %p, state %#x, matrix %p.\n", iface, State, lpMatrix);
1252
1253     /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
1254     wined3d_mutex_lock();
1255     hr = wined3d_device_set_transform(This->wined3d_device, State, (const WINED3DMATRIX *)lpMatrix);
1256     wined3d_mutex_unlock();
1257
1258     return hr;
1259 }
1260
1261 static HRESULT WINAPI IDirect3DDevice8Impl_GetTransform(IDirect3DDevice8 *iface,
1262         D3DTRANSFORMSTATETYPE State, D3DMATRIX *pMatrix)
1263 {
1264     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1265     HRESULT hr;
1266
1267     TRACE("iface %p, state %#x, matrix %p.\n", iface, State, pMatrix);
1268
1269     /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
1270     wined3d_mutex_lock();
1271     hr = wined3d_device_get_transform(This->wined3d_device, State, (WINED3DMATRIX *)pMatrix);
1272     wined3d_mutex_unlock();
1273
1274     return hr;
1275 }
1276
1277 static HRESULT WINAPI IDirect3DDevice8Impl_MultiplyTransform(IDirect3DDevice8 *iface,
1278         D3DTRANSFORMSTATETYPE State, const D3DMATRIX *pMatrix)
1279 {
1280     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1281     HRESULT hr;
1282
1283     TRACE("iface %p, state %#x, matrix %p.\n", iface, State, pMatrix);
1284
1285     /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
1286     wined3d_mutex_lock();
1287     hr = wined3d_device_multiply_transform(This->wined3d_device, State, (const WINED3DMATRIX *)pMatrix);
1288     wined3d_mutex_unlock();
1289
1290     return hr;
1291 }
1292
1293 static HRESULT WINAPI IDirect3DDevice8Impl_SetViewport(IDirect3DDevice8 *iface,
1294         const D3DVIEWPORT8 *pViewport)
1295 {
1296     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1297     HRESULT hr;
1298
1299     TRACE("iface %p, viewport %p.\n", iface, pViewport);
1300
1301     /* Note: D3DVIEWPORT8 is compatible with WINED3DVIEWPORT */
1302     wined3d_mutex_lock();
1303     hr = wined3d_device_set_viewport(This->wined3d_device, (const WINED3DVIEWPORT *)pViewport);
1304     wined3d_mutex_unlock();
1305
1306     return hr;
1307 }
1308
1309 static HRESULT WINAPI IDirect3DDevice8Impl_GetViewport(IDirect3DDevice8 *iface,
1310         D3DVIEWPORT8 *pViewport)
1311 {
1312     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1313     HRESULT hr;
1314
1315     TRACE("iface %p, viewport %p.\n", iface, pViewport);
1316
1317     /* Note: D3DVIEWPORT8 is compatible with WINED3DVIEWPORT */
1318     wined3d_mutex_lock();
1319     hr = wined3d_device_get_viewport(This->wined3d_device, (WINED3DVIEWPORT *)pViewport);
1320     wined3d_mutex_unlock();
1321
1322     return hr;
1323 }
1324
1325 static HRESULT WINAPI IDirect3DDevice8Impl_SetMaterial(IDirect3DDevice8 *iface,
1326         const D3DMATERIAL8 *pMaterial)
1327 {
1328     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1329     HRESULT hr;
1330
1331     TRACE("iface %p, material %p.\n", iface, pMaterial);
1332
1333     /* Note: D3DMATERIAL8 is compatible with WINED3DMATERIAL */
1334     wined3d_mutex_lock();
1335     hr = wined3d_device_set_material(This->wined3d_device, (const WINED3DMATERIAL *)pMaterial);
1336     wined3d_mutex_unlock();
1337
1338     return hr;
1339 }
1340
1341 static HRESULT WINAPI IDirect3DDevice8Impl_GetMaterial(IDirect3DDevice8 *iface,
1342         D3DMATERIAL8 *pMaterial)
1343 {
1344     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1345     HRESULT hr;
1346
1347     TRACE("iface %p, material %p.\n", iface, pMaterial);
1348
1349     /* Note: D3DMATERIAL8 is compatible with WINED3DMATERIAL */
1350     wined3d_mutex_lock();
1351     hr = wined3d_device_get_material(This->wined3d_device, (WINED3DMATERIAL *)pMaterial);
1352     wined3d_mutex_unlock();
1353
1354     return hr;
1355 }
1356
1357 static HRESULT WINAPI IDirect3DDevice8Impl_SetLight(IDirect3DDevice8 *iface, DWORD Index,
1358         const D3DLIGHT8 *pLight)
1359 {
1360     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1361     HRESULT hr;
1362
1363     TRACE("iface %p, index %u, light %p.\n", iface, Index, pLight);
1364
1365     /* Note: D3DLIGHT8 is compatible with WINED3DLIGHT */
1366     wined3d_mutex_lock();
1367     hr = wined3d_device_set_light(This->wined3d_device, Index, (const WINED3DLIGHT *)pLight);
1368     wined3d_mutex_unlock();
1369
1370     return hr;
1371 }
1372
1373 static HRESULT WINAPI IDirect3DDevice8Impl_GetLight(IDirect3DDevice8 *iface, DWORD Index,
1374         D3DLIGHT8 *pLight)
1375 {
1376     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1377     HRESULT hr;
1378
1379     TRACE("iface %p, index %u, light %p.\n", iface, Index, pLight);
1380
1381     /* Note: D3DLIGHT8 is compatible with WINED3DLIGHT */
1382     wined3d_mutex_lock();
1383     hr = wined3d_device_get_light(This->wined3d_device, Index, (WINED3DLIGHT *)pLight);
1384     wined3d_mutex_unlock();
1385
1386     return hr;
1387 }
1388
1389 static HRESULT WINAPI IDirect3DDevice8Impl_LightEnable(IDirect3DDevice8 *iface, DWORD Index,
1390         BOOL Enable)
1391 {
1392     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1393     HRESULT hr;
1394
1395     TRACE("iface %p, index %u, enable %#x.\n", iface, Index, Enable);
1396
1397     wined3d_mutex_lock();
1398     hr = wined3d_device_set_light_enable(This->wined3d_device, Index, Enable);
1399     wined3d_mutex_unlock();
1400
1401     return hr;
1402 }
1403
1404 static HRESULT WINAPI IDirect3DDevice8Impl_GetLightEnable(IDirect3DDevice8 *iface, DWORD Index,
1405         BOOL *pEnable)
1406 {
1407     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1408     HRESULT hr;
1409
1410     TRACE("iface %p, index %u, enable %p.\n", iface, Index, pEnable);
1411
1412     wined3d_mutex_lock();
1413     hr = wined3d_device_get_light_enable(This->wined3d_device, Index, pEnable);
1414     wined3d_mutex_unlock();
1415
1416     return hr;
1417 }
1418
1419 static HRESULT WINAPI IDirect3DDevice8Impl_SetClipPlane(IDirect3DDevice8 *iface, DWORD Index,
1420         const float *pPlane)
1421 {
1422     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1423     HRESULT hr;
1424
1425     TRACE("iface %p, index %u, plane %p.\n", iface, Index, pPlane);
1426
1427     wined3d_mutex_lock();
1428     hr = wined3d_device_set_clip_plane(This->wined3d_device, Index, pPlane);
1429     wined3d_mutex_unlock();
1430
1431     return hr;
1432 }
1433
1434 static HRESULT WINAPI IDirect3DDevice8Impl_GetClipPlane(IDirect3DDevice8 *iface, DWORD Index,
1435         float *pPlane)
1436 {
1437     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(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_get_clip_plane(This->wined3d_device, Index, pPlane);
1444     wined3d_mutex_unlock();
1445
1446     return hr;
1447 }
1448
1449 static HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(IDirect3DDevice8 *iface,
1450         D3DRENDERSTATETYPE State, DWORD Value)
1451 {
1452     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1453     HRESULT hr;
1454
1455     TRACE("iface %p, state %#x, value %#x.\n", iface, State, Value);
1456
1457     wined3d_mutex_lock();
1458     switch (State)
1459     {
1460         case D3DRS_ZBIAS:
1461             hr = wined3d_device_set_render_state(This->wined3d_device, WINED3DRS_DEPTHBIAS, Value);
1462             break;
1463
1464         default:
1465             hr = wined3d_device_set_render_state(This->wined3d_device, State, Value);
1466     }
1467     wined3d_mutex_unlock();
1468
1469     return hr;
1470 }
1471
1472 static HRESULT WINAPI IDirect3DDevice8Impl_GetRenderState(IDirect3DDevice8 *iface,
1473         D3DRENDERSTATETYPE State, DWORD *pValue)
1474 {
1475     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1476     HRESULT hr;
1477
1478     TRACE("iface %p, state %#x, value %p.\n", iface, State, pValue);
1479
1480     wined3d_mutex_lock();
1481     switch (State)
1482     {
1483         case D3DRS_ZBIAS:
1484             hr = wined3d_device_get_render_state(This->wined3d_device, WINED3DRS_DEPTHBIAS, pValue);
1485             break;
1486
1487         default:
1488             hr = wined3d_device_get_render_state(This->wined3d_device, State, pValue);
1489     }
1490     wined3d_mutex_unlock();
1491
1492     return hr;
1493 }
1494
1495 static HRESULT WINAPI IDirect3DDevice8Impl_BeginStateBlock(IDirect3DDevice8 *iface)
1496 {
1497     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1498     HRESULT hr;
1499
1500     TRACE("iface %p.\n", iface);
1501
1502     wined3d_mutex_lock();
1503     hr = wined3d_device_begin_stateblock(This->wined3d_device);
1504     wined3d_mutex_unlock();
1505
1506     return hr;
1507 }
1508
1509 static HRESULT WINAPI IDirect3DDevice8Impl_EndStateBlock(IDirect3DDevice8 *iface, DWORD *pToken)
1510 {
1511     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1512     struct wined3d_stateblock *stateblock;
1513     HRESULT hr;
1514
1515     TRACE("iface %p, token %p.\n", iface, pToken);
1516
1517     /* Tell wineD3D to endstateblock before anything else (in case we run out
1518      * of memory later and cause locking problems)
1519      */
1520     wined3d_mutex_lock();
1521     hr = wined3d_device_end_stateblock(This->wined3d_device, &stateblock);
1522     if (FAILED(hr))
1523     {
1524         WARN("IWineD3DDevice_EndStateBlock returned an error\n");
1525         wined3d_mutex_unlock();
1526         return hr;
1527     }
1528
1529     *pToken = d3d8_allocate_handle(&This->handle_table, stateblock, D3D8_HANDLE_SB);
1530     wined3d_mutex_unlock();
1531
1532     if (*pToken == D3D8_INVALID_HANDLE)
1533     {
1534         ERR("Failed to create a handle\n");
1535         wined3d_mutex_lock();
1536         wined3d_stateblock_decref(stateblock);
1537         wined3d_mutex_unlock();
1538         return E_FAIL;
1539     }
1540     ++*pToken;
1541
1542     TRACE("Returning %#x (%p).\n", *pToken, stateblock);
1543
1544     return hr;
1545 }
1546
1547 static HRESULT WINAPI IDirect3DDevice8Impl_ApplyStateBlock(IDirect3DDevice8 *iface, DWORD Token)
1548 {
1549     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1550     struct wined3d_stateblock *stateblock;
1551     HRESULT hr;
1552
1553     TRACE("iface %p, token %#x.\n", iface, Token);
1554
1555     if (!Token) return D3D_OK;
1556
1557     wined3d_mutex_lock();
1558     stateblock = d3d8_get_object(&This->handle_table, Token - 1, D3D8_HANDLE_SB);
1559     if (!stateblock)
1560     {
1561         WARN("Invalid handle (%#x) passed.\n", Token);
1562         wined3d_mutex_unlock();
1563         return D3DERR_INVALIDCALL;
1564     }
1565     hr = wined3d_stateblock_apply(stateblock);
1566     wined3d_mutex_unlock();
1567
1568     return hr;
1569 }
1570
1571 static HRESULT WINAPI IDirect3DDevice8Impl_CaptureStateBlock(IDirect3DDevice8 *iface, DWORD Token)
1572 {
1573     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1574     struct wined3d_stateblock *stateblock;
1575     HRESULT hr;
1576
1577     TRACE("iface %p, token %#x.\n", iface, Token);
1578
1579     wined3d_mutex_lock();
1580     stateblock = d3d8_get_object(&This->handle_table, Token - 1, D3D8_HANDLE_SB);
1581     if (!stateblock)
1582     {
1583         WARN("Invalid handle (%#x) passed.\n", Token);
1584         wined3d_mutex_unlock();
1585         return D3DERR_INVALIDCALL;
1586     }
1587     hr = wined3d_stateblock_capture(stateblock);
1588     wined3d_mutex_unlock();
1589
1590     return hr;
1591 }
1592
1593 static HRESULT WINAPI IDirect3DDevice8Impl_DeleteStateBlock(IDirect3DDevice8 *iface, DWORD Token)
1594 {
1595     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1596     struct wined3d_stateblock *stateblock;
1597
1598     TRACE("iface %p, token %#x.\n", iface, Token);
1599
1600     wined3d_mutex_lock();
1601     stateblock = d3d8_free_handle(&This->handle_table, Token - 1, D3D8_HANDLE_SB);
1602
1603     if (!stateblock)
1604     {
1605         WARN("Invalid handle (%#x) passed.\n", Token);
1606         wined3d_mutex_unlock();
1607         return D3DERR_INVALIDCALL;
1608     }
1609
1610     if (wined3d_stateblock_decref(stateblock))
1611     {
1612         ERR("Stateblock %p has references left, this shouldn't happen.\n", stateblock);
1613     }
1614     wined3d_mutex_unlock();
1615
1616     return D3D_OK;
1617 }
1618
1619 static HRESULT WINAPI IDirect3DDevice8Impl_CreateStateBlock(IDirect3DDevice8 *iface,
1620         D3DSTATEBLOCKTYPE Type, DWORD *handle)
1621 {
1622     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1623     struct wined3d_stateblock *stateblock;
1624     HRESULT hr;
1625
1626     TRACE("iface %p, type %#x, handle %p.\n", iface, Type, handle);
1627
1628     if (Type != D3DSBT_ALL
1629             && Type != D3DSBT_PIXELSTATE
1630             && Type != D3DSBT_VERTEXSTATE)
1631     {
1632         WARN("Unexpected stateblock type, returning D3DERR_INVALIDCALL\n");
1633         return D3DERR_INVALIDCALL;
1634     }
1635
1636     wined3d_mutex_lock();
1637     hr = wined3d_stateblock_create(This->wined3d_device, (WINED3DSTATEBLOCKTYPE)Type, &stateblock);
1638     if (FAILED(hr))
1639     {
1640         wined3d_mutex_unlock();
1641         ERR("IWineD3DDevice_CreateStateBlock failed, hr %#x\n", hr);
1642         return hr;
1643     }
1644
1645     *handle = d3d8_allocate_handle(&This->handle_table, stateblock, D3D8_HANDLE_SB);
1646     wined3d_mutex_unlock();
1647
1648     if (*handle == D3D8_INVALID_HANDLE)
1649     {
1650         ERR("Failed to allocate a handle.\n");
1651         wined3d_mutex_lock();
1652         wined3d_stateblock_decref(stateblock);
1653         wined3d_mutex_unlock();
1654         return E_FAIL;
1655     }
1656     ++*handle;
1657
1658     TRACE("Returning %#x (%p).\n", *handle, stateblock);
1659
1660     return hr;
1661 }
1662
1663 static HRESULT WINAPI IDirect3DDevice8Impl_SetClipStatus(IDirect3DDevice8 *iface,
1664         const D3DCLIPSTATUS8 *pClipStatus)
1665 {
1666     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1667     HRESULT hr;
1668
1669     TRACE("iface %p, clip_status %p.\n", iface, pClipStatus);
1670 /* FIXME: Verify that D3DCLIPSTATUS8 ~= WINED3DCLIPSTATUS */
1671
1672     wined3d_mutex_lock();
1673     hr = wined3d_device_set_clip_status(This->wined3d_device, (const WINED3DCLIPSTATUS *)pClipStatus);
1674     wined3d_mutex_unlock();
1675
1676     return hr;
1677 }
1678
1679 static HRESULT WINAPI IDirect3DDevice8Impl_GetClipStatus(IDirect3DDevice8 *iface,
1680         D3DCLIPSTATUS8 *pClipStatus)
1681 {
1682     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1683     HRESULT hr;
1684
1685     TRACE("iface %p, clip_status %p.\n", iface, pClipStatus);
1686
1687     wined3d_mutex_lock();
1688     hr = wined3d_device_get_clip_status(This->wined3d_device, (WINED3DCLIPSTATUS *)pClipStatus);
1689     wined3d_mutex_unlock();
1690
1691     return hr;
1692 }
1693
1694 static HRESULT WINAPI IDirect3DDevice8Impl_GetTexture(IDirect3DDevice8 *iface,
1695         DWORD Stage, IDirect3DBaseTexture8 **ppTexture)
1696 {
1697     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1698     struct wined3d_texture *wined3d_texture;
1699     HRESULT hr;
1700
1701     TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, ppTexture);
1702
1703     if(ppTexture == NULL){
1704         return D3DERR_INVALIDCALL;
1705     }
1706
1707     wined3d_mutex_lock();
1708     hr = wined3d_device_get_texture(This->wined3d_device, Stage, &wined3d_texture);
1709     if (FAILED(hr))
1710     {
1711         WARN("Failed to get texture for stage %u, hr %#x.\n", Stage, hr);
1712         wined3d_mutex_unlock();
1713         *ppTexture = NULL;
1714         return hr;
1715     }
1716
1717     if (wined3d_texture)
1718     {
1719         *ppTexture = wined3d_texture_get_parent(wined3d_texture);
1720         IDirect3DBaseTexture8_AddRef(*ppTexture);
1721         wined3d_texture_decref(wined3d_texture);
1722     }
1723     else
1724     {
1725         *ppTexture = NULL;
1726     }
1727     wined3d_mutex_unlock();
1728
1729     return D3D_OK;
1730 }
1731
1732 static HRESULT WINAPI IDirect3DDevice8Impl_SetTexture(IDirect3DDevice8 *iface, DWORD Stage,
1733         IDirect3DBaseTexture8 *pTexture)
1734 {
1735     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1736     HRESULT hr;
1737
1738     TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, pTexture);
1739
1740     wined3d_mutex_lock();
1741     hr = wined3d_device_set_texture(This->wined3d_device, Stage,
1742             pTexture ? ((IDirect3DBaseTexture8Impl *)pTexture)->wined3d_texture : NULL);
1743     wined3d_mutex_unlock();
1744
1745     return hr;
1746 }
1747
1748 static const struct tss_lookup
1749 {
1750     BOOL sampler_state;
1751     DWORD state;
1752 }
1753 tss_lookup[] =
1754 {
1755     {FALSE, WINED3DTSS_FORCE_DWORD},            /*  0, unused */
1756     {FALSE, WINED3DTSS_COLOROP},                /*  1, D3DTSS_COLOROP */
1757     {FALSE, WINED3DTSS_COLORARG1},              /*  2, D3DTSS_COLORARG1 */
1758     {FALSE, WINED3DTSS_COLORARG2},              /*  3, D3DTSS_COLORARG2 */
1759     {FALSE, WINED3DTSS_ALPHAOP},                /*  4, D3DTSS_ALPHAOP */
1760     {FALSE, WINED3DTSS_ALPHAARG1},              /*  5, D3DTSS_ALPHAARG1 */
1761     {FALSE, WINED3DTSS_ALPHAARG2},              /*  6, D3DTSS_ALPHAARG2 */
1762     {FALSE, WINED3DTSS_BUMPENVMAT00},           /*  7, D3DTSS_BUMPENVMAT00 */
1763     {FALSE, WINED3DTSS_BUMPENVMAT01},           /*  8, D3DTSS_BUMPENVMAT01 */
1764     {FALSE, WINED3DTSS_BUMPENVMAT10},           /*  9, D3DTSS_BUMPENVMAT10 */
1765     {FALSE, WINED3DTSS_BUMPENVMAT11},           /* 10, D3DTSS_BUMPENVMAT11 */
1766     {FALSE, WINED3DTSS_TEXCOORDINDEX},          /* 11, D3DTSS_TEXCOORDINDEX */
1767     {FALSE, WINED3DTSS_FORCE_DWORD},            /* 12, unused */
1768     {TRUE,  WINED3DSAMP_ADDRESSU},              /* 13, D3DTSS_ADDRESSU */
1769     {TRUE,  WINED3DSAMP_ADDRESSV},              /* 14, D3DTSS_ADDRESSV */
1770     {TRUE,  WINED3DSAMP_BORDERCOLOR},           /* 15, D3DTSS_BORDERCOLOR */
1771     {TRUE,  WINED3DSAMP_MAGFILTER},             /* 16, D3DTSS_MAGFILTER */
1772     {TRUE,  WINED3DSAMP_MINFILTER},             /* 17, D3DTSS_MINFILTER */
1773     {TRUE,  WINED3DSAMP_MIPFILTER},             /* 18, D3DTSS_MIPFILTER */
1774     {TRUE,  WINED3DSAMP_MIPMAPLODBIAS},         /* 19, D3DTSS_MIPMAPLODBIAS */
1775     {TRUE,  WINED3DSAMP_MAXMIPLEVEL},           /* 20, D3DTSS_MAXMIPLEVEL */
1776     {TRUE,  WINED3DSAMP_MAXANISOTROPY},         /* 21, D3DTSS_MAXANISOTROPY */
1777     {FALSE, WINED3DTSS_BUMPENVLSCALE},          /* 22, D3DTSS_BUMPENVLSCALE */
1778     {FALSE, WINED3DTSS_BUMPENVLOFFSET},         /* 23, D3DTSS_BUMPENVLOFFSET */
1779     {FALSE, WINED3DTSS_TEXTURETRANSFORMFLAGS},  /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
1780     {TRUE,  WINED3DSAMP_ADDRESSW},              /* 25, D3DTSS_ADDRESSW */
1781     {FALSE, WINED3DTSS_COLORARG0},              /* 26, D3DTSS_COLORARG0 */
1782     {FALSE, WINED3DTSS_ALPHAARG0},              /* 27, D3DTSS_ALPHAARG0 */
1783     {FALSE, WINED3DTSS_RESULTARG},              /* 28, D3DTSS_RESULTARG */
1784 };
1785
1786 static HRESULT  WINAPI  IDirect3DDevice8Impl_GetTextureStageState(IDirect3DDevice8 *iface,
1787         DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD *pValue)
1788 {
1789     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1790     const struct tss_lookup *l;
1791     HRESULT hr;
1792
1793     TRACE("iface %p, stage %u, state %#x, value %p.\n", iface, Stage, Type, pValue);
1794
1795     if (Type >= sizeof(tss_lookup) / sizeof(*tss_lookup))
1796     {
1797         WARN("Invalid Type %#x passed.\n", Type);
1798         return D3D_OK;
1799     }
1800
1801     l = &tss_lookup[Type];
1802
1803     wined3d_mutex_lock();
1804     if (l->sampler_state)
1805         hr = wined3d_device_get_sampler_state(This->wined3d_device, Stage, l->state, pValue);
1806     else
1807         hr = wined3d_device_get_texture_stage_state(This->wined3d_device, Stage, l->state, pValue);
1808     wined3d_mutex_unlock();
1809
1810     return hr;
1811 }
1812
1813 static HRESULT WINAPI IDirect3DDevice8Impl_SetTextureStageState(IDirect3DDevice8 *iface,
1814         DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value)
1815 {
1816     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1817     const struct tss_lookup *l;
1818     HRESULT hr;
1819
1820     TRACE("iface %p, stage %u, state %#x, value %#x.\n", iface, Stage, Type, Value);
1821
1822     if (Type >= sizeof(tss_lookup) / sizeof(*tss_lookup))
1823     {
1824         WARN("Invalid Type %#x passed.\n", Type);
1825         return D3D_OK;
1826     }
1827
1828     l = &tss_lookup[Type];
1829
1830     wined3d_mutex_lock();
1831     if (l->sampler_state)
1832         hr = wined3d_device_set_sampler_state(This->wined3d_device, Stage, l->state, Value);
1833     else
1834         hr = wined3d_device_set_texture_stage_state(This->wined3d_device, Stage, l->state, Value);
1835     wined3d_mutex_unlock();
1836
1837     return hr;
1838 }
1839
1840 static HRESULT WINAPI IDirect3DDevice8Impl_ValidateDevice(IDirect3DDevice8 *iface,
1841         DWORD *pNumPasses)
1842 {
1843     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1844     HRESULT hr;
1845
1846     TRACE("iface %p, pass_count %p.\n", iface, pNumPasses);
1847
1848     wined3d_mutex_lock();
1849     hr = wined3d_device_validate_device(This->wined3d_device, pNumPasses);
1850     wined3d_mutex_unlock();
1851
1852     return hr;
1853 }
1854
1855 static HRESULT WINAPI IDirect3DDevice8Impl_GetInfo(IDirect3DDevice8 *iface,
1856         DWORD info_id, void *info, DWORD info_size)
1857 {
1858     FIXME("iface %p, info_id %#x, info %p, info_size %u stub!\n", iface, info_id, info, info_size);
1859
1860     return D3D_OK;
1861 }
1862
1863 static HRESULT WINAPI IDirect3DDevice8Impl_SetPaletteEntries(IDirect3DDevice8 *iface,
1864         UINT PaletteNumber, const PALETTEENTRY *pEntries)
1865 {
1866     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1867     HRESULT hr;
1868
1869     TRACE("iface %p, palette_idx %u, entries %p.\n", iface, PaletteNumber, pEntries);
1870
1871     wined3d_mutex_lock();
1872     hr = wined3d_device_set_palette_entries(This->wined3d_device, PaletteNumber, pEntries);
1873     wined3d_mutex_unlock();
1874
1875     return hr;
1876 }
1877
1878 static HRESULT WINAPI IDirect3DDevice8Impl_GetPaletteEntries(IDirect3DDevice8 *iface,
1879         UINT PaletteNumber, PALETTEENTRY *pEntries)
1880 {
1881     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1882     HRESULT hr;
1883
1884     TRACE("iface %p, palette_idx %u, entries %p.\n", iface, PaletteNumber, pEntries);
1885
1886     wined3d_mutex_lock();
1887     hr = wined3d_device_get_palette_entries(This->wined3d_device, PaletteNumber, pEntries);
1888     wined3d_mutex_unlock();
1889
1890     return hr;
1891 }
1892
1893 static HRESULT WINAPI IDirect3DDevice8Impl_SetCurrentTexturePalette(IDirect3DDevice8 *iface,
1894         UINT PaletteNumber)
1895 {
1896     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1897     HRESULT hr;
1898
1899     TRACE("iface %p, palette_idx %u.\n", iface, PaletteNumber);
1900
1901     wined3d_mutex_lock();
1902     hr = wined3d_device_set_current_texture_palette(This->wined3d_device, PaletteNumber);
1903     wined3d_mutex_unlock();
1904
1905     return hr;
1906 }
1907
1908 static HRESULT  WINAPI  IDirect3DDevice8Impl_GetCurrentTexturePalette(IDirect3DDevice8 *iface,
1909         UINT *PaletteNumber)
1910 {
1911     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1912     HRESULT hr;
1913
1914     TRACE("iface %p, palette_idx %p.\n", iface, PaletteNumber);
1915
1916     wined3d_mutex_lock();
1917     hr = wined3d_device_get_current_texture_palette(This->wined3d_device, PaletteNumber);
1918     wined3d_mutex_unlock();
1919
1920     return hr;
1921 }
1922
1923 static HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitive(IDirect3DDevice8 *iface,
1924         D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount)
1925 {
1926     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1927     HRESULT hr;
1928
1929     TRACE("iface %p, primitive_type %#x, start_vertex %u, primitive_count %u.\n",
1930             iface, PrimitiveType, StartVertex, PrimitiveCount);
1931
1932     wined3d_mutex_lock();
1933     wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
1934     hr = wined3d_device_draw_primitive(This->wined3d_device, StartVertex,
1935             vertex_count_from_primitive_count(PrimitiveType, PrimitiveCount));
1936     wined3d_mutex_unlock();
1937
1938     return hr;
1939 }
1940
1941 static HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitive(IDirect3DDevice8 *iface,
1942         D3DPRIMITIVETYPE PrimitiveType, UINT MinVertexIndex, UINT NumVertices, UINT startIndex,
1943         UINT primCount)
1944 {
1945     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1946     HRESULT hr;
1947
1948     TRACE("iface %p, primitive_type %#x, min_vertex_idx %u, vertex_count %u, start_idx %u, primitive_count %u.\n",
1949             iface, PrimitiveType, MinVertexIndex, NumVertices, startIndex, primCount);
1950
1951     wined3d_mutex_lock();
1952     wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
1953     hr = wined3d_device_draw_indexed_primitive(This->wined3d_device, startIndex,
1954             vertex_count_from_primitive_count(PrimitiveType, primCount));
1955     wined3d_mutex_unlock();
1956
1957     return hr;
1958 }
1959
1960 static HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitiveUP(IDirect3DDevice8 *iface,
1961         D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, const void *pVertexStreamZeroData,
1962         UINT VertexStreamZeroStride)
1963 {
1964     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1965     HRESULT hr;
1966
1967     TRACE("iface %p, primitive_type %#x, primitive_count %u, data %p, stride %u.\n",
1968             iface, PrimitiveType, PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
1969
1970     wined3d_mutex_lock();
1971     wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
1972     hr = wined3d_device_draw_primitive_up(This->wined3d_device,
1973             vertex_count_from_primitive_count(PrimitiveType, PrimitiveCount),
1974             pVertexStreamZeroData, VertexStreamZeroStride);
1975     wined3d_mutex_unlock();
1976
1977     return hr;
1978 }
1979
1980 static HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitiveUP(IDirect3DDevice8 *iface,
1981         D3DPRIMITIVETYPE PrimitiveType, UINT MinVertexIndex, UINT NumVertexIndices,
1982         UINT PrimitiveCount, const void *pIndexData, D3DFORMAT IndexDataFormat,
1983         const void *pVertexStreamZeroData, UINT VertexStreamZeroStride)
1984 {
1985     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
1986     HRESULT hr;
1987
1988     TRACE("iface %p, primitive_type %#x, min_vertex_idx %u, index_count %u, primitive_count %u,\n"
1989             "index_data %p, index_format %#x, vertex_data %p, vertex_stride %u.\n",
1990             iface, PrimitiveType, MinVertexIndex, NumVertexIndices, PrimitiveCount,
1991             pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
1992
1993     wined3d_mutex_lock();
1994     wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
1995     hr = wined3d_device_draw_indexed_primitive_up(This->wined3d_device,
1996             vertex_count_from_primitive_count(PrimitiveType, PrimitiveCount), pIndexData,
1997             wined3dformat_from_d3dformat(IndexDataFormat), pVertexStreamZeroData, VertexStreamZeroStride);
1998     wined3d_mutex_unlock();
1999
2000     return hr;
2001 }
2002
2003 static HRESULT WINAPI IDirect3DDevice8Impl_ProcessVertices(IDirect3DDevice8 *iface,
2004         UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IDirect3DVertexBuffer8 *pDestBuffer,
2005         DWORD Flags)
2006 {
2007     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
2008     HRESULT hr;
2009     IDirect3DVertexBuffer8Impl *dest = (IDirect3DVertexBuffer8Impl *) pDestBuffer;
2010
2011     TRACE("iface %p, src_start_idx %u, dst_idx %u, vertex_count %u, dst_buffer %p, flags %#x.\n",
2012             iface, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, Flags);
2013
2014     wined3d_mutex_lock();
2015     hr = wined3d_device_process_vertices(This->wined3d_device, SrcStartIndex, DestIndex,
2016             VertexCount, dest->wineD3DVertexBuffer, NULL, Flags, dest->fvf);
2017     wined3d_mutex_unlock();
2018
2019     return hr;
2020 }
2021
2022 static HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(IDirect3DDevice8 *iface,
2023         const DWORD *declaration, const DWORD *byte_code, DWORD *shader, DWORD usage)
2024 {
2025     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
2026     IDirect3DVertexShader8Impl *object;
2027     DWORD shader_handle;
2028     DWORD handle;
2029     HRESULT hr;
2030
2031     TRACE("iface %p, declaration %p, byte_code %p, shader %p, usage %#x.\n",
2032             iface, declaration, byte_code, shader, usage);
2033
2034     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
2035     if (!object)
2036     {
2037         ERR("Failed to allocate vertex shader memory.\n");
2038         *shader = 0;
2039         return E_OUTOFMEMORY;
2040     }
2041
2042     wined3d_mutex_lock();
2043     handle = d3d8_allocate_handle(&This->handle_table, object, D3D8_HANDLE_VS);
2044     wined3d_mutex_unlock();
2045     if (handle == D3D8_INVALID_HANDLE)
2046     {
2047         ERR("Failed to allocate vertex shader handle.\n");
2048         HeapFree(GetProcessHeap(), 0, object);
2049         *shader = 0;
2050         return E_OUTOFMEMORY;
2051     }
2052
2053     shader_handle = handle + VS_HIGHESTFIXEDFXF + 1;
2054
2055     hr = vertexshader_init(object, This, declaration, byte_code, shader_handle, usage);
2056     if (FAILED(hr))
2057     {
2058         WARN("Failed to initialize vertex shader, hr %#x.\n", hr);
2059         wined3d_mutex_lock();
2060         d3d8_free_handle(&This->handle_table, handle, D3D8_HANDLE_VS);
2061         wined3d_mutex_unlock();
2062         HeapFree(GetProcessHeap(), 0, object);
2063         *shader = 0;
2064         return hr;
2065     }
2066
2067     TRACE("Created vertex shader %p (handle %#x).\n", object, shader_handle);
2068     *shader = shader_handle;
2069
2070     return D3D_OK;
2071 }
2072
2073 static IDirect3DVertexDeclaration8Impl *IDirect3DDevice8Impl_FindDecl(IDirect3DDevice8Impl *This, DWORD fvf)
2074 {
2075     IDirect3DVertexDeclaration8Impl *d3d8_declaration;
2076     HRESULT hr;
2077     int p, low, high; /* deliberately signed */
2078     struct FvfToDecl *convertedDecls = This->decls;
2079
2080     TRACE("Searching for declaration for fvf %08x... ", fvf);
2081
2082     low = 0;
2083     high = This->numConvertedDecls - 1;
2084     while(low <= high) {
2085         p = (low + high) >> 1;
2086         TRACE("%d ", p);
2087         if(convertedDecls[p].fvf == fvf) {
2088             TRACE("found %p\n", convertedDecls[p].decl);
2089             return (IDirect3DVertexDeclaration8Impl *)convertedDecls[p].decl;
2090         } else if(convertedDecls[p].fvf < fvf) {
2091             low = p + 1;
2092         } else {
2093             high = p - 1;
2094         }
2095     }
2096     TRACE("not found. Creating and inserting at position %d.\n", low);
2097
2098     d3d8_declaration = HeapAlloc(GetProcessHeap(), 0, sizeof(*d3d8_declaration));
2099     if (!d3d8_declaration)
2100     {
2101         ERR("Memory allocation failed.\n");
2102         return NULL;
2103     }
2104
2105     hr = vertexdeclaration_init_fvf(d3d8_declaration, This, fvf);
2106     if (FAILED(hr))
2107     {
2108         WARN("Failed to initialize vertex declaration, hr %#x.\n", hr);
2109         HeapFree(GetProcessHeap(), 0, d3d8_declaration);
2110         return NULL;
2111     }
2112
2113     if(This->declArraySize == This->numConvertedDecls) {
2114         int grow = This->declArraySize / 2;
2115         convertedDecls = HeapReAlloc(GetProcessHeap(), 0, convertedDecls,
2116                                      sizeof(convertedDecls[0]) * (This->numConvertedDecls + grow));
2117         if(!convertedDecls) {
2118             /* This will destroy it */
2119             IDirect3DVertexDeclaration8_Release((IDirect3DVertexDeclaration8 *)d3d8_declaration);
2120             return NULL;
2121         }
2122         This->decls = convertedDecls;
2123         This->declArraySize += grow;
2124     }
2125
2126     memmove(convertedDecls + low + 1, convertedDecls + low, sizeof(convertedDecls[0]) * (This->numConvertedDecls - low));
2127     convertedDecls[low].decl = (IDirect3DVertexDeclaration8 *)d3d8_declaration;
2128     convertedDecls[low].fvf = fvf;
2129     This->numConvertedDecls++;
2130
2131     TRACE("Returning %p. %u decls in array\n", d3d8_declaration, This->numConvertedDecls);
2132     return d3d8_declaration;
2133 }
2134
2135 static HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShader(IDirect3DDevice8 *iface, DWORD pShader)
2136 {
2137     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
2138     IDirect3DVertexShader8Impl *shader;
2139     HRESULT hr;
2140
2141     TRACE("iface %p, shader %#x.\n", iface, pShader);
2142
2143     if (VS_HIGHESTFIXEDFXF >= pShader) {
2144         TRACE("Setting FVF, %#x\n", pShader);
2145
2146         wined3d_mutex_lock();
2147         wined3d_device_set_vertex_declaration(This->wined3d_device,
2148                 IDirect3DDevice8Impl_FindDecl(This, pShader)->wined3d_vertex_declaration);
2149         wined3d_device_set_vertex_shader(This->wined3d_device, NULL);
2150         wined3d_mutex_unlock();
2151
2152         return D3D_OK;
2153     }
2154
2155     TRACE("Setting shader\n");
2156
2157     wined3d_mutex_lock();
2158     shader = d3d8_get_object(&This->handle_table, pShader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_VS);
2159     if (!shader)
2160     {
2161         WARN("Invalid handle (%#x) passed.\n", pShader);
2162         wined3d_mutex_unlock();
2163
2164         return D3DERR_INVALIDCALL;
2165     }
2166
2167     hr = wined3d_device_set_vertex_declaration(This->wined3d_device,
2168             ((IDirect3DVertexDeclaration8Impl *)shader->vertex_declaration)->wined3d_vertex_declaration);
2169     if (SUCCEEDED(hr))
2170         hr = wined3d_device_set_vertex_shader(This->wined3d_device, shader->wined3d_shader);
2171     wined3d_mutex_unlock();
2172
2173     TRACE("Returning hr %#x\n", hr);
2174
2175     return hr;
2176 }
2177
2178 static HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShader(IDirect3DDevice8 *iface, DWORD *ppShader)
2179 {
2180     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
2181     struct wined3d_vertex_declaration *wined3d_declaration;
2182     IDirect3DVertexDeclaration8 *d3d8_declaration;
2183     HRESULT hr;
2184
2185     TRACE("iface %p, shader %p.\n", iface, ppShader);
2186
2187     wined3d_mutex_lock();
2188     hr = wined3d_device_get_vertex_declaration(This->wined3d_device, &wined3d_declaration);
2189     if (FAILED(hr))
2190     {
2191         wined3d_mutex_unlock();
2192         WARN("(%p) : Call to IWineD3DDevice_GetVertexDeclaration failed %#x (device %p)\n",
2193                 This, hr, This->wined3d_device);
2194         return hr;
2195     }
2196
2197     if (!wined3d_declaration)
2198     {
2199         wined3d_mutex_unlock();
2200         *ppShader = 0;
2201         return D3D_OK;
2202     }
2203
2204     d3d8_declaration = wined3d_vertex_declaration_get_parent(wined3d_declaration);
2205     wined3d_vertex_declaration_decref(wined3d_declaration);
2206     wined3d_mutex_unlock();
2207     *ppShader = ((IDirect3DVertexDeclaration8Impl *)d3d8_declaration)->shader_handle;
2208
2209     TRACE("(%p) : returning %#x\n", This, *ppShader);
2210
2211     return hr;
2212 }
2213
2214 static HRESULT WINAPI IDirect3DDevice8Impl_DeleteVertexShader(IDirect3DDevice8 *iface, DWORD pShader)
2215 {
2216     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
2217     IDirect3DVertexShader8Impl *shader;
2218     struct wined3d_shader *cur;
2219
2220     TRACE("iface %p, shader %#x.\n", iface, pShader);
2221
2222     wined3d_mutex_lock();
2223     shader = d3d8_free_handle(&This->handle_table, pShader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_VS);
2224     if (!shader)
2225     {
2226         WARN("Invalid handle (%#x) passed.\n", pShader);
2227         wined3d_mutex_unlock();
2228
2229         return D3DERR_INVALIDCALL;
2230     }
2231
2232     cur = wined3d_device_get_vertex_shader(This->wined3d_device);
2233     if (cur)
2234     {
2235         if (cur == shader->wined3d_shader)
2236             IDirect3DDevice8_SetVertexShader(iface, 0);
2237         wined3d_shader_decref(cur);
2238     }
2239
2240     wined3d_mutex_unlock();
2241
2242     if (IDirect3DVertexShader8_Release(&shader->IDirect3DVertexShader8_iface))
2243     {
2244         ERR("Shader %p has references left, this shouldn't happen.\n", shader);
2245     }
2246
2247     return D3D_OK;
2248 }
2249
2250 static HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShaderConstant(IDirect3DDevice8 *iface,
2251         DWORD Register, const void *pConstantData, DWORD ConstantCount)
2252 {
2253     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
2254     HRESULT hr;
2255
2256     TRACE("iface %p, register %u, data %p, count %u.\n",
2257             iface, Register, pConstantData, ConstantCount);
2258
2259     if(Register + ConstantCount > D3D8_MAX_VERTEX_SHADER_CONSTANTF) {
2260         WARN("Trying to access %u constants, but d3d8 only supports %u\n",
2261              Register + ConstantCount, D3D8_MAX_VERTEX_SHADER_CONSTANTF);
2262         return D3DERR_INVALIDCALL;
2263     }
2264
2265     wined3d_mutex_lock();
2266     hr = wined3d_device_set_vs_consts_f(This->wined3d_device, Register, pConstantData, ConstantCount);
2267     wined3d_mutex_unlock();
2268
2269     return hr;
2270 }
2271
2272 static HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderConstant(IDirect3DDevice8 *iface,
2273         DWORD Register, void *pConstantData, DWORD ConstantCount)
2274 {
2275     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
2276     HRESULT hr;
2277
2278     TRACE("iface %p, register %u, data %p, count %u.\n",
2279             iface, Register, pConstantData, ConstantCount);
2280
2281     if(Register + ConstantCount > D3D8_MAX_VERTEX_SHADER_CONSTANTF) {
2282         WARN("Trying to access %u constants, but d3d8 only supports %u\n",
2283              Register + ConstantCount, D3D8_MAX_VERTEX_SHADER_CONSTANTF);
2284         return D3DERR_INVALIDCALL;
2285     }
2286
2287     wined3d_mutex_lock();
2288     hr = wined3d_device_get_vs_consts_f(This->wined3d_device, Register, pConstantData, ConstantCount);
2289     wined3d_mutex_unlock();
2290
2291     return hr;
2292 }
2293
2294 static HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderDeclaration(IDirect3DDevice8 *iface,
2295         DWORD pVertexShader, void *pData, DWORD *pSizeOfData)
2296 {
2297     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
2298     IDirect3DVertexDeclaration8Impl *declaration;
2299     IDirect3DVertexShader8Impl *shader;
2300
2301     TRACE("iface %p, shader %#x, data %p, data_size %p.\n",
2302             iface, pVertexShader, pData, pSizeOfData);
2303
2304     wined3d_mutex_lock();
2305     shader = d3d8_get_object(&This->handle_table, pVertexShader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_VS);
2306     wined3d_mutex_unlock();
2307
2308     if (!shader)
2309     {
2310         WARN("Invalid handle (%#x) passed.\n", pVertexShader);
2311         return D3DERR_INVALIDCALL;
2312     }
2313     declaration = (IDirect3DVertexDeclaration8Impl *)shader->vertex_declaration;
2314
2315     /* If pData is NULL, we just return the required size of the buffer. */
2316     if (!pData) {
2317         *pSizeOfData = declaration->elements_size;
2318         return D3D_OK;
2319     }
2320
2321     /* MSDN claims that if *pSizeOfData is smaller than the required size
2322      * we should write the required size and return D3DERR_MOREDATA.
2323      * That's not actually true. */
2324     if (*pSizeOfData < declaration->elements_size) {
2325         return D3DERR_INVALIDCALL;
2326     }
2327
2328     CopyMemory(pData, declaration->elements, declaration->elements_size);
2329
2330     return D3D_OK;
2331 }
2332
2333 static HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderFunction(IDirect3DDevice8 *iface,
2334         DWORD pVertexShader, void *pData, DWORD *pSizeOfData)
2335 {
2336     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
2337     IDirect3DVertexShader8Impl *shader = NULL;
2338     HRESULT hr;
2339
2340     TRACE("iface %p, shader %#x, data %p, data_size %p.\n",
2341             iface, pVertexShader, pData, pSizeOfData);
2342
2343     wined3d_mutex_lock();
2344     shader = d3d8_get_object(&This->handle_table, pVertexShader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_VS);
2345     if (!shader)
2346     {
2347         WARN("Invalid handle (%#x) passed.\n", pVertexShader);
2348         wined3d_mutex_unlock();
2349
2350         return D3DERR_INVALIDCALL;
2351     }
2352
2353     if (!shader->wined3d_shader)
2354     {
2355         wined3d_mutex_unlock();
2356         *pSizeOfData = 0;
2357         return D3D_OK;
2358     }
2359
2360     hr = wined3d_shader_get_byte_code(shader->wined3d_shader, pData, pSizeOfData);
2361     wined3d_mutex_unlock();
2362
2363     return hr;
2364 }
2365
2366 static HRESULT WINAPI IDirect3DDevice8Impl_SetIndices(IDirect3DDevice8 *iface,
2367         IDirect3DIndexBuffer8 *pIndexData, UINT baseVertexIndex)
2368 {
2369     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
2370     IDirect3DIndexBuffer8Impl *ib = unsafe_impl_from_IDirect3DIndexBuffer8(pIndexData);
2371     HRESULT hr;
2372
2373     TRACE("iface %p, buffer %p, base_vertex_idx %u.\n", iface, pIndexData, baseVertexIndex);
2374
2375     /* WineD3D takes an INT(due to d3d9), but d3d8 uses UINTs. Do I have to add a check here that
2376      * the UINT doesn't cause an overflow in the INT? It seems rather unlikely because such large
2377      * vertex buffers can't be created to address them with an index that requires the 32nd bit
2378      * (4 Byte minimum vertex size * 2^31-1 -> 8 gb buffer. The index sign would be the least
2379      * problem)
2380      */
2381     wined3d_mutex_lock();
2382     wined3d_device_set_base_vertex_index(This->wined3d_device, baseVertexIndex);
2383     hr = wined3d_device_set_index_buffer(This->wined3d_device,
2384             ib ? ib->wineD3DIndexBuffer : NULL,
2385             ib ? ib->format : WINED3DFMT_UNKNOWN);
2386     wined3d_mutex_unlock();
2387
2388     return hr;
2389 }
2390
2391 static HRESULT WINAPI IDirect3DDevice8Impl_GetIndices(IDirect3DDevice8 *iface,
2392         IDirect3DIndexBuffer8 **ppIndexData, UINT *pBaseVertexIndex)
2393 {
2394     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
2395     struct wined3d_buffer *retIndexData = NULL;
2396     HRESULT hr;
2397
2398     TRACE("iface %p, buffer %p, base_vertex_index %p.\n", iface, ppIndexData, pBaseVertexIndex);
2399
2400     if(ppIndexData == NULL){
2401         return D3DERR_INVALIDCALL;
2402     }
2403
2404     /* The case from UINT to INT is safe because d3d8 will never set negative values */
2405     wined3d_mutex_lock();
2406     *pBaseVertexIndex = wined3d_device_get_base_vertex_index(This->wined3d_device);
2407     hr = wined3d_device_get_index_buffer(This->wined3d_device, &retIndexData);
2408     if (SUCCEEDED(hr) && retIndexData)
2409     {
2410         *ppIndexData = wined3d_buffer_get_parent(retIndexData);
2411         IDirect3DIndexBuffer8_AddRef(*ppIndexData);
2412         wined3d_buffer_decref(retIndexData);
2413     } else {
2414         if (FAILED(hr)) FIXME("Call to GetIndices failed\n");
2415         *ppIndexData = NULL;
2416     }
2417     wined3d_mutex_unlock();
2418
2419     return hr;
2420 }
2421
2422 static HRESULT WINAPI IDirect3DDevice8Impl_CreatePixelShader(IDirect3DDevice8 *iface,
2423         const DWORD *byte_code, DWORD *shader)
2424 {
2425     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
2426     IDirect3DPixelShader8Impl *object;
2427     DWORD shader_handle;
2428     DWORD handle;
2429     HRESULT hr;
2430
2431     TRACE("iface %p, byte_code %p, shader %p.\n", iface, byte_code, shader);
2432
2433     if (!shader)
2434     {
2435         TRACE("(%p) Invalid call\n", This);
2436         return D3DERR_INVALIDCALL;
2437     }
2438
2439     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
2440     if (!object)
2441     {
2442         ERR("Failed to allocate pixel shader memmory.\n");
2443         return E_OUTOFMEMORY;
2444     }
2445
2446     wined3d_mutex_lock();
2447     handle = d3d8_allocate_handle(&This->handle_table, object, D3D8_HANDLE_PS);
2448     wined3d_mutex_unlock();
2449     if (handle == D3D8_INVALID_HANDLE)
2450     {
2451         ERR("Failed to allocate pixel shader handle.\n");
2452         HeapFree(GetProcessHeap(), 0, object);
2453         return E_OUTOFMEMORY;
2454     }
2455
2456     shader_handle = handle + VS_HIGHESTFIXEDFXF + 1;
2457
2458     hr = pixelshader_init(object, This, byte_code, shader_handle);
2459     if (FAILED(hr))
2460     {
2461         WARN("Failed to initialize pixel shader, hr %#x.\n", hr);
2462         wined3d_mutex_lock();
2463         d3d8_free_handle(&This->handle_table, handle, D3D8_HANDLE_PS);
2464         wined3d_mutex_unlock();
2465         HeapFree(GetProcessHeap(), 0, object);
2466         *shader = 0;
2467         return hr;
2468     }
2469
2470     TRACE("Created pixel shader %p (handle %#x).\n", object, shader_handle);
2471     *shader = shader_handle;
2472
2473     return D3D_OK;
2474 }
2475
2476 static HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShader(IDirect3DDevice8 *iface, DWORD pShader)
2477 {
2478     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
2479     IDirect3DPixelShader8Impl *shader;
2480     HRESULT hr;
2481
2482     TRACE("iface %p, shader %#x.\n", iface, pShader);
2483
2484     wined3d_mutex_lock();
2485
2486     if (!pShader)
2487     {
2488         hr = wined3d_device_set_pixel_shader(This->wined3d_device, NULL);
2489         wined3d_mutex_unlock();
2490         return hr;
2491     }
2492
2493     shader = d3d8_get_object(&This->handle_table, pShader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_PS);
2494     if (!shader)
2495     {
2496         WARN("Invalid handle (%#x) passed.\n", pShader);
2497         wined3d_mutex_unlock();
2498         return D3DERR_INVALIDCALL;
2499     }
2500
2501     TRACE("(%p) : Setting shader %p\n", This, shader);
2502     hr = wined3d_device_set_pixel_shader(This->wined3d_device, shader->wined3d_shader);
2503     wined3d_mutex_unlock();
2504
2505     return hr;
2506 }
2507
2508 static HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShader(IDirect3DDevice8 *iface, DWORD *ppShader)
2509 {
2510     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
2511     struct wined3d_shader *object;
2512
2513     TRACE("iface %p, shader %p.\n", iface, ppShader);
2514
2515     if (NULL == ppShader) {
2516         TRACE("(%p) Invalid call\n", This);
2517         return D3DERR_INVALIDCALL;
2518     }
2519
2520     wined3d_mutex_lock();
2521     object = wined3d_device_get_pixel_shader(This->wined3d_device);
2522     if (object)
2523     {
2524         IDirect3DPixelShader8Impl *d3d8_shader;
2525         d3d8_shader = wined3d_shader_get_parent(object);
2526         wined3d_shader_decref(object);
2527         *ppShader = d3d8_shader->handle;
2528     }
2529     else
2530     {
2531         *ppShader = 0;
2532     }
2533     wined3d_mutex_unlock();
2534
2535     TRACE("(%p) : returning %#x\n", This, *ppShader);
2536
2537     return D3D_OK;
2538 }
2539
2540 static HRESULT WINAPI IDirect3DDevice8Impl_DeletePixelShader(IDirect3DDevice8 *iface, DWORD pShader)
2541 {
2542     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
2543     IDirect3DPixelShader8Impl *shader;
2544     struct wined3d_shader *cur;
2545
2546     TRACE("iface %p, shader %#x.\n", iface, pShader);
2547
2548     wined3d_mutex_lock();
2549
2550     shader = d3d8_free_handle(&This->handle_table, pShader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_PS);
2551     if (!shader)
2552     {
2553         WARN("Invalid handle (%#x) passed.\n", pShader);
2554         wined3d_mutex_unlock();
2555         return D3DERR_INVALIDCALL;
2556     }
2557
2558     cur = wined3d_device_get_pixel_shader(This->wined3d_device);
2559     if (cur)
2560     {
2561         if (cur == shader->wined3d_shader)
2562             IDirect3DDevice8_SetPixelShader(iface, 0);
2563         wined3d_shader_decref(cur);
2564     }
2565
2566     wined3d_mutex_unlock();
2567
2568     if (IDirect3DPixelShader8_Release(&shader->IDirect3DPixelShader8_iface))
2569     {
2570         ERR("Shader %p has references left, this shouldn't happen.\n", shader);
2571     }
2572
2573     return D3D_OK;
2574 }
2575
2576 static HRESULT  WINAPI  IDirect3DDevice8Impl_SetPixelShaderConstant(IDirect3DDevice8 *iface,
2577         DWORD Register, const void *pConstantData, DWORD ConstantCount)
2578 {
2579     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
2580     HRESULT hr;
2581
2582     TRACE("iface %p, register %u, data %p, count %u.\n",
2583             iface, Register, pConstantData, ConstantCount);
2584
2585     wined3d_mutex_lock();
2586     hr = wined3d_device_set_ps_consts_f(This->wined3d_device, Register, pConstantData, ConstantCount);
2587     wined3d_mutex_unlock();
2588
2589     return hr;
2590 }
2591
2592 static HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderConstant(IDirect3DDevice8 *iface,
2593         DWORD Register, void *pConstantData, DWORD ConstantCount)
2594 {
2595     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
2596     HRESULT hr;
2597
2598     TRACE("iface %p, register %u, data %p, count %u.\n",
2599             iface, Register, pConstantData, ConstantCount);
2600
2601     wined3d_mutex_lock();
2602     hr = wined3d_device_get_ps_consts_f(This->wined3d_device, Register, pConstantData, ConstantCount);
2603     wined3d_mutex_unlock();
2604
2605     return hr;
2606 }
2607
2608 static HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderFunction(IDirect3DDevice8 *iface,
2609         DWORD pPixelShader, void *pData, DWORD *pSizeOfData)
2610 {
2611     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
2612     IDirect3DPixelShader8Impl *shader = NULL;
2613     HRESULT hr;
2614
2615     TRACE("iface %p, shader %#x, data %p, data_size %p.\n",
2616             iface, pPixelShader, pData, pSizeOfData);
2617
2618     wined3d_mutex_lock();
2619     shader = d3d8_get_object(&This->handle_table, pPixelShader - (VS_HIGHESTFIXEDFXF + 1), D3D8_HANDLE_PS);
2620     if (!shader)
2621     {
2622         WARN("Invalid handle (%#x) passed.\n", pPixelShader);
2623         wined3d_mutex_unlock();
2624
2625         return D3DERR_INVALIDCALL;
2626     }
2627
2628     hr = wined3d_shader_get_byte_code(shader->wined3d_shader, pData, pSizeOfData);
2629     wined3d_mutex_unlock();
2630
2631     return hr;
2632 }
2633
2634 static HRESULT WINAPI IDirect3DDevice8Impl_DrawRectPatch(IDirect3DDevice8 *iface, UINT Handle,
2635         const float *pNumSegs, const D3DRECTPATCH_INFO *pRectPatchInfo)
2636 {
2637     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
2638     HRESULT hr;
2639
2640     TRACE("iface %p, handle %#x, segment_count %p, patch_info %p.\n",
2641             iface, Handle, pNumSegs, pRectPatchInfo);
2642
2643     wined3d_mutex_lock();
2644     hr = wined3d_device_draw_rect_patch(This->wined3d_device, Handle,
2645             pNumSegs, (const WINED3DRECTPATCH_INFO *)pRectPatchInfo);
2646     wined3d_mutex_unlock();
2647
2648     return hr;
2649 }
2650
2651 static HRESULT WINAPI IDirect3DDevice8Impl_DrawTriPatch(IDirect3DDevice8 *iface, UINT Handle,
2652         const float *pNumSegs, const D3DTRIPATCH_INFO *pTriPatchInfo)
2653 {
2654     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
2655     HRESULT hr;
2656
2657     TRACE("iface %p, handle %#x, segment_count %p, patch_info %p.\n",
2658             iface, Handle, pNumSegs, pTriPatchInfo);
2659
2660     wined3d_mutex_lock();
2661     hr = wined3d_device_draw_tri_patch(This->wined3d_device, Handle,
2662             pNumSegs, (const WINED3DTRIPATCH_INFO *)pTriPatchInfo);
2663     wined3d_mutex_unlock();
2664
2665     return hr;
2666 }
2667
2668 static HRESULT WINAPI IDirect3DDevice8Impl_DeletePatch(IDirect3DDevice8 *iface, UINT Handle)
2669 {
2670     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
2671     HRESULT hr;
2672
2673     TRACE("iface %p, handle %#x.\n", iface, Handle);
2674
2675     wined3d_mutex_lock();
2676     hr = wined3d_device_delete_patch(This->wined3d_device, Handle);
2677     wined3d_mutex_unlock();
2678
2679     return hr;
2680 }
2681
2682 static HRESULT WINAPI IDirect3DDevice8Impl_SetStreamSource(IDirect3DDevice8 *iface,
2683         UINT StreamNumber, IDirect3DVertexBuffer8 *pStreamData, UINT Stride)
2684 {
2685     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
2686     HRESULT hr;
2687
2688     TRACE("iface %p, stream_idx %u, buffer %p, stride %u.\n",
2689             iface, StreamNumber, pStreamData, Stride);
2690
2691     wined3d_mutex_lock();
2692     hr = wined3d_device_set_stream_source(This->wined3d_device, StreamNumber,
2693             pStreamData ? ((IDirect3DVertexBuffer8Impl *)pStreamData)->wineD3DVertexBuffer : NULL,
2694             0/* Offset in bytes */, Stride);
2695     wined3d_mutex_unlock();
2696
2697     return hr;
2698 }
2699
2700 static HRESULT WINAPI IDirect3DDevice8Impl_GetStreamSource(IDirect3DDevice8 *iface,
2701         UINT StreamNumber, IDirect3DVertexBuffer8 **pStream, UINT *pStride)
2702 {
2703     IDirect3DDevice8Impl *This = impl_from_IDirect3DDevice8(iface);
2704     struct wined3d_buffer *retStream = NULL;
2705     HRESULT hr;
2706
2707     TRACE("iface %p, stream_idx %u, buffer %p, stride %p.\n",
2708             iface, StreamNumber, pStream, pStride);
2709
2710     if(pStream == NULL){
2711         return D3DERR_INVALIDCALL;
2712     }
2713
2714     wined3d_mutex_lock();
2715     hr = wined3d_device_get_stream_source(This->wined3d_device, StreamNumber,
2716             &retStream, 0 /* Offset in bytes */, pStride);
2717     if (SUCCEEDED(hr) && retStream)
2718     {
2719         *pStream = wined3d_buffer_get_parent(retStream);
2720         IDirect3DVertexBuffer8_AddRef(*pStream);
2721         wined3d_buffer_decref(retStream);
2722     }
2723     else
2724     {
2725         if (FAILED(hr)) FIXME("Call to GetStreamSource failed, hr %#x.\n", hr);
2726         *pStream = NULL;
2727     }
2728     wined3d_mutex_unlock();
2729
2730     return hr;
2731 }
2732
2733 static const IDirect3DDevice8Vtbl Direct3DDevice8_Vtbl =
2734 {
2735     IDirect3DDevice8Impl_QueryInterface,
2736     IDirect3DDevice8Impl_AddRef,
2737     IDirect3DDevice8Impl_Release,
2738     IDirect3DDevice8Impl_TestCooperativeLevel,
2739     IDirect3DDevice8Impl_GetAvailableTextureMem,
2740     IDirect3DDevice8Impl_ResourceManagerDiscardBytes,
2741     IDirect3DDevice8Impl_GetDirect3D,
2742     IDirect3DDevice8Impl_GetDeviceCaps,
2743     IDirect3DDevice8Impl_GetDisplayMode,
2744     IDirect3DDevice8Impl_GetCreationParameters,
2745     IDirect3DDevice8Impl_SetCursorProperties,
2746     IDirect3DDevice8Impl_SetCursorPosition,
2747     IDirect3DDevice8Impl_ShowCursor,
2748     IDirect3DDevice8Impl_CreateAdditionalSwapChain,
2749     IDirect3DDevice8Impl_Reset,
2750     IDirect3DDevice8Impl_Present,
2751     IDirect3DDevice8Impl_GetBackBuffer,
2752     IDirect3DDevice8Impl_GetRasterStatus,
2753     IDirect3DDevice8Impl_SetGammaRamp,
2754     IDirect3DDevice8Impl_GetGammaRamp,
2755     IDirect3DDevice8Impl_CreateTexture,
2756     IDirect3DDevice8Impl_CreateVolumeTexture,
2757     IDirect3DDevice8Impl_CreateCubeTexture,
2758     IDirect3DDevice8Impl_CreateVertexBuffer,
2759     IDirect3DDevice8Impl_CreateIndexBuffer,
2760     IDirect3DDevice8Impl_CreateRenderTarget,
2761     IDirect3DDevice8Impl_CreateDepthStencilSurface,
2762     IDirect3DDevice8Impl_CreateImageSurface,
2763     IDirect3DDevice8Impl_CopyRects,
2764     IDirect3DDevice8Impl_UpdateTexture,
2765     IDirect3DDevice8Impl_GetFrontBuffer,
2766     IDirect3DDevice8Impl_SetRenderTarget,
2767     IDirect3DDevice8Impl_GetRenderTarget,
2768     IDirect3DDevice8Impl_GetDepthStencilSurface,
2769     IDirect3DDevice8Impl_BeginScene,
2770     IDirect3DDevice8Impl_EndScene,
2771     IDirect3DDevice8Impl_Clear,
2772     IDirect3DDevice8Impl_SetTransform,
2773     IDirect3DDevice8Impl_GetTransform,
2774     IDirect3DDevice8Impl_MultiplyTransform,
2775     IDirect3DDevice8Impl_SetViewport,
2776     IDirect3DDevice8Impl_GetViewport,
2777     IDirect3DDevice8Impl_SetMaterial,
2778     IDirect3DDevice8Impl_GetMaterial,
2779     IDirect3DDevice8Impl_SetLight,
2780     IDirect3DDevice8Impl_GetLight,
2781     IDirect3DDevice8Impl_LightEnable,
2782     IDirect3DDevice8Impl_GetLightEnable,
2783     IDirect3DDevice8Impl_SetClipPlane,
2784     IDirect3DDevice8Impl_GetClipPlane,
2785     IDirect3DDevice8Impl_SetRenderState,
2786     IDirect3DDevice8Impl_GetRenderState,
2787     IDirect3DDevice8Impl_BeginStateBlock,
2788     IDirect3DDevice8Impl_EndStateBlock,
2789     IDirect3DDevice8Impl_ApplyStateBlock,
2790     IDirect3DDevice8Impl_CaptureStateBlock,
2791     IDirect3DDevice8Impl_DeleteStateBlock,
2792     IDirect3DDevice8Impl_CreateStateBlock,
2793     IDirect3DDevice8Impl_SetClipStatus,
2794     IDirect3DDevice8Impl_GetClipStatus,
2795     IDirect3DDevice8Impl_GetTexture,
2796     IDirect3DDevice8Impl_SetTexture,
2797     IDirect3DDevice8Impl_GetTextureStageState,
2798     IDirect3DDevice8Impl_SetTextureStageState,
2799     IDirect3DDevice8Impl_ValidateDevice,
2800     IDirect3DDevice8Impl_GetInfo,
2801     IDirect3DDevice8Impl_SetPaletteEntries,
2802     IDirect3DDevice8Impl_GetPaletteEntries,
2803     IDirect3DDevice8Impl_SetCurrentTexturePalette,
2804     IDirect3DDevice8Impl_GetCurrentTexturePalette,
2805     IDirect3DDevice8Impl_DrawPrimitive,
2806     IDirect3DDevice8Impl_DrawIndexedPrimitive,
2807     IDirect3DDevice8Impl_DrawPrimitiveUP,
2808     IDirect3DDevice8Impl_DrawIndexedPrimitiveUP,
2809     IDirect3DDevice8Impl_ProcessVertices,
2810     IDirect3DDevice8Impl_CreateVertexShader,
2811     IDirect3DDevice8Impl_SetVertexShader,
2812     IDirect3DDevice8Impl_GetVertexShader,
2813     IDirect3DDevice8Impl_DeleteVertexShader,
2814     IDirect3DDevice8Impl_SetVertexShaderConstant,
2815     IDirect3DDevice8Impl_GetVertexShaderConstant,
2816     IDirect3DDevice8Impl_GetVertexShaderDeclaration,
2817     IDirect3DDevice8Impl_GetVertexShaderFunction,
2818     IDirect3DDevice8Impl_SetStreamSource,
2819     IDirect3DDevice8Impl_GetStreamSource,
2820     IDirect3DDevice8Impl_SetIndices,
2821     IDirect3DDevice8Impl_GetIndices,
2822     IDirect3DDevice8Impl_CreatePixelShader,
2823     IDirect3DDevice8Impl_SetPixelShader,
2824     IDirect3DDevice8Impl_GetPixelShader,
2825     IDirect3DDevice8Impl_DeletePixelShader,
2826     IDirect3DDevice8Impl_SetPixelShaderConstant,
2827     IDirect3DDevice8Impl_GetPixelShaderConstant,
2828     IDirect3DDevice8Impl_GetPixelShaderFunction,
2829     IDirect3DDevice8Impl_DrawRectPatch,
2830     IDirect3DDevice8Impl_DrawTriPatch,
2831     IDirect3DDevice8Impl_DeletePatch
2832 };
2833
2834 static inline IDirect3DDevice8Impl *device_from_device_parent(struct wined3d_device_parent *device_parent)
2835 {
2836     return CONTAINING_RECORD(device_parent, IDirect3DDevice8Impl, device_parent);
2837 }
2838
2839 static void CDECL device_parent_wined3d_device_created(struct wined3d_device_parent *device_parent,
2840         struct wined3d_device *device)
2841 {
2842     TRACE("device_parent %p, device %p\n", device_parent, device);
2843 }
2844
2845 static HRESULT CDECL device_parent_create_surface(struct wined3d_device_parent *device_parent,
2846         void *container_parent, UINT width, UINT height, enum wined3d_format_id format, DWORD usage,
2847         WINED3DPOOL pool, UINT level, WINED3DCUBEMAP_FACES face, struct wined3d_surface **surface)
2848 {
2849     IDirect3DDevice8Impl *device = device_from_device_parent(device_parent);
2850     IDirect3DSurface8Impl *d3d_surface;
2851     BOOL lockable = TRUE;
2852     HRESULT hr;
2853
2854     TRACE("device_parent %p, container_parent %p, width %u, height %u, format %#x, usage %#x,\n"
2855             "\tpool %#x, level %u, face %u, surface %p.\n",
2856             device_parent, container_parent, width, height, format, usage, pool, level, face, surface);
2857
2858
2859     if (pool == WINED3DPOOL_DEFAULT && !(usage & WINED3DUSAGE_DYNAMIC)) lockable = FALSE;
2860
2861     hr = IDirect3DDevice8Impl_CreateSurface(device, width, height,
2862             d3dformat_from_wined3dformat(format), lockable, FALSE /* Discard */, level,
2863             (IDirect3DSurface8 **)&d3d_surface, usage, pool, D3DMULTISAMPLE_NONE, 0 /* MultisampleQuality */);
2864     if (FAILED(hr))
2865     {
2866         WARN("Failed to create surface, hr %#x.\n", hr);
2867         return hr;
2868     }
2869
2870     *surface = d3d_surface->wined3d_surface;
2871     wined3d_surface_incref(*surface);
2872
2873     d3d_surface->container = container_parent;
2874     IUnknown_Release(d3d_surface->parentDevice);
2875     d3d_surface->parentDevice = NULL;
2876
2877     IDirect3DSurface8_Release(&d3d_surface->IDirect3DSurface8_iface);
2878     d3d_surface->forwardReference = container_parent;
2879
2880     return hr;
2881 }
2882
2883 static HRESULT CDECL device_parent_create_rendertarget(struct wined3d_device_parent *device_parent,
2884         void *container_parent, UINT width, UINT height, enum wined3d_format_id format,
2885         WINED3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality, BOOL lockable,
2886         struct wined3d_surface **surface)
2887 {
2888     IDirect3DDevice8Impl *device = device_from_device_parent(device_parent);
2889     IDirect3DSurface8Impl *d3d_surface;
2890     HRESULT hr;
2891
2892     TRACE("device_parent %p, container_parent %p, width %u, height %u, format %#x, multisample_type %#x,\n"
2893             "\tmultisample_quality %u, lockable %u, surface %p.\n",
2894             device_parent, container_parent, width, height, format,
2895             multisample_type, multisample_quality, lockable, surface);
2896
2897     hr = IDirect3DDevice8_CreateRenderTarget(&device->IDirect3DDevice8_iface, width, height,
2898             d3dformat_from_wined3dformat(format), multisample_type, lockable, (IDirect3DSurface8 **)&d3d_surface);
2899     if (FAILED(hr))
2900     {
2901         WARN("Failed to create rendertarget, hr %#x.\n", hr);
2902         return hr;
2903     }
2904
2905     *surface = d3d_surface->wined3d_surface;
2906     wined3d_surface_incref(*surface);
2907
2908     d3d_surface->container = (IUnknown *)&device->IDirect3DDevice8_iface;
2909     /* Implicit surfaces are created with an refcount of 0 */
2910     IDirect3DSurface8_Release(&d3d_surface->IDirect3DSurface8_iface);
2911
2912     return hr;
2913 }
2914
2915 static HRESULT CDECL device_parent_create_depth_stencil(struct wined3d_device_parent *device_parent,
2916         UINT width, UINT height, enum wined3d_format_id format, WINED3DMULTISAMPLE_TYPE multisample_type,
2917         DWORD multisample_quality, BOOL discard, struct wined3d_surface **surface)
2918 {
2919     IDirect3DDevice8Impl *device = device_from_device_parent(device_parent);
2920     IDirect3DSurface8Impl *d3d_surface;
2921     HRESULT hr;
2922
2923     TRACE("device_parent %p, width %u, height %u, format %#x, multisample_type %#x,\n"
2924             "\tmultisample_quality %u, discard %u, surface %p.\n",
2925             device_parent, width, height, format, multisample_type, multisample_quality, discard, surface);
2926
2927     hr = IDirect3DDevice8_CreateDepthStencilSurface(&device->IDirect3DDevice8_iface, width, height,
2928             d3dformat_from_wined3dformat(format), multisample_type, (IDirect3DSurface8 **)&d3d_surface);
2929     if (FAILED(hr))
2930     {
2931         WARN("Failed to create depth/stencil surface, hr %#x.\n", hr);
2932         return hr;
2933     }
2934
2935     *surface = d3d_surface->wined3d_surface;
2936     wined3d_surface_incref(*surface);
2937
2938     d3d_surface->container = (IUnknown *)&device->IDirect3DDevice8_iface;
2939     /* Implicit surfaces are created with an refcount of 0 */
2940     IDirect3DSurface8_Release(&d3d_surface->IDirect3DSurface8_iface);
2941
2942     return hr;
2943 }
2944
2945 static HRESULT CDECL device_parent_create_volume(struct wined3d_device_parent *device_parent,
2946         void *container_parent, UINT width, UINT height, UINT depth, enum wined3d_format_id format,
2947         WINED3DPOOL pool, DWORD usage, struct wined3d_volume **volume)
2948 {
2949     IDirect3DDevice8Impl *device = device_from_device_parent(device_parent);
2950     IDirect3DVolume8Impl *object;
2951     HRESULT hr;
2952
2953     TRACE("device_parent %p, container_parent %p, width %u, height %u, depth %u, "
2954             "format %#x, pool %#x, usage %#x, volume %p.\n",
2955             device_parent, container_parent, width, height, depth,
2956             format, pool, usage, volume);
2957
2958     /* Allocate the storage for the device */
2959     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
2960     if (!object)
2961     {
2962         FIXME("Allocation of memory failed\n");
2963         *volume = NULL;
2964         return D3DERR_OUTOFVIDEOMEMORY;
2965     }
2966
2967     hr = volume_init(object, device, width, height, depth, usage, format, pool);
2968     if (FAILED(hr))
2969     {
2970         WARN("Failed to initialize volume, hr %#x.\n", hr);
2971         HeapFree(GetProcessHeap(), 0, object);
2972         return hr;
2973     }
2974
2975     *volume = object->wined3d_volume;
2976     wined3d_volume_incref(*volume);
2977     IDirect3DVolume8_Release(&object->IDirect3DVolume8_iface);
2978
2979     object->container = container_parent;
2980     object->forwardReference = container_parent;
2981
2982     TRACE("Created volume %p.\n", object);
2983
2984     return hr;
2985 }
2986
2987 static HRESULT CDECL device_parent_create_swapchain(struct wined3d_device_parent *device_parent,
2988         WINED3DPRESENT_PARAMETERS *present_parameters, struct wined3d_swapchain **swapchain)
2989 {
2990     IDirect3DDevice8Impl *device = device_from_device_parent(device_parent);
2991     D3DPRESENT_PARAMETERS local_parameters;
2992     IDirect3DSwapChain8 *d3d_swapchain;
2993     HRESULT hr;
2994
2995     TRACE("device_parent %p, present_parameters %p, swapchain %p.\n", device_parent, present_parameters, swapchain);
2996
2997     /* Copy the presentation parameters */
2998     local_parameters.BackBufferWidth = present_parameters->BackBufferWidth;
2999     local_parameters.BackBufferHeight = present_parameters->BackBufferHeight;
3000     local_parameters.BackBufferFormat = d3dformat_from_wined3dformat(present_parameters->BackBufferFormat);
3001     local_parameters.BackBufferCount = present_parameters->BackBufferCount;
3002     local_parameters.MultiSampleType = present_parameters->MultiSampleType;
3003     local_parameters.SwapEffect = present_parameters->SwapEffect;
3004     local_parameters.hDeviceWindow = present_parameters->hDeviceWindow;
3005     local_parameters.Windowed = present_parameters->Windowed;
3006     local_parameters.EnableAutoDepthStencil = present_parameters->EnableAutoDepthStencil;
3007     local_parameters.AutoDepthStencilFormat = d3dformat_from_wined3dformat(present_parameters->AutoDepthStencilFormat);
3008     local_parameters.Flags = present_parameters->Flags;
3009     local_parameters.FullScreen_RefreshRateInHz = present_parameters->FullScreen_RefreshRateInHz;
3010     local_parameters.FullScreen_PresentationInterval = present_parameters->PresentationInterval;
3011
3012     hr = IDirect3DDevice8_CreateAdditionalSwapChain(&device->IDirect3DDevice8_iface,
3013             &local_parameters, &d3d_swapchain);
3014     if (FAILED(hr))
3015     {
3016         WARN("Failed to create swapchain, hr %#x.\n", hr);
3017         *swapchain = NULL;
3018         return hr;
3019     }
3020
3021     *swapchain = ((IDirect3DSwapChain8Impl *)d3d_swapchain)->wined3d_swapchain;
3022     wined3d_swapchain_incref(*swapchain);
3023     IDirect3DSwapChain8_Release(d3d_swapchain);
3024
3025     /* Copy back the presentation parameters */
3026     present_parameters->BackBufferWidth = local_parameters.BackBufferWidth;
3027     present_parameters->BackBufferHeight = local_parameters.BackBufferHeight;
3028     present_parameters->BackBufferFormat = wined3dformat_from_d3dformat(local_parameters.BackBufferFormat);
3029     present_parameters->BackBufferCount = local_parameters.BackBufferCount;
3030     present_parameters->MultiSampleType = local_parameters.MultiSampleType;
3031     present_parameters->SwapEffect = local_parameters.SwapEffect;
3032     present_parameters->hDeviceWindow = local_parameters.hDeviceWindow;
3033     present_parameters->Windowed = local_parameters.Windowed;
3034     present_parameters->EnableAutoDepthStencil = local_parameters.EnableAutoDepthStencil;
3035     present_parameters->AutoDepthStencilFormat = wined3dformat_from_d3dformat(local_parameters.AutoDepthStencilFormat);
3036     present_parameters->Flags = local_parameters.Flags;
3037     present_parameters->FullScreen_RefreshRateInHz = local_parameters.FullScreen_RefreshRateInHz;
3038     present_parameters->PresentationInterval = local_parameters.FullScreen_PresentationInterval;
3039
3040     return hr;
3041 }
3042
3043 static const struct wined3d_device_parent_ops d3d8_wined3d_device_parent_ops =
3044 {
3045     device_parent_wined3d_device_created,
3046     device_parent_create_surface,
3047     device_parent_create_rendertarget,
3048     device_parent_create_depth_stencil,
3049     device_parent_create_volume,
3050     device_parent_create_swapchain,
3051 };
3052
3053 static void setup_fpu(void)
3054 {
3055 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3056     WORD cw;
3057     __asm__ volatile ("fnstcw %0" : "=m" (cw));
3058     cw = (cw & ~0xf3f) | 0x3f;
3059     __asm__ volatile ("fldcw %0" : : "m" (cw));
3060 #else
3061     FIXME("FPU setup not implemented for this platform.\n");
3062 #endif
3063 }
3064
3065 HRESULT device_init(IDirect3DDevice8Impl *device, IDirect3D8Impl *parent, struct wined3d *wined3d, UINT adapter,
3066         D3DDEVTYPE device_type, HWND focus_window, DWORD flags, D3DPRESENT_PARAMETERS *parameters)
3067 {
3068     WINED3DPRESENT_PARAMETERS wined3d_parameters;
3069     HRESULT hr;
3070
3071     device->IDirect3DDevice8_iface.lpVtbl = &Direct3DDevice8_Vtbl;
3072     device->device_parent.ops = &d3d8_wined3d_device_parent_ops;
3073     device->ref = 1;
3074     device->handle_table.entries = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3075             D3D8_INITIAL_HANDLE_TABLE_SIZE * sizeof(*device->handle_table.entries));
3076     if (!device->handle_table.entries)
3077     {
3078         ERR("Failed to allocate handle table memory.\n");
3079         return E_OUTOFMEMORY;
3080     }
3081     device->handle_table.table_size = D3D8_INITIAL_HANDLE_TABLE_SIZE;
3082
3083     if (!(flags & D3DCREATE_FPU_PRESERVE)) setup_fpu();
3084
3085     wined3d_mutex_lock();
3086     hr = wined3d_device_create(wined3d, adapter, device_type, focus_window, flags, 4,
3087             &device->device_parent, &device->wined3d_device);
3088     if (FAILED(hr))
3089     {
3090         WARN("Failed to create wined3d device, hr %#x.\n", hr);
3091         wined3d_mutex_unlock();
3092         HeapFree(GetProcessHeap(), 0, device->handle_table.entries);
3093         return hr;
3094     }
3095
3096     if (!parameters->Windowed)
3097     {
3098         HWND device_window = parameters->hDeviceWindow;
3099
3100         if (!focus_window)
3101             focus_window = device_window;
3102         if (FAILED(hr = wined3d_device_acquire_focus_window(device->wined3d_device, focus_window)))
3103         {
3104             ERR("Failed to acquire focus window, hr %#x.\n", hr);
3105             wined3d_device_decref(device->wined3d_device);
3106             wined3d_mutex_unlock();
3107             HeapFree(GetProcessHeap(), 0, device->handle_table.entries);
3108             return hr;
3109         }
3110
3111         if (!device_window)
3112             device_window = focus_window;
3113         wined3d_device_setup_fullscreen_window(device->wined3d_device, device_window,
3114                 parameters->BackBufferWidth,
3115                 parameters->BackBufferHeight);
3116     }
3117
3118     if (flags & D3DCREATE_MULTITHREADED)
3119         wined3d_device_set_multithreaded(device->wined3d_device);
3120
3121     wined3d_parameters.BackBufferWidth = parameters->BackBufferWidth;
3122     wined3d_parameters.BackBufferHeight = parameters->BackBufferHeight;
3123     wined3d_parameters.BackBufferFormat = wined3dformat_from_d3dformat(parameters->BackBufferFormat);
3124     wined3d_parameters.BackBufferCount = parameters->BackBufferCount;
3125     wined3d_parameters.MultiSampleType = parameters->MultiSampleType;
3126     wined3d_parameters.MultiSampleQuality = 0; /* d3d9 only */
3127     wined3d_parameters.SwapEffect = parameters->SwapEffect;
3128     wined3d_parameters.hDeviceWindow = parameters->hDeviceWindow;
3129     wined3d_parameters.Windowed = parameters->Windowed;
3130     wined3d_parameters.EnableAutoDepthStencil = parameters->EnableAutoDepthStencil;
3131     wined3d_parameters.AutoDepthStencilFormat = wined3dformat_from_d3dformat(parameters->AutoDepthStencilFormat);
3132     wined3d_parameters.Flags = parameters->Flags;
3133     wined3d_parameters.FullScreen_RefreshRateInHz = parameters->FullScreen_RefreshRateInHz;
3134     wined3d_parameters.PresentationInterval = parameters->FullScreen_PresentationInterval;
3135     wined3d_parameters.AutoRestoreDisplayMode = TRUE;
3136
3137     hr = wined3d_device_init_3d(device->wined3d_device, &wined3d_parameters);
3138     if (FAILED(hr))
3139     {
3140         WARN("Failed to initialize 3D, hr %#x.\n", hr);
3141         wined3d_device_release_focus_window(device->wined3d_device);
3142         wined3d_device_decref(device->wined3d_device);
3143         wined3d_mutex_unlock();
3144         HeapFree(GetProcessHeap(), 0, device->handle_table.entries);
3145         return hr;
3146     }
3147
3148     hr = wined3d_device_set_render_state(device->wined3d_device, WINED3DRS_POINTSIZE_MIN, 0);
3149     wined3d_mutex_unlock();
3150     if (FAILED(hr))
3151     {
3152         ERR("Failed to set minimum pointsize, hr %#x.\n", hr);
3153         goto err;
3154     }
3155
3156     parameters->BackBufferWidth = wined3d_parameters.BackBufferWidth;
3157     parameters->BackBufferHeight = wined3d_parameters.BackBufferHeight;
3158     parameters->BackBufferFormat = d3dformat_from_wined3dformat(wined3d_parameters.BackBufferFormat);
3159     parameters->BackBufferCount = wined3d_parameters.BackBufferCount;
3160     parameters->MultiSampleType = wined3d_parameters.MultiSampleType;
3161     parameters->SwapEffect = wined3d_parameters.SwapEffect;
3162     parameters->hDeviceWindow = wined3d_parameters.hDeviceWindow;
3163     parameters->Windowed = wined3d_parameters.Windowed;
3164     parameters->EnableAutoDepthStencil = wined3d_parameters.EnableAutoDepthStencil;
3165     parameters->AutoDepthStencilFormat = d3dformat_from_wined3dformat(wined3d_parameters.AutoDepthStencilFormat);
3166     parameters->Flags = wined3d_parameters.Flags;
3167     parameters->FullScreen_RefreshRateInHz = wined3d_parameters.FullScreen_RefreshRateInHz;
3168     parameters->FullScreen_PresentationInterval = wined3d_parameters.PresentationInterval;
3169
3170     device->declArraySize = 16;
3171     device->decls = HeapAlloc(GetProcessHeap(), 0, device->declArraySize * sizeof(*device->decls));
3172     if (!device->decls)
3173     {
3174         ERR("Failed to allocate FVF vertex delcaration map memory.\n");
3175         hr = E_OUTOFMEMORY;
3176         goto err;
3177     }
3178
3179     device->d3d_parent = &parent->IDirect3D8_iface;
3180     IDirect3D8_AddRef(device->d3d_parent);
3181
3182     return D3D_OK;
3183
3184 err:
3185     wined3d_mutex_lock();
3186     wined3d_device_uninit_3d(device->wined3d_device);
3187     wined3d_device_release_focus_window(device->wined3d_device);
3188     wined3d_device_decref(device->wined3d_device);
3189     wined3d_mutex_unlock();
3190     HeapFree(GetProcessHeap(), 0, device->handle_table.entries);
3191     return hr;
3192 }