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