From d5d6a56809032796444fe63c220a2e940ce237c0 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Thu, 18 Jun 2020 03:56:00 +0200 Subject: Move resetOpenGLState out of QQFBO QQFBO is not the only client of resetOpenGLState. Although in theory third-party GL code that integrates with QtQuick should reset its state, in practice it doesn't. By making resetOpenGLState only available into QQFBO, now we're blocking a Qt5->6 upgrade path. There's also no compelling reason for this function to be in QQFBO at all, so move it out to as a free function in a ad-hoc new namespace. Change-Id: Ic8e5c7e244db37a5b6257d516e6aea3a9db44898 Reviewed-by: Laszlo Agocs --- src/quick/CMakeLists.txt | 1 + src/quick/items/qquickframebufferobject.cpp | 80 +----------------- src/quick/items/qquickframebufferobject.h | 1 - src/quick/items/qquickwindow.cpp | 8 +- src/quick/util/qquickopenglutils.cpp | 127 ++++++++++++++++++++++++++++ src/quick/util/qquickopenglutils.h | 59 +++++++++++++ src/quick/util/util.pri | 8 ++ 7 files changed, 202 insertions(+), 82 deletions(-) create mode 100644 src/quick/util/qquickopenglutils.cpp create mode 100644 src/quick/util/qquickopenglutils.h diff --git a/src/quick/CMakeLists.txt b/src/quick/CMakeLists.txt index 07a9927250..3fc9110d0c 100644 --- a/src/quick/CMakeLists.txt +++ b/src/quick/CMakeLists.txt @@ -484,6 +484,7 @@ qt_extend_target(Quick CONDITION QT_FEATURE_quick_shadereffect qt_extend_target(Quick CONDITION QT_FEATURE_opengl OR QT_FEATURE_opengles2 OR QT_FEATURE_opengles3 SOURCES items/qquickframebufferobject.cpp items/qquickframebufferobject.h + util/qquickopenglutils.cpp util/qquickopenglutils.h ) qt_extend_target(Quick CONDITION QT_FEATURE_quick_canvas diff --git a/src/quick/items/qquickframebufferobject.cpp b/src/quick/items/qquickframebufferobject.cpp index 66fa8818c0..03de94756d 100644 --- a/src/quick/items/qquickframebufferobject.cpp +++ b/src/quick/items/qquickframebufferobject.cpp @@ -41,7 +41,6 @@ #include #include -#include #include #include #include @@ -49,6 +48,7 @@ #include #include +#include QT_BEGIN_NAMESPACE @@ -209,7 +209,6 @@ public: , renderPending(true) , invalidatePending(false) , devicePixelRatio(1) - , vaoHelper(nullptr) { qsgnode_set_description(this, QStringLiteral("fbonode")); } @@ -220,7 +219,6 @@ public: delete texture(); delete fbo; delete msDisplayFbo; - delete vaoHelper; } void scheduleRender() @@ -241,7 +239,7 @@ public Q_SLOTS: renderPending = false; window->beginExternalCommands(); - renderer->resetOpenGLState(); + QQuickOpenGLUtils::resetOpenGLState(); fbo->bind(); QOpenGLContext::currentContext()->functions()->glViewport(0, 0, fbo->width(), fbo->height()); @@ -277,7 +275,6 @@ public: bool invalidatePending; qreal devicePixelRatio; - QOpenGLVertexArrayObjectHelper *vaoHelper; }; static inline bool isOpenGL(QSGRenderContext *rc) @@ -477,7 +474,7 @@ QOpenGLFramebufferObject *QQuickFramebufferObject::Renderer::framebufferObject() * context. This means that the state might have been modified by Quick before * invoking this function. * - * \note It is recommended to call resetOpenGLState() before + * \note It is recommended to call QQuickOpenGLUtils::resetOpenGLState() before * returning. This resets OpenGL state used by the Qt Quick renderer and thus * avoids interference from the state changes made by the rendering code in this * function. @@ -553,77 +550,6 @@ void QQuickFramebufferObject::Renderer::update() ((QSGFramebufferObjectNode *) data)->scheduleRender(); } -/*! - Call this function to reset the OpenGL context its default state. - - The scene graph uses the OpenGL context and will both rely on and - clobber its state. When mixing raw OpenGL commands with scene - graph rendering, this function provides a convenient way of - resetting the OpenGL context state back to its default values. - - This function does not touch state in the fixed-function pipeline. - - \warning This function will only reset the OpenGL context in - relation to what may be changed internally as part of the OpenGL - scene graph. It does not reset anything that has been changed - externally such as direct OpenGL calls done inside the application - code if those same calls are not used internally. (for example, - various OpenGL 3.x or 4.x specific state) - - \since 6.0 - */ -void QQuickFramebufferObject::Renderer::resetOpenGLState() -{ - QOpenGLContext *ctx = QOpenGLContext::currentContext(); - if (!ctx || !data) - return; - - QOpenGLFunctions *gl = ctx->functions(); - - gl->glBindBuffer(GL_ARRAY_BUFFER, 0); - gl->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - QOpenGLVertexArrayObjectHelper *&vaoHelper(static_cast(data)->vaoHelper); - if (!vaoHelper) - vaoHelper = new QOpenGLVertexArrayObjectHelper(ctx); - if (vaoHelper->isValid()) - vaoHelper->glBindVertexArray(0); - - if (ctx->isOpenGLES() || (gl->openGLFeatures() & QOpenGLFunctions::FixedFunctionPipeline)) { - int maxAttribs; - gl->glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxAttribs); - for (int i=0; iglVertexAttribPointer(i, 4, GL_FLOAT, GL_FALSE, 0, nullptr); - gl->glDisableVertexAttribArray(i); - } - } - - gl->glActiveTexture(GL_TEXTURE0); - gl->glBindTexture(GL_TEXTURE_2D, 0); - - gl->glDisable(GL_DEPTH_TEST); - gl->glDisable(GL_STENCIL_TEST); - gl->glDisable(GL_SCISSOR_TEST); - - gl->glColorMask(true, true, true, true); - gl->glClearColor(0, 0, 0, 0); - - gl->glDepthMask(true); - gl->glDepthFunc(GL_LESS); - gl->glClearDepthf(1); - - gl->glStencilMask(0xff); - gl->glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - gl->glStencilFunc(GL_ALWAYS, 0, 0xff); - - gl->glDisable(GL_BLEND); - gl->glBlendFunc(GL_ONE, GL_ZERO); - - gl->glUseProgram(0); - - QOpenGLFramebufferObject::bindDefault(); -} - #include "qquickframebufferobject.moc" #include "moc_qquickframebufferobject.cpp" diff --git a/src/quick/items/qquickframebufferobject.h b/src/quick/items/qquickframebufferobject.h index e8aa4a24fb..4bb335c6ed 100644 --- a/src/quick/items/qquickframebufferobject.h +++ b/src/quick/items/qquickframebufferobject.h @@ -68,7 +68,6 @@ public: QOpenGLFramebufferObject *framebufferObject() const; void update(); void invalidateFramebufferObject(); - void resetOpenGLState(); private: friend class QSGFramebufferObjectNode; friend class QQuickFramebufferObject; diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 523177b072..54926c3e9b 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -4970,7 +4970,7 @@ const QQuickWindow::GraphicsStateInfo &QQuickWindow::graphicsStateInfo() application, not retrieved from the scene graph). With graphics APIs where no native command buffer concept is exposed (OpenGL, Direct 3D 11), beginExternalCommands() and endExternalCommands() together provide a - replacement for the removed Qt 5 resetOpenGLState() function. + replacement for the Qt 5 resetOpenGLState() function. Calling this function and endExternalCommands() is not necessary within the \l{QSGRenderNode::render()}{render()} implementation of a QSGRenderNode @@ -4992,7 +4992,7 @@ const QQuickWindow::GraphicsStateInfo &QQuickWindow::graphicsStateInfo() the OpenGL state in the context can have arbitrary settings, and this function does not perform any resetting of the state back to defaults. - \sa endExternalCommands() + \sa endExternalCommands(), QQuickOpenGLUtils::resetOpenGLState() \since 5.14 */ @@ -5022,14 +5022,14 @@ void QQuickWindow::beginExternalCommands() application, not retrieved from the scene graph). With graphics APIs where no native command buffer concept is exposed (OpenGL, Direct 3D 11), beginExternalCommands() and endExternalCommands() together provide a - replacement for the removed Qt 5 resetOpenGLState() function. + replacement for the Qt 5 resetOpenGLState() function. Calling this function and beginExternalCommands() is not necessary within the \l{QSGRenderNode::render()}{render()} implementation of a QSGRenderNode because the scene graph performs the necessary steps implicitly for render nodes. - \sa beginExternalCommands() + \sa beginExternalCommands(), QQuickOpenGLUtils::resetOpenGLState() \since 5.14 */ diff --git a/src/quick/util/qquickopenglutils.cpp b/src/quick/util/qquickopenglutils.cpp new file mode 100644 index 0000000000..3a81e2dbd3 --- /dev/null +++ b/src/quick/util/qquickopenglutils.cpp @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** 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 "qquickopenglutils.h" + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +/*! + \namespace QQuickOpenGLUtils + \inmodule QtQuick + \since 6.0 + + \brief The QQuickOpenGLUtils namespace contains utilities for Qt + Quick when used with an OpenGL backend. +*/ + +/*! + Call this function to reset the current OpenGL context its default state. + + The scene graph uses the OpenGL context and will both rely on and + clobber its state. When mixing raw OpenGL commands with scene + graph rendering, this function provides a convenient way of + resetting the OpenGL context state back to its default values. + + This function does not touch state in the fixed-function pipeline. + + \warning This function will only reset the OpenGL context in + relation to what may be changed internally as part of the OpenGL + scene graph. It does not reset anything that has been changed + externally such as direct OpenGL calls done inside the application + code if those same calls are not used internally (for example, + various OpenGL 3.x or 4.x specific state). + + \since 6.0 +*/ +void QQuickOpenGLUtils::resetOpenGLState() +{ + QOpenGLContext *ctx = QOpenGLContext::currentContext(); + if (!ctx) + return; + + QOpenGLFunctions *gl = ctx->functions(); + + gl->glBindBuffer(GL_ARRAY_BUFFER, 0); + gl->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + QOpenGLVertexArrayObjectHelper *vaoHelper = QOpenGLVertexArrayObjectHelper::vertexArrayObjectHelperForContext(ctx); + if (vaoHelper->isValid()) + vaoHelper->glBindVertexArray(0); + + if (ctx->isOpenGLES() || (gl->openGLFeatures() & QOpenGLFunctions::FixedFunctionPipeline)) { + int maxAttribs; + gl->glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxAttribs); + for (int i=0; iglVertexAttribPointer(i, 4, GL_FLOAT, GL_FALSE, 0, nullptr); + gl->glDisableVertexAttribArray(i); + } + } + + gl->glActiveTexture(GL_TEXTURE0); + gl->glBindTexture(GL_TEXTURE_2D, 0); + + gl->glDisable(GL_DEPTH_TEST); + gl->glDisable(GL_STENCIL_TEST); + gl->glDisable(GL_SCISSOR_TEST); + + gl->glColorMask(true, true, true, true); + gl->glClearColor(0, 0, 0, 0); + + gl->glDepthMask(true); + gl->glDepthFunc(GL_LESS); + gl->glClearDepthf(1); + + gl->glStencilMask(0xff); + gl->glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + gl->glStencilFunc(GL_ALWAYS, 0, 0xff); + + gl->glDisable(GL_BLEND); + gl->glBlendFunc(GL_ONE, GL_ZERO); + + gl->glUseProgram(0); + + QOpenGLFramebufferObject::bindDefault(); +} + +QT_END_NAMESPACE diff --git a/src/quick/util/qquickopenglutils.h b/src/quick/util/qquickopenglutils.h new file mode 100644 index 0000000000..38e3f00c19 --- /dev/null +++ b/src/quick/util/qquickopenglutils.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QQUICKOPENGLUTILS_H +#define QQUICKOPENGLUTILS_H + +#if 0 +#pragma qt_class(QQuickOpenGLUtils) +#endif + +#include + +QT_BEGIN_NAMESPACE + +namespace QQuickOpenGLUtils { + +Q_QUICK_EXPORT void resetOpenGLState(); + +} // namespace QQuickOpenGLUtils + +QT_END_NAMESPACE + +#endif // QQUICKOPENGLUTILS_H diff --git a/src/quick/util/util.pri b/src/quick/util/util.pri index f61a967959..56e7d342f8 100644 --- a/src/quick/util/util.pri +++ b/src/quick/util/util.pri @@ -80,3 +80,11 @@ qtConfig(quick-path) { $$PWD/qquickpath_p_p.h \ $$PWD/qquickpathinterpolator_p.h } + +qtConfig(opengl(es1|es2)?) { + SOURCES += \ + $$PWD/qquickopenglutils.cpp + + HEADERS += \ + $$PWD/qquickopenglutils.h +} -- cgit v1.2.3