summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorTomaž Vajngerl <tomaz.vajngerl@collabora.co.uk>2016-05-20 14:59:24 +0900
committerTomaž Vajngerl <quikee@gmail.com>2016-05-23 23:34:31 +0000
commit3cac38b2311538a0aecca765eb62c30c5098a85c (patch)
tree81a3119dedeadada66dcade0ac0a2b42981b7a38 /vcl
parentac06e4ef9d56677e1469e94b99045b3e02c7511f (diff)
opengl: combined shaders to reduce shader switching
Combine most common shaders for non-texture drawing and texture drawing into two combined shaders. Inside the shader we switch between the code paths with if statements. Using if statements (or any other branching statements) is discouraged inside shaders but on the other hand we reduce program state changes if we have less shader changes - which is more important for us as we want to push more work to the GPU. Change-Id: I6701b93faa9b0f55dd0af6d983ce4c2de4539c70 Reviewed-on: https://gerrit.libreoffice.org/25357 Reviewed-by: Tomaž Vajngerl <quikee@gmail.com> Tested-by: Tomaž Vajngerl <quikee@gmail.com>
Diffstat (limited to 'vcl')
-rw-r--r--vcl/Package_opengl.mk4
-rw-r--r--vcl/inc/opengl/program.hxx19
-rw-r--r--vcl/opengl/combinedFragmentShader.glsl45
-rw-r--r--vcl/opengl/combinedTextureFragmentShader.glsl64
-rw-r--r--vcl/opengl/combinedTextureVertexShader.glsl32
-rw-r--r--vcl/opengl/combinedVertexShader.glsl47
-rw-r--r--vcl/opengl/gdiimpl.cxx69
-rw-r--r--vcl/opengl/program.cxx18
8 files changed, 273 insertions, 25 deletions
diff --git a/vcl/Package_opengl.mk b/vcl/Package_opengl.mk
index a0f6e9a27128..2fa917eeac42 100644
--- a/vcl/Package_opengl.mk
+++ b/vcl/Package_opengl.mk
@@ -21,6 +21,10 @@ $(eval $(call gb_Package_add_files,vcl_opengl_shader,$(LIBO_ETC_FOLDER)/opengl,\
invert50FragmentShader.glsl \
convolutionFragmentShader.glsl \
linearGradientFragmentShader.glsl \
+ combinedTextureFragmentShader.glsl \
+ combinedTextureVertexShader.glsl \
+ combinedFragmentShader.glsl \
+ combinedVertexShader.glsl \
lineFragmentShader.glsl \
lineVertexShader.glsl \
maskFragmentShader.glsl \
diff --git a/vcl/inc/opengl/program.hxx b/vcl/inc/opengl/program.hxx
index 5944c72be127..2fab98c6b4d5 100644
--- a/vcl/inc/opengl/program.hxx
+++ b/vcl/inc/opengl/program.hxx
@@ -27,6 +27,21 @@
typedef std::unordered_map< OString, GLuint, OStringHash > UniformCache;
typedef std::list< OpenGLTexture > TextureList;
+enum class TextureShaderType
+{
+ Normal = 0,
+ Blend,
+ Masked,
+ Diff,
+ MaskedColor
+};
+
+enum class DrawShaderType
+{
+ Normal = 0,
+ Line
+};
+
class VCL_PLUGIN_PUBLIC OpenGLProgram
{
private:
@@ -78,6 +93,10 @@ public:
void SetTransform( const OString& rName, const OpenGLTexture& rTexture,
const basegfx::B2DPoint& rNull, const basegfx::B2DPoint& rX,
const basegfx::B2DPoint& rY );
+ void SetIdentityTransform(const OString& rName);
+ void SetShaderType(TextureShaderType eTextureShaderType);
+ void SetShaderType(DrawShaderType eDrawShaderType);
+
void SetBlendMode( GLenum nSFactor, GLenum nDFactor );
void ApplyMatrix(float fWidth, float fHeight, float fPixelOffset = 0.0f);
diff --git a/vcl/opengl/combinedFragmentShader.glsl b/vcl/opengl/combinedFragmentShader.glsl
new file mode 100644
index 000000000000..c44e75c09373
--- /dev/null
+++ b/vcl/opengl/combinedFragmentShader.glsl
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+varying float fade_factor; // 0->1 fade factor used for AA
+uniform vec4 color;
+
+uniform float line_width;
+uniform float feather;
+
+#define TYPE_NORMAL 0
+#define TYPE_LINE 1
+
+uniform int type;
+
+void main()
+{
+ float alpha = 1.0;
+
+ if (type == TYPE_LINE)
+ {
+ float start = (line_width / 2.0) - feather; // where we start to apply alpha
+ float end = (line_width / 2.0) + feather; // where we end to apply alpha
+
+ // Calculate the multiplier so we can transform the 0->1 fade factor
+ // to take feather and line width into account.
+ float multiplied = 1.0 / (1.0 - (start / end));
+
+ float dist = (1.0 - abs(fade_factor)) * multiplied;
+
+ alpha = clamp(dist, 0.0, 1.0);
+ }
+
+ vec4 result_color = color;
+ result_color.a = result_color.a * alpha;
+
+ gl_FragColor = result_color;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/opengl/combinedTextureFragmentShader.glsl b/vcl/opengl/combinedTextureFragmentShader.glsl
new file mode 100644
index 000000000000..d8864cfe21c5
--- /dev/null
+++ b/vcl/opengl/combinedTextureFragmentShader.glsl
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+varying vec2 tex_coord;
+varying vec2 alpha_coord;
+varying vec2 mask_coord;
+
+uniform sampler2D texture;
+uniform sampler2D mask;
+uniform sampler2D alpha;
+
+uniform vec4 color;
+
+uniform int type;
+
+#define TYPE_NORMAL 0
+#define TYPE_BLEND 1
+#define TYPE_MASKED 2
+#define TYPE_DIFF 3
+#define TYPE_MASKED_COLOR 4
+
+void main()
+{
+ vec4 texelTexture = texture2D(texture, tex_coord);
+
+ if (type == TYPE_NORMAL)
+ {
+ gl_FragColor = texelTexture;
+ }
+ else if (type == TYPE_BLEND)
+ {
+ vec4 texelMask = texture2D(mask, mask_coord);
+ vec4 texelAlpha = texture2D(alpha, alpha_coord);
+ gl_FragColor = texelTexture;
+ gl_FragColor.a = 1.0 - (1.0 - floor(texelAlpha.r)) * texelMask.r;
+ }
+ else if (type == TYPE_MASKED)
+ {
+ vec4 texelMask = texture2D(mask, mask_coord);
+ gl_FragColor = texelTexture;
+ gl_FragColor.a = 1.0 - texelMask.r;
+ }
+ else if (type == TYPE_DIFF)
+ {
+ vec4 texelMask = texture2D(mask, mask_coord);
+ float alpha = 1.0 - abs(texelTexture.r - texelMask.r);
+ if (alpha > 0.0)
+ gl_FragColor = texelMask / alpha;
+ gl_FragColor.a = alpha;
+ }
+ else if (type == TYPE_MASKED_COLOR)
+ {
+ gl_FragColor = color;
+ gl_FragColor.a = 1.0 - texelTexture.r;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/opengl/combinedTextureVertexShader.glsl b/vcl/opengl/combinedTextureVertexShader.glsl
new file mode 100644
index 000000000000..883ec631fa73
--- /dev/null
+++ b/vcl/opengl/combinedTextureVertexShader.glsl
@@ -0,0 +1,32 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+attribute vec4 position;
+attribute vec2 tex_coord_in;
+attribute vec2 mask_coord_in;
+attribute vec2 alpha_coord_in;
+
+varying vec2 tex_coord;
+varying vec2 mask_coord;
+varying vec2 alpha_coord;
+
+uniform mat4 mvp;
+uniform mat4 transform;
+
+uniform int type;
+
+void main()
+{
+ gl_Position = mvp * transform * position;
+ tex_coord = tex_coord_in;
+ mask_coord = mask_coord_in;
+ alpha_coord = alpha_coord_in;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/opengl/combinedVertexShader.glsl b/vcl/opengl/combinedVertexShader.glsl
new file mode 100644
index 000000000000..9272544c33ef
--- /dev/null
+++ b/vcl/opengl/combinedVertexShader.glsl
@@ -0,0 +1,47 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+attribute vec2 position;
+attribute vec4 extrusion_vectors;
+
+varying float fade_factor; // fade factor for anti-aliasing
+
+uniform float line_width;
+uniform float feather; // width where we fade the line
+
+uniform mat4 mvp;
+
+#define TYPE_NORMAL 0
+#define TYPE_LINE 1
+
+uniform int type;
+
+void main()
+{
+ vec4 final_position = vec4(position, 0.0, 1.0);
+
+ if (type == TYPE_LINE)
+ {
+ vec2 extrusion_vector = extrusion_vectors.xy;
+ // miter factor to additionaly lenghten the distance of vertex (needed for miter)
+ // if 1.0 - miter_factor has no effect
+ float miter_factor = 1.0f / abs(extrusion_vectors.z);
+ // fade factor is always -1.0 or 1.0 -> we transport that info together with length
+ fade_factor = sign(extrusion_vectors.z);
+
+ float rendered_thickness = (line_width + feather * 2.0) * miter_factor;
+
+ // lengthen the vertex in directon of the extrusion vector by line width.
+ final_position = vec4(position + (extrusion_vector * (rendered_thickness / 2.0) ), 0.0, 1.0);
+ }
+
+ gl_Position = mvp * final_position;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx
index a92e5b3fca5e..58b4d62cca2e 100644
--- a/vcl/opengl/gdiimpl.cxx
+++ b/vcl/opengl/gdiimpl.cxx
@@ -544,8 +544,9 @@ bool OpenGLSalGraphicsImpl::UseSolid( SalColor nColor, sal_uInt8 nTransparency )
{
if( nColor == SALCOLOR_NONE )
return false;
- if( !UseProgram( "dumbVertexShader", "solidFragmentShader" ) )
+ if (!UseProgram("combinedVertexShader", "combinedFragmentShader"))
return false;
+ mpProgram->SetShaderType(DrawShaderType::Normal);
mpProgram->SetColor( "color", nColor, nTransparency );
#ifdef DBG_UTIL
mProgramIsSolidColor = true;
@@ -560,8 +561,9 @@ bool OpenGLSalGraphicsImpl::UseSolid( SalColor nColor, double fTransparency )
{
if( nColor == SALCOLOR_NONE )
return false;
- if( !UseProgram( "dumbVertexShader", "solidFragmentShader" ) )
+ if (!UseProgram("combinedVertexShader", "combinedFragmentShader"))
return false;
+ mpProgram->SetShaderType(DrawShaderType::Normal);
mpProgram->SetColorf( "color", nColor, fTransparency );
#ifdef DBG_UTIL
mProgramIsSolidColor = true;
@@ -925,12 +927,13 @@ bool OpenGLSalGraphicsImpl::UseLine(SalColor nColor, double fTransparency, GLflo
{
if( nColor == SALCOLOR_NONE )
return false;
- if( !UseProgram( "lineVertexShader", "lineFragmentShader" ) )
+ if (!UseProgram("combinedVertexShader", "combinedFragmentShader"))
return false;
+ mpProgram->SetShaderType(DrawShaderType::Line);
mpProgram->SetColorf("color", nColor, fTransparency);
mpProgram->SetUniform1f("line_width", fLineWidth);
// The width of the feather - area we make lineary transparent in VS.
- // Good AA value is 0.5
+ // Good AA value is 0.5f, no AA if feather 0.0f
mpProgram->SetUniform1f("feather", bUseAA ? 0.5f : 0.0f);
// We need blending or AA won't work correctly
mpProgram->SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
@@ -970,7 +973,7 @@ void OpenGLSalGraphicsImpl::DrawConvexPolygon( sal_uInt32 nPoints, const SalPoin
#endif
SalColor lastSolidColor = mProgramSolidColor;
double lastSolidTransparency = mProgramSolidTransparency;
- if (UseLine(lastSolidColor, lastSolidTransparency, 1.0f ,true))
+ if (UseLine(lastSolidColor, lastSolidTransparency, 1.0f, true))
{
for( i = 0; i < nPoints; ++i )
{
@@ -1013,7 +1016,7 @@ void OpenGLSalGraphicsImpl::DrawConvexPolygon( const tools::Polygon& rPolygon, b
#endif
SalColor lastSolidColor = mProgramSolidColor;
double lastSolidTransparency = mProgramSolidTransparency;
- if (UseLine(lastSolidColor, lastSolidTransparency, 1.0f ,true))
+ if (UseLine(lastSolidColor, lastSolidTransparency, 1.0f, true))
{
for( i = 0; i < nPoints; ++i )
{
@@ -1063,7 +1066,7 @@ void OpenGLSalGraphicsImpl::DrawTrapezoid( const basegfx::B2DTrapezoid& trapezoi
#endif
SalColor lastSolidColor = mProgramSolidColor;
double lastSolidTransparency = mProgramSolidTransparency;
- if (UseLine(lastSolidColor, lastSolidTransparency, 1.0f ,true))
+ if (UseLine(lastSolidColor, lastSolidTransparency, 1.0f, true))
{
for( i = 0; i < nPoints; ++i )
{
@@ -1184,9 +1187,11 @@ void OpenGLSalGraphicsImpl::DrawTexture( OpenGLTexture& rTexture, const SalTwoRe
SAL_INFO("vcl.opengl", "draw texture");
- if( !UseProgram( "textureVertexShader", "textureFragmentShader" ) )
+ if (!UseProgram("combinedTextureVertexShader", "combinedTextureFragmentShader"))
return;
- mpProgram->SetTexture( "sampler", rTexture );
+ mpProgram->SetShaderType(TextureShaderType::Normal);
+ mpProgram->SetIdentityTransform("transform");
+ mpProgram->SetTexture("texture", rTexture);
DrawTextureRect( rTexture, pPosAry, bInverted );
mpProgram->Clean();
}
@@ -1393,9 +1398,11 @@ void OpenGLSalGraphicsImpl::DrawAlphaTexture( OpenGLTexture& rTexture, const Sal
{
OpenGLZone aZone;
- if( !UseProgram( "textureVertexShader", "textureFragmentShader" ) )
+ if (!UseProgram("combinedTextureVertexShader", "combinedTextureFragmentShader"))
return;
- mpProgram->SetTexture( "sampler", rTexture );
+ mpProgram->SetShaderType(TextureShaderType::Normal);
+ mpProgram->SetIdentityTransform("transform");
+ mpProgram->SetTexture("texture", rTexture);
mpProgram->SetBlendMode( bPremultiplied ? GL_ONE : GL_SRC_ALPHA,
GL_ONE_MINUS_SRC_ALPHA );
DrawTextureRect( rTexture, rPosAry, bInverted );
@@ -1406,8 +1413,10 @@ void OpenGLSalGraphicsImpl::DrawTextureDiff( OpenGLTexture& rTexture, OpenGLText
{
OpenGLZone aZone;
- if( !UseProgram( "maskedTextureVertexShader", "diffTextureFragmentShader" ) )
+ if (!UseProgram("combinedTextureVertexShader", "combinedTextureFragmentShader"))
return;
+ mpProgram->SetShaderType(TextureShaderType::Diff);
+ mpProgram->SetIdentityTransform("transform");
mpProgram->SetTexture( "texture", rTexture );
mpProgram->SetTexture( "mask", rMask );
mpProgram->SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
@@ -1424,9 +1433,11 @@ void OpenGLSalGraphicsImpl::DrawTextureWithMask( OpenGLTexture& rTexture, OpenGL
{
OpenGLZone aZone;
- if( !UseProgram( "maskedTextureVertexShader", "maskedTextureFragmentShader" ) )
+ if (!UseProgram("combinedTextureVertexShader", "combinedTextureFragmentShader"))
return;
- mpProgram->SetTexture( "sampler", rTexture );
+ mpProgram->SetShaderType(TextureShaderType::Masked);
+ mpProgram->SetIdentityTransform("transform");
+ mpProgram->SetTexture( "texture", rTexture );
mpProgram->SetTexture( "mask", rMask );
mpProgram->SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
@@ -1446,9 +1457,10 @@ void OpenGLSalGraphicsImpl::DrawBlendedTexture( OpenGLTexture& rTexture, OpenGLT
{
OpenGLZone aZone;
- if( !UseProgram( "blendedTextureVertexShader", "blendedTextureFragmentShader" ) )
+ if (!UseProgram("combinedTextureVertexShader", "combinedTextureFragmentShader"))
return;
- mpProgram->SetTexture( "sampler", rTexture );
+ mpProgram->SetShaderType(TextureShaderType::Blend);
+ mpProgram->SetTexture( "texture", rTexture );
mpProgram->SetTexture( "mask", rMask );
mpProgram->SetTexture( "alpha", rAlpha );
@@ -1469,10 +1481,12 @@ void OpenGLSalGraphicsImpl::DrawMask( OpenGLTexture& rMask, SalColor nMaskColor,
{
OpenGLZone aZone;
- if( !UseProgram( "textureVertexShader", "maskFragmentShader" ) )
+ if (!UseProgram("combinedTextureVertexShader", "combinedTextureFragmentShader"))
return;
+ mpProgram->SetShaderType(TextureShaderType::MaskedColor);
+ mpProgram->SetIdentityTransform("transform");
mpProgram->SetColor( "color", nMaskColor, 0 );
- mpProgram->SetTexture( "sampler", rMask );
+ mpProgram->SetTexture("texture", rMask);
mpProgram->SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
DrawTextureRect( rMask, pPosAry );
mpProgram->Clean();
@@ -1530,15 +1544,16 @@ void OpenGLSalGraphicsImpl::FlushDeferredDrawing()
}
#endif
- if( !UseProgram( "textureVertexShader", "maskFragmentShader" ) )
+ if (!UseProgram("combinedTextureVertexShader", "combinedTextureFragmentShader"))
return;
-
+ mpProgram->SetShaderType(TextureShaderType::MaskedColor);
+ mpProgram->SetIdentityTransform("transform");
mpProgram->SetBlendMode(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
for (auto& rPair : mpAccumulatedTextures->getAccumulatedTexturesMap())
{
OpenGLTexture& rTexture = rPair.second->maTexture;
- mpProgram->SetTexture("sampler", rTexture);
+ mpProgram->SetTexture("texture", rTexture);
for (auto& rColorTwoRectPair: rPair.second->maColorTextureDrawParametersMap)
{
mpProgram->SetColor("color", rColorTwoRectPair.first, 0);
@@ -2048,11 +2063,13 @@ bool OpenGLSalGraphicsImpl::blendBitmap(
VCL_GL_INFO( "::blendBitmap" );
PreDraw();
- if (!UseProgram("textureVertexShader", "textureFragmentShader"))
+ if (!UseProgram("combinedTextureVertexShader", "combinedTextureFragmentShader"))
return true;
+ mpProgram->SetShaderType(TextureShaderType::Normal);
+ mpProgram->SetIdentityTransform("transform");
+ mpProgram->SetTexture("texture", rTexture);
mpProgram->SetBlendMode(GL_ZERO, GL_SRC_COLOR);
- mpProgram->SetTexture("sampler", rTexture);
DrawTextureRect(rTexture, rPosAry);
mpProgram->Clean();
@@ -2332,12 +2349,14 @@ void OpenGLSalGraphicsImpl::doFlush()
VCL_GL_INFO( "Texture height " << maOffscreenTex.GetHeight() << " vs. window height " << GetHeight() );
OpenGLProgram *pProgram =
- mpWindowContext->UseProgram( "textureVertexShader", "textureFragmentShader", "// flush shader\n" ); // flush helps profiling
+ mpWindowContext->UseProgram("combinedTextureVertexShader", "combinedTextureFragmentShader", "// flush shader\n" ); // flush helps profiling
if( !pProgram )
VCL_GL_INFO( "Can't compile simple copying shader !" );
else
{
- pProgram->SetTexture( "sampler", maOffscreenTex );
+ pProgram->SetShaderType(TextureShaderType::Normal);
+ pProgram->SetIdentityTransform("transform");
+ pProgram->SetTexture("texture", maOffscreenTex);
SalTwoRect aPosAry( 0, 0, maOffscreenTex.GetWidth(), maOffscreenTex.GetHeight(),
0, 0, maOffscreenTex.GetWidth(), maOffscreenTex.GetHeight() );
diff --git a/vcl/opengl/program.cxx b/vcl/opengl/program.cxx
index 71530cbf75cb..2331080d28c1 100644
--- a/vcl/opengl/program.cxx
+++ b/vcl/opengl/program.cxx
@@ -135,6 +135,16 @@ void OpenGLProgram::SetExtrusionVectors(const GLvoid* pData)
SetVertexAttrib(mnNormalAttrib, "extrusion_vectors", pData, 3);
}
+void OpenGLProgram::SetShaderType(TextureShaderType eTextureShaderType)
+{
+ SetUniform1i("type", GLint(eTextureShaderType));
+}
+
+void OpenGLProgram::SetShaderType(DrawShaderType eDrawShaderType)
+{
+ SetUniform1i("type", GLint(eDrawShaderType));
+}
+
GLuint OpenGLProgram::GetUniformLocation( const OString& rName )
{
auto it = maUniformLocations.find( rName );
@@ -286,6 +296,14 @@ void OpenGLProgram::SetTransform(
CHECK_GL_ERROR();
}
+void OpenGLProgram::SetIdentityTransform(const OString& rName)
+{
+ GLuint nUniform = GetUniformLocation(rName);
+ glm::mat4 aMatrix = glm::mat4();
+ glUniformMatrix4fv(nUniform, 1, GL_FALSE, glm::value_ptr( aMatrix ) );
+ CHECK_GL_ERROR();
+}
+
void OpenGLProgram::ApplyMatrix(float fWidth, float fHeight, float fPixelOffset)
{