From 35dd2556abb3fb7d99777a82cf7bba3a0b04be56 Mon Sep 17 00:00:00 2001
|
From: Jeffy Chen <jeffy.chen@rock-chips.com>
|
Date: Mon, 15 Jun 2020 16:48:42 +0800
|
Subject: [PATCH 02/15] Revert "Use a dedicated EGLContext for the decorations
|
blitter"
|
|
This reverts commit 7a69fc27a7cb5c5e9c70c1c56e534e6e59b46696.
|
|
Somehow mali doesn't work well with this.
|
|
Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
|
---
|
.../client/wayland-egl/qwaylandglcontext.cpp | 203 +++++++++++++-----
|
.../client/wayland-egl/qwaylandglcontext.h | 4 +-
|
2 files changed, 148 insertions(+), 59 deletions(-)
|
|
diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp
|
index ccebf43d..53cdfed6 100644
|
--- a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp
|
+++ b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp
|
@@ -56,7 +56,6 @@
|
#include <QtGui/QSurfaceFormat>
|
#include <QtGui/QOpenGLShaderProgram>
|
#include <QtGui/QOpenGLFunctions>
|
-#include <QOpenGLBuffer>
|
|
#include <QtCore/qmutex.h>
|
|
@@ -139,10 +138,19 @@ public:
|
qDebug() << "Shader Program link failed.";
|
qDebug() << m_blitProgram->log();
|
}
|
+ }
|
+ ~DecorationsBlitter()
|
+ {
|
+ delete m_blitProgram;
|
+ }
|
+ void blit(QWaylandEglWindow *window)
|
+ {
|
+ Q_ASSERT(window->wlSurface());
|
+ QOpenGLTextureCache *cache = QOpenGLTextureCache::cacheForContext(m_context->context());
|
|
- m_blitProgram->bind();
|
- m_blitProgram->enableAttributeArray(0);
|
- m_blitProgram->enableAttributeArray(1);
|
+ QSize surfaceSize = window->surfaceSize();
|
+ int scale = window->scale() ;
|
+ glViewport(0, 0, surfaceSize.width() * scale, surfaceSize.height() * scale);
|
|
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_BLEND);
|
@@ -151,8 +159,9 @@ public:
|
glDepthMask(GL_FALSE);
|
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
|
- m_buffer.create();
|
- m_buffer.bind();
|
+ m_context->mUseNativeDefaultFbo = true;
|
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
+ m_context->mUseNativeDefaultFbo = false;
|
|
static const GLfloat squareVertices[] = {
|
-1.f, -1.f,
|
@@ -160,12 +169,14 @@ public:
|
-1.f, 1.0f,
|
1.0f, 1.0f
|
};
|
+
|
static const GLfloat inverseSquareVertices[] = {
|
-1.f, 1.f,
|
1.f, 1.f,
|
-1.f, -1.f,
|
1.f, -1.f
|
};
|
+
|
static const GLfloat textureVertices[] = {
|
0.0f, 0.0f,
|
1.0f, 0.0f,
|
@@ -173,57 +184,44 @@ public:
|
1.0f, 1.0f,
|
};
|
|
- m_squareVerticesOffset = 0;
|
- m_inverseSquareVerticesOffset = sizeof(squareVertices);
|
- m_textureVerticesOffset = sizeof(squareVertices) + sizeof(textureVertices);
|
-
|
- m_buffer.allocate(sizeof(squareVertices) + sizeof(inverseSquareVertices) + sizeof(textureVertices));
|
- m_buffer.write(m_squareVerticesOffset, squareVertices, sizeof(squareVertices));
|
- m_buffer.write(m_inverseSquareVerticesOffset, inverseSquareVertices, sizeof(inverseSquareVertices));
|
- m_buffer.write(m_textureVerticesOffset, textureVertices, sizeof(textureVertices));
|
-
|
- m_blitProgram->setAttributeBuffer(1, GL_FLOAT, m_textureVerticesOffset, 2);
|
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
|
+ m_blitProgram->bind();
|
|
- m_textureWrap = m_context->context()->functions()->hasOpenGLFeature(QOpenGLFunctions::NPOTTextureRepeat) ? GL_REPEAT : GL_CLAMP_TO_EDGE;
|
- }
|
- ~DecorationsBlitter()
|
- {
|
- delete m_blitProgram;
|
- }
|
- void blit(QWaylandEglWindow *window)
|
- {
|
- Q_ASSERT(window->wlSurface());
|
- QOpenGLTextureCache *cache = QOpenGLTextureCache::cacheForContext(m_context->context());
|
+ m_blitProgram->enableAttributeArray(0);
|
+ m_blitProgram->enableAttributeArray(1);
|
+ m_blitProgram->setAttributeArray(1, textureVertices, 2);
|
|
- QSize surfaceSize = window->surfaceSize();
|
- int scale = window->scale() ;
|
- glViewport(0, 0, surfaceSize.width() * scale, surfaceSize.height() * scale);
|
+ glActiveTexture(GL_TEXTURE0);
|
|
//Draw Decoration
|
- m_blitProgram->setAttributeBuffer(0, GL_FLOAT, m_inverseSquareVerticesOffset, 2);
|
+ m_blitProgram->setAttributeArray(0, inverseSquareVertices, 2);
|
QImage decorationImage = window->decoration()->contentImage();
|
cache->bindTexture(m_context->context(), decorationImage);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_textureWrap);
|
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_textureWrap);
|
+ if (m_context->context()->functions()->hasOpenGLFeature(QOpenGLFunctions::NPOTTextureRepeat)) {
|
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
+ } else {
|
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
+ }
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
|
//Draw Content
|
- m_blitProgram->setAttributeBuffer(0, GL_FLOAT, m_squareVerticesOffset, 2);
|
+ m_blitProgram->setAttributeArray(0, squareVertices, 2);
|
glBindTexture(GL_TEXTURE_2D, window->contentTexture());
|
QRect r = window->contentsRect();
|
glViewport(r.x() * scale, r.y() * scale, r.width() * scale, r.height() * scale);
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
+
|
+ //Cleanup
|
+ m_blitProgram->disableAttributeArray(0);
|
+ m_blitProgram->disableAttributeArray(1);
|
}
|
|
QOpenGLShaderProgram *m_blitProgram = nullptr;
|
QWaylandGLContext *m_context = nullptr;
|
- QOpenGLBuffer m_buffer;
|
- int m_squareVerticesOffset;
|
- int m_inverseSquareVerticesOffset;
|
- int m_textureVerticesOffset;
|
- int m_textureWrap;
|
};
|
|
|
@@ -310,13 +308,6 @@ QWaylandGLContext::QWaylandGLContext(EGLDisplay eglDisplay, QWaylandDisplay *dis
|
return;
|
}
|
|
- // Create an EGL context for the decorations blitter. By using a dedicated context we don't need to make sure to not
|
- // change the context state and we also use OpenGL ES 2 API independently to what the app is using to draw.
|
- QVector<EGLint> eglDecorationsContextAttrs = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
|
- m_decorationsContext = eglCreateContext(m_eglDisplay, m_config, m_context, eglDecorationsContextAttrs.constData());
|
- if (m_decorationsContext == EGL_NO_CONTEXT)
|
- qWarning("QWaylandGLContext: Failed to create the decorations EGLContext. Decorations will not be drawn.");
|
-
|
EGLint a = EGL_MIN_SWAP_INTERVAL;
|
EGLint b = EGL_MAX_SWAP_INTERVAL;
|
if (!eglGetConfigAttrib(m_eglDisplay, m_config, a, &a) ||
|
@@ -431,7 +422,12 @@ bool QWaylandGLContext::makeCurrent(QPlatformSurface *surface)
|
|
if (window->isExposed())
|
window->setCanResize(false);
|
- if (m_decorationsContext != EGL_NO_CONTEXT && !window->decoration())
|
+ // Core profiles mandate the use of VAOs when rendering. We would then need to use one
|
+ // in DecorationsBlitter, but for that we would need a QOpenGLFunctions_3_2_Core instead
|
+ // of the QOpenGLFunctions we use, but that would break when using a lower version context.
|
+ // Instead of going crazy, just disable decorations for core profiles until we use
|
+ // subsurfaces for them.
|
+ if (m_format.profile() != QSurfaceFormat::CoreProfile && !window->decoration())
|
window->createDecoration();
|
|
if (eglSurface == EGL_NO_SURFACE) {
|
@@ -458,6 +454,102 @@ void QWaylandGLContext::doneCurrent()
|
eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
}
|
|
+#define STATE_GUARD_VERTEX_ATTRIB_COUNT 2
|
+
|
+class StateGuard
|
+{
|
+public:
|
+ StateGuard() {
|
+ QOpenGLFunctions glFuncs(QOpenGLContext::currentContext());
|
+
|
+ glGetIntegerv(GL_CURRENT_PROGRAM, (GLint *) &m_program);
|
+ glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint *) &m_activeTextureUnit);
|
+ glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint *) &m_texture);
|
+ glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint *) &m_fbo);
|
+ glGetIntegerv(GL_VIEWPORT, m_viewport);
|
+ glGetIntegerv(GL_DEPTH_WRITEMASK, &m_depthWriteMask);
|
+ glGetIntegerv(GL_COLOR_WRITEMASK, m_colorWriteMask);
|
+ m_blend = glIsEnabled(GL_BLEND);
|
+ m_depth = glIsEnabled(GL_DEPTH_TEST);
|
+ m_cull = glIsEnabled(GL_CULL_FACE);
|
+ m_scissor = glIsEnabled(GL_SCISSOR_TEST);
|
+ for (int i = 0; i < STATE_GUARD_VERTEX_ATTRIB_COUNT; ++i) {
|
+ glFuncs.glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, (GLint *) &m_vertexAttribs[i].enabled);
|
+ glFuncs.glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, (GLint *) &m_vertexAttribs[i].arrayBuffer);
|
+ glFuncs.glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_SIZE, &m_vertexAttribs[i].size);
|
+ glFuncs.glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &m_vertexAttribs[i].stride);
|
+ glFuncs.glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_TYPE, (GLint *) &m_vertexAttribs[i].type);
|
+ glFuncs.glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, (GLint *) &m_vertexAttribs[i].normalized);
|
+ glFuncs.glGetVertexAttribPointerv(i, GL_VERTEX_ATTRIB_ARRAY_POINTER, &m_vertexAttribs[i].pointer);
|
+ }
|
+ glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLint *) &m_minFilter);
|
+ glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (GLint *) &m_magFilter);
|
+ glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (GLint *) &m_wrapS);
|
+ glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (GLint *) &m_wrapT);
|
+ }
|
+
|
+ ~StateGuard() {
|
+ QOpenGLFunctions glFuncs(QOpenGLContext::currentContext());
|
+
|
+ glFuncs.glUseProgram(m_program);
|
+ glActiveTexture(m_activeTextureUnit);
|
+ glBindTexture(GL_TEXTURE_2D, m_texture);
|
+ glFuncs.glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
|
+ glViewport(m_viewport[0], m_viewport[1], m_viewport[2], m_viewport[3]);
|
+ glDepthMask(m_depthWriteMask);
|
+ glColorMask(m_colorWriteMask[0], m_colorWriteMask[1], m_colorWriteMask[2], m_colorWriteMask[3]);
|
+ if (m_blend)
|
+ glEnable(GL_BLEND);
|
+ if (m_depth)
|
+ glEnable(GL_DEPTH_TEST);
|
+ if (m_cull)
|
+ glEnable(GL_CULL_FACE);
|
+ if (m_scissor)
|
+ glEnable(GL_SCISSOR_TEST);
|
+ for (int i = 0; i < STATE_GUARD_VERTEX_ATTRIB_COUNT; ++i) {
|
+ if (m_vertexAttribs[i].enabled)
|
+ glFuncs.glEnableVertexAttribArray(i);
|
+ GLuint prevBuf;
|
+ glGetIntegerv(GL_ARRAY_BUFFER_BINDING, (GLint *) &prevBuf);
|
+ glFuncs.glBindBuffer(GL_ARRAY_BUFFER, m_vertexAttribs[i].arrayBuffer);
|
+ glFuncs.glVertexAttribPointer(i, m_vertexAttribs[i].size, m_vertexAttribs[i].type,
|
+ m_vertexAttribs[i].normalized, m_vertexAttribs[i].stride,
|
+ m_vertexAttribs[i].pointer);
|
+ glFuncs.glBindBuffer(GL_ARRAY_BUFFER, prevBuf);
|
+ }
|
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_minFilter);
|
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, m_magFilter);
|
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_wrapS);
|
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_wrapT);
|
+ }
|
+
|
+private:
|
+ GLuint m_program;
|
+ GLenum m_activeTextureUnit;
|
+ GLuint m_texture;
|
+ GLuint m_fbo;
|
+ GLint m_depthWriteMask;
|
+ GLint m_colorWriteMask[4];
|
+ GLboolean m_blend;
|
+ GLboolean m_depth;
|
+ GLboolean m_cull;
|
+ GLboolean m_scissor;
|
+ GLint m_viewport[4];
|
+ struct VertexAttrib {
|
+ bool enabled;
|
+ GLuint arrayBuffer;
|
+ GLint size;
|
+ GLint stride;
|
+ GLenum type;
|
+ bool normalized;
|
+ void *pointer = nullptr;
|
+ } m_vertexAttribs[STATE_GUARD_VERTEX_ATTRIB_COUNT];
|
+ GLenum m_minFilter;
|
+ GLenum m_magFilter;
|
+ GLenum m_wrapS;
|
+ GLenum m_wrapT;
|
+};
|
+
|
void QWaylandGLContext::swapBuffers(QPlatformSurface *surface)
|
{
|
QWaylandEglWindow *window = static_cast<QWaylandEglWindow *>(surface);
|
@@ -465,23 +557,15 @@ void QWaylandGLContext::swapBuffers(QPlatformSurface *surface)
|
EGLSurface eglSurface = window->eglSurface();
|
|
if (window->decoration()) {
|
- if (m_api != EGL_OPENGL_ES_API)
|
- eglBindAPI(EGL_OPENGL_ES_API);
|
+ makeCurrent(surface);
|
|
- // save the current EGL content and surface to set it again after the blitter is done
|
- EGLDisplay currentDisplay = eglGetCurrentDisplay();
|
- EGLContext currentContext = eglGetCurrentContext();
|
- EGLSurface currentSurfaceDraw = eglGetCurrentSurface(EGL_DRAW);
|
- EGLSurface currentSurfaceRead = eglGetCurrentSurface(EGL_READ);
|
- eglMakeCurrent(m_eglDisplay, eglSurface, eglSurface, m_decorationsContext);
|
+ // Must save & restore all state. Applications are usually not prepared
|
+ // for random context state changes in a swapBuffers() call.
|
+ StateGuard stateGuard;
|
|
if (!m_blitter)
|
m_blitter = new DecorationsBlitter(this);
|
m_blitter->blit(window);
|
-
|
- if (m_api != EGL_OPENGL_ES_API)
|
- eglBindAPI(m_api);
|
- eglMakeCurrent(currentDisplay, currentSurfaceDraw, currentSurfaceRead, currentContext);
|
}
|
|
int swapInterval = m_supportNonBlockingSwap ? 0 : m_format.swapInterval();
|
@@ -499,6 +583,9 @@ void QWaylandGLContext::swapBuffers(QPlatformSurface *surface)
|
|
GLuint QWaylandGLContext::defaultFramebufferObject(QPlatformSurface *surface) const
|
{
|
+ if (mUseNativeDefaultFbo)
|
+ return 0;
|
+
|
return static_cast<QWaylandEglWindow *>(surface)->contentFBO();
|
}
|
|
diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.h b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.h
|
index 46c7bb76..be12c360 100644
|
--- a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.h
|
+++ b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.h
|
@@ -87,12 +87,14 @@ private:
|
QWaylandDisplay *m_display = nullptr;
|
EGLContext m_context;
|
EGLContext m_shareEGLContext;
|
- EGLContext m_decorationsContext;
|
EGLConfig m_config;
|
QSurfaceFormat m_format;
|
DecorationsBlitter *m_blitter = nullptr;
|
+ bool mUseNativeDefaultFbo = false;
|
uint m_api;
|
bool m_supportNonBlockingSwap = true;
|
+
|
+ friend class DecorationsBlitter;
|
};
|
|
}
|
--
|
2.20.1
|