[3/5] d3dx9: Implement rendering to cube textures in ID3DXRenderToEnvMap.

Józef Kucia joseph.kucia at gmail.com
Tue Jul 31 08:26:39 CDT 2012


---
 dlls/d3dx9_36/render.c |  187 ++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 180 insertions(+), 7 deletions(-)

diff --git a/dlls/d3dx9_36/render.c b/dlls/d3dx9_36/render.c
index 97a2916..cca6b44 100644
--- a/dlls/d3dx9_36/render.c
+++ b/dlls/d3dx9_36/render.c
@@ -416,6 +416,14 @@ HRESULT WINAPI D3DXCreateRenderToSurface(IDirect3DDevice9 *device,
 }
 
 
+enum render_state
+{
+    INITIAL,
+
+    CUBE_BEGIN,
+    CUBE_FACE
+};
+
 struct render_to_envmap
 {
     ID3DXRenderToEnvMap ID3DXRenderToEnvMap_iface;
@@ -423,8 +431,33 @@ struct render_to_envmap
 
     IDirect3DDevice9 *device;
     D3DXRTE_DESC desc;
+
+    enum render_state state;
+    struct device_state previous_device_state;
+
+    D3DCUBEMAP_FACES face;
+    DWORD filter;
+
+    IDirect3DSurface9 *render_target;
+    IDirect3DSurface9 *depth_stencil;
+
+    IDirect3DCubeTexture9 *dst_cube_texture;
 };
 
+static void copy_render_target_to_cube_texture_face(IDirect3DCubeTexture9 *cube_texture,
+        D3DCUBEMAP_FACES face, IDirect3DSurface9 *render_target, DWORD filter)
+{
+    HRESULT hr;
+    IDirect3DSurface9 *cube_surface;
+
+    IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture, face, 0, &cube_surface);
+
+    hr = D3DXLoadSurfaceFromSurface(cube_surface, NULL, NULL, render_target, NULL, NULL, filter, 0);
+    if (FAILED(hr)) ERR("Copying render target data to surface failed %#x\n", hr);
+
+    IDirect3DSurface9_Release(cube_surface);
+}
+
 static inline struct render_to_envmap *impl_from_ID3DXRenderToEnvMap(ID3DXRenderToEnvMap *iface)
 {
     return CONTAINING_RECORD(iface, struct render_to_envmap, ID3DXRenderToEnvMap_iface);
@@ -469,6 +502,13 @@ static ULONG WINAPI D3DXRenderToEnvMap_Release(ID3DXRenderToEnvMap *iface)
 
     if (!ref)
     {
+        if (render->dst_cube_texture) IDirect3DSurface9_Release(render->dst_cube_texture);
+
+        if (render->render_target) IDirect3DSurface9_Release(render->render_target);
+        if (render->depth_stencil) IDirect3DSurface9_Release(render->depth_stencil);
+
+        device_state_release(&render->previous_device_state);
+
         IDirect3DDevice9_Release(render->device);
 
         HeapFree(GetProcessHeap(), 0, render);
@@ -507,8 +547,52 @@ static HRESULT WINAPI D3DXRenderToEnvMap_GetDesc(ID3DXRenderToEnvMap *iface,
 static HRESULT WINAPI D3DXRenderToEnvMap_BeginCube(ID3DXRenderToEnvMap *iface,
                                                    IDirect3DCubeTexture9 *texture)
 {
-    FIXME("(%p)->(%p): stub\n", iface, texture);
-    return E_NOTIMPL;
+    struct render_to_envmap *render = impl_from_ID3DXRenderToEnvMap(iface);
+    HRESULT hr;
+    D3DSURFACE_DESC level_desc;
+
+    TRACE("(%p)->(%p)\n", iface, texture);
+
+    if (!texture) return D3DERR_INVALIDCALL;
+
+    if (render->state != INITIAL) return D3DERR_INVALIDCALL;
+
+    IDirect3DCubeTexture9_GetLevelDesc(texture, 0, &level_desc);
+    if (level_desc.Format != render->desc.Format || level_desc.Width != render->desc.Size)
+        return D3DERR_INVALIDCALL;
+
+    if (!(level_desc.Usage & D3DUSAGE_RENDERTARGET))
+    {
+        hr = IDirect3DDevice9_CreateRenderTarget(render->device, level_desc.Width, level_desc.Height,
+                level_desc.Format, level_desc.MultiSampleType, level_desc.MultiSampleQuality,
+                TRUE, &render->render_target, NULL);
+        if (FAILED(hr)) goto cleanup;
+        IDirect3DCubeTexture9_GetLevelDesc(texture, 0, &level_desc);
+    }
+
+    if (render->desc.DepthStencil)
+    {
+        hr = IDirect3DDevice9_CreateDepthStencilSurface(render->device, level_desc.Width, level_desc.Height,
+                render->desc.DepthStencilFormat, level_desc.MultiSampleType, level_desc.MultiSampleQuality,
+                TRUE, &render->depth_stencil, NULL);
+        if (FAILED(hr)) goto cleanup;
+    }
+
+    IDirect3DCubeTexture9_AddRef(texture);
+    render->dst_cube_texture = texture;
+    render->state = CUBE_BEGIN;
+    return D3D_OK;
+
+cleanup:
+    if (render->dst_cube_texture) IDirect3DSurface9_Release(render->dst_cube_texture);
+    render->dst_cube_texture = NULL;
+
+    if (render->render_target) IDirect3DSurface9_Release(render->render_target);
+    render->render_target = NULL;
+    if (render->depth_stencil) IDirect3DSurface9_Release(render->depth_stencil);
+    render->depth_stencil = NULL;
+
+    return hr;
 }
 
 static HRESULT WINAPI D3DXRenderToEnvMap_BeginSphere(ID3DXRenderToEnvMap *iface,
@@ -538,17 +622,94 @@ static HRESULT WINAPI D3DXRenderToEnvMap_Face(ID3DXRenderToEnvMap *iface,
                                               D3DCUBEMAP_FACES face,
                                               DWORD filter)
 {
-    FIXME("(%p)->(%u, %#x): stub\n", iface, face, filter);
-    return E_NOTIMPL;
+    struct render_to_envmap *render = impl_from_ID3DXRenderToEnvMap(iface);
+    HRESULT hr;
+    unsigned int i;
+
+    TRACE("(%p)->(%u, %#x)\n", iface, face, filter);
+
+    if (render->state == CUBE_FACE)
+    {
+        IDirect3DDevice9_EndScene(render->device);
+        if (render->render_target)
+            copy_render_target_to_cube_texture_face(render->dst_cube_texture, render->face,
+                    render->render_target, render->filter);
+
+        device_state_restore(render->device, &render->previous_device_state);
+
+        render->state = CUBE_BEGIN;
+    }
+    else if (render->state != CUBE_BEGIN)
+        return D3DERR_INVALIDCALL;
+
+    device_state_capture(render->device, &render->previous_device_state);
+
+    for (i = 1; i < render->previous_device_state.num_render_targets; i++)
+        IDirect3DDevice9_SetRenderTarget(render->device, i, NULL);
+
+    if (!render->render_target)
+    {
+        IDirect3DSurface9 *render_target;
+        IDirect3DCubeTexture9_GetCubeMapSurface(render->dst_cube_texture, face, 0, &render_target);
+        hr = IDirect3DDevice9_SetRenderTarget(render->device, 0, render_target);
+        IDirect3DSurface9_Release(render_target);
+    }
+    else hr = IDirect3DDevice9_SetRenderTarget(render->device, 0, render->render_target);
+
+    if (FAILED(hr)) goto cleanup;
+
+    hr = IDirect3DDevice9_SetDepthStencilSurface(render->device, render->depth_stencil);
+    if (FAILED(hr)) goto cleanup;
+
+    render->state = CUBE_FACE;
+    render->face = face;
+    render->filter = filter;
+    return IDirect3DDevice9_BeginScene(render->device);
+
+cleanup:
+    device_state_restore(render->device, &render->previous_device_state);
+    return hr;
 }
 
 static HRESULT WINAPI D3DXRenderToEnvMap_End(ID3DXRenderToEnvMap *iface,
                                              DWORD filter)
 {
-    FIXME("(%p)->(%#x): stub\n", iface, filter);
-    return E_NOTIMPL;
-}
+    struct render_to_envmap *render = impl_from_ID3DXRenderToEnvMap(iface);
+
+    TRACE("(%p)->(%#x)\n", iface, filter);
 
+    if (render->state == INITIAL) return D3DERR_INVALIDCALL;
+
+    if (render->state == CUBE_FACE)
+    {
+        IDirect3DDevice9_EndScene(render->device);
+        if (render->render_target)
+            copy_render_target_to_cube_texture_face(render->dst_cube_texture, render->face,
+                    render->render_target, render->filter);
+
+        device_state_restore(render->device, &render->previous_device_state);
+    }
+
+    D3DXFilterTexture((IDirect3DBaseTexture9 *)render->dst_cube_texture, NULL, 0, filter);
+
+    if (render->render_target)
+    {
+        IDirect3DSurface9_Release(render->render_target);
+        render->render_target = NULL;
+    }
+
+    if (render->depth_stencil)
+    {
+        IDirect3DSurface9_Release(render->depth_stencil);
+        render->depth_stencil = NULL;
+    }
+
+    IDirect3DSurface9_Release(render->dst_cube_texture);
+    render->dst_cube_texture = NULL;
+
+    render->state = INITIAL;
+    return D3D_OK;
+}
 
 static HRESULT WINAPI D3DXRenderToEnvMap_OnLostDevice(ID3DXRenderToEnvMap *iface)
 {
@@ -613,6 +774,18 @@ HRESULT WINAPI D3DXCreateRenderToEnvMap(IDirect3DDevice9 *device,
     render->desc.DepthStencil = depth_stencil;
     render->desc.DepthStencilFormat = depth_stencil_format;
 
+    render->state = INITIAL;
+    render->render_target = NULL;
+    render->depth_stencil = NULL;
+    render->dst_cube_texture = NULL;
+
+    hr = device_state_init(device, &render->previous_device_state);
+    if (FAILED(hr))
+    {
+        HeapFree(GetProcessHeap(), 0, render);
+        return hr;
+    }
+
     IDirect3DDevice9_AddRef(device);
     render->device = device;
 
-- 
1.7.8.6




More information about the wine-patches mailing list