d3dx9: Implement rendering to cube textures in ID3DXRenderToEnvMap.

This commit is contained in:
Józef Kucia 2012-07-31 15:26:39 +02:00 committed by Alexandre Julliard
parent 8c4adc0617
commit 17d92f3b8f
1 changed files with 180 additions and 7 deletions

View File

@ -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;