Skip to content

Commit 18e1214

Browse files
authored
Adds gl::ScopedColorMask and gl::ScopedStencilMask. (#2324)
* Adds gl::ScopedColorMask and gl::ScopedStencilMask. * Changed the implementation of gl::ScopedColorMask and gl::ScopedStencilMask to use gl::Context instead of querying the OpenGL state. --------- Co-authored-by: paulhoux <paulhoux@users.noreply.github.com>
1 parent b4eaa2f commit 18e1214

File tree

4 files changed

+182
-0
lines changed

4 files changed

+182
-0
lines changed

include/cinder/gl/Context.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,28 @@ class CI_API Context {
170170
void popFrontFace( bool forceRestore = false );
171171
//! Returns the winding order defining front-facing polygons, either \c GL_CW or \c GL_CCW (the default).
172172
GLenum getFrontFace();
173+
174+
//! Set the current color mask, which enables and disables writing of frame buffer color components.
175+
void colorMask( bool red, bool green, bool blue, bool alpha );
176+
//! Push the current color mask, which enables and disables writing of frame buffer color components.
177+
void pushColorMask( bool red, bool green, bool blue, bool alpha );
178+
//! Pops the current color mask, which enables and disables writing of frame buffer color components.
179+
void popColorMask( bool forceRestore = false );
180+
//! 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).
181+
glm::bvec4 getColorMask();
182+
183+
//! Set the current stencil mask, which controls the front and back writing of individual bits in the stencil planes (front and back).
184+
void stencilMask( GLuint mask );
185+
//! Set the current stencil mask, which controls the front and back writing of individual bits in the stencil planes (front and back).
186+
void stencilMask( GLuint front, GLuint back );
187+
//! Push the current stencil mask, which controls the front and back writing of individual bits in the stencil planes (front and back).
188+
void pushStencilMask( GLuint mask );
189+
//! Push the current stencil mask, which controls the front and back writing of individual bits in the stencil planes (front and back).
190+
void pushStencilMask( GLuint front, GLuint back );
191+
//! Pops the current stencil mask, which controls the front and back writing of individual bits in the stencil planes (front and back).
192+
void popStencilMask( bool forceRestore = false );
193+
//! Returns the current stencil mask, which controls the front and back writing of individual bits in the stencil planes (front and back).
194+
glm::u8vec2 getStencilMask();
173195

174196
#if ! defined( CINDER_GL_ES )
175197
//! 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.
@@ -535,6 +557,9 @@ class CI_API Context {
535557
std::vector<GLenum> mCullFaceStack;
536558
std::vector<GLenum> mFrontFaceStack;
537559

560+
std::vector<glm::bvec4> mColorMaskStack;
561+
std::vector<glm::u8vec2> mStencilMaskStack;
562+
538563
#if ! defined( CINDER_GL_ES )
539564
std::vector<GLenum> mLogicOpStack;
540565
std::vector<GLenum> mPolygonModeStack;

include/cinder/gl/scoped.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,30 @@ struct CI_API ScopedFrontFace : private Noncopyable {
360360
Context *mCtx;
361361
};
362362

363+
//! Scopes writing of frame buffer color components
364+
class ScopedColorMask : private Noncopyable {
365+
public:
366+
//! Values for \a red, \a green, \a blue and \a alpha may be \c GL_TRUE or \c GL_FALSE
367+
ScopedColorMask( GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha );
368+
~ScopedColorMask();
369+
370+
private:
371+
Context *mCtx;
372+
};
373+
374+
//! Scopes the front and back writing of individual bits in the stencil planes (front and back)
375+
class ScopedStencilMask : private Noncopyable {
376+
public:
377+
//! Values for \a mask may be between \c 0x00 and \c 0xFF
378+
ScopedStencilMask( GLuint mask );
379+
//! Values for \a front and \a back may be between \c 0x00 and \c 0xFF
380+
ScopedStencilMask( GLuint front, GLuint back );
381+
~ScopedStencilMask();
382+
383+
private:
384+
Context *mCtx;
385+
};
386+
363387
#if defined( CINDER_GL_HAS_KHR_DEBUG )
364388

365389
//! Scopes debug group message

src/cinder/gl/Context.cpp

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,12 @@ Context::Context( const std::shared_ptr<PlatformData> &platformData )
8787
#endif
8888
mDefaultArrayVboIdx = 0;
8989

90+
// initial state for color mask is enabled
91+
mColorMaskStack.emplace_back( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
92+
93+
// initial state for stencil mask is all bits enabled
94+
mStencilMaskStack.emplace_back( 0xFF, 0xFF );
95+
9096
// initial state for depth mask is enabled
9197
mBoolStateStack[GL_DEPTH_WRITEMASK] = vector<GLboolean>();
9298
mBoolStateStack[GL_DEPTH_WRITEMASK].push_back( GL_TRUE );
@@ -470,6 +476,101 @@ GLenum Context::getFrontFace()
470476
return mFrontFaceStack.back();
471477
}
472478

479+
//////////////////////////////////////////////////////////////////
480+
// ColorMask
481+
void Context::colorMask( bool red, bool green, bool blue, bool alpha )
482+
{
483+
if( setStackState( mColorMaskStack, glm::bvec4( red, green, blue, alpha ) ) ) {
484+
glColorMask( red, green, blue, alpha );
485+
}
486+
}
487+
488+
void Context::pushColorMask( bool red, bool green, bool blue, bool alpha )
489+
{
490+
if( pushStackState( mColorMaskStack, glm::bvec4( red, green, blue, alpha ) ) ) {
491+
glColorMask( red, green, blue, alpha );
492+
}
493+
}
494+
495+
void Context::popColorMask( bool forceRestore )
496+
{
497+
if( mColorMaskStack.empty() )
498+
CI_LOG_E( "Color mask stack underflow" );
499+
else if( popStackState( mColorMaskStack ) || forceRestore ) {
500+
const auto mask = getColorMask();
501+
glColorMask( mask.r, mask.g, mask.b, mask.a );
502+
}
503+
}
504+
505+
glm::bvec4 Context::getColorMask()
506+
{
507+
if( mColorMaskStack.empty() ) {
508+
GLboolean queriedBool[4];
509+
glGetBooleanv( GL_COLOR_WRITEMASK, queriedBool );
510+
mColorMaskStack.emplace_back( queriedBool[0], queriedBool[1], queriedBool[2], queriedBool[3] ); // push twice
511+
mColorMaskStack.emplace_back( queriedBool[0], queriedBool[1], queriedBool[2], queriedBool[3] );
512+
}
513+
514+
return mColorMaskStack.back();
515+
}
516+
517+
//////////////////////////////////////////////////////////////////
518+
// StencilMask
519+
void Context::stencilMask( GLuint mask )
520+
{
521+
if( setStackState( mStencilMaskStack, glm::u8vec2( mask, mask ) ) ) {
522+
glStencilMask( mask );
523+
}
524+
}
525+
526+
void Context::stencilMask( GLuint front, GLuint back )
527+
{
528+
if( setStackState( mStencilMaskStack, glm::u8vec2( front, back ) ) ) {
529+
glStencilMaskSeparate( GL_FRONT, front );
530+
glStencilMaskSeparate( GL_BACK, back );
531+
}
532+
}
533+
534+
void Context::pushStencilMask( GLuint mask )
535+
{
536+
if( pushStackState( mStencilMaskStack, glm::u8vec2( mask, mask ) ) ) {
537+
glStencilMask( mask );
538+
}
539+
}
540+
541+
void Context::pushStencilMask( GLuint front, GLuint back )
542+
{
543+
if( pushStackState( mStencilMaskStack, glm::u8vec2( front, back ) ) ) {
544+
glStencilMaskSeparate( GL_FRONT, front );
545+
glStencilMaskSeparate( GL_BACK, back );
546+
}
547+
}
548+
549+
void Context::popStencilMask( bool forceRestore )
550+
{
551+
if( mStencilMaskStack.empty() )
552+
CI_LOG_E( "Stencil mask stack underflow" );
553+
else if( popStackState( mStencilMaskStack ) || forceRestore ) {
554+
const auto mask = getStencilMask();
555+
glStencilMaskSeparate( GL_FRONT, mask[0] );
556+
glStencilMaskSeparate( GL_BACK, mask[1] );
557+
}
558+
}
559+
560+
glm::u8vec2 Context::getStencilMask()
561+
{
562+
if( mStencilMaskStack.empty() ) {
563+
GLint queriedIntFront;
564+
GLint queriedIntBack;
565+
glGetIntegerv( GL_STENCIL_WRITEMASK, &queriedIntFront );
566+
glGetIntegerv( GL_STENCIL_BACK_WRITEMASK, &queriedIntBack );
567+
mStencilMaskStack.emplace_back( queriedIntFront, queriedIntBack ); // push twice
568+
mStencilMaskStack.emplace_back( queriedIntFront, queriedIntBack );
569+
}
570+
571+
return mStencilMaskStack.back();
572+
}
573+
473574
//////////////////////////////////////////////////////////////////
474575
// LogicOp
475576
#if ! defined( CINDER_GL_ES )

src/cinder/gl/scoped.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,38 @@ ScopedFrontFace::~ScopedFrontFace()
513513
mCtx->popFrontFace();
514514
}
515515

516+
///////////////////////////////////////////////////////////////////////////////////////////
517+
// ScopedColorMask
518+
ScopedColorMask::ScopedColorMask( GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha )
519+
: mCtx( gl::context() )
520+
{
521+
mCtx->pushColorMask( red, green, blue, alpha );
522+
}
523+
524+
ScopedColorMask::~ScopedColorMask()
525+
{
526+
mCtx->popColorMask();
527+
}
528+
529+
///////////////////////////////////////////////////////////////////////////////////////////
530+
// ScopedStencilMask
531+
ScopedStencilMask::ScopedStencilMask( GLuint mask )
532+
: mCtx( gl::context() )
533+
{
534+
mCtx->pushStencilMask( mask );
535+
}
536+
537+
ScopedStencilMask::ScopedStencilMask( GLuint front, GLuint back )
538+
: mCtx( gl::context() )
539+
{
540+
mCtx->pushStencilMask( front, back );
541+
}
542+
543+
ScopedStencilMask::~ScopedStencilMask()
544+
{
545+
mCtx->popStencilMask();
546+
}
547+
516548
///////////////////////////////////////////////////////////////////////////////////////////
517549
// ScopedDebugGroup
518550
#if defined( CINDER_GL_HAS_KHR_DEBUG )

0 commit comments

Comments
 (0)