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>
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() :
20 mnEnabledAttribs( 0 ),
21 mnPositionAttrib( SAL_MAX_UINT32
),
22 mnTexCoordAttrib( SAL_MAX_UINT32
),
23 mnAlphaCoordAttrib( SAL_MAX_UINT32
),
24 mnMaskCoordAttrib( SAL_MAX_UINT32
),
28 mfLastPixelOffset(0.0)
32 OpenGLProgram::~OpenGLProgram()
34 maUniformLocations
.clear();
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
);
48 bool OpenGLProgram::Use()
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
-- );
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
);
84 // disable blending if enabled
88 glDisable( GL_BLEND
);
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
;
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,
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
);
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)
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,
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
)
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
);
282 bool OpenGLProgram::DrawTexture( const OpenGLTexture
& rTexture
)
287 float fWidth
= rTexture
.GetWidth();
288 float fHeight
= rTexture
.GetHeight();
291 float fMaxX
= fWidth
;
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 );
308 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */