1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
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() :
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
),
32 mfLastPixelOffset(0.0)
36 OpenGLProgram::~OpenGLProgram()
38 maUniformLocations
.clear();
41 glDeleteProgram( mnId
);
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
);
55 void OpenGLProgram::Reuse()
60 bool OpenGLProgram::Use()
71 bool OpenGLProgram::Clean()
73 // unbind all textures
74 for (OpenGLTexture
& rTexture
: maTextures
)
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
);
97 bool OpenGLProgram::EnableVertexAttrib(GLuint
& rAttrib
, const OString
& rName
)
99 if( rAttrib
== SAL_MAX_UINT32
)
101 GLint aLocation
= glGetAttribLocation(mnId
, rName
.getStr());
105 rAttrib
= GLuint(aLocation
);
107 if( (mnEnabledAttribs
& ( 1 << rAttrib
)) == 0 )
109 glEnableVertexAttribArray( rAttrib
);
111 mnEnabledAttribs
|= ( 1 << rAttrib
);
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
);
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() );
178 maUniformLocations
[rName
] = nLocation
;
185 void OpenGLProgram::DrawArrays(GLenum aMode
, std::vector
<GLfloat
>& aVertices
)
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
)
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
);
209 void OpenGLProgram::SetUniform2f( const OString
& rName
, GLfloat v1
, GLfloat v2
)
211 GLuint nUniform
= GetUniformLocation( rName
);
212 glUniform2f( nUniform
, v1
, v2
);
216 void OpenGLProgram::SetUniform1fv( const OString
& rName
, GLsizei nCount
, GLfloat
* aValues
)
218 GLuint nUniform
= GetUniformLocation( rName
);
219 glUniform1fv( nUniform
, nCount
, aValues
);
223 void OpenGLProgram::SetUniform2fv( const OString
& rName
, GLsizei nCount
, GLfloat
* aValues
)
225 GLuint nUniform
= GetUniformLocation( rName
);
226 glUniform2fv( nUniform
, nCount
, aValues
);
230 void OpenGLProgram::SetUniform1i( const OString
& rName
, GLint v1
)
232 GLuint nUniform
= GetUniformLocation( rName
);
233 glUniform1i( nUniform
, v1
);
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) );
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
) );
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 );
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,
290 void OpenGLProgram::SetTexture( const OString
& rName
, OpenGLTexture
& rTexture
)
292 GLuint nUniform
= GetUniformLocation( rName
);
293 int nIndex
= maTextures
.size();
295 glUniform1i( nUniform
, nIndex
);
298 OpenGLContext::getVCLContext()->state().texture().active(nIndex
);
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)
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,
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
) );
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
) );
337 void OpenGLProgram::ApplyMatrix(float fWidth
, float fHeight
, float fPixelOffset
)
340 if (mfLastWidth
== fWidth
&& mfLastHeight
== fHeight
&& mfLastPixelOffset
== fPixelOffset
)
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
));
359 void OpenGLProgram::SetBlendMode(GLenum nSFactor
, GLenum nDFactor
)
361 OpenGLContext::getVCLContext()->state().blend().enable();
362 OpenGLContext::getVCLContext()->state().blend().func(nSFactor
, nDFactor
);
366 bool OpenGLProgram::DrawTexture( const OpenGLTexture
& rTexture
)
371 float fWidth
= rTexture
.GetWidth();
372 float fHeight
= rTexture
.GetHeight();
375 float fMaxX
= fWidth
;
377 float fMaxY
= fHeight
;
379 std::vector
<GLfloat
> aPosition
{
385 GLfloat aTexCoord
[8];
387 rTexture
.GetWholeCoord( aTexCoord
);
388 SetTextureCoord( aTexCoord
);
389 ApplyMatrix(fWidth
, fHeight
);
390 DrawArrays(GL_TRIANGLE_FAN
, aPosition
);
396 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */