aboutsummaryrefslogtreecommitdiffstats
path: root/src/declarative/items
diff options
context:
space:
mode:
Diffstat (limited to 'src/declarative/items')
-rw-r--r--src/declarative/items/context2d/qsgcontext2d.cpp8
-rw-r--r--src/declarative/items/qsgborderimage.cpp15
-rw-r--r--src/declarative/items/qsgcanvas.cpp651
-rw-r--r--src/declarative/items/qsgcanvas.h30
-rw-r--r--src/declarative/items/qsgcanvas_p.h91
-rw-r--r--src/declarative/items/qsgflickable.cpp4
-rw-r--r--src/declarative/items/qsgimage.cpp61
-rw-r--r--src/declarative/items/qsgimage_p.h10
-rw-r--r--src/declarative/items/qsgimage_p_p.h4
-rw-r--r--src/declarative/items/qsgitem.cpp54
-rw-r--r--src/declarative/items/qsgitem.h9
-rw-r--r--src/declarative/items/qsgmousearea.cpp4
-rw-r--r--src/declarative/items/qsgmousearea_p_p.h2
-rw-r--r--src/declarative/items/qsgpainteditem.cpp6
-rw-r--r--src/declarative/items/qsgpathview.cpp4
-rw-r--r--src/declarative/items/qsgpincharea.cpp4
-rw-r--r--src/declarative/items/qsgshadereffect.cpp76
-rw-r--r--src/declarative/items/qsgshadereffect_p.h3
-rw-r--r--src/declarative/items/qsgshadereffectmesh_p.h3
-rw-r--r--src/declarative/items/qsgshadereffectnode.cpp40
-rw-r--r--src/declarative/items/qsgshadereffectnode_p.h10
-rw-r--r--src/declarative/items/qsgshadereffectsource.cpp157
-rw-r--r--src/declarative/items/qsgshadereffectsource_p.h22
-rw-r--r--src/declarative/items/qsgspriteengine.cpp2
-rw-r--r--src/declarative/items/qsgtext.cpp4
-rw-r--r--src/declarative/items/qsgtextedit.cpp20
-rw-r--r--src/declarative/items/qsgtextinput.cpp20
-rw-r--r--src/declarative/items/qsgtextnode.cpp9
-rw-r--r--src/declarative/items/qsgtextnode_p.h1
-rw-r--r--src/declarative/items/qsgview.cpp65
-rw-r--r--src/declarative/items/qsgview.h7
-rw-r--r--src/declarative/items/qsgview_p.h2
32 files changed, 772 insertions, 626 deletions
diff --git a/src/declarative/items/context2d/qsgcontext2d.cpp b/src/declarative/items/context2d/qsgcontext2d.cpp
index 4cfe1ba012..71bc7df980 100644
--- a/src/declarative/items/context2d/qsgcontext2d.cpp
+++ b/src/declarative/items/context2d/qsgcontext2d.cpp
@@ -43,13 +43,13 @@
#include "qsgcontext2d_p_p.h"
#include "private/qsgadaptationlayer_p.h"
#include "qsgcanvasitem_p.h"
-#include <QtOpenGL/qglframebufferobject.h>
+#include <QtGui/qopenglframebufferobject.h>
#include <QtCore/qdebug.h>
#include "private/qsgcontext_p.h"
-#include <QtGui/qgraphicsitem.h>
-#include <QtGui/qapplication.h>
-#include <QtGui/qgraphicseffect.h>
+#include <QtWidgets/qgraphicsitem.h>
+#include <QtWidgets/qapplication.h>
+#include <QtWidgets/qgraphicseffect.h>
#include <qdeclarativeinfo.h>
#include <QtCore/qmath.h>
#include "qdeclarativepixmapcache_p.h"
diff --git a/src/declarative/items/qsgborderimage.cpp b/src/declarative/items/qsgborderimage.cpp
index bd62eaf1bb..30b10321a0 100644
--- a/src/declarative/items/qsgborderimage.cpp
+++ b/src/declarative/items/qsgborderimage.cpp
@@ -582,11 +582,16 @@ QSGNode *QSGBorderImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *
node->setTexture(texture);
- const QSGScaleGrid *border = d->getScaleGrid();
- node->setInnerRect(QRectF(border->left(),
- border->top(),
- qMax(1, d->pix.width() - border->right() - border->left()),
- qMax(1, d->pix.height() - border->bottom() - border->top())));
+ // Don't implicitly create the scalegrid in the rendering thread...
+ if (d->border) {
+ const QSGScaleGrid *border = d->getScaleGrid();
+ node->setInnerRect(QRectF(border->left(),
+ border->top(),
+ qMax(1, d->pix.width() - border->right() - border->left()),
+ qMax(1, d->pix.height() - border->bottom() - border->top())));
+ } else {
+ node->setInnerRect(QRectF(0, 0, width(), height()));
+ }
node->setRect(QRectF(0, 0, width(), height()));
node->setFiltering(d->smooth ? QSGTexture::Linear : QSGTexture::Nearest);
node->setHorzontalTileMode(d->horizontalTileMode);
diff --git a/src/declarative/items/qsgcanvas.cpp b/src/declarative/items/qsgcanvas.cpp
index 845617c7a5..95ee95d0f7 100644
--- a/src/declarative/items/qsgcanvas.cpp
+++ b/src/declarative/items/qsgcanvas.cpp
@@ -50,12 +50,14 @@
#include <private/qsgrenderer_p.h>
#include <private/qsgflashnode_p.h>
+#include <private/qguiapplication_p.h>
+#include <QtGui/QPlatformInputContext>
+
#include <private/qabstractanimation_p.h>
#include <QtGui/qpainter.h>
-#include <QtGui/qgraphicssceneevent.h>
+#include <QtWidgets/qgraphicssceneevent.h>
#include <QtGui/qmatrix4x4.h>
-#include <QtGui/qinputcontext.h>
#include <QtCore/qvarlengtharray.h>
#include <QtCore/qabstractanimation.h>
@@ -63,26 +65,105 @@
QT_BEGIN_NAMESPACE
-DEFINE_BOOL_CONFIG_OPTION(qmlNoThreadedRenderer, QML_NO_THREADED_RENDERER)
DEFINE_BOOL_CONFIG_OPTION(qmlFixedAnimationStep, QML_FIXED_ANIMATION_STEP)
+DEFINE_BOOL_CONFIG_OPTION(qmlNoThreadedRenderer, QML_BAD_GUI_RENDER_LOOP)
+
+extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha);
+
+class QSGCanvasPlainRenderLoop : public QObject, public QSGCanvasRenderLoop
+{
+public:
+ QSGCanvasPlainRenderLoop()
+ : updatePending(false)
+ , animationRunning(false)
+ {
+ qWarning("QSGCanvas: using non-threaded render loop. Be very sure to not access scene graph "
+ "objects outside the QSGItem::updatePaintNode() call. Failing to do so will cause "
+ "your code to crash on other platforms!");
+ }
+
+ virtual void paint() {
+ if (animationRunning && animationDriver())
+ animationDriver()->advance();
+ syncSceneGraph();
+ makeCurrent();
+ glViewport(0, 0, size.width(), size.height());
+ renderSceneGraph(size);
+ swapBuffers();
+ updatePending = false;
+
+ if (animationRunning)
+ maybeUpdate();
+ }
+
+ virtual QImage grab() {
+ return qt_gl_read_framebuffer(size, false, false);
+ }
+
+ virtual void startRendering() {
+ if (!glContext()) {
+ createGLContext();
+ makeCurrent();
+ initializeSceneGraph();
+ } else {
+ makeCurrent();
+ }
+ maybeUpdate();
+ }
+
+ virtual void stopRendering() { }
+
+ virtual void maybeUpdate() {
+ if (!updatePending) {
+ QApplication::postEvent(this, new QEvent(QEvent::User));
+ updatePending = true;
+ }
+ }
+
+ virtual void animationStarted() {
+ animationRunning = true;
+ maybeUpdate();
+ }
+
+ virtual void animationStopped() {
+ animationRunning = false;
+ }
+
+ virtual bool isRunning() const { return glContext(); } // Event loop is always running...
+ virtual void resize(const QSize &s) { size = s; }
+ virtual void setWindowSize(const QSize &s) { size = s; }
+
+ bool event(QEvent *e) {
+ if (e->type() == QEvent::User) {
+ paint();
+ return true;
+ }
+ return QObject::event(e);
+ }
+
+ QSize size;
+
+ uint updatePending : 1;
+ uint animationRunning : 1;
+};
+
-extern Q_OPENGL_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha);
/*
Focus behavior
==============
-Prior to being added to a valid canvas items can set and clear focus with no
+Prior to being added to a valid canvas items can set and clear focus with no
effect. Only once items are added to a canvas (by way of having a parent set that
-already belongs to a canvas) do the focus rules apply. Focus goes back to
+already belongs to a canvas) do the focus rules apply. Focus goes back to
having no effect if an item is removed from a canvas.
When an item is moved into a new focus scope (either being added to a canvas
-for the first time, or having its parent changed), if the focus scope already has
+for the first time, or having its parent changed), if the focus scope already has
a scope focused item that takes precedence over the item being added. Otherwise,
-the focus of the added tree is used. In the case of of a tree of items being
+the focus of the added tree is used. In the case of of a tree of items being
added to a canvas for the first time, which may have a conflicted focus state (two
-or more items in one scope having focus set), the same rule is applied item by item -
+or more items in one scope having focus set), the same rule is applied item by item -
thus the first item that has focus will get it (assuming the scope doesn't already
have a scope focused item), and the other items will have their focus cleared.
*/
@@ -165,134 +246,50 @@ QSGRootItem::QSGRootItem()
{
}
-void QSGCanvas::paintEvent(QPaintEvent *)
+void QSGCanvas::exposeEvent(QExposeEvent *)
{
Q_D(QSGCanvas);
-
- if (!d->threadedRendering) {
-#ifdef FRAME_TIMING
- int lastFrame = frameTimer.restart();
-#endif
-
- if (d->animationDriver && d->animationDriver->isRunning())
- d->animationDriver->advance();
-
-#ifdef FRAME_TIMING
- int animationTime = frameTimer.elapsed();
-#endif
-
- Q_ASSERT(d->context);
-
- d->polishItems();
-
- QDeclarativeDebugTrace::addEvent(QDeclarativeDebugTrace::FramePaint);
- QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Painting);
-
-#ifdef FRAME_TIMING
- int polishTime = frameTimer.elapsed();
-#endif
-
- makeCurrent();
-
-#ifdef FRAME_TIMING
- int makecurrentTime = frameTimer.elapsed();
-#endif
-
- d->syncSceneGraph();
-
-#ifdef FRAME_TIMING
- int syncTime = frameTimer.elapsed();
-#endif
-
- d->renderSceneGraph(d->widgetSize);
-
- swapBuffers();
-
-#ifdef FRAME_TIMING
- printf("FrameTimes, last=%d, animations=%d, polish=%d, makeCurrent=%d, sync=%d, sgrender=%d, readback=%d, total=%d\n",
- lastFrame,
- animationTime,
- polishTime - animationTime,
- makecurrentTime - polishTime,
- syncTime - makecurrentTime,
- sceneGraphRenderTime - syncTime,
- readbackTime - sceneGraphRenderTime,
- frameTimer.elapsed());
-#endif
-
- QDeclarativeDebugTrace::endRange(QDeclarativeDebugTrace::Painting);
-
- if (d->animationDriver && d->animationDriver->isRunning())
- update();
- } else {
- if (updatesEnabled()) {
- d->thread->paint();
- setUpdatesEnabled(false);
- }
- }
+ d->thread->paint();
}
void QSGCanvas::resizeEvent(QResizeEvent *e)
{
Q_D(QSGCanvas);
- if (d->threadedRendering) {
- d->thread->resize(e->size());
- } else {
- d->widgetSize = e->size();
- d->viewportSize = d->widgetSize;
- QGLWidget::resizeEvent(e);
- }
+ d->thread->resize(size());
}
-void QSGCanvas::showEvent(QShowEvent *e)
+void QSGCanvas::animationStarted()
{
- Q_D(QSGCanvas);
-
- QGLWidget::showEvent(e);
-
- if (!d->contextFailed) {
- if (d->threadedRendering) {
- if (d->vsyncAnimations) {
- if (!d->animationDriver) {
- d->animationDriver = d->context->createAnimationDriver(this);
- connect(d->animationDriver, SIGNAL(started()), d->thread, SLOT(animationStarted()), Qt::DirectConnection);
- connect(d->animationDriver, SIGNAL(stopped()), d->thread, SLOT(animationStopped()), Qt::DirectConnection);
- }
- d->animationDriver->install();
- }
- d->thread->startRenderThread();
- setUpdatesEnabled(true);
- } else {
- makeCurrent();
-
- if (!d->context || !d->context->isReady()) {
- d->initializeSceneGraph();
- if (d->vsyncAnimations) {
- d->animationDriver = d->context->createAnimationDriver(this);
- connect(d->animationDriver, SIGNAL(started()), this, SLOT(update()));
- }
- }
+ d_func()->thread->animationStarted();
+}
- if (d->animationDriver)
- d->animationDriver->install();
- }
- }
+void QSGCanvas::animationStopped()
+{
+ d_func()->thread->animationStopped();
}
-void QSGCanvas::hideEvent(QHideEvent *e)
+void QSGCanvas::showEvent(QShowEvent *e)
{
Q_D(QSGCanvas);
-
- if (!d->contextFailed) {
- if (d->threadedRendering) {
- d->thread->stopRenderThread();
+ if (d->vsyncAnimations) {
+ if (!d->animationDriver) {
+ d->animationDriver = d->context->createAnimationDriver(this);
+ connect(d->animationDriver, SIGNAL(started()), this, SLOT(animationStarted()), Qt::DirectConnection);
+ connect(d->animationDriver, SIGNAL(stopped()), this, SLOT(animationStopped()), Qt::DirectConnection);
}
+ d->animationDriver->install();
+ }
- if (d->animationDriver)
- d->animationDriver->uninstall();
+ if (!d->thread->isRunning()) {
+ d->thread->setWindowSize(size());
+ d->thread->startRendering();
}
+}
- QGLWidget::hideEvent(e);
+void QSGCanvas::hideEvent(QHideEvent *e)
+{
+ Q_D(QSGCanvas);
+ d->thread->stopRendering();
}
@@ -313,7 +310,7 @@ void QSGCanvas::hideEvent(QHideEvent *e)
void QSGCanvas::setVSyncAnimations(bool enabled)
{
Q_D(QSGCanvas);
- if (isVisible()) {
+ if (visible()) {
qWarning("QSGCanvas::setVSyncAnimations: Cannot be changed when widget is shown");
return;
}
@@ -332,22 +329,28 @@ bool QSGCanvas::vsyncAnimations() const
return d->vsyncAnimations;
}
-
-
-void QSGCanvas::focusOutEvent(QFocusEvent *event)
+/*!
+ This function is an attempt to localize all uses of QInputContext::update in
+ one place up until the point where we have public API for the QInputContext API.
+ */
+void QSGCanvasPrivate::updateInputContext()
{
- Q_D(QSGCanvas);
- d->rootItem->setFocus(false);
- QGLWidget::focusOutEvent(event);
+ QPlatformInputContext *ic = QGuiApplicationPrivate::platformIntegration()->inputContext();
+ if (ic)
+ ic->update();
}
-
-void QSGCanvas::focusInEvent(QFocusEvent *event)
+/*!
+ This function is an attempt to localize all uses of QInputContext::reset in
+ one place up until the point where we have public API for the QInputContext API.
+ */
+void QSGCanvasPrivate::resetInputContext()
{
- Q_D(QSGCanvas);
- d->rootItem->setFocus(true);
- QGLWidget::focusInEvent(event);
+ QPlatformInputContext *ic = QGuiApplicationPrivate::platformIntegration()->inputContext();
+ if (ic)
+ ic->reset();
}
+
void QSGCanvasPrivate::initializeSceneGraph()
{
if (!context)
@@ -356,14 +359,12 @@ void QSGCanvasPrivate::initializeSceneGraph()
if (context->isReady())
return;
- QGLContext *glctx = const_cast<QGLContext *>(QGLContext::currentContext());
+ QOpenGLContext *glctx = const_cast<QOpenGLContext *>(QOpenGLContext::currentContext());
context->initialize(glctx);
- if (!threadedRendering) {
- Q_Q(QSGCanvas);
- QObject::connect(context->renderer(), SIGNAL(sceneGraphChanged()), q, SLOT(maybeUpdate()),
- Qt::DirectConnection);
- }
+ Q_Q(QSGCanvas);
+ QObject::connect(context->renderer(), SIGNAL(sceneGraphChanged()), q, SLOT(maybeUpdate()),
+ Qt::DirectConnection);
if (!QSGItemPrivate::get(rootItem)->itemNode()->parent()) {
context->rootNode()->appendChildNode(QSGItemPrivate::get(rootItem)->itemNode());
@@ -417,23 +418,17 @@ void QSGCanvas::sceneGraphChanged()
// d->needsRepaint = true;
}
-
QSGCanvasPrivate::QSGCanvasPrivate()
: rootItem(0)
, activeFocusItem(0)
, mouseGrabberItem(0)
, dirtyItemList(0)
, context(0)
- , contextFailed(false)
- , threadedRendering(false)
- , animationRunning(false)
- , renderThreadAwakened(false)
, vsyncAnimations(false)
, thread(0)
, animationDriver(0)
, renderTarget(0)
{
- threadedRendering = !qmlNoThreadedRenderer();
}
QSGCanvasPrivate::~QSGCanvasPrivate()
@@ -444,31 +439,36 @@ void QSGCanvasPrivate::init(QSGCanvas *c)
{
QUnifiedTimer::instance(true)->setConsistentTiming(qmlFixedAnimationStep());
- if (!c->context() || !c->context()->isValid()) {
- contextFailed = true;
- qWarning("QSGCanvas: Couldn't acquire a GL context.");
- }
-
q_ptr = c;
Q_Q(QSGCanvas);
- q->setAttribute(Qt::WA_AcceptTouchEvents);
- q->setFocusPolicy(Qt::StrongFocus);
-
rootItem = new QSGRootItem;
QSGItemPrivate *rootItemPrivate = QSGItemPrivate::get(rootItem);
rootItemPrivate->canvas = q;
rootItemPrivate->flags |= QSGItem::ItemIsFocusScope;
- context = QSGContext::createDefaultContext();
+ // QML always has focus. It is important that this call happens after the rootItem
+ // has a canvas..
+ rootItem->setFocus(true);
+
+ bool threaded = !qmlNoThreadedRenderer();
- if (threadedRendering) {
- thread = new QSGCanvasRenderThread;
- thread->renderer = q;
- thread->d = this;
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ThreadedOpenGL)) {
+ qWarning("QSGCanvas: platform does not support threaded rendering!");
+ threaded = false;
}
+ if (threaded)
+ thread = new QSGCanvasRenderThread();
+ else
+ thread = new QSGCanvasPlainRenderLoop();
+
+ thread->renderer = q;
+ thread->d = this;
+
+ context = QSGContext::createDefaultContext();
+ thread->moveContextToThread(context);
}
void QSGCanvasPrivate::sceneMouseEventForTransform(QGraphicsSceneMouseEvent &sceneEvent,
@@ -478,7 +478,7 @@ void QSGCanvasPrivate::sceneMouseEventForTransform(QGraphicsSceneMouseEvent &sce
sceneEvent.setLastPos(transform.map(sceneEvent.lastScenePos()));
for (int ii = 0; ii < 5; ++ii) {
if (sceneEvent.buttons() & (1 << ii)) {
- sceneEvent.setButtonDownPos((Qt::MouseButton)(1 << ii),
+ sceneEvent.setButtonDownPos((Qt::MouseButton)(1 << ii),
transform.map(sceneEvent.buttonDownScenePos((Qt::MouseButton)(1 << ii))));
}
}
@@ -516,8 +516,6 @@ Fill in the data in \a sceneEvent based on \a event. This method leaves the ite
*/
void QSGCanvasPrivate::sceneMouseEventFromMouseEvent(QGraphicsSceneMouseEvent &sceneEvent, QMouseEvent *event)
{
- Q_Q(QSGCanvas);
-
Q_ASSERT(event);
if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonDblClick) {
@@ -549,16 +547,16 @@ void QSGCanvasPrivate::sceneMouseEventFromMouseEvent(QGraphicsSceneMouseEvent &s
sceneEvent.setScenePos(event->pos());
sceneEvent.setScreenPos(event->globalPos());
sceneEvent.setLastScenePos(lastMousePosition);
- sceneEvent.setLastScreenPos(q->mapToGlobal(lastMousePosition));
+ sceneEvent.setLastScreenPos(lastMousePosition); // ### refactor: should do mapToGlobal
sceneEvent.setButtons(event->buttons());
sceneEvent.setButton(event->button());
sceneEvent.setModifiers(event->modifiers());
- sceneEvent.setWidget(q);
+// sceneEvent.setWidget(q); // ### refactor:
for (int ii = 0; ii < 5; ++ii) {
if (sceneEvent.buttons() & (1 << ii)) {
sceneEvent.setButtonDownScenePos((Qt::MouseButton)(1 << ii), buttonDownPositions[ii]);
- sceneEvent.setButtonDownScreenPos((Qt::MouseButton)(1 << ii), q->mapToGlobal(buttonDownPositions[ii]));
+ sceneEvent.setButtonDownScreenPos((Qt::MouseButton)(1 << ii), buttonDownPositions[ii]); // ### refactor: should do mapToGlobal
}
}
@@ -571,9 +569,9 @@ Translates the data in \a touchEvent to this canvas. This method leaves the ite
*/
void QSGCanvasPrivate::translateTouchEvent(QTouchEvent *touchEvent)
{
- Q_Q(QSGCanvas);
+// Q_Q(QSGCanvas);
- touchEvent->setWidget(q);
+// touchEvent->setWidget(q); // ### refactor...
QList<QTouchEvent::TouchPoint> touchPoints = touchEvent->touchPoints();
for (int i = 0; i < touchPoints.count(); ++i) {
@@ -626,8 +624,7 @@ void QSGCanvasPrivate::setFocusInScope(QSGItem *scope, QSGItem *item, FocusOptio
if (oldActiveFocusItem) {
#ifndef QT_NO_IM
- if (QInputContext *ic = inputContext())
- ic->reset();
+ resetInputContext();
#endif
activeFocusItem = 0;
@@ -671,13 +668,13 @@ void QSGCanvasPrivate::setFocusInScope(QSGItem *scope, QSGItem *item, FocusOptio
}
if (!(options & DontChangeFocusProperty)) {
- if (item != rootItem || q->hasFocus()) {
+ // if (item != rootItem || q->hasFocus()) { // ### refactor: focus handling...
itemPrivate->focus = true;
changed << item;
- }
+ // }
}
- if (newActiveFocusItem && q->hasFocus()) {
+ if (newActiveFocusItem) { // ### refactor: && q->hasFocus()) {
activeFocusItem = newActiveFocusItem;
QSGItemPrivate::get(newActiveFocusItem)->activeFocus = true;
@@ -695,7 +692,7 @@ void QSGCanvasPrivate::setFocusInScope(QSGItem *scope, QSGItem *item, FocusOptio
updateInputMethodData();
QFocusEvent event(QEvent::FocusIn, Qt::OtherFocusReason);
- q->sendEvent(newActiveFocusItem, &event);
+ q->sendEvent(newActiveFocusItem, &event);
} else {
updateInputMethodData();
}
@@ -736,8 +733,7 @@ void QSGCanvasPrivate::clearFocusInScope(QSGItem *scope, QSGItem *item, FocusOpt
Q_ASSERT(oldActiveFocusItem);
#ifndef QT_NO_IM
- if (QInputContext *ic = inputContext())
- ic->reset();
+ resetInputContext();
#endif
activeFocusItem = 0;
@@ -782,12 +778,12 @@ void QSGCanvasPrivate::clearFocusInScope(QSGItem *scope, QSGItem *item, FocusOpt
updateInputMethodData();
QFocusEvent event(QEvent::FocusIn, Qt::OtherFocusReason);
- q->sendEvent(newActiveFocusItem, &event);
+ q->sendEvent(newActiveFocusItem, &event);
} else {
updateInputMethodData();
}
- if (!changed.isEmpty())
+ if (!changed.isEmpty())
notifyFocusChangesRecur(changed.data(), changed.count() - 1);
}
@@ -811,16 +807,17 @@ void QSGCanvasPrivate::notifyFocusChangesRecur(QSGItem **items, int remaining)
itemPrivate->itemChange(QSGItem::ItemActiveFocusHasChanged, itemPrivate->activeFocus);
emit item->activeFocusChanged(itemPrivate->activeFocus);
}
- }
+ }
}
void QSGCanvasPrivate::updateInputMethodData()
{
- Q_Q(QSGCanvas);
- bool enabled = activeFocusItem
- && (QSGItemPrivate::get(activeFocusItem)->flags & QSGItem::ItemAcceptsInputMethod);
- q->setAttribute(Qt::WA_InputMethodEnabled, enabled);
- q->setInputMethodHints(enabled ? activeFocusItem->inputMethodHints() : Qt::ImhNone);
+ // Q_Q(QSGCanvas);
+ // ### refactor: port..
+// bool enabled = activeFocusItem
+// && (QSGItemPrivate::get(activeFocusItem)->flags & QSGItem::ItemAcceptsInputMethod);
+// q->setAttribute(Qt::WA_InputMethodEnabled, enabled);
+// q->setInputMethodHints(enabled ? activeFocusItem->inputMethodHints() : Qt::ImhNone);
}
QVariant QSGCanvas::inputMethodQuery(Qt::InputMethodQuery query) const
@@ -857,42 +854,18 @@ void QSGCanvasPrivate::cleanup(QSGNode *n)
q->maybeUpdate();
}
-static QGLFormat tweakFormat(const QGLFormat &format = QGLFormat::defaultFormat())
-{
- QGLFormat f = format;
- f.setSwapInterval(1);
- return f;
-}
-
-QSGCanvas::QSGCanvas(QWidget *parent, Qt::WindowFlags f)
- : QGLWidget(*(new QSGCanvasPrivate), tweakFormat(), parent, (QGLWidget *) 0, f)
-{
- Q_D(QSGCanvas);
-
- d->init(this);
-}
-
-QSGCanvas::QSGCanvas(const QGLFormat &format, QWidget *parent, Qt::WindowFlags f)
- : QGLWidget(*(new QSGCanvasPrivate), tweakFormat(format), parent, (QGLWidget *) 0, f)
-{
- Q_D(QSGCanvas);
-
- d->init(this);
-}
-QSGCanvas::QSGCanvas(QSGCanvasPrivate &dd, QWidget *parent, Qt::WindowFlags f)
-: QGLWidget(dd, tweakFormat(), parent, 0, f)
+QSGCanvas::QSGCanvas(QWindow *parent)
+ : QWindow(parent)
{
Q_D(QSGCanvas);
-
d->init(this);
}
-QSGCanvas::QSGCanvas(QSGCanvasPrivate &dd, const QGLFormat &format, QWidget *parent, Qt::WindowFlags f)
-: QGLWidget(dd, tweakFormat(format), parent, 0, f)
+QSGCanvas::QSGCanvas(QSGCanvasPrivate &dd, QWindow *parent)
+ : QWindow(dd, parent)
{
Q_D(QSGCanvas);
-
d->init(this);
}
@@ -900,8 +873,8 @@ QSGCanvas::~QSGCanvas()
{
Q_D(QSGCanvas);
- if (d->threadedRendering && d->thread->isRunning()) {
- d->thread->stopRenderThread();
+ if (d->thread->isRunning()) {
+ d->thread->stopRendering();
delete d->thread;
d->thread = 0;
}
@@ -913,41 +886,26 @@ QSGCanvas::~QSGCanvas()
delete d->rootItem; d->rootItem = 0;
d->cleanupNodes();
-
- if (!d->contextFailed) {
- // We need to remove all references to textures pointing to "our" QSGContext
- // from the QDeclarativePixmapCache. Call into the cache to remove the GL / Scene Graph
- // part of those cache entries.
- // To "play nice" with other GL apps that are potentially running in the GUI thread,
- // We get the current context and only temporarily make our own current
- QGLContext *currentContext = const_cast<QGLContext *>(QGLContext::currentContext());
- makeCurrent();
- extern void qt_declarative_pixmapstore_clean(QSGContext *context);
- qt_declarative_pixmapstore_clean(d->context);
- delete d->context;
- if (currentContext)
- currentContext->makeCurrent();
- }
}
QSGItem *QSGCanvas::rootItem() const
{
Q_D(const QSGCanvas);
-
+
return d->rootItem;
}
QSGItem *QSGCanvas::activeFocusItem() const
{
Q_D(const QSGCanvas);
-
+
return d->activeFocusItem;
}
QSGItem *QSGCanvas::mouseGrabberItem() const
{
Q_D(const QSGCanvas);
-
+
return d->mouseGrabberItem;
}
@@ -958,7 +916,7 @@ bool QSGCanvasPrivate::clearHover()
if (hoverItems.isEmpty())
return false;
- QPointF pos = q->mapFromGlobal(QCursor::pos());
+ QPointF pos = QCursor::pos(); // ### refactor: q->mapFromGlobal(QCursor::pos());
bool accepted = false;
foreach (QSGItem* item, hoverItems)
@@ -972,29 +930,6 @@ bool QSGCanvas::event(QEvent *e)
{
Q_D(QSGCanvas);
- if (e->type() == QEvent::User) {
- if (!d->thread->syncAlreadyHappened)
- d->thread->sync(false);
- else
- d->renderThreadAwakened = false;
-
- d->thread->syncAlreadyHappened = false;
-
- if (d->animationRunning && d->animationDriver) {
-#ifdef THREAD_DEBUG
- qDebug("GUI: Advancing animations...\n");
-#endif
-
- d->animationDriver->advance();
-
-#ifdef THREAD_DEBUG
- qDebug("GUI: Animations advanced...\n");
-#endif
- }
-
- return true;
- }
-
switch (e->type()) {
case QEvent::TouchBegin:
@@ -1024,7 +959,7 @@ bool QSGCanvas::event(QEvent *e)
break;
}
- return QGLWidget::event(e);
+ return QWindow::event(e);
}
void QSGCanvas::keyPressEvent(QKeyEvent *e)
@@ -1081,7 +1016,7 @@ bool QSGCanvasPrivate::deliverInitialMousePressEvent(QSGItem *item, QGraphicsSce
event->accept();
mouseGrabberItem = item;
q->sendEvent(item, event);
- if (event->isAccepted())
+ if (event->isAccepted())
return true;
mouseGrabberItem->ungrabMouse();
mouseGrabberItem = 0;
@@ -1095,10 +1030,10 @@ bool QSGCanvasPrivate::deliverMouseEvent(QGraphicsSceneMouseEvent *sceneEvent)
{
Q_Q(QSGCanvas);
- if (!mouseGrabberItem &&
+ if (!mouseGrabberItem &&
sceneEvent->type() == QEvent::GraphicsSceneMousePress &&
(sceneEvent->button() & sceneEvent->buttons()) == sceneEvent->buttons()) {
-
+
return deliverInitialMousePressEvent(rootItem, sceneEvent);
}
@@ -1118,7 +1053,7 @@ bool QSGCanvasPrivate::deliverMouseEvent(QGraphicsSceneMouseEvent *sceneEvent)
void QSGCanvas::mousePressEvent(QMouseEvent *event)
{
Q_D(QSGCanvas);
-
+
#ifdef MOUSE_DEBUG
qWarning() << "QSGCanvas::mousePressEvent()" << event->pos() << event->button() << event->buttons();
#endif
@@ -1133,13 +1068,13 @@ void QSGCanvas::mousePressEvent(QMouseEvent *event)
void QSGCanvas::mouseReleaseEvent(QMouseEvent *event)
{
Q_D(QSGCanvas);
-
+
#ifdef MOUSE_DEBUG
qWarning() << "QSGCanvas::mouseReleaseEvent()" << event->pos() << event->button() << event->buttons();
#endif
if (!d->mouseGrabberItem) {
- QGLWidget::mouseReleaseEvent(event);
+ QWindow::mouseReleaseEvent(event);
return;
}
@@ -1155,7 +1090,7 @@ void QSGCanvas::mouseReleaseEvent(QMouseEvent *event)
void QSGCanvas::mouseDoubleClickEvent(QMouseEvent *event)
{
Q_D(QSGCanvas);
-
+
#ifdef MOUSE_DEBUG
qWarning() << "QSGCanvas::mouseDoubleClickEvent()" << event->pos() << event->button() << event->buttons();
#endif
@@ -1169,7 +1104,7 @@ void QSGCanvas::mouseDoubleClickEvent(QMouseEvent *event)
else
event->ignore();
return;
- }
+ }
d->deliverMouseEvent(&sceneEvent);
event->setAccepted(sceneEvent.isAccepted());
@@ -1194,7 +1129,7 @@ bool QSGCanvasPrivate::sendHoverEvent(QEvent::Type type, QSGItem *item,
void QSGCanvas::mouseMoveEvent(QMouseEvent *event)
{
Q_D(QSGCanvas);
-
+
#ifdef MOUSE_DEBUG
qWarning() << "QSGCanvas::mouseMoveEvent()" << event->pos() << event->button() << event->buttons();
#endif
@@ -1462,7 +1397,7 @@ bool QSGCanvasPrivate::deliverTouchPoints(QSGItem *item, QTouchEvent *event, con
if (eventStates != Qt::TouchPointStationary) {
QTouchEvent touchEvent(eventType);
- touchEvent.setWidget(q);
+ // touchEvent.setWidget(q); // ### refactor: what is the consequence of not setting the widget?
touchEvent.setDeviceType(event->deviceType());
touchEvent.setModifiers(event->modifiers());
touchEvent.setTouchPointStates(eventStates);
@@ -1568,17 +1503,17 @@ bool QSGCanvasPrivate::sendFilteredMouseEvent(QSGItem *target, QSGItem *item, QG
return true;
QSGItemPrivate *targetPrivate = QSGItemPrivate::get(target);
- if (targetPrivate->filtersChildMouseEvents)
+ if (targetPrivate->filtersChildMouseEvents)
if (target->childMouseEventFilter(item, event))
return true;
return false;
}
-bool QSGCanvas::sendEvent(QSGItem *item, QEvent *e)
-{
+bool QSGCanvas::sendEvent(QSGItem *item, QEvent *e)
+{
Q_D(QSGCanvas);
-
+
if (!item) {
qWarning("QSGCanvas::sendEvent: Cannot send event to a null item");
return false;
@@ -1612,7 +1547,7 @@ bool QSGCanvas::sendEvent(QSGItem *item, QEvent *e)
case QEvent::GraphicsSceneMouseRelease:
case QEvent::GraphicsSceneMouseDoubleClick:
case QEvent::GraphicsSceneMouseMove:
- // XXX todo - should sendEvent be doing this? how does it relate to forwarded events?
+ // XXX todo - should sendEvent be doing this? how does it relate to forwarded events?
{
QGraphicsSceneMouseEvent *se = static_cast<QGraphicsSceneMouseEvent *>(e);
if (!d->sendFilteredMouseEvent(item->parentItem(), item, se)) {
@@ -1644,7 +1579,7 @@ bool QSGCanvas::sendEvent(QSGItem *item, QEvent *e)
break;
}
- return false;
+ return false;
}
void QSGCanvasPrivate::cleanupNodes()
@@ -1689,12 +1624,12 @@ void QSGCanvasPrivate::updateDirtyNode(QSGItem *item)
itemPriv->dirtyAttributes = 0;
if ((dirty & QSGItemPrivate::TransformUpdateMask) ||
- (dirty & QSGItemPrivate::Size && itemPriv->origin != QSGItem::TopLeft &&
+ (dirty & QSGItemPrivate::Size && itemPriv->origin != QSGItem::TopLeft &&
(itemPriv->scale != 1. || itemPriv->rotation != 0.))) {
QMatrix4x4 matrix;
- if (itemPriv->x != 0. || itemPriv->y != 0.)
+ if (itemPriv->x != 0. || itemPriv->y != 0.)
matrix.translate(itemPriv->x, itemPriv->y);
for (int ii = itemPriv->transforms.count() - 1; ii >= 0; --ii)
@@ -1842,10 +1777,10 @@ void QSGCanvasPrivate::updateDirtyNode(QSGItem *item)
if (dirty & QSGItemPrivate::ContentUpdateMask) {
if (itemPriv->flags & QSGItem::ItemHasContents) {
- updatePaintNodeData.transformNode = itemPriv->itemNode();
+ updatePaintNodeData.transformNode = itemPriv->itemNode();
itemPriv->paintNode = item->updatePaintNode(itemPriv->paintNode, &updatePaintNodeData);
- Q_ASSERT(itemPriv->paintNode == 0 ||
+ Q_ASSERT(itemPriv->paintNode == 0 ||
itemPriv->paintNode->parent() == 0 ||
itemPriv->paintNode->parent() == itemPriv->childContainerNode());
@@ -1916,28 +1851,8 @@ void QSGCanvas::maybeUpdate()
{
Q_D(QSGCanvas);
- if (d->threadedRendering && d->thread && d->thread->isRunning()) {
- Q_ASSERT_X(QThread::currentThread() == QApplication::instance()->thread() || d->thread->inSync,
- "QSGCanvas::update",
- "Function can only be called from GUI thread or during QSGItem::updatePaintNode()");
-
- if (d->thread->inSync) {
- d->thread->isExternalUpdatePending = true;
-
- } else if (!d->renderThreadAwakened) {
-#ifdef THREAD_DEBUG
- printf("GUI: doing update...\n");
-#endif
- d->renderThreadAwakened = true;
- d->thread->lockInGui();
- d->thread->isExternalUpdatePending = true;
- if (d->thread->isRenderBlocked)
- d->thread->wake();
- d->thread->unlockInGui();
- }
- } else if (!d->animationDriver || !d->animationDriver->isRunning()) {
- update();
- }
+ if (d->thread && d->thread->isRunning())
+ d->thread->maybeUpdate();
}
/*!
@@ -1977,7 +1892,7 @@ QSGEngine *QSGCanvas::sceneGraphEngine() const
the rendering.
*/
-void QSGCanvas::setRenderTarget(QGLFramebufferObject *fbo)
+void QSGCanvas::setRenderTarget(QOpenGLFramebufferObject *fbo)
{
Q_D(QSGCanvas);
if (d->context && d->context && QThread::currentThread() != d->context->thread()) {
@@ -1996,7 +1911,7 @@ void QSGCanvas::setRenderTarget(QGLFramebufferObject *fbo)
The default is to render to the surface of the canvas, in which
case the render target is 0.
*/
-QGLFramebufferObject *QSGCanvas::renderTarget() const
+QOpenGLFramebufferObject *QSGCanvas::renderTarget() const
{
Q_D(const QSGCanvas);
return d->renderTarget;
@@ -2009,17 +1924,21 @@ QGLFramebufferObject *QSGCanvas::renderTarget() const
This function might not work if the view is not visible.
\warning Calling this function will cause performance problems.
+
+ \warning This function can only be called from the GUI thread.
*/
QImage QSGCanvas::grabFrameBuffer()
{
Q_D(QSGCanvas);
- if (d->threadedRendering)
- return d->thread ? d->thread->grab() : QImage();
- else {
- // render a fresh copy of the scene graph in the current thread.
- d->renderSceneGraph(size());
- return QGLWidget::grabFrameBuffer(false);
- }
+ return d->thread ? d->thread->grab() : QImage();
+}
+
+
+
+void QSGCanvasRenderLoop::createGLContext()
+{
+ gl = new QOpenGLContext();
+ gl->create();
}
@@ -2029,12 +1948,14 @@ void QSGCanvasRenderThread::run()
qDebug("QML Rendering Thread Started");
#endif
- renderer->makeCurrent();
-
- if (!d->context->isReady())
- d->initializeSceneGraph();
+ if (!glContext()) {
+ createGLContext();
+ makeCurrent();
+ initializeSceneGraph();
+ } else {
+ makeCurrent();
+ }
-
while (!shouldExit) {
lock();
@@ -2059,7 +1980,7 @@ void QSGCanvasRenderThread::run()
#ifdef THREAD_DEBUG
printf(" RenderThread: aquired sync lock...\n");
#endif
- QApplication::postEvent(renderer, new QEvent(QEvent::User));
+ QApplication::postEvent(this, new QEvent(QEvent::User));
#ifdef THREAD_DEBUG
printf(" RenderThread: going to sleep...\n");
#endif
@@ -2072,7 +1993,7 @@ void QSGCanvasRenderThread::run()
printf(" RenderThread: Doing locked sync\n");
#endif
inSync = true;
- d->syncSceneGraph();
+ syncSceneGraph();
inSync = false;
// Wake GUI after sync to let it continue animating and event processing.
@@ -2088,7 +2009,7 @@ void QSGCanvasRenderThread::run()
printf(" RenderThread: rendering... %d x %d\n", windowSize.width(), windowSize.height());
#endif
- d->renderSceneGraph(windowSize);
+ renderSceneGraph(windowSize);
// The content of the target buffer is undefined after swap() so grab needs
// to happen before swap();
@@ -2104,8 +2025,7 @@ void QSGCanvasRenderThread::run()
printf(" RenderThread: wait for swap...\n");
#endif
- renderer->swapBuffers();
-
+ swapBuffers();
#ifdef THREAD_DEBUG
printf(" RenderThread: swap complete...\n");
#endif
@@ -2121,7 +2041,7 @@ void QSGCanvasRenderThread::run()
// but we don't want to lock an extra time.
wake();
- if (!d->animationRunning && !isExternalUpdatePending && !shouldExit && !doGrab) {
+ if (!animationRunning && !isExternalUpdatePending && !shouldExit && !doGrab) {
#ifdef THREAD_DEBUG
printf(" RenderThread: nothing to do, going to sleep...\n");
#endif
@@ -2131,13 +2051,16 @@ void QSGCanvasRenderThread::run()
}
unlock();
+
+ // Process any "deleteLater" objects...
+ QCoreApplication::processEvents();
}
#ifdef THREAD_DEBUG
- printf(" RenderThread: exited... Good Night!\n");
+ printf(" RenderThread: render loop exited... Good Night!\n");
#endif
- renderer->doneCurrent();
+ doneCurrent();
lock();
hasExited = true;
@@ -2146,6 +2069,40 @@ void QSGCanvasRenderThread::run()
#endif
wake();
unlock();
+
+#ifdef THREAD_DEBUG
+ printf(" RenderThread: All done...\n");
+#endif
+}
+
+
+
+bool QSGCanvasRenderThread::event(QEvent *e)
+{
+ Q_ASSERT(QThread::currentThread() == qApp->thread());
+
+ if (e->type() == QEvent::User) {
+ if (!syncAlreadyHappened)
+ sync(false);
+
+ syncAlreadyHappened = false;
+
+ if (animationRunning && animationDriver()) {
+#ifdef THREAD_DEBUG
+ qDebug("GUI: Advancing animations...\n");
+#endif
+
+ animationDriver()->advance();
+
+#ifdef THREAD_DEBUG
+ qDebug("GUI: Animations advanced...\n");
+#endif
+ }
+
+ return true;
+ }
+
+ return QThread::event(e);
}
@@ -2165,20 +2122,18 @@ void QSGCanvasRenderThread::sync(bool guiAlreadyLocked)
#ifdef THREAD_DEBUG
printf("GUI: sync - %s\n", guiAlreadyLocked ? "outside event" : "inside event");
#endif
- Q_ASSERT(d->threadedRendering);
-
if (!guiAlreadyLocked)
- d->thread->lockInGui();
+ lockInGui();
- d->renderThreadAwakened = false;
+ renderThreadAwakened = false;
- d->polishItems();
+ polishItems();
- d->thread->wake();
- d->thread->wait();
+ wake();
+ wait();
if (!guiAlreadyLocked)
- d->thread->unlockInGui();
+ unlockInGui();
}
@@ -2228,7 +2183,7 @@ void QSGCanvasRenderThread::animationStarted()
lockInGui();
- d->animationRunning = true;
+ animationRunning = true;
if (isRenderBlocked)
wake();
@@ -2245,7 +2200,7 @@ void QSGCanvasRenderThread::animationStopped()
#endif
lockInGui();
- d->animationRunning = false;
+ animationRunning = false;
unlockInGui();
}
@@ -2266,10 +2221,6 @@ void QSGCanvasRenderThread::paint()
wait();
}
unlockInGui();
-
- // paint is only called for the inital show. After that we will do all
- // drawing ourselves, so block future updates..
- renderer->setUpdatesEnabled(false);
}
@@ -2300,7 +2251,7 @@ void QSGCanvasRenderThread::resize(const QSize &size)
-void QSGCanvasRenderThread::startRenderThread()
+void QSGCanvasRenderThread::startRendering()
{
#ifdef THREAD_DEBUG
printf("GUI: Starting Render Thread\n");
@@ -2309,14 +2260,12 @@ void QSGCanvasRenderThread::startRenderThread()
shouldExit = false;
isGuiBlocked = 0;
isGuiBlockPending = false;
-
- renderer->doneCurrent();
start();
}
-void QSGCanvasRenderThread::stopRenderThread()
+void QSGCanvasRenderThread::stopRendering()
{
#ifdef THREAD_DEBUG
printf("GUI: stopping render thread\n");
@@ -2348,6 +2297,11 @@ void QSGCanvasRenderThread::stopRenderThread()
// Actually wait for the thread to terminate. Otherwise we can delete it
// too early and crash.
QThread::wait();
+
+#ifdef THREAD_DEBUG
+ printf("GUI: thread has terminated and we're all good..\n");
+#endif
+
}
@@ -2357,6 +2311,11 @@ QImage QSGCanvasRenderThread::grab()
if (!isRunning())
return QImage();
+ if (QThread::currentThread() != qApp->thread()) {
+ qWarning("QSGCanvas::grabFrameBuffer: can only be called from the GUI thread");
+ return QImage();
+ }
+
#ifdef THREAD_DEBUG
printf("GUI: doing a pixelwise grab..\n");
#endif
@@ -2381,6 +2340,30 @@ QImage QSGCanvasRenderThread::grab()
}
+
+void QSGCanvasRenderThread::maybeUpdate()
+{
+ Q_ASSERT_X(QThread::currentThread() == QApplication::instance()->thread() || inSync,
+ "QSGCanvas::update",
+ "Function can only be called from GUI thread or during QSGItem::updatePaintNode()");
+
+ if (inSync) {
+ isExternalUpdatePending = true;
+
+ } else if (!renderThreadAwakened) {
+#ifdef THREAD_DEBUG
+ printf("GUI: doing update...\n");
+#endif
+ renderThreadAwakened = true;
+ lockInGui();
+ isExternalUpdatePending = true;
+ if (isRenderBlocked)
+ wake();
+ unlockInGui();
+ }
+}
+
+
#include "moc_qsgcanvas.cpp"
QT_END_NAMESPACE
diff --git a/src/declarative/items/qsgcanvas.h b/src/declarative/items/qsgcanvas.h
index a5f69ff559..e364ee88f5 100644
--- a/src/declarative/items/qsgcanvas.h
+++ b/src/declarative/items/qsgcanvas.h
@@ -43,8 +43,8 @@
#define QSGCANVAS_H
#include <QtCore/qmetatype.h>
-#include <QtOpenGL/qgl.h>
-#include <QtGui/qwidget.h>
+#include <QtGui/qopengl.h>
+#include <QtWidgets/qwidget.h>
QT_BEGIN_HEADER
@@ -55,15 +55,15 @@ QT_MODULE(Declarative)
class QSGItem;
class QSGEngine;
class QSGCanvasPrivate;
-class QGLFramebufferObject;
+class QOpenGLFramebufferObject;
-class Q_DECLARATIVE_EXPORT QSGCanvas : public QGLWidget
+class Q_DECLARATIVE_EXPORT QSGCanvas : public QWindow
{
Q_OBJECT
Q_DECLARE_PRIVATE(QSGCanvas)
public:
- QSGCanvas(QWidget *parent = 0, Qt::WindowFlags f = 0);
- QSGCanvas(const QGLFormat &format, QWidget *parent = 0, Qt::WindowFlags f = 0);
+ QSGCanvas(QWindow *parent = 0);
+
virtual ~QSGCanvas();
QSGItem *rootItem() const;
@@ -82,25 +82,24 @@ public:
QImage grabFrameBuffer();
- void setRenderTarget(QGLFramebufferObject *fbo);
- QGLFramebufferObject *renderTarget() const;
+ void setRenderTarget(QOpenGLFramebufferObject *fbo);
+ QOpenGLFramebufferObject *renderTarget() const;
+
+signals:
+ void frameSwapped();
Q_SIGNALS:
void sceneGraphInitialized();
protected:
- QSGCanvas(QSGCanvasPrivate &dd, QWidget *parent = 0, Qt::WindowFlags f = 0);
- QSGCanvas(QSGCanvasPrivate &dd, const QGLFormat &format, QWidget *parent = 0, Qt::WindowFlags f = 0);
+ QSGCanvas(QSGCanvasPrivate &dd, QWindow *parent = 0);
- virtual void paintEvent(QPaintEvent *);
+ virtual void exposeEvent(QExposeEvent *);
virtual void resizeEvent(QResizeEvent *);
virtual void showEvent(QShowEvent *);
virtual void hideEvent(QHideEvent *);
- virtual void focusOutEvent(QFocusEvent *);
- virtual void focusInEvent(QFocusEvent *);
-
virtual bool event(QEvent *);
virtual void keyPressEvent(QKeyEvent *);
virtual void keyReleaseEvent(QKeyEvent *);
@@ -116,9 +115,12 @@ protected:
private Q_SLOTS:
void sceneGraphChanged();
void maybeUpdate();
+ void animationStarted();
+ void animationStopped();
private:
friend class QSGItem;
+ friend class QSGCanvasRenderLoop;
Q_DISABLE_COPY(QSGCanvas)
};
diff --git a/src/declarative/items/qsgcanvas_p.h b/src/declarative/items/qsgcanvas_p.h
index d26b311e59..e5347f53ae 100644
--- a/src/declarative/items/qsgcanvas_p.h
+++ b/src/declarative/items/qsgcanvas_p.h
@@ -64,8 +64,10 @@
#include <QtCore/qmutex.h>
#include <QtCore/qwaitcondition.h>
#include <private/qwidget_p.h>
-#include <private/qgl_p.h>
-#include <QtOpenGL/qglframebufferobject.h>
+#include <private/qwindow_p.h>
+#include <private/qopengl_p.h>
+#include <qopenglcontext.h>
+#include <QtGui/qopenglframebufferobject.h>
QT_BEGIN_NAMESPACE
@@ -80,9 +82,9 @@ public:
class QSGCanvasPrivate;
class QTouchEvent;
-class QSGCanvasRenderThread;
+class QSGCanvasRenderLoop;
-class QSGCanvasPrivate : public QGLWidgetPrivate
+class QSGCanvasPrivate : public QWindowPrivate
{
public:
Q_DECLARE_PUBLIC(QSGCanvas)
@@ -141,6 +143,9 @@ public:
void syncSceneGraph();
void renderSceneGraph(const QSize &size);
+ void updateInputContext();
+ void resetInputContext();
+
QSGItem::UpdatePaintNodeData updatePaintNodeData;
QSGItem *dirtyItemList;
@@ -156,32 +161,77 @@ public:
QSGContext *context;
- uint contextFailed : 1;
- uint threadedRendering : 1;
- uint animationRunning: 1;
- uint renderThreadAwakened : 1;
-
uint vsyncAnimations : 1;
- QSGCanvasRenderThread *thread;
+ QSGCanvasRenderLoop *thread;
QSize widgetSize;
QSize viewportSize;
QAnimationDriver *animationDriver;
- QGLFramebufferObject *renderTarget;
+ QOpenGLFramebufferObject *renderTarget;
QHash<int, QSGItem *> itemForTouchPointId;
};
+class QSGCanvasRenderLoop
+{
+public:
+ QSGCanvasRenderLoop()
+ : d(0)
+ , renderer(0)
+ , gl(0)
+ {
+ }
+ virtual ~QSGCanvasRenderLoop()
+ {
+ delete gl;
+ }
+
+ friend class QSGCanvasPrivate;
+
+ virtual void paint() = 0;
+ virtual void resize(const QSize &size) = 0;
+ virtual void startRendering() = 0;
+ virtual void stopRendering() = 0;
+ virtual QImage grab() = 0;
+ virtual void setWindowSize(const QSize &size) = 0;
+ virtual void maybeUpdate() = 0;
+ virtual bool isRunning() const = 0;
+ virtual void animationStarted() = 0;
+ virtual void animationStopped() = 0;
+ virtual void moveContextToThread(QSGContext *) { }
+
+protected:
+ void initializeSceneGraph() { d->initializeSceneGraph(); }
+ void syncSceneGraph() { d->syncSceneGraph(); }
+ void renderSceneGraph(const QSize &size) { d->renderSceneGraph(size); }
+ void polishItems() { d->polishItems(); }
+ QAnimationDriver *animationDriver() const { return d->animationDriver; }
+
+ inline QOpenGLContext *glContext() const { return gl; }
+ void createGLContext();
+ void makeCurrent() { gl->makeCurrent(renderer); }
+ void doneCurrent() { gl->doneCurrent(); }
+ void swapBuffers() {
+ gl->swapBuffers(renderer);
+ emit renderer->frameSwapped();
+ }
+
+private:
+ QSGCanvasPrivate *d;
+ QSGCanvas *renderer;
+ QOpenGLContext *gl;
+};
-class QSGCanvasRenderThread : public QThread
+class QSGCanvasRenderThread : public QThread, public QSGCanvasRenderLoop
{
Q_OBJECT
public:
QSGCanvasRenderThread()
: mutex(QMutex::NonRecursive)
+ , animationRunning(false)
, isGuiBlocked(0)
, isPaintCompleted(false)
, isGuiBlockPending(false)
@@ -192,6 +242,7 @@ public:
, doGrab(false)
, shouldExit(false)
, hasExited(false)
+ , renderThreadAwakened(false)
{}
inline void lock() { mutex.lock(); }
@@ -204,10 +255,16 @@ public:
void paint();
void resize(const QSize &size);
- void startRenderThread();
- void stopRenderThread();
+ void startRendering();
+ void stopRendering();
void exhaustSyncEvent();
void sync(bool guiAlreadyLocked);
+ bool isRunning() const { return QThread::isRunning(); }
+ void setWindowSize(const QSize &size) { windowSize = size; }
+ void maybeUpdate();
+ void moveContextToThread(QSGContext *c) { c->moveToThread(this); }
+
+ bool event(QEvent *);
QImage grab();
@@ -222,9 +279,7 @@ public:
QSize windowSize;
QSize renderedSize;
- QSGCanvas *renderer;
- QSGCanvasPrivate *d;
-
+ uint animationRunning: 1;
int isGuiBlocked;
uint isPaintCompleted : 1;
uint isGuiBlockPending : 1;
@@ -232,10 +287,10 @@ public:
uint isExternalUpdatePending : 1;
uint syncAlreadyHappened : 1;
uint inSync : 1;
-
uint doGrab : 1;
uint shouldExit : 1;
uint hasExited : 1;
+ uint renderThreadAwakened : 1;
QImage grabContent;
diff --git a/src/declarative/items/qsgflickable.cpp b/src/declarative/items/qsgflickable.cpp
index d62197f7d6..e63698eca7 100644
--- a/src/declarative/items/qsgflickable.cpp
+++ b/src/declarative/items/qsgflickable.cpp
@@ -45,8 +45,8 @@
#include "qsgcanvas_p.h"
#include <QtDeclarative/qdeclarativeinfo.h>
-#include <QtGui/qgraphicssceneevent.h>
-#include <QtGui/qapplication.h>
+#include <QtWidgets/qgraphicssceneevent.h>
+#include <QtWidgets/qapplication.h>
#include "qplatformdefs.h"
QT_BEGIN_NAMESPACE
diff --git a/src/declarative/items/qsgimage.cpp b/src/declarative/items/qsgimage.cpp
index e2e766ff0a..cb12c177cd 100644
--- a/src/declarative/items/qsgimage.cpp
+++ b/src/declarative/items/qsgimage.cpp
@@ -42,6 +42,8 @@
#include "qsgimage_p.h"
#include "qsgimage_p_p.h"
+#include <private/qsgtextureprovider_p.h>
+
#include <private/qsgcontext_p.h>
#include <private/qsgadaptationlayer_p.h>
@@ -50,6 +52,36 @@
QT_BEGIN_NAMESPACE
+class QSGImageTextureProvider : public QSGTextureProvider
+{
+ Q_OBJECT
+public:
+ QSGImageTextureProvider(const QSGImage *imageItem)
+ : d((QSGImagePrivate *) QSGItemPrivate::get(imageItem))
+ , m_texture(0)
+ , m_smooth(false)
+ {
+ }
+
+ QSGTexture *texture() const {
+ if (m_texture) {
+ m_texture->setFiltering(m_smooth ? QSGTexture::Linear : QSGTexture::Nearest);
+ m_texture->setMipmapFiltering(QSGTexture::Nearest);
+ m_texture->setHorizontalWrapMode(QSGTexture::ClampToEdge);
+ m_texture->setVerticalWrapMode(QSGTexture::ClampToEdge);
+ }
+ return m_texture;
+ }
+
+ friend class QSGImage;
+
+ QSGImagePrivate *d;
+ QSGTexture *m_texture;
+ bool m_smooth;
+};
+
+#include "qsgimage.moc"
+
QSGImagePrivate::QSGImagePrivate()
: fillMode(QSGImage::Stretch)
, paintedWidth(0)
@@ -57,6 +89,7 @@ QSGImagePrivate::QSGImagePrivate()
, pixmapChanged(false)
, hAlign(QSGImage::AlignHCenter)
, vAlign(QSGImage::AlignVCenter)
+ , provider(0)
{
}
@@ -127,6 +160,9 @@ QSGImage::QSGImage(QSGImagePrivate &dd, QSGItem *parent)
QSGImage::~QSGImage()
{
+ Q_D(QSGImage);
+ if (d->provider)
+ d->provider->deleteLater();
}
void QSGImagePrivate::setPixmap(const QPixmap &pixmap)
@@ -500,17 +536,20 @@ QRectF QSGImage::boundingRect() const
return QRectF(0, 0, qMax(width(), d->paintedWidth), qMax(height(), d->paintedHeight));
}
-QSGTexture *QSGImage::texture() const
+QSGTextureProvider *QSGImage::textureProvider() const
{
Q_D(const QSGImage);
- QSGTexture *t = d->pix.texture(d->sceneGraphContext());
- if (t) {
- t->setFiltering(QSGItemPrivate::get(this)->smooth ? QSGTexture::Linear : QSGTexture::Nearest);
- t->setMipmapFiltering(QSGTexture::None);
- t->setHorizontalWrapMode(QSGTexture::ClampToEdge);
- t->setVerticalWrapMode(QSGTexture::ClampToEdge);
+ if (!d->provider) {
+ // Make sure it gets thread affinity on the rendering thread so deletion works properly..
+ Q_ASSERT_X(d->canvas
+ && d->sceneGraphContext()
+ && QThread::currentThread() == d->sceneGraphContext()->thread(),
+ "QSGImage::textureProvider",
+ "Cannot be used outside the GUI thread");
+ const_cast<QSGImagePrivate *>(d)->provider = new QSGImageTextureProvider(this);
}
- return t;
+
+ return d->provider;
}
QSGNode *QSGImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
@@ -519,6 +558,12 @@ QSGNode *QSGImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
QSGTexture *texture = d->pix.texture(d->sceneGraphContext());
+ // Copy over the current texture state into the texture provider...
+ if (d->provider) {
+ d->provider->m_smooth = d->smooth;
+ d->provider->m_texture = texture;
+ }
+
if (!texture || width() <= 0 || height() <= 0) {
delete oldNode;
return 0;
diff --git a/src/declarative/items/qsgimage_p.h b/src/declarative/items/qsgimage_p.h
index 4faf96dfa0..9bf1d910d1 100644
--- a/src/declarative/items/qsgimage_p.h
+++ b/src/declarative/items/qsgimage_p.h
@@ -53,7 +53,7 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Declarative)
class QSGImagePrivate;
-class Q_AUTOTEST_EXPORT QSGImage : public QSGImageBase, public QSGTextureProvider
+class Q_AUTOTEST_EXPORT QSGImage : public QSGImageBase
{
Q_OBJECT
Q_ENUMS(FillMode)
@@ -63,12 +63,9 @@ class Q_AUTOTEST_EXPORT QSGImage : public QSGImageBase, public QSGTextureProvide
Q_PROPERTY(FillMode fillMode READ fillMode WRITE setFillMode NOTIFY fillModeChanged)
Q_PROPERTY(qreal paintedWidth READ paintedWidth NOTIFY paintedGeometryChanged)
Q_PROPERTY(qreal paintedHeight READ paintedHeight NOTIFY paintedGeometryChanged)
- Q_PROPERTY(QSGTexture *texture READ texture)
Q_PROPERTY(HAlignment horizontalAlignment READ horizontalAlignment WRITE setHorizontalAlignment NOTIFY horizontalAlignmentChanged)
Q_PROPERTY(VAlignment verticalAlignment READ verticalAlignment WRITE setVerticalAlignment NOTIFY verticalAlignmentChanged)
- Q_INTERFACES(QSGTextureProvider)
-
public:
QSGImage(QSGItem *parent=0);
~QSGImage();
@@ -90,14 +87,15 @@ public:
QRectF boundingRect() const;
- virtual QSGTexture *texture() const;
-
HAlignment horizontalAlignment() const;
void setHorizontalAlignment(HAlignment align);
VAlignment verticalAlignment() const;
void setVerticalAlignment(VAlignment align);
+ bool isTextureProvider() const { return true; }
+ QSGTextureProvider *textureProvider() const;
+
Q_SIGNALS:
void fillModeChanged();
void paintedGeometryChanged();
diff --git a/src/declarative/items/qsgimage_p_p.h b/src/declarative/items/qsgimage_p_p.h
index d0b109942a..9f8b9716c7 100644
--- a/src/declarative/items/qsgimage_p_p.h
+++ b/src/declarative/items/qsgimage_p_p.h
@@ -59,7 +59,7 @@
QT_BEGIN_NAMESPACE
-class QSGImagePrivate;
+class QSGImageTextureProvider;
class QSGImagePrivate : public QSGImageBasePrivate
{
@@ -76,6 +76,8 @@ public:
bool pixmapChanged : 1;
QSGImage::HAlignment hAlign;
QSGImage::VAlignment vAlign;
+
+ QSGImageTextureProvider *provider;
};
QT_END_NAMESPACE
diff --git a/src/declarative/items/qsgitem.cpp b/src/declarative/items/qsgitem.cpp
index c2abc46ab9..a7797630c0 100644
--- a/src/declarative/items/qsgitem.cpp
+++ b/src/declarative/items/qsgitem.cpp
@@ -51,9 +51,8 @@
#include <QtDeclarative/qdeclarativeengine.h>
#include <QtDeclarative/qdeclarativecomponent.h>
#include <QtDeclarative/qdeclarativeinfo.h>
-#include <QtGui/qgraphicstransform.h>
+#include <QtWidgets/qgraphicstransform.h>
#include <QtGui/qpen.h>
-#include <QtGui/qinputcontext.h>
#include <QtCore/qdebug.h>
#include <QtCore/qcoreevent.h>
#include <QtCore/qnumeric.h>
@@ -2046,9 +2045,6 @@ void QSGItemPrivate::initCanvas(InitializationState *state, QSGCanvas *c)
if (canvas && polishScheduled)
QSGCanvasPrivate::get(canvas)->itemsToPolish.insert(q);
- if (canvas && hoverEnabled && !canvas->hasMouseTracking())
- canvas->setMouseTracking(true);
-
itemNodeInstance = 0;
opacityNode = 0;
clipNode = 0;
@@ -2929,11 +2925,10 @@ void QSGItem::setInputMethodHints(Qt::InputMethodHints hints)
if (!d->canvas || d->canvas->activeFocusItem() != this)
return;
- QSGCanvasPrivate::get(d->canvas)->updateInputMethodData();
+ QSGCanvasPrivate *cd = QSGCanvasPrivate::get(d->canvas);
+ cd->updateInputMethodData();
#ifndef QT_NO_IM
- if (d->canvas->hasFocus())
- if (QInputContext *inputContext = d->canvas->inputContext())
- inputContext->update();
+ cd->updateInputContext();
#endif
}
@@ -2941,9 +2936,8 @@ void QSGItem::updateMicroFocus()
{
#ifndef QT_NO_IM
Q_D(QSGItem);
- if (d->canvas && d->canvas->hasFocus())
- if (QInputContext *inputContext = d->canvas->inputContext())
- inputContext->update();
+ if (d->canvas)
+ QSGCanvasPrivate::get(d->canvas)->updateInputContext();
#endif
}
@@ -4415,7 +4409,7 @@ bool QSGItem::isUnderMouse() const
return false;
QPoint cursorPos = QCursor::pos();
- if (QRectF(0, 0, width(), height()).contains(mapFromScene(d->canvas->mapFromGlobal(cursorPos))))
+ if (QRectF(0, 0, width(), height()).contains(mapFromScene(cursorPos))) // ### refactor: d->canvas->mapFromGlobal(cursorPos))))
return true;
return false;
}
@@ -4430,22 +4424,6 @@ void QSGItem::setAcceptHoverEvents(bool enabled)
{
Q_D(QSGItem);
d->hoverEnabled = enabled;
-
- if (d->canvas){
- QSGCanvasPrivate *c = QSGCanvasPrivate::get(d->canvas);
- if (d->hoverEnabled){
- if (!d->canvas->hasMouseTracking())
- d->canvas->setMouseTracking(true);
- if (isUnderMouse())
- c->hoverItems.prepend(this);
- c->sendHoverEvent(QEvent::HoverEnter, this, c->lastMousePosition, c->lastMousePosition,
- QApplication::keyboardModifiers(), true);
- } else {
- c->hoverItems.removeAll(this);
- c->sendHoverEvent(QEvent::HoverLeave, this, c->lastMousePosition, c->lastMousePosition,
- QApplication::keyboardModifiers(), true);
- }
- }
}
void QSGItem::grabMouse()
@@ -4980,6 +4958,24 @@ qint64 QSGItemPrivate::restart(QElapsedTimer &t)
return ((QElapsedTimerConsistentTimeHack*)&t)->restart();
}
+/*!
+ \fn bool QSGItem::isTextureProvider() const
+
+ Returns true if this item is a texture provider. The default
+ implementation returns false.
+
+ This function can be called from any thread.
+ */
+
+/*!
+ \fn QSGTextureProvider *QSGItem::textureProvider() const
+
+ Returns the texture provider for an item. The default implementation
+ returns 0.
+
+ This function may only be called on the rendering thread.
+ */
+
QT_END_NAMESPACE
#include <moc_qsgitem.cpp>
diff --git a/src/declarative/items/qsgitem.h b/src/declarative/items/qsgitem.h
index 249a2065dd..02a7a33ed8 100644
--- a/src/declarative/items/qsgitem.h
+++ b/src/declarative/items/qsgitem.h
@@ -48,9 +48,9 @@
#include <QtCore/QObject>
#include <QtCore/QList>
-#include <QtGui/qgraphicssceneevent.h>
+#include <QtWidgets/qgraphicssceneevent.h>
#include <QtGui/qfont.h>
-#include <QtGui/qaction.h>
+#include <QtWidgets/qaction.h>
QT_BEGIN_HEADER
@@ -95,6 +95,8 @@ class QSGEngine;
class QTouchEvent;
class QSGNode;
class QSGTransformNode;
+class QSGTextureProvider;
+
class Q_DECLARATIVE_EXPORT QSGItem : public QObject, public QDeclarativeParserStatus
{
Q_OBJECT
@@ -305,6 +307,9 @@ public:
UpdatePaintNodeData();
};
+ virtual bool isTextureProvider() const { return false; }
+ virtual QSGTextureProvider *textureProvider() const { return 0; }
+
public Q_SLOTS:
void update();
void updateMicroFocus();
diff --git a/src/declarative/items/qsgmousearea.cpp b/src/declarative/items/qsgmousearea.cpp
index 0f9d0a4780..7d86d2e248 100644
--- a/src/declarative/items/qsgmousearea.cpp
+++ b/src/declarative/items/qsgmousearea.cpp
@@ -45,8 +45,8 @@
#include "qsgevent.h"
#include "qsgevents_p_p.h"
-#include <QtGui/qgraphicssceneevent.h>
-#include <QtGui/qapplication.h>
+#include <QtWidgets/qgraphicssceneevent.h>
+#include <QtWidgets/qapplication.h>
#include <float.h>
diff --git a/src/declarative/items/qsgmousearea_p_p.h b/src/declarative/items/qsgmousearea_p_p.h
index 30ec75c3a9..ff531c627c 100644
--- a/src/declarative/items/qsgmousearea_p_p.h
+++ b/src/declarative/items/qsgmousearea_p_p.h
@@ -56,7 +56,7 @@
#include "qsgitem_p.h"
-#include <QtGui/qgraphicssceneevent.h>
+#include <QtWidgets/qgraphicssceneevent.h>
#include <QtCore/qbasictimer.h>
QT_BEGIN_NAMESPACE
diff --git a/src/declarative/items/qsgpainteditem.cpp b/src/declarative/items/qsgpainteditem.cpp
index 95aa2b4fb2..76d5a00e90 100644
--- a/src/declarative/items/qsgpainteditem.cpp
+++ b/src/declarative/items/qsgpainteditem.cpp
@@ -56,10 +56,10 @@ QT_BEGIN_NAMESPACE
The QSGPaintedItem makes it possible to use the QPainter API with the QML Scene Graph.
It sets up a textured rectangle in the Scene Graph and uses a QPainter to paint
- onto the texture. The render target can be either a QImage or a QGLFramebufferObject.
+ onto the texture. The render target can be either a QImage or a QOpenGLFramebufferObject.
When the render target is a QImage, QPainter first renders into the image then
the content is uploaded to the texture.
- When a QGLFramebufferObject is used, QPainter paints directly onto the texture.
+ When a QOpenGLFramebufferObject is used, QPainter paints directly onto the texture.
Call update() to trigger a repaint.
To enable QPainter to do anti-aliased rendering, use setAntialiasing().
@@ -84,7 +84,7 @@ QT_BEGIN_NAMESPACE
can potentially be slow if the item is large. This render target allows high quality
anti-aliasing and fast item resizing.
- \value FramebufferObject QPainter paints into a QGLFramebufferObject using the GL
+ \value FramebufferObject QPainter paints into a QOpenGLFramebufferObject using the GL
paint engine. Painting can be faster as no texture upload is required, but anti-aliasing
quality is not as good as if using an image. This render target allows faster rendering
in some cases, but you should avoid using it if the item is resized often.
diff --git a/src/declarative/items/qsgpathview.cpp b/src/declarative/items/qsgpathview.cpp
index 88c5df9cfb..2c3e3cee71 100644
--- a/src/declarative/items/qsgpathview.cpp
+++ b/src/declarative/items/qsgpathview.cpp
@@ -48,8 +48,8 @@
#include <private/qlistmodelinterface_p.h>
#include <QtGui/qevent.h>
-#include <QtGui/qgraphicssceneevent.h>
-#include <QtGui/qapplication.h>
+#include <QtWidgets/qgraphicssceneevent.h>
+#include <QtWidgets/qapplication.h>
#include <QtCore/qmath.h>
#include <math.h>
diff --git a/src/declarative/items/qsgpincharea.cpp b/src/declarative/items/qsgpincharea.cpp
index b37dcaf646..54c32e5025 100644
--- a/src/declarative/items/qsgpincharea.cpp
+++ b/src/declarative/items/qsgpincharea.cpp
@@ -42,8 +42,8 @@
#include "qsgpincharea_p_p.h"
#include "qsgcanvas.h"
-#include <QtGui/qgraphicssceneevent.h>
-#include <QtGui/qapplication.h>
+#include <QtWidgets/qgraphicssceneevent.h>
+#include <QtWidgets/qapplication.h>
#include <float.h>
#include <math.h>
diff --git a/src/declarative/items/qsgshadereffect.cpp b/src/declarative/items/qsgshadereffect.cpp
index c5ea64dcd2..b81e7f15af 100644
--- a/src/declarative/items/qsgshadereffect.cpp
+++ b/src/declarative/items/qsgshadereffect.cpp
@@ -49,8 +49,11 @@
#include <private/qsgtextureprovider_p.h>
#include "qsgcanvas.h"
+#include <qsgimage_p.h>
+#include <qsgshadereffectsource_p.h>
+
#include <QtCore/qsignalmapper.h>
-#include <QtOpenGL/qglframebufferobject.h>
+#include <QtGui/qopenglframebufferobject.h>
QT_BEGIN_NAMESPACE
@@ -402,7 +405,7 @@ void QSGShaderEffect::setSource(const QVariant &var, int index)
SourceData &source = m_sources[index];
- source.item = 0;
+ source.sourceObject = 0;
if (var.isNull()) {
return;
} else if (!qVariantCanConvert<QObject *>(var)) {
@@ -411,21 +414,23 @@ void QSGShaderEffect::setSource(const QVariant &var, int index)
}
QObject *obj = qVariantValue<QObject *>(var);
-
- QSGTextureProvider *int3rface = QSGTextureProvider::from(obj);
- if (!int3rface) {
- qWarning("Could not assign property '%s', did not implement QSGTextureProvider.", source.name.constData());
+ QSGItem *item = qobject_cast<QSGItem *>(obj);
+ if (!item || !item->isTextureProvider()) {
+ qWarning("ShaderEffect: source uniform [%s] is not assigned a valid texture provider: %s [%s]",
+ qPrintable(source.name), qPrintable(obj->objectName()), obj->metaObject()->className());
+ return;
}
- source.item = qobject_cast<QSGItem *>(obj);
+ source.sourceObject = item;
+
// TODO: Find better solution.
- // 'source.item' needs a canvas to get a scenegraph node.
+ // 'item' needs a canvas to get a scenegraph node.
// The easiest way to make sure it gets a canvas is to
// make it a part of the same item tree as 'this'.
- if (source.item && source.item->parentItem() == 0) {
- source.item->setParentItem(this);
- source.item->setVisible(false);
+ if (item && item->parentItem() == 0) {
+ item->setParentItem(this);
+ item->setVisible(false);
}
}
@@ -484,8 +489,9 @@ void QSGShaderEffect::reset()
for (int i = 0; i < m_sources.size(); ++i) {
const SourceData &source = m_sources.at(i);
delete source.mapper;
- if (source.item && source.item->parentItem() == this)
- source.item->setParentItem(0);
+ QSGItem *item = qobject_cast<QSGItem *>(source.sourceObject);
+ if (item && item->parentItem() == this)
+ item->setParentItem(0);
}
m_sources.clear();
@@ -558,7 +564,7 @@ void QSGShaderEffect::lookThroughShaderCode(const QByteArray &code)
SourceData d;
d.mapper = new QSignalMapper;
d.name = name;
- d.item = 0;
+ d.sourceObject = 0;
m_sources.append(d);
}
}
@@ -576,14 +582,22 @@ QSGNode *QSGShaderEffect::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData
{
QSGShaderEffectNode *node = static_cast<QSGShaderEffectNode *>(oldNode);
+ // In the case of a bad vertex shader, don't try to create a node...
+ if (m_source.attributeNames.isEmpty()) {
+ if (node)
+ delete node;
+ return 0;
+ }
+
if (!node) {
node = new QSGShaderEffectNode;
- node->setMaterial(&m_material);
m_programDirty = true;
m_dirtyData = true;
m_dirtyGeometry = true;
}
+ QSGShaderEffectMaterial *material = node->shaderMaterial();
+
if (m_dirtyMesh) {
node->setGeometry(0);
m_dirtyMesh = false;
@@ -616,45 +630,45 @@ QSGNode *QSGShaderEffect::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData
s.vertexCode = qt_default_vertex_code;
s.className = metaObject()->className();
- m_material.setProgramSource(s);
+ material->setProgramSource(s);
node->markDirty(QSGNode::DirtyMaterial);
m_programDirty = false;
}
// Update blending
- if (bool(m_material.flags() & QSGMaterial::Blending) != m_blending) {
- m_material.setFlag(QSGMaterial::Blending, m_blending);
+ if (bool(material->flags() & QSGMaterial::Blending) != m_blending) {
+ material->setFlag(QSGMaterial::Blending, m_blending);
node->markDirty(QSGNode::DirtyMaterial);
}
- if (int(m_material.cullMode()) != int(m_cullMode)) {
- m_material.setCullMode(QSGShaderEffectMaterial::CullMode(m_cullMode));
+ if (int(material->cullMode()) != int(m_cullMode)) {
+ material->setCullMode(QSGShaderEffectMaterial::CullMode(m_cullMode));
node->markDirty(QSGNode::DirtyMaterial);
}
if (m_dirtyData) {
QVector<QPair<QByteArray, QVariant> > values;
- QVector<QPair<QByteArray, QPointer<QSGItem> > > textures;
- const QVector<QPair<QByteArray, QPointer<QSGItem> > > &oldTextures = m_material.textureProviders();
+ QVector<QPair<QByteArray, QSGTextureProvider *> > textures;
+ const QVector<QPair<QByteArray, QSGTextureProvider *> > &oldTextures = material->textureProviders();
for (QSet<QByteArray>::const_iterator it = m_source.uniformNames.begin();
it != m_source.uniformNames.end(); ++it) {
values.append(qMakePair(*it, property(*it)));
}
for (int i = 0; i < oldTextures.size(); ++i) {
- QSGTextureProvider *oldSource = QSGTextureProvider::from(oldTextures.at(i).second);
- if (oldSource && oldSource->textureChangedSignal())
- disconnect(oldTextures.at(i).second, oldSource->textureChangedSignal(), node, SLOT(markDirtyTexture()));
+ QSGTextureProvider *t = oldTextures.at(i).second;
+ if (t)
+ disconnect(t, SIGNAL(textureChanged()), node, SLOT(markDirtyTexture()));
}
for (int i = 0; i < m_sources.size(); ++i) {
const SourceData &source = m_sources.at(i);
- textures.append(qMakePair(source.name, source.item));
- QSGTextureProvider *t = QSGTextureProvider::from(source.item);
- if (t && t->textureChangedSignal())
- connect(source.item, t->textureChangedSignal(), node, SLOT(markDirtyTexture()), Qt::DirectConnection);
+ QSGTextureProvider *t = source.sourceObject->textureProvider();
+ textures.append(qMakePair(source.name, t));
+ if (t)
+ connect(t, SIGNAL(textureChanged()), node, SLOT(markDirtyTexture()), Qt::DirectConnection);
}
- m_material.setUniforms(values);
- m_material.setTextureProviders(textures);
+ material->setUniforms(values);
+ material->setTextureProviders(textures);
node->markDirty(QSGNode::DirtyMaterial);
m_dirtyData = false;
}
diff --git a/src/declarative/items/qsgshadereffect_p.h b/src/declarative/items/qsgshadereffect_p.h
index 0cced9a229..5d90fe0e61 100644
--- a/src/declarative/items/qsgshadereffect_p.h
+++ b/src/declarative/items/qsgshadereffect_p.h
@@ -138,11 +138,10 @@ private:
struct SourceData
{
QSignalMapper *mapper;
- QPointer<QSGItem> item;
+ QPointer<QSGItem> sourceObject;
QByteArray name;
};
QVector<SourceData> m_sources;
- QSGShaderEffectMaterial m_material;
uint m_blending : 1;
uint m_dirtyData : 1;
diff --git a/src/declarative/items/qsgshadereffectmesh_p.h b/src/declarative/items/qsgshadereffectmesh_p.h
index 463c3d9073..4a1a8ae61b 100644
--- a/src/declarative/items/qsgshadereffectmesh_p.h
+++ b/src/declarative/items/qsgshadereffectmesh_p.h
@@ -41,10 +41,11 @@
#include "qdeclarativeparserstatus.h"
+#include <QtGui/qcolor.h>
#include <QtCore/qobject.h>
#include <QtCore/qsize.h>
#include <QtCore/qvariant.h>
-#include <QtOpenGL/qglfunctions.h>
+#include <QtGui/qopenglfunctions.h>
#ifndef SHADEREFFECTMESH_H
#define SHADEREFFECTMESH_H
diff --git a/src/declarative/items/qsgshadereffectnode.cpp b/src/declarative/items/qsgshadereffectnode.cpp
index 8bd781ce58..c5d208345e 100644
--- a/src/declarative/items/qsgshadereffectnode.cpp
+++ b/src/declarative/items/qsgshadereffectnode.cpp
@@ -108,17 +108,17 @@ void QSGCustomMaterialShader::updateState(const RenderState &state, QSGMaterial
}
}
- QGLFunctions *functions = state.context()->functions();
+ QOpenGLFunctions *functions = state.context()->functions();
for (int i = material->m_textures.size() - 1; i >= 0; --i) {
- QPointer<QSGItem> source = material->m_textures.at(i).second;
- QSGTextureProvider *provider = QSGTextureProvider::from(source);
- QSGTexture *texture = provider ? provider->texture() : 0;
- if (!source || !provider || !texture) {
- qWarning("ShaderEffectItem: source or provider missing when binding textures");
- continue;
- }
functions->glActiveTexture(GL_TEXTURE0 + i);
- provider->texture()->bind();
+ if (QSGTextureProvider *provider = material->m_textures.at(i).second) {
+ if (QSGTexture *texture = provider->texture()) {
+ texture->bind();
+ continue;
+ }
+ }
+ qWarning("ShaderEffectItem: source or provider missing when binding textures");
+ glBindTexture(GL_TEXTURE_2D, 0);
}
if (material->m_source.respectsOpacity)
@@ -271,12 +271,12 @@ void QSGShaderEffectMaterial::setUniforms(const QVector<QPair<QByteArray, QVaria
m_uniformValues = uniformValues;
}
-void QSGShaderEffectMaterial::setTextureProviders(const QVector<QPair<QByteArray, QPointer<QSGItem> > > &textures)
+void QSGShaderEffectMaterial::setTextureProviders(const QVector<QPair<QByteArray, QSGTextureProvider *> > &textures)
{
m_textures = textures;
}
-const QVector<QPair<QByteArray, QPointer<QSGItem> > > &QSGShaderEffectMaterial::textureProviders() const
+const QVector<QPair<QByteArray, QSGTextureProvider *> > &QSGShaderEffectMaterial::textureProviders() const
{
return m_textures;
}
@@ -284,20 +284,9 @@ const QVector<QPair<QByteArray, QPointer<QSGItem> > > &QSGShaderEffectMaterial::
void QSGShaderEffectMaterial::updateTextures() const
{
for (int i = 0; i < m_textures.size(); ++i) {
- QSGItem *item = m_textures.at(i).second;
- if (item) {
- QSGTextureProvider *provider = QSGTextureProvider::from(item);
- if (provider) {
- QSGTexture *texture = provider->texture();
- if (!texture) {
- qWarning("QSGShaderEffectMaterial: no texture from %s [%s]",
- qPrintable(item->objectName()),
- item->metaObject()->className());
- }
- if (QSGDynamicTexture *t = qobject_cast<QSGDynamicTexture *>(provider->texture())) {
- t->updateTexture();
- }
- }
+ if (QSGTextureProvider *provider = m_textures.at(i).second) {
+ if (QSGDynamicTexture *texture = qobject_cast<QSGDynamicTexture *>(provider->texture()))
+ texture->updateTexture();
}
}
}
@@ -306,6 +295,7 @@ void QSGShaderEffectMaterial::updateTextures() const
QSGShaderEffectNode::QSGShaderEffectNode()
{
QSGNode::setFlag(UsePreprocess, true);
+ setMaterial(&m_material);
}
QSGShaderEffectNode::~QSGShaderEffectNode()
diff --git a/src/declarative/items/qsgshadereffectnode_p.h b/src/declarative/items/qsgshadereffectnode_p.h
index eee70703ea..d95dfaf3cb 100644
--- a/src/declarative/items/qsgshadereffectnode_p.h
+++ b/src/declarative/items/qsgshadereffectnode_p.h
@@ -100,8 +100,8 @@ public:
void setProgramSource(const QSGShaderEffectProgram &);
void setUniforms(const QVector<QPair<QByteArray, QVariant> > &uniformValues);
- void setTextureProviders(const QVector<QPair<QByteArray, QPointer<QSGItem> > > &textures);
- const QVector<QPair<QByteArray, QPointer<QSGItem> > > &textureProviders() const;
+ void setTextureProviders(const QVector<QPair<QByteArray, QSGTextureProvider *> > &textures);
+ const QVector<QPair<QByteArray, QSGTextureProvider *> > &textureProviders() const;
void updateTextures() const;
protected:
@@ -118,7 +118,7 @@ protected:
QSGShaderEffectProgram m_source;
QVector<QPair<QByteArray, QVariant> > m_uniformValues;
- QVector<QPair<QByteArray, QPointer<QSGItem> > > m_textures;
+ QVector<QPair<QByteArray, QSGTextureProvider *> > m_textures;
CullMode m_cullMode;
static QHash<QSGShaderEffectMaterialKey, QSharedPointer<QSGMaterialType> > materialMap;
@@ -136,9 +136,13 @@ public:
virtual void preprocess();
+ QSGShaderEffectMaterial *shaderMaterial() { return &m_material; }
+
private Q_SLOTS:
void markDirtyTexture();
+private:
+ QSGShaderEffectMaterial m_material;
};
QT_END_NAMESPACE
diff --git a/src/declarative/items/qsgshadereffectsource.cpp b/src/declarative/items/qsgshadereffectsource.cpp
index e05d20ed69..bb55af524b 100644
--- a/src/declarative/items/qsgshadereffectsource.cpp
+++ b/src/declarative/items/qsgshadereffectsource.cpp
@@ -46,7 +46,7 @@
#include <private/qsgadaptationlayer_p.h>
#include <private/qsgrenderer_p.h>
-#include "qglframebufferobject.h"
+#include "qopenglframebufferobject.h"
#include "qmath.h"
#include <private/qsgtexture_p.h>
@@ -54,6 +54,33 @@ QT_BEGIN_NAMESPACE
DEFINE_BOOL_CONFIG_OPTION(qmlFboOverlay, QML_FBO_OVERLAY)
+class QSGShaderEffectSourceTextureProvider : public QSGTextureProvider
+{
+ Q_OBJECT
+public:
+ QSGShaderEffectSourceTextureProvider()
+ : sourceTexture(0)
+ {
+ }
+
+ QSGTexture *texture() const {
+ sourceTexture->setMipmapFiltering(mipmapFiltering);
+ sourceTexture->setFiltering(filtering);
+ sourceTexture->setHorizontalWrapMode(horizontalWrap);
+ sourceTexture->setVerticalWrapMode(verticalWrap);
+ return sourceTexture;
+ }
+
+ QSGShaderEffectTexture *sourceTexture;
+
+ QSGTexture::Filtering mipmapFiltering;
+ QSGTexture::Filtering filtering;
+ QSGTexture::WrapMode horizontalWrap;
+ QSGTexture::WrapMode verticalWrap;
+};
+#include "qsgshadereffectsource.moc"
+
+
QSGShaderEffectSourceNode::QSGShaderEffectSourceNode()
{
setFlag(UsePreprocess, true);
@@ -76,6 +103,7 @@ QSGShaderEffectTexture::QSGShaderEffectTexture(QSGItem *shaderSource)
#ifdef QSG_DEBUG_FBO_OVERLAY
, m_debugOverlay(0)
#endif
+ , m_context(0)
, m_mipmap(false)
, m_live(true)
, m_recursive(false)
@@ -96,6 +124,17 @@ QSGShaderEffectTexture::~QSGShaderEffectTexture()
#endif
}
+void QSGShaderEffectTexture::scheduleForCleanup()
+{
+ if (m_context)
+ m_context->scheduleTextureForCleanup(this);
+ else {
+ // Never really been used, hence we can delete it right away..
+ Q_ASSERT(!m_fbo);
+ delete this;
+ }
+}
+
int QSGShaderEffectTexture::textureId() const
{
@@ -226,10 +265,12 @@ void QSGShaderEffectTexture::grab()
return;
}
- QSGContext *context = QSGItemPrivate::get(m_shaderSource)->sceneGraphContext();
+ if (!m_context)
+ m_context = QSGItemPrivate::get(m_shaderSource)->sceneGraphContext();
+ Q_ASSERT(QSGItemPrivate::get(m_shaderSource)->sceneGraphContext() == m_context);
if (!m_renderer) {
- m_renderer = context->createRenderer();
+ m_renderer = m_context->createRenderer();
connect(m_renderer, SIGNAL(sceneGraphChanged()), this, SLOT(markDirtyTexture()), Qt::DirectConnection);
}
m_renderer->setRootNode(static_cast<QSGRootNode *>(root));
@@ -248,27 +289,27 @@ void QSGShaderEffectTexture::grab()
// Don't delete the FBO right away in case it is used recursively.
deleteFboLater = true;
delete m_secondaryFbo;
- QGLFramebufferObjectFormat format;
+ QOpenGLFramebufferObjectFormat format;
- format.setAttachment(QGLFramebufferObject::CombinedDepthStencil);
+ format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
format.setInternalTextureFormat(m_format);
format.setSamples(8);
- m_secondaryFbo = new QGLFramebufferObject(m_size, format);
+ m_secondaryFbo = new QOpenGLFramebufferObject(m_size, format);
} else {
- QGLFramebufferObjectFormat format;
- format.setAttachment(QGLFramebufferObject::CombinedDepthStencil);
+ QOpenGLFramebufferObjectFormat format;
+ format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
format.setInternalTextureFormat(m_format);
format.setMipmap(m_mipmap);
if (m_recursive) {
deleteFboLater = true;
delete m_secondaryFbo;
- m_secondaryFbo = new QGLFramebufferObject(m_size, format);
+ m_secondaryFbo = new QOpenGLFramebufferObject(m_size, format);
glBindTexture(GL_TEXTURE_2D, m_secondaryFbo->texture());
updateBindOptions(true);
} else {
delete m_fbo;
delete m_secondaryFbo;
- m_fbo = new QGLFramebufferObject(m_size, format);
+ m_fbo = new QOpenGLFramebufferObject(m_size, format);
m_secondaryFbo = 0;
glBindTexture(GL_TEXTURE_2D, m_fbo->texture());
updateBindOptions(true);
@@ -281,7 +322,7 @@ void QSGShaderEffectTexture::grab()
Q_ASSERT(m_fbo);
Q_ASSERT(!m_multisampling);
- m_secondaryFbo = new QGLFramebufferObject(m_size, m_fbo->format());
+ m_secondaryFbo = new QOpenGLFramebufferObject(m_size, m_fbo->format());
glBindTexture(GL_TEXTURE_2D, m_secondaryFbo->texture());
updateBindOptions(true);
}
@@ -293,7 +334,7 @@ void QSGShaderEffectTexture::grab()
#ifdef QSG_DEBUG_FBO_OVERLAY
if (qmlFboOverlay()) {
if (!m_debugOverlay)
- m_debugOverlay = context->createRectangleNode();
+ m_debugOverlay = m_context->createRectangleNode();
m_debugOverlay->setRect(QRectF(0, 0, m_size.width(), m_size.height()));
m_debugOverlay->setColor(QColor(0xff, 0x00, 0x80, 0x40));
m_debugOverlay->setPenColor(QColor());
@@ -306,7 +347,7 @@ void QSGShaderEffectTexture::grab()
m_dirtyTexture = false;
- const QGLContext *ctx = QGLContext::currentContext();
+ QOpenGLContext *ctx = m_context->glContext();
m_renderer->setDeviceRect(m_size);
m_renderer->setViewportRect(m_size);
QRectF mirrored(m_rect.left(), m_rect.bottom(), m_rect.width(), -m_rect.height());
@@ -318,29 +359,29 @@ void QSGShaderEffectTexture::grab()
if (deleteFboLater) {
delete m_fbo;
- QGLFramebufferObjectFormat format;
+ QOpenGLFramebufferObjectFormat format;
format.setInternalTextureFormat(m_format);
- format.setAttachment(QGLFramebufferObject::NoAttachment);
+ format.setAttachment(QOpenGLFramebufferObject::NoAttachment);
format.setMipmap(m_mipmap);
format.setSamples(0);
- m_fbo = new QGLFramebufferObject(m_size, format);
+ m_fbo = new QOpenGLFramebufferObject(m_size, format);
glBindTexture(GL_TEXTURE_2D, m_fbo->texture());
updateBindOptions(true);
}
QRect r(QPoint(), m_size);
- QGLFramebufferObject::blitFramebuffer(m_fbo, r, m_secondaryFbo, r);
+ QOpenGLFramebufferObject::blitFramebuffer(m_fbo, r, m_secondaryFbo, r);
} else {
if (m_recursive) {
m_renderer->renderScene(QSGBindableFbo(m_secondaryFbo));
if (deleteFboLater) {
delete m_fbo;
- QGLFramebufferObjectFormat format;
- format.setAttachment(QGLFramebufferObject::CombinedDepthStencil);
+ QOpenGLFramebufferObjectFormat format;
+ format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
format.setInternalTextureFormat(m_format);
format.setMipmap(m_mipmap);
- m_fbo = new QGLFramebufferObject(m_size, format);
+ m_fbo = new QOpenGLFramebufferObject(m_size, format);
glBindTexture(GL_TEXTURE_2D, m_fbo->texture());
updateBindOptions(true);
}
@@ -452,6 +493,7 @@ QImage QSGShaderEffectTexture::toImage() const
QSGShaderEffectSource::QSGShaderEffectSource(QSGItem *parent)
: QSGItem(parent)
+ , m_provider(0)
, m_wrapMode(ClampToEdge)
, m_sourceItem(0)
, m_textureSize(0, 0)
@@ -464,17 +506,36 @@ QSGShaderEffectSource::QSGShaderEffectSource(QSGItem *parent)
{
setFlag(ItemHasContents);
m_texture = new QSGShaderEffectTexture(this);
- connect(m_texture, SIGNAL(textureChanged()), this, SIGNAL(textureChanged()), Qt::DirectConnection);
connect(m_texture, SIGNAL(textureChanged()), this, SLOT(update()));
}
QSGShaderEffectSource::~QSGShaderEffectSource()
{
- delete m_texture;
+ m_texture->scheduleForCleanup();
+
+ if (m_provider)
+ m_provider->deleteLater();
+
if (m_sourceItem)
QSGItemPrivate::get(m_sourceItem)->derefFromEffectItem(m_hideSource);
}
+QSGTextureProvider *QSGShaderEffectSource::textureProvider() const
+{
+ if (!m_provider) {
+ // Make sure it gets thread affinity on the rendering thread so deletion works properly..
+ Q_ASSERT_X(QSGItemPrivate::get(this)->canvas
+ && QSGItemPrivate::get(this)->sceneGraphContext()
+ && QThread::currentThread() == QSGItemPrivate::get(this)->sceneGraphContext()->thread(),
+ "QSGShaderEffectSource::textureProvider",
+ "Cannot be used outside the GUI thread");
+ const_cast<QSGShaderEffectSource *>(this)->m_provider = new QSGShaderEffectSourceTextureProvider();
+ connect(m_texture, SIGNAL(textureChanged()), m_provider, SIGNAL(textureChanged()), Qt::DirectConnection);
+ m_provider->sourceTexture = m_texture;
+ }
+ return m_provider;
+}
+
/*!
\qmlproperty enumeration ShaderEffectSource::wrapMode
@@ -761,17 +822,6 @@ static void get_wrap_mode(QSGShaderEffectSource::WrapMode mode, QSGTexture::Wrap
}
-QSGTexture *QSGShaderEffectSource::texture() const
-{
- m_texture->setMipmapFiltering(m_mipmap ? QSGTexture::Linear : QSGTexture::None);
- m_texture->setFiltering(QSGItemPrivate::get(this)->smooth ? QSGTexture::Linear : QSGTexture::Nearest);
- QSGTexture::WrapMode h, v;
- get_wrap_mode(m_wrapMode, &h, &v);
- m_texture->setHorizontalWrapMode(h);
- m_texture->setVerticalWrapMode(v);
- return m_texture;
-}
-
QSGNode *QSGShaderEffectSource::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
{
if (!m_sourceItem || m_sourceItem->width() == 0 || m_sourceItem->height() == 0) {
@@ -779,19 +829,7 @@ QSGNode *QSGShaderEffectSource::updatePaintNode(QSGNode *oldNode, UpdatePaintNod
return 0;
}
- QSGShaderEffectSourceNode *node = static_cast<QSGShaderEffectSourceNode *>(oldNode);
- if (!node) {
- node = new QSGShaderEffectSourceNode;
- node->setTexture(m_texture);
- connect(m_texture, SIGNAL(textureChanged()), node, SLOT(markDirtyTexture()), Qt::DirectConnection);
- }
-
- // If live and recursive, update continuously.
- if (m_live && m_recursive)
- node->markDirty(QSGNode::DirtyMaterial);
-
QSGShaderEffectTexture *tex = qobject_cast<QSGShaderEffectTexture *>(m_texture);
-
tex->setLive(m_live);
tex->setItem(QSGItemPrivate::get(m_sourceItem)->itemNode());
QRectF sourceRect = m_sourceRect.width() == 0 || m_sourceRect.height() == 0
@@ -823,12 +861,35 @@ QSGNode *QSGShaderEffectSource::updatePaintNode(QSGNode *oldNode, UpdatePaintNod
? QSGTexture::Linear
: QSGTexture::Nearest;
QSGTexture::Filtering mmFiltering = m_mipmap ? filtering : QSGTexture::None;
- node->setMipmapFiltering(mmFiltering);
- node->setFiltering(filtering);
-
QSGTexture::WrapMode hWrap, vWrap;
get_wrap_mode(m_wrapMode, &hWrap, &vWrap);
+ if (m_provider) {
+ m_provider->mipmapFiltering = mmFiltering;
+ m_provider->filtering = filtering;
+ m_provider->horizontalWrap = hWrap;
+ m_provider->verticalWrap = vWrap;
+ }
+
+ // Don't create the paint node if we're not spanning any area
+ if (width() == 0 || height() == 0) {
+ delete oldNode;
+ return 0;
+ }
+
+ QSGShaderEffectSourceNode *node = static_cast<QSGShaderEffectSourceNode *>(oldNode);
+ if (!node) {
+ node = new QSGShaderEffectSourceNode;
+ node->setTexture(m_texture);
+ connect(m_texture, SIGNAL(textureChanged()), node, SLOT(markDirtyTexture()), Qt::DirectConnection);
+ }
+
+ // If live and recursive, update continuously.
+ if (m_live && m_recursive)
+ node->markDirty(QSGNode::DirtyMaterial);
+
+ node->setMipmapFiltering(mmFiltering);
+ node->setFiltering(filtering);
node->setHorizontalWrapMode(hWrap);
node->setVerticalWrapMode(vWrap);
node->setTargetRect(QRectF(0, 0, width(), height()));
diff --git a/src/declarative/items/qsgshadereffectsource_p.h b/src/declarative/items/qsgshadereffectsource_p.h
index 0cb449a46c..77cb412884 100644
--- a/src/declarative/items/qsgshadereffectsource_p.h
+++ b/src/declarative/items/qsgshadereffectsource_p.h
@@ -62,7 +62,9 @@ QT_MODULE(Declarative)
class QSGNode;
class UpdatePaintNodeData;
-class QGLFramebufferObject;
+class QOpenGLFramebufferObject;
+
+class QSGShaderEffectSourceTextureProvider;
class QSGShaderEffectSourceNode : public QObject, public QSGDefaultImageNode
{
@@ -114,6 +116,7 @@ public:
void scheduleUpdate();
+ void scheduleForCleanup();
QImage toImage() const;
Q_SIGNALS:
@@ -132,13 +135,15 @@ private:
QSGItem *m_shaderSource;
QSGRenderer *m_renderer;
- QGLFramebufferObject *m_fbo;
- QGLFramebufferObject *m_secondaryFbo;
+ QOpenGLFramebufferObject *m_fbo;
+ QOpenGLFramebufferObject *m_secondaryFbo;
#ifdef QSG_DEBUG_FBO_OVERLAY
QSGRectangleNode *m_debugOverlay;
#endif
+ QSGContext *m_context;
+
uint m_mipmap : 1;
uint m_live : 1;
uint m_recursive : 1;
@@ -148,7 +153,7 @@ private:
uint m_grab : 1;
};
-class QSGShaderEffectSource : public QSGItem, public QSGTextureProvider
+class QSGShaderEffectSource : public QSGItem
{
Q_OBJECT
Q_PROPERTY(WrapMode wrapMode READ wrapMode WRITE setWrapMode NOTIFY wrapModeChanged)
@@ -160,7 +165,7 @@ class QSGShaderEffectSource : public QSGItem, public QSGTextureProvider
Q_PROPERTY(bool hideSource READ hideSource WRITE setHideSource NOTIFY hideSourceChanged)
Q_PROPERTY(bool mipmap READ mipmap WRITE setMipmap NOTIFY mipmapChanged)
Q_PROPERTY(bool recursive READ recursive WRITE setRecursive NOTIFY recursiveChanged)
- Q_INTERFACES(QSGTextureProvider)
+
Q_ENUMS(Format WrapMode)
public:
enum WrapMode {
@@ -206,8 +211,8 @@ public:
bool recursive() const;
void setRecursive(bool enabled);
- QSGTexture *texture() const;
- const char *textureChangedSignal() const { return SIGNAL(textureChanged()); }
+ bool isTextureProvider() const { return true; }
+ QSGTextureProvider *textureProvider() const;
Q_INVOKABLE void scheduleUpdate();
@@ -228,7 +233,8 @@ protected:
virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
private:
- QSGTexture *m_texture;
+ QSGShaderEffectSourceTextureProvider *m_provider;
+ QSGShaderEffectTexture *m_texture;
WrapMode m_wrapMode;
QPointer<QSGItem> m_sourceItem;
QRectF m_sourceRect;
diff --git a/src/declarative/items/qsgspriteengine.cpp b/src/declarative/items/qsgspriteengine.cpp
index 1915db6000..7e6492e419 100644
--- a/src/declarative/items/qsgspriteengine.cpp
+++ b/src/declarative/items/qsgspriteengine.cpp
@@ -44,7 +44,7 @@
#include <QDebug>
#include <QPainter>
#include <QSet>
-#include <QtOpenGL>
+#include <QtGui>
QT_BEGIN_NAMESPACE
diff --git a/src/declarative/items/qsgtext.cpp b/src/declarative/items/qsgtext.cpp
index 7e8cf2d099..bac0be969b 100644
--- a/src/declarative/items/qsgtext.cpp
+++ b/src/declarative/items/qsgtext.cpp
@@ -50,13 +50,13 @@
#include <private/qsgtexture_p.h>
#include <QtDeclarative/qdeclarativeinfo.h>
-#include <QtGui/qgraphicssceneevent.h>
+#include <QtWidgets/qgraphicssceneevent.h>
#include <QtGui/qabstracttextdocumentlayout.h>
#include <QtGui/qpainter.h>
#include <QtGui/qtextdocument.h>
#include <QtGui/qtextobject.h>
#include <QtGui/qtextcursor.h>
-#include <QtGui/qapplication.h>
+#include <QtWidgets/qapplication.h>
#include <private/qdeclarativestyledtext_p.h>
#include <private/qdeclarativepixmapcache_p.h>
diff --git a/src/declarative/items/qsgtextedit.cpp b/src/declarative/items/qsgtextedit.cpp
index eeeaa206db..1c0ed62f0d 100644
--- a/src/declarative/items/qsgtextedit.cpp
+++ b/src/declarative/items/qsgtextedit.cpp
@@ -47,8 +47,8 @@
#include "qsgsimplerectnode.h"
#include <QtDeclarative/qdeclarativeinfo.h>
-#include <QtGui/qapplication.h>
-#include <QtGui/qgraphicssceneevent.h>
+#include <QtWidgets/qapplication.h>
+#include <QtWidgets/qgraphicssceneevent.h>
#include <QtGui/qpainter.h>
#include <QtGui/qtextobject.h>
#include <QtCore/qmath.h>
@@ -1360,9 +1360,11 @@ void QSGTextEdit::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
d->control->processEvent(event, QPointF(0, -d->yoff));
if (!d->showInputPanelOnFocus) { // input panel on click
if (d->focusOnPress && !isReadOnly() && boundingRect().contains(event->pos())) {
- if (canvas() && canvas() == qApp->focusWidget()) {
- qt_widget_private(canvas())->handleSoftwareInputPanel(event->button(), d->clickCausedFocus);
- }
+ // ### refactor: port properly
+ qDebug("QSGTextEdit: virtual keyboard handling not implemented");
+// if (canvas() && canvas() == qApp->focusWidget()) {
+// qt_widget_private(canvas())->handleSoftwareInputPanel(event->button(), d->clickCausedFocus);
+// }
}
}
d->clickCausedFocus = false;
@@ -1412,7 +1414,7 @@ void QSGTextEdit::itemChange(ItemChange change, const ItemChangeData &value)
{
Q_D(QSGTextEdit);
if (change == ItemActiveFocusHasChanged) {
- setCursorVisible(value.boolValue && d->canvas && d->canvas->hasFocus());
+ setCursorVisible(value.boolValue); // ### refactor: focus handling && d->canvas && d->canvas->hasFocus());
}
QSGItem::itemChange(change, value);
}
@@ -1906,7 +1908,7 @@ void QSGTextEditPrivate::updateDefaultTextOption()
void QSGTextEdit::openSoftwareInputPanel()
{
if (qApp) {
- if (canvas() && canvas() == qApp->focusWidget()) {
+ if (canvas()) {
QEvent event(QEvent::RequestSoftwareInputPanel);
QApplication::sendEvent(canvas(), &event);
}
@@ -1953,9 +1955,9 @@ void QSGTextEdit::openSoftwareInputPanel()
\endcode
*/
void QSGTextEdit::closeSoftwareInputPanel()
-{
+{
if (qApp) {
- if (canvas() && canvas() == qApp->focusWidget()) {
+ if (canvas()) {
QEvent event(QEvent::CloseSoftwareInputPanel);
QApplication::sendEvent(canvas(), &event);
}
diff --git a/src/declarative/items/qsgtextinput.cpp b/src/declarative/items/qsgtextinput.cpp
index 222a9002e7..d30faadb34 100644
--- a/src/declarative/items/qsgtextinput.cpp
+++ b/src/declarative/items/qsgtextinput.cpp
@@ -48,8 +48,8 @@
#include <private/qsgdistancefieldglyphcache_p.h>
#include <QtDeclarative/qdeclarativeinfo.h>
-#include <QtGui/qgraphicssceneevent.h>
-#include <QtGui/qinputcontext.h>
+#include <QtWidgets/qgraphicssceneevent.h>
+#include <QtWidgets/qinputcontext.h>
#include <QTextBoundaryFinder>
#include <qstyle.h>
#include <qsgtextnode_p.h>
@@ -888,7 +888,7 @@ void QSGTextInput::setEchoMode(QSGTextInput::EchoMode echo)
Q_D(QSGTextInput);
if (echoMode() == echo)
return;
- d->control->setEchoMode((uint)echo);
+ d->control->setEchoMode((QLineControl::EchoMode)echo);
d->updateInputMethodHints();
q_textChanged();
emit echoModeChanged(echoMode());
@@ -1149,8 +1149,10 @@ void QSGTextInput::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
}
if (!d->showInputPanelOnFocus) { // input panel on click
if (d->focusOnPress && !isReadOnly() && boundingRect().contains(event->pos())) {
- if (canvas() && canvas() == qApp->focusWidget()) {
- qt_widget_private(canvas())->handleSoftwareInputPanel(event->button(), d->clickCausedFocus);
+ if (canvas() && canvas() == QGuiApplication::activeWindow()) {
+ // ### refactor: implement virtual keyboard properly..
+ qDebug("QSGTextInput: virtual keyboard no implemented...");
+// qt_widget_private(canvas())->handleSoftwareInputPanel(event->button(), d->clickCausedFocus);
}
}
}
@@ -1230,7 +1232,6 @@ bool QSGTextInput::event(QEvent* ev)
void QSGTextInput::geometryChanged(const QRectF &newGeometry,
const QRectF &oldGeometry)
{
- Q_D(QSGTextInput);
if (newGeometry.width() != oldGeometry.width()) {
updateSize();
updateCursorRectangle();
@@ -1741,9 +1742,8 @@ void QSGTextInput::moveCursorSelection(int pos, SelectionMode mode)
*/
void QSGTextInput::openSoftwareInputPanel()
{
- QEvent event(QEvent::RequestSoftwareInputPanel);
if (qApp) {
- if (canvas() && canvas() == qApp->focusWidget()) {
+ if (canvas()) {
QEvent event(QEvent::RequestSoftwareInputPanel);
QApplication::sendEvent(canvas(), &event);
}
@@ -1792,7 +1792,7 @@ void QSGTextInput::openSoftwareInputPanel()
void QSGTextInput::closeSoftwareInputPanel()
{
if (qApp) {
- if (canvas() && canvas() == qApp->focusWidget()) {
+ if (canvas()) {
QEvent event(QEvent::CloseSoftwareInputPanel);
QApplication::sendEvent(canvas(), &event);
}
@@ -1816,7 +1816,7 @@ void QSGTextInput::itemChange(ItemChange change, const ItemChangeData &value)
if (change == ItemActiveFocusHasChanged) {
bool hasFocus = value.boolValue;
d->focused = hasFocus;
- setCursorVisible(hasFocus && d->canvas && d->canvas->hasFocus());
+ setCursorVisible(hasFocus); // ### refactor: && d->canvas && d->canvas->hasFocus()
if(echoMode() == QSGTextInput::PasswordEchoOnEdit && !hasFocus)
d->control->updatePasswordEchoEditing(false);//QLineControl sets it on key events, but doesn't deal with focus events
if (!hasFocus)
diff --git a/src/declarative/items/qsgtextnode.cpp b/src/declarative/items/qsgtextnode.cpp
index ef0f98bf1d..1ae457b6fa 100644
--- a/src/declarative/items/qsgtextnode.cpp
+++ b/src/declarative/items/qsgtextnode.cpp
@@ -132,6 +132,15 @@ QSGGlyphNode *QSGTextNode::addGlyphs(const QPointF &position, const QGlyphRun &g
node->setColor(color);
node->update();
+ /* We flag the geometry as static, but we never call markVertexDataDirty
+ or markIndexDataDirty on them. This is because all text nodes are
+ discarded when a change occurs. If we start appending/removing from
+ existing geometry, then we also need to start marking the geometry as
+ dirty.
+ */
+ node->geometry()->setIndexDataPattern(QSGGeometry::StaticPattern);
+ node->geometry()->setVertexDataPattern(QSGGeometry::StaticPattern);
+
if (parentNode == 0)
parentNode = this;
parentNode->appendChildNode(node);
diff --git a/src/declarative/items/qsgtextnode_p.h b/src/declarative/items/qsgtextnode_p.h
index 4c5199aefa..e9b9b98edf 100644
--- a/src/declarative/items/qsgtextnode_p.h
+++ b/src/declarative/items/qsgtextnode_p.h
@@ -44,6 +44,7 @@
#include <qsgnode.h>
#include <qsgtext_p.h>
+#include <qglyphrun.h>
QT_BEGIN_NAMESPACE
diff --git a/src/declarative/items/qsgview.cpp b/src/declarative/items/qsgview.cpp
index e2fb42e22b..236fd4ec1f 100644
--- a/src/declarative/items/qsgview.cpp
+++ b/src/declarative/items/qsgview.cpp
@@ -54,7 +54,7 @@
#include <QtCore/qbasictimer.h>
-// XXX todo - This whole class should probably be merged with QDeclarativeView for
+// XXX todo - This whole class should probably be merged with QDeclarativeView for
// maximum seamlessness
QT_BEGIN_NAMESPACE
@@ -62,19 +62,18 @@ DEFINE_BOOL_CONFIG_OPTION(frameRateDebug, QML_SHOW_FRAMERATE)
void QSGViewPrivate::init()
{
- q_func()->setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Preferred);
QDeclarativeEnginePrivate::get(&engine)->sgContext = QSGCanvasPrivate::context;
QDeclarativeInspectorService::instance()->addView(q_func());
}
QSGViewPrivate::QSGViewPrivate()
-: root(0), component(0), resizeMode(QSGView::SizeViewToRootObject), initialSize(0,0)
+ : root(0), component(0), resizeMode(QSGView::SizeViewToRootObject), initialSize(0,0), resized(false)
{
}
-QSGViewPrivate::~QSGViewPrivate()
-{
+QSGViewPrivate::~QSGViewPrivate()
+{
QDeclarativeInspectorService::instance()->removeView(q_func());
delete root;
@@ -96,7 +95,7 @@ void QSGViewPrivate::execute()
if (!component->isLoading()) {
q->continueExecute();
} else {
- QObject::connect(component, SIGNAL(statusChanged(QDeclarativeComponent::Status)),
+ QObject::connect(component, SIGNAL(statusChanged(QDeclarativeComponent::Status)),
q, SLOT(continueExecute()));
}
}
@@ -112,28 +111,17 @@ void QSGViewPrivate::itemGeometryChanged(QSGItem *resizeItem, const QRectF &newG
QSGItemChangeListener::itemGeometryChanged(resizeItem, newGeometry, oldGeometry);
}
-QSGView::QSGView(QWidget *parent, Qt::WindowFlags f)
-: QSGCanvas(*(new QSGViewPrivate), parent, f)
-{
- d_func()->init();
-}
-
-QSGView::QSGView(const QGLFormat &format, QWidget *parent, Qt::WindowFlags f)
-: QSGCanvas(*(new QSGViewPrivate), format, parent, f)
-{
- d_func()->init();
-}
-
-QSGView::QSGView(const QUrl &source, QWidget *parent, Qt::WindowFlags f)
-: QSGCanvas(*(new QSGViewPrivate), parent, f)
+QSGView::QSGView(QWindow *parent, Qt::WindowFlags f)
+: QSGCanvas(*(new QSGViewPrivate), parent)
{
+ setWindowFlags(f);
d_func()->init();
- setSource(source);
}
-QSGView::QSGView(const QUrl &source, const QGLFormat &format, QWidget *parent, Qt::WindowFlags f)
-: QSGCanvas(*(new QSGViewPrivate), format, parent, f)
+QSGView::QSGView(const QUrl &source, QWindow *parent, Qt::WindowFlags f)
+: QSGCanvas(*(new QSGViewPrivate), parent)
{
+ setWindowFlags(f);
d_func()->init();
setSource(source);
}
@@ -231,8 +219,6 @@ void QSGViewPrivate::updateSize()
if (!qFuzzyCompare(q->height(), root->height()))
root->setHeight(q->height());
}
-
- q->updateGeometry();
}
QSize QSGViewPrivate::rootObjectSize() const
@@ -319,14 +305,13 @@ void QSGViewPrivate::setRootObject(QObject *obj)
delete obj;
root = 0;
}
-
if (root) {
initialSize = rootObjectSize();
- if ((resizeMode == QSGView::SizeViewToRootObject || !q->testAttribute(Qt::WA_Resized))
+ if ((resizeMode == QSGView::SizeViewToRootObject || !resized) // ### refactor: || !q->testAttribute(Qt::WA_Resized)
&& initialSize != q->size()) {
- if (!(q->parentWidget() && q->parentWidget()->layout())) {
- q->resize(initialSize);
- }
+
+ q->resize(initialSize);
+ resized = true;
}
initResize();
}
@@ -381,26 +366,10 @@ QSGItem *QSGView::rootObject() const
void QSGView::resizeEvent(QResizeEvent *e)
{
Q_D(QSGView);
- if (d->resizeMode == SizeRootObjectToView)
+ if (d->resizeMode == SizeRootObjectToView)
d->updateSize();
-
- QSGCanvas::resizeEvent(e);
-}
-/*!
- \internal
-*/
-void QSGView::paintEvent(QPaintEvent *event)
-{
- Q_D(QSGView);
- int time = 0;
- if (frameRateDebug())
- time = d->frameTimer.restart();
-
- QSGCanvas::paintEvent(event);
-
- if (frameRateDebug())
- qDebug() << "paintEvent:" << d->frameTimer.elapsed() << "time since last frame:" << time;
+ QSGCanvas::resizeEvent(e);
}
void QSGView::keyPressEvent(QKeyEvent *e)
diff --git a/src/declarative/items/qsgview.h b/src/declarative/items/qsgview.h
index 9b5ace13f3..62b52c865b 100644
--- a/src/declarative/items/qsgview.h
+++ b/src/declarative/items/qsgview.h
@@ -66,10 +66,8 @@ class Q_DECLARATIVE_EXPORT QSGView : public QSGCanvas
Q_PROPERTY(QUrl source READ source WRITE setSource DESIGNABLE true)
Q_ENUMS(ResizeMode Status)
public:
- explicit QSGView(QWidget *parent = 0, Qt::WindowFlags f = 0);
- explicit QSGView(const QGLFormat &format, QWidget *parent = 0, Qt::WindowFlags f = 0);
- QSGView(const QUrl &source, QWidget *parent = 0, Qt::WindowFlags f = 0);
- QSGView(const QUrl &source, const QGLFormat &format, QWidget *parent = 0, Qt::WindowFlags f = 0);
+ explicit QSGView(QWindow *parent = 0, Qt::WindowFlags f = 0);
+ QSGView(const QUrl &source, QWindow *parent = 0, Qt::WindowFlags f = 0);
virtual ~QSGView();
QUrl source() const;
@@ -102,7 +100,6 @@ private Q_SLOTS:
protected:
virtual void resizeEvent(QResizeEvent *);
- virtual void paintEvent(QPaintEvent *event);
virtual void timerEvent(QTimerEvent*);
virtual void keyPressEvent(QKeyEvent *);
diff --git a/src/declarative/items/qsgview_p.h b/src/declarative/items/qsgview_p.h
index 8b2ee88ee8..3f8d69e8c0 100644
--- a/src/declarative/items/qsgview_p.h
+++ b/src/declarative/items/qsgview_p.h
@@ -97,6 +97,8 @@ public:
QSGView::ResizeMode resizeMode;
QSize initialSize;
QElapsedTimer frameTimer;
+
+ bool resized;
};
QT_END_NAMESPACE