Merge "Klockwork: Remove unreachable code" into tizen
[platform/core/uifw/dali-core.git] / dali / internal / render / gl-resources / context.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/render/gl-resources/context.h>
20
21 // EXTERNAL INCLUDES
22 #include <algorithm>
23 #include <limits>
24
25 // INTERNAL INCLUDES
26 #include <dali/public-api/common/constants.h>
27 #include <dali/internal/render/shaders/program.h>
28 #include <dali/integration-api/platform-abstraction.h>
29 #include <dali/internal/render/common/render-manager.h>
30 #include <dali/integration-api/debug.h>
31
32 namespace Dali
33 {
34
35 namespace Internal
36 {
37
38 namespace // unnamed namespace
39 {
40
41 /**
42  * GL error strings
43  */
44 struct errorStrings
45 {
46   const GLenum errorCode;
47   const char* errorString;
48 };
49 errorStrings errors[] =
50 {
51    { GL_NO_ERROR,           "GL_NO_ERROR" },
52    { GL_INVALID_ENUM,       "GL_INVALID_ENUM" },
53    { GL_INVALID_VALUE,      "GL_INVALID_VALUE" },
54    { GL_INVALID_OPERATION,  "GL_INVALID_OPERATION" },
55    { GL_OUT_OF_MEMORY,      "GL_OUT_OF_MEMORY" }
56 };
57
58 /*
59  * Called by std::for_each from ~Context
60  */
61 void deletePrograms(std::pair< std::size_t, Program* > hashProgram)
62 {
63   DALI_ASSERT_DEBUG( hashProgram.second );
64   delete hashProgram.second;
65 }
66
67 const unsigned int UNINITIALIZED_TEXTURE_UNIT = std::numeric_limits<unsigned int>::max();// GL_MAX_TEXTURE_UNITS can't be used because it's depreciated in gles2
68
69 } // unnamed namespace
70
71 #ifdef DEBUG_ENABLED
72 Debug::Filter* Context::gGlLogFilter = Debug::Filter::New(Debug::Concise, false, "LOG_CONTEXT");
73 Debug::Filter* gContextLogFilter = Debug::Filter::New(Debug::Concise, false, "LOG_CONTEXT_META");
74 #endif
75
76 Context::Context(Integration::GlAbstraction& glAbstraction)
77 : mGlAbstraction(glAbstraction),
78   mGlContextCreated(false),
79   mColorMask(true),
80   mStencilMask(0xFF),
81   mBlendEnabled(false),
82   mDepthTestEnabled(false),
83   mDepthMaskEnabled(false),
84   mDitherEnabled(true), // This the only GL capability which defaults to true
85   mPolygonOffsetFillEnabled(false),
86   mSampleAlphaToCoverageEnabled(false),
87   mSampleCoverageEnabled(false),
88   mScissorTestEnabled(false),
89   mStencilTestEnabled(false),
90   mClearColorSet(false),
91   mBoundArrayBufferId(0),
92   mBoundElementArrayBufferId(0),
93   mBoundTransformFeedbackBufferId(0),
94   mActiveTextureUnit( UNINITIALIZED_TEXTURE_UNIT ),
95   mUsingDefaultBlendColor(true),
96   mBlendFuncSeparateSrcRGB(GL_ONE),
97   mBlendFuncSeparateDstRGB(GL_ZERO),
98   mBlendFuncSeparateSrcAlpha(GL_ONE),
99   mBlendFuncSeparateDstAlpha(GL_ZERO),
100   mBlendEquationSeparateModeRGB( GL_FUNC_ADD ),
101   mBlendEquationSeparateModeAlpha( GL_FUNC_ADD ),
102   mMaxTextureSize(0),
103   mClearColor(Color::WHITE),    // initial color, never used until it's been set by the user
104   mCullFaceMode(CullNone),
105   mViewPort( 0, 0, 0, 0 ),
106   mCurrentProgram( NULL ),
107   mFrameCount( 0 ),
108   mCulledCount( 0 ),
109   mRendererCount( 0 )
110 {
111 }
112
113 Context::~Context()
114 {
115   // release the cached programs
116   std::for_each(mProgramCache.begin(), mProgramCache.end(), deletePrograms);
117   mProgramCache.clear();
118 }
119
120 void Context::GlContextCreated()
121 {
122   DALI_LOG_INFO(gContextLogFilter, Debug::Verbose, "Context::GlContextCreated()\n");
123
124   DALI_ASSERT_DEBUG(!mGlContextCreated);
125
126   mGlContextCreated = true;
127
128   // Set the initial GL state, and check it.
129   ResetGlState();
130
131   // Programs now load on demand
132 }
133
134 void Context::GlContextDestroyed()
135 {
136   DALI_LOG_INFO(gContextLogFilter, Debug::Verbose, "Context::GlContextDestroyed()\n");
137   SetCurrentProgram( NULL );
138   // Inform programs they are no longer valid
139   const ProgramContainer::iterator endp = mProgramCache.end();
140   for ( ProgramContainer::iterator itp = mProgramCache.begin(); itp != endp; ++itp )
141   {
142     (*itp).second->GlContextDestroyed();
143   }
144
145   mGlContextCreated = false;
146 }
147
148 const char* Context::ErrorToString( GLenum errorCode )
149 {
150   for( unsigned int i = 0; i < sizeof(errors) / sizeof(errors[0]); ++i)
151   {
152     if (errorCode == errors[i].errorCode)
153     {
154       return errors[i].errorString;
155     }
156   }
157   return "Unknown Open GLES error";
158 }
159
160 void Context::ResetProgramMatrices()
161 {
162   const ProgramContainer::iterator endp = mProgramCache.end();
163   for ( ProgramContainer::iterator itp = mProgramCache.begin(); itp != endp; ++itp )
164   {
165     (*itp).second->SetProjectionMatrix( NULL );
166     (*itp).second->SetViewMatrix( NULL );
167   }
168 }
169
170 Program* Context::GetCachedProgram( std::size_t hash ) const
171 {
172   std::map< std::size_t, Program* >::const_iterator iter = mProgramCache.find(hash);
173
174   if (iter != mProgramCache.end())
175   {
176      return iter->second;
177   }
178   return NULL;
179 }
180
181 void Context::CacheProgram( std::size_t hash, Program* pointer )
182 {
183   mProgramCache[ hash ] = pointer;
184 }
185
186 const Rect< int >& Context::GetViewport()
187 {
188   return mViewPort;
189 }
190
191 void Context::FlushVertexAttributeLocations()
192 {
193   for( unsigned int i = 0; i < MAX_ATTRIBUTE_CACHE_SIZE; ++i )
194   {
195     // see if our cached state is different to the actual state
196     if (mVertexAttributeCurrentState[ i ] != mVertexAttributeCachedState[ i ] )
197     {
198       // it's different so make the change to the driver
199       // and update the cached state
200       mVertexAttributeCurrentState[ i ] = mVertexAttributeCachedState[ i ];
201
202       if (mVertexAttributeCurrentState[ i ] )
203       {
204         LOG_GL("EnableVertexAttribArray %d\n", i);
205         CHECK_GL( *this, mGlAbstraction.EnableVertexAttribArray( i ) );
206       }
207       else
208       {
209         LOG_GL("DisableVertexAttribArray %d\n", i);
210         CHECK_GL( *this, mGlAbstraction.DisableVertexAttribArray( i ) );
211       }
212     }
213   }
214
215 }
216
217 void Context::SetVertexAttributeLocation(unsigned int location, bool state)
218 {
219
220   if( location >= MAX_ATTRIBUTE_CACHE_SIZE )
221   {
222     // not cached, make the gl call through context
223     if ( state )
224     {
225        LOG_GL("EnableVertexAttribArray %d\n", location);
226        CHECK_GL( *this, mGlAbstraction.EnableVertexAttribArray( location ) );
227     }
228     else
229     {
230       LOG_GL("DisableVertexAttribArray %d\n", location);
231       CHECK_GL( *this, mGlAbstraction.DisableVertexAttribArray( location ) );
232     }
233   }
234   else
235   {
236     // set the cached state, it will be set at the next draw call
237     // if it's different from the current driver state
238     mVertexAttributeCachedState[ location ] = state;
239   }
240 }
241
242 void Context::ResetVertexAttributeState()
243 {
244   // reset attribute cache
245   for( unsigned int i=0; i < MAX_ATTRIBUTE_CACHE_SIZE; ++i )
246   {
247     mVertexAttributeCachedState[ i ] = false;
248     mVertexAttributeCurrentState[ i ] = false;
249
250     LOG_GL("DisableVertexAttribArray %d\n", i);
251     CHECK_GL( *this, mGlAbstraction.DisableVertexAttribArray( i ) );
252   }
253 }
254
255 void Context::ResetGlState()
256 {
257   DALI_LOG_INFO(gContextLogFilter, Debug::Verbose, "Context::ResetGlState()\n");
258   DALI_ASSERT_DEBUG(mGlContextCreated);
259
260   mClearColorSet = false;
261   // Render manager will call clear in next render
262
263   // Reset internal state and Synchronize it with real OpenGL context.
264   // This may seem like overkill, but the GL context is not owned by dali-core,
265   // and no assumptions should be made about the initial state.
266   mColorMask = true;
267   mGlAbstraction.ColorMask( true, true, true, true );
268
269   mStencilMask = 0xFF;
270   mGlAbstraction.StencilMask( 0xFF );
271
272   mBlendEnabled = false;
273   mGlAbstraction.Disable(GL_BLEND);
274
275   mDepthTestEnabled = false;
276   mGlAbstraction.Disable(GL_DEPTH_TEST);
277
278   mDepthMaskEnabled = false;
279   mGlAbstraction.DepthMask(GL_FALSE);
280
281   mDitherEnabled = false; // This the only GL capability which defaults to true
282   mGlAbstraction.Disable(GL_DITHER);
283
284   mPolygonOffsetFillEnabled = false;
285   mGlAbstraction.Disable(GL_POLYGON_OFFSET_FILL);
286
287   mSampleAlphaToCoverageEnabled = false;
288   mGlAbstraction.Disable(GL_SAMPLE_ALPHA_TO_COVERAGE);
289
290   mSampleCoverageEnabled = false;
291   mGlAbstraction.Disable(GL_SAMPLE_COVERAGE);
292
293   mScissorTestEnabled = false;
294   mGlAbstraction.Disable(GL_SCISSOR_TEST);
295
296   mStencilTestEnabled = false;
297   mGlAbstraction.Disable(GL_STENCIL_TEST);
298
299   mBoundArrayBufferId = 0;
300   LOG_GL("BindBuffer GL_ARRAY_BUFFER 0\n");
301   mGlAbstraction.BindBuffer(GL_ARRAY_BUFFER, mBoundArrayBufferId);
302
303   mBoundElementArrayBufferId = 0;
304   LOG_GL("BindBuffer GL_ELEMENT_ARRAY_BUFFER 0\n");
305   mGlAbstraction.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, mBoundElementArrayBufferId);
306
307 #ifndef EMSCRIPTEN // not in WebGL
308   mBoundTransformFeedbackBufferId = 0;
309   LOG_GL("BindBuffer GL_TRANSFORM_FEEDBACK_BUFFER 0\n");
310   mGlAbstraction.BindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, mBoundTransformFeedbackBufferId);
311 #endif
312
313   mActiveTextureUnit = UNINITIALIZED_TEXTURE_UNIT;
314
315   mUsingDefaultBlendColor = true;
316   mGlAbstraction.BlendColor( 0.0f, 0.0f, 0.0f, 0.0f );
317
318   mBlendFuncSeparateSrcRGB = GL_ONE;
319   mBlendFuncSeparateDstRGB = GL_ZERO;
320   mBlendFuncSeparateSrcAlpha = GL_ONE;
321   mBlendFuncSeparateDstAlpha = GL_ZERO;
322   mGlAbstraction.BlendFuncSeparate( mBlendFuncSeparateSrcRGB, mBlendFuncSeparateDstRGB,
323                                     mBlendFuncSeparateSrcAlpha, mBlendFuncSeparateDstAlpha );
324
325   // initial state is GL_FUNC_ADD for both RGB and Alpha blend modes
326   mBlendEquationSeparateModeRGB = GL_FUNC_ADD;
327   mBlendEquationSeparateModeAlpha = GL_FUNC_ADD;
328   mGlAbstraction.BlendEquationSeparate( mBlendEquationSeparateModeRGB, mBlendEquationSeparateModeAlpha);
329
330   mCullFaceMode = CullNone;
331   mGlAbstraction.Disable(GL_CULL_FACE);
332   mGlAbstraction.FrontFace(GL_CCW);
333   mGlAbstraction.CullFace(GL_BACK);
334
335   // rebind texture units
336   for( unsigned int i=0; i < MAX_TEXTURE_UNITS; ++i )
337   {
338     mBound2dTextureId[ i ] = 0;
339     // set active texture
340     mGlAbstraction.ActiveTexture( GL_TEXTURE0 + i );
341     // bind the previous texture
342     mGlAbstraction.BindTexture(GL_TEXTURE_2D, mBound2dTextureId[ i ] );
343   }
344
345   // get maximum texture size
346   mGlAbstraction.GetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
347
348   GLint numProgramBinaryFormats;
349   mGlAbstraction.GetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS_OES, &numProgramBinaryFormats);
350   if( GL_NO_ERROR == mGlAbstraction.GetError() && 0 != numProgramBinaryFormats )
351   {
352     mProgramBinaryFormats.Resize(numProgramBinaryFormats);
353     mGlAbstraction.GetIntegerv(GL_PROGRAM_BINARY_FORMATS_OES, &mProgramBinaryFormats[0]);
354   }
355
356   // reset viewport, this will be set to something useful when rendering
357   mViewPort.x = mViewPort.y = mViewPort.width = mViewPort.height = 0;
358
359   ResetVertexAttributeState();
360 }
361
362 #ifdef DALI_CONTEXT_LOGGING
363
364 void Context::PrintCurrentState()
365 {
366   DALI_LOG_INFO(SceneGraph::Context::gGlLogFilter, Debug::General,
367                 "----------------- Context State BEGIN -----------------\n"
368                 "Blend = %s\n"
369                 "Cull Face = %s\n"
370                 "Depth Test = %s\n"
371                 "Depth Mask = %s\n"
372                 "Dither = %s\n"
373                 "Polygon Offset Fill = %s\n"
374                 "Sample Alpha To Coverage = %s\n"
375                 "Sample Coverage = %s\n"
376                 "Scissor Test = %s\n"
377                 "Stencil Test = %s\n"
378                 "----------------- Context State END -----------------\n",
379                 mBlendEnabled ? "Enabled" : "Disabled",
380                 mDepthTestEnabled ? "Enabled" : "Disabled",
381                 mDepthMaskEnabled ? "Enabled" : "Disabled",
382                 mDitherEnabled ? "Enabled" : "Disabled",
383                 mPolygonOffsetFillEnabled ? "Enabled" : "Disabled",
384                 mSampleAlphaToCoverageEnabled ? "Enabled" : "Disabled",
385                 mSampleCoverageEnabled ? "Enabled" : "Disabled",
386                 mScissorTestEnabled ? "Enabled" : "Disabled",
387                 mStencilTestEnabled ? "Enabled" : "Disabled");
388 }
389
390 #endif // DALI_CONTEXT_LOGGING
391
392 } // namespace Internal
393
394 } // namespace Dali