2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali/internal/render/common/render-algorithms.h>
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>
28 using Dali::Internal::SceneGraph::RenderItem;
29 using Dali::Internal::SceneGraph::RenderList;
30 using Dali::Internal::SceneGraph::RenderListContainer;
31 using Dali::Internal::SceneGraph::RenderInstruction;
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
47 inline void SetScissorTest( const RenderList& renderList, Context& context )
50 if( renderList.IsClipping() )
52 context.SetScissorTest( true );
54 const Dali::ClippingBox& clip = renderList.GetClippingBox();
55 context.Scissor(clip.x, clip.y, clip.width, clip.height);
59 context.SetScissorTest( false );
64 * Sets the render flags for depth testing and stencil buffer
66 * @param[in] renderList The render list from which to get the render flags
67 * @param[in] context The context
69 inline void SetRenderFlags( const RenderList& renderList, Context& context )
71 const unsigned int renderFlags = renderList.GetFlags();
73 bool enableDepthBuffer = ( ( renderFlags & RenderList::DEPTH_BUFFER_ENABLED ) != 0u );
74 bool depthMask = ( ( renderFlags & RenderList::DEPTH_WRITE ) != 0u );
76 GLbitfield clearMask = ( renderFlags & RenderList::DEPTH_CLEAR ) ? GL_DEPTH_BUFFER_BIT : 0u;
78 context.EnableDepthBuffer( enableDepthBuffer );
79 context.DepthMask( depthMask );
81 // Stencil enabled, writing, and clearing...
82 const bool enableStencilBuffer( renderFlags & RenderList::STENCIL_BUFFER_ENABLED );
83 const bool enableStencilWrite( renderFlags & RenderList::STENCIL_WRITE );
85 context.EnableStencilBuffer( enableStencilBuffer );
87 if( enableStencilBuffer )
89 context.StencilFunc( (enableStencilWrite ? GL_ALWAYS : GL_EQUAL), 1, 0xFF );
90 context.StencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
92 clearMask |= (renderFlags & RenderList::STENCIL_CLEAR) ? GL_STENCIL_BUFFER_BIT : 0u;
95 // Write to stencil buffer or color buffer, but not both
96 context.StencilMask( enableStencilWrite ? 0xFF : 0x00 );
97 context.ColorMask( !enableStencilWrite );
99 // Clear depth and/or stencil buffer.
102 // only clear if the depth and/or stencil buffer have been written to after a previous clear
103 context.Clear( clearMask, Context::CHECK_CACHED_VALUES );
109 * Process a render-list.
110 * @param[in] renderList The render-list to process.
111 * @param[in] context The GL context.
112 * @param[in] defaultShader The default shader to use.
113 * @param[in] buffer The current render buffer index (previous update buffer)
114 * @param[in] frameTime The elapsed time between the last two updates.
115 * @param[in] viewMatrix The view matrix from the appropriate camera.
116 * @param[in] projectionMatrix The projection matrix from the appropriate camera.
117 * @param[in] cullMode True if the renderers should be subjected to clipspace culling
119 inline void ProcessRenderList(
120 const RenderList& renderList,
122 SceneGraph::TextureCache& textureCache,
123 SceneGraph::Shader& defaultShader,
124 BufferIndex bufferIndex,
126 const Matrix& viewMatrix,
127 const Matrix& projectionMatrix,
130 DALI_PRINT_RENDER_LIST( renderList );
132 SetScissorTest( renderList, context );
133 SetRenderFlags( renderList, context );
135 size_t count = renderList.Count();
136 for ( size_t index = 0; index < count; ++index )
138 const RenderItem& item = renderList.GetItem( index );
140 DALI_PRINT_RENDER_ITEM( item );
142 SceneGraph::Renderer* renderer = const_cast< SceneGraph::Renderer* >( item.GetRenderer() );
143 const Matrix& modelViewMatrix = item.GetModelViewMatrix();
145 renderer->Render( context, textureCache, bufferIndex, defaultShader, modelViewMatrix, viewMatrix, projectionMatrix, frameTime, cullMode );
150 * Render items from the currentIndex until the depth index changes.
151 * Leaves currentIndex pointing at the
153 * @param[in] renderList The render-list to process.
154 * @param[in] context The GL context.
155 * @param[in] defaultShader The default shader to use.
156 * @param[in] buffer The current render buffer index (previous update buffer)
157 * @param[in] frameTime The elapsed time between the last two updates.
158 * @param[in] viewMatrix The view matrix from the appropriate camera.
159 * @param[in] projectionMatrix The projection matrix from the appropriate camera.
160 * @param[in] cullMode True if the renderers should be subjected to clipspace culling
161 * @param[in] depthIndex The current depth index
162 * @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.
164 inline void RenderItemsAtDepthIndex(
165 const RenderList& renderList,
167 SceneGraph::TextureCache& textureCache,
168 SceneGraph::Shader& defaultShader,
169 BufferIndex bufferIndex,
171 const Matrix& viewMatrix,
172 const Matrix& projectionMatrix,
175 size_t& currentIndex ) // Out parameter
177 const size_t count = renderList.Count();
179 // Don't initialise currentIndex. Ever.
180 for( ; currentIndex < count ; currentIndex++ )
182 const RenderItem& renderItem = renderList.GetItem( currentIndex );
183 DALI_PRINT_RENDER_ITEM( renderItem );
185 if( renderItem.GetDepthIndex() == depthIndex )
187 SceneGraph::Renderer* renderer = const_cast< SceneGraph::Renderer* >( renderItem.GetRenderer() );
188 const Matrix& modelViewMatrix = renderItem.GetModelViewMatrix();
189 renderer->Render( context, textureCache, bufferIndex, defaultShader, modelViewMatrix, viewMatrix, projectionMatrix, frameTime, cullMode );
194 break; // Stop iterating when we reach a new depth index
201 * Process two interleaved render-lists.
203 * For each depth index, it will set the flags for the first list,
204 * render items in the first list, set flags for the second list and
205 * render items from the second list.
207 * @param[in] renderList1 The first render-list to process.
208 * @param[in] renderList2 The second render-list to process.
209 * @param[in] context The GL context.
210 * @param[in] defaultShader The default shader to use.
211 * @param[in] buffer The current render buffer index (previous update buffer)
212 * @param[in] frameTime The elapsed time between the last two updates.
213 * @param[in] viewMatrix The view matrix from the appropriate camera.
214 * @param[in] projectionMatrix The projection matrix from the appropriate camera.
215 * @param[in] cullMode True if the renderers should be subjected to clipspace culling
218 inline void ProcessInterleavedRenderLists(
219 const RenderList& renderList1,
220 const RenderList& renderList2,
222 SceneGraph::TextureCache& textureCache,
223 SceneGraph::Shader& defaultShader,
224 BufferIndex bufferIndex,
226 const Matrix& viewMatrix,
227 const Matrix& projectionMatrix,
231 SetScissorTest( renderList1, context ); // Scissor settings are identical for both lists
232 size_t count1 = renderList1.Count();
233 size_t count2 = renderList2.Count();
237 int depthIndex=renderList1.GetItem( 0 ).GetDepthIndex();
239 while( index1 < count1 || index2 < count2 )
241 if( index1 < count1 && index2 < count2 )
243 // Take the lowest depth index in both lists
244 depthIndex = std::min( renderList1.GetItem( index1 ).GetDepthIndex(),
245 renderList2.GetItem( index2 ).GetDepthIndex() );
247 else if( index1 < count1 )
249 // Items left only in list 1
250 depthIndex = renderList1.GetItem( index1 ).GetDepthIndex();
252 else // index2 < count2
254 // Items left only in list 2
255 depthIndex = renderList2.GetItem( index2 ).GetDepthIndex();
258 // Between each successive depth index, reset the flags.
259 SetRenderFlags( renderList1, context );
261 // Find and render items in the first list that correspond to the current depth index
262 if( index1 < count1 )
264 RenderItemsAtDepthIndex( renderList1, context, textureCache, defaultShader,
265 bufferIndex, frameTime, viewMatrix, projectionMatrix,
266 cullMode, depthIndex,
267 index1 ); // Out parameter
270 SetRenderFlags( renderList2, context );
271 if( index2 < count2 )
273 RenderItemsAtDepthIndex( renderList2, context, textureCache, defaultShader,
274 bufferIndex, frameTime, viewMatrix, projectionMatrix,
275 cullMode, depthIndex,
276 index2 ); // Out parameter
282 void ProcessRenderInstruction( const RenderInstruction& instruction,
284 SceneGraph::TextureCache& textureCache,
285 SceneGraph::Shader& defaultShader,
286 BufferIndex bufferIndex,
289 DALI_PRINT_RENDER_INSTRUCTION( instruction, bufferIndex );
291 const Matrix* viewMatrix = instruction.GetViewMatrix( bufferIndex );
292 const Matrix* projectionMatrix = instruction.GetProjectionMatrix( bufferIndex );
294 DALI_ASSERT_DEBUG( NULL != viewMatrix );
295 DALI_ASSERT_DEBUG( NULL != projectionMatrix );
297 if( NULL != viewMatrix &&
298 NULL != projectionMatrix )
300 const RenderListContainer::SizeType count = instruction.RenderListCount();
302 // Iterate through each render list in order. If a pair of render lists
303 // are marked as interleaved, then process them together.
304 for( RenderListContainer::SizeType index = 0; index < count; ++index )
306 const RenderList* renderList = instruction.GetRenderList( index );
309 !renderList->IsEmpty() )
311 if( renderList->GetInterleave() &&
313 instruction.GetRenderList(index+1)->GetInterleave() )
315 ProcessInterleavedRenderLists( *renderList,
316 *(instruction.GetRenderList(index+1)),
324 instruction.mCullMode );
325 index++; // Skip over next render list
329 ProcessRenderList( *renderList, context, textureCache, defaultShader, bufferIndex, frameTime, *viewMatrix, *projectionMatrix, instruction.mCullMode );
336 } // namespace Render
338 } // namespace Internal