From 7eb24d68115619d8d78e6a427d5c723e5ffc15a5 Mon Sep 17 00:00:00 2001 From: Pasi Keranen Date: Mon, 17 Feb 2014 09:29:48 +0200 Subject: First step towards FXAA based antialiasing. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I40e767373156cf3e7f89c05767846a4949df319c Reviewed-by: Tomi Korpipää Reviewed-by: Miikka Heikkinen --- src/datavisualizationqml2/abstractdeclarative.cpp | 114 ++++++++++++++++----- src/datavisualizationqml2/abstractdeclarative_p.h | 24 +++-- .../datavisualizationqml2.pro | 6 +- .../declarativerendernode.cpp | 83 +++++++++++++++ .../declarativerendernode_p.h | 64 ++++++++++++ 5 files changed, 258 insertions(+), 33 deletions(-) create mode 100644 src/datavisualizationqml2/declarativerendernode.cpp create mode 100644 src/datavisualizationqml2/declarativerendernode_p.h (limited to 'src/datavisualizationqml2') diff --git a/src/datavisualizationqml2/abstractdeclarative.cpp b/src/datavisualizationqml2/abstractdeclarative.cpp index 2dc600c2..7415df9b 100644 --- a/src/datavisualizationqml2/abstractdeclarative.cpp +++ b/src/datavisualizationqml2/abstractdeclarative.cpp @@ -19,6 +19,7 @@ #include "abstractdeclarative_p.h" #include "qvalue3daxis.h" #include "declarativetheme_p.h" +#include "declarativerendernode_p.h" #include #include @@ -33,7 +34,9 @@ static QHash windowClearList; AbstractDeclarative::AbstractDeclarative(QQuickItem *parent) : QQuickItem(parent), m_controller(0), - m_clearWindowBeforeRendering(true) + m_renderMode(DirectToBackground), + m_node(0), + m_initialisedSize(0, 0) { connect(this, &QQuickItem::windowChanged, this, &AbstractDeclarative::handleWindowChanged); setAntialiasing(true); @@ -45,6 +48,68 @@ AbstractDeclarative::~AbstractDeclarative() checkWindowList(0); } +void AbstractDeclarative::setRenderingMode(AbstractDeclarative::RenderingMode mode) +{ + if (mode == m_renderMode) + return; + + m_renderMode = mode; + + switch (mode) { + case DirectToBackground: + // Intentional flowthrough + case DirectToBackground_NoClear: + // Delete render node + delete m_node; + m_node = 0; + m_initialisedSize = QSize(0, 0); + setAntialiasing(true); + setFlag(QQuickItem::ItemHasContents, false); + break; + case Indirect_NoAA: + // Force recreation of render node by resetting the initialized size + setAntialiasing(false); + m_initialisedSize = QSize(0, 0); + setFlag(QQuickItem::ItemHasContents, true); + break; + } + + updateWindowParameters(); + + emit renderingModeChanged(mode); +} + +AbstractDeclarative::RenderingMode AbstractDeclarative::renderingMode() const +{ + return m_renderMode; +} + +QSGNode *AbstractDeclarative::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) +{ + // If old node exists and has right size, reuse it. + if (oldNode && m_initialisedSize == boundingRect().size().toSize()) { + // Update bounding rectangle (that has same size as before). + DeclarativeRenderNode *renderNode = static_cast(oldNode); + renderNode->setRect(boundingRect()); + return oldNode; + } + + // Create a new render node when size changes or if there is no node yet + m_initialisedSize = boundingRect().size().toSize(); + + // Delete old node + if (oldNode) { + m_node = 0; + delete oldNode; + } + + // Create a new one and set its bounding rectangle + DeclarativeRenderNode *node = new DeclarativeRenderNode(window(), m_controller, m_renderMode, this); + node->setRect(boundingRect()); + m_node = node; + return node; +} + Declarative3DScene* AbstractDeclarative::scene() const { return static_cast(m_controller->scene()); @@ -65,19 +130,6 @@ void AbstractDeclarative::clearSelection() m_controller->clearSelection(); } -void AbstractDeclarative::setClearWindowBeforeRendering(bool enable) -{ - if (m_clearWindowBeforeRendering != enable) { - m_clearWindowBeforeRendering = enable; - emit clearWindowBeforeRenderingChanged(enable); - } -} - -bool AbstractDeclarative::clearWindowBeforeRendering() const -{ - return m_clearWindowBeforeRendering; -} - void AbstractDeclarative::setSelectionMode(SelectionFlags mode) { int intmode = int(mode); @@ -130,7 +182,7 @@ void AbstractDeclarative::setSharedController(Abstract3DController *controller) void AbstractDeclarative::synchDataToRenderer() { - if (m_clearWindowBeforeRendering && clearList.size()) + if (m_renderMode == DirectToBackground && clearList.size()) clearList.clear(); m_controller->initializeOpenGL(); m_controller->synchDataToRenderer(); @@ -143,12 +195,14 @@ void AbstractDeclarative::handleWindowChanged(QQuickWindow *window) if (!window) return; - connect(window, &QQuickWindow::beforeSynchronizing, this, - &AbstractDeclarative::synchDataToRenderer, Qt::DirectConnection); - connect(window, &QQuickWindow::beforeRendering, this, - &AbstractDeclarative::render, Qt::DirectConnection); - connect(m_controller.data(), &Abstract3DController::needRender, window, - &QQuickWindow::update); + connect(window, &QQuickWindow::beforeSynchronizing, + this, &AbstractDeclarative::synchDataToRenderer, + Qt::DirectConnection); + connect(window, &QQuickWindow::beforeRendering, + this, &AbstractDeclarative::render, + Qt::DirectConnection); + connect(m_controller.data(), &Abstract3DController::needRender, + window, &QQuickWindow::update); updateWindowParameters(); } @@ -184,9 +238,15 @@ void AbstractDeclarative::updateWindowParameters() win->update(); } - QPointF point = QQuickItem::mapToScene(QPointF(0.0f, 0.0f)); - scene->d_ptr->setViewport(QRect(point.x(), point.y(), m_cachedGeometry.width(), - m_cachedGeometry.height())); + if (m_renderMode == DirectToBackground || m_renderMode == DirectToBackground_NoClear) { + // Origo mapping is needed when rendering directly to background + QPointF point = QQuickItem::mapToScene(QPointF(0.0f, 0.0f)); + scene->d_ptr->setViewport(QRect(point.x(), point.y(), m_cachedGeometry.width(), + m_cachedGeometry.height())); + } else { + // No translation needed when rendering to FBO + scene->d_ptr->setViewport(m_cachedGeometry.toRect()); + } } } @@ -205,9 +265,13 @@ void AbstractDeclarative::render() { updateWindowParameters(); + // If we're not rendering directly to the background, return + if (m_renderMode != DirectToBackground && m_renderMode != DirectToBackground_NoClear) + return; + // Clear the background once per window as that is not done by default const QQuickWindow *win = window(); - if (m_clearWindowBeforeRendering && !clearList.contains(win)) { + if (m_renderMode == DirectToBackground && !clearList.contains(win)) { clearList.append(win); QColor clearColor = win->color(); glClearColor(clearColor.redF(), clearColor.greenF(), clearColor.blueF(), 1.0f); diff --git a/src/datavisualizationqml2/abstractdeclarative_p.h b/src/datavisualizationqml2/abstractdeclarative_p.h index 16effca0..83a1bbdb 100644 --- a/src/datavisualizationqml2/abstractdeclarative_p.h +++ b/src/datavisualizationqml2/abstractdeclarative_p.h @@ -42,17 +42,20 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION +class DeclarativeRenderNode; + class AbstractDeclarative : public QQuickItem { Q_OBJECT Q_ENUMS(ShadowQuality) + Q_ENUMS(RenderingMode) Q_FLAGS(SelectionFlag SelectionFlags) Q_PROPERTY(SelectionFlags selectionMode READ selectionMode WRITE setSelectionMode NOTIFY selectionModeChanged) Q_PROPERTY(ShadowQuality shadowQuality READ shadowQuality WRITE setShadowQuality NOTIFY shadowQualityChanged) Q_PROPERTY(Declarative3DScene* scene READ scene NOTIFY sceneChanged) Q_PROPERTY(QAbstract3DInputHandler* inputHandler READ inputHandler WRITE setInputHandler NOTIFY inputHandlerChanged) Q_PROPERTY(Q3DTheme* theme READ theme WRITE setTheme NOTIFY themeChanged) - Q_PROPERTY(bool clearWindowBeforeRendering READ clearWindowBeforeRendering WRITE setClearWindowBeforeRendering NOTIFY clearWindowBeforeRenderingChanged) + Q_PROPERTY(RenderingMode renderingMode READ renderingMode WRITE setRenderingMode NOTIFY renderingModeChanged) public: enum SelectionFlag { @@ -79,10 +82,19 @@ public: ShadowQualitySoftHigh }; + enum RenderingMode { + DirectToBackground = 0, + DirectToBackground_NoClear, + Indirect_NoAA + }; + public: explicit AbstractDeclarative(QQuickItem *parent = 0); virtual ~AbstractDeclarative(); + virtual void setRenderingMode(RenderingMode mode); + virtual AbstractDeclarative::RenderingMode renderingMode() const; + virtual void setSelectionMode(SelectionFlags mode); virtual AbstractDeclarative::SelectionFlags selectionMode() const; @@ -99,9 +111,6 @@ public: Q_INVOKABLE virtual void clearSelection(); - virtual void setClearWindowBeforeRendering(bool enable); - virtual bool clearWindowBeforeRendering() const; - virtual void geometryChanged(const QRectF & newGeometry, const QRectF & oldGeometry); void setSharedController(Abstract3DController *controller); @@ -128,6 +137,7 @@ protected: virtual void updateWindowParameters(); virtual void handleSelectionModeChange(QAbstract3DGraph::SelectionFlags mode); virtual void handleShadowQualityChange(QAbstract3DGraph::ShadowQuality quality); + virtual QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *); signals: void selectionModeChanged(SelectionFlags mode); @@ -135,12 +145,14 @@ signals: void sceneChanged(Q3DScene *scene); void inputHandlerChanged(QAbstract3DInputHandler *inputHandler); void themeChanged(Q3DTheme *theme); - void clearWindowBeforeRenderingChanged(bool enable); + void renderingModeChanged(RenderingMode mode); private: QPointer m_controller; QRectF m_cachedGeometry; - bool m_clearWindowBeforeRendering; + AbstractDeclarative::RenderingMode m_renderMode; + DeclarativeRenderNode *m_node; + QSize m_initialisedSize; }; Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractDeclarative::SelectionFlags) diff --git a/src/datavisualizationqml2/datavisualizationqml2.pro b/src/datavisualizationqml2/datavisualizationqml2.pro index d6e8570c..254fefde 100644 --- a/src/datavisualizationqml2/datavisualizationqml2.pro +++ b/src/datavisualizationqml2/datavisualizationqml2.pro @@ -25,7 +25,8 @@ SOURCES += \ declarativeseries.cpp \ declarativetheme.cpp \ declarativecolor.cpp \ - declarativescene.cpp + declarativescene.cpp \ + declarativerendernode.cpp HEADERS += \ datavisualizationqml2_plugin.h \ @@ -37,7 +38,8 @@ HEADERS += \ declarativeseries_p.h \ declarativetheme_p.h \ declarativecolor_p.h \ - declarativescene_p.h + declarativescene_p.h \ + declarativerendernode_p.h OTHER_FILES = qmldir diff --git a/src/datavisualizationqml2/declarativerendernode.cpp b/src/datavisualizationqml2/declarativerendernode.cpp new file mode 100644 index 00000000..612d11df --- /dev/null +++ b/src/datavisualizationqml2/declarativerendernode.cpp @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "declarativerendernode_p.h" +#include +#include + +QT_BEGIN_NAMESPACE_DATAVISUALIZATION + +DeclarativeRenderNode::DeclarativeRenderNode(QQuickWindow *window, Abstract3DController *controller, AbstractDeclarative::RenderingMode mode, QObject *parent) + : QObject(parent), + m_fbo(0), + m_texture(0), + m_window(window), + m_controller(controller), + m_mode(mode) +{ + connect(window, &QQuickWindow::beforeRendering, + this, &DeclarativeRenderNode::renderFBO, + Qt::DirectConnection); +} + +DeclarativeRenderNode::~DeclarativeRenderNode() +{ + delete m_texture; + delete m_fbo; +} + +void DeclarativeRenderNode::renderFBO() +{ + QSize size = rect().size().toSize(); + + // Create FBO + if (!m_fbo) { + QOpenGLFramebufferObjectFormat format; + format.setAttachment(QOpenGLFramebufferObject::Depth); + m_fbo = new QOpenGLFramebufferObject(size, format); + m_texture = m_window->createTextureFromId(m_fbo->texture(), size); + + setTexture(m_texture); + + // Flip texture + QSize ts = m_texture->textureSize(); + QRectF sourceRect(0, 0, ts.width(), ts.height()); + float tmp = sourceRect.top(); + sourceRect.setTop(sourceRect.bottom()); + sourceRect.setBottom(tmp); + QSGGeometry *geometry = this->geometry(); + QSGGeometry::updateTexturedRectGeometry(geometry, rect(), + m_texture->convertToNormalizedSourceRect(sourceRect)); + markDirty(DirtyMaterial); + } + + // Call the shared rendering function + m_fbo->bind(); + glDisable(GL_BLEND); + + m_controller->render(m_fbo->handle()); + + glEnable(GL_BLEND); + + m_fbo->release(); + + // New view is in the FBO, request repaint of scene graph + m_window->update(); +} + +QT_END_NAMESPACE_DATAVISUALIZATION diff --git a/src/datavisualizationqml2/declarativerendernode_p.h b/src/datavisualizationqml2/declarativerendernode_p.h new file mode 100644 index 00000000..b8250512 --- /dev/null +++ b/src/datavisualizationqml2/declarativerendernode_p.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVis3D module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVis3D API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef DECLARATIVERENDERNODE_P_H +#define DECLARATIVERENDERNODE_P_H + +#include +#include "datavisualizationglobal_p.h" +#include "abstract3dcontroller_p.h" +#include "abstractdeclarative_p.h" +#include + +class QOpenGLFramebufferObject; +class QSGTexture; +class QQuickWindow; + +QT_BEGIN_NAMESPACE_DATAVISUALIZATION + +class DeclarativeRenderNode : public QObject, public QSGSimpleTextureNode +{ + Q_OBJECT +public: + explicit DeclarativeRenderNode(QQuickWindow *window, Abstract3DController *controller, AbstractDeclarative::RenderingMode mode, QObject *parent = 0); + virtual ~DeclarativeRenderNode(); + + // Renders view to FBO before render cycle starts. + void renderFBO(); + +private: + QOpenGLFramebufferObject *m_fbo; + QSGTexture *m_texture; + QQuickWindow *m_window; + QPointer m_controller; + AbstractDeclarative::RenderingMode m_mode; +}; + +QT_END_NAMESPACE_DATAVISUALIZATION + +#endif // DECLARATIVERENDERNODE_P_H -- cgit v1.2.3