std::shared_ptr<DepthStencilStateProvider> D3DGraphicContextProvider::create_depth_stencil_state(const DepthStencilStateDescription &desc)
{
	std::map<DepthStencilStateDescription, std::shared_ptr<DepthStencilStateProvider> >::iterator it = depth_stencil_states.find(desc);
	if (it != depth_stencil_states.end())
	{
		return it->second;
	}
	else
	{
		std::shared_ptr<DepthStencilStateProvider> state(new D3DDepthStencilStateProvider(window->get_device(), desc));
		depth_stencil_states[desc.clone()] = state;
		return state;
	}
}
	std::shared_ptr<DepthStencilStateProvider> GL1GraphicContextProvider::create_depth_stencil_state(const DepthStencilStateDescription &desc)
	{
		auto it = depth_stencil_states.find(desc);
		if (it != depth_stencil_states.end())
		{
			return it->second;
		}
		else
		{
			std::shared_ptr<DepthStencilStateProvider> state(new OpenGLDepthStencilStateProvider(desc));
			depth_stencil_states[desc.clone()] = state;
			return state;
		}
	}
	D3DDepthStencilStateProvider::D3DDepthStencilStateProvider(const ComPtr<ID3D11Device> &device, const DepthStencilStateDescription &desc)
	{
		CompareFunction front, back;
		int front_ref, front_mask, back_ref, back_mask;
		desc.get_stencil_compare_front(front, front_ref, front_mask);
		desc.get_stencil_compare_back(back, back_ref, back_mask);

		unsigned char front_write_mask, back_write_mask;
		desc.get_stencil_write_mask(front_write_mask, back_write_mask);

		StencilOp fail_front, pass_depth_fail_front, pass_depth_pass_front;
		StencilOp fail_back, pass_depth_fail_back, pass_depth_pass_back;
		desc.get_stencil_op_front(fail_front, pass_depth_fail_front, pass_depth_pass_front);
		desc.get_stencil_op_back(fail_back, pass_depth_fail_back, pass_depth_pass_back);

		D3D11_DEPTH_STENCIL_DESC d3d_desc;
		d3d_desc.DepthEnable = desc.is_depth_test_enabled() ? TRUE : FALSE;
		d3d_desc.DepthWriteMask = desc.is_depth_write_enabled() ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
		d3d_desc.DepthFunc = to_d3d_compare_func(desc.get_depth_compare_function());
		d3d_desc.StencilEnable = desc.is_stencil_test_enabled();
		d3d_desc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK; // To do: should this use the write masks instead?
		d3d_desc.StencilWriteMask = front_write_mask | back_write_mask;
		d3d_desc.FrontFace.StencilFunc = to_d3d_compare_func(front);
		d3d_desc.FrontFace.StencilDepthFailOp = to_d3d_stencil_op(pass_depth_fail_front);
		d3d_desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
		d3d_desc.FrontFace.StencilFailOp = to_d3d_stencil_op(fail_front);
		d3d_desc.BackFace.StencilFunc = to_d3d_compare_func(back);
		d3d_desc.BackFace.StencilDepthFailOp = to_d3d_stencil_op(pass_depth_fail_back);
		d3d_desc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
		d3d_desc.BackFace.StencilFailOp = to_d3d_stencil_op(fail_back);

		HRESULT result = device->CreateDepthStencilState(&d3d_desc, state.output_variable());
		D3DTarget::throw_if_failed("D3D11Device.CreateDepthStencilState failed", result);

		// "The formats that support stenciling are DXGI_FORMAT_D24_UNORM_S8_UINT and DXGI_FORMAT_D32_FLOAT_S8X24_UINT."
	}