Delete buffer after the resource of nativeImage is destroyed 81/262781/6 accepted/tizen/unified/20211123.143850 accepted/tizen/unified/20211125.003900 submit/tizen/20211117.081222 submit/tizen/20211122.105712 submit/tizen/20211123.152301
authorsunghyun kim <scholb.kim@samsung.com>
Thu, 19 Aug 2021 13:35:27 +0000 (22:35 +0900)
committertscholb <scholb.kim@samsung.com>
Fri, 12 Nov 2021 09:05:14 +0000 (18:05 +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 166cb9609509c752d6526b462665e568d4cff7a5..d165adfba289d00523dff0864815c0270a14c2fc 100644 (file)
@@ -35,6 +35,7 @@
 #include <dali-toolkit/devel-api/visual-factory/visual-factory.h>
 #include <dali-toolkit/devel-api/controls/control-devel.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>
@@ -177,6 +178,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
@@ -1129,6 +1156,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));
 }
 
 bool WidgetView::OnTouch( Dali::Actor actor, const Dali::TouchEvent& event )
@@ -1210,6 +1242,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;
@@ -1255,9 +1309,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;
     }
 
@@ -1620,22 +1681,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;
 }
 
 bool WidgetView::LaunchWidget()
index 831618b2ec5dd271b2c98cfed4c3802e588a6c85..f9526412a4b9bef9d6e73bcd4fad175cacbba9a9 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:
@@ -205,6 +248,14 @@ public: // Internal API
    */
   void UpdateImageSource( tbm_surface_h source );
 
+  /**
+   * @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
    */
@@ -459,13 +510,13 @@ private:
   screen_connector_toolkit_h mWatcherHandle; ///< Handle for screen connector
   tizen_remote_surface* mRemoteSurface;      ///< RemoteSurface for controlling events and visibillity
   wl_buffer* mBuffer;                        ///< Buffer for screen_connector. WidgetView need to release previous buffer
+  std::vector<std::unique_ptr<WidgetBuffer>> mBufferContainer;
   bool mCreated;                             ///< Check whether widget instance is created or not
   bool mResizeRequired;                      ///< Check whether widget instance need to resize.
   bool mPaused;                              ///< Check whether widget is paused or not
   bool mPausedManually;                      ///< Check whether widget is paused or not by application
   bool mWindowVisible;                       ///< Check whether window is visible or not
   bool mPreviewEnable;                      ///< Check whether preview is enable or not
-
   Dali::Property::Map mEffectPropertyMap;    ///< Shader for effect
 
   // Notification for property change confirmation