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