Merge "Merge remote-tracking branch 'origin/5.14' into 5.15"
This commit is contained in:
commit
fd44fb7675
@ -845,7 +845,7 @@ EGLint SwapChain11::copyOffscreenToBackbuffer(const gl::Context *context,
|
|||||||
stateManager->setRenderTarget(mBackBufferRTView.get(), nullptr);
|
stateManager->setRenderTarget(mBackBufferRTView.get(), nullptr);
|
||||||
|
|
||||||
// Set the viewport
|
// Set the viewport
|
||||||
stateManager->setSimpleViewport(mWidth, mHeight);
|
stateManager->setSimpleViewport(width, height);
|
||||||
|
|
||||||
// Apply textures
|
// Apply textures
|
||||||
stateManager->setSimplePixelTextureAndSampler(mOffscreenSRView, mPassThroughSampler);
|
stateManager->setSimplePixelTextureAndSampler(mOffscreenSRView, mPassThroughSampler);
|
||||||
|
@ -0,0 +1,27 @@
|
|||||||
|
From 029d42d1049dcde7950c11fb9adf07c07a8c4c02 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Oliver Wolff <oliver.wolff@qt.io>
|
||||||
|
Date: Wed, 18 Mar 2020 10:56:53 +0100
|
||||||
|
Subject: [PATCH] ANGLE: Fix resizing of windows (Take 2)
|
||||||
|
|
||||||
|
Task-number: QTBUG-62475
|
||||||
|
Change-Id: I0ea17e7875906508941ae64bb396a4236928b0f9
|
||||||
|
---
|
||||||
|
.../angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
|
||||||
|
index e8f13b388f..9ece77ecbc 100644
|
||||||
|
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
|
||||||
|
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
|
||||||
|
@@ -845,7 +845,7 @@ EGLint SwapChain11::copyOffscreenToBackbuffer(const gl::Context *context,
|
||||||
|
stateManager->setRenderTarget(mBackBufferRTView.get(), nullptr);
|
||||||
|
|
||||||
|
// Set the viewport
|
||||||
|
- stateManager->setSimpleViewport(mWidth, mHeight);
|
||||||
|
+ stateManager->setSimpleViewport(width, height);
|
||||||
|
|
||||||
|
// Apply textures
|
||||||
|
stateManager->setSimplePixelTextureAndSampler(mOffscreenSRView, mPassThroughSampler);
|
||||||
|
--
|
||||||
|
2.20.1.windows.1
|
||||||
|
|
@ -844,11 +844,6 @@ static QCborValue::Type convertToExtendedType(QCborContainerPrivate *d)
|
|||||||
return QCborValue::Tag;
|
return QCborValue::Tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if QT_CONFIG(cborstreamreader)
|
|
||||||
// in qcborstream.cpp
|
|
||||||
extern void qt_cbor_stream_set_error(QCborStreamReaderPrivate *d, QCborError error);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if QT_CONFIG(cborstreamwriter)
|
#if QT_CONFIG(cborstreamwriter)
|
||||||
static void writeDoubleToCbor(QCborStreamWriter &writer, double d, QCborValue::EncodingOptions opt)
|
static void writeDoubleToCbor(QCborStreamWriter &writer, double d, QCborValue::EncodingOptions opt)
|
||||||
{
|
{
|
||||||
@ -1462,23 +1457,59 @@ static Element decodeBasicValueFromCbor(QCborStreamReader &reader)
|
|||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline QCborContainerPrivate *createContainerFromCbor(QCborStreamReader &reader)
|
static inline QCborContainerPrivate *createContainerFromCbor(QCborStreamReader &reader, int remainingRecursionDepth)
|
||||||
{
|
{
|
||||||
auto d = new QCborContainerPrivate;
|
if (Q_UNLIKELY(remainingRecursionDepth == 0)) {
|
||||||
|
QCborContainerPrivate::setErrorInReader(reader, { QCborError::NestingTooDeep });
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
QCborContainerPrivate *d = nullptr;
|
||||||
|
int mapShift = reader.isMap() ? 1 : 0;
|
||||||
|
if (reader.isLengthKnown()) {
|
||||||
|
quint64 len = reader.length();
|
||||||
|
|
||||||
|
// Clamp allocation to 1M elements (avoids crashing due to corrupt
|
||||||
|
// stream or loss of precision when converting from quint64 to
|
||||||
|
// QVector::size_type).
|
||||||
|
len = qMin(len, quint64(1024 * 1024 - 1));
|
||||||
|
if (len) {
|
||||||
|
d = new QCborContainerPrivate;
|
||||||
d->ref.storeRelaxed(1);
|
d->ref.storeRelaxed(1);
|
||||||
d->decodeFromCbor(reader);
|
d->elements.reserve(qsizetype(len) << mapShift);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
d = new QCborContainerPrivate;
|
||||||
|
d->ref.storeRelaxed(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.enterContainer();
|
||||||
|
if (reader.lastError() != QCborError::NoError)
|
||||||
|
return d;
|
||||||
|
|
||||||
|
while (reader.hasNext() && reader.lastError() == QCborError::NoError)
|
||||||
|
d->decodeValueFromCbor(reader, remainingRecursionDepth - 1);
|
||||||
|
|
||||||
|
if (reader.lastError() == QCborError::NoError)
|
||||||
|
reader.leaveContainer();
|
||||||
|
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
static QCborValue taggedValueFromCbor(QCborStreamReader &reader)
|
static QCborValue taggedValueFromCbor(QCborStreamReader &reader, int remainingRecursionDepth)
|
||||||
{
|
{
|
||||||
|
if (Q_UNLIKELY(remainingRecursionDepth == 0)) {
|
||||||
|
QCborContainerPrivate::setErrorInReader(reader, { QCborError::NestingTooDeep });
|
||||||
|
return QCborValue::Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
auto d = new QCborContainerPrivate;
|
auto d = new QCborContainerPrivate;
|
||||||
d->append(reader.toTag());
|
d->append(reader.toTag());
|
||||||
reader.next();
|
reader.next();
|
||||||
|
|
||||||
if (reader.lastError() == QCborError::NoError) {
|
if (reader.lastError() == QCborError::NoError) {
|
||||||
// decode tagged value
|
// decode tagged value
|
||||||
d->decodeValueFromCbor(reader);
|
d->decodeValueFromCbor(reader, remainingRecursionDepth - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
QCborValue::Type type;
|
QCborValue::Type type;
|
||||||
@ -1494,6 +1525,13 @@ static QCborValue taggedValueFromCbor(QCborStreamReader &reader)
|
|||||||
return QCborContainerPrivate::makeValue(type, -1, d);
|
return QCborContainerPrivate::makeValue(type, -1, d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// in qcborstream.cpp
|
||||||
|
extern void qt_cbor_stream_set_error(QCborStreamReaderPrivate *d, QCborError error);
|
||||||
|
inline void QCborContainerPrivate::setErrorInReader(QCborStreamReader &reader, QCborError error)
|
||||||
|
{
|
||||||
|
qt_cbor_stream_set_error(reader.d.data(), error);
|
||||||
|
}
|
||||||
|
|
||||||
void QCborContainerPrivate::decodeStringFromCbor(QCborStreamReader &reader)
|
void QCborContainerPrivate::decodeStringFromCbor(QCborStreamReader &reader)
|
||||||
{
|
{
|
||||||
auto addByteData_local = [this](QByteArray::size_type len) -> qint64 {
|
auto addByteData_local = [this](QByteArray::size_type len) -> qint64 {
|
||||||
@ -1538,7 +1576,7 @@ void QCborContainerPrivate::decodeStringFromCbor(QCborStreamReader &reader)
|
|||||||
return; // error
|
return; // error
|
||||||
if (len != rawlen) {
|
if (len != rawlen) {
|
||||||
// truncation
|
// truncation
|
||||||
qt_cbor_stream_set_error(reader.d.data(), { QCborError::DataTooLarge });
|
setErrorInReader(reader, { QCborError::DataTooLarge });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1548,7 +1586,7 @@ void QCborContainerPrivate::decodeStringFromCbor(QCborStreamReader &reader)
|
|||||||
e.value = addByteData_local(len);
|
e.value = addByteData_local(len);
|
||||||
if (e.value < 0) {
|
if (e.value < 0) {
|
||||||
// overflow
|
// overflow
|
||||||
qt_cbor_stream_set_error(reader.d.data(), { QCborError::DataTooLarge });
|
setErrorInReader(reader, { QCborError::DataTooLarge });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1562,7 +1600,7 @@ void QCborContainerPrivate::decodeStringFromCbor(QCborStreamReader &reader)
|
|||||||
auto utf8result = QUtf8::isValidUtf8(dataPtr() + data.size() - len, len);
|
auto utf8result = QUtf8::isValidUtf8(dataPtr() + data.size() - len, len);
|
||||||
if (!utf8result.isValidUtf8) {
|
if (!utf8result.isValidUtf8) {
|
||||||
r.status = QCborStreamReader::Error;
|
r.status = QCborStreamReader::Error;
|
||||||
qt_cbor_stream_set_error(reader.d.data(), { QCborError::InvalidUtf8String });
|
setErrorInReader(reader, { QCborError::InvalidUtf8String });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
isAscii = isAscii && utf8result.isValidAscii;
|
isAscii = isAscii && utf8result.isValidAscii;
|
||||||
@ -1586,7 +1624,7 @@ void QCborContainerPrivate::decodeStringFromCbor(QCborStreamReader &reader)
|
|||||||
|
|
||||||
// error
|
// error
|
||||||
r.status = QCborStreamReader::Error;
|
r.status = QCborStreamReader::Error;
|
||||||
qt_cbor_stream_set_error(reader.d.data(), { QCborError::DataTooLarge });
|
setErrorInReader(reader, { QCborError::DataTooLarge });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r.status == QCborStreamReader::Error) {
|
if (r.status == QCborStreamReader::Error) {
|
||||||
@ -1612,9 +1650,10 @@ void QCborContainerPrivate::decodeStringFromCbor(QCborStreamReader &reader)
|
|||||||
elements.append(e);
|
elements.append(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QCborContainerPrivate::decodeValueFromCbor(QCborStreamReader &reader)
|
void QCborContainerPrivate::decodeValueFromCbor(QCborStreamReader &reader, int remainingRecursionDepth)
|
||||||
{
|
{
|
||||||
switch (reader.type()) {
|
QCborStreamReader::Type t = reader.type();
|
||||||
|
switch (t) {
|
||||||
case QCborStreamReader::UnsignedInteger:
|
case QCborStreamReader::UnsignedInteger:
|
||||||
case QCborStreamReader::NegativeInteger:
|
case QCborStreamReader::NegativeInteger:
|
||||||
case QCborStreamReader::SimpleType:
|
case QCborStreamReader::SimpleType:
|
||||||
@ -1631,37 +1670,17 @@ void QCborContainerPrivate::decodeValueFromCbor(QCborStreamReader &reader)
|
|||||||
|
|
||||||
case QCborStreamReader::Array:
|
case QCborStreamReader::Array:
|
||||||
case QCborStreamReader::Map:
|
case QCborStreamReader::Map:
|
||||||
|
return append(makeValue(t == QCborStreamReader::Array ? QCborValue::Array : QCborValue::Map, -1,
|
||||||
|
createContainerFromCbor(reader, remainingRecursionDepth),
|
||||||
|
MoveContainer));
|
||||||
|
|
||||||
case QCborStreamReader::Tag:
|
case QCborStreamReader::Tag:
|
||||||
return append(QCborValue::fromCbor(reader));
|
return append(taggedValueFromCbor(reader, remainingRecursionDepth));
|
||||||
|
|
||||||
case QCborStreamReader::Invalid:
|
case QCborStreamReader::Invalid:
|
||||||
return; // probably a decode error
|
return; // probably a decode error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QCborContainerPrivate::decodeFromCbor(QCborStreamReader &reader)
|
|
||||||
{
|
|
||||||
int mapShift = reader.isMap() ? 1 : 0;
|
|
||||||
if (reader.isLengthKnown()) {
|
|
||||||
quint64 len = reader.length();
|
|
||||||
|
|
||||||
// Clamp allocation to 1M elements (avoids crashing due to corrupt
|
|
||||||
// stream or loss of precision when converting from quint64 to
|
|
||||||
// QVector::size_type).
|
|
||||||
len = qMin(len, quint64(1024 * 1024 - 1));
|
|
||||||
elements.reserve(qsizetype(len) << mapShift);
|
|
||||||
}
|
|
||||||
|
|
||||||
reader.enterContainer();
|
|
||||||
if (reader.lastError() != QCborError::NoError)
|
|
||||||
return;
|
|
||||||
|
|
||||||
while (reader.hasNext() && reader.lastError() == QCborError::NoError)
|
|
||||||
decodeValueFromCbor(reader);
|
|
||||||
|
|
||||||
if (reader.lastError() == QCborError::NoError)
|
|
||||||
reader.leaveContainer();
|
|
||||||
}
|
|
||||||
#endif // QT_CONFIG(cborstreamreader)
|
#endif // QT_CONFIG(cborstreamreader)
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -2363,6 +2382,8 @@ QCborValueRef QCborValue::operator[](qint64 key)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if QT_CONFIG(cborstreamreader)
|
#if QT_CONFIG(cborstreamreader)
|
||||||
|
enum { MaximumRecursionDepth = 1024 };
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Decodes one item from the CBOR stream found in \a reader and returns the
|
Decodes one item from the CBOR stream found in \a reader and returns the
|
||||||
equivalent representation. This function is recursive: if the item is a map
|
equivalent representation. This function is recursive: if the item is a map
|
||||||
@ -2423,12 +2444,12 @@ QCborValue QCborValue::fromCbor(QCborStreamReader &reader)
|
|||||||
case QCborStreamReader::Map:
|
case QCborStreamReader::Map:
|
||||||
result.n = -1;
|
result.n = -1;
|
||||||
result.t = reader.isArray() ? Array : Map;
|
result.t = reader.isArray() ? Array : Map;
|
||||||
result.container = createContainerFromCbor(reader);
|
result.container = createContainerFromCbor(reader, MaximumRecursionDepth);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// tag
|
// tag
|
||||||
case QCborStreamReader::Tag:
|
case QCborStreamReader::Tag:
|
||||||
result = taggedValueFromCbor(reader);
|
result = taggedValueFromCbor(reader, MaximumRecursionDepth);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -405,9 +405,9 @@ public:
|
|||||||
elements.remove(idx);
|
elements.remove(idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void decodeValueFromCbor(QCborStreamReader &reader);
|
void decodeValueFromCbor(QCborStreamReader &reader, int remainiingStackDepth);
|
||||||
void decodeFromCbor(QCborStreamReader &reader);
|
|
||||||
void decodeStringFromCbor(QCborStreamReader &reader);
|
void decodeStringFromCbor(QCborStreamReader &reader);
|
||||||
|
static inline void setErrorInReader(QCborStreamReader &reader, QCborError error);
|
||||||
};
|
};
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -47,6 +47,8 @@
|
|||||||
#include <QScopedPointer>
|
#include <QScopedPointer>
|
||||||
#include "qiosurfacegraphicsbuffer.h"
|
#include "qiosurfacegraphicsbuffer.h"
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
class QCocoaBackingStore : public QRasterBackingStore
|
class QCocoaBackingStore : public QRasterBackingStore
|
||||||
@ -71,8 +73,9 @@ private:
|
|||||||
void redrawRoundedBottomCorners(CGRect) const;
|
void redrawRoundedBottomCorners(CGRect) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class QCALayerBackingStore : public QCocoaBackingStore
|
class QCALayerBackingStore : public QObject, public QCocoaBackingStore
|
||||||
{
|
{
|
||||||
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
QCALayerBackingStore(QWindow *window);
|
QCALayerBackingStore(QWindow *window);
|
||||||
~QCALayerBackingStore();
|
~QCALayerBackingStore();
|
||||||
@ -119,6 +122,11 @@ private:
|
|||||||
QMacNotificationObserver m_backingPropertiesObserver;
|
QMacNotificationObserver m_backingPropertiesObserver;
|
||||||
|
|
||||||
std::list<std::unique_ptr<GraphicsBuffer>> m_buffers;
|
std::list<std::unique_ptr<GraphicsBuffer>> m_buffers;
|
||||||
|
|
||||||
|
void flushSubWindow(QWindow *window);
|
||||||
|
std::unordered_map<QWindow*, std::unique_ptr<QCALayerBackingStore>> m_subWindowBackingstores;
|
||||||
|
void windowDestroyed(QObject *object);
|
||||||
|
bool m_clearSurfaceOnPaint = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -382,7 +382,7 @@ void QCALayerBackingStore::beginPaint(const QRegion ®ion)
|
|||||||
// Although undocumented, QBackingStore::beginPaint expects the painted region
|
// Although undocumented, QBackingStore::beginPaint expects the painted region
|
||||||
// to be cleared before use if the window has a surface format with an alpha.
|
// to be cleared before use if the window has a surface format with an alpha.
|
||||||
// Fresh IOSurfaces are already cleared, so we don't need to clear those.
|
// Fresh IOSurfaces are already cleared, so we don't need to clear those.
|
||||||
if (!bufferWasRecreated && window()->format().hasAlpha()) {
|
if (m_clearSurfaceOnPaint && !bufferWasRecreated && window()->format().hasAlpha()) {
|
||||||
qCDebug(lcQpaBackingStore) << "Clearing" << region << "before use";
|
qCDebug(lcQpaBackingStore) << "Clearing" << region << "before use";
|
||||||
QPainter painter(m_buffers.back()->asImage());
|
QPainter painter(m_buffers.back()->asImage());
|
||||||
painter.setCompositionMode(QPainter::CompositionMode_Source);
|
painter.setCompositionMode(QPainter::CompositionMode_Source);
|
||||||
@ -511,9 +511,13 @@ void QCALayerBackingStore::flush(QWindow *flushedWindow, const QRegion ®ion,
|
|||||||
if (!prepareForFlush())
|
if (!prepareForFlush())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (flushedWindow != window()) {
|
||||||
|
flushSubWindow(flushedWindow);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QMacAutoReleasePool pool;
|
QMacAutoReleasePool pool;
|
||||||
|
|
||||||
NSView *backingStoreView = static_cast<QCocoaWindow *>(window()->handle())->view();
|
|
||||||
NSView *flushedView = static_cast<QCocoaWindow *>(flushedWindow->handle())->view();
|
NSView *flushedView = static_cast<QCocoaWindow *>(flushedWindow->handle())->view();
|
||||||
|
|
||||||
// If the backingstore is just flushed, without being painted to first, then we may
|
// If the backingstore is just flushed, without being painted to first, then we may
|
||||||
@ -548,7 +552,7 @@ void QCALayerBackingStore::flush(QWindow *flushedWindow, const QRegion ®ion,
|
|||||||
// are committed as part of a display-cycle instead of on the next runloop pass. This
|
// are committed as part of a display-cycle instead of on the next runloop pass. This
|
||||||
// means CA won't try to throttle us if we flush too fast, and we'll coalesce our flush
|
// means CA won't try to throttle us if we flush too fast, and we'll coalesce our flush
|
||||||
// with other pending view and layer updates.
|
// with other pending view and layer updates.
|
||||||
backingStoreView.window.viewsNeedDisplay = YES;
|
flushedView.window.viewsNeedDisplay = YES;
|
||||||
|
|
||||||
if (window()->format().swapBehavior() == QSurfaceFormat::SingleBuffer) {
|
if (window()->format().swapBehavior() == QSurfaceFormat::SingleBuffer) {
|
||||||
// The private API [CALayer reloadValueForKeyPath:@"contents"] would be preferable,
|
// The private API [CALayer reloadValueForKeyPath:@"contents"] would be preferable,
|
||||||
@ -556,28 +560,10 @@ void QCALayerBackingStore::flush(QWindow *flushedWindow, const QRegion ®ion,
|
|||||||
flushedView.layer.contents = nil;
|
flushedView.layer.contents = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flushedView == backingStoreView) {
|
|
||||||
qCInfo(lcQpaBackingStore) << "Flushing" << backBufferSurface
|
qCInfo(lcQpaBackingStore) << "Flushing" << backBufferSurface
|
||||||
<< "to" << flushedView.layer << "of" << flushedView;
|
<< "to" << flushedView.layer << "of" << flushedView;
|
||||||
|
|
||||||
flushedView.layer.contents = backBufferSurface;
|
flushedView.layer.contents = backBufferSurface;
|
||||||
} else {
|
|
||||||
auto subviewRect = [flushedView convertRect:flushedView.bounds toView:backingStoreView];
|
|
||||||
auto scale = flushedView.layer.contentsScale;
|
|
||||||
subviewRect = CGRectApplyAffineTransform(subviewRect, CGAffineTransformMakeScale(scale, scale));
|
|
||||||
|
|
||||||
// We make a copy of the image data up front, which means we don't
|
|
||||||
// need to mark the IOSurface as being in use. FIXME: Investigate
|
|
||||||
// if there's a cheaper way to get sub-image data to a layer.
|
|
||||||
m_buffers.back()->lock(QPlatformGraphicsBuffer::SWReadAccess);
|
|
||||||
QImage subImage = m_buffers.back()->asImage()->copy(QRectF::fromCGRect(subviewRect).toRect());
|
|
||||||
m_buffers.back()->unlock();
|
|
||||||
|
|
||||||
qCInfo(lcQpaBackingStore) << "Flushing" << subImage
|
|
||||||
<< "to" << flushedView.layer << "of subview" << flushedView;
|
|
||||||
QCFType<CGImageRef> cgImage = CGImageCreateCopyWithColorSpace(
|
|
||||||
QCFType<CGImageRef>(subImage.toCGImage()), colorSpace());
|
|
||||||
flushedView.layer.contents = (__bridge id)static_cast<CGImageRef>(cgImage);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Since we may receive multiple flushes before a new frame is started, we do not
|
// 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
|
// swap any buffers just yet. Instead we check in the next beginPaint if the layer's
|
||||||
@ -589,6 +575,53 @@ void QCALayerBackingStore::flush(QWindow *flushedWindow, const QRegion ®ion,
|
|||||||
// the window server.
|
// the window server.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QCALayerBackingStore::flushSubWindow(QWindow *subWindow)
|
||||||
|
{
|
||||||
|
qCInfo(lcQpaBackingStore) << "Flushing sub-window" << subWindow
|
||||||
|
<< "via its own backingstore";
|
||||||
|
|
||||||
|
auto &subWindowBackingStore = m_subWindowBackingstores[subWindow];
|
||||||
|
if (!subWindowBackingStore) {
|
||||||
|
subWindowBackingStore.reset(new QCALayerBackingStore(subWindow));
|
||||||
|
QObject::connect(subWindow, &QObject::destroyed, this, &QCALayerBackingStore::windowDestroyed);
|
||||||
|
subWindowBackingStore->m_clearSurfaceOnPaint = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto subWindowSize = subWindow->size();
|
||||||
|
static const auto kNoStaticContents = QRegion();
|
||||||
|
subWindowBackingStore->resize(subWindowSize, kNoStaticContents);
|
||||||
|
|
||||||
|
auto subWindowLocalRect = QRect(QPoint(), subWindowSize);
|
||||||
|
subWindowBackingStore->beginPaint(subWindowLocalRect);
|
||||||
|
|
||||||
|
QPainter painter(subWindowBackingStore->m_buffers.back()->asImage());
|
||||||
|
painter.setCompositionMode(QPainter::CompositionMode_Source);
|
||||||
|
|
||||||
|
NSView *backingStoreView = static_cast<QCocoaWindow *>(window()->handle())->view();
|
||||||
|
NSView *flushedView = static_cast<QCocoaWindow *>(subWindow->handle())->view();
|
||||||
|
auto subviewRect = [flushedView convertRect:flushedView.bounds toView:backingStoreView];
|
||||||
|
auto scale = flushedView.layer.contentsScale;
|
||||||
|
subviewRect = CGRectApplyAffineTransform(subviewRect, CGAffineTransformMakeScale(scale, scale));
|
||||||
|
|
||||||
|
m_buffers.back()->lock(QPlatformGraphicsBuffer::SWReadAccess);
|
||||||
|
const QImage *backingStoreImage = m_buffers.back()->asImage();
|
||||||
|
painter.drawImage(subWindowLocalRect, *backingStoreImage, QRectF::fromCGRect(subviewRect));
|
||||||
|
m_buffers.back()->unlock();
|
||||||
|
|
||||||
|
painter.end();
|
||||||
|
subWindowBackingStore->endPaint();
|
||||||
|
subWindowBackingStore->flush(subWindow, subWindowLocalRect, QPoint());
|
||||||
|
|
||||||
|
qCInfo(lcQpaBackingStore) << "Done flushing sub-window" << subWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QCALayerBackingStore::windowDestroyed(QObject *object)
|
||||||
|
{
|
||||||
|
auto *window = static_cast<QWindow*>(object);
|
||||||
|
qCInfo(lcQpaBackingStore) << "Removing backingstore for sub-window" << window;
|
||||||
|
m_subWindowBackingstores.erase(window);
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef QT_NO_OPENGL
|
#ifndef QT_NO_OPENGL
|
||||||
void QCALayerBackingStore::composeAndFlush(QWindow *window, const QRegion ®ion, const QPoint &offset,
|
void QCALayerBackingStore::composeAndFlush(QWindow *window, const QRegion ®ion, const QPoint &offset,
|
||||||
QPlatformTextureList *textures, bool translucentBackground)
|
QPlatformTextureList *textures, bool translucentBackground)
|
||||||
@ -722,4 +755,6 @@ QImage *QCALayerBackingStore::GraphicsBuffer::asImage()
|
|||||||
return &m_image;
|
return &m_image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "moc_qcocoabackingstore.cpp"
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -102,6 +102,8 @@ private slots:
|
|||||||
void fromCborStreamReaderIODevice();
|
void fromCborStreamReaderIODevice();
|
||||||
void validation_data();
|
void validation_data();
|
||||||
void validation();
|
void validation();
|
||||||
|
void recursionLimit_data();
|
||||||
|
void recursionLimit();
|
||||||
void toDiagnosticNotation_data();
|
void toDiagnosticNotation_data();
|
||||||
void toDiagnosticNotation();
|
void toDiagnosticNotation();
|
||||||
|
|
||||||
@ -1720,6 +1722,58 @@ void tst_QCborValue::validation()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_QCborValue::recursionLimit_data()
|
||||||
|
{
|
||||||
|
constexpr int RecursionAttempts = 4096;
|
||||||
|
QTest::addColumn<QByteArray>("data");
|
||||||
|
QByteArray arrays(RecursionAttempts, char(0x81));
|
||||||
|
QByteArray _arrays(RecursionAttempts, char(0x9f));
|
||||||
|
QByteArray maps(RecursionAttempts, char(0xa1));
|
||||||
|
QByteArray _maps(RecursionAttempts, char(0xbf));
|
||||||
|
QByteArray tags(RecursionAttempts, char(0xc0));
|
||||||
|
|
||||||
|
QTest::newRow("array-nesting-too-deep") << arrays;
|
||||||
|
QTest::newRow("_array-nesting-too-deep") << _arrays;
|
||||||
|
QTest::newRow("map-nesting-too-deep") << maps;
|
||||||
|
QTest::newRow("_map-nesting-too-deep") << _maps;
|
||||||
|
QTest::newRow("tag-nesting-too-deep") << tags;
|
||||||
|
|
||||||
|
QByteArray mixed(5 * RecursionAttempts, Qt::Uninitialized);
|
||||||
|
char *ptr = mixed.data();
|
||||||
|
for (int i = 0; i < RecursionAttempts; ++i) {
|
||||||
|
quint8 type = qBound(quint8(QCborStreamReader::Array), quint8(i & 0x80), quint8(QCborStreamReader::Tag));
|
||||||
|
quint8 additional_info = i & 0x1f;
|
||||||
|
if (additional_info == 0x1f)
|
||||||
|
(void)additional_info; // leave it
|
||||||
|
else if (additional_info > 0x1a)
|
||||||
|
additional_info = 0x1a;
|
||||||
|
else if (additional_info < 1)
|
||||||
|
additional_info = 1;
|
||||||
|
|
||||||
|
*ptr++ = type | additional_info;
|
||||||
|
if (additional_info == 0x18) {
|
||||||
|
*ptr++ = uchar(i);
|
||||||
|
} else if (additional_info == 0x19) {
|
||||||
|
qToBigEndian(ushort(i), ptr);
|
||||||
|
ptr += 2;
|
||||||
|
} else if (additional_info == 0x1a) {
|
||||||
|
qToBigEndian(uint(i), ptr);
|
||||||
|
ptr += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QTest::newRow("mixed-nesting-too-deep") << mixed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QCborValue::recursionLimit()
|
||||||
|
{
|
||||||
|
QFETCH(QByteArray, data);
|
||||||
|
|
||||||
|
QCborParserError error;
|
||||||
|
QCborValue decoded = QCborValue::fromCbor(data, &error);
|
||||||
|
QCOMPARE(error.error, QCborError::NestingTooDeep);
|
||||||
|
}
|
||||||
|
|
||||||
void tst_QCborValue::toDiagnosticNotation_data()
|
void tst_QCborValue::toDiagnosticNotation_data()
|
||||||
{
|
{
|
||||||
QTest::addColumn<QCborValue>("v");
|
QTest::addColumn<QCborValue>("v");
|
||||||
|
Loading…
Reference in New Issue
Block a user