aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/particles/qquickimageparticle.cpp10
-rw-r--r--src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp4
-rw-r--r--src/qml/compiler/qv4ssa.cpp123
-rw-r--r--src/qml/compiler/qv4ssa_p.h15
-rw-r--r--src/qml/jit/qv4assembler.cpp13
-rw-r--r--src/qml/jit/qv4assembler_p.h10
-rw-r--r--src/qml/jit/qv4isel_masm.cpp28
-rw-r--r--src/qml/jit/qv4regalloc.cpp76
-rw-r--r--src/qml/jit/qv4targetplatform_p.h2
-rw-r--r--src/qml/jsruntime/qv4numberobject.cpp22
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp96
-rw-r--r--src/qml/qml/qml.pri6
-rw-r--r--src/qml/qml/qqmlengine.cpp2
-rw-r--r--src/qml/qml/qqmljavascriptexpression.cpp2
-rw-r--r--src/qml/qml/qqmlloggingcategory.cpp128
-rw-r--r--src/qml/qml/qqmlloggingcategory_p.h89
-rw-r--r--src/qml/qml/qqmlpropertycache.cpp34
-rw-r--r--src/qml/qml/qqmlpropertycache_p.h67
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp25
-rw-r--r--src/quick/doc/src/concepts/visualcanvas/adaptations.qdoc4
-rw-r--r--src/quick/items/context2d/qquickcontext2d_p.h4
-rw-r--r--src/quick/items/qquickframebufferobject.cpp11
-rw-r--r--src/quick/items/qquickrectangle.cpp2
-rw-r--r--src/quick/items/qquickwindow.cpp6
-rw-r--r--src/quick/scenegraph/qsgcontext_p.h3
-rw-r--r--src/quick/scenegraph/qsgdefaultglyphnode_p.cpp23
-rw-r--r--src/quick/scenegraph/qsgdefaultrendercontext.cpp6
-rw-r--r--tests/auto/qml/qjsengine/tst_qjsengine.cpp9
-rw-r--r--tests/auto/qml/qqmlconsole/data/categorized_logging.qml65
-rw-r--r--tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp36
-rw-r--r--tests/auto/qml/qqmlextensionplugin/tst_qqmlextensionplugin.cpp6
-rw-r--r--tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp18
-rw-r--r--tests/auto/shared/util.cpp11
-rw-r--r--tests/auto/shared/util.h5
34 files changed, 724 insertions, 237 deletions
diff --git a/src/particles/qquickimageparticle.cpp b/src/particles/qquickimageparticle.cpp
index 07cbee1383..c68153aca8 100644
--- a/src/particles/qquickimageparticle.cpp
+++ b/src/particles/qquickimageparticle.cpp
@@ -49,6 +49,7 @@
#include <private/qquicksprite_p.h>
#include <private/qquickspriteengine_p.h>
#include <QOpenGLFunctions>
+#include <QSGRendererInterface>
#include <QtQuick/private/qsgshadersourcebuilder_p.h>
#include <QtQuick/private/qsgtexture_p.h>
#include <private/qqmlglobal_p.h>
@@ -1469,8 +1470,17 @@ void QQuickImageParticle::finishBuildParticleNodes(QSGNode** node)
update();
}
+static inline bool isOpenGL(QSGRenderContext *rc)
+{
+ QSGRendererInterface *rif = rc->sceneGraphContext()->rendererInterface(rc);
+ return !rif || rif->graphicsApi() == QSGRendererInterface::OpenGL;
+}
+
QSGNode *QQuickImageParticle::updatePaintNode(QSGNode *node, UpdatePaintNodeData *)
{
+ if (!node && !isOpenGL(QQuickItemPrivate::get(this)->sceneGraphRenderContext()))
+ return 0;
+
if (m_pleaseReset){
if (node)
delete node;
diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp
index 900dfe7ef7..2644c693ce 100644
--- a/src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp
+++ b/src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp
@@ -737,9 +737,13 @@ void QSGD3D12EnginePrivate::initialize(WId w, const QSize &size, float dpr, int
const bool debugLayer = qEnvironmentVariableIntValue("QT_D3D_DEBUG") != 0;
if (debugLayer) {
qCDebug(QSG_LOG_INFO_GENERAL, "Enabling debug layer");
+#if !defined(Q_OS_WINRT) || !defined(NDEBUG)
ComPtr<ID3D12Debug> debugController;
if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController))))
debugController->EnableDebugLayer();
+#else
+ qCDebug(QSG_LOG_INFO_GENERAL, "Using DebugInterface will not allow certification to pass");
+#endif
}
QSGD3D12DeviceManager *dev = deviceManager();
diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp
index 6d55b43354..a37d8ef7a5 100644
--- a/src/qml/compiler/qv4ssa.cpp
+++ b/src/qml/compiler/qv4ssa.cpp
@@ -4343,7 +4343,59 @@ private:
* See LifeTimeIntervals::renumber for details on the numbering.
*/
class LifeRanges {
- typedef QSet<Temp> LiveRegs;
+ class LiveRegs
+ {
+ typedef std::vector<int> Storage;
+ Storage regs;
+
+ public:
+ void insert(int r)
+ {
+ if (find(r) == end())
+ regs.push_back(r);
+ }
+
+ void unite(const LiveRegs &other)
+ {
+ if (other.empty())
+ return;
+ if (empty()) {
+ regs = other.regs;
+ return;
+ }
+ for (int r : other.regs)
+ insert(r);
+ }
+
+ typedef Storage::iterator iterator;
+ iterator find(int r)
+ { return std::find(regs.begin(), regs.end(), r); }
+
+ iterator begin()
+ { return regs.begin(); }
+
+ iterator end()
+ { return regs.end(); }
+
+ void erase(iterator it)
+ { regs.erase(it); }
+
+ void remove(int r)
+ {
+ iterator it = find(r);
+ if (it != end())
+ erase(it);
+ }
+
+ bool empty() const
+ { return regs.empty(); }
+
+ int size() const
+ { return int(regs.size()); }
+
+ int at(int idx) const
+ { return regs.at(idx); }
+ };
std::vector<LiveRegs> _liveIn;
std::vector<LifeTimeInterval *> _intervals;
@@ -4351,14 +4403,21 @@ class LifeRanges {
LifeTimeInterval &interval(const Temp *temp)
{
- LifeTimeInterval *&lti = _intervals[temp->index];
- if (Q_UNLIKELY(!lti)) {
- lti = new LifeTimeInterval;
- lti->setTemp(*temp);
- }
+ LifeTimeInterval *lti = _intervals[temp->index];
+ Q_ASSERT(lti);
return *lti;
}
+ void ensureInterval(const IR::Temp &temp)
+ {
+ Q_ASSERT(!temp.isInvalid());
+ LifeTimeInterval *&lti = _intervals[temp.index];
+ if (lti)
+ return;
+ lti = new LifeTimeInterval;
+ lti->setTemp(temp);
+ }
+
int defPosition(IR::Stmt *s) const
{
return usePosition(s) + 1;
@@ -4412,13 +4471,13 @@ public:
IRPrinter printer(&qout);
for (size_t i = 0, ei = _liveIn.size(); i != ei; ++i) {
qout << "L" << i <<" live-in: ";
- QList<Temp> live = QList<Temp>::fromSet(_liveIn.at(i));
- if (live.isEmpty())
+ auto live = _liveIn.at(i);
+ if (live.empty())
qout << "(none)";
std::sort(live.begin(), live.end());
for (int i = 0; i < live.size(); ++i) {
if (i > 0) qout << ", ";
- printer.print(&live[i]);
+ qout << '%' << live.at(i);
}
qout << endl;
}
@@ -4437,8 +4496,10 @@ private:
for (Stmt *s : successor->statements()) {
if (Phi *phi = s->asPhi()) {
- if (Temp *t = phi->incoming.at(bbIndex)->asTemp())
- live.insert(*t);
+ if (Temp *t = phi->incoming.at(bbIndex)->asTemp()) {
+ ensureInterval(*t);
+ live.insert(t->index);
+ }
} else {
break;
}
@@ -4447,14 +4508,15 @@ private:
const QVector<Stmt *> &statements = bb->statements();
- foreach (const Temp &opd, live)
- interval(&opd).addRange(start(bb), end(bb));
+ for (int reg : live)
+ _intervals[reg]->addRange(start(bb), end(bb));
InputOutputCollector collector;
for (int i = statements.size() - 1; i >= 0; --i) {
Stmt *s = statements.at(i);
if (Phi *phi = s->asPhi()) {
- LiveRegs::iterator it = live.find(*phi->targetTemp);
+ ensureInterval(*phi->targetTemp);
+ LiveRegs::iterator it = live.find(phi->targetTemp->index);
if (it == live.end()) {
// a phi node target that is only defined, but never used
interval(phi->targetTemp).setFrom(start(bb));
@@ -4467,25 +4529,27 @@ private:
collector.collect(s);
//### TODO: use DefUses from the optimizer, because it already has all this information
if (Temp *opd = collector.output) {
+ ensureInterval(*opd);
LifeTimeInterval &lti = interval(opd);
lti.setFrom(defPosition(s));
- live.remove(lti.temp());
+ live.remove(lti.temp().index);
_sortedIntervals->add(&lti);
}
//### TODO: use DefUses from the optimizer, because it already has all this information
for (size_t i = 0, ei = collector.inputs.size(); i != ei; ++i) {
Temp *opd = collector.inputs[i];
+ ensureInterval(*opd);
interval(opd).addRange(start(bb), usePosition(s));
- live.insert(*opd);
+ live.insert(opd->index);
}
}
if (loopEnd) { // Meaning: bb is a loop header, because loopEnd is set to non-null.
- foreach (const Temp &opd, live)
- interval(&opd).addRange(start(bb), usePosition(loopEnd->terminator()));
+ for (int reg : live)
+ _intervals[reg]->addRange(start(bb), usePosition(loopEnd->terminator()));
}
- _liveIn[bb->index()] = live;
+ _liveIn[bb->index()] = std::move(live);
}
};
@@ -5055,7 +5119,7 @@ void LifeTimeInterval::setFrom(int from) {
Q_ASSERT(from > 0);
if (_ranges.isEmpty()) { // this is the case where there is no use, only a define
- _ranges.push_front(Range(from, from));
+ _ranges.prepend(Range(from, from));
if (_end == InvalidPosition)
_end = from;
} else {
@@ -5069,7 +5133,7 @@ void LifeTimeInterval::addRange(int from, int to) {
Q_ASSERT(to >= from);
if (_ranges.isEmpty()) {
- _ranges.push_front(Range(from, to));
+ _ranges.prepend(Range(from, to));
_end = to;
return;
}
@@ -5084,12 +5148,12 @@ void LifeTimeInterval::addRange(int from, int to) {
break;
p1->start = qMin(p->start, p1->start);
p1->end = qMax(p->end, p1->end);
- _ranges.pop_front();
+ _ranges.remove(0);
p = &_ranges.first();
}
} else {
if (to < p->start) {
- _ranges.push_front(Range(from, to));
+ _ranges.prepend(Range(from, to));
} else {
Q_ASSERT(from > _ranges.last().end);
_ranges.push_back(Range(from, to));
@@ -5130,7 +5194,7 @@ LifeTimeInterval LifeTimeInterval::split(int atPosition, int newStart)
}
if (newInterval._ranges.first().end == atPosition)
- newInterval._ranges.removeFirst();
+ newInterval._ranges.remove(0);
if (newStart == InvalidPosition) {
// the temp stays inactive for the rest of its lifetime
@@ -5150,7 +5214,7 @@ LifeTimeInterval LifeTimeInterval::split(int atPosition, int newStart)
break;
} else {
// the temp stays inactive for this interval, so remove it.
- newInterval._ranges.removeFirst();
+ newInterval._ranges.remove(0);
}
}
Q_ASSERT(!newInterval._ranges.isEmpty());
@@ -5181,15 +5245,6 @@ void LifeTimeInterval::dump(QTextStream &out) const {
out << " (register " << _reg << ")";
}
-bool LifeTimeInterval::lessThan(const LifeTimeInterval *r1, const LifeTimeInterval *r2) {
- if (r1->_ranges.first().start == r2->_ranges.first().start) {
- if (r1->isSplitFromInterval() == r2->isSplitFromInterval())
- return r1->_ranges.last().end < r2->_ranges.last().end;
- else
- return r1->isSplitFromInterval();
- } else
- return r1->_ranges.first().start < r2->_ranges.first().start;
-}
bool LifeTimeInterval::lessThanForTemp(const LifeTimeInterval *r1, const LifeTimeInterval *r2)
{
diff --git a/src/qml/compiler/qv4ssa_p.h b/src/qml/compiler/qv4ssa_p.h
index ffba13f2ae..f64fb9c3d9 100644
--- a/src/qml/compiler/qv4ssa_p.h
+++ b/src/qml/compiler/qv4ssa_p.h
@@ -76,7 +76,7 @@ public:
bool covers(int position) const { return start <= position && position <= end; }
};
- typedef QVector<Range> Ranges;
+ typedef QVarLengthArray<Range, 4> Ranges;
private:
Temp _temp;
@@ -90,7 +90,7 @@ public:
enum { InvalidPosition = -1 };
enum { InvalidRegister = -1 };
- explicit LifeTimeInterval(int rangeCapacity = 2)
+ explicit LifeTimeInterval(int rangeCapacity = 4)
: _end(InvalidPosition)
, _reg(InvalidRegister)
, _isFixedInterval(0)
@@ -147,6 +147,17 @@ public:
}
};
+inline bool LifeTimeInterval::lessThan(const LifeTimeInterval *r1, const LifeTimeInterval *r2)
+{
+ if (r1->_ranges.first().start == r2->_ranges.first().start) {
+ if (r1->isSplitFromInterval() == r2->isSplitFromInterval())
+ return r1->_ranges.last().end < r2->_ranges.last().end;
+ else
+ return r1->isSplitFromInterval();
+ } else
+ return r1->_ranges.first().start < r2->_ranges.first().start;
+}
+
class LifeTimeIntervals
{
Q_DISABLE_COPY(LifeTimeIntervals)
diff --git a/src/qml/jit/qv4assembler.cpp b/src/qml/jit/qv4assembler.cpp
index 9c839936c2..5e05f14192 100644
--- a/src/qml/jit/qv4assembler.cpp
+++ b/src/qml/jit/qv4assembler.cpp
@@ -152,11 +152,14 @@ Assembler::Assembler(InstructionSelection *isel, IR::Function* function, QV4::Ex
, _executableAllocator(executableAllocator)
, _isel(isel)
{
+ _addrs.resize(_function->basicBlockCount());
+ _patches.resize(_function->basicBlockCount());
+ _labelPatches.resize(_function->basicBlockCount());
}
void Assembler::registerBlock(IR::BasicBlock* block, IR::BasicBlock *nextBlock)
{
- _addrs[block] = label();
+ _addrs[block->index()] = label();
catchBlock = block->catchBlock;
_nextBlock = nextBlock;
}
@@ -166,12 +169,12 @@ void Assembler::jumpToBlock(IR::BasicBlock* current, IR::BasicBlock *target)
Q_UNUSED(current);
if (target != _nextBlock)
- _patches[target].append(jump());
+ _patches[target->index()].push_back(jump());
}
void Assembler::addPatch(IR::BasicBlock* targetBlock, Jump targetJump)
{
- _patches[targetBlock].append(targetJump);
+ _patches[targetBlock->index()].push_back(targetJump);
}
void Assembler::addPatch(DataLabelPtr patch, Label target)
@@ -179,12 +182,12 @@ void Assembler::addPatch(DataLabelPtr patch, Label target)
DataLabelPatch p;
p.dataLabel = patch;
p.target = target;
- _dataLabelPatches.append(p);
+ _dataLabelPatches.push_back(p);
}
void Assembler::addPatch(DataLabelPtr patch, IR::BasicBlock *target)
{
- _labelPatches[target].append(patch);
+ _labelPatches[target->index()].push_back(patch);
}
void Assembler::generateCJumpOnNonZero(RegisterID reg, IR::BasicBlock *currentBlock,
diff --git a/src/qml/jit/qv4assembler_p.h b/src/qml/jit/qv4assembler_p.h
index 2ef0db78c0..7d4d90882a 100644
--- a/src/qml/jit/qv4assembler_p.h
+++ b/src/qml/jit/qv4assembler_p.h
@@ -58,8 +58,6 @@
#include "private/qv4lookup_p.h"
#include "qv4targetplatform_p.h"
-#include <QtCore/QHash>
-#include <QtCore/QStack>
#include <config.h>
#include <wtf/Vector.h>
@@ -1073,8 +1071,8 @@ public:
private:
QScopedPointer<const StackLayout> _stackLayout;
IR::Function *_function;
- QHash<IR::BasicBlock *, Label> _addrs;
- QHash<IR::BasicBlock *, QVector<Jump> > _patches;
+ std::vector<Label> _addrs;
+ std::vector<std::vector<Jump>> _patches;
#ifndef QT_NO_DEBUG
QVector<CallInfo> _callInfos;
#endif
@@ -1083,9 +1081,9 @@ private:
DataLabelPtr dataLabel;
Label target;
};
- QList<DataLabelPatch> _dataLabelPatches;
+ std::vector<DataLabelPatch> _dataLabelPatches;
- QHash<IR::BasicBlock *, QVector<DataLabelPtr> > _labelPatches;
+ std::vector<std::vector<DataLabelPtr>> _labelPatches;
IR::BasicBlock *_nextBlock;
QV4::ExecutableAllocator *_executableAllocator;
diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp
index 2cb3596c33..dd3b803ca8 100644
--- a/src/qml/jit/qv4isel_masm.cpp
+++ b/src/qml/jit/qv4isel_masm.cpp
@@ -144,13 +144,10 @@ JSC::MacroAssemblerCodeRef Assembler::link(int *codeSize)
Label endOfCode = label();
{
- QHashIterator<IR::BasicBlock *, QVector<Jump> > it(_patches);
- while (it.hasNext()) {
- it.next();
- IR::BasicBlock *block = it.key();
- Label target = _addrs.value(block);
+ for (size_t i = 0, ei = _patches.size(); i != ei; ++i) {
+ Label target = _addrs.at(i);
Q_ASSERT(target.isSet());
- foreach (Jump jump, it.value())
+ for (Jump jump : qAsConst(_patches.at(i)))
jump.linkTo(target, this);
}
}
@@ -158,21 +155,18 @@ JSC::MacroAssemblerCodeRef Assembler::link(int *codeSize)
JSC::JSGlobalData dummy(_executableAllocator);
JSC::LinkBuffer linkBuffer(dummy, this, 0);
- foreach (const DataLabelPatch &p, _dataLabelPatches)
+ for (const DataLabelPatch &p : qAsConst(_dataLabelPatches))
linkBuffer.patch(p.dataLabel, linkBuffer.locationOf(p.target));
// link exception handlers
- foreach(Jump jump, exceptionPropagationJumps)
+ for (Jump jump : qAsConst(exceptionPropagationJumps))
linkBuffer.link(jump, linkBuffer.locationOf(exceptionReturnLabel));
{
- QHashIterator<IR::BasicBlock *, QVector<DataLabelPtr> > it(_labelPatches);
- while (it.hasNext()) {
- it.next();
- IR::BasicBlock *block = it.key();
- Label target = _addrs.value(block);
+ for (size_t i = 0, ei = _labelPatches.size(); i != ei; ++i) {
+ Label target = _addrs.at(i);
Q_ASSERT(target.isSet());
- foreach (DataLabelPtr label, it.value())
+ for (DataLabelPtr label : _labelPatches.at(i))
linkBuffer.patch(label, linkBuffer.locationOf(target));
}
}
@@ -187,7 +181,7 @@ JSC::MacroAssemblerCodeRef Assembler::link(int *codeSize)
if (showCode) {
QHash<void*, const char*> functions;
#ifndef QT_NO_DEBUG
- foreach (CallInfo call, _callInfos)
+ for (CallInfo call : qAsConst(_callInfos))
functions[linkBuffer.locationOf(call.label).dataLocation()] = call.functionName;
#endif
@@ -337,7 +331,7 @@ void InstructionSelection::run(int functionIndex)
continue;
_as->registerBlock(_block, nextBlock);
- foreach (IR::Stmt *s, _block->statements()) {
+ for (IR::Stmt *s : _block->statements()) {
if (s->location.isValid()) {
if (int(s->location.startLine) != lastLine) {
_as->loadPtr(Address(Assembler::EngineRegister, qOffsetOf(QV4::ExecutionEngine, current)), Assembler::ScratchRegister);
@@ -1682,7 +1676,7 @@ void InstructionSelection::calculateRegistersToSave(const RegisterInformation &u
regularRegistersToSave.clear();
fpRegistersToSave.clear();
- foreach (const RegisterInfo &ri, Assembler::getRegisterInfo()) {
+ for (const RegisterInfo &ri : Assembler::getRegisterInfo()) {
#if defined(RESTORE_EBX_ON_CALL)
if (ri.isRegularRegister() && ri.reg<JSC::X86Registers::RegisterID>() == JSC::X86Registers::ebx) {
regularRegistersToSave.append(ri);
diff --git a/src/qml/jit/qv4regalloc.cpp b/src/qml/jit/qv4regalloc.cpp
index deef719b67..350ab7e0c6 100644
--- a/src/qml/jit/qv4regalloc.cpp
+++ b/src/qml/jit/qv4regalloc.cpp
@@ -814,10 +814,10 @@ class ResolutionPhase
Q_DISABLE_COPY(ResolutionPhase)
LifeTimeIntervals::Ptr _intervals;
- QVector<LifeTimeInterval *> _unprocessed;
+ QVector<LifeTimeInterval *> _unprocessedReverseOrder;
IR::Function *_function;
const std::vector<int> &_assignedSpillSlots;
- QHash<IR::Temp, const LifeTimeInterval *> _intervalForTemp;
+ std::vector<const LifeTimeInterval *> _liveIntervals;
const QVector<const RegisterInfo *> &_intRegs;
const QVector<const RegisterInfo *> &_fpRegs;
@@ -825,26 +825,26 @@ class ResolutionPhase
std::vector<Move *> _loads;
std::vector<Move *> _stores;
- QHash<BasicBlock *, QList<const LifeTimeInterval *> > _liveAtStart;
- QHash<BasicBlock *, QList<const LifeTimeInterval *> > _liveAtEnd;
+ std::vector<std::vector<const LifeTimeInterval *> > _liveAtStart;
+ std::vector<std::vector<const LifeTimeInterval *> > _liveAtEnd;
public:
- ResolutionPhase(const QVector<LifeTimeInterval *> &unprocessed,
+ ResolutionPhase(QVector<LifeTimeInterval *> &&unprocessedReversedOrder,
const LifeTimeIntervals::Ptr &intervals,
IR::Function *function,
const std::vector<int> &assignedSpillSlots,
const QVector<const RegisterInfo *> &intRegs,
const QVector<const RegisterInfo *> &fpRegs)
: _intervals(intervals)
+ , _unprocessedReverseOrder(unprocessedReversedOrder)
, _function(function)
, _assignedSpillSlots(assignedSpillSlots)
, _intRegs(intRegs)
, _fpRegs(fpRegs)
, _currentStmt(0)
{
- _unprocessed = unprocessed;
- _liveAtStart.reserve(function->basicBlockCount());
- _liveAtEnd.reserve(function->basicBlockCount());
+ _liveAtStart.resize(function->basicBlockCount());
+ _liveAtEnd.resize(function->basicBlockCount());
}
void run() {
@@ -883,7 +883,7 @@ private:
cleanOldIntervals(_intervals->startPosition(bb));
addNewIntervals(_intervals->startPosition(bb));
- _liveAtStart[bb] = _intervalForTemp.values();
+ _liveAtStart[bb->index()] = _liveIntervals;
for (int i = 0, ei = statements.size(); i != ei; ++i) {
_currentStmt = statements.at(i);
@@ -905,24 +905,24 @@ private:
}
cleanOldIntervals(_intervals->endPosition(bb));
- _liveAtEnd[bb] = _intervalForTemp.values();
+ _liveAtEnd[bb->index()] = _liveIntervals;
if (DebugRegAlloc) {
QBuffer buf;
buf.open(QIODevice::WriteOnly);
QTextStream os(&buf);
os << "Intervals live at the start of L" << bb->index() << ":" << endl;
- if (_liveAtStart[bb].isEmpty())
+ if (_liveAtStart[bb->index()].empty())
os << "\t(none)" << endl;
- for (const LifeTimeInterval *i : _liveAtStart.value(bb)) {
+ for (const LifeTimeInterval *i : _liveAtStart.at(bb->index())) {
os << "\t";
i->dump(os);
os << endl;
}
os << "Intervals live at the end of L" << bb->index() << ":" << endl;
- if (_liveAtEnd[bb].isEmpty())
+ if (_liveAtEnd[bb->index()].empty())
os << "\t(none)" << endl;
- for (const LifeTimeInterval *i : _liveAtEnd.value(bb)) {
+ for (const LifeTimeInterval *i : _liveAtEnd.at(bb->index())) {
os << "\t";
i->dump(os);
os << endl;
@@ -935,9 +935,19 @@ private:
}
+ const LifeTimeInterval *findLiveInterval(Temp *t) const
+ {
+ for (const LifeTimeInterval *lti : _liveIntervals) {
+ if (lti->temp() == *t)
+ return lti;
+ }
+
+ return nullptr;
+ }
+
void maybeGenerateSpill(Temp *t)
{
- const LifeTimeInterval *i = _intervalForTemp[*t];
+ const LifeTimeInterval *i = findLiveInterval(t);
if (i->reg() == LifeTimeInterval::InvalidRegister)
return;
@@ -953,26 +963,27 @@ private:
if (position == Stmt::InvalidId)
return;
- while (!_unprocessed.isEmpty()) {
- const LifeTimeInterval *i = _unprocessed.constFirst();
+ while (!_unprocessedReverseOrder.isEmpty()) {
+ const LifeTimeInterval *i = _unprocessedReverseOrder.constLast();
if (i->start() > position)
break;
Q_ASSERT(!i->isFixedInterval());
- _intervalForTemp[i->temp()] = i;
+ _liveIntervals.push_back(i);
// qDebug() << "-- Activating interval for temp" << i->temp().index;
- _unprocessed.removeFirst();
+ _unprocessedReverseOrder.removeLast();
}
}
void cleanOldIntervals(int position)
{
- QMutableHashIterator<Temp, const LifeTimeInterval *> it(_intervalForTemp);
- while (it.hasNext()) {
- const LifeTimeInterval *i = it.next().value();
- if (i->end() < position || i->isFixedInterval())
- it.remove();
+ for (size_t it = 0; it != _liveIntervals.size(); ) {
+ const LifeTimeInterval *lti = _liveIntervals.at(it);
+ if (lti->end() < position || lti->isFixedInterval())
+ _liveIntervals.erase(_liveIntervals.begin() + it);
+ else
+ ++it;
}
}
@@ -1019,7 +1030,7 @@ private:
int successorStart = _intervals->startPosition(successor);
Q_ASSERT(successorStart > 0);
- for (const LifeTimeInterval *it : _liveAtStart.value(successor)) {
+ for (const LifeTimeInterval *it : _liveAtStart.at(successor->index())) {
bool isPhiTarget = false;
Expr *moveFrom = 0;
@@ -1033,7 +1044,7 @@ private:
Temp *t = opd->asTemp();
Q_ASSERT(t);
- for (const LifeTimeInterval *it2 : _liveAtEnd.value(predecessor)) {
+ for (const LifeTimeInterval *it2 : _liveAtEnd.at(predecessor->index())) {
if (it2->temp() == *t
&& it2->reg() != LifeTimeInterval::InvalidRegister
&& it2->covers(predecessorEnd)) {
@@ -1048,7 +1059,7 @@ private:
}
}
} else {
- for (const LifeTimeInterval *predIt : _liveAtEnd.value(predecessor)) {
+ for (const LifeTimeInterval *predIt : _liveAtEnd.at(predecessor->index())) {
if (predIt->temp() == it->temp()) {
if (predIt->reg() != LifeTimeInterval::InvalidRegister
&& predIt->covers(predecessorEnd)) {
@@ -1198,7 +1209,7 @@ private:
if (t->kind != Temp::VirtualRegister)
return;
- const LifeTimeInterval *i = _intervalForTemp[*t];
+ const LifeTimeInterval *i = findLiveInterval(t);
Q_ASSERT(i->isValid());
if (_currentStmt != 0 && i->start() == usePosition(_currentStmt)) {
@@ -1314,8 +1325,13 @@ void RegisterAllocator::run(IR::Function *function, const Optimizer &opt)
if (DebugRegAlloc)
dump(function);
- std::sort(_handled.begin(), _handled.end(), LifeTimeInterval::lessThan);
- ResolutionPhase(_handled, _lifeTimeIntervals, function, _assignedSpillSlots, _normalRegisters, _fpRegisters).run();
+ // sort the ranges in reverse order, so the ResolutionPhase can take from the end (and thereby
+ // prevent the copy overhead that taking from the beginning would give).
+ std::sort(_handled.begin(), _handled.end(),
+ [](const LifeTimeInterval *r1, const LifeTimeInterval *r2) -> bool {
+ return LifeTimeInterval::lessThan(r2, r1);
+ });
+ ResolutionPhase(std::move(_handled), _lifeTimeIntervals, function, _assignedSpillSlots, _normalRegisters, _fpRegisters).run();
function->tempCount = *std::max_element(_assignedSpillSlots.begin(), _assignedSpillSlots.end()) + 1;
diff --git a/src/qml/jit/qv4targetplatform_p.h b/src/qml/jit/qv4targetplatform_p.h
index 6f0a7374c3..7e265258d5 100644
--- a/src/qml/jit/qv4targetplatform_p.h
+++ b/src/qml/jit/qv4targetplatform_p.h
@@ -563,7 +563,7 @@ public:
#endif // Linux on MIPS (32 bit)
public: // utility functions
- static RegisterInformation getRegisterInfo()
+ static const RegisterInformation getRegisterInfo()
{
static const RegisterInformation info = getPlatformRegisterInfo();
diff --git a/src/qml/jsruntime/qv4numberobject.cpp b/src/qml/jsruntime/qv4numberobject.cpp
index d27eef1d79..f8e0d8763b 100644
--- a/src/qml/jsruntime/qv4numberobject.cpp
+++ b/src/qml/jsruntime/qv4numberobject.cpp
@@ -285,12 +285,30 @@ ReturnedValue NumberPrototype::method_toPrecision(CallContext *ctx)
if (!ctx->argc() || ctx->args()[0].isUndefined())
return RuntimeHelpers::toString(scope.engine, v);
- double precision = ctx->args()[0].toInt32();
+ int precision = ctx->args()[0].toInt32();
if (precision < 1 || precision > 21) {
ScopedString error(scope, scope.engine->newString(QStringLiteral("Number.prototype.toPrecision: precision out of range")));
return ctx->engine()->throwRangeError(error);
}
- QString result = NumberLocale::instance()->toString(v->asDouble(), 'g', precision);
+ // TODO: Once we get a NumberOption to retain trailing zeroes, replace the code below with:
+ // QString result = NumberLocale::instance()->toString(v->asDouble(), 'g', precision);
+ QByteArray format = "%#." + QByteArray::number(precision) + "g";
+ QString result = QString::asprintf(format.constData(), v->asDouble());
+ if (result.endsWith(QLatin1Char('.'))) {
+ // This is 'f' notation, not 'e'.
+ result.chop(1);
+ } else {
+ int ePos = result.indexOf(QLatin1Char('e'));
+ if (ePos != -1) {
+ Q_ASSERT(ePos + 2 < result.length()); // always '+' or '-', and number, after 'e'
+ Q_ASSERT(ePos > 0); // 'e' is not the first character
+
+ if (result.at(ePos + 2) == QLatin1Char('0')) // Drop leading zeroes in exponent
+ result = result.remove(ePos + 2, 1);
+ if (result.at(ePos - 1) == QLatin1Char('.')) // Drop trailing dots before 'e'
+ result = result.remove(ePos - 1, 1);
+ }
+ }
return scope.engine->newString(result)->asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 633c5f60c9..9462101a2a 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -44,7 +44,6 @@
#include <private/qqmlvmemetaobject_p.h>
#include <private/qqmlbinding_p.h>
#include <private/qjsvalue_p.h>
-#include <private/qqmlaccessors_p.h>
#include <private/qqmlexpression_p.h>
#include <private/qqmlglobal_p.h>
#include <private/qqmltypewrapper_p.h>
@@ -115,93 +114,57 @@ static QPair<QObject *, int> extractQtSignal(const Value &value)
return qMakePair((QObject *)0, -1);
}
-
-struct ReadAccessor {
- static inline void Indirect(QObject *object, const QQmlPropertyData &property,
- void *output, QQmlNotifier **n)
- {
- Q_ASSERT(n == 0);
- Q_UNUSED(n);
-
- void *args[] = { output, 0 };
- QMetaObject::metacall(object, QMetaObject::ReadProperty, property.coreIndex(), args);
- }
-
- static inline void Direct(QObject *object, const QQmlPropertyData &property,
- void *output, QQmlNotifier **n)
- {
- Q_ASSERT(n == 0);
- Q_UNUSED(n);
-
- void *args[] = { output, 0 };
- object->qt_metacall(QMetaObject::ReadProperty, property.coreIndex(), args);
- }
-
- static inline void Accessor(QObject *object, const QQmlPropertyData &property,
- void *output, QQmlNotifier **n)
- {
- Q_ASSERT(property.accessors());
-
- property.accessors()->read(object, output);
- if (n) property.accessors()->notifier(object, n);
- }
-};
-
-// Load value properties
-template<void (*ReadFunction)(QObject *, const QQmlPropertyData &,
- void *, QQmlNotifier **)>
-static QV4::ReturnedValue LoadProperty(QV4::ExecutionEngine *v4, QObject *object,
- const QQmlPropertyData &property,
- QQmlNotifier **notifier)
+static QV4::ReturnedValue loadProperty(QV4::ExecutionEngine *v4, QObject *object,
+ const QQmlPropertyData &property)
{
Q_ASSERT(!property.isFunction());
QV4::Scope scope(v4);
if (property.isQObject()) {
QObject *rv = 0;
- ReadFunction(object, property, &rv, notifier);
+ property.readProperty(object, &rv);
return QV4::QObjectWrapper::wrap(v4, rv);
} else if (property.isQList()) {
return QmlListWrapper::create(v4, object, property.coreIndex(), property.propType());
} else if (property.propType() == QMetaType::QReal) {
qreal v = 0;
- ReadFunction(object, property, &v, notifier);
+ property.readProperty(object, &v);
return QV4::Encode(v);
} else if (property.propType() == QMetaType::Int || property.isEnum()) {
int v = 0;
- ReadFunction(object, property, &v, notifier);
+ property.readProperty(object, &v);
return QV4::Encode(v);
} else if (property.propType() == QMetaType::Bool) {
bool v = false;
- ReadFunction(object, property, &v, notifier);
+ property.readProperty(object, &v);
return QV4::Encode(v);
} else if (property.propType() == QMetaType::QString) {
QString v;
- ReadFunction(object, property, &v, notifier);
+ property.readProperty(object, &v);
return v4->newString(v)->asReturnedValue();
} else if (property.propType() == QMetaType::UInt) {
uint v = 0;
- ReadFunction(object, property, &v, notifier);
+ property.readProperty(object, &v);
return QV4::Encode(v);
} else if (property.propType() == QMetaType::Float) {
float v = 0;
- ReadFunction(object, property, &v, notifier);
+ property.readProperty(object, &v);
return QV4::Encode(v);
} else if (property.propType() == QMetaType::Double) {
double v = 0;
- ReadFunction(object, property, &v, notifier);
+ property.readProperty(object, &v);
return QV4::Encode(v);
} else if (property.isV4Handle()) {
QQmlV4Handle handle;
- ReadFunction(object, property, &handle, notifier);
+ property.readProperty(object, &handle);
return handle;
} else if (property.propType() == qMetaTypeId<QJSValue>()) {
QJSValue v;
- ReadFunction(object, property, &v, notifier);
+ property.readProperty(object, &v);
return QJSValuePrivate::convertedToValue(v4, v);
} else if (property.isQVariant()) {
QVariant v;
- ReadFunction(object, property, &v, notifier);
+ property.readProperty(object, &v);
if (QQmlValueTypeFactory::isValueType(v.userType())) {
if (const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(v.userType()))
@@ -210,13 +173,9 @@ static QV4::ReturnedValue LoadProperty(QV4::ExecutionEngine *v4, QObject *object
return scope.engine->fromVariant(v);
} else if (QQmlValueTypeFactory::isValueType(property.propType())) {
- Q_ASSERT(notifier == 0);
-
if (const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(property.propType()))
return QV4::QQmlValueTypeWrapper::create(v4, object, property.coreIndex(), valueTypeMetaObject, property.propType());
} else {
- Q_ASSERT(notifier == 0);
-
// see if it's a sequence type
bool succeeded = false;
QV4::ScopedValue retn(scope, QV4::SequencePrototype::newSequence(v4, property.propType(), object, property.coreIndex(), &succeeded));
@@ -231,7 +190,7 @@ static QV4::ReturnedValue LoadProperty(QV4::ExecutionEngine *v4, QObject *object
return QV4::Encode::undefined();
} else {
QVariant v(property.propType(), (void *)0);
- ReadFunction(object, property, v.data(), notifier);
+ property.readProperty(object, v.data());
return scope.engine->fromVariant(v);
}
}
@@ -352,29 +311,6 @@ ReturnedValue QObjectWrapper::getProperty(ExecutionEngine *engine, QObject *obje
QQmlEnginePrivate *ep = engine->qmlEngine() ? QQmlEnginePrivate::get(engine->qmlEngine()) : 0;
- if (property->hasAccessors()) {
- QQmlNotifier *n = 0;
- QQmlNotifier **nptr = 0;
-
- if (ep && ep->propertyCapture && property->accessors()->notifier)
- nptr = &n;
-
- Scope scope(engine);
- QV4::ScopedValue rv(scope, LoadProperty<ReadAccessor::Accessor>(engine, object, *property, nptr));
-
- if (captureRequired && !property->isConstant()) {
- if (property->accessors()->notifier) {
- if (n && ep->propertyCapture)
- ep->propertyCapture->captureProperty(n);
- } else {
- if (ep->propertyCapture)
- ep->propertyCapture->captureProperty(object, property->coreIndex(), property->notifyIndex());
- }
- }
-
- return rv->asReturnedValue();
- }
-
if (captureRequired && ep && ep->propertyCapture && !property->isConstant())
ep->propertyCapture->captureProperty(object, property->coreIndex(), property->notifyIndex());
@@ -382,10 +318,8 @@ ReturnedValue QObjectWrapper::getProperty(ExecutionEngine *engine, QObject *obje
QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(object);
Q_ASSERT(vmemo);
return vmemo->vmeProperty(property->coreIndex());
- } else if (property->isDirect()) {
- return LoadProperty<ReadAccessor::Direct>(engine, object, *property, 0);
} else {
- return LoadProperty<ReadAccessor::Indirect>(engine, object, *property, 0);
+ return loadProperty(engine, object, *property);
}
}
diff --git a/src/qml/qml/qml.pri b/src/qml/qml/qml.pri
index 87be140cbb..4244b16210 100644
--- a/src/qml/qml/qml.pri
+++ b/src/qml/qml/qml.pri
@@ -49,7 +49,8 @@ SOURCES += \
$$PWD/qqmlfileselector.cpp \
$$PWD/qqmlobjectcreator.cpp \
$$PWD/qqmldirparser.cpp \
- $$PWD/qqmldelayedcallqueue.cpp
+ $$PWD/qqmldelayedcallqueue.cpp \
+ $$PWD/qqmlloggingcategory.cpp
HEADERS += \
$$PWD/qqmlglobal_p.h \
@@ -121,7 +122,8 @@ HEADERS += \
$$PWD/qqmlfileselector.h \
$$PWD/qqmlobjectcreator_p.h \
$$PWD/qqmldirparser_p.h \
- $$PWD/qqmldelayedcallqueue_p.h
+ $$PWD/qqmldelayedcallqueue_p.h \
+ $$PWD/qqmlloggingcategory_p.h
include(ftw/ftw.pri)
include(v8/v8.pri)
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index 0cc96be5a8..7e4fe73ba1 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -89,6 +89,7 @@
#include <private/qqmlobjectmodel_p.h>
#include <private/qquickworkerscript_p.h>
#include <private/qqmlinstantiator_p.h>
+#include <private/qqmlloggingcategory_p.h>
#ifdef Q_OS_WIN // for %APPDATA%
# include <qt_windows.h>
@@ -187,6 +188,7 @@ void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int
qmlRegisterType<QQmlInstantiator>(uri, versionMajor, (versionMinor < 1 ? 1 : versionMinor), "Instantiator"); //Only available in >=2.1
qmlRegisterCustomType<QQmlConnections>(uri, versionMajor, versionMinor,"Connections", new QQmlConnectionsParser);
qmlRegisterType<QQmlInstanceModel>();
+ qmlRegisterType<QQmlLoggingCategory>(uri, versionMajor, (versionMinor < 8 ? 8 : versionMinor), "LoggingCategory"); //Only available in >=2.8
}
diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp
index 4b54123892..ebc4d49c36 100644
--- a/src/qml/qml/qqmljavascriptexpression.cpp
+++ b/src/qml/qml/qqmljavascriptexpression.cpp
@@ -235,7 +235,7 @@ void QQmlPropertyCapture::captureProperty(QQmlNotifier *n, Duration duration)
g->connect(n);
}
- if (duration == OnlyOnce)
+ if (duration == Permanently)
expression->permanentGuards.prepend(g);
else
expression->activeGuards.prepend(g);
diff --git a/src/qml/qml/qqmlloggingcategory.cpp b/src/qml/qml/qqmlloggingcategory.cpp
new file mode 100644
index 0000000000..88cf14cba0
--- /dev/null
+++ b/src/qml/qml/qqmlloggingcategory.cpp
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmlloggingcategory_p.h"
+
+#include <QtQml/qqmlinfo.h>
+
+/*!
+ \qmltype LoggingCategory
+ \ingroup qml-utility-elements
+ \inqmlmodule QtQml
+ \brief Defines a logging category in QML
+ \since 5.8
+
+ A logging category can be passed to console.log() and friends as the first argument.
+ If supplied to to the logger the LoggingCategory's name will be used as Logging Category
+ otherwise the default logging category will be used.
+
+ \qml
+ import QtQuick 2.8
+
+ Item {
+ LoggingCategory {
+ id: category
+ name: "com.qt.category"
+ }
+
+ Component.onCompleted: {
+ console.log(category, "message");
+ }
+ }
+ \endqml
+
+ \note As the creation of objects is expensive, it is encouraged to put the needed
+ LoggingCategory definitions into a singleton and import this where needed.
+
+ \sa QLoggingCategory
+*/
+
+/*!
+ \qmlproperty string QtQml::LoggingCategory::name
+
+ Holds the name of the logging category.
+
+ \note This property needs to be set when declaring the LoggingCategory
+ and cannot be changed later.
+
+ \sa QLoggingCategory::name()
+*/
+
+QQmlLoggingCategory::QQmlLoggingCategory(QObject *parent)
+ : QObject(parent)
+ , m_initialized(false)
+{
+}
+
+QQmlLoggingCategory::~QQmlLoggingCategory()
+{
+}
+
+QString QQmlLoggingCategory::name() const
+{
+ return QString::fromUtf8(m_name);
+}
+
+QLoggingCategory *QQmlLoggingCategory::category() const
+{
+ return m_category.data();
+}
+
+void QQmlLoggingCategory::classBegin()
+{
+}
+
+void QQmlLoggingCategory::componentComplete()
+{
+ m_initialized = true;
+ if (m_name.isNull())
+ qmlInfo(this) << QString(QLatin1String("Declaring the name of the LoggingCategory is mandatory and cannot be changed later !"));
+}
+
+void QQmlLoggingCategory::setName(const QString &name)
+{
+ if (m_initialized) {
+ qmlInfo(this) << QString(QLatin1String("The name of a LoggingCategory cannot be changed after the Item is created"));
+ return;
+ }
+
+ m_name = name.toUtf8();
+ QScopedPointer<QLoggingCategory> category(new QLoggingCategory(m_name.constData()));
+ m_category.swap(category);
+}
diff --git a/src/qml/qml/qqmlloggingcategory_p.h b/src/qml/qml/qqmlloggingcategory_p.h
new file mode 100644
index 0000000000..2b7f2f5b53
--- /dev/null
+++ b/src/qml/qml/qqmlloggingcategory_p.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLLOGGINGCATEGORY_P_H
+#define QQMLLOGGINGCATEGORY_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qobject.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qloggingcategory.h>
+
+#include <QtQml/qqmlparserstatus.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlLoggingCategory : public QObject, public QQmlParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QQmlParserStatus)
+
+ Q_PROPERTY(QString name READ name WRITE setName)
+
+public:
+ QQmlLoggingCategory(QObject *parent = 0);
+ virtual ~QQmlLoggingCategory();
+
+ QString name() const;
+ void setName(const QString &name);
+
+ QLoggingCategory *category() const;
+
+ void classBegin() override;
+ void componentComplete() override;
+
+private:
+ QByteArray m_name;
+ QScopedPointer<QLoggingCategory> m_category;
+ bool m_initialized;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLLOGGINGCATEGORY_H
diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp
index 5c53e342f3..ed00eddb30 100644
--- a/src/qml/qml/qqmlpropertycache.cpp
+++ b/src/qml/qml/qqmlpropertycache.cpp
@@ -150,7 +150,7 @@ void QQmlPropertyData::lazyLoad(const QMetaProperty &p)
Q_ASSERT(p.revision() <= Q_INT16_MAX);
setRevision(p.revision());
- _flags = fastFlagsForProperty(p);
+ setFlags(fastFlagsForProperty(p));
int type = static_cast<int>(p.type());
if (type == QMetaType::QObjectStar) {
@@ -171,7 +171,7 @@ void QQmlPropertyData::load(const QMetaProperty &p, QQmlEngine *engine)
setPropType(p.userType());
setCoreIndex(p.propertyIndex());
setNotifyIndex(QMetaObjectPrivate::signalIndex(p.notifySignal()));
- _flags = fastFlagsForProperty(p);
+ setFlags(fastFlagsForProperty(p));
flagsForPropertyType(propType(), engine, _flags);
Q_ASSERT(p.revision() <= Q_INT16_MAX);
setRevision(p.revision());
@@ -344,7 +344,7 @@ void QQmlPropertyCache::appendProperty(const QString &name, QQmlPropertyData::Fl
data.setPropType(propType);
data.setCoreIndex(coreIndex);
data.setNotifyIndex(notifyIndex);
- data._flags = flags;
+ data.setFlags(flags);
QQmlPropertyData *old = findNamedProperty(name);
if (old)
@@ -363,7 +363,7 @@ void QQmlPropertyCache::appendSignal(const QString &name, QQmlPropertyData::Flag
QQmlPropertyData data;
data.setPropType(QVariant::Invalid);
data.setCoreIndex(coreIndex);
- data._flags = flags;
+ data.setFlags(flags);
data.setArguments(nullptr);
QQmlPropertyData handler = data;
@@ -409,7 +409,7 @@ void QQmlPropertyCache::appendMethod(const QString &name, QQmlPropertyData::Flag
args->argumentsValid = true;
data.setArguments(args);
- data._flags = flags;
+ data.setFlags(flags);
QQmlPropertyData *old = findNamedProperty(name);
if (old)
@@ -568,9 +568,9 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject,
QQmlPropertyData *sigdata = 0;
if (m.methodType() == QMetaMethod::Signal)
- data->_flags = signalFlags;
+ data->setFlags(signalFlags);
else
- data->_flags = methodFlags;
+ data->setFlags(methodFlags);
data->lazyLoad(m);
data->_flags.isDirect = !dynamicMetaObject;
@@ -650,7 +650,7 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject,
QQmlPropertyData *data = &propertyIndexCache[ii - propertyIndexCacheStart];
- data->_flags = propertyFlags;
+ data->setFlags(propertyFlags);
data->lazyLoad(p);
data->_flags.isDirect = !dynamicMetaObject;
@@ -672,16 +672,18 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject,
setNamedProperty(propName, ii, data, (old != 0));
}
- QQmlAccessorProperties::Property *accessorProperty = accessorProperties.property(str);
-
- // Fast properties may not be overrides or revisioned
- Q_ASSERT(accessorProperty == 0 || (old == 0 && data->revision() == 0));
+ bool isGadget = true;
+ for (const QMetaObject *it = metaObject; it != nullptr; it = it->superClass()) {
+ if (it == &QObject::staticMetaObject)
+ isGadget = false;
+ }
- if (accessorProperty) {
- data->setAccessors(accessorProperty->accessors);
- } else if (old) {
+ if (isGadget) // always dispatch over a 'normal' meta-call so the QQmlValueType can intercept
+ data->_flags.isDirect = false;
+ else
+ data->trySetStaticMetaCallFunction(metaObject->d.static_metacall, ii - propOffset);
+ if (old)
data->markAsOverrideOf(old);
- }
}
}
diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h
index 63a9c63d90..f28b2d0599 100644
--- a/src/qml/qml/qqmlpropertycache_p.h
+++ b/src/qml/qml/qqmlpropertycache_p.h
@@ -86,6 +86,8 @@ template <typename T> class QQmlPropertyCacheAliasCreator;
class QQmlPropertyRawData
{
public:
+ typedef QObjectPrivate::StaticMetaCallFunction StaticMetaCallFunction;
+
struct Flags {
enum Types {
OtherType = 0,
@@ -100,6 +102,14 @@ public:
QVariantType = 9 // Property is a QVariant
};
+ // The _otherBits (which "pad" the Flags struct to align it nicely) are used
+ // to store the relative property index. It will only get used when said index fits. See
+ // trySetStaticMetaCallFunction for details.
+ // (Note: this padding is done here, because certain compilers have surprising behavior
+ // when an enum is declared in-between two bit fields.)
+ enum { BitsLeftInFlags = 10 };
+ unsigned _otherBits : BitsLeftInFlags; // align to 32 bits
+
// Can apply to all properties, except IsFunction
unsigned isConstant : 1; // Has CONST flag
unsigned isWritable : 1; // Has WRITE function
@@ -126,15 +136,18 @@ public:
unsigned notFullyResolved : 1; // True if the type data is to be lazily resolved
unsigned overrideIndexIsProperty: 1;
- unsigned _padding : 10; // align to 32 bits
-
inline Flags();
inline bool operator==(const Flags &other) const;
inline void copyPropertyTypeFlags(Flags from);
};
Flags flags() const { return _flags; }
- void setFlags(Flags f) { _flags = f; }
+ void setFlags(Flags f)
+ {
+ unsigned otherBits = _flags._otherBits;
+ _flags = f;
+ _flags._otherBits = otherBits;
+ }
bool isValid() const { return coreIndex() != -1; }
@@ -147,6 +160,7 @@ public:
bool isOverridden() const { return _flags.isOverridden; }
bool isDirect() const { return _flags.isDirect; }
bool hasAccessors() const { return accessors() != nullptr; }
+ bool hasStaticMetaCallFunction() const { return staticMetaCallFunction() != nullptr; }
bool isFunction() const { return _flags.type == Flags::FunctionType; }
bool isQObject() const { return _flags.type == Flags::QObjectDerivedType; }
bool isEnum() const { return _flags.type == Flags::EnumType; }
@@ -226,8 +240,17 @@ public:
_metaObjectOffset = qint16(off);
}
- QQmlAccessors *accessors() const { return _accessors; }
- void setAccessors(QQmlAccessors *acc) { _accessors = acc; }
+ QQmlAccessors *accessors() const { return nullptr; } // TODO: remove in subsequent patch
+
+ StaticMetaCallFunction staticMetaCallFunction() const { return _staticMetaCallFunction; }
+ void trySetStaticMetaCallFunction(StaticMetaCallFunction f, unsigned relativePropertyIndex)
+ {
+ if (relativePropertyIndex < (1 << Flags::BitsLeftInFlags) - 1) {
+ _flags._otherBits = relativePropertyIndex;
+ _staticMetaCallFunction = f;
+ }
+ }
+ quint16 relativePropertyIndex() const { Q_ASSERT(hasStaticMetaCallFunction()); return _flags._otherBits; }
private:
Flags _flags;
@@ -243,7 +266,7 @@ private:
qint16 _metaObjectOffset;
QQmlPropertyCacheMethodArguments *_arguments;
- QQmlAccessors *_accessors;
+ StaticMetaCallFunction _staticMetaCallFunction;
friend class QQmlPropertyData;
friend class QQmlPropertyCache;
@@ -286,22 +309,24 @@ public:
inline void readPropertyWithArgs(QObject *target, void *args[]) const
{
- if (hasAccessors()) {
- accessors()->read(target, args[0]);
- } else {
+ if (hasStaticMetaCallFunction())
+ staticMetaCallFunction()(target, QMetaObject::ReadProperty, relativePropertyIndex(), args);
+ else if (isDirect())
+ target->qt_metacall(QMetaObject::ReadProperty, coreIndex(), args);
+ else
QMetaObject::metacall(target, QMetaObject::ReadProperty, coreIndex(), args);
- }
}
bool writeProperty(QObject *target, void *value, WriteFlags flags) const
{
- if (flags.testFlag(BypassInterceptor) && hasAccessors() && accessors()->write) {
- accessors()->write(target, value);
- } else {
- int status = -1;
- void *argv[] = { value, 0, &status, &flags };
+ int status = -1;
+ void *argv[] = { value, 0, &status, &flags };
+ if (flags.testFlag(BypassInterceptor) && hasStaticMetaCallFunction())
+ staticMetaCallFunction()(target, QMetaObject::WriteProperty, relativePropertyIndex(), argv);
+ else if (flags.testFlag(BypassInterceptor) && isDirect())
+ target->qt_metacall(QMetaObject::WriteProperty, coreIndex(), argv);
+ else
QMetaObject::metacall(target, QMetaObject::WriteProperty, coreIndex(), argv);
- }
return true;
}
@@ -568,7 +593,8 @@ public:
};
QQmlPropertyRawData::Flags::Flags()
- : isConstant(false)
+ : _otherBits(0)
+ , isConstant(false)
, isWritable(false)
, isResettable(false)
, isAlias(false)
@@ -587,7 +613,6 @@ QQmlPropertyRawData::Flags::Flags()
, isConstructor(false)
, notFullyResolved(false)
, overrideIndexIsProperty(false)
- , _padding(0)
{}
bool QQmlPropertyRawData::Flags::operator==(const QQmlPropertyRawData::Flags &other) const
@@ -635,7 +660,7 @@ QQmlPropertyData::QQmlPropertyData()
setRevision(0);
setMetaObjectOffset(-1);
setArguments(nullptr);
- setAccessors(nullptr);
+ trySetStaticMetaCallFunction(nullptr, 0);
}
QQmlPropertyData::QQmlPropertyData(const QQmlPropertyRawData &d)
@@ -645,7 +670,7 @@ QQmlPropertyData::QQmlPropertyData(const QQmlPropertyRawData &d)
bool QQmlPropertyData::operator==(const QQmlPropertyRawData &other)
{
- return _flags == other._flags &&
+ return flags() == other.flags() &&
propType() == other.propType() &&
coreIndex() == other.coreIndex() &&
notifyIndex() == other.notifyIndex() &&
@@ -752,7 +777,7 @@ QQmlPropertyCache::overrideData(QQmlPropertyData *data) const
bool QQmlPropertyCache::isAllowedInRevision(QQmlPropertyData *data) const
{
- return (data->hasAccessors() || (data->metaObjectOffset() == -1 && data->revision() == 0)) ||
+ return (data->metaObjectOffset() == -1 && data->revision() == 0) ||
(allowedRevisionCache[data->metaObjectOffset()] >= data->revision());
}
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
index fd36f76d0e..5d70b17ece 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -42,6 +42,7 @@
#include <QtQml/qqmlcomponent.h>
#include <private/qqmlengine_p.h>
#include <private/qqmlcomponent_p.h>
+#include <private/qqmlloggingcategory_p.h>
#include <private/qqmlstringconverters_p.h>
#include <private/qqmllocale_p.h>
#include <private/qv8engine_p.h>
@@ -76,6 +77,8 @@
#include <QtCore/qcoreapplication.h>
#include <QtCore/qloggingcategory.h>
+#include <QDebug>
+
QT_BEGIN_NAMESPACE
using namespace QV4;
@@ -1491,11 +1494,26 @@ static QString jsStack(QV4::ExecutionEngine *engine) {
static QV4::ReturnedValue writeToConsole(ConsoleLogTypes logType, CallContext *ctx,
bool printStack = false)
{
+ QLoggingCategory *loggingCategory = 0;
QString result;
QV4::ExecutionEngine *v4 = ctx->d()->engine;
- for (int i = 0; i < ctx->argc(); ++i) {
- if (i != 0)
+ int start = 0;
+ if (ctx->argc() > 0) {
+ if (const QObjectWrapper* wrapper = ctx->args()[0].as<QObjectWrapper>()) {
+ if (QQmlLoggingCategory* category = qobject_cast<QQmlLoggingCategory*>(wrapper->object())) {
+ if (category->category())
+ loggingCategory = category->category();
+ else
+ V4THROW_ERROR("A QmlLoggingCatgory was provided without a valid name");
+ start = 1;
+ }
+ }
+ }
+
+
+ for (int i = start; i < ctx->argc(); ++i) {
+ if (i != start)
result.append(QLatin1Char(' '));
if (ctx->args()[i].as<ArrayObject>())
@@ -1510,7 +1528,8 @@ static QV4::ReturnedValue writeToConsole(ConsoleLogTypes logType, CallContext *c
static QLoggingCategory qmlLoggingCategory("qml");
static QLoggingCategory jsLoggingCategory("js");
- QLoggingCategory *loggingCategory = v4->qmlEngine() ? &qmlLoggingCategory : &jsLoggingCategory;
+ if (!loggingCategory)
+ loggingCategory = v4->qmlEngine() ? &qmlLoggingCategory : &jsLoggingCategory;
QV4::StackFrame frame = v4->currentStackFrame();
const QByteArray baSource = frame.source.toUtf8();
const QByteArray baFunction = frame.function.toUtf8();
diff --git a/src/quick/doc/src/concepts/visualcanvas/adaptations.qdoc b/src/quick/doc/src/concepts/visualcanvas/adaptations.qdoc
index bbc64f1484..9ce26e1bb8 100644
--- a/src/quick/doc/src/concepts/visualcanvas/adaptations.qdoc
+++ b/src/quick/doc/src/concepts/visualcanvas/adaptations.qdoc
@@ -150,7 +150,7 @@ develpoment files are present. In practice this currently means Visual Studio
The adaptation is available both in normal, OpenGL-enabled Qt builds and also
when Qt was configured with \c{-no-opengl}. However, it is never the default,
meaning the user or the application has to explicitly request it by setting the
-\c{QT_QUICK_BACKEND} environment variable or by calling
+\c{QT_QUICK_BACKEND} environment variable to \c{d3d12} or by calling
QQuickWindow::setSceneGraphBackend().
\section2 Motivation
@@ -165,7 +165,7 @@ vendor-supported solution. This means that there are fewer problems anticipated
with drivers, operations like window resizes, and special events like graphics
device loss caused by device resets or graphics driver updates.
-Peformance-wise the general expectation is a somewhat lower CPU usage compared
+Performance-wise the general expectation is a somewhat lower CPU usage compared
to OpenGL due to lower driver overhead, and a higher GPU utilization with less
wasted idle time. The backend does not heavily utilize threads yet, which means
there are opportunities for further improvements in the future, for example to
diff --git a/src/quick/items/context2d/qquickcontext2d_p.h b/src/quick/items/context2d/qquickcontext2d_p.h
index cfb62ee052..b526c8320d 100644
--- a/src/quick/items/context2d/qquickcontext2d_p.h
+++ b/src/quick/items/context2d/qquickcontext2d_p.h
@@ -126,8 +126,8 @@ public:
struct State {
State()
- : strokeStyle(QColor("#000000"))
- , fillStyle(QColor("#000000"))
+ : strokeStyle(QColor(Qt::black))
+ , fillStyle(QColor(Qt::black))
, fillPatternRepeatX(false)
, fillPatternRepeatY(false)
, strokePatternRepeatX(false)
diff --git a/src/quick/items/qquickframebufferobject.cpp b/src/quick/items/qquickframebufferobject.cpp
index d8147a48a5..857cd44b15 100644
--- a/src/quick/items/qquickframebufferobject.cpp
+++ b/src/quick/items/qquickframebufferobject.cpp
@@ -44,6 +44,7 @@
#include <private/qquickitem_p.h>
#include <QSGSimpleTextureNode>
+#include <QSGRendererInterface>
QT_BEGIN_NAMESPACE
@@ -260,6 +261,12 @@ public:
int devicePixelRatio;
};
+static inline bool isOpenGL(QSGRenderContext *rc)
+{
+ QSGRendererInterface *rif = rc->sceneGraphContext()->rendererInterface(rc);
+ return !rif || rif->graphicsApi() == QSGRendererInterface::OpenGL;
+}
+
/*!
* \internal
*/
@@ -278,6 +285,8 @@ QSGNode *QQuickFramebufferObject::updatePaintNode(QSGNode *node, UpdatePaintNode
Q_D(QQuickFramebufferObject);
if (!n) {
+ if (!isOpenGL(d->sceneGraphRenderContext()))
+ return 0;
if (!d->node)
d->node = new QSGFramebufferObjectNode;
n = d->node;
@@ -360,6 +369,8 @@ QSGTextureProvider *QQuickFramebufferObject::textureProvider() const
qWarning("QQuickFramebufferObject::textureProvider: can only be queried on the rendering thread of an exposed window");
return 0;
}
+ if (!isOpenGL(d->sceneGraphRenderContext()))
+ return 0;
if (!d->node)
d->node = new QSGFramebufferObjectNode;
return d->node;
diff --git a/src/quick/items/qquickrectangle.cpp b/src/quick/items/qquickrectangle.cpp
index 223976c32f..9e747f2c47 100644
--- a/src/quick/items/qquickrectangle.cpp
+++ b/src/quick/items/qquickrectangle.cpp
@@ -72,7 +72,7 @@ QT_BEGIN_NAMESPACE
QQuickPen::QQuickPen(QObject *parent)
: QObject(parent)
, m_width(1)
- , m_color("#000000")
+ , m_color(Qt::black)
, m_aligned(true)
, m_valid(false)
{
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index a54d6daf9c..c72565b2f4 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -2247,8 +2247,12 @@ bool QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, QQuickPo
me->accept();
q->sendEvent(item, me);
if (me->isAccepted()) {
- if (!q->mouseGrabberItem())
+ auto mouseGrabber = q->mouseGrabberItem();
+ if (mouseGrabber && mouseGrabber != item) {
+ item->mouseUngrabEvent();
+ } else {
item->grabMouse();
+ }
point->setAccepted(true);
}
return me->isAccepted();
diff --git a/src/quick/scenegraph/qsgcontext_p.h b/src/quick/scenegraph/qsgcontext_p.h
index 43cf1c28ab..899278843e 100644
--- a/src/quick/scenegraph/qsgcontext_p.h
+++ b/src/quick/scenegraph/qsgcontext_p.h
@@ -139,7 +139,8 @@ public Q_SLOTS:
void textureFactoryDestroyed(QObject *o);
protected:
- QSGContext *m_sg;
+ // Hold m_sg with QPointer in the rare case it gets deleted before us.
+ QPointer<QSGContext> m_sg;
QMutex m_mutex;
QHash<QQuickTextureFactory *, QSGTexture *> m_textures;
diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
index 7c2663d5a3..3501f30487 100644
--- a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
+++ b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
@@ -41,6 +41,7 @@
#include <private/qsgmaterialshader_p.h>
#include <qopenglshaderprogram.h>
+#include <qopenglframebufferobject.h>
#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qplatformintegration.h>
@@ -210,6 +211,7 @@ public:
void activate();
void deactivate();
+ bool useSRGB() const;
uint m_useSRGB : 1;
};
@@ -229,11 +231,26 @@ void QSG24BitTextMaskShader::initialize()
}
}
+bool QSG24BitTextMaskShader::useSRGB() const
+{
+#ifdef Q_OS_MACOS
+ if (!m_useSRGB)
+ return false;
+
+ // m_useSRGB is true, but if some QOGLFBO was bound check it's texture format:
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ QOpenGLFramebufferObject *qfbo = QOpenGLContextPrivate::get(ctx)->qgl_current_fbo;
+ return !qfbo || qfbo->format().internalTextureFormat() == GL_SRGB8_ALPHA8_EXT;
+#else
+ return m_useSRGB;
+#endif
+}
+
void QSG24BitTextMaskShader::activate()
{
QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions();
funcs->glBlendFunc(GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_COLOR);
- if (m_useSRGB)
+ if (useSRGB())
funcs->glEnable(GL_FRAMEBUFFER_SRGB);
}
@@ -241,7 +258,7 @@ void QSG24BitTextMaskShader::deactivate()
{
QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions();
funcs->glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- if (m_useSRGB)
+ if (useSRGB())
funcs->glDisable(GL_FRAMEBUFFER_SRGB);
}
@@ -266,7 +283,7 @@ void QSG24BitTextMaskShader::updateState(const RenderState &state, QSGMaterial *
if (oldMaterial == 0 || material->color() != oldMaterial->color() || state.isOpacityDirty()) {
QVector4D color = material->color();
- if (m_useSRGB)
+ if (useSRGB())
color = qt_sRGB_to_linear_RGB(color);
QOpenGLContext::currentContext()->functions()->glBlendColor(color.x(), color.y(), color.z(), color.w());
color = qsg_premultiply(color, state.opacity());
diff --git a/src/quick/scenegraph/qsgdefaultrendercontext.cpp b/src/quick/scenegraph/qsgdefaultrendercontext.cpp
index 4fcc81fb18..6f10611ba3 100644
--- a/src/quick/scenegraph/qsgdefaultrendercontext.cpp
+++ b/src/quick/scenegraph/qsgdefaultrendercontext.cpp
@@ -70,6 +70,9 @@ QSGDefaultRenderContext::QSGDefaultRenderContext(QSGContext *context)
*/
void QSGDefaultRenderContext::initialize(void *context)
{
+ if (!m_sg)
+ return;
+
QOpenGLContext *openglContext = static_cast<QOpenGLContext *>(context);
QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions();
@@ -163,7 +166,8 @@ void QSGDefaultRenderContext::invalidate()
m_gl->setProperty(QSG_RENDERCONTEXT_PROPERTY, QVariant());
m_gl = 0;
- m_sg->renderContextInvalidated(this);
+ if (m_sg)
+ m_sg->renderContextInvalidated(this);
emit invalidated();
}
diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
index cd55ae191d..7163fd8cff 100644
--- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp
+++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
@@ -2154,6 +2154,15 @@ void tst_QJSEngine::jsNumberClass()
QJSValue ret = eng.evaluate("new Number(123).toPrecision()");
QVERIFY(ret.isString());
QCOMPARE(ret.toString(), QString::fromLatin1("123"));
+ ret = eng.evaluate("new Number(42).toPrecision(1)");
+ QVERIFY(ret.isString());
+ QCOMPARE(ret.toString(), QString::fromLatin1("4e+1"));
+ ret = eng.evaluate("new Number(42).toPrecision(2)");
+ QVERIFY(ret.isString());
+ QCOMPARE(ret.toString(), QString::fromLatin1("42"));
+ ret = eng.evaluate("new Number(42).toPrecision(3)");
+ QVERIFY(ret.isString());
+ QCOMPARE(ret.toString(), QString::fromLatin1("42.0"));
}
}
diff --git a/tests/auto/qml/qqmlconsole/data/categorized_logging.qml b/tests/auto/qml/qqmlconsole/data/categorized_logging.qml
new file mode 100644
index 0000000000..d19b6ecc41
--- /dev/null
+++ b/tests/auto/qml/qqmlconsole/data/categorized_logging.qml
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.8
+
+Item {
+ id:root
+
+ LoggingCategory {
+ id: testCategory
+ name: "qt.test"
+ }
+
+ LoggingCategory {
+ id: emptyCategory
+ }
+
+ Component.onCompleted: {
+ console.debug(testCategory, "console.debug");
+ console.log(testCategory, "console.log");
+ console.info(testCategory, "console.info");
+ console.warn(testCategory, "console.warn");
+ console.error(testCategory, "console.error");
+
+ testCategory.name = "qt.test2";
+
+ console.error(emptyCategory, "console.error");
+ }
+}
diff --git a/tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp b/tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp
index f12656c5fe..f832143935 100644
--- a/tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp
+++ b/tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp
@@ -40,6 +40,7 @@ public:
private slots:
void logging();
+ void categorized_logging();
void tracing();
void profiling();
void testAssert();
@@ -87,6 +88,41 @@ void tst_qqmlconsole::logging()
delete object;
}
+void tst_qqmlconsole::categorized_logging()
+{
+ QUrl testUrl = testFileUrl("categorized_logging.qml");
+ QQmlTestMessageHandler messageHandler;
+ messageHandler.setIncludeCategoriesEnabled(true);
+
+ QLoggingCategory testCategory("qt.test");
+ testCategory.setEnabled(QtDebugMsg, true);
+ QVERIFY(testCategory.isDebugEnabled());
+ QVERIFY(testCategory.isWarningEnabled());
+ QVERIFY(testCategory.isCriticalEnabled());
+
+ QQmlComponent component(&engine, testUrl);
+ QObject *object = component.create();
+ QVERIFY2(object != 0, component.errorString().toUtf8());
+
+ QVERIFY(messageHandler.messages().contains("qt.test: console.info"));
+ QVERIFY(messageHandler.messages().contains("qt.test: console.warn"));
+ QVERIFY(messageHandler.messages().contains("qt.test: console.error"));
+
+ QString emptyCategory = "default: " + QString::fromLatin1("%1:%2:%3: ").arg(testUrl.toString()).arg(50).arg(5) +
+ "QML LoggingCategory: Declaring the name of the LoggingCategory is mandatory and cannot be changed later !";
+ QVERIFY(messageHandler.messages().contains(emptyCategory));
+
+ QString changedCategory = "default: " + QString::fromLatin1("%1:%2:%3: ").arg(testUrl.toString()).arg(45).arg(5) +
+ "QML LoggingCategory: The name of a LoggingCategory cannot be changed after the Item is created";
+ QVERIFY(messageHandler.messages().contains(changedCategory));
+
+ QString useEmptyCategory = "default: " + QString::fromLatin1("%1:%2: ").arg(testUrl.toString()).arg(63) +
+ "Error: A QmlLoggingCatgory was provided without a valid name";
+ QVERIFY(messageHandler.messages().contains(useEmptyCategory));
+
+ delete object;
+}
+
void tst_qqmlconsole::tracing()
{
QUrl testUrl = testFileUrl("tracing.qml");
diff --git a/tests/auto/qml/qqmlextensionplugin/tst_qqmlextensionplugin.cpp b/tests/auto/qml/qqmlextensionplugin/tst_qqmlextensionplugin.cpp
index ab5e958323..124a107a37 100644
--- a/tests/auto/qml/qqmlextensionplugin/tst_qqmlextensionplugin.cpp
+++ b/tests/auto/qml/qqmlextensionplugin/tst_qqmlextensionplugin.cpp
@@ -80,6 +80,10 @@ void tst_qqmlextensionplugin::iidCheck_data()
QList<QString> files;
for (QDirIterator it(QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath), QDirIterator::Subdirectories); it.hasNext(); ) {
QString file = it.next();
+#if defined(Q_OS_DARWIN)
+ if (file.contains(QLatin1String(".dSYM/")))
+ continue;
+#endif
if (file.endsWith(SUFFIX)) {
files << file;
}
@@ -105,7 +109,7 @@ void tst_qqmlextensionplugin::iidCheck()
QFETCH(QString, filePath);
QPluginLoader loader(filePath);
- QVERIFY(loader.load());
+ QVERIFY2(loader.load(), qPrintable(loader.errorString()));
QVERIFY(loader.instance() != Q_NULLPTR);
if (qobject_cast<QQmlExtensionPlugin *>(loader.instance())) {
diff --git a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
index 7baff93574..b69c6eedf8 100644
--- a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
+++ b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
@@ -125,6 +125,7 @@ private slots:
void containsPress_data();
void containsPress();
void ignoreBySource();
+ void notPressedAfterStolenGrab();
private:
int startDragDistance() const {
@@ -1987,6 +1988,23 @@ void tst_QQuickMouseArea::ignoreBySource()
QCOMPARE(flickable->contentY(), 0.);
}
+void tst_QQuickMouseArea::notPressedAfterStolenGrab()
+{
+ QQuickWindow window;
+ window.resize(200, 200);
+ window.show();
+ QTest::qWaitForWindowExposed(&window);
+
+ QQuickMouseArea *ma = new QQuickMouseArea(window.contentItem());
+ ma->setSize(window.size());
+ QObject::connect(ma,
+ static_cast<void (QQuickMouseArea::*)(QQuickMouseEvent*)>(&QQuickMouseArea::pressed),
+ [&]() { window.contentItem()->grabMouse(); });
+
+ QTest::mouseClick(&window, Qt::LeftButton);
+ QVERIFY(!ma->pressed());
+}
+
QTEST_MAIN(tst_QQuickMouseArea)
#include "tst_qquickmousearea.moc"
diff --git a/tests/auto/shared/util.cpp b/tests/auto/shared/util.cpp
index 55041eeb4d..96beb51612 100644
--- a/tests/auto/shared/util.cpp
+++ b/tests/auto/shared/util.cpp
@@ -101,11 +101,15 @@ Q_GLOBAL_STATIC(QMutex, qQmlTestMessageHandlerMutex)
QQmlTestMessageHandler *QQmlTestMessageHandler::m_instance = 0;
-void QQmlTestMessageHandler::messageHandler(QtMsgType, const QMessageLogContext &, const QString &message)
+void QQmlTestMessageHandler::messageHandler(QtMsgType, const QMessageLogContext &context, const QString &message)
{
QMutexLocker locker(qQmlTestMessageHandlerMutex());
- if (QQmlTestMessageHandler::m_instance)
- QQmlTestMessageHandler::m_instance->m_messages.push_back(message);
+ if (QQmlTestMessageHandler::m_instance) {
+ if (QQmlTestMessageHandler::m_instance->m_includeCategories)
+ QQmlTestMessageHandler::m_instance->m_messages.push_back(QString("%1: %2").arg(context.category, message));
+ else
+ QQmlTestMessageHandler::m_instance->m_messages.push_back(message);
+ }
}
QQmlTestMessageHandler::QQmlTestMessageHandler()
@@ -114,6 +118,7 @@ QQmlTestMessageHandler::QQmlTestMessageHandler()
Q_ASSERT(!QQmlTestMessageHandler::m_instance);
QQmlTestMessageHandler::m_instance = this;
m_oldHandler = qInstallMessageHandler(messageHandler);
+ m_includeCategories = false;
}
QQmlTestMessageHandler::~QQmlTestMessageHandler()
diff --git a/tests/auto/shared/util.h b/tests/auto/shared/util.h
index 47a4aae231..33d7cbd1d0 100644
--- a/tests/auto/shared/util.h
+++ b/tests/auto/shared/util.h
@@ -87,12 +87,15 @@ public:
void clear() { m_messages.clear(); }
+ void setIncludeCategoriesEnabled(bool enabled) { m_includeCategories = enabled; }
+
private:
- static void messageHandler(QtMsgType, const QMessageLogContext &, const QString &message);
+ static void messageHandler(QtMsgType, const QMessageLogContext &context, const QString &message);
static QQmlTestMessageHandler *m_instance;
QStringList m_messages;
QtMessageHandler m_oldHandler;
+ bool m_includeCategories;
};
#endif // QQMLTESTUTILS_H