diff options
Diffstat (limited to 'src/quick/items')
-rw-r--r-- | src/quick/items/context2d/qquickcontext2d.cpp | 3 | ||||
-rw-r--r-- | src/quick/items/context2d/qquickcontext2d_p.h | 2 | ||||
-rw-r--r-- | src/quick/items/items.pri | 8 | ||||
-rw-r--r-- | src/quick/items/qquickthreadedwindowmanager.cpp | 910 | ||||
-rw-r--r-- | src/quick/items/qquickthreadedwindowmanager_p.h | 181 | ||||
-rw-r--r-- | src/quick/items/qquickwindow.cpp | 70 | ||||
-rw-r--r-- | src/quick/items/qquickwindow_p.h | 4 | ||||
-rw-r--r-- | src/quick/items/qquickwindowmanager.cpp | 363 | ||||
-rw-r--r-- | src/quick/items/qquickwindowmanager_p.h | 87 |
9 files changed, 55 insertions, 1573 deletions
diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp index a46cd6ab70..c857a69f75 100644 --- a/src/quick/items/context2d/qquickcontext2d.cpp +++ b/src/quick/items/context2d/qquickcontext2d.cpp @@ -62,7 +62,6 @@ #include <private/qv8domerrors_p.h> #include <QtCore/qnumeric.h> #include <private/qquickwindow_p.h> -#include <private/qquickwindowmanager_p.h> #if defined(Q_OS_QNX) || defined(Q_OS_LINUX_ANDROID) #include <ctype.h> @@ -3348,7 +3347,6 @@ QQuickContext2D::QQuickContext2D(QObject *parent) : QQuickCanvasContext(parent) , m_buffer(new QQuickContext2DCommandBuffer) , m_v8engine(0) - , m_windowManager(0) , m_surface(0) , m_glContext(0) , m_thread(0) @@ -3380,7 +3378,6 @@ void QQuickContext2D::init(QQuickCanvasItem *canvasItem, const QVariantMap &args m_renderTarget = canvasItem->renderTarget(); QQuickWindow *window = canvasItem->window(); - m_windowManager = QQuickWindowPrivate::get(window)->windowManager; m_renderStrategy = canvasItem->renderStrategy(); switch (m_renderTarget) { diff --git a/src/quick/items/context2d/qquickcontext2d_p.h b/src/quick/items/context2d/qquickcontext2d_p.h index 2124c731b2..8d96ab579b 100644 --- a/src/quick/items/context2d/qquickcontext2d_p.h +++ b/src/quick/items/context2d/qquickcontext2d_p.h @@ -70,7 +70,6 @@ class QQuickContext2DCommandBuffer; class QQuickContext2DTexture; class QQuickPixmap; class QSGTexture; -class QQuickWindowManager; class QSurface; class QOpenGLContext; @@ -240,7 +239,6 @@ public: v8::Local<v8::Value> m_strokeStyle; v8::Handle<v8::Value> m_v8path; QV8Engine *m_v8engine; - QQuickWindowManager *m_windowManager; QSurface *m_surface; QOpenGLContext *m_glContext; v8::Persistent<v8::Object> m_v8value; diff --git a/src/quick/items/items.pri b/src/quick/items/items.pri index 13abf7b958..5272a3d5f7 100644 --- a/src/quick/items/items.pri +++ b/src/quick/items/items.pri @@ -74,9 +74,7 @@ HEADERS += \ $$PWD/qquickitemview_p_p.h \ $$PWD/qquickitemviewtransition_p.h \ $$PWD/qquickscreen_p.h \ - $$PWD/qquickwindowmodule_p.h \ - $$PWD/qquickwindowmanager_p.h \ - $$PWD/qquickthreadedwindowmanager_p.h + $$PWD/qquickwindowmodule_p.h SOURCES += \ $$PWD/qquickevents.cpp \ @@ -128,9 +126,7 @@ SOURCES += \ $$PWD/qquickitemview.cpp \ $$PWD/qquickitemviewtransition.cpp \ $$PWD/qquickwindowmodule.cpp \ - $$PWD/qquickscreen.cpp \ - $$PWD/qquickwindowmanager.cpp \ - $$PWD/qquickthreadedwindowmanager.cpp + $$PWD/qquickscreen.cpp SOURCES += \ $$PWD/qquickshadereffect.cpp \ diff --git a/src/quick/items/qquickthreadedwindowmanager.cpp b/src/quick/items/qquickthreadedwindowmanager.cpp deleted file mode 100644 index 6c7b9c0448..0000000000 --- a/src/quick/items/qquickthreadedwindowmanager.cpp +++ /dev/null @@ -1,910 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qquickwindowmanager_p.h" -#include "qquickthreadedwindowmanager_p.h" - -#include <QtCore/QTime> -#include <QtCore/QDebug> - -#include <QtGui/QOpenGLContext> -#include <QtGui/private/qguiapplication_p.h> -#include <qpa/qplatformintegration.h> - -#include <QtQml/private/qqmlglobal_p.h> - -#include <QtQuick/QQuickWindow> -#include <QtQuick/private/qquickwindow_p.h> - -QT_BEGIN_NAMESPACE - -//#define THREAD_DEBUG -extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha); - -const QEvent::Type QEvent_Sync = QEvent::Type(QEvent::User); -const QEvent::Type QEvent_DeferredUpdate = QEvent::Type(QEvent::User + 1); - -#define QQUICK_RENDER_TIMING -#ifdef QQUICK_RENDER_TIMING -DEFINE_BOOL_CONFIG_OPTION(qquick_render_timing, QML_RENDER_TIMING) -static QTime threadTimer; -static int syncTime; -static int renderTime; -static int swapTime; -#endif - - -/* - Threaded Rendering - ================== - - The threaded rendering uses a number of different variables to track potential - states used to handle resizing, initial paint, grabbing and driving animations - while ALWAYS keeping the GL context in the rendering thread and keeping the - overhead of normal one-shot paints and vblank driven animations at a minimum. - - Resize, initial show and grab suffer slightly in this model as they are locked - to the rendering in the rendering thread, but this is a necessary evil for - the system to work. - - Variables that are used: - - Private::animationRunning: This is true while the animations are running, and only - written to inside locks. - - RenderThread::isGuiLocked: This is used to indicate that the GUI thread owns the - lock. This variable is an integer to allow for recursive calls to lockInGui() - without using a recursive mutex. See isPostingSyncEvent. - - RenderThread::isPostingSyncEvent: This variable is set in the render thread just - before the sync event is sent to the GUI thread. It is used to avoid deadlocks - in the case where render thread waits while waiting for GUI to pick up the sync - event and GUI thread gets a resizeEvent, the initial paintEvent or a grab. - When this happens, we use the - exhaustSyncEvent() function to do the sync right there and mark the coming - sync event to be discarded. There can only ever be one sync incoming. - - RenderThread::isRenderBlock: This variable is true when animations are not - running and the render thread has gone to sleep, waiting for more to do. - - RenderThread::isExternalUpdatePending: This variable is set to false when - a new render pass is started and to true in maybeUpdate(). It is an - indication to the render thread that another render pass needs to take - place, rather than the render thread going to sleep after completing its swap. - - RenderThread::doGrab: This variable is set by the grab() function and - tells the renderer to do a grab after rendering is complete and before - swapping happens. - - RenderThread::shouldExit: This variable is used to determine if the render - thread should do a nother pass. It is typically set as a result of show() - and unset as a result of hide() or during shutdown() - - RenderThread::hasExited: Used by the GUI thread to synchronize the shutdown - after shouldExit has been set to true. - */ - - -void QQuickRenderThreadSingleContextWindowManager::initialize() -{ - Q_ASSERT(m_rendered_windows.size()); - - QQuickWindow *win = 0; - for (QHash<QQuickWindow *, WindowData *>::const_iterator it = m_rendered_windows.constBegin(); - it != m_rendered_windows.constEnd() && !win; ++it) { - if (QQuickWindowPrivate::get(it.key())->isRenderable()) - win = it.key(); - } - if (!win) - return; - - gl = new QOpenGLContext(); - // Pick up the surface format from one of them - gl->setFormat(win->requestedFormat()); - gl->create(); - if (!gl->makeCurrent(win)) - qWarning("QQuickWindow: makeCurrent() failed..."); - - Q_ASSERT(!sg->isReady()); - sg->initialize(gl); -} - - -/*! - This function is called when the window is created to register the window with - the window manager. - - Called on GUI Thread. - */ - -void QQuickRenderThreadSingleContextWindowManager::show(QQuickWindow *window) -{ -#ifdef THREAD_DEBUG - printf("GUI: Window added to windowing system, %p, %dx%d\n", window, window->width(), window->height()); -#endif - - WindowTracker tracker; - tracker.window = window; - tracker.isVisible = false; - tracker.toBeRemoved = false; - m_tracked_windows << tracker; - - connect(window, SIGNAL(widthChanged(int)), this, SLOT(windowVisibilityChanged()), Qt::DirectConnection); - connect(window, SIGNAL(heightChanged(int)), this, SLOT(windowVisibilityChanged()), Qt::DirectConnection); - - windowVisibilityChanged(); -} - - -void QQuickRenderThreadSingleContextWindowManager::handleAddedWindow(QQuickWindow *window) -{ -#ifdef THREAD_DEBUG - printf(" RenderThread: adding window: %p\n", window); -#endif - - WindowData *data = new WindowData; - data->sizeWasChanged = false; - data->windowSize = window->size(); - data->isVisible = window->isVisible(); - data->isRenderable = QQuickWindowPrivate::get(window)->isRenderable(); - m_rendered_windows[window] = data; - - isExternalUpdatePending = true; -} - - -/*! - Called on Render Thread - */ -void QQuickRenderThreadSingleContextWindowManager::handleAddedWindows() -{ -#ifdef THREAD_DEBUG - printf(" RenderThread: about to add %d\n", m_added_windows.size()); -#endif - - while (m_added_windows.size()) { - QQuickWindow *window = m_added_windows.takeLast(); - handleAddedWindow(window); - } -} - - -/*! - Called on the GUI Thread, from the window' destructor - */ - -void QQuickRenderThreadSingleContextWindowManager::windowDestroyed(QQuickWindow *window) -{ -#ifdef THREAD_DEBUG - printf("GUI: Window destroyed: %p\n", window); -#endif - - hide(window); -} - - -/*! - Called on GUI Thread - */ - -void QQuickRenderThreadSingleContextWindowManager::hide(QQuickWindow *window) -{ -#ifdef THREAD_DEBUG - printf("GUI: Window hidden: %p\n", window); -#endif - - int position = -1; - for (int i=0; i<m_tracked_windows.size(); ++i) { - if (m_tracked_windows.at(i).window == window) { - m_tracked_windows[i].toBeRemoved = true; - position = i; - break; - } - } - - if (position >= 0) { - disconnect(window, SIGNAL(widthChanged(int)), this, SLOT(windowVisibilityChanged())); - disconnect(window, SIGNAL(heightChanged(int)), this, SLOT(windowVisibilityChanged())); - windowVisibilityChanged(); - m_tracked_windows.removeAt(position); - } - -#ifdef THREAD_DEBUG - printf("GUI: Window removal completed... %p\n", window); -#endif -} - -/*! - Called on Render Thread - */ -void QQuickRenderThreadSingleContextWindowManager::handleRemovedWindows(bool clearGLContext) -{ -#ifdef THREAD_DEBUG - printf(" RenderThread: about to remove %d\n", m_removed_windows.size()); -#endif - - bool removedAnything = false; - while (m_removed_windows.size()) { - QQuickWindow *window = m_removed_windows.takeLast(); -#ifdef THREAD_DEBUG - printf(" RenderThread: removing %p\n", window); -#endif - - QQuickWindowPrivate::get(window)->cleanupNodesOnShutdown(); - delete m_rendered_windows.take(window); - removedAnything = true; - } - - // If a window is removed because it has been hidden it will take with it - // the gl context (at least on Mac) if bound, so disconnect the gl context - // from anything - if (removedAnything && clearGLContext) - gl->doneCurrent(); -} - - - -/*! - Called on GUI Thread - */ - -void QQuickRenderThreadSingleContextWindowManager::windowVisibilityChanged() -{ - bool anyoneShowing = false; - QList<QQuickWindow *> toAdd, toRemove; - - // Not optimal, but also not frequently used... - for (int i=0; i<m_tracked_windows.size(); ++i) { - WindowTracker &t = const_cast<WindowTracker &>(m_tracked_windows.at(i)); - QQuickWindow *win = t.window; - - Q_ASSERT(win->isVisible() || QQuickWindowPrivate::get(win)->renderWithoutShowing || t.toBeRemoved); - bool windowVisible = win->width() > 0 && win->height() > 0; - anyoneShowing |= (windowVisible && !t.toBeRemoved); - - if ((!windowVisible && t.isVisible) || t.toBeRemoved) { - toRemove << win; - } else if (windowVisible && !t.isVisible) { - toAdd << win; - } - t.isVisible = windowVisible; - } - - if (isRunning()) { - if (!anyoneShowing) { - stopRendering(); - } else { - lockInGui(); - exhaustSyncEvent(); - m_added_windows << toAdd; - m_removed_windows << toRemove; - while (isRunning() && (m_added_windows.size() || m_removed_windows.size())) { - if (isRenderBlocked) - wake(); - wait(); - } - unlockInGui(); - } - - } else if (anyoneShowing) { - Q_ASSERT(toRemove.isEmpty()); // since loop is not running, nothing is showing now - for (int i=0; i<toAdd.size(); ++i) - handleAddedWindow(toAdd.at(i)); - startRendering(); - } - -} - - -void QQuickRenderThreadSingleContextWindowManager::run() -{ -#ifdef THREAD_DEBUG - printf("QML Rendering Thread Started\n"); -#endif - - lock(); - Q_ASSERT(!gl); - initialize(); - // Wake GUI as it is waiting for the GL context to have appeared, as - // an indication that the render thread is now running. - wake(); - unlock(); - - if (!gl) - return; - - while (!shouldExit) { - lock(); - -#ifdef THREAD_DEBUG - printf(" RenderThread: *** NEW FRAME ***\n"); -#endif - - isExternalUpdatePending = false; - handleAddedWindows(); - - if (!isGuiLocked) { - isPostingSyncEvent = true; - -#ifdef THREAD_DEBUG - printf(" RenderThread: acquired sync lock...\n"); -#endif - QCoreApplication::postEvent(this, new QEvent(QEvent_Sync)); - -#ifdef THREAD_DEBUG - printf(" RenderThread: going to sleep...\n"); -#endif - wake(); // In case the event got through all the way to wait() before this thread got to wait. - wait(); - - - isPostingSyncEvent = false; - } - -#ifdef THREAD_DEBUG - printf(" RenderThread: Doing locked sync\n"); -#endif -#ifdef QQUICK_RENDER_TIMING - if (qquick_render_timing()) - threadTimer.start(); -#endif - inSync = true; - for (QHash<QQuickWindow *, WindowData *>::const_iterator it = m_rendered_windows.constBegin(); - it != m_rendered_windows.constEnd(); ++it) { - QQuickWindow *window = it.key(); - -#ifdef THREAD_DEBUG - printf(" RenderThread: Syncing window: %p\n", window); -#endif - - WindowData *windowData = it.value(); - QQuickWindowPrivate *windowPrivate = QQuickWindowPrivate::get(window); - - windowData->isRenderable = windowPrivate->isRenderable(); - - if (windowData->isRenderable) { - gl->makeCurrent(window); - - if (windowData->viewportSize != windowData->windowSize) { -#ifdef THREAD_DEBUG - printf(" RenderThread: --- window has changed size...\n"); -#endif - windowData->viewportSize = windowData->windowSize; - windowData->sizeWasChanged = true; - glViewport(0, 0, windowData->viewportSize.width(), windowData->viewportSize.height()); - } - - windowPrivate->syncSceneGraph(); - } - } - inSync = false; - - // Wake GUI after sync to let it continue animating and event processing. - wake(); - unlock(); -#ifdef THREAD_DEBUG - printf(" RenderThread: sync done\n"); -#endif -#ifdef QQUICK_RENDER_TIMING - if (qquick_render_timing()) - syncTime = threadTimer.elapsed(); -#endif - - for (QHash<QQuickWindow *, WindowData *>::const_iterator it = m_rendered_windows.constBegin(); - it != m_rendered_windows.constEnd(); ++it) { - QQuickWindow *window = it.key(); - WindowData *windowData = it.value(); - QQuickWindowPrivate *windowPrivate = QQuickWindowPrivate::get(window); - - if (!windowData->isRenderable) - continue; - -#ifdef THREAD_DEBUG - printf(" RenderThread: Rendering window %p\n", window); -#endif - - Q_ASSERT(windowData->windowSize.width() > 0 && windowData->windowSize.height() > 0); - -#ifdef THREAD_DEBUG - printf(" RenderThread: --- rendering at size %dx%d\n", - windowData->viewportSize.width(), windowData->viewportSize.height() - ); -#endif - - // We only need to re-makeCurrent when we have multiple surfaces. - if (m_rendered_windows.size() > 1) - gl->makeCurrent(window); - - windowPrivate->renderSceneGraph(windowData->viewportSize); -#ifdef QQUICK_RENDER_TIMING - if (qquick_render_timing()) - renderTime = threadTimer.elapsed() - syncTime; -#endif - - // The content of the target buffer is undefined after swap() so grab needs - // to happen before swap(); - if (window == windowToGrab) { -#ifdef THREAD_DEBUG - printf(" RenderThread: --- grabbing...\n"); -#endif - grabContent = qt_gl_read_framebuffer(windowData->windowSize, false, false); - windowToGrab = 0; - } - -#ifdef THREAD_DEBUG - printf(" RenderThread: --- wait for swap...\n"); -#endif - - if (windowData->isVisible && window->isExposed()) - gl->swapBuffers(window); - - windowPrivate->fireFrameSwapped(); -#ifdef THREAD_DEBUG - printf(" RenderThread: --- swap complete...\n"); -#endif - - } - -#ifdef QQUICK_RENDER_TIMING - if (qquick_render_timing()) { - static QTime lastFrameTime = QTime::currentTime(); - swapTime = threadTimer.elapsed() - renderTime - syncTime; - qDebug() << "- Breakdown of frame time; sync:" << syncTime - << "ms render:" << renderTime << "ms swap:" << swapTime - << "ms total:" << swapTime + renderTime + syncTime - << "ms time since last frame:" << (lastFrameTime.msecsTo(QTime::currentTime())) - << "ms"; - lastFrameTime = QTime::currentTime(); - } -#endif - - lock(); - - handleRemovedWindows(); - - // Update sizes... - for (QHash<QQuickWindow *, WindowData *>::const_iterator it = m_rendered_windows.constBegin(); - it != m_rendered_windows.constEnd(); ++it) { - WindowData *windowData = it.value(); - if (windowData->sizeWasChanged) { - windowData->renderedSize = windowData->viewportSize; - windowData->sizeWasChanged = false; - } - } - - - // Wake the GUI thread now that rendering is complete, to signal that painting - // is done, resizing is done or grabbing is completed. For grabbing, we're - // signalling this much later than needed (we could have done it before swap) - // but we don't want to lock an extra time. - wake(); - - if (!animationRunning && !isExternalUpdatePending && !shouldExit && !windowToGrab) { -#ifdef THREAD_DEBUG - printf(" RenderThread: nothing to do, going to sleep...\n"); -#endif - isRenderBlocked = true; - wait(); - isRenderBlocked = false; - } - - unlock(); - - QCoreApplication::processEvents(); - - // Process any "deleteLater" objects... - QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); - } - -#ifdef THREAD_DEBUG - printf(" RenderThread: deleting all outstanding nodes\n"); -#endif - - m_removed_windows << m_rendered_windows.keys(); - handleRemovedWindows(false); - - sg->invalidate(); - - gl->doneCurrent(); - delete gl; - gl = 0; - -#ifdef THREAD_DEBUG - printf(" RenderThread: render loop exited... Good Night!\n"); -#endif - - lock(); - hasExited = true; - -#ifdef THREAD_DEBUG - printf(" RenderThread: waking GUI for final sleep..\n"); -#endif - wake(); - unlock(); - -#ifdef THREAD_DEBUG - printf(" RenderThread: All done...\n"); -#endif -} - -bool QQuickRenderThreadSingleContextWindowManager::event(QEvent *e) -{ - Q_ASSERT(QThread::currentThread() == qApp->thread()); - - if (e->type() == QEvent_Sync) { - - // If all windowes have been hidden, ignore the event - if (!isRunning()) - return true; - - if (!syncAlreadyHappened) - sync(false); - - syncAlreadyHappened = false; - - if (animationRunning) { -#ifdef THREAD_DEBUG - printf("GUI: Advancing animations...\n"); -#endif - - animDriver->advance(); - -#ifdef THREAD_DEBUG - printf("GUI: Animations advanced...\n"); -#endif - } - - return true; - } else if (e->type() == QEvent_DeferredUpdate) { - handleDeferredUpdate(); - - } else if (e->type() == QEvent::Timer) { -#ifdef THREAD_DEBUG - printf("GUI: Animations advanced via timer...\n"); -#endif - animDriver->advance(); - } - - return QThread::event(e); -} - - - -void QQuickRenderThreadSingleContextWindowManager::exhaustSyncEvent() -{ - if (isPostingSyncEvent) { - sync(true); - syncAlreadyHappened = true; - } -} - - - -void QQuickRenderThreadSingleContextWindowManager::sync(bool guiAlreadyLocked) -{ -#ifdef THREAD_DEBUG - printf("GUI: sync - %s\n", guiAlreadyLocked ? "outside event" : "inside event"); -#endif - if (!guiAlreadyLocked) - lockInGui(); - - for (QHash<QQuickWindow *, WindowData *>::const_iterator it = m_rendered_windows.constBegin(); - it != m_rendered_windows.constEnd(); ++it) { - QQuickWindowPrivate::get(it.key())->polishItems(); - } - - wake(); - wait(); - - if (!guiAlreadyLocked) - unlockInGui(); -} - - - - -/*! - Acquires the mutex for the GUI thread. The function uses the isGuiLocked - variable to keep track of how many recursion levels the gui is locked with. - We only actually acquire the mutex for the first level to avoid deadlocking - ourselves. - */ - -void QQuickRenderThreadSingleContextWindowManager::lockInGui() -{ - if (++isGuiLocked == 1) - lock(); - -#ifdef THREAD_DEBUG - printf("GUI: acquired lock... level=%d\n", isGuiLocked); -#endif -} - - - -void QQuickRenderThreadSingleContextWindowManager::unlockInGui() -{ -#ifdef THREAD_DEBUG - printf("GUI: releasing lock... level=%d\n", isGuiLocked); -#endif - - if (--isGuiLocked == 0) - unlock(); -} - - - - -void QQuickRenderThreadSingleContextWindowManager::animationStarted() -{ -#ifdef THREAD_DEBUG - printf("GUI: animationStarted()\n"); -#endif - - if (!isRunning()) { - animationTimer = startTimer(1000/60); - return; - } - - lockInGui(); - - animationRunning = true; - - if (isRenderBlocked) - wake(); - - unlockInGui(); -} - - - -void QQuickRenderThreadSingleContextWindowManager::animationStopped() -{ -#ifdef THREAD_DEBUG - printf("GUI: animationStopped()...\n"); -#endif - - if (!isRunning()) { - killTimer(animationTimer); - animationTimer = -1; - return; - } - - lockInGui(); - animationRunning = false; - unlockInGui(); -} - - -void QQuickRenderThreadSingleContextWindowManager::exposureChanged(QQuickWindow *window) -{ - Q_UNUSED(window); -#ifdef THREAD_DEBUG - printf("GUI: exposure changed: %p\n", window); -#endif - - if (window->isExposed()) - maybeUpdate(window); - -#ifdef THREAD_DEBUG - printf("GUI: exposure changed done: %p\n", window); -#endif -} - - - -void QQuickRenderThreadSingleContextWindowManager::resize(QQuickWindow *window, const QSize &size) -{ -#ifdef THREAD_DEBUG - printf("GUI: Resize Event: %p = %dx%d\n", window, size.width(), size.height()); -#endif - - // If the rendering thread is not running we do not need to do anything. - // Also if the window is being resized to an invalid size, it will be removed - // by the windowVisibilityChanged slot as result of width/heightcChanged() - if (!isRunning() || size.width() <= 0 || size.height() <= 0) - return; - - lockInGui(); - exhaustSyncEvent(); - - WindowData *windowData = m_rendered_windows.value(window); - if (windowData) { - windowData->windowSize = size; - while (isRunning() && windowData->renderedSize != size && size.width() > 0 && size.height() > 0) { - if (isRenderBlocked) - wake(); - wait(); - } - } - unlockInGui(); - -#ifdef THREAD_DEBUG - printf("GUI: Resize done: %p\n", window); -#endif -} - - - -void QQuickRenderThreadSingleContextWindowManager::startRendering() -{ -#ifdef THREAD_DEBUG - printf("GUI: Starting Render Thread\n"); -#endif - hasExited = false; - shouldExit = false; - isGuiLocked = 0; - isPostingSyncEvent = false; - syncAlreadyHappened = false; - inSync = false; - - lockInGui(); - animationRunning = animDriver->isRunning(); - start(); // Start the render thread... - wait(); - unlockInGui(); - - // Animations will now be driven from the rendering thread. - if (animationTimer >= 0) { - killTimer(animationTimer); - animationTimer = -1; - } - - -} - - - -void QQuickRenderThreadSingleContextWindowManager::stopRendering() -{ -#ifdef THREAD_DEBUG - printf("GUI: stopping render thread\n"); -#endif - - lockInGui(); - exhaustSyncEvent(); - shouldExit = true; - - if (isRenderBlocked) { -#ifdef THREAD_DEBUG - printf("GUI: waking up render thread\n"); -#endif - wake(); - } - - while (!hasExited) { -#ifdef THREAD_DEBUG - printf("GUI: waiting for render thread to have exited..\n"); -#endif - wait(); - } - - unlockInGui(); - -#ifdef THREAD_DEBUG - printf("GUI: waiting for render thread to terminate..\n"); -#endif - // 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 - - // Activate timer to keep animations running - if (animDriver->isRunning()) - animationTimer = startTimer(1000/60); -} - - - -QImage QQuickRenderThreadSingleContextWindowManager::grab(QQuickWindow *window) -{ - if (!isRunning()) - return QImage(); - - if (QThread::currentThread() != qApp->thread()) { - qWarning("QQuickWindow::grabFrameBuffer: can only be called from the GUI thread"); - return QImage(); - } else if (window->size().width() <= 0 || window->size().height() <= 0 ) { - qWarning("QQuickWindow::grabFrameBuffer: Can't grab a Window with size %dx%d", window->size().width(), window->size().height()); - return QImage(); - } - -#ifdef THREAD_DEBUG - printf("GUI: doing a pixelwise grab..\n"); -#endif - - lockInGui(); - exhaustSyncEvent(); - - windowToGrab = window; - while (isRunning() && windowToGrab) { - if (isRenderBlocked) - wake(); - wait(); - } - - QImage grabbed = grabContent; - grabContent = QImage(); - - unlockInGui(); - - return grabbed; -} - - -void QQuickRenderThreadSingleContextWindowManager::handleDeferredUpdate() -{ -#ifdef THREAD_DEBUG - printf("GUI: handling update to ourselves...\n"); -#endif - - isDeferredUpdatePosted = false; - - lockInGui(); - isExternalUpdatePending = true; - if (isRenderBlocked) - wake(); - unlockInGui(); -} - -void QQuickRenderThreadSingleContextWindowManager::maybeUpdate(QQuickWindow *) -{ - Q_ASSERT_X(QThread::currentThread() == QCoreApplication::instance()->thread() || inSync, - "QQuickWindow::update", - "Function can only be called from GUI thread or during QQuickItem::updatePaintNode()"); - - if (inSync) { - isExternalUpdatePending = true; - - } else if (!isDeferredUpdatePosted) { -#ifdef THREAD_DEBUG - printf("GUI: posting update to ourselves...\n"); -#endif - isDeferredUpdatePosted = true; - QCoreApplication::postEvent(this, new QEvent(QEvent_DeferredUpdate)); - } - -} - -QT_END_NAMESPACE diff --git a/src/quick/items/qquickthreadedwindowmanager_p.h b/src/quick/items/qquickthreadedwindowmanager_p.h deleted file mode 100644 index 76325e2d4f..0000000000 --- a/src/quick/items/qquickthreadedwindowmanager_p.h +++ /dev/null @@ -1,181 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QQUICKTHREADEDWINDOWMANAGER_P_H -#define QQUICKTHREADEDWINDOWMANAGER_P_H - -#include "qquickwindowmanager_p.h" - -#include <QtCore/QCoreApplication> -#include <QtCore/QMutex> -#include <QtCore/QWaitCondition> -#include <QtCore/private/qabstractanimation_p.h> - -#include <QtGui/QOpenGLContext> -#include <QtQuick/private/qsgcontext_p.h> -#include <private/qtquickglobal_p.h> - -QT_BEGIN_NAMESPACE - -class QQuickRenderThreadSingleContextWindowManager : public QThread, public QQuickWindowManager -{ - Q_OBJECT -public: - QQuickRenderThreadSingleContextWindowManager() - : sg(QSGContext::createDefaultContext()) - , gl(0) - , animationTimer(-1) - , isGuiLocked(0) - , animationRunning(false) - , isPostingSyncEvent(false) - , isRenderBlocked(false) - , isExternalUpdatePending(false) - , syncAlreadyHappened(false) - , inSync(false) - , shouldExit(false) - , hasExited(false) - , isDeferredUpdatePosted(false) - , windowToGrab(0) - { - sg->moveToThread(this); - - animDriver = sg->createAnimationDriver(this); - animDriver->install(); - connect(animDriver, SIGNAL(started()), this, SLOT(animationStarted())); - connect(animDriver, SIGNAL(stopped()), this, SLOT(animationStopped())); - } - - QSGContext *sceneGraphContext() const { return sg; } - - void releaseResources() { } - - void show(QQuickWindow *window); - void hide(QQuickWindow *window); - - void windowDestroyed(QQuickWindow *window); - - void exposureChanged(QQuickWindow *window); - QImage grab(QQuickWindow *window); - void resize(QQuickWindow *window, const QSize &size); - void handleDeferredUpdate(); - void maybeUpdate(QQuickWindow *window); - void update(QQuickWindow *window) { maybeUpdate(window); } // identical for this implementation - - void startRendering(); - void stopRendering(); - - void exhaustSyncEvent(); - void sync(bool guiAlreadyLocked); - - void initialize(); - - bool event(QEvent *); - - inline void lock() { mutex.lock(); } - inline void unlock() { mutex.unlock(); } - inline void wait() { condition.wait(&mutex); } - inline void wake() { condition.wakeOne(); } - void lockInGui(); - void unlockInGui(); - - void run(); - - QAnimationDriver *animationDriver() const { return animDriver; } - -public slots: - void animationStarted(); - void animationStopped(); - void windowVisibilityChanged(); - -private: - void handleAddedWindows(); - void handleAddedWindow(QQuickWindow *window); - void handleRemovedWindows(bool clearGLContext = true); - - QSGContext *sg; - QOpenGLContext *gl; - QAnimationDriver *animDriver; - int animationTimer; - - QMutex mutex; - QWaitCondition condition; - - int isGuiLocked; - uint animationRunning: 1; - uint isPostingSyncEvent : 1; - uint isRenderBlocked : 1; - uint isExternalUpdatePending : 1; - uint syncAlreadyHappened : 1; - uint inSync : 1; - uint shouldExit : 1; - uint hasExited : 1; - uint isDeferredUpdatePosted : 1; - - QQuickWindow *windowToGrab; - QImage grabContent; - - struct WindowData { - QSize renderedSize; - QSize windowSize; - QSize viewportSize; - - uint sizeWasChanged : 1; - uint isVisible : 1; - uint isRenderable : 1; - }; - - QHash<QQuickWindow *, WindowData *> m_rendered_windows; - - struct WindowTracker { - QQuickWindow *window; - uint isVisible : 1; - uint toBeRemoved : 1; - }; - - QList<WindowTracker> m_tracked_windows; - - QList<QQuickWindow *> m_removed_windows; - QList<QQuickWindow *> m_added_windows; -}; - -QT_END_NAMESPACE - -#endif // QQUICKTHREADEDWINDOWMANAGER_P_H diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 1b76dd7390..bf82423ca9 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -50,7 +50,7 @@ #include <QtQuick/private/qsgtexture_p.h> #include <QtQuick/private/qsgflashnode_p.h> -#include <private/qquickwindowmanager_p.h> +#include <private/qsgrenderloop_p.h> #include <private/qguiapplication_p.h> #include <QtGui/QInputMethod> @@ -366,8 +366,8 @@ QQuickWindowPrivate::QQuickWindowPrivate() , windowManager(0) , clearColor(Qt::white) , clearBeforeRendering(true) - , persistentGLContext(false) - , persistentSceneGraph(false) + , persistentGLContext(true) + , persistentSceneGraph(true) , lastWheelEventAccepted(false) , renderTarget(0) , renderTargetId(0) @@ -392,7 +392,7 @@ void QQuickWindowPrivate::init(QQuickWindow *c) contentItemPrivate->windowRefCount = 1; contentItemPrivate->flags |= QQuickItem::ItemIsFocusScope; - windowManager = QQuickWindowManager::instance(); + windowManager = QSGRenderLoop::instance(); context = windowManager->sceneGraphContext(); q->setSurfaceType(QWindow::OpenGLSurface); q->setFormat(context->defaultSurfaceFormat()); @@ -923,6 +923,8 @@ QQuickWindow::QQuickWindow(QWindow *parent) d->init(this); } + + /*! \internal */ @@ -966,20 +968,32 @@ QQuickWindow::~QQuickWindow() void QQuickWindow::releaseResources() { Q_D(QQuickWindow); - d->windowManager->releaseResources(); + d->windowManager->releaseResources(this); QQuickPixmap::purgeCache(); } /*! - Sets whether the OpenGL context can be released as a part of a call to - releaseResources() to \a persistent. + Sets whether the OpenGL context can be released to \a + persistent. The default value is true. + + The OpenGL context can be released to free up graphics resources + when the window is obscured, hidden or not rendering. When this + happens is implementation specific. - The OpenGL context might still be released when the user makes an explicit - call to hide(). + The QOpenGLContext::aboutToBeDestroyed() signal is emitted from + the QQuickWindow::openglContext() when the OpenGL context is about + to be released. The QQuickWindow::sceneGraphInitialized() signal + is emitted when a new OpenGL context is created for this + window. Make a Qt::DirectConnection to these signals to be + notified. - \sa setPersistentSceneGraph() + The OpenGL context is still released when the last QQuickWindow is + deleted. + + \sa setPersistentSceneGraph(), + QOpenGLContext::aboutToBeDestroyed(), sceneGraphInitialized() */ void QQuickWindow::setPersistentOpenGLContext(bool persistent) @@ -989,9 +1003,13 @@ void QQuickWindow::setPersistentOpenGLContext(bool persistent) } + /*! - Returns whether the OpenGL context can be released as a part of a call to - releaseResources(). + Returns whether the OpenGL context can be released during the + lifetime of the QQuickWindow. + + \note This is a hint. When and how this happens is implementation + specific. */ bool QQuickWindow::isPersistentOpenGLContext() const @@ -1003,13 +1021,24 @@ bool QQuickWindow::isPersistentOpenGLContext() const /*! - Sets whether the scene graph nodes and resources can be released as a - part of a call to releaseResources() to \a persistent. + Sets whether the scene graph nodes and resources can be released + to \a persistent. The default value is true. + + The scene graph nodes and resources can be released to free up + graphics resources when the window is obscured, hidden or not + rendering. When this happens is implementation specific. - The scene graph nodes and resources might still be released when the user - makes an explicit call to hide(). + The QQuickWindow::sceneGraphInvalidated() signal is emitted when + cleanup occurs. The QQuickWindow::sceneGraphInitialized() signal + is emitted when a new scene graph is recreated for this + window. Make a Qt::DirectConnection to these signals to be + notified. - \sa setPersistentOpenGLContext() + The scene graph nodes and resources are still released when the + last QQuickWindow is deleted. + + \sa setPersistentOpenGLContext(), + sceneGraphInvalidated(), sceneGraphInitialized() */ void QQuickWindow::setPersistentSceneGraph(bool persistent) @@ -1021,8 +1050,11 @@ void QQuickWindow::setPersistentSceneGraph(bool persistent) /*! - Returns whether the scene graph nodes and resources can be released as a part - of a call to releaseResources(). + Returns whether the scene graph nodes and resources can be + released during the lifetime of this QQuickWindow. + + \note This is a hint. When and how this happens is implementation + specific. */ bool QQuickWindow::isPersistentSceneGraph() const diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h index da2ae8284d..f272f30f8e 100644 --- a/src/quick/items/qquickwindow_p.h +++ b/src/quick/items/qquickwindow_p.h @@ -73,7 +73,7 @@ QT_BEGIN_NAMESPACE //Make it easy to identify and customize the root item if needed -class QQuickWindowManager; +class QSGRenderLoop; class QQuickRootItem : public QQuickItem { @@ -200,7 +200,7 @@ public: QSGContext *context; QSGRenderer *renderer; - QQuickWindowManager *windowManager; + QSGRenderLoop *windowManager; QColor clearColor; diff --git a/src/quick/items/qquickwindowmanager.cpp b/src/quick/items/qquickwindowmanager.cpp deleted file mode 100644 index 69aa63c278..0000000000 --- a/src/quick/items/qquickwindowmanager.cpp +++ /dev/null @@ -1,363 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qquickwindowmanager_p.h" -#include "qquickthreadedwindowmanager_p.h" - -#include <QtCore/QCoreApplication> -#include <QtCore/QTime> -#include <QtCore/private/qabstractanimation_p.h> - -#include <QtGui/QOpenGLContext> -#include <QtGui/private/qguiapplication_p.h> -#include <qpa/qplatformintegration.h> - -#include <QtQml/private/qqmlglobal_p.h> - -#include <QtQuick/QQuickWindow> -#include <QtQuick/private/qquickwindow_p.h> -#include <QtQuick/private/qsgcontext_p.h> - -QT_BEGIN_NAMESPACE - -DEFINE_BOOL_CONFIG_OPTION(qquick_render_timing, QML_RENDER_TIMING) - -extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha); - -/*! - expectations for this manager to work: - - one opengl context to render multiple windows - - OpenGL pipeline will not block for vsync in swap - - OpenGL pipeline will block based on a full buffer queue. - - Multiple screens can share the OpenGL context - - Animations are advanced for all windows once per swap - */ - -DEFINE_BOOL_CONFIG_OPTION(qmlNoThreadedRenderer, QML_BAD_GUI_RENDER_LOOP); -DEFINE_BOOL_CONFIG_OPTION(qmlForceThreadedRenderer, QML_FORCE_THREADED_RENDERER); // Might trigger graphics driver threading bugs, use at own risk - -QQuickWindowManager *QQuickWindowManager::s_instance = 0; - -QQuickWindowManager::~QQuickWindowManager() -{ -} - -class QQuickTrivialWindowManager : public QObject, public QQuickWindowManager -{ - Q_OBJECT -public: - QQuickTrivialWindowManager(); - - void show(QQuickWindow *window); - void hide(QQuickWindow *window); - - void windowDestroyed(QQuickWindow *window); - - void initializeGL(); - void renderWindow(QQuickWindow *window); - void exposureChanged(QQuickWindow *window); - QImage grab(QQuickWindow *window); - void resize(QQuickWindow *window, const QSize &size); - - void maybeUpdate(QQuickWindow *window); - void update(QQuickWindow *window) { maybeUpdate(window); } // identical for this implementation. - - void releaseResources() { } - - QAnimationDriver *animationDriver() const { return 0; } - - QSGContext *sceneGraphContext() const; - - bool event(QEvent *); - - struct WindowData { - bool updatePending : 1; - bool grabOnly : 1; - }; - - QHash<QQuickWindow *, WindowData> m_windows; - - QOpenGLContext *gl; - QSGContext *sg; - - QImage grabContent; - - bool eventPending; -}; - - -QQuickWindowManager *QQuickWindowManager::instance() -{ - if (!s_instance) { - - s_instance = QSGContext::createWindowManager(); - - bool bufferQueuing = QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::BufferQueueingOpenGL); -#ifdef Q_OS_WIN - bool fancy = false; // QTBUG-28037 -#else - bool fancy = QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ThreadedOpenGL); -#endif - if (qmlNoThreadedRenderer()) - fancy = false; - else if (qmlForceThreadedRenderer()) - fancy = true; - - // Enable fixed animation steps... - QByteArray fixed = qgetenv("QML_FIXED_ANIMATION_STEP"); - bool fixedAnimationSteps = bufferQueuing; - if (fixed == "no") - fixedAnimationSteps = false; - else if (fixed.length()) - fixedAnimationSteps = true; - if (fixedAnimationSteps) - QUnifiedTimer::instance(true)->setConsistentTiming(true); - - if (!s_instance) { - s_instance = fancy - ? (QQuickWindowManager*) new QQuickRenderThreadSingleContextWindowManager - : (QQuickWindowManager*) new QQuickTrivialWindowManager; - } - } - return s_instance; -} - -void QQuickWindowManager::setInstance(QQuickWindowManager *instance) -{ - Q_ASSERT(!s_instance); - s_instance = instance; -} - -QQuickTrivialWindowManager::QQuickTrivialWindowManager() - : gl(0) - , eventPending(false) -{ - sg = QSGContext::createDefaultContext(); -} - - -void QQuickTrivialWindowManager::show(QQuickWindow *window) -{ - WindowData data; - data.updatePending = false; - data.grabOnly = false; - m_windows[window] = data; - - maybeUpdate(window); -} - -void QQuickTrivialWindowManager::hide(QQuickWindow *window) -{ - if (!m_windows.contains(window)) - return; - - m_windows.remove(window); - QQuickWindowPrivate *cd = QQuickWindowPrivate::get(window); - cd->cleanupNodesOnShutdown(); - - if (m_windows.size() == 0) { - sg->invalidate(); - delete gl; - gl = 0; - } -} - -void QQuickTrivialWindowManager::windowDestroyed(QQuickWindow *window) -{ - hide(window); -} - -void QQuickTrivialWindowManager::renderWindow(QQuickWindow *window) -{ - bool renderWithoutShowing = QQuickWindowPrivate::get(window)->renderWithoutShowing; - if ((!window->isExposed() && !renderWithoutShowing) || !m_windows.contains(window)) - return; - - WindowData &data = const_cast<WindowData &>(m_windows[window]); - - QQuickWindow *masterWindow = 0; - if (!window->isVisible() && !renderWithoutShowing) { - // Find a "proper surface" to bind... - for (QHash<QQuickWindow *, WindowData>::const_iterator it = m_windows.constBegin(); - it != m_windows.constEnd() && !masterWindow; ++it) { - if (it.key()->isVisible()) - masterWindow = it.key(); - } - } else { - masterWindow = window; - } - - if (!masterWindow) - return; - - if (!QQuickWindowPrivate::get(masterWindow)->isRenderable()) { - qWarning().nospace() - << "Unable to find a renderable master window " - << masterWindow << "when trying to render" - << window << " (" << window->geometry() << ")."; - return; - } - - if (!gl) { - gl = new QOpenGLContext(); - gl->setFormat(masterWindow->requestedFormat()); - gl->create(); - if (!gl->makeCurrent(masterWindow)) - qWarning("QQuickWindow: makeCurrent() failed..."); - sg->initialize(gl); - } else { - gl->makeCurrent(masterWindow); - } - - bool alsoSwap = data.updatePending; - data.updatePending = false; - - QQuickWindowPrivate *cd = QQuickWindowPrivate::get(window); - cd->polishItems(); - - int renderTime = 0, syncTime = 0; - QTime renderTimer; - if (qquick_render_timing()) - renderTimer.start(); - - cd->syncSceneGraph(); - - if (qquick_render_timing()) - syncTime = renderTimer.elapsed(); - - cd->renderSceneGraph(window->size()); - - if (qquick_render_timing()) - renderTime = renderTimer.elapsed() - syncTime; - - if (data.grabOnly) { - grabContent = qt_gl_read_framebuffer(window->size(), false, false); - data.grabOnly = false; - } - - if (alsoSwap && window->isVisible()) { - gl->swapBuffers(window); - cd->fireFrameSwapped(); - } - - if (qquick_render_timing()) { - static QTime lastFrameTime = QTime::currentTime(); - const int swapTime = renderTimer.elapsed() - renderTime - syncTime; - qDebug() << "- Breakdown of frame time; sync:" << syncTime - << "ms render:" << renderTime << "ms swap:" << swapTime - << "ms total:" << swapTime + renderTime + syncTime - << "ms time since last frame:" << (lastFrameTime.msecsTo(QTime::currentTime())) - << "ms"; - lastFrameTime = QTime::currentTime(); - } - - // Might have been set during syncSceneGraph() - if (data.updatePending) - maybeUpdate(window); -} - -void QQuickTrivialWindowManager::exposureChanged(QQuickWindow *window) -{ - if (window->isExposed()) - maybeUpdate(window); -} - -QImage QQuickTrivialWindowManager::grab(QQuickWindow *window) -{ - if (!m_windows.contains(window)) - return QImage(); - - m_windows[window].grabOnly = true; - - renderWindow(window); - - QImage grabbed = grabContent; - grabContent = QImage(); - return grabbed; -} - - - -void QQuickTrivialWindowManager::resize(QQuickWindow *, const QSize &) -{ -} - - - -void QQuickTrivialWindowManager::maybeUpdate(QQuickWindow *window) -{ - if (!m_windows.contains(window)) - return; - - m_windows[window].updatePending = true; - - if (!eventPending) { - QCoreApplication::postEvent(this, new QEvent(QEvent::User)); - eventPending = true; - } -} - - - -QSGContext *QQuickTrivialWindowManager::sceneGraphContext() const -{ - return sg; -} - - -bool QQuickTrivialWindowManager::event(QEvent *e) -{ - if (e->type() == QEvent::User) { - eventPending = false; - for (QHash<QQuickWindow *, WindowData>::const_iterator it = m_windows.constBegin(); - it != m_windows.constEnd(); ++it) { - const WindowData &data = it.value(); - if (data.updatePending) - renderWindow(it.key()); - } - return true; - } - return QObject::event(e); -} - -#include "qquickwindowmanager.moc" - -QT_END_NAMESPACE diff --git a/src/quick/items/qquickwindowmanager_p.h b/src/quick/items/qquickwindowmanager_p.h deleted file mode 100644 index 94142a9d90..0000000000 --- a/src/quick/items/qquickwindowmanager_p.h +++ /dev/null @@ -1,87 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QQUICKWINDOWMANAGER_P_H -#define QQUICKWINDOWMANAGER_P_H - -#include <QtGui/QImage> -#include <private/qtquickglobal_p.h> - -QT_BEGIN_NAMESPACE - -class QQuickWindow; -class QSGContext; -class QAnimationDriver; - -class Q_QUICK_PRIVATE_EXPORT QQuickWindowManager -{ -public: - virtual ~QQuickWindowManager(); - - virtual void show(QQuickWindow *window) = 0; - virtual void hide(QQuickWindow *window) = 0; - - virtual void windowDestroyed(QQuickWindow *window) = 0; - - virtual void exposureChanged(QQuickWindow *window) = 0; - virtual QImage grab(QQuickWindow *window) = 0; - virtual void resize(QQuickWindow *window, const QSize &size) = 0; - - virtual void update(QQuickWindow *window) = 0; - virtual void maybeUpdate(QQuickWindow *window) = 0; - - virtual QAnimationDriver *animationDriver() const = 0; - - virtual QSGContext *sceneGraphContext() const = 0; - - virtual void releaseResources() = 0; - - // ### make this less of a singleton - static QQuickWindowManager *instance(); - static void setInstance(QQuickWindowManager *instance); - -private: - static QQuickWindowManager *s_instance; -}; - -QT_END_NAMESPACE - -#endif // QQUICKWINDOWMANAGER_P_H |