[D3D8][D3D9][DDRAW][WINED3D] Sync with Wine Staging 1.9.4. CORE-10912
[reactos.git] / reactos / dll / directx / wine / d3d9 / device.c
1 /*
2 * IDirect3DDevice9 implementation
3 *
4 * Copyright 2002-2005 Jason Edmeades
5 * Copyright 2002-2005 Raphael Junqueira
6 * Copyright 2005 Oliver Stieber
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 */
22
23 #include "d3d9_private.h"
24
25 static void STDMETHODCALLTYPE d3d9_null_wined3d_object_destroyed(void *parent) {}
26
27 static const struct wined3d_parent_ops d3d9_null_wined3d_parent_ops =
28 {
29 d3d9_null_wined3d_object_destroyed,
30 };
31
32 D3DFORMAT d3dformat_from_wined3dformat(enum wined3d_format_id format)
33 {
34 BYTE *c = (BYTE *)&format;
35
36 /* Don't translate FOURCC formats */
37 if (isprint(c[0]) && isprint(c[1]) && isprint(c[2]) && isprint(c[3])) return format;
38
39 switch(format)
40 {
41 case WINED3DFMT_UNKNOWN: return D3DFMT_UNKNOWN;
42 case WINED3DFMT_B8G8R8_UNORM: return D3DFMT_R8G8B8;
43 case WINED3DFMT_B8G8R8A8_UNORM: return D3DFMT_A8R8G8B8;
44 case WINED3DFMT_B8G8R8X8_UNORM: return D3DFMT_X8R8G8B8;
45 case WINED3DFMT_B5G6R5_UNORM: return D3DFMT_R5G6B5;
46 case WINED3DFMT_B5G5R5X1_UNORM: return D3DFMT_X1R5G5B5;
47 case WINED3DFMT_B5G5R5A1_UNORM: return D3DFMT_A1R5G5B5;
48 case WINED3DFMT_B4G4R4A4_UNORM: return D3DFMT_A4R4G4B4;
49 case WINED3DFMT_B2G3R3_UNORM: return D3DFMT_R3G3B2;
50 case WINED3DFMT_A8_UNORM: return D3DFMT_A8;
51 case WINED3DFMT_B2G3R3A8_UNORM: return D3DFMT_A8R3G3B2;
52 case WINED3DFMT_B4G4R4X4_UNORM: return D3DFMT_X4R4G4B4;
53 case WINED3DFMT_R10G10B10A2_UNORM: return D3DFMT_A2B10G10R10;
54 case WINED3DFMT_R8G8B8A8_UNORM: return D3DFMT_A8B8G8R8;
55 case WINED3DFMT_R8G8B8X8_UNORM: return D3DFMT_X8B8G8R8;
56 case WINED3DFMT_R16G16_UNORM: return D3DFMT_G16R16;
57 case WINED3DFMT_B10G10R10A2_UNORM: return D3DFMT_A2R10G10B10;
58 case WINED3DFMT_R16G16B16A16_UNORM: return D3DFMT_A16B16G16R16;
59 case WINED3DFMT_P8_UINT_A8_UNORM: return D3DFMT_A8P8;
60 case WINED3DFMT_P8_UINT: return D3DFMT_P8;
61 case WINED3DFMT_L8_UNORM: return D3DFMT_L8;
62 case WINED3DFMT_L8A8_UNORM: return D3DFMT_A8L8;
63 case WINED3DFMT_L4A4_UNORM: return D3DFMT_A4L4;
64 case WINED3DFMT_R8G8_SNORM: return D3DFMT_V8U8;
65 case WINED3DFMT_R5G5_SNORM_L6_UNORM: return D3DFMT_L6V5U5;
66 case WINED3DFMT_R8G8_SNORM_L8X8_UNORM: return D3DFMT_X8L8V8U8;
67 case WINED3DFMT_R8G8B8A8_SNORM: return D3DFMT_Q8W8V8U8;
68 case WINED3DFMT_R16G16_SNORM: return D3DFMT_V16U16;
69 case WINED3DFMT_R10G10B10_SNORM_A2_UNORM: return D3DFMT_A2W10V10U10;
70 case WINED3DFMT_D16_LOCKABLE: return D3DFMT_D16_LOCKABLE;
71 case WINED3DFMT_D32_UNORM: return D3DFMT_D32;
72 case WINED3DFMT_S1_UINT_D15_UNORM: return D3DFMT_D15S1;
73 case WINED3DFMT_D24_UNORM_S8_UINT: return D3DFMT_D24S8;
74 case WINED3DFMT_X8D24_UNORM: return D3DFMT_D24X8;
75 case WINED3DFMT_S4X4_UINT_D24_UNORM: return D3DFMT_D24X4S4;
76 case WINED3DFMT_D16_UNORM: return D3DFMT_D16;
77 case WINED3DFMT_L16_UNORM: return D3DFMT_L16;
78 case WINED3DFMT_D32_FLOAT: return D3DFMT_D32F_LOCKABLE;
79 case WINED3DFMT_S8_UINT_D24_FLOAT: return D3DFMT_D24FS8;
80 case WINED3DFMT_VERTEXDATA: return D3DFMT_VERTEXDATA;
81 case WINED3DFMT_R16_UINT: return D3DFMT_INDEX16;
82 case WINED3DFMT_R32_UINT: return D3DFMT_INDEX32;
83 case WINED3DFMT_R16G16B16A16_SNORM: return D3DFMT_Q16W16V16U16;
84 case WINED3DFMT_R16_FLOAT: return D3DFMT_R16F;
85 case WINED3DFMT_R16G16_FLOAT: return D3DFMT_G16R16F;
86 case WINED3DFMT_R16G16B16A16_FLOAT: return D3DFMT_A16B16G16R16F;
87 case WINED3DFMT_R32_FLOAT: return D3DFMT_R32F;
88 case WINED3DFMT_R32G32_FLOAT: return D3DFMT_G32R32F;
89 case WINED3DFMT_R32G32B32A32_FLOAT: return D3DFMT_A32B32G32R32F;
90 case WINED3DFMT_R8G8_SNORM_Cx: return D3DFMT_CxV8U8;
91 default:
92 FIXME("Unhandled wined3d format %#x.\n", format);
93 return D3DFMT_UNKNOWN;
94 }
95 }
96
97 enum wined3d_format_id wined3dformat_from_d3dformat(D3DFORMAT format)
98 {
99 BYTE *c = (BYTE *)&format;
100
101 /* Don't translate FOURCC formats */
102 if (isprint(c[0]) && isprint(c[1]) && isprint(c[2]) && isprint(c[3])) return format;
103
104 switch(format)
105 {
106 case D3DFMT_UNKNOWN: return WINED3DFMT_UNKNOWN;
107 case D3DFMT_R8G8B8: return WINED3DFMT_B8G8R8_UNORM;
108 case D3DFMT_A8R8G8B8: return WINED3DFMT_B8G8R8A8_UNORM;
109 case D3DFMT_X8R8G8B8: return WINED3DFMT_B8G8R8X8_UNORM;
110 case D3DFMT_R5G6B5: return WINED3DFMT_B5G6R5_UNORM;
111 case D3DFMT_X1R5G5B5: return WINED3DFMT_B5G5R5X1_UNORM;
112 case D3DFMT_A1R5G5B5: return WINED3DFMT_B5G5R5A1_UNORM;
113 case D3DFMT_A4R4G4B4: return WINED3DFMT_B4G4R4A4_UNORM;
114 case D3DFMT_R3G3B2: return WINED3DFMT_B2G3R3_UNORM;
115 case D3DFMT_A8: return WINED3DFMT_A8_UNORM;
116 case D3DFMT_A8R3G3B2: return WINED3DFMT_B2G3R3A8_UNORM;
117 case D3DFMT_X4R4G4B4: return WINED3DFMT_B4G4R4X4_UNORM;
118 case D3DFMT_A2B10G10R10: return WINED3DFMT_R10G10B10A2_UNORM;
119 case D3DFMT_A8B8G8R8: return WINED3DFMT_R8G8B8A8_UNORM;
120 case D3DFMT_X8B8G8R8: return WINED3DFMT_R8G8B8X8_UNORM;
121 case D3DFMT_G16R16: return WINED3DFMT_R16G16_UNORM;
122 case D3DFMT_A2R10G10B10: return WINED3DFMT_B10G10R10A2_UNORM;
123 case D3DFMT_A16B16G16R16: return WINED3DFMT_R16G16B16A16_UNORM;
124 case D3DFMT_A8P8: return WINED3DFMT_P8_UINT_A8_UNORM;
125 case D3DFMT_P8: return WINED3DFMT_P8_UINT;
126 case D3DFMT_L8: return WINED3DFMT_L8_UNORM;
127 case D3DFMT_A8L8: return WINED3DFMT_L8A8_UNORM;
128 case D3DFMT_A4L4: return WINED3DFMT_L4A4_UNORM;
129 case D3DFMT_V8U8: return WINED3DFMT_R8G8_SNORM;
130 case D3DFMT_L6V5U5: return WINED3DFMT_R5G5_SNORM_L6_UNORM;
131 case D3DFMT_X8L8V8U8: return WINED3DFMT_R8G8_SNORM_L8X8_UNORM;
132 case D3DFMT_Q8W8V8U8: return WINED3DFMT_R8G8B8A8_SNORM;
133 case D3DFMT_V16U16: return WINED3DFMT_R16G16_SNORM;
134 case D3DFMT_A2W10V10U10: return WINED3DFMT_R10G10B10_SNORM_A2_UNORM;
135 case D3DFMT_D16_LOCKABLE: return WINED3DFMT_D16_LOCKABLE;
136 case D3DFMT_D32: return WINED3DFMT_D32_UNORM;
137 case D3DFMT_D15S1: return WINED3DFMT_S1_UINT_D15_UNORM;
138 case D3DFMT_D24S8: return WINED3DFMT_D24_UNORM_S8_UINT;
139 case D3DFMT_D24X8: return WINED3DFMT_X8D24_UNORM;
140 case D3DFMT_D24X4S4: return WINED3DFMT_S4X4_UINT_D24_UNORM;
141 case D3DFMT_D16: return WINED3DFMT_D16_UNORM;
142 case D3DFMT_L16: return WINED3DFMT_L16_UNORM;
143 case D3DFMT_D32F_LOCKABLE: return WINED3DFMT_D32_FLOAT;
144 case D3DFMT_D24FS8: return WINED3DFMT_S8_UINT_D24_FLOAT;
145 case D3DFMT_VERTEXDATA: return WINED3DFMT_VERTEXDATA;
146 case D3DFMT_INDEX16: return WINED3DFMT_R16_UINT;
147 case D3DFMT_INDEX32: return WINED3DFMT_R32_UINT;
148 case D3DFMT_Q16W16V16U16: return WINED3DFMT_R16G16B16A16_SNORM;
149 case D3DFMT_R16F: return WINED3DFMT_R16_FLOAT;
150 case D3DFMT_G16R16F: return WINED3DFMT_R16G16_FLOAT;
151 case D3DFMT_A16B16G16R16F: return WINED3DFMT_R16G16B16A16_FLOAT;
152 case D3DFMT_R32F: return WINED3DFMT_R32_FLOAT;
153 case D3DFMT_G32R32F: return WINED3DFMT_R32G32_FLOAT;
154 case D3DFMT_A32B32G32R32F: return WINED3DFMT_R32G32B32A32_FLOAT;
155 case D3DFMT_CxV8U8: return WINED3DFMT_R8G8_SNORM_Cx;
156 default:
157 FIXME("Unhandled D3DFORMAT %#x\n", format);
158 return WINED3DFMT_UNKNOWN;
159 }
160 }
161
162 static UINT vertex_count_from_primitive_count(D3DPRIMITIVETYPE primitive_type, UINT primitive_count)
163 {
164 switch(primitive_type)
165 {
166 case D3DPT_POINTLIST:
167 return primitive_count;
168
169 case D3DPT_LINELIST:
170 return primitive_count * 2;
171
172 case D3DPT_LINESTRIP:
173 return primitive_count + 1;
174
175 case D3DPT_TRIANGLELIST:
176 return primitive_count * 3;
177
178 case D3DPT_TRIANGLESTRIP:
179 case D3DPT_TRIANGLEFAN:
180 return primitive_count + 2;
181
182 default:
183 FIXME("Unhandled primitive type %#x\n", primitive_type);
184 return 0;
185 }
186 }
187
188 void present_parameters_from_wined3d_swapchain_desc(D3DPRESENT_PARAMETERS *present_parameters,
189 const struct wined3d_swapchain_desc *swapchain_desc)
190 {
191 present_parameters->BackBufferWidth = swapchain_desc->backbuffer_width;
192 present_parameters->BackBufferHeight = swapchain_desc->backbuffer_height;
193 present_parameters->BackBufferFormat = d3dformat_from_wined3dformat(swapchain_desc->backbuffer_format);
194 present_parameters->BackBufferCount = swapchain_desc->backbuffer_count;
195 present_parameters->MultiSampleType = swapchain_desc->multisample_type;
196 present_parameters->MultiSampleQuality = swapchain_desc->multisample_quality;
197 present_parameters->SwapEffect = swapchain_desc->swap_effect;
198 present_parameters->hDeviceWindow = swapchain_desc->device_window;
199 present_parameters->Windowed = swapchain_desc->windowed;
200 present_parameters->EnableAutoDepthStencil = swapchain_desc->enable_auto_depth_stencil;
201 present_parameters->AutoDepthStencilFormat
202 = d3dformat_from_wined3dformat(swapchain_desc->auto_depth_stencil_format);
203 present_parameters->Flags = swapchain_desc->flags;
204 present_parameters->FullScreen_RefreshRateInHz = swapchain_desc->refresh_rate;
205 present_parameters->PresentationInterval = swapchain_desc->swap_interval;
206 }
207
208 static BOOL wined3d_swapchain_desc_from_present_parameters(struct wined3d_swapchain_desc *swapchain_desc,
209 const D3DPRESENT_PARAMETERS *present_parameters, BOOL extended)
210 {
211 D3DSWAPEFFECT highest_swapeffect = extended ? D3DSWAPEFFECT_FLIPEX : D3DSWAPEFFECT_COPY;
212 UINT highest_bb_count = extended ? 30 : 3;
213
214 if (!present_parameters->SwapEffect || present_parameters->SwapEffect > highest_swapeffect)
215 {
216 WARN("Invalid swap effect %u passed.\n", present_parameters->SwapEffect);
217 return FALSE;
218 }
219 if (present_parameters->BackBufferCount > highest_bb_count
220 || (present_parameters->SwapEffect == D3DSWAPEFFECT_COPY
221 && present_parameters->BackBufferCount > 1))
222 {
223 WARN("Invalid backbuffer count %u.\n", present_parameters->BackBufferCount);
224 return FALSE;
225 }
226
227 swapchain_desc->backbuffer_width = present_parameters->BackBufferWidth;
228 swapchain_desc->backbuffer_height = present_parameters->BackBufferHeight;
229 swapchain_desc->backbuffer_format = wined3dformat_from_d3dformat(present_parameters->BackBufferFormat);
230 swapchain_desc->backbuffer_count = max(1, present_parameters->BackBufferCount);
231 swapchain_desc->multisample_type = present_parameters->MultiSampleType;
232 swapchain_desc->multisample_quality = present_parameters->MultiSampleQuality;
233 swapchain_desc->swap_effect = present_parameters->SwapEffect;
234 swapchain_desc->device_window = present_parameters->hDeviceWindow;
235 swapchain_desc->windowed = present_parameters->Windowed;
236 swapchain_desc->enable_auto_depth_stencil = present_parameters->EnableAutoDepthStencil;
237 swapchain_desc->auto_depth_stencil_format
238 = wined3dformat_from_d3dformat(present_parameters->AutoDepthStencilFormat);
239 swapchain_desc->flags = present_parameters->Flags;
240 swapchain_desc->refresh_rate = present_parameters->FullScreen_RefreshRateInHz;
241 swapchain_desc->swap_interval = present_parameters->PresentationInterval;
242 swapchain_desc->auto_restore_display_mode = TRUE;
243
244 return TRUE;
245 }
246
247 static HRESULT WINAPI d3d9_device_QueryInterface(IDirect3DDevice9Ex *iface, REFIID riid, void **out)
248 {
249 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
250
251 if (IsEqualGUID(riid, &IID_IDirect3DDevice9)
252 || IsEqualGUID(riid, &IID_IUnknown))
253 {
254 IDirect3DDevice9Ex_AddRef(iface);
255 *out = iface;
256 return S_OK;
257 }
258
259 if (IsEqualGUID(riid, &IID_IDirect3DDevice9Ex))
260 {
261 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
262
263 /* Find out if the creating d3d9 interface was created with Direct3DCreate9Ex.
264 * It doesn't matter with which function the device was created. */
265 if (!device->d3d_parent->extended)
266 {
267 WARN("IDirect3D9 instance wasn't created with CreateDirect3D9Ex, returning E_NOINTERFACE.\n");
268 *out = NULL;
269 return E_NOINTERFACE;
270 }
271
272 IDirect3DDevice9Ex_AddRef(iface);
273 *out = iface;
274 return S_OK;
275 }
276
277 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
278
279 *out = NULL;
280 return E_NOINTERFACE;
281 }
282
283 static ULONG WINAPI d3d9_device_AddRef(IDirect3DDevice9Ex *iface)
284 {
285 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
286 ULONG refcount = InterlockedIncrement(&device->refcount);
287
288 TRACE("%p increasing refcount to %u.\n", iface, refcount);
289
290 return refcount;
291 }
292
293 static ULONG WINAPI DECLSPEC_HOTPATCH d3d9_device_Release(IDirect3DDevice9Ex *iface)
294 {
295 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
296 ULONG refcount;
297
298 if (device->in_destruction)
299 return 0;
300
301 refcount = InterlockedDecrement(&device->refcount);
302
303 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
304
305 if (!refcount)
306 {
307 unsigned i;
308 device->in_destruction = TRUE;
309
310 wined3d_mutex_lock();
311 for (i = 0; i < device->fvf_decl_count; ++i)
312 {
313 wined3d_vertex_declaration_decref(device->fvf_decls[i].decl);
314 }
315 HeapFree(GetProcessHeap(), 0, device->fvf_decls);
316
317 if (device->vertex_buffer)
318 wined3d_buffer_decref(device->vertex_buffer);
319 if (device->index_buffer)
320 wined3d_buffer_decref(device->index_buffer);
321
322 HeapFree(GetProcessHeap(), 0, device->implicit_swapchains);
323
324 wined3d_device_uninit_3d(device->wined3d_device);
325 wined3d_device_release_focus_window(device->wined3d_device);
326 wined3d_device_decref(device->wined3d_device);
327 wined3d_mutex_unlock();
328
329 IDirect3D9Ex_Release(&device->d3d_parent->IDirect3D9Ex_iface);
330
331 HeapFree(GetProcessHeap(), 0, device);
332 }
333
334 return refcount;
335 }
336
337 static HRESULT WINAPI d3d9_device_TestCooperativeLevel(IDirect3DDevice9Ex *iface)
338 {
339 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
340
341 TRACE("iface %p.\n", iface);
342
343 TRACE("device state: %#x.\n", device->device_state);
344
345 if (device->d3d_parent->extended)
346 return D3D_OK;
347
348 switch (device->device_state)
349 {
350 default:
351 case D3D9_DEVICE_STATE_OK:
352 return D3D_OK;
353 case D3D9_DEVICE_STATE_LOST:
354 return D3DERR_DEVICELOST;
355 case D3D9_DEVICE_STATE_NOT_RESET:
356 return D3DERR_DEVICENOTRESET;
357 }
358 }
359
360 static UINT WINAPI d3d9_device_GetAvailableTextureMem(IDirect3DDevice9Ex *iface)
361 {
362 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
363 UINT ret;
364
365 TRACE("iface %p.\n", iface);
366
367 wined3d_mutex_lock();
368 ret = wined3d_device_get_available_texture_mem(device->wined3d_device);
369 wined3d_mutex_unlock();
370
371 return ret;
372 }
373
374 static HRESULT WINAPI d3d9_device_EvictManagedResources(IDirect3DDevice9Ex *iface)
375 {
376 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
377
378 TRACE("iface %p.\n", iface);
379
380 wined3d_mutex_lock();
381 wined3d_device_evict_managed_resources(device->wined3d_device);
382 wined3d_mutex_unlock();
383
384 return D3D_OK;
385 }
386
387 static HRESULT WINAPI d3d9_device_GetDirect3D(IDirect3DDevice9Ex *iface, IDirect3D9 **d3d9)
388 {
389 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
390
391 TRACE("iface %p, d3d9 %p.\n", iface, d3d9);
392
393 if (!d3d9)
394 return D3DERR_INVALIDCALL;
395
396 return IDirect3D9Ex_QueryInterface(&device->d3d_parent->IDirect3D9Ex_iface, &IID_IDirect3D9, (void **)d3d9);
397 }
398
399 static HRESULT WINAPI d3d9_device_GetDeviceCaps(IDirect3DDevice9Ex *iface, D3DCAPS9 *caps)
400 {
401 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
402 WINED3DCAPS *wined3d_caps;
403 HRESULT hr;
404
405 TRACE("iface %p, caps %p.\n", iface, caps);
406
407 if (!caps)
408 return D3DERR_INVALIDCALL;
409
410 if (!(wined3d_caps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*wined3d_caps))))
411 return D3DERR_INVALIDCALL; /* well this is what MSDN says to return */
412
413 memset(caps, 0, sizeof(*caps));
414
415 wined3d_mutex_lock();
416 hr = wined3d_device_get_device_caps(device->wined3d_device, wined3d_caps);
417 wined3d_mutex_unlock();
418
419 WINECAPSTOD3D9CAPS(caps, wined3d_caps)
420 HeapFree(GetProcessHeap(), 0, wined3d_caps);
421
422 /* Some functionality is implemented in d3d9.dll, not wined3d.dll. Add the needed caps */
423 caps->DevCaps2 |= D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES;
424
425 filter_caps(caps);
426
427 return hr;
428 }
429
430 static HRESULT WINAPI d3d9_device_GetDisplayMode(IDirect3DDevice9Ex *iface, UINT swapchain, D3DDISPLAYMODE *mode)
431 {
432 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
433 struct wined3d_display_mode wined3d_mode;
434 HRESULT hr;
435
436 TRACE("iface %p, swapchain %u, mode %p.\n", iface, swapchain, mode);
437
438 wined3d_mutex_lock();
439 hr = wined3d_device_get_display_mode(device->wined3d_device, swapchain, &wined3d_mode, NULL);
440 wined3d_mutex_unlock();
441
442 if (SUCCEEDED(hr))
443 {
444 mode->Width = wined3d_mode.width;
445 mode->Height = wined3d_mode.height;
446 mode->RefreshRate = wined3d_mode.refresh_rate;
447 mode->Format = d3dformat_from_wined3dformat(wined3d_mode.format_id);
448 }
449
450 return hr;
451 }
452
453 static HRESULT WINAPI d3d9_device_GetCreationParameters(IDirect3DDevice9Ex *iface,
454 D3DDEVICE_CREATION_PARAMETERS *parameters)
455 {
456 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
457
458 TRACE("iface %p, parameters %p.\n", iface, parameters);
459
460 wined3d_mutex_lock();
461 wined3d_device_get_creation_parameters(device->wined3d_device,
462 (struct wined3d_device_creation_parameters *)parameters);
463 wined3d_mutex_unlock();
464
465 return D3D_OK;
466 }
467
468 static HRESULT WINAPI d3d9_device_SetCursorProperties(IDirect3DDevice9Ex *iface,
469 UINT hotspot_x, UINT hotspot_y, IDirect3DSurface9 *bitmap)
470 {
471 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
472 struct d3d9_surface *bitmap_impl = unsafe_impl_from_IDirect3DSurface9(bitmap);
473 HRESULT hr;
474
475 TRACE("iface %p, hotspot_x %u, hotspot_y %u, bitmap %p.\n",
476 iface, hotspot_x, hotspot_y, bitmap);
477
478 if (!bitmap)
479 {
480 WARN("No cursor bitmap, returning D3DERR_INVALIDCALL.\n");
481 return D3DERR_INVALIDCALL;
482 }
483
484 wined3d_mutex_lock();
485 hr = wined3d_device_set_cursor_properties(device->wined3d_device,
486 hotspot_x, hotspot_y, bitmap_impl->wined3d_texture, bitmap_impl->sub_resource_idx);
487 wined3d_mutex_unlock();
488
489 return hr;
490 }
491
492 static void WINAPI d3d9_device_SetCursorPosition(IDirect3DDevice9Ex *iface, int x, int y, DWORD flags)
493 {
494 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
495
496 TRACE("iface %p, x %u, y %u, flags %#x.\n", iface, x, y, flags);
497
498 wined3d_mutex_lock();
499 wined3d_device_set_cursor_position(device->wined3d_device, x, y, flags);
500 wined3d_mutex_unlock();
501 }
502
503 static BOOL WINAPI d3d9_device_ShowCursor(IDirect3DDevice9Ex *iface, BOOL show)
504 {
505 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
506 BOOL ret;
507
508 TRACE("iface %p, show %#x.\n", iface, show);
509
510 wined3d_mutex_lock();
511 ret = wined3d_device_show_cursor(device->wined3d_device, show);
512 wined3d_mutex_unlock();
513
514 return ret;
515 }
516
517 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_CreateAdditionalSwapChain(IDirect3DDevice9Ex *iface,
518 D3DPRESENT_PARAMETERS *present_parameters, IDirect3DSwapChain9 **swapchain)
519 {
520 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
521 struct wined3d_swapchain_desc desc;
522 struct d3d9_swapchain *object;
523 UINT i, count;
524 HRESULT hr;
525
526 TRACE("iface %p, present_parameters %p, swapchain %p.\n",
527 iface, present_parameters, swapchain);
528
529 if (!present_parameters->Windowed)
530 {
531 WARN("Trying to create an additional fullscreen swapchain, returning D3DERR_INVALIDCALL.\n");
532 return D3DERR_INVALIDCALL;
533 }
534
535 wined3d_mutex_lock();
536 count = wined3d_device_get_swapchain_count(device->wined3d_device);
537 for (i = 0; i < count; ++i)
538 {
539 struct wined3d_swapchain *wined3d_swapchain;
540
541 wined3d_swapchain = wined3d_device_get_swapchain(device->wined3d_device, i);
542 wined3d_swapchain_get_desc(wined3d_swapchain, &desc);
543
544 if (!desc.windowed)
545 {
546 wined3d_mutex_unlock();
547 WARN("Trying to create an additional swapchain in fullscreen mode, returning D3DERR_INVALIDCALL.\n");
548 return D3DERR_INVALIDCALL;
549 }
550 }
551 wined3d_mutex_unlock();
552
553 if (!wined3d_swapchain_desc_from_present_parameters(&desc, present_parameters,
554 device->d3d_parent->extended))
555 return D3DERR_INVALIDCALL;
556 if (SUCCEEDED(hr = d3d9_swapchain_create(device, &desc, &object)))
557 *swapchain = (IDirect3DSwapChain9 *)&object->IDirect3DSwapChain9Ex_iface;
558 present_parameters_from_wined3d_swapchain_desc(present_parameters, &desc);
559
560 return hr;
561 }
562
563 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_GetSwapChain(IDirect3DDevice9Ex *iface,
564 UINT swapchain_idx, IDirect3DSwapChain9 **swapchain)
565 {
566 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
567 HRESULT hr;
568
569 TRACE("iface %p, swapchain_idx %u, swapchain %p.\n", iface, swapchain_idx, swapchain);
570
571 wined3d_mutex_lock();
572 if (swapchain_idx < device->implicit_swapchain_count)
573 {
574 *swapchain = (IDirect3DSwapChain9 *)&device->implicit_swapchains[swapchain_idx]->IDirect3DSwapChain9Ex_iface;
575 IDirect3DSwapChain9Ex_AddRef(*swapchain);
576 hr = D3D_OK;
577 }
578 else
579 {
580 *swapchain = NULL;
581 hr = D3DERR_INVALIDCALL;
582 }
583 wined3d_mutex_unlock();
584
585 return hr;
586 }
587
588 static UINT WINAPI d3d9_device_GetNumberOfSwapChains(IDirect3DDevice9Ex *iface)
589 {
590 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
591 UINT count;
592
593 TRACE("iface %p.\n", iface);
594
595 wined3d_mutex_lock();
596 count = wined3d_device_get_swapchain_count(device->wined3d_device);
597 wined3d_mutex_unlock();
598
599 return count;
600 }
601
602 static HRESULT CDECL reset_enum_callback(struct wined3d_resource *resource)
603 {
604 struct wined3d_resource_desc desc;
605
606 wined3d_resource_get_desc(resource, &desc);
607 if (desc.pool == WINED3D_POOL_DEFAULT)
608 {
609 struct d3d9_surface *surface;
610
611 if (desc.resource_type == WINED3D_RTYPE_TEXTURE_2D)
612 {
613 IUnknown *parent = wined3d_resource_get_parent(resource);
614 IDirect3DBaseTexture9 *texture;
615
616 if (SUCCEEDED(IUnknown_QueryInterface(parent, &IID_IDirect3DBaseTexture9, (void **)&texture)))
617 {
618 IDirect3DBaseTexture9_Release(texture);
619 WARN("Texture %p (resource %p) in pool D3DPOOL_DEFAULT blocks the Reset call.\n", texture, resource);
620 return D3DERR_INVALIDCALL;
621 }
622
623 return D3D_OK;
624 }
625
626 if (desc.resource_type != WINED3D_RTYPE_SURFACE)
627 {
628 WARN("Resource %p in pool D3DPOOL_DEFAULT blocks the Reset call.\n", resource);
629 return D3DERR_INVALIDCALL;
630 }
631
632 surface = wined3d_resource_get_parent(resource);
633 if (surface->resource.refcount)
634 {
635 WARN("Surface %p (resource %p) in pool D3DPOOL_DEFAULT blocks the Reset call.\n", surface, resource);
636 return D3DERR_INVALIDCALL;
637 }
638
639 WARN("Surface %p (resource %p) is an implicit resource with ref 0.\n", surface, resource);
640 }
641
642 return D3D_OK;
643 }
644
645 static HRESULT d3d9_device_get_swapchains(struct d3d9_device *device)
646 {
647 UINT i, new_swapchain_count = wined3d_device_get_swapchain_count(device->wined3d_device);
648 struct wined3d_swapchain *wined3d_swapchain;
649
650 if (!(device->implicit_swapchains = HeapAlloc(GetProcessHeap(), 0,
651 new_swapchain_count * sizeof(*device->implicit_swapchains))))
652 return E_OUTOFMEMORY;
653
654 for (i = 0; i < new_swapchain_count; ++i)
655 {
656 wined3d_swapchain = wined3d_device_get_swapchain(device->wined3d_device, i);
657 device->implicit_swapchains[i] = wined3d_swapchain_get_parent(wined3d_swapchain);
658 }
659 device->implicit_swapchain_count = new_swapchain_count;
660
661 return D3D_OK;
662 }
663
664 static HRESULT d3d9_device_reset(struct d3d9_device *device,
665 D3DPRESENT_PARAMETERS *present_parameters, D3DDISPLAYMODEEX *mode)
666 {
667 struct wined3d_swapchain_desc swapchain_desc;
668 struct wined3d_display_mode wined3d_mode;
669 HRESULT hr;
670
671 if (!device->d3d_parent->extended && device->device_state == D3D9_DEVICE_STATE_LOST)
672 {
673 WARN("App not active, returning D3DERR_DEVICELOST.\n");
674 return D3DERR_DEVICELOST;
675 }
676
677 if (mode)
678 {
679 wined3d_mode.width = mode->Width;
680 wined3d_mode.height = mode->Height;
681 wined3d_mode.refresh_rate = mode->RefreshRate;
682 wined3d_mode.format_id = wined3dformat_from_d3dformat(mode->Format);
683 wined3d_mode.scanline_ordering = mode->ScanLineOrdering;
684 }
685
686 if (!wined3d_swapchain_desc_from_present_parameters(&swapchain_desc, present_parameters,
687 device->d3d_parent->extended))
688 return D3DERR_INVALIDCALL;
689
690 wined3d_mutex_lock();
691
692 if (device->vertex_buffer)
693 {
694 wined3d_buffer_decref(device->vertex_buffer);
695 device->vertex_buffer = NULL;
696 device->vertex_buffer_size = 0;
697 }
698
699 if (device->index_buffer)
700 {
701 wined3d_buffer_decref(device->index_buffer);
702 device->index_buffer = NULL;
703 device->index_buffer_size = 0;
704 }
705
706 if (SUCCEEDED(hr = wined3d_device_reset(device->wined3d_device, &swapchain_desc,
707 mode ? &wined3d_mode : NULL, reset_enum_callback, !device->d3d_parent->extended)))
708 {
709 HeapFree(GetProcessHeap(), 0, device->implicit_swapchains);
710
711 if (FAILED(hr = d3d9_device_get_swapchains(device)))
712 {
713 device->device_state = D3D9_DEVICE_STATE_NOT_RESET;
714 }
715 else
716 {
717 wined3d_swapchain_get_desc(device->implicit_swapchains[0]->wined3d_swapchain, &swapchain_desc);
718 present_parameters->BackBufferWidth = swapchain_desc.backbuffer_width;
719 present_parameters->BackBufferHeight = swapchain_desc.backbuffer_height;
720 present_parameters->BackBufferFormat = d3dformat_from_wined3dformat(swapchain_desc.backbuffer_format);
721 present_parameters->BackBufferCount = swapchain_desc.backbuffer_count;
722
723 device->device_state = D3D9_DEVICE_STATE_OK;
724 }
725 }
726 else if (!device->d3d_parent->extended)
727 {
728 device->device_state = D3D9_DEVICE_STATE_NOT_RESET;
729 }
730
731 wined3d_mutex_unlock();
732
733 return hr;
734 }
735
736 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_Reset(IDirect3DDevice9Ex *iface,
737 D3DPRESENT_PARAMETERS *present_parameters)
738 {
739 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
740
741 TRACE("iface %p, present_parameters %p.\n", iface, present_parameters);
742
743 return d3d9_device_reset(device, present_parameters, NULL);
744 }
745
746 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_Present(IDirect3DDevice9Ex *iface,
747 const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override, const RGNDATA *dirty_region)
748 {
749 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
750 UINT i;
751 HRESULT hr;
752
753 TRACE("iface %p, src_rect %p, dst_rect %p, dst_window_override %p, dirty_region %p.\n",
754 iface, src_rect, dst_rect, dst_window_override, dirty_region);
755
756 if (device->device_state != D3D9_DEVICE_STATE_OK)
757 return device->d3d_parent->extended ? S_PRESENT_OCCLUDED : D3DERR_DEVICELOST;
758
759 wined3d_mutex_lock();
760 for (i = 0; i < device->implicit_swapchain_count; ++i)
761 {
762 hr = wined3d_swapchain_present(device->implicit_swapchains[i]->wined3d_swapchain, src_rect,
763 dst_rect, dst_window_override, dirty_region, 0);
764 if (FAILED(hr))
765 {
766 wined3d_mutex_unlock();
767 return hr;
768 }
769 }
770 wined3d_mutex_unlock();
771
772 return D3D_OK;
773 }
774
775 static HRESULT WINAPI d3d9_device_GetBackBuffer(IDirect3DDevice9Ex *iface, UINT swapchain,
776 UINT backbuffer_idx, D3DBACKBUFFER_TYPE backbuffer_type, IDirect3DSurface9 **backbuffer)
777 {
778 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
779 HRESULT hr;
780
781 TRACE("iface %p, swapchain %u, backbuffer_idx %u, backbuffer_type %#x, backbuffer %p.\n",
782 iface, swapchain, backbuffer_idx, backbuffer_type, backbuffer);
783
784 /* backbuffer_type is ignored by native. */
785
786 /* No need to check for backbuffer == NULL, Windows crashes in that case. */
787 *backbuffer = NULL;
788
789 wined3d_mutex_lock();
790 if (swapchain >= device->implicit_swapchain_count)
791 {
792 wined3d_mutex_unlock();
793 WARN("Swapchain index %u is out of range, returning D3DERR_INVALIDCALL.\n", swapchain);
794 return D3DERR_INVALIDCALL;
795 }
796
797 hr = IDirect3DSwapChain9Ex_GetBackBuffer(&device->implicit_swapchains[swapchain]->IDirect3DSwapChain9Ex_iface,
798 backbuffer_idx, backbuffer_type, backbuffer);
799 wined3d_mutex_unlock();
800
801 return hr;
802 }
803
804 static HRESULT WINAPI d3d9_device_GetRasterStatus(IDirect3DDevice9Ex *iface,
805 UINT swapchain, D3DRASTER_STATUS *raster_status)
806 {
807 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
808 HRESULT hr;
809
810 TRACE("iface %p, swapchain %u, raster_status %p.\n", iface, swapchain, raster_status);
811
812 wined3d_mutex_lock();
813 hr = wined3d_device_get_raster_status(device->wined3d_device,
814 swapchain, (struct wined3d_raster_status *)raster_status);
815 wined3d_mutex_unlock();
816
817 return hr;
818 }
819
820 static HRESULT WINAPI d3d9_device_SetDialogBoxMode(IDirect3DDevice9Ex *iface, BOOL enable)
821 {
822 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
823 HRESULT hr;
824
825 TRACE("iface %p, enable %#x.\n", iface, enable);
826
827 wined3d_mutex_lock();
828 hr = wined3d_device_set_dialog_box_mode(device->wined3d_device, enable);
829 wined3d_mutex_unlock();
830
831 return hr;
832 }
833
834 static void WINAPI d3d9_device_SetGammaRamp(IDirect3DDevice9Ex *iface,
835 UINT swapchain, DWORD flags, const D3DGAMMARAMP *ramp)
836 {
837 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
838
839 TRACE("iface %p, swapchain %u, flags %#x, ramp %p.\n", iface, swapchain, flags, ramp);
840
841 /* Note: D3DGAMMARAMP is compatible with struct wined3d_gamma_ramp. */
842 wined3d_mutex_lock();
843 wined3d_device_set_gamma_ramp(device->wined3d_device, swapchain, flags, (const struct wined3d_gamma_ramp *)ramp);
844 wined3d_mutex_unlock();
845 }
846
847 static void WINAPI d3d9_device_GetGammaRamp(IDirect3DDevice9Ex *iface, UINT swapchain, D3DGAMMARAMP *ramp)
848 {
849 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
850
851 TRACE("iface %p, swapchain %u, ramp %p.\n", iface, swapchain, ramp);
852
853 /* Note: D3DGAMMARAMP is compatible with struct wined3d_gamma_ramp. */
854 wined3d_mutex_lock();
855 wined3d_device_get_gamma_ramp(device->wined3d_device, swapchain, (struct wined3d_gamma_ramp *)ramp);
856 wined3d_mutex_unlock();
857 }
858
859 static HRESULT WINAPI d3d9_device_CreateTexture(IDirect3DDevice9Ex *iface,
860 UINT width, UINT height, UINT levels, DWORD usage, D3DFORMAT format,
861 D3DPOOL pool, IDirect3DTexture9 **texture, HANDLE *shared_handle)
862 {
863 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
864 struct d3d9_texture *object;
865 BOOL set_mem = FALSE;
866 HRESULT hr;
867
868 TRACE("iface %p, width %u, height %u, levels %u, usage %#x, format %#x, pool %#x, texture %p, shared_handle %p.\n",
869 iface, width, height, levels, usage, format, pool, texture, shared_handle);
870
871 *texture = NULL;
872 if (shared_handle)
873 {
874 if (!device->d3d_parent->extended)
875 {
876 WARN("Trying to create a shared or user memory texture on a non-ex device.\n");
877 return E_NOTIMPL;
878 }
879
880 if (pool == D3DPOOL_SYSTEMMEM)
881 {
882 if (levels != 1)
883 return D3DERR_INVALIDCALL;
884 set_mem = TRUE;
885 }
886 else
887 {
888 if (pool != D3DPOOL_DEFAULT)
889 {
890 WARN("Trying to create a shared texture in pool %#x.\n", pool);
891 return D3DERR_INVALIDCALL;
892 }
893 FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
894 }
895 }
896
897 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
898 if (!object)
899 return D3DERR_OUTOFVIDEOMEMORY;
900
901 hr = texture_init(object, device, width, height, levels, usage, format, pool);
902 if (FAILED(hr))
903 {
904 WARN("Failed to initialize texture, hr %#x.\n", hr);
905 HeapFree(GetProcessHeap(), 0, object);
906 return hr;
907 }
908
909 if (set_mem)
910 wined3d_texture_update_desc(object->wined3d_texture, width, height,
911 wined3dformat_from_d3dformat(format), WINED3D_MULTISAMPLE_NONE, 0,
912 *shared_handle, 0);
913
914 TRACE("Created texture %p.\n", object);
915 *texture = (IDirect3DTexture9 *)&object->IDirect3DBaseTexture9_iface;
916
917 return D3D_OK;
918 }
919
920 static HRESULT WINAPI d3d9_device_CreateVolumeTexture(IDirect3DDevice9Ex *iface,
921 UINT width, UINT height, UINT depth, UINT levels, DWORD usage, D3DFORMAT format,
922 D3DPOOL pool, IDirect3DVolumeTexture9 **texture, HANDLE *shared_handle)
923 {
924 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
925 struct d3d9_texture *object;
926 HRESULT hr;
927
928 TRACE("iface %p, width %u, height %u, depth %u, levels %u\n",
929 iface, width, height, depth, levels);
930 TRACE("usage %#x, format %#x, pool %#x, texture %p, shared_handle %p.\n",
931 usage, format, pool, texture, shared_handle);
932
933 *texture = NULL;
934 if (shared_handle)
935 {
936 if (!device->d3d_parent->extended)
937 {
938 WARN("Trying to create a shared volume texture on a non-ex device.\n");
939 return E_NOTIMPL;
940 }
941
942 if (pool != D3DPOOL_DEFAULT)
943 {
944 WARN("Trying to create a shared volume texture in pool %#x.\n", pool);
945 return D3DERR_INVALIDCALL;
946 }
947 FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
948 }
949
950 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
951 if (!object)
952 return D3DERR_OUTOFVIDEOMEMORY;
953
954 hr = volumetexture_init(object, device, width, height, depth, levels, usage, format, pool);
955 if (FAILED(hr))
956 {
957 WARN("Failed to initialize volume texture, hr %#x.\n", hr);
958 HeapFree(GetProcessHeap(), 0, object);
959 return hr;
960 }
961
962 TRACE("Created volume texture %p.\n", object);
963 *texture = (IDirect3DVolumeTexture9 *)&object->IDirect3DBaseTexture9_iface;
964
965 return D3D_OK;
966 }
967
968 static HRESULT WINAPI d3d9_device_CreateCubeTexture(IDirect3DDevice9Ex *iface,
969 UINT edge_length, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool,
970 IDirect3DCubeTexture9 **texture, HANDLE *shared_handle)
971 {
972 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
973 struct d3d9_texture *object;
974 HRESULT hr;
975
976 TRACE("iface %p, edge_length %u, levels %u, usage %#x, format %#x, pool %#x, texture %p, shared_handle %p.\n",
977 iface, edge_length, levels, usage, format, pool, texture, shared_handle);
978
979 *texture = NULL;
980 if (shared_handle)
981 {
982 if (!device->d3d_parent->extended)
983 {
984 WARN("Trying to create a shared cube texture on a non-ex device.\n");
985 return E_NOTIMPL;
986 }
987
988 if (pool != D3DPOOL_DEFAULT)
989 {
990 WARN("Trying to create a shared cube texture in pool %#x.\n", pool);
991 return D3DERR_INVALIDCALL;
992 }
993 FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
994 }
995
996 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
997 if (!object)
998 return D3DERR_OUTOFVIDEOMEMORY;
999
1000 hr = cubetexture_init(object, device, edge_length, levels, usage, format, pool);
1001 if (FAILED(hr))
1002 {
1003 WARN("Failed to initialize cube texture, hr %#x.\n", hr);
1004 HeapFree(GetProcessHeap(), 0, object);
1005 return hr;
1006 }
1007
1008 TRACE("Created cube texture %p.\n", object);
1009 *texture = (IDirect3DCubeTexture9 *)&object->IDirect3DBaseTexture9_iface;
1010
1011 return D3D_OK;
1012 }
1013
1014 static HRESULT WINAPI d3d9_device_CreateVertexBuffer(IDirect3DDevice9Ex *iface, UINT size,
1015 DWORD usage, DWORD fvf, D3DPOOL pool, IDirect3DVertexBuffer9 **buffer,
1016 HANDLE *shared_handle)
1017 {
1018 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
1019 struct d3d9_vertexbuffer *object;
1020 HRESULT hr;
1021
1022 TRACE("iface %p, size %u, usage %#x, fvf %#x, pool %#x, buffer %p, shared_handle %p.\n",
1023 iface, size, usage, fvf, pool, buffer, shared_handle);
1024
1025 if (shared_handle)
1026 {
1027 if (!device->d3d_parent->extended)
1028 {
1029 WARN("Trying to create a shared vertex buffer on a non-ex device.\n");
1030 return E_NOTIMPL;
1031 }
1032
1033 if (pool != D3DPOOL_DEFAULT)
1034 {
1035 WARN("Trying to create a shared vertex buffer in pool %#x.\n", pool);
1036 return D3DERR_NOTAVAILABLE;
1037 }
1038 FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
1039 }
1040
1041 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1042 if (!object)
1043 return D3DERR_OUTOFVIDEOMEMORY;
1044
1045 hr = vertexbuffer_init(object, device, size, usage, fvf, pool);
1046 if (FAILED(hr))
1047 {
1048 WARN("Failed to initialize vertex buffer, hr %#x.\n", hr);
1049 HeapFree(GetProcessHeap(), 0, object);
1050 return hr;
1051 }
1052
1053 TRACE("Created vertex buffer %p.\n", object);
1054 *buffer = &object->IDirect3DVertexBuffer9_iface;
1055
1056 return D3D_OK;
1057 }
1058
1059 static HRESULT WINAPI d3d9_device_CreateIndexBuffer(IDirect3DDevice9Ex *iface, UINT size,
1060 DWORD usage, D3DFORMAT format, D3DPOOL pool, IDirect3DIndexBuffer9 **buffer,
1061 HANDLE *shared_handle)
1062 {
1063 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
1064 struct d3d9_indexbuffer *object;
1065 HRESULT hr;
1066
1067 TRACE("iface %p, size %u, usage %#x, format %#x, pool %#x, buffer %p, shared_handle %p.\n",
1068 iface, size, usage, format, pool, buffer, shared_handle);
1069
1070 if (shared_handle)
1071 {
1072 if (!device->d3d_parent->extended)
1073 {
1074 WARN("Trying to create a shared index buffer on a non-ex device.\n");
1075 return E_NOTIMPL;
1076 }
1077
1078 if (pool != D3DPOOL_DEFAULT)
1079 {
1080 WARN("Trying to create a shared index buffer in pool %#x.\n", pool);
1081 return D3DERR_NOTAVAILABLE;
1082 }
1083 FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
1084 }
1085
1086 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1087 if (!object)
1088 return D3DERR_OUTOFVIDEOMEMORY;
1089
1090 hr = indexbuffer_init(object, device, size, usage, format, pool);
1091 if (FAILED(hr))
1092 {
1093 WARN("Failed to initialize index buffer, hr %#x.\n", hr);
1094 HeapFree(GetProcessHeap(), 0, object);
1095 return hr;
1096 }
1097
1098 TRACE("Created index buffer %p.\n", object);
1099 *buffer = &object->IDirect3DIndexBuffer9_iface;
1100
1101 return D3D_OK;
1102 }
1103
1104 static HRESULT d3d9_device_create_surface(struct d3d9_device *device, UINT width, UINT height,
1105 D3DFORMAT format, DWORD flags, IDirect3DSurface9 **surface, UINT usage, D3DPOOL pool,
1106 D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality, void *user_mem)
1107 {
1108 struct wined3d_resource *sub_resource;
1109 struct wined3d_resource_desc desc;
1110 struct d3d9_surface *surface_impl;
1111 struct wined3d_texture *texture;
1112 HRESULT hr;
1113
1114 TRACE("device %p, width %u, height %u, format %#x, flags %#x, surface %p.\n"
1115 "usage %#x, pool %#x, multisample_type %#x, multisample_quality %u.\n",
1116 device, width, height, format, flags, surface, usage, pool,
1117 multisample_type, multisample_quality);
1118
1119 desc.resource_type = WINED3D_RTYPE_TEXTURE_2D;
1120 desc.format = wined3dformat_from_d3dformat(format);
1121 desc.multisample_type = multisample_type;
1122 desc.multisample_quality = multisample_quality;
1123 desc.usage = usage & WINED3DUSAGE_MASK;
1124 desc.pool = pool;
1125 desc.width = width;
1126 desc.height = height;
1127 desc.depth = 1;
1128 desc.size = 0;
1129
1130 wined3d_mutex_lock();
1131
1132 if (FAILED(hr = wined3d_texture_create(device->wined3d_device, &desc,
1133 1, flags, NULL, NULL, &d3d9_null_wined3d_parent_ops, &texture)))
1134 {
1135 wined3d_mutex_unlock();
1136 WARN("Failed to create texture, hr %#x.\n", hr);
1137 if (hr == WINED3DERR_NOTAVAILABLE)
1138 hr = D3DERR_INVALIDCALL;
1139 return hr;
1140 }
1141
1142 sub_resource = wined3d_texture_get_sub_resource(texture, 0);
1143 surface_impl = wined3d_resource_get_parent(sub_resource);
1144 surface_impl->parent_device = &device->IDirect3DDevice9Ex_iface;
1145 *surface = &surface_impl->IDirect3DSurface9_iface;
1146 IDirect3DSurface9_AddRef(*surface);
1147
1148 if (user_mem)
1149 wined3d_texture_update_desc(texture, width, height,
1150 desc.format, multisample_type, multisample_quality, user_mem, 0);
1151
1152 wined3d_texture_decref(texture);
1153
1154 wined3d_mutex_unlock();
1155
1156 return D3D_OK;
1157 }
1158
1159 static HRESULT WINAPI d3d9_device_CreateRenderTarget(IDirect3DDevice9Ex *iface, UINT width, UINT height,
1160 D3DFORMAT format, D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality,
1161 BOOL lockable, IDirect3DSurface9 **surface, HANDLE *shared_handle)
1162 {
1163 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
1164 DWORD flags = 0;
1165
1166 TRACE("iface %p, width %u, height %u, format %#x, multisample_type %#x, multisample_quality %u.\n"
1167 "lockable %#x, surface %p, shared_handle %p.\n",
1168 iface, width, height, format, multisample_type, multisample_quality,
1169 lockable, surface, shared_handle);
1170
1171 *surface = NULL;
1172 if (shared_handle)
1173 {
1174 if (!device->d3d_parent->extended)
1175 {
1176 WARN("Trying to create a shared render target on a non-ex device.\n");
1177 return E_NOTIMPL;
1178 }
1179
1180 FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
1181 }
1182
1183 if (lockable)
1184 flags |= WINED3D_TEXTURE_CREATE_MAPPABLE;
1185
1186 return d3d9_device_create_surface(device, width, height, format, flags, surface,
1187 D3DUSAGE_RENDERTARGET, D3DPOOL_DEFAULT, multisample_type, multisample_quality, NULL);
1188 }
1189
1190 static HRESULT WINAPI d3d9_device_CreateDepthStencilSurface(IDirect3DDevice9Ex *iface, UINT width, UINT height,
1191 D3DFORMAT format, D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality,
1192 BOOL discard, IDirect3DSurface9 **surface, HANDLE *shared_handle)
1193 {
1194 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
1195 DWORD flags = WINED3D_TEXTURE_CREATE_MAPPABLE;
1196
1197 TRACE("iface %p, width %u, height %u, format %#x, multisample_type %#x, multisample_quality %u.\n"
1198 "discard %#x, surface %p, shared_handle %p.\n",
1199 iface, width, height, format, multisample_type, multisample_quality,
1200 discard, surface, shared_handle);
1201
1202 *surface = NULL;
1203 if (shared_handle)
1204 {
1205 if (!device->d3d_parent->extended)
1206 {
1207 WARN("Trying to create a shared depth stencil on a non-ex device.\n");
1208 return E_NOTIMPL;
1209 }
1210
1211 FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
1212 }
1213
1214 if (discard)
1215 flags |= WINED3D_TEXTURE_CREATE_DISCARD;
1216
1217 return d3d9_device_create_surface(device, width, height, format, flags, surface,
1218 D3DUSAGE_DEPTHSTENCIL, D3DPOOL_DEFAULT, multisample_type, multisample_quality, NULL);
1219 }
1220
1221
1222 static HRESULT WINAPI d3d9_device_UpdateSurface(IDirect3DDevice9Ex *iface,
1223 IDirect3DSurface9 *src_surface, const RECT *src_rect,
1224 IDirect3DSurface9 *dst_surface, const POINT *dst_point)
1225 {
1226 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
1227 struct d3d9_surface *src = unsafe_impl_from_IDirect3DSurface9(src_surface);
1228 struct d3d9_surface *dst = unsafe_impl_from_IDirect3DSurface9(dst_surface);
1229 struct wined3d_box src_box;
1230 HRESULT hr;
1231
1232 TRACE("iface %p, src_surface %p, src_rect %p, dst_surface %p, dst_point %p.\n",
1233 iface, src_surface, src_rect, dst_surface, dst_point);
1234
1235 if (src_rect)
1236 {
1237 src_box.left = src_rect->left;
1238 src_box.top = src_rect->top;
1239 src_box.right = src_rect->right;
1240 src_box.bottom = src_rect->bottom;
1241 src_box.front = 0;
1242 src_box.back = 1;
1243 }
1244
1245 wined3d_mutex_lock();
1246 hr = wined3d_device_copy_sub_resource_region(device->wined3d_device,
1247 wined3d_texture_get_resource(dst->wined3d_texture), dst->sub_resource_idx, dst_point ? dst_point->x : 0,
1248 dst_point ? dst_point->y : 0, 0, wined3d_texture_get_resource(src->wined3d_texture),
1249 src->sub_resource_idx, src_rect ? &src_box : NULL);
1250 wined3d_mutex_unlock();
1251
1252 if (FAILED(hr))
1253 return D3DERR_INVALIDCALL;
1254
1255 return hr;
1256 }
1257
1258 static HRESULT WINAPI d3d9_device_UpdateTexture(IDirect3DDevice9Ex *iface,
1259 IDirect3DBaseTexture9 *src_texture, IDirect3DBaseTexture9 *dst_texture)
1260 {
1261 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
1262 struct d3d9_texture *src_impl, *dst_impl;
1263 HRESULT hr;
1264
1265 TRACE("iface %p, src_texture %p, dst_texture %p.\n", iface, src_texture, dst_texture);
1266
1267 src_impl = unsafe_impl_from_IDirect3DBaseTexture9(src_texture);
1268 dst_impl = unsafe_impl_from_IDirect3DBaseTexture9(dst_texture);
1269
1270 wined3d_mutex_lock();
1271 hr = wined3d_device_update_texture(device->wined3d_device,
1272 src_impl->wined3d_texture, dst_impl->wined3d_texture);
1273 wined3d_mutex_unlock();
1274
1275 return hr;
1276 }
1277
1278 static HRESULT WINAPI d3d9_device_GetRenderTargetData(IDirect3DDevice9Ex *iface,
1279 IDirect3DSurface9 *render_target, IDirect3DSurface9 *dst_surface)
1280 {
1281 struct d3d9_surface *rt_impl = unsafe_impl_from_IDirect3DSurface9(render_target);
1282 struct d3d9_surface *dst_impl = unsafe_impl_from_IDirect3DSurface9(dst_surface);
1283 struct wined3d_resource_desc wined3d_desc;
1284 struct wined3d_resource *sub_resource;
1285 RECT dst_rect, src_rect;
1286 HRESULT hr;
1287
1288 TRACE("iface %p, render_target %p, dst_surface %p.\n", iface, render_target, dst_surface);
1289
1290 wined3d_mutex_lock();
1291 sub_resource = wined3d_texture_get_sub_resource(dst_impl->wined3d_texture, dst_impl->sub_resource_idx);
1292 wined3d_resource_get_desc(sub_resource, &wined3d_desc);
1293 dst_rect.left = 0;
1294 dst_rect.top = 0;
1295 dst_rect.right = wined3d_desc.width;
1296 dst_rect.bottom = wined3d_desc.height;
1297
1298 sub_resource = wined3d_texture_get_sub_resource(rt_impl->wined3d_texture, rt_impl->sub_resource_idx);
1299 wined3d_resource_get_desc(sub_resource, &wined3d_desc);
1300 src_rect.left = 0;
1301 src_rect.top = 0;
1302 src_rect.right = wined3d_desc.width;
1303 src_rect.bottom = wined3d_desc.height;
1304
1305 /* TODO: Check surface sizes, pools, etc. */
1306 if (wined3d_desc.multisample_type)
1307 hr = D3DERR_INVALIDCALL;
1308 else
1309 hr = wined3d_texture_blt(dst_impl->wined3d_texture, dst_impl->sub_resource_idx, &dst_rect,
1310 rt_impl->wined3d_texture, rt_impl->sub_resource_idx, &src_rect, 0, NULL, WINED3D_TEXF_POINT);
1311 wined3d_mutex_unlock();
1312
1313 return hr;
1314 }
1315
1316 static HRESULT WINAPI d3d9_device_GetFrontBufferData(IDirect3DDevice9Ex *iface,
1317 UINT swapchain, IDirect3DSurface9 *dst_surface)
1318 {
1319 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
1320 struct d3d9_surface *dst_impl = unsafe_impl_from_IDirect3DSurface9(dst_surface);
1321 HRESULT hr = D3DERR_INVALIDCALL;
1322
1323 TRACE("iface %p, swapchain %u, dst_surface %p.\n", iface, swapchain, dst_surface);
1324
1325 wined3d_mutex_lock();
1326 if (swapchain < device->implicit_swapchain_count)
1327 hr = wined3d_swapchain_get_front_buffer_data(device->implicit_swapchains[swapchain]->wined3d_swapchain,
1328 dst_impl->wined3d_texture, dst_impl->sub_resource_idx);
1329 wined3d_mutex_unlock();
1330
1331 return hr;
1332 }
1333
1334 static HRESULT WINAPI d3d9_device_StretchRect(IDirect3DDevice9Ex *iface, IDirect3DSurface9 *src_surface,
1335 const RECT *src_rect, IDirect3DSurface9 *dst_surface, const RECT *dst_rect, D3DTEXTUREFILTERTYPE filter)
1336 {
1337 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
1338 struct d3d9_surface *src = unsafe_impl_from_IDirect3DSurface9(src_surface);
1339 struct d3d9_surface *dst = unsafe_impl_from_IDirect3DSurface9(dst_surface);
1340 HRESULT hr = D3DERR_INVALIDCALL;
1341 struct wined3d_resource_desc src_desc, dst_desc;
1342 struct wined3d_resource *sub_resource;
1343 RECT d, s;
1344
1345 TRACE("iface %p, src_surface %p, src_rect %p, dst_surface %p, dst_rect %p, filter %#x.\n",
1346 iface, src_surface, src_rect, dst_surface, dst_rect, filter);
1347
1348 wined3d_mutex_lock();
1349 sub_resource = wined3d_texture_get_sub_resource(dst->wined3d_texture, dst->sub_resource_idx);
1350 wined3d_resource_get_desc(sub_resource, &dst_desc);
1351 if (!dst_rect)
1352 {
1353 d.left = 0;
1354 d.top = 0;
1355 d.right = dst_desc.width;
1356 d.bottom = dst_desc.height;
1357 dst_rect = &d;
1358 }
1359
1360 sub_resource = wined3d_texture_get_sub_resource(src->wined3d_texture, src->sub_resource_idx);
1361 wined3d_resource_get_desc(sub_resource, &src_desc);
1362 if (!src_rect)
1363 {
1364 s.left = 0;
1365 s.top = 0;
1366 s.right = src_desc.width;
1367 s.bottom = src_desc.height;
1368 src_rect = &s;
1369 }
1370
1371 if (src_desc.usage & WINED3DUSAGE_DEPTHSTENCIL)
1372 {
1373 if (device->in_scene)
1374 {
1375 WARN("Rejecting depth / stencil blit while in scene.\n");
1376 goto done;
1377 }
1378
1379 if (src_rect->left || src_rect->top || src_rect->right != src_desc.width
1380 || src_rect->bottom != src_desc.height)
1381 {
1382 WARN("Rejecting depth / stencil blit with invalid source rect %s.\n",
1383 wine_dbgstr_rect(src_rect));
1384 goto done;
1385 }
1386
1387 if (dst_rect->left || dst_rect->top || dst_rect->right != dst_desc.width
1388 || dst_rect->bottom != dst_desc.height)
1389 {
1390 WARN("Rejecting depth / stencil blit with invalid destination rect %s.\n",
1391 wine_dbgstr_rect(dst_rect));
1392 goto done;
1393 }
1394
1395 if (src_desc.width != dst_desc.width || src_desc.height != dst_desc.height)
1396 {
1397 WARN("Rejecting depth / stencil blit with mismatched surface sizes.\n");
1398 goto done;
1399 }
1400 }
1401
1402 hr = wined3d_texture_blt(dst->wined3d_texture, dst->sub_resource_idx, dst_rect,
1403 src->wined3d_texture, src->sub_resource_idx, src_rect, 0, NULL, filter);
1404 if (hr == WINEDDERR_INVALIDRECT)
1405 hr = D3DERR_INVALIDCALL;
1406
1407 done:
1408 wined3d_mutex_unlock();
1409 return hr;
1410 }
1411
1412 static HRESULT WINAPI d3d9_device_ColorFill(IDirect3DDevice9Ex *iface,
1413 IDirect3DSurface9 *surface, const RECT *rect, D3DCOLOR color)
1414 {
1415 const struct wined3d_color c =
1416 {
1417 ((color >> 16) & 0xff) / 255.0f,
1418 ((color >> 8) & 0xff) / 255.0f,
1419 (color & 0xff) / 255.0f,
1420 ((color >> 24) & 0xff) / 255.0f,
1421 };
1422 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
1423 struct d3d9_surface *surface_impl = unsafe_impl_from_IDirect3DSurface9(surface);
1424 struct wined3d_resource *wined3d_resource;
1425 struct wined3d_resource_desc desc;
1426 HRESULT hr;
1427
1428 TRACE("iface %p, surface %p, rect %p, color 0x%08x.\n", iface, surface, rect, color);
1429
1430 wined3d_mutex_lock();
1431
1432 if (!(wined3d_resource = wined3d_texture_get_sub_resource(surface_impl->wined3d_texture, surface_impl->sub_resource_idx)))
1433 {
1434 wined3d_mutex_unlock();
1435 return D3DERR_INVALIDCALL;
1436 }
1437 wined3d_resource_get_desc(wined3d_resource, &desc);
1438
1439 if (desc.pool != WINED3D_POOL_DEFAULT)
1440 {
1441 wined3d_mutex_unlock();
1442 WARN("Colorfill is not allowed on surfaces in pool %#x, returning D3DERR_INVALIDCALL.\n", desc.pool);
1443 return D3DERR_INVALIDCALL;
1444 }
1445 if ((desc.usage & (WINED3DUSAGE_RENDERTARGET | WINED3DUSAGE_TEXTURE)) == WINED3DUSAGE_TEXTURE)
1446 {
1447 wined3d_mutex_unlock();
1448 WARN("Colorfill is not allowed on non-RT textures, returning D3DERR_INVALIDCALL.\n");
1449 return D3DERR_INVALIDCALL;
1450 }
1451 if (desc.usage & WINED3DUSAGE_DEPTHSTENCIL)
1452 {
1453 wined3d_mutex_unlock();
1454 WARN("Colorfill is not allowed on depth stencil surfaces, returning D3DERR_INVALIDCALL.\n");
1455 return D3DERR_INVALIDCALL;
1456 }
1457
1458 hr = wined3d_device_clear_rendertarget_view(device->wined3d_device,
1459 d3d9_surface_get_rendertarget_view(surface_impl), rect, &c);
1460
1461 wined3d_mutex_unlock();
1462
1463 return hr;
1464 }
1465
1466 static HRESULT WINAPI d3d9_device_CreateOffscreenPlainSurface(IDirect3DDevice9Ex *iface,
1467 UINT width, UINT height, D3DFORMAT format, D3DPOOL pool, IDirect3DSurface9 **surface,
1468 HANDLE *shared_handle)
1469 {
1470 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
1471 void *user_mem = NULL;
1472
1473 TRACE("iface %p, width %u, height %u, format %#x, pool %#x, surface %p, shared_handle %p.\n",
1474 iface, width, height, format, pool, surface, shared_handle);
1475
1476 *surface = NULL;
1477 if (pool == D3DPOOL_MANAGED)
1478 {
1479 WARN("Attempting to create a managed offscreen plain surface.\n");
1480 return D3DERR_INVALIDCALL;
1481 }
1482
1483 if (shared_handle)
1484 {
1485 if (!device->d3d_parent->extended)
1486 {
1487 WARN("Trying to create a shared or user memory surface on a non-ex device.\n");
1488 return E_NOTIMPL;
1489 }
1490
1491 if (pool == D3DPOOL_SYSTEMMEM)
1492 user_mem = *shared_handle;
1493 else
1494 {
1495 if (pool != D3DPOOL_DEFAULT)
1496 {
1497 WARN("Trying to create a shared surface in pool %#x.\n", pool);
1498 return D3DERR_INVALIDCALL;
1499 }
1500 FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
1501 }
1502 }
1503
1504 /* FIXME: Offscreen surfaces are supposed to be always lockable,
1505 * regardless of the pool they're created in. Should we set dynamic usage
1506 * here? */
1507 return d3d9_device_create_surface(device, width, height, format,
1508 WINED3D_TEXTURE_CREATE_MAPPABLE, surface, 0, pool, D3DMULTISAMPLE_NONE, 0, user_mem);
1509 }
1510
1511 static HRESULT WINAPI d3d9_device_SetRenderTarget(IDirect3DDevice9Ex *iface, DWORD idx, IDirect3DSurface9 *surface)
1512 {
1513 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
1514 struct d3d9_surface *surface_impl = unsafe_impl_from_IDirect3DSurface9(surface);
1515 HRESULT hr;
1516
1517 TRACE("iface %p, idx %u, surface %p.\n", iface, idx, surface);
1518
1519 if (idx >= D3D9_MAX_SIMULTANEOUS_RENDERTARGETS)
1520 {
1521 WARN("Invalid index %u specified.\n", idx);
1522 return D3DERR_INVALIDCALL;
1523 }
1524
1525 if (!idx && !surface_impl)
1526 {
1527 WARN("Trying to set render target 0 to NULL.\n");
1528 return D3DERR_INVALIDCALL;
1529 }
1530
1531 wined3d_mutex_lock();
1532 hr = wined3d_device_set_rendertarget_view(device->wined3d_device, idx,
1533 surface_impl ? d3d9_surface_get_rendertarget_view(surface_impl) : NULL, TRUE);
1534 wined3d_mutex_unlock();
1535
1536 return hr;
1537 }
1538
1539 static HRESULT WINAPI d3d9_device_GetRenderTarget(IDirect3DDevice9Ex *iface, DWORD idx, IDirect3DSurface9 **surface)
1540 {
1541 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
1542 struct wined3d_rendertarget_view *wined3d_rtv;
1543 struct d3d9_surface *surface_impl;
1544 HRESULT hr = D3D_OK;
1545
1546 TRACE("iface %p, idx %u, surface %p.\n", iface, idx, surface);
1547
1548 if (!surface)
1549 return D3DERR_INVALIDCALL;
1550
1551 if (idx >= D3D9_MAX_SIMULTANEOUS_RENDERTARGETS)
1552 {
1553 WARN("Invalid index %u specified.\n", idx);
1554 return D3DERR_INVALIDCALL;
1555 }
1556
1557 wined3d_mutex_lock();
1558 if ((wined3d_rtv = wined3d_device_get_rendertarget_view(device->wined3d_device, idx)))
1559 {
1560 /* We want the sub resource parent here, since the view itself may be
1561 * internal to wined3d and may not have a parent. */
1562 surface_impl = wined3d_rendertarget_view_get_sub_resource_parent(wined3d_rtv);
1563 *surface = &surface_impl->IDirect3DSurface9_iface;
1564 IDirect3DSurface9_AddRef(*surface);
1565 }
1566 else
1567 {
1568 hr = D3DERR_NOTFOUND;
1569 *surface = NULL;
1570 }
1571 wined3d_mutex_unlock();
1572
1573 return hr;
1574 }
1575
1576 static HRESULT WINAPI d3d9_device_SetDepthStencilSurface(IDirect3DDevice9Ex *iface, IDirect3DSurface9 *depth_stencil)
1577 {
1578 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
1579 struct d3d9_surface *ds_impl = unsafe_impl_from_IDirect3DSurface9(depth_stencil);
1580
1581 TRACE("iface %p, depth_stencil %p.\n", iface, depth_stencil);
1582
1583 wined3d_mutex_lock();
1584 wined3d_device_set_depth_stencil_view(device->wined3d_device,
1585 ds_impl ? d3d9_surface_get_rendertarget_view(ds_impl) : NULL);
1586 wined3d_mutex_unlock();
1587
1588 return D3D_OK;
1589 }
1590
1591 static HRESULT WINAPI d3d9_device_GetDepthStencilSurface(IDirect3DDevice9Ex *iface, IDirect3DSurface9 **depth_stencil)
1592 {
1593 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
1594 struct wined3d_rendertarget_view *wined3d_dsv;
1595 struct d3d9_surface *surface_impl;
1596 HRESULT hr = D3D_OK;
1597
1598 TRACE("iface %p, depth_stencil %p.\n", iface, depth_stencil);
1599
1600 if (!depth_stencil)
1601 return D3DERR_INVALIDCALL;
1602
1603 wined3d_mutex_lock();
1604 if ((wined3d_dsv = wined3d_device_get_depth_stencil_view(device->wined3d_device)))
1605 {
1606 /* We want the sub resource parent here, since the view itself may be
1607 * internal to wined3d and may not have a parent. */
1608 surface_impl = wined3d_rendertarget_view_get_sub_resource_parent(wined3d_dsv);
1609 *depth_stencil = &surface_impl->IDirect3DSurface9_iface;
1610 IDirect3DSurface9_AddRef(*depth_stencil);
1611 }
1612 else
1613 {
1614 hr = D3DERR_NOTFOUND;
1615 *depth_stencil = NULL;
1616 }
1617 wined3d_mutex_unlock();
1618
1619 return hr;
1620 }
1621
1622 static HRESULT WINAPI d3d9_device_BeginScene(IDirect3DDevice9Ex *iface)
1623 {
1624 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
1625 HRESULT hr;
1626
1627 TRACE("iface %p.\n", iface);
1628
1629 wined3d_mutex_lock();
1630 if (SUCCEEDED(hr = wined3d_device_begin_scene(device->wined3d_device)))
1631 device->in_scene = TRUE;
1632 wined3d_mutex_unlock();
1633
1634 return hr;
1635 }
1636
1637 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_EndScene(IDirect3DDevice9Ex *iface)
1638 {
1639 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
1640 HRESULT hr;
1641
1642 TRACE("iface %p.\n", iface);
1643
1644 wined3d_mutex_lock();
1645 if (SUCCEEDED(hr = wined3d_device_end_scene(device->wined3d_device)))
1646 device->in_scene = FALSE;
1647 wined3d_mutex_unlock();
1648
1649 return hr;
1650 }
1651
1652 static HRESULT WINAPI d3d9_device_Clear(IDirect3DDevice9Ex *iface, DWORD rect_count,
1653 const D3DRECT *rects, DWORD flags, D3DCOLOR color, float z, DWORD stencil)
1654 {
1655 const struct wined3d_color c =
1656 {
1657 ((color >> 16) & 0xff) / 255.0f,
1658 ((color >> 8) & 0xff) / 255.0f,
1659 (color & 0xff) / 255.0f,
1660 ((color >> 24) & 0xff) / 255.0f,
1661 };
1662 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
1663 HRESULT hr;
1664
1665 TRACE("iface %p, rect_count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %u.\n",
1666 iface, rect_count, rects, flags, color, z, stencil);
1667
1668 wined3d_mutex_lock();
1669 hr = wined3d_device_clear(device->wined3d_device, rect_count, (const RECT *)rects, flags, &c, z, stencil);
1670 wined3d_mutex_unlock();
1671
1672 return hr;
1673 }
1674
1675 static HRESULT WINAPI d3d9_device_SetTransform(IDirect3DDevice9Ex *iface,
1676 D3DTRANSFORMSTATETYPE state, const D3DMATRIX *matrix)
1677 {
1678 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
1679
1680 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
1681
1682 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
1683 wined3d_mutex_lock();
1684 wined3d_device_set_transform(device->wined3d_device, state, (const struct wined3d_matrix *)matrix);
1685 wined3d_mutex_unlock();
1686
1687 return D3D_OK;
1688 }
1689
1690 static HRESULT WINAPI d3d9_device_GetTransform(IDirect3DDevice9Ex *iface,
1691 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
1692 {
1693 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
1694
1695 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
1696
1697 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
1698 wined3d_mutex_lock();
1699 wined3d_device_get_transform(device->wined3d_device, state, (struct wined3d_matrix *)matrix);
1700 wined3d_mutex_unlock();
1701
1702 return D3D_OK;
1703 }
1704
1705 static HRESULT WINAPI d3d9_device_MultiplyTransform(IDirect3DDevice9Ex *iface,
1706 D3DTRANSFORMSTATETYPE state, const D3DMATRIX *matrix)
1707 {
1708 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
1709
1710 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
1711
1712 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
1713 wined3d_mutex_lock();
1714 wined3d_device_multiply_transform(device->wined3d_device, state, (const struct wined3d_matrix *)matrix);
1715 wined3d_mutex_unlock();
1716
1717 return D3D_OK;
1718 }
1719
1720 static HRESULT WINAPI d3d9_device_SetViewport(IDirect3DDevice9Ex *iface, const D3DVIEWPORT9 *viewport)
1721 {
1722 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
1723
1724 TRACE("iface %p, viewport %p.\n", iface, viewport);
1725
1726 /* Note: D3DVIEWPORT9 is compatible with struct wined3d_viewport. */
1727 wined3d_mutex_lock();
1728 wined3d_device_set_viewport(device->wined3d_device, (const struct wined3d_viewport *)viewport);
1729 wined3d_mutex_unlock();
1730
1731 return D3D_OK;
1732 }
1733
1734 static HRESULT WINAPI d3d9_device_GetViewport(IDirect3DDevice9Ex *iface, D3DVIEWPORT9 *viewport)
1735 {
1736 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
1737
1738 TRACE("iface %p, viewport %p.\n", iface, viewport);
1739
1740 /* Note: D3DVIEWPORT9 is compatible with struct wined3d_viewport. */
1741 wined3d_mutex_lock();
1742 wined3d_device_get_viewport(device->wined3d_device, (struct wined3d_viewport *)viewport);
1743 wined3d_mutex_unlock();
1744
1745 return D3D_OK;
1746 }
1747
1748 static HRESULT WINAPI d3d9_device_SetMaterial(IDirect3DDevice9Ex *iface, const D3DMATERIAL9 *material)
1749 {
1750 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
1751
1752 TRACE("iface %p, material %p.\n", iface, material);
1753
1754 /* Note: D3DMATERIAL9 is compatible with struct wined3d_material. */
1755 wined3d_mutex_lock();
1756 wined3d_device_set_material(device->wined3d_device, (const struct wined3d_material *)material);
1757 wined3d_mutex_unlock();
1758
1759 return D3D_OK;
1760 }
1761
1762 static HRESULT WINAPI d3d9_device_GetMaterial(IDirect3DDevice9Ex *iface, D3DMATERIAL9 *material)
1763 {
1764 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
1765
1766 TRACE("iface %p, material %p.\n", iface, material);
1767
1768 /* Note: D3DMATERIAL9 is compatible with struct wined3d_material. */
1769 wined3d_mutex_lock();
1770 wined3d_device_get_material(device->wined3d_device, (struct wined3d_material *)material);
1771 wined3d_mutex_unlock();
1772
1773 return D3D_OK;
1774 }
1775
1776 static HRESULT WINAPI d3d9_device_SetLight(IDirect3DDevice9Ex *iface, DWORD index, const D3DLIGHT9 *light)
1777 {
1778 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
1779 HRESULT hr;
1780
1781 TRACE("iface %p, index %u, light %p.\n", iface, index, light);
1782
1783 /* Note: D3DLIGHT9 is compatible with struct wined3d_light. */
1784 wined3d_mutex_lock();
1785 hr = wined3d_device_set_light(device->wined3d_device, index, (const struct wined3d_light *)light);
1786 wined3d_mutex_unlock();
1787
1788 return hr;
1789 }
1790
1791 static HRESULT WINAPI d3d9_device_GetLight(IDirect3DDevice9Ex *iface, DWORD index, D3DLIGHT9 *light)
1792 {
1793 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
1794 HRESULT hr;
1795
1796 TRACE("iface %p, index %u, light %p.\n", iface, index, light);
1797
1798 /* Note: D3DLIGHT9 is compatible with struct wined3d_light. */
1799 wined3d_mutex_lock();
1800 hr = wined3d_device_get_light(device->wined3d_device, index, (struct wined3d_light *)light);
1801 wined3d_mutex_unlock();
1802
1803 return hr;
1804 }
1805
1806 static HRESULT WINAPI d3d9_device_LightEnable(IDirect3DDevice9Ex *iface, DWORD index, BOOL enable)
1807 {
1808 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
1809 HRESULT hr;
1810
1811 TRACE("iface %p, index %u, enable %#x.\n", iface, index, enable);
1812
1813 wined3d_mutex_lock();
1814 hr = wined3d_device_set_light_enable(device->wined3d_device, index, enable);
1815 wined3d_mutex_unlock();
1816
1817 return hr;
1818 }
1819
1820 static HRESULT WINAPI d3d9_device_GetLightEnable(IDirect3DDevice9Ex *iface, DWORD index, BOOL *enable)
1821 {
1822 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
1823 HRESULT hr;
1824
1825 TRACE("iface %p, index %u, enable %p.\n", iface, index, enable);
1826
1827 wined3d_mutex_lock();
1828 hr = wined3d_device_get_light_enable(device->wined3d_device, index, enable);
1829 wined3d_mutex_unlock();
1830
1831 return hr;
1832 }
1833
1834 static HRESULT WINAPI d3d9_device_SetClipPlane(IDirect3DDevice9Ex *iface, DWORD index, const float *plane)
1835 {
1836 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
1837 HRESULT hr;
1838
1839 TRACE("iface %p, index %u, plane %p.\n", iface, index, plane);
1840
1841 wined3d_mutex_lock();
1842 hr = wined3d_device_set_clip_plane(device->wined3d_device, index, (const struct wined3d_vec4 *)plane);
1843 wined3d_mutex_unlock();
1844
1845 return hr;
1846 }
1847
1848 static HRESULT WINAPI d3d9_device_GetClipPlane(IDirect3DDevice9Ex *iface, DWORD index, float *plane)
1849 {
1850 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
1851 HRESULT hr;
1852
1853 TRACE("iface %p, index %u, plane %p.\n", iface, index, plane);
1854
1855 wined3d_mutex_lock();
1856 hr = wined3d_device_get_clip_plane(device->wined3d_device, index, (struct wined3d_vec4 *)plane);
1857 wined3d_mutex_unlock();
1858
1859 return hr;
1860 }
1861
1862 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_SetRenderState(IDirect3DDevice9Ex *iface,
1863 D3DRENDERSTATETYPE state, DWORD value)
1864 {
1865 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
1866
1867 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
1868
1869 wined3d_mutex_lock();
1870 wined3d_device_set_render_state(device->wined3d_device, state, value);
1871 wined3d_mutex_unlock();
1872
1873 return D3D_OK;
1874 }
1875
1876 static HRESULT WINAPI d3d9_device_GetRenderState(IDirect3DDevice9Ex *iface,
1877 D3DRENDERSTATETYPE state, DWORD *value)
1878 {
1879 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
1880
1881 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
1882
1883 wined3d_mutex_lock();
1884 *value = wined3d_device_get_render_state(device->wined3d_device, state);
1885 wined3d_mutex_unlock();
1886
1887 return D3D_OK;
1888 }
1889
1890 static HRESULT WINAPI d3d9_device_CreateStateBlock(IDirect3DDevice9Ex *iface,
1891 D3DSTATEBLOCKTYPE type, IDirect3DStateBlock9 **stateblock)
1892 {
1893 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
1894 struct d3d9_stateblock *object;
1895 HRESULT hr;
1896
1897 TRACE("iface %p, type %#x, stateblock %p.\n", iface, type, stateblock);
1898
1899 if (type != D3DSBT_ALL && type != D3DSBT_PIXELSTATE && type != D3DSBT_VERTEXSTATE)
1900 {
1901 WARN("Unexpected stateblock type, returning D3DERR_INVALIDCALL.\n");
1902 return D3DERR_INVALIDCALL;
1903 }
1904
1905 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1906 if (!object)
1907 return E_OUTOFMEMORY;
1908
1909 hr = stateblock_init(object, device, type, NULL);
1910 if (FAILED(hr))
1911 {
1912 WARN("Failed to initialize stateblock, hr %#x.\n", hr);
1913 HeapFree(GetProcessHeap(), 0, object);
1914 return hr;
1915 }
1916
1917 TRACE("Created stateblock %p.\n", object);
1918 *stateblock = &object->IDirect3DStateBlock9_iface;
1919
1920 return D3D_OK;
1921 }
1922
1923 static HRESULT WINAPI d3d9_device_BeginStateBlock(IDirect3DDevice9Ex *iface)
1924 {
1925 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
1926 HRESULT hr;
1927
1928 TRACE("iface %p.\n", iface);
1929
1930 wined3d_mutex_lock();
1931 hr = wined3d_device_begin_stateblock(device->wined3d_device);
1932 wined3d_mutex_unlock();
1933
1934 return hr;
1935 }
1936
1937 static HRESULT WINAPI d3d9_device_EndStateBlock(IDirect3DDevice9Ex *iface, IDirect3DStateBlock9 **stateblock)
1938 {
1939 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
1940 struct wined3d_stateblock *wined3d_stateblock;
1941 struct d3d9_stateblock *object;
1942 HRESULT hr;
1943
1944 TRACE("iface %p, stateblock %p.\n", iface, stateblock);
1945
1946 wined3d_mutex_lock();
1947 hr = wined3d_device_end_stateblock(device->wined3d_device, &wined3d_stateblock);
1948 wined3d_mutex_unlock();
1949 if (FAILED(hr))
1950 {
1951 WARN("IWineD3DDevice_EndStateBlock() failed, hr %#x.\n", hr);
1952 return hr;
1953 }
1954
1955 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1956 if (!object)
1957 {
1958 wined3d_mutex_lock();
1959 wined3d_stateblock_decref(wined3d_stateblock);
1960 wined3d_mutex_unlock();
1961 return E_OUTOFMEMORY;
1962 }
1963
1964 hr = stateblock_init(object, device, 0, wined3d_stateblock);
1965 if (FAILED(hr))
1966 {
1967 WARN("Failed to initialize stateblock, hr %#x.\n", hr);
1968 wined3d_mutex_lock();
1969 wined3d_stateblock_decref(wined3d_stateblock);
1970 wined3d_mutex_unlock();
1971 HeapFree(GetProcessHeap(), 0, object);
1972 return hr;
1973 }
1974
1975 TRACE("Created stateblock %p.\n", object);
1976 *stateblock = &object->IDirect3DStateBlock9_iface;
1977
1978 return D3D_OK;
1979 }
1980
1981 static HRESULT WINAPI d3d9_device_SetClipStatus(IDirect3DDevice9Ex *iface, const D3DCLIPSTATUS9 *clip_status)
1982 {
1983 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
1984 HRESULT hr;
1985
1986 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
1987
1988 wined3d_mutex_lock();
1989 hr = wined3d_device_set_clip_status(device->wined3d_device, (const struct wined3d_clip_status *)clip_status);
1990 wined3d_mutex_unlock();
1991
1992 return hr;
1993 }
1994
1995 static HRESULT WINAPI d3d9_device_GetClipStatus(IDirect3DDevice9Ex *iface, D3DCLIPSTATUS9 *clip_status)
1996 {
1997 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
1998 HRESULT hr;
1999
2000 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
2001
2002 wined3d_mutex_lock();
2003 hr = wined3d_device_get_clip_status(device->wined3d_device, (struct wined3d_clip_status *)clip_status);
2004 wined3d_mutex_unlock();
2005
2006 return hr;
2007 }
2008
2009 static HRESULT WINAPI d3d9_device_GetTexture(IDirect3DDevice9Ex *iface, DWORD stage, IDirect3DBaseTexture9 **texture)
2010 {
2011 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
2012 struct wined3d_texture *wined3d_texture = NULL;
2013 struct d3d9_texture *texture_impl;
2014
2015 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
2016
2017 if (!texture)
2018 return D3DERR_INVALIDCALL;
2019
2020 wined3d_mutex_lock();
2021 if ((wined3d_texture = wined3d_device_get_texture(device->wined3d_device, stage)))
2022 {
2023 texture_impl = wined3d_texture_get_parent(wined3d_texture);
2024 *texture = &texture_impl->IDirect3DBaseTexture9_iface;
2025 IDirect3DBaseTexture9_AddRef(*texture);
2026 }
2027 else
2028 {
2029 *texture = NULL;
2030 }
2031 wined3d_mutex_unlock();
2032
2033 return D3D_OK;
2034 }
2035
2036 static HRESULT WINAPI d3d9_device_SetTexture(IDirect3DDevice9Ex *iface, DWORD stage, IDirect3DBaseTexture9 *texture)
2037 {
2038 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
2039 struct d3d9_texture *texture_impl;
2040 HRESULT hr;
2041
2042 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
2043
2044 texture_impl = unsafe_impl_from_IDirect3DBaseTexture9(texture);
2045
2046 wined3d_mutex_lock();
2047 hr = wined3d_device_set_texture(device->wined3d_device, stage,
2048 texture_impl ? texture_impl->wined3d_texture : NULL);
2049 wined3d_mutex_unlock();
2050
2051 return hr;
2052 }
2053
2054 static const enum wined3d_texture_stage_state tss_lookup[] =
2055 {
2056 WINED3D_TSS_INVALID, /* 0, unused */
2057 WINED3D_TSS_COLOR_OP, /* 1, D3DTSS_COLOROP */
2058 WINED3D_TSS_COLOR_ARG1, /* 2, D3DTSS_COLORARG1 */
2059 WINED3D_TSS_COLOR_ARG2, /* 3, D3DTSS_COLORARG2 */
2060 WINED3D_TSS_ALPHA_OP, /* 4, D3DTSS_ALPHAOP */
2061 WINED3D_TSS_ALPHA_ARG1, /* 5, D3DTSS_ALPHAARG1 */
2062 WINED3D_TSS_ALPHA_ARG2, /* 6, D3DTSS_ALPHAARG2 */
2063 WINED3D_TSS_BUMPENV_MAT00, /* 7, D3DTSS_BUMPENVMAT00 */
2064 WINED3D_TSS_BUMPENV_MAT01, /* 8, D3DTSS_BUMPENVMAT01 */
2065 WINED3D_TSS_BUMPENV_MAT10, /* 9, D3DTSS_BUMPENVMAT10 */
2066 WINED3D_TSS_BUMPENV_MAT11, /* 10, D3DTSS_BUMPENVMAT11 */
2067 WINED3D_TSS_TEXCOORD_INDEX, /* 11, D3DTSS_TEXCOORDINDEX */
2068 WINED3D_TSS_INVALID, /* 12, unused */
2069 WINED3D_TSS_INVALID, /* 13, unused */
2070 WINED3D_TSS_INVALID, /* 14, unused */
2071 WINED3D_TSS_INVALID, /* 15, unused */
2072 WINED3D_TSS_INVALID, /* 16, unused */
2073 WINED3D_TSS_INVALID, /* 17, unused */
2074 WINED3D_TSS_INVALID, /* 18, unused */
2075 WINED3D_TSS_INVALID, /* 19, unused */
2076 WINED3D_TSS_INVALID, /* 20, unused */
2077 WINED3D_TSS_INVALID, /* 21, unused */
2078 WINED3D_TSS_BUMPENV_LSCALE, /* 22, D3DTSS_BUMPENVLSCALE */
2079 WINED3D_TSS_BUMPENV_LOFFSET, /* 23, D3DTSS_BUMPENVLOFFSET */
2080 WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
2081 WINED3D_TSS_INVALID, /* 25, unused */
2082 WINED3D_TSS_COLOR_ARG0, /* 26, D3DTSS_COLORARG0 */
2083 WINED3D_TSS_ALPHA_ARG0, /* 27, D3DTSS_ALPHAARG0 */
2084 WINED3D_TSS_RESULT_ARG, /* 28, D3DTSS_RESULTARG */
2085 WINED3D_TSS_INVALID, /* 29, unused */
2086 WINED3D_TSS_INVALID, /* 30, unused */
2087 WINED3D_TSS_INVALID, /* 31, unused */
2088 WINED3D_TSS_CONSTANT, /* 32, D3DTSS_CONSTANT */
2089 };
2090
2091 static HRESULT WINAPI d3d9_device_GetTextureStageState(IDirect3DDevice9Ex *iface,
2092 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
2093 {
2094 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
2095
2096 TRACE("iface %p, stage %u, state %#x, value %p.\n", iface, stage, state, value);
2097
2098 if (state >= sizeof(tss_lookup) / sizeof(*tss_lookup))
2099 {
2100 WARN("Invalid state %#x passed.\n", state);
2101 return D3D_OK;
2102 }
2103
2104 wined3d_mutex_lock();
2105 *value = wined3d_device_get_texture_stage_state(device->wined3d_device, stage, tss_lookup[state]);
2106 wined3d_mutex_unlock();
2107
2108 return D3D_OK;
2109 }
2110
2111 static HRESULT WINAPI d3d9_device_SetTextureStageState(IDirect3DDevice9Ex *iface,
2112 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
2113 {
2114 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
2115
2116 TRACE("iface %p, stage %u, state %#x, value %#x.\n", iface, stage, state, value);
2117
2118 if (state >= sizeof(tss_lookup) / sizeof(*tss_lookup))
2119 {
2120 WARN("Invalid state %#x passed.\n", state);
2121 return D3D_OK;
2122 }
2123
2124 wined3d_mutex_lock();
2125 wined3d_device_set_texture_stage_state(device->wined3d_device, stage, tss_lookup[state], value);
2126 wined3d_mutex_unlock();
2127
2128 return D3D_OK;
2129 }
2130
2131 static HRESULT WINAPI d3d9_device_GetSamplerState(IDirect3DDevice9Ex *iface,
2132 DWORD sampler, D3DSAMPLERSTATETYPE state, DWORD *value)
2133 {
2134 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
2135
2136 TRACE("iface %p, sampler %u, state %#x, value %p.\n", iface, sampler, state, value);
2137
2138 wined3d_mutex_lock();
2139 *value = wined3d_device_get_sampler_state(device->wined3d_device, sampler, state);
2140 wined3d_mutex_unlock();
2141
2142 return D3D_OK;
2143 }
2144
2145 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_SetSamplerState(IDirect3DDevice9Ex *iface,
2146 DWORD sampler, D3DSAMPLERSTATETYPE state, DWORD value)
2147 {
2148 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
2149
2150 TRACE("iface %p, sampler %u, state %#x, value %#x.\n", iface, sampler, state, value);
2151
2152 wined3d_mutex_lock();
2153 wined3d_device_set_sampler_state(device->wined3d_device, sampler, state, value);
2154 wined3d_mutex_unlock();
2155
2156 return D3D_OK;
2157 }
2158
2159 static HRESULT WINAPI d3d9_device_ValidateDevice(IDirect3DDevice9Ex *iface, DWORD *pass_count)
2160 {
2161 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
2162 HRESULT hr;
2163
2164 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
2165
2166 wined3d_mutex_lock();
2167 hr = wined3d_device_validate_device(device->wined3d_device, pass_count);
2168 wined3d_mutex_unlock();
2169
2170 return hr;
2171 }
2172
2173 static HRESULT WINAPI d3d9_device_SetPaletteEntries(IDirect3DDevice9Ex *iface,
2174 UINT palette_idx, const PALETTEENTRY *entries)
2175 {
2176 WARN("iface %p, palette_idx %u, entries %p unimplemented.\n", iface, palette_idx, entries);
2177
2178 /* The d3d9 palette API is non-functional on Windows. Getters and setters are implemented,
2179 * and some drivers allow the creation of P8 surfaces. These surfaces can be copied to
2180 * other P8 surfaces with StretchRect, but cannot be converted to (A)RGB.
2181 *
2182 * Some older(dx7) cards may have support for P8 textures, but games cannot rely on this. */
2183 return D3D_OK;
2184 }
2185
2186 static HRESULT WINAPI d3d9_device_GetPaletteEntries(IDirect3DDevice9Ex *iface,
2187 UINT palette_idx, PALETTEENTRY *entries)
2188 {
2189 FIXME("iface %p, palette_idx %u, entries %p unimplemented.\n", iface, palette_idx, entries);
2190
2191 return D3DERR_INVALIDCALL;
2192 }
2193
2194 static HRESULT WINAPI d3d9_device_SetCurrentTexturePalette(IDirect3DDevice9Ex *iface, UINT palette_idx)
2195 {
2196 WARN("iface %p, palette_idx %u unimplemented.\n", iface, palette_idx);
2197
2198 return D3D_OK;
2199 }
2200
2201 static HRESULT WINAPI d3d9_device_GetCurrentTexturePalette(IDirect3DDevice9Ex *iface, UINT *palette_idx)
2202 {
2203 FIXME("iface %p, palette_idx %p.\n", iface, palette_idx);
2204
2205 return D3DERR_INVALIDCALL;
2206 }
2207
2208 static HRESULT WINAPI d3d9_device_SetScissorRect(IDirect3DDevice9Ex *iface, const RECT *rect)
2209 {
2210 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
2211
2212 TRACE("iface %p, rect %p.\n", iface, rect);
2213
2214 wined3d_mutex_lock();
2215 wined3d_device_set_scissor_rect(device->wined3d_device, rect);
2216 wined3d_mutex_unlock();
2217
2218 return D3D_OK;
2219 }
2220
2221 static HRESULT WINAPI d3d9_device_GetScissorRect(IDirect3DDevice9Ex *iface, RECT *rect)
2222 {
2223 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
2224
2225 TRACE("iface %p, rect %p.\n", iface, rect);
2226
2227 wined3d_mutex_lock();
2228 wined3d_device_get_scissor_rect(device->wined3d_device, rect);
2229 wined3d_mutex_unlock();
2230
2231 return D3D_OK;
2232 }
2233
2234 static HRESULT WINAPI d3d9_device_SetSoftwareVertexProcessing(IDirect3DDevice9Ex *iface, BOOL software)
2235 {
2236 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
2237
2238 TRACE("iface %p, software %#x.\n", iface, software);
2239
2240 wined3d_mutex_lock();
2241 wined3d_device_set_software_vertex_processing(device->wined3d_device, software);
2242 wined3d_mutex_unlock();
2243
2244 return D3D_OK;
2245 }
2246
2247 static BOOL WINAPI d3d9_device_GetSoftwareVertexProcessing(IDirect3DDevice9Ex *iface)
2248 {
2249 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
2250 BOOL ret;
2251
2252 TRACE("iface %p.\n", iface);
2253
2254 wined3d_mutex_lock();
2255 ret = wined3d_device_get_software_vertex_processing(device->wined3d_device);
2256 wined3d_mutex_unlock();
2257
2258 return ret;
2259 }
2260
2261 static HRESULT WINAPI d3d9_device_SetNPatchMode(IDirect3DDevice9Ex *iface, float segment_count)
2262 {
2263 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
2264 HRESULT hr;
2265
2266 TRACE("iface %p, segment_count %.8e.\n", iface, segment_count);
2267
2268 wined3d_mutex_lock();
2269 hr = wined3d_device_set_npatch_mode(device->wined3d_device, segment_count);
2270 wined3d_mutex_unlock();
2271
2272 return hr;
2273 }
2274
2275 static float WINAPI d3d9_device_GetNPatchMode(IDirect3DDevice9Ex *iface)
2276 {
2277 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
2278 float ret;
2279
2280 TRACE("iface %p.\n", iface);
2281
2282 wined3d_mutex_lock();
2283 ret = wined3d_device_get_npatch_mode(device->wined3d_device);
2284 wined3d_mutex_unlock();
2285
2286 return ret;
2287 }
2288
2289 static HRESULT WINAPI d3d9_device_DrawPrimitive(IDirect3DDevice9Ex *iface,
2290 D3DPRIMITIVETYPE primitive_type, UINT start_vertex, UINT primitive_count)
2291 {
2292 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
2293 HRESULT hr;
2294
2295 TRACE("iface %p, primitive_type %#x, start_vertex %u, primitive_count %u.\n",
2296 iface, primitive_type, start_vertex, primitive_count);
2297
2298 wined3d_mutex_lock();
2299 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
2300 hr = wined3d_device_draw_primitive(device->wined3d_device, start_vertex,
2301 vertex_count_from_primitive_count(primitive_type, primitive_count));
2302 wined3d_mutex_unlock();
2303
2304 return hr;
2305 }
2306
2307 static HRESULT WINAPI d3d9_device_DrawIndexedPrimitive(IDirect3DDevice9Ex *iface,
2308 D3DPRIMITIVETYPE primitive_type, INT base_vertex_idx, UINT min_vertex_idx,
2309 UINT vertex_count, UINT start_idx, UINT primitive_count)
2310 {
2311 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
2312 HRESULT hr;
2313
2314 TRACE("iface %p, primitive_type %#x, base_vertex_idx %u, min_vertex_idx %u,\n"
2315 "vertex_count %u, start_idx %u, primitive_count %u.\n",
2316 iface, primitive_type, base_vertex_idx, min_vertex_idx,
2317 vertex_count, start_idx, primitive_count);
2318
2319 wined3d_mutex_lock();
2320 wined3d_device_set_base_vertex_index(device->wined3d_device, base_vertex_idx);
2321 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
2322 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, start_idx,
2323 vertex_count_from_primitive_count(primitive_type, primitive_count));
2324 wined3d_mutex_unlock();
2325
2326 return hr;
2327 }
2328
2329 /* The caller is responsible for wined3d locking */
2330 static HRESULT d3d9_device_prepare_vertex_buffer(struct d3d9_device *device, UINT min_size)
2331 {
2332 HRESULT hr;
2333
2334 if (device->vertex_buffer_size < min_size || !device->vertex_buffer)
2335 {
2336 UINT size = max(device->vertex_buffer_size * 2, min_size);
2337 struct wined3d_buffer *buffer;
2338
2339 TRACE("Growing vertex buffer to %u bytes\n", size);
2340
2341 hr = wined3d_buffer_create_vb(device->wined3d_device, size, WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY,
2342 WINED3D_POOL_DEFAULT, NULL, &d3d9_null_wined3d_parent_ops, &buffer);
2343 if (FAILED(hr))
2344 {
2345 ERR("(%p) wined3d_buffer_create_vb failed with hr = %08x\n", device, hr);
2346 return hr;
2347 }
2348
2349 if (device->vertex_buffer)
2350 wined3d_buffer_decref(device->vertex_buffer);
2351
2352 device->vertex_buffer = buffer;
2353 device->vertex_buffer_size = size;
2354 device->vertex_buffer_pos = 0;
2355 }
2356 return D3D_OK;
2357 }
2358
2359 static HRESULT WINAPI d3d9_device_DrawPrimitiveUP(IDirect3DDevice9Ex *iface,
2360 D3DPRIMITIVETYPE primitive_type, UINT primitive_count, const void *data, UINT stride)
2361 {
2362 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
2363 HRESULT hr;
2364 UINT vtx_count = vertex_count_from_primitive_count(primitive_type, primitive_count);
2365 UINT size = vtx_count * stride;
2366 UINT vb_pos, align;
2367 BYTE *buffer_data;
2368
2369 TRACE("iface %p, primitive_type %#x, primitive_count %u, data %p, stride %u.\n",
2370 iface, primitive_type, primitive_count, data, stride);
2371
2372 if (!primitive_count)
2373 {
2374 WARN("primitive_count is 0, returning D3D_OK\n");
2375 return D3D_OK;
2376 }
2377
2378 wined3d_mutex_lock();
2379
2380 hr = d3d9_device_prepare_vertex_buffer(device, size);
2381 if (FAILED(hr))
2382 goto done;
2383
2384 vb_pos = device->vertex_buffer_pos;
2385 align = vb_pos % stride;
2386 if (align) align = stride - align;
2387 if (vb_pos + size + align > device->vertex_buffer_size)
2388 vb_pos = 0;
2389 else
2390 vb_pos += align;
2391
2392 hr = wined3d_buffer_map(device->vertex_buffer, vb_pos, size, &buffer_data,
2393 vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
2394 if (FAILED(hr))
2395 goto done;
2396 memcpy(buffer_data, data, size);
2397 wined3d_buffer_unmap(device->vertex_buffer);
2398 device->vertex_buffer_pos = vb_pos + size;
2399
2400 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, stride);
2401 if (FAILED(hr))
2402 goto done;
2403
2404 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
2405 hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / stride, vtx_count);
2406 wined3d_device_set_stream_source(device->wined3d_device, 0, NULL, 0, 0);
2407
2408 done:
2409 wined3d_mutex_unlock();
2410 return hr;
2411 }
2412
2413 /* The caller is responsible for wined3d locking */
2414 static HRESULT d3d9_device_prepare_index_buffer(struct d3d9_device *device, UINT min_size)
2415 {
2416 HRESULT hr;
2417
2418 if (device->index_buffer_size < min_size || !device->index_buffer)
2419 {
2420 UINT size = max(device->index_buffer_size * 2, min_size);
2421 struct wined3d_buffer *buffer;
2422
2423 TRACE("Growing index buffer to %u bytes\n", size);
2424
2425 hr = wined3d_buffer_create_ib(device->wined3d_device, size, WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY,
2426 WINED3D_POOL_DEFAULT, NULL, &d3d9_null_wined3d_parent_ops, &buffer);
2427 if (FAILED(hr))
2428 {
2429 ERR("(%p) wined3d_buffer_create_ib failed with hr = %08x\n", device, hr);
2430 return hr;
2431 }
2432
2433 if (device->index_buffer)
2434 wined3d_buffer_decref(device->index_buffer);
2435
2436 device->index_buffer = buffer;
2437 device->index_buffer_size = size;
2438 device->index_buffer_pos = 0;
2439 }
2440 return D3D_OK;
2441 }
2442
2443 static HRESULT WINAPI d3d9_device_DrawIndexedPrimitiveUP(IDirect3DDevice9Ex *iface,
2444 D3DPRIMITIVETYPE primitive_type, UINT min_vertex_idx, UINT vertex_count,
2445 UINT primitive_count, const void *index_data, D3DFORMAT index_format,
2446 const void *vertex_data, UINT vertex_stride)
2447 {
2448 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
2449 HRESULT hr;
2450 BYTE *buffer_data;
2451
2452 UINT idx_count = vertex_count_from_primitive_count(primitive_type, primitive_count);
2453 UINT idx_fmt_size = index_format == D3DFMT_INDEX16 ? 2 : 4;
2454 UINT idx_size = idx_count * idx_fmt_size;
2455 UINT ib_pos;
2456
2457 UINT vtx_size = vertex_count * vertex_stride;
2458 UINT vb_pos, align;
2459
2460 TRACE("iface %p, primitive_type %#x, min_vertex_idx %u, vertex_count %u, primitive_count %u,\n"
2461 "index_data %p, index_format %#x, vertex_data %p, vertex_stride %u.\n",
2462 iface, primitive_type, min_vertex_idx, vertex_count, primitive_count,
2463 index_data, index_format, vertex_data, vertex_stride);
2464
2465 if (!primitive_count)
2466 {
2467 WARN("primitive_count is 0, returning D3D_OK\n");
2468 return D3D_OK;
2469 }
2470
2471 wined3d_mutex_lock();
2472
2473 hr = d3d9_device_prepare_vertex_buffer(device, vtx_size);
2474 if (FAILED(hr))
2475 goto done;
2476
2477 vb_pos = device->vertex_buffer_pos;
2478 align = vb_pos % vertex_stride;
2479 if (align) align = vertex_stride - align;
2480 if (vb_pos + vtx_size + align > device->vertex_buffer_size)
2481 vb_pos = 0;
2482 else
2483 vb_pos += align;
2484
2485 hr = wined3d_buffer_map(device->vertex_buffer, vb_pos, vtx_size, &buffer_data,
2486 vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
2487 if (FAILED(hr))
2488 goto done;
2489 memcpy(buffer_data, vertex_data, vtx_size);
2490 wined3d_buffer_unmap(device->vertex_buffer);
2491 device->vertex_buffer_pos = vb_pos + vtx_size;
2492
2493 hr = d3d9_device_prepare_index_buffer(device, idx_size);
2494 if (FAILED(hr))
2495 goto done;
2496
2497 ib_pos = device->index_buffer_pos;
2498 align = ib_pos % idx_fmt_size;
2499 if (align) align = idx_fmt_size - align;
2500 if (ib_pos + idx_size + align > device->index_buffer_size)
2501 ib_pos = 0;
2502 else
2503 ib_pos += align;
2504
2505 hr = wined3d_buffer_map(device->index_buffer, ib_pos, idx_size, &buffer_data,
2506 ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
2507 if (FAILED(hr))
2508 goto done;
2509 memcpy(buffer_data, index_data, idx_size);
2510 wined3d_buffer_unmap(device->index_buffer);
2511 device->index_buffer_pos = ib_pos + idx_size;
2512
2513 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, vertex_stride);
2514 if (FAILED(hr))
2515 goto done;
2516
2517 wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer,
2518 wined3dformat_from_d3dformat(index_format));
2519 wined3d_device_set_base_vertex_index(device->wined3d_device, vb_pos / vertex_stride);
2520
2521 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
2522 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / idx_fmt_size, idx_count);
2523
2524 wined3d_device_set_stream_source(device->wined3d_device, 0, NULL, 0, 0);
2525 wined3d_device_set_index_buffer(device->wined3d_device, NULL, WINED3DFMT_UNKNOWN);
2526 wined3d_device_set_base_vertex_index(device->wined3d_device, 0);
2527
2528 done:
2529 wined3d_mutex_unlock();
2530 return hr;
2531 }
2532
2533 static HRESULT WINAPI d3d9_device_ProcessVertices(IDirect3DDevice9Ex *iface,
2534 UINT src_start_idx, UINT dst_idx, UINT vertex_count, IDirect3DVertexBuffer9 *dst_buffer,
2535 IDirect3DVertexDeclaration9 *declaration, DWORD flags)
2536 {
2537 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
2538 struct d3d9_vertexbuffer *dst_impl = unsafe_impl_from_IDirect3DVertexBuffer9(dst_buffer);
2539 struct d3d9_vertex_declaration *decl_impl = unsafe_impl_from_IDirect3DVertexDeclaration9(declaration);
2540 HRESULT hr;
2541
2542 TRACE("iface %p, src_start_idx %u, dst_idx %u, vertex_count %u, dst_buffer %p, declaration %p, flags %#x.\n",
2543 iface, src_start_idx, dst_idx, vertex_count, dst_buffer, declaration, flags);
2544
2545 wined3d_mutex_lock();
2546 hr = wined3d_device_process_vertices(device->wined3d_device, src_start_idx, dst_idx, vertex_count,
2547 dst_impl->wined3d_buffer, decl_impl ? decl_impl->wined3d_declaration : NULL,
2548 flags, dst_impl->fvf);
2549 wined3d_mutex_unlock();
2550
2551 return hr;
2552 }
2553
2554 static HRESULT WINAPI d3d9_device_CreateVertexDeclaration(IDirect3DDevice9Ex *iface,
2555 const D3DVERTEXELEMENT9 *elements, IDirect3DVertexDeclaration9 **declaration)
2556 {
2557 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
2558 struct d3d9_vertex_declaration *object;
2559 HRESULT hr;
2560
2561 TRACE("iface %p, elements %p, declaration %p.\n", iface, elements, declaration);
2562
2563 if (!declaration)
2564 {
2565 WARN("Caller passed a NULL declaration, returning D3DERR_INVALIDCALL.\n");
2566 return D3DERR_INVALIDCALL;
2567 }
2568
2569 if (SUCCEEDED(hr = d3d9_vertex_declaration_create(device, elements, &object)))
2570 *declaration = &object->IDirect3DVertexDeclaration9_iface;
2571
2572 return hr;
2573 }
2574
2575 static HRESULT WINAPI d3d9_device_SetVertexDeclaration(IDirect3DDevice9Ex *iface,
2576 IDirect3DVertexDeclaration9 *declaration)
2577 {
2578 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
2579 struct d3d9_vertex_declaration *decl_impl = unsafe_impl_from_IDirect3DVertexDeclaration9(declaration);
2580
2581 TRACE("iface %p, declaration %p.\n", iface, declaration);
2582
2583 wined3d_mutex_lock();
2584 wined3d_device_set_vertex_declaration(device->wined3d_device,
2585 decl_impl ? decl_impl->wined3d_declaration : NULL);
2586 wined3d_mutex_unlock();
2587
2588 return D3D_OK;
2589 }
2590
2591 static HRESULT WINAPI d3d9_device_GetVertexDeclaration(IDirect3DDevice9Ex *iface,
2592 IDirect3DVertexDeclaration9 **declaration)
2593 {
2594 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
2595 struct wined3d_vertex_declaration *wined3d_declaration;
2596 struct d3d9_vertex_declaration *declaration_impl;
2597
2598 TRACE("iface %p, declaration %p.\n", iface, declaration);
2599
2600 if (!declaration) return D3DERR_INVALIDCALL;
2601
2602 wined3d_mutex_lock();
2603 if ((wined3d_declaration = wined3d_device_get_vertex_declaration(device->wined3d_device)))
2604 {
2605 declaration_impl = wined3d_vertex_declaration_get_parent(wined3d_declaration);
2606 *declaration = &declaration_impl->IDirect3DVertexDeclaration9_iface;
2607 IDirect3DVertexDeclaration9_AddRef(*declaration);
2608 }
2609 else
2610 {
2611 *declaration = NULL;
2612 }
2613 wined3d_mutex_unlock();
2614
2615 TRACE("Returning %p.\n", *declaration);
2616 return D3D_OK;
2617 }
2618
2619 static struct wined3d_vertex_declaration *device_get_fvf_declaration(struct d3d9_device *device, DWORD fvf)
2620 {
2621 struct wined3d_vertex_declaration *wined3d_declaration;
2622 struct fvf_declaration *fvf_decls = device->fvf_decls;
2623 struct d3d9_vertex_declaration *d3d9_declaration;
2624 D3DVERTEXELEMENT9 *elements;
2625 int p, low, high; /* deliberately signed */
2626 HRESULT hr;
2627
2628 TRACE("Searching for declaration for fvf %08x... ", fvf);
2629
2630 low = 0;
2631 high = device->fvf_decl_count - 1;
2632 while (low <= high)
2633 {
2634 p = (low + high) >> 1;
2635 TRACE("%d ", p);
2636
2637 if (fvf_decls[p].fvf == fvf)
2638 {
2639 TRACE("found %p.\n", fvf_decls[p].decl);
2640 return fvf_decls[p].decl;
2641 }
2642
2643 if (fvf_decls[p].fvf < fvf)
2644 low = p + 1;
2645 else
2646 high = p - 1;
2647 }
2648 TRACE("not found. Creating and inserting at position %d.\n", low);
2649
2650 if (FAILED(hr = vdecl_convert_fvf(fvf, &elements)))
2651 return NULL;
2652
2653 hr = d3d9_vertex_declaration_create(device, elements, &d3d9_declaration);
2654 HeapFree(GetProcessHeap(), 0, elements);
2655 if (FAILED(hr))
2656 return NULL;
2657
2658 if (device->fvf_decl_size == device->fvf_decl_count)
2659 {
2660 UINT grow = max(device->fvf_decl_size / 2, 8);
2661
2662 fvf_decls = HeapReAlloc(GetProcessHeap(), 0, fvf_decls, sizeof(*fvf_decls) * (device->fvf_decl_size + grow));
2663 if (!fvf_decls)
2664 {
2665 IDirect3DVertexDeclaration9_Release(&d3d9_declaration->IDirect3DVertexDeclaration9_iface);
2666 return NULL;
2667 }
2668 device->fvf_decls = fvf_decls;
2669 device->fvf_decl_size += grow;
2670 }
2671
2672 d3d9_declaration->fvf = fvf;
2673 wined3d_declaration = d3d9_declaration->wined3d_declaration;
2674 wined3d_vertex_declaration_incref(wined3d_declaration);
2675 IDirect3DVertexDeclaration9_Release(&d3d9_declaration->IDirect3DVertexDeclaration9_iface);
2676
2677 memmove(fvf_decls + low + 1, fvf_decls + low, sizeof(*fvf_decls) * (device->fvf_decl_count - low));
2678 fvf_decls[low].decl = wined3d_declaration;
2679 fvf_decls[low].fvf = fvf;
2680 ++device->fvf_decl_count;
2681
2682 TRACE("Returning %p. %u declarations in array.\n", wined3d_declaration, device->fvf_decl_count);
2683
2684 return wined3d_declaration;
2685 }
2686
2687 static HRESULT WINAPI d3d9_device_SetFVF(IDirect3DDevice9Ex *iface, DWORD fvf)
2688 {
2689 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
2690 struct wined3d_vertex_declaration *decl;
2691
2692 TRACE("iface %p, fvf %#x.\n", iface, fvf);
2693
2694 if (!fvf)
2695 {
2696 WARN("%#x is not a valid FVF.\n", fvf);
2697 return D3D_OK;
2698 }
2699
2700 wined3d_mutex_lock();
2701 if (!(decl = device_get_fvf_declaration(device, fvf)))
2702 {
2703 wined3d_mutex_unlock();
2704 ERR("Failed to create a vertex declaration for fvf %#x.\n", fvf);
2705 return D3DERR_DRIVERINTERNALERROR;
2706 }
2707
2708 wined3d_device_set_vertex_declaration(device->wined3d_device, decl);
2709 wined3d_mutex_unlock();
2710
2711 return D3D_OK;
2712 }
2713
2714 static HRESULT WINAPI d3d9_device_GetFVF(IDirect3DDevice9Ex *iface, DWORD *fvf)
2715 {
2716 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
2717 struct wined3d_vertex_declaration *wined3d_declaration;
2718 struct d3d9_vertex_declaration *d3d9_declaration;
2719
2720 TRACE("iface %p, fvf %p.\n", iface, fvf);
2721
2722 wined3d_mutex_lock();
2723 if ((wined3d_declaration = wined3d_device_get_vertex_declaration(device->wined3d_device)))
2724 {
2725 d3d9_declaration = wined3d_vertex_declaration_get_parent(wined3d_declaration);
2726 *fvf = d3d9_declaration->fvf;
2727 }
2728 else
2729 {
2730 *fvf = 0;
2731 }
2732 wined3d_mutex_unlock();
2733
2734 TRACE("Returning FVF %#x.\n", *fvf);
2735
2736 return D3D_OK;
2737 }
2738
2739 static HRESULT WINAPI d3d9_device_CreateVertexShader(IDirect3DDevice9Ex *iface,
2740 const DWORD *byte_code, IDirect3DVertexShader9 **shader)
2741 {
2742 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
2743 struct d3d9_vertexshader *object;
2744 HRESULT hr;
2745
2746 TRACE("iface %p, byte_code %p, shader %p.\n", iface, byte_code, shader);
2747
2748 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
2749 if (!object)
2750 return E_OUTOFMEMORY;
2751
2752 hr = vertexshader_init(object, device, byte_code);
2753 if (FAILED(hr))
2754 {
2755 WARN("Failed to initialize vertex shader, hr %#x.\n", hr);
2756 HeapFree(GetProcessHeap(), 0, object);
2757 return hr;
2758 }
2759
2760 TRACE("Created vertex shader %p.\n", object);
2761 *shader = &object->IDirect3DVertexShader9_iface;
2762
2763 return D3D_OK;
2764 }
2765
2766 static HRESULT WINAPI d3d9_device_SetVertexShader(IDirect3DDevice9Ex *iface, IDirect3DVertexShader9 *shader)
2767 {
2768 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
2769 struct d3d9_vertexshader *shader_obj = unsafe_impl_from_IDirect3DVertexShader9(shader);
2770
2771 TRACE("iface %p, shader %p.\n", iface, shader);
2772
2773 wined3d_mutex_lock();
2774 wined3d_device_set_vertex_shader(device->wined3d_device,
2775 shader_obj ? shader_obj->wined3d_shader : NULL);
2776 wined3d_mutex_unlock();
2777
2778 return D3D_OK;
2779 }
2780
2781 static HRESULT WINAPI d3d9_device_GetVertexShader(IDirect3DDevice9Ex *iface, IDirect3DVertexShader9 **shader)
2782 {
2783 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
2784 struct d3d9_vertexshader *shader_impl;
2785 struct wined3d_shader *wined3d_shader;
2786
2787 TRACE("iface %p, shader %p.\n", iface, shader);
2788
2789 wined3d_mutex_lock();
2790 if ((wined3d_shader = wined3d_device_get_vertex_shader(device->wined3d_device)))
2791 {
2792 shader_impl = wined3d_shader_get_parent(wined3d_shader);
2793 *shader = &shader_impl->IDirect3DVertexShader9_iface;
2794 IDirect3DVertexShader9_AddRef(*shader);
2795 }
2796 else
2797 {
2798 *shader = NULL;
2799 }
2800 wined3d_mutex_unlock();
2801
2802 TRACE("Returning %p.\n", *shader);
2803
2804 return D3D_OK;
2805 }
2806
2807 static HRESULT WINAPI d3d9_device_SetVertexShaderConstantF(IDirect3DDevice9Ex *iface,
2808 UINT reg_idx, const float *data, UINT count)
2809 {
2810 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
2811 HRESULT hr;
2812
2813 TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
2814
2815 if (reg_idx + count > D3D9_MAX_VERTEX_SHADER_CONSTANTF)
2816 {
2817 WARN("Trying to access %u constants, but d3d9 only supports %u\n",
2818 reg_idx + count, D3D9_MAX_VERTEX_SHADER_CONSTANTF);
2819 return D3DERR_INVALIDCALL;
2820 }
2821
2822 wined3d_mutex_lock();
2823 hr = wined3d_device_set_vs_consts_f(device->wined3d_device, reg_idx, data, count);
2824 wined3d_mutex_unlock();
2825
2826 return hr;
2827 }
2828
2829 static HRESULT WINAPI d3d9_device_GetVertexShaderConstantF(IDirect3DDevice9Ex *iface,
2830 UINT reg_idx, float *data, UINT count)
2831 {
2832 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
2833 HRESULT hr;
2834
2835 TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
2836
2837 if (reg_idx + count > D3D9_MAX_VERTEX_SHADER_CONSTANTF)
2838 {
2839 WARN("Trying to access %u constants, but d3d9 only supports %u\n",
2840 reg_idx + count, D3D9_MAX_VERTEX_SHADER_CONSTANTF);
2841 return D3DERR_INVALIDCALL;
2842 }
2843
2844 wined3d_mutex_lock();
2845 hr = wined3d_device_get_vs_consts_f(device->wined3d_device, reg_idx, data, count);
2846 wined3d_mutex_unlock();
2847
2848 return hr;
2849 }
2850
2851 static HRESULT WINAPI d3d9_device_SetVertexShaderConstantI(IDirect3DDevice9Ex *iface,
2852 UINT reg_idx, const int *data, UINT count)
2853 {
2854 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
2855 HRESULT hr;
2856
2857 TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
2858
2859 wined3d_mutex_lock();
2860 hr = wined3d_device_set_vs_consts_i(device->wined3d_device, reg_idx, data, count);
2861 wined3d_mutex_unlock();
2862
2863 return hr;
2864 }
2865
2866 static HRESULT WINAPI d3d9_device_GetVertexShaderConstantI(IDirect3DDevice9Ex *iface,
2867 UINT reg_idx, int *data, UINT count)
2868 {
2869 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
2870 HRESULT hr;
2871
2872 TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
2873
2874 wined3d_mutex_lock();
2875 hr = wined3d_device_get_vs_consts_i(device->wined3d_device, reg_idx, data, count);
2876 wined3d_mutex_unlock();
2877
2878 return hr;
2879 }
2880
2881 static HRESULT WINAPI d3d9_device_SetVertexShaderConstantB(IDirect3DDevice9Ex *iface,
2882 UINT reg_idx, const BOOL *data, UINT count)
2883 {
2884 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
2885 HRESULT hr;
2886
2887 TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
2888
2889 wined3d_mutex_lock();
2890 hr = wined3d_device_set_vs_consts_b(device->wined3d_device, reg_idx, data, count);
2891 wined3d_mutex_unlock();
2892
2893 return hr;
2894 }
2895
2896 static HRESULT WINAPI d3d9_device_GetVertexShaderConstantB(IDirect3DDevice9Ex *iface,
2897 UINT reg_idx, BOOL *data, UINT count)
2898 {
2899 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
2900 HRESULT hr;
2901
2902 TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
2903
2904 wined3d_mutex_lock();
2905 hr = wined3d_device_get_vs_consts_b(device->wined3d_device, reg_idx, data, count);
2906 wined3d_mutex_unlock();
2907
2908 return hr;
2909 }
2910
2911 static HRESULT WINAPI d3d9_device_SetStreamSource(IDirect3DDevice9Ex *iface,
2912 UINT stream_idx, IDirect3DVertexBuffer9 *buffer, UINT offset, UINT stride)
2913 {
2914 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
2915 struct d3d9_vertexbuffer *buffer_impl = unsafe_impl_from_IDirect3DVertexBuffer9(buffer);
2916 HRESULT hr;
2917
2918 TRACE("iface %p, stream_idx %u, buffer %p, offset %u, stride %u.\n",
2919 iface, stream_idx, buffer, offset, stride);
2920
2921 wined3d_mutex_lock();
2922 hr = wined3d_device_set_stream_source(device->wined3d_device, stream_idx,
2923 buffer_impl ? buffer_impl->wined3d_buffer : NULL, offset, stride);
2924 wined3d_mutex_unlock();
2925
2926 return hr;
2927 }
2928
2929 static HRESULT WINAPI d3d9_device_GetStreamSource(IDirect3DDevice9Ex *iface,
2930 UINT stream_idx, IDirect3DVertexBuffer9 **buffer, UINT *offset, UINT *stride)
2931 {
2932 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
2933 struct d3d9_vertexbuffer *buffer_impl;
2934 struct wined3d_buffer *wined3d_buffer;
2935 HRESULT hr;
2936
2937 TRACE("iface %p, stream_idx %u, buffer %p, offset %p, stride %p.\n",
2938 iface, stream_idx, buffer, offset, stride);
2939
2940 if (!buffer)
2941 return D3DERR_INVALIDCALL;
2942
2943 wined3d_mutex_lock();
2944 hr = wined3d_device_get_stream_source(device->wined3d_device, stream_idx, &wined3d_buffer, offset, stride);
2945 if (SUCCEEDED(hr) && wined3d_buffer)
2946 {
2947 buffer_impl = wined3d_buffer_get_parent(wined3d_buffer);
2948 *buffer = &buffer_impl->IDirect3DVertexBuffer9_iface;
2949 IDirect3DVertexBuffer9_AddRef(*buffer);
2950 }
2951 else
2952 {
2953 if (FAILED(hr))
2954 FIXME("Call to GetStreamSource failed %p %p\n", offset, stride);
2955 *buffer = NULL;
2956 }
2957 wined3d_mutex_unlock();
2958
2959 return hr;
2960 }
2961
2962 static HRESULT WINAPI d3d9_device_SetStreamSourceFreq(IDirect3DDevice9Ex *iface, UINT stream_idx, UINT freq)
2963 {
2964 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
2965 HRESULT hr;
2966
2967 TRACE("iface %p, stream_idx %u, freq %u.\n", iface, stream_idx, freq);
2968
2969 wined3d_mutex_lock();
2970 hr = wined3d_device_set_stream_source_freq(device->wined3d_device, stream_idx, freq);
2971 wined3d_mutex_unlock();
2972
2973 return hr;
2974 }
2975
2976 static HRESULT WINAPI d3d9_device_GetStreamSourceFreq(IDirect3DDevice9Ex *iface, UINT stream_idx, UINT *freq)
2977 {
2978 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
2979 HRESULT hr;
2980
2981 TRACE("iface %p, stream_idx %u, freq %p.\n", iface, stream_idx, freq);
2982
2983 wined3d_mutex_lock();
2984 hr = wined3d_device_get_stream_source_freq(device->wined3d_device, stream_idx, freq);
2985 wined3d_mutex_unlock();
2986
2987 return hr;
2988 }
2989
2990 static HRESULT WINAPI d3d9_device_SetIndices(IDirect3DDevice9Ex *iface, IDirect3DIndexBuffer9 *buffer)
2991 {
2992 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
2993 struct d3d9_indexbuffer *ib = unsafe_impl_from_IDirect3DIndexBuffer9(buffer);
2994
2995 TRACE("iface %p, buffer %p.\n", iface, buffer);
2996
2997 wined3d_mutex_lock();
2998 wined3d_device_set_index_buffer(device->wined3d_device,
2999 ib ? ib->wined3d_buffer : NULL,
3000 ib ? ib->format : WINED3DFMT_UNKNOWN);
3001 wined3d_mutex_unlock();
3002
3003 return D3D_OK;
3004 }
3005
3006 static HRESULT WINAPI d3d9_device_GetIndices(IDirect3DDevice9Ex *iface, IDirect3DIndexBuffer9 **buffer)
3007 {
3008 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
3009 enum wined3d_format_id wined3d_format;
3010 struct wined3d_buffer *wined3d_buffer;
3011 struct d3d9_indexbuffer *buffer_impl;
3012
3013 TRACE("iface %p, buffer %p.\n", iface, buffer);
3014
3015 if (!buffer)
3016 return D3DERR_INVALIDCALL;
3017
3018 wined3d_mutex_lock();
3019 if ((wined3d_buffer = wined3d_device_get_index_buffer(device->wined3d_device, &wined3d_format)))
3020 {
3021 buffer_impl = wined3d_buffer_get_parent(wined3d_buffer);
3022 *buffer = &buffer_impl->IDirect3DIndexBuffer9_iface;
3023 IDirect3DIndexBuffer9_AddRef(*buffer);
3024 }
3025 else
3026 {
3027 *buffer = NULL;
3028 }
3029 wined3d_mutex_unlock();
3030
3031 return D3D_OK;
3032 }
3033
3034 static HRESULT WINAPI d3d9_device_CreatePixelShader(IDirect3DDevice9Ex *iface,
3035 const DWORD *byte_code, IDirect3DPixelShader9 **shader)
3036 {
3037 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
3038 struct d3d9_pixelshader *object;
3039 HRESULT hr;
3040
3041 TRACE("iface %p, byte_code %p, shader %p.\n", iface, byte_code, shader);
3042
3043 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
3044 if (!object)
3045 {
3046 FIXME("Failed to allocate pixel shader memory.\n");
3047 return E_OUTOFMEMORY;
3048 }
3049
3050 hr = pixelshader_init(object, device, byte_code);
3051 if (FAILED(hr))
3052 {
3053 WARN("Failed to initialize pixel shader, hr %#x.\n", hr);
3054 HeapFree(GetProcessHeap(), 0, object);
3055 return hr;
3056 }
3057
3058 TRACE("Created pixel shader %p.\n", object);
3059 *shader = &object->IDirect3DPixelShader9_iface;
3060
3061 return D3D_OK;
3062 }
3063
3064 static HRESULT WINAPI d3d9_device_SetPixelShader(IDirect3DDevice9Ex *iface, IDirect3DPixelShader9 *shader)
3065 {
3066 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
3067 struct d3d9_pixelshader *shader_obj = unsafe_impl_from_IDirect3DPixelShader9(shader);
3068
3069 TRACE("iface %p, shader %p.\n", iface, shader);
3070
3071 wined3d_mutex_lock();
3072 wined3d_device_set_pixel_shader(device->wined3d_device,
3073 shader_obj ? shader_obj->wined3d_shader : NULL);
3074 wined3d_mutex_unlock();
3075
3076 return D3D_OK;
3077 }
3078
3079 static HRESULT WINAPI d3d9_device_GetPixelShader(IDirect3DDevice9Ex *iface, IDirect3DPixelShader9 **shader)
3080 {
3081 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
3082 struct d3d9_pixelshader *shader_impl;
3083 struct wined3d_shader *wined3d_shader;
3084
3085 TRACE("iface %p, shader %p.\n", iface, shader);
3086
3087 if (!shader) return D3DERR_INVALIDCALL;
3088
3089 wined3d_mutex_lock();
3090 if ((wined3d_shader = wined3d_device_get_pixel_shader(device->wined3d_device)))
3091 {
3092 shader_impl = wined3d_shader_get_parent(wined3d_shader);
3093 *shader = &shader_impl->IDirect3DPixelShader9_iface;
3094 IDirect3DPixelShader9_AddRef(*shader);
3095 }
3096 else
3097 {
3098 *shader = NULL;
3099 }
3100 wined3d_mutex_unlock();
3101
3102 TRACE("Returning %p.\n", *shader);
3103
3104 return D3D_OK;
3105 }
3106
3107 static HRESULT WINAPI d3d9_device_SetPixelShaderConstantF(IDirect3DDevice9Ex *iface,
3108 UINT reg_idx, const float *data, UINT count)
3109 {
3110 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
3111 HRESULT hr;
3112
3113 TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
3114
3115 wined3d_mutex_lock();
3116 hr = wined3d_device_set_ps_consts_f(device->wined3d_device, reg_idx, data, count);
3117 wined3d_mutex_unlock();
3118
3119 return hr;
3120 }
3121
3122 static HRESULT WINAPI d3d9_device_GetPixelShaderConstantF(IDirect3DDevice9Ex *iface,
3123 UINT reg_idx, float *data, UINT count)
3124 {
3125 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
3126 HRESULT hr;
3127
3128 TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
3129
3130 wined3d_mutex_lock();
3131 hr = wined3d_device_get_ps_consts_f(device->wined3d_device, reg_idx, data, count);
3132 wined3d_mutex_unlock();
3133
3134 return hr;
3135 }
3136
3137 static HRESULT WINAPI d3d9_device_SetPixelShaderConstantI(IDirect3DDevice9Ex *iface,
3138 UINT reg_idx, const int *data, UINT count)
3139 {
3140 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
3141 HRESULT hr;
3142
3143 TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
3144
3145 wined3d_mutex_lock();
3146 hr = wined3d_device_set_ps_consts_i(device->wined3d_device, reg_idx, data, count);
3147 wined3d_mutex_unlock();
3148
3149 return hr;
3150 }
3151
3152 static HRESULT WINAPI d3d9_device_GetPixelShaderConstantI(IDirect3DDevice9Ex *iface,
3153 UINT reg_idx, int *data, UINT count)
3154 {
3155 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
3156 HRESULT hr;
3157
3158 TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
3159
3160 wined3d_mutex_lock();
3161 hr = wined3d_device_get_ps_consts_i(device->wined3d_device, reg_idx, data, count);
3162 wined3d_mutex_unlock();
3163
3164 return hr;
3165 }
3166
3167 static HRESULT WINAPI d3d9_device_SetPixelShaderConstantB(IDirect3DDevice9Ex *iface,
3168 UINT reg_idx, const BOOL *data, UINT count)
3169 {
3170 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
3171 HRESULT hr;
3172
3173 TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
3174
3175 wined3d_mutex_lock();
3176 hr = wined3d_device_set_ps_consts_b(device->wined3d_device, reg_idx, data, count);
3177 wined3d_mutex_unlock();
3178
3179 return hr;
3180 }
3181
3182 static HRESULT WINAPI d3d9_device_GetPixelShaderConstantB(IDirect3DDevice9Ex *iface,
3183 UINT reg_idx, BOOL *data, UINT count)
3184 {
3185 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
3186 HRESULT hr;
3187
3188 TRACE("iface %p, reg_idx %u, data %p, count %u.\n", iface, reg_idx, data, count);
3189
3190 wined3d_mutex_lock();
3191 hr = wined3d_device_get_ps_consts_b(device->wined3d_device, reg_idx, data, count);
3192 wined3d_mutex_unlock();
3193
3194 return hr;
3195 }
3196
3197 static HRESULT WINAPI d3d9_device_DrawRectPatch(IDirect3DDevice9Ex *iface, UINT handle,
3198 const float *segment_count, const D3DRECTPATCH_INFO *patch_info)
3199 {
3200 FIXME("iface %p, handle %#x, segment_count %p, patch_info %p unimplemented.\n",
3201 iface, handle, segment_count, patch_info);
3202 return D3D_OK;
3203 }
3204
3205 static HRESULT WINAPI d3d9_device_DrawTriPatch(IDirect3DDevice9Ex *iface, UINT handle,
3206 const float *segment_count, const D3DTRIPATCH_INFO *patch_info)
3207 {
3208 FIXME("iface %p, handle %#x, segment_count %p, patch_info %p unimplemented.\n",
3209 iface, handle, segment_count, patch_info);
3210 return D3D_OK;
3211 }
3212
3213 static HRESULT WINAPI d3d9_device_DeletePatch(IDirect3DDevice9Ex *iface, UINT handle)
3214 {
3215 FIXME("iface %p, handle %#x unimplemented.\n", iface, handle);
3216 return D3DERR_INVALIDCALL;
3217 }
3218
3219 static HRESULT WINAPI d3d9_device_CreateQuery(IDirect3DDevice9Ex *iface, D3DQUERYTYPE type, IDirect3DQuery9 **query)
3220 {
3221 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
3222 struct d3d9_query *object;
3223 HRESULT hr;
3224
3225 TRACE("iface %p, type %#x, query %p.\n", iface, type, query);
3226
3227 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
3228 if (!object)
3229 return E_OUTOFMEMORY;
3230
3231 hr = query_init(object, device, type);
3232 if (FAILED(hr))
3233 {
3234 WARN("Failed to initialize query, hr %#x.\n", hr);
3235 HeapFree(GetProcessHeap(), 0, object);
3236 return hr;
3237 }
3238
3239 TRACE("Created query %p.\n", object);
3240 if (query) *query = &object->IDirect3DQuery9_iface;
3241 else IDirect3DQuery9_Release(&object->IDirect3DQuery9_iface);
3242
3243 return D3D_OK;
3244 }
3245
3246 static HRESULT WINAPI d3d9_device_SetConvolutionMonoKernel(IDirect3DDevice9Ex *iface,
3247 UINT width, UINT height, float *rows, float *columns)
3248 {
3249 FIXME("iface %p, width %u, height %u, rows %p, columns %p stub!\n",
3250 iface, width, height, rows, columns);
3251
3252 return E_NOTIMPL;
3253 }
3254
3255 static HRESULT WINAPI d3d9_device_ComposeRects(IDirect3DDevice9Ex *iface,
3256 IDirect3DSurface9 *src_surface, IDirect3DSurface9 *dst_surface, IDirect3DVertexBuffer9 *src_descs,
3257 UINT rect_count, IDirect3DVertexBuffer9 *dst_descs, D3DCOMPOSERECTSOP operation, INT offset_x, INT offset_y)
3258 {
3259 FIXME("iface %p, src_surface %p, dst_surface %p, src_descs %p, rect_count %u,\n"
3260 "dst_descs %p, operation %#x, offset_x %u, offset_y %u stub!\n",
3261 iface, src_surface, dst_surface, src_descs, rect_count,
3262 dst_descs, operation, offset_x, offset_y);
3263
3264 return E_NOTIMPL;
3265 }
3266
3267 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_PresentEx(IDirect3DDevice9Ex *iface,
3268 const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override,
3269 const RGNDATA *dirty_region, DWORD flags)
3270 {
3271 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
3272 UINT i;
3273 HRESULT hr;
3274
3275 TRACE("iface %p, src_rect %s, dst_rect %s, dst_window_override %p, dirty_region %p, flags %#x.\n",
3276 iface, wine_dbgstr_rect(src_rect), wine_dbgstr_rect(dst_rect),
3277 dst_window_override, dirty_region, flags);
3278
3279 if (device->device_state != D3D9_DEVICE_STATE_OK)
3280 return S_PRESENT_OCCLUDED;
3281
3282 wined3d_mutex_lock();
3283 for (i = 0; i < device->implicit_swapchain_count; ++i)
3284 {
3285 if (FAILED(hr = wined3d_swapchain_present(device->implicit_swapchains[i]->wined3d_swapchain, src_rect,
3286 dst_rect, dst_window_override, dirty_region, flags)))
3287 {
3288 wined3d_mutex_unlock();
3289 return hr;
3290 }
3291 }
3292 wined3d_mutex_unlock();
3293
3294 return D3D_OK;
3295 }
3296
3297 static HRESULT WINAPI d3d9_device_GetGPUThreadPriority(IDirect3DDevice9Ex *iface, INT *priority)
3298 {
3299 FIXME("iface %p, priority %p stub!\n", iface, priority);
3300
3301 return E_NOTIMPL;
3302 }
3303
3304 static HRESULT WINAPI d3d9_device_SetGPUThreadPriority(IDirect3DDevice9Ex *iface, INT priority)
3305 {
3306 FIXME("iface %p, priority %d stub!\n", iface, priority);
3307
3308 return E_NOTIMPL;
3309 }
3310
3311 static HRESULT WINAPI d3d9_device_WaitForVBlank(IDirect3DDevice9Ex *iface, UINT swapchain_idx)
3312 {
3313 FIXME("iface %p, swapchain_idx %u stub!\n", iface, swapchain_idx);
3314
3315 return E_NOTIMPL;
3316 }
3317
3318 static HRESULT WINAPI d3d9_device_CheckResourceResidency(IDirect3DDevice9Ex *iface,
3319 IDirect3DResource9 **resources, UINT32 resource_count)
3320 {
3321 FIXME("iface %p, resources %p, resource_count %u stub!\n",
3322 iface, resources, resource_count);
3323
3324 return E_NOTIMPL;
3325 }
3326
3327 static HRESULT WINAPI d3d9_device_SetMaximumFrameLatency(IDirect3DDevice9Ex *iface, UINT max_latency)
3328 {
3329 FIXME("iface %p, max_latency %u stub!\n", iface, max_latency);
3330
3331 return E_NOTIMPL;
3332 }
3333
3334 static HRESULT WINAPI d3d9_device_GetMaximumFrameLatency(IDirect3DDevice9Ex *iface, UINT *max_latency)
3335 {
3336 FIXME("iface %p, max_latency %p stub!\n", iface, max_latency);
3337
3338 *max_latency = 2;
3339
3340 return E_NOTIMPL;
3341 }
3342
3343 static HRESULT WINAPI d3d9_device_CheckDeviceState(IDirect3DDevice9Ex *iface, HWND dst_window)
3344 {
3345 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
3346 struct wined3d_swapchain_desc swapchain_desc;
3347
3348 TRACE("iface %p, dst_window %p.\n", iface, dst_window);
3349
3350 wined3d_mutex_lock();
3351 wined3d_swapchain_get_desc(device->implicit_swapchains[0]->wined3d_swapchain, &swapchain_desc);
3352 wined3d_mutex_unlock();
3353
3354 if (swapchain_desc.windowed)
3355 return D3D_OK;
3356
3357 /* FIXME: This is actually supposed to check if any other device is in
3358 * fullscreen mode. */
3359 if (dst_window != swapchain_desc.device_window)
3360 return device->device_state == D3D9_DEVICE_STATE_OK ? S_PRESENT_OCCLUDED : D3D_OK;
3361
3362 return device->device_state == D3D9_DEVICE_STATE_OK ? D3D_OK : S_PRESENT_OCCLUDED;
3363 }
3364
3365 static HRESULT WINAPI d3d9_device_CreateRenderTargetEx(IDirect3DDevice9Ex *iface,
3366 UINT width, UINT height, D3DFORMAT format, D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality,
3367 BOOL lockable, IDirect3DSurface9 **surface, HANDLE *shared_handle, DWORD usage)
3368 {
3369 FIXME("iface %p, width %u, height %u, format %#x, multisample_type %#x, multisample_quality %u,\n"
3370 "lockable %#x, surface %p, shared_handle %p, usage %#x stub!\n",
3371 iface, width, height, format, multisample_type, multisample_quality,
3372 lockable, surface, shared_handle, usage);
3373
3374 *surface = NULL;
3375 if (shared_handle)
3376 FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
3377
3378 return E_NOTIMPL;
3379 }
3380
3381 static HRESULT WINAPI d3d9_device_CreateOffscreenPlainSurfaceEx(IDirect3DDevice9Ex *iface,
3382 UINT width, UINT height, D3DFORMAT format, D3DPOOL pool, IDirect3DSurface9 **surface,
3383 HANDLE *shared_handle, DWORD usage)
3384 {
3385 FIXME("iface %p, width %u, height %u, format %#x, pool %#x, surface %p, shared_handle %p, usage %#x stub!\n",
3386 iface, width, height, format, pool, surface, shared_handle, usage);
3387
3388 return E_NOTIMPL;
3389 }
3390
3391 static HRESULT WINAPI d3d9_device_CreateDepthStencilSurfaceEx(IDirect3DDevice9Ex *iface,
3392 UINT width, UINT height, D3DFORMAT format, D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality,
3393 BOOL discard, IDirect3DSurface9 **surface, HANDLE *shared_handle, DWORD usage)
3394 {
3395 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
3396 DWORD flags = WINED3D_TEXTURE_CREATE_MAPPABLE;
3397
3398 TRACE("iface %p, width %u, height %u, format %#x, multisample_type %#x, multisample_quality %u, "
3399 "discard %#x, surface %p, shared_handle %p, usage %#x.\n",
3400 iface, width, height, format, multisample_type, multisample_quality,
3401 discard, surface, shared_handle, usage);
3402
3403 if (usage & D3DUSAGE_DEPTHSTENCIL)
3404 {
3405 WARN("Invalid usage %#x.\n", usage);
3406 return D3DERR_INVALIDCALL;
3407 }
3408
3409 if (shared_handle)
3410 FIXME("Resource sharing not implemented, *shared_handle %p.\n", *shared_handle);
3411
3412 if (discard)
3413 flags |= WINED3D_TEXTURE_CREATE_DISCARD;
3414
3415 return d3d9_device_create_surface(device, width, height, format, flags, surface,
3416 D3DUSAGE_DEPTHSTENCIL | usage, D3DPOOL_DEFAULT, multisample_type, multisample_quality, NULL);
3417 }
3418
3419 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_ResetEx(IDirect3DDevice9Ex *iface,
3420 D3DPRESENT_PARAMETERS *present_parameters, D3DDISPLAYMODEEX *mode)
3421 {
3422 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
3423
3424 TRACE("iface %p, present_parameters %p, mode %p.\n", iface, present_parameters, mode);
3425
3426 return d3d9_device_reset(device, present_parameters, mode);
3427 }
3428
3429 static HRESULT WINAPI d3d9_device_GetDisplayModeEx(IDirect3DDevice9Ex *iface,
3430 UINT swapchain_idx, D3DDISPLAYMODEEX *mode, D3DDISPLAYROTATION *rotation)
3431 {
3432 struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
3433 struct wined3d_display_mode wined3d_mode;
3434 HRESULT hr;
3435
3436 TRACE("iface %p, swapchain_idx %u, mode %p, rotation %p.\n",
3437 iface, swapchain_idx, mode, rotation);
3438
3439 if (mode->Size != sizeof(*mode))
3440 return D3DERR_INVALIDCALL;
3441
3442 wined3d_mutex_lock();
3443 hr = wined3d_device_get_display_mode(device->wined3d_device, swapchain_idx, &wined3d_mode,
3444 (enum wined3d_display_rotation *)rotation);
3445 wined3d_mutex_unlock();
3446
3447 if (SUCCEEDED(hr))
3448 {
3449 mode->Width = wined3d_mode.width;
3450 mode->Height = wined3d_mode.height;
3451 mode->RefreshRate = wined3d_mode.refresh_rate;
3452 mode->Format = d3dformat_from_wined3dformat(wined3d_mode.format_id);
3453 mode->ScanLineOrdering = wined3d_mode.scanline_ordering;
3454 }
3455
3456 return hr;
3457 }
3458
3459 static const struct IDirect3DDevice9ExVtbl d3d9_device_vtbl =
3460 {
3461 /* IUnknown */
3462 d3d9_device_QueryInterface,
3463 d3d9_device_AddRef,
3464 d3d9_device_Release,
3465 /* IDirect3DDevice9 */
3466 d3d9_device_TestCooperativeLevel,
3467 d3d9_device_GetAvailableTextureMem,
3468 d3d9_device_EvictManagedResources,
3469 d3d9_device_GetDirect3D,
3470 d3d9_device_GetDeviceCaps,
3471 d3d9_device_GetDisplayMode,
3472 d3d9_device_GetCreationParameters,
3473 d3d9_device_SetCursorProperties,
3474 d3d9_device_SetCursorPosition,
3475 d3d9_device_ShowCursor,
3476 d3d9_device_CreateAdditionalSwapChain,
3477 d3d9_device_GetSwapChain,
3478 d3d9_device_GetNumberOfSwapChains,
3479 d3d9_device_Reset,
3480 d3d9_device_Present,
3481 d3d9_device_GetBackBuffer,
3482 d3d9_device_GetRasterStatus,
3483 d3d9_device_SetDialogBoxMode,
3484 d3d9_device_SetGammaRamp,
3485 d3d9_device_GetGammaRamp,
3486 d3d9_device_CreateTexture,
3487 d3d9_device_CreateVolumeTexture,
3488 d3d9_device_CreateCubeTexture,
3489 d3d9_device_CreateVertexBuffer,
3490 d3d9_device_CreateIndexBuffer,
3491 d3d9_device_CreateRenderTarget,
3492 d3d9_device_CreateDepthStencilSurface,
3493 d3d9_device_UpdateSurface,
3494 d3d9_device_UpdateTexture,
3495 d3d9_device_GetRenderTargetData,
3496 d3d9_device_GetFrontBufferData,
3497 d3d9_device_StretchRect,
3498 d3d9_device_ColorFill,
3499 d3d9_device_CreateOffscreenPlainSurface,
3500 d3d9_device_SetRenderTarget,
3501 d3d9_device_GetRenderTarget,
3502 d3d9_device_SetDepthStencilSurface,
3503 d3d9_device_GetDepthStencilSurface,
3504 d3d9_device_BeginScene,
3505 d3d9_device_EndScene,
3506 d3d9_device_Clear,
3507 d3d9_device_SetTransform,
3508 d3d9_device_GetTransform,
3509 d3d9_device_MultiplyTransform,
3510 d3d9_device_SetViewport,
3511 d3d9_device_GetViewport,
3512 d3d9_device_SetMaterial,
3513 d3d9_device_GetMaterial,
3514 d3d9_device_SetLight,
3515 d3d9_device_GetLight,
3516 d3d9_device_LightEnable,
3517 d3d9_device_GetLightEnable,
3518 d3d9_device_SetClipPlane,
3519 d3d9_device_GetClipPlane,
3520 d3d9_device_SetRenderState,
3521 d3d9_device_GetRenderState,
3522 d3d9_device_CreateStateBlock,
3523 d3d9_device_BeginStateBlock,
3524 d3d9_device_EndStateBlock,
3525 d3d9_device_SetClipStatus,
3526 d3d9_device_GetClipStatus,
3527 d3d9_device_GetTexture,
3528 d3d9_device_SetTexture,
3529 d3d9_device_GetTextureStageState,
3530 d3d9_device_SetTextureStageState,
3531 d3d9_device_GetSamplerState,
3532 d3d9_device_SetSamplerState,
3533 d3d9_device_ValidateDevice,
3534 d3d9_device_SetPaletteEntries,
3535 d3d9_device_GetPaletteEntries,
3536 d3d9_device_SetCurrentTexturePalette,
3537 d3d9_device_GetCurrentTexturePalette,
3538 d3d9_device_SetScissorRect,
3539 d3d9_device_GetScissorRect,
3540 d3d9_device_SetSoftwareVertexProcessing,
3541 d3d9_device_GetSoftwareVertexProcessing,
3542 d3d9_device_SetNPatchMode,
3543 d3d9_device_GetNPatchMode,
3544 d3d9_device_DrawPrimitive,
3545 d3d9_device_DrawIndexedPrimitive,
3546 d3d9_device_DrawPrimitiveUP,
3547 d3d9_device_DrawIndexedPrimitiveUP,
3548 d3d9_device_ProcessVertices,
3549 d3d9_device_CreateVertexDeclaration,
3550 d3d9_device_SetVertexDeclaration,
3551 d3d9_device_GetVertexDeclaration,
3552 d3d9_device_SetFVF,
3553 d3d9_device_GetFVF,
3554 d3d9_device_CreateVertexShader,
3555 d3d9_device_SetVertexShader,
3556 d3d9_device_GetVertexShader,
3557 d3d9_device_SetVertexShaderConstantF,
3558 d3d9_device_GetVertexShaderConstantF,
3559 d3d9_device_SetVertexShaderConstantI,
3560 d3d9_device_GetVertexShaderConstantI,
3561 d3d9_device_SetVertexShaderConstantB,
3562 d3d9_device_GetVertexShaderConstantB,
3563 d3d9_device_SetStreamSource,
3564 d3d9_device_GetStreamSource,
3565 d3d9_device_SetStreamSourceFreq,
3566 d3d9_device_GetStreamSourceFreq,
3567 d3d9_device_SetIndices,
3568 d3d9_device_GetIndices,
3569 d3d9_device_CreatePixelShader,
3570 d3d9_device_SetPixelShader,
3571 d3d9_device_GetPixelShader,
3572 d3d9_device_SetPixelShaderConstantF,
3573 d3d9_device_GetPixelShaderConstantF,
3574 d3d9_device_SetPixelShaderConstantI,
3575 d3d9_device_GetPixelShaderConstantI,
3576 d3d9_device_SetPixelShaderConstantB,
3577 d3d9_device_GetPixelShaderConstantB,
3578 d3d9_device_DrawRectPatch,
3579 d3d9_device_DrawTriPatch,
3580 d3d9_device_DeletePatch,
3581 d3d9_device_CreateQuery,
3582 /* IDirect3DDevice9Ex */
3583 d3d9_device_SetConvolutionMonoKernel,
3584 d3d9_device_ComposeRects,
3585 d3d9_device_PresentEx,
3586 d3d9_device_GetGPUThreadPriority,
3587 d3d9_device_SetGPUThreadPriority,
3588 d3d9_device_WaitForVBlank,
3589 d3d9_device_CheckResourceResidency,
3590 d3d9_device_SetMaximumFrameLatency,
3591 d3d9_device_GetMaximumFrameLatency,
3592 d3d9_device_CheckDeviceState,
3593 d3d9_device_CreateRenderTargetEx,
3594 d3d9_device_CreateOffscreenPlainSurfaceEx,
3595 d3d9_device_CreateDepthStencilSurfaceEx,
3596 d3d9_device_ResetEx,
3597 d3d9_device_GetDisplayModeEx,
3598 };
3599
3600 static inline struct d3d9_device *device_from_device_parent(struct wined3d_device_parent *device_parent)
3601 {
3602 return CONTAINING_RECORD(device_parent, struct d3d9_device, device_parent);
3603 }
3604
3605 static void CDECL device_parent_wined3d_device_created(struct wined3d_device_parent *device_parent,
3606 struct wined3d_device *device)
3607 {
3608 TRACE("device_parent %p, device %p.\n", device_parent, device);
3609 }
3610
3611 static void CDECL device_parent_mode_changed(struct wined3d_device_parent *device_parent)
3612 {
3613 TRACE("device_parent %p.\n", device_parent);
3614 }
3615
3616 static void CDECL device_parent_activate(struct wined3d_device_parent *device_parent, BOOL activate)
3617 {
3618 struct d3d9_device *device = device_from_device_parent(device_parent);
3619
3620 TRACE("device_parent %p, activate %#x.\n", device_parent, activate);
3621
3622 if (!device->d3d_parent)
3623 return;
3624
3625 if (!activate)
3626 InterlockedCompareExchange(&device->device_state, D3D9_DEVICE_STATE_LOST, D3D9_DEVICE_STATE_OK);
3627 else if (device->d3d_parent->extended)
3628 InterlockedCompareExchange(&device->device_state, D3D9_DEVICE_STATE_OK, D3D9_DEVICE_STATE_LOST);
3629 else
3630 InterlockedCompareExchange(&device->device_state, D3D9_DEVICE_STATE_NOT_RESET, D3D9_DEVICE_STATE_LOST);
3631 }
3632
3633 static HRESULT CDECL device_parent_surface_created(struct wined3d_device_parent *device_parent,
3634 struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx,
3635 void **parent, const struct wined3d_parent_ops **parent_ops)
3636 {
3637 struct d3d9_surface *d3d_surface;
3638
3639 TRACE("device_parent %p, wined3d_texture %p, sub_resource_idx %u, parent %p, parent_ops %p.\n",
3640 device_parent, wined3d_texture, sub_resource_idx, parent, parent_ops);
3641
3642 if (!(d3d_surface = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*d3d_surface))))
3643 return E_OUTOFMEMORY;
3644
3645 surface_init(d3d_surface, wined3d_texture, sub_resource_idx, parent_ops);
3646 *parent = d3d_surface;
3647 TRACE("Created surface %p.\n", d3d_surface);
3648
3649 return D3D_OK;
3650 }
3651
3652 static HRESULT CDECL device_parent_volume_created(struct wined3d_device_parent *device_parent,
3653 struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx,
3654 void **parent, const struct wined3d_parent_ops **parent_ops)
3655 {
3656 struct d3d9_volume *d3d_volume;
3657
3658 TRACE("device_parent %p, texture %p, sub_resource_idx %u, parent %p, parent_ops %p.\n",
3659 device_parent, wined3d_texture, sub_resource_idx, parent, parent_ops);
3660
3661 if (!(d3d_volume = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*d3d_volume))))
3662 return E_OUTOFMEMORY;
3663
3664 volume_init(d3d_volume, wined3d_texture, sub_resource_idx, parent_ops);
3665 *parent = d3d_volume;
3666 TRACE("Created volume %p.\n", d3d_volume);
3667
3668 return D3D_OK;
3669 }
3670
3671 static HRESULT CDECL device_parent_create_swapchain_texture(struct wined3d_device_parent *device_parent,
3672 void *container_parent, const struct wined3d_resource_desc *desc, struct wined3d_texture **texture)
3673 {
3674 struct d3d9_device *device = device_from_device_parent(device_parent);
3675 struct d3d9_surface *d3d_surface;
3676 HRESULT hr;
3677
3678 TRACE("device_parent %p, container_parent %p, desc %p, texture %p.\n",
3679 device_parent, container_parent, desc, texture);
3680
3681 if (container_parent == device_parent)
3682 container_parent = &device->IDirect3DDevice9Ex_iface;
3683
3684 if (FAILED(hr = wined3d_texture_create(device->wined3d_device, desc, 1,
3685 WINED3D_TEXTURE_CREATE_MAPPABLE, NULL, container_parent, &d3d9_null_wined3d_parent_ops, texture)))
3686 {
3687 WARN("Failed to create texture, hr %#x.\n", hr);
3688 return hr;
3689 }
3690
3691 d3d_surface = wined3d_resource_get_parent(wined3d_texture_get_sub_resource(*texture, 0));
3692 d3d_surface->parent_device = &device->IDirect3DDevice9Ex_iface;
3693
3694 return hr;
3695 }
3696
3697 static HRESULT CDECL device_parent_create_swapchain(struct wined3d_device_parent *device_parent,
3698 struct wined3d_swapchain_desc *desc, struct wined3d_swapchain **swapchain)
3699 {
3700 struct d3d9_device *device = device_from_device_parent(device_parent);
3701 struct d3d9_swapchain *d3d_swapchain;
3702 HRESULT hr;
3703
3704 TRACE("device_parent %p, desc %p, swapchain %p\n", device_parent, desc, swapchain);
3705
3706 hr = d3d9_swapchain_create(device, desc, &d3d_swapchain);
3707 if (FAILED(hr))
3708 {
3709 WARN("Failed to create swapchain, hr %#x.\n", hr);
3710 *swapchain = NULL;
3711 return hr;
3712 }
3713
3714 *swapchain = d3d_swapchain->wined3d_swapchain;
3715 wined3d_swapchain_incref(*swapchain);
3716 IDirect3DSwapChain9Ex_Release(&d3d_swapchain->IDirect3DSwapChain9Ex_iface);
3717
3718 return hr;
3719 }
3720
3721 static const struct wined3d_device_parent_ops d3d9_wined3d_device_parent_ops =
3722 {
3723 device_parent_wined3d_device_created,
3724 device_parent_mode_changed,
3725 device_parent_activate,
3726 device_parent_surface_created,
3727 device_parent_volume_created,
3728 device_parent_create_swapchain_texture,
3729 device_parent_create_swapchain,
3730 };
3731
3732 static void setup_fpu(void)
3733 {
3734 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3735 WORD cw;
3736 __asm__ volatile ("fnstcw %0" : "=m" (cw));
3737 cw = (cw & ~0xf3f) | 0x3f;
3738 __asm__ volatile ("fldcw %0" : : "m" (cw));
3739 #elif defined(__i386__) && defined(_MSC_VER)
3740 WORD cw;
3741 __asm fnstcw cw;
3742 cw = (cw & ~0xf3f) | 0x3f;
3743 __asm fldcw cw;
3744 #else
3745 FIXME("FPU setup not implemented for this platform.\n");
3746 #endif
3747 }
3748
3749 HRESULT device_init(struct d3d9_device *device, struct d3d9 *parent, struct wined3d *wined3d,
3750 UINT adapter, D3DDEVTYPE device_type, HWND focus_window, DWORD flags,
3751 D3DPRESENT_PARAMETERS *parameters, D3DDISPLAYMODEEX *mode)
3752 {
3753 struct wined3d_swapchain_desc *swapchain_desc;
3754 UINT i, count = 1;
3755 HRESULT hr;
3756
3757 if (mode)
3758 FIXME("Ignoring display mode.\n");
3759
3760 device->IDirect3DDevice9Ex_iface.lpVtbl = &d3d9_device_vtbl;
3761 device->device_parent.ops = &d3d9_wined3d_device_parent_ops;
3762 device->refcount = 1;
3763
3764 if (!(flags & D3DCREATE_FPU_PRESERVE)) setup_fpu();
3765
3766 wined3d_mutex_lock();
3767 hr = wined3d_device_create(wined3d, adapter, device_type, focus_window, flags, 4,
3768 &device->device_parent, &device->wined3d_device);
3769 if (FAILED(hr))
3770 {
3771 WARN("Failed to create wined3d device, hr %#x.\n", hr);
3772 wined3d_mutex_unlock();
3773 return hr;
3774 }
3775
3776 if (flags & D3DCREATE_ADAPTERGROUP_DEVICE)
3777 {
3778 WINED3DCAPS caps;
3779
3780 wined3d_get_device_caps(wined3d, adapter, device_type, &caps);
3781 count = caps.NumberOfAdaptersInGroup;
3782 }
3783
3784 if (flags & D3DCREATE_MULTITHREADED)
3785 wined3d_device_set_multithreaded(device->wined3d_device);
3786
3787 if (!parameters->Windowed)
3788 {
3789 if (!focus_window)
3790 focus_window = parameters->hDeviceWindow;
3791 if (FAILED(hr = wined3d_device_acquire_focus_window(device->wined3d_device, focus_window)))
3792 {
3793 ERR("Failed to acquire focus window, hr %#x.\n", hr);
3794 wined3d_device_decref(device->wined3d_device);
3795 wined3d_mutex_unlock();
3796 return hr;
3797 }
3798
3799 for (i = 0; i < count; ++i)
3800 {
3801 HWND device_window = parameters[i].hDeviceWindow;
3802
3803 if (!device_window) device_window = focus_window;
3804 wined3d_device_setup_fullscreen_window(device->wined3d_device, device_window,
3805 parameters[i].BackBufferWidth,
3806 parameters[i].BackBufferHeight);
3807 }
3808 }
3809
3810 swapchain_desc = HeapAlloc(GetProcessHeap(), 0, sizeof(*swapchain_desc) * count);
3811 if (!swapchain_desc)
3812 {
3813 ERR("Failed to allocate wined3d parameters.\n");
3814 wined3d_device_release_focus_window(device->wined3d_device);
3815 wined3d_device_decref(device->wined3d_device);
3816 wined3d_mutex_unlock();
3817 return E_OUTOFMEMORY;
3818 }
3819
3820 for (i = 0; i < count; ++i)
3821 {
3822 if (!wined3d_swapchain_desc_from_present_parameters(&swapchain_desc[i], &parameters[i],
3823 parent->extended))
3824 {
3825 wined3d_device_release_focus_window(device->wined3d_device);
3826 wined3d_device_decref(device->wined3d_device);
3827 HeapFree(GetProcessHeap(), 0, swapchain_desc);
3828 wined3d_mutex_unlock();
3829 return D3DERR_INVALIDCALL;
3830 }
3831 }
3832
3833 hr = wined3d_device_init_3d(device->wined3d_device, swapchain_desc);
3834 if (FAILED(hr))
3835 {
3836 WARN("Failed to initialize 3D, hr %#x.\n", hr);
3837 wined3d_device_release_focus_window(device->wined3d_device);
3838 HeapFree(GetProcessHeap(), 0, swapchain_desc);
3839 wined3d_device_decref(device->wined3d_device);
3840 wined3d_mutex_unlock();
3841 return hr;
3842 }
3843
3844 if (FAILED(hr = d3d9_device_get_swapchains(device)))
3845 {
3846 wined3d_device_uninit_3d(device->wined3d_device);
3847 wined3d_device_release_focus_window(device->wined3d_device);
3848 wined3d_device_decref(device->wined3d_device);
3849 wined3d_mutex_unlock();
3850 return E_OUTOFMEMORY;
3851 }
3852
3853 for (i = 0; i < count; ++i)
3854 {
3855 present_parameters_from_wined3d_swapchain_desc(&parameters[i], &swapchain_desc[i]);
3856 }
3857
3858 wined3d_mutex_unlock();
3859
3860 HeapFree(GetProcessHeap(), 0, swapchain_desc);
3861
3862 /* Initialize the converted declaration array. This creates a valid pointer
3863 * and when adding decls HeapReAlloc() can be used without further checking. */
3864 device->fvf_decls = HeapAlloc(GetProcessHeap(), 0, 0);
3865 if (!device->fvf_decls)
3866 {
3867 ERR("Failed to allocate FVF vertex declaration map memory.\n");
3868 wined3d_mutex_lock();
3869 HeapFree(GetProcessHeap(), 0, device->implicit_swapchains);
3870 wined3d_device_uninit_3d(device->wined3d_device);
3871 wined3d_device_release_focus_window(device->wined3d_device);
3872 wined3d_device_decref(device->wined3d_device);
3873 wined3d_mutex_unlock();
3874 return E_OUTOFMEMORY;
3875 }
3876
3877 IDirect3D9Ex_AddRef(&parent->IDirect3D9Ex_iface);
3878 device->d3d_parent = parent;
3879
3880 return D3D_OK;
3881 }