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