ddraw: Cube texture support.

This commit is contained in:
Stefan Dösinger 2007-04-27 13:50:42 +02:00 committed by Alexandre Julliard
parent 94b3fddec8
commit cdaf29f64e
1 changed files with 159 additions and 28 deletions

View File

@ -1597,17 +1597,57 @@ D3D7CB_CreateSurface(IUnknown *device,
HANDLE *SharedHandle)
{
ICOM_THIS_FROM(IDirectDrawImpl, IDirectDraw7, device);
IDirectDrawSurfaceImpl *surf = This->tex_root;
IDirectDrawSurfaceImpl *surf = NULL;
int i = 0;
TRACE("(%p) call back. surf=%p\n", device, surf);
DDSCAPS2 searchcaps = This->tex_root->surface_desc.ddsCaps;
TRACE("(%p) call back. surf=%p. Face %d level %d\n", device, This->tex_root, Face, level);
searchcaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_ALLFACES;
switch(Face)
{
case WINED3DCUBEMAP_FACE_POSITIVE_X:
TRACE("Asked for positive x\n");
if(searchcaps.dwCaps2 & DDSCAPS2_CUBEMAP) {
searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEX;
}
surf = This->tex_root; break;
case WINED3DCUBEMAP_FACE_NEGATIVE_X:
TRACE("Asked for negative x\n");
searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEX; break;
case WINED3DCUBEMAP_FACE_POSITIVE_Y:
TRACE("Asked for positive y\n");
searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEY; break;
case WINED3DCUBEMAP_FACE_NEGATIVE_Y:
TRACE("Asked for negative y\n");
searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEY; break;
case WINED3DCUBEMAP_FACE_POSITIVE_Z:
TRACE("Asked for positive z\n");
searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEZ; break;
case WINED3DCUBEMAP_FACE_NEGATIVE_Z:
TRACE("Asked for negative z\n");
searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEZ; break;
default: {ERR("Unexpected cube face\n");} /* Stupid compiler */
}
if(!surf)
{
IDirectDrawSurface7 *attached;
IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(This->tex_root, IDirectDrawSurface7),
&searchcaps,
&attached);
surf = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, attached);
IDirectDrawSurface7_Release(attached);
}
if(!surf) ERR("root search surface not found\n");
/* Find the wanted mipmap. There are enough mipmaps in the chain */
while(i < level)
{
IDirectDrawSurface7 *attached;
IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(surf, IDirectDrawSurface7),
&This->tex_root->surface_desc.ddsCaps,
&searchcaps,
&attached);
if(!attached) ERR("Surface not found\n");
surf = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, attached);
IDirectDrawSurface7_Release(attached);
i++;
@ -1728,7 +1768,7 @@ IDirectDrawImpl_CreateNewSurface(IDirectDrawImpl *This,
IDirectDrawImpl_RecreateAllSurfaces(This);
TRACE("(%p) Done recreating all surfaces\n", This);
}
else if(This->ImplType != SURFACE_OPENGL)
else if(This->ImplType != SURFACE_OPENGL && pDDSD->ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
{
WARN("The application requests a 3D capable surface, but a non-opengl surface was set in the registry\n");
/* Do not fail surface creation, only fail 3D device creation */
@ -1946,16 +1986,31 @@ IDirectDrawImpl_CreateNewSurface(IDirectDrawImpl *This,
return DD_OK;
}
/*****************************************************************************
* CreateAdditionalSurfaces
*
* Creates a new mipmap chain.
*
* Params:
* root: Root surface to attach the newly created chain to
* count: number of surfaces to create
* DDSD: Description of the surface. Intentionally not a pointer to avoid side
* effects on the caller
* CubeFaceRoot: Wether the new surface is a root of a cube map face. This
* creates an additional surface without the mipmapping flags
*
*****************************************************************************/
static HRESULT
CreateAdditionalSurfaces(IDirectDrawImpl *This,
IDirectDrawSurfaceImpl *root,
UINT count,
DDSURFACEDESC2 *DDSD)
DDSURFACEDESC2 DDSD,
BOOL CubeFaceRoot)
{
UINT i, level = 0;
UINT i, j, level = 0;
HRESULT hr;
IDirectDrawSurfaceImpl *last = root;
for(i = 0; i < count; i++)
{
IDirectDrawSurfaceImpl *object2 = NULL;
@ -1963,15 +2018,22 @@ CreateAdditionalSurfaces(IDirectDrawImpl *This,
/* increase the mipmap level, but only if a mipmap is created
* In this case, also halve the size
*/
if(DDSD->ddsCaps.dwCaps & DDSCAPS_MIPMAP)
if(DDSD.ddsCaps.dwCaps & DDSCAPS_MIPMAP && !CubeFaceRoot)
{
level++;
if(DDSD->dwWidth > 1) DDSD->dwWidth /= 2;
if(DDSD->dwHeight > 1) DDSD->dwHeight /= 2;
if(DDSD.dwWidth > 1) DDSD.dwWidth /= 2;
if(DDSD.dwHeight > 1) DDSD.dwHeight /= 2;
/* Set the mipmap sublevel flag according to msdn */
DDSD.ddsCaps.dwCaps2 |= DDSCAPS2_MIPMAPSUBLEVEL;
}
else
{
DDSD.ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL;
}
CubeFaceRoot = FALSE;
hr = IDirectDrawImpl_CreateNewSurface(This,
DDSD,
&DDSD,
&object2,
level);
if(hr != DD_OK)
@ -1980,14 +2042,19 @@ CreateAdditionalSurfaces(IDirectDrawImpl *This,
}
/* Add the new surface to the complex attachment array */
last->complex_array[0] = object2;
for(j = 0; j < MAX_COMPLEX_ATTACHED; j++)
{
if(last->complex_array[j]) continue;
last->complex_array[j] = object2;
break;
}
last = object2;
/* Remove the (possible) back buffer cap from the new surface description,
* because only one surface in the flipping chain is a back buffer, one
* is a front buffer, the others are just primary surfaces.
*/
DDSD->ddsCaps.dwCaps &= ~DDSCAPS_BACKBUFFER;
DDSD.ddsCaps.dwCaps &= ~DDSCAPS_BACKBUFFER;
}
return DD_OK;
}
@ -2135,6 +2202,30 @@ IDirectDrawImpl_CreateSurface(IDirectDraw7 *iface,
return E_POINTER; /* unchecked */
}
/* Check cube maps but only if the size includes them */
if (DDSD->dwSize >= sizeof(DDSURFACEDESC2))
{
if(DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES &&
!(DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
{
WARN("Cube map faces requested without cube map flag\n");
return DDERR_INVALIDCAPS;
}
if(DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP &&
(DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES) == 0)
{
WARN("Cube map without faces requested\n");
return DDERR_INVALIDPARAMS;
}
/* Quick tests confirm those can be created, but we don't do that yet */
if(DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP &&
(DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES) != DDSCAPS2_CUBEMAP_ALLFACES)
{
FIXME("Partial cube maps not supported yet\n");
}
}
/* According to the msdn this flag is ignored by CreateSurface */
if (DDSD->dwSize >= sizeof(DDSURFACEDESC2))
DDSD->ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL;
@ -2293,6 +2384,13 @@ IDirectDrawImpl_CreateSurface(IDirectDraw7 *iface,
desc2.ddsCaps.dwCaps |= DDSCAPS_FRONTBUFFER;
}
/* The root surface in a cube map is positive x */
if(desc2.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
{
desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_ALLFACES;
desc2.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEX;
}
/* Create the first surface */
hr = IDirectDrawImpl_CreateNewSurface(This, &desc2, &object, 0);
if( hr != DD_OK)
@ -2315,13 +2413,30 @@ IDirectDrawImpl_CreateSurface(IDirectDraw7 *iface,
desc2.ddsCaps.dwCaps &= ~DDSCAPS_FRONTBUFFER; /* It's not a front buffer */
desc2.ddsCaps.dwCaps |= DDSCAPS_BACKBUFFER;
}
/* Set the DDSCAPS2_MIPMAPSUBLEVEL flag on mipmap sublevels according to the msdn */
if(DDSD->ddsCaps.dwCaps & DDSCAPS_MIPMAP)
hr = DD_OK;
if(desc2.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
{
desc2.ddsCaps.dwCaps2 |= DDSCAPS2_MIPMAPSUBLEVEL;
desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_ALLFACES;
desc2.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEZ;
hr |= CreateAdditionalSurfaces(This, object, extra_surfaces + 1, desc2, TRUE);
desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_NEGATIVEZ;
desc2.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEZ;
hr |= CreateAdditionalSurfaces(This, object, extra_surfaces + 1, desc2, TRUE);
desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_POSITIVEZ;
desc2.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEY;
hr |= CreateAdditionalSurfaces(This, object, extra_surfaces + 1, desc2, TRUE);
desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_NEGATIVEY;
desc2.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEY;
hr |= CreateAdditionalSurfaces(This, object, extra_surfaces + 1, desc2, TRUE);
desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_POSITIVEY;
desc2.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEX;
hr |= CreateAdditionalSurfaces(This, object, extra_surfaces + 1, desc2, TRUE);
desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_NEGATIVEX;
desc2.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEX;
}
hr = CreateAdditionalSurfaces(This, object, extra_surfaces, &desc2);
hr |= CreateAdditionalSurfaces(This, object, extra_surfaces, desc2, FALSE);
if(hr != DD_OK)
{
/* This destroys and possibly created surfaces too */
@ -2370,7 +2485,7 @@ IDirectDrawImpl_CreateSurface(IDirectDraw7 *iface,
}
/* Create a WineD3DTexture if a texture was requested */
if(DDSD->ddsCaps.dwCaps & DDSCAPS_TEXTURE)
if(desc2.ddsCaps.dwCaps & DDSCAPS_TEXTURE)
{
UINT levels;
WINED3DFORMAT Format;
@ -2402,16 +2517,32 @@ IDirectDrawImpl_CreateSurface(IDirectDraw7 *iface,
/* The surfaces are already created, the callback only
* passes the IWineD3DSurface to WineD3D
*/
hr = IWineD3DDevice_CreateTexture( This->wineD3DDevice,
DDSD->dwWidth, DDSD->dwHeight,
levels, /* MipMapCount = Levels */
0, /* usage */
Format,
Pool,
(IWineD3DTexture **) &object->wineD3DTexture,
0, /* SharedHandle */
(IUnknown *) ICOM_INTERFACE(object, IDirectDrawSurface7),
D3D7CB_CreateSurface );
if(desc2.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
{
hr = IWineD3DDevice_CreateCubeTexture(This->wineD3DDevice,
DDSD->dwWidth, /* Edgelength */
levels,
0, /* usage */
Format,
Pool,
(IWineD3DCubeTexture **) &object->wineD3DTexture,
0, /* SharedHandle */
(IUnknown *) ICOM_INTERFACE(object, IDirectDrawSurface7),
D3D7CB_CreateSurface);
}
else
{
hr = IWineD3DDevice_CreateTexture(This->wineD3DDevice,
DDSD->dwWidth, DDSD->dwHeight,
levels, /* MipMapCount = Levels */
0, /* usage */
Format,
Pool,
(IWineD3DTexture **) &object->wineD3DTexture,
0, /* SharedHandle */
(IUnknown *) ICOM_INTERFACE(object, IDirectDrawSurface7),
D3D7CB_CreateSurface );
}
This->tex_root = NULL;
}