1 /* DirectDraw Surface Implementation
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
8 * This file contains the (internal) driver registration functions,
9 * driver enumeration APIs and DirectDraw creation functions.
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #include "wine/port.h"
29 #include "ddraw_private.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(ddraw
);
33 static inline IDirectDrawSurfaceImpl
*surface_from_gamma_control(IDirectDrawGammaControl
*iface
)
35 return (IDirectDrawSurfaceImpl
*)((char*)iface
36 - FIELD_OFFSET(IDirectDrawSurfaceImpl
, IDirectDrawGammaControl_vtbl
));
39 /*****************************************************************************
40 * IUnknown parts follow
41 *****************************************************************************/
43 /*****************************************************************************
44 * IDirectDrawSurface7::QueryInterface
46 * A normal QueryInterface implementation. For QueryInterface rules
47 * see ddraw.c, IDirectDraw7::QueryInterface. This method
48 * can Query IDirectDrawSurface interfaces in all version, IDirect3DTexture
49 * in all versions, the IDirectDrawGammaControl interface and it can
50 * create an IDirect3DDevice. (Uses IDirect3D7::CreateDevice)
53 * riid: The interface id queried for
54 * obj: Address to write the pointer to
58 * E_NOINTERFACE if the requested interface wasn't found
60 *****************************************************************************/
61 static HRESULT WINAPI
ddraw_surface7_QueryInterface(IDirectDrawSurface7
*iface
, REFIID riid
, void **obj
)
63 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(iface
);
65 TRACE("iface %p, riid %s, object %p.\n", iface
, debugstr_guid(riid
), obj
);
67 /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
71 return DDERR_INVALIDPARAMS
;
73 if (IsEqualGUID(riid
, &IID_IUnknown
)
74 || IsEqualGUID(riid
, &IID_IDirectDrawSurface7
)
75 || IsEqualGUID(riid
, &IID_IDirectDrawSurface4
) )
77 IUnknown_AddRef(iface
);
79 TRACE("(%p) returning IDirectDrawSurface7 interface at %p\n", This
, *obj
);
82 else if( IsEqualGUID(riid
, &IID_IDirectDrawSurface3
)
83 || IsEqualGUID(riid
, &IID_IDirectDrawSurface2
)
84 || IsEqualGUID(riid
, &IID_IDirectDrawSurface
) )
86 IUnknown_AddRef(iface
);
87 *obj
= &This
->IDirectDrawSurface3_iface
;
88 TRACE("(%p) returning IDirectDrawSurface3 interface at %p\n", This
, *obj
);
91 else if( IsEqualGUID(riid
, &IID_IDirectDrawGammaControl
) )
93 IUnknown_AddRef(iface
);
94 *obj
= &This
->IDirectDrawGammaControl_vtbl
;
95 TRACE("(%p) returning IDirectDrawGammaControl interface at %p\n", This
, *obj
);
98 else if( IsEqualGUID(riid
, &IID_D3DDEVICE_WineD3D
) ||
99 IsEqualGUID(riid
, &IID_IDirect3DHALDevice
)||
100 IsEqualGUID(riid
, &IID_IDirect3DRGBDevice
) )
102 IDirect3DDevice7
*d3d
;
104 /* Call into IDirect3D7 for creation */
105 IDirect3D7_CreateDevice(&This
->ddraw
->IDirect3D7_iface
, riid
, &This
->IDirectDrawSurface7_iface
,
110 *obj
= (IDirect3DDevice
*)&((IDirect3DDeviceImpl
*)d3d
)->IDirect3DDevice_vtbl
;
111 TRACE("(%p) Returning IDirect3DDevice interface at %p\n", This
, *obj
);
115 WARN("Unable to create a IDirect3DDevice instance, returning E_NOINTERFACE\n");
116 return E_NOINTERFACE
;
118 else if (IsEqualGUID( &IID_IDirect3DTexture
, riid
) ||
119 IsEqualGUID( &IID_IDirect3DTexture2
, riid
))
121 if (IsEqualGUID( &IID_IDirect3DTexture
, riid
))
123 *obj
= &This
->IDirect3DTexture_vtbl
;
124 TRACE(" returning Direct3DTexture interface at %p.\n", *obj
);
128 *obj
= &This
->IDirect3DTexture2_vtbl
;
129 TRACE(" returning Direct3DTexture2 interface at %p.\n", *obj
);
131 IUnknown_AddRef( (IUnknown
*) *obj
);
135 ERR("No interface\n");
136 return E_NOINTERFACE
;
139 static HRESULT WINAPI
ddraw_surface3_QueryInterface(IDirectDrawSurface3
*iface
, REFIID riid
, void **object
)
141 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface3(iface
);
142 TRACE("iface %p, riid %s, object %p.\n", iface
, debugstr_guid(riid
), object
);
144 return ddraw_surface7_QueryInterface(&This
->IDirectDrawSurface7_iface
, riid
, object
);
147 static HRESULT WINAPI
ddraw_gamma_control_QueryInterface(IDirectDrawGammaControl
*iface
, REFIID riid
, void **object
)
149 IDirectDrawSurfaceImpl
*This
= surface_from_gamma_control(iface
);
150 TRACE("iface %p, riid %s, object %p.\n", iface
, debugstr_guid(riid
), object
);
152 return ddraw_surface7_QueryInterface(&This
->IDirectDrawSurface7_iface
, riid
, object
);
155 static HRESULT WINAPI
d3d_texture2_QueryInterface(IDirect3DTexture2
*iface
, REFIID riid
, void **object
)
157 IDirectDrawSurfaceImpl
*This
= surface_from_texture2(iface
);
158 TRACE("iface %p, riid %s, object %p.\n", iface
, debugstr_guid(riid
), object
);
160 return ddraw_surface7_QueryInterface(&This
->IDirectDrawSurface7_iface
, riid
, object
);
163 static HRESULT WINAPI
d3d_texture1_QueryInterface(IDirect3DTexture
*iface
, REFIID riid
, void **object
)
165 IDirectDrawSurfaceImpl
*This
= surface_from_texture1(iface
);
166 TRACE("iface %p, riid %s, object %p.\n", iface
, debugstr_guid(riid
), object
);
168 return ddraw_surface7_QueryInterface(&This
->IDirectDrawSurface7_iface
, riid
, object
);
171 /*****************************************************************************
172 * IDirectDrawSurface7::AddRef
174 * A normal addref implementation
179 *****************************************************************************/
180 static ULONG WINAPI
ddraw_surface7_AddRef(IDirectDrawSurface7
*iface
)
182 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(iface
);
183 ULONG refCount
= InterlockedIncrement(&This
->ref
);
185 TRACE("%p increasing refcount to %u.\n", This
, refCount
);
189 EnterCriticalSection(&ddraw_cs
);
190 if (This
->wined3d_surface
)
191 wined3d_surface_incref(This
->wined3d_surface
);
192 if (This
->wined3d_texture
)
193 wined3d_texture_incref(This
->wined3d_texture
);
194 LeaveCriticalSection(&ddraw_cs
);
200 static ULONG WINAPI
ddraw_surface3_AddRef(IDirectDrawSurface3
*iface
)
202 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface3(iface
);
203 TRACE("iface %p.\n", iface
);
205 return ddraw_surface7_AddRef(&This
->IDirectDrawSurface7_iface
);
208 static ULONG WINAPI
ddraw_gamma_control_AddRef(IDirectDrawGammaControl
*iface
)
210 IDirectDrawSurfaceImpl
*This
= surface_from_gamma_control(iface
);
211 TRACE("iface %p.\n", iface
);
213 return ddraw_surface7_AddRef(&This
->IDirectDrawSurface7_iface
);
216 static ULONG WINAPI
d3d_texture2_AddRef(IDirect3DTexture2
*iface
)
218 IDirectDrawSurfaceImpl
*This
= surface_from_texture2(iface
);
219 TRACE("iface %p.\n", iface
);
221 return ddraw_surface7_AddRef(&This
->IDirectDrawSurface7_iface
);
224 static ULONG WINAPI
d3d_texture1_AddRef(IDirect3DTexture
*iface
)
226 IDirectDrawSurfaceImpl
*This
= surface_from_texture1(iface
);
227 TRACE("iface %p.\n", iface
);
229 return ddraw_surface7_AddRef(&This
->IDirectDrawSurface7_iface
);
232 /*****************************************************************************
233 * ddraw_surface_destroy
235 * A helper function for IDirectDrawSurface7::Release
237 * Frees the surface, regardless of its refcount.
238 * See IDirectDrawSurface7::Release for more information
241 * This: Surface to free
243 *****************************************************************************/
244 void ddraw_surface_destroy(IDirectDrawSurfaceImpl
*This
)
246 TRACE("surface %p.\n", This
);
248 /* Check the refcount and give a warning */
251 /* This can happen when a complex surface is destroyed,
252 * because the 2nd surface was addref()ed when the app
253 * called GetAttachedSurface
255 WARN("(%p): Destroying surface with refount %d\n", This
, This
->ref
);
258 if (This
->wined3d_surface
)
259 wined3d_surface_decref(This
->wined3d_surface
);
262 static void ddraw_surface_cleanup(IDirectDrawSurfaceImpl
*surface
)
264 IDirectDrawSurfaceImpl
*surf
;
265 IUnknown
*ifaceToRelease
;
268 TRACE("surface %p.\n", surface
);
270 if (surface
->wined3d_swapchain
)
272 IDirectDrawImpl
*ddraw
= surface
->ddraw
;
274 /* If it's the render target, destroy the D3D device. */
275 if (ddraw
->d3d_initialized
&& surface
== ddraw
->d3d_target
)
277 TRACE("Destroying the render target, uninitializing D3D.\n");
279 for (i
= 0; i
< ddraw
->numConvertedDecls
; ++i
)
281 wined3d_vertex_declaration_decref(ddraw
->decls
[i
].decl
);
283 HeapFree(GetProcessHeap(), 0, ddraw
->decls
);
284 ddraw
->numConvertedDecls
= 0;
286 if (FAILED(wined3d_device_uninit_3d(ddraw
->wined3d_device
)))
288 ERR("Failed to uninit 3D.\n");
292 /* Free the d3d window if one was created. */
293 if (ddraw
->d3d_window
&& ddraw
->d3d_window
!= ddraw
->dest_window
)
295 TRACE("Destroying the hidden render window %p.\n", ddraw
->d3d_window
);
296 DestroyWindow(ddraw
->d3d_window
);
297 ddraw
->d3d_window
= 0;
301 ddraw
->d3d_initialized
= FALSE
;
302 ddraw
->d3d_target
= NULL
;
306 wined3d_device_uninit_gdi(ddraw
->wined3d_device
);
309 surface
->wined3d_swapchain
= NULL
;
311 /* Reset to the default surface implementation type. This is needed
312 * if applications use non render target surfaces and expect blits to
313 * work after destroying the render target.
315 * TODO: Recreate existing offscreen surfaces. */
316 ddraw
->ImplType
= DefaultSurfaceType
;
318 TRACE("D3D unloaded.\n");
321 /* The refcount test shows that the palette is detached when the surface
323 IDirectDrawSurface7_SetPalette(&surface
->IDirectDrawSurface7_iface
, NULL
);
325 /* Loop through all complex attached surfaces and destroy them.
327 * Yet again, only the root can have more than one complexly attached
328 * surface, all the others have a total of one. */
329 for (i
= 0; i
< MAX_COMPLEX_ATTACHED
; ++i
)
331 if (!surface
->complex_array
[i
])
334 surf
= surface
->complex_array
[i
];
335 surface
->complex_array
[i
] = NULL
;
338 IDirectDrawSurfaceImpl
*destroy
= surf
;
339 surf
= surf
->complex_array
[0]; /* Iterate through the "tree" */
340 ddraw_surface_destroy(destroy
); /* Destroy it */
344 ifaceToRelease
= surface
->ifaceToRelease
;
346 /* Destroy the root surface. */
347 ddraw_surface_destroy(surface
);
349 /* Reduce the ddraw refcount */
351 IUnknown_Release(ifaceToRelease
);
354 /*****************************************************************************
355 * IDirectDrawSurface7::Release
357 * Reduces the surface's refcount by 1. If the refcount falls to 0, the
358 * surface is destroyed.
360 * Destroying the surface is a bit tricky. For the connection between
361 * WineD3DSurfaces and DirectDrawSurfaces see IDirectDraw7::CreateSurface
362 * It has a nice graph explaining the connection.
364 * What happens here is basically this:
365 * When a surface is destroyed, its WineD3DSurface is released,
366 * and the refcount of the DirectDraw interface is reduced by 1. If it has
367 * complex surfaces attached to it, then these surfaces are destroyed too,
368 * regardless of their refcount. If any surface being destroyed has another
369 * surface attached to it (with a "soft" attachment, not complex), then
370 * this surface is detached with DeleteAttachedSurface.
372 * When the surface is a texture, the WineD3DTexture is released.
373 * If the surface is the Direct3D render target, then the D3D
374 * capabilities of the WineD3DDevice are uninitialized, which causes the
375 * swapchain to be released.
377 * When a complex sublevel falls to ref zero, then this is ignored.
382 *****************************************************************************/
383 static ULONG WINAPI
ddraw_surface7_Release(IDirectDrawSurface7
*iface
)
385 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(iface
);
386 ULONG ref
= InterlockedDecrement(&This
->ref
);
388 TRACE("%p decreasing refcount to %u.\n", This
, ref
);
392 /* Complex attached surfaces are destroyed implicitly when the root is released */
393 EnterCriticalSection(&ddraw_cs
);
394 if(!This
->is_complex_root
)
396 WARN("(%p) Attempt to destroy a surface that is not a complex root\n", This
);
397 LeaveCriticalSection(&ddraw_cs
);
400 if (This
->wined3d_texture
) /* If it's a texture, destroy the wined3d texture. */
401 wined3d_texture_decref(This
->wined3d_texture
);
403 ddraw_surface_cleanup(This
);
404 LeaveCriticalSection(&ddraw_cs
);
410 static ULONG WINAPI
ddraw_surface3_Release(IDirectDrawSurface3
*iface
)
412 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface3(iface
);
413 TRACE("iface %p.\n", iface
);
415 return ddraw_surface7_Release(&This
->IDirectDrawSurface7_iface
);
418 static ULONG WINAPI
ddraw_gamma_control_Release(IDirectDrawGammaControl
*iface
)
420 IDirectDrawSurfaceImpl
*This
= surface_from_gamma_control(iface
);
421 TRACE("iface %p.\n", iface
);
423 return ddraw_surface7_Release(&This
->IDirectDrawSurface7_iface
);
426 static ULONG WINAPI
d3d_texture2_Release(IDirect3DTexture2
*iface
)
428 IDirectDrawSurfaceImpl
*This
= surface_from_texture2(iface
);
429 TRACE("iface %p.\n", iface
);
431 return ddraw_surface7_Release(&This
->IDirectDrawSurface7_iface
);
434 static ULONG WINAPI
d3d_texture1_Release(IDirect3DTexture
*iface
)
436 IDirectDrawSurfaceImpl
*This
= surface_from_texture1(iface
);
437 TRACE("iface %p.\n", iface
);
439 return ddraw_surface7_Release(&This
->IDirectDrawSurface7_iface
);
442 /*****************************************************************************
443 * IDirectDrawSurface7::GetAttachedSurface
445 * Returns an attached surface with the requested caps. Surface attachment
446 * and complex surfaces are not clearly described by the MSDN or sdk,
447 * so this method is tricky and likely to contain problems.
448 * This implementation searches the complex list first, then the
451 * The chains are searched from This down to the last surface in the chain,
452 * not from the first element in the chain. The first surface found is
453 * returned. The MSDN says that this method fails if more than one surface
454 * matches the caps, but it is not sure if that is right. The attachment
455 * structure may not even allow two matching surfaces.
457 * The found surface is AddRef-ed before it is returned.
460 * Caps: Pointer to a DDCAPS2 structure describing the caps asked for
461 * Surface: Address to store the found surface
465 * DDERR_INVALIDPARAMS if Caps or Surface is NULL
466 * DDERR_NOTFOUND if no surface was found
468 *****************************************************************************/
469 static HRESULT WINAPI
ddraw_surface7_GetAttachedSurface(IDirectDrawSurface7
*iface
,
470 DDSCAPS2
*Caps
, IDirectDrawSurface7
**Surface
)
472 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(iface
);
473 IDirectDrawSurfaceImpl
*surf
;
477 TRACE("iface %p, caps %p, attachment %p.\n", iface
, Caps
, Surface
);
479 EnterCriticalSection(&ddraw_cs
);
481 if(This
->version
< 7)
483 /* Earlier dx apps put garbage into these members, clear them */
484 our_caps
.dwCaps
= Caps
->dwCaps
;
485 our_caps
.dwCaps2
= 0;
486 our_caps
.dwCaps3
= 0;
487 our_caps
.dwCaps4
= 0;
494 TRACE("(%p): Looking for caps: %x,%x,%x,%x\n", This
, our_caps
.dwCaps
, our_caps
.dwCaps2
, our_caps
.dwCaps3
, our_caps
.dwCaps4
); /* FIXME: Better debugging */
496 for(i
= 0; i
< MAX_COMPLEX_ATTACHED
; i
++)
498 surf
= This
->complex_array
[i
];
503 TRACE("Surface: (%p) caps: %x,%x,%x,%x\n", surf
,
504 surf
->surface_desc
.ddsCaps
.dwCaps
,
505 surf
->surface_desc
.ddsCaps
.dwCaps2
,
506 surf
->surface_desc
.ddsCaps
.dwCaps3
,
507 surf
->surface_desc
.ddsCaps
.dwCaps4
);
510 if (((surf
->surface_desc
.ddsCaps
.dwCaps
& our_caps
.dwCaps
) == our_caps
.dwCaps
) &&
511 ((surf
->surface_desc
.ddsCaps
.dwCaps2
& our_caps
.dwCaps2
) == our_caps
.dwCaps2
)) {
513 /* MSDN: "This method fails if more than one surface is attached
514 * that matches the capabilities requested."
516 * Not sure how to test this.
519 TRACE("(%p): Returning surface %p\n", This
, surf
);
520 TRACE("(%p): mipmapcount=%d\n", This
, surf
->mipmap_level
);
521 *Surface
= &surf
->IDirectDrawSurface7_iface
;
522 ddraw_surface7_AddRef(*Surface
);
523 LeaveCriticalSection(&ddraw_cs
);
528 /* Next, look at the attachment chain */
531 while( (surf
= surf
->next_attached
) )
535 TRACE("Surface: (%p) caps: %x,%x,%x,%x\n", surf
,
536 surf
->surface_desc
.ddsCaps
.dwCaps
,
537 surf
->surface_desc
.ddsCaps
.dwCaps2
,
538 surf
->surface_desc
.ddsCaps
.dwCaps3
,
539 surf
->surface_desc
.ddsCaps
.dwCaps4
);
542 if (((surf
->surface_desc
.ddsCaps
.dwCaps
& our_caps
.dwCaps
) == our_caps
.dwCaps
) &&
543 ((surf
->surface_desc
.ddsCaps
.dwCaps2
& our_caps
.dwCaps2
) == our_caps
.dwCaps2
)) {
545 TRACE("(%p): Returning surface %p\n", This
, surf
);
546 *Surface
= &surf
->IDirectDrawSurface7_iface
;
547 ddraw_surface7_AddRef(*Surface
);
548 LeaveCriticalSection(&ddraw_cs
);
553 TRACE("(%p) Didn't find a valid surface\n", This
);
554 LeaveCriticalSection(&ddraw_cs
);
557 return DDERR_NOTFOUND
;
560 static HRESULT WINAPI
ddraw_surface3_GetAttachedSurface(IDirectDrawSurface3
*iface
,
561 DDSCAPS
*caps
, IDirectDrawSurface3
**attachment
)
563 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface3(iface
);
564 IDirectDrawSurface7
*attachment7
;
565 IDirectDrawSurfaceImpl
*attachment_impl
;
569 TRACE("iface %p, caps %p, attachment %p.\n", iface
, caps
, attachment
);
571 caps2
.dwCaps
= caps
->dwCaps
;
576 hr
= ddraw_surface7_GetAttachedSurface(&This
->IDirectDrawSurface7_iface
,
577 &caps2
, &attachment7
);
583 attachment_impl
= impl_from_IDirectDrawSurface7(attachment7
);
584 *attachment
= &attachment_impl
->IDirectDrawSurface3_iface
;
589 /*****************************************************************************
590 * IDirectDrawSurface7::Lock
592 * Locks the surface and returns a pointer to the surface's memory
595 * Rect: Rectangle to lock. If NULL, the whole surface is locked
596 * DDSD: Pointer to a DDSURFACEDESC2 which shall receive the surface's desc.
597 * Flags: Locking flags, e.g Read only or write only
598 * h: An event handle that's not used and must be NULL
602 * DDERR_INVALIDPARAMS if DDSD is NULL
603 * For more details, see IWineD3DSurface::LockRect
605 *****************************************************************************/
606 static HRESULT WINAPI
ddraw_surface7_Lock(IDirectDrawSurface7
*iface
,
607 RECT
*Rect
, DDSURFACEDESC2
*DDSD
, DWORD Flags
, HANDLE h
)
609 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(iface
);
610 WINED3DLOCKED_RECT LockedRect
;
613 TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
614 iface
, wine_dbgstr_rect(Rect
), DDSD
, Flags
, h
);
617 return DDERR_INVALIDPARAMS
;
619 /* This->surface_desc.dwWidth and dwHeight are changeable, thus lock */
620 EnterCriticalSection(&ddraw_cs
);
622 /* Should I check for the handle to be NULL?
624 * The DDLOCK flags and the D3DLOCK flags are equal
625 * for the supported values. The others are ignored by WineD3D
628 if(DDSD
->dwSize
!= sizeof(DDSURFACEDESC
) &&
629 DDSD
->dwSize
!= sizeof(DDSURFACEDESC2
))
631 WARN("Invalid structure size %d, returning DDERR_INVALIDPARAMS\n", DDERR_INVALIDPARAMS
);
632 LeaveCriticalSection(&ddraw_cs
);
633 return DDERR_INVALIDPARAMS
;
636 /* Windows zeroes this if the rect is invalid */
643 || (Rect
->left
> Rect
->right
)
644 || (Rect
->top
> Rect
->bottom
)
645 || (Rect
->right
> This
->surface_desc
.dwWidth
)
646 || (Rect
->bottom
> This
->surface_desc
.dwHeight
))
648 WARN("Trying to lock an invalid rectangle, returning DDERR_INVALIDPARAMS\n");
649 LeaveCriticalSection(&ddraw_cs
);
650 return DDERR_INVALIDPARAMS
;
654 hr
= wined3d_surface_map(This
->wined3d_surface
, &LockedRect
, Rect
, Flags
);
657 LeaveCriticalSection(&ddraw_cs
);
660 /* D3D8 and D3D9 return the general D3DERR_INVALIDCALL error, but ddraw has a more
661 * specific error. But since IWineD3DSurface::LockRect returns that error in this
662 * only occasion, keep d3d8 and d3d9 free from the return value override. There are
663 * many different places where d3d8/9 would have to catch the DDERR_SURFACEBUSY, it
664 * is much easier to do it in one place in ddraw
666 case WINED3DERR_INVALIDCALL
: return DDERR_SURFACEBUSY
;
671 /* Override the memory area. The pitch should be set already. Strangely windows
672 * does not set the LPSURFACE flag on locked surfaces !?!.
673 * DDSD->dwFlags |= DDSD_LPSURFACE;
675 This
->surface_desc
.lpSurface
= LockedRect
.pBits
;
676 DD_STRUCT_COPY_BYSIZE(DDSD
,&(This
->surface_desc
));
678 TRACE("locked surface returning description :\n");
679 if (TRACE_ON(ddraw
)) DDRAW_dump_surface_desc(DDSD
);
681 LeaveCriticalSection(&ddraw_cs
);
685 static HRESULT WINAPI
ddraw_surface3_Lock(IDirectDrawSurface3
*iface
, RECT
*rect
,
686 DDSURFACEDESC
*surface_desc
, DWORD flags
, HANDLE h
)
688 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface3(iface
);
689 TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
690 iface
, wine_dbgstr_rect(rect
), surface_desc
, flags
, h
);
692 return ddraw_surface7_Lock(&This
->IDirectDrawSurface7_iface
,
693 rect
, (DDSURFACEDESC2
*)surface_desc
, flags
, h
);
696 /*****************************************************************************
697 * IDirectDrawSurface7::Unlock
699 * Unlocks an locked surface
702 * Rect: Not used by this implementation
706 * For more details, see IWineD3DSurface::UnlockRect
708 *****************************************************************************/
709 static HRESULT WINAPI
ddraw_surface7_Unlock(IDirectDrawSurface7
*iface
, RECT
*pRect
)
711 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(iface
);
714 TRACE("iface %p, rect %s.\n", iface
, wine_dbgstr_rect(pRect
));
716 EnterCriticalSection(&ddraw_cs
);
717 hr
= wined3d_surface_unmap(This
->wined3d_surface
);
720 This
->surface_desc
.lpSurface
= NULL
;
722 LeaveCriticalSection(&ddraw_cs
);
726 static HRESULT WINAPI
ddraw_surface3_Unlock(IDirectDrawSurface3
*iface
, void *data
)
728 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface3(iface
);
729 TRACE("iface %p, data %p.\n", iface
, data
);
731 /* data might not be the LPRECT of later versions, so drop it. */
732 return ddraw_surface7_Unlock(&This
->IDirectDrawSurface7_iface
, NULL
);
735 /*****************************************************************************
736 * IDirectDrawSurface7::Flip
738 * Flips a surface with the DDSCAPS_FLIP flag. The flip is relayed to
739 * IWineD3DSurface::Flip. Because WineD3D doesn't handle attached surfaces,
740 * the flip target is passed to WineD3D, even if the app didn't specify one
743 * DestOverride: Specifies the surface that will become the new front
744 * buffer. If NULL, the current back buffer is used
745 * Flags: some DirectDraw flags, see include/ddraw.h
749 * DDERR_NOTFLIPPABLE if no flip target could be found
750 * DDERR_INVALIDOBJECT if the surface isn't a front buffer
751 * For more details, see IWineD3DSurface::Flip
753 *****************************************************************************/
754 static HRESULT WINAPI
ddraw_surface7_Flip(IDirectDrawSurface7
*iface
, IDirectDrawSurface7
*DestOverride
, DWORD Flags
)
756 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(iface
);
757 IDirectDrawSurfaceImpl
*Override
= unsafe_impl_from_IDirectDrawSurface7(DestOverride
);
758 IDirectDrawSurface7
*Override7
;
761 TRACE("iface %p, dst %p, flags %#x.\n", iface
, DestOverride
, Flags
);
763 /* Flip has to be called from a front buffer
764 * What about overlay surfaces, AFAIK they can flip too?
766 if( !(This
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_FRONTBUFFER
| DDSCAPS_OVERLAY
)) )
767 return DDERR_INVALIDOBJECT
; /* Unchecked */
769 EnterCriticalSection(&ddraw_cs
);
771 /* WineD3D doesn't keep track of attached surface, so find the target */
776 memset(&Caps
, 0, sizeof(Caps
));
777 Caps
.dwCaps
|= DDSCAPS_BACKBUFFER
;
778 hr
= ddraw_surface7_GetAttachedSurface(iface
, &Caps
, &Override7
);
781 ERR("Can't find a flip target\n");
782 LeaveCriticalSection(&ddraw_cs
);
783 return DDERR_NOTFLIPPABLE
; /* Unchecked */
785 Override
= impl_from_IDirectDrawSurface7(Override7
);
787 /* For the GetAttachedSurface */
788 ddraw_surface7_Release(Override7
);
791 hr
= wined3d_surface_flip(This
->wined3d_surface
, Override
->wined3d_surface
, Flags
);
792 LeaveCriticalSection(&ddraw_cs
);
796 static HRESULT WINAPI
ddraw_surface3_Flip(IDirectDrawSurface3
*iface
, IDirectDrawSurface3
*dst
, DWORD flags
)
798 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface3(iface
);
799 IDirectDrawSurfaceImpl
*dst_impl
= unsafe_impl_from_IDirectDrawSurface3(dst
);
800 TRACE("iface %p, dst %p, flags %#x.\n", iface
, dst
, flags
);
802 return ddraw_surface7_Flip(&This
->IDirectDrawSurface7_iface
,
803 dst_impl
? &dst_impl
->IDirectDrawSurface7_iface
: NULL
, flags
);
806 /*****************************************************************************
807 * IDirectDrawSurface7::Blt
809 * Performs a blit on the surface
812 * DestRect: Destination rectangle, can be NULL
813 * SrcSurface: Source surface, can be NULL
814 * SrcRect: Source rectangle, can be NULL
816 * DDBltFx: Some extended blt parameters, connected to the flags
820 * See IWineD3DSurface::Blt for more details
822 *****************************************************************************/
823 static HRESULT WINAPI
ddraw_surface7_Blt(IDirectDrawSurface7
*iface
, RECT
*DestRect
,
824 IDirectDrawSurface7
*SrcSurface
, RECT
*SrcRect
, DWORD Flags
, DDBLTFX
*DDBltFx
)
826 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(iface
);
827 IDirectDrawSurfaceImpl
*Src
= unsafe_impl_from_IDirectDrawSurface7(SrcSurface
);
830 TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
831 iface
, wine_dbgstr_rect(DestRect
), SrcSurface
, wine_dbgstr_rect(SrcRect
), Flags
, DDBltFx
);
833 /* Check for validity of the flags here. WineD3D Has the software-opengl selection path and would have
834 * to check at 2 places, and sometimes do double checks. This also saves the call to wined3d :-)
836 if((Flags
& DDBLT_KEYSRCOVERRIDE
) && (!DDBltFx
|| Flags
& DDBLT_KEYSRC
)) {
837 WARN("Invalid source color key parameters, returning DDERR_INVALIDPARAMS\n");
838 return DDERR_INVALIDPARAMS
;
841 if((Flags
& DDBLT_KEYDESTOVERRIDE
) && (!DDBltFx
|| Flags
& DDBLT_KEYDEST
)) {
842 WARN("Invalid destination color key parameters, returning DDERR_INVALIDPARAMS\n");
843 return DDERR_INVALIDPARAMS
;
846 /* Sizes can change, therefore hold the lock when testing the rectangles */
847 EnterCriticalSection(&ddraw_cs
);
850 if(DestRect
->top
>= DestRect
->bottom
|| DestRect
->left
>= DestRect
->right
||
851 DestRect
->right
> This
->surface_desc
.dwWidth
||
852 DestRect
->bottom
> This
->surface_desc
.dwHeight
)
854 WARN("Destination rectangle is invalid, returning DDERR_INVALIDRECT\n");
855 LeaveCriticalSection(&ddraw_cs
);
856 return DDERR_INVALIDRECT
;
861 if(SrcRect
->top
>= SrcRect
->bottom
|| SrcRect
->left
>=SrcRect
->right
||
862 SrcRect
->right
> Src
->surface_desc
.dwWidth
||
863 SrcRect
->bottom
> Src
->surface_desc
.dwHeight
)
865 WARN("Source rectangle is invalid, returning DDERR_INVALIDRECT\n");
866 LeaveCriticalSection(&ddraw_cs
);
867 return DDERR_INVALIDRECT
;
871 if(Flags
& DDBLT_KEYSRC
&& (!Src
|| !(Src
->surface_desc
.dwFlags
& DDSD_CKSRCBLT
))) {
872 WARN("DDBLT_KEYDEST blit without color key in surface, returning DDERR_INVALIDPARAMS\n");
873 LeaveCriticalSection(&ddraw_cs
);
874 return DDERR_INVALIDPARAMS
;
877 /* TODO: Check if the DDBltFx contains any ddraw surface pointers. If it
878 * does, copy the struct, and replace the ddraw surfaces with the wined3d
879 * surfaces. So far no blitting operations using surfaces in the bltfx
880 * struct are supported anyway. */
881 hr
= wined3d_surface_blt(This
->wined3d_surface
, DestRect
, Src
? Src
->wined3d_surface
: NULL
,
882 SrcRect
, Flags
, (WINEDDBLTFX
*)DDBltFx
, WINED3DTEXF_LINEAR
);
884 LeaveCriticalSection(&ddraw_cs
);
887 case WINED3DERR_NOTAVAILABLE
: return DDERR_UNSUPPORTED
;
888 case WINED3DERR_WRONGTEXTUREFORMAT
: return DDERR_INVALIDPIXELFORMAT
;
893 static HRESULT WINAPI
ddraw_surface3_Blt(IDirectDrawSurface3
*iface
, RECT
*dst_rect
,
894 IDirectDrawSurface3
*src_surface
, RECT
*src_rect
, DWORD flags
, DDBLTFX
*fx
)
896 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface3(iface
);
897 IDirectDrawSurfaceImpl
*src_impl
= unsafe_impl_from_IDirectDrawSurface3(src_surface
);
898 TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
899 iface
, wine_dbgstr_rect(dst_rect
), src_surface
, wine_dbgstr_rect(src_rect
), flags
, fx
);
901 return ddraw_surface7_Blt(&This
->IDirectDrawSurface7_iface
, dst_rect
,
902 src_impl
? &src_impl
->IDirectDrawSurface7_iface
: NULL
, src_rect
, flags
, fx
);
905 /*****************************************************************************
906 * IDirectDrawSurface7::AddAttachedSurface
908 * Attaches a surface to another surface. How the surface attachments work
909 * is not totally understood yet, and this method is prone to problems.
910 * he surface that is attached is AddRef-ed.
912 * Tests with complex surfaces suggest that the surface attachments form a
913 * tree, but no method to test this has been found yet.
915 * The attachment list consists of a first surface (first_attached) and
916 * for each surface a pointer to the next attached surface (next_attached).
917 * For the first surface, and a surface that has no attachments
918 * first_attached points to the surface itself. A surface that has
919 * no successors in the chain has next_attached set to NULL.
921 * Newly attached surfaces are attached right after the root surface.
922 * If a surface is attached to a complex surface compound, it's attached to
923 * the surface that the app requested, not the complex root. See
924 * GetAttachedSurface for a description how surfaces are found.
926 * This is how the current implementation works, and it was coded by looking
927 * at the needs of the applications.
929 * So far only Z-Buffer attachments are tested, and they are activated in
930 * WineD3D. Mipmaps could be tricky to activate in WineD3D.
931 * Back buffers should work in 2D mode, but they are not tested(They can be
932 * attached in older iface versions). Rendering to the front buffer and
933 * switching between that and double buffering is not yet implemented in
934 * WineD3D, so for 3D it might have unexpected results.
936 * ddraw_surface_attach_surface is the real thing,
937 * ddraw_surface7_AddAttachedSurface is a wrapper around it that
938 * performs additional checks. Version 7 of this interface is much more restrictive
939 * than its predecessors.
942 * Attach: Surface to attach to iface
946 * DDERR_CANNOTATTACHSURFACE if the surface can't be attached for some reason
948 *****************************************************************************/
949 static HRESULT
ddraw_surface_attach_surface(IDirectDrawSurfaceImpl
*This
, IDirectDrawSurfaceImpl
*Surf
)
951 TRACE("surface %p, attachment %p.\n", This
, Surf
);
954 return DDERR_CANNOTATTACHSURFACE
; /* unchecked */
956 EnterCriticalSection(&ddraw_cs
);
958 /* Check if the surface is already attached somewhere */
959 if (Surf
->next_attached
|| Surf
->first_attached
!= Surf
)
961 /* TODO: Test for the structure of the manual attachment. Is it a
962 * chain or a list? What happens if one surface is attached to 2
963 * different surfaces? */
964 WARN("Surface %p is already attached somewhere. next_attached %p, first_attached %p.\n",
965 Surf
, Surf
->next_attached
, Surf
->first_attached
);
967 LeaveCriticalSection(&ddraw_cs
);
968 return DDERR_SURFACEALREADYATTACHED
;
971 /* This inserts the new surface at the 2nd position in the chain, right after the root surface */
972 Surf
->next_attached
= This
->next_attached
;
973 Surf
->first_attached
= This
->first_attached
;
974 This
->next_attached
= Surf
;
976 /* Check if the WineD3D depth stencil needs updating */
977 if(This
->ddraw
->d3ddevice
)
979 IDirect3DDeviceImpl_UpdateDepthStencil(This
->ddraw
->d3ddevice
);
982 ddraw_surface7_AddRef(&Surf
->IDirectDrawSurface7_iface
);
983 LeaveCriticalSection(&ddraw_cs
);
987 static HRESULT WINAPI
ddraw_surface7_AddAttachedSurface(IDirectDrawSurface7
*iface
, IDirectDrawSurface7
*Attach
)
989 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(iface
);
990 IDirectDrawSurfaceImpl
*Surf
= unsafe_impl_from_IDirectDrawSurface7(Attach
);
992 TRACE("iface %p, attachment %p.\n", iface
, Attach
);
994 /* Version 7 of this interface seems to refuse everything except z buffers, as per msdn */
995 if(!(Surf
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_ZBUFFER
))
998 WARN("Application tries to attach a non Z buffer surface. caps %08x\n",
999 Surf
->surface_desc
.ddsCaps
.dwCaps
);
1000 return DDERR_CANNOTATTACHSURFACE
;
1003 return ddraw_surface_attach_surface(This
, Surf
);
1006 static HRESULT WINAPI
ddraw_surface3_AddAttachedSurface(IDirectDrawSurface3
*iface
, IDirectDrawSurface3
*attachment
)
1008 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface3(iface
);
1009 IDirectDrawSurfaceImpl
*attach_impl
= unsafe_impl_from_IDirectDrawSurface3(attachment
);
1011 TRACE("iface %p, attachment %p.\n", iface
, attachment
);
1013 /* Tests suggest that
1014 * -> offscreen plain surfaces can be attached to other offscreen plain surfaces
1015 * -> offscreen plain surfaces can be attached to primaries
1016 * -> primaries can be attached to offscreen plain surfaces
1017 * -> z buffers can be attached to primaries */
1018 if (This
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_PRIMARYSURFACE
| DDSCAPS_OFFSCREENPLAIN
)
1019 && attach_impl
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_PRIMARYSURFACE
| DDSCAPS_OFFSCREENPLAIN
))
1021 /* Sizes have to match */
1022 if (attach_impl
->surface_desc
.dwWidth
!= This
->surface_desc
.dwWidth
1023 || attach_impl
->surface_desc
.dwHeight
!= This
->surface_desc
.dwHeight
)
1025 WARN("Surface sizes do not match.\n");
1026 return DDERR_CANNOTATTACHSURFACE
;
1030 else if (This
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_PRIMARYSURFACE
| DDSCAPS_3DDEVICE
)
1031 && attach_impl
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_ZBUFFER
))
1037 WARN("Invalid attachment combination.\n");
1038 return DDERR_CANNOTATTACHSURFACE
;
1041 return ddraw_surface_attach_surface(This
, attach_impl
);
1044 /*****************************************************************************
1045 * IDirectDrawSurface7::DeleteAttachedSurface
1047 * Removes a surface from the attachment chain. The surface's refcount
1048 * is decreased by one after it has been removed
1051 * Flags: Some flags, not used by this implementation
1052 * Attach: Surface to detach
1056 * DDERR_SURFACENOTATTACHED if the surface isn't attached to
1058 *****************************************************************************/
1059 static HRESULT WINAPI
ddraw_surface7_DeleteAttachedSurface(IDirectDrawSurface7
*iface
,
1060 DWORD Flags
, IDirectDrawSurface7
*Attach
)
1062 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(iface
);
1063 IDirectDrawSurfaceImpl
*Surf
= unsafe_impl_from_IDirectDrawSurface7(Attach
);
1064 IDirectDrawSurfaceImpl
*Prev
= This
;
1066 TRACE("iface %p, flags %#x, attachment %p.\n", iface
, Flags
, Attach
);
1068 EnterCriticalSection(&ddraw_cs
);
1069 if (!Surf
|| (Surf
->first_attached
!= This
) || (Surf
== This
) )
1071 LeaveCriticalSection(&ddraw_cs
);
1072 return DDERR_CANNOTDETACHSURFACE
;
1075 /* Remove MIPMAPSUBLEVEL if this seemed to be one */
1076 if (This
->surface_desc
.ddsCaps
.dwCaps
&
1077 Surf
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_MIPMAP
)
1079 Surf
->surface_desc
.ddsCaps
.dwCaps2
&= ~DDSCAPS2_MIPMAPSUBLEVEL
;
1080 /* FIXME: we should probably also subtract from dwMipMapCount of this
1081 * and all parent surfaces */
1084 /* Find the predecessor of the detached surface */
1087 if(Prev
->next_attached
== Surf
) break;
1088 Prev
= Prev
->next_attached
;
1091 /* There must be a surface, otherwise there's a bug */
1092 assert(Prev
!= NULL
);
1094 /* Unchain the surface */
1095 Prev
->next_attached
= Surf
->next_attached
;
1096 Surf
->next_attached
= NULL
;
1097 Surf
->first_attached
= Surf
;
1099 /* Check if the WineD3D depth stencil needs updating */
1100 if(This
->ddraw
->d3ddevice
)
1102 IDirect3DDeviceImpl_UpdateDepthStencil(This
->ddraw
->d3ddevice
);
1105 ddraw_surface7_Release(Attach
);
1106 LeaveCriticalSection(&ddraw_cs
);
1110 static HRESULT WINAPI
ddraw_surface3_DeleteAttachedSurface(IDirectDrawSurface3
*iface
,
1111 DWORD flags
, IDirectDrawSurface3
*attachment
)
1113 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface3(iface
);
1114 IDirectDrawSurfaceImpl
*attachment_impl
= unsafe_impl_from_IDirectDrawSurface3(attachment
);
1115 TRACE("iface %p, flags %#x, attachment %p.\n", iface
, flags
, attachment
);
1117 return ddraw_surface7_DeleteAttachedSurface(&This
->IDirectDrawSurface7_iface
, flags
,
1118 attachment_impl
? &attachment_impl
->IDirectDrawSurface7_iface
: NULL
);
1121 /*****************************************************************************
1122 * IDirectDrawSurface7::AddOverlayDirtyRect
1124 * "This method is not currently implemented"
1132 *****************************************************************************/
1133 static HRESULT WINAPI
ddraw_surface7_AddOverlayDirtyRect(IDirectDrawSurface7
*iface
, RECT
*Rect
)
1135 TRACE("iface %p, rect %s.\n", iface
, wine_dbgstr_rect(Rect
));
1137 return DDERR_UNSUPPORTED
; /* unchecked */
1140 static HRESULT WINAPI
ddraw_surface3_AddOverlayDirtyRect(IDirectDrawSurface3
*iface
, RECT
*rect
)
1142 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface3(iface
);
1143 TRACE("iface %p, rect %s.\n", iface
, wine_dbgstr_rect(rect
));
1145 return ddraw_surface7_AddOverlayDirtyRect(&This
->IDirectDrawSurface7_iface
, rect
);
1148 /*****************************************************************************
1149 * IDirectDrawSurface7::GetDC
1151 * Returns a GDI device context for the surface
1154 * hdc: Address of a HDC variable to store the dc to
1158 * DDERR_INVALIDPARAMS if hdc is NULL
1159 * For details, see IWineD3DSurface::GetDC
1161 *****************************************************************************/
1162 static HRESULT WINAPI
ddraw_surface7_GetDC(IDirectDrawSurface7
*iface
, HDC
*hdc
)
1164 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(iface
);
1167 TRACE("iface %p, dc %p.\n", iface
, hdc
);
1170 return DDERR_INVALIDPARAMS
;
1172 EnterCriticalSection(&ddraw_cs
);
1173 hr
= wined3d_surface_getdc(This
->wined3d_surface
, hdc
);
1174 LeaveCriticalSection(&ddraw_cs
);
1177 /* Some, but not all errors set *hdc to NULL. E.g. DCALREADYCREATED does not
1180 case WINED3DERR_INVALIDCALL
:
1181 if(hdc
) *hdc
= NULL
;
1182 return DDERR_INVALIDPARAMS
;
1188 static HRESULT WINAPI
ddraw_surface3_GetDC(IDirectDrawSurface3
*iface
, HDC
*dc
)
1190 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface3(iface
);
1191 TRACE("iface %p, dc %p.\n", iface
, dc
);
1193 return ddraw_surface7_GetDC(&This
->IDirectDrawSurface7_iface
, dc
);
1196 /*****************************************************************************
1197 * IDirectDrawSurface7::ReleaseDC
1199 * Releases the DC that was constructed with GetDC
1202 * hdc: HDC to release
1206 * For more details, see IWineD3DSurface::ReleaseDC
1208 *****************************************************************************/
1209 static HRESULT WINAPI
ddraw_surface7_ReleaseDC(IDirectDrawSurface7
*iface
, HDC hdc
)
1211 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(iface
);
1214 TRACE("iface %p, dc %p.\n", iface
, hdc
);
1216 EnterCriticalSection(&ddraw_cs
);
1217 hr
= wined3d_surface_releasedc(This
->wined3d_surface
, hdc
);
1218 LeaveCriticalSection(&ddraw_cs
);
1222 static HRESULT WINAPI
ddraw_surface3_ReleaseDC(IDirectDrawSurface3
*iface
, HDC dc
)
1224 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface3(iface
);
1225 TRACE("iface %p, dc %p.\n", iface
, dc
);
1227 return ddraw_surface7_ReleaseDC(&This
->IDirectDrawSurface7_iface
, dc
);
1230 /*****************************************************************************
1231 * IDirectDrawSurface7::GetCaps
1233 * Returns the surface's caps
1236 * Caps: Address to write the caps to
1240 * DDERR_INVALIDPARAMS if Caps is NULL
1242 *****************************************************************************/
1243 static HRESULT WINAPI
ddraw_surface7_GetCaps(IDirectDrawSurface7
*iface
, DDSCAPS2
*Caps
)
1245 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(iface
);
1247 TRACE("iface %p, caps %p.\n", iface
, Caps
);
1250 return DDERR_INVALIDPARAMS
;
1252 *Caps
= This
->surface_desc
.ddsCaps
;
1256 static HRESULT WINAPI
ddraw_surface3_GetCaps(IDirectDrawSurface3
*iface
, DDSCAPS
*caps
)
1258 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface3(iface
);
1262 TRACE("iface %p, caps %p.\n", iface
, caps
);
1264 hr
= ddraw_surface7_GetCaps(&This
->IDirectDrawSurface7_iface
, &caps2
);
1265 if (FAILED(hr
)) return hr
;
1267 caps
->dwCaps
= caps2
.dwCaps
;
1271 /*****************************************************************************
1272 * IDirectDrawSurface7::SetPriority
1274 * Sets a texture priority for managed textures.
1277 * Priority: The new priority
1281 * For more details, see IWineD3DSurface::SetPriority
1283 *****************************************************************************/
1284 static HRESULT WINAPI
ddraw_surface7_SetPriority(IDirectDrawSurface7
*iface
, DWORD Priority
)
1286 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(iface
);
1289 TRACE("iface %p, priority %u.\n", iface
, Priority
);
1291 EnterCriticalSection(&ddraw_cs
);
1292 hr
= wined3d_surface_set_priority(This
->wined3d_surface
, Priority
);
1293 LeaveCriticalSection(&ddraw_cs
);
1297 /*****************************************************************************
1298 * IDirectDrawSurface7::GetPriority
1300 * Returns the surface's priority
1303 * Priority: Address of a variable to write the priority to
1307 * DDERR_INVALIDPARAMS if Priority == NULL
1308 * For more details, see IWineD3DSurface::GetPriority
1310 *****************************************************************************/
1311 static HRESULT WINAPI
ddraw_surface7_GetPriority(IDirectDrawSurface7
*iface
, DWORD
*Priority
)
1313 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(iface
);
1315 TRACE("iface %p, priority %p.\n", iface
, Priority
);
1319 return DDERR_INVALIDPARAMS
;
1322 EnterCriticalSection(&ddraw_cs
);
1323 *Priority
= wined3d_surface_get_priority(This
->wined3d_surface
);
1324 LeaveCriticalSection(&ddraw_cs
);
1328 /*****************************************************************************
1329 * IDirectDrawSurface7::SetPrivateData
1331 * Stores some data in the surface that is intended for the application's
1335 * tag: GUID that identifies the data
1336 * Data: Pointer to the private data
1337 * Size: Size of the private data
1342 * For more details, see IWineD3DSurface::SetPrivateData
1344 *****************************************************************************/
1345 static HRESULT WINAPI
ddraw_surface7_SetPrivateData(IDirectDrawSurface7
*iface
,
1346 REFGUID tag
, void *Data
, DWORD Size
, DWORD Flags
)
1348 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(iface
);
1351 TRACE("iface %p, tag %s, data %p, data_size %u, flags %#x.\n",
1352 iface
, debugstr_guid(tag
), Data
, Size
, Flags
);
1354 EnterCriticalSection(&ddraw_cs
);
1355 hr
= wined3d_surface_set_private_data(This
->wined3d_surface
, tag
, Data
, Size
, Flags
);
1356 LeaveCriticalSection(&ddraw_cs
);
1359 case WINED3DERR_INVALIDCALL
: return DDERR_INVALIDPARAMS
;
1364 /*****************************************************************************
1365 * IDirectDrawSurface7::GetPrivateData
1367 * Returns the private data set with IDirectDrawSurface7::SetPrivateData
1370 * tag: GUID of the data to return
1371 * Data: Address where to write the data to
1372 * Size: Size of the buffer at Data
1376 * DDERR_INVALIDPARAMS if Data is NULL
1377 * For more details, see IWineD3DSurface::GetPrivateData
1379 *****************************************************************************/
1380 static HRESULT WINAPI
ddraw_surface7_GetPrivateData(IDirectDrawSurface7
*iface
, REFGUID tag
, void *Data
, DWORD
*Size
)
1382 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(iface
);
1385 TRACE("iface %p, tag %s, data %p, data_size %p.\n",
1386 iface
, debugstr_guid(tag
), Data
, Size
);
1389 return DDERR_INVALIDPARAMS
;
1391 EnterCriticalSection(&ddraw_cs
);
1392 hr
= wined3d_surface_get_private_data(This
->wined3d_surface
, tag
, Data
, Size
);
1393 LeaveCriticalSection(&ddraw_cs
);
1397 /*****************************************************************************
1398 * IDirectDrawSurface7::FreePrivateData
1400 * Frees private data stored in the surface
1403 * tag: Tag of the data to free
1407 * For more details, see IWineD3DSurface::FreePrivateData
1409 *****************************************************************************/
1410 static HRESULT WINAPI
ddraw_surface7_FreePrivateData(IDirectDrawSurface7
*iface
, REFGUID tag
)
1412 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(iface
);
1415 TRACE("iface %p, tag %s.\n", iface
, debugstr_guid(tag
));
1417 EnterCriticalSection(&ddraw_cs
);
1418 hr
= wined3d_surface_free_private_data(This
->wined3d_surface
, tag
);
1419 LeaveCriticalSection(&ddraw_cs
);
1423 /*****************************************************************************
1424 * IDirectDrawSurface7::PageLock
1426 * Prevents a sysmem surface from being paged out
1429 * Flags: Not used, must be 0(unchecked)
1432 * DD_OK, because it's a stub
1434 *****************************************************************************/
1435 static HRESULT WINAPI
ddraw_surface7_PageLock(IDirectDrawSurface7
*iface
, DWORD Flags
)
1437 TRACE("iface %p, flags %#x.\n", iface
, Flags
);
1439 /* This is Windows memory management related - we don't need this */
1443 static HRESULT WINAPI
ddraw_surface3_PageLock(IDirectDrawSurface3
*iface
, DWORD flags
)
1445 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface3(iface
);
1446 TRACE("iface %p, flags %#x.\n", iface
, flags
);
1448 return ddraw_surface7_PageLock(&This
->IDirectDrawSurface7_iface
, flags
);
1451 /*****************************************************************************
1452 * IDirectDrawSurface7::PageUnlock
1454 * Allows a sysmem surface to be paged out
1457 * Flags: Not used, must be 0(unchecked)
1460 * DD_OK, because it's a stub
1462 *****************************************************************************/
1463 static HRESULT WINAPI
ddraw_surface7_PageUnlock(IDirectDrawSurface7
*iface
, DWORD Flags
)
1465 TRACE("iface %p, flags %#x.\n", iface
, Flags
);
1470 static HRESULT WINAPI
ddraw_surface3_PageUnlock(IDirectDrawSurface3
*iface
, DWORD flags
)
1472 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface3(iface
);
1473 TRACE("iface %p, flags %#x.\n", iface
, flags
);
1475 return ddraw_surface7_PageUnlock(&This
->IDirectDrawSurface7_iface
, flags
);
1478 /*****************************************************************************
1479 * IDirectDrawSurface7::BltBatch
1481 * An unimplemented function
1489 *****************************************************************************/
1490 static HRESULT WINAPI
ddraw_surface7_BltBatch(IDirectDrawSurface7
*iface
, DDBLTBATCH
*Batch
, DWORD Count
, DWORD Flags
)
1492 TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface
, Batch
, Count
, Flags
);
1494 /* MSDN: "not currently implemented" */
1495 return DDERR_UNSUPPORTED
;
1498 static HRESULT WINAPI
ddraw_surface3_BltBatch(IDirectDrawSurface3
*iface
, DDBLTBATCH
*batch
, DWORD count
, DWORD flags
)
1500 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface3(iface
);
1501 TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface
, batch
, count
, flags
);
1503 return ddraw_surface7_BltBatch(&This
->IDirectDrawSurface7_iface
, batch
, count
, flags
);
1506 /*****************************************************************************
1507 * IDirectDrawSurface7::EnumAttachedSurfaces
1509 * Enumerates all surfaces attached to this surface
1512 * context: Pointer to pass unmodified to the callback
1513 * cb: Callback function to call for each surface
1517 * DDERR_INVALIDPARAMS if cb is NULL
1519 *****************************************************************************/
1520 static HRESULT WINAPI
ddraw_surface7_EnumAttachedSurfaces(IDirectDrawSurface7
*iface
,
1521 void *context
, LPDDENUMSURFACESCALLBACK7 cb
)
1523 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(iface
);
1524 IDirectDrawSurfaceImpl
*surf
;
1525 DDSURFACEDESC2 desc
;
1528 /* Attached surfaces aren't handled in WineD3D */
1529 TRACE("iface %p, context %p, callback %p.\n", iface
, context
, cb
);
1532 return DDERR_INVALIDPARAMS
;
1534 EnterCriticalSection(&ddraw_cs
);
1535 for(i
= 0; i
< MAX_COMPLEX_ATTACHED
; i
++)
1537 surf
= This
->complex_array
[i
];
1540 ddraw_surface7_AddRef(&surf
->IDirectDrawSurface7_iface
);
1541 desc
= surf
->surface_desc
;
1542 /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
1543 if (cb(&surf
->IDirectDrawSurface7_iface
, &desc
, context
) == DDENUMRET_CANCEL
)
1545 LeaveCriticalSection(&ddraw_cs
);
1550 for (surf
= This
->next_attached
; surf
!= NULL
; surf
= surf
->next_attached
)
1552 ddraw_surface7_AddRef(&surf
->IDirectDrawSurface7_iface
);
1553 desc
= surf
->surface_desc
;
1554 /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
1555 if (cb(&surf
->IDirectDrawSurface7_iface
, &desc
, context
) == DDENUMRET_CANCEL
)
1557 LeaveCriticalSection(&ddraw_cs
);
1562 TRACE(" end of enumeration.\n");
1564 LeaveCriticalSection(&ddraw_cs
);
1568 struct callback_info
1570 LPDDENUMSURFACESCALLBACK callback
;
1574 static HRESULT CALLBACK
EnumCallback(IDirectDrawSurface7
*surface
, DDSURFACEDESC2
*surface_desc
, void *context
)
1576 IDirectDrawSurfaceImpl
*surface_impl
= impl_from_IDirectDrawSurface7(surface
);
1577 const struct callback_info
*info
= context
;
1579 return info
->callback((IDirectDrawSurface
*)&surface_impl
->IDirectDrawSurface3_iface
,
1580 (DDSURFACEDESC
*)surface_desc
, info
->context
);
1583 static HRESULT WINAPI
ddraw_surface3_EnumAttachedSurfaces(IDirectDrawSurface3
*iface
,
1584 void *context
, LPDDENUMSURFACESCALLBACK callback
)
1586 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface3(iface
);
1587 struct callback_info info
;
1589 TRACE("iface %p, context %p, callback %p.\n", iface
, context
, callback
);
1591 info
.callback
= callback
;
1592 info
.context
= context
;
1594 return ddraw_surface7_EnumAttachedSurfaces(&This
->IDirectDrawSurface7_iface
,
1595 &info
, EnumCallback
);
1598 /*****************************************************************************
1599 * IDirectDrawSurface7::EnumOverlayZOrders
1601 * "Enumerates the overlay surfaces on the specified destination"
1604 * Flags: DDENUMOVERLAYZ_BACKTOFRONT or DDENUMOVERLAYZ_FRONTTOBACK
1605 * context: context to pass back to the callback
1606 * cb: callback function to call for each enumerated surface
1609 * DD_OK, because it's a stub
1611 *****************************************************************************/
1612 static HRESULT WINAPI
ddraw_surface7_EnumOverlayZOrders(IDirectDrawSurface7
*iface
,
1613 DWORD Flags
, void *context
, LPDDENUMSURFACESCALLBACK7 cb
)
1615 FIXME("iface %p, flags %#x, context %p, callback %p stub!\n", iface
, Flags
, context
, cb
);
1620 static HRESULT WINAPI
ddraw_surface3_EnumOverlayZOrders(IDirectDrawSurface3
*iface
,
1621 DWORD flags
, void *context
, LPDDENUMSURFACESCALLBACK callback
)
1623 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface3(iface
);
1624 struct callback_info info
;
1626 TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface
, flags
, context
, callback
);
1628 info
.callback
= callback
;
1629 info
.context
= context
;
1631 return ddraw_surface7_EnumOverlayZOrders(&This
->IDirectDrawSurface7_iface
,
1632 flags
, &info
, EnumCallback
);
1635 /*****************************************************************************
1636 * IDirectDrawSurface7::GetBltStatus
1638 * Returns the blitting status
1641 * Flags: DDGBS_CANBLT or DDGBS_ISBLTDONE
1644 * See IWineD3DSurface::Blt
1646 *****************************************************************************/
1647 static HRESULT WINAPI
ddraw_surface7_GetBltStatus(IDirectDrawSurface7
*iface
, DWORD Flags
)
1649 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(iface
);
1652 TRACE("iface %p, flags %#x.\n", iface
, Flags
);
1654 EnterCriticalSection(&ddraw_cs
);
1655 hr
= wined3d_surface_get_blt_status(This
->wined3d_surface
, Flags
);
1656 LeaveCriticalSection(&ddraw_cs
);
1659 case WINED3DERR_INVALIDCALL
: return DDERR_INVALIDPARAMS
;
1664 static HRESULT WINAPI
ddraw_surface3_GetBltStatus(IDirectDrawSurface3
*iface
, DWORD flags
)
1666 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface3(iface
);
1667 TRACE("iface %p, flags %#x.\n", iface
, flags
);
1669 return ddraw_surface7_GetBltStatus(&This
->IDirectDrawSurface7_iface
, flags
);
1672 /*****************************************************************************
1673 * IDirectDrawSurface7::GetColorKey
1675 * Returns the color key assigned to the surface
1679 * CKey: Address to store the key to
1683 * DDERR_INVALIDPARAMS if CKey is NULL
1685 *****************************************************************************/
1686 static HRESULT WINAPI
ddraw_surface7_GetColorKey(IDirectDrawSurface7
*iface
, DWORD Flags
, DDCOLORKEY
*CKey
)
1688 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(iface
);
1690 TRACE("iface %p, flags %#x, color_key %p.\n", iface
, Flags
, CKey
);
1693 return DDERR_INVALIDPARAMS
;
1695 EnterCriticalSection(&ddraw_cs
);
1699 case DDCKEY_DESTBLT
:
1700 if (!(This
->surface_desc
.dwFlags
& DDSD_CKDESTBLT
))
1702 LeaveCriticalSection(&ddraw_cs
);
1703 return DDERR_NOCOLORKEY
;
1705 *CKey
= This
->surface_desc
.ddckCKDestBlt
;
1708 case DDCKEY_DESTOVERLAY
:
1709 if (!(This
->surface_desc
.dwFlags
& DDSD_CKDESTOVERLAY
))
1711 LeaveCriticalSection(&ddraw_cs
);
1712 return DDERR_NOCOLORKEY
;
1714 *CKey
= This
->surface_desc
.u3
.ddckCKDestOverlay
;
1718 if (!(This
->surface_desc
.dwFlags
& DDSD_CKSRCBLT
))
1720 LeaveCriticalSection(&ddraw_cs
);
1721 return DDERR_NOCOLORKEY
;
1723 *CKey
= This
->surface_desc
.ddckCKSrcBlt
;
1726 case DDCKEY_SRCOVERLAY
:
1727 if (!(This
->surface_desc
.dwFlags
& DDSD_CKSRCOVERLAY
))
1729 LeaveCriticalSection(&ddraw_cs
);
1730 return DDERR_NOCOLORKEY
;
1732 *CKey
= This
->surface_desc
.ddckCKSrcOverlay
;
1736 LeaveCriticalSection(&ddraw_cs
);
1737 return DDERR_INVALIDPARAMS
;
1740 LeaveCriticalSection(&ddraw_cs
);
1744 static HRESULT WINAPI
ddraw_surface3_GetColorKey(IDirectDrawSurface3
*iface
, DWORD flags
, DDCOLORKEY
*color_key
)
1746 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface3(iface
);
1747 TRACE("iface %p, flags %#x, color_key %p.\n", iface
, flags
, color_key
);
1749 return ddraw_surface7_GetColorKey(&This
->IDirectDrawSurface7_iface
, flags
, color_key
);
1752 /*****************************************************************************
1753 * IDirectDrawSurface7::GetFlipStatus
1755 * Returns the flipping status of the surface
1758 * Flags: DDGFS_CANFLIP of DDGFS_ISFLIPDONE
1761 * See IWineD3DSurface::GetFlipStatus
1763 *****************************************************************************/
1764 static HRESULT WINAPI
ddraw_surface7_GetFlipStatus(IDirectDrawSurface7
*iface
, DWORD Flags
)
1766 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(iface
);
1769 TRACE("iface %p, flags %#x.\n", iface
, Flags
);
1771 EnterCriticalSection(&ddraw_cs
);
1772 hr
= wined3d_surface_get_flip_status(This
->wined3d_surface
, Flags
);
1773 LeaveCriticalSection(&ddraw_cs
);
1776 case WINED3DERR_INVALIDCALL
: return DDERR_INVALIDPARAMS
;
1781 static HRESULT WINAPI
ddraw_surface3_GetFlipStatus(IDirectDrawSurface3
*iface
, DWORD flags
)
1783 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface3(iface
);
1784 TRACE("iface %p, flags %#x.\n", iface
, flags
);
1786 return ddraw_surface7_GetFlipStatus(&This
->IDirectDrawSurface7_iface
, flags
);
1789 /*****************************************************************************
1790 * IDirectDrawSurface7::GetOverlayPosition
1792 * Returns the display coordinates of a visible and active overlay surface
1799 * DDERR_NOTAOVERLAYSURFACE, because it's a stub
1800 *****************************************************************************/
1801 static HRESULT WINAPI
ddraw_surface7_GetOverlayPosition(IDirectDrawSurface7
*iface
, LONG
*X
, LONG
*Y
)
1803 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(iface
);
1806 TRACE("iface %p, x %p, y %p.\n", iface
, X
, Y
);
1808 EnterCriticalSection(&ddraw_cs
);
1809 hr
= wined3d_surface_get_overlay_position(This
->wined3d_surface
, X
, Y
);
1810 LeaveCriticalSection(&ddraw_cs
);
1814 static HRESULT WINAPI
ddraw_surface3_GetOverlayPosition(IDirectDrawSurface3
*iface
, LONG
*x
, LONG
*y
)
1816 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface3(iface
);
1817 TRACE("iface %p, x %p, y %p.\n", iface
, x
, y
);
1819 return ddraw_surface7_GetOverlayPosition(&This
->IDirectDrawSurface7_iface
, x
, y
);
1822 /*****************************************************************************
1823 * IDirectDrawSurface7::GetPixelFormat
1825 * Returns the pixel format of the Surface
1828 * PixelFormat: Pointer to a DDPIXELFORMAT structure to which the pixel
1829 * format should be written
1833 * DDERR_INVALIDPARAMS if PixelFormat is NULL
1835 *****************************************************************************/
1836 static HRESULT WINAPI
ddraw_surface7_GetPixelFormat(IDirectDrawSurface7
*iface
, DDPIXELFORMAT
*PixelFormat
)
1838 /* What is DDERR_INVALIDSURFACETYPE for here? */
1839 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(iface
);
1841 TRACE("iface %p, pixel_format %p.\n", iface
, PixelFormat
);
1844 return DDERR_INVALIDPARAMS
;
1846 EnterCriticalSection(&ddraw_cs
);
1847 DD_STRUCT_COPY_BYSIZE(PixelFormat
,&This
->surface_desc
.u4
.ddpfPixelFormat
);
1848 LeaveCriticalSection(&ddraw_cs
);
1853 static HRESULT WINAPI
ddraw_surface3_GetPixelFormat(IDirectDrawSurface3
*iface
, DDPIXELFORMAT
*pixel_format
)
1855 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface3(iface
);
1856 TRACE("iface %p, pixel_format %p.\n", iface
, pixel_format
);
1858 return ddraw_surface7_GetPixelFormat(&This
->IDirectDrawSurface7_iface
, pixel_format
);
1861 /*****************************************************************************
1862 * IDirectDrawSurface7::GetSurfaceDesc
1864 * Returns the description of this surface
1867 * DDSD: Address of a DDSURFACEDESC2 structure that is to be filled with the
1872 * DDERR_INVALIDPARAMS if DDSD is NULL
1874 *****************************************************************************/
1875 static HRESULT WINAPI
ddraw_surface7_GetSurfaceDesc(IDirectDrawSurface7
*iface
, DDSURFACEDESC2
*DDSD
)
1877 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(iface
);
1879 TRACE("iface %p, surface_desc %p.\n", iface
, DDSD
);
1882 return DDERR_INVALIDPARAMS
;
1884 if (DDSD
->dwSize
!= sizeof(DDSURFACEDESC2
))
1886 WARN("Incorrect struct size %d, returning DDERR_INVALIDPARAMS\n",DDSD
->dwSize
);
1887 return DDERR_INVALIDPARAMS
;
1890 EnterCriticalSection(&ddraw_cs
);
1891 DD_STRUCT_COPY_BYSIZE(DDSD
,&This
->surface_desc
);
1892 TRACE("Returning surface desc:\n");
1893 if (TRACE_ON(ddraw
)) DDRAW_dump_surface_desc(DDSD
);
1895 LeaveCriticalSection(&ddraw_cs
);
1899 static HRESULT WINAPI
ddraw_surface3_GetSurfaceDesc(IDirectDrawSurface3
*iface
, DDSURFACEDESC
*surface_desc
)
1901 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface3(iface
);
1903 TRACE("iface %p, surface_desc %p.\n", iface
, surface_desc
);
1905 if (!surface_desc
) return DDERR_INVALIDPARAMS
;
1907 if (surface_desc
->dwSize
!= sizeof(DDSURFACEDESC
))
1909 WARN("Incorrect structure size %u, returning DDERR_INVALIDPARAMS.\n", surface_desc
->dwSize
);
1910 return DDERR_INVALIDPARAMS
;
1913 EnterCriticalSection(&ddraw_cs
);
1914 DD_STRUCT_COPY_BYSIZE(surface_desc
, (DDSURFACEDESC
*)&This
->surface_desc
);
1915 TRACE("Returning surface desc:\n");
1916 if (TRACE_ON(ddraw
))
1918 /* DDRAW_dump_surface_desc handles the smaller size */
1919 DDRAW_dump_surface_desc((DDSURFACEDESC2
*)surface_desc
);
1922 LeaveCriticalSection(&ddraw_cs
);
1926 /*****************************************************************************
1927 * IDirectDrawSurface7::Initialize
1929 * Initializes the surface. This is a no-op in Wine
1932 * DD: Pointer to an DirectDraw interface
1933 * DDSD: Surface description for initialization
1936 * DDERR_ALREADYINITIALIZED
1938 *****************************************************************************/
1939 static HRESULT WINAPI
ddraw_surface7_Initialize(IDirectDrawSurface7
*iface
,
1940 IDirectDraw
*ddraw
, DDSURFACEDESC2
*surface_desc
)
1942 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface
, ddraw
, surface_desc
);
1944 return DDERR_ALREADYINITIALIZED
;
1947 static HRESULT WINAPI
ddraw_surface3_Initialize(IDirectDrawSurface3
*iface
,
1948 IDirectDraw
*ddraw
, DDSURFACEDESC
*surface_desc
)
1950 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface3(iface
);
1951 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface
, ddraw
, surface_desc
);
1953 return ddraw_surface7_Initialize(&This
->IDirectDrawSurface7_iface
,
1954 ddraw
, (DDSURFACEDESC2
*)surface_desc
);
1957 /*****************************************************************************
1958 * IDirect3DTexture1::Initialize
1960 * The sdk says it's not implemented
1968 *****************************************************************************/
1969 static HRESULT WINAPI
d3d_texture1_Initialize(IDirect3DTexture
*iface
,
1970 IDirect3DDevice
*device
, IDirectDrawSurface
*surface
)
1972 TRACE("iface %p, device %p, surface %p.\n", iface
, device
, surface
);
1974 return DDERR_UNSUPPORTED
; /* Unchecked */
1977 /*****************************************************************************
1978 * IDirectDrawSurface7::IsLost
1980 * Checks if the surface is lost
1983 * DD_OK, if the surface is usable
1984 * DDERR_ISLOST if the surface is lost
1985 * See IWineD3DSurface::IsLost for more details
1987 *****************************************************************************/
1988 static HRESULT WINAPI
ddraw_surface7_IsLost(IDirectDrawSurface7
*iface
)
1990 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(iface
);
1993 TRACE("iface %p.\n", iface
);
1995 EnterCriticalSection(&ddraw_cs
);
1996 /* We lose the surface if the implementation was changed */
1997 if(This
->ImplType
!= This
->ddraw
->ImplType
)
1999 /* But this shouldn't happen. When we change the implementation,
2000 * all surfaces are re-created automatically, and their content
2003 ERR(" (%p) Implementation was changed from %d to %d\n", This
, This
->ImplType
, This
->ddraw
->ImplType
);
2004 LeaveCriticalSection(&ddraw_cs
);
2005 return DDERR_SURFACELOST
;
2008 hr
= wined3d_surface_is_lost(This
->wined3d_surface
);
2009 LeaveCriticalSection(&ddraw_cs
);
2012 /* D3D8 and 9 loose full devices, thus there's only a DEVICELOST error.
2013 * WineD3D uses the same error for surfaces
2015 case WINED3DERR_DEVICELOST
: return DDERR_SURFACELOST
;
2020 static HRESULT WINAPI
ddraw_surface3_IsLost(IDirectDrawSurface3
*iface
)
2022 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface3(iface
);
2023 TRACE("iface %p.\n", iface
);
2025 return ddraw_surface7_IsLost(&This
->IDirectDrawSurface7_iface
);
2028 /*****************************************************************************
2029 * IDirectDrawSurface7::Restore
2031 * Restores a lost surface. This makes the surface usable again, but
2032 * doesn't reload its old contents
2036 * See IWineD3DSurface::Restore for more details
2038 *****************************************************************************/
2039 static HRESULT WINAPI
ddraw_surface7_Restore(IDirectDrawSurface7
*iface
)
2041 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(iface
);
2044 TRACE("iface %p.\n", iface
);
2046 EnterCriticalSection(&ddraw_cs
);
2047 if(This
->ImplType
!= This
->ddraw
->ImplType
)
2049 /* Call the recreation callback. Make sure to AddRef first */
2050 IDirectDrawSurface_AddRef(iface
);
2051 ddraw_recreate_surfaces_cb(iface
, &This
->surface_desc
, NULL
/* Not needed */);
2053 hr
= wined3d_surface_restore(This
->wined3d_surface
);
2054 LeaveCriticalSection(&ddraw_cs
);
2058 static HRESULT WINAPI
ddraw_surface3_Restore(IDirectDrawSurface3
*iface
)
2060 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface3(iface
);
2061 TRACE("iface %p.\n", iface
);
2063 return ddraw_surface7_Restore(&This
->IDirectDrawSurface7_iface
);
2066 /*****************************************************************************
2067 * IDirectDrawSurface7::SetOverlayPosition
2069 * Changes the display coordinates of an overlay surface
2076 * DDERR_NOTAOVERLAYSURFACE, because we don't support overlays right now
2077 *****************************************************************************/
2078 static HRESULT WINAPI
ddraw_surface7_SetOverlayPosition(IDirectDrawSurface7
*iface
, LONG X
, LONG Y
)
2080 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(iface
);
2083 TRACE("iface %p, x %d, y %d.\n", iface
, X
, Y
);
2085 EnterCriticalSection(&ddraw_cs
);
2086 hr
= wined3d_surface_set_overlay_position(This
->wined3d_surface
, X
, Y
);
2087 LeaveCriticalSection(&ddraw_cs
);
2091 static HRESULT WINAPI
ddraw_surface3_SetOverlayPosition(IDirectDrawSurface3
*iface
, LONG x
, LONG y
)
2093 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface3(iface
);
2094 TRACE("iface %p, x %d, y %d.\n", iface
, x
, y
);
2096 return ddraw_surface7_SetOverlayPosition(&This
->IDirectDrawSurface7_iface
, x
, y
);
2099 /*****************************************************************************
2100 * IDirectDrawSurface7::UpdateOverlay
2102 * Modifies the attributes of an overlay surface.
2105 * SrcRect: The section of the source being used for the overlay
2106 * DstSurface: Address of the surface that is overlaid
2107 * DstRect: Place of the overlay
2108 * Flags: some DDOVER_* flags
2111 * DDERR_UNSUPPORTED, because we don't support overlays
2113 *****************************************************************************/
2114 static HRESULT WINAPI
ddraw_surface7_UpdateOverlay(IDirectDrawSurface7
*iface
, RECT
*SrcRect
,
2115 IDirectDrawSurface7
*DstSurface
, RECT
*DstRect
, DWORD Flags
, DDOVERLAYFX
*FX
)
2117 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(iface
);
2118 IDirectDrawSurfaceImpl
*Dst
= unsafe_impl_from_IDirectDrawSurface7(DstSurface
);
2121 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
2122 iface
, wine_dbgstr_rect(SrcRect
), DstSurface
, wine_dbgstr_rect(DstRect
), Flags
, FX
);
2124 EnterCriticalSection(&ddraw_cs
);
2125 hr
= wined3d_surface_update_overlay(This
->wined3d_surface
, SrcRect
,
2126 Dst
? Dst
->wined3d_surface
: NULL
, DstRect
, Flags
, (WINEDDOVERLAYFX
*)FX
);
2127 LeaveCriticalSection(&ddraw_cs
);
2129 case WINED3DERR_INVALIDCALL
: return DDERR_INVALIDPARAMS
;
2130 case WINEDDERR_NOTAOVERLAYSURFACE
: return DDERR_NOTAOVERLAYSURFACE
;
2131 case WINEDDERR_OVERLAYNOTVISIBLE
: return DDERR_OVERLAYNOTVISIBLE
;
2137 static HRESULT WINAPI
ddraw_surface3_UpdateOverlay(IDirectDrawSurface3
*iface
, RECT
*src_rect
,
2138 IDirectDrawSurface3
*dst_surface
, RECT
*dst_rect
, DWORD flags
, DDOVERLAYFX
*fx
)
2140 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface3(iface
);
2141 IDirectDrawSurfaceImpl
*dst_impl
= unsafe_impl_from_IDirectDrawSurface3(dst_surface
);
2142 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
2143 iface
, wine_dbgstr_rect(src_rect
), dst_surface
, wine_dbgstr_rect(dst_rect
), flags
, fx
);
2145 return ddraw_surface7_UpdateOverlay(&This
->IDirectDrawSurface7_iface
, src_rect
,
2146 dst_impl
? &dst_impl
->IDirectDrawSurface7_iface
: NULL
, dst_rect
, flags
, fx
);
2149 /*****************************************************************************
2150 * IDirectDrawSurface7::UpdateOverlayDisplay
2152 * The DX7 sdk says that it's not implemented
2157 * Returns: DDERR_UNSUPPORTED, because we don't support overlays
2159 *****************************************************************************/
2160 static HRESULT WINAPI
ddraw_surface7_UpdateOverlayDisplay(IDirectDrawSurface7
*iface
, DWORD Flags
)
2162 TRACE("iface %p, flags %#x.\n", iface
, Flags
);
2164 return DDERR_UNSUPPORTED
;
2167 static HRESULT WINAPI
ddraw_surface3_UpdateOverlayDisplay(IDirectDrawSurface3
*iface
, DWORD flags
)
2169 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface3(iface
);
2170 TRACE("iface %p, flags %#x.\n", iface
, flags
);
2172 return ddraw_surface7_UpdateOverlayDisplay(&This
->IDirectDrawSurface7_iface
, flags
);
2175 /*****************************************************************************
2176 * IDirectDrawSurface7::UpdateOverlayZOrder
2178 * Sets an overlay's Z order
2181 * Flags: DDOVERZ_* flags
2182 * DDSRef: Defines the relative position in the overlay chain
2185 * DDERR_NOTOVERLAYSURFACE, because we don't support overlays
2187 *****************************************************************************/
2188 static HRESULT WINAPI
ddraw_surface7_UpdateOverlayZOrder(IDirectDrawSurface7
*iface
,
2189 DWORD Flags
, IDirectDrawSurface7
*DDSRef
)
2191 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(iface
);
2192 IDirectDrawSurfaceImpl
*Ref
= unsafe_impl_from_IDirectDrawSurface7(DDSRef
);
2195 TRACE("iface %p, flags %#x, reference %p.\n", iface
, Flags
, DDSRef
);
2197 EnterCriticalSection(&ddraw_cs
);
2198 hr
= wined3d_surface_update_overlay_z_order(This
->wined3d_surface
,
2199 Flags
, Ref
? Ref
->wined3d_surface
: NULL
);
2200 LeaveCriticalSection(&ddraw_cs
);
2204 static HRESULT WINAPI
ddraw_surface3_UpdateOverlayZOrder(IDirectDrawSurface3
*iface
,
2205 DWORD flags
, IDirectDrawSurface3
*reference
)
2207 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface3(iface
);
2208 IDirectDrawSurfaceImpl
*reference_impl
= unsafe_impl_from_IDirectDrawSurface3(reference
);
2209 TRACE("iface %p, flags %#x, reference %p.\n", iface
, flags
, reference
);
2211 return ddraw_surface7_UpdateOverlayZOrder(&This
->IDirectDrawSurface7_iface
, flags
,
2212 reference_impl
? &reference_impl
->IDirectDrawSurface7_iface
: NULL
);
2215 /*****************************************************************************
2216 * IDirectDrawSurface7::GetDDInterface
2218 * Returns the IDirectDraw7 interface pointer of the DirectDraw object this
2219 * surface belongs to
2222 * DD: Address to write the interface pointer to
2226 * DDERR_INVALIDPARAMS if DD is NULL
2228 *****************************************************************************/
2229 static HRESULT WINAPI
ddraw_surface7_GetDDInterface(IDirectDrawSurface7
*iface
, void **DD
)
2231 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(iface
);
2233 TRACE("iface %p, ddraw %p.\n", iface
, DD
);
2236 return DDERR_INVALIDPARAMS
;
2238 switch(This
->version
)
2241 *DD
= &This
->ddraw
->IDirectDraw7_iface
;
2245 *DD
= &This
->ddraw
->IDirectDraw4_iface
;
2249 *DD
= &This
->ddraw
->IDirectDraw2_iface
;
2253 *DD
= &This
->ddraw
->IDirectDraw_iface
;
2257 IUnknown_AddRef((IUnknown
*)*DD
);
2262 static HRESULT WINAPI
ddraw_surface3_GetDDInterface(IDirectDrawSurface3
*iface
, void **ddraw
)
2264 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface3(iface
);
2265 TRACE("iface %p, ddraw %p.\n", iface
, ddraw
);
2267 return ddraw_surface7_GetDDInterface(&This
->IDirectDrawSurface7_iface
, ddraw
);
2270 /* This seems also windows implementation specific - I don't think WineD3D needs this */
2271 static HRESULT WINAPI
ddraw_surface7_ChangeUniquenessValue(IDirectDrawSurface7
*iface
)
2273 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(iface
);
2274 volatile IDirectDrawSurfaceImpl
* vThis
= This
;
2276 TRACE("iface %p.\n", iface
);
2278 EnterCriticalSection(&ddraw_cs
);
2279 /* A uniqueness value of 0 is apparently special.
2280 * This needs to be checked.
2281 * TODO: Write tests for this code and check if the volatile, interlocked stuff is really needed
2284 DWORD old_uniqueness_value
= vThis
->uniqueness_value
;
2285 DWORD new_uniqueness_value
= old_uniqueness_value
+1;
2287 if (old_uniqueness_value
== 0) break;
2288 if (new_uniqueness_value
== 0) new_uniqueness_value
= 1;
2290 if (InterlockedCompareExchange((LONG
*)&vThis
->uniqueness_value
,
2291 old_uniqueness_value
,
2292 new_uniqueness_value
)
2293 == old_uniqueness_value
)
2297 LeaveCriticalSection(&ddraw_cs
);
2301 static HRESULT WINAPI
ddraw_surface7_GetUniquenessValue(IDirectDrawSurface7
*iface
, DWORD
*pValue
)
2303 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(iface
);
2305 TRACE("iface %p, value %p.\n", iface
, pValue
);
2307 EnterCriticalSection(&ddraw_cs
);
2308 *pValue
= This
->uniqueness_value
;
2309 LeaveCriticalSection(&ddraw_cs
);
2313 /*****************************************************************************
2314 * IDirectDrawSurface7::SetLOD
2316 * Sets the level of detail of a texture
2319 * MaxLOD: LOD to set
2323 * DDERR_INVALIDOBJECT if the surface is invalid for this method
2325 *****************************************************************************/
2326 static HRESULT WINAPI
ddraw_surface7_SetLOD(IDirectDrawSurface7
*iface
, DWORD MaxLOD
)
2328 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(iface
);
2331 TRACE("iface %p, lod %u.\n", iface
, MaxLOD
);
2333 EnterCriticalSection(&ddraw_cs
);
2334 if (!(This
->surface_desc
.ddsCaps
.dwCaps2
& DDSCAPS2_TEXTUREMANAGE
))
2336 LeaveCriticalSection(&ddraw_cs
);
2337 return DDERR_INVALIDOBJECT
;
2340 if (!This
->wined3d_texture
)
2342 ERR("(%p) The DirectDraw texture has no WineD3DTexture!\n", This
);
2343 LeaveCriticalSection(&ddraw_cs
);
2344 return DDERR_INVALIDOBJECT
;
2347 hr
= wined3d_texture_set_lod(This
->wined3d_texture
, MaxLOD
);
2348 LeaveCriticalSection(&ddraw_cs
);
2352 /*****************************************************************************
2353 * IDirectDrawSurface7::GetLOD
2355 * Returns the level of detail of a Direct3D texture
2358 * MaxLOD: Address to write the LOD to
2362 * DDERR_INVALIDPARAMS if MaxLOD is NULL
2363 * DDERR_INVALIDOBJECT if the surface is invalid for this method
2365 *****************************************************************************/
2366 static HRESULT WINAPI
ddraw_surface7_GetLOD(IDirectDrawSurface7
*iface
, DWORD
*MaxLOD
)
2368 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(iface
);
2370 TRACE("iface %p, lod %p.\n", iface
, MaxLOD
);
2373 return DDERR_INVALIDPARAMS
;
2375 EnterCriticalSection(&ddraw_cs
);
2376 if (!(This
->surface_desc
.ddsCaps
.dwCaps2
& DDSCAPS2_TEXTUREMANAGE
))
2378 LeaveCriticalSection(&ddraw_cs
);
2379 return DDERR_INVALIDOBJECT
;
2382 *MaxLOD
= wined3d_texture_get_lod(This
->wined3d_texture
);
2383 LeaveCriticalSection(&ddraw_cs
);
2387 /*****************************************************************************
2388 * IDirectDrawSurface7::BltFast
2390 * Performs a fast Blit.
2393 * dstx: The x coordinate to blit to on the destination
2394 * dsty: The y coordinate to blit to on the destination
2395 * Source: The source surface
2396 * rsrc: The source rectangle
2397 * trans: Type of transfer. Some DDBLTFAST_* flags
2401 * For more details, see IWineD3DSurface::BltFast
2403 *****************************************************************************/
2404 static HRESULT WINAPI
ddraw_surface7_BltFast(IDirectDrawSurface7
*iface
, DWORD dstx
, DWORD dsty
,
2405 IDirectDrawSurface7
*Source
, RECT
*rsrc
, DWORD trans
)
2407 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(iface
);
2408 IDirectDrawSurfaceImpl
*src
= unsafe_impl_from_IDirectDrawSurface7(Source
);
2409 DWORD src_w
, src_h
, dst_w
, dst_h
;
2412 TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
2413 iface
, dstx
, dsty
, Source
, wine_dbgstr_rect(rsrc
), trans
);
2415 dst_w
= This
->surface_desc
.dwWidth
;
2416 dst_h
= This
->surface_desc
.dwHeight
;
2418 /* Source must be != NULL, This is not checked by windows. Windows happily throws a 0xc0000005
2423 if(rsrc
->top
> rsrc
->bottom
|| rsrc
->left
> rsrc
->right
||
2424 rsrc
->right
> src
->surface_desc
.dwWidth
||
2425 rsrc
->bottom
> src
->surface_desc
.dwHeight
)
2427 WARN("Source rectangle is invalid, returning DDERR_INVALIDRECT\n");
2428 return DDERR_INVALIDRECT
;
2431 src_w
= rsrc
->right
- rsrc
->left
;
2432 src_h
= rsrc
->bottom
- rsrc
->top
;
2436 src_w
= src
->surface_desc
.dwWidth
;
2437 src_h
= src
->surface_desc
.dwHeight
;
2440 if (src_w
> dst_w
|| dstx
> dst_w
- src_w
2441 || src_h
> dst_h
|| dsty
> dst_h
- src_h
)
2443 WARN("Destination area out of bounds, returning DDERR_INVALIDRECT.\n");
2444 return DDERR_INVALIDRECT
;
2447 EnterCriticalSection(&ddraw_cs
);
2448 hr
= wined3d_surface_bltfast(This
->wined3d_surface
, dstx
, dsty
,
2449 src
? src
->wined3d_surface
: NULL
, rsrc
, trans
);
2450 LeaveCriticalSection(&ddraw_cs
);
2453 case WINED3DERR_NOTAVAILABLE
: return DDERR_UNSUPPORTED
;
2454 case WINED3DERR_WRONGTEXTUREFORMAT
: return DDERR_INVALIDPIXELFORMAT
;
2459 static HRESULT WINAPI
ddraw_surface3_BltFast(IDirectDrawSurface3
*iface
, DWORD dst_x
, DWORD dst_y
,
2460 IDirectDrawSurface3
*src_surface
, RECT
*src_rect
, DWORD flags
)
2462 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface3(iface
);
2463 IDirectDrawSurfaceImpl
*src_impl
= unsafe_impl_from_IDirectDrawSurface3(src_surface
);
2464 TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
2465 iface
, dst_x
, dst_y
, src_surface
, wine_dbgstr_rect(src_rect
), flags
);
2467 return ddraw_surface7_BltFast(&This
->IDirectDrawSurface7_iface
, dst_x
, dst_y
,
2468 src_impl
? &src_impl
->IDirectDrawSurface7_iface
: NULL
, src_rect
, flags
);
2471 /*****************************************************************************
2472 * IDirectDrawSurface7::GetClipper
2474 * Returns the IDirectDrawClipper interface of the clipper assigned to this
2478 * Clipper: Address to store the interface pointer at
2482 * DDERR_INVALIDPARAMS if Clipper is NULL
2483 * DDERR_NOCLIPPERATTACHED if there's no clipper attached
2485 *****************************************************************************/
2486 static HRESULT WINAPI
ddraw_surface7_GetClipper(IDirectDrawSurface7
*iface
, IDirectDrawClipper
**Clipper
)
2488 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(iface
);
2490 TRACE("iface %p, clipper %p.\n", iface
, Clipper
);
2494 LeaveCriticalSection(&ddraw_cs
);
2495 return DDERR_INVALIDPARAMS
;
2498 EnterCriticalSection(&ddraw_cs
);
2499 if(This
->clipper
== NULL
)
2501 LeaveCriticalSection(&ddraw_cs
);
2502 return DDERR_NOCLIPPERATTACHED
;
2505 *Clipper
= (IDirectDrawClipper
*)This
->clipper
;
2506 IDirectDrawClipper_AddRef(*Clipper
);
2507 LeaveCriticalSection(&ddraw_cs
);
2511 static HRESULT WINAPI
ddraw_surface3_GetClipper(IDirectDrawSurface3
*iface
, IDirectDrawClipper
**clipper
)
2513 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface3(iface
);
2514 TRACE("iface %p, clipper %p.\n", iface
, clipper
);
2516 return ddraw_surface7_GetClipper(&This
->IDirectDrawSurface7_iface
, clipper
);
2519 /*****************************************************************************
2520 * IDirectDrawSurface7::SetClipper
2522 * Sets a clipper for the surface
2525 * Clipper: IDirectDrawClipper interface of the clipper to set
2530 *****************************************************************************/
2531 static HRESULT WINAPI
ddraw_surface7_SetClipper(IDirectDrawSurface7
*iface
, IDirectDrawClipper
*Clipper
)
2533 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(iface
);
2534 IDirectDrawClipperImpl
*oldClipper
= This
->clipper
;
2538 TRACE("iface %p, clipper %p.\n", iface
, Clipper
);
2540 EnterCriticalSection(&ddraw_cs
);
2541 if ((IDirectDrawClipperImpl
*)Clipper
== This
->clipper
)
2543 LeaveCriticalSection(&ddraw_cs
);
2547 This
->clipper
= (IDirectDrawClipperImpl
*)Clipper
;
2549 if (Clipper
!= NULL
)
2550 IDirectDrawClipper_AddRef(Clipper
);
2552 IDirectDrawClipper_Release((IDirectDrawClipper
*)oldClipper
);
2554 hr
= wined3d_surface_set_clipper(This
->wined3d_surface
,
2555 This
->clipper
? This
->clipper
->wineD3DClipper
: NULL
);
2557 if (This
->wined3d_swapchain
)
2561 IDirectDrawClipper_GetHWnd(Clipper
, &clipWindow
);
2565 wined3d_swapchain_set_window(This
->wined3d_swapchain
, clipWindow
);
2567 wined3d_swapchain_set_window(This
->wined3d_swapchain
, This
->ddraw
->d3d_window
);
2570 LeaveCriticalSection(&ddraw_cs
);
2574 static HRESULT WINAPI
ddraw_surface3_SetClipper(IDirectDrawSurface3
*iface
, IDirectDrawClipper
*clipper
)
2576 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface3(iface
);
2577 TRACE("iface %p, clipper %p.\n", iface
, clipper
);
2579 return ddraw_surface7_SetClipper(&This
->IDirectDrawSurface7_iface
, clipper
);
2582 /*****************************************************************************
2583 * IDirectDrawSurface7::SetSurfaceDesc
2585 * Sets the surface description. It can override the pixel format, the surface
2587 * It's not really tested.
2590 * DDSD: Pointer to the new surface description to set
2595 * DDERR_INVALIDPARAMS if DDSD is NULL
2597 *****************************************************************************/
2598 static HRESULT WINAPI
ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7
*iface
, DDSURFACEDESC2
*DDSD
, DWORD Flags
)
2600 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(iface
);
2601 enum wined3d_format_id newFormat
= WINED3DFMT_UNKNOWN
;
2604 TRACE("iface %p, surface_desc %p, flags %#x.\n", iface
, DDSD
, Flags
);
2607 return DDERR_INVALIDPARAMS
;
2609 EnterCriticalSection(&ddraw_cs
);
2610 if (DDSD
->dwFlags
& DDSD_PIXELFORMAT
)
2612 newFormat
= PixelFormat_DD2WineD3D(&DDSD
->u4
.ddpfPixelFormat
);
2614 if(newFormat
== WINED3DFMT_UNKNOWN
)
2616 ERR("Requested to set an unknown pixelformat\n");
2617 LeaveCriticalSection(&ddraw_cs
);
2618 return DDERR_INVALIDPARAMS
;
2620 if(newFormat
!= PixelFormat_DD2WineD3D(&This
->surface_desc
.u4
.ddpfPixelFormat
) )
2622 hr
= wined3d_surface_set_format(This
->wined3d_surface
, newFormat
);
2625 LeaveCriticalSection(&ddraw_cs
);
2630 if (DDSD
->dwFlags
& DDSD_CKDESTOVERLAY
)
2632 wined3d_surface_set_color_key(This
->wined3d_surface
, DDCKEY_DESTOVERLAY
,
2633 (WINEDDCOLORKEY
*)&DDSD
->u3
.ddckCKDestOverlay
);
2635 if (DDSD
->dwFlags
& DDSD_CKDESTBLT
)
2637 wined3d_surface_set_color_key(This
->wined3d_surface
, DDCKEY_DESTBLT
,
2638 (WINEDDCOLORKEY
*)&DDSD
->ddckCKDestBlt
);
2640 if (DDSD
->dwFlags
& DDSD_CKSRCOVERLAY
)
2642 wined3d_surface_set_color_key(This
->wined3d_surface
, DDCKEY_SRCOVERLAY
,
2643 (WINEDDCOLORKEY
*)&DDSD
->ddckCKSrcOverlay
);
2645 if (DDSD
->dwFlags
& DDSD_CKSRCBLT
)
2647 wined3d_surface_set_color_key(This
->wined3d_surface
, DDCKEY_SRCBLT
,
2648 (WINEDDCOLORKEY
*)&DDSD
->ddckCKSrcBlt
);
2650 if (DDSD
->dwFlags
& DDSD_LPSURFACE
&& DDSD
->lpSurface
)
2652 hr
= wined3d_surface_set_mem(This
->wined3d_surface
, DDSD
->lpSurface
);
2655 /* No need for a trace here, wined3d does that for us */
2658 case WINED3DERR_INVALIDCALL
:
2659 LeaveCriticalSection(&ddraw_cs
);
2660 return DDERR_INVALIDPARAMS
;
2667 This
->surface_desc
= *DDSD
;
2669 LeaveCriticalSection(&ddraw_cs
);
2673 static HRESULT WINAPI
ddraw_surface3_SetSurfaceDesc(IDirectDrawSurface3
*iface
,
2674 DDSURFACEDESC
*surface_desc
, DWORD flags
)
2676 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface3(iface
);
2677 TRACE("iface %p, surface_desc %p, flags %#x.\n", iface
, surface_desc
, flags
);
2679 return ddraw_surface7_SetSurfaceDesc(&This
->IDirectDrawSurface7_iface
,
2680 (DDSURFACEDESC2
*)surface_desc
, flags
);
2683 /*****************************************************************************
2684 * IDirectDrawSurface7::GetPalette
2686 * Returns the IDirectDrawPalette interface of the palette currently assigned
2690 * Pal: Address to write the interface pointer to
2694 * DDERR_INVALIDPARAMS if Pal is NULL
2696 *****************************************************************************/
2697 static HRESULT WINAPI
ddraw_surface7_GetPalette(IDirectDrawSurface7
*iface
, IDirectDrawPalette
**Pal
)
2699 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(iface
);
2700 struct wined3d_palette
*wined3d_palette
;
2703 TRACE("iface %p, palette %p.\n", iface
, Pal
);
2706 return DDERR_INVALIDPARAMS
;
2708 EnterCriticalSection(&ddraw_cs
);
2709 wined3d_palette
= wined3d_surface_get_palette(This
->wined3d_surface
);
2710 if (wined3d_palette
)
2712 *Pal
= wined3d_palette_get_parent(wined3d_palette
);
2713 IDirectDrawPalette_AddRef(*Pal
);
2718 hr
= DDERR_NOPALETTEATTACHED
;
2721 LeaveCriticalSection(&ddraw_cs
);
2725 static HRESULT WINAPI
ddraw_surface3_GetPalette(IDirectDrawSurface3
*iface
, IDirectDrawPalette
**palette
)
2727 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface3(iface
);
2728 TRACE("iface %p, palette %p.\n", iface
, palette
);
2730 return ddraw_surface7_GetPalette(&This
->IDirectDrawSurface7_iface
, palette
);
2733 /*****************************************************************************
2736 * EnumAttachedSurface callback for SetColorKey. Used to set color keys
2737 * recursively in the surface tree
2739 *****************************************************************************/
2743 WINEDDCOLORKEY
*CKey
;
2747 static HRESULT WINAPI
2748 SetColorKeyEnum(IDirectDrawSurface7
*surface
,
2749 DDSURFACEDESC2
*desc
,
2752 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(surface
);
2753 struct SCKContext
*ctx
= context
;
2756 hr
= wined3d_surface_set_color_key(This
->wined3d_surface
, ctx
->Flags
, ctx
->CKey
);
2759 WARN("IWineD3DSurface_SetColorKey failed, hr = %08x\n", hr
);
2763 ddraw_surface7_EnumAttachedSurfaces(surface
, context
, SetColorKeyEnum
);
2764 ddraw_surface7_Release(surface
);
2766 return DDENUMRET_OK
;
2769 /*****************************************************************************
2770 * IDirectDrawSurface7::SetColorKey
2772 * Sets the color keying options for the surface. Observations showed that
2773 * in case of complex surfaces the color key has to be assigned to all
2778 * CKey: The new color key
2782 * See IWineD3DSurface::SetColorKey for details
2784 *****************************************************************************/
2785 static HRESULT WINAPI
ddraw_surface7_SetColorKey(IDirectDrawSurface7
*iface
, DWORD Flags
, DDCOLORKEY
*CKey
)
2787 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(iface
);
2788 DDCOLORKEY FixedCKey
;
2789 struct SCKContext ctx
= { DD_OK
, (WINEDDCOLORKEY
*) (CKey
? &FixedCKey
: NULL
), Flags
};
2791 TRACE("iface %p, flags %#x, color_key %p.\n", iface
, Flags
, CKey
);
2793 EnterCriticalSection(&ddraw_cs
);
2797 /* Handle case where dwColorSpaceHighValue < dwColorSpaceLowValue */
2798 if (FixedCKey
.dwColorSpaceHighValue
< FixedCKey
.dwColorSpaceLowValue
)
2799 FixedCKey
.dwColorSpaceHighValue
= FixedCKey
.dwColorSpaceLowValue
;
2801 switch (Flags
& ~DDCKEY_COLORSPACE
)
2803 case DDCKEY_DESTBLT
:
2804 This
->surface_desc
.ddckCKDestBlt
= FixedCKey
;
2805 This
->surface_desc
.dwFlags
|= DDSD_CKDESTBLT
;
2808 case DDCKEY_DESTOVERLAY
:
2809 This
->surface_desc
.u3
.ddckCKDestOverlay
= FixedCKey
;
2810 This
->surface_desc
.dwFlags
|= DDSD_CKDESTOVERLAY
;
2813 case DDCKEY_SRCOVERLAY
:
2814 This
->surface_desc
.ddckCKSrcOverlay
= FixedCKey
;
2815 This
->surface_desc
.dwFlags
|= DDSD_CKSRCOVERLAY
;
2819 This
->surface_desc
.ddckCKSrcBlt
= FixedCKey
;
2820 This
->surface_desc
.dwFlags
|= DDSD_CKSRCBLT
;
2824 LeaveCriticalSection(&ddraw_cs
);
2825 return DDERR_INVALIDPARAMS
;
2830 switch (Flags
& ~DDCKEY_COLORSPACE
)
2832 case DDCKEY_DESTBLT
:
2833 This
->surface_desc
.dwFlags
&= ~DDSD_CKDESTBLT
;
2836 case DDCKEY_DESTOVERLAY
:
2837 This
->surface_desc
.dwFlags
&= ~DDSD_CKDESTOVERLAY
;
2840 case DDCKEY_SRCOVERLAY
:
2841 This
->surface_desc
.dwFlags
&= ~DDSD_CKSRCOVERLAY
;
2845 This
->surface_desc
.dwFlags
&= ~DDSD_CKSRCBLT
;
2849 LeaveCriticalSection(&ddraw_cs
);
2850 return DDERR_INVALIDPARAMS
;
2853 ctx
.ret
= wined3d_surface_set_color_key(This
->wined3d_surface
, Flags
, ctx
.CKey
);
2854 ddraw_surface7_EnumAttachedSurfaces(iface
, &ctx
, SetColorKeyEnum
);
2855 LeaveCriticalSection(&ddraw_cs
);
2858 case WINED3DERR_INVALIDCALL
: return DDERR_INVALIDPARAMS
;
2859 default: return ctx
.ret
;
2863 static HRESULT WINAPI
ddraw_surface3_SetColorKey(IDirectDrawSurface3
*iface
, DWORD flags
, DDCOLORKEY
*color_key
)
2865 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface3(iface
);
2866 TRACE("iface %p, flags %#x, color_key %p.\n", iface
, flags
, color_key
);
2868 return ddraw_surface7_SetColorKey(&This
->IDirectDrawSurface7_iface
, flags
, color_key
);
2871 /*****************************************************************************
2872 * IDirectDrawSurface7::SetPalette
2874 * Assigns a DirectDrawPalette object to the surface
2877 * Pal: Interface to the palette to set
2882 *****************************************************************************/
2883 static HRESULT WINAPI
ddraw_surface7_SetPalette(IDirectDrawSurface7
*iface
, IDirectDrawPalette
*Pal
)
2885 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface7(iface
);
2886 IDirectDrawPalette
*oldPal
;
2887 IDirectDrawSurfaceImpl
*surf
;
2888 IDirectDrawPaletteImpl
*PalImpl
= (IDirectDrawPaletteImpl
*)Pal
;
2891 TRACE("iface %p, palette %p.\n", iface
, Pal
);
2893 if (!(This
->surface_desc
.u4
.ddpfPixelFormat
.dwFlags
& (DDPF_PALETTEINDEXED1
| DDPF_PALETTEINDEXED2
|
2894 DDPF_PALETTEINDEXED4
| DDPF_PALETTEINDEXED8
| DDPF_PALETTEINDEXEDTO8
))) {
2895 return DDERR_INVALIDPIXELFORMAT
;
2898 /* Find the old palette */
2899 EnterCriticalSection(&ddraw_cs
);
2900 hr
= IDirectDrawSurface_GetPalette(iface
, &oldPal
);
2901 if(hr
!= DD_OK
&& hr
!= DDERR_NOPALETTEATTACHED
)
2903 LeaveCriticalSection(&ddraw_cs
);
2906 if(oldPal
) IDirectDrawPalette_Release(oldPal
); /* For the GetPalette */
2908 /* Set the new Palette */
2909 wined3d_surface_set_palette(This
->wined3d_surface
, PalImpl
? PalImpl
->wineD3DPalette
: NULL
);
2910 /* AddRef the Palette */
2911 if(Pal
) IDirectDrawPalette_AddRef(Pal
);
2913 /* Release the old palette */
2914 if(oldPal
) IDirectDrawPalette_Release(oldPal
);
2916 /* If this is a front buffer, also update the back buffers
2917 * TODO: How do things work for palettized cube textures?
2919 if(This
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_FRONTBUFFER
)
2921 /* For primary surfaces the tree is just a list, so the simpler scheme fits too */
2922 DDSCAPS2 caps2
= { DDSCAPS_PRIMARYSURFACE
, 0, 0, 0 };
2927 IDirectDrawSurface7
*attach
;
2929 hr
= ddraw_surface7_GetAttachedSurface(&surf
->IDirectDrawSurface7_iface
, &caps2
, &attach
);
2935 TRACE("Setting palette on %p\n", attach
);
2936 ddraw_surface7_SetPalette(attach
, Pal
);
2937 surf
= impl_from_IDirectDrawSurface7(attach
);
2938 ddraw_surface7_Release(attach
);
2942 LeaveCriticalSection(&ddraw_cs
);
2946 static HRESULT WINAPI
ddraw_surface3_SetPalette(IDirectDrawSurface3
*iface
, IDirectDrawPalette
*palette
)
2948 IDirectDrawSurfaceImpl
*This
= impl_from_IDirectDrawSurface3(iface
);
2949 TRACE("iface %p, palette %p.\n", iface
, palette
);
2951 return ddraw_surface7_SetPalette(&This
->IDirectDrawSurface7_iface
, palette
);
2954 /**********************************************************
2955 * IDirectDrawGammaControl::GetGammaRamp
2957 * Returns the current gamma ramp for a surface
2961 * gamma_ramp: Address to write the ramp to
2965 * DDERR_INVALIDPARAMS if gamma_ramp is NULL
2967 **********************************************************/
2968 static HRESULT WINAPI
ddraw_gamma_control_GetGammaRamp(IDirectDrawGammaControl
*iface
,
2969 DWORD flags
, DDGAMMARAMP
*gamma_ramp
)
2971 IDirectDrawSurfaceImpl
*surface
= surface_from_gamma_control(iface
);
2973 TRACE("iface %p, flags %#x, gamma_ramp %p.\n", iface
, flags
, gamma_ramp
);
2977 WARN("Invalid gamma_ramp passed.\n");
2978 return DDERR_INVALIDPARAMS
;
2981 EnterCriticalSection(&ddraw_cs
);
2982 if (surface
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_PRIMARYSURFACE
)
2984 /* Note: DDGAMMARAMP is compatible with WINED3DGAMMARAMP. */
2985 wined3d_device_get_gamma_ramp(surface
->ddraw
->wined3d_device
, 0, (WINED3DGAMMARAMP
*)gamma_ramp
);
2989 ERR("Not implemented for non-primary surfaces.\n");
2991 LeaveCriticalSection(&ddraw_cs
);
2996 /**********************************************************
2997 * IDirectDrawGammaControl::SetGammaRamp
2999 * Sets the red, green and blue gamma ramps for
3002 * flags: Can be DDSGR_CALIBRATE to request calibration
3003 * gamma_ramp: Structure containing the new gamma ramp
3007 * DDERR_INVALIDPARAMS if gamma_ramp is NULL
3009 **********************************************************/
3010 static HRESULT WINAPI
ddraw_gamma_control_SetGammaRamp(IDirectDrawGammaControl
*iface
,
3011 DWORD flags
, DDGAMMARAMP
*gamma_ramp
)
3013 IDirectDrawSurfaceImpl
*surface
= surface_from_gamma_control(iface
);
3015 TRACE("iface %p, flags %#x, gamma_ramp %p.\n", iface
, flags
, gamma_ramp
);
3019 WARN("Invalid gamma_ramp passed.\n");
3020 return DDERR_INVALIDPARAMS
;
3023 EnterCriticalSection(&ddraw_cs
);
3024 if (surface
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_PRIMARYSURFACE
)
3026 /* Note: DDGAMMARAMP is compatible with WINED3DGAMMARAMP */
3027 wined3d_device_set_gamma_ramp(surface
->ddraw
->wined3d_device
, 0, flags
, (WINED3DGAMMARAMP
*)gamma_ramp
);
3031 ERR("Not implemented for non-primary surfaces.\n");
3033 LeaveCriticalSection(&ddraw_cs
);
3038 /*****************************************************************************
3039 * IDirect3DTexture2::PaletteChanged
3041 * Informs the texture about a palette change
3044 * start: Start index of the change
3045 * count: The number of changed entries
3048 * D3D_OK, because it's a stub
3050 *****************************************************************************/
3051 static HRESULT WINAPI
d3d_texture2_PaletteChanged(IDirect3DTexture2
*iface
, DWORD start
, DWORD count
)
3053 FIXME("iface %p, start %u, count %u stub!\n", iface
, start
, count
);
3058 static HRESULT WINAPI
d3d_texture1_PaletteChanged(IDirect3DTexture
*iface
, DWORD start
, DWORD count
)
3060 IDirectDrawSurfaceImpl
*surface
= surface_from_texture1(iface
);
3062 TRACE("iface %p, start %u, count %u.\n", iface
, start
, count
);
3064 return d3d_texture2_PaletteChanged((IDirect3DTexture2
*)&surface
->IDirect3DTexture2_vtbl
, start
, count
);
3067 /*****************************************************************************
3068 * IDirect3DTexture::Unload
3070 * DX5 SDK: "The IDirect3DTexture2::Unload method is not implemented
3076 *****************************************************************************/
3077 static HRESULT WINAPI
d3d_texture1_Unload(IDirect3DTexture
*iface
)
3079 WARN("iface %p. Not implemented.\n", iface
);
3081 return DDERR_UNSUPPORTED
;
3084 /*****************************************************************************
3085 * IDirect3DTexture2::GetHandle
3087 * Returns handle for the texture. At the moment, the interface
3088 * to the IWineD3DTexture is used.
3091 * device: Device this handle is assigned to
3092 * handle: Address to store the handle at.
3097 *****************************************************************************/
3098 static HRESULT WINAPI
d3d_texture2_GetHandle(IDirect3DTexture2
*iface
,
3099 IDirect3DDevice2
*device
, D3DTEXTUREHANDLE
*handle
)
3101 IDirectDrawSurfaceImpl
*surface
= surface_from_texture2(iface
);
3103 TRACE("iface %p, device %p, handle %p.\n", iface
, device
, handle
);
3105 EnterCriticalSection(&ddraw_cs
);
3107 if (!surface
->Handle
)
3109 DWORD h
= ddraw_allocate_handle(&device_from_device2(device
)->handle_table
, surface
, DDRAW_HANDLE_SURFACE
);
3110 if (h
== DDRAW_INVALID_HANDLE
)
3112 ERR("Failed to allocate a texture handle.\n");
3113 LeaveCriticalSection(&ddraw_cs
);
3114 return DDERR_OUTOFMEMORY
;
3117 surface
->Handle
= h
+ 1;
3120 TRACE("Returning handle %08x.\n", surface
->Handle
);
3121 *handle
= surface
->Handle
;
3123 LeaveCriticalSection(&ddraw_cs
);
3128 static HRESULT WINAPI
d3d_texture1_GetHandle(IDirect3DTexture
*iface
,
3129 IDirect3DDevice
*device
, D3DTEXTUREHANDLE
*handle
)
3131 IDirect3DTexture2
*texture2
= (IDirect3DTexture2
*)&surface_from_texture1(iface
)->IDirect3DTexture2_vtbl
;
3132 IDirect3DDevice2
*device2
= (IDirect3DDevice2
*)&device_from_device1(device
)->IDirect3DDevice2_vtbl
;
3134 TRACE("iface %p, device %p, handle %p.\n", iface
, device
, handle
);
3136 return d3d_texture2_GetHandle(texture2
, device2
, handle
);
3139 /*****************************************************************************
3140 * get_sub_mimaplevel
3142 * Helper function that returns the next mipmap level
3144 * tex_ptr: Surface of which to return the next level
3146 *****************************************************************************/
3147 static IDirectDrawSurfaceImpl
*get_sub_mimaplevel(IDirectDrawSurfaceImpl
*surface
)
3149 /* Now go down the mipmap chain to the next surface */
3150 static DDSCAPS2 mipmap_caps
= { DDSCAPS_MIPMAP
| DDSCAPS_TEXTURE
, 0, 0, 0 };
3151 IDirectDrawSurface7
*next_level
;
3154 hr
= ddraw_surface7_GetAttachedSurface(&surface
->IDirectDrawSurface7_iface
, &mipmap_caps
, &next_level
);
3155 if (FAILED(hr
)) return NULL
;
3157 ddraw_surface7_Release(next_level
);
3159 return impl_from_IDirectDrawSurface7(next_level
);
3162 /*****************************************************************************
3163 * IDirect3DTexture2::Load
3165 * Loads a texture created with the DDSCAPS_ALLOCONLOAD
3167 * This function isn't relayed to WineD3D because the whole interface is
3168 * implemented in DDraw only. For speed improvements a implementation which
3169 * takes OpenGL more into account could be placed into WineD3D.
3172 * src_texture: Address of the texture to load
3176 * D3DERR_TEXTURE_LOAD_FAILED.
3178 *****************************************************************************/
3179 static HRESULT WINAPI
d3d_texture2_Load(IDirect3DTexture2
*iface
, IDirect3DTexture2
*src_texture
)
3181 IDirectDrawSurfaceImpl
*dst_surface
= surface_from_texture2(iface
);
3182 IDirectDrawSurfaceImpl
*src_surface
= surface_from_texture2(src_texture
);
3185 TRACE("iface %p, src_texture %p.\n", iface
, src_texture
);
3187 if (src_surface
== dst_surface
)
3189 TRACE("copying surface %p to surface %p, why?\n", src_surface
, dst_surface
);
3193 EnterCriticalSection(&ddraw_cs
);
3195 if (((src_surface
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_MIPMAP
)
3196 != (dst_surface
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_MIPMAP
))
3197 || (src_surface
->surface_desc
.u2
.dwMipMapCount
!= dst_surface
->surface_desc
.u2
.dwMipMapCount
))
3199 ERR("Trying to load surfaces with different mip-map counts.\n");
3204 struct wined3d_palette
*wined3d_dst_pal
, *wined3d_src_pal
;
3205 IDirectDrawPalette
*dst_pal
= NULL
, *src_pal
= NULL
;
3206 DDSURFACEDESC
*src_desc
, *dst_desc
;
3208 TRACE("Copying surface %p to surface %p (mipmap level %d).\n",
3209 src_surface
, dst_surface
, src_surface
->mipmap_level
);
3211 /* Suppress the ALLOCONLOAD flag */
3212 dst_surface
->surface_desc
.ddsCaps
.dwCaps
&= ~DDSCAPS_ALLOCONLOAD
;
3214 /* Get the palettes */
3215 wined3d_dst_pal
= wined3d_surface_get_palette(dst_surface
->wined3d_surface
);
3216 if (wined3d_dst_pal
)
3217 dst_pal
= wined3d_palette_get_parent(wined3d_dst_pal
);
3219 wined3d_src_pal
= wined3d_surface_get_palette(src_surface
->wined3d_surface
);
3220 if (wined3d_src_pal
)
3221 src_pal
= wined3d_palette_get_parent(wined3d_src_pal
);
3225 PALETTEENTRY palent
[256];
3229 LeaveCriticalSection(&ddraw_cs
);
3230 return DDERR_NOPALETTEATTACHED
;
3232 IDirectDrawPalette_GetEntries(src_pal
, 0, 0, 256, palent
);
3233 IDirectDrawPalette_SetEntries(dst_pal
, 0, 0, 256, palent
);
3236 /* Copy one surface on the other */
3237 dst_desc
= (DDSURFACEDESC
*)&(dst_surface
->surface_desc
);
3238 src_desc
= (DDSURFACEDESC
*)&(src_surface
->surface_desc
);
3240 if ((src_desc
->dwWidth
!= dst_desc
->dwWidth
) || (src_desc
->dwHeight
!= dst_desc
->dwHeight
))
3242 /* Should also check for same pixel format, u1.lPitch, ... */
3243 ERR("Error in surface sizes.\n");
3244 LeaveCriticalSection(&ddraw_cs
);
3245 return D3DERR_TEXTURE_LOAD_FAILED
;
3249 WINED3DLOCKED_RECT src_rect
, dst_rect
;
3251 /* Copy also the ColorKeying stuff */
3252 if (src_desc
->dwFlags
& DDSD_CKSRCBLT
)
3254 dst_desc
->dwFlags
|= DDSD_CKSRCBLT
;
3255 dst_desc
->ddckCKSrcBlt
.dwColorSpaceLowValue
= src_desc
->ddckCKSrcBlt
.dwColorSpaceLowValue
;
3256 dst_desc
->ddckCKSrcBlt
.dwColorSpaceHighValue
= src_desc
->ddckCKSrcBlt
.dwColorSpaceHighValue
;
3259 /* Copy the main memory texture into the surface that corresponds
3260 * to the OpenGL texture object. */
3262 hr
= wined3d_surface_map(src_surface
->wined3d_surface
, &src_rect
, NULL
, 0);
3265 ERR("Failed to lock source surface, hr %#x.\n", hr
);
3266 LeaveCriticalSection(&ddraw_cs
);
3267 return D3DERR_TEXTURE_LOAD_FAILED
;
3270 hr
= wined3d_surface_map(dst_surface
->wined3d_surface
, &dst_rect
, NULL
, 0);
3273 ERR("Failed to lock destination surface, hr %#x.\n", hr
);
3274 wined3d_surface_unmap(src_surface
->wined3d_surface
);
3275 LeaveCriticalSection(&ddraw_cs
);
3276 return D3DERR_TEXTURE_LOAD_FAILED
;
3279 if (dst_surface
->surface_desc
.u4
.ddpfPixelFormat
.dwFlags
& DDPF_FOURCC
)
3280 memcpy(dst_rect
.pBits
, src_rect
.pBits
, src_surface
->surface_desc
.u1
.dwLinearSize
);
3282 memcpy(dst_rect
.pBits
, src_rect
.pBits
, src_rect
.Pitch
* src_desc
->dwHeight
);
3284 wined3d_surface_unmap(src_surface
->wined3d_surface
);
3285 wined3d_surface_unmap(dst_surface
->wined3d_surface
);
3288 if (src_surface
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_MIPMAP
)
3289 src_surface
= get_sub_mimaplevel(src_surface
);
3293 if (dst_surface
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_MIPMAP
)
3294 dst_surface
= get_sub_mimaplevel(dst_surface
);
3298 if (!src_surface
|| !dst_surface
)
3300 if (src_surface
!= dst_surface
)
3301 ERR("Loading surface with different mipmap structure.\n");
3306 LeaveCriticalSection(&ddraw_cs
);
3311 static HRESULT WINAPI
d3d_texture1_Load(IDirect3DTexture
*iface
, IDirect3DTexture
*src_texture
)
3313 TRACE("iface %p, src_texture %p.\n", iface
, src_texture
);
3315 return d3d_texture2_Load((IDirect3DTexture2
*)&surface_from_texture1(iface
)->IDirect3DTexture2_vtbl
,
3316 src_texture
? (IDirect3DTexture2
*)&surface_from_texture1(src_texture
)->IDirect3DTexture2_vtbl
: NULL
);
3319 /*****************************************************************************
3321 *****************************************************************************/
3323 static const struct IDirectDrawSurface7Vtbl ddraw_surface7_vtbl
=
3326 ddraw_surface7_QueryInterface
,
3327 ddraw_surface7_AddRef
,
3328 ddraw_surface7_Release
,
3329 /* IDirectDrawSurface */
3330 ddraw_surface7_AddAttachedSurface
,
3331 ddraw_surface7_AddOverlayDirtyRect
,
3333 ddraw_surface7_BltBatch
,
3334 ddraw_surface7_BltFast
,
3335 ddraw_surface7_DeleteAttachedSurface
,
3336 ddraw_surface7_EnumAttachedSurfaces
,
3337 ddraw_surface7_EnumOverlayZOrders
,
3338 ddraw_surface7_Flip
,
3339 ddraw_surface7_GetAttachedSurface
,
3340 ddraw_surface7_GetBltStatus
,
3341 ddraw_surface7_GetCaps
,
3342 ddraw_surface7_GetClipper
,
3343 ddraw_surface7_GetColorKey
,
3344 ddraw_surface7_GetDC
,
3345 ddraw_surface7_GetFlipStatus
,
3346 ddraw_surface7_GetOverlayPosition
,
3347 ddraw_surface7_GetPalette
,
3348 ddraw_surface7_GetPixelFormat
,
3349 ddraw_surface7_GetSurfaceDesc
,
3350 ddraw_surface7_Initialize
,
3351 ddraw_surface7_IsLost
,
3352 ddraw_surface7_Lock
,
3353 ddraw_surface7_ReleaseDC
,
3354 ddraw_surface7_Restore
,
3355 ddraw_surface7_SetClipper
,
3356 ddraw_surface7_SetColorKey
,
3357 ddraw_surface7_SetOverlayPosition
,
3358 ddraw_surface7_SetPalette
,
3359 ddraw_surface7_Unlock
,
3360 ddraw_surface7_UpdateOverlay
,
3361 ddraw_surface7_UpdateOverlayDisplay
,
3362 ddraw_surface7_UpdateOverlayZOrder
,
3363 /* IDirectDrawSurface2 */
3364 ddraw_surface7_GetDDInterface
,
3365 ddraw_surface7_PageLock
,
3366 ddraw_surface7_PageUnlock
,
3367 /* IDirectDrawSurface3 */
3368 ddraw_surface7_SetSurfaceDesc
,
3369 /* IDirectDrawSurface4 */
3370 ddraw_surface7_SetPrivateData
,
3371 ddraw_surface7_GetPrivateData
,
3372 ddraw_surface7_FreePrivateData
,
3373 ddraw_surface7_GetUniquenessValue
,
3374 ddraw_surface7_ChangeUniquenessValue
,
3375 /* IDirectDrawSurface7 */
3376 ddraw_surface7_SetPriority
,
3377 ddraw_surface7_GetPriority
,
3378 ddraw_surface7_SetLOD
,
3379 ddraw_surface7_GetLOD
,
3382 static const struct IDirectDrawSurface3Vtbl ddraw_surface3_vtbl
=
3385 ddraw_surface3_QueryInterface
,
3386 ddraw_surface3_AddRef
,
3387 ddraw_surface3_Release
,
3388 /* IDirectDrawSurface */
3389 ddraw_surface3_AddAttachedSurface
,
3390 ddraw_surface3_AddOverlayDirtyRect
,
3392 ddraw_surface3_BltBatch
,
3393 ddraw_surface3_BltFast
,
3394 ddraw_surface3_DeleteAttachedSurface
,
3395 ddraw_surface3_EnumAttachedSurfaces
,
3396 ddraw_surface3_EnumOverlayZOrders
,
3397 ddraw_surface3_Flip
,
3398 ddraw_surface3_GetAttachedSurface
,
3399 ddraw_surface3_GetBltStatus
,
3400 ddraw_surface3_GetCaps
,
3401 ddraw_surface3_GetClipper
,
3402 ddraw_surface3_GetColorKey
,
3403 ddraw_surface3_GetDC
,
3404 ddraw_surface3_GetFlipStatus
,
3405 ddraw_surface3_GetOverlayPosition
,
3406 ddraw_surface3_GetPalette
,
3407 ddraw_surface3_GetPixelFormat
,
3408 ddraw_surface3_GetSurfaceDesc
,
3409 ddraw_surface3_Initialize
,
3410 ddraw_surface3_IsLost
,
3411 ddraw_surface3_Lock
,
3412 ddraw_surface3_ReleaseDC
,
3413 ddraw_surface3_Restore
,
3414 ddraw_surface3_SetClipper
,
3415 ddraw_surface3_SetColorKey
,
3416 ddraw_surface3_SetOverlayPosition
,
3417 ddraw_surface3_SetPalette
,
3418 ddraw_surface3_Unlock
,
3419 ddraw_surface3_UpdateOverlay
,
3420 ddraw_surface3_UpdateOverlayDisplay
,
3421 ddraw_surface3_UpdateOverlayZOrder
,
3422 /* IDirectDrawSurface2 */
3423 ddraw_surface3_GetDDInterface
,
3424 ddraw_surface3_PageLock
,
3425 ddraw_surface3_PageUnlock
,
3426 /* IDirectDrawSurface3 */
3427 ddraw_surface3_SetSurfaceDesc
,
3430 static const struct IDirectDrawGammaControlVtbl ddraw_gamma_control_vtbl
=
3432 ddraw_gamma_control_QueryInterface
,
3433 ddraw_gamma_control_AddRef
,
3434 ddraw_gamma_control_Release
,
3435 ddraw_gamma_control_GetGammaRamp
,
3436 ddraw_gamma_control_SetGammaRamp
,
3439 static const struct IDirect3DTexture2Vtbl d3d_texture2_vtbl
=
3441 d3d_texture2_QueryInterface
,
3442 d3d_texture2_AddRef
,
3443 d3d_texture2_Release
,
3444 d3d_texture2_GetHandle
,
3445 d3d_texture2_PaletteChanged
,
3449 static const struct IDirect3DTextureVtbl d3d_texture1_vtbl
=
3451 d3d_texture1_QueryInterface
,
3452 d3d_texture1_AddRef
,
3453 d3d_texture1_Release
,
3454 d3d_texture1_Initialize
,
3455 d3d_texture1_GetHandle
,
3456 d3d_texture1_PaletteChanged
,
3458 d3d_texture1_Unload
,
3461 IDirectDrawSurfaceImpl
*unsafe_impl_from_IDirectDrawSurface7(IDirectDrawSurface7
*iface
)
3463 if (!iface
) return NULL
;
3464 assert(iface
->lpVtbl
== &ddraw_surface7_vtbl
);
3465 return CONTAINING_RECORD(iface
, IDirectDrawSurfaceImpl
, IDirectDrawSurface7_iface
);
3468 IDirectDrawSurfaceImpl
*unsafe_impl_from_IDirectDrawSurface4(IDirectDrawSurface4
*iface
)
3470 if (!iface
) return NULL
;
3471 assert(iface
->lpVtbl
== (struct IDirectDrawSurface4Vtbl
*)&ddraw_surface7_vtbl
);
3472 return CONTAINING_RECORD(iface
, IDirectDrawSurfaceImpl
, IDirectDrawSurface7_iface
);
3475 IDirectDrawSurfaceImpl
*unsafe_impl_from_IDirectDrawSurface3(IDirectDrawSurface3
*iface
)
3477 if (!iface
) return NULL
;
3478 assert(iface
->lpVtbl
== &ddraw_surface3_vtbl
);
3479 return CONTAINING_RECORD(iface
, IDirectDrawSurfaceImpl
, IDirectDrawSurface3_iface
);
3482 static void STDMETHODCALLTYPE
ddraw_surface_wined3d_object_destroyed(void *parent
)
3484 IDirectDrawSurfaceImpl
*surface
= parent
;
3486 TRACE("surface %p.\n", surface
);
3488 /* Check for attached surfaces and detach them. */
3489 if (surface
->first_attached
!= surface
)
3491 IDirectDrawSurface7
*root
= &surface
->first_attached
->IDirectDrawSurface7_iface
;
3492 IDirectDrawSurface7
*detach
= &surface
->IDirectDrawSurface7_iface
;
3494 /* Well, this shouldn't happen: The surface being attached is
3495 * referenced in AddAttachedSurface(), so it shouldn't be released
3496 * until DeleteAttachedSurface() is called, because the refcount is
3497 * held. It looks like the application released it often enough to
3499 WARN("Surface is still attached to surface %p.\n", surface
->first_attached
);
3501 /* The refcount will drop to -1 here */
3502 if (FAILED(IDirectDrawSurface7_DeleteAttachedSurface(root
, 0, detach
)))
3503 ERR("DeleteAttachedSurface failed.\n");
3506 while (surface
->next_attached
)
3508 IDirectDrawSurface7
*root
= &surface
->IDirectDrawSurface7_iface
;
3509 IDirectDrawSurface7
*detach
= &surface
->next_attached
->IDirectDrawSurface7_iface
;
3511 if (FAILED(IDirectDrawSurface7_DeleteAttachedSurface(root
, 0, detach
)))
3512 ERR("DeleteAttachedSurface failed.\n");
3515 /* Having a texture handle set implies that the device still exists. */
3516 if (surface
->Handle
)
3517 ddraw_free_handle(&surface
->ddraw
->d3ddevice
->handle_table
, surface
->Handle
- 1, DDRAW_HANDLE_SURFACE
);
3519 /* Reduce the ddraw surface count. */
3520 InterlockedDecrement(&surface
->ddraw
->surfaces
);
3521 list_remove(&surface
->surface_list_entry
);
3523 HeapFree(GetProcessHeap(), 0, surface
);
3526 const struct wined3d_parent_ops ddraw_surface_wined3d_parent_ops
=
3528 ddraw_surface_wined3d_object_destroyed
,
3531 static void STDMETHODCALLTYPE
ddraw_texture_wined3d_object_destroyed(void *parent
)
3533 IDirectDrawSurfaceImpl
*surface
= parent
;
3535 TRACE("surface %p.\n", surface
);
3537 ddraw_surface_cleanup(surface
);
3540 static const struct wined3d_parent_ops ddraw_texture_wined3d_parent_ops
=
3542 ddraw_texture_wined3d_object_destroyed
,
3545 HRESULT
ddraw_surface_create_texture(IDirectDrawSurfaceImpl
*surface
)
3547 const DDSURFACEDESC2
*desc
= &surface
->surface_desc
;
3548 enum wined3d_format_id format
;
3552 if (desc
->ddsCaps
.dwCaps
& DDSCAPS_MIPMAP
)
3553 levels
= desc
->u2
.dwMipMapCount
;
3557 /* DDSCAPS_SYSTEMMEMORY textures are in WINED3DPOOL_SYSTEMMEM.
3558 * Should I forward the MANAGED cap to the managed pool? */
3559 if (desc
->ddsCaps
.dwCaps
& DDSCAPS_SYSTEMMEMORY
)
3560 pool
= WINED3DPOOL_SYSTEMMEM
;
3562 pool
= WINED3DPOOL_DEFAULT
;
3564 format
= PixelFormat_DD2WineD3D(&surface
->surface_desc
.u4
.ddpfPixelFormat
);
3565 if (desc
->ddsCaps
.dwCaps2
& DDSCAPS2_CUBEMAP
)
3566 return wined3d_texture_create_cube(surface
->ddraw
->wined3d_device
, desc
->dwWidth
,
3567 levels
, 0, format
, pool
, surface
, &ddraw_texture_wined3d_parent_ops
, &surface
->wined3d_texture
);
3569 return wined3d_texture_create_2d(surface
->ddraw
->wined3d_device
, desc
->dwWidth
, desc
->dwHeight
,
3570 levels
, 0, format
, pool
, surface
, &ddraw_texture_wined3d_parent_ops
, &surface
->wined3d_texture
);
3573 HRESULT
ddraw_surface_init(IDirectDrawSurfaceImpl
*surface
, IDirectDrawImpl
*ddraw
,
3574 DDSURFACEDESC2
*desc
, UINT mip_level
, WINED3DSURFTYPE surface_type
)
3576 struct wined3d_resource_desc wined3d_desc
;
3577 struct wined3d_resource
*wined3d_resource
;
3578 WINED3DPOOL pool
= WINED3DPOOL_DEFAULT
;
3579 enum wined3d_format_id format
;
3583 if (!(desc
->ddsCaps
.dwCaps
& (DDSCAPS_VIDEOMEMORY
| DDSCAPS_SYSTEMMEMORY
))
3584 && !((desc
->ddsCaps
.dwCaps
& DDSCAPS_TEXTURE
)
3585 && (desc
->ddsCaps
.dwCaps2
& DDSCAPS2_TEXTUREMANAGE
)))
3587 /* Tests show surfaces without memory flags get these flags added
3588 * right after creation. */
3589 desc
->ddsCaps
.dwCaps
|= DDSCAPS_LOCALVIDMEM
| DDSCAPS_VIDEOMEMORY
;
3592 if (desc
->ddsCaps
.dwCaps
& DDSCAPS_PRIMARYSURFACE
)
3594 usage
|= WINED3DUSAGE_RENDERTARGET
;
3595 desc
->ddsCaps
.dwCaps
|= DDSCAPS_VISIBLE
;
3598 if ((desc
->ddsCaps
.dwCaps
& DDSCAPS_3DDEVICE
) && !(desc
->ddsCaps
.dwCaps
& DDSCAPS_ZBUFFER
))
3600 usage
|= WINED3DUSAGE_RENDERTARGET
;
3603 if (desc
->ddsCaps
.dwCaps
& (DDSCAPS_OVERLAY
))
3605 usage
|= WINED3DUSAGE_OVERLAY
;
3608 if (ddraw
->depthstencil
|| (desc
->ddsCaps
.dwCaps
& DDSCAPS_ZBUFFER
))
3610 /* The depth stencil creation callback sets this flag. Set the
3611 * wined3d usage to let it know it's a depth/stencil surface. */
3612 usage
|= WINED3DUSAGE_DEPTHSTENCIL
;
3615 if (desc
->ddsCaps
.dwCaps
& DDSCAPS_SYSTEMMEMORY
)
3617 pool
= WINED3DPOOL_SYSTEMMEM
;
3619 else if (desc
->ddsCaps
.dwCaps2
& DDSCAPS2_TEXTUREMANAGE
)
3621 pool
= WINED3DPOOL_MANAGED
;
3622 /* Managed textures have the system memory flag set. */
3623 desc
->ddsCaps
.dwCaps
|= DDSCAPS_SYSTEMMEMORY
;
3625 else if (desc
->ddsCaps
.dwCaps
& DDSCAPS_VIDEOMEMORY
)
3627 /* Videomemory adds localvidmem. This is mutually exclusive with
3628 * systemmemory and texturemanage. */
3629 desc
->ddsCaps
.dwCaps
|= DDSCAPS_LOCALVIDMEM
;
3632 format
= PixelFormat_DD2WineD3D(&desc
->u4
.ddpfPixelFormat
);
3633 if (format
== WINED3DFMT_UNKNOWN
)
3635 WARN("Unsupported / unknown pixelformat.\n");
3636 return DDERR_INVALIDPIXELFORMAT
;
3639 surface
->IDirectDrawSurface7_iface
.lpVtbl
= &ddraw_surface7_vtbl
;
3640 surface
->IDirectDrawSurface3_iface
.lpVtbl
= &ddraw_surface3_vtbl
;
3641 surface
->IDirectDrawGammaControl_vtbl
= &ddraw_gamma_control_vtbl
;
3642 surface
->IDirect3DTexture2_vtbl
= &d3d_texture2_vtbl
;
3643 surface
->IDirect3DTexture_vtbl
= &d3d_texture1_vtbl
;
3645 surface
->version
= 7;
3646 surface
->ddraw
= ddraw
;
3648 copy_to_surfacedesc2(&surface
->surface_desc
, desc
);
3650 surface
->first_attached
= surface
;
3651 surface
->ImplType
= surface_type
;
3653 hr
= wined3d_surface_create(ddraw
->wined3d_device
, desc
->dwWidth
, desc
->dwHeight
, format
,
3654 TRUE
/* Lockable */, FALSE
/* Discard */, mip_level
, usage
, pool
,
3655 WINED3DMULTISAMPLE_NONE
, 0 /* MultiSampleQuality */, surface_type
, surface
,
3656 &ddraw_surface_wined3d_parent_ops
, &surface
->wined3d_surface
);
3659 WARN("Failed to create wined3d surface, hr %#x.\n", hr
);
3663 surface
->surface_desc
.dwFlags
|= DDSD_PIXELFORMAT
;
3664 wined3d_resource
= wined3d_surface_get_resource(surface
->wined3d_surface
);
3665 wined3d_resource_get_desc(wined3d_resource
, &wined3d_desc
);
3667 format
= wined3d_desc
.format
;
3668 if (format
== WINED3DFMT_UNKNOWN
)
3670 FIXME("IWineD3DSurface::GetDesc returned WINED3DFMT_UNKNOWN.\n");
3672 PixelFormat_WineD3DtoDD(&surface
->surface_desc
.u4
.ddpfPixelFormat
, format
);
3674 /* Anno 1602 stores the pitch right after surface creation, so make sure
3675 * it's there. TODO: Test other fourcc formats. */
3676 if (format
== WINED3DFMT_DXT1
|| format
== WINED3DFMT_DXT2
|| format
== WINED3DFMT_DXT3
3677 || format
== WINED3DFMT_DXT4
|| format
== WINED3DFMT_DXT5
)
3679 surface
->surface_desc
.dwFlags
|= DDSD_LINEARSIZE
;
3680 if (format
== WINED3DFMT_DXT1
)
3682 surface
->surface_desc
.u1
.dwLinearSize
= max(4, wined3d_desc
.width
) * max(4, wined3d_desc
.height
) / 2;
3686 surface
->surface_desc
.u1
.dwLinearSize
= max(4, wined3d_desc
.width
) * max(4, wined3d_desc
.height
);
3691 surface
->surface_desc
.dwFlags
|= DDSD_PITCH
;
3692 surface
->surface_desc
.u1
.lPitch
= wined3d_surface_get_pitch(surface
->wined3d_surface
);
3695 if (desc
->dwFlags
& DDSD_CKDESTOVERLAY
)
3697 wined3d_surface_set_color_key(surface
->wined3d_surface
, DDCKEY_DESTOVERLAY
,
3698 (WINEDDCOLORKEY
*)&desc
->u3
.ddckCKDestOverlay
);
3700 if (desc
->dwFlags
& DDSD_CKDESTBLT
)
3702 wined3d_surface_set_color_key(surface
->wined3d_surface
, DDCKEY_DESTBLT
,
3703 (WINEDDCOLORKEY
*)&desc
->ddckCKDestBlt
);
3705 if (desc
->dwFlags
& DDSD_CKSRCOVERLAY
)
3707 wined3d_surface_set_color_key(surface
->wined3d_surface
, DDCKEY_SRCOVERLAY
,
3708 (WINEDDCOLORKEY
*)&desc
->ddckCKSrcOverlay
);
3710 if (desc
->dwFlags
& DDSD_CKSRCBLT
)
3712 wined3d_surface_set_color_key(surface
->wined3d_surface
, DDCKEY_SRCBLT
,
3713 (WINEDDCOLORKEY
*)&desc
->ddckCKSrcBlt
);
3715 if (desc
->dwFlags
& DDSD_LPSURFACE
)
3717 hr
= wined3d_surface_set_mem(surface
->wined3d_surface
, desc
->lpSurface
);
3720 ERR("Failed to set surface memory, hr %#x.\n", hr
);
3721 wined3d_surface_decref(surface
->wined3d_surface
);