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