diff options
-rw-r--r-- | src/plugins/platforms/ios/qioscontext.h | 21 | ||||
-rw-r--r-- | src/plugins/platforms/ios/qioscontext.mm | 100 | ||||
-rw-r--r-- | src/plugins/platforms/ios/qioswindow.h | 11 | ||||
-rw-r--r-- | src/plugins/platforms/ios/qioswindow.mm | 65 |
4 files changed, 113 insertions, 84 deletions
diff --git a/src/plugins/platforms/ios/qioscontext.h b/src/plugins/platforms/ios/qioscontext.h index b45917832c..082ec4794c 100644 --- a/src/plugins/platforms/ios/qioscontext.h +++ b/src/plugins/platforms/ios/qioscontext.h @@ -48,8 +48,10 @@ QT_BEGIN_NAMESPACE -class QIOSContext : public QPlatformOpenGLContext +class QIOSContext : public QObject, public QPlatformOpenGLContext { + Q_OBJECT + public: QIOSContext(QOpenGLContext *context); ~QIOSContext(); @@ -62,15 +64,26 @@ public: void doneCurrent(); GLuint defaultFramebufferObject(QPlatformSurface *) const; - GLuint defaultColorRenderbuffer(QPlatformSurface *) const; - QFunctionPointer getProcAddress(const QByteArray &procName); - EAGLContext *nativeContext() const; +private Q_SLOTS: + void windowDestroyed(QObject *object); private: EAGLContext *m_eaglContext; QSurfaceFormat m_format; + + struct FramebufferObject { + GLuint handle; + GLuint colorRenderbuffer; + GLuint depthRenderbuffer; + GLint renderbufferWidth; + GLint renderbufferHeight; + }; + + static void deleteBuffers(const FramebufferObject &framebufferObject); + + mutable QHash<QWindow *, FramebufferObject> m_framebufferObjects; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/ios/qioscontext.mm b/src/plugins/platforms/ios/qioscontext.mm index 00629a84ab..dc431b57dd 100644 --- a/src/plugins/platforms/ios/qioscontext.mm +++ b/src/plugins/platforms/ios/qioscontext.mm @@ -70,12 +70,25 @@ QIOSContext::QIOSContext(QOpenGLContext *context) QIOSContext::~QIOSContext() { - if ([EAGLContext currentContext] == m_eaglContext) - doneCurrent(); + [EAGLContext setCurrentContext:m_eaglContext]; + + foreach (const FramebufferObject &framebufferObject, m_framebufferObjects) + deleteBuffers(framebufferObject); + [EAGLContext setCurrentContext:nil]; [m_eaglContext release]; } +void QIOSContext::deleteBuffers(const FramebufferObject &framebufferObject) +{ + if (framebufferObject.handle) + glDeleteFramebuffers(1, &framebufferObject.handle); + if (framebufferObject.colorRenderbuffer) + glDeleteRenderbuffers(1, &framebufferObject.colorRenderbuffer); + if (framebufferObject.depthRenderbuffer) + glDeleteRenderbuffers(1, &framebufferObject.depthRenderbuffer); +} + QSurfaceFormat QIOSContext::format() const { return m_format; @@ -88,8 +101,7 @@ bool QIOSContext::makeCurrent(QPlatformSurface *surface) [EAGLContext setCurrentContext:m_eaglContext]; glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebufferObject(surface)); - // Ensures render buffers are set up and match the size of the window - return defaultColorRenderbuffer(surface) != 0; + return true; } void QIOSContext::doneCurrent() @@ -100,20 +112,86 @@ void QIOSContext::doneCurrent() void QIOSContext::swapBuffers(QPlatformSurface *surface) { Q_ASSERT(surface && surface->surface()->surfaceType() == QSurface::OpenGLSurface); + Q_ASSERT(surface->surface()->surfaceClass() == QSurface::Window); + QWindow *window = static_cast<QWindow *>(surface->surface()); + Q_ASSERT(m_framebufferObjects.contains(window)); [EAGLContext setCurrentContext:m_eaglContext]; - glBindRenderbuffer(GL_RENDERBUFFER, defaultColorRenderbuffer(surface)); + glBindRenderbuffer(GL_RENDERBUFFER, m_framebufferObjects[window].colorRenderbuffer); [m_eaglContext presentRenderbuffer:GL_RENDERBUFFER]; } GLuint QIOSContext::defaultFramebufferObject(QPlatformSurface *surface) const { - return static_cast<QIOSWindow *>(surface)->framebufferObject(*this); + Q_ASSERT(surface && surface->surface()->surfaceClass() == QSurface::Window); + QWindow *window = static_cast<QWindow *>(surface->surface()); + + FramebufferObject &framebufferObject = m_framebufferObjects[window]; + + // Set up an FBO for the window if it hasn't been created yet + if (!framebufferObject.handle) { + [EAGLContext setCurrentContext:m_eaglContext]; + + glGenFramebuffers(1, &framebufferObject.handle); + glBindFramebuffer(GL_FRAMEBUFFER, framebufferObject.handle); + + glGenRenderbuffers(1, &framebufferObject.colorRenderbuffer); + glBindRenderbuffer(GL_RENDERBUFFER, framebufferObject.colorRenderbuffer); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, + framebufferObject.colorRenderbuffer); + + if (m_format.depthBufferSize() > 0 || m_format.stencilBufferSize() > 0) { + glGenRenderbuffers(1, &framebufferObject.depthRenderbuffer); + glBindRenderbuffer(GL_RENDERBUFFER, framebufferObject.depthRenderbuffer); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, + framebufferObject.depthRenderbuffer); + + if (m_format.stencilBufferSize() > 0) + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, + framebufferObject.depthRenderbuffer); + } + + connect(window, SIGNAL(destroyed(QObject*)), this, SLOT(windowDestroyed(QObject*))); + } + + // Ensure that the FBO's buffers match the size of the window + QIOSWindow *platformWindow = static_cast<QIOSWindow *>(surface); + if (framebufferObject.renderbufferWidth != platformWindow->effectiveWidth() || + framebufferObject.renderbufferHeight != platformWindow->effectiveHeight()) { + + glBindRenderbuffer(GL_RENDERBUFFER, framebufferObject.colorRenderbuffer); + CAEAGLLayer *layer = static_cast<CAEAGLLayer *>(platformWindow->nativeView().layer); + [m_eaglContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:layer]; + + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &framebufferObject.renderbufferWidth); + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &framebufferObject.renderbufferHeight); + + if (framebufferObject.depthRenderbuffer) { + glBindRenderbuffer(GL_RENDERBUFFER, framebufferObject.depthRenderbuffer); + + // FIXME: Support more fine grained control over depth/stencil buffer sizes + if (m_format.stencilBufferSize() > 0) + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, + framebufferObject.renderbufferWidth, framebufferObject.renderbufferHeight); + else + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, + framebufferObject.renderbufferWidth, framebufferObject.renderbufferHeight); + } + + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + NSLog(@"Failed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER)); + } + + return framebufferObject.handle; } -GLuint QIOSContext::defaultColorRenderbuffer(QPlatformSurface *surface) const +void QIOSContext::windowDestroyed(QObject *object) { - return static_cast<QIOSWindow *>(surface)->colorRenderbuffer(*this); + QWindow *window = static_cast<QWindow *>(object); + if (m_framebufferObjects.contains(window)) { + deleteBuffers(m_framebufferObjects[window]); + m_framebufferObjects.remove(window); + } } QFunctionPointer QIOSContext::getProcAddress(const QByteArray& functionName) @@ -121,7 +199,5 @@ QFunctionPointer QIOSContext::getProcAddress(const QByteArray& functionName) return reinterpret_cast<QFunctionPointer>(dlsym(RTLD_NEXT, functionName.constData())); } -EAGLContext *QIOSContext::nativeContext() const -{ - return m_eaglContext; -} +#include "moc_qioscontext.cpp" + diff --git a/src/plugins/platforms/ios/qioswindow.h b/src/plugins/platforms/ios/qioswindow.h index 63099682f1..1f36c525ce 100644 --- a/src/plugins/platforms/ios/qioswindow.h +++ b/src/plugins/platforms/ios/qioswindow.h @@ -67,9 +67,9 @@ public: void handleContentOrientationChange(Qt::ScreenOrientation orientation); void setVisible(bool visible); - GLuint framebufferObject(const QIOSContext &context) const; - GLuint colorRenderbuffer(const QIOSContext &context) const; qreal devicePixelRatio() const; + int effectiveWidth() const; + int effectiveHeight() const; UIView *nativeView() const { return m_view; } @@ -77,13 +77,6 @@ private: UIView *m_view; QRect m_requestedGeometry; - mutable struct GLData { - GLuint framebufferObject; - GLuint colorRenderbuffer; - GLuint depthRenderbuffer; - GLint renderbufferWidth; - GLint renderbufferHeight; - } m_glData; qreal m_devicePixelRatio; }; diff --git a/src/plugins/platforms/ios/qioswindow.mm b/src/plugins/platforms/ios/qioswindow.mm index 9c814ac924..88debb7c33 100644 --- a/src/plugins/platforms/ios/qioswindow.mm +++ b/src/plugins/platforms/ios/qioswindow.mm @@ -229,7 +229,6 @@ QIOSWindow::QIOSWindow(QWindow *window) : QPlatformWindow(window) , m_view([[EAGLView alloc] initWithQIOSWindow:this]) , m_requestedGeometry(QPlatformWindow::geometry()) - , m_glData() , m_devicePixelRatio(1.0) { if (isQtApplication()) @@ -249,13 +248,6 @@ QIOSWindow::QIOSWindow(QWindow *window) QIOSWindow::~QIOSWindow() { - if (m_glData.framebufferObject) - glDeleteFramebuffers(1, &m_glData.framebufferObject); - if (m_glData.colorRenderbuffer) - glDeleteRenderbuffers(1, &m_glData.colorRenderbuffer); - if (m_glData.depthRenderbuffer) - glDeleteRenderbuffers(1, &m_glData.depthRenderbuffer); - [m_view removeFromSuperview]; [m_view release]; } @@ -325,64 +317,19 @@ void QIOSWindow::handleContentOrientationChange(Qt::ScreenOrientation orientatio [[UIApplication sharedApplication] setStatusBarOrientation:uiOrientation animated:NO]; } -GLuint QIOSWindow::framebufferObject(const QIOSContext &context) const +qreal QIOSWindow::devicePixelRatio() const { - if (!m_glData.framebufferObject) { - [EAGLContext setCurrentContext:context.nativeContext()]; - - glGenFramebuffers(1, &m_glData.framebufferObject); - glBindFramebuffer(GL_FRAMEBUFFER, m_glData.framebufferObject); - - glGenRenderbuffers(1, &m_glData.colorRenderbuffer); - glBindRenderbuffer(GL_RENDERBUFFER, m_glData.colorRenderbuffer); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_glData.colorRenderbuffer); - - QSurfaceFormat requestedFormat = context.format(); - if (requestedFormat.depthBufferSize() > 0 || requestedFormat.stencilBufferSize() > 0) { - glGenRenderbuffers(1, &m_glData.depthRenderbuffer); - glBindRenderbuffer(GL_RENDERBUFFER, m_glData.depthRenderbuffer); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_glData.depthRenderbuffer); - - if (requestedFormat.stencilBufferSize() > 0) - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_glData.depthRenderbuffer); - } - } - - return m_glData.framebufferObject; + return m_devicePixelRatio; } -GLuint QIOSWindow::colorRenderbuffer(const QIOSContext &context) const +int QIOSWindow::effectiveWidth() const { - if (!m_glData.colorRenderbuffer || - m_glData.renderbufferWidth != geometry().width() * m_devicePixelRatio || - m_glData.renderbufferHeight != geometry().height() * m_devicePixelRatio) { - - glBindRenderbuffer(GL_RENDERBUFFER, m_glData.colorRenderbuffer); - [context.nativeContext() renderbufferStorage:GL_RENDERBUFFER fromDrawable:static_cast<CAEAGLLayer *>(m_view.layer)]; - - glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &m_glData.renderbufferWidth); - glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &m_glData.renderbufferHeight); - - if (m_glData.depthRenderbuffer) { - glBindRenderbuffer(GL_RENDERBUFFER, m_glData.depthRenderbuffer); - - // FIXME: Support more fine grained control over depth/stencil buffer sizes - if (context.format().stencilBufferSize() > 0) - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, m_glData.renderbufferWidth, m_glData.renderbufferHeight); - else - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, m_glData.renderbufferWidth, m_glData.renderbufferHeight); - } - - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - NSLog(@"Failed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER)); - } - - return m_glData.colorRenderbuffer; + return geometry().width() * m_devicePixelRatio; } -qreal QIOSWindow::devicePixelRatio() const +int QIOSWindow::effectiveHeight() const { - return m_devicePixelRatio; + return geometry().height() * m_devicePixelRatio; } QT_END_NAMESPACE |