Branch libreoffice-5-0-4
[LibreOffice.git] / vcl / opengl / program.cxx
blob0919c1ac8b09a9a1d52d7552268bd7a3a3fdbab6
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>
12 #include <vcl/opengl/OpenGLHelper.hxx>
14 #include <glm/glm.hpp>
15 #include <glm/gtc/type_ptr.hpp>
16 #include <glm/gtc/matrix_transform.hpp>
18 OpenGLProgram::OpenGLProgram() :
19 mnId( 0 ),
20 mnEnabledAttribs( 0 ),
21 mnPositionAttrib( SAL_MAX_UINT32 ),
22 mnTexCoordAttrib( SAL_MAX_UINT32 ),
23 mnAlphaCoordAttrib( SAL_MAX_UINT32 ),
24 mnMaskCoordAttrib( SAL_MAX_UINT32 ),
25 mbBlending( false ),
26 mfLastWidth(0.0),
27 mfLastHeight(0.0),
28 mfLastPixelOffset(0.0)
32 OpenGLProgram::~OpenGLProgram()
34 maUniformLocations.clear();
35 if( mnId != 0 )
36 glDeleteProgram( mnId );
39 bool OpenGLProgram::Load( const OUString& rVertexShader,
40 const OUString& rFragmentShader,
41 const rtl::OString& preamble,
42 const rtl::OString& rDigest )
44 mnId = OpenGLHelper::LoadShaders( rVertexShader, rFragmentShader, preamble, rDigest );
45 return ( mnId != 0 );
48 bool OpenGLProgram::Use()
50 if( !mnId )
51 return false;
53 glUseProgram( mnId );
54 return true;
57 bool OpenGLProgram::Clean()
59 // unbind all textures
60 if( !maTextures.empty() )
62 int nIndex( maTextures.size() - 1 );
63 TextureList::reverse_iterator it( maTextures.rbegin() );
64 while( it != maTextures.rend() )
66 glActiveTexture( GL_TEXTURE0 + nIndex-- );
67 it->Unbind();
68 ++it;
70 maTextures.clear();
73 // disable any enabled vertex attrib array
74 if( mnEnabledAttribs )
76 for( int i = 0; i < 32; i++ )
78 if( mnEnabledAttribs & ( 1 << i ) )
79 glDisableVertexAttribArray( i );
81 mnEnabledAttribs = 0;
84 // disable blending if enabled
85 if( mbBlending )
87 mbBlending = false;
88 glDisable( GL_BLEND );
91 CHECK_GL_ERROR();
92 return true;
95 void OpenGLProgram::SetVertexAttrib( GLuint& rAttrib, const OString& rName, const GLvoid* pData )
97 if( rAttrib == SAL_MAX_UINT32 )
98 rAttrib = glGetAttribLocation( mnId, rName.getStr() );
99 if( (mnEnabledAttribs & ( 1 << rAttrib )) == 0 )
101 glEnableVertexAttribArray( rAttrib );
102 mnEnabledAttribs |= ( 1 << rAttrib );
104 glVertexAttribPointer( rAttrib, 2, GL_FLOAT, GL_FALSE, 0, pData );
107 void OpenGLProgram::SetVertices( const GLvoid* pData )
109 SetVertexAttrib( mnPositionAttrib, "position", pData );
112 void OpenGLProgram::SetTextureCoord( const GLvoid* pData )
114 SetVertexAttrib( mnTexCoordAttrib, "tex_coord_in", pData );
117 void OpenGLProgram::SetAlphaCoord( const GLvoid* pData )
119 SetVertexAttrib( mnAlphaCoordAttrib, "alpha_coord_in", pData );
122 void OpenGLProgram::SetMaskCoord(const GLvoid* pData)
124 SetVertexAttrib(mnMaskCoordAttrib, "mask_coord_in", pData);
127 GLuint OpenGLProgram::GetUniformLocation( const OString& rName )
129 auto it = maUniformLocations.find( rName );
130 if( it == maUniformLocations.end() )
132 GLuint nLocation = glGetUniformLocation( mnId, rName.getStr() );
133 maUniformLocations[rName] = nLocation;
134 return nLocation;
137 return it->second;
140 void OpenGLProgram::SetUniform1f( const OString& rName, GLfloat v1 )
142 GLuint nUniform = GetUniformLocation( rName );
143 glUniform1f( nUniform, v1 );
146 void OpenGLProgram::SetUniform2f( const OString& rName, GLfloat v1, GLfloat v2 )
148 GLuint nUniform = GetUniformLocation( rName );
149 glUniform2f( nUniform, v1, v2 );
152 void OpenGLProgram::SetUniform1fv( const OString& rName, GLsizei nCount, GLfloat* aValues )
154 GLuint nUniform = GetUniformLocation( rName );
155 glUniform1fv( nUniform, nCount, aValues );
158 void OpenGLProgram::SetUniform2fv( const OString& rName, GLsizei nCount, GLfloat* aValues )
160 GLuint nUniform = GetUniformLocation( rName );
161 glUniform2fv( nUniform, nCount, aValues );
164 void OpenGLProgram::SetUniform1i( const OString& rName, GLint v1 )
166 GLuint nUniform = GetUniformLocation( rName );
167 glUniform1i( nUniform, v1 );
170 void OpenGLProgram::SetColor( const OString& rName, SalColor nColor, sal_uInt8 nTransparency )
172 GLuint nUniform = GetUniformLocation( rName );
173 glUniform4f( nUniform,
174 ((float) SALCOLOR_RED( nColor )) / 255,
175 ((float) SALCOLOR_GREEN( nColor )) / 255,
176 ((float) SALCOLOR_BLUE( nColor )) / 255,
177 (100 - nTransparency) * (1.0 / 100) );
179 if( nTransparency > 0 )
180 SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
183 void OpenGLProgram::SetColorf( const OString& rName, SalColor nColor, double fTransparency )
185 GLuint nUniform = GetUniformLocation( rName );
186 glUniform4f( nUniform,
187 ((float) SALCOLOR_RED( nColor )) / 255,
188 ((float) SALCOLOR_GREEN( nColor )) / 255,
189 ((float) SALCOLOR_BLUE( nColor )) / 255,
190 (1.0f - fTransparency) );
192 if( fTransparency > 0.0 )
193 SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
196 void OpenGLProgram::SetColor( const OString& rName, const Color& rColor )
198 GLuint nUniform = GetUniformLocation( rName );
199 glUniform4f( nUniform,
200 ((float) rColor.GetRed()) / 255,
201 ((float) rColor.GetGreen()) / 255,
202 ((float) rColor.GetBlue()) / 255,
203 1.0f - ((float) rColor.GetTransparency()) / 255 );
205 if( rColor.GetTransparency() > 0 )
206 SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
209 void OpenGLProgram::SetColorWithIntensity( const OString& rName, const Color& rColor, long nFactor )
211 GLuint nUniform = GetUniformLocation( rName );
212 glUniform4f( nUniform,
213 ((float) rColor.GetRed()) * nFactor / 25500.0,
214 ((float) rColor.GetGreen()) * nFactor / 25500.0,
215 ((float) rColor.GetBlue()) * nFactor / 25500.0,
216 1.0f );
219 void OpenGLProgram::SetTexture( const OString& rName, OpenGLTexture& rTexture )
221 GLuint nUniform = GetUniformLocation( rName );
222 int nIndex = maTextures.size();
224 glUniform1i( nUniform, nIndex );
225 glActiveTexture( GL_TEXTURE0 + nIndex );
226 rTexture.Bind();
227 maTextures.push_back( rTexture );
230 void OpenGLProgram::SetTransform(
231 const OString& rName,
232 const OpenGLTexture& rTexture,
233 const basegfx::B2DPoint& rNull,
234 const basegfx::B2DPoint& rX,
235 const basegfx::B2DPoint& rY )
237 auto nTexWidth = rTexture.GetWidth();
238 auto nTexHeight = rTexture.GetHeight();
239 if (nTexWidth == 0 || nTexHeight == 0)
240 return;
242 GLuint nUniform = GetUniformLocation( rName );
243 const basegfx::B2DVector aXRel = rX - rNull;
244 const basegfx::B2DVector aYRel = rY - rNull;
245 const float aValues[] = {
246 (float) aXRel.getX()/nTexWidth, (float) aXRel.getY()/nTexWidth, 0, 0,
247 (float) aYRel.getX()/nTexHeight, (float) aYRel.getY()/nTexHeight, 0, 0,
248 0, 0, 1, 0,
249 (float) rNull.getX(), (float) rNull.getY(), 0, 1 };
250 glm::mat4 mMatrix = glm::make_mat4( aValues );
251 glUniformMatrix4fv( nUniform, 1, GL_FALSE, glm::value_ptr( mMatrix ) );
254 void OpenGLProgram::ApplyMatrix(float fWidth, float fHeight, float fPixelOffset)
257 if (mfLastWidth == fWidth && mfLastHeight == fHeight && mfLastPixelOffset == fPixelOffset)
258 return;
260 mfLastWidth = fWidth;
261 mfLastHeight = fHeight;
262 mfLastPixelOffset = fPixelOffset;
264 OString sProjectionMatrix("mvp");
265 GLuint nUniform = GetUniformLocation(sProjectionMatrix);
267 glm::mat4 mMVP = glm::ortho(0.0f, fWidth, fHeight, 0.0f, 0.0f, 1.0f);
269 if (fPixelOffset != 0.0f)
270 mMVP = glm::translate(mMVP, glm::vec3(fPixelOffset, fPixelOffset, 0.0f));
272 glUniformMatrix4fv(nUniform, 1, GL_FALSE, glm::value_ptr(mMVP));
275 void OpenGLProgram::SetBlendMode( GLenum nSFactor, GLenum nDFactor )
277 glEnable( GL_BLEND );
278 glBlendFunc( nSFactor, nDFactor );
279 mbBlending = true;
282 bool OpenGLProgram::DrawTexture( const OpenGLTexture& rTexture )
284 if (!rTexture)
285 return false;
287 float fWidth = rTexture.GetWidth();
288 float fHeight = rTexture.GetHeight();
290 float fMinX = 0.0f;
291 float fMaxX = fWidth;
292 float fMinY = 0.0f;
293 float fMaxY = fHeight;
295 GLfloat aPosition[8] = { fMinX, fMaxY, fMinX, fMinY, fMaxX, fMinY, fMaxX, fMaxY };
296 GLfloat aTexCoord[8];
298 rTexture.GetWholeCoord( aTexCoord );
299 SetVertices( aPosition );
300 SetTextureCoord( aTexCoord );
301 ApplyMatrix(fWidth, fHeight);
302 glDrawArrays( GL_TRIANGLE_FAN, 0, 4 );
303 CHECK_GL_ERROR();
305 return true;
308 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */