aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/scenegraph/qsgdefaultcontext.cpp
diff options
context:
space:
mode:
authorAndy Nichols <andy.nichols@theqtcompany.com>2016-03-15 13:39:41 +0100
committerLaszlo Agocs <laszlo.agocs@theqtcompany.com>2016-03-22 09:51:54 +0000
commit90d98e1330bd46b5defafd5d6b86fa8fe157b48d (patch)
tree722e2b1d371c6b58144d51b8167faa9d1c86e7f0 /src/quick/scenegraph/qsgdefaultcontext.cpp
parente32fb877ec0662dfda41ce490d77d8bf35a377f1 (diff)
Enable building Qt Quick module with QT_NO_OPENGL defined
Currently the Qt Quick module depends on either the OpenGL or OpenGLES headers being available at build time. Since we are adding support for adaptations that do not depend on OpenGL, it should be possible to build Qt Quick in environments that do not have OpenGL development headers. This does present many challenges though because in some cases GL types, and classes that require OpenGL are part of the public APIs. However since these classes were never available when QT_NO_OPENGL was defined, it should be possible to redefine the function signatures under this scenario, since it's not possible to break binary compatibility if there never were any binaries to break compatibility with. One of the bigger changes that was necessary to facilitate this change is creating interfaces out of QSGContext and QSGRenderContext. Here the default behavior was usage of OpenGL directly, even though subclasses could override all OpenGL usage. Making them interfaces should bring QSGContext and QSGRenderContext more in line with the other classes present in the adaptation layer. Change-Id: Iaa54dc0f6cfd18d2da1d059548abf509bd71f200 Reviewed-by: Laszlo Agocs <laszlo.agocs@theqtcompany.com>
Diffstat (limited to 'src/quick/scenegraph/qsgdefaultcontext.cpp')
-rw-r--r--src/quick/scenegraph/qsgdefaultcontext.cpp243
1 files changed, 243 insertions, 0 deletions
diff --git a/src/quick/scenegraph/qsgdefaultcontext.cpp b/src/quick/scenegraph/qsgdefaultcontext.cpp
new file mode 100644
index 0000000000..f969359e7c
--- /dev/null
+++ b/src/quick/scenegraph/qsgdefaultcontext.cpp
@@ -0,0 +1,243 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsgdefaultcontext_p.h"
+
+#include <QtQuick/private/qsgdistancefieldutil_p.h>
+#include <QtQuick/private/qsgdefaultrectanglenode_p.h>
+#include <QtQuick/private/qsgdefaultimagenode_p.h>
+#include <QtQuick/private/qsgdefaultpainternode_p.h>
+#include <QtQuick/private/qsgdefaultglyphnode_p.h>
+#include <QtQuick/private/qsgdistancefieldglyphnode_p.h>
+#include <QtQuick/private/qsgdistancefieldglyphnode_p_p.h>
+#include <QtQuick/private/qsgrenderloop_p.h>
+#include <QtQuick/private/qsgdefaultlayer_p.h>
+#include <QtQuick/private/qsgdefaultrendercontext_p.h>
+
+#include <QtGui/QOpenGLContext>
+#include <QtGui/QOpenGLFramebufferObject>
+
+#include <QtQuick/QQuickWindow>
+
+#include <private/qqmlglobal_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QSGMultisampleAntialiasing {
+ class ImageNode : public QSGDefaultImageNode {
+ public:
+ void setAntialiasing(bool) { }
+ };
+
+
+ class RectangleNode : public QSGDefaultRectangleNode {
+ public:
+ void setAntialiasing(bool) { }
+ };
+}
+
+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 openglRenderContext = 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) {
+ if (openglRenderContext->openglContext()->format().samples() > 0)
+ m_antialiasingMethod = MsaaAntialiasing;
+ else
+ m_antialiasingMethod = VertexAntialiasing;
+ }
+ }
+
+ // With OpenGL ES, except for Angle on Windows, 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;
+#ifndef Q_OS_WIN32
+ if (openglRenderContext->openglContext()->isOpenGLES())
+ m_distanceFieldAntialiasing = QSGGlyphNode::GrayAntialiasing;
+#endif
+ }
+
+ static bool dumped = false;
+ if (!dumped && QSG_LOG_INFO().isDebugEnabled()) {
+ dumped = true;
+ QSurfaceFormat format = openglRenderContext->openglContext()->format();
+ QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions();
+ qCDebug(QSG_LOG_INFO) << "R/G/B/A Buffers: " << format.redBufferSize() << format.greenBufferSize() << format.blueBufferSize() << format.alphaBufferSize();
+ qCDebug(QSG_LOG_INFO) << "Depth Buffer: " << format.depthBufferSize();
+ qCDebug(QSG_LOG_INFO) << "Stencil Buffer: " << format.stencilBufferSize();
+ qCDebug(QSG_LOG_INFO) << "Samples: " << format.samples();
+ qCDebug(QSG_LOG_INFO) << "GL_VENDOR: " << (const char *) funcs->glGetString(GL_VENDOR);
+ qCDebug(QSG_LOG_INFO) << "GL_RENDERER: " << (const char *) funcs->glGetString(GL_RENDERER);
+ qCDebug(QSG_LOG_INFO) << "GL_VERSION: " << (const char *) funcs->glGetString(GL_VERSION);
+ QSet<QByteArray> exts = openglRenderContext->openglContext()->extensions();
+ QByteArray all; foreach (const QByteArray &e, exts) all += ' ' + e;
+ qCDebug(QSG_LOG_INFO) << "GL_EXTENSIONS: " << all.constData();
+ qCDebug(QSG_LOG_INFO) << "Max Texture Size: " << openglRenderContext->maxTextureSize();
+ qCDebug(QSG_LOG_INFO) << "Debug context: " << format.testOption(QSurfaceFormat::DebugContext);
+ }
+
+ m_mutex.unlock();
+}
+
+void QSGDefaultContext::renderContextInvalidated(QSGRenderContext *)
+{
+}
+
+QSGRenderContext *QSGDefaultContext::createRenderContext()
+{
+ return new QSGDefaultRenderContext(this);
+}
+
+QSGRectangleNode *QSGDefaultContext::createRectangleNode()
+{
+ return m_antialiasingMethod == MsaaAntialiasing
+ ? new QSGMultisampleAntialiasing::RectangleNode
+ : new QSGDefaultRectangleNode;
+}
+
+QSGImageNode *QSGDefaultContext::createImageNode()
+{
+ return m_antialiasingMethod == MsaaAntialiasing
+ ? new QSGMultisampleAntialiasing::ImageNode
+ : new QSGDefaultImageNode;
+}
+
+QSGPainterNode *QSGDefaultContext::createPainterNode(QQuickPaintedItem *item)
+{
+ return new QSGDefaultPainterNode(item);
+}
+
+QSGGlyphNode *QSGDefaultContext::createGlyphNode(QSGRenderContext *rc, bool preferNativeGlyphNode)
+{
+ if (m_distanceFieldDisabled || preferNativeGlyphNode) {
+ return new QSGDefaultGlyphNode;
+ } else {
+ QSGDistanceFieldGlyphNode *node = new QSGDistanceFieldGlyphNode(rc);
+ node->setPreferredAntialiasingMode(m_distanceFieldAntialiasing);
+ return node;
+ }
+}
+
+/*!
+ * Factory function for scene graph backends of the QStyle stylable elements. Returns a
+ * null pointer if the backend doesn't provide its own node type.
+ */
+QSGNinePatchNode *QSGDefaultContext::createNinePatchNode()
+{
+ return nullptr;
+}
+
+QSGLayer *QSGDefaultContext::createLayer(QSGRenderContext *renderContext)
+{
+ return new QSGDefaultLayer(renderContext);
+}
+
+QSurfaceFormat QSGDefaultContext::defaultSurfaceFormat() const
+{
+ QSurfaceFormat format = QSurfaceFormat::defaultFormat();
+ static bool useDepth = qEnvironmentVariableIsEmpty("QSG_NO_DEPTH_BUFFER");
+ static bool useStencil = qEnvironmentVariableIsEmpty("QSG_NO_STENCIL_BUFFER");
+ static bool enableDebug = qEnvironmentVariableIsSet("QSG_OPENGL_DEBUG");
+ format.setDepthBufferSize(useDepth ? 24 : 0);
+ format.setStencilBufferSize(useStencil ? 8 : 0);
+ if (enableDebug)
+ format.setOption(QSurfaceFormat::DebugContext);
+ if (QQuickWindow::hasDefaultAlphaBuffer())
+ format.setAlphaBufferSize(8);
+ format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
+ return format;
+}
+
+void QSGDefaultContext::setDistanceFieldEnabled(bool enabled)
+{
+ m_distanceFieldDisabled = !enabled;
+}
+
+bool QSGDefaultContext::isDistanceFieldEnabled() const
+{
+ return !m_distanceFieldDisabled;
+}
+
+QT_END_NAMESPACE