Tizen 2.1 base
[framework/osp/uifw.git] / src / ui / effects / renderer / graphics-engine / FUiEffects_RendererGraphicsEngineRenderShaderCache.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Flora License, Version 1.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://floralicense.org/license/
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an AS IS BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 /**
19  * @file                FUiEffects_RendererGraphicsEngineRenderShaderCache.cpp
20  * @brief               Implementation of class for render shaders cache
21  *
22  */
23
24 #include <string>
25
26 #include <renderer/graphics-engine/FUiEffects_RendererGraphicsEngineRenderShaderCache.h>
27 #include <renderer/graphics-engine/FUiEffects_RendererGraphicsEngineRender.h>
28 #include <renderer/engine-model/FUiEffects_RendererEngineModelProgramProperty.h>
29 #include <renderer/engine-model/FUiEffects_RendererEngineModelShaderProperty.h>
30
31 namespace Tizen { namespace Ui { namespace Effects { namespace _Renderer { namespace GraphicsEngine
32 {
33
34 GLenum
35 RenderShaderCache::GetShaderType(Tizen::Ui::Effects::_Renderer::EngineModel::ShaderProperty::ShaderType::Value shaderType)
36 {
37         switch (shaderType)
38         {
39         case EngineModel::ShaderProperty::ShaderType::VERTEX:
40                 return GL_VERTEX_SHADER;
41         case EngineModel::ShaderProperty::ShaderType::FRAGMENT:
42                 return GL_FRAGMENT_SHADER;
43         }
44         return GL_VERTEX_SHADER;
45 }
46
47 bool
48 RenderShaderCache::IsBinary(Tizen::Ui::Effects::_Renderer::EngineModel::ShaderProperty::DataType::Value dataType)
49 {
50         if (dataType == EngineModel::ShaderProperty::DataType::BINARY_DATA)
51         {
52                 return true;
53         }
54
55         return false;
56 }
57
58 RenderShaderCache::RenderShaderCache(Render *pRender, EngineModel::ShaderProperty* pShader):
59         RenderCache(pRender),
60         _shaderId(0),
61         _pShader(pShader)
62 {
63 }
64
65 RenderShaderCache::~RenderShaderCache(void)
66 {
67
68 }
69
70 void
71 RenderShaderCache::DropCache(void)
72 {
73         _shaderId = 0;
74         return;
75 }
76
77 void
78 RenderShaderCache::Die(void)
79 {
80         _pShader = null;
81         RenderCache::Die();
82         return;
83 }
84
85 void
86 RenderShaderCache::DestroyCache(void)
87 {
88         if (_pShader)
89         {
90                 _pShader->SetCache(RenderShaderCachePtr());
91         }
92
93         _pShader = null;
94
95         if (_shaderId)
96         {
97                 glDeleteShader(_shaderId);
98         }
99
100         return;
101 }
102
103 void
104 RenderShaderCache::Validate(Render* pRender)
105 {
106         if (!_invalid)
107         {
108                 return;
109         }
110         if (null == _pShader)
111         {
112                 return;
113         }
114         if (!_shaderId)
115         {
116                 _shaderId = glCreateShader(GetShaderType(_pShader->GetShaderType()));
117         }
118
119         if (!IsBinary(_pShader->GetDataType()))
120         {
121                 const char* pData = (reinterpret_cast<const char*>(_pShader->GetData()));
122
123                 glShaderSource(_shaderId, 1, &pData, null);
124                 glCompileShader(_shaderId);
125
126                 GLint compiled = GL_FALSE;
127                 glGetShaderiv(_shaderId, GL_COMPILE_STATUS, &compiled);
128
129                 if (!compiled)
130                 {
131                         int infologLength = 0;
132                         int charsWritten = 0;
133
134                         glGetShaderiv(_shaderId, GL_INFO_LOG_LENGTH, &infologLength);
135
136                         if (infologLength > 0)
137                         {
138                                 std::string infoLog(infologLength, '\0');
139
140                                 glGetShaderInfoLog(_shaderId, infologLength, &charsWritten, &infoLog[0]);
141                                 SysLogException(NID_UI_EFFECT, E_SYSTEM, "Shader compilation error: %s in \"%s\"", infoLog.c_str(), pData);
142                         }
143                 }
144                 else
145                 {
146                         SysLog(NID_UI_EFFECT, "Shader was compiled successfully");
147                 }
148         }
149         _invalid = false;
150         return;
151 }
152
153 void
154 RenderShaderCache::AttachToProgram(Render* pRender, GLuint programId)
155 {
156         if (_invalid)
157         {
158                 Validate(pRender);
159         }
160
161         glAttachShader(programId, _shaderId);
162
163         return;
164 }
165
166 RenderProgramCache::RenderProgramCache(Render* pRender, EngineModel::ProgramProperty* pProgram)
167         : RenderCache(pRender)
168         , _attributes()
169         , _uniforms()
170         , _programId(0)
171         , _pVertexShader(null)
172         , _pFragmentShader(null)
173         , _pProgram(pProgram)
174 {
175 }
176
177 RenderProgramCache::~RenderProgramCache(void)
178 {
179
180 }
181
182 void
183 RenderProgramCache::DropCache(void)
184 {
185         _programId = 0;
186         return;
187 }
188
189 void
190 RenderProgramCache::Die(void)
191 {
192         _pProgram = null;
193         RenderCache::Die();
194         return;
195 }
196
197 void
198 RenderProgramCache::DestroyCache(void)
199 {
200         if (_pProgram)
201         {
202                 _pProgram->SetCache(RenderProgramCachePtr());
203         }
204
205         _pProgram = null;
206
207         if (_programId)
208         {
209                 glDeleteProgram(_programId);
210         }
211
212         return;
213 }
214
215 void
216 RenderProgramCache::Validate(Render* pRender)
217 {
218         if (!_invalid)
219         {
220                 return;
221         }
222         if (!_pProgram)
223         {
224                 return;
225         }
226
227         EngineModel::ShaderPropertyPtr vertexShaderProperty = _pProgram->GetShader(Tizen::Ui::Effects::_Renderer::EngineModel::ShaderProperty::ShaderType::VERTEX);
228         if (!vertexShaderProperty)
229         {
230                 return;
231         }
232
233         _pVertexShader = static_cast<RenderShaderCache*>(System::GetImpl(vertexShaderProperty->GetCache()));
234         if (!_pVertexShader)
235         {
236                 pRender->BuildCache(*System::GetImpl(vertexShaderProperty));
237                 _pVertexShader = static_cast<RenderShaderCache*>(System::GetImpl(vertexShaderProperty->GetCache()));
238         }
239
240         EngineModel::ShaderPropertyPtr fragmentShaderProperty = _pProgram->GetShader(Tizen::Ui::Effects::_Renderer::EngineModel::ShaderProperty::ShaderType::FRAGMENT);
241         if (!fragmentShaderProperty)
242         {
243                 return;
244         }
245         _pFragmentShader = static_cast<RenderShaderCache*>(System::GetImpl(fragmentShaderProperty->GetCache()));
246         if (!_pFragmentShader)
247         {
248                 pRender->BuildCache(*System::GetImpl(fragmentShaderProperty));
249                 _pFragmentShader = static_cast<RenderShaderCache*>(System::GetImpl(fragmentShaderProperty->GetCache()));
250         }
251
252         if (_programId != 0)
253         {
254                 glDeleteProgram(_programId);
255         }
256
257         _programId = glCreateProgram();
258
259         _pVertexShader->AttachToProgram(pRender, _programId);
260         _pFragmentShader->AttachToProgram(pRender, _programId);
261         glLinkProgram(_programId);
262
263         int isLinked = GL_FALSE;
264         glGetProgramiv(_programId, GL_LINK_STATUS, (int *)&isLinked);
265
266         if (isLinked == GL_FALSE)
267         {
268                 int infologLength = 0;
269                 int charsWritten = 0;
270
271                 glGetProgramiv(_programId, GL_INFO_LOG_LENGTH, &infologLength);
272
273                 if (infologLength > 0)
274                 {
275                         std::string infoLog(infologLength, '\0');
276
277                         glGetProgramInfoLog(_programId, infologLength, &charsWritten, &infoLog[0]);
278                         SysLogException(NID_UI_EFFECT, E_SYSTEM, "Shader program linkage error: %s", infoLog.c_str());
279                 }
280         }
281         else
282         {
283                 SysLog(NID_UI_EFFECT, "Compiled shader was linked successfully");
284         }
285
286         _attributes.clear();
287         _uniforms.clear();
288
289         char nameBuffer[256];
290         GLint nameLength = 0;
291         GLenum type = 0;
292         GLint size = 0;
293
294         GLint numAttributes = 0;
295         glGetProgramiv(_programId, GL_ACTIVE_ATTRIBUTES, &numAttributes);
296         _attributes.resize(numAttributes);
297         for (GLint i = 0; numAttributes > i; ++i)
298         {
299                 glGetActiveAttrib(_programId, i, 250, &nameLength, &size, &type, nameBuffer);
300                 nameBuffer[nameLength] = 0;
301                 _attributes[i].first.type = type;
302                 _attributes[i].first.size = size;
303                 _attributes[i].first.location = glGetAttribLocation(_programId, nameBuffer);
304                 _attributes[i].second = nameBuffer;
305         }
306
307         GLint numUniforms = 0;
308         glGetProgramiv(_programId, GL_ACTIVE_UNIFORMS, &numUniforms);
309         _uniforms.resize(numUniforms);
310
311         for (GLint i = 0; numUniforms > i; ++i)
312         {
313                 glGetActiveUniform(_programId, i, 250, &nameLength, &size, &type, nameBuffer);
314                 nameBuffer[nameLength] = 0;
315                 _uniforms[i].first.type = type;
316                 _uniforms[i].first.size = size;
317                 _uniforms[i].first.location = glGetUniformLocation(_programId, nameBuffer);
318                 _uniforms[i].second = nameBuffer;
319         }
320
321         _invalid = false;
322         return;
323 }
324
325 void
326 RenderProgramCache::UseProgram(Render* pRender)
327 {
328         if (_invalid)
329         {
330                 Validate(pRender);
331         }
332
333         glUseProgram(_programId);
334
335         return;
336 }
337
338 void
339 RenderProgramCache::EnableAttributes(Render*)
340 {
341         const AttribuleListSizeType len = _attributes.size();
342         for (AttribuleListSizeType i = 0; len > i; ++i)
343         {
344                 glEnableVertexAttribArray(_attributes[i].first.location);
345         }
346         return;
347 }
348
349 void
350 RenderProgramCache::DisableAttributes(Render*)
351 {
352         const AttribuleListSizeType len = _attributes.size();
353         for (AttribuleListSizeType i = 0; len > i; ++i)
354         {
355                 glDisableVertexAttribArray(_attributes[i].first.location);
356         }
357         return;
358 }
359
360 const RenderProgramCache::AttribuleListValueType&
361 RenderProgramCache::GetAttribute(AttribuleListSizeType aIndex)
362 {
363         return _attributes[aIndex];
364 }
365
366 RenderProgramCache::AttribuleListSizeType
367 RenderProgramCache::GetNumAttributes(void)
368 {
369         return _attributes.size();
370 }
371
372 const RenderProgramCache::UniformListValueType&
373 RenderProgramCache::GetUniform(UniformListSizeType aIndex)
374 {
375         return _uniforms[aIndex];
376 }
377
378 RenderProgramCache::UniformListSizeType
379 RenderProgramCache::GetNumUniforms(void)
380 {
381         return _uniforms.size();
382 }
383
384
385 }}}}} // Tizen::Ui::Effects::_Renderer::GraphicsEngine