Merge "Performance enhancement, cache glClear state" 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
24 // INTERNAL INCLUDES
25 #include <dali/public-api/common/constants.h>
26 #include <dali/public-api/common/compile-time-assert.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 namespace Dali
32 {
33
34 namespace Internal
35 {
36
37 namespace // unnamed namespace
38 {
39
40 DALI_COMPILE_TIME_ASSERT( TEXTURE_UNIT_LAST <= Context::MAX_TEXTURE_UNITS );
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 } // unnamed namespace
60
61 #ifdef DEBUG_ENABLED
62 Debug::Filter* gContextLogFilter = Debug::Filter::New(Debug::Concise, false, "LOG_CONTEXT_STATE");
63 #endif
64
65 Context::Context(Integration::GlAbstraction& glAbstraction)
66 : mGlAbstraction(glAbstraction),
67   mGlContextCreated(false),
68   mColorMask(true),
69   mStencilMask(0xFF),
70   mBlendEnabled(false),
71   mDepthBufferEnabled(false),
72   mDepthMaskEnabled(false),
73   mDitherEnabled(true), // This the only GL capability which defaults to true
74   mPolygonOffsetFillEnabled(false),
75   mSampleAlphaToCoverageEnabled(false),
76   mSampleCoverageEnabled(false),
77   mScissorTestEnabled(false),
78   mStencilBufferEnabled(false),
79   mClearColorSet(false),
80   mBoundArrayBufferId(0),
81   mBoundElementArrayBufferId(0),
82   mBoundTransformFeedbackBufferId(0),
83   mActiveTextureUnit( TEXTURE_UNIT_LAST ),
84   mUsingDefaultBlendColor(true),
85   mBlendFuncSeparateSrcRGB(GL_ONE),
86   mBlendFuncSeparateDstRGB(GL_ZERO),
87   mBlendFuncSeparateSrcAlpha(GL_ONE),
88   mBlendFuncSeparateDstAlpha(GL_ZERO),
89   mBlendEquationSeparateModeRGB( GL_FUNC_ADD ),
90   mBlendEquationSeparateModeAlpha( GL_FUNC_ADD ),
91   mMaxTextureSize(0),
92   mClearColor(Color::WHITE),    // initial color, never used until it's been set by the user
93   mCullFaceMode(CullNone),
94   mViewPort( 0, 0, 0, 0 ),
95   mFrameCount( 0 ),
96   mCulledCount( 0 ),
97   mRendererCount( 0 )
98 {
99 }
100
101 Context::~Context()
102 {
103 }
104
105 void Context::GlContextCreated()
106 {
107   DALI_LOG_INFO(gContextLogFilter, Debug::Verbose, "Context::GlContextCreated()\n");
108
109   DALI_ASSERT_DEBUG(!mGlContextCreated);
110
111   mGlContextCreated = true;
112
113   // Set the initial GL state, and check it.
114   ResetGlState();
115
116 #ifdef DEBUG_ENABLED
117   PrintCurrentState();
118 #endif
119 }
120
121 void Context::GlContextDestroyed()
122 {
123   DALI_LOG_INFO(gContextLogFilter, Debug::Verbose, "Context::GlContextDestroyed()\n");
124   mGlContextCreated = false;
125 }
126
127 const char* Context::ErrorToString( GLenum errorCode )
128 {
129   for( unsigned int i = 0; i < sizeof(errors) / sizeof(errors[0]); ++i)
130   {
131     if (errorCode == errors[i].errorCode)
132     {
133       return errors[i].errorString;
134     }
135   }
136   return "Unknown Open GLES error";
137 }
138
139 const Rect< int >& Context::GetViewport()
140 {
141   return mViewPort;
142 }
143
144 void Context::FlushVertexAttributeLocations()
145 {
146   for( unsigned int i = 0; i < MAX_ATTRIBUTE_CACHE_SIZE; ++i )
147   {
148     // see if our cached state is different to the actual state
149     if (mVertexAttributeCurrentState[ i ] != mVertexAttributeCachedState[ i ] )
150     {
151       // it's different so make the change to the driver
152       // and update the cached state
153       mVertexAttributeCurrentState[ i ] = mVertexAttributeCachedState[ i ];
154
155       if (mVertexAttributeCurrentState[ i ] )
156       {
157         LOG_GL("EnableVertexAttribArray %d\n", i);
158         CHECK_GL( mGlAbstraction, mGlAbstraction.EnableVertexAttribArray( i ) );
159       }
160       else
161       {
162         LOG_GL("DisableVertexAttribArray %d\n", i);
163         CHECK_GL( mGlAbstraction, mGlAbstraction.DisableVertexAttribArray( i ) );
164       }
165     }
166   }
167
168 }
169
170 void Context::SetVertexAttributeLocation(unsigned int location, bool state)
171 {
172
173   if( location >= MAX_ATTRIBUTE_CACHE_SIZE )
174   {
175     // not cached, make the gl call through context
176     if ( state )
177     {
178        LOG_GL("EnableVertexAttribArray %d\n", location);
179        CHECK_GL( mGlAbstraction, mGlAbstraction.EnableVertexAttribArray( location ) );
180     }
181     else
182     {
183       LOG_GL("DisableVertexAttribArray %d\n", location);
184       CHECK_GL( mGlAbstraction, mGlAbstraction.DisableVertexAttribArray( location ) );
185     }
186   }
187   else
188   {
189     // set the cached state, it will be set at the next draw call
190     // if it's different from the current driver state
191     mVertexAttributeCachedState[ location ] = state;
192   }
193 }
194
195 void Context::ResetVertexAttributeState()
196 {
197   // reset attribute cache
198   for( unsigned int i=0; i < MAX_ATTRIBUTE_CACHE_SIZE; ++i )
199   {
200     mVertexAttributeCachedState[ i ] = false;
201     mVertexAttributeCurrentState[ i ] = false;
202
203     LOG_GL("DisableVertexAttribArray %d\n", i);
204     CHECK_GL( mGlAbstraction, mGlAbstraction.DisableVertexAttribArray( i ) );
205   }
206 }
207
208 void Context::ResetGlState()
209 {
210   DALI_LOG_INFO(gContextLogFilter, Debug::Verbose, "Context::ResetGlState()\n");
211   DALI_ASSERT_DEBUG(mGlContextCreated);
212
213   mClearColorSet = false;
214   // Render manager will call clear in next render
215
216   // Reset internal state and Synchronize it with real OpenGL context.
217   // This may seem like overkill, but the GL context is not owned by dali-core,
218   // and no assumptions should be made about the initial state.
219   mColorMask = true;
220   mGlAbstraction.ColorMask( true, true, true, true );
221
222   mStencilMask = 0xFF;
223   mGlAbstraction.StencilMask( 0xFF );
224
225   mBlendEnabled = false;
226   mGlAbstraction.Disable(GL_BLEND);
227
228   mDepthBufferEnabled = false;
229   mGlAbstraction.Disable(GL_DEPTH_TEST);
230
231   mDepthMaskEnabled = false;
232   mGlAbstraction.DepthMask(GL_FALSE);
233
234   mDitherEnabled = false; // This the only GL capability which defaults to true
235   mGlAbstraction.Disable(GL_DITHER);
236
237   mPolygonOffsetFillEnabled = false;
238   mGlAbstraction.Disable(GL_POLYGON_OFFSET_FILL);
239
240   mSampleAlphaToCoverageEnabled = false;
241   mGlAbstraction.Disable(GL_SAMPLE_ALPHA_TO_COVERAGE);
242
243   mSampleCoverageEnabled = false;
244   mGlAbstraction.Disable(GL_SAMPLE_COVERAGE);
245
246   mScissorTestEnabled = false;
247   mGlAbstraction.Disable(GL_SCISSOR_TEST);
248
249   mStencilBufferEnabled = false;
250   mGlAbstraction.Disable(GL_STENCIL_TEST);
251
252   mBoundArrayBufferId = 0;
253   LOG_GL("BindBuffer GL_ARRAY_BUFFER 0\n");
254   mGlAbstraction.BindBuffer(GL_ARRAY_BUFFER, mBoundArrayBufferId);
255
256   mBoundElementArrayBufferId = 0;
257   LOG_GL("BindBuffer GL_ELEMENT_ARRAY_BUFFER 0\n");
258   mGlAbstraction.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, mBoundElementArrayBufferId);
259
260 #ifndef EMSCRIPTEN // not in WebGL
261   mBoundTransformFeedbackBufferId = 0;
262   LOG_GL("BindBuffer GL_TRANSFORM_FEEDBACK_BUFFER 0\n");
263   mGlAbstraction.BindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, mBoundTransformFeedbackBufferId);
264 #endif
265
266   mActiveTextureUnit = TEXTURE_UNIT_LAST;
267
268   mUsingDefaultBlendColor = true;
269   mGlAbstraction.BlendColor( 0.0f, 0.0f, 0.0f, 0.0f );
270
271   mBlendFuncSeparateSrcRGB = GL_ONE;
272   mBlendFuncSeparateDstRGB = GL_ZERO;
273   mBlendFuncSeparateSrcAlpha = GL_ONE;
274   mBlendFuncSeparateDstAlpha = GL_ZERO;
275   mGlAbstraction.BlendFuncSeparate( mBlendFuncSeparateSrcRGB, mBlendFuncSeparateDstRGB,
276                                     mBlendFuncSeparateSrcAlpha, mBlendFuncSeparateDstAlpha );
277
278   // initial state is GL_FUNC_ADD for both RGB and Alpha blend modes
279   mBlendEquationSeparateModeRGB = GL_FUNC_ADD;
280   mBlendEquationSeparateModeAlpha = GL_FUNC_ADD;
281   mGlAbstraction.BlendEquationSeparate( mBlendEquationSeparateModeRGB, mBlendEquationSeparateModeAlpha);
282
283   mCullFaceMode = CullNone;
284   mGlAbstraction.Disable(GL_CULL_FACE);
285   mGlAbstraction.FrontFace(GL_CCW);
286   mGlAbstraction.CullFace(GL_BACK);
287
288   // rebind texture units to 0
289   for( unsigned int i=0; i < MAX_TEXTURE_UNITS; ++i )
290   {
291     mBound2dTextureId[ i ] = 0;
292     // set active texture
293     mGlAbstraction.ActiveTexture( GL_TEXTURE0 + i );
294     mGlAbstraction.BindTexture(GL_TEXTURE_2D, mBound2dTextureId[ i ] );
295   }
296
297   // get maximum texture size
298   mGlAbstraction.GetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
299
300   // reset viewport, this will be set to something useful when rendering
301   mViewPort.x = mViewPort.y = mViewPort.width = mViewPort.height = 0;
302
303   ResetVertexAttributeState();
304
305   mFrameBufferStateCache.Reset();
306 }
307
308 #ifdef DEBUG_ENABLED
309
310 void Context::PrintCurrentState()
311 {
312   const char* cullFaceModes[] = { "CullNone", "CullFront", "CullBack", "CullFrontAndBack" };
313   DALI_LOG_INFO( gContextLogFilter, Debug::General,
314                 "\n----------------- Context State BEGIN -----------------\n"
315                 "Blend = %s\n"
316                 "Cull Face = %s\n"
317                 "Depth Test = %s\n"
318                 "Depth Mask = %s\n"
319                 "Dither = %s\n"
320                 "Polygon Offset Fill = %s\n"
321                 "Sample Alpha To Coverage = %s\n"
322                 "Sample Coverage = %s\n"
323                 "Scissor Test = %s\n"
324                 "Stencil Test = %s\n"
325                 "----------------- Context State END -----------------\n",
326                 mBlendEnabled ? "Enabled" : "Disabled",
327                 cullFaceModes[ mCullFaceMode ],
328                 mDepthBufferEnabled ? "Enabled" : "Disabled",
329                 mDepthMaskEnabled ? "Enabled" : "Disabled",
330                 mDitherEnabled ? "Enabled" : "Disabled",
331                 mPolygonOffsetFillEnabled ? "Enabled" : "Disabled",
332                 mSampleAlphaToCoverageEnabled ? "Enabled" : "Disabled",
333                 mSampleCoverageEnabled ? "Enabled" : "Disabled",
334                 mScissorTestEnabled ? "Enabled" : "Disabled",
335                 mStencilBufferEnabled ? "Enabled" : "Disabled");
336 }
337
338 #endif // DALI_CONTEXT_LOGGING
339
340 } // namespace Internal
341
342 } // namespace Dali