[PATCH 3/5] ddraw: Create texture surfaces from device_parent_create_texture_surface().
Henri Verbeet
hverbeet at codeweavers.com
Fri Jul 13 05:53:09 CDT 2012
Instead of creating them in advance and hoping we can find them back later.
---
dlls/ddraw/ddraw.c | 246 ++++++++++++++++++--------------------------------
dlls/ddraw/surface.c | 39 ++++++++-
2 files changed, 124 insertions(+), 161 deletions(-)
diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c
index 838652f..2a44d1f 100644
--- a/dlls/ddraw/ddraw.c
+++ b/dlls/ddraw/ddraw.c
@@ -2639,71 +2639,6 @@ static HRESULT ddraw_create_surface(struct ddraw *ddraw, DDSURFACEDESC2 *pDDSD,
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: Whether the new surface is a root of a cube map face. This
- * creates an additional surface without the mipmapping flags
- *
- *****************************************************************************/
-static HRESULT CreateAdditionalSurfaces(struct ddraw *ddraw, struct ddraw_surface *root,
- UINT count, DDSURFACEDESC2 DDSD, BOOL CubeFaceRoot, UINT version)
-{
- struct ddraw_surface *last = root;
- UINT i, j, level = 0;
- HRESULT hr;
-
- for (i = 0; i < count; ++i)
- {
- struct ddraw_surface *object2 = NULL;
-
- /* increase the mipmap level, but only if a mipmap is created
- * In this case, also halve the size
- */
- if(DDSD.ddsCaps.dwCaps & DDSCAPS_MIPMAP && !CubeFaceRoot)
- {
- level++;
- 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 = ddraw_create_surface(ddraw, &DDSD, &object2, level, version);
- if(hr != DD_OK)
- {
- return hr;
- }
-
- /* Add the new surface to the complex attachment array */
- 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;
- }
- return DD_OK;
-}
static HRESULT CDECL ddraw_reset_enum_callback(struct wined3d_resource *resource)
{
@@ -2793,7 +2728,6 @@ static HRESULT CreateSurface(struct ddraw *ddraw, DDSURFACEDESC2 *DDSD,
struct ddraw_surface *object = NULL;
struct wined3d_display_mode mode;
HRESULT hr;
- LONG extra_surfaces = 0;
DDSURFACEDESC2 desc2;
const DWORD sysvidmem = DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
@@ -2984,7 +2918,6 @@ static HRESULT CreateSurface(struct ddraw *ddraw, DDSURFACEDESC2 *DDSD,
/* Not-complex mipmap -> Mipmapcount = 1 */
desc2.u2.dwMipMapCount = 1;
}
- extra_surfaces = desc2.u2.dwMipMapCount - 1;
/* There's a mipmap count in the created surface in any case */
desc2.dwFlags |= DDSD_MIPMAPCOUNT;
@@ -3046,46 +2979,39 @@ static HRESULT CreateSurface(struct ddraw *ddraw, DDSURFACEDESC2 *DDSD,
*/
if(DDSD->dwFlags & DDSD_BACKBUFFERCOUNT)
{
- extra_surfaces = DDSD->dwBackBufferCount;
+ struct ddraw_surface *last = object;
+ UINT i;
+
desc2.ddsCaps.dwCaps &= ~DDSCAPS_FRONTBUFFER; /* It's not a front buffer */
desc2.ddsCaps.dwCaps |= DDSCAPS_BACKBUFFER;
desc2.dwBackBufferCount = 0;
- }
- hr = DD_OK;
- if(desc2.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
- {
- desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_ALLFACES;
- desc2.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEZ;
- hr |= CreateAdditionalSurfaces(ddraw, object, extra_surfaces + 1, desc2, TRUE, version);
- desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_NEGATIVEZ;
- desc2.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEZ;
- hr |= CreateAdditionalSurfaces(ddraw, object, extra_surfaces + 1, desc2, TRUE, version);
- desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_POSITIVEZ;
- desc2.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEY;
- hr |= CreateAdditionalSurfaces(ddraw, object, extra_surfaces + 1, desc2, TRUE, version);
- desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_NEGATIVEY;
- desc2.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEY;
- hr |= CreateAdditionalSurfaces(ddraw, object, extra_surfaces + 1, desc2, TRUE, version);
- desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_POSITIVEY;
- desc2.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEX;
- hr |= CreateAdditionalSurfaces(ddraw, object, extra_surfaces + 1, desc2, TRUE, version);
- desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_NEGATIVEX;
- desc2.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEX;
- }
+ for (i = 0; i < DDSD->dwBackBufferCount; ++i)
+ {
+ struct ddraw_surface *object2 = NULL;
- hr |= CreateAdditionalSurfaces(ddraw, object, extra_surfaces, desc2, FALSE, version);
- if(hr != DD_OK)
- {
- /* This destroys and possibly created surfaces too */
- if (version == 7)
- IDirectDrawSurface7_Release(&object->IDirectDrawSurface7_iface);
- else if (version == 4)
- IDirectDrawSurface4_Release(&object->IDirectDrawSurface4_iface);
- else
- IDirectDrawSurface_Release(&object->IDirectDrawSurface_iface);
+ if (FAILED(hr = ddraw_create_surface(ddraw, &desc2, &object2, 0, version)))
+ {
+ if (version == 7)
+ IDirectDrawSurface7_Release(&object->IDirectDrawSurface7_iface);
+ else if (version == 4)
+ IDirectDrawSurface4_Release(&object->IDirectDrawSurface4_iface);
+ else
+ IDirectDrawSurface_Release(&object->IDirectDrawSurface_iface);
- return hr;
+ return hr;
+ }
+
+ /* Add the new surface to the complex attachment array. */
+ last->complex_array[0] = object2;
+ 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. */
+ desc2.ddsCaps.dwCaps &= ~DDSCAPS_BACKBUFFER;
+ }
}
if (desc2.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
@@ -5360,72 +5286,76 @@ static HRESULT CDECL device_parent_create_texture_surface(struct wined3d_device_
void *container_parent, UINT width, UINT height, enum wined3d_format_id format, DWORD usage,
enum wined3d_pool pool, UINT level, enum wined3d_cubemap_face face, struct wined3d_surface **surface)
{
+ struct ddraw *ddraw = ddraw_from_device_parent(device_parent);
struct ddraw_surface *tex_root = container_parent;
- struct ddraw_surface *surf = NULL;
- DDSCAPS2 searchcaps;
- UINT i = 0;
+ DDSURFACEDESC2 desc = tex_root->surface_desc;
+ struct ddraw_surface *ddraw_surface;
+ HRESULT hr;
TRACE("device_parent %p, container_parent %p, width %u, height %u, format %#x, usage %#x,\n"
"\tpool %#x, level %u, face %u, surface %p.\n",
device_parent, container_parent, width, height, format, usage, pool, level, face, surface);
- searchcaps = tex_root->surface_desc.ddsCaps;
- searchcaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_ALLFACES;
- switch (face)
+ /* The ddraw root surface is created before the wined3d texture. */
+ if (!level && face == WINED3D_CUBEMAP_FACE_POSITIVE_X)
{
- case WINED3D_CUBEMAP_FACE_POSITIVE_X:
- TRACE("Asked for positive x\n");
- if (searchcaps.dwCaps2 & DDSCAPS2_CUBEMAP)
- {
- searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEX;
- }
- surf = tex_root; break;
- case WINED3D_CUBEMAP_FACE_NEGATIVE_X:
- TRACE("Asked for negative x\n");
- searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEX; break;
- case WINED3D_CUBEMAP_FACE_POSITIVE_Y:
- TRACE("Asked for positive y\n");
- searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEY; break;
- case WINED3D_CUBEMAP_FACE_NEGATIVE_Y:
- TRACE("Asked for negative y\n");
- searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEY; break;
- case WINED3D_CUBEMAP_FACE_POSITIVE_Z:
- TRACE("Asked for positive z\n");
- searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEZ; break;
- case WINED3D_CUBEMAP_FACE_NEGATIVE_Z:
- TRACE("Asked for negative z\n");
- searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEZ; break;
- default:
- ERR("Unexpected cube face.\n");
- }
-
- if (!surf)
- {
- IDirectDrawSurface7 *attached;
- IDirectDrawSurface7_GetAttachedSurface(&tex_root->IDirectDrawSurface7_iface, &searchcaps, &attached);
- surf = unsafe_impl_from_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(&surf->IDirectDrawSurface7_iface, &searchcaps, &attached);
- if(!attached) ERR("Surface not found\n");
- surf = impl_from_IDirectDrawSurface7(attached);
- IDirectDrawSurface7_Release(attached);
- ++i;
- }
-
- /* Return the surface */
- *surface = surf->wined3d_surface;
- wined3d_surface_incref(*surface);
+ ddraw_surface = tex_root;
+ goto done;
+ }
- TRACE("Returning wineD3DSurface %p, it belongs to surface %p\n", *surface, surf);
+ desc.dwWidth = width;
+ desc.dwHeight = height;
+ if (level)
+ desc.ddsCaps.dwCaps2 |= DDSCAPS2_MIPMAPSUBLEVEL;
+ else
+ desc.ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL;
- return D3D_OK;
+ if (desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
+ {
+ desc.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_ALLFACES;
+
+ switch (face)
+ {
+ case WINED3D_CUBEMAP_FACE_POSITIVE_X:
+ desc.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEX;
+ break;
+
+ case WINED3D_CUBEMAP_FACE_NEGATIVE_X:
+ desc.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEX;
+ break;
+
+ case WINED3D_CUBEMAP_FACE_POSITIVE_Y:
+ desc.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEY;
+ break;
+
+ case WINED3D_CUBEMAP_FACE_NEGATIVE_Y:
+ desc.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEY;
+ break;
+
+ case WINED3D_CUBEMAP_FACE_POSITIVE_Z:
+ desc.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEZ;
+ break;
+
+ case WINED3D_CUBEMAP_FACE_NEGATIVE_Z:
+ desc.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEZ;
+ break;
+
+ default:
+ ERR("Unexpected cube face.\n");
+ return DDERR_INVALIDPARAMS;
+ }
+
+ }
+
+ /* FIXME: Validate that format, usage, pool, etc. really make sense. */
+ if (FAILED(hr = ddraw_create_surface(ddraw, &desc, &ddraw_surface, 0, tex_root->version)))
+ return hr;
+
+done:
+ *surface = ddraw_surface->wined3d_surface;
+ wined3d_surface_incref(*surface);
+
+ return DD_OK;
}
static void STDMETHODCALLTYPE ddraw_frontbuffer_destroyed(void *parent)
diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c
index bb594be..2357790 100644
--- a/dlls/ddraw/surface.c
+++ b/dlls/ddraw/surface.c
@@ -5590,15 +5590,23 @@ static const struct wined3d_parent_ops ddraw_texture_wined3d_parent_ops =
HRESULT ddraw_surface_create_texture(struct ddraw_surface *surface)
{
const DDSURFACEDESC2 *desc = &surface->surface_desc;
+ struct ddraw_surface *mip, **attach;
+ struct wined3d_resource *resource;
enum wined3d_format_id format;
+ UINT layers, levels, i, j;
enum wined3d_pool pool;
- UINT levels;
+ HRESULT hr;
if (desc->ddsCaps.dwCaps & DDSCAPS_MIPMAP)
levels = desc->u2.dwMipMapCount;
else
levels = 1;
+ if (desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
+ layers = 6;
+ else
+ layers = 1;
+
/* DDSCAPS_SYSTEMMEMORY textures are in WINED3D_POOL_SYSTEM_MEM.
* Should I forward the MANAGED cap to the managed pool? */
if (desc->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
@@ -5608,11 +5616,36 @@ HRESULT ddraw_surface_create_texture(struct ddraw_surface *surface)
format = PixelFormat_DD2WineD3D(&surface->surface_desc.u4.ddpfPixelFormat);
if (desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
- return wined3d_texture_create_cube(surface->ddraw->wined3d_device, desc->dwWidth,
+ hr = wined3d_texture_create_cube(surface->ddraw->wined3d_device, desc->dwWidth,
levels, 0, format, pool, surface, &ddraw_texture_wined3d_parent_ops, &surface->wined3d_texture);
else
- return wined3d_texture_create_2d(surface->ddraw->wined3d_device, desc->dwWidth, desc->dwHeight,
+ hr = wined3d_texture_create_2d(surface->ddraw->wined3d_device, desc->dwWidth, desc->dwHeight,
levels, 0, format, pool, surface, &ddraw_texture_wined3d_parent_ops, &surface->wined3d_texture);
+
+ if (FAILED(hr))
+ {
+ WARN("Failed to create wined3d texture, hr %#x.\n", hr);
+ return hr;
+ }
+
+ for (i = 0; i < layers; ++i)
+ {
+ attach = &surface->complex_array[layers - 1 - i];
+
+ for (j = 0; j < levels; ++j)
+ {
+ resource = wined3d_texture_get_sub_resource(surface->wined3d_texture, i * levels + j);
+ mip = wined3d_resource_get_parent(resource);
+
+ if (mip == surface)
+ continue;
+
+ *attach = mip;
+ attach = &mip->complex_array[0];
+ }
+ }
+
+ return DD_OK;
}
HRESULT ddraw_surface_init(struct ddraw_surface *surface, struct ddraw *ddraw,
--
1.7.8.6
More information about the wine-patches
mailing list