ios: Add support for QOpenGLWidget and QQuickWidget

The global shared context is now always enabled on iOS. This means that
contexts used by QOpenGLWindow/Widget and QQuickWindow/Widget and the
iOS backingstore will share with each other.

[ChangeLog][QtGui] QOpenGLWidget and QQuickWidget are now supported on iOS.

Task-number: QTBUG-40034
Change-Id: Ibfb99ffcb18f8f8d263662fbf237bc348fc730ee
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@theqtcompany.com>
bb10
Laszlo Agocs 2015-05-04 10:56:02 +02:00 committed by Tor Arne Vestbø
parent fe1fb593ae
commit e46b6db986
4 changed files with 125 additions and 9 deletions

View File

@ -39,6 +39,8 @@
QT_BEGIN_NAMESPACE
class QOpenGLPaintDevice;
class QOpenGLFramebufferObject;
class QOffscreenSurface;
class QIOSBackingStore : public QPlatformBackingStore
{
@ -49,13 +51,19 @@ public:
QPaintDevice *paintDevice();
void beginPaint(const QRegion &);
void endPaint();
void flush(QWindow *window, const QRegion &region, const QPoint &offset);
void resize(const QSize &size, const QRegion &staticContents);
GLuint toTexture(const QRegion &dirtyRegion, QSize *textureSize, TextureFlags *flags) const;
void makeCurrent();
private:
QOpenGLContext *m_context;
QOpenGLPaintDevice *m_device;
QOpenGLFramebufferObject *m_fbo;
QOffscreenSurface *m_surface;
};
QT_END_NAMESPACE

View File

@ -36,41 +36,117 @@
#include <QtGui/QOpenGLContext>
#include <QtGui/QOpenGLPaintDevice>
#include <QtGui/QOpenGLFramebufferObject>
#include <QtGui/QOffscreenSurface>
#include <QtGui/private/qwindow_p.h>
#include <QtDebug>
class QIOSPaintDevice : public QOpenGLPaintDevice
{
public:
QIOSPaintDevice(QIOSBackingStore *backingStore) : m_backingStore(backingStore) { }
void ensureActiveTarget() Q_DECL_OVERRIDE;
private:
QIOSBackingStore *m_backingStore;
};
void QIOSPaintDevice::ensureActiveTarget()
{
m_backingStore->makeCurrent();
}
QIOSBackingStore::QIOSBackingStore(QWindow *window)
: QPlatformBackingStore(window)
, m_context(new QOpenGLContext)
, m_device(0)
, m_fbo(0)
, m_surface(0)
{
QSurfaceFormat fmt = window->requestedFormat();
fmt.setDepthBufferSize(16);
fmt.setStencilBufferSize(8);
// Due to sharing QIOSContext redirects our makeCurrent on window() attempts to
// the global share context. Hence it is essential to have a compatible format.
fmt.setDepthBufferSize(QSurfaceFormat::defaultFormat().depthBufferSize());
fmt.setStencilBufferSize(QSurfaceFormat::defaultFormat().stencilBufferSize());
// Needed to prevent QOpenGLContext::makeCurrent() from failing
window->setSurfaceType(QSurface::OpenGLSurface);
if (fmt.depthBufferSize() == 0)
qWarning("No depth in default format, expect rendering errors");
if (window->surfaceType() == QSurface::RasterSurface)
window->setSurfaceType(QSurface::OpenGLSurface);
m_context->setFormat(fmt);
m_context->setScreen(window->screen());
Q_ASSERT(QOpenGLContext::globalShareContext());
m_context->setShareContext(QOpenGLContext::globalShareContext());
m_context->create();
}
QIOSBackingStore::~QIOSBackingStore()
{
delete m_fbo;
delete m_surface;
delete m_context;
delete m_device;
}
void QIOSBackingStore::makeCurrent()
{
QSurface *surface = m_surface ? m_surface : static_cast<QSurface *>(window());
if (!m_context->makeCurrent(surface))
qWarning("QIOSBackingStore: makeCurrent() failed");
if (m_fbo)
m_fbo->bind();
}
void QIOSBackingStore::beginPaint(const QRegion &)
{
m_context->makeCurrent(window());
if (qt_window_private(window())->compositing) {
if (!m_fbo) {
delete m_device;
m_device = 0;
}
if (!m_surface) {
m_surface = new QOffscreenSurface;
m_surface->setFormat(m_context->format());
m_surface->create();
}
if (!m_context->makeCurrent(m_surface))
qWarning("QIOSBackingStore: Failed to make offscreen surface current");
const QSize size = window()->size() * window()->devicePixelRatio();
if (m_fbo && m_fbo->size() != size) {
delete m_fbo;
m_fbo = 0;
}
if (!m_fbo)
m_fbo = new QOpenGLFramebufferObject(size, QOpenGLFramebufferObject::CombinedDepthStencil);
} else if (m_fbo) {
delete m_fbo;
m_fbo = 0;
delete m_surface;
m_surface = 0;
delete m_device;
m_device = 0;
}
makeCurrent();
if (!m_device)
m_device = new QIOSPaintDevice(this);
}
void QIOSBackingStore::endPaint()
{
if (m_fbo) {
m_fbo->release();
glFlush();
}
}
QPaintDevice *QIOSBackingStore::paintDevice()
{
if (!m_device)
m_device = new QOpenGLPaintDevice;
Q_ASSERT(m_device);
// Keep paint device size and device pixel ratio in sync with window
qreal devicePixelRatio = window()->devicePixelRatio();
@ -82,6 +158,8 @@ QPaintDevice *QIOSBackingStore::paintDevice()
void QIOSBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
{
Q_ASSERT(!qt_window_private(window)->compositing);
Q_UNUSED(region);
Q_UNUSED(offset);
@ -111,4 +189,21 @@ void QIOSBackingStore::resize(const QSize &size, const QRegion &staticContents)
qWarning() << "QIOSBackingStore needs to have the same size as its window";
}
GLuint QIOSBackingStore::toTexture(const QRegion &dirtyRegion, QSize *textureSize, TextureFlags *flags) const
{
Q_ASSERT(qt_window_private(window())->compositing);
Q_UNUSED(dirtyRegion);
if (flags)
*flags = TextureFlip;
if (!m_fbo)
return 0;
if (textureSize)
*textureSize = m_fbo->size();
return m_fbo->texture();
}
QT_END_NAMESPACE

View File

@ -116,7 +116,8 @@ static QString fboStatusString(GLenum status)
bool QIOSContext::makeCurrent(QPlatformSurface *surface)
{
Q_ASSERT(surface && surface->surface()->surfaceType() == QSurface::OpenGLSurface);
Q_ASSERT(surface && (surface->surface()->surfaceType() == QSurface::OpenGLSurface
|| surface->surface()->surfaceType() == QSurface::RasterGLSurface));
[EAGLContext setCurrentContext:m_eaglContext];
@ -141,7 +142,8 @@ void QIOSContext::doneCurrent()
void QIOSContext::swapBuffers(QPlatformSurface *surface)
{
Q_ASSERT(surface && surface->surface()->surfaceType() == QSurface::OpenGLSurface);
Q_ASSERT(surface && (surface->surface()->surfaceType() == QSurface::OpenGLSurface
|| surface->surface()->surfaceType() == QSurface::RasterGLSurface));
if (surface->surface()->surfaceClass() == QSurface::Offscreen)
return; // Nothing to do

View File

@ -77,6 +77,15 @@ QIOSIntegration::QIOSIntegration()
"'applicationDidFinishLaunching' inside your UIApplication delegate.\n");
}
// The backingstore needs a global share context in order to support composition in
// QPlatformBackingStore.
qApp->setAttribute(Qt::AA_ShareOpenGLContexts, true);
// And that context must match the format used for the backingstore's context.
QSurfaceFormat fmt;
fmt.setDepthBufferSize(16);
fmt.setStencilBufferSize(8);
QSurfaceFormat::setDefaultFormat(fmt);
// Set current directory to app bundle folder
QDir::setCurrent(QString::fromUtf8([[[NSBundle mainBundle] bundlePath] UTF8String]));
@ -137,6 +146,8 @@ bool QIOSIntegration::hasCapability(Capability cap) const
return false;
case ApplicationState:
return true;
case RasterGLSurface:
return true;
default:
return QPlatformIntegration::hasCapability(cap);
}