1From dcea7e200b90a5ad5571a558d5a693165381c9fc Mon Sep 17 00:00:00 2001 2From: Jeffy Chen <jeffy.chen@rock-chips.com> 3Date: Mon, 15 Jun 2020 16:48:42 +0800 4Subject: [PATCH 03/17] Revert "Use a dedicated EGLContext for the decorations 5 blitter" 6 7This reverts commit 7a69fc27a7cb5c5e9c70c1c56e534e6e59b46696. 8 9Somehow mali doesn't work well with this. 10 11Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com> 12--- 13 .../client/wayland-egl/qwaylandglcontext.cpp | 205 +++++++++++++----- 14 .../client/wayland-egl/qwaylandglcontext.h | 4 +- 15 2 files changed, 148 insertions(+), 61 deletions(-) 16 17diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp 18index 1a1c349..d076d9e 100644 19--- a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp 20+++ b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp 21@@ -56,7 +56,6 @@ 22 #include <QtGui/QSurfaceFormat> 23 #include <QtGui/QOpenGLShaderProgram> 24 #include <QtGui/QOpenGLFunctions> 25-#include <QOpenGLBuffer> 26 27 #include <QtCore/qmutex.h> 28 29@@ -139,10 +138,19 @@ public: 30 qDebug() << "Shader Program link failed."; 31 qDebug() << m_blitProgram->log(); 32 } 33+ } 34+ ~DecorationsBlitter() 35+ { 36+ delete m_blitProgram; 37+ } 38+ void blit(QWaylandEglWindow *window) 39+ { 40+ Q_ASSERT(window->wlSurface()); 41+ QOpenGLTextureCache *cache = QOpenGLTextureCache::cacheForContext(m_context->context()); 42 43- m_blitProgram->bind(); 44- m_blitProgram->enableAttributeArray(0); 45- m_blitProgram->enableAttributeArray(1); 46+ QSize surfaceSize = window->surfaceSize(); 47+ int scale = window->scale() ; 48+ glViewport(0, 0, surfaceSize.width() * scale, surfaceSize.height() * scale); 49 50 glDisable(GL_DEPTH_TEST); 51 glDisable(GL_BLEND); 52@@ -151,8 +159,9 @@ public: 53 glDepthMask(GL_FALSE); 54 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 55 56- m_buffer.create(); 57- m_buffer.bind(); 58+ m_context->mUseNativeDefaultFbo = true; 59+ glBindFramebuffer(GL_FRAMEBUFFER, 0); 60+ m_context->mUseNativeDefaultFbo = false; 61 62 static const GLfloat squareVertices[] = { 63 -1.f, -1.f, 64@@ -160,12 +169,14 @@ public: 65 -1.f, 1.0f, 66 1.0f, 1.0f 67 }; 68+ 69 static const GLfloat inverseSquareVertices[] = { 70 -1.f, 1.f, 71 1.f, 1.f, 72 -1.f, -1.f, 73 1.f, -1.f 74 }; 75+ 76 static const GLfloat textureVertices[] = { 77 0.0f, 0.0f, 78 1.0f, 0.0f, 79@@ -173,57 +184,44 @@ public: 80 1.0f, 1.0f, 81 }; 82 83- m_squareVerticesOffset = 0; 84- m_inverseSquareVerticesOffset = sizeof(squareVertices); 85- m_textureVerticesOffset = sizeof(squareVertices) + sizeof(textureVertices); 86- 87- m_buffer.allocate(sizeof(squareVertices) + sizeof(inverseSquareVertices) + sizeof(textureVertices)); 88- m_buffer.write(m_squareVerticesOffset, squareVertices, sizeof(squareVertices)); 89- m_buffer.write(m_inverseSquareVerticesOffset, inverseSquareVertices, sizeof(inverseSquareVertices)); 90- m_buffer.write(m_textureVerticesOffset, textureVertices, sizeof(textureVertices)); 91- 92- m_blitProgram->setAttributeBuffer(1, GL_FLOAT, m_textureVerticesOffset, 2); 93+ glBindBuffer(GL_ARRAY_BUFFER, 0); 94+ m_blitProgram->bind(); 95 96- m_textureWrap = m_context->context()->functions()->hasOpenGLFeature(QOpenGLFunctions::NPOTTextureRepeat) ? GL_REPEAT : GL_CLAMP_TO_EDGE; 97- } 98- ~DecorationsBlitter() 99- { 100- delete m_blitProgram; 101- } 102- void blit(QWaylandEglWindow *window) 103- { 104- Q_ASSERT(window->wlSurface()); 105- QOpenGLTextureCache *cache = QOpenGLTextureCache::cacheForContext(m_context->context()); 106+ m_blitProgram->enableAttributeArray(0); 107+ m_blitProgram->enableAttributeArray(1); 108+ m_blitProgram->setAttributeArray(1, textureVertices, 2); 109 110- QSize surfaceSize = window->surfaceSize(); 111- int scale = window->scale() ; 112- glViewport(0, 0, surfaceSize.width() * scale, surfaceSize.height() * scale); 113+ glActiveTexture(GL_TEXTURE0); 114 115 //Draw Decoration 116- m_blitProgram->setAttributeBuffer(0, GL_FLOAT, m_inverseSquareVerticesOffset, 2); 117+ m_blitProgram->setAttributeArray(0, inverseSquareVertices, 2); 118 QImage decorationImage = window->decoration()->contentImage(); 119 cache->bindTexture(m_context->context(), decorationImage); 120 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 121 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 122- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_textureWrap); 123- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_textureWrap); 124+ if (m_context->context()->functions()->hasOpenGLFeature(QOpenGLFunctions::NPOTTextureRepeat)) { 125+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 126+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 127+ } else { 128+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 129+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 130+ } 131 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 132 133 //Draw Content 134- m_blitProgram->setAttributeBuffer(0, GL_FLOAT, m_squareVerticesOffset, 2); 135+ m_blitProgram->setAttributeArray(0, squareVertices, 2); 136 glBindTexture(GL_TEXTURE_2D, window->contentTexture()); 137 QRect r = window->contentsRect(); 138 glViewport(r.x() * scale, r.y() * scale, r.width() * scale, r.height() * scale); 139 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 140+ 141+ //Cleanup 142+ m_blitProgram->disableAttributeArray(0); 143+ m_blitProgram->disableAttributeArray(1); 144 } 145 146 QOpenGLShaderProgram *m_blitProgram = nullptr; 147 QWaylandGLContext *m_context = nullptr; 148- QOpenGLBuffer m_buffer; 149- int m_squareVerticesOffset; 150- int m_inverseSquareVerticesOffset; 151- int m_textureVerticesOffset; 152- int m_textureWrap; 153 }; 154 155 156@@ -310,13 +308,6 @@ QWaylandGLContext::QWaylandGLContext(EGLDisplay eglDisplay, QWaylandDisplay *dis 157 return; 158 } 159 160- // Create an EGL context for the decorations blitter. By using a dedicated context we don't need to make sure to not 161- // change the context state and we also use OpenGL ES 2 API independently to what the app is using to draw. 162- QVector<EGLint> eglDecorationsContextAttrs = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; 163- m_decorationsContext = eglCreateContext(m_eglDisplay, m_config, m_context, eglDecorationsContextAttrs.constData()); 164- if (m_decorationsContext == EGL_NO_CONTEXT) 165- qWarning("QWaylandGLContext: Failed to create the decorations EGLContext. Decorations will not be drawn."); 166- 167 EGLint a = EGL_MIN_SWAP_INTERVAL; 168 EGLint b = EGL_MAX_SWAP_INTERVAL; 169 if (!eglGetConfigAttrib(m_eglDisplay, m_config, a, &a) || 170@@ -406,8 +397,6 @@ void QWaylandGLContext::updateGLFormat() 171 QWaylandGLContext::~QWaylandGLContext() 172 { 173 delete m_blitter; 174- if (m_decorationsContext != EGL_NO_CONTEXT) 175- eglDestroyContext(m_eglDisplay, m_decorationsContext); 176 eglDestroyContext(m_eglDisplay, m_context); 177 } 178 179@@ -435,7 +424,12 @@ bool QWaylandGLContext::makeCurrent(QPlatformSurface *surface) 180 181 if (window->isExposed()) 182 window->setCanResize(false); 183- if (m_decorationsContext != EGL_NO_CONTEXT && !window->decoration()) 184+ // Core profiles mandate the use of VAOs when rendering. We would then need to use one 185+ // in DecorationsBlitter, but for that we would need a QOpenGLFunctions_3_2_Core instead 186+ // of the QOpenGLFunctions we use, but that would break when using a lower version context. 187+ // Instead of going crazy, just disable decorations for core profiles until we use 188+ // subsurfaces for them. 189+ if (m_format.profile() != QSurfaceFormat::CoreProfile && !window->decoration()) 190 window->createDecoration(); 191 192 if (eglSurface == EGL_NO_SURFACE) { 193@@ -466,6 +460,102 @@ void QWaylandGLContext::doneCurrent() 194 eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 195 } 196 197+#define STATE_GUARD_VERTEX_ATTRIB_COUNT 2 198+ 199+class StateGuard 200+{ 201+public: 202+ StateGuard() { 203+ QOpenGLFunctions glFuncs(QOpenGLContext::currentContext()); 204+ 205+ glGetIntegerv(GL_CURRENT_PROGRAM, (GLint *) &m_program); 206+ glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint *) &m_activeTextureUnit); 207+ glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint *) &m_texture); 208+ glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint *) &m_fbo); 209+ glGetIntegerv(GL_VIEWPORT, m_viewport); 210+ glGetIntegerv(GL_DEPTH_WRITEMASK, &m_depthWriteMask); 211+ glGetIntegerv(GL_COLOR_WRITEMASK, m_colorWriteMask); 212+ m_blend = glIsEnabled(GL_BLEND); 213+ m_depth = glIsEnabled(GL_DEPTH_TEST); 214+ m_cull = glIsEnabled(GL_CULL_FACE); 215+ m_scissor = glIsEnabled(GL_SCISSOR_TEST); 216+ for (int i = 0; i < STATE_GUARD_VERTEX_ATTRIB_COUNT; ++i) { 217+ glFuncs.glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, (GLint *) &m_vertexAttribs[i].enabled); 218+ glFuncs.glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, (GLint *) &m_vertexAttribs[i].arrayBuffer); 219+ glFuncs.glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_SIZE, &m_vertexAttribs[i].size); 220+ glFuncs.glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &m_vertexAttribs[i].stride); 221+ glFuncs.glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_TYPE, (GLint *) &m_vertexAttribs[i].type); 222+ glFuncs.glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, (GLint *) &m_vertexAttribs[i].normalized); 223+ glFuncs.glGetVertexAttribPointerv(i, GL_VERTEX_ATTRIB_ARRAY_POINTER, &m_vertexAttribs[i].pointer); 224+ } 225+ glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLint *) &m_minFilter); 226+ glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (GLint *) &m_magFilter); 227+ glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (GLint *) &m_wrapS); 228+ glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (GLint *) &m_wrapT); 229+ } 230+ 231+ ~StateGuard() { 232+ QOpenGLFunctions glFuncs(QOpenGLContext::currentContext()); 233+ 234+ glFuncs.glUseProgram(m_program); 235+ glActiveTexture(m_activeTextureUnit); 236+ glBindTexture(GL_TEXTURE_2D, m_texture); 237+ glFuncs.glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); 238+ glViewport(m_viewport[0], m_viewport[1], m_viewport[2], m_viewport[3]); 239+ glDepthMask(m_depthWriteMask); 240+ glColorMask(m_colorWriteMask[0], m_colorWriteMask[1], m_colorWriteMask[2], m_colorWriteMask[3]); 241+ if (m_blend) 242+ glEnable(GL_BLEND); 243+ if (m_depth) 244+ glEnable(GL_DEPTH_TEST); 245+ if (m_cull) 246+ glEnable(GL_CULL_FACE); 247+ if (m_scissor) 248+ glEnable(GL_SCISSOR_TEST); 249+ for (int i = 0; i < STATE_GUARD_VERTEX_ATTRIB_COUNT; ++i) { 250+ if (m_vertexAttribs[i].enabled) 251+ glFuncs.glEnableVertexAttribArray(i); 252+ GLuint prevBuf; 253+ glGetIntegerv(GL_ARRAY_BUFFER_BINDING, (GLint *) &prevBuf); 254+ glFuncs.glBindBuffer(GL_ARRAY_BUFFER, m_vertexAttribs[i].arrayBuffer); 255+ glFuncs.glVertexAttribPointer(i, m_vertexAttribs[i].size, m_vertexAttribs[i].type, 256+ m_vertexAttribs[i].normalized, m_vertexAttribs[i].stride, 257+ m_vertexAttribs[i].pointer); 258+ glFuncs.glBindBuffer(GL_ARRAY_BUFFER, prevBuf); 259+ } 260+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_minFilter); 261+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, m_magFilter); 262+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_wrapS); 263+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_wrapT); 264+ } 265+ 266+private: 267+ GLuint m_program; 268+ GLenum m_activeTextureUnit; 269+ GLuint m_texture; 270+ GLuint m_fbo; 271+ GLint m_depthWriteMask; 272+ GLint m_colorWriteMask[4]; 273+ GLboolean m_blend; 274+ GLboolean m_depth; 275+ GLboolean m_cull; 276+ GLboolean m_scissor; 277+ GLint m_viewport[4]; 278+ struct VertexAttrib { 279+ bool enabled; 280+ GLuint arrayBuffer; 281+ GLint size; 282+ GLint stride; 283+ GLenum type; 284+ bool normalized; 285+ void *pointer = nullptr; 286+ } m_vertexAttribs[STATE_GUARD_VERTEX_ATTRIB_COUNT]; 287+ GLenum m_minFilter; 288+ GLenum m_magFilter; 289+ GLenum m_wrapS; 290+ GLenum m_wrapT; 291+}; 292+ 293 void QWaylandGLContext::swapBuffers(QPlatformSurface *surface) 294 { 295 QWaylandEglWindow *window = static_cast<QWaylandEglWindow *>(surface); 296@@ -473,23 +563,15 @@ void QWaylandGLContext::swapBuffers(QPlatformSurface *surface) 297 EGLSurface eglSurface = window->eglSurface(); 298 299 if (window->decoration()) { 300- if (m_api != EGL_OPENGL_ES_API) 301- eglBindAPI(EGL_OPENGL_ES_API); 302+ makeCurrent(surface); 303 304- // save the current EGL content and surface to set it again after the blitter is done 305- EGLDisplay currentDisplay = eglGetCurrentDisplay(); 306- EGLContext currentContext = eglGetCurrentContext(); 307- EGLSurface currentSurfaceDraw = eglGetCurrentSurface(EGL_DRAW); 308- EGLSurface currentSurfaceRead = eglGetCurrentSurface(EGL_READ); 309- eglMakeCurrent(m_eglDisplay, eglSurface, eglSurface, m_decorationsContext); 310+ // Must save & restore all state. Applications are usually not prepared 311+ // for random context state changes in a swapBuffers() call. 312+ StateGuard stateGuard; 313 314 if (!m_blitter) 315 m_blitter = new DecorationsBlitter(this); 316 m_blitter->blit(window); 317- 318- if (m_api != EGL_OPENGL_ES_API) 319- eglBindAPI(m_api); 320- eglMakeCurrent(currentDisplay, currentSurfaceDraw, currentSurfaceRead, currentContext); 321 } 322 323 int swapInterval = m_supportNonBlockingSwap ? 0 : m_format.swapInterval(); 324@@ -507,6 +589,9 @@ void QWaylandGLContext::swapBuffers(QPlatformSurface *surface) 325 326 GLuint QWaylandGLContext::defaultFramebufferObject(QPlatformSurface *surface) const 327 { 328+ if (mUseNativeDefaultFbo) 329+ return 0; 330+ 331 return static_cast<QWaylandEglWindow *>(surface)->contentFBO(); 332 } 333 334diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.h b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.h 335index 93edaec..cacd909 100644 336--- a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.h 337+++ b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.h 338@@ -87,13 +87,15 @@ private: 339 QWaylandDisplay *m_display = nullptr; 340 EGLContext m_context; 341 EGLContext m_shareEGLContext; 342- EGLContext m_decorationsContext; 343 EGLConfig m_config; 344 QSurfaceFormat m_format; 345 DecorationsBlitter *m_blitter = nullptr; 346+ bool mUseNativeDefaultFbo = false; 347 uint m_api; 348 bool m_supportNonBlockingSwap = true; 349 bool m_supportSurfaceLessContext = false; 350+ 351+ friend class DecorationsBlitter; 352 }; 353 354 } 355-- 3562.20.1 357 358