From a4387a05849bc5d4398c5a8fb738eebd9b96a494 Mon Sep 17 00:00:00 2001 From: Ferran Sole Date: Thu, 13 Aug 2015 09:38:24 +0100 Subject: [PATCH] Changed drawing order for 2D and 3D layers -In 2D Layers, all renderers (opaque and transparent) are sorted based on its SortModifier/DepthIndex. -In 3D Layers, opaque renderers are sorted by mesh and material to reduce GL state changes and transparent renderers are sorted back to front. SortModifier/DepthIndex is used as an offset to the Z position of the transparent renderers when sorting. Change-Id: I5ca4cd4786bd106d62edf6428c58ad538a0dd2f3 --- dali/internal/render/common/render-algorithms.cpp | 133 ++----- dali/internal/render/common/render-item.cpp | 8 +- dali/internal/render/common/render-item.h | 16 + dali/internal/render/common/render-list.h | 25 +- .../update/manager/prepare-render-algorithms.cpp | 6 +- .../update/manager/prepare-render-instructions.cpp | 383 ++++++--------------- .../update/manager/prepare-render-instructions.h | 8 +- .../update/manager/process-render-tasks.cpp | 6 +- dali/internal/update/manager/update-algorithms.cpp | 2 +- dali/internal/update/nodes/scene-graph-layer.h | 3 +- 10 files changed, 173 insertions(+), 417 deletions(-) diff --git a/dali/internal/render/common/render-algorithms.cpp b/dali/internal/render/common/render-algorithms.cpp index 95785de..faa4b4e 100644 --- a/dali/internal/render/common/render-algorithms.cpp +++ b/dali/internal/render/common/render-algorithms.cpp @@ -71,12 +71,10 @@ inline void SetRenderFlags( const RenderList& renderList, Context& context ) const unsigned int renderFlags = renderList.GetFlags(); bool enableDepthBuffer = ( ( renderFlags & RenderList::DEPTH_BUFFER_ENABLED ) != 0u ); - bool depthMask = ( ( renderFlags & RenderList::DEPTH_WRITE ) != 0u ); GLbitfield clearMask = ( renderFlags & RenderList::DEPTH_CLEAR ) ? GL_DEPTH_BUFFER_BIT : 0u; context.EnableDepthBuffer( enableDepthBuffer ); - context.DepthMask( depthMask ); // Stencil enabled, writing, and clearing... const bool enableStencilBuffer( renderFlags & RenderList::STENCIL_BUFFER_ENABLED ); @@ -132,17 +130,34 @@ inline void ProcessRenderList( SetScissorTest( renderList, context ); SetRenderFlags( renderList, context ); - size_t count = renderList.Count(); - for ( size_t index = 0; index < count; ++index ) + if( renderList.HasColorRenderItems() ) { - const RenderItem& item = renderList.GetItem( index ); + bool depthBufferEnabled = ( ( renderList.GetFlags() & RenderList::DEPTH_BUFFER_ENABLED ) != 0u ); + size_t count = renderList.Count(); + for ( size_t index = 0; index < count; ++index ) + { + const RenderItem& item = renderList.GetItem( index ); + DALI_PRINT_RENDER_ITEM( item ); + + //Enable depth writes if depth buffer is enabled and item is opaque + context.DepthMask( depthBufferEnabled && item.IsOpaque() ); - DALI_PRINT_RENDER_ITEM( item ); + SceneGraph::Renderer* renderer = const_cast< SceneGraph::Renderer* >( item.GetRenderer() ); + renderer->Render( context, textureCache, bufferIndex, defaultShader, item.GetModelViewMatrix(), viewMatrix, projectionMatrix, frameTime, cullMode ); + } + } + else + { + size_t count = renderList.Count(); + for ( size_t index = 0; index < count; ++index ) + { + const RenderItem& item = renderList.GetItem( index ); + DALI_PRINT_RENDER_ITEM( item ); - SceneGraph::Renderer* renderer = const_cast< SceneGraph::Renderer* >( item.GetRenderer() ); - const Matrix& modelViewMatrix = item.GetModelViewMatrix(); + SceneGraph::Renderer* renderer = const_cast< SceneGraph::Renderer* >( item.GetRenderer() ); + renderer->Render( context, textureCache, bufferIndex, defaultShader, item.GetModelViewMatrix(), viewMatrix, projectionMatrix, frameTime, cullMode ); + } - renderer->Render( context, textureCache, bufferIndex, defaultShader, modelViewMatrix, viewMatrix, projectionMatrix, frameTime, cullMode ); } } @@ -197,87 +212,6 @@ inline void RenderItemsAtDepthIndex( } -/** - * Process two interleaved render-lists. - * - * For each depth index, it will set the flags for the first list, - * render items in the first list, set flags for the second list and - * render items from the second list. - * - * @param[in] renderList1 The first render-list to process. - * @param[in] renderList2 The second render-list to process. - * @param[in] context The GL context. - * @param[in] defaultShader The default shader to use. - * @param[in] buffer The current render buffer index (previous update buffer) - * @param[in] frameTime The elapsed time between the last two updates. - * @param[in] viewMatrix The view matrix from the appropriate camera. - * @param[in] projectionMatrix The projection matrix from the appropriate camera. - * @param[in] cullMode True if the renderers should be subjected to clipspace culling - */ - -inline void ProcessInterleavedRenderLists( - const RenderList& renderList1, - const RenderList& renderList2, - Context& context, - SceneGraph::TextureCache& textureCache, - SceneGraph::Shader& defaultShader, - BufferIndex bufferIndex, - float frameTime, - const Matrix& viewMatrix, - const Matrix& projectionMatrix, - bool cullMode ) -{ - - SetScissorTest( renderList1, context ); // Scissor settings are identical for both lists - size_t count1 = renderList1.Count(); - size_t count2 = renderList2.Count(); - size_t index1 = 0; - size_t index2 = 0; - - int depthIndex=renderList1.GetItem( 0 ).GetDepthIndex(); - - while( index1 < count1 || index2 < count2 ) - { - if( index1 < count1 && index2 < count2 ) - { - // Take the lowest depth index in both lists - depthIndex = std::min( renderList1.GetItem( index1 ).GetDepthIndex(), - renderList2.GetItem( index2 ).GetDepthIndex() ); - } - else if( index1 < count1 ) - { - // Items left only in list 1 - depthIndex = renderList1.GetItem( index1 ).GetDepthIndex(); - } - else // index2 < count2 - { - // Items left only in list 2 - depthIndex = renderList2.GetItem( index2 ).GetDepthIndex(); - } - - // Between each successive depth index, reset the flags. - SetRenderFlags( renderList1, context ); - - // Find and render items in the first list that correspond to the current depth index - if( index1 < count1 ) - { - RenderItemsAtDepthIndex( renderList1, context, textureCache, defaultShader, - bufferIndex, frameTime, viewMatrix, projectionMatrix, - cullMode, depthIndex, - index1 ); // Out parameter - } - - SetRenderFlags( renderList2, context ); - if( index2 < count2 ) - { - RenderItemsAtDepthIndex( renderList2, context, textureCache, defaultShader, - bufferIndex, frameTime, viewMatrix, projectionMatrix, - cullMode, depthIndex, - index2 ); // Out parameter - } - } -} - void ProcessRenderInstruction( const RenderInstruction& instruction, Context& context, @@ -308,26 +242,7 @@ void ProcessRenderInstruction( const RenderInstruction& instruction, if( renderList && !renderList->IsEmpty() ) { - if( renderList->GetInterleave() && - index < count-1 && - instruction.GetRenderList(index+1)->GetInterleave() ) - { - ProcessInterleavedRenderLists( *renderList, - *(instruction.GetRenderList(index+1)), - context, - textureCache, - defaultShader, - bufferIndex, - frameTime, - *viewMatrix, - *projectionMatrix, - instruction.mCullMode ); - index++; // Skip over next render list - } - else - { ProcessRenderList( *renderList, context, textureCache, defaultShader, bufferIndex, frameTime, *viewMatrix, *projectionMatrix, instruction.mCullMode ); - } } } } diff --git a/dali/internal/render/common/render-item.cpp b/dali/internal/render/common/render-item.cpp index 63e868f..a082149 100644 --- a/dali/internal/render/common/render-item.cpp +++ b/dali/internal/render/common/render-item.cpp @@ -33,7 +33,8 @@ namespace SceneGraph RenderItem::RenderItem() : mModelViewMatrix( false ), mRenderer( NULL ), - mDepthIndex(0) + mDepthIndex(0), + mIsOpaque(true) { } @@ -71,6 +72,11 @@ void RenderItem::SetDepthIndex( int depthIndex ) mDepthIndex = depthIndex; } +void RenderItem::SetIsOpaque( bool isOpaque ) +{ + mIsOpaque = isOpaque; +} + } // namespace SceneGraph } // namespace Internal diff --git a/dali/internal/render/common/render-item.h b/dali/internal/render/common/render-item.h index 35c1107..839a1bd 100644 --- a/dali/internal/render/common/render-item.h +++ b/dali/internal/render/common/render-item.h @@ -96,6 +96,21 @@ public: */ void SetDepthIndex( int depthIndex ); + /** + * Set if the RenderItem is opaque + * @param[in] isOpaque true if the RenderItem is opaque, false otherwise + */ + void SetIsOpaque( bool isOpaque ); + + /** + * Check if the RenderItem is opaque + * @return True if it is opaque, false otherwise + */ + bool IsOpaque() const + { + return mIsOpaque; + } + private: // RenderItems should not be copied as they are heavy @@ -105,6 +120,7 @@ private: Matrix mModelViewMatrix; Renderer* mRenderer; int mDepthIndex; + bool mIsOpaque:1; }; } // namespace SceneGraph diff --git a/dali/internal/render/common/render-list.h b/dali/internal/render/common/render-list.h index 192f5f3..dfe58f1 100644 --- a/dali/internal/render/common/render-list.h +++ b/dali/internal/render/common/render-list.h @@ -78,7 +78,7 @@ public: mRenderFlags( 0u ), mClippingBox( NULL ), mSourceLayer( NULL ), - mInterleave(false) + mHasColorRenderItems( false ) { } @@ -285,22 +285,21 @@ public: } /** - * Determine if this render list should be interleaved with it's adjacent - * neighbour. - * @return true if the render list should be interleaved + * Set if the RenderList contains color RenderItems + * @param[in] hasColorRenderItems True if it contains color RenderItems, false otherwise */ - bool GetInterleave() const + void SetHasColorRenderItems( bool hasColorRenderItems ) { - return mInterleave; + mHasColorRenderItems = hasColorRenderItems; } /** - * Set the interleave flag for this render list - * @param[in] interleave The interleave flag. + * Check if the RenderList contains color RenderItems + * @return true if the RenderList contains color RenderItems, false otherwise */ - void SetInterleave(bool interleave) + bool HasColorRenderItems() const { - mInterleave = interleave; + return mHasColorRenderItems; } private: @@ -316,9 +315,9 @@ private: unsigned int mRenderFlags; ///< The render flags - ClippingBox* mClippingBox; ///< The clipping box, in window coordinates, when clipping is enabled - Layer* mSourceLayer; ///< The originating layer where the renderers are from - bool mInterleave; ///< True if render list should be interleaved + ClippingBox* mClippingBox; ///< The clipping box, in window coordinates, when clipping is enabled + Layer* mSourceLayer; ///< The originating layer where the renderers are from + bool mHasColorRenderItems : 1; ///< True if list contains color render items }; } // namespace SceneGraph diff --git a/dali/internal/update/manager/prepare-render-algorithms.cpp b/dali/internal/update/manager/prepare-render-algorithms.cpp index 51e1699..c213f95 100644 --- a/dali/internal/update/manager/prepare-render-algorithms.cpp +++ b/dali/internal/update/manager/prepare-render-algorithms.cpp @@ -48,8 +48,7 @@ void ClearRenderables( SortedLayerPointers& sortedLayers ) for ( SortedLayersIter iter = sortedLayers.begin(); iter != endIter; ++iter ) { (*iter)->stencilRenderables.clear(); - (*iter)->opaqueRenderables.clear(); - (*iter)->transparentRenderables.clear(); + (*iter)->colorRenderables.clear(); (*iter)->overlayRenderables.clear(); } } @@ -77,8 +76,7 @@ void PrepareRenderables( BufferIndex updateBufferIndex, SortedLayerPointers& sor Layer& layer = **iter; PrepareRenderables( updateBufferIndex, layer.stencilRenderables ); - PrepareRenderables( updateBufferIndex, layer.opaqueRenderables ); - PrepareRenderables( updateBufferIndex, layer.transparentRenderables ); + PrepareRenderables( updateBufferIndex, layer.colorRenderables ); PrepareRenderables( updateBufferIndex, layer.overlayRenderables ); } } diff --git a/dali/internal/update/manager/prepare-render-instructions.cpp b/dali/internal/update/manager/prepare-render-instructions.cpp index 999d3c9..db7e383 100644 --- a/dali/internal/update/manager/prepare-render-instructions.cpp +++ b/dali/internal/update/manager/prepare-render-instructions.cpp @@ -55,105 +55,6 @@ namespace SceneGraph { /** - * 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 @@ -200,10 +101,11 @@ inline void AddRendererToRenderList( BufferIndex updateBufferIndex, if ( inside ) { - // Get the next free RenderItem + // Get the next free RenderItem and initialization RenderItem& item = renderList.GetNextFreeItem(); const Renderer& renderer = renderable.GetRenderer(); item.SetRenderer( const_cast< Renderer* >( &renderer ) ); + item.SetIsOpaque( renderable.IsFullyOpaque(updateBufferIndex) ); if( isLayer3d ) { item.SetDepthIndex( renderable.GetDepthIndex() ); @@ -214,8 +116,7 @@ inline void AddRendererToRenderList( BufferIndex updateBufferIndex, } // save MV matrix onto the item - Matrix& modelViewMatrix = item.GetModelViewMatrix(); - Matrix::Multiply( modelViewMatrix, worldMatrix, viewMatrix ); + Matrix::Multiply( item.GetModelViewMatrix(), worldMatrix, viewMatrix ); } } @@ -321,133 +222,57 @@ bool CompareItems( const RendererWithSortAttributes& lhs, const RendererWithSort * @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( Equals(lhs.zValue, rhs.zValue) ) + bool lhsIsOpaque = lhs.renderItem->IsOpaque(); + if( lhsIsOpaque == rhs.renderItem->IsOpaque()) { - if( lhs.shader == rhs.shader ) + if( lhsIsOpaque ) { - if( lhs.material == rhs.material ) + //If both RenderItems are opaque, sort using shader, then material then geometry + if( lhs.shader == rhs.shader ) { - return lhs.geometry < rhs.geometry; + if( lhs.material == rhs.material ) + { + return lhs.geometry < rhs.geometry; + } + return lhs.material < rhs.material; } - return lhs.material < rhs.material; + return lhs.shader < rhs.shader; } - return lhs.shader < rhs.shader; - } - return lhs.zValue > rhs.zValue; -} - -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", index, 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 disableDepthTest is true if depth test should be disabled 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, - bool disableDepthTest, - 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, disableDepthTest ); - return; + //If both RenderItems are transparent, sort using z,then shader, then material, then geometry + if( Equals(lhs.zValue, rhs.zValue) ) + { + if( lhs.shader == rhs.shader ) + { + if( lhs.material == rhs.material ) + { + return lhs.geometry < rhs.geometry; + } + return lhs.material < rhs.material; + } + return lhs.shader < rhs.shader; + } + return lhs.zValue > rhs.zValue; } } - AddRenderersToRenderList( updateBufferIndex, opaqueRenderList, layer.opaqueRenderables, viewMatrix, cameraAttachment, layer.GetBehavior() == Dali::Layer::LAYER_3D ); - - // opaque flags can only be set after renderers are added - SetOpaqueRenderFlags(opaqueRenderList, transparentRenderablesExist, stencilRenderablesExist, disableDepthTest ); - - // 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 color render items + * @param colorRenderList 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 SortColorRenderItems( 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 ) @@ -470,13 +295,13 @@ inline void SortTransparentRenderItems( BufferIndex bufferIndex, RenderList& tra { 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 ] ); + layer.colorRenderables[index]->SetSortAttributes( bufferIndex, sortingHelper[ index ] ); // the default sorting function should get inlined here - sortingHelper[ index ].zValue = Internal::Layer::ZValue( item.GetModelViewMatrix().GetTranslation3() ) + item.GetDepthIndex(); + sortingHelper[ index ].zValue = Internal::Layer::ZValue( item.GetModelViewMatrix().GetTranslation3() ) - item.GetDepthIndex(); // keep the renderitem pointer in the helper so we can quickly reorder items after sort sortingHelper[ index ].renderItem = &item; @@ -487,10 +312,10 @@ inline void SortTransparentRenderItems( BufferIndex bufferIndex, RenderList& tra 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() ); + layer.colorRenderables[index]->SetSortAttributes( bufferIndex, sortingHelper[ index ] ); + sortingHelper[ index ].zValue = (*sortFunction)( item.GetModelViewMatrix().GetTranslation3() ) - item.GetDepthIndex(); // keep the renderitem pointer in the helper so we can quickly reorder items after sort sortingHelper[ index ].renderItem = &item; @@ -500,7 +325,7 @@ inline void SortTransparentRenderItems( BufferIndex bufferIndex, RenderList& tra 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(), CompareItemsWithZValue ); + std::stable_sort( sortingHelper.begin(), sortingHelper.end(), CompareItems3D ); } else { @@ -510,7 +335,7 @@ inline void SortTransparentRenderItems( BufferIndex bufferIndex, RenderList& tra // 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; @@ -519,50 +344,67 @@ inline void SortTransparentRenderItems( BufferIndex bufferIndex, RenderList& tra } /** - * 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 cameraAttachment 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 tryReuseRenderList whether to try to reuse the cached items from the instruction */ -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::CameraAttachment& cameraAttachment, + bool stencilRenderablesExist, + RenderInstruction& instruction, + RendererSortingHelper& sortingHelper, + bool tryReuseRenderList ) { - 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.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, layer.GetBehavior() == Dali::Layer::LAYER_3D ); + AddRenderersToRenderList( updateBufferIndex, renderList, layer.colorRenderables, viewMatrix, cameraAttachment, layer.GetBehavior() == Dali::Layer::LAYER_3D ); + SortColorRenderItems( updateBufferIndex, renderList, layer, sortingHelper ); - // sorting is only needed if more than 1 item - if( renderableCount > 1 ) + //Set render flags + unsigned int flags = 0u; + if( stencilRenderablesExist ) { - SortTransparentRenderItems( updateBufferIndex, transparentRenderList, layer, sortingHelper.transparent ); + flags = RenderList::STENCIL_BUFFER_ENABLED; } + + // 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 ) && + ( !renderList.GetRenderer( 0 )->RequiresDepthTest() ) && + ( !renderList.GetItem(0).IsOpaque() ) ) + { + //Nothing to do here + } + else if( !layer.IsDepthTestDisabled()) + { + flags |= RenderList::DEPTH_BUFFER_ENABLED; + flags |= RenderList::DEPTH_CLEAR; + } + + renderList.ClearFlags(); + renderList.SetFlags( flags ); } /** @@ -584,7 +426,14 @@ inline void AddOverlayRenderers( BufferIndex updateBufferIndex, { RenderList& overlayRenderList = instruction.GetNextFreeRenderList( layer.overlayRenderables.size() ); overlayRenderList.SetClipping( layer.IsClipping(), layer.GetClippingBox() ); - SetOverlayRenderFlags( overlayRenderList, stencilRenderablesExist ); + 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 ) @@ -614,7 +463,11 @@ inline void AddStencilRenderers( BufferIndex updateBufferIndex, { RenderList& stencilRenderList = instruction.GetNextFreeRenderList( layer.stencilRenderables.size() ); stencilRenderList.SetClipping( layer.IsClipping(), layer.GetClippingBox() ); - SetStencilRenderFlags( stencilRenderList ); + 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 ) @@ -658,49 +511,29 @@ void PrepareRenderInstruction( BufferIndex updateBufferIndex, Layer& layer = **iter; const bool stencilRenderablesExist( !layer.stencilRenderables.empty() ); - const bool opaqueRenderablesExist( !layer.opaqueRenderables.empty() ); - const bool transparentRenderablesExist( !layer.transparentRenderables.empty() ); + const bool colorRenderablesExist( !layer.colorRenderables.empty() ); const bool overlayRenderablesExist( !layer.overlayRenderables.empty() ); - const bool disableDepthTest( layer.IsDepthTestDisabled() ); 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 ); } - if ( opaqueRenderablesExist ) + if ( colorRenderablesExist ) { - AddOpaqueRenderers( updateBufferIndex, - layer, - viewMatrix, - cameraAttachment, - transparentRenderablesExist, - stencilRenderablesExist, - disableDepthTest, - instruction, - sortingHelper, - tryReuseRenderList ); + AddColorRenderers( updateBufferIndex, + layer, + viewMatrix, + cameraAttachment, + stencilRenderablesExist, + instruction, + sortingHelper, + tryReuseRenderList ); } - 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, diff --git a/dali/internal/update/manager/prepare-render-instructions.h b/dali/internal/update/manager/prepare-render-instructions.h index b773752..d8e794f 100644 --- a/dali/internal/update/manager/prepare-render-instructions.h +++ b/dali/internal/update/manager/prepare-render-instructions.h @@ -58,13 +58,7 @@ struct RendererWithSortAttributes float zValue; // The zValue of the given renderer (either distance from camera, or a custom calculated value) }; -typedef std::vector< RendererWithSortAttributes > RenderItemSortingHelper; - -struct RendererSortingHelper -{ - RenderItemSortingHelper transparent; - RenderItemSortingHelper opaque; -}; +typedef std::vector< RendererWithSortAttributes > RendererSortingHelper; class RenderTask; class RenderInstructionContainer; diff --git a/dali/internal/update/manager/process-render-tasks.cpp b/dali/internal/update/manager/process-render-tasks.cpp index 366db13..478b58a 100644 --- a/dali/internal/update/manager/process-render-tasks.cpp +++ b/dali/internal/update/manager/process-render-tasks.cpp @@ -164,13 +164,9 @@ static bool AddRenderablesForTask( BufferIndex updateBufferIndex, { layer->overlayRenderables.push_back( renderable ); } - else if ( renderable->IsFullyOpaque( updateBufferIndex ) ) - { - layer->opaqueRenderables.push_back( renderable ); - } else { - layer->transparentRenderables.push_back( renderable ); + layer->colorRenderables.push_back( renderable ); } } } diff --git a/dali/internal/update/manager/update-algorithms.cpp b/dali/internal/update/manager/update-algorithms.cpp index 232621a..2e296dc 100644 --- a/dali/internal/update/manager/update-algorithms.cpp +++ b/dali/internal/update/manager/update-algorithms.cpp @@ -319,7 +319,7 @@ inline void AddRenderableToLayer( Layer& layer, { // The renderables are stored into the opaque list temporarily for PrepareRenderables() // step. The list is cleared by ProcessRenderTasks(). - layer.opaqueRenderables.push_back( &renderable ); + layer.colorRenderables.push_back( &renderable ); } /** diff --git a/dali/internal/update/nodes/scene-graph-layer.h b/dali/internal/update/nodes/scene-graph-layer.h index e414cc3..90789e4 100644 --- a/dali/internal/update/nodes/scene-graph-layer.h +++ b/dali/internal/update/nodes/scene-graph-layer.h @@ -199,8 +199,7 @@ private: public: // For update-algorithms RenderableAttachmentContainer stencilRenderables; - RenderableAttachmentContainer transparentRenderables; - RenderableAttachmentContainer opaqueRenderables; + RenderableAttachmentContainer colorRenderables; RenderableAttachmentContainer overlayRenderables; private: -- 2.7.4