Revert "License conversion from Flora to Apache 2.0"
[platform/core/uifw/dali-core.git] / dali / internal / update / manager / prepare-render-instructions.cpp
1 //
2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Flora License, Version 1.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://floralicense.org/license/
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 // CLASS HEADER
18 #include <dali/internal/update/manager/prepare-render-instructions.h>
19
20 // INTERNAL INCLUDES
21 #include <dali/internal/event/actors/layer-impl.h> // for the default sorting function
22 #include <dali/internal/update/resources/resource-manager-declarations.h>
23 #include <dali/internal/update/manager/sorted-layers.h>
24 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
25 #include <dali/internal/update/node-attachments/scene-graph-renderable-attachment.h>
26 #include <dali/internal/update/nodes/scene-graph-layer.h>
27 #include <dali/internal/render/common/render-item.h>
28 #include <dali/internal/render/common/render-tracker.h>
29 #include <dali/internal/render/common/render-instruction.h>
30 #include <dali/internal/render/common/render-instruction-container.h>
31 #include <dali/internal/render/renderers/scene-graph-renderer.h>
32
33 namespace Dali
34 {
35
36 namespace Internal
37 {
38
39 namespace SceneGraph
40 {
41
42 /**
43  * Set flags for opaque renderlist
44  * @param renderList to set the flags to
45  * @param transparentRenderersExist is true if there is transparent renderers in this layer
46  * @param stencilRenderablesExist is true if there are stencil renderers on this layer
47  * @param depthTestDisabled whether depth test is disabled.
48  */
49 inline void SetOpaqueRenderFlags( RenderList& renderList, bool transparentRenderersExist, bool stencilRenderablesExist, bool depthTestDisabled )
50 {
51   // Special optimization if depth test is disabled or if only one opaque rendered in the layer (for example background image)
52   // and this renderer does not need depth test against itself (for example a mesh actor)
53   // if this layer has got exactly one opaque renderer
54   // and this renderer is not interested in depth testing
55   // (i.e. is an image or text and not a model)
56   if ( ( (  renderList.Count() == 1 ) &&
57          (  !transparentRenderersExist ) &&
58          (  !renderList.GetRenderer( 0 )->RequiresDepthTest() ) ) ||
59        depthTestDisabled )
60   {
61     // no need to enable depth test or clear depth buffer
62     // if there's something transparent already rendered by previous layers,
63     // this opaque renderer will correctly draw on top of them since no depth test
64     renderList.ClearFlags();
65   }
66   else
67   {
68     // Prepare for rendering multiple opaque objects
69     unsigned int flags = RenderList::DEPTH_TEST | RenderList::DEPTH_WRITE | RenderList::DEPTH_CLEAR; // clear depth buffer, draw over the previously rendered layers;
70
71     renderList.ClearFlags();
72     renderList.SetFlags(flags);
73   }
74
75   if( stencilRenderablesExist )
76   {
77     renderList.SetFlags( RenderList::STENCIL_TEST );
78   }
79 }
80
81 /**
82  * Set the transparent flags on the renderlist
83  * @param renderList to set the flags on
84  * @param opaqueRenderersExist is true if there are opaque renderers on this layer
85  * @param stencilRenderablesExist is true if there are stencil renderers on this layer
86  * @param depthTestDisabled whether depth test is disabled.
87  */
88 inline void SetTransparentRenderFlags( RenderList& renderList, bool opaqueRenderersExist, bool stencilRenderablesExist, bool depthTestDisabled )
89 {
90   renderList.ClearFlags();
91   // We don't need to write to the depth buffer, as transparent objects
92   // don't obscure each other.
93
94   if ( opaqueRenderersExist && !depthTestDisabled )
95   {
96     // If there are a mix of opaque and transparent objects, the transparent
97     // objects should be rendered with depth test on to avoid background objects
98     // appearing in front of opaque foreground objects.
99
100     renderList.SetFlags( RenderList::DEPTH_TEST );
101   }
102
103   if( stencilRenderablesExist )
104   {
105     renderList.SetFlags( RenderList::STENCIL_TEST );
106   }
107 }
108
109
110 /**
111  * Set flags for overlay renderlist
112  * @param renderList to set the flags for
113  * @param stencilRenderablesExist is true if there are stencil renderers on this layer
114  */
115 inline void SetOverlayRenderFlags( RenderList& renderList, bool stencilRenderablesExist )
116 {
117   if(stencilRenderablesExist)
118   {
119     renderList.SetFlags(RenderList::STENCIL_TEST);
120   }
121 }
122
123 /**
124  * Set flags for stencil renderlist
125  * @param renderList to set the flags for
126  */
127 inline void SetStencilRenderFlags( RenderList& renderList )
128 {
129   renderList.ClearFlags();
130   renderList.SetFlags(RenderList::STENCIL_CLEAR | RenderList::STENCIL_WRITE | RenderList::STENCIL_TEST);
131 }
132
133 /**
134  * Add a renderer to the list
135  * @param updateBufferIndex to read the model matrix from
136  * @param renderList to add the item to
137  * @param renderable attachment
138  * @param viewMatrix used to calculate modelview matrix for the item
139  */
140 inline void AddRendererToRenderList( BufferIndex updateBufferIndex,
141                                      RenderList& renderList,
142                                      RenderableAttachment& renderable,
143                                      const Matrix& viewMatrix )
144 {
145   const Renderer& renderer = renderable.GetRenderer();
146
147   // Get the next free RenderItem
148   RenderItem& item = renderList.GetNextFreeItem();
149   item.SetRenderer( const_cast< Renderer* >( &renderer ) );
150
151   // calculate MV matrix onto the item
152   Matrix& modelViewMatrix = item.GetModelViewMatrix();
153   const Matrix& worldMatrix = renderable.GetParent().GetWorldMatrix( updateBufferIndex );
154
155   Matrix::Multiply( modelViewMatrix, worldMatrix, viewMatrix );
156 }
157
158 /**
159  * Add all renderers to the list
160  * @param updateBufferIndex to read the model matrix from
161  * @param renderList to add the items to
162  * @param renderable attachments
163  * @param viewMatrix used to calculate modelview matrix for the items
164  */
165 inline void AddRenderersToRenderList( BufferIndex updateBufferIndex,
166                                       RenderList& renderList,
167                                       RenderableAttachmentContainer& attachments,
168                                       const Matrix& viewMatrix )
169 {
170   // Add renderer for each attachment
171   const RenderableAttachmentIter endIter = attachments.end();
172   for ( RenderableAttachmentIter iter = attachments.begin(); iter != endIter; ++iter )
173   {
174     RenderableAttachment& attachment = **iter;
175     AddRendererToRenderList( updateBufferIndex, renderList, attachment, viewMatrix );
176   }
177 }
178
179 /**
180  * Try to reuse cached renderitems from the renderlist
181  * This avoids recalculating the model view matrices in case this part of the scene was static
182  * An example case is a toolbar layer that rarely changes or a popup on top of the rest of the stage
183  * @param layer that is being processed
184  * @param renderList that is cached from frame N-1
185  * @param attachmentList that is being used
186  */
187 inline bool TryReuseCachedRenderers( Layer& layer,
188                                      RenderList& renderList,
189                                      RenderableAttachmentContainer& attachmentList )
190 {
191   bool retValue = false;
192   size_t renderableCount = attachmentList.size();
193   // check that the cached list originates from this layer and that the counts match
194   if( ( renderList.GetSourceLayer() == &layer )&&
195       ( renderList.GetCachedItemCount() == renderableCount ) )
196   {
197     // check that all the same renderers are there. This gives us additional security in avoiding rendering the wrong attachments
198     // Attachments are not sorted, but render list is so at this stage renderers may be in different order
199     // therefore we check a combined sum of all renderer addresses
200     size_t checkSumNew = 0;
201     size_t checkSumOld = 0;
202     for( size_t index = 0; index < renderableCount; ++index )
203     {
204       RenderableAttachment* attachment = attachmentList[ index ];
205       const Renderer& renderer = attachment->GetRenderer();
206       checkSumNew += size_t( &renderer );
207       checkSumOld += size_t( renderList.GetRenderer( index ) );
208     }
209     if( checkSumNew == checkSumOld )
210     {
211       // tell list to reuse its existing items
212       renderList.ReuseCachedItems();
213       retValue = true;
214     }
215   }
216   return retValue;
217 }
218
219 /**
220  * Add opaque renderers from the layer onto the next free render list
221  * @param updateBufferIndex to use
222  * @param layer to get the renderers from
223  * @param viewmatrix for the camera from rendertask
224  * @param transparentRenderersExist is true if there is transparent renderers in this layer
225  * @param stencilRenderablesExist is true if there are stencil renderers on this layer
226  * @param instruction to fill in
227  * @param tryReuseRenderList whether to try to reuse the cached items from the instruction
228  */
229 inline void AddOpaqueRenderers( BufferIndex updateBufferIndex,
230                                 Layer& layer,
231                                 const Matrix& viewMatrix,
232                                 bool transparentRenderablesExist,
233                                 bool stencilRenderablesExist,
234                                 RenderInstruction& instruction,
235                                 bool tryReuseRenderList )
236 {
237   RenderList& opaqueRenderList = instruction.GetNextFreeRenderList( layer.opaqueRenderables.size() );
238   opaqueRenderList.SetClipping( layer.IsClipping(), layer.GetClippingBox() );
239
240   // try to reuse cached renderitems from last time around
241   if( tryReuseRenderList )
242   {
243     if( TryReuseCachedRenderers( layer, opaqueRenderList, layer.opaqueRenderables ) )
244     {
245       // reset the flags as other layers might have changed
246       // opaque flags can only be set after renderers are added
247       SetOpaqueRenderFlags(opaqueRenderList, transparentRenderablesExist, stencilRenderablesExist, layer.IsDepthTestDisabled() );
248       return;
249     }
250   }
251   AddRenderersToRenderList( updateBufferIndex, opaqueRenderList, layer.opaqueRenderables, viewMatrix );
252
253   // opaque flags can only be set after renderers are added
254   SetOpaqueRenderFlags(opaqueRenderList, transparentRenderablesExist, stencilRenderablesExist, layer.IsDepthTestDisabled() );
255 }
256
257 /**
258  * Function which sorts based on the calculated depth values ordering them back to front
259  * @param lhs item
260  * @param rhs item
261  * @return true if left item is greater than right
262  */
263 bool SortByDepthSortValue( const RendererWithSortValue& lhs, const RendererWithSortValue& rhs )
264 {
265   return lhs.first > rhs.first;
266 }
267
268 /**
269  * Sort transparent render items
270  * @param transparentRenderList to sort
271  * @param layer where the renderers are from
272  * @param sortingHelper to use for sorting the renderitems (to avoid reallocating)
273  */
274 inline void SortTransparentRenderItems( RenderList& transparentRenderList, Layer& layer, RendererSortingHelper& sortingHelper )
275 {
276   const size_t renderableCount = transparentRenderList.Count();
277   // reserve space if needed
278   const unsigned int oldcapacity = sortingHelper.size();
279   if( oldcapacity < renderableCount )
280   {
281     sortingHelper.reserve( renderableCount );
282     // add real objects (reserve does not construct objects)
283     sortingHelper.insert( sortingHelper.begin() + oldcapacity,
284                           (renderableCount - oldcapacity),
285                           RendererWithSortValue( 0.0f, NULL ) );
286   }
287   else
288   {
289     // clear extra elements from helper, does not decrease capability
290     sortingHelper.resize( renderableCount );
291   }
292   // calculate the sorting value, once per item by calling the layers sort function
293   // Using an if and two for-loops rather than if inside for as its better for branch prediction
294   if( layer.UsesDefaultSortFunction() )
295   {
296     for( size_t index = 0; index < renderableCount; ++index )
297     {
298       RenderItem& item = transparentRenderList.GetItem( index );
299       // the default sorting function should get inlined here
300       sortingHelper[ index ].first = Internal::Layer::ZValue(
301           item.GetModelViewMatrix().GetTranslation3(),
302           layer.transparentRenderables[ index ]->GetSortModifier() );
303       // keep the renderitem pointer in the helper so we can quickly reorder items after sort
304       sortingHelper[ index ].second = &item;
305     }
306   }
307   else
308   {
309     const Dali::Layer::SortFunctionType sortFunction = layer.GetSortFunction();
310     for( size_t index = 0; index < renderableCount; ++index )
311     {
312       RenderItem& item = transparentRenderList.GetItem( index );
313       sortingHelper[ index ].first = (*sortFunction)(
314           item.GetModelViewMatrix().GetTranslation3(),
315           layer.transparentRenderables[ index ]->GetSortModifier() );
316       // keep the renderitem pointer in the helper so we can quickly reorder items after sort
317       sortingHelper[ index ].second = &item;
318     }
319   }
320
321   // sort the renderers back to front, Z Axis point from near plane to far plane
322   std::sort( sortingHelper.begin(), sortingHelper.end(), SortByDepthSortValue );
323
324   // reorder/repopulate the renderitems in renderlist to correct order based on sortinghelper
325   RenderItemContainer::Iterator renderListIter = transparentRenderList.GetContainer().Begin();
326   for( unsigned int index = 0; index < renderableCount; ++index, ++renderListIter )
327   {
328     *renderListIter = sortingHelper[ index ].second;
329   }
330 }
331
332 /**
333  * Add transparent renderers from the layer onto the next free render list
334  * @param updateBufferIndex to use
335  * @param layer to get the renderers from
336  * @param viewmatrix for the camera from rendertask
337  * @param opaqueRenderablesExist is true if there are opaque renderers on this layer
338  * @param stencilRenderablesExist is true if there are stencil renderers on this layer
339  * @param instruction to fill in
340  * @param sortingHelper to use for sorting the renderitems (to avoid reallocating)
341  * @param tryReuseRenderList whether to try to reuse the cached items from the instruction
342  */
343 inline void AddTransparentRenderers( BufferIndex updateBufferIndex,
344                                      Layer& layer,
345                                      const Matrix& viewMatrix,
346                                      bool opaqueRenderablesExist,
347                                      bool stencilRenderablesExist,
348                                      RenderInstruction& instruction,
349                                      RendererSortingHelper& sortingHelper,
350                                      bool tryReuseRenderList )
351 {
352   const size_t renderableCount = layer.transparentRenderables.size();
353   RenderList& transparentRenderList = instruction.GetNextFreeRenderList( renderableCount );
354   transparentRenderList.SetClipping( layer.IsClipping(), layer.GetClippingBox() );
355   // transparent flags are independent of the amount of transparent renderers
356   SetTransparentRenderFlags( transparentRenderList, opaqueRenderablesExist, stencilRenderablesExist, layer.IsDepthTestDisabled() );
357
358   // try to reuse cached renderitems from last time around
359   if( tryReuseRenderList )
360   {
361     if( TryReuseCachedRenderers( layer, transparentRenderList, layer.transparentRenderables ) )
362     {
363       return;
364     }
365   }
366   transparentRenderList.SetSourceLayer( &layer );
367
368   AddRenderersToRenderList( updateBufferIndex, transparentRenderList, layer.transparentRenderables, viewMatrix );
369
370   // sorting is only needed if more than 1 item
371   if( renderableCount > 1 )
372   {
373     SortTransparentRenderItems( transparentRenderList, layer, sortingHelper );
374   }
375 }
376
377 /**
378  * Add overlay renderers from the layer onto the next free render list
379  * @param updateBufferIndex to use
380  * @param layer to get the renderers from
381  * @param viewmatrix for the camera from rendertask
382  * @param stencilRenderablesExist is true if there are stencil renderers on this layer
383  * @param instruction to fill in
384  * @param tryReuseRenderList whether to try to reuse the cached items from the instruction
385  */
386 inline void AddOverlayRenderers( BufferIndex updateBufferIndex,
387                                  Layer& layer,
388                                  const Matrix& viewMatrix,
389                                  bool stencilRenderablesExist,
390                                  RenderInstruction& instruction,
391                                  bool tryReuseRenderList )
392 {
393   RenderList& overlayRenderList = instruction.GetNextFreeRenderList( layer.overlayRenderables.size() );
394   overlayRenderList.SetClipping( layer.IsClipping(), layer.GetClippingBox() );
395   SetOverlayRenderFlags( overlayRenderList, stencilRenderablesExist );
396
397   // try to reuse cached renderitems from last time around
398   if( tryReuseRenderList )
399   {
400     if( TryReuseCachedRenderers( layer, overlayRenderList, layer.overlayRenderables ) )
401     {
402       return;
403     }
404   }
405   AddRenderersToRenderList( updateBufferIndex, overlayRenderList, layer.overlayRenderables, viewMatrix );
406 }
407
408 /**
409  * Add stencil renderers from the layer onto the next free render list
410  * @param updateBufferIndex to use
411  * @param layer to get the renderers from
412  * @param viewmatrix for the camera from rendertask
413  * @param instruction to fill in
414  * @param tryReuseRenderList whether to try to reuse the cached items from the instruction
415  */
416 inline void AddStencilRenderers( BufferIndex updateBufferIndex,
417                                  Layer& layer,
418                                  const Matrix& viewMatrix,
419                                  RenderInstruction& instruction,
420                                  bool tryReuseRenderList )
421 {
422   RenderList& stencilRenderList = instruction.GetNextFreeRenderList( layer.stencilRenderables.size() );
423   stencilRenderList.SetClipping( layer.IsClipping(), layer.GetClippingBox() );
424   SetStencilRenderFlags( stencilRenderList );
425
426   // try to reuse cached renderitems from last time around
427   if( tryReuseRenderList )
428   {
429     if( TryReuseCachedRenderers( layer, stencilRenderList, layer.stencilRenderables ) )
430     {
431       return;
432     }
433   }
434   AddRenderersToRenderList( updateBufferIndex, stencilRenderList, layer.stencilRenderables, viewMatrix );
435 }
436
437 /**
438  * Prepare a single render instruction
439  * @param updateBufferIndex to use
440  * @param sortedLayers to prepare the instruction from
441  * @param renderTask to get the view matrix
442  * @param sortingHelper to use for sorting the renderitems (to avoid reallocating)
443  * @param renderTracker An optional render tracker object
444  * @param instructions container
445  */
446 void PrepareRenderInstruction( BufferIndex updateBufferIndex,
447                                SortedLayerPointers& sortedLayers,
448                                RenderTask& renderTask,
449                                RendererSortingHelper& sortingHelper,
450                                RenderTracker* renderTracker,
451                                RenderInstructionContainer& instructions )
452 {
453   // Retrieve the RenderInstruction buffer from the RenderInstructionContainer
454   // then populate with instructions.
455   RenderInstruction& instruction = instructions.GetNextInstruction( updateBufferIndex );
456   renderTask.PrepareRenderInstruction( instruction, updateBufferIndex );
457   bool viewMatrixHasNotChanged = !renderTask.ViewMatrixUpdated();
458
459   const Matrix& viewMatrix = renderTask.GetViewMatrix( updateBufferIndex );
460
461   const SortedLayersIter endIter = sortedLayers.end();
462   for ( SortedLayersIter iter = sortedLayers.begin(); iter != endIter; ++iter )
463   {
464     Layer& layer = **iter;
465
466     const bool stencilRenderablesExist( !layer.stencilRenderables.empty() );
467     const bool opaqueRenderablesExist( !layer.opaqueRenderables.empty() );
468     const bool transparentRenderablesExist( !layer.transparentRenderables.empty() );
469     const bool overlayRenderablesExist( !layer.overlayRenderables.empty() );
470     const bool tryReuseRenderList( layer.CanReuseRenderers() && viewMatrixHasNotChanged );
471
472     // Ignore stencils if there's nothing to test
473     if( stencilRenderablesExist &&
474         ( opaqueRenderablesExist || transparentRenderablesExist || overlayRenderablesExist ) )
475     {
476       AddStencilRenderers( updateBufferIndex, layer, viewMatrix, instruction, tryReuseRenderList );
477     }
478
479     if ( opaqueRenderablesExist )
480     {
481       AddOpaqueRenderers( updateBufferIndex,
482                           layer,
483                           viewMatrix,
484                           transparentRenderablesExist,
485                           stencilRenderablesExist,
486                           instruction,
487                           tryReuseRenderList );
488     }
489
490     if ( transparentRenderablesExist )
491     {
492       AddTransparentRenderers( updateBufferIndex,
493                                layer,
494                                viewMatrix,
495                                opaqueRenderablesExist,
496                                stencilRenderablesExist,
497                                instruction,
498                                sortingHelper,
499                                tryReuseRenderList );
500     }
501
502     if ( overlayRenderablesExist )
503     {
504       AddOverlayRenderers( updateBufferIndex, layer, viewMatrix, stencilRenderablesExist,
505                            instruction, tryReuseRenderList );
506     }
507   }
508
509   instruction.mRenderTracker = renderTracker;
510
511   // inform the render instruction that all renderers have been added and this frame is complete
512   instruction.UpdateCompleted();
513 }
514
515 } // SceneGraph
516
517 } // Internal
518
519 } // Dali