diff --git a/libkwineffects/kwinglutils.cpp b/libkwineffects/kwinglutils.cpp index 9e93e57613..e1d5b7b1c2 100644 --- a/libkwineffects/kwinglutils.cpp +++ b/libkwineffects/kwinglutils.cpp @@ -869,14 +869,17 @@ void ShaderManager::resetShader(ShaderType type) /*** GLRenderTarget ***/ bool GLRenderTarget::sSupported = false; +bool GLRenderTarget::s_blitSupported = false; QStack GLRenderTarget::s_renderTargets = QStack(); void GLRenderTarget::initStatic() { #ifdef KWIN_HAVE_OPENGLES sSupported = true; + s_blitSupported = false; #else sSupported = hasGLExtension("GL_EXT_framebuffer_object") && glFramebufferTexture2D; + s_blitSupported = hasGLExtension("GL_EXT_framebuffer_blit"); #endif } @@ -885,6 +888,11 @@ bool GLRenderTarget::isRenderTargetBound() return !s_renderTargets.isEmpty(); } +bool GLRenderTarget::blitSupported() +{ + return s_blitSupported; +} + void GLRenderTarget::pushRenderTarget(GLRenderTarget* target) { target->enable(); @@ -1037,6 +1045,25 @@ void GLRenderTarget::initFBO() mValid = true; } +void GLRenderTarget::blitFromFramebuffer(const QRect &source, const QRect &destination, GLenum filter) +{ + if (!GLRenderTarget::blitSupported()) { + return; + } +#ifndef KWIN_HAVE_OPENGLES + GLRenderTarget::pushRenderTarget(this); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebuffer); + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + const QRect s = source.isNull() ? QRect(0, 0, displayWidth(), displayHeight()) : source; + const QRect d = destination.isNull() ? QRect(0, 0, mTexture->width(), mTexture->height()) : destination; + + glBlitFramebuffer(s.x(), displayHeight() - s.y() - s.height(), s.x() + s.width(), displayHeight() - s.y(), + d.x(), mTexture->height() - d.y() - d.height(), d.x() + d.width(), mTexture->height() - d.y(), + GL_COLOR_BUFFER_BIT, filter); + GLRenderTarget::popRenderTarget(); +#endif +} + //********************************* // GLVertexBufferPrivate diff --git a/libkwineffects/kwinglutils.h b/libkwineffects/kwinglutils.h index 6a0a7f95e7..59bac2e7f3 100644 --- a/libkwineffects/kwinglutils.h +++ b/libkwineffects/kwinglutils.h @@ -412,6 +412,27 @@ public: static void pushRenderTarget(GLRenderTarget *target); static GLRenderTarget *popRenderTarget(); static bool isRenderTargetBound(); + /** + * Whether the GL_EXT_framebuffer_blit extension is supported. + * This functionality is not available in OpenGL ES 2.0. + * + * @returns whether framebuffer blitting is supported. + * @since 4.8 + **/ + static bool blitSupported(); + + /** + * Blits the content of the current draw framebuffer into the texture attached to this FBO. + * + * Be aware that framebuffer blitting may not be supported on all hardware. Use @link blitSupported to check whether + * it is supported. + * @param source Geometry in screen coordinates which should be blitted, if not specified complete framebuffer is used + * @param destination Geometry in attached texture, if not specified complete texture is used as destination + * @param filter The filter to use if blitted content needs to be scaled. + * @see blitSupported + * @since 4.8 + **/ + void blitFromFramebuffer(const QRect &source = QRect(), const QRect &destination = QRect(), GLenum filter = GL_LINEAR); protected: @@ -420,6 +441,7 @@ protected: private: static bool sSupported; + static bool s_blitSupported; static QStack s_renderTargets; GLTexture* mTexture; diff --git a/libkwineffects/kwinglutils_funcs.cpp b/libkwineffects/kwinglutils_funcs.cpp index d935a7f99d..b05c1c3263 100644 --- a/libkwineffects/kwinglutils_funcs.cpp +++ b/libkwineffects/kwinglutils_funcs.cpp @@ -79,6 +79,7 @@ glFramebufferTexture3D_func glFramebufferTexture3D; glFramebufferRenderbuffer_func glFramebufferRenderbuffer; glGetFramebufferAttachmentParameteriv_func glGetFramebufferAttachmentParameteriv; glGenerateMipmap_func glGenerateMipmap; +glBlitFramebuffer_func glBlitFramebuffer; // Shader functions glCreateShader_func glCreateShader; glShaderSource_func glShaderSource; @@ -225,6 +226,11 @@ void glResolveFunctions() glGetFramebufferAttachmentParameteriv = NULL; glGenerateMipmap = NULL; } + if (hasGLExtension("GL_EXT_framebuffer_blit")) { + glBlitFramebuffer = (glBlitFramebuffer_func) getProcAddress("glBlitFramebufferEXT"); + } else { + glBlitFramebuffer = NULL; + } if (hasGLExtension("GL_ARB_shading_language_100") && hasGLExtension("GL_ARB_fragment_shader")) { GL_RESOLVE_WITH_EXT(glCreateShader, glCreateShaderObjectARB); GL_RESOLVE_WITH_EXT(glShaderSource, glShaderSourceARB); diff --git a/libkwineffects/kwinglutils_funcs.h b/libkwineffects/kwinglutils_funcs.h index 45df4d5ff3..2f5829c09d 100644 --- a/libkwineffects/kwinglutils_funcs.h +++ b/libkwineffects/kwinglutils_funcs.h @@ -232,6 +232,7 @@ typedef void (*glFramebufferTexture3D_func)(GLenum target, GLenum attachment, GL typedef void (*glFramebufferRenderbuffer_func)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); typedef void (*glGetFramebufferAttachmentParameteriv_func)(GLenum target, GLenum attachment, GLenum pname, GLint *params); typedef void (*glGenerateMipmap_func)(GLenum target); +typedef void (*glBlitFramebuffer_func)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); extern KWIN_EXPORT glIsRenderbuffer_func glIsRenderbuffer; extern KWIN_EXPORT glBindRenderbuffer_func glBindRenderbuffer; extern KWIN_EXPORT glDeleteRenderbuffers_func glDeleteRenderbuffers; @@ -249,6 +250,7 @@ extern KWIN_EXPORT glFramebufferTexture3D_func glFramebufferTexture3D; extern KWIN_EXPORT glFramebufferRenderbuffer_func glFramebufferRenderbuffer; extern KWIN_EXPORT glGetFramebufferAttachmentParameteriv_func glGetFramebufferAttachmentParameteriv; extern KWIN_EXPORT glGenerateMipmap_func glGenerateMipmap; +extern KWIN_EXPORT glBlitFramebuffer_func glBlitFramebuffer; // Shader stuff typedef GLuint(*glCreateShader_func)(GLenum); typedef GLvoid(*glShaderSource_func)(GLuint, GLsizei, const GLchar**, const GLint*);