From bed50115eeba9ddce7003455ac805cbb698e2375 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20D=C3=B6singer?= Date: Fri, 4 May 2007 18:31:14 +0200 Subject: [PATCH] ddraw: More tests and fixes on surface attachments. --- dlls/ddraw/ddraw.c | 16 ++- dlls/ddraw/ddraw_private.h | 2 + dlls/ddraw/ddraw_thunks.c | 4 + dlls/ddraw/surface.c | 71 +++++----- dlls/ddraw/surface_thunks.c | 40 +++++- dlls/ddraw/tests/dsurface.c | 256 +++++++++++++++++++++++++++++++++++- 6 files changed, 344 insertions(+), 45 deletions(-) diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c index 36b3a955f92..16672f32cee 100644 --- a/dlls/ddraw/ddraw.c +++ b/dlls/ddraw/ddraw.c @@ -1798,7 +1798,7 @@ IDirectDrawImpl_CreateNewSurface(IDirectDrawImpl *This, { Usage |= WINED3DUSAGE_OVERLAY; } - if(This->depthstencil) + if(This->depthstencil || (pDDSD->ddsCaps.dwCaps & DDSCAPS_ZBUFFER) ) { /* The depth stencil creation callback sets this flag. * Set the WineD3D usage to let it know that it's a depth @@ -2198,6 +2198,12 @@ IDirectDrawImpl_CreateSurface(IDirectDraw7 *iface, return CLASS_E_NOAGGREGATION; /* unchecked */ } + if (Surf == NULL) + { + FIXME("(%p) You want to get back a surface? Don't give NULL ptrs!\n", This); + return E_POINTER; /* unchecked */ + } + if (!(DDSD->dwFlags & DDSD_CAPS)) { /* DVIDEO.DLL does forget the DDSD_CAPS flag ... *sigh* */ @@ -2230,12 +2236,10 @@ IDirectDrawImpl_CreateSurface(IDirectDraw7 *iface, return DDERR_NOEXCLUSIVEMODE; } - if (Surf == NULL) - { - FIXME("(%p) You want to get back a surface? Don't give NULL ptrs!\n", This); - return E_POINTER; /* unchecked */ + if(DDSD->ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER)) { + WARN("Application tried to create an explicit front or back buffer\n"); + return DDERR_INVALIDCAPS; } - /* Check cube maps but only if the size includes them */ if (DDSD->dwSize >= sizeof(DDSURFACEDESC2)) { diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h index 2c144f7b2fc..9845102b42f 100644 --- a/dlls/ddraw/ddraw_private.h +++ b/dlls/ddraw/ddraw_private.h @@ -272,6 +272,8 @@ const IDirectDrawGammaControlVtbl IDirectDrawGammaControl_Vtbl; const IDirect3DTexture2Vtbl IDirect3DTexture2_Vtbl; const IDirect3DTextureVtbl IDirect3DTexture1_Vtbl; +HRESULT WINAPI IDirectDrawSurfaceImpl_AddAttachedSurface(IDirectDrawSurfaceImpl *This, IDirectDrawSurfaceImpl *Surf); + /* Get the number of bytes per pixel for a given surface */ #define PFGET_BPP(pf) (pf.dwFlags&DDPF_PALETTEINDEXED8?1:((pf.dwRGBBitCount+7)/8)) #define GET_BPP(desc) PFGET_BPP(desc.ddpfPixelFormat) diff --git a/dlls/ddraw/ddraw_thunks.c b/dlls/ddraw/ddraw_thunks.c index c832ff7f434..b748ad47985 100644 --- a/dlls/ddraw/ddraw_thunks.c +++ b/dlls/ddraw/ddraw_thunks.c @@ -386,6 +386,10 @@ IDirectDrawImpl_CreateSurface(LPDIRECTDRAW This, LPDDSURFACEDESC pSDesc, IDirectDrawSurfaceImpl *impl; HRESULT hr; + /* Remove front buffer flag, this causes failure in v7, and its added to normal + * primaries anyway + */ + pSDesc->ddsCaps.dwCaps &= ~DDSCAPS_FRONTBUFFER; /* the LPDDSURFACEDESC -> LPDDSURFACEDESC2 conversion should be ok, * since the data layout is the same */ hr = IDirectDraw7_CreateSurface(COM_INTERFACE_CAST(IDirectDrawImpl, diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c index 5f2652638d2..220444dc3dc 100644 --- a/dlls/ddraw/surface.c +++ b/dlls/ddraw/surface.c @@ -780,11 +780,16 @@ IDirectDrawSurfaceImpl_Blt(IDirectDrawSurface7 *iface, * * So far only Z-Buffer attachments are tested, and they are activated in * WineD3D. Mipmaps could be tricky to activate in WineD3D. - * Back buffers should work in 2D mode, but they are not tested(Not sure if - * they can be attached at all). Rendering to the primary surface and + * Back buffers should work in 2D mode, but they are not tested(They can be + * attached in older iface versions). Rendering to the front buffer and * switching between that and double buffering is not yet implemented in * WineD3D, so for 3D it might have unexpected results. * + * IDirectDrawSurfaceImpl_AddAttachedSurface is the real thing, + * IDirectDrawSurface7Impl_AddAttachedSurface is a wrapper around it that + * performs additional checks. Version 7 of this interface is much more restrictive + * than its predecessors. + * * Params: * Attach: Surface to attach to iface * @@ -793,45 +798,24 @@ IDirectDrawSurfaceImpl_Blt(IDirectDrawSurface7 *iface, * DDERR_CANNOTATTACHSURFACE if the surface can't be attached for some reason * *****************************************************************************/ -static HRESULT WINAPI -IDirectDrawSurfaceImpl_AddAttachedSurface(IDirectDrawSurface7 *iface, - IDirectDrawSurface7 *Attach) +HRESULT WINAPI +IDirectDrawSurfaceImpl_AddAttachedSurface(IDirectDrawSurfaceImpl *This, + IDirectDrawSurfaceImpl *Surf) { - ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface); - IDirectDrawSurfaceImpl *Surf = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, Attach); TRACE("(%p)->(%p)\n", This, Surf); - /* Should I make sure to add it to the first complex surface? */ - if(Surf == This) return DDERR_CANNOTATTACHSURFACE; /* unchecked */ - /* MSDN: Only Z buffer surfaces can be attached. An old comment said that apparently - * mipmaps and back buffers can be attached too, although our tests say no. - */ - if(!(Surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)) - { - /* Write a fixme until we know for sure what is going on */ - FIXME("Application tries to attach a non Z buffer surface. caps %08x\n", - Surf->surface_desc.ddsCaps.dwCaps); - return DDERR_CANNOTATTACHSURFACE; - } - - /* Set MIPMAPSUBLEVEL if this seems to be one */ - if (This->surface_desc.ddsCaps.dwCaps & - Surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) - { - Surf->surface_desc.ddsCaps.dwCaps2 |= DDSCAPS2_MIPMAPSUBLEVEL; - /* FIXME: we should probably also add to dwMipMapCount of this - * and all parent surfaces (update create_texture if you do) */ - } - /* Check if the surface is already attached somewhere */ if( (Surf->next_attached != NULL) || (Surf->first_attached != Surf) ) { - ERR("(%p) The Surface %p is already attached somewhere else: next_attached = %p, first_attached = %p, can't handle by now\n", This, Surf, Surf->next_attached, Surf->first_attached); - return DDERR_CANNOTATTACHSURFACE; + /* TODO: Test for the structure of the manual attachment. Is it a chain or a list? + * What happens if one surface is attached to 2 different surfaces? + */ + FIXME("(%p) The Surface %p is already attached somewhere else: next_attached = %p, first_attached = %p, can't handle by now\n", This, Surf, Surf->next_attached, Surf->first_attached); + return DDERR_SURFACEALREADYATTACHED; } /* This inserts the new surface at the 2nd position in the chain, right after the root surface */ @@ -848,10 +832,29 @@ IDirectDrawSurfaceImpl_AddAttachedSurface(IDirectDrawSurface7 *iface, /* MSDN: * "This method increments the reference count of the surface being attached." */ - IDirectDrawSurface7_AddRef(Attach); + IDirectDrawSurface7_AddRef(ICOM_INTERFACE(Surf, IDirectDrawSurface7)); return DD_OK; } +static HRESULT WINAPI +IDirectDrawSurface7Impl_AddAttachedSurface(IDirectDrawSurface7 *iface, + IDirectDrawSurface7 *Attach) +{ + ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface); + IDirectDrawSurfaceImpl *Surf = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, Attach); + + /* Version 7 of this interface seems to refuse everything except z buffers, as per msdn */ + if(!(Surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)) + { + + WARN("Application tries to attach a non Z buffer surface. caps %08x\n", + Surf->surface_desc.ddsCaps.dwCaps); + return DDERR_CANNOTATTACHSURFACE; + } + + return IDirectDrawSurfaceImpl_AddAttachedSurface(This, + Surf); +} /***************************************************************************** * IDirectDrawSurface7::DeleteAttachedSurface * @@ -878,7 +881,7 @@ IDirectDrawSurfaceImpl_DeleteAttachedSurface(IDirectDrawSurface7 *iface, TRACE("(%p)->(%08x,%p)\n", This, Flags, Surf); if (!Surf || (Surf->first_attached != This) || (Surf == This) ) - return DDERR_SURFACENOTATTACHED; /* unchecked */ + return DDERR_CANNOTDETACHSURFACE; /* Remove MIPMAPSUBLEVEL if this seemed to be one */ if (This->surface_desc.ddsCaps.dwCaps & @@ -2309,7 +2312,7 @@ const IDirectDrawSurface7Vtbl IDirectDrawSurface7_Vtbl = IDirectDrawSurfaceImpl_AddRef, IDirectDrawSurfaceImpl_Release, /*** IDirectDrawSurface ***/ - IDirectDrawSurfaceImpl_AddAttachedSurface, + IDirectDrawSurface7Impl_AddAttachedSurface, IDirectDrawSurfaceImpl_AddOverlayDirtyRect, IDirectDrawSurfaceImpl_Blt, IDirectDrawSurfaceImpl_BltBatch, diff --git a/dlls/ddraw/surface_thunks.c b/dlls/ddraw/surface_thunks.c index bba49bd3756..299e4f682dd 100644 --- a/dlls/ddraw/surface_thunks.c +++ b/dlls/ddraw/surface_thunks.c @@ -64,11 +64,45 @@ IDirectDrawSurface3Impl_Release(LPDIRECTDRAWSURFACE3 iface) } static HRESULT WINAPI -IDirectDrawSurface3Impl_AddAttachedSurface(LPDIRECTDRAWSURFACE3 This, +IDirectDrawSurface3Impl_AddAttachedSurface(LPDIRECTDRAWSURFACE3 iface, LPDIRECTDRAWSURFACE3 pAttach) { - return IDirectDrawSurface7_AddAttachedSurface(CONVERT(This), - CONVERT(pAttach)); + ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface3, iface); + IDirectDrawSurfaceImpl *Surf = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface3, pAttach); + TRACE("(%p)->(%p)\n", This, Surf); + + /* Tests suggest that + * -> offscreen plain surfaces can be attached to other offscreen plain surfaces + * -> offscreen plain surfaces can be attached to primaries + * -> primaries can be attached to offscreen plain surfaces + * -> z buffers can be attached to primaries + * + */ + if(This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_OFFSCREENPLAIN) && + Surf->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_OFFSCREENPLAIN)) + { + /* Sizes have to match */ + if(Surf->surface_desc.dwWidth != This->surface_desc.dwWidth || + Surf->surface_desc.dwHeight != This->surface_desc.dwHeight) + { + WARN("Surface sizes do not match\n"); + return DDERR_CANNOTATTACHSURFACE; + } + /* OK */ + } + else if(This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE) && + Surf->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) + { + /* OK */ + } + else + { + WARN("Invalid attachment combination\n"); + return DDERR_CANNOTATTACHSURFACE; + } + + return IDirectDrawSurfaceImpl_AddAttachedSurface(This, + Surf); } static HRESULT WINAPI diff --git a/dlls/ddraw/tests/dsurface.c b/dlls/ddraw/tests/dsurface.c index 653cf7e0322..a2d7e7a7fad 100644 --- a/dlls/ddraw/tests/dsurface.c +++ b/dlls/ddraw/tests/dsurface.c @@ -965,11 +965,11 @@ HRESULT WINAPI SurfaceCounter(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *desc return DDENUMRET_OK; } -static void AttachmentTest(void) +static void AttachmentTest7(void) { HRESULT hr; IDirectDraw7 *dd7; - IDirectDrawSurface7 *surface1, *surface2, *surface3; + IDirectDrawSurface7 *surface1, *surface2, *surface3, *surface4; DDSURFACEDESC2 ddsd; UINT num; DDSCAPS2 caps = {DDSCAPS_TEXTURE, 0, 0, 0}; @@ -1031,6 +1031,26 @@ static void AttachmentTest(void) hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface3); ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 32x32 texture mip level to a 16x16 surface returned %08x\n", hr); + IDirectDrawSurface7_Release(surface2); + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = 16; + ddsd.dwHeight = 16; + hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface2, NULL); + ok(hr==DD_OK,"CreateSurface returned: %x\n",hr); + + hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface2); + ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 16x16 offscreen plain surface to a 128x128 texture root returned %08x\n", hr); + hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface1); + ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 128x128 texture root to a 16x16 offscreen plain surface returned %08x\n", hr); + hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface2); + ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 16x16 offscreen plain surface to a 32x32 texture mip level returned %08x\n", hr); + hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface3); + ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 32x32 texture mip level to a 16x16 offscreen plain surface returned %08x\n", hr); + IDirectDrawSurface7_Release(surface3); IDirectDrawSurface7_Release(surface2); IDirectDrawSurface7_Release(surface1); @@ -1051,11 +1071,242 @@ static void AttachmentTest(void) ok(num == 1, "Primary surface has %d surfaces attached, expected 1\n", num); IDirectDrawSurface7_Release(surface1); + /* Those are some invalid descriptions, no need to test attachments with them */ + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER; + hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface1, NULL); + ok(hr==DDERR_INVALIDCAPS,"CreateSurface returned: %x\n",hr); + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER; + hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface2, NULL); + ok(hr==DDERR_INVALIDCAPS,"CreateSurface returned: %x\n",hr); + + /* Try a single primary and two offscreen plain surfaces */ + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface1, NULL); + ok(hr==DD_OK,"CreateSurface returned: %x\n",hr); + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = GetSystemMetrics(SM_CXSCREEN); + ddsd.dwHeight = GetSystemMetrics(SM_CYSCREEN); + hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface2, NULL); + ok(hr==DD_OK,"CreateSurface returned: %x\n",hr); + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = GetSystemMetrics(SM_CXSCREEN); + ddsd.dwHeight = GetSystemMetrics(SM_CYSCREEN); + hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface3, NULL); + ok(hr==DD_OK,"CreateSurface returned: %x\n",hr); + + /* This one has a different size */ + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = 128; + ddsd.dwHeight = 128; + hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface4, NULL); + ok(hr==DD_OK,"CreateSurface returned: %x\n",hr); + + hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface2); + ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching an offscreen plain surface to a front buffer returned %08x\n", hr); + hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface1); + ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a front buffer to an offscreen plain surface returned %08x\n", hr); + hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface3); + ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching an offscreen plain surface to another offscreen plain surface returned %08x\n", hr); + hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface4); + ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching an offscreen plain surface to a front buffer of different size returned %08x\n", hr); + hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface1); + ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a front buffer to an offscreen plain surface of different size returned %08x\n", hr); + + IDirectDrawSurface7_Release(surface4); + IDirectDrawSurface7_Release(surface3); + IDirectDrawSurface7_Release(surface2); + IDirectDrawSurface7_Release(surface1); + hr =IDirectDraw7_SetCooperativeLevel(dd7, NULL, DDSCL_NORMAL); ok(hr == DD_OK, "SetCooperativeLevel returned %08x\n", hr); IDirectDraw7_Release(dd7); } +static void AttachmentTest(void) +{ + HRESULT hr; + IDirectDrawSurface *surface1, *surface2, *surface3, *surface4; + DDSURFACEDESC ddsd; + DDSCAPS caps = {DDSCAPS_TEXTURE}; + HWND window = CreateWindow( "static", "ddraw_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL ); + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT; + ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP; + U2(ddsd).dwMipMapCount = 3; /* Will create 128x128, 64x64, 32x32 */ + ddsd.dwWidth = 128; + ddsd.dwHeight = 128; + hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &surface1, NULL); + ok(hr==DD_OK,"CreateSurface returned: %x\n",hr); + + hr = IDirectDrawSurface7_GetAttachedSurface(surface1, &caps, &surface2); + ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr); + hr = IDirectDrawSurface7_GetAttachedSurface(surface2, &caps, &surface3); + ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr); + + /* Try to attach a 16x16 miplevel - Should not work as far I can see */ + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE; + ddsd.dwWidth = 16; + ddsd.dwHeight = 16; + hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface4, NULL); + ok(hr==DD_OK,"CreateSurface returned: %x\n",hr); + + hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface4); + ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 16x16 surface to a 128x128 texture root returned %08x\n", hr); + hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface1); + ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 128x128 texture root to a 16x16 texture returned %08x\n", hr); + hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface4); + ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 16x16 surface to a 32x32 texture mip level returned %08x\n", hr); + hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface3); + ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 32x32 texture mip level to a 16x16 surface returned %08x\n", hr); + hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface4); + ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 16x16 surface to a 64x64 texture sublevel returned %08x\n", hr); + hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface2); + ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 64x64 texture sublevel to a 16x16 texture returned %08x\n", hr); + + IDirectDrawSurface7_Release(surface4); + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = 16; + ddsd.dwHeight = 16; + hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &surface4, NULL); + ok(hr==DD_OK,"CreateSurface returned: %x\n",hr); + + hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface4); + ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 16x16 offscreen plain surface to a 128x128 texture root returned %08x\n", hr); + hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface1); + ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 128x128 texture root to a 16x16 offscreen plain surface returned %08x\n", hr); + hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface4); + ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 16x16 offscreen plain surface to a 32x32 texture mip level returned %08x\n", hr); + hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface3); + ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 32x32 texture mip level to a 16x16 offscreen plain surface returned %08x\n", hr); + hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface4); + ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 16x16 offscreen plain surface to a 64x64 texture sublevel returned %08x\n", hr); + hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface2); + ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 64x64 texture sublevel to a 16x16 offscreen plain surface returned %08x\n", hr); + + IDirectDrawSurface7_Release(surface4); + IDirectDrawSurface7_Release(surface3); + IDirectDrawSurface7_Release(surface2); + IDirectDrawSurface7_Release(surface1); + + hr = IDirectDraw_SetCooperativeLevel(lpDD, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN); + ok(hr == DD_OK, "SetCooperativeLevel returned %08x\n", hr); + + /* Creating a back buffer as-is is not allowed, no need to perform attachment tests */ + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER; + hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface2, NULL); + ok(hr==DDERR_INVALIDCAPS,"CreateSurface returned: %x\n",hr); + /* This old ddraw version happily creates explicit front buffers */ + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER; + hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface1, NULL); + ok(hr==DD_OK,"CreateSurface returned: %x\n",hr); + IDirectDrawSurface_Release(surface1); + + /* Try a single primary and two offscreen plain surfaces */ + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface1, NULL); + ok(hr==DD_OK,"CreateSurface returned: %x\n",hr); + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = GetSystemMetrics(SM_CXSCREEN); + ddsd.dwHeight = GetSystemMetrics(SM_CYSCREEN); + hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface2, NULL); + ok(hr==DD_OK,"CreateSurface returned: %x\n",hr); + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = GetSystemMetrics(SM_CXSCREEN); + ddsd.dwHeight = GetSystemMetrics(SM_CYSCREEN); + hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface3, NULL); + ok(hr==DD_OK,"CreateSurface returned: %x\n",hr); + + /* This one has a different size */ + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.dwWidth = 128; + ddsd.dwHeight = 128; + hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface4, NULL); + ok(hr==DD_OK,"CreateSurface returned: %x\n",hr); + + hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2); + ok(hr == DD_OK, "Attaching an offscreen plain surface to a front buffer returned %08x\n", hr); + /* Try the reverse without detaching first */ + hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1); + ok(hr == DDERR_SURFACEALREADYATTACHED, "Attaching an attached surface to its attachee returned %08x\n", hr); + hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2); + ok(hr == DD_OK, "DeleteAttachedSurface failed with %08x\n", hr); + hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1); + ok(hr == DD_OK, "Attaching a front buffer to an offscreen plain surface returned %08x\n", hr); + /* Try to detach reversed */ + hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2); + ok(hr == DDERR_CANNOTDETACHSURFACE, "DeleteAttachedSurface returned %08x\n", hr); + /* Now the proper detach */ + hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface1); + ok(hr == DD_OK, "DeleteAttachedSurface failed with %08x\n", hr); + hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface3); + ok(hr == DD_OK, "Attaching an offscreen plain surface to another offscreen plain surface returned %08x\n", hr); + hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface3); + ok(hr == DD_OK, "DeleteAttachedSurface failed with %08x\n", hr); + hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4); + ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching an offscreen plain surface to a front buffer of different size returned %08x\n", hr); + hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1); + ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a front buffer to an offscreen plain surface of different size returned %08x\n", hr); + + IDirectDrawSurface_Release(surface4); + IDirectDrawSurface_Release(surface3); + IDirectDrawSurface_Release(surface2); + IDirectDrawSurface_Release(surface1); + + hr =IDirectDraw_SetCooperativeLevel(lpDD, NULL, DDSCL_NORMAL); + ok(hr == DD_OK, "SetCooperativeLevel returned %08x\n", hr); + + DestroyWindow(window); +} + struct compare { DWORD width, height; @@ -1831,6 +2082,7 @@ START_TEST(dsurface) GetDDInterface_7(); EnumTest(); AttachmentTest(); + AttachmentTest7(); CubeMapTest(); test_lockrect_invalid(); CompressedTest();