xref: /reactos/dll/directx/wine/d3d9/directx.c (revision bd712186)
1 /*
2  * IDirect3D9 implementation
3  *
4  * Copyright 2002 Jason Edmeades
5  * Copyright 2005 Oliver Stieber
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21 
22 #include "config.h"
23 #include "d3d9_private.h"
24 
25 WINE_DEFAULT_DEBUG_CHANNEL(d3d9);
26 
27 static inline struct d3d9 *impl_from_IDirect3D9Ex(IDirect3D9Ex *iface)
28 {
29     return CONTAINING_RECORD(iface, struct d3d9, IDirect3D9Ex_iface);
30 }
31 
32 static HRESULT WINAPI d3d9_QueryInterface(IDirect3D9Ex *iface, REFIID riid, void **out)
33 {
34     struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
35 
36     TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
37 
38     if (IsEqualGUID(riid, &IID_IDirect3D9)
39             || IsEqualGUID(riid, &IID_IUnknown))
40     {
41         IDirect3D9Ex_AddRef(&d3d9->IDirect3D9Ex_iface);
42         *out = &d3d9->IDirect3D9Ex_iface;
43         return S_OK;
44     }
45 
46     if (IsEqualGUID(riid, &IID_IDirect3D9Ex))
47     {
48         if (!d3d9->extended)
49         {
50             WARN("Application asks for IDirect3D9Ex, but this instance wasn't created with Direct3DCreate9Ex.\n");
51             *out = NULL;
52             return E_NOINTERFACE;
53         }
54 
55         IDirect3D9Ex_AddRef(&d3d9->IDirect3D9Ex_iface);
56         *out = &d3d9->IDirect3D9Ex_iface;
57         return S_OK;
58     }
59 
60     WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
61 
62     *out = NULL;
63     return E_NOINTERFACE;
64 }
65 
66 static ULONG WINAPI d3d9_AddRef(IDirect3D9Ex *iface)
67 {
68     struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
69     ULONG refcount = InterlockedIncrement(&d3d9->refcount);
70 
71     TRACE("%p increasing refcount to %u.\n", iface, refcount);
72 
73     return refcount;
74 }
75 
76 static ULONG WINAPI d3d9_Release(IDirect3D9Ex *iface)
77 {
78     struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
79     ULONG refcount = InterlockedDecrement(&d3d9->refcount);
80 
81     TRACE("%p decreasing refcount to %u.\n", iface, refcount);
82 
83     if (!refcount)
84     {
85         wined3d_mutex_lock();
86         wined3d_decref(d3d9->wined3d);
87         wined3d_mutex_unlock();
88 
89         heap_free(d3d9);
90     }
91 
92     return refcount;
93 }
94 
95 static HRESULT WINAPI d3d9_RegisterSoftwareDevice(IDirect3D9Ex *iface, void *init_function)
96 {
97     struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
98     HRESULT hr;
99 
100     TRACE("iface %p, init_function %p.\n", iface, init_function);
101 
102     wined3d_mutex_lock();
103     hr = wined3d_register_software_device(d3d9->wined3d, init_function);
104     wined3d_mutex_unlock();
105 
106     return hr;
107 }
108 
109 static UINT WINAPI d3d9_GetAdapterCount(IDirect3D9Ex *iface)
110 {
111     struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
112     UINT ret;
113 
114     TRACE("iface %p.\n", iface);
115 
116     wined3d_mutex_lock();
117     ret = wined3d_get_adapter_count(d3d9->wined3d);
118     wined3d_mutex_unlock();
119 
120     return ret;
121 }
122 
123 static HRESULT WINAPI d3d9_GetAdapterIdentifier(IDirect3D9Ex *iface, UINT adapter,
124         DWORD flags, D3DADAPTER_IDENTIFIER9 *identifier)
125 {
126     struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
127     struct wined3d_adapter_identifier adapter_id;
128     HRESULT hr;
129 
130     TRACE("iface %p, adapter %u, flags %#x, identifier %p.\n",
131             iface, adapter, flags, identifier);
132 
133     adapter_id.driver = identifier->Driver;
134     adapter_id.driver_size = sizeof(identifier->Driver);
135     adapter_id.description = identifier->Description;
136     adapter_id.description_size = sizeof(identifier->Description);
137     adapter_id.device_name = identifier->DeviceName;
138     adapter_id.device_name_size = sizeof(identifier->DeviceName);
139 
140     wined3d_mutex_lock();
141     hr = wined3d_get_adapter_identifier(d3d9->wined3d, adapter, flags, &adapter_id);
142     wined3d_mutex_unlock();
143 
144     identifier->DriverVersion = adapter_id.driver_version;
145     identifier->VendorId = adapter_id.vendor_id;
146     identifier->DeviceId = adapter_id.device_id;
147     identifier->SubSysId = adapter_id.subsystem_id;
148     identifier->Revision = adapter_id.revision;
149     memcpy(&identifier->DeviceIdentifier, &adapter_id.device_identifier, sizeof(identifier->DeviceIdentifier));
150     identifier->WHQLLevel = adapter_id.whql_level;
151 
152     return hr;
153 }
154 
155 static UINT WINAPI d3d9_GetAdapterModeCount(IDirect3D9Ex *iface, UINT adapter, D3DFORMAT format)
156 {
157     struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
158     UINT ret;
159 
160     TRACE("iface %p, adapter %u, format %#x.\n", iface, adapter, format);
161 
162     /* Others than that not supported by d3d9, but reported by wined3d for ddraw. Filter them out. */
163     if (format != D3DFMT_X8R8G8B8 && format != D3DFMT_R5G6B5)
164         return 0;
165 
166     wined3d_mutex_lock();
167     ret = wined3d_get_adapter_mode_count(d3d9->wined3d, adapter,
168             wined3dformat_from_d3dformat(format), WINED3D_SCANLINE_ORDERING_UNKNOWN);
169     wined3d_mutex_unlock();
170 
171     return ret;
172 }
173 
174 static HRESULT WINAPI d3d9_EnumAdapterModes(IDirect3D9Ex *iface, UINT adapter,
175         D3DFORMAT format, UINT mode_idx, D3DDISPLAYMODE *mode)
176 {
177     struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
178     struct wined3d_display_mode wined3d_mode;
179     HRESULT hr;
180 
181     TRACE("iface %p, adapter %u, format %#x, mode_idx %u, mode %p.\n",
182             iface, adapter, format, mode_idx, mode);
183 
184     if (format != D3DFMT_X8R8G8B8 && format != D3DFMT_R5G6B5)
185         return D3DERR_INVALIDCALL;
186 
187     wined3d_mutex_lock();
188     hr = wined3d_enum_adapter_modes(d3d9->wined3d, adapter, wined3dformat_from_d3dformat(format),
189             WINED3D_SCANLINE_ORDERING_UNKNOWN, mode_idx, &wined3d_mode);
190     wined3d_mutex_unlock();
191 
192     if (SUCCEEDED(hr))
193     {
194         mode->Width = wined3d_mode.width;
195         mode->Height = wined3d_mode.height;
196         mode->RefreshRate = wined3d_mode.refresh_rate;
197         mode->Format = d3dformat_from_wined3dformat(wined3d_mode.format_id);
198     }
199 
200     return hr;
201 }
202 
203 static HRESULT WINAPI d3d9_GetAdapterDisplayMode(IDirect3D9Ex *iface, UINT adapter, D3DDISPLAYMODE *mode)
204 {
205     struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
206     struct wined3d_display_mode wined3d_mode;
207     HRESULT hr;
208 
209     TRACE("iface %p, adapter %u, mode %p.\n", iface, adapter, mode);
210 
211     wined3d_mutex_lock();
212     hr = wined3d_get_adapter_display_mode(d3d9->wined3d, adapter, &wined3d_mode, NULL);
213     wined3d_mutex_unlock();
214 
215     if (SUCCEEDED(hr))
216     {
217         mode->Width = wined3d_mode.width;
218         mode->Height = wined3d_mode.height;
219         mode->RefreshRate = wined3d_mode.refresh_rate;
220         mode->Format = d3dformat_from_wined3dformat(wined3d_mode.format_id);
221     }
222 
223     return hr;
224 }
225 
226 static HRESULT WINAPI d3d9_CheckDeviceType(IDirect3D9Ex *iface, UINT adapter, D3DDEVTYPE device_type,
227         D3DFORMAT display_format, D3DFORMAT backbuffer_format, BOOL windowed)
228 {
229     struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
230     HRESULT hr;
231 
232     TRACE("iface %p, adapter %u, device_type %#x, display_format %#x, backbuffer_format %#x, windowed %#x.\n",
233             iface, adapter, device_type, display_format, backbuffer_format, windowed);
234 
235     /* Others than that not supported by d3d9, but reported by wined3d for ddraw. Filter them out. */
236     if (!windowed && display_format != D3DFMT_X8R8G8B8 && display_format != D3DFMT_R5G6B5)
237         return WINED3DERR_NOTAVAILABLE;
238 
239     wined3d_mutex_lock();
240     hr = wined3d_check_device_type(d3d9->wined3d, adapter, device_type, wined3dformat_from_d3dformat(display_format),
241             wined3dformat_from_d3dformat(backbuffer_format), windowed);
242     wined3d_mutex_unlock();
243 
244     return hr;
245 }
246 
247 static HRESULT WINAPI d3d9_CheckDeviceFormat(IDirect3D9Ex *iface, UINT adapter, D3DDEVTYPE device_type,
248         D3DFORMAT adapter_format, DWORD usage, D3DRESOURCETYPE resource_type, D3DFORMAT format)
249 {
250     struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
251     enum wined3d_resource_type wined3d_rtype;
252     HRESULT hr;
253 
254     TRACE("iface %p, adapter %u, device_type %#x, adapter_format %#x, usage %#x, resource_type %#x, format %#x.\n",
255             iface, adapter, device_type, adapter_format, usage, resource_type, format);
256 
257     usage = usage & (WINED3DUSAGE_MASK | WINED3DUSAGE_QUERY_MASK);
258     switch (resource_type)
259     {
260         case D3DRTYPE_CUBETEXTURE:
261             usage |= WINED3DUSAGE_LEGACY_CUBEMAP;
262         case D3DRTYPE_TEXTURE:
263             usage |= WINED3DUSAGE_TEXTURE;
264         case D3DRTYPE_SURFACE:
265             wined3d_rtype = WINED3D_RTYPE_TEXTURE_2D;
266             break;
267 
268         case D3DRTYPE_VOLUMETEXTURE:
269         case D3DRTYPE_VOLUME:
270             usage |= WINED3DUSAGE_TEXTURE;
271             wined3d_rtype = WINED3D_RTYPE_TEXTURE_3D;
272             break;
273 
274         case D3DRTYPE_VERTEXBUFFER:
275         case D3DRTYPE_INDEXBUFFER:
276             wined3d_rtype = WINED3D_RTYPE_BUFFER;
277             break;
278 
279         default:
280             FIXME("Unhandled resource type %#x.\n", resource_type);
281             return WINED3DERR_INVALIDCALL;
282     }
283 
284     wined3d_mutex_lock();
285     hr = wined3d_check_device_format(d3d9->wined3d, adapter, device_type, wined3dformat_from_d3dformat(adapter_format),
286             usage, wined3d_rtype, wined3dformat_from_d3dformat(format));
287     wined3d_mutex_unlock();
288 
289     return hr;
290 }
291 
292 static HRESULT WINAPI d3d9_CheckDeviceMultiSampleType(IDirect3D9Ex *iface, UINT adapter, D3DDEVTYPE device_type,
293         D3DFORMAT format, BOOL windowed, D3DMULTISAMPLE_TYPE multisample_type, DWORD *levels)
294 {
295     struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
296     HRESULT hr;
297 
298     TRACE("iface %p, adapter %u, device_type %#x, format %#x, windowed %#x, multisample_type %#x, levels %p.\n",
299             iface, adapter, device_type, format, windowed, multisample_type, levels);
300 
301     if (multisample_type > D3DMULTISAMPLE_16_SAMPLES)
302         return D3DERR_INVALIDCALL;
303 
304     wined3d_mutex_lock();
305     hr = wined3d_check_device_multisample_type(d3d9->wined3d, adapter, device_type,
306             wined3dformat_from_d3dformat(format), windowed, multisample_type, levels);
307     wined3d_mutex_unlock();
308     if (hr == WINED3DERR_NOTAVAILABLE && levels)
309         *levels = 1;
310 
311     return hr;
312 }
313 
314 static HRESULT WINAPI d3d9_CheckDepthStencilMatch(IDirect3D9Ex *iface, UINT adapter, D3DDEVTYPE device_type,
315         D3DFORMAT adapter_format, D3DFORMAT rt_format, D3DFORMAT ds_format)
316 {
317     struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
318     HRESULT hr;
319 
320     TRACE("iface %p, adapter %u, device_type %#x, adapter_format %#x, rt_format %#x, ds_format %#x.\n",
321             iface, adapter, device_type, adapter_format, rt_format, ds_format);
322 
323     wined3d_mutex_lock();
324     hr = wined3d_check_depth_stencil_match(d3d9->wined3d, adapter, device_type,
325             wined3dformat_from_d3dformat(adapter_format), wined3dformat_from_d3dformat(rt_format),
326             wined3dformat_from_d3dformat(ds_format));
327     wined3d_mutex_unlock();
328 
329     return hr;
330 }
331 
332 static HRESULT WINAPI d3d9_CheckDeviceFormatConversion(IDirect3D9Ex *iface, UINT adapter,
333         D3DDEVTYPE device_type, D3DFORMAT src_format, D3DFORMAT dst_format)
334 {
335     struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
336     HRESULT hr;
337 
338     TRACE("iface %p, adapter %u, device_type %#x, src_format %#x, dst_format %#x.\n",
339             iface, adapter, device_type, src_format, dst_format);
340 
341     wined3d_mutex_lock();
342     hr = wined3d_check_device_format_conversion(d3d9->wined3d, adapter, device_type,
343             wined3dformat_from_d3dformat(src_format), wined3dformat_from_d3dformat(dst_format));
344     wined3d_mutex_unlock();
345 
346     return hr;
347 }
348 
349 static HRESULT WINAPI d3d9_GetDeviceCaps(IDirect3D9Ex *iface, UINT adapter, D3DDEVTYPE device_type, D3DCAPS9 *caps)
350 {
351     struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
352     WINED3DCAPS wined3d_caps;
353     HRESULT hr;
354 
355     TRACE("iface %p, adapter %u, device_type %#x, caps %p.\n", iface, adapter, device_type, caps);
356 
357     if (!caps)
358         return D3DERR_INVALIDCALL;
359 
360     memset(caps, 0, sizeof(*caps));
361 
362     wined3d_mutex_lock();
363     hr = wined3d_get_device_caps(d3d9->wined3d, adapter, device_type, &wined3d_caps);
364     wined3d_mutex_unlock();
365 
366     d3dcaps_from_wined3dcaps(caps, &wined3d_caps);
367 
368     return hr;
369 }
370 
371 static HMONITOR WINAPI d3d9_GetAdapterMonitor(IDirect3D9Ex *iface, UINT adapter)
372 {
373     struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
374     struct wined3d_output_desc desc;
375     HRESULT hr;
376 
377     TRACE("iface %p, adapter %u.\n", iface, adapter);
378 
379     wined3d_mutex_lock();
380     hr = wined3d_get_output_desc(d3d9->wined3d, adapter, &desc);
381     wined3d_mutex_unlock();
382 
383     if (FAILED(hr))
384     {
385         WARN("Failed to get output desc, hr %#x.\n", hr);
386         return NULL;
387     }
388 
389     return desc.monitor;
390 }
391 
392 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_CreateDevice(IDirect3D9Ex *iface, UINT adapter,
393         D3DDEVTYPE device_type, HWND focus_window, DWORD flags, D3DPRESENT_PARAMETERS *parameters,
394         IDirect3DDevice9 **device)
395 {
396     struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
397     struct d3d9_device *object;
398     HRESULT hr;
399 
400     TRACE("iface %p, adapter %u, device_type %#x, focus_window %p, flags %#x, parameters %p, device %p.\n",
401             iface, adapter, device_type, focus_window, flags, parameters, device);
402 
403     if (!(object = heap_alloc_zero(sizeof(*object))))
404         return E_OUTOFMEMORY;
405 
406     hr = device_init(object, d3d9, d3d9->wined3d, adapter, device_type, focus_window, flags, parameters, NULL);
407     if (FAILED(hr))
408     {
409         WARN("Failed to initialize device, hr %#x.\n", hr);
410         heap_free(object);
411         return hr;
412     }
413 
414     TRACE("Created device %p.\n", object);
415     *device = (IDirect3DDevice9 *)&object->IDirect3DDevice9Ex_iface;
416 
417     return D3D_OK;
418 }
419 
420 static UINT WINAPI d3d9_GetAdapterModeCountEx(IDirect3D9Ex *iface,
421         UINT adapter, const D3DDISPLAYMODEFILTER *filter)
422 {
423     struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
424     UINT ret;
425 
426     TRACE("iface %p, adapter %u, filter %p.\n", iface, adapter, filter);
427 
428     if (filter->Format != D3DFMT_X8R8G8B8 && filter->Format != D3DFMT_R5G6B5)
429         return 0;
430 
431     wined3d_mutex_lock();
432     ret = wined3d_get_adapter_mode_count(d3d9->wined3d, adapter,
433             wined3dformat_from_d3dformat(filter->Format), filter->ScanLineOrdering);
434     wined3d_mutex_unlock();
435 
436     return ret;
437 }
438 
439 static HRESULT WINAPI d3d9_EnumAdapterModesEx(IDirect3D9Ex *iface,
440         UINT adapter, const D3DDISPLAYMODEFILTER *filter, UINT mode_idx, D3DDISPLAYMODEEX *mode)
441 {
442     struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
443     struct wined3d_display_mode wined3d_mode;
444     HRESULT hr;
445 
446     TRACE("iface %p, adapter %u, filter %p, mode_idx %u, mode %p.\n",
447             iface, adapter, filter, mode_idx, mode);
448 
449     if (filter->Format != D3DFMT_X8R8G8B8 && filter->Format != D3DFMT_R5G6B5)
450         return D3DERR_INVALIDCALL;
451 
452     wined3d_mutex_lock();
453     hr = wined3d_enum_adapter_modes(d3d9->wined3d, adapter, wined3dformat_from_d3dformat(filter->Format),
454             filter->ScanLineOrdering, mode_idx, &wined3d_mode);
455     wined3d_mutex_unlock();
456 
457     if (SUCCEEDED(hr))
458     {
459         mode->Width = wined3d_mode.width;
460         mode->Height = wined3d_mode.height;
461         mode->RefreshRate = wined3d_mode.refresh_rate;
462         mode->Format = d3dformat_from_wined3dformat(wined3d_mode.format_id);
463         mode->ScanLineOrdering = wined3d_mode.scanline_ordering;
464     }
465 
466     return hr;
467 }
468 
469 static HRESULT WINAPI d3d9_GetAdapterDisplayModeEx(IDirect3D9Ex *iface,
470         UINT adapter, D3DDISPLAYMODEEX *mode, D3DDISPLAYROTATION *rotation)
471 {
472     struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
473     struct wined3d_display_mode wined3d_mode;
474     HRESULT hr;
475 
476     TRACE("iface %p, adapter %u, mode %p, rotation %p.\n",
477             iface, adapter, mode, rotation);
478 
479     if (mode->Size != sizeof(*mode))
480         return D3DERR_INVALIDCALL;
481 
482     wined3d_mutex_lock();
483     hr = wined3d_get_adapter_display_mode(d3d9->wined3d, adapter, &wined3d_mode,
484             (enum wined3d_display_rotation *)rotation);
485     wined3d_mutex_unlock();
486 
487     if (SUCCEEDED(hr))
488     {
489         mode->Width = wined3d_mode.width;
490         mode->Height = wined3d_mode.height;
491         mode->RefreshRate = wined3d_mode.refresh_rate;
492         mode->Format = d3dformat_from_wined3dformat(wined3d_mode.format_id);
493         mode->ScanLineOrdering = wined3d_mode.scanline_ordering;
494     }
495 
496     return hr;
497 }
498 
499 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_CreateDeviceEx(IDirect3D9Ex *iface,
500         UINT adapter, D3DDEVTYPE device_type, HWND focus_window, DWORD flags,
501         D3DPRESENT_PARAMETERS *parameters, D3DDISPLAYMODEEX *mode, IDirect3DDevice9Ex **device)
502 {
503     struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
504     struct d3d9_device *object;
505     HRESULT hr;
506 
507     TRACE("iface %p, adapter %u, device_type %#x, focus_window %p, flags %#x, parameters %p, mode %p, device %p.\n",
508             iface, adapter, device_type, focus_window, flags, parameters, mode, device);
509 
510     if (!(object = heap_alloc_zero(sizeof(*object))))
511         return E_OUTOFMEMORY;
512 
513     hr = device_init(object, d3d9, d3d9->wined3d, adapter, device_type, focus_window, flags, parameters, mode);
514     if (FAILED(hr))
515     {
516         WARN("Failed to initialize device, hr %#x.\n", hr);
517         heap_free(object);
518         return hr;
519     }
520 
521     TRACE("Created device %p.\n", object);
522     *device = &object->IDirect3DDevice9Ex_iface;
523 
524     return D3D_OK;
525 }
526 
527 static HRESULT WINAPI d3d9_GetAdapterLUID(IDirect3D9Ex *iface, UINT adapter, LUID *luid)
528 {
529     struct d3d9 *d3d9 = impl_from_IDirect3D9Ex(iface);
530     struct wined3d_adapter_identifier adapter_id;
531     HRESULT hr;
532 
533     TRACE("iface %p, adapter %u, luid %p.\n", iface, adapter, luid);
534 
535     adapter_id.driver_size = 0;
536     adapter_id.description_size = 0;
537     adapter_id.device_name_size = 0;
538 
539     wined3d_mutex_lock();
540     hr = wined3d_get_adapter_identifier(d3d9->wined3d, adapter, 0, &adapter_id);
541     wined3d_mutex_unlock();
542 
543     memcpy(luid, &adapter_id.adapter_luid, sizeof(*luid));
544 
545     return hr;
546 }
547 
548 static const struct IDirect3D9ExVtbl d3d9_vtbl =
549 {
550     /* IUnknown */
551     d3d9_QueryInterface,
552     d3d9_AddRef,
553     d3d9_Release,
554     /* IDirect3D9 */
555     d3d9_RegisterSoftwareDevice,
556     d3d9_GetAdapterCount,
557     d3d9_GetAdapterIdentifier,
558     d3d9_GetAdapterModeCount,
559     d3d9_EnumAdapterModes,
560     d3d9_GetAdapterDisplayMode,
561     d3d9_CheckDeviceType,
562     d3d9_CheckDeviceFormat,
563     d3d9_CheckDeviceMultiSampleType,
564     d3d9_CheckDepthStencilMatch,
565     d3d9_CheckDeviceFormatConversion,
566     d3d9_GetDeviceCaps,
567     d3d9_GetAdapterMonitor,
568     d3d9_CreateDevice,
569     /* IDirect3D9Ex */
570     d3d9_GetAdapterModeCountEx,
571     d3d9_EnumAdapterModesEx,
572     d3d9_GetAdapterDisplayModeEx,
573     d3d9_CreateDeviceEx,
574     d3d9_GetAdapterLUID,
575 };
576 
577 BOOL d3d9_init(struct d3d9 *d3d9, BOOL extended)
578 {
579     DWORD flags = WINED3D_PRESENT_CONVERSION | WINED3D_HANDLE_RESTORE | WINED3D_PIXEL_CENTER_INTEGER
580             | WINED3D_SRGB_READ_WRITE_CONTROL | WINED3D_LEGACY_UNBOUND_RESOURCE_COLOR
581             | WINED3D_NO_PRIMITIVE_RESTART | WINED3D_LEGACY_CUBEMAP_FILTERING
582             | WINED3D_NORMALIZED_DEPTH_BIAS | WINED3D_LIMIT_VIEWPORT;
583 
584     if (!extended)
585         flags |= WINED3D_VIDMEM_ACCOUNTING;
586     else
587         flags |= WINED3D_RESTORE_MODE_ON_ACTIVATE;
588 
589     d3d9->IDirect3D9Ex_iface.lpVtbl = &d3d9_vtbl;
590     d3d9->refcount = 1;
591 
592     wined3d_mutex_lock();
593     d3d9->wined3d = wined3d_create(flags);
594     wined3d_mutex_unlock();
595     if (!d3d9->wined3d)
596         return FALSE;
597     d3d9->extended = extended;
598 
599     return TRUE;
600 }
601