From 4b83e2ee155c9ebf71e2fc46ab9abdb40bbb1061 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Fri, 2 Jun 2017 16:19:17 +0200 Subject: RenderStates: rework to split node and rendering part The apply method was removed from GenericState and its subclasses. This allows to keep the GenericStates in the aspect part and let the renderer perform the right calls based on the state class it is provided with. Change-Id: I9c3ac04b4eb489e7443e67615e35e850c0aba07f Task-number: QTBUG-61151 Reviewed-by: Mike Krus --- .../opengl/graphicshelpers/submissioncontext.cpp | 382 ++++++++++++++++++++- .../opengl/graphicshelpers/submissioncontext_p.h | 5 + src/render/renderers/opengl/renderer/renderer.cpp | 6 +- .../opengl/renderstates/renderstateset.cpp | 266 -------------- .../opengl/renderstates/renderstateset_p.h | 17 +- src/render/renderstates/genericstate_p.h | 6 +- src/render/renderstates/renderstatenode.cpp | 191 ++++++++++- src/render/renderstates/renderstates.cpp | 144 -------- src/render/renderstates/renderstates_p.h | 25 +- src/render/renderstates/statevariant.cpp | 68 ---- src/render/renderstates/statevariant_p.h | 8 +- 11 files changed, 591 insertions(+), 527 deletions(-) (limited to 'src/render') diff --git a/src/render/renderers/opengl/graphicshelpers/submissioncontext.cpp b/src/render/renderers/opengl/graphicshelpers/submissioncontext.cpp index df7d61902..2279aeacb 100644 --- a/src/render/renderers/opengl/graphicshelpers/submissioncontext.cpp +++ b/src/render/renderers/opengl/graphicshelpers/submissioncontext.cpp @@ -41,6 +41,7 @@ #include #include +#include #include #include #include @@ -139,6 +140,192 @@ void copyGLFramebufferDataToImage(QImage &img, const uchar *srcData, uint stride } } +// Render States Helpers +template +void applyStateHelper(const GenericState *state, SubmissionContext *gc) +{ +} + +template<> +void applyStateHelper(const AlphaFunc *state, SubmissionContext *gc) +{ + const auto values = state->values(); + gc->alphaTest(std::get<0>(values), std::get<1>(values)); +} + +template<> +void applyStateHelper(const BlendEquationArguments *state, SubmissionContext *gc) +{ + const auto values = state->values(); + // Un-indexed BlendEquationArguments -> Use normal GL1.0 functions + if (std::get<5>(values) < 0) { + if (std::get<4>(values)) { + gc->openGLContext()->functions()->glEnable(GL_BLEND); + gc->openGLContext()->functions()->glBlendFuncSeparate(std::get<0>(values), std::get<1>(values), std::get<2>(values), std::get<3>(values)); + } else { + gc->openGLContext()->functions()->glDisable(GL_BLEND); + } + } + // BlendEquationArguments for a particular Draw Buffer. Different behaviours for + // (1) 3.0-3.3: only enablei/disablei supported. + // (2) 4.0+: all operations supported. + // We just ignore blend func parameter for (1), so no warnings get + // printed. + else { + if (std::get<4>(values)) { + gc->enablei(GL_BLEND, std::get<5>(values)); + if (gc->supportsDrawBuffersBlend()) { + gc->blendFuncSeparatei(std::get<5>(values), std::get<0>(values), std::get<1>(values), std::get<2>(values), std::get<3>(values)); + } + } else { + gc->disablei(GL_BLEND, std::get<5>(values)); + } + } +} + +template<> +void applyStateHelper(const BlendEquation *state, SubmissionContext *gc) +{ + gc->blendEquation(std::get<0>(state->values())); +} + +template<> +void applyStateHelper(const MSAAEnabled *state, SubmissionContext *gc) +{ + gc->setMSAAEnabled(std::get<0>(state->values())); +} + + +template<> +void applyStateHelper(const DepthTest *state, SubmissionContext *gc) +{ + gc->depthTest(std::get<0>(state->values())); +} + + +template<> +void applyStateHelper(const NoDepthMask *state, SubmissionContext *gc) +{ + gc->depthMask(std::get<0>(state->values())); +} + + +template<> +void applyStateHelper(const CullFace *state, SubmissionContext *gc) +{ + const auto values = state->values(); + if (std::get<0>(values) == QCullFace::NoCulling) { + gc->openGLContext()->functions()->glDisable(GL_CULL_FACE); + } else { + gc->openGLContext()->functions()->glEnable(GL_CULL_FACE); + gc->openGLContext()->functions()->glCullFace(std::get<0>(values)); + } +} + +template<> +void applyStateHelper(const FrontFace *state, SubmissionContext *gc) +{ + gc->frontFace(std::get<0>(state->values())); +} + +template<> +void applyStateHelper(const ScissorTest *state, SubmissionContext *gc) +{ + const auto values = state->values(); + gc->openGLContext()->functions()->glEnable(GL_SCISSOR_TEST); + gc->openGLContext()->functions()->glScissor(std::get<0>(values), std::get<1>(values), std::get<2>(values), std::get<3>(values)); +} + +template<> +void applyStateHelper(const StencilTest *state, SubmissionContext *gc) +{ + const auto values = state->values(); + gc->openGLContext()->functions()->glEnable(GL_STENCIL_TEST); + gc->openGLContext()->functions()->glStencilFuncSeparate(GL_FRONT, std::get<0>(values), std::get<1>(values), std::get<2>(values)); + gc->openGLContext()->functions()->glStencilFuncSeparate(GL_BACK, std::get<3>(values), std::get<4>(values), std::get<5>(values)); +} + +template<> +void applyStateHelper(const AlphaCoverage *, SubmissionContext *gc) +{ + gc->setAlphaCoverageEnabled(true); +} + +template<> +void applyStateHelper(const PointSize *state, SubmissionContext *gc) +{ + const auto values = state->values(); + gc->pointSize(std::get<0>(values), std::get<1>(values)); +} + + +template<> +void applyStateHelper(const PolygonOffset *state, SubmissionContext *gc) +{ + const auto values = state->values(); + gc->openGLContext()->functions()->glEnable(GL_POLYGON_OFFSET_FILL); + gc->openGLContext()->functions()->glPolygonOffset(std::get<0>(values), std::get<1>(values)); +} + +template<> +void applyStateHelper(const ColorMask *state, SubmissionContext *gc) +{ + const auto values = state->values(); + gc->openGLContext()->functions()->glColorMask(std::get<0>(values), std::get<1>(values), std::get<2>(values), std::get<3>(values)); +} + +template<> +void applyStateHelper(const ClipPlane *state, SubmissionContext *gc) +{ + const auto values = state->values(); + gc->enableClipPlane(std::get<0>(values)); + gc->setClipPlane(std::get<0>(values), std::get<1>(values), std::get<2>(values)); +} + +template<> +void applyStateHelper(const SeamlessCubemap *, SubmissionContext *gc) +{ + gc->setSeamlessCubemap(true); +} + +template<> +void applyStateHelper(const StencilOp *state, SubmissionContext *gc) +{ + const auto values = state->values(); + gc->openGLContext()->functions()->glStencilOpSeparate(GL_FRONT, std::get<0>(values), std::get<1>(values), std::get<2>(values)); + gc->openGLContext()->functions()->glStencilOpSeparate(GL_BACK, std::get<3>(values), std::get<4>(values), std::get<5>(values)); +} + +template<> +void applyStateHelper(const StencilMask *state, SubmissionContext *gc) +{ + const auto values = state->values(); + gc->openGLContext()->functions()->glStencilMaskSeparate(GL_FRONT, std::get<0>(values)); + gc->openGLContext()->functions()->glStencilMaskSeparate(GL_BACK, std::get<1>(values)); +} + +template<> +void applyStateHelper(const Dithering *, SubmissionContext *gc) +{ + gc->openGLContext()->functions()->glEnable(GL_DITHER); +} + +#ifndef GL_LINE_SMOOTH +#define GL_LINE_SMOOTH 0x0B20 +#endif + +template<> +void applyStateHelper(const LineWidth *state, SubmissionContext *gc) +{ + const auto values = state->values(); + if (std::get<1>(values)) + gc->openGLContext()->functions()->glEnable(GL_LINE_SMOOTH); + else + gc->openGLContext()->functions()->glDisable(GL_LINE_SMOOTH); + + gc->openGLContext()->functions()->glLineWidth(std::get<0>(values)); +} + } // anonymous unsigned int nextFreeContextId() @@ -789,7 +976,7 @@ void SubmissionContext::setCurrentStateSet(RenderStateSet *ss) if (ss == m_stateSet) return; if (ss) - ss->apply(this); + applyStateSet(ss); m_stateSet = ss; } @@ -798,6 +985,199 @@ RenderStateSet *SubmissionContext::currentStateSet() const return m_stateSet; } +void SubmissionContext::applyState(const StateVariant &stateVariant) +{ + switch (stateVariant.type) { + + case AlphaCoverageStateMask: { + applyStateHelper(static_cast(stateVariant.constState()), this); + break; + } + case AlphaTestMask: { + applyStateHelper(static_cast(stateVariant.constState()), this); + break; + } + case BlendStateMask: { + applyStateHelper(static_cast(stateVariant.constState()), this); + break; + } + case BlendEquationArgumentsMask: { + applyStateHelper(static_cast(stateVariant.constState()), this); + break; + } + case MSAAEnabledStateMask: { + applyStateHelper(static_cast(stateVariant.constState()), this); + break; + } + + case CullFaceStateMask: { + applyStateHelper(static_cast(stateVariant.constState()), this); + break; + } + + case DepthWriteStateMask: { + applyStateHelper(static_cast(stateVariant.constState()), this); + break; + } + + case DepthTestStateMask: { + applyStateHelper(static_cast(stateVariant.constState()), this); + break; + } + + case FrontFaceStateMask: { + applyStateHelper(static_cast(stateVariant.constState()), this); + break; + } + + case ScissorStateMask: { + applyStateHelper(static_cast(stateVariant.constState()), this); + break; + } + + case StencilTestStateMask: { + applyStateHelper(static_cast(stateVariant.constState()), this); + break; + } + + case PointSizeMask: { + applyStateHelper(static_cast(stateVariant.constState()), this); + break; + } + + case PolygonOffsetStateMask: { + applyStateHelper(static_cast(stateVariant.constState()), this); + break; + } + + case ColorStateMask: { + applyStateHelper(static_cast(stateVariant.constState()), this); + break; + } + + case ClipPlaneMask: { + applyStateHelper(static_cast(stateVariant.constState()), this); + break; + } + + case SeamlessCubemapMask: { + applyStateHelper(static_cast(stateVariant.constState()), this); + break; + } + + case StencilOpMask: { + applyStateHelper(static_cast(stateVariant.constState()), this); + break; + } + + case StencilWriteStateMask: { + applyStateHelper(static_cast(stateVariant.constState()), this); + break; + } + + case DitheringStateMask: { + applyStateHelper(static_cast(stateVariant.constState()), this); + break; + } + + case LineWidthMask: { + applyStateHelper(static_cast(stateVariant.constState()), this); + break; + } + default: + Q_UNREACHABLE(); + } +} + +void SubmissionContext::resetMasked(qint64 maskOfStatesToReset) +{ + // TO DO -> Call gcHelper methods instead of raw GL + // QOpenGLFunctions shouldn't be used here directly + QOpenGLFunctions *funcs = m_gl->functions(); + + if (maskOfStatesToReset & ScissorStateMask) + funcs->glDisable(GL_SCISSOR_TEST); + + if (maskOfStatesToReset & BlendStateMask) + funcs->glDisable(GL_BLEND); + + if (maskOfStatesToReset & StencilWriteStateMask) + funcs->glStencilMask(0); + + if (maskOfStatesToReset & StencilTestStateMask) + funcs->glDisable(GL_STENCIL_TEST); + + if (maskOfStatesToReset & DepthTestStateMask) + funcs->glDisable(GL_DEPTH_TEST); + + if (maskOfStatesToReset & DepthWriteStateMask) + funcs->glDepthMask(GL_TRUE); // reset to default + + if (maskOfStatesToReset & FrontFaceStateMask) + funcs->glFrontFace(GL_CCW); // reset to default + + if (maskOfStatesToReset & CullFaceStateMask) + funcs->glDisable(GL_CULL_FACE); + + if (maskOfStatesToReset & DitheringStateMask) + funcs->glDisable(GL_DITHER); + + if (maskOfStatesToReset & AlphaCoverageStateMask) + setAlphaCoverageEnabled(false); + + if (maskOfStatesToReset & PointSizeMask) + pointSize(false, 1.0f); // reset to default + + if (maskOfStatesToReset & PolygonOffsetStateMask) + funcs->glDisable(GL_POLYGON_OFFSET_FILL); + + if (maskOfStatesToReset & ColorStateMask) + funcs->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + + if (maskOfStatesToReset & ClipPlaneMask) { + GLint max = maxClipPlaneCount(); + for (GLint i = 0; i < max; ++i) + disableClipPlane(i); + } + + if (maskOfStatesToReset & SeamlessCubemapMask) + setSeamlessCubemap(false); + + if (maskOfStatesToReset & StencilOpMask) + funcs->glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + + if (maskOfStatesToReset & LineWidthMask) + funcs->glLineWidth(1.0f); +} + +void SubmissionContext::applyStateSet(RenderStateSet *ss) +{ + RenderStateSet* previousStates = currentStateSet(); + + const StateMaskSet invOurState = ~ss->stateMask(); + // generate a mask for each set bit in previous, where we do not have + // the corresponding bit set. + + StateMaskSet stateToReset = 0; + if (previousStates) { + stateToReset = previousStates->stateMask() & invOurState; + qCDebug(RenderStates) << "previous states " << QString::number(previousStates->stateMask(), 2); + } + qCDebug(RenderStates) << " current states " << QString::number(ss->stateMask(), 2) << "inverse " << QString::number(invOurState, 2) << " -> states to change: " << QString::number(stateToReset, 2); + + // Reset states that aren't active in the current state set + resetMasked(stateToReset); + + // Apply states that weren't in the previous state or that have + // different values + const QVector statesToSet = ss->states(); + for (const StateVariant &ds : statesToSet) { + if (previousStates && previousStates->contains(ds)) + continue; + applyState(ds); + } +} + void SubmissionContext::clearColor(const QColor &color) { if (m_currClearColorValue != color) { diff --git a/src/render/renderers/opengl/graphicshelpers/submissioncontext_p.h b/src/render/renderers/opengl/graphicshelpers/submissioncontext_p.h index 8efdcbc63..2881812e5 100644 --- a/src/render/renderers/opengl/graphicshelpers/submissioncontext_p.h +++ b/src/render/renderers/opengl/graphicshelpers/submissioncontext_p.h @@ -79,6 +79,7 @@ class AttachmentPack; class Attribute; class Buffer; class ShaderManager; +struct StateVariant; enum TextureScope { @@ -152,6 +153,10 @@ public: // RenderState void setCurrentStateSet(RenderStateSet* ss); RenderStateSet *currentStateSet() const; + void applyState(const StateVariant &state); + + void resetMasked(qint64 maskOfStatesToReset); + void applyStateSet(RenderStateSet *ss); // Wrappers void clearColor(const QColor &color); diff --git a/src/render/renderers/opengl/renderer/renderer.cpp b/src/render/renderers/opengl/renderer/renderer.cpp index 2611fb6cc..85ac4d2ec 100644 --- a/src/render/renderers/opengl/renderer/renderer.cpp +++ b/src/render/renderers/opengl/renderer/renderer.cpp @@ -229,9 +229,9 @@ Renderer::Renderer(QRenderAspect::RenderType type) m_filterCompatibleTechniqueJob->setRenderer(this); m_defaultRenderStateSet = new RenderStateSet; - m_defaultRenderStateSet->addState(RenderStateSet::createState(GL_LESS)); - m_defaultRenderStateSet->addState(RenderStateSet::createState(GL_BACK)); - m_defaultRenderStateSet->addState(RenderStateSet::createState(true, true, true, true)); + m_defaultRenderStateSet->addState(StateVariant::createState(GL_LESS)); + m_defaultRenderStateSet->addState(StateVariant::createState(GL_BACK)); + m_defaultRenderStateSet->addState(StateVariant::createState(true, true, true, true)); } Renderer::~Renderer() diff --git a/src/render/renderers/opengl/renderstates/renderstateset.cpp b/src/render/renderers/opengl/renderstates/renderstateset.cpp index bf84b0e1c..f7fc279a1 100644 --- a/src/render/renderers/opengl/renderstates/renderstateset.cpp +++ b/src/render/renderers/opengl/renderstates/renderstateset.cpp @@ -45,50 +45,9 @@ #include #include -#include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - QT_BEGIN_NAMESPACE namespace Qt3DRender { @@ -139,33 +98,6 @@ int RenderStateSet::changeCost(RenderStateSet *previousState) return cost; } -void RenderStateSet::apply(SubmissionContext *gc) -{ - RenderStateSet* previousStates = gc->currentStateSet(); - - const StateMaskSet invOurState = ~stateMask(); - // generate a mask for each set bit in previous, where we do not have - // the corresponding bit set. - - StateMaskSet stateToReset = 0; - if (previousStates) { - stateToReset = previousStates->stateMask() & invOurState; - qCDebug(RenderStates) << "previous states " << QString::number(previousStates->stateMask(), 2); - } - qCDebug(RenderStates) << " current states " << QString::number(stateMask(), 2) << "inverse " << QString::number(invOurState, 2) << " -> states to change: " << QString::number(stateToReset, 2); - - // Reset states that aren't active in the current state set - resetMasked(stateToReset, gc); - - // Apply states that weren't in the previous state or that have - // different values - for (const StateVariant &ds : qAsConst(m_states)) { - if (previousStates && previousStates->contains(ds)) - continue; - ds.apply(gc); - } -} - StateMaskSet RenderStateSet::stateMask() const { return m_stateMask; @@ -176,67 +108,6 @@ void RenderStateSet::merge(RenderStateSet *other) m_stateMask |= other->stateMask(); } -void RenderStateSet::resetMasked(StateMaskSet maskOfStatesToReset, SubmissionContext *gc) -{ - // TO DO -> Call gcHelper methods instead of raw GL - // QOpenGLFunctions shouldn't be used here directly - QOpenGLFunctions *funcs = gc->openGLContext()->functions(); - - if (maskOfStatesToReset & ScissorStateMask) - funcs->glDisable(GL_SCISSOR_TEST); - - if (maskOfStatesToReset & BlendStateMask) - funcs->glDisable(GL_BLEND); - - if (maskOfStatesToReset & StencilWriteStateMask) - funcs->glStencilMask(0); - - if (maskOfStatesToReset & StencilTestStateMask) - funcs->glDisable(GL_STENCIL_TEST); - - if (maskOfStatesToReset & DepthTestStateMask) - funcs->glDisable(GL_DEPTH_TEST); - - if (maskOfStatesToReset & DepthWriteStateMask) - funcs->glDepthMask(GL_TRUE); // reset to default - - if (maskOfStatesToReset & FrontFaceStateMask) - funcs->glFrontFace(GL_CCW); // reset to default - - if (maskOfStatesToReset & CullFaceStateMask) - funcs->glDisable(GL_CULL_FACE); - - if (maskOfStatesToReset & DitheringStateMask) - funcs->glDisable(GL_DITHER); - - if (maskOfStatesToReset & AlphaCoverageStateMask) - gc->setAlphaCoverageEnabled(false); - - if (maskOfStatesToReset & PointSizeMask) - gc->pointSize(false, 1.0f); // reset to default - - if (maskOfStatesToReset & PolygonOffsetStateMask) - funcs->glDisable(GL_POLYGON_OFFSET_FILL); - - if (maskOfStatesToReset & ColorStateMask) - funcs->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - - if (maskOfStatesToReset & ClipPlaneMask) { - GLint max = gc->maxClipPlaneCount(); - for (GLint i = 0; i < max; ++i) - gc->disableClipPlane(i); - } - - if (maskOfStatesToReset & SeamlessCubemapMask) - gc->setSeamlessCubemap(false); - - if (maskOfStatesToReset & StencilOpMask) - funcs->glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - - if (maskOfStatesToReset & LineWidthMask) - funcs->glLineWidth(1.0f); -} - bool RenderStateSet::contains(const StateVariant &ds) const { // trivial reject using the state mask bits @@ -250,143 +121,6 @@ bool RenderStateSet::contains(const StateVariant &ds) const return false; } -StateVariant RenderStateSet::initializeStateFromPeer(const Qt3DRender::QRenderStateCreatedChangeBasePtr change) -{ - switch (change->renderStateType()) { - case AlphaCoverageStateMask: { - return RenderStateSet::createState(); - } - - case AlphaTestMask: { - const auto typedChange = qSharedPointerCast>(change); - const auto &data = typedChange->data; - return RenderStateSet::createState(data.alphaFunction, data.referenceValue); - } - - case BlendStateMask: { - const auto typedChange = qSharedPointerCast>(change); - const auto &data = typedChange->data; - return RenderStateSet::createState(data.blendFunction); - } - - case BlendEquationArgumentsMask: { - const auto typedChange = qSharedPointerCast>(change); - const auto &data = typedChange->data; - return RenderStateSet::createState( - data.sourceRgb, data.destinationRgb, - data.sourceAlpha, data.destinationAlpha, - change->isNodeEnabled(), - data.bufferIndex); - } - - case MSAAEnabledStateMask: { - return RenderStateSet::createState(change->isNodeEnabled()); - } - - case CullFaceStateMask: { - const auto typedChange = qSharedPointerCast>(change); - const auto &data = typedChange->data; - return RenderStateSet::createState(data.mode); - } - - case DepthWriteStateMask: { - return RenderStateSet::createState(false); - } - - case DepthTestStateMask: { - const auto typedChange = qSharedPointerCast>(change); - const auto &data = typedChange->data; - return RenderStateSet::createState(data.depthFunction); - } - - case FrontFaceStateMask: { - const auto typedChange = qSharedPointerCast>(change); - const auto &data = typedChange->data; - return RenderStateSet::createState(data.direction); - } - - case ScissorStateMask: { - const auto typedChange = qSharedPointerCast>(change); - const auto &data = typedChange->data; - return RenderStateSet::createState(data.left, data.bottom, - data.width, data.height); - } - - case StencilTestStateMask: { - const auto typedChange = qSharedPointerCast>(change); - const auto &data = typedChange->data; - return RenderStateSet::createState(data.front.stencilFunction, - data.front.referenceValue, - data.front.comparisonMask, - data.back.stencilFunction, - data.back.referenceValue, - data.back.comparisonMask); - } - - case PointSizeMask: { - const auto typedChange = qSharedPointerCast>(change); - const auto &data = typedChange->data; - const bool isProgrammable = (data.sizeMode == QPointSize::Programmable); - return RenderStateSet::createState(isProgrammable, data.value); - } - - case PolygonOffsetStateMask: { - const auto typedChange = qSharedPointerCast>(change); - const auto &data = typedChange->data; - return RenderStateSet::createState(data.scaleFactor, data.depthSteps); - } - - case ColorStateMask: { - const auto typedChange = qSharedPointerCast>(change); - const auto &data = typedChange->data; - return RenderStateSet::createState(data.redMasked, data.greenMasked, - data.blueMasked, data.alphaMasked); - } - - case ClipPlaneMask: { - const auto typedChange = qSharedPointerCast>(change); - const auto &data = typedChange->data; - return RenderStateSet::createState(data.planeIndex, - data.normal, - data.distance); - } - - case SeamlessCubemapMask: { - return RenderStateSet::createState(); - } - - case StencilOpMask: { - const auto typedChange = qSharedPointerCast>(change); - const auto &data = typedChange->data; - return RenderStateSet::createState(data.front.stencilTestFailureOperation, - data.front.depthTestFailureOperation, - data.front.allTestsPassOperation, - data.back.stencilTestFailureOperation, - data.back.depthTestFailureOperation, - data.back.allTestsPassOperation); - } - - case StencilWriteStateMask: { - const auto typedChange = qSharedPointerCast>(change); - const auto &data = typedChange->data; - return RenderStateSet::createState(data.frontOutputMask, - data.backOutputMask); - } - - case LineWidthMask: { - const auto typedChange = qSharedPointerCast>(change); - const auto &data = typedChange->data; - return RenderStateSet::createState(data.value, data.smooth); - } - - // TODO: Fix Dithering state - case DitheringStateMask: - default: - Q_UNREACHABLE(); - return StateVariant(); - } -} - } // namespace Render } // namespace Qt3DRender diff --git a/src/render/renderers/opengl/renderstates/renderstateset_p.h b/src/render/renderers/opengl/renderstates/renderstateset_p.h index 58d46c7a6..09b58b859 100644 --- a/src/render/renderers/opengl/renderstates/renderstateset_p.h +++ b/src/render/renderers/opengl/renderstates/renderstateset_p.h @@ -65,7 +65,6 @@ class QRenderState; namespace Render { -class SubmissionContext; class RenderState; class RenderStateSet @@ -89,30 +88,18 @@ public: */ int changeCost(RenderStateSet* previousState); - void apply(SubmissionContext *gc); - StateMaskSet stateMask() const; void merge(RenderStateSet *other); - void resetMasked(StateMaskSet maskOfStatesToReset, SubmissionContext* gc); - - template - static StateVariant createState(Args... values) - { - State state; - state.set(values...); - return StateVariant::fromValue(state); - } - static StateVariant initializeStateFromPeer(const Qt3DRender::QRenderStateCreatedChangeBasePtr change); + QVector states() const { return m_states; } -private: /** * @brief contains - check if this set contains a matching piece of state * @param ds * @return */ bool contains(const StateVariant &ds) const; - +private: StateMaskSet m_stateMask; QVector m_states; }; diff --git a/src/render/renderstates/genericstate_p.h b/src/render/renderstates/genericstate_p.h index 236d36690..69c3dee15 100644 --- a/src/render/renderstates/genericstate_p.h +++ b/src/render/renderstates/genericstate_p.h @@ -78,7 +78,6 @@ class RenderStateImpl public: virtual ~RenderStateImpl() {} - virtual void apply(GraphicsContext* gc) const = 0; virtual StateMask mask() const = 0; virtual bool equalTo(const RenderStateImpl &renderState) const = 0; virtual void updateProperty(const char *name, const QVariant &value); @@ -110,6 +109,11 @@ public: return stateMask; } + std::tuple values() const + { + return m_values; + } + protected: std::tuple m_values; }; diff --git a/src/render/renderstates/renderstatenode.cpp b/src/render/renderstates/renderstatenode.cpp index d1698e4b6..52d5e20ce 100644 --- a/src/render/renderstates/renderstatenode.cpp +++ b/src/render/renderstates/renderstatenode.cpp @@ -38,13 +38,196 @@ #include #include #include -#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include QT_BEGIN_NAMESPACE namespace Qt3DRender { namespace Render { +namespace { + +StateVariant createStateImplementation(const Qt3DRender::QRenderStateCreatedChangeBasePtr renderStateChange) +{ + switch (renderStateChange->renderStateType()) { + + case AlphaCoverageStateMask: { + return StateVariant::createState(); + } + + case AlphaTestMask: { + const auto typedChange = qSharedPointerCast>(renderStateChange); + const auto &data = typedChange->data; + return StateVariant::createState(data.alphaFunction, data.referenceValue); + } + + case BlendStateMask: { + const auto typedChange = qSharedPointerCast>(renderStateChange); + const auto &data = typedChange->data; + return StateVariant::createState(data.blendFunction); + } + + case BlendEquationArgumentsMask: { + const auto typedChange = qSharedPointerCast>(renderStateChange); + const auto &data = typedChange->data; + return StateVariant::createState( + data.sourceRgb, data.destinationRgb, + data.sourceAlpha, data.destinationAlpha, + renderStateChange->isNodeEnabled(), + data.bufferIndex); + } + + case MSAAEnabledStateMask: { + return StateVariant::createState(renderStateChange->isNodeEnabled()); + } + + case CullFaceStateMask: { + const auto typedChange = qSharedPointerCast>(renderStateChange); + const auto &data = typedChange->data; + return StateVariant::createState(data.mode); + } + + case DepthWriteStateMask: { + return StateVariant::createState(false); + } + + case DepthTestStateMask: { + const auto typedChange = qSharedPointerCast>(renderStateChange); + const auto &data = typedChange->data; + return StateVariant::createState(data.depthFunction); + } + + case FrontFaceStateMask: { + const auto typedChange = qSharedPointerCast>(renderStateChange); + const auto &data = typedChange->data; + return StateVariant::createState(data.direction); + } + + case ScissorStateMask: { + const auto typedChange = qSharedPointerCast>(renderStateChange); + const auto &data = typedChange->data; + return StateVariant::createState(data.left, data.bottom, + data.width, data.height); + } + + case StencilTestStateMask: { + const auto typedChange = qSharedPointerCast>(renderStateChange); + const auto &data = typedChange->data; + return StateVariant::createState(data.front.stencilFunction, + data.front.referenceValue, + data.front.comparisonMask, + data.back.stencilFunction, + data.back.referenceValue, + data.back.comparisonMask); + } + + case PointSizeMask: { + const auto typedChange = qSharedPointerCast>(renderStateChange); + const auto &data = typedChange->data; + const bool isProgrammable = (data.sizeMode == QPointSize::Programmable); + return StateVariant::createState(isProgrammable, data.value); + } + + case PolygonOffsetStateMask: { + const auto typedChange = qSharedPointerCast>(renderStateChange); + const auto &data = typedChange->data; + return StateVariant::createState(data.scaleFactor, data.depthSteps); + } + + case ColorStateMask: { + const auto typedChange = qSharedPointerCast>(renderStateChange); + const auto &data = typedChange->data; + return StateVariant::createState(data.redMasked, data.greenMasked, + data.blueMasked, data.alphaMasked); + } + + case ClipPlaneMask: { + const auto typedChange = qSharedPointerCast>(renderStateChange); + const auto &data = typedChange->data; + return StateVariant::createState(data.planeIndex, + data.normal, + data.distance); + } + + case SeamlessCubemapMask: { + return StateVariant::createState(); + } + + case StencilOpMask: { + const auto typedChange = qSharedPointerCast>(renderStateChange); + const auto &data = typedChange->data; + return StateVariant::createState(data.front.stencilTestFailureOperation, + data.front.depthTestFailureOperation, + data.front.allTestsPassOperation, + data.back.stencilTestFailureOperation, + data.back.depthTestFailureOperation, + data.back.allTestsPassOperation); + } + + case StencilWriteStateMask: { + const auto typedChange = qSharedPointerCast>(renderStateChange); + const auto &data = typedChange->data; + return StateVariant::createState(data.frontOutputMask, + data.backOutputMask); + } + + case DitheringStateMask: { + return StateVariant::createState(); + } + + case LineWidthMask: { + const auto typedChange = qSharedPointerCast>(renderStateChange); + const auto &data = typedChange->data; + return StateVariant::createState(data.value, data.smooth); + } + + default: + Q_UNREACHABLE(); + return StateVariant(); + } +} + +} // anonymous + RenderStateNode::RenderStateNode() : BackendNode() { @@ -59,11 +242,11 @@ void RenderStateNode::cleanup() { } -void RenderStateNode::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) +void RenderStateNode::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &chang3) { cleanup(); - const auto renderStateChange = qSharedPointerCast(change); - m_impl = RenderStateSet::initializeStateFromPeer(renderStateChange); + const auto renderStateChange = qSharedPointerCast(chang3); + m_impl = createStateImplementation(renderStateChange); } void RenderStateNode::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) diff --git a/src/render/renderstates/renderstates.cpp b/src/render/renderstates/renderstates.cpp index 4a2ec69b0..d6be80b1c 100644 --- a/src/render/renderstates/renderstates.cpp +++ b/src/render/renderstates/renderstates.cpp @@ -60,34 +60,6 @@ void RenderStateImpl::updateProperty(const char *name, const QVariant &value) Q_UNUSED(value); } -void BlendEquationArguments::apply(GraphicsContext* gc) const -{ - // Un-indexed BlendEquationArguments -> Use normal GL1.0 functions - if (std::get<5>(m_values) < 0) { - if (std::get<4>(m_values)) { - gc->openGLContext()->functions()->glEnable(GL_BLEND); - gc->openGLContext()->functions()->glBlendFuncSeparate(std::get<0>(m_values), std::get<1>(m_values), std::get<2>(m_values), std::get<3>(m_values)); - } else { - gc->openGLContext()->functions()->glDisable(GL_BLEND); - } - } - // BlendEquationArguments for a particular Draw Buffer. Different behaviours for - // (1) 3.0-3.3: only enablei/disablei supported. - // (2) 4.0+: all operations supported. - // We just ignore blend func parameter for (1), so no warnings get - // printed. - else { - if (std::get<4>(m_values)) { - gc->enablei(GL_BLEND, std::get<5>(m_values)); - if (gc->supportsDrawBuffersBlend()) { - gc->blendFuncSeparatei(std::get<5>(m_values), std::get<0>(m_values), std::get<1>(m_values), std::get<2>(m_values), std::get<3>(m_values)); - } - } else { - gc->disablei(GL_BLEND, std::get<5>(m_values)); - } - } -} - void BlendEquationArguments::updateProperty(const char *name, const QVariant &value) { if (name == QByteArrayLiteral("sourceRgb")) std::get<0>(m_values) = value.toInt(); @@ -98,21 +70,11 @@ void BlendEquationArguments::updateProperty(const char *name, const QVariant &va else if (name == QByteArrayLiteral("bufferIndex")) std::get<5>(m_values) = value.toInt(); } -void BlendEquation::apply(GraphicsContext *gc) const -{ - gc->blendEquation(std::get<0>(m_values)); -} - void BlendEquation::updateProperty(const char *name, const QVariant &value) { if (name == QByteArrayLiteral("blendFunction")) std::get<0>(m_values) = value.toInt(); } -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")) @@ -121,73 +83,32 @@ void AlphaFunc::updateProperty(const char *name, const QVariant &value) std::get<1>(m_values) = value.toFloat(); } -void MSAAEnabled::apply(GraphicsContext *gc) const -{ - gc->setMSAAEnabled(std::get<0>(m_values)); -} - void MSAAEnabled::updateProperty(const char *name, const QVariant &value) { if (name == QByteArrayLiteral("enabled")) std::get<0>(m_values) = value.toBool(); } -void DepthTest::apply(GraphicsContext *gc) const -{ - gc->depthTest(std::get<0>(m_values)); -} - void DepthTest::updateProperty(const char *name, const QVariant &value) { if (name == QByteArrayLiteral("depthFunction")) std::get<0>(m_values) = value.toInt(); } -void CullFace::apply(GraphicsContext *gc) const -{ - if (std::get<0>(m_values) == QCullFace::NoCulling) { - gc->openGLContext()->functions()->glDisable(GL_CULL_FACE); - } else { - gc->openGLContext()->functions()->glEnable(GL_CULL_FACE); - gc->openGLContext()->functions()->glCullFace(std::get<0>(m_values)); - } -} - void CullFace::updateProperty(const char *name, const QVariant &value) { if (name == QByteArrayLiteral("mode")) std::get<0>(m_values) = value.toInt(); } -void FrontFace::apply(GraphicsContext *gc) const -{ - gc->frontFace(std::get<0>(m_values)); -} - void FrontFace::updateProperty(const char *name, const QVariant &value) { if (name == QByteArrayLiteral("direction")) std::get<0>(m_values) = value.toInt(); } -void NoDepthMask::apply(GraphicsContext *gc) const -{ - gc->depthMask(std::get<0>(m_values)); -} - void NoDepthMask::updateProperty(const char *name, const QVariant &value) { if (name == QByteArrayLiteral("mask")) std::get<0>(m_values) = value.toBool(); } -void Dithering::apply(GraphicsContext *gc) const -{ - gc->openGLContext()->functions()->glEnable(GL_DITHER); -} - -void ScissorTest::apply(GraphicsContext *gc) const -{ - gc->openGLContext()->functions()->glEnable(GL_SCISSOR_TEST); - gc->openGLContext()->functions()->glScissor(std::get<0>(m_values), std::get<1>(m_values), std::get<2>(m_values), std::get<3>(m_values)); -} - void ScissorTest::updateProperty(const char *name, const QVariant &value) { if (name == QByteArrayLiteral("left")) std::get<0>(m_values) = value.toInt(); @@ -196,13 +117,6 @@ void ScissorTest::updateProperty(const char *name, const QVariant &value) else if (name == QByteArrayLiteral("height")) std::get<3>(m_values) = value.toInt(); } -void StencilTest::apply(GraphicsContext *gc) const -{ - gc->openGLContext()->functions()->glEnable(GL_STENCIL_TEST); - gc->openGLContext()->functions()->glStencilFuncSeparate(GL_FRONT, std::get<0>(m_values), std::get<1>(m_values), std::get<2>(m_values)); - 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")) { @@ -216,39 +130,18 @@ void StencilTest::updateProperty(const char *name, const QVariant &value) } } -void AlphaCoverage::apply(GraphicsContext *gc) const -{ - gc->setAlphaCoverageEnabled(true); -} - -void PointSize::apply(GraphicsContext *gc) const -{ - gc->pointSize(std::get<0>(m_values), std::get<1>(m_values)); -} - void PointSize::updateProperty(const char *name, const QVariant &value) { 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(); } -void PolygonOffset::apply(GraphicsContext *gc) const -{ - gc->openGLContext()->functions()->glEnable(GL_POLYGON_OFFSET_FILL); - gc->openGLContext()->functions()->glPolygonOffset(std::get<0>(m_values), std::get<1>(m_values)); -} - void PolygonOffset::updateProperty(const char *name, const QVariant &value) { 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 -{ - gc->openGLContext()->functions()->glColorMask(std::get<0>(m_values), std::get<1>(m_values), std::get<2>(m_values), std::get<3>(m_values)); -} - void ColorMask::updateProperty(const char *name, const QVariant &value) { if (name == QByteArrayLiteral("redMasked")) std::get<0>(m_values) = value.toBool(); @@ -257,12 +150,6 @@ void ColorMask::updateProperty(const char *name, const QVariant &value) else if (name == QByteArrayLiteral("alphaMasked")) std::get<3>(m_values) = value.toBool(); } -void ClipPlane::apply(GraphicsContext *gc) const -{ - gc->enableClipPlane(std::get<0>(m_values)); - gc->setClipPlane(std::get<0>(m_values), std::get<1>(m_values), std::get<2>(m_values)); -} - void ClipPlane::updateProperty(const char *name, const QVariant &value) { if (name == QByteArrayLiteral("planeIndex")) std::get<0>(m_values) = value.toInt(); @@ -270,17 +157,6 @@ void ClipPlane::updateProperty(const char *name, const QVariant &value) else if (name == QByteArrayLiteral("distance")) std::get<2>(m_values) = value.toFloat(); } -void SeamlessCubemap::apply(GraphicsContext *gc) const -{ - gc->setSeamlessCubemap(true); -} - -void StencilOp::apply(GraphicsContext *gc) const -{ - gc->openGLContext()->functions()->glStencilOpSeparate(GL_FRONT, std::get<0>(m_values), std::get<1>(m_values), std::get<2>(m_values)); - 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")) { @@ -294,32 +170,12 @@ void StencilOp::updateProperty(const char *name, const QVariant &value) } } -void StencilMask::apply(GraphicsContext *gc) const -{ - gc->openGLContext()->functions()->glStencilMaskSeparate(GL_FRONT, std::get<0>(m_values)); - gc->openGLContext()->functions()->glStencilMaskSeparate(GL_BACK, std::get<1>(m_values)); -} - void StencilMask::updateProperty(const char *name, const QVariant &value) { 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 -#define GL_LINE_SMOOTH 0x0B20 -#endif - -void LineWidth::apply(GraphicsContext *gc) const -{ - if (std::get<1>(m_values)) - gc->openGLContext()->functions()->glEnable(GL_LINE_SMOOTH); - else - gc->openGLContext()->functions()->glDisable(GL_LINE_SMOOTH); - - gc->openGLContext()->functions()->glLineWidth(std::get<0>(m_values)); -} - void LineWidth::updateProperty(const char *name, const QVariant &value) { if (name == QByteArrayLiteral("value")) diff --git a/src/render/renderstates/renderstates_p.h b/src/render/renderstates/renderstates_p.h index c85606f87..eafaeb25f 100644 --- a/src/render/renderstates/renderstates_p.h +++ b/src/render/renderstates/renderstates_p.h @@ -62,138 +62,115 @@ namespace Render { class Q_AUTOTEST_EXPORT BlendEquationArguments : public GenericState { public: - void apply(GraphicsContext *gc) const override; void updateProperty(const char *name, const QVariant &value) override; }; class Q_AUTOTEST_EXPORT BlendEquation : public GenericState { public: - void apply(GraphicsContext *gc) const override; void updateProperty(const char *name, const QVariant &value) override; }; - class Q_AUTOTEST_EXPORT AlphaFunc : public GenericState { public: - void apply(GraphicsContext *gc) const override; void updateProperty(const char *name, const QVariant &value) override; }; class Q_AUTOTEST_EXPORT MSAAEnabled : public GenericState { public: - void apply(GraphicsContext *gc) const override; void updateProperty(const char *name, const QVariant &value) override; }; class Q_AUTOTEST_EXPORT DepthTest : public GenericState { public: - void apply(GraphicsContext *gc) const override; void updateProperty(const char *name, const QVariant &value) override; }; class Q_AUTOTEST_EXPORT NoDepthMask : public GenericState { public: - void apply(GraphicsContext *gc) const override; void updateProperty(const char *name, const QVariant &value) override; }; class Q_AUTOTEST_EXPORT CullFace : public GenericState { public: - void apply(GraphicsContext *gc) const override; void updateProperty(const char *name, const QVariant &value) override; }; class Q_AUTOTEST_EXPORT FrontFace : public GenericState { public: - void apply(GraphicsContext *gc) const override; void updateProperty(const char *name, const QVariant &value) override; }; class Q_AUTOTEST_EXPORT Dithering : public GenericState { -public: - void apply(GraphicsContext *gc) const override; }; class Q_AUTOTEST_EXPORT ScissorTest : public GenericState { public: - void apply(GraphicsContext *gc) const override; void updateProperty(const char *name, const QVariant &value) override; }; class Q_AUTOTEST_EXPORT StencilTest : public GenericState { public: - void apply(GraphicsContext *gc) const override; void updateProperty(const char *name, const QVariant &value) override; }; class Q_AUTOTEST_EXPORT AlphaCoverage : public GenericState { -public: - void apply(GraphicsContext *gc) const override; }; class Q_AUTOTEST_EXPORT PointSize : public GenericState { public: - void apply(GraphicsContext *gc) const override; void updateProperty(const char *name, const QVariant &value) override; }; class Q_AUTOTEST_EXPORT PolygonOffset : public GenericState { public: - void apply(GraphicsContext *gc) const override; + void updateProperty(const char *name, const QVariant &value) override; }; class Q_AUTOTEST_EXPORT ColorMask : public GenericState { public: - void apply(GraphicsContext *gc) const final; void updateProperty(const char *name, const QVariant &value) override; }; class Q_AUTOTEST_EXPORT ClipPlane : public GenericState { public: - void apply(GraphicsContext *gc) const final; void updateProperty(const char *name, const QVariant &value) override; }; class Q_AUTOTEST_EXPORT SeamlessCubemap : public GenericState { -public: - void apply(GraphicsContext *gc) const override; }; class Q_AUTOTEST_EXPORT StencilOp : public GenericState { public: - void apply(GraphicsContext *gc) const final; void updateProperty(const char *name, const QVariant &value) override; }; class Q_AUTOTEST_EXPORT StencilMask : public GenericState { public: - void apply(GraphicsContext *gc) const final; void updateProperty(const char *name, const QVariant &value) override; }; class Q_AUTOTEST_EXPORT LineWidth : public GenericState { public: - void apply(GraphicsContext *gc) const final; void updateProperty(const char *name, const QVariant &value) override; }; diff --git a/src/render/renderstates/statevariant.cpp b/src/render/renderstates/statevariant.cpp index e72262825..8161cba0b 100644 --- a/src/render/renderstates/statevariant.cpp +++ b/src/render/renderstates/statevariant.cpp @@ -44,74 +44,6 @@ QT_BEGIN_NAMESPACE namespace Qt3DRender { namespace Render { -void StateVariant::apply(GraphicsContext *gc) const -{ - switch (type) { - case BlendEquationArgumentsMask: - data.blendEquationArguments.apply(gc); - return; - case BlendStateMask: - data.blendEquation.apply(gc); - return; - case AlphaTestMask: - data.alphaFunc.apply(gc); - return; - case MSAAEnabledStateMask: - data.msaaEnabled.apply(gc); - return; - case DepthTestStateMask: - data.depthTest.apply(gc); - return; - case DepthWriteStateMask: - data.noDepthMask.apply(gc); - return; - case CullFaceStateMask: - data.cullFace.apply(gc); - return; - case FrontFaceStateMask: - data.frontFace.apply(gc); - return; - case DitheringStateMask: - data.dithering.apply(gc); - return; - case ScissorStateMask: - data.scissorTest.apply(gc); - return; - case StencilTestStateMask: - data.stencilTest.apply(gc); - return; - case AlphaCoverageStateMask: - data.alphaCoverage.apply(gc); - return; - case PointSizeMask: - data.pointSize.apply(gc); - return; - case PolygonOffsetStateMask: - data.polygonOffset.apply(gc); - return; - case ColorStateMask: - data.colorMask.apply(gc); - return; - case ClipPlaneMask: - data.clipPlane.apply(gc); - return; - case SeamlessCubemapMask: - data.seamlessCubemap.apply(gc); - return; - case StencilOpMask: - data.stencilOp.apply(gc); - return; - case StencilWriteStateMask: - data.stencilMask.apply(gc); - return; - case LineWidthMask: - data.lineWidth.apply(gc); - return; - default: - Q_UNREACHABLE(); - } -} - RenderStateImpl *StateVariant::state() { switch (type) { diff --git a/src/render/renderstates/statevariant_p.h b/src/render/renderstates/statevariant_p.h index 3fc93e7bd..ac3c12682 100644 --- a/src/render/renderstates/statevariant_p.h +++ b/src/render/renderstates/statevariant_p.h @@ -107,7 +107,13 @@ struct Q_AUTOTEST_EXPORT StateVariant } } data; - void apply(GraphicsContext *gc) const; + template + static StateVariant createState(Args... values) + { + State state; + state.set(values...); + return StateVariant::fromValue(state); + } template static StateVariant fromValue(const GenericState &state) -- cgit v1.2.3