diff options
Diffstat (limited to 'src/declarative/items')
27 files changed, 449 insertions, 479 deletions
diff --git a/src/declarative/items/context2d/qsgcontext2d.cpp b/src/declarative/items/context2d/qsgcontext2d.cpp index 4cfe1ba012..4d455419ad 100644 --- a/src/declarative/items/context2d/qsgcontext2d.cpp +++ b/src/declarative/items/context2d/qsgcontext2d.cpp @@ -47,9 +47,9 @@ #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 931a681c1a..8d54bce419 100644 --- a/src/declarative/items/qsgborderimage.cpp +++ b/src/declarative/items/qsgborderimage.cpp @@ -585,11 +585,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 6873c41cef..0d4001a393 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,7 +65,6 @@ QT_BEGIN_NAMESPACE -DEFINE_BOOL_CONFIG_OPTION(qmlNoThreadedRenderer, QML_NO_THREADED_RENDERER) DEFINE_BOOL_CONFIG_OPTION(qmlFixedAnimationStep, QML_FIXED_ANIMATION_STEP) extern Q_OPENGL_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha); @@ -165,134 +166,40 @@ 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) { 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())); - } - } - - if (d->animationDriver) - d->animationDriver->install(); + 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(); + } + + if (!d->thread->isRunning()) { + d->thread->windowSize = size(); + d->thread->startRenderThread(); } } void QSGCanvas::hideEvent(QHideEvent *e) { Q_D(QSGCanvas); - - if (!d->contextFailed) { - if (d->threadedRendering) { - d->thread->stopRenderThread(); - } - - if (d->animationDriver) - d->animationDriver->uninstall(); - } - - QGLWidget::hideEvent(e); + d->thread->stopRenderThread(); } @@ -313,7 +220,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 +239,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) @@ -359,11 +272,9 @@ void QSGCanvasPrivate::initializeSceneGraph() QGLContext *glctx = const_cast<QGLContext *>(QGLContext::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,15 +328,12 @@ 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) @@ -433,7 +341,6 @@ QSGCanvasPrivate::QSGCanvasPrivate() , animationDriver(0) , renderTarget(0) { - threadedRendering = !qmlNoThreadedRenderer(); } QSGCanvasPrivate::~QSGCanvasPrivate() @@ -444,31 +351,25 @@ 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); - if (threadedRendering) { - thread = new QSGCanvasRenderThread; - thread->renderer = q; - thread->d = this; - } + thread = new QSGCanvasRenderThread; + thread->renderer = q; + thread->d = this; + context = QSGContext::createDefaultContext(); + context->moveToThread(thread); } void QSGCanvasPrivate::sceneMouseEventForTransform(QGraphicsSceneMouseEvent &sceneEvent, @@ -516,8 +417,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 +448,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 +470,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 +525,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 +569,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; @@ -736,8 +634,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; @@ -816,11 +713,12 @@ void QSGCanvasPrivate::notifyFocusChangesRecur(QSGItem **items, int remaining) 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 +755,18 @@ void QSGCanvasPrivate::cleanup(QSGNode *n) q->maybeUpdate(); } -static QGLFormat tweakFormat(const QGLFormat &format = QGLFormat::defaultFormat()) -{ - QGLFormat f = format; - f.setSwapInterval(0); - 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) +QSGCanvas::QSGCanvas(QWindow *parent) + : QWindow(parent) { Q_D(QSGCanvas); - d->init(this); } -QSGCanvas::QSGCanvas(QSGCanvasPrivate &dd, QWidget *parent, Qt::WindowFlags f) -: QGLWidget(dd, tweakFormat(), parent, 0, f) +QSGCanvas::QSGCanvas(QSGCanvasPrivate &dd, QWindow *parent) + : QWindow(dd, 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) -{ - Q_D(QSGCanvas); - d->init(this); } @@ -900,7 +774,7 @@ QSGCanvas::~QSGCanvas() { Q_D(QSGCanvas); - if (d->threadedRendering && d->thread->isRunning()) { + if (d->thread->isRunning()) { d->thread->stopRenderThread(); delete d->thread; d->thread = 0; @@ -913,21 +787,6 @@ 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 @@ -958,7 +817,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) @@ -1022,7 +881,7 @@ bool QSGCanvas::event(QEvent *e) break; } - return QGLWidget::event(e); + return QWindow::event(e); } void QSGCanvas::keyPressEvent(QKeyEvent *e) @@ -1137,7 +996,7 @@ void QSGCanvas::mouseReleaseEvent(QMouseEvent *event) #endif if (!d->mouseGrabberItem) { - QGLWidget::mouseReleaseEvent(event); + QWindow::mouseReleaseEvent(event); return; } @@ -1462,7 +1321,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); @@ -1916,7 +1775,7 @@ void QSGCanvas::maybeUpdate() { Q_D(QSGCanvas); - if (d->threadedRendering && d->thread && d->thread->isRunning()) { + if (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()"); @@ -1935,8 +1794,6 @@ void QSGCanvas::maybeUpdate() d->thread->wake(); d->thread->unlockInGui(); } - } else if (!d->animationDriver || !d->animationDriver->isRunning()) { - update(); } } @@ -2009,17 +1866,13 @@ 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(); } @@ -2029,11 +1882,15 @@ void QSGCanvasRenderThread::run() qDebug("QML Rendering Thread Started"); #endif - renderer->makeCurrent(); + if (!guiContext) { + guiContext = new QGuiGLContext(); + guiContext->create(); + guiContext->makeCurrent(renderer); - if (!d->context->isReady()) d->initializeSceneGraph(); - + } else { + guiContext->makeCurrent(renderer); + } while (!shouldExit) { lock(); @@ -2104,8 +1961,8 @@ void QSGCanvasRenderThread::run() printf(" RenderThread: wait for swap...\n"); #endif - renderer->swapBuffers(); - + guiContext->swapBuffers(renderer); + emit renderer->frameSwapped();//notify compositor that frame has been swapped #ifdef THREAD_DEBUG printf(" RenderThread: swap complete...\n"); #endif @@ -2131,13 +1988,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(); + guiContext->doneCurrent(); lock(); hasExited = true; @@ -2146,6 +2006,10 @@ void QSGCanvasRenderThread::run() #endif wake(); unlock(); + +#ifdef THREAD_DEBUG + printf(" RenderThread: All done...\n"); +#endif } @@ -2165,8 +2029,6 @@ 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(); @@ -2266,10 +2128,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); } @@ -2309,8 +2167,6 @@ void QSGCanvasRenderThread::startRenderThread() shouldExit = false; isGuiBlocked = 0; isGuiBlockPending = false; - - renderer->doneCurrent(); start(); } @@ -2348,6 +2204,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 +2218,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 diff --git a/src/declarative/items/qsgcanvas.h b/src/declarative/items/qsgcanvas.h index a5f69ff559..86efdcbfdc 100644 --- a/src/declarative/items/qsgcanvas.h +++ b/src/declarative/items/qsgcanvas.h @@ -44,7 +44,7 @@ #include <QtCore/qmetatype.h> #include <QtOpenGL/qgl.h> -#include <QtGui/qwidget.h> +#include <QtWidgets/qwidget.h> QT_BEGIN_HEADER @@ -57,13 +57,13 @@ class QSGEngine; class QSGCanvasPrivate; class QGLFramebufferObject; -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; @@ -85,22 +85,21 @@ public: void setRenderTarget(QGLFramebufferObject *fbo); QGLFramebufferObject *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 *); @@ -119,6 +118,7 @@ private Q_SLOTS: private: friend class QSGItem; + friend class QSGCanvasRenderThread; Q_DISABLE_COPY(QSGCanvas) }; diff --git a/src/declarative/items/qsgcanvas_p.h b/src/declarative/items/qsgcanvas_p.h index d26b311e59..bf65e95812 100644 --- a/src/declarative/items/qsgcanvas_p.h +++ b/src/declarative/items/qsgcanvas_p.h @@ -64,7 +64,9 @@ #include <QtCore/qmutex.h> #include <QtCore/qwaitcondition.h> #include <private/qwidget_p.h> +#include <private/qwindow_p.h> #include <private/qgl_p.h> +#include <qguiglcontext_qpa.h> #include <QtOpenGL/qglframebufferobject.h> QT_BEGIN_NAMESPACE @@ -82,7 +84,7 @@ class QSGCanvasPrivate; class QTouchEvent; class QSGCanvasRenderThread; -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,8 +161,6 @@ public: QSGContext *context; - uint contextFailed : 1; - uint threadedRendering : 1; uint animationRunning: 1; uint renderThreadAwakened : 1; @@ -182,6 +185,7 @@ class QSGCanvasRenderThread : public QThread public: QSGCanvasRenderThread() : mutex(QMutex::NonRecursive) + , guiContext(0) , isGuiBlocked(0) , isPaintCompleted(false) , isGuiBlockPending(false) @@ -225,6 +229,8 @@ public: QSGCanvas *renderer; QSGCanvasPrivate *d; + QGuiGLContext *guiContext; + int isGuiBlocked; uint isPaintCompleted : 1; uint isGuiBlockPending : 1; 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/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 6045c5fee9..6649dc9f2c 100644 --- a/src/declarative/items/qsgshadereffect.cpp +++ b/src/declarative/items/qsgshadereffect.cpp @@ -49,6 +49,9 @@ #include <private/qsgtextureprovider_p.h> #include "qsgcanvas.h" +#include <qsgimage_p.h> +#include <qsgshadereffectsource_p.h> + #include <QtCore/qsignalmapper.h> #include <QtOpenGL/qglframebufferobject.h> @@ -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); } } @@ -578,12 +584,13 @@ QSGNode *QSGShaderEffect::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData 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 +623,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/qsgshadereffectnode.cpp b/src/declarative/items/qsgshadereffectnode.cpp index 8bd781ce58..d51317a122 100644 --- a/src/declarative/items/qsgshadereffectnode.cpp +++ b/src/declarative/items/qsgshadereffectnode.cpp @@ -110,15 +110,15 @@ void QSGCustomMaterialShader::updateState(const RenderState &state, QSGMaterial QGLFunctions *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 d7653b578b..ef6dd64532 100644 --- a/src/declarative/items/qsgshadereffectsource.cpp +++ b/src/declarative/items/qsgshadereffectsource.cpp @@ -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)); @@ -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(); + const QGLContext *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()); @@ -444,6 +485,7 @@ void QSGShaderEffectTexture::grab() QSGShaderEffectSource::QSGShaderEffectSource(QSGItem *parent) : QSGItem(parent) + , m_provider(0) , m_wrapMode(ClampToEdge) , m_sourceItem(0) , m_textureSize(0, 0) @@ -456,17 +498,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 @@ -753,17 +814,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) { @@ -771,19 +821,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 @@ -815,12 +853,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 ac8fde50d9..92a4ce8a76 100644 --- a/src/declarative/items/qsgshadereffectsource_p.h +++ b/src/declarative/items/qsgshadereffectsource_p.h @@ -64,6 +64,8 @@ class QSGNode; class UpdatePaintNodeData; class QGLFramebufferObject; +class QSGShaderEffectSourceTextureProvider; + class QSGShaderEffectSourceNode : public QObject, public QSGDefaultImageNode { Q_OBJECT @@ -114,6 +116,8 @@ public: void scheduleUpdate(); + void scheduleForCleanup(); + Q_SIGNALS: void textureChanged(); @@ -137,6 +141,8 @@ private: QSGRectangleNode *m_debugOverlay; #endif + QSGContext *m_context; + uint m_mipmap : 1; uint m_live : 1; uint m_recursive : 1; @@ -146,7 +152,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) @@ -158,7 +164,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 { @@ -204,8 +210,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(); @@ -226,7 +232,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/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/qsgview.cpp b/src/declarative/items/qsgview.cpp index 416b803814..48b3074363 100644 --- a/src/declarative/items/qsgview.cpp +++ b/src/declarative/items/qsgview.cpp @@ -87,18 +87,19 @@ public: QSGView::ResizeMode resizeMode; QSize initialSize; QElapsedTimer frameTimer; + + bool resized; }; 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) { } @@ -141,28 +142,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) +QSGView::QSGView(QWindow *parent, Qt::WindowFlags f) +: QSGCanvas(*(new QSGViewPrivate), parent) { + setWindowFlags(f); d_func()->init(); } -QSGView::QSGView(const QUrl &source, QWidget *parent, Qt::WindowFlags f) -: QSGCanvas(*(new QSGViewPrivate), parent, 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); } @@ -260,8 +250,6 @@ void QSGViewPrivate::updateSize() if (!qFuzzyCompare(q->height(), root->height())) root->setHeight(q->height()); } - - q->updateGeometry(); } QSize QSGViewPrivate::rootObjectSize() const @@ -348,14 +336,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(); } @@ -416,22 +403,6 @@ void QSGView::resizeEvent(QResizeEvent *e) 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; -} - void QSGView::keyPressEvent(QKeyEvent *e) { QDeclarativeDebugTrace::addEvent(QDeclarativeDebugTrace::Key); 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 *); |