Merge "Merge remote-tracking branch 'origin/5.15' into dev"

bb10
Qt Forward Merge Bot 2019-11-29 01:01:07 +01:00
commit 3de89e57c9
44 changed files with 938 additions and 410 deletions

View File

@ -28,6 +28,7 @@ EMTERP_FLAGS = \
EMCC_COMMON_LFLAGS = \
-s WASM=1 \
-s FULL_ES2=1 \
-s FULL_ES3=1 \
-s USE_WEBGL2=1 \
-s NO_EXIT_RUNTIME=0 \
-s ERROR_ON_UNDEFINED_SYMBOLS=1 \

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@ -189,6 +189,9 @@ QT_BEGIN_NAMESPACE
\value Unicode_8_0 Version 8.0 Since Qt 5.6
\value Unicode_9_0 Version 9.0 Since Qt 5.11
\value Unicode_10_0 Version 10.0 Since Qt 5.11
\value Unicode_11_0 Version 11.0 Since Qt 5.15
\value Unicode_12_0 Version 12.0 Since Qt 5.15
\value Unicode_12_1 Version 12.1 Since Qt 5.15
\value Unicode_Unassigned The value is not assigned to any character
in version 8.0 of Unicode.
@ -288,145 +291,156 @@ QT_BEGIN_NAMESPACE
\value Script_Common For characters that may be used with multiple scripts
and that do not inherit their script from the preceding characters.
\value Script_Latin
\value Script_Greek
\value Script_Cyrillic
\value Script_Armenian
\value Script_Hebrew
\value Script_Adlam Since Qt 5.11
\value Script_Ahom Since Qt 5.6
\value Script_AnatolianHieroglyphs Since Qt 5.6
\value Script_Arabic
\value Script_Syriac
\value Script_Thaana
\value Script_Devanagari
\value Script_Armenian
\value Script_Avestan
\value Script_Balinese
\value Script_Bamum
\value Script_BassaVah Since Qt 5.5
\value Script_Batak
\value Script_Bengali
\value Script_Gurmukhi
\value Script_Gujarati
\value Script_Oriya
\value Script_Tamil
\value Script_Telugu
\value Script_Kannada
\value Script_Malayalam
\value Script_Sinhala
\value Script_Thai
\value Script_Lao
\value Script_Tibetan
\value Script_Myanmar
\value Script_Georgian
\value Script_Hangul
\value Script_Ethiopic
\value Script_Cherokee
\value Script_CanadianAboriginal
\value Script_Ogham
\value Script_Runic
\value Script_Khmer
\value Script_Mongolian
\value Script_Hiragana
\value Script_Katakana
\value Script_Bhaiksuki Since Qt 5.11
\value Script_Bopomofo
\value Script_Han
\value Script_Yi
\value Script_OldItalic
\value Script_Gothic
\value Script_Deseret
\value Script_Tagalog
\value Script_Hanunoo
\value Script_Buhid
\value Script_Tagbanwa
\value Script_Coptic
\value Script_Limbu
\value Script_TaiLe
\value Script_LinearB
\value Script_Ugaritic
\value Script_Shavian
\value Script_Osmanya
\value Script_Cypriot
\value Script_Brahmi
\value Script_Braille
\value Script_Buginese
\value Script_NewTaiLue
\value Script_Glagolitic
\value Script_Tifinagh
\value Script_SylotiNagri
\value Script_OldPersian
\value Script_Kharoshthi
\value Script_Balinese
\value Script_Cuneiform
\value Script_Phoenician
\value Script_PhagsPa
\value Script_Nko
\value Script_Sundanese
\value Script_Lepcha
\value Script_OlChiki
\value Script_Vai
\value Script_Saurashtra
\value Script_KayahLi
\value Script_Rejang
\value Script_Lycian
\value Script_Buhid
\value Script_CanadianAboriginal
\value Script_Carian
\value Script_Lydian
\value Script_Cham
\value Script_TaiTham
\value Script_TaiViet
\value Script_Avestan
\value Script_EgyptianHieroglyphs
\value Script_Samaritan
\value Script_Lisu
\value Script_Bamum
\value Script_Javanese
\value Script_MeeteiMayek
\value Script_ImperialAramaic
\value Script_OldSouthArabian
\value Script_InscriptionalParthian
\value Script_InscriptionalPahlavi
\value Script_OldTurkic
\value Script_Kaithi
\value Script_Batak
\value Script_Brahmi
\value Script_Mandaic
\value Script_CaucasianAlbanian Since Qt 5.5
\value Script_Chakma
\value Script_Cham
\value Script_Cherokee
\value Script_Coptic
\value Script_Cuneiform
\value Script_Cypriot
\value Script_Cyrillic
\value Script_Deseret
\value Script_Devanagari
\value Script_Dogra Since Qt 5.15
\value Script_Duployan Since Qt 5.5
\value Script_EgyptianHieroglyphs
\value Script_Elbasan Since Qt 5.5
\value Script_Elymaic Since Qt 5.15
\value Script_Ethiopic
\value Script_Georgian
\value Script_Glagolitic
\value Script_Gothic
\value Script_Grantha Since Qt 5.5
\value Script_Greek
\value Script_Gujarati
\value Script_GunjalaGondi Since Qt 5.15
\value Script_Gurmukhi
\value Script_Han
\value Script_Hangul
\value Script_HanifiRohingya Since Qt 5.15
\value Script_Hanunoo
\value Script_Hatran Since Qt 5.6
\value Script_Hebrew
\value Script_Hiragana
\value Script_ImperialAramaic
\value Script_InscriptionalPahlavi
\value Script_InscriptionalParthian
\value Script_Javanese
\value Script_Kaithi
\value Script_Kannada
\value Script_Katakana
\value Script_KayahLi
\value Script_Kharoshthi
\value Script_Khmer
\value Script_Khojki Since Qt 5.5
\value Script_Khudawadi Since Qt 5.5
\value Script_Lao
\value Script_Latin
\value Script_Lepcha
\value Script_Limbu
\value Script_LinearA Since Qt 5.5
\value Script_LinearB
\value Script_Lisu
\value Script_Lycian
\value Script_Lydian
\value Script_Mahajani Since Qt 5.5
\value Script_Makasar Since Qt 5.15
\value Script_Malayalam
\value Script_Mandaic
\value Script_Manichaean Since Qt 5.5
\value Script_Marchen Since Qt 5.11
\value Script_MasaramGondi Since Qt 5.11
\value Script_Medefaidrin Since Qt 5.15
\value Script_MeeteiMayek
\value Script_MendeKikakui Since Qt 5.5
\value Script_MeroiticCursive
\value Script_MeroiticHieroglyphs
\value Script_Miao
\value Script_Modi Since Qt 5.5
\value Script_Mongolian
\value Script_Mro Since Qt 5.5
\value Script_Multani Since Qt 5.6
\value Script_Myanmar
\value Script_Nabataean Since Qt 5.5
\value Script_Nandinagari Since Qt 5.15
\value Script_Newa Since Qt 5.11
\value Script_NewTaiLue
\value Script_Nko
\value Script_Nushu Since Qt 5.11
\value Script_NyiakengPuachueHmong Since Qt 5.15
\value Script_Ogham
\value Script_OlChiki
\value Script_OldHungarian Since Qt 5.6
\value Script_OldItalic
\value Script_OldNorthArabian Since Qt 5.5
\value Script_OldPermic Since Qt 5.5
\value Script_OldPersian
\value Script_OldSogdian Since Qt 5.15
\value Script_OldSouthArabian
\value Script_OldTurkic
\value Script_Oriya
\value Script_Osage Since Qt 5.11
\value Script_Osmanya
\value Script_PahawhHmong Since Qt 5.5
\value Script_Palmyrene Since Qt 5.5
\value Script_PauCinHau Since Qt 5.5
\value Script_PhagsPa
\value Script_Phoenician
\value Script_PsalterPahlavi Since Qt 5.5
\value Script_Rejang
\value Script_Runic
\value Script_Samaritan
\value Script_Saurashtra
\value Script_Sharada
\value Script_Shavian
\value Script_Siddham Since Qt 5.5
\value Script_SignWriting Since Qt 5.6
\value Script_Sinhala
\value Script_Sogdian Since Qt 5.15
\value Script_SoraSompeng
\value Script_Soyombo Since Qt 5.11
\value Script_Sundaneseo
\value Script_SylotiNagri
\value Script_Syriac
\value Script_Tagalog
\value Script_Tagbanwa
\value Script_TaiLe
\value Script_TaiTham
\value Script_TaiViet
\value Script_Takri
\value Script_CaucasianAlbanian
\value Script_BassaVah
\value Script_Duployan
\value Script_Elbasan
\value Script_Grantha
\value Script_PahawhHmong
\value Script_Khojki
\value Script_LinearA
\value Script_Mahajani
\value Script_Manichaean
\value Script_MendeKikakui
\value Script_Modi
\value Script_Mro
\value Script_OldNorthArabian
\value Script_Nabataean
\value Script_Palmyrene
\value Script_PauCinHau
\value Script_OldPermic
\value Script_PsalterPahlavi
\value Script_Siddham
\value Script_Khudawadi
\value Script_Tirhuta
\value Script_WarangCiti
\value Script_Ahom
\value Script_AnatolianHieroglyphs
\value Script_Hatran
\value Script_Multani
\value Script_OldHungarian
\value Script_SignWriting
\value Script_Adlam
\value Script_Bhaiksuki
\value Script_Marchen
\value Script_Newa
\value Script_Osage
\value Script_Tangut
\value Script_MasaramGondi
\value Script_Nushu
\value Script_Soyombo
\value Script_ZanabazarSquare
\value Script_Tamil
\value Script_Tangut Since Qt 5.11
\value Script_Telugu
\value Script_Thaana
\value Script_Thai
\value Script_Tibetan
\value Script_Tifinagh
\value Script_Tirhuta Since Qt 5.5
\value Script_Ugaritic
\value Script_Vai
\value Script_Wancho Since Qt 5.15
\value Script_WarangCiti Since Qt 5.5
\value Script_Yi
\value Script_ZanabazarSquare Since Qt 5.11
\omitvalue ScriptCount

View File

@ -437,7 +437,7 @@ public:
Unicode_10_0,
Unicode_11_0,
Unicode_12_0,
Unicode_12_1,
Unicode_12_1
};
// ****** WHEN ADDING FUNCTIONS, CONSIDER ADDING TO QCharRef TOO

View File

@ -122,7 +122,8 @@ enum GraphemeBreakClass {
Graphemebreak_E_Modifier,
Graphemebreak_Glue_After_Zwj,
Graphemebreak_E_Base_GAZ,
NumGraphemeBreakClasses,
NumGraphemeBreakClasses
};
enum WordBreakClass {
@ -149,7 +150,8 @@ enum WordBreakClass {
WordBreak_Glue_After_Zwj,
WordBreak_E_Base_GAZ,
WordBreak_WSegSpace,
NumWordBreakClasses,
NumWordBreakClasses
};
enum SentenceBreakClass {
@ -167,6 +169,7 @@ enum SentenceBreakClass {
SentenceBreak_SContinue,
SentenceBreak_STerm,
SentenceBreak_Close,
NumSentenceBreakClasses
};
@ -182,6 +185,7 @@ enum LineBreakClass {
LineBreak_EB, LineBreak_EM, LineBreak_ZWJ,
LineBreak_SA, LineBreak_SG, LineBreak_SP,
LineBreak_CR, LineBreak_LF, LineBreak_BK,
NumLineBreakClasses
};

View File

@ -1315,7 +1315,7 @@
},
"opengles3": {
"label": "OpenGL ES 3.0",
"condition": "features.opengles2 && !features.angle && tests.opengles3 && !config.wasm",
"condition": "features.opengles2 && !features.angle && tests.opengles3",
"output": [
"publicFeature",
{ "type": "define", "name": "QT_OPENGL_ES_3" }

View File

@ -45,13 +45,13 @@
#include "qvector.h"
#include "qcoreapplication.h"
#include <private/qkeymapper_p.h>
#include <QtCore/qloggingcategory.h>
#include <algorithm>
QT_BEGIN_NAMESPACE
// To enable verbose output uncomment below
//#define DEBUG_QSHORTCUTMAP
Q_LOGGING_CATEGORY(lcShortcutMap, "qt.gui.shortcutmap")
/* \internal
Entry data for QShortcutMap
@ -163,11 +163,9 @@ int QShortcutMap::addShortcut(QObject *owner, const QKeySequence &key, Qt::Short
QShortcutEntry newEntry(owner, key, context, --(d->currentId), true, matcher);
const auto it = std::upper_bound(d->sequences.begin(), d->sequences.end(), newEntry);
d->sequences.insert(it, newEntry); // Insert sorted
#if defined(DEBUG_QSHORTCUTMAP)
qDebug().nospace()
qCDebug(lcShortcutMap).nospace()
<< "QShortcutMap::addShortcut(" << owner << ", "
<< key << ", " << context << ") = " << d->currentId;
#endif
return d->currentId;
}
@ -210,11 +208,9 @@ int QShortcutMap::removeShortcut(int id, QObject *owner, const QKeySequence &key
return itemsRemoved;
--i;
}
#if defined(DEBUG_QSHORTCUTMAP)
qDebug().nospace()
qCDebug(lcShortcutMap).nospace()
<< "QShortcutMap::removeShortcut(" << id << ", " << owner << ", "
<< key << ") = " << itemsRemoved;
#endif
return itemsRemoved;
}
@ -248,11 +244,9 @@ int QShortcutMap::setShortcutEnabled(bool enable, int id, QObject *owner, const
return itemsChanged;
--i;
}
#if defined(DEBUG_QSHORTCUTMAP)
qDebug().nospace()
qCDebug(lcShortcutMap).nospace()
<< "QShortcutMap::setShortcutEnabled(" << enable << ", " << id << ", "
<< owner << ", " << key << ") = " << itemsChanged;
#endif
return itemsChanged;
}
@ -286,11 +280,9 @@ int QShortcutMap::setShortcutAutoRepeat(bool on, int id, QObject *owner, const Q
return itemsChanged;
--i;
}
#if defined(DEBUG_QSHORTCUTMAP)
qDebug().nospace()
qCDebug(lcShortcutMap).nospace()
<< "QShortcutMap::setShortcutAutoRepeat(" << on << ", " << id << ", "
<< owner << ", " << key << ") = " << itemsChanged;
#endif
return itemsChanged;
}
@ -393,9 +385,7 @@ QKeySequence::SequenceMatch QShortcutMap::nextState(QKeyEvent *e)
clearSequence(d->currentSequences);
d->currentState = result;
#if defined(DEBUG_QSHORTCUTMAP)
qDebug().nospace() << "QShortcutMap::nextState(" << e << ") = " << result;
#endif
qCDebug(lcShortcutMap).nospace() << "QShortcutMap::nextState(" << e << ") = " << result;
return result;
}
@ -434,9 +424,7 @@ QKeySequence::SequenceMatch QShortcutMap::find(QKeyEvent *e, int ignoredModifier
return QKeySequence::NoMatch;
createNewSequences(e, d->newEntries, ignoredModifiers);
#if defined(DEBUG_QSHORTCUTMAP)
qDebug() << "Possible shortcut key sequences:" << d->newEntries;
#endif
qCDebug(lcShortcutMap) << "Possible shortcut key sequences:" << d->newEntries;
// Should never happen
if (d->newEntries == d->currentSequences) {
@ -489,15 +477,11 @@ QKeySequence::SequenceMatch QShortcutMap::find(QKeyEvent *e, int ignoredModifier
// previous list. If this match is equal or better than the last match, append to the list
if (oneKSResult > result) {
okEntries.clear();
#if defined(DEBUG_QSHORTCUTMAP)
qDebug() << "Found better match (" << d->newEntries << "), clearing key sequence list";
#endif
qCDebug(lcShortcutMap) << "Found better match (" << d->newEntries << "), clearing key sequence list";
}
if (oneKSResult && oneKSResult >= result) {
okEntries << d->newEntries.at(i);
#if defined(DEBUG_QSHORTCUTMAP)
qDebug() << "Added ok key sequence" << d->newEntries;
#endif
qCDebug(lcShortcutMap) << "Added ok key sequence" << d->newEntries;
}
}
@ -513,9 +497,7 @@ QKeySequence::SequenceMatch QShortcutMap::find(QKeyEvent *e, int ignoredModifier
}
if (result != QKeySequence::NoMatch)
d->currentSequences = okEntries;
#if defined(DEBUG_QSHORTCUTMAP)
qDebug() << "Returning shortcut match == " << result;
#endif
qCDebug(lcShortcutMap) << "Returning shortcut match == " << result;
return QKeySequence::SequenceMatch(result);
}
@ -538,19 +520,16 @@ void QShortcutMap::createNewSequences(QKeyEvent *e, QVector<QKeySequence> &ksl,
{
Q_D(QShortcutMap);
QList<int> possibleKeys = QKeyMapper::possibleKeys(e);
#if defined(DEBUG_QSHORTCUTMAP)
{
QDebug debug = qDebug().nospace();
debug << __FUNCTION__ << '(' << e << ", ignoredModifiers="
if (lcShortcutMap().isDebugEnabled()) {
qCDebug(lcShortcutMap).nospace() << __FUNCTION__ << '(' << e << ", ignoredModifiers="
<< Qt::KeyboardModifiers(ignoredModifiers) << "), possibleKeys=(";
for (int i = 0, size = possibleKeys.size(); i < size; ++i) {
if (i)
debug << ", ";
debug << QKeySequence(possibleKeys.at(i));
qCDebug(lcShortcutMap).nospace() << ", ";
qCDebug(lcShortcutMap).nospace() << QKeySequence(possibleKeys.at(i));
}
debug << ')';
qCDebug(lcShortcutMap).nospace() << ')';
}
#endif // DEBUG_QSHORTCUTMAP
int pkTotal = possibleKeys.count();
if (!pkTotal)
return;
@ -659,16 +638,13 @@ void QShortcutMap::dispatchEvent(QKeyEvent *e)
// Find next
const QShortcutEntry *current = 0, *next = 0;
int i = 0, enabledShortcuts = 0;
#if defined(DEBUG_QSHORTCUTMAP)
QVector<const QShortcutEntry*> ambiguousShortcuts;
#endif
while(i < d->identicals.size()) {
current = d->identicals.at(i);
if (current->enabled || !next){
++enabledShortcuts;
#if defined(DEBUG_QSHORTCUTMAP)
ambiguousShortcuts.append(current);
#endif
if (lcShortcutMap().isDebugEnabled())
ambiguousShortcuts.append(current);
if (enabledShortcuts > d->ambigCount + 1)
break;
next = current;
@ -681,19 +657,18 @@ void QShortcutMap::dispatchEvent(QKeyEvent *e)
if (!next || (e->isAutoRepeat() && !next->autorepeat))
return;
// Dispatch next enabled
#if defined(DEBUG_QSHORTCUTMAP)
if (ambiguousShortcuts.size() > 1) {
qDebug() << "The following shortcuts are about to be activated ambiguously:";
for (const QShortcutEntry *entry : qAsConst(ambiguousShortcuts)) {
qDebug().nospace() << "- " << entry->keyseq << " (belonging to " << entry->owner << ")";
if (lcShortcutMap().isDebugEnabled()) {
if (ambiguousShortcuts.size() > 1) {
qCDebug(lcShortcutMap) << "The following shortcuts are about to be activated ambiguously:";
for (const QShortcutEntry *entry : qAsConst(ambiguousShortcuts))
qCDebug(lcShortcutMap).nospace() << "- " << entry->keyseq << " (belonging to " << entry->owner << ")";
}
}
qDebug().nospace()
<< "QShortcutMap::dispatchEvent(): Sending QShortcutEvent(\""
<< next->keyseq.toString() << "\", " << next->id << ", "
<< (bool)(enabledShortcuts>1) << ") to object(" << next->owner << ')';
#endif
qCDebug(lcShortcutMap).nospace()
<< "QShortcutMap::dispatchEvent(): Sending QShortcutEvent(\""
<< next->keyseq.toString() << "\", " << next->id << ", "
<< static_cast<bool>(enabledShortcuts>1) << ") to object(" << next->owner << ')';
}
QShortcutEvent se(next->keyseq, next->id, enabledShortcuts>1);
QCoreApplication::sendEvent(const_cast<QObject *>(next->owner), &se);
}

View File

@ -48,8 +48,7 @@
#ifdef Q_OS_WIN
#include "qrhid3d11_p_p.h"
#endif
//#ifdef Q_OS_DARWIN
#ifdef Q_OS_MACOS
#if defined(Q_OS_MACOS) || defined(Q_OS_IOS)
#include "qrhimetal_p_p.h"
#endif
@ -2253,9 +2252,7 @@ bool QRhiTexture::buildFrom(const QRhiNativeHandles *src)
\value Repeat
\value ClampToEdge
\value Border
\value Mirror
\value MirrorOnce
*/
/*!
@ -2321,6 +2318,24 @@ QRhiResource::Type QRhiRenderPassDescriptor::resourceType() const
return RenderPassDescriptor;
}
/*!
\fn bool QRhiRenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *other) const;
\return true if the \a other QRhiRenderPassDescriptor is compatible with
this one, meaning \c this and \a other can be used interchangebly in
QRhiGraphicsPipeline::setRenderPassDescriptor().
The concept of the compatibility of renderpass descriptors is similar to
the \l{QRhiShaderResourceBindings::isLayoutCompatible}{layout
compatibility} of QRhiShaderResourceBindings instances. They allow better
reuse of QRhiGraphicsPipeline instances: for example, a
QRhiGraphicsPipeline instance cache is expected to use these functions to
look for a matching pipeline, instead of just comparing pointers, thus
allowing a different QRhiRenderPassDescriptor and
QRhiShaderResourceBindings to be used in combination with the pipeline, as
long as they are compatible.
*/
/*!
\return a pointer to a backend-specific QRhiNativeHandles subclass, such as
QRhiVulkanRenderPassNativeHandles. The returned value is null when exposing
@ -4049,8 +4064,7 @@ QRhi *QRhi::create(Implementation impl, QRhiInitParams *params, Flags flags, QRh
break;
#endif
case Metal:
//#ifdef Q_OS_DARWIN
#ifdef Q_OS_MACOS
#if defined(Q_OS_MACOS) || defined(Q_OS_IOS)
r->d = new QRhiMetal(static_cast<QRhiMetalInitParams *>(params),
static_cast<QRhiMetalNativeHandles *>(importDevice));
break;

View File

@ -812,9 +812,7 @@ public:
enum AddressMode {
Repeat,
ClampToEdge,
Border,
Mirror,
MirrorOnce
};
enum CompareOp {
@ -913,6 +911,7 @@ class Q_GUI_EXPORT QRhiRenderPassDescriptor : public QRhiResource
public:
QRhiResource::Type resourceType() const override;
virtual bool isCompatible(const QRhiRenderPassDescriptor *other) const = 0;
virtual const QRhiNativeHandles *nativeHandles();
protected:

View File

@ -2862,12 +2862,8 @@ static inline D3D11_TEXTURE_ADDRESS_MODE toD3DAddressMode(QRhiSampler::AddressMo
return D3D11_TEXTURE_ADDRESS_WRAP;
case QRhiSampler::ClampToEdge:
return D3D11_TEXTURE_ADDRESS_CLAMP;
case QRhiSampler::Border:
return D3D11_TEXTURE_ADDRESS_BORDER;
case QRhiSampler::Mirror:
return D3D11_TEXTURE_ADDRESS_MIRROR;
case QRhiSampler::MirrorOnce:
return D3D11_TEXTURE_ADDRESS_MIRROR_ONCE;
default:
Q_UNREACHABLE();
return D3D11_TEXTURE_ADDRESS_CLAMP;
@ -2944,6 +2940,12 @@ void QD3D11RenderPassDescriptor::release()
// nothing to do here
}
bool QD3D11RenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *other) const
{
Q_UNUSED(other);
return true;
}
QD3D11ReferenceRenderTarget::QD3D11ReferenceRenderTarget(QRhiImplementation *rhi)
: QRhiRenderTarget(rhi),
d(rhi)

View File

@ -136,6 +136,7 @@ struct QD3D11RenderPassDescriptor : public QRhiRenderPassDescriptor
QD3D11RenderPassDescriptor(QRhiImplementation *rhi);
~QD3D11RenderPassDescriptor();
void release() override;
bool isCompatible(const QRhiRenderPassDescriptor *other) const override;
};
struct QD3D11RenderTargetData

View File

@ -1785,11 +1785,6 @@ static inline GLenum toGlWrapMode(QRhiSampler::AddressMode m)
return GL_CLAMP_TO_EDGE;
case QRhiSampler::Mirror:
return GL_MIRRORED_REPEAT;
case QRhiSampler::MirrorOnce:
Q_FALLTHROUGH();
case QRhiSampler::Border:
qWarning("Unsupported wrap mode %d", m);
return GL_CLAMP_TO_EDGE;
default:
Q_UNREACHABLE();
return GL_CLAMP_TO_EDGE;
@ -3460,6 +3455,12 @@ void QGles2RenderPassDescriptor::release()
// nothing to do here
}
bool QGles2RenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *other) const
{
Q_UNUSED(other);
return true;
}
QGles2ReferenceRenderTarget::QGles2ReferenceRenderTarget(QRhiImplementation *rhi)
: QRhiRenderTarget(rhi),
d(rhi)

View File

@ -185,6 +185,7 @@ struct QGles2RenderPassDescriptor : public QRhiRenderPassDescriptor
QGles2RenderPassDescriptor(QRhiImplementation *rhi);
~QGles2RenderPassDescriptor();
void release() override;
bool isCompatible(const QRhiRenderPassDescriptor *other) const override;
};
struct QGles2RenderTargetData

View File

@ -41,6 +41,8 @@
#ifdef Q_OS_MACOS
#include <AppKit/AppKit.h>
#else
#include <UIKit/UIKit.h>
#endif
#include <Metal/Metal.h>
@ -318,7 +320,13 @@ struct QMetalComputePipelineData
struct QMetalSwapChainData
{
// The iOS simulator's headers mark CAMetalLayer as iOS 13.0+ only.
// (for real device SDKs it is 8.0+)
#ifdef TARGET_IPHONE_SIMULATOR
API_AVAILABLE(ios(13.0)) CAMetalLayer *layer = nullptr;
#else
CAMetalLayer *layer = nullptr;
#endif
id<CAMetalDrawable> curDrawable;
dispatch_semaphore_t sem[QMTL_FRAMES_IN_FLIGHT];
MTLRenderPassDescriptor *rp = nullptr;
@ -1763,8 +1771,10 @@ void QRhiMetal::executeBufferHostWritesForCurrentFrame(QMetalBuffer *bufD)
if (changeEnd == -1 || u.offset + u.data.size() > changeEnd)
changeEnd = u.offset + u.data.size();
}
#ifdef Q_OS_MACOS
if (changeBegin >= 0 && bufD->d->managed)
[bufD->d->buf[idx] didModifyRange: NSMakeRange(NSUInteger(changeBegin), NSUInteger(changeEnd - changeBegin))];
#endif
bufD->d->pendingUpdates[idx].clear();
}
@ -1798,8 +1808,12 @@ void QRhiMetal::beginPass(QRhiCommandBuffer *cb,
if (color0.needsDrawableForTex || color0.needsDrawableForResolveTex) {
Q_ASSERT(currentSwapChain);
QMetalSwapChain *swapChainD = QRHI_RES(QMetalSwapChain, currentSwapChain);
if (!swapChainD->d->curDrawable)
swapChainD->d->curDrawable = [swapChainD->d->layer nextDrawable];
if (!swapChainD->d->curDrawable) {
#ifdef TARGET_IPHONE_SIMULATOR
if (@available(ios 13.0, *))
#endif
swapChainD->d->curDrawable = [swapChainD->d->layer nextDrawable];
}
if (!swapChainD->d->curDrawable) {
qWarning("No drawable");
return;
@ -2170,12 +2184,13 @@ bool QMetalRenderBuffer::build()
case DepthStencil:
#ifdef Q_OS_MACOS
desc.storageMode = MTLStorageModePrivate;
#else
desc.storageMode = MTLResourceStorageModeMemoryless;
transientBacking = true;
#endif
d->format = rhiD->d->dev.depth24Stencil8PixelFormatSupported
? MTLPixelFormatDepth24Unorm_Stencil8 : MTLPixelFormatDepth32Float_Stencil8;
#else
desc.storageMode = MTLStorageModeMemoryless;
transientBacking = true;
d->format = MTLPixelFormatDepth32Float_Stencil8;
#endif
desc.pixelFormat = d->format;
break;
case Color:
@ -2569,12 +2584,8 @@ static inline MTLSamplerAddressMode toMetalAddressMode(QRhiSampler::AddressMode
return MTLSamplerAddressModeRepeat;
case QRhiSampler::ClampToEdge:
return MTLSamplerAddressModeClampToEdge;
case QRhiSampler::Border:
return MTLSamplerAddressModeClampToBorderColor;
case QRhiSampler::Mirror:
return MTLSamplerAddressModeMirrorRepeat;
case QRhiSampler::MirrorOnce:
return MTLSamplerAddressModeMirrorClampToEdge;
default:
Q_UNREACHABLE();
return MTLSamplerAddressModeClampToEdge;
@ -2647,6 +2658,32 @@ void QMetalRenderPassDescriptor::release()
// nothing to do here
}
bool QMetalRenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *other) const
{
if (!other)
return false;
const QMetalRenderPassDescriptor *o = QRHI_RES(const QMetalRenderPassDescriptor, other);
if (colorAttachmentCount != o->colorAttachmentCount)
return false;
if (hasDepthStencil != o->hasDepthStencil)
return false;
for (int i = 0; i < colorAttachmentCount; ++i) {
if (colorFormat[i] != o->colorFormat[i])
return false;
}
if (hasDepthStencil) {
if (dsFormat != o->dsFormat)
return false;
}
return true;
}
QMetalReferenceRenderTarget::QMetalReferenceRenderTarget(QRhiImplementation *rhi)
: QRhiRenderTarget(rhi),
d(new QMetalRenderTargetData)
@ -3311,7 +3348,11 @@ bool QMetalGraphicsPipeline::build()
// validation blows up otherwise.
MTLPixelFormat fmt = MTLPixelFormat(rpD->dsFormat);
rpDesc.depthAttachmentPixelFormat = fmt;
#ifdef Q_OS_MACOS
if (fmt != MTLPixelFormatDepth16Unorm && fmt != MTLPixelFormatDepth32Float)
#else
if (fmt != MTLPixelFormatDepth32Float)
#endif
rpDesc.stencilAttachmentPixelFormat = fmt;
}
@ -3528,6 +3569,10 @@ QMetalSwapChain::~QMetalSwapChain()
void QMetalSwapChain::release()
{
#ifdef TARGET_IPHONE_SIMULATOR
if (@available(ios 13.0, *)) {
#endif
if (!d->layer)
return;
@ -3556,6 +3601,10 @@ void QMetalSwapChain::release()
QRHI_PROF_F(releaseSwapChain(this));
rhiD->unregisterResource(this);
#ifdef TARGET_IPHONE_SIMULATOR
}
#endif
}
QRhiCommandBuffer *QMetalSwapChain::currentFrameCommandBuffer()
@ -3578,16 +3627,20 @@ QRhiRenderPassDescriptor *QMetalSwapChain::newCompatibleRenderPassDescriptor()
{
chooseFormats(); // ensure colorFormat and similar are filled out
QRHI_RES_RHI(QRhiMetal);
QMetalRenderPassDescriptor *rpD = new QMetalRenderPassDescriptor(m_rhi);
rpD->colorAttachmentCount = 1;
rpD->hasDepthStencil = m_depthStencil != nullptr;
rpD->colorFormat[0] = int(d->colorFormat);
#ifdef Q_OS_MACOS
// m_depthStencil may not be built yet so cannot rely on computed fields in it
QRHI_RES_RHI(QRhiMetal);
rpD->dsFormat = rhiD->d->dev.depth24Stencil8PixelFormatSupported
? MTLPixelFormatDepth24Unorm_Stencil8 : MTLPixelFormatDepth32Float_Stencil8;
#else
rpD->dsFormat = MTLPixelFormatDepth32Float_Stencil8;
#endif
return rpD;
}
@ -3603,6 +3656,10 @@ void QMetalSwapChain::chooseFormats()
bool QMetalSwapChain::buildOrResize()
{
#ifdef TARGET_IPHONE_SIMULATOR
if (@available(ios 13.0, *)) {
#endif
Q_ASSERT(m_window);
const bool needsRegistration = !window || window != m_window;
@ -3622,7 +3679,11 @@ bool QMetalSwapChain::buildOrResize()
return false;
}
#ifdef Q_OS_MACOS
NSView *view = reinterpret_cast<NSView *>(window->winId());
#else
UIView *view = reinterpret_cast<UIView *>(window->winId());
#endif
Q_ASSERT(view);
d->layer = static_cast<CAMetalLayer *>(view.layer);
Q_ASSERT(d->layer);
@ -3726,6 +3787,15 @@ bool QMetalSwapChain::buildOrResize()
rhiD->registerResource(this);
return true;
#ifdef TARGET_IPHONE_SIMULATOR
} else {
// Won't ever get here in a normal app because MTLDevice creation would
// fail too. Print a warning, just in case.
qWarning("No CAMetalLayer support in this version of the iOS Simulator");
return false;
}
#endif
}
QT_END_NAMESPACE

View File

@ -138,6 +138,7 @@ struct QMetalRenderPassDescriptor : public QRhiRenderPassDescriptor
QMetalRenderPassDescriptor(QRhiImplementation *rhi);
~QMetalRenderPassDescriptor();
void release() override;
bool isCompatible(const QRhiRenderPassDescriptor *other) const override;
// there is no MTLRenderPassDescriptor here as one will be created for each pass in beginPass()

View File

@ -690,6 +690,12 @@ void QNullRenderPassDescriptor::release()
{
}
bool QNullRenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *other) const
{
Q_UNUSED(other);
return true;
}
QNullReferenceRenderTarget::QNullReferenceRenderTarget(QRhiImplementation *rhi)
: QRhiRenderTarget(rhi),
d(rhi)

View File

@ -101,6 +101,7 @@ struct QNullRenderPassDescriptor : public QRhiRenderPassDescriptor
QNullRenderPassDescriptor(QRhiImplementation *rhi);
~QNullRenderPassDescriptor();
void release() override;
bool isCompatible(const QRhiRenderPassDescriptor *other) const override;
};
struct QNullRenderTargetData

View File

@ -1032,54 +1032,62 @@ VkFormat QRhiVulkan::optimalDepthStencilFormat()
return optimalDsFormat;
}
bool QRhiVulkan::createDefaultRenderPass(VkRenderPass *rp, bool hasDepthStencil, VkSampleCountFlagBits samples, VkFormat colorFormat)
bool QRhiVulkan::createDefaultRenderPass(QVkRenderPassDescriptor *rpD, bool hasDepthStencil, VkSampleCountFlagBits samples, VkFormat colorFormat)
{
VkAttachmentDescription attDesc[3];
memset(attDesc, 0, sizeof(attDesc));
// attachment list layout is color (1), ds (0-1), resolve (0-1)
attDesc[0].format = colorFormat;
attDesc[0].samples = samples;
attDesc[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
attDesc[0].storeOp = samples > VK_SAMPLE_COUNT_1_BIT ? VK_ATTACHMENT_STORE_OP_DONT_CARE : VK_ATTACHMENT_STORE_OP_STORE;
attDesc[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attDesc[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attDesc[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attDesc[0].finalLayout = samples > VK_SAMPLE_COUNT_1_BIT ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
VkAttachmentDescription attDesc;
memset(&attDesc, 0, sizeof(attDesc));
attDesc.format = colorFormat;
attDesc.samples = samples;
attDesc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
attDesc.storeOp = samples > VK_SAMPLE_COUNT_1_BIT ? VK_ATTACHMENT_STORE_OP_DONT_CARE : VK_ATTACHMENT_STORE_OP_STORE;
attDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attDesc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attDesc.finalLayout = samples > VK_SAMPLE_COUNT_1_BIT ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
rpD->attDescs.append(attDesc);
// clear on load + no store + lazy alloc + transient image should play
// nicely with tiled GPUs (no physical backing necessary for ds buffer)
attDesc[1].format = optimalDepthStencilFormat();
attDesc[1].samples = samples;
attDesc[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
attDesc[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attDesc[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
attDesc[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attDesc[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attDesc[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
rpD->colorRefs.append({ 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL });
if (samples > VK_SAMPLE_COUNT_1_BIT) {
attDesc[2].format = colorFormat;
attDesc[2].samples = VK_SAMPLE_COUNT_1_BIT;
attDesc[2].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
attDesc[2].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attDesc[2].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attDesc[2].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attDesc[2].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attDesc[2].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
if (hasDepthStencil) {
// clear on load + no store + lazy alloc + transient image should play
// nicely with tiled GPUs (no physical backing necessary for ds buffer)
memset(&attDesc, 0, sizeof(attDesc));
attDesc.format = optimalDepthStencilFormat();
attDesc.samples = samples;
attDesc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
attDesc.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
attDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attDesc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attDesc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
rpD->attDescs.append(attDesc);
rpD->dsRef = { 1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL };
}
VkAttachmentReference colorRef = { 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
VkAttachmentReference dsRef = { 1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL };
VkAttachmentReference resolveRef = { 2, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
if (samples > VK_SAMPLE_COUNT_1_BIT) {
memset(&attDesc, 0, sizeof(attDesc));
attDesc.format = colorFormat;
attDesc.samples = VK_SAMPLE_COUNT_1_BIT;
attDesc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
attDesc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attDesc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attDesc.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
rpD->attDescs.append(attDesc);
rpD->resolveRefs.append({ 2, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL });
}
VkSubpassDescription subpassDesc;
memset(&subpassDesc, 0, sizeof(subpassDesc));
subpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpassDesc.colorAttachmentCount = 1;
subpassDesc.pColorAttachments = &colorRef;
subpassDesc.pDepthStencilAttachment = hasDepthStencil ? &dsRef : nullptr;
subpassDesc.pColorAttachments = rpD->colorRefs.constData();
subpassDesc.pDepthStencilAttachment = hasDepthStencil ? &rpD->dsRef : nullptr;
// Replace the first implicit dep (TOP_OF_PIPE / ALL_COMMANDS) with our own.
VkSubpassDependency subpassDep;
@ -1095,7 +1103,7 @@ bool QRhiVulkan::createDefaultRenderPass(VkRenderPass *rp, bool hasDepthStencil,
memset(&rpInfo, 0, sizeof(rpInfo));
rpInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
rpInfo.attachmentCount = 1;
rpInfo.pAttachments = attDesc;
rpInfo.pAttachments = rpD->attDescs.constData();
rpInfo.subpassCount = 1;
rpInfo.pSubpasses = &subpassDesc;
rpInfo.dependencyCount = 1;
@ -1106,19 +1114,21 @@ bool QRhiVulkan::createDefaultRenderPass(VkRenderPass *rp, bool hasDepthStencil,
if (samples > VK_SAMPLE_COUNT_1_BIT) {
rpInfo.attachmentCount += 1;
subpassDesc.pResolveAttachments = &resolveRef;
subpassDesc.pResolveAttachments = rpD->resolveRefs.constData();
}
VkResult err = df->vkCreateRenderPass(dev, &rpInfo, nullptr, rp);
VkResult err = df->vkCreateRenderPass(dev, &rpInfo, nullptr, &rpD->rp);
if (err != VK_SUCCESS) {
qWarning("Failed to create renderpass: %d", err);
return false;
}
rpD->hasDepthStencil = hasDepthStencil;
return true;
}
bool QRhiVulkan::createOffscreenRenderPass(VkRenderPass *rp,
bool QRhiVulkan::createOffscreenRenderPass(QVkRenderPassDescriptor *rpD,
const QRhiColorAttachment *firstColorAttachment,
const QRhiColorAttachment *lastColorAttachment,
bool preserveColor,
@ -1126,10 +1136,6 @@ bool QRhiVulkan::createOffscreenRenderPass(VkRenderPass *rp,
QRhiRenderBuffer *depthStencilBuffer,
QRhiTexture *depthTexture)
{
QVarLengthArray<VkAttachmentDescription, 8> attDescs;
QVarLengthArray<VkAttachmentReference, 8> colorRefs;
QVarLengthArray<VkAttachmentReference, 8> resolveRefs;
// attachment list layout is color (0-8), ds (0-1), resolve (0-8)
for (auto it = firstColorAttachment; it != lastColorAttachment; ++it) {
@ -1150,14 +1156,14 @@ bool QRhiVulkan::createOffscreenRenderPass(VkRenderPass *rp,
// this has to interact correctly with activateTextureRenderTarget(), hence leaving in COLOR_ATT
attDesc.initialLayout = preserveColor ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_UNDEFINED;
attDesc.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
attDescs.append(attDesc);
rpD->attDescs.append(attDesc);
const VkAttachmentReference ref = { uint32_t(attDescs.count() - 1), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
colorRefs.append(ref);
const VkAttachmentReference ref = { uint32_t(rpD->attDescs.count() - 1), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
rpD->colorRefs.append(ref);
}
const bool hasDepthStencil = depthStencilBuffer || depthTexture;
if (hasDepthStencil) {
rpD->hasDepthStencil = depthStencilBuffer || depthTexture;
if (rpD->hasDepthStencil) {
const VkFormat dsFormat = depthTexture ? QRHI_RES(QVkTexture, depthTexture)->vkformat
: QRHI_RES(QVkRenderBuffer, depthStencilBuffer)->vkformat;
const VkSampleCountFlagBits samples = depthTexture ? QRHI_RES(QVkTexture, depthTexture)->samples
@ -1174,9 +1180,9 @@ bool QRhiVulkan::createOffscreenRenderPass(VkRenderPass *rp,
attDesc.stencilStoreOp = storeOp;
attDesc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attDesc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
attDescs.append(attDesc);
rpD->attDescs.append(attDesc);
}
VkAttachmentReference dsRef = { uint32_t(attDescs.count() - 1), VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL };
rpD->dsRef = { uint32_t(rpD->attDescs.count() - 1), VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL };
for (auto it = firstColorAttachment; it != lastColorAttachment; ++it) {
if (it->resolveTexture()) {
@ -1194,37 +1200,37 @@ bool QRhiVulkan::createOffscreenRenderPass(VkRenderPass *rp,
attDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attDesc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attDesc.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
attDescs.append(attDesc);
rpD->attDescs.append(attDesc);
const VkAttachmentReference ref = { uint32_t(attDescs.count() - 1), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
resolveRefs.append(ref);
const VkAttachmentReference ref = { uint32_t(rpD->attDescs.count() - 1), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
rpD->resolveRefs.append(ref);
} else {
const VkAttachmentReference ref = { VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
resolveRefs.append(ref);
rpD->resolveRefs.append(ref);
}
}
VkSubpassDescription subpassDesc;
memset(&subpassDesc, 0, sizeof(subpassDesc));
subpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpassDesc.colorAttachmentCount = uint32_t(colorRefs.count());
Q_ASSERT(colorRefs.count() == resolveRefs.count());
subpassDesc.pColorAttachments = !colorRefs.isEmpty() ? colorRefs.constData() : nullptr;
subpassDesc.pDepthStencilAttachment = hasDepthStencil ? &dsRef : nullptr;
subpassDesc.pResolveAttachments = !resolveRefs.isEmpty() ? resolveRefs.constData() : nullptr;
subpassDesc.colorAttachmentCount = uint32_t(rpD->colorRefs.count());
Q_ASSERT(rpD->colorRefs.count() == rpD->resolveRefs.count());
subpassDesc.pColorAttachments = !rpD->colorRefs.isEmpty() ? rpD->colorRefs.constData() : nullptr;
subpassDesc.pDepthStencilAttachment = rpD->hasDepthStencil ? &rpD->dsRef : nullptr;
subpassDesc.pResolveAttachments = !rpD->resolveRefs.isEmpty() ? rpD->resolveRefs.constData() : nullptr;
VkRenderPassCreateInfo rpInfo;
memset(&rpInfo, 0, sizeof(rpInfo));
rpInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
rpInfo.attachmentCount = uint32_t(attDescs.count());
rpInfo.pAttachments = attDescs.constData();
rpInfo.attachmentCount = uint32_t(rpD->attDescs.count());
rpInfo.pAttachments = rpD->attDescs.constData();
rpInfo.subpassCount = 1;
rpInfo.pSubpasses = &subpassDesc;
// don't yet know the correct initial/final access and stage stuff for the
// implicit deps at this point, so leave it to the resource tracking to
// generate barriers
VkResult err = df->vkCreateRenderPass(dev, &rpInfo, nullptr, rp);
VkResult err = df->vkCreateRenderPass(dev, &rpInfo, nullptr, &rpD->rp);
if (err != VK_SUCCESS) {
qWarning("Failed to create renderpass: %d", err);
return false;
@ -4617,12 +4623,8 @@ static inline VkSamplerAddressMode toVkAddressMode(QRhiSampler::AddressMode m)
return VK_SAMPLER_ADDRESS_MODE_REPEAT;
case QRhiSampler::ClampToEdge:
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
case QRhiSampler::Border:
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
case QRhiSampler::Mirror:
return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
case QRhiSampler::MirrorOnce:
return VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE;
default:
Q_UNREACHABLE();
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
@ -5505,6 +5507,61 @@ void QVkRenderPassDescriptor::release()
rhiD->unregisterResource(this);
}
static inline bool attachmentDescriptionEquals(const VkAttachmentDescription &a, const VkAttachmentDescription &b)
{
return a.format == b.format
&& a.samples == b.samples
&& a.loadOp == b.loadOp
&& a.storeOp == b.storeOp
&& a.stencilLoadOp == b.stencilLoadOp
&& a.stencilStoreOp == b.stencilStoreOp
&& a.initialLayout == b.initialLayout
&& a.finalLayout == b.finalLayout;
}
bool QVkRenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *other) const
{
if (!other)
return false;
const QVkRenderPassDescriptor *o = QRHI_RES(const QVkRenderPassDescriptor, other);
if (attDescs.count() != o->attDescs.count())
return false;
if (colorRefs.count() != o->colorRefs.count())
return false;
if (resolveRefs.count() != o->resolveRefs.count())
return false;
if (hasDepthStencil != o->hasDepthStencil)
return false;
for (int i = 0, ie = colorRefs.count(); i != ie; ++i) {
const uint32_t attIdx = colorRefs[i].attachment;
if (attIdx != o->colorRefs[i].attachment)
return false;
if (attIdx != VK_ATTACHMENT_UNUSED && !attachmentDescriptionEquals(attDescs[attIdx], o->attDescs[attIdx]))
return false;
}
if (hasDepthStencil) {
const uint32_t attIdx = dsRef.attachment;
if (attIdx != o->dsRef.attachment)
return false;
if (attIdx != VK_ATTACHMENT_UNUSED && !attachmentDescriptionEquals(attDescs[attIdx], o->attDescs[attIdx]))
return false;
}
for (int i = 0, ie = resolveRefs.count(); i != ie; ++i) {
const uint32_t attIdx = resolveRefs[i].attachment;
if (attIdx != o->resolveRefs[i].attachment)
return false;
if (attIdx != VK_ATTACHMENT_UNUSED && !attachmentDescriptionEquals(attDescs[attIdx], o->attDescs[attIdx]))
return false;
}
return true;
}
const QRhiNativeHandles *QVkRenderPassDescriptor::nativeHandles()
{
nativeHandlesStruct.renderPass = rp;
@ -5588,7 +5645,7 @@ QRhiRenderPassDescriptor *QVkTextureRenderTarget::newCompatibleRenderPassDescrip
QRHI_RES_RHI(QRhiVulkan);
QVkRenderPassDescriptor *rp = new QVkRenderPassDescriptor(m_rhi);
if (!rhiD->createOffscreenRenderPass(&rp->rp,
if (!rhiD->createOffscreenRenderPass(rp,
m_desc.cbeginColorAttachments(),
m_desc.cendColorAttachments(),
m_flags.testFlag(QRhiTextureRenderTarget::PreserveColorContents),
@ -6289,7 +6346,7 @@ QRhiRenderPassDescriptor *QVkSwapChain::newCompatibleRenderPassDescriptor()
QRHI_RES_RHI(QRhiVulkan);
QVkRenderPassDescriptor *rp = new QVkRenderPassDescriptor(m_rhi);
if (!rhiD->createDefaultRenderPass(&rp->rp,
if (!rhiD->createDefaultRenderPass(rp,
m_depthStencil != nullptr,
samples,
colorFormat))

View File

@ -171,10 +171,16 @@ struct QVkRenderPassDescriptor : public QRhiRenderPassDescriptor
QVkRenderPassDescriptor(QRhiImplementation *rhi);
~QVkRenderPassDescriptor();
void release() override;
bool isCompatible(const QRhiRenderPassDescriptor *other) const override;
const QRhiNativeHandles *nativeHandles() override;
VkRenderPass rp = VK_NULL_HANDLE;
bool ownsRp = false;
QVarLengthArray<VkAttachmentDescription, 8> attDescs;
QVarLengthArray<VkAttachmentReference, 8> colorRefs;
QVarLengthArray<VkAttachmentReference, 8> resolveRefs;
bool hasDepthStencil = false;
VkAttachmentReference dsRef;
QRhiVulkanRenderPassNativeHandles nativeHandlesStruct;
int lastActiveFrameSlot = -1;
};
@ -727,11 +733,11 @@ public:
VkFormat optimalDepthStencilFormat();
VkSampleCountFlagBits effectiveSampleCount(int sampleCount);
bool createDefaultRenderPass(VkRenderPass *rp,
bool createDefaultRenderPass(QVkRenderPassDescriptor *rpD,
bool hasDepthStencil,
VkSampleCountFlagBits samples,
VkFormat colorFormat);
bool createOffscreenRenderPass(VkRenderPass *rp,
bool createOffscreenRenderPass(QVkRenderPassDescriptor *rpD,
const QRhiColorAttachment *firstColorAttachment,
const QRhiColorAttachment *lastColorAttachment,
bool preserveColor,

View File

@ -43,15 +43,15 @@ win32 {
LIBS += -ld3d11 -ldxgi -ldxguid
}
# darwin {
macos {
macos|ios {
HEADERS += \
rhi/qrhimetal_p.h \
rhi/qrhimetal_p_p.h
SOURCES += \
rhi/qrhimetal.mm
LIBS += -framework AppKit -framework Metal
macos: LIBS += -framework AppKit
LIBS += -framework Metal
}
include($$PWD/../../3rdparty/VulkanMemoryAllocator.pri)

View File

@ -51,6 +51,9 @@
#include <qpa/qplatformintegration.h>
#import <QuartzCore/CAEAGLLayer.h>
#ifdef Q_OS_IOS
#import <QuartzCore/CAMetalLayer.h>
#endif
#include <QtDebug>
@ -58,9 +61,15 @@ QT_BEGIN_NAMESPACE
QIOSWindow::QIOSWindow(QWindow *window)
: QPlatformWindow(window)
, m_view([[QUIView alloc] initWithQIOSWindow:this])
, m_windowLevel(0)
{
#ifdef Q_OS_IOS
if (window->surfaceType() == QSurface::MetalSurface)
m_view = [[QUIMetalView alloc] initWithQIOSWindow:this];
else
#endif
m_view = [[QUIView alloc] initWithQIOSWindow:this];
connect(qGuiApp, &QGuiApplication::applicationStateChanged, this, &QIOSWindow::applicationStateChanged);
setParent(QPlatformWindow::parent());

View File

@ -70,3 +70,7 @@ QT_END_NAMESPACE
@property (nonatomic, readonly) UIEdgeInsets qt_safeAreaInsets;
@end
#ifdef Q_OS_IOS
@interface QUIMetalView : QUIView
@end
#endif

View File

@ -100,13 +100,15 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
- (instancetype)initWithFrame:(CGRect)frame
{
if ((self = [super initWithFrame:frame])) {
// Set up EAGL layer
CAEAGLLayer *eaglLayer = static_cast<CAEAGLLayer *>(self.layer);
eaglLayer.opaque = TRUE;
eaglLayer.drawableProperties = @{
kEAGLDrawablePropertyRetainedBacking: @(YES),
kEAGLDrawablePropertyColorFormat: kEAGLColorFormatRGBA8
};
if ([self.layer isKindOfClass:[CAEAGLLayer class]]) {
// Set up EAGL layer
CAEAGLLayer *eaglLayer = static_cast<CAEAGLLayer *>(self.layer);
eaglLayer.opaque = TRUE;
eaglLayer.drawableProperties = @{
kEAGLDrawablePropertyRetainedBacking: @(YES),
kEAGLDrawablePropertyColorFormat: kEAGLColorFormatRGBA8
};
}
if (isQtApplication())
self.hidden = YES;
@ -675,6 +677,25 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
@end
#ifdef Q_OS_IOS
@implementation QUIMetalView
+ (Class)layerClass
{
#ifdef TARGET_IPHONE_SIMULATOR
if (@available(ios 13.0, *))
#endif
return [CAMetalLayer class];
#ifdef TARGET_IPHONE_SIMULATOR
return nil;
#endif
}
@end
#endif
#ifndef QT_NO_ACCESSIBILITY
// Include category as an alternative to using -ObjC (Apple QA1490)
#include "quiview_accessibility.mm"

View File

@ -11,9 +11,7 @@ HEADERS += qwindowsxpstyle_p.h qwindowsxpstyle_p_p.h
SOURCES += qwindowsxpstyle.cpp
QMAKE_USE_PRIVATE += user32 gdi32
# DEFINES/LIBS needed for qwizard_win.cpp and the styles
include(../../../widgets/kernel/win.pri)
LIBS_PRIVATE *= -luxtheme
DISTFILES += windowsvistastyle.json

View File

@ -460,7 +460,7 @@ int main(int argc, char *argv[])
}
// Run androiddeployqt
static auto verbose = g_options.verbose ? QStringLiteral("--verbose") : QStringLiteral();
static auto verbose = g_options.verbose ? QStringLiteral("--verbose") : QString();
if (!execCommand(QStringLiteral("%1 %3 --reinstall --output %2 --apk %4").arg(g_options.androidDeployQtCommand,
g_options.buildPath,
verbose,

View File

@ -376,7 +376,11 @@ Q_WIDGETS_EXPORT QSize qSmartMinSize(const QSize &sizeHint, const QSize &minSize
Q_WIDGETS_EXPORT QSize qSmartMinSize(const QWidgetItem *i)
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QWidget *w = const_cast<QWidgetItem *>(i)->widget();
#else
QWidget *w = i->widget();
#endif
return qSmartMinSize(w->sizeHint(), w->minimumSizeHint(),
w->minimumSize(), w->maximumSize(),
w->sizePolicy());
@ -414,8 +418,11 @@ Q_WIDGETS_EXPORT QSize qSmartMaxSize(const QSize &sizeHint,
Q_WIDGETS_EXPORT QSize qSmartMaxSize(const QWidgetItem *i, Qt::Alignment align)
{
QWidget *w = const_cast<QWidgetItem*>(i)->widget();
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QWidget *w = const_cast<QWidgetItem *>(i)->widget();
#else
QWidget *w = i->widget();
#endif
return qSmartMaxSize(w->sizeHint().expandedTo(w->minimumSizeHint()), w->minimumSize(), w->maximumSize(),
w->sizePolicy(), align);
}

View File

@ -291,14 +291,12 @@ void QSpacerItem::changeSize(int w, int h, QSizePolicy::Policy hPolicy,
/*!
Destructor.
*/
QWidgetItem::~QWidgetItem() {}
QWidgetItem::~QWidgetItem() = default;
/*!
Destroys the QLayoutItem.
*/
QLayoutItem::~QLayoutItem()
{
}
QLayoutItem::~QLayoutItem() = default;
/*!
Invalidates any cached information in this layout item.
@ -362,7 +360,11 @@ QSpacerItem * QSpacerItem::spacerItem()
\sa layout(), spacerItem()
*/
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QWidget *QLayoutItem::widget()
#else
QWidget *QLayoutItem::widget() const
#endif
{
return nullptr;
}
@ -370,7 +372,11 @@ QWidget *QLayoutItem::widget()
/*!
Returns the widget managed by this item.
*/
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QWidget *QWidgetItem::widget()
#else
QWidget *QWidgetItem::widget() const
#endif
{
return wid;
}

View File

@ -74,7 +74,11 @@ public:
virtual int minimumHeightForWidth(int) const;
virtual void invalidate();
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
virtual QWidget *widget();
#else
virtual QWidget *widget() const;
#endif
virtual QLayout *layout();
virtual QSpacerItem *spacerItem();
@ -133,7 +137,11 @@ public:
bool isEmpty() const override;
void setGeometry(const QRect&) override;
QRect geometry() const override;
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QWidget *widget() override;
#else
QWidget *widget() const override;
#endif
bool hasHeightForWidth() const override;
int heightForWidth(int) const override;

View File

@ -1,7 +1,6 @@
# Qt/Windows only configuration file
# --------------------------------------------------------------------
INCLUDEPATH += ../3rdparty/wintab
!winrt {
LIBS_PRIVATE *= -luxtheme -ldwmapi
QMAKE_USE_PRIVATE += shell32

View File

@ -201,7 +201,11 @@ inline QLayoutItem *QDockWidgetItem::dockWidgetChildItem() const
inline QDockWidgetLayout *QDockWidgetItem::dockWidgetLayout() const
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QWidget *w = const_cast<QDockWidgetItem*>(this)->widget();
#else
QWidget *w = widget();
#endif
if (w != nullptr)
return qobject_cast<QDockWidgetLayout*>(w->layout());
return nullptr;

View File

@ -52,7 +52,7 @@
# define TST_D3D11
#endif
#ifdef Q_OS_DARWIN
#if defined(Q_OS_MACOS) || defined(Q_OS_IOS)
# include <QtGui/private/qrhimetal_p.h>
# define TST_MTL
#endif
@ -91,6 +91,10 @@ private slots:
void renderToTextureTexturedQuadAndUniformBuffer();
void renderToWindowSimple_data();
void renderToWindowSimple();
void srbLayoutCompatibility_data();
void srbLayoutCompatibility();
void renderPassDescriptorCompatibility_data();
void renderPassDescriptorCompatibility();
private:
struct {
@ -1728,5 +1732,318 @@ void tst_QRhi::renderToWindowSimple()
QVERIFY(redCount < blueCount);
}
void tst_QRhi::srbLayoutCompatibility_data()
{
rhiTestData();
}
void tst_QRhi::srbLayoutCompatibility()
{
QFETCH(QRhi::Implementation, impl);
QFETCH(QRhiInitParams *, initParams);
QScopedPointer<QRhi> rhi(QRhi::create(impl, initParams, QRhi::Flags(), nullptr));
if (!rhi)
QSKIP("QRhi could not be created, skipping testing texture resource updates");
QScopedPointer<QRhiTexture> texture(rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512)));
QVERIFY(texture->build());
QScopedPointer<QRhiSampler> sampler(rhi->newSampler(QRhiSampler::Nearest, QRhiSampler::Nearest, QRhiSampler::None,
QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge));
QVERIFY(sampler->build());
QScopedPointer<QRhiSampler> otherSampler(rhi->newSampler(QRhiSampler::Nearest, QRhiSampler::Nearest, QRhiSampler::None,
QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge));
QVERIFY(otherSampler->build());
QScopedPointer<QRhiBuffer> buf(rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 1024));
QVERIFY(buf->build());
QScopedPointer<QRhiBuffer> otherBuf(rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 256));
QVERIFY(otherBuf->build());
// empty (compatible)
{
QScopedPointer<QRhiShaderResourceBindings> srb1(rhi->newShaderResourceBindings());
QVERIFY(srb1->build());
QScopedPointer<QRhiShaderResourceBindings> srb2(rhi->newShaderResourceBindings());
QVERIFY(srb2->build());
QVERIFY(srb1->isLayoutCompatible(srb2.data()));
QVERIFY(srb2->isLayoutCompatible(srb1.data()));
}
// different count (not compatible)
{
QScopedPointer<QRhiShaderResourceBindings> srb1(rhi->newShaderResourceBindings());
QVERIFY(srb1->build());
QScopedPointer<QRhiShaderResourceBindings> srb2(rhi->newShaderResourceBindings());
srb2->setBindings({
QRhiShaderResourceBinding::sampledTexture(0, QRhiShaderResourceBinding::FragmentStage, texture.data(), sampler.data())
});
QVERIFY(srb2->build());
QVERIFY(!srb1->isLayoutCompatible(srb2.data()));
QVERIFY(!srb2->isLayoutCompatible(srb1.data()));
}
// full match (compatible)
{
QScopedPointer<QRhiShaderResourceBindings> srb1(rhi->newShaderResourceBindings());
srb1->setBindings({
QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage, buf.data()),
QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, texture.data(), sampler.data())
});
QVERIFY(srb1->build());
QScopedPointer<QRhiShaderResourceBindings> srb2(rhi->newShaderResourceBindings());
srb2->setBindings({
QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage, buf.data()),
QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, texture.data(), sampler.data())
});
QVERIFY(srb2->build());
QVERIFY(srb1->isLayoutCompatible(srb2.data()));
QVERIFY(srb2->isLayoutCompatible(srb1.data()));
}
// different visibility (not compatible)
{
QScopedPointer<QRhiShaderResourceBindings> srb1(rhi->newShaderResourceBindings());
srb1->setBindings({
QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, buf.data()),
});
QVERIFY(srb1->build());
QScopedPointer<QRhiShaderResourceBindings> srb2(rhi->newShaderResourceBindings());
srb2->setBindings({
QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage, buf.data()),
});
QVERIFY(srb2->build());
QVERIFY(!srb1->isLayoutCompatible(srb2.data()));
QVERIFY(!srb2->isLayoutCompatible(srb1.data()));
}
// different binding points (not compatible)
{
QScopedPointer<QRhiShaderResourceBindings> srb1(rhi->newShaderResourceBindings());
srb1->setBindings({
QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage, buf.data()),
});
QVERIFY(srb1->build());
QScopedPointer<QRhiShaderResourceBindings> srb2(rhi->newShaderResourceBindings());
srb2->setBindings({
QRhiShaderResourceBinding::uniformBuffer(1, QRhiShaderResourceBinding::VertexStage, buf.data()),
});
QVERIFY(srb2->build());
QVERIFY(!srb1->isLayoutCompatible(srb2.data()));
QVERIFY(!srb2->isLayoutCompatible(srb1.data()));
}
// different buffer region offset and size (compatible)
{
QScopedPointer<QRhiShaderResourceBindings> srb1(rhi->newShaderResourceBindings());
srb1->setBindings({
QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage, buf.data(), rhi->ubufAligned(1), 128),
QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, texture.data(), sampler.data())
});
QVERIFY(srb1->build());
QScopedPointer<QRhiShaderResourceBindings> srb2(rhi->newShaderResourceBindings());
srb2->setBindings({
QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage, buf.data()),
QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, texture.data(), sampler.data())
});
QVERIFY(srb2->build());
QVERIFY(srb1->isLayoutCompatible(srb2.data()));
QVERIFY(srb2->isLayoutCompatible(srb1.data()));
}
// different resources (compatible)
{
QScopedPointer<QRhiShaderResourceBindings> srb1(rhi->newShaderResourceBindings());
srb1->setBindings({
QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage, otherBuf.data()),
QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, texture.data(), otherSampler.data())
});
QVERIFY(srb1->build());
QScopedPointer<QRhiShaderResourceBindings> srb2(rhi->newShaderResourceBindings());
srb2->setBindings({
QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage, buf.data()),
QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, texture.data(), sampler.data())
});
QVERIFY(srb2->build());
QVERIFY(srb1->isLayoutCompatible(srb2.data()));
QVERIFY(srb2->isLayoutCompatible(srb1.data()));
}
}
void tst_QRhi::renderPassDescriptorCompatibility_data()
{
rhiTestData();
}
void tst_QRhi::renderPassDescriptorCompatibility()
{
QFETCH(QRhi::Implementation, impl);
QFETCH(QRhiInitParams *, initParams);
QScopedPointer<QRhi> rhi(QRhi::create(impl, initParams, QRhi::Flags(), nullptr));
if (!rhi)
QSKIP("QRhi could not be created, skipping testing texture resource updates");
// Note that checking compatibility is only relevant with backends where
// there is a concept of renderpass descriptions (Vulkan, and partially
// Metal). It is perfectly fine for isCompatible() to always return true
// when that is not the case (D3D11, OpenGL). Hence the 'if (Vulkan or
// Metal)' for all the negative tests. Also note "partial" for Metal:
// resolve textures for examples have no effect on compatibility with Metal.
// tex and tex2 have the same format
QScopedPointer<QRhiTexture> tex(rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 1, QRhiTexture::RenderTarget));
QVERIFY(tex->build());
QScopedPointer<QRhiTexture> tex2(rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 1, QRhiTexture::RenderTarget));
QVERIFY(tex2->build());
QScopedPointer<QRhiRenderBuffer> ds(rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, QSize(512, 512)));
QVERIFY(ds->build());
// two texture rendertargets with tex and tex2 as color0 (compatible)
{
QScopedPointer<QRhiTextureRenderTarget> rt(rhi->newTextureRenderTarget({ tex.data() }));
QScopedPointer<QRhiRenderPassDescriptor> rpDesc(rt->newCompatibleRenderPassDescriptor());
rt->setRenderPassDescriptor(rpDesc.data());
QVERIFY(rt->build());
QScopedPointer<QRhiTextureRenderTarget> rt2(rhi->newTextureRenderTarget({ tex2.data() }));
QScopedPointer<QRhiRenderPassDescriptor> rpDesc2(rt2->newCompatibleRenderPassDescriptor());
rt2->setRenderPassDescriptor(rpDesc2.data());
QVERIFY(rt2->build());
QVERIFY(rpDesc->isCompatible(rpDesc2.data()));
QVERIFY(rpDesc2->isCompatible(rpDesc.data()));
}
// two texture rendertargets with tex and tex2 as color0, and a depth-stencil attachment as well (compatible)
{
QRhiTextureRenderTargetDescription desc({ tex.data() }, ds.data());
QScopedPointer<QRhiTextureRenderTarget> rt(rhi->newTextureRenderTarget(desc));
QScopedPointer<QRhiRenderPassDescriptor> rpDesc(rt->newCompatibleRenderPassDescriptor());
rt->setRenderPassDescriptor(rpDesc.data());
QVERIFY(rt->build());
QScopedPointer<QRhiTextureRenderTarget> rt2(rhi->newTextureRenderTarget(desc));
QScopedPointer<QRhiRenderPassDescriptor> rpDesc2(rt2->newCompatibleRenderPassDescriptor());
rt2->setRenderPassDescriptor(rpDesc2.data());
QVERIFY(rt2->build());
QVERIFY(rpDesc->isCompatible(rpDesc2.data()));
QVERIFY(rpDesc2->isCompatible(rpDesc.data()));
}
// now one of them does not have the ds attachment (not compatible)
{
QScopedPointer<QRhiTextureRenderTarget> rt(rhi->newTextureRenderTarget({ { tex.data() }, ds.data() }));
QScopedPointer<QRhiRenderPassDescriptor> rpDesc(rt->newCompatibleRenderPassDescriptor());
rt->setRenderPassDescriptor(rpDesc.data());
QVERIFY(rt->build());
QScopedPointer<QRhiTextureRenderTarget> rt2(rhi->newTextureRenderTarget({ tex.data() }));
QScopedPointer<QRhiRenderPassDescriptor> rpDesc2(rt2->newCompatibleRenderPassDescriptor());
rt2->setRenderPassDescriptor(rpDesc2.data());
QVERIFY(rt2->build());
if (impl == QRhi::Vulkan || impl == QRhi::Metal) {
QVERIFY(!rpDesc->isCompatible(rpDesc2.data()));
QVERIFY(!rpDesc2->isCompatible(rpDesc.data()));
}
}
if (rhi->isFeatureSupported(QRhi::MultisampleRenderBuffer)) {
// resolve attachments (compatible)
{
QScopedPointer<QRhiRenderBuffer> msaaRenderBuffer(rhi->newRenderBuffer(QRhiRenderBuffer::Color, QSize(512, 512), 4));
QVERIFY(msaaRenderBuffer->build());
QScopedPointer<QRhiRenderBuffer> msaaRenderBuffer2(rhi->newRenderBuffer(QRhiRenderBuffer::Color, QSize(512, 512), 4));
QVERIFY(msaaRenderBuffer2->build());
QRhiColorAttachment colorAtt(msaaRenderBuffer.data()); // color0, multisample
colorAtt.setResolveTexture(tex.data()); // resolved into a non-msaa texture
QScopedPointer<QRhiTextureRenderTarget> rt(rhi->newTextureRenderTarget({ colorAtt }));
QScopedPointer<QRhiRenderPassDescriptor> rpDesc(rt->newCompatibleRenderPassDescriptor());
rt->setRenderPassDescriptor(rpDesc.data());
QVERIFY(rt->build());
QRhiColorAttachment colorAtt2(msaaRenderBuffer2.data()); // color0, multisample
colorAtt2.setResolveTexture(tex2.data()); // resolved into a non-msaa texture
QScopedPointer<QRhiTextureRenderTarget> rt2(rhi->newTextureRenderTarget({ colorAtt2 }));
QScopedPointer<QRhiRenderPassDescriptor> rpDesc2(rt2->newCompatibleRenderPassDescriptor());
rt2->setRenderPassDescriptor(rpDesc2.data());
QVERIFY(rt2->build());
QVERIFY(rpDesc->isCompatible(rpDesc2.data()));
QVERIFY(rpDesc2->isCompatible(rpDesc.data()));
}
// missing resolve for one of them (not compatible)
{
QScopedPointer<QRhiRenderBuffer> msaaRenderBuffer(rhi->newRenderBuffer(QRhiRenderBuffer::Color, QSize(512, 512), 4));
QVERIFY(msaaRenderBuffer->build());
QScopedPointer<QRhiRenderBuffer> msaaRenderBuffer2(rhi->newRenderBuffer(QRhiRenderBuffer::Color, QSize(512, 512), 4));
QVERIFY(msaaRenderBuffer2->build());
QRhiColorAttachment colorAtt(msaaRenderBuffer.data()); // color0, multisample
colorAtt.setResolveTexture(tex.data()); // resolved into a non-msaa texture
QScopedPointer<QRhiTextureRenderTarget> rt(rhi->newTextureRenderTarget({ colorAtt }));
QScopedPointer<QRhiRenderPassDescriptor> rpDesc(rt->newCompatibleRenderPassDescriptor());
rt->setRenderPassDescriptor(rpDesc.data());
QVERIFY(rt->build());
QRhiColorAttachment colorAtt2(msaaRenderBuffer2.data()); // color0, multisample
QScopedPointer<QRhiTextureRenderTarget> rt2(rhi->newTextureRenderTarget({ colorAtt2 }));
QScopedPointer<QRhiRenderPassDescriptor> rpDesc2(rt2->newCompatibleRenderPassDescriptor());
rt2->setRenderPassDescriptor(rpDesc2.data());
QVERIFY(rt2->build());
if (impl == QRhi::Vulkan) { // no Metal here
QVERIFY(!rpDesc->isCompatible(rpDesc2.data()));
QVERIFY(!rpDesc2->isCompatible(rpDesc.data()));
}
}
} else {
qDebug("Skipping multisample renderbuffer dependent tests");
}
if (rhi->isTextureFormatSupported(QRhiTexture::RGBA32F)) {
QScopedPointer<QRhiTexture> tex3(rhi->newTexture(QRhiTexture::RGBA32F, QSize(512, 512), 1, QRhiTexture::RenderTarget));
QVERIFY(tex3->build());
// different texture formats (not compatible)
{
QScopedPointer<QRhiTextureRenderTarget> rt(rhi->newTextureRenderTarget({ tex.data() }));
QScopedPointer<QRhiRenderPassDescriptor> rpDesc(rt->newCompatibleRenderPassDescriptor());
rt->setRenderPassDescriptor(rpDesc.data());
QVERIFY(rt->build());
QScopedPointer<QRhiTextureRenderTarget> rt2(rhi->newTextureRenderTarget({ tex3.data() }));
QScopedPointer<QRhiRenderPassDescriptor> rpDesc2(rt2->newCompatibleRenderPassDescriptor());
rt2->setRenderPassDescriptor(rpDesc2.data());
QVERIFY(rt2->build());
if (impl == QRhi::Vulkan || impl == QRhi::Metal) {
QVERIFY(!rpDesc->isCompatible(rpDesc2.data()));
QVERIFY(!rpDesc2->isCompatible(rpDesc.data()));
}
}
} else {
qDebug("Skipping texture format dependent tests");
}
}
#include <tst_qrhi.moc>
QTEST_MAIN(tst_QRhi)

View File

@ -8299,20 +8299,14 @@ void tst_QGraphicsItem::sorting()
_paintedItems.clear();
view.viewport()->repaint();
#if defined(Q_OS_MAC)
// There's no difference between repaint and update on the Mac,
// so we have to process events here to make sure we get the event.
QTest::qWait(100);
#endif
view.viewport()->update();
const GraphicsItems expected{grid[0][0], grid[0][1], grid[0][2], grid[0][3],
grid[1][0], grid[1][1], grid[1][2], grid[1][3],
grid[2][0], grid[2][1], grid[2][2], grid[2][3],
grid[3][0], grid[3][1], grid[3][2], grid[3][3],
grid[4][0], grid[4][1], grid[4][2], grid[4][3],
item1, item2};
QCOMPARE(_paintedItems, expected);
QTRY_COMPARE(_paintedItems, expected);
}
void tst_QGraphicsItem::itemHasNoContents()
@ -8339,13 +8333,7 @@ void tst_QGraphicsItem::itemHasNoContents()
_paintedItems.clear();
view.viewport()->repaint();
#ifdef Q_OS_MAC
// There's no difference between update() and repaint() on the Mac,
// so we have to process events here to make sure we get the event.
QTest::qWait(10);
#endif
view.viewport()->update();
QTRY_COMPARE(_paintedItems, GraphicsItems{item2});
}

View File

@ -358,13 +358,13 @@ void tst_QGraphicsView::renderHints()
QCOMPARE(item->hints, 0);
view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
view.repaint();
view.update();
QTRY_COMPARE(item->hints, view.renderHints());
view.setRenderHints(QPainter::Antialiasing);
QCOMPARE(view.renderHints(), QPainter::Antialiasing);
view.repaint();
view.update();
QTRY_COMPARE(item->hints, view.renderHints());
}
@ -2631,13 +2631,12 @@ void tst_QGraphicsView::optimizationFlags()
class MessUpPainterItem : public QGraphicsRectItem
{
public:
MessUpPainterItem(const QRectF &rect) : QGraphicsRectItem(rect), dirtyPainter(false)
{ }
bool dirtyPainter;
using QGraphicsRectItem::QGraphicsRectItem;
bool dirtyPainter = false;
bool receivedPaintEvent = false;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *w)
{
receivedPaintEvent = true;
dirtyPainter = (painter->pen().color() != w->palette().color(w->foregroundRole()));
painter->setPen(Qt::red);
}
@ -2675,18 +2674,22 @@ void tst_QGraphicsView::optimizationFlags_dontSavePainterState()
QGraphicsView view(&scene);
view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
view.viewport()->repaint();
parent->receivedPaintEvent = false;
child->receivedPaintEvent = false;
view.viewport()->update();
QTRY_VERIFY(parent->receivedPaintEvent);
QTRY_VERIFY(child->receivedPaintEvent);
QVERIFY(!parent->dirtyPainter);
QVERIFY(!child->dirtyPainter);
view.setOptimizationFlags(QGraphicsView::DontSavePainterState);
view.viewport()->repaint();
parent->receivedPaintEvent = false;
child->receivedPaintEvent = false;
view.viewport()->update();
#ifdef Q_OS_MAC
// Repaint on OS X actually does require spinning the event loop.
QTest::qWait(100);
#endif
QTRY_VERIFY(parent->receivedPaintEvent);
QTRY_VERIFY(child->receivedPaintEvent);
QVERIFY(!parent->dirtyPainter);
QVERIFY(child->dirtyPainter);
@ -2753,7 +2756,7 @@ void tst_QGraphicsView::optimizationFlags_dontSavePainterState2()
QVERIFY(QTest::qWaitForWindowExposed(&view));
// Make sure the view is repainted; otherwise the tests below will fail.
view.viewport()->repaint();
view.viewport()->update();
QTRY_VERIFY(view.painted);
// Make sure the painter's world transform is preserved after drawItems.
@ -4732,14 +4735,12 @@ void tst_QGraphicsView::QTBUG_5859_exposedRect()
QGraphicsView view(&scene);
view.scale(4.15, 4.15);
view.showNormal();
qApp->setActiveWindow(&view);
QApplication::setActiveWindow(&view);
QVERIFY(QTest::qWaitForWindowExposed(&view));
QVERIFY(QTest::qWaitForWindowActive(&view));
view.viewport()->repaint(10,10,20,20);
QApplication::processEvents();
QCOMPARE(item.lastExposedRect, scene.lastBackgroundExposedRect);
view.viewport()->update(10,10,20,20);
QTRY_COMPARE(item.lastExposedRect, scene.lastBackgroundExposedRect);
}
#ifndef QT_NO_CURSOR

View File

@ -1186,7 +1186,7 @@ void tst_QGraphicsWidget::layoutDirection()
for (int i = 0; i < children.count(); ++i) {
QTRY_COMPARE(children[i]->layoutDirection(), layoutDirection);
QTRY_COMPARE(children[i]->testAttribute(Qt::WA_SetLayoutDirection), false);
view->repaint();
view->update();
QTRY_COMPARE(children[i]->m_painterLayoutDirection, layoutDirection);
}
}

View File

@ -77,6 +77,30 @@ static void initStandardTreeModel(QStandardItemModel *model)
model->insertRow(2, item);
}
class TreeView : public QTreeView
{
Q_OBJECT
public:
using QTreeView::QTreeView;
using QTreeView::selectedIndexes;
void paintEvent(QPaintEvent *event) override
{
QTreeView::paintEvent(event);
wasPainted = true;
}
bool wasPainted = false;
public slots:
void handleSelectionChanged()
{
//let's select the last item
QModelIndex idx = model()->index(0, 0);
selectionModel()->select(QItemSelection(idx, idx), QItemSelectionModel::Select);
disconnect(selectionModel(), &QItemSelectionModel::selectionChanged,
this, &TreeView::handleSelectionChanged);
}
};
class tst_QTreeView : public QObject
{
Q_OBJECT
@ -2980,7 +3004,7 @@ void tst_QTreeView::evilModel()
{
QFETCH(bool, visible);
// init
QTreeView view;
TreeView view;
EvilModel model;
view.setModel(&model);
view.setVisible(visible);
@ -3018,7 +3042,7 @@ void tst_QTreeView::evilModel()
view.scrollTo(thirdLevel);
model.change();
view.repaint();
view.update(); // will not do anything since view is not visible
model.change();
QTest::mouseDClick(view.viewport(), Qt::LeftButton);
@ -3175,7 +3199,7 @@ void tst_QTreeView::filterProxyModelCrash()
QSortFilterProxyModel proxy;
proxy.setSourceModel(&model);
QTreeView view;
TreeView view;
view.setModel(&proxy);
view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
@ -3184,7 +3208,8 @@ void tst_QTreeView::filterProxyModelCrash()
QTest::qWait(20);
proxy.invalidate();
view.repaint(); //used to crash
view.update(); //used to crash
QTRY_VERIFY(view.wasPainted);
}
void tst_QTreeView::renderToPixmap_data()
@ -3652,10 +3677,7 @@ void tst_QTreeView::task220298_selectColumns()
}
};
class TreeView : public QTreeView {
public:
using QTreeView::selectedIndexes;
} view;
TreeView view;
Model model;
view.setModel(&model);
view.show();
@ -4004,20 +4026,6 @@ void tst_QTreeView::task254234_proxySort()
QCOMPARE(view.model()->data(view.model()->index(1, 1)).toString(), QString::fromLatin1("g"));
}
class TreeView : public QTreeView
{
Q_OBJECT
public slots:
void handleSelectionChanged()
{
//let's select the last item
QModelIndex idx = model()->index(0, 0);
selectionModel()->select(QItemSelection(idx, idx), QItemSelectionModel::Select);
disconnect(selectionModel(), &QItemSelectionModel::selectionChanged,
this, &TreeView::handleSelectionChanged);
}
};
void tst_QTreeView::task248022_changeSelection()
{
//we check that changing the selection between the mouse press and the mouse release

View File

@ -8385,12 +8385,9 @@ void tst_QWidget::resizeInPaintEvent()
widget.resizeInPaintEvent = true;
// This will call resize in the paintEvent, which in turn will call
// invalidateBackingStore() and a new update request should be posted.
widget.repaint();
QCOMPARE(widget.numPaintEvents, 1);
widget.numPaintEvents = 0;
// Make sure the resize triggers another update.
QTRY_COMPARE(widget.numPaintEvents, 1);
// the resize triggers another update.
widget.update();
QTRY_COMPARE(widget.numPaintEvents, 2);
}
void tst_QWidget::opaqueChildren()
@ -8559,8 +8556,8 @@ void tst_QWidget::immediateRepaintAfterInvalidateBackingStore()
// The entire widget is already dirty, but this time we want to update immediately
// by calling repaint(), and thus we have to repaint the widget and not wait for
// the UpdateRequest to be sent when we get back to the event loop.
widget->repaint();
QCOMPARE(widget->numPaintEvents, 1);
widget->update();
QTRY_COMPARE(widget->numPaintEvents, 1);
}
#endif
@ -9832,7 +9829,7 @@ public:
if (!static_cast<QWidgetPrivate*>(d_ptr.data())->maybeRepaintManager()) {
static_cast<QWidgetPrivate*>(d_ptr.data())->topData()->repaintManager.reset(new QWidgetRepaintManager(this));
static_cast<QWidgetPrivate*>(d_ptr.data())->invalidateBackingStore(this->rect());
repaint();
update();
}
}
};
@ -9855,7 +9852,7 @@ void tst_QWidget::scrollWithoutBackingStore()
scrollable.scroll(-25,-25);
QCOMPARE(child.pos(),QPoint(25,25));
scrollable.enableBackingStore();
QCOMPARE(child.pos(),QPoint(25,25));
QTRY_COMPARE(child.pos(),QPoint(25,25));
}
#endif

View File

@ -79,24 +79,22 @@ using namespace QTestPrivate;
class StyleOptionTestStyle : public QCommonStyle
{
private:
bool readOnly;
public:
inline StyleOptionTestStyle() : QCommonStyle(), readOnly(false)
{
}
bool readOnly = false;
mutable bool wasDrawn = false;
inline void setReadOnly(bool readOnly)
using QCommonStyle::QCommonStyle;
void setReadOnly(bool readOnly)
{
this->readOnly = readOnly;
}
inline void drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *,
const QWidget *) const
void drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *,
const QWidget *) const override
{
switch (pe) {
case PE_PanelLineEdit:
wasDrawn = true;
if (readOnly)
QVERIFY(opt->state & QStyle::State_ReadOnly);
else
@ -3287,19 +3285,22 @@ void tst_QLineEdit::readOnlyStyleOption()
QLineEdit *testWidget = ensureTestWidget();
bool wasReadOnly = testWidget->isReadOnly();
QStyle *oldStyle = testWidget->style();
testWidget->show();
QTRY_VERIFY(QTest::qWaitForWindowExposed(testWidget));
StyleOptionTestStyle myStyle;
testWidget->setStyle(&myStyle);
myStyle.setReadOnly(true);
testWidget->setReadOnly(true);
testWidget->repaint();
qApp->processEvents();
testWidget->update();
QTRY_VERIFY(myStyle.wasDrawn);
myStyle.wasDrawn = false;
testWidget->setReadOnly(false);
myStyle.setReadOnly(false);
testWidget->repaint();
qApp->processEvents();
testWidget->update();
QTRY_VERIFY(myStyle.wasDrawn);
testWidget->setReadOnly(wasReadOnly);
testWidget->setStyle(oldStyle);

View File

@ -77,7 +77,7 @@
#include <QtGui/private/qrhid3d11_p.h>
#endif
#ifdef Q_OS_DARWIN
#if defined(Q_OS_MACOS) || defined(Q_OS_IOS)
#include <QtGui/private/qrhimetal_p.h>
#endif
@ -283,7 +283,7 @@ void Window::init()
}
#endif
#ifdef Q_OS_DARWIN
#if defined(Q_OS_MACOS) || defined(Q_OS_IOS)
if (graphicsApi == Metal) {
QRhiMetalInitParams params;
m_r = QRhi::create(QRhi::Metal, &params);
@ -483,7 +483,7 @@ int main(int argc, char **argv)
// Defaults.
#if defined(Q_OS_WIN)
graphicsApi = D3D11;
#elif defined(Q_OS_DARWIN)
#elif defined(Q_OS_MACOS) || defined(Q_OS_IOS)
graphicsApi = Metal;
#elif QT_CONFIG(vulkan)
graphicsApi = Vulkan;

View File

@ -78,7 +78,7 @@
#include <QtGui/private/qrhid3d11_p.h>
#endif
#ifdef Q_OS_DARWIN
#if defined(Q_OS_MACOS) || defined(Q_OS_IOS)
#include <QtGui/private/qrhimetal_p.h>
#endif
@ -148,7 +148,7 @@ void createRhi()
}
#endif
#ifdef Q_OS_DARWIN
#if defined(Q_OS_MACOS) || defined(Q_OS_IOS)
if (graphicsApi == Metal) {
QRhiMetalInitParams params;
r.r = QRhi::create(QRhi::Metal, &params);
@ -530,7 +530,7 @@ int main(int argc, char **argv)
#if defined(Q_OS_WIN)
graphicsApi = D3D11;
#elif defined(Q_OS_DARWIN)
#elif defined(Q_OS_MACOS) || defined(Q_OS_IOS)
graphicsApi = Metal;
#elif QT_CONFIG(vulkan)
graphicsApi = Vulkan;

View File

@ -82,7 +82,7 @@
#include <QtGui/private/qrhid3d11_p.h>
#endif
#ifdef Q_OS_DARWIN
#if defined(Q_OS_MACOS) || defined(Q_OS_IOS)
#include <QtGui/private/qrhimetal_p.h>
#endif
@ -376,7 +376,7 @@ void Renderer::createRhi()
}
#endif
#ifdef Q_OS_DARWIN
#if defined(Q_OS_MACOS) || defined(Q_OS_IOS)
if (graphicsApi == Metal) {
QRhiMetalInitParams params;
r = QRhi::create(QRhi::Metal, &params, rhiFlags);
@ -730,7 +730,7 @@ int main(int argc, char **argv)
#if defined(Q_OS_WIN)
graphicsApi = D3D11;
#elif defined(Q_OS_DARWIN)
#elif defined(Q_OS_MACOS) || defined(Q_OS_IOS)
graphicsApi = Metal;
#elif QT_CONFIG(vulkan)
graphicsApi = Vulkan;

View File

@ -72,7 +72,7 @@
#include <QtGui/private/qrhid3d11_p.h>
#endif
#ifdef Q_OS_DARWIN
#if defined(Q_OS_MACOS) || defined(Q_OS_IOS)
#include <QtGui/private/qrhimetal_p.h>
#endif
@ -130,7 +130,7 @@ int main(int argc, char **argv)
#if defined(Q_OS_WIN)
graphicsApi = D3D11;
#elif defined(Q_OS_DARWIN)
#elif defined(Q_OS_MACOS) || defined(Q_OS_IOS)
graphicsApi = Metal;
#elif QT_CONFIG(vulkan)
graphicsApi = Vulkan;
@ -217,7 +217,7 @@ int main(int argc, char **argv)
}
#endif
#ifdef Q_OS_DARWIN
#if defined(Q_OS_MACOS) || defined(Q_OS_IOS)
if (graphicsApi == Metal) {
QRhiMetalInitParams params;
r = QRhi::create(QRhi::Metal, &params);

View File

@ -78,7 +78,7 @@
#include <QtGui/private/qrhid3d11_p.h>
#endif
#ifdef Q_OS_DARWIN
#if defined(Q_OS_MACOS) || defined(Q_OS_IOS)
#include <QtGui/private/qrhimetal_p.h>
#endif
@ -292,7 +292,7 @@ void Window::init()
}
#endif
#ifdef Q_OS_DARWIN
#if defined(Q_OS_MACOS) || defined(Q_OS_IOS)
if (graphicsApi == Metal) {
QRhiMetalInitParams params;
m_r = QRhi::create(QRhi::Metal, &params, rhiFlags);
@ -445,7 +445,7 @@ int main(int argc, char **argv)
// Defaults.
#if defined(Q_OS_WIN)
graphicsApi = D3D11;
#elif defined(Q_OS_DARWIN)
#elif defined(Q_OS_MACOS) || defined(Q_OS_IOS)
graphicsApi = Metal;
#elif QT_CONFIG(vulkan)
graphicsApi = Vulkan;

View File

@ -239,7 +239,7 @@ void Window::customRender()
if (d.testStage == 6) {
const QRhiNativeHandles *h = d.tex->nativeHandles();
if (h) {
#ifdef Q_OS_DARWIN
#if defined(Q_OS_MACOS) || defined(Q_OS_IOS)
if (graphicsApi == Metal) {
qDebug() << "Metal texture: " << static_cast<const QRhiMetalTextureNativeHandles *>(h)->texture;
// Now could cast to id<MTLTexture> and do something with

View File

@ -37,6 +37,9 @@ To update:
the same time and update text/qt_attribution.json to match; use the
UCD Revision number, rather than the Unicode standard number, as the
Version, for all that qunicodetables.cpp uses the latter.
* If there are enum additions in qchar.h (public API), be sure to also
update the documentation in qchar.cpp for each affected enum,
respecting the existing ordering.
* If you don't normally build in the source tree, remember to delete
qtbase/.qmake.stash while you're cleaning up.

View File

@ -193,9 +193,9 @@ enum Direction {
DirLRI = QChar::DirLRI,
DirRLI = QChar::DirRLI,
DirFSI = QChar::DirFSI,
DirPDI = QChar::DirPDI
DirPDI = QChar::DirPDI,
, Dir_Unassigned
Dir_Unassigned
};
static QHash<QByteArray, Direction> directionMap;
@ -245,9 +245,9 @@ enum JoiningType {
Joining_Dual,
Joining_Right,
Joining_Left,
Joining_Transparent
Joining_Transparent,
, Joining_Unassigned
Joining_Unassigned
};
static QHash<QByteArray, JoiningType> joining_map;
@ -294,7 +294,8 @@ static const char *grapheme_break_class_string =
" Graphemebreak_E_Modifier,\n"
" Graphemebreak_Glue_After_Zwj,\n"
" Graphemebreak_E_Base_GAZ,\n"
" NumGraphemeBreakClasses,\n"
"\n"
" NumGraphemeBreakClasses\n"
"};\n\n";
enum GraphemeBreakClass {
@ -381,7 +382,8 @@ static const char *word_break_class_string =
" WordBreak_Glue_After_Zwj,\n"
" WordBreak_E_Base_GAZ,\n"
" WordBreak_WSegSpace,\n"
" NumWordBreakClasses,\n"
"\n"
" NumWordBreakClasses\n"
"};\n\n";
enum WordBreakClass {
@ -469,6 +471,7 @@ static const char *sentence_break_class_string =
" SentenceBreak_SContinue,\n"
" SentenceBreak_STerm,\n"
" SentenceBreak_Close,\n"
"\n"
" NumSentenceBreakClasses\n"
"};\n\n";
@ -486,9 +489,9 @@ enum SentenceBreakClass {
SentenceBreak_ATerm,
SentenceBreak_SContinue,
SentenceBreak_STerm,
SentenceBreak_Close
SentenceBreak_Close,
, SentenceBreak_Unassigned
SentenceBreak_Unassigned
};
static QHash<QByteArray, SentenceBreakClass> sentence_break_map;
@ -537,6 +540,7 @@ static const char *line_break_class_string =
" LineBreak_EB, LineBreak_EM, LineBreak_ZWJ,\n"
" LineBreak_SA, LineBreak_SG, LineBreak_SP,\n"
" LineBreak_CR, LineBreak_LF, LineBreak_BK,\n"
"\n"
" NumLineBreakClasses\n"
"};\n\n";