Added property to Renderer to specify the depth function
[platform/core/uifw/dali-core.git] / dali / internal / render / common / render-algorithms.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/common/render-algorithms.h>
20
21 // INTERNAL INCLUDES
22 #include <dali/internal/render/common/render-debug.h>
23 #include <dali/internal/render/common/render-list.h>
24 #include <dali/internal/render/common/render-instruction.h>
25 #include <dali/internal/render/gl-resources/context.h>
26 #include <dali/internal/render/renderers/render-renderer.h>
27
28 using Dali::Internal::SceneGraph::RenderItem;
29 using Dali::Internal::SceneGraph::RenderList;
30 using Dali::Internal::SceneGraph::RenderListContainer;
31 using Dali::Internal::SceneGraph::RenderInstruction;
32
33 namespace Dali
34 {
35
36 namespace Internal
37 {
38
39 namespace Render
40 {
41
42 /**
43  * Helper to set the depth function
44  * @param[in] context The GL context
45  * @param[in] depthFunction The depth function
46  */
47 inline void SetDepthFunction( Context& context, DepthFunction::Type depthFunction )
48 {
49   switch( depthFunction )
50   {
51     case DepthFunction::OFF:
52     {
53       context.EnableDepthBuffer( false );
54       break;
55     }
56     case DepthFunction::NEVER:
57     {
58       context.EnableDepthBuffer( true );
59       context.DepthFunc( GL_NEVER );
60       break;
61     }
62     case DepthFunction::ALWAYS:
63     {
64       context.EnableDepthBuffer( true );
65       context.DepthFunc( GL_ALWAYS );
66       break;
67     }
68     case DepthFunction::LESS:
69     {
70       context.EnableDepthBuffer( true );
71       context.DepthFunc( GL_LESS );
72       break;
73     }
74     case DepthFunction::GREATER:
75     {
76       context.EnableDepthBuffer( true );
77       context.DepthFunc( GL_GREATER );
78       break;
79     }
80     case DepthFunction::EQUAL:
81     {
82       context.EnableDepthBuffer( true );
83       context.DepthFunc( GL_EQUAL );
84       break;
85     }
86     case DepthFunction::NOT_EQUAL:
87     {
88       context.EnableDepthBuffer( true );
89       context.DepthFunc( GL_NOTEQUAL );
90       break;
91     }
92     case DepthFunction::LESS_EQUAL:
93     {
94       context.EnableDepthBuffer( true );
95       context.DepthFunc( GL_LEQUAL );
96       break;
97     }
98     case DepthFunction::GREATER_EQUAL:
99     {
100       context.EnableDepthBuffer( true );
101       context.DepthFunc( GL_GEQUAL );
102       break;
103     }
104   }
105 }
106
107 /**
108  * Sets up the scissor test if required.
109  * @param[in] renderList The render list from which to get the clipping flag
110  * @param[in] context The context
111  */
112 inline void SetScissorTest( const RenderList& renderList, Context& context )
113 {
114   // Scissor testing
115   if( renderList.IsClipping() )
116   {
117     context.SetScissorTest( true );
118
119     const Dali::ClippingBox& clip = renderList.GetClippingBox();
120     context.Scissor(clip.x, clip.y, clip.width, clip.height);
121   }
122   else
123   {
124     context.SetScissorTest( false );
125   }
126 }
127
128 /**
129  * Sets the render flags for depth testing and stencil buffer
130  *
131  * @param[in] renderList The render list from which to get the render flags
132  * @param[in] context The context
133  */
134 inline void SetRenderFlags( const RenderList& renderList, Context& context )
135 {
136   const unsigned int renderFlags = renderList.GetFlags();
137
138   if( ( renderFlags & RenderList::DEPTH_BUFFER_ENABLED ) != 0u )
139   {
140     //Enable depth testing
141     context.EnableDepthBuffer( true );
142   }
143   else
144   {
145     //Disable depth test and depth write
146     context.EnableDepthBuffer( false );
147     context.DepthMask( false );
148   }
149
150   GLbitfield clearMask   = ( renderFlags & RenderList::DEPTH_CLEAR ) ? GL_DEPTH_BUFFER_BIT : 0u;
151
152   // Stencil enabled, writing, and clearing...
153   const bool enableStencilBuffer( renderFlags & RenderList::STENCIL_BUFFER_ENABLED );
154   const bool enableStencilWrite( renderFlags & RenderList::STENCIL_WRITE );
155   context.EnableStencilBuffer( enableStencilBuffer );
156   if( enableStencilBuffer )
157   {
158     context.StencilFunc( (enableStencilWrite ? GL_ALWAYS : GL_EQUAL), 1, 0xFF );
159     context.StencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
160
161     clearMask |= (renderFlags & RenderList::STENCIL_CLEAR) ? GL_STENCIL_BUFFER_BIT : 0u;
162   }
163
164   // Write to stencil buffer or color buffer, but not both
165   context.StencilMask( enableStencilWrite ? 0xFF : 0x00 );
166   context.ColorMask( !enableStencilWrite );
167
168   // Clear depth and/or stencil buffer.
169   if( clearMask )
170   {
171     // only clear if the depth and/or stencil buffer have been written to after a previous clear
172     context.Clear( clearMask, Context::CHECK_CACHED_VALUES );
173   }
174 }
175
176
177 /**
178  * Process a render-list.
179  * @param[in] renderList The render-list to process.
180  * @param[in] context The GL context.
181  * @param[in] defaultShader The default shader to use.
182  * @param[in] buffer The current render buffer index (previous update buffer)
183  * @param[in] viewMatrix The view matrix from the appropriate camera.
184  * @param[in] projectionMatrix The projection matrix from the appropriate camera.
185  */
186 inline void ProcessRenderList(
187   const RenderList& renderList,
188   Context& context,
189   SceneGraph::TextureCache& textureCache,
190   SceneGraph::Shader& defaultShader,
191   BufferIndex bufferIndex,
192   const Matrix& viewMatrix,
193   const Matrix& projectionMatrix )
194 {
195   DALI_PRINT_RENDER_LIST( renderList );
196
197   SetScissorTest( renderList, context );
198   SetRenderFlags( renderList, context );
199
200   if( renderList.HasColorRenderItems() )
201   {
202     bool depthBufferEnabled = ( ( renderList.GetFlags() & RenderList::DEPTH_BUFFER_ENABLED ) != 0u );
203     size_t count = renderList.Count();
204
205     if( depthBufferEnabled )
206     {
207       for ( size_t index = 0; index < count; ++index )
208       {
209         const RenderItem& item = renderList.GetItem( index );
210         DALI_PRINT_RENDER_ITEM( item );
211
212         DepthWriteMode::Type depthWriteMode = item.mRenderer->GetDepthWriteMode();
213         context.DepthMask( ( depthWriteMode == DepthWriteMode::AUTO && item.mIsOpaque ) ||
214                            ( depthWriteMode == DepthWriteMode::ON ) );
215
216         SetDepthFunction( context, item.mRenderer->GetDepthFunction() );
217         item.mRenderer->Render( context, textureCache, bufferIndex, *item.mNode, defaultShader,
218                                 item.mModelMatrix, item.mModelViewMatrix, viewMatrix, projectionMatrix, item.mSize, !item.mIsOpaque );
219       }
220     }
221     else
222     {
223       for ( size_t index = 0; index < count; ++index )
224       {
225         const RenderItem& item = renderList.GetItem( index );
226         DALI_PRINT_RENDER_ITEM( item );
227         item.mRenderer->Render( context, textureCache, bufferIndex, *item.mNode, defaultShader,
228                                 item.mModelMatrix, item.mModelViewMatrix, viewMatrix, projectionMatrix, item.mSize, !item.mIsOpaque );
229       }
230     }
231   }
232   else
233   {
234     size_t count = renderList.Count();
235     for ( size_t index = 0; index < count; ++index )
236     {
237       const RenderItem& item = renderList.GetItem( index );
238       DALI_PRINT_RENDER_ITEM( item );
239
240       item.mRenderer->Render( context, textureCache, bufferIndex, *item.mNode, defaultShader,
241                               item.mModelMatrix, item.mModelViewMatrix, viewMatrix, projectionMatrix, item.mSize, !item.mIsOpaque );
242     }
243
244   }
245 }
246
247 void ProcessRenderInstruction( const RenderInstruction& instruction,
248                                Context& context,
249                                SceneGraph::TextureCache& textureCache,
250                                SceneGraph::Shader& defaultShader,
251                                BufferIndex bufferIndex )
252 {
253   DALI_PRINT_RENDER_INSTRUCTION( instruction, bufferIndex );
254
255   const Matrix* viewMatrix       = instruction.GetViewMatrix( bufferIndex );
256   const Matrix* projectionMatrix = instruction.GetProjectionMatrix( bufferIndex );
257
258   DALI_ASSERT_DEBUG( NULL != viewMatrix );
259   DALI_ASSERT_DEBUG( NULL != projectionMatrix );
260
261   if( NULL != viewMatrix &&
262       NULL != projectionMatrix )
263   {
264     const RenderListContainer::SizeType count = instruction.RenderListCount();
265
266     // Iterate through each render list in order. If a pair of render lists
267     // are marked as interleaved, then process them together.
268     for( RenderListContainer::SizeType index = 0; index < count; ++index )
269     {
270       const RenderList* renderList = instruction.GetRenderList( index );
271
272       if(  renderList &&
273           !renderList->IsEmpty() )
274       {
275         ProcessRenderList( *renderList, context, textureCache, defaultShader, bufferIndex, *viewMatrix, *projectionMatrix );
276       }
277     }
278   }
279 }
280
281 } // namespace Render
282
283 } // namespace Internal
284
285 } // namespace Dali