diff options
author | Simon Hausmann <[email protected]> | 2014-01-24 16:37:45 +0100 |
---|---|---|
committer | Simon Hausmann <[email protected]> | 2014-01-24 18:27:41 +0100 |
commit | 22041acdfe85c9a9b814e11cd86e8ee5a55be82d (patch) | |
tree | 1b4d1bfa0ebba9e5d1495b5ca7055dba94642c46 /src | |
parent | 6ae57f01bb1495a74b23a81c590672ce788d5400 (diff) | |
parent | 2407cd29e628671f7f5144e0d241d4249a3ab612 (diff) |
Merge remote-tracking branch 'origin/stable' into dev
Conflicts:
src/imports/dialogs/qquickmessagedialog.cpp
src/imports/dialogs/qquickmessagedialog_p.h
src/qml/debugger/qqmlprofilerservice_p.h
src/qml/jsruntime/qv4regexpobject.cpp
tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro
Change-Id: Ic8a43366b44d6970966acbf03b206d0dee00c28d
Diffstat (limited to 'src')
32 files changed, 408 insertions, 202 deletions
diff --git a/src/qml/compiler/qv4isel_masm.cpp b/src/qml/compiler/qv4isel_masm.cpp index 6df94e713d..b8b16a4151 100644 --- a/src/qml/compiler/qv4isel_masm.cpp +++ b/src/qml/compiler/qv4isel_masm.cpp @@ -1966,12 +1966,21 @@ void InstructionSelection::visitRet(V4IR::Ret *s) Assembler::ScratchRegister); _as->xor64(Assembler::ScratchRegister, Assembler::ReturnValueRegister); } else if (t->type == V4IR::UInt32Type) { - Address tmp = addressForArgument(0); - _as->storeUInt32((Assembler::RegisterID) t->index, Pointer(tmp)); - _as->load64(tmp, Assembler::ReturnValueRegister); + Assembler::RegisterID srcReg = (Assembler::RegisterID) t->index; + Assembler::Jump intRange = _as->branch32(Assembler::GreaterThanOrEqual, srcReg, Assembler::TrustedImm32(0)); + _as->convertUInt32ToDouble(srcReg, Assembler::FPGpr0, Assembler::ReturnValueRegister); + _as->moveDoubleTo64(Assembler::FPGpr0, Assembler::ReturnValueRegister); + _as->move(Assembler::TrustedImm64(QV4::Value::NaNEncodeMask), Assembler::ScratchRegister); + _as->xor64(Assembler::ScratchRegister, Assembler::ReturnValueRegister); + Assembler::Jump done = _as->jump(); + intRange.link(_as); + _as->zeroExtend32ToPtr(srcReg, Assembler::ReturnValueRegister); + quint64 tag = QV4::Value::_Integer_Type; + _as->or64(Assembler::TrustedImm64(tag << 32), + Assembler::ReturnValueRegister); + done.link(_as); } else { - _as->zeroExtend32ToPtr((Assembler::RegisterID) t->index, - Assembler::ReturnValueRegister); + _as->zeroExtend32ToPtr((Assembler::RegisterID) t->index, Assembler::ReturnValueRegister); quint64 tag; switch (t->type) { case V4IR::SInt32Type: diff --git a/src/qml/compiler/qv4isel_masm_p.h b/src/qml/compiler/qv4isel_masm_p.h index f5d4e469e5..a146220015 100644 --- a/src/qml/compiler/qv4isel_masm_p.h +++ b/src/qml/compiler/qv4isel_masm_p.h @@ -1481,6 +1481,7 @@ protected: typedef Assembler::Address Address; typedef Assembler::Pointer Pointer; +#if !defined(ARGUMENTS_IN_REGISTERS) Address addressForArgument(int index) const { // StackFrameRegister points to its old value on the stack, and above @@ -1488,6 +1489,7 @@ protected: // values before reaching the first argument. return Address(Assembler::StackFrameRegister, (index + 2) * sizeof(void*)); } +#endif Pointer baseAddressForCallArguments() { diff --git a/src/qml/compiler/qv4regalloc.cpp b/src/qml/compiler/qv4regalloc.cpp index f95cd55b04..2f1f64e523 100644 --- a/src/qml/compiler/qv4regalloc.cpp +++ b/src/qml/compiler/qv4regalloc.cpp @@ -860,7 +860,6 @@ private: if (it->end() < successorStart) continue; - bool lifeTimeHole = false; bool isPhiTarget = false; Expr *moveFrom = 0; @@ -906,9 +905,7 @@ private: predIt->temp().type); } else { int spillSlot = _assignedSpillSlots.value(predIt->temp(), -1); - if (spillSlot == -1) - lifeTimeHole = true; - else + if (spillSlot != -1) moveFrom = createTemp(Temp::StackSlot, spillSlot, predIt->temp().type); } break; @@ -916,9 +913,11 @@ private: } } if (!moveFrom) { -#if defined(QT_NO_DEBUG) - Q_UNUSED(lifeTimeHole); -#else +#if !defined(QT_NO_DEBUG) + bool lifeTimeHole = false; + if (it->ranges().first().start <= successorStart && it->ranges().last().end >= successorStart) + lifeTimeHole = !it->covers(successorStart); + Q_ASSERT(!_info->isPhiTarget(it->temp()) || it->isSplitFromInterval() || lifeTimeHole); if (_info->def(it->temp()) != successorStart && !it->isSplitFromInterval()) { const int successorEnd = successor->statements.last()->id; @@ -960,9 +959,6 @@ private: moveTo = createTemp(Temp::StackSlot, spillSlot, it->temp().type); } else { moveTo = createTemp(Temp::PhysicalRegister, platformRegister(*it), it->temp().type); - const int spillSlot = _assignedSpillSlots.value(it->temp(), -1); - if (isPhiTarget && spillSlot != -1) - mapping.add(moveFrom, createTemp(Temp::StackSlot, spillSlot, it->temp().type)); } // add move to mapping diff --git a/src/qml/debugger/qqmlprofilerservice_p.h b/src/qml/debugger/qqmlprofilerservice_p.h index 6d7c0dcb51..c3329dbb89 100644 --- a/src/qml/debugger/qqmlprofilerservice_p.h +++ b/src/qml/debugger/qqmlprofilerservice_p.h @@ -57,6 +57,7 @@ #include <private/qqmlboundsignal_p.h> // this contains QUnifiedTimer #include <private/qabstractanimation_p.h> +#include <private/qv4function_p.h> #include <QtCore/qelapsedtimer.h> #include <QtCore/qmetaobject.h> @@ -401,8 +402,20 @@ struct QQmlBindingProfiler { struct QQmlHandlingSignalProfiler { QQmlHandlingSignalProfiler(QQmlBoundSignalExpression *expression) { - Q_QML_PROFILE(startHandlingSignal(expression->sourceFile(), expression->lineNumber(), - expression->columnNumber())); + if (QQmlProfilerService::enabled) { + if (expression->sourceFile().isEmpty()) { + QV4::Function *function = expression->function(); + if (function) { + Q_QML_PROFILE(startHandlingSignal( + function->sourceFile(), function->compiledFunction->location.line, + function->compiledFunction->location.column)); + } + } else { + Q_QML_PROFILE(startHandlingSignal( + expression->sourceFile(), expression->lineNumber(), + expression->columnNumber())); + } + } } ~QQmlHandlingSignalProfiler() diff --git a/src/qml/doc/src/qmlfunctions.qdoc b/src/qml/doc/src/qmlfunctions.qdoc index 19cd3b3f02..d3d3174193 100644 --- a/src/qml/doc/src/qmlfunctions.qdoc +++ b/src/qml/doc/src/qmlfunctions.qdoc @@ -238,7 +238,7 @@ Usage: \code // First, define the singleton type provider function (callback). - static QJSValue *example_qjsvalue_singletontype_provider(QQmlEngine *engine, QJSEngine *scriptEngine) + static QJSValue example_qjsvalue_singletontype_provider(QQmlEngine *engine, QJSEngine *scriptEngine) { Q_UNUSED(engine) diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp index 0734e92b19..c8de31ef78 100644 --- a/src/qml/jsapi/qjsvalue.cpp +++ b/src/qml/jsapi/qjsvalue.cpp @@ -746,7 +746,7 @@ static bool js_equal(const QString &string, QV4::ValueRef value) if (value->isNumber()) return __qmljs_string_to_number(string) == value->asDouble(); if (value->isBoolean()) - return __qmljs_string_to_number(string) == value->booleanValue(); + return __qmljs_string_to_number(string) == double(value->booleanValue()); if (value->isObject()) { Scope scope(value->objectValue()->engine()); ScopedValue p(scope, __qmljs_to_primitive(value, PREFERREDTYPE_HINT)); diff --git a/src/qml/jsruntime/qv4alloca_p.h b/src/qml/jsruntime/qv4alloca_p.h index f507d174e1..e51c6dff00 100644 --- a/src/qml/jsruntime/qv4alloca_p.h +++ b/src/qml/jsruntime/qv4alloca_p.h @@ -50,7 +50,9 @@ # define alloca _alloca # endif #else +#if !defined(__FreeBSD__) && !defined(__DragonFly__) # include <alloca.h> #endif +#endif #endif diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 995c711a02..299d11a4a1 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -77,6 +77,9 @@ #if USE(PTHREADS) # include <pthread.h> # include <sys/resource.h> +#if HAVE(PTHREAD_NP_H) +# include <pthread_np.h> +#endif #endif QT_BEGIN_NAMESPACE @@ -109,7 +112,11 @@ quintptr getStackLimit() # else void* stackBottom = 0; pthread_attr_t attr; +#if HAVE(PTHREAD_NP_H) && OS(FREEBSD) + if (pthread_attr_get_np(pthread_self(), &attr) == 0) { +#else if (pthread_getattr_np(pthread_self(), &attr) == 0) { +#endif size_t stackSize = 0; pthread_attr_getstack(&attr, &stackBottom, &stackSize); pthread_attr_destroy(&attr); diff --git a/src/qml/jsruntime/qv4mm.cpp b/src/qml/jsruntime/qv4mm.cpp index 0af0fea49a..0ba0b18cda 100644 --- a/src/qml/jsruntime/qv4mm.cpp +++ b/src/qml/jsruntime/qv4mm.cpp @@ -67,6 +67,10 @@ #include <sys/storage.h> // __tls() #endif +#if USE(PTHREADS) && HAVE(PTHREAD_NP_H) +#include <pthread_np.h> +#endif + QT_BEGIN_NAMESPACE using namespace QV4; @@ -234,7 +238,11 @@ MemoryManager::MemoryManager() # else void* stackBottom = 0; pthread_attr_t attr; +#if HAVE(PTHREAD_NP_H) && OS(FREEBSD) + if (pthread_attr_get_np(pthread_self(), &attr) == 0) { +#else if (pthread_getattr_np(pthread_self(), &attr) == 0) { +#endif size_t stackSize = 0; pthread_attr_getstack(&attr, &stackBottom, &stackSize); pthread_attr_destroy(&attr); diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp index aafecb5ad8..95b6569196 100644 --- a/src/qml/jsruntime/qv4regexpobject.cpp +++ b/src/qml/jsruntime/qv4regexpobject.cpp @@ -237,6 +237,15 @@ RegExpCtor::RegExpCtor(ExecutionContext *scope) : FunctionObject(scope, QStringLiteral("RegExp")) { setVTable(staticVTable()); + clearLastMatch(); +} + +void RegExpCtor::clearLastMatch() +{ + lastMatch = Primitive::nullValue(); + lastInput = engine()->newIdentifier(QString()); + lastMatchStart = 0; + lastMatchEnd = 0; } ReturnedValue RegExpCtor::construct(Managed *m, CallData *callData) @@ -299,6 +308,14 @@ ReturnedValue RegExpCtor::call(Managed *that, CallData *callData) return construct(that, callData); } +void RegExpCtor::markObjects(Managed *that, ExecutionEngine *e) +{ + RegExpCtor *This = static_cast<RegExpCtor*>(that); + This->lastMatch.mark(e); + This->lastInput.mark(e); + FunctionObject::markObjects(that, e); +} + void RegExpPrototype::init(ExecutionEngine *engine, ObjectRef ctor) { Scope scope(engine); @@ -306,6 +323,28 @@ void RegExpPrototype::init(ExecutionEngine *engine, ObjectRef ctor) ctor->defineReadonlyProperty(engine->id_prototype, (o = this)); ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(2)); + + // Properties deprecated in the spec but required by "the web" :( + ctor->defineAccessorProperty(QStringLiteral("lastMatch"), method_get_lastMatch_n<0>, 0); + ctor->defineAccessorProperty(QStringLiteral("$&"), method_get_lastMatch_n<0>, 0); + ctor->defineAccessorProperty(QStringLiteral("$1"), method_get_lastMatch_n<1>, 0); + ctor->defineAccessorProperty(QStringLiteral("$2"), method_get_lastMatch_n<2>, 0); + ctor->defineAccessorProperty(QStringLiteral("$3"), method_get_lastMatch_n<3>, 0); + ctor->defineAccessorProperty(QStringLiteral("$4"), method_get_lastMatch_n<4>, 0); + ctor->defineAccessorProperty(QStringLiteral("$5"), method_get_lastMatch_n<5>, 0); + ctor->defineAccessorProperty(QStringLiteral("$6"), method_get_lastMatch_n<6>, 0); + ctor->defineAccessorProperty(QStringLiteral("$7"), method_get_lastMatch_n<7>, 0); + ctor->defineAccessorProperty(QStringLiteral("$8"), method_get_lastMatch_n<8>, 0); + ctor->defineAccessorProperty(QStringLiteral("$9"), method_get_lastMatch_n<9>, 0); + ctor->defineAccessorProperty(QStringLiteral("lastParen"), method_get_lastParen, 0); + ctor->defineAccessorProperty(QStringLiteral("$+"), method_get_lastParen, 0); + ctor->defineAccessorProperty(QStringLiteral("input"), method_get_input, 0); + ctor->defineAccessorProperty(QStringLiteral("$_"), method_get_input, 0); + ctor->defineAccessorProperty(QStringLiteral("leftContext"), method_get_leftContext, 0); + ctor->defineAccessorProperty(QStringLiteral("$`"), method_get_leftContext, 0); + ctor->defineAccessorProperty(QStringLiteral("rightContext"), method_get_rightContext, 0); + ctor->defineAccessorProperty(QStringLiteral("$'"), method_get_rightContext, 0); + defineDefaultProperty(QStringLiteral("constructor"), (o = ctor)); defineDefaultProperty(QStringLiteral("exec"), method_exec, 1); defineDefaultProperty(QStringLiteral("test"), method_test, 1); @@ -333,7 +372,11 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx) } uint* matchOffsets = (uint*)alloca(r->value->captureCount() * 2 * sizeof(uint)); - int result = r->value->match(s, offset, matchOffsets); + const int result = r->value->match(s, offset, matchOffsets); + + Scoped<RegExpCtor> regExpCtor(scope, ctx->engine->regExpCtor); + regExpCtor->clearLastMatch(); + if (result == -1) { r->lastIndexProperty(ctx)->value = Primitive::fromInt32(0); return Encode::null(); @@ -351,10 +394,14 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx) array->arrayData->put(i, v); } array->setArrayLengthUnchecked(len); - array->memberData[Index_ArrayIndex].value = Primitive::fromInt32(result); array->memberData[Index_ArrayInput].value = arg.asReturnedValue(); + regExpCtor->lastMatch = array; + regExpCtor->lastInput = arg->stringValue(); + regExpCtor->lastMatchStart = matchOffsets[0]; + regExpCtor->lastMatchEnd = matchOffsets[1]; + if (r->global) r->lastIndexProperty(ctx)->value = Primitive::fromInt32(matchOffsets[1]); @@ -395,4 +442,46 @@ ReturnedValue RegExpPrototype::method_compile(CallContext *ctx) return Encode::undefined(); } +template <int index> +ReturnedValue RegExpPrototype::method_get_lastMatch_n(CallContext *ctx) +{ + Scope scope(ctx); + ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->engine->regExpCtor.objectValue())->lastMatch); + ScopedValue result(scope, lastMatch ? lastMatch->getIndexed(index) : Encode::undefined()); + if (result->isUndefined()) + return ctx->engine->newString(QString())->asReturnedValue(); + return result.asReturnedValue(); +} + +ReturnedValue RegExpPrototype::method_get_lastParen(CallContext *ctx) +{ + Scope scope(ctx); + ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->engine->regExpCtor.objectValue())->lastMatch); + ScopedValue result(scope, lastMatch ? lastMatch->getIndexed(lastMatch->getLength() - 1) : Encode::undefined()); + if (result->isUndefined()) + return ctx->engine->newString(QString())->asReturnedValue(); + return result.asReturnedValue(); +} + +ReturnedValue RegExpPrototype::method_get_input(CallContext *ctx) +{ + return static_cast<RegExpCtor*>(ctx->engine->regExpCtor.objectValue())->lastInput.asReturnedValue(); +} + +ReturnedValue RegExpPrototype::method_get_leftContext(CallContext *ctx) +{ + Scope scope(ctx); + Scoped<RegExpCtor> regExpCtor(scope, ctx->engine->regExpCtor); + QString lastInput = regExpCtor->lastInput->toQString(); + return ctx->engine->newString(lastInput.left(regExpCtor->lastMatchStart))->asReturnedValue(); +} + +ReturnedValue RegExpPrototype::method_get_rightContext(CallContext *ctx) +{ + Scope scope(ctx); + Scoped<RegExpCtor> regExpCtor(scope, ctx->engine->regExpCtor); + QString lastInput = regExpCtor->lastInput->toQString(); + return ctx->engine->newString(lastInput.mid(regExpCtor->lastMatchEnd))->asReturnedValue(); +} + QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4regexpobject_p.h b/src/qml/jsruntime/qv4regexpobject_p.h index d306efb218..a4cb4b9fb5 100644 --- a/src/qml/jsruntime/qv4regexpobject_p.h +++ b/src/qml/jsruntime/qv4regexpobject_p.h @@ -107,8 +107,15 @@ struct RegExpCtor: FunctionObject V4_OBJECT RegExpCtor(ExecutionContext *scope); + SafeValue lastMatch; + SafeString lastInput; + int lastMatchStart; + int lastMatchEnd; + void clearLastMatch(); + static ReturnedValue construct(Managed *m, CallData *callData); static ReturnedValue call(Managed *that, CallData *callData); + static void markObjects(Managed *that, ExecutionEngine *e); }; struct RegExpPrototype: RegExpObject @@ -120,6 +127,13 @@ struct RegExpPrototype: RegExpObject static ReturnedValue method_test(CallContext *ctx); static ReturnedValue method_toString(CallContext *ctx); static ReturnedValue method_compile(CallContext *ctx); + + template <int index> + static ReturnedValue method_get_lastMatch_n(CallContext *ctx); + static ReturnedValue method_get_lastParen(CallContext *ctx); + static ReturnedValue method_get_input(CallContext *ctx); + static ReturnedValue method_get_leftContext(CallContext *ctx); + static ReturnedValue method_get_rightContext(CallContext *ctx); }; } diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h index 21f45745cb..2c71a36a3d 100644 --- a/src/qml/jsruntime/qv4scopedvalue_p.h +++ b/src/qml/jsruntime/qv4scopedvalue_p.h @@ -65,6 +65,9 @@ struct Scope { explicit Scope(ExecutionEngine *e) : engine(e) +#ifndef QT_NO_DEBUG + , size(0) +#endif { mark = engine->jsStackTop; } diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp index 68160edf5e..bc56fe1f2d 100644 --- a/src/qml/qml/qqmlboundsignal.cpp +++ b/src/qml/qml/qqmlboundsignal.cpp @@ -136,6 +136,17 @@ QString QQmlBoundSignalExpression::expression() const } } +QV4::Function *QQmlBoundSignalExpression::function() const +{ + if (m_expressionFunctionValid) { + Q_ASSERT (context() && engine()); + QV4::Scope scope(QQmlEnginePrivate::get(engine())->v4engine()); + QV4::Scoped<QV4::FunctionObject> v(scope, m_v8function.value()); + return v ? v->function : 0; + } + return 0; +} + // Parts of this function mirror code in QQmlExpressionPrivate::value() and v8value(). // Changes made here may need to be made there and vice versa. void QQmlBoundSignalExpression::evaluate(void **a) diff --git a/src/qml/qml/qqmlboundsignal_p.h b/src/qml/qml/qqmlboundsignal_p.h index feb79d5484..fe0dbd380e 100644 --- a/src/qml/qml/qqmlboundsignal_p.h +++ b/src/qml/qml/qqmlboundsignal_p.h @@ -90,6 +90,7 @@ public: quint16 lineNumber() const { return m_line; } quint16 columnNumber() const { return m_column; } QString expression() const; + QV4::Function *function() const; QObject *target() const { return m_target; } QQmlEngine *engine() const { return context() ? context()->engine : 0; } diff --git a/src/qml/qml/qqmlcompiler.cpp b/src/qml/qml/qqmlcompiler.cpp index cd0dea975b..e36f3fd967 100644 --- a/src/qml/qml/qqmlcompiler.cpp +++ b/src/qml/qml/qqmlcompiler.cpp @@ -1681,6 +1681,7 @@ static AST::FunctionDeclaration *convertSignalHandlerExpressionToFunctionDeclara AST::FunctionBody *body = new (pool) AST::FunctionBody(elements); AST::FunctionDeclaration *functionDeclaration = new (pool) AST::FunctionDeclaration(jsEngine->newStringRef(signalName), paramList, body); + functionDeclaration->functionToken = statement->firstSourceLocation(); return functionDeclaration; } diff --git a/src/qml/qml/qqmlinstruction_p.h b/src/qml/qml/qqmlinstruction_p.h index aeda9832f3..d76c9f9f64 100644 --- a/src/qml/qml/qqmlinstruction_p.h +++ b/src/qml/qml/qqmlinstruction_p.h @@ -151,8 +151,10 @@ QT_BEGIN_NAMESPACE #ifdef QML_THREADED_VME_INTERPRETER # define QML_INSTR_HEADER void *code; +# define QML_INSTR_HEADER_INIT this->code = 0; #else # define QML_INSTR_HEADER quint8 instructionType; +# define QML_INSTR_HEADER_INIT this->instructionType = 0; #endif #define QML_INSTR_ENUM(I, FMT) I, @@ -547,6 +549,8 @@ FOR_EACH_QML_INSTR(QML_INSTR_META_TEMPLATE); template<int Instr> class QQmlInstructionData : public QQmlInstructionMeta<Instr>::DataType { +public: + QQmlInstructionData() : QQmlInstructionMeta<Instr>::DataType() { QML_INSTR_HEADER_INIT } }; QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index 1dd8ce0e3e..90d3ca3308 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -1836,6 +1836,17 @@ QList<QQmlType*> QQmlMetaType::qmlTypes() } /*! + Returns the list of all registered types. +*/ +QList<QQmlType*> QQmlMetaType::qmlAllTypes() +{ + QReadLocker lock(metaTypeDataLock()); + QQmlMetaTypeData *data = metaTypeData(); + + return data->types; +} + +/*! Returns the list of registered QML singleton types. */ QList<QQmlType*> QQmlMetaType::qmlSingletonTypes() diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h index 6c19da6b15..019e6b8821 100644 --- a/src/qml/qml/qqmlmetatype_p.h +++ b/src/qml/qml/qqmlmetatype_p.h @@ -80,6 +80,7 @@ public: static QList<QString> qmlTypeNames(); static QList<QQmlType*> qmlTypes(); static QList<QQmlType*> qmlSingletonTypes(); + static QList<QQmlType*> qmlAllTypes(); static QQmlType *qmlType(const QString &qualifiedName, int, int); static QQmlType *qmlType(const QHashedStringRef &name, const QHashedStringRef &module, int, int); diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp index 7cc37e0556..333c11cb29 100644 --- a/src/quick/items/qquickflickable.cpp +++ b/src/quick/items/qquickflickable.cpp @@ -2309,6 +2309,7 @@ void QQuickFlickable::timelineCompleted() return; } movementEnding(); + d->updateBeginningEnd(); } void QQuickFlickable::movementStarting() diff --git a/src/quick/items/qquickmultipointtoucharea.cpp b/src/quick/items/qquickmultipointtoucharea.cpp index 6b273dcd43..973f6efdcc 100644 --- a/src/quick/items/qquickmultipointtoucharea.cpp +++ b/src/quick/items/qquickmultipointtoucharea.cpp @@ -324,7 +324,6 @@ void QQuickTouchPoint::setSceneY(qreal sceneY) QQuickMultiPointTouchArea::QQuickMultiPointTouchArea(QQuickItem *parent) : QQuickItem(parent), - _currentWindow(0), _minimumTouchPoints(0), _maximumTouchPoints(INT_MAX), _stealMouse(false) @@ -334,8 +333,8 @@ QQuickMultiPointTouchArea::QQuickMultiPointTouchArea(QQuickItem *parent) if (qmlVisualTouchDebugging()) { setFlag(QQuickItem::ItemHasContents); } -#ifdef Q_OS_MAC - connect(this, &QQuickItem::windowChanged, this, &QQuickMultiPointTouchArea::setTouchEventsEnabledForWindow); +#ifdef Q_OS_OSX + setAcceptHoverEvents(true); // needed to enable touch events on mouse hover. #endif } @@ -548,28 +547,31 @@ void QQuickMultiPointTouchArea::addTouchPoint(const QTouchEvent::TouchPoint *p) _pressedTouchPoints.append(dtp); } -void QQuickMultiPointTouchArea::setTouchEventsEnabledForWindow(QWindow *window) +#ifdef Q_OS_OSX +void QQuickMultiPointTouchArea::hoverEnterEvent(QHoverEvent *event) +{ + Q_UNUSED(event); + setTouchEventsEnabled(true); +} + +void QQuickMultiPointTouchArea::hoverLeaveEvent(QHoverEvent *event) +{ + Q_UNUSED(event); + setTouchEventsEnabled(false); +} + +void QQuickMultiPointTouchArea::setTouchEventsEnabled(bool enable) { -#ifdef Q_OS_MAC // Resolve function for enabling touch events from the (cocoa) platform plugin. typedef void (*RegisterTouchWindowFunction)(QWindow *, bool); RegisterTouchWindowFunction registerTouchWindow = reinterpret_cast<RegisterTouchWindowFunction>( QGuiApplication::platformNativeInterface()->nativeResourceFunctionForIntegration("registertouchwindow")); if (!registerTouchWindow) - return; // Not necessarily an error, Qt migh be using a different platform plugin. - - // Disable touch on the old window, enable on the new window. - if (_currentWindow) - registerTouchWindow(_currentWindow, false); - if (window) - registerTouchWindow(window, true); - // Save the current window, setTouchEventsEnabledForWindow will be called - // with a null window on disable. - _currentWindow = window; -#else // Q_OS_MAC - Q_UNUSED(window) -#endif + return; // Not necessarily an error, Qt might be using a different platform plugin. + + registerTouchWindow(window(), enable); } +#endif // Q_OS_OSX void QQuickMultiPointTouchArea::addTouchPrototype(QQuickTouchPoint *prototype) { diff --git a/src/quick/items/qquickmultipointtoucharea_p.h b/src/quick/items/qquickmultipointtoucharea_p.h index 2e1f2a98fb..83cc407401 100644 --- a/src/quick/items/qquickmultipointtoucharea_p.h +++ b/src/quick/items/qquickmultipointtoucharea_p.h @@ -250,9 +250,11 @@ protected: bool shouldFilter(QEvent *event); void grabGesture(); virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *); - -protected Q_SLOTS: - void setTouchEventsEnabledForWindow(QWindow *window); +#ifdef Q_OS_OSX + void hoverEnterEvent(QHoverEvent *event); + void hoverLeaveEvent(QHoverEvent *event); + void setTouchEventsEnabled(bool enable); +#endif private: void ungrab(); @@ -261,7 +263,6 @@ private: QList<QObject*> _releasedTouchPoints; QList<QObject*> _pressedTouchPoints; QList<QObject*> _movedTouchPoints; - QWindow *_currentWindow; int _minimumTouchPoints; int _maximumTouchPoints; bool _stealMouse; diff --git a/src/quick/items/qquickpincharea.cpp b/src/quick/items/qquickpincharea.cpp index 419792aaa5..f741a08512 100644 --- a/src/quick/items/qquickpincharea.cpp +++ b/src/quick/items/qquickpincharea.cpp @@ -248,14 +248,13 @@ QQuickPinchAreaPrivate::~QQuickPinchAreaPrivate() QQuickPinchArea::QQuickPinchArea(QQuickItem *parent) : QQuickItem(*(new QQuickPinchAreaPrivate), parent) - , _currentWindow(0) { Q_D(QQuickPinchArea); d->init(); setAcceptedMouseButtons(Qt::LeftButton); setFiltersChildMouseEvents(true); -#ifdef Q_OS_MAC - connect(this, &QQuickItem::windowChanged, this, &QQuickPinchArea::setTouchEventsEnabledForWindow); +#ifdef Q_OS_OSX + setAcceptHoverEvents(true); // needed to enable touch events on mouse hover. #endif } @@ -537,37 +536,39 @@ void QQuickPinchArea::itemChange(ItemChange change, const ItemChangeData &value) QQuickItem::itemChange(change, value); } -QQuickPinch *QQuickPinchArea::pinch() +#ifdef Q_OS_OSX +void QQuickPinchArea::hoverEnterEvent(QHoverEvent *event) { - Q_D(QQuickPinchArea); - if (!d->pinch) - d->pinch = new QQuickPinch; - return d->pinch; + Q_UNUSED(event); + setTouchEventsEnabled(true); } -void QQuickPinchArea::setTouchEventsEnabledForWindow(QWindow *window) +void QQuickPinchArea::hoverLeaveEvent(QHoverEvent *event) +{ + Q_UNUSED(event); + setTouchEventsEnabled(false); +} + +void QQuickPinchArea::setTouchEventsEnabled(bool enable) { -#ifdef Q_OS_MAC // Resolve function for enabling touch events from the (cocoa) platform plugin. typedef void (*RegisterTouchWindowFunction)(QWindow *, bool); RegisterTouchWindowFunction registerTouchWindow = reinterpret_cast<RegisterTouchWindowFunction>( QGuiApplication::platformNativeInterface()->nativeResourceFunctionForIntegration("registertouchwindow")); if (!registerTouchWindow) - return; // Not necessarily an error, Qt migh be using a different platform plugin. - - // Disable touch on the old window, enable on the new window. - if (_currentWindow) - registerTouchWindow(_currentWindow, false); - if (window) - registerTouchWindow(window, true); - // Save the current window, setTouchEventsEnabledForWindow will be called - // with a null window on disable. - _currentWindow = window; -#else // Q_OS_MAC - Q_UNUSED(window) -#endif + return; // Not necessarily an error, Qt might be using a different platform plugin. + + registerTouchWindow(window(), enable); } +#endif // Q_OS_OSX +QQuickPinch *QQuickPinchArea::pinch() +{ + Q_D(QQuickPinchArea); + if (!d->pinch) + d->pinch = new QQuickPinch; + return d->pinch; +} QT_END_NAMESPACE diff --git a/src/quick/items/qquickpincharea_p.h b/src/quick/items/qquickpincharea_p.h index c991145fc7..81bdbda3a1 100644 --- a/src/quick/items/qquickpincharea_p.h +++ b/src/quick/items/qquickpincharea_p.h @@ -282,9 +282,11 @@ protected: virtual void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry); virtual void itemChange(ItemChange change, const ItemChangeData& value); - -private Q_SLOTS: - void setTouchEventsEnabledForWindow(QWindow *window); +#ifdef Q_OS_OSX + void hoverEnterEvent(QHoverEvent *event); + void hoverLeaveEvent(QHoverEvent *event); + void setTouchEventsEnabled(bool enable); +#endif private: void updatePinch(); @@ -292,7 +294,6 @@ private: void handleRelease(); private: - QWindow *_currentWindow; Q_DISABLE_COPY(QQuickPinchArea) Q_DECLARE_PRIVATE(QQuickPinchArea) }; diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp index beb2039924..5b5dd0ef03 100644 --- a/src/quick/items/qquicktext.cpp +++ b/src/quick/items/qquicktext.cpp @@ -2088,7 +2088,7 @@ QRectF QQuickText::boundingRect() const Q_D(const QQuickText); QRectF rect = d->layedOutTextRect; - rect.moveLeft(QQuickTextUtil::alignedX(rect.width(), width(), d->hAlign)); + rect.moveLeft(QQuickTextUtil::alignedX(rect.width(), width(), effectiveHAlign())); rect.moveTop(QQuickTextUtil::alignedY(rect.height(), height(), d->vAlign)); if (d->style != Normal) @@ -2225,11 +2225,11 @@ QSGNode *QQuickText::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data const QColor linkColor = QColor::fromRgba(d->linkColor); if (d->richText) { - const qreal dx = QQuickTextUtil::alignedX(d->layedOutTextRect.width(), width(), d->hAlign); + const qreal dx = QQuickTextUtil::alignedX(d->layedOutTextRect.width(), width(), effectiveHAlign()); d->ensureDoc(); node->addTextDocument(QPointF(dx, dy), d->extra->doc, color, d->style, styleColor, linkColor); } else if (d->layedOutTextRect.width() > 0) { - const qreal dx = QQuickTextUtil::alignedX(d->lineWidth, width(), d->hAlign); + const qreal dx = QQuickTextUtil::alignedX(d->lineWidth, width(), effectiveHAlign()); int unelidedLineCount = d->lineCount; if (d->elideLayout) unelidedLineCount -= 1; @@ -2501,7 +2501,7 @@ QString QQuickTextPrivate::anchorAt(const QPointF &mousePos) const link = anchorAt(elideLayout, translatedMousePos); return link; } else if (richText && extra.isAllocated() && extra->doc) { - translatedMousePos.rx() -= QQuickTextUtil::alignedX(layedOutTextRect.width(), q->width(), hAlign); + translatedMousePos.rx() -= QQuickTextUtil::alignedX(layedOutTextRect.width(), q->width(), q->effectiveHAlign()); return extra->doc->documentLayout()->anchorAt(translatedMousePos); } return QString(); diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index c57ca5e838..a311971266 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -343,6 +343,8 @@ void QQuickWindowPrivate::syncSceneGraph() if (clearBeforeRendering) mode |= QSGRenderer::ClearColorBuffer; renderer->setClearMode(mode); + + context->endSync(); } diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp index 700ec051ff..1a9669f9ab 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp @@ -599,11 +599,6 @@ void Element::computeBounds() boundsOutsideFloatRange = bounds.isOutsideFloatRange(); } -RenderNodeElement::~RenderNodeElement() -{ - delete fbo; -} - bool Batch::isMaterialCompatible(Element *e) const { // If material has changed between opaque and translucent, it is not compatible @@ -751,6 +746,7 @@ Renderer::Renderer(QSGRenderContext *ctx) , m_nextRenderOrder(0) , m_partialRebuild(false) , m_partialRebuildRoot(0) + , m_useDepthBuffer(true) , m_opaqueBatches(16) , m_alphaBatches(16) , m_batchPool(16) @@ -761,6 +757,8 @@ Renderer::Renderer(QSGRenderContext *ctx) , m_zRange(0) , m_currentMaterial(0) , m_currentShader(0) + , m_currentClip(0) + , m_currentClipType(NoClip) , m_vao(0) { setNodeUpdater(new Updater(this)); @@ -809,6 +807,8 @@ Renderer::Renderer(QSGRenderContext *ctx) m_vao = new QOpenGLVertexArrayObject(this); m_vao->create(); } + + m_useDepthBuffer = ctx->openglContext()->format().depthBufferSize() > 0; } static void qsg_wipeBuffer(Buffer *buffer, QOpenGLFunctions *funcs) @@ -1005,6 +1005,8 @@ void Renderer::nodeWasAdded(QSGNode *node, Node *shadowParent) snode->data = e; Q_ASSERT(!m_renderNodeElements.contains(static_cast<QSGRenderNode *>(node))); m_renderNodeElements.insert(e->renderNode, e); + m_useDepthBuffer = false; + m_rebuild |= FullRebuild; } QSGNODE_TRAVERSE(node) @@ -1250,7 +1252,7 @@ void Renderer::buildRenderLists(QSGNode *node) Q_ASSERT(e); bool opaque = gn->inheritedOpacity() > OPAQUE_LIMIT && !(gn->activeMaterial()->flags() & QSGMaterial::Blending); - if (opaque) + if (opaque && m_useDepthBuffer) m_opaqueRenderList << e; else m_alphaRenderList << e; @@ -1631,10 +1633,13 @@ void Renderer::uploadMergedElement(Element *e, int vaOffset, char **vertexData, } } - float *vzorder = (float *) *zData; - float zorder = 1.0f - e->order * m_zRange; - for (int i=0; i<vCount; ++i) - vzorder[i] = zorder; + if (m_useDepthBuffer) { + float *vzorder = (float *) *zData; + float zorder = 1.0f - e->order * m_zRange; + for (int i=0; i<vCount; ++i) + vzorder[i] = zorder; + *zData += vCount * sizeof(float); + } int iCount = g->indexCount(); quint16 *indices = (quint16 *) *indexData; @@ -1658,7 +1663,6 @@ void Renderer::uploadMergedElement(Element *e, int vaOffset, char **vertexData, } *vertexData += vCount * vSize; - *zData += vCount * sizeof(float); *indexData += iCount * sizeof(quint16); *iBase += vCount; *indexCount += iCount; @@ -1754,8 +1758,9 @@ void Renderer::uploadBatch(Batch *b) int bufferSize = b->vertexCount * g->sizeOfVertex(); int ibufferSize = 0; if (b->merged) { - bufferSize += b->vertexCount * sizeof(float); ibufferSize = b->indexCount * sizeof(quint16); + if (m_useDepthBuffer) + bufferSize += b->vertexCount * sizeof(float); } else { ibufferSize = unmergedIndexSize; } @@ -1777,7 +1782,7 @@ void Renderer::uploadBatch(Batch *b) #ifdef QSG_SEPARATE_INDEX_BUFFER char *indexData = b->ibo.data; #else - char *indexData = zData + b->vertexCount * sizeof(float); + char *indexData = zData + (m_useDepthBuffer ? b->vertexCount * sizeof(float) : 0); #endif quint16 iOffset = 0; @@ -1857,7 +1862,7 @@ void Renderer::uploadBatch(Batch *b) dump << ") "; offset += attr.tupleSize * size_of_type(attr.type); } - if (b->merged) { + if (b->merged && m_useDepthBuffer) { float zorder = ((float*)(b->vbo.data + b->vertexCount * g->sizeOfVertex()))[i]; dump << " Z:(" << zorder << ")"; } @@ -1907,10 +1912,10 @@ void Renderer::updateClip(const QSGClipNode *clipList, const Batch *batch) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); if (batch->isOpaque) glDisable(GL_DEPTH_TEST); - ClipType type = updateStencilClip(m_currentClip); + m_currentClipType = updateStencilClip(m_currentClip); if (batch->isOpaque) { glEnable(GL_DEPTH_TEST); - if (type & StencilClip) + if (m_currentClipType & StencilClip) glDepthMask(true); } } @@ -2025,7 +2030,7 @@ void Renderer::renderMergedBatch(const Batch *batch) QSGMaterial *material = gn->activeMaterial(); - ShaderManager::Shader *sms = m_shaderManager->prepareMaterial(material); + ShaderManager::Shader *sms = m_useDepthBuffer ? m_shaderManager->prepareMaterial(material) : m_shaderManager->prepareMaterialNoRewrite(material); QSGMaterialShader *program = sms->program; if (m_currentShader != sms) @@ -2054,7 +2059,8 @@ void Renderer::renderMergedBatch(const Batch *batch) glVertexAttribPointer(a.position, a.tupleSize, a.type, normalize, g->sizeOfVertex(), (void *) (qintptr) (offset + draw.vertices)); offset += a.tupleSize * size_of_type(a.type); } - glVertexAttribPointer(sms->pos_order, 1, GL_FLOAT, false, 0, (void *) (qintptr) (draw.zorders)); + if (m_useDepthBuffer) + glVertexAttribPointer(sms->pos_order, 1, GL_FLOAT, false, 0, (void *) (qintptr) (draw.zorders)); glDrawElements(g->drawingMode(), draw.indexCount, GL_UNSIGNED_SHORT, (void *) (qintptr) (indexBase + draw.indices)); } @@ -2136,8 +2142,10 @@ void Renderer::renderUnmergedBatch(const Batch *batch) m_current_determinant = m_current_model_view_matrix.determinant(); m_current_projection_matrix = projectionMatrix(); - m_current_projection_matrix(2, 2) = m_zRange; - m_current_projection_matrix(2, 3) = 1.0f - e->order * m_zRange; + if (m_useDepthBuffer) { + m_current_projection_matrix(2, 2) = m_zRange; + m_current_projection_matrix(2, 3) = 1.0f - e->order * m_zRange; + } program->updateState(state(dirty), material, m_currentMaterial); @@ -2187,25 +2195,25 @@ void Renderer::renderBatches() << " -> Alpha: " << qsg_countNodesInBatches(m_alphaBatches) << " nodes in " << m_alphaBatches.size() << " batches..."; } - for (QHash<QSGRenderNode *, RenderNodeElement *>::const_iterator it = m_renderNodeElements.constBegin(); - it != m_renderNodeElements.constEnd(); ++it) { - prepareRenderNode(it.value()); - } - QRect r = viewportRect(); glViewport(r.x(), deviceRect().bottom() - r.bottom(), r.width(), r.height()); glClearColor(clearColor().redF(), clearColor().greenF(), clearColor().blueF(), clearColor().alphaF()); + + if (m_useDepthBuffer) { #if defined(QT_OPENGL_ES) - glClearDepthf(1); + glClearDepthf(1); #else - glClearDepth(1); + glClearDepth(1); #endif - + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + glDepthMask(true); + glDisable(GL_BLEND); + } else { + glDisable(GL_DEPTH_TEST); + glDepthMask(false); + } glDisable(GL_CULL_FACE); - glDisable(GL_BLEND); - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LESS); - glDepthMask(true); glColorMask(true, true, true, true); glDisable(GL_SCISSOR_TEST); glDisable(GL_STENCIL_TEST); @@ -2232,7 +2240,8 @@ void Renderer::renderBatches() } glEnable(GL_BLEND); - glDepthMask(false); + if (m_useDepthBuffer) + glDepthMask(false); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); if (Q_LIKELY(renderAlpha)) { @@ -2252,7 +2261,6 @@ void Renderer::renderBatches() updateStencilClip(0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - } void Renderer::deleteRemovedElements() @@ -2404,33 +2412,15 @@ void Renderer::render() m_vao->release(); } -void Renderer::prepareRenderNode(RenderNodeElement *e) +void Renderer::renderRenderNode(Batch *batch) { - if (e->fbo && e->fbo->size() != deviceRect().size()) { - delete e->fbo; - e->fbo = 0; - } + if (Q_UNLIKELY(debug_render)) + qDebug() << " -" << batch << "rendernode"; - if (!e->fbo) - e->fbo = new QOpenGLFramebufferObject(deviceRect().size(), QOpenGLFramebufferObject::CombinedDepthStencil); - e->fbo->bind(); + Q_ASSERT(batch->first->isRenderNode); + RenderNodeElement *e = (RenderNodeElement *) batch->first; - glDisable(GL_STENCIL_TEST); - glDisable(GL_SCISSOR_TEST); - glDisable(GL_DEPTH_TEST); - glDisable(GL_BLEND); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - glClearColor(0, 0, 0, 0); - glClear(GL_COLOR_BUFFER_BIT); - - QSGRenderNode::RenderState state; - QMatrix4x4 pm = projectionMatrix(); - state.projectionMatrix = ± - state.scissorEnabled = false; - state.stencilEnabled = false; + setActiveShader(0, 0); QSGNode *clip = e->renderNode->parent(); e->renderNode->m_clip_list = 0; @@ -2442,6 +2432,16 @@ void Renderer::prepareRenderNode(RenderNodeElement *e) clip = clip->parent(); } + updateClip(e->renderNode->m_clip_list, batch); + + QSGRenderNode::RenderState state; + QMatrix4x4 pm = projectionMatrix(); + state.projectionMatrix = ± + state.scissorEnabled = m_currentClipType & ScissorClip; + state.stencilEnabled = m_currentClipType & StencilClip; + state.scissorRect = m_current_scissor_rect; + state.stencilValue = m_current_stencil_value; + QSGNode *xform = e->renderNode->parent(); QMatrix4x4 matrix; while (xform != rootNode()) { @@ -2463,66 +2463,51 @@ void Renderer::prepareRenderNode(RenderNodeElement *e) opacity = opacity->parent(); } + glDisable(GL_STENCIL_TEST); + glDisable(GL_SCISSOR_TEST); + glDisable(GL_DEPTH_TEST); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + e->renderNode->render(state); e->renderNode->m_matrix = 0; + e->renderNode->m_clip_list = 0; - bindable()->bind(); -} - -void Renderer::renderRenderNode(Batch *batch) -{ - updateStencilClip(0); - m_currentClip = 0; - - setActiveShader(0, 0); - - if (!m_shaderManager->blitProgram) { - m_shaderManager->blitProgram = new QOpenGLShaderProgram(); - - QSGShaderSourceBuilder::initializeProgramFromFiles( - m_shaderManager->blitProgram, - QStringLiteral(":/scenegraph/shaders/rendernode.vert"), - QStringLiteral(":/scenegraph/shaders/rendernode.frag")); - m_shaderManager->blitProgram->bindAttributeLocation("av", 0); - m_shaderManager->blitProgram->bindAttributeLocation("at", 1); - m_shaderManager->blitProgram->link(); - - Q_ASSERT(m_shaderManager->blitProgram->isLinked()); + QSGRenderNode::StateFlags changes = e->renderNode->changedStates(); + if (changes & QSGRenderNode::ViewportState) { + QRect r = viewportRect(); + glViewport(r.x(), deviceRect().bottom() - r.bottom(), r.width(), r.height()); } - RenderNodeElement *e = static_cast<RenderNodeElement *>(batch->first); - glBindTexture(GL_TEXTURE_2D, e->fbo->texture()); - - m_shaderManager->blitProgram->bind(); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glEnable(GL_BLEND); - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + if (changes & QSGRenderNode::StencilState) { + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + glStencilMask(0xff); + glDisable(GL_STENCIL_TEST); + } - glEnableVertexAttribArray(0); - glEnableVertexAttribArray(1); + if (changes & (QSGRenderNode::StencilState | QSGRenderNode::ScissorState)) { + glDisable(GL_SCISSOR_TEST); + m_currentClip = 0; + m_currentClipType = NoClip; + } - float z = 1.0f - e->order * m_zRange; + if (changes & QSGRenderNode::DepthState) + glDisable(GL_DEPTH_TEST); - float av[] = { -1, -1, z, - 1, -1, z, - -1, 1, z, - 1, 1, z }; - float at[] = { 0, 0, - 1, 0, - 0, 1, - 1, 1 }; + if (changes & QSGRenderNode::ColorState) + bindable()->reactivate(); - glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, av); - glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, at); + if (changes & QSGRenderNode::BlendState) { + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + if (changes & QSGRenderNode::CullState) { + glFrontFace(isMirrored() ? GL_CW : GL_CCW); + glDisable(GL_CULL_FACE); + } - glDisableVertexAttribArray(0); - glDisableVertexAttribArray(1); - glBindTexture(GL_TEXTURE_2D, 0); } QT_END_NAMESPACE diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h index 001c3b21ab..0aa84da185 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h @@ -194,15 +194,11 @@ struct RenderNodeElement : public Element { RenderNodeElement(QSGRenderNode *rn) : Element(0) , renderNode(rn) - , fbo(0) { isRenderNode = true; } - ~RenderNodeElement(); - QSGRenderNode *renderNode; - QOpenGLFramebufferObject *fbo; }; struct BatchRootInfo { @@ -436,7 +432,6 @@ private: void renderUnmergedBatch(const Batch *batch); void updateClip(const QSGClipNode *clipList, const Batch *batch); const QMatrix4x4 &matrixForRoot(Node *node); - void prepareRenderNode(RenderNodeElement *e); void renderRenderNode(Batch *batch); void setActiveShader(QSGMaterialShader *program, ShaderManager::Shader *shader); @@ -460,6 +455,8 @@ private: bool m_partialRebuild; QSGNode *m_partialRebuildRoot; + bool m_useDepthBuffer; + QHash<QSGRenderNode *, RenderNodeElement *> m_renderNodeElements; QDataBuffer<Batch *> m_opaqueBatches; QDataBuffer<Batch *> m_alphaBatches; @@ -483,6 +480,7 @@ private: QSGMaterialShader *m_currentProgram; ShaderManager::Shader *m_currentShader; const QSGClipNode *m_currentClip; + ClipType m_currentClipType; // For minimal OpenGL core profile support QOpenGLVertexArrayObject *m_vao; diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp index 90803db9fe..829d33a0d7 100644 --- a/src/quick/scenegraph/qsgcontext.cpp +++ b/src/quick/scenegraph/qsgcontext.cpp @@ -210,10 +210,17 @@ void QSGContext::renderContextInitialized(QSGRenderContext *renderContext) static bool dumped = false; if (!dumped && qEnvironmentVariableIsSet("QSG_INFO")) { dumped = true; - qDebug() << "GL_VENDOR: " << (const char *) glGetString(GL_VENDOR); - qDebug() << "GL_RENDERER: " << (const char *) glGetString(GL_RENDERER); - qDebug() << "GL_VERSION: " << (const char *) glGetString(GL_VERSION); - qDebug() << "GL_EXTENSIONS:\n " << QByteArray((const char *) glGetString(GL_EXTENSIONS)).replace(" ", "\n ").constData(); + QSurfaceFormat format = renderContext->openglContext()->format(); + qDebug() << "R/G/B/A Buffers: " << format.redBufferSize() << format.greenBufferSize() << format.blueBufferSize() << format.alphaBufferSize(); + qDebug() << "Depth Buffer: " << format.depthBufferSize(); + qDebug() << "Stencil Buffer: " << format.stencilBufferSize(); + qDebug() << "Samples: " << format.samples(); + qDebug() << "GL_VENDOR: " << (const char *) glGetString(GL_VENDOR); + qDebug() << "GL_RENDERER: " << (const char *) glGetString(GL_RENDERER); + qDebug() << "GL_VERSION: " << (const char *) glGetString(GL_VERSION); + QSet<QByteArray> exts = renderContext->openglContext()->extensions(); + QByteArray all; foreach (const QByteArray &e, exts) all += ' ' + e; + qDebug() << "GL_EXTENSIONS: " << all.constData(); } d->mutex.unlock(); @@ -282,8 +289,10 @@ QSGGlyphNode *QSGContext::createGlyphNode(QSGRenderContext *rc) QSurfaceFormat QSGContext::defaultSurfaceFormat() const { QSurfaceFormat format; - format.setDepthBufferSize(24); - format.setStencilBufferSize(8); + static bool useDepth = qEnvironmentVariableIsEmpty("QSG_NO_DEPTH_BUFFER"); + static bool useStencil = qEnvironmentVariableIsEmpty("QSG_NO_STENCIL_BUFFER"); + format.setDepthBufferSize(useDepth ? 24 : 0); + format.setStencilBufferSize(useStencil ? 8 : 0); if (QQuickWindow::hasDefaultAlphaBuffer()) format.setAlphaBufferSize(8); format.setSwapBehavior(QSurfaceFormat::DoubleBuffer); @@ -349,6 +358,12 @@ QSGRenderContext::~QSGRenderContext() invalidate(); } +void QSGRenderContext::endSync() +{ + qDeleteAll(m_texturesToDelete); + m_texturesToDelete.clear(); +} + static QBasicMutex qsg_framerender_mutex; void QSGRenderContext::renderNextFrame(QSGRenderer *renderer, GLuint fboId) @@ -466,6 +481,9 @@ void QSGRenderContext::invalidate() if (!m_gl) return; + qDeleteAll(m_texturesToDelete); + m_texturesToDelete.clear(); + qDeleteAll(m_textures.values()); m_textures.clear(); @@ -608,10 +626,8 @@ QSGTexture *QSGRenderContext::textureForFactory(QQuickTextureFactory *factory, Q void QSGRenderContext::textureFactoryDestroyed(QObject *o) { m_mutex.lock(); - QSGTexture *t = m_textures.take(static_cast<QQuickTextureFactory *>(o)); + m_texturesToDelete << m_textures.take(static_cast<QQuickTextureFactory *>(o)); m_mutex.unlock(); - if (t) - t->deleteLater(); } QT_END_NAMESPACE diff --git a/src/quick/scenegraph/qsgcontext_p.h b/src/quick/scenegraph/qsgcontext_p.h index c562a909c5..c1bf78a018 100644 --- a/src/quick/scenegraph/qsgcontext_p.h +++ b/src/quick/scenegraph/qsgcontext_p.h @@ -94,6 +94,7 @@ public: virtual void invalidate(); virtual void renderNextFrame(QSGRenderer *renderer, GLuint fboId); + virtual void endSync(); virtual QSharedPointer<QSGDepthStencilBuffer> depthStencilBufferForFbo(QOpenGLFramebufferObject *fbo); QSGDepthStencilBufferManager *depthStencilBufferManager(); @@ -124,6 +125,7 @@ protected: QMutex m_mutex; QHash<QQuickTextureFactory *, QSGTexture *> m_textures; + QSet<QSGTexture *> m_texturesToDelete; QSGAtlasTexture::Manager *m_atlasManager; QSGDepthStencilBufferManager *m_depthStencilManager; diff --git a/src/quick/scenegraph/qsgdefaultrectanglenode.cpp b/src/quick/scenegraph/qsgdefaultrectanglenode.cpp index fb989fd6fb..810a503cee 100644 --- a/src/quick/scenegraph/qsgdefaultrectanglenode.cpp +++ b/src/quick/scenegraph/qsgdefaultrectanglenode.cpp @@ -385,7 +385,7 @@ void QSGDefaultRectangleNode::updateGeometry() int borderTail = 0; int outerAAHead = 0; int outerAATail = 0; - bool hasFill = m_color.rgba() != 0 || !stops.isEmpty(); + bool hasFill = m_color.alpha() > 0 || !stops.isEmpty(); if (hasFill) indexCount += fillIndexCount; if (m_antialiasing) { @@ -609,7 +609,7 @@ void QSGDefaultRectangleNode::updateGeometry() int borderTail = 0; int outerAAHead = 0; int outerAATail = 0; - bool hasFill = m_color.rgba() != 0 || !stops.isEmpty(); + bool hasFill = m_color.alpha() > 0 || !stops.isEmpty(); if (hasFill) indexCount += fillIndexCount; if (m_antialiasing) { diff --git a/src/quick/scenegraph/util/qsgatlastexture.cpp b/src/quick/scenegraph/util/qsgatlastexture.cpp index 6e0fdc7290..d080c59198 100644 --- a/src/quick/scenegraph/util/qsgatlastexture.cpp +++ b/src/quick/scenegraph/util/qsgatlastexture.cpp @@ -48,6 +48,7 @@ #include <QtGui/QGuiApplication> #include <QtGui/QScreen> #include <QtGui/QSurface> +#include <QtGui/qpa/qplatformnativeinterface.h> #include <private/qsgtexture_p.h> @@ -144,10 +145,21 @@ Atlas::Atlas(const QSize &size) { #ifdef QT_OPENGL_ES +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_NO_SDK) + QString *deviceName = + static_cast<QString *>(QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("AndroidDeviceName")); + static bool wrongfullyReportsBgra8888Support = deviceName->compare(QStringLiteral("samsung SM-T211"), Qt::CaseInsensitive) == 0 + || deviceName->compare(QStringLiteral("samsung SM-T210"), Qt::CaseInsensitive) == 0 + || deviceName->compare(QStringLiteral("samsung SM-T215"), Qt::CaseInsensitive) == 0; +#else + static bool wrongfullyReportsBgra8888Support = false; +#endif + const char *ext = (const char *) glGetString(GL_EXTENSIONS); - if (strstr(ext, "GL_EXT_bgra") - || strstr(ext, "GL_EXT_texture_format_BGRA8888") - || strstr(ext, "GL_IMG_texture_format_BGRA8888")) { + if (!wrongfullyReportsBgra8888Support + && (strstr(ext, "GL_EXT_bgra") + || strstr(ext, "GL_EXT_texture_format_BGRA8888") + || strstr(ext, "GL_IMG_texture_format_BGRA8888"))) { m_internalFormat = m_externalFormat = GL_BGRA; #ifdef Q_OS_IOS } else if (strstr(ext, "GL_APPLE_texture_format_BGRA8888")) { diff --git a/src/quick/scenegraph/util/qsgtexture.cpp b/src/quick/scenegraph/util/qsgtexture.cpp index d84ccb7a1f..ae1bec3f42 100644 --- a/src/quick/scenegraph/util/qsgtexture.cpp +++ b/src/quick/scenegraph/util/qsgtexture.cpp @@ -47,8 +47,10 @@ #include <qthread.h> #include <private/qqmlprofilerservice_p.h> #include <private/qqmlglobal_p.h> +#include <QtGui/qguiapplication.h> +#include <QtGui/qpa/qplatformnativeinterface.h> -#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID) +#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID) && !defined(__UCLIBC__) #define CAN_BACKTRACE_EXECINFO #endif @@ -679,14 +681,25 @@ void QSGPlainTexture::bind() GLenum externalFormat = GL_RGBA; GLenum internalFormat = GL_RGBA; +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_NO_SDK) + QString *deviceName = + static_cast<QString *>(QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("AndroidDeviceName")); + static bool wrongfullyReportsBgra8888Support = deviceName->compare(QStringLiteral("samsung SM-T211"), Qt::CaseInsensitive) == 0 + || deviceName->compare(QStringLiteral("samsung SM-T210"), Qt::CaseInsensitive) == 0 + || deviceName->compare(QStringLiteral("samsung SM-T215"), Qt::CaseInsensitive) == 0; +#else + static bool wrongfullyReportsBgra8888Support = false; +#endif + QOpenGLContext *context = QOpenGLContext::currentContext(); if (context->hasExtension(QByteArrayLiteral("GL_EXT_bgra"))) { externalFormat = GL_BGRA; #ifdef QT_OPENGL_ES internalFormat = GL_BGRA; #endif - } else if (context->hasExtension(QByteArrayLiteral("GL_EXT_texture_format_BGRA8888")) - || context->hasExtension(QByteArrayLiteral("GL_IMG_texture_format_BGRA8888"))) { + } else if (!wrongfullyReportsBgra8888Support + && (context->hasExtension(QByteArrayLiteral("GL_EXT_texture_format_BGRA8888")) + || context->hasExtension(QByteArrayLiteral("GL_IMG_texture_format_BGRA8888")))) { externalFormat = GL_BGRA; internalFormat = GL_BGRA; #ifdef Q_OS_IOS |