summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSvenn-Arne Dragly <s@dragly.com>2018-10-15 19:21:34 +0200
committerAndy Nichols <andy.nichols@qt.io>2018-10-16 07:19:05 +0000
commit7f75012d2efd597605eb031660d8929c6a3bcb04 (patch)
tree48df9930c38b7b23d99a79d87fcb9209cf53f61c
parent39e41cedc7cca3bf951177d9afb6e5960a981280 (diff)
Add support for the Dragon render aspect in Studio3D
The Dragon render aspect can be enabled by setting dragonRenderAspectEnabled: true on a Presentation item. Change-Id: Ic21b5493d1bdfc4a1de9ff4a4ad643b2ad72c7ed Reviewed-by: Andy Nichols <andy.nichols@qt.io>
-rw-r--r--src/imports/studio3d/q3dsstudio3ditem.cpp3
-rw-r--r--src/imports/studio3d/q3dsstudio3drenderer.cpp29
-rw-r--r--src/imports/studio3d/q3dsstudio3drenderer_p.h7
-rw-r--r--src/runtime/api/q3dspresentation.cpp35
-rw-r--r--src/runtime/api/q3dspresentation.h5
-rw-r--r--src/runtime/api/q3dspresentation_p.h4
-rw-r--r--src/runtime/dragon/dragonactivatedsurface.cpp10
-rw-r--r--src/runtime/dragon/dragonactivatedsurface_p.h5
-rw-r--r--src/runtime/dragon/dragonrenderer.cpp57
-rw-r--r--src/runtime/dragon/dragonrenderer_p.h16
-rw-r--r--src/runtime/dragon/qdragonrenderaspect.cpp14
-rw-r--r--src/runtime/dragon/qdragonrenderaspect_p.h5
-rw-r--r--src/runtime/q3dsengine.cpp2
13 files changed, 152 insertions, 40 deletions
diff --git a/src/imports/studio3d/q3dsstudio3ditem.cpp b/src/imports/studio3d/q3dsstudio3ditem.cpp
index 25a4d8c..381b88a 100644
--- a/src/imports/studio3d/q3dsstudio3ditem.cpp
+++ b/src/imports/studio3d/q3dsstudio3ditem.cpp
@@ -427,6 +427,9 @@ void Q3DSStudio3DItem::createEngine()
if (m_sourceFlags.testFlag(Q3DSPresentationController::Profiling))
flags |= Q3DSEngine::EnableProfiling;
+ if (m_sourceFlags.testFlag(Q3DSPresentationController::AwakenTheDragon))
+ flags |= Q3DSEngine::AwakenTheDragon;
+
m_engine->setFlags(flags);
m_engine->setAutoToggleProfileUi(false); // up to the app to control this via the API instead
diff --git a/src/imports/studio3d/q3dsstudio3drenderer.cpp b/src/imports/studio3d/q3dsstudio3drenderer.cpp
index 7ea2163..d0d1399 100644
--- a/src/imports/studio3d/q3dsstudio3drenderer.cpp
+++ b/src/imports/studio3d/q3dsstudio3drenderer.cpp
@@ -33,6 +33,7 @@
#include <private/q3dslayer3dsgnode_p.h>
#include <private/q3dsengine_p.h>
#include <private/q3dslogging_p.h>
+#include <private/qdragonrenderaspect_p.h>
#include <QQuickWindow>
#include <QOpenGLContext>
#include <QGuiApplication>
@@ -87,10 +88,16 @@ Q3DSStudio3DRenderer::Q3DSStudio3DRenderer(Q3DSStudio3DItem *item, Q3DSLayer3DSG
this, &Q3DSStudio3DRenderer::renderOffscreen, Qt::DirectConnection);
ContextSaver saver;
- m_renderAspect = new Qt3DRender::QRenderAspect(Qt3DRender::QRenderAspect::Synchronous);
- m_aspectEngine->registerAspect(m_renderAspect);
- m_renderAspectD = static_cast<Qt3DRender::QRenderAspectPrivate *>(Qt3DRender::QRenderAspectPrivate::get(m_renderAspect));
- m_renderAspectD->renderInitialize(ctx);
+ if (m_item->engine()->flags().testFlag(Q3DSEngine::AwakenTheDragon)) {
+ m_dragonRenderAspect = new Qt3DRender::Dragon::QDragonRenderAspect(Qt3DRender::Dragon::Renderer::Synchronous);
+ m_dragonRenderAspect->initialize(ctx);
+ m_aspectEngine->registerAspect(m_dragonRenderAspect);
+ } else {
+ m_renderAspect = new Qt3DRender::QRenderAspect(Qt3DRender::QRenderAspect::Synchronous);
+ m_aspectEngine->registerAspect(m_renderAspect);
+ m_renderAspectD = static_cast<Qt3DRender::QRenderAspectPrivate *>(Qt3DRender::QRenderAspectPrivate::get(m_renderAspect));
+ m_renderAspectD->renderInitialize(ctx);
+ }
QMetaObject::invokeMethod(m_item, "startEngine");
@@ -102,7 +109,9 @@ Q3DSStudio3DRenderer::~Q3DSStudio3DRenderer()
{
qCDebug(lcStudio3D, "[R] renderer %p dtor", this);
ContextSaver saver;
- m_renderAspectD->renderShutdown();
+
+ if (m_item->engine()->flags().testFlag(Q3DSEngine::AwakenTheDragon))
+ m_renderAspectD->renderShutdown();
}
void Q3DSStudio3DRenderer::invalidateItem()
@@ -148,7 +157,12 @@ void Q3DSStudio3DRenderer::renderOffscreen()
ContextSaver saver;
w->resetOpenGLState();
m_fbo->bind();
- m_renderAspectD->renderSynchronous();
+
+ if (m_item->engine()->flags().testFlag(Q3DSEngine::AwakenTheDragon))
+ m_currentFrame = m_dragonRenderAspect->renderSynchronous(std::move(m_currentFrame));
+ else
+ m_renderAspectD->renderSynchronous();
+
if (saver.context()->surface() != saver.surface())
saver.context()->makeCurrent(saver.surface());
w->resetOpenGLState();
@@ -156,6 +170,9 @@ void Q3DSStudio3DRenderer::renderOffscreen()
if (m_node) {
m_node->markDirty(QSGNode::DirtyMaterial);
} else {
+ if (m_item->engine()->flags().testFlag(Q3DSEngine::AwakenTheDragon))
+ qFatal("View3D is not yet supported in the Dragon render aspect.");
+
QSharedPointer<Qt3DRender::Render::ResourceAccessor> ra = m_renderAspectD->m_renderer->nodeManagers()->resourceAccessor();
if (ra) {
for (auto vd : m_viewDesc) {
diff --git a/src/imports/studio3d/q3dsstudio3drenderer_p.h b/src/imports/studio3d/q3dsstudio3drenderer_p.h
index e2c1ce1..6508be7 100644
--- a/src/imports/studio3d/q3dsstudio3drenderer_p.h
+++ b/src/imports/studio3d/q3dsstudio3drenderer_p.h
@@ -46,6 +46,7 @@
#include <QElapsedTimer>
#include <QOpenGLFramebufferObject>
#include <QSGTexture>
+#include <private/dragonrenderer_p.h>
#include "q3dsstudio3dviewdesc_p.h"
QT_BEGIN_NAMESPACE
@@ -61,6 +62,9 @@ class QAspectEngine;
namespace Qt3DRender {
class QRenderAspect;
class QRenderAspectPrivate;
+namespace Dragon {
+class QDragonRenderAspect;
+}
}
class Q3DSStudio3DRenderer : public QObject
@@ -92,6 +96,7 @@ private:
Qt3DCore::QAspectEngine *m_aspectEngine;
Qt3DRender::QRenderAspect *m_renderAspect = nullptr;
Qt3DRender::QRenderAspectPrivate *m_renderAspectD = nullptr;
+ Qt3DRender::Dragon::QDragonRenderAspect *m_dragonRenderAspect = nullptr;
QScopedPointer<QSGTexture> m_texture;
QScopedPointer<QOpenGLFramebufferObject> m_fbo;
@@ -100,6 +105,8 @@ private:
QVector<Q3DSStudio3DViewDesc> m_viewDesc;
QElapsedTimer m_renderTimer;
bool m_usingRenderThread;
+
+ Qt3DRender::Dragon::Renderer::Frame m_currentFrame;
};
QT_END_NAMESPACE
diff --git a/src/runtime/api/q3dspresentation.cpp b/src/runtime/api/q3dspresentation.cpp
index 6c502e1..3a8e37e 100644
--- a/src/runtime/api/q3dspresentation.cpp
+++ b/src/runtime/api/q3dspresentation.cpp
@@ -169,6 +169,38 @@ void Q3DSPresentation::setProfilingEnabled(bool enable)
}
/*!
+ \property Q3DSPresentation::dragonRenderAspectEnabled
+
+ When enabled, the new, experimental Qt3D render aspect
+ (codenamed "Dragon") is enabled.
+ This render aspect will replace the original render aspect
+ in a future release.
+ This property will be deprecated once the aspect has been
+ replaced.
+
+ The default value is \c false.
+
+ \note Changing the value after the presentation has been loaded
+ has no effect for the already loaded presentation. Therefore the
+ changing of this property must happen before calling setSource().
+*/
+bool Q3DSPresentation::isDragonRenderAspectEnabled() const
+{
+ Q_D(const Q3DSPresentation);
+ return d->dragonRenderAspectEnabled;
+}
+
+void Q3DSPresentation::setDragonRenderAspectEnabled(bool dragonRenderAspectEnabled)
+{
+ Q_D(Q3DSPresentation);
+ if (d->dragonRenderAspectEnabled == dragonRenderAspectEnabled)
+ return;
+
+ d->dragonRenderAspectEnabled = dragonRenderAspectEnabled;
+ emit dragonRenderAspectEnabledChanged();
+}
+
+/*!
\property Q3DSPresentation::profileUiVisible
When this property is \c{true}, the interactive statistics and profile
@@ -616,6 +648,9 @@ Q3DSPresentationController::SourceFlags Q3DSPresentationPrivate::sourceFlags() c
if (profiling)
flags |= Q3DSPresentationController::Profiling;
+ if (dragonRenderAspectEnabled)
+ flags |= Q3DSPresentationController::AwakenTheDragon;
+
return flags;
}
diff --git a/src/runtime/api/q3dspresentation.h b/src/runtime/api/q3dspresentation.h
index 085ce89..898eef8 100644
--- a/src/runtime/api/q3dspresentation.h
+++ b/src/runtime/api/q3dspresentation.h
@@ -56,6 +56,7 @@ class Q3DSV_EXPORT Q3DSPresentation : public QObject
Q_PROPERTY(bool profilingEnabled READ isProfilingEnabled WRITE setProfilingEnabled NOTIFY profilingEnabledChanged)
Q_PROPERTY(bool profileUiVisible READ isProfileUiVisible WRITE setProfileUiVisible NOTIFY profileUiVisibleChanged)
Q_PROPERTY(float profileUiScale READ profileUiScale WRITE setProfileUiScale NOTIFY profileUiScaleChanged)
+ Q_PROPERTY(bool dragonRenderAspectEnabled READ isDragonRenderAspectEnabled WRITE setDragonRenderAspectEnabled NOTIFY dragonRenderAspectEnabledChanged)
public:
explicit Q3DSPresentation(QObject *parent = nullptr);
@@ -73,6 +74,9 @@ public:
float profileUiScale() const;
void setProfileUiScale(float scale);
+ bool isDragonRenderAspectEnabled() const;
+ void setDragonRenderAspectEnabled(bool dragonRenderAspectEnabled);
+
Q_INVOKABLE void reload();
Q_INVOKABLE void setDataInputValue(const QString &name, const QVariant &value);
@@ -109,6 +113,7 @@ Q_SIGNALS:
void customSignalEmitted(const QString &elementPath, const QString &name);
void slideEntered(const QString &elementPath, int index, const QString &name);
void slideExited(const QString &elementPath, int index, const QString &name);
+ void dragonRenderAspectEnabledChanged();
protected:
Q3DSPresentation(Q3DSPresentationPrivate &dd, QObject *parent);
diff --git a/src/runtime/api/q3dspresentation_p.h b/src/runtime/api/q3dspresentation_p.h
index b056c0c..63c0f9a 100644
--- a/src/runtime/api/q3dspresentation_p.h
+++ b/src/runtime/api/q3dspresentation_p.h
@@ -59,7 +59,8 @@ public:
void initializePresentationController(Q3DSEngine *engine, Q3DSPresentation *presentation);
enum SourceFlag {
- Profiling = 0x01
+ Profiling = 0x01,
+ AwakenTheDragon = 0x02
};
Q_DECLARE_FLAGS(SourceFlags, SourceFlag)
@@ -119,6 +120,7 @@ public:
bool profileUiVisible = false;
float profileUiScale = 1.0f;
QVector<Q3DSInlineQmlSubPresentation *> inlineQmlSubPresentations;
+ bool dragonRenderAspectEnabled = false;
};
QT_END_NAMESPACE
diff --git a/src/runtime/dragon/dragonactivatedsurface.cpp b/src/runtime/dragon/dragonactivatedsurface.cpp
index 2657be9..e485759 100644
--- a/src/runtime/dragon/dragonactivatedsurface.cpp
+++ b/src/runtime/dragon/dragonactivatedsurface.cpp
@@ -420,9 +420,9 @@ void ActivatedSurface::applyUniform(const ShaderUniform &description, const Unif
}
}
-DrawContext ActivatedSurface::beginDrawing()
+DrawContext ActivatedSurface::beginDrawing(bool autoSwapBuffers)
{
- return DrawContext(m_glContext, m_surface);
+ return DrawContext(m_glContext, m_surface, autoSwapBuffers);
}
UniformValue standardUniformValue(StandardUniform standardUniformType,
@@ -1661,14 +1661,16 @@ void ActivatedSurface::blitFramebuffer(const BlitFramebufferInfo &blitFramebuffe
}
}
-DrawContext::DrawContext(QOpenGLContext *openGLContext, QSurface *surface)
+DrawContext::DrawContext(QOpenGLContext *openGLContext, QSurface *surface, bool autoSwapBuffers)
: m_openGLContext(openGLContext)
, m_surface(surface)
+ , m_autoSwapBuffers(autoSwapBuffers)
{ }
DrawContext::~DrawContext()
{
- m_openGLContext->swapBuffers(m_surface);
+ if (m_autoSwapBuffers)
+ m_openGLContext->swapBuffers(m_surface);
}
#define QT3D_DRAGON_UNIFORM_TYPE_IMPL(UniformTypeEnum, BaseType, Func) \
diff --git a/src/runtime/dragon/dragonactivatedsurface_p.h b/src/runtime/dragon/dragonactivatedsurface_p.h
index 65e8fe0..dbccf57 100644
--- a/src/runtime/dragon/dragonactivatedsurface_p.h
+++ b/src/runtime/dragon/dragonactivatedsurface_p.h
@@ -89,9 +89,10 @@ class DrawContext
public:
~DrawContext();
private:
- DrawContext(QOpenGLContext *openGLContext, QSurface *surface);
+ DrawContext(QOpenGLContext *openGLContext, QSurface *surface, bool autoSwapBuffers);
QOpenGLContext *m_openGLContext = nullptr;
QSurface *m_surface = nullptr;
+ bool m_autoSwapBuffers = true;
friend class ActivatedSurface;
};
@@ -160,7 +161,7 @@ public:
// Parameter/uniform functions
void applyUniform(const ShaderUniform &description, const UniformValue &v);
- DrawContext beginDrawing();
+ DrawContext beginDrawing(bool autoSwapBuffers);
void blitFramebuffer(const BlitFramebufferInfo &blitFramebufferInfo, uint defaultFboId, const MutableContainer<GLTexture> &glTextures);
private:
diff --git a/src/runtime/dragon/dragonrenderer.cpp b/src/runtime/dragon/dragonrenderer.cpp
index afd0089..175534c 100644
--- a/src/runtime/dragon/dragonrenderer.cpp
+++ b/src/runtime/dragon/dragonrenderer.cpp
@@ -132,10 +132,11 @@ a Renderer for each backend.
*/
-Renderer::Renderer()
+Renderer::Renderer(RenderType renderType)
: nextFrameSemaphore(1)
- , m_renderThread(new RenderThread(this))
+ , m_renderThread(renderType == Threaded ? new RenderThread(this) : nullptr)
, m_running(1)
+ , m_renderType(renderType)
{
if (m_renderThread)
m_renderThread->waitForStart();
@@ -160,20 +161,31 @@ Renderer::~Renderer()
m_renderThread->wait();
}
m_offscreenHelper->deleteLater();
+ if (m_ownedContext)
+ m_glContext->deleteLater();
}
-void Renderer::initialize()
+/*!
+ * \internal
+ * \brief Renderer::initialize
+ *
+ * If a context is provided to this function, it will be used for rendering,
+ * which is the case for Studio3D and Scene3D items.
+ */
+void Renderer::initialize(QOpenGLContext *context)
{
- // TODO don't forget to delete this
- m_glContext = new QOpenGLContext;
- m_glContext->setShareContext(qt_gl_global_share_context());
- m_glContext->create();
- // if (m_glContext->create())
- // qCDebug(Render::Backend) << "OpenGL context created with actual format"
- // << m_glContext->format();
- // else
- // qCWarning(Render::Backend) << Q_FUNC_INFO << "OpenGL context creation failed";
- m_ownedContext = true;
+ if (context != nullptr) {
+ m_glContext = context;
+ } else {
+ m_glContext = new QOpenGLContext;
+ m_glContext->setShareContext(qt_gl_global_share_context());
+
+ if (!m_glContext->create())
+ qWarning() << Q_FUNC_INFO << "OpenGL context creation failed";
+
+ m_ownedContext = true;
+ }
+
if (!m_glContext->shareContext()) {
// TODO don't forget to delete this
m_shareContext = new QOpenGLContext;
@@ -367,6 +379,8 @@ Renderer::Frame Renderer::doRender(Renderer::Frame frame)
continue;
}
+ const GLuint fboBeforeRender = activeSurface.glHelper()->boundFrameBufferObject();
+
// We only need to do preparations such as uploading textures for one surface
if (!preparationsComplete) {
{
@@ -483,6 +497,12 @@ Renderer::Frame Renderer::doRender(Renderer::Frame frame)
}
}
+ {
+ GLRenderTarget renderTarget;
+ renderTarget.frameBufferObjectId = fboBeforeRender;
+ frame.createdRenderTargets[QNodeId()] = renderTarget;
+ }
+
// Create render target
if (!view->renderTargetId.isNull()) {
auto defaultFBO = m_glContext->defaultFramebufferObject();
@@ -491,7 +511,8 @@ Renderer::Frame Renderer::doRender(Renderer::Frame frame)
auto lastBoundFBOId = activeSurface.glHelper()->boundFrameBufferObject();
const auto &renderTargetNodeId = view->renderTargetId;
const auto &attachments = view->attachmentPack;
- if (!frame.createdRenderTargets.contains(view->renderTargetId)) {
+
+ if (!frame.createdRenderTargets.contains(renderTargetNodeId)) {
GLRenderTarget renderTarget;
if (defaultFBO != 0 && lastBoundFBOId == defaultFBO) {
// this is the default fbo that some platforms create (iOS),
@@ -558,7 +579,9 @@ Renderer::Frame Renderer::doRender(Renderer::Frame frame)
if (!preparationsComplete)
return frame;
- DrawContext drawContext = activeSurface.beginDrawing();
+ // TODO might be better to just have to call swapBuffers manually
+ bool autoSwapBuffers = m_renderType == RenderType::Threaded;
+ DrawContext drawContext = activeSurface.beginDrawing(autoSwapBuffers);
// TODO consider what m_ownCurrent was used for in SubmissionContext
@@ -592,9 +615,7 @@ Renderer::Frame Renderer::doRender(Renderer::Frame frame)
// TODO handle render state set
// TODO consider having this function return a render target that is passed to the following functions
- activeSurface.activateRenderTarget(frame.createdRenderTargets[view->renderTargetId]
- .frameBufferObjectId,
- view->attachmentPack);
+ activeSurface.activateRenderTarget(frame.createdRenderTargets[view->renderTargetId].frameBufferObjectId, view->attachmentPack);
activeSurface.clearBackBuffer(view->clearBackBufferInfo);
// TODO make it return a viewport, used by other functions that need one
diff --git a/src/runtime/dragon/dragonrenderer_p.h b/src/runtime/dragon/dragonrenderer_p.h
index dc8f627..c040819 100644
--- a/src/runtime/dragon/dragonrenderer_p.h
+++ b/src/runtime/dragon/dragonrenderer_p.h
@@ -134,7 +134,7 @@ struct GLRenderTarget
class Renderer
{
-private:
+public:
/*!
* \brief The Frame struct holds data that is shared across frames,
* such as already uploaded textures and active textures.
@@ -152,8 +152,14 @@ private:
int number = 0;
};
-public:
- Renderer();
+ // TODO a cleaner option is to move all thread-specific code into a separate class
+ // instead of letting one class handle both cases
+ enum RenderType {
+ Synchronous,
+ Threaded
+ };
+
+ Renderer(RenderType renderType);
~Renderer();
void render();
@@ -163,7 +169,7 @@ public:
void addLatestData(FrameInput data);
GraphicsApiFilterData contextInfo(RenderViews views);
- void initialize();
+ void initialize(QOpenGLContext *context = nullptr);
QSemaphore nextFrameSemaphore;
@@ -206,6 +212,8 @@ private:
OffscreenSurfaceHelper *m_offscreenHelper;
+ RenderType m_renderType;
+
// // Shaders
// Render::ShaderCache *m_shaderCache = nullptr;
diff --git a/src/runtime/dragon/qdragonrenderaspect.cpp b/src/runtime/dragon/qdragonrenderaspect.cpp
index 3427068..f82c1f5 100644
--- a/src/runtime/dragon/qdragonrenderaspect.cpp
+++ b/src/runtime/dragon/qdragonrenderaspect.cpp
@@ -187,8 +187,8 @@ QT_BEGIN_NAMESPACE
namespace Qt3DRender {
namespace Dragon {
-QDragonRenderAspect::QDragonRenderAspect()
- : m_renderer(new Renderer())
+QDragonRenderAspect::QDragonRenderAspect(Renderer::RenderType renderType)
+ : m_renderer(new Renderer(renderType))
{
registerBackendType<Qt3DCore::QEntity>(m_entities);
registerBackendType<Qt3DCore::QTransform>(m_transforms);
@@ -512,6 +512,16 @@ QVector<Qt3DCore::QAspectJobPtr> QDragonRenderAspect::jobsToExecute(qint64 time)
return m_jobs;
}
+Renderer::Frame QDragonRenderAspect::renderSynchronous(Renderer::Frame frame)
+{
+ return m_renderer->doRender(std::move(frame));
+}
+
+void QDragonRenderAspect::initialize(QOpenGLContext *context)
+{
+ m_renderer->initialize(context);
+}
+
} // namespace Dragon
} // namespace Qt3DRender
QT_END_NAMESPACE
diff --git a/src/runtime/dragon/qdragonrenderaspect_p.h b/src/runtime/dragon/qdragonrenderaspect_p.h
index d60f759..32cb559 100644
--- a/src/runtime/dragon/qdragonrenderaspect_p.h
+++ b/src/runtime/dragon/qdragonrenderaspect_p.h
@@ -114,9 +114,10 @@ class Q3DSV_EXPORT QDragonRenderAspect : public Qt3DCore::QAbstractAspect
{
Q_OBJECT
public:
- QDragonRenderAspect();
+ QDragonRenderAspect(Renderer::RenderType renderType);
+ Renderer::Frame renderSynchronous(Renderer::Frame frame);
+ void initialize(QOpenGLContext *context);
- // QAbstractAspect interface
private:
QVector<Qt3DCore::QAspectJobPtr> jobsToExecute(qint64 time) override;
diff --git a/src/runtime/q3dsengine.cpp b/src/runtime/q3dsengine.cpp
index 500c8fa..16c49ef 100644
--- a/src/runtime/q3dsengine.cpp
+++ b/src/runtime/q3dsengine.cpp
@@ -390,7 +390,7 @@ void Q3DSEngine::createAspectEngine()
if (!m_flags.testFlag(WithoutRenderAspect)) {
m_renderLoopStats.usingAsyncRenderAspect = true;
if (m_flags.testFlag(AwakenTheDragon))
- m_aspectEngine->registerAspect(new Qt3DRender::Dragon::QDragonRenderAspect);
+ m_aspectEngine->registerAspect(new Qt3DRender::Dragon::QDragonRenderAspect(Qt3DRender::Dragon::Renderer::Threaded));
else
m_aspectEngine->registerAspect(new Qt3DRender::QRenderAspect);
} else {