2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
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
8 // http://floralicense.org/license/
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.
18 #include <dali/internal/render/gl-resources/context.h>
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>
39 namespace // unnamed namespace
47 const GLenum errorCode;
48 const char* errorString;
50 errorStrings errors[] =
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" }
60 * Called by std::for_each from ~Context
62 void deletePrograms(std::pair< std::size_t, Program* > hashProgram)
64 DALI_ASSERT_DEBUG( hashProgram.second );
65 delete hashProgram.second;
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
70 } // unnamed namespace
73 Debug::Filter* Context::gGlLogFilter = Debug::Filter::New(Debug::Concise, false, "LOG_CONTEXT");
76 Context::Context(Integration::GlAbstraction& glAbstraction)
77 : mGlAbstraction(glAbstraction),
78 mGlContextCreated(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 ),
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 )
113 // release the cached programs
114 std::for_each(mProgramCache.begin(), mProgramCache.end(), deletePrograms);
115 mProgramCache.clear();
118 void Context::GlContextCreated()
120 DALI_ASSERT_DEBUG(!mGlContextCreated);
122 mGlContextCreated = true;
124 // Set the initial GL state, and check it.
127 const ProgramContainer::iterator endp = mProgramCache.end();
128 for ( ProgramContainer::iterator itp = mProgramCache.begin(); itp != endp; ++itp )
130 (*itp).second->GlContextCreated();
134 void Context::GlContextDestroyed()
136 const ProgramContainer::iterator endp = mProgramCache.end();
137 for ( ProgramContainer::iterator itp = mProgramCache.begin(); itp != endp; ++itp )
139 (*itp).second->GlContextDestroyed();
142 mGlContextCreated = false;
145 const char* Context::ErrorToString( GLenum errorCode )
147 for( unsigned int i = 0; i < sizeof(errors) / sizeof(errors[0]); ++i)
149 if (errorCode == errors[i].errorCode)
151 return errors[i].errorString;
154 return "Unknown Open GLES error";
157 Program* Context::GetCachedProgram( std::size_t hash ) const
159 std::map< std::size_t, Program* >::const_iterator iter = mProgramCache.find(hash);
161 if (iter != mProgramCache.end())
168 void Context::CacheProgram( std::size_t hash, Program* pointer )
170 mProgramCache[ hash ] = pointer;
173 const Rect< int >& Context::GetViewport()
178 void Context::FlushVertexAttributeLocations()
180 for( unsigned int i = 0; i < MAX_ATTRIBUTE_CACHE_SIZE; ++i )
182 // see if our cached state is different to the actual state
183 if (mVertexAttributeCurrentState[ i ] != mVertexAttributeCachedState[ i ] )
185 // it's different so make the change to the driver
186 // and update the cached state
187 mVertexAttributeCurrentState[ i ] = mVertexAttributeCachedState[ i ];
189 if (mVertexAttributeCurrentState[ i ] )
191 LOG_GL("EnableVertexAttribArray %d\n", i);
192 CHECK_GL( *this, mGlAbstraction.EnableVertexAttribArray( i ) );
196 LOG_GL("DisableVertexAttribArray %d\n", i);
197 CHECK_GL( *this, mGlAbstraction.DisableVertexAttribArray( i ) );
204 void Context::SetVertexAttributeLocation(unsigned int location, bool state)
207 if( location >= MAX_ATTRIBUTE_CACHE_SIZE )
209 // not cached, make the gl call through context
212 LOG_GL("EnableVertexAttribArray %d\n", location);
213 CHECK_GL( *this, mGlAbstraction.EnableVertexAttribArray( location ) );
217 LOG_GL("DisableVertexAttribArray %d\n", location);
218 CHECK_GL( *this, mGlAbstraction.DisableVertexAttribArray( location ) );
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;
229 void Context::ResetVertexAttributeState()
231 // reset attribute cache
232 for( unsigned int i=0; i < MAX_ATTRIBUTE_CACHE_SIZE; ++i )
234 mVertexAttributeCachedState[ i ] = false;
235 mVertexAttributeCurrentState[ i ] = false;
237 LOG_GL("DisableVertexAttribArray %d\n", i);
238 CHECK_GL( *this, mGlAbstraction.DisableVertexAttribArray( i ) );
242 void Context::ResetGlState()
244 DALI_ASSERT_DEBUG(mGlContextCreated);
246 mClearColorSet = false;
247 // Render manager will call clear in next render
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.
253 mGlAbstraction.ColorMask( true, true, true, true );
256 mGlAbstraction.StencilMask( 0xFF );
258 mBlendEnabled = false;
259 mGlAbstraction.Disable(GL_BLEND);
261 mDepthTestEnabled = false;
262 mGlAbstraction.Disable(GL_DEPTH_TEST);
264 mDepthMaskEnabled = false;
265 mGlAbstraction.DepthMask(GL_FALSE);
267 mDitherEnabled = false; // This the only GL capability which defaults to true
268 mGlAbstraction.Disable(GL_DITHER);
270 mPolygonOffsetFillEnabled = false;
271 mGlAbstraction.Disable(GL_POLYGON_OFFSET_FILL);
273 mSampleAlphaToCoverageEnabled = false;
274 mGlAbstraction.Disable(GL_SAMPLE_ALPHA_TO_COVERAGE);
276 mSampleCoverageEnabled = false;
277 mGlAbstraction.Disable(GL_SAMPLE_COVERAGE);
279 mScissorTestEnabled = false;
280 mGlAbstraction.Disable(GL_SCISSOR_TEST);
282 mStencilTestEnabled = false;
283 mGlAbstraction.Disable(GL_STENCIL_TEST);
285 mBoundArrayBufferId = 0;
286 LOG_GL("BindBuffer GL_ARRAY_BUFFER 0\n");
287 mGlAbstraction.BindBuffer(GL_ARRAY_BUFFER, mBoundArrayBufferId);
289 mBoundElementArrayBufferId = 0;
290 LOG_GL("BindBuffer GL_ELEMENT_ARRAY_BUFFER 0\n");
291 mGlAbstraction.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, mBoundElementArrayBufferId);
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);
299 mActiveTextureUnit = UNINITIALIZED_TEXTURE_UNIT;
301 mUsingDefaultBlendColor = true;
302 mGlAbstraction.BlendColor( 0.0f, 0.0f, 0.0f, 0.0f );
304 mBlendFuncSeparateSrcRGB = GL_ONE;
305 mBlendFuncSeparateDstRGB = GL_ZERO;
306 mBlendFuncSeparateSrcAlpha = GL_ONE;
307 mBlendFuncSeparateDstAlpha = GL_ZERO;
308 mGlAbstraction.BlendFuncSeparate( mBlendFuncSeparateSrcRGB, mBlendFuncSeparateDstRGB,
309 mBlendFuncSeparateSrcAlpha, mBlendFuncSeparateDstAlpha );
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);
316 mCullFaceMode = CullNone;
317 mGlAbstraction.Disable(GL_CULL_FACE);
318 mGlAbstraction.FrontFace(GL_CCW);
319 mGlAbstraction.CullFace(GL_BACK);
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 )
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 ] );
335 // get maximum texture size
336 mGlAbstraction.GetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
338 GLint numProgramBinaryFormats;
339 mGlAbstraction.GetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS_OES, &numProgramBinaryFormats);
340 if( GL_NO_ERROR == mGlAbstraction.GetError() && 0 != numProgramBinaryFormats )
342 mProgramBinaryFormats.resize(numProgramBinaryFormats);
343 mGlAbstraction.GetIntegerv(GL_PROGRAM_BINARY_FORMATS_OES, &mProgramBinaryFormats[0]);
346 // reset viewport, this will be set to something useful when rendering
347 mViewPort.x = mViewPort.y = mViewPort.width = mViewPort.height = 0;
349 ResetVertexAttributeState();
352 #ifdef DALI_CONTEXT_LOGGING
354 void Context::PrintCurrentState()
356 DALI_LOG_INFO(SceneGraph::Context::gGlLogFilter, Debug::General,
357 "----------------- Context State BEGIN -----------------\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");
380 #endif // DALI_CONTEXT_LOGGING
382 } // namespace Internal