RenderState.cpp 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223
  1. #include "Base.h"
  2. #include "RenderState.h"
  3. #include "Node.h"
  4. #include "Pass.h"
  5. #include "Technique.h"
  6. #include "Node.h"
  7. #include "Scene.h"
  8. // Render state override bits
  9. #define RS_BLEND 1
  10. #define RS_BLEND_FUNC 2
  11. #define RS_CULL_FACE 4
  12. #define RS_DEPTH_TEST 8
  13. #define RS_DEPTH_WRITE 16
  14. #define RS_DEPTH_FUNC 32
  15. #define RS_CULL_FACE_SIDE 64
  16. #define RS_STENCIL_TEST 128
  17. #define RS_STENCIL_WRITE 256
  18. #define RS_STENCIL_FUNC 512
  19. #define RS_STENCIL_OP 1024
  20. #define RS_FRONT_FACE 2048
  21. #define RS_ALL_ONES 0xFFFFFFFF
  22. namespace gameplay
  23. {
  24. RenderState::StateBlock* RenderState::StateBlock::_defaultState = NULL;
  25. std::vector<RenderState::ResolveAutoBindingCallback> RenderState::_customAutoBindingResolvers;
  26. RenderState::RenderState()
  27. : _nodeBinding(NULL), _state(NULL), _parent(NULL)
  28. {
  29. }
  30. RenderState::~RenderState()
  31. {
  32. SAFE_RELEASE(_state);
  33. // Destroy all the material parameters
  34. for (size_t i = 0, count = _parameters.size(); i < count; ++i)
  35. {
  36. SAFE_RELEASE(_parameters[i]);
  37. }
  38. }
  39. void RenderState::initialize()
  40. {
  41. if (StateBlock::_defaultState == NULL)
  42. {
  43. StateBlock::_defaultState = StateBlock::create();
  44. }
  45. }
  46. void RenderState::finalize()
  47. {
  48. SAFE_RELEASE(StateBlock::_defaultState);
  49. }
  50. void RenderState::registerAutoBindingResolver(ResolveAutoBindingCallback callback)
  51. {
  52. _customAutoBindingResolvers.push_back(callback);
  53. }
  54. MaterialParameter* RenderState::getParameter(const char* name) const
  55. {
  56. GP_ASSERT(name);
  57. // Search for an existing parameter with this name.
  58. MaterialParameter* param;
  59. for (size_t i = 0, count = _parameters.size(); i < count; ++i)
  60. {
  61. param = _parameters[i];
  62. GP_ASSERT(param);
  63. if (strcmp(param->getName(), name) == 0)
  64. {
  65. return param;
  66. }
  67. }
  68. // Create a new parameter and store it in our list.
  69. param = new MaterialParameter(name);
  70. _parameters.push_back(param);
  71. return param;
  72. }
  73. unsigned int RenderState::getParameterCount() const
  74. {
  75. return _parameters.size();
  76. }
  77. MaterialParameter* RenderState::getParameterByIndex(unsigned int index)
  78. {
  79. return _parameters[index];
  80. }
  81. void RenderState::addParameter(MaterialParameter* param)
  82. {
  83. _parameters.push_back(param);
  84. param->addRef();
  85. }
  86. void RenderState::removeParameter(const char* name)
  87. {
  88. for (size_t i = 0, count = _parameters.size(); i < count; ++i)
  89. {
  90. MaterialParameter* p = _parameters[i];
  91. if (p->_name == name)
  92. {
  93. _parameters.erase(_parameters.begin() + i);
  94. SAFE_RELEASE(p);
  95. break;
  96. }
  97. }
  98. }
  99. /**
  100. * @script{ignore}
  101. */
  102. const char* autoBindingToString(RenderState::AutoBinding autoBinding)
  103. {
  104. // NOTE: As new AutoBinding values are added, this switch statement must be updatd.
  105. switch (autoBinding)
  106. {
  107. case RenderState::NONE:
  108. return NULL;
  109. case RenderState::VIEW_MATRIX:
  110. return "VIEW_MATRIX";
  111. case RenderState::PROJECTION_MATRIX:
  112. return "PROJECTION_MATRIX";
  113. case RenderState::WORLD_VIEW_MATRIX:
  114. return "WORLD_VIEW_MATRIX";
  115. case RenderState::VIEW_PROJECTION_MATRIX:
  116. return "VIEW_PROJECTION_MATRIX";
  117. case RenderState::WORLD_VIEW_PROJECTION_MATRIX:
  118. return "WORLD_VIEW_PROJECTION_MATRIX";
  119. case RenderState::INVERSE_TRANSPOSE_WORLD_MATRIX:
  120. return "INVERSE_TRANSPOSE_WORLD_MATRIX";
  121. case RenderState::INVERSE_TRANSPOSE_WORLD_VIEW_MATRIX:
  122. return "INVERSE_TRANSPOSE_WORLD_VIEW_MATRIX";
  123. case RenderState::CAMERA_WORLD_POSITION:
  124. return "CAMERA_WORLD_POSITION";
  125. case RenderState::CAMERA_VIEW_POSITION:
  126. return "CAMERA_VIEW_POSITION";
  127. case RenderState::MATRIX_PALETTE:
  128. return "MATRIX_PALETTE";
  129. case RenderState::SCENE_AMBIENT_COLOR:
  130. return "SCENE_AMBIENT_COLOR";
  131. default:
  132. return "";
  133. }
  134. }
  135. void RenderState::setParameterAutoBinding(const char* name, AutoBinding autoBinding)
  136. {
  137. setParameterAutoBinding(name, autoBindingToString(autoBinding));
  138. }
  139. void RenderState::setParameterAutoBinding(const char* name, const char* autoBinding)
  140. {
  141. GP_ASSERT(name);
  142. GP_ASSERT(autoBinding);
  143. if (autoBinding == NULL)
  144. {
  145. // Remove an existing auto-binding
  146. std::map<std::string, std::string>::iterator itr = _autoBindings.find(name);
  147. if (itr != _autoBindings.end())
  148. _autoBindings.erase(itr);
  149. }
  150. else
  151. {
  152. // Add/update an auto-binding
  153. _autoBindings[name] = autoBinding;
  154. }
  155. // If we already have a node binding set, pass it to our handler now
  156. if (_nodeBinding)
  157. {
  158. applyAutoBinding(name, autoBinding);
  159. }
  160. }
  161. void RenderState::setStateBlock(StateBlock* state)
  162. {
  163. if (_state != state)
  164. {
  165. SAFE_RELEASE(_state);
  166. _state = state;
  167. if (_state)
  168. {
  169. _state->addRef();
  170. }
  171. }
  172. }
  173. RenderState::StateBlock* RenderState::getStateBlock() const
  174. {
  175. if (_state == NULL)
  176. {
  177. _state = StateBlock::create();
  178. }
  179. return _state;
  180. }
  181. void RenderState::setNodeBinding(Node* node)
  182. {
  183. if (_nodeBinding != node)
  184. {
  185. _nodeBinding = node;
  186. if (_nodeBinding)
  187. {
  188. // Apply all existing auto-bindings using this node.
  189. std::map<std::string, std::string>::const_iterator itr = _autoBindings.begin();
  190. while (itr != _autoBindings.end())
  191. {
  192. applyAutoBinding(itr->first.c_str(), itr->second.c_str());
  193. ++itr;
  194. }
  195. }
  196. }
  197. }
  198. void RenderState::applyAutoBinding(const char* uniformName, const char* autoBinding)
  199. {
  200. GP_ASSERT(_nodeBinding);
  201. MaterialParameter* param = getParameter(uniformName);
  202. GP_ASSERT(param);
  203. bool bound = false;
  204. // First attempt to resolve the binding using custom registered resolvers.
  205. if (_customAutoBindingResolvers.size() > 0)
  206. {
  207. for (size_t i = 0, count = _customAutoBindingResolvers.size(); i < count; ++i)
  208. {
  209. if (_customAutoBindingResolvers[i](autoBinding, _nodeBinding, param))
  210. {
  211. // Handled by custom auto binding resolver
  212. bound = true;
  213. break;
  214. }
  215. }
  216. }
  217. // Perform built-in resolution
  218. if (!bound)
  219. {
  220. bound = true;
  221. if (strcmp(autoBinding, "WORLD_MATRIX") == 0)
  222. {
  223. param->bindValue(this, &RenderState::autoBindingGetWorldMatrix);
  224. }
  225. else if (strcmp(autoBinding, "VIEW_MATRIX") == 0)
  226. {
  227. param->bindValue(this, &RenderState::autoBindingGetViewMatrix);
  228. }
  229. else if (strcmp(autoBinding, "PROJECTION_MATRIX") == 0)
  230. {
  231. param->bindValue(this, &RenderState::autoBindingGetProjectionMatrix);
  232. }
  233. else if (strcmp(autoBinding, "WORLD_VIEW_MATRIX") == 0)
  234. {
  235. param->bindValue(this, &RenderState::autoBindingGetWorldViewMatrix);
  236. }
  237. else if (strcmp(autoBinding, "VIEW_PROJECTION_MATRIX") == 0)
  238. {
  239. param->bindValue(this, &RenderState::autoBindingGetViewProjectionMatrix);
  240. }
  241. else if (strcmp(autoBinding, "WORLD_VIEW_PROJECTION_MATRIX") == 0)
  242. {
  243. param->bindValue(this, &RenderState::autoBindingGetWorldViewProjectionMatrix);
  244. }
  245. else if (strcmp(autoBinding, "INVERSE_TRANSPOSE_WORLD_MATRIX") == 0)
  246. {
  247. param->bindValue(this, &RenderState::autoBindingGetInverseTransposeWorldMatrix);
  248. }
  249. else if (strcmp(autoBinding, "INVERSE_TRANSPOSE_WORLD_VIEW_MATRIX") == 0)
  250. {
  251. param->bindValue(this, &RenderState::autoBindingGetInverseTransposeWorldViewMatrix);
  252. }
  253. else if (strcmp(autoBinding, "CAMERA_WORLD_POSITION") == 0)
  254. {
  255. param->bindValue(this, &RenderState::autoBindingGetCameraWorldPosition);
  256. }
  257. else if (strcmp(autoBinding, "CAMERA_VIEW_POSITION") == 0)
  258. {
  259. param->bindValue(this, &RenderState::autoBindingGetCameraViewPosition);
  260. }
  261. else if (strcmp(autoBinding, "MATRIX_PALETTE") == 0)
  262. {
  263. param->bindValue(this, &RenderState::autoBindingGetMatrixPalette, &RenderState::autoBindingGetMatrixPaletteSize);
  264. }
  265. else if (strcmp(autoBinding, "SCENE_AMBIENT_COLOR") == 0)
  266. {
  267. param->bindValue(this, &RenderState::autoBindingGetAmbientColor);
  268. }
  269. else
  270. {
  271. bound = false;
  272. GP_WARN("Unsupported auto binding type (%s).", autoBinding);
  273. }
  274. }
  275. if (bound)
  276. {
  277. // Mark parameter as an auto binding
  278. if (param->_type == MaterialParameter::METHOD && param->_value.method)
  279. param->_value.method->_autoBinding = true;
  280. }
  281. }
  282. const Matrix& RenderState::autoBindingGetWorldMatrix() const
  283. {
  284. return _nodeBinding ? _nodeBinding->getWorldMatrix() : Matrix::identity();
  285. }
  286. const Matrix& RenderState::autoBindingGetViewMatrix() const
  287. {
  288. return _nodeBinding ? _nodeBinding->getViewMatrix() : Matrix::identity();
  289. }
  290. const Matrix& RenderState::autoBindingGetProjectionMatrix() const
  291. {
  292. return _nodeBinding ? _nodeBinding->getProjectionMatrix() : Matrix::identity();
  293. }
  294. const Matrix& RenderState::autoBindingGetWorldViewMatrix() const
  295. {
  296. return _nodeBinding ? _nodeBinding->getWorldViewMatrix() : Matrix::identity();
  297. }
  298. const Matrix& RenderState::autoBindingGetViewProjectionMatrix() const
  299. {
  300. return _nodeBinding ? _nodeBinding->getViewProjectionMatrix() : Matrix::identity();
  301. }
  302. const Matrix& RenderState::autoBindingGetWorldViewProjectionMatrix() const
  303. {
  304. return _nodeBinding ? _nodeBinding->getWorldViewProjectionMatrix() : Matrix::identity();
  305. }
  306. const Matrix& RenderState::autoBindingGetInverseTransposeWorldMatrix() const
  307. {
  308. return _nodeBinding ? _nodeBinding->getInverseTransposeWorldMatrix() : Matrix::identity();
  309. }
  310. const Matrix& RenderState::autoBindingGetInverseTransposeWorldViewMatrix() const
  311. {
  312. return _nodeBinding ? _nodeBinding->getInverseTransposeWorldViewMatrix() : Matrix::identity();
  313. }
  314. Vector3 RenderState::autoBindingGetCameraWorldPosition() const
  315. {
  316. return _nodeBinding ? _nodeBinding->getActiveCameraTranslationWorld() : Vector3::zero();
  317. }
  318. Vector3 RenderState::autoBindingGetCameraViewPosition() const
  319. {
  320. return _nodeBinding ? _nodeBinding->getActiveCameraTranslationView() : Vector3::zero();
  321. }
  322. const Vector4* RenderState::autoBindingGetMatrixPalette() const
  323. {
  324. Model* model = _nodeBinding ? _nodeBinding->getModel() : NULL;
  325. MeshSkin* skin = model ? model->getSkin() : NULL;
  326. return skin ? skin->getMatrixPalette() : NULL;
  327. }
  328. unsigned int RenderState::autoBindingGetMatrixPaletteSize() const
  329. {
  330. Model* model = _nodeBinding ? _nodeBinding->getModel() : NULL;
  331. MeshSkin* skin = model ? model->getSkin() : NULL;
  332. return skin ? skin->getMatrixPaletteSize() : 0;
  333. }
  334. const Vector3& RenderState::autoBindingGetAmbientColor() const
  335. {
  336. Scene* scene = _nodeBinding ? _nodeBinding->getScene() : NULL;
  337. return scene ? scene->getAmbientColor() : Vector3::zero();
  338. }
  339. void RenderState::bind(Pass* pass)
  340. {
  341. GP_ASSERT(pass);
  342. // Get the combined modified state bits for our RenderState hierarchy.
  343. long stateOverrideBits = _state ? _state->_bits : 0;
  344. RenderState* rs = _parent;
  345. while (rs)
  346. {
  347. if (rs->_state)
  348. {
  349. stateOverrideBits |= rs->_state->_bits;
  350. }
  351. rs = rs->_parent;
  352. }
  353. // Restore renderer state to its default, except for explicitly specified states
  354. StateBlock::restore(stateOverrideBits);
  355. // Apply parameter bindings and renderer state for the entire hierarchy, top-down.
  356. rs = NULL;
  357. Effect* effect = pass->getEffect();
  358. while ((rs = getTopmost(rs)))
  359. {
  360. for (size_t i = 0, count = rs->_parameters.size(); i < count; ++i)
  361. {
  362. GP_ASSERT(rs->_parameters[i]);
  363. rs->_parameters[i]->bind(effect);
  364. }
  365. if (rs->_state)
  366. {
  367. rs->_state->bindNoRestore();
  368. }
  369. }
  370. }
  371. RenderState* RenderState::getTopmost(RenderState* below)
  372. {
  373. RenderState* rs = this;
  374. if (rs == below)
  375. {
  376. // Nothing below ourself.
  377. return NULL;
  378. }
  379. while (rs)
  380. {
  381. if (rs->_parent == below || rs->_parent == NULL)
  382. {
  383. // Stop traversing up here.
  384. return rs;
  385. }
  386. rs = rs->_parent;
  387. }
  388. return NULL;
  389. }
  390. void RenderState::cloneInto(RenderState* renderState, NodeCloneContext& context) const
  391. {
  392. GP_ASSERT(renderState);
  393. // Clone parameters
  394. for (std::map<std::string, std::string>::const_iterator it = _autoBindings.begin(); it != _autoBindings.end(); ++it)
  395. {
  396. renderState->setParameterAutoBinding(it->first.c_str(), it->second.c_str());
  397. }
  398. for (std::vector<MaterialParameter*>::const_iterator it = _parameters.begin(); it != _parameters.end(); ++it)
  399. {
  400. const MaterialParameter* param = *it;
  401. GP_ASSERT(param);
  402. // If this parameter is a method binding auto binding, don't clone it - it will get setup automatically
  403. // via the cloned auto bindings instead.
  404. if (param->_type == MaterialParameter::METHOD && param->_value.method && param->_value.method->_autoBinding)
  405. continue;
  406. MaterialParameter* paramCopy = new MaterialParameter(param->getName());
  407. param->cloneInto(paramCopy);
  408. renderState->_parameters.push_back(paramCopy);
  409. }
  410. // Clone our state block
  411. if (_state)
  412. {
  413. _state->cloneInto(renderState->getStateBlock());
  414. }
  415. // Notes:
  416. // 1. _nodeBinding should not be set here, it should be set by the caller.
  417. // 2. _parent should not be set here, since it's set in the constructor of Technique and Pass.
  418. }
  419. RenderState::StateBlock::StateBlock()
  420. : _cullFaceEnabled(false), _depthTestEnabled(false), _depthWriteEnabled(true), _depthFunction(RenderState::DEPTH_LESS),
  421. _blendEnabled(false), _blendSrc(RenderState::BLEND_ONE), _blendDst(RenderState::BLEND_ZERO),
  422. _cullFaceSide(CULL_FACE_SIDE_BACK), _frontFace(FRONT_FACE_CCW), _stencilTestEnabled(false), _stencilWrite(RS_ALL_ONES),
  423. _stencilFunction(RenderState::STENCIL_ALWAYS), _stencilFunctionRef(0), _stencilFunctionMask(RS_ALL_ONES),
  424. _stencilOpSfail(RenderState::STENCIL_OP_KEEP), _stencilOpDpfail(RenderState::STENCIL_OP_KEEP), _stencilOpDppass(RenderState::STENCIL_OP_KEEP),
  425. _bits(0L)
  426. {
  427. }
  428. RenderState::StateBlock::StateBlock(const StateBlock& copy)
  429. {
  430. // Hidden
  431. }
  432. RenderState::StateBlock::~StateBlock()
  433. {
  434. }
  435. RenderState::StateBlock* RenderState::StateBlock::create()
  436. {
  437. return new RenderState::StateBlock();
  438. }
  439. void RenderState::StateBlock::bind()
  440. {
  441. // When the public bind() is called with no RenderState object passed in,
  442. // we assume we are being called to bind the state of a single StateBlock,
  443. // irrespective of whether it belongs to a hierarchy of RenderStates.
  444. // Therefore, we call restore() here with only this StateBlock's override
  445. // bits to restore state before applying the new state.
  446. StateBlock::restore(_bits);
  447. bindNoRestore();
  448. }
  449. void RenderState::StateBlock::bindNoRestore()
  450. {
  451. GP_ASSERT(_defaultState);
  452. // Update any state that differs from _defaultState and flip _defaultState bits
  453. if ((_bits & RS_BLEND) && (_blendEnabled != _defaultState->_blendEnabled))
  454. {
  455. if (_blendEnabled)
  456. GL_ASSERT( glEnable(GL_BLEND) );
  457. else
  458. GL_ASSERT( glDisable(GL_BLEND) );
  459. _defaultState->_blendEnabled = _blendEnabled;
  460. }
  461. if ((_bits & RS_BLEND_FUNC) && (_blendSrc != _defaultState->_blendSrc || _blendDst != _defaultState->_blendDst))
  462. {
  463. GL_ASSERT( glBlendFunc((GLenum)_blendSrc, (GLenum)_blendDst) );
  464. _defaultState->_blendSrc = _blendSrc;
  465. _defaultState->_blendDst = _blendDst;
  466. }
  467. if ((_bits & RS_CULL_FACE) && (_cullFaceEnabled != _defaultState->_cullFaceEnabled))
  468. {
  469. if (_cullFaceEnabled)
  470. GL_ASSERT( glEnable(GL_CULL_FACE) );
  471. else
  472. GL_ASSERT( glDisable(GL_CULL_FACE) );
  473. _defaultState->_cullFaceEnabled = _cullFaceEnabled;
  474. }
  475. if ((_bits & RS_CULL_FACE_SIDE) && (_cullFaceSide != _defaultState->_cullFaceSide))
  476. {
  477. GL_ASSERT( glCullFace((GLenum)_cullFaceSide) );
  478. _defaultState->_cullFaceSide = _cullFaceSide;
  479. }
  480. if ((_bits & RS_FRONT_FACE) && (_frontFace != _defaultState->_frontFace))
  481. {
  482. GL_ASSERT( glFrontFace((GLenum)_frontFace) );
  483. _defaultState->_frontFace = _frontFace;
  484. }
  485. if ((_bits & RS_DEPTH_TEST) && (_depthTestEnabled != _defaultState->_depthTestEnabled))
  486. {
  487. if (_depthTestEnabled)
  488. GL_ASSERT( glEnable(GL_DEPTH_TEST) );
  489. else
  490. GL_ASSERT( glDisable(GL_DEPTH_TEST) );
  491. _defaultState->_depthTestEnabled = _depthTestEnabled;
  492. }
  493. if ((_bits & RS_DEPTH_WRITE) && (_depthWriteEnabled != _defaultState->_depthWriteEnabled))
  494. {
  495. GL_ASSERT( glDepthMask(_depthWriteEnabled ? GL_TRUE : GL_FALSE) );
  496. _defaultState->_depthWriteEnabled = _depthWriteEnabled;
  497. }
  498. if ((_bits & RS_DEPTH_FUNC) && (_depthFunction != _defaultState->_depthFunction))
  499. {
  500. GL_ASSERT( glDepthFunc((GLenum)_depthFunction) );
  501. _defaultState->_depthFunction = _depthFunction;
  502. }
  503. if ((_bits & RS_STENCIL_TEST) && (_stencilTestEnabled != _defaultState->_stencilTestEnabled))
  504. {
  505. if (_stencilTestEnabled)
  506. GL_ASSERT( glEnable(GL_STENCIL_TEST) );
  507. else
  508. GL_ASSERT( glDisable(GL_STENCIL_TEST) );
  509. _defaultState->_stencilTestEnabled = _stencilTestEnabled;
  510. }
  511. if ((_bits & RS_STENCIL_WRITE) && (_stencilWrite != _defaultState->_stencilWrite))
  512. {
  513. GL_ASSERT( glStencilMask(_stencilWrite) );
  514. _defaultState->_stencilWrite = _stencilWrite;
  515. }
  516. if ((_bits & RS_STENCIL_FUNC) && (_stencilFunction != _defaultState->_stencilFunction ||
  517. _stencilFunctionRef != _defaultState->_stencilFunctionRef ||
  518. _stencilFunctionMask != _defaultState->_stencilFunctionMask))
  519. {
  520. GL_ASSERT( glStencilFunc((GLenum)_stencilFunction, _stencilFunctionRef, _stencilFunctionMask) );
  521. _defaultState->_stencilFunction = _stencilFunction;
  522. _defaultState->_stencilFunctionRef = _stencilFunctionRef;
  523. _defaultState->_stencilFunctionMask = _stencilFunctionMask;
  524. }
  525. if ((_bits & RS_STENCIL_OP) && (_stencilOpSfail != _defaultState->_stencilOpSfail ||
  526. _stencilOpDpfail != _defaultState->_stencilOpDpfail ||
  527. _stencilOpDppass != _defaultState->_stencilOpDppass))
  528. {
  529. GL_ASSERT( glStencilOp((GLenum)_stencilOpSfail, (GLenum)_stencilOpDpfail, (GLenum)_stencilOpDppass) );
  530. _defaultState->_stencilOpSfail = _stencilOpSfail;
  531. _defaultState->_stencilOpDpfail = _stencilOpDpfail;
  532. _defaultState->_stencilOpDppass = _stencilOpDppass;
  533. }
  534. _defaultState->_bits |= _bits;
  535. }
  536. void RenderState::StateBlock::restore(long stateOverrideBits)
  537. {
  538. GP_ASSERT(_defaultState);
  539. // If there is no state to restore (i.e. no non-default state), do nothing.
  540. if (_defaultState->_bits == 0)
  541. {
  542. return;
  543. }
  544. // Restore any state that is not overridden and is not default
  545. if (!(stateOverrideBits & RS_BLEND) && (_defaultState->_bits & RS_BLEND))
  546. {
  547. GL_ASSERT( glDisable(GL_BLEND) );
  548. _defaultState->_bits &= ~RS_BLEND;
  549. _defaultState->_blendEnabled = false;
  550. }
  551. if (!(stateOverrideBits & RS_BLEND_FUNC) && (_defaultState->_bits & RS_BLEND_FUNC))
  552. {
  553. GL_ASSERT( glBlendFunc(GL_ONE, GL_ZERO) );
  554. _defaultState->_bits &= ~RS_BLEND_FUNC;
  555. _defaultState->_blendSrc = RenderState::BLEND_ONE;
  556. _defaultState->_blendDst = RenderState::BLEND_ZERO;
  557. }
  558. if (!(stateOverrideBits & RS_CULL_FACE) && (_defaultState->_bits & RS_CULL_FACE))
  559. {
  560. GL_ASSERT( glDisable(GL_CULL_FACE) );
  561. _defaultState->_bits &= ~RS_CULL_FACE;
  562. _defaultState->_cullFaceEnabled = false;
  563. }
  564. if (!(stateOverrideBits & RS_CULL_FACE_SIDE) && (_defaultState->_bits & RS_CULL_FACE_SIDE))
  565. {
  566. GL_ASSERT( glCullFace((GLenum)GL_BACK) );
  567. _defaultState->_bits &= ~RS_CULL_FACE_SIDE;
  568. _defaultState->_cullFaceSide = RenderState::CULL_FACE_SIDE_BACK;
  569. }
  570. if (!(stateOverrideBits & RS_FRONT_FACE) && (_defaultState->_bits & RS_FRONT_FACE))
  571. {
  572. GL_ASSERT( glFrontFace((GLenum)GL_CCW) );
  573. _defaultState->_bits &= ~RS_FRONT_FACE;
  574. _defaultState->_frontFace = RenderState::FRONT_FACE_CCW;
  575. }
  576. if (!(stateOverrideBits & RS_DEPTH_TEST) && (_defaultState->_bits & RS_DEPTH_TEST))
  577. {
  578. GL_ASSERT( glDisable(GL_DEPTH_TEST) );
  579. _defaultState->_bits &= ~RS_DEPTH_TEST;
  580. _defaultState->_depthTestEnabled = false;
  581. }
  582. if (!(stateOverrideBits & RS_DEPTH_WRITE) && (_defaultState->_bits & RS_DEPTH_WRITE))
  583. {
  584. GL_ASSERT( glDepthMask(GL_TRUE) );
  585. _defaultState->_bits &= ~RS_DEPTH_WRITE;
  586. _defaultState->_depthWriteEnabled = true;
  587. }
  588. if (!(stateOverrideBits & RS_DEPTH_FUNC) && (_defaultState->_bits & RS_DEPTH_FUNC))
  589. {
  590. GL_ASSERT( glDepthFunc((GLenum)GL_LESS) );
  591. _defaultState->_bits &= ~RS_DEPTH_FUNC;
  592. _defaultState->_depthFunction = RenderState::DEPTH_LESS;
  593. }
  594. if (!(stateOverrideBits & RS_STENCIL_TEST) && (_defaultState->_bits & RS_STENCIL_TEST))
  595. {
  596. GL_ASSERT( glDisable(GL_STENCIL_TEST) );
  597. _defaultState->_bits &= ~RS_STENCIL_TEST;
  598. _defaultState->_stencilTestEnabled = false;
  599. }
  600. if (!(stateOverrideBits & RS_STENCIL_WRITE) && (_defaultState->_bits & RS_STENCIL_WRITE))
  601. {
  602. GL_ASSERT( glStencilMask(RS_ALL_ONES) );
  603. _defaultState->_bits &= ~RS_STENCIL_WRITE;
  604. _defaultState->_stencilWrite = RS_ALL_ONES;
  605. }
  606. if (!(stateOverrideBits & RS_STENCIL_FUNC) && (_defaultState->_bits & RS_STENCIL_FUNC))
  607. {
  608. GL_ASSERT( glStencilFunc((GLenum)RenderState::STENCIL_ALWAYS, 0, RS_ALL_ONES) );
  609. _defaultState->_bits &= ~RS_STENCIL_FUNC;
  610. _defaultState->_stencilFunction = RenderState::STENCIL_ALWAYS;
  611. _defaultState->_stencilFunctionRef = 0;
  612. _defaultState->_stencilFunctionMask = RS_ALL_ONES;
  613. }
  614. if (!(stateOverrideBits & RS_STENCIL_OP) && (_defaultState->_bits & RS_STENCIL_OP))
  615. {
  616. GL_ASSERT( glStencilOp((GLenum)RenderState::STENCIL_OP_KEEP, (GLenum)RenderState::STENCIL_OP_KEEP, (GLenum)RenderState::STENCIL_OP_KEEP) );
  617. _defaultState->_bits &= ~RS_STENCIL_OP;
  618. _defaultState->_stencilOpSfail = RenderState::STENCIL_OP_KEEP;
  619. _defaultState->_stencilOpDpfail = RenderState::STENCIL_OP_KEEP;
  620. _defaultState->_stencilOpDppass = RenderState::STENCIL_OP_KEEP;
  621. }
  622. }
  623. void RenderState::StateBlock::enableDepthWrite()
  624. {
  625. GP_ASSERT(_defaultState);
  626. // Internal method used by Game::clear() to restore depth writing before a
  627. // clear operation. This is necessary if the last code to draw before the
  628. // next frame leaves depth writing disabled.
  629. if (!_defaultState->_depthWriteEnabled)
  630. {
  631. GL_ASSERT( glDepthMask(GL_TRUE) );
  632. _defaultState->_bits &= ~RS_DEPTH_WRITE;
  633. _defaultState->_depthWriteEnabled = true;
  634. }
  635. }
  636. void RenderState::StateBlock::cloneInto(StateBlock* state)
  637. {
  638. GP_ASSERT(state);
  639. state->_cullFaceEnabled = _cullFaceEnabled;
  640. state->_depthTestEnabled = _depthTestEnabled;
  641. state->_depthWriteEnabled = _depthWriteEnabled;
  642. state->_depthFunction = _depthFunction;
  643. state->_blendEnabled = _blendEnabled;
  644. state->_blendSrc = _blendSrc;
  645. state->_blendDst = _blendDst;
  646. state->_cullFaceSide = _cullFaceSide;
  647. state->_frontFace = _frontFace;
  648. state->_stencilTestEnabled = _stencilTestEnabled;
  649. state->_stencilWrite = _stencilWrite;
  650. state->_stencilFunction = _stencilFunction;
  651. state->_stencilFunctionRef = _stencilFunctionRef;
  652. state->_stencilFunctionMask = _stencilFunctionMask;
  653. state->_stencilOpSfail = _stencilOpSfail;
  654. state->_stencilOpDpfail = _stencilOpDpfail;
  655. state->_stencilOpDppass = _stencilOpDppass;
  656. state->_bits = _bits;
  657. }
  658. static bool parseBoolean(const char* value)
  659. {
  660. GP_ASSERT(value);
  661. if (strlen(value) == 4)
  662. {
  663. return (
  664. tolower(value[0]) == 't' &&
  665. tolower(value[1]) == 'r' &&
  666. tolower(value[2]) == 'u' &&
  667. tolower(value[3]) == 'e' );
  668. }
  669. return false;
  670. }
  671. static int parseInt(const char* value)
  672. {
  673. GP_ASSERT(value);
  674. int rValue;
  675. int scanned = sscanf(value, "%d", &rValue);
  676. if (scanned != 1)
  677. {
  678. GP_ERROR("Error attempting to parse int '%s'. (Will default to 0 if errors are treated as warnings)", value);
  679. return 0;
  680. }
  681. return rValue;
  682. }
  683. static unsigned int parseUInt(const char* value)
  684. {
  685. GP_ASSERT(value);
  686. unsigned int rValue;
  687. int scanned = sscanf(value, "%u", &rValue);
  688. if (scanned != 1)
  689. {
  690. GP_ERROR("Error attempting to parse unsigned int '%s'. (Will default to 0 if errors are treated as warnings)", value);
  691. return 0;
  692. }
  693. return rValue;
  694. }
  695. static RenderState::Blend parseBlend(const char* value)
  696. {
  697. GP_ASSERT(value);
  698. // Convert the string to uppercase for comparison.
  699. std::string upper(value);
  700. std::transform(upper.begin(), upper.end(), upper.begin(), (int(*)(int))toupper);
  701. if (upper == "ZERO")
  702. return RenderState::BLEND_ZERO;
  703. else if (upper == "ONE")
  704. return RenderState::BLEND_ONE;
  705. else if (upper == "SRC_COLOR")
  706. return RenderState::BLEND_SRC_COLOR;
  707. else if (upper == "ONE_MINUS_SRC_COLOR")
  708. return RenderState::BLEND_ONE_MINUS_SRC_COLOR;
  709. else if (upper == "DST_COLOR")
  710. return RenderState::BLEND_DST_COLOR;
  711. else if (upper == "ONE_MINUS_DST_COLOR")
  712. return RenderState::BLEND_ONE_MINUS_DST_COLOR;
  713. else if (upper == "SRC_ALPHA")
  714. return RenderState::BLEND_SRC_ALPHA;
  715. else if (upper == "ONE_MINUS_SRC_ALPHA")
  716. return RenderState::BLEND_ONE_MINUS_SRC_ALPHA;
  717. else if (upper == "DST_ALPHA")
  718. return RenderState::BLEND_DST_ALPHA;
  719. else if (upper == "ONE_MINUS_DST_ALPHA")
  720. return RenderState::BLEND_ONE_MINUS_DST_ALPHA;
  721. else if (upper == "CONSTANT_ALPHA")
  722. return RenderState::BLEND_CONSTANT_ALPHA;
  723. else if (upper == "ONE_MINUS_CONSTANT_ALPHA")
  724. return RenderState::BLEND_ONE_MINUS_CONSTANT_ALPHA;
  725. else if (upper == "SRC_ALPHA_SATURATE")
  726. return RenderState::BLEND_SRC_ALPHA_SATURATE;
  727. else
  728. {
  729. GP_ERROR("Unsupported blend value (%s). (Will default to BLEND_ONE if errors are treated as warnings)", value);
  730. return RenderState::BLEND_ONE;
  731. }
  732. }
  733. static RenderState::DepthFunction parseDepthFunc(const char* value)
  734. {
  735. GP_ASSERT(value);
  736. // Convert string to uppercase for comparison
  737. std::string upper(value);
  738. std::transform(upper.begin(), upper.end(), upper.begin(), (int(*)(int))toupper);
  739. if (upper == "NEVER")
  740. return RenderState::DEPTH_NEVER;
  741. else if (upper == "LESS")
  742. return RenderState::DEPTH_LESS;
  743. else if (upper == "EQUAL")
  744. return RenderState::DEPTH_EQUAL;
  745. else if (upper == "LEQUAL")
  746. return RenderState::DEPTH_LEQUAL;
  747. else if (upper == "GREATER")
  748. return RenderState::DEPTH_GREATER;
  749. else if (upper == "NOTEQUAL")
  750. return RenderState::DEPTH_NOTEQUAL;
  751. else if (upper == "GEQUAL")
  752. return RenderState::DEPTH_GEQUAL;
  753. else if (upper == "ALWAYS")
  754. return RenderState::DEPTH_ALWAYS;
  755. else
  756. {
  757. GP_ERROR("Unsupported depth function value (%s). Will default to DEPTH_LESS if errors are treated as warnings)", value);
  758. return RenderState::DEPTH_LESS;
  759. }
  760. }
  761. static RenderState::CullFaceSide parseCullFaceSide(const char* value)
  762. {
  763. GP_ASSERT(value);
  764. // Convert string to uppercase for comparison
  765. std::string upper(value);
  766. std::transform(upper.begin(), upper.end(), upper.begin(), (int(*)(int))toupper);
  767. if (upper == "BACK")
  768. return RenderState::CULL_FACE_SIDE_BACK;
  769. else if (upper == "FRONT")
  770. return RenderState::CULL_FACE_SIDE_FRONT;
  771. else if (upper == "FRONT_AND_BACK")
  772. return RenderState::CULL_FACE_SIDE_FRONT_AND_BACK;
  773. else
  774. {
  775. GP_ERROR("Unsupported cull face side value (%s). Will default to BACK if errors are treated as warnings.", value);
  776. return RenderState::CULL_FACE_SIDE_BACK;
  777. }
  778. }
  779. static RenderState::FrontFace parseFrontFace(const char* value)
  780. {
  781. GP_ASSERT(value);
  782. // Convert string to uppercase for comparison
  783. std::string upper(value);
  784. std::transform(upper.begin(), upper.end(), upper.begin(), (int(*)(int))toupper);
  785. if (upper == "CCW")
  786. return RenderState::FRONT_FACE_CCW;
  787. else if (upper == "CW")
  788. return RenderState::FRONT_FACE_CW;
  789. else
  790. {
  791. GP_ERROR("Unsupported front face side value (%s). Will default to CCW if errors are treated as warnings.", value);
  792. return RenderState::FRONT_FACE_CCW;
  793. }
  794. }
  795. static RenderState::StencilFunction parseStencilFunc(const char* value)
  796. {
  797. GP_ASSERT(value);
  798. // Convert string to uppercase for comparison
  799. std::string upper(value);
  800. std::transform(upper.begin(), upper.end(), upper.begin(), (int(*)(int))toupper);
  801. if (upper == "NEVER")
  802. return RenderState::STENCIL_NEVER;
  803. else if (upper == "LESS")
  804. return RenderState::STENCIL_LESS;
  805. else if (upper == "EQUAL")
  806. return RenderState::STENCIL_EQUAL;
  807. else if (upper == "LEQUAL")
  808. return RenderState::STENCIL_LEQUAL;
  809. else if (upper == "GREATER")
  810. return RenderState::STENCIL_GREATER;
  811. else if (upper == "NOTEQUAL")
  812. return RenderState::STENCIL_NOTEQUAL;
  813. else if (upper == "GEQUAL")
  814. return RenderState::STENCIL_GEQUAL;
  815. else if (upper == "ALWAYS")
  816. return RenderState::STENCIL_ALWAYS;
  817. else
  818. {
  819. GP_ERROR("Unsupported stencil function value (%s). Will default to STENCIL_ALWAYS if errors are treated as warnings)", value);
  820. return RenderState::STENCIL_ALWAYS;
  821. }
  822. }
  823. static RenderState::StencilOperation parseStencilOp(const char* value)
  824. {
  825. GP_ASSERT(value);
  826. // Convert string to uppercase for comparison
  827. std::string upper(value);
  828. std::transform(upper.begin(), upper.end(), upper.begin(), (int(*)(int))toupper);
  829. if (upper == "KEEP")
  830. return RenderState::STENCIL_OP_KEEP;
  831. else if (upper == "ZERO")
  832. return RenderState::STENCIL_OP_ZERO;
  833. else if (upper == "REPLACE")
  834. return RenderState::STENCIL_OP_REPLACE;
  835. else if (upper == "INCR")
  836. return RenderState::STENCIL_OP_INCR;
  837. else if (upper == "DECR")
  838. return RenderState::STENCIL_OP_DECR;
  839. else if (upper == "INVERT")
  840. return RenderState::STENCIL_OP_INVERT;
  841. else if (upper == "INCR_WRAP")
  842. return RenderState::STENCIL_OP_INCR_WRAP;
  843. else if (upper == "DECR_WRAP")
  844. return RenderState::STENCIL_OP_DECR_WRAP;
  845. else
  846. {
  847. GP_ERROR("Unsupported stencil operation value (%s). Will default to STENCIL_OP_KEEP if errors are treated as warnings)", value);
  848. return RenderState::STENCIL_OP_KEEP;
  849. }
  850. }
  851. void RenderState::StateBlock::setState(const char* name, const char* value)
  852. {
  853. GP_ASSERT(name);
  854. if (strcmp(name, "blend") == 0)
  855. {
  856. setBlend(parseBoolean(value));
  857. }
  858. else if (strcmp(name, "blendSrc") == 0 || strcmp(name, "srcBlend") == 0 ) // Leaving srcBlend for backward compat.
  859. {
  860. setBlendSrc(parseBlend(value));
  861. }
  862. else if (strcmp(name, "blendDst") == 0 || strcmp(name, "dstBlend") == 0) // // Leaving dstBlend for backward compat.
  863. {
  864. setBlendDst(parseBlend(value));
  865. }
  866. else if (strcmp(name, "cullFace") == 0)
  867. {
  868. setCullFace(parseBoolean(value));
  869. }
  870. else if (strcmp(name, "cullFaceSide") == 0)
  871. {
  872. setCullFaceSide(parseCullFaceSide(value));
  873. }
  874. else if (strcmp(name, "frontFace") == 0)
  875. {
  876. setFrontFace(parseFrontFace(value));
  877. }
  878. else if (strcmp(name, "depthTest") == 0)
  879. {
  880. setDepthTest(parseBoolean(value));
  881. }
  882. else if (strcmp(name, "depthWrite") == 0)
  883. {
  884. setDepthWrite(parseBoolean(value));
  885. }
  886. else if (strcmp(name, "depthFunc") == 0)
  887. {
  888. setDepthFunction(parseDepthFunc(value));
  889. }
  890. else if (strcmp(name, "stencilTest") == 0)
  891. {
  892. setStencilTest(parseBoolean(value));
  893. }
  894. else if (strcmp(name, "stencilWrite") == 0)
  895. {
  896. setStencilWrite(parseUInt(value));
  897. }
  898. else if (strcmp(name, "stencilFunc") == 0)
  899. {
  900. setStencilFunction(parseStencilFunc(value), _stencilFunctionRef, _stencilFunctionMask);
  901. }
  902. else if (strcmp(name, "stencilFuncRef") == 0)
  903. {
  904. setStencilFunction(_stencilFunction, parseInt(value), _stencilFunctionMask);
  905. }
  906. else if (strcmp(name, "stencilFuncMask") == 0)
  907. {
  908. setStencilFunction(_stencilFunction, _stencilFunctionRef, parseUInt(value));
  909. }
  910. else if (strcmp(name, "stencilOpSfail") == 0)
  911. {
  912. setStencilOperation(parseStencilOp(value), _stencilOpDpfail, _stencilOpDppass);
  913. }
  914. else if (strcmp(name, "stencilOpDpfail") == 0)
  915. {
  916. setStencilOperation(_stencilOpSfail, parseStencilOp(value), _stencilOpDppass);
  917. }
  918. else if (strcmp(name, "stencilOpDppass") == 0)
  919. {
  920. setStencilOperation(_stencilOpSfail, _stencilOpDpfail, parseStencilOp(value));
  921. }
  922. else
  923. {
  924. GP_ERROR("Unsupported render state string '%s'.", name);
  925. }
  926. }
  927. void RenderState::StateBlock::setBlend(bool enabled)
  928. {
  929. _blendEnabled = enabled;
  930. if (!enabled)
  931. {
  932. _bits &= ~RS_BLEND;
  933. }
  934. else
  935. {
  936. _bits |= RS_BLEND;
  937. }
  938. }
  939. void RenderState::StateBlock::setBlendSrc(Blend blend)
  940. {
  941. _blendSrc = blend;
  942. if (_blendSrc == BLEND_ONE && _blendDst == BLEND_ZERO)
  943. {
  944. // Default blend func
  945. _bits &= ~RS_BLEND_FUNC;
  946. }
  947. else
  948. {
  949. _bits |= RS_BLEND_FUNC;
  950. }
  951. }
  952. void RenderState::StateBlock::setBlendDst(Blend blend)
  953. {
  954. _blendDst = blend;
  955. if (_blendSrc == BLEND_ONE && _blendDst == BLEND_ZERO)
  956. {
  957. // Default blend func
  958. _bits &= ~RS_BLEND_FUNC;
  959. }
  960. else
  961. {
  962. _bits |= RS_BLEND_FUNC;
  963. }
  964. }
  965. void RenderState::StateBlock::setCullFace(bool enabled)
  966. {
  967. _cullFaceEnabled = enabled;
  968. if (!enabled)
  969. {
  970. _bits &= ~RS_CULL_FACE;
  971. }
  972. else
  973. {
  974. _bits |= RS_CULL_FACE;
  975. }
  976. }
  977. void RenderState::StateBlock::setCullFaceSide(CullFaceSide side)
  978. {
  979. _cullFaceSide = side;
  980. if (_cullFaceSide == CULL_FACE_SIDE_BACK)
  981. {
  982. // Default cull side
  983. _bits &= ~RS_CULL_FACE_SIDE;
  984. }
  985. else
  986. {
  987. _bits |= RS_CULL_FACE_SIDE;
  988. }
  989. }
  990. void RenderState::StateBlock::setFrontFace(FrontFace winding)
  991. {
  992. _frontFace = winding;
  993. if (_frontFace == FRONT_FACE_CCW)
  994. {
  995. // Default front face
  996. _bits &= ~RS_FRONT_FACE;
  997. }
  998. else
  999. {
  1000. _bits |= RS_FRONT_FACE;
  1001. }
  1002. }
  1003. void RenderState::StateBlock::setDepthTest(bool enabled)
  1004. {
  1005. _depthTestEnabled = enabled;
  1006. if (!enabled)
  1007. {
  1008. _bits &= ~RS_DEPTH_TEST;
  1009. }
  1010. else
  1011. {
  1012. _bits |= RS_DEPTH_TEST;
  1013. }
  1014. }
  1015. void RenderState::StateBlock::setDepthWrite(bool enabled)
  1016. {
  1017. _depthWriteEnabled = enabled;
  1018. if (enabled)
  1019. {
  1020. _bits &= ~RS_DEPTH_WRITE;
  1021. }
  1022. else
  1023. {
  1024. _bits |= RS_DEPTH_WRITE;
  1025. }
  1026. }
  1027. void RenderState::StateBlock::setDepthFunction(DepthFunction func)
  1028. {
  1029. _depthFunction = func;
  1030. if (_depthFunction == DEPTH_LESS)
  1031. {
  1032. // Default depth function
  1033. _bits &= ~RS_DEPTH_FUNC;
  1034. }
  1035. else
  1036. {
  1037. _bits |= RS_DEPTH_FUNC;
  1038. }
  1039. }
  1040. void RenderState::StateBlock::setStencilTest(bool enabled)
  1041. {
  1042. _stencilTestEnabled = enabled;
  1043. if (!enabled)
  1044. {
  1045. _bits &= ~RS_STENCIL_TEST;
  1046. }
  1047. else
  1048. {
  1049. _bits |= RS_STENCIL_TEST;
  1050. }
  1051. }
  1052. void RenderState::StateBlock::setStencilWrite(unsigned int mask)
  1053. {
  1054. _stencilWrite = mask;
  1055. if (mask == RS_ALL_ONES)
  1056. {
  1057. // Default stencil write
  1058. _bits &= ~RS_STENCIL_WRITE;
  1059. }
  1060. else
  1061. {
  1062. _bits |= RS_STENCIL_WRITE;
  1063. }
  1064. }
  1065. void RenderState::StateBlock::setStencilFunction(StencilFunction func, int ref, unsigned int mask)
  1066. {
  1067. _stencilFunction = func;
  1068. _stencilFunctionRef = ref;
  1069. _stencilFunctionMask = mask;
  1070. if (func == STENCIL_ALWAYS && ref == 0 && mask == RS_ALL_ONES)
  1071. {
  1072. // Default stencil function
  1073. _bits &= ~RS_STENCIL_FUNC;
  1074. }
  1075. else
  1076. {
  1077. _bits |= RS_STENCIL_FUNC;
  1078. }
  1079. }
  1080. void RenderState::StateBlock::setStencilOperation(StencilOperation sfail, StencilOperation dpfail, StencilOperation dppass)
  1081. {
  1082. _stencilOpSfail = sfail;
  1083. _stencilOpDpfail = dpfail;
  1084. _stencilOpDppass = dppass;
  1085. if (sfail == STENCIL_OP_KEEP && dpfail == STENCIL_OP_KEEP && dppass == STENCIL_OP_KEEP)
  1086. {
  1087. // Default stencil operation
  1088. _bits &= ~RS_STENCIL_OP;
  1089. }
  1090. else
  1091. {
  1092. _bits |= RS_STENCIL_OP;
  1093. }
  1094. }
  1095. }