summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTor Arne Vestbø <tor.arne.vestbo@theqtcompany.com>2015-12-14 17:20:58 +0100
committerTor Arne Vestbø <tor.arne.vestbo@theqtcompany.com>2015-12-17 01:11:52 +0000
commit3e892e4a972446d17afde178a7b17482ecaced33 (patch)
treedce269b0b5dbb42b0471318f070348aafcdcd1e0
parent4891fd02c5503e6f3838276883f7bba0b89cdb0d (diff)
iOS: Switch backingstore to use raster paint engine, not GL
Now that more of the raster operations are NEON-optimized this should be acceptable. The switch enables antialiased drawing, and makes iOS in line with other platforms in having QBackingStore backed by a QImage. The use of QImage also allows us to remove code from the backingstore implementation that was only needed to support the composeAndFlush code path. The common parts of a raster backingstore implementation have been factored out into QRasterBackingStore in platformsupport, which can be shared with more platforms in the future. [ChangeLog][iOS] QBackingStore now uses the raster paint engine instead of the OpenGL paint engine, enabling improved antialiased drawing. In case of performance regressions, the old code path can be enabled by setting the window's surface type to QSurface::OpenGLSurface. Task-number: QTBUG-35271 Change-Id: Ia300b9a5edf8dc0b4bfb99d84ed3c23a8523c267 Reviewed-by: Laszlo Agocs <laszlo.agocs@theqtcompany.com>
-rw-r--r--src/platformsupport/graphics/graphics.pri2
-rw-r--r--src/platformsupport/graphics/qrasterbackingstore.cpp104
-rw-r--r--src/platformsupport/graphics/qrasterbackingstore_p.h71
-rw-r--r--src/platformsupport/platformsupport.pro1
-rw-r--r--src/plugins/platforms/ios/qiosbackingstore.h21
-rw-r--r--src/plugins/platforms/ios/qiosbackingstore.mm111
6 files changed, 225 insertions, 85 deletions
diff --git a/src/platformsupport/graphics/graphics.pri b/src/platformsupport/graphics/graphics.pri
new file mode 100644
index 0000000000..43062682aa
--- /dev/null
+++ b/src/platformsupport/graphics/graphics.pri
@@ -0,0 +1,2 @@
+HEADERS += $$PWD/qrasterbackingstore_p.h
+SOURCES += $$PWD/qrasterbackingstore.cpp
diff --git a/src/platformsupport/graphics/qrasterbackingstore.cpp b/src/platformsupport/graphics/qrasterbackingstore.cpp
new file mode 100644
index 0000000000..a64a4cfa40
--- /dev/null
+++ b/src/platformsupport/graphics/qrasterbackingstore.cpp
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qrasterbackingstore_p.h"
+
+#include <QtGui/qpainter.h>
+
+QT_BEGIN_NAMESPACE
+
+QRasterBackingStore::QRasterBackingStore(QWindow *window)
+ : QPlatformBackingStore(window)
+{
+}
+
+QRasterBackingStore::~QRasterBackingStore()
+{
+}
+
+void QRasterBackingStore::resize(const QSize &size, const QRegion &staticContents)
+{
+ Q_UNUSED(staticContents);
+
+ int windowDevicePixelRatio = window()->devicePixelRatio();
+ QSize effectiveBufferSize = size * windowDevicePixelRatio;
+
+ if (m_image.size() == effectiveBufferSize)
+ return;
+
+ QImage::Format format = window()->format().hasAlpha() ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32;
+ m_image = QImage(effectiveBufferSize, format);
+ m_image.setDevicePixelRatio(windowDevicePixelRatio);
+ if (format == QImage::Format_ARGB32_Premultiplied)
+ m_image.fill(Qt::transparent);
+}
+
+QPaintDevice *QRasterBackingStore::paintDevice()
+{
+ return &m_image;
+}
+
+QImage QRasterBackingStore::toImage() const
+{
+ return m_image;
+}
+
+bool QRasterBackingStore::scroll(const QRegion &region, int dx, int dy)
+{
+ if (window()->surfaceType() != QSurface::RasterSurface)
+ return false;
+
+ extern void qt_scrollRectInImage(QImage &, const QRect &, const QPoint &);
+
+ const qreal devicePixelRatio = m_image.devicePixelRatio();
+ const QPoint delta(dx * devicePixelRatio, dy * devicePixelRatio);
+
+ foreach (const QRect &rect, region.rects())
+ qt_scrollRectInImage(m_image, QRect(rect.topLeft() * devicePixelRatio, rect.size() * devicePixelRatio), delta);
+
+ return true;
+}
+
+void QRasterBackingStore::beginPaint(const QRegion &region)
+{
+ if (!m_image.hasAlphaChannel())
+ return;
+
+ QPainter painter(&m_image);
+ painter.setCompositionMode(QPainter::CompositionMode_Source);
+ const QColor blank = Qt::transparent;
+ foreach (const QRect &rect, region.rects())
+ painter.fillRect(rect, blank);
+}
+
+QT_END_NAMESPACE
diff --git a/src/platformsupport/graphics/qrasterbackingstore_p.h b/src/platformsupport/graphics/qrasterbackingstore_p.h
new file mode 100644
index 0000000000..314a6e6e79
--- /dev/null
+++ b/src/platformsupport/graphics/qrasterbackingstore_p.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QRASTERBACKINGSTORE_P_H
+#define QRASTERBACKINGSTORE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <qpa/qplatformbackingstore.h>
+
+
+QT_BEGIN_NAMESPACE
+
+class QRasterBackingStore : public QPlatformBackingStore
+{
+public:
+ QRasterBackingStore(QWindow *window);
+ ~QRasterBackingStore();
+
+ QPaintDevice *paintDevice() Q_DECL_OVERRIDE;
+ QImage toImage() const Q_DECL_OVERRIDE;
+ void resize (const QSize &size, const QRegion &) Q_DECL_OVERRIDE;
+ bool scroll(const QRegion &area, int dx, int dy) Q_DECL_OVERRIDE;
+ void beginPaint(const QRegion &region) Q_DECL_OVERRIDE;
+
+protected:
+ QImage m_image;
+};
+
+QT_END_NAMESPACE
+
+#endif // QRASTERBACKINGSTORE_P_H
diff --git a/src/platformsupport/platformsupport.pro b/src/platformsupport/platformsupport.pro
index 1ea6d0eb69..81c7faa389 100644
--- a/src/platformsupport/platformsupport.pro
+++ b/src/platformsupport/platformsupport.pro
@@ -25,5 +25,6 @@ contains(QT_CONFIG, dbus) {
include(dbusmenu/dbusmenu.pri)
include(dbustray/dbustray.pri)
}
+ios: include(graphics/graphics.pri)
load(qt_module)
diff --git a/src/plugins/platforms/ios/qiosbackingstore.h b/src/plugins/platforms/ios/qiosbackingstore.h
index 5d2ae429f1..387a286447 100644
--- a/src/plugins/platforms/ios/qiosbackingstore.h
+++ b/src/plugins/platforms/ios/qiosbackingstore.h
@@ -36,34 +36,31 @@
#include <qpa/qplatformbackingstore.h>
+#include <QtPlatformSupport/private/qrasterbackingstore_p.h>
+
QT_BEGIN_NAMESPACE
class QOpenGLPaintDevice;
-class QOpenGLFramebufferObject;
-class QOffscreenSurface;
-class QIOSBackingStore : public QPlatformBackingStore
+class QIOSBackingStore : public QRasterBackingStore
{
public:
QIOSBackingStore(QWindow *window);
~QIOSBackingStore();
- QPaintDevice *paintDevice();
+ QPaintDevice *paintDevice() Q_DECL_OVERRIDE;
- void beginPaint(const QRegion &);
- void endPaint();
+ void beginPaint(const QRegion &) Q_DECL_OVERRIDE;
+ void endPaint() Q_DECL_OVERRIDE;
- 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 flush(QWindow *window, const QRegion &region, const QPoint &offset) Q_DECL_OVERRIDE;
+ void resize(const QSize &size, const QRegion &staticContents) Q_DECL_OVERRIDE;
void makeCurrent();
private:
QOpenGLContext *m_context;
- QOpenGLPaintDevice *m_device;
- QOpenGLFramebufferObject *m_fbo;
- QOffscreenSurface *m_surface;
+ QOpenGLPaintDevice *m_glDevice;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/ios/qiosbackingstore.mm b/src/plugins/platforms/ios/qiosbackingstore.mm
index 875d06dc80..f408c13af3 100644
--- a/src/plugins/platforms/ios/qiosbackingstore.mm
+++ b/src/plugins/platforms/ios/qiosbackingstore.mm
@@ -38,6 +38,7 @@
#include <QtGui/QOpenGLPaintDevice>
#include <QtGui/QOpenGLFramebufferObject>
#include <QtGui/QOffscreenSurface>
+#include <QtGui/qpainter.h>
#include <QtGui/private/qwindow_p.h>
#include <QtDebug>
@@ -58,13 +59,12 @@ void QIOSPaintDevice::ensureActiveTarget()
}
QIOSBackingStore::QIOSBackingStore(QWindow *window)
- : QPlatformBackingStore(window)
+ : QRasterBackingStore(window)
, m_context(new QOpenGLContext)
- , m_device(0)
- , m_fbo(0)
- , m_surface(0)
+ , m_glDevice(nullptr)
{
QSurfaceFormat fmt = window->requestedFormat();
+
// 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());
@@ -73,8 +73,10 @@ QIOSBackingStore::QIOSBackingStore(QWindow *window)
if (fmt.depthBufferSize() == 0)
qWarning("No depth in default format, expect rendering errors");
+ // We use the surface both for raster operations and for GL drawing (when
+ // we blit the raster image), so the type needs to cover both use cases.
if (window->surfaceType() == QSurface::RasterSurface)
- window->setSurfaceType(QSurface::OpenGLSurface);
+ window->setSurfaceType(QSurface::RasterGLSurface);
m_context->setFormat(fmt);
m_context->setScreen(window->screen());
@@ -85,75 +87,44 @@ QIOSBackingStore::QIOSBackingStore(QWindow *window)
QIOSBackingStore::~QIOSBackingStore()
{
- delete m_fbo;
- delete m_surface;
delete m_context;
- delete m_device;
+ delete m_glDevice;
}
void QIOSBackingStore::makeCurrent()
{
- QSurface *surface = m_surface ? m_surface : static_cast<QSurface *>(window());
- if (!m_context->makeCurrent(surface))
+ if (!m_context->makeCurrent(window()))
qWarning("QIOSBackingStore: makeCurrent() failed");
- if (m_fbo)
- m_fbo->bind();
}
-void QIOSBackingStore::beginPaint(const QRegion &)
+void QIOSBackingStore::beginPaint(const QRegion &region)
{
- 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);
+ if (!m_glDevice)
+ m_glDevice = new QIOSPaintDevice(this);
+
+ if (window()->surfaceType() == QSurface::RasterGLSurface)
+ QRasterBackingStore::beginPaint(region);
}
void QIOSBackingStore::endPaint()
{
- if (m_fbo) {
- m_fbo->release();
- glFlush();
- }
}
QPaintDevice *QIOSBackingStore::paintDevice()
{
- Q_ASSERT(m_device);
+ Q_ASSERT(m_glDevice);
// Keep paint device size and device pixel ratio in sync with window
qreal devicePixelRatio = window()->devicePixelRatio();
- m_device->setSize(window()->size() * devicePixelRatio);
- m_device->setDevicePixelRatio(devicePixelRatio);
+ m_glDevice->setSize(window()->size() * devicePixelRatio);
+ m_glDevice->setDevicePixelRatio(devicePixelRatio);
- return m_device;
+ if (window()->surfaceType() == QSurface::RasterGLSurface)
+ return QRasterBackingStore::paintDevice();
+ else
+ return m_glDevice;
}
void QIOSBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
@@ -171,6 +142,11 @@ void QIOSBackingStore::flush(QWindow *window, const QRegion &region, const QPoin
return;
}
+ if (window->surfaceType() == QSurface::RasterGLSurface) {
+ QPainter painter(m_glDevice);
+ painter.drawImage(QPoint(), m_image);
+ }
+
m_context->makeCurrent(window);
m_context->swapBuffers(window);
}
@@ -179,31 +155,20 @@ void QIOSBackingStore::resize(const QSize &size, const QRegion &staticContents)
{
Q_UNUSED(staticContents);
- // Resizing the backing store would in our case mean resizing the QWindow,
- // as we cheat and use an QOpenGLPaintDevice that we target at the window.
- // That's probably not what the user intended, so we ignore resizes of the
- // backing store and always keep the paint device's size in sync with the
- // window size in beginPaint().
+ if (window()->surfaceType() == QSurface::OpenGLSurface) {
+ // Resizing the backing store would in this case mean resizing the QWindow,
+ // as we use an QOpenGLPaintDevice that we target at the window. That's
+ // probably not what the user intended, so we ignore resizes of the backing
+ // store and always keep the paint device's size in sync with the window
+ // size in beginPaint().
- if (size != window()->size() && !window()->inherits("QWidgetWindow"))
- 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 (size != window()->size() && !window()->inherits("QWidgetWindow"))
+ qWarning() << "QIOSBackingStore needs to have the same size as its window";
- if (!m_fbo)
- return 0;
-
- if (textureSize)
- *textureSize = m_fbo->size();
+ return;
+ }
- return m_fbo->texture();
+ QRasterBackingStore::resize(size, staticContents);
}
QT_END_NAMESPACE