Changed depth sorting algorithm.
[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/scene-graph-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  * Sets up the scissor test if required.
44  * @param[in] renderList The render list from which to get the clipping flag
45  * @param[in] context The context
46  */
47 inline void SetScissorTest( const RenderList& renderList, Context& context )
48 {
49   // Scissor testing
50   if( renderList.IsClipping() )
51   {
52     context.SetScissorTest( true );
53
54     const Dali::ClippingBox& clip = renderList.GetClippingBox();
55     context.Scissor(clip.x, clip.y, clip.width, clip.height);
56   }
57   else
58   {
59     context.SetScissorTest( false );
60   }
61 }
62
63 /**
64  * Sets the render flags for depth testing and stencil buffer
65  *
66  * @param[in] renderList The render list from which to get the render flags
67  * @param[in] context The context
68  */
69 inline void SetRenderFlags( const RenderList& renderList, Context& context )
70 {
71   const unsigned int renderFlags = renderList.GetFlags();
72
73   bool enableDepthBuffer = ( ( renderFlags & RenderList::DEPTH_BUFFER_ENABLED ) != 0u );
74   bool depthMask         = ( ( renderFlags & RenderList::DEPTH_WRITE ) != 0u );
75
76   GLbitfield clearMask   = ( renderFlags & RenderList::DEPTH_CLEAR ) ? GL_DEPTH_BUFFER_BIT : 0u;
77
78   context.EnableDepthBuffer( enableDepthBuffer );
79   context.DepthMask( depthMask );
80
81   // Stencil enabled, writing, and clearing...
82   const bool enableStencilBuffer( renderFlags & RenderList::STENCIL_BUFFER_ENABLED );
83   const bool enableStencilWrite( renderFlags & RenderList::STENCIL_WRITE );
84
85   context.EnableStencilBuffer( enableStencilBuffer );
86
87   if( enableStencilBuffer )
88   {
89     context.StencilFunc( (enableStencilWrite ? GL_ALWAYS : GL_EQUAL), 1, 0xFF );
90     context.StencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
91
92     clearMask |= (renderFlags & RenderList::STENCIL_CLEAR) ? GL_STENCIL_BUFFER_BIT : 0u;
93   }
94
95   // Write to stencil buffer or color buffer, but not both
96   context.StencilMask( enableStencilWrite ? 0xFF : 0x00 );
97   context.ColorMask( !enableStencilWrite );
98
99   // Clear depth and/or stencil buffer.
100   if( clearMask )
101   {
102     // only clear if the depth and/or stencil buffer have been written to after a previous clear
103     context.Clear( clearMask, Context::CHECK_CACHED_VALUES );
104   }
105 }
106
107
108 /**
109  * Process a render-list.
110  * @param[in] renderList The render-list to process.
111  * @param[in] context The GL context.
112  * @param[in] defaultShader The default shader to use.
113  * @param[in] buffer The current render buffer index (previous update buffer)
114  * @param[in] frameTime The elapsed time between the last two updates.
115  * @param[in] viewMatrix The view matrix from the appropriate camera.
116  * @param[in] projectionMatrix The projection matrix from the appropriate camera.
117  * @param[in] cullMode True if the renderers should be subjected to clipspace culling
118  */
119 inline void ProcessRenderList(
120   const RenderList& renderList,
121   Context& context,
122   SceneGraph::TextureCache& textureCache,
123   SceneGraph::Shader& defaultShader,
124   BufferIndex bufferIndex,
125   float frameTime,
126   const Matrix& viewMatrix,
127   const Matrix& projectionMatrix,
128   bool cullMode )
129 {
130   DALI_PRINT_RENDER_LIST( renderList );
131
132   SetScissorTest( renderList, context );
133   SetRenderFlags( renderList, context );
134
135   size_t count = renderList.Count();
136   for ( size_t index = 0; index < count; ++index )
137   {
138     const RenderItem& item = renderList.GetItem( index );
139
140     DALI_PRINT_RENDER_ITEM( item );
141
142     SceneGraph::Renderer* renderer = const_cast< SceneGraph::Renderer* >( item.GetRenderer() );
143     const Matrix& modelViewMatrix = item.GetModelViewMatrix();
144
145     renderer->Render( context, textureCache, bufferIndex, defaultShader, modelViewMatrix, viewMatrix, projectionMatrix, frameTime, cullMode );
146   }
147 }
148
149 /**
150  * Render items from the currentIndex until the depth index changes.
151  * Leaves currentIndex pointing at the
152  *
153  * @param[in] renderList The render-list to process.
154  * @param[in] context The GL context.
155  * @param[in] defaultShader The default shader to use.
156  * @param[in] buffer The current render buffer index (previous update buffer)
157  * @param[in] frameTime The elapsed time between the last two updates.
158  * @param[in] viewMatrix The view matrix from the appropriate camera.
159  * @param[in] projectionMatrix The projection matrix from the appropriate camera.
160  * @param[in] cullMode True if the renderers should be subjected to clipspace culling
161  * @param[in] depthIndex The current depth index
162  * @param[inout] currentIndex On entry, the index in the render list of the first item at the given depth index. On exit, the index of the first item at the next depth index.
163  */
164 inline void RenderItemsAtDepthIndex(
165   const RenderList&         renderList,
166   Context&                  context,
167   SceneGraph::TextureCache& textureCache,
168   SceneGraph::Shader&       defaultShader,
169   BufferIndex               bufferIndex,
170   float                     frameTime,
171   const Matrix&             viewMatrix,
172   const Matrix&             projectionMatrix,
173   bool                      cullMode,
174   int                       depthIndex,
175   size_t&                   currentIndex ) // Out parameter
176 {
177   const size_t count = renderList.Count();
178
179   // Don't initialise currentIndex. Ever.
180   for( ; currentIndex < count ; currentIndex++ )
181   {
182     const RenderItem& renderItem = renderList.GetItem( currentIndex );
183     DALI_PRINT_RENDER_ITEM( renderItem );
184
185     if( renderItem.GetDepthIndex() == depthIndex )
186     {
187       SceneGraph::Renderer* renderer = const_cast< SceneGraph::Renderer* >( renderItem.GetRenderer() );
188       const Matrix& modelViewMatrix = renderItem.GetModelViewMatrix();
189       renderer->Render( context, textureCache, bufferIndex, defaultShader, modelViewMatrix, viewMatrix, projectionMatrix, frameTime, cullMode );
190
191     }
192     else
193     {
194       break; // Stop iterating when we reach a new depth index
195     }
196   }
197 }
198
199
200 /**
201  * Process two interleaved render-lists.
202  *
203  * For each depth index, it will set the flags for the first list,
204  * render items in the first list, set flags for the second list and
205  * render items from the second list.
206  *
207  * @param[in] renderList1 The first render-list to process.
208  * @param[in] renderList2 The second render-list to process.
209  * @param[in] context The GL context.
210  * @param[in] defaultShader The default shader to use.
211  * @param[in] buffer The current render buffer index (previous update buffer)
212  * @param[in] frameTime The elapsed time between the last two updates.
213  * @param[in] viewMatrix The view matrix from the appropriate camera.
214  * @param[in] projectionMatrix The projection matrix from the appropriate camera.
215  * @param[in] cullMode True if the renderers should be subjected to clipspace culling
216  */
217
218 inline void ProcessInterleavedRenderLists(
219   const RenderList&         renderList1,
220   const RenderList&         renderList2,
221   Context&                  context,
222   SceneGraph::TextureCache& textureCache,
223   SceneGraph::Shader&       defaultShader,
224   BufferIndex               bufferIndex,
225   float                     frameTime,
226   const Matrix&             viewMatrix,
227   const Matrix&             projectionMatrix,
228   bool                      cullMode )
229 {
230
231   SetScissorTest( renderList1, context ); // Scissor settings are identical for both lists
232   size_t count1 = renderList1.Count();
233   size_t count2 = renderList2.Count();
234   size_t index1 = 0;
235   size_t index2 = 0;
236
237   int depthIndex=renderList1.GetItem( 0 ).GetDepthIndex();
238
239   while( index1 < count1 || index2 < count2 )
240   {
241     if( index1 < count1 && index2 < count2 )
242     {
243       // Take the lowest depth index in both lists
244       depthIndex = std::min( renderList1.GetItem( index1 ).GetDepthIndex(),
245                              renderList2.GetItem( index2 ).GetDepthIndex() );
246     }
247     else if( index1 < count1 )
248     {
249       // Items left only in list 1
250       depthIndex = renderList1.GetItem( index1 ).GetDepthIndex();
251     }
252     else // index2 < count2
253     {
254       // Items left only in list 2
255       depthIndex = renderList2.GetItem( index2 ).GetDepthIndex();
256     }
257
258     // Between each successive depth index, reset the flags.
259     SetRenderFlags( renderList1, context );
260
261     // Find and render items in the first list that correspond to the current depth index
262     if( index1 < count1 )
263     {
264       RenderItemsAtDepthIndex( renderList1, context, textureCache, defaultShader,
265                                bufferIndex, frameTime, viewMatrix, projectionMatrix,
266                                cullMode, depthIndex,
267                                index1 ); // Out parameter
268     }
269
270     SetRenderFlags( renderList2, context );
271     if( index2 < count2 )
272     {
273       RenderItemsAtDepthIndex( renderList2, context, textureCache, defaultShader,
274                                bufferIndex, frameTime, viewMatrix, projectionMatrix,
275                                cullMode, depthIndex,
276                                index2 ); // Out parameter
277     }
278   }
279 }
280
281
282 void ProcessRenderInstruction( const RenderInstruction& instruction,
283                                Context& context,
284                                SceneGraph::TextureCache& textureCache,
285                                SceneGraph::Shader& defaultShader,
286                                BufferIndex bufferIndex,
287                                float frameTime )
288 {
289   DALI_PRINT_RENDER_INSTRUCTION( instruction, bufferIndex );
290
291   const Matrix* viewMatrix       = instruction.GetViewMatrix( bufferIndex );
292   const Matrix* projectionMatrix = instruction.GetProjectionMatrix( bufferIndex );
293
294   DALI_ASSERT_DEBUG( NULL != viewMatrix );
295   DALI_ASSERT_DEBUG( NULL != projectionMatrix );
296
297   if( NULL != viewMatrix &&
298       NULL != projectionMatrix )
299   {
300     const RenderListContainer::SizeType count = instruction.RenderListCount();
301
302     // Iterate through each render list in order. If a pair of render lists
303     // are marked as interleaved, then process them together.
304     for( RenderListContainer::SizeType index = 0; index < count; ++index )
305     {
306       const RenderList* renderList = instruction.GetRenderList( index );
307
308       if(  renderList &&
309           !renderList->IsEmpty() )
310       {
311         if( renderList->GetInterleave() &&
312             index < count-1 &&
313             instruction.GetRenderList(index+1)->GetInterleave() )
314         {
315           ProcessInterleavedRenderLists( *renderList,
316                                          *(instruction.GetRenderList(index+1)),
317                                          context,
318                                          textureCache,
319                                          defaultShader,
320                                          bufferIndex,
321                                          frameTime,
322                                          *viewMatrix,
323                                          *projectionMatrix,
324                                          instruction.mCullMode );
325           index++; // Skip over next render list
326         }
327         else
328         {
329           ProcessRenderList( *renderList, context, textureCache, defaultShader, bufferIndex, frameTime, *viewMatrix, *projectionMatrix, instruction.mCullMode );
330         }
331       }
332     }
333   }
334 }
335
336 } // namespace Render
337
338 } // namespace Internal
339
340 } // namespace Dali