mirror of https://github.com/axmolengine/axmol.git
Merge pull request #4898 from nutty898/develop_nutty_modify_framework_optimizeclipping
Develop nutty modify framework optimizeclipping
This commit is contained in:
commit
0f374ce838
|
@ -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 *)¤tStencilWriteMask);
|
|
||||||
glGetIntegerv(GL_STENCIL_FUNC, (GLint *)¤tStencilFunc);
|
|
||||||
glGetIntegerv(GL_STENCIL_REF, ¤tStencilRef);
|
|
||||||
glGetIntegerv(GL_STENCIL_VALUE_MASK, (GLint *)¤tStencilValueMask);
|
|
||||||
glGetIntegerv(GL_STENCIL_FAIL, (GLint *)¤tStencilFail);
|
|
||||||
glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, (GLint *)¤tStencilPassDepthFail);
|
|
||||||
glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, (GLint *)¤tStencilPassDepthPass);
|
|
||||||
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, ¤tDepthWriteMask);
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue