Merge "Add FreeReleasedBuffers method to NativeImageSourceQueue" into devel/master
[platform/core/uifw/dali-adaptor.git] / dali / internal / imaging / tizen / native-image-source-queue-impl-tizen.cpp
index 35d4458..b5d926b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -24,6 +24,7 @@
 #include <tbm_surface_internal.h>
 
 // INTERNAL INCLUDES
+#include <dali/devel-api/adaptor-framework/environment-variable.h>
 #include <dali/internal/adaptor/common/adaptor-impl.h>
 #include <dali/internal/graphics/common/egl-image-extensions.h>
 #include <dali/internal/graphics/gles/egl-graphics.h>
@@ -36,11 +37,6 @@ namespace Adaptor
 {
 namespace
 {
-#define TBM_SURFACE_QUEUE_SIZE 3
-
-const char* FRAGMENT_PREFIX = "#extension GL_OES_EGL_image_external:require\n";
-const char* SAMPLER_TYPE    = "samplerExternalOES";
-
 // clang-format off
 int FORMATS_BLENDING_REQUIRED[] = {
   TBM_FORMAT_ARGB4444, TBM_FORMAT_ABGR4444,
@@ -55,24 +51,36 @@ int FORMATS_BLENDING_REQUIRED[] = {
 };
 // clang-format on
 
-const int NUM_FORMATS_BLENDING_REQUIRED = 18;
+const char* SAMPLER_TYPE = "samplerExternalOES";
+
+constexpr int32_t NUM_FORMATS_BLENDING_REQUIRED = 18;
+
+constexpr int32_t DEFAULT_TBM_SURFACE_QUEUE_SIZE = 3u;
+constexpr auto    TBM_SURFACE_QUEUE_SIZE         = "DALI_TBM_SURFACE_QUEUE_SIZE";
+
+int32_t GetTbmSurfaceQueueSize()
+{
+  static auto    queueSizeString = EnvironmentVariable::GetEnvironmentVariable(TBM_SURFACE_QUEUE_SIZE);
+  static int32_t queueSize       = queueSizeString ? std::atoi(queueSizeString) : DEFAULT_TBM_SURFACE_QUEUE_SIZE;
+  return queueSize;
+}
 
 } // namespace
 
-NativeImageSourceQueueTizen* NativeImageSourceQueueTizen::New(uint32_t width, uint32_t height, Dali::NativeImageSourceQueue::ColorDepth depth, Any nativeImageSourceQueue)
+NativeImageSourceQueueTizen* NativeImageSourceQueueTizen::New(uint32_t width, uint32_t height, Dali::NativeImageSourceQueue::ColorFormat colorFormat, Any nativeImageSourceQueue)
 {
-  NativeImageSourceQueueTizen* image = new NativeImageSourceQueueTizen(width, height, depth, nativeImageSourceQueue);
+  NativeImageSourceQueueTizen* image = new NativeImageSourceQueueTizen(width, height, colorFormat, nativeImageSourceQueue);
   DALI_ASSERT_DEBUG(image && "NativeImageSourceQueueTizen allocation failed.");
 
   if(image)
   {
-    image->Initialize(depth);
+    image->Initialize(colorFormat);
   }
 
   return image;
 }
 
-NativeImageSourceQueueTizen::NativeImageSourceQueueTizen(uint32_t width, uint32_t height, Dali::NativeImageSourceQueue::ColorDepth depth, Any nativeImageSourceQueue)
+NativeImageSourceQueueTizen::NativeImageSourceQueueTizen(uint32_t width, uint32_t height, Dali::NativeImageSourceQueue::ColorFormat colorFormat, Any nativeImageSourceQueue)
 : mMutex(),
   mWidth(width),
   mHeight(height),
@@ -83,7 +91,9 @@ NativeImageSourceQueueTizen::NativeImageSourceQueueTizen(uint32_t width, uint32_
   mEglGraphics(NULL),
   mEglImageExtensions(NULL),
   mOwnTbmQueue(false),
-  mBlendingRequired(false)
+  mBlendingRequired(false),
+  mIsResized(false),
+  mFreeRequest(false)
 {
   DALI_ASSERT_ALWAYS(Adaptor::IsAvailable());
 
@@ -111,7 +121,7 @@ NativeImageSourceQueueTizen::~NativeImageSourceQueueTizen()
   }
 }
 
-void NativeImageSourceQueueTizen::Initialize(Dali::NativeImageSourceQueue::ColorDepth depth)
+void NativeImageSourceQueueTizen::Initialize(Dali::NativeImageSourceQueue::ColorFormat colorFormat)
 {
   if(mWidth == 0 || mHeight == 0)
   {
@@ -120,31 +130,39 @@ void NativeImageSourceQueueTizen::Initialize(Dali::NativeImageSourceQueue::Color
 
   if(mTbmQueue == NULL)
   {
-    int format = TBM_FORMAT_ARGB8888;
+    int tbmFormat = TBM_FORMAT_ARGB8888;
 
-    switch(depth)
+    switch(colorFormat)
     {
-      case Dali::NativeImageSourceQueue::COLOR_DEPTH_DEFAULT:
-      case Dali::NativeImageSourceQueue::COLOR_DEPTH_32:
+      case Dali::NativeImageSourceQueue::ColorFormat::RGBA8888: // TODO : Implement me after other codes fixed.
+      case Dali::NativeImageSourceQueue::ColorFormat::BGRA8888:
       {
-        format            = TBM_FORMAT_ARGB8888;
+        tbmFormat         = TBM_FORMAT_ARGB8888;
         mBlendingRequired = true;
         break;
       }
-      case Dali::NativeImageSourceQueue::COLOR_DEPTH_24:
+      case Dali::NativeImageSourceQueue::ColorFormat::RGBX8888: // TODO : Implement me after other codes fixed.
+      case Dali::NativeImageSourceQueue::ColorFormat::BGRX8888:
+      {
+        tbmFormat         = TBM_FORMAT_XRGB8888;
+        mBlendingRequired = false;
+        break;
+      }
+      case Dali::NativeImageSourceQueue::ColorFormat::RGB888: // TODO : Implement me after other codes fixed.
+      case Dali::NativeImageSourceQueue::ColorFormat::BGR888:
       {
-        format            = TBM_FORMAT_RGB888;
+        tbmFormat         = TBM_FORMAT_RGB888;
         mBlendingRequired = false;
         break;
       }
       default:
       {
-        DALI_LOG_WARNING("Wrong color depth.\n");
+        DALI_LOG_WARNING("Wrong color format.\n");
         return;
       }
     }
 
-    mTbmQueue = tbm_surface_queue_create(TBM_SURFACE_QUEUE_SIZE, mWidth, mHeight, format, 0);
+    mTbmQueue = tbm_surface_queue_create(GetTbmSurfaceQueueSize(), mWidth, mHeight, tbmFormat, 0);
     if(!mTbmQueue)
     {
       DALI_LOG_ERROR("NativeImageSourceQueueTizen::Initialize: tbm_surface_queue_create is failed! [%p]\n", mTbmQueue);
@@ -181,12 +199,16 @@ void NativeImageSourceQueueTizen::SetSize(uint32_t width, uint32_t height)
 {
   Dali::Mutex::ScopedLock lock(mMutex);
 
-  tbm_surface_queue_reset(mTbmQueue, width, height, tbm_surface_queue_get_format(mTbmQueue));
+  if(mWidth == width && mHeight == height)
+  {
+    return;
+  }
 
-  mWidth  = width;
-  mHeight = height;
+  tbm_surface_queue_reset(mTbmQueue, width, height, tbm_surface_queue_get_format(mTbmQueue));
 
-  ResetEglImageList();
+  mWidth     = width;
+  mHeight    = height;
+  mIsResized = true;
 }
 
 void NativeImageSourceQueueTizen::IgnoreSourceImage()
@@ -281,6 +303,12 @@ bool NativeImageSourceQueueTizen::EnqueueBuffer(uint8_t* buffer)
   return false;
 }
 
+void NativeImageSourceQueueTizen::FreeReleasedBuffers()
+{
+  Dali::Mutex::ScopedLock lock(mMutex);
+  mFreeRequest = true;
+}
+
 bool NativeImageSourceQueueTizen::CreateResource()
 {
   mEglImageExtensions = mEglGraphics->GetImageExtensions();
@@ -293,7 +321,7 @@ void NativeImageSourceQueueTizen::DestroyResource()
 {
   Dali::Mutex::ScopedLock lock(mMutex);
 
-  ResetEglImageList();
+  ResetEglImageList(true);
 }
 
 uint32_t NativeImageSourceQueueTizen::TargetTexture()
@@ -305,22 +333,41 @@ void NativeImageSourceQueueTizen::PrepareTexture()
 {
   Dali::Mutex::ScopedLock lock(mMutex);
 
-  tbm_surface_h oldSurface = mConsumeSurface;
+  bool updated = false;
 
-  if(tbm_surface_queue_can_acquire(mTbmQueue, 0))
+  do
   {
-    if(tbm_surface_queue_acquire(mTbmQueue, &mConsumeSurface) != TBM_SURFACE_QUEUE_ERROR_NONE)
-    {
-      DALI_LOG_ERROR("Failed to aquire a tbm_surface\n");
-      return;
-    }
+    tbm_surface_h oldSurface = mConsumeSurface;
 
-    if(oldSurface)
+    if(tbm_surface_queue_can_acquire(mTbmQueue, 0))
     {
-      if(tbm_surface_internal_is_valid(oldSurface))
+      if(tbm_surface_queue_acquire(mTbmQueue, &mConsumeSurface) != TBM_SURFACE_QUEUE_ERROR_NONE)
+      {
+        DALI_LOG_ERROR("Failed to aquire a tbm_surface\n");
+        return;
+      }
+
+      if(oldSurface)
       {
-        tbm_surface_queue_release(mTbmQueue, oldSurface);
+        if(tbm_surface_internal_is_valid(oldSurface))
+        {
+          tbm_surface_queue_release(mTbmQueue, oldSurface);
+        }
       }
+      updated = true;
+    }
+    else
+    {
+      break;
+    }
+  } while(mFreeRequest); // Get the last one if buffer free was requested
+
+  if(updated)
+  {
+    if(mIsResized)
+    {
+      ResetEglImageList(false);
+      mIsResized = false;
     }
 
     if(mConsumeSurface)
@@ -349,11 +396,19 @@ void NativeImageSourceQueueTizen::PrepareTexture()
       }
     }
   }
-}
 
-const char* NativeImageSourceQueueTizen::GetCustomFragmentPrefix() const
-{
-  return FRAGMENT_PREFIX;
+  if(mFreeRequest)
+  {
+    auto iter = std::remove_if(mEglImages.begin(), mEglImages.end(), [&](EglImagePair& eglImage) {
+        if(mConsumeSurface == eglImage.first) return false;
+        mEglImageExtensions->DestroyImageKHR(eglImage.second);
+        tbm_surface_internal_unref(eglImage.first);
+        return true; });
+    mEglImages.erase(iter, mEglImages.end());
+
+    tbm_surface_queue_free_flush(mTbmQueue);
+    mFreeRequest = false;
+  }
 }
 
 bool NativeImageSourceQueueTizen::ApplyNativeFragmentShader(std::string& shader)
@@ -381,9 +436,11 @@ bool NativeImageSourceQueueTizen::SourceChanged() const
   return false;
 }
 
-void NativeImageSourceQueueTizen::ResetEglImageList()
+void NativeImageSourceQueueTizen::ResetEglImageList(bool releaseConsumeSurface)
 {
-  if(mConsumeSurface)
+  // When Tbm surface queue is reset(resized), the surface acquired before reset() is still valid, not the others.
+  // We can still use the acquired surface so that we will release it as the oldSurface in PrepareTexture() when the next surface is ready.
+  if(releaseConsumeSurface && mConsumeSurface)
   {
     if(tbm_surface_internal_is_valid(mConsumeSurface))
     {
@@ -403,7 +460,7 @@ void NativeImageSourceQueueTizen::ResetEglImageList()
 
 bool NativeImageSourceQueueTizen::CheckBlending(int format)
 {
-  for(int i = 0; i < NUM_FORMATS_BLENDING_REQUIRED; ++i)
+  for(int32_t i = 0; i < NUM_FORMATS_BLENDING_REQUIRED; ++i)
   {
     if(format == FORMATS_BLENDING_REQUIRED[i])
     {