1 /*
2 * Copyright 1997-2000 Marcus Meissner
3 * Copyright 1998-2000 Lionel Ulmer
4 * Copyright 2000-2001 TransGaming Technologies Inc.
5 * Copyright 2006 Stefan Dösinger
6 * Copyright 2008 Denver Gingerich
7 * Copyright 2007-2008, 2011, 2013 Stefan Dösinger for CodeWeavers
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24 #include "config.h"
25 #include "wine/port.h"
26
27 #include "ddraw_private.h"
28
29 #include "wine/exception.h"
30
31 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
32
33 static const struct ddraw *exclusive_ddraw;
34 static HWND exclusive_window;
35
36 /* Device identifier. Don't relay it to WineD3D */
37 static const DDDEVICEIDENTIFIER2 deviceidentifier =
38 {
39 "vga.dll", /* default 2D driver */
40 "DirectDraw HAL",
41 { { 0x00010001, 0x00010001 } },
42 0, 0, 0, 0,
43 /* a8373c10-7ac4-4deb-849a-009844d08b2d */
44 {0xa8373c10,0x7ac4,0x4deb, {0x84,0x9a,0x00,0x98,0x44,0xd0,0x8b,0x2d}},
45 0
46 };
47
48 static struct enum_device_entry
49 {
50 char interface_name[100];
51 char device_name[100];
52 const GUID *device_guid;
53 DWORD remove_caps;
54 } device_list7[] =
55 {
56 /* T&L HAL device */
57 {
58 "WINE Direct3D7 Hardware Transform and Lighting acceleration using WineD3D",
59 "Wine D3D7 T&L HAL",
60 &IID_IDirect3DTnLHalDevice,
61 0,
62 },
63
64 /* HAL device */
65 {
66 "WINE Direct3D7 Hardware acceleration using WineD3D",
67 "Direct3D HAL",
68 &IID_IDirect3DHALDevice,
69 0,
70 },
71
72 /* RGB device */
73 {
74 "WINE Direct3D7 RGB Software Emulation using WineD3D",
75 "Wine D3D7 RGB",
76 &IID_IDirect3DRGBDevice,
77 D3DDEVCAPS_HWTRANSFORMANDLIGHT,
78 },
79 };
80
ddraw_null_wined3d_object_destroyed(void * parent)81 static void STDMETHODCALLTYPE ddraw_null_wined3d_object_destroyed(void *parent) {}
82
83 const struct wined3d_parent_ops ddraw_null_wined3d_parent_ops =
84 {
85 ddraw_null_wined3d_object_destroyed,
86 };
87
impl_from_IDirectDraw(IDirectDraw * iface)88 static inline struct ddraw *impl_from_IDirectDraw(IDirectDraw *iface)
89 {
90 return CONTAINING_RECORD(iface, struct ddraw, IDirectDraw_iface);
91 }
92
impl_from_IDirectDraw2(IDirectDraw2 * iface)93 static inline struct ddraw *impl_from_IDirectDraw2(IDirectDraw2 *iface)
94 {
95 return CONTAINING_RECORD(iface, struct ddraw, IDirectDraw2_iface);
96 }
97
impl_from_IDirectDraw4(IDirectDraw4 * iface)98 static inline struct ddraw *impl_from_IDirectDraw4(IDirectDraw4 *iface)
99 {
100 return CONTAINING_RECORD(iface, struct ddraw, IDirectDraw4_iface);
101 }
102
impl_from_IDirectDraw7(IDirectDraw7 * iface)103 static inline struct ddraw *impl_from_IDirectDraw7(IDirectDraw7 *iface)
104 {
105 return CONTAINING_RECORD(iface, struct ddraw, IDirectDraw7_iface);
106 }
107
impl_from_IDirect3D(IDirect3D * iface)108 static inline struct ddraw *impl_from_IDirect3D(IDirect3D *iface)
109 {
110 return CONTAINING_RECORD(iface, struct ddraw, IDirect3D_iface);
111 }
112
impl_from_IDirect3D2(IDirect3D2 * iface)113 static inline struct ddraw *impl_from_IDirect3D2(IDirect3D2 *iface)
114 {
115 return CONTAINING_RECORD(iface, struct ddraw, IDirect3D2_iface);
116 }
117
impl_from_IDirect3D3(IDirect3D3 * iface)118 static inline struct ddraw *impl_from_IDirect3D3(IDirect3D3 *iface)
119 {
120 return CONTAINING_RECORD(iface, struct ddraw, IDirect3D3_iface);
121 }
122
impl_from_IDirect3D7(IDirect3D7 * iface)123 static inline struct ddraw *impl_from_IDirect3D7(IDirect3D7 *iface)
124 {
125 return CONTAINING_RECORD(iface, struct ddraw, IDirect3D7_iface);
126 }
127
ddraw7_QueryInterface(IDirectDraw7 * iface,REFIID riid,void ** out)128 static HRESULT WINAPI ddraw7_QueryInterface(IDirectDraw7 *iface, REFIID riid, void **out)
129 {
130 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
131
132 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
133
134 if (!riid)
135 {
136 *out = NULL;
137 return DDERR_INVALIDPARAMS;
138 }
139
140 /* The refcount unit test revealed that an IDirect3D7 interface can only
141 * be queried from a DirectDraw object that was created as an IDirectDraw7
142 * interface. The older interfaces can query any IDirect3D version except
143 * 7, because they are all initially created as IDirectDraw. This isn't
144 * really crucial behavior, and messy to implement with the common
145 * creation function, so it has been left out here. */
146 if (IsEqualGUID(&IID_IDirectDraw7, riid)
147 || IsEqualGUID(&IID_IUnknown, riid))
148 {
149 *out = &ddraw->IDirectDraw7_iface;
150 TRACE("Returning IDirectDraw7 interface %p.\n", *out);
151 }
152 else if (IsEqualGUID(&IID_IDirectDraw4, riid))
153 {
154 *out = &ddraw->IDirectDraw4_iface;
155 TRACE("Returning IDirectDraw4 interface %p.\n", *out);
156 }
157 else if (IsEqualGUID(&IID_IDirectDraw2, riid))
158 {
159 *out = &ddraw->IDirectDraw2_iface;
160 TRACE("Returning IDirectDraw2 interface %p.\n", *out);
161 }
162 else if (IsEqualGUID(&IID_IDirectDraw, riid))
163 {
164 *out = &ddraw->IDirectDraw_iface;
165 TRACE("Returning IDirectDraw interface %p.\n", *out);
166 }
167 else if (IsEqualGUID(&IID_IDirect3D7, riid))
168 {
169 ddraw->d3dversion = 7;
170 *out = &ddraw->IDirect3D7_iface;
171 TRACE("Returning Direct3D7 interface %p.\n", *out);
172 }
173 else if (IsEqualGUID(&IID_IDirect3D3, riid))
174 {
175 ddraw->d3dversion = 3;
176 *out = &ddraw->IDirect3D3_iface;
177 TRACE("Returning Direct3D3 interface %p.\n", *out);
178 }
179 else if (IsEqualGUID(&IID_IDirect3D2, riid))
180 {
181 ddraw->d3dversion = 2;
182 *out = &ddraw->IDirect3D2_iface;
183 TRACE("Returning Direct3D2 interface %p.\n", *out);
184 }
185 else if (IsEqualGUID(&IID_IDirect3D, riid))
186 {
187 ddraw->d3dversion = 1;
188 *out = &ddraw->IDirect3D_iface;
189 TRACE("Returning Direct3D interface %p.\n", *out);
190 }
191 /* Unknown interface */
192 else
193 {
194 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
195 *out = NULL;
196 return E_NOINTERFACE;
197 }
198
199 IUnknown_AddRef((IUnknown *)*out);
200 return S_OK;
201 }
202
ddraw4_QueryInterface(IDirectDraw4 * iface,REFIID riid,void ** object)203 static HRESULT WINAPI ddraw4_QueryInterface(IDirectDraw4 *iface, REFIID riid, void **object)
204 {
205 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
206
207 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
208
209 return ddraw7_QueryInterface(&ddraw->IDirectDraw7_iface, riid, object);
210 }
211
ddraw2_QueryInterface(IDirectDraw2 * iface,REFIID riid,void ** object)212 static HRESULT WINAPI ddraw2_QueryInterface(IDirectDraw2 *iface, REFIID riid, void **object)
213 {
214 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
215
216 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
217
218 return ddraw7_QueryInterface(&ddraw->IDirectDraw7_iface, riid, object);
219 }
220
ddraw1_QueryInterface(IDirectDraw * iface,REFIID riid,void ** object)221 static HRESULT WINAPI ddraw1_QueryInterface(IDirectDraw *iface, REFIID riid, void **object)
222 {
223 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
224
225 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
226
227 return ddraw7_QueryInterface(&ddraw->IDirectDraw7_iface, riid, object);
228 }
229
d3d7_QueryInterface(IDirect3D7 * iface,REFIID riid,void ** object)230 static HRESULT WINAPI d3d7_QueryInterface(IDirect3D7 *iface, REFIID riid, void **object)
231 {
232 struct ddraw *ddraw = impl_from_IDirect3D7(iface);
233
234 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
235
236 return ddraw7_QueryInterface(&ddraw->IDirectDraw7_iface, riid, object);
237 }
238
d3d3_QueryInterface(IDirect3D3 * iface,REFIID riid,void ** object)239 static HRESULT WINAPI d3d3_QueryInterface(IDirect3D3 *iface, REFIID riid, void **object)
240 {
241 struct ddraw *ddraw = impl_from_IDirect3D3(iface);
242
243 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
244
245 return ddraw7_QueryInterface(&ddraw->IDirectDraw7_iface, riid, object);
246 }
247
d3d2_QueryInterface(IDirect3D2 * iface,REFIID riid,void ** object)248 static HRESULT WINAPI d3d2_QueryInterface(IDirect3D2 *iface, REFIID riid, void **object)
249 {
250 struct ddraw *ddraw = impl_from_IDirect3D2(iface);
251
252 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
253
254 return ddraw7_QueryInterface(&ddraw->IDirectDraw7_iface, riid, object);
255 }
256
d3d1_QueryInterface(IDirect3D * iface,REFIID riid,void ** object)257 static HRESULT WINAPI d3d1_QueryInterface(IDirect3D *iface, REFIID riid, void **object)
258 {
259 struct ddraw *ddraw = impl_from_IDirect3D(iface);
260
261 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
262
263 return ddraw7_QueryInterface(&ddraw->IDirectDraw7_iface, riid, object);
264 }
265
266 /*****************************************************************************
267 * IDirectDraw7::AddRef
268 *
269 * Increases the interfaces refcount, basically
270 *
271 * DDraw refcounting is a bit tricky. The different DirectDraw interface
272 * versions have individual refcounts, but the IDirect3D interfaces do not.
273 * All interfaces are from one object, that means calling QueryInterface on an
274 * IDirectDraw7 interface for an IDirectDraw4 interface does not create a new
275 * ddraw object.
276 *
277 * That means all AddRef and Release implementations of IDirectDrawX work
278 * with their own counter, and IDirect3DX::AddRef thunk to IDirectDraw (1),
279 * except of IDirect3D7 which thunks to IDirectDraw7
280 *
281 * Returns: The new refcount
282 *
283 *****************************************************************************/
ddraw7_AddRef(IDirectDraw7 * iface)284 static ULONG WINAPI ddraw7_AddRef(IDirectDraw7 *iface)
285 {
286 struct ddraw *This = impl_from_IDirectDraw7(iface);
287 ULONG ref = InterlockedIncrement(&This->ref7);
288
289 TRACE("%p increasing refcount to %u.\n", This, ref);
290
291 if(ref == 1) InterlockedIncrement(&This->numIfaces);
292
293 return ref;
294 }
295
ddraw4_AddRef(IDirectDraw4 * iface)296 static ULONG WINAPI ddraw4_AddRef(IDirectDraw4 *iface)
297 {
298 struct ddraw *This = impl_from_IDirectDraw4(iface);
299 ULONG ref = InterlockedIncrement(&This->ref4);
300
301 TRACE("%p increasing refcount to %u.\n", This, ref);
302
303 if (ref == 1) InterlockedIncrement(&This->numIfaces);
304
305 return ref;
306 }
307
ddraw2_AddRef(IDirectDraw2 * iface)308 static ULONG WINAPI ddraw2_AddRef(IDirectDraw2 *iface)
309 {
310 struct ddraw *This = impl_from_IDirectDraw2(iface);
311 ULONG ref = InterlockedIncrement(&This->ref2);
312
313 TRACE("%p increasing refcount to %u.\n", This, ref);
314
315 if (ref == 1) InterlockedIncrement(&This->numIfaces);
316
317 return ref;
318 }
319
ddraw1_AddRef(IDirectDraw * iface)320 static ULONG WINAPI ddraw1_AddRef(IDirectDraw *iface)
321 {
322 struct ddraw *This = impl_from_IDirectDraw(iface);
323 ULONG ref = InterlockedIncrement(&This->ref1);
324
325 TRACE("%p increasing refcount to %u.\n", This, ref);
326
327 if (ref == 1) InterlockedIncrement(&This->numIfaces);
328
329 return ref;
330 }
331
d3d7_AddRef(IDirect3D7 * iface)332 static ULONG WINAPI d3d7_AddRef(IDirect3D7 *iface)
333 {
334 struct ddraw *This = impl_from_IDirect3D7(iface);
335
336 TRACE("iface %p.\n", iface);
337
338 return ddraw7_AddRef(&This->IDirectDraw7_iface);
339 }
340
d3d3_AddRef(IDirect3D3 * iface)341 static ULONG WINAPI d3d3_AddRef(IDirect3D3 *iface)
342 {
343 struct ddraw *This = impl_from_IDirect3D3(iface);
344
345 TRACE("iface %p.\n", iface);
346
347 return ddraw1_AddRef(&This->IDirectDraw_iface);
348 }
349
d3d2_AddRef(IDirect3D2 * iface)350 static ULONG WINAPI d3d2_AddRef(IDirect3D2 *iface)
351 {
352 struct ddraw *This = impl_from_IDirect3D2(iface);
353
354 TRACE("iface %p.\n", iface);
355
356 return ddraw1_AddRef(&This->IDirectDraw_iface);
357 }
358
d3d1_AddRef(IDirect3D * iface)359 static ULONG WINAPI d3d1_AddRef(IDirect3D *iface)
360 {
361 struct ddraw *This = impl_from_IDirect3D(iface);
362
363 TRACE("iface %p.\n", iface);
364
365 return ddraw1_AddRef(&This->IDirectDraw_iface);
366 }
367
ddraw_destroy_swapchain(struct ddraw * ddraw)368 static void ddraw_destroy_swapchain(struct ddraw *ddraw)
369 {
370 TRACE("Destroying the swapchain.\n");
371
372 wined3d_swapchain_decref(ddraw->wined3d_swapchain);
373 ddraw->wined3d_swapchain = NULL;
374
375 if (!(ddraw->flags & DDRAW_NO3D))
376 {
377 UINT i;
378
379 for (i = 0; i < ddraw->numConvertedDecls; ++i)
380 {
381 wined3d_vertex_declaration_decref(ddraw->decls[i].decl);
382 }
383 heap_free(ddraw->decls);
384 ddraw->numConvertedDecls = 0;
385
386 if (FAILED(wined3d_device_uninit_3d(ddraw->wined3d_device)))
387 {
388 ERR("Failed to uninit 3D.\n");
389 }
390 else
391 {
392 /* Free the d3d window if one was created. */
393 if (ddraw->d3d_window && ddraw->d3d_window != ddraw->dest_window)
394 {
395 TRACE("Destroying the hidden render window %p.\n", ddraw->d3d_window);
396 DestroyWindow(ddraw->d3d_window);
397 ddraw->d3d_window = 0;
398 }
399 }
400
401 ddraw->flags &= ~DDRAW_D3D_INITIALIZED;
402 }
403 else
404 {
405 wined3d_device_uninit_gdi(ddraw->wined3d_device);
406 }
407
408 ddraw_set_swapchain_window(ddraw, NULL);
409
410 TRACE("Swapchain destroyed.\n");
411 }
412
413 /*****************************************************************************
414 * ddraw_destroy
415 *
416 * Destroys a ddraw object if all refcounts are 0. This is to share code
417 * between the IDirectDrawX::Release functions
418 *
419 * Params:
420 * This: DirectDraw object to destroy
421 *
422 *****************************************************************************/
ddraw_destroy(struct ddraw * This)423 static void ddraw_destroy(struct ddraw *This)
424 {
425 IDirectDraw7_SetCooperativeLevel(&This->IDirectDraw7_iface, NULL, DDSCL_NORMAL);
426 IDirectDraw7_RestoreDisplayMode(&This->IDirectDraw7_iface);
427
428 /* Destroy the device window if we created one */
429 if(This->devicewindow != 0)
430 {
431 TRACE(" (%p) Destroying the device window %p\n", This, This->devicewindow);
432 DestroyWindow(This->devicewindow);
433 This->devicewindow = 0;
434 }
435
436 wined3d_mutex_lock();
437 list_remove(&This->ddraw_list_entry);
438 wined3d_mutex_unlock();
439
440 if (This->wined3d_swapchain)
441 ddraw_destroy_swapchain(This);
442 wined3d_device_decref(This->wined3d_device);
443 wined3d_decref(This->wined3d);
444
445 if (This->d3ddevice)
446 This->d3ddevice->ddraw = NULL;
447
448 /* Now free the object */
449 heap_free(This);
450 }
451
452 /*****************************************************************************
453 * IDirectDraw7::Release
454 *
455 * Decreases the refcount. If the refcount falls to 0, the object is destroyed
456 *
457 * Returns: The new refcount
458 *****************************************************************************/
ddraw7_Release(IDirectDraw7 * iface)459 static ULONG WINAPI ddraw7_Release(IDirectDraw7 *iface)
460 {
461 struct ddraw *This = impl_from_IDirectDraw7(iface);
462 ULONG ref = InterlockedDecrement(&This->ref7);
463
464 TRACE("%p decreasing refcount to %u.\n", This, ref);
465
466 if (!ref && !InterlockedDecrement(&This->numIfaces))
467 ddraw_destroy(This);
468
469 return ref;
470 }
471
ddraw4_Release(IDirectDraw4 * iface)472 static ULONG WINAPI ddraw4_Release(IDirectDraw4 *iface)
473 {
474 struct ddraw *This = impl_from_IDirectDraw4(iface);
475 ULONG ref = InterlockedDecrement(&This->ref4);
476
477 TRACE("%p decreasing refcount to %u.\n", This, ref);
478
479 if (!ref && !InterlockedDecrement(&This->numIfaces))
480 ddraw_destroy(This);
481
482 return ref;
483 }
484
ddraw2_Release(IDirectDraw2 * iface)485 static ULONG WINAPI ddraw2_Release(IDirectDraw2 *iface)
486 {
487 struct ddraw *This = impl_from_IDirectDraw2(iface);
488 ULONG ref = InterlockedDecrement(&This->ref2);
489
490 TRACE("%p decreasing refcount to %u.\n", This, ref);
491
492 if (!ref && !InterlockedDecrement(&This->numIfaces))
493 ddraw_destroy(This);
494
495 return ref;
496 }
497
ddraw1_Release(IDirectDraw * iface)498 static ULONG WINAPI ddraw1_Release(IDirectDraw *iface)
499 {
500 struct ddraw *This = impl_from_IDirectDraw(iface);
501 ULONG ref = InterlockedDecrement(&This->ref1);
502
503 TRACE("%p decreasing refcount to %u.\n", This, ref);
504
505 if (!ref && !InterlockedDecrement(&This->numIfaces))
506 ddraw_destroy(This);
507
508 return ref;
509 }
510
d3d7_Release(IDirect3D7 * iface)511 static ULONG WINAPI d3d7_Release(IDirect3D7 *iface)
512 {
513 struct ddraw *This = impl_from_IDirect3D7(iface);
514
515 TRACE("iface %p.\n", iface);
516
517 return ddraw7_Release(&This->IDirectDraw7_iface);
518 }
519
d3d3_Release(IDirect3D3 * iface)520 static ULONG WINAPI d3d3_Release(IDirect3D3 *iface)
521 {
522 struct ddraw *This = impl_from_IDirect3D3(iface);
523
524 TRACE("iface %p.\n", iface);
525
526 return ddraw1_Release(&This->IDirectDraw_iface);
527 }
528
d3d2_Release(IDirect3D2 * iface)529 static ULONG WINAPI d3d2_Release(IDirect3D2 *iface)
530 {
531 struct ddraw *This = impl_from_IDirect3D2(iface);
532
533 TRACE("iface %p.\n", iface);
534
535 return ddraw1_Release(&This->IDirectDraw_iface);
536 }
537
d3d1_Release(IDirect3D * iface)538 static ULONG WINAPI d3d1_Release(IDirect3D *iface)
539 {
540 struct ddraw *This = impl_from_IDirect3D(iface);
541
542 TRACE("iface %p.\n", iface);
543
544 return ddraw1_Release(&This->IDirectDraw_iface);
545 }
546
547 /*****************************************************************************
548 * IDirectDraw methods
549 *****************************************************************************/
550
ddraw_set_focus_window(struct ddraw * ddraw,HWND window)551 static HRESULT ddraw_set_focus_window(struct ddraw *ddraw, HWND window)
552 {
553 /* FIXME: This looks wrong, exclusive mode should imply a destination
554 * window. */
555 if ((ddraw->cooperative_level & DDSCL_EXCLUSIVE) && ddraw->dest_window)
556 {
557 TRACE("Setting DDSCL_SETFOCUSWINDOW with an already set window, returning DDERR_HWNDALREADYSET.\n");
558 return DDERR_HWNDALREADYSET;
559 }
560
561 ddraw->focuswindow = window;
562
563 return DD_OK;
564 }
565
ddraw_attach_d3d_device(struct ddraw * ddraw,struct wined3d_swapchain_desc * swapchain_desc)566 static HRESULT ddraw_attach_d3d_device(struct ddraw *ddraw,
567 struct wined3d_swapchain_desc *swapchain_desc)
568 {
569 HWND window = swapchain_desc->device_window;
570 HRESULT hr;
571
572 TRACE("ddraw %p.\n", ddraw);
573
574 if (!window || window == GetDesktopWindow())
575 {
576 window = CreateWindowExA(0, DDRAW_WINDOW_CLASS_NAME, "Hidden D3D Window",
577 WS_DISABLED, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN),
578 NULL, NULL, NULL, NULL);
579 if (!window)
580 {
581 ERR("Failed to create window, last error %#x.\n", GetLastError());
582 return E_FAIL;
583 }
584
585 ShowWindow(window, SW_HIDE); /* Just to be sure */
586 WARN("No window for the Direct3DDevice, created hidden window %p.\n", window);
587
588 swapchain_desc->device_window = window;
589 }
590 else
591 {
592 TRACE("Using existing window %p for Direct3D rendering.\n", window);
593 }
594 ddraw->d3d_window = window;
595
596 /* Set this NOW, otherwise creating the depth stencil surface will cause a
597 * recursive loop until ram or emulated video memory is full. */
598 ddraw->flags |= DDRAW_D3D_INITIALIZED;
599 hr = wined3d_device_init_3d(ddraw->wined3d_device, swapchain_desc);
600 if (FAILED(hr))
601 {
602 ddraw->flags &= ~DDRAW_D3D_INITIALIZED;
603 return hr;
604 }
605
606 ddraw->declArraySize = 2;
607 if (!(ddraw->decls = heap_alloc_zero(ddraw->declArraySize * sizeof(*ddraw->decls))))
608 {
609 ERR("Error allocating an array for the converted vertex decls.\n");
610 ddraw->declArraySize = 0;
611 hr = wined3d_device_uninit_3d(ddraw->wined3d_device);
612 return E_OUTOFMEMORY;
613 }
614
615 TRACE("Successfully initialized 3D.\n");
616
617 return DD_OK;
618 }
619
ddraw_create_swapchain(struct ddraw * ddraw,HWND window,BOOL windowed)620 static HRESULT ddraw_create_swapchain(struct ddraw *ddraw, HWND window, BOOL windowed)
621 {
622 struct wined3d_swapchain_desc swapchain_desc;
623 struct wined3d_display_mode mode;
624 HRESULT hr = WINED3D_OK;
625
626 if (FAILED(hr = wined3d_get_adapter_display_mode(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL)))
627 {
628 ERR("Failed to get display mode.\n");
629 return hr;
630 }
631
632 memset(&swapchain_desc, 0, sizeof(swapchain_desc));
633 swapchain_desc.backbuffer_width = mode.width;
634 swapchain_desc.backbuffer_height = mode.height;
635 swapchain_desc.backbuffer_format = mode.format_id;
636 swapchain_desc.backbuffer_usage = WINED3DUSAGE_RENDERTARGET;
637 swapchain_desc.swap_effect = WINED3D_SWAP_EFFECT_COPY;
638 swapchain_desc.device_window = window;
639 swapchain_desc.windowed = windowed;
640 swapchain_desc.flags = WINED3D_SWAPCHAIN_ALLOW_MODE_SWITCH;
641
642 if (!(ddraw->flags & DDRAW_NO3D))
643 hr = ddraw_attach_d3d_device(ddraw, &swapchain_desc);
644 else
645 hr = wined3d_device_init_gdi(ddraw->wined3d_device, &swapchain_desc);
646
647 if (FAILED(hr))
648 {
649 ERR("Failed to create swapchain, hr %#x.\n", hr);
650 return hr;
651 }
652
653 if (!(ddraw->wined3d_swapchain = wined3d_device_get_swapchain(ddraw->wined3d_device, 0)))
654 {
655 ERR("Failed to get swapchain.\n");
656 return DDERR_INVALIDPARAMS;
657 }
658
659 wined3d_swapchain_incref(ddraw->wined3d_swapchain);
660 ddraw_set_swapchain_window(ddraw, window);
661
662 if (ddraw->primary && ddraw->primary->palette)
663 wined3d_swapchain_set_palette(ddraw->wined3d_swapchain, ddraw->primary->palette->wined3d_palette);
664
665 return DD_OK;
666 }
667
668 /*****************************************************************************
669 * IDirectDraw7::RestoreDisplayMode
670 *
671 * Restores the display mode to what it was at creation time. Basically.
672 *
673 * Returns
674 * DD_OK on success
675 * DDERR_NOEXCLUSIVE mode if the device isn't in fullscreen mode
676 *
677 *****************************************************************************/
ddraw7_RestoreDisplayMode(IDirectDraw7 * iface)678 static HRESULT WINAPI ddraw7_RestoreDisplayMode(IDirectDraw7 *iface)
679 {
680 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
681 HRESULT hr;
682
683 TRACE("iface %p.\n", iface);
684
685 wined3d_mutex_lock();
686
687 if (!(ddraw->flags & DDRAW_RESTORE_MODE))
688 {
689 wined3d_mutex_unlock();
690 return DD_OK;
691 }
692
693 if (exclusive_ddraw && exclusive_ddraw != ddraw)
694 {
695 wined3d_mutex_unlock();
696 return DDERR_NOEXCLUSIVEMODE;
697 }
698
699 if (SUCCEEDED(hr = wined3d_set_adapter_display_mode(ddraw->wined3d, WINED3DADAPTER_DEFAULT, NULL)))
700 ddraw->flags &= ~DDRAW_RESTORE_MODE;
701
702 InterlockedCompareExchange(&ddraw->device_state, DDRAW_DEVICE_STATE_NOT_RESTORED, DDRAW_DEVICE_STATE_OK);
703
704 wined3d_mutex_unlock();
705
706 return hr;
707 }
708
ddraw4_RestoreDisplayMode(IDirectDraw4 * iface)709 static HRESULT WINAPI ddraw4_RestoreDisplayMode(IDirectDraw4 *iface)
710 {
711 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
712
713 TRACE("iface %p.\n", iface);
714
715 return ddraw7_RestoreDisplayMode(&ddraw->IDirectDraw7_iface);
716 }
717
ddraw2_RestoreDisplayMode(IDirectDraw2 * iface)718 static HRESULT WINAPI ddraw2_RestoreDisplayMode(IDirectDraw2 *iface)
719 {
720 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
721
722 TRACE("iface %p.\n", iface);
723
724 return ddraw7_RestoreDisplayMode(&ddraw->IDirectDraw7_iface);
725 }
726
ddraw1_RestoreDisplayMode(IDirectDraw * iface)727 static HRESULT WINAPI ddraw1_RestoreDisplayMode(IDirectDraw *iface)
728 {
729 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
730
731 TRACE("iface %p.\n", iface);
732
733 return ddraw7_RestoreDisplayMode(&ddraw->IDirectDraw7_iface);
734 }
735
736 /*****************************************************************************
737 * IDirectDraw7::SetCooperativeLevel
738 *
739 * Sets the cooperative level for the DirectDraw object, and the window
740 * assigned to it. The cooperative level determines the general behavior
741 * of the DirectDraw application
742 *
743 * Warning: This is quite tricky, as it's not really documented which
744 * cooperative levels can be combined with each other. If a game fails
745 * after this function, try to check the cooperative levels passed on
746 * Windows, and if it returns something different.
747 *
748 * If you think that this function caused the failure because it writes a
749 * fixme, be sure to run again with a +ddraw trace.
750 *
751 * What is known about cooperative levels (See the ddraw modes test):
752 * DDSCL_EXCLUSIVE requires DDSCL_FULLSCREEN.
753 * DDSCL_NORMAL is not compatible with DDSCL_EXCLUSIVE.
754 * Unlike what msdn claims, DDSCL_NORMAL | DDSCL_FULLSCREEN is allowed.
755 * DDSCL_SETFOCUSWINDOW can be passed only in DDSCL_NORMAL mode, but after that
756 * DDSCL_EXCLUSIVE can be activated.
757 * DDSCL_SETFOCUSWINDOW may only be used with DDSCL_NOWINDOWCHANGES or
758 * DDSCL_CREATEDEVICEWINDOW.
759 *
760 * Handled flags: DDSCL_NORMAL, DDSCL_FULLSCREEN, DDSCL_EXCLUSIVE,
761 * DDSCL_CREATEDEVICEWINDOW, DDSCL_SETDEVICEWINDOW
762 * DDSCL_SETFOCUSWINDOW (partially),
763 * DDSCL_MULTITHREADED (work in progress)
764 * DDSCL_FPUPRESERVE (see device.c)
765 *
766 * Unsure about this: DDSCL_FPUSETUP
767 *
768 * These don't seem very important for wine:
769 * DDSCL_ALLOWREBOOT, DDSCL_NOWINDOWCHANGES, DDSCL_ALLOWMODEX
770 *
771 * Returns:
772 * DD_OK if the cooperative level was set successfully
773 * DDERR_INVALIDPARAMS if the passed cooperative level combination is invalid
774 * DDERR_HWNDALREADYSET if DDSCL_SETFOCUSWINDOW is passed in exclusive mode
775 * (Probably others too, have to investigate)
776 *
777 *****************************************************************************/
ddraw_set_cooperative_level(struct ddraw * ddraw,HWND window,DWORD cooplevel,BOOL restore_mode_on_normal)778 static HRESULT ddraw_set_cooperative_level(struct ddraw *ddraw, HWND window,
779 DWORD cooplevel, BOOL restore_mode_on_normal)
780 {
781 struct wined3d_rendertarget_view *rtv = NULL, *dsv = NULL;
782 struct wined3d_stateblock *stateblock;
783 BOOL restore_state = FALSE;
784 HRESULT hr;
785
786 TRACE("ddraw %p, window %p, flags %#x, restore_mode_on_normal %x.\n", ddraw, window, cooplevel,
787 restore_mode_on_normal);
788 DDRAW_dump_cooperativelevel(cooplevel);
789
790 wined3d_mutex_lock();
791
792 if (ddraw->flags & DDRAW_SCL_RECURSIVE)
793 {
794 WARN("Recursive call, returning DD_OK.\n");
795 hr = DD_OK;
796 goto done;
797 }
798 ddraw->flags |= DDRAW_SCL_RECURSIVE;
799
800 /* Tests suggest that we need one of them: */
801 if(!(cooplevel & (DDSCL_SETFOCUSWINDOW |
802 DDSCL_NORMAL |
803 DDSCL_EXCLUSIVE )))
804 {
805 TRACE("Incorrect cooplevel flags, returning DDERR_INVALIDPARAMS\n");
806 hr = DDERR_INVALIDPARAMS;
807 goto done;
808 }
809
810 if ((cooplevel & DDSCL_CREATEDEVICEWINDOW) && !(cooplevel & DDSCL_EXCLUSIVE))
811 {
812 WARN("DDSCL_CREATEDEVICEWINDOW requires DDSCL_EXCLUSIVE.\n");
813 hr = DDERR_INVALIDPARAMS;
814 goto done;
815 }
816
817 /* Handle those levels first which set various hwnds */
818 if ((cooplevel & DDSCL_SETFOCUSWINDOW) && !(cooplevel & DDSCL_CREATEDEVICEWINDOW))
819 {
820 /* This isn't compatible with a lot of flags */
821 if (cooplevel & (DDSCL_MULTITHREADED
822 | DDSCL_FPUSETUP
823 | DDSCL_FPUPRESERVE
824 | DDSCL_ALLOWREBOOT
825 | DDSCL_ALLOWMODEX
826 | DDSCL_SETDEVICEWINDOW
827 | DDSCL_NORMAL
828 | DDSCL_EXCLUSIVE
829 | DDSCL_FULLSCREEN))
830 {
831 WARN("Called with incompatible flags, returning DDERR_INVALIDPARAMS.\n");
832 hr = DDERR_INVALIDPARAMS;
833 goto done;
834 }
835
836 hr = ddraw_set_focus_window(ddraw, window);
837 goto done;
838 }
839
840 if (cooplevel & DDSCL_EXCLUSIVE)
841 {
842 if (!(cooplevel & DDSCL_FULLSCREEN) || !(window || (cooplevel & DDSCL_CREATEDEVICEWINDOW)))
843 {
844 WARN("DDSCL_EXCLUSIVE requires DDSCL_FULLSCREEN and a window.\n");
845 hr = DDERR_INVALIDPARAMS;
846 goto done;
847 }
848
849 if (cooplevel & DDSCL_CREATEDEVICEWINDOW)
850 {
851 HWND device_window;
852
853 if (!ddraw->focuswindow && !(cooplevel & DDSCL_SETFOCUSWINDOW))
854 {
855 WARN("No focus window set.\n");
856 hr = DDERR_NOFOCUSWINDOW;
857 goto done;
858 }
859
860 device_window = CreateWindowExA(0, DDRAW_WINDOW_CLASS_NAME, "DirectDrawDeviceWnd",
861 WS_POPUP, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN),
862 NULL, NULL, NULL, NULL);
863 if (!device_window)
864 {
865 ERR("Failed to create window, last error %#x.\n", GetLastError());
866 hr = E_FAIL;
867 goto done;
868 }
869
870 ShowWindow(device_window, SW_SHOW);
871 TRACE("Created a device window %p.\n", device_window);
872
873 /* Native apparently leaks the created device window if setting the
874 * focus window below fails. */
875 ddraw->cooperative_level |= DDSCL_CREATEDEVICEWINDOW;
876 ddraw->devicewindow = device_window;
877
878 if (cooplevel & DDSCL_SETFOCUSWINDOW)
879 {
880 if (!window)
881 {
882 hr = DDERR_NOHWND;
883 goto done;
884 }
885
886 if (FAILED(hr = ddraw_set_focus_window(ddraw, window)))
887 goto done;
888 }
889
890 window = device_window;
891 }
892 }
893 else
894 {
895 if (ddraw->cooperative_level & DDSCL_CREATEDEVICEWINDOW)
896 DestroyWindow(ddraw->devicewindow);
897 ddraw->devicewindow = NULL;
898 ddraw->focuswindow = NULL;
899 }
900
901 if ((cooplevel & DDSCL_FULLSCREEN) != (ddraw->cooperative_level & DDSCL_FULLSCREEN) || window != ddraw->dest_window)
902 {
903 if (ddraw->cooperative_level & DDSCL_FULLSCREEN)
904 wined3d_device_restore_fullscreen_window(ddraw->wined3d_device, ddraw->dest_window, NULL);
905
906 if (cooplevel & DDSCL_FULLSCREEN)
907 {
908 struct wined3d_display_mode display_mode;
909
910 wined3d_get_adapter_display_mode(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &display_mode, NULL);
911 wined3d_device_setup_fullscreen_window(ddraw->wined3d_device, window,
912 display_mode.width, display_mode.height);
913 }
914 }
915
916 if ((cooplevel & DDSCL_EXCLUSIVE) && exclusive_window != window)
917 {
918 ddraw->device_state = DDRAW_DEVICE_STATE_NOT_RESTORED;
919 exclusive_window = window;
920 }
921
922 if (cooplevel & DDSCL_MULTITHREADED && !(ddraw->cooperative_level & DDSCL_MULTITHREADED))
923 wined3d_device_set_multithreaded(ddraw->wined3d_device);
924
925 if (ddraw->wined3d_swapchain)
926 {
927 if (!(ddraw->flags & DDRAW_NO3D))
928 {
929 restore_state = TRUE;
930
931 if (FAILED(hr = wined3d_stateblock_create(ddraw->wined3d_device, WINED3D_SBT_ALL, &stateblock)))
932 {
933 ERR("Failed to create stateblock, hr %#x.\n", hr);
934 goto done;
935 }
936
937 wined3d_stateblock_capture(stateblock);
938 rtv = wined3d_device_get_rendertarget_view(ddraw->wined3d_device, 0);
939 /* Rendering to ddraw->wined3d_frontbuffer. */
940 if (rtv && !wined3d_rendertarget_view_get_sub_resource_parent(rtv))
941 rtv = NULL;
942 else if (rtv)
943 wined3d_rendertarget_view_incref(rtv);
944
945 if ((dsv = wined3d_device_get_depth_stencil_view(ddraw->wined3d_device)))
946 wined3d_rendertarget_view_incref(dsv);
947 }
948
949 ddraw_destroy_swapchain(ddraw);
950 }
951
952 if (FAILED(hr = ddraw_create_swapchain(ddraw, window, !(cooplevel & DDSCL_FULLSCREEN))))
953 ERR("Failed to create swapchain, hr %#x.\n", hr);
954
955 if (restore_state)
956 {
957 if (dsv)
958 {
959 wined3d_device_set_depth_stencil_view(ddraw->wined3d_device, dsv);
960 wined3d_rendertarget_view_decref(dsv);
961 }
962
963 if (rtv)
964 {
965 wined3d_device_set_rendertarget_view(ddraw->wined3d_device, 0, rtv, FALSE);
966 wined3d_rendertarget_view_decref(rtv);
967 }
968
969 wined3d_stateblock_apply(stateblock);
970 wined3d_stateblock_decref(stateblock);
971 }
972
973 if (!(cooplevel & DDSCL_EXCLUSIVE) && (ddraw->cooperative_level & DDSCL_EXCLUSIVE)
974 && restore_mode_on_normal)
975 {
976 hr = ddraw7_RestoreDisplayMode(&ddraw->IDirectDraw7_iface);
977 if (FAILED(hr))
978 ERR("RestoreDisplayMode failed\n");
979 }
980
981 if ((ddraw->cooperative_level & DDSCL_EXCLUSIVE)
982 && (window != ddraw->dest_window || !(cooplevel & DDSCL_EXCLUSIVE)))
983 wined3d_device_release_focus_window(ddraw->wined3d_device);
984
985 if ((cooplevel & DDSCL_EXCLUSIVE)
986 && (window != ddraw->dest_window || !(ddraw->cooperative_level & DDSCL_EXCLUSIVE)))
987 {
988 hr = wined3d_device_acquire_focus_window(ddraw->wined3d_device, window);
989 if (FAILED(hr))
990 {
991 ERR("Failed to acquire focus window, hr %#x.\n", hr);
992 goto done;
993 }
994 }
995
996 /* Unhandled flags */
997 if (cooplevel & DDSCL_ALLOWREBOOT)
998 WARN("Unhandled flag DDSCL_ALLOWREBOOT, harmless\n");
999 if (cooplevel & DDSCL_ALLOWMODEX)
1000 WARN("Unhandled flag DDSCL_ALLOWMODEX, harmless\n");
1001 if (cooplevel & DDSCL_FPUSETUP)
1002 WARN("Unhandled flag DDSCL_FPUSETUP, harmless\n");
1003
1004 if (cooplevel & DDSCL_EXCLUSIVE)
1005 exclusive_ddraw = ddraw;
1006 else if (exclusive_ddraw == ddraw)
1007 exclusive_ddraw = NULL;
1008
1009 /* Store the cooperative_level */
1010 ddraw->cooperative_level = cooplevel;
1011 ddraw->dest_window = window;
1012
1013 TRACE("SetCooperativeLevel returning DD_OK\n");
1014 hr = DD_OK;
1015 done:
1016 ddraw->flags &= ~DDRAW_SCL_RECURSIVE;
1017 wined3d_mutex_unlock();
1018
1019 return hr;
1020 }
1021
ddraw7_SetCooperativeLevel(IDirectDraw7 * iface,HWND window,DWORD flags)1022 static HRESULT WINAPI ddraw7_SetCooperativeLevel(IDirectDraw7 *iface, HWND window, DWORD flags)
1023 {
1024 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1025
1026 TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags);
1027
1028 return ddraw_set_cooperative_level(ddraw, window, flags, !(ddraw->flags & DDRAW_SCL_DDRAW1));
1029 }
1030
ddraw4_SetCooperativeLevel(IDirectDraw4 * iface,HWND window,DWORD flags)1031 static HRESULT WINAPI ddraw4_SetCooperativeLevel(IDirectDraw4 *iface, HWND window, DWORD flags)
1032 {
1033 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1034
1035 TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags);
1036
1037 return ddraw_set_cooperative_level(ddraw, window, flags, !(ddraw->flags & DDRAW_SCL_DDRAW1));
1038 }
1039
ddraw2_SetCooperativeLevel(IDirectDraw2 * iface,HWND window,DWORD flags)1040 static HRESULT WINAPI ddraw2_SetCooperativeLevel(IDirectDraw2 *iface, HWND window, DWORD flags)
1041 {
1042 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1043
1044 TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags);
1045
1046 return ddraw_set_cooperative_level(ddraw, window, flags, !(ddraw->flags & DDRAW_SCL_DDRAW1));
1047 }
1048
ddraw1_SetCooperativeLevel(IDirectDraw * iface,HWND window,DWORD flags)1049 static HRESULT WINAPI ddraw1_SetCooperativeLevel(IDirectDraw *iface, HWND window, DWORD flags)
1050 {
1051 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1052 HRESULT hr;
1053
1054 TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags);
1055
1056 hr = ddraw_set_cooperative_level(ddraw, window, flags, FALSE);
1057 if (SUCCEEDED(hr))
1058 ddraw->flags |= DDRAW_SCL_DDRAW1;
1059 return hr;
1060 }
1061
1062 /*****************************************************************************
1063 * IDirectDraw7::SetDisplayMode
1064 *
1065 * Sets the display screen resolution, color depth and refresh frequency
1066 * when in fullscreen mode (in theory).
1067 * Possible return values listed in the SDK suggest that this method fails
1068 * when not in fullscreen mode, but this is wrong. Windows 2000 happily sets
1069 * the display mode in DDSCL_NORMAL mode without an hwnd specified.
1070 * It seems to be valid to pass 0 for With and Height, this has to be tested
1071 * It could mean that the current video mode should be left as-is. (But why
1072 * call it then?)
1073 *
1074 * Params:
1075 * Height, Width: Screen dimension
1076 * BPP: Color depth in Bits per pixel
1077 * Refreshrate: Screen refresh rate
1078 * Flags: Other stuff
1079 *
1080 * Returns
1081 * DD_OK on success
1082 *
1083 *****************************************************************************/
ddraw7_SetDisplayMode(IDirectDraw7 * iface,DWORD width,DWORD height,DWORD bpp,DWORD refresh_rate,DWORD flags)1084 static HRESULT WINAPI ddraw7_SetDisplayMode(IDirectDraw7 *iface, DWORD width, DWORD height,
1085 DWORD bpp, DWORD refresh_rate, DWORD flags)
1086 {
1087 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1088 struct wined3d_display_mode mode;
1089 enum wined3d_format_id format;
1090 HRESULT hr;
1091
1092 TRACE("iface %p, width %u, height %u, bpp %u, refresh_rate %u, flags %#x.\n",
1093 iface, width, height, bpp, refresh_rate, flags);
1094
1095 if (force_refresh_rate != 0)
1096 {
1097 TRACE("ForceRefreshRate overriding passed-in refresh rate (%u Hz) to %u Hz\n",
1098 refresh_rate, force_refresh_rate);
1099 refresh_rate = force_refresh_rate;
1100 }
1101
1102 wined3d_mutex_lock();
1103
1104 if (exclusive_ddraw && exclusive_ddraw != ddraw)
1105 {
1106 wined3d_mutex_unlock();
1107 return DDERR_NOEXCLUSIVEMODE;
1108 }
1109
1110 if (!width || !height)
1111 {
1112 /* It looks like Need for Speed Porsche Unleashed expects DD_OK here. */
1113 wined3d_mutex_unlock();
1114 return DD_OK;
1115 }
1116
1117 switch (bpp)
1118 {
1119 case 8: format = WINED3DFMT_P8_UINT; break;
1120 case 15: format = WINED3DFMT_B5G5R5X1_UNORM; break;
1121 case 16: format = WINED3DFMT_B5G6R5_UNORM; break;
1122 case 24: format = WINED3DFMT_B8G8R8_UNORM; break;
1123 case 32: format = WINED3DFMT_B8G8R8X8_UNORM; break;
1124 default: format = WINED3DFMT_UNKNOWN; break;
1125 }
1126
1127 mode.width = width;
1128 mode.height = height;
1129 mode.refresh_rate = refresh_rate;
1130 mode.format_id = format;
1131 mode.scanline_ordering = WINED3D_SCANLINE_ORDERING_UNKNOWN;
1132
1133 /* TODO: The possible return values from msdn suggest that the screen mode
1134 * can't be changed if a surface is locked or some drawing is in progress. */
1135 if (SUCCEEDED(hr = wined3d_set_adapter_display_mode(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode)))
1136 {
1137 if (ddraw->primary)
1138 {
1139 DDSURFACEDESC2 *surface_desc = &ddraw->primary->surface_desc;
1140
1141 if (FAILED(hr = wined3d_swapchain_resize_buffers(ddraw->wined3d_swapchain, 0,
1142 surface_desc->dwWidth, surface_desc->dwHeight, mode.format_id, WINED3D_MULTISAMPLE_NONE, 0)))
1143 ERR("Failed to resize buffers, hr %#x.\n", hr);
1144 else
1145 ddrawformat_from_wined3dformat(&ddraw->primary->surface_desc.u4.ddpfPixelFormat, mode.format_id);
1146 }
1147 ddraw->flags |= DDRAW_RESTORE_MODE;
1148 #ifdef __REACTOS__
1149 if (ddraw->cooperative_level & DDSCL_EXCLUSIVE)
1150 SetWindowPos(ddraw->dest_window, HWND_TOP, 0, 0, width, height, SWP_SHOWWINDOW | SWP_NOACTIVATE);
1151 #endif
1152 }
1153
1154 InterlockedCompareExchange(&ddraw->device_state, DDRAW_DEVICE_STATE_NOT_RESTORED, DDRAW_DEVICE_STATE_OK);
1155
1156 wined3d_mutex_unlock();
1157
1158 switch (hr)
1159 {
1160 case WINED3DERR_NOTAVAILABLE: return DDERR_UNSUPPORTED;
1161 default: return hr;
1162 }
1163 }
1164
ddraw4_SetDisplayMode(IDirectDraw4 * iface,DWORD width,DWORD height,DWORD bpp,DWORD refresh_rate,DWORD flags)1165 static HRESULT WINAPI ddraw4_SetDisplayMode(IDirectDraw4 *iface, DWORD width, DWORD height,
1166 DWORD bpp, DWORD refresh_rate, DWORD flags)
1167 {
1168 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1169
1170 TRACE("iface %p, width %u, height %u, bpp %u, refresh_rate %u, flags %#x.\n",
1171 iface, width, height, bpp, refresh_rate, flags);
1172
1173 return ddraw7_SetDisplayMode(&ddraw->IDirectDraw7_iface, width, height, bpp, refresh_rate, flags);
1174 }
1175
ddraw2_SetDisplayMode(IDirectDraw2 * iface,DWORD width,DWORD height,DWORD bpp,DWORD refresh_rate,DWORD flags)1176 static HRESULT WINAPI ddraw2_SetDisplayMode(IDirectDraw2 *iface,
1177 DWORD width, DWORD height, DWORD bpp, DWORD refresh_rate, DWORD flags)
1178 {
1179 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1180
1181 TRACE("iface %p, width %u, height %u, bpp %u, refresh_rate %u, flags %#x.\n",
1182 iface, width, height, bpp, refresh_rate, flags);
1183
1184 return ddraw7_SetDisplayMode(&ddraw->IDirectDraw7_iface, width, height, bpp, refresh_rate, flags);
1185 }
1186
ddraw1_SetDisplayMode(IDirectDraw * iface,DWORD width,DWORD height,DWORD bpp)1187 static HRESULT WINAPI ddraw1_SetDisplayMode(IDirectDraw *iface, DWORD width, DWORD height, DWORD bpp)
1188 {
1189 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1190
1191 TRACE("iface %p, width %u, height %u, bpp %u.\n", iface, width, height, bpp);
1192
1193 return ddraw7_SetDisplayMode(&ddraw->IDirectDraw7_iface, width, height, bpp, 0, 0);
1194 }
1195
ddraw_d3dcaps1_from_7(D3DDEVICEDESC * caps1,D3DDEVICEDESC7 * caps7)1196 void ddraw_d3dcaps1_from_7(D3DDEVICEDESC *caps1, D3DDEVICEDESC7 *caps7)
1197 {
1198 memset(caps1, 0, sizeof(*caps1));
1199 caps1->dwSize = sizeof(*caps1);
1200 caps1->dwFlags = D3DDD_COLORMODEL
1201 | D3DDD_DEVCAPS
1202 | D3DDD_TRANSFORMCAPS
1203 | D3DDD_BCLIPPING
1204 | D3DDD_LIGHTINGCAPS
1205 | D3DDD_LINECAPS
1206 | D3DDD_TRICAPS
1207 | D3DDD_DEVICERENDERBITDEPTH
1208 | D3DDD_DEVICEZBUFFERBITDEPTH
1209 | D3DDD_MAXBUFFERSIZE
1210 | D3DDD_MAXVERTEXCOUNT;
1211 caps1->dcmColorModel = D3DCOLOR_RGB;
1212 caps1->dwDevCaps = caps7->dwDevCaps;
1213 caps1->dtcTransformCaps.dwSize = sizeof(caps1->dtcTransformCaps);
1214 caps1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
1215 caps1->bClipping = TRUE;
1216 caps1->dlcLightingCaps.dwSize = sizeof(caps1->dlcLightingCaps);
1217 caps1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL
1218 | D3DLIGHTCAPS_PARALLELPOINT
1219 | D3DLIGHTCAPS_POINT
1220 | D3DLIGHTCAPS_SPOT;
1221 caps1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
1222 caps1->dlcLightingCaps.dwNumLights = caps7->dwMaxActiveLights;
1223 caps1->dpcLineCaps = caps7->dpcLineCaps;
1224 caps1->dpcTriCaps = caps7->dpcTriCaps;
1225 caps1->dwDeviceRenderBitDepth = caps7->dwDeviceRenderBitDepth;
1226 caps1->dwDeviceZBufferBitDepth = caps7->dwDeviceZBufferBitDepth;
1227 caps1->dwMaxBufferSize = 0;
1228 caps1->dwMaxVertexCount = 65536;
1229 caps1->dwMinTextureWidth = caps7->dwMinTextureWidth;
1230 caps1->dwMinTextureHeight = caps7->dwMinTextureHeight;
1231 caps1->dwMaxTextureWidth = caps7->dwMaxTextureWidth;
1232 caps1->dwMaxTextureHeight = caps7->dwMaxTextureHeight;
1233 caps1->dwMinStippleWidth = 1;
1234 caps1->dwMinStippleHeight = 1;
1235 caps1->dwMaxStippleWidth = 32;
1236 caps1->dwMaxStippleHeight = 32;
1237 caps1->dwMaxTextureRepeat = caps7->dwMaxTextureRepeat;
1238 caps1->dwMaxTextureAspectRatio = caps7->dwMaxTextureAspectRatio;
1239 caps1->dwMaxAnisotropy = caps7->dwMaxAnisotropy;
1240 caps1->dvGuardBandLeft = caps7->dvGuardBandLeft;
1241 caps1->dvGuardBandTop = caps7->dvGuardBandTop;
1242 caps1->dvGuardBandRight = caps7->dvGuardBandRight;
1243 caps1->dvGuardBandBottom = caps7->dvGuardBandBottom;
1244 caps1->dvExtentsAdjust = caps7->dvExtentsAdjust;
1245 caps1->dwStencilCaps = caps7->dwStencilCaps;
1246 caps1->dwFVFCaps = caps7->dwFVFCaps;
1247 caps1->dwTextureOpCaps = caps7->dwTextureOpCaps;
1248 caps1->wMaxTextureBlendStages = caps7->wMaxTextureBlendStages;
1249 caps1->wMaxSimultaneousTextures = caps7->wMaxSimultaneousTextures;
1250 }
1251
ddraw_get_d3dcaps(const struct ddraw * ddraw,D3DDEVICEDESC7 * caps)1252 HRESULT ddraw_get_d3dcaps(const struct ddraw *ddraw, D3DDEVICEDESC7 *caps)
1253 {
1254 WINED3DCAPS wined3d_caps;
1255 HRESULT hr;
1256
1257 TRACE("ddraw %p, caps %p.\n", ddraw, caps);
1258
1259 memset(&wined3d_caps, 0, sizeof(wined3d_caps));
1260
1261 wined3d_mutex_lock();
1262 hr = wined3d_get_device_caps(ddraw->wined3d, 0, WINED3D_DEVICE_TYPE_HAL, &wined3d_caps);
1263 wined3d_mutex_unlock();
1264 if (FAILED(hr))
1265 {
1266 WARN("Failed to get device caps, hr %#x.\n", hr);
1267 return hr;
1268 }
1269
1270 caps->dwDevCaps = wined3d_caps.DevCaps;
1271 caps->dpcLineCaps.dwMiscCaps = wined3d_caps.PrimitiveMiscCaps;
1272 caps->dpcLineCaps.dwRasterCaps = wined3d_caps.RasterCaps;
1273 caps->dpcLineCaps.dwZCmpCaps = wined3d_caps.ZCmpCaps;
1274 caps->dpcLineCaps.dwSrcBlendCaps = wined3d_caps.SrcBlendCaps;
1275 caps->dpcLineCaps.dwDestBlendCaps = wined3d_caps.DestBlendCaps;
1276 caps->dpcLineCaps.dwAlphaCmpCaps = wined3d_caps.AlphaCmpCaps;
1277 caps->dpcLineCaps.dwShadeCaps = wined3d_caps.ShadeCaps;
1278 caps->dpcLineCaps.dwTextureCaps = wined3d_caps.TextureCaps;
1279 caps->dpcLineCaps.dwTextureFilterCaps = wined3d_caps.TextureFilterCaps;
1280 caps->dpcLineCaps.dwTextureAddressCaps = wined3d_caps.TextureAddressCaps;
1281
1282 caps->dwMaxTextureWidth = wined3d_caps.MaxTextureWidth;
1283 caps->dwMaxTextureHeight = wined3d_caps.MaxTextureHeight;
1284
1285 caps->dwMaxTextureRepeat = wined3d_caps.MaxTextureRepeat;
1286 caps->dwMaxTextureAspectRatio = wined3d_caps.MaxTextureAspectRatio;
1287 caps->dwMaxAnisotropy = wined3d_caps.MaxAnisotropy;
1288 caps->dvMaxVertexW = wined3d_caps.MaxVertexW;
1289
1290 caps->dvGuardBandLeft = wined3d_caps.GuardBandLeft;
1291 caps->dvGuardBandTop = wined3d_caps.GuardBandTop;
1292 caps->dvGuardBandRight = wined3d_caps.GuardBandRight;
1293 caps->dvGuardBandBottom = wined3d_caps.GuardBandBottom;
1294
1295 caps->dvExtentsAdjust = wined3d_caps.ExtentsAdjust;
1296 caps->dwStencilCaps = wined3d_caps.StencilCaps;
1297
1298 caps->dwFVFCaps = wined3d_caps.FVFCaps;
1299 caps->dwTextureOpCaps = wined3d_caps.TextureOpCaps;
1300
1301 caps->dwVertexProcessingCaps = wined3d_caps.VertexProcessingCaps;
1302 caps->dwMaxActiveLights = wined3d_caps.MaxActiveLights;
1303
1304 /* Remove all non-d3d7 caps */
1305 caps->dwDevCaps &= (
1306 D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_SORTINCREASINGZ | D3DDEVCAPS_SORTDECREASINGZ |
1307 D3DDEVCAPS_SORTEXACT | D3DDEVCAPS_EXECUTESYSTEMMEMORY | D3DDEVCAPS_EXECUTEVIDEOMEMORY |
1308 D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
1309 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_CANRENDERAFTERFLIP |
1310 D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_DRAWPRIMITIVES2 | D3DDEVCAPS_SEPARATETEXTUREMEMORIES |
1311 D3DDEVCAPS_DRAWPRIMITIVES2EX | D3DDEVCAPS_HWTRANSFORMANDLIGHT | D3DDEVCAPS_CANBLTSYSTONONLOCAL |
1312 D3DDEVCAPS_HWRASTERIZATION);
1313
1314 caps->dwStencilCaps &= (
1315 D3DSTENCILCAPS_KEEP | D3DSTENCILCAPS_ZERO | D3DSTENCILCAPS_REPLACE |
1316 D3DSTENCILCAPS_INCRSAT | D3DSTENCILCAPS_DECRSAT | D3DSTENCILCAPS_INVERT |
1317 D3DSTENCILCAPS_INCR | D3DSTENCILCAPS_DECR);
1318
1319 /* FVF caps ?*/
1320
1321 caps->dwTextureOpCaps &= (
1322 D3DTEXOPCAPS_DISABLE | D3DTEXOPCAPS_SELECTARG1 | D3DTEXOPCAPS_SELECTARG2 |
1323 D3DTEXOPCAPS_MODULATE | D3DTEXOPCAPS_MODULATE2X | D3DTEXOPCAPS_MODULATE4X |
1324 D3DTEXOPCAPS_ADD | D3DTEXOPCAPS_ADDSIGNED | D3DTEXOPCAPS_ADDSIGNED2X |
1325 D3DTEXOPCAPS_SUBTRACT | D3DTEXOPCAPS_ADDSMOOTH | D3DTEXOPCAPS_BLENDTEXTUREALPHA |
1326 D3DTEXOPCAPS_BLENDFACTORALPHA | D3DTEXOPCAPS_BLENDTEXTUREALPHAPM | D3DTEXOPCAPS_BLENDCURRENTALPHA |
1327 D3DTEXOPCAPS_PREMODULATE | D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR | D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
1328 D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR | D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA | D3DTEXOPCAPS_BUMPENVMAP |
1329 D3DTEXOPCAPS_BUMPENVMAPLUMINANCE | D3DTEXOPCAPS_DOTPRODUCT3);
1330
1331 caps->dwVertexProcessingCaps &= (
1332 D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7 | D3DVTXPCAPS_VERTEXFOG |
1333 D3DVTXPCAPS_DIRECTIONALLIGHTS | D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER);
1334
1335 caps->dpcLineCaps.dwMiscCaps &= (
1336 D3DPMISCCAPS_MASKPLANES | D3DPMISCCAPS_MASKZ | D3DPMISCCAPS_LINEPATTERNREP |
1337 D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLNONE | D3DPMISCCAPS_CULLCW |
1338 D3DPMISCCAPS_CULLCCW);
1339
1340 caps->dpcLineCaps.dwRasterCaps &= (
1341 D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_ROP2 | D3DPRASTERCAPS_XOR |
1342 D3DPRASTERCAPS_PAT | D3DPRASTERCAPS_ZTEST | D3DPRASTERCAPS_SUBPIXEL |
1343 D3DPRASTERCAPS_SUBPIXELX | D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_FOGTABLE |
1344 D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ANTIALIASSORTDEPENDENT | D3DPRASTERCAPS_ANTIALIASSORTINDEPENDENT |
1345 D3DPRASTERCAPS_ANTIALIASEDGES | D3DPRASTERCAPS_MIPMAPLODBIAS | D3DPRASTERCAPS_ZBIAS |
1346 D3DPRASTERCAPS_ZBUFFERLESSHSR | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_ANISOTROPY |
1347 D3DPRASTERCAPS_WBUFFER | D3DPRASTERCAPS_TRANSLUCENTSORTINDEPENDENT | D3DPRASTERCAPS_WFOG |
1348 D3DPRASTERCAPS_ZFOG);
1349
1350 caps->dpcLineCaps.dwZCmpCaps &= (
1351 D3DPCMPCAPS_NEVER | D3DPCMPCAPS_LESS | D3DPCMPCAPS_EQUAL |
1352 D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_NOTEQUAL |
1353 D3DPCMPCAPS_GREATEREQUAL | D3DPCMPCAPS_ALWAYS);
1354
1355 caps->dpcLineCaps.dwSrcBlendCaps &= (
1356 D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR |
1357 D3DPBLENDCAPS_INVSRCCOLOR | D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA |
1358 D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_DESTCOLOR |
1359 D3DPBLENDCAPS_INVDESTCOLOR | D3DPBLENDCAPS_SRCALPHASAT | D3DPBLENDCAPS_BOTHSRCALPHA |
1360 D3DPBLENDCAPS_BOTHINVSRCALPHA);
1361
1362 caps->dpcLineCaps.dwDestBlendCaps &= (
1363 D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR |
1364 D3DPBLENDCAPS_INVSRCCOLOR | D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA |
1365 D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_DESTCOLOR |
1366 D3DPBLENDCAPS_INVDESTCOLOR | D3DPBLENDCAPS_SRCALPHASAT | D3DPBLENDCAPS_BOTHSRCALPHA |
1367 D3DPBLENDCAPS_BOTHINVSRCALPHA);
1368
1369 caps->dpcLineCaps.dwAlphaCmpCaps &= (
1370 D3DPCMPCAPS_NEVER | D3DPCMPCAPS_LESS | D3DPCMPCAPS_EQUAL |
1371 D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_NOTEQUAL |
1372 D3DPCMPCAPS_GREATEREQUAL | D3DPCMPCAPS_ALWAYS);
1373
1374 caps->dpcLineCaps.dwShadeCaps &= (
1375 D3DPSHADECAPS_COLORFLATMONO | D3DPSHADECAPS_COLORFLATRGB | D3DPSHADECAPS_COLORGOURAUDMONO |
1376 D3DPSHADECAPS_COLORGOURAUDRGB | D3DPSHADECAPS_COLORPHONGMONO | D3DPSHADECAPS_COLORPHONGRGB |
1377 D3DPSHADECAPS_SPECULARFLATMONO | D3DPSHADECAPS_SPECULARFLATRGB | D3DPSHADECAPS_SPECULARGOURAUDMONO |
1378 D3DPSHADECAPS_SPECULARGOURAUDRGB | D3DPSHADECAPS_SPECULARPHONGMONO | D3DPSHADECAPS_SPECULARPHONGRGB |
1379 D3DPSHADECAPS_ALPHAFLATBLEND | D3DPSHADECAPS_ALPHAFLATSTIPPLED | D3DPSHADECAPS_ALPHAGOURAUDBLEND |
1380 D3DPSHADECAPS_ALPHAGOURAUDSTIPPLED | D3DPSHADECAPS_ALPHAPHONGBLEND | D3DPSHADECAPS_ALPHAPHONGSTIPPLED |
1381 D3DPSHADECAPS_FOGFLAT | D3DPSHADECAPS_FOGGOURAUD | D3DPSHADECAPS_FOGPHONG);
1382
1383 caps->dpcLineCaps.dwTextureCaps &= (
1384 D3DPTEXTURECAPS_PERSPECTIVE | D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_ALPHA |
1385 D3DPTEXTURECAPS_TRANSPARENCY | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_SQUAREONLY |
1386 D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE | D3DPTEXTURECAPS_ALPHAPALETTE| D3DPTEXTURECAPS_NONPOW2CONDITIONAL |
1387 D3DPTEXTURECAPS_PROJECTED | D3DPTEXTURECAPS_CUBEMAP | D3DPTEXTURECAPS_COLORKEYBLEND);
1388
1389 caps->dpcLineCaps.dwTextureFilterCaps &= (
1390 D3DPTFILTERCAPS_NEAREST | D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_MIPNEAREST |
1391 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST | D3DPTFILTERCAPS_LINEARMIPLINEAR |
1392 D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MINFLINEAR | D3DPTFILTERCAPS_MINFANISOTROPIC |
1393 D3DPTFILTERCAPS_MIPFPOINT | D3DPTFILTERCAPS_MIPFLINEAR | D3DPTFILTERCAPS_MAGFPOINT |
1394 D3DPTFILTERCAPS_MAGFLINEAR | D3DPTFILTERCAPS_MAGFANISOTROPIC | D3DPTFILTERCAPS_MAGFAFLATCUBIC |
1395 D3DPTFILTERCAPS_MAGFGAUSSIANCUBIC);
1396
1397 caps->dpcLineCaps.dwTextureAddressCaps &= (
1398 D3DPTADDRESSCAPS_WRAP | D3DPTADDRESSCAPS_MIRROR | D3DPTADDRESSCAPS_CLAMP |
1399 D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_INDEPENDENTUV);
1400
1401 if (!(caps->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2))
1402 {
1403 /* DirectX7 always has the np2 flag set, no matter what the card
1404 * supports. Some old games (Rollcage) check the caps incorrectly.
1405 * If wined3d supports nonpow2 textures it also has np2 conditional
1406 * support. */
1407 caps->dpcLineCaps.dwTextureCaps |= D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL;
1408 }
1409
1410 /* Fill the missing members, and do some fixup */
1411 caps->dpcLineCaps.dwSize = sizeof(caps->dpcLineCaps);
1412 caps->dpcLineCaps.dwTextureBlendCaps = D3DPTBLENDCAPS_ADD
1413 | D3DPTBLENDCAPS_MODULATEMASK
1414 | D3DPTBLENDCAPS_COPY
1415 | D3DPTBLENDCAPS_DECAL
1416 | D3DPTBLENDCAPS_DECALALPHA
1417 | D3DPTBLENDCAPS_DECALMASK
1418 | D3DPTBLENDCAPS_MODULATE
1419 | D3DPTBLENDCAPS_MODULATEALPHA;
1420 caps->dpcLineCaps.dwStippleWidth = 32;
1421 caps->dpcLineCaps.dwStippleHeight = 32;
1422 /* Use the same for the TriCaps */
1423 caps->dpcTriCaps = caps->dpcLineCaps;
1424
1425 caps->dwDeviceRenderBitDepth = DDBD_16 | DDBD_24 | DDBD_32;
1426 caps->dwDeviceZBufferBitDepth = DDBD_16 | DDBD_24;
1427 caps->dwMinTextureWidth = 1;
1428 caps->dwMinTextureHeight = 1;
1429
1430 /* Convert DWORDs safely to WORDs */
1431 caps->wMaxTextureBlendStages = min(wined3d_caps.MaxTextureBlendStages, 0xffff);
1432 caps->wMaxSimultaneousTextures = min(wined3d_caps.MaxSimultaneousTextures, 0xffff);
1433 caps->wMaxUserClipPlanes = min(wined3d_caps.MaxUserClipPlanes, D3DMAXUSERCLIPPLANES);
1434 caps->wMaxVertexBlendMatrices = min(wined3d_caps.MaxVertexBlendMatrices, 0xffff);
1435
1436 caps->deviceGUID = IID_IDirect3DTnLHalDevice;
1437
1438 caps->dwReserved1 = 0;
1439 caps->dwReserved2 = 0;
1440 caps->dwReserved3 = 0;
1441 caps->dwReserved4 = 0;
1442
1443 return DD_OK;
1444 }
1445
enum_zbuffer(DDPIXELFORMAT * format,void * ctx)1446 HRESULT CALLBACK enum_zbuffer(DDPIXELFORMAT *format, void *ctx)
1447 {
1448 DDCAPS *caps = ctx;
1449
1450 switch (format->u1.dwZBufferBitDepth)
1451 {
1452 case 8:
1453 caps->dwZBufferBitDepths |= DDBD_8;
1454 break;
1455 case 16:
1456 caps->dwZBufferBitDepths |= DDBD_16;
1457 break;
1458 case 24:
1459 caps->dwZBufferBitDepths |= DDBD_24;
1460 break;
1461 case 32:
1462 caps->dwZBufferBitDepths |= DDBD_32;
1463 break;
1464 }
1465 return D3DENUMRET_OK;
1466 }
1467
1468 /*****************************************************************************
1469 * IDirectDraw7::GetCaps
1470 *
1471 * Returns the drives capabilities
1472 *
1473 * Used for version 1, 2, 4 and 7
1474 *
1475 * Params:
1476 * DriverCaps: Structure to write the Hardware accelerated caps to
1477 * HelCaps: Structure to write the emulation caps to
1478 *
1479 * Returns
1480 * This implementation returns DD_OK only
1481 *
1482 *****************************************************************************/
ddraw7_GetCaps(IDirectDraw7 * iface,DDCAPS * DriverCaps,DDCAPS * HELCaps)1483 static HRESULT WINAPI ddraw7_GetCaps(IDirectDraw7 *iface, DDCAPS *DriverCaps, DDCAPS *HELCaps)
1484 {
1485 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1486 DDCAPS caps;
1487 WINED3DCAPS winecaps;
1488 HRESULT hr;
1489 DDSCAPS2 ddscaps = {0, 0, 0, {0}};
1490
1491 TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, DriverCaps, HELCaps);
1492
1493 /* One structure must be != NULL */
1494 if (!DriverCaps && !HELCaps)
1495 {
1496 WARN("Invalid parameters.\n");
1497 return DDERR_INVALIDPARAMS;
1498 }
1499
1500 memset(&caps, 0, sizeof(caps));
1501 memset(&winecaps, 0, sizeof(winecaps));
1502 caps.dwSize = sizeof(caps);
1503
1504 wined3d_mutex_lock();
1505 hr = wined3d_device_get_device_caps(ddraw->wined3d_device, &winecaps);
1506 if (FAILED(hr))
1507 {
1508 WARN("Failed to get device caps, %#x.\n", hr);
1509 wined3d_mutex_unlock();
1510 return hr;
1511 }
1512
1513 hr = IDirectDraw7_GetAvailableVidMem(iface, &ddscaps, &caps.dwVidMemTotal, &caps.dwVidMemFree);
1514 if (FAILED(hr))
1515 {
1516 WARN("IDirectDraw7::GetAvailableVidMem failed\n");
1517 wined3d_mutex_unlock();
1518 return hr;
1519 }
1520
1521 hr = IDirectDraw7_GetFourCCCodes(iface, &caps.dwNumFourCCCodes, NULL);
1522 wined3d_mutex_unlock();
1523 if (FAILED(hr))
1524 {
1525 WARN("IDirectDraw7::GetFourCCCodes failed\n");
1526 return hr;
1527 }
1528
1529 caps.dwCaps = winecaps.ddraw_caps.caps;
1530 caps.dwCaps2 = winecaps.ddraw_caps.caps2;
1531 caps.dwCKeyCaps = winecaps.ddraw_caps.color_key_caps;
1532 caps.dwFXCaps = winecaps.ddraw_caps.fx_caps;
1533 caps.dwPalCaps = DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE;
1534 caps.ddsCaps.dwCaps = winecaps.ddraw_caps.dds_caps;
1535 caps.dwSVBCaps = winecaps.ddraw_caps.svb_caps;
1536 caps.dwSVBCKeyCaps = winecaps.ddraw_caps.svb_color_key_caps;
1537 caps.dwSVBFXCaps = winecaps.ddraw_caps.svb_fx_caps;
1538 caps.dwVSBCaps = winecaps.ddraw_caps.vsb_caps;
1539 caps.dwVSBCKeyCaps = winecaps.ddraw_caps.vsb_color_key_caps;
1540 caps.dwVSBFXCaps = winecaps.ddraw_caps.vsb_fx_caps;
1541 caps.dwSSBCaps = winecaps.ddraw_caps.ssb_caps;
1542 caps.dwSSBCKeyCaps = winecaps.ddraw_caps.ssb_color_key_caps;
1543 caps.dwSSBFXCaps = winecaps.ddraw_caps.ssb_fx_caps;
1544
1545 caps.dwCaps |= DDCAPS_ALIGNSTRIDE;
1546 caps.dwAlignStrideAlign = DDRAW_STRIDE_ALIGNMENT;
1547
1548 caps.ddsOldCaps.dwCaps = caps.ddsCaps.dwCaps;
1549
1550 IDirect3D7_EnumZBufferFormats(&ddraw->IDirect3D7_iface, &IID_IDirect3DHALDevice, enum_zbuffer, &caps);
1551
1552 if(DriverCaps)
1553 {
1554 DD_STRUCT_COPY_BYSIZE(DriverCaps, &caps);
1555 if (TRACE_ON(ddraw))
1556 {
1557 TRACE("Driver Caps :\n");
1558 DDRAW_dump_DDCAPS(DriverCaps);
1559 }
1560
1561 }
1562 if(HELCaps)
1563 {
1564 DD_STRUCT_COPY_BYSIZE(HELCaps, &caps);
1565 if (TRACE_ON(ddraw))
1566 {
1567 TRACE("HEL Caps :\n");
1568 DDRAW_dump_DDCAPS(HELCaps);
1569 }
1570 }
1571
1572 return DD_OK;
1573 }
1574
ddraw4_GetCaps(IDirectDraw4 * iface,DDCAPS * driver_caps,DDCAPS * hel_caps)1575 static HRESULT WINAPI ddraw4_GetCaps(IDirectDraw4 *iface, DDCAPS *driver_caps, DDCAPS *hel_caps)
1576 {
1577 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1578
1579 TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, driver_caps, hel_caps);
1580
1581 return ddraw7_GetCaps(&ddraw->IDirectDraw7_iface, driver_caps, hel_caps);
1582 }
1583
ddraw2_GetCaps(IDirectDraw2 * iface,DDCAPS * driver_caps,DDCAPS * hel_caps)1584 static HRESULT WINAPI ddraw2_GetCaps(IDirectDraw2 *iface, DDCAPS *driver_caps, DDCAPS *hel_caps)
1585 {
1586 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1587
1588 TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, driver_caps, hel_caps);
1589
1590 return ddraw7_GetCaps(&ddraw->IDirectDraw7_iface, driver_caps, hel_caps);
1591 }
1592
ddraw1_GetCaps(IDirectDraw * iface,DDCAPS * driver_caps,DDCAPS * hel_caps)1593 static HRESULT WINAPI ddraw1_GetCaps(IDirectDraw *iface, DDCAPS *driver_caps, DDCAPS *hel_caps)
1594 {
1595 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1596
1597 TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, driver_caps, hel_caps);
1598
1599 return ddraw7_GetCaps(&ddraw->IDirectDraw7_iface, driver_caps, hel_caps);
1600 }
1601
1602 /*****************************************************************************
1603 * IDirectDraw7::Compact
1604 *
1605 * No idea what it does, MSDN says it's not implemented.
1606 *
1607 * Returns
1608 * DD_OK, but this is unchecked
1609 *
1610 *****************************************************************************/
ddraw7_Compact(IDirectDraw7 * iface)1611 static HRESULT WINAPI ddraw7_Compact(IDirectDraw7 *iface)
1612 {
1613 TRACE("iface %p.\n", iface);
1614
1615 return DD_OK;
1616 }
1617
ddraw4_Compact(IDirectDraw4 * iface)1618 static HRESULT WINAPI ddraw4_Compact(IDirectDraw4 *iface)
1619 {
1620 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1621
1622 TRACE("iface %p.\n", iface);
1623
1624 return ddraw7_Compact(&ddraw->IDirectDraw7_iface);
1625 }
1626
ddraw2_Compact(IDirectDraw2 * iface)1627 static HRESULT WINAPI ddraw2_Compact(IDirectDraw2 *iface)
1628 {
1629 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1630
1631 TRACE("iface %p.\n", iface);
1632
1633 return ddraw7_Compact(&ddraw->IDirectDraw7_iface);
1634 }
1635
ddraw1_Compact(IDirectDraw * iface)1636 static HRESULT WINAPI ddraw1_Compact(IDirectDraw *iface)
1637 {
1638 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1639
1640 TRACE("iface %p.\n", iface);
1641
1642 return ddraw7_Compact(&ddraw->IDirectDraw7_iface);
1643 }
1644
1645 /*****************************************************************************
1646 * IDirectDraw7::GetDisplayMode
1647 *
1648 * Returns information about the current display mode
1649 *
1650 * Exists in versions 1, 2, 4 and 7
1651 *
1652 * Params:
1653 * DDSD: Address of a surface description structure to write the info to
1654 *
1655 * Returns
1656 * DD_OK
1657 *
1658 *****************************************************************************/
ddraw7_GetDisplayMode(IDirectDraw7 * iface,DDSURFACEDESC2 * DDSD)1659 static HRESULT WINAPI ddraw7_GetDisplayMode(IDirectDraw7 *iface, DDSURFACEDESC2 *DDSD)
1660 {
1661 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1662 struct wined3d_display_mode mode;
1663 HRESULT hr;
1664
1665 TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
1666
1667 /* This seems sane */
1668 if (!DDSD || (DDSD->dwSize != sizeof(DDSURFACEDESC) && DDSD->dwSize != sizeof(DDSURFACEDESC2)))
1669 return DDERR_INVALIDPARAMS;
1670
1671 wined3d_mutex_lock();
1672
1673 if (FAILED(hr = wined3d_get_adapter_display_mode(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL)))
1674 {
1675 ERR("Failed to get display mode, hr %#x.\n", hr);
1676 wined3d_mutex_unlock();
1677 return hr;
1678 }
1679
1680 memset(DDSD, 0, DDSD->dwSize);
1681 DDSD->dwSize = sizeof(*DDSD);
1682 DDSD->dwFlags |= DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT | DDSD_PITCH | DDSD_REFRESHRATE;
1683 DDSD->dwWidth = mode.width;
1684 DDSD->dwHeight = mode.height;
1685 DDSD->u2.dwRefreshRate = 60;
1686 DDSD->ddsCaps.dwCaps = 0;
1687 DDSD->u4.ddpfPixelFormat.dwSize = sizeof(DDSD->u4.ddpfPixelFormat);
1688 ddrawformat_from_wined3dformat(&DDSD->u4.ddpfPixelFormat, mode.format_id);
1689 DDSD->u1.lPitch = mode.width * DDSD->u4.ddpfPixelFormat.u1.dwRGBBitCount / 8;
1690
1691 if(TRACE_ON(ddraw))
1692 {
1693 TRACE("Returning surface desc :\n");
1694 DDRAW_dump_surface_desc(DDSD);
1695 }
1696
1697 wined3d_mutex_unlock();
1698
1699 return DD_OK;
1700 }
1701
ddraw4_GetDisplayMode(IDirectDraw4 * iface,DDSURFACEDESC2 * surface_desc)1702 static HRESULT WINAPI ddraw4_GetDisplayMode(IDirectDraw4 *iface, DDSURFACEDESC2 *surface_desc)
1703 {
1704 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1705
1706 TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
1707
1708 return ddraw7_GetDisplayMode(&ddraw->IDirectDraw7_iface, surface_desc);
1709 }
1710
ddraw2_GetDisplayMode(IDirectDraw2 * iface,DDSURFACEDESC * surface_desc)1711 static HRESULT WINAPI ddraw2_GetDisplayMode(IDirectDraw2 *iface, DDSURFACEDESC *surface_desc)
1712 {
1713 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1714 HRESULT hr;
1715
1716 TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
1717
1718 hr = ddraw7_GetDisplayMode(&ddraw->IDirectDraw7_iface, (DDSURFACEDESC2 *)surface_desc);
1719 if (SUCCEEDED(hr)) surface_desc->dwSize = sizeof(*surface_desc);
1720 return hr;
1721 }
1722
ddraw1_GetDisplayMode(IDirectDraw * iface,DDSURFACEDESC * surface_desc)1723 static HRESULT WINAPI ddraw1_GetDisplayMode(IDirectDraw *iface, DDSURFACEDESC *surface_desc)
1724 {
1725 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1726 HRESULT hr;
1727
1728 TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
1729
1730 hr = ddraw7_GetDisplayMode(&ddraw->IDirectDraw7_iface, (DDSURFACEDESC2 *)surface_desc);
1731 if (SUCCEEDED(hr)) surface_desc->dwSize = sizeof(*surface_desc);
1732 return hr;
1733 }
1734
1735 /*****************************************************************************
1736 * IDirectDraw7::GetFourCCCodes
1737 *
1738 * Returns an array of supported FourCC codes.
1739 *
1740 * Exists in versions 1, 2, 4 and 7
1741 *
1742 * Params:
1743 * NumCodes: Contains the number of Codes that Codes can carry. Returns the number
1744 * of enumerated codes
1745 * Codes: Pointer to an array of DWORDs where the supported codes are written
1746 * to
1747 *
1748 * Returns
1749 * Always returns DD_OK, as it's a stub for now
1750 *
1751 *****************************************************************************/
ddraw7_GetFourCCCodes(IDirectDraw7 * iface,DWORD * NumCodes,DWORD * Codes)1752 static HRESULT WINAPI ddraw7_GetFourCCCodes(IDirectDraw7 *iface, DWORD *NumCodes, DWORD *Codes)
1753 {
1754 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1755 static const enum wined3d_format_id formats[] =
1756 {
1757 WINED3DFMT_YUY2, WINED3DFMT_UYVY, WINED3DFMT_YV12,
1758 WINED3DFMT_DXT1, WINED3DFMT_DXT2, WINED3DFMT_DXT3, WINED3DFMT_DXT4, WINED3DFMT_DXT5,
1759 WINED3DFMT_ATI2N, WINED3DFMT_NVHU, WINED3DFMT_NVHS
1760 };
1761 struct wined3d_display_mode mode;
1762 DWORD count = 0, i, outsize;
1763 HRESULT hr;
1764
1765 TRACE("iface %p, codes_count %p, codes %p.\n", iface, NumCodes, Codes);
1766
1767 if (FAILED(hr = wined3d_get_adapter_display_mode(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL)))
1768 {
1769 ERR("Failed to get display mode, hr %#x.\n", hr);
1770 return hr;
1771 }
1772
1773 outsize = NumCodes && Codes ? *NumCodes : 0;
1774
1775 for (i = 0; i < ARRAY_SIZE(formats); ++i)
1776 {
1777 if (SUCCEEDED(wined3d_check_device_format(ddraw->wined3d, WINED3DADAPTER_DEFAULT, WINED3D_DEVICE_TYPE_HAL,
1778 mode.format_id, 0, WINED3D_RTYPE_TEXTURE_2D, formats[i])))
1779 {
1780 if (count < outsize)
1781 Codes[count] = formats[i];
1782 ++count;
1783 }
1784 }
1785 if(NumCodes) {
1786 TRACE("Returning %u FourCC codes\n", count);
1787 *NumCodes = count;
1788 }
1789
1790 return DD_OK;
1791 }
1792
ddraw4_GetFourCCCodes(IDirectDraw4 * iface,DWORD * codes_count,DWORD * codes)1793 static HRESULT WINAPI ddraw4_GetFourCCCodes(IDirectDraw4 *iface, DWORD *codes_count, DWORD *codes)
1794 {
1795 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1796
1797 TRACE("iface %p, codes_count %p, codes %p.\n", iface, codes_count, codes);
1798
1799 return ddraw7_GetFourCCCodes(&ddraw->IDirectDraw7_iface, codes_count, codes);
1800 }
1801
ddraw2_GetFourCCCodes(IDirectDraw2 * iface,DWORD * codes_count,DWORD * codes)1802 static HRESULT WINAPI ddraw2_GetFourCCCodes(IDirectDraw2 *iface, DWORD *codes_count, DWORD *codes)
1803 {
1804 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1805
1806 TRACE("iface %p, codes_count %p, codes %p.\n", iface, codes_count, codes);
1807
1808 return ddraw7_GetFourCCCodes(&ddraw->IDirectDraw7_iface, codes_count, codes);
1809 }
1810
ddraw1_GetFourCCCodes(IDirectDraw * iface,DWORD * codes_count,DWORD * codes)1811 static HRESULT WINAPI ddraw1_GetFourCCCodes(IDirectDraw *iface, DWORD *codes_count, DWORD *codes)
1812 {
1813 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1814
1815 TRACE("iface %p, codes_count %p, codes %p.\n", iface, codes_count, codes);
1816
1817 return ddraw7_GetFourCCCodes(&ddraw->IDirectDraw7_iface, codes_count, codes);
1818 }
1819
ddraw7_GetMonitorFrequency(IDirectDraw7 * iface,DWORD * frequency)1820 static HRESULT WINAPI ddraw7_GetMonitorFrequency(IDirectDraw7 *iface, DWORD *frequency)
1821 {
1822 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1823 struct wined3d_display_mode mode;
1824 HRESULT hr;
1825
1826 TRACE("iface %p, frequency %p.\n", iface, frequency);
1827
1828 wined3d_mutex_lock();
1829 hr = wined3d_get_adapter_display_mode(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL);
1830 wined3d_mutex_unlock();
1831 if (FAILED(hr))
1832 {
1833 WARN("Failed to get display mode, hr %#x.\n", hr);
1834 return hr;
1835 }
1836
1837 *frequency = mode.refresh_rate;
1838
1839 return DD_OK;
1840 }
1841
ddraw4_GetMonitorFrequency(IDirectDraw4 * iface,DWORD * frequency)1842 static HRESULT WINAPI ddraw4_GetMonitorFrequency(IDirectDraw4 *iface, DWORD *frequency)
1843 {
1844 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1845
1846 TRACE("iface %p, frequency %p.\n", iface, frequency);
1847
1848 return ddraw7_GetMonitorFrequency(&ddraw->IDirectDraw7_iface, frequency);
1849 }
1850
ddraw2_GetMonitorFrequency(IDirectDraw2 * iface,DWORD * frequency)1851 static HRESULT WINAPI ddraw2_GetMonitorFrequency(IDirectDraw2 *iface, DWORD *frequency)
1852 {
1853 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1854
1855 TRACE("iface %p, frequency %p.\n", iface, frequency);
1856
1857 return ddraw7_GetMonitorFrequency(&ddraw->IDirectDraw7_iface, frequency);
1858 }
1859
ddraw1_GetMonitorFrequency(IDirectDraw * iface,DWORD * frequency)1860 static HRESULT WINAPI ddraw1_GetMonitorFrequency(IDirectDraw *iface, DWORD *frequency)
1861 {
1862 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1863
1864 TRACE("iface %p, frequency %p.\n", iface, frequency);
1865
1866 return ddraw7_GetMonitorFrequency(&ddraw->IDirectDraw7_iface, frequency);
1867 }
1868
ddraw7_GetVerticalBlankStatus(IDirectDraw7 * iface,BOOL * status)1869 static HRESULT WINAPI ddraw7_GetVerticalBlankStatus(IDirectDraw7 *iface, BOOL *status)
1870 {
1871 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1872 struct wined3d_raster_status raster_status;
1873 HRESULT hr;
1874
1875 TRACE("iface %p, status %p.\n", iface, status);
1876
1877 if(!status)
1878 return DDERR_INVALIDPARAMS;
1879
1880 wined3d_mutex_lock();
1881 hr = wined3d_get_adapter_raster_status(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &raster_status);
1882 wined3d_mutex_unlock();
1883 if (FAILED(hr))
1884 {
1885 WARN("Failed to get raster status, hr %#x.\n", hr);
1886 return hr;
1887 }
1888
1889 *status = raster_status.in_vblank;
1890
1891 return DD_OK;
1892 }
1893
ddraw4_GetVerticalBlankStatus(IDirectDraw4 * iface,BOOL * status)1894 static HRESULT WINAPI ddraw4_GetVerticalBlankStatus(IDirectDraw4 *iface, BOOL *status)
1895 {
1896 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1897
1898 TRACE("iface %p, status %p.\n", iface, status);
1899
1900 return ddraw7_GetVerticalBlankStatus(&ddraw->IDirectDraw7_iface, status);
1901 }
1902
ddraw2_GetVerticalBlankStatus(IDirectDraw2 * iface,BOOL * status)1903 static HRESULT WINAPI ddraw2_GetVerticalBlankStatus(IDirectDraw2 *iface, BOOL *status)
1904 {
1905 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1906
1907 TRACE("iface %p, status %p.\n", iface, status);
1908
1909 return ddraw7_GetVerticalBlankStatus(&ddraw->IDirectDraw7_iface, status);
1910 }
1911
ddraw1_GetVerticalBlankStatus(IDirectDraw * iface,BOOL * status)1912 static HRESULT WINAPI ddraw1_GetVerticalBlankStatus(IDirectDraw *iface, BOOL *status)
1913 {
1914 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1915
1916 TRACE("iface %p, status %p.\n", iface, status);
1917
1918 return ddraw7_GetVerticalBlankStatus(&ddraw->IDirectDraw7_iface, status);
1919 }
1920
1921 /*****************************************************************************
1922 * IDirectDraw7::GetAvailableVidMem
1923 *
1924 * Returns the total and free video memory
1925 *
1926 * Params:
1927 * caps: Specifies the memory type asked for
1928 * total: Pointer to a DWORD to be filled with the total memory
1929 * free: Pointer to a DWORD to be filled with the free memory
1930 *
1931 * Returns
1932 * DD_OK on success
1933 * DDERR_INVALIDPARAMS if free and total are NULL
1934 *
1935 *****************************************************************************/
ddraw7_GetAvailableVidMem(IDirectDraw7 * iface,DDSCAPS2 * caps,DWORD * total,DWORD * free)1936 static HRESULT WINAPI ddraw7_GetAvailableVidMem(IDirectDraw7 *iface, DDSCAPS2 *caps, DWORD *total,
1937 DWORD *free)
1938 {
1939 unsigned int framebuffer_size, total_vidmem, free_vidmem;
1940 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1941 struct wined3d_display_mode mode;
1942 HRESULT hr = DD_OK;
1943
1944 TRACE("iface %p, caps %p, total %p, free %p.\n", iface, caps, total, free);
1945
1946 if (!total && !free)
1947 return DDERR_INVALIDPARAMS;
1948
1949 if (TRACE_ON(ddraw))
1950 {
1951 TRACE("Asked for memory with description: ");
1952 DDRAW_dump_DDSCAPS2(caps);
1953 }
1954 wined3d_mutex_lock();
1955
1956 /* Todo: System memory vs local video memory vs non-local video memory
1957 * The MSDN also mentions differences between texture memory and other
1958 * resources, but that's not important
1959 */
1960
1961 /* Some applications (e.g. 3DMark 2000) assume that the reported amount of
1962 * video memory doesn't include the memory used by the default framebuffer.
1963 */
1964 if (FAILED(hr = wined3d_get_adapter_display_mode(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL)))
1965 {
1966 WARN("Failed to get display mode, hr %#x.\n", hr);
1967 wined3d_mutex_unlock();
1968 return hr;
1969 }
1970 framebuffer_size = wined3d_calculate_format_pitch(ddraw->wined3d, WINED3DADAPTER_DEFAULT,
1971 mode.format_id, mode.width);
1972 framebuffer_size *= mode.height;
1973
1974 if (free)
1975 {
1976 free_vidmem = wined3d_device_get_available_texture_mem(ddraw->wined3d_device);
1977 *free = framebuffer_size > free_vidmem ? 0 : free_vidmem - framebuffer_size;
1978 TRACE("Free video memory %#x.\n", *free);
1979 }
1980
1981 if (total)
1982 {
1983 struct wined3d_adapter_identifier desc = {0};
1984
1985 hr = wined3d_get_adapter_identifier(ddraw->wined3d, WINED3DADAPTER_DEFAULT, 0, &desc);
1986 total_vidmem = min(UINT_MAX, desc.video_memory);
1987 *total = framebuffer_size > total_vidmem ? 0 : total_vidmem - framebuffer_size;
1988 TRACE("Total video memory %#x.\n", *total);
1989 }
1990
1991 wined3d_mutex_unlock();
1992
1993 return hr;
1994 }
1995
ddraw4_GetAvailableVidMem(IDirectDraw4 * iface,DDSCAPS2 * caps,DWORD * total,DWORD * free)1996 static HRESULT WINAPI ddraw4_GetAvailableVidMem(IDirectDraw4 *iface,
1997 DDSCAPS2 *caps, DWORD *total, DWORD *free)
1998 {
1999 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2000
2001 TRACE("iface %p, caps %p, total %p, free %p.\n", iface, caps, total, free);
2002
2003 return ddraw7_GetAvailableVidMem(&ddraw->IDirectDraw7_iface, caps, total, free);
2004 }
2005
ddraw2_GetAvailableVidMem(IDirectDraw2 * iface,DDSCAPS * caps,DWORD * total,DWORD * free)2006 static HRESULT WINAPI ddraw2_GetAvailableVidMem(IDirectDraw2 *iface,
2007 DDSCAPS *caps, DWORD *total, DWORD *free)
2008 {
2009 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2010 DDSCAPS2 caps2;
2011
2012 TRACE("iface %p, caps %p, total %p, free %p.\n", iface, caps, total, free);
2013
2014 DDRAW_Convert_DDSCAPS_1_To_2(caps, &caps2);
2015 return ddraw7_GetAvailableVidMem(&ddraw->IDirectDraw7_iface, &caps2, total, free);
2016 }
2017
2018 /*****************************************************************************
2019 * IDirectDraw7::Initialize
2020 *
2021 * Initializes a DirectDraw interface.
2022 *
2023 * Params:
2024 * GUID: Interface identifier. Well, don't know what this is really good
2025 * for
2026 *
2027 * Returns
2028 * Returns DD_OK on the first call,
2029 * DDERR_ALREADYINITIALIZED on repeated calls
2030 *
2031 *****************************************************************************/
ddraw7_Initialize(IDirectDraw7 * iface,GUID * guid)2032 static HRESULT WINAPI ddraw7_Initialize(IDirectDraw7 *iface, GUID *guid)
2033 {
2034 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2035
2036 TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
2037
2038 if (ddraw->flags & DDRAW_INITIALIZED)
2039 return DDERR_ALREADYINITIALIZED;
2040
2041 /* FIXME: To properly take the GUID into account we should call
2042 * ddraw_init() here instead of in DDRAW_Create(). */
2043 if (guid)
2044 FIXME("Ignoring guid %s.\n", debugstr_guid(guid));
2045
2046 ddraw->flags |= DDRAW_INITIALIZED;
2047 return DD_OK;
2048 }
2049
ddraw4_Initialize(IDirectDraw4 * iface,GUID * guid)2050 static HRESULT WINAPI ddraw4_Initialize(IDirectDraw4 *iface, GUID *guid)
2051 {
2052 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2053
2054 TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
2055
2056 return ddraw7_Initialize(&ddraw->IDirectDraw7_iface, guid);
2057 }
2058
ddraw2_Initialize(IDirectDraw2 * iface,GUID * guid)2059 static HRESULT WINAPI ddraw2_Initialize(IDirectDraw2 *iface, GUID *guid)
2060 {
2061 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2062
2063 TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
2064
2065 return ddraw7_Initialize(&ddraw->IDirectDraw7_iface, guid);
2066 }
2067
ddraw1_Initialize(IDirectDraw * iface,GUID * guid)2068 static HRESULT WINAPI ddraw1_Initialize(IDirectDraw *iface, GUID *guid)
2069 {
2070 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
2071
2072 TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
2073
2074 return ddraw7_Initialize(&ddraw->IDirectDraw7_iface, guid);
2075 }
2076
d3d1_Initialize(IDirect3D * iface,REFIID riid)2077 static HRESULT WINAPI d3d1_Initialize(IDirect3D *iface, REFIID riid)
2078 {
2079 TRACE("iface %p, riid %s.\n", iface, debugstr_guid(riid));
2080
2081 return DDERR_ALREADYINITIALIZED;
2082 }
2083
2084 /*****************************************************************************
2085 * IDirectDraw7::FlipToGDISurface
2086 *
2087 * "Makes the surface that the GDI writes to the primary surface"
2088 * Looks like some windows specific thing we don't have to care about.
2089 * According to MSDN it permits GDI dialog boxes in FULLSCREEN mode. Good to
2090 * show error boxes ;)
2091 * Well, just return DD_OK.
2092 *
2093 * Returns:
2094 * Always returns DD_OK
2095 *
2096 *****************************************************************************/
ddraw7_FlipToGDISurface(IDirectDraw7 * iface)2097 static HRESULT WINAPI ddraw7_FlipToGDISurface(IDirectDraw7 *iface)
2098 {
2099 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2100 IDirectDrawSurface7 *gdi_surface;
2101 struct ddraw_surface *gdi_impl;
2102 HRESULT hr;
2103
2104 TRACE("iface %p.\n", iface);
2105
2106 wined3d_mutex_lock();
2107
2108 if (FAILED(hr = IDirectDraw7_GetGDISurface(iface, &gdi_surface)))
2109 {
2110 WARN("Failed to retrieve GDI surface, hr %#x.\n", hr);
2111 wined3d_mutex_unlock();
2112 return hr;
2113 }
2114
2115 gdi_impl = impl_from_IDirectDrawSurface7(gdi_surface);
2116 if (gdi_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER)
2117 hr = DD_OK;
2118 else
2119 hr = IDirectDrawSurface7_Flip(&ddraw->primary->IDirectDrawSurface7_iface, gdi_surface, DDFLIP_WAIT);
2120 IDirectDrawSurface7_Release(gdi_surface);
2121
2122 wined3d_mutex_unlock();
2123
2124 return hr;
2125 }
2126
ddraw4_FlipToGDISurface(IDirectDraw4 * iface)2127 static HRESULT WINAPI ddraw4_FlipToGDISurface(IDirectDraw4 *iface)
2128 {
2129 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2130
2131 TRACE("iface %p.\n", iface);
2132
2133 return ddraw7_FlipToGDISurface(&ddraw->IDirectDraw7_iface);
2134 }
2135
ddraw2_FlipToGDISurface(IDirectDraw2 * iface)2136 static HRESULT WINAPI ddraw2_FlipToGDISurface(IDirectDraw2 *iface)
2137 {
2138 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2139
2140 TRACE("iface %p.\n", iface);
2141
2142 return ddraw7_FlipToGDISurface(&ddraw->IDirectDraw7_iface);
2143 }
2144
ddraw1_FlipToGDISurface(IDirectDraw * iface)2145 static HRESULT WINAPI ddraw1_FlipToGDISurface(IDirectDraw *iface)
2146 {
2147 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
2148
2149 TRACE("iface %p.\n", iface);
2150
2151 return ddraw7_FlipToGDISurface(&ddraw->IDirectDraw7_iface);
2152 }
2153
2154 /*****************************************************************************
2155 * IDirectDraw7::WaitForVerticalBlank
2156 *
2157 * This method allows applications to get in sync with the vertical blank
2158 * interval.
2159 * The wormhole demo in the DirectX 7 sdk uses this call, and it doesn't
2160 * redraw the screen, most likely because of this stub
2161 *
2162 * Parameters:
2163 * Flags: one of DDWAITVB_BLOCKBEGIN, DDWAITVB_BLOCKBEGINEVENT
2164 * or DDWAITVB_BLOCKEND
2165 * h: Not used, according to MSDN
2166 *
2167 * Returns:
2168 * Always returns DD_OK
2169 *
2170 *****************************************************************************/
ddraw7_WaitForVerticalBlank(IDirectDraw7 * iface,DWORD Flags,HANDLE event)2171 static HRESULT WINAPI ddraw7_WaitForVerticalBlank(IDirectDraw7 *iface, DWORD Flags, HANDLE event)
2172 {
2173 static BOOL hide;
2174
2175 TRACE("iface %p, flags %#x, event %p.\n", iface, Flags, event);
2176
2177 /* This function is called often, so print the fixme only once */
2178 if(!hide)
2179 {
2180 FIXME("iface %p, flags %#x, event %p stub!\n", iface, Flags, event);
2181 hide = TRUE;
2182 }
2183
2184 /* MSDN says DDWAITVB_BLOCKBEGINEVENT is not supported */
2185 if(Flags & DDWAITVB_BLOCKBEGINEVENT)
2186 return DDERR_UNSUPPORTED; /* unchecked */
2187
2188 return DD_OK;
2189 }
2190
ddraw4_WaitForVerticalBlank(IDirectDraw4 * iface,DWORD flags,HANDLE event)2191 static HRESULT WINAPI ddraw4_WaitForVerticalBlank(IDirectDraw4 *iface, DWORD flags, HANDLE event)
2192 {
2193 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2194
2195 TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event);
2196
2197 return ddraw7_WaitForVerticalBlank(&ddraw->IDirectDraw7_iface, flags, event);
2198 }
2199
ddraw2_WaitForVerticalBlank(IDirectDraw2 * iface,DWORD flags,HANDLE event)2200 static HRESULT WINAPI ddraw2_WaitForVerticalBlank(IDirectDraw2 *iface, DWORD flags, HANDLE event)
2201 {
2202 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2203
2204 TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event);
2205
2206 return ddraw7_WaitForVerticalBlank(&ddraw->IDirectDraw7_iface, flags, event);
2207 }
2208
ddraw1_WaitForVerticalBlank(IDirectDraw * iface,DWORD flags,HANDLE event)2209 static HRESULT WINAPI ddraw1_WaitForVerticalBlank(IDirectDraw *iface, DWORD flags, HANDLE event)
2210 {
2211 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
2212
2213 TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event);
2214
2215 return ddraw7_WaitForVerticalBlank(&ddraw->IDirectDraw7_iface, flags, event);
2216 }
2217
ddraw7_GetScanLine(IDirectDraw7 * iface,DWORD * Scanline)2218 static HRESULT WINAPI ddraw7_GetScanLine(IDirectDraw7 *iface, DWORD *Scanline)
2219 {
2220 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2221 struct wined3d_raster_status raster_status;
2222 HRESULT hr;
2223
2224 TRACE("iface %p, line %p.\n", iface, Scanline);
2225
2226 wined3d_mutex_lock();
2227 hr = wined3d_get_adapter_raster_status(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &raster_status);
2228 wined3d_mutex_unlock();
2229 if (FAILED(hr))
2230 {
2231 WARN("Failed to get raster status, hr %#x.\n", hr);
2232 return hr;
2233 }
2234
2235 *Scanline = raster_status.scan_line;
2236
2237 if (raster_status.in_vblank)
2238 return DDERR_VERTICALBLANKINPROGRESS;
2239
2240 return DD_OK;
2241 }
2242
ddraw4_GetScanLine(IDirectDraw4 * iface,DWORD * line)2243 static HRESULT WINAPI ddraw4_GetScanLine(IDirectDraw4 *iface, DWORD *line)
2244 {
2245 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2246
2247 TRACE("iface %p, line %p.\n", iface, line);
2248
2249 return ddraw7_GetScanLine(&ddraw->IDirectDraw7_iface, line);
2250 }
2251
ddraw2_GetScanLine(IDirectDraw2 * iface,DWORD * line)2252 static HRESULT WINAPI ddraw2_GetScanLine(IDirectDraw2 *iface, DWORD *line)
2253 {
2254 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2255
2256 TRACE("iface %p, line %p.\n", iface, line);
2257
2258 return ddraw7_GetScanLine(&ddraw->IDirectDraw7_iface, line);
2259 }
2260
ddraw1_GetScanLine(IDirectDraw * iface,DWORD * line)2261 static HRESULT WINAPI ddraw1_GetScanLine(IDirectDraw *iface, DWORD *line)
2262 {
2263 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
2264
2265 TRACE("iface %p, line %p.\n", iface, line);
2266
2267 return ddraw7_GetScanLine(&ddraw->IDirectDraw7_iface, line);
2268 }
2269
ddraw7_TestCooperativeLevel(IDirectDraw7 * iface)2270 static HRESULT WINAPI ddraw7_TestCooperativeLevel(IDirectDraw7 *iface)
2271 {
2272 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2273
2274 TRACE("iface %p.\n", iface);
2275
2276 return ddraw->device_state == DDRAW_DEVICE_STATE_LOST ? DDERR_NOEXCLUSIVEMODE : DD_OK;
2277 }
2278
ddraw4_TestCooperativeLevel(IDirectDraw4 * iface)2279 static HRESULT WINAPI ddraw4_TestCooperativeLevel(IDirectDraw4 *iface)
2280 {
2281 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2282
2283 TRACE("iface %p.\n", iface);
2284
2285 return ddraw7_TestCooperativeLevel(&ddraw->IDirectDraw7_iface);
2286 }
2287
2288 /*****************************************************************************
2289 * IDirectDraw7::GetGDISurface
2290 *
2291 * Returns the surface that GDI is treating as the primary surface.
2292 * For Wine this is the front buffer
2293 *
2294 * Params:
2295 * GDISurface: Address to write the surface pointer to
2296 *
2297 * Returns:
2298 * DD_OK if the surface was found
2299 * DDERR_NOTFOUND if the GDI surface wasn't found
2300 *
2301 *****************************************************************************/
ddraw7_GetGDISurface(IDirectDraw7 * iface,IDirectDrawSurface7 ** GDISurface)2302 static HRESULT WINAPI ddraw7_GetGDISurface(IDirectDraw7 *iface, IDirectDrawSurface7 **GDISurface)
2303 {
2304 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2305
2306 TRACE("iface %p, surface %p.\n", iface, GDISurface);
2307
2308 wined3d_mutex_lock();
2309
2310 if (!(*GDISurface = &ddraw->primary->IDirectDrawSurface7_iface))
2311 {
2312 WARN("Primary not created yet.\n");
2313 wined3d_mutex_unlock();
2314 return DDERR_NOTFOUND;
2315 }
2316 IDirectDrawSurface7_AddRef(*GDISurface);
2317
2318 wined3d_mutex_unlock();
2319
2320 return DD_OK;
2321 }
2322
ddraw4_GetGDISurface(IDirectDraw4 * iface,IDirectDrawSurface4 ** surface)2323 static HRESULT WINAPI ddraw4_GetGDISurface(IDirectDraw4 *iface, IDirectDrawSurface4 **surface)
2324 {
2325 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2326 struct ddraw_surface *surface_impl;
2327 IDirectDrawSurface7 *surface7;
2328 HRESULT hr;
2329
2330 TRACE("iface %p, surface %p.\n", iface, surface);
2331
2332 hr = ddraw7_GetGDISurface(&ddraw->IDirectDraw7_iface, &surface7);
2333 if (FAILED(hr))
2334 {
2335 *surface = NULL;
2336 return hr;
2337 }
2338 surface_impl = impl_from_IDirectDrawSurface7(surface7);
2339 *surface = &surface_impl->IDirectDrawSurface4_iface;
2340 IDirectDrawSurface4_AddRef(*surface);
2341 IDirectDrawSurface7_Release(surface7);
2342
2343 return hr;
2344 }
2345
ddraw2_GetGDISurface(IDirectDraw2 * iface,IDirectDrawSurface ** surface)2346 static HRESULT WINAPI ddraw2_GetGDISurface(IDirectDraw2 *iface, IDirectDrawSurface **surface)
2347 {
2348 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2349 struct ddraw_surface *surface_impl;
2350 IDirectDrawSurface7 *surface7;
2351 HRESULT hr;
2352
2353 TRACE("iface %p, surface %p.\n", iface, surface);
2354
2355 hr = ddraw7_GetGDISurface(&ddraw->IDirectDraw7_iface, &surface7);
2356 if (FAILED(hr))
2357 {
2358 *surface = NULL;
2359 return hr;
2360 }
2361 surface_impl = impl_from_IDirectDrawSurface7(surface7);
2362 *surface = &surface_impl->IDirectDrawSurface_iface;
2363 IDirectDrawSurface_AddRef(*surface);
2364 IDirectDrawSurface7_Release(surface7);
2365
2366 return hr;
2367 }
2368
ddraw1_GetGDISurface(IDirectDraw * iface,IDirectDrawSurface ** surface)2369 static HRESULT WINAPI ddraw1_GetGDISurface(IDirectDraw *iface, IDirectDrawSurface **surface)
2370 {
2371 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
2372 struct ddraw_surface *surface_impl;
2373 IDirectDrawSurface7 *surface7;
2374 HRESULT hr;
2375
2376 TRACE("iface %p, surface %p.\n", iface, surface);
2377
2378 hr = ddraw7_GetGDISurface(&ddraw->IDirectDraw7_iface, &surface7);
2379 if (FAILED(hr))
2380 {
2381 *surface = NULL;
2382 return hr;
2383 }
2384 surface_impl = impl_from_IDirectDrawSurface7(surface7);
2385 *surface = &surface_impl->IDirectDrawSurface_iface;
2386 IDirectDrawSurface_AddRef(*surface);
2387 IDirectDrawSurface7_Release(surface7);
2388
2389 return hr;
2390 }
2391
2392 struct displaymodescallback_context
2393 {
2394 LPDDENUMMODESCALLBACK func;
2395 void *context;
2396 };
2397
EnumDisplayModesCallbackThunk(DDSURFACEDESC2 * surface_desc,void * context)2398 static HRESULT CALLBACK EnumDisplayModesCallbackThunk(DDSURFACEDESC2 *surface_desc, void *context)
2399 {
2400 struct displaymodescallback_context *cbcontext = context;
2401 DDSURFACEDESC desc;
2402
2403 DDSD2_to_DDSD(surface_desc, &desc);
2404 return cbcontext->func(&desc, cbcontext->context);
2405 }
2406
2407 /*****************************************************************************
2408 * IDirectDraw7::EnumDisplayModes
2409 *
2410 * Enumerates the supported Display modes. The modes can be filtered with
2411 * the DDSD parameter.
2412 *
2413 * Params:
2414 * Flags: can be DDEDM_REFRESHRATES and DDEDM_STANDARDVGAMODES. For old ddraw
2415 * versions (3 and older?) this is reserved and must be 0.
2416 * DDSD: Surface description to filter the modes
2417 * Context: Pointer passed back to the callback function
2418 * cb: Application-provided callback function
2419 *
2420 * Returns:
2421 * DD_OK on success
2422 * DDERR_INVALIDPARAMS if the callback wasn't set
2423 *
2424 *****************************************************************************/
ddraw7_EnumDisplayModes(IDirectDraw7 * iface,DWORD Flags,DDSURFACEDESC2 * DDSD,void * Context,LPDDENUMMODESCALLBACK2 cb)2425 static HRESULT WINAPI ddraw7_EnumDisplayModes(IDirectDraw7 *iface, DWORD Flags,
2426 DDSURFACEDESC2 *DDSD, void *Context, LPDDENUMMODESCALLBACK2 cb)
2427 {
2428 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2429 struct wined3d_display_mode *enum_modes = NULL;
2430 struct wined3d_display_mode mode;
2431 unsigned int modenum, fmt;
2432 DDSURFACEDESC2 callback_sd;
2433 unsigned enum_mode_count = 0, enum_mode_array_size = 16;
2434 DDPIXELFORMAT pixelformat;
2435
2436 static const enum wined3d_format_id checkFormatList[] =
2437 {
2438 WINED3DFMT_B8G8R8X8_UNORM,
2439 WINED3DFMT_B5G6R5_UNORM,
2440 WINED3DFMT_P8_UINT,
2441 };
2442
2443 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2444 iface, Flags, DDSD, Context, cb);
2445
2446 if (!cb)
2447 return DDERR_INVALIDPARAMS;
2448
2449 if (!(enum_modes = heap_alloc(enum_mode_array_size * sizeof(*enum_modes))))
2450 return DDERR_OUTOFMEMORY;
2451
2452 wined3d_mutex_lock();
2453
2454 pixelformat.dwSize = sizeof(pixelformat);
2455 for(fmt = 0; fmt < ARRAY_SIZE(checkFormatList); fmt++)
2456 {
2457 modenum = 0;
2458 while (wined3d_enum_adapter_modes(ddraw->wined3d, WINED3DADAPTER_DEFAULT, checkFormatList[fmt],
2459 WINED3D_SCANLINE_ORDERING_UNKNOWN, modenum++, &mode) == WINED3D_OK)
2460 {
2461 BOOL found = FALSE;
2462 unsigned i;
2463
2464 ddrawformat_from_wined3dformat(&pixelformat, mode.format_id);
2465 if (DDSD)
2466 {
2467 if (DDSD->dwFlags & DDSD_WIDTH && mode.width != DDSD->dwWidth)
2468 continue;
2469 if (DDSD->dwFlags & DDSD_HEIGHT && mode.height != DDSD->dwHeight)
2470 continue;
2471 if (DDSD->dwFlags & DDSD_REFRESHRATE && mode.refresh_rate != DDSD->u2.dwRefreshRate)
2472 continue;
2473 if (DDSD->dwFlags & DDSD_PIXELFORMAT
2474 && pixelformat.u1.dwRGBBitCount != DDSD->u4.ddpfPixelFormat.u1.dwRGBBitCount)
2475 continue;
2476 }
2477
2478 /* DX docs state EnumDisplayMode should return only unique modes */
2479 for (i = 0; i < enum_mode_count; i++)
2480 {
2481 if (enum_modes[i].width == mode.width && enum_modes[i].height == mode.height
2482 && enum_modes[i].format_id == mode.format_id
2483 && (enum_modes[i].refresh_rate == mode.refresh_rate || !(Flags & DDEDM_REFRESHRATES)))
2484 {
2485 found = TRUE;
2486 break;
2487 }
2488 }
2489 if(found) continue;
2490
2491 memset(&callback_sd, 0, sizeof(callback_sd));
2492 callback_sd.dwSize = sizeof(callback_sd);
2493 callback_sd.u4.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
2494
2495 callback_sd.dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT|DDSD_PITCH|DDSD_REFRESHRATE;
2496 if (Flags & DDEDM_REFRESHRATES)
2497 callback_sd.u2.dwRefreshRate = mode.refresh_rate;
2498
2499 callback_sd.dwWidth = mode.width;
2500 callback_sd.dwHeight = mode.height;
2501
2502 callback_sd.u4.ddpfPixelFormat=pixelformat;
2503
2504 /* Calc pitch and DWORD align like MSDN says */
2505 callback_sd.u1.lPitch = (callback_sd.u4.ddpfPixelFormat.u1.dwRGBBitCount / 8) * mode.width;
2506 callback_sd.u1.lPitch = (callback_sd.u1.lPitch + 3) & ~3;
2507
2508 TRACE("Enumerating %dx%dx%d @%d\n", callback_sd.dwWidth, callback_sd.dwHeight, callback_sd.u4.ddpfPixelFormat.u1.dwRGBBitCount,
2509 callback_sd.u2.dwRefreshRate);
2510
2511 if(cb(&callback_sd, Context) == DDENUMRET_CANCEL)
2512 {
2513 TRACE("Application asked to terminate the enumeration\n");
2514 heap_free(enum_modes);
2515 wined3d_mutex_unlock();
2516 return DD_OK;
2517 }
2518
2519 if (enum_mode_count == enum_mode_array_size)
2520 {
2521 struct wined3d_display_mode *new_enum_modes;
2522
2523 enum_mode_array_size *= 2;
2524 if (!(new_enum_modes = heap_realloc(enum_modes, enum_mode_array_size * sizeof(*new_enum_modes))))
2525 {
2526 heap_free(enum_modes);
2527 wined3d_mutex_unlock();
2528 return DDERR_OUTOFMEMORY;
2529 }
2530
2531 enum_modes = new_enum_modes;
2532 }
2533 enum_modes[enum_mode_count++] = mode;
2534 }
2535 }
2536
2537 TRACE("End of enumeration\n");
2538 heap_free(enum_modes);
2539 wined3d_mutex_unlock();
2540
2541 return DD_OK;
2542 }
2543
ddraw4_EnumDisplayModes(IDirectDraw4 * iface,DWORD flags,DDSURFACEDESC2 * surface_desc,void * context,LPDDENUMMODESCALLBACK2 callback)2544 static HRESULT WINAPI ddraw4_EnumDisplayModes(IDirectDraw4 *iface, DWORD flags,
2545 DDSURFACEDESC2 *surface_desc, void *context, LPDDENUMMODESCALLBACK2 callback)
2546 {
2547 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2548
2549 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2550 iface, flags, surface_desc, context, callback);
2551
2552 return ddraw7_EnumDisplayModes(&ddraw->IDirectDraw7_iface, flags, surface_desc, context, callback);
2553 }
2554
ddraw2_EnumDisplayModes(IDirectDraw2 * iface,DWORD flags,DDSURFACEDESC * surface_desc,void * context,LPDDENUMMODESCALLBACK callback)2555 static HRESULT WINAPI ddraw2_EnumDisplayModes(IDirectDraw2 *iface, DWORD flags,
2556 DDSURFACEDESC *surface_desc, void *context, LPDDENUMMODESCALLBACK callback)
2557 {
2558 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2559 struct displaymodescallback_context cbcontext;
2560 DDSURFACEDESC2 surface_desc2;
2561
2562 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2563 iface, flags, surface_desc, context, callback);
2564
2565 cbcontext.func = callback;
2566 cbcontext.context = context;
2567
2568 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
2569 return ddraw7_EnumDisplayModes(&ddraw->IDirectDraw7_iface, flags,
2570 surface_desc ? &surface_desc2 : NULL, &cbcontext, EnumDisplayModesCallbackThunk);
2571 }
2572
ddraw1_EnumDisplayModes(IDirectDraw * iface,DWORD flags,DDSURFACEDESC * surface_desc,void * context,LPDDENUMMODESCALLBACK callback)2573 static HRESULT WINAPI ddraw1_EnumDisplayModes(IDirectDraw *iface, DWORD flags,
2574 DDSURFACEDESC *surface_desc, void *context, LPDDENUMMODESCALLBACK callback)
2575 {
2576 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
2577 struct displaymodescallback_context cbcontext;
2578 DDSURFACEDESC2 surface_desc2;
2579
2580 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2581 iface, flags, surface_desc, context, callback);
2582
2583 cbcontext.func = callback;
2584 cbcontext.context = context;
2585
2586 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
2587 return ddraw7_EnumDisplayModes(&ddraw->IDirectDraw7_iface, flags,
2588 surface_desc ? &surface_desc2 : NULL, &cbcontext, EnumDisplayModesCallbackThunk);
2589 }
2590
2591 /*****************************************************************************
2592 * IDirectDraw7::EvaluateMode
2593 *
2594 * Used with IDirectDraw7::StartModeTest to test video modes.
2595 * EvaluateMode is used to pass or fail a mode, and continue with the next
2596 * mode
2597 *
2598 * Params:
2599 * Flags: DDEM_MODEPASSED or DDEM_MODEFAILED
2600 * Timeout: Returns the amount of seconds left before the mode would have
2601 * been failed automatically
2602 *
2603 * Returns:
2604 * This implementation always DD_OK, because it's a stub
2605 *
2606 *****************************************************************************/
ddraw7_EvaluateMode(IDirectDraw7 * iface,DWORD Flags,DWORD * Timeout)2607 static HRESULT WINAPI ddraw7_EvaluateMode(IDirectDraw7 *iface, DWORD Flags, DWORD *Timeout)
2608 {
2609 FIXME("iface %p, flags %#x, timeout %p stub!\n", iface, Flags, Timeout);
2610
2611 /* When implementing this, implement it in WineD3D */
2612
2613 return DD_OK;
2614 }
2615
2616 /*****************************************************************************
2617 * IDirectDraw7::GetDeviceIdentifier
2618 *
2619 * Returns the device identifier, which gives information about the driver
2620 * Our device identifier is defined at the beginning of this file.
2621 *
2622 * Params:
2623 * DDDI: Address for the returned structure
2624 * Flags: Can be DDGDI_GETHOSTIDENTIFIER
2625 *
2626 * Returns:
2627 * On success it returns DD_OK
2628 * DDERR_INVALIDPARAMS if DDDI is NULL
2629 *
2630 *****************************************************************************/
ddraw7_GetDeviceIdentifier(IDirectDraw7 * iface,DDDEVICEIDENTIFIER2 * DDDI,DWORD Flags)2631 static HRESULT WINAPI ddraw7_GetDeviceIdentifier(IDirectDraw7 *iface,
2632 DDDEVICEIDENTIFIER2 *DDDI, DWORD Flags)
2633 {
2634 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2635 struct wined3d_adapter_identifier adapter_id;
2636 HRESULT hr = S_OK;
2637
2638 TRACE("iface %p, device_identifier %p, flags %#x.\n", iface, DDDI, Flags);
2639
2640 if (!DDDI)
2641 return DDERR_INVALIDPARAMS;
2642
2643 if (Flags & DDGDI_GETHOSTIDENTIFIER)
2644 {
2645 /* The DDGDI_GETHOSTIDENTIFIER returns the information about the 2D
2646 * host adapter, if there's a secondary 3D adapter. This doesn't apply
2647 * to any modern hardware, nor is it interesting for Wine, so ignore it.
2648 * Size of DDDEVICEIDENTIFIER2 may be aligned to 8 bytes and thus 4
2649 * bytes too long. So only copy the relevant part of the structure
2650 */
2651
2652 memcpy(DDDI, &deviceidentifier, FIELD_OFFSET(DDDEVICEIDENTIFIER2, dwWHQLLevel) + sizeof(DWORD));
2653 return DD_OK;
2654 }
2655
2656 /* Drakan: Order of the Flame expects accurate D3D device information from ddraw */
2657 adapter_id.driver = DDDI->szDriver;
2658 adapter_id.driver_size = sizeof(DDDI->szDriver);
2659 adapter_id.description = DDDI->szDescription;
2660 adapter_id.description_size = sizeof(DDDI->szDescription);
2661 adapter_id.device_name_size = 0;
2662 wined3d_mutex_lock();
2663 hr = wined3d_get_adapter_identifier(ddraw->wined3d, WINED3DADAPTER_DEFAULT, 0x0, &adapter_id);
2664 wined3d_mutex_unlock();
2665 if (FAILED(hr)) return hr;
2666
2667 DDDI->liDriverVersion = adapter_id.driver_version;
2668 DDDI->dwVendorId = adapter_id.vendor_id;
2669 DDDI->dwDeviceId = adapter_id.device_id;
2670 DDDI->dwSubSysId = adapter_id.subsystem_id;
2671 DDDI->dwRevision = adapter_id.revision;
2672 DDDI->guidDeviceIdentifier = adapter_id.device_identifier;
2673 DDDI->dwWHQLLevel = adapter_id.whql_level;
2674 return DD_OK;
2675 }
2676
ddraw4_GetDeviceIdentifier(IDirectDraw4 * iface,DDDEVICEIDENTIFIER * identifier,DWORD flags)2677 static HRESULT WINAPI ddraw4_GetDeviceIdentifier(IDirectDraw4 *iface,
2678 DDDEVICEIDENTIFIER *identifier, DWORD flags)
2679 {
2680 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2681 DDDEVICEIDENTIFIER2 identifier2;
2682 HRESULT hr;
2683
2684 TRACE("iface %p, identifier %p, flags %#x.\n", iface, identifier, flags);
2685
2686 hr = ddraw7_GetDeviceIdentifier(&ddraw->IDirectDraw7_iface, &identifier2, flags);
2687 DDRAW_Convert_DDDEVICEIDENTIFIER_2_To_1(&identifier2, identifier);
2688
2689 return hr;
2690 }
2691
2692 /*****************************************************************************
2693 * IDirectDraw7::GetSurfaceFromDC
2694 *
2695 * Returns the Surface for a GDI device context handle.
2696 * Is this related to IDirectDrawSurface::GetDC ???
2697 *
2698 * Params:
2699 * hdc: hdc to return the surface for
2700 * Surface: Address to write the surface pointer to
2701 *
2702 * Returns:
2703 * Always returns DD_OK because it's a stub
2704 *
2705 *****************************************************************************/
ddraw7_GetSurfaceFromDC(IDirectDraw7 * iface,HDC dc,IDirectDrawSurface7 ** surface)2706 static HRESULT WINAPI ddraw7_GetSurfaceFromDC(IDirectDraw7 *iface,
2707 HDC dc, IDirectDrawSurface7 **surface)
2708 {
2709 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2710 struct ddraw_surface *surface_impl;
2711
2712 TRACE("iface %p, dc %p, surface %p.\n", iface, dc, surface);
2713
2714 if (!surface)
2715 return E_INVALIDARG;
2716
2717 if (!dc)
2718 goto done;
2719
2720 wined3d_mutex_lock();
2721 LIST_FOR_EACH_ENTRY(surface_impl, &ddraw->surface_list, struct ddraw_surface, surface_list_entry)
2722 {
2723 if (surface_impl->dc != dc)
2724 continue;
2725
2726 TRACE("Found surface %p for dc %p.\n", surface_impl, dc);
2727 *surface = &surface_impl->IDirectDrawSurface7_iface;
2728 IDirectDrawSurface7_AddRef(*surface);
2729 wined3d_mutex_unlock();
2730 return DD_OK;
2731 }
2732 wined3d_mutex_unlock();
2733
2734 done:
2735 TRACE("No surface found for dc %p.\n", dc);
2736 *surface = NULL;
2737 return DDERR_NOTFOUND;
2738 }
2739
ddraw4_GetSurfaceFromDC(IDirectDraw4 * iface,HDC dc,IDirectDrawSurface4 ** surface)2740 static HRESULT WINAPI ddraw4_GetSurfaceFromDC(IDirectDraw4 *iface, HDC dc,
2741 IDirectDrawSurface4 **surface)
2742 {
2743 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2744 struct ddraw_surface *surface_impl;
2745 IDirectDrawSurface7 *surface7;
2746 HRESULT hr;
2747
2748 TRACE("iface %p, dc %p, surface %p.\n", iface, dc, surface);
2749
2750 if (!surface) return E_INVALIDARG;
2751
2752 hr = ddraw7_GetSurfaceFromDC(&ddraw->IDirectDraw7_iface, dc, &surface7);
2753 if (FAILED(hr))
2754 {
2755 *surface = NULL;
2756 return hr;
2757 }
2758 surface_impl = impl_from_IDirectDrawSurface7(surface7);
2759 /* Tests say this is true */
2760 *surface = (IDirectDrawSurface4 *)&surface_impl->IDirectDrawSurface_iface;
2761 IDirectDrawSurface_AddRef(&surface_impl->IDirectDrawSurface_iface);
2762 IDirectDrawSurface7_Release(surface7);
2763
2764 return hr;
2765 }
2766
restore_callback(IDirectDrawSurface7 * surface,DDSURFACEDESC2 * desc,void * context)2767 static HRESULT CALLBACK restore_callback(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *desc, void *context)
2768 {
2769 IDirectDrawSurface_Restore(surface);
2770 IDirectDrawSurface_Release(surface);
2771
2772 return DDENUMRET_OK;
2773 }
2774
ddraw7_RestoreAllSurfaces(IDirectDraw7 * iface)2775 static HRESULT WINAPI ddraw7_RestoreAllSurfaces(IDirectDraw7 *iface)
2776 {
2777 TRACE("iface %p.\n", iface);
2778
2779 return IDirectDraw7_EnumSurfaces(iface, DDENUMSURFACES_ALL | DDENUMSURFACES_DOESEXIST,
2780 NULL, NULL, restore_callback);
2781 }
2782
ddraw4_RestoreAllSurfaces(IDirectDraw4 * iface)2783 static HRESULT WINAPI ddraw4_RestoreAllSurfaces(IDirectDraw4 *iface)
2784 {
2785 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2786
2787 TRACE("iface %p.\n", iface);
2788
2789 return ddraw7_RestoreAllSurfaces(&ddraw->IDirectDraw7_iface);
2790 }
2791
2792 /*****************************************************************************
2793 * IDirectDraw7::StartModeTest
2794 *
2795 * Tests the specified video modes to update the system registry with
2796 * refresh rate information. StartModeTest starts the mode test,
2797 * EvaluateMode is used to fail or pass a mode. If EvaluateMode
2798 * isn't called within 15 seconds, the mode is failed automatically
2799 *
2800 * As refresh rates are handled by the X server, I don't think this
2801 * Method is important
2802 *
2803 * Params:
2804 * Modes: An array of mode specifications
2805 * NumModes: The number of modes in Modes
2806 * Flags: Some flags...
2807 *
2808 * Returns:
2809 * Returns DDERR_TESTFINISHED if flags contains DDSMT_ISTESTREQUIRED,
2810 * if no modes are passed, DDERR_INVALIDPARAMS is returned,
2811 * otherwise DD_OK
2812 *
2813 *****************************************************************************/
ddraw7_StartModeTest(IDirectDraw7 * iface,SIZE * Modes,DWORD NumModes,DWORD Flags)2814 static HRESULT WINAPI ddraw7_StartModeTest(IDirectDraw7 *iface, SIZE *Modes, DWORD NumModes, DWORD Flags)
2815 {
2816 FIXME("iface %p, modes %p, mode_count %u, flags %#x partial stub!\n",
2817 iface, Modes, NumModes, Flags);
2818
2819 /* This looks sane */
2820 if( (!Modes) || (NumModes == 0) ) return DDERR_INVALIDPARAMS;
2821
2822 /* DDSMT_ISTESTREQUIRED asks if a mode test is necessary.
2823 * As it is not, DDERR_TESTFINISHED is returned
2824 * (hopefully that's correct
2825 *
2826 if(Flags & DDSMT_ISTESTREQUIRED) return DDERR_TESTFINISHED;
2827 * well, that value doesn't (yet) exist in the wine headers, so ignore it
2828 */
2829
2830 return DD_OK;
2831 }
2832
ddraw7_CreateSurface(IDirectDraw7 * iface,DDSURFACEDESC2 * surface_desc,IDirectDrawSurface7 ** surface,IUnknown * outer_unknown)2833 static HRESULT WINAPI ddraw7_CreateSurface(IDirectDraw7 *iface, DDSURFACEDESC2 *surface_desc,
2834 IDirectDrawSurface7 **surface, IUnknown *outer_unknown)
2835 {
2836 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2837 struct ddraw_surface *impl;
2838 HRESULT hr;
2839
2840 TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
2841 iface, surface_desc, surface, outer_unknown);
2842
2843 wined3d_mutex_lock();
2844
2845 if (!(ddraw->cooperative_level & (DDSCL_NORMAL | DDSCL_EXCLUSIVE)))
2846 {
2847 WARN("Cooperative level not set.\n");
2848 wined3d_mutex_unlock();
2849 return DDERR_NOCOOPERATIVELEVELSET;
2850 }
2851
2852 if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC2))
2853 {
2854 WARN("Application supplied invalid surface descriptor\n");
2855 wined3d_mutex_unlock();
2856 return DDERR_INVALIDPARAMS;
2857 }
2858
2859 __TRY
2860 {
2861 *surface = NULL;
2862 }
2863 __EXCEPT_PAGE_FAULT
2864 {
2865 WARN("Surface pointer %p is invalid.\n", surface);
2866 wined3d_mutex_unlock();
2867 return DDERR_INVALIDPARAMS;
2868 }
2869 __ENDTRY;
2870
2871 if(surface_desc->ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER))
2872 {
2873 if (TRACE_ON(ddraw))
2874 {
2875 TRACE(" (%p) Requesting surface desc :\n", iface);
2876 DDRAW_dump_surface_desc(surface_desc);
2877 }
2878
2879 WARN("Application tried to create an explicit front or back buffer\n");
2880 wined3d_mutex_unlock();
2881 return DDERR_INVALIDCAPS;
2882 }
2883
2884 hr = ddraw_surface_create(ddraw, surface_desc, &impl, outer_unknown, 7);
2885 wined3d_mutex_unlock();
2886 if (FAILED(hr))
2887 return hr;
2888
2889 *surface = &impl->IDirectDrawSurface7_iface;
2890 IDirectDraw7_AddRef(iface);
2891 impl->ifaceToRelease = (IUnknown *)iface;
2892
2893 return hr;
2894 }
2895
ddraw4_CreateSurface(IDirectDraw4 * iface,DDSURFACEDESC2 * surface_desc,IDirectDrawSurface4 ** surface,IUnknown * outer_unknown)2896 static HRESULT WINAPI ddraw4_CreateSurface(IDirectDraw4 *iface,
2897 DDSURFACEDESC2 *surface_desc, IDirectDrawSurface4 **surface, IUnknown *outer_unknown)
2898 {
2899 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2900 struct ddraw_surface *impl;
2901 HRESULT hr;
2902
2903 TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
2904 iface, surface_desc, surface, outer_unknown);
2905
2906 wined3d_mutex_lock();
2907
2908 if (!(ddraw->cooperative_level & (DDSCL_NORMAL | DDSCL_EXCLUSIVE)))
2909 {
2910 WARN("Cooperative level not set.\n");
2911 wined3d_mutex_unlock();
2912 return DDERR_NOCOOPERATIVELEVELSET;
2913 }
2914
2915 if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC2))
2916 {
2917 WARN("Application supplied invalid surface descriptor\n");
2918 wined3d_mutex_unlock();
2919 return DDERR_INVALIDPARAMS;
2920 }
2921
2922 __TRY
2923 {
2924 *surface = NULL;
2925 }
2926 __EXCEPT_PAGE_FAULT
2927 {
2928 WARN("Surface pointer %p is invalid.\n", surface);
2929 wined3d_mutex_unlock();
2930 return DDERR_INVALIDPARAMS;
2931 }
2932 __ENDTRY;
2933
2934 if(surface_desc->ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER))
2935 {
2936 if (TRACE_ON(ddraw))
2937 {
2938 TRACE(" (%p) Requesting surface desc :\n", iface);
2939 DDRAW_dump_surface_desc(surface_desc);
2940 }
2941
2942 WARN("Application tried to create an explicit front or back buffer\n");
2943 wined3d_mutex_unlock();
2944 return DDERR_INVALIDCAPS;
2945 }
2946
2947 hr = ddraw_surface_create(ddraw, surface_desc, &impl, outer_unknown, 4);
2948 wined3d_mutex_unlock();
2949 if (FAILED(hr))
2950 return hr;
2951
2952 *surface = &impl->IDirectDrawSurface4_iface;
2953 IDirectDraw4_AddRef(iface);
2954 impl->ifaceToRelease = (IUnknown *)iface;
2955
2956 return hr;
2957 }
2958
ddraw2_CreateSurface(IDirectDraw2 * iface,DDSURFACEDESC * surface_desc,IDirectDrawSurface ** surface,IUnknown * outer_unknown)2959 static HRESULT WINAPI ddraw2_CreateSurface(IDirectDraw2 *iface,
2960 DDSURFACEDESC *surface_desc, IDirectDrawSurface **surface, IUnknown *outer_unknown)
2961 {
2962 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2963 struct ddraw_surface *impl;
2964 HRESULT hr;
2965 DDSURFACEDESC2 surface_desc2;
2966
2967 TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
2968 iface, surface_desc, surface, outer_unknown);
2969
2970 wined3d_mutex_lock();
2971
2972 if (!(ddraw->cooperative_level & (DDSCL_NORMAL | DDSCL_EXCLUSIVE)))
2973 {
2974 WARN("Cooperative level not set.\n");
2975 wined3d_mutex_unlock();
2976 return DDERR_NOCOOPERATIVELEVELSET;
2977 }
2978
2979 if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC))
2980 {
2981 WARN("Application supplied invalid surface descriptor\n");
2982 wined3d_mutex_unlock();
2983 return DDERR_INVALIDPARAMS;
2984 }
2985
2986 __TRY
2987 {
2988 *surface = NULL;
2989 }
2990 __EXCEPT_PAGE_FAULT
2991 {
2992 WARN("Surface pointer %p is invalid.\n", surface);
2993 wined3d_mutex_unlock();
2994 return DDERR_INVALIDPARAMS;
2995 }
2996 __ENDTRY;
2997
2998 DDSD_to_DDSD2(surface_desc, &surface_desc2);
2999 if(surface_desc->ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER))
3000 {
3001 if (TRACE_ON(ddraw))
3002 {
3003 TRACE(" (%p) Requesting surface desc :\n", iface);
3004 DDRAW_dump_surface_desc((DDSURFACEDESC2 *)surface_desc);
3005 }
3006
3007 WARN("Application tried to create an explicit front or back buffer\n");
3008 wined3d_mutex_unlock();
3009 return DDERR_INVALIDCAPS;
3010 }
3011
3012 hr = ddraw_surface_create(ddraw, &surface_desc2, &impl, outer_unknown, 2);
3013 wined3d_mutex_unlock();
3014 if (FAILED(hr))
3015 return hr;
3016
3017 *surface = &impl->IDirectDrawSurface_iface;
3018 impl->ifaceToRelease = NULL;
3019
3020 return hr;
3021 }
3022
ddraw1_CreateSurface(IDirectDraw * iface,DDSURFACEDESC * surface_desc,IDirectDrawSurface ** surface,IUnknown * outer_unknown)3023 static HRESULT WINAPI ddraw1_CreateSurface(IDirectDraw *iface,
3024 DDSURFACEDESC *surface_desc, IDirectDrawSurface **surface, IUnknown *outer_unknown)
3025 {
3026 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
3027 struct ddraw_surface *impl;
3028 HRESULT hr;
3029 DDSURFACEDESC2 surface_desc2;
3030
3031 TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
3032 iface, surface_desc, surface, outer_unknown);
3033
3034 wined3d_mutex_lock();
3035
3036 if (!(ddraw->cooperative_level & (DDSCL_NORMAL | DDSCL_EXCLUSIVE)))
3037 {
3038 WARN("Cooperative level not set.\n");
3039 wined3d_mutex_unlock();
3040 return DDERR_NOCOOPERATIVELEVELSET;
3041 }
3042
3043 if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC))
3044 {
3045 WARN("Application supplied invalid surface descriptor\n");
3046 wined3d_mutex_unlock();
3047 return DDERR_INVALIDPARAMS;
3048 }
3049
3050 __TRY
3051 {
3052 *surface = NULL;
3053 }
3054 __EXCEPT_PAGE_FAULT
3055 {
3056 WARN("Surface pointer %p is invalid.\n", surface);
3057 wined3d_mutex_unlock();
3058 return DDERR_INVALIDPARAMS;
3059 }
3060 __ENDTRY;
3061
3062 if ((surface_desc->ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER))
3063 == (DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER)
3064 || (surface_desc->ddsCaps.dwCaps & (DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER))
3065 == ((DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER)))
3066 {
3067 WARN("Application tried to create an explicit front or back buffer.\n");
3068 wined3d_mutex_unlock();
3069 return DDERR_INVALIDCAPS;
3070 }
3071
3072 DDSD_to_DDSD2(surface_desc, &surface_desc2);
3073 hr = ddraw_surface_create(ddraw, &surface_desc2, &impl, outer_unknown, 1);
3074 wined3d_mutex_unlock();
3075 if (FAILED(hr))
3076 return hr;
3077
3078 *surface = &impl->IDirectDrawSurface_iface;
3079 impl->ifaceToRelease = NULL;
3080
3081 return hr;
3082 }
3083
3084 static BOOL
Main_DirectDraw_DDPIXELFORMAT_Match(const DDPIXELFORMAT * requested,const DDPIXELFORMAT * provided)3085 Main_DirectDraw_DDPIXELFORMAT_Match(const DDPIXELFORMAT *requested,
3086 const DDPIXELFORMAT *provided)
3087 {
3088 /* Some flags must be present in both or neither for a match. */
3089 static const DWORD must_match = DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2
3090 | DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_FOURCC
3091 | DDPF_ZBUFFER | DDPF_STENCILBUFFER;
3092
3093 if ((requested->dwFlags & provided->dwFlags) != requested->dwFlags)
3094 return FALSE;
3095
3096 if ((requested->dwFlags & must_match) != (provided->dwFlags & must_match))
3097 return FALSE;
3098
3099 if (requested->dwFlags & DDPF_FOURCC)
3100 if (requested->dwFourCC != provided->dwFourCC)
3101 return FALSE;
3102
3103 if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_ZBUFFER|DDPF_ALPHA
3104 |DDPF_LUMINANCE|DDPF_BUMPDUDV))
3105 if (requested->u1.dwRGBBitCount != provided->u1.dwRGBBitCount)
3106 return FALSE;
3107
3108 if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_STENCILBUFFER
3109 |DDPF_LUMINANCE|DDPF_BUMPDUDV))
3110 if (requested->u2.dwRBitMask != provided->u2.dwRBitMask)
3111 return FALSE;
3112
3113 if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_ZBUFFER|DDPF_BUMPDUDV))
3114 if (requested->u3.dwGBitMask != provided->u3.dwGBitMask)
3115 return FALSE;
3116
3117 /* I could be wrong about the bumpmapping. MSDN docs are vague. */
3118 if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_STENCILBUFFER
3119 |DDPF_BUMPDUDV))
3120 if (requested->u4.dwBBitMask != provided->u4.dwBBitMask)
3121 return FALSE;
3122
3123 if (requested->dwFlags & (DDPF_ALPHAPIXELS|DDPF_ZPIXELS))
3124 if (requested->u5.dwRGBAlphaBitMask != provided->u5.dwRGBAlphaBitMask)
3125 return FALSE;
3126
3127 return TRUE;
3128 }
3129
ddraw_match_surface_desc(const DDSURFACEDESC2 * requested,const DDSURFACEDESC2 * provided)3130 static BOOL ddraw_match_surface_desc(const DDSURFACEDESC2 *requested, const DDSURFACEDESC2 *provided)
3131 {
3132 struct compare_info
3133 {
3134 DWORD flag;
3135 ptrdiff_t offset;
3136 size_t size;
3137 };
3138
3139 #define CMP(FLAG, FIELD) \
3140 { DDSD_##FLAG, offsetof(DDSURFACEDESC2, FIELD), \
3141 sizeof(((DDSURFACEDESC2 *)(NULL))->FIELD) }
3142
3143 static const struct compare_info compare[] =
3144 {
3145 CMP(ALPHABITDEPTH, dwAlphaBitDepth),
3146 CMP(BACKBUFFERCOUNT, u5.dwBackBufferCount),
3147 CMP(CAPS, ddsCaps),
3148 CMP(CKDESTBLT, ddckCKDestBlt),
3149 CMP(CKDESTOVERLAY, u3 /* ddckCKDestOverlay */),
3150 CMP(CKSRCBLT, ddckCKSrcBlt),
3151 CMP(CKSRCOVERLAY, ddckCKSrcOverlay),
3152 CMP(HEIGHT, dwHeight),
3153 CMP(LINEARSIZE, u1 /* dwLinearSize */),
3154 CMP(LPSURFACE, lpSurface),
3155 CMP(MIPMAPCOUNT, u2 /* dwMipMapCount */),
3156 CMP(PITCH, u1 /* lPitch */),
3157 /* PIXELFORMAT: manual */
3158 CMP(REFRESHRATE, u2 /* dwRefreshRate */),
3159 CMP(TEXTURESTAGE, dwTextureStage),
3160 CMP(WIDTH, dwWidth),
3161 /* ZBUFFERBITDEPTH: "obsolete" */
3162 };
3163
3164 #undef CMP
3165
3166 unsigned int i;
3167
3168 if ((requested->dwFlags & provided->dwFlags) != requested->dwFlags)
3169 return FALSE;
3170
3171 for (i=0; i < ARRAY_SIZE(compare); i++)
3172 {
3173 if (requested->dwFlags & compare[i].flag
3174 && memcmp((const char *)provided + compare[i].offset,
3175 (const char *)requested + compare[i].offset,
3176 compare[i].size) != 0)
3177 return FALSE;
3178 }
3179
3180 if (requested->dwFlags & DDSD_PIXELFORMAT)
3181 {
3182 if (!Main_DirectDraw_DDPIXELFORMAT_Match(&requested->u4.ddpfPixelFormat,
3183 &provided->u4.ddpfPixelFormat))
3184 return FALSE;
3185 }
3186
3187 return TRUE;
3188 }
3189
3190 struct surfacescallback2_context
3191 {
3192 LPDDENUMSURFACESCALLBACK2 func;
3193 void *context;
3194 };
3195
3196 struct surfacescallback_context
3197 {
3198 LPDDENUMSURFACESCALLBACK func;
3199 void *context;
3200 };
3201
EnumSurfacesCallback2Thunk(IDirectDrawSurface7 * surface,DDSURFACEDESC2 * surface_desc,void * context)3202 static HRESULT CALLBACK EnumSurfacesCallback2Thunk(IDirectDrawSurface7 *surface,
3203 DDSURFACEDESC2 *surface_desc, void *context)
3204 {
3205 struct ddraw_surface *surface_impl = impl_from_IDirectDrawSurface7(surface);
3206 struct surfacescallback2_context *cbcontext = context;
3207
3208 IDirectDrawSurface4_AddRef(&surface_impl->IDirectDrawSurface4_iface);
3209 IDirectDrawSurface7_Release(surface);
3210
3211 return cbcontext->func(&surface_impl->IDirectDrawSurface4_iface,
3212 surface_desc, cbcontext->context);
3213 }
3214
EnumSurfacesCallbackThunk(IDirectDrawSurface7 * surface,DDSURFACEDESC2 * surface_desc,void * context)3215 static HRESULT CALLBACK EnumSurfacesCallbackThunk(IDirectDrawSurface7 *surface,
3216 DDSURFACEDESC2 *surface_desc, void *context)
3217 {
3218 struct ddraw_surface *surface_impl = impl_from_IDirectDrawSurface7(surface);
3219 struct surfacescallback_context *cbcontext = context;
3220
3221 IDirectDrawSurface_AddRef(&surface_impl->IDirectDrawSurface_iface);
3222 IDirectDrawSurface7_Release(surface);
3223
3224 return cbcontext->func(&surface_impl->IDirectDrawSurface_iface,
3225 (DDSURFACEDESC *)surface_desc, cbcontext->context);
3226 }
3227
3228 /*****************************************************************************
3229 * IDirectDraw7::EnumSurfaces
3230 *
3231 * Loops through all surfaces attached to this device and calls the
3232 * application callback. This can't be relayed to WineD3DDevice,
3233 * because some WineD3DSurfaces' parents are IParent objects
3234 *
3235 * Params:
3236 * Flags: Some filtering flags. See IDirectDrawImpl_EnumSurfacesCallback
3237 * DDSD: Description to filter for
3238 * Context: Application-provided pointer, it's passed unmodified to the
3239 * Callback function
3240 * Callback: Address to call for each surface
3241 *
3242 * Returns:
3243 * DDERR_INVALIDPARAMS if the callback is NULL
3244 * DD_OK on success
3245 *
3246 *****************************************************************************/
ddraw7_EnumSurfaces(IDirectDraw7 * iface,DWORD Flags,DDSURFACEDESC2 * DDSD,void * Context,LPDDENUMSURFACESCALLBACK7 Callback)3247 static HRESULT WINAPI ddraw7_EnumSurfaces(IDirectDraw7 *iface, DWORD Flags,
3248 DDSURFACEDESC2 *DDSD, void *Context, LPDDENUMSURFACESCALLBACK7 Callback)
3249 {
3250 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
3251 struct ddraw_surface *surf;
3252 DWORD match_flags = Flags & (DDENUMSURFACES_ALL | DDENUMSURFACES_NOMATCH | DDENUMSURFACES_MATCH);
3253
3254 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3255 iface, Flags, DDSD, Context, Callback);
3256
3257 if (!Callback)
3258 return DDERR_INVALIDPARAMS;
3259
3260 if (Flags & DDENUMSURFACES_CANBECREATED)
3261 {
3262 IDirectDrawSurface7 *surface;
3263 DDSURFACEDESC2 testdesc;
3264 HRESULT hr;
3265
3266 if (match_flags != DDENUMSURFACES_MATCH)
3267 return DDERR_INVALIDPARAMS;
3268
3269 if (!DDSD)
3270 return DDERR_INVALIDPARAMS;
3271
3272 memcpy(&testdesc, DDSD, sizeof(testdesc));
3273 if (!(testdesc.dwFlags & DDSD_WIDTH))
3274 {
3275 testdesc.dwFlags |= DDSD_WIDTH;
3276 testdesc.dwWidth = 512;
3277 }
3278 if (!(testdesc.dwFlags & DDSD_HEIGHT))
3279 {
3280 testdesc.dwFlags |= DDSD_HEIGHT;
3281 testdesc.dwHeight = 512;
3282 }
3283
3284 hr = IDirectDraw7_CreateSurface(iface, &testdesc, &surface, NULL);
3285 if (SUCCEEDED(hr))
3286 {
3287 surf = unsafe_impl_from_IDirectDrawSurface7(surface);
3288 Callback(NULL, &surf->surface_desc, Context);
3289 IDirectDrawSurface7_Release(surface);
3290 }
3291 else
3292 ERR("Failed to create surface, hr %#x.\n", hr);
3293 }
3294 else if (Flags & DDENUMSURFACES_DOESEXIST)
3295 {
3296 BOOL all, nomatch;
3297 DDSURFACEDESC2 desc;
3298 struct list *entry, *entry2;
3299
3300 /* a combination of match flags is not allowed */
3301 if (match_flags != 0 &&
3302 match_flags != DDENUMSURFACES_ALL &&
3303 match_flags != DDENUMSURFACES_MATCH &&
3304 match_flags != DDENUMSURFACES_NOMATCH)
3305 return DDERR_INVALIDPARAMS;
3306
3307 all = (Flags & DDENUMSURFACES_ALL) != 0;
3308 nomatch = (Flags & DDENUMSURFACES_NOMATCH) != 0;
3309
3310 if (!all && !DDSD)
3311 return DDERR_INVALIDPARAMS;
3312
3313 wined3d_mutex_lock();
3314
3315 /* Use the _SAFE enumeration, the app may destroy enumerated surfaces */
3316 LIST_FOR_EACH_SAFE(entry, entry2, &ddraw->surface_list)
3317 {
3318 surf = LIST_ENTRY(entry, struct ddraw_surface, surface_list_entry);
3319
3320 if (!surf->iface_count)
3321 {
3322 WARN("Not enumerating surface %p because it doesn't have any references.\n", surf);
3323 continue;
3324 }
3325
3326 if (all || (nomatch != ddraw_match_surface_desc(DDSD, &surf->surface_desc)))
3327 {
3328 TRACE("Enumerating surface %p.\n", surf);
3329 desc = surf->surface_desc;
3330 IDirectDrawSurface7_AddRef(&surf->IDirectDrawSurface7_iface);
3331 if (Callback(&surf->IDirectDrawSurface7_iface, &desc, Context) != DDENUMRET_OK)
3332 {
3333 wined3d_mutex_unlock();
3334 return DD_OK;
3335 }
3336 }
3337 }
3338
3339 wined3d_mutex_unlock();
3340 }
3341 else
3342 return DDERR_INVALIDPARAMS;
3343
3344 return DD_OK;
3345 }
3346
ddraw4_EnumSurfaces(IDirectDraw4 * iface,DWORD flags,DDSURFACEDESC2 * surface_desc,void * context,LPDDENUMSURFACESCALLBACK2 callback)3347 static HRESULT WINAPI ddraw4_EnumSurfaces(IDirectDraw4 *iface, DWORD flags,
3348 DDSURFACEDESC2 *surface_desc, void *context, LPDDENUMSURFACESCALLBACK2 callback)
3349 {
3350 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
3351 struct surfacescallback2_context cbcontext;
3352
3353 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3354 iface, flags, surface_desc, context, callback);
3355
3356 cbcontext.func = callback;
3357 cbcontext.context = context;
3358
3359 return ddraw7_EnumSurfaces(&ddraw->IDirectDraw7_iface, flags, surface_desc,
3360 &cbcontext, EnumSurfacesCallback2Thunk);
3361 }
3362
ddraw2_EnumSurfaces(IDirectDraw2 * iface,DWORD flags,DDSURFACEDESC * surface_desc,void * context,LPDDENUMSURFACESCALLBACK callback)3363 static HRESULT WINAPI ddraw2_EnumSurfaces(IDirectDraw2 *iface, DWORD flags,
3364 DDSURFACEDESC *surface_desc, void *context, LPDDENUMSURFACESCALLBACK callback)
3365 {
3366 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
3367 struct surfacescallback_context cbcontext;
3368 DDSURFACEDESC2 surface_desc2;
3369
3370 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3371 iface, flags, surface_desc, context, callback);
3372
3373 cbcontext.func = callback;
3374 cbcontext.context = context;
3375
3376 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
3377 return ddraw7_EnumSurfaces(&ddraw->IDirectDraw7_iface, flags,
3378 surface_desc ? &surface_desc2 : NULL, &cbcontext, EnumSurfacesCallbackThunk);
3379 }
3380
ddraw1_EnumSurfaces(IDirectDraw * iface,DWORD flags,DDSURFACEDESC * surface_desc,void * context,LPDDENUMSURFACESCALLBACK callback)3381 static HRESULT WINAPI ddraw1_EnumSurfaces(IDirectDraw *iface, DWORD flags,
3382 DDSURFACEDESC *surface_desc, void *context, LPDDENUMSURFACESCALLBACK callback)
3383 {
3384 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
3385 struct surfacescallback_context cbcontext;
3386 DDSURFACEDESC2 surface_desc2;
3387
3388 TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3389 iface, flags, surface_desc, context, callback);
3390
3391 cbcontext.func = callback;
3392 cbcontext.context = context;
3393
3394 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
3395 return ddraw7_EnumSurfaces(&ddraw->IDirectDraw7_iface, flags,
3396 surface_desc ? &surface_desc2 : NULL, &cbcontext, EnumSurfacesCallbackThunk);
3397 }
3398
3399 /*****************************************************************************
3400 * DirectDrawCreateClipper (DDRAW.@)
3401 *
3402 * Creates a new IDirectDrawClipper object.
3403 *
3404 * Params:
3405 * Clipper: Address to write the interface pointer to
3406 * UnkOuter: For aggregation support, which ddraw doesn't have. Has to be
3407 * NULL
3408 *
3409 * Returns:
3410 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
3411 * E_OUTOFMEMORY if allocating the object failed
3412 *
3413 *****************************************************************************/
DirectDrawCreateClipper(DWORD flags,IDirectDrawClipper ** clipper,IUnknown * outer_unknown)3414 HRESULT WINAPI DirectDrawCreateClipper(DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3415 {
3416 struct ddraw_clipper *object;
3417 HRESULT hr;
3418
3419 TRACE("flags %#x, clipper %p, outer_unknown %p.\n",
3420 flags, clipper, outer_unknown);
3421
3422 if (outer_unknown)
3423 return CLASS_E_NOAGGREGATION;
3424
3425 wined3d_mutex_lock();
3426
3427 if (!(object = heap_alloc_zero(sizeof(*object))))
3428 {
3429 wined3d_mutex_unlock();
3430 return E_OUTOFMEMORY;
3431 }
3432
3433 hr = ddraw_clipper_init(object);
3434 if (FAILED(hr))
3435 {
3436 WARN("Failed to initialize clipper, hr %#x.\n", hr);
3437 heap_free(object);
3438 wined3d_mutex_unlock();
3439 return hr;
3440 }
3441
3442 TRACE("Created clipper %p.\n", object);
3443 *clipper = &object->IDirectDrawClipper_iface;
3444 wined3d_mutex_unlock();
3445
3446 return DD_OK;
3447 }
3448
3449 /*****************************************************************************
3450 * IDirectDraw7::CreateClipper
3451 *
3452 * Creates a DDraw clipper. See DirectDrawCreateClipper for details
3453 *
3454 *****************************************************************************/
ddraw7_CreateClipper(IDirectDraw7 * iface,DWORD Flags,IDirectDrawClipper ** Clipper,IUnknown * UnkOuter)3455 static HRESULT WINAPI ddraw7_CreateClipper(IDirectDraw7 *iface, DWORD Flags,
3456 IDirectDrawClipper **Clipper, IUnknown *UnkOuter)
3457 {
3458 TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3459 iface, Flags, Clipper, UnkOuter);
3460
3461 return DirectDrawCreateClipper(Flags, Clipper, UnkOuter);
3462 }
3463
ddraw4_CreateClipper(IDirectDraw4 * iface,DWORD flags,IDirectDrawClipper ** clipper,IUnknown * outer_unknown)3464 static HRESULT WINAPI ddraw4_CreateClipper(IDirectDraw4 *iface, DWORD flags,
3465 IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3466 {
3467 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
3468
3469 TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3470 iface, flags, clipper, outer_unknown);
3471
3472 return ddraw7_CreateClipper(&ddraw->IDirectDraw7_iface, flags, clipper, outer_unknown);
3473 }
3474
ddraw2_CreateClipper(IDirectDraw2 * iface,DWORD flags,IDirectDrawClipper ** clipper,IUnknown * outer_unknown)3475 static HRESULT WINAPI ddraw2_CreateClipper(IDirectDraw2 *iface,
3476 DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3477 {
3478 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
3479
3480 TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3481 iface, flags, clipper, outer_unknown);
3482
3483 return ddraw7_CreateClipper(&ddraw->IDirectDraw7_iface, flags, clipper, outer_unknown);
3484 }
3485
ddraw1_CreateClipper(IDirectDraw * iface,DWORD flags,IDirectDrawClipper ** clipper,IUnknown * outer_unknown)3486 static HRESULT WINAPI ddraw1_CreateClipper(IDirectDraw *iface,
3487 DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3488 {
3489 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
3490
3491 TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3492 iface, flags, clipper, outer_unknown);
3493
3494 return ddraw7_CreateClipper(&ddraw->IDirectDraw7_iface, flags, clipper, outer_unknown);
3495 }
3496
3497 /*****************************************************************************
3498 * IDirectDraw7::CreatePalette
3499 *
3500 * Creates a new IDirectDrawPalette object
3501 *
3502 * Params:
3503 * Flags: The flags for the new clipper
3504 * ColorTable: Color table to assign to the new clipper
3505 * Palette: Address to write the interface pointer to
3506 * UnkOuter: For aggregation support, which ddraw doesn't have. Has to be
3507 * NULL
3508 *
3509 * Returns:
3510 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
3511 * E_OUTOFMEMORY if allocating the object failed
3512 *
3513 *****************************************************************************/
ddraw7_CreatePalette(IDirectDraw7 * iface,DWORD Flags,PALETTEENTRY * ColorTable,IDirectDrawPalette ** Palette,IUnknown * pUnkOuter)3514 static HRESULT WINAPI ddraw7_CreatePalette(IDirectDraw7 *iface, DWORD Flags,
3515 PALETTEENTRY *ColorTable, IDirectDrawPalette **Palette, IUnknown *pUnkOuter)
3516 {
3517 struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
3518 struct ddraw_palette *object;
3519 HRESULT hr;
3520
3521 TRACE("iface %p, flags %#x, color_table %p, palette %p, outer_unknown %p.\n",
3522 iface, Flags, ColorTable, Palette, pUnkOuter);
3523
3524 if (pUnkOuter)
3525 return CLASS_E_NOAGGREGATION;
3526
3527 wined3d_mutex_lock();
3528
3529 /* The refcount test shows that a cooplevel is required for this */
3530 if (!ddraw->cooperative_level)
3531 {
3532 WARN("No cooperative level set, returning DDERR_NOCOOPERATIVELEVELSET\n");
3533 wined3d_mutex_unlock();
3534 return DDERR_NOCOOPERATIVELEVELSET;
3535 }
3536
3537 if (!(object = heap_alloc(sizeof(*object))))
3538 {
3539 ERR("Out of memory when allocating memory for a palette implementation\n");
3540 wined3d_mutex_unlock();
3541 return E_OUTOFMEMORY;
3542 }
3543
3544 hr = ddraw_palette_init(object, ddraw, Flags, ColorTable);
3545 if (FAILED(hr))
3546 {
3547 WARN("Failed to initialize palette, hr %#x.\n", hr);
3548 heap_free(object);
3549 wined3d_mutex_unlock();
3550 return hr;
3551 }
3552
3553 TRACE("Created palette %p.\n", object);
3554 *Palette = &object->IDirectDrawPalette_iface;
3555 wined3d_mutex_unlock();
3556
3557 return DD_OK;
3558 }
3559
ddraw4_CreatePalette(IDirectDraw4 * iface,DWORD flags,PALETTEENTRY * entries,IDirectDrawPalette ** palette,IUnknown * outer_unknown)3560 static HRESULT WINAPI ddraw4_CreatePalette(IDirectDraw4 *iface, DWORD flags, PALETTEENTRY *entries,
3561 IDirectDrawPalette **palette, IUnknown *outer_unknown)
3562 {
3563 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
3564 HRESULT hr;
3565
3566 TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n",
3567 iface, flags, entries, palette, outer_unknown);
3568
3569 hr = ddraw7_CreatePalette(&ddraw->IDirectDraw7_iface, flags, entries, palette, outer_unknown);
3570 if (SUCCEEDED(hr) && *palette)
3571 {
3572 struct ddraw_palette *impl = impl_from_IDirectDrawPalette(*palette);
3573 IDirectDraw7_Release(&ddraw->IDirectDraw7_iface);
3574 IDirectDraw4_AddRef(iface);
3575 impl->ifaceToRelease = (IUnknown *)iface;
3576 }
3577 return hr;
3578 }
3579
ddraw2_CreatePalette(IDirectDraw2 * iface,DWORD flags,PALETTEENTRY * entries,IDirectDrawPalette ** palette,IUnknown * outer_unknown)3580 static HRESULT WINAPI ddraw2_CreatePalette(IDirectDraw2 *iface, DWORD flags,
3581 PALETTEENTRY *entries, IDirectDrawPalette **palette, IUnknown *outer_unknown)
3582 {
3583 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
3584 HRESULT hr;
3585
3586 TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n",
3587 iface, flags, entries, palette, outer_unknown);
3588
3589 hr = ddraw7_CreatePalette(&ddraw->IDirectDraw7_iface, flags, entries, palette, outer_unknown);
3590 if (SUCCEEDED(hr) && *palette)
3591 {
3592 struct ddraw_palette *impl = impl_from_IDirectDrawPalette(*palette);
3593 IDirectDraw7_Release(&ddraw->IDirectDraw7_iface);
3594 impl->ifaceToRelease = NULL;
3595 }
3596
3597 return hr;
3598 }
3599
ddraw1_CreatePalette(IDirectDraw * iface,DWORD flags,PALETTEENTRY * entries,IDirectDrawPalette ** palette,IUnknown * outer_unknown)3600 static HRESULT WINAPI ddraw1_CreatePalette(IDirectDraw *iface, DWORD flags,
3601 PALETTEENTRY *entries, IDirectDrawPalette **palette, IUnknown *outer_unknown)
3602 {
3603 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
3604 HRESULT hr;
3605
3606 TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n",
3607 iface, flags, entries, palette, outer_unknown);
3608
3609 hr = ddraw7_CreatePalette(&ddraw->IDirectDraw7_iface, flags, entries, palette, outer_unknown);
3610 if (SUCCEEDED(hr) && *palette)
3611 {
3612 struct ddraw_palette *impl = impl_from_IDirectDrawPalette(*palette);
3613 IDirectDraw7_Release(&ddraw->IDirectDraw7_iface);
3614 impl->ifaceToRelease = NULL;
3615 }
3616
3617 return hr;
3618 }
3619
3620 /*****************************************************************************
3621 * IDirectDraw7::DuplicateSurface
3622 *
3623 * Duplicates a surface. The surface memory points to the same memory as
3624 * the original surface, and it's released when the last surface referencing
3625 * it is released. I guess that's beyond Wine's surface management right now
3626 * (Idea: create a new DDraw surface with the same WineD3DSurface. I need a
3627 * test application to implement this)
3628 *
3629 * Params:
3630 * Src: Address of the source surface
3631 * Dest: Address to write the new surface pointer to
3632 *
3633 * Returns:
3634 * See IDirectDraw7::CreateSurface
3635 *
3636 *****************************************************************************/
ddraw7_DuplicateSurface(IDirectDraw7 * iface,IDirectDrawSurface7 * Src,IDirectDrawSurface7 ** Dest)3637 static HRESULT WINAPI ddraw7_DuplicateSurface(IDirectDraw7 *iface,
3638 IDirectDrawSurface7 *Src, IDirectDrawSurface7 **Dest)
3639 {
3640 struct ddraw_surface *src_surface = unsafe_impl_from_IDirectDrawSurface7(Src);
3641
3642 FIXME("iface %p, src %p, dst %p partial stub!\n", iface, Src, Dest);
3643
3644 /* For now, simply create a new, independent surface */
3645 return IDirectDraw7_CreateSurface(iface, &src_surface->surface_desc, Dest, NULL);
3646 }
3647
ddraw4_DuplicateSurface(IDirectDraw4 * iface,IDirectDrawSurface4 * src,IDirectDrawSurface4 ** dst)3648 static HRESULT WINAPI ddraw4_DuplicateSurface(IDirectDraw4 *iface, IDirectDrawSurface4 *src,
3649 IDirectDrawSurface4 **dst)
3650 {
3651 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface4(src);
3652 struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
3653 struct ddraw_surface *dst_impl;
3654 IDirectDrawSurface7 *dst7;
3655 HRESULT hr;
3656
3657 TRACE("iface %p, src %p, dst %p.\n", iface, src, dst);
3658
3659 hr = ddraw7_DuplicateSurface(&ddraw->IDirectDraw7_iface,
3660 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, &dst7);
3661 if (FAILED(hr))
3662 {
3663 *dst = NULL;
3664 return hr;
3665 }
3666 dst_impl = impl_from_IDirectDrawSurface7(dst7);
3667 *dst = &dst_impl->IDirectDrawSurface4_iface;
3668 IDirectDrawSurface4_AddRef(*dst);
3669 IDirectDrawSurface7_Release(dst7);
3670
3671 return hr;
3672 }
3673
ddraw2_DuplicateSurface(IDirectDraw2 * iface,IDirectDrawSurface * src,IDirectDrawSurface ** dst)3674 static HRESULT WINAPI ddraw2_DuplicateSurface(IDirectDraw2 *iface,
3675 IDirectDrawSurface *src, IDirectDrawSurface **dst)
3676 {
3677 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface(src);
3678 struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
3679 struct ddraw_surface *dst_impl;
3680 IDirectDrawSurface7 *dst7;
3681 HRESULT hr;
3682
3683 TRACE("iface %p, src %p, dst %p.\n", iface, src, dst);
3684
3685 hr = ddraw7_DuplicateSurface(&ddraw->IDirectDraw7_iface,
3686 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, &dst7);
3687 if (FAILED(hr))
3688 return hr;
3689 dst_impl = impl_from_IDirectDrawSurface7(dst7);
3690 *dst = &dst_impl->IDirectDrawSurface_iface;
3691 IDirectDrawSurface_AddRef(*dst);
3692 IDirectDrawSurface7_Release(dst7);
3693
3694 return hr;
3695 }
3696
ddraw1_DuplicateSurface(IDirectDraw * iface,IDirectDrawSurface * src,IDirectDrawSurface ** dst)3697 static HRESULT WINAPI ddraw1_DuplicateSurface(IDirectDraw *iface, IDirectDrawSurface *src,
3698 IDirectDrawSurface **dst)
3699 {
3700 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface(src);
3701 struct ddraw *ddraw = impl_from_IDirectDraw(iface);
3702 struct ddraw_surface *dst_impl;
3703 IDirectDrawSurface7 *dst7;
3704 HRESULT hr;
3705
3706 TRACE("iface %p, src %p, dst %p.\n", iface, src, dst);
3707
3708 hr = ddraw7_DuplicateSurface(&ddraw->IDirectDraw7_iface,
3709 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, &dst7);
3710 if (FAILED(hr))
3711 return hr;
3712 dst_impl = impl_from_IDirectDrawSurface7(dst7);
3713 *dst = &dst_impl->IDirectDrawSurface_iface;
3714 IDirectDrawSurface_AddRef(*dst);
3715 IDirectDrawSurface7_Release(dst7);
3716
3717 return hr;
3718 }
3719
3720 /*****************************************************************************
3721 * IDirect3D7::EnumDevices
3722 *
3723 * The EnumDevices method for IDirect3D7. It enumerates all supported
3724 * D3D7 devices. Currently the T&L, HAL and RGB devices are enumerated.
3725 *
3726 * Params:
3727 * callback: Function to call for each enumerated device
3728 * context: Pointer to pass back to the app
3729 *
3730 * Returns:
3731 * D3D_OK, or the return value of the GetCaps call
3732 *
3733 *****************************************************************************/
d3d7_EnumDevices(IDirect3D7 * iface,LPD3DENUMDEVICESCALLBACK7 callback,void * context)3734 static HRESULT WINAPI d3d7_EnumDevices(IDirect3D7 *iface, LPD3DENUMDEVICESCALLBACK7 callback, void *context)
3735 {
3736 struct ddraw *ddraw = impl_from_IDirect3D7(iface);
3737 D3DDEVICEDESC7 device_desc7;
3738 DWORD dev_caps;
3739 HRESULT hr;
3740 size_t i;
3741
3742 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
3743
3744 if (!callback)
3745 return DDERR_INVALIDPARAMS;
3746
3747 wined3d_mutex_lock();
3748
3749 if (FAILED(hr = ddraw_get_d3dcaps(ddraw, &device_desc7)))
3750 {
3751 wined3d_mutex_unlock();
3752 return hr;
3753 }
3754
3755 dev_caps = device_desc7.dwDevCaps;
3756
3757 for (i = 0; i < ARRAY_SIZE(device_list7); i++)
3758 {
3759 HRESULT ret;
3760
3761 device_desc7.deviceGUID = *device_list7[i].device_guid;
3762 device_desc7.dwDevCaps = dev_caps & ~device_list7[i].remove_caps;
3763
3764 ret = callback(device_list7[i].interface_name, device_list7[i].device_name, &device_desc7, context);
3765 if (ret != DDENUMRET_OK)
3766 {
3767 TRACE("Application cancelled the enumeration.\n");
3768 wined3d_mutex_unlock();
3769 return D3D_OK;
3770 }
3771 }
3772
3773 TRACE("End of enumeration.\n");
3774
3775 wined3d_mutex_unlock();
3776
3777 return D3D_OK;
3778 }
3779
3780 /*****************************************************************************
3781 * IDirect3D3::EnumDevices
3782 *
3783 * Enumerates all supported Direct3DDevice interfaces. This is the
3784 * implementation for Direct3D 1 to Direc3D 3, Version 7 has its own.
3785 *
3786 * Versions 1, 2 and 3
3787 *
3788 * Params:
3789 * callback: Application-provided routine to call for each enumerated device
3790 * Context: Pointer to pass to the callback
3791 *
3792 * Returns:
3793 * D3D_OK on success,
3794 * The result of IDirect3DImpl_GetCaps if it failed
3795 *
3796 *****************************************************************************/
d3d3_EnumDevices(IDirect3D3 * iface,LPD3DENUMDEVICESCALLBACK callback,void * context)3797 static HRESULT WINAPI d3d3_EnumDevices(IDirect3D3 *iface, LPD3DENUMDEVICESCALLBACK callback, void *context)
3798 {
3799 static CHAR wined3d_description[] = "Wine D3DDevice using WineD3D and OpenGL";
3800
3801 struct ddraw *ddraw = impl_from_IDirect3D3(iface);
3802 D3DDEVICEDESC device_desc1, hal_desc, hel_desc;
3803 D3DDEVICEDESC7 device_desc7;
3804 HRESULT hr;
3805
3806 /* Some games (Motoracer 2 demo) have the bad idea to modify the device
3807 * name string. Let's put the string in a sufficiently sized array in
3808 * writable memory. */
3809 char device_name[50];
3810 strcpy(device_name,"Direct3D HEL");
3811
3812 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
3813
3814 if (!callback)
3815 return DDERR_INVALIDPARAMS;
3816
3817 wined3d_mutex_lock();
3818
3819 if (FAILED(hr = ddraw_get_d3dcaps(ddraw, &device_desc7)))
3820 {
3821 wined3d_mutex_unlock();
3822 return hr;
3823 }
3824 ddraw_d3dcaps1_from_7(&device_desc1, &device_desc7);
3825
3826 /* Do I have to enumerate the reference id? Note from old d3d7:
3827 * "It seems that enumerating the reference IID on Direct3D 1 games
3828 * (AvP / Motoracer2) breaks them". So do not enumerate this iid in V1
3829 *
3830 * There's a registry key HKLM\Software\Microsoft\Direct3D\Drivers,
3831 * EnumReference which enables / disables enumerating the reference
3832 * rasterizer. It's a DWORD, 0 means disabled, 2 means enabled. The
3833 * enablerefrast.reg and disablerefrast.reg files in the DirectX 7.0 sdk
3834 * demo directory suggest this.
3835 *
3836 * Some games(GTA 2) seem to use the second enumerated device, so I have
3837 * to enumerate at least 2 devices. So enumerate the reference device to
3838 * have 2 devices.
3839 *
3840 * Other games (Rollcage) tell emulation and hal device apart by certain
3841 * flags. Rollcage expects D3DPTEXTURECAPS_POW2 to be set (yeah, it is a
3842 * limitation flag), and it refuses all devices that have the perspective
3843 * flag set. This way it refuses the emulation device, and HAL devices
3844 * never have POW2 unset in d3d7 on windows. */
3845 if (ddraw->d3dversion != 1)
3846 {
3847 static CHAR reference_description[] = "RGB Direct3D emulation";
3848
3849 TRACE("Enumerating WineD3D D3DDevice interface.\n");
3850 hal_desc = device_desc1;
3851 hel_desc = device_desc1;
3852 /* The rgb device has the pow2 flag set in the hel caps, but not in the hal caps. */
3853 hal_desc.dpcLineCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2
3854 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE);
3855 hal_desc.dpcTriCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2
3856 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE);
3857 /* RGB, RAMP and MMX devices have a HAL dcmColorModel of 0 */
3858 hal_desc.dcmColorModel = 0;
3859 /* RGB, RAMP and MMX devices cannot report HAL hardware flags */
3860 hal_desc.dwFlags = 0;
3861
3862 hr = callback((GUID *)&IID_IDirect3DRGBDevice, reference_description,
3863 device_name, &hal_desc, &hel_desc, context);
3864 if (hr != D3DENUMRET_OK)
3865 {
3866 TRACE("Application cancelled the enumeration.\n");
3867 wined3d_mutex_unlock();
3868 return D3D_OK;
3869 }
3870 }
3871
3872 strcpy(device_name,"Direct3D HAL");
3873
3874 TRACE("Enumerating HAL Direct3D device.\n");
3875 hal_desc = device_desc1;
3876 hel_desc = device_desc1;
3877
3878 /* The hal device does not have the pow2 flag set in hel, but in hal. */
3879 hel_desc.dpcLineCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2
3880 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE);
3881 hel_desc.dpcTriCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2
3882 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE);
3883 /* HAL devices have a HEL dcmColorModel of 0 */
3884 hel_desc.dcmColorModel = 0;
3885
3886 hr = callback((GUID *)&IID_IDirect3DHALDevice, wined3d_description,
3887 device_name, &hal_desc, &hel_desc, context);
3888 if (hr != D3DENUMRET_OK)
3889 {
3890 TRACE("Application cancelled the enumeration.\n");
3891 wined3d_mutex_unlock();
3892 return D3D_OK;
3893 }
3894
3895 TRACE("End of enumeration.\n");
3896
3897 wined3d_mutex_unlock();
3898
3899 return D3D_OK;
3900 }
3901
d3d2_EnumDevices(IDirect3D2 * iface,LPD3DENUMDEVICESCALLBACK callback,void * context)3902 static HRESULT WINAPI d3d2_EnumDevices(IDirect3D2 *iface, LPD3DENUMDEVICESCALLBACK callback, void *context)
3903 {
3904 struct ddraw *ddraw = impl_from_IDirect3D2(iface);
3905
3906 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
3907
3908 return d3d3_EnumDevices(&ddraw->IDirect3D3_iface, callback, context);
3909 }
3910
d3d1_EnumDevices(IDirect3D * iface,LPD3DENUMDEVICESCALLBACK callback,void * context)3911 static HRESULT WINAPI d3d1_EnumDevices(IDirect3D *iface, LPD3DENUMDEVICESCALLBACK callback, void *context)
3912 {
3913 struct ddraw *ddraw = impl_from_IDirect3D(iface);
3914
3915 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
3916
3917 return d3d3_EnumDevices(&ddraw->IDirect3D3_iface, callback, context);
3918 }
3919
3920 /*****************************************************************************
3921 * IDirect3D3::CreateLight
3922 *
3923 * Creates an IDirect3DLight interface. This interface is used in
3924 * Direct3D3 or earlier for lighting. In Direct3D7 it has been replaced
3925 * by the DIRECT3DLIGHT7 structure. Wine's Direct3DLight implementation
3926 * uses the IDirect3DDevice7 interface with D3D7 lights.
3927 *
3928 * Versions 1, 2 and 3
3929 *
3930 * Params:
3931 * light: Address to store the new interface pointer
3932 * outer_unknown: Basically for aggregation, but ddraw doesn't support it.
3933 * Must be NULL
3934 *
3935 * Returns:
3936 * D3D_OK on success
3937 * DDERR_OUTOFMEMORY if memory allocation failed
3938 * CLASS_E_NOAGGREGATION if outer_unknown != NULL
3939 *
3940 *****************************************************************************/
d3d3_CreateLight(IDirect3D3 * iface,IDirect3DLight ** light,IUnknown * outer_unknown)3941 static HRESULT WINAPI d3d3_CreateLight(IDirect3D3 *iface, IDirect3DLight **light,
3942 IUnknown *outer_unknown)
3943 {
3944 struct ddraw *ddraw = impl_from_IDirect3D3(iface);
3945 struct d3d_light *object;
3946
3947 TRACE("iface %p, light %p, outer_unknown %p.\n", iface, light, outer_unknown);
3948
3949 if (outer_unknown)
3950 return CLASS_E_NOAGGREGATION;
3951
3952 if (!(object = heap_alloc_zero(sizeof(*object))))
3953 {
3954 ERR("Failed to allocate light memory.\n");
3955 return DDERR_OUTOFMEMORY;
3956 }
3957
3958 d3d_light_init(object, ddraw);
3959
3960 TRACE("Created light %p.\n", object);
3961 *light = &object->IDirect3DLight_iface;
3962
3963 return D3D_OK;
3964 }
3965
d3d2_CreateLight(IDirect3D2 * iface,IDirect3DLight ** light,IUnknown * outer_unknown)3966 static HRESULT WINAPI d3d2_CreateLight(IDirect3D2 *iface, IDirect3DLight **light, IUnknown *outer_unknown)
3967 {
3968 struct ddraw *ddraw = impl_from_IDirect3D2(iface);
3969
3970 TRACE("iface %p, light %p, outer_unknown %p.\n", iface, light, outer_unknown);
3971
3972 return d3d3_CreateLight(&ddraw->IDirect3D3_iface, light, outer_unknown);
3973 }
3974
d3d1_CreateLight(IDirect3D * iface,IDirect3DLight ** light,IUnknown * outer_unknown)3975 static HRESULT WINAPI d3d1_CreateLight(IDirect3D *iface, IDirect3DLight **light, IUnknown *outer_unknown)
3976 {
3977 struct ddraw *ddraw = impl_from_IDirect3D(iface);
3978
3979 TRACE("iface %p, light %p, outer_unknown %p.\n", iface, light, outer_unknown);
3980
3981 return d3d3_CreateLight(&ddraw->IDirect3D3_iface, light, outer_unknown);
3982 }
3983
3984 /*****************************************************************************
3985 * IDirect3D3::CreateMaterial
3986 *
3987 * Creates an IDirect3DMaterial interface. This interface is used by Direct3D3
3988 * and older versions. The IDirect3DMaterial implementation wraps its
3989 * functionality to IDirect3DDevice7::SetMaterial and friends.
3990 *
3991 * Versions 1, 2 and 3
3992 *
3993 * Params:
3994 * material: Address to store the new interface's pointer to
3995 * outer_unknown: Basically for aggregation, but ddraw doesn't support it.
3996 * Must be NULL
3997 *
3998 * Returns:
3999 * D3D_OK on success
4000 * DDERR_OUTOFMEMORY if memory allocation failed
4001 * CLASS_E_NOAGGREGATION if outer_unknown != NULL
4002 *
4003 *****************************************************************************/
d3d3_CreateMaterial(IDirect3D3 * iface,IDirect3DMaterial3 ** material,IUnknown * outer_unknown)4004 static HRESULT WINAPI d3d3_CreateMaterial(IDirect3D3 *iface, IDirect3DMaterial3 **material,
4005 IUnknown *outer_unknown)
4006 {
4007 struct ddraw *ddraw = impl_from_IDirect3D3(iface);
4008 struct d3d_material *object;
4009
4010 TRACE("iface %p, material %p, outer_unknown %p.\n", iface, material, outer_unknown);
4011
4012 if (outer_unknown) return CLASS_E_NOAGGREGATION;
4013
4014 object = d3d_material_create(ddraw);
4015 if (!object)
4016 {
4017 ERR("Failed to allocate material memory.\n");
4018 return DDERR_OUTOFMEMORY;
4019 }
4020
4021 TRACE("Created material %p.\n", object);
4022 *material = &object->IDirect3DMaterial3_iface;
4023
4024 return D3D_OK;
4025 }
4026
d3d2_CreateMaterial(IDirect3D2 * iface,IDirect3DMaterial2 ** material,IUnknown * outer_unknown)4027 static HRESULT WINAPI d3d2_CreateMaterial(IDirect3D2 *iface, IDirect3DMaterial2 **material,
4028 IUnknown *outer_unknown)
4029 {
4030 struct ddraw *ddraw = impl_from_IDirect3D2(iface);
4031 struct d3d_material *object;
4032
4033 TRACE("iface %p, material %p, outer_unknown %p.\n", iface, material, outer_unknown);
4034
4035 object = d3d_material_create(ddraw);
4036 if (!object)
4037 {
4038 ERR("Failed to allocate material memory.\n");
4039 return DDERR_OUTOFMEMORY;
4040 }
4041
4042 TRACE("Created material %p.\n", object);
4043 *material = &object->IDirect3DMaterial2_iface;
4044
4045 return D3D_OK;
4046 }
4047
d3d1_CreateMaterial(IDirect3D * iface,IDirect3DMaterial ** material,IUnknown * outer_unknown)4048 static HRESULT WINAPI d3d1_CreateMaterial(IDirect3D *iface, IDirect3DMaterial **material,
4049 IUnknown *outer_unknown)
4050 {
4051 struct ddraw *ddraw = impl_from_IDirect3D(iface);
4052 struct d3d_material *object;
4053
4054 TRACE("iface %p, material %p, outer_unknown %p.\n", iface, material, outer_unknown);
4055
4056 object = d3d_material_create(ddraw);
4057 if (!object)
4058 {
4059 ERR("Failed to allocate material memory.\n");
4060 return DDERR_OUTOFMEMORY;
4061 }
4062
4063 TRACE("Created material %p.\n", object);
4064 *material = &object->IDirect3DMaterial_iface;
4065
4066 return D3D_OK;
4067 }
4068
4069 /*****************************************************************************
4070 * IDirect3D3::CreateViewport
4071 *
4072 * Creates an IDirect3DViewport interface. This interface is used
4073 * by Direct3D and earlier versions for Viewport management. In Direct3D7
4074 * it has been replaced by a viewport structure and
4075 * IDirect3DDevice7::*Viewport. Wine's IDirect3DViewport implementation
4076 * uses the IDirect3DDevice7 methods for its functionality
4077 *
4078 * Params:
4079 * Viewport: Address to store the new interface pointer
4080 * outer_unknown: Basically for aggregation, but ddraw doesn't support it.
4081 * Must be NULL
4082 *
4083 * Returns:
4084 * D3D_OK on success
4085 * DDERR_OUTOFMEMORY if memory allocation failed
4086 * CLASS_E_NOAGGREGATION if outer_unknown != NULL
4087 *
4088 *****************************************************************************/
d3d3_CreateViewport(IDirect3D3 * iface,IDirect3DViewport3 ** viewport,IUnknown * outer_unknown)4089 static HRESULT WINAPI d3d3_CreateViewport(IDirect3D3 *iface, IDirect3DViewport3 **viewport,
4090 IUnknown *outer_unknown)
4091 {
4092 struct ddraw *ddraw = impl_from_IDirect3D3(iface);
4093 struct d3d_viewport *object;
4094
4095 TRACE("iface %p, viewport %p, outer_unknown %p.\n", iface, viewport, outer_unknown);
4096
4097 if (outer_unknown) return CLASS_E_NOAGGREGATION;
4098
4099 if (!(object = heap_alloc_zero(sizeof(*object))))
4100 {
4101 ERR("Failed to allocate viewport memory.\n");
4102 return DDERR_OUTOFMEMORY;
4103 }
4104
4105 d3d_viewport_init(object, ddraw);
4106
4107 TRACE("Created viewport %p.\n", object);
4108 *viewport = &object->IDirect3DViewport3_iface;
4109
4110 return D3D_OK;
4111 }
4112
d3d2_CreateViewport(IDirect3D2 * iface,IDirect3DViewport2 ** viewport,IUnknown * outer_unknown)4113 static HRESULT WINAPI d3d2_CreateViewport(IDirect3D2 *iface, IDirect3DViewport2 **viewport, IUnknown *outer_unknown)
4114 {
4115 struct ddraw *ddraw = impl_from_IDirect3D2(iface);
4116
4117 TRACE("iface %p, viewport %p, outer_unknown %p.\n", iface, viewport, outer_unknown);
4118
4119 return d3d3_CreateViewport(&ddraw->IDirect3D3_iface, (IDirect3DViewport3 **)viewport,
4120 outer_unknown);
4121 }
4122
d3d1_CreateViewport(IDirect3D * iface,IDirect3DViewport ** viewport,IUnknown * outer_unknown)4123 static HRESULT WINAPI d3d1_CreateViewport(IDirect3D *iface, IDirect3DViewport **viewport, IUnknown *outer_unknown)
4124 {
4125 struct ddraw *ddraw = impl_from_IDirect3D(iface);
4126
4127 TRACE("iface %p, viewport %p, outer_unknown %p.\n", iface, viewport, outer_unknown);
4128
4129 return d3d3_CreateViewport(&ddraw->IDirect3D3_iface, (IDirect3DViewport3 **)viewport,
4130 outer_unknown);
4131 }
4132
4133 /*****************************************************************************
4134 * IDirect3D3::FindDevice
4135 *
4136 * This method finds a device with the requested properties and returns a
4137 * device description
4138 *
4139 * Versions 1, 2 and 3
4140 * Params:
4141 * fds: Describes the requested device characteristics
4142 * fdr: Returns the device description
4143 *
4144 * Returns:
4145 * D3D_OK on success
4146 * DDERR_INVALIDPARAMS if no device was found
4147 *
4148 *****************************************************************************/
d3d3_FindDevice(IDirect3D3 * iface,D3DFINDDEVICESEARCH * fds,D3DFINDDEVICERESULT * fdr)4149 static HRESULT WINAPI d3d3_FindDevice(IDirect3D3 *iface, D3DFINDDEVICESEARCH *fds, D3DFINDDEVICERESULT *fdr)
4150 {
4151 struct ddraw *ddraw = impl_from_IDirect3D3(iface);
4152 D3DDEVICEDESC7 desc7;
4153 D3DDEVICEDESC desc1;
4154 HRESULT hr;
4155
4156 TRACE("iface %p, fds %p, fdr %p.\n", iface, fds, fdr);
4157
4158 if (!fds || !fdr) return DDERR_INVALIDPARAMS;
4159
4160 if (fds->dwSize != sizeof(D3DFINDDEVICESEARCH) || (fdr->dwSize != sizeof(D3DFINDDEVICERESULT1) &&
4161 fdr->dwSize != sizeof(D3DFINDDEVICERESULT2) && fdr->dwSize != sizeof(D3DFINDDEVICERESULT)))
4162 return DDERR_INVALIDPARAMS;
4163
4164 if ((fds->dwFlags & D3DFDS_COLORMODEL)
4165 && fds->dcmColorModel != D3DCOLOR_RGB)
4166 {
4167 WARN("Trying to request a non-RGB D3D color model. Not supported.\n");
4168 return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */
4169 }
4170
4171 if (fds->dwFlags & D3DFDS_GUID)
4172 {
4173 TRACE("Trying to match guid %s.\n", debugstr_guid(&(fds->guid)));
4174 if (!IsEqualGUID(&IID_D3DDEVICE_WineD3D, &fds->guid)
4175 && !IsEqualGUID(&IID_IDirect3DHALDevice, &fds->guid)
4176 && !IsEqualGUID(&IID_IDirect3DRGBDevice, &fds->guid))
4177 {
4178 WARN("No match for this GUID.\n");
4179 return DDERR_NOTFOUND;
4180 }
4181 }
4182
4183 /* Get the caps */
4184 if (FAILED(hr = ddraw_get_d3dcaps(ddraw, &desc7)))
4185 return hr;
4186
4187 /* Now return our own GUID */
4188 ddraw_d3dcaps1_from_7(&desc1, &desc7);
4189 fdr->guid = IID_D3DDEVICE_WineD3D;
4190
4191 if (fdr->dwSize == sizeof(D3DFINDDEVICERESULT1))
4192 {
4193 D3DFINDDEVICERESULT1 *fdr1 = (D3DFINDDEVICERESULT1 *)fdr;
4194 memcpy(&fdr1->ddHwDesc, &desc1, sizeof(fdr1->ddHwDesc));
4195 memcpy(&fdr1->ddSwDesc, &desc1, sizeof(fdr1->ddSwDesc));
4196 }
4197 else if (fdr->dwSize == sizeof(D3DFINDDEVICERESULT2))
4198 {
4199 D3DFINDDEVICERESULT2 *fdr2 = (D3DFINDDEVICERESULT2 *)fdr;
4200 memcpy(&fdr2->ddHwDesc, &desc1, sizeof(fdr2->ddHwDesc));
4201 memcpy(&fdr2->ddSwDesc, &desc1, sizeof(fdr2->ddSwDesc));
4202 }
4203 else
4204 {
4205 fdr->ddHwDesc = desc1;
4206 fdr->ddSwDesc = desc1;
4207 }
4208
4209 TRACE("Returning Wine's wined3d device with (undumped) capabilities.\n");
4210
4211 return D3D_OK;
4212 }
4213
d3d2_FindDevice(IDirect3D2 * iface,D3DFINDDEVICESEARCH * fds,D3DFINDDEVICERESULT * fdr)4214 static HRESULT WINAPI d3d2_FindDevice(IDirect3D2 *iface, D3DFINDDEVICESEARCH *fds, D3DFINDDEVICERESULT *fdr)
4215 {
4216 struct ddraw *ddraw = impl_from_IDirect3D2(iface);
4217
4218 TRACE("iface %p, fds %p, fdr %p.\n", iface, fds, fdr);
4219
4220 return d3d3_FindDevice(&ddraw->IDirect3D3_iface, fds, fdr);
4221 }
4222
d3d1_FindDevice(IDirect3D * iface,D3DFINDDEVICESEARCH * fds,D3DFINDDEVICERESULT * fdr)4223 static HRESULT WINAPI d3d1_FindDevice(IDirect3D *iface, D3DFINDDEVICESEARCH *fds, D3DFINDDEVICERESULT *fdr)
4224 {
4225 struct ddraw *ddraw = impl_from_IDirect3D(iface);
4226
4227 TRACE("iface %p, fds %p, fdr %p.\n", iface, fds, fdr);
4228
4229 return d3d3_FindDevice(&ddraw->IDirect3D3_iface, fds, fdr);
4230 }
4231
4232 /*****************************************************************************
4233 * IDirect3D7::CreateDevice
4234 *
4235 * Creates an IDirect3DDevice7 interface.
4236 *
4237 * Versions 2, 3 and 7. IDirect3DDevice 1 interfaces are interfaces to
4238 * DirectDraw surfaces and are created with
4239 * IDirectDrawSurface::QueryInterface. This method uses CreateDevice to
4240 * create the device object and QueryInterfaces for IDirect3DDevice
4241 *
4242 * Params:
4243 * refiid: IID of the device to create
4244 * Surface: Initial rendertarget
4245 * Device: Address to return the interface pointer
4246 *
4247 * Returns:
4248 * D3D_OK on success
4249 * DDERR_OUTOFMEMORY if memory allocation failed
4250 * DDERR_INVALIDPARAMS if a device exists already
4251 *
4252 *****************************************************************************/
d3d7_CreateDevice(IDirect3D7 * iface,REFCLSID riid,IDirectDrawSurface7 * surface,IDirect3DDevice7 ** device)4253 static HRESULT WINAPI d3d7_CreateDevice(IDirect3D7 *iface, REFCLSID riid,
4254 IDirectDrawSurface7 *surface, IDirect3DDevice7 **device)
4255 {
4256 struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface7(surface);
4257 struct ddraw *ddraw = impl_from_IDirect3D7(iface);
4258 struct d3d_device *object;
4259 HRESULT hr;
4260
4261 TRACE("iface %p, riid %s, surface %p, device %p.\n", iface, debugstr_guid(riid), surface, device);
4262
4263 wined3d_mutex_lock();
4264 if (SUCCEEDED(hr = d3d_device_create(ddraw, riid, target, (IUnknown *)surface, 7, &object, NULL)))
4265 {
4266 *device = &object->IDirect3DDevice7_iface;
4267 }
4268 else
4269 {
4270 WARN("Failed to create device, hr %#x.\n", hr);
4271 *device = NULL;
4272 }
4273 wined3d_mutex_unlock();
4274
4275 return hr;
4276 }
4277
d3d3_CreateDevice(IDirect3D3 * iface,REFCLSID riid,IDirectDrawSurface4 * surface,IDirect3DDevice3 ** device,IUnknown * outer_unknown)4278 static HRESULT WINAPI d3d3_CreateDevice(IDirect3D3 *iface, REFCLSID riid,
4279 IDirectDrawSurface4 *surface, IDirect3DDevice3 **device, IUnknown *outer_unknown)
4280 {
4281 struct ddraw_surface *surface_impl = unsafe_impl_from_IDirectDrawSurface4(surface);
4282 struct ddraw *ddraw = impl_from_IDirect3D3(iface);
4283 struct d3d_device *device_impl;
4284 HRESULT hr;
4285
4286 TRACE("iface %p, riid %s, surface %p, device %p, outer_unknown %p.\n",
4287 iface, debugstr_guid(riid), surface, device, outer_unknown);
4288
4289 if (outer_unknown)
4290 return CLASS_E_NOAGGREGATION;
4291
4292 wined3d_mutex_lock();
4293 if (SUCCEEDED(hr = d3d_device_create(ddraw, riid, surface_impl, (IUnknown *)surface, 3, &device_impl, NULL)))
4294 {
4295 *device = &device_impl->IDirect3DDevice3_iface;
4296 }
4297 else
4298 {
4299 WARN("Failed to create device, hr %#x.\n", hr);
4300 *device = NULL;
4301 }
4302 wined3d_mutex_unlock();
4303
4304 return hr;
4305 }
4306
d3d2_CreateDevice(IDirect3D2 * iface,REFCLSID riid,IDirectDrawSurface * surface,IDirect3DDevice2 ** device)4307 static HRESULT WINAPI d3d2_CreateDevice(IDirect3D2 *iface, REFCLSID riid,
4308 IDirectDrawSurface *surface, IDirect3DDevice2 **device)
4309 {
4310 struct ddraw_surface *surface_impl = unsafe_impl_from_IDirectDrawSurface(surface);
4311 struct ddraw *ddraw = impl_from_IDirect3D2(iface);
4312 struct d3d_device *device_impl;
4313 HRESULT hr;
4314
4315 TRACE("iface %p, riid %s, surface %p, device %p.\n",
4316 iface, debugstr_guid(riid), surface, device);
4317
4318 wined3d_mutex_lock();
4319 if (SUCCEEDED(hr = d3d_device_create(ddraw, riid, surface_impl, (IUnknown *)surface, 2, &device_impl, NULL)))
4320 {
4321 *device = &device_impl->IDirect3DDevice2_iface;
4322 }
4323 else
4324 {
4325 WARN("Failed to create device, hr %#x.\n", hr);
4326 *device = NULL;
4327 }
4328 wined3d_mutex_unlock();
4329
4330 return hr;
4331 }
4332
4333 /*****************************************************************************
4334 * IDirect3D7::CreateVertexBuffer
4335 *
4336 * Creates a new vertex buffer object and returns a IDirect3DVertexBuffer7
4337 * interface.
4338 *
4339 * Versions 3 and 7
4340 *
4341 * Params:
4342 * desc: Requested Vertex buffer properties
4343 * vertex_buffer: Address to return the interface pointer at
4344 * flags: Some flags, should be 0
4345 *
4346 * Returns
4347 * D3D_OK on success
4348 * DDERR_OUTOFMEMORY if memory allocation failed
4349 * DDERR_INVALIDPARAMS if desc or vertex_buffer is NULL
4350 *
4351 *****************************************************************************/
d3d7_CreateVertexBuffer(IDirect3D7 * iface,D3DVERTEXBUFFERDESC * desc,IDirect3DVertexBuffer7 ** vertex_buffer,DWORD flags)4352 static HRESULT WINAPI d3d7_CreateVertexBuffer(IDirect3D7 *iface, D3DVERTEXBUFFERDESC *desc,
4353 IDirect3DVertexBuffer7 **vertex_buffer, DWORD flags)
4354 {
4355 struct ddraw *ddraw = impl_from_IDirect3D7(iface);
4356 struct d3d_vertex_buffer *object;
4357 HRESULT hr;
4358
4359 TRACE("iface %p, desc %p, vertex_buffer %p, flags %#x.\n",
4360 iface, desc, vertex_buffer, flags);
4361
4362 if (!vertex_buffer || !desc) return DDERR_INVALIDPARAMS;
4363
4364 hr = d3d_vertex_buffer_create(&object, ddraw, desc);
4365 if (hr == D3D_OK)
4366 {
4367 TRACE("Created vertex buffer %p.\n", object);
4368 *vertex_buffer = &object->IDirect3DVertexBuffer7_iface;
4369 }
4370 else
4371 WARN("Failed to create vertex buffer, hr %#x.\n", hr);
4372
4373 return hr;
4374 }
4375
d3d3_CreateVertexBuffer(IDirect3D3 * iface,D3DVERTEXBUFFERDESC * desc,IDirect3DVertexBuffer ** vertex_buffer,DWORD flags,IUnknown * outer_unknown)4376 static HRESULT WINAPI d3d3_CreateVertexBuffer(IDirect3D3 *iface, D3DVERTEXBUFFERDESC *desc,
4377 IDirect3DVertexBuffer **vertex_buffer, DWORD flags, IUnknown *outer_unknown)
4378 {
4379 struct ddraw *ddraw = impl_from_IDirect3D3(iface);
4380 struct d3d_vertex_buffer *object;
4381 HRESULT hr;
4382
4383 TRACE("iface %p, desc %p, vertex_buffer %p, flags %#x, outer_unknown %p.\n",
4384 iface, desc, vertex_buffer, flags, outer_unknown);
4385
4386 if (outer_unknown)
4387 return CLASS_E_NOAGGREGATION;
4388 if (!vertex_buffer || !desc)
4389 return DDERR_INVALIDPARAMS;
4390
4391 hr = d3d_vertex_buffer_create(&object, ddraw, desc);
4392 if (hr == D3D_OK)
4393 {
4394 TRACE("Created vertex buffer %p.\n", object);
4395 *vertex_buffer = (IDirect3DVertexBuffer *)&object->IDirect3DVertexBuffer7_iface;
4396 }
4397 else
4398 WARN("Failed to create vertex buffer, hr %#x.\n", hr);
4399
4400 return hr;
4401 }
4402
4403 /*****************************************************************************
4404 * IDirect3D7::EnumZBufferFormats
4405 *
4406 * Enumerates all supported Z buffer pixel formats
4407 *
4408 * Versions 3 and 7
4409 *
4410 * Params:
4411 * device_iid:
4412 * callback: callback to call for each pixel format
4413 * context: Pointer to pass back to the callback
4414 *
4415 * Returns:
4416 * D3D_OK on success
4417 * DDERR_INVALIDPARAMS if callback is NULL
4418 *
4419 *****************************************************************************/
d3d7_EnumZBufferFormats(IDirect3D7 * iface,REFCLSID device_iid,LPD3DENUMPIXELFORMATSCALLBACK callback,void * context)4420 static HRESULT WINAPI d3d7_EnumZBufferFormats(IDirect3D7 *iface, REFCLSID device_iid,
4421 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
4422 {
4423 struct ddraw *ddraw = impl_from_IDirect3D7(iface);
4424 struct wined3d_display_mode mode;
4425 enum wined3d_device_type type;
4426 unsigned int i;
4427 HRESULT hr;
4428
4429 /* Order matters. Specifically, BattleZone II (full version) expects the
4430 * 16-bit depth formats to be listed before the 24 and 32 ones. */
4431 static const enum wined3d_format_id formats[] =
4432 {
4433 WINED3DFMT_S1_UINT_D15_UNORM,
4434 WINED3DFMT_D16_UNORM,
4435 WINED3DFMT_X8D24_UNORM,
4436 WINED3DFMT_S4X4_UINT_D24_UNORM,
4437 WINED3DFMT_D24_UNORM_S8_UINT,
4438 WINED3DFMT_D32_UNORM,
4439 };
4440
4441 TRACE("iface %p, device_iid %s, callback %p, context %p.\n",
4442 iface, debugstr_guid(device_iid), callback, context);
4443
4444 if (!callback) return DDERR_INVALIDPARAMS;
4445
4446 if (IsEqualGUID(device_iid, &IID_IDirect3DHALDevice)
4447 || IsEqualGUID(device_iid, &IID_IDirect3DTnLHalDevice)
4448 || IsEqualGUID(device_iid, &IID_D3DDEVICE_WineD3D))
4449 {
4450 TRACE("Asked for HAL device.\n");
4451 type = WINED3D_DEVICE_TYPE_HAL;
4452 }
4453 else if (IsEqualGUID(device_iid, &IID_IDirect3DRGBDevice)
4454 || IsEqualGUID(device_iid, &IID_IDirect3DMMXDevice))
4455 {
4456 TRACE("Asked for SW device.\n");
4457 type = WINED3D_DEVICE_TYPE_SW;
4458 }
4459 else if (IsEqualGUID(device_iid, &IID_IDirect3DRefDevice))
4460 {
4461 TRACE("Asked for REF device.\n");
4462 type = WINED3D_DEVICE_TYPE_REF;
4463 }
4464 else if (IsEqualGUID(device_iid, &IID_IDirect3DNullDevice))
4465 {
4466 TRACE("Asked for NULLREF device.\n");
4467 type = WINED3D_DEVICE_TYPE_NULLREF;
4468 }
4469 else
4470 {
4471 FIXME("Unexpected device GUID %s.\n", debugstr_guid(device_iid));
4472 type = WINED3D_DEVICE_TYPE_HAL;
4473 }
4474
4475 wined3d_mutex_lock();
4476 /* We need an adapter format from somewhere to please wined3d and WGL.
4477 * Use the current display mode. So far all cards offer the same depth
4478 * stencil format for all modes, but if some do not and applications do
4479 * not like that we'll have to find some workaround, like iterating over
4480 * all imaginable formats and collecting all the depth stencil formats we
4481 * can get. */
4482 if (FAILED(hr = wined3d_get_adapter_display_mode(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL)))
4483 {
4484 ERR("Failed to get display mode, hr %#x.\n", hr);
4485 wined3d_mutex_unlock();
4486 return hr;
4487 }
4488
4489 for (i = 0; i < ARRAY_SIZE(formats); ++i)
4490 {
4491 if (SUCCEEDED(wined3d_check_device_format(ddraw->wined3d, WINED3DADAPTER_DEFAULT, type, mode.format_id,
4492 WINED3DUSAGE_DEPTHSTENCIL, WINED3D_RTYPE_TEXTURE_2D, formats[i])))
4493 {
4494 DDPIXELFORMAT pformat;
4495
4496 memset(&pformat, 0, sizeof(pformat));
4497 pformat.dwSize = sizeof(pformat);
4498 ddrawformat_from_wined3dformat(&pformat, formats[i]);
4499
4500 TRACE("Enumerating wined3d format %#x.\n", formats[i]);
4501 hr = callback(&pformat, context);
4502 if (hr != DDENUMRET_OK)
4503 {
4504 TRACE("Format enumeration cancelled by application.\n");
4505 wined3d_mutex_unlock();
4506 return D3D_OK;
4507 }
4508 }
4509 }
4510
4511 /* Historically some windows drivers used dwZBufferBitDepth=24 for WINED3DFMT_X8D24_UNORM,
4512 * while others used dwZBufferBitDepth=32. In either case the pitch matches a 32 bits per
4513 * pixel format, so we use dwZBufferBitDepth=32. Some games expect 24. Windows Vista and
4514 * newer enumerate both versions, so we do the same(bug 22434) */
4515 if (SUCCEEDED(wined3d_check_device_format(ddraw->wined3d, WINED3DADAPTER_DEFAULT, type, mode.format_id,
4516 WINED3DUSAGE_DEPTHSTENCIL, WINED3D_RTYPE_TEXTURE_2D, WINED3DFMT_X8D24_UNORM)))
4517 {
4518 DDPIXELFORMAT x8d24 =
4519 {
4520 sizeof(x8d24), DDPF_ZBUFFER, 0,
4521 {24}, {0x00000000}, {0x00ffffff}, {0x00000000}
4522 };
4523 TRACE("Enumerating WINED3DFMT_X8D24_UNORM, dwZBufferBitDepth=24 version\n");
4524 callback(&x8d24, context);
4525 }
4526
4527 TRACE("End of enumeration.\n");
4528
4529 wined3d_mutex_unlock();
4530
4531 return D3D_OK;
4532 }
4533
d3d3_EnumZBufferFormats(IDirect3D3 * iface,REFCLSID device_iid,LPD3DENUMPIXELFORMATSCALLBACK callback,void * context)4534 static HRESULT WINAPI d3d3_EnumZBufferFormats(IDirect3D3 *iface, REFCLSID device_iid,
4535 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
4536 {
4537 struct ddraw *ddraw = impl_from_IDirect3D3(iface);
4538
4539 TRACE("iface %p, device_iid %s, callback %p, context %p.\n",
4540 iface, debugstr_guid(device_iid), callback, context);
4541
4542 return d3d7_EnumZBufferFormats(&ddraw->IDirect3D7_iface, device_iid, callback, context);
4543 }
4544
4545 /*****************************************************************************
4546 * IDirect3D7::EvictManagedTextures
4547 *
4548 * Removes all managed textures (=surfaces with DDSCAPS2_TEXTUREMANAGE or
4549 * DDSCAPS2_D3DTEXTUREMANAGE caps) to be removed from video memory.
4550 *
4551 * Versions 3 and 7
4552 *
4553 * Returns:
4554 * D3D_OK, because it's a stub
4555 *
4556 *****************************************************************************/
d3d7_EvictManagedTextures(IDirect3D7 * iface)4557 static HRESULT WINAPI d3d7_EvictManagedTextures(IDirect3D7 *iface)
4558 {
4559 struct ddraw *ddraw = impl_from_IDirect3D7(iface);
4560
4561 TRACE("iface %p!\n", iface);
4562
4563 wined3d_mutex_lock();
4564 if (ddraw->flags & DDRAW_D3D_INITIALIZED)
4565 wined3d_device_evict_managed_resources(ddraw->wined3d_device);
4566 wined3d_mutex_unlock();
4567
4568 return D3D_OK;
4569 }
4570
d3d3_EvictManagedTextures(IDirect3D3 * iface)4571 static HRESULT WINAPI d3d3_EvictManagedTextures(IDirect3D3 *iface)
4572 {
4573 struct ddraw *ddraw = impl_from_IDirect3D3(iface);
4574
4575 TRACE("iface %p.\n", iface);
4576
4577 return d3d7_EvictManagedTextures(&ddraw->IDirect3D7_iface);
4578 }
4579
4580 /*****************************************************************************
4581 * IDirectDraw7 VTable
4582 *****************************************************************************/
4583 static const struct IDirectDraw7Vtbl ddraw7_vtbl =
4584 {
4585 /* IUnknown */
4586 ddraw7_QueryInterface,
4587 ddraw7_AddRef,
4588 ddraw7_Release,
4589 /* IDirectDraw */
4590 ddraw7_Compact,
4591 ddraw7_CreateClipper,
4592 ddraw7_CreatePalette,
4593 ddraw7_CreateSurface,
4594 ddraw7_DuplicateSurface,
4595 ddraw7_EnumDisplayModes,
4596 ddraw7_EnumSurfaces,
4597 ddraw7_FlipToGDISurface,
4598 ddraw7_GetCaps,
4599 ddraw7_GetDisplayMode,
4600 ddraw7_GetFourCCCodes,
4601 ddraw7_GetGDISurface,
4602 ddraw7_GetMonitorFrequency,
4603 ddraw7_GetScanLine,
4604 ddraw7_GetVerticalBlankStatus,
4605 ddraw7_Initialize,
4606 ddraw7_RestoreDisplayMode,
4607 ddraw7_SetCooperativeLevel,
4608 ddraw7_SetDisplayMode,
4609 ddraw7_WaitForVerticalBlank,
4610 /* IDirectDraw2 */
4611 ddraw7_GetAvailableVidMem,
4612 /* IDirectDraw3 */
4613 ddraw7_GetSurfaceFromDC,
4614 /* IDirectDraw4 */
4615 ddraw7_RestoreAllSurfaces,
4616 ddraw7_TestCooperativeLevel,
4617 ddraw7_GetDeviceIdentifier,
4618 /* IDirectDraw7 */
4619 ddraw7_StartModeTest,
4620 ddraw7_EvaluateMode
4621 };
4622
4623 static const struct IDirectDraw4Vtbl ddraw4_vtbl =
4624 {
4625 /* IUnknown */
4626 ddraw4_QueryInterface,
4627 ddraw4_AddRef,
4628 ddraw4_Release,
4629 /* IDirectDraw */
4630 ddraw4_Compact,
4631 ddraw4_CreateClipper,
4632 ddraw4_CreatePalette,
4633 ddraw4_CreateSurface,
4634 ddraw4_DuplicateSurface,
4635 ddraw4_EnumDisplayModes,
4636 ddraw4_EnumSurfaces,
4637 ddraw4_FlipToGDISurface,
4638 ddraw4_GetCaps,
4639 ddraw4_GetDisplayMode,
4640 ddraw4_GetFourCCCodes,
4641 ddraw4_GetGDISurface,
4642 ddraw4_GetMonitorFrequency,
4643 ddraw4_GetScanLine,
4644 ddraw4_GetVerticalBlankStatus,
4645 ddraw4_Initialize,
4646 ddraw4_RestoreDisplayMode,
4647 ddraw4_SetCooperativeLevel,
4648 ddraw4_SetDisplayMode,
4649 ddraw4_WaitForVerticalBlank,
4650 /* IDirectDraw2 */
4651 ddraw4_GetAvailableVidMem,
4652 /* IDirectDraw3 */
4653 ddraw4_GetSurfaceFromDC,
4654 /* IDirectDraw4 */
4655 ddraw4_RestoreAllSurfaces,
4656 ddraw4_TestCooperativeLevel,
4657 ddraw4_GetDeviceIdentifier,
4658 };
4659
4660 static const struct IDirectDraw2Vtbl ddraw2_vtbl =
4661 {
4662 /* IUnknown */
4663 ddraw2_QueryInterface,
4664 ddraw2_AddRef,
4665 ddraw2_Release,
4666 /* IDirectDraw */
4667 ddraw2_Compact,
4668 ddraw2_CreateClipper,
4669 ddraw2_CreatePalette,
4670 ddraw2_CreateSurface,
4671 ddraw2_DuplicateSurface,
4672 ddraw2_EnumDisplayModes,
4673 ddraw2_EnumSurfaces,
4674 ddraw2_FlipToGDISurface,
4675 ddraw2_GetCaps,
4676 ddraw2_GetDisplayMode,
4677 ddraw2_GetFourCCCodes,
4678 ddraw2_GetGDISurface,
4679 ddraw2_GetMonitorFrequency,
4680 ddraw2_GetScanLine,
4681 ddraw2_GetVerticalBlankStatus,
4682 ddraw2_Initialize,
4683 ddraw2_RestoreDisplayMode,
4684 ddraw2_SetCooperativeLevel,
4685 ddraw2_SetDisplayMode,
4686 ddraw2_WaitForVerticalBlank,
4687 /* IDirectDraw2 */
4688 ddraw2_GetAvailableVidMem,
4689 };
4690
4691 static struct IDirectDrawVtbl ddraw1_vtbl =
4692 {
4693 /* IUnknown */
4694 ddraw1_QueryInterface,
4695 ddraw1_AddRef,
4696 ddraw1_Release,
4697 /* IDirectDraw */
4698 ddraw1_Compact,
4699 ddraw1_CreateClipper,
4700 ddraw1_CreatePalette,
4701 ddraw1_CreateSurface,
4702 ddraw1_DuplicateSurface,
4703 ddraw1_EnumDisplayModes,
4704 ddraw1_EnumSurfaces,
4705 ddraw1_FlipToGDISurface,
4706 ddraw1_GetCaps,
4707 ddraw1_GetDisplayMode,
4708 ddraw1_GetFourCCCodes,
4709 ddraw1_GetGDISurface,
4710 ddraw1_GetMonitorFrequency,
4711 ddraw1_GetScanLine,
4712 ddraw1_GetVerticalBlankStatus,
4713 ddraw1_Initialize,
4714 ddraw1_RestoreDisplayMode,
4715 ddraw1_SetCooperativeLevel,
4716 ddraw1_SetDisplayMode,
4717 ddraw1_WaitForVerticalBlank,
4718 };
4719
4720 static const struct IDirect3D7Vtbl d3d7_vtbl =
4721 {
4722 /* IUnknown methods */
4723 d3d7_QueryInterface,
4724 d3d7_AddRef,
4725 d3d7_Release,
4726 /* IDirect3D7 methods */
4727 d3d7_EnumDevices,
4728 d3d7_CreateDevice,
4729 d3d7_CreateVertexBuffer,
4730 d3d7_EnumZBufferFormats,
4731 d3d7_EvictManagedTextures
4732 };
4733
4734 static const struct IDirect3D3Vtbl d3d3_vtbl =
4735 {
4736 /* IUnknown methods */
4737 d3d3_QueryInterface,
4738 d3d3_AddRef,
4739 d3d3_Release,
4740 /* IDirect3D3 methods */
4741 d3d3_EnumDevices,
4742 d3d3_CreateLight,
4743 d3d3_CreateMaterial,
4744 d3d3_CreateViewport,
4745 d3d3_FindDevice,
4746 d3d3_CreateDevice,
4747 d3d3_CreateVertexBuffer,
4748 d3d3_EnumZBufferFormats,
4749 d3d3_EvictManagedTextures
4750 };
4751
4752 static const struct IDirect3D2Vtbl d3d2_vtbl =
4753 {
4754 /* IUnknown methods */
4755 d3d2_QueryInterface,
4756 d3d2_AddRef,
4757 d3d2_Release,
4758 /* IDirect3D2 methods */
4759 d3d2_EnumDevices,
4760 d3d2_CreateLight,
4761 d3d2_CreateMaterial,
4762 d3d2_CreateViewport,
4763 d3d2_FindDevice,
4764 d3d2_CreateDevice
4765 };
4766
4767 static const struct IDirect3DVtbl d3d1_vtbl =
4768 {
4769 /* IUnknown methods */
4770 d3d1_QueryInterface,
4771 d3d1_AddRef,
4772 d3d1_Release,
4773 /* IDirect3D methods */
4774 d3d1_Initialize,
4775 d3d1_EnumDevices,
4776 d3d1_CreateLight,
4777 d3d1_CreateMaterial,
4778 d3d1_CreateViewport,
4779 d3d1_FindDevice
4780 };
4781
4782 /*****************************************************************************
4783 * ddraw_find_decl
4784 *
4785 * Finds the WineD3D vertex declaration for a specific fvf, and creates one
4786 * if none was found.
4787 *
4788 * This function is in ddraw.c and the DDraw object space because D3D7
4789 * vertex buffers are created using the IDirect3D interface to the ddraw
4790 * object, so they can be valid across D3D devices(theoretically. The ddraw
4791 * object also owns the wined3d device
4792 *
4793 * Parameters:
4794 * This: Device
4795 * fvf: Fvf to find the decl for
4796 *
4797 * Returns:
4798 * NULL in case of an error, the vertex declaration for the FVF otherwise.
4799 *
4800 *****************************************************************************/
ddraw_find_decl(struct ddraw * This,DWORD fvf)4801 struct wined3d_vertex_declaration *ddraw_find_decl(struct ddraw *This, DWORD fvf)
4802 {
4803 struct wined3d_vertex_declaration *pDecl = NULL;
4804 HRESULT hr;
4805 int p, low, high; /* deliberately signed */
4806 struct FvfToDecl *convertedDecls = This->decls;
4807
4808 TRACE("Searching for declaration for fvf %08x... ", fvf);
4809
4810 low = 0;
4811 high = This->numConvertedDecls - 1;
4812 while(low <= high) {
4813 p = (low + high) >> 1;
4814 TRACE("%d ", p);
4815 if(convertedDecls[p].fvf == fvf) {
4816 TRACE("found %p\n", convertedDecls[p].decl);
4817 return convertedDecls[p].decl;
4818 } else if(convertedDecls[p].fvf < fvf) {
4819 low = p + 1;
4820 } else {
4821 high = p - 1;
4822 }
4823 }
4824 TRACE("not found. Creating and inserting at position %d.\n", low);
4825
4826 hr = wined3d_vertex_declaration_create_from_fvf(This->wined3d_device,
4827 fvf, This, &ddraw_null_wined3d_parent_ops, &pDecl);
4828 if (hr != S_OK) return NULL;
4829
4830 if (This->declArraySize == This->numConvertedDecls)
4831 {
4832 unsigned int grow = max(This->declArraySize / 2, 8);
4833
4834 if (!(convertedDecls = heap_realloc(convertedDecls,
4835 (This->numConvertedDecls + grow) * sizeof(*convertedDecls))))
4836 {
4837 wined3d_vertex_declaration_decref(pDecl);
4838 return NULL;
4839 }
4840 This->decls = convertedDecls;
4841 This->declArraySize += grow;
4842 }
4843
4844 memmove(convertedDecls + low + 1, convertedDecls + low, sizeof(convertedDecls[0]) * (This->numConvertedDecls - low));
4845 convertedDecls[low].decl = pDecl;
4846 convertedDecls[low].fvf = fvf;
4847 This->numConvertedDecls++;
4848
4849 TRACE("Returning %p. %d decls in array\n", pDecl, This->numConvertedDecls);
4850 return pDecl;
4851 }
4852
ddraw_from_device_parent(struct wined3d_device_parent * device_parent)4853 static inline struct ddraw *ddraw_from_device_parent(struct wined3d_device_parent *device_parent)
4854 {
4855 return CONTAINING_RECORD(device_parent, struct ddraw, device_parent);
4856 }
4857
device_parent_wined3d_device_created(struct wined3d_device_parent * device_parent,struct wined3d_device * device)4858 static void CDECL device_parent_wined3d_device_created(struct wined3d_device_parent *device_parent,
4859 struct wined3d_device *device)
4860 {
4861 TRACE("device_parent %p, device %p.\n", device_parent, device);
4862 }
4863
4864 /* This is run from device_process_message() in wined3d, we can't take the
4865 * wined3d mutex. */
4866 /* FIXME: We only get mode change notifications in exclusive mode, but we
4867 * should mark surfaces as lost on mode changes in DDSCL_NORMAL mode as well. */
device_parent_mode_changed(struct wined3d_device_parent * device_parent)4868 static void CDECL device_parent_mode_changed(struct wined3d_device_parent *device_parent)
4869 {
4870 struct ddraw *ddraw = ddraw_from_device_parent(device_parent);
4871 MONITORINFO monitor_info;
4872 HMONITOR monitor;
4873 RECT *r;
4874
4875 TRACE("device_parent %p.\n", device_parent);
4876
4877 if (!(ddraw->cooperative_level & DDSCL_EXCLUSIVE) || !ddraw->swapchain_window)
4878 {
4879 TRACE("Nothing to resize.\n");
4880 return;
4881 }
4882
4883 monitor = MonitorFromWindow(ddraw->swapchain_window, MONITOR_DEFAULTTOPRIMARY);
4884 monitor_info.cbSize = sizeof(monitor_info);
4885 if (!GetMonitorInfoW(monitor, &monitor_info))
4886 {
4887 ERR("Failed to get monitor info.\n");
4888 return;
4889 }
4890
4891 r = &monitor_info.rcMonitor;
4892 TRACE("Resizing window %p to %s.\n", ddraw->swapchain_window, wine_dbgstr_rect(r));
4893
4894 if (!SetWindowPos(ddraw->swapchain_window, HWND_TOP, r->left, r->top,
4895 r->right - r->left, r->bottom - r->top, SWP_SHOWWINDOW | SWP_NOACTIVATE))
4896 ERR("Failed to resize window.\n");
4897
4898 InterlockedCompareExchange(&ddraw->device_state, DDRAW_DEVICE_STATE_NOT_RESTORED, DDRAW_DEVICE_STATE_OK);
4899 }
4900
device_parent_activate(struct wined3d_device_parent * device_parent,BOOL activate)4901 static void CDECL device_parent_activate(struct wined3d_device_parent *device_parent, BOOL activate)
4902 {
4903 struct ddraw *ddraw = ddraw_from_device_parent(device_parent);
4904
4905 TRACE("device_parent %p, activate %#x.\n", device_parent, activate);
4906
4907 if (!activate)
4908 {
4909 ddraw->device_state = DDRAW_DEVICE_STATE_LOST;
4910 exclusive_window = NULL;
4911 }
4912 else
4913 {
4914 InterlockedCompareExchange(&ddraw->device_state, DDRAW_DEVICE_STATE_NOT_RESTORED, DDRAW_DEVICE_STATE_LOST);
4915 }
4916 }
4917
ddraw_update_lost_surfaces(struct ddraw * ddraw)4918 void ddraw_update_lost_surfaces(struct ddraw *ddraw)
4919 {
4920 struct ddraw_surface *surface;
4921
4922 if (ddraw->device_state != DDRAW_DEVICE_STATE_NOT_RESTORED)
4923 return;
4924
4925 LIST_FOR_EACH_ENTRY(surface, &ddraw->surface_list, struct ddraw_surface, surface_list_entry)
4926 {
4927 surface->is_lost = TRUE;
4928 }
4929 ddraw->device_state = DDRAW_DEVICE_STATE_OK;
4930 }
4931
device_parent_surface_created(struct wined3d_device_parent * device_parent,struct wined3d_texture * wined3d_texture,unsigned int sub_resource_idx,void ** parent,const struct wined3d_parent_ops ** parent_ops)4932 static HRESULT CDECL device_parent_surface_created(struct wined3d_device_parent *device_parent,
4933 struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx,
4934 void **parent, const struct wined3d_parent_ops **parent_ops)
4935 {
4936 struct ddraw *ddraw = ddraw_from_device_parent(device_parent);
4937 struct ddraw_surface *ddraw_surface;
4938
4939 TRACE("device_parent %p, wined3d_texture %p, sub_resource_idx %u, parent %p, parent_ops %p.\n",
4940 device_parent, wined3d_texture, sub_resource_idx, parent, parent_ops);
4941
4942 /* We have a swapchain or wined3d internal texture. */
4943 if (!wined3d_texture_get_parent(wined3d_texture) || wined3d_texture_get_parent(wined3d_texture) == ddraw)
4944 {
4945 *parent = NULL;
4946 *parent_ops = &ddraw_null_wined3d_parent_ops;
4947
4948 return DD_OK;
4949 }
4950
4951 if (!(ddraw_surface = heap_alloc_zero(sizeof(*ddraw_surface))))
4952 {
4953 ERR("Failed to allocate surface memory.\n");
4954 return DDERR_OUTOFVIDEOMEMORY;
4955 }
4956
4957 ddraw_surface_init(ddraw_surface, ddraw, wined3d_texture, sub_resource_idx, parent_ops);
4958 *parent = ddraw_surface;
4959
4960 ddraw_update_lost_surfaces(ddraw);
4961 list_add_head(&ddraw->surface_list, &ddraw_surface->surface_list_entry);
4962
4963 TRACE("Created ddraw surface %p.\n", ddraw_surface);
4964
4965 return DD_OK;
4966 }
4967
device_parent_volume_created(struct wined3d_device_parent * device_parent,struct wined3d_texture * wined3d_texture,unsigned int sub_resource_idx,void ** parent,const struct wined3d_parent_ops ** parent_ops)4968 static HRESULT CDECL device_parent_volume_created(struct wined3d_device_parent *device_parent,
4969 struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx,
4970 void **parent, const struct wined3d_parent_ops **parent_ops)
4971 {
4972 TRACE("device_parent %p, texture %p, sub_resource_idx %u, parent %p, parent_ops %p.\n",
4973 device_parent, wined3d_texture, sub_resource_idx, parent, parent_ops);
4974
4975 *parent = NULL;
4976 *parent_ops = &ddraw_null_wined3d_parent_ops;
4977
4978 return DD_OK;
4979 }
4980
ddraw_frontbuffer_destroyed(void * parent)4981 static void STDMETHODCALLTYPE ddraw_frontbuffer_destroyed(void *parent)
4982 {
4983 struct ddraw *ddraw = parent;
4984 ddraw->wined3d_frontbuffer = NULL;
4985 }
4986
4987 static const struct wined3d_parent_ops ddraw_frontbuffer_parent_ops =
4988 {
4989 ddraw_frontbuffer_destroyed,
4990 };
4991
device_parent_create_swapchain_texture(struct wined3d_device_parent * device_parent,void * container_parent,const struct wined3d_resource_desc * desc,DWORD texture_flags,struct wined3d_texture ** texture)4992 static HRESULT CDECL device_parent_create_swapchain_texture(struct wined3d_device_parent *device_parent,
4993 void *container_parent, const struct wined3d_resource_desc *desc, DWORD texture_flags,
4994 struct wined3d_texture **texture)
4995 {
4996 struct ddraw *ddraw = ddraw_from_device_parent(device_parent);
4997 HRESULT hr;
4998
4999 TRACE("device_parent %p, container_parent %p, desc %p, texture flags %#x, texture %p.\n",
5000 device_parent, container_parent, desc, texture_flags, texture);
5001
5002 if (ddraw->wined3d_frontbuffer)
5003 {
5004 ERR("Frontbuffer already created.\n");
5005 return E_FAIL;
5006 }
5007
5008 if (FAILED(hr = wined3d_texture_create(ddraw->wined3d_device, desc, 1, 1,
5009 texture_flags | WINED3D_TEXTURE_CREATE_MAPPABLE, NULL, ddraw, &ddraw_frontbuffer_parent_ops, texture)))
5010 {
5011 WARN("Failed to create texture, hr %#x.\n", hr);
5012 return hr;
5013 }
5014
5015 ddraw->wined3d_frontbuffer = *texture;
5016
5017 return hr;
5018 }
5019
device_parent_create_swapchain(struct wined3d_device_parent * device_parent,struct wined3d_swapchain_desc * desc,struct wined3d_swapchain ** swapchain)5020 static HRESULT CDECL device_parent_create_swapchain(struct wined3d_device_parent *device_parent,
5021 struct wined3d_swapchain_desc *desc, struct wined3d_swapchain **swapchain)
5022 {
5023 struct ddraw *ddraw = ddraw_from_device_parent(device_parent);
5024 HRESULT hr;
5025
5026 TRACE("device_parent %p, desc %p, swapchain %p.\n", device_parent, desc, swapchain);
5027
5028 if (ddraw->wined3d_swapchain)
5029 {
5030 ERR("Swapchain already created.\n");
5031 return E_FAIL;
5032 }
5033
5034 if (FAILED(hr = wined3d_swapchain_create(ddraw->wined3d_device, desc, NULL,
5035 &ddraw_null_wined3d_parent_ops, swapchain)))
5036 WARN("Failed to create swapchain, hr %#x.\n", hr);
5037
5038 return hr;
5039 }
5040
5041 static const struct wined3d_device_parent_ops ddraw_wined3d_device_parent_ops =
5042 {
5043 device_parent_wined3d_device_created,
5044 device_parent_mode_changed,
5045 device_parent_activate,
5046 device_parent_surface_created,
5047 device_parent_volume_created,
5048 device_parent_create_swapchain_texture,
5049 device_parent_create_swapchain,
5050 };
5051
ddraw_init(struct ddraw * ddraw,DWORD flags,enum wined3d_device_type device_type)5052 HRESULT ddraw_init(struct ddraw *ddraw, DWORD flags, enum wined3d_device_type device_type)
5053 {
5054 WINED3DCAPS caps;
5055 HRESULT hr;
5056
5057 ddraw->IDirectDraw7_iface.lpVtbl = &ddraw7_vtbl;
5058 ddraw->IDirectDraw_iface.lpVtbl = &ddraw1_vtbl;
5059 ddraw->IDirectDraw2_iface.lpVtbl = &ddraw2_vtbl;
5060 ddraw->IDirectDraw4_iface.lpVtbl = &ddraw4_vtbl;
5061 ddraw->IDirect3D_iface.lpVtbl = &d3d1_vtbl;
5062 ddraw->IDirect3D2_iface.lpVtbl = &d3d2_vtbl;
5063 ddraw->IDirect3D3_iface.lpVtbl = &d3d3_vtbl;
5064 ddraw->IDirect3D7_iface.lpVtbl = &d3d7_vtbl;
5065 ddraw->device_parent.ops = &ddraw_wined3d_device_parent_ops;
5066 ddraw->numIfaces = 1;
5067 ddraw->ref7 = 1;
5068
5069 flags |= DDRAW_WINED3D_FLAGS;
5070 if (!(ddraw->wined3d = wined3d_create(flags)))
5071 {
5072 flags |= WINED3D_NO3D;
5073 if (!(ddraw->wined3d = wined3d_create(flags)))
5074 {
5075 WARN("Failed to create a wined3d object.\n");
5076 return E_FAIL;
5077 }
5078 }
5079
5080 if (FAILED(hr = wined3d_get_device_caps(ddraw->wined3d, WINED3DADAPTER_DEFAULT, device_type, &caps)))
5081 {
5082 ERR("Failed to get device caps, hr %#x.\n", hr);
5083 wined3d_decref(ddraw->wined3d);
5084 return E_FAIL;
5085 }
5086
5087 if (!(caps.ddraw_caps.caps & WINEDDCAPS_3D))
5088 {
5089 WARN("Created a wined3d object without 3D support.\n");
5090 ddraw->flags |= DDRAW_NO3D;
5091 }
5092
5093 if (FAILED(hr = wined3d_device_create(ddraw->wined3d, WINED3DADAPTER_DEFAULT, device_type,
5094 NULL, 0, DDRAW_STRIDE_ALIGNMENT, &ddraw->device_parent, &ddraw->wined3d_device)))
5095 {
5096 WARN("Failed to create a wined3d device, hr %#x.\n", hr);
5097 wined3d_decref(ddraw->wined3d);
5098 return hr;
5099 }
5100
5101 list_init(&ddraw->surface_list);
5102
5103 return DD_OK;
5104 }
5105