Revision control

++ // Copyright (C) 2016 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
++ // Qt-Security score:significant reason:default
++
++ #include "qsgdefaultcontext_p.h"
++
++ #include <QtQuick/private/qsgdefaultinternalrectanglenode_p.h>
++ #include <QtQuick/private/qsgdefaultinternalimagenode_p.h>
++ #include <QtQuick/private/qsgdefaultpainternode_p.h>
++ #include <QtQuick/private/qsgdefaultglyphnode_p.h>
++ #include <QtQuick/private/qsgcurveglyphnode_p.h>
++ #include <QtQuick/private/qsgdistancefieldglyphnode_p.h>
++ #include <QtQuick/private/qsgdistancefieldglyphnode_p_p.h>
++ #include <QtQuick/private/qsgrhisupport_p.h>
++ #include <QtQuick/private/qsgrhilayer_p.h>
++ #include <QtQuick/private/qsgdefaultrendercontext_p.h>
++ #include <QtQuick/private/qsgdefaultrectanglenode_p.h>
++ #include <QtQuick/private/qsgdefaultimagenode_p.h>
++ #include <QtQuick/private/qsgdefaultninepatchnode_p.h>
++ #if QT_CONFIG(quick_sprite)
++ #include <QtQuick/private/qsgdefaultspritenode_p.h>
++ #endif
++ #include <QtQuick/private/qsgrhishadereffectnode_p.h>
++ #include <QtQuick/private/qsginternaltextnode_p.h>
++ #include <QtQuick/private/qsgrhiinternaltextnode_p.h>
++
++ #include <QOpenGLContext>
++
++ #include <QtQuick/private/qquickwindow_p.h>
++ #include <QtQuick/private/qquickitem_p.h>
++
++ #include <private/qqmlglobal_p.h>
++
++ #include <algorithm>
++
++ #include <rhi/qrhi.h>
++
++ QT_BEGIN_NAMESPACE
++
++ namespace QSGMultisampleAntialiasing {
++ class ImageNode : public QSGDefaultInternalImageNode {
++ public:
++ ImageNode(QSGDefaultRenderContext *rc) : QSGDefaultInternalImageNode(rc) { }
++ void setAntialiasing(bool) override { }
++ };
++
++ class RectangleNode : public QSGDefaultInternalRectangleNode {
++ public:
++ void setAntialiasing(bool) override { }
++ };
++ }
++
++ DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
++
++ QSGDefaultContext::QSGDefaultContext(QObject *parent)
++ : QSGContext (parent)
++ , m_antialiasingMethod(QSGContext::UndecidedAntialiasing)
++ , m_distanceFieldDisabled(qmlDisableDistanceField())
++ , m_distanceFieldAntialiasing(QSGGlyphNode::HighQualitySubPixelAntialiasing)
++ , m_distanceFieldAntialiasingDecided(false)
++ {
++ if (Q_UNLIKELY(!qEnvironmentVariableIsEmpty("QSG_DISTANCEFIELD_ANTIALIASING"))) {
++ const QByteArray mode = qgetenv("QSG_DISTANCEFIELD_ANTIALIASING");
++ m_distanceFieldAntialiasingDecided = true;
++ if (mode == "subpixel")
++ m_distanceFieldAntialiasing = QSGGlyphNode::HighQualitySubPixelAntialiasing;
++ else if (mode == "subpixel-lowq")
++ m_distanceFieldAntialiasing = QSGGlyphNode::LowQualitySubPixelAntialiasing;
++ else if (mode == "gray")
++ m_distanceFieldAntialiasing = QSGGlyphNode::GrayAntialiasing;
++ }
++
++ // Adds compatibility with Qt 5.3 and earlier's QSG_RENDER_TIMING
++ if (qEnvironmentVariableIsSet("QSG_RENDER_TIMING")) {
++ const_cast<QLoggingCategory &>(QSG_LOG_TIME_GLYPH()).setEnabled(QtDebugMsg, true);
++ const_cast<QLoggingCategory &>(QSG_LOG_TIME_TEXTURE()).setEnabled(QtDebugMsg, true);
++ const_cast<QLoggingCategory &>(QSG_LOG_TIME_RENDERER()).setEnabled(QtDebugMsg, true);
++ const_cast<QLoggingCategory &>(QSG_LOG_TIME_RENDERLOOP()).setEnabled(QtDebugMsg, true);
++ const_cast<QLoggingCategory &>(QSG_LOG_TIME_COMPILATION()).setEnabled(QtDebugMsg, true);
++ }
++ }
++
++ QSGDefaultContext::~QSGDefaultContext()
++ {
++
++ }
++
++ void QSGDefaultContext::renderContextInitialized(QSGRenderContext *renderContext)
++ {
++ m_mutex.lock();
++
++ auto rc = static_cast<const QSGDefaultRenderContext *>(renderContext);
++ if (m_antialiasingMethod == UndecidedAntialiasing) {
++ if (Q_UNLIKELY(qEnvironmentVariableIsSet("QSG_ANTIALIASING_METHOD"))) {
++ const QByteArray aaType = qgetenv("QSG_ANTIALIASING_METHOD");
++ if (aaType == "msaa")
++ m_antialiasingMethod = MsaaAntialiasing;
++ else if (aaType == "vertex")
++ m_antialiasingMethod = VertexAntialiasing;
++ }
++ if (m_antialiasingMethod == UndecidedAntialiasing)
++ m_antialiasingMethod = rc->msaaSampleCount() > 1 ? MsaaAntialiasing : VertexAntialiasing;
++ }
++
++ #if QT_CONFIG(opengl)
++ // With OpenGL ES, use GrayAntialiasing, unless
++ // some value had been requested explicitly. This could not be decided
++ // before without a context. Now the context is ready.
++ if (!m_distanceFieldAntialiasingDecided) {
++ m_distanceFieldAntialiasingDecided = true;
++ Q_ASSERT(rc->rhi());
++ if (rc->rhi()->backend() == QRhi::OpenGLES2
++ && static_cast<const QRhiGles2NativeHandles *>(rc->rhi()->nativeHandles())->context->isOpenGLES())
++ {
++ m_distanceFieldAntialiasing = QSGGlyphNode::GrayAntialiasing;
++ }
++ }
++ #endif
++
++ m_mutex.unlock();
++ }
++
++ void QSGDefaultContext::renderContextInvalidated(QSGRenderContext *)
++ {
++ }
++
++ QSGRenderContext *QSGDefaultContext::createRenderContext()
++ {
++ return new QSGDefaultRenderContext(this);
++ }
++
++ QSGInternalRectangleNode *QSGDefaultContext::createInternalRectangleNode()
++ {
++ return m_antialiasingMethod == MsaaAntialiasing
++ ? new QSGMultisampleAntialiasing::RectangleNode
++ : new QSGDefaultInternalRectangleNode;
++ }
++
++ QSGInternalImageNode *QSGDefaultContext::createInternalImageNode(QSGRenderContext *renderContext)
++ {
++ return m_antialiasingMethod == MsaaAntialiasing
++ ? new QSGMultisampleAntialiasing::ImageNode(static_cast<QSGDefaultRenderContext *>(renderContext))
++ : new QSGDefaultInternalImageNode(static_cast<QSGDefaultRenderContext *>(renderContext));
++ }
++
++ QSGPainterNode *QSGDefaultContext::createPainterNode(QQuickPaintedItem *item)
++ {
++ return new QSGDefaultPainterNode(item);
++ }
++
++ QSGInternalTextNode *QSGDefaultContext::createInternalTextNode(QSGRenderContext *renderContext)
++ {
++ return new QSGRhiInternalTextNode(renderContext);
++ }
++
++ QSGTextNode::RenderType QSGDefaultContext::processTextRenderType(QSGTextNode::RenderType renderType)
++ {
++ if (renderType == QSGTextNode::QtRendering && m_distanceFieldDisabled)
++ return QSGTextNode::NativeRendering;
++ else
++ return renderType;
++ }
++
++ QSGGlyphNode *QSGDefaultContext::createGlyphNode(QSGRenderContext *rc,
++ QSGTextNode::RenderType renderType)
++ {
++ if (renderType == QSGTextNode::CurveRendering) {
++ return new QSGCurveGlyphNode(rc);
++ } else if (renderType == QSGTextNode::NativeRendering) {
++ return new QSGDefaultGlyphNode(rc);
++ } else {
++ QSGDistanceFieldGlyphNode *node = new QSGDistanceFieldGlyphNode(rc);
++ node->setPreferredAntialiasingMode(m_distanceFieldAntialiasing);
++ return node;
++ }
++ }
++
++ QSGLayer *QSGDefaultContext::createLayer(QSGRenderContext *renderContext)
++ {
++ return new QSGRhiLayer(renderContext);
++ }
++
++ QSurfaceFormat QSGDefaultContext::defaultSurfaceFormat() const
++ {
++ QSurfaceFormat format = QSurfaceFormat::defaultFormat();
++ // These depend solely on the env.vars., not QQuickGraphicsConfiguration
++ // since that does not have a flag that maps 100% to QSG_NO_xx_BUFFER.
++ static bool useDepth = qEnvironmentVariableIsEmpty("QSG_NO_DEPTH_BUFFER");
++ static bool useStencil = qEnvironmentVariableIsEmpty("QSG_NO_STENCIL_BUFFER");
++ static bool enableDebug = qEnvironmentVariableIsSet("QSG_OPENGL_DEBUG");
++ static bool disableVSync = qEnvironmentVariableIsSet("QSG_NO_VSYNC");
++ if (useDepth && format.depthBufferSize() == -1)
++ format.setDepthBufferSize(24);
++ else if (!useDepth)
++ format.setDepthBufferSize(0);
++ if (useStencil && format.stencilBufferSize() == -1)
++ format.setStencilBufferSize(8);
++ else if (!useStencil)
++ format.setStencilBufferSize(0);
++ if (enableDebug)
++ format.setOption(QSurfaceFormat::DebugContext);
++ if (QQuickWindow::hasDefaultAlphaBuffer())
++ format.setAlphaBufferSize(8);
++ format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
++ if (disableVSync) // swapInterval defaults to 1, it has no -1 special value
++ format.setSwapInterval(0);
++ return format;
++ }
++
++ void QSGDefaultContext::setDistanceFieldEnabled(bool enabled)
++ {
++ m_distanceFieldDisabled = !enabled;
++ }
++
++ bool QSGDefaultContext::isDistanceFieldEnabled() const
++ {
++ return !m_distanceFieldDisabled;
++ }
++
++ QSGRendererInterface *QSGDefaultContext::rendererInterface(QSGRenderContext *renderContext)
++ {
++ Q_UNUSED(renderContext);
++ return this;
++ }
++
++ QSGRectangleNode *QSGDefaultContext::createRectangleNode()
++ {
++ return new QSGDefaultRectangleNode;
++ }
++
++ QSGImageNode *QSGDefaultContext::createImageNode()
++ {
++ return new QSGDefaultImageNode;
++ }
++
++ QSGNinePatchNode *QSGDefaultContext::createNinePatchNode()
++ {
++ return new QSGDefaultNinePatchNode;
++ }
++
++ #if QT_CONFIG(quick_sprite)
++ QSGSpriteNode *QSGDefaultContext::createSpriteNode()
++ {
++ return new QSGDefaultSpriteNode;
++ }
++ #endif
++
++ QSGGuiThreadShaderEffectManager *QSGDefaultContext::createGuiThreadShaderEffectManager()
++ {
++ return new QSGRhiGuiThreadShaderEffectManager;
++ }
++
++ QSGShaderEffectNode *QSGDefaultContext::createShaderEffectNode(QSGRenderContext *renderContext)
++ {
++ return new QSGRhiShaderEffectNode(static_cast<QSGDefaultRenderContext *>(renderContext));
++ }
++
++ QSGRendererInterface::GraphicsApi QSGDefaultContext::graphicsApi() const
++ {
++ return QSGRhiSupport::instance()->graphicsApi();
++ }
++
++ void *QSGDefaultContext::getResource(QQuickWindow *window, Resource resource) const
++ {
++ if (!window)
++ return nullptr;
++
++ // Unlike the graphicsApi and shaderType and similar queries, getting a
++ // native resource is only possible when there is an initialized
++ // rendercontext, or rather, only within rendering a frame, as per
++ // QSGRendererInterface docs. This is good since getting some things is
++ // only possible within a beginFrame - endFrame with the RHI.
++
++ const QSGDefaultRenderContext *rc = static_cast<const QSGDefaultRenderContext *>(
++ QQuickWindowPrivate::get(window)->context);
++ QSGRhiSupport *rhiSupport = QSGRhiSupport::instance();
++
++ #if QT_CONFIG(vulkan)
++ if (resource == VulkanInstanceResource)
++ return window->vulkanInstance();
++ #endif
++ return const_cast<void *>(rhiSupport->rifResource(resource, rc, window));
++ }
++
++ QSGRendererInterface::ShaderType QSGDefaultContext::shaderType() const
++ {
++ return RhiShader;
++ }
++
++ QSGRendererInterface::ShaderCompilationTypes QSGDefaultContext::shaderCompilationType() const
++ {
++ return OfflineCompilation;
++ }
++
++ QSGRendererInterface::ShaderSourceTypes QSGDefaultContext::shaderSourceType() const
++ {
++ return ShaderSourceFile;
++ }
++
++ QT_END_NAMESPACE
++
++ static void initResources()
++ {
++ Q_INIT_RESOURCE(scenegraph_shaders);
++ }
++
++ Q_CONSTRUCTOR_FUNCTION(initResources)