Skip to content

Commit

Permalink
Fixed|Cleanup: Framebuffer initialization
Browse files Browse the repository at this point in the history
The GL init/ready notifications are now done when the first
Canvas::paintGL() is issued. Canvas::initializeGL() performs the
low-level OpenGL API initialization.

GLTextureFramebuffer's asset state is now separate from the base
class's state to avoid confusion.
  • Loading branch information
skyjake committed Sep 4, 2016
1 parent 875613d commit b38eefd
Show file tree
Hide file tree
Showing 14 changed files with 108 additions and 70 deletions.
2 changes: 1 addition & 1 deletion doomsday/apps/client/src/gl/dgl_common.cpp
Expand Up @@ -368,7 +368,7 @@ void GL_SetMultisample(dd_bool on)
else glDisable(GL_MULTISAMPLE);
#endif*/

/// @todo Do this via QSurfaceFormat.
/// @todo Do this via GLFramebuffer.
qDebug() << "GL_SetMultisample:" << on << "(not implemented)";
}

Expand Down
2 changes: 1 addition & 1 deletion doomsday/apps/client/src/render/viewports.cpp
Expand Up @@ -1004,7 +1004,7 @@ static void clearViewPorts()

if(fx::Bloom::isEnabled() ||
(App_InFineSystem().finaleInProgess() && !GameUIWidget::finaleStretch()) ||
ClientApp::vr().mode() == VRConfig::OculusRift)
ClientApp::vr().mode() == VRConfig::OculusRift)
{
// Parts of the previous frame might leak in the bloom unless we clear the color
// buffer. Not doing this would result in very bright HOMs in map holes and game
Expand Down
2 changes: 1 addition & 1 deletion doomsday/sdk/libappfw/src/guirootwidget.cpp
Expand Up @@ -413,7 +413,7 @@ void GuiRootWidget::draw()
{
// Widgets may not yet be ready on the first frame; make sure
// we don't show garbage.
window().canvas().renderTarget().clear(GLFramebuffer::Color);
window().canvas().framebuffer().clear(GLFramebuffer::Color);

d->noFramesDrawnYet = false;
}
Expand Down
2 changes: 1 addition & 1 deletion doomsday/sdk/libappfw/src/vrwindowtransform.cpp
Expand Up @@ -52,7 +52,7 @@ DENG2_PIMPL(VRWindowTransform)

GLFramebuffer &target() const
{
return canvas().renderTarget();
return canvas().framebuffer();
}

int width() const
Expand Down
2 changes: 2 additions & 0 deletions doomsday/sdk/libgui/include/de/graphics/glshaderbank.h
Expand Up @@ -45,6 +45,8 @@ class LIBGUI_PUBLIC GLShaderBank : public InfoBank
public:
GLShaderBank();

void clear();

void addFromInfo(File const &file);

GLShader &shader(DotPath const &path, GLShader::Type type) const;
Expand Down
Expand Up @@ -55,9 +55,9 @@ class LIBGUI_PUBLIC GLTextureFramebuffer : public GLFramebuffer
typedef Vector2ui Size;

public:
GLTextureFramebuffer(Image::Format const & colorFormat = Image::RGB_888,
Size const & initialSize = Size(),
int sampleCount = 0 /*default*/);
GLTextureFramebuffer(Image::Format const &colorFormat = Image::RGB_888,
Size const &initialSize = Size(),
int sampleCount = 0 /*default*/);

void glInit();
void glDeinit();
Expand Down
6 changes: 2 additions & 4 deletions doomsday/sdk/libgui/include/de/gui/canvas.h
Expand Up @@ -168,9 +168,7 @@ class LIBGUI_PUBLIC Canvas : public QOpenGLWidget, public KeyEventSource, public
*
* @return GL render target.
*/
GLFramebuffer &renderTarget() const;

GLTextureFramebuffer &framebuffer();
GLTextureFramebuffer &framebuffer() const;

/**
* Copies or swaps the back buffer to the front, making it visible.
Expand All @@ -192,7 +190,7 @@ class LIBGUI_PUBLIC Canvas : public QOpenGLWidget, public KeyEventSource, public
void mouseDoubleClickEvent(QMouseEvent *ev);
void mouseMoveEvent(QMouseEvent *ev);
void wheelEvent(QWheelEvent *ev);
void showEvent(QShowEvent *ev);
//void showEvent(QShowEvent *ev);

protected slots:
void notifyReady();
Expand Down
82 changes: 40 additions & 42 deletions doomsday/sdk/libgui/src/canvas.cpp
Expand Up @@ -51,7 +51,7 @@ namespace de {

DENG2_PIMPL(Canvas)
{
GLTextureFramebuffer framebuf;
GLTextureFramebuffer backing;

CanvasWindow *parent;
bool readyNotified;
Expand Down Expand Up @@ -193,19 +193,20 @@ DENG2_PIMPL(Canvas)

void reconfigureFramebuffer()
{
framebuf.setColorFormat(Image::RGB_888);
framebuf.resize(currentSize);
backing.setColorFormat(Image::RGB_888);
backing.resize(currentSize);
}

void glInit()
{
DENG2_ASSERT(parent != 0);
framebuf.glInit();
GLInfo::glInit();
backing.glInit();
}

void glDeinit()
{
framebuf.glDeinit();
backing.glDeinit();
GLInfo::glDeinit();
}

Expand Down Expand Up @@ -343,14 +344,9 @@ void Canvas::copyAudiencesFrom(Canvas const &other)
audienceForMouseEvent() = other.audienceForMouseEvent();
}

GLFramebuffer &Canvas::renderTarget() const
{
return d->framebuf;
}

GLTextureFramebuffer &Canvas::framebuffer()
GLTextureFramebuffer &Canvas::framebuffer() const
{
return d->framebuf;
return d->backing;
}

/*void Canvas::swapBuffers(gl::SwapBufferMode swapMode)
Expand All @@ -361,11 +357,9 @@ GLTextureFramebuffer &Canvas::framebuffer()
void Canvas::initializeGL()
{
LOG_AS("Canvas");
LOGDEV_GL_NOTE("Notifying GL init (during paint)");
LOGDEV_GL_NOTE("Initializing OpenGL window");

GLInfo::glInit();

DENG2_FOR_AUDIENCE2(GLInit, i) i->canvasGLInit(*this);
d->glInit();
}

void Canvas::resizeGL(int w, int h)
Expand All @@ -391,20 +385,25 @@ void Canvas::updateSize()
LOGDEV_GL_MSG("Canvas %p resizing now") << this;
#endif

makeCurrent();
d->currentSize = d->pendingSize;
d->reconfigureFramebuffer();

if (d->readyNotified)
{
makeCurrent();
d->reconfigureFramebuffer();
}

DENG2_FOR_AUDIENCE2(GLResize, i) i->canvasGLResized(*this);
}

#if 0
void Canvas::showEvent(QShowEvent* ev)
{
LOG_AS("Canvas");

QOpenGLWidget::showEvent(ev);

// The first time the window is shown, run the initialization callback. On
/*// The first time the window is shown, run the initialization callback. On
// some platforms, OpenGL is not fully ready to be used before the window
// actually appears on screen.
if (isVisible() && !d->readyNotified)
Expand All @@ -417,64 +416,63 @@ void Canvas::showEvent(QShowEvent* ev)
#endif
GLInfo::glInit();
QTimer::singleShot(1, this, SLOT(notifyReady()));
}
}*/
}
#endif

void Canvas::notifyReady()
{
if (d->readyNotified) return;

d->readyNotified = true;

d->glInit();
makeCurrent();

d->reconfigureFramebuffer();

// Everybody can perform GL init now.
DENG2_FOR_AUDIENCE2(GLInit, i) i->canvasGLInit(*this);

// Print some information.
QSurfaceFormat const fmt = format();

/*if (fmt.openGLVersionFlags().testFlag(QGLFormat::OpenGL_Version_3_3))
LOG_GL_NOTE("OpenGL 3.3 supported");
else if ((fmt.openGLVersionFlags().testFlag(QGLFormat::OpenGL_Version_3_2)))
LOG_GL_NOTE("OpenGL 3.2 supported");
else if ((fmt.openGLVersionFlags().testFlag(QGLFormat::OpenGL_Version_3_1)))
LOG_GL_NOTE("OpenGL 3.1 supported");
else if ((fmt.openGLVersionFlags().testFlag(QGLFormat::OpenGL_Version_3_0)))
LOG_GL_NOTE("OpenGL 3.0 supported");
else if ((fmt.openGLVersionFlags().testFlag(QGLFormat::OpenGL_Version_2_1)))
LOG_GL_NOTE("OpenGL 2.1 supported");
else if ((fmt.openGLVersionFlags().testFlag(QGLFormat::OpenGL_Version_2_0)))
LOG_GL_NOTE("OpenGL 2.0 supported");
else
LOG_GL_WARNING("OpenGL 2.0 is not supported!");*/

LOG_GL_NOTE("OpenGL %i.%i supported (%s)")
LOG_GL_NOTE("OpenGL %i.%i supported%s")
<< fmt.majorVersion() << fmt.minorVersion()
<< (fmt.profile() == QSurfaceFormat::CompatibilityProfile? "Compatibility" : "Core");
<< (fmt.majorVersion() > 2?
(fmt.profile() == QSurfaceFormat::CompatibilityProfile? " (Compatibility)"
: " (Core)") : "");

LOGDEV_GL_XVERBOSE("Notifying GL ready");
DENG2_FOR_AUDIENCE2(GLReady, i) i->canvasGLReady(*this);

// This Canvas instance might have been destroyed now.
doneCurrent();
}

void Canvas::paintGL()
{
if (!d->parent/* || d->parent->isRecreationInProgress()*/) return;

DENG2_ASSERT(QOpenGLContext::currentContext() != nullptr);

GLFramebuffer::setDefaultFramebuffer(defaultFramebufferObject());

if (!d->readyNotified)
{
QTimer::singleShot(1, this, SLOT(notifyReady()));
return;
}

DENG2_ASSERT(QOpenGLContext::currentContext() != nullptr);

LIBGUI_ASSERT_GL_OK();

// Make sure any changes to the state stack are in effect.
GLState::current().apply();
GLState::current().target().glBind();

DENG2_FOR_AUDIENCE2(GLDraw, i) i->canvasGLDraw(*this);

LIBGUI_ASSERT_GL_OK();

d->framebuf.blit();
d->backing.blit();
}

void Canvas::focusInEvent(QFocusEvent*)
Expand Down
2 changes: 1 addition & 1 deletion doomsday/sdk/libgui/src/canvaswindow.cpp
Expand Up @@ -41,7 +41,7 @@ static CanvasWindow *mainWindow = 0;

DENG2_PIMPL(CanvasWindow)
{
Canvas* canvas; ///< Drawing surface for the contents of the window.
Canvas *canvas; ///< Drawing surface for the contents of the window.
//Canvas* recreated;
Canvas::FocusChangeAudience canvasFocusAudience; ///< Stored here during recreation.
bool ready;
Expand Down
13 changes: 10 additions & 3 deletions doomsday/sdk/libgui/src/graphics/glframebuffer.cpp
Expand Up @@ -517,7 +517,11 @@ void GLFramebuffer::glBind() const
{
LIBGUI_ASSERT_GL_OK();
DENG2_ASSERT(isReady());
if (!isReady()) return;
if (!isReady())
{
//qWarning() << "GLFramebuffer: Trying to bind a not-ready FBO";
return;
}

GLuint const fbo = (d->fbo? d->fbo : defaultFramebuffer);

Expand All @@ -535,8 +539,8 @@ void GLFramebuffer::glBind() const
//DENG2_ASSERT(!d->fbo || glIsFramebuffer(d->fbo));
if (fbo && !GLInfo::EXT_framebuffer_object()->glIsFramebufferEXT(fbo))
{
qDebug() << "GLFramebuffer: WARNING! Attempting to bind FBO" << fbo
<< "that is not a valid OpenGL FBO";
qWarning() << "[GLFramebuffer] WARNING! Attempting to bind FBO" << fbo
<< "that is not a valid OpenGL FBO";
}

//qDebug() << "GLFramebuffer: binding FBO" << d->fbo;
Expand Down Expand Up @@ -674,6 +678,8 @@ void GLFramebuffer::blit(gl::Filter filtering) const
{
LIBGUI_ASSERT_GL_OK();

//qDebug() << "Blitting from" << d->fbo << "to" << defaultFramebuffer << size().asText();

GLInfo::EXT_framebuffer_object()->glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, d->fbo);
GLInfo::EXT_framebuffer_object()->glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, defaultFramebuffer);

Expand Down Expand Up @@ -703,6 +709,7 @@ GLFramebuffer::Size GLFramebuffer::size() const
{
return d->size;
}
//qDebug() << "FBO" << d->fbo << "size" << CanvasWindow::main().canvas().size().asText();
return CanvasWindow::main().canvas().size();
}

Expand Down
5 changes: 5 additions & 0 deletions doomsday/sdk/libgui/src/graphics/glshaderbank.cpp
Expand Up @@ -176,6 +176,11 @@ DENG2_PIMPL(GLShaderBank)
GLShaderBank::GLShaderBank() : InfoBank("GLShaderBank"), d(new Impl(this))
{}

void GLShaderBank::clear()
{
d->clearShaders();
}

void GLShaderBank::addFromInfo(File const &file)
{
LOG_AS("GLShaderBank");
Expand Down
4 changes: 2 additions & 2 deletions doomsday/sdk/libgui/src/graphics/glstate.cpp
Expand Up @@ -604,7 +604,7 @@ GLFramebuffer &GLState::target() const
{
return *d->target;
}
return CanvasWindow::main().canvas().renderTarget();
return CanvasWindow::main().canvas().framebuffer();
}

Rectangleui GLState::viewport() const
Expand Down Expand Up @@ -661,7 +661,7 @@ void GLState::apply() const
}

internal::currentTarget = newTarget;
internal::currentTarget.get()->glBind();
newTarget->glBind();

if ((oldTarget && oldTarget->hasActiveRect()) || newTarget->hasActiveRect())
{
Expand Down

0 comments on commit b38eefd

Please sign in to comment.