d3dx9: Implement rendering to cube textures in ID3DXRenderToEnvMap.
This commit is contained in:
parent
8c4adc0617
commit
17d92f3b8f
|
@ -416,6 +416,14 @@ HRESULT WINAPI D3DXCreateRenderToSurface(IDirect3DDevice9 *device,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum render_state
|
||||||
|
{
|
||||||
|
INITIAL,
|
||||||
|
|
||||||
|
CUBE_BEGIN,
|
||||||
|
CUBE_FACE
|
||||||
|
};
|
||||||
|
|
||||||
struct render_to_envmap
|
struct render_to_envmap
|
||||||
{
|
{
|
||||||
ID3DXRenderToEnvMap ID3DXRenderToEnvMap_iface;
|
ID3DXRenderToEnvMap ID3DXRenderToEnvMap_iface;
|
||||||
|
@ -423,8 +431,33 @@ struct render_to_envmap
|
||||||
|
|
||||||
IDirect3DDevice9 *device;
|
IDirect3DDevice9 *device;
|
||||||
D3DXRTE_DESC desc;
|
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)
|
static inline struct render_to_envmap *impl_from_ID3DXRenderToEnvMap(ID3DXRenderToEnvMap *iface)
|
||||||
{
|
{
|
||||||
return CONTAINING_RECORD(iface, struct render_to_envmap, 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 (!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);
|
IDirect3DDevice9_Release(render->device);
|
||||||
|
|
||||||
HeapFree(GetProcessHeap(), 0, render);
|
HeapFree(GetProcessHeap(), 0, render);
|
||||||
|
@ -507,8 +547,52 @@ static HRESULT WINAPI D3DXRenderToEnvMap_GetDesc(ID3DXRenderToEnvMap *iface,
|
||||||
static HRESULT WINAPI D3DXRenderToEnvMap_BeginCube(ID3DXRenderToEnvMap *iface,
|
static HRESULT WINAPI D3DXRenderToEnvMap_BeginCube(ID3DXRenderToEnvMap *iface,
|
||||||
IDirect3DCubeTexture9 *texture)
|
IDirect3DCubeTexture9 *texture)
|
||||||
{
|
{
|
||||||
FIXME("(%p)->(%p): stub\n", iface, texture);
|
struct render_to_envmap *render = impl_from_ID3DXRenderToEnvMap(iface);
|
||||||
return E_NOTIMPL;
|
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,
|
static HRESULT WINAPI D3DXRenderToEnvMap_BeginSphere(ID3DXRenderToEnvMap *iface,
|
||||||
|
@ -538,17 +622,94 @@ static HRESULT WINAPI D3DXRenderToEnvMap_Face(ID3DXRenderToEnvMap *iface,
|
||||||
D3DCUBEMAP_FACES face,
|
D3DCUBEMAP_FACES face,
|
||||||
DWORD filter)
|
DWORD filter)
|
||||||
{
|
{
|
||||||
FIXME("(%p)->(%u, %#x): stub\n", iface, face, filter);
|
struct render_to_envmap *render = impl_from_ID3DXRenderToEnvMap(iface);
|
||||||
return E_NOTIMPL;
|
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,
|
static HRESULT WINAPI D3DXRenderToEnvMap_End(ID3DXRenderToEnvMap *iface,
|
||||||
DWORD filter)
|
DWORD filter)
|
||||||
{
|
{
|
||||||
FIXME("(%p)->(%#x): stub\n", iface, filter);
|
struct render_to_envmap *render = impl_from_ID3DXRenderToEnvMap(iface);
|
||||||
return E_NOTIMPL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
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)
|
static HRESULT WINAPI D3DXRenderToEnvMap_OnLostDevice(ID3DXRenderToEnvMap *iface)
|
||||||
{
|
{
|
||||||
|
@ -613,6 +774,18 @@ HRESULT WINAPI D3DXCreateRenderToEnvMap(IDirect3DDevice9 *device,
|
||||||
render->desc.DepthStencil = depth_stencil;
|
render->desc.DepthStencil = depth_stencil;
|
||||||
render->desc.DepthStencilFormat = depth_stencil_format;
|
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);
|
IDirect3DDevice9_AddRef(device);
|
||||||
render->device = device;
|
render->device = device;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue