[Tizen] Use environment variable for native image queue size
[platform/core/uifw/dali-adaptor.git] / dali / internal / imaging / tizen / native-image-source-queue-impl-tizen.cpp
index 7f72939..c47b775 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,10 +37,6 @@ namespace Adaptor
 {
 namespace
 {
-#define TBM_SURFACE_QUEUE_SIZE 3
-
-const char* SAMPLER_TYPE = "samplerExternalOES";
-
 // clang-format off
 int FORMATS_BLENDING_REQUIRED[] = {
   TBM_FORMAT_ARGB4444, TBM_FORMAT_ABGR4444,
@@ -54,43 +51,54 @@ 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)
-: mCustomFragmentPrefix(),
-  mMutex(),
+NativeImageSourceQueueTizen::NativeImageSourceQueueTizen(uint32_t width, uint32_t height, Dali::NativeImageSourceQueue::ColorFormat colorFormat, Any nativeImageSourceQueue)
+: mMutex(),
   mWidth(width),
   mHeight(height),
   mTbmQueue(NULL),
   mConsumeSurface(NULL),
   mEglImages(),
+  mBuffers(),
   mEglGraphics(NULL),
   mEglImageExtensions(NULL),
   mOwnTbmQueue(false),
-  mBlendingRequired(false)
+  mBlendingRequired(false),
+  mIsResized(false)
 {
   DALI_ASSERT_ALWAYS(Adaptor::IsAvailable());
 
   GraphicsInterface* graphics = &(Adaptor::GetImplementation(Adaptor::Get()).GetGraphicsInterface());
   mEglGraphics                = static_cast<EglGraphics*>(graphics);
 
-  mCustomFragmentPrefix = mEglGraphics->GetEglImageExtensionString();
-
   mTbmQueue = GetSurfaceFromAny(nativeImageSourceQueue);
 
   if(mTbmQueue != NULL)
@@ -112,7 +120,7 @@ NativeImageSourceQueueTizen::~NativeImageSourceQueueTizen()
   }
 }
 
-void NativeImageSourceQueueTizen::Initialize(Dali::NativeImageSourceQueue::ColorDepth depth)
+void NativeImageSourceQueueTizen::Initialize(Dali::NativeImageSourceQueue::ColorFormat colorFormat)
 {
   if(mWidth == 0 || mHeight == 0)
   {
@@ -121,31 +129,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:
       {
-        format            = TBM_FORMAT_RGB888;
+        tbmFormat         = TBM_FORMAT_XRGB8888;
+        mBlendingRequired = false;
+        break;
+      }
+      case Dali::NativeImageSourceQueue::ColorFormat::RGB888: // TODO : Implement me after other codes fixed.
+      case Dali::NativeImageSourceQueue::ColorFormat::BGR888:
+      {
+        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);
@@ -182,12 +198,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()
@@ -210,6 +230,78 @@ void NativeImageSourceQueueTizen::IgnoreSourceImage()
   }
 }
 
+bool NativeImageSourceQueueTizen::CanDequeueBuffer()
+{
+  Dali::Mutex::ScopedLock lock(mMutex);
+  if(tbm_surface_queue_can_dequeue(mTbmQueue, 0))
+  {
+    return true;
+  }
+  return false;
+}
+
+uint8_t* NativeImageSourceQueueTizen::DequeueBuffer(uint32_t& width, uint32_t& height, uint32_t& stride)
+{
+  Dali::Mutex::ScopedLock lock(mMutex);
+  if(mTbmQueue == NULL)
+  {
+    DALI_LOG_ERROR("TbmQueue is NULL");
+    return NULL;
+  }
+
+  tbm_surface_h tbmSurface;
+  if(tbm_surface_queue_dequeue(mTbmQueue, &tbmSurface) != TBM_SURFACE_QUEUE_ERROR_NONE)
+  {
+    DALI_LOG_ERROR("Failed to dequeue a tbm_surface [%p]\n", tbmSurface);
+    return NULL;
+  }
+
+  tbm_surface_info_s info;
+  int                ret = tbm_surface_map(tbmSurface, TBM_OPTION_WRITE, &info);
+  if(ret != TBM_SURFACE_ERROR_NONE)
+  {
+    DALI_LOG_ERROR("tbm_surface_map is failed! [%d] [%p]\n", ret, tbmSurface);
+    tbm_surface_queue_cancel_dequeue(mTbmQueue, tbmSurface);
+    return NULL;
+  }
+
+  unsigned char* buffer = info.planes[0].ptr;
+  if(!buffer)
+  {
+    DALI_LOG_ERROR("tbm buffer pointer is null! [%p]\n", tbmSurface);
+    tbm_surface_unmap(tbmSurface);
+    tbm_surface_queue_cancel_dequeue(mTbmQueue, tbmSurface);
+    return NULL;
+  }
+
+  tbm_surface_internal_ref(tbmSurface);
+
+  stride = info.planes[0].stride;
+  width  = mWidth;
+  height = mHeight;
+
+  // Push the buffer
+  mBuffers.push_back(BufferPair(tbmSurface, buffer));
+  return buffer;
+}
+
+bool NativeImageSourceQueueTizen::EnqueueBuffer(uint8_t* buffer)
+{
+  Dali::Mutex::ScopedLock lock(mMutex);
+  auto                    bufferInstance = std::find_if(mBuffers.begin(),
+                                     mBuffers.end(),
+                                     [buffer](BufferPair pair) { return (pair.second == buffer); });
+  if(bufferInstance != mBuffers.end())
+  {
+    tbm_surface_internal_unref((*bufferInstance).first);
+    tbm_surface_unmap((*bufferInstance).first);
+    tbm_surface_queue_enqueue(mTbmQueue, (*bufferInstance).first);
+    mBuffers.erase(bufferInstance);
+    return true;
+  }
+  return false;
+}
+
 bool NativeImageSourceQueueTizen::CreateResource()
 {
   mEglImageExtensions = mEglGraphics->GetImageExtensions();
@@ -222,7 +314,7 @@ void NativeImageSourceQueueTizen::DestroyResource()
 {
   Dali::Mutex::ScopedLock lock(mMutex);
 
-  ResetEglImageList();
+  ResetEglImageList(true);
 }
 
 uint32_t NativeImageSourceQueueTizen::TargetTexture()
@@ -252,6 +344,12 @@ void NativeImageSourceQueueTizen::PrepareTexture()
       }
     }
 
+    if(mIsResized)
+    {
+      ResetEglImageList(false);
+      mIsResized = false;
+    }
+
     if(mConsumeSurface)
     {
       bool existing = false;
@@ -280,9 +378,9 @@ void NativeImageSourceQueueTizen::PrepareTexture()
   }
 }
 
-const char* NativeImageSourceQueueTizen::GetCustomFragmentPrefix() const
+bool NativeImageSourceQueueTizen::ApplyNativeFragmentShader(std::string& shader)
 {
-  return mCustomFragmentPrefix;
+  return mEglGraphics->ApplyNativeFragmentShader(shader, SAMPLER_TYPE);
 }
 
 const char* NativeImageSourceQueueTizen::GetCustomSamplerTypename() const
@@ -305,9 +403,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))
     {
@@ -327,7 +427,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])
     {