Add API for setting resource destruction callback
[platform/core/uifw/dali-adaptor.git] / dali / internal / imaging / ubuntu-x11 / native-image-source-impl-x.cpp
index be32323..5ae65a1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #include <dali/internal/imaging/ubuntu-x11/native-image-source-impl-x.h>
 
 // EXTERNAL INCLUDES
-#include <Ecore_X.h>
-#include <X11/Xutil.h>
 #include <X11/Xlib.h>
+#include <X11/Xutil.h>
 #include <dali/integration-api/debug.h>
+#include <dali/internal/system/linux/dali-ecore-x.h>
 
 // INTERNAL INCLUDES
-#include <dali/internal/graphics/common/egl-image-extensions.h>
-#include <dali/internal/graphics/gles20/egl-graphics.h>
+#include <dali/integration-api/adaptor-framework/render-surface-interface.h>
 #include <dali/internal/adaptor/common/adaptor-impl.h>
-#include <dali/devel-api/adaptor-framework/bitmap-saver.h>
-#include <dali/integration-api/render-surface.h>
-
+#include <dali/internal/graphics/common/egl-image-extensions.h>
+#include <dali/internal/graphics/gles/egl-graphics.h>
 
 namespace Dali
 {
-
 namespace Internal
 {
-
 namespace Adaptor
 {
 using Dali::Integration::PixelBuffer;
@@ -45,38 +41,39 @@ using Dali::Integration::PixelBuffer;
 // Pieces needed to save compressed images (temporary location while plumbing):
 namespace
 {
-
-  /**
+/**
    * Free an allocated XImage on destruction.
    */
-  struct XImageJanitor
+struct XImageJanitor
+{
+  XImageJanitor(XImage* const pXImage)
+  : mXImage(pXImage)
   {
-    XImageJanitor( XImage* const  pXImage ) : mXImage( pXImage )
-    {
-      DALI_ASSERT_DEBUG(pXImage != 0 && "Null pointer to XImage.");
-    }
+    DALI_ASSERT_DEBUG(pXImage != 0 && "Null pointer to XImage.");
+  }
 
-    ~XImageJanitor()
+  ~XImageJanitor()
+  {
+    if(mXImage)
     {
-      if( mXImage )
+      if(!XDestroyImage(mXImage))
       {
-        if( !XDestroyImage(mXImage) )
-        {
-          DALI_LOG_ERROR("XImage deallocation failure");
-        }
+        DALI_LOG_ERROR("XImage deallocation failure");
       }
     }
-    XImage* const  mXImage;
-  private:
-    XImageJanitor( const XImageJanitor& rhs );
-    XImageJanitor& operator = ( const XImageJanitor& rhs );
-  };
-}
+  }
+  XImage* const mXImage;
+
+private:
+  XImageJanitor(const XImageJanitor& rhs);
+  XImageJanitor& operator=(const XImageJanitor& rhs);
+};
+} // namespace
 
-NativeImageSourceX* NativeImageSourceX::New(unsigned int width, unsigned int height, Dali::NativeImageSource::ColorDepth depth, Any nativeImageSource )
+NativeImageSourceX* NativeImageSourceX::New(uint32_t width, uint32_t height, Dali::NativeImageSource::ColorDepth depth, Any nativeImageSource)
 {
-  NativeImageSourceX* image = new NativeImageSourceX( width, height, depth, nativeImageSource );
-  DALI_ASSERT_DEBUG( image && "NativeImageSource allocation failed." );
+  NativeImageSourceX* image = new NativeImageSourceX(width, height, depth, nativeImageSource);
+  DALI_ASSERT_DEBUG(image && "NativeImageSource allocation failed.");
 
   // 2nd phase construction
   if(image) //< Defensive in case we ever compile without exceptions.
@@ -87,24 +84,25 @@ NativeImageSourceX* NativeImageSourceX::New(unsigned int width, unsigned int hei
   return image;
 }
 
-NativeImageSourceX::NativeImageSourceX( unsigned int width, unsigned int height, Dali::NativeImageSource::ColorDepth depth, Any nativeImageSource )
-: mWidth( width ),
-  mHeight( height ),
-  mOwnPixmap( true ),
-  mPixmap( 0 ),
-  mBlendingRequired( false ),
-  mColorDepth( depth ),
-  mEglImageKHR( NULL ),
-  mEglImageExtensions( NULL )
+NativeImageSourceX::NativeImageSourceX(uint32_t width, uint32_t height, Dali::NativeImageSource::ColorDepth depth, Any nativeImageSource)
+: mWidth(width),
+  mHeight(height),
+  mOwnPixmap(true),
+  mPixmap(0),
+  mBlendingRequired(false),
+  mColorDepth(depth),
+  mEglImageKHR(NULL),
+  mEglImageExtensions(NULL),
+  mResourceDestructionCallback()
 {
-  DALI_ASSERT_ALWAYS( Adaptor::IsAvailable() );
+  DALI_ASSERT_ALWAYS(Adaptor::IsAvailable());
 
-  GraphicsInterface* graphics = &( Adaptor::GetImplementation( Adaptor::Get() ).GetGraphicsInterface() );
-  auto eglGraphics = static_cast<EglGraphics *>(graphics);
+  GraphicsInterface* graphics    = &(Adaptor::GetImplementation(Adaptor::Get()).GetGraphicsInterface());
+  auto               eglGraphics = static_cast<EglGraphics*>(graphics);
 
   mEglImageExtensions = eglGraphics->GetImageExtensions();
 
-  DALI_ASSERT_DEBUG( mEglImageExtensions );
+  DALI_ASSERT_DEBUG(mEglImageExtensions);
 
   // assign the pixmap
   mPixmap = GetPixmapFromAny(nativeImageSource);
@@ -113,7 +111,7 @@ NativeImageSourceX::NativeImageSourceX( unsigned int width, unsigned int height,
 void NativeImageSourceX::Initialize()
 {
   // if pixmap has been created outside of X11 Image we can return
-  if (mPixmap)
+  if(mPixmap)
   {
     // we don't own the pixmap
     mOwnPixmap = false;
@@ -131,17 +129,18 @@ void NativeImageSourceX::Initialize()
      If depth = 8, Pixel::A8;
      If depth = 16, Pixel::RGB565;
      If depth = 32, Pixel::RGBA8888 */
-  mBlendingRequired = ( depth == 32 || depth == 8 );
+  mBlendingRequired = (depth == 32 || depth == 8);
 
-  mPixmap = ecore_x_pixmap_new( 0, mWidth, mHeight, depth );
+  mPixmap = ecore_x_pixmap_new(0, mWidth, mHeight, depth);
   ecore_x_sync();
 }
 
 NativeImageSourceX::~NativeImageSourceX()
 {
-  if (mOwnPixmap && mPixmap)
+  if(mOwnPixmap && mPixmap)
   {
-    ecore_x_pixmap_free(mPixmap);
+    // Temporarily disable this as this causes a crash with EFL Version 1.24.0
+    //ecore_x_pixmap_free(mPixmap);
   }
 }
 
@@ -155,19 +154,21 @@ bool NativeImageSourceX::GetPixels(std::vector<unsigned char>& pixbuf, unsigned&
 {
   DALI_ASSERT_DEBUG(sizeof(unsigned) == 4);
   bool success = false;
-  width  = mWidth;
-  height = mHeight;
+  width        = mWidth;
+  height       = mHeight;
 
   // Open a display connection
-  Display* displayConnection = XOpenDisplay( 0 );
-
-  XImageJanitor xImageJanitor( XGetImage( displayConnection,
-                                          mPixmap,
-                                          0, 0, // x,y of subregion to extract.
-                                          width, height, // of subregion to extract.
-                                          0xFFFFFFFF,
-                                          ZPixmap ) );
-  XImage* const  pXImage = xImageJanitor.mXImage;
+  Display* displayConnection = XOpenDisplay(0);
+
+  XImageJanitor xImageJanitor(XGetImage(displayConnection,
+                                        mPixmap,
+                                        0,
+                                        0, // x,y of subregion to extract.
+                                        width,
+                                        height, // of subregion to extract.
+                                        0xFFFFFFFF,
+                                        ZPixmap));
+  XImage* const pXImage = xImageJanitor.mXImage;
   DALI_ASSERT_DEBUG(pXImage && "XImage (from pixmap) could not be retrieved from the server");
   if(!pXImage)
   {
@@ -185,23 +186,23 @@ bool NativeImageSourceX::GetPixels(std::vector<unsigned char>& pixbuf, unsigned&
       case 24:
       {
         pixelFormat = Pixel::RGB888;
-        pixbuf.resize(width*height*3);
+        pixbuf.resize(width * height * 3);
         unsigned char* bufPtr = &pixbuf[0];
 
-        for(unsigned y = height-1; y < height; --y)
+        for(unsigned y = 0; y < height; ++y)
         {
-          for(unsigned x = 0; x < width; ++x, bufPtr+=3)
+          for(unsigned x = 0; x < width; ++x, bufPtr += 3)
           {
-            const unsigned pixel = XGetPixel(pXImage,x,y);
+            const unsigned pixel = XGetPixel(pXImage, x, y);
 
             // store as RGB
-            const unsigned blue  =  pixel & 0xFFU;
-            const unsigned green = (pixel >> 8)  & 0xFFU;
+            const unsigned blue  = pixel & 0xFFU;
+            const unsigned green = (pixel >> 8) & 0xFFU;
             const unsigned red   = (pixel >> 16) & 0xFFU;
 
-            *bufPtr = red;
-            *(bufPtr+1) = green;
-            *(bufPtr+2) = blue;
+            *bufPtr       = red;
+            *(bufPtr + 1) = green;
+            *(bufPtr + 2) = blue;
           }
         }
         success = true;
@@ -213,22 +214,22 @@ bool NativeImageSourceX::GetPixels(std::vector<unsigned char>& pixbuf, unsigned&
         {
           // Sweep through the image, doing a vertical flip, but handling each scanline as
           // an inlined intrinsic/builtin memcpy (should be fast):
-          pixbuf.resize(width*height*4);
-          unsigned * bufPtr = reinterpret_cast<unsigned *>(&pixbuf[0]);
+          pixbuf.resize(width * height * 4);
+          unsigned*      bufPtr        = reinterpret_cast<unsigned*>(&pixbuf[0]);
           const unsigned xDataLineSkip = pXImage->bytes_per_line;
-          const size_t copy_count = static_cast< size_t >( width ) * 4;
-          pixelFormat = Pixel::BGRA8888;
+          const size_t   copy_count    = static_cast<size_t>(width) * 4;
+          pixelFormat                  = Pixel::BGRA8888;
 
-          for(unsigned y = height-1; y < height; --y, bufPtr += width)
+          for(unsigned y = 0; y < height; ++y, bufPtr += width)
           {
-            const char * const in = pXImage->data + xDataLineSkip * y;
+            const char* const in = pXImage->data + xDataLineSkip * y;
 
             // Copy a whole scanline at a time:
-            DALI_ASSERT_DEBUG( size_t( bufPtr ) >= size_t( &pixbuf[0] ));
-            DALI_ASSERT_DEBUG( reinterpret_cast<size_t>( bufPtr ) + copy_count <= reinterpret_cast<size_t>( &pixbuf[pixbuf.size()] ) );
-            DALI_ASSERT_DEBUG( in >= pXImage->data );
-            DALI_ASSERT_DEBUG( in + copy_count <= pXImage->data + xDataLineSkip * height );
-            __builtin_memcpy( bufPtr, in, copy_count );
+            DALI_ASSERT_DEBUG(size_t(bufPtr) >= size_t(&pixbuf[0]));
+            DALI_ASSERT_DEBUG(reinterpret_cast<size_t>(bufPtr) + copy_count <= reinterpret_cast<size_t>(&pixbuf[pixbuf.size()]));
+            DALI_ASSERT_DEBUG(in >= pXImage->data);
+            DALI_ASSERT_DEBUG(in + copy_count <= pXImage->data + xDataLineSkip * height);
+            __builtin_memcpy(bufPtr, in, copy_count);
           }
           success = true;
         }
@@ -255,34 +256,21 @@ bool NativeImageSourceX::GetPixels(std::vector<unsigned char>& pixbuf, unsigned&
   {
     DALI_LOG_ERROR("Failed to get pixels from NativeImageSource.\n");
     pixbuf.resize(0);
-    width = 0;
+    width  = 0;
     height = 0;
   }
 
   // Close the display connection
-  XCloseDisplay( displayConnection );
+  XCloseDisplay(displayConnection);
 
   return success;
 }
 
-bool NativeImageSourceX::EncodeToFile(const std::string& filename) const
-{
-  std::vector< unsigned char > pixbuf;
-  unsigned int width(0), height(0);
-  Pixel::Format pixelFormat;
-
-  if(GetPixels(pixbuf, width, height, pixelFormat))
-  {
-    return Dali::EncodeToFile(&pixbuf[0], filename, pixelFormat, width, height);
-  }
-  return false;
-}
-
-void NativeImageSourceX::SetSource( Any source )
+void NativeImageSourceX::SetSource(Any source)
 {
-  mPixmap = GetPixmapFromAny( source );
+  mPixmap = GetPixmapFromAny(source);
 
-  if (mPixmap)
+  if(mPixmap)
   {
     // we don't own the pixmap
     mOwnPixmap = false;
@@ -292,36 +280,41 @@ void NativeImageSourceX::SetSource( Any source )
   }
 }
 
-bool NativeImageSourceX::IsColorDepthSupported( Dali::NativeImageSource::ColorDepth colorDepth )
+bool NativeImageSourceX::IsColorDepthSupported(Dali::NativeImageSource::ColorDepth colorDepth)
 {
   return true;
 }
 
-bool NativeImageSourceX::GlExtensionCreate()
+bool NativeImageSourceX::CreateResource()
 {
   // if the image existed previously delete it.
-  if (mEglImageKHR != NULL)
+  if(mEglImageKHR != NULL)
   {
-    GlExtensionDestroy();
+    DestroyResource();
   }
 
   // casting from an unsigned int to a void *, which should then be cast back
   // to an unsigned int in the driver.
-  EGLClientBuffer eglBuffer = reinterpret_cast< EGLClientBuffer > (mPixmap);
+  EGLClientBuffer eglBuffer = reinterpret_cast<EGLClientBuffer>(mPixmap);
 
-  mEglImageKHR = mEglImageExtensions->CreateImageKHR( eglBuffer );
+  mEglImageKHR = mEglImageExtensions->CreateImageKHR(eglBuffer);
 
   return mEglImageKHR != NULL;
 }
 
-void NativeImageSourceX::GlExtensionDestroy()
+void NativeImageSourceX::DestroyResource()
 {
   mEglImageExtensions->DestroyImageKHR(mEglImageKHR);
 
   mEglImageKHR = NULL;
+
+  if(mResourceDestructionCallback)
+  {
+    mResourceDestructionCallback->Trigger();
+  }
 }
 
-unsigned int NativeImageSourceX::TargetTexture()
+uint32_t NativeImageSourceX::TargetTexture()
 {
   mEglImageExtensions->TargetTextureKHR(mEglImageKHR);
 
@@ -334,7 +327,7 @@ void NativeImageSourceX::PrepareTexture()
 
 int NativeImageSourceX::GetPixelDepth(Dali::NativeImageSource::ColorDepth depth) const
 {
-  switch (depth)
+  switch(depth)
   {
     case Dali::NativeImageSource::COLOR_DEPTH_DEFAULT:
     {
@@ -365,15 +358,40 @@ int NativeImageSourceX::GetPixelDepth(Dali::NativeImageSource::ColorDepth depth)
   }
 }
 
+int NativeImageSourceX::GetTextureTarget() const
+{
+  return GL_TEXTURE_2D;
+}
+
+bool NativeImageSourceX::ApplyNativeFragmentShader(std::string& shader)
+{
+  return false;
+}
+
+const char* NativeImageSourceX::GetCustomSamplerTypename() const
+{
+  return nullptr;
+}
+
+Any NativeImageSourceX::GetNativeImageHandle() const
+{
+  return Any(mPixmap);
+}
+
+bool NativeImageSourceX::SourceChanged() const
+{
+  return false;
+}
+
 Ecore_X_Pixmap NativeImageSourceX::GetPixmapFromAny(Any pixmap) const
 {
-  if (pixmap.Empty())
+  if(pixmap.Empty())
   {
     return 0;
   }
 
   // see if it is of type x11 pixmap
-  if (pixmap.GetType() == typeid (Pixmap))
+  if(pixmap.GetType() == typeid(Pixmap))
   {
     // get the x pixmap type
     Pixmap xpixmap = AnyCast<Pixmap>(pixmap);
@@ -392,19 +410,34 @@ void NativeImageSourceX::GetPixmapDetails()
   int x, y;
 
   // get the width, height and depth
-  ecore_x_pixmap_geometry_get( mPixmap, &x, &y, reinterpret_cast< int* >( &mWidth ), reinterpret_cast< int* >( &mHeight ) );
+  ecore_x_pixmap_geometry_get(mPixmap, &x, &y, reinterpret_cast<int*>(&mWidth), reinterpret_cast<int*>(&mHeight));
 
   // set whether blending is required according to pixel format based on the depth
   /* default pixel format is RGB888
      If depth = 8, Pixel::A8;
      If depth = 16, Pixel::RGB565;
      If depth = 32, Pixel::RGBA8888 */
-  int depth = ecore_x_pixmap_depth_get(mPixmap);
-  mBlendingRequired = ( depth == 32 || depth == 8 );
+  int depth         = ecore_x_pixmap_depth_get(mPixmap);
+  mBlendingRequired = (depth == 32 || depth == 8);
+}
+
+uint8_t* NativeImageSourceX::AcquireBuffer(uint16_t& width, uint16_t& height, uint16_t& stride)
+{
+  return NULL;
+}
+
+bool NativeImageSourceX::ReleaseBuffer()
+{
+  return false;
+}
+
+void NativeImageSourceX::SetResourceDestructionCallback(EventThreadCallback* callback)
+{
+  mResourceDestructionCallback = std::unique_ptr<EventThreadCallback>(callback);
 }
 
 } // namespace Adaptor
 
-} // namespace internal
+} // namespace Internal
 
 } // namespace Dali