From 21965187096f8bde7866b05459444793e1a6c1b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 10 Dec 2012 17:49:53 +0100 Subject: iOS: Update GL render buffers when the accociated window is resized We keep track of the with and height of the FBO's buffers, and update their storage if the window size has changed since last time. Change-Id: I97788b69e7067a5b5b9f28e8498cf1bc5d2cf6ea Reviewed-by: Richard Moe Gustavsen --- src/plugins/platforms/ios/qioscontext.h | 2 + src/plugins/platforms/ios/qioscontext.mm | 16 +++---- src/plugins/platforms/ios/qioswindow.h | 9 ++++ src/plugins/platforms/ios/qioswindow.mm | 82 ++++++++++++++++++-------------- 4 files changed, 66 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/ios/qioscontext.h b/src/plugins/platforms/ios/qioscontext.h index 102aaaa387..b45917832c 100644 --- a/src/plugins/platforms/ios/qioscontext.h +++ b/src/plugins/platforms/ios/qioscontext.h @@ -62,6 +62,8 @@ public: void doneCurrent(); GLuint defaultFramebufferObject(QPlatformSurface *) const; + GLuint defaultColorRenderbuffer(QPlatformSurface *) const; + QFunctionPointer getProcAddress(const QByteArray &procName); EAGLContext *nativeContext() const; diff --git a/src/plugins/platforms/ios/qioscontext.mm b/src/plugins/platforms/ios/qioscontext.mm index 8beb588b03..68db28212b 100644 --- a/src/plugins/platforms/ios/qioscontext.mm +++ b/src/plugins/platforms/ios/qioscontext.mm @@ -88,7 +88,8 @@ bool QIOSContext::makeCurrent(QPlatformSurface *surface) [EAGLContext setCurrentContext:m_eaglContext]; glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebufferObject(surface)); - return true; + // Ensures render buffers are set up and match the size of the window + return defaultColorRenderbuffer(surface) != 0; } void QIOSContext::doneCurrent() @@ -101,13 +102,7 @@ void QIOSContext::swapBuffers(QPlatformSurface *surface) Q_ASSERT(surface && surface->surface()->surfaceType() == QSurface::OpenGLSurface); [EAGLContext setCurrentContext:m_eaglContext]; - - GLint renderbuffer; - glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebufferObject(surface)); - glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &renderbuffer); - glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer); - + glBindRenderbuffer(GL_RENDERBUFFER, defaultColorRenderbuffer(surface)); [m_eaglContext presentRenderbuffer:GL_RENDERBUFFER]; } @@ -116,6 +111,11 @@ GLuint QIOSContext::defaultFramebufferObject(QPlatformSurface *surface) const return static_cast(surface)->framebufferObject(*const_cast(this)); } +GLuint QIOSContext::defaultColorRenderbuffer(QPlatformSurface *surface) const +{ + return static_cast(surface)->colorRenderbuffer(*const_cast(this)); +} + QFunctionPointer QIOSContext::getProcAddress(const QByteArray& functionName) { return reinterpret_cast(dlsym(RTLD_NEXT, functionName.constData())); diff --git a/src/plugins/platforms/ios/qioswindow.h b/src/plugins/platforms/ios/qioswindow.h index 2a762d2bdc..4c55249046 100644 --- a/src/plugins/platforms/ios/qioswindow.h +++ b/src/plugins/platforms/ios/qioswindow.h @@ -88,12 +88,21 @@ public: void handleContentOrientationChange(Qt::ScreenOrientation orientation); GLuint framebufferObject(const QIOSContext &context) const; + GLuint colorRenderbuffer(const QIOSContext &context) const; EAGLView *nativeView() const { return m_view; } private: EAGLView *m_view; QRect m_requestedGeometry; + + mutable struct GLData { + GLuint framebufferObject; + GLuint colorRenderbuffer; + GLuint depthRenderbuffer; + GLint renderbufferWidth; + GLint renderbufferHeight; + } m_glData; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/ios/qioswindow.mm b/src/plugins/platforms/ios/qioswindow.mm index b209bbc159..90734e58e8 100644 --- a/src/plugins/platforms/ios/qioswindow.mm +++ b/src/plugins/platforms/ios/qioswindow.mm @@ -116,6 +116,10 @@ static QRect fromCGRect(const CGRect &rect) QRect geometry = fromCGRect(self.frame); m_qioswindow->QPlatformWindow::setGeometry(geometry); QWindowSystemInterface::handleGeometryChange(m_qioswindow->window(), geometry); + + // If we have a new size here we need to resize the FBO's corresponding buffers, + // but we defer that to when the application calls makeCurrent. + [super layoutSubviews]; } @@ -200,6 +204,7 @@ QIOSWindow::QIOSWindow(QWindow *window) : QPlatformWindow(window) , m_view([[EAGLView alloc] initWithQIOSWindow:this]) , m_requestedGeometry(QPlatformWindow::geometry()) + , m_glData() { if ([[UIApplication sharedApplication].delegate isKindOfClass:[QIOSApplicationDelegate class]]) [[UIApplication sharedApplication].delegate.window.rootViewController.view addSubview:m_view]; @@ -209,6 +214,13 @@ 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 release]; } @@ -259,56 +271,56 @@ void QIOSWindow::handleContentOrientationChange(Qt::ScreenOrientation orientatio GLuint QIOSWindow::framebufferObject(const QIOSContext &context) const { - static GLuint framebuffer = 0; + if (!m_glData.framebufferObject) { + [EAGLContext setCurrentContext:context.nativeContext()]; - // FIXME: Cache context and recreate framebuffer if window - // is used with a different context then last time. + glGenFramebuffers(1, &m_glData.framebufferObject); + glBindFramebuffer(GL_FRAMEBUFFER, m_glData.framebufferObject); - if (!framebuffer) { - EAGLContext* eaglContext = context.nativeContext(); + glGenRenderbuffers(1, &m_glData.colorRenderbuffer); + glBindRenderbuffer(GL_RENDERBUFFER, m_glData.colorRenderbuffer); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_glData.colorRenderbuffer); - [EAGLContext setCurrentContext:eaglContext]; + 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); - // Create the framebuffer and bind it - glGenFramebuffers(1, &framebuffer); - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); + if (requestedFormat.stencilBufferSize() > 0) + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_glData.depthRenderbuffer); + } + } - GLint width; - GLint height; + return m_glData.framebufferObject; +} - // Create a color renderbuffer, allocate storage for it, - // and attach it to the framebuffer’s color attachment point. - GLuint colorRenderbuffer; - glGenRenderbuffers(1, &colorRenderbuffer); - glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer); - [eaglContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:static_cast(m_view.layer)]; - glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &width); - glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &height); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRenderbuffer); +GLuint QIOSWindow::colorRenderbuffer(const QIOSContext &context) const +{ + if (!m_glData.colorRenderbuffer || + m_glData.renderbufferWidth != geometry().width() || m_glData.renderbufferHeight != geometry().height()) { - QSurfaceFormat requestedFormat = context.format(); - if (requestedFormat.depthBufferSize() > 0 || requestedFormat.stencilBufferSize() > 0) { - // Create a depth or depth/stencil renderbuffer, allocate storage for it, - // and attach it to the framebuffer’s depth attachment point. - GLuint depthRenderbuffer; - glGenRenderbuffers(1, &depthRenderbuffer); - glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer); + glBindRenderbuffer(GL_RENDERBUFFER, m_glData.colorRenderbuffer); + [context.nativeContext() renderbufferStorage:GL_RENDERBUFFER fromDrawable:static_cast(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 (requestedFormat.stencilBufferSize() > 0) { - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, width, height); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthRenderbuffer); - } else { - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height); - } - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRenderbuffer); + 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 framebuffer; + return m_glData.colorRenderbuffer; } QT_END_NAMESPACE -- cgit v1.2.3