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 OString
& preamble
,
49 const OString
& rDigest
)
51 mnId
= OpenGLHelper::LoadShaders( rVertexShader
, rFragmentShader
, preamble
, rDigest
);
55 void OpenGLProgram::Reuse()
60 void OpenGLProgram::Use()
70 void OpenGLProgram::Clean()
72 // unbind all textures
73 for (OpenGLTexture
& rTexture
: maTextures
)
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
);
94 bool OpenGLProgram::EnableVertexAttrib(GLuint
& rAttrib
, const OString
& rName
)
96 if( rAttrib
== SAL_MAX_UINT32
)
98 GLint aLocation
= glGetAttribLocation(mnId
, rName
.getStr());
102 rAttrib
= GLuint(aLocation
);
104 if( (mnEnabledAttribs
& ( 1 << rAttrib
)) == 0 )
106 glEnableVertexAttribArray( rAttrib
);
108 mnEnabledAttribs
|= ( 1 << rAttrib
);
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
);
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() );
175 maUniformLocations
[rName
] = nLocation
;
182 void OpenGLProgram::DrawArrays(GLenum aMode
, std::vector
<GLfloat
>& aVertices
)
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
)
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
);
206 void OpenGLProgram::SetUniform2f( const OString
& rName
, GLfloat v1
, GLfloat v2
)
208 GLuint nUniform
= GetUniformLocation( rName
);
209 glUniform2f( nUniform
, v1
, v2
);
213 void OpenGLProgram::SetUniform1fv( const OString
& rName
, GLsizei nCount
, GLfloat
const * aValues
)
215 GLuint nUniform
= GetUniformLocation( rName
);
216 glUniform1fv( nUniform
, nCount
, aValues
);
220 void OpenGLProgram::SetUniform2fv( const OString
& rName
, GLsizei nCount
, GLfloat
const * aValues
)
222 GLuint nUniform
= GetUniformLocation( rName
);
223 glUniform2fv( nUniform
, nCount
, aValues
);
227 void OpenGLProgram::SetUniform1i( const OString
& rName
, GLint v1
)
229 GLuint nUniform
= GetUniformLocation( rName
);
230 glUniform1i( nUniform
, v1
);
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) );
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
) );
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 );
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,
287 void OpenGLProgram::SetTexture( const OString
& rName
, OpenGLTexture
& rTexture
)
289 GLuint nUniform
= GetUniformLocation( rName
);
290 int nIndex
= maTextures
.size();
292 glUniform1i( nUniform
, nIndex
);
295 OpenGLContext::getVCLContext()->state().texture().active(nIndex
);
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)
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,
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
) );
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
) );
334 void OpenGLProgram::ApplyMatrix(float fWidth
, float fHeight
, float fPixelOffset
)
337 if (mfLastWidth
== fWidth
&& mfLastHeight
== fHeight
&& mfLastPixelOffset
== fPixelOffset
)
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
));
355 void OpenGLProgram::SetBlendMode(GLenum nSFactor
, GLenum nDFactor
)
357 OpenGLContext::getVCLContext()->state().blend().enable();
358 OpenGLContext::getVCLContext()->state().blend().func(nSFactor
, nDFactor
);
362 void OpenGLProgram::DrawTexture( const OpenGLTexture
& rTexture
)
367 float fWidth
= rTexture
.GetWidth();
368 float fHeight
= rTexture
.GetHeight();
371 float fMaxX
= fWidth
;
373 float fMaxY
= fHeight
;
375 std::vector
<GLfloat
> aPosition
{
381 GLfloat aTexCoord
[8];
383 rTexture
.GetWholeCoord( aTexCoord
);
384 SetTextureCoord( aTexCoord
);
385 ApplyMatrix(fWidth
, fHeight
);
386 DrawArrays(GL_TRIANGLE_FAN
, aPosition
);
390 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */