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
parent
fe1fb593ae
commit
e46b6db986
|
|
@ -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 ®ion, 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
|
||||
|
|
|
|||
|
|
@ -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 ®ion, 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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue