Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Glew include
Toshihiro Shimizu 890ddd
#include <gl glew.h=""></gl>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzCore includes
Toshihiro Shimizu 890ddd
#include "tgl.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Qt includes
Toshihiro Shimizu 890ddd
#include <qcoreapplication></qcoreapplication>
Toshihiro Shimizu 890ddd
#include <qthread></qthread>
Toshihiro Shimizu 890ddd
#include <qdatetime></qdatetime>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include <qglpixelbuffer></qglpixelbuffer>
Toshihiro Shimizu 890ddd
#include <qglframebufferobject></qglframebufferobject>
Toshihiro Shimizu 890ddd
#include <qglshaderprogram></qglshaderprogram>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// STD includes
Toshihiro Shimizu 890ddd
#include <map></map>
Toshihiro Shimizu 890ddd
#include <memory></memory>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "stdfx/shadingcontext.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//*****************************************************************
Toshihiro Shimizu 890ddd
//    Local Namespace stuff
Toshihiro Shimizu 890ddd
//*****************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
typedef std::auto_ptr<qglpixelbuffer> QGLPixelBufferP;</qglpixelbuffer>
Toshihiro Shimizu 890ddd
typedef std::auto_ptr<qglframebufferobject> QGLFramebufferObjectP;</qglframebufferobject>
Toshihiro Shimizu 890ddd
typedef std::auto_ptr<qglshaderprogram> QGLShaderProgramP;</qglshaderprogram>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct CompiledShader {
Toshihiro Shimizu 890ddd
	QGLShaderProgramP m_program;
Toshihiro Shimizu 890ddd
	QDateTime m_lastModified;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	CompiledShader() {}
Toshihiro Shimizu 890ddd
	CompiledShader(const CompiledShader &)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		assert(!m_program.get());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//*****************************************************************
Toshihiro Shimizu 890ddd
//    ShadingContext::Imp  definition
Toshihiro Shimizu 890ddd
//*****************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct ShadingContext::Imp {
Toshihiro Shimizu 890ddd
	QGLPixelBufferP m_pixelBuffer; //!< OpenGL context.
Toshihiro Shimizu 890ddd
	QGLFramebufferObjectP m_fbo;   //!< Output buffer.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::map
Toshihiro Shimizu 890ddd
			 CompiledShader> m_shaderPrograms; //!< Shader Programs stored in the context.
Toshihiro Shimizu 890ddd
											   //!  \warning   Values have \p auto_ptr members.
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	Imp();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	static QGLFormat format();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void initMatrix(int lx, int ly);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Toshihiro Shimizu 890ddd
	// Not copyable
Toshihiro Shimizu 890ddd
	Imp(const Imp &);
Toshihiro Shimizu 890ddd
	Imp &operator=(const Imp &);
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
ShadingContext::Imp::Imp()
Toshihiro Shimizu 890ddd
	: m_pixelBuffer(new QGLPixelBuffer(1, 1, format()))
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
QGLFormat ShadingContext::Imp::format()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	QGLFormat fmt;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef MACOSX
Toshihiro Shimizu 890ddd
	fmt.setVersion(3, 2);
Toshihiro Shimizu 890ddd
	fmt.setProfile(QGLFormat::CompatibilityProfile);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return fmt;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ShadingContext::Imp::initMatrix(int lx, int ly)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	glViewport(0, 0, lx, ly);
Toshihiro Shimizu 890ddd
	glMatrixMode(GL_PROJECTION);
Toshihiro Shimizu 890ddd
	glLoadIdentity();
Toshihiro Shimizu 890ddd
	gluOrtho2D(0, lx, 0, ly);
Toshihiro Shimizu 890ddd
	glMatrixMode(GL_MODELVIEW);
Toshihiro Shimizu 890ddd
	glLoadIdentity();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//*****************************************************************
Toshihiro Shimizu 890ddd
//    ShadingContext  implementation
Toshihiro Shimizu 890ddd
//*****************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
ShadingContext::ShadingContext()
Toshihiro Shimizu 890ddd
	: m_imp(new Imp)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	makeCurrent();
Toshihiro Shimizu 890ddd
	glewExperimental = GL_TRUE;
Toshihiro Shimizu 890ddd
	glewInit();
Toshihiro Shimizu 890ddd
	doneCurrent();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
ShadingContext::~ShadingContext()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
ShadingContext::Support ShadingContext::support()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return !QGLPixelBuffer::hasOpenGLPbuffers() ? NO_PIXEL_BUFFER : !QGLShaderProgram::hasOpenGLShaderPrograms() ? NO_SHADERS : OK;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool ShadingContext::isValid() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_imp->m_pixelBuffer->isValid();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
QGLFormat ShadingContext::defaultFormat(int channelsSize)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
  QGL::FormatOptions opts =
Toshihiro Shimizu 890ddd
    QGL::SingleBuffer     |
Toshihiro Shimizu 890ddd
    QGL::NoAccumBuffer    |
Toshihiro Shimizu 890ddd
    QGL::NoDepthBuffer    |                           // I guess it could be necessary to let at least
Toshihiro Shimizu 890ddd
    QGL::NoOverlay        |                           // the depth buffer enabled... Fragment shaders could
Toshihiro Shimizu 890ddd
    QGL::NoSampleBuffers  |                           // use it...
Toshihiro Shimizu 890ddd
    QGL::NoStencilBuffer  |
Toshihiro Shimizu 890ddd
    QGL::NoStereoBuffers;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  QGLFormat fmt(opts);
Toshihiro Shimizu 890ddd
  fmt.setDirectRendering(true);                       // Just to be explicit - USE HARDWARE ACCELERATION
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  fmt.setRedBufferSize(channelsSize);
Toshihiro Shimizu 890ddd
  fmt.setGreenBufferSize(channelsSize);
Toshihiro Shimizu 890ddd
  fmt.setBlueBufferSize(channelsSize);
Toshihiro Shimizu 890ddd
  fmt.setAlphaBufferSize(channelsSize);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  // TODO: 64-bit mode should be settable here
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  return fmt;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
//--------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ShadingContext::makeCurrent()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_imp->m_pixelBuffer->makeCurrent();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ShadingContext::doneCurrent()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_imp->m_pixelBuffer->doneCurrent();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ShadingContext::resize(int lx, int ly, const QGLFramebufferObjectFormat &fmt)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_imp->m_fbo.get() &&
Toshihiro Shimizu 890ddd
		m_imp->m_fbo->width() == lx &&
Toshihiro Shimizu 890ddd
		m_imp->m_fbo->height() == ly &&
Toshihiro Shimizu 890ddd
		m_imp->m_fbo->format() == fmt)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (lx == 0 || ly == 0) {
Toshihiro Shimizu 890ddd
		m_imp->m_fbo.reset(0);
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		m_imp->m_fbo.reset(new QGLFramebufferObject(lx, ly, fmt));
Toshihiro Shimizu 890ddd
		assert(m_imp->m_fbo->isValid());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_imp->m_fbo->bind();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
QGLFramebufferObjectFormat ShadingContext::format() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	QGLFramebufferObject *fbo = m_imp->m_fbo.get();
Toshihiro Shimizu 890ddd
	return fbo ? m_imp->m_fbo->format() : QGLFramebufferObjectFormat();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TDimension ShadingContext::size() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	QGLFramebufferObject *fbo = m_imp->m_fbo.get();
Toshihiro Shimizu 890ddd
	return fbo ? TDimension(fbo->width(), fbo->height()) : TDimension();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ShadingContext::addShaderProgram(
Toshihiro Shimizu 890ddd
	const QString &shaderName, QGLShaderProgram *program)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::map<qstring, compiledshader="">::iterator st =</qstring,>
Toshihiro Shimizu 890ddd
		m_imp->m_shaderPrograms.insert(std::make_pair(shaderName, CompiledShader())).first;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	st->second.m_program.reset(program);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ShadingContext::addShaderProgram(
Toshihiro Shimizu 890ddd
	const QString &shaderName, QGLShaderProgram *program, const QDateTime &lastModified)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::map<qstring, compiledshader="">::iterator st =</qstring,>
Toshihiro Shimizu 890ddd
		m_imp->m_shaderPrograms.insert(std::make_pair(shaderName, CompiledShader())).first;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	st->second.m_program.reset(program);
Toshihiro Shimizu 890ddd
	st->second.m_lastModified = lastModified;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool ShadingContext::removeShaderProgram(const QString &shaderName)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return (m_imp->m_shaderPrograms.erase(shaderName) > 0);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
QGLShaderProgram *ShadingContext::shaderProgram(const QString &shaderName) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::map<qstring, compiledshader="">::iterator st =</qstring,>
Toshihiro Shimizu 890ddd
		m_imp->m_shaderPrograms.find(shaderName);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return (st != m_imp->m_shaderPrograms.end()) ? st->second.m_program.get() : 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
QDateTime ShadingContext::lastModified(const QString &shaderName) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::map<qstring, compiledshader="">::iterator st =</qstring,>
Toshihiro Shimizu 890ddd
		m_imp->m_shaderPrograms.find(shaderName);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return (st != m_imp->m_shaderPrograms.end()) ? st->second.m_lastModified : QDateTime();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
std::pair<qglshaderprogram *,="" qdatetime=""> ShadingContext::shaderData(</qglshaderprogram>
Toshihiro Shimizu 890ddd
	const QString &shaderName) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::map<qstring, compiledshader="">::iterator st =</qstring,>
Toshihiro Shimizu 890ddd
		m_imp->m_shaderPrograms.find(shaderName);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return (st != m_imp->m_shaderPrograms.end()) ? std::make_pair(st->second.m_program.get(), st->second.m_lastModified) : std::make_pair((QGLShaderProgram *)0, QDateTime());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
GLuint ShadingContext::loadTexture(const TRasterP &src, GLuint texUnit)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	glActiveTexture(GL_TEXTURE0 + texUnit);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	GLuint texId;
Toshihiro Shimizu 890ddd
	glGenTextures(1, &texId);
Toshihiro Shimizu 890ddd
	glBindTexture(GL_TEXTURE_2D, texId);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);	   // These must be used on a bound texture,
Toshihiro Shimizu 890ddd
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);	   // and are remembered in the OpenGL context.
Toshihiro Shimizu 890ddd
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // They can be set here, no need for
Toshihiro Shimizu 890ddd
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // the user to do it.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	glPixelStorei(GL_UNPACK_ROW_LENGTH, src->getWrap());
Toshihiro Shimizu 890ddd
	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	GLenum chanType = TRaster32P(src) ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	glTexImage2D(GL_TEXTURE_2D,
Toshihiro Shimizu 890ddd
				 0,			   // one level only
Toshihiro Shimizu 890ddd
				 GL_RGBA,	  // pixel channels count
Toshihiro Shimizu 890ddd
				 src->getLx(), // width
Toshihiro Shimizu 890ddd
				 src->getLy(), // height
Toshihiro Shimizu 890ddd
				 0,			   // border size
Toshihiro Shimizu 890ddd
				 TGL_FMT,	  // pixel format
Toshihiro Shimizu 890ddd
				 chanType,	 // channel data type
Toshihiro Shimizu 890ddd
				 (GLvoid *)src->getRawData());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(glGetError() == GL_NO_ERROR);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return texId;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ShadingContext::unloadTexture(GLuint texId)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	glDeleteTextures(1, &texId);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ShadingContext::draw(const TRasterP &dst)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert("ShadingContext::resize() must be invoked at least once before this" && m_imp->m_fbo.get());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int lx = dst->getLx(), ly = dst->getLy(); // NOTE: We're not using m_imp->m_fbo's size, since
Toshihiro Shimizu 890ddd
											  // it could be possibly greater than the required
Toshihiro Shimizu 890ddd
											  // destination surface.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_imp->initMatrix(lx, ly); // This call sets the OpenGL viewport to this
Toshihiro Shimizu 890ddd
							   // size - and matches (1, 1) to dst's (lx, ly)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		glBegin(GL_QUADS);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		glVertex2f(0.0, 0.0);
Toshihiro Shimizu 890ddd
		glVertex2f(lx, 0.0);
Toshihiro Shimizu 890ddd
		glVertex2f(lx, ly);
Toshihiro Shimizu 890ddd
		glVertex2f(0.0, ly);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		glEnd();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	glPixelStorei(GL_PACK_ROW_LENGTH, dst->getWrap());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Read the fbo to dst
Toshihiro Shimizu 890ddd
	if (TRaster32P ras32 = dst)
Toshihiro Shimizu 890ddd
		glReadPixels(0, 0, lx, ly, GL_BGRA_EXT, GL_UNSIGNED_BYTE, dst->getRawData());
Toshihiro Shimizu 890ddd
	else {
Toshihiro Shimizu 890ddd
		assert(TRaster64P(dst));
Toshihiro Shimizu 890ddd
		glReadPixels(0, 0, lx, ly, GL_BGRA_EXT, GL_UNSIGNED_SHORT, dst->getRawData());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(glGetError() == GL_NO_ERROR);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ShadingContext::transformFeedback(
Toshihiro Shimizu 890ddd
	int varyingsCount, const GLsizeiptr *varyingSizes, GLvoid **bufs)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// Generate buffer objects
Toshihiro Shimizu 890ddd
	std::vector<gluint> bufferObjectNames(varyingsCount, 0);</gluint>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	glGenBuffers(varyingsCount, &bufferObjectNames[0]);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (int v = 0; v != varyingsCount; ++v) {
Toshihiro Shimizu 890ddd
		glBindBuffer(GL_ARRAY_BUFFER, bufferObjectNames[v]);
Toshihiro Shimizu 890ddd
		glBufferData(GL_ARRAY_BUFFER, varyingSizes[v], bufs[v], GL_STATIC_READ);
Toshihiro Shimizu 890ddd
		glBindBuffer(GL_ARRAY_BUFFER, 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, v, bufferObjectNames[v]);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Draw
Toshihiro Shimizu 890ddd
	GLuint Query = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	glGenQueries(1, &Query);
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		// Disable rasterization, vertices processing only!
Toshihiro Shimizu 890ddd
		glEnable(GL_RASTERIZER_DISCARD);
Toshihiro Shimizu 890ddd
		glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, Query);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		glBeginTransformFeedback(GL_POINTS);
Toshihiro Shimizu 890ddd
		glBegin(GL_POINTS);
Toshihiro Shimizu 890ddd
		glVertex2f(0.0f, 0.0f);
Toshihiro Shimizu 890ddd
		glEnd();
Toshihiro Shimizu 890ddd
		glEndTransformFeedback();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
Toshihiro Shimizu 890ddd
		glDisable(GL_RASTERIZER_DISCARD);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	GLint count = 0;
Toshihiro Shimizu 890ddd
	glGetQueryObjectiv(Query, GL_QUERY_RESULT, &count);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	glDeleteQueries(1, &Query);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Retrieve transformed data
Toshihiro Shimizu 890ddd
	for (int v = 0; v != varyingsCount; ++v) {
Toshihiro Shimizu 890ddd
		glBindBuffer(GL_ARRAY_BUFFER, bufferObjectNames[v]);
Toshihiro Shimizu 890ddd
		glGetBufferSubData(GL_ARRAY_BUFFER, 0, varyingSizes[v], bufs[v]);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	glBindBuffer(GL_ARRAY_BUFFER, 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Delete buffer objects
Toshihiro Shimizu 890ddd
	glDeleteBuffers(varyingsCount, &bufferObjectNames[0]);
Toshihiro Shimizu 890ddd
}