Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds gl::ScopedColorMask and gl::ScopedStencilMask. #2324

Merged
merged 2 commits into from
Jan 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions include/cinder/gl/Context.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,28 @@ class CI_API Context {
void popFrontFace( bool forceRestore = false );
//! Returns the winding order defining front-facing polygons, either \c GL_CW or \c GL_CCW (the default).
GLenum getFrontFace();

//! Set the current color mask, which enables and disables writing of frame buffer color components.
void colorMask( bool red, bool green, bool blue, bool alpha );
//! Push the current color mask, which enables and disables writing of frame buffer color components.
void pushColorMask( bool red, bool green, bool blue, bool alpha );
//! Pops the current color mask, which enables and disables writing of frame buffer color components.
void popColorMask( bool forceRestore = false );
//! Returns the current color mask, which enables and disables writing of frame buffer color components. Default is \c GL_TRUE for all 4 components (red, green, blue, alpha).
glm::bvec4 getColorMask();

//! Set the current stencil mask, which controls the front and back writing of individual bits in the stencil planes (front and back).
void stencilMask( GLuint mask );
//! Set the current stencil mask, which controls the front and back writing of individual bits in the stencil planes (front and back).
void stencilMask( GLuint front, GLuint back );
//! Push the current stencil mask, which controls the front and back writing of individual bits in the stencil planes (front and back).
void pushStencilMask( GLuint mask );
//! Push the current stencil mask, which controls the front and back writing of individual bits in the stencil planes (front and back).
void pushStencilMask( GLuint front, GLuint back );
//! Pops the current stencil mask, which controls the front and back writing of individual bits in the stencil planes (front and back).
void popStencilMask( bool forceRestore = false );
//! Returns the current stencil mask, which controls the front and back writing of individual bits in the stencil planes (front and back).
glm::u8vec2 getStencilMask();

#if ! defined( CINDER_GL_ES )
//! Analogous to glLogicOp( \a mode ). Valid arguments are \c GL_CLEAR, \c GL_SET, \c GL_COPY, \c GL_COPY_INVERTED, \c GL_NOOP, \c GL_INVERT, \c GL_AND, \c GL_NAND, \c GL_OR, \c GL_NOR, \c GL_XOR, \c GL_EQUIV, \c GL_AND_REVERSE, \c GL_AND_INVERTED, \c GL_OR_REVERSE, or \c GL_OR_INVERTED.
Expand Down Expand Up @@ -535,6 +557,9 @@ class CI_API Context {
std::vector<GLenum> mCullFaceStack;
std::vector<GLenum> mFrontFaceStack;

std::vector<glm::bvec4> mColorMaskStack;
std::vector<glm::u8vec2> mStencilMaskStack;

#if ! defined( CINDER_GL_ES )
std::vector<GLenum> mLogicOpStack;
std::vector<GLenum> mPolygonModeStack;
Expand Down
24 changes: 24 additions & 0 deletions include/cinder/gl/scoped.h
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,30 @@ struct CI_API ScopedFrontFace : private Noncopyable {
Context *mCtx;
};

//! Scopes writing of frame buffer color components
class ScopedColorMask : private Noncopyable {
public:
//! Values for \a red, \a green, \a blue and \a alpha may be \c GL_TRUE or \c GL_FALSE
ScopedColorMask( GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha );
~ScopedColorMask();

private:
Context *mCtx;
};

//! Scopes the front and back writing of individual bits in the stencil planes (front and back)
class ScopedStencilMask : private Noncopyable {
public:
//! Values for \a mask may be between \c 0x00 and \c 0xFF
ScopedStencilMask( GLuint mask );
//! Values for \a front and \a back may be between \c 0x00 and \c 0xFF
ScopedStencilMask( GLuint front, GLuint back );
~ScopedStencilMask();

private:
Context *mCtx;
};

#if defined( CINDER_GL_HAS_KHR_DEBUG )

//! Scopes debug group message
Expand Down
101 changes: 101 additions & 0 deletions src/cinder/gl/Context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ Context::Context( const std::shared_ptr<PlatformData> &platformData )
#endif
mDefaultArrayVboIdx = 0;

// initial state for color mask is enabled
mColorMaskStack.emplace_back( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );

// initial state for stencil mask is all bits enabled
mStencilMaskStack.emplace_back( 0xFF, 0xFF );

// initial state for depth mask is enabled
mBoolStateStack[GL_DEPTH_WRITEMASK] = vector<GLboolean>();
mBoolStateStack[GL_DEPTH_WRITEMASK].push_back( GL_TRUE );
Expand Down Expand Up @@ -470,6 +476,101 @@ GLenum Context::getFrontFace()
return mFrontFaceStack.back();
}

//////////////////////////////////////////////////////////////////
// ColorMask
void Context::colorMask( bool red, bool green, bool blue, bool alpha )
{
if( setStackState( mColorMaskStack, glm::bvec4( red, green, blue, alpha ) ) ) {
glColorMask( red, green, blue, alpha );
}
}

void Context::pushColorMask( bool red, bool green, bool blue, bool alpha )
{
if( pushStackState( mColorMaskStack, glm::bvec4( red, green, blue, alpha ) ) ) {
glColorMask( red, green, blue, alpha );
}
}

void Context::popColorMask( bool forceRestore )
{
if( mColorMaskStack.empty() )
CI_LOG_E( "Color mask stack underflow" );
else if( popStackState( mColorMaskStack ) || forceRestore ) {
const auto mask = getColorMask();
glColorMask( mask.r, mask.g, mask.b, mask.a );
}
}

glm::bvec4 Context::getColorMask()
{
if( mColorMaskStack.empty() ) {
GLboolean queriedBool[4];
glGetBooleanv( GL_COLOR_WRITEMASK, queriedBool );
mColorMaskStack.emplace_back( queriedBool[0], queriedBool[1], queriedBool[2], queriedBool[3] ); // push twice
mColorMaskStack.emplace_back( queriedBool[0], queriedBool[1], queriedBool[2], queriedBool[3] );
}

return mColorMaskStack.back();
}

//////////////////////////////////////////////////////////////////
// StencilMask
void Context::stencilMask( GLuint mask )
{
if( setStackState( mStencilMaskStack, glm::u8vec2( mask, mask ) ) ) {
glStencilMask( mask );
}
}

void Context::stencilMask( GLuint front, GLuint back )
{
if( setStackState( mStencilMaskStack, glm::u8vec2( front, back ) ) ) {
glStencilMaskSeparate( GL_FRONT, front );
glStencilMaskSeparate( GL_BACK, back );
}
}

void Context::pushStencilMask( GLuint mask )
{
if( pushStackState( mStencilMaskStack, glm::u8vec2( mask, mask ) ) ) {
glStencilMask( mask );
}
}

void Context::pushStencilMask( GLuint front, GLuint back )
{
if( pushStackState( mStencilMaskStack, glm::u8vec2( front, back ) ) ) {
glStencilMaskSeparate( GL_FRONT, front );
glStencilMaskSeparate( GL_BACK, back );
}
}

void Context::popStencilMask( bool forceRestore )
{
if( mStencilMaskStack.empty() )
CI_LOG_E( "Stencil mask stack underflow" );
else if( popStackState( mStencilMaskStack ) || forceRestore ) {
const auto mask = getStencilMask();
glStencilMaskSeparate( GL_FRONT, mask[0] );
glStencilMaskSeparate( GL_BACK, mask[1] );
}
}

glm::u8vec2 Context::getStencilMask()
{
if( mStencilMaskStack.empty() ) {
GLint queriedIntFront;
GLint queriedIntBack;
glGetIntegerv( GL_STENCIL_WRITEMASK, &queriedIntFront );
glGetIntegerv( GL_STENCIL_BACK_WRITEMASK, &queriedIntBack );
mStencilMaskStack.emplace_back( queriedIntFront, queriedIntBack ); // push twice
mStencilMaskStack.emplace_back( queriedIntFront, queriedIntBack );
}

return mStencilMaskStack.back();
}

//////////////////////////////////////////////////////////////////
// LogicOp
#if ! defined( CINDER_GL_ES )
Expand Down
32 changes: 32 additions & 0 deletions src/cinder/gl/scoped.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,38 @@ ScopedFrontFace::~ScopedFrontFace()
mCtx->popFrontFace();
}

///////////////////////////////////////////////////////////////////////////////////////////
// ScopedColorMask
ScopedColorMask::ScopedColorMask( GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha )
: mCtx( gl::context() )
{
mCtx->pushColorMask( red, green, blue, alpha );
}

ScopedColorMask::~ScopedColorMask()
{
mCtx->popColorMask();
}

///////////////////////////////////////////////////////////////////////////////////////////
// ScopedStencilMask
ScopedStencilMask::ScopedStencilMask( GLuint mask )
: mCtx( gl::context() )
{
mCtx->pushStencilMask( mask );
}

ScopedStencilMask::ScopedStencilMask( GLuint front, GLuint back )
: mCtx( gl::context() )
{
mCtx->pushStencilMask( front, back );
}

ScopedStencilMask::~ScopedStencilMask()
{
mCtx->popStencilMask();
}

///////////////////////////////////////////////////////////////////////////////////////////
// ScopedDebugGroup
#if defined( CINDER_GL_HAS_KHR_DEBUG )
Expand Down