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