From c2a4f81927f9410c2f9b811487c290829f0f1019 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Fri, 21 Sep 2012 11:25:08 +0200 Subject: [PATCH] Introduce a helper class to automatically push/pop Shaders The ShaderBinder class can be used for the case that a block of code should be executed with a given Shader being bound. This is useful for all the cases where there is a if-block for OpenGL2 execution with a Shader being pushed in the first line to the ShaderManager and popped in the last line of the block. With the helper this can be simplified to: ShaderBinder binder(myCustomShader); or ShaderBinder binder(ShaderManager::GenericShader); The ctor of ShaderBinder pushes the given Shader to the stack and once the helper goes out of scope it will be popped again from the stack. In addition the helper can take care of OpenGL 1 compositing, that is it just does nothing. So it can also be used where there is a shared OpenGL1 and OpenGL2 code path where the Shader should only be pushed in OpenGL2. This basically removes all the checks for the compositing type before pushing/popping a Shader to the stack. REVIEW: 106521 --- effects/cube/cube.cpp | 22 ++----- effects/explosion/explosion.cpp | 3 +- effects/flipswitch/flipswitch.cpp | 13 ++-- effects/invert/invert.cpp | 3 +- effects/logout/logout.cpp | 6 +- effects/lookingglass/lookingglass.cpp | 6 +- effects/magnifier/magnifier.cpp | 8 +-- effects/mousemark/mousemark.cpp | 7 +-- effects/resize/resize.cpp | 7 +-- effects/showfps/showfps.cpp | 14 +---- effects/showpaint/showpaint.cpp | 7 +-- effects/snaphelper/snaphelper.cpp | 7 +-- effects/trackmouse/trackmouse.cpp | 10 ++- lanczosfilter.cpp | 11 ++-- libkwineffects/kwinglutils.h | 89 +++++++++++++++++++++++++++ scene_opengl.cpp | 13 ++-- 16 files changed, 129 insertions(+), 97 deletions(-) diff --git a/effects/cube/cube.cpp b/effects/cube/cube.cpp index da594db957..dba9c135d1 100644 --- a/effects/cube/cube.cpp +++ b/effects/cube/cube.cpp @@ -213,10 +213,9 @@ void CubeEffect::loadConfig(QString config) } // set the cap color on the shader - if (effects->compositingType() == OpenGL2Compositing && m_capShader->isValid()) { - ShaderManager::instance()->pushShader(m_capShader); + if (m_capShader->isValid()) { + ShaderBinder binder(m_capShader); m_capShader->setUniform("u_capColor", capColor); - ShaderManager::instance()->popShader(); } } @@ -311,7 +310,7 @@ bool CubeEffect::loadShader() kError(1212) << "The cylinder shader failed to load!" << endl; return false; } else { - shaderManager->pushShader(cylinderShader); + ShaderBinder binder(cylinderShader); cylinderShader->setUniform("sampler", 0); QMatrix4x4 projection; float fovy = 60.0f; @@ -334,7 +333,6 @@ bool CubeEffect::loadShader() cylinderShader->setUniform(GLShader::WindowTransformation, identity); QRect rect = effects->clientArea(FullArea, activeScreen, effects->currentDesktop()); cylinderShader->setUniform("width", (float)rect.width() * 0.5f); - shaderManager->popShader(); } // TODO: use generic shader - currently it is failing in alpha/brightness manipulation sphereShader = new GLShader(sphereVertexshader, fragmentshader); @@ -342,7 +340,7 @@ bool CubeEffect::loadShader() kError(1212) << "The sphere shader failed to load!" << endl; return false; } else { - shaderManager->pushShader(sphereShader); + ShaderBinder binder(sphereShader); sphereShader->setUniform("sampler", 0); QMatrix4x4 projection; float fovy = 60.0f; @@ -367,7 +365,6 @@ bool CubeEffect::loadShader() sphereShader->setUniform("width", (float)rect.width() * 0.5f); sphereShader->setUniform("height", (float)rect.height() * 0.5f); sphereShader->setUniform("u_offset", QVector2D(0, 0)); - shaderManager->popShader(); checkGLError("Loading Sphere Shader"); } return true; @@ -404,15 +401,10 @@ void CubeEffect::paintScreen(int mask, QRegion region, ScreenPaintData& data) // wallpaper if (wallpaper) { - if (effects->compositingType() == OpenGL2Compositing) { - ShaderManager::instance()->pushShader(ShaderManager::SimpleShader); - } + ShaderBinder binder(ShaderManager::SimpleShader); wallpaper->bind(); wallpaper->render(region, rect); wallpaper->unbind(); - if (effects->compositingType() == OpenGL2Compositing) { - ShaderManager::instance()->popShader(); - } } glEnable(GL_BLEND); @@ -500,7 +492,7 @@ void CubeEffect::paintScreen(int mask, QRegion region, ScreenPaintData& data) ShaderManager *shaderManager = ShaderManager::instance(); if (shaderManager->isValid() && m_reflectionShader->isValid()) { // ensure blending is enabled - no attribute stack - shaderManager->pushShader(m_reflectionShader); + ShaderBinder binder(m_reflectionShader); QMatrix4x4 windowTransformation; windowTransformation.translate(rect.x() + rect.width() * 0.5f, 0.0, 0.0); m_reflectionShader->setUniform("windowTransformation", windowTransformation); @@ -525,8 +517,6 @@ void CubeEffect::paintScreen(int mask, QRegion region, ScreenPaintData& data) vbo->reset(); vbo->setData(6, 3, verts.data(), texcoords.data()); vbo->render(GL_TRIANGLES); - - shaderManager->popShader(); } else { #ifndef KWIN_HAVE_OPENGLES glColor4f(0.0, 0.0, 0.0, alpha); diff --git a/effects/explosion/explosion.cpp b/effects/explosion/explosion.cpp index 63be488fce..5dd029e0c2 100644 --- a/effects/explosion/explosion.cpp +++ b/effects/explosion/explosion.cpp @@ -80,10 +80,9 @@ bool ExplosionEffect::loadData() kError(1212) << "The shader failed to load!" << endl; return false; } else { - ShaderManager::instance()->pushShader(mShader); + ShaderBinder binder(mShader); mShader->setUniform("startOffsetTexture", 4); mShader->setUniform("endOffsetTexture", 5); - ShaderManager::instance()->popShader(); } mStartOffsetTex = new GLTexture(starttexture); diff --git a/effects/flipswitch/flipswitch.cpp b/effects/flipswitch/flipswitch.cpp index 223ae8ec64..da5915af90 100644 --- a/effects/flipswitch/flipswitch.cpp +++ b/effects/flipswitch/flipswitch.cpp @@ -219,7 +219,6 @@ void FlipSwitchEffect::paintScreen(int mask, QRegion region, ScreenPaintData& da // TODO: move to kwinglutils QMatrix4x4 origProjection; QMatrix4x4 origModelview; - ShaderManager *shaderManager = ShaderManager::instance(); if (effects->numScreens() > 1) { // unfortunatelly we have to change the projection matrix in dual screen mode QRect fullRect = effects->clientArea(FullArea, effects->activeScreen(), effects->currentDesktop()); @@ -265,13 +264,13 @@ void FlipSwitchEffect::paintScreen(int mask, QRegion region, ScreenPaintData& da projection.frustum(xmin * xminFactor, xmax * xmaxFactor, ymin * yminFactor, ymax * ymaxFactor, zNear, zFar); QMatrix4x4 modelview; modelview.translate(xTranslate, yTranslate, 0.0); - if (shaderManager->isShaderBound()) { - GLShader *shader = shaderManager->pushShader(ShaderManager::GenericShader); + if (effects->compositingType() == OpenGL2Compositing) { + ShaderBinder binder(ShaderManager::GenericShader); + GLShader *shader = binder.shader(); origProjection = shader->getUniformMatrix4x4("projection"); origModelview = shader->getUniformMatrix4x4("modelview"); shader->setUniform("projection", projection); shader->setUniform("modelview", origModelview * modelview); - shaderManager->popShader(); } else { #ifndef KWIN_HAVE_OPENGLES glMatrixMode(GL_PROJECTION); @@ -377,11 +376,11 @@ void FlipSwitchEffect::paintScreen(int mask, QRegion region, ScreenPaintData& da } if (effects->numScreens() > 1) { - if (shaderManager->isShaderBound()) { - GLShader *shader = shaderManager->pushShader(ShaderManager::GenericShader); + if (effects->compositingType() == OpenGL2Compositing) { + ShaderBinder binder(ShaderManager::GenericShader); + GLShader *shader = binder.shader(); shader->setUniform("projection", origProjection); shader->setUniform("modelview", origModelview); - shaderManager->popShader(); } else { #ifndef KWIN_HAVE_OPENGLES popMatrix(); diff --git a/effects/invert/invert.cpp b/effects/invert/invert.cpp index 327d24e835..04b6475e2d 100644 --- a/effects/invert/invert.cpp +++ b/effects/invert/invert.cpp @@ -124,11 +124,10 @@ void InvertEffect::paintEffectFrame(KWin::EffectFrame* frame, QRegion region, do { if (m_valid && m_allWindows) { frame->setShader(m_shader); - ShaderManager::instance()->pushShader(m_shader); + ShaderBinder binder(m_shader); m_shader->setUniform("screenTransformation", QMatrix4x4()); m_shader->setUniform("windowTransformation", QMatrix4x4()); effects->paintEffectFrame(frame, region, opacity, frameOpacity); - ShaderManager::instance()->popShader(); } else { effects->paintEffectFrame(frame, region, opacity, frameOpacity); } diff --git a/effects/logout/logout.cpp b/effects/logout/logout.cpp index 2c068e251e..1d4023f9c6 100644 --- a/effects/logout/logout.cpp +++ b/effects/logout/logout.cpp @@ -307,7 +307,7 @@ void LogoutEffect::renderVignetting() QMatrix4x4 projection = ShaderManager::instance()->pushShader(KWin::ShaderManager::SimpleShader)->getUniformMatrix4x4("projection"); ShaderManager::instance()->popShader(); - ShaderManager::instance()->pushShader(m_vignettingShader); + ShaderBinder binder(m_vignettingShader); m_vignettingShader->setUniform(KWin::GLShader::ProjectionMatrix, projection); m_vignettingShader->setUniform("u_progress", (float)progress * 0.9f); glEnable(GL_BLEND); @@ -335,7 +335,6 @@ void LogoutEffect::renderVignetting() } glDisable(GL_SCISSOR_TEST); glDisable(GL_BLEND); - ShaderManager::instance()->popShader(); } void LogoutEffect::renderVignettingLegacy() @@ -384,7 +383,7 @@ void LogoutEffect::renderBlurTexture() return; } // Unmodified base image - ShaderManager::instance()->pushShader(m_blurShader); + ShaderBinder binder(m_blurShader); m_blurShader->setUniform(GLShader::Offset, QVector2D(0, 0)); m_blurShader->setUniform(GLShader::ModulationConstant, QVector4D(1.0, 1.0, 1.0, 1.0)); m_blurShader->setUniform(GLShader::Saturation, 1.0); @@ -396,7 +395,6 @@ void LogoutEffect::renderBlurTexture() blurTexture->render(infiniteRegion(), QRect(0, 0, displayWidth(), displayHeight())); blurTexture->unbind(); glDisable(GL_BLEND); - ShaderManager::instance()->popShader(); checkGLError("Render blur texture"); } diff --git a/effects/lookingglass/lookingglass.cpp b/effects/lookingglass/lookingglass.cpp index 4b58178482..167481838e 100644 --- a/effects/lookingglass/lookingglass.cpp +++ b/effects/lookingglass/lookingglass.cpp @@ -119,9 +119,8 @@ bool LookingGlassEffect::loadData() const QString fragmentshader = KGlobal::dirs()->findResource("data", "kwin/lookingglass.frag"); m_shader = ShaderManager::instance()->loadFragmentShader(ShaderManager::SimpleShader, fragmentshader); if (m_shader->isValid()) { - ShaderManager::instance()->pushShader(m_shader); + ShaderBinder binder(m_shader); m_shader->setUniform("u_textureSize", QVector2D(displayWidth(), displayHeight())); - ShaderManager::instance()->popShader(); } else { kError(1212) << "The shader failed to load!" << endl; return false; @@ -242,12 +241,11 @@ void LookingGlassEffect::postPaintScreen() m_texture->bind(); // Use the shader - ShaderManager::instance()->pushShader(m_shader); + ShaderBinder binder(m_shader); m_shader->setUniform("u_zoom", (float)zoom); m_shader->setUniform("u_radius", (float)radius); m_shader->setUniform("u_cursor", QVector2D(cursorPos().x(), cursorPos().y())); m_vbo->render(GL_TRIANGLES); - ShaderManager::instance()->popShader(); m_texture->unbind(); } } diff --git a/effects/magnifier/magnifier.cpp b/effects/magnifier/magnifier.cpp index 50fdcc5d52..f1e2c3d1c6 100644 --- a/effects/magnifier/magnifier.cpp +++ b/effects/magnifier/magnifier.cpp @@ -168,13 +168,9 @@ void MagnifierEffect::paintScreen(int mask, QRegion region, ScreenPaintData& dat verts << area.right() + FRAME_WIDTH << area.bottom() + FRAME_WIDTH; verts << area.right() + FRAME_WIDTH << area.bottom() + 1; vbo->setData(verts.size() / 2, 2, verts.constData(), NULL); - if (effects->compositingType() == OpenGL2Compositing) { - ShaderManager::instance()->pushShader(ShaderManager::ColorShader); - } + + ShaderBinder binder(ShaderManager::ColorShader); vbo->render(GL_TRIANGLES); - if (effects->compositingType() == OpenGL2Compositing) { - ShaderManager::instance()->popShader(); - } } if (effects->compositingType() == XRenderCompositing) { #ifdef KWIN_HAVE_XRENDER_COMPOSITING diff --git a/effects/mousemark/mousemark.cpp b/effects/mousemark/mousemark.cpp index 5c032e83eb..23f67a307f 100644 --- a/effects/mousemark/mousemark.cpp +++ b/effects/mousemark/mousemark.cpp @@ -116,9 +116,7 @@ void MouseMarkEffect::paintScreen(int mask, QRegion region, ScreenPaintData& dat vbo->reset(); vbo->setUseColor(true); vbo->setColor(color); - if (effects->compositingType() == OpenGL2Compositing) { - ShaderManager::instance()->pushShader(ShaderManager::ColorShader); - } + ShaderBinder binder(ShaderManager::ColorShader); QVector verts; foreach (const Mark & mark, marks) { verts.clear(); @@ -138,9 +136,6 @@ void MouseMarkEffect::paintScreen(int mask, QRegion region, ScreenPaintData& dat vbo->setData(verts.size() / 2, 2, verts.data(), NULL); vbo->render(GL_LINE_STRIP); } - if (effects->compositingType() == OpenGL2Compositing) { - ShaderManager::instance()->popShader(); - } glLineWidth(1.0); #ifndef KWIN_HAVE_OPENGLES glDisable(GL_LINE_SMOOTH); diff --git a/effects/resize/resize.cpp b/effects/resize/resize.cpp index 5a4715f6f0..990d283d9f 100644 --- a/effects/resize/resize.cpp +++ b/effects/resize/resize.cpp @@ -86,9 +86,7 @@ void ResizeEffect::paintWindow(EffectWindow* w, int mask, QRegion region, Window GLVertexBuffer *vbo = GLVertexBuffer::streamingBuffer(); vbo->reset(); vbo->setUseColor(true); - if (effects->compositingType() == OpenGL2Compositing) { - ShaderManager::instance()->pushShader(ShaderManager::ColorShader); - } + ShaderBinder binder(ShaderManager::ColorShader); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); color.setAlphaF(alpha); @@ -105,9 +103,6 @@ void ResizeEffect::paintWindow(EffectWindow* w, int mask, QRegion region, Window } vbo->setData(verts.count() / 2, 2, verts.data(), NULL); vbo->render(GL_TRIANGLES); - if (effects->compositingType() == OpenGL2Compositing) { - ShaderManager::instance()->popShader(); - } glDisable(GL_BLEND); } diff --git a/effects/showfps/showfps.cpp b/effects/showfps/showfps.cpp index 5914f3923f..0e7f275f43 100644 --- a/effects/showfps/showfps.cpp +++ b/effects/showfps/showfps.cpp @@ -176,9 +176,7 @@ void ShowFpsEffect::paintGL(int fps) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // TODO painting first the background white and then the contents // means that the contents also blend with the background, I guess - if (effects->compositingType() == OpenGL2Compositing) { - ShaderManager::instance()->pushShader(ShaderManager::ColorShader); - } + ShaderBinder binder(ShaderManager::ColorShader); GLVertexBuffer *vbo = GLVertexBuffer::streamingBuffer(); vbo->reset(); QColor color(255, 255, 255); @@ -228,9 +226,6 @@ void ShowFpsEffect::paintGL(int fps) // Paint amount of rendered pixels graph paintDrawSizeGraph(x, y); - if (effects->compositingType() == OpenGL2Compositing) { - ShaderManager::instance()->popShader(); - } // Paint FPS numerical value paintFPSText(fps); @@ -449,14 +444,11 @@ void ShowFpsEffect::paintFPSText(int fps) delete fpsText; fpsText = new GLTexture(im); fpsText->bind(); + ShaderBinder binder(ShaderManager::SimpleShader); if (effects->compositingType() == OpenGL2Compositing) { - GLShader *shader = ShaderManager::instance()->pushShader(ShaderManager::SimpleShader); - shader->setUniform("offset", QVector2D(0, 0)); + binder.shader()->setUniform("offset", QVector2D(0, 0)); } fpsText->render(QRegion(fpsTextRect), fpsTextRect); - if (effects->compositingType() == OpenGL2Compositing) { - ShaderManager::instance()->popShader(); - } fpsText->unbind(); effects->addRepaint(fpsTextRect); } diff --git a/effects/showpaint/showpaint.cpp b/effects/showpaint/showpaint.cpp index ef475aaf3e..4cbd9ae6c7 100644 --- a/effects/showpaint/showpaint.cpp +++ b/effects/showpaint/showpaint.cpp @@ -76,9 +76,7 @@ void ShowPaintEffect::paintGL() GLVertexBuffer *vbo = GLVertexBuffer::streamingBuffer(); vbo->reset(); vbo->setUseColor(true); - if (effects->compositingType() == OpenGL2Compositing) { - ShaderManager::instance()->pushShader(ShaderManager::ColorShader); - } + ShaderBinder binder(ShaderManager::ColorShader); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); QColor color = colors[ color_index ]; @@ -96,9 +94,6 @@ void ShowPaintEffect::paintGL() } vbo->setData(verts.count() / 2, 2, verts.data(), NULL); vbo->render(GL_TRIANGLES); - if (effects->compositingType() == OpenGL2Compositing) { - ShaderManager::instance()->popShader(); - } glDisable(GL_BLEND); } diff --git a/effects/snaphelper/snaphelper.cpp b/effects/snaphelper/snaphelper.cpp index 924183aff7..cdb00bc65d 100644 --- a/effects/snaphelper/snaphelper.cpp +++ b/effects/snaphelper/snaphelper.cpp @@ -81,9 +81,7 @@ void SnapHelperEffect::postPaintScreen() GLVertexBuffer *vbo = GLVertexBuffer::streamingBuffer(); vbo->reset(); vbo->setUseColor(true); - if (effects->compositingType() == OpenGL2Compositing) { - ShaderManager::instance()->pushShader(ShaderManager::ColorShader); - } + ShaderBinder binder(ShaderManager::ColorShader); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -122,9 +120,6 @@ void SnapHelperEffect::postPaintScreen() } vbo->setData(verts.count() / 2, 2, verts.data(), NULL); vbo->render(GL_LINES); - if (effects->compositingType() == OpenGL2Compositing) { - ShaderManager::instance()->popShader(); - } glDisable(GL_BLEND); glLineWidth(1.0); diff --git a/effects/trackmouse/trackmouse.cpp b/effects/trackmouse/trackmouse.cpp index 350c217bd1..602c9a5353 100644 --- a/effects/trackmouse/trackmouse.cpp +++ b/effects/trackmouse/trackmouse.cpp @@ -125,11 +125,10 @@ void TrackMouseEffect::paintScreen(int mask, QRegion region, ScreenPaintData& da return; if ( effects->isOpenGLCompositing() && m_texture[0] && m_texture[1]) { - GLShader *shader(0); + ShaderBinder binder(ShaderManager::GenericShader); + GLShader *shader(binder.shader()); QMatrix4x4 modelview; - if (effects->compositingType() == OpenGL2Compositing) { - ShaderManager::instance()->pushShader(ShaderManager::GenericShader); - shader = ShaderManager::instance()->getBoundShader(); + if (shader) { modelview = shader->getUniformMatrix4x4("modelview"); } glEnable(GL_BLEND); @@ -154,9 +153,8 @@ void TrackMouseEffect::paintScreen(int mask, QRegion region, ScreenPaintData& da popMatrix(); } glDisable(GL_BLEND); - if (effects->compositingType() == OpenGL2Compositing) { + if (shader) { shader->setUniform(GLShader::ModelViewMatrix, modelview); - ShaderManager::instance()->popShader(); } } #ifdef KWIN_HAVE_XRENDER_COMPOSITING diff --git a/lanczosfilter.cpp b/lanczosfilter.cpp index 07ff3a419a..67277c6736 100644 --- a/lanczosfilter.cpp +++ b/lanczosfilter.cpp @@ -210,7 +210,8 @@ void LanczosFilter::performPaint(EffectWindowImpl* w, int mask, QRegion region, const qreal rgb = data.brightness() * data.opacity(); const qreal a = data.opacity(); - GLShader *shader = ShaderManager::instance()->pushShader(ShaderManager::SimpleShader); + ShaderBinder binder(ShaderManager::SimpleShader); + GLShader *shader = binder.shader(); shader->setUniform(GLShader::Offset, QVector2D(0, 0)); shader->setUniform(GLShader::ModulationConstant, QVector4D(rgb, rgb, rgb, a)); shader->setUniform(GLShader::Saturation, data.saturation()); @@ -218,7 +219,6 @@ void LanczosFilter::performPaint(EffectWindowImpl* w, int mask, QRegion region, cachedTexture->render(region, textureRect, hardwareClipping); - ShaderManager::instance()->popShader(); glDisable(GL_BLEND); } else { prepareRenderStates(cachedTexture, data.opacity(), data.brightness(), data.saturation()); @@ -347,7 +347,8 @@ void LanczosFilter::performPaint(EffectWindowImpl* w, int mask, QRegion region, const qreal rgb = data.brightness() * data.opacity(); const qreal a = data.opacity(); - GLShader *shader = ShaderManager::instance()->pushShader(ShaderManager::SimpleShader); + ShaderBinder binder(ShaderManager::SimpleShader); + GLShader *shader = binder.shader(); shader->setUniform(GLShader::Offset, QVector2D(0, 0)); shader->setUniform(GLShader::ModulationConstant, QVector4D(rgb, rgb, rgb, a)); shader->setUniform(GLShader::Saturation, data.saturation()); @@ -355,7 +356,6 @@ void LanczosFilter::performPaint(EffectWindowImpl* w, int mask, QRegion region, cache->render(region, textureRect, hardwareClipping); - ShaderManager::instance()->popShader(); glDisable(GL_BLEND); } else { prepareRenderStates(cache, data.opacity(), data.brightness(), data.saturation()); @@ -621,11 +621,10 @@ bool LanczosShader::init() !(gl->isRadeon() && gl->chipClass() < R600)) { m_shader = ShaderManager::instance()->loadFragmentShader(ShaderManager::SimpleShader, ":/resources/lanczos-fragment.glsl"); if (m_shader->isValid()) { - ShaderManager::instance()->pushShader(m_shader); + ShaderBinder binder(m_shader); m_uTexUnit = m_shader->uniformLocation("texUnit"); m_uKernel = m_shader->uniformLocation("kernel"); m_uOffsets = m_shader->uniformLocation("offsets"); - ShaderManager::instance()->popShader(); return true; } else { kDebug(1212) << "Shader is not valid"; diff --git a/libkwineffects/kwinglutils.h b/libkwineffects/kwinglutils.h index 679443edba..445ddc7ccc 100644 --- a/libkwineffects/kwinglutils.h +++ b/libkwineffects/kwinglutils.h @@ -394,6 +394,95 @@ private: static ShaderManager *s_shaderManager; }; +/** + * An helper class to push a Shader on to ShaderManager's stack and ensuring that the Shader + * gets popped again from the stack automatically once the object goes out of life. + * + * How to use: + * @code + * { + * GLShader *myCustomShaderIWantToPush; + * ShaderBinder binder(myCustomShaderIWantToPush); + * // do stuff with the shader being pushed on the stack + * } + * // here the Shader is automatically popped as helper does no longer exist. + * @endcode + * + * This class takes care for the case that the Compositor uses OpenGL 1 and the ShaderManager is + * not valid. In that case the helper does not do anything. So this helper can be used to simplify + * the code to remove checks for OpenGL 1/2. + * @since 4.10 + **/ +class KWIN_EXPORT ShaderBinder +{ +public: + /** + * @brief Pushes the Shader of the given @p type to the ShaderManager's stack. + * + * @param type The built-in Shader type + * @param reset Whether all uniforms should be reset to their default values. Defaults to false. + * @see ShaderManager::pushShader + **/ + ShaderBinder(ShaderManager::ShaderType type, bool reset = false); + /** + * @brief Pushes the given @p shader to the ShaderManager's stack. + * + * @param shader The Shader to push on the stack + * @see ShaderManager::pushShader + **/ + ShaderBinder(GLShader *shader); + ~ShaderBinder(); + + /** + * @return The Shader pushed to the Stack. On OpenGL 1 this returns a @c null pointer. + **/ + GLShader *shader(); + +private: + GLShader *m_shader; +}; + +inline +ShaderBinder::ShaderBinder(ShaderManager::ShaderType type, bool reset) + : m_shader(NULL) +{ +#ifndef KWIN_HAVE_OPENGLES + if (!ShaderManager::instance()->isValid()) { + return; + } +#endif + m_shader = ShaderManager::instance()->pushShader(type, reset); +} + +inline +ShaderBinder::ShaderBinder(GLShader *shader) + : m_shader(shader) +{ +#ifndef KWIN_HAVE_OPENGLES + if (!ShaderManager::instance()->isValid()) { + return; + } +#endif + ShaderManager::instance()->pushShader(shader); +} + +inline +ShaderBinder::~ShaderBinder() +{ +#ifndef KWIN_HAVE_OPENGLES + if (!ShaderManager::instance()->isValid()) { + return; + } +#endif + ShaderManager::instance()->popShader(); +} + +inline +GLShader* ShaderBinder::shader() +{ + return m_shader; +} + /** * @short Render target object * diff --git a/scene_opengl.cpp b/scene_opengl.cpp index 3e4290a556..164d463eae 100644 --- a/scene_opengl.cpp +++ b/scene_opengl.cpp @@ -447,14 +447,11 @@ SceneOpenGL2::~SceneOpenGL2() void SceneOpenGL2::paintGenericScreen(int mask, ScreenPaintData data) { - ShaderManager *shaderManager = ShaderManager::instance(); + ShaderBinder binder(ShaderManager::GenericShader); - GLShader *shader = shaderManager->pushShader(ShaderManager::GenericShader); - shader->setUniform(GLShader::ScreenTransformation, transformation(mask, data)); + binder.shader()->setUniform(GLShader::ScreenTransformation, transformation(mask, data)); Scene::paintGenericScreen(mask, data); - - shaderManager->popShader(); } void SceneOpenGL2::doPaintBackground(const QVector< float >& vertices) @@ -464,12 +461,10 @@ void SceneOpenGL2::doPaintBackground(const QVector< float >& vertices) vbo->setUseColor(true); vbo->setData(vertices.count() / 2, 2, vertices.data(), NULL); - GLShader *shader = ShaderManager::instance()->pushShader(ShaderManager::ColorShader); - shader->setUniform(GLShader::Offset, QVector2D(0, 0)); + ShaderBinder binder(ShaderManager::ColorShader); + binder.shader()->setUniform(GLShader::Offset, QVector2D(0, 0)); vbo->render(GL_TRIANGLES); - - ShaderManager::instance()->popShader(); } SceneOpenGL::Window *SceneOpenGL2::createWindow(Toplevel *t)