Merge "Allow multiple renderers per Actor and sharing renderers between actors" into...
[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  * 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       item.GetRenderer().Render( context, textureCache, bufferIndex, item.GetNode(), defaultShader, item.GetModelViewMatrix(), viewMatrix, projectionMatrix, frameTime, cullMode, !item.IsOpaque() );
146     }
147   }
148   else
149   {
150     size_t count = renderList.Count();
151     for ( size_t index = 0; index < count; ++index )
152     {
153       const RenderItem& item = renderList.GetItem( index );
154       DALI_PRINT_RENDER_ITEM( item );
155
156       item.GetRenderer().Render( context, textureCache, bufferIndex, item.GetNode(), defaultShader, item.GetModelViewMatrix(), viewMatrix, projectionMatrix, frameTime, cullMode, !item.IsOpaque() );
157     }
158
159   }
160 }
161
162 /**
163  * Render items from the currentIndex until the depth index changes.
164  * Leaves currentIndex pointing at the
165  *
166  * @param[in] renderList The render-list to process.
167  * @param[in] context The GL context.
168  * @param[in] defaultShader The default shader to use.
169  * @param[in] buffer The current render buffer index (previous update buffer)
170  * @param[in] frameTime The elapsed time between the last two updates.
171  * @param[in] viewMatrix The view matrix from the appropriate camera.
172  * @param[in] projectionMatrix The projection matrix from the appropriate camera.
173  * @param[in] cullMode True if the renderers should be subjected to clipspace culling
174  * @param[in] depthIndex The current depth index
175  * @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.
176  */
177 inline void RenderItemsAtDepthIndex(
178   const RenderList&         renderList,
179   Context&                  context,
180   SceneGraph::TextureCache& textureCache,
181   SceneGraph::Shader&       defaultShader,
182   BufferIndex               bufferIndex,
183   float                     frameTime,
184   const Matrix&             viewMatrix,
185   const Matrix&             projectionMatrix,
186   bool                      cullMode,
187   int                       depthIndex,
188   size_t&                   currentIndex ) // Out parameter
189 {
190   const size_t count = renderList.Count();
191
192   // Don't initialise currentIndex. Ever.
193   for( ; currentIndex < count ; currentIndex++ )
194   {
195     const RenderItem& renderItem = renderList.GetItem( currentIndex );
196     DALI_PRINT_RENDER_ITEM( renderItem );
197
198     if( renderItem.GetDepthIndex() == depthIndex )
199     {
200       const Matrix& modelViewMatrix = renderItem.GetModelViewMatrix();
201       renderItem.GetRenderer().Render( context, textureCache, bufferIndex, renderItem.GetNode(), defaultShader, modelViewMatrix, viewMatrix, projectionMatrix, frameTime, cullMode, !renderItem.IsOpaque() );
202
203     }
204     else
205     {
206       break; // Stop iterating when we reach a new depth index
207     }
208   }
209 }
210
211
212
213 void ProcessRenderInstruction( const RenderInstruction& instruction,
214                                Context& context,
215                                SceneGraph::TextureCache& textureCache,
216                                SceneGraph::Shader& defaultShader,
217                                BufferIndex bufferIndex,
218                                float frameTime )
219 {
220   DALI_PRINT_RENDER_INSTRUCTION( instruction, bufferIndex );
221
222   const Matrix* viewMatrix       = instruction.GetViewMatrix( bufferIndex );
223   const Matrix* projectionMatrix = instruction.GetProjectionMatrix( bufferIndex );
224
225   DALI_ASSERT_DEBUG( NULL != viewMatrix );
226   DALI_ASSERT_DEBUG( NULL != projectionMatrix );
227
228   if( NULL != viewMatrix &&
229       NULL != projectionMatrix )
230   {
231     const RenderListContainer::SizeType count = instruction.RenderListCount();
232
233     // Iterate through each render list in order. If a pair of render lists
234     // are marked as interleaved, then process them together.
235     for( RenderListContainer::SizeType index = 0; index < count; ++index )
236     {
237       const RenderList* renderList = instruction.GetRenderList( index );
238
239       if(  renderList &&
240           !renderList->IsEmpty() )
241       {
242           ProcessRenderList( *renderList, context, textureCache, defaultShader, bufferIndex, frameTime, *viewMatrix, *projectionMatrix, instruction.mCullMode );
243       }
244     }
245   }
246 }
247
248 } // namespace Render
249
250 } // namespace Internal
251
252 } // namespace Dali