Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tstencilcontrol.h"
Toshihiro Shimizu 890ddd
#include "tgl.h"
Toshihiro Shimizu 890ddd
#include "tthreadmessage.h"
Toshihiro Shimizu 890ddd
#include <stack></stack>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include <qthreadstorage></qthreadstorage>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// singleton
Shinya Kitaoka 120a6e
class StencilControlManager {
Shinya Kitaoka 120a6e
  QThreadStorage<tstencilcontrol *=""> m_storage;</tstencilcontrol>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  StencilControlManager() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  static StencilControlManager *instance() {
Shinya Kitaoka 120a6e
    static StencilControlManager theInstance;
Shinya Kitaoka 120a6e
    return &theInstance;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TStencilControl *getCurrentStencilControl() {
Shinya Kitaoka 120a6e
    if (!m_storage.hasLocalData()) {
Shinya Kitaoka 120a6e
      m_storage.setLocalData(new TStencilControl);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    return m_storage.localData();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ~StencilControlManager() {}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // Local namepace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class TStencilControl::Imp {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  int m_stencilBitCount;
Shinya Kitaoka 120a6e
  int m_pushCount;
Shinya Kitaoka 120a6e
  int m_currentWriting;  // current stencil bit plane.
Shinya Kitaoka 120a6e
  // 0 is the first bit plane ; -1 menas no stencil mask is writing
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int m_virtualState;
Shinya Kitaoka 120a6e
// the state of the (eventually virtual) top mask.
Shinya Kitaoka 120a6e
// A mask is virtual if overflows stencil buffer
Shinya Kitaoka 120a6e
// 0 is closed and disabled, 1 closed and enabled and 2 is opened
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef _DEBUG
Shinya Kitaoka 120a6e
  std::stack<bool> fullState;</bool>
Toshihiro Shimizu 890ddd
// state of each mask in the stack (except top mask).
Toshihiro Shimizu 890ddd
// 'true' means opend; 'false' means close and enabled
Toshihiro Shimizu 890ddd
// Used only for assert
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  unsigned char m_writingMask;  // bit mask. The i-th bit=1 iff the i-th mask is
Shinya Kitaoka 120a6e
                                // opened to write
Shinya Kitaoka 120a6e
  unsigned char m_drawOnScreenMask;  // bitmsk.The ith bit=1 iff the ith mask
Shinya Kitaoka 120a6e
                                     // WRITE also ON SCREEN WHEN WRITE ON
Shinya Kitaoka 120a6e
                                     // STENCIL BIT PLANE
Shinya Kitaoka 120a6e
  unsigned char
Shinya Kitaoka 120a6e
      m_enabledMask;  // bit mask. The i-th bit=1 iff the i-th mask is enabled
Shinya Kitaoka 120a6e
  unsigned char
Shinya Kitaoka 120a6e
      m_inOrOutMask;  // bit mask. The i-th bit=1 iff the i-th mask is inside
Shinya Kitaoka 120a6e
  unsigned char m_drawOnlyOnceMask;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  Imp();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void updateOpenGlState();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void pushMask();
Shinya Kitaoka 120a6e
  // make a new stencil plane the current one.
Shinya Kitaoka 120a6e
  // if there is no plane available, increase a counter and does not push
Shinya Kitaoka 120a6e
  // (virtual masks)
Shinya Kitaoka 120a6e
  // So the same number of pop has no effect
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void popMask();
Shinya Kitaoka 120a6e
  // assert if the stencil stack contains only 0
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void beginMask(DrawMode drawMode);
Shinya Kitaoka 120a6e
  // clear the current stencil plane; start writing to it
Shinya Kitaoka 120a6e
  // if drawOnScreen is not 0, it writes also to the color buffer (or stencil
Shinya Kitaoka 120a6e
  // plane if another
Shinya Kitaoka 120a6e
  // mask is open). If drawOnScreen is 2, it drows only once (by stencil buffer)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void endMask();
Shinya Kitaoka 120a6e
  // end writing to the stencil plane.
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void enableMask(MaskType maskType);
Shinya Kitaoka 120a6e
  void disableMask();
Shinya Kitaoka 120a6e
  // between enableMask()/disableMask() drawing is filtered by the values of the
Shinya Kitaoka 120a6e
  // current
Shinya Kitaoka 120a6e
  // stencil plane
Shinya Kitaoka 120a6e
  // n.b. enableMask()/disableMask() can be nidified. Between the inner pair
Shinya Kitaoka 120a6e
  // writing is enabled
Shinya Kitaoka 120a6e
  // according to the AND of all of them
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TStencilControl::Imp::Imp()
Shinya Kitaoka 120a6e
    : m_stencilBitCount(0)
Shinya Kitaoka 120a6e
    , m_pushCount(1)
Shinya Kitaoka 120a6e
    , m_currentWriting(-1)
Shinya Kitaoka 120a6e
    , m_enabledMask(0)
Shinya Kitaoka 120a6e
    , m_writingMask(0)
Shinya Kitaoka 120a6e
    , m_inOrOutMask(0)
Shinya Kitaoka 120a6e
    , m_drawOnScreenMask(0)
Shinya Kitaoka 120a6e
    , m_drawOnlyOnceMask(0)
Shinya Kitaoka 120a6e
    , m_virtualState(0) {
Shinya Kitaoka 120a6e
  glGetIntegerv(GL_STENCIL_BITS, (GLint *)&m_stencilBitCount);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  glStencilMask(0xFFFFFFFF);
Shinya Kitaoka 120a6e
  // glClearStencil(0);
Shinya Kitaoka 120a6e
  glClear(GL_STENCIL_BUFFER_BIT);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TStencilControl *TStencilControl::instance() {
Shinya Kitaoka 120a6e
  StencilControlManager *instance = StencilControlManager::instance();
Shinya Kitaoka 120a6e
  return instance->getCurrentStencilControl();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TStencilControl::TStencilControl() : m_imp(new Imp) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TStencilControl::~TStencilControl() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TStencilControl::Imp::updateOpenGlState() {
Shinya Kitaoka 120a6e
  if (m_currentWriting >= 0) {  // writing on stencil buffer
Shinya Kitaoka 120a6e
    unsigned char currentWritingMask = 1 << m_currentWriting;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    bool drawOnlyOnce = (currentWritingMask & m_drawOnlyOnceMask) != 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (currentWritingMask & m_drawOnScreenMask) {
Shinya Kitaoka 120a6e
      unsigned char lastWritingMask;
Shinya Kitaoka 120a6e
      int lastWriting = m_currentWriting - 1;
Shinya Kitaoka 120a6e
      for (; lastWriting >= 0; lastWriting--) {
Shinya Kitaoka 120a6e
        lastWritingMask = 1 << lastWriting;
Shinya Kitaoka 120a6e
        if ((lastWritingMask & m_writingMask) == lastWritingMask) break;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      if (lastWriting < 0) {
Shinya Kitaoka 120a6e
        // glColorMask(1,1,1,1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        if (drawOnlyOnce)
Shinya Kitaoka 120a6e
          m_enabledMask |= currentWritingMask;
Shinya Kitaoka 120a6e
        else
Shinya Kitaoka 120a6e
          m_enabledMask &= ~currentWritingMask;
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        tglMultColorMask(0, 0, 0, 0);
Shinya Kitaoka 120a6e
        // glDrawBuffer(GL_NONE);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        drawOnlyOnce = false;  // essendo solo un'effetto visivo, se sto
Shinya Kitaoka 120a6e
                               // scrivendo su una maschera e non a schermo, e'
Shinya Kitaoka 120a6e
                               // inutile
Shinya Kitaoka 120a6e
        currentWritingMask |= lastWritingMask;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else
Shinya Kitaoka 120a6e
      tglMultColorMask(0, 0, 0, 0);
Shinya Kitaoka 120a6e
    // glDrawBuffer(GL_NONE);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    glStencilMask(currentWritingMask);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (drawOnlyOnce) {
Shinya Kitaoka 120a6e
      glStencilFunc(GL_EQUAL, m_inOrOutMask, m_enabledMask);
Shinya Kitaoka 120a6e
      glStencilOp(GL_KEEP, GL_INVERT, GL_INVERT);
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      glStencilFunc(GL_EQUAL, currentWritingMask | m_inOrOutMask,
Shinya Kitaoka 120a6e
                    m_enabledMask);
Shinya Kitaoka 120a6e
      glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  } else {  // writing on screen buffer
Shinya Kitaoka 120a6e
    glStencilMask(0xFFFFFFFF);
Shinya Kitaoka 120a6e
    glStencilFunc(GL_EQUAL, m_inOrOutMask, m_enabledMask);
Shinya Kitaoka 120a6e
    glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
Shinya Kitaoka 120a6e
    // glColorMask(1,1,1,1);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!m_enabledMask && m_currentWriting < 0)
Shinya Kitaoka 120a6e
    glDisable(GL_STENCIL_TEST);
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    glEnable(GL_STENCIL_TEST);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TStencilControl::Imp::pushMask() { m_pushCount++; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TStencilControl::Imp::beginMask(DrawMode drawMode) {
Shinya Kitaoka 120a6e
  m_currentWriting          = m_pushCount - 1;
Shinya Kitaoka 120a6e
  unsigned char currentMask = 1 << m_currentWriting;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_writingMask |= currentMask;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (drawMode == DRAW_ALSO_ON_SCREEN) {
Shinya Kitaoka 120a6e
    m_drawOnScreenMask |= currentMask;
Shinya Kitaoka 120a6e
  } else if (drawMode == DRAW_ON_SCREEN_ONLY_ONCE) {
Shinya Kitaoka 120a6e
    m_drawOnScreenMask |= currentMask;
Shinya Kitaoka 120a6e
    m_drawOnlyOnceMask |= currentMask;
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    m_drawOnScreenMask &= ~currentMask;
Shinya Kitaoka 120a6e
    m_drawOnlyOnceMask &= ~currentMask;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  glEnable(GL_STENCIL_TEST);
Shinya Kitaoka 120a6e
  glStencilMask(currentMask);      // enabled to modify only current bitPlane
Shinya Kitaoka 120a6e
  glClear(GL_STENCIL_BUFFER_BIT);  // and clear it
Shinya Kitaoka 120a6e
  updateOpenGlState();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TStencilControl::Imp::endMask() {
Shinya Kitaoka 120a6e
  assert(m_pushCount - 1 == m_currentWriting);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  unsigned char currentMask = 1 << (m_pushCount - 1);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_writingMask &= ~currentMask;  // stop writing
Shinya Kitaoka 120a6e
  m_enabledMask &= ~currentMask;
Shinya Kitaoka 120a6e
  m_drawOnScreenMask &= ~currentMask;
Shinya Kitaoka 120a6e
  m_drawOnlyOnceMask &= ~currentMask;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //----------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_currentWriting--;
Shinya Kitaoka 120a6e
  for (; m_currentWriting >= 0; m_currentWriting--) {
Shinya Kitaoka 120a6e
    unsigned char currentWritingMask = 1 << m_currentWriting;
Shinya Kitaoka 120a6e
    if ((currentWritingMask & m_writingMask) == currentWritingMask) break;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  updateOpenGlState();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TStencilControl::Imp::enableMask(MaskType maskType) {
Shinya Kitaoka 120a6e
  unsigned char currentMask = 1 << (m_pushCount - 1);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if ((m_enabledMask & currentMask) == 0) glPushAttrib(GL_ALL_ATTRIB_BITS);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_enabledMask |= currentMask;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  assert(maskType == SHOW_INSIDE || maskType == SHOW_OUTSIDE);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (maskType == SHOW_INSIDE)
Shinya Kitaoka 120a6e
    m_inOrOutMask |= currentMask;
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    m_inOrOutMask &= ~currentMask;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  updateOpenGlState();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TStencilControl::Imp::disableMask() {
Shinya Kitaoka 120a6e
  unsigned char currentMask = 1 << (m_pushCount - 1);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_enabledMask &= ~currentMask;
Shinya Kitaoka 120a6e
  m_inOrOutMask &= ~currentMask;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  updateOpenGlState();
Shinya Kitaoka 120a6e
  glPopAttrib();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TStencilControl::Imp::popMask() {
Shinya Kitaoka 120a6e
  --m_pushCount;
Shinya Kitaoka 120a6e
  assert(m_pushCount > 0);  // there is at least one mask in the stack
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// questo forse e' un po' brutto:
Shinya Kitaoka 120a6e
// La maschera e' chiusa.
Shinya Kitaoka 120a6e
// Se e' abilitata,    open = push+open
Shinya Kitaoka 120a6e
// Se e' disabilitata, open =      open
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TStencilControl::beginMask(DrawMode drawMode) {
Shinya Kitaoka 120a6e
  glPushAttrib(GL_ALL_ATTRIB_BITS);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (m_imp->m_virtualState)  // opened or enabled
Shinya Kitaoka 120a6e
  {
Toshihiro Shimizu 890ddd
#ifdef _DEBUG
Shinya Kitaoka 120a6e
    m_imp->fullState.push(m_imp->m_virtualState == 2);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    m_imp->pushMask();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_imp->m_virtualState = 2;  // opened
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (m_imp->m_pushCount <= m_imp->m_stencilBitCount)
Shinya Kitaoka 120a6e
    m_imp->beginMask(drawMode);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TStencilControl::endMask() {
Shinya Kitaoka 120a6e
  if (!m_imp->m_virtualState)  // closed and disabled
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    m_imp->popMask();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef _DEBUG
Shinya Kitaoka 120a6e
    assert(m_imp->fullState.top());  // the state before last push must be
Shinya Kitaoka 120a6e
                                     // opened
Shinya Kitaoka 120a6e
    m_imp->fullState.pop();
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  assert(m_imp->m_virtualState != 1);  // yet closed
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_imp->m_virtualState = 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (m_imp->m_pushCount <= m_imp->m_stencilBitCount) m_imp->endMask();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  glPopAttrib();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TStencilControl::enableMask(MaskType maskType) {
Shinya Kitaoka 120a6e
  assert(m_imp->m_virtualState != 2);  // cannot enable an opened mask
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_imp->m_virtualState = 1;  // enabled
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (m_imp->m_pushCount <= m_imp->m_stencilBitCount)
Shinya Kitaoka 120a6e
    m_imp->enableMask(maskType);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TStencilControl::disableMask() {
Shinya Kitaoka 120a6e
  assert(m_imp->m_virtualState != 2);  // cannot disable an opened mask
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!m_imp->m_virtualState)  // closed and disabled
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    m_imp->popMask();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef _DEBUG
Shinya Kitaoka 120a6e
    assert(
Shinya Kitaoka 120a6e
        !m_imp->fullState.top());  // the state before last push must be enabled
Shinya Kitaoka 120a6e
    m_imp->fullState.pop();
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_imp->m_virtualState = 0;  // close and disabled
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (m_imp->m_pushCount <= m_imp->m_stencilBitCount) m_imp->disableMask();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------