[Tizen] Delete buffer after the resource of nativeImage is destroyed 76/262876/7 accepted/tizen/6.0/unified/20210908.124503 submit/tizen_6.0/20210908.054804
authorsunghyun kim <scholb.kim@samsung.com>
Thu, 19 Aug 2021 13:35:27 +0000 (22:35 +0900)
committertscholb <scholb.kim@samsung.com>
Fri, 27 Aug 2021 05:22:00 +0000 (14:22 +0900)
Previously WidgetView deleted the previous buffer when updating the next buffer.
But in this struct, the buffers in use may be cleared if the rendering is fast.
Thus, To resolve these problems, it has been modified to erase the buffer using WidgetBuffer and EventCallback.

Change-Id: I4e00bed378a98d735a06830ef2b77c6aefe4a4a7

widget_viewer_dali/internal/widget_view/widget_view_impl.cpp
widget_viewer_dali/internal/widget_view/widget_view_impl.h

index 755305e60f71ec5b3479f7072421f6f584476b17..5c2cd757f6d3a34061c98e7655212cb03f7aa255 100644 (file)
@@ -34,6 +34,7 @@
 #include <dali-toolkit/public-api/visuals/visual-properties.h>
 #include <dali-toolkit/devel-api/visual-factory/visual-factory.h>
 #include <dali/integration-api/debug.h>
+#include <dali/devel-api/adaptor-framework/event-thread-callback.h>
 #include <string.h>
 #ifdef ECORE_WL2
 #include <Ecore_Wl2.h>
@@ -264,6 +265,32 @@ static void OnSurfaceRemoved( const char *appid, const char *instance_id, const
 
 } // unnamed namespace
 
+
+WidgetBuffer::WidgetBuffer(wl_buffer* buffer, Dali::WidgetView::Internal::WidgetView& widgetview, Dali::NativeImageSourcePtr source)
+: mBuffer(buffer),
+  mWidgetView(widgetview),
+  mImageSource(source)
+{
+}
+
+WidgetBuffer::~WidgetBuffer()
+{
+  if(mImageSource)
+  {
+    Dali::DevelNativeImageSource::SetResourceDestructionCallback(*mImageSource,NULL);
+  }
+}
+
+void WidgetBuffer::OnResourceDestruction()
+{
+  mWidgetView.DeleteBuffer(mBuffer, this);
+}
+
+wl_buffer* WidgetBuffer::GetBuffer() const
+{
+  return mBuffer;
+}
+
 Dali::WidgetView::WidgetView WidgetView::New( const std::string& widgetId, const std::string& contentInfo, int width, int height, float updatePeriod )
 {
   // Create the implementation, temporarily owned on stack
@@ -1227,6 +1254,11 @@ void WidgetView::UpdateImageSource( tbm_surface_h source )
     textureSet.SetTexture( 0u, texture );
     mRenderer.SetProperty( Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA, true );
   }
+
+  // Register a callback using WidgetBuffer class
+  auto widgetBuffer = new WidgetBuffer(mBuffer,*this,mImageSource);
+  Dali::DevelNativeImageSource::SetResourceDestructionCallback(*mImageSource, new EventThreadCallback(MakeCallback(widgetBuffer, &WidgetBuffer::OnResourceDestruction)));
+  mBufferContainer.push_back(std::unique_ptr<WidgetBuffer>(widgetBuffer));
 }
 
 void WidgetView::ConnectSignal( tizen_remote_surface* surface )
@@ -1325,6 +1357,28 @@ bool WidgetView::OnKeyEvent( const Dali::KeyEvent& event )
   return false;
 }
 
+void WidgetView::DeleteBuffer(wl_buffer* buffer, WidgetBuffer* widgetBuffer)
+{
+  bool findBuffer = false;
+  auto bufferInstance = std::find_if( mBufferContainer.begin(),
+                                      mBufferContainer.end(),
+                                      [widgetBuffer]( std::unique_ptr<WidgetBuffer>& instanceBuffer)
+                                      { return (instanceBuffer->GetBuffer() == widgetBuffer->GetBuffer()); } );
+  if(bufferInstance != mBufferContainer.end())
+  {
+    mBufferContainer.erase(bufferInstance);
+    findBuffer = true;
+  }
+
+  if( findBuffer && mWatcherHandle != NULL )
+  {
+    if( mRemoteSurface != NULL && buffer != NULL && tizen_remote_surface_get_version( mRemoteSurface ) >= TIZEN_REMOTE_SURFACE_RELEASE_SINCE_VERSION )
+    {
+      screen_connector_toolkit_dispose_buffer( mWatcherHandle , buffer );
+    }
+  }
+}
+
 Vector3 WidgetView::GetNaturalSize()
 {
   Vector3 size;
@@ -1370,9 +1424,16 @@ void WidgetView::CloseRemoteSurface()
 {
   if( mWatcherHandle != NULL )
   {
-    if( mRemoteSurface != NULL && mBuffer != NULL && tizen_remote_surface_get_version( mRemoteSurface ) >= TIZEN_REMOTE_SURFACE_RELEASE_SINCE_VERSION )
+    if( mBufferContainer.size() )
     {
-      screen_connector_toolkit_dispose_buffer( mWatcherHandle , mBuffer );
+      for( std::vector<std::unique_ptr<WidgetBuffer>>::iterator iter = mBufferContainer.begin(), endIter = mBufferContainer.end(); iter != endIter; ++iter )
+      {
+        if( mRemoteSurface != NULL && (*iter)->GetBuffer() != NULL && tizen_remote_surface_get_version( mRemoteSurface ) >= TIZEN_REMOTE_SURFACE_RELEASE_SINCE_VERSION )
+        {
+          screen_connector_toolkit_dispose_buffer( mWatcherHandle , (*iter)->GetBuffer() );
+        }
+      }
+      mBufferContainer.clear();
       mBuffer = NULL;
     }
 
@@ -1734,22 +1795,10 @@ void WidgetView::UpdateBuffer( struct tizen_remote_surface *surface, struct wl_b
     DALI_LOG_ERROR("tbm surface is NULL");
     return;
   }
-  UpdateImageSource( tbmSurface );
 
-  if( mBuffer != NULL && tizen_remote_surface_get_version( surface ) >= TIZEN_REMOTE_SURFACE_RELEASE_SINCE_VERSION )
-  {
-    if( mWatcherHandle != NULL )
-    {
-      screen_connector_toolkit_dispose_buffer( mWatcherHandle , mBuffer );
-    }
-    else
-    {
-      DALI_LOG_ERROR("WidgetView can't dispose buffer because mWatcherHandle is invalid. ");
-    }
-  }
-
-  mRemoteSurface = surface;
   mBuffer = buffer;
+  UpdateImageSource( tbmSurface );
+  mRemoteSurface = surface;
 }
 
 void WidgetView::ReloadWidget()
index 641c23b0be593bda6767d4537b7a08012fd4ce9d..1cb6eb6df42386a4384324c16e2df8b5657d12d9 100644 (file)
@@ -23,7 +23,6 @@
 
 // EXTERNAL INCLUDES
 #include <dali/public-api/rendering/renderer.h>
-#include <dali/public-api/adaptor-framework/native-image-source.h>
 #include <dali-toolkit/public-api/controls/control-impl.h>
 #include <dali-toolkit/public-api/controls/text-controls/text-label.h>
 #include <dali-toolkit/public-api/controls/image-view/image-view.h>
@@ -31,6 +30,7 @@
 #include <wayland-extension/tizen-remote-surface-client-protocol.h>
 #include <tbm_surface.h>
 #include <screen_connector_toolkit.h>
+#include <dali/devel-api/adaptor-framework/native-image-source-devel.h>
 #include <dali/devel-api/adaptor-framework/window-devel.h>
 #include <dali/public-api/object/property-notification.h>
 
@@ -43,6 +43,49 @@ namespace WidgetView
 namespace Internal
 {
 
+/**
+ * @brief WidgetBuffer is a class for managing resource the widget's buffer
+ */
+class WidgetBuffer
+{
+public:
+
+  /**
+   * @brief Construct a new Widget Buffer object
+   *
+   */
+  WidgetBuffer( wl_buffer* buffer, Dali::WidgetView::Internal::WidgetView& widgetview, Dali::NativeImageSourcePtr source);
+
+  /**
+   * @brief Destroy the Widget Buffer object
+   *
+   */
+  virtual ~WidgetBuffer();
+
+  /**
+   * @brief Get the wayland buffer
+   *
+   * @return wl_buffer*
+   */
+  wl_buffer* GetBuffer() const;
+
+  /**
+   * @brief Callback for ResourceDestruction
+   *
+   */
+  void OnResourceDestruction();
+
+  WidgetBuffer( const WidgetBuffer& );
+
+  WidgetBuffer& operator= ( const WidgetBuffer& );
+
+private:
+
+  wl_buffer* mBuffer;
+  Dali::WidgetView::Internal::WidgetView& mWidgetView;
+  Dali::NativeImageSourcePtr mImageSource;
+};
+
 class WidgetView : public Toolkit::Internal::Control
 {
 public:
@@ -144,6 +187,17 @@ public: // Internal API
 
   void ConnectSignal( tizen_remote_surface* surface );
 
+  /**
+   * @brief Delete a buffer and its resource.
+   *
+   * @param buffer the wayland buffer
+   * @param widgetBuffer a pointer of widgetbuffer
+   */
+  void DeleteBuffer(wl_buffer* buffer, WidgetBuffer* widgetBuffer);
+
+  /**
+   * @brief Callback for touch event
+   */
   bool OnTouch( Dali::Actor actor, const Dali::TouchEvent& event );
 
   bool OnWheelEvent( Dali::Actor actor, const Dali::WheelEvent& event );
@@ -354,6 +408,7 @@ private:
   screen_connector_toolkit_h mWatcherHandle;
   tizen_remote_surface* mRemoteSurface;
   wl_buffer* mBuffer;
+  std::vector<std::unique_ptr<WidgetBuffer>> mBufferContainer;
   bool mCreated;
   bool mResizeRequired;
   bool mPaused;