2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali/internal/render/gl-resources/context.h>
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>
40 namespace // unnamed namespace
48 const GLenum errorCode;
49 const char* errorString;
51 errorStrings errors[] =
53 { GL_NO_ERROR, "GL_NO_ERROR" },
54 { GL_INVALID_ENUM, "GL_INVALID_ENUM" },
55 { GL_INVALID_VALUE, "GL_INVALID_VALUE" },
56 { GL_INVALID_OPERATION, "GL_INVALID_OPERATION" },
57 { GL_OUT_OF_MEMORY, "GL_OUT_OF_MEMORY" }
61 * Called by std::for_each from ~Context
63 void deletePrograms(std::pair< std::size_t, Program* > hashProgram)
65 DALI_ASSERT_DEBUG( hashProgram.second );
66 delete hashProgram.second;
69 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
71 } // unnamed namespace
74 Debug::Filter* Context::gGlLogFilter = Debug::Filter::New(Debug::Concise, false, "LOG_CONTEXT");
75 Debug::Filter* gContextLogFilter = Debug::Filter::New(Debug::Concise, false, "LOG_CONTEXT_META");
78 Context::Context(Integration::GlAbstraction& glAbstraction)
79 : mGlAbstraction(glAbstraction),
80 mGlContextCreated(false),
84 mDepthTestEnabled(false),
85 mDepthMaskEnabled(false),
86 mDitherEnabled(true), // This the only GL capability which defaults to true
87 mPolygonOffsetFillEnabled(false),
88 mSampleAlphaToCoverageEnabled(false),
89 mSampleCoverageEnabled(false),
90 mScissorTestEnabled(false),
91 mStencilTestEnabled(false),
92 mClearColorSet(false),
93 mBoundArrayBufferId(0),
94 mBoundElementArrayBufferId(0),
95 mBoundTransformFeedbackBufferId(0),
96 mActiveTextureUnit( UNINITIALIZED_TEXTURE_UNIT ),
97 mUsingDefaultBlendColor(true),
98 mBlendFuncSeparateSrcRGB(GL_ONE),
99 mBlendFuncSeparateDstRGB(GL_ZERO),
100 mBlendFuncSeparateSrcAlpha(GL_ONE),
101 mBlendFuncSeparateDstAlpha(GL_ZERO),
102 mBlendEquationSeparateModeRGB( GL_FUNC_ADD ),
103 mBlendEquationSeparateModeAlpha( GL_FUNC_ADD ),
106 mClearColor(Color::WHITE), // initial color, never used until it's been set by the user
107 mCullFaceMode(CullNone),
108 mViewPort( 0, 0, 0, 0 ),
109 mCurrentProgram( NULL )
115 // release the cached programs
116 std::for_each(mProgramCache.begin(), mProgramCache.end(), deletePrograms);
117 mProgramCache.clear();
120 void Context::GlContextCreated()
122 DALI_LOG_INFO(gContextLogFilter, Debug::Verbose, "Context::GlContextCreated()\n");
124 DALI_ASSERT_DEBUG(!mGlContextCreated);
126 mGlContextCreated = true;
128 // Set the initial GL state, and check it.
131 // Programs now load on demand
134 void Context::GlContextDestroyed()
136 DALI_LOG_INFO(gContextLogFilter, Debug::Verbose, "Context::GlContextDestroyed()\n");
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 )
142 (*itp).second->GlContextDestroyed();
145 mGlContextCreated = false;
148 const char* Context::ErrorToString( GLenum errorCode )
150 for( unsigned int i = 0; i < sizeof(errors) / sizeof(errors[0]); ++i)
152 if (errorCode == errors[i].errorCode)
154 return errors[i].errorString;
157 return "Unknown Open GLES error";
160 void Context::ResetProgramMatrices()
162 const ProgramContainer::iterator endp = mProgramCache.end();
163 for ( ProgramContainer::iterator itp = mProgramCache.begin(); itp != endp; ++itp )
165 (*itp).second->SetProjectionMatrix( NULL );
166 (*itp).second->SetViewMatrix( NULL );
170 Program* Context::GetCachedProgram( std::size_t hash ) const
172 std::map< std::size_t, Program* >::const_iterator iter = mProgramCache.find(hash);
174 if (iter != mProgramCache.end())
181 void Context::CacheProgram( std::size_t hash, Program* pointer )
183 mProgramCache[ hash ] = pointer;
186 const Rect< int >& Context::GetViewport()
191 void Context::FlushVertexAttributeLocations()
193 for( unsigned int i = 0; i < MAX_ATTRIBUTE_CACHE_SIZE; ++i )
195 // see if our cached state is different to the actual state
196 if (mVertexAttributeCurrentState[ i ] != mVertexAttributeCachedState[ i ] )
198 // it's different so make the change to the driver
199 // and update the cached state
200 mVertexAttributeCurrentState[ i ] = mVertexAttributeCachedState[ i ];
202 if (mVertexAttributeCurrentState[ i ] )
204 LOG_GL("EnableVertexAttribArray %d\n", i);
205 CHECK_GL( *this, mGlAbstraction.EnableVertexAttribArray( i ) );
209 LOG_GL("DisableVertexAttribArray %d\n", i);
210 CHECK_GL( *this, mGlAbstraction.DisableVertexAttribArray( i ) );
217 void Context::SetVertexAttributeLocation(unsigned int location, bool state)
220 if( location >= MAX_ATTRIBUTE_CACHE_SIZE )
222 // not cached, make the gl call through context
225 LOG_GL("EnableVertexAttribArray %d\n", location);
226 CHECK_GL( *this, mGlAbstraction.EnableVertexAttribArray( location ) );
230 LOG_GL("DisableVertexAttribArray %d\n", location);
231 CHECK_GL( *this, mGlAbstraction.DisableVertexAttribArray( location ) );
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;
242 void Context::ResetVertexAttributeState()
244 // reset attribute cache
245 for( unsigned int i=0; i < MAX_ATTRIBUTE_CACHE_SIZE; ++i )
247 mVertexAttributeCachedState[ i ] = false;
248 mVertexAttributeCurrentState[ i ] = false;
250 LOG_GL("DisableVertexAttribArray %d\n", i);
251 CHECK_GL( *this, mGlAbstraction.DisableVertexAttribArray( i ) );
255 void Context::ResetGlState()
257 DALI_LOG_INFO(gContextLogFilter, Debug::Verbose, "Context::ResetGlState()\n");
258 DALI_ASSERT_DEBUG(mGlContextCreated);
260 mClearColorSet = false;
261 // Render manager will call clear in next render
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.
267 mGlAbstraction.ColorMask( true, true, true, true );
270 mGlAbstraction.StencilMask( 0xFF );
272 mBlendEnabled = false;
273 mGlAbstraction.Disable(GL_BLEND);
275 mDepthTestEnabled = false;
276 mGlAbstraction.Disable(GL_DEPTH_TEST);
278 mDepthMaskEnabled = false;
279 mGlAbstraction.DepthMask(GL_FALSE);
281 mDitherEnabled = false; // This the only GL capability which defaults to true
282 mGlAbstraction.Disable(GL_DITHER);
284 mPolygonOffsetFillEnabled = false;
285 mGlAbstraction.Disable(GL_POLYGON_OFFSET_FILL);
287 mSampleAlphaToCoverageEnabled = false;
288 mGlAbstraction.Disable(GL_SAMPLE_ALPHA_TO_COVERAGE);
290 mSampleCoverageEnabled = false;
291 mGlAbstraction.Disable(GL_SAMPLE_COVERAGE);
293 mScissorTestEnabled = false;
294 mGlAbstraction.Disable(GL_SCISSOR_TEST);
296 mStencilTestEnabled = false;
297 mGlAbstraction.Disable(GL_STENCIL_TEST);
299 mBoundArrayBufferId = 0;
300 LOG_GL("BindBuffer GL_ARRAY_BUFFER 0\n");
301 mGlAbstraction.BindBuffer(GL_ARRAY_BUFFER, mBoundArrayBufferId);
303 mBoundElementArrayBufferId = 0;
304 LOG_GL("BindBuffer GL_ELEMENT_ARRAY_BUFFER 0\n");
305 mGlAbstraction.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, mBoundElementArrayBufferId);
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);
313 mActiveTextureUnit = UNINITIALIZED_TEXTURE_UNIT;
315 mUsingDefaultBlendColor = true;
316 mGlAbstraction.BlendColor( 0.0f, 0.0f, 0.0f, 0.0f );
318 mBlendFuncSeparateSrcRGB = GL_ONE;
319 mBlendFuncSeparateDstRGB = GL_ZERO;
320 mBlendFuncSeparateSrcAlpha = GL_ONE;
321 mBlendFuncSeparateDstAlpha = GL_ZERO;
322 mGlAbstraction.BlendFuncSeparate( mBlendFuncSeparateSrcRGB, mBlendFuncSeparateDstRGB,
323 mBlendFuncSeparateSrcAlpha, mBlendFuncSeparateDstAlpha );
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);
330 mCullFaceMode = CullNone;
331 mGlAbstraction.Disable(GL_CULL_FACE);
332 mGlAbstraction.FrontFace(GL_CCW);
333 mGlAbstraction.CullFace(GL_BACK);
335 // get max texture units
336 mGlAbstraction.GetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &mMaxTextureUnits);
337 DALI_ASSERT_DEBUG(mMaxTextureUnits > 7); // according to GLES 2.0 specification
338 mBound2dTextureId.reserve(mMaxTextureUnits);
339 // rebind texture units
340 for( int i=0; i < mMaxTextureUnits; ++i )
342 mBound2dTextureId[ i ] = 0;
343 // set active texture
344 mGlAbstraction.ActiveTexture( GL_TEXTURE0 + i );
345 // bind the previous texture
346 mGlAbstraction.BindTexture(GL_TEXTURE_2D, mBound2dTextureId[ i ] );
349 // get maximum texture size
350 mGlAbstraction.GetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
352 GLint numProgramBinaryFormats;
353 mGlAbstraction.GetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS_OES, &numProgramBinaryFormats);
354 if( GL_NO_ERROR == mGlAbstraction.GetError() && 0 != numProgramBinaryFormats )
356 mProgramBinaryFormats.resize(numProgramBinaryFormats);
357 mGlAbstraction.GetIntegerv(GL_PROGRAM_BINARY_FORMATS_OES, &mProgramBinaryFormats[0]);
360 // reset viewport, this will be set to something useful when rendering
361 mViewPort.x = mViewPort.y = mViewPort.width = mViewPort.height = 0;
363 ResetVertexAttributeState();
366 #ifdef DALI_CONTEXT_LOGGING
368 void Context::PrintCurrentState()
370 DALI_LOG_INFO(SceneGraph::Context::gGlLogFilter, Debug::General,
371 "----------------- Context State BEGIN -----------------\n"
377 "Polygon Offset Fill = %s\n"
378 "Sample Alpha To Coverage = %s\n"
379 "Sample Coverage = %s\n"
380 "Scissor Test = %s\n"
381 "Stencil Test = %s\n"
382 "----------------- Context State END -----------------\n",
383 mBlendEnabled ? "Enabled" : "Disabled",
384 mDepthTestEnabled ? "Enabled" : "Disabled",
385 mDepthMaskEnabled ? "Enabled" : "Disabled",
386 mDitherEnabled ? "Enabled" : "Disabled",
387 mPolygonOffsetFillEnabled ? "Enabled" : "Disabled",
388 mSampleAlphaToCoverageEnabled ? "Enabled" : "Disabled",
389 mSampleCoverageEnabled ? "Enabled" : "Disabled",
390 mScissorTestEnabled ? "Enabled" : "Disabled",
391 mStencilTestEnabled ? "Enabled" : "Disabled");
394 #endif // DALI_CONTEXT_LOGGING
396 } // namespace Internal