ddraw: Add a separate function for surface initialization.

This commit is contained in:
Henri Verbeet 2010-08-19 18:57:49 +02:00 committed by Alexandre Julliard
parent c87fd4a65c
commit 4378d4b31e
3 changed files with 170 additions and 189 deletions

View File

@ -2487,13 +2487,8 @@ ULONG WINAPI D3D7CB_DestroySwapChain(IWineD3DSwapChain *pSwapChain) {
static HRESULT ddraw_create_surface(IDirectDrawImpl *This, DDSURFACEDESC2 *pDDSD,
IDirectDrawSurfaceImpl **ppSurf, UINT level)
{
HRESULT hr;
UINT Width, Height;
WINED3DFORMAT Format = WINED3DFMT_UNKNOWN;
DWORD Usage = 0;
WINED3DSURFTYPE ImplType = This->ImplType;
WINED3DSURFACE_DESC Desc;
WINED3DPOOL Pool = WINED3DPOOL_DEFAULT;
HRESULT hr;
if (TRACE_ON(ddraw))
{
@ -2556,57 +2551,6 @@ static HRESULT ddraw_create_surface(IDirectDrawImpl *This, DDSURFACEDESC2 *pDDSD
}
}
if (!(pDDSD->ddsCaps.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY)) &&
!((pDDSD->ddsCaps.dwCaps & DDSCAPS_TEXTURE) && (pDDSD->ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE)) )
{
/* Tests show surfaces without memory flags get these flags added right after creation. */
pDDSD->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY;
}
/* Get the correct wined3d usage */
if (pDDSD->ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE |
DDSCAPS_3DDEVICE ) )
{
Usage |= WINED3DUSAGE_RENDERTARGET;
pDDSD->ddsCaps.dwCaps |= DDSCAPS_VISIBLE;
}
if (pDDSD->ddsCaps.dwCaps & (DDSCAPS_OVERLAY))
{
Usage |= WINED3DUSAGE_OVERLAY;
}
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
* Stencil surface.
*/
Usage |= WINED3DUSAGE_DEPTHSTENCIL;
}
if(pDDSD->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
{
Pool = WINED3DPOOL_SYSTEMMEM;
}
else if(pDDSD->ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE)
{
Pool = WINED3DPOOL_MANAGED;
/* Managed textures have the system memory flag set */
pDDSD->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
}
else if(pDDSD->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
{
/* Videomemory adds localvidmem, this is mutually exclusive with systemmemory
* and texturemanage
*/
pDDSD->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM;
}
Format = PixelFormat_DD2WineD3D(&pDDSD->u4.ddpfPixelFormat);
if(Format == WINED3DFMT_UNKNOWN)
{
ERR("Unsupported / Unknown pixelformat\n");
return DDERR_INVALIDPIXELFORMAT;
}
/* Create the Surface object */
*ppSurf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectDrawSurfaceImpl));
if(!*ppSurf)
@ -2614,41 +2558,12 @@ static HRESULT ddraw_create_surface(IDirectDrawImpl *This, DDSURFACEDESC2 *pDDSD
ERR("(%p) Error allocating memory for a surface\n", This);
return DDERR_OUTOFVIDEOMEMORY;
}
(*ppSurf)->lpVtbl = &IDirectDrawSurface7_Vtbl;
(*ppSurf)->IDirectDrawSurface3_vtbl = &IDirectDrawSurface3_Vtbl;
(*ppSurf)->IDirectDrawGammaControl_vtbl = &IDirectDrawGammaControl_Vtbl;
(*ppSurf)->IDirect3DTexture2_vtbl = &IDirect3DTexture2_Vtbl;
(*ppSurf)->IDirect3DTexture_vtbl = &IDirect3DTexture1_Vtbl;
(*ppSurf)->ref = 1;
(*ppSurf)->version = 7;
TRACE("%p->version = %d\n", (*ppSurf), (*ppSurf)->version);
(*ppSurf)->ddraw = This;
(*ppSurf)->surface_desc.dwSize = sizeof(DDSURFACEDESC2);
(*ppSurf)->surface_desc.u4.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
DD_STRUCT_COPY_BYSIZE(&(*ppSurf)->surface_desc, pDDSD);
/* Surface attachments */
(*ppSurf)->next_attached = NULL;
(*ppSurf)->first_attached = *ppSurf;
/* Needed to re-create the surface on an implementation change */
(*ppSurf)->ImplType = ImplType;
/* For D3DDevice creation */
(*ppSurf)->isRenderTarget = FALSE;
/* A trace message for debugging */
TRACE("(%p) Created IDirectDrawSurface implementation structure at %p\n", This, *ppSurf);
/* Now create the WineD3D Surface */
hr = IWineD3DDevice_CreateSurface(This->wineD3DDevice, pDDSD->dwWidth, pDDSD->dwHeight, Format,
TRUE /* Lockable */, FALSE /* Discard */, level, &(*ppSurf)->WineD3DSurface,
Usage, Pool, WINED3DMULTISAMPLE_NONE, 0 /* MultiSampleQuality */, ImplType,
(IUnknown *)*ppSurf, &ddraw_null_wined3d_parent_ops);
if(hr != D3D_OK)
hr = ddraw_surface_init(*ppSurf, This, pDDSD, level, ImplType);
if (FAILED(hr))
{
ERR("IWineD3DDevice::CreateSurface failed. hr = %08x\n", hr);
WARN("Failed to initialize surface, hr %#x.\n", hr);
HeapFree(GetProcessHeap(), 0, *ppSurf);
return hr;
}
@ -2656,93 +2571,7 @@ static HRESULT ddraw_create_surface(IDirectDrawImpl *This, DDSURFACEDESC2 *pDDSD
InterlockedIncrement(&This->surfaces);
list_add_head(&This->surface_list, &(*ppSurf)->surface_list_entry);
/* Here we could store all created surfaces in the DirectDrawImpl structure,
* But this could also be delegated to WineDDraw, as it keeps track of all its
* resources. Not implemented for now, as there are more important things ;)
*/
/* Get the pixel format of the WineD3DSurface and store it.
* Don't use the Format choosen above, WineD3D might have
* changed it
*/
(*ppSurf)->surface_desc.dwFlags |= DDSD_PIXELFORMAT;
hr = IWineD3DSurface_GetDesc((*ppSurf)->WineD3DSurface, &Desc);
if(hr != D3D_OK)
{
ERR("IWineD3DSurface::GetDesc failed\n");
IDirectDrawSurface7_Release( (IDirectDrawSurface7 *) *ppSurf);
return hr;
}
Format = Desc.format;
Width = Desc.width;
Height = Desc.height;
if(Format == WINED3DFMT_UNKNOWN)
{
FIXME("IWineD3DSurface::GetDesc returned WINED3DFMT_UNKNOWN\n");
}
PixelFormat_WineD3DtoDD( &(*ppSurf)->surface_desc.u4.ddpfPixelFormat, Format);
/* Anno 1602 stores the pitch right after surface creation, so make sure it's there.
* I can't LockRect() the surface here because if OpenGL surfaces are in use, the
* WineD3DDevice might not be usable for 3D yet, so an extra method was created.
* TODO: Test other fourcc formats
*/
if(Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5)
{
(*ppSurf)->surface_desc.dwFlags |= DDSD_LINEARSIZE;
if(Format == WINED3DFMT_DXT1)
{
(*ppSurf)->surface_desc.u1.dwLinearSize = max(4, Width) * max(4, Height) / 2;
}
else
{
(*ppSurf)->surface_desc.u1.dwLinearSize = max(4, Width) * max(4, Height);
}
}
else
{
(*ppSurf)->surface_desc.dwFlags |= DDSD_PITCH;
(*ppSurf)->surface_desc.u1.lPitch = IWineD3DSurface_GetPitch((*ppSurf)->WineD3DSurface);
}
/* Application passed a color key? Set it! */
if(pDDSD->dwFlags & DDSD_CKDESTOVERLAY)
{
IWineD3DSurface_SetColorKey((*ppSurf)->WineD3DSurface,
DDCKEY_DESTOVERLAY,
(WINEDDCOLORKEY *) &pDDSD->u3.ddckCKDestOverlay);
}
if(pDDSD->dwFlags & DDSD_CKDESTBLT)
{
IWineD3DSurface_SetColorKey((*ppSurf)->WineD3DSurface,
DDCKEY_DESTBLT,
(WINEDDCOLORKEY *) &pDDSD->ddckCKDestBlt);
}
if(pDDSD->dwFlags & DDSD_CKSRCOVERLAY)
{
IWineD3DSurface_SetColorKey((*ppSurf)->WineD3DSurface,
DDCKEY_SRCOVERLAY,
(WINEDDCOLORKEY *) &pDDSD->ddckCKSrcOverlay);
}
if(pDDSD->dwFlags & DDSD_CKSRCBLT)
{
IWineD3DSurface_SetColorKey((*ppSurf)->WineD3DSurface,
DDCKEY_SRCBLT,
(WINEDDCOLORKEY *) &pDDSD->ddckCKSrcBlt);
}
if ( pDDSD->dwFlags & DDSD_LPSURFACE)
{
hr = IWineD3DSurface_SetMem((*ppSurf)->WineD3DSurface, pDDSD->lpSurface);
if(hr != WINED3D_OK)
{
/* No need for a trace here, wined3d does that for us */
IDirectDrawSurface7_Release((IDirectDrawSurface7 *)*ppSurf);
return hr;
}
}
TRACE("Created surface %p.\n", *ppSurf);
return DD_OK;
}

View File

@ -271,14 +271,9 @@ struct IDirectDrawSurfaceImpl
DWORD Handle;
};
/* VTable declaration. It's located in surface.c / surface_thunks.c */
extern const IDirectDrawSurface7Vtbl IDirectDrawSurface7_Vtbl DECLSPEC_HIDDEN;
extern const IDirectDrawSurface3Vtbl IDirectDrawSurface3_Vtbl DECLSPEC_HIDDEN;
extern const IDirectDrawGammaControlVtbl IDirectDrawGammaControl_Vtbl DECLSPEC_HIDDEN;
extern const IDirect3DTexture2Vtbl IDirect3DTexture2_Vtbl DECLSPEC_HIDDEN;
extern const IDirect3DTextureVtbl IDirect3DTexture1_Vtbl DECLSPEC_HIDDEN;
void ddraw_surface_destroy(IDirectDrawSurfaceImpl *surface) DECLSPEC_HIDDEN;
HRESULT ddraw_surface_init(IDirectDrawSurfaceImpl *surface, IDirectDrawImpl *ddraw,
DDSURFACEDESC2 *desc, UINT mip_level, WINED3DSURFTYPE surface_type) DECLSPEC_HIDDEN;
static inline IDirectDrawSurfaceImpl *surface_from_texture1(IDirect3DTexture *iface)
{

View File

@ -3347,7 +3347,7 @@ static HRESULT WINAPI d3d_texture1_Load(IDirect3DTexture *iface, IDirect3DTextur
* The VTable
*****************************************************************************/
const IDirectDrawSurface7Vtbl IDirectDrawSurface7_Vtbl =
static const struct IDirectDrawSurface7Vtbl ddraw_surface7_vtbl =
{
/* IUnknown */
ddraw_surface7_QueryInterface,
@ -3406,7 +3406,7 @@ const IDirectDrawSurface7Vtbl IDirectDrawSurface7_Vtbl =
ddraw_surface7_GetLOD,
};
const IDirectDrawSurface3Vtbl IDirectDrawSurface3_Vtbl =
static const struct IDirectDrawSurface3Vtbl ddraw_surface3_vtbl =
{
/* IUnknown */
ddraw_surface3_QueryInterface,
@ -3454,7 +3454,7 @@ const IDirectDrawSurface3Vtbl IDirectDrawSurface3_Vtbl =
ddraw_surface3_SetSurfaceDesc,
};
const IDirectDrawGammaControlVtbl IDirectDrawGammaControl_Vtbl =
static const struct IDirectDrawGammaControlVtbl ddraw_gamma_control_vtbl =
{
ddraw_gamma_control_QueryInterface,
ddraw_gamma_control_AddRef,
@ -3463,7 +3463,7 @@ const IDirectDrawGammaControlVtbl IDirectDrawGammaControl_Vtbl =
ddraw_gamma_control_SetGammaRamp,
};
const IDirect3DTexture2Vtbl IDirect3DTexture2_Vtbl =
static const struct IDirect3DTexture2Vtbl d3d_texture2_vtbl =
{
d3d_texture2_QueryInterface,
d3d_texture2_AddRef,
@ -3473,7 +3473,7 @@ const IDirect3DTexture2Vtbl IDirect3DTexture2_Vtbl =
d3d_texture2_Load,
};
const IDirect3DTextureVtbl IDirect3DTexture1_Vtbl =
static const struct IDirect3DTextureVtbl d3d_texture1_vtbl =
{
d3d_texture1_QueryInterface,
d3d_texture1_AddRef,
@ -3484,3 +3484,160 @@ const IDirect3DTextureVtbl IDirect3DTexture1_Vtbl =
d3d_texture1_Load,
d3d_texture1_Unload,
};
HRESULT ddraw_surface_init(IDirectDrawSurfaceImpl *surface, IDirectDrawImpl *ddraw,
DDSURFACEDESC2 *desc, UINT mip_level, WINED3DSURFTYPE surface_type)
{
WINED3DPOOL pool = WINED3DPOOL_DEFAULT;
WINED3DSURFACE_DESC wined3d_desc;
WINED3DFORMAT format;
DWORD usage = 0;
HRESULT hr;
if (!(desc->ddsCaps.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY))
&& !((desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE)
&& (desc->ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE)))
{
/* Tests show surfaces without memory flags get these flags added
* right after creation. */
desc->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY;
}
if (desc->ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE))
{
usage |= WINED3DUSAGE_RENDERTARGET;
desc->ddsCaps.dwCaps |= DDSCAPS_VISIBLE;
}
if (desc->ddsCaps.dwCaps & (DDSCAPS_OVERLAY))
{
usage |= WINED3DUSAGE_OVERLAY;
}
if (ddraw->depthstencil || (desc->ddsCaps.dwCaps & DDSCAPS_ZBUFFER))
{
/* The depth stencil creation callback sets this flag. Set the
* wined3d usage to let it know it's a depth/stencil surface. */
usage |= WINED3DUSAGE_DEPTHSTENCIL;
}
if (desc->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
{
pool = WINED3DPOOL_SYSTEMMEM;
}
else if (desc->ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE)
{
pool = WINED3DPOOL_MANAGED;
/* Managed textures have the system memory flag set. */
desc->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
}
else if (desc->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
{
/* Videomemory adds localvidmem. This is mutually exclusive with
* systemmemory and texturemanage. */
desc->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM;
}
format = PixelFormat_DD2WineD3D(&desc->u4.ddpfPixelFormat);
if (format == WINED3DFMT_UNKNOWN)
{
WARN("Unsupported / unknown pixelformat.\n");
return DDERR_INVALIDPIXELFORMAT;
}
surface->lpVtbl = &ddraw_surface7_vtbl;
surface->IDirectDrawSurface3_vtbl = &ddraw_surface3_vtbl;
surface->IDirectDrawGammaControl_vtbl = &ddraw_gamma_control_vtbl;
surface->IDirect3DTexture2_vtbl = &d3d_texture2_vtbl;
surface->IDirect3DTexture_vtbl = &d3d_texture1_vtbl;
surface->ref = 1;
surface->version = 7;
surface->ddraw = ddraw;
surface->surface_desc.dwSize = sizeof(DDSURFACEDESC2);
surface->surface_desc.u4.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
DD_STRUCT_COPY_BYSIZE(&surface->surface_desc, desc);
surface->first_attached = surface;
surface->ImplType = surface_type;
hr = IWineD3DDevice_CreateSurface(ddraw->wineD3DDevice, desc->dwWidth, desc->dwHeight, format,
TRUE /* Lockable */, FALSE /* Discard */, mip_level, &surface->WineD3DSurface,
usage, pool, WINED3DMULTISAMPLE_NONE, 0 /* MultiSampleQuality */, surface_type,
(IUnknown *)surface, &ddraw_null_wined3d_parent_ops);
if (FAILED(hr))
{
WARN("Failed to create wined3d surface, hr %#x.\n", hr);
return hr;
}
surface->surface_desc.dwFlags |= DDSD_PIXELFORMAT;
hr = IWineD3DSurface_GetDesc(surface->WineD3DSurface, &wined3d_desc);
if (FAILED(hr))
{
ERR("Failed to get wined3d surface desc, hr %#x.\n", hr);
IWineD3DSurface_Release(surface->WineD3DSurface);
return hr;
}
format = wined3d_desc.format;
if (format == WINED3DFMT_UNKNOWN)
{
FIXME("IWineD3DSurface::GetDesc returned WINED3DFMT_UNKNOWN.\n");
}
PixelFormat_WineD3DtoDD(&surface->surface_desc.u4.ddpfPixelFormat, format);
/* Anno 1602 stores the pitch right after surface creation, so make sure
* it's there. TODO: Test other fourcc formats. */
if (format == WINED3DFMT_DXT1 || format == WINED3DFMT_DXT2 || format == WINED3DFMT_DXT3
|| format == WINED3DFMT_DXT4 || format == WINED3DFMT_DXT5)
{
surface->surface_desc.dwFlags |= DDSD_LINEARSIZE;
if (format == WINED3DFMT_DXT1)
{
surface->surface_desc.u1.dwLinearSize = max(4, wined3d_desc.width) * max(4, wined3d_desc.height) / 2;
}
else
{
surface->surface_desc.u1.dwLinearSize = max(4, wined3d_desc.width) * max(4, wined3d_desc.height);
}
}
else
{
surface->surface_desc.dwFlags |= DDSD_PITCH;
surface->surface_desc.u1.lPitch = IWineD3DSurface_GetPitch(surface->WineD3DSurface);
}
if (desc->dwFlags & DDSD_CKDESTOVERLAY)
{
IWineD3DSurface_SetColorKey(surface->WineD3DSurface,
DDCKEY_DESTOVERLAY, (WINEDDCOLORKEY *)&desc->u3.ddckCKDestOverlay);
}
if (desc->dwFlags & DDSD_CKDESTBLT)
{
IWineD3DSurface_SetColorKey(surface->WineD3DSurface,
DDCKEY_DESTBLT, (WINEDDCOLORKEY *)&desc->ddckCKDestBlt);
}
if (desc->dwFlags & DDSD_CKSRCOVERLAY)
{
IWineD3DSurface_SetColorKey(surface->WineD3DSurface,
DDCKEY_SRCOVERLAY, (WINEDDCOLORKEY *)&desc->ddckCKSrcOverlay);
}
if (desc->dwFlags & DDSD_CKSRCBLT)
{
IWineD3DSurface_SetColorKey(surface->WineD3DSurface,
DDCKEY_SRCBLT, (WINEDDCOLORKEY *)&desc->ddckCKSrcBlt);
}
if (desc->dwFlags & DDSD_LPSURFACE)
{
hr = IWineD3DSurface_SetMem(surface->WineD3DSurface, desc->lpSurface);
if (FAILED(hr))
{
ERR("Failed to set surface memory, hr %#x.\n", hr);
IWineD3DSurface_Release(surface->WineD3DSurface);
return hr;
}
}
return DD_OK;
}