summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/cocoa/qcocoabackingstore.mm
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/cocoa/qcocoabackingstore.mm')
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.mm364
1 files changed, 236 insertions, 128 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
index 01787da1af..b211b5d02d 100644
--- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm
+++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://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 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <AppKit/AppKit.h>
@@ -45,6 +9,7 @@
#include "qcocoahelpers.h"
#include <QtCore/qmath.h>
+#include <QtCore/private/qcore_mac_p.h>
#include <QtGui/qpainter.h>
#include <QuartzCore/CATransaction.h>
@@ -52,14 +17,15 @@
QT_BEGIN_NAMESPACE
QCocoaBackingStore::QCocoaBackingStore(QWindow *window)
- : QRasterBackingStore(window)
+ : QPlatformBackingStore(window)
{
}
QCFType<CGColorSpaceRef> QCocoaBackingStore::colorSpace() const
{
- NSView *view = static_cast<QCocoaWindow *>(window()->handle())->view();
- return QCFType<CGColorSpaceRef>::constructFromGet(view.window.colorSpace.CGColorSpace);
+ const auto *platformWindow = static_cast<QCocoaWindow *>(window()->handle());
+ const QNSView *view = qnsview_cast(platformWindow->view());
+ return QCFType<CGColorSpaceRef>::constructFromGet(view.colorSpace.CGColorSpace);
}
// ----------------------------------------------------------------------------
@@ -67,7 +33,9 @@ QCFType<CGColorSpaceRef> QCocoaBackingStore::colorSpace() const
QCALayerBackingStore::QCALayerBackingStore(QWindow *window)
: QCocoaBackingStore(window)
{
- qCDebug(lcQpaBackingStore) << "Creating QCALayerBackingStore for" << window;
+ qCDebug(lcQpaBackingStore) << "Creating QCALayerBackingStore for" << window
+ << "with" << window->format();
+
m_buffers.resize(1);
observeBackingPropertiesChanges();
@@ -105,12 +73,11 @@ bool QCALayerBackingStore::eventFilter(QObject *watched, QEvent *event)
void QCALayerBackingStore::resize(const QSize &size, const QRegion &staticContents)
{
- qCDebug(lcQpaBackingStore) << "Resize requested to" << size;
-
- if (!staticContents.isNull())
- qCWarning(lcQpaBackingStore) << "QCALayerBackingStore does not support static contents";
+ qCDebug(lcQpaBackingStore) << "Resize requested to" << size
+ << "with static contents" << staticContents;
m_requestedSize = size;
+ m_staticContents = staticContents;
}
void QCALayerBackingStore::beginPaint(const QRegion &region)
@@ -138,7 +105,8 @@ void QCALayerBackingStore::beginPaint(const QRegion &region)
painter.fillRect(rect, Qt::transparent);
}
- m_paintedRegion += region;
+ // We assume the client is going to paint the entire region
+ updateDirtyStates(region);
}
void QCALayerBackingStore::ensureBackBuffer()
@@ -146,13 +114,6 @@ void QCALayerBackingStore::ensureBackBuffer()
if (window()->format().swapBehavior() == QSurfaceFormat::SingleBuffer)
return;
- // The current back buffer may have been assigned to a layer in a previous flush,
- // but we deferred the swap. Do it now if the surface has been picked up by CA.
- if (m_buffers.back() && m_buffers.back()->isInUse() && m_buffers.back() != m_buffers.front()) {
- qCInfo(lcQpaBackingStore) << "Back buffer has been picked up by CA, swapping to front";
- std::swap(m_buffers.back(), m_buffers.front());
- }
-
if (Q_UNLIKELY(lcQpaBackingStore().isDebugEnabled())) {
// ┌───────┬───────┬───────┬─────┬──────┐
// │ front ┊ spare ┊ spare ┊ ... ┊ back │
@@ -228,11 +189,50 @@ bool QCALayerBackingStore::recreateBackBufferIfNeeded()
}
#endif
- qCInfo(lcQpaBackingStore) << "Creating surface of" << requestedBufferSize
- << "based on requested" << m_requestedSize << "and dpr =" << devicePixelRatio;
+ qCInfo(lcQpaBackingStore)<< "Creating surface of" << requestedBufferSize
+ << "for" << window() << "based on requested" << m_requestedSize
+ << "dpr =" << devicePixelRatio << "and color space" << colorSpace();
static auto pixelFormat = QImage::toPixelFormat(QImage::Format_ARGB32_Premultiplied);
- m_buffers.back().reset(new GraphicsBuffer(requestedBufferSize, devicePixelRatio, pixelFormat, colorSpace()));
+ auto *newBackBuffer = new GraphicsBuffer(requestedBufferSize, devicePixelRatio, pixelFormat, colorSpace());
+
+ if (!m_staticContents.isEmpty() && m_buffers.back()) {
+ // We implicitly support static backingstore content as a result of
+ // finalizing the back buffer on flush, where we copy any non-painted
+ // areas from the front buffer. But there is no guarantee that a resize
+ // will always come after a flush, where we have a pristine front buffer
+ // to copy from. It may come after a few begin/endPaints, where the back
+ // buffer then contains (part of) the latest state. We also have the case
+ // of single-buffered backingstore, where the front and back buffer is
+ // the same, which means we must do the copy from the old back buffer
+ // to the newly resized buffer now, before we replace it below.
+
+ // If the back buffer has been partially filled already, we need to
+ // copy parts of the static content from that. The rest we copy from
+ // the front buffer.
+ const QRegion backBufferRegion = m_staticContents - m_buffers.back()->dirtyRegion;
+ const QRegion frontBufferRegion = m_staticContents - backBufferRegion;
+
+ qCInfo(lcQpaBackingStore) << "Preserving static content" << backBufferRegion
+ << "from back buffer, and" << frontBufferRegion << "from front buffer";
+
+ newBackBuffer->lock(QPlatformGraphicsBuffer::SWWriteAccess);
+ blitBuffer(m_buffers.back().get(), backBufferRegion, newBackBuffer);
+ Q_ASSERT(frontBufferRegion.isEmpty() || m_buffers.front());
+ blitBuffer(m_buffers.front().get(), frontBufferRegion, newBackBuffer);
+ newBackBuffer->unlock();
+
+ // The new back buffer now is valid for the static contents region.
+ // We don't need to maintain the static contents region for resizes
+ // of any other buffers in the swap chain, as these will finalize
+ // their content on flush from the buffer we just filled, and we
+ // don't need to mark them dirty for the area we just filled, as
+ // new buffers are fully dirty when created.
+ newBackBuffer->dirtyRegion -= m_staticContents;
+ m_staticContents = {};
+ }
+
+ m_buffers.back().reset(newBackBuffer);
return true;
}
@@ -247,8 +247,68 @@ QPaintDevice *QCALayerBackingStore::paintDevice()
void QCALayerBackingStore::endPaint()
{
- qCInfo(lcQpaBackingStore) << "Paint ended with painted region" << m_paintedRegion;
+ qCInfo(lcQpaBackingStore) << "Paint ended. Back buffer valid region is now" << m_buffers.back()->validRegion();
+ m_buffers.back()->unlock();
+
+ // Since we can have multiple begin/endPaint rounds before a flush
+ // we defer finalizing the back buffer until its content is needed.
+}
+
+bool QCALayerBackingStore::scroll(const QRegion &region, int dx, int dy)
+{
+ if (!m_buffers.back()) {
+ qCInfo(lcQpaBackingStore) << "Scroll requested with no back buffer. Ignoring.";
+ return false;
+ }
+
+ const QPoint scrollDelta(dx, dy);
+ qCInfo(lcQpaBackingStore) << "Scrolling" << region << "by" << scrollDelta;
+
+ ensureBackBuffer();
+ recreateBackBufferIfNeeded();
+
+ const QRegion inPlaceRegion = region - m_buffers.back()->dirtyRegion;
+ const QRegion frontBufferRegion = region - inPlaceRegion;
+
+ QMacAutoReleasePool pool;
+
+ m_buffers.back()->lock(QPlatformGraphicsBuffer::SWWriteAccess);
+
+ if (!inPlaceRegion.isEmpty()) {
+ // We have to scroll everything in one go, instead of scrolling the
+ // individual rects of the region, as otherwise we may end up reading
+ // already overwritten (scrolled) pixels.
+ const QRect inPlaceBoundingRect = inPlaceRegion.boundingRect();
+
+ qCDebug(lcQpaBackingStore) << "Scrolling" << inPlaceBoundingRect << "in place";
+ QImage *backBufferImage = m_buffers.back()->asImage();
+ const qreal devicePixelRatio = backBufferImage->devicePixelRatio();
+ const QPoint devicePixelDelta = scrollDelta * devicePixelRatio;
+
+ extern void qt_scrollRectInImage(QImage &, const QRect &, const QPoint &);
+
+ qt_scrollRectInImage(*backBufferImage,
+ QRect(inPlaceBoundingRect.topLeft() * devicePixelRatio,
+ inPlaceBoundingRect.size() * devicePixelRatio),
+ devicePixelDelta);
+ }
+
+ if (!frontBufferRegion.isEmpty()) {
+ qCDebug(lcQpaBackingStore) << "Scrolling" << frontBufferRegion << "by copying from front buffer";
+ blitBuffer(m_buffers.front().get(), frontBufferRegion, m_buffers.back().get(), scrollDelta);
+ }
+
m_buffers.back()->unlock();
+
+ // Mark the target region as filled. Note: We do not mark the source region
+ // as dirty, even though the content has conceptually been "moved", as that
+ // would complicate things when preserving from the front buffer. This matches
+ // the behavior of other backingstore implementations using qt_scrollRectInImage.
+ updateDirtyStates(region.translated(scrollDelta));
+
+ qCInfo(lcQpaBackingStore) << "Scroll ended. Back buffer valid region is now" << m_buffers.back()->validRegion();
+
+ return true;
}
void QCALayerBackingStore::flush(QWindow *flushedWindow, const QRegion &region, const QPoint &offset)
@@ -256,14 +316,23 @@ void QCALayerBackingStore::flush(QWindow *flushedWindow, const QRegion &region,
Q_UNUSED(region);
Q_UNUSED(offset);
- if (!prepareForFlush())
+ if (!m_buffers.back()) {
+ qCWarning(lcQpaBackingStore) << "Tried to flush backingstore without painting to it first";
return;
+ }
+
+ finalizeBackBuffer();
if (flushedWindow != window()) {
flushSubWindow(flushedWindow);
return;
}
+ if (m_buffers.front()->isInUse() && !m_buffers.front()->isDirty()) {
+ qCInfo(lcQpaBackingStore) << "Asked to flush, but front buffer is up to date. Ignoring.";
+ return;
+ }
+
QMacAutoReleasePool pool;
NSView *flushedView = static_cast<QCocoaWindow *>(flushedWindow->handle())->view();
@@ -287,16 +356,6 @@ void QCALayerBackingStore::flush(QWindow *flushedWindow, const QRegion &region,
const bool isSingleBuffered = window()->format().swapBehavior() == QSurfaceFormat::SingleBuffer;
id backBufferSurface = (__bridge id)m_buffers.back()->surface();
- if (!isSingleBuffered && flushedView.layer.contents == backBufferSurface) {
- // We've managed to paint to the back buffer again before Core Animation had time
- // to flush the transaction and persist the layer changes to the window server, or
- // we've been asked to flush without painting anything. The layer already knows about
- // the back buffer, and we don't need to re-apply it to pick up any possible surface
- // changes, so bail out early.
- qCInfo(lcQpaBackingStore).nospace() << "Skipping flush of " << flushedView
- << ", layer already reflects back buffer";
- return;
- }
// Trigger a new display cycle if there isn't one. This ensures that our layer updates
// are committed as part of a display-cycle instead of on the next runloop pass. This
@@ -315,14 +374,17 @@ void QCALayerBackingStore::flush(QWindow *flushedWindow, const QRegion &region,
flushedView.layer.contents = backBufferSurface;
- // Since we may receive multiple flushes before a new frame is started, we do not
- // swap any buffers just yet. Instead we check in the next beginPaint if the layer's
- // surface is in use, and if so swap to an unused surface as the new back buffer.
+ if (!isSingleBuffered) {
+ // Mark the surface as in use, so that we don't end up rendering
+ // to it while it's assigned to a layer.
+ IOSurfaceIncrementUseCount(m_buffers.back()->surface());
- // Note: Ideally CoreAnimation would mark a surface as in use the moment we assign
- // it to a layer, but as that's not the case we may end up painting to the same back
- // buffer once more if we are painting faster than CA can ship the surfaces over to
- // the window server.
+ if (m_buffers.back() != m_buffers.front()) {
+ qCInfo(lcQpaBackingStore) << "Swapping back buffer to front";
+ std::swap(m_buffers.back(), m_buffers.front());
+ IOSurfaceDecrementUseCount(m_buffers.back()->surface());
+ }
+ }
}
void QCALayerBackingStore::flushSubWindow(QWindow *subWindow)
@@ -372,22 +434,30 @@ void QCALayerBackingStore::windowDestroyed(QObject *object)
m_subWindowBackingstores.erase(window);
}
-#ifndef QT_NO_OPENGL
-void QCALayerBackingStore::composeAndFlush(QWindow *window, const QRegion &region, const QPoint &offset,
- QPlatformTextureList *textures, bool translucentBackground)
+QPlatformBackingStore::FlushResult QCALayerBackingStore::rhiFlush(QWindow *window,
+ qreal sourceDevicePixelRatio,
+ const QRegion &region,
+ const QPoint &offset,
+ QPlatformTextureList *textures,
+ bool translucentBackground)
{
- if (!prepareForFlush())
- return;
+ if (!m_buffers.back()) {
+ qCWarning(lcQpaBackingStore) << "Tried to flush backingstore without painting to it first";
+ return FlushFailed;
+ }
+
+ finalizeBackBuffer();
- QPlatformBackingStore::composeAndFlush(window, region, offset, textures, translucentBackground);
+ return QPlatformBackingStore::rhiFlush(window, sourceDevicePixelRatio, region, offset, textures, translucentBackground);
}
-#endif
QImage QCALayerBackingStore::toImage() const
{
- if (!const_cast<QCALayerBackingStore*>(this)->prepareForFlush())
+ if (!m_buffers.back())
return QImage();
+ const_cast<QCALayerBackingStore*>(this)->finalizeBackBuffer();
+
// We need to make a copy here, as the returned image could be used just
// for reading, in which case it won't detach, and then the underlying
// image data might change under the feet of the client when we re-use
@@ -409,10 +479,11 @@ void QCALayerBackingStore::backingPropertiesChanged()
qCDebug(lcQpaBackingStore) << "Backing properties for" << window() << "did change";
- qCDebug(lcQpaBackingStore) << "Updating color space of existing buffers";
+ const auto newColorSpace = colorSpace();
+ qCDebug(lcQpaBackingStore) << "Updating color space of existing buffers to" << newColorSpace;
for (auto &buffer : m_buffers) {
if (buffer)
- buffer->setColorSpace(colorSpace());
+ buffer->setColorSpace(newColorSpace);
}
}
@@ -421,69 +492,99 @@ QPlatformGraphicsBuffer *QCALayerBackingStore::graphicsBuffer() const
return m_buffers.back().get();
}
-bool QCALayerBackingStore::prepareForFlush()
+void QCALayerBackingStore::updateDirtyStates(const QRegion &paintedRegion)
{
- if (!m_buffers.back()) {
- qCWarning(lcQpaBackingStore) << "Tried to flush backingstore without painting to it first";
- return false;
- }
-
// Update dirty state of buffers based on what was painted. The back buffer will be
// less dirty, since we painted to it, while other buffers will become more dirty.
// This allows us to minimize copies between front and back buffers on swap in the
// cases where the painted region overlaps with the previous frame (front buffer).
for (const auto &buffer : m_buffers) {
if (buffer == m_buffers.back())
- buffer->dirtyRegion -= m_paintedRegion;
+ buffer->dirtyRegion -= paintedRegion;
else
- buffer->dirtyRegion += m_paintedRegion;
+ buffer->dirtyRegion += paintedRegion;
}
+}
+void QCALayerBackingStore::finalizeBackBuffer()
+{
// After painting, the back buffer is only guaranteed to have content for the painted
// region, and may still have dirty areas that need to be synced up with the front buffer,
// if we have one. We know that the front buffer is always up to date.
- if (!m_buffers.back()->dirtyRegion.isEmpty() && m_buffers.front() != m_buffers.back()) {
- QRegion preserveRegion = m_buffers.back()->dirtyRegion;
- qCDebug(lcQpaBackingStore) << "Preserving" << preserveRegion << "from front to back buffer";
- m_buffers.front()->lock(QPlatformGraphicsBuffer::SWReadAccess);
- const QImage *frontBuffer = m_buffers.front()->asImage();
+ if (!m_buffers.back()->isDirty())
+ return;
- const QRect frontSurfaceBounds(QPoint(0, 0), m_buffers.front()->size());
- const qreal sourceDevicePixelRatio = frontBuffer->devicePixelRatio();
+ qCDebug(lcQpaBackingStore) << "Finalizing back buffer with dirty region" << m_buffers.back()->dirtyRegion;
+ if (m_buffers.back() != m_buffers.front()) {
m_buffers.back()->lock(QPlatformGraphicsBuffer::SWWriteAccess);
- QPainter painter(m_buffers.back()->asImage());
- painter.setCompositionMode(QPainter::CompositionMode_Source);
+ blitBuffer(m_buffers.front().get(), m_buffers.back()->dirtyRegion, m_buffers.back().get());
+ m_buffers.back()->unlock();
+ } else {
+ qCDebug(lcQpaBackingStore) << "Front and back buffer is the same. Can not finalize back buffer.";
+ }
- // Let painter operate in device pixels, to make it easier to compare coordinates
- const qreal targetDevicePixelRatio = painter.device()->devicePixelRatio();
- painter.scale(1.0 / targetDevicePixelRatio, 1.0 / targetDevicePixelRatio);
+ // The back buffer is now completely in sync, ready to be presented
+ m_buffers.back()->dirtyRegion = QRegion();
+}
- for (const QRect &rect : preserveRegion) {
- QRect sourceRect(rect.topLeft() * sourceDevicePixelRatio, rect.size() * sourceDevicePixelRatio);
- QRect targetRect(rect.topLeft() * targetDevicePixelRatio, rect.size() * targetDevicePixelRatio);
+/*
+ \internal
-#ifdef QT_DEBUG
- if (Q_UNLIKELY(!frontSurfaceBounds.contains(sourceRect.bottomRight()))) {
- qCWarning(lcQpaBackingStore) << "Front buffer too small to preserve"
- << QRegion(sourceRect).subtracted(frontSurfaceBounds);
- }
-#endif
- painter.drawImage(targetRect, *frontBuffer, sourceRect);
- }
+ Blits \a sourceRegion from \a sourceBuffer to \a destinationBuffer,
+ at offset \a destinationOffset.
- m_buffers.back()->unlock();
- m_buffers.front()->unlock();
+ The source buffer is automatically locked for read only access
+ during the blit.
- // The back buffer is now completely in sync, ready to be presented
- m_buffers.back()->dirtyRegion = QRegion();
- }
+ The destination buffer has to be locked for write access by the
+ caller.
+*/
+
+void QCALayerBackingStore::blitBuffer(GraphicsBuffer *sourceBuffer, const QRegion &sourceRegion,
+ GraphicsBuffer *destinationBuffer, const QPoint &destinationOffset)
+{
+ Q_ASSERT(sourceBuffer && destinationBuffer);
+ Q_ASSERT(sourceBuffer != destinationBuffer);
- // Prepare for another round of painting
- m_paintedRegion = QRegion();
+ if (sourceRegion.isEmpty())
+ return;
- return true;
+ qCDebug(lcQpaBackingStore) << "Blitting" << sourceRegion << "of" << sourceBuffer
+ << "to" << sourceRegion.translated(destinationOffset) << "of" << destinationBuffer;
+
+ Q_ASSERT(destinationBuffer->isLocked() == QPlatformGraphicsBuffer::SWWriteAccess);
+
+ sourceBuffer->lock(QPlatformGraphicsBuffer::SWReadAccess);
+ const QImage *sourceImage = sourceBuffer->asImage();
+
+ const QRect sourceBufferBounds(QPoint(0, 0), sourceBuffer->size());
+ const qreal sourceDevicePixelRatio = sourceImage->devicePixelRatio();
+
+ QPainter painter(destinationBuffer->asImage());
+ painter.setCompositionMode(QPainter::CompositionMode_Source);
+
+ // Let painter operate in device pixels, to make it easier to compare coordinates
+ const qreal destinationDevicePixelRatio = painter.device()->devicePixelRatio();
+ painter.scale(1.0 / destinationDevicePixelRatio, 1.0 / destinationDevicePixelRatio);
+
+ for (const QRect &rect : sourceRegion) {
+ QRect sourceRect(rect.topLeft() * sourceDevicePixelRatio,
+ rect.size() * sourceDevicePixelRatio);
+ QRect destinationRect((rect.topLeft() + destinationOffset) * destinationDevicePixelRatio,
+ rect.size() * destinationDevicePixelRatio);
+
+#ifdef QT_DEBUG
+ if (Q_UNLIKELY(!sourceBufferBounds.contains(sourceRect.bottomRight()))) {
+ qCWarning(lcQpaBackingStore) << "Source buffer of size" << sourceBuffer->size()
+ << "is too small to blit" << sourceRect;
+ }
+#endif
+ painter.drawImage(destinationRect, *sourceImage, sourceRect);
+ }
+
+ sourceBuffer->unlock();
}
// ----------------------------------------------------------------------------
@@ -491,12 +592,19 @@ bool QCALayerBackingStore::prepareForFlush()
QCALayerBackingStore::GraphicsBuffer::GraphicsBuffer(const QSize &size, qreal devicePixelRatio,
const QPixelFormat &format, QCFType<CGColorSpaceRef> colorSpace)
: QIOSurfaceGraphicsBuffer(size, format)
- , dirtyRegion(0, 0, size.width() / devicePixelRatio, size.height() / devicePixelRatio)
+ , dirtyRegion(QRect(QPoint(0, 0), size / devicePixelRatio))
, m_devicePixelRatio(devicePixelRatio)
{
setColorSpace(colorSpace);
}
+QRegion QCALayerBackingStore::GraphicsBuffer::validRegion() const
+{
+
+ QRegion fullRegion = QRect(QPoint(0, 0), size() / m_devicePixelRatio);
+ return fullRegion - dirtyRegion;
+}
+
QImage *QCALayerBackingStore::GraphicsBuffer::asImage()
{
if (m_image.isNull()) {
@@ -514,6 +622,6 @@ QImage *QCALayerBackingStore::GraphicsBuffer::asImage()
return &m_image;
}
-#include "moc_qcocoabackingstore.cpp"
-
QT_END_NAMESPACE
+
+#include "moc_qcocoabackingstore.cpp"