From 17d92f3b8f508a37163c8d0e91c456594c17f3f2 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=B3zef=20Kucia?= Date: Tue, 31 Jul 2012 15:26:39 +0200 Subject: [PATCH] d3dx9: Implement rendering to cube textures in ID3DXRenderToEnvMap. --- dlls/d3dx9_36/render.c | 187 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 180 insertions(+), 7 deletions(-) diff --git a/dlls/d3dx9_36/render.c b/dlls/d3dx9_36/render.c index 97a29164772..cca6b44734b 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; -- 2.11.4.GIT