[dali_1.1.8] Merge branch 'devel/master'
[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] viewMatrix The view matrix from the appropriate camera.
113  * @param[in] projectionMatrix The projection matrix from the appropriate camera.
114  * @param[in] cullMode True if the renderers should be subjected to clipspace culling
115  */
116 inline void ProcessRenderList(
117   const RenderList& renderList,
118   Context& context,
119   SceneGraph::TextureCache& textureCache,
120   SceneGraph::Shader& defaultShader,
121   BufferIndex bufferIndex,
122   const Matrix& viewMatrix,
123   const Matrix& projectionMatrix,
124   bool cullMode )
125 {
126   DALI_PRINT_RENDER_LIST( renderList );
127
128   SetScissorTest( renderList, context );
129   SetRenderFlags( renderList, context );
130
131   if( renderList.HasColorRenderItems() )
132   {
133     bool depthBufferEnabled = ( ( renderList.GetFlags() & RenderList::DEPTH_BUFFER_ENABLED ) != 0u );
134     size_t count = renderList.Count();
135     for ( size_t index = 0; index < count; ++index )
136     {
137       const RenderItem& item = renderList.GetItem( index );
138       DALI_PRINT_RENDER_ITEM( item );
139
140       //Enable depth writes if depth buffer is enabled and item is opaque
141       context.DepthMask( depthBufferEnabled && ( item.IsOpaque() || item.GetRenderer().RequiresDepthTest() ) );
142
143       item.GetRenderer().Render( context, textureCache, bufferIndex, item.GetNode(), defaultShader, item.GetModelViewMatrix(), viewMatrix, projectionMatrix, cullMode, !item.IsOpaque() );
144     }
145   }
146   else
147   {
148     size_t count = renderList.Count();
149     for ( size_t index = 0; index < count; ++index )
150     {
151       const RenderItem& item = renderList.GetItem( index );
152       DALI_PRINT_RENDER_ITEM( item );
153
154       item.GetRenderer().Render( context, textureCache, bufferIndex, item.GetNode(), defaultShader, item.GetModelViewMatrix(), viewMatrix, projectionMatrix, cullMode, !item.IsOpaque() );
155     }
156
157   }
158 }
159
160 void ProcessRenderInstruction( const RenderInstruction& instruction,
161                                Context& context,
162                                SceneGraph::TextureCache& textureCache,
163                                SceneGraph::Shader& defaultShader,
164                                BufferIndex bufferIndex )
165 {
166   DALI_PRINT_RENDER_INSTRUCTION( instruction, bufferIndex );
167
168   const Matrix* viewMatrix       = instruction.GetViewMatrix( bufferIndex );
169   const Matrix* projectionMatrix = instruction.GetProjectionMatrix( bufferIndex );
170
171   DALI_ASSERT_DEBUG( NULL != viewMatrix );
172   DALI_ASSERT_DEBUG( NULL != projectionMatrix );
173
174   if( NULL != viewMatrix &&
175       NULL != projectionMatrix )
176   {
177     const RenderListContainer::SizeType count = instruction.RenderListCount();
178
179     // Iterate through each render list in order. If a pair of render lists
180     // are marked as interleaved, then process them together.
181     for( RenderListContainer::SizeType index = 0; index < count; ++index )
182     {
183       const RenderList* renderList = instruction.GetRenderList( index );
184
185       if(  renderList &&
186           !renderList->IsEmpty() )
187       {
188         ProcessRenderList( *renderList, context, textureCache, defaultShader, bufferIndex, *viewMatrix, *projectionMatrix, instruction.mCullMode );
189       }
190     }
191   }
192 }
193
194 } // namespace Render
195
196 } // namespace Internal
197
198 } // namespace Dali