Send PixelData instead of raw buffer
[platform/core/uifw/dali-core.git] / dali / internal / render / renderers / render-texture.cpp
index 1e74ce3..f016af6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
@@ -22,6 +22,7 @@
 
 // INTERNAL INCLUDES
 #include <dali/integration-api/debug.h>
+#include <dali/internal/common/memory-pool-object-allocator.h>
 
 namespace Dali
 {
@@ -35,6 +36,9 @@ namespace
 Debug::Filter* gTextureFilter = Debug::Filter::New(Debug::Concise, false, "LOG_TEXTURE");
 #endif
 
+// Memory pool used to allocate new textures. Memory used by this pool will be released when shutting down DALi
+MemoryPoolObjectAllocator<Texture> gTextureMemoryPool;
+
 /**
  * Converts DALi pixel format to Graphics::Format
  * @param format
@@ -107,10 +111,10 @@ constexpr Graphics::Format ConvertPixelFormat(Pixel::Format format)
       return Graphics::Format::ETC2_R8G8B8A1_SRGB_BLOCK; // no 'punchthrough' format
 
     case Pixel::COMPRESSED_RGBA8_ETC2_EAC:
-      return Graphics::Format::ETC2_R8G8B8_UNORM_BLOCK; // doesn't seem to map onto any format
+      return Graphics::Format::ETC2_R8G8B8A8_UNORM_BLOCK;
 
     case Pixel::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
-      return Graphics::Format::ETC2_R8G8B8A8_SRGB_BLOCK; // doesn't seem to map onto any format
+      return Graphics::Format::ETC2_R8G8B8A8_SRGB_BLOCK;
 
     case Pixel::COMPRESSED_RGB8_ETC1:
       return Graphics::Format::ETC2_R8G8B8_UNORM_BLOCK; // doesn't seem to be supported at all
@@ -148,7 +152,6 @@ constexpr Graphics::Format ConvertPixelFormat(Pixel::Format format)
     case Pixel::COMPRESSED_RGBA_ASTC_12x12_KHR:
       return Graphics::Format::ASTC_12x12_UNORM_BLOCK;
     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
-
       return Graphics::Format::ASTC_4x4_SRGB_BLOCK; // not type with alpha, but likely to use SRGB
     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
       return Graphics::Format::ASTC_5x4_SRGB_BLOCK;
@@ -176,10 +179,18 @@ constexpr Graphics::Format ConvertPixelFormat(Pixel::Format format)
       return Graphics::Format::ASTC_12x10_SRGB_BLOCK;
     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
       return Graphics::Format::ASTC_12x12_SRGB_BLOCK;
+
     case Pixel::RGB16F:
       return Graphics::Format::R16G16B16_SFLOAT;
     case Pixel::RGB32F:
       return Graphics::Format::R32G32B32_SFLOAT;
+    case Pixel::R11G11B10F:
+      return Graphics::Format::R11G11B10_UFLOAT_PACK32;
+
+    case Pixel::CHROMINANCE_U:
+      return Graphics::Format::L8;
+    case Pixel::CHROMINANCE_V:
+      return Graphics::Format::L8;
   }
   return Graphics::Format::UNDEFINED;
 }
@@ -198,6 +209,24 @@ constexpr Graphics::TextureType ConvertType(Texture::Type type)
 
 } //Unnamed namespace
 
+TextureKey Texture::NewKey(Type type, Pixel::Format format, ImageDimensions size)
+{
+  void* ptr = gTextureMemoryPool.AllocateRawThreadSafe();
+  auto  key = gTextureMemoryPool.GetKeyFromPtr(static_cast<Texture*>(ptr));
+  new(ptr) Texture(type, format, size);
+
+  return TextureKey(key);
+}
+
+TextureKey Texture::NewKey(NativeImageInterfacePtr nativeImageInterface)
+{
+  void* ptr = gTextureMemoryPool.AllocateRawThreadSafe();
+  auto  key = gTextureMemoryPool.GetKeyFromPtr(static_cast<Texture*>(ptr));
+  new(ptr) Texture(nativeImageInterface);
+
+  return TextureKey(key);
+}
+
 Texture::Texture(Type type, Pixel::Format format, ImageDimensions size)
 : mGraphicsController(nullptr),
   mGraphicsTexture(nullptr),
@@ -207,7 +236,8 @@ Texture::Texture(Type type, Pixel::Format format, ImageDimensions size)
   mWidth(size.GetWidth()),
   mHeight(size.GetHeight()),
   mType(type),
-  mHasAlpha(HasAlpha(format))
+  mHasAlpha(HasAlpha(format)),
+  mUpdated(true)
 {
 }
 
@@ -220,12 +250,23 @@ Texture::Texture(NativeImageInterfacePtr nativeImageInterface)
   mWidth(static_cast<uint16_t>(nativeImageInterface->GetWidth())),   // ignoring overflow, not happening in practice
   mHeight(static_cast<uint16_t>(nativeImageInterface->GetHeight())), // ignoring overflow, not happening in practice
   mType(TextureType::TEXTURE_2D),
-  mHasAlpha(nativeImageInterface->RequiresBlending())
+  mHasAlpha(nativeImageInterface->RequiresBlending()),
+  mUpdated(true)
 {
 }
 
 Texture::~Texture() = default;
 
+void Texture::operator delete(void* ptr)
+{
+  gTextureMemoryPool.FreeThreadSafe(static_cast<Texture*>(ptr));
+}
+
+Render::Texture* Texture::Get(TextureKey::KeyType key)
+{
+  return gTextureMemoryPool.GetPtrFromKey(key);
+}
+
 void Texture::Initialize(Graphics::Controller& graphicsController)
 {
   mGraphicsController = &graphicsController;
@@ -271,7 +312,7 @@ void Texture::CreateWithData(Graphics::TextureUsageFlags usage, uint8_t* data, u
 
 void Texture::Upload(PixelDataPtr pixelData, const Internal::Texture::UploadParams& params)
 {
-  DALI_ASSERT_ALWAYS(mNativeImage == nullptr);
+  DALI_ASSERT_ALWAYS(!mNativeImage);
 
   if(!mGraphicsTexture)
   {
@@ -279,21 +320,67 @@ void Texture::Upload(PixelDataPtr pixelData, const Internal::Texture::UploadPara
   }
 
   Graphics::TextureUpdateInfo info{};
+
+  const uint32_t srcStride = pixelData->GetStride();
+  uint32_t       srcOffset = 0u;
+  uint32_t       srcSize   = pixelData->GetBufferSize();
+
+  const bool requiredSubPixelData = (!Pixel::IsCompressed(pixelData->GetPixelFormat())) &&
+                                    ((params.dataXOffset != 0) ||
+                                     (params.dataYOffset != 0) ||
+                                     (params.dataWidth != pixelData->GetWidth()) ||
+                                     (params.dataHeight != pixelData->GetHeight()));
+
+  if(requiredSubPixelData)
+  {
+    /**
+     * TextureUpdateInfo use byte scaled offset / size.
+     *
+     * To make we only use sub-data of inputed PixelData, make srcOffset as 'start of SubPixelData.
+     *
+     *   |---- dataStrideByte -----|
+     *   |-----| <-- dataXOffsetByte
+     *   ...........................
+     *   ......A-----------+........
+     *   ......|           |........
+     *   ......|           |........
+     *   ......+-----------+C.......
+     *   ......B....................
+     *
+     * A) Start of SubPixelData. offsetByte = dataStrideByte * dataYOffset + dataXOffsetByte.
+     * B) offsetByte = A).offsetByte + dataStrideByte * dataHeight. Note, It can be out of original PixelData boundary.
+     * C) End of SubPixelData. offsetByte = B).offsetByte - dataStrideByte + dataWidthByte.
+     *
+     * srcOffset = A).offsetByte;
+     * srcSize = ( C).offsetByte - A).offsetByte );
+     */
+    const uint32_t bytePerPixel    = Pixel::GetBytesPerPixel(pixelData->GetPixelFormat());
+    const uint32_t dataStrideByte  = (srcStride ? srcStride : static_cast<uint32_t>(params.dataWidth)) * bytePerPixel;
+    const uint32_t dataXOffsetByte = params.dataXOffset * bytePerPixel;
+    const uint32_t dataWidthByte   = static_cast<uint32_t>(params.dataWidth) * bytePerPixel;
+
+    srcOffset = params.dataYOffset * dataStrideByte + dataXOffsetByte;
+    srcSize   = static_cast<uint32_t>(params.dataHeight) * dataStrideByte - (dataStrideByte - dataWidthByte);
+  }
+
   info.dstTexture   = mGraphicsTexture.get();
   info.dstOffset2D  = {params.xOffset, params.yOffset};
   info.layer        = params.layer;
   info.level        = params.mipmap;
   info.srcReference = 0;
-  info.srcExtent2D  = {params.width, params.height};
-  info.srcOffset    = 0;
-  info.srcSize      = pixelData->GetBufferSize();
+  info.srcExtent2D  = {params.dataWidth, params.dataHeight};
+  info.srcOffset    = srcOffset;
+  info.srcSize      = srcSize;
+  info.srcStride    = srcStride;
   info.srcFormat    = ConvertPixelFormat(pixelData->GetPixelFormat());
 
   Graphics::TextureUpdateSourceInfo updateSourceInfo{};
-  updateSourceInfo.sourceType          = Graphics::TextureUpdateSourceInfo::Type::MEMORY;
-  updateSourceInfo.memorySource.memory = pixelData->GetBuffer();
+  updateSourceInfo.sourceType                = Graphics::TextureUpdateSourceInfo::Type::PIXEL_DATA;
+  updateSourceInfo.pixelDataSource.pixelData = Dali::PixelData(pixelData.Get());
 
   mGraphicsController->UpdateTextures({info}, {updateSourceInfo});
+
+  SetUpdated(true);
 }
 
 bool Texture::HasAlphaChannel() const
@@ -316,6 +403,11 @@ void Texture::GenerateMipmaps()
   mGraphicsController->GenerateTextureMipmaps(*mGraphicsTexture.get());
 }
 
+void Texture::OnRenderFinished()
+{
+  SetUpdated(false);
+}
+
 } // namespace Render
 
 } // namespace Internal