diff options
author | Sean Harmer <sean.harmer@kdab.com> | 2017-08-19 15:53:30 +0100 |
---|---|---|
committer | Sean Harmer <sean.harmer@kdab.com> | 2017-08-19 16:28:52 +0100 |
commit | 8f863343a9e2e2f3630f22407f4e5e30e72745cf (patch) | |
tree | 5574e3c2215d74345e15df5f45ed3211e065541a /src/render | |
parent | 3edb85002b848033bbeefa33001d19fb514ef489 (diff) | |
parent | 9d8c9ada161ad97634992c444196add0abb4f9d1 (diff) |
Merge branch '5.9' into dev
Conflicts:
src/render/backend/renderer.cpp
src/render/backend/renderview.cpp
src/render/graphicshelpers/graphicscontext_p.h
src/render/graphicshelpers/graphicshelperes2_p.h
src/render/graphicshelpers/graphicshelpergl2_p.h
src/render/graphicshelpers/graphicshelpergl3_2_p.h
src/render/graphicshelpers/graphicshelpergl3_3_p.h
src/render/graphicshelpers/graphicshelpergl4_p.h
src/render/graphicshelpers/graphicshelperinterface_p.h
src/render/jobs/pickboundingvolumejob.cpp
tests/auto/animation/clipanimator/tst_clipanimator.cpp
tests/auto/auto.pro
tests/manual/manual.pro
Also disabled the QQmlMetaType codepaths following commit
49a11e882059ee1729f776722e085dd21d378c36 in qtdeclarative. The
QQmlMetaType codepaths will be re-enabled once a qt5.git
integration has succeeded.
Change-Id: Ia654d75425e6d406c472d19864383612208cad2b
Diffstat (limited to 'src/render')
40 files changed, 575 insertions, 175 deletions
diff --git a/src/render/backend/entity.cpp b/src/render/backend/entity.cpp index 061fc06c4..34568c1a7 100644 --- a/src/render/backend/entity.cpp +++ b/src/render/backend/entity.cpp @@ -180,9 +180,9 @@ void Entity::initializeFromPeer(const QNodeCreatedChangeBasePtr &change) m_shaderDataComponents.clear(); m_lightComponents.clear(); m_environmentLightComponents.clear(); - m_localBoundingVolume.reset(new Sphere(peerId())); - m_worldBoundingVolume.reset(new Sphere(peerId())); - m_worldBoundingVolumeWithChildren.reset(new Sphere(peerId())); + m_localBoundingVolume = QSharedPointer<Sphere>::create(peerId()); + m_worldBoundingVolume = QSharedPointer<Sphere>::create(peerId()); + m_worldBoundingVolumeWithChildren = QSharedPointer<Sphere>::create(peerId()); for (const auto &idAndType : qAsConst(data.componentIdsAndTypes)) addComponent(idAndType); diff --git a/src/render/backend/rendercommand.cpp b/src/render/backend/rendercommand.cpp index 044ef035c..85c4858cf 100644 --- a/src/render/backend/rendercommand.cpp +++ b/src/render/backend/rendercommand.cpp @@ -66,21 +66,11 @@ RenderCommand::RenderCommand() , m_primitiveRestartEnabled(false) , m_isValid(false) { - m_sortingType.global = 0; m_workGroups[0] = 0; m_workGroups[1] = 0; m_workGroups[2] = 0; } -bool compareCommands(RenderCommand *r1, RenderCommand *r2) -{ - // The smaller m_depth is, the closer it is to the eye. - if (r1->m_sortBackToFront && r2->m_sortBackToFront) - return r1->m_depth > r2->m_depth; - - return r1->m_sortingType.global < r2->m_sortingType.global; -} - } // namespace Render } // namespace Qt3DRender diff --git a/src/render/backend/rendercommand_p.h b/src/render/backend/rendercommand_p.h index 4b2966fc6..57fb553b7 100644 --- a/src/render/backend/rendercommand_p.h +++ b/src/render/backend/rendercommand_p.h @@ -70,13 +70,14 @@ namespace Render { class RenderStateSet; -class RenderCommand +class Q_AUTOTEST_EXPORT RenderCommand { public: RenderCommand(); HVao m_vao; // VAO used during the submission step to store all states and VBOs HShader m_shader; // Shader for given pass and mesh + HMaterial m_material; // Purely used to ease sorting (minimize stage changes, binding changes ....) ShaderParameterPack m_parameterPack; // Might need to be reworked so as to be able to destroy the // Texture while submission is happening. RenderStateSet *m_stateSet; @@ -101,11 +102,6 @@ public: CommandType m_type; - union sortingType { - char sorts[4]; - int global; - } m_sortingType; - bool m_sortBackToFront; int m_workGroups[3]; @@ -127,8 +123,6 @@ public: bool m_isValid; }; -bool compareCommands(RenderCommand *r1, RenderCommand *r2); - } // namespace Render } // namespace Qt3DRender diff --git a/src/render/backend/renderer.cpp b/src/render/backend/renderer.cpp index 3ca1a1675..b056d4380 100644 --- a/src/render/backend/renderer.cpp +++ b/src/render/backend/renderer.cpp @@ -157,7 +157,7 @@ Renderer::Renderer(QRenderAspect::RenderType type) , m_graphicsContext(nullptr) , m_renderQueue(new RenderQueue()) , m_renderThread(type == QRenderAspect::Threaded ? new RenderThread(this) : nullptr) - , m_vsyncFrameAdvanceService(new VSyncFrameAdvanceService()) + , m_vsyncFrameAdvanceService(new VSyncFrameAdvanceService(m_renderThread != nullptr)) , m_waitForInitializationToBeCompleted(0) , m_pickEventFilter(new PickEventFilter()) , m_exposed(0) @@ -1364,10 +1364,13 @@ Renderer::ViewSubmissionResultData Renderer::submitRenderViews(const QVector<Ren if (!request.rect.isEmpty()) rect = rect.intersected(request.rect); QImage image; - if (!rect.isEmpty()) + if (!rect.isEmpty()) { + // Bind fbo as read framebuffer + m_graphicsContext->bindFramebuffer(m_graphicsContext->activeFBO(), GraphicsHelperInterface::FBORead); image = m_graphicsContext->readFramebuffer(rect); - else + } else { qWarning() << "Requested capture rectangle is outside framebuffer"; + } Render::RenderCapture *renderCapture = static_cast<Render::RenderCapture*>(m_nodesManager->frameGraphManager()->lookupNode(renderView->renderCaptureNodeId())); renderCapture->addRenderCapture(request.captureId, image); @@ -1386,7 +1389,7 @@ Renderer::ViewSubmissionResultData Renderer::submitRenderViews(const QVector<Ren // lastBoundFBOId != m_graphicsContext->activeFBO() when the last FrameGraph leaf node/renderView // contains RenderTargetSelector/RenderTarget if (lastBoundFBOId != m_graphicsContext->activeFBO()) - m_graphicsContext->bindFramebuffer(lastBoundFBOId); + m_graphicsContext->bindFramebuffer(lastBoundFBOId, GraphicsHelperInterface::FBOReadAndDraw); // Reset state and call doneCurrent if the surface // is valid and was actually activated diff --git a/src/render/backend/renderview.cpp b/src/render/backend/renderview.cpp index 8177f958b..cded6b804 100644 --- a/src/render/backend/renderview.cpp +++ b/src/render/backend/renderview.cpp @@ -267,11 +267,178 @@ RenderView::~RenderView() } } +namespace { + +template<int SortType> +struct AdjacentSubRangeFinder +{ + static bool adjacentSubRange(RenderCommand *, RenderCommand *) + { + Q_UNREACHABLE(); + return false; + } +}; + +template<> +struct AdjacentSubRangeFinder<QSortPolicy::StateChangeCost> +{ + static bool adjacentSubRange(RenderCommand *a, RenderCommand *b) + { + return a->m_changeCost == b->m_changeCost; + } +}; + +template<> +struct AdjacentSubRangeFinder<QSortPolicy::BackToFront> +{ + static bool adjacentSubRange(RenderCommand *a, RenderCommand *b) + { + return a->m_depth == b->m_depth; + } +}; + +template<> +struct AdjacentSubRangeFinder<QSortPolicy::Material> +{ + static bool adjacentSubRange(RenderCommand *a, RenderCommand *b) + { + return a->m_shaderDna == b->m_shaderDna; + } +}; + +template<typename Predicate> +int advanceUntilNonAdjacent(const QVector<RenderCommand *> &commands, + const int beg, const int end, Predicate pred) +{ + int i = beg + 1; + while (i < end) { + if (!pred(*(commands.begin() + beg), *(commands.begin() + i))) + break; + ++i; + } + return i; +} + + +using CommandIt = QVector<RenderCommand *>::iterator; + +template<int SortType> +struct SubRangeSorter +{ + static void sortSubRange(CommandIt begin, const CommandIt end) + { + Q_UNREACHABLE(); + } +}; + +template<> +struct SubRangeSorter<QSortPolicy::StateChangeCost> +{ + static void sortSubRange(CommandIt begin, const CommandIt end) + { + std::stable_sort(begin, end, [] (RenderCommand *a, RenderCommand *b) { + return a->m_changeCost > b->m_changeCost; + }); + } +}; + +template<> +struct SubRangeSorter<QSortPolicy::BackToFront> +{ + static void sortSubRange(CommandIt begin, const CommandIt end) + { + std::stable_sort(begin, end, [] (RenderCommand *a, RenderCommand *b) { + return a->m_depth > b->m_depth; + }); + } +}; + +template<> +struct SubRangeSorter<QSortPolicy::Material> +{ + static void sortSubRange(CommandIt begin, const CommandIt end) + { + // First we sort by shaderDNA + std::stable_sort(begin, end, [] (RenderCommand *a, RenderCommand *b) { + return a->m_shaderDna > b->m_shaderDna; + }); + } +}; + + +int findSubRange(const QVector<RenderCommand *> &commands, + const int begin, const int end, + const QSortPolicy::SortType sortType) +{ + switch (sortType) { + case QSortPolicy::StateChangeCost: + return advanceUntilNonAdjacent(commands, begin, end, AdjacentSubRangeFinder<QSortPolicy::StateChangeCost>::adjacentSubRange); + case QSortPolicy::BackToFront: + return advanceUntilNonAdjacent(commands, begin, end, AdjacentSubRangeFinder<QSortPolicy::BackToFront>::adjacentSubRange); + case QSortPolicy::Material: + return advanceUntilNonAdjacent(commands, begin, end, AdjacentSubRangeFinder<QSortPolicy::Material>::adjacentSubRange); + default: + Q_UNREACHABLE(); + return end; + } +} + +void sortByMaterial(QVector<RenderCommand *> &commands, int begin, const int end) +{ + // We try to arrange elements so that their rendering cost is minimized for a given shader + int rangeEnd = advanceUntilNonAdjacent(commands, begin, end, AdjacentSubRangeFinder<QSortPolicy::Material>::adjacentSubRange); + while (begin != end) { + if (begin + 1 < rangeEnd) { + std::stable_sort(commands.begin() + begin + 1, commands.begin() + rangeEnd, [] (RenderCommand *a, RenderCommand *b){ + return a->m_material < b->m_material; + }); + } + begin = rangeEnd; + rangeEnd = advanceUntilNonAdjacent(commands, begin, end, AdjacentSubRangeFinder<QSortPolicy::Material>::adjacentSubRange); + } +} + +void sortCommandRange(QVector<RenderCommand *> &commands, int begin, const int end, const int level, + const QVector<Qt3DRender::QSortPolicy::SortType> &sortingTypes) +{ + if (level >= sortingTypes.size()) + return; + + switch (sortingTypes.at(level)) { + case QSortPolicy::StateChangeCost: + SubRangeSorter<QSortPolicy::StateChangeCost>::sortSubRange(commands.begin() + begin, commands.begin() + end); + break; + case QSortPolicy::BackToFront: + SubRangeSorter<QSortPolicy::BackToFront>::sortSubRange(commands.begin() + begin, commands.begin() + end); + break; + case QSortPolicy::Material: + // Groups all same shader DNA together + SubRangeSorter<QSortPolicy::Material>::sortSubRange(commands.begin() + begin, commands.begin() + end); + // Group all same material together (same parameters most likely) + sortByMaterial(commands, begin, end); + break; + default: + Q_UNREACHABLE(); + } + + // For all sub ranges of adjacent item for sortType[i] + // Perform filtering with sortType[i + 1] + int rangeEnd = findSubRange(commands, begin, end, sortingTypes.at(level)); + while (begin != end) { + sortCommandRange(commands, begin, rangeEnd, level + 1, sortingTypes); + begin = rangeEnd; + rangeEnd = findSubRange(commands, begin, end, sortingTypes.at(level)); + } +} + +} // anonymous + void RenderView::sort() { - // Compares the bitsetKey of the RenderCommands - // Key[Depth | StateCost | Shader] - std::sort(m_commands.begin(), m_commands.end(), compareCommands); + sortCommandRange(m_commands, 0, m_commands.size(), 0, m_data.m_sortingTypes); + + // For RenderCommand with the same shader + // We compute the adjacent change cost // Minimize uniform changes int i = 0; @@ -392,6 +559,7 @@ QVector<RenderCommand *> RenderView::buildDrawRenderCommands(const QVector<Entit && !geometryRenderer->geometryId().isNull()) { const Qt3DCore::QNodeId materialComponentId = entity->componentUuid<Material>(); + const HMaterial materialHandle = entity->componentHandle<Material, 16>(); const QVector<RenderPassParameterData> renderPassData = m_parameters.value(materialComponentId); HGeometry geometryHandle = m_manager->lookupHandle<Geometry, GeometryManager, HGeometry>(geometryRenderer->geometryId()); Geometry *geometry = m_manager->data<Geometry, GeometryManager>(geometryHandle); @@ -403,6 +571,7 @@ QVector<RenderCommand *> RenderView::buildDrawRenderCommands(const QVector<Entit command->m_depth = m_data.m_eyePos.distanceToPoint(entity->worldBoundingVolume()->center()); command->m_geometry = geometryHandle; command->m_geometryRenderer = geometryRendererHandle; + command->m_material = materialHandle; // For RenderPass based states we use the globally set RenderState // if no renderstates are defined as part of the pass. That means: // RenderPass { renderStates: [] } will use the states defined by @@ -482,7 +651,7 @@ QVector<RenderCommand *> RenderView::buildDrawRenderCommands(const QVector<Entit command->m_verticesPerPatch = geometryRenderer->verticesPerPatch(); } - buildSortingKey(command); + prepareForSorting(command); commands.append(command); } } @@ -703,27 +872,21 @@ void RenderView::setDefaultUniformBlockShaderDataValue(ShaderParameterPack &unif } } -void RenderView::buildSortingKey(RenderCommand *command) const +void RenderView::prepareForSorting(RenderCommand *command) const { // Build a bitset key depending on the SortingCriterion - int sortCount = m_data.m_sortingTypes.count(); + const int sortCount = m_data.m_sortingTypes.count(); // If sortCount == 0, no sorting is applied // Handle at most 4 filters at once for (int i = 0; i < sortCount && i < 4; i++) { switch (m_data.m_sortingTypes.at(i)) { - case QSortPolicy::StateChangeCost: - command->m_sortingType.sorts[i] = command->m_changeCost; // State change cost - break; case QSortPolicy::BackToFront: command->m_sortBackToFront = true; // Depth value break; - case QSortPolicy::Material: - command->m_sortingType.sorts[i] = command->m_shaderDna; // Material - break; default: - Q_UNREACHABLE(); + break; } } } diff --git a/src/render/backend/renderview_p.h b/src/render/backend/renderview_p.h index e69cd2a52..5579e8e95 100644 --- a/src/render/backend/renderview_p.h +++ b/src/render/backend/renderview_p.h @@ -354,7 +354,7 @@ private: Shader *shader, ShaderData *shaderData, const QString &structName) const; - void buildSortingKey(RenderCommand *command) const; + void prepareForSorting(RenderCommand *command) const; }; } // namespace Render diff --git a/src/render/frontend/qlevelofdetail.cpp b/src/render/frontend/qlevelofdetail.cpp index 03df4e6a8..a3596a518 100644 --- a/src/render/frontend/qlevelofdetail.cpp +++ b/src/render/frontend/qlevelofdetail.cpp @@ -277,7 +277,7 @@ QLevelOfDetailPrivate::QLevelOfDetailPrivate() * If this value to nullptr, the bounding volume of the entity is used. Care must be * taken that this bounding volume never becomes invalid. * - * \sa Qt3dRender::QLevelOfDetailBoundingSphere + * \sa Qt3DRender::QLevelOfDetailBoundingSphere */ diff --git a/src/render/frontend/qrenderaspect.cpp b/src/render/frontend/qrenderaspect.cpp index 1f928f768..532e55d0f 100644 --- a/src/render/frontend/qrenderaspect.cpp +++ b/src/render/frontend/qrenderaspect.cpp @@ -393,6 +393,7 @@ QRenderAspect::~QRenderAspect() { } +// Called by Scene3DRenderer only void QRenderAspectPrivate::renderInitialize(QOpenGLContext *context) { if (m_renderer->api() == Render::AbstractRenderer::OpenGL) diff --git a/src/render/geometry/qgeometryrenderer.cpp b/src/render/geometry/qgeometryrenderer.cpp index 666c72d83..a497bab97 100644 --- a/src/render/geometry/qgeometryrenderer.cpp +++ b/src/render/geometry/qgeometryrenderer.cpp @@ -182,6 +182,7 @@ QGeometryRendererPrivate::~QGeometryRendererPrivate() \list \li QGeometryRenderer.Points + \li QGeometryRenderer.Lines \li QGeometryRenderer.LineLoop \li QGeometryRenderer.LineStrip \li QGeometryRenderer.Triangles diff --git a/src/render/geometry/qmesh.cpp b/src/render/geometry/qmesh.cpp index 109a8a445..9a1f10bc5 100644 --- a/src/render/geometry/qmesh.cpp +++ b/src/render/geometry/qmesh.cpp @@ -101,8 +101,18 @@ void QMeshPrivate::updateFunctor() * * Loads mesh data from external files in a variety of formats. * - * In Qt3D 5.9, Mesh supports the following formats: Wavefront OBJ, Stanford Triangle Format PLY, STL (STereoLithography). - * QMesh will also support Autodesk FBX files if the SDK is installed and the fbx geometry loader plugin is built and found. + * In Qt3D 5.9, Mesh supports the following formats: + * + * \list + * \li Wavefront OBJ + * \li Stanford Triangle Format PLY + * \li STL (STereoLithography) + * \endlist + * + * QMesh will also support the following format if the SDK is installed and the fbx geometry loader plugin is built and found. + * \list + * \li Autodesk FBX + * \endlist */ /*! @@ -139,8 +149,18 @@ void QMeshPrivate::updateFunctor() * Loads mesh data from external files in a variety of formats. * Qt3DRender::QMesh loads data into a single mesh. * - * In Qt3D 5.9, QMesh supports the following formats: Wavefront OBJ, Stanford Triangle Format PLY, STL (STereoLithography). - * QMesh will also support Autodesk FBX files if the SDK is installed and the fbx geometry loader plugin is built and found. + * In Qt3D 5.9, QMesh supports the following formats: + * + * \list + * \li Wavefront OBJ + * \li Stanford Triangle Format PLY + * \li STL (STereoLithography) + * \endlist + * + * QMesh will also support the following format if the SDK is installed and the fbx geometry loader plugin is built and found: + * \list + * \li Autodesk FBX + * \endlist * * If you wish to load an entire scene made of several objects, you should rather use the Qt3DRender::QSceneLoader instead. * diff --git a/src/render/graphicshelpers/graphicscontext.cpp b/src/render/graphicshelpers/graphicscontext.cpp index 7910c828a..f09336243 100644 --- a/src/render/graphicshelpers/graphicscontext.cpp +++ b/src/render/graphicshelpers/graphicscontext.cpp @@ -592,7 +592,7 @@ void GraphicsContext::activateRenderTarget(Qt3DCore::QNodeId renderTargetNodeId, // Insert FBO into hash m_renderTargets.insert(renderTargetNodeId, fboId); // Bind FBO - m_glHelper->bindFrameBufferObject(fboId); + m_glHelper->bindFrameBufferObject(fboId, GraphicsHelperInterface::FBODraw); bindFrameBufferAttachmentHelper(fboId, attachments); } else { qCritical() << "Failed to create FBO"; @@ -616,13 +616,13 @@ void GraphicsContext::activateRenderTarget(Qt3DCore::QNodeId renderTargetNodeId, } if (needsResize) { - m_glHelper->bindFrameBufferObject(fboId); + m_glHelper->bindFrameBufferObject(fboId, GraphicsHelperInterface::FBODraw); bindFrameBufferAttachmentHelper(fboId, attachments); } } } m_activeFBO = fboId; - m_glHelper->bindFrameBufferObject(m_activeFBO); + m_glHelper->bindFrameBufferObject(m_activeFBO, GraphicsHelperInterface::FBODraw); // Set active drawBuffers activateDrawBuffers(attachments); } @@ -972,9 +972,9 @@ void GraphicsContext::alphaTest(GLenum mode1, GLenum mode2) m_glHelper->alphaTest(mode1, mode2); } -void GraphicsContext::bindFramebuffer(GLuint fbo) +void GraphicsContext::bindFramebuffer(GLuint fbo, GraphicsHelperInterface::FBOBindMode mode) { - m_glHelper->bindFrameBufferObject(fbo); + m_glHelper->bindFrameBufferObject(fbo, mode); } void GraphicsContext::depthTest(GLenum mode) diff --git a/src/render/graphicshelpers/graphicscontext_p.h b/src/render/graphicshelpers/graphicscontext_p.h index 9252bb467..fcb17ade7 100644 --- a/src/render/graphicshelpers/graphicscontext_p.h +++ b/src/render/graphicshelpers/graphicscontext_p.h @@ -70,6 +70,7 @@ #include <Qt3DRender/private/qgraphicsapifilter_p.h> #include <Qt3DRender/private/shadercache_p.h> #include <Qt3DRender/private/uniform_p.h> +#include <Qt3DRender/private/graphicshelperinterface_p.h> #include <qmath.h> QT_BEGIN_NAMESPACE @@ -194,7 +195,7 @@ public: // Wrapper methods void alphaTest(GLenum mode1, GLenum mode2); - void bindFramebuffer(GLuint fbo); + void bindFramebuffer(GLuint fbo, GraphicsHelperInterface::FBOBindMode mode); void bindBufferBase(GLenum target, GLuint bindingIndex, GLuint buffer); void bindFragOutputs(GLuint shader, const QHash<QString, int> &outputs); void bindUniformBlock(GLuint programId, GLuint uniformBlockIndex, GLuint uniformBlockBinding); diff --git a/src/render/graphicshelpers/graphicshelperes2.cpp b/src/render/graphicshelpers/graphicshelperes2.cpp index 4954aac9e..a72e6159c 100644 --- a/src/render/graphicshelpers/graphicshelperes2.cpp +++ b/src/render/graphicshelpers/graphicshelperes2.cpp @@ -63,6 +63,15 @@ QT_BEGIN_NAMESPACE #define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 #endif +// ES 2.0 FBO +#ifndef GL_DRAW_FRAMEBUFFER +#define GL_DRAW_FRAMEBUFFER 0x8CA9 +#endif + +#ifndef GL_READ_FRAMEBUFFER +#define GL_READ_FRAMEBUFFER 0x8CA8 +#endif + namespace Qt3DRender { namespace Render { @@ -344,9 +353,20 @@ void GraphicsHelperES2::releaseFrameBufferObject(GLuint frameBufferId) m_funcs->glDeleteFramebuffers(1, &frameBufferId); } -void GraphicsHelperES2::bindFrameBufferObject(GLuint frameBufferId) +void GraphicsHelperES2::bindFrameBufferObject(GLuint frameBufferId, FBOBindMode mode) { - m_funcs->glBindFramebuffer(GL_FRAMEBUFFER, frameBufferId); + switch (mode) { + case FBODraw: + m_funcs->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frameBufferId); + return; + case FBORead: + m_funcs->glBindFramebuffer(GL_READ_FRAMEBUFFER, frameBufferId); + return; + case FBOReadAndDraw: + default: + m_funcs->glBindFramebuffer(GL_FRAMEBUFFER, frameBufferId); + return; + } } GLuint GraphicsHelperES2::boundFrameBufferObject() diff --git a/src/render/graphicshelpers/graphicshelperes2_p.h b/src/render/graphicshelpers/graphicshelperes2_p.h index d068b5307..b93268188 100644 --- a/src/render/graphicshelpers/graphicshelperes2_p.h +++ b/src/render/graphicshelpers/graphicshelperes2_p.h @@ -75,7 +75,7 @@ public: bool frameBufferNeedsRenderBuffer(const Attachment &attachment) Q_DECL_OVERRIDE; void bindFrameBufferAttachment(QOpenGLTexture *texture, const Attachment &attachment) Q_DECL_OVERRIDE; void bindFrameBufferAttachment(RenderBuffer *renderBuffer, const Attachment &attachment) Q_DECL_OVERRIDE; - void bindFrameBufferObject(GLuint frameBufferId) Q_DECL_OVERRIDE; + void bindFrameBufferObject(GLuint frameBufferId, FBOBindMode mode) Q_DECL_OVERRIDE; void bindShaderStorageBlock(GLuint programId, GLuint shaderStorageBlockIndex, GLuint shaderStorageBlockBinding) Q_DECL_OVERRIDE; void bindUniformBlock(GLuint programId, GLuint uniformBlockIndex, GLuint uniformBlockBinding) Q_DECL_OVERRIDE; void blendEquation(GLenum mode) Q_DECL_OVERRIDE; diff --git a/src/render/graphicshelpers/graphicshelpergl2.cpp b/src/render/graphicshelpers/graphicshelpergl2.cpp index 28d1a91c9..9abc392ee 100644 --- a/src/render/graphicshelpers/graphicshelpergl2.cpp +++ b/src/render/graphicshelpers/graphicshelpergl2.cpp @@ -418,12 +418,24 @@ void GraphicsHelperGL2::bindFragDataLocation(GLuint, const QHash<QString, int> & qCritical() << "bindFragDataLocation is not supported by GL 2.0"; } -void GraphicsHelperGL2::bindFrameBufferObject(GLuint frameBufferId) +void GraphicsHelperGL2::bindFrameBufferObject(GLuint frameBufferId, FBOBindMode mode) { - if (m_fboFuncs != nullptr) - m_fboFuncs->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frameBufferId); - else + if (m_fboFuncs != nullptr) { + switch (mode) { + case FBODraw: + m_fboFuncs->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frameBufferId); + return; + case FBORead: + m_fboFuncs->glBindFramebuffer(GL_READ_FRAMEBUFFER, frameBufferId); + return; + case FBOReadAndDraw: + default: + m_fboFuncs->glBindFramebuffer(GL_FRAMEBUFFER, frameBufferId); + return; + } + } else { qWarning() << "FBO not supported by your OpenGL hardware"; + } } GLuint GraphicsHelperGL2::boundFrameBufferObject() diff --git a/src/render/graphicshelpers/graphicshelpergl2_p.h b/src/render/graphicshelpers/graphicshelpergl2_p.h index 7d617937d..3a15af260 100644 --- a/src/render/graphicshelpers/graphicshelpergl2_p.h +++ b/src/render/graphicshelpers/graphicshelpergl2_p.h @@ -75,7 +75,7 @@ public: bool frameBufferNeedsRenderBuffer(const Attachment &attachment) Q_DECL_OVERRIDE; void bindFrameBufferAttachment(QOpenGLTexture *texture, const Attachment &attachment) Q_DECL_OVERRIDE; void bindFrameBufferAttachment(RenderBuffer *renderBuffer, const Attachment &attachment) Q_DECL_OVERRIDE; - void bindFrameBufferObject(GLuint frameBufferId) Q_DECL_OVERRIDE; + void bindFrameBufferObject(GLuint frameBufferId, FBOBindMode mode) Q_DECL_OVERRIDE; void bindShaderStorageBlock(GLuint programId, GLuint shaderStorageBlockIndex, GLuint shaderStorageBlockBinding) Q_DECL_OVERRIDE; void bindUniformBlock(GLuint programId, GLuint uniformBlockIndex, GLuint uniformBlockBinding) Q_DECL_OVERRIDE; void blendEquation(GLenum mode) Q_DECL_OVERRIDE; diff --git a/src/render/graphicshelpers/graphicshelpergl3_2.cpp b/src/render/graphicshelpers/graphicshelpergl3_2.cpp index 47e850871..54c46babe 100644 --- a/src/render/graphicshelpers/graphicshelpergl3_2.cpp +++ b/src/render/graphicshelpers/graphicshelpergl3_2.cpp @@ -392,9 +392,20 @@ void GraphicsHelperGL3_2::releaseFrameBufferObject(GLuint frameBufferId) m_funcs->glDeleteFramebuffers(1, &frameBufferId); } -void GraphicsHelperGL3_2::bindFrameBufferObject(GLuint frameBufferId) +void GraphicsHelperGL3_2::bindFrameBufferObject(GLuint frameBufferId, FBOBindMode mode) { - m_funcs->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frameBufferId); + switch (mode) { + case FBODraw: + m_funcs->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frameBufferId); + return; + case FBORead: + m_funcs->glBindFramebuffer(GL_READ_FRAMEBUFFER, frameBufferId); + return; + case FBOReadAndDraw: + default: + m_funcs->glBindFramebuffer(GL_FRAMEBUFFER, frameBufferId); + return; + } } GLuint GraphicsHelperGL3_2::boundFrameBufferObject() diff --git a/src/render/graphicshelpers/graphicshelpergl3_2_p.h b/src/render/graphicshelpers/graphicshelpergl3_2_p.h index 94ff4b4eb..bebe14ade 100644 --- a/src/render/graphicshelpers/graphicshelpergl3_2_p.h +++ b/src/render/graphicshelpers/graphicshelpergl3_2_p.h @@ -77,7 +77,7 @@ public: bool frameBufferNeedsRenderBuffer(const Attachment &attachment) Q_DECL_OVERRIDE; void bindFrameBufferAttachment(QOpenGLTexture *texture, const Attachment &attachment) Q_DECL_OVERRIDE; void bindFrameBufferAttachment(RenderBuffer *renderBuffer, const Attachment &attachment) Q_DECL_OVERRIDE; - void bindFrameBufferObject(GLuint frameBufferId) Q_DECL_OVERRIDE; + void bindFrameBufferObject(GLuint frameBufferId, FBOBindMode mode) Q_DECL_OVERRIDE; void bindShaderStorageBlock(GLuint programId, GLuint shaderStorageBlockIndex, GLuint shaderStorageBlockBinding) Q_DECL_OVERRIDE; void bindUniformBlock(GLuint programId, GLuint uniformBlockIndex, GLuint uniformBlockBinding) Q_DECL_OVERRIDE; void blendEquation(GLenum mode) Q_DECL_OVERRIDE; diff --git a/src/render/graphicshelpers/graphicshelpergl3_3.cpp b/src/render/graphicshelpers/graphicshelpergl3_3.cpp index fbb1455c6..e1ae23e6d 100644 --- a/src/render/graphicshelpers/graphicshelpergl3_3.cpp +++ b/src/render/graphicshelpers/graphicshelpergl3_3.cpp @@ -379,9 +379,20 @@ void GraphicsHelperGL3_3::releaseFrameBufferObject(GLuint frameBufferId) m_funcs->glDeleteFramebuffers(1, &frameBufferId); } -void GraphicsHelperGL3_3::bindFrameBufferObject(GLuint frameBufferId) +void GraphicsHelperGL3_3::bindFrameBufferObject(GLuint frameBufferId, FBOBindMode mode) { - m_funcs->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frameBufferId); + switch (mode) { + case FBODraw: + m_funcs->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frameBufferId); + return; + case FBORead: + m_funcs->glBindFramebuffer(GL_READ_FRAMEBUFFER, frameBufferId); + return; + case FBOReadAndDraw: + default: + m_funcs->glBindFramebuffer(GL_FRAMEBUFFER, frameBufferId); + return; + } } GLuint GraphicsHelperGL3_3::boundFrameBufferObject() diff --git a/src/render/graphicshelpers/graphicshelpergl3_3_p.h b/src/render/graphicshelpers/graphicshelpergl3_3_p.h index 3b03cf851..e890fd1a4 100644 --- a/src/render/graphicshelpers/graphicshelpergl3_3_p.h +++ b/src/render/graphicshelpers/graphicshelpergl3_3_p.h @@ -77,7 +77,7 @@ public: bool frameBufferNeedsRenderBuffer(const Attachment &attachment) Q_DECL_OVERRIDE; void bindFrameBufferAttachment(QOpenGLTexture *texture, const Attachment &attachment) Q_DECL_OVERRIDE; void bindFrameBufferAttachment(RenderBuffer *renderBuffer, const Attachment &attachment) Q_DECL_OVERRIDE; - void bindFrameBufferObject(GLuint frameBufferId) Q_DECL_OVERRIDE; + void bindFrameBufferObject(GLuint frameBufferId, FBOBindMode mode) Q_DECL_OVERRIDE; void bindShaderStorageBlock(GLuint programId, GLuint shaderStorageBlockIndex, GLuint shaderStorageBlockBinding) Q_DECL_OVERRIDE; void bindUniformBlock(GLuint programId, GLuint uniformBlockIndex, GLuint uniformBlockBinding) Q_DECL_OVERRIDE; void blendEquation(GLenum mode) Q_DECL_OVERRIDE; diff --git a/src/render/graphicshelpers/graphicshelpergl4.cpp b/src/render/graphicshelpers/graphicshelpergl4.cpp index 9cb1f02ee..badbaf67d 100644 --- a/src/render/graphicshelpers/graphicshelpergl4.cpp +++ b/src/render/graphicshelpers/graphicshelpergl4.cpp @@ -652,9 +652,20 @@ void GraphicsHelperGL4::releaseFrameBufferObject(GLuint frameBufferId) m_funcs->glDeleteFramebuffers(1, &frameBufferId); } -void GraphicsHelperGL4::bindFrameBufferObject(GLuint frameBufferId) -{ - m_funcs->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frameBufferId); +void GraphicsHelperGL4::bindFrameBufferObject(GLuint frameBufferId, FBOBindMode mode) +{ + switch (mode) { + case FBODraw: + m_funcs->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frameBufferId); + return; + case FBORead: + m_funcs->glBindFramebuffer(GL_READ_FRAMEBUFFER, frameBufferId); + return; + case FBOReadAndDraw: + default: + m_funcs->glBindFramebuffer(GL_FRAMEBUFFER, frameBufferId); + return; + } } GLuint GraphicsHelperGL4::boundFrameBufferObject() diff --git a/src/render/graphicshelpers/graphicshelpergl4_p.h b/src/render/graphicshelpers/graphicshelpergl4_p.h index e636832b3..1effbc9b9 100644 --- a/src/render/graphicshelpers/graphicshelpergl4_p.h +++ b/src/render/graphicshelpers/graphicshelpergl4_p.h @@ -75,7 +75,7 @@ public: bool frameBufferNeedsRenderBuffer(const Attachment &attachment) Q_DECL_OVERRIDE; void bindFrameBufferAttachment(QOpenGLTexture *texture, const Attachment &attachment) Q_DECL_OVERRIDE; void bindFrameBufferAttachment(RenderBuffer *renderBuffer, const Attachment &attachment) Q_DECL_OVERRIDE; - void bindFrameBufferObject(GLuint frameBufferId) Q_DECL_OVERRIDE; + void bindFrameBufferObject(GLuint frameBufferId, FBOBindMode mode) Q_DECL_OVERRIDE; void bindShaderStorageBlock(GLuint programId, GLuint shaderStorageBlockIndex, GLuint shaderStorageBlockBinding) Q_DECL_OVERRIDE; void bindUniformBlock(GLuint programId, GLuint uniformBlockIndex, GLuint uniformBlockBinding) Q_DECL_OVERRIDE; void blendEquation(GLenum mode) Q_DECL_OVERRIDE; diff --git a/src/render/graphicshelpers/graphicshelperinterface_p.h b/src/render/graphicshelpers/graphicshelperinterface_p.h index 45326eb91..9ded1835e 100644 --- a/src/render/graphicshelpers/graphicshelperinterface_p.h +++ b/src/render/graphicshelpers/graphicshelperinterface_p.h @@ -85,6 +85,12 @@ public: MapBuffer }; + enum FBOBindMode { + FBODraw, + FBORead, + FBOReadAndDraw + }; + virtual ~GraphicsHelperInterface() {} virtual void alphaTest(GLenum mode1, GLenum mode2) = 0; virtual void bindBufferBase(GLenum target, GLuint index, GLuint buffer) = 0; @@ -92,7 +98,7 @@ public: virtual bool frameBufferNeedsRenderBuffer(const Attachment &attachment) = 0; virtual void bindFrameBufferAttachment(QOpenGLTexture *texture, const Attachment &attachment) = 0; virtual void bindFrameBufferAttachment(RenderBuffer *renderBuffer, const Attachment &attachment) = 0; - virtual void bindFrameBufferObject(GLuint frameBufferId) = 0; + virtual void bindFrameBufferObject(GLuint frameBufferId, FBOBindMode mode) = 0; virtual void bindShaderStorageBlock(GLuint programId, GLuint shaderStorageBlockIndex, GLuint shaderStorageBlockBinding) = 0; virtual void bindUniformBlock(GLuint programId, GLuint uniformBlockIndex, GLuint uniformBlockBinding) = 0; virtual void blendEquation(GLenum mode) = 0; diff --git a/src/render/jobs/pickboundingvolumejob.cpp b/src/render/jobs/pickboundingvolumejob.cpp index 2f39c6641..f0426b8fb 100644 --- a/src/render/jobs/pickboundingvolumejob.cpp +++ b/src/render/jobs/pickboundingvolumejob.cpp @@ -358,32 +358,32 @@ void PickBoundingVolumeJob::dispatchPickEvents(const QMouseEvent &event, QPickEventPtr pickEvent; switch (hit.m_type) { case QCollisionQueryResult::Hit::Triangle: - pickEvent.reset(new QPickTriangleEvent(event.localPos(), hit.m_intersection, - localIntersection, hit.m_distance, - hit.m_primitiveIndex, - hit.m_vertexIndex[0], - hit.m_vertexIndex[1], - hit.m_vertexIndex[2], - eventButton, eventButtons, - eventModifiers, hit.m_uvw)); + pickEvent = QPickTriangleEventPtr::create(event.localPos(), hit.m_intersection, + localIntersection, hit.m_distance, + hit.m_primitiveIndex, + hit.m_vertexIndex[0], + hit.m_vertexIndex[1], + hit.m_vertexIndex[2], + eventButton, eventButtons, + eventModifiers, hit.m_uvw); break; case QCollisionQueryResult::Hit::Edge: - pickEvent.reset(new QPickLineEvent(event.localPos(), hit.m_intersection, - localIntersection, hit.m_distance, - hit.m_primitiveIndex, - hit.m_vertexIndex[0], hit.m_vertexIndex[1], - eventButton, eventButtons, eventModifiers)); + pickEvent = QPickLineEventPtr::create(event.localPos(), hit.m_intersection, + localIntersection, hit.m_distance, + hit.m_primitiveIndex, + hit.m_vertexIndex[0], hit.m_vertexIndex[1], + eventButton, eventButtons, eventModifiers); break; case QCollisionQueryResult::Hit::Point: - pickEvent.reset(new QPickPointEvent(event.localPos(), hit.m_intersection, - localIntersection, hit.m_distance, - hit.m_vertexIndex[0], - eventButton, eventButtons, eventModifiers)); + pickEvent = QPickPointEventPtr::create(event.localPos(), hit.m_intersection, + localIntersection, hit.m_distance, + hit.m_vertexIndex[0], + eventButton, eventButtons, eventModifiers); break; case QCollisionQueryResult::Hit::Entity: - pickEvent.reset(new QPickEvent(event.localPos(), hit.m_intersection, - localIntersection, hit.m_distance, - eventButton, eventButtons, eventModifiers)); + pickEvent = QPickEventPtr::create(event.localPos(), hit.m_intersection, + localIntersection, hit.m_distance, + eventButton, eventButtons, eventModifiers); break; default: Q_UNREACHABLE(); diff --git a/src/render/materialsystem/qparameter.cpp b/src/render/materialsystem/qparameter.cpp index 64c672737..b9bfa44e7 100644 --- a/src/render/materialsystem/qparameter.cpp +++ b/src/render/materialsystem/qparameter.cpp @@ -88,7 +88,7 @@ \endcode When it comes to texture support, the Parameter value should be set to the - appropriate \l {Qt3DRender::QAbstractTexture}{Texture} subclass that matches the sampler type of the shader + appropriate \l {Qt3DRender::QAbstractTexture}{texture} subclass that matches the sampler type of the shader uniform. \code @@ -101,7 +101,7 @@ // uniform sampler2D diffuseTexture \endcode - \sa Texture + \sa Qt3DRender::QAbstractTexture */ /*! diff --git a/src/render/picking/qobjectpicker.cpp b/src/render/picking/qobjectpicker.cpp index 49f608a67..77d319676 100644 --- a/src/render/picking/qobjectpicker.cpp +++ b/src/render/picking/qobjectpicker.cpp @@ -82,10 +82,10 @@ namespace Qt3DRender { */ /*! - * \qmltype ObjectPicker - * \instantiates Qt3DRender::QObjectPicker - * \inqmlmodule Qt3D.Render - * \brief The ObjectPicker class instantiates a component that can + \qmltype ObjectPicker + \instantiates Qt3DRender::QObjectPicker + \inqmlmodule Qt3D.Render + \brief The ObjectPicker class instantiates a component that can be used to interact with an Entity by a process known as picking. For every combination of viewport and camera, picking casts a ray through the scene to @@ -109,80 +109,107 @@ namespace Qt3DRender { \note Instances of this component shouldn't be shared, not respecting that condition will most likely result in undefined behavior. - */ /*! + \qmlsignal Qt3D.Render::ObjectPicker::clicked(PickEvent pick) + + This signal is emitted when the bounding volume defined by the pickAttribute + property intersects with a ray on a mouse click the PickEvent \a pick contains + details of the event. +*/ + +/*! \qmlsignal Qt3D.Render::ObjectPicker::pressed(PickEvent pick) - This signal is emitted when the bounding volume defined by the pickAttribute property intersects - with a ray on a mouse press. + + This signal is emitted when the bounding volume defined by the + pickAttribute property intersects with a ray on a mouse press. Intersection + information are accessible through the \a pick parameter. */ /*! \qmlsignal Qt3D.Render::ObjectPicker::released(PickEvent pick) - This signal is emitted when the bounding volume defined by the pickAttribute property intersects - with a ray on a mouse release. + + This signal is emitted when the bounding volume defined by the + pickAttribute property intersects with a ray on a mouse release. + Intersection information are accessible through the \a pick parameter. */ /*! \qmlsignal Qt3D.Render::ObjectPicker::clicked(PickEvent pick) - This signal is emitted when the bounding volume defined by the pickAttribute property intersects - with a ray on a mouse click. + + This signal is emitted when the bounding volume defined by the + pickAttribute property intersects with a ray on a mouse click. Intersection + information are accessible through the pick \a parameter. */ /*! \qmlsignal Qt3D.Render::ObjectPicker::moved(PickEvent pick) - This signal is emitted when the bounding volume defined by the pickAttribute property intersects - with a ray on a mouse move with a button pressed. + + This signal is emitted when the bounding volume defined by the + pickAttribute property intersects with a ray on a mouse move with a button + pressed. Intersection information are accessible through the \a pick + parameter. */ /*! \qmlsignal Qt3D.Render::ObjectPicker::entered() - This signal is emitted when the bounding volume defined by the pickAttribute property intersects - with a ray on the mouse entering the volume. + + This signal is emitted when the bounding volume defined by the pickAttribute + property intersects with a ray on the mouse entering the volume. */ /*! \qmlsignal Qt3D.Render::ObjectPicker::exited() - This signal is emitted when the bounding volume defined by the pickAttribute property intersects - with a ray on the ray exiting the volume. + + This signal is emitted when the bounding volume defined by the pickAttribute + property intersects with a ray on the ray exiting the volume. */ /*! - \fn QObjectPicker::clicked(Qt3DRender::QPickEvent *pick) - This signal is emitted when the bounding volume defined by the pickAttribute property intersects - with a ray on a mouse click the QPickEvent \a pick contains details of the event. + \fn QObjectPicker::clicked(Qt3DRender::QPickEvent *pick) + + This signal is emitted when the bounding volume defined by the pickAttribute + property intersects with a ray on a mouse click the QPickEvent \a pick contains + details of the event. */ /*! - \fn QObjectPicker::entered() - This signal is emitted when the bounding volume defined by the pickAttribute property intersects - with a ray on the mouse entering the volume. + \fn QObjectPicker::entered() + + This signal is emitted when the bounding volume defined by the pickAttribute + property intersects with a ray on the mouse entering the volume. */ /*! - \fn QObjectPicker::exited() - This signal is emitted when the bounding volume defined by the pickAttribute property intersects - with a ray on the ray exiting the volume. + \fn QObjectPicker::exited() + + This signal is emitted when the bounding volume defined by the pickAttribute + property intersects with a ray on the ray exiting the volume. */ /*! - \fn QObjectPicker::moved(Qt3DRender::QPickEvent *pick) - This signal is emitted when the bounding volume defined by the pickAttribute property intersects - with a ray on a mouse move with a button pressed the QPickEvent \a pick contains details of the event. + \fn QObjectPicker::moved(Qt3DRender::QPickEvent *pick) + This signal is emitted when the bounding volume defined by the + pickAttribute property intersects with a ray on a mouse move with a button + pressed the QPickEvent \a pick contains details of the event. */ /*! - \fn QObjectPicker::pressed(Qt3DRender::QPickEvent *pick) - This signal is emitted when the bounding volume defined by the pickAttribute property intersects - with a ray on a mouse press the QPickEvent \a pick contains details of the event. + \fn QObjectPicker::pressed(Qt3DRender::QPickEvent *pick) + + This signal is emitted when the bounding volume defined by the + pickAttribute property intersects with a ray on a mouse press the + QPickEvent \a pick contains details of the event. */ /*! - \fn QObjectPicker::released(Qt3DRender::QPickEvent *pick) - This signal is emitted when the bounding volume defined by the pickAttribute property intersects - with a ray on a mouse release the QPickEvent \a pick contains details of the event. + \fn QObjectPicker::released(Qt3DRender::QPickEvent *pick) + + This signal is emitted when the bounding volume defined by the + pickAttribute property intersects with a ray on a mouse release the + QPickEvent \a pick contains details of the event. */ QObjectPicker::QObjectPicker(Qt3DCore::QNode *parent) diff --git a/src/render/picking/qpicklineevent.h b/src/render/picking/qpicklineevent.h index 102989450..09697ad22 100644 --- a/src/render/picking/qpicklineevent.h +++ b/src/render/picking/qpicklineevent.h @@ -41,6 +41,7 @@ #define QT3DRENDER_QPICKLINEEVENT_H #include <Qt3DRender/qpickevent.h> +#include <QtCore/qsharedpointer.h> QT_BEGIN_NAMESPACE @@ -68,6 +69,8 @@ private: Q_DECLARE_PRIVATE(QPickLineEvent) }; +typedef QSharedPointer<QPickLineEvent> QPickLineEventPtr; + } // Qt3DRender QT_END_NAMESPACE diff --git a/src/render/picking/qpickpointevent.h b/src/render/picking/qpickpointevent.h index fbfebcedd..f298f64b9 100644 --- a/src/render/picking/qpickpointevent.h +++ b/src/render/picking/qpickpointevent.h @@ -41,6 +41,7 @@ #define QT3DRENDER_QPICKPOINTEVENT_H #include <Qt3DRender/qpickevent.h> +#include <QtCore/qsharedpointer.h> QT_BEGIN_NAMESPACE @@ -64,6 +65,8 @@ private: Q_DECLARE_PRIVATE(QPickPointEvent) }; +typedef QSharedPointer<QPickPointEvent> QPickPointEventPtr; + } // Qt3DRender QT_END_NAMESPACE diff --git a/src/render/picking/qpicktriangleevent.h b/src/render/picking/qpicktriangleevent.h index 7655a0b94..f116af288 100644 --- a/src/render/picking/qpicktriangleevent.h +++ b/src/render/picking/qpicktriangleevent.h @@ -41,6 +41,7 @@ #define QT3DRENDER_QPICKTRIANGLEEVENT_H #include <Qt3DRender/qpickevent.h> +#include <QtCore/qsharedpointer.h> QT_BEGIN_NAMESPACE @@ -75,6 +76,8 @@ private: Q_DECLARE_PRIVATE(QPickTriangleEvent) }; +typedef QSharedPointer<QPickTriangleEvent> QPickTriangleEventPtr; + } // Qt3DRender QT_END_NAMESPACE diff --git a/src/render/renderstates/qstencilmask_p.h b/src/render/renderstates/qstencilmask_p.h index a6aad60b9..762b249f8 100644 --- a/src/render/renderstates/qstencilmask_p.h +++ b/src/render/renderstates/qstencilmask_p.h @@ -60,7 +60,7 @@ class QT3DRENDERSHARED_PRIVATE_EXPORT QStencilMaskPrivate : public QRenderStateP { public: QStencilMaskPrivate() - : QRenderStatePrivate(Render::StencilTestStateMask) + : QRenderStatePrivate(Render::StencilWriteStateMask) , m_frontOutputMask(0) , m_backOutputMask(0) {} diff --git a/src/render/renderstates/qstenciloperation.cpp b/src/render/renderstates/qstenciloperation.cpp index 7a5b113d8..66a326d55 100644 --- a/src/render/renderstates/qstenciloperation.cpp +++ b/src/render/renderstates/qstenciloperation.cpp @@ -40,6 +40,7 @@ #include "qstenciloperation.h" #include "qstenciloperation_p.h" #include "qstenciloperationarguments.h" +#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/private/qrenderstatecreatedchange_p.h> QT_BEGIN_NAMESPACE @@ -103,6 +104,19 @@ namespace Qt3DRender { QStencilOperation::QStencilOperation(QNode *parent) : QRenderState(*new QStencilOperationPrivate(), parent) { + Q_D(QStencilOperation); + + const auto resend = [d]() { d->resendArguments(); }; + + (void) connect(d->m_front, &QStencilOperationArguments::allTestsPassOperationChanged, resend); + (void) connect(d->m_front, &QStencilOperationArguments::depthTestFailureOperationChanged, resend); + (void) connect(d->m_front, &QStencilOperationArguments::stencilTestFailureOperationChanged, resend); + (void) connect(d->m_front, &QStencilOperationArguments::faceModeChanged, resend); + + (void) connect(d->m_back, &QStencilOperationArguments::allTestsPassOperationChanged, resend); + (void) connect(d->m_back, &QStencilOperationArguments::depthTestFailureOperationChanged, resend); + (void) connect(d->m_back, &QStencilOperationArguments::stencilTestFailureOperationChanged, resend); + (void) connect(d->m_back, &QStencilOperationArguments::faceModeChanged, resend); } /*! \internal */ @@ -110,6 +124,30 @@ QStencilOperation::~QStencilOperation() { } +/*! \internal */ +void QStencilOperationPrivate::resendArguments() +{ + auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(m_id); + QStencilOperationData data; + fillData(data); + e->setPropertyName("arguments"); + e->setValue(QVariant::fromValue(data)); + notifyObservers(e); +} + +/*! \internal */ +void QStencilOperationPrivate::fillData(QStencilOperationData &data) const +{ + data.front.face = m_front->faceMode(); + data.front.stencilTestFailureOperation = m_front->stencilTestFailureOperation(); + data.front.depthTestFailureOperation = m_front->depthTestFailureOperation(); + data.front.allTestsPassOperation = m_front->allTestsPassOperation(); + data.back.face = m_back->faceMode(); + data.back.stencilTestFailureOperation = m_back->stencilTestFailureOperation(); + data.back.depthTestFailureOperation = m_back->depthTestFailureOperation(); + data.back.allTestsPassOperation = m_back->allTestsPassOperation(); +} + QStencilOperationArguments *QStencilOperation::front() const { Q_D(const QStencilOperation); @@ -125,16 +163,7 @@ QStencilOperationArguments *QStencilOperation::back() const Qt3DCore::QNodeCreatedChangeBasePtr QStencilOperation::createNodeCreationChange() const { auto creationChange = QRenderStateCreatedChangePtr<QStencilOperationData>::create(this); - auto &data = creationChange->data; - Q_D(const QStencilOperation); - data.front.face = d->m_front->faceMode(); - data.front.stencilTestFailureOperation = d->m_front->stencilTestFailureOperation(); - data.front.depthTestFailureOperation = d->m_front->depthTestFailureOperation(); - data.front.allTestsPassOperation = d->m_front->allTestsPassOperation(); - data.back.face = d->m_back->faceMode(); - data.back.stencilTestFailureOperation = d->m_back->stencilTestFailureOperation(); - data.back.depthTestFailureOperation = d->m_back->depthTestFailureOperation(); - data.back.allTestsPassOperation = d->m_back->allTestsPassOperation(); + d_func()->fillData(creationChange->data); return creationChange; } diff --git a/src/render/renderstates/qstenciloperation_p.h b/src/render/renderstates/qstenciloperation_p.h index 3273ada23..dbce734b1 100644 --- a/src/render/renderstates/qstenciloperation_p.h +++ b/src/render/renderstates/qstenciloperation_p.h @@ -58,6 +58,12 @@ QT_BEGIN_NAMESPACE namespace Qt3DRender { +struct QStencilOperationData +{ + QStencilOperationArgumentsData front; + QStencilOperationArgumentsData back; +}; + class QT3DRENDERSHARED_PRIVATE_EXPORT QStencilOperationPrivate : public QRenderStatePrivate { public: @@ -69,16 +75,15 @@ public: QStencilOperationArguments *m_front; QStencilOperationArguments *m_back; -}; -struct QStencilOperationData -{ - QStencilOperationArgumentsData front; - QStencilOperationArgumentsData back; + void resendArguments(); + void fillData(QStencilOperationData &data) const; }; } // namespace Qt3DRender QT_END_NAMESPACE +Q_DECLARE_METATYPE(Qt3DRender::QStencilOperationData) + #endif // QT3DRENDER_QSTENCILOPERATION_P_H diff --git a/src/render/renderstates/qstenciltest.cpp b/src/render/renderstates/qstenciltest.cpp index f1e42f1e3..74acfe3bc 100644 --- a/src/render/renderstates/qstenciltest.cpp +++ b/src/render/renderstates/qstenciltest.cpp @@ -41,6 +41,7 @@ #include "qstenciltest.h" #include "qstenciltest_p.h" #include "qstenciltestarguments.h" +#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/private/qrenderstatecreatedchange_p.h> QT_BEGIN_NAMESPACE @@ -106,6 +107,19 @@ namespace Qt3DRender { QStencilTest::QStencilTest(QNode *parent) : QRenderState(*new QStencilTestPrivate, parent) { + Q_D(QStencilTest); + + const auto resend = [d]() { d->resendArguments(); }; + + (void) connect(d->m_front, &QStencilTestArguments::comparisonMaskChanged, resend); + (void) connect(d->m_front, &QStencilTestArguments::faceModeChanged, resend); + (void) connect(d->m_front, &QStencilTestArguments::referenceValueChanged, resend); + (void) connect(d->m_front, &QStencilTestArguments::stencilFunctionChanged, resend); + + (void) connect(d->m_back, &QStencilTestArguments::comparisonMaskChanged, resend); + (void) connect(d->m_back, &QStencilTestArguments::faceModeChanged, resend); + (void) connect(d->m_back, &QStencilTestArguments::referenceValueChanged, resend); + (void) connect(d->m_back, &QStencilTestArguments::stencilFunctionChanged, resend); } /*! \internal */ @@ -113,6 +127,30 @@ QStencilTest::~QStencilTest() { } +/*! \internal */ +void QStencilTestPrivate::resendArguments() +{ + auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(m_id); + QStencilTestData data; + fillData(data); + e->setPropertyName("arguments"); + e->setValue(QVariant::fromValue(data)); + notifyObservers(e); +} + +/*! \internal */ +void QStencilTestPrivate::fillData(QStencilTestData &data) const +{ + data.front.face = m_front->faceMode(); + data.front.comparisonMask = m_front->comparisonMask(); + data.front.referenceValue = m_front->referenceValue(); + data.front.stencilFunction = m_front->stencilFunction(); + data.back.face = m_back->faceMode(); + data.back.comparisonMask = m_back->comparisonMask(); + data.back.referenceValue = m_back->referenceValue(); + data.back.stencilFunction = m_back->stencilFunction(); +} + QStencilTestArguments *QStencilTest::front() const { Q_D(const QStencilTest); @@ -128,16 +166,7 @@ QStencilTestArguments *QStencilTest::back() const Qt3DCore::QNodeCreatedChangeBasePtr QStencilTest::createNodeCreationChange() const { auto creationChange = QRenderStateCreatedChangePtr<QStencilTestData>::create(this); - auto &data = creationChange->data; - Q_D(const QStencilTest); - data.front.face = d->m_front->faceMode(); - data.front.comparisonMask = d->m_front->comparisonMask(); - data.front.referenceValue = d->m_front->referenceValue(); - data.front.stencilFunction = d->m_front->stencilFunction(); - data.back.face = d->m_back->faceMode(); - data.back.comparisonMask = d->m_back->comparisonMask(); - data.back.referenceValue = d->m_back->referenceValue(); - data.back.stencilFunction = d->m_back->stencilFunction(); + d_func()->fillData(creationChange->data); return creationChange; } diff --git a/src/render/renderstates/qstenciltest_p.h b/src/render/renderstates/qstenciltest_p.h index fc17cfde8..838ba5bc0 100644 --- a/src/render/renderstates/qstenciltest_p.h +++ b/src/render/renderstates/qstenciltest_p.h @@ -58,6 +58,12 @@ QT_BEGIN_NAMESPACE namespace Qt3DRender { +struct QStencilTestData +{ + QStencilTestArgumentsData front; + QStencilTestArgumentsData back; +}; + class QT3DRENDERSHARED_PRIVATE_EXPORT QStencilTestPrivate : public QRenderStatePrivate { public: @@ -71,16 +77,15 @@ public: Q_DECLARE_PUBLIC(QStencilTest) QStencilTestArguments *m_front; QStencilTestArguments *m_back; -}; -struct QStencilTestData -{ - QStencilTestArgumentsData front; - QStencilTestArgumentsData back; + void resendArguments(); + void fillData(QStencilTestData &data) const; }; } // namespace Qt3DRender QT_END_NAMESPACE +Q_DECLARE_METATYPE(Qt3DRender::QStencilTestData) + #endif // QT3DRENDER_QSTENCILTEST_P_H diff --git a/src/render/renderstates/renderstates.cpp b/src/render/renderstates/renderstates.cpp index d94191a13..d5e12aeab 100644 --- a/src/render/renderstates/renderstates.cpp +++ b/src/render/renderstates/renderstates.cpp @@ -43,8 +43,11 @@ #include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DRender/qrenderstate.h> #include <Qt3DRender/qcullface.h> +#include <Qt3DRender/qpointsize.h> #include <Qt3DRender/private/graphicscontext_p.h> +#include <Qt3DRender/private/qstenciloperation_p.h> +#include <Qt3DRender/private/qstenciltest_p.h> QT_BEGIN_NAMESPACE @@ -102,7 +105,7 @@ void BlendEquation::apply(GraphicsContext *gc) const void BlendEquation::updateProperty(const char *name, const QVariant &value) { - if (name == QByteArrayLiteral("mode")) std::get<0>(m_values) = value.toInt(); + if (name == QByteArrayLiteral("blendFunction")) std::get<0>(m_values) = value.toInt(); } void AlphaFunc::apply(GraphicsContext* gc) const @@ -110,6 +113,14 @@ void AlphaFunc::apply(GraphicsContext* gc) const gc->alphaTest(std::get<0>(m_values), std::get<1>(m_values)); } +void AlphaFunc::updateProperty(const char *name, const QVariant &value) +{ + if (name == QByteArrayLiteral("alphaFunction")) + std::get<0>(m_values) = value.toInt(); + if (name == QByteArrayLiteral("referenceValue")) + std::get<1>(m_values) = value.toFloat(); +} + void MSAAEnabled::apply(GraphicsContext *gc) const { gc->setMSAAEnabled(std::get<0>(m_values)); @@ -128,7 +139,7 @@ void DepthTest::apply(GraphicsContext *gc) const void DepthTest::updateProperty(const char *name, const QVariant &value) { - if (name == QByteArrayLiteral("func")) std::get<0>(m_values) = value.toInt(); + if (name == QByteArrayLiteral("depthFunction")) std::get<0>(m_values) = value.toInt(); } void CullFace::apply(GraphicsContext *gc) const @@ -192,6 +203,19 @@ void StencilTest::apply(GraphicsContext *gc) const gc->openGLContext()->functions()->glStencilFuncSeparate(GL_BACK, std::get<3>(m_values), std::get<4>(m_values), std::get<5>(m_values)); } +void StencilTest::updateProperty(const char *name, const QVariant &value) +{ + if (name == QByteArrayLiteral("arguments")) { + const QStencilTestData data = value.value<QStencilTestData>(); + std::get<0>(m_values) = data.front.stencilFunction; + std::get<1>(m_values) = data.front.referenceValue; + std::get<2>(m_values) = data.front.comparisonMask; + std::get<3>(m_values) = data.back.stencilFunction; + std::get<4>(m_values) = data.back.referenceValue; + std::get<5>(m_values) = data.back.comparisonMask; + } +} + void AlphaCoverage::apply(GraphicsContext *gc) const { gc->setAlphaCoverageEnabled(true); @@ -204,7 +228,7 @@ void PointSize::apply(GraphicsContext *gc) const void PointSize::updateProperty(const char *name, const QVariant &value) { - if (name == QByteArrayLiteral("specification")) std::get<0>(m_values) = value.toBool(); + if (name == QByteArrayLiteral("sizeMode")) std::get<0>(m_values) = (value.toInt() == QPointSize::Programmable); else if (name == QByteArrayLiteral("value")) std::get<1>(m_values) = value.toFloat(); } @@ -216,8 +240,8 @@ void PolygonOffset::apply(GraphicsContext *gc) const void PolygonOffset::updateProperty(const char *name, const QVariant &value) { - if (name == QByteArrayLiteral("factor")) std::get<0>(m_values) = value.toFloat(); - else if (name == QByteArrayLiteral("units")) std::get<1>(m_values) = value.toFloat(); + if (name == QByteArrayLiteral("scaleFactor")) std::get<0>(m_values) = value.toFloat(); + else if (name == QByteArrayLiteral("depthSteps")) std::get<1>(m_values) = value.toFloat(); } void ColorMask::apply(GraphicsContext *gc) const @@ -227,10 +251,10 @@ void ColorMask::apply(GraphicsContext *gc) const void ColorMask::updateProperty(const char *name, const QVariant &value) { - if (name == QByteArrayLiteral("red")) std::get<0>(m_values) = value.toBool(); - else if (name == QByteArrayLiteral("green")) std::get<1>(m_values) = value.toBool(); - else if (name == QByteArrayLiteral("blue")) std::get<2>(m_values) = value.toBool(); - else if (name == QByteArrayLiteral("alpha")) std::get<3>(m_values) = value.toBool(); + if (name == QByteArrayLiteral("redMasked")) std::get<0>(m_values) = value.toBool(); + else if (name == QByteArrayLiteral("greenMasked")) std::get<1>(m_values) = value.toBool(); + else if (name == QByteArrayLiteral("blueMasked")) std::get<2>(m_values) = value.toBool(); + else if (name == QByteArrayLiteral("alphaMasked")) std::get<3>(m_values) = value.toBool(); } void ClipPlane::apply(GraphicsContext *gc) const @@ -257,6 +281,19 @@ void StencilOp::apply(GraphicsContext *gc) const gc->openGLContext()->functions()->glStencilOpSeparate(GL_BACK, std::get<3>(m_values), std::get<4>(m_values), std::get<5>(m_values)); } +void StencilOp::updateProperty(const char *name, const QVariant &value) +{ + if (name == QByteArrayLiteral("arguments")) { + const QStencilOperationData data = value.value<QStencilOperationData>(); + std::get<0>(m_values) = data.front.stencilTestFailureOperation; + std::get<1>(m_values) = data.front.depthTestFailureOperation; + std::get<2>(m_values) = data.front.allTestsPassOperation; + std::get<3>(m_values) = data.back.stencilTestFailureOperation; + std::get<4>(m_values) = data.back.depthTestFailureOperation; + std::get<5>(m_values) = data.back.allTestsPassOperation; + } +} + void StencilMask::apply(GraphicsContext *gc) const { gc->openGLContext()->functions()->glStencilMaskSeparate(GL_FRONT, std::get<0>(m_values)); @@ -265,8 +302,8 @@ void StencilMask::apply(GraphicsContext *gc) const void StencilMask::updateProperty(const char *name, const QVariant &value) { - if (name == QByteArrayLiteral("frontMask")) std::get<0>(m_values) = value.toInt(); - else if (name == QByteArrayLiteral("backMask")) std::get<1>(m_values) = value.toInt(); + if (name == QByteArrayLiteral("frontOutputMask")) std::get<0>(m_values) = value.toInt(); + else if (name == QByteArrayLiteral("backOutputMask")) std::get<1>(m_values) = value.toInt(); } #ifndef GL_LINE_SMOOTH diff --git a/src/render/renderstates/renderstates_p.h b/src/render/renderstates/renderstates_p.h index b503067a9..2b1af1c4c 100644 --- a/src/render/renderstates/renderstates_p.h +++ b/src/render/renderstates/renderstates_p.h @@ -78,6 +78,7 @@ class Q_AUTOTEST_EXPORT AlphaFunc : public GenericState<AlphaFunc, AlphaTestMask { public: void apply(GraphicsContext *gc) const Q_DECL_OVERRIDE; + void updateProperty(const char *name, const QVariant &value) Q_DECL_OVERRIDE; }; class Q_AUTOTEST_EXPORT MSAAEnabled : public GenericState<MSAAEnabled, MSAAEnabledStateMask, GLboolean> @@ -132,6 +133,7 @@ class Q_AUTOTEST_EXPORT StencilTest : public GenericState<StencilTest, StencilTe { public: void apply(GraphicsContext *gc) const Q_DECL_OVERRIDE; + void updateProperty(const char *name, const QVariant &value) Q_DECL_OVERRIDE; }; class Q_AUTOTEST_EXPORT AlphaCoverage : public GenericState<AlphaCoverage, AlphaCoverageStateMask> @@ -178,6 +180,7 @@ class Q_AUTOTEST_EXPORT StencilOp : public GenericState<StencilOp, StencilOpMask { public: void apply(GraphicsContext *gc) const Q_DECL_FINAL; + void updateProperty(const char *name, const QVariant &value) Q_DECL_OVERRIDE; }; class Q_AUTOTEST_EXPORT StencilMask : public GenericState<StencilMask, StencilWriteStateMask, uint, uint> diff --git a/src/render/renderstates/statevariant_p.h b/src/render/renderstates/statevariant_p.h index 55ec23899..393e4156c 100644 --- a/src/render/renderstates/statevariant_p.h +++ b/src/render/renderstates/statevariant_p.h @@ -58,7 +58,7 @@ QT_BEGIN_NAMESPACE namespace Qt3DRender { namespace Render { -struct StateVariant +struct Q_AUTOTEST_EXPORT StateVariant { StateMask type; diff --git a/src/render/services/vsyncframeadvanceservice.cpp b/src/render/services/vsyncframeadvanceservice.cpp index 533b0fba1..880985aea 100644 --- a/src/render/services/vsyncframeadvanceservice.cpp +++ b/src/render/services/vsyncframeadvanceservice.cpp @@ -52,20 +52,22 @@ namespace Render { class VSyncFrameAdvanceServicePrivate Q_DECL_FINAL : public Qt3DCore::QAbstractFrameAdvanceServicePrivate { public: - VSyncFrameAdvanceServicePrivate() + explicit VSyncFrameAdvanceServicePrivate(bool drivenByRenderThread) : QAbstractFrameAdvanceServicePrivate(QStringLiteral("Renderer Aspect Frame Advance Service - aligned with vsync")) , m_semaphore(0) , m_elapsedTimeSincePreviousFrame(0) + , m_drivenByRenderThread(drivenByRenderThread) { } QSemaphore m_semaphore; QElapsedTimer m_elapsed; quint64 m_elapsedTimeSincePreviousFrame; + bool m_drivenByRenderThread; }; -VSyncFrameAdvanceService::VSyncFrameAdvanceService() - : QAbstractFrameAdvanceService(*new VSyncFrameAdvanceServicePrivate()) +VSyncFrameAdvanceService::VSyncFrameAdvanceService(bool drivenByRenderThread) + : QAbstractFrameAdvanceService(*new VSyncFrameAdvanceServicePrivate(drivenByRenderThread)) { } @@ -77,7 +79,17 @@ VSyncFrameAdvanceService::~VSyncFrameAdvanceService() qint64 VSyncFrameAdvanceService::waitForNextFrame() { Q_D(VSyncFrameAdvanceService); - d->m_semaphore.acquire(1); + + // When rendering with Scene3D, we always want to acquire the available + // amount + 1 to handle the cases where for some reason proceedToNextFrame + // is being called more than once between calls to waitForNextFrame This + // could be the case when resizing the window + + // When Qt3D is driving rendering however, this shouldn't happen + if (d->m_drivenByRenderThread) + d->m_semaphore.acquire(1); + else + d->m_semaphore.acquire(d->m_semaphore.available() + 1); const quint64 currentTime = d->m_elapsed.nsecsElapsed(); qCDebug(VSyncAdvanceService) << "Elapsed nsecs since last call " << currentTime - d->m_elapsedTimeSincePreviousFrame; diff --git a/src/render/services/vsyncframeadvanceservice_p.h b/src/render/services/vsyncframeadvanceservice_p.h index 98daebf81..f33d41b98 100644 --- a/src/render/services/vsyncframeadvanceservice_p.h +++ b/src/render/services/vsyncframeadvanceservice_p.h @@ -64,7 +64,7 @@ class VSyncFrameAdvanceServicePrivate; class Q_AUTOTEST_EXPORT VSyncFrameAdvanceService Q_DECL_FINAL : public Qt3DCore::QAbstractFrameAdvanceService { public: - VSyncFrameAdvanceService(); + explicit VSyncFrameAdvanceService(bool drivenByRenderThread); ~VSyncFrameAdvanceService(); qint64 waitForNextFrame() Q_DECL_FINAL; diff --git a/src/render/texture/qpaintedtextureimage.cpp b/src/render/texture/qpaintedtextureimage.cpp index 4d03eb809..db03b26b9 100644 --- a/src/render/texture/qpaintedtextureimage.cpp +++ b/src/render/texture/qpaintedtextureimage.cpp @@ -88,7 +88,7 @@ void QPaintedTextureImagePrivate::repaint() painter.end(); ++m_generation; - m_currentGenerator.reset(new QPaintedTextureImageDataGenerator(*m_image.data(), m_generation, q_func()->id())); + m_currentGenerator = QSharedPointer<QPaintedTextureImageDataGenerator>::create(*m_image.data(), m_generation, q_func()->id()); q_func()->notifyDataGeneratorChanged(); } |