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
Jeremy Bullock d165bb
#include <qopenglframebufferobject></qopenglframebufferobject>
Jeremy Bullock d165bb
#include <qopenglshaderprogram></qopenglshaderprogram>
tomosu ac0809
#include <qopenglcontext></qopenglcontext>
Jeremy Bullock d165bb
#include <qoffscreensurface></qoffscreensurface>
Jeremy Bullock d165bb
#include <qopenglwidget></qopenglwidget>
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
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Jeremy Bullock d165bb
typedef std::unique_ptr<qopenglcontext> QOpenGLContextP;</qopenglcontext>
Jeremy Bullock d165bb
typedef std::unique_ptr<qopenglframebufferobject> QOpenGLFramebufferObjectP;</qopenglframebufferobject>
Jeremy Bullock d165bb
typedef std::unique_ptr<qopenglshaderprogram> QOpenGLShaderProgramP;</qopenglshaderprogram>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct CompiledShader {
Jeremy Bullock d165bb
  QOpenGLShaderProgramP m_program;
Shinya Kitaoka 120a6e
  QDateTime m_lastModified;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  CompiledShader() {}
Shinya Kitaoka 120a6e
  CompiledShader(const CompiledShader &) { assert(!m_program.get()); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Jeremy Bullock d165bb
TQOpenGLWidget::TQOpenGLWidget() {}
Jeremy Bullock d165bb
Jeremy Bullock d165bb
void TQOpenGLWidget::initializeGL() {
shun_iwasawa 339330
  QOffscreenSurface *surface = new QOffscreenSurface();
shun_iwasawa 339330
  // context()->create();
shun_iwasawa 339330
  // context()->makeCurrent(surface);
Jeremy Bullock d165bb
}
Jeremy Bullock d165bb
Toshihiro Shimizu 890ddd
//*****************************************************************
Toshihiro Shimizu 890ddd
//    ShadingContext::Imp  definition
Toshihiro Shimizu 890ddd
//*****************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct ShadingContext::Imp {
shun_iwasawa 339330
  QOpenGLContextP m_context;        //!< OpenGL context.
shun_iwasawa 339330
  QOpenGLFramebufferObjectP m_fbo;  //!< Output buffer.
Jeremy Bullock d165bb
  QOffscreenSurface *m_surface;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::map
Shinya Kitaoka 120a6e
           CompiledShader>
Shinya Kitaoka 120a6e
      m_shaderPrograms;  //!< Shader Programs stored in the context.
Shinya Kitaoka 2a7129
                         //!  \warning   Values have \p unique_ptr members.
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  Imp();
Toshihiro Shimizu 890ddd
Jeremy Bullock d165bb
  static QSurfaceFormat format();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void initMatrix(int lx, int ly);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Shinya Kitaoka 120a6e
  // Not copyable
Shinya Kitaoka 120a6e
  Imp(const Imp &);
Shinya Kitaoka 120a6e
  Imp &operator=(const Imp &);
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------
Toshihiro Shimizu 890ddd
shun_iwasawa 339330
ShadingContext::Imp::Imp() : m_context(new QOpenGLContext()), m_surface() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------
Toshihiro Shimizu 890ddd
Jeremy Bullock d165bb
QSurfaceFormat ShadingContext::Imp::format() {
Jeremy Bullock d165bb
  QSurfaceFormat fmt;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef MACOSX
Shinya Kitaoka 120a6e
  fmt.setVersion(3, 2);
Jeremy Bullock 5b52af
  fmt.setProfile(QSurfaceFormat::CompatibilityProfile);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return fmt;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ShadingContext::Imp::initMatrix(int lx, int ly) {
Shinya Kitaoka 120a6e
  glViewport(0, 0, lx, ly);
Shinya Kitaoka 120a6e
  glMatrixMode(GL_PROJECTION);
Shinya Kitaoka 120a6e
  glLoadIdentity();
Shinya Kitaoka 120a6e
  gluOrtho2D(0, lx, 0, ly);
Shinya Kitaoka 120a6e
  glMatrixMode(GL_MODELVIEW);
Shinya Kitaoka 120a6e
  glLoadIdentity();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//*****************************************************************
Toshihiro Shimizu 890ddd
//    ShadingContext  implementation
Toshihiro Shimizu 890ddd
//*****************************************************************
Toshihiro Shimizu 890ddd
shun_iwasawa 339330
ShadingContext::ShadingContext(QOffscreenSurface *surface) : m_imp(new Imp) {
shun_iwasawa 339330
  m_imp->m_surface = surface;
shun_iwasawa 339330
  m_imp->m_surface->create();
shun_iwasawa 339330
  QSurfaceFormat format;
shun_iwasawa 339330
  m_imp->m_context->setFormat(format);
shun_iwasawa 339330
  m_imp->m_context->create();
shun_iwasawa 339330
  m_imp->m_context->makeCurrent(m_imp->m_surface);
shun_iwasawa 339330
shun_iwasawa 339330
  // m_imp->m_pixelBuffer->context()->create();
shun_iwasawa 339330
  // m_imp->m_fbo(new QOpenGLFramebufferObject(1, 1));
Shinya Kitaoka 120a6e
  makeCurrent();
Martin van Zijl 708c58
   if( GLEW_VERSION_3_2 ) {
Martin van Zijl 708c58
       glewExperimental = GL_TRUE;
Martin van Zijl 708c58
   }
Shinya Kitaoka 120a6e
  glewInit();
Shinya Kitaoka 120a6e
  doneCurrent();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------
Toshihiro Shimizu 890ddd
tomosu ac0809
ShadingContext::~ShadingContext() {
shun-iwasawa 27b0cf
  // Destructor of QGLPixelBuffer calls QOpenGLContext::makeCurrent()
shun-iwasawa 27b0cf
  // internally,
tomosu ac0809
  // so the current thread must be the owner of QGLPixelBuffer context,
tomosu ac0809
  // when the destructor of m_imp->m_context is called.
1213cf
  m_imp->m_context->moveToThread(QThread::currentThread());
tomosu ac0809
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
ShadingContext::Support ShadingContext::support() {
shun_iwasawa 339330
  // return !QGLPixelBuffer::hasOpenGLPbuffers()
Jeremy Bullock d165bb
  //           ? NO_PIXEL_BUFFER
shun_iwasawa 339330
  //           : !QOpenGLShaderProgram::hasOpenGLShaderPrograms() ? NO_SHADERS :
shun_iwasawa 339330
  //           OK;
shun_iwasawa 339330
  return !QOpenGLShaderProgram::hasOpenGLShaderPrograms() ? NO_SHADERS : OK;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------
Toshihiro Shimizu 890ddd
Jeremy Bullock d165bb
bool ShadingContext::isValid() const { return m_imp->m_context->isValid(); }
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    |
Shinya Kitaoka 120a6e
    QGL::NoDepthBuffer    |                           // I guess it could be
Shinya Kitaoka 120a6e
necessary to let at least
Shinya Kitaoka 120a6e
    QGL::NoOverlay        |                           // the depth buffer
Shinya Kitaoka 120a6e
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);
Shinya Kitaoka 120a6e
  fmt.setDirectRendering(true);                       // Just to be explicit -
Shinya Kitaoka 120a6e
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
tomosu ac0809
void ShadingContext::makeCurrent() {
shun_iwasawa 339330
  m_imp->m_context->moveToThread(QThread::currentThread());
1213cf
  m_imp->m_context.reset(new QOpenGLContext());
shun_iwasawa 339330
  QSurfaceFormat format;
shun_iwasawa 339330
  m_imp->m_context->setFormat(format);
shun_iwasawa 339330
  m_imp->m_context->create();
shun_iwasawa 339330
  m_imp->m_context->makeCurrent(m_imp->m_surface);
tomosu ac0809
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------
Toshihiro Shimizu 890ddd
tomosu ac0809
void ShadingContext::doneCurrent() {
1213cf
  m_imp->m_context->moveToThread(0);
Jeremy Bullock d165bb
  m_imp->m_context->doneCurrent();
tomosu ac0809
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ShadingContext::resize(int lx, int ly,
Jeremy Bullock d165bb
                            const QOpenGLFramebufferObjectFormat &fmt) {
Shinya Kitaoka 120a6e
  if (m_imp->m_fbo.get() && m_imp->m_fbo->width() == lx &&
Shinya Kitaoka 120a6e
      m_imp->m_fbo->height() == ly && m_imp->m_fbo->format() == fmt)
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (lx == 0 || ly == 0) {
Shinya Kitaoka 120a6e
    m_imp->m_fbo.reset(0);
Shinya Kitaoka 120a6e
  } else {
shun_iwasawa 339330
    bool get                         = m_imp->m_fbo.get();
shun_iwasawa 339330
    QOpenGLContext *currContext      = m_imp->m_context->currentContext();
shun_iwasawa 339330
    bool yes                         = false;
shun_iwasawa 339330
    if (currContext) bool yes        = true;
shun_iwasawa 339330
    while (!currContext) currContext = m_imp->m_context->currentContext();
shun_iwasawa 339330
    m_imp->m_fbo.reset(new QOpenGLFramebufferObject(lx, ly, fmt));
Shinya Kitaoka 120a6e
    assert(m_imp->m_fbo->isValid());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_imp->m_fbo->bind();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------
Toshihiro Shimizu 890ddd
Jeremy Bullock d165bb
QOpenGLFramebufferObjectFormat ShadingContext::format() const {
Jeremy Bullock d165bb
  QOpenGLFramebufferObject *fbo = m_imp->m_fbo.get();
Jeremy Bullock d165bb
  return fbo ? m_imp->m_fbo->format() : QOpenGLFramebufferObjectFormat();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TDimension ShadingContext::size() const {
Jeremy Bullock d165bb
  QOpenGLFramebufferObject *fbo = m_imp->m_fbo.get();
Shinya Kitaoka 120a6e
  return fbo ? TDimension(fbo->width(), fbo->height()) : TDimension();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ShadingContext::addShaderProgram(const QString &shaderName,
Jeremy Bullock d165bb
                                      QOpenGLShaderProgram *program) {
Shinya Kitaoka 120a6e
  std::map<qstring, compiledshader="">::iterator st =</qstring,>
Shinya Kitaoka 120a6e
      m_imp->m_shaderPrograms
Shinya Kitaoka 120a6e
          .insert(std::make_pair(shaderName, CompiledShader()))
Shinya Kitaoka 120a6e
          .first;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  st->second.m_program.reset(program);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ShadingContext::addShaderProgram(const QString &shaderName,
Jeremy Bullock d165bb
                                      QOpenGLShaderProgram *program,
Shinya Kitaoka 120a6e
                                      const QDateTime &lastModified) {
Shinya Kitaoka 120a6e
  std::map<qstring, compiledshader="">::iterator st =</qstring,>
Shinya Kitaoka 120a6e
      m_imp->m_shaderPrograms
Shinya Kitaoka 120a6e
          .insert(std::make_pair(shaderName, CompiledShader()))
Shinya Kitaoka 120a6e
          .first;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  st->second.m_program.reset(program);
Shinya Kitaoka 120a6e
  st->second.m_lastModified = lastModified;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool ShadingContext::removeShaderProgram(const QString &shaderName) {
Shinya Kitaoka 120a6e
  return (m_imp->m_shaderPrograms.erase(shaderName) > 0);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------
Toshihiro Shimizu 890ddd
Jeremy Bullock d165bb
QOpenGLShaderProgram *ShadingContext::shaderProgram(
Shinya Kitaoka 120a6e
    const QString &shaderName) const {
Shinya Kitaoka 120a6e
  std::map<qstring, compiledshader="">::iterator st =</qstring,>
Shinya Kitaoka 120a6e
      m_imp->m_shaderPrograms.find(shaderName);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  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
Shinya Kitaoka 120a6e
QDateTime ShadingContext::lastModified(const QString &shaderName) const {
Shinya Kitaoka 120a6e
  std::map<qstring, compiledshader="">::iterator st =</qstring,>
Shinya Kitaoka 120a6e
      m_imp->m_shaderPrograms.find(shaderName);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return (st != m_imp->m_shaderPrograms.end()) ? st->second.m_lastModified
Shinya Kitaoka 120a6e
                                               : QDateTime();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------
Toshihiro Shimizu 890ddd
Jeremy Bullock d165bb
std::pair<qopenglshaderprogram *,="" qdatetime=""> ShadingContext::shaderData(</qopenglshaderprogram>
Shinya Kitaoka 120a6e
    const QString &shaderName) const {
Shinya Kitaoka 120a6e
  std::map<qstring, compiledshader="">::iterator st =</qstring,>
Shinya Kitaoka 120a6e
      m_imp->m_shaderPrograms.find(shaderName);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return (st != m_imp->m_shaderPrograms.end())
Shinya Kitaoka 120a6e
             ? std::make_pair(st->second.m_program.get(),
Shinya Kitaoka 120a6e
                              st->second.m_lastModified)
Jeremy Bullock d165bb
             : std::make_pair((QOpenGLShaderProgram *)0, QDateTime());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
GLuint ShadingContext::loadTexture(const TRasterP &src, GLuint texUnit) {
Shinya Kitaoka 120a6e
  glActiveTexture(GL_TEXTURE0 + texUnit);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  GLuint texId;
Shinya Kitaoka 120a6e
  glGenTextures(1, &texId);
Shinya Kitaoka 120a6e
  glBindTexture(GL_TEXTURE_2D, texId);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
Shinya Kitaoka 120a6e
                  GL_CLAMP);  // These must be used on a bound texture,
Shinya Kitaoka 120a6e
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
Shinya Kitaoka 120a6e
                  GL_CLAMP);  // and are remembered in the OpenGL context.
Shinya Kitaoka 120a6e
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
Shinya Kitaoka 120a6e
                  GL_NEAREST);  // They can be set here, no need for
Shinya Kitaoka 120a6e
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
Shinya Kitaoka 120a6e
                  GL_NEAREST);  // the user to do it.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  glPixelStorei(GL_UNPACK_ROW_LENGTH, src->getWrap());
Shinya Kitaoka 120a6e
  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  GLenum chanType = TRaster32P(src) ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  glTexImage2D(GL_TEXTURE_2D,
Shinya Kitaoka 120a6e
               0,             // one level only
Shinya Kitaoka 120a6e
               GL_RGBA,       // pixel channels count
Shinya Kitaoka 120a6e
               src->getLx(),  // width
Shinya Kitaoka 120a6e
               src->getLy(),  // height
Shinya Kitaoka 120a6e
               0,             // border size
Shinya Kitaoka 120a6e
               TGL_FMT,       // pixel format
Shinya Kitaoka 120a6e
               chanType,      // channel data type
Shinya Kitaoka 120a6e
               (GLvoid *)src->getRawData());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  assert(glGetError() == GL_NO_ERROR);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return texId;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ShadingContext::unloadTexture(GLuint texId) {
Shinya Kitaoka 120a6e
  glDeleteTextures(1, &texId);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ShadingContext::draw(const TRasterP &dst) {
Shinya Kitaoka 120a6e
  assert("ShadingContext::resize() must be invoked at least once before this" &&
Shinya Kitaoka 120a6e
         m_imp->m_fbo.get());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int lx = dst->getLx(),
Shinya Kitaoka 120a6e
      ly = dst->getLy();  // NOTE: We're not using m_imp->m_fbo's size, since
Shinya Kitaoka 120a6e
                          // it could be possibly greater than the required
Shinya Kitaoka 120a6e
                          // destination surface.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_imp->initMatrix(lx, ly);  // This call sets the OpenGL viewport to this
Shinya Kitaoka 120a6e
                              // size - and matches (1, 1) to dst's (lx, ly)
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    glBegin(GL_QUADS);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    glVertex2f(0.0, 0.0);
Shinya Kitaoka 120a6e
    glVertex2f(lx, 0.0);
Shinya Kitaoka 120a6e
    glVertex2f(lx, ly);
Shinya Kitaoka 120a6e
    glVertex2f(0.0, ly);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    glEnd();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  glPixelStorei(GL_PACK_ROW_LENGTH, dst->getWrap());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Read the fbo to dst
Shinya Kitaoka 120a6e
  if (TRaster32P ras32 = dst)
Shinya Kitaoka 120a6e
    glReadPixels(0, 0, lx, ly, GL_BGRA_EXT, GL_UNSIGNED_BYTE,
Shinya Kitaoka 120a6e
                 dst->getRawData());
Shinya Kitaoka 120a6e
  else {
Shinya Kitaoka 120a6e
    assert(TRaster64P(dst));
Shinya Kitaoka 120a6e
    glReadPixels(0, 0, lx, ly, GL_BGRA_EXT, GL_UNSIGNED_SHORT,
Shinya Kitaoka 120a6e
                 dst->getRawData());
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  assert(glGetError() == GL_NO_ERROR);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ShadingContext::transformFeedback(int varyingsCount,
Shinya Kitaoka 120a6e
                                       const GLsizeiptr *varyingSizes,
Shinya Kitaoka 120a6e
                                       GLvoid **bufs) {
Shinya Kitaoka 120a6e
  // Generate buffer objects
Shinya Kitaoka 120a6e
  std::vector<gluint> bufferObjectNames(varyingsCount, 0);</gluint>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  glGenBuffers(varyingsCount, &bufferObjectNames[0]);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  for (int v = 0; v != varyingsCount; ++v) {
Shinya Kitaoka 120a6e
    glBindBuffer(GL_ARRAY_BUFFER, bufferObjectNames[v]);
Shinya Kitaoka 120a6e
    glBufferData(GL_ARRAY_BUFFER, varyingSizes[v], bufs[v], GL_STATIC_READ);
Shinya Kitaoka 120a6e
    glBindBuffer(GL_ARRAY_BUFFER, 0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, v, bufferObjectNames[v]);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Draw
Shinya Kitaoka 120a6e
  GLuint Query = 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  glGenQueries(1, &Query);
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    // Disable rasterization, vertices processing only!
Shinya Kitaoka 120a6e
    glEnable(GL_RASTERIZER_DISCARD);
Shinya Kitaoka 120a6e
    glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, Query);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    glBeginTransformFeedback(GL_POINTS);
Shinya Kitaoka 120a6e
    glBegin(GL_POINTS);
Shinya Kitaoka 120a6e
    glVertex2f(0.0f, 0.0f);
Shinya Kitaoka 120a6e
    glEnd();
Shinya Kitaoka 120a6e
    glEndTransformFeedback();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
Shinya Kitaoka 120a6e
    glDisable(GL_RASTERIZER_DISCARD);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  GLint count = 0;
Shinya Kitaoka 120a6e
  glGetQueryObjectiv(Query, GL_QUERY_RESULT, &count);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  glDeleteQueries(1, &Query);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Retrieve transformed data
Shinya Kitaoka 120a6e
  for (int v = 0; v != varyingsCount; ++v) {
Shinya Kitaoka 120a6e
    glBindBuffer(GL_ARRAY_BUFFER, bufferObjectNames[v]);
Shinya Kitaoka 120a6e
    glGetBufferSubData(GL_ARRAY_BUFFER, 0, varyingSizes[v], bufs[v]);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  glBindBuffer(GL_ARRAY_BUFFER, 0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Delete buffer objects
Shinya Kitaoka 120a6e
  glDeleteBuffers(varyingsCount, &bufferObjectNames[0]);
Toshihiro Shimizu 890ddd
}