[Tizen] Implement partial update accepted/tizen/unified/20190911.111620 submit/tizen/20190910.094904
authorJoogab Yun <joogab.yun@samsung.com>
Mon, 15 Apr 2019 07:28:30 +0000 (16:28 +0900)
committerJoogab Yun <joogab.yun@samsung.com>
Tue, 10 Sep 2019 09:10:58 +0000 (18:10 +0900)
1. It works when the DALI_PARTIAL_UPDATE_AVAILABLE environment variable is set.
2. Add Update Size Hint property
  - By default, it works with the size of the render item.
    If you set the UPDATE_SIZE_HINT property, the update size hint determines the update area.
   ex)
      Vector2 updateSizeHint = Vector2(width, height);
      mView1.SetProperty(Dali::DevelActor::Property::UPDATE_SIZE_HINT, updateSizeHint);

Change-Id: Ic008de12eb4b344004e3f6defa9eeb4a45e365a4

40 files changed:
automated-tests/src/dali/dali-test-suite-utils/test-application.cpp [changed mode: 0644->0755]
automated-tests/src/dali/dali-test-suite-utils/test-render-surface.cpp [changed mode: 0644->0755]
automated-tests/src/dali/dali-test-suite-utils/test-render-surface.h [changed mode: 0644->0755]
automated-tests/src/dali/utc-Dali-Actor.cpp [changed mode: 0644->0755]
dali/devel-api/actors/actor-devel.h [changed mode: 0644->0755]
dali/integration-api/core-enumerations.h [changed mode: 0644->0755]
dali/integration-api/core.cpp [changed mode: 0644->0755]
dali/integration-api/core.h [changed mode: 0644->0755]
dali/integration-api/render-surface.h [changed mode: 0644->0755]
dali/internal/common/core-impl.cpp [changed mode: 0644->0755]
dali/internal/common/core-impl.h [changed mode: 0644->0755]
dali/internal/event/actors/actor-impl.cpp [changed mode: 0644->0755]
dali/internal/event/actors/actor-impl.h
dali/internal/event/common/scene-impl.cpp [changed mode: 0644->0755]
dali/internal/event/rendering/frame-buffer-impl.cpp [changed mode: 0644->0755]
dali/internal/event/rendering/frame-buffer-impl.h [changed mode: 0644->0755]
dali/internal/render/common/render-algorithms.cpp [changed mode: 0644->0755]
dali/internal/render/common/render-algorithms.h [changed mode: 0644->0755]
dali/internal/render/common/render-item.cpp [changed mode: 0644->0755]
dali/internal/render/common/render-item.h [changed mode: 0644->0755]
dali/internal/render/common/render-list.h [changed mode: 0644->0755]
dali/internal/render/common/render-manager.cpp [changed mode: 0644->0755]
dali/internal/render/common/render-manager.h [changed mode: 0644->0755]
dali/internal/render/renderers/render-surface-frame-buffer.cpp [changed mode: 0644->0755]
dali/internal/render/renderers/render-surface-frame-buffer.h [changed mode: 0644->0755]
dali/internal/update/animation/scene-graph-animator.h [changed mode: 0644->0755]
dali/internal/update/common/property-owner-messages.h [changed mode: 0644->0755]
dali/internal/update/common/property-owner.cpp [changed mode: 0644->0755]
dali/internal/update/common/property-owner.h [changed mode: 0644->0755]
dali/internal/update/manager/render-instruction-processor.cpp [changed mode: 0644->0755]
dali/internal/update/manager/transform-manager.cpp [changed mode: 0644->0755]
dali/internal/update/manager/transform-manager.h [changed mode: 0644->0755]
dali/internal/update/manager/update-manager.cpp [changed mode: 0644->0755]
dali/internal/update/nodes/node-declarations.h [changed mode: 0644->0755]
dali/internal/update/nodes/node-messages.h [changed mode: 0644->0755]
dali/internal/update/nodes/node.cpp
dali/internal/update/nodes/node.h
dali/internal/update/nodes/scene-graph-layer.cpp
dali/internal/update/rendering/scene-graph-renderer.cpp [changed mode: 0644->0755]
dali/internal/update/rendering/scene-graph-renderer.h

old mode 100644 (file)
new mode 100755 (executable)
index 338b71f..8dbdc62
@@ -63,7 +63,8 @@ void TestApplication::CreateCore()
                                         mDataRetentionPolicy,
                                         Integration::RenderToFrameBuffer::FALSE,
                                         Integration::DepthBufferAvailable::TRUE,
-                                        Integration::StencilBufferAvailable::TRUE );
+                                        Integration::StencilBufferAvailable::TRUE,
+                                        Integration::PartialUpdateAvailable::FALSE );
 
   mCore->ContextCreated();
 
old mode 100644 (file)
new mode 100755 (executable)
index 066b37e..84381d3
@@ -117,4 +117,14 @@ Vector4 TestRenderSurface::GetBackgroundColor()
   return mBackgroundColor;
 }
 
+Rect<int32_t> TestRenderSurface::SetDamagedRect( const Rect<int32_t>& damagedRectArray )
+{
+  return damagedRectArray;
+}
+
+int32_t TestRenderSurface::GetBufferAge()
+{
+  return 0;
+}
+
 } // Namespace dali
old mode 100644 (file)
new mode 100755 (executable)
index be38d00..2fed827
@@ -137,6 +137,16 @@ public:
    */
   virtual Vector4 GetBackgroundColor();
 
+  /**
+   * @copydoc Dali::Integration::RenderSurface::SetDamagedRect
+   */
+  virtual Rect<int32_t> SetDamagedRect( const Rect<int32_t>& damagedRectArray );
+
+  /**
+   * @copydoc Dali::Integration::RenderSurface::GetBufferAge
+   */
+  virtual int32_t GetBufferAge();
+
 private:
 
   /**
old mode 100644 (file)
new mode 100755 (executable)
index 12cbecd..7ced69b
@@ -3284,6 +3284,7 @@ const PropertyStringIndex PROPERTY_TABLE[] =
   { "inheritPosition",          Actor::Property::INHERIT_POSITION,         Property::BOOLEAN     },
   { "clippingMode",             Actor::Property::CLIPPING_MODE,            Property::STRING      },
   { "opacity",                  DevelActor::Property::OPACITY,             Property::FLOAT       },
+  { "updateSizeHint",           DevelActor::Property::UPDATE_SIZE_HINT,    Property::VECTOR2     },
 };
 const unsigned int PROPERTY_TABLE_COUNT = sizeof( PROPERTY_TABLE ) / sizeof( PROPERTY_TABLE[0] );
 } // unnamed namespace
@@ -7196,6 +7197,36 @@ int utcDaliActorCulled(void)
   END_TEST;
 }
 
+int UtcDaliActorUpdateSizeHint(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Vector3 vector(100.0f, 100.0f, 0.0f);
+
+  DALI_TEST_CHECK(vector != actor.GetCurrentSize());
+
+  actor.SetSize(vector.x, vector.y);
+
+
+  Vector2 updateSizeHint = Vector2(150.f, 150.f);
+  actor.SetProperty(Dali::DevelActor::Property::UPDATE_SIZE_HINT, updateSizeHint);
+
+  // Flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+
+  Vector2 currentSizeHint = actor.GetProperty( Dali::DevelActor::Property::UPDATE_SIZE_HINT ).Get< Vector2 >();
+  DALI_TEST_EQUALS( currentSizeHint, updateSizeHint, Math::MACHINE_EPSILON_0, TEST_LOCATION );
+
+  // Flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  END_TEST;
+}
+
 int utcDaliEnsureRenderWhenRemovingLastRenderableActor(void)
 {
   TestApplication application;
old mode 100644 (file)
new mode 100755 (executable)
index ff521de..af3d4c5
@@ -128,6 +128,13 @@ enum Type
    * @note True means that the actor is out of the view frustum.
    */
   CULLED = INHERIT_LAYOUT_DIRECTION + 5,
+
+  /**
+   * @brief Sets the update size hint of the actor.
+   * @details Name "updateSizeHint", type Property::VECTOR2.
+   * @note When this value is set, the update area is determined by this value when a partial update.
+   */
+  UPDATE_SIZE_HINT = INHERIT_LAYOUT_DIRECTION + 6,
 };
 
 } // namespace Property
old mode 100644 (file)
new mode 100755 (executable)
index 24299f4..92ab037
@@ -56,6 +56,15 @@ enum class StencilBufferAvailable
   TRUE
 };
 
+/**
+ * @brief Enumerations to specify whether the partial update is available.
+ */
+enum class PartialUpdateAvailable
+{
+  FALSE = 0,
+  TRUE
+};
+
 } // namespace Integration
 
 } // namespace Dali
old mode 100644 (file)
new mode 100755 (executable)
index 1f664e4..f3bb7ad
@@ -43,7 +43,8 @@ Core* Core::New( RenderController& renderController,
                  ResourcePolicy::DataRetention policy,
                  RenderToFrameBuffer renderToFboEnabled,
                  DepthBufferAvailable depthBufferAvailable,
-                 StencilBufferAvailable stencilBufferAvailable )
+                 StencilBufferAvailable stencilBufferAvailable,
+                 PartialUpdateAvailable partialUpdateAvailable )
 {
   Core* instance = new Core;
   instance->mImpl = new Internal::Core( renderController,
@@ -54,7 +55,8 @@ Core* Core::New( RenderController& renderController,
                                         policy,
                                         renderToFboEnabled,
                                         depthBufferAvailable,
-                                        stencilBufferAvailable );
+                                        stencilBufferAvailable,
+                                        partialUpdateAvailable );
 
   return instance;
 }
old mode 100644 (file)
new mode 100755 (executable)
index 2e57a76..7ae6d62
@@ -232,6 +232,7 @@ public:
    * @param[in] renderToFboEnabled Whether rendering into the Frame Buffer Object is enabled.
    * @param[in] depthBufferAvailable Whether the depth buffer is available
    * @param[in] stencilBufferAvailable Whether the stencil buffer is available
+   * @param[in] partialUpdateAvailble whether the partial update is available
    * @return A newly allocated Core.
    */
   static Core* New( RenderController& renderController,
@@ -242,7 +243,8 @@ public:
                     ResourcePolicy::DataRetention policy,
                     RenderToFrameBuffer renderToFboEnabled,
                     DepthBufferAvailable depthBufferAvailable,
-                    StencilBufferAvailable stencilBufferAvailable );
+                    StencilBufferAvailable stencilBufferAvailable,
+                    PartialUpdateAvailable partialUpdateAvailable );
 
   /**
    * Non-virtual destructor. Core is not intended as a base class.
old mode 100644 (file)
new mode 100755 (executable)
index b0a3b37..6cb82c0
@@ -189,6 +189,18 @@ public:
    */
   virtual Integration::StencilBufferAvailable GetStencilBufferRequired() = 0;
 
+  /**
+   * @brief Sets currentframe updated/damaged rects
+   * @return
+   */
+  virtual Rect<int32_t> SetDamagedRect( const Rect<int32_t>& damagedRectArray ) = 0;
+
+  /**
+   * @brief Gets buffer age
+   * @return current buffer age
+   */
+  virtual int32_t GetBufferAge() = 0;
+
 private:
 
   /**
old mode 100644 (file)
new mode 100755 (executable)
index 75e373b..863c7e5
@@ -89,7 +89,8 @@ Core::Core( RenderController& renderController,
             ResourcePolicy::DataRetention dataRetentionPolicy,
             Integration::RenderToFrameBuffer renderToFboEnabled,
             Integration::DepthBufferAvailable depthBufferAvailable,
-            Integration::StencilBufferAvailable stencilBufferAvailable )
+            Integration::StencilBufferAvailable stencilBufferAvailable,
+            Integration::PartialUpdateAvailable partialUpdateAvailable )
 : mRenderController( renderController ),
   mPlatform(platform),
   mProcessingEvent(false),
@@ -109,7 +110,7 @@ Core::Core( RenderController& renderController,
 
   mRenderTaskProcessor = new SceneGraph::RenderTaskProcessor();
 
-  mRenderManager = RenderManager::New( glAbstraction, glSyncAbstraction, glContextHelperAbstraction, depthBufferAvailable, stencilBufferAvailable );
+  mRenderManager = RenderManager::New( glAbstraction, glSyncAbstraction, glContextHelperAbstraction, depthBufferAvailable, stencilBufferAvailable, partialUpdateAvailable );
 
   RenderQueue& renderQueue = mRenderManager->GetRenderQueue();
 
old mode 100644 (file)
new mode 100755 (executable)
index b37e454..6e02bb4
@@ -88,7 +88,8 @@ public:
         ResourcePolicy::DataRetention dataRetentionPolicy,
         Integration::RenderToFrameBuffer renderToFboEnabled,
         Integration::DepthBufferAvailable depthBufferAvailable,
-        Integration::StencilBufferAvailable stencilBufferAvailable );
+        Integration::StencilBufferAvailable stencilBufferAvailable,
+        Integration::PartialUpdateAvailable partialUpdateAvailable );
 
   /**
    * Destructor
old mode 100644 (file)
new mode 100755 (executable)
index 876182f..e57648f
@@ -214,6 +214,7 @@ DALI_PROPERTY( "opacity",                   FLOAT,    true,  true,  true,  Dali:
 DALI_PROPERTY( "screenPosition",            VECTOR2,  false, false, false, Dali::DevelActor::Property::SCREEN_POSITION )
 DALI_PROPERTY( "positionUsesAnchorPoint",   BOOLEAN,  true,  false, false, Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT )
 DALI_PROPERTY( "culled",                    BOOLEAN,  false, false, true, Dali::DevelActor::Property::CULLED )
+DALI_PROPERTY( "updateSizeHint",            VECTOR2,  true,  false, true, Dali::DevelActor::Property::UPDATE_SIZE_HINT )
 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX, ActorDefaultProperties )
 
 // Signals
@@ -2718,6 +2719,12 @@ void Actor::SetDefaultProperty( Property::Index index, const Property::Value& pr
       break;
     }
 
+    case Dali::DevelActor::Property::UPDATE_SIZE_HINT:
+    {
+      SetUpdateSizeHint( property.Get< Vector2 >() );
+      break;
+    }
+
     default:
     {
       // this can happen in the case of a non-animatable default property so just do nothing
@@ -3976,6 +3983,12 @@ bool Actor::GetCurrentPropertyValue( Property::Index index, Property::Value& val
       break;
     }
 
+    case Dali::DevelActor::Property::UPDATE_SIZE_HINT:
+    {
+      value = GetUpdateSizeHint();
+      break;
+    }
+
     default:
     {
       // Must be an event-side only property
@@ -4725,6 +4738,19 @@ float Actor::GetMaximumSize( Dimension::Type dimension ) const
   return FLT_MAX;  // Default
 }
 
+void Actor::SetUpdateSizeHint( const Vector2& updateSizeHint )
+{
+  // node is being used in a separate thread; queue a message to set the value & base value
+  SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mUpdateSizeHint, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, Vector3(updateSizeHint.width, updateSizeHint.height, 0.f ) );
+}
+
+Vector2 Actor::GetUpdateSizeHint() const
+{
+  // node is being used in a separate thread; copy the value from the previous update
+  Vector3 updateSizeHint = GetNode().GetUpdateSizeHint( GetEventThreadServices().GetEventBufferIndex() );
+  return Vector2( updateSizeHint.width, updateSizeHint.height );
+}
+
 Object* Actor::GetParentObject() const
 {
   return mParent;
index 53fe06a..05a22f5 100755 (executable)
@@ -1228,6 +1228,18 @@ public:
   float GetMaximumSize( Dimension::Type dimension ) const;
 
   /**
+   * @brief Sets the update size hint of an actor for partial update.
+   * @param [in] updateSizeHint The new updateSizeHint.
+   */
+  void SetUpdateSizeHint( const Vector2& updateSizeHint );
+
+  /**
+   * @brief Return the update size hint of actor
+   * @return Return the update size hint
+   */
+  Vector2 GetUpdateSizeHint() const;
+
+  /**
    * @copydoc Dali::Actor::AddRenderer()
    */
   uint32_t AddRenderer( Renderer& renderer );
old mode 100644 (file)
new mode 100755 (executable)
index 917f76a..82f5196
@@ -149,6 +149,10 @@ void Scene::Add(Actor& actor)
 void Scene::Remove(Actor& actor)
 {
   mRootLayer->Remove( actor );
+  if( mSurface )
+  {
+    mRenderTaskList->GetTask( 0u )->GetFrameBuffer()->SetPartialUpdateEnabled( false );
+  }
 }
 
 Size Scene::GetSize() const
old mode 100644 (file)
new mode 100755 (executable)
index 33afe35..fe94b5b
@@ -134,6 +134,15 @@ void FrameBuffer::MarkSurfaceAsInvalid()
   }
 }
 
+void FrameBuffer::SetPartialUpdateEnabled( bool value )
+{
+  if( mRenderObject->IsSurfaceBacked() )
+  {
+    SetFrameBufferPartialUpdateMessage( mEventThreadServices.GetUpdateManager(), static_cast<Render::SurfaceFrameBuffer*>( mRenderObject ), value );
+  }
+}
+
+
 FrameBuffer::~FrameBuffer()
 {
   if( EventThreadServices::IsCoreRunning() && mRenderObject )
old mode 100644 (file)
new mode 100755 (executable)
index 8484948..16c61f5
@@ -114,6 +114,12 @@ public:
    */
   void MarkSurfaceAsInvalid();
 
+  /**
+   * @brief Sets whether partial update is required for partial update
+   * @param[in] value whether partial update or not
+   */
+  void SetPartialUpdateEnabled( bool value );
+
 private: // implementation
 
   /**
old mode 100644 (file)
new mode 100755 (executable)
index a8d2162..610496d
@@ -415,7 +415,8 @@ inline void RenderAlgorithms::ProcessRenderList( const RenderList& renderList,
                                                  Integration::DepthBufferAvailable depthBufferAvailable,
                                                  Integration::StencilBufferAvailable stencilBufferAvailable,
                                                  Vector<GLuint>& boundTextures,
-                                                 int orientation )
+                                                 int orientation,
+                                                 Dali::ClippingBox& scissorBox )
 {
   DALI_PRINT_RENDER_LIST( renderList );
 
@@ -474,6 +475,12 @@ inline void RenderAlgorithms::ProcessRenderList( const RenderList& renderList,
     mScissorStack.push_back( layerScissorBox );
     mHasLayerScissor = true;
   }
+  else if ( !scissorBox.IsEmpty() )
+  {
+    context.SetScissorTest( true );
+    context.Scissor( scissorBox.x, scissorBox.y, scissorBox.width, scissorBox.height );
+    mScissorStack.push_back( scissorBox );
+  }
   else
   {
     // We are not performing a layer clip. Add the viewport as the root scissor rectangle.
@@ -522,7 +529,8 @@ void RenderAlgorithms::ProcessRenderInstruction( const RenderInstruction& instru
                                                  Integration::DepthBufferAvailable depthBufferAvailable,
                                                  Integration::StencilBufferAvailable stencilBufferAvailable,
                                                  Vector<GLuint>& boundTextures,
-                                                 int orientation )
+                                                 int orientation,
+                                                 Dali::ClippingBox& scissorBox )
 {
   DALI_PRINT_RENDER_INSTRUCTION( instruction, bufferIndex );
 
@@ -552,7 +560,8 @@ void RenderAlgorithms::ProcessRenderInstruction( const RenderInstruction& instru
                             depthBufferAvailable,
                             stencilBufferAvailable,
                             boundTextures,
-                            orientation );
+                            orientation,
+                            scissorBox );
       }
     }
   }
old mode 100644 (file)
new mode 100755 (executable)
index 98c219b..bb5e066
@@ -59,6 +59,7 @@ class RenderAlgorithms
      * @param[in] depthBufferAvailable   Whether the depth buffer is available
      * @param[in] stencilBufferAvailable Whether the stencil buffer is available
      * @param[in] boundTextures          The textures bound for rendering
+     * @param[in] scissorBox             The damaged rect for partial update
      */
     void ProcessRenderInstruction( const SceneGraph::RenderInstruction& instruction,
                                    Context& context,
@@ -66,7 +67,8 @@ class RenderAlgorithms
                                    Integration::DepthBufferAvailable depthBufferAvailable,
                                    Integration::StencilBufferAvailable stencilBufferAvailable,
                                    Vector<GLuint>& boundTextures,
-                                   int orientation);
+                                   int orientation,
+                                   Dali::ClippingBox& scissorBox );
 
   private:
 
@@ -118,6 +120,7 @@ class RenderAlgorithms
      * @param[in] depthBufferAvailable   Whether the depth buffer is available
      * @param[in] stencilBufferAvailable Whether the stencil buffer is available
      * @param[in] boundTextures          The textures bound for rendering
+     * @param[in] scissorBox             The damaged rect for partial update
      */
     inline void ProcessRenderList( const Dali::Internal::SceneGraph::RenderList& renderList,
                                    Context& context,
@@ -127,7 +130,8 @@ class RenderAlgorithms
                                    Integration::DepthBufferAvailable depthBufferAvailable,
                                    Integration::StencilBufferAvailable stencilBufferAvailable,
                                    Vector<GLuint>& boundTextures,
-                                   int orientation );
+                                   int orientation,
+                                   Dali::ClippingBox& scissorBox );
 
     // Prevent copying:
     RenderAlgorithms( RenderAlgorithms& rhs );
old mode 100644 (file)
new mode 100755 (executable)
index d47f808..e562036
@@ -46,11 +46,13 @@ RenderItem::RenderItem()
 : mModelMatrix( false ),
   mModelViewMatrix( false ),
   mSize(),
+  mUpdateSizeHint(),
   mRenderer( NULL ),
   mNode( NULL ),
   mTextureSet( NULL ),
   mDepthIndex( 0 ),
-  mIsOpaque( true )
+  mIsOpaque( true ),
+  mPartialUpdateEnabled( false )
 {
 }
 
@@ -59,11 +61,22 @@ RenderItem::~RenderItem()
 }
 
 
-ClippingBox RenderItem::CalculateViewportSpaceAABB( const int viewportWidth, const int viewportHeight ) const
+ClippingBox RenderItem::CalculateViewportSpaceAABB( const int viewportWidth, const int viewportHeight, const bool useUpdateSizeHint ) const
 {
   // Calculate extent vector of the AABB:
-  const float halfActorX = mSize.x * 0.5f;
-  const float halfActorY = mSize.y * 0.5f;
+  float halfActorX;
+  float halfActorY;
+  if( useUpdateSizeHint )
+  {
+    halfActorX = mUpdateSizeHint.x * 0.5f;
+    halfActorY = mUpdateSizeHint.y * 0.5f;
+  }
+  else
+  {
+    halfActorX = mSize.x * 0.5f;
+    halfActorY = mSize.y * 0.5f;
+  }
+
 
   // To transform the actor bounds to screen-space, We do a fast, 2D version of a matrix multiply optimized for 2D quads.
   // This reduces float multiplications from 64 (16 * 4) to 12 (4 * 3).
old mode 100644 (file)
new mode 100755 (executable)
index 7dbd3fb..96a6130
@@ -65,9 +65,10 @@ struct RenderItem
    *
    * @param[in]    viewportWidth     The width of the viewport to calculate for
    * @param[in]    viewportHeight    The height of the viewport to calculate for
+   * @param[in]    useUpdateSizeHint Set to true if you want to use update size hint instead of item size
    * @return                         The AABB coordinates in viewport-space (x, y, width, height)
    */
-  ClippingBox CalculateViewportSpaceAABB( const int viewportWidth, const int viewportHeight ) const;
+  ClippingBox CalculateViewportSpaceAABB( const int viewportWidth, const int viewportHeight, const bool useUpdateSizeHint = false ) const;
 
   /**
    * Overriden delete operator.
@@ -79,11 +80,13 @@ struct RenderItem
   Matrix            mModelMatrix;
   Matrix            mModelViewMatrix;
   Vector3           mSize;
+  Vector3           mUpdateSizeHint;
   Render::Renderer* mRenderer;
   Node*             mNode;
   const void*       mTextureSet;        //< Used for sorting only
   int               mDepthIndex;
   bool              mIsOpaque:1;
+  bool              mPartialUpdateEnabled:1;
 
 private:
 
old mode 100644 (file)
new mode 100755 (executable)
index 41af19f..90925eb
@@ -63,7 +63,8 @@ public:
   : mNextFree( 0 ),
     mClippingBox( NULL ),
     mSourceLayer( NULL ),
-    mHasColorRenderItems( false )
+    mHasColorRenderItems( false ),
+    mPartialUpdateEnabled( false )
   {
   }
 
@@ -258,6 +259,24 @@ public:
     return mHasColorRenderItems;
   }
 
+  /**
+   * Enable/Disable Partial update dirty flag
+   * @param[in] true to mark dirty else false
+   */
+  void SetPartialUpdateEnabled( bool value )
+  {
+    mPartialUpdateEnabled = value;
+  }
+
+  /**
+   * Get Partial update dirty flag
+   * @return true if dirty else false
+   */
+  bool IsPartialUpdateEnabled() const
+  {
+    return mPartialUpdateEnabled;
+  }
+
 private:
 
   /*
@@ -272,6 +291,7 @@ private:
   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
+  bool         mPartialUpdateEnabled : 1; //< True if partial update is needed.
 
 };
 
old mode 100644 (file)
new mode 100755 (executable)
index d9c2ea0..986e430
@@ -62,6 +62,37 @@ Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_REN
 } // unnamed namespace
 #endif
 
+namespace
+{
+const float partialUpdateRatio = 0.8f; // If the partial update area exceeds 80%, change to full update.
+
+/**
+ * @brief Find the intersection of two AABB rectangles.
+ * This is a logical AND operation. IE. The intersection is the area overlapped by both rectangles.
+ * @param[in]     aabbA                  Rectangle A
+ * @param[in]     aabbB                  Rectangle B
+ * @return                               The intersection of rectangle A & B (result is a rectangle)
+ */
+inline ClippingBox IntersectAABB( const ClippingBox& aabbA, const ClippingBox& aabbB )
+{
+  ClippingBox intersectionBox;
+
+  // First calculate the largest starting positions in X and Y.
+  intersectionBox.x = std::max( aabbA.x, aabbB.x );
+  intersectionBox.y = std::max( aabbA.y, aabbB.y );
+
+  // Now calculate the smallest ending positions, and take the largest starting
+  // positions from the result, to get the width and height respectively.
+  // If the two boxes do not intersect at all, then we need a 0 width and height clipping area.
+  // We use max here to clamp both width and height to >= 0 for this use-case.
+  intersectionBox.width =  std::max( std::min( aabbA.x + aabbA.width,  aabbB.x + aabbB.width  ) - intersectionBox.x, 0 );
+  intersectionBox.height = std::max( std::min( aabbA.y + aabbA.height, aabbB.y + aabbB.height ) - intersectionBox.y, 0 );
+
+  return intersectionBox;
+}
+
+}
+
 /**
  * Structure to contain internal data
  */
@@ -71,7 +102,8 @@ struct RenderManager::Impl
         Integration::GlSyncAbstraction& glSyncAbstraction,
         Integration::GlContextHelperAbstraction& glContextHelperAbstraction,
         Integration::DepthBufferAvailable depthBufferAvailableParam,
-        Integration::StencilBufferAvailable stencilBufferAvailableParam )
+        Integration::StencilBufferAvailable stencilBufferAvailableParam,
+        Integration::PartialUpdateAvailable partialUpdateAvailableParam )
   : context( glAbstraction, &surfaceContextContainer ),
     currentContext( &context ),
     glAbstraction( glAbstraction ),
@@ -92,6 +124,7 @@ struct RenderManager::Impl
     programController( glAbstraction ),
     depthBufferAvailable( depthBufferAvailableParam ),
     stencilBufferAvailable( stencilBufferAvailableParam ),
+    partialUpdateAvailable( partialUpdateAvailableParam ),
     defaultSurfaceOrientation( 0 )
   {
      // Create thread pool with just one thread ( there may be a need to create more threads in the future ).
@@ -171,6 +204,7 @@ struct RenderManager::Impl
 
   Integration::DepthBufferAvailable         depthBufferAvailable;     ///< Whether the depth buffer is available
   Integration::StencilBufferAvailable       stencilBufferAvailable;   ///< Whether the stencil buffer is available
+  Integration::PartialUpdateAvailable       partialUpdateAvailable;   ///< Whether the partial update is available
 
   std::unique_ptr<Dali::ThreadPool>         threadPool;               ///< The thread pool
   Vector<GLuint>                            boundTextures;            ///< The textures bound for rendering
@@ -183,14 +217,16 @@ RenderManager* RenderManager::New( Integration::GlAbstraction& glAbstraction,
                                    Integration::GlSyncAbstraction& glSyncAbstraction,
                                    Integration::GlContextHelperAbstraction& glContextHelperAbstraction,
                                    Integration::DepthBufferAvailable depthBufferAvailable,
-                                   Integration::StencilBufferAvailable stencilBufferAvailable )
+                                   Integration::StencilBufferAvailable stencilBufferAvailable,
+                                   Integration::PartialUpdateAvailable partialUpdateAvailable )
 {
   RenderManager* manager = new RenderManager;
   manager->mImpl = new Impl( glAbstraction,
                              glSyncAbstraction,
                              glContextHelperAbstraction,
                              depthBufferAvailable,
-                             stencilBufferAvailable );
+                             stencilBufferAvailable,
+                             partialUpdateAvailable );
   return manager;
 }
 
@@ -592,10 +628,87 @@ void RenderManager::Render( Integration::RenderStatus& status, bool forceClear )
   DALI_PRINT_RENDER_END();
 }
 
+bool GetDamagedRect( Rect<int32_t> &viewportRect, RenderInstruction& instruction, Rect<int32_t> &damagedRect )
+{
+  // merge bounding
+  int dx1 = viewportRect.width, dx2 = 0, dy1 = viewportRect.height, dy2 = 0;
+  int checkWidth = static_cast<int>( static_cast<float>( viewportRect.width ) * partialUpdateRatio );
+  int checkHeight = static_cast<int>( static_cast<float>( viewportRect.height ) * partialUpdateRatio );
+  Rect<int32_t> screenRect;
+
+  bool isPartialUpdate = false;
+
+  const RenderListContainer::SizeType renderListCount = instruction.RenderListCount();
+  // Iterate through each render list.
+
+  for( RenderListContainer::SizeType index = 0; index < renderListCount; ++index )
+  {
+    const RenderList* renderList = instruction.GetRenderList( index );
+
+    if( renderList && !renderList->IsEmpty() && renderList->IsPartialUpdateEnabled() )
+    {
+      const std::size_t itemCount = renderList->Count();
+      for( uint32_t itemIndex = 0u; itemIndex < itemCount; ++itemIndex )
+      {
+        const RenderItem& item = renderList->GetItem( itemIndex );
+
+        if( item.mPartialUpdateEnabled )
+        {
+          isPartialUpdate = true;
+
+          screenRect = item.CalculateViewportSpaceAABB( viewportRect.width, viewportRect.height, true );
+
+          dx1 = std::min( screenRect.x, dx1 );
+          dx2 = std::max( screenRect.x + screenRect.width, dx2);
+          dy1 = std::min( screenRect.y, dy1 );
+          dy2 = std::max( screenRect.y + screenRect.height, dy2 );
+
+          if( ( dx2 - dx1 )  > checkWidth && ( dy2 - dy1 ) > checkHeight )
+          {
+            return false;
+          }
+        }
+      }
+    }
+  }
+
+  if( isPartialUpdate )
+  {
+    if( dx1 < 0.0f )
+    {
+      dx1 = 0.0f;
+    }
+    if( dy1 < 0.0f )
+    {
+      dy1 = 0.0f;
+    }
+    if( dx2 > viewportRect.width )
+    {
+      dx2 = viewportRect.width;
+    }
+    if( dy2 > viewportRect.height )
+    {
+      dy2 = viewportRect.height;
+    }
+
+    damagedRect.x = dx1;
+    damagedRect.y = dy1;
+    damagedRect.width = dx2 - dx1;
+    damagedRect.height = dy2 - dy1;
+  }
+
+  return isPartialUpdate;
+}
+
 void RenderManager::DoRender( RenderInstruction& instruction )
 {
   Rect<int32_t> viewportRect;
   Vector4   clearColor;
+  bool isPartialUpdate = false;
+  Rect<int32_t> damagedRect;
+  Rect<int32_t> mergedRect;
+  Dali::ClippingBox scissorBox;
+  Dali::ClippingBox intersectRect;
 
   if ( instruction.mIsClearColorSet )
   {
@@ -611,6 +724,7 @@ void RenderManager::DoRender( RenderInstruction& instruction )
   Vector4 backgroundColor = mImpl->backgroundColor;
   Integration::DepthBufferAvailable depthBufferAvailable = mImpl->depthBufferAvailable;
   Integration::StencilBufferAvailable stencilBufferAvailable = mImpl->stencilBufferAvailable;
+  Integration::PartialUpdateAvailable partialUpdateAvailable = mImpl->partialUpdateAvailable;
 
   Render::SurfaceFrameBuffer* surfaceFrameBuffer = nullptr;
   if ( instruction.mFrameBuffer != 0 )
@@ -676,25 +790,64 @@ void RenderManager::DoRender( RenderInstruction& instruction )
     mImpl->currentContext->BindFramebuffer( GL_FRAMEBUFFER, 0u );
   }
 
+
+  if( surfaceFrameBuffer &&
+      partialUpdateAvailable == Integration::PartialUpdateAvailable::TRUE )
+  {
+    const RenderListContainer::SizeType renderListCount = instruction.RenderListCount();
+    // Iterate through each render list.
+    if( surfaceFrameBuffer->IsPartialUpdateEnabled() )
+    {
+      isPartialUpdate = GetDamagedRect( surfaceRect, instruction, damagedRect ) ;
+    }
+
+    if( !isPartialUpdate )
+    {
+      damagedRect = surfaceRect;
+    }
+
+    mergedRect = surfaceFrameBuffer->SetDamagedRect( damagedRect );
+
+    if( mergedRect.IsEmpty() )
+    {
+      isPartialUpdate = false;
+    }
+    else
+    {
+      scissorBox.x = mergedRect.x;
+      scissorBox.y = mergedRect.y;
+      scissorBox.width = mergedRect.width;
+      scissorBox.height = mergedRect.height;
+    }
+  }
+
   if ( surfaceFrameBuffer )
   {
-    mImpl->currentContext->Viewport( surfaceRect.x,
-                              surfaceRect.y,
-                              surfaceRect.width,
-                              surfaceRect.height );
+      mImpl->currentContext->Viewport( surfaceRect.x,
+                                surfaceRect.y,
+                                surfaceRect.width,
+                                surfaceRect.height );
+
 
-    mImpl->currentContext->ClearColor( backgroundColor.r,
-                                backgroundColor.g,
-                                backgroundColor.b,
-                                backgroundColor.a );
+      mImpl->currentContext->ClearColor( backgroundColor.r,
+                                  backgroundColor.g,
+                                  backgroundColor.b,
+                                  backgroundColor.a );
   }
 
   // Clear the entire color, depth and stencil buffers for the default framebuffer, if required.
   // It is important to clear all 3 buffers when they are being used, for performance on deferred renderers
   // e.g. previously when the depth & stencil buffers were NOT cleared, it caused the DDK to exceed a "vertex count limit",
   // and then stall. That problem is only noticeable when rendering a large number of vertices per frame.
-
-  mImpl->currentContext->SetScissorTest( false );
+  if( isPartialUpdate )
+  {
+    mImpl->currentContext->SetScissorTest( true );
+    mImpl->currentContext->Scissor( scissorBox.x, scissorBox.y, scissorBox.width, scissorBox.height );
+  }
+  else
+  {
+    mImpl->currentContext->SetScissorTest( false );
+  }
 
   GLbitfield clearMask = GL_COLOR_BUFFER_BIT;
 
@@ -715,6 +868,12 @@ void RenderManager::DoRender( RenderInstruction& instruction )
 
   mImpl->currentContext->Clear( clearMask, Context::FORCE_CLEAR );
 
+  if( isPartialUpdate )
+  {
+    mImpl->currentContext->SetScissorTest( false );
+  }
+
+
   if( !instruction.mIgnoreRenderToFbo && ( instruction.mFrameBuffer != 0 ) )
   {
     if ( instruction.mFrameBuffer->IsSurfaceBacked() ) // Surface rendering
@@ -786,7 +945,15 @@ void RenderManager::DoRender( RenderInstruction& instruction )
 
     // Clear the viewport area only
     mImpl->currentContext->SetScissorTest( true );
-    mImpl->currentContext->Scissor( viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height );
+    if( isPartialUpdate )
+    {
+      intersectRect = IntersectAABB( scissorBox, viewportRect );
+      mImpl->currentContext->Scissor( intersectRect.x, intersectRect.y, intersectRect.width, intersectRect.height );
+    }
+    else
+    {
+      mImpl->currentContext->Scissor( viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height );
+    }
     mImpl->currentContext->ColorMask( true );
     mImpl->currentContext->Clear( GL_COLOR_BUFFER_BIT , Context::CHECK_CACHED_VALUES );
     mImpl->currentContext->SetScissorTest( false );
@@ -802,7 +969,8 @@ void RenderManager::DoRender( RenderInstruction& instruction )
       depthBufferAvailable,
       stencilBufferAvailable,
       mImpl->boundTextures,
-      surfaceOrientation );
+      surfaceOrientation,
+      scissorBox );
 
   // Synchronise the FBO/Texture access when there are multiple contexts
   if ( mImpl->currentContext->IsSurfacelessContextSupported() )
old mode 100644 (file)
new mode 100755 (executable)
index 248c9fd..3d064b2
@@ -83,7 +83,8 @@ public:
                              Integration::GlSyncAbstraction& glSyncAbstraction,
                              Integration::GlContextHelperAbstraction& glContextHelperAbstraction,
                              Integration::DepthBufferAvailable depthBufferAvailable,
-                             Integration::StencilBufferAvailable stencilBufferAvailable );
+                             Integration::StencilBufferAvailable stencilBufferAvailable,
+                             Integration::PartialUpdateAvailable partialUpdateAvailable );
 
   /**
    * Non-virtual destructor; not intended as a base class
old mode 100644 (file)
new mode 100755 (executable)
index 7154ff6..babd67f
@@ -35,7 +35,9 @@ SurfaceFrameBuffer::SurfaceFrameBuffer( Integration::RenderSurface* surface )
   mHeight( mSurface->GetPositionSize().height ),
   mBackgroundColor( 0.f, 0.f, 0.f, 1.f ),
   mSizeChanged( false ),
-  mIsSurfaceInvalid( false )
+  mBackgroundColorChanged( false ),
+  mIsSurfaceInvalid( false ),
+  mPartialUpdateEnabled( true )
 {
 }
 
@@ -104,6 +106,18 @@ void SurfaceFrameBuffer::PostRender()
   }
 
   mSizeChanged = false;
+  mBackgroundColorChanged = false;
+  mPartialUpdateEnabled = true;
+}
+
+Rect<int32_t> SurfaceFrameBuffer::SetDamagedRect( const Rect<int32_t>& damagedRect )
+{
+  Rect<int32_t> ret;
+  if ( IsSurfaceValid() )
+  {
+    ret = mSurface->SetDamagedRect( damagedRect );
+  }
+  return ret;
 }
 
 Context* SurfaceFrameBuffer::GetContext()
@@ -134,6 +148,7 @@ void SurfaceFrameBuffer::SetSize( uint32_t width, uint32_t height )
 void SurfaceFrameBuffer::SetBackgroundColor( const Vector4& color )
 {
   mBackgroundColor = color;
+  mBackgroundColorChanged = true;
 }
 
 bool SurfaceFrameBuffer::IsSurfaceValid() const
@@ -141,6 +156,21 @@ bool SurfaceFrameBuffer::IsSurfaceValid() const
   return mSurface && !mIsSurfaceInvalid;
 }
 
+bool SurfaceFrameBuffer::IsPartialUpdateEnabled() const
+{
+  bool ret = false;
+  if ( IsSurfaceValid() )
+  {
+    ret = mSurface->GetBufferAge() && ( mPartialUpdateEnabled && !( mSizeChanged || mBackgroundColorChanged ) );
+  }
+  return ret;
+}
+
+void SurfaceFrameBuffer::SetPartialUpdateEnabled( bool value )
+{
+  mPartialUpdateEnabled = value;
+}
+
 } //Render
 
 } //Internal
old mode 100644 (file)
new mode 100755 (executable)
index edd667d..fa71289
@@ -135,6 +135,24 @@ public:
    */
   Vector4 GetBackgroundColor();
 
+  /**
+   * @brief Sets currentframe updated/damaged rects
+   * @return merged update rects
+   */
+  Rect<int32_t> SetDamagedRect( const Rect<int32_t>& damagedRect );
+
+  /**
+   * @brief Gets whether partial update is required for partial update
+   * @return whether partial update or not
+   */
+  bool IsPartialUpdateEnabled() const;
+
+  /**
+   * @brief Sets whether partial update is required for partial update
+   * @param[in] value whether partial update or not
+   */
+  void SetPartialUpdateEnabled( bool value );
+
 private:
 
   Integration::RenderSurface* mSurface;   ///< The render surface
@@ -144,7 +162,9 @@ private:
   uint32_t                    mHeight;
   Vector4                     mBackgroundColor;
   bool                        mSizeChanged;
+  bool                        mBackgroundColorChanged;
   std::atomic<bool>           mIsSurfaceInvalid; ///< This is set only from the event thread and read only from the render thread
+  bool                        mPartialUpdateEnabled; ///< This value is whether partial update is required
 };
 
 // Messages for FrameBuffer
@@ -170,6 +190,17 @@ inline void SetFrameBufferBackgroundColorMessage( SceneGraph::UpdateManager& upd
   new (slot) LocalType( surfaceFrameBuffer, &SurfaceFrameBuffer::SetBackgroundColor, color );
 }
 
+inline void SetFrameBufferPartialUpdateMessage( SceneGraph::UpdateManager& updateManager, SurfaceFrameBuffer* surfaceFrameBuffer, bool value )
+{
+  typedef MessageValue1< SurfaceFrameBuffer, bool > LocalType;
+
+  // Reserve some memory inside the message queue
+  uint32_t* slot = updateManager.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( surfaceFrameBuffer, &SurfaceFrameBuffer::SetPartialUpdateEnabled, value );
+}
+
 } // namespace Render
 
 } // namespace Internal
old mode 100644 (file)
new mode 100755 (executable)
index 0b3ff50..cbf0842
@@ -519,6 +519,11 @@ public:
       progress = SetProgress( progress );
     }
 
+    if( mPropertyOwner )
+    {
+      mPropertyOwner->SetPropertyDirty( true );
+    }
+
     float alpha = ApplyAlphaFunction( progress );
 
     // PropertyType specific part
old mode 100644 (file)
new mode 100755 (executable)
index 1e31299..8668e4e
@@ -108,6 +108,7 @@ public:
    */
   virtual void Process( BufferIndex updateBufferIndex )
   {
+    mSceneObject->SetPropertyDirty( true );
     (mProperty->*mMemberFunction)( updateBufferIndex, mParam );
   }
 
@@ -187,6 +188,7 @@ public:
    */
   virtual void Process( BufferIndex updateBufferIndex )
   {
+    mSceneObject->SetPropertyDirty( true );
     (mProperty->*mMemberFunction)( updateBufferIndex, mParam );
   }
 
old mode 100644 (file)
new mode 100755 (executable)
index fb655e3..81ca85c
@@ -171,7 +171,15 @@ void PropertyOwner::RemoveUniformMapObserver( UniformMap::Observer& observer )
   mUniformMaps.RemoveObserver( observer );
 }
 
+void PropertyOwner::SetPropertyDirty( bool value )
+{
+  mPropertyDirty = value;
+}
 
+bool PropertyOwner::IsPropertyDirty() const
+{
+  return mPropertyDirty;
+}
 
 } // namespace SceneGraph
 
old mode 100644 (file)
new mode 100755 (executable)
index 843a19b..637d82b
@@ -206,6 +206,18 @@ public:
    */
   void RemoveUniformMapObserver( UniformMap::Observer& observer );
 
+  /**
+   * Set whether property has changed to run following a render.
+   * @param[in] value Set to true if the property has changed
+   */
+  virtual void SetPropertyDirty( bool value );
+
+  /**
+   * Query the property status following rendering of a frame.
+   * @return True if the property has changed
+   */
+  virtual bool IsPropertyDirty() const;
+
 
 protected:
 
@@ -226,6 +238,7 @@ protected:
 
   OwnedPropertyContainer mCustomProperties; ///< Properties provided with InstallCustomProperty()
   UniformMap mUniformMaps; ///< Container of owned uniform maps
+  bool mPropertyDirty:1; ///< Required for marking it dirty in case of partial update.
 
 private:
 
old mode 100644 (file)
new mode 100755 (executable)
index 204a472..a76632e
@@ -33,6 +33,7 @@
 #include <dali/internal/render/renderers/render-renderer.h>
 #include <dali/internal/render/renderers/render-property-buffer.h>
 #include <dali/internal/update/nodes/scene-graph-layer.h>
+#include <dali/internal/common/math.h>
 
 namespace
 {
@@ -161,8 +162,8 @@ inline void AddRendererToRenderList( BufferIndex updateBufferIndex,
 {
   bool inside( true );
   Node* node = renderable.mNode;
-
-  if( cull && renderable.mRenderer && !renderable.mRenderer->GetShader().HintEnabled( Dali::Shader::Hint::MODIFIES_GEOMETRY ) )
+  bool isModifiesGeometryHint = false;
+  if( cull && renderable.mRenderer && !( isModifiesGeometryHint = renderable.mRenderer->GetShader().HintEnabled( Dali::Shader::Hint::MODIFIES_GEOMETRY ) ) )
   {
     const Vector4& boundingSphere = node->GetBoundingSphere();
     inside = ( boundingSphere.w > Math::MACHINE_EPSILON_1000 ) &&
@@ -180,17 +181,27 @@ inline void AddRendererToRenderList( BufferIndex updateBufferIndex,
       item.mNode = renderable.mNode;
       item.mIsOpaque = ( opacityType == Renderer::OPAQUE );
       item.mDepthIndex = 0;
+      item.mPartialUpdateEnabled = false;
 
-      if(!isLayer3d)
+      if( !isLayer3d )
       {
         item.mDepthIndex = renderable.mNode->GetDepthIndex();
       }
+      if( isLayer3d || isModifiesGeometryHint )
+      {
+        renderList.SetPartialUpdateEnabled( false );
+      }
 
       if( DALI_LIKELY( renderable.mRenderer ) )
       {
         item.mRenderer =   &renderable.mRenderer->GetRenderer();
         item.mTextureSet =  renderable.mRenderer->GetTextures();
         item.mDepthIndex += renderable.mRenderer->GetDepthIndex();
+
+        if( FaceCullingMode::NONE != renderable.mRenderer->GetFaceCullingMode() )
+        {
+          renderList.SetPartialUpdateEnabled( false );
+        }
       }
       else
       {
@@ -201,13 +212,27 @@ inline void AddRendererToRenderList( BufferIndex updateBufferIndex,
       node->GetWorldMatrixAndSize( item.mModelMatrix, item.mSize );
 
       Matrix::Multiply( item.mModelViewMatrix, item.mModelMatrix, viewMatrix );
-    }
 
-     node->SetCulled( updateBufferIndex, false );
+      if( DALI_LIKELY( item.mRenderer ) && renderList.IsPartialUpdateEnabled() )
+      {
+        if( node->IsPropertyDirty() || node->IsComponentChanged() )
+        {
+          item.mPartialUpdateEnabled = true;
+
+          item.mUpdateSizeHint = item.mSize;
+          Vector3 updateSizeHint = node->GetUpdateSizeHint( updateBufferIndex );
+          if( updateSizeHint != Vector3::ZERO )
+          {
+            item.mUpdateSizeHint = updateSizeHint;
+          }
+        }
+      }
+    }
+    node->SetCulled( updateBufferIndex, false );
   }
   else
   {
-     node->SetCulled( updateBufferIndex, true );
+    node->SetCulled( updateBufferIndex, true );
   }
 }
 
@@ -434,6 +459,10 @@ void RenderInstructionProcessor::Prepare( BufferIndex updateBufferIndex,
       if( !SetupRenderList( renderables, layer, instruction, tryReuseRenderList, &renderList ) )
       {
         renderList->SetHasColorRenderItems( true );
+        if( !isLayer3D )
+        {
+          renderList->SetPartialUpdateEnabled( true );
+        }
         AddRenderersToRenderList( updateBufferIndex,
                                   *renderList,
                                   renderables,
@@ -456,6 +485,10 @@ void RenderInstructionProcessor::Prepare( BufferIndex updateBufferIndex,
       if( !SetupRenderList( renderables, layer, instruction, tryReuseRenderList, &renderList ) )
       {
         renderList->SetHasColorRenderItems( false );
+        if( !isLayer3D )
+        {
+          renderList->SetPartialUpdateEnabled( true );
+        }
         AddRenderersToRenderList( updateBufferIndex,
                                   *renderList,
                                   renderables,
old mode 100644 (file)
new mode 100755 (executable)
index c2cc4bb..651d230
@@ -106,6 +106,10 @@ TransformId TransformManager::CreateTransform()
     mSizeBase.PushBack(Vector3(0.0f,0.0f,0.0f));
     mComponentDirty.PushBack(false);
     mLocalMatrixDirty.PushBack(false);
+    mComponentChanged.PushBack(false);
+    mPrevWorld.PushBack(Matrix::IDENTITY);
+    mUpdateSizeHint.PushBack(Vector3(0.0f,0.0f,0.0f));
+    mUpdateSizeHintBase.PushBack(Vector3(0.0f,0.0f,0.0f));
   }
   else
   {
@@ -123,6 +127,10 @@ TransformId TransformManager::CreateTransform()
     mSizeBase[mComponentCount] = Vector3(0.0f,0.0f,0.0f);
     mComponentDirty[mComponentCount] = false;
     mLocalMatrixDirty[mComponentCount] = false;
+    mComponentChanged[mComponentCount] = false;
+    mPrevWorld[mComponentCount].SetIdentity();
+    mUpdateSizeHint[mComponentCount] = Vector3(0.0f,0.0f,0.0f);
+    mUpdateSizeHintBase[mComponentCount] = Vector3(0.0f,0.0f,0.0f);
   }
 
   mComponentCount++;
@@ -146,6 +154,10 @@ void TransformManager::RemoveTransform(TransformId id)
   mComponentDirty[index] = mComponentDirty[mComponentCount];
   mLocalMatrixDirty[index] = mLocalMatrixDirty[mComponentCount];
   mBoundingSpheres[index] = mBoundingSpheres[mComponentCount];
+  mComponentChanged[index] = mComponentChanged[mComponentCount];
+  mPrevWorld[index] = mPrevWorld[mComponentCount];
+  mUpdateSizeHint[index] = mUpdateSizeHint[mComponentCount];
+  mUpdateSizeHintBase[index] = mUpdateSizeHintBase[mComponentCount];
 
   TransformId lastItemId = mComponentId[mComponentCount];
   mIds[ lastItemId ] = index;
@@ -215,7 +227,6 @@ void TransformManager::SetInheritOrientation( TransformId id, bool inherit )
   {
     mInheritanceMode[ index ] &= ~INHERIT_ORIENTATION;
   }
-
   mComponentDirty[index] = true;
 }
 
@@ -226,6 +237,7 @@ void TransformManager::ResetToBaseValue()
     memcpy( &mTxComponentAnimatable[0], &mTxComponentAnimatableBaseValue[0], sizeof(TransformComponentAnimatable)*mComponentCount );
     memcpy( &mSize[0], &mSizeBase[0], sizeof(Vector3)*mComponentCount );
     memset( &mLocalMatrixDirty[0], false, sizeof(bool)*mComponentCount );
+    memcpy( &mUpdateSizeHint[0], &mUpdateSizeHintBase[0], sizeof(Vector3)*mComponentCount );
   }
 }
 
@@ -246,6 +258,8 @@ void TransformManager::Update()
   const Vector3 topLeft( 0.0f, 0.0f, 0.5f );
   for( unsigned int i(0); i<mComponentCount; ++i )
   {
+    mPrevWorld[i] = mWorld[i];
+
     if( DALI_LIKELY( mInheritanceMode[i] != DONT_INHERIT_TRANSFORM && mParent[i] != INVALID_TRANSFORM_ID ) )
     {
       const TransformId& parentIndex = mIds[mParent[i] ];
@@ -322,7 +336,17 @@ void TransformManager::Update()
     mBoundingSpheres[i] = mWorld[i].GetTranslation();
     mBoundingSpheres[i].w = Length( centerToEdgeWorldSpace );
 
+    mComponentChanged[i] = false;
+
+    // Due to parent transformation child transformation could be changed
+    if( mComponentDirty[i] ||
+        mPrevWorld[i] != mWorld[i] )
+    {
+      mComponentChanged[i] = true;
+    }
+
     mComponentDirty[i] = false;
+
   }
 }
 
@@ -340,6 +364,10 @@ void TransformManager::SwapComponents( unsigned int i, unsigned int j )
   std::swap( mComponentDirty[i], mComponentDirty[j] );
   std::swap( mBoundingSpheres[i], mBoundingSpheres[j] );
   std::swap( mWorld[i], mWorld[j] );
+  std::swap( mComponentChanged[i], mComponentChanged[j] );
+  std::swap( mPrevWorld[i], mPrevWorld[j] );
+  std::swap( mUpdateSizeHint[i], mUpdateSizeHint[j] );
+  std::swap( mUpdateSizeHintBase[i], mUpdateSizeHintBase[j] );
 
   mIds[ mComponentId[i] ] = i;
   mIds[ mComponentId[j] ] = j;
@@ -409,6 +437,12 @@ Vector3& TransformManager::GetVector3PropertyValue( TransformId id, TransformMan
       mComponentDirty[ index ] = true;
       return mSize[ index ];
     }
+    case TRANSFORM_PROPERTY_UPDATE_SIZE_HINT:
+    {
+      TransformId index( mIds[id] );
+      mComponentDirty[ index ] = true;
+      return mUpdateSizeHint[ index ];
+    }
     default:
     {
       DALI_ASSERT_ALWAYS(false);
@@ -441,6 +475,10 @@ const Vector3& TransformManager::GetVector3PropertyValue( TransformId id, Transf
     {
       return mSize[ mIds[id] ];
     }
+    case TRANSFORM_PROPERTY_UPDATE_SIZE_HINT:
+    {
+      return mUpdateSizeHint[ mIds[id] ];
+    }
     default:
     {
       DALI_ASSERT_ALWAYS(false);
@@ -473,6 +511,10 @@ const float& TransformManager::GetVector3PropertyComponentValue(TransformId id,
     {
       return mSize[ mIds[id] ][component];
     }
+    case TRANSFORM_PROPERTY_UPDATE_SIZE_HINT:
+    {
+      return mUpdateSizeHint[ mIds[id] ][component];
+    }
     default:
     {
       DALI_ASSERT_ALWAYS(false);
@@ -513,6 +555,11 @@ void TransformManager::SetVector3PropertyValue( TransformId id, TransformManager
       mSize[ index ] = value;
       break;
     }
+    case TRANSFORM_PROPERTY_UPDATE_SIZE_HINT:
+    {
+      mUpdateSizeHint[ index ] = value;
+      break;
+    }
     default:
     {
       DALI_ASSERT_ALWAYS(false);
@@ -552,6 +599,11 @@ void TransformManager::SetVector3PropertyComponentValue( TransformId id, Transfo
       mSize[ index ][component] = value;
       break;
     }
+    case TRANSFORM_PROPERTY_UPDATE_SIZE_HINT:
+    {
+      mUpdateSizeHint[ index ][component] = value;
+      break;
+    }
     default:
     {
       DALI_ASSERT_ALWAYS(false);
@@ -591,6 +643,11 @@ void TransformManager::BakeVector3PropertyValue( TransformId id, TransformManage
       mSize[ index ] = mSizeBase[index] = value;
       break;
     }
+    case TRANSFORM_PROPERTY_UPDATE_SIZE_HINT:
+    {
+      mUpdateSizeHint[ index ] = mUpdateSizeHintBase[index] = value;
+      break;
+    }
     default:
     {
       DALI_ASSERT_ALWAYS(false);
@@ -630,6 +687,11 @@ void TransformManager::BakeRelativeVector3PropertyValue( TransformId id, Transfo
       mSize[ index ] = mSizeBase[index] = mSize[ index ] + value;
       break;
     }
+    case TRANSFORM_PROPERTY_UPDATE_SIZE_HINT:
+    {
+      mUpdateSizeHint[ index ] = mUpdateSizeHintBase[index] = mUpdateSizeHint[ index ] + value;
+      break;
+    }
     default:
     {
       DALI_ASSERT_ALWAYS(false);
@@ -669,6 +731,11 @@ void TransformManager::BakeMultiplyVector3PropertyValue( TransformId id, Transfo
       mSize[ index ] = mSizeBase[index] = mSize[ index ] * value;
       break;
     }
+    case TRANSFORM_PROPERTY_UPDATE_SIZE_HINT:
+    {
+      mUpdateSizeHint[ index ] = mUpdateSizeHintBase[index] = mUpdateSizeHint[ index ] * value;
+      break;
+    }
     default:
     {
       DALI_ASSERT_ALWAYS(false);
@@ -708,6 +775,11 @@ void TransformManager::BakeVector3PropertyComponentValue( TransformId id, Transf
       mSize[ index ][component] = mSizeBase[index][component] = value;
       break;
     }
+    case TRANSFORM_PROPERTY_UPDATE_SIZE_HINT:
+    {
+      mUpdateSizeHint[ index ][component] = mUpdateSizeHintBase[index][component] = value;
+      break;
+    }
     default:
     {
       DALI_ASSERT_ALWAYS(false);
@@ -747,6 +819,11 @@ void TransformManager::BakeXVector3PropertyValue( TransformId id, TransformManag
       mSize[ index ].x = mSizeBase[index].x = value;
       break;
     }
+    case TRANSFORM_PROPERTY_UPDATE_SIZE_HINT:
+    {
+      mUpdateSizeHint[ index ].x = mUpdateSizeHintBase[index].x = value;
+      break;
+    }
     default:
     {
       DALI_ASSERT_ALWAYS(false);
@@ -786,6 +863,11 @@ void TransformManager::BakeYVector3PropertyValue( TransformId id, TransformManag
       mSize[ index ].y = mSizeBase[index].y = value;
       break;
     }
+    case TRANSFORM_PROPERTY_UPDATE_SIZE_HINT:
+    {
+      mUpdateSizeHint[ index ].y = mUpdateSizeHintBase[index].y = value;
+      break;
+    }
     default:
     {
       DALI_ASSERT_ALWAYS(false);
@@ -825,6 +907,11 @@ void TransformManager::BakeZVector3PropertyValue( TransformId id, TransformManag
       mSize[ index ].z = mSizeBase[index].z = value;
       break;
     }
+    case TRANSFORM_PROPERTY_UPDATE_SIZE_HINT:
+    {
+      mUpdateSizeHint[ index ].z = mUpdateSizeHintBase[index].z = value;
+      break;
+    }
     default:
     {
       DALI_ASSERT_ALWAYS(false);
@@ -870,6 +957,11 @@ const Vector4& TransformManager::GetBoundingSphere( TransformId id ) const
   return mBoundingSpheres[ mIds[id] ];
 }
 
+bool TransformManager::IsComponentChanged( TransformId id )
+{
+  return mComponentChanged[ mIds[id]];
+}
+
 void TransformManager::GetWorldMatrixAndSize( TransformId id, Matrix& worldMatrix, Vector3& size ) const
 {
   TransformId index = mIds[id];
@@ -877,6 +969,11 @@ void TransformManager::GetWorldMatrixAndSize( TransformId id, Matrix& worldMatri
   size = mSize[index];
 }
 
+const Vector3& TransformManager::GetUpdateSizeHint( TransformId id ) const
+{
+  return mUpdateSizeHint[ mIds[id] ];
+}
+
 void TransformManager::SetPositionUsesAnchorPoint( TransformId id, bool value )
 {
   TransformId index( mIds[ id ] );
old mode 100644 (file)
new mode 100755 (executable)
index 6bf9bda..30b253b
@@ -89,6 +89,7 @@ enum TransformManagerProperty
   TRANSFORM_PROPERTY_WORLD_SCALE,
   TRANSFORM_PROPERTY_WORLD_ORIENTATION,
   TRANSFORM_PROPERTY_WORLD_MATRIX,
+  TRANSFORM_PROPERTY_UPDATE_SIZE_HINT,
   TRANSFORM_PROPERTY_COUNT,
 };
 
@@ -336,6 +337,13 @@ public:
   const Vector4& GetBoundingSphere( TransformId id ) const;
 
   /**
+   * Component of node is changed or not
+   * @param[in] id Id of the transform component
+   * @return true if Component box is changed else false.
+   */
+  bool IsComponentChanged( TransformId id );
+
+  /**
    * Get the world matrix and size of a given component
    * @param[in] id Id of the transform component
    * @param[out] The world matrix of the component
@@ -344,6 +352,14 @@ public:
   void GetWorldMatrixAndSize( TransformId id, Matrix& worldMatrix, Vector3& size ) const;
 
   /**
+   * Get the update size hint,
+   * @param[in] id Id of the transform component
+   * @return The update size hint of the component
+   */
+  const Vector3& GetUpdateSizeHint( TransformId id ) const;
+
+
+  /**
    * @brief Sets the boolean which states whether the position should use the anchor-point on the given transform component.
    * @param[in] id Id of the transform component
    * @param[in] value True if the position should use the anchor-point
@@ -383,6 +399,7 @@ private:
   Vector< Vector3 > mSize;                                                ///< Size of the components
   Vector< TransformId > mParent;                                          ///< Parent of the components
   Vector< Matrix > mWorld;                                                ///< Local to world transform of the components
+  Vector< Matrix > mPrevWorld;                                            ///< Local to world transform of the components in last frame
   Vector< Matrix > mLocal;                                                ///< Local to parent space transform of the components
   Vector< Vector4 > mBoundingSpheres;                                     ///< Bounding spheres. xyz is the center and w is the radius
   Vector< TransformComponentAnimatable > mTxComponentAnimatableBaseValue; ///< Base values for the animatable part of the components
@@ -390,6 +407,9 @@ private:
   Vector< bool > mComponentDirty;                                         ///< 1u if some of the parts of the component has changed in this frame, 0 otherwise
   Vector< bool > mLocalMatrixDirty;                                       ///< 1u if the local matrix has been updated in this frame, 0 otherwise
   Vector< SOrderItem > mOrderedComponents;                                ///< Used to reorder components when hierarchy changes
+  Vector< bool> mComponentChanged;                                        ///< Component is changed or not
+  Vector< Vector3 > mUpdateSizeHint;                                      ///< BoundingBox of the components
+  Vector< Vector3 > mUpdateSizeHintBase;                                     ///< Base value for the boundingBox of the components
   bool mReorder;                                                          ///< Flag to determine if the components have to reordered in the next Update
 };
 
old mode 100644 (file)
new mode 100755 (executable)
index 571e8b3..4d1842e
@@ -426,6 +426,8 @@ void UpdateManager::ConnectNode( Node* parent, Node* node )
 
   parent->ConnectChild( node );
 
+  parent->SetPropertyDirty( true );
+
   // Inform the frame-callback-processor, if set, about the node-hierarchy changing
   if( mImpl->frameCallbackProcessor )
   {
@@ -633,6 +635,8 @@ void UpdateManager::RemoveRenderer( Renderer* renderer )
 {
   DALI_LOG_INFO( gLogFilter, Debug::General, "[%x] RemoveRenderer\n", renderer );
 
+  renderer->SetDirty( true );
+
   // Find the renderer and destroy it
   EraseUsingDiscardQueue( mImpl->renderers, renderer, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
   // Need to remove the render object as well
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 3fdb2e2..a005dd3
@@ -105,6 +105,7 @@ public:
    */
   virtual void Process( BufferIndex updateBufferIndex )
   {
+    mNode->SetPropertyDirty( true );
     (mProperty->*mMemberFunction)( updateBufferIndex, mParam );
   }
 
@@ -186,6 +187,7 @@ public:
    */
   virtual void Process( BufferIndex updateBufferIndex )
   {
+    mNode->SetPropertyDirty( true );
     (mProperty->*mMemberFunction)( updateBufferIndex, mParam );
   }
 
@@ -265,6 +267,7 @@ public:
    */
   virtual void Process( BufferIndex updateBufferIndex )
   {
+    mNode->SetPropertyDirty( true );
     (mProperty->*mMemberFunction)( updateBufferIndex, mParam );
   }
 
@@ -344,6 +347,7 @@ public:
    */
   virtual void Process( BufferIndex updateBufferIndex )
   {
+    mNode->SetPropertyDirty( true );
     (mProperty->*mMemberFunction)( updateBufferIndex, mParam );
   }
 
index d80d7c4..f1faa84 100755 (executable)
@@ -87,6 +87,7 @@ Node::Node()
   mPosition( TRANSFORM_PROPERTY_POSITION ),                                       // Zero initialized by default
   mOrientation(),                                                                 // Initialized to identity by default
   mScale( TRANSFORM_PROPERTY_SCALE ),
+  mUpdateSizeHint( TRANSFORM_PROPERTY_UPDATE_SIZE_HINT ),
   mVisible( true ),
   mCulled( false ),
   mColor( Color::WHITE ),
@@ -114,6 +115,7 @@ Node::Node()
 {
   mUniformMapChanged[0] = 0u;
   mUniformMapChanged[1] = 0u;
+  mPropertyDirty = false;
 
 #ifdef DEBUG_ENABLED
   gNodeCount++;
@@ -153,6 +155,7 @@ void Node::CreateTransform( SceneGraph::TransformManager* transformManager )
   //Initialize all the animatable properties
   mPosition.Initialize( transformManager, mTransformId );
   mScale.Initialize( transformManager, mTransformId );
+  mUpdateSizeHint.Initialize( transformManager, mTransformId );
   mOrientation.Initialize( transformManager, mTransformId );
   mSize.Initialize( transformManager, mTransformId );
   mParentOrigin.Initialize( transformManager, mTransformId );
@@ -283,6 +286,7 @@ void Node::AddRenderer( Renderer* renderer )
   }
 
   mRenderer.PushBack( renderer );
+  SetPropertyDirty( true );
 }
 
 void Node::RemoveRenderer( const Renderer* renderer )
@@ -292,6 +296,7 @@ void Node::RemoveRenderer( const Renderer* renderer )
   {
     if( mRenderer[i] == renderer )
     {
+      SetPropertyDirty( true );
       mRenderer.Erase( mRenderer.Begin()+i);
       return;
     }
@@ -331,6 +336,9 @@ NodePropertyFlags Node::GetInheritedDirtyFlags( NodePropertyFlags parentFlags )
 void Node::ResetDirtyFlags( BufferIndex updateBufferIndex )
 {
   mDirtyFlags = NodePropertyFlags::NOTHING;
+
+  SetPropertyDirty( false );
+
 }
 
 void Node::SetParent( Node& parentNode )
@@ -373,6 +381,31 @@ void Node::RecursiveDisconnectFromSceneGraph( BufferIndex updateBufferIndex )
   }
 }
 
+void Node::SetPropertyDirty( bool value )
+{
+  mPropertyDirty = value;
+
+  const NodeIter endIter = mChildren.End();
+  for ( NodeIter iter = mChildren.Begin(); iter != endIter; ++iter )
+  {
+    Node* current = *iter;
+    current->SetPropertyDirty( value );
+  }
+}
+
+bool Node::IsPropertyDirty() const
+{
+  for( auto&& existingRenderer : mRenderer )
+  {
+    if( existingRenderer->IsDirty() )
+    {
+      return true;
+    }
+  }
+
+  return mPropertyDirty;
+}
+
 } // namespace SceneGraph
 
 } // namespace Internal
index 5cd6073..5600523 100755 (executable)
@@ -182,6 +182,7 @@ public:
    */
   void SetClippingMode( const ClippingMode::Type clippingMode )
   {
+    SetPropertyDirty( true );
     mClippingMode = clippingMode;
   }
 
@@ -313,6 +314,7 @@ public:
    */
   void SetDirtyFlag( NodePropertyFlags flag )
   {
+    SetPropertyDirty( true );
     mDirtyFlags |= flag;
   }
 
@@ -321,6 +323,7 @@ public:
    */
   void SetAllDirtyFlags()
   {
+    SetPropertyDirty( true );
     mDirtyFlags = NodePropertyFlags::ALL;
   }
 
@@ -684,6 +687,7 @@ public:
    */
   void SetDrawMode( const DrawMode::Type& drawMode )
   {
+    SetPropertyDirty( true );
     mDrawMode = drawMode;
   }
 
@@ -720,6 +724,7 @@ public:
    */
   void SetDepthIndex( uint32_t depthIndex )
   {
+    SetPropertyDirty( true );
     mDepthIndex = depthIndex;
   }
 
@@ -765,6 +770,42 @@ public:
     return mCulled[bufferIndex];
   }
 
+  /**
+ * @Is component changed
+ * @Return true if component is changed else false
+ */
+  bool IsComponentChanged()
+  {
+    return (mTransformId != INVALID_TRANSFORM_ID) &&
+           (mTransformManager->IsComponentChanged( mTransformId ));
+  }
+
+  /**
+   * Retrieve the update size hint of the node
+   * @return A vector3 describing the update size hint
+   */
+  const Vector3& GetUpdateSizeHint( BufferIndex bufferIndex ) const
+  {
+    if( mTransformId != INVALID_TRANSFORM_ID )
+    {
+      return mTransformManager->GetUpdateSizeHint( mTransformId );
+    }
+
+    return Vector3::ZERO;
+  }
+
+  /**
+   * Set whether partial update needs to run following a render.
+   * @param[in] value Set to true if an partial update is required to be run
+   */
+  virtual void SetPropertyDirty( bool value );
+
+  /**
+   * Query the property status following rendering of a frame.
+   * @return True if the property has changed
+   */
+  virtual bool IsPropertyDirty() const;
+
 public:
   /**
    * @copydoc UniformMap::Add
@@ -877,6 +918,7 @@ public: // Default properties
   TransformManagerPropertyVector3    mPosition;               ///< Local transform; distance between parent-origin & anchor-point
   TransformManagerPropertyQuaternion mOrientation;            ///< Local transform; rotation relative to parent node
   TransformManagerPropertyVector3    mScale;                  ///< Local transform; scale relative to parent node
+  TransformManagerPropertyVector3    mUpdateSizeHint;         ///< Local transform; update size hint is provided for partial update
 
   AnimatableProperty<bool>           mVisible;                ///< Visibility can be inherited from the Node hierachy
   AnimatableProperty<bool>           mCulled;                 ///< True if the node is culled. This is not animatable. It is just double-buffered.
index 8f9ff00..d23419c 100755 (executable)
@@ -64,6 +64,7 @@ void Layer::SetSortFunction( Dali::Layer::SortFunctionType function )
 {
   if( mSortFunction != function )
   {
+    SetPropertyDirty( true );
     // is a custom sort function used
     if( function != Internal::Layer::ZValue )
     {
@@ -84,21 +85,25 @@ void Layer::SetSortFunction( Dali::Layer::SortFunctionType function )
 void Layer::SetClipping(bool enabled)
 {
   mIsClipping = enabled;
+  SetPropertyDirty( true );
 }
 
 void Layer::SetClippingBox(const Dali::ClippingBox& box)
 {
   mClippingBox.Set(box.x, box.y, box.width, box.height);
+  SetPropertyDirty( true );
 }
 
 void Layer::SetBehavior( Dali::Layer::Behavior behavior )
 {
   mBehavior = behavior;
+  SetPropertyDirty( true );
 }
 
 void Layer::SetDepthTestDisabled( bool disable )
 {
   mDepthTestDisabled = disable;
+  SetPropertyDirty( true );
 }
 
 bool Layer::IsDepthTestDisabled() const
old mode 100644 (file)
new mode 100755 (executable)
index 169be5c..d42e960
@@ -143,6 +143,7 @@ Renderer::Renderer()
   mDepthTestMode( DepthTestMode::AUTO ),
   mRenderingBehavior( DevelRenderer::Rendering::IF_REQUIRED ),
   mPremultipledAlphaEnabled( false ),
+  mDirty( false ),
   mOpacity( 1.0f ),
   mDepthIndex( 0 )
 {
@@ -175,12 +176,14 @@ void Renderer::operator delete( void* ptr )
 
 void Renderer::PrepareRender( BufferIndex updateBufferIndex )
 {
+  SetDirty( false );
   if( mRegenerateUniformMap == UNIFORM_MAP_READY )
   {
     mUniformMapChanged[updateBufferIndex] = false;
   }
   else
   {
+    mDirty = true;
     if( mRegenerateUniformMap == REGENERATE_UNIFORM_MAP)
     {
       CollectedUniformMap& localMap = mCollectedUniformMap[ updateBufferIndex ];
@@ -215,6 +218,7 @@ void Renderer::PrepareRender( BufferIndex updateBufferIndex )
 
   if( mResendFlag != 0 )
   {
+    mDirty = true;
     if( mResendFlag & RESEND_GEOMETRY )
     {
       typedef MessageValue1< Render::Renderer, Render::Geometry* > DerivedType;
@@ -395,6 +399,7 @@ void Renderer::SetGeometry( Render::Geometry* geometry )
 void Renderer::SetDepthIndex( int depthIndex )
 {
   mDepthIndex = depthIndex;
+  mDirty = true;
 }
 
 void Renderer::SetFaceCullingMode( FaceCullingMode::Type faceCullingMode )
@@ -411,6 +416,7 @@ FaceCullingMode::Type Renderer::GetFaceCullingMode() const
 void Renderer::SetBlendMode( BlendMode::Type blendingMode )
 {
   mBlendMode = blendingMode;
+  mDirty = true;
 }
 
 BlendMode::Type Renderer::GetBlendMode() const
@@ -583,6 +589,7 @@ const Render::Renderer::StencilParameters& Renderer::GetStencilParameters() cons
 
 void Renderer::BakeOpacity( BufferIndex updateBufferIndex, float opacity )
 {
+  mDirty = true;
   mOpacity.Bake( updateBufferIndex, opacity );
 }
 
@@ -594,6 +601,7 @@ float Renderer::GetOpacity( BufferIndex updateBufferIndex ) const
 void Renderer::SetRenderingBehavior( DevelRenderer::Rendering::Type renderingBehavior )
 {
   mRenderingBehavior = renderingBehavior;
+  mDirty = true;
 }
 
 DevelRenderer::Rendering::Type Renderer::GetRenderingBehavior() const
@@ -612,7 +620,6 @@ void Renderer::ConnectToSceneGraph( SceneController& sceneController, BufferInde
 
   mRenderer = Render::Renderer::New( mRenderDataProvider, mGeometry, mBlendBitmask, GetBlendColor(), static_cast< FaceCullingMode::Type >( mFaceCullingMode ),
                                          mPremultipledAlphaEnabled, mDepthWriteMode, mDepthTestMode, mDepthFunction, mStencilParameters );
-
   OwnerPointer< Render::Renderer > transferOwnership( mRenderer );
   mSceneController->GetRenderMessageDispatcher().AddRenderer( transferOwnership );
 }
@@ -650,6 +657,7 @@ void Renderer::UpdateTextureSet()
       mRenderDataProvider->mTextures.clear();
       mRenderDataProvider->mSamplers.clear();
     }
+    mDirty = true;
   }
 }
 
@@ -755,6 +763,46 @@ void Renderer::ObservedObjectDestroyed(PropertyOwner& owner)
   }
 }
 
+void Renderer::SetDirty( bool value )
+{
+  mDirty = value;
+  if( mShader )
+  {
+    mShader->SetPropertyDirty( value );
+  }
+}
+
+bool Renderer::IsDirty() const
+{
+  bool ret = false;
+  if( mShader )
+  {
+    ret = mShader->IsPropertyDirty();
+  }
+
+  // check native image
+  if( mTextureSet )
+  {
+    uint32_t textureCount = mTextureSet->GetTextureCount();
+
+    if(textureCount > 0)
+    {
+      Dali::Internal::Render::Texture* texture;
+      for( uint32_t i = 0; i<textureCount; ++i )
+      {
+        texture = const_cast<Dali::Internal::SceneGraph::TextureSet *>(mTextureSet)->GetTexture(i);
+        if( texture && texture->IsNativeImage() )
+        {
+          ret = true;
+          break;
+        }
+      }
+    }
+  }
+
+  return ret | mDirty;
+}
+
 } // namespace SceneGraph
 } // namespace Internal
 } // namespace Dali
index 7051e44..3dda873 100755 (executable)
@@ -380,6 +380,18 @@ public:
    */
   void DisconnectFromSceneGraph( SceneController& sceneController, BufferIndex bufferIndex );
 
+  /**
+   * Enable/Disable Partial update dirty flag
+   * @param[in] true to mark dirty else false
+   */
+  void SetDirty( bool value );
+
+  /**
+   * Get Partial update dirty flag
+   * @return true if dirty else false
+   */
+  bool IsDirty() const;
+
 public: // Implementation of ConnectionChangePropagator
   /**
    * @copydoc ConnectionChangePropagator::AddObserver
@@ -473,6 +485,7 @@ private:
 
   bool                         mUniformMapChanged[2];             ///< Records if the uniform map has been altered this frame
   bool                         mPremultipledAlphaEnabled:1;       ///< Flag indicating whether the Pre-multiplied Alpha Blending is required
+  bool                         mDirty:1;                          ///< Required for marking it dirty in case of partial update.
 
 public: