1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#include "RenderAPI/BsBlendState.h"
4#include "Managers/BsRenderStateManager.h"
5#include "RenderAPI/BsRenderAPI.h"
6#include "Private/RTTI/BsBlendStateRTTI.h"
7#include "Resources/BsResources.h"
8
9namespace bs
10{
11 bool RENDER_TARGET_BLEND_STATE_DESC::operator == (const RENDER_TARGET_BLEND_STATE_DESC& rhs) const
12 {
13 return blendEnable == rhs.blendEnable &&
14 srcBlend == rhs.srcBlend &&
15 dstBlend == rhs.dstBlend &&
16 blendOp == rhs.blendOp &&
17 srcBlendAlpha == rhs.srcBlendAlpha &&
18 dstBlendAlpha == rhs.dstBlendAlpha &&
19 blendOpAlpha == rhs.blendOpAlpha &&
20 renderTargetWriteMask == rhs.renderTargetWriteMask;
21 }
22
23 bool BLEND_STATE_DESC::operator == (const BLEND_STATE_DESC& rhs) const
24 {
25 bool equals = alphaToCoverageEnable == rhs.alphaToCoverageEnable &&
26 independantBlendEnable == rhs.independantBlendEnable;
27
28 if (equals)
29 {
30 for (UINT32 i = 0; i < BS_MAX_MULTIPLE_RENDER_TARGETS; i++)
31 {
32 equals &= renderTargetDesc[i] == rhs.renderTargetDesc[i];
33 }
34 }
35
36 return equals;
37 }
38
39 BlendProperties::BlendProperties(const BLEND_STATE_DESC& desc)
40 :mData(desc), mHash(BlendState::generateHash(desc))
41 { }
42
43 bool BlendProperties::getBlendEnabled(UINT32 renderTargetIdx) const
44 {
45 assert(renderTargetIdx < BS_MAX_MULTIPLE_RENDER_TARGETS);
46
47 return mData.renderTargetDesc[renderTargetIdx].blendEnable;
48 }
49
50 BlendFactor BlendProperties::getSrcBlend(UINT32 renderTargetIdx) const
51 {
52 assert(renderTargetIdx < BS_MAX_MULTIPLE_RENDER_TARGETS);
53
54 return mData.renderTargetDesc[renderTargetIdx].srcBlend;
55 }
56
57 BlendFactor BlendProperties::getDstBlend(UINT32 renderTargetIdx) const
58 {
59 assert(renderTargetIdx < BS_MAX_MULTIPLE_RENDER_TARGETS);
60
61 return mData.renderTargetDesc[renderTargetIdx].dstBlend;
62 }
63
64 BlendOperation BlendProperties::getBlendOperation(UINT32 renderTargetIdx) const
65 {
66 assert(renderTargetIdx < BS_MAX_MULTIPLE_RENDER_TARGETS);
67
68 return mData.renderTargetDesc[renderTargetIdx].blendOp;
69 }
70
71 BlendFactor BlendProperties::getAlphaSrcBlend(UINT32 renderTargetIdx) const
72 {
73 assert(renderTargetIdx < BS_MAX_MULTIPLE_RENDER_TARGETS);
74
75 return mData.renderTargetDesc[renderTargetIdx].srcBlendAlpha;
76 }
77
78 BlendFactor BlendProperties::getAlphaDstBlend(UINT32 renderTargetIdx) const
79 {
80 assert(renderTargetIdx < BS_MAX_MULTIPLE_RENDER_TARGETS);
81
82 return mData.renderTargetDesc[renderTargetIdx].dstBlendAlpha;
83 }
84
85 BlendOperation BlendProperties::getAlphaBlendOperation(UINT32 renderTargetIdx) const
86 {
87 assert(renderTargetIdx < BS_MAX_MULTIPLE_RENDER_TARGETS);
88
89 return mData.renderTargetDesc[renderTargetIdx].blendOpAlpha;
90 }
91
92 UINT8 BlendProperties::getRenderTargetWriteMask(UINT32 renderTargetIdx) const
93 {
94 assert(renderTargetIdx < BS_MAX_MULTIPLE_RENDER_TARGETS);
95
96 return mData.renderTargetDesc[renderTargetIdx].renderTargetWriteMask;
97 }
98
99 BlendState::BlendState(const BLEND_STATE_DESC& desc)
100 :mProperties(desc), mId(0)
101 { }
102
103 BlendState::~BlendState()
104 {
105
106 }
107
108 SPtr<ct::BlendState> BlendState::getCore() const
109 {
110 return std::static_pointer_cast<ct::BlendState>(mCoreSpecific);
111 }
112
113 SPtr<ct::CoreObject> BlendState::createCore() const
114 {
115 SPtr<ct::BlendState> core = ct::RenderStateManager::instance()._createBlendState(mProperties.mData);
116 mId = core->getId(); // Accessing core from sim thread is okay here since core ID is immutable
117
118 return core;
119 }
120
121 const BlendProperties& BlendState::getProperties() const
122 {
123 return mProperties;
124 }
125
126 const SPtr<BlendState>& BlendState::getDefault()
127 {
128 return RenderStateManager::instance().getDefaultBlendState();
129 }
130
131 SPtr<BlendState> BlendState::create(const BLEND_STATE_DESC& desc)
132 {
133 return RenderStateManager::instance().createBlendState(desc);
134 }
135
136 UINT64 BlendState::generateHash(const BLEND_STATE_DESC& desc)
137 {
138 size_t hash = 0;
139 bs_hash_combine(hash, desc.alphaToCoverageEnable);
140 bs_hash_combine(hash, desc.independantBlendEnable);
141
142 for (UINT32 i = 0; i < BS_MAX_MULTIPLE_RENDER_TARGETS; i++)
143 {
144 bs_hash_combine(hash, desc.renderTargetDesc[i].blendEnable);
145 bs_hash_combine(hash, (UINT32)desc.renderTargetDesc[i].srcBlend);
146 bs_hash_combine(hash, (UINT32)desc.renderTargetDesc[i].dstBlend);
147 bs_hash_combine(hash, (UINT32)desc.renderTargetDesc[i].blendOp);
148 bs_hash_combine(hash, (UINT32)desc.renderTargetDesc[i].srcBlendAlpha);
149 bs_hash_combine(hash, (UINT32)desc.renderTargetDesc[i].dstBlendAlpha);
150 bs_hash_combine(hash, (UINT32)desc.renderTargetDesc[i].blendOpAlpha);
151 bs_hash_combine(hash, desc.renderTargetDesc[i].renderTargetWriteMask);
152 }
153
154 return (UINT64)hash;
155 }
156
157 /************************************************************************/
158 /* RTTI */
159 /************************************************************************/
160
161 RTTITypeBase* BlendState::getRTTIStatic()
162 {
163 return BlendStateRTTI::instance();
164 }
165
166 RTTITypeBase* BlendState::getRTTI() const
167 {
168 return BlendState::getRTTIStatic();
169 }
170
171 namespace ct
172 {
173 BlendState::BlendState(const BLEND_STATE_DESC& desc, UINT32 id)
174 :mProperties(desc), mId(id)
175 {
176
177 }
178
179 BlendState::~BlendState()
180 {
181
182 }
183
184 void BlendState::initialize()
185 {
186 // Since we cache states it's possible this object was already initialized
187 // (i.e. multiple sim-states can share a single core-state)
188 if (isInitialized())
189 return;
190
191 createInternal();
192 CoreObject::initialize();
193 }
194
195 const BlendProperties& BlendState::getProperties() const
196 {
197 return mProperties;
198 }
199
200 SPtr<BlendState> BlendState::create(const BLEND_STATE_DESC& desc)
201 {
202 return RenderStateManager::instance().createBlendState(desc);
203 }
204
205 const SPtr<BlendState>& BlendState::getDefault()
206 {
207 return RenderStateManager::instance().getDefaultBlendState();
208 }
209 }
210}