[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