Merge "Remove cubemap cache temperary + Fix bug when Uploaded PixelData resue after...
authorAdeel Kazmi <adeel.kazmi@samsung.com>
Wed, 17 Jan 2024 12:27:28 +0000 (12:27 +0000)
committerGerrit Code Review <gerrit@review>
Wed, 17 Jan 2024 12:27:28 +0000 (12:27 +0000)
automated-tests/src/dali-scene3d/utc-Dali-EnvironmentDefinition.cpp
dali-scene3d/internal/common/environment-map-load-task.cpp
dali-scene3d/internal/common/image-resource-loader.cpp
dali-scene3d/internal/common/image-resource-loader.h
dali-scene3d/internal/model-components/model-primitive-impl.cpp
dali-scene3d/public-api/loader/environment-definition.cpp
dali-scene3d/public-api/loader/environment-map-data.cpp
dali-scene3d/public-api/loader/resource-bundle.cpp

index 5dd2f1c..8d5e694 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 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.
@@ -18,9 +18,9 @@
 // Enable debug log for test coverage
 #define DEBUG_ENABLED 1
 
-#include "dali-scene3d/public-api/loader/environment-definition.h"
 #include <dali-test-suite-utils.h>
 #include <string_view>
+#include "dali-scene3d/public-api/loader/environment-definition.h"
 
 using namespace Dali;
 using namespace Dali::Scene3D::Loader;
@@ -28,16 +28,16 @@ using namespace Dali::Scene3D::Loader;
 int UtcDaliEnvironmentDefinitionLoadRawDefault(void)
 {
   EnvironmentDefinition envDef;
-  auto rawData = envDef.LoadRaw("");
+  auto                  rawData = envDef.LoadRaw("");
 
   DALI_TEST_EQUAL(rawData.mDiffuse.mPixelData.size(), 6u);
-  for (auto& face: rawData.mDiffuse.mPixelData)
+  for(auto& face : rawData.mDiffuse.mPixelData)
   {
     DALI_TEST_EQUAL(face.size(), 1u);
   }
 
   DALI_TEST_EQUAL(rawData.mSpecular.mPixelData.size(), 6u);
-  for (auto& face: rawData.mSpecular.mPixelData)
+  for(auto& face : rawData.mSpecular.mPixelData)
   {
     DALI_TEST_EQUAL(face.size(), 1u);
   }
@@ -47,9 +47,9 @@ int UtcDaliEnvironmentDefinitionLoadRawDefault(void)
 
 int UtcDaliEnvironmentDefinitionLoadRawFail(void)
 {
-  for (auto name: { "nonexistent.ktx", TEST_RESOURCE_DIR "Cobe.obj" , TEST_RESOURCE_DIR "truncated.ktx" })
+  for(auto name : {"nonexistent.ktx", TEST_RESOURCE_DIR "Cobe.obj", TEST_RESOURCE_DIR "truncated.ktx"})
   {
-    EnvironmentDefinition envDef { name, name };
+    EnvironmentDefinition envDef{name, name};
     DALI_TEST_ASSERTION(envDef.LoadRaw(""), "Failed to load cubemap texture");
 
     envDef.mDiffuseMapPath = "";
@@ -61,15 +61,15 @@ int UtcDaliEnvironmentDefinitionLoadRawFail(void)
 
 int UtcDaliEnvironmentDefinitionLoadRawSuccess(void)
 {
-  EnvironmentDefinition envDef { "forest_irradiance.ktx", "forest_radiance.ktx" };
-  auto rawData = envDef.LoadRaw(TEST_RESOURCE_DIR "/");
+  EnvironmentDefinition envDef{"forest_irradiance.ktx", "forest_radiance.ktx"};
+  auto                  rawData = envDef.LoadRaw(TEST_RESOURCE_DIR "/");
 
   DALI_TEST_EQUAL(rawData.mDiffuse.mPixelData.size(), 6u);
-  for (auto& face: rawData.mDiffuse.mPixelData)
+  for(auto& face : rawData.mDiffuse.mPixelData)
   {
     DALI_TEST_EQUAL(face.size(), 1u);
     uint32_t size = 64u;
-    for (auto& mipLevel : face)
+    for(auto& mipLevel : face)
     {
       DALI_TEST_EQUAL(mipLevel.GetPixelFormat(), Pixel::Format::RGB888);
       DALI_TEST_EQUAL(mipLevel.GetWidth(), size);
@@ -79,11 +79,11 @@ int UtcDaliEnvironmentDefinitionLoadRawSuccess(void)
   }
 
   DALI_TEST_EQUAL(rawData.mSpecular.mPixelData.size(), 6u);
-  for (auto& face: rawData.mSpecular.mPixelData)
+  for(auto& face : rawData.mSpecular.mPixelData)
   {
     DALI_TEST_EQUAL(face.size(), 5u);
     uint32_t size = 64u;
-    for (auto& mipLevel : face)
+    for(auto& mipLevel : face)
     {
       DALI_TEST_EQUAL(mipLevel.GetPixelFormat(), Pixel::Format::RGB888);
       DALI_TEST_EQUAL(mipLevel.GetWidth(), size);
@@ -98,8 +98,8 @@ int UtcDaliEnvironmentDefinitionLoadRawSuccess(void)
 int UtcDaliEnvironmentDefinitionLoadEmptyRaw(void)
 {
   EnvironmentDefinition::RawData rawData;
-  EnvironmentDefinition envDef;
-  auto textures = envDef.Load(std::move(rawData));
+  EnvironmentDefinition          envDef;
+  auto                           textures = envDef.Load(std::move(rawData));
   DALI_TEST_CHECK(!textures.mDiffuse);
   DALI_TEST_CHECK(!textures.mSpecular);
 
@@ -108,7 +108,6 @@ int UtcDaliEnvironmentDefinitionLoadEmptyRaw(void)
 
 namespace
 {
-
 void CheckTextureDefault(Texture texture)
 {
   DALI_TEST_CHECK(texture);
@@ -123,15 +122,16 @@ void CheckTextureNotDefault(Texture texture)
   DALI_TEST_CHECK(texture.GetHeight() > 1u);
 }
 
-}
+} // namespace
 
 int UtcDaliEnvironmentDefinitionLoadDefault(void)
 {
   EnvironmentDefinition envDef{};
-  auto rawData = envDef.LoadRaw(TEST_RESOURCE_DIR "/");;
+  auto                  rawData = envDef.LoadRaw(TEST_RESOURCE_DIR "/");
+  ;
 
   TestApplication app;
-  auto textures = envDef.Load(std::move(rawData));
+  auto            textures = envDef.Load(std::move(rawData));
 
   CheckTextureDefault(textures.mSpecular);
   CheckTextureDefault(textures.mDiffuse);
@@ -141,11 +141,12 @@ int UtcDaliEnvironmentDefinitionLoadDefault(void)
 
 int UtcDaliEnvironmentDefinitionLoadDiffuse(void)
 {
-  EnvironmentDefinition envDef{ "forest_irradiance.ktx" };
-  auto rawData = envDef.LoadRaw(TEST_RESOURCE_DIR "/");;
+  EnvironmentDefinition envDef{"forest_irradiance.ktx"};
+  auto                  rawData = envDef.LoadRaw(TEST_RESOURCE_DIR "/");
+  ;
 
   TestApplication app;
-  auto textures = envDef.Load(std::move(rawData));
+  auto            textures = envDef.Load(std::move(rawData));
 
   CheckTextureNotDefault(textures.mDiffuse);
   CheckTextureDefault(textures.mSpecular);
@@ -155,11 +156,12 @@ int UtcDaliEnvironmentDefinitionLoadDiffuse(void)
 
 int UtcDaliEnvironmentDefinitionLoadSpecular(void)
 {
-  EnvironmentDefinition envDef{ "", "forest_radiance.ktx" };
-  auto rawData = envDef.LoadRaw(TEST_RESOURCE_DIR "/");;
+  EnvironmentDefinition envDef{"", "forest_radiance.ktx"};
+  auto                  rawData = envDef.LoadRaw(TEST_RESOURCE_DIR "/");
+  ;
 
   TestApplication app;
-  auto textures = envDef.Load(std::move(rawData));
+  auto            textures = envDef.Load(std::move(rawData));
 
   CheckTextureDefault(textures.mDiffuse);
   CheckTextureNotDefault(textures.mSpecular);
@@ -169,11 +171,12 @@ int UtcDaliEnvironmentDefinitionLoadSpecular(void)
 
 int UtcDaliEnvironmentDefinitionLoadBoth(void)
 {
-  EnvironmentDefinition envDef{ "forest_irradiance.ktx", "forest_radiance.ktx" };
-  auto rawData = envDef.LoadRaw(TEST_RESOURCE_DIR "/");;
+  EnvironmentDefinition envDef{"forest_irradiance.ktx", "forest_radiance.ktx"};
+  auto                  rawData = envDef.LoadRaw(TEST_RESOURCE_DIR "/");
+  ;
 
   TestApplication app;
-  auto textures = envDef.Load(std::move(rawData));
+  auto            textures = envDef.Load(std::move(rawData));
 
   CheckTextureNotDefault(textures.mDiffuse);
   CheckTextureNotDefault(textures.mSpecular);
index 8bc8239..385eb39 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023 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.
@@ -19,6 +19,7 @@
 #include <dali-scene3d/internal/common/environment-map-load-task.h>
 
 // INTERNAL INCLUDES
+#include <dali-scene3d/internal/common/image-resource-loader.h>
 #include <dali-scene3d/public-api/loader/environment-map-loader.h>
 
 namespace Dali
index 3403cfa..bc1a21d 100644 (file)
@@ -36,6 +36,7 @@
 #include <functional> ///< for std::function
 #include <memory>     ///< for std::shared_ptr
 #include <mutex>
+#include <sstream>
 #include <string>
 #include <utility> ///< for std::pair
 
@@ -50,16 +51,8 @@ constexpr uint32_t GC_PERIOD_MILLISECONDS                     = 1000u;
 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_IMAGE_RESOURCE_LOADER");
 #endif
 
-bool SupportPixelDataCache(Dali::PixelData pixelData)
+bool IsDefaultPixelData(const Dali::PixelData& pixelData)
 {
-  // Check given pixelData support to release data after upload.
-  // This is cause we need to reduce CPU memory usage.
-  if(Dali::Integration::IsPixelDataReleaseAfterUpload(pixelData))
-  {
-    return true;
-  }
-
-  // Check given pixelData is default pixelData.
   if(pixelData == Dali::Scene3D::Internal::ImageResourceLoader::GetEmptyPixelDataWhiteRGB() ||
      pixelData == Dali::Scene3D::Internal::ImageResourceLoader::GetEmptyPixelDataWhiteRGBA() ||
      pixelData == Dali::Scene3D::Internal::ImageResourceLoader::GetEmptyPixelDataZAxisRGB() ||
@@ -70,19 +63,21 @@ bool SupportPixelDataCache(Dali::PixelData pixelData)
   return false;
 }
 
-bool SupportPixelDataListCache(const std::vector<std::vector<Dali::PixelData>>& pixelDataList)
+bool SupportPixelDataCache(const Dali::PixelData& pixelData)
 {
-  for(const auto& pixelDataListLevel0 : pixelDataList)
+  // Check given pixelData support to release data after upload.
+  // This is cause we need to reduce CPU memory usage.
+  if(Dali::Integration::IsPixelDataReleaseAfterUpload(pixelData))
   {
-    for(const auto& pixelData : pixelDataListLevel0)
-    {
-      if(!SupportPixelDataCache(pixelData))
-      {
-        return false;
-      }
-    }
+    return true;
   }
-  return true;
+
+  // Check given pixelData is default pixelData.
+  if(IsDefaultPixelData(pixelData))
+  {
+    return true;
+  }
+  return false;
 }
 
 struct ImageInformation
@@ -152,21 +147,6 @@ std::size_t GenerateHash(const Dali::PixelData& pixelData, bool mipmapRequired)
   return reinterpret_cast<std::size_t>(static_cast<void*>(pixelData.GetObjectPtr())) ^ (static_cast<std::size_t>(mipmapRequired) << (sizeof(std::size_t) * 4));
 }
 
-std::size_t GenerateHash(const std::vector<std::vector<Dali::PixelData>>& pixelDataList, bool mipmapRequired)
-{
-  std::size_t result = 0x12345678u + pixelDataList.size();
-  for(const auto& mipmapPixelDataList : pixelDataList)
-  {
-    result += (result << 5) + mipmapPixelDataList.size();
-    for(const auto& pixelData : mipmapPixelDataList)
-    {
-      result += (result << 5) + GenerateHash(pixelData, false);
-    }
-  }
-
-  return result ^ (static_cast<std::size_t>(mipmapRequired) << (sizeof(std::size_t) * 4));
-}
-
 // Item Creation functor list
 
 Dali::PixelData CreatePixelDataFromImageInfo(const ImageInformation& info, bool releasePixelData)
@@ -197,27 +177,17 @@ Dali::Texture CreateTextureFromPixelData(const Dali::PixelData& pixelData, bool
   return texture;
 }
 
-Dali::Texture CreateCubeTextureFromPixelDataList(const std::vector<std::vector<Dali::PixelData>>& pixelDataList, bool mipmapRequired)
+// Check function whether we can collect given data as garbage, or not.
+bool PixelDataCacheCollectable(const ImageInformation& info, const Dali::PixelData& pixelData)
 {
-  Dali::Texture texture;
-  if(!pixelDataList.empty() && !pixelDataList[0].empty())
-  {
-    texture = Dali::Texture::New(Dali::TextureType::TEXTURE_CUBE, pixelDataList[0][0].GetPixelFormat(), pixelDataList[0][0].GetWidth(), pixelDataList[0][0].GetHeight());
-    for(size_t iSide = 0u, iEndSize = pixelDataList.size(); iSide < iEndSize; ++iSide)
-    {
-      auto& side = pixelDataList[iSide];
-      for(size_t iMipLevel = 0u, iEndMipLevel = pixelDataList[0].size(); iMipLevel < iEndMipLevel; ++iMipLevel)
-      {
-        texture.Upload(side[iMipLevel], Dali::CubeMapLayer::POSITIVE_X + iSide, iMipLevel, 0u, 0u, side[iMipLevel].GetWidth(), side[iMipLevel].GetHeight());
-      }
-    }
-    if(mipmapRequired)
-    {
-      texture.GenerateMipmaps();
-    }
-  }
+  return pixelData.GetBaseObject().ReferenceCount() <= 1;
+}
 
-  return texture;
+bool TextureCacheCollectable(const Dali::PixelData& pixelData, const Dali::Texture& texture)
+{
+  return !IsDefaultPixelData(pixelData) &&                  ///< If key is not default pixelData
+         pixelData.GetBaseObject().ReferenceCount() <= 2 && ///< And it have reference count as 2 (1 is for the key of this container, and other is PixelData cache.)
+         texture.GetBaseObject().ReferenceCount() <= 1;     ///< And nobody use this texture, except this contianer.
 }
 
 // Forward declare, for signal connection.
@@ -232,15 +202,12 @@ public:
   CacheImpl()
   : mPixelDataCache{},
     mTextureCache{},
-    mCubeTextureCache{},
     mTimer{},
     mLatestCollectedPixelDataIter{mPixelDataCache.begin()},
     mLatestCollectedTextureIter{mTextureCache.begin()},
-    mLatestCollectedCubeTextureIter{mCubeTextureCache.begin()},
+    mDataMutex{},
     mPixelDataContainerUpdated{false},
     mTextureContainerUpdated{false},
-    mCubeTextureContainerUpdated{false},
-    mDataMutex{},
     mDestroyed{false},
     mFullCollectRequested{false}
   {
@@ -259,17 +226,14 @@ public:
     {
       mDataMutex.lock();
 
-      mDestroyed                      = true;
-      mPixelDataContainerUpdated      = false;
-      mTextureContainerUpdated        = false;
-      mCubeTextureContainerUpdated    = false;
-      mLatestCollectedPixelDataIter   = decltype(mLatestCollectedPixelDataIter)();   // Invalidate iterator
-      mLatestCollectedTextureIter     = decltype(mLatestCollectedTextureIter)();     // Invalidate iterator
-      mLatestCollectedCubeTextureIter = decltype(mLatestCollectedCubeTextureIter){}; // Invalidate iterator
+      mDestroyed                    = true;
+      mPixelDataContainerUpdated    = false;
+      mTextureContainerUpdated      = false;
+      mLatestCollectedPixelDataIter = decltype(mLatestCollectedPixelDataIter)(); // Invalidate iterator
+      mLatestCollectedTextureIter   = decltype(mLatestCollectedTextureIter)();   // Invalidate iterator
 
       mPixelDataCache.clear();
       mTextureCache.clear();
-      mCubeTextureCache.clear();
 
       mDataMutex.unlock();
     }
@@ -285,9 +249,8 @@ public:
 
 private: // Unified API for this class
   // Let compare with hash first. And then, check detail keys after.
-  using PixelDataCacheContainer   = std::map<std::size_t, std::vector<std::pair<ImageInformation, Dali::PixelData>>>;
-  using TextureCacheContainer     = std::map<std::size_t, std::vector<std::pair<Dali::PixelData, Dali::Texture>>>;
-  using CubeTextureCacheContainer = std::map<std::size_t, std::vector<std::pair<std::vector<std::vector<Dali::PixelData>>, Dali::Texture>>>;
+  using PixelDataCacheContainer = std::map<std::size_t, std::vector<std::pair<ImageInformation, Dali::PixelData>>>;
+  using TextureCacheContainer   = std::map<std::size_t, std::vector<std::pair<Dali::PixelData, Dali::Texture>>>;
 
   /**
    * @brief Try to get cached item, or create new handle if there is no item.
@@ -314,6 +277,7 @@ private: // Unified API for this class
       bool found = false;
 
       auto iter = cacheContainer.lower_bound(hashValue);
+      DALI_LOG_INFO(gLogFilter, Debug::Verbose, "HashValue : %zu\n", hashValue);
       if((iter == cacheContainer.end()) || (hashValue != iter->first))
       {
         containerUpdated = true;
@@ -356,6 +320,7 @@ private: // Unified API for this class
 
     return returnItem;
   }
+
   /**
    * @brief Try to collect garbages, which reference counts are 1.
    *
@@ -367,15 +332,10 @@ private: // Unified API for this class
    * @oaram[in, out] checkedCount The number of iteration checked total.
    * @return True if we iterate whole container, so we don't need to check anymore. False otherwise
    */
-  template<bool needMutex, typename ContainerType, typename Iterator = typename ContainerType::iterator>
-  bool CollectGarbages(ContainerType& cacheContainer, bool fullCollect, bool& containerUpdated, Iterator& lastIterator, uint32_t& checkedCount)
+  template<typename KeyType, typename ValueType, bool (*Collectable)(const KeyType&, const ValueType&), typename ContainerType, typename Iterator = typename ContainerType::iterator>
+  bool CollectGarbages(ContainerType& cacheContainer, bool fullCollect, bool& containerUpdated, Iterator& lastIterator, uint32_t& checkedCount, uint32_t& collectedCount)
   {
-    if constexpr(needMutex)
-    {
-      mDataMutex.lock();
-    }
-
-    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Collect Garbages : %zu\n", cacheContainer.size());
+    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Collect Garbages : %zu (checkedCount : %d, fullCollect? %d)\n", cacheContainer.size(), checkedCount, fullCollect);
     // Container changed. We should re-collect garbage from begin again.
     if(fullCollect || containerUpdated)
     {
@@ -391,9 +351,11 @@ private: // Unified API for this class
       {
         auto& item = jter->second;
         DALI_LOG_INFO(gLogFilter, Debug::Verbose, "item : %p, ref count : %u\n", item.GetObjectPtr(), (item ? item.GetBaseObject().ReferenceCount() : 0u));
-        if(!item || (item.GetBaseObject().ReferenceCount() == 1u))
+        if(!item || Collectable(jter->first, item))
         {
+          DALI_LOG_INFO(gLogFilter, Debug::Verbose, "GC!!!\n");
           // This item is garbage! just remove it.
+          ++collectedCount;
           jter = cachePairList.erase(jter);
         }
         else
@@ -412,11 +374,6 @@ private: // Unified API for this class
       }
     }
 
-    if constexpr(needMutex)
-    {
-      mDataMutex.unlock();
-    }
-
     return (lastIterator != cacheContainer.end());
   }
 
@@ -435,19 +392,6 @@ public: // Called by main thread.
   }
 
   /**
-   * @brief Try to get cached cube texture, or newly create if there is no cube texture that already cached.
-   *
-   * @param[in] pixelDataList The pixelData list of image.
-   * @param[in] mipmapRequired True if result texture need to generate mipmap.
-   * @return Texture that has been cached. Or empty handle if we fail to found cached item.
-   */
-  Dali::Texture GetOrCreateCachedCubeTexture(const std::vector<std::vector<Dali::PixelData>>& pixelDataList, bool mipmapRequired)
-  {
-    auto hashValue = GenerateHash(pixelDataList, mipmapRequired);
-    return GetOrCreateCachedItem<false, std::vector<std::vector<Dali::PixelData>>, Dali::Texture, CreateCubeTextureFromPixelDataList>(mCubeTextureCache, hashValue, pixelDataList, mipmapRequired, mCubeTextureContainerUpdated);
-  }
-
-  /**
    * @brief Request incremental gargabe collect.
    *
    * @param[in] fullCollect True if we will collect whole items, or incrementally.
@@ -467,12 +411,9 @@ public: // Called by main thread.
       if(!mTimer.IsRunning())
       {
         // Restart container interating.
-        if(!mPixelDataContainerUpdated)
-        {
-          mDataMutex.lock();
-          mPixelDataContainerUpdated = true;
-          mDataMutex.unlock();
-        }
+        mDataMutex.lock();
+        mPixelDataContainerUpdated = true;
+        mDataMutex.unlock();
         mTextureContainerUpdated = true;
         mTimer.Start();
       }
@@ -512,40 +453,44 @@ private: // Called by main thread
   bool IncrementalGarbageCollect(bool fullCollect)
   {
     bool continueTimer = false;
+    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "GC start\n");
 
     // Try to collect Texture GC first, due to the reference count of pixelData who become key of textures.
     // After all texture GC finished, then check PixelData cache.
-    uint32_t checkedCount = 0u;
+    uint32_t checkedCount   = 0u;
+    uint32_t collectedCount = 0u;
 
-    // GC Cube Texture
-    continueTimer |= CollectGarbages<false>(mCubeTextureCache, fullCollect, mCubeTextureContainerUpdated, mLatestCollectedCubeTextureIter, checkedCount);
+    // We should lock mutex during GC pixelData.
+    mDataMutex.lock();
 
     // GC Texture
-    continueTimer |= CollectGarbages<false>(mTextureCache, fullCollect, mTextureContainerUpdated, mLatestCollectedTextureIter, checkedCount);
+    continueTimer |= CollectGarbages<Dali::PixelData, Dali::Texture, TextureCacheCollectable>(mTextureCache, fullCollect, mTextureContainerUpdated, mLatestCollectedTextureIter, checkedCount, collectedCount);
+
+    // GC PixelData last. If there are some collected Texture before, we should full-collect.
+    // (Since most of PixelData use 'ReleaseAfterUpload' flags).
+    continueTimer |= CollectGarbages<ImageInformation, Dali::PixelData, PixelDataCacheCollectable>(mPixelDataCache, fullCollect || (collectedCount > 0u), mPixelDataContainerUpdated, mLatestCollectedPixelDataIter, checkedCount, collectedCount);
+
+    mDataMutex.unlock();
 
-    // GC PixelData. We should lock mutex during GC pixelData.
-    continueTimer |= CollectGarbages<true>(mPixelDataCache, fullCollect, mPixelDataContainerUpdated, mLatestCollectedPixelDataIter, checkedCount);
+    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "GC finished. checkedCount : %u, continueTimer : %d\n", checkedCount, continueTimer);
 
     return continueTimer;
   }
 
 private:
-  PixelDataCacheContainer   mPixelDataCache;
-  TextureCacheContainer     mTextureCache;
-  CubeTextureCacheContainer mCubeTextureCache;
+  PixelDataCacheContainer mPixelDataCache;
+  TextureCacheContainer   mTextureCache;
 
   Dali::Timer mTimer;
 
   // Be used when we garbage collection.
-  PixelDataCacheContainer::iterator   mLatestCollectedPixelDataIter;
-  TextureCacheContainer::iterator     mLatestCollectedTextureIter;
-  CubeTextureCacheContainer::iterator mLatestCollectedCubeTextureIter;
+  PixelDataCacheContainer::iterator mLatestCollectedPixelDataIter;
+  TextureCacheContainer::iterator   mLatestCollectedTextureIter;
+
+  std::mutex mDataMutex;
 
   bool mPixelDataContainerUpdated;
   bool mTextureContainerUpdated;
-  bool mCubeTextureContainerUpdated;
-
-  std::mutex mDataMutex;
 
   bool mDestroyed : 1;
   bool mFullCollectRequested : 1;
@@ -553,6 +498,7 @@ private:
 
 static std::shared_ptr<CacheImpl> gCacheImpl{nullptr};
 static Dali::Texture              gEmptyTextureWhiteRGB{};
+static Dali::Texture              gEmptyCubeTextureWhiteRGB{};
 
 std::shared_ptr<CacheImpl> GetCacheImpl()
 {
@@ -569,6 +515,7 @@ void DestroyCacheImpl()
 
   // Remove texture object when application stopped.
   gEmptyTextureWhiteRGB.Reset();
+  gEmptyCubeTextureWhiteRGB.Reset();
 }
 
 } // namespace
@@ -589,27 +536,29 @@ Dali::Texture GetEmptyTextureWhiteRGB()
   return gEmptyTextureWhiteRGB;
 }
 
-Dali::Texture GetCachedTexture(Dali::PixelData pixelData, bool mipmapRequired)
+Dali::Texture GetEmptyCubeTextureWhiteRGB()
 {
-  if(SupportPixelDataCache(pixelData))
+  if(!gEmptyCubeTextureWhiteRGB)
   {
-    return GetCacheImpl()->GetOrCreateCachedTexture(pixelData, mipmapRequired);
-  }
-  else
-  {
-    return CreateTextureFromPixelData(pixelData, mipmapRequired);
+    Dali::PixelData emptyPixelData = GetEmptyPixelDataWhiteRGB();
+    gEmptyCubeTextureWhiteRGB      = Texture::New(TextureType::TEXTURE_CUBE, emptyPixelData.GetPixelFormat(), emptyPixelData.GetWidth(), emptyPixelData.GetHeight());
+    for(size_t iSide = 0u; iSide < 6; ++iSide)
+    {
+      gEmptyCubeTextureWhiteRGB.Upload(emptyPixelData, CubeMapLayer::POSITIVE_X + iSide, 0u, 0u, 0u, emptyPixelData.GetWidth(), emptyPixelData.GetHeight());
+    }
   }
+  return gEmptyCubeTextureWhiteRGB;
 }
 
-Dali::Texture GetCachedCubeTexture(const std::vector<std::vector<Dali::PixelData>>& pixelDataList, bool mipmapRequired)
+Dali::Texture GetCachedTexture(Dali::PixelData pixelData, bool mipmapRequired)
 {
-  if(SupportPixelDataListCache(pixelDataList))
+  if(SupportPixelDataCache(pixelData))
   {
-    return GetCacheImpl()->GetOrCreateCachedCubeTexture(pixelDataList, mipmapRequired);
+    return GetCacheImpl()->GetOrCreateCachedTexture(pixelData, mipmapRequired);
   }
   else
   {
-    return CreateCubeTextureFromPixelDataList(pixelDataList, mipmapRequired);
+    return CreateTextureFromPixelData(pixelData, mipmapRequired);
   }
 }
 
index df0d9e7..3957009 100644 (file)
@@ -48,20 +48,18 @@ namespace ImageResourceLoader
 Dali::Texture GetEmptyTextureWhiteRGB();
 
 /**
- * @brief Get cached texture handle, or create new texture and upload.
- * @param[in] pixelData The PixelData of image to upload
- * @param[in] mipmapRequired True if this texture need to generate mipmap
- * @return A Texture object containing the pixelData, or an invalid object on failure
+ * @brief Get cached cube texture handle filled as white with RGB888 format at 6 faces.
+ * @return A Texture object containing the white RGB888 color at 6 faces.
  */
-Dali::Texture GetCachedTexture(Dali::PixelData pixelData, bool mipmapRequired);
+Dali::Texture GetEmptyCubeTextureWhiteRGB();
 
 /**
- * @brief Get cached cube texture handle, or create new texture and upload.
- * @param[in] pixelDataList The list of PixelData to upload. pixelDataList[FACE_OF_CUBE][MIPMAP_LEVEL].
+ * @brief Get cached texture handle, or create new texture and upload.
+ * @param[in] pixelData The PixelData of image to upload
  * @param[in] mipmapRequired True if this texture need to generate mipmap
  * @return A Texture object containing the pixelData, or an invalid object on failure
  */
-Dali::Texture GetCachedCubeTexture(const std::vector<std::vector<Dali::PixelData>>& pixelDataList, bool mipmapRequired);
+Dali::Texture GetCachedTexture(Dali::PixelData pixelData, bool mipmapRequired);
 
 /**
  * @brief Request to remove unused Texture and PixelData. We can choose the collect garbages incrementally or fully.
index 1adf514..fb5a904 100644 (file)
@@ -402,14 +402,7 @@ void ModelPrimitive::ApplyMaterialToRenderer(MaterialModifyObserver::ModifyFlag
     Texture brdfTexture = Scene3D::Loader::EnvironmentDefinition::GetBrdfTexture();
     if(!mSpecularTexture || !mDiffuseTexture)
     {
-      Scene3D::Loader::EnvironmentMapData environmentMapData;
-      environmentMapData.mPixelData.resize(6);
-      for(auto& face : environmentMapData.mPixelData)
-      {
-        face.push_back(Dali::Scene3D::Internal::ImageResourceLoader::GetEmptyPixelDataWhiteRGB());
-      }
-      environmentMapData.SetEnvironmentMapType(Dali::Scene3D::EnvironmentMapType::CUBEMAP);
-      Texture iblTexture = environmentMapData.GetTexture();
+      Texture iblTexture = Dali::Scene3D::Internal::ImageResourceLoader::GetEmptyCubeTextureWhiteRGB();
       mDiffuseTexture    = iblTexture;
       mSpecularTexture   = iblTexture;
     }
index 877f0ea..9c74f23 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023 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.
index f7472c4..3b7f878 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023 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.
@@ -38,11 +38,31 @@ Texture EnvironmentMapData::GetTexture()
   {
     if(mEnvironmentMapType == Scene3D::EnvironmentMapType::CUBEMAP)
     {
-      mEnvironmentMapTexture = Dali::Scene3D::Internal::ImageResourceLoader::GetCachedCubeTexture(mPixelData, mPixelData[0].size() == 1u);
+      // Check for the default case, that we might share the graphic resources
+      if(mPixelData[0].size() > 0u)
+      {
+        if(mPixelData[0][0] == Dali::Scene3D::Internal::ImageResourceLoader::GetEmptyPixelDataWhiteRGB())
+        {
+          mEnvironmentMapTexture = Dali::Scene3D::Internal::ImageResourceLoader::GetEmptyCubeTextureWhiteRGB();
+        }
+        else
+        {
+          mEnvironmentMapTexture = Texture::New(TextureType::TEXTURE_CUBE, mPixelData[0][0].GetPixelFormat(), mPixelData[0][0].GetWidth(), mPixelData[0][0].GetHeight());
+          for(size_t iSide = 0u, iEndSize = mPixelData.size(); iSide < iEndSize; ++iSide)
+          {
+            auto& side = mPixelData[iSide];
+            for(size_t iMipLevel = 0u, iEndMipLevel = mPixelData[0].size(); iMipLevel < iEndMipLevel; ++iMipLevel)
+            {
+              mEnvironmentMapTexture.Upload(side[iMipLevel], CubeMapLayer::POSITIVE_X + iSide, iMipLevel, 0u, 0u, side[iMipLevel].GetWidth(), side[iMipLevel].GetHeight());
+            }
+          }
+        }
+      }
     }
     else
     {
-      mEnvironmentMapTexture = Dali::Scene3D::Internal::ImageResourceLoader::GetCachedTexture(mPixelData[0][0], mPixelData[0].size() == 1u);
+      mEnvironmentMapTexture = Texture::New(TextureType::TEXTURE_2D, mPixelData[0][0].GetPixelFormat(), mPixelData[0][0].GetWidth(), mPixelData[0][0].GetHeight());
+      mEnvironmentMapTexture.Upload(mPixelData[0][0], 0, 0, 0, 0, mPixelData[0][0].GetWidth(), mPixelData[0][0].GetHeight());
     }
 
     // If mipmap is not defined explicitly, use GenerateMipmaps.
index 6b4dde6..2af4da4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023 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.
@@ -19,6 +19,7 @@
 #include <dali-scene3d/public-api/loader/resource-bundle.h>
 
 // EXTERNAL INCLUDES
+#include <dali-scene3d/internal/common/image-resource-loader.h>
 #include <dali-toolkit/public-api/image-loader/sync-image-loader.h>
 #include <dali/public-api/rendering/sampler.h>
 #include <cstring>