Version 5.2.0.0.beta1, tag libreoffice-5.2.0.0.beta1
[LibreOffice.git] / vcl / opengl / program.cxx
blob2331080d28c1e87d19ea39f3c5680cbc7827bd7e
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 mnNormalAttrib( SAL_MAX_UINT32 ),
28 mbBlending( false ),
29 mfLastWidth(0.0),
30 mfLastHeight(0.0),
31 mfLastPixelOffset(0.0)
35 OpenGLProgram::~OpenGLProgram()
37 maUniformLocations.clear();
38 if( mnId != 0 )
40 glDeleteProgram( mnId );
41 CHECK_GL_ERROR();
45 bool OpenGLProgram::Load( const OUString& rVertexShader,
46 const OUString& rFragmentShader,
47 const rtl::OString& preamble,
48 const rtl::OString& rDigest )
50 mnId = OpenGLHelper::LoadShaders( rVertexShader, rFragmentShader, preamble, rDigest );
51 return ( mnId != 0 );
54 void OpenGLProgram::Reuse()
56 mbBlending = false;
59 bool OpenGLProgram::Use()
61 if (!mnId)
62 return false;
64 glUseProgram(mnId);
65 CHECK_GL_ERROR();
66 Reuse();
67 return true;
70 bool 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;
93 return true;
96 void OpenGLProgram::SetVertexAttrib( GLuint& rAttrib, const OString& rName, const GLvoid* pData, GLint nSize )
98 if( rAttrib == SAL_MAX_UINT32 )
100 rAttrib = glGetAttribLocation( mnId, rName.getStr() );
101 CHECK_GL_ERROR();
103 if( (mnEnabledAttribs & ( 1 << rAttrib )) == 0 )
105 glEnableVertexAttribArray( rAttrib );
106 CHECK_GL_ERROR();
107 mnEnabledAttribs |= ( 1 << rAttrib );
109 glVertexAttribPointer( rAttrib, nSize, GL_FLOAT, GL_FALSE, 0, pData );
110 CHECK_GL_ERROR();
113 void OpenGLProgram::SetVertices( const GLvoid* pData )
115 SetVertexAttrib( mnPositionAttrib, "position", pData );
118 void OpenGLProgram::SetTextureCoord( const GLvoid* pData )
120 SetVertexAttrib( mnTexCoordAttrib, "tex_coord_in", pData );
123 void OpenGLProgram::SetAlphaCoord( const GLvoid* pData )
125 SetVertexAttrib( mnAlphaCoordAttrib, "alpha_coord_in", pData );
128 void OpenGLProgram::SetMaskCoord(const GLvoid* pData)
130 SetVertexAttrib(mnMaskCoordAttrib, "mask_coord_in", pData);
133 void OpenGLProgram::SetExtrusionVectors(const GLvoid* pData)
135 SetVertexAttrib(mnNormalAttrib, "extrusion_vectors", pData, 3);
138 void OpenGLProgram::SetShaderType(TextureShaderType eTextureShaderType)
140 SetUniform1i("type", GLint(eTextureShaderType));
143 void OpenGLProgram::SetShaderType(DrawShaderType eDrawShaderType)
145 SetUniform1i("type", GLint(eDrawShaderType));
148 GLuint OpenGLProgram::GetUniformLocation( const OString& rName )
150 auto it = maUniformLocations.find( rName );
151 if( it == maUniformLocations.end() )
153 GLuint nLocation = glGetUniformLocation( mnId, rName.getStr() );
154 CHECK_GL_ERROR();
155 maUniformLocations[rName] = nLocation;
156 return nLocation;
159 return it->second;
162 void OpenGLProgram::DrawArrays(GLenum aMode, std::vector<GLfloat>& aVertices)
164 if (!mbBlending)
165 OpenGLContext::getVCLContext()->state()->blend().disable();
167 SetVertices(aVertices.data());
168 glDrawArrays(aMode, 0, aVertices.size() / 2);
171 void OpenGLProgram::SetUniform1f( const OString& rName, GLfloat v1 )
173 GLuint nUniform = GetUniformLocation( rName );
174 glUniform1f( nUniform, v1 );
175 CHECK_GL_ERROR();
178 void OpenGLProgram::SetUniform2f( const OString& rName, GLfloat v1, GLfloat v2 )
180 GLuint nUniform = GetUniformLocation( rName );
181 glUniform2f( nUniform, v1, v2 );
182 CHECK_GL_ERROR();
185 void OpenGLProgram::SetUniform1fv( const OString& rName, GLsizei nCount, GLfloat* aValues )
187 GLuint nUniform = GetUniformLocation( rName );
188 glUniform1fv( nUniform, nCount, aValues );
189 CHECK_GL_ERROR();
192 void OpenGLProgram::SetUniform2fv( const OString& rName, GLsizei nCount, GLfloat* aValues )
194 GLuint nUniform = GetUniformLocation( rName );
195 glUniform2fv( nUniform, nCount, aValues );
196 CHECK_GL_ERROR();
199 void OpenGLProgram::SetUniform1i( const OString& rName, GLint v1 )
201 GLuint nUniform = GetUniformLocation( rName );
202 glUniform1i( nUniform, v1 );
203 CHECK_GL_ERROR();
206 void OpenGLProgram::SetColor( const OString& rName, SalColor nColor, sal_uInt8 nTransparency )
208 GLuint nUniform = GetUniformLocation( rName );
209 glUniform4f( nUniform,
210 ((float) SALCOLOR_RED( nColor )) / 255,
211 ((float) SALCOLOR_GREEN( nColor )) / 255,
212 ((float) SALCOLOR_BLUE( nColor )) / 255,
213 (100 - nTransparency) * (1.0 / 100) );
214 CHECK_GL_ERROR();
216 if( nTransparency > 0 )
217 SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
220 void OpenGLProgram::SetColorf( const OString& rName, SalColor nColor, double fTransparency )
222 GLuint nUniform = GetUniformLocation( rName );
223 glUniform4f( nUniform,
224 ((float) SALCOLOR_RED( nColor )) / 255,
225 ((float) SALCOLOR_GREEN( nColor )) / 255,
226 ((float) SALCOLOR_BLUE( nColor )) / 255,
227 (1.0f - fTransparency) );
228 CHECK_GL_ERROR();
230 if( fTransparency > 0.0 )
231 SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
234 void OpenGLProgram::SetColor( const OString& rName, const Color& rColor )
236 GLuint nUniform = GetUniformLocation( rName );
237 glUniform4f( nUniform,
238 ((float) rColor.GetRed()) / 255,
239 ((float) rColor.GetGreen()) / 255,
240 ((float) rColor.GetBlue()) / 255,
241 1.0f - ((float) rColor.GetTransparency()) / 255 );
242 CHECK_GL_ERROR();
244 if( rColor.GetTransparency() > 0 )
245 SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
248 void OpenGLProgram::SetColorWithIntensity( const OString& rName, const Color& rColor, long nFactor )
250 GLuint nUniform = GetUniformLocation( rName );
251 glUniform4f( nUniform,
252 ((float) rColor.GetRed()) * nFactor / 25500.0,
253 ((float) rColor.GetGreen()) * nFactor / 25500.0,
254 ((float) rColor.GetBlue()) * nFactor / 25500.0,
255 1.0f );
256 CHECK_GL_ERROR();
259 void OpenGLProgram::SetTexture( const OString& rName, OpenGLTexture& rTexture )
261 GLuint nUniform = GetUniformLocation( rName );
262 int nIndex = maTextures.size();
264 glUniform1i( nUniform, nIndex );
265 CHECK_GL_ERROR();
267 std::unique_ptr<RenderState>& rState = OpenGLContext::getVCLContext()->state();
268 rState->texture().active(nIndex);
270 rTexture.Bind();
271 maTextures.push_back(rTexture);
274 void OpenGLProgram::SetTransform(
275 const OString& rName,
276 const OpenGLTexture& rTexture,
277 const basegfx::B2DPoint& rNull,
278 const basegfx::B2DPoint& rX,
279 const basegfx::B2DPoint& rY )
281 auto nTexWidth = rTexture.GetWidth();
282 auto nTexHeight = rTexture.GetHeight();
283 if (nTexWidth == 0 || nTexHeight == 0)
284 return;
286 GLuint nUniform = GetUniformLocation( rName );
287 const basegfx::B2DVector aXRel = rX - rNull;
288 const basegfx::B2DVector aYRel = rY - rNull;
289 const float aValues[] = {
290 (float) aXRel.getX()/nTexWidth, (float) aXRel.getY()/nTexWidth, 0, 0,
291 (float) aYRel.getX()/nTexHeight, (float) aYRel.getY()/nTexHeight, 0, 0,
292 0, 0, 1, 0,
293 (float) rNull.getX(), (float) rNull.getY(), 0, 1 };
294 glm::mat4 aMatrix = glm::make_mat4( aValues );
295 glUniformMatrix4fv( nUniform, 1, GL_FALSE, glm::value_ptr( aMatrix ) );
296 CHECK_GL_ERROR();
299 void OpenGLProgram::SetIdentityTransform(const OString& rName)
301 GLuint nUniform = GetUniformLocation(rName);
302 glm::mat4 aMatrix = glm::mat4();
303 glUniformMatrix4fv(nUniform, 1, GL_FALSE, glm::value_ptr( aMatrix ) );
304 CHECK_GL_ERROR();
307 void OpenGLProgram::ApplyMatrix(float fWidth, float fHeight, float fPixelOffset)
310 if (mfLastWidth == fWidth && mfLastHeight == fHeight && mfLastPixelOffset == fPixelOffset)
311 return;
313 mfLastWidth = fWidth;
314 mfLastHeight = fHeight;
315 mfLastPixelOffset = fPixelOffset;
317 OString sProjectionMatrix("mvp");
318 GLuint nUniform = GetUniformLocation(sProjectionMatrix);
320 glm::mat4 aMVP = glm::ortho(0.0f, fWidth, fHeight, 0.0f, 0.0f, 1.0f);
322 if (fPixelOffset != 0.0f)
323 aMVP = glm::translate(aMVP, glm::vec3(fPixelOffset, fPixelOffset, 0.0f));
325 glUniformMatrix4fv(nUniform, 1, GL_FALSE, glm::value_ptr(aMVP));
326 CHECK_GL_ERROR();
329 void OpenGLProgram::SetBlendMode(GLenum nSFactor, GLenum nDFactor)
331 OpenGLContext::getVCLContext()->state()->blend().enable();
332 OpenGLContext::getVCLContext()->state()->blend().func(nSFactor, nDFactor);
333 mbBlending = true;
336 bool OpenGLProgram::DrawTexture( const OpenGLTexture& rTexture )
338 if (!rTexture)
339 return false;
341 float fWidth = rTexture.GetWidth();
342 float fHeight = rTexture.GetHeight();
344 float fMinX = 0.0f;
345 float fMaxX = fWidth;
346 float fMinY = 0.0f;
347 float fMaxY = fHeight;
349 std::vector<GLfloat> aPosition {
350 fMinX, fMaxY,
351 fMinX, fMinY,
352 fMaxX, fMinY,
353 fMaxX, fMaxY
355 GLfloat aTexCoord[8];
357 rTexture.GetWholeCoord( aTexCoord );
358 SetTextureCoord( aTexCoord );
359 ApplyMatrix(fWidth, fHeight);
360 DrawArrays(GL_TRIANGLE_FAN, aPosition);
361 CHECK_GL_ERROR();
363 return true;
366 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */