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