Changed drawing order for 2D and 3D layers
[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
75   GLbitfield clearMask   = ( renderFlags & RenderList::DEPTH_CLEAR ) ? GL_DEPTH_BUFFER_BIT : 0u;
76
77   context.EnableDepthBuffer( enableDepthBuffer );
78
79   // Stencil enabled, writing, and clearing...
80   const bool enableStencilBuffer( renderFlags & RenderList::STENCIL_BUFFER_ENABLED );
81   const bool enableStencilWrite( renderFlags & RenderList::STENCIL_WRITE );
82
83   context.EnableStencilBuffer( enableStencilBuffer );
84
85   if( enableStencilBuffer )
86   {
87     context.StencilFunc( (enableStencilWrite ? GL_ALWAYS : GL_EQUAL), 1, 0xFF );
88     context.StencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
89
90     clearMask |= (renderFlags & RenderList::STENCIL_CLEAR) ? GL_STENCIL_BUFFER_BIT : 0u;
91   }
92
93   // Write to stencil buffer or color buffer, but not both
94   context.StencilMask( enableStencilWrite ? 0xFF : 0x00 );
95   context.ColorMask( !enableStencilWrite );
96
97   // Clear depth and/or stencil buffer.
98   if( clearMask )
99   {
100     // only clear if the depth and/or stencil buffer have been written to after a previous clear
101     context.Clear( clearMask, Context::CHECK_CACHED_VALUES );
102   }
103 }
104
105
106 /**
107  * Process a render-list.
108  * @param[in] renderList The render-list to process.
109  * @param[in] context The GL context.
110  * @param[in] defaultShader The default shader to use.
111  * @param[in] buffer The current render buffer index (previous update buffer)
112  * @param[in] frameTime The elapsed time between the last two updates.
113  * @param[in] viewMatrix The view matrix from the appropriate camera.
114  * @param[in] projectionMatrix The projection matrix from the appropriate camera.
115  * @param[in] cullMode True if the renderers should be subjected to clipspace culling
116  */
117 inline void ProcessRenderList(
118   const RenderList& renderList,
119   Context& context,
120   SceneGraph::TextureCache& textureCache,
121   SceneGraph::Shader& defaultShader,
122   BufferIndex bufferIndex,
123   float frameTime,
124   const Matrix& viewMatrix,
125   const Matrix& projectionMatrix,
126   bool cullMode )
127 {
128   DALI_PRINT_RENDER_LIST( renderList );
129
130   SetScissorTest( renderList, context );
131   SetRenderFlags( renderList, context );
132
133   if( renderList.HasColorRenderItems() )
134   {
135     bool depthBufferEnabled = ( ( renderList.GetFlags() & RenderList::DEPTH_BUFFER_ENABLED ) != 0u );
136     size_t count = renderList.Count();
137     for ( size_t index = 0; index < count; ++index )
138     {
139       const RenderItem& item = renderList.GetItem( index );
140       DALI_PRINT_RENDER_ITEM( item );
141
142       //Enable depth writes if depth buffer is enabled and item is opaque
143       context.DepthMask( depthBufferEnabled && item.IsOpaque() );
144
145       SceneGraph::Renderer* renderer = const_cast< SceneGraph::Renderer* >( item.GetRenderer() );
146       renderer->Render( context, textureCache, bufferIndex, defaultShader, item.GetModelViewMatrix(), viewMatrix, projectionMatrix, frameTime, cullMode );
147     }
148   }
149   else
150   {
151     size_t count = renderList.Count();
152     for ( size_t index = 0; index < count; ++index )
153     {
154       const RenderItem& item = renderList.GetItem( index );
155       DALI_PRINT_RENDER_ITEM( item );
156
157       SceneGraph::Renderer* renderer = const_cast< SceneGraph::Renderer* >( item.GetRenderer() );
158       renderer->Render( context, textureCache, bufferIndex, defaultShader, item.GetModelViewMatrix(), viewMatrix, projectionMatrix, frameTime, cullMode );
159     }
160
161   }
162 }
163
164 /**
165  * Render items from the currentIndex until the depth index changes.
166  * Leaves currentIndex pointing at the
167  *
168  * @param[in] renderList The render-list to process.
169  * @param[in] context The GL context.
170  * @param[in] defaultShader The default shader to use.
171  * @param[in] buffer The current render buffer index (previous update buffer)
172  * @param[in] frameTime The elapsed time between the last two updates.
173  * @param[in] viewMatrix The view matrix from the appropriate camera.
174  * @param[in] projectionMatrix The projection matrix from the appropriate camera.
175  * @param[in] cullMode True if the renderers should be subjected to clipspace culling
176  * @param[in] depthIndex The current depth index
177  * @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.
178  */
179 inline void RenderItemsAtDepthIndex(
180   const RenderList&         renderList,
181   Context&                  context,
182   SceneGraph::TextureCache& textureCache,
183   SceneGraph::Shader&       defaultShader,
184   BufferIndex               bufferIndex,
185   float                     frameTime,
186   const Matrix&             viewMatrix,
187   const Matrix&             projectionMatrix,
188   bool                      cullMode,
189   int                       depthIndex,
190   size_t&                   currentIndex ) // Out parameter
191 {
192   const size_t count = renderList.Count();
193
194   // Don't initialise currentIndex. Ever.
195   for( ; currentIndex < count ; currentIndex++ )
196   {
197     const RenderItem& renderItem = renderList.GetItem( currentIndex );
198     DALI_PRINT_RENDER_ITEM( renderItem );
199
200     if( renderItem.GetDepthIndex() == depthIndex )
201     {
202       SceneGraph::Renderer* renderer = const_cast< SceneGraph::Renderer* >( renderItem.GetRenderer() );
203       const Matrix& modelViewMatrix = renderItem.GetModelViewMatrix();
204       renderer->Render( context, textureCache, bufferIndex, defaultShader, modelViewMatrix, viewMatrix, projectionMatrix, frameTime, cullMode );
205
206     }
207     else
208     {
209       break; // Stop iterating when we reach a new depth index
210     }
211   }
212 }
213
214
215
216 void ProcessRenderInstruction( const RenderInstruction& instruction,
217                                Context& context,
218                                SceneGraph::TextureCache& textureCache,
219                                SceneGraph::Shader& defaultShader,
220                                BufferIndex bufferIndex,
221                                float frameTime )
222 {
223   DALI_PRINT_RENDER_INSTRUCTION( instruction, bufferIndex );
224
225   const Matrix* viewMatrix       = instruction.GetViewMatrix( bufferIndex );
226   const Matrix* projectionMatrix = instruction.GetProjectionMatrix( bufferIndex );
227
228   DALI_ASSERT_DEBUG( NULL != viewMatrix );
229   DALI_ASSERT_DEBUG( NULL != projectionMatrix );
230
231   if( NULL != viewMatrix &&
232       NULL != projectionMatrix )
233   {
234     const RenderListContainer::SizeType count = instruction.RenderListCount();
235
236     // Iterate through each render list in order. If a pair of render lists
237     // are marked as interleaved, then process them together.
238     for( RenderListContainer::SizeType index = 0; index < count; ++index )
239     {
240       const RenderList* renderList = instruction.GetRenderList( index );
241
242       if(  renderList &&
243           !renderList->IsEmpty() )
244       {
245           ProcessRenderList( *renderList, context, textureCache, defaultShader, bufferIndex, frameTime, *viewMatrix, *projectionMatrix, instruction.mCullMode );
246       }
247     }
248   }
249 }
250
251 } // namespace Render
252
253 } // namespace Internal
254
255 } // namespace Dali