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