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