Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / vcl / opengl / program.cxx
blob6557eccf8f422fe0389dc429b29dadb990ebbad7
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 OString& preamble,
49 const OString& rDigest )
51 mnId = OpenGLHelper::LoadShaders( rVertexShader, rFragmentShader, preamble, rDigest );
52 return ( mnId != 0 );
55 void OpenGLProgram::Reuse()
57 mbBlending = false;
60 void OpenGLProgram::Use()
62 if (!mnId)
63 return;
65 glUseProgram(mnId);
66 CHECK_GL_ERROR();
67 Reuse();
70 void OpenGLProgram::Clean()
72 // unbind all textures
73 for (OpenGLTexture& rTexture : maTextures)
75 rTexture.Unbind();
77 maTextures.clear();
79 // disable any enabled vertex attrib array
80 if( mnEnabledAttribs )
82 for( int i = 0; i < 32; i++ )
84 if( mnEnabledAttribs & ( 1 << i ) )
86 glDisableVertexAttribArray( i );
87 CHECK_GL_ERROR();
90 mnEnabledAttribs = 0;
94 bool OpenGLProgram::EnableVertexAttrib(GLuint& rAttrib, const OString& rName)
96 if( rAttrib == SAL_MAX_UINT32 )
98 GLint aLocation = glGetAttribLocation(mnId, rName.getStr());
99 CHECK_GL_ERROR();
100 if (aLocation < 0)
101 return false;
102 rAttrib = GLuint(aLocation);
104 if( (mnEnabledAttribs & ( 1 << rAttrib )) == 0 )
106 glEnableVertexAttribArray( rAttrib );
107 CHECK_GL_ERROR();
108 mnEnabledAttribs |= ( 1 << rAttrib );
110 return true;
113 void OpenGLProgram::SetVertexAttrib(GLuint& rAttrib, const OString& rName, GLint nSize,
114 GLenum eType, GLboolean bNormalized, GLsizei aStride,
115 const GLvoid* pPointer)
117 if (EnableVertexAttrib(rAttrib, rName))
119 glVertexAttribPointer(rAttrib, nSize, eType, bNormalized, aStride, pPointer);
120 CHECK_GL_ERROR();
122 else
124 VCL_GL_INFO("Vertex attribute '" << rName << "' doesn't exist in this program (" << mnId << ")");
128 void OpenGLProgram::SetVertices( const GLvoid* pData )
130 SetVertexAttrib(mnPositionAttrib, "position", 2, GL_FLOAT, GL_FALSE, 0, pData);
133 void OpenGLProgram::SetTextureCoord( const GLvoid* pData )
135 SetVertexAttrib(mnTexCoordAttrib, "tex_coord_in", 2, GL_FLOAT, GL_FALSE, 0, pData);
138 void OpenGLProgram::SetAlphaCoord( const GLvoid* pData )
140 SetVertexAttrib(mnAlphaCoordAttrib, "alpha_coord_in", 2, GL_FLOAT, GL_FALSE, 0, pData);
143 void OpenGLProgram::SetMaskCoord(const GLvoid* pData)
145 SetVertexAttrib(mnMaskCoordAttrib, "mask_coord_in", 2, GL_FLOAT, GL_FALSE, 0, pData);
148 void OpenGLProgram::SetExtrusionVectors(const GLvoid* pData)
150 SetVertexAttrib(mnExtrusionVectorsAttrib, "extrusion_vectors", 3, GL_FLOAT, GL_FALSE, 0, pData);
153 void OpenGLProgram::SetVertexColors(std::vector<GLubyte>& rColorVector)
155 SetVertexAttrib(mnVertexColorsAttrib, "vertex_color_in", 4, GL_UNSIGNED_BYTE, GL_FALSE, 0, rColorVector.data());
158 void OpenGLProgram::SetShaderType(TextureShaderType eTextureShaderType)
160 SetUniform1i("type", GLint(eTextureShaderType));
163 void OpenGLProgram::SetShaderType(DrawShaderType eDrawShaderType)
165 SetUniform1i("type", GLint(eDrawShaderType));
168 GLuint OpenGLProgram::GetUniformLocation( const OString& rName )
170 auto it = maUniformLocations.find( rName );
171 if( it == maUniformLocations.end() )
173 GLuint nLocation = glGetUniformLocation( mnId, rName.getStr() );
174 CHECK_GL_ERROR();
175 maUniformLocations[rName] = nLocation;
176 return nLocation;
179 return it->second;
182 void OpenGLProgram::DrawArrays(GLenum aMode, std::vector<GLfloat>& aVertices)
184 if (!mbBlending)
185 OpenGLContext::getVCLContext()->state().blend().disable();
187 SetVertices(aVertices.data());
188 glDrawArrays(aMode, 0, aVertices.size() / 2);
191 void OpenGLProgram::DrawElements(GLenum aMode, GLuint nNumberOfVertices)
193 if (!mbBlending)
194 OpenGLContext::getVCLContext()->state().blend().disable();
196 glDrawElements(aMode, nNumberOfVertices, GL_UNSIGNED_INT, nullptr);
199 void OpenGLProgram::SetUniform1f( const OString& rName, GLfloat v1 )
201 GLuint nUniform = GetUniformLocation( rName );
202 glUniform1f( nUniform, v1 );
203 CHECK_GL_ERROR();
206 void OpenGLProgram::SetUniform2f( const OString& rName, GLfloat v1, GLfloat v2 )
208 GLuint nUniform = GetUniformLocation( rName );
209 glUniform2f( nUniform, v1, v2 );
210 CHECK_GL_ERROR();
213 void OpenGLProgram::SetUniform1fv( const OString& rName, GLsizei nCount, GLfloat const * aValues )
215 GLuint nUniform = GetUniformLocation( rName );
216 glUniform1fv( nUniform, nCount, aValues );
217 CHECK_GL_ERROR();
220 void OpenGLProgram::SetUniform2fv( const OString& rName, GLsizei nCount, GLfloat const * aValues )
222 GLuint nUniform = GetUniformLocation( rName );
223 glUniform2fv( nUniform, nCount, aValues );
224 CHECK_GL_ERROR();
227 void OpenGLProgram::SetUniform1i( const OString& rName, GLint v1 )
229 GLuint nUniform = GetUniformLocation( rName );
230 glUniform1i( nUniform, v1 );
231 CHECK_GL_ERROR();
234 void OpenGLProgram::SetColor( const OString& rName, Color nColor, sal_uInt8 nTransparency )
236 GLuint nUniform = GetUniformLocation( rName );
237 glUniform4f( nUniform,
238 nColor.GetRed() / 255.0f,
239 nColor.GetGreen() / 255.0f,
240 nColor.GetBlue() / 255.0f,
241 (100 - nTransparency) * (1.0 / 100) );
242 CHECK_GL_ERROR();
244 if( nTransparency > 0 )
245 SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
248 void OpenGLProgram::SetColorf( const OString& rName, Color nColor, double fTransparency )
250 GLuint nUniform = GetUniformLocation( rName );
251 glUniform4f( nUniform,
252 nColor.GetRed() / 255.0f,
253 nColor.GetGreen() / 255.0f,
254 nColor.GetBlue() / 255.0f,
255 (1.0f - fTransparency) );
256 CHECK_GL_ERROR();
258 if( fTransparency > 0.0 )
259 SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
262 void OpenGLProgram::SetColor( const OString& rName, const Color& rColor )
264 GLuint nUniform = GetUniformLocation( rName );
265 glUniform4f( nUniform,
266 static_cast<float>(rColor.GetRed()) / 255,
267 static_cast<float>(rColor.GetGreen()) / 255,
268 static_cast<float>(rColor.GetBlue()) / 255,
269 1.0f - static_cast<float>(rColor.GetTransparency()) / 255 );
270 CHECK_GL_ERROR();
272 if( rColor.GetTransparency() > 0 )
273 SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
276 void OpenGLProgram::SetColorWithIntensity( const OString& rName, const Color& rColor, long nFactor )
278 GLuint nUniform = GetUniformLocation( rName );
279 glUniform4f( nUniform,
280 static_cast<float>(rColor.GetRed()) * nFactor / 25500.0,
281 static_cast<float>(rColor.GetGreen()) * nFactor / 25500.0,
282 static_cast<float>(rColor.GetBlue()) * nFactor / 25500.0,
283 1.0f );
284 CHECK_GL_ERROR();
287 void OpenGLProgram::SetTexture( const OString& rName, OpenGLTexture& rTexture )
289 GLuint nUniform = GetUniformLocation( rName );
290 int nIndex = maTextures.size();
292 glUniform1i( nUniform, nIndex );
293 CHECK_GL_ERROR();
295 OpenGLContext::getVCLContext()->state().texture().active(nIndex);
297 rTexture.Bind();
298 maTextures.push_back(rTexture);
301 void OpenGLProgram::SetTransform(
302 const OString& rName,
303 const OpenGLTexture& rTexture,
304 const basegfx::B2DPoint& rNull,
305 const basegfx::B2DPoint& rX,
306 const basegfx::B2DPoint& rY )
308 auto nTexWidth = rTexture.GetWidth();
309 auto nTexHeight = rTexture.GetHeight();
310 if (nTexWidth == 0 || nTexHeight == 0)
311 return;
313 GLuint nUniform = GetUniformLocation( rName );
314 const basegfx::B2DVector aXRel = rX - rNull;
315 const basegfx::B2DVector aYRel = rY - rNull;
316 const float aValues[] = {
317 static_cast<float>(aXRel.getX())/nTexWidth, static_cast<float>(aXRel.getY())/nTexWidth, 0, 0,
318 static_cast<float>(aYRel.getX())/nTexHeight, static_cast<float>(aYRel.getY())/nTexHeight, 0, 0,
319 0, 0, 1, 0,
320 static_cast<float>(rNull.getX()), static_cast<float>(rNull.getY()), 0, 1 };
321 glm::mat4 aMatrix = glm::make_mat4( aValues );
322 glUniformMatrix4fv( nUniform, 1, GL_FALSE, glm::value_ptr( aMatrix ) );
323 CHECK_GL_ERROR();
326 void OpenGLProgram::SetIdentityTransform(const OString& rName)
328 GLuint nUniform = GetUniformLocation(rName);
329 glm::mat4 aMatrix {};
330 glUniformMatrix4fv(nUniform, 1, GL_FALSE, glm::value_ptr( aMatrix ) );
331 CHECK_GL_ERROR();
334 void OpenGLProgram::ApplyMatrix(float fWidth, float fHeight, float fPixelOffset)
337 if (mfLastWidth == fWidth && mfLastHeight == fHeight && mfLastPixelOffset == fPixelOffset)
338 return;
340 mfLastWidth = fWidth;
341 mfLastHeight = fHeight;
342 mfLastPixelOffset = fPixelOffset;
344 GLuint nUniform = GetUniformLocation("mvp");
346 glm::mat4 aMVP = glm::ortho(0.0f, fWidth, fHeight, 0.0f, 0.0f, 1.0f);
348 if (fPixelOffset != 0.0f)
349 aMVP = glm::translate(aMVP, glm::vec3(fPixelOffset, fPixelOffset, 0.0f));
351 glUniformMatrix4fv(nUniform, 1, GL_FALSE, glm::value_ptr(aMVP));
352 CHECK_GL_ERROR();
355 void OpenGLProgram::SetBlendMode(GLenum nSFactor, GLenum nDFactor)
357 OpenGLContext::getVCLContext()->state().blend().enable();
358 OpenGLContext::getVCLContext()->state().blend().func(nSFactor, nDFactor);
359 mbBlending = true;
362 void OpenGLProgram::DrawTexture( const OpenGLTexture& rTexture )
364 if (!rTexture)
365 return;
367 float fWidth = rTexture.GetWidth();
368 float fHeight = rTexture.GetHeight();
370 float fMinX = 0.0f;
371 float fMaxX = fWidth;
372 float fMinY = 0.0f;
373 float fMaxY = fHeight;
375 std::vector<GLfloat> aPosition {
376 fMinX, fMaxY,
377 fMinX, fMinY,
378 fMaxX, fMinY,
379 fMaxX, fMaxY
381 GLfloat aTexCoord[8];
383 rTexture.GetWholeCoord( aTexCoord );
384 SetTextureCoord( aTexCoord );
385 ApplyMatrix(fWidth, fHeight);
386 DrawArrays(GL_TRIANGLE_FAN, aPosition);
387 CHECK_GL_ERROR();
390 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */