diff --git a/framework/graphics/blendstate.hpp b/framework/graphics/blendstate.hpp index 6baa4c9..0aa64b5 100644 --- a/framework/graphics/blendstate.hpp +++ b/framework/graphics/blendstate.hpp @@ -1,9 +1,7 @@ #ifndef XNA_GRAPHICS_BLENDSTATE_HPP #define XNA_GRAPHICS_BLENDSTATE_HPP -#include "../types.hpp" -#include "../forward.hpp" -#include "../enums.hpp" +#include "../default.hpp" namespace xna { struct BlendRenderTarget { @@ -24,13 +22,17 @@ namespace xna { class IBlendState { public: virtual ~IBlendState() {} + virtual bool Initialize(GraphicsDevice& device, xna_error_nullarg) = 0; + virtual void AlphaToCoverageEnable(bool value) = 0; + virtual void IndependentBlendEnable(bool value) = 0; + virtual void RenderTargets(std::vector const& value) = 0; + + virtual bool Apply(GraphicsDevice& device, xna_error_nullarg) = 0; static PBlendState Opaque(); static PBlendState AlphaBlend(); static PBlendState Additive(); static PBlendState NonPremultiplied(); - - virtual bool Apply(GraphicsDevice* device) = 0; }; } diff --git a/framework/platform/blendstate-dx.cpp b/framework/platform/blendstate-dx.cpp index e7fa87c..d6a369f 100644 --- a/framework/platform/blendstate-dx.cpp +++ b/framework/platform/blendstate-dx.cpp @@ -2,81 +2,80 @@ #include "device-dx.hpp" namespace xna { - BlendState::BlendState(GraphicsDevice* device) { - _device = device; - } - - bool BlendState::Apply(GraphicsDevice* device) { - - D3D11_BLEND_DESC blendDesc{}; - blendDesc.AlphaToCoverageEnable = AlphaToCoverage; - blendDesc.IndependentBlendEnable = IndependentBlendEnable; - - for (size_t i = 0; i < 8; ++i) { - if (RenderTargets[i] == nullptr) - break; - - blendDesc.RenderTarget[0].BlendEnable = RenderTargets[0]->Enabled; - blendDesc.RenderTarget[0].SrcBlend = BlendMapper::ConvertBlend(RenderTargets[0]->Source); - blendDesc.RenderTarget[0].DestBlend = BlendMapper::ConvertBlend(RenderTargets[0]->Destination); - blendDesc.RenderTarget[0].BlendOp = BlendMapper::ConvertOperation(RenderTargets[0]->Operation); - blendDesc.RenderTarget[0].SrcBlendAlpha = BlendMapper::ConvertBlend(RenderTargets[0]->SourceAlpha); - blendDesc.RenderTarget[0].DestBlendAlpha = BlendMapper::ConvertBlend(RenderTargets[0]->DestinationAlpha); - blendDesc.RenderTarget[0].BlendOpAlpha = BlendMapper::ConvertOperation(RenderTargets[0]->OperationAlpha); - blendDesc.RenderTarget[0].RenderTargetWriteMask = BlendMapper::ConvertColorWrite(RenderTargets[0]->WriteMask); + bool BlendState::Initialize(GraphicsDevice& device, xna_error_ptr_arg) + { + if (!device._device) { + xna_error_apply(err, XnaErrorCode::ARGUMENT_IS_NULL); + return false; } - if (_device == nullptr || _device != device) - _device = device; + if (_blendState) { + _blendState->Release(); + _blendState = nullptr; + } - if FAILED(_device->_device->CreateBlendState(&blendDesc, &_blendState)) - return false; + const auto hr = device._device->CreateBlendState(&_description, &_blendState); - _device->_context->OMSetBlendState(_blendState, nullptr, 0xffffffff); + if (FAILED(hr)) { + xna_error_apply(err, XnaErrorCode::FAILED_OPERATION); + return false; + } + + return true; + } + + bool BlendState::Apply(GraphicsDevice& device, xna_error_ptr_arg) { + if (!device._context) { + xna_error_apply(err, XnaErrorCode::ARGUMENT_IS_NULL); + return false; + } + + if (!_blendState) { + const auto init = Initialize(device, err); + if (!init) return false; + } + + device._context->OMSetBlendState(_blendState, nullptr, 0xffffffff); return true; } PBlendState IBlendState::Opaque() { - auto blendState = New(nullptr); - blendState->RenderTargets[0] = New(); - blendState->RenderTargets[0]->Source = Blend::SourceAlpha; - blendState->RenderTargets[0]->SourceAlpha = Blend::SourceAlpha; - blendState->RenderTargets[0]->Destination = Blend::Zero; - blendState->RenderTargets[0]->DestinationAlpha = Blend::Zero; + auto blendState = New(); + blendState->_description.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; + blendState->_description.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA; + blendState->_description.RenderTarget[0].DestBlend = D3D11_BLEND_DEST_ALPHA; + blendState->_description.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; return blendState; } PBlendState IBlendState::AlphaBlend() { - auto blendState = New(nullptr); - blendState->RenderTargets[0] = New(); - blendState->RenderTargets[0]->Source = Blend::One; - blendState->RenderTargets[0]->SourceAlpha = Blend::One; - blendState->RenderTargets[0]->Destination = Blend::InverseSourceAlpha; - blendState->RenderTargets[0]->DestinationAlpha = Blend::InverseSourceAlpha; + auto blendState = New(); + blendState->_description.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE; + blendState->_description.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; + blendState->_description.RenderTarget[0].DestBlend = D3D11_BLEND_INV_DEST_ALPHA; + blendState->_description.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_DEST_ALPHA; return blendState; } PBlendState IBlendState::Additive() { - auto blendState = New(nullptr); - blendState->RenderTargets[0] = New(); - blendState->RenderTargets[0]->Source = Blend::SourceAlpha; - blendState->RenderTargets[0]->SourceAlpha = Blend::SourceAlpha; - blendState->RenderTargets[0]->Destination = Blend::One; - blendState->RenderTargets[0]->DestinationAlpha = Blend::One; + auto blendState = New(); + blendState->_description.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; + blendState->_description.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA; + blendState->_description.RenderTarget[0].DestBlend = D3D11_BLEND_ONE; + blendState->_description.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ONE; return blendState; } PBlendState IBlendState::NonPremultiplied() { - auto blendState = New(nullptr); - blendState->RenderTargets[0] = New(); - blendState->RenderTargets[0]->Source = Blend::SourceAlpha; - blendState->RenderTargets[0]->SourceAlpha = Blend::SourceAlpha; - blendState->RenderTargets[0]->Destination = Blend::InverseSourceAlpha; - blendState->RenderTargets[0]->DestinationAlpha = Blend::InverseSourceAlpha; + auto blendState = New(); + blendState->_description.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; + blendState->_description.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA; + blendState->_description.RenderTarget[0].DestBlend = D3D11_BLEND_INV_DEST_ALPHA; + blendState->_description.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_DEST_ALPHA; return blendState; } diff --git a/framework/platform/blendstate-dx.hpp b/framework/platform/blendstate-dx.hpp index 8a8f5e9..616ea4c 100644 --- a/framework/platform/blendstate-dx.hpp +++ b/framework/platform/blendstate-dx.hpp @@ -8,7 +8,7 @@ namespace xna { class BlendState : public IBlendState { public: - BlendState(GraphicsDevice* device); + BlendState() = default; virtual ~BlendState() override { if (_blendState) { @@ -16,21 +16,39 @@ namespace xna { _blendState = nullptr; } } + virtual bool Initialize(GraphicsDevice& device, xna_error_nullarg) override; + + virtual constexpr void AlphaToCoverageEnable(bool value) override { + _description.AlphaToCoverageEnable = value; + } - virtual bool Apply(GraphicsDevice* device) override; + virtual constexpr void IndependentBlendEnable(bool value) override { + _description.IndependentBlendEnable = value; + } + + virtual void RenderTargets(std::vector const& value) override { + for (size_t i = 0; i < value.size() && i < 8; ++i) { + _description.RenderTarget[i].BlendEnable = value[i].Enabled; + _description.RenderTarget[i].SrcBlend = ConvertBlend(value[i].Source); + _description.RenderTarget[i].DestBlend = ConvertBlend(value[i].Destination); + _description.RenderTarget[i].BlendOp = ConvertOperation(value[i].Operation); + _description.RenderTarget[i].SrcBlendAlpha = ConvertBlend(value[i].SourceAlpha); + _description.RenderTarget[i].DestBlendAlpha = ConvertBlend(value[i].DestinationAlpha); + _description.RenderTarget[i].BlendOpAlpha = ConvertOperation(value[i].OperationAlpha); + _description.RenderTarget[i].RenderTargetWriteMask = ConvertColorWrite(value[i].WriteMask); + } + } + + virtual bool Apply(GraphicsDevice& device, xna_error_nullarg) override; public: - ID3D11BlendState* _blendState{ nullptr }; - GraphicsDevice* _device{ nullptr }; - bool AlphaToCoverage{ false }; - bool IndependentBlendEnable{ false }; - PBlendRenderTarget RenderTargets[8]; - }; + ID3D11BlendState* _blendState{ nullptr }; + D3D11_BLEND_DESC _description{}; - struct BlendMapper { + public: static constexpr D3D11_BLEND ConvertBlend(Blend blend) { switch (blend) - { + { case xna::Blend::Zero: return D3D11_BLEND_ZERO; case xna::Blend::One: @@ -105,7 +123,7 @@ namespace xna { return D3D11_COLOR_WRITE_ENABLE_ALL; } } - }; + }; } #endif \ No newline at end of file diff --git a/framework/platform/device-dx.cpp b/framework/platform/device-dx.cpp index b016cf1..6fa9279 100644 --- a/framework/platform/device-dx.cpp +++ b/framework/platform/device-dx.cpp @@ -82,7 +82,7 @@ namespace xna { _context->RSSetViewports(1, &view); - _blendState->Apply(this); + _blendState->Apply(*this); return true; }