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()
: _textureID(0)
, _glProgramState(nullptr)
, _blendType(BlendFunc::DISABLE)
, _displayColor(1.0f, 1.0f, 1.0f, 1.0f)
, _matrixPalette(nullptr)
, _matrixPaletteSize(0)
, _materialID(0)
, _vao(0)
, _cullFaceEnabled(false)
, _cullFace(GL_BACK)
, _depthTestEnabled(false)
, _depthWriteEnabled(false)
, _forceDepthWrite(false)
, _renderStateCullFaceEnabled(false)
, _renderStateDepthTest(false)
, _renderStateDepthWrite(GL_FALSE)
, _material(nullptr)
, _stateBlock(nullptr)
, _forceDepthWrite(false)
{
_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)
// listen the event that renderer was recreated on Android/WP8
_rendererRecreatedListener = EventListenerCustom::create(EVENT_RENDERER_RECREATED, CC_CALLBACK_1(MeshCommand::listenRendererRecreated, this));
@ -116,23 +120,23 @@ void MeshCommand::init(float globalOrder,
void MeshCommand::init(float globalZOrder,
GLuint textureID,
cocos2d::GLProgramState *glProgramState,
cocos2d::GLProgramState* glProgramState,
cocos2d::BlendFunc blendType,
GLuint vertexBuffer,
GLuint indexBuffer,
GLenum primitive,
GLenum indexFormat,
ssize_t indexCount,
const cocos2d::Mat4 &mv,
const cocos2d::Mat4& mv,
uint32_t flags)
{
CCASSERT(glProgramState, "GLProgramState cannot be nill");
CCASSERT(!_material, "cannot init with GLProgramState if previously inited without GLProgramState");
RenderCommand::init(globalZOrder, mv, flags);
_globalOrder = globalZOrder;
_textureID = textureID;
_blendType = blendType;
_glProgramState = glProgramState;
_vertexBuffer = vertexBuffer;
@ -143,27 +147,34 @@ void MeshCommand::init(float globalZOrder,
_mv.set(mv);
_is3D = true;
if (!_stateBlock) {
_stateBlock = RenderState::StateBlock::create();
CC_SAFE_RETAIN(_stateBlock);
}
_stateBlock->setBlendFunc(blendType);
}
void MeshCommand::setCullFaceEnabled(bool enable)
{
CCASSERT(!_material, "If using material, you should call material->setCullFace()");
_cullFaceEnabled = enable;
_stateBlock->setCullFace(enable);
}
void MeshCommand::setCullFace(GLenum cullFace)
{
CCASSERT(!_material, "If using material, you should call material->setCullFaceSide()");
_cullFace = cullFace;
_stateBlock->setCullFaceSide((RenderState::CullFaceSide)cullFace);
}
void MeshCommand::setDepthTestEnabled(bool enable)
{
CCASSERT(!_material, "If using material, you should call material->setDepthTest()");
_depthTestEnabled = enable;
_stateBlock->setDepthTest(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()");
_forceDepthWrite = enable;
_depthWriteEnabled = enable;
_stateBlock->setDepthWrite(enable);
}
void MeshCommand::setDisplayColor(const Vec4& color)
@ -205,16 +216,18 @@ void MeshCommand::setTransparent(bool value)
if (_isTransparent && !_forceDepthWrite)
{
_depthWriteEnabled = false;
_stateBlock->setDepthWrite(false);
}
else
{
_depthWriteEnabled = true;
_stateBlock->setDepthWrite(true);
}
}
MeshCommand::~MeshCommand()
{
CC_SAFE_RELEASE(_stateBlock);
releaseVAO();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
Director::getInstance()->getEventDispatcher()->removeEventListener(_rendererRecreatedListener);
@ -227,64 +240,8 @@ void MeshCommand::applyRenderState()
// blend and texture
GL::bindTexture2D(_textureID);
GL::blendFunc(_blendType.src, _blendType.dst);
// cull face
_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);
}
_stateBlock->bind();
}
void MeshCommand::genMaterialID(GLuint texID, void* glProgramState, GLuint vertexBuffer, GLuint indexBuffer, BlendFunc blend)
@ -353,9 +310,6 @@ void MeshCommand::batchDraw()
// Draw
glDrawElements(_primitive, (GLsizei)_indexCount, _indexFormat, 0);
CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, _indexCount);
//restore render state
restoreRenderState();
}
}
void MeshCommand::postBatchDraw()
@ -404,9 +358,6 @@ void MeshCommand::execute()
glDrawElements(_primitive, (GLsizei)_indexCount, _indexFormat, 0);
CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, _indexCount);
//restore render state
restoreRenderState();
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

View File

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

View File

@ -749,26 +749,8 @@ void RenderState::StateBlock::setBlend(bool enabled)
void RenderState::StateBlock::setBlendFunc(const BlendFunc& blendFunc)
{
if (blendFunc == BlendFunc::DISABLE)
{
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);
}
setBlendSrc((RenderState::Blend)blendFunc.src);
setBlendDst((RenderState::Blend)blendFunc.dst);
}
void RenderState::StateBlock::setBlendSrc(Blend blend)

View File

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

View File

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