File indexing completed on 2024-11-10 04:56:57
0001 /* 0002 SPDX-FileCopyrightText: 2010 Fredrik Höglund <fredrik@kde.org> 0003 SPDX-FileCopyrightText: 2014 Marco Martin <mart@kde.org> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "contrastshader.h" 0009 0010 #include "effect/effecthandler.h" 0011 #include "opengl/glplatform.h" 0012 0013 #include <QByteArray> 0014 #include <QMatrix4x4> 0015 #include <QTextStream> 0016 #include <QVector2D> 0017 0018 #include <cmath> 0019 0020 namespace KWin 0021 { 0022 0023 ContrastShader::ContrastShader() 0024 : m_valid(false) 0025 , m_shader(nullptr) 0026 , m_opacity(1) 0027 { 0028 } 0029 0030 void ContrastShader::reset() 0031 { 0032 m_shader.reset(); 0033 0034 setIsValid(false); 0035 } 0036 0037 void ContrastShader::setOpacity(float opacity) 0038 { 0039 m_opacity = opacity; 0040 0041 ShaderManager::instance()->pushShader(m_shader.get()); 0042 m_shader->setUniform(m_opacityLocation, opacity); 0043 ShaderManager::instance()->popShader(); 0044 } 0045 0046 float ContrastShader::opacity() const 0047 { 0048 return m_opacity; 0049 } 0050 0051 void ContrastShader::setColorMatrix(const QMatrix4x4 &matrix) 0052 { 0053 if (!isValid()) { 0054 return; 0055 } 0056 0057 ShaderManager::instance()->pushShader(m_shader.get()); 0058 m_shader->setUniform(m_colorMatrixLocation, matrix); 0059 ShaderManager::instance()->popShader(); 0060 } 0061 0062 void ContrastShader::setTextureMatrix(const QMatrix4x4 &matrix) 0063 { 0064 if (!isValid()) { 0065 return; 0066 } 0067 0068 m_shader->setUniform(m_textureMatrixLocation, matrix); 0069 } 0070 0071 void ContrastShader::setModelViewProjectionMatrix(const QMatrix4x4 &matrix) 0072 { 0073 if (!isValid()) { 0074 return; 0075 } 0076 0077 m_shader->setUniform(m_mvpMatrixLocation, matrix); 0078 } 0079 0080 void ContrastShader::bind() 0081 { 0082 if (!isValid()) { 0083 return; 0084 } 0085 0086 ShaderManager::instance()->pushShader(m_shader.get()); 0087 } 0088 0089 void ContrastShader::unbind() 0090 { 0091 ShaderManager::instance()->popShader(); 0092 } 0093 0094 void ContrastShader::init() 0095 { 0096 reset(); 0097 0098 const bool gles = GLPlatform::instance()->isGLES(); 0099 const bool glsl_140 = !gles && GLPlatform::instance()->glslVersion() >= Version(1, 40); 0100 const bool core = glsl_140 || (gles && GLPlatform::instance()->glslVersion() >= Version(3, 0)); 0101 0102 QByteArray vertexSource; 0103 QByteArray fragmentSource; 0104 0105 const QByteArray attribute = core ? "in" : "attribute"; 0106 const QByteArray varying_in = core ? (gles ? "in" : "noperspective in") : "varying"; 0107 const QByteArray varying_out = core ? (gles ? "out" : "noperspective out") : "varying"; 0108 const QByteArray texture2D = core ? "texture" : "texture2D"; 0109 const QByteArray fragColor = core ? "fragColor" : "gl_FragColor"; 0110 0111 // Vertex shader 0112 // =================================================================== 0113 QTextStream stream(&vertexSource); 0114 0115 if (gles) { 0116 if (core) { 0117 stream << "#version 300 es\n\n"; 0118 } 0119 stream << "precision highp float;\n"; 0120 } else if (glsl_140) { 0121 stream << "#version 140\n\n"; 0122 } 0123 0124 stream << "uniform mat4 modelViewProjectionMatrix;\n"; 0125 stream << "uniform mat4 textureMatrix;\n"; 0126 stream << attribute << " vec4 vertex;\n\n"; 0127 stream << varying_out << " vec4 varyingTexCoords;\n"; 0128 stream << "\n"; 0129 stream << "void main(void)\n"; 0130 stream << "{\n"; 0131 stream << " varyingTexCoords = vec4(textureMatrix * vertex).stst;\n"; 0132 stream << " gl_Position = modelViewProjectionMatrix * vertex;\n"; 0133 stream << "}\n"; 0134 stream.flush(); 0135 0136 // Fragment shader 0137 // =================================================================== 0138 QTextStream stream2(&fragmentSource); 0139 0140 if (gles) { 0141 if (core) { 0142 stream2 << "#version 300 es\n\n"; 0143 } 0144 stream2 << "precision highp float;\n"; 0145 } else if (glsl_140) { 0146 stream2 << "#version 140\n\n"; 0147 } 0148 0149 stream2 << "uniform mat4 colorMatrix;\n"; 0150 stream2 << "uniform sampler2D sampler;\n"; 0151 stream2 << "uniform float opacity;\n"; 0152 stream2 << varying_in << " vec4 varyingTexCoords;\n"; 0153 0154 if (core) { 0155 stream2 << "out vec4 fragColor;\n\n"; 0156 } 0157 0158 stream2 << "void main(void)\n"; 0159 stream2 << "{\n"; 0160 stream2 << " vec4 tex = " << texture2D << "(sampler, varyingTexCoords.st);\n"; 0161 0162 stream2 << " if (opacity >= 1.0) {\n"; 0163 stream2 << " " << fragColor << " = tex * colorMatrix;\n"; 0164 stream2 << " } else {\n"; 0165 stream2 << " " << fragColor << " = tex * (opacity * colorMatrix + (1.0 - opacity) * mat4(1.0));\n"; 0166 stream2 << " }\n"; 0167 0168 stream2 << "}\n"; 0169 stream2.flush(); 0170 0171 m_shader = ShaderManager::instance()->loadShaderFromCode(vertexSource, fragmentSource); 0172 0173 if (m_shader->isValid()) { 0174 m_colorMatrixLocation = m_shader->uniformLocation("colorMatrix"); 0175 m_textureMatrixLocation = m_shader->uniformLocation("textureMatrix"); 0176 m_mvpMatrixLocation = m_shader->uniformLocation("modelViewProjectionMatrix"); 0177 m_opacityLocation = m_shader->uniformLocation("opacity"); 0178 0179 QMatrix4x4 modelViewProjection; 0180 const QSize screenSize = effects->virtualScreenSize(); 0181 modelViewProjection.ortho(0, screenSize.width(), screenSize.height(), 0, 0, 65535); 0182 ShaderManager::instance()->pushShader(m_shader.get()); 0183 m_shader->setUniform(m_colorMatrixLocation, QMatrix4x4()); 0184 m_shader->setUniform(m_textureMatrixLocation, QMatrix4x4()); 0185 m_shader->setUniform(m_mvpMatrixLocation, modelViewProjection); 0186 m_shader->setUniform(m_opacityLocation, (float)1.0); 0187 ShaderManager::instance()->popShader(); 0188 } 0189 0190 setIsValid(m_shader->isValid()); 0191 } 0192 0193 void ContrastShader::setIsValid(bool value) 0194 { 0195 m_valid = value; 0196 } 0197 0198 bool ContrastShader::isValid() const 0199 { 0200 return m_valid; 0201 } 0202 0203 } // namespace KWin