aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/compiler/qv4isel_p.cpp3
-rw-r--r--src/qml/compiler/qv4ssa.cpp3
-rw-r--r--src/qml/doc/src/qmllanguageref/modules/qmldir.qdoc14
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp19
-rw-r--r--src/qml/qml/qqmljavascriptexpression.cpp113
-rw-r--r--src/qml/qml/qqmljavascriptexpression_p.h5
-rw-r--r--src/quick/items/qquickitemview.cpp2
-rw-r--r--src/quick/items/qquickrectangle.cpp20
-rw-r--r--src/quick/items/qquickrectangle_p.h6
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp22
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h3
-rw-r--r--src/quick/scenegraph/coreapi/qsgmaterial.cpp6
-rw-r--r--src/quick/scenegraph/coreapi/qsgnode.cpp5
-rw-r--r--src/quick/scenegraph/coreapi/qsgnode.h1
-rw-r--r--src/quick/scenegraph/coreapi/qsgrenderer_p.h1
-rw-r--r--src/quick/scenegraph/qsgcontext.cpp34
-rw-r--r--src/quick/scenegraph/qsgcontext_p.h3
-rw-r--r--tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp7
18 files changed, 164 insertions, 103 deletions
diff --git a/src/qml/compiler/qv4isel_p.cpp b/src/qml/compiler/qv4isel_p.cpp
index b86837e167..644e06b59a 100644
--- a/src/qml/compiler/qv4isel_p.cpp
+++ b/src/qml/compiler/qv4isel_p.cpp
@@ -53,7 +53,8 @@
#include <cassert>
namespace {
-QTextStream qout(stderr, QIODevice::WriteOnly);
+Q_GLOBAL_STATIC_WITH_ARGS(QTextStream, qout, (stderr, QIODevice::WriteOnly));
+#define qout *qout()
} // anonymous namespace
using namespace QQmlJS;
diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp
index 52c546039c..5f79146127 100644
--- a/src/qml/compiler/qv4ssa.cpp
+++ b/src/qml/compiler/qv4ssa.cpp
@@ -77,7 +77,8 @@ using namespace V4IR;
namespace {
-QTextStream qout(stdout, QIODevice::WriteOnly);
+Q_GLOBAL_STATIC_WITH_ARGS(QTextStream, qout, (stderr, QIODevice::WriteOnly));
+#define qout *qout()
void showMeTheCode(Function *function)
{
diff --git a/src/qml/doc/src/qmllanguageref/modules/qmldir.qdoc b/src/qml/doc/src/qmllanguageref/modules/qmldir.qdoc
index c89d4a3c0d..88c866baf3 100644
--- a/src/qml/doc/src/qmllanguageref/modules/qmldir.qdoc
+++ b/src/qml/doc/src/qmllanguageref/modules/qmldir.qdoc
@@ -27,7 +27,7 @@
/*!
\page qtqml-modules-qmldir.html
\title Module Definition qmldir Files
-\brief How to write a qmldir file which defines a QML module
+\brief Defines a QML module
There are two distinct types of \c qmldir files:
\list
@@ -177,6 +177,18 @@ plugin <Name> [<Path>]
\code
plugin MyPluginLibrary
\endcode
+ \row
+ \li C++ Plugin Class
+ \li
+ \code
+ classname <C++ plugin class>
+ \endcode
+ \li Provides the class name of the C++ plugin used by the module.
+
+ This information is required for all the QML modules that depend
+ on a C++ plugin for additional functionality. Qt Quick applications
+ built with static linking cannot resolve the module imports without
+ this information.
\row
\li Type Information Description File Declaration
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index 58e0277395..fb87822a5a 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -447,11 +447,12 @@ ReturnedValue ScriptFunction::construct(Managed *that, CallData *callData)
callData->thisObject = obj.asReturnedValue();
ExecutionContext *ctx = context->newCallContext(f.getPointer(), callData);
+ ExecutionContextSaver ctxSaver(context);
+ ScopedValue result(scope, Q_V4_PROFILE(v4, ctx, f->function));
+
if (f->function->compiledFunction->hasQmlDependencies())
QmlContextWrapper::registerQmlDependencies(v4, f->function->compiledFunction);
- ExecutionContextSaver ctxSaver(context);
- ScopedValue result(scope, Q_V4_PROFILE(v4, ctx, f->function));
if (result->isObject())
return result.asReturnedValue();
return obj.asReturnedValue();
@@ -470,11 +471,13 @@ ReturnedValue ScriptFunction::call(Managed *that, CallData *callData)
CallContext *ctx = context->newCallContext(f, callData);
+ ExecutionContextSaver ctxSaver(context);
+ ScopedValue result(scope, Q_V4_PROFILE(v4, ctx, f->function));
+
if (f->function->compiledFunction->hasQmlDependencies())
QmlContextWrapper::registerQmlDependencies(ctx->engine, f->function->compiledFunction);
- ExecutionContextSaver ctxSaver(context);
- return Q_V4_PROFILE(v4, ctx, f->function);
+ return result.asReturnedValue();
}
DEFINE_OBJECT_VTABLE(SimpleScriptFunction);
@@ -542,11 +545,11 @@ ReturnedValue SimpleScriptFunction::construct(Managed *that, CallData *callData)
}
Q_ASSERT(v4->currentContext() == &ctx);
+ Scoped<Object> result(scope, Q_V4_PROFILE(v4, &ctx, f->function));
+
if (f->function->compiledFunction->hasQmlDependencies())
QmlContextWrapper::registerQmlDependencies(v4, f->function->compiledFunction);
- Scoped<Object> result(scope, Q_V4_PROFILE(v4, &ctx, f->function));
-
if (!result)
return callData->thisObject.asReturnedValue();
return result.asReturnedValue();
@@ -579,10 +582,12 @@ ReturnedValue SimpleScriptFunction::call(Managed *that, CallData *callData)
}
Q_ASSERT(v4->currentContext() == &ctx);
+ ScopedValue result(scope, Q_V4_PROFILE(v4, &ctx, f->function));
+
if (f->function->compiledFunction->hasQmlDependencies())
QmlContextWrapper::registerQmlDependencies(v4, f->function->compiledFunction);
- return Q_V4_PROFILE(v4, &ctx, f->function);
+ return result.asReturnedValue();
}
diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp
index b7673bdb37..b233b6e98c 100644
--- a/src/qml/qml/qqmljavascriptexpression.cpp
+++ b/src/qml/qml/qqmljavascriptexpression.cpp
@@ -138,8 +138,12 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QQmlContextData *context,
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context->engine);
+ // All code that follows must check with watcher before it accesses data members
+ // incase we have been deleted.
+ DeleteWatcher watcher(this);
+
Q_ASSERT(notifyOnValueChanged() || activeGuards.isEmpty());
- GuardCapture capture(context->engine, this);
+ GuardCapture capture(context->engine, this, &watcher);
QQmlEnginePrivate::PropertyCapture *lastPropertyCapture = ep->propertyCapture;
ep->propertyCapture = notifyOnValueChanged()?&capture:0;
@@ -148,10 +152,6 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QQmlContextData *context,
if (notifyOnValueChanged())
capture.guards.copyAndClearPrepend(activeGuards);
- // All code that follows must check with watcher before it accesses data members
- // incase we have been deleted.
- DeleteWatcher watcher(this);
-
QV4::ExecutionEngine *v4 = QV8Engine::getV4(ep->v8engine());
QV4::Scope scope(v4);
QV4::ScopedValue result(scope, QV4::Primitive::undefinedValue());
@@ -196,72 +196,75 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QQmlContextData *context,
void QQmlJavaScriptExpression::GuardCapture::captureProperty(QQmlNotifier *n)
{
- if (expression) {
+ if (watcher->wasDeleted())
+ return;
+
+ Q_ASSERT(expression);
+ // Try and find a matching guard
+ while (!guards.isEmpty() && !guards.first()->isConnected(n))
+ guards.takeFirst()->Delete();
+
+ Guard *g = 0;
+ if (!guards.isEmpty()) {
+ g = guards.takeFirst();
+ g->cancelNotify();
+ Q_ASSERT(g->isConnected(n));
+ } else {
+ g = Guard::New(expression, engine);
+ g->connect(n);
+ }
+
+ expression->activeGuards.prepend(g);
+}
+
+/*! \internal
+ \reimp
+
+ \a n is in the signal index range (see QObjectPrivate::signalIndex()).
+*/
+void QQmlJavaScriptExpression::GuardCapture::captureProperty(QObject *o, int c, int n)
+{
+ if (watcher->wasDeleted())
+ return;
+
+ Q_ASSERT(expression);
+ if (n == -1) {
+ if (!errorString) {
+ errorString = new QStringList;
+ QString preamble = QLatin1String("QQmlExpression: Expression ") +
+ expression->m_vtable->expressionIdentifier(expression) +
+ QLatin1String(" depends on non-NOTIFYable properties:");
+ errorString->append(preamble);
+ }
+
+ const QMetaObject *metaObj = o->metaObject();
+ QMetaProperty metaProp = metaObj->property(c);
+
+ QString error = QLatin1String(" ") +
+ QString::fromUtf8(metaObj->className()) +
+ QLatin1String("::") +
+ QString::fromUtf8(metaProp.name());
+ errorString->append(error);
+ } else {
// Try and find a matching guard
- while (!guards.isEmpty() && !guards.first()->isConnected(n))
+ while (!guards.isEmpty() && !guards.first()->isConnected(o, n))
guards.takeFirst()->Delete();
Guard *g = 0;
if (!guards.isEmpty()) {
g = guards.takeFirst();
g->cancelNotify();
- Q_ASSERT(g->isConnected(n));
+ Q_ASSERT(g->isConnected(o, n));
} else {
g = Guard::New(expression, engine);
- g->connect(n);
+ g->connect(o, n, engine);
}
expression->activeGuards.prepend(g);
}
}
-/*! \internal
- \reimp
-
- \a n is in the signal index range (see QObjectPrivate::signalIndex()).
-*/
-void QQmlJavaScriptExpression::GuardCapture::captureProperty(QObject *o, int c, int n)
-{
- if (expression) {
- if (n == -1) {
- if (!errorString) {
- errorString = new QStringList;
- QString preamble = QLatin1String("QQmlExpression: Expression ") +
- expression->m_vtable->expressionIdentifier(expression) +
- QLatin1String(" depends on non-NOTIFYable properties:");
- errorString->append(preamble);
- }
-
- const QMetaObject *metaObj = o->metaObject();
- QMetaProperty metaProp = metaObj->property(c);
-
- QString error = QLatin1String(" ") +
- QString::fromUtf8(metaObj->className()) +
- QLatin1String("::") +
- QString::fromUtf8(metaProp.name());
- errorString->append(error);
- } else {
-
- // Try and find a matching guard
- while (!guards.isEmpty() && !guards.first()->isConnected(o, n))
- guards.takeFirst()->Delete();
-
- Guard *g = 0;
- if (!guards.isEmpty()) {
- g = guards.takeFirst();
- g->cancelNotify();
- Q_ASSERT(g->isConnected(o, n));
- } else {
- g = Guard::New(expression, engine);
- g->connect(o, n, engine);
- }
-
- expression->activeGuards.prepend(g);
- }
- }
-}
-
void QQmlJavaScriptExpression::clearError()
{
if (m_vtable.hasValue()) {
diff --git a/src/qml/qml/qqmljavascriptexpression_p.h b/src/qml/qml/qqmljavascriptexpression_p.h
index 7d65f1c9cc..d0f10e498d 100644
--- a/src/qml/qml/qqmljavascriptexpression_p.h
+++ b/src/qml/qml/qqmljavascriptexpression_p.h
@@ -161,8 +161,8 @@ private:
friend void QQmlJavaScriptExpressionGuard_callback(QQmlNotifierEndpoint *, void **);
struct GuardCapture : public QQmlEnginePrivate::PropertyCapture {
- GuardCapture(QQmlEngine *engine, QQmlJavaScriptExpression *e)
- : engine(engine), expression(e), errorString(0) { }
+ GuardCapture(QQmlEngine *engine, QQmlJavaScriptExpression *e, DeleteWatcher *w)
+ : engine(engine), expression(e), watcher(w), errorString(0) { }
~GuardCapture() {
Q_ASSERT(guards.isEmpty());
@@ -174,6 +174,7 @@ private:
QQmlEngine *engine;
QQmlJavaScriptExpression *expression;
+ DeleteWatcher *watcher;
QFieldList<Guard, &Guard::next> guards;
QStringList *errorString;
};
diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp
index 10f134f7ae..30d0619f7a 100644
--- a/src/quick/items/qquickitemview.cpp
+++ b/src/quick/items/qquickitemview.cpp
@@ -1872,7 +1872,7 @@ void QQuickItemViewPrivate::layout()
prepareVisibleItemTransitions();
- QRectF viewBounds(0, position(), q->width(), q->height());
+ QRectF viewBounds(q->contentX(), q->contentY(), q->width(), q->height());
for (QList<FxViewItem*>::Iterator it = releasePendingTransition.begin();
it != releasePendingTransition.end(); ) {
FxViewItem *item = *it;
diff --git a/src/quick/items/qquickrectangle.cpp b/src/quick/items/qquickrectangle.cpp
index ee1b66f2b5..8d9f6b9d4a 100644
--- a/src/quick/items/qquickrectangle.cpp
+++ b/src/quick/items/qquickrectangle.cpp
@@ -255,6 +255,18 @@ QQmlListProperty<QQuickGradientStop> QQuickGradient::stops()
return QQmlListProperty<QQuickGradientStop>(this, m_stops);
}
+QGradientStops QQuickGradient::gradientStops() const
+{
+ QGradientStops stops;
+ for (int i = 0; i < m_stops.size(); ++i){
+ int j = 0;
+ while (j < stops.size() && stops.at(j).first < m_stops[i]->position())
+ j++;
+ stops.insert(j, QGradientStop(m_stops.at(i)->position(), m_stops.at(i)->color()));
+ }
+ return stops;
+}
+
void QQuickGradient::doUpdate()
{
emit updated();
@@ -492,13 +504,7 @@ QSGNode *QQuickRectangle::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData
QGradientStops stops;
if (d->gradient) {
- QList<QQuickGradientStop *> qxstops = d->gradient->m_stops;
- for (int i = 0; i < qxstops.size(); ++i){
- int j = 0;
- while (j < stops.size() && stops.at(j).first < qxstops[i]->position())
- j++;
- stops.insert(j, QGradientStop(qxstops.at(i)->position(), qxstops.at(i)->color()));
- }
+ stops = d->gradient->gradientStops();
}
rectangle->setGradientStops(stops);
diff --git a/src/quick/items/qquickrectangle_p.h b/src/quick/items/qquickrectangle_p.h
index 009512afd4..09b530c191 100644
--- a/src/quick/items/qquickrectangle_p.h
+++ b/src/quick/items/qquickrectangle_p.h
@@ -81,7 +81,7 @@ private:
bool m_valid : 1;
};
-class Q_AUTOTEST_EXPORT QQuickGradientStop : public QObject
+class Q_QUICK_PRIVATE_EXPORT QQuickGradientStop : public QObject
{
Q_OBJECT
@@ -105,7 +105,7 @@ private:
QColor m_color;
};
-class Q_AUTOTEST_EXPORT QQuickGradient : public QObject
+class Q_QUICK_PRIVATE_EXPORT QQuickGradient : public QObject
{
Q_OBJECT
@@ -118,6 +118,8 @@ public:
QQmlListProperty<QQuickGradientStop> stops();
+ QGradientStops gradientStops() const;
+
Q_SIGNALS:
void updated();
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
index f121e16523..30081093f2 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
@@ -143,11 +143,6 @@ ShaderManager::Shader *ShaderManager::prepareMaterial(QSGMaterial *material)
QSurfaceFormat::OpenGLContextProfile profile = ctx->format().profile();
QOpenGLShaderProgram *p = s->program();
- p->addShaderFromSourceCode(QOpenGLShader::Vertex,
- qsgShaderRewriter_insertZAttributes(s->vertexShader(), profile));
- p->addShaderFromSourceCode(QOpenGLShader::Fragment,
- s->fragmentShader());
-
char const *const *attr = s->attributeNames();
int i;
for (i = 0; attr[i]; ++i) {
@@ -155,14 +150,10 @@ ShaderManager::Shader *ShaderManager::prepareMaterial(QSGMaterial *material)
p->bindAttributeLocation(attr[i], i);
}
p->bindAttributeLocation("_qt_order", i);
-
- p->link();
- if (!p->isLinked()) {
- qDebug() << "Renderer failed shader compilation:" << endl << p->log();
+ context->compile(s, material, qsgShaderRewriter_insertZAttributes(s->vertexShader(), profile), 0);
+ context->initialize(s);
+ if (!p->isLinked())
return 0;
- }
-
- s->initialize();
shader = new Shader;
shader->program = s;
@@ -198,8 +189,8 @@ ShaderManager::Shader *ShaderManager::prepareMaterialNoRewrite(QSGMaterial *mate
#endif
QSGMaterialShader *s = static_cast<QSGMaterialShader *>(material->createShader());
- s->compile();
- s->initialize();
+ context->compile(s, material);
+ context->initialize(s);
shader = new Shader();
shader->program = s;
@@ -292,6 +283,7 @@ void Updater::updateStates(QSGNode *n)
m_added = 0;
m_transformChange = 0;
+ m_opacityChange = 0;
Node *sn = renderer->m_nodes.value(n, 0);
Q_ASSERT(sn);
@@ -779,7 +771,7 @@ Renderer::Renderer(QSGRenderContext *ctx)
m_shaderManager = ctx->findChild<ShaderManager *>(QStringLiteral("__qt_ShaderManager"), Qt::FindDirectChildrenOnly);
if (!m_shaderManager) {
- m_shaderManager = new ShaderManager();
+ m_shaderManager = new ShaderManager(ctx);
m_shaderManager->setObjectName(QStringLiteral("__qt_ShaderManager"));
m_shaderManager->setParent(ctx);
QObject::connect(ctx, SIGNAL(invalidated()), m_shaderManager, SLOT(invalidated()), Qt::DirectConnection);
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
index c38c483df4..7c06de774a 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
@@ -371,7 +371,7 @@ public:
float lastOpacity;
};
- ShaderManager() : blitProgram(0), visualizeProgram(0) { }
+ ShaderManager(QSGRenderContext *ctx) : blitProgram(0), visualizeProgram(0), context(ctx) { }
~ShaderManager() {
qDeleteAll(rewrittenShaders.values());
qDeleteAll(stockShaders.values());
@@ -389,6 +389,7 @@ public:
QOpenGLShaderProgram *blitProgram;
QOpenGLShaderProgram *visualizeProgram;
+ QSGRenderContext *context;
};
class Q_QUICK_PRIVATE_EXPORT Renderer : public QSGRenderer
diff --git a/src/quick/scenegraph/coreapi/qsgmaterial.cpp b/src/quick/scenegraph/coreapi/qsgmaterial.cpp
index 686d1438b4..4954fe20bb 100644
--- a/src/quick/scenegraph/coreapi/qsgmaterial.cpp
+++ b/src/quick/scenegraph/coreapi/qsgmaterial.cpp
@@ -257,9 +257,6 @@ const char *QSGMaterialShader::fragmentShader() const
State that is global for all uses of the shader, independent of the geometry
that is being drawn, can be setup in this function.
-
- If reimplemented, make sure to either call the base class implementation to
- enable the vertex attribute registers.
*/
void QSGMaterialShader::activate()
@@ -271,9 +268,6 @@ void QSGMaterialShader::activate()
/*!
This function is called by the scene graph to indicate that geometry will
no longer to be rendered using this shader.
-
- If reimplemented, make sure to either call the base class implementation to
- disable the vertex attribute registers.
*/
void QSGMaterialShader::deactivate()
diff --git a/src/quick/scenegraph/coreapi/qsgnode.cpp b/src/quick/scenegraph/coreapi/qsgnode.cpp
index b0c869c096..5c196b252c 100644
--- a/src/quick/scenegraph/coreapi/qsgnode.cpp
+++ b/src/quick/scenegraph/coreapi/qsgnode.cpp
@@ -648,10 +648,7 @@ void QSGNode::setFlags(Flags f, bool enabled)
/*!
- Marks this node with the states in \a bits as dirty.
-
- When a node is marked dirty, it recursively marks the parent chain
- as dirty and notify all connected renderers that the has dirty states.
+ Notifies all connected renderers that the node has dirty \a bits.
*/
void QSGNode::markDirty(DirtyState bits)
diff --git a/src/quick/scenegraph/coreapi/qsgnode.h b/src/quick/scenegraph/coreapi/qsgnode.h
index 60e7652e7a..f85184db90 100644
--- a/src/quick/scenegraph/coreapi/qsgnode.h
+++ b/src/quick/scenegraph/coreapi/qsgnode.h
@@ -161,6 +161,7 @@ protected:
private:
friend class QSGRootNode;
friend class QSGBatchRenderer::Renderer;
+ friend class QSGRenderer;
void init();
void destroy();
diff --git a/src/quick/scenegraph/coreapi/qsgrenderer_p.h b/src/quick/scenegraph/coreapi/qsgrenderer_p.h
index 296d6e2cfd..55c9444365 100644
--- a/src/quick/scenegraph/coreapi/qsgrenderer_p.h
+++ b/src/quick/scenegraph/coreapi/qsgrenderer_p.h
@@ -150,6 +150,7 @@ protected:
void addNodesToPreprocess(QSGNode *node);
void removeNodesToPreprocess(QSGNode *node);
+ void markNodeDirtyState(QSGNode *node, QSGNode::DirtyState state) { node->m_dirtyState |= state; }
QColor m_clear_color;
ClearMode m_clear_mode;
diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp
index dd00f75fae..9f58876def 100644
--- a/src/quick/scenegraph/qsgcontext.cpp
+++ b/src/quick/scenegraph/qsgcontext.cpp
@@ -631,4 +631,38 @@ void QSGRenderContext::textureFactoryDestroyed(QObject *o)
m_mutex.unlock();
}
+/*!
+ Compile \a shader, optionally using \a vertexCode and \a fragmentCode as
+ replacement for the source code supplied by \a shader.
+
+ If \a vertexCode or \a fragmentCode is supplied, the caller is responsible
+ for setting up attribute bindings.
+
+ \a material is supplied in case the implementation needs to take the
+ material flags into account.
+ */
+
+void QSGRenderContext::compile(QSGMaterialShader *shader, QSGMaterial *material, const char *vertexCode, const char *fragmentCode)
+{
+ Q_UNUSED(material);
+ if (vertexCode || fragmentCode) {
+ Q_ASSERT_X((material->flags() & QSGMaterial::CustomCompileStep) == 0,
+ "QSGRenderContext::compile()",
+ "materials with custom compile step cannot have custom vertex/fragment code");
+ QOpenGLShaderProgram *p = shader->program();
+ p->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexCode ? vertexCode : shader->vertexShader());
+ p->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentCode ? fragmentCode : shader->fragmentShader());
+ p->link();
+ if (!p->isLinked())
+ qWarning() << "shader compilation failed:" << endl << p->log();
+ } else {
+ shader->compile();
+ }
+}
+
+void QSGRenderContext::initialize(QSGMaterialShader *shader)
+{
+ shader->initialize();
+}
+
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/qsgcontext_p.h b/src/quick/scenegraph/qsgcontext_p.h
index 3b58cecd6a..f8d5588649 100644
--- a/src/quick/scenegraph/qsgcontext_p.h
+++ b/src/quick/scenegraph/qsgcontext_p.h
@@ -106,6 +106,9 @@ public:
virtual QSGTexture *createTextureNoAtlas(const QImage &image) const;
virtual QSGRenderer *createRenderer();
+ virtual void compile(QSGMaterialShader *shader, QSGMaterial *material, const char *vertexCode = 0, const char *fragmentCode = 0);
+ virtual void initialize(QSGMaterialShader *shader);
+
void registerFontengineForCleanup(QFontEngine *engine);
static QSGRenderContext *from(QOpenGLContext *context);
diff --git a/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp b/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp
index 1fed2ecda8..2ecb3c4725 100644
--- a/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp
+++ b/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp
@@ -81,6 +81,13 @@ void tst_qquickrectangle::gradient()
QCOMPARE(stops.at(&stops, 1)->position(), 1.0);
QCOMPARE(stops.at(&stops, 1)->color(), QColor("white"));
+ QGradientStops gradientStops = grad->gradientStops();
+ QCOMPARE(gradientStops.count(), 2);
+ QCOMPARE(gradientStops.at(0).first, 0.0);
+ QCOMPARE(gradientStops.at(0).second, QColor("gray"));
+ QCOMPARE(gradientStops.at(1).first, 1.0);
+ QCOMPARE(gradientStops.at(1).second, QColor("white"));
+
QMetaObject::invokeMethod(rect, "resetGradient");
grad = rect->gradient();