Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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 : */
9 :
10 : #include <opengl/program.hxx>
11 :
12 : #include <vcl/opengl/OpenGLHelper.hxx>
13 :
14 : #include <glm/glm.hpp>
15 : #include <glm/gtc/type_ptr.hpp>
16 :
17 0 : OpenGLProgram::OpenGLProgram() :
18 : mnId( 0 ),
19 : mnEnabledAttribs( 0 ),
20 : mnPositionAttrib( SAL_MAX_UINT32 ),
21 : mnTexCoordAttrib( SAL_MAX_UINT32 ),
22 : mnAlphaCoordAttrib( SAL_MAX_UINT32 ),
23 0 : mbBlending( false )
24 : {
25 0 : }
26 :
27 0 : OpenGLProgram::~OpenGLProgram()
28 : {
29 0 : maUniformLocations.clear();
30 0 : if( mnId != 0 )
31 0 : glDeleteProgram( mnId );
32 0 : }
33 :
34 0 : bool OpenGLProgram::Load( const OUString& rVertexShader, const OUString& rFragmentShader, const OString& preamble )
35 : {
36 0 : mnId = OpenGLHelper::LoadShaders( rVertexShader, rFragmentShader, preamble );
37 0 : return ( mnId != 0 );
38 : }
39 :
40 0 : bool OpenGLProgram::Use()
41 : {
42 0 : if( !mnId )
43 0 : return false;
44 :
45 0 : glUseProgram( mnId );
46 0 : return true;
47 : }
48 :
49 0 : bool OpenGLProgram::Clean()
50 : {
51 : // unbind all textures
52 0 : if( !maTextures.empty() )
53 : {
54 0 : int nIndex( maTextures.size() - 1 );
55 0 : TextureList::reverse_iterator it( maTextures.rbegin() );
56 0 : while( it != maTextures.rend() )
57 : {
58 0 : glActiveTexture( GL_TEXTURE0 + nIndex-- );
59 0 : it->Unbind();
60 0 : ++it;
61 : }
62 0 : maTextures.clear();
63 : }
64 :
65 : // disable any enabled vertex attrib array
66 0 : if( mnEnabledAttribs )
67 : {
68 0 : for( int i = 0; i < 32; i++ )
69 : {
70 0 : if( mnEnabledAttribs & ( 1 << i ) )
71 0 : glDisableVertexAttribArray( i );
72 : }
73 0 : mnEnabledAttribs = 0;
74 : }
75 :
76 : // disable blending if enabled
77 0 : if( mbBlending )
78 : {
79 0 : mbBlending = false;
80 0 : glDisable( GL_BLEND );
81 : }
82 :
83 0 : CHECK_GL_ERROR();
84 0 : return true;
85 : }
86 :
87 0 : void OpenGLProgram::SetVertexAttrib( GLuint& rAttrib, const OString& rName, const GLvoid* pData )
88 : {
89 0 : if( rAttrib == SAL_MAX_UINT32 )
90 0 : rAttrib = glGetAttribLocation( mnId, rName.getStr() );
91 0 : if( (mnEnabledAttribs & ( 1 << rAttrib )) == 0 )
92 : {
93 0 : glEnableVertexAttribArray( rAttrib );
94 0 : mnEnabledAttribs |= ( 1 << rAttrib );
95 : }
96 0 : glVertexAttribPointer( rAttrib, 2, GL_FLOAT, GL_FALSE, 0, pData );
97 0 : }
98 :
99 0 : void OpenGLProgram::SetVertices( const GLvoid* pData )
100 : {
101 0 : SetVertexAttrib( mnPositionAttrib, "position", pData );
102 0 : }
103 :
104 0 : void OpenGLProgram::SetTextureCoord( const GLvoid* pData )
105 : {
106 0 : SetVertexAttrib( mnTexCoordAttrib, "tex_coord_in", pData );
107 0 : }
108 :
109 0 : void OpenGLProgram::SetAlphaCoord( const GLvoid* pData )
110 : {
111 0 : SetVertexAttrib( mnAlphaCoordAttrib, "alpha_coord_in", pData );
112 0 : }
113 :
114 0 : GLuint OpenGLProgram::GetUniformLocation( const OString& rName )
115 : {
116 0 : auto it = maUniformLocations.find( rName );
117 0 : if( it == maUniformLocations.end() )
118 : {
119 0 : GLuint nLocation = glGetUniformLocation( mnId, rName.getStr() );
120 0 : maUniformLocations[rName] = nLocation;
121 0 : return nLocation;
122 : }
123 :
124 0 : return it->second;
125 : }
126 :
127 0 : void OpenGLProgram::SetUniform1f( const OString& rName, GLfloat v1 )
128 : {
129 0 : GLuint nUniform = GetUniformLocation( rName );
130 0 : glUniform1f( nUniform, v1 );
131 0 : }
132 :
133 0 : void OpenGLProgram::SetUniform2f( const OString& rName, GLfloat v1, GLfloat v2 )
134 : {
135 0 : GLuint nUniform = GetUniformLocation( rName );
136 0 : glUniform2f( nUniform, v1, v2 );
137 0 : }
138 :
139 0 : void OpenGLProgram::SetUniform1fv( const OString& rName, GLsizei nCount, GLfloat* aValues )
140 : {
141 0 : GLuint nUniform = GetUniformLocation( rName );
142 0 : glUniform1fv( nUniform, nCount, aValues );
143 0 : }
144 :
145 0 : void OpenGLProgram::SetUniform2fv( const OString& rName, GLsizei nCount, GLfloat* aValues )
146 : {
147 0 : GLuint nUniform = GetUniformLocation( rName );
148 0 : glUniform2fv( nUniform, nCount, aValues );
149 0 : }
150 :
151 0 : void OpenGLProgram::SetUniform1i( const OString& rName, GLint v1 )
152 : {
153 0 : GLuint nUniform = GetUniformLocation( rName );
154 0 : glUniform1i( nUniform, v1 );
155 0 : }
156 :
157 0 : void OpenGLProgram::SetColor( const OString& rName, SalColor nColor, sal_uInt8 nTransparency )
158 : {
159 0 : GLuint nUniform = GetUniformLocation( rName );
160 : glUniform4f( nUniform,
161 0 : ((float) SALCOLOR_RED( nColor )) / 255,
162 0 : ((float) SALCOLOR_GREEN( nColor )) / 255,
163 : ((float) SALCOLOR_BLUE( nColor )) / 255,
164 0 : (100 - nTransparency) * (1.0 / 100) );
165 :
166 0 : if( nTransparency > 0 )
167 0 : SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
168 0 : }
169 :
170 0 : void OpenGLProgram::SetColorf( const OString& rName, SalColor nColor, double fTransparency )
171 : {
172 0 : GLuint nUniform = GetUniformLocation( rName );
173 : glUniform4f( nUniform,
174 0 : ((float) SALCOLOR_RED( nColor )) / 255,
175 0 : ((float) SALCOLOR_GREEN( nColor )) / 255,
176 : ((float) SALCOLOR_BLUE( nColor )) / 255,
177 0 : (1.0f - fTransparency) );
178 :
179 0 : if( fTransparency > 0.0 )
180 0 : SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
181 0 : }
182 :
183 0 : void OpenGLProgram::SetColor( const OString& rName, const Color& rColor )
184 : {
185 0 : GLuint nUniform = GetUniformLocation( rName );
186 : glUniform4f( nUniform,
187 0 : ((float) rColor.GetRed()) / 255,
188 0 : ((float) rColor.GetGreen()) / 255,
189 0 : ((float) rColor.GetBlue()) / 255,
190 0 : 1.0f - ((float) rColor.GetTransparency()) / 255 );
191 :
192 0 : if( rColor.GetTransparency() > 0 )
193 0 : SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
194 0 : }
195 :
196 0 : void OpenGLProgram::SetColorWithIntensity( const OString& rName, const Color& rColor, long nFactor )
197 : {
198 0 : GLuint nUniform = GetUniformLocation( rName );
199 : glUniform4f( nUniform,
200 0 : ((float) rColor.GetRed()) * nFactor / 25500.0,
201 0 : ((float) rColor.GetGreen()) * nFactor / 25500.0,
202 0 : ((float) rColor.GetBlue()) * nFactor / 25500.0,
203 0 : 1.0f );
204 0 : }
205 :
206 0 : void OpenGLProgram::SetTexture( const OString& rName, OpenGLTexture& rTexture )
207 : {
208 0 : GLuint nUniform = GetUniformLocation( rName );
209 0 : int nIndex = maTextures.size();
210 :
211 0 : glUniform1i( nUniform, nIndex );
212 0 : glActiveTexture( GL_TEXTURE0 + nIndex );
213 0 : rTexture.Bind();
214 0 : maTextures.push_back( rTexture );
215 0 : }
216 :
217 0 : void OpenGLProgram::SetTransform(
218 : const OString& rName,
219 : const OpenGLTexture& rTexture,
220 : const basegfx::B2DPoint& rNull,
221 : const basegfx::B2DPoint& rX,
222 : const basegfx::B2DPoint& rY )
223 : {
224 0 : auto nTexWidth = rTexture.GetWidth();
225 0 : auto nTexHeight = rTexture.GetHeight();
226 0 : if (nTexWidth == 0 || nTexHeight == 0)
227 0 : return;
228 :
229 0 : GLuint nUniform = GetUniformLocation( rName );
230 0 : const basegfx::B2DVector aXRel = rX - rNull;
231 0 : const basegfx::B2DVector aYRel = rY - rNull;
232 : const float aValues[] = {
233 0 : (float) aXRel.getX()/nTexWidth, (float) aXRel.getY()/nTexWidth, 0, 0,
234 0 : (float) aYRel.getX()/nTexHeight, (float) aYRel.getY()/nTexHeight, 0, 0,
235 : 0, 0, 1, 0,
236 0 : (float) rNull.getX(), (float) rNull.getY(), 0, 1 };
237 0 : glm::mat4 mMatrix = glm::make_mat4( aValues );
238 0 : glUniformMatrix4fv( nUniform, 1, GL_FALSE, glm::value_ptr( mMatrix ) );
239 : }
240 :
241 0 : void OpenGLProgram::SetBlendMode( GLenum nSFactor, GLenum nDFactor )
242 : {
243 0 : glEnable( GL_BLEND );
244 0 : glBlendFunc( nSFactor, nDFactor );
245 0 : mbBlending = true;
246 0 : }
247 :
248 0 : bool OpenGLProgram::DrawTexture( OpenGLTexture& rTexture )
249 : {
250 0 : GLfloat aPosition[8] = { -1, -1, -1, 1, 1, 1, 1, -1 };
251 : GLfloat aTexCoord[8];
252 :
253 0 : if( !rTexture )
254 0 : return false;
255 :
256 0 : rTexture.GetWholeCoord( aTexCoord );
257 0 : SetVertices( aPosition );
258 0 : SetTextureCoord( aTexCoord );
259 0 : glDrawArrays( GL_TRIANGLE_FAN, 0, 4 );
260 0 : CHECK_GL_ERROR();
261 :
262 0 : return true;
263 : }
264 :
265 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|