aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items/qquickframebufferobject.cpp
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2020-06-11 15:32:53 +0200
committerLaszlo Agocs <laszlo.agocs@qt.io>2020-06-12 12:38:39 +0200
commit9943181dcc9e2b0de630669219edcaf62956c1f1 (patch)
treee9535243cbaf755cac734a9880e6aa3c9bee17ca /src/quick/items/qquickframebufferobject.cpp
parent69c7ed97c2dde8b45cc29d08eb4568dc08fcd00a (diff)
Move resetOpenGLState() to QQuickFbo
QQuickWindow should not have OpenGL specifics in its API in Qt 6. However, resetOpenGLState() is used by applications commonly in combination with QQuickFramebufferObject (not the least because the documentation recommends it!). This is no problem in practice because QQuickFramebufferObject remains an OpenGL-only feature. So to minimize the breaks, move the function into QQuickFramebufferObject::Renderer so any application that calls the function can continue to do so by just calling it on 'this' instead. The rendercontrol_opengl example used to call this function as well, but unnecessarily, it will still function the same way without it. Note that there is a chance that there are applications that call resetOpenGLState() in other contexts, for example in slots connected to before or afterRendering(). For these it will need to be determined if the call is necessary at all, and if it is, should be replaced by (re)setting the appropriate OpenGL state manually instead. Task-number: QTBUG-84523 Change-Id: I335599f77e8a84e347a44427eb1a1bf917796ee8 Reviewed-by: Christian Strømme <christian.stromme@qt.io>
Diffstat (limited to 'src/quick/items/qquickframebufferobject.cpp')
-rw-r--r--src/quick/items/qquickframebufferobject.cpp78
1 files changed, 76 insertions, 2 deletions
diff --git a/src/quick/items/qquickframebufferobject.cpp b/src/quick/items/qquickframebufferobject.cpp
index 9026591119..81ea49f4de 100644
--- a/src/quick/items/qquickframebufferobject.cpp
+++ b/src/quick/items/qquickframebufferobject.cpp
@@ -41,6 +41,7 @@
#include <QOpenGLFramebufferObject>
#include <QOpenGLFunctions>
+#include <private/qopenglvertexarrayobject_p.h>
#include <private/qquickitem_p.h>
#include <private/qsgadaptationlayer_p.h>
#include <qsgtextureprovider.h>
@@ -208,6 +209,7 @@ public:
, renderPending(true)
, invalidatePending(false)
, devicePixelRatio(1)
+ , vaoHelper(nullptr)
{
qsgnode_set_description(this, QStringLiteral("fbonode"));
}
@@ -218,6 +220,7 @@ public:
delete texture();
delete fbo;
delete msDisplayFbo;
+ delete vaoHelper;
}
void scheduleRender()
@@ -238,7 +241,7 @@ public Q_SLOTS:
renderPending = false;
window->beginExternalCommands();
- window->resetOpenGLState();
+ renderer->resetOpenGLState();
fbo->bind();
QOpenGLContext::currentContext()->functions()->glViewport(0, 0, fbo->width(), fbo->height());
@@ -274,6 +277,7 @@ public:
bool invalidatePending;
qreal devicePixelRatio;
+ QOpenGLVertexArrayObjectHelper *vaoHelper;
};
static inline bool isOpenGL(QSGRenderContext *rc)
@@ -473,7 +477,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 QQuickWindow::resetOpenGLState() before
+ * \note It is recommended to call 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.
@@ -549,6 +553,76 @@ 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<QSGFramebufferObjectNode *>(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; i<maxAttribs; ++i) {
+ gl->glVertexAttribPointer(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"