aboutsummaryrefslogtreecommitdiffstats
path: root/examples/quick/scenegraph/opengltextureinthread/threadrenderer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'examples/quick/scenegraph/opengltextureinthread/threadrenderer.cpp')
-rw-r--r--examples/quick/scenegraph/opengltextureinthread/threadrenderer.cpp302
1 files changed, 0 insertions, 302 deletions
diff --git a/examples/quick/scenegraph/opengltextureinthread/threadrenderer.cpp b/examples/quick/scenegraph/opengltextureinthread/threadrenderer.cpp
deleted file mode 100644
index 6f6ec467dc..0000000000
--- a/examples/quick/scenegraph/opengltextureinthread/threadrenderer.cpp
+++ /dev/null
@@ -1,302 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** 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 The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "threadrenderer.h"
-#include "logorenderer.h"
-
-#include <QtCore/QMutex>
-#include <QtCore/QThread>
-
-#include <QOpenGLContext>
-#include <QOpenGLFramebufferObject>
-#include <QtGui/QGuiApplication>
-#include <QtGui/QOffscreenSurface>
-
-#include <QtQuick/QQuickWindow>
-#include <qsgsimpletexturenode.h>
-
-QList<QThread *> ThreadRenderer::threads;
-
-/*
- * The render thread shares a context with the scene graph and will
- * render into two separate FBOs, one to use for display and one
- * to use for rendering
- */
-class RenderThread : public QThread
-{
- Q_OBJECT
-public:
- RenderThread(const QSize &size)
- : surface(nullptr)
- , context(nullptr)
- , m_renderFbo(nullptr)
- , m_displayFbo(nullptr)
- , m_logoRenderer(nullptr)
- , m_size(size)
- {
- ThreadRenderer::threads << this;
- }
-
- QOffscreenSurface *surface;
- QOpenGLContext *context;
-
-public slots:
- void renderNext()
- {
- context->makeCurrent(surface);
-
- if (!m_renderFbo) {
- // Initialize the buffers and renderer
- QOpenGLFramebufferObjectFormat format;
- format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
- m_renderFbo = new QOpenGLFramebufferObject(m_size, format);
- m_displayFbo = new QOpenGLFramebufferObject(m_size, format);
- m_logoRenderer = new LogoRenderer();
- m_logoRenderer->initialize();
- }
-
- m_renderFbo->bind();
- context->functions()->glViewport(0, 0, m_size.width(), m_size.height());
-
- m_logoRenderer->render();
-
- // We need to flush the contents to the FBO before posting
- // the texture to the other thread, otherwise, we might
- // get unexpected results.
- context->functions()->glFlush();
-
- m_renderFbo->bindDefault();
- qSwap(m_renderFbo, m_displayFbo);
-
- emit textureReady(m_displayFbo->texture(), m_size);
- }
-
- void shutDown()
- {
- context->makeCurrent(surface);
- delete m_renderFbo;
- delete m_displayFbo;
- delete m_logoRenderer;
- context->doneCurrent();
- delete context;
-
- // schedule this to be deleted only after we're done cleaning up
- surface->deleteLater();
-
- // Stop event processing, move the thread to GUI and make sure it is deleted.
- exit();
- moveToThread(QGuiApplication::instance()->thread());
- }
-
-signals:
- void textureReady(int id, const QSize &size);
-
-private:
- QOpenGLFramebufferObject *m_renderFbo;
- QOpenGLFramebufferObject *m_displayFbo;
-
- LogoRenderer *m_logoRenderer;
- QSize m_size;
-};
-
-
-
-class TextureNode : public QObject, public QSGSimpleTextureNode
-{
- Q_OBJECT
-
-public:
- TextureNode(QQuickWindow *window)
- : m_id(0)
- , m_size(0, 0)
- , m_texture(nullptr)
- , m_window(window)
- {
- // Our texture node must have a texture, so use the default 0 texture.
- GLuint id = 0;
- m_texture = m_window->createTextureFromNativeObject(QQuickWindow::NativeObjectTexture, id, 0, QSize(1, 1));
- setTexture(m_texture);
- setFiltering(QSGTexture::Linear);
- }
-
- ~TextureNode() override
- {
- delete m_texture;
- }
-
-signals:
- void textureInUse();
- void pendingNewTexture();
-
-public slots:
-
- // This function gets called on the FBO rendering thread and will store the
- // texture id and size and schedule an update on the window.
- void newTexture(int id, const QSize &size) {
- m_mutex.lock();
- m_id = id;
- m_size = size;
- m_mutex.unlock();
-
- // We cannot call QQuickWindow::update directly here, as this is only allowed
- // from the rendering thread or GUI thread.
- emit pendingNewTexture();
- }
-
-
- // Before the scene graph starts to render, we update to the pending texture
- void prepareNode() {
- m_mutex.lock();
- int newId = m_id;
- QSize size = m_size;
- m_id = 0;
- m_mutex.unlock();
- if (newId) {
- delete m_texture;
- // note: include QQuickWindow::TextureHasAlphaChannel if the rendered content
- // has alpha.
- m_texture = m_window->createTextureFromNativeObject(QQuickWindow::NativeObjectTexture, newId, 0, QSize(1, 1));
- setTexture(m_texture);
-
- markDirty(DirtyMaterial);
-
- // This will notify the rendering thread that the texture is now being rendered
- // and it can start rendering to the other one.
- emit textureInUse();
- }
- }
-
-private:
-
- int m_id;
- QSize m_size;
-
- QMutex m_mutex;
-
- QSGTexture *m_texture;
- QQuickWindow *m_window;
-};
-
-ThreadRenderer::ThreadRenderer()
- : m_renderThread(nullptr)
-{
- setFlag(ItemHasContents, true);
- m_renderThread = new RenderThread(QSize(512, 512));
-}
-
-void ThreadRenderer::ready()
-{
- m_renderThread->surface = new QOffscreenSurface();
- m_renderThread->surface->setFormat(m_renderThread->context->format());
- m_renderThread->surface->create();
-
- m_renderThread->moveToThread(m_renderThread);
-
- connect(window(), &QQuickWindow::sceneGraphInvalidated, m_renderThread, &RenderThread::shutDown, Qt::QueuedConnection);
-
- m_renderThread->start();
- update();
-}
-
-QSGNode *ThreadRenderer::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
-{
- TextureNode *node = static_cast<TextureNode *>(oldNode);
-
- if (!m_renderThread->context) {
- QOpenGLContext *current = window()->openglContext();
- // Some GL implementations requres that the currently bound context is
- // made non-current before we set up sharing, so we doneCurrent here
- // and makeCurrent down below while setting up our own context.
- current->doneCurrent();
-
- m_renderThread->context = new QOpenGLContext();
- m_renderThread->context->setFormat(current->format());
- m_renderThread->context->setShareContext(current);
- m_renderThread->context->create();
- m_renderThread->context->moveToThread(m_renderThread);
-
- current->makeCurrent(window());
-
- QMetaObject::invokeMethod(this, "ready");
- return nullptr;
- }
-
- if (!node) {
- node = new TextureNode(window());
-
- /* Set up connections to get the production of FBO textures in sync with vsync on the
- * rendering thread.
- *
- * When a new texture is ready on the rendering thread, we use a direct connection to
- * the texture node to let it know a new texture can be used. The node will then
- * emit pendingNewTexture which we bind to QQuickWindow::update to schedule a redraw.
- *
- * When the scene graph starts rendering the next frame, the prepareNode() function
- * is used to update the node with the new texture. Once it completes, it emits
- * textureInUse() which we connect to the FBO rendering thread's renderNext() to have
- * it start producing content into its current "back buffer".
- *
- * This FBO rendering pipeline is throttled by vsync on the scene graph rendering thread.
- */
- connect(m_renderThread, &RenderThread::textureReady, node, &TextureNode::newTexture, Qt::DirectConnection);
- connect(node, &TextureNode::pendingNewTexture, window(), &QQuickWindow::update, Qt::QueuedConnection);
- connect(window(), &QQuickWindow::beforeRendering, node, &TextureNode::prepareNode, Qt::DirectConnection);
- connect(node, &TextureNode::textureInUse, m_renderThread, &RenderThread::renderNext, Qt::QueuedConnection);
-
- // Get the production of FBO textures started..
- QMetaObject::invokeMethod(m_renderThread, "renderNext", Qt::QueuedConnection);
- }
-
- node->setRect(boundingRect());
-
- return node;
-}
-
-#include "threadrenderer.moc"