/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
// INTERNAL INCLUDES
#include <dali/public-api/shader-effects/shader-effect.h>
+#include <dali/public-api/actors/layer.h>
#include <dali/integration-api/debug.h>
#include <dali/internal/event/actors/layer-impl.h> // for the default sorting function
-#include <dali/internal/update/effects/scene-graph-material.h>
-#include <dali/internal/update/geometry/scene-graph-geometry.h>
-#include <dali/internal/update/node-attachments/scene-graph-renderer-attachment.h>
-#include <dali/internal/update/resources/resource-manager-declarations.h>
+#include <dali/internal/update/nodes/scene-graph-layer.h>
#include <dali/internal/update/manager/sorted-layers.h>
#include <dali/internal/update/render-tasks/scene-graph-render-task.h>
-#include <dali/internal/update/node-attachments/scene-graph-renderable-attachment.h>
-#include <dali/internal/update/nodes/scene-graph-layer.h>
+#include <dali/internal/update/rendering/scene-graph-texture-set.h>
+#include <dali/internal/update/resources/resource-manager-declarations.h>
#include <dali/internal/render/common/render-item.h>
#include <dali/internal/render/common/render-tracker.h>
#include <dali/internal/render/common/render-instruction.h>
#include <dali/internal/render/common/render-instruction-container.h>
#include <dali/internal/render/shaders/scene-graph-shader.h>
-#include <dali/internal/render/renderers/scene-graph-renderer.h>
+#include <dali/internal/render/renderers/render-renderer.h>
+#include <dali/internal/render/renderers/render-property-buffer.h>
+#include <dali/internal/update/manager/geometry-batcher.h>
namespace
{
{
/**
- * Set flags for opaque renderlist
- * @param renderList to set the flags to
- * @param transparentRenderersExist is true if there is transparent renderers in this layer
- * @param stencilRenderablesExist is true if there are stencil renderers on this layer
- * @param depthTestDisabled whether depth test is disabled.
- */
-inline void SetOpaqueRenderFlags( RenderList& renderList, bool transparentRenderersExist, bool stencilRenderablesExist, bool depthTestDisabled )
-{
- //@todo MESH_REWORK Move RequiresDepthTest from render thread object to update thread object
-
- renderList.SetInterleave(transparentRenderersExist);
-
- // Special optimization if depth test is disabled or if only one opaque rendered in the layer (for example background image)
- // and this renderer does not need depth test against itself (e.g. mesh)
- // and if this layer has got exactly one opaque renderer
- // and this renderer is not interested in depth testing
- // (i.e. is an image and not a mesh)
- if ( ( renderList.Count() == 1 ) &&
- ( !transparentRenderersExist ) &&
- ( !renderList.GetRenderer( 0 )->RequiresDepthTest() ) )
- {
- // no need to enable depth test or clear depth buffer
- // if there's something transparent already rendered by previous layers,
- // this opaque renderer will correctly draw on top of them since no depth test
- renderList.ClearFlags();
- renderList.SetInterleave(false);
- }
- else if( depthTestDisabled )
- {
- renderList.ClearFlags();
- }
- else
- {
- // Prepare for rendering multiple opaque objects
- unsigned int flags = RenderList::DEPTH_BUFFER_ENABLED | RenderList::DEPTH_WRITE | RenderList::DEPTH_CLEAR; // clear depth buffer, draw over the previously rendered layers;
-
- renderList.ClearFlags();
- renderList.SetFlags(flags);
- }
-
- if( stencilRenderablesExist )
- {
- renderList.SetFlags( RenderList::STENCIL_BUFFER_ENABLED );
- }
-}
-
-/**
- * Set the transparent flags on the renderlist
- * @param renderList to set the flags on
- * @param opaqueRenderersExist is true if there are opaque renderers on this layer
- * @param stencilRenderablesExist is true if there are stencil renderers on this layer
- * @param depthTestDisabled whether depth test is disabled.
- */
-inline void SetTransparentRenderFlags( RenderList& renderList, bool opaqueRenderersExist, bool stencilRenderablesExist, bool depthTestDisabled )
-{
- renderList.ClearFlags();
- // We don't need to write to the depth buffer, as transparent objects
- // don't obscure each other.
-
- renderList.SetInterleave(opaqueRenderersExist);
- if ( opaqueRenderersExist && !depthTestDisabled )
- {
- // If there are a mix of opaque and transparent objects, the transparent
- // objects should be rendered with depth test on to avoid background objects
- // appearing in front of opaque foreground objects.
- renderList.SetFlags( RenderList::DEPTH_BUFFER_ENABLED );
- }
-
- if( stencilRenderablesExist )
- {
- renderList.SetFlags( RenderList::STENCIL_BUFFER_ENABLED );
- }
-}
-
-
-/**
- * Set flags for overlay renderlist
- * @param renderList to set the flags for
- * @param stencilRenderablesExist is true if there are stencil renderers on this layer
- */
-inline void SetOverlayRenderFlags( RenderList& renderList, bool stencilRenderablesExist )
-{
- if(stencilRenderablesExist)
- {
- renderList.SetFlags(RenderList::STENCIL_BUFFER_ENABLED);
- }
-}
-
-/**
- * Set flags for stencil renderlist
- * @param renderList to set the flags for
- */
-inline void SetStencilRenderFlags( RenderList& renderList )
-{
- renderList.ClearFlags();
- renderList.SetFlags(RenderList::STENCIL_CLEAR | RenderList::STENCIL_WRITE | RenderList::STENCIL_BUFFER_ENABLED );
-}
-
-/**
* Add a renderer to the list
* @param updateBufferIndex to read the model matrix from
* @param renderList to add the item to
- * @param renderable attachment
+ * @param renderable Node-Renderer pair
* @param viewMatrix used to calculate modelview matrix for the item
+ * @param camera The camera used to render
+ * @param geometryBatcher The instance of the geometry batcher
+ * @param isLayer3d Whether we are processing a 3D layer or not
+ * @param cull Whether frustum culling is enabled or not
*/
inline void AddRendererToRenderList( BufferIndex updateBufferIndex,
RenderList& renderList,
- RenderableAttachment& renderable,
+ Renderable& renderable,
const Matrix& viewMatrix,
- SceneGraph::CameraAttachment& cameraAttachment )
+ SceneGraph::Camera& camera,
+ GeometryBatcher& geometryBatcher,
+ bool isLayer3d,
+ bool cull )
{
- // Check for cull against view frustum
- Matrix mvm;
- bool inside = true;
+ // discard renderable early if it belongs to the batch which has been consumed in during frame
+ Node* renderableNode = renderable.mNode;
+ const bool batchingValid( renderable.mRenderer->IsBatchingEnabled() && renderableNode->mBatchIndex != BATCH_NULL_HANDLE );
+ if( batchingValid && geometryBatcher.HasRendered( renderableNode->mBatchIndex ) )
+ {
+ return;
+ }
- const Node& parentNode = renderable.GetParent();
- const Matrix& worldMatrix = parentNode.GetWorldMatrix( updateBufferIndex );
- Matrix::Multiply( mvm, worldMatrix, viewMatrix );
+ bool inside( true );
+ const Node* batchParentNode = renderable.mNode->GetBatchParent();
+ const Node* node = ( renderable.mRenderer->IsBatchingEnabled() && batchParentNode ) ?
+ batchParentNode : renderableNode;
- if ( RendererAttachment* rendererAttachment = dynamic_cast< RendererAttachment* >( &renderable ) )
+ if ( cull && !renderable.mRenderer->GetShader().HintEnabled( Dali::Shader::Hint::MODIFIES_GEOMETRY ) )
{
- if ( rendererAttachment->GetMaterial().GetShader()->GeometryHintEnabled( Dali::ShaderEffect::HINT_DOESNT_MODIFY_GEOMETRY ) )
+ const Vector4& boundingSphere = node->GetBoundingSphere();
+ inside = (boundingSphere.w > Math::MACHINE_EPSILON_1000) &&
+ (camera.CheckSphereInFrustum( updateBufferIndex, Vector3(boundingSphere), boundingSphere.w ) );
+ }
+
+ if( inside )
+ {
+ if( batchingValid )
+ {
+ geometryBatcher.SetRendered( renderableNode->mBatchIndex );
+ }
+
+ Renderer::Opacity opacity = renderable.mRenderer->GetOpacity( updateBufferIndex, *renderable.mNode );
+ if( opacity != Renderer::TRANSPARENT )
{
- // Get the geometry extents for frustum checking
- const Vector3& position = worldMatrix.GetTranslation3();
- const Geometry& geometry = rendererAttachment->GetGeometry();
- const Vector3& localCenter = geometry.mCenter[ updateBufferIndex ];
- const Vector3& size = parentNode.GetSize( updateBufferIndex );
- Vector3 center = position + ( localCenter * size );
-
- // If the size components are all the same, then we can do a quick bounding sphere check
- if ( fabsf( size.x - size.y ) <= Math::MACHINE_EPSILON_1 * size.x )
+ // Get the next free RenderItem
+ RenderItem& item = renderList.GetNextFreeItem();
+ item.mRenderer = &renderable.mRenderer->GetRenderer();
+ item.mNode = renderable.mNode;
+ item.mIsOpaque = (opacity == Renderer::OPAQUE);
+
+ if( isLayer3d )
{
- inside = cameraAttachment.CheckSphereInFrustum( updateBufferIndex, center, geometry.mRadius[ updateBufferIndex ] * size.x );
+ item.mDepthIndex = renderable.mRenderer->GetDepthIndex();
}
-
- if ( inside )
+ else
{
- // Check against AABB of model
- inside = cameraAttachment.CheckAABBInFrustum( updateBufferIndex, center, geometry.mHalfExtents[ updateBufferIndex ] * size );
+ item.mDepthIndex = renderable.mRenderer->GetDepthIndex() + static_cast<int>( renderable.mNode->GetDepth() ) * Dali::Layer::TREE_DEPTH_MULTIPLIER;
}
+ // save MV matrix onto the item
+ node->GetWorldMatrixAndSize( item.mModelMatrix, item.mSize );
+ Matrix::Multiply( item.mModelViewMatrix, item.mModelMatrix, viewMatrix );
}
}
-
- if ( inside )
- {
- // Get the next free RenderItem
- RenderItem& item = renderList.GetNextFreeItem();
- const Renderer& renderer = renderable.GetRenderer();
- item.SetRenderer( const_cast< Renderer* >( &renderer ) );
- item.SetDepthIndex( renderable.GetDepthIndex(updateBufferIndex) );
-
- // save MV matrix onto the item
- Matrix& modelViewMatrix = item.GetModelViewMatrix();
- modelViewMatrix = mvm;
- }
}
/**
* Add all renderers to the list
* @param updateBufferIndex to read the model matrix from
* @param renderList to add the items to
- * @param renderable attachments
+ * @param renderers to render
+ * NodeRendererContainer Node-Renderer pairs
* @param viewMatrix used to calculate modelview matrix for the items
+ * @param camera The camera used to render
+ * @param geometryBatcher The instance of the geometry batcher
+ * @param isLayer3d Whether we are processing a 3D layer or not
+ * @param cull Whether frustum culling is enabled or not
*/
inline void AddRenderersToRenderList( BufferIndex updateBufferIndex,
RenderList& renderList,
- RenderableAttachmentContainer& attachments,
+ RenderableContainer& renderers,
const Matrix& viewMatrix,
- SceneGraph::CameraAttachment& cameraAttachment )
+ SceneGraph::Camera& camera,
+ GeometryBatcher* geometryBatcher,
+ bool isLayer3d,
+ bool cull)
{
DALI_LOG_INFO( gRenderListLogFilter, Debug::Verbose, "AddRenderersToRenderList()\n");
- // Add renderer for each attachment
- int index=0;
- const RenderableAttachmentIter endIter = attachments.end();
- for ( RenderableAttachmentIter iter = attachments.begin(); iter != endIter; ++iter )
+ unsigned int rendererCount( renderers.Size() );
+ for( unsigned int i(0); i<rendererCount; ++i )
{
- RenderableAttachment& attachment = **iter;
- AddRendererToRenderList( updateBufferIndex, renderList, attachment, viewMatrix, cameraAttachment );
-
- DALI_LOG_INFO( gRenderListLogFilter, Debug::Verbose, " List[%d].renderer = %p\n", index, &(attachment.GetRenderer()));
- index++;
+ AddRendererToRenderList( updateBufferIndex, renderList, renderers[i], viewMatrix, camera, *geometryBatcher, isLayer3d, cull );
}
}
* An example case is a toolbar layer that rarely changes or a popup on top of the rest of the stage
* @param layer that is being processed
* @param renderList that is cached from frame N-1
- * @param attachmentList that is being used
+ * @param renderables list of renderables
*/
inline bool TryReuseCachedRenderers( Layer& layer,
RenderList& renderList,
- RenderableAttachmentContainer& attachmentList )
+ RenderableContainer& renderables )
{
bool retValue = false;
- size_t renderableCount = attachmentList.size();
+ size_t renderableCount = renderables.Size();
// check that the cached list originates from this layer and that the counts match
if( ( renderList.GetSourceLayer() == &layer )&&
( renderList.GetCachedItemCount() == renderableCount ) )
{
- // check that all the same renderers are there. This gives us additional security in avoiding rendering the wrong attachments
- // Attachments are not sorted, but render list is so at this stage renderers may be in different order
+ // check that all the same renderers are there. This gives us additional security in avoiding rendering the wrong things
+ // Render list is sorted so at this stage renderers may be in different order
// therefore we check a combined sum of all renderer addresses
size_t checkSumNew = 0;
size_t checkSumOld = 0;
for( size_t index = 0; index < renderableCount; ++index )
{
- RenderableAttachment* attachment = attachmentList[ index ];
- const Renderer& renderer = attachment->GetRenderer();
+ const Render::Renderer& renderer = renderables[index].mRenderer->GetRenderer();
checkSumNew += size_t( &renderer );
- checkSumOld += size_t( renderList.GetRenderer( index ) );
+ checkSumOld += size_t( &renderList.GetRenderer( index ) );
}
if( checkSumNew == checkSumOld )
{
return retValue;
}
-
/**
* Function which sorts render items by depth index then by instance
- * ptrs of shader/geometry/material.
+ * ptrs of shader/texture/geometry.
* @param lhs item
* @param rhs item
* @return true if left item is greater than right
*/
bool CompareItems( const RendererWithSortAttributes& lhs, const RendererWithSortAttributes& rhs )
{
- // @todo MESH_REWORK Consider replacing all these sortAttributes with a single long int that
- // encapsulates the same data (e.g. the middle-order bits of the ptrs)
- if( lhs.renderItem->GetDepthIndex() == rhs.renderItem->GetDepthIndex() )
+ if( lhs.renderItem->mDepthIndex == rhs.renderItem->mDepthIndex )
{
if( lhs.shader == rhs.shader )
{
- if( lhs.material == rhs.material )
+ if( lhs.textureResourceId == rhs.textureResourceId )
{
- return lhs.geometry < lhs.geometry;
+ return lhs.geometry < rhs.geometry;
}
- return lhs.material < rhs.material;
+ return lhs.textureResourceId < rhs.textureResourceId;
}
- return lhs.shader < rhs.shader;;
+ return lhs.shader < rhs.shader;
}
- return lhs.renderItem->GetDepthIndex() < rhs.renderItem->GetDepthIndex();
+ return lhs.renderItem->mDepthIndex < rhs.renderItem->mDepthIndex;
}
/**
- * Function which sorts the render items by depth index then by Z function,
- * then by instance ptrs of shader/geometry/material.
+ * Function which sorts the render items by Z function, then
+ * by instance ptrs of shader/texture/geometry.
* @param lhs item
* @param rhs item
* @return true if left item is greater than right
*/
-bool CompareItemsWithZValue( const RendererWithSortAttributes& lhs, const RendererWithSortAttributes& rhs )
+bool CompareItems3D( const RendererWithSortAttributes& lhs, const RendererWithSortAttributes& rhs )
{
- // @todo MESH_REWORK Consider replacing all these sortAttributes with a single long int that
- // encapsulates the same data (e.g. the middle-order bits of the ptrs)
-
- if( lhs.renderItem->GetDepthIndex() == rhs.renderItem->GetDepthIndex() )
+ bool lhsIsOpaque = lhs.renderItem->mIsOpaque;
+ if( lhsIsOpaque == rhs.renderItem->mIsOpaque )
{
- if( Equals(lhs.zValue, rhs.zValue) )
+ if( lhsIsOpaque )
{
+ //If both RenderItems are opaque, sort using shader, then texture then geometry
if( lhs.shader == rhs.shader )
{
- if( lhs.material == rhs.material )
+ if( lhs.textureResourceId == rhs.textureResourceId )
{
- return lhs.geometry < lhs.geometry;
+ return lhs.geometry < rhs.geometry;
}
- return lhs.material < rhs.material;
+ return lhs.textureResourceId < rhs.textureResourceId;
}
- return lhs.shader < rhs.shader;;
+ return lhs.shader < rhs.shader;
}
- return lhs.zValue > rhs.zValue;
- }
- return lhs.renderItem->GetDepthIndex() < rhs.renderItem->GetDepthIndex();
-}
-
-inline void SortOpaqueRenderItems(
- BufferIndex bufferIndex,
- RenderList& opaqueRenderList,
- Layer& layer,
- RenderItemSortingHelper& sortingHelper )
-{
- const size_t renderableCount = opaqueRenderList.Count();
- // reserve space if needed
- const unsigned int oldcapacity = sortingHelper.size();
- if( oldcapacity < renderableCount )
- {
- sortingHelper.reserve( renderableCount );
- // add real objects (reserve does not construct objects)
- sortingHelper.insert( sortingHelper.begin() + oldcapacity,
- (renderableCount - oldcapacity),
- RendererWithSortAttributes() );
- }
- else
- {
- // clear extra elements from helper, does not decrease capability
- sortingHelper.resize( renderableCount );
- }
-
- for( size_t index = 0; index < renderableCount; ++index )
- {
- RenderItem& item = opaqueRenderList.GetItem( index );
-
- //@todo MESH_REWORK After merge of RenderableAttachment and RendererAttachment, should instead store the renderable ptr and get the fields directly
- layer.opaqueRenderables[index]->SetSortAttributes( bufferIndex, sortingHelper[ index ] );
-
- sortingHelper[ index ].zValue = 0;
- sortingHelper[ index ].renderItem = &item;
- }
-
- // Sort the renderers by depth index, then by instance
- std::stable_sort( sortingHelper.begin(), sortingHelper.end(), CompareItems );
-
- DALI_LOG_INFO( gRenderListLogFilter, Debug::Verbose, "Sorted Opaque List:\n");
-
- // Repopulate the render items in the render list based on the sorting helper
- RenderItemContainer::Iterator renderListIter = opaqueRenderList.GetContainer().Begin();
- for( unsigned int index = 0; index < renderableCount; ++index, ++renderListIter )
- {
- *renderListIter = sortingHelper[ index ].renderItem;
- DALI_LOG_INFO( gRenderListLogFilter, Debug::Verbose, " sortedList[%d] = %p\n", sortingHelper[ index ].renderItem->GetRenderer() );
- }
-}
-
-/**
- * Add opaque renderers from the layer onto the next free render list
- * @param updateBufferIndex to use
- * @param layer to get the renderers from
- * @param viewmatrix for the camera from rendertask
- * @param cameraAttachment to use the view frustum
- * @param transparentRenderersExist is true if there is transparent renderers in this layer
- * @param stencilRenderablesExist is true if there are stencil renderers on this layer
- * @param instruction to fill in
- * @param tryReuseRenderList whether to try to reuse the cached items from the instruction
- */
-inline void AddOpaqueRenderers( BufferIndex updateBufferIndex,
- Layer& layer,
- const Matrix& viewMatrix,
- SceneGraph::CameraAttachment& cameraAttachment,
- bool transparentRenderablesExist,
- bool stencilRenderablesExist,
- RenderInstruction& instruction,
- RendererSortingHelper& sortingHelper,
- bool tryReuseRenderList )
-{
- const size_t renderableCount = layer.opaqueRenderables.size();
- RenderList& opaqueRenderList = instruction.GetNextFreeRenderList( layer.opaqueRenderables.size() );
- opaqueRenderList.SetClipping( layer.IsClipping(), layer.GetClippingBox() );
-
- // try to reuse cached renderitems from last time around
- if( tryReuseRenderList )
- {
- if( TryReuseCachedRenderers( layer, opaqueRenderList, layer.opaqueRenderables ) )
+ else
{
- // reset the flags as other layers might have changed
- // opaque flags can only be set after renderers are added
- SetOpaqueRenderFlags(opaqueRenderList, transparentRenderablesExist, stencilRenderablesExist, layer.IsDepthTestDisabled() );
- return;
+ //If both RenderItems are transparent, sort using z,then shader, then texture, then geometry
+ if( Equals(lhs.zValue, rhs.zValue) )
+ {
+ if( lhs.shader == rhs.shader )
+ {
+ if( lhs.textureResourceId == rhs.textureResourceId )
+ {
+ return lhs.geometry < rhs.geometry;
+ }
+ return lhs.textureResourceId < rhs.textureResourceId;
+ }
+ return lhs.shader < rhs.shader;
+ }
+ return lhs.zValue > rhs.zValue;
}
}
- AddRenderersToRenderList( updateBufferIndex, opaqueRenderList, layer.opaqueRenderables, viewMatrix, cameraAttachment );
-
- // opaque flags can only be set after renderers are added
- SetOpaqueRenderFlags(opaqueRenderList, transparentRenderablesExist, stencilRenderablesExist, layer.IsDepthTestDisabled() );
-
- // sorting is only needed if more than 1 item
- if( renderableCount > 1 )
+ else
{
- SortOpaqueRenderItems( updateBufferIndex, opaqueRenderList, layer, sortingHelper.opaque );
+ return lhsIsOpaque;
}
}
/**
- * Sort transparent render items
- * @param transparentRenderList to sort
+ * Sort render items
+ * @param bufferIndex The buffer to read from
+ * @param renderList to sort
* @param layer where the renderers are from
* @param sortingHelper to use for sorting the renderitems (to avoid reallocating)
*/
-inline void SortTransparentRenderItems( BufferIndex bufferIndex, RenderList& transparentRenderList, Layer& layer, RenderItemSortingHelper& sortingHelper )
+inline void SortRenderItems( BufferIndex bufferIndex, RenderList& renderList, Layer& layer, RendererSortingHelper& sortingHelper )
{
- const size_t renderableCount = transparentRenderList.Count();
+ const size_t renderableCount = renderList.Count();
// reserve space if needed
const unsigned int oldcapacity = sortingHelper.size();
if( oldcapacity < renderableCount )
{
for( size_t index = 0; index < renderableCount; ++index )
{
- RenderItem& item = transparentRenderList.GetItem( index );
+ RenderItem& item = renderList.GetItem( index );
- //@todo MESH_REWORK After merge of RenderableAttachment and RendererAttachment, should instead store the renderable ptr and get the fields directly
- layer.transparentRenderables[index]->SetSortAttributes( bufferIndex, sortingHelper[ index ] );
+ item.mRenderer->SetSortAttributes( bufferIndex, sortingHelper[ index ] );
// the default sorting function should get inlined here
- sortingHelper[ index ].zValue = Internal::Layer::ZValue( item.GetModelViewMatrix().GetTranslation3() );
+ sortingHelper[ index ].zValue = Internal::Layer::ZValue( item.mModelViewMatrix.GetTranslation3() ) - item.mDepthIndex;
// keep the renderitem pointer in the helper so we can quickly reorder items after sort
sortingHelper[ index ].renderItem = &item;
const Dali::Layer::SortFunctionType sortFunction = layer.GetSortFunction();
for( size_t index = 0; index < renderableCount; ++index )
{
- RenderItem& item = transparentRenderList.GetItem( index );
+ RenderItem& item = renderList.GetItem( index );
- layer.transparentRenderables[index]->SetSortAttributes( bufferIndex, sortingHelper[ index ] );
- sortingHelper[ index ].zValue = (*sortFunction)( item.GetModelViewMatrix().GetTranslation3() );
+ item.mRenderer->SetSortAttributes( bufferIndex, sortingHelper[ index ] );
+ sortingHelper[ index ].zValue = (*sortFunction)( item.mModelViewMatrix.GetTranslation3() ) - item.mDepthIndex;
// keep the renderitem pointer in the helper so we can quickly reorder items after sort
sortingHelper[ index ].renderItem = &item;
}
}
- // sort the renderers back to front, Z Axis point from near plane to far plane
- std::stable_sort( sortingHelper.begin(), sortingHelper.end(), CompareItemsWithZValue );
+ if( layer.GetBehavior() == Dali::Layer::LAYER_3D)
+ {
+ // sort the renderers back to front, Z Axis point from near plane to far plane
+ std::stable_sort( sortingHelper.begin(), sortingHelper.end(), CompareItems3D );
+ }
+ else
+ {
+ // sort the renderers based on DepthIndex
+ std::stable_sort( sortingHelper.begin(), sortingHelper.end(), CompareItems );
+ }
// reorder/repopulate the renderitems in renderlist to correct order based on sortinghelper
DALI_LOG_INFO( gRenderListLogFilter, Debug::Verbose, "Sorted Transparent List:\n");
- RenderItemContainer::Iterator renderListIter = transparentRenderList.GetContainer().Begin();
+ RenderItemContainer::Iterator renderListIter = renderList.GetContainer().Begin();
for( unsigned int index = 0; index < renderableCount; ++index, ++renderListIter )
{
*renderListIter = sortingHelper[ index ].renderItem;
- DALI_LOG_INFO( gRenderListLogFilter, Debug::Verbose, " sortedList[%d] = %p\n", index, sortingHelper[ index ].renderItem->GetRenderer() );
+ DALI_LOG_INFO( gRenderListLogFilter, Debug::Verbose, " sortedList[%d] = %p\n", index, sortingHelper[ index ].renderItem->mRenderer);
}
}
/**
- * Add transparent renderers from the layer onto the next free render list
+ * Add color renderers from the layer onto the next free render list
* @param updateBufferIndex to use
* @param layer to get the renderers from
* @param viewmatrix for the camera from rendertask
- * @param opaqueRenderablesExist is true if there are opaque renderers on this layer
+ * @param camera to use the view frustum
* @param stencilRenderablesExist is true if there are stencil renderers on this layer
* @param instruction to fill in
* @param sortingHelper to use for sorting the renderitems (to avoid reallocating)
+ * @param geometryBatcher the instance of the geometry batcher
* @param tryReuseRenderList whether to try to reuse the cached items from the instruction
+ * @param cull Whether frustum culling is enabled or not
*/
-inline void AddTransparentRenderers( BufferIndex updateBufferIndex,
- Layer& layer,
- const Matrix& viewMatrix,
- SceneGraph::CameraAttachment& cameraAttachment,
- bool opaqueRenderablesExist,
- bool stencilRenderablesExist,
- RenderInstruction& instruction,
- RendererSortingHelper& sortingHelper,
- bool tryReuseRenderList )
+inline void AddColorRenderers( BufferIndex updateBufferIndex,
+ Layer& layer,
+ const Matrix& viewMatrix,
+ SceneGraph::Camera& camera,
+ bool stencilRenderablesExist,
+ RenderInstruction& instruction,
+ RendererSortingHelper& sortingHelper,
+ GeometryBatcher& geometryBatcher,
+ bool tryReuseRenderList,
+ bool cull)
{
- const size_t renderableCount = layer.transparentRenderables.size();
- RenderList& transparentRenderList = instruction.GetNextFreeRenderList( renderableCount );
- transparentRenderList.SetClipping( layer.IsClipping(), layer.GetClippingBox() );
-
- // transparent flags are independent of the amount of transparent renderers
- SetTransparentRenderFlags( transparentRenderList, opaqueRenderablesExist, stencilRenderablesExist, layer.IsDepthTestDisabled() );
+ RenderList& renderList = instruction.GetNextFreeRenderList( layer.colorRenderables.Size() );
+ renderList.SetClipping( layer.IsClipping(), layer.GetClippingBox() );
+ renderList.SetSourceLayer( &layer );
+ renderList.SetHasColorRenderItems( true );
// try to reuse cached renderitems from last time around
if( tryReuseRenderList )
{
- if( TryReuseCachedRenderers( layer, transparentRenderList, layer.transparentRenderables ) )
+ if( TryReuseCachedRenderers( layer, renderList, layer.colorRenderables ) )
{
return;
}
}
- transparentRenderList.SetSourceLayer( &layer );
- AddRenderersToRenderList( updateBufferIndex, transparentRenderList, layer.transparentRenderables, viewMatrix, cameraAttachment );
+ AddRenderersToRenderList( updateBufferIndex, renderList, layer.colorRenderables, viewMatrix, camera, &geometryBatcher, layer.GetBehavior() == Dali::Layer::LAYER_3D, cull );
+ SortRenderItems( updateBufferIndex, renderList, layer, sortingHelper );
- // sorting is only needed if more than 1 item
- if( renderableCount > 1 )
+ // Setup the render flags for stencil.
+ renderList.ClearFlags();
+ if( stencilRenderablesExist )
{
- SortTransparentRenderItems( updateBufferIndex, transparentRenderList, layer, sortingHelper.transparent );
+ // Note: SetFlags does not overwrite, it ORs, so ClearFlags() is also required.
+ renderList.SetFlags( RenderList::STENCIL_BUFFER_ENABLED );
}
}
* @param updateBufferIndex to use
* @param layer to get the renderers from
* @param viewmatrix for the camera from rendertask
+ * @param camera to use
* @param stencilRenderablesExist is true if there are stencil renderers on this layer
* @param instruction to fill in
* @param tryReuseRenderList whether to try to reuse the cached items from the instruction
+ * @param cull Whether frustum culling is enabled or not
*/
inline void AddOverlayRenderers( BufferIndex updateBufferIndex,
Layer& layer,
const Matrix& viewMatrix,
- SceneGraph::CameraAttachment& cameraAttachment,
+ SceneGraph::Camera& camera,
bool stencilRenderablesExist,
RenderInstruction& instruction,
- bool tryReuseRenderList )
+ RendererSortingHelper& sortingHelper,
+ bool tryReuseRenderList,
+ bool cull )
{
- RenderList& overlayRenderList = instruction.GetNextFreeRenderList( layer.overlayRenderables.size() );
+ RenderList& overlayRenderList = instruction.GetNextFreeRenderList( layer.overlayRenderables.Size() );
overlayRenderList.SetClipping( layer.IsClipping(), layer.GetClippingBox() );
- SetOverlayRenderFlags( overlayRenderList, stencilRenderablesExist );
+ overlayRenderList.SetSourceLayer( &layer );
+ overlayRenderList.SetHasColorRenderItems( false );
+
+ //Set render flags
+ overlayRenderList.ClearFlags();
+ if(stencilRenderablesExist)
+ {
+ overlayRenderList.SetFlags(RenderList::STENCIL_BUFFER_ENABLED);
+ }
// try to reuse cached renderitems from last time around
if( tryReuseRenderList )
return;
}
}
- AddRenderersToRenderList( updateBufferIndex, overlayRenderList, layer.overlayRenderables, viewMatrix, cameraAttachment );
+ AddRenderersToRenderList( updateBufferIndex, overlayRenderList, layer.overlayRenderables, viewMatrix, camera, NULL, layer.GetBehavior() == Dali::Layer::LAYER_3D, cull );
+ SortRenderItems( updateBufferIndex, overlayRenderList, layer, sortingHelper );
}
/**
* @param updateBufferIndex to use
* @param layer to get the renderers from
* @param viewmatrix for the camera from rendertask
+ * @param camera to use
* @param instruction to fill in
* @param tryReuseRenderList whether to try to reuse the cached items from the instruction
+ * @param cull Whether frustum culling is enabled or not
*/
inline void AddStencilRenderers( BufferIndex updateBufferIndex,
Layer& layer,
const Matrix& viewMatrix,
- SceneGraph::CameraAttachment& cameraAttachment,
+ SceneGraph::Camera& camera,
RenderInstruction& instruction,
- bool tryReuseRenderList )
+ bool tryReuseRenderList,
+ bool cull )
{
- RenderList& stencilRenderList = instruction.GetNextFreeRenderList( layer.stencilRenderables.size() );
+ RenderList& stencilRenderList = instruction.GetNextFreeRenderList( layer.stencilRenderables.Size() );
stencilRenderList.SetClipping( layer.IsClipping(), layer.GetClippingBox() );
- SetStencilRenderFlags( stencilRenderList );
+ stencilRenderList.SetSourceLayer( &layer );
+ stencilRenderList.SetHasColorRenderItems( false );
+
+ //Set render flags
+ stencilRenderList.ClearFlags();
+ stencilRenderList.SetFlags(RenderList::STENCIL_CLEAR | RenderList::STENCIL_WRITE | RenderList::STENCIL_BUFFER_ENABLED );
// try to reuse cached renderitems from last time around
if( tryReuseRenderList )
return;
}
}
- AddRenderersToRenderList( updateBufferIndex, stencilRenderList, layer.stencilRenderables, viewMatrix, cameraAttachment );
+ AddRenderersToRenderList( updateBufferIndex, stencilRenderList, layer.stencilRenderables, viewMatrix, camera, NULL, layer.GetBehavior() == Dali::Layer::LAYER_3D, cull );
}
-/**
- * Prepare a single render instruction
- * @param updateBufferIndex to use
- * @param sortedLayers to prepare the instruction from
- * @param renderTask to get the view matrix
- * @param sortingHelper to use for sorting the renderitems (to avoid reallocating)
- * @param renderTracker An optional render tracker object
- * @param instructions container
- */
void PrepareRenderInstruction( BufferIndex updateBufferIndex,
SortedLayerPointers& sortedLayers,
RenderTask& renderTask,
RendererSortingHelper& sortingHelper,
- RenderTracker* renderTracker,
- RenderInstructionContainer& instructions )
+ bool cull,
+ RenderInstructionContainer& instructions,
+ GeometryBatcher& geometryBatcher )
{
// Retrieve the RenderInstruction buffer from the RenderInstructionContainer
// then populate with instructions.
bool viewMatrixHasNotChanged = !renderTask.ViewMatrixUpdated();
const Matrix& viewMatrix = renderTask.GetViewMatrix( updateBufferIndex );
- SceneGraph::CameraAttachment& cameraAttachment = renderTask.GetCameraAttachment();
+ SceneGraph::Camera& camera = renderTask.GetCamera();
const SortedLayersIter endIter = sortedLayers.end();
for ( SortedLayersIter iter = sortedLayers.begin(); iter != endIter; ++iter )
{
Layer& layer = **iter;
- const bool stencilRenderablesExist( !layer.stencilRenderables.empty() );
- const bool opaqueRenderablesExist( !layer.opaqueRenderables.empty() );
- const bool transparentRenderablesExist( !layer.transparentRenderables.empty() );
- const bool overlayRenderablesExist( !layer.overlayRenderables.empty() );
- const bool tryReuseRenderList( viewMatrixHasNotChanged && layer.CanReuseRenderers(renderTask.GetCamera()) );
+ const bool stencilRenderablesExist( !layer.stencilRenderables.Empty() );
+ const bool colorRenderablesExist( !layer.colorRenderables.Empty() );
+ const bool overlayRenderablesExist( !layer.overlayRenderables.Empty() );
+ const bool tryReuseRenderList( viewMatrixHasNotChanged && layer.CanReuseRenderers( &renderTask.GetCamera() ) );
// Ignore stencils if there's nothing to test
if( stencilRenderablesExist &&
- ( opaqueRenderablesExist || transparentRenderablesExist || overlayRenderablesExist ) )
+ ( colorRenderablesExist || overlayRenderablesExist ) )
{
- AddStencilRenderers( updateBufferIndex, layer, viewMatrix, cameraAttachment, instruction, tryReuseRenderList );
+ AddStencilRenderers( updateBufferIndex, layer, viewMatrix, camera, instruction, tryReuseRenderList, cull );
}
- if ( opaqueRenderablesExist )
+ if ( colorRenderablesExist )
{
- AddOpaqueRenderers( updateBufferIndex,
- layer,
- viewMatrix,
- cameraAttachment,
- transparentRenderablesExist,
- stencilRenderablesExist,
- instruction,
- sortingHelper,
- tryReuseRenderList );
+ AddColorRenderers( updateBufferIndex,
+ layer,
+ viewMatrix,
+ camera,
+ stencilRenderablesExist,
+ instruction,
+ sortingHelper,
+ geometryBatcher,
+ tryReuseRenderList,
+ cull );
}
- if ( transparentRenderablesExist )
- {
- AddTransparentRenderers( updateBufferIndex,
- layer,
- viewMatrix,
- cameraAttachment,
- opaqueRenderablesExist,
- stencilRenderablesExist,
- instruction,
- sortingHelper,
- tryReuseRenderList );
- }
-
- // @todo MESH_REWORK Mark opaque and transparent render lists as interleaveable.
- // ( Saves having to have a pair of lists for each depth index )
-
if ( overlayRenderablesExist )
{
- AddOverlayRenderers( updateBufferIndex, layer, viewMatrix, cameraAttachment, stencilRenderablesExist,
- instruction, tryReuseRenderList );
+ AddOverlayRenderers( updateBufferIndex, layer, viewMatrix, camera, stencilRenderablesExist,
+ instruction, sortingHelper, tryReuseRenderList, cull );
}
}
- instruction.mRenderTracker = renderTracker;
- instruction.mCullMode = renderTask.GetCullMode();
-
// inform the render instruction that all renderers have been added and this frame is complete
instruction.UpdateCompleted();
}