[D3D8][D3D9][DDRAW][WINED3D] Sync with Wine Staging 1.9.4. CORE-10912
[reactos.git] / reactos / dll / directx / wine / ddraw / surface.c
1 /* DirectDraw Surface Implementation
2 *
3 * Copyright (c) 1997-2000 Marcus Meissner
4 * Copyright (c) 1998-2000 Lionel Ulmer
5 * Copyright (c) 2000-2001 TransGaming Technologies Inc.
6 * Copyright (c) 2006 Stefan Dösinger
7 * Copyright (c) 2011 Ričardas Barkauskas 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 "ddraw_private.h"
25
26 static struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface2(IDirectDrawSurface2 *iface);
27 static struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface3(IDirectDrawSurface3 *iface);
28
29 static inline struct ddraw_surface *impl_from_IDirectDrawGammaControl(IDirectDrawGammaControl *iface)
30 {
31 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawGammaControl_iface);
32 }
33
34 /* This is slow, of course. Also, in case of locks, we can't prevent other
35 * applications from drawing to the screen while we've locked the frontbuffer.
36 * We'd like to do this in wined3d instead, but for that to work wined3d needs
37 * to support windowless rendering first. */
38 HRESULT ddraw_surface_update_frontbuffer(struct ddraw_surface *surface, const RECT *rect, BOOL read)
39 {
40 HDC surface_dc, screen_dc;
41 int x, y, w, h;
42 HRESULT hr;
43 BOOL ret;
44 RECT r;
45
46 if (!rect)
47 {
48 SetRect(&r, 0, 0, surface->surface_desc.dwWidth, surface->surface_desc.dwHeight);
49 rect = &r;
50 }
51
52 x = rect->left;
53 y = rect->top;
54 w = rect->right - rect->left;
55 h = rect->bottom - rect->top;
56
57 if (w <= 0 || h <= 0)
58 return DD_OK;
59
60 if (surface->ddraw->swapchain_window)
61 {
62 /* Nothing to do, we control the frontbuffer, or at least the parts we
63 * care about. */
64 if (read)
65 return DD_OK;
66
67 return wined3d_texture_blt(surface->ddraw->wined3d_frontbuffer, 0, rect,
68 surface->wined3d_texture, surface->sub_resource_idx, rect, 0, NULL, WINED3D_TEXF_POINT);
69 }
70
71 if (FAILED(hr = wined3d_texture_get_dc(surface->wined3d_texture, surface->sub_resource_idx, &surface_dc)))
72 {
73 ERR("Failed to get surface DC, hr %#x.\n", hr);
74 return hr;
75 }
76 if (surface->palette)
77 wined3d_palette_apply_to_dc(surface->palette->wineD3DPalette, surface_dc);
78
79 if (!(screen_dc = GetDC(NULL)))
80 {
81 wined3d_texture_release_dc(surface->wined3d_texture, surface->sub_resource_idx, surface_dc);
82 ERR("Failed to get screen DC.\n");
83 return E_FAIL;
84 }
85
86 if (read)
87 ret = BitBlt(surface_dc, x, y, w, h,
88 screen_dc, x, y, SRCCOPY);
89 else
90 ret = BitBlt(screen_dc, x, y, w, h,
91 surface_dc, x, y, SRCCOPY);
92
93 ReleaseDC(NULL, screen_dc);
94 wined3d_texture_release_dc(surface->wined3d_texture, surface->sub_resource_idx, surface_dc);
95
96 if (!ret)
97 {
98 ERR("Failed to blit to/from screen.\n");
99 return E_FAIL;
100 }
101
102 return DD_OK;
103 }
104
105 /*****************************************************************************
106 * IUnknown parts follow
107 *****************************************************************************/
108
109 /*****************************************************************************
110 * IDirectDrawSurface7::QueryInterface
111 *
112 * A normal QueryInterface implementation. For QueryInterface rules
113 * see ddraw.c, IDirectDraw7::QueryInterface. This method
114 * can Query IDirectDrawSurface interfaces in all version, IDirect3DTexture
115 * in all versions, the IDirectDrawGammaControl interface and it can
116 * create an IDirect3DDevice. (Uses IDirect3D7::CreateDevice)
117 *
118 * Params:
119 * riid: The interface id queried for
120 * obj: Address to write the pointer to
121 *
122 * Returns:
123 * S_OK on success
124 * E_NOINTERFACE if the requested interface wasn't found
125 *
126 *****************************************************************************/
127 static HRESULT WINAPI ddraw_surface7_QueryInterface(IDirectDrawSurface7 *iface, REFIID riid, void **obj)
128 {
129 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
130
131 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
132
133 /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
134 *obj = NULL;
135
136 if(!riid)
137 return DDERR_INVALIDPARAMS;
138
139 if (IsEqualGUID(riid, &IID_IDirectDrawSurface7))
140 {
141 IDirectDrawSurface7_AddRef(iface);
142 *obj = iface;
143 TRACE("(%p) returning IDirectDrawSurface7 interface at %p\n", This, *obj);
144 return S_OK;
145 }
146
147 if (IsEqualGUID(riid, &IID_IDirectDrawSurface4))
148 {
149 IDirectDrawSurface4_AddRef(&This->IDirectDrawSurface4_iface);
150 *obj = &This->IDirectDrawSurface4_iface;
151 TRACE("(%p) returning IDirectDrawSurface4 interface at %p\n", This, *obj);
152 return S_OK;
153 }
154
155 if (IsEqualGUID(riid, &IID_IDirectDrawSurface3))
156 {
157 IDirectDrawSurface3_AddRef(&This->IDirectDrawSurface3_iface);
158 *obj = &This->IDirectDrawSurface3_iface;
159 TRACE("(%p) returning IDirectDrawSurface3 interface at %p\n", This, *obj);
160 return S_OK;
161 }
162
163 if (IsEqualGUID(riid, &IID_IDirectDrawSurface2))
164 {
165 IDirectDrawSurface2_AddRef(&This->IDirectDrawSurface2_iface);
166 *obj = &This->IDirectDrawSurface2_iface;
167 TRACE("(%p) returning IDirectDrawSurface2 interface at %p\n", This, *obj);
168 return S_OK;
169 }
170
171 if (IsEqualGUID(riid, &IID_IDirectDrawSurface)
172 || IsEqualGUID(riid, &IID_IUnknown))
173 {
174 IDirectDrawSurface_AddRef(&This->IDirectDrawSurface_iface);
175 *obj = &This->IDirectDrawSurface_iface;
176 TRACE("(%p) returning IDirectDrawSurface interface at %p\n", This, *obj);
177 return S_OK;
178 }
179
180 if (IsEqualGUID(riid, &IID_IDirectDrawGammaControl))
181 {
182 IDirectDrawGammaControl_AddRef(&This->IDirectDrawGammaControl_iface);
183 *obj = &This->IDirectDrawGammaControl_iface;
184 TRACE("(%p) returning IDirectDrawGammaControl interface at %p\n", This, *obj);
185 return S_OK;
186 }
187
188 if (IsEqualGUID(riid, &IID_IDirectDrawColorControl))
189 {
190 WARN("Color control not implemented.\n");
191 *obj = NULL;
192 return E_NOINTERFACE;
193 }
194
195 if (This->version != 7)
196 {
197 if (IsEqualGUID(riid, &IID_D3DDEVICE_WineD3D)
198 || IsEqualGUID(riid, &IID_IDirect3DHALDevice)
199 || IsEqualGUID(riid, &IID_IDirect3DRGBDevice))
200 {
201 wined3d_mutex_lock();
202 if (!This->device1)
203 {
204 HRESULT hr;
205
206 if (FAILED(hr = d3d_device_create(This->ddraw, riid, This, (IUnknown *)&This->IDirectDrawSurface_iface,
207 1, &This->device1, (IUnknown *)&This->IDirectDrawSurface_iface)))
208 {
209 This->device1 = NULL;
210 wined3d_mutex_unlock();
211 WARN("Failed to create device, hr %#x.\n", hr);
212 return hr;
213 }
214 }
215 wined3d_mutex_unlock();
216
217 IDirect3DDevice_AddRef(&This->device1->IDirect3DDevice_iface);
218 *obj = &This->device1->IDirect3DDevice_iface;
219 return S_OK;
220 }
221
222 if (IsEqualGUID(&IID_IDirect3DTexture2, riid))
223 {
224 IDirect3DTexture2_AddRef(&This->IDirect3DTexture2_iface);
225 *obj = &This->IDirect3DTexture2_iface;
226 return S_OK;
227 }
228
229 if (IsEqualGUID( &IID_IDirect3DTexture, riid ))
230 {
231 IDirect3DTexture2_AddRef(&This->IDirect3DTexture_iface);
232 *obj = &This->IDirect3DTexture_iface;
233 return S_OK;
234 }
235 }
236
237 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
238
239 if (This->version != 7)
240 return E_INVALIDARG;
241
242 return E_NOINTERFACE;
243 }
244
245 static HRESULT WINAPI ddraw_surface4_QueryInterface(IDirectDrawSurface4 *iface, REFIID riid, void **object)
246 {
247 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
248
249 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
250
251 return ddraw_surface7_QueryInterface(&surface->IDirectDrawSurface7_iface, riid, object);
252 }
253
254 static HRESULT WINAPI ddraw_surface3_QueryInterface(IDirectDrawSurface3 *iface, REFIID riid, void **object)
255 {
256 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
257
258 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
259
260 return ddraw_surface7_QueryInterface(&surface->IDirectDrawSurface7_iface, riid, object);
261 }
262
263 static HRESULT WINAPI ddraw_surface2_QueryInterface(IDirectDrawSurface2 *iface, REFIID riid, void **object)
264 {
265 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
266
267 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
268
269 return ddraw_surface7_QueryInterface(&surface->IDirectDrawSurface7_iface, riid, object);
270 }
271
272 static HRESULT WINAPI ddraw_surface1_QueryInterface(IDirectDrawSurface *iface, REFIID riid, void **object)
273 {
274 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
275
276 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
277
278 return ddraw_surface7_QueryInterface(&surface->IDirectDrawSurface7_iface, riid, object);
279 }
280
281 static HRESULT WINAPI ddraw_gamma_control_QueryInterface(IDirectDrawGammaControl *iface,
282 REFIID riid, void **object)
283 {
284 struct ddraw_surface *surface = impl_from_IDirectDrawGammaControl(iface);
285
286 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
287
288 return ddraw_surface7_QueryInterface(&surface->IDirectDrawSurface7_iface, riid, object);
289 }
290
291 static HRESULT WINAPI d3d_texture2_QueryInterface(IDirect3DTexture2 *iface, REFIID riid, void **object)
292 {
293 struct ddraw_surface *surface = impl_from_IDirect3DTexture2(iface);
294
295 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
296
297 return ddraw_surface7_QueryInterface(&surface->IDirectDrawSurface7_iface, riid, object);
298 }
299
300 static HRESULT WINAPI d3d_texture1_QueryInterface(IDirect3DTexture *iface, REFIID riid, void **object)
301 {
302 struct ddraw_surface *surface = impl_from_IDirect3DTexture(iface);
303
304 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
305
306 return ddraw_surface7_QueryInterface(&surface->IDirectDrawSurface7_iface, riid, object);
307 }
308
309 static void ddraw_surface_add_iface(struct ddraw_surface *surface)
310 {
311 ULONG iface_count = InterlockedIncrement(&surface->iface_count);
312 TRACE("%p increasing iface count to %u.\n", surface, iface_count);
313
314 if (iface_count == 1)
315 {
316 if (surface->ifaceToRelease)
317 IUnknown_AddRef(surface->ifaceToRelease);
318 wined3d_mutex_lock();
319 if (surface->wined3d_rtv)
320 wined3d_rendertarget_view_incref(surface->wined3d_rtv);
321 wined3d_texture_incref(surface->wined3d_texture);
322 wined3d_mutex_unlock();
323 }
324 }
325
326 /*****************************************************************************
327 * IDirectDrawSurface7::AddRef
328 *
329 * A normal addref implementation
330 *
331 * Returns:
332 * The new refcount
333 *
334 *****************************************************************************/
335 static ULONG WINAPI ddraw_surface7_AddRef(IDirectDrawSurface7 *iface)
336 {
337 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
338 ULONG refcount = InterlockedIncrement(&This->ref7);
339
340 TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
341
342 if (refcount == 1)
343 {
344 ddraw_surface_add_iface(This);
345 }
346
347 return refcount;
348 }
349
350 static ULONG WINAPI ddraw_surface4_AddRef(IDirectDrawSurface4 *iface)
351 {
352 struct ddraw_surface *This = impl_from_IDirectDrawSurface4(iface);
353 ULONG refcount = InterlockedIncrement(&This->ref4);
354
355 TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
356
357 if (refcount == 1)
358 {
359 ddraw_surface_add_iface(This);
360 }
361
362 return refcount;
363 }
364
365 static ULONG WINAPI ddraw_surface3_AddRef(IDirectDrawSurface3 *iface)
366 {
367 struct ddraw_surface *This = impl_from_IDirectDrawSurface3(iface);
368 ULONG refcount = InterlockedIncrement(&This->ref3);
369
370 TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
371
372 if (refcount == 1)
373 {
374 ddraw_surface_add_iface(This);
375 }
376
377 return refcount;
378 }
379
380 static ULONG WINAPI ddraw_surface2_AddRef(IDirectDrawSurface2 *iface)
381 {
382 struct ddraw_surface *This = impl_from_IDirectDrawSurface2(iface);
383 ULONG refcount = InterlockedIncrement(&This->ref2);
384
385 TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
386
387 if (refcount == 1)
388 {
389 ddraw_surface_add_iface(This);
390 }
391
392 return refcount;
393 }
394
395 static ULONG WINAPI ddraw_surface1_AddRef(IDirectDrawSurface *iface)
396 {
397 struct ddraw_surface *This = impl_from_IDirectDrawSurface(iface);
398 ULONG refcount = InterlockedIncrement(&This->ref1);
399
400 TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
401
402 if (refcount == 1)
403 {
404 ddraw_surface_add_iface(This);
405 }
406
407 return refcount;
408 }
409
410 static ULONG WINAPI ddraw_gamma_control_AddRef(IDirectDrawGammaControl *iface)
411 {
412 struct ddraw_surface *This = impl_from_IDirectDrawGammaControl(iface);
413 ULONG refcount = InterlockedIncrement(&This->gamma_count);
414
415 TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
416
417 if (refcount == 1)
418 {
419 ddraw_surface_add_iface(This);
420 }
421
422 return refcount;
423 }
424
425 static ULONG WINAPI d3d_texture2_AddRef(IDirect3DTexture2 *iface)
426 {
427 struct ddraw_surface *surface = impl_from_IDirect3DTexture2(iface);
428
429 TRACE("iface %p.\n", iface);
430
431 return IUnknown_AddRef(surface->texture_outer);
432 }
433
434 static ULONG WINAPI d3d_texture1_AddRef(IDirect3DTexture *iface)
435 {
436 struct ddraw_surface *surface = impl_from_IDirect3DTexture(iface);
437
438 TRACE("iface %p.\n", iface);
439
440 return IUnknown_AddRef(surface->texture_outer);
441 }
442
443 static HRESULT ddraw_surface_set_palette(struct ddraw_surface *surface, IDirectDrawPalette *palette)
444 {
445 struct ddraw_palette *palette_impl = unsafe_impl_from_IDirectDrawPalette(palette);
446 struct ddraw_palette *prev;
447
448 TRACE("iface %p, palette %p.\n", surface, palette);
449
450 if (palette_impl && palette_impl->flags & DDPCAPS_ALPHA
451 && !(surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE))
452 {
453 WARN("Alpha palette set on non-texture surface, returning DDERR_INVALIDSURFACETYPE.\n");
454 return DDERR_INVALIDSURFACETYPE;
455 }
456
457 if (!format_is_paletteindexed(&surface->surface_desc.u4.ddpfPixelFormat))
458 return DDERR_INVALIDPIXELFORMAT;
459
460 wined3d_mutex_lock();
461
462 prev = surface->palette;
463 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
464 {
465 if (prev)
466 prev->flags &= ~DDPCAPS_PRIMARYSURFACE;
467 if (palette_impl)
468 palette_impl->flags |= DDPCAPS_PRIMARYSURFACE;
469 wined3d_swapchain_set_palette(surface->ddraw->wined3d_swapchain,
470 palette_impl ? palette_impl->wineD3DPalette : NULL);
471 ddraw_surface_update_frontbuffer(surface, NULL, FALSE);
472 }
473 if (palette_impl)
474 IDirectDrawPalette_AddRef(&palette_impl->IDirectDrawPalette_iface);
475 if (prev)
476 IDirectDrawPalette_Release(&prev->IDirectDrawPalette_iface);
477 surface->palette = palette_impl;
478
479 wined3d_mutex_unlock();
480
481 return DD_OK;
482 }
483
484 static void ddraw_surface_cleanup(struct ddraw_surface *surface)
485 {
486 struct ddraw_surface *surf;
487 UINT i;
488
489 TRACE("surface %p.\n", surface);
490
491 /* The refcount test shows that the palette is detached when the surface
492 * is destroyed. */
493 ddraw_surface_set_palette(surface, NULL);
494
495 /* Loop through all complex attached surfaces and destroy them.
496 *
497 * Yet again, only the root can have more than one complexly attached
498 * surface, all the others have a total of one. */
499 for (i = 0; i < MAX_COMPLEX_ATTACHED; ++i)
500 {
501 if (!surface->complex_array[i])
502 break;
503
504 surf = surface->complex_array[i];
505 surface->complex_array[i] = NULL;
506 if (!surf->is_complex_root)
507 ddraw_surface_cleanup(surf);
508 }
509
510 if (surface->device1)
511 IUnknown_Release(&surface->device1->IUnknown_inner);
512
513 if (surface->iface_count > 1)
514 {
515 /* This can happen when a complex surface is destroyed, because the
516 * 2nd surface was addref()ed when the app called
517 * GetAttachedSurface(). */
518 WARN("Destroying surface %p with refcounts 7: %u 4: %u 3: %u 2: %u 1: %u.\n",
519 surface, surface->ref7, surface->ref4, surface->ref3, surface->ref2, surface->ref1);
520 }
521
522 if (surface->wined3d_rtv)
523 wined3d_rendertarget_view_decref(surface->wined3d_rtv);
524 wined3d_texture_decref(surface->wined3d_texture);
525 }
526
527 ULONG ddraw_surface_release_iface(struct ddraw_surface *This)
528 {
529 ULONG iface_count = InterlockedDecrement(&This->iface_count);
530 TRACE("%p decreasing iface count to %u.\n", This, iface_count);
531
532 if (iface_count == 0)
533 {
534 IUnknown *release_iface = This->ifaceToRelease;
535
536 /* Complex attached surfaces are destroyed implicitly when the root is released */
537 wined3d_mutex_lock();
538 if(!This->is_complex_root)
539 {
540 WARN("(%p) Attempt to destroy a surface that is not a complex root\n", This);
541 wined3d_mutex_unlock();
542 return iface_count;
543 }
544 ddraw_surface_cleanup(This);
545 wined3d_mutex_unlock();
546
547 if (release_iface)
548 IUnknown_Release(release_iface);
549 }
550
551 return iface_count;
552 }
553
554 /*****************************************************************************
555 * IDirectDrawSurface7::Release
556 *
557 * Reduces the surface's refcount by 1. If the refcount falls to 0, the
558 * surface is destroyed.
559 *
560 * Destroying the surface is a bit tricky. For the connection between
561 * WineD3DSurfaces and DirectDrawSurfaces see IDirectDraw7::CreateSurface
562 * It has a nice graph explaining the connection.
563 *
564 * What happens here is basically this:
565 * When a surface is destroyed, its WineD3DSurface is released,
566 * and the refcount of the DirectDraw interface is reduced by 1. If it has
567 * complex surfaces attached to it, then these surfaces are destroyed too,
568 * regardless of their refcount. If any surface being destroyed has another
569 * surface attached to it (with a "soft" attachment, not complex), then
570 * this surface is detached with DeleteAttachedSurface.
571 *
572 * When the surface is a texture, the WineD3DTexture is released.
573 * If the surface is the Direct3D render target, then the D3D
574 * capabilities of the WineD3DDevice are uninitialized, which causes the
575 * swapchain to be released.
576 *
577 * When a complex sublevel falls to ref zero, then this is ignored.
578 *
579 * Returns:
580 * The new refcount
581 *
582 *****************************************************************************/
583 static ULONG WINAPI ddraw_surface7_Release(IDirectDrawSurface7 *iface)
584 {
585 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
586 ULONG refcount = InterlockedDecrement(&This->ref7);
587
588 TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
589
590 if (refcount == 0)
591 {
592 ddraw_surface_release_iface(This);
593 }
594
595 return refcount;
596 }
597
598 static ULONG WINAPI ddraw_surface4_Release(IDirectDrawSurface4 *iface)
599 {
600 struct ddraw_surface *This = impl_from_IDirectDrawSurface4(iface);
601 ULONG refcount = InterlockedDecrement(&This->ref4);
602
603 TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
604
605 if (refcount == 0)
606 {
607 ddraw_surface_release_iface(This);
608 }
609
610 return refcount;
611 }
612
613 static ULONG WINAPI ddraw_surface3_Release(IDirectDrawSurface3 *iface)
614 {
615 struct ddraw_surface *This = impl_from_IDirectDrawSurface3(iface);
616 ULONG refcount = InterlockedDecrement(&This->ref3);
617
618 TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
619
620 if (refcount == 0)
621 {
622 ddraw_surface_release_iface(This);
623 }
624
625 return refcount;
626 }
627
628 static ULONG WINAPI ddraw_surface2_Release(IDirectDrawSurface2 *iface)
629 {
630 struct ddraw_surface *This = impl_from_IDirectDrawSurface2(iface);
631 ULONG refcount = InterlockedDecrement(&This->ref2);
632
633 TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
634
635 if (refcount == 0)
636 {
637 ddraw_surface_release_iface(This);
638 }
639
640 return refcount;
641 }
642
643 static ULONG WINAPI ddraw_surface1_Release(IDirectDrawSurface *iface)
644 {
645 struct ddraw_surface *This = impl_from_IDirectDrawSurface(iface);
646 ULONG refcount = InterlockedDecrement(&This->ref1);
647
648 TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
649
650 if (refcount == 0)
651 {
652 ddraw_surface_release_iface(This);
653 }
654
655 return refcount;
656 }
657
658 static ULONG WINAPI ddraw_gamma_control_Release(IDirectDrawGammaControl *iface)
659 {
660 struct ddraw_surface *This = impl_from_IDirectDrawGammaControl(iface);
661 ULONG refcount = InterlockedDecrement(&This->gamma_count);
662
663 TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
664
665 if (refcount == 0)
666 {
667 ddraw_surface_release_iface(This);
668 }
669
670 return refcount;
671 }
672
673 static ULONG WINAPI d3d_texture2_Release(IDirect3DTexture2 *iface)
674 {
675 struct ddraw_surface *surface = impl_from_IDirect3DTexture2(iface);
676
677 TRACE("iface %p.\n", iface);
678
679 return IUnknown_Release(surface->texture_outer);
680 }
681
682 static ULONG WINAPI d3d_texture1_Release(IDirect3DTexture *iface)
683 {
684 struct ddraw_surface *surface = impl_from_IDirect3DTexture(iface);
685
686 TRACE("iface %p.\n", iface);
687
688 return IUnknown_Release(surface->texture_outer);
689 }
690
691 /*****************************************************************************
692 * IDirectDrawSurface7::GetAttachedSurface
693 *
694 * Returns an attached surface with the requested caps. Surface attachment
695 * and complex surfaces are not clearly described by the MSDN or sdk,
696 * so this method is tricky and likely to contain problems.
697 * This implementation searches the complex list first, then the
698 * attachment chain.
699 *
700 * The chains are searched from This down to the last surface in the chain,
701 * not from the first element in the chain. The first surface found is
702 * returned. The MSDN says that this method fails if more than one surface
703 * matches the caps, but it is not sure if that is right. The attachment
704 * structure may not even allow two matching surfaces.
705 *
706 * The found surface is AddRef-ed before it is returned.
707 *
708 * Params:
709 * Caps: Pointer to a DDCAPS2 structure describing the caps asked for
710 * Surface: Address to store the found surface
711 *
712 * Returns:
713 * DD_OK on success
714 * DDERR_INVALIDPARAMS if Caps or Surface is NULL
715 * DDERR_NOTFOUND if no surface was found
716 *
717 *****************************************************************************/
718 static HRESULT WINAPI ddraw_surface7_GetAttachedSurface(IDirectDrawSurface7 *iface,
719 DDSCAPS2 *Caps, IDirectDrawSurface7 **Surface)
720 {
721 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
722 struct ddraw_surface *surf;
723 DDSCAPS2 our_caps;
724 int i;
725
726 TRACE("iface %p, caps %p, attachment %p.\n", iface, Caps, Surface);
727
728 wined3d_mutex_lock();
729
730 if(This->version < 7)
731 {
732 /* Earlier dx apps put garbage into these members, clear them */
733 our_caps.dwCaps = Caps->dwCaps;
734 our_caps.dwCaps2 = 0;
735 our_caps.dwCaps3 = 0;
736 our_caps.u1.dwCaps4 = 0;
737 }
738 else
739 {
740 our_caps = *Caps;
741 }
742
743 TRACE("(%p): Looking for caps: %x,%x,%x,%x\n", This, our_caps.dwCaps, our_caps.dwCaps2, our_caps.dwCaps3, our_caps.u1.dwCaps4); /* FIXME: Better debugging */
744
745 for(i = 0; i < MAX_COMPLEX_ATTACHED; i++)
746 {
747 surf = This->complex_array[i];
748 if(!surf) break;
749
750 TRACE("Surface: (%p) caps: %#x, %#x, %#x, %#x.\n", surf,
751 surf->surface_desc.ddsCaps.dwCaps,
752 surf->surface_desc.ddsCaps.dwCaps2,
753 surf->surface_desc.ddsCaps.dwCaps3,
754 surf->surface_desc.ddsCaps.u1.dwCaps4);
755
756 if (((surf->surface_desc.ddsCaps.dwCaps & our_caps.dwCaps) == our_caps.dwCaps) &&
757 ((surf->surface_desc.ddsCaps.dwCaps2 & our_caps.dwCaps2) == our_caps.dwCaps2)) {
758
759 /* MSDN: "This method fails if more than one surface is attached
760 * that matches the capabilities requested."
761 *
762 * Not sure how to test this.
763 */
764
765 TRACE("(%p): Returning surface %p\n", This, surf);
766 *Surface = &surf->IDirectDrawSurface7_iface;
767 ddraw_surface7_AddRef(*Surface);
768 wined3d_mutex_unlock();
769
770 return DD_OK;
771 }
772 }
773
774 /* Next, look at the attachment chain */
775 surf = This;
776
777 while( (surf = surf->next_attached) )
778 {
779 TRACE("Surface: (%p) caps: %#x, %#x, %#x, %#x.\n", surf,
780 surf->surface_desc.ddsCaps.dwCaps,
781 surf->surface_desc.ddsCaps.dwCaps2,
782 surf->surface_desc.ddsCaps.dwCaps3,
783 surf->surface_desc.ddsCaps.u1.dwCaps4);
784
785 if (((surf->surface_desc.ddsCaps.dwCaps & our_caps.dwCaps) == our_caps.dwCaps) &&
786 ((surf->surface_desc.ddsCaps.dwCaps2 & our_caps.dwCaps2) == our_caps.dwCaps2)) {
787
788 TRACE("(%p): Returning surface %p\n", This, surf);
789 *Surface = &surf->IDirectDrawSurface7_iface;
790 ddraw_surface7_AddRef(*Surface);
791 wined3d_mutex_unlock();
792 return DD_OK;
793 }
794 }
795
796 TRACE("(%p) Didn't find a valid surface\n", This);
797
798 wined3d_mutex_unlock();
799
800 *Surface = NULL;
801 return DDERR_NOTFOUND;
802 }
803
804 static HRESULT WINAPI ddraw_surface4_GetAttachedSurface(IDirectDrawSurface4 *iface,
805 DDSCAPS2 *caps, IDirectDrawSurface4 **attachment)
806 {
807 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
808 struct ddraw_surface *attachment_impl;
809 IDirectDrawSurface7 *attachment7;
810 HRESULT hr;
811
812 TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, attachment);
813
814 hr = ddraw_surface7_GetAttachedSurface(&surface->IDirectDrawSurface7_iface,
815 caps, &attachment7);
816 if (FAILED(hr))
817 {
818 *attachment = NULL;
819 return hr;
820 }
821 attachment_impl = impl_from_IDirectDrawSurface7(attachment7);
822 *attachment = &attachment_impl->IDirectDrawSurface4_iface;
823 ddraw_surface4_AddRef(*attachment);
824 ddraw_surface7_Release(attachment7);
825
826 return hr;
827 }
828
829 static HRESULT WINAPI ddraw_surface3_GetAttachedSurface(IDirectDrawSurface3 *iface,
830 DDSCAPS *caps, IDirectDrawSurface3 **attachment)
831 {
832 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
833 struct ddraw_surface *attachment_impl;
834 IDirectDrawSurface7 *attachment7;
835 DDSCAPS2 caps2;
836 HRESULT hr;
837
838 TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, attachment);
839
840 caps2.dwCaps = caps->dwCaps;
841 caps2.dwCaps2 = 0;
842 caps2.dwCaps3 = 0;
843 caps2.u1.dwCaps4 = 0;
844
845 hr = ddraw_surface7_GetAttachedSurface(&surface->IDirectDrawSurface7_iface,
846 &caps2, &attachment7);
847 if (FAILED(hr))
848 {
849 *attachment = NULL;
850 return hr;
851 }
852 attachment_impl = impl_from_IDirectDrawSurface7(attachment7);
853 *attachment = &attachment_impl->IDirectDrawSurface3_iface;
854 ddraw_surface3_AddRef(*attachment);
855 ddraw_surface7_Release(attachment7);
856
857 return hr;
858 }
859
860 static HRESULT WINAPI ddraw_surface2_GetAttachedSurface(IDirectDrawSurface2 *iface,
861 DDSCAPS *caps, IDirectDrawSurface2 **attachment)
862 {
863 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
864 struct ddraw_surface *attachment_impl;
865 IDirectDrawSurface7 *attachment7;
866 DDSCAPS2 caps2;
867 HRESULT hr;
868
869 TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, attachment);
870
871 caps2.dwCaps = caps->dwCaps;
872 caps2.dwCaps2 = 0;
873 caps2.dwCaps3 = 0;
874 caps2.u1.dwCaps4 = 0;
875
876 hr = ddraw_surface7_GetAttachedSurface(&surface->IDirectDrawSurface7_iface,
877 &caps2, &attachment7);
878 if (FAILED(hr))
879 {
880 *attachment = NULL;
881 return hr;
882 }
883 attachment_impl = impl_from_IDirectDrawSurface7(attachment7);
884 *attachment = &attachment_impl->IDirectDrawSurface2_iface;
885 ddraw_surface2_AddRef(*attachment);
886 ddraw_surface7_Release(attachment7);
887
888 return hr;
889 }
890
891 static HRESULT WINAPI ddraw_surface1_GetAttachedSurface(IDirectDrawSurface *iface,
892 DDSCAPS *caps, IDirectDrawSurface **attachment)
893 {
894 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
895 struct ddraw_surface *attachment_impl;
896 IDirectDrawSurface7 *attachment7;
897 DDSCAPS2 caps2;
898 HRESULT hr;
899
900 TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, attachment);
901
902 caps2.dwCaps = caps->dwCaps;
903 caps2.dwCaps2 = 0;
904 caps2.dwCaps3 = 0;
905 caps2.u1.dwCaps4 = 0;
906
907 hr = ddraw_surface7_GetAttachedSurface(&surface->IDirectDrawSurface7_iface,
908 &caps2, &attachment7);
909 if (FAILED(hr))
910 {
911 *attachment = NULL;
912 return hr;
913 }
914 attachment_impl = impl_from_IDirectDrawSurface7(attachment7);
915 *attachment = &attachment_impl->IDirectDrawSurface_iface;
916 ddraw_surface1_AddRef(*attachment);
917 ddraw_surface7_Release(attachment7);
918
919 return hr;
920 }
921
922 /*****************************************************************************
923 * IDirectDrawSurface7::Lock
924 *
925 * Locks the surface and returns a pointer to the surface's memory
926 *
927 * Params:
928 * Rect: Rectangle to lock. If NULL, the whole surface is locked
929 * DDSD: Pointer to a DDSURFACEDESC2 which shall receive the surface's desc.
930 * Flags: Locking flags, e.g Read only or write only
931 * h: An event handle that's not used and must be NULL
932 *
933 * Returns:
934 * DD_OK on success
935 * DDERR_INVALIDPARAMS if DDSD is NULL
936 * For more details, see IWineD3DSurface::LockRect
937 *
938 *****************************************************************************/
939 static HRESULT surface_lock(struct ddraw_surface *surface,
940 RECT *rect, DDSURFACEDESC2 *surface_desc, DWORD flags, HANDLE h)
941 {
942 struct wined3d_box box;
943 struct wined3d_map_desc map_desc;
944 HRESULT hr = DD_OK;
945
946 TRACE("surface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
947 surface, wine_dbgstr_rect(rect), surface_desc, flags, h);
948
949 /* surface->surface_desc.dwWidth and dwHeight are changeable, thus lock */
950 wined3d_mutex_lock();
951
952 /* Should I check for the handle to be NULL?
953 *
954 * The DDLOCK flags and the D3DLOCK flags are equal
955 * for the supported values. The others are ignored by WineD3D
956 */
957
958 /* Windows zeroes this if the rect is invalid */
959 surface_desc->lpSurface = NULL;
960
961 if (rect)
962 {
963 if ((rect->left < 0) || (rect->top < 0)
964 || (rect->left > rect->right) || (rect->right > surface->surface_desc.dwWidth)
965 || (rect->top > rect->bottom) || (rect->bottom > surface->surface_desc.dwHeight))
966 {
967 WARN("Trying to lock an invalid rectangle, returning DDERR_INVALIDPARAMS\n");
968 wined3d_mutex_unlock();
969 return DDERR_INVALIDPARAMS;
970 }
971 box.left = rect->left;
972 box.top = rect->top;
973 box.right = rect->right;
974 box.bottom = rect->bottom;
975 box.front = 0;
976 box.back = 1;
977 }
978
979 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
980 hr = ddraw_surface_update_frontbuffer(surface, rect, TRUE);
981 if (SUCCEEDED(hr))
982 hr = wined3d_resource_sub_resource_map(wined3d_texture_get_resource(surface->wined3d_texture),
983 surface->sub_resource_idx, &map_desc, rect ? &box : NULL, flags);
984 if (FAILED(hr))
985 {
986 wined3d_mutex_unlock();
987 switch(hr)
988 {
989 /* D3D8 and D3D9 return the general D3DERR_INVALIDCALL error, but ddraw has a more
990 * specific error. But since IWineD3DSurface::LockRect returns that error in this
991 * only occasion, keep d3d8 and d3d9 free from the return value override. There are
992 * many different places where d3d8/9 would have to catch the DDERR_SURFACEBUSY, it
993 * is much easier to do it in one place in ddraw
994 */
995 case WINED3DERR_INVALIDCALL: return DDERR_SURFACEBUSY;
996 default: return hr;
997 }
998 }
999
1000 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1001 {
1002 if (flags & DDLOCK_READONLY)
1003 memset(&surface->ddraw->primary_lock, 0, sizeof(surface->ddraw->primary_lock));
1004 else if (rect)
1005 surface->ddraw->primary_lock = *rect;
1006 else
1007 SetRect(&surface->ddraw->primary_lock, 0, 0, surface->surface_desc.dwWidth, surface->surface_desc.dwHeight);
1008 }
1009
1010 /* Windows does not set DDSD_LPSURFACE on locked surfaces. */
1011 DD_STRUCT_COPY_BYSIZE(surface_desc, &surface->surface_desc);
1012 surface_desc->lpSurface = map_desc.data;
1013
1014 TRACE("locked surface returning description :\n");
1015 if (TRACE_ON(ddraw))
1016 DDRAW_dump_surface_desc(surface_desc);
1017
1018 wined3d_mutex_unlock();
1019
1020 return DD_OK;
1021 }
1022
1023 static HRESULT WINAPI ddraw_surface7_Lock(IDirectDrawSurface7 *iface,
1024 RECT *rect, DDSURFACEDESC2 *surface_desc, DWORD flags, HANDLE h)
1025 {
1026 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
1027
1028 TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
1029 iface, wine_dbgstr_rect(rect), surface_desc, flags, h);
1030
1031 if (!surface_desc) return DDERR_INVALIDPARAMS;
1032 if (surface_desc->dwSize != sizeof(DDSURFACEDESC) &&
1033 surface_desc->dwSize != sizeof(DDSURFACEDESC2))
1034 {
1035 WARN("Invalid structure size %d, returning DDERR_INVALIDPARAMS\n", surface_desc->dwSize);
1036 return DDERR_INVALIDPARAMS;
1037 }
1038 return surface_lock(surface, rect, surface_desc, flags, h);
1039 }
1040
1041 static HRESULT WINAPI ddraw_surface4_Lock(IDirectDrawSurface4 *iface, RECT *rect,
1042 DDSURFACEDESC2 *surface_desc, DWORD flags, HANDLE h)
1043 {
1044 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
1045
1046 TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
1047 iface, wine_dbgstr_rect(rect), surface_desc, flags, h);
1048
1049 if (!surface_desc) return DDERR_INVALIDPARAMS;
1050 if (surface_desc->dwSize != sizeof(DDSURFACEDESC) &&
1051 surface_desc->dwSize != sizeof(DDSURFACEDESC2))
1052 {
1053 WARN("Invalid structure size %d, returning DDERR_INVALIDPARAMS\n", surface_desc->dwSize);
1054 return DDERR_INVALIDPARAMS;
1055 }
1056 return surface_lock(surface, rect, surface_desc, flags, h);
1057 }
1058
1059 static HRESULT WINAPI ddraw_surface3_Lock(IDirectDrawSurface3 *iface, RECT *rect,
1060 DDSURFACEDESC *surface_desc, DWORD flags, HANDLE h)
1061 {
1062 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
1063 DDSURFACEDESC2 surface_desc2;
1064 HRESULT hr;
1065
1066 TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
1067 iface, wine_dbgstr_rect(rect), surface_desc, flags, h);
1068
1069 if (!surface_desc) return DDERR_INVALIDPARAMS;
1070 if (surface_desc->dwSize != sizeof(DDSURFACEDESC) &&
1071 surface_desc->dwSize != sizeof(DDSURFACEDESC2))
1072 {
1073 WARN("Invalid structure size %d, returning DDERR_INVALIDPARAMS\n", surface_desc->dwSize);
1074 return DDERR_INVALIDPARAMS;
1075 }
1076
1077 surface_desc2.dwSize = surface_desc->dwSize;
1078 surface_desc2.dwFlags = 0;
1079 hr = surface_lock(surface, rect, &surface_desc2, flags, h);
1080 DDSD2_to_DDSD(&surface_desc2, surface_desc);
1081 surface_desc->dwSize = surface_desc2.dwSize;
1082 return hr;
1083 }
1084
1085 static HRESULT WINAPI ddraw_surface2_Lock(IDirectDrawSurface2 *iface, RECT *rect,
1086 DDSURFACEDESC *surface_desc, DWORD flags, HANDLE h)
1087 {
1088 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
1089 DDSURFACEDESC2 surface_desc2;
1090 HRESULT hr;
1091
1092 TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
1093 iface, wine_dbgstr_rect(rect), surface_desc, flags, h);
1094
1095 if (!surface_desc) return DDERR_INVALIDPARAMS;
1096 if (surface_desc->dwSize != sizeof(DDSURFACEDESC) &&
1097 surface_desc->dwSize != sizeof(DDSURFACEDESC2))
1098 {
1099 WARN("Invalid structure size %d, returning DDERR_INVALIDPARAMS\n", surface_desc->dwSize);
1100 return DDERR_INVALIDPARAMS;
1101 }
1102
1103 surface_desc2.dwSize = surface_desc->dwSize;
1104 surface_desc2.dwFlags = 0;
1105 hr = surface_lock(surface, rect, &surface_desc2, flags, h);
1106 DDSD2_to_DDSD(&surface_desc2, surface_desc);
1107 surface_desc->dwSize = surface_desc2.dwSize;
1108 return hr;
1109 }
1110
1111 static HRESULT WINAPI ddraw_surface1_Lock(IDirectDrawSurface *iface, RECT *rect,
1112 DDSURFACEDESC *surface_desc, DWORD flags, HANDLE h)
1113 {
1114 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
1115 DDSURFACEDESC2 surface_desc2;
1116 HRESULT hr;
1117 TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
1118 iface, wine_dbgstr_rect(rect), surface_desc, flags, h);
1119
1120 if (!surface_desc) return DDERR_INVALIDPARAMS;
1121 if (surface_desc->dwSize != sizeof(DDSURFACEDESC) &&
1122 surface_desc->dwSize != sizeof(DDSURFACEDESC2))
1123 {
1124 WARN("Invalid structure size %d, returning DDERR_INVALIDPARAMS\n", surface_desc->dwSize);
1125 return DDERR_INVALIDPARAMS;
1126 }
1127
1128 surface_desc2.dwSize = surface_desc->dwSize;
1129 surface_desc2.dwFlags = 0;
1130 hr = surface_lock(surface, rect, &surface_desc2, flags, h);
1131 DDSD2_to_DDSD(&surface_desc2, surface_desc);
1132 surface_desc->dwSize = surface_desc2.dwSize;
1133 return hr;
1134 }
1135
1136 /*****************************************************************************
1137 * IDirectDrawSurface7::Unlock
1138 *
1139 * Unlocks an locked surface
1140 *
1141 * Params:
1142 * Rect: Not used by this implementation
1143 *
1144 * Returns:
1145 * D3D_OK on success
1146 * For more details, see IWineD3DSurface::UnlockRect
1147 *
1148 *****************************************************************************/
1149 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_Unlock(IDirectDrawSurface7 *iface, RECT *pRect)
1150 {
1151 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
1152 HRESULT hr;
1153
1154 TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(pRect));
1155
1156 wined3d_mutex_lock();
1157 hr = wined3d_resource_sub_resource_unmap(wined3d_texture_get_resource(surface->wined3d_texture), surface->sub_resource_idx);
1158 if (SUCCEEDED(hr) && surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1159 hr = ddraw_surface_update_frontbuffer(surface, &surface->ddraw->primary_lock, FALSE);
1160 wined3d_mutex_unlock();
1161
1162 return hr;
1163 }
1164
1165 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface4_Unlock(IDirectDrawSurface4 *iface, RECT *pRect)
1166 {
1167 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
1168
1169 TRACE("iface %p, rect %p.\n", iface, pRect);
1170
1171 return ddraw_surface7_Unlock(&surface->IDirectDrawSurface7_iface, pRect);
1172 }
1173
1174 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface3_Unlock(IDirectDrawSurface3 *iface, void *data)
1175 {
1176 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
1177
1178 TRACE("iface %p, data %p.\n", iface, data);
1179
1180 /* data might not be the LPRECT of later versions, so drop it. */
1181 return ddraw_surface7_Unlock(&surface->IDirectDrawSurface7_iface, NULL);
1182 }
1183
1184 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface2_Unlock(IDirectDrawSurface2 *iface, void *data)
1185 {
1186 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
1187
1188 TRACE("iface %p, data %p.\n", iface, data);
1189
1190 /* data might not be the LPRECT of later versions, so drop it. */
1191 return ddraw_surface7_Unlock(&surface->IDirectDrawSurface7_iface, NULL);
1192 }
1193
1194 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_Unlock(IDirectDrawSurface *iface, void *data)
1195 {
1196 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
1197
1198 TRACE("iface %p, data %p.\n", iface, data);
1199
1200 /* data might not be the LPRECT of later versions, so drop it. */
1201 return ddraw_surface7_Unlock(&surface->IDirectDrawSurface7_iface, NULL);
1202 }
1203
1204 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_Flip(IDirectDrawSurface7 *iface,
1205 IDirectDrawSurface7 *src, DWORD flags)
1206 {
1207 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface7(iface);
1208 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface7(src);
1209 struct wined3d_rendertarget_view *tmp_rtv, *src_rtv, *rtv;
1210 struct ddraw_texture *ddraw_texture, *prev_ddraw_texture;
1211 DDSCAPS2 caps = {DDSCAPS_FLIP, 0, 0, {0}};
1212 struct wined3d_texture *texture;
1213 IDirectDrawSurface7 *current;
1214 HRESULT hr;
1215
1216 TRACE("iface %p, src %p, flags %#x.\n", iface, src, flags);
1217
1218 if (src == iface || !(dst_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_OVERLAY)))
1219 return DDERR_NOTFLIPPABLE;
1220
1221 if (IDirectDrawSurface7_IsLost(iface) == DDERR_SURFACELOST)
1222 return DDERR_SURFACELOST;
1223
1224 wined3d_mutex_lock();
1225
1226 if (!(dst_impl->ddraw->cooperative_level & DDSCL_EXCLUSIVE))
1227 {
1228 WARN("Not in exclusive mode.\n");
1229 wined3d_mutex_unlock();
1230 return DDERR_NOEXCLUSIVEMODE;
1231 }
1232
1233 tmp_rtv = ddraw_surface_get_rendertarget_view(dst_impl);
1234 if (dst_impl->sub_resource_idx)
1235 ERR("Invalid sub-resource index %u on surface %p.\n", dst_impl->sub_resource_idx, dst_impl);
1236 texture = dst_impl->wined3d_texture;
1237 rtv = wined3d_device_get_rendertarget_view(dst_impl->ddraw->wined3d_device, 0);
1238 ddraw_texture = wined3d_texture_get_parent(dst_impl->wined3d_texture);
1239
1240 if (src_impl)
1241 {
1242 for (current = iface; current != src;)
1243 {
1244 if (FAILED(hr = ddraw_surface7_GetAttachedSurface(current, &caps, &current)))
1245 {
1246 WARN("Surface %p is not on the same flip chain as surface %p.\n", src, iface);
1247 wined3d_mutex_unlock();
1248 return DDERR_NOTFLIPPABLE;
1249 }
1250 ddraw_surface7_Release(current);
1251 if (current == iface)
1252 {
1253 WARN("Surface %p is not on the same flip chain as surface %p.\n", src, iface);
1254 wined3d_mutex_unlock();
1255 return DDERR_NOTFLIPPABLE;
1256 }
1257 }
1258
1259 src_rtv = ddraw_surface_get_rendertarget_view(src_impl);
1260 if (rtv == dst_impl->wined3d_rtv)
1261 wined3d_device_set_rendertarget_view(dst_impl->ddraw->wined3d_device, 0, src_rtv, FALSE);
1262 wined3d_rendertarget_view_set_parent(src_rtv, dst_impl);
1263 dst_impl->wined3d_rtv = src_rtv;
1264 wined3d_resource_set_parent(wined3d_texture_get_sub_resource(src_impl->wined3d_texture, 0), dst_impl);
1265 prev_ddraw_texture = wined3d_texture_get_parent(src_impl->wined3d_texture);
1266 wined3d_resource_set_parent(wined3d_texture_get_resource(src_impl->wined3d_texture), ddraw_texture);
1267 if (src_impl->sub_resource_idx)
1268 ERR("Invalid sub-resource index %u on surface %p.\n", src_impl->sub_resource_idx, src_impl);
1269 dst_impl->wined3d_texture = src_impl->wined3d_texture;
1270 ddraw_texture = prev_ddraw_texture;
1271 }
1272 else
1273 {
1274 for (current = iface;;)
1275 {
1276 if (FAILED(hr = ddraw_surface7_GetAttachedSurface(current, &caps, &current)))
1277 {
1278 ERR("Can't find a flip target\n");
1279 wined3d_mutex_unlock();
1280 return DDERR_NOTFLIPPABLE; /* Unchecked */
1281 }
1282 ddraw_surface7_Release(current);
1283 if (current == iface)
1284 {
1285 dst_impl = impl_from_IDirectDrawSurface7(iface);
1286 break;
1287 }
1288
1289 src_impl = impl_from_IDirectDrawSurface7(current);
1290 src_rtv = ddraw_surface_get_rendertarget_view(src_impl);
1291 if (rtv == dst_impl->wined3d_rtv)
1292 wined3d_device_set_rendertarget_view(dst_impl->ddraw->wined3d_device, 0, src_rtv, FALSE);
1293 wined3d_rendertarget_view_set_parent(src_rtv, dst_impl);
1294 dst_impl->wined3d_rtv = src_rtv;
1295 wined3d_resource_set_parent(wined3d_texture_get_sub_resource(src_impl->wined3d_texture, 0), dst_impl);
1296 prev_ddraw_texture = wined3d_texture_get_parent(src_impl->wined3d_texture);
1297 wined3d_resource_set_parent(wined3d_texture_get_resource(src_impl->wined3d_texture), ddraw_texture);
1298 ddraw_texture = prev_ddraw_texture;
1299 if (src_impl->sub_resource_idx)
1300 ERR("Invalid sub-resource index %u on surface %p.\n", src_impl->sub_resource_idx, src_impl);
1301 dst_impl->wined3d_texture = src_impl->wined3d_texture;
1302 dst_impl = src_impl;
1303 }
1304 }
1305
1306 /* We don't have to worry about potential texture bindings, since
1307 * flippable surfaces can never be textures. */
1308 if (rtv == src_impl->wined3d_rtv)
1309 wined3d_device_set_rendertarget_view(dst_impl->ddraw->wined3d_device, 0, tmp_rtv, FALSE);
1310 wined3d_rendertarget_view_set_parent(tmp_rtv, src_impl);
1311 src_impl->wined3d_rtv = tmp_rtv;
1312 wined3d_resource_set_parent(wined3d_texture_get_sub_resource(texture, 0), src_impl);
1313 wined3d_resource_set_parent(wined3d_texture_get_resource(texture), ddraw_texture);
1314 src_impl->wined3d_texture = texture;
1315
1316 if (flags)
1317 {
1318 static UINT once;
1319 if (!once++)
1320 FIXME("Ignoring flags %#x.\n", flags);
1321 else
1322 WARN("Ignoring flags %#x.\n", flags);
1323 }
1324
1325 if (dst_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1326 hr = ddraw_surface_update_frontbuffer(dst_impl, NULL, FALSE);
1327 else
1328 hr = DD_OK;
1329
1330 wined3d_mutex_unlock();
1331
1332 return hr;
1333 }
1334
1335 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface4_Flip(IDirectDrawSurface4 *iface,
1336 IDirectDrawSurface4 *dst, DWORD flags)
1337 {
1338 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
1339 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface4(dst);
1340
1341 TRACE("iface %p, dst %p, flags %#x.\n", iface, dst, flags);
1342
1343 return ddraw_surface7_Flip(&surface->IDirectDrawSurface7_iface,
1344 dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, flags);
1345 }
1346
1347 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface3_Flip(IDirectDrawSurface3 *iface,
1348 IDirectDrawSurface3 *dst, DWORD flags)
1349 {
1350 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
1351 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface3(dst);
1352
1353 TRACE("iface %p, dst %p, flags %#x.\n", iface, dst, flags);
1354
1355 return ddraw_surface7_Flip(&surface->IDirectDrawSurface7_iface,
1356 dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, flags);
1357 }
1358
1359 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface2_Flip(IDirectDrawSurface2 *iface,
1360 IDirectDrawSurface2 *dst, DWORD flags)
1361 {
1362 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
1363 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface2(dst);
1364
1365 TRACE("iface %p, dst %p, flags %#x.\n", iface, dst, flags);
1366
1367 return ddraw_surface7_Flip(&surface->IDirectDrawSurface7_iface,
1368 dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, flags);
1369 }
1370
1371 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_Flip(IDirectDrawSurface *iface,
1372 IDirectDrawSurface *dst, DWORD flags)
1373 {
1374 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
1375 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface(dst);
1376
1377 TRACE("iface %p, dst %p, flags %#x.\n", iface, dst, flags);
1378
1379 return ddraw_surface7_Flip(&surface->IDirectDrawSurface7_iface,
1380 dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, flags);
1381 }
1382
1383 static HRESULT ddraw_surface_blt_clipped(struct ddraw_surface *dst_surface, const RECT *dst_rect_in,
1384 struct ddraw_surface *src_surface, const RECT *src_rect_in, DWORD flags,
1385 const struct wined3d_blt_fx *fx, enum wined3d_texture_filter_type filter)
1386 {
1387 struct wined3d_texture *wined3d_src_texture;
1388 unsigned int src_sub_resource_idx;
1389 RECT src_rect, dst_rect;
1390 float scale_x, scale_y;
1391 const RECT *clip_rect;
1392 UINT clip_list_size;
1393 RGNDATA *clip_list;
1394 HRESULT hr = DD_OK;
1395 UINT i;
1396
1397 if (!dst_rect_in)
1398 {
1399 dst_rect.left = 0;
1400 dst_rect.top = 0;
1401 dst_rect.right = dst_surface->surface_desc.dwWidth;
1402 dst_rect.bottom = dst_surface->surface_desc.dwHeight;
1403 }
1404 else
1405 {
1406 dst_rect = *dst_rect_in;
1407 }
1408
1409 if (IsRectEmpty(&dst_rect))
1410 return DDERR_INVALIDRECT;
1411
1412 if (src_surface)
1413 {
1414 if (!src_rect_in)
1415 {
1416 src_rect.left = 0;
1417 src_rect.top = 0;
1418 src_rect.right = src_surface->surface_desc.dwWidth;
1419 src_rect.bottom = src_surface->surface_desc.dwHeight;
1420 }
1421 else
1422 {
1423 src_rect = *src_rect_in;
1424 }
1425
1426 if (IsRectEmpty(&src_rect))
1427 return DDERR_INVALIDRECT;
1428
1429 wined3d_src_texture = src_surface->wined3d_texture;
1430 src_sub_resource_idx = src_surface->sub_resource_idx;
1431 }
1432 else
1433 {
1434 SetRect(&src_rect, 0, 0, 0, 0);
1435 wined3d_src_texture = NULL;
1436 src_sub_resource_idx = 0;
1437 }
1438
1439 if (!dst_surface->clipper)
1440 {
1441 if (src_surface && src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1442 hr = ddraw_surface_update_frontbuffer(src_surface, &src_rect, TRUE);
1443 if (SUCCEEDED(hr))
1444 hr = wined3d_texture_blt(dst_surface->wined3d_texture, dst_surface->sub_resource_idx, &dst_rect,
1445 wined3d_src_texture, src_sub_resource_idx, &src_rect, flags, fx, filter);
1446 if (SUCCEEDED(hr) && (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE))
1447 hr = ddraw_surface_update_frontbuffer(dst_surface, &dst_rect, FALSE);
1448
1449 return hr;
1450 }
1451
1452 scale_x = (float)(src_rect.right - src_rect.left) / (float)(dst_rect.right - dst_rect.left);
1453 scale_y = (float)(src_rect.bottom - src_rect.top) / (float)(dst_rect.bottom - dst_rect.top);
1454
1455 if (FAILED(hr = IDirectDrawClipper_GetClipList(&dst_surface->clipper->IDirectDrawClipper_iface,
1456 &dst_rect, NULL, &clip_list_size)))
1457 {
1458 WARN("Failed to get clip list size, hr %#x.\n", hr);
1459 return hr;
1460 }
1461
1462 if (!(clip_list = HeapAlloc(GetProcessHeap(), 0, clip_list_size)))
1463 {
1464 WARN("Failed to allocate clip list.\n");
1465 return E_OUTOFMEMORY;
1466 }
1467
1468 if (FAILED(hr = IDirectDrawClipper_GetClipList(&dst_surface->clipper->IDirectDrawClipper_iface,
1469 &dst_rect, clip_list, &clip_list_size)))
1470 {
1471 WARN("Failed to get clip list, hr %#x.\n", hr);
1472 HeapFree(GetProcessHeap(), 0, clip_list);
1473 return hr;
1474 }
1475
1476 clip_rect = (RECT *)clip_list->Buffer;
1477 for (i = 0; i < clip_list->rdh.nCount; ++i)
1478 {
1479 RECT src_rect_clipped = src_rect;
1480
1481 if (src_surface)
1482 {
1483 src_rect_clipped.left += (LONG)((clip_rect[i].left - dst_rect.left) * scale_x);
1484 src_rect_clipped.top += (LONG)((clip_rect[i].top - dst_rect.top) * scale_y);
1485 src_rect_clipped.right -= (LONG)((dst_rect.right - clip_rect[i].right) * scale_x);
1486 src_rect_clipped.bottom -= (LONG)((dst_rect.bottom - clip_rect[i].bottom) * scale_y);
1487
1488 if (src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1489 {
1490 if (FAILED(hr = ddraw_surface_update_frontbuffer(src_surface, &src_rect_clipped, TRUE)))
1491 break;
1492 }
1493 }
1494
1495 if (FAILED(hr = wined3d_texture_blt(dst_surface->wined3d_texture, dst_surface->sub_resource_idx,
1496 &clip_rect[i], wined3d_src_texture, src_sub_resource_idx, &src_rect_clipped, flags, fx, filter)))
1497 break;
1498
1499 if (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1500 {
1501 if (FAILED(hr = ddraw_surface_update_frontbuffer(dst_surface, &clip_rect[i], FALSE)))
1502 break;
1503 }
1504 }
1505
1506 HeapFree(GetProcessHeap(), 0, clip_list);
1507 return hr;
1508 }
1509
1510 /*****************************************************************************
1511 * IDirectDrawSurface7::Blt
1512 *
1513 * Performs a blit on the surface
1514 *
1515 * Params:
1516 * DestRect: Destination rectangle, can be NULL
1517 * SrcSurface: Source surface, can be NULL
1518 * SrcRect: Source rectangle, can be NULL
1519 * Flags: Blt flags
1520 * DDBltFx: Some extended blt parameters, connected to the flags
1521 *
1522 * Returns:
1523 * D3D_OK on success
1524 * See IWineD3DSurface::Blt for more details
1525 *
1526 *****************************************************************************/
1527 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_Blt(IDirectDrawSurface7 *iface, RECT *dst_rect,
1528 IDirectDrawSurface7 *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
1529 {
1530 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface7(iface);
1531 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface7(src_surface);
1532 struct wined3d_blt_fx wined3d_fx;
1533 HRESULT hr = DD_OK;
1534 DDBLTFX rop_fx;
1535
1536 TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
1537 iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
1538
1539 /* Check for validity of the flags here. WineD3D Has the software-opengl selection path and would have
1540 * to check at 2 places, and sometimes do double checks. This also saves the call to wined3d :-)
1541 */
1542 if ((flags & DDBLT_KEYSRCOVERRIDE) && (!fx || flags & DDBLT_KEYSRC))
1543 {
1544 WARN("Invalid source color key parameters, returning DDERR_INVALIDPARAMS\n");
1545 return DDERR_INVALIDPARAMS;
1546 }
1547
1548 if ((flags & DDBLT_KEYDESTOVERRIDE) && (!fx || flags & DDBLT_KEYDEST))
1549 {
1550 WARN("Invalid destination color key parameters, returning DDERR_INVALIDPARAMS\n");
1551 return DDERR_INVALIDPARAMS;
1552 }
1553
1554 if (flags & DDBLT_DDROPS)
1555 {
1556 FIXME("DDBLT_DDROPS not implemented.\n");
1557 if (fx)
1558 FIXME(" rop %#x, pattern %p.\n", fx->dwDDROP, fx->u5.lpDDSPattern);
1559 return DDERR_NORASTEROPHW;
1560 }
1561
1562 wined3d_mutex_lock();
1563
1564 if (flags & (DDBLT_COLORFILL | DDBLT_DEPTHFILL))
1565 {
1566 if (flags & DDBLT_ROP)
1567 {
1568 wined3d_mutex_unlock();
1569 WARN("DDBLT_ROP used with DDBLT_COLORFILL or DDBLT_DEPTHFILL, returning DDERR_INVALIDPARAMS.\n");
1570 return DDERR_INVALIDPARAMS;
1571 }
1572 if (src_impl)
1573 {
1574 wined3d_mutex_unlock();
1575 WARN("Depth or colorfill is not compatible with source surfaces, returning DDERR_INVALIDPARAMS\n");
1576 return DDERR_INVALIDPARAMS;
1577 }
1578 if (!fx)
1579 {
1580 wined3d_mutex_unlock();
1581 WARN("Depth or colorfill used with NULL fx, returning DDERR_INVALIDPARAMS.\n");
1582 return DDERR_INVALIDPARAMS;
1583 }
1584
1585 if ((flags & (DDBLT_COLORFILL | DDBLT_DEPTHFILL)) == (DDBLT_COLORFILL | DDBLT_DEPTHFILL))
1586 flags &= ~DDBLT_DEPTHFILL;
1587
1588 if ((dst_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER) && (flags & DDBLT_COLORFILL))
1589 {
1590 wined3d_mutex_unlock();
1591 WARN("DDBLT_COLORFILL used on a depth buffer, returning DDERR_INVALIDPARAMS.\n");
1592 return DDERR_INVALIDPARAMS;
1593 }
1594 if (!(dst_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER) && (flags & DDBLT_DEPTHFILL))
1595 {
1596 wined3d_mutex_unlock();
1597 WARN("DDBLT_DEPTHFILL used on a color buffer, returning DDERR_INVALIDPARAMS.\n");
1598 return DDERR_INVALIDPARAMS;
1599 }
1600 }
1601
1602 if (flags & DDBLT_ROP)
1603 {
1604 if (!fx)
1605 {
1606 wined3d_mutex_unlock();
1607 WARN("DDBLT_ROP used with NULL fx, returning DDERR_INVALIDPARAMS.\n");
1608 return DDERR_INVALIDPARAMS;
1609 }
1610
1611 flags &= ~DDBLT_ROP;
1612 switch (fx->dwROP)
1613 {
1614 case SRCCOPY:
1615 break;
1616
1617 case WHITENESS:
1618 case BLACKNESS:
1619 rop_fx = *fx;
1620
1621 if (fx->dwROP == WHITENESS)
1622 rop_fx.u5.dwFillColor = 0xffffffff;
1623 else
1624 rop_fx.u5.dwFillColor = 0;
1625
1626 if (dst_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
1627 flags |= DDBLT_DEPTHFILL;
1628 else
1629 flags |= DDBLT_COLORFILL;
1630
1631 fx = &rop_fx;
1632 break;
1633
1634 default:
1635 wined3d_mutex_unlock();
1636 WARN("Unsupported ROP %#x used, returning DDERR_NORASTEROPHW.\n", fx->dwROP);
1637 return DDERR_NORASTEROPHW;
1638 }
1639 }
1640
1641 if (flags & DDBLT_KEYSRC && (!src_impl || !(src_impl->surface_desc.dwFlags & DDSD_CKSRCBLT)))
1642 {
1643 WARN("DDBLT_KEYDEST blit without color key in surface, returning DDERR_INVALIDPARAMS\n");
1644 wined3d_mutex_unlock();
1645 return DDERR_INVALIDPARAMS;
1646 }
1647
1648 if (flags & ~WINED3D_BLT_MASK)
1649 {
1650 wined3d_mutex_unlock();
1651 FIXME("Unhandled flags %#x.\n", flags);
1652 return E_NOTIMPL;
1653 }
1654
1655 if (fx)
1656 {
1657 wined3d_fx.fx = fx->dwDDFX;
1658 wined3d_fx.fill_color = fx->u5.dwFillColor;
1659 wined3d_fx.dst_color_key.color_space_low_value = fx->ddckDestColorkey.dwColorSpaceLowValue;
1660 wined3d_fx.dst_color_key.color_space_high_value = fx->ddckDestColorkey.dwColorSpaceHighValue;
1661 wined3d_fx.src_color_key.color_space_low_value = fx->ddckSrcColorkey.dwColorSpaceLowValue;
1662 wined3d_fx.src_color_key.color_space_high_value = fx->ddckSrcColorkey.dwColorSpaceHighValue;
1663 }
1664
1665 hr = ddraw_surface_blt_clipped(dst_impl, dst_rect, src_impl,
1666 src_rect, flags, fx ? &wined3d_fx : NULL, WINED3D_TEXF_LINEAR);
1667
1668 wined3d_mutex_unlock();
1669 switch(hr)
1670 {
1671 case WINED3DERR_NOTAVAILABLE: return DDERR_UNSUPPORTED;
1672 default: return hr;
1673 }
1674 }
1675
1676 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface4_Blt(IDirectDrawSurface4 *iface, RECT *dst_rect,
1677 IDirectDrawSurface4 *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
1678 {
1679 struct ddraw_surface *dst = impl_from_IDirectDrawSurface4(iface);
1680 struct ddraw_surface *src = unsafe_impl_from_IDirectDrawSurface4(src_surface);
1681
1682 TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
1683 iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
1684
1685 return ddraw_surface7_Blt(&dst->IDirectDrawSurface7_iface, dst_rect,
1686 src ? &src->IDirectDrawSurface7_iface : NULL, src_rect, flags, fx);
1687 }
1688
1689 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface3_Blt(IDirectDrawSurface3 *iface, RECT *dst_rect,
1690 IDirectDrawSurface3 *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
1691 {
1692 struct ddraw_surface *dst = impl_from_IDirectDrawSurface3(iface);
1693 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface3(src_surface);
1694
1695 TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
1696 iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
1697
1698 return ddraw_surface7_Blt(&dst->IDirectDrawSurface7_iface, dst_rect,
1699 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags, fx);
1700 }
1701
1702 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface2_Blt(IDirectDrawSurface2 *iface, RECT *dst_rect,
1703 IDirectDrawSurface2 *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
1704 {
1705 struct ddraw_surface *dst = impl_from_IDirectDrawSurface2(iface);
1706 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface2(src_surface);
1707
1708 TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
1709 iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
1710
1711 return ddraw_surface7_Blt(&dst->IDirectDrawSurface7_iface, dst_rect,
1712 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags, fx);
1713 }
1714
1715 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_Blt(IDirectDrawSurface *iface, RECT *dst_rect,
1716 IDirectDrawSurface *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
1717 {
1718 struct ddraw_surface *dst = impl_from_IDirectDrawSurface(iface);
1719 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface(src_surface);
1720
1721 TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
1722 iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
1723
1724 return ddraw_surface7_Blt(&dst->IDirectDrawSurface7_iface, dst_rect,
1725 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags, fx);
1726 }
1727
1728 /*****************************************************************************
1729 * IDirectDrawSurface7::AddAttachedSurface
1730 *
1731 * Attaches a surface to another surface. How the surface attachments work
1732 * is not totally understood yet, and this method is prone to problems.
1733 * The surface that is attached is AddRef-ed.
1734 *
1735 * Tests with complex surfaces suggest that the surface attachments form a
1736 * tree, but no method to test this has been found yet.
1737 *
1738 * The attachment list consists of a first surface (first_attached) and
1739 * for each surface a pointer to the next attached surface (next_attached).
1740 * For the first surface, and a surface that has no attachments
1741 * first_attached points to the surface itself. A surface that has
1742 * no successors in the chain has next_attached set to NULL.
1743 *
1744 * Newly attached surfaces are attached right after the root surface.
1745 * If a surface is attached to a complex surface compound, it's attached to
1746 * the surface that the app requested, not the complex root. See
1747 * GetAttachedSurface for a description how surfaces are found.
1748 *
1749 * This is how the current implementation works, and it was coded by looking
1750 * at the needs of the applications.
1751 *
1752 * So far only Z-Buffer attachments are tested, and they are activated in
1753 * WineD3D. Mipmaps could be tricky to activate in WineD3D.
1754 * Back buffers should work in 2D mode, but they are not tested(They can be
1755 * attached in older iface versions). Rendering to the front buffer and
1756 * switching between that and double buffering is not yet implemented in
1757 * WineD3D, so for 3D it might have unexpected results.
1758 *
1759 * ddraw_surface_attach_surface is the real thing,
1760 * ddraw_surface7_AddAttachedSurface is a wrapper around it that
1761 * performs additional checks. Version 7 of this interface is much more restrictive
1762 * than its predecessors.
1763 *
1764 * Params:
1765 * Attach: Surface to attach to iface
1766 *
1767 * Returns:
1768 * DD_OK on success
1769 * DDERR_CANNOTATTACHSURFACE if the surface can't be attached for some reason
1770 *
1771 *****************************************************************************/
1772 static HRESULT ddraw_surface_attach_surface(struct ddraw_surface *This, struct ddraw_surface *Surf)
1773 {
1774 TRACE("surface %p, attachment %p.\n", This, Surf);
1775
1776 if(Surf == This)
1777 return DDERR_CANNOTATTACHSURFACE; /* unchecked */
1778
1779 wined3d_mutex_lock();
1780
1781 /* Check if the surface is already attached somewhere */
1782 if (Surf->next_attached || Surf->first_attached != Surf)
1783 {
1784 /* TODO: Test for the structure of the manual attachment. Is it a
1785 * chain or a list? What happens if one surface is attached to 2
1786 * different surfaces? */
1787 WARN("Surface %p is already attached somewhere. next_attached %p, first_attached %p.\n",
1788 Surf, Surf->next_attached, Surf->first_attached);
1789
1790 wined3d_mutex_unlock();
1791 return DDERR_SURFACEALREADYATTACHED;
1792 }
1793
1794 /* This inserts the new surface at the 2nd position in the chain, right after the root surface */
1795 Surf->next_attached = This->next_attached;
1796 Surf->first_attached = This->first_attached;
1797 This->next_attached = Surf;
1798
1799 /* Check if the WineD3D depth stencil needs updating */
1800 if (This->ddraw->d3ddevice)
1801 d3d_device_update_depth_stencil(This->ddraw->d3ddevice);
1802
1803 wined3d_mutex_unlock();
1804
1805 return DD_OK;
1806 }
1807
1808 static HRESULT WINAPI ddraw_surface7_AddAttachedSurface(IDirectDrawSurface7 *iface, IDirectDrawSurface7 *attachment)
1809 {
1810 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
1811 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface7(attachment);
1812 HRESULT hr;
1813
1814 TRACE("iface %p, attachment %p.\n", iface, attachment);
1815
1816 /* Version 7 of this interface seems to refuse everything except z buffers, as per msdn */
1817 if(!(attachment_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER))
1818 {
1819
1820 WARN("Application tries to attach a non Z buffer surface. caps %08x\n",
1821 attachment_impl->surface_desc.ddsCaps.dwCaps);
1822 return DDERR_CANNOTATTACHSURFACE;
1823 }
1824
1825 hr = ddraw_surface_attach_surface(This, attachment_impl);
1826 if (FAILED(hr))
1827 {
1828 return hr;
1829 }
1830 attachment_impl->attached_iface = (IUnknown *)attachment;
1831 IUnknown_AddRef(attachment_impl->attached_iface);
1832 return hr;
1833 }
1834
1835 static HRESULT WINAPI ddraw_surface4_AddAttachedSurface(IDirectDrawSurface4 *iface, IDirectDrawSurface4 *attachment)
1836 {
1837 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
1838 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface4(attachment);
1839 HRESULT hr;
1840
1841 TRACE("iface %p, attachment %p.\n", iface, attachment);
1842
1843 /* Tests suggest that
1844 * -> offscreen plain surfaces can be attached to other offscreen plain surfaces
1845 * -> offscreen plain surfaces can be attached to primaries
1846 * -> primaries can be attached to offscreen plain surfaces
1847 * -> z buffers can be attached to primaries */
1848 if (surface->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_OFFSCREENPLAIN)
1849 && attachment_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_OFFSCREENPLAIN))
1850 {
1851 /* Sizes have to match */
1852 if (attachment_impl->surface_desc.dwWidth != surface->surface_desc.dwWidth
1853 || attachment_impl->surface_desc.dwHeight != surface->surface_desc.dwHeight)
1854 {
1855 WARN("Surface sizes do not match.\n");
1856 return DDERR_CANNOTATTACHSURFACE;
1857 }
1858 }
1859 else if (!(surface->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE))
1860 || !(attachment_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)))
1861 {
1862 WARN("Invalid attachment combination.\n");
1863 return DDERR_CANNOTATTACHSURFACE;
1864 }
1865
1866 if (FAILED(hr = ddraw_surface_attach_surface(surface, attachment_impl)))
1867 return hr;
1868
1869 attachment_impl->attached_iface = (IUnknown *)attachment;
1870 IUnknown_AddRef(attachment_impl->attached_iface);
1871 return hr;
1872 }
1873
1874 static HRESULT WINAPI ddraw_surface3_AddAttachedSurface(IDirectDrawSurface3 *iface, IDirectDrawSurface3 *attachment)
1875 {
1876 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
1877 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface3(attachment);
1878 HRESULT hr;
1879
1880 TRACE("iface %p, attachment %p.\n", iface, attachment);
1881
1882 if (FAILED(hr = ddraw_surface4_AddAttachedSurface(&surface->IDirectDrawSurface4_iface,
1883 attachment_impl ? &attachment_impl->IDirectDrawSurface4_iface : NULL)))
1884 return hr;
1885
1886 attachment_impl->attached_iface = (IUnknown *)attachment;
1887 IUnknown_AddRef(attachment_impl->attached_iface);
1888 ddraw_surface4_Release(&attachment_impl->IDirectDrawSurface4_iface);
1889 return hr;
1890 }
1891
1892 static HRESULT WINAPI ddraw_surface2_AddAttachedSurface(IDirectDrawSurface2 *iface, IDirectDrawSurface2 *attachment)
1893 {
1894 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
1895 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface2(attachment);
1896 HRESULT hr;
1897
1898 TRACE("iface %p, attachment %p.\n", iface, attachment);
1899
1900 if (FAILED(hr = ddraw_surface4_AddAttachedSurface(&surface->IDirectDrawSurface4_iface,
1901 attachment_impl ? &attachment_impl->IDirectDrawSurface4_iface : NULL)))
1902 return hr;
1903
1904 attachment_impl->attached_iface = (IUnknown *)attachment;
1905 IUnknown_AddRef(attachment_impl->attached_iface);
1906 ddraw_surface4_Release(&attachment_impl->IDirectDrawSurface4_iface);
1907 return hr;
1908 }
1909
1910 static HRESULT WINAPI ddraw_surface1_AddAttachedSurface(IDirectDrawSurface *iface, IDirectDrawSurface *attachment)
1911 {
1912 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
1913 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface(attachment);
1914 HRESULT hr;
1915
1916 TRACE("iface %p, attachment %p.\n", iface, attachment);
1917
1918 if (FAILED(hr = ddraw_surface4_AddAttachedSurface(&surface->IDirectDrawSurface4_iface,
1919 attachment_impl ? &attachment_impl->IDirectDrawSurface4_iface : NULL)))
1920 return hr;
1921
1922 attachment_impl->attached_iface = (IUnknown *)attachment;
1923 IUnknown_AddRef(attachment_impl->attached_iface);
1924 ddraw_surface4_Release(&attachment_impl->IDirectDrawSurface4_iface);
1925 return hr;
1926 }
1927
1928 /*****************************************************************************
1929 * IDirectDrawSurface7::DeleteAttachedSurface
1930 *
1931 * Removes a surface from the attachment chain. The surface's refcount
1932 * is decreased by one after it has been removed
1933 *
1934 * Params:
1935 * Flags: Some flags, not used by this implementation
1936 * Attach: Surface to detach
1937 *
1938 * Returns:
1939 * DD_OK on success
1940 * DDERR_SURFACENOTATTACHED if the surface isn't attached to
1941 *
1942 *****************************************************************************/
1943 static HRESULT ddraw_surface_delete_attached_surface(struct ddraw_surface *surface,
1944 struct ddraw_surface *attachment, IUnknown *detach_iface)
1945 {
1946 struct ddraw_surface *prev = surface;
1947
1948 TRACE("surface %p, attachment %p, detach_iface %p.\n", surface, attachment, detach_iface);
1949
1950 wined3d_mutex_lock();
1951 if (!attachment || (attachment->first_attached != surface) || (attachment == surface) )
1952 {
1953 wined3d_mutex_unlock();
1954 return DDERR_CANNOTDETACHSURFACE;
1955 }
1956
1957 if (attachment->attached_iface != detach_iface)
1958 {
1959 WARN("attachment->attach_iface %p != detach_iface %p.\n", attachment->attached_iface, detach_iface);
1960 wined3d_mutex_unlock();
1961 return DDERR_SURFACENOTATTACHED;
1962 }
1963
1964 /* Remove MIPMAPSUBLEVEL if this seemed to be one */
1965 if (surface->surface_desc.ddsCaps.dwCaps & attachment->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
1966 {
1967 attachment->surface_desc.ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL;
1968 /* FIXME: we should probably also subtract from dwMipMapCount of this
1969 * and all parent surfaces */
1970 }
1971
1972 /* Find the predecessor of the detached surface */
1973 while (prev)
1974 {
1975 if (prev->next_attached == attachment)
1976 break;
1977 prev = prev->next_attached;
1978 }
1979
1980 /* There must be a surface, otherwise there's a bug */
1981 assert(prev);
1982
1983 /* Unchain the surface */
1984 prev->next_attached = attachment->next_attached;
1985 attachment->next_attached = NULL;
1986 attachment->first_attached = attachment;
1987
1988 /* Check if the wined3d depth stencil needs updating. */
1989 if (surface->ddraw->d3ddevice)
1990 d3d_device_update_depth_stencil(surface->ddraw->d3ddevice);
1991 wined3d_mutex_unlock();
1992
1993 /* Set attached_iface to NULL before releasing it, the surface may go
1994 * away. */
1995 attachment->attached_iface = NULL;
1996 IUnknown_Release(detach_iface);
1997
1998 return DD_OK;
1999 }
2000
2001 static HRESULT WINAPI ddraw_surface7_DeleteAttachedSurface(IDirectDrawSurface7 *iface,
2002 DWORD flags, IDirectDrawSurface7 *attachment)
2003 {
2004 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2005 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface7(attachment);
2006
2007 TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment);
2008
2009 return ddraw_surface_delete_attached_surface(surface, attachment_impl, (IUnknown *)attachment);
2010 }
2011
2012 static HRESULT WINAPI ddraw_surface4_DeleteAttachedSurface(IDirectDrawSurface4 *iface,
2013 DWORD flags, IDirectDrawSurface4 *attachment)
2014 {
2015 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2016 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface4(attachment);
2017
2018 TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment);
2019
2020 return ddraw_surface_delete_attached_surface(surface, attachment_impl, (IUnknown *)attachment);
2021 }
2022
2023 static HRESULT WINAPI ddraw_surface3_DeleteAttachedSurface(IDirectDrawSurface3 *iface,
2024 DWORD flags, IDirectDrawSurface3 *attachment)
2025 {
2026 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2027 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface3(attachment);
2028
2029 TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment);
2030
2031 return ddraw_surface_delete_attached_surface(surface, attachment_impl, (IUnknown *)attachment);
2032 }
2033
2034 static HRESULT WINAPI ddraw_surface2_DeleteAttachedSurface(IDirectDrawSurface2 *iface,
2035 DWORD flags, IDirectDrawSurface2 *attachment)
2036 {
2037 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2038 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface2(attachment);
2039
2040 TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment);
2041
2042 return ddraw_surface_delete_attached_surface(surface, attachment_impl, (IUnknown *)attachment);
2043 }
2044
2045 static HRESULT WINAPI ddraw_surface1_DeleteAttachedSurface(IDirectDrawSurface *iface,
2046 DWORD flags, IDirectDrawSurface *attachment)
2047 {
2048 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2049 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface(attachment);
2050
2051 TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment);
2052
2053 return ddraw_surface_delete_attached_surface(surface, attachment_impl, (IUnknown *)attachment);
2054 }
2055
2056 /*****************************************************************************
2057 * IDirectDrawSurface7::AddOverlayDirtyRect
2058 *
2059 * "This method is not currently implemented"
2060 *
2061 * Params:
2062 * Rect: ?
2063 *
2064 * Returns:
2065 * DDERR_UNSUPPORTED
2066 *
2067 *****************************************************************************/
2068 static HRESULT WINAPI ddraw_surface7_AddOverlayDirtyRect(IDirectDrawSurface7 *iface, RECT *Rect)
2069 {
2070 TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(Rect));
2071
2072 return DDERR_UNSUPPORTED; /* unchecked */
2073 }
2074
2075 static HRESULT WINAPI ddraw_surface4_AddOverlayDirtyRect(IDirectDrawSurface4 *iface, RECT *rect)
2076 {
2077 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2078
2079 TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect));
2080
2081 return ddraw_surface7_AddOverlayDirtyRect(&surface->IDirectDrawSurface7_iface, rect);
2082 }
2083
2084 static HRESULT WINAPI ddraw_surface3_AddOverlayDirtyRect(IDirectDrawSurface3 *iface, RECT *rect)
2085 {
2086 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2087
2088 TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect));
2089
2090 return ddraw_surface7_AddOverlayDirtyRect(&surface->IDirectDrawSurface7_iface, rect);
2091 }
2092
2093 static HRESULT WINAPI ddraw_surface2_AddOverlayDirtyRect(IDirectDrawSurface2 *iface, RECT *rect)
2094 {
2095 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2096
2097 TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect));
2098
2099 return ddraw_surface7_AddOverlayDirtyRect(&surface->IDirectDrawSurface7_iface, rect);
2100 }
2101
2102 static HRESULT WINAPI ddraw_surface1_AddOverlayDirtyRect(IDirectDrawSurface *iface, RECT *rect)
2103 {
2104 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2105
2106 TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect));
2107
2108 return ddraw_surface7_AddOverlayDirtyRect(&surface->IDirectDrawSurface7_iface, rect);
2109 }
2110
2111 /*****************************************************************************
2112 * IDirectDrawSurface7::GetDC
2113 *
2114 * Returns a GDI device context for the surface
2115 *
2116 * Params:
2117 * hdc: Address of a HDC variable to store the dc to
2118 *
2119 * Returns:
2120 * DD_OK on success
2121 * DDERR_INVALIDPARAMS if hdc is NULL
2122 * For details, see IWineD3DSurface::GetDC
2123 *
2124 *****************************************************************************/
2125 static HRESULT WINAPI ddraw_surface7_GetDC(IDirectDrawSurface7 *iface, HDC *dc)
2126 {
2127 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2128 HRESULT hr = DD_OK;
2129
2130 TRACE("iface %p, dc %p.\n", iface, dc);
2131
2132 if (!dc)
2133 return DDERR_INVALIDPARAMS;
2134
2135 wined3d_mutex_lock();
2136 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
2137 hr = ddraw_surface_update_frontbuffer(surface, NULL, TRUE);
2138 if (SUCCEEDED(hr))
2139 hr = wined3d_texture_get_dc(surface->wined3d_texture, surface->sub_resource_idx, dc);
2140
2141 if (SUCCEEDED(hr))
2142 {
2143 surface->dc = *dc;
2144
2145 if (format_is_paletteindexed(&surface->surface_desc.u4.ddpfPixelFormat))
2146 {
2147 const struct ddraw_palette *palette;
2148
2149 if (surface->palette)
2150 palette = surface->palette;
2151 else if (surface->ddraw->primary)
2152 palette = surface->ddraw->primary->palette;
2153 else
2154 palette = NULL;
2155
2156 if (palette)
2157 wined3d_palette_apply_to_dc(palette->wineD3DPalette, *dc);
2158 }
2159 }
2160
2161 wined3d_mutex_unlock();
2162 switch (hr)
2163 {
2164 /* Some, but not all errors set *dc to NULL. E.g. DCALREADYCREATED
2165 * does not touch *dc. */
2166 case WINED3DERR_INVALIDCALL:
2167 *dc = NULL;
2168 return DDERR_INVALIDPARAMS;
2169
2170 default:
2171 return hr;
2172 }
2173 }
2174
2175 static HRESULT WINAPI ddraw_surface4_GetDC(IDirectDrawSurface4 *iface, HDC *dc)
2176 {
2177 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2178
2179 TRACE("iface %p, dc %p.\n", iface, dc);
2180
2181 return ddraw_surface7_GetDC(&surface->IDirectDrawSurface7_iface, dc);
2182 }
2183
2184 static HRESULT WINAPI ddraw_surface3_GetDC(IDirectDrawSurface3 *iface, HDC *dc)
2185 {
2186 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2187
2188 TRACE("iface %p, dc %p.\n", iface, dc);
2189
2190 return ddraw_surface7_GetDC(&surface->IDirectDrawSurface7_iface, dc);
2191 }
2192
2193 static HRESULT WINAPI ddraw_surface2_GetDC(IDirectDrawSurface2 *iface, HDC *dc)
2194 {
2195 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2196
2197 TRACE("iface %p, dc %p.\n", iface, dc);
2198
2199 return ddraw_surface7_GetDC(&surface->IDirectDrawSurface7_iface, dc);
2200 }
2201
2202 static HRESULT WINAPI ddraw_surface1_GetDC(IDirectDrawSurface *iface, HDC *dc)
2203 {
2204 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2205
2206 TRACE("iface %p, dc %p.\n", iface, dc);
2207
2208 return ddraw_surface7_GetDC(&surface->IDirectDrawSurface7_iface, dc);
2209 }
2210
2211 /*****************************************************************************
2212 * IDirectDrawSurface7::ReleaseDC
2213 *
2214 * Releases the DC that was constructed with GetDC
2215 *
2216 * Params:
2217 * hdc: HDC to release
2218 *
2219 * Returns:
2220 * DD_OK on success
2221 * For more details, see IWineD3DSurface::ReleaseDC
2222 *
2223 *****************************************************************************/
2224 static HRESULT WINAPI ddraw_surface7_ReleaseDC(IDirectDrawSurface7 *iface, HDC hdc)
2225 {
2226 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2227 HRESULT hr;
2228
2229 TRACE("iface %p, dc %p.\n", iface, hdc);
2230
2231 wined3d_mutex_lock();
2232 if (SUCCEEDED(hr = wined3d_texture_release_dc(surface->wined3d_texture, surface->sub_resource_idx, hdc)))
2233 {
2234 surface->dc = NULL;
2235 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
2236 hr = ddraw_surface_update_frontbuffer(surface, NULL, FALSE);
2237 }
2238 wined3d_mutex_unlock();
2239
2240
2241 return hr;
2242 }
2243
2244 static HRESULT WINAPI ddraw_surface4_ReleaseDC(IDirectDrawSurface4 *iface, HDC dc)
2245 {
2246 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2247
2248 TRACE("iface %p, dc %p.\n", iface, dc);
2249
2250 return ddraw_surface7_ReleaseDC(&surface->IDirectDrawSurface7_iface, dc);
2251 }
2252
2253 static HRESULT WINAPI ddraw_surface3_ReleaseDC(IDirectDrawSurface3 *iface, HDC dc)
2254 {
2255 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2256
2257 TRACE("iface %p, dc %p.\n", iface, dc);
2258
2259 return ddraw_surface7_ReleaseDC(&surface->IDirectDrawSurface7_iface, dc);
2260 }
2261
2262 static HRESULT WINAPI ddraw_surface2_ReleaseDC(IDirectDrawSurface2 *iface, HDC dc)
2263 {
2264 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2265
2266 TRACE("iface %p, dc %p.\n", iface, dc);
2267
2268 return ddraw_surface7_ReleaseDC(&surface->IDirectDrawSurface7_iface, dc);
2269 }
2270
2271 static HRESULT WINAPI ddraw_surface1_ReleaseDC(IDirectDrawSurface *iface, HDC dc)
2272 {
2273 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2274
2275 TRACE("iface %p, dc %p.\n", iface, dc);
2276
2277 return ddraw_surface7_ReleaseDC(&surface->IDirectDrawSurface7_iface, dc);
2278 }
2279
2280 /*****************************************************************************
2281 * IDirectDrawSurface7::GetCaps
2282 *
2283 * Returns the surface's caps
2284 *
2285 * Params:
2286 * Caps: Address to write the caps to
2287 *
2288 * Returns:
2289 * DD_OK on success
2290 * DDERR_INVALIDPARAMS if Caps is NULL
2291 *
2292 *****************************************************************************/
2293 static HRESULT WINAPI ddraw_surface7_GetCaps(IDirectDrawSurface7 *iface, DDSCAPS2 *Caps)
2294 {
2295 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2296
2297 TRACE("iface %p, caps %p.\n", iface, Caps);
2298
2299 if(!Caps)
2300 return DDERR_INVALIDPARAMS;
2301
2302 *Caps = surface->surface_desc.ddsCaps;
2303
2304 return DD_OK;
2305 }
2306
2307 static HRESULT WINAPI ddraw_surface4_GetCaps(IDirectDrawSurface4 *iface, DDSCAPS2 *caps)
2308 {
2309 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2310
2311 TRACE("iface %p, caps %p.\n", iface, caps);
2312
2313 return ddraw_surface7_GetCaps(&surface->IDirectDrawSurface7_iface, caps);
2314 }
2315
2316 static HRESULT WINAPI ddraw_surface3_GetCaps(IDirectDrawSurface3 *iface, DDSCAPS *caps)
2317 {
2318 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2319 DDSCAPS2 caps2;
2320 HRESULT hr;
2321
2322 TRACE("iface %p, caps %p.\n", iface, caps);
2323
2324 hr = ddraw_surface7_GetCaps(&surface->IDirectDrawSurface7_iface, &caps2);
2325 if (FAILED(hr)) return hr;
2326
2327 caps->dwCaps = caps2.dwCaps;
2328 return hr;
2329 }
2330
2331 static HRESULT WINAPI ddraw_surface2_GetCaps(IDirectDrawSurface2 *iface, DDSCAPS *caps)
2332 {
2333 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2334 DDSCAPS2 caps2;
2335 HRESULT hr;
2336
2337 TRACE("iface %p, caps %p.\n", iface, caps);
2338
2339 hr = ddraw_surface7_GetCaps(&surface->IDirectDrawSurface7_iface, &caps2);
2340 if (FAILED(hr)) return hr;
2341
2342 caps->dwCaps = caps2.dwCaps;
2343 return hr;
2344 }
2345
2346 static HRESULT WINAPI ddraw_surface1_GetCaps(IDirectDrawSurface *iface, DDSCAPS *caps)
2347 {
2348 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2349 DDSCAPS2 caps2;
2350 HRESULT hr;
2351
2352 TRACE("iface %p, caps %p.\n", iface, caps);
2353
2354 hr = ddraw_surface7_GetCaps(&surface->IDirectDrawSurface7_iface, &caps2);
2355 if (FAILED(hr)) return hr;
2356
2357 caps->dwCaps = caps2.dwCaps;
2358 return hr;
2359 }
2360
2361 static HRESULT WINAPI ddraw_surface7_SetPriority(IDirectDrawSurface7 *iface, DWORD priority)
2362 {
2363 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2364 DWORD managed = DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE;
2365 HRESULT hr;
2366 struct wined3d_resource *resource;
2367
2368 TRACE("iface %p, priority %u.\n", iface, priority);
2369
2370 wined3d_mutex_lock();
2371 /* No need to check for offscreen plain surfaces or mipmap sublevels. SetPriority
2372 * calls on such surfaces segfault on Windows. */
2373 if (!(surface->surface_desc.ddsCaps.dwCaps2 & managed))
2374 {
2375 WARN("Called on non-managed texture returning DDERR_INVALIDPARAMS.\n");
2376 hr = DDERR_INVALIDPARAMS;
2377 }
2378 else
2379 {
2380 resource = wined3d_texture_get_resource(surface->wined3d_texture);
2381 wined3d_resource_set_priority(resource, priority);
2382 hr = DD_OK;
2383 }
2384 wined3d_mutex_unlock();
2385
2386 return hr;
2387 }
2388
2389 static HRESULT WINAPI ddraw_surface7_GetPriority(IDirectDrawSurface7 *iface, DWORD *priority)
2390 {
2391 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2392 const struct wined3d_resource *resource;
2393 DWORD managed = DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE;
2394 HRESULT hr;
2395
2396 TRACE("iface %p, priority %p.\n", iface, priority);
2397
2398 wined3d_mutex_lock();
2399 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_OFFSCREENPLAIN)
2400 {
2401 WARN("Called on offscreenplain surface, returning DDERR_INVALIDOBJECT.\n");
2402 hr = DDERR_INVALIDOBJECT;
2403 }
2404 else if (!(surface->surface_desc.ddsCaps.dwCaps2 & managed) || !surface->is_complex_root)
2405 {
2406 WARN("Called on non-managed texture or non-root surface, returning DDERR_INVALIDPARAMS.\n");
2407 hr = DDERR_INVALIDPARAMS;
2408 }
2409 else
2410 {
2411 resource = wined3d_texture_get_resource(surface->wined3d_texture);
2412 *priority = wined3d_resource_get_priority(resource);
2413 hr = DD_OK;
2414 }
2415 wined3d_mutex_unlock();
2416
2417 return hr;
2418 }
2419
2420 /*****************************************************************************
2421 * IDirectDrawSurface7::SetPrivateData
2422 *
2423 * Stores some data in the surface that is intended for the application's
2424 * use.
2425 *
2426 * Params:
2427 * tag: GUID that identifies the data
2428 * Data: Pointer to the private data
2429 * Size: Size of the private data
2430 * Flags: Some flags
2431 *
2432 * Returns:
2433 * D3D_OK on success
2434 * For more details, see IWineD3DSurface::SetPrivateData
2435 *
2436 *****************************************************************************/
2437 static HRESULT WINAPI ddraw_surface7_SetPrivateData(IDirectDrawSurface7 *iface,
2438 REFGUID tag, void *data, DWORD size, DWORD flags)
2439 {
2440 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2441 HRESULT hr;
2442
2443 TRACE("iface %p, tag %s, data %p, data_size %u, flags %#x.\n",
2444 iface, debugstr_guid(tag), data, size, flags);
2445
2446 if (!data)
2447 {
2448 WARN("data is NULL, returning DDERR_INVALIDPARAMS.\n");
2449 return DDERR_INVALIDPARAMS;
2450 }
2451
2452 wined3d_mutex_lock();
2453 hr = wined3d_private_store_set_private_data(&surface->private_store, tag, data, size, flags);
2454 wined3d_mutex_unlock();
2455 return hr_ddraw_from_wined3d(hr);
2456 }
2457
2458 static HRESULT WINAPI ddraw_surface4_SetPrivateData(IDirectDrawSurface4 *iface,
2459 REFGUID tag, void *data, DWORD size, DWORD flags)
2460 {
2461 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2462
2463 TRACE("iface %p, tag %s, data %p, data_size %u, flags %#x.\n",
2464 iface, debugstr_guid(tag), data, size, flags);
2465
2466 return ddraw_surface7_SetPrivateData(&surface->IDirectDrawSurface7_iface, tag, data, size, flags);
2467 }
2468
2469 /*****************************************************************************
2470 * IDirectDrawSurface7::GetPrivateData
2471 *
2472 * Returns the private data set with IDirectDrawSurface7::SetPrivateData
2473 *
2474 * Params:
2475 * tag: GUID of the data to return
2476 * Data: Address where to write the data to
2477 * Size: Size of the buffer at Data
2478 *
2479 * Returns:
2480 * DD_OK on success
2481 * DDERR_INVALIDPARAMS if Data is NULL
2482 * For more details, see IWineD3DSurface::GetPrivateData
2483 *
2484 *****************************************************************************/
2485 static HRESULT WINAPI ddraw_surface7_GetPrivateData(IDirectDrawSurface7 *iface, REFGUID tag, void *data, DWORD *size)
2486 {
2487 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2488 const struct wined3d_private_data *stored_data;
2489 HRESULT hr;
2490
2491 TRACE("iface %p, tag %s, data %p, data_size %p.\n",
2492 iface, debugstr_guid(tag), data, size);
2493
2494 wined3d_mutex_lock();
2495 stored_data = wined3d_private_store_get_private_data(&surface->private_store, tag);
2496 if (!stored_data)
2497 {
2498 hr = DDERR_NOTFOUND;
2499 goto done;
2500 }
2501 if (!size)
2502 {
2503 hr = DDERR_INVALIDPARAMS;
2504 goto done;
2505 }
2506 if (*size < stored_data->size)
2507 {
2508 *size = stored_data->size;
2509 hr = DDERR_MOREDATA;
2510 goto done;
2511 }
2512 if (!data)
2513 {
2514 hr = DDERR_INVALIDPARAMS;
2515 goto done;
2516 }
2517
2518 *size = stored_data->size;
2519 memcpy(data, stored_data->content.data, stored_data->size);
2520 hr = DD_OK;
2521
2522 done:
2523 wined3d_mutex_unlock();
2524 return hr;
2525 }
2526
2527 static HRESULT WINAPI ddraw_surface4_GetPrivateData(IDirectDrawSurface4 *iface, REFGUID tag, void *data, DWORD *size)
2528 {
2529 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2530
2531 TRACE("iface %p, tag %s, data %p, data_size %p.\n",
2532 iface, debugstr_guid(tag), data, size);
2533
2534 return ddraw_surface7_GetPrivateData(&surface->IDirectDrawSurface7_iface, tag, data, size);
2535 }
2536
2537 /*****************************************************************************
2538 * IDirectDrawSurface7::FreePrivateData
2539 *
2540 * Frees private data stored in the surface
2541 *
2542 * Params:
2543 * tag: Tag of the data to free
2544 *
2545 * Returns:
2546 * D3D_OK on success
2547 * For more details, see IWineD3DSurface::FreePrivateData
2548 *
2549 *****************************************************************************/
2550 static HRESULT WINAPI ddraw_surface7_FreePrivateData(IDirectDrawSurface7 *iface, REFGUID tag)
2551 {
2552 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2553 struct wined3d_private_data *entry;
2554
2555 TRACE("iface %p, tag %s.\n", iface, debugstr_guid(tag));
2556
2557 wined3d_mutex_lock();
2558 entry = wined3d_private_store_get_private_data(&surface->private_store, tag);
2559 if (!entry)
2560 {
2561 wined3d_mutex_unlock();
2562 return DDERR_NOTFOUND;
2563 }
2564
2565 wined3d_private_store_free_private_data(&surface->private_store, entry);
2566 wined3d_mutex_unlock();
2567
2568 return DD_OK;
2569 }
2570
2571 static HRESULT WINAPI ddraw_surface4_FreePrivateData(IDirectDrawSurface4 *iface, REFGUID tag)
2572 {
2573 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2574
2575 TRACE("iface %p, tag %s.\n", iface, debugstr_guid(tag));
2576
2577 return ddraw_surface7_FreePrivateData(&surface->IDirectDrawSurface7_iface, tag);
2578 }
2579
2580 /*****************************************************************************
2581 * IDirectDrawSurface7::PageLock
2582 *
2583 * Prevents a sysmem surface from being paged out
2584 *
2585 * Params:
2586 * Flags: Not used, must be 0(unchecked)
2587 *
2588 * Returns:
2589 * DD_OK, because it's a stub
2590 *
2591 *****************************************************************************/
2592 static HRESULT WINAPI ddraw_surface7_PageLock(IDirectDrawSurface7 *iface, DWORD Flags)
2593 {
2594 TRACE("iface %p, flags %#x.\n", iface, Flags);
2595
2596 /* This is Windows memory management related - we don't need this */
2597 return DD_OK;
2598 }
2599
2600 static HRESULT WINAPI ddraw_surface4_PageLock(IDirectDrawSurface4 *iface, DWORD flags)
2601 {
2602 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2603
2604 TRACE("iface %p, flags %#x.\n", iface, flags);
2605
2606 return ddraw_surface7_PageLock(&surface->IDirectDrawSurface7_iface, flags);
2607 }
2608
2609 static HRESULT WINAPI ddraw_surface3_PageLock(IDirectDrawSurface3 *iface, DWORD flags)
2610 {
2611 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2612
2613 TRACE("iface %p, flags %#x.\n", iface, flags);
2614
2615 return ddraw_surface7_PageLock(&surface->IDirectDrawSurface7_iface, flags);
2616 }
2617
2618 static HRESULT WINAPI ddraw_surface2_PageLock(IDirectDrawSurface2 *iface, DWORD flags)
2619 {
2620 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2621
2622 TRACE("iface %p, flags %#x.\n", iface, flags);
2623
2624 return ddraw_surface7_PageLock(&surface->IDirectDrawSurface7_iface, flags);
2625 }
2626
2627 /*****************************************************************************
2628 * IDirectDrawSurface7::PageUnlock
2629 *
2630 * Allows a sysmem surface to be paged out
2631 *
2632 * Params:
2633 * Flags: Not used, must be 0(unchecked)
2634 *
2635 * Returns:
2636 * DD_OK, because it's a stub
2637 *
2638 *****************************************************************************/
2639 static HRESULT WINAPI ddraw_surface7_PageUnlock(IDirectDrawSurface7 *iface, DWORD Flags)
2640 {
2641 TRACE("iface %p, flags %#x.\n", iface, Flags);
2642
2643 return DD_OK;
2644 }
2645
2646 static HRESULT WINAPI ddraw_surface4_PageUnlock(IDirectDrawSurface4 *iface, DWORD flags)
2647 {
2648 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2649
2650 TRACE("iface %p, flags %#x.\n", iface, flags);
2651
2652 return ddraw_surface7_PageUnlock(&surface->IDirectDrawSurface7_iface, flags);
2653 }
2654
2655 static HRESULT WINAPI ddraw_surface3_PageUnlock(IDirectDrawSurface3 *iface, DWORD flags)
2656 {
2657 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2658
2659 TRACE("iface %p, flags %#x.\n", iface, flags);
2660
2661 return ddraw_surface7_PageUnlock(&surface->IDirectDrawSurface7_iface, flags);
2662 }
2663
2664 static HRESULT WINAPI ddraw_surface2_PageUnlock(IDirectDrawSurface2 *iface, DWORD flags)
2665 {
2666 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2667
2668 TRACE("iface %p, flags %#x.\n", iface, flags);
2669
2670 return ddraw_surface7_PageUnlock(&surface->IDirectDrawSurface7_iface, flags);
2671 }
2672
2673 /*****************************************************************************
2674 * IDirectDrawSurface7::BltBatch
2675 *
2676 * An unimplemented function
2677 *
2678 * Params:
2679 * ?
2680 *
2681 * Returns:
2682 * DDERR_UNSUPPORTED
2683 *
2684 *****************************************************************************/
2685 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_BltBatch(IDirectDrawSurface7 *iface, DDBLTBATCH *Batch, DWORD Count, DWORD Flags)
2686 {
2687 TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, Batch, Count, Flags);
2688
2689 /* MSDN: "not currently implemented" */
2690 return DDERR_UNSUPPORTED;
2691 }
2692
2693 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface4_BltBatch(IDirectDrawSurface4 *iface, DDBLTBATCH *batch, DWORD count, DWORD flags)
2694 {
2695 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2696
2697 TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags);
2698
2699 return ddraw_surface7_BltBatch(&surface->IDirectDrawSurface7_iface, batch, count, flags);
2700 }
2701
2702 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface3_BltBatch(IDirectDrawSurface3 *iface, DDBLTBATCH *batch, DWORD count, DWORD flags)
2703 {
2704 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2705
2706 TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags);
2707
2708 return ddraw_surface7_BltBatch(&surface->IDirectDrawSurface7_iface, batch, count, flags);
2709 }
2710
2711 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface2_BltBatch(IDirectDrawSurface2 *iface, DDBLTBATCH *batch, DWORD count, DWORD flags)
2712 {
2713 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2714
2715 TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags);
2716
2717 return ddraw_surface7_BltBatch(&surface->IDirectDrawSurface7_iface, batch, count, flags);
2718 }
2719
2720 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_BltBatch(IDirectDrawSurface *iface, DDBLTBATCH *batch, DWORD count, DWORD flags)
2721 {
2722 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2723
2724 TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags);
2725
2726 return ddraw_surface7_BltBatch(&surface->IDirectDrawSurface7_iface, batch, count, flags);
2727 }
2728
2729 /*****************************************************************************
2730 * IDirectDrawSurface7::EnumAttachedSurfaces
2731 *
2732 * Enumerates all surfaces attached to this surface
2733 *
2734 * Params:
2735 * context: Pointer to pass unmodified to the callback
2736 * cb: Callback function to call for each surface
2737 *
2738 * Returns:
2739 * DD_OK on success
2740 * DDERR_INVALIDPARAMS if cb is NULL
2741 *
2742 *****************************************************************************/
2743 static HRESULT WINAPI ddraw_surface7_EnumAttachedSurfaces(IDirectDrawSurface7 *iface,
2744 void *context, LPDDENUMSURFACESCALLBACK7 cb)
2745 {
2746 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2747 struct ddraw_surface *surf;
2748 DDSURFACEDESC2 desc;
2749 int i;
2750
2751 /* Attached surfaces aren't handled in WineD3D */
2752 TRACE("iface %p, context %p, callback %p.\n", iface, context, cb);
2753
2754 if(!cb)
2755 return DDERR_INVALIDPARAMS;
2756
2757 wined3d_mutex_lock();
2758
2759 for(i = 0; i < MAX_COMPLEX_ATTACHED; i++)
2760 {
2761 surf = surface->complex_array[i];
2762 if(!surf) break;
2763
2764 ddraw_surface7_AddRef(&surf->IDirectDrawSurface7_iface);
2765 desc = surf->surface_desc;
2766 /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
2767 if (cb(&surf->IDirectDrawSurface7_iface, &desc, context) == DDENUMRET_CANCEL)
2768 {
2769 wined3d_mutex_unlock();
2770 return DD_OK;
2771 }
2772 }
2773
2774 for (surf = surface->next_attached; surf != NULL; surf = surf->next_attached)
2775 {
2776 ddraw_surface7_AddRef(&surf->IDirectDrawSurface7_iface);
2777 desc = surf->surface_desc;
2778 /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
2779 if (cb(&surf->IDirectDrawSurface7_iface, &desc, context) == DDENUMRET_CANCEL)
2780 {
2781 wined3d_mutex_unlock();
2782 return DD_OK;
2783 }
2784 }
2785
2786 TRACE(" end of enumeration.\n");
2787
2788 wined3d_mutex_unlock();
2789
2790 return DD_OK;
2791 }
2792
2793 struct callback_info2
2794 {
2795 LPDDENUMSURFACESCALLBACK2 callback;
2796 void *context;
2797 };
2798
2799 struct callback_info
2800 {
2801 LPDDENUMSURFACESCALLBACK callback;
2802 void *context;
2803 };
2804
2805 static HRESULT CALLBACK EnumCallback2(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *surface_desc, void *context)
2806 {
2807 struct ddraw_surface *surface_impl = impl_from_IDirectDrawSurface7(surface);
2808 const struct callback_info2 *info = context;
2809
2810 ddraw_surface4_AddRef(&surface_impl->IDirectDrawSurface4_iface);
2811 ddraw_surface7_Release(surface);
2812
2813 return info->callback(&surface_impl->IDirectDrawSurface4_iface, surface_desc, info->context);
2814 }
2815
2816 static HRESULT CALLBACK EnumCallback(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *surface_desc, void *context)
2817 {
2818 struct ddraw_surface *surface_impl = impl_from_IDirectDrawSurface7(surface);
2819 const struct callback_info *info = context;
2820
2821 ddraw_surface1_AddRef(&surface_impl->IDirectDrawSurface_iface);
2822 ddraw_surface7_Release(surface);
2823
2824 /* FIXME: Check surface_test.dwSize */
2825 return info->callback(&surface_impl->IDirectDrawSurface_iface,
2826 (DDSURFACEDESC *)surface_desc, info->context);
2827 }
2828
2829 static HRESULT WINAPI ddraw_surface4_EnumAttachedSurfaces(IDirectDrawSurface4 *iface,
2830 void *context, LPDDENUMSURFACESCALLBACK2 callback)
2831 {
2832 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2833 struct callback_info2 info;
2834
2835 TRACE("iface %p, context %p, callback %p.\n", iface, context, callback);
2836
2837 info.callback = callback;
2838 info.context = context;
2839
2840 return ddraw_surface7_EnumAttachedSurfaces(&surface->IDirectDrawSurface7_iface,
2841 &info, EnumCallback2);
2842 }
2843
2844 static HRESULT WINAPI ddraw_surface3_EnumAttachedSurfaces(IDirectDrawSurface3 *iface,
2845 void *context, LPDDENUMSURFACESCALLBACK callback)
2846 {
2847 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2848 struct callback_info info;
2849
2850 TRACE("iface %p, context %p, callback %p.\n", iface, context, callback);
2851
2852 info.callback = callback;
2853 info.context = context;
2854
2855 return ddraw_surface7_EnumAttachedSurfaces(&surface->IDirectDrawSurface7_iface,
2856 &info, EnumCallback);
2857 }
2858
2859 static HRESULT WINAPI ddraw_surface2_EnumAttachedSurfaces(IDirectDrawSurface2 *iface,
2860 void *context, LPDDENUMSURFACESCALLBACK callback)
2861 {
2862 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2863 struct callback_info info;
2864
2865 TRACE("iface %p, context %p, callback %p.\n", iface, context, callback);
2866
2867 info.callback = callback;
2868 info.context = context;
2869
2870 return ddraw_surface7_EnumAttachedSurfaces(&surface->IDirectDrawSurface7_iface,
2871 &info, EnumCallback);
2872 }
2873
2874 static HRESULT WINAPI ddraw_surface1_EnumAttachedSurfaces(IDirectDrawSurface *iface,
2875 void *context, LPDDENUMSURFACESCALLBACK callback)
2876 {
2877 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2878 struct callback_info info;
2879
2880 TRACE("iface %p, context %p, callback %p.\n", iface, context, callback);
2881
2882 info.callback = callback;
2883 info.context = context;
2884
2885 return ddraw_surface7_EnumAttachedSurfaces(&surface->IDirectDrawSurface7_iface,
2886 &info, EnumCallback);
2887 }
2888
2889 /*****************************************************************************
2890 * IDirectDrawSurface7::EnumOverlayZOrders
2891 *
2892 * "Enumerates the overlay surfaces on the specified destination"
2893 *
2894 * Params:
2895 * Flags: DDENUMOVERLAYZ_BACKTOFRONT or DDENUMOVERLAYZ_FRONTTOBACK
2896 * context: context to pass back to the callback
2897 * cb: callback function to call for each enumerated surface
2898 *
2899 * Returns:
2900 * DD_OK, because it's a stub
2901 *
2902 *****************************************************************************/
2903 static HRESULT WINAPI ddraw_surface7_EnumOverlayZOrders(IDirectDrawSurface7 *iface,
2904 DWORD Flags, void *context, LPDDENUMSURFACESCALLBACK7 cb)
2905 {
2906 FIXME("iface %p, flags %#x, context %p, callback %p stub!\n", iface, Flags, context, cb);
2907
2908 return DD_OK;
2909 }
2910
2911 static HRESULT WINAPI ddraw_surface4_EnumOverlayZOrders(IDirectDrawSurface4 *iface,
2912 DWORD flags, void *context, LPDDENUMSURFACESCALLBACK2 callback)
2913 {
2914 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2915 struct callback_info2 info;
2916
2917 TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback);
2918
2919 info.callback = callback;
2920 info.context = context;
2921
2922 return ddraw_surface7_EnumOverlayZOrders(&surface->IDirectDrawSurface7_iface,
2923 flags, &info, EnumCallback2);
2924 }
2925
2926 static HRESULT WINAPI ddraw_surface3_EnumOverlayZOrders(IDirectDrawSurface3 *iface,
2927 DWORD flags, void *context, LPDDENUMSURFACESCALLBACK callback)
2928 {
2929 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2930 struct callback_info info;
2931
2932 TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback);
2933
2934 info.callback = callback;
2935 info.context = context;
2936
2937 return ddraw_surface7_EnumOverlayZOrders(&surface->IDirectDrawSurface7_iface,
2938 flags, &info, EnumCallback);
2939 }
2940
2941 static HRESULT WINAPI ddraw_surface2_EnumOverlayZOrders(IDirectDrawSurface2 *iface,
2942 DWORD flags, void *context, LPDDENUMSURFACESCALLBACK callback)
2943 {
2944 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2945 struct callback_info info;
2946
2947 TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback);
2948
2949 info.callback = callback;
2950 info.context = context;
2951
2952 return ddraw_surface7_EnumOverlayZOrders(&surface->IDirectDrawSurface7_iface,
2953 flags, &info, EnumCallback);
2954 }
2955
2956 static HRESULT WINAPI ddraw_surface1_EnumOverlayZOrders(IDirectDrawSurface *iface,
2957 DWORD flags, void *context, LPDDENUMSURFACESCALLBACK callback)
2958 {
2959 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2960 struct callback_info info;
2961
2962 TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback);
2963
2964 info.callback = callback;
2965 info.context = context;
2966
2967 return ddraw_surface7_EnumOverlayZOrders(&surface->IDirectDrawSurface7_iface,
2968 flags, &info, EnumCallback);
2969 }
2970
2971 /*****************************************************************************
2972 * IDirectDrawSurface7::GetBltStatus
2973 *
2974 * Returns the blitting status
2975 *
2976 * Params:
2977 * Flags: DDGBS_CANBLT or DDGBS_ISBLTDONE
2978 *
2979 * Returns:
2980 * See IWineD3DSurface::Blt
2981 *
2982 *****************************************************************************/
2983 static HRESULT WINAPI ddraw_surface7_GetBltStatus(IDirectDrawSurface7 *iface, DWORD Flags)
2984 {
2985 TRACE("iface %p, flags %#x.\n", iface, Flags);
2986
2987 switch (Flags)
2988 {
2989 case WINEDDGBS_CANBLT:
2990 case WINEDDGBS_ISBLTDONE:
2991 return DD_OK;
2992
2993 default:
2994 return DDERR_INVALIDPARAMS;
2995 }
2996 }
2997
2998 static HRESULT WINAPI ddraw_surface4_GetBltStatus(IDirectDrawSurface4 *iface, DWORD flags)
2999 {
3000 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3001
3002 TRACE("iface %p, flags %#x.\n", iface, flags);
3003
3004 return ddraw_surface7_GetBltStatus(&surface->IDirectDrawSurface7_iface, flags);
3005 }
3006
3007 static HRESULT WINAPI ddraw_surface3_GetBltStatus(IDirectDrawSurface3 *iface, DWORD flags)
3008 {
3009 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3010
3011 TRACE("iface %p, flags %#x.\n", iface, flags);
3012
3013 return ddraw_surface7_GetBltStatus(&surface->IDirectDrawSurface7_iface, flags);
3014 }
3015
3016 static HRESULT WINAPI ddraw_surface2_GetBltStatus(IDirectDrawSurface2 *iface, DWORD flags)
3017 {
3018 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3019
3020 TRACE("iface %p, flags %#x.\n", iface, flags);
3021
3022 return ddraw_surface7_GetBltStatus(&surface->IDirectDrawSurface7_iface, flags);
3023 }
3024
3025 static HRESULT WINAPI ddraw_surface1_GetBltStatus(IDirectDrawSurface *iface, DWORD flags)
3026 {
3027 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3028
3029 TRACE("iface %p, flags %#x.\n", iface, flags);
3030
3031 return ddraw_surface7_GetBltStatus(&surface->IDirectDrawSurface7_iface, flags);
3032 }
3033
3034 /*****************************************************************************
3035 * IDirectDrawSurface7::GetColorKey
3036 *
3037 * Returns the color key assigned to the surface
3038 *
3039 * Params:
3040 * Flags: Some flags
3041 * CKey: Address to store the key to
3042 *
3043 * Returns:
3044 * DD_OK on success
3045 * DDERR_INVALIDPARAMS if CKey is NULL
3046 *
3047 *****************************************************************************/
3048 static HRESULT WINAPI ddraw_surface7_GetColorKey(IDirectDrawSurface7 *iface, DWORD Flags, DDCOLORKEY *CKey)
3049 {
3050 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
3051
3052 TRACE("iface %p, flags %#x, color_key %p.\n", iface, Flags, CKey);
3053
3054 if(!CKey)
3055 return DDERR_INVALIDPARAMS;
3056
3057 wined3d_mutex_lock();
3058
3059 switch (Flags)
3060 {
3061 case DDCKEY_DESTBLT:
3062 if (!(This->surface_desc.dwFlags & DDSD_CKDESTBLT))
3063 {
3064 wined3d_mutex_unlock();
3065 return DDERR_NOCOLORKEY;
3066 }
3067 *CKey = This->surface_desc.ddckCKDestBlt;
3068 break;
3069
3070 case DDCKEY_DESTOVERLAY:
3071 if (!(This->surface_desc.dwFlags & DDSD_CKDESTOVERLAY))
3072 {
3073 wined3d_mutex_unlock();
3074 return DDERR_NOCOLORKEY;
3075 }
3076 *CKey = This->surface_desc.u3.ddckCKDestOverlay;
3077 break;
3078
3079 case DDCKEY_SRCBLT:
3080 if (!(This->surface_desc.dwFlags & DDSD_CKSRCBLT))
3081 {
3082 wined3d_mutex_unlock();
3083 return DDERR_NOCOLORKEY;
3084 }
3085 *CKey = This->surface_desc.ddckCKSrcBlt;
3086 break;
3087
3088 case DDCKEY_SRCOVERLAY:
3089 if (!(This->surface_desc.dwFlags & DDSD_CKSRCOVERLAY))
3090 {
3091 wined3d_mutex_unlock();
3092 return DDERR_NOCOLORKEY;
3093 }
3094 *CKey = This->surface_desc.ddckCKSrcOverlay;
3095 break;
3096
3097 default:
3098 wined3d_mutex_unlock();
3099 return DDERR_INVALIDPARAMS;
3100 }
3101
3102 wined3d_mutex_unlock();
3103
3104 return DD_OK;
3105 }
3106
3107 static HRESULT WINAPI ddraw_surface4_GetColorKey(IDirectDrawSurface4 *iface, DWORD flags, DDCOLORKEY *color_key)
3108 {
3109 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3110
3111 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
3112
3113 return ddraw_surface7_GetColorKey(&surface->IDirectDrawSurface7_iface, flags, color_key);
3114 }
3115
3116 static HRESULT WINAPI ddraw_surface3_GetColorKey(IDirectDrawSurface3 *iface, DWORD flags, DDCOLORKEY *color_key)
3117 {
3118 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3119
3120 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
3121
3122 return ddraw_surface7_GetColorKey(&surface->IDirectDrawSurface7_iface, flags, color_key);
3123 }
3124
3125 static HRESULT WINAPI ddraw_surface2_GetColorKey(IDirectDrawSurface2 *iface, DWORD flags, DDCOLORKEY *color_key)
3126 {
3127 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3128
3129 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
3130
3131 return ddraw_surface7_GetColorKey(&surface->IDirectDrawSurface7_iface, flags, color_key);
3132 }
3133
3134 static HRESULT WINAPI ddraw_surface1_GetColorKey(IDirectDrawSurface *iface, DWORD flags, DDCOLORKEY *color_key)
3135 {
3136 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3137
3138 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
3139
3140 return ddraw_surface7_GetColorKey(&surface->IDirectDrawSurface7_iface, flags, color_key);
3141 }
3142
3143 /*****************************************************************************
3144 * IDirectDrawSurface7::GetFlipStatus
3145 *
3146 * Returns the flipping status of the surface
3147 *
3148 * Params:
3149 * Flags: DDGFS_CANFLIP of DDGFS_ISFLIPDONE
3150 *
3151 * Returns:
3152 * See IWineD3DSurface::GetFlipStatus
3153 *
3154 *****************************************************************************/
3155 static HRESULT WINAPI ddraw_surface7_GetFlipStatus(IDirectDrawSurface7 *iface, DWORD Flags)
3156 {
3157 TRACE("iface %p, flags %#x.\n", iface, Flags);
3158
3159 /* XXX: DDERR_INVALIDSURFACETYPE */
3160
3161 switch (Flags)
3162 {
3163 case WINEDDGFS_CANFLIP:
3164 case WINEDDGFS_ISFLIPDONE:
3165 return DD_OK;
3166
3167 default:
3168 return DDERR_INVALIDPARAMS;
3169 }
3170 }
3171
3172 static HRESULT WINAPI ddraw_surface4_GetFlipStatus(IDirectDrawSurface4 *iface, DWORD flags)
3173 {
3174 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3175
3176 TRACE("iface %p, flags %#x.\n", iface, flags);
3177
3178 return ddraw_surface7_GetFlipStatus(&surface->IDirectDrawSurface7_iface, flags);
3179 }
3180
3181 static HRESULT WINAPI ddraw_surface3_GetFlipStatus(IDirectDrawSurface3 *iface, DWORD flags)
3182 {
3183 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3184
3185 TRACE("iface %p, flags %#x.\n", iface, flags);
3186
3187 return ddraw_surface7_GetFlipStatus(&surface->IDirectDrawSurface7_iface, flags);
3188 }
3189
3190 static HRESULT WINAPI ddraw_surface2_GetFlipStatus(IDirectDrawSurface2 *iface, DWORD flags)
3191 {
3192 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3193
3194 TRACE("iface %p, flags %#x.\n", iface, flags);
3195
3196 return ddraw_surface7_GetFlipStatus(&surface->IDirectDrawSurface7_iface, flags);
3197 }
3198
3199 static HRESULT WINAPI ddraw_surface1_GetFlipStatus(IDirectDrawSurface *iface, DWORD flags)
3200 {
3201 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3202
3203 TRACE("iface %p, flags %#x.\n", iface, flags);
3204
3205 return ddraw_surface7_GetFlipStatus(&surface->IDirectDrawSurface7_iface, flags);
3206 }
3207
3208 /*****************************************************************************
3209 * IDirectDrawSurface7::GetOverlayPosition
3210 *
3211 * Returns the display coordinates of a visible and active overlay surface
3212 *
3213 * Params:
3214 * X
3215 * Y
3216 *
3217 * Returns:
3218 * DDERR_NOTAOVERLAYSURFACE, because it's a stub
3219 *****************************************************************************/
3220 static HRESULT WINAPI ddraw_surface7_GetOverlayPosition(IDirectDrawSurface7 *iface, LONG *x, LONG *y)
3221 {
3222 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3223 HRESULT hr;
3224
3225 TRACE("iface %p, x %p, y %p.\n", iface, x, y);
3226
3227 wined3d_mutex_lock();
3228 hr = wined3d_texture_get_overlay_position(surface->wined3d_texture,
3229 surface->sub_resource_idx, x, y);
3230 wined3d_mutex_unlock();
3231
3232 return hr;
3233 }
3234
3235 static HRESULT WINAPI ddraw_surface4_GetOverlayPosition(IDirectDrawSurface4 *iface, LONG *x, LONG *y)
3236 {
3237 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3238
3239 TRACE("iface %p, x %p, y %p.\n", iface, x, y);
3240
3241 return ddraw_surface7_GetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3242 }
3243
3244 static HRESULT WINAPI ddraw_surface3_GetOverlayPosition(IDirectDrawSurface3 *iface, LONG *x, LONG *y)
3245 {
3246 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3247
3248 TRACE("iface %p, x %p, y %p.\n", iface, x, y);
3249
3250 return ddraw_surface7_GetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3251 }
3252
3253 static HRESULT WINAPI ddraw_surface2_GetOverlayPosition(IDirectDrawSurface2 *iface, LONG *x, LONG *y)
3254 {
3255 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3256
3257 TRACE("iface %p, x %p, y %p.\n", iface, x, y);
3258
3259 return ddraw_surface7_GetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3260 }
3261
3262 static HRESULT WINAPI ddraw_surface1_GetOverlayPosition(IDirectDrawSurface *iface, LONG *x, LONG *y)
3263 {
3264 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3265
3266 TRACE("iface %p, x %p, y %p.\n", iface, x, y);
3267
3268 return ddraw_surface7_GetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3269 }
3270
3271 /*****************************************************************************
3272 * IDirectDrawSurface7::GetPixelFormat
3273 *
3274 * Returns the pixel format of the Surface
3275 *
3276 * Params:
3277 * PixelFormat: Pointer to a DDPIXELFORMAT structure to which the pixel
3278 * format should be written
3279 *
3280 * Returns:
3281 * DD_OK on success
3282 * DDERR_INVALIDPARAMS if PixelFormat is NULL
3283 *
3284 *****************************************************************************/
3285 static HRESULT WINAPI ddraw_surface7_GetPixelFormat(IDirectDrawSurface7 *iface, DDPIXELFORMAT *PixelFormat)
3286 {
3287 /* What is DDERR_INVALIDSURFACETYPE for here? */
3288 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3289
3290 TRACE("iface %p, pixel_format %p.\n", iface, PixelFormat);
3291
3292 if(!PixelFormat)
3293 return DDERR_INVALIDPARAMS;
3294
3295 wined3d_mutex_lock();
3296 DD_STRUCT_COPY_BYSIZE(PixelFormat, &surface->surface_desc.u4.ddpfPixelFormat);
3297 wined3d_mutex_unlock();
3298
3299 return DD_OK;
3300 }
3301
3302 static HRESULT WINAPI ddraw_surface4_GetPixelFormat(IDirectDrawSurface4 *iface, DDPIXELFORMAT *pixel_format)
3303 {
3304 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3305
3306 TRACE("iface %p, pixel_format %p.\n", iface, pixel_format);
3307
3308 return ddraw_surface7_GetPixelFormat(&surface->IDirectDrawSurface7_iface, pixel_format);
3309 }
3310
3311 static HRESULT WINAPI ddraw_surface3_GetPixelFormat(IDirectDrawSurface3 *iface, DDPIXELFORMAT *pixel_format)
3312 {
3313 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3314
3315 TRACE("iface %p, pixel_format %p.\n", iface, pixel_format);
3316
3317 return ddraw_surface7_GetPixelFormat(&surface->IDirectDrawSurface7_iface, pixel_format);
3318 }
3319
3320 static HRESULT WINAPI ddraw_surface2_GetPixelFormat(IDirectDrawSurface2 *iface, DDPIXELFORMAT *pixel_format)
3321 {
3322 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3323
3324 TRACE("iface %p, pixel_format %p.\n", iface, pixel_format);
3325
3326 return ddraw_surface7_GetPixelFormat(&surface->IDirectDrawSurface7_iface, pixel_format);
3327 }
3328
3329 static HRESULT WINAPI ddraw_surface1_GetPixelFormat(IDirectDrawSurface *iface, DDPIXELFORMAT *pixel_format)
3330 {
3331 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3332
3333 TRACE("iface %p, pixel_format %p.\n", iface, pixel_format);
3334
3335 return ddraw_surface7_GetPixelFormat(&surface->IDirectDrawSurface7_iface, pixel_format);
3336 }
3337
3338 /*****************************************************************************
3339 * IDirectDrawSurface7::GetSurfaceDesc
3340 *
3341 * Returns the description of this surface
3342 *
3343 * Params:
3344 * DDSD: Address of a DDSURFACEDESC2 structure that is to be filled with the
3345 * surface desc
3346 *
3347 * Returns:
3348 * DD_OK on success
3349 * DDERR_INVALIDPARAMS if DDSD is NULL
3350 *
3351 *****************************************************************************/
3352 static HRESULT WINAPI ddraw_surface7_GetSurfaceDesc(IDirectDrawSurface7 *iface, DDSURFACEDESC2 *DDSD)
3353 {
3354 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3355
3356 TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
3357
3358 if(!DDSD)
3359 return DDERR_INVALIDPARAMS;
3360
3361 if (DDSD->dwSize != sizeof(DDSURFACEDESC2))
3362 {
3363 WARN("Incorrect struct size %d, returning DDERR_INVALIDPARAMS\n",DDSD->dwSize);
3364 return DDERR_INVALIDPARAMS;
3365 }
3366
3367 wined3d_mutex_lock();
3368 DD_STRUCT_COPY_BYSIZE(DDSD, &surface->surface_desc);
3369 TRACE("Returning surface desc:\n");
3370 if (TRACE_ON(ddraw)) DDRAW_dump_surface_desc(DDSD);
3371 wined3d_mutex_unlock();
3372
3373 return DD_OK;
3374 }
3375
3376 static HRESULT WINAPI ddraw_surface4_GetSurfaceDesc(IDirectDrawSurface4 *iface, DDSURFACEDESC2 *DDSD)
3377 {
3378 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3379
3380 TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
3381
3382 return ddraw_surface7_GetSurfaceDesc(&surface->IDirectDrawSurface7_iface, DDSD);
3383 }
3384
3385 static HRESULT WINAPI ddraw_surface3_GetSurfaceDesc(IDirectDrawSurface3 *iface, DDSURFACEDESC *surface_desc)
3386 {
3387 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3388
3389 TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
3390
3391 if (!surface_desc) return DDERR_INVALIDPARAMS;
3392
3393 if (surface_desc->dwSize != sizeof(DDSURFACEDESC))
3394 {
3395 WARN("Incorrect structure size %u, returning DDERR_INVALIDPARAMS.\n", surface_desc->dwSize);
3396 return DDERR_INVALIDPARAMS;
3397 }
3398
3399 wined3d_mutex_lock();
3400 DDSD2_to_DDSD(&surface->surface_desc, surface_desc);
3401 TRACE("Returning surface desc:\n");
3402 if (TRACE_ON(ddraw))
3403 {
3404 /* DDRAW_dump_surface_desc handles the smaller size */
3405 DDRAW_dump_surface_desc((DDSURFACEDESC2 *)surface_desc);
3406 }
3407 wined3d_mutex_unlock();
3408
3409 return DD_OK;
3410 }
3411
3412 static HRESULT WINAPI ddraw_surface2_GetSurfaceDesc(IDirectDrawSurface2 *iface, DDSURFACEDESC *DDSD)
3413 {
3414 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3415
3416 TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
3417
3418 return ddraw_surface3_GetSurfaceDesc(&surface->IDirectDrawSurface3_iface, DDSD);
3419 }
3420
3421 static HRESULT WINAPI ddraw_surface1_GetSurfaceDesc(IDirectDrawSurface *iface, DDSURFACEDESC *DDSD)
3422 {
3423 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3424
3425 TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
3426
3427 return ddraw_surface3_GetSurfaceDesc(&surface->IDirectDrawSurface3_iface, DDSD);
3428 }
3429
3430 /*****************************************************************************
3431 * IDirectDrawSurface7::Initialize
3432 *
3433 * Initializes the surface. This is a no-op in Wine
3434 *
3435 * Params:
3436 * DD: Pointer to an DirectDraw interface
3437 * DDSD: Surface description for initialization
3438 *
3439 * Returns:
3440 * DDERR_ALREADYINITIALIZED
3441 *
3442 *****************************************************************************/
3443 static HRESULT WINAPI ddraw_surface7_Initialize(IDirectDrawSurface7 *iface,
3444 IDirectDraw *ddraw, DDSURFACEDESC2 *surface_desc)
3445 {
3446 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
3447
3448 return DDERR_ALREADYINITIALIZED;
3449 }
3450
3451 static HRESULT WINAPI ddraw_surface4_Initialize(IDirectDrawSurface4 *iface,
3452 IDirectDraw *ddraw, DDSURFACEDESC2 *surface_desc)
3453 {
3454 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3455
3456 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
3457
3458 return ddraw_surface7_Initialize(&surface->IDirectDrawSurface7_iface,
3459 ddraw, surface_desc);
3460 }
3461
3462 static HRESULT WINAPI ddraw_surface3_Initialize(IDirectDrawSurface3 *iface,
3463 IDirectDraw *ddraw, DDSURFACEDESC *surface_desc)
3464 {
3465 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3466 DDSURFACEDESC2 surface_desc2;
3467
3468 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
3469
3470 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
3471 return ddraw_surface7_Initialize(&surface->IDirectDrawSurface7_iface,
3472 ddraw, surface_desc ? &surface_desc2 : NULL);
3473 }
3474
3475 static HRESULT WINAPI ddraw_surface2_Initialize(IDirectDrawSurface2 *iface,
3476 IDirectDraw *ddraw, DDSURFACEDESC *surface_desc)
3477 {
3478 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3479 DDSURFACEDESC2 surface_desc2;
3480
3481 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
3482
3483 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
3484 return ddraw_surface7_Initialize(&surface->IDirectDrawSurface7_iface,
3485 ddraw, surface_desc ? &surface_desc2 : NULL);
3486 }
3487
3488 static HRESULT WINAPI ddraw_surface1_Initialize(IDirectDrawSurface *iface,
3489 IDirectDraw *ddraw, DDSURFACEDESC *surface_desc)
3490 {
3491 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3492 DDSURFACEDESC2 surface_desc2;
3493
3494 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
3495
3496 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
3497 return ddraw_surface7_Initialize(&surface->IDirectDrawSurface7_iface,
3498 ddraw, surface_desc ? &surface_desc2 : NULL);
3499 }
3500
3501 /*****************************************************************************
3502 * IDirect3DTexture1::Initialize
3503 *
3504 * The sdk says it's not implemented
3505 *
3506 * Params:
3507 * ?
3508 *
3509 * Returns
3510 * DDERR_UNSUPPORTED
3511 *
3512 *****************************************************************************/
3513 static HRESULT WINAPI d3d_texture1_Initialize(IDirect3DTexture *iface,
3514 IDirect3DDevice *device, IDirectDrawSurface *surface)
3515 {
3516 TRACE("iface %p, device %p, surface %p.\n", iface, device, surface);
3517
3518 return DDERR_UNSUPPORTED; /* Unchecked */
3519 }
3520
3521 /*****************************************************************************
3522 * IDirectDrawSurface7::IsLost
3523 *
3524 * Checks if the surface is lost
3525 *
3526 * Returns:
3527 * DD_OK, if the surface is usable
3528 * DDERR_ISLOST if the surface is lost
3529 * See IWineD3DSurface::IsLost for more details
3530 *
3531 *****************************************************************************/
3532 static HRESULT WINAPI ddraw_surface7_IsLost(IDirectDrawSurface7 *iface)
3533 {
3534 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3535
3536 TRACE("iface %p.\n", iface);
3537
3538 if (surface->ddraw->device_state != DDRAW_DEVICE_STATE_OK || surface->is_lost)
3539 return DDERR_SURFACELOST;
3540
3541 return DD_OK;
3542 }
3543
3544 static HRESULT WINAPI ddraw_surface4_IsLost(IDirectDrawSurface4 *iface)
3545 {
3546 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3547
3548 TRACE("iface %p.\n", iface);
3549
3550 return ddraw_surface7_IsLost(&surface->IDirectDrawSurface7_iface);
3551 }
3552
3553 static HRESULT WINAPI ddraw_surface3_IsLost(IDirectDrawSurface3 *iface)
3554 {
3555 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3556
3557 TRACE("iface %p.\n", iface);
3558
3559 return ddraw_surface7_IsLost(&surface->IDirectDrawSurface7_iface);
3560 }
3561
3562 static HRESULT WINAPI ddraw_surface2_IsLost(IDirectDrawSurface2 *iface)
3563 {
3564 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3565
3566 TRACE("iface %p.\n", iface);
3567
3568 return ddraw_surface7_IsLost(&surface->IDirectDrawSurface7_iface);
3569 }
3570
3571 static HRESULT WINAPI ddraw_surface1_IsLost(IDirectDrawSurface *iface)
3572 {
3573 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3574
3575 TRACE("iface %p.\n", iface);
3576
3577 return ddraw_surface7_IsLost(&surface->IDirectDrawSurface7_iface);
3578 }
3579
3580 /*****************************************************************************
3581 * IDirectDrawSurface7::Restore
3582 *
3583 * Restores a lost surface. This makes the surface usable again, but
3584 * doesn't reload its old contents
3585 *
3586 * Returns:
3587 * DD_OK on success
3588 * See IWineD3DSurface::Restore for more details
3589 *
3590 *****************************************************************************/
3591 static HRESULT WINAPI ddraw_surface7_Restore(IDirectDrawSurface7 *iface)
3592 {
3593 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3594
3595 TRACE("iface %p.\n", iface);
3596
3597 ddraw_update_lost_surfaces(surface->ddraw);
3598 surface->is_lost = FALSE;
3599
3600 return DD_OK;
3601 }
3602
3603 static HRESULT WINAPI ddraw_surface4_Restore(IDirectDrawSurface4 *iface)
3604 {
3605 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3606
3607 TRACE("iface %p.\n", iface);
3608
3609 return ddraw_surface7_Restore(&surface->IDirectDrawSurface7_iface);
3610 }
3611
3612 static HRESULT WINAPI ddraw_surface3_Restore(IDirectDrawSurface3 *iface)
3613 {
3614 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3615
3616 TRACE("iface %p.\n", iface);
3617
3618 return ddraw_surface7_Restore(&surface->IDirectDrawSurface7_iface);
3619 }
3620
3621 static HRESULT WINAPI ddraw_surface2_Restore(IDirectDrawSurface2 *iface)
3622 {
3623 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3624
3625 TRACE("iface %p.\n", iface);
3626
3627 return ddraw_surface7_Restore(&surface->IDirectDrawSurface7_iface);
3628 }
3629
3630 static HRESULT WINAPI ddraw_surface1_Restore(IDirectDrawSurface *iface)
3631 {
3632 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3633
3634 TRACE("iface %p.\n", iface);
3635
3636 return ddraw_surface7_Restore(&surface->IDirectDrawSurface7_iface);
3637 }
3638
3639 /*****************************************************************************
3640 * IDirectDrawSurface7::SetOverlayPosition
3641 *
3642 * Changes the display coordinates of an overlay surface
3643 *
3644 * Params:
3645 * X:
3646 * Y:
3647 *
3648 * Returns:
3649 * DDERR_NOTAOVERLAYSURFACE, because we don't support overlays right now
3650 *****************************************************************************/
3651 static HRESULT WINAPI ddraw_surface7_SetOverlayPosition(IDirectDrawSurface7 *iface, LONG x, LONG y)
3652 {
3653 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3654 HRESULT hr;
3655
3656 TRACE("iface %p, x %d, y %d.\n", iface, x, y);
3657
3658 wined3d_mutex_lock();
3659 hr = wined3d_texture_set_overlay_position(surface->wined3d_texture,
3660 surface->sub_resource_idx, x, y);
3661 wined3d_mutex_unlock();
3662
3663 return hr;
3664 }
3665
3666 static HRESULT WINAPI ddraw_surface4_SetOverlayPosition(IDirectDrawSurface4 *iface, LONG x, LONG y)
3667 {
3668 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3669
3670 TRACE("iface %p, x %d, y %d.\n", iface, x, y);
3671
3672 return ddraw_surface7_SetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3673 }
3674
3675 static HRESULT WINAPI ddraw_surface3_SetOverlayPosition(IDirectDrawSurface3 *iface, LONG x, LONG y)
3676 {
3677 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3678
3679 TRACE("iface %p, x %d, y %d.\n", iface, x, y);
3680
3681 return ddraw_surface7_SetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3682 }
3683
3684 static HRESULT WINAPI ddraw_surface2_SetOverlayPosition(IDirectDrawSurface2 *iface, LONG x, LONG y)
3685 {
3686 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3687
3688 TRACE("iface %p, x %d, y %d.\n", iface, x, y);
3689
3690 return ddraw_surface7_SetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3691 }
3692
3693 static HRESULT WINAPI ddraw_surface1_SetOverlayPosition(IDirectDrawSurface *iface, LONG x, LONG y)
3694 {
3695 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3696
3697 TRACE("iface %p, x %d, y %d.\n", iface, x, y);
3698
3699 return ddraw_surface7_SetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3700 }
3701
3702 /*****************************************************************************
3703 * IDirectDrawSurface7::UpdateOverlay
3704 *
3705 * Modifies the attributes of an overlay surface.
3706 *
3707 * Params:
3708 * SrcRect: The section of the source being used for the overlay
3709 * DstSurface: Address of the surface that is overlaid
3710 * DstRect: Place of the overlay
3711 * Flags: some DDOVER_* flags
3712 *
3713 * Returns:
3714 * DDERR_UNSUPPORTED, because we don't support overlays
3715 *
3716 *****************************************************************************/
3717 static HRESULT WINAPI ddraw_surface7_UpdateOverlay(IDirectDrawSurface7 *iface, RECT *src_rect,
3718 IDirectDrawSurface7 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
3719 {
3720 struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface7(iface);
3721 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface7(dst_surface);
3722 struct wined3d_texture *dst_wined3d_texture = NULL;
3723 unsigned int dst_sub_resource_idx = 0;
3724 HRESULT hr;
3725
3726 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
3727 iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
3728
3729 if (fx)
3730 FIXME("Ignoring fx %p.\n", fx);
3731
3732 wined3d_mutex_lock();
3733 if (dst_impl)
3734 {
3735 dst_wined3d_texture = dst_impl->wined3d_texture;
3736 dst_sub_resource_idx = dst_impl->sub_resource_idx;
3737 }
3738 hr = wined3d_texture_update_overlay(src_impl->wined3d_texture, src_impl->sub_resource_idx,
3739 src_rect, dst_wined3d_texture, dst_sub_resource_idx, dst_rect, flags);
3740 wined3d_mutex_unlock();
3741
3742 switch (hr)
3743 {
3744 case WINED3DERR_INVALIDCALL: return DDERR_INVALIDPARAMS;
3745 case WINEDDERR_NOTAOVERLAYSURFACE: return DDERR_NOTAOVERLAYSURFACE;
3746 case WINEDDERR_OVERLAYNOTVISIBLE: return DDERR_OVERLAYNOTVISIBLE;
3747 default:
3748 return hr;
3749 }
3750 }
3751
3752 static HRESULT WINAPI ddraw_surface4_UpdateOverlay(IDirectDrawSurface4 *iface, RECT *src_rect,
3753 IDirectDrawSurface4 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
3754 {
3755 struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface4(iface);
3756 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface4(dst_surface);
3757
3758 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
3759 iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
3760
3761 return ddraw_surface7_UpdateOverlay(&src_impl->IDirectDrawSurface7_iface, src_rect,
3762 dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx);
3763 }
3764
3765 static HRESULT WINAPI ddraw_surface3_UpdateOverlay(IDirectDrawSurface3 *iface, RECT *src_rect,
3766 IDirectDrawSurface3 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
3767 {
3768 struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface3(iface);
3769 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface3(dst_surface);
3770
3771 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
3772 iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
3773
3774 return ddraw_surface7_UpdateOverlay(&src_impl->IDirectDrawSurface7_iface, src_rect,
3775 dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx);
3776 }
3777
3778 static HRESULT WINAPI ddraw_surface2_UpdateOverlay(IDirectDrawSurface2 *iface, RECT *src_rect,
3779 IDirectDrawSurface2 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
3780 {
3781 struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface2(iface);
3782 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface2(dst_surface);
3783
3784 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
3785 iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
3786
3787 return ddraw_surface7_UpdateOverlay(&src_impl->IDirectDrawSurface7_iface, src_rect,
3788 dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx);
3789 }
3790
3791 static HRESULT WINAPI ddraw_surface1_UpdateOverlay(IDirectDrawSurface *iface, RECT *src_rect,
3792 IDirectDrawSurface *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
3793 {
3794 struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface(iface);
3795 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface(dst_surface);
3796
3797 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
3798 iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
3799
3800 return ddraw_surface7_UpdateOverlay(&src_impl->IDirectDrawSurface7_iface, src_rect,
3801 dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx);
3802 }
3803
3804 /*****************************************************************************
3805 * IDirectDrawSurface7::UpdateOverlayDisplay
3806 *
3807 * The DX7 sdk says that it's not implemented
3808 *
3809 * Params:
3810 * Flags: ?
3811 *
3812 * Returns: DDERR_UNSUPPORTED, because we don't support overlays
3813 *
3814 *****************************************************************************/
3815 static HRESULT WINAPI ddraw_surface7_UpdateOverlayDisplay(IDirectDrawSurface7 *iface, DWORD Flags)
3816 {
3817 TRACE("iface %p, flags %#x.\n", iface, Flags);
3818
3819 return DDERR_UNSUPPORTED;
3820 }
3821
3822 static HRESULT WINAPI ddraw_surface4_UpdateOverlayDisplay(IDirectDrawSurface4 *iface, DWORD flags)
3823 {
3824 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3825
3826 TRACE("iface %p, flags %#x.\n", iface, flags);
3827
3828 return ddraw_surface7_UpdateOverlayDisplay(&surface->IDirectDrawSurface7_iface, flags);
3829 }
3830
3831 static HRESULT WINAPI ddraw_surface3_UpdateOverlayDisplay(IDirectDrawSurface3 *iface, DWORD flags)
3832 {
3833 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3834
3835 TRACE("iface %p, flags %#x.\n", iface, flags);
3836
3837 return ddraw_surface7_UpdateOverlayDisplay(&surface->IDirectDrawSurface7_iface, flags);
3838 }
3839
3840 static HRESULT WINAPI ddraw_surface2_UpdateOverlayDisplay(IDirectDrawSurface2 *iface, DWORD flags)
3841 {
3842 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3843
3844 TRACE("iface %p, flags %#x.\n", iface, flags);
3845
3846 return ddraw_surface7_UpdateOverlayDisplay(&surface->IDirectDrawSurface7_iface, flags);
3847 }
3848
3849 static HRESULT WINAPI ddraw_surface1_UpdateOverlayDisplay(IDirectDrawSurface *iface, DWORD flags)
3850 {
3851 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3852
3853 TRACE("iface %p, flags %#x.\n", iface, flags);
3854
3855 return ddraw_surface7_UpdateOverlayDisplay(&surface->IDirectDrawSurface7_iface, flags);
3856 }
3857
3858 /*****************************************************************************
3859 * IDirectDrawSurface7::UpdateOverlayZOrder
3860 *
3861 * Sets an overlay's Z order
3862 *
3863 * Params:
3864 * Flags: DDOVERZ_* flags
3865 * DDSRef: Defines the relative position in the overlay chain
3866 *
3867 * Returns:
3868 * DDERR_NOTOVERLAYSURFACE, because we don't support overlays
3869 *
3870 *****************************************************************************/
3871 static HRESULT WINAPI ddraw_surface7_UpdateOverlayZOrder(IDirectDrawSurface7 *iface,
3872 DWORD flags, IDirectDrawSurface7 *reference)
3873 {
3874 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3875
3876 FIXME("iface %p, flags %#x, reference %p stub!\n", iface, flags, reference);
3877
3878 wined3d_mutex_lock();
3879 if (!(surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_OVERLAY))
3880 {
3881 WARN("Not an overlay surface.\n");
3882 wined3d_mutex_unlock();
3883 return DDERR_NOTAOVERLAYSURFACE;
3884 }
3885 wined3d_mutex_unlock();
3886
3887 return DD_OK;
3888 }
3889
3890 static HRESULT WINAPI ddraw_surface4_UpdateOverlayZOrder(IDirectDrawSurface4 *iface,
3891 DWORD flags, IDirectDrawSurface4 *reference)
3892 {
3893 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3894 struct ddraw_surface *reference_impl = unsafe_impl_from_IDirectDrawSurface4(reference);
3895
3896 TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference);
3897
3898 return ddraw_surface7_UpdateOverlayZOrder(&surface->IDirectDrawSurface7_iface, flags,
3899 reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL);
3900 }
3901
3902 static HRESULT WINAPI ddraw_surface3_UpdateOverlayZOrder(IDirectDrawSurface3 *iface,
3903 DWORD flags, IDirectDrawSurface3 *reference)
3904 {
3905 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3906 struct ddraw_surface *reference_impl = unsafe_impl_from_IDirectDrawSurface3(reference);
3907
3908 TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference);
3909
3910 return ddraw_surface7_UpdateOverlayZOrder(&surface->IDirectDrawSurface7_iface, flags,
3911 reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL);
3912 }
3913
3914 static HRESULT WINAPI ddraw_surface2_UpdateOverlayZOrder(IDirectDrawSurface2 *iface,
3915 DWORD flags, IDirectDrawSurface2 *reference)
3916 {
3917 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3918 struct ddraw_surface *reference_impl = unsafe_impl_from_IDirectDrawSurface2(reference);
3919
3920 TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference);
3921
3922 return ddraw_surface7_UpdateOverlayZOrder(&surface->IDirectDrawSurface7_iface, flags,
3923 reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL);
3924 }
3925
3926 static HRESULT WINAPI ddraw_surface1_UpdateOverlayZOrder(IDirectDrawSurface *iface,
3927 DWORD flags, IDirectDrawSurface *reference)
3928 {
3929 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3930 struct ddraw_surface *reference_impl = unsafe_impl_from_IDirectDrawSurface(reference);
3931
3932 TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference);
3933
3934 return ddraw_surface7_UpdateOverlayZOrder(&surface->IDirectDrawSurface7_iface, flags,
3935 reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL);
3936 }
3937
3938 /*****************************************************************************
3939 * IDirectDrawSurface7::GetDDInterface
3940 *
3941 * Returns the IDirectDraw7 interface pointer of the DirectDraw object this
3942 * surface belongs to
3943 *
3944 * Params:
3945 * DD: Address to write the interface pointer to
3946 *
3947 * Returns:
3948 * DD_OK on success
3949 * DDERR_INVALIDPARAMS if DD is NULL
3950 *
3951 *****************************************************************************/
3952 static HRESULT WINAPI ddraw_surface7_GetDDInterface(IDirectDrawSurface7 *iface, void **DD)
3953 {
3954 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
3955
3956 TRACE("iface %p, ddraw %p.\n", iface, DD);
3957
3958 if(!DD)
3959 return DDERR_INVALIDPARAMS;
3960
3961 switch(This->version)
3962 {
3963 case 7:
3964 *DD = &This->ddraw->IDirectDraw7_iface;
3965 break;
3966
3967 case 4:
3968 *DD = &This->ddraw->IDirectDraw4_iface;
3969 break;
3970
3971 case 2:
3972 *DD = &This->ddraw->IDirectDraw2_iface;
3973 break;
3974
3975 case 1:
3976 *DD = &This->ddraw->IDirectDraw_iface;
3977 break;
3978
3979 }
3980 IUnknown_AddRef((IUnknown *)*DD);
3981
3982 return DD_OK;
3983 }
3984
3985 static HRESULT WINAPI ddraw_surface4_GetDDInterface(IDirectDrawSurface4 *iface, void **ddraw)
3986 {
3987 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3988
3989 TRACE("iface %p, ddraw %p.\n", iface, ddraw);
3990
3991 return ddraw_surface7_GetDDInterface(&surface->IDirectDrawSurface7_iface, ddraw);
3992 }
3993
3994 static HRESULT WINAPI ddraw_surface3_GetDDInterface(IDirectDrawSurface3 *iface, void **ddraw)
3995 {
3996 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3997
3998 TRACE("iface %p, ddraw %p.\n", iface, ddraw);
3999
4000 return ddraw_surface7_GetDDInterface(&surface->IDirectDrawSurface7_iface, ddraw);
4001 }
4002
4003 static HRESULT WINAPI ddraw_surface2_GetDDInterface(IDirectDrawSurface2 *iface, void **ddraw)
4004 {
4005 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
4006
4007 TRACE("iface %p, ddraw %p.\n", iface, ddraw);
4008
4009 return ddraw_surface7_GetDDInterface(&surface->IDirectDrawSurface7_iface, ddraw);
4010 }
4011
4012 static HRESULT WINAPI ddraw_surface7_ChangeUniquenessValue(IDirectDrawSurface7 *iface)
4013 {
4014 TRACE("iface %p.\n", iface);
4015
4016 return DD_OK;
4017 }
4018
4019 static HRESULT WINAPI ddraw_surface4_ChangeUniquenessValue(IDirectDrawSurface4 *iface)
4020 {
4021 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4022
4023 TRACE("iface %p.\n", iface);
4024
4025 return ddraw_surface7_ChangeUniquenessValue(&surface->IDirectDrawSurface7_iface);
4026 }
4027
4028 static HRESULT WINAPI ddraw_surface7_GetUniquenessValue(IDirectDrawSurface7 *iface, DWORD *pValue)
4029 {
4030 TRACE("iface %p, value %p.\n", iface, pValue);
4031
4032 *pValue = 0;
4033
4034 return DD_OK;
4035 }
4036
4037 static HRESULT WINAPI ddraw_surface4_GetUniquenessValue(IDirectDrawSurface4 *iface, DWORD *pValue)
4038 {
4039 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4040
4041 TRACE("iface %p, value %p.\n", iface, pValue);
4042
4043 return ddraw_surface7_GetUniquenessValue(&surface->IDirectDrawSurface7_iface, pValue);
4044 }
4045
4046 /*****************************************************************************
4047 * IDirectDrawSurface7::SetLOD
4048 *
4049 * Sets the level of detail of a texture
4050 *
4051 * Params:
4052 * MaxLOD: LOD to set
4053 *
4054 * Returns:
4055 * DD_OK on success
4056 * DDERR_INVALIDOBJECT if the surface is invalid for this method
4057 *
4058 *****************************************************************************/
4059 static HRESULT WINAPI ddraw_surface7_SetLOD(IDirectDrawSurface7 *iface, DWORD MaxLOD)
4060 {
4061 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
4062 HRESULT hr;
4063
4064 TRACE("iface %p, lod %u.\n", iface, MaxLOD);
4065
4066 wined3d_mutex_lock();
4067 if (!(surface->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE))
4068 {
4069 wined3d_mutex_unlock();
4070 return DDERR_INVALIDOBJECT;
4071 }
4072
4073 hr = wined3d_texture_set_lod(surface->wined3d_texture, MaxLOD);
4074 wined3d_mutex_unlock();
4075
4076 return hr;
4077 }
4078
4079 /*****************************************************************************
4080 * IDirectDrawSurface7::GetLOD
4081 *
4082 * Returns the level of detail of a Direct3D texture
4083 *
4084 * Params:
4085 * MaxLOD: Address to write the LOD to
4086 *
4087 * Returns:
4088 * DD_OK on success
4089 * DDERR_INVALIDPARAMS if MaxLOD is NULL
4090 * DDERR_INVALIDOBJECT if the surface is invalid for this method
4091 *
4092 *****************************************************************************/
4093 static HRESULT WINAPI ddraw_surface7_GetLOD(IDirectDrawSurface7 *iface, DWORD *MaxLOD)
4094 {
4095 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
4096
4097 TRACE("iface %p, lod %p.\n", iface, MaxLOD);
4098
4099 if(!MaxLOD)
4100 return DDERR_INVALIDPARAMS;
4101
4102 wined3d_mutex_lock();
4103 if (!(surface->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE))
4104 {
4105 wined3d_mutex_unlock();
4106 return DDERR_INVALIDOBJECT;
4107 }
4108
4109 *MaxLOD = wined3d_texture_get_lod(surface->wined3d_texture);
4110 wined3d_mutex_unlock();
4111
4112 return DD_OK;
4113 }
4114
4115 /*****************************************************************************
4116 * IDirectDrawSurface7::BltFast
4117 *
4118 * Performs a fast Blit.
4119 *
4120 * Params:
4121 * dstx: The x coordinate to blit to on the destination
4122 * dsty: The y coordinate to blit to on the destination
4123 * Source: The source surface
4124 * rsrc: The source rectangle
4125 * trans: Type of transfer. Some DDBLTFAST_* flags
4126 *
4127 * Returns:
4128 * DD_OK on success
4129 * For more details, see IWineD3DSurface::BltFast
4130 *
4131 *****************************************************************************/
4132 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_BltFast(IDirectDrawSurface7 *iface,
4133 DWORD dst_x, DWORD dst_y, IDirectDrawSurface7 *src_surface, RECT *src_rect, DWORD trans)
4134 {
4135 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface7(iface);
4136 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface7(src_surface);
4137 DWORD src_w, src_h, dst_w, dst_h;
4138 HRESULT hr = DD_OK;
4139 RECT dst_rect, s;
4140 DWORD flags = 0;
4141
4142 TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
4143 iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), trans);
4144
4145 dst_w = dst_impl->surface_desc.dwWidth;
4146 dst_h = dst_impl->surface_desc.dwHeight;
4147
4148 if (!src_rect)
4149 {
4150 SetRect(&s, 0, 0, src_impl->surface_desc.dwWidth, src_impl->surface_desc.dwHeight);
4151 src_rect = &s;
4152 }
4153
4154 src_w = src_rect->right - src_rect->left;
4155 src_h = src_rect->bottom - src_rect->top;
4156 if (src_w > dst_w || dst_x > dst_w - src_w
4157 || src_h > dst_h || dst_y > dst_h - src_h)
4158 {
4159 WARN("Destination area out of bounds, returning DDERR_INVALIDRECT.\n");
4160 return DDERR_INVALIDRECT;
4161 }
4162
4163 SetRect(&dst_rect, dst_x, dst_y, dst_x + src_w, dst_y + src_h);
4164 if (trans & DDBLTFAST_SRCCOLORKEY)
4165 flags |= WINED3D_BLT_SRC_CKEY;
4166 if (trans & DDBLTFAST_DESTCOLORKEY)
4167 flags |= WINED3D_BLT_DST_CKEY;
4168 if (trans & DDBLTFAST_WAIT)
4169 flags |= WINED3D_BLT_WAIT;
4170 if (trans & DDBLTFAST_DONOTWAIT)
4171 flags |= WINED3D_BLT_DO_NOT_WAIT;
4172
4173 wined3d_mutex_lock();
4174 if (dst_impl->clipper)
4175 {
4176 wined3d_mutex_unlock();
4177 WARN("Destination surface has a clipper set, returning DDERR_BLTFASTCANTCLIP.\n");
4178 return DDERR_BLTFASTCANTCLIP;
4179 }
4180
4181 if (src_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
4182 hr = ddraw_surface_update_frontbuffer(src_impl, src_rect, TRUE);
4183 if (SUCCEEDED(hr))
4184 hr = wined3d_texture_blt(dst_impl->wined3d_texture, dst_impl->sub_resource_idx, &dst_rect,
4185 src_impl->wined3d_texture, src_impl->sub_resource_idx, src_rect, flags, NULL, WINED3D_TEXF_POINT);
4186 if (SUCCEEDED(hr) && (dst_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE))
4187 hr = ddraw_surface_update_frontbuffer(dst_impl, &dst_rect, FALSE);
4188 wined3d_mutex_unlock();
4189
4190 switch(hr)
4191 {
4192 case WINED3DERR_NOTAVAILABLE: return DDERR_UNSUPPORTED;
4193 default: return hr;
4194 }
4195 }
4196
4197 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface4_BltFast(IDirectDrawSurface4 *iface, DWORD dst_x, DWORD dst_y,
4198 IDirectDrawSurface4 *src_surface, RECT *src_rect, DWORD flags)
4199 {
4200 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface4(iface);
4201 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface4(src_surface);
4202
4203 TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
4204 iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags);
4205
4206 return ddraw_surface7_BltFast(&dst_impl->IDirectDrawSurface7_iface, dst_x, dst_y,
4207 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags);
4208 }
4209
4210 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface3_BltFast(IDirectDrawSurface3 *iface, DWORD dst_x, DWORD dst_y,
4211 IDirectDrawSurface3 *src_surface, RECT *src_rect, DWORD flags)
4212 {
4213 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface3(iface);
4214 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface3(src_surface);
4215
4216 TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
4217 iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags);
4218
4219 return ddraw_surface7_BltFast(&dst_impl->IDirectDrawSurface7_iface, dst_x, dst_y,
4220 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags);
4221 }
4222
4223 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface2_BltFast(IDirectDrawSurface2 *iface, DWORD dst_x, DWORD dst_y,
4224 IDirectDrawSurface2 *src_surface, RECT *src_rect, DWORD flags)
4225 {
4226 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface2(iface);
4227 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface2(src_surface);
4228
4229 TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
4230 iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags);
4231
4232 return ddraw_surface7_BltFast(&dst_impl->IDirectDrawSurface7_iface, dst_x, dst_y,
4233 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags);
4234 }
4235
4236 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_BltFast(IDirectDrawSurface *iface, DWORD dst_x, DWORD dst_y,
4237 IDirectDrawSurface *src_surface, RECT *src_rect, DWORD flags)
4238 {
4239 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface(iface);
4240 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface(src_surface);
4241
4242 TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
4243 iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags);
4244
4245 return ddraw_surface7_BltFast(&dst_impl->IDirectDrawSurface7_iface, dst_x, dst_y,
4246 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags);
4247 }
4248
4249 /*****************************************************************************
4250 * IDirectDrawSurface7::GetClipper
4251 *
4252 * Returns the IDirectDrawClipper interface of the clipper assigned to this
4253 * surface
4254 *
4255 * Params:
4256 * Clipper: Address to store the interface pointer at
4257 *
4258 * Returns:
4259 * DD_OK on success
4260 * DDERR_INVALIDPARAMS if Clipper is NULL
4261 * DDERR_NOCLIPPERATTACHED if there's no clipper attached
4262 *
4263 *****************************************************************************/
4264 static HRESULT WINAPI ddraw_surface7_GetClipper(IDirectDrawSurface7 *iface, IDirectDrawClipper **Clipper)
4265 {
4266 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
4267
4268 TRACE("iface %p, clipper %p.\n", iface, Clipper);
4269
4270 if (!Clipper)
4271 return DDERR_INVALIDPARAMS;
4272
4273 wined3d_mutex_lock();
4274 if (!surface->clipper)
4275 {
4276 wined3d_mutex_unlock();
4277 return DDERR_NOCLIPPERATTACHED;
4278 }
4279
4280 *Clipper = (IDirectDrawClipper *)surface->clipper;
4281 IDirectDrawClipper_AddRef(*Clipper);
4282 wined3d_mutex_unlock();
4283
4284 return DD_OK;
4285 }
4286
4287 static HRESULT WINAPI ddraw_surface4_GetClipper(IDirectDrawSurface4 *iface, IDirectDrawClipper **clipper)
4288 {
4289 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4290
4291 TRACE("iface %p, clipper %p.\n", iface, clipper);
4292
4293 return ddraw_surface7_GetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4294 }
4295
4296 static HRESULT WINAPI ddraw_surface3_GetClipper(IDirectDrawSurface3 *iface, IDirectDrawClipper **clipper)
4297 {
4298 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4299
4300 TRACE("iface %p, clipper %p.\n", iface, clipper);
4301
4302 return ddraw_surface7_GetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4303 }
4304
4305 static HRESULT WINAPI ddraw_surface2_GetClipper(IDirectDrawSurface2 *iface, IDirectDrawClipper **clipper)
4306 {
4307 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
4308
4309 TRACE("iface %p, clipper %p.\n", iface, clipper);
4310
4311 return ddraw_surface7_GetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4312 }
4313
4314 static HRESULT WINAPI ddraw_surface1_GetClipper(IDirectDrawSurface *iface, IDirectDrawClipper **clipper)
4315 {
4316 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
4317
4318 TRACE("iface %p, clipper %p.\n", iface, clipper);
4319
4320 return ddraw_surface7_GetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4321 }
4322
4323 /*****************************************************************************
4324 * IDirectDrawSurface7::SetClipper
4325 *
4326 * Sets a clipper for the surface
4327 *
4328 * Params:
4329 * Clipper: IDirectDrawClipper interface of the clipper to set
4330 *
4331 * Returns:
4332 * DD_OK on success
4333 *
4334 *****************************************************************************/
4335 static HRESULT WINAPI ddraw_surface7_SetClipper(IDirectDrawSurface7 *iface,
4336 IDirectDrawClipper *iclipper)
4337 {
4338 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
4339 struct ddraw_clipper *clipper = unsafe_impl_from_IDirectDrawClipper(iclipper);
4340 struct ddraw_clipper *old_clipper = This->clipper;
4341 HWND clipWindow;
4342
4343 TRACE("iface %p, clipper %p.\n", iface, iclipper);
4344
4345 wined3d_mutex_lock();
4346 if (clipper == This->clipper)
4347 {
4348 wined3d_mutex_unlock();
4349 return DD_OK;
4350 }
4351
4352 This->clipper = clipper;
4353
4354 if (clipper != NULL)
4355 IDirectDrawClipper_AddRef(iclipper);
4356 if (old_clipper)
4357 IDirectDrawClipper_Release(&old_clipper->IDirectDrawClipper_iface);
4358
4359 if ((This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) && This->ddraw->wined3d_swapchain)
4360 {
4361 clipWindow = NULL;
4362 if(clipper) {
4363 IDirectDrawClipper_GetHWnd(iclipper, &clipWindow);
4364 }
4365
4366 if (clipWindow)
4367 {
4368 wined3d_swapchain_set_window(This->ddraw->wined3d_swapchain, clipWindow);
4369 ddraw_set_swapchain_window(This->ddraw, clipWindow);
4370 }
4371 else
4372 {
4373 wined3d_swapchain_set_window(This->ddraw->wined3d_swapchain, This->ddraw->d3d_window);
4374 ddraw_set_swapchain_window(This->ddraw, This->ddraw->dest_window);
4375 }
4376 }
4377
4378 wined3d_mutex_unlock();
4379
4380 return DD_OK;
4381 }
4382
4383 static HRESULT WINAPI ddraw_surface4_SetClipper(IDirectDrawSurface4 *iface, IDirectDrawClipper *clipper)
4384 {
4385 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4386
4387 TRACE("iface %p, clipper %p.\n", iface, clipper);
4388
4389 return ddraw_surface7_SetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4390 }
4391
4392 static HRESULT WINAPI ddraw_surface3_SetClipper(IDirectDrawSurface3 *iface, IDirectDrawClipper *clipper)
4393 {
4394 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4395
4396 TRACE("iface %p, clipper %p.\n", iface, clipper);
4397
4398 return ddraw_surface7_SetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4399 }
4400
4401 static HRESULT WINAPI ddraw_surface2_SetClipper(IDirectDrawSurface2 *iface, IDirectDrawClipper *clipper)
4402 {
4403 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
4404
4405 TRACE("iface %p, clipper %p.\n", iface, clipper);
4406
4407 return ddraw_surface7_SetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4408 }
4409
4410 static HRESULT WINAPI ddraw_surface1_SetClipper(IDirectDrawSurface *iface, IDirectDrawClipper *clipper)
4411 {
4412 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
4413
4414 TRACE("iface %p, clipper %p.\n", iface, clipper);
4415
4416 return ddraw_surface7_SetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4417 }
4418
4419 /*****************************************************************************
4420 * IDirectDrawSurface7::SetSurfaceDesc
4421 *
4422 * Sets the surface description. It can override the pixel format, the surface
4423 * memory, ...
4424 * It's not really tested.
4425 *
4426 * Params:
4427 * DDSD: Pointer to the new surface description to set
4428 * Flags: Some flags
4429 *
4430 * Returns:
4431 * DD_OK on success
4432 * DDERR_INVALIDPARAMS if DDSD is NULL
4433 *
4434 *****************************************************************************/
4435 static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface, DDSURFACEDESC2 *DDSD, DWORD Flags)
4436 {
4437 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
4438 HRESULT hr;
4439 const DWORD allowed_flags = DDSD_LPSURFACE | DDSD_PIXELFORMAT | DDSD_WIDTH
4440 | DDSD_HEIGHT | DDSD_PITCH | DDSD_CAPS;
4441 enum wined3d_format_id format_id;
4442 UINT pitch, width, height;
4443
4444 TRACE("iface %p, surface_desc %p, flags %#x.\n", iface, DDSD, Flags);
4445
4446 if (!DDSD)
4447 {
4448 WARN("DDSD is NULL, returning DDERR_INVALIDPARAMS\n");
4449 return DDERR_INVALIDPARAMS;
4450 }
4451 if (Flags)
4452 {
4453 WARN("Flags is %x, returning DDERR_INVALIDPARAMS\n", Flags);
4454 return DDERR_INVALIDPARAMS;
4455 }
4456 if (!(This->surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
4457 || This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE
4458 || This->surface_desc.ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE))
4459 {
4460 WARN("Surface is not in system memory, returning DDERR_INVALIDSURFACETYPE.\n");
4461 return DDERR_INVALIDSURFACETYPE;
4462 }
4463
4464 /* Tests show that only LPSURFACE and PIXELFORMAT can be set, and LPSURFACE is required
4465 * for PIXELFORMAT to work */
4466 if (DDSD->dwFlags & ~allowed_flags)
4467 {
4468 WARN("Invalid flags (0x%08x) set, returning DDERR_INVALIDPARAMS\n", DDSD->dwFlags);
4469 return DDERR_INVALIDPARAMS;
4470 }
4471 if (!(DDSD->dwFlags & DDSD_LPSURFACE) || !DDSD->lpSurface)
4472 {
4473 WARN("DDSD_LPSURFACE is not set or lpSurface is NULL, returning DDERR_INVALIDPARAMS\n");
4474 return DDERR_INVALIDPARAMS;
4475 }
4476 if ((DDSD->dwFlags & DDSD_CAPS) && DDSD->ddsCaps.dwCaps)
4477 {
4478 WARN("DDSD_CAPS is set, returning DDERR_INVALIDCAPS.\n");
4479 return DDERR_INVALIDCAPS;
4480 }
4481 if (DDSD->dwFlags & DDSD_WIDTH)
4482 {
4483 if (!(DDSD->dwFlags & DDSD_PITCH))
4484 {
4485 WARN("DDSD_WIDTH is set, but DDSD_PITCH is not, returning DDERR_INVALIDPARAMS.\n");
4486 return DDERR_INVALIDPARAMS;
4487 }
4488 if (!DDSD->dwWidth || DDSD->u1.lPitch <= 0 || DDSD->u1.lPitch & 0x3)
4489 {
4490 WARN("Pitch is %d, width is %u, returning DDERR_INVALIDPARAMS.\n",
4491 DDSD->u1.lPitch, DDSD->dwWidth);
4492 return DDERR_INVALIDPARAMS;
4493 }
4494 if (DDSD->dwWidth != This->surface_desc.dwWidth)
4495 TRACE("Surface width changed from %u to %u.\n", This->surface_desc.dwWidth, DDSD->dwWidth);
4496 if (DDSD->u1.lPitch != This->surface_desc.u1.lPitch)
4497 TRACE("Surface pitch changed from %u to %u.\n", This->surface_desc.u1.lPitch, DDSD->u1.lPitch);
4498 pitch = DDSD->u1.lPitch;
4499 width = DDSD->dwWidth;
4500 }
4501 else if (DDSD->dwFlags & DDSD_PITCH)
4502 {
4503 WARN("DDSD_PITCH is set, but DDSD_WIDTH is not, returning DDERR_INVALIDPARAMS.\n");
4504 return DDERR_INVALIDPARAMS;
4505 }
4506 else
4507 {
4508 pitch = This->surface_desc.u1.lPitch;
4509 width = This->surface_desc.dwWidth;
4510 }
4511
4512 if (DDSD->dwFlags & DDSD_HEIGHT)
4513 {
4514 if (!DDSD->dwHeight)
4515 {
4516 WARN("Height is 0, returning DDERR_INVALIDPARAMS.\n");
4517 return DDERR_INVALIDPARAMS;
4518 }
4519 if (DDSD->dwHeight != This->surface_desc.dwHeight)
4520 TRACE("Surface height changed from %u to %u.\n", This->surface_desc.dwHeight, DDSD->dwHeight);
4521 height = DDSD->dwHeight;
4522 }
4523 else
4524 {
4525 height = This->surface_desc.dwHeight;
4526 }
4527
4528 wined3d_mutex_lock();
4529 if (DDSD->dwFlags & DDSD_PIXELFORMAT)
4530 {
4531 enum wined3d_format_id current_format_id;
4532 format_id = wined3dformat_from_ddrawformat(&DDSD->u4.ddpfPixelFormat);
4533
4534 if (format_id == WINED3DFMT_UNKNOWN)
4535 {
4536 ERR("Requested to set an unknown pixelformat\n");
4537 wined3d_mutex_unlock();
4538 return DDERR_INVALIDPARAMS;
4539 }
4540 current_format_id = wined3dformat_from_ddrawformat(&This->surface_desc.u4.ddpfPixelFormat);
4541 if (format_id != current_format_id)
4542 TRACE("Surface format changed from %#x to %#x.\n", current_format_id, format_id);
4543 }
4544 else
4545 {
4546 format_id = wined3dformat_from_ddrawformat(&This->surface_desc.u4.ddpfPixelFormat);
4547 }
4548
4549 if (FAILED(hr = wined3d_texture_update_desc(This->wined3d_texture, width, height,
4550 format_id, WINED3D_MULTISAMPLE_NONE, 0, DDSD->lpSurface, pitch)))
4551 {
4552 WARN("Failed to update surface desc, hr %#x.\n", hr);
4553 wined3d_mutex_unlock();
4554 return hr_ddraw_from_wined3d(hr);
4555 }
4556
4557 if (DDSD->dwFlags & DDSD_WIDTH)
4558 This->surface_desc.dwWidth = width;
4559 if (DDSD->dwFlags & DDSD_PITCH)
4560 This->surface_desc.u1.lPitch = DDSD->u1.lPitch;
4561 if (DDSD->dwFlags & DDSD_HEIGHT)
4562 This->surface_desc.dwHeight = height;
4563 if (DDSD->dwFlags & DDSD_PIXELFORMAT)
4564 This->surface_desc.u4.ddpfPixelFormat = DDSD->u4.ddpfPixelFormat;
4565
4566 wined3d_mutex_unlock();
4567
4568 return DD_OK;
4569 }
4570
4571 static HRESULT WINAPI ddraw_surface4_SetSurfaceDesc(IDirectDrawSurface4 *iface,
4572 DDSURFACEDESC2 *surface_desc, DWORD flags)
4573 {
4574 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4575
4576 TRACE("iface %p, surface_desc %p, flags %#x.\n", iface, surface_desc, flags);
4577
4578 return ddraw_surface7_SetSurfaceDesc(&surface->IDirectDrawSurface7_iface,
4579 surface_desc, flags);
4580 }
4581
4582 static HRESULT WINAPI ddraw_surface3_SetSurfaceDesc(IDirectDrawSurface3 *iface,
4583 DDSURFACEDESC *surface_desc, DWORD flags)
4584 {
4585 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4586 DDSURFACEDESC2 surface_desc2;
4587
4588 TRACE("iface %p, surface_desc %p, flags %#x.\n", iface, surface_desc, flags);
4589
4590 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
4591 return ddraw_surface7_SetSurfaceDesc(&surface->IDirectDrawSurface7_iface,
4592 surface_desc ? &surface_desc2 : NULL, flags);
4593 }
4594
4595 static HRESULT WINAPI ddraw_surface7_GetPalette(IDirectDrawSurface7 *iface, IDirectDrawPalette **palette)
4596 {
4597 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
4598 struct ddraw_palette *palette_impl;
4599 HRESULT hr = DD_OK;
4600
4601 TRACE("iface %p, palette %p.\n", iface, palette);
4602
4603 if (!palette)
4604 return DDERR_INVALIDPARAMS;
4605 if (IDirectDrawSurface7_IsLost(iface) == DDERR_SURFACELOST)
4606 {
4607 WARN("Surface lost, returning DDERR_SURFACELOST.\n");
4608 return DDERR_SURFACELOST;
4609 }
4610
4611 wined3d_mutex_lock();
4612 if ((palette_impl = surface->palette))
4613 {
4614 *palette = &palette_impl->IDirectDrawPalette_iface;
4615 IDirectDrawPalette_AddRef(*palette);
4616 }
4617 else
4618 {
4619 *palette = NULL;
4620 hr = DDERR_NOPALETTEATTACHED;
4621 }
4622 wined3d_mutex_unlock();
4623
4624 return hr;
4625 }
4626
4627 static HRESULT WINAPI ddraw_surface4_GetPalette(IDirectDrawSurface4 *iface, IDirectDrawPalette **palette)
4628 {
4629 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4630
4631 TRACE("iface %p, palette %p.\n", iface, palette);
4632
4633 return ddraw_surface7_GetPalette(&surface->IDirectDrawSurface7_iface, palette);
4634 }
4635
4636 static HRESULT WINAPI ddraw_surface3_GetPalette(IDirectDrawSurface3 *iface, IDirectDrawPalette **palette)
4637 {
4638 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4639
4640 TRACE("iface %p, palette %p.\n", iface, palette);
4641
4642 return ddraw_surface7_GetPalette(&surface->IDirectDrawSurface7_iface, palette);
4643 }
4644
4645 static HRESULT WINAPI ddraw_surface2_GetPalette(IDirectDrawSurface2 *iface, IDirectDrawPalette **palette)
4646 {
4647 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
4648
4649 TRACE("iface %p, palette %p.\n", iface, palette);
4650
4651 return ddraw_surface7_GetPalette(&surface->IDirectDrawSurface7_iface, palette);
4652 }
4653
4654 static HRESULT WINAPI ddraw_surface1_GetPalette(IDirectDrawSurface *iface, IDirectDrawPalette **palette)
4655 {
4656 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
4657
4658 TRACE("iface %p, palette %p.\n", iface, palette);
4659
4660 return ddraw_surface7_GetPalette(&surface->IDirectDrawSurface7_iface, palette);
4661 }
4662
4663 static HRESULT ddraw_surface_set_color_key(struct ddraw_surface *surface, DWORD flags, DDCOLORKEY *color_key)
4664 {
4665 DDCOLORKEY fixed_color_key;
4666 HRESULT hr = WINED3D_OK;
4667
4668 if (flags & DDCKEY_COLORSPACE)
4669 {
4670 if (color_key && color_key->dwColorSpaceLowValue != color_key->dwColorSpaceHighValue)
4671 {
4672 WARN("Range color keys are not supported, returning DDERR_NOCOLORKEYHW.\n");
4673 return DDERR_NOCOLORKEYHW;
4674 }
4675 flags &= ~DDCKEY_COLORSPACE;
4676 }
4677
4678 wined3d_mutex_lock();
4679
4680 if (color_key)
4681 {
4682 fixed_color_key.dwColorSpaceLowValue = fixed_color_key.dwColorSpaceHighValue = color_key->dwColorSpaceLowValue;
4683 switch (flags & ~DDCKEY_COLORSPACE)
4684 {
4685 case DDCKEY_DESTBLT:
4686 surface->surface_desc.ddckCKDestBlt = fixed_color_key;
4687 surface->surface_desc.dwFlags |= DDSD_CKDESTBLT;
4688 break;
4689
4690 case DDCKEY_DESTOVERLAY:
4691 surface->surface_desc.u3.ddckCKDestOverlay = fixed_color_key;
4692 surface->surface_desc.dwFlags |= DDSD_CKDESTOVERLAY;
4693 break;
4694
4695 case DDCKEY_SRCOVERLAY:
4696 surface->surface_desc.ddckCKSrcOverlay = fixed_color_key;
4697 surface->surface_desc.dwFlags |= DDSD_CKSRCOVERLAY;
4698 break;
4699
4700 case DDCKEY_SRCBLT:
4701 surface->surface_desc.ddckCKSrcBlt = fixed_color_key;
4702 surface->surface_desc.dwFlags |= DDSD_CKSRCBLT;
4703 break;
4704
4705 default:
4706 wined3d_mutex_unlock();
4707 return DDERR_INVALIDPARAMS;
4708 }
4709 }
4710 else
4711 {
4712 switch (flags & ~DDCKEY_COLORSPACE)
4713 {
4714 case DDCKEY_DESTBLT:
4715 surface->surface_desc.dwFlags &= ~DDSD_CKDESTBLT;
4716 break;
4717
4718 case DDCKEY_DESTOVERLAY:
4719 surface->surface_desc.dwFlags &= ~DDSD_CKDESTOVERLAY;
4720 break;
4721
4722 case DDCKEY_SRCOVERLAY:
4723 surface->surface_desc.dwFlags &= ~DDSD_CKSRCOVERLAY;
4724 break;
4725
4726 case DDCKEY_SRCBLT:
4727 surface->surface_desc.dwFlags &= ~DDSD_CKSRCBLT;
4728 break;
4729
4730 default:
4731 wined3d_mutex_unlock();
4732 return DDERR_INVALIDPARAMS;
4733 }
4734 }
4735
4736 if (surface->is_complex_root)
4737 hr = wined3d_texture_set_color_key(surface->wined3d_texture, flags,
4738 color_key ? (struct wined3d_color_key *)&fixed_color_key : NULL);
4739
4740 wined3d_mutex_unlock();
4741
4742 return hr_ddraw_from_wined3d(hr);
4743 }
4744
4745 static HRESULT WINAPI ddraw_surface7_SetColorKey(IDirectDrawSurface7 *iface, DWORD flags, DDCOLORKEY *color_key)
4746 {
4747 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
4748
4749 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
4750
4751 if (surface->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
4752 return DDERR_NOTONMIPMAPSUBLEVEL;
4753
4754 return ddraw_surface_set_color_key(surface, flags, color_key);
4755 }
4756
4757 static HRESULT WINAPI ddraw_surface4_SetColorKey(IDirectDrawSurface4 *iface, DWORD flags, DDCOLORKEY *color_key)
4758 {
4759 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4760
4761 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
4762
4763 return ddraw_surface_set_color_key(surface, flags, color_key);
4764 }
4765
4766 static HRESULT WINAPI ddraw_surface3_SetColorKey(IDirectDrawSurface3 *iface, DWORD flags, DDCOLORKEY *color_key)
4767 {
4768 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4769
4770 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
4771
4772 return ddraw_surface_set_color_key(surface, flags, color_key);
4773 }
4774
4775 static HRESULT WINAPI ddraw_surface2_SetColorKey(IDirectDrawSurface2 *iface, DWORD flags, DDCOLORKEY *color_key)
4776 {
4777 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
4778
4779 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
4780
4781 return ddraw_surface_set_color_key(surface, flags, color_key);
4782 }
4783
4784 static HRESULT WINAPI ddraw_surface1_SetColorKey(IDirectDrawSurface *iface, DWORD flags, DDCOLORKEY *color_key)
4785 {
4786 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
4787
4788 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
4789
4790 return ddraw_surface_set_color_key(surface, flags, color_key);
4791 }
4792
4793 static HRESULT WINAPI ddraw_surface7_SetPalette(IDirectDrawSurface7 *iface, IDirectDrawPalette *palette)
4794 {
4795 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
4796
4797 TRACE("iface %p, palette %p.\n", iface, palette);
4798
4799 if (surface->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
4800 return DDERR_NOTONMIPMAPSUBLEVEL;
4801 if (IDirectDrawSurface7_IsLost(iface) == DDERR_SURFACELOST)
4802 {
4803 WARN("Surface lost, returning DDERR_SURFACELOST.\n");
4804 return DDERR_SURFACELOST;
4805 }
4806
4807 return ddraw_surface_set_palette(surface, palette);
4808 }
4809
4810 static HRESULT WINAPI ddraw_surface4_SetPalette(IDirectDrawSurface4 *iface, IDirectDrawPalette *palette)
4811 {
4812 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4813
4814 TRACE("iface %p, palette %p.\n", iface, palette);
4815
4816 if (IDirectDrawSurface4_IsLost(iface) == DDERR_SURFACELOST)
4817 {
4818 WARN("Surface lost, returning DDERR_SURFACELOST.\n");
4819 return DDERR_SURFACELOST;
4820 }
4821
4822 return ddraw_surface_set_palette(surface, palette);
4823 }
4824
4825 static HRESULT WINAPI ddraw_surface3_SetPalette(IDirectDrawSurface3 *iface, IDirectDrawPalette *palette)
4826 {
4827 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4828
4829 TRACE("iface %p, palette %p.\n", iface, palette);
4830
4831 if (IDirectDrawSurface3_IsLost(iface) == DDERR_SURFACELOST)
4832 {
4833 WARN("Surface lost, returning DDERR_SURFACELOST.\n");
4834 return DDERR_SURFACELOST;
4835 }
4836
4837 return ddraw_surface_set_palette(surface, palette);
4838 }
4839
4840 static HRESULT WINAPI ddraw_surface2_SetPalette(IDirectDrawSurface2 *iface, IDirectDrawPalette *palette)
4841 {
4842 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
4843
4844 TRACE("iface %p, palette %p.\n", iface, palette);
4845
4846 if (IDirectDrawSurface2_IsLost(iface) == DDERR_SURFACELOST)
4847 {
4848 WARN("Surface lost, returning DDERR_SURFACELOST.\n");
4849 return DDERR_SURFACELOST;
4850 }
4851
4852 return ddraw_surface_set_palette(surface, palette);
4853 }
4854
4855 static HRESULT WINAPI ddraw_surface1_SetPalette(IDirectDrawSurface *iface, IDirectDrawPalette *palette)
4856 {
4857 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
4858
4859 TRACE("iface %p, palette %p.\n", iface, palette);
4860
4861 if (IDirectDrawSurface_IsLost(iface) == DDERR_SURFACELOST)
4862 {
4863 WARN("Surface lost, returning DDERR_SURFACELOST.\n");
4864 return DDERR_SURFACELOST;
4865 }
4866
4867 return ddraw_surface_set_palette(surface, palette);
4868 }
4869
4870 /**********************************************************
4871 * IDirectDrawGammaControl::GetGammaRamp
4872 *
4873 * Returns the current gamma ramp for a surface
4874 *
4875 * Params:
4876 * flags: Ignored
4877 * gamma_ramp: Address to write the ramp to
4878 *
4879 * Returns:
4880 * DD_OK on success
4881 * DDERR_INVALIDPARAMS if gamma_ramp is NULL
4882 *
4883 **********************************************************/
4884 static HRESULT WINAPI ddraw_gamma_control_GetGammaRamp(IDirectDrawGammaControl *iface,
4885 DWORD flags, DDGAMMARAMP *gamma_ramp)
4886 {
4887 struct ddraw_surface *surface = impl_from_IDirectDrawGammaControl(iface);
4888
4889 TRACE("iface %p, flags %#x, gamma_ramp %p.\n", iface, flags, gamma_ramp);
4890
4891 if (!gamma_ramp)
4892 {
4893 WARN("Invalid gamma_ramp passed.\n");
4894 return DDERR_INVALIDPARAMS;
4895 }
4896
4897 wined3d_mutex_lock();
4898 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
4899 {
4900 /* Note: DDGAMMARAMP is compatible with struct wined3d_gamma_ramp. */
4901 wined3d_device_get_gamma_ramp(surface->ddraw->wined3d_device, 0, (struct wined3d_gamma_ramp *)gamma_ramp);
4902 }
4903 else
4904 {
4905 ERR("Not implemented for non-primary surfaces.\n");
4906 }
4907 wined3d_mutex_unlock();
4908
4909 return DD_OK;
4910 }
4911
4912 /**********************************************************
4913 * IDirectDrawGammaControl::SetGammaRamp
4914 *
4915 * Sets the red, green and blue gamma ramps for
4916 *
4917 * Params:
4918 * flags: Can be DDSGR_CALIBRATE to request calibration
4919 * gamma_ramp: Structure containing the new gamma ramp
4920 *
4921 * Returns:
4922 * DD_OK on success
4923 * DDERR_INVALIDPARAMS if gamma_ramp is NULL
4924 *
4925 **********************************************************/
4926 static HRESULT WINAPI ddraw_gamma_control_SetGammaRamp(IDirectDrawGammaControl *iface,
4927 DWORD flags, DDGAMMARAMP *gamma_ramp)
4928 {
4929 struct ddraw_surface *surface = impl_from_IDirectDrawGammaControl(iface);
4930
4931 TRACE("iface %p, flags %#x, gamma_ramp %p.\n", iface, flags, gamma_ramp);
4932
4933 if (!gamma_ramp)
4934 {
4935 WARN("Invalid gamma_ramp passed.\n");
4936 return DDERR_INVALIDPARAMS;
4937 }
4938
4939 wined3d_mutex_lock();
4940 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
4941 {
4942 /* Note: DDGAMMARAMP is compatible with struct wined3d_gamma_ramp. */
4943 wined3d_device_set_gamma_ramp(surface->ddraw->wined3d_device,
4944 0, flags, (struct wined3d_gamma_ramp *)gamma_ramp);
4945 }
4946 else
4947 {
4948 ERR("Not implemented for non-primary surfaces.\n");
4949 }
4950 wined3d_mutex_unlock();
4951
4952 return DD_OK;
4953 }
4954
4955 /*****************************************************************************
4956 * IDirect3DTexture2::PaletteChanged
4957 *
4958 * Informs the texture about a palette change
4959 *
4960 * Params:
4961 * start: Start index of the change
4962 * count: The number of changed entries
4963 *
4964 * Returns
4965 * D3D_OK, because it's a stub
4966 *
4967 *****************************************************************************/
4968 static HRESULT WINAPI d3d_texture2_PaletteChanged(IDirect3DTexture2 *iface, DWORD start, DWORD count)
4969 {
4970 FIXME("iface %p, start %u, count %u stub!\n", iface, start, count);
4971
4972 return D3D_OK;
4973 }
4974
4975 static HRESULT WINAPI d3d_texture1_PaletteChanged(IDirect3DTexture *iface, DWORD start, DWORD count)
4976 {
4977 struct ddraw_surface *surface = impl_from_IDirect3DTexture(iface);
4978
4979 TRACE("iface %p, start %u, count %u.\n", iface, start, count);
4980
4981 return d3d_texture2_PaletteChanged(&surface->IDirect3DTexture2_iface, start, count);
4982 }
4983
4984 /*****************************************************************************
4985 * IDirect3DTexture::Unload
4986 *
4987 * DX5 SDK: "The IDirect3DTexture2::Unload method is not implemented
4988 *
4989 *
4990 * Returns:
4991 * DDERR_UNSUPPORTED
4992 *
4993 *****************************************************************************/
4994 static HRESULT WINAPI d3d_texture1_Unload(IDirect3DTexture *iface)
4995 {
4996 WARN("iface %p. Not implemented.\n", iface);
4997
4998 return DDERR_UNSUPPORTED;
4999 }
5000
5001 /*****************************************************************************
5002 * IDirect3DTexture2::GetHandle
5003 *
5004 * Returns handle for the texture. At the moment, the interface
5005 * to the IWineD3DTexture is used.
5006 *
5007 * Params:
5008 * device: Device this handle is assigned to
5009 * handle: Address to store the handle at.
5010 *
5011 * Returns:
5012 * D3D_OK
5013 *
5014 *****************************************************************************/
5015 static HRESULT WINAPI d3d_texture2_GetHandle(IDirect3DTexture2 *iface,
5016 IDirect3DDevice2 *device, D3DTEXTUREHANDLE *handle)
5017 {
5018 struct ddraw_surface *surface = impl_from_IDirect3DTexture2(iface);
5019 struct d3d_device *device_impl = unsafe_impl_from_IDirect3DDevice2(device);
5020
5021 TRACE("iface %p, device %p, handle %p.\n", iface, device, handle);
5022
5023 wined3d_mutex_lock();
5024
5025 if (!surface->Handle)
5026 {
5027 DWORD h = ddraw_allocate_handle(&device_impl->handle_table, surface, DDRAW_HANDLE_SURFACE);
5028 if (h == DDRAW_INVALID_HANDLE)
5029 {
5030 ERR("Failed to allocate a texture handle.\n");
5031 wined3d_mutex_unlock();
5032 return DDERR_OUTOFMEMORY;
5033 }
5034
5035 surface->Handle = h + 1;
5036 }
5037
5038 TRACE("Returning handle %08x.\n", surface->Handle);
5039 *handle = surface->Handle;
5040
5041 wined3d_mutex_unlock();
5042
5043 return D3D_OK;
5044 }
5045
5046 static HRESULT WINAPI d3d_texture1_GetHandle(IDirect3DTexture *iface,
5047 IDirect3DDevice *device, D3DTEXTUREHANDLE *handle)
5048 {
5049 struct ddraw_surface *surface = impl_from_IDirect3DTexture(iface);
5050 struct d3d_device *device_impl = unsafe_impl_from_IDirect3DDevice(device);
5051
5052 TRACE("iface %p, device %p, handle %p.\n", iface, device, handle);
5053
5054 return d3d_texture2_GetHandle(&surface->IDirect3DTexture2_iface,
5055 device_impl ? &device_impl->IDirect3DDevice2_iface : NULL, handle);
5056 }
5057
5058 /*****************************************************************************
5059 * get_sub_mimaplevel
5060 *
5061 * Helper function that returns the next mipmap level
5062 *
5063 * tex_ptr: Surface of which to return the next level
5064 *
5065 *****************************************************************************/
5066 static struct ddraw_surface *get_sub_mimaplevel(struct ddraw_surface *surface)
5067 {
5068 /* Now go down the mipmap chain to the next surface */
5069 static DDSCAPS2 mipmap_caps = { DDSCAPS_MIPMAP | DDSCAPS_TEXTURE, 0, 0, {0} };
5070 IDirectDrawSurface7 *next_level;
5071 HRESULT hr;
5072
5073 hr = ddraw_surface7_GetAttachedSurface(&surface->IDirectDrawSurface7_iface, &mipmap_caps, &next_level);
5074 if (FAILED(hr)) return NULL;
5075
5076 ddraw_surface7_Release(next_level);
5077
5078 return impl_from_IDirectDrawSurface7(next_level);
5079 }
5080
5081 static BOOL compare_format(DDPIXELFORMAT *format1, DDPIXELFORMAT *format2)
5082 {
5083 if ((format1->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_FOURCC)) !=
5084 (format2->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_FOURCC)))
5085 return FALSE;
5086
5087 if (format1->dwFlags & (DDPF_RGB|DDPF_YUV))
5088 {
5089 if (!(format1->dwFlags & DDPF_ALPHA))
5090 {
5091 /* The RGB and YUV bits are stored in the same fields */
5092 if (format1->u1.dwRGBBitCount != format2->u1.dwRGBBitCount)
5093 return FALSE;
5094
5095 if (format1->u2.dwRBitMask != format2->u2.dwRBitMask)
5096 return FALSE;
5097
5098 if (format1->u3.dwGBitMask != format2->u3.dwGBitMask)
5099 return FALSE;
5100
5101 if (format1->u4.dwBBitMask != format2->u4.dwBBitMask)
5102 return FALSE;
5103 }
5104
5105 if (format1->dwFlags & (DDPF_ALPHAPIXELS | DDPF_ALPHA))
5106 {
5107 if (format1->u5.dwRGBAlphaBitMask != format2->u5.dwRGBAlphaBitMask)
5108 return FALSE;
5109 }
5110 }
5111
5112 if (format1->dwFlags & DDPF_FOURCC)
5113 {
5114 if (format1->dwFourCC != format2->dwFourCC)
5115 return FALSE;
5116 }
5117
5118 return TRUE;
5119 }
5120
5121 /*****************************************************************************
5122 * IDirect3DTexture2::Load
5123 *
5124 * Loads a texture created with the DDSCAPS_ALLOCONLOAD
5125 *
5126 * This function isn't relayed to WineD3D because the whole interface is
5127 * implemented in DDraw only. For speed improvements an implementation which
5128 * takes OpenGL more into account could be placed into WineD3D.
5129 *
5130 * Params:
5131 * src_texture: Address of the texture to load
5132 *
5133 * Returns:
5134 * D3D_OK on success
5135 * D3DERR_TEXTURE_LOAD_FAILED.
5136 *
5137 *****************************************************************************/
5138 static HRESULT WINAPI d3d_texture2_Load(IDirect3DTexture2 *iface, IDirect3DTexture2 *src_texture)
5139 {
5140 struct ddraw_surface *dst_surface = impl_from_IDirect3DTexture2(iface);
5141 struct ddraw_surface *src_surface = unsafe_impl_from_IDirect3DTexture2(src_texture);
5142 RECT src_rect, dst_rect;
5143 HRESULT hr;
5144
5145 TRACE("iface %p, src_texture %p.\n", iface, src_texture);
5146
5147 if (src_surface == dst_surface)
5148 {
5149 TRACE("copying surface %p to surface %p, why?\n", src_surface, dst_surface);
5150 return D3D_OK;
5151 }
5152
5153 wined3d_mutex_lock();
5154
5155 for (;;)
5156 {
5157 DDSURFACEDESC *src_desc = (DDSURFACEDESC *)&src_surface->surface_desc;
5158
5159 TRACE("Copying surface %p to surface %p.\n", src_surface, dst_surface);
5160
5161 if (compare_format(&src_surface->surface_desc.u4.ddpfPixelFormat,
5162 &dst_surface->surface_desc.u4.ddpfPixelFormat))
5163 {
5164 struct ddraw_palette *dst_pal, *src_pal;
5165
5166 /* Get the palettes */
5167 dst_pal = dst_surface->palette;
5168 src_pal = src_surface->palette;
5169
5170 if (src_pal)
5171 {
5172 PALETTEENTRY palent[256];
5173
5174 if (!dst_pal)
5175 {
5176 wined3d_mutex_unlock();
5177 return DDERR_NOPALETTEATTACHED;
5178 }
5179 IDirectDrawPalette_GetEntries(&src_pal->IDirectDrawPalette_iface, 0, 0, 256, palent);
5180 IDirectDrawPalette_SetEntries(&dst_pal->IDirectDrawPalette_iface, 0, 0, 256, palent);
5181 }
5182
5183 if (src_desc->dwFlags & DDSD_CKSRCBLT)
5184 {
5185 IDirectDrawSurface7_SetColorKey(&dst_surface->IDirectDrawSurface7_iface,
5186 DDCKEY_SRCBLT, &src_desc->ddckCKSrcBlt);
5187 }
5188 }
5189 else
5190 {
5191 if (src_desc->dwFlags & DDSD_CKSRCBLT)
5192 return E_FAIL;
5193 }
5194
5195 /* Suppress the ALLOCONLOAD flag */
5196 dst_surface->surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_ALLOCONLOAD;
5197
5198 SetRect(&src_rect, 0, 0, src_surface->surface_desc.dwWidth, src_surface->surface_desc.dwHeight);
5199 SetRect(&dst_rect, 0, 0, dst_surface->surface_desc.dwWidth, dst_surface->surface_desc.dwHeight);
5200
5201 hr = wined3d_texture_blt(dst_surface->wined3d_texture, dst_surface->sub_resource_idx, &dst_rect,
5202 src_surface->wined3d_texture, src_surface->sub_resource_idx, &src_rect,
5203 0, NULL, WINED3D_TEXF_LINEAR);
5204 if (FAILED(hr))
5205 {
5206 ERR("Failed to blit surface, hr %#x.\n", hr);
5207 wined3d_mutex_unlock();
5208 return hr;
5209 }
5210
5211 if (src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
5212 src_surface = get_sub_mimaplevel(src_surface);
5213 else
5214 src_surface = NULL;
5215
5216 if (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
5217 dst_surface = get_sub_mimaplevel(dst_surface);
5218 else
5219 dst_surface = NULL;
5220
5221 if (src_surface && !dst_surface)
5222 return DDERR_NOTFOUND;
5223
5224 if (!src_surface || !dst_surface)
5225 break;
5226 }
5227
5228 wined3d_mutex_unlock();
5229
5230 return hr;
5231 }
5232
5233 static HRESULT WINAPI d3d_texture1_Load(IDirect3DTexture *iface, IDirect3DTexture *src_texture)
5234 {
5235 struct ddraw_surface *dst_surface = impl_from_IDirect3DTexture(iface);
5236 struct ddraw_surface *src_surface = unsafe_impl_from_IDirect3DTexture(src_texture);
5237
5238 TRACE("iface %p, src_texture %p.\n", iface, src_texture);
5239
5240 return d3d_texture2_Load(&dst_surface->IDirect3DTexture2_iface,
5241 src_surface ? &src_surface->IDirect3DTexture2_iface : NULL);
5242 }
5243
5244 /*****************************************************************************
5245 * The VTable
5246 *****************************************************************************/
5247
5248 static const struct IDirectDrawSurface7Vtbl ddraw_surface7_vtbl =
5249 {
5250 /* IUnknown */
5251 ddraw_surface7_QueryInterface,
5252 ddraw_surface7_AddRef,
5253 ddraw_surface7_Release,
5254 /* IDirectDrawSurface */
5255 ddraw_surface7_AddAttachedSurface,
5256 ddraw_surface7_AddOverlayDirtyRect,
5257 ddraw_surface7_Blt,
5258 ddraw_surface7_BltBatch,
5259 ddraw_surface7_BltFast,
5260 ddraw_surface7_DeleteAttachedSurface,
5261 ddraw_surface7_EnumAttachedSurfaces,
5262 ddraw_surface7_EnumOverlayZOrders,
5263 ddraw_surface7_Flip,
5264 ddraw_surface7_GetAttachedSurface,
5265 ddraw_surface7_GetBltStatus,
5266 ddraw_surface7_GetCaps,
5267 ddraw_surface7_GetClipper,
5268 ddraw_surface7_GetColorKey,
5269 ddraw_surface7_GetDC,
5270 ddraw_surface7_GetFlipStatus,
5271 ddraw_surface7_GetOverlayPosition,
5272 ddraw_surface7_GetPalette,
5273 ddraw_surface7_GetPixelFormat,
5274 ddraw_surface7_GetSurfaceDesc,
5275 ddraw_surface7_Initialize,
5276 ddraw_surface7_IsLost,
5277 ddraw_surface7_Lock,
5278 ddraw_surface7_ReleaseDC,
5279 ddraw_surface7_Restore,
5280 ddraw_surface7_SetClipper,
5281 ddraw_surface7_SetColorKey,
5282 ddraw_surface7_SetOverlayPosition,
5283 ddraw_surface7_SetPalette,
5284 ddraw_surface7_Unlock,
5285 ddraw_surface7_UpdateOverlay,
5286 ddraw_surface7_UpdateOverlayDisplay,
5287 ddraw_surface7_UpdateOverlayZOrder,
5288 /* IDirectDrawSurface2 */
5289 ddraw_surface7_GetDDInterface,
5290 ddraw_surface7_PageLock,
5291 ddraw_surface7_PageUnlock,
5292 /* IDirectDrawSurface3 */
5293 ddraw_surface7_SetSurfaceDesc,
5294 /* IDirectDrawSurface4 */
5295 ddraw_surface7_SetPrivateData,
5296 ddraw_surface7_GetPrivateData,
5297 ddraw_surface7_FreePrivateData,
5298 ddraw_surface7_GetUniquenessValue,
5299 ddraw_surface7_ChangeUniquenessValue,
5300 /* IDirectDrawSurface7 */
5301 ddraw_surface7_SetPriority,
5302 ddraw_surface7_GetPriority,
5303 ddraw_surface7_SetLOD,
5304 ddraw_surface7_GetLOD,
5305 };
5306
5307 static const struct IDirectDrawSurface4Vtbl ddraw_surface4_vtbl =
5308 {
5309 /* IUnknown */
5310 ddraw_surface4_QueryInterface,
5311 ddraw_surface4_AddRef,
5312 ddraw_surface4_Release,
5313 /* IDirectDrawSurface */
5314 ddraw_surface4_AddAttachedSurface,
5315 ddraw_surface4_AddOverlayDirtyRect,
5316 ddraw_surface4_Blt,
5317 ddraw_surface4_BltBatch,
5318 ddraw_surface4_BltFast,
5319 ddraw_surface4_DeleteAttachedSurface,
5320 ddraw_surface4_EnumAttachedSurfaces,
5321 ddraw_surface4_EnumOverlayZOrders,
5322 ddraw_surface4_Flip,
5323 ddraw_surface4_GetAttachedSurface,
5324 ddraw_surface4_GetBltStatus,
5325 ddraw_surface4_GetCaps,
5326 ddraw_surface4_GetClipper,
5327 ddraw_surface4_GetColorKey,
5328 ddraw_surface4_GetDC,
5329 ddraw_surface4_GetFlipStatus,
5330 ddraw_surface4_GetOverlayPosition,
5331 ddraw_surface4_GetPalette,
5332 ddraw_surface4_GetPixelFormat,
5333 ddraw_surface4_GetSurfaceDesc,
5334 ddraw_surface4_Initialize,
5335 ddraw_surface4_IsLost,
5336 ddraw_surface4_Lock,
5337 ddraw_surface4_ReleaseDC,
5338 ddraw_surface4_Restore,
5339 ddraw_surface4_SetClipper,
5340 ddraw_surface4_SetColorKey,
5341 ddraw_surface4_SetOverlayPosition,
5342 ddraw_surface4_SetPalette,
5343 ddraw_surface4_Unlock,
5344 ddraw_surface4_UpdateOverlay,
5345 ddraw_surface4_UpdateOverlayDisplay,
5346 ddraw_surface4_UpdateOverlayZOrder,
5347 /* IDirectDrawSurface2 */
5348 ddraw_surface4_GetDDInterface,
5349 ddraw_surface4_PageLock,
5350 ddraw_surface4_PageUnlock,
5351 /* IDirectDrawSurface3 */
5352 ddraw_surface4_SetSurfaceDesc,
5353 /* IDirectDrawSurface4 */
5354 ddraw_surface4_SetPrivateData,
5355 ddraw_surface4_GetPrivateData,
5356 ddraw_surface4_FreePrivateData,
5357 ddraw_surface4_GetUniquenessValue,
5358 ddraw_surface4_ChangeUniquenessValue,
5359 };
5360
5361 static const struct IDirectDrawSurface3Vtbl ddraw_surface3_vtbl =
5362 {
5363 /* IUnknown */
5364 ddraw_surface3_QueryInterface,
5365 ddraw_surface3_AddRef,
5366 ddraw_surface3_Release,
5367 /* IDirectDrawSurface */
5368 ddraw_surface3_AddAttachedSurface,
5369 ddraw_surface3_AddOverlayDirtyRect,
5370 ddraw_surface3_Blt,
5371 ddraw_surface3_BltBatch,
5372 ddraw_surface3_BltFast,
5373 ddraw_surface3_DeleteAttachedSurface,
5374 ddraw_surface3_EnumAttachedSurfaces,
5375 ddraw_surface3_EnumOverlayZOrders,
5376 ddraw_surface3_Flip,
5377 ddraw_surface3_GetAttachedSurface,
5378 ddraw_surface3_GetBltStatus,
5379 ddraw_surface3_GetCaps,
5380 ddraw_surface3_GetClipper,
5381 ddraw_surface3_GetColorKey,
5382 ddraw_surface3_GetDC,
5383 ddraw_surface3_GetFlipStatus,
5384 ddraw_surface3_GetOverlayPosition,
5385 ddraw_surface3_GetPalette,
5386 ddraw_surface3_GetPixelFormat,
5387 ddraw_surface3_GetSurfaceDesc,
5388 ddraw_surface3_Initialize,
5389 ddraw_surface3_IsLost,
5390 ddraw_surface3_Lock,
5391 ddraw_surface3_ReleaseDC,
5392 ddraw_surface3_Restore,
5393 ddraw_surface3_SetClipper,
5394 ddraw_surface3_SetColorKey,
5395 ddraw_surface3_SetOverlayPosition,
5396 ddraw_surface3_SetPalette,
5397 ddraw_surface3_Unlock,
5398 ddraw_surface3_UpdateOverlay,
5399 ddraw_surface3_UpdateOverlayDisplay,
5400 ddraw_surface3_UpdateOverlayZOrder,
5401 /* IDirectDrawSurface2 */
5402 ddraw_surface3_GetDDInterface,
5403 ddraw_surface3_PageLock,
5404 ddraw_surface3_PageUnlock,
5405 /* IDirectDrawSurface3 */
5406 ddraw_surface3_SetSurfaceDesc,
5407 };
5408
5409 static const struct IDirectDrawSurface2Vtbl ddraw_surface2_vtbl =
5410 {
5411 /* IUnknown */
5412 ddraw_surface2_QueryInterface,
5413 ddraw_surface2_AddRef,
5414 ddraw_surface2_Release,
5415 /* IDirectDrawSurface */
5416 ddraw_surface2_AddAttachedSurface,
5417 ddraw_surface2_AddOverlayDirtyRect,
5418 ddraw_surface2_Blt,
5419 ddraw_surface2_BltBatch,
5420 ddraw_surface2_BltFast,
5421 ddraw_surface2_DeleteAttachedSurface,
5422 ddraw_surface2_EnumAttachedSurfaces,
5423 ddraw_surface2_EnumOverlayZOrders,
5424 ddraw_surface2_Flip,
5425 ddraw_surface2_GetAttachedSurface,
5426 ddraw_surface2_GetBltStatus,
5427 ddraw_surface2_GetCaps,
5428 ddraw_surface2_GetClipper,
5429 ddraw_surface2_GetColorKey,
5430 ddraw_surface2_GetDC,
5431 ddraw_surface2_GetFlipStatus,
5432 ddraw_surface2_GetOverlayPosition,
5433 ddraw_surface2_GetPalette,
5434 ddraw_surface2_GetPixelFormat,
5435 ddraw_surface2_GetSurfaceDesc,
5436 ddraw_surface2_Initialize,
5437 ddraw_surface2_IsLost,
5438 ddraw_surface2_Lock,
5439 ddraw_surface2_ReleaseDC,
5440 ddraw_surface2_Restore,
5441 ddraw_surface2_SetClipper,
5442 ddraw_surface2_SetColorKey,
5443 ddraw_surface2_SetOverlayPosition,
5444 ddraw_surface2_SetPalette,
5445 ddraw_surface2_Unlock,
5446 ddraw_surface2_UpdateOverlay,
5447 ddraw_surface2_UpdateOverlayDisplay,
5448 ddraw_surface2_UpdateOverlayZOrder,
5449 /* IDirectDrawSurface2 */
5450 ddraw_surface2_GetDDInterface,
5451 ddraw_surface2_PageLock,
5452 ddraw_surface2_PageUnlock,
5453 };
5454
5455 static struct IDirectDrawSurfaceVtbl ddraw_surface1_vtbl =
5456 {
5457 /* IUnknown */
5458 ddraw_surface1_QueryInterface,
5459 ddraw_surface1_AddRef,
5460 ddraw_surface1_Release,
5461 /* IDirectDrawSurface */
5462 ddraw_surface1_AddAttachedSurface,
5463 ddraw_surface1_AddOverlayDirtyRect,
5464 ddraw_surface1_Blt,
5465 ddraw_surface1_BltBatch,
5466 ddraw_surface1_BltFast,
5467 ddraw_surface1_DeleteAttachedSurface,
5468 ddraw_surface1_EnumAttachedSurfaces,
5469 ddraw_surface1_EnumOverlayZOrders,
5470 ddraw_surface1_Flip,
5471 ddraw_surface1_GetAttachedSurface,
5472 ddraw_surface1_GetBltStatus,
5473 ddraw_surface1_GetCaps,
5474 ddraw_surface1_GetClipper,
5475 ddraw_surface1_GetColorKey,
5476 ddraw_surface1_GetDC,
5477 ddraw_surface1_GetFlipStatus,
5478 ddraw_surface1_GetOverlayPosition,
5479 ddraw_surface1_GetPalette,
5480 ddraw_surface1_GetPixelFormat,
5481 ddraw_surface1_GetSurfaceDesc,
5482 ddraw_surface1_Initialize,
5483 ddraw_surface1_IsLost,
5484 ddraw_surface1_Lock,
5485 ddraw_surface1_ReleaseDC,
5486 ddraw_surface1_Restore,
5487 ddraw_surface1_SetClipper,
5488 ddraw_surface1_SetColorKey,
5489 ddraw_surface1_SetOverlayPosition,
5490 ddraw_surface1_SetPalette,
5491 ddraw_surface1_Unlock,
5492 ddraw_surface1_UpdateOverlay,
5493 ddraw_surface1_UpdateOverlayDisplay,
5494 ddraw_surface1_UpdateOverlayZOrder,
5495 };
5496
5497 static const struct IDirectDrawGammaControlVtbl ddraw_gamma_control_vtbl =
5498 {
5499 ddraw_gamma_control_QueryInterface,
5500 ddraw_gamma_control_AddRef,
5501 ddraw_gamma_control_Release,
5502 ddraw_gamma_control_GetGammaRamp,
5503 ddraw_gamma_control_SetGammaRamp,
5504 };
5505
5506 static const struct IDirect3DTexture2Vtbl d3d_texture2_vtbl =
5507 {
5508 d3d_texture2_QueryInterface,
5509 d3d_texture2_AddRef,
5510 d3d_texture2_Release,
5511 d3d_texture2_GetHandle,
5512 d3d_texture2_PaletteChanged,
5513 d3d_texture2_Load,
5514 };
5515
5516 static const struct IDirect3DTextureVtbl d3d_texture1_vtbl =
5517 {
5518 d3d_texture1_QueryInterface,
5519 d3d_texture1_AddRef,
5520 d3d_texture1_Release,
5521 d3d_texture1_Initialize,
5522 d3d_texture1_GetHandle,
5523 d3d_texture1_PaletteChanged,
5524 d3d_texture1_Load,
5525 d3d_texture1_Unload,
5526 };
5527
5528 /* Some games (e.g. Tomb Raider 3) pass the wrong version of the
5529 * IDirectDrawSurface interface to ddraw methods. */
5530 struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface7(IDirectDrawSurface7 *iface)
5531 {
5532 if (!iface) return NULL;
5533 if (iface->lpVtbl != &ddraw_surface7_vtbl)
5534 {
5535 HRESULT hr = IDirectDrawSurface7_QueryInterface(iface, &IID_IDirectDrawSurface7, (void **)&iface);
5536 if (FAILED(hr))
5537 {
5538 WARN("Object %p doesn't expose interface IDirectDrawSurface7.\n", iface);
5539 return NULL;
5540 }
5541 IDirectDrawSurface7_Release(iface);
5542 }
5543 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawSurface7_iface);
5544 }
5545
5546 struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface4(IDirectDrawSurface4 *iface)
5547 {
5548 if (!iface) return NULL;
5549 if (iface->lpVtbl != &ddraw_surface4_vtbl)
5550 {
5551 HRESULT hr = IDirectDrawSurface4_QueryInterface(iface, &IID_IDirectDrawSurface4, (void **)&iface);
5552 if (FAILED(hr))
5553 {
5554 WARN("Object %p doesn't expose interface IDirectDrawSurface4.\n", iface);
5555 return NULL;
5556 }
5557 IDirectDrawSurface4_Release(iface);
5558 }
5559 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawSurface4_iface);
5560 }
5561
5562 static struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface3(IDirectDrawSurface3 *iface)
5563 {
5564 if (!iface) return NULL;
5565 if (iface->lpVtbl != &ddraw_surface3_vtbl)
5566 {
5567 HRESULT hr = IDirectDrawSurface3_QueryInterface(iface, &IID_IDirectDrawSurface3, (void **)&iface);
5568 if (FAILED(hr))
5569 {
5570 WARN("Object %p doesn't expose interface IDirectDrawSurface3.\n", iface);
5571 return NULL;
5572 }
5573 IDirectDrawSurface3_Release(iface);
5574 }
5575 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawSurface3_iface);
5576 }
5577
5578 static struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface2(IDirectDrawSurface2 *iface)
5579 {
5580 if (!iface) return NULL;
5581 if (iface->lpVtbl != &ddraw_surface2_vtbl)
5582 {
5583 HRESULT hr = IDirectDrawSurface2_QueryInterface(iface, &IID_IDirectDrawSurface2, (void **)&iface);
5584 if (FAILED(hr))
5585 {
5586 WARN("Object %p doesn't expose interface IDirectDrawSurface2.\n", iface);
5587 return NULL;
5588 }
5589 IDirectDrawSurface2_Release(iface);
5590 }
5591 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawSurface2_iface);
5592 }
5593
5594 struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface(IDirectDrawSurface *iface)
5595 {
5596 if (!iface) return NULL;
5597 if (iface->lpVtbl != &ddraw_surface1_vtbl)
5598 {
5599 HRESULT hr = IDirectDrawSurface_QueryInterface(iface, &IID_IDirectDrawSurface, (void **)&iface);
5600 if (FAILED(hr))
5601 {
5602 WARN("Object %p doesn't expose interface IDirectDrawSurface.\n", iface);
5603 return NULL;
5604 }
5605 IDirectDrawSurface_Release(iface);
5606 }
5607 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawSurface_iface);
5608 }
5609
5610 struct ddraw_surface *unsafe_impl_from_IDirect3DTexture2(IDirect3DTexture2 *iface)
5611 {
5612 if (!iface) return NULL;
5613 assert(iface->lpVtbl == &d3d_texture2_vtbl);
5614 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirect3DTexture2_iface);
5615 }
5616
5617 struct ddraw_surface *unsafe_impl_from_IDirect3DTexture(IDirect3DTexture *iface)
5618 {
5619 if (!iface) return NULL;
5620 assert(iface->lpVtbl == &d3d_texture1_vtbl);
5621 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirect3DTexture_iface);
5622 }
5623
5624 static void STDMETHODCALLTYPE ddraw_surface_wined3d_object_destroyed(void *parent)
5625 {
5626 struct ddraw_surface *surface = parent;
5627
5628 TRACE("surface %p.\n", surface);
5629
5630 /* Check for attached surfaces and detach them. */
5631 if (surface->first_attached != surface)
5632 {
5633 /* Well, this shouldn't happen: The surface being attached is
5634 * referenced in AddAttachedSurface(), so it shouldn't be released
5635 * until DeleteAttachedSurface() is called, because the refcount is
5636 * held. It looks like the application released it often enough to
5637 * force this. */
5638 WARN("Surface is still attached to surface %p.\n", surface->first_attached);
5639
5640 /* The refcount will drop to -1 here */
5641 if (FAILED(ddraw_surface_delete_attached_surface(surface->first_attached, surface, surface->attached_iface)))
5642 ERR("DeleteAttachedSurface failed.\n");
5643 }
5644
5645 while (surface->next_attached)
5646 if (FAILED(ddraw_surface_delete_attached_surface(surface,
5647 surface->next_attached, surface->next_attached->attached_iface)))
5648 ERR("DeleteAttachedSurface failed.\n");
5649
5650 /* Having a texture handle set implies that the device still exists. */
5651 if (surface->Handle)
5652 ddraw_free_handle(&surface->ddraw->d3ddevice->handle_table, surface->Handle - 1, DDRAW_HANDLE_SURFACE);
5653
5654 /* Reduce the ddraw surface count. */
5655 list_remove(&surface->surface_list_entry);
5656
5657 if (surface->clipper)
5658 IDirectDrawClipper_Release(&surface->clipper->IDirectDrawClipper_iface);
5659
5660 if (surface == surface->ddraw->primary)
5661 surface->ddraw->primary = NULL;
5662
5663 wined3d_private_store_cleanup(&surface->private_store);
5664
5665 HeapFree(GetProcessHeap(), 0, surface);
5666 }
5667
5668 static const struct wined3d_parent_ops ddraw_surface_wined3d_parent_ops =
5669 {
5670 ddraw_surface_wined3d_object_destroyed,
5671 };
5672
5673 static void STDMETHODCALLTYPE ddraw_texture_wined3d_object_destroyed(void *parent)
5674 {
5675 TRACE("parent %p.\n", parent);
5676
5677 HeapFree(GetProcessHeap(), 0, parent);
5678 }
5679
5680 static const struct wined3d_parent_ops ddraw_texture_wined3d_parent_ops =
5681 {
5682 ddraw_texture_wined3d_object_destroyed,
5683 };
5684
5685 static HRESULT CDECL ddraw_reset_enum_callback(struct wined3d_resource *resource)
5686 {
5687 return DD_OK;
5688 }
5689
5690 HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_desc,
5691 struct ddraw_surface **surface, IUnknown *outer_unknown, unsigned int version)
5692 {
5693 struct wined3d_resource_desc wined3d_desc, wined3d_mip_desc;
5694 struct ddraw_surface *root, *mip, **attach;
5695 struct wined3d_texture *wined3d_texture;
5696 struct wined3d_resource *resource;
5697 struct wined3d_display_mode mode;
5698 DDSURFACEDESC2 *desc, *mip_desc;
5699 struct ddraw_texture *texture;
5700 unsigned int layers = 1;
5701 unsigned int pitch = 0;
5702 UINT levels, i, j;
5703 HRESULT hr;
5704
5705 TRACE("ddraw %p, surface_desc %p, surface %p, outer_unknown %p, version %u.\n",
5706 ddraw, surface_desc, surface, outer_unknown, version);
5707 if (TRACE_ON(ddraw))
5708 {
5709 TRACE("Requesting surface desc:\n");
5710 DDRAW_dump_surface_desc(surface_desc);
5711 }
5712
5713 if (outer_unknown)
5714 return CLASS_E_NOAGGREGATION;
5715
5716 if (!surface)
5717 return E_POINTER;
5718
5719 if (!(texture = HeapAlloc(GetProcessHeap(), 0, sizeof(*texture))))
5720 return E_OUTOFMEMORY;
5721
5722 texture->version = version;
5723 texture->surface_desc = *surface_desc;
5724 desc = &texture->surface_desc;
5725
5726 /* Ensure DDSD_CAPS is always set. */
5727 desc->dwFlags |= DDSD_CAPS;
5728
5729 if (desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
5730 {
5731 DWORD flippable = desc->ddsCaps.dwCaps & (DDSCAPS_FLIP | DDSCAPS_COMPLEX);
5732
5733 if (desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE)
5734 {
5735 WARN("Tried to create a primary surface with DDSCAPS_TEXTURE.\n");
5736 HeapFree(GetProcessHeap(), 0, texture);
5737 return DDERR_INVALIDCAPS;
5738 }
5739
5740 if (flippable)
5741 {
5742 if (flippable != (DDSCAPS_FLIP | DDSCAPS_COMPLEX))
5743 {
5744 WARN("Tried to create a flippable primary surface without both DDSCAPS_FLIP and DDSCAPS_COMPLEX.\n");
5745 HeapFree(GetProcessHeap(), 0, texture);
5746 return DDERR_INVALIDCAPS;
5747 }
5748
5749 if (!(desc->dwFlags & DDSD_BACKBUFFERCOUNT) || !desc->u5.dwBackBufferCount)
5750 {
5751 WARN("Tried to create a flippable primary surface without any back buffers.\n");
5752 HeapFree(GetProcessHeap(), 0, texture);
5753 return DDERR_INVALIDCAPS;
5754 }
5755
5756 if (!(ddraw->cooperative_level & DDSCL_EXCLUSIVE))
5757 {
5758 WARN("Tried to create a flippable primary surface without DDSCL_EXCLUSIVE.\n");
5759 HeapFree(GetProcessHeap(), 0, texture);
5760 return DDERR_NOEXCLUSIVEMODE;
5761 }
5762 }
5763 }
5764
5765 /* This is a special case in ddrawex, but not allowed in ddraw. */
5766 if ((desc->ddsCaps.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY))
5767 == (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY))
5768 {
5769 WARN("Tried to create a surface in both system and video memory.\n");
5770 HeapFree(GetProcessHeap(), 0, texture);
5771 return DDERR_INVALIDCAPS;
5772 }
5773
5774 if ((desc->ddsCaps.dwCaps & (DDSCAPS_ALLOCONLOAD | DDSCAPS_MIPMAP))
5775 && !(desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE))
5776 {
5777 WARN("Caps %#x require DDSCAPS_TEXTURE.\n", desc->ddsCaps.dwCaps);
5778 HeapFree(GetProcessHeap(), 0, texture);
5779 return DDERR_INVALIDCAPS;
5780 }
5781
5782 if ((desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES)
5783 && !(desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
5784 {
5785 WARN("Cube map faces requested without cube map flag.\n");
5786 HeapFree(GetProcessHeap(), 0, texture);
5787 return DDERR_INVALIDCAPS;
5788 }
5789
5790 if ((desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
5791 && !(desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES))
5792 {
5793 WARN("Cube map without faces requested.\n");
5794 HeapFree(GetProcessHeap(), 0, texture);
5795 return DDERR_INVALIDPARAMS;
5796 }
5797
5798 if ((desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
5799 && (desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES) != DDSCAPS2_CUBEMAP_ALLFACES)
5800 FIXME("Partial cube maps not implemented.\n");
5801
5802 if (desc->ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE))
5803 {
5804 if (!(desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE))
5805 {
5806 WARN("DDSCAPS2_TEXTUREMANAGE used without DDSCAPS_TEXTURE, returning DDERR_INVALIDCAPS.\n");
5807 HeapFree(GetProcessHeap(), 0, texture);
5808 return DDERR_INVALIDCAPS;
5809 }
5810 if (desc->ddsCaps.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY))
5811 {
5812 WARN("DDSCAPS2_TEXTUREMANAGE used width DDSCAPS_VIDEOMEMORY "
5813 "or DDSCAPS_SYSTEMMEMORY, returning DDERR_INVALIDCAPS.\n");
5814 HeapFree(GetProcessHeap(), 0, texture);
5815 return DDERR_INVALIDCAPS;
5816 }
5817 }
5818
5819 if (FAILED(hr = wined3d_get_adapter_display_mode(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL)))
5820 {
5821 ERR("Failed to get display mode, hr %#x.\n", hr);
5822 HeapFree(GetProcessHeap(), 0, texture);
5823 return hr_ddraw_from_wined3d(hr);
5824 }
5825
5826 /* No pixelformat given? Use the current screen format. */
5827 if (!(desc->dwFlags & DDSD_PIXELFORMAT))
5828 {
5829 desc->dwFlags |= DDSD_PIXELFORMAT;
5830 desc->u4.ddpfPixelFormat.dwSize = sizeof(desc->u4.ddpfPixelFormat);
5831 ddrawformat_from_wined3dformat(&desc->u4.ddpfPixelFormat, mode.format_id);
5832 }
5833
5834 wined3d_desc.resource_type = WINED3D_RTYPE_TEXTURE_2D;
5835 wined3d_desc.format = wined3dformat_from_ddrawformat(&desc->u4.ddpfPixelFormat);
5836 if (wined3d_desc.format == WINED3DFMT_UNKNOWN)
5837 {
5838 WARN("Unsupported / unknown pixelformat.\n");
5839 HeapFree(GetProcessHeap(), 0, texture);
5840 return DDERR_INVALIDPIXELFORMAT;
5841 }
5842
5843 /* No width or no height? Use the screen size. */
5844 if (!(desc->dwFlags & DDSD_WIDTH) || !(desc->dwFlags & DDSD_HEIGHT))
5845 {
5846 if (!(desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE))
5847 {
5848 WARN("No width / height specified.\n");
5849 HeapFree(GetProcessHeap(), 0, texture);
5850 return DDERR_INVALIDPARAMS;
5851 }
5852
5853 desc->dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
5854 desc->dwWidth = mode.width;
5855 desc->dwHeight = mode.height;
5856 }
5857
5858 if (!desc->dwWidth || !desc->dwHeight)
5859 {
5860 HeapFree(GetProcessHeap(), 0, texture);
5861 return DDERR_INVALIDPARAMS;
5862 }
5863
5864 if (desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
5865 {
5866 /* The first surface is a front buffer, the back buffers are created
5867 * afterwards. */
5868 if (desc->ddsCaps.dwCaps & DDSCAPS_FLIP)
5869 desc->ddsCaps.dwCaps |= DDSCAPS_FRONTBUFFER;
5870 desc->ddsCaps.dwCaps |= DDSCAPS_VISIBLE;
5871 if (ddraw->cooperative_level & DDSCL_EXCLUSIVE)
5872 {
5873 struct wined3d_swapchain_desc swapchain_desc;
5874
5875 wined3d_swapchain_get_desc(ddraw->wined3d_swapchain, &swapchain_desc);
5876 swapchain_desc.backbuffer_width = mode.width;
5877 swapchain_desc.backbuffer_height = mode.height;
5878 swapchain_desc.backbuffer_format = mode.format_id;
5879
5880 if (FAILED(hr = wined3d_device_reset(ddraw->wined3d_device,
5881 &swapchain_desc, NULL, ddraw_reset_enum_callback, TRUE)))
5882 {
5883 ERR("Failed to reset device.\n");
5884 HeapFree(GetProcessHeap(), 0, texture);
5885 return hr_ddraw_from_wined3d(hr);
5886 }
5887 }
5888 }
5889
5890 wined3d_desc.multisample_type = WINED3D_MULTISAMPLE_NONE;
5891 wined3d_desc.multisample_quality = 0;
5892 wined3d_desc.usage = 0;
5893 wined3d_desc.pool = WINED3D_POOL_DEFAULT;
5894 wined3d_desc.width = desc->dwWidth;
5895 wined3d_desc.height = desc->dwHeight;
5896 wined3d_desc.depth = 1;
5897 wined3d_desc.size = 0;
5898
5899 if ((desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) && (ddraw->flags & DDRAW_NO3D))
5900 {
5901 WARN("The application requests a 3D capable surface, but the ddraw object was created without 3D support.\n");
5902 /* Do not fail surface creation, only fail 3D device creation. */
5903 }
5904
5905 /* Mipmap count fixes */
5906 if (desc->ddsCaps.dwCaps & DDSCAPS_MIPMAP)
5907 {
5908 if (desc->ddsCaps.dwCaps & DDSCAPS_COMPLEX)
5909 {
5910 if (desc->dwFlags & DDSD_MIPMAPCOUNT)
5911 {
5912 /* Mipmap count is given, should not be 0. */
5913 if (!desc->u2.dwMipMapCount)
5914 {
5915 HeapFree(GetProcessHeap(), 0, texture);
5916 return DDERR_INVALIDPARAMS;
5917 }
5918 }
5919 else
5920 {
5921 /* Undocumented feature: Create sublevels until either the
5922 * width or the height is 1. */
5923 if (version == 7)
5924 desc->u2.dwMipMapCount = wined3d_log2i(max(desc->dwWidth, desc->dwHeight)) + 1;
5925 else
5926 desc->u2.dwMipMapCount = wined3d_log2i(min(desc->dwWidth, desc->dwHeight)) + 1;
5927 }
5928 }
5929 else
5930 {
5931 desc->u2.dwMipMapCount = 1;
5932 }
5933
5934 desc->dwFlags |= DDSD_MIPMAPCOUNT;
5935 levels = desc->u2.dwMipMapCount;
5936 }
5937 else
5938 {
5939 levels = 1;
5940 }
5941
5942 if (!(desc->ddsCaps.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY)))
5943 {
5944 if (!(desc->ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE)))
5945 {
5946 enum wined3d_resource_type rtype;
5947 DWORD usage = 0;
5948
5949 if (desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
5950 {
5951 usage |= WINED3DUSAGE_LEGACY_CUBEMAP;
5952 rtype = WINED3D_RTYPE_TEXTURE_2D;
5953 }
5954 else if (desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE)
5955 rtype = WINED3D_RTYPE_TEXTURE_2D;
5956 else
5957 rtype = WINED3D_RTYPE_SURFACE;
5958
5959 if (desc->ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
5960 usage = WINED3DUSAGE_DEPTHSTENCIL;
5961 else if (desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
5962 usage = WINED3DUSAGE_RENDERTARGET;
5963
5964 if (SUCCEEDED(hr = wined3d_check_device_format(ddraw->wined3d, WINED3DADAPTER_DEFAULT,
5965 WINED3D_DEVICE_TYPE_HAL, mode.format_id, usage, rtype, wined3d_desc.format)))
5966 desc->ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
5967 else
5968 desc->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
5969 }
5970 else if (!(desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE))
5971 {
5972 /* Tests show surfaces without memory flags get these flags added
5973 * right after creation. */
5974 desc->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY;
5975 }
5976 }
5977
5978 if ((desc->ddsCaps.dwCaps & (DDSCAPS_OVERLAY | DDSCAPS_SYSTEMMEMORY))
5979 == (DDSCAPS_OVERLAY | DDSCAPS_SYSTEMMEMORY))
5980 {
5981 WARN("System memory overlays are not allowed.\n");
5982 HeapFree(GetProcessHeap(), 0, texture);
5983 return DDERR_NOOVERLAYHW;
5984 }
5985
5986 if (desc->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
5987 {
5988 /*
5989 * The ddraw RGB device allows to use system memory surfaces as rendering target.
5990 * This does not cause problems because the RGB device does software rasterization
5991 * though it will fail with hardware accelerated ddraw. In order to be partially
5992 * compatible with games requesting explicitly the RGB device, we ignore the
5993 * specified location and try to create rendering targets in video memory if
5994 * possible.
5995 */
5996 if ((desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) &&
5997 SUCCEEDED(hr = wined3d_check_device_format(ddraw->wined3d, WINED3DADAPTER_DEFAULT,
5998 WINED3D_DEVICE_TYPE_HAL, mode.format_id, WINED3DUSAGE_RENDERTARGET,
5999 WINED3D_RTYPE_SURFACE, wined3d_desc.format)))
6000 {
6001 FIXME("Application wants to create rendering target in system memory, using video memory instead\n");
6002 wined3d_desc.usage |= WINED3DUSAGE_RENDERTARGET;
6003 }
6004 else
6005 wined3d_desc.pool = WINED3D_POOL_SYSTEM_MEM;
6006 }
6007 else
6008 {
6009 if (desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE)
6010 wined3d_desc.usage |= WINED3DUSAGE_TEXTURE;
6011 if (desc->ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
6012 wined3d_desc.usage |= WINED3DUSAGE_DEPTHSTENCIL;
6013 else if (desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
6014 wined3d_desc.usage |= WINED3DUSAGE_RENDERTARGET;
6015
6016 if (desc->ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE))
6017 {
6018 wined3d_desc.pool = WINED3D_POOL_MANAGED;
6019 /* Managed textures have the system memory flag set. */
6020 desc->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
6021 }
6022 else if (desc->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
6023 {
6024 /* Videomemory adds localvidmem. This is mutually exclusive with
6025 * systemmemory and texturemanage. */
6026 desc->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM;
6027 wined3d_desc.usage |= WINED3DUSAGE_DYNAMIC;
6028 }
6029 }
6030
6031 if (desc->dwFlags & DDSD_LPSURFACE)
6032 {
6033 if (wined3d_desc.pool != WINED3D_POOL_SYSTEM_MEM)
6034 {
6035 WARN("User memory surfaces should be in the system memory pool.\n");
6036 HeapFree(GetProcessHeap(), 0, texture);
6037 return DDERR_INVALIDCAPS;
6038 }
6039
6040 if (version < 4)
6041 {
6042 WARN("User memory surfaces not supported before version 4.\n");
6043 HeapFree(GetProcessHeap(), 0, texture);
6044 return DDERR_INVALIDPARAMS;
6045 }
6046
6047 if (!desc->lpSurface)
6048 {
6049 WARN("NULL surface memory pointer specified.\n");
6050 HeapFree(GetProcessHeap(), 0, texture);
6051 return DDERR_INVALIDPARAMS;
6052 }
6053
6054 if (format_is_compressed(&desc->u4.ddpfPixelFormat))
6055 {
6056 if (version != 4 && (desc->dwFlags & DDSD_PITCH))
6057 {
6058 WARN("Pitch specified on a compressed user memory surface.\n");
6059 HeapFree(GetProcessHeap(), 0, texture);
6060 return DDERR_INVALIDPARAMS;
6061 }
6062
6063 if (!(desc->dwFlags & (DDSD_LINEARSIZE | DDSD_PITCH)))
6064 {
6065 WARN("Compressed user memory surfaces should explicitly specify the linear size.\n");
6066 HeapFree(GetProcessHeap(), 0, texture);
6067 return DDERR_INVALIDPARAMS;
6068 }
6069
6070 if ((desc->dwFlags & DDSD_LINEARSIZE)
6071 && desc->u1.dwLinearSize < wined3d_calculate_format_pitch(ddraw->wined3d, WINED3DADAPTER_DEFAULT,
6072 wined3d_desc.format, wined3d_desc.width) * ((desc->dwHeight + 3) / 4))
6073 {
6074 WARN("Invalid linear size %u specified.\n", desc->u1.dwLinearSize);
6075 HeapFree(GetProcessHeap(), 0, texture);
6076 return DDERR_INVALIDPARAMS;
6077 }
6078 }
6079 else
6080 {
6081 if (!(desc->dwFlags & DDSD_PITCH))
6082 {
6083 WARN("User memory surfaces should explicitly specify the pitch.\n");
6084 HeapFree(GetProcessHeap(), 0, texture);
6085 return DDERR_INVALIDPARAMS;
6086 }
6087
6088 if (desc->u1.lPitch < wined3d_calculate_format_pitch(ddraw->wined3d, WINED3DADAPTER_DEFAULT,
6089 wined3d_desc.format, wined3d_desc.width) || desc->u1.lPitch & 3)
6090 {
6091 WARN("Invalid pitch %u specified.\n", desc->u1.lPitch);
6092 HeapFree(GetProcessHeap(), 0, texture);
6093 return DDERR_INVALIDPARAMS;
6094 }
6095
6096 pitch = desc->u1.lPitch;
6097 }
6098 }
6099
6100 if (((desc->dwFlags & DDSD_CKDESTOVERLAY)
6101 && desc->u3.ddckCKDestOverlay.dwColorSpaceLowValue != desc->u3.ddckCKDestOverlay.dwColorSpaceHighValue)
6102 || ((desc->dwFlags & DDSD_CKDESTBLT)
6103 && desc->ddckCKDestBlt.dwColorSpaceLowValue != desc->ddckCKDestBlt.dwColorSpaceHighValue)
6104 || ((desc->dwFlags & DDSD_CKSRCOVERLAY)
6105 && desc->ddckCKSrcOverlay.dwColorSpaceLowValue != desc->ddckCKSrcOverlay.dwColorSpaceHighValue)
6106 || ((desc->dwFlags & DDSD_CKSRCBLT)
6107 && desc->ddckCKSrcBlt.dwColorSpaceLowValue != desc->ddckCKSrcBlt.dwColorSpaceHighValue))
6108 {
6109 WARN("Range color keys not supported, returning DDERR_NOCOLORKEYHW.\n");
6110 HeapFree(GetProcessHeap(), 0, texture);
6111 return DDERR_NOCOLORKEYHW;
6112 }
6113
6114 if (desc->ddsCaps.dwCaps & (DDSCAPS_OVERLAY))
6115 wined3d_desc.usage |= WINED3DUSAGE_OVERLAY;
6116
6117 if (desc->ddsCaps.dwCaps & DDSCAPS_OWNDC)
6118 wined3d_desc.usage |= WINED3DUSAGE_OWNDC;
6119
6120 if (desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6121 {
6122 wined3d_desc.usage |= WINED3DUSAGE_LEGACY_CUBEMAP;
6123 layers = 6;
6124 }
6125
6126 /* Some applications assume surfaces will always be mapped at the same
6127 * address. Some of those also assume that this address is valid even when
6128 * the surface isn't mapped, and that updates done this way will be
6129 * visible on the screen. The game Nox is such an application,
6130 * Commandos: Behind Enemy Lines is another. We set
6131 * WINED3D_TEXTURE_CREATE_PIN_SYSMEM because of this. */
6132 if (FAILED(hr = wined3d_texture_create(ddraw->wined3d_device, &wined3d_desc, levels,
6133 WINED3D_TEXTURE_CREATE_PIN_SYSMEM, NULL, texture, &ddraw_texture_wined3d_parent_ops, &wined3d_texture)))
6134 {
6135 WARN("Failed to create wined3d texture, hr %#x.\n", hr);
6136 HeapFree(GetProcessHeap(), 0, texture);
6137 return hr_ddraw_from_wined3d(hr);
6138 }
6139
6140 root = wined3d_texture_get_sub_resource_parent(wined3d_texture, 0);
6141 wined3d_texture_decref(wined3d_texture);
6142 root->is_complex_root = TRUE;
6143 texture->root = root;
6144
6145 if (desc->dwFlags & DDSD_CKDESTOVERLAY)
6146 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_DESTOVERLAY,
6147 (struct wined3d_color_key *)&desc->u3.ddckCKDestOverlay);
6148 if (desc->dwFlags & DDSD_CKDESTBLT)
6149 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_DESTBLT,
6150 (struct wined3d_color_key *)&desc->ddckCKDestBlt);
6151 if (desc->dwFlags & DDSD_CKSRCOVERLAY)
6152 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_SRCOVERLAY,
6153 (struct wined3d_color_key *)&desc->ddckCKSrcOverlay);
6154 if (desc->dwFlags & DDSD_CKSRCBLT)
6155 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_SRCBLT,
6156 (struct wined3d_color_key *)&desc->ddckCKSrcBlt);
6157
6158 for (i = 0; i < layers; ++i)
6159 {
6160 attach = &root->complex_array[layers - 1 - i];
6161
6162 for (j = 0; j < levels; ++j)
6163 {
6164 mip = wined3d_texture_get_sub_resource_parent(wined3d_texture, i * levels + j);
6165 mip_desc = &mip->surface_desc;
6166
6167 if (j)
6168 {
6169 resource = wined3d_texture_get_sub_resource(wined3d_texture, i * levels + j);
6170 wined3d_resource_get_desc(resource, &wined3d_mip_desc);
6171 mip_desc->dwWidth = wined3d_mip_desc.width;
6172 mip_desc->dwHeight = wined3d_mip_desc.height;
6173
6174 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_MIPMAPSUBLEVEL;
6175 }
6176 else
6177 {
6178 mip_desc->ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL;
6179 }
6180
6181 if (mip_desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6182 {
6183 mip_desc->ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_ALLFACES;
6184
6185 switch (i)
6186 {
6187 case WINED3D_CUBEMAP_FACE_POSITIVE_X:
6188 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEX;
6189 break;
6190 case WINED3D_CUBEMAP_FACE_NEGATIVE_X:
6191 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEX;
6192 break;
6193 case WINED3D_CUBEMAP_FACE_POSITIVE_Y:
6194 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEY;
6195 break;
6196 case WINED3D_CUBEMAP_FACE_NEGATIVE_Y:
6197 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEY;
6198 break;
6199 case WINED3D_CUBEMAP_FACE_POSITIVE_Z:
6200 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEZ;
6201 break;
6202 case WINED3D_CUBEMAP_FACE_NEGATIVE_Z:
6203 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEZ;
6204 break;
6205 }
6206
6207 }
6208
6209 if (mip == root)
6210 continue;
6211
6212 *attach = mip;
6213 attach = &mip->complex_array[0];
6214 }
6215 }
6216
6217 if ((desc->dwFlags & DDSD_LPSURFACE) && FAILED(hr = wined3d_texture_update_desc(wined3d_texture,
6218 wined3d_desc.width, wined3d_desc.height, wined3d_desc.format,
6219 WINED3D_MULTISAMPLE_NONE, 0, desc->lpSurface, pitch)))
6220 {
6221 ERR("Failed to set surface memory, hr %#x.\n", hr);
6222 goto fail;
6223 }
6224
6225 if (desc->dwFlags & DDSD_BACKBUFFERCOUNT)
6226 {
6227 unsigned int count = desc->u5.dwBackBufferCount;
6228 struct ddraw_surface *last = root;
6229
6230 attach = &last->complex_array[0];
6231 for (i = 0; i < count; ++i)
6232 {
6233 if (!(texture = HeapAlloc(GetProcessHeap(), 0, sizeof(*texture))))
6234 {
6235 hr = E_OUTOFMEMORY;
6236 goto fail;
6237 }
6238
6239 texture->version = version;
6240 texture->surface_desc = root->surface_desc;
6241 desc = &texture->surface_desc;
6242
6243 /* Only one surface in the flipping chain is a back buffer, one is
6244 * a front buffer, the others are just flippable surfaces. */
6245 desc->ddsCaps.dwCaps &= ~(DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER
6246 | DDSCAPS_BACKBUFFER);
6247 if (!i)
6248 desc->ddsCaps.dwCaps |= DDSCAPS_BACKBUFFER;
6249 desc->u5.dwBackBufferCount = 0;
6250
6251 if (FAILED(hr = wined3d_texture_create(ddraw->wined3d_device, &wined3d_desc, 1,
6252 WINED3D_TEXTURE_CREATE_PIN_SYSMEM, NULL, texture,
6253 &ddraw_texture_wined3d_parent_ops, &wined3d_texture)))
6254 {
6255 HeapFree(GetProcessHeap(), 0, texture);
6256 hr = hr_ddraw_from_wined3d(hr);
6257 goto fail;
6258 }
6259
6260 last = wined3d_texture_get_sub_resource_parent(wined3d_texture, 0);
6261 wined3d_texture_decref(wined3d_texture);
6262 texture->root = last;
6263
6264 if (desc->dwFlags & DDSD_CKDESTOVERLAY)
6265 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_DESTOVERLAY,
6266 (struct wined3d_color_key *)&desc->u3.ddckCKDestOverlay);
6267 if (desc->dwFlags & DDSD_CKDESTBLT)
6268 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_DESTBLT,
6269 (struct wined3d_color_key *)&desc->ddckCKDestBlt);
6270 if (desc->dwFlags & DDSD_CKSRCOVERLAY)
6271 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_SRCOVERLAY,
6272 (struct wined3d_color_key *)&desc->ddckCKSrcOverlay);
6273 if (desc->dwFlags & DDSD_CKSRCBLT)
6274 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_SRCBLT,
6275 (struct wined3d_color_key *)&desc->ddckCKSrcBlt);
6276
6277 *attach = last;
6278 attach = &last->complex_array[0];
6279 }
6280 *attach = root;
6281 }
6282
6283 if (surface_desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
6284 ddraw->primary = root;
6285 *surface = root;
6286
6287 return DD_OK;
6288
6289 fail:
6290 if (version == 7)
6291 IDirectDrawSurface7_Release(&root->IDirectDrawSurface7_iface);
6292 else if (version == 4)
6293 IDirectDrawSurface4_Release(&root->IDirectDrawSurface4_iface);
6294 else
6295 IDirectDrawSurface_Release(&root->IDirectDrawSurface_iface);
6296
6297 return hr;
6298 }
6299
6300 void ddraw_surface_init(struct ddraw_surface *surface, struct ddraw *ddraw,
6301 struct wined3d_texture *wined3d_texture, unsigned int sub_resource_idx,
6302 const struct wined3d_parent_ops **parent_ops)
6303 {
6304 struct ddraw_texture *texture = wined3d_texture_get_parent(wined3d_texture);
6305 unsigned int texture_level, row_pitch, slice_pitch;
6306 DDSURFACEDESC2 *desc = &surface->surface_desc;
6307 unsigned int version = texture->version;
6308
6309 surface->IDirectDrawSurface7_iface.lpVtbl = &ddraw_surface7_vtbl;
6310 surface->IDirectDrawSurface4_iface.lpVtbl = &ddraw_surface4_vtbl;
6311 surface->IDirectDrawSurface3_iface.lpVtbl = &ddraw_surface3_vtbl;
6312 surface->IDirectDrawSurface2_iface.lpVtbl = &ddraw_surface2_vtbl;
6313 surface->IDirectDrawSurface_iface.lpVtbl = &ddraw_surface1_vtbl;
6314 surface->IDirectDrawGammaControl_iface.lpVtbl = &ddraw_gamma_control_vtbl;
6315 surface->IDirect3DTexture2_iface.lpVtbl = &d3d_texture2_vtbl;
6316 surface->IDirect3DTexture_iface.lpVtbl = &d3d_texture1_vtbl;
6317 surface->iface_count = 1;
6318 surface->version = version;
6319 surface->ddraw = ddraw;
6320
6321 if (version == 7)
6322 {
6323 surface->ref7 = 1;
6324 surface->texture_outer = (IUnknown *)&surface->IDirectDrawSurface7_iface;
6325 }
6326 else if (version == 4)
6327 {
6328 surface->ref4 = 1;
6329 surface->texture_outer = (IUnknown *)&surface->IDirectDrawSurface4_iface;
6330 }
6331 else
6332 {
6333 surface->ref1 = 1;
6334 surface->texture_outer = (IUnknown *)&surface->IDirectDrawSurface_iface;
6335 }
6336
6337 *desc = texture->surface_desc;
6338 surface->first_attached = surface;
6339
6340 texture_level = desc->ddsCaps.dwCaps & DDSCAPS_MIPMAP ? sub_resource_idx % desc->u2.dwMipMapCount : 0;
6341 wined3d_texture_get_pitch(wined3d_texture, texture_level, &row_pitch, &slice_pitch);
6342 if (format_is_compressed(&desc->u4.ddpfPixelFormat))
6343 {
6344 if (desc->dwFlags & DDSD_LPSURFACE)
6345 desc->u1.dwLinearSize = ~0u;
6346 else
6347 desc->u1.dwLinearSize = slice_pitch;
6348 desc->dwFlags |= DDSD_LINEARSIZE;
6349 desc->dwFlags &= ~(DDSD_LPSURFACE | DDSD_PITCH);
6350 }
6351 else
6352 {
6353 if (!(desc->dwFlags & DDSD_LPSURFACE))
6354 desc->u1.lPitch = row_pitch;
6355 desc->dwFlags |= DDSD_PITCH;
6356 desc->dwFlags &= ~(DDSD_LPSURFACE | DDSD_LINEARSIZE);
6357 }
6358 desc->lpSurface = NULL;
6359
6360 wined3d_texture_incref(surface->wined3d_texture = wined3d_texture);
6361 surface->sub_resource_idx = sub_resource_idx;
6362 *parent_ops = &ddraw_surface_wined3d_parent_ops;
6363
6364 wined3d_private_store_init(&surface->private_store);
6365 }
6366
6367 static void STDMETHODCALLTYPE view_wined3d_object_destroyed(void *parent)
6368 {
6369 struct ddraw_surface *surface = parent;
6370
6371 /* If the surface reference count drops to zero, we release our reference
6372 * to the view, but don't clear the pointer yet, in case e.g. a
6373 * GetRenderTarget() call brings the surface back before the view is
6374 * actually destroyed. When the view is destroyed, we need to clear the
6375 * pointer, or a subsequent surface AddRef() would reference it again.
6376 *
6377 * This is safe because as long as the view still has a reference to the
6378 * texture, the surface is also still alive, and we're called before the
6379 * view releases that reference. */
6380 surface->wined3d_rtv = NULL;
6381 }
6382
6383 static const struct wined3d_parent_ops ddraw_view_wined3d_parent_ops =
6384 {
6385 view_wined3d_object_destroyed,
6386 };
6387
6388 struct wined3d_rendertarget_view *ddraw_surface_get_rendertarget_view(struct ddraw_surface *surface)
6389 {
6390 HRESULT hr;
6391
6392 if (surface->wined3d_rtv)
6393 return surface->wined3d_rtv;
6394
6395 if (FAILED(hr = wined3d_rendertarget_view_create_from_sub_resource(surface->wined3d_texture,
6396 surface->sub_resource_idx, surface, &ddraw_view_wined3d_parent_ops, &surface->wined3d_rtv)))
6397 {
6398 ERR("Failed to create rendertarget view, hr %#x.\n", hr);
6399 return NULL;
6400 }
6401
6402 return surface->wined3d_rtv;
6403 }