@@ -571,6 +571,248 @@ glm::u8vec2 Context::getStencilMask()
571571 return mStencilMaskStack .back ();
572572}
573573
574+ void Context::stencilOp (GLenum stencilFail, GLenum depthFail, GLenum depthPass)
575+ {
576+ stencilOpSeparate ( GL_FRONT_AND_BACK, stencilFail, depthFail, depthPass );
577+ }
578+
579+ void Context::stencilOpSeparate (GLenum face, GLenum stencilFail, GLenum depthFail, GLenum depthPass)
580+ {
581+ switch (face)
582+ {
583+ case GL_FRONT:
584+ if (setStackState (mStencilOpFrontStack , StencilOp{ stencilFail, depthFail, depthPass }))
585+ glStencilOpSeparate (GL_FRONT, stencilFail, depthFail, depthPass);
586+ break ;
587+ case GL_BACK:
588+ if (setStackState (mStencilOpBackStack , StencilOp{ stencilFail, depthFail, depthPass }))
589+ glStencilOpSeparate (GL_BACK, stencilFail, depthFail, depthPass);
590+ break ;
591+ default :
592+ if (setStackState (mStencilOpFrontStack , StencilOp{ stencilFail, depthFail, depthPass }))
593+ glStencilOpSeparate (GL_FRONT, stencilFail, depthFail, depthPass);
594+ if (setStackState (mStencilOpBackStack , StencilOp{ stencilFail, depthFail, depthPass }))
595+ glStencilOpSeparate (GL_BACK, stencilFail, depthFail, depthPass);
596+ break ;
597+ }
598+ }
599+
600+ void Context::pushStencilOp (GLenum stencilFail, GLenum depthFail, GLenum depthPass)
601+ {
602+ pushStencilOpSeparate ( GL_FRONT_AND_BACK, stencilFail, depthFail, depthPass );
603+ }
604+
605+ void Context::pushStencilOpSeparate (GLenum face, GLenum stencilFail, GLenum depthFail, GLenum depthPass)
606+ {
607+ switch (face)
608+ {
609+ case GL_FRONT:
610+ if (pushStackState (mStencilOpFrontStack , StencilOp{ stencilFail, depthFail, depthPass }))
611+ glStencilOpSeparate (GL_FRONT, stencilFail, depthFail, depthPass);
612+ break ;
613+ case GL_BACK:
614+ if (pushStackState (mStencilOpBackStack , StencilOp{ stencilFail, depthFail, depthPass }))
615+ glStencilOpSeparate (GL_BACK, stencilFail, depthFail, depthPass);
616+ break ;
617+ default :
618+ if (pushStackState (mStencilOpFrontStack , StencilOp{ stencilFail, depthFail, depthPass }))
619+ glStencilOpSeparate (GL_FRONT, stencilFail, depthFail, depthPass);
620+ if (pushStackState (mStencilOpBackStack , StencilOp{ stencilFail, depthFail, depthPass }))
621+ glStencilOpSeparate (GL_BACK, stencilFail, depthFail, depthPass);
622+ break ;
623+ }
624+ }
625+
626+ void Context::popStencilOp (bool forceRestore)
627+ {
628+ popStencilOpSeparate (GL_FRONT, forceRestore);
629+ popStencilOpSeparate (GL_BACK, forceRestore);
630+ }
631+
632+ void Context::popStencilOpSeparate (GLenum face, bool forceRestore)
633+ {
634+ switch (face)
635+ {
636+ case GL_FRONT:
637+ if (mStencilOpFrontStack .empty ())
638+ CI_LOG_E (" Stencil operation stack underflow" );
639+ else if (popStackState (mStencilOpFrontStack ) || forceRestore) {
640+ const auto op = getStencilOp ();
641+ glStencilOpSeparate (GL_FRONT, op.first .stencilFail , op.first .depthFail , op.first .depthPass );
642+ }
643+ break ;
644+ case GL_BACK:
645+ if (mStencilOpBackStack .empty ())
646+ CI_LOG_E (" Stencil operation stack underflow" );
647+ else if (popStackState (mStencilOpBackStack ) || forceRestore) {
648+ const auto op = getStencilOp ();
649+ glStencilOpSeparate (GL_BACK, op.second .stencilFail , op.second .depthFail , op.second .depthPass );
650+ }
651+ break ;
652+ default :
653+ if (mStencilOpFrontStack .empty () || mStencilOpBackStack .empty ())
654+ CI_LOG_E (" Stencil operation stack underflow" );
655+ else {
656+ if (popStackState (mStencilOpFrontStack ) || forceRestore) {
657+ const auto op = getStencilOp ();
658+ glStencilOpSeparate (GL_FRONT, op.first .stencilFail , op.first .depthFail , op.first .depthPass );
659+ }
660+ if (popStackState (mStencilOpBackStack ) || forceRestore) {
661+ const auto op = getStencilOp ();
662+ glStencilOpSeparate (GL_BACK, op.second .stencilFail , op.second .depthFail , op.second .depthPass );
663+ }
664+ }
665+ break ;
666+ }
667+ }
668+
669+ std::pair<Context::StencilOp, Context::StencilOp> Context::getStencilOp ()
670+ {
671+ if (mStencilOpFrontStack .empty ()) {
672+ GLint queriedInt[3 ];
673+ glGetIntegerv (GL_STENCIL_FAIL, queriedInt);
674+ glGetIntegerv (GL_STENCIL_PASS_DEPTH_FAIL, queriedInt + 1 );
675+ glGetIntegerv (GL_STENCIL_PASS_DEPTH_PASS, queriedInt + 2 );
676+ // push twice in anticipation of later pop
677+ mStencilOpFrontStack .emplace_back (queriedInt[0 ], queriedInt[1 ], queriedInt[2 ]);
678+ mStencilOpFrontStack .emplace_back (queriedInt[0 ], queriedInt[1 ], queriedInt[2 ]);
679+ }
680+
681+ if (mStencilOpBackStack .empty ()) {
682+ GLint queriedInt[3 ];
683+ glGetIntegerv (GL_STENCIL_BACK_FAIL, queriedInt);
684+ glGetIntegerv (GL_STENCIL_BACK_PASS_DEPTH_FAIL, queriedInt + 1 );
685+ glGetIntegerv (GL_STENCIL_BACK_PASS_DEPTH_PASS, queriedInt + 2 );
686+ // push twice in anticipation of later pop
687+ mStencilOpBackStack .emplace_back (queriedInt[0 ], queriedInt[1 ], queriedInt[2 ]);
688+ mStencilOpBackStack .emplace_back (queriedInt[0 ], queriedInt[1 ], queriedInt[2 ]);
689+ }
690+
691+ return std::make_pair (mStencilOpFrontStack .back (), mStencilOpBackStack .back ());
692+ }
693+
694+ void Context::stencilFunc (GLenum func, GLint ref, GLuint mask)
695+ {
696+ stencilFuncSeparate (GL_FRONT, func, ref, mask);
697+ stencilFuncSeparate (GL_BACK, func, ref, mask);
698+ }
699+
700+ void Context::stencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask)
701+ {
702+ switch (face)
703+ {
704+ case GL_FRONT:
705+ if (setStackState (mStencilFuncFrontStack , StencilFunc{ func, ref, mask }))
706+ glStencilFuncSeparate (GL_FRONT, func, ref, mask);
707+ break ;
708+ case GL_BACK:
709+ if (setStackState (mStencilFuncBackStack , StencilFunc{ func, ref, mask }))
710+ glStencilFuncSeparate (GL_BACK, func, ref, mask);
711+ break ;
712+ default :
713+ if (setStackState (mStencilFuncFrontStack , StencilFunc{ func, ref, mask }))
714+ glStencilFuncSeparate (GL_FRONT, func, ref, mask);
715+ if (setStackState (mStencilFuncBackStack , StencilFunc{ func, ref, mask }))
716+ glStencilFuncSeparate (GL_BACK, func, ref, mask);
717+ break ;
718+ }
719+ }
720+
721+ void Context::pushStencilFunc (GLenum func, GLint ref, GLuint mask)
722+ {
723+ pushStencilFuncSeparate (GL_FRONT, func, ref, mask);
724+ pushStencilFuncSeparate (GL_BACK, func, ref, mask);
725+ }
726+
727+ void Context::pushStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask)
728+ {
729+ switch (face)
730+ {
731+ case GL_FRONT:
732+ if (pushStackState (mStencilFuncFrontStack , StencilFunc{ func, ref, mask }))
733+ glStencilFuncSeparate (GL_FRONT, func, ref, mask);
734+ break ;
735+ case GL_BACK:
736+ if (pushStackState (mStencilFuncBackStack , StencilFunc{ func, ref, mask }))
737+ glStencilFuncSeparate (GL_BACK, func, ref, mask);
738+ break ;
739+ default :
740+ if (pushStackState (mStencilFuncFrontStack , StencilFunc{ func, ref, mask }))
741+ glStencilFuncSeparate (GL_FRONT, func, ref, mask);
742+ if (pushStackState (mStencilFuncBackStack , StencilFunc{ func, ref, mask }))
743+ glStencilFuncSeparate (GL_BACK, func, ref, mask);
744+ break ;
745+ }
746+ }
747+
748+ void Context::popStencilFunc (bool forceRestore)
749+ {
750+ popStencilFuncSeparate (GL_FRONT, forceRestore);
751+ popStencilFuncSeparate (GL_BACK, forceRestore);
752+ }
753+
754+ void Context::popStencilFuncSeparate (GLenum face, bool forceRestore)
755+ {
756+ switch (face)
757+ {
758+ case GL_FRONT:
759+ if (mStencilFuncFrontStack .empty ())
760+ CI_LOG_E (" Stencil function stack underflow" );
761+ else if (popStackState (mStencilFuncFrontStack ) || forceRestore) {
762+ const auto func = getStencilFunc ();
763+ glStencilFuncSeparate (GL_FRONT, func.first .func , func.first .ref , func.first .mask );
764+ }
765+ break ;
766+ case GL_BACK:
767+ if (mStencilFuncBackStack .empty ())
768+ CI_LOG_E (" Stencil function stack underflow" );
769+ else if (popStackState (mStencilFuncBackStack ) || forceRestore) {
770+ const auto func = getStencilFunc ();
771+ glStencilFuncSeparate (GL_BACK, func.second .func , func.second .ref , func.second .mask );
772+ }
773+ break ;
774+ default :
775+ if (mStencilFuncFrontStack .empty () || mStencilFuncBackStack .empty ())
776+ CI_LOG_E (" Stencil function stack underflow" );
777+ else {
778+ if (popStackState (mStencilFuncFrontStack ) || forceRestore) {
779+ const auto func = getStencilFunc ();
780+ glStencilFuncSeparate (GL_FRONT, func.first .func , func.first .ref , func.first .mask );
781+ }
782+ if (popStackState (mStencilFuncBackStack ) || forceRestore) {
783+ const auto func = getStencilFunc ();
784+ glStencilFuncSeparate (GL_BACK, func.second .func , func.second .ref , func.second .mask );
785+ }
786+ }
787+ break ;
788+ }
789+ }
790+
791+ std::pair<Context::StencilFunc, Context::StencilFunc> Context::getStencilFunc ()
792+ {
793+ if (mStencilFuncFrontStack .empty ()) {
794+ GLint queriedInt[3 ];
795+ glGetIntegerv (GL_STENCIL_FUNC, queriedInt);
796+ glGetIntegerv (GL_STENCIL_REF, queriedInt + 1 );
797+ glGetIntegerv (GL_STENCIL_VALUE_MASK, queriedInt + 2 );
798+ // push twice in anticipation of later pop
799+ mStencilFuncFrontStack .emplace_back (queriedInt[0 ], queriedInt[1 ], queriedInt[2 ]);
800+ mStencilFuncFrontStack .emplace_back (queriedInt[0 ], queriedInt[1 ], queriedInt[2 ]);
801+ }
802+
803+ if (mStencilFuncBackStack .empty ()) {
804+ GLint queriedInt[3 ];
805+ glGetIntegerv (GL_STENCIL_BACK_FUNC, queriedInt);
806+ glGetIntegerv (GL_STENCIL_BACK_REF, queriedInt + 1 );
807+ glGetIntegerv (GL_STENCIL_BACK_VALUE_MASK, queriedInt + 2 );
808+ // push twice in anticipation of later pop
809+ mStencilFuncBackStack .emplace_back (queriedInt[0 ], queriedInt[1 ], queriedInt[2 ]);
810+ mStencilFuncBackStack .emplace_back (queriedInt[0 ], queriedInt[1 ], queriedInt[2 ]);
811+ }
812+
813+ return std::make_pair (mStencilFuncFrontStack .back (), mStencilFuncBackStack .back ());
814+ }
815+
574816// ////////////////////////////////////////////////////////////////
575817// LogicOp
576818#if ! defined( CINDER_GL_ES )
0 commit comments