1
0
mirror of https://github.com/borgesdan/xn65 synced 2024-12-29 21:54:47 +01:00

294 lines
7.6 KiB
C++

#include "xna/xna-dx.hpp"
#include "xna/game/gdevicemanager.hpp"
namespace xna {
static void reset(GraphicsDevice::PlatformImplementation& impl)
{
if (impl._device) {
impl._device->Release();
impl._device = nullptr;
}
if (impl._context) {
impl._context->Release();
impl._context = nullptr;
}
if (impl._factory) {
impl._factory->Release();
impl._factory = nullptr;
}
}
static void createDevice(GraphicsDevice::PlatformImplementation& impl) {
//
// See ref
//
// D3D_DRIVER_TYPE
// https://learn.microsoft.com/en-us/windows/win32/api/d3dcommon/ne-d3dcommon-d3d_driver_type
//
// D3D11CreateDevice function
// https://learn.microsoft.com/en-us/windows/win32/api/d3d11/nf-d3d11-d3d11createdevice
//
auto createDeviceFlags = 0;
#if _DEBUG
createDeviceFlags = D3D11_CREATE_DEVICE_FLAG::D3D11_CREATE_DEVICE_DEBUG;
#endif
const auto& currentAdapter = impl._adapter;
const auto& pAdapter = GraphicsAdapter::UseNullDevice() ? NULL : currentAdapter->impl->dxAdapter.Get();
//
// if pAdapter is not NULL driverType must be D3D_DRIVER_TYPE_UNKNOWN
//
auto driverType = D3D_DRIVER_TYPE_UNKNOWN;
if (GraphicsAdapter::UseReferenceDevice())
driverType = D3D_DRIVER_TYPE_WARP;
else if (GraphicsAdapter::UseNullDevice())
driverType = D3D_DRIVER_TYPE_HARDWARE;
auto hr = D3D11CreateDevice(
//_In_opt_ IDXGIAdapter* pAdapter,
pAdapter,
//D3D_DRIVER_TYPE DriverType,
driverType,
//HMODULE Software,
NULL,
//UINT Flags,
createDeviceFlags,
//_In_reads_opt_( FeatureLevels ) CONST D3D_FEATURE_LEVEL* pFeatureLevels,
impl.featureLevels,
//UINT FeatureLevels,
7,
//UINT SDKVersion,
D3D11_SDK_VERSION,
//_COM_Outptr_opt_ ID3D11Device** ppDevice
impl._device.GetAddressOf(),
//_Out_opt_ D3D_FEATURE_LEVEL* pFeatureLevel,
&impl.currentFeatureLevel,
//_COM_Outptr_opt_ ID3D11DeviceContext** ppImmediateContext
impl._context.GetAddressOf());
if FAILED(hr)
Exception::Throw(Exception::FAILED_TO_CREATE);
}
static void initAndApplyState(GraphicsDevice::PlatformImplementation& impl, PGraphicsDevice const& device) {
impl._blendState->Bind(device);
impl._blendState->Initialize();
impl._blendState->Apply();
impl._rasterizerState->Bind(device);
impl._rasterizerState->Initialize();
impl._rasterizerState->Apply();
impl._depthStencilState->Bind(device);
impl._depthStencilState->Initialize();
impl._depthStencilState->Apply();
impl._samplerStates->Apply(*device);
}
GraphicsDevice::GraphicsDevice() {
impl = unew<PlatformImplementation>();
impl->_adapter = GraphicsAdapter::DefaultAdapter();
}
GraphicsDevice::GraphicsDevice(GraphicsDeviceInformation const& info) {
impl = unew<PlatformImplementation>();
impl->_adapter = info.Adapter;
impl->_presentationParameters = info.PresentParameters;
}
GraphicsDevice::GraphicsDevice(sptr<GraphicsAdapter> const& adapter, GraphicsProfile const& graphicsProfile, sptr<PresentationParameters> const& presentationParameters) {
impl = unew<PlatformImplementation>();
impl->_adapter = adapter;
impl->_presentationParameters = presentationParameters;
}
bool GraphicsDevice::Initialize() {
auto _this = shared_from_this();
if (!impl)
impl = uptr<PlatformImplementation>();
reset(*impl);
createDevice(*impl);
auto hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)&impl->_factory);
if FAILED(hr)
Exception::Throw(Exception::FAILED_TO_CREATE);
//const auto bounds = impl->_gameWindow->ClientBounds();
impl->_viewport = xna::Viewport(0.0F, 0.0F,
impl->_presentationParameters->BackBufferWidth,
impl->_presentationParameters->BackBufferHeight,
0.0F, 1.F);
//COLORREF color = impl->_gameWindow->impl->Color();
const auto backColor = Colors::CornflowerBlue;
const auto backColorV3 = backColor.ToVector3();
impl->_backgroundColor[0] = backColorV3.X;
impl->_backgroundColor[1] = backColorV3.Y;
impl->_backgroundColor[2] = backColorV3.Z;
impl->_backgroundColor[3] = 1.0f;
impl->_swapChain = snew<xna::SwapChain>(_this);
impl->_swapChain->Initialize();
auto hwnd = reinterpret_cast<HWND>(impl->_presentationParameters->DeviceWindowHandle);
hr = impl->_factory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_ALT_ENTER);
if (FAILED(hr))
Exception::Throw(Exception::FAILED_TO_MAKE_WINDOW_ASSOCIATION);
impl->_renderTarget2D = snew<RenderTarget2D>(_this);
if (!impl->_renderTarget2D->Initialize())
return false;
impl->_renderTarget2D->Apply();
D3D11_VIEWPORT view{};
view.TopLeftX = impl->_viewport.X;
view.TopLeftY = impl->_viewport.Y;
view.Width = impl->_viewport.Width;
view.Height = impl->_viewport.Height;
view.MinDepth = impl->_viewport.MinDetph;
view.MaxDepth = impl->_viewport.MaxDepth;
impl->_context->RSSetViewports(1, &view);
initAndApplyState(*impl, _this);
return true;
}
bool GraphicsDevice::Present() {
if (!impl) return false;
const auto result = impl->_swapChain->Present(impl->_usevsync);
impl->_context->OMSetRenderTargets(
1,
impl->_renderTarget2D->render_impl->_renderTargetView.GetAddressOf(),
nullptr);
return result;
}
void GraphicsDevice::Clear(Color const& color) {
if (!impl) return;
const auto v4 = color.ToVector4();
impl->_backgroundColor[0] = v4.X;
impl->_backgroundColor[1] = v4.Y;
impl->_backgroundColor[2] = v4.Z;
impl->_backgroundColor[3] = v4.W;
impl->_context->ClearRenderTargetView(
impl->_renderTarget2D->render_impl->_renderTargetView.Get(),
impl->_backgroundColor);
}
void GraphicsDevice::Clear(ClearOptions options, Color const& color, float depth, Int stencil) {
if (!impl) return;
switch (options)
{
case xna::ClearOptions::DepthBuffer:
Exception::Throw(Exception::NOT_IMPLEMENTED);
break;
case xna::ClearOptions::Stencil:
Exception::Throw(Exception::NOT_IMPLEMENTED);
break;
case xna::ClearOptions::Target:
Clear(color);
break;
default:
return;
}
}
void GraphicsDevice::Clear(ClearOptions options, Vector4 const& color, float depth, Int stencil) {
if (!impl) return;
}
sptr<GraphicsAdapter> GraphicsDevice::Adapter() const {
if (!impl) return nullptr;
return impl->_adapter;
}
xna::Viewport GraphicsDevice::Viewport() const {
if (!impl) return {};
return impl->_viewport;
}
void GraphicsDevice::Viewport(xna::Viewport const& viewport) {
if (!impl) return;
impl->_viewport = viewport;
}
void GraphicsDevice::UseVSync(bool use) {
if (!impl) return;
impl->_usevsync = use;
}
sptr<xna::BlendState> GraphicsDevice::BlendState() const {
return impl->_blendState;
}
void GraphicsDevice::BlendState(sptr<xna::BlendState> const& value) {
impl->_blendState = value;
}
sptr<xna::DepthStencilState> GraphicsDevice::DepthStencilState() const {
return impl->_depthStencilState;
}
void GraphicsDevice::DepthStencilState(sptr<xna::DepthStencilState> const& value) {
impl->_depthStencilState = value;
}
sptr<xna::RasterizerState> GraphicsDevice::RasterizerState() const {
return impl->_rasterizerState;
}
void GraphicsDevice::RasterizerState(sptr<xna::RasterizerState> const& value) {
impl->_rasterizerState = value;
}
sptr<SamplerStateCollection> GraphicsDevice::SamplerStates() const {
return impl->_samplerStates;
}
Int GraphicsDevice::MultiSampleMask() const {
return impl->_multiSampleMask;
}
void GraphicsDevice::MultiSampleMask(Int value) {
impl->_multiSampleMask = value;
}
void GraphicsDevice::Reset(sptr<PresentationParameters> const& presentationParameters, sptr<GraphicsAdapter> const& graphicsAdapter){
impl = unew<PlatformImplementation>();
impl->_adapter = graphicsAdapter;
impl->_presentationParameters = presentationParameters;
Initialize();
}
}