Merge "Remove API to set if a geometry requires writing to the depth buffer" 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   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         Renderer& renderer = item.GetRenderer();
148         Dali::Renderer::DepthWriteMode depthWriteMode = renderer.GetDepthWriteMode();
149         context.DepthMask( ( depthWriteMode == Dali::Renderer::DEPTH_WRITE_AUTO && item.IsOpaque() ) ||
150                            ( depthWriteMode == Dali::Renderer::DEPTH_WRITE_ON ) );
151
152         renderer.Render( context, textureCache, bufferIndex, item.GetNode(), defaultShader, item.GetModelViewMatrix(), viewMatrix, projectionMatrix, item.GetSize(), !item.IsOpaque() );
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.GetRenderer().Render( context, textureCache, bufferIndex, item.GetNode(), defaultShader, item.GetModelViewMatrix(), viewMatrix, projectionMatrix, item.GetSize(), !item.IsOpaque() );
162       }
163     }
164   }
165   else
166   {
167     size_t count = renderList.Count();
168     for ( size_t index = 0; index < count; ++index )
169     {
170       const RenderItem& item = renderList.GetItem( index );
171       DALI_PRINT_RENDER_ITEM( item );
172
173       item.GetRenderer().Render( context, textureCache, bufferIndex, item.GetNode(), defaultShader, item.GetModelViewMatrix(), viewMatrix, projectionMatrix, item.GetSize(), !item.IsOpaque() );
174     }
175
176   }
177 }
178
179 void ProcessRenderInstruction( const RenderInstruction& instruction,
180                                Context& context,
181                                SceneGraph::TextureCache& textureCache,
182                                SceneGraph::Shader& defaultShader,
183                                BufferIndex bufferIndex )
184 {
185   DALI_PRINT_RENDER_INSTRUCTION( instruction, bufferIndex );
186
187   const Matrix* viewMatrix       = instruction.GetViewMatrix( bufferIndex );
188   const Matrix* projectionMatrix = instruction.GetProjectionMatrix( bufferIndex );
189
190   DALI_ASSERT_DEBUG( NULL != viewMatrix );
191   DALI_ASSERT_DEBUG( NULL != projectionMatrix );
192
193   if( NULL != viewMatrix &&
194       NULL != projectionMatrix )
195   {
196     const RenderListContainer::SizeType count = instruction.RenderListCount();
197
198     // Iterate through each render list in order. If a pair of render lists
199     // are marked as interleaved, then process them together.
200     for( RenderListContainer::SizeType index = 0; index < count; ++index )
201     {
202       const RenderList* renderList = instruction.GetRenderList( index );
203
204       if(  renderList &&
205           !renderList->IsEmpty() )
206       {
207         ProcessRenderList( *renderList, context, textureCache, defaultShader, bufferIndex, *viewMatrix, *projectionMatrix );
208       }
209     }
210   }
211 }
212
213 } // namespace Render
214
215 } // namespace Internal
216
217 } // namespace Dali