MeshCommand uses StateBlock

When MeshCommand is used with GLProgramState, it will use the StateBlock
internally, instead of the manual and error prone way of keeping state
This commit is contained in:
Ricardo Quesada 2015-05-19 18:13:18 -07:00
parent 703852de69
commit ac54dad9a0
5 changed files with 46 additions and 116 deletions

View File

@ -49,23 +49,27 @@ NS_CC_BEGIN
MeshCommand::MeshCommand() MeshCommand::MeshCommand()
: _textureID(0) : _textureID(0)
, _glProgramState(nullptr) , _glProgramState(nullptr)
, _blendType(BlendFunc::DISABLE)
, _displayColor(1.0f, 1.0f, 1.0f, 1.0f) , _displayColor(1.0f, 1.0f, 1.0f, 1.0f)
, _matrixPalette(nullptr) , _matrixPalette(nullptr)
, _matrixPaletteSize(0) , _matrixPaletteSize(0)
, _materialID(0) , _materialID(0)
, _vao(0) , _vao(0)
, _cullFaceEnabled(false)
, _cullFace(GL_BACK)
, _depthTestEnabled(false)
, _depthWriteEnabled(false)
, _forceDepthWrite(false)
, _renderStateCullFaceEnabled(false)
, _renderStateDepthTest(false)
, _renderStateDepthWrite(GL_FALSE)
, _material(nullptr) , _material(nullptr)
, _stateBlock(nullptr)
, _forceDepthWrite(false)
{ {
_type = RenderCommand::Type::MESH_COMMAND; _type = RenderCommand::Type::MESH_COMMAND;
_stateBlock = RenderState::StateBlock::create();
CC_SAFE_RETAIN(_stateBlock);
_stateBlock->setCullFace(false);
_stateBlock->setCullFaceSide(RenderState::CULL_FACE_SIDE_BACK);
_stateBlock->setDepthTest(false);
_stateBlock->setDepthWrite(false);
_stateBlock->setBlend(true);
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
// listen the event that renderer was recreated on Android/WP8 // listen the event that renderer was recreated on Android/WP8
_rendererRecreatedListener = EventListenerCustom::create(EVENT_RENDERER_RECREATED, CC_CALLBACK_1(MeshCommand::listenRendererRecreated, this)); _rendererRecreatedListener = EventListenerCustom::create(EVENT_RENDERER_RECREATED, CC_CALLBACK_1(MeshCommand::listenRendererRecreated, this));
@ -127,12 +131,12 @@ void MeshCommand::init(float globalZOrder,
uint32_t flags) uint32_t flags)
{ {
CCASSERT(glProgramState, "GLProgramState cannot be nill"); CCASSERT(glProgramState, "GLProgramState cannot be nill");
CCASSERT(!_material, "cannot init with GLProgramState if previously inited without GLProgramState");
RenderCommand::init(globalZOrder, mv, flags); RenderCommand::init(globalZOrder, mv, flags);
_globalOrder = globalZOrder; _globalOrder = globalZOrder;
_textureID = textureID; _textureID = textureID;
_blendType = blendType;
_glProgramState = glProgramState; _glProgramState = glProgramState;
_vertexBuffer = vertexBuffer; _vertexBuffer = vertexBuffer;
@ -143,27 +147,34 @@ void MeshCommand::init(float globalZOrder,
_mv.set(mv); _mv.set(mv);
_is3D = true; _is3D = true;
if (!_stateBlock) {
_stateBlock = RenderState::StateBlock::create();
CC_SAFE_RETAIN(_stateBlock);
}
_stateBlock->setBlendFunc(blendType);
} }
void MeshCommand::setCullFaceEnabled(bool enable) void MeshCommand::setCullFaceEnabled(bool enable)
{ {
CCASSERT(!_material, "If using material, you should call material->setCullFace()"); CCASSERT(!_material, "If using material, you should call material->setCullFace()");
_cullFaceEnabled = enable; _stateBlock->setCullFace(enable);
} }
void MeshCommand::setCullFace(GLenum cullFace) void MeshCommand::setCullFace(GLenum cullFace)
{ {
CCASSERT(!_material, "If using material, you should call material->setCullFaceSide()"); CCASSERT(!_material, "If using material, you should call material->setCullFaceSide()");
_cullFace = cullFace; _stateBlock->setCullFaceSide((RenderState::CullFaceSide)cullFace);
} }
void MeshCommand::setDepthTestEnabled(bool enable) void MeshCommand::setDepthTestEnabled(bool enable)
{ {
CCASSERT(!_material, "If using material, you should call material->setDepthTest()"); CCASSERT(!_material, "If using material, you should call material->setDepthTest()");
_depthTestEnabled = enable; _stateBlock->setDepthTest(enable);
} }
void MeshCommand::setDepthWriteEnabled(bool enable) void MeshCommand::setDepthWriteEnabled(bool enable)
@ -171,7 +182,7 @@ void MeshCommand::setDepthWriteEnabled(bool enable)
CCASSERT(!_material, "If using material, you should call material->setDepthWrite()"); CCASSERT(!_material, "If using material, you should call material->setDepthWrite()");
_forceDepthWrite = enable; _forceDepthWrite = enable;
_depthWriteEnabled = enable; _stateBlock->setDepthWrite(enable);
} }
void MeshCommand::setDisplayColor(const Vec4& color) void MeshCommand::setDisplayColor(const Vec4& color)
@ -205,16 +216,18 @@ void MeshCommand::setTransparent(bool value)
if (_isTransparent && !_forceDepthWrite) if (_isTransparent && !_forceDepthWrite)
{ {
_depthWriteEnabled = false; _stateBlock->setDepthWrite(false);
} }
else else
{ {
_depthWriteEnabled = true; _stateBlock->setDepthWrite(true);
} }
} }
MeshCommand::~MeshCommand() MeshCommand::~MeshCommand()
{ {
CC_SAFE_RELEASE(_stateBlock);
releaseVAO(); releaseVAO();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
Director::getInstance()->getEventDispatcher()->removeEventListener(_rendererRecreatedListener); Director::getInstance()->getEventDispatcher()->removeEventListener(_rendererRecreatedListener);
@ -227,64 +240,8 @@ void MeshCommand::applyRenderState()
// blend and texture // blend and texture
GL::bindTexture2D(_textureID); GL::bindTexture2D(_textureID);
GL::blendFunc(_blendType.src, _blendType.dst);
// cull face _stateBlock->bind();
_renderStateCullFaceEnabled = glIsEnabled(GL_CULL_FACE) != GL_FALSE;
GLint cullface;
glGetIntegerv(GL_CULL_FACE_MODE, &cullface);
_renderStateCullFace = (GLenum)cullface;
if (_cullFaceEnabled != _renderStateCullFaceEnabled)
{
_cullFaceEnabled ? glEnable(GL_CULL_FACE) : glDisable(GL_CULL_FACE);
}
if (_cullFace != _renderStateCullFace)
{
glCullFace(_cullFace);
}
// depth
_renderStateDepthTest = (glIsEnabled(GL_DEPTH_TEST) != GL_FALSE);
glGetBooleanv(GL_DEPTH_WRITEMASK, &_renderStateDepthWrite);
if (_depthTestEnabled != _renderStateDepthTest)
{
_depthTestEnabled ? glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST);
}
if (_depthWriteEnabled != _renderStateDepthWrite)
{
glDepthMask(_depthWriteEnabled);
}
}
void MeshCommand::restoreRenderState()
{
CCASSERT(!_material, "Must not be called when using Material");
// cull
if (_cullFaceEnabled != _renderStateCullFaceEnabled)
{
_renderStateCullFaceEnabled ? glEnable(GL_CULL_FACE) : glDisable(GL_CULL_FACE);
}
if (_cullFace != _renderStateCullFace)
{
glCullFace(_renderStateCullFace);
}
// depth
if (_depthTestEnabled != _renderStateDepthTest)
{
_renderStateDepthTest ? glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST);
}
if (_depthWriteEnabled != _renderStateDepthWrite)
{
glDepthMask(_renderStateDepthWrite);
}
} }
void MeshCommand::genMaterialID(GLuint texID, void* glProgramState, GLuint vertexBuffer, GLuint indexBuffer, BlendFunc blend) void MeshCommand::genMaterialID(GLuint texID, void* glProgramState, GLuint vertexBuffer, GLuint indexBuffer, BlendFunc blend)
@ -353,9 +310,6 @@ void MeshCommand::batchDraw()
// Draw // Draw
glDrawElements(_primitive, (GLsizei)_indexCount, _indexFormat, 0); glDrawElements(_primitive, (GLsizei)_indexCount, _indexFormat, 0);
CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, _indexCount); CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, _indexCount);
//restore render state
restoreRenderState();
} }
} }
void MeshCommand::postBatchDraw() void MeshCommand::postBatchDraw()
@ -404,9 +358,6 @@ void MeshCommand::execute()
glDrawElements(_primitive, (GLsizei)_indexCount, _indexFormat, 0); glDrawElements(_primitive, (GLsizei)_indexCount, _indexFormat, 0);
CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, _indexCount); CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, _indexCount);
//restore render state
restoreRenderState();
} }
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

View File

@ -28,6 +28,7 @@
#include <unordered_map> #include <unordered_map>
#include "renderer/CCRenderCommand.h" #include "renderer/CCRenderCommand.h"
#include "renderer/CCGLProgram.h" #include "renderer/CCGLProgram.h"
#include "renderer/CCRenderState.h"
#include "math/CCMath.h" #include "math/CCMath.h"
NS_CC_BEGIN NS_CC_BEGIN
@ -93,11 +94,9 @@ protected:
// apply renderstate, not used when using material // apply renderstate, not used when using material
void applyRenderState(); void applyRenderState();
void restoreRenderState();
GLuint _textureID; GLuint _textureID;
GLProgramState* _glProgramState; GLProgramState* _glProgramState;
BlendFunc _blendType;
Vec4 _displayColor; // in order to support tint and fade in fade out Vec4 _displayColor; // in order to support tint and fade in fade out
@ -116,16 +115,8 @@ protected:
ssize_t _indexCount; ssize_t _indexCount;
// States, default value all false // States, default value all false
bool _cullFaceEnabled;
GLenum _cullFace;
bool _depthTestEnabled;
bool _depthWriteEnabled;
bool _forceDepthWrite; bool _forceDepthWrite;
RenderState::StateBlock* _stateBlock;
bool _renderStateCullFaceEnabled;
bool _renderStateDepthTest;
GLboolean _renderStateDepthWrite;
GLenum _renderStateCullFace;
// ModelView transform // ModelView transform
Mat4 _mv; Mat4 _mv;

View File

@ -749,26 +749,8 @@ void RenderState::StateBlock::setBlend(bool enabled)
void RenderState::StateBlock::setBlendFunc(const BlendFunc& blendFunc) void RenderState::StateBlock::setBlendFunc(const BlendFunc& blendFunc)
{ {
if (blendFunc == BlendFunc::DISABLE) setBlendSrc((RenderState::Blend)blendFunc.src);
{ setBlendDst((RenderState::Blend)blendFunc.dst);
setBlendSrc(BLEND_ONE);
setBlendDst(BLEND_ZERO);
}
else if (blendFunc == BlendFunc::ALPHA_PREMULTIPLIED)
{
setBlendSrc(BLEND_ONE);
setBlendDst(BLEND_ONE_MINUS_SRC_ALPHA);
}
else if (blendFunc == BlendFunc::ALPHA_NON_PREMULTIPLIED)
{
setBlendSrc(BLEND_SRC_ALPHA);
setBlendDst(BLEND_ONE_MINUS_SRC_ALPHA);
}
else if (blendFunc == BlendFunc::ADDITIVE)
{
setBlendSrc(BLEND_SRC_ALPHA);
setBlendDst(BLEND_ONE);
}
} }
void RenderState::StateBlock::setBlendSrc(Blend blend) void RenderState::StateBlock::setBlendSrc(Blend blend)

View File

@ -352,6 +352,8 @@ public:
uint32_t getHash() const; uint32_t getHash() const;
bool isDirty() const; bool isDirty() const;
static StateBlock* _defaultState;
protected: protected:
StateBlock(); StateBlock();
~StateBlock(); ~StateBlock();
@ -382,8 +384,6 @@ public:
long _bits; long _bits;
static StateBlock* _defaultState;
mutable uint32_t _hash; mutable uint32_t _hash;
mutable bool _hashDirty; mutable bool _hashDirty;
}; };

View File

@ -28,6 +28,7 @@ THE SOFTWARE.
#include "renderer/ccGLStateCache.h" #include "renderer/ccGLStateCache.h"
#include "renderer/CCGLProgram.h" #include "renderer/CCGLProgram.h"
#include "renderer/CCRenderState.h"
#include "base/CCDirector.h" #include "base/CCDirector.h"
#include "base/ccConfig.h" #include "base/ccConfig.h"
#include "base/CCConfiguration.h" #include "base/CCConfiguration.h"
@ -109,11 +110,16 @@ static void SetBlending(GLenum sfactor, GLenum dfactor)
if (sfactor == GL_ONE && dfactor == GL_ZERO) if (sfactor == GL_ONE && dfactor == GL_ZERO)
{ {
glDisable(GL_BLEND); glDisable(GL_BLEND);
RenderState::StateBlock::_defaultState->setBlend(false);
} }
else else
{ {
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc(sfactor, dfactor); glBlendFunc(sfactor, dfactor);
RenderState::StateBlock::_defaultState->setBlend(true);
RenderState::StateBlock::_defaultState->setBlendSrc((RenderState::Blend)sfactor);
RenderState::StateBlock::_defaultState->setBlendSrc((RenderState::Blend)dfactor);
} }
} }