From 2200febcd6e4146c0a6f9fb18eae1b9ae2e944cb Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Tue, 21 Sep 2021 12:29:17 +0300 Subject: [PATCH] Restore fbo binding after updating surface texture from EGLStreams Currently, data from client buffer EGLStream is copied to a surface texture. An fbo is used for that purpose. The main issue with it is that it doesn't restore the old framebuffer binding. The surface texture can be updated in the middle of a compositing cycle. If the framebuffer binding is not restored, any window that must be rendered in an offscreen texture won't be rendered to the offscreen texture. This change makes EglStreamSurfaceTextureWayland restore the fbo binding so the DeformEffect and software screen rotation work as expected with the proprietary NVIDIA driver. BUG: 442697 --- src/plugins/platforms/drm/egl_stream_backend.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/plugins/platforms/drm/egl_stream_backend.cpp b/src/plugins/platforms/drm/egl_stream_backend.cpp index e5bcc086b9..a62f17dd60 100644 --- a/src/plugins/platforms/drm/egl_stream_backend.cpp +++ b/src/plugins/platforms/drm/egl_stream_backend.cpp @@ -627,6 +627,11 @@ void EglStreamSurfaceTextureWayland::createFbo() glDeleteRenderbuffers(1, &m_rbo); glDeleteFramebuffers(1, &m_fbo); + GLuint oldReadFbo = 0; + GLuint oldDrawFbo = 0; + glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, reinterpret_cast(&oldReadFbo)); + glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, reinterpret_cast(&oldDrawFbo)); + glGenFramebuffers(1, &m_fbo); glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); glGenRenderbuffers(1, &m_rbo); @@ -634,17 +639,20 @@ void EglStreamSurfaceTextureWayland::createFbo() glRenderbufferStorage(GL_RENDERBUFFER, m_format, m_texture->width(), m_texture->height()); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo); glBindRenderbuffer(GL_RENDERBUFFER, 0); - glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindFramebuffer(GL_READ_FRAMEBUFFER, oldReadFbo); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, oldDrawFbo); } // Renders the contents of the given EXTERNAL_OES texture // to the scratch framebuffer, then copies this to m_texture void EglStreamSurfaceTextureWayland::copyExternalTexture(GLuint tex) { - GLint oldViewport[4], oldProgram; + GLint oldViewport[4], oldProgram, oldReadFbo, oldDrawFbo; glGetIntegerv(GL_VIEWPORT, oldViewport); glViewport(0, 0, m_texture->width(), m_texture->height()); glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); + glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, reinterpret_cast(&oldReadFbo)); + glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, reinterpret_cast(&oldDrawFbo)); glUseProgram(0); glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); glBindRenderbuffer(GL_RENDERBUFFER, m_rbo); @@ -670,7 +678,8 @@ void EglStreamSurfaceTextureWayland::copyExternalTexture(GLuint tex) glDisable(GL_TEXTURE_EXTERNAL_OES); glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0); glBindRenderbuffer(GL_RENDERBUFFER, 0); - glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindFramebuffer(GL_READ_FRAMEBUFFER, oldReadFbo); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, oldDrawFbo); glUseProgram(oldProgram); glViewport(oldViewport[0], oldViewport[1], oldViewport[2], oldViewport[3]); }