Version 5.4.3.2, tag libreoffice-5.4.3.2
[LibreOffice.git] / vcl / opengl / program.cxx
blob0dab8b02e1f611aba103fc91b5f39f2082e0bc8a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include "opengl/program.hxx"
11 #include "opengl/RenderState.hxx"
13 #include <vcl/opengl/OpenGLHelper.hxx>
14 #include <vcl/opengl/OpenGLContext.hxx>
16 #include <glm/glm.hpp>
17 #include <glm/gtc/type_ptr.hpp>
18 #include <glm/gtc/matrix_transform.hpp>
20 OpenGLProgram::OpenGLProgram() :
21 mnId( 0 ),
22 mnEnabledAttribs( 0 ),
23 mnPositionAttrib( SAL_MAX_UINT32 ),
24 mnTexCoordAttrib( SAL_MAX_UINT32 ),
25 mnAlphaCoordAttrib( SAL_MAX_UINT32 ),
26 mnMaskCoordAttrib( SAL_MAX_UINT32 ),
27 mnExtrusionVectorsAttrib( SAL_MAX_UINT32 ),
28 mnVertexColorsAttrib( SAL_MAX_UINT32 ),
29 mbBlending(false),
30 mfLastWidth(0.0),
31 mfLastHeight(0.0),
32 mfLastPixelOffset(0.0)
36 OpenGLProgram::~OpenGLProgram()
38 maUniformLocations.clear();
39 if( mnId != 0 )
41 glDeleteProgram( mnId );
42 CHECK_GL_ERROR();
46 bool OpenGLProgram::Load( const OUString& rVertexShader,
47 const OUString& rFragmentShader,
48 const rtl::OString& preamble,
49 const rtl::OString& rDigest )
51 mnId = OpenGLHelper::LoadShaders( rVertexShader, rFragmentShader, preamble, rDigest );
52 return ( mnId != 0 );
55 void OpenGLProgram::Reuse()
57 mbBlending = false;
60 bool OpenGLProgram::Use()
62 if (!mnId)
63 return false;
65 glUseProgram(mnId);
66 CHECK_GL_ERROR();
67 Reuse();
68 return true;
71 bool OpenGLProgram::Clean()
73 // unbind all textures
74 for (OpenGLTexture& rTexture : maTextures)
76 rTexture.Unbind();
78 maTextures.clear();
80 // disable any enabled vertex attrib array
81 if( mnEnabledAttribs )
83 for( int i = 0; i < 32; i++ )
85 if( mnEnabledAttribs & ( 1 << i ) )
87 glDisableVertexAttribArray( i );
88 CHECK_GL_ERROR();
91 mnEnabledAttribs = 0;
94 return true;
97 bool OpenGLProgram::EnableVertexAttrib(GLuint& rAttrib, const OString& rName)
99 if( rAttrib == SAL_MAX_UINT32 )
101 GLint aLocation = glGetAttribLocation(mnId, rName.getStr());
102 CHECK_GL_ERROR();
103 if (aLocation < 0)
104 return false;
105 rAttrib = GLuint(aLocation);
107 if( (mnEnabledAttribs & ( 1 << rAttrib )) == 0 )
109 glEnableVertexAttribArray( rAttrib );
110 CHECK_GL_ERROR();
111 mnEnabledAttribs |= ( 1 << rAttrib );
113 return true;
116 void OpenGLProgram::SetVertexAttrib(GLuint& rAttrib, const OString& rName, GLint nSize,
117 GLenum eType, GLboolean bNormalized, GLsizei aStride,
118 const GLvoid* pPointer)
120 if (EnableVertexAttrib(rAttrib, rName))
122 glVertexAttribPointer(rAttrib, nSize, eType, bNormalized, aStride, pPointer);
123 CHECK_GL_ERROR();
125 else
127 VCL_GL_INFO("Vertex attribute '" << rName << "' doesn't exist in this program (" << mnId << ")");
131 void OpenGLProgram::SetVertices( const GLvoid* pData )
133 SetVertexAttrib(mnPositionAttrib, "position", 2, GL_FLOAT, GL_FALSE, 0, pData);
136 void OpenGLProgram::SetTextureCoord( const GLvoid* pData )
138 SetVertexAttrib(mnTexCoordAttrib, "tex_coord_in", 2, GL_FLOAT, GL_FALSE, 0, pData);
141 void OpenGLProgram::SetAlphaCoord( const GLvoid* pData )
143 SetVertexAttrib(mnAlphaCoordAttrib, "alpha_coord_in", 2, GL_FLOAT, GL_FALSE, 0, pData);
146 void OpenGLProgram::SetMaskCoord(const GLvoid* pData)
148 SetVertexAttrib(mnMaskCoordAttrib, "mask_coord_in", 2, GL_FLOAT, GL_FALSE, 0, pData);
151 void OpenGLProgram::SetExtrusionVectors(const GLvoid* pData)
153 SetVertexAttrib(mnExtrusionVectorsAttrib, "extrusion_vectors", 3, GL_FLOAT, GL_FALSE, 0, pData);
156 void OpenGLProgram::SetVertexColors(std::vector<GLubyte>& rColorVector)
158 SetVertexAttrib(mnVertexColorsAttrib, "vertex_color_in", 4, GL_UNSIGNED_BYTE, GL_FALSE, 0, rColorVector.data());
161 void OpenGLProgram::SetShaderType(TextureShaderType eTextureShaderType)
163 SetUniform1i("type", GLint(eTextureShaderType));
166 void OpenGLProgram::SetShaderType(DrawShaderType eDrawShaderType)
168 SetUniform1i("type", GLint(eDrawShaderType));
171 GLuint OpenGLProgram::GetUniformLocation( const OString& rName )
173 auto it = maUniformLocations.find( rName );
174 if( it == maUniformLocations.end() )
176 GLuint nLocation = glGetUniformLocation( mnId, rName.getStr() );
177 CHECK_GL_ERROR();
178 maUniformLocations[rName] = nLocation;
179 return nLocation;
182 return it->second;
185 void OpenGLProgram::DrawArrays(GLenum aMode, std::vector<GLfloat>& aVertices)
187 if (!mbBlending)
188 OpenGLContext::getVCLContext()->state().blend().disable();
190 SetVertices(aVertices.data());
191 glDrawArrays(aMode, 0, aVertices.size() / 2);
194 void OpenGLProgram::DrawElements(GLenum aMode, GLuint nNumberOfVertices)
196 if (!mbBlending)
197 OpenGLContext::getVCLContext()->state().blend().disable();
199 glDrawElements(aMode, nNumberOfVertices, GL_UNSIGNED_INT, nullptr);
202 void OpenGLProgram::SetUniform1f( const OString& rName, GLfloat v1 )
204 GLuint nUniform = GetUniformLocation( rName );
205 glUniform1f( nUniform, v1 );
206 CHECK_GL_ERROR();
209 void OpenGLProgram::SetUniform2f( const OString& rName, GLfloat v1, GLfloat v2 )
211 GLuint nUniform = GetUniformLocation( rName );
212 glUniform2f( nUniform, v1, v2 );
213 CHECK_GL_ERROR();
216 void OpenGLProgram::SetUniform1fv( const OString& rName, GLsizei nCount, GLfloat* aValues )
218 GLuint nUniform = GetUniformLocation( rName );
219 glUniform1fv( nUniform, nCount, aValues );
220 CHECK_GL_ERROR();
223 void OpenGLProgram::SetUniform2fv( const OString& rName, GLsizei nCount, GLfloat* aValues )
225 GLuint nUniform = GetUniformLocation( rName );
226 glUniform2fv( nUniform, nCount, aValues );
227 CHECK_GL_ERROR();
230 void OpenGLProgram::SetUniform1i( const OString& rName, GLint v1 )
232 GLuint nUniform = GetUniformLocation( rName );
233 glUniform1i( nUniform, v1 );
234 CHECK_GL_ERROR();
237 void OpenGLProgram::SetColor( const OString& rName, SalColor nColor, sal_uInt8 nTransparency )
239 GLuint nUniform = GetUniformLocation( rName );
240 glUniform4f( nUniform,
241 ((float) SALCOLOR_RED( nColor )) / 255,
242 ((float) SALCOLOR_GREEN( nColor )) / 255,
243 ((float) SALCOLOR_BLUE( nColor )) / 255,
244 (100 - nTransparency) * (1.0 / 100) );
245 CHECK_GL_ERROR();
247 if( nTransparency > 0 )
248 SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
251 void OpenGLProgram::SetColorf( const OString& rName, SalColor nColor, double fTransparency )
253 GLuint nUniform = GetUniformLocation( rName );
254 glUniform4f( nUniform,
255 ((float) SALCOLOR_RED( nColor )) / 255,
256 ((float) SALCOLOR_GREEN( nColor )) / 255,
257 ((float) SALCOLOR_BLUE( nColor )) / 255,
258 (1.0f - fTransparency) );
259 CHECK_GL_ERROR();
261 if( fTransparency > 0.0 )
262 SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
265 void OpenGLProgram::SetColor( const OString& rName, const Color& rColor )
267 GLuint nUniform = GetUniformLocation( rName );
268 glUniform4f( nUniform,
269 ((float) rColor.GetRed()) / 255,
270 ((float) rColor.GetGreen()) / 255,
271 ((float) rColor.GetBlue()) / 255,
272 1.0f - ((float) rColor.GetTransparency()) / 255 );
273 CHECK_GL_ERROR();
275 if( rColor.GetTransparency() > 0 )
276 SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
279 void OpenGLProgram::SetColorWithIntensity( const OString& rName, const Color& rColor, long nFactor )
281 GLuint nUniform = GetUniformLocation( rName );
282 glUniform4f( nUniform,
283 ((float) rColor.GetRed()) * nFactor / 25500.0,
284 ((float) rColor.GetGreen()) * nFactor / 25500.0,
285 ((float) rColor.GetBlue()) * nFactor / 25500.0,
286 1.0f );
287 CHECK_GL_ERROR();
290 void OpenGLProgram::SetTexture( const OString& rName, OpenGLTexture& rTexture )
292 GLuint nUniform = GetUniformLocation( rName );
293 int nIndex = maTextures.size();
295 glUniform1i( nUniform, nIndex );
296 CHECK_GL_ERROR();
298 OpenGLContext::getVCLContext()->state().texture().active(nIndex);
300 rTexture.Bind();
301 maTextures.push_back(rTexture);
304 void OpenGLProgram::SetTransform(
305 const OString& rName,
306 const OpenGLTexture& rTexture,
307 const basegfx::B2DPoint& rNull,
308 const basegfx::B2DPoint& rX,
309 const basegfx::B2DPoint& rY )
311 auto nTexWidth = rTexture.GetWidth();
312 auto nTexHeight = rTexture.GetHeight();
313 if (nTexWidth == 0 || nTexHeight == 0)
314 return;
316 GLuint nUniform = GetUniformLocation( rName );
317 const basegfx::B2DVector aXRel = rX - rNull;
318 const basegfx::B2DVector aYRel = rY - rNull;
319 const float aValues[] = {
320 (float) aXRel.getX()/nTexWidth, (float) aXRel.getY()/nTexWidth, 0, 0,
321 (float) aYRel.getX()/nTexHeight, (float) aYRel.getY()/nTexHeight, 0, 0,
322 0, 0, 1, 0,
323 (float) rNull.getX(), (float) rNull.getY(), 0, 1 };
324 glm::mat4 aMatrix = glm::make_mat4( aValues );
325 glUniformMatrix4fv( nUniform, 1, GL_FALSE, glm::value_ptr( aMatrix ) );
326 CHECK_GL_ERROR();
329 void OpenGLProgram::SetIdentityTransform(const OString& rName)
331 GLuint nUniform = GetUniformLocation(rName);
332 glm::mat4 aMatrix = glm::mat4();
333 glUniformMatrix4fv(nUniform, 1, GL_FALSE, glm::value_ptr( aMatrix ) );
334 CHECK_GL_ERROR();
337 void OpenGLProgram::ApplyMatrix(float fWidth, float fHeight, float fPixelOffset)
340 if (mfLastWidth == fWidth && mfLastHeight == fHeight && mfLastPixelOffset == fPixelOffset)
341 return;
343 mfLastWidth = fWidth;
344 mfLastHeight = fHeight;
345 mfLastPixelOffset = fPixelOffset;
347 OString sProjectionMatrix("mvp");
348 GLuint nUniform = GetUniformLocation(sProjectionMatrix);
350 glm::mat4 aMVP = glm::ortho(0.0f, fWidth, fHeight, 0.0f, 0.0f, 1.0f);
352 if (fPixelOffset != 0.0f)
353 aMVP = glm::translate(aMVP, glm::vec3(fPixelOffset, fPixelOffset, 0.0f));
355 glUniformMatrix4fv(nUniform, 1, GL_FALSE, glm::value_ptr(aMVP));
356 CHECK_GL_ERROR();
359 void OpenGLProgram::SetBlendMode(GLenum nSFactor, GLenum nDFactor)
361 OpenGLContext::getVCLContext()->state().blend().enable();
362 OpenGLContext::getVCLContext()->state().blend().func(nSFactor, nDFactor);
363 mbBlending = true;
366 bool OpenGLProgram::DrawTexture( const OpenGLTexture& rTexture )
368 if (!rTexture)
369 return false;
371 float fWidth = rTexture.GetWidth();
372 float fHeight = rTexture.GetHeight();
374 float fMinX = 0.0f;
375 float fMaxX = fWidth;
376 float fMinY = 0.0f;
377 float fMaxY = fHeight;
379 std::vector<GLfloat> aPosition {
380 fMinX, fMaxY,
381 fMinX, fMinY,
382 fMaxX, fMinY,
383 fMaxX, fMaxY
385 GLfloat aTexCoord[8];
387 rTexture.GetWholeCoord( aTexCoord );
388 SetTextureCoord( aTexCoord );
389 ApplyMatrix(fWidth, fHeight);
390 DrawArrays(GL_TRIANGLE_FAN, aPosition);
391 CHECK_GL_ERROR();
393 return true;
396 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */