From 2654fdb346ef740ecc2591edc7af860c08455548 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 26 Mar 2014 15:58:15 +0100 Subject: iOS: Check FBO status and return failure from QIOSContext::makeCurrent() The Khronos documentation for glCheckFramebufferStatus recommends calling the function to see if the framebuffer is complete prior to rendering. We now give more info to clients that call makeCurrent(), by storing the state of the default FBO and returning that, instead of always returning true and leaving the clients vulnerable to calling OpenGL functions on a non-complete FBO. Change-Id: Ia99c21f811ac799b350f07e73b2ae4b173d71120 Reviewed-by: Richard Moe Gustavsen Reviewed-by: Laszlo Agocs --- src/plugins/platforms/ios/qioscontext.h | 2 ++ src/plugins/platforms/ios/qioscontext.mm | 40 +++++++++++++++++++++++++++----- 2 files changed, 36 insertions(+), 6 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/ios/qioscontext.h b/src/plugins/platforms/ios/qioscontext.h index c48a0251a9..52357a5d58 100644 --- a/src/plugins/platforms/ios/qioscontext.h +++ b/src/plugins/platforms/ios/qioscontext.h @@ -85,10 +85,12 @@ private: GLuint depthRenderbuffer; GLint renderbufferWidth; GLint renderbufferHeight; + bool isComplete; }; static void deleteBuffers(const FramebufferObject &framebufferObject); + FramebufferObject &backingFramebufferObjectFor(QPlatformSurface *) const; mutable QHash m_framebufferObjects; }; diff --git a/src/plugins/platforms/ios/qioscontext.mm b/src/plugins/platforms/ios/qioscontext.mm index 7310d2904f..a35b4f164c 100644 --- a/src/plugins/platforms/ios/qioscontext.mm +++ b/src/plugins/platforms/ios/qioscontext.mm @@ -94,14 +94,33 @@ QSurfaceFormat QIOSContext::format() const return m_format; } +#define QT_IOS_GL_STATUS_CASE(val) case val: return QLatin1Literal(#val) + +static QString fboStatusString(GLenum status) +{ + switch (status) { + QT_IOS_GL_STATUS_CASE(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT); + QT_IOS_GL_STATUS_CASE(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS); + QT_IOS_GL_STATUS_CASE(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT); + QT_IOS_GL_STATUS_CASE(GL_FRAMEBUFFER_UNSUPPORTED); + default: + return QString(QStringLiteral("unknown status: %x")).arg(status); + } +} + bool QIOSContext::makeCurrent(QPlatformSurface *surface) { Q_ASSERT(surface && surface->surface()->surfaceType() == QSurface::OpenGLSurface); [EAGLContext setCurrentContext:m_eaglContext]; - glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebufferObject(surface)); + FramebufferObject &framebufferObject = backingFramebufferObjectFor(surface); + + // We bind the default FBO even if it's incomplete, so that clients who + // call glCheckFramebufferStatus as a result of this function returning + // false will get a matching error code. + glBindFramebuffer(GL_FRAMEBUFFER, framebufferObject.handle); - return true; + return framebufferObject.isComplete; } void QIOSContext::doneCurrent() @@ -121,7 +140,7 @@ void QIOSContext::swapBuffers(QPlatformSurface *surface) [m_eaglContext presentRenderbuffer:GL_RENDERBUFFER]; } -GLuint QIOSContext::defaultFramebufferObject(QPlatformSurface *surface) const +QIOSContext::FramebufferObject &QIOSContext::backingFramebufferObjectFor(QPlatformSurface *surface) const { Q_ASSERT(surface && surface->surface()->surfaceClass() == QSurface::Window); QIOSWindow *window = static_cast(surface); @@ -181,11 +200,20 @@ GLuint QIOSContext::defaultFramebufferObject(QPlatformSurface *surface) const framebufferObject.renderbufferWidth, framebufferObject.renderbufferHeight); } - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - NSLog(@"Failed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER)); + framebufferObject.isComplete = glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE; + + if (!framebufferObject.isComplete) { + qWarning("QIOSContext failed to make complete framebuffer object (%s)", + qPrintable(fboStatusString(glCheckFramebufferStatus(GL_FRAMEBUFFER)))); + } } - return framebufferObject.handle; + return framebufferObject; +} + +GLuint QIOSContext::defaultFramebufferObject(QPlatformSurface *surface) const +{ + return backingFramebufferObjectFor(surface).handle; } void QIOSContext::windowDestroyed(QObject *object) -- cgit v1.2.3