Make PixelData flag that we release buffer after texture upload
[platform/core/uifw/dali-adaptor.git] / dali / internal / imaging / common / pixel-buffer-impl.cpp
index 533db68..3afdce5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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/common/pixel-buffer-impl.h>
 
 // EXTERNAL INCLUDES
+#include <dali/integration-api/pixel-data-integ.h>
 #include <stdlib.h>
 #include <cstring>
 
 // INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
 #include <dali/internal/imaging/common/alpha-mask.h>
 #include <dali/internal/imaging/common/gaussian-blur.h>
 #include <dali/internal/imaging/common/image-operations.h>
@@ -36,6 +38,10 @@ namespace Adaptor
 {
 namespace
 {
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gPixelBufferFilter = Debug::Filter::New(Debug::NoLogging, false, "DALI_LOG_PIXEL_BUFFER_SIZE");
+#endif
+
 const float TWO_PI = 2.f * Math::PI; ///< 360 degrees in radians
 // based on W3C Recommendations (https://www.w3.org/TR/AERT/#color-contrast)
 constexpr uint32_t BRIGHTNESS_CONSTANT_R = 299;
@@ -43,11 +49,15 @@ constexpr uint32_t BRIGHTNESS_CONSTANT_G = 587;
 constexpr uint32_t BRIGHTNESS_CONSTANT_B = 114;
 } // namespace
 
-PixelBuffer::PixelBuffer(unsigned char*      buffer,
-                         unsigned int        bufferSize,
-                         unsigned int        width,
-                         unsigned int        height,
-                         unsigned int        stride,
+#if defined(DEBUG_ENABLED)
+uint32_t PixelBuffer::gPixelBufferAllocationTotal{0};
+#endif
+
+PixelBuffer::PixelBuffer(uint8_t*            buffer,
+                         uint32_t            bufferSize,
+                         uint32_t            width,
+                         uint32_t            height,
+                         uint32_t            stride,
                          Dali::Pixel::Format pixelFormat)
 : mMetadata(),
   mBuffer(buffer),
@@ -65,53 +75,75 @@ PixelBuffer::~PixelBuffer()
   ReleaseBuffer();
 }
 
-PixelBufferPtr PixelBuffer::New(unsigned int        width,
-                                unsigned int        height,
+PixelBufferPtr PixelBuffer::New(uint32_t            width,
+                                uint32_t            height,
                                 Dali::Pixel::Format pixelFormat)
 {
-  unsigned int   bufferSize = width * height * Dali::Pixel::GetBytesPerPixel(pixelFormat);
-  unsigned char* buffer     = NULL;
+  uint32_t bufferSize = width * height * Dali::Pixel::GetBytesPerPixel(pixelFormat);
+  uint8_t* buffer     = NULL;
   if(bufferSize > 0)
   {
-    buffer = static_cast<unsigned char*>(malloc(bufferSize));
+    buffer = static_cast<uint8_t*>(malloc(bufferSize));
+#if defined(DEBUG_ENABLED)
+    gPixelBufferAllocationTotal += bufferSize;
+#endif
   }
+  DALI_LOG_INFO(gPixelBufferFilter, Debug::Concise, "Allocated PixelBuffer of size %u\n", bufferSize);
+
   return new PixelBuffer(buffer, bufferSize, width, height, width, pixelFormat);
 }
 
-PixelBufferPtr PixelBuffer::New(unsigned char*      buffer,
-                                unsigned int        bufferSize,
-                                unsigned int        width,
-                                unsigned int        height,
-                                unsigned int        stride,
+PixelBufferPtr PixelBuffer::New(uint8_t*            buffer,
+                                uint32_t            bufferSize,
+                                uint32_t            width,
+                                uint32_t            height,
+                                uint32_t            stride,
                                 Dali::Pixel::Format pixelFormat)
 {
   return new PixelBuffer(buffer, bufferSize, width, height, stride, pixelFormat);
 }
 
-Dali::PixelData PixelBuffer::Convert(PixelBuffer& pixelBuffer)
-{
-  Dali::PixelData pixelData = Dali::PixelData::New(pixelBuffer.mBuffer,
-                                                   pixelBuffer.mBufferSize,
-                                                   pixelBuffer.mWidth,
-                                                   pixelBuffer.mHeight,
-                                                   pixelBuffer.mStride,
-                                                   pixelBuffer.mPixelFormat,
-                                                   Dali::PixelData::FREE);
-  pixelBuffer.mBuffer       = NULL;
-  pixelBuffer.mWidth        = 0;
-  pixelBuffer.mHeight       = 0;
-  pixelBuffer.mBufferSize   = 0;
-  pixelBuffer.mStride       = 0;
+Dali::PixelData PixelBuffer::Convert(PixelBuffer& pixelBuffer, bool releaseAfterUpload)
+{
+#if defined(DEBUG_ENABLED)
+  gPixelBufferAllocationTotal -= pixelBuffer.mBufferSize;
+#endif
+  Dali::PixelData pixelData;
+  if(releaseAfterUpload)
+  {
+    pixelData = Dali::Integration::NewPixelDataWithReleaseAfterUpload(pixelBuffer.mBuffer,
+                                                                      pixelBuffer.mBufferSize,
+                                                                      pixelBuffer.mWidth,
+                                                                      pixelBuffer.mHeight,
+                                                                      pixelBuffer.mStride,
+                                                                      pixelBuffer.mPixelFormat,
+                                                                      Dali::PixelData::FREE);
+  }
+  else
+  {
+    pixelData = Dali::PixelData::New(pixelBuffer.mBuffer,
+                                     pixelBuffer.mBufferSize,
+                                     pixelBuffer.mWidth,
+                                     pixelBuffer.mHeight,
+                                     pixelBuffer.mStride,
+                                     pixelBuffer.mPixelFormat,
+                                     Dali::PixelData::FREE);
+  }
+  pixelBuffer.mBuffer     = NULL;
+  pixelBuffer.mWidth      = 0;
+  pixelBuffer.mHeight     = 0;
+  pixelBuffer.mBufferSize = 0;
+  pixelBuffer.mStride     = 0;
 
   return pixelData;
 }
 
-unsigned int PixelBuffer::GetWidth() const
+uint32_t PixelBuffer::GetWidth() const
 {
   return mWidth;
 }
 
-unsigned int PixelBuffer::GetHeight() const
+uint32_t PixelBuffer::GetHeight() const
 {
   return mHeight;
 }
@@ -126,28 +158,28 @@ Dali::Pixel::Format PixelBuffer::GetPixelFormat() const
   return mPixelFormat;
 }
 
-unsigned char* PixelBuffer::GetBuffer() const
+uint8_t* PixelBuffer::GetBuffer() const
 {
   return mBuffer;
 }
 
-const unsigned char* const PixelBuffer::GetConstBuffer() const
+const uint8_t* PixelBuffer::GetConstBuffer() const
 {
   return mBuffer;
 }
 
-unsigned int PixelBuffer::GetBufferSize() const
+uint32_t PixelBuffer::GetBufferSize() const
 {
   return mBufferSize;
 }
 
 Dali::PixelData PixelBuffer::CreatePixelData() const
 {
-  unsigned char* destBuffer = NULL;
+  uint8_t* destBuffer = NULL;
 
   if(mBufferSize > 0)
   {
-    destBuffer = static_cast<unsigned char*>(malloc(mBufferSize));
+    destBuffer = static_cast<uint8_t*>(malloc(mBufferSize));
     memcpy(destBuffer, mBuffer, mBufferSize);
   }
 
@@ -219,7 +251,11 @@ void PixelBuffer::ReleaseBuffer()
 {
   if(mBuffer)
   {
+#if defined(DEBUG_ENABLED)
+    gPixelBufferAllocationTotal -= mBufferSize;
+#endif
     free(mBuffer);
+    mBuffer = nullptr;
   }
 }
 
@@ -228,6 +264,9 @@ void PixelBuffer::AllocateFixedSize(uint32_t size)
   ReleaseBuffer();
   mBuffer     = reinterpret_cast<unsigned char*>(malloc(size));
   mBufferSize = size;
+#if defined(DEBUG_ENABLED)
+  gPixelBufferAllocationTotal += size;
+#endif
 }
 
 bool PixelBuffer::Rotate(Degree angle)
@@ -302,6 +341,10 @@ bool PixelBuffer::Rotate(Degree angle)
     pixelsOut   = nullptr;
     mBufferSize = mWidth * mHeight * pixelSize;
     mStride     = mWidth; // The buffer is tightly packed.
+
+#if defined(DEBUG_ENABLED)
+    gPixelBufferAllocationTotal += mBufferSize;
+#endif
   }
 
   return success;
@@ -349,12 +392,12 @@ PixelBufferPtr PixelBuffer::NewCrop(const PixelBuffer& inBuffer, uint16_t x, uin
     destStride = (inBuffer.mWidth - x) * bytesPerPixel;
   }
 
-  int            srcOffset  = x * bytesPerPixel + y * srcStride;
-  int            destOffset = 0;
-  unsigned char* destBuffer = outBuffer->mBuffer;
+  int      srcOffset  = x * bytesPerPixel + y * srcStride;
+  int      destOffset = 0;
+  uint8_t* destBuffer = outBuffer->mBuffer;
 
   // Clamp crop to last row
-  unsigned int endRow = y + cropDimensions.GetHeight();
+  uint16_t endRow = y + cropDimensions.GetHeight();
   if(endRow > inBuffer.mHeight)
   {
     endRow = inBuffer.mHeight - 1;
@@ -450,15 +493,15 @@ void PixelBuffer::ApplyGaussianBlur(const float blurRadius)
 
 void PixelBuffer::MultiplyColorByAlpha()
 {
-  auto bytesPerPixel = Pixel::GetBytesPerPixel(mPixelFormat);
-
   // Compressed textures have unknown size of the pixel. Alpha premultiplication
   // must be skipped in such case
-  if(Pixel::GetBytesPerPixel(mPixelFormat) && Pixel::HasAlpha(mPixelFormat))
+  if(!Pixel::IsCompressed(mPixelFormat) && Pixel::HasAlpha(mPixelFormat))
   {
-    unsigned char*     pixel       = mBuffer;
-    const unsigned int strideBytes = mStride * bytesPerPixel;
-    const unsigned int widthBytes  = mWidth * bytesPerPixel;
+    auto bytesPerPixel = Pixel::GetBytesPerPixel(mPixelFormat);
+
+    uint8_t*       pixel       = mBuffer;
+    const uint32_t strideBytes = mStride * bytesPerPixel;
+    const uint32_t widthBytes  = mWidth * bytesPerPixel;
 
     // Collect all valid channel list before lookup whole buffer
     std::vector<Channel> validChannelList;
@@ -472,11 +515,11 @@ void PixelBuffer::MultiplyColorByAlpha()
 
     if(DALI_LIKELY(!validChannelList.empty()))
     {
-      for(unsigned int y = 0; y < mHeight; y++)
+      for(uint32_t y = 0; y < mHeight; y++)
       {
-        for(unsigned int x = 0; x < widthBytes; x += bytesPerPixel)
+        for(uint32_t x = 0; x < widthBytes; x += bytesPerPixel)
         {
-          unsigned int alpha = ReadChannel(&pixel[x], mPixelFormat, Adaptor::ALPHA);
+          uint32_t alpha = ReadChannel(&pixel[x], mPixelFormat, Adaptor::ALPHA);
           if(alpha < 255)
           {
             // If alpha is 255, we don't need to change color. Skip current pixel
@@ -515,7 +558,7 @@ uint32_t PixelBuffer::GetBrightness() const
 
   if(bytesPerPixel && mWidth && mHeight)
   {
-    unsigned char* pixel       = mBuffer;
+    uint8_t*       pixel       = mBuffer;
     const uint32_t strideBytes = mStride * bytesPerPixel;
     const uint32_t widthBytes  = mWidth * bytesPerPixel;
     const uint32_t bufferSize  = mWidth * mHeight;
@@ -524,9 +567,9 @@ uint32_t PixelBuffer::GetBrightness() const
     uint64_t green = 0;
     uint64_t blue  = 0;
 
-    for(unsigned int y = 0; y < mHeight; y++)
+    for(uint32_t y = 0; y < mHeight; y++)
     {
-      for(unsigned int x = 0; x < widthBytes; x += bytesPerPixel)
+      for(uint32_t x = 0; x < widthBytes; x += bytesPerPixel)
       {
         red += ReadChannel(&pixel[x], mPixelFormat, Adaptor::RED);
         green += ReadChannel(&pixel[x], mPixelFormat, Adaptor::GREEN);