RenderItem clean-up
[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   if( ( renderFlags & RenderList::DEPTH_BUFFER_ENABLED ) != 0u )
74   {
75     //Enable depth testing
76     context.EnableDepthBuffer( true );
77   }
78   else
79   {
80     //Disable depth test and depth write
81     context.EnableDepthBuffer( false );
82     context.DepthMask( false );
83   }
84
85   GLbitfield clearMask   = ( renderFlags & RenderList::DEPTH_CLEAR ) ? GL_DEPTH_BUFFER_BIT : 0u;
86
87   // Stencil enabled, writing, and clearing...
88   const bool enableStencilBuffer( renderFlags & RenderList::STENCIL_BUFFER_ENABLED );
89   const bool enableStencilWrite( renderFlags & RenderList::STENCIL_WRITE );
90   context.EnableStencilBuffer( enableStencilBuffer );
91   if( enableStencilBuffer )
92   {
93     context.StencilFunc( (enableStencilWrite ? GL_ALWAYS : GL_EQUAL), 1, 0xFF );
94     context.StencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
95
96     clearMask |= (renderFlags & RenderList::STENCIL_CLEAR) ? GL_STENCIL_BUFFER_BIT : 0u;
97   }
98
99   // Write to stencil buffer or color buffer, but not both
100   context.StencilMask( enableStencilWrite ? 0xFF : 0x00 );
101   context.ColorMask( !enableStencilWrite );
102
103   // Clear depth and/or stencil buffer.
104   if( clearMask )
105   {
106     // only clear if the depth and/or stencil buffer have been written to after a previous clear
107     context.Clear( clearMask, Context::CHECK_CACHED_VALUES );
108   }
109 }
110
111
112 /**
113  * Process a render-list.
114  * @param[in] renderList The render-list to process.
115  * @param[in] context The GL context.
116  * @param[in] defaultShader The default shader to use.
117  * @param[in] buffer The current render buffer index (previous update buffer)
118  * @param[in] viewMatrix The view matrix from the appropriate camera.
119  * @param[in] projectionMatrix The projection matrix from the appropriate camera.
120  */
121 inline void ProcessRenderList(
122   const RenderList& renderList,
123   Context& context,
124   SceneGraph::TextureCache& textureCache,
125   SceneGraph::Shader& defaultShader,
126   BufferIndex bufferIndex,
127   const Matrix& viewMatrix,
128   const Matrix& projectionMatrix )
129 {
130   DALI_PRINT_RENDER_LIST( renderList );
131
132   SetScissorTest( renderList, context );
133   SetRenderFlags( renderList, context );
134
135   if( renderList.HasColorRenderItems() )
136   {
137     bool depthBufferEnabled = ( ( renderList.GetFlags() & RenderList::DEPTH_BUFFER_ENABLED ) != 0u );
138     size_t count = renderList.Count();
139
140     if( depthBufferEnabled )
141     {
142       for ( size_t index = 0; index < count; ++index )
143       {
144         const RenderItem& item = renderList.GetItem( index );
145         DALI_PRINT_RENDER_ITEM( item );
146
147         DepthWriteMode::Type depthWriteMode = item.mRenderer->GetDepthWriteMode();
148         context.DepthMask( ( depthWriteMode == DepthWriteMode::AUTO && item.mIsOpaque ) ||
149                            ( depthWriteMode == DepthWriteMode::ON ) );
150
151         item.mRenderer->Render( context, textureCache, bufferIndex, *item.mNode, defaultShader,
152                                 item.mModelMatrix, item.mModelViewMatrix, viewMatrix, projectionMatrix, item.mSize, !item.mIsOpaque );
153       }
154     }
155     else
156     {
157       for ( size_t index = 0; index < count; ++index )
158       {
159         const RenderItem& item = renderList.GetItem( index );
160         DALI_PRINT_RENDER_ITEM( item );
161         item.mRenderer->Render( context, textureCache, bufferIndex, *item.mNode, defaultShader,
162                                 item.mModelMatrix, item.mModelViewMatrix, viewMatrix, projectionMatrix, item.mSize, !item.mIsOpaque );
163       }
164     }
165   }
166   else
167   {
168     size_t count = renderList.Count();
169     for ( size_t index = 0; index < count; ++index )
170     {
171       const RenderItem& item = renderList.GetItem( index );
172       DALI_PRINT_RENDER_ITEM( item );
173
174       item.mRenderer->Render( context, textureCache, bufferIndex, *item.mNode, defaultShader,
175                               item.mModelMatrix, item.mModelViewMatrix, viewMatrix, projectionMatrix, item.mSize, !item.mIsOpaque );
176     }
177
178   }
179 }
180
181 void ProcessRenderInstruction( const RenderInstruction& instruction,
182                                Context& context,
183                                SceneGraph::TextureCache& textureCache,
184                                SceneGraph::Shader& defaultShader,
185                                BufferIndex bufferIndex )
186 {
187   DALI_PRINT_RENDER_INSTRUCTION( instruction, bufferIndex );
188
189   const Matrix* viewMatrix       = instruction.GetViewMatrix( bufferIndex );
190   const Matrix* projectionMatrix = instruction.GetProjectionMatrix( bufferIndex );
191
192   DALI_ASSERT_DEBUG( NULL != viewMatrix );
193   DALI_ASSERT_DEBUG( NULL != projectionMatrix );
194
195   if( NULL != viewMatrix &&
196       NULL != projectionMatrix )
197   {
198     const RenderListContainer::SizeType count = instruction.RenderListCount();
199
200     // Iterate through each render list in order. If a pair of render lists
201     // are marked as interleaved, then process them together.
202     for( RenderListContainer::SizeType index = 0; index < count; ++index )
203     {
204       const RenderList* renderList = instruction.GetRenderList( index );
205
206       if(  renderList &&
207           !renderList->IsEmpty() )
208       {
209         ProcessRenderList( *renderList, context, textureCache, defaultShader, bufferIndex, *viewMatrix, *projectionMatrix );
210       }
211     }
212   }
213 }
214
215 } // namespace Render
216
217 } // namespace Internal
218
219 } // namespace Dali