Merge pull request #4898 from nutty898/develop_nutty_modify_framework_optimizeclipping

Develop nutty modify framework optimizeclipping
This commit is contained in:
James Chen 2014-01-05 21:58:36 -08:00
commit 0f374ce838
2 changed files with 202 additions and 74 deletions

View File

@ -25,6 +25,14 @@
#include "gui/UILayout.h" #include "gui/UILayout.h"
#include "gui/UIHelper.h" #include "gui/UIHelper.h"
#include "extensions/GUI/CCControlExtension/CCScale9Sprite.h" #include "extensions/GUI/CCControlExtension/CCScale9Sprite.h"
#include "kazmath/GL/matrix.h"
#include "CCGLProgram.h"
#include "CCShaderCache.h"
#include "CCDirector.h"
#include "CCDrawingPrimitives.h"
#include "CCRenderer.h"
#include "CCGroupCommand.h"
#include "CCCustomCommand.h"
NS_CC_BEGIN NS_CC_BEGIN
@ -34,6 +42,7 @@ static const int BACKGROUNDIMAGE_Z = (-1);
static const int BCAKGROUNDCOLORRENDERER_Z = (-2); static const int BCAKGROUNDCOLORRENDERER_Z = (-2);
static GLint g_sStencilBits = -1; static GLint g_sStencilBits = -1;
static GLint s_layer = -1;
Layout::Layout(): Layout::Layout():
_clippingEnabled(false), _clippingEnabled(false),
@ -54,11 +63,22 @@ _backGroundImageTextureSize(Size::ZERO),
_layoutType(LAYOUT_ABSOLUTE), _layoutType(LAYOUT_ABSOLUTE),
_clippingType(LAYOUT_CLIPPING_STENCIL), _clippingType(LAYOUT_CLIPPING_STENCIL),
_clippingStencil(nullptr), _clippingStencil(nullptr),
_handleScissor(false),
_scissorRectDirty(false), _scissorRectDirty(false),
_clippingRect(Rect::ZERO), _clippingRect(Rect::ZERO),
_clippingParent(nullptr), _clippingParent(nullptr),
_doLayoutDirty(true) _doLayoutDirty(true),
_currentStencilEnabled(GL_FALSE),
_currentStencilWriteMask(~0),
_currentStencilFunc(GL_ALWAYS),
_currentStencilRef(0),
_currentStencilValueMask(~0),
_currentStencilFail(GL_KEEP),
_currentStencilPassDepthFail(GL_KEEP),
_currentStencilPassDepthPass(GL_KEEP),
_currentDepthWriteMask(GL_TRUE),
_currentAlphaTestEnabled(GL_FALSE),
_currentAlphaTestFunc(GL_ALWAYS),
_currentAlphaTestRef(1)
{ {
_widgetType = WidgetTypeContainer; _widgetType = WidgetTypeContainer;
} }
@ -67,6 +87,24 @@ Layout::~Layout()
{ {
} }
void Layout::onEnter()
{
Widget::onEnter();
if (_clippingStencil)
{
_clippingStencil->onEnter();
}
}
void Layout::onExit()
{
Widget::onExit();
if (_clippingStencil)
{
_clippingStencil->onExit();
}
}
Layout* Layout::create() Layout* Layout::create()
{ {
Layout* layout = new Layout(); Layout* layout = new Layout();
@ -151,104 +189,150 @@ void Layout::sortAllChildren()
void Layout::stencilClippingVisit() void Layout::stencilClippingVisit()
{ {
if (!_clippingStencil || !_clippingStencil->isVisible()) if(!_visible)
{
Node::visit();
return; return;
}
if (g_sStencilBits < 1)
{
Node::visit();
return;
}
static GLint layer = -1;
if (layer + 1 == g_sStencilBits)
{
static bool once = true;
if (once)
{
char warning[200] = {0};
snprintf(warning, sizeof(warning), "Nesting more than %d stencils is not supported. Everything will be drawn without stencil for this node and its childs.", g_sStencilBits);
CCLOG("%s", warning);
once = false; kmGLPushMatrix();
transform();
//Add group command
Renderer* renderer = Director::getInstance()->getRenderer();
_groupCommand.init(0,_vertexZ);
renderer->addCommand(&_groupCommand);
renderer->pushGroup(_groupCommand.getRenderQueueID());
_beforeVisitCmdStencil.init(0,_vertexZ);
_beforeVisitCmdStencil.func = CC_CALLBACK_0(Layout::onBeforeVisitStencil, this);
renderer->addCommand(&_beforeVisitCmdStencil);
_clippingStencil->visit();
_afterDrawStencilCmd.init(0,_vertexZ);
_afterDrawStencilCmd.func = CC_CALLBACK_0(Layout::onAfterDrawStencil, this);
renderer->addCommand(&_afterDrawStencilCmd);
int i = 0;
if(!_children.empty())
{
sortAllChildren();
// draw children zOrder < 0
for( ; i < _children.size(); i++ )
{
auto node = _children.at(i);
if ( node && node->getZOrder() < 0 )
node->visit();
else
break;
} }
Node::visit(); // self draw
return; this->draw();
for(auto it=_children.cbegin()+i; it != _children.cend(); ++it)
(*it)->visit();
} }
layer++; else
GLint mask_layer = 0x1 << layer; {
this->draw();
}
_afterVisitCmdStencil.init(0,_vertexZ);
_afterVisitCmdStencil.func = CC_CALLBACK_0(Layout::onAfterVisitStencil, this);
renderer->addCommand(&_afterVisitCmdStencil);
renderer->popGroup();
kmGLPopMatrix();
}
void Layout::onBeforeVisitStencil()
{
s_layer++;
GLint mask_layer = 0x1 << s_layer;
GLint mask_layer_l = mask_layer - 1; GLint mask_layer_l = mask_layer - 1;
GLint mask_layer_le = mask_layer | mask_layer_l; _mask_layer_le = mask_layer | mask_layer_l;
GLboolean currentStencilEnabled = GL_FALSE; _currentStencilEnabled = glIsEnabled(GL_STENCIL_TEST);
GLuint currentStencilWriteMask = ~0; glGetIntegerv(GL_STENCIL_WRITEMASK, (GLint *)&_currentStencilWriteMask);
GLenum currentStencilFunc = GL_ALWAYS; glGetIntegerv(GL_STENCIL_FUNC, (GLint *)&_currentStencilFunc);
GLint currentStencilRef = 0; glGetIntegerv(GL_STENCIL_REF, &_currentStencilRef);
GLuint currentStencilValueMask = ~0; glGetIntegerv(GL_STENCIL_VALUE_MASK, (GLint *)&_currentStencilValueMask);
GLenum currentStencilFail = GL_KEEP; glGetIntegerv(GL_STENCIL_FAIL, (GLint *)&_currentStencilFail);
GLenum currentStencilPassDepthFail = GL_KEEP; glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, (GLint *)&_currentStencilPassDepthFail);
GLenum currentStencilPassDepthPass = GL_KEEP; glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, (GLint *)&_currentStencilPassDepthPass);
currentStencilEnabled = glIsEnabled(GL_STENCIL_TEST);
glGetIntegerv(GL_STENCIL_WRITEMASK, (GLint *)&currentStencilWriteMask);
glGetIntegerv(GL_STENCIL_FUNC, (GLint *)&currentStencilFunc);
glGetIntegerv(GL_STENCIL_REF, &currentStencilRef);
glGetIntegerv(GL_STENCIL_VALUE_MASK, (GLint *)&currentStencilValueMask);
glGetIntegerv(GL_STENCIL_FAIL, (GLint *)&currentStencilFail);
glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, (GLint *)&currentStencilPassDepthFail);
glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, (GLint *)&currentStencilPassDepthPass);
glEnable(GL_STENCIL_TEST); glEnable(GL_STENCIL_TEST);
CHECK_GL_ERROR_DEBUG(); CHECK_GL_ERROR_DEBUG();
glStencilMask(mask_layer); glStencilMask(mask_layer);
GLboolean currentDepthWriteMask = GL_TRUE; glGetBooleanv(GL_DEPTH_WRITEMASK, &_currentDepthWriteMask);
glGetBooleanv(GL_DEPTH_WRITEMASK, &currentDepthWriteMask);
glDepthMask(GL_FALSE); glDepthMask(GL_FALSE);
glStencilFunc(GL_NEVER, mask_layer, mask_layer); glStencilFunc(GL_NEVER, mask_layer, mask_layer);
glStencilOp(GL_ZERO, GL_KEEP, GL_KEEP); glStencilOp(GL_ZERO, GL_KEEP, GL_KEEP);
kmGLMatrixMode(KM_GL_MODELVIEW); kmGLMatrixMode(KM_GL_MODELVIEW);
kmGLPushMatrix(); kmGLPushMatrix();
kmGLLoadIdentity(); kmGLLoadIdentity();
kmGLMatrixMode(KM_GL_PROJECTION); kmGLMatrixMode(KM_GL_PROJECTION);
kmGLPushMatrix(); kmGLPushMatrix();
kmGLLoadIdentity(); kmGLLoadIdentity();
DrawPrimitives::drawSolidRect(Point(-1,-1), Point(1,1), Color4F(1, 1, 1, 1)); DrawPrimitives::drawSolidRect(Point(-1,-1), Point(1,1), Color4F(1, 1, 1, 1));
kmGLMatrixMode(KM_GL_PROJECTION); kmGLMatrixMode(KM_GL_PROJECTION);
kmGLPopMatrix(); kmGLPopMatrix();
kmGLMatrixMode(KM_GL_MODELVIEW); kmGLMatrixMode(KM_GL_MODELVIEW);
kmGLPopMatrix(); kmGLPopMatrix();
glStencilFunc(GL_NEVER, mask_layer, mask_layer); glStencilFunc(GL_NEVER, mask_layer, mask_layer);
glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP); glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP);
}
kmGLPushMatrix(); void Layout::onAfterDrawStencil()
transform(); {
_clippingStencil->visit(); glDepthMask(_currentDepthWriteMask);
kmGLPopMatrix(); glStencilFunc(GL_EQUAL, _mask_layer_le, _mask_layer_le);
glDepthMask(currentDepthWriteMask);
glStencilFunc(GL_EQUAL, mask_layer_le, mask_layer_le);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
Node::visit(); }
glStencilFunc(currentStencilFunc, currentStencilRef, currentStencilValueMask);
glStencilOp(currentStencilFail, currentStencilPassDepthFail, currentStencilPassDepthPass);
glStencilMask(currentStencilWriteMask); void Layout::onAfterVisitStencil()
if (!currentStencilEnabled) {
glStencilFunc(_currentStencilFunc, _currentStencilRef, _currentStencilValueMask);
glStencilOp(_currentStencilFail, _currentStencilPassDepthFail, _currentStencilPassDepthPass);
glStencilMask(_currentStencilWriteMask);
if (!_currentStencilEnabled)
{ {
glDisable(GL_STENCIL_TEST); glDisable(GL_STENCIL_TEST);
} }
layer--; s_layer--;
}
void Layout::onBeforeVisitScissor()
{
Rect clippingRect = getClippingRect();
glEnable(GL_SCISSOR_TEST);
EGLView::getInstance()->setScissorInPoints(clippingRect.origin.x, clippingRect.origin.y, clippingRect.size.width, clippingRect.size.height);
}
void Layout::onAfterVisitScissor()
{
glDisable(GL_SCISSOR_TEST);
} }
void Layout::scissorClippingVisit() void Layout::scissorClippingVisit()
{ {
Rect clippingRect = getClippingRect(); Renderer* renderer = Director::getInstance()->getRenderer();
if (_handleScissor)
{ _beforeVisitCmdScissor.init(0, _vertexZ);
glEnable(GL_SCISSOR_TEST); _beforeVisitCmdScissor.func = CC_CALLBACK_0(Layout::onBeforeVisitScissor, this);
} renderer->addCommand(&_beforeVisitCmdScissor);
EGLView::getInstance()->setScissorInPoints(clippingRect.origin.x, clippingRect.origin.y, clippingRect.size.width, clippingRect.size.height);
Node::visit(); Node::visit();
if (_handleScissor)
{ _afterVisitCmdScissor.init(0, _vertexZ);
glDisable(GL_SCISSOR_TEST); _afterVisitCmdScissor.func = CC_CALLBACK_0(Layout::onAfterVisitScissor, this);
} renderer->addCommand(&_afterVisitCmdScissor);
} }
void Layout::setClippingEnabled(bool able) void Layout::setClippingEnabled(bool able)
@ -262,16 +346,31 @@ void Layout::setClippingEnabled(bool able)
{ {
case LAYOUT_CLIPPING_STENCIL: case LAYOUT_CLIPPING_STENCIL:
if (able) if (able)
{
static bool once = true;
if (once)
{ {
glGetIntegerv(GL_STENCIL_BITS, &g_sStencilBits); glGetIntegerv(GL_STENCIL_BITS, &g_sStencilBits);
if (g_sStencilBits <= 0)
{
CCLOG("Stencil buffer is not enabled.");
}
once = false;
}
_clippingStencil = DrawNode::create(); _clippingStencil = DrawNode::create();
if (_running)
{
_clippingStencil->onEnter(); _clippingStencil->onEnter();
}
_clippingStencil->retain(); _clippingStencil->retain();
setStencilClippingSize(_size); setStencilClippingSize(_size);
} }
else else
{
if (_running)
{ {
_clippingStencil->onExit(); _clippingStencil->onExit();
}
_clippingStencil->release(); _clippingStencil->release();
_clippingStencil = nullptr; _clippingStencil = nullptr;
} }
@ -310,7 +409,6 @@ void Layout::setStencilClippingSize(const Size &size)
const Rect& Layout::getClippingRect() const Rect& Layout::getClippingRect()
{ {
_handleScissor = true;
Point worldPos = convertToWorldSpace(Point::ZERO); Point worldPos = convertToWorldSpace(Point::ZERO);
AffineTransform t = getNodeToWorldAffineTransform(); AffineTransform t = getNodeToWorldAffineTransform();
float scissorWidth = _size.width*t.a; float scissorWidth = _size.width*t.a;
@ -329,11 +427,6 @@ const Rect& Layout::getClippingRect()
{ {
_clippingParent = parent; _clippingParent = parent;
firstClippingParentFounded = true; firstClippingParentFounded = true;
}
if (parent->_clippingType == LAYOUT_CLIPPING_SCISSOR)
{
_handleScissor = false;
break; break;
} }
} }

View File

@ -214,6 +214,9 @@ public:
virtual void sortAllChildren() override; virtual void sortAllChildren() override;
void requestDoLayout(); void requestDoLayout();
virtual void onEnter() override;
virtual void onExit() override;
protected: protected:
//override "init" method of widget. //override "init" method of widget.
virtual bool init() override; virtual bool init() override;
@ -235,6 +238,14 @@ protected:
void setStencilClippingSize(const Size& size); void setStencilClippingSize(const Size& size);
const Rect& getClippingRect(); const Rect& getClippingRect();
virtual void doLayout(); virtual void doLayout();
//clipping
void onBeforeVisitStencil();
void onAfterDrawStencil();
void onAfterVisitStencil();
void onBeforeVisitScissor();
void onAfterVisitScissor();
protected: protected:
bool _clippingEnabled; bool _clippingEnabled;
@ -256,11 +267,35 @@ protected:
LayoutType _layoutType; LayoutType _layoutType;
LayoutClippingType _clippingType; LayoutClippingType _clippingType;
DrawNode* _clippingStencil; DrawNode* _clippingStencil;
bool _handleScissor;
bool _scissorRectDirty; bool _scissorRectDirty;
Rect _clippingRect; Rect _clippingRect;
Layout* _clippingParent; Layout* _clippingParent;
bool _doLayoutDirty; bool _doLayoutDirty;
//clipping
GLboolean _currentStencilEnabled;
GLuint _currentStencilWriteMask;
GLenum _currentStencilFunc;
GLint _currentStencilRef;
GLuint _currentStencilValueMask;
GLenum _currentStencilFail;
GLenum _currentStencilPassDepthFail;
GLenum _currentStencilPassDepthPass;
GLboolean _currentDepthWriteMask;
GLboolean _currentAlphaTestEnabled;
GLenum _currentAlphaTestFunc;
GLclampf _currentAlphaTestRef;
GLint _mask_layer_le;
GroupCommand _groupCommand;
CustomCommand _beforeVisitCmdStencil;
CustomCommand _afterDrawStencilCmd;
CustomCommand _afterVisitCmdStencil;
CustomCommand _beforeVisitCmdScissor;
CustomCommand _afterVisitCmdScissor;
}; };
} }