Make Texture can use Uploaded data infomation 51/294351/11
authorEunki, Hong <eunkiki.hong@samsung.com>
Fri, 16 Jun 2023 07:22:25 +0000 (16:22 +0900)
committerEunki Hong <eunkiki.hong@samsung.com>
Mon, 10 Jul 2023 01:42:22 +0000 (10:42 +0900)
Make new way to use Dali::Texture that don't know the destination size.
For special case, if width and height are both 0, 0, and format is INVALID,
let we make to use uploaded pixeldata's size and format.

Change-Id: Ieec3f102d2568f3481344e164c5c29ff20c6a604
Signed-off-by: Eunki, Hong <eunkiki.hong@samsung.com>
automated-tests/src/dali/utc-Dali-Texture.cpp
dali/internal/event/rendering/texture-impl.cpp
dali/internal/event/rendering/texture-impl.h
dali/internal/render/common/render-manager.cpp
dali/internal/render/renderers/render-frame-buffer.h
dali/internal/render/renderers/render-texture.cpp
dali/internal/render/renderers/render-texture.h
dali/public-api/rendering/texture.cpp
dali/public-api/rendering/texture.h

index 3b63aa5..c817afa 100644 (file)
@@ -70,6 +70,16 @@ int UtcDaliTextureNew03(void)
   END_TEST;
 }
 
+int UtcDaliTextureNew04(void)
+{
+  TestApplication application;
+
+  Texture texture = Texture::New(TextureType::TEXTURE_2D);
+
+  DALI_TEST_CHECK(texture);
+  END_TEST;
+}
+
 int UtcDaliTextureCopyConstructor(void)
 {
   TestApplication application;
@@ -653,6 +663,80 @@ int UtcDaliTextureUpload07(void)
   END_TEST;
 }
 
+int UtcDaliTextureUpload08(void)
+{
+  TestApplication application;
+
+  //Create the texture without pixel information
+  tet_infoline("Creating a Texure without any size/format information");
+  Texture texture = Texture::New(TextureType::TEXTURE_2D);
+
+  application.GetGlAbstraction().EnableTextureCallTrace(true);
+
+  application.SendNotification();
+  application.Render();
+
+  TraceCallStack& callStack = application.GetGlAbstraction().GetTextureTrace();
+
+  tet_infoline("TexImage2D should not be called with a null pointer to reserve storage for the texture in the gpu");
+  DALI_TEST_CHECK(!callStack.FindMethod("GenTextures"));
+  DALI_TEST_CHECK(!callStack.FindMethod("TexImage2D"));
+
+  tet_infoline("Upload data to the texture");
+  unsigned int width(64);
+  unsigned int height(64);
+  callStack.Reset();
+
+  tet_infoline("Creating a RGB pixel buffer and adding that to the texture to ensure it is handled correctly");
+  unsigned int   bufferSize(width * height * 3);
+  unsigned char* buffer    = reinterpret_cast<unsigned char*>(malloc(bufferSize));
+  PixelData      pixelData = PixelData::New(buffer, bufferSize, width, height, Pixel::RGB888, PixelData::FREE);
+  texture.Upload(pixelData);
+  application.SendNotification();
+  application.Render();
+
+  tet_infoline("GetWidth / GetHeight / GetPixelFormat will return uploaded value");
+  DALI_TEST_EQUALS(texture.GetWidth(), width, TEST_LOCATION);
+  DALI_TEST_EQUALS(texture.GetHeight(), height, TEST_LOCATION);
+  DALI_TEST_EQUALS(texture.GetPixelFormat(), Pixel::RGB888, TEST_LOCATION);
+
+  tet_infoline("TexImage2D should be called to upload the data");
+  DALI_TEST_CHECK(callStack.FindMethod("GenTextures"));
+  {
+    std::stringstream out;
+    out << GL_TEXTURE_2D << ", " << 0u << ", " << width << ", " << height;
+    DALI_TEST_CHECK(callStack.FindMethodAndParams("TexImage2D", out.str().c_str()));
+  }
+
+  tet_infoline("Upload another data to the texture");
+  width  = 40;
+  height = 73;
+  callStack.Reset();
+
+  tet_infoline("Creating a RGB pixel buffer and adding that to the texture to ensure it is handled correctly");
+  bufferSize = width * height * 4;
+  buffer     = reinterpret_cast<unsigned char*>(malloc(bufferSize));
+  pixelData  = PixelData::New(buffer, bufferSize, width, height, Pixel::RGBA8888, PixelData::FREE);
+  texture.Upload(pixelData);
+  application.SendNotification();
+  application.Render();
+
+  tet_infoline("TexImage2D should be generate new graphics, and be called to upload the data");
+  DALI_TEST_CHECK(callStack.FindMethod("GenTextures"));
+  {
+    std::stringstream out;
+    out << GL_TEXTURE_2D << ", " << 0u << ", " << width << ", " << height;
+    DALI_TEST_CHECK(callStack.FindMethodAndParams("TexImage2D", out.str().c_str()));
+  }
+
+  tet_infoline("GetWidth / GetHeight / GetPixelFormat will return uploaded value");
+  DALI_TEST_EQUALS(texture.GetWidth(), width, TEST_LOCATION);
+  DALI_TEST_EQUALS(texture.GetHeight(), height, TEST_LOCATION);
+  DALI_TEST_EQUALS(texture.GetPixelFormat(), Pixel::RGBA8888, TEST_LOCATION);
+
+  END_TEST;
+}
+
 int UtcDaliTextureUploadSubPixelData01(void)
 {
   TestApplication application;
index c8a69b2..e582632 100644 (file)
@@ -54,7 +54,8 @@ Texture::Texture(TextureType::Type type, Pixel::Format format, ImageDimensions s
   mNativeImage(),
   mSize(size),
   mType(type),
-  mFormat(format)
+  mFormat(format),
+  mUseUploadedParameter(mSize.GetWidth() == 0u && mSize.GetHeight() == 0u && mFormat == Pixel::INVALID)
 {
 }
 
@@ -64,7 +65,8 @@ Texture::Texture(NativeImageInterfacePtr nativeImageInterface)
   mNativeImage(nativeImageInterface),
   mSize(nativeImageInterface->GetWidth(), nativeImageInterface->GetHeight()),
   mType(TextureType::TEXTURE_2D),
-  mFormat(Pixel::RGB888)
+  mFormat(Pixel::RGB888),
+  mUseUploadedParameter(false)
 {
 }
 
@@ -133,10 +135,8 @@ bool Texture::UploadSubPixelData(PixelDataPtr pixelData,
   constexpr auto max_value = std::numeric_limits<uint16_t>::max();
   DALI_ASSERT_ALWAYS(layer < max_value &&
                      mipmap < max_value &&
-                     xOffset < max_value &&
-                     yOffset < max_value &&
-                     width < max_value &&
-                     height < max_value &&
+                     xOffset + width < max_value &&
+                     yOffset + height < max_value &&
                      dataWidth < max_value &&
                      dataHeight < max_value &&
                      "Parameter value out of range");
@@ -158,7 +158,7 @@ bool Texture::UploadSubPixelData(PixelDataPtr pixelData,
       else
       {
         Pixel::Format pixelDataFormat = pixelData->GetPixelFormat();
-        if((pixelDataFormat == mFormat) || ((pixelDataFormat == Pixel::RGB888) && (mFormat == Pixel::RGBA8888)))
+        if((mUseUploadedParameter || pixelDataFormat == mFormat) || ((pixelDataFormat == Pixel::RGB888) && (mFormat == Pixel::RGBA8888)))
         {
           if(pixelDataSize < width * height)
           {
@@ -177,13 +177,20 @@ bool Texture::UploadSubPixelData(PixelDataPtr pixelData,
           {
             DALI_LOG_ERROR("PixelData of an incorrect subsize when trying to update texture\n");
           }
-          else if((xOffset + width > (mSize.GetWidth() / (1u << mipmap))) ||
-                  (yOffset + height > (mSize.GetHeight() / (1u << mipmap))))
+          else if(!mUseUploadedParameter &&
+                  ((xOffset + width > (static_cast<uint32_t>(mSize.GetWidth()) >> mipmap)) ||
+                   (yOffset + height > (static_cast<uint32_t>(mSize.GetHeight()) >> mipmap))))
           {
             DALI_LOG_ERROR("Texture update area out of bounds\n");
           }
           else
           {
+            if(mUseUploadedParameter)
+            {
+              mSize   = ImageDimensions(xOffset + width, yOffset + height);
+              mFormat = pixelDataFormat;
+            }
+
             //Parameters are correct. Send message to upload data to the texture
             UploadParams params = {static_cast<uint32_t>(dataXOffset),
                                    static_cast<uint32_t>(dataYOffset),
index 3f6166b..f97fd5a 100644 (file)
@@ -194,6 +194,8 @@ private:                                               // data
   ImageDimensions         mSize;        ///< Size of the texture
   Dali::TextureType::Type mType;        ///< Texture type (cached)
   Pixel::Format           mFormat;      ///< Pixel format
+
+  bool mUseUploadedParameter : 1; ///< Whether ths texture size and format depend on uploaded image or not.
 };
 
 } // namespace Internal
index afef026..adb9ba0 100644 (file)
@@ -202,10 +202,9 @@ struct RenderManager::Impl
   Integration::StencilBufferAvailable stencilBufferAvailable; ///< Whether the stencil buffer is available
   Integration::PartialUpdateAvailable partialUpdateAvailable; ///< Whether the partial update is available
 
-  std::unique_ptr<Dali::ThreadPool> threadPool;            ///< The thread pool
-  Vector<Graphics::Texture*>        boundTextures;         ///< The textures bound for rendering
-  Vector<Graphics::Texture*>        textureDependencyList; ///< The dependency list of bound textures
-  Vector<Render::TextureKey>        updatedTextures{};     ///< The updated texture list
+  std::unique_ptr<Dali::ThreadPool> threadPool;        ///< The thread pool
+  Vector<Graphics::Texture*>        boundTextures;     ///< The textures bound for rendering
+  Vector<Render::TextureKey>        updatedTextures{}; ///< The updated texture list
 
   uint32_t    frameCount{0u};                                                    ///< The current frame count
   BufferIndex renderBufferIndex{SceneGraphBuffers::INITIAL_UPDATE_BUFFER_INDEX}; ///< The index of the buffer to read from;
@@ -970,15 +969,6 @@ void RenderManager::RenderScene(Integration::RenderStatus& status, Integration::
     // this ensures we will set view and projection matrix once per program per camera
     mImpl->programController.ResetProgramMatrices();
 
-    if(instruction.mFrameBuffer)
-    {
-      // For each offscreen buffer, update the dependency list with the new texture id used by this frame buffer.
-      for(unsigned int i0 = 0, i1 = instruction.mFrameBuffer->GetColorAttachmentCount(); i0 < i1; ++i0)
-      {
-        mImpl->textureDependencyList.PushBack(instruction.mFrameBuffer->GetTexture(i0));
-      }
-    }
-
     if(!instruction.mIgnoreRenderToFbo && (instruction.mFrameBuffer != nullptr))
     {
       // Offscreen buffer rendering
index 097e703..e1eb657 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_RENDER_FRAME_BUFFER_H
 
 /*
- * Copyright (c) 2022 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.
@@ -119,15 +119,6 @@ public:
     return mCreateInfo.colorAttachments.size();
   }
 
-  /**
-   * @brief Get the texture bound to this frame buffer as color attachment @a index.
-   * @return The texture.
-   */
-  Graphics::Texture* GetTexture(uint8_t index)
-  {
-    return mCreateInfo.colorAttachments[index].texture;
-  };
-
   Graphics::Framebuffer* GetGraphicsObject()
   {
     return mGraphicsObject.get();
index eb5c3cf..a38ede9 100644 (file)
@@ -241,7 +241,8 @@ Texture::Texture(Type type, Pixel::Format format, ImageDimensions size)
   mHeight(size.GetHeight()),
   mType(type),
   mHasAlpha(HasAlpha(format)),
-  mUpdated(true)
+  mUpdated(true),
+  mUseUploadedParameter(mWidth == 0u && mHeight == 0u && mPixelFormat == Pixel::INVALID)
 {
 }
 
@@ -255,7 +256,8 @@ Texture::Texture(NativeImageInterfacePtr nativeImageInterface)
   mHeight(static_cast<uint16_t>(nativeImageInterface->GetHeight())), // ignoring overflow, not happening in practice
   mType(TextureType::TEXTURE_2D),
   mHasAlpha(nativeImageInterface->RequiresBlending()),
-  mUpdated(true)
+  mUpdated(true),
+  mUseUploadedParameter(false)
 {
 }
 
@@ -318,22 +320,20 @@ void Texture::Upload(PixelDataPtr pixelData, const Internal::Texture::UploadPara
 {
   DALI_ASSERT_ALWAYS(!mNativeImage);
 
-  if(!mGraphicsTexture)
-  {
-    Create(static_cast<Graphics::TextureUsageFlags>(Graphics::TextureUsageFlagBits::SAMPLE));
-  }
-
-  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())) &&
+  // Cache uploaded data
+  const auto uploadedDataWidth   = params.dataWidth;
+  const auto uploadedDataHeight  = params.dataHeight;
+  const auto uploadedPixelFormat = pixelData->GetPixelFormat();
+
+  const bool requiredSubPixelData = (!Pixel::IsCompressed(uploadedPixelFormat)) &&
                                     ((params.dataXOffset != 0) ||
                                      (params.dataYOffset != 0) ||
-                                     (params.dataWidth != pixelData->GetWidth()) ||
-                                     (params.dataHeight != pixelData->GetHeight()));
+                                     (uploadedDataWidth != pixelData->GetWidth()) ||
+                                     (uploadedDataHeight != pixelData->GetHeight()));
 
   if(requiredSubPixelData)
   {
@@ -358,25 +358,41 @@ void Texture::Upload(PixelDataPtr pixelData, const Internal::Texture::UploadPara
      * 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 bytePerPixel    = Pixel::GetBytesPerPixel(uploadedPixelFormat);
+    const uint32_t dataStrideByte  = (srcStride ? srcStride : pixelData->GetWidth()) * bytePerPixel;
     const uint32_t dataXOffsetByte = params.dataXOffset * bytePerPixel;
-    const uint32_t dataWidthByte   = static_cast<uint32_t>(params.dataWidth) * bytePerPixel;
+    const uint32_t dataWidthByte   = static_cast<uint32_t>(uploadedDataWidth) * bytePerPixel;
 
     srcOffset = params.dataYOffset * dataStrideByte + dataXOffsetByte;
-    srcSize   = static_cast<uint32_t>(params.dataHeight) * dataStrideByte - (dataStrideByte - dataWidthByte);
+    srcSize   = static_cast<uint32_t>(uploadedDataHeight) * dataStrideByte - (dataStrideByte - dataWidthByte);
   }
 
+  // Update render texture value as uploaded data.
+  if(mUseUploadedParameter)
+  {
+    mWidth       = params.xOffset + uploadedDataWidth;
+    mHeight      = params.yOffset + uploadedDataHeight;
+    mPixelFormat = uploadedPixelFormat;
+  }
+
+  // Always create new graphics texture object if we use uploaded parameter as texture.
+  if(!mGraphicsTexture || mUseUploadedParameter)
+  {
+    Create(static_cast<Graphics::TextureUsageFlags>(Graphics::TextureUsageFlagBits::SAMPLE));
+  }
+
+  Graphics::TextureUpdateInfo info{};
+
   info.dstTexture   = mGraphicsTexture.get();
   info.dstOffset2D  = {params.xOffset, params.yOffset};
   info.layer        = params.layer;
   info.level        = params.mipmap;
   info.srcReference = 0;
-  info.srcExtent2D  = {params.dataWidth, params.dataHeight};
+  info.srcExtent2D  = {uploadedDataWidth, uploadedDataHeight};
   info.srcOffset    = srcOffset;
   info.srcSize      = srcSize;
   info.srcStride    = srcStride;
-  info.srcFormat    = ConvertPixelFormat(pixelData->GetPixelFormat());
+  info.srcFormat    = ConvertPixelFormat(uploadedPixelFormat);
 
   mUpdatedArea = Rect<uint16_t>(params.xOffset, params.yOffset, params.width, params.height);
 
index 2e4dcee..8895cfc 100644 (file)
@@ -111,13 +111,6 @@ public:
   void Create(Graphics::TextureUsageFlags usage);
 
   /**
-   * Create a texture with a buffer if non-null
-   * @param[in] usage How texture will be used
-   * @param[in] buffer Buffer to copy
-   */
-  void CreateWithData(Graphics::TextureUsageFlags usage, uint8_t* buffer, uint32_t bufferSize);
-
-  /**
    * Deletes the texture from the GPU
    */
   void Destroy();
@@ -164,6 +157,15 @@ public:
   }
 
   /**
+   * Return the pixel format of the texture
+   * @return The pixel format of the texture data.
+   */
+  Pixel::Format GetPixelFormat() const
+  {
+    return mPixelFormat;
+  }
+
+  /**
    * Return the width of the texture
    * @return The width of the texture
    */
@@ -222,6 +224,14 @@ private:
    */
   void ApplySampler(Render::Sampler* sampler);
 
+  /**
+   * Create a texture with a buffer if non-null
+   * @param[in] usage How texture will be used
+   * @param[in] buffer Buffer to copy
+   * @param[in] bufferSize Size of buffer to copy
+   */
+  void CreateWithData(Graphics::TextureUsageFlags usage, uint8_t* buffer, uint32_t bufferSize);
+
 private:
   Graphics::Controller*                  mGraphicsController;
   Graphics::UniquePtr<Graphics::Texture> mGraphicsTexture;
@@ -230,12 +240,16 @@ private:
   Render::Sampler         mSampler;     ///< The current sampler state
 
   Rect<uint16_t> mUpdatedArea{}; ///< Updated area of the texture
-  Pixel::Format  mPixelFormat;   ///< Pixel format of the texture
-  uint16_t       mWidth;         ///< Width of the texture
-  uint16_t       mHeight;        ///< Height of the texture
-  Type           mType : 3;      ///< Type of the texture
-  bool           mHasAlpha : 1;  ///< Whether the format has an alpha channel
-  bool           mUpdated : 1;   ///< Whether the texture is updated
+
+  Pixel::Format mPixelFormat; ///< Pixel format of the texture
+  uint16_t      mWidth;       ///< Width of the texture
+  uint16_t      mHeight;      ///< Height of the texture
+
+  Type mType : 3;     ///< Type of the texture
+  bool mHasAlpha : 1; ///< Whether the format has an alpha channel
+  bool mUpdated : 1;  ///< Whether the texture is updated
+
+  bool mUseUploadedParameter : 1; ///< Whether ths texture size and format depend on uploaded image or not.
 };
 
 } // namespace Render
index 2f62053..2ba28e0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022 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.
@@ -30,6 +30,12 @@ Texture Texture::New(TextureType::Type type, Pixel::Format format, uint32_t widt
   return Texture(texture.Get());
 }
 
+Texture Texture::New(TextureType::Type type)
+{
+  Internal::TexturePtr texture = Internal::Texture::New(type, Pixel::INVALID, 0u, 0u);
+  return Texture(texture.Get());
+}
+
 Texture Texture::New(NativeImageInterface& nativeImageInterface)
 {
   Internal::TexturePtr texture = Internal::Texture::New(nativeImageInterface);
index 9819677..11d973a 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TEXTURE_H
 
 /*
- * Copyright (c) 2022 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.
@@ -86,6 +86,17 @@ public:
   static Texture New(TextureType::Type type, Pixel::Format format, uint32_t width, uint32_t height);
 
   /**
+   * @brief Creates a new Texture object with no informations.
+   * Texture will use Uploaded PixelData size and format.
+   * Before texture Upload is called, width, height and format return invalid values.
+   *
+   * @SINCE_2_2.34
+   * @param[in] type The type of the texture
+   * @return A handle to a newly allocated Texture
+   */
+  static Texture New(TextureType::Type type);
+
+  /**
    * @brief Creates a new Texture object from a native image.
    *
    * @SINCE_1_1.43