Merge branch 'devel/master' into tizen
authorWoochan Lee <wc0917.lee@samsung.com>
Tue, 20 Feb 2024 04:18:49 +0000 (13:18 +0900)
committerWoochan Lee <wc0917.lee@samsung.com>
Tue, 20 Feb 2024 04:18:49 +0000 (13:18 +0900)
31 files changed:
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-gl-abstraction.cpp
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-gl-abstraction.h
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-sync-impl.cpp
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-sync-impl.h
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-sync-object.h
dali/integration-api/adaptor-framework/shader-precompiler.h
dali/internal/adaptor/common/combined-update-render-controller.cpp
dali/internal/adaptor/common/combined-update-render-controller.h
dali/internal/graphics/android/egl-sync-implementation-android.cpp [new file with mode: 0644]
dali/internal/graphics/common/egl-include.h
dali/internal/graphics/file.list
dali/internal/graphics/generic/egl-sync-implementation.cpp [new file with mode: 0644]
dali/internal/graphics/gles-impl/egl-graphics-controller.cpp
dali/internal/graphics/gles-impl/egl-graphics-controller.h
dali/internal/graphics/gles-impl/egl-sync-object.cpp
dali/internal/graphics/gles-impl/egl-sync-object.h
dali/internal/graphics/gles-impl/gles-context.cpp
dali/internal/graphics/gles-impl/gles-graphics-program.cpp
dali/internal/graphics/gles-impl/gles-sync-object.cpp
dali/internal/graphics/gles-impl/gles-sync-object.h
dali/internal/graphics/gles-impl/gles-sync-pool.cpp
dali/internal/graphics/gles-impl/gles-sync-pool.h
dali/internal/graphics/gles-impl/gles-texture-dependency-checker.cpp
dali/internal/graphics/gles-impl/gles-texture-dependency-checker.h
dali/internal/graphics/gles/egl-sync-implementation.h
dali/internal/graphics/gles/gl-implementation.h
dali/internal/graphics/macos/egl-sync-implementation-macos.cpp [new file with mode: 0644]
dali/internal/graphics/tizen/egl-sync-implementation-tizen.cpp [moved from dali/internal/graphics/gles/egl-sync-implementation.cpp with 70% similarity]
dali/internal/graphics/windows-gl/egl-sync-implementation-windows.cpp [new file with mode: 0644]
dali/public-api/dali-adaptor-version.cpp
packaging/dali-adaptor.spec

index b861c66..fc1eb65 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.
@@ -209,6 +209,11 @@ bool TestGlAbstraction::IsBlendEquationSupported(DevelBlendEquation::Type blendE
   return true;
 }
 
+uint32_t TestGlAbstraction::GetShaderLanguageVersion()
+{
+  return mShaderLanguageVersion;
+}
+
 std::string TestGlAbstraction::GetShaderVersionPrefix()
 {
   return std::string("");
index 3f04a6b..a70c21f 100644 (file)
@@ -2,7 +2,7 @@
 #define TEST_GL_ABSTRACTION_H
 
 /*
- * 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.
@@ -77,6 +77,8 @@ public:
 
   bool IsBlendEquationSupported(DevelBlendEquation::Type blendEquation) override;
 
+  uint32_t GetShaderLanguageVersion();
+
   std::string GetShaderVersionPrefix();
 
   std::string GetVertexShaderPrefix();
@@ -2712,6 +2714,8 @@ public:
   TraceCallStack mViewportTrace;
 
   // Shaders & Uniforms
+  uint32_t mShaderLanguageVersion{320u};
+
   GLuint                                 mLastShaderIdUsed;
   GLuint                                 mLastProgramIdUsed{0u};
   GLuint                                 mLastUniformIdUsed;
index 17f53a7..bb4a500 100644 (file)
@@ -38,6 +38,16 @@ bool TestSyncObject::IsSynced()
   return synced;
 }
 
+void TestSyncObject::Wait()
+{
+  mTrace.PushCall("SyncObject::Wait", ""); // Trace the method
+}
+
+void TestSyncObject::ClientWait()
+{
+  mTrace.PushCall("SyncObject::ClientWait", ""); // Trace the method
+}
+
 TestGraphicsSyncImplementation::TestGraphicsSyncImplementation()
 {
   Initialize();
index cbc5331..21fd358 100644 (file)
@@ -2,7 +2,7 @@
 #define TEST_SYNC_IMPLEMENTATION_H
 
 /*
- * Copyright (c) 2021 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.
@@ -40,7 +40,10 @@ class TestSyncObject : public Integration::GraphicsSyncAbstraction::SyncObject
 public:
   TestSyncObject(TraceCallStack& trace);
   ~TestSyncObject() override;
-  bool            IsSynced() override;
+  bool IsSynced() override;
+  void Wait() override;
+  void ClientWait() override;
+
   bool            synced;
   TraceCallStack& mTrace;
 };
index c33de6c..6886687 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TEST_GRAPHICS_SYNC_OBJECT_H_
 
 /*
- * Copyright (c) 2021 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,8 +19,7 @@
 
 #include <dali/graphics-api/graphics-sync-object-create-info.h>
 #include <dali/graphics-api/graphics-sync-object.h>
-
-#include <test-graphics-sync-impl.h>
+#include "test-graphics-sync-impl.h"
 
 namespace Dali
 {
index 6b14439..28d445d 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTEGRATION_SHADER_PRECOMPILER_H
 
 /*
- * 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.
  */
 
 // INTERNAL HEADER
-#include <dali/public-api/common/dali-common.h>
-#include <dali/public-api/object/base-handle.h>
-#include <dali/public-api/common/vector-wrapper.h>
 #include <dali/devel-api/threading/conditional-wait.h>
 #include <dali/devel-api/threading/mutex.h>
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/public-api/object/base-handle.h>
 
 // EXTERNAL HEDAER
-#include <string_view>
-#include <memory>
-#include <mutex>
 #include <dali/graphics-api/graphics-program.h>
 #include <dali/graphics-api/graphics-types.h>
+#include <memory>
+#include <mutex>
+#include <string_view>
 
 namespace Dali
 {
 struct RawShaderData
 {
-  int shaderCount;
+  int                           shaderCount;
   std::vector<std::string_view> vertexPrefix;
   std::vector<std::string_view> fragmentPrefix;
-  std::string_view vertexShader;
-  std::string_view fragmentShader;
+  std::vector<std::string_view> shaderName;
+  std::string_view              vertexShader;
+  std::string_view              fragmentShader;
 };
 
 /**
@@ -125,14 +126,14 @@ private:
 
 private:
   std::vector<Graphics::UniquePtr<Dali::Graphics::Program>> mProgram;
-  static std::unique_ptr<ShaderPreCompiler> mInstance;
-  static std::once_flag mOnceFlag;
-  std::vector<RawShaderData> mRawShaderList;
-  ConditionalWait mConditionalWait;
-  Dali::Mutex mMutex;
-  bool mPrecompiled;
-  bool mEnabled;
-  bool mNeedsSleep{true};
+  static std::unique_ptr<ShaderPreCompiler>                 mInstance;
+  static std::once_flag                                     mOnceFlag;
+  std::vector<RawShaderData>                                mRawShaderList;
+  ConditionalWait                                           mConditionalWait;
+  Dali::Mutex                                               mMutex;
+  bool                                                      mPrecompiled;
+  bool                                                      mEnabled;
+  bool                                                      mNeedsSleep{true};
 };
 
 } // namespace Dali
index e87d65b..3697bc4 100644 (file)
@@ -612,7 +612,7 @@ void CombinedUpdateRenderController::UpdateRenderThread()
         {
           auto vertexShader   = graphics.GetController().GetGraphicsConfig().GetVertexShaderPrefix() + std::string(precompiledShader->vertexPrefix[i].data()) + std::string(precompiledShader->vertexShader.data());
           auto fragmentShader = graphics.GetController().GetGraphicsConfig().GetFragmentShaderPrefix() + std::string(precompiledShader->fragmentPrefix[i].data()) + std::string(precompiledShader->fragmentShader.data());
-          PreCompileShader(std::move(vertexShader), std::move(fragmentShader));
+          PreCompileShader(std::move(vertexShader), std::move(fragmentShader), static_cast<uint32_t>(i) < precompiledShader->shaderName.size() ? std::string(precompiledShader->shaderName[i]) : "");
         }
         DALI_LOG_RELEASE_INFO("ShaderPreCompiler[ENABLE], shader count :%d \n", numberOfPrecompiledShader);
       }
@@ -1049,7 +1049,7 @@ void CombinedUpdateRenderController::SurfaceResized(uint32_t resizedCount)
   }
 }
 
-void CombinedUpdateRenderController::PreCompileShader(std::string vertexShader, std::string fragmentShader)
+void CombinedUpdateRenderController::PreCompileShader(std::string vertexShader, std::string fragmentShader, std::string shaderName)
 {
   GraphicsInterface& graphics = mAdaptorInterfaces.GetGraphicsInterface();
 
@@ -1079,6 +1079,7 @@ void CombinedUpdateRenderController::PreCompileShader(std::string vertexShader,
 
   auto createInfo = Graphics::ProgramCreateInfo();
   createInfo.SetShaderState(shaderStates);
+  createInfo.SetName(shaderName);
 
   auto graphicsProgram = graphics.GetController().CreateProgram(createInfo, nullptr);
   ShaderPreCompiler::Get().AddPreCompiledProgram(std::move(graphicsProgram));
index 35505fe..625e9e4 100644 (file)
@@ -279,8 +279,9 @@ private:
    *
    * @param[in] vertexShader vertexShader need to precompile
    * @param[in] fragmentShader fragmentShader need to precompile
+   * @param[in] shaderName the name of precompile shader (option)
   */
-  void PreCompileShader(std::string vertexShader, std::string fragmentShader);
+  void PreCompileShader(std::string vertexShader, std::string fragmentShader, std::string shaderName = "");
 
   /**
    * Cancel the precompile
diff --git a/dali/internal/graphics/android/egl-sync-implementation-android.cpp b/dali/internal/graphics/android/egl-sync-implementation-android.cpp
new file mode 100644 (file)
index 0000000..df12970
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/graphics/gles/egl-sync-implementation.h>
+
+// EXTERNAL INCLUDES
+
+#include <dali/integration-api/debug.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/graphics/gles/egl-debug.h>
+#include <dali/internal/graphics/gles/egl-implementation.h>
+
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gLogSyncFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_FENCE_SYNC");
+#endif
+
+namespace Dali
+{
+namespace Internal
+{
+namespace Adaptor
+{
+EglSyncObject::EglSyncObject(EglImplementation& eglImpl)
+: mPollCounter(3),
+  mEglImplementation(eglImpl)
+{
+}
+
+EglSyncObject::~EglSyncObject()
+{
+}
+
+bool EglSyncObject::IsSynced()
+{
+  return true;
+}
+
+void EglSyncObject::Wait()
+{
+}
+
+void EglSyncObject::ClientWait()
+{
+}
+
+EglSyncImplementation::EglSyncImplementation()
+: mEglImplementation(NULL),
+  mSyncInitialized(false),
+  mSyncInitializeFailed(false)
+{
+}
+
+EglSyncImplementation::~EglSyncImplementation()
+{
+}
+
+void EglSyncImplementation::Initialize(EglImplementation* eglImpl)
+{
+  mEglImplementation = eglImpl;
+}
+
+Integration::GraphicsSyncAbstraction::SyncObject* EglSyncImplementation::CreateSyncObject()
+{
+  DALI_ASSERT_ALWAYS(mEglImplementation && "Sync Implementation not initialized");
+  return new EglSyncObject(*mEglImplementation);
+}
+
+void EglSyncImplementation::DestroySyncObject(Integration::GraphicsSyncAbstraction::SyncObject* syncObject)
+{
+  DALI_ASSERT_ALWAYS(mEglImplementation && "Sync Implementation not initialized");
+  delete static_cast<EglSyncObject*>(syncObject);
+}
+
+void EglSyncImplementation::InitializeEglSync()
+{
+}
+
+} // namespace Adaptor
+} // namespace Internal
+} // namespace Dali
index 96ce884..905291c 100644 (file)
@@ -5,6 +5,8 @@
 #include <EGL/egl.h>
 
 // Undef unneded symbols that fail to compile on MS Windows
+#if defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) /* Win32 and WinCE */
+
 #undef ERROR
 
 #undef OPAQUE
@@ -20,6 +22,7 @@
 #undef max
 
 #undef DIFFERENCE
+#endif
 
 #include <EGL/eglext.h>
 
index 8041345..3f8b5dd 100644 (file)
@@ -3,7 +3,6 @@
 SET( adaptor_graphics_gles_src_files
     ${adaptor_graphics_dir}/gles/egl-debug.cpp
     ${adaptor_graphics_dir}/gles/egl-implementation.cpp
-    ${adaptor_graphics_dir}/gles/egl-sync-implementation.cpp
     ${adaptor_graphics_dir}/gles/gl-extensions.cpp
     ${adaptor_graphics_dir}/gles/gl-extensions-support.cpp
     ${adaptor_graphics_dir}/gles/gl-implementation.cpp
@@ -17,31 +16,37 @@ INCLUDE( ${adaptor_graphics_dir}/gles-impl/file.list )
 # module: graphics, backend: tizen
 SET( adaptor_graphics_tizen_src_files
     ${adaptor_graphics_dir}/tizen/egl-image-extensions-tizen.cpp
+    ${adaptor_graphics_dir}/tizen/egl-sync-implementation-tizen.cpp
 )
 
 # module: graphics, backend: ubuntu
 SET( adaptor_graphics_ubuntu_src_files
     ${adaptor_graphics_dir}/generic/egl-image-extensions-generic.cpp
+    ${adaptor_graphics_dir}/generic/egl-sync-implementation.cpp
 )
 
 # module: graphics, backend: libuv-x11
 SET( adaptor_graphics_x11_src_files
     ${adaptor_graphics_dir}/generic/egl-image-extensions-generic.cpp
+    ${adaptor_graphics_dir}/generic/egl-sync-implementation.cpp
 )
 
 # module: graphics, backend: android
 SET( adaptor_graphics_android_src_files
     ${adaptor_graphics_dir}/android/egl-image-extensions-android.cpp
+    ${adaptor_graphics_dir}/android/egl-sync-implementation-android.cpp
 )
 
 # module: graphics, backend: windows
 SET( adaptor_graphics_windows_src_files
     ${adaptor_graphics_dir}/windows-gl/egl-image-extensions.cpp
+    ${adaptor_graphics_dir}/windows/egl-sync-implementation-windows.cpp
 )
 
 # module: graphics, backend: macos
 SET( adaptor_graphics_macos_src_files
     ${adaptor_graphics_dir}/macos/egl-image-extensions.cpp
+    ${adaptor_graphics_dir}/macos/egl-sync-implementation-macos.cpp
 )
 
 # include GLES implementation
diff --git a/dali/internal/graphics/generic/egl-sync-implementation.cpp b/dali/internal/graphics/generic/egl-sync-implementation.cpp
new file mode 100644 (file)
index 0000000..842407f
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/graphics/gles/egl-sync-implementation.h>
+
+// EXTERNAL INCLUDES
+
+#include <dali/integration-api/debug.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/graphics/gles/egl-debug.h>
+#include <dali/internal/graphics/gles/egl-implementation.h>
+
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gLogSyncFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_FENCE_SYNC");
+#endif
+
+namespace Dali
+{
+namespace Internal
+{
+namespace Adaptor
+{
+EglSyncObject::EglSyncObject(EglImplementation& eglImpl)
+: mPollCounter(3),
+  mEglImplementation(eglImpl)
+{
+  EGLDisplay display = mEglImplementation.GetDisplay();
+  mEglSync           = eglCreateSync(display, EGL_SYNC_FENCE, NULL);
+}
+
+EglSyncObject::~EglSyncObject()
+{
+  if(mEglSync && mEglImplementation.IsGlesInitialized())
+  {
+    EGLDisplay display = mEglImplementation.GetDisplay();
+    eglDestroySync(display, mEglSync);
+  }
+}
+
+bool EglSyncObject::IsSynced()
+{
+  DALI_LOG_INFO(gLogSyncFilter, Debug::General, "eglClientWaitSync\n");
+  auto result = eglClientWaitSync(mEglImplementation.GetDisplay(), mEglSync, 0 | EGL_SYNC_FLUSH_COMMANDS_BIT, 0);
+
+  if(result == EGL_FALSE)
+  {
+    EGLint error = eglGetError();
+    if(EGL_SUCCESS != error)
+    {
+      DALI_LOG_ERROR("eglClientSyncWait failed: %#0.4x\n", error);
+    }
+  }
+  else if(result == EGL_CONDITION_SATISFIED)
+  {
+    DALI_LOG_INFO(gLogSyncFilter, Debug::General, "eglClientWaitSync Synced!\n");
+    return true;
+  }
+  DALI_LOG_INFO(gLogSyncFilter, Debug::General, "eglClientWaitSync not synced :(\n");
+  return false;
+}
+
+void EglSyncObject::Wait()
+{
+  DALI_LOG_INFO(gLogSyncFilter, Debug::General, "eglWaitSync\n");
+  if(!eglWaitSync(mEglImplementation.GetDisplay(), mEglSync, 0))
+  {
+    EGLint error = eglGetError();
+    if(EGL_SUCCESS != error)
+    {
+      DALI_LOG_ERROR("eglSyncWait failed: %#0.4x\n", error);
+    }
+  }
+}
+
+void EglSyncObject::ClientWait()
+{
+  DALI_LOG_INFO(gLogSyncFilter, Debug::General, "eglWaitSync (blocking)\n");
+  auto result = eglClientWaitSync(mEglImplementation.GetDisplay(), mEglSync, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, EGL_FOREVER);
+  if(result == EGL_FALSE)
+  {
+    EGLint error = eglGetError();
+    if(EGL_SUCCESS != error)
+    {
+      DALI_LOG_ERROR("eglSyncWait failed: %#0.4x\n", error);
+    }
+  }
+  else if(result == EGL_CONDITION_SATISFIED)
+  {
+    DALI_LOG_INFO(gLogSyncFilter, Debug::General, "eglClientWaitSync Synced!\n");
+  }
+}
+
+EglSyncImplementation::EglSyncImplementation()
+: mEglImplementation(NULL),
+  mSyncInitialized(false),
+  mSyncInitializeFailed(false)
+{
+}
+
+EglSyncImplementation::~EglSyncImplementation()
+{
+}
+
+void EglSyncImplementation::Initialize(EglImplementation* eglImpl)
+{
+  mEglImplementation = eglImpl;
+}
+
+Integration::GraphicsSyncAbstraction::SyncObject* EglSyncImplementation::CreateSyncObject()
+{
+  DALI_ASSERT_ALWAYS(mEglImplementation && "Sync Implementation not initialized");
+  return new EglSyncObject(*mEglImplementation);
+}
+
+void EglSyncImplementation::DestroySyncObject(Integration::GraphicsSyncAbstraction::SyncObject* syncObject)
+{
+  DALI_ASSERT_ALWAYS(mEglImplementation && "Sync Implementation not initialized");
+  delete static_cast<EglSyncObject*>(syncObject);
+}
+
+void EglSyncImplementation::InitializeEglSync()
+{
+}
+
+} // namespace Adaptor
+} // namespace Internal
+} // namespace Dali
index abe4c47..3d7979a 100644 (file)
@@ -438,7 +438,7 @@ void EglGraphicsController::ProcessDiscardQueues()
   DALI_TRACE_SCOPE(gTraceFilter, "DALI_EGL_CONTROLLER_DISCARD_QUEUE");
 
   // Process textures
-  ProcessDiscardQueue<GLES::Texture>(mDiscardTextureQueue);
+  ProcessDiscardSet<GLES::Texture>(mDiscardTextureSet);
 
   // Process buffers
   ProcessDiscardQueue<GLES::Buffer>(mDiscardBufferQueue);
@@ -777,89 +777,93 @@ void EglGraphicsController::ProcessTextureUpdateQueue()
           sourceBufferReleaseRequired = Dali::Integration::IsPixelDataReleaseAfterUpload(source.pixelDataSource.pixelData) && info.srcOffset == 0u;
         }
 
-        auto                 sourceStride = info.srcStride;
-        std::vector<uint8_t> tempBuffer;
-
-        if(mGlAbstraction->TextureRequiresConverting(srcFormat, destFormat, isSubImage))
+        // Skip texture upload if given texture is already discarded for this render loop.
+        if(mDiscardTextureSet.find(texture) == mDiscardTextureSet.end())
         {
-          // Convert RGB to RGBA if necessary.
-          if(texture->TryConvertPixelData(sourceBuffer, info.srcFormat, createInfo.format, info.srcSize, info.srcStride, info.srcExtent2D.width, info.srcExtent2D.height, tempBuffer))
+          auto                 sourceStride = info.srcStride;
+          std::vector<uint8_t> tempBuffer;
+
+          if(mGlAbstraction->TextureRequiresConverting(srcFormat, destFormat, isSubImage))
           {
-            sourceBuffer = &tempBuffer[0];
-            sourceStride = 0u; // Converted buffer compacted. make stride as 0.
-            srcFormat    = destFormat;
-            srcType      = GLES::GLTextureFormatType(createInfo.format).type;
+            // Convert RGB to RGBA if necessary.
+            if(texture->TryConvertPixelData(sourceBuffer, info.srcFormat, createInfo.format, info.srcSize, info.srcStride, info.srcExtent2D.width, info.srcExtent2D.height, tempBuffer))
+            {
+              sourceBuffer = &tempBuffer[0];
+              sourceStride = 0u; // Converted buffer compacted. make stride as 0.
+              srcFormat    = destFormat;
+              srcType      = GLES::GLTextureFormatType(createInfo.format).type;
+            }
           }
-        }
 
-        // Calculate the maximum mipmap level for the texture
-        texture->SetMaxMipMapLevel(std::max(texture->GetMaxMipMapLevel(), info.level));
+          // Calculate the maximum mipmap level for the texture
+          texture->SetMaxMipMapLevel(std::max(texture->GetMaxMipMapLevel(), info.level));
 
-        GLenum bindTarget{GL_TEXTURE_2D};
-        GLenum target{GL_TEXTURE_2D};
+          GLenum bindTarget{GL_TEXTURE_2D};
+          GLenum target{GL_TEXTURE_2D};
 
-        if(createInfo.textureType == Graphics::TextureType::TEXTURE_CUBEMAP)
-        {
-          bindTarget = GL_TEXTURE_CUBE_MAP;
-          target     = GL_TEXTURE_CUBE_MAP_POSITIVE_X + info.layer;
-        }
+          if(createInfo.textureType == Graphics::TextureType::TEXTURE_CUBEMAP)
+          {
+            bindTarget = GL_TEXTURE_CUBE_MAP;
+            target     = GL_TEXTURE_CUBE_MAP_POSITIVE_X + info.layer;
+          }
 
-        mGlAbstraction->PixelStorei(GL_UNPACK_ALIGNMENT, 1);
-        mGlAbstraction->PixelStorei(GL_UNPACK_ROW_LENGTH, sourceStride);
+          mGlAbstraction->PixelStorei(GL_UNPACK_ALIGNMENT, 1);
+          mGlAbstraction->PixelStorei(GL_UNPACK_ROW_LENGTH, sourceStride);
 
-        mCurrentContext->BindTexture(bindTarget, texture->GetTextureTypeId(), texture->GetGLTexture());
+          mCurrentContext->BindTexture(bindTarget, texture->GetTextureTypeId(), texture->GetGLTexture());
 
-        if(!isSubImage)
-        {
-          if(!texture->IsCompressed())
-          {
-            mGlAbstraction->TexImage2D(target,
-                                       info.level,
-                                       destInternalFormat,
-                                       info.srcExtent2D.width,
-                                       info.srcExtent2D.height,
-                                       0,
-                                       srcFormat,
-                                       srcType,
-                                       sourceBuffer);
-          }
-          else
-          {
-            mGlAbstraction->CompressedTexImage2D(target,
-                                                 info.level,
-                                                 destInternalFormat,
-                                                 info.srcExtent2D.width,
-                                                 info.srcExtent2D.height,
-                                                 0,
-                                                 info.srcSize,
-                                                 sourceBuffer);
-          }
-        }
-        else
-        {
-          if(!texture->IsCompressed())
+          if(!isSubImage)
           {
-            mGlAbstraction->TexSubImage2D(target,
-                                          info.level,
-                                          info.dstOffset2D.x,
-                                          info.dstOffset2D.y,
-                                          info.srcExtent2D.width,
-                                          info.srcExtent2D.height,
-                                          srcFormat,
-                                          srcType,
-                                          sourceBuffer);
+            if(!texture->IsCompressed())
+            {
+              mGlAbstraction->TexImage2D(target,
+                                         info.level,
+                                         destInternalFormat,
+                                         info.srcExtent2D.width,
+                                         info.srcExtent2D.height,
+                                         0,
+                                         srcFormat,
+                                         srcType,
+                                         sourceBuffer);
+            }
+            else
+            {
+              mGlAbstraction->CompressedTexImage2D(target,
+                                                   info.level,
+                                                   destInternalFormat,
+                                                   info.srcExtent2D.width,
+                                                   info.srcExtent2D.height,
+                                                   0,
+                                                   info.srcSize,
+                                                   sourceBuffer);
+            }
           }
           else
           {
-            mGlAbstraction->CompressedTexSubImage2D(target,
-                                                    info.level,
-                                                    info.dstOffset2D.x,
-                                                    info.dstOffset2D.y,
-                                                    info.srcExtent2D.width,
-                                                    info.srcExtent2D.height,
-                                                    srcFormat,
-                                                    info.srcSize,
-                                                    sourceBuffer);
+            if(!texture->IsCompressed())
+            {
+              mGlAbstraction->TexSubImage2D(target,
+                                            info.level,
+                                            info.dstOffset2D.x,
+                                            info.dstOffset2D.y,
+                                            info.srcExtent2D.width,
+                                            info.srcExtent2D.height,
+                                            srcFormat,
+                                            srcType,
+                                            sourceBuffer);
+            }
+            else
+            {
+              mGlAbstraction->CompressedTexSubImage2D(target,
+                                                      info.level,
+                                                      info.dstOffset2D.x,
+                                                      info.dstOffset2D.y,
+                                                      info.srcExtent2D.width,
+                                                      info.srcExtent2D.height,
+                                                      srcFormat,
+                                                      info.srcSize,
+                                                      sourceBuffer);
+            }
           }
         }
 
index c4a0ba0..cddc538 100644 (file)
@@ -22,6 +22,7 @@
 #include <dali/graphics-api/graphics-controller.h>
 #include <queue>
 #include <unordered_map>
+#include <unordered_set>
 
 // INTERNAL INCLUDES
 #include <dali/integration-api/graphics-sync-abstraction.h>
@@ -384,7 +385,7 @@ public:
    */
   void DiscardResource(GLES::Texture* texture)
   {
-    mDiscardTextureQueue.push(texture);
+    mDiscardTextureSet.insert(texture);
   }
 
   /**
@@ -645,6 +646,40 @@ public:
   }
 
   /**
+   * @brief Processes a discard set for type specified
+   *
+   * @param[in,out] set Reference to the discard set
+   */
+  template<class U, class T>
+  void ProcessDiscardSet(T& set)
+  {
+    while(!set.empty())
+    {
+      auto  iter   = set.begin();
+      auto* object = const_cast<U*>(*iter);
+
+      // Destroy
+      object->DestroyResource();
+
+      // Free
+      auto* clbk = object->GetCreateInfo().allocationCallbacks;
+      if(clbk)
+      {
+        // Call destructor
+        object->~U();
+
+        // Free memory
+        clbk->freeCallback(object, clbk->userData);
+      }
+      else
+      {
+        delete object;
+      }
+      set.erase(iter);
+    }
+  }
+
+  /**
    * @brief Processes all resource create queues
    */
   void ProcessCreateQueues();
@@ -820,8 +855,8 @@ private:
   Internal::Adaptor::EglSyncImplementation* mEglSyncImplementation{nullptr};
   Internal::Adaptor::GraphicsInterface*     mGraphics{nullptr}; // Pointer to owning structure via interface.
 
-  std::queue<GLES::Texture*> mCreateTextureQueue;  ///< Create queue for texture resource
-  std::queue<GLES::Texture*> mDiscardTextureQueue; ///< Discard queue for texture resource
+  std::queue<GLES::Texture*>         mCreateTextureQueue; ///< Create queue for texture resource
+  std::unordered_set<GLES::Texture*> mDiscardTextureSet;  ///< Discard queue for texture resource
 
   std::queue<GLES::Buffer*> mCreateBufferQueue;  ///< Create queue for buffer resource
   std::queue<GLES::Buffer*> mDiscardBufferQueue; ///< Discard queue for buffer resource
index 14410b4..44dd8f4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 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 d014a7f..05ad261 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_GRAPHICS_EGL_SYNC_OBJECT_H
 
 /*
- * Copyright (c) 2021 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.
@@ -24,6 +24,7 @@
 // INTERNAL INCLUDES
 #include <dali/internal/graphics/gles-impl/gles-graphics-resource.h>
 
+//#include <dali/internal/graphics/gles/egl-sync-implementation.h>
 namespace Dali::Internal::Adaptor
 {
 class EglSyncImplementation;
@@ -34,6 +35,9 @@ namespace Dali::Graphics::EGL
 {
 using SyncObjectResource = GLES::Resource<Graphics::SyncObject, Graphics::SyncObjectCreateInfo>;
 
+/**
+ * Proxy to EglSyncObject that also implements a graphics resource
+ */
 class SyncObject : public SyncObjectResource
 {
 public:
index b7e2b5e..c90b2a8 100644 (file)
@@ -378,8 +378,8 @@ void Context::Flush(bool reset, const GLES::DrawCallDescriptor& drawCall, GLES::
       texture->InitializeResource();
     }
 
-    // Warning, this may cause glWaitSync to occur on the GPU.
-    dependencyChecker.CheckNeedsSync(this, texture);
+    // Warning, this may cause glWaitSync to occur on the GPU, or glClientWaitSync to block the CPU.
+    dependencyChecker.CheckNeedsSync(this, texture, true);
     texture->Bind(binding);
     texture->Prepare();
 
index 2141e32..06b742f 100644 (file)
@@ -83,6 +83,10 @@ struct ProgramImpl::Impl
     {
       createInfo.shaderState = new std::vector<ShaderState>(*info.shaderState);
     }
+
+    // Create new reference of std::string_view.
+    name            = std::string(info.name);
+    createInfo.name = name;
   }
 
   ~Impl()
@@ -92,6 +96,7 @@ struct ProgramImpl::Impl
 
   EglGraphicsController& controller;
   ProgramCreateInfo      createInfo;
+  std::string            name;
   uint32_t               glProgram{};
   uint32_t               refCount{0u};
 
@@ -142,6 +147,8 @@ bool ProgramImpl::Create()
 
   auto program = gl->CreateProgram();
 
+  DALI_LOG_INFO(gGraphicsProgramLogFilter, Debug::Verbose, "Program[%s] create program id : %u\n", mImpl->name.c_str(), program);
+
   const auto& info = mImpl->createInfo;
   for(const auto& state : *info.shaderState)
   {
@@ -150,9 +157,13 @@ bool ProgramImpl::Create()
     // Compile shader first (ignored when compiled)
     if(shader->GetImplementation()->Compile())
     {
-      gl->AttachShader(program, shader->GetImplementation()->GetGLShader());
+      auto shaderId = shader->GetImplementation()->GetGLShader();
+      DALI_LOG_INFO(gGraphicsProgramLogFilter, Debug::Verbose, "Program[%s] attach shader : %u\n", mImpl->name.c_str(), shaderId);
+      gl->AttachShader(program, shaderId);
     }
   }
+
+  DALI_LOG_INFO(gGraphicsProgramLogFilter, Debug::Verbose, "Program[%s] call glLinkProgram\n", mImpl->name.c_str());
   gl->LinkProgram(program);
 
   GLint status{0};
@@ -164,7 +175,7 @@ bool ProgramImpl::Create()
     gl->GetProgramInfoLog(program, 4096, &size, output);
 
     // log on error
-    DALI_LOG_ERROR("glLinkProgam failed:\n%s\n", output);
+    DALI_LOG_ERROR("glLinkProgam[%s] failed:\n%s\n", mImpl->name.c_str(), output);
     gl->DeleteProgram(program);
     return false;
   }
index f44fdc3..1d1bc11 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 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 32a89f6..37d0a81 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_GRAPHICS_GLES_SYNC_OBJECT_H
 
 /*
- * Copyright (c) 2021 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.
@@ -35,6 +35,9 @@ namespace Dali::Graphics::GLES
 {
 using SyncObjectResource = Resource<Graphics::SyncObject, Graphics::SyncObjectCreateInfo>;
 
+/**
+ * Class that maintains a glFenceSync object.
+ */
 class SyncObject : public SyncObjectResource
 {
 public:
index 770deb0..c4cd399 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.
 
 // Internal Headers
 #include <dali/internal/graphics/gles-impl/egl-graphics-controller.h>
+#include <dali/internal/graphics/gles/egl-sync-implementation.h>
+
+#if defined(DEBUG_ENABLED)
+extern Debug::Filter* gLogSyncFilter;
+#endif
 
 namespace Dali::Graphics::GLES
 {
-AgingSyncObject::AgingSyncObject(Graphics::EglGraphicsController& controller, const Context* writeContext)
+AgingSyncObject::AgingSyncObject(Graphics::EglGraphicsController& controller, const Context* writeContext, bool _egl)
 : controller(controller),
-  writeContext(writeContext)
+  writeContext(writeContext),
+  egl(_egl)
 {
-  auto gl = controller.GetGL();
-  if(gl)
+  if(egl)
+  {
+    eglSyncObject = static_cast<Internal::Adaptor::EglSyncObject*>(controller.GetEglSyncImplementation().CreateSyncObject());
+    DALI_LOG_INFO(gLogSyncFilter, Debug::Verbose, "AgingSyncObject::cons; EGL::CreateSyncObject: %p\n", eglSyncObject);
+  }
+  else
   {
-    glSyncObject = gl->FenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+    auto gl = controller.GetGL();
+    if(gl)
+    {
+      glSyncObject = gl->FenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+    }
   }
 }
 
 AgingSyncObject::~AgingSyncObject()
 {
-  auto gl = controller.GetGL();
-  if(gl && glSyncObject != nullptr)
+  if(!controller.IsShuttingDown())
   {
-    gl->DeleteSync(glSyncObject);
+    if(egl)
+    {
+      DALI_LOG_INFO(gLogSyncFilter, Debug::Verbose, "AgingSyncObject::dstr; EGL::DestroySyncObject: %p\n", eglSyncObject);
+      controller.GetEglSyncImplementation().DestroySyncObject(eglSyncObject);
+    }
+    else
+    {
+      auto gl = controller.GetGL();
+      if(gl && glSyncObject != nullptr)
+      {
+        gl->DeleteSync(glSyncObject);
+      }
+    }
+  }
+}
+
+bool AgingSyncObject::ClientWait()
+{
+  bool synced = false;
+  if(egl)
+  {
+    if(eglSyncObject)
+    {
+      DALI_LOG_INFO(gLogSyncFilter, Debug::Verbose, "AgingSyncObject::ClientWait(); EGL::ClientWaitSync\n");
+      eglSyncObject->ClientWait();
+      synced = true;
+    }
+  }
+  else
+  {
+    auto gl = controller.GetGL();
+    if(gl && glSyncObject)
+    {
+      DALI_LOG_INFO(gLogSyncFilter, Debug::Verbose, "AgingSyncObject::ClientWait(); glClientWaitSync 1ms\n");
+      const GLuint64 TIMEOUT = 1000000; //1ms!
+      GLenum         result  = gl->ClientWaitSync(glSyncObject, GL_SYNC_FLUSH_COMMANDS_BIT, TIMEOUT);
+
+      synced = (result == GL_ALREADY_SIGNALED || result == GL_CONDITION_SATISFIED);
+    }
+  }
+  DALI_LOG_INFO(gLogSyncFilter, Debug::Verbose, "AgingSyncObject::ClientWait(); Result: %s\n", synced ? "Synced" : "NOT SYNCED");
+  return synced;
+}
+
+void AgingSyncObject::Wait()
+{
+  if(egl)
+  {
+    if(eglSyncObject)
+    {
+      DALI_LOG_INFO(gLogSyncFilter, Debug::Verbose, "AgingSyncObject::Wait(); EGL::WaitSync\n");
+      eglSyncObject->Wait();
+    }
+  }
+  else
+  {
+    auto gl = controller.GetGL();
+    if(gl && glSyncObject)
+    {
+      DALI_LOG_INFO(gLogSyncFilter, Debug::Verbose, "AgingSyncObject::Wait(); glWaitSync\n");
+      gl->WaitSync(glSyncObject, 0, 0ull);
+    }
   }
 }
 
 SyncPool::~SyncPool() = default;
 
-AgingSyncObject* SyncPool::AllocateSyncObject(const Context* writeContext)
+AgingSyncObject* SyncPool::AllocateSyncObject(const Context* writeContext, SyncPool::SyncContext syncContext)
 {
-  std::unique_ptr<AgingSyncObject> syncObject = std::make_unique<AgingSyncObject>(mController, writeContext);
+  std::unique_ptr<AgingSyncObject> syncObject = std::make_unique<AgingSyncObject>(mController, writeContext, (syncContext == SyncContext::EGL));
   mSyncObjects.push_back(std::move(syncObject));
   return mSyncObjects.back().get();
 }
 
 void SyncPool::Wait(AgingSyncObject* syncPoolObject)
 {
-  auto gl = mController.GetGL();
-  if(gl && syncPoolObject->glSyncObject != nullptr)
+  if(syncPoolObject != nullptr)
   {
     syncPoolObject->syncing = true;
-    gl->WaitSync(syncPoolObject->glSyncObject, 0, GL_TIMEOUT_IGNORED);
+    syncPoolObject->Wait();
+  }
+}
+
+bool SyncPool::ClientWait(AgingSyncObject* syncPoolObject)
+{
+  if(syncPoolObject)
+  {
+    return syncPoolObject->ClientWait();
   }
+  return false;
 }
 
 void SyncPool::FreeSyncObject(AgingSyncObject* agingSyncObject)
@@ -79,12 +161,14 @@ void SyncPool::FreeSyncObject(AgingSyncObject* agingSyncObject)
  */
 void SyncPool::AgeSyncObjects()
 {
+  DALI_LOG_INFO(gLogSyncFilter, Debug::Verbose, "AgeSyncObjects: count: %d\n", mSyncObjects.size());
+
   if(!mSyncObjects.empty())
   {
     // Age the remaining sync objects.
     for(auto& agingSyncObject : mSyncObjects)
     {
-      if(agingSyncObject != nullptr && agingSyncObject->glSyncObject != 0)
+      if(agingSyncObject != nullptr && (agingSyncObject->glSyncObject != 0 || agingSyncObject->eglSyncObject != nullptr))
       {
         if(agingSyncObject->age > 0)
         {
@@ -100,6 +184,8 @@ void SyncPool::AgeSyncObjects()
   // Move any old sync objects to the end of the list, and then remove them all.
   mSyncObjects.erase(std::remove_if(mSyncObjects.begin(), mSyncObjects.end(), [&](std::unique_ptr<AgingSyncObject>& agingSyncObject) { return agingSyncObject == nullptr; }),
                      mSyncObjects.end());
+
+  DALI_LOG_INFO(gLogSyncFilter, Debug::Verbose, "AgeSyncObjects: count after erase: %d\n", mSyncObjects.size());
 }
 
 } // namespace Dali::Graphics::GLES
index d394b03..e92cdf0 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_GRAPHICS_GLES_SYNC_POOL_H
 
 /*
- * 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/integration-api/gl-abstraction.h>
 #include <dali/public-api/common/vector-wrapper.h>
 
-namespace Dali::Graphics
+namespace Dali
+{
+namespace Internal::Adaptor
+{
+class EglSyncObject;
+}
+
+namespace Graphics
 {
 class EglGraphicsController;
 
@@ -31,14 +38,22 @@ class Context;
 
 struct AgingSyncObject
 {
-  AgingSyncObject(Graphics::EglGraphicsController& controller, const Context* writeContext);
+  AgingSyncObject(Graphics::EglGraphicsController& controller, const Context* writeContext, bool egl = false);
   ~AgingSyncObject();
 
   EglGraphicsController& controller;
   const Context*         writeContext;
-  GLsync                 glSyncObject{0};
-  uint8_t                age{2};
-  bool                   syncing{false};
+  union
+  {
+    GLsync                            glSyncObject;
+    Internal::Adaptor::EglSyncObject* eglSyncObject;
+  };
+  uint8_t age{2};
+  bool    syncing{false};
+  bool    egl{false};
+
+  void Wait();
+  bool ClientWait();
 };
 using AgingSyncPtrRef = std::unique_ptr<AgingSyncObject>&;
 
@@ -51,6 +66,12 @@ using AgingSyncPtrRef = std::unique_ptr<AgingSyncObject>&;
 class SyncPool
 {
 public:
+  enum class SyncContext
+  {
+    EGL, ///< Use EGL sync when syncing between multiple contexts
+    GL   ///< Use GL sync when syncing in the same context
+  };
+
   explicit SyncPool(Graphics::EglGraphicsController& graphicsController)
   : mController(graphicsController)
   {
@@ -63,19 +84,26 @@ public:
    * @param writeContext
    * @return An owned ptr to a sync object
    */
-  AgingSyncObject* AllocateSyncObject(const Context* writeContext);
+  AgingSyncObject* AllocateSyncObject(const Context* writeContext, SyncContext syncContext);
 
   /**
-   * Wait on a sync object in any context
+   * Wait on a sync object in any context in the GPU
    * @param syncPoolObject The object to wait on.
    */
   void Wait(AgingSyncObject* syncPoolObject);
 
   /**
+   * Wait on a sync object in any context in the CPU
+   * @param syncPoolObject The object to wait on.
+   * @return true if the sync object was signaled, false if it timed out
+   */
+  bool ClientWait(AgingSyncObject* syncPoolObject);
+
+  /**
    * Delete the sync object if it's not needed.
-   *
+   * @param syncPoolObject The object to delete.
    */
-  void FreeSyncObject(AgingSyncObject* agingSyncObject);
+  void FreeSyncObject(AgingSyncObject* syncPoolObject);
 
   /**
    * Age outstanding sync objects. Call at the end of each frame.
@@ -89,6 +117,7 @@ private:
 };
 
 } // namespace GLES
-} // namespace Dali::Graphics
+} // namespace Graphics
+} // namespace Dali
 
 #endif //DALI_GRAPHICS_GLES_SYNC_POOL_H
index cb0ed25..0ce3e44 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 "gles-texture-dependency-checker.h"
 
 // EXTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
 #include <dali/internal/graphics/gles-impl/egl-graphics-controller.h>
 
+#if defined(DEBUG_ENABLED)
+extern Debug::Filter* gLogSyncFilter;
+#endif
+
 namespace Dali::Graphics::GLES
 {
 void TextureDependencyChecker::Reset()
@@ -70,12 +75,16 @@ void TextureDependencyChecker::AddTextures(const GLES::Context* writeContext, co
       texture->SetDependencyIndex(index);
     }
   }
-  textureDependency.writeContext    = const_cast<GLES::Context*>(writeContext);
-  textureDependency.framebuffer     = const_cast<GLES::Framebuffer*>(framebuffer);
-  textureDependency.agingSyncObject = mController.GetSyncPool().AllocateSyncObject(writeContext);
+  textureDependency.writeContext = const_cast<GLES::Context*>(writeContext);
+  textureDependency.framebuffer  = const_cast<GLES::Framebuffer*>(framebuffer);
+
+  // We have to check on different EGL contexts: The shared resource context is used to write to fbos,
+  // but they are usually drawn onto separate scene context.
+  DALI_LOG_INFO(gLogSyncFilter, Debug::Verbose, "TextureDependencyChecker::AddTextures() Allocating sync object\n");
+  textureDependency.agingSyncObject = mController.GetSyncPool().AllocateSyncObject(writeContext, SyncPool::SyncContext::EGL);
 }
 
-void TextureDependencyChecker::CheckNeedsSync(const GLES::Context* readContext, const GLES::Texture* texture)
+void TextureDependencyChecker::CheckNeedsSync(const GLES::Context* readContext, const GLES::Texture* texture, bool cpu)
 {
   uint32_t dependencyIndex = texture->GetDependencyIndex();
   if(dependencyIndex < mTextureDependencies.size())
@@ -86,9 +95,19 @@ void TextureDependencyChecker::CheckNeedsSync(const GLES::Context* readContext,
       // Needs syncing!
       textureDependency.syncing = true;
 
-      // Wait on the sync object in GPU. This will ensure that the writeContext completes its tasks prior
-      // to the sync point.
-      mController.GetSyncPool().Wait(textureDependency.agingSyncObject);
+      if(cpu)
+      {
+        DALI_LOG_INFO(gLogSyncFilter, Debug::Verbose, "TextureDependencyChecker::CheckNeedsSync Insert CPU WAIT");
+        mController.GetSyncPool().ClientWait(textureDependency.agingSyncObject);
+      }
+      else
+      {
+        // Wait on the sync object in GPU. This will ensure that the writeContext completes its tasks prior
+        // to the sync point.
+        // However, this may instead timeout, and we can't tell the difference (at least, for glFenceSync)
+        DALI_LOG_INFO(gLogSyncFilter, Debug::Verbose, "TextureDependencyChecker::CheckNeedsSync Insert GPU WAIT");
+        mController.GetSyncPool().Wait(textureDependency.agingSyncObject);
+      }
     }
   }
 }
index 8861229..63b1127 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_GLES_TEXTURE_DEPENDENCY_CHECKER_H
 
 /*
- * 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.
@@ -63,12 +63,21 @@ public:
 
   /**
    * Check if the given texture needs syncing before being read.  This
-   * will perform a glWaitSync() (GPU side semaphore) if the texture
-   * needs syncing.
+   * will perform either a glWaitSync() (GPU side semaphore), or a
+   * glClientWaitSync(CPU fence) if the texture needs syncing.
    * @param[in] readContext The context that the texture is being read (drawn with)
    * @param[in] texture The texture being read
+   * @param[in] cpuSync True if glClientWaitSync should be used instead of glWaitSync
    */
-  void CheckNeedsSync(const Context* readContext, const Texture* texture);
+  void CheckNeedsSync(const Context* readContext, const Texture* texture, bool cpuSync = false);
+
+  /**
+   * Get the number of (offscreen) textures for dependency checking
+   */
+  size_t GetTextureCount() const
+  {
+    return mTextureDependencies.size();
+  }
 
 private:
   struct TextureDependency
index 6a29ca9..b1bd6ad 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_ADAPTOR_EGL_SYNC_IMPLEMENTATION_H
 
 /*
- * Copyright (c) 2021 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.
@@ -50,11 +50,24 @@ public:
 
   bool IsSynced() override;
 
+  /**
+   * Set up a GPU wait (returns immediately on CPU) for this sync. Can work across
+   * EGL contexts.
+   */
+  void Wait() override;
+
+  /**
+   * Wait on the CPU until the GPU executes this sync. Warning: could be a long time!
+   * Can work across EGL contexts.
+   */
+  void ClientWait() override;
+
 private:
 #ifdef _ARCH_ARM_
   EGLSyncKHR mEglSync;
 #else
-  int mPollCounter; // Implementations without fence sync use a 3 frame counter
+  EGLSync mEglSync;
+  int     mPollCounter; // Implementations without fence sync use a 3 frame counter
 #endif
   EglImplementation& mEglImplementation;
 };
index bf40d8c..1cc2c18 100644 (file)
@@ -208,6 +208,11 @@ public:
     return false;
   }
 
+  uint32_t GetShaderLanguageVersion() override
+  {
+    return static_cast<uint32_t>(GetShadingLanguageVersion());
+  }
+
   std::string GetShaderVersionPrefix() override
   {
     if(mShaderVersionPrefix == "")
@@ -877,7 +882,7 @@ public:
 
     glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels);
 
-    FINISH_DURATION_CHECK_WITH_FORMAT("glTexImage2D", "size : %u x %u", width, height);
+    FINISH_DURATION_CHECK_WITH_FORMAT("glTexImage2D", "size : %u x %u, format : %d, type : %d", width, height, static_cast<int>(format), static_cast<int>(type));
   }
 
   void TexParameterf(GLenum target, GLenum pname, GLfloat param) override
@@ -906,7 +911,7 @@ public:
 
     glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
 
-    FINISH_DURATION_CHECK_WITH_FORMAT("glTexSubImage2D", "size : %u x %u", width, height);
+    FINISH_DURATION_CHECK_WITH_FORMAT("glTexSubImage2D", "size : %u x %u, format : %d, type : %d", width, height, static_cast<int>(format), static_cast<int>(type));
   }
 
   void Uniform1f(GLint location, GLfloat x) override
diff --git a/dali/internal/graphics/macos/egl-sync-implementation-macos.cpp b/dali/internal/graphics/macos/egl-sync-implementation-macos.cpp
new file mode 100644 (file)
index 0000000..df12970
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/graphics/gles/egl-sync-implementation.h>
+
+// EXTERNAL INCLUDES
+
+#include <dali/integration-api/debug.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/graphics/gles/egl-debug.h>
+#include <dali/internal/graphics/gles/egl-implementation.h>
+
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gLogSyncFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_FENCE_SYNC");
+#endif
+
+namespace Dali
+{
+namespace Internal
+{
+namespace Adaptor
+{
+EglSyncObject::EglSyncObject(EglImplementation& eglImpl)
+: mPollCounter(3),
+  mEglImplementation(eglImpl)
+{
+}
+
+EglSyncObject::~EglSyncObject()
+{
+}
+
+bool EglSyncObject::IsSynced()
+{
+  return true;
+}
+
+void EglSyncObject::Wait()
+{
+}
+
+void EglSyncObject::ClientWait()
+{
+}
+
+EglSyncImplementation::EglSyncImplementation()
+: mEglImplementation(NULL),
+  mSyncInitialized(false),
+  mSyncInitializeFailed(false)
+{
+}
+
+EglSyncImplementation::~EglSyncImplementation()
+{
+}
+
+void EglSyncImplementation::Initialize(EglImplementation* eglImpl)
+{
+  mEglImplementation = eglImpl;
+}
+
+Integration::GraphicsSyncAbstraction::SyncObject* EglSyncImplementation::CreateSyncObject()
+{
+  DALI_ASSERT_ALWAYS(mEglImplementation && "Sync Implementation not initialized");
+  return new EglSyncObject(*mEglImplementation);
+}
+
+void EglSyncImplementation::DestroySyncObject(Integration::GraphicsSyncAbstraction::SyncObject* syncObject)
+{
+  DALI_ASSERT_ALWAYS(mEglImplementation && "Sync Implementation not initialized");
+  delete static_cast<EglSyncObject*>(syncObject);
+}
+
+void EglSyncImplementation::InitializeEglSync()
+{
+}
+
+} // namespace Adaptor
+} // namespace Internal
+} // namespace Dali
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 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.
@@ -31,6 +31,7 @@
 #include <dali/integration-api/debug.h>
 
 // INTERNAL INCLUDES
+#include <dali/internal/graphics/gles/egl-debug.h>
 #include <dali/internal/graphics/gles/egl-implementation.h>
 
 #ifdef _ARCH_ARM_
 static PFNEGLCREATESYNCKHRPROC     eglCreateSyncKHR     = NULL;
 static PFNEGLCLIENTWAITSYNCKHRPROC eglClientWaitSyncKHR = NULL;
 static PFNEGLDESTROYSYNCKHRPROC    eglDestroySyncKHR    = NULL;
+static PFNEGLWAITSYNCKHRPROC       eglWaitSyncKHR       = NULL;
 
 #endif
 
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gLogSyncFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_FENCE_SYNC");
+#endif
+
 namespace Dali
 {
 namespace Internal
@@ -50,9 +56,9 @@ namespace Adaptor
 {
 #ifdef _ARCH_ARM_
 
-EglSyncObject::EglSyncObject(EglImplementation& eglSyncImpl)
+EglSyncObject::EglSyncObject(EglImplementation& eglImpl)
 : mEglSync(NULL),
-  mEglImplementation(eglSyncImpl)
+  mEglImplementation(eglImpl)
 {
   EGLDisplay display = mEglImplementation.GetDisplay();
   mEglSync           = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, NULL);
@@ -61,6 +67,10 @@ EglSyncObject::EglSyncObject(EglImplementation& eglSyncImpl)
     DALI_LOG_ERROR("eglCreateSyncKHR failed %#0.4x\n", eglGetError());
     mEglSync = NULL;
   }
+  else
+  {
+    DALI_LOG_INFO(gLogSyncFilter, Debug::General, "eglCreateSyncKHR Success: %p\n", mEglSync);
+  }
 }
 
 EglSyncObject::~EglSyncObject()
@@ -73,6 +83,10 @@ EglSyncObject::~EglSyncObject()
     {
       DALI_LOG_ERROR("eglDestroySyncKHR failed %#0.4x\n", error);
     }
+    else
+    {
+      DALI_LOG_INFO(gLogSyncFilter, Debug::General, "eglDestroySyncKHR Success: %p\n", mEglSync);
+    }
   }
 }
 
@@ -82,6 +96,7 @@ bool EglSyncObject::IsSynced()
 
   if(mEglSync != NULL)
   {
+    DALI_LOG_INFO(gLogSyncFilter, Debug::General, "eglClientWaitSync no timeout\n");
     EGLint result = eglClientWaitSyncKHR(mEglImplementation.GetDisplay(), mEglSync, 0, 0ull);
     EGLint error  = eglGetError();
     if(EGL_SUCCESS != error)
@@ -94,9 +109,46 @@ bool EglSyncObject::IsSynced()
     }
   }
 
+  DALI_LOG_INFO(gLogSyncFilter, Debug::General, "eglClientWaitSync(%p, 0, 0) %s\n", mEglSync, synced ? "Synced" : "NOT SYNCED");
   return synced;
 }
 
+void EglSyncObject::ClientWait()
+{
+  bool synced = false;
+  if(mEglSync != nullptr)
+  {
+    DALI_LOG_INFO(gLogSyncFilter, Debug::General, "eglClientWaitSync FOREVER\n");
+    auto result = eglClientWaitSyncKHR(mEglImplementation.GetDisplay(), mEglSync, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, EGL_FOREVER_KHR);
+    if(result == EGL_FALSE)
+    {
+      Egl::PrintError(eglGetError());
+    }
+    else if(result == EGL_CONDITION_SATISFIED_KHR)
+    {
+      synced = true;
+    }
+  }
+  DALI_LOG_INFO(gLogSyncFilter, Debug::General, "eglClientWaitSync(%p, 0, FOREVER) %s\n", mEglSync, synced ? "Synced" : "NOT SYNCED");
+}
+
+void EglSyncObject::Wait()
+{
+  if(mEglSync != nullptr)
+  {
+    DALI_LOG_INFO(gLogSyncFilter, Debug::General, "eglWaitSync\n");
+    auto result = eglWaitSyncKHR(mEglImplementation.GetDisplay(), mEglSync, 0);
+    if(EGL_FALSE == result)
+    {
+      Egl::PrintError(eglGetError());
+    }
+    else
+    {
+      DALI_LOG_INFO(gLogSyncFilter, Debug::General, "eglWaitSync() %p synced!\n", mEglSync);
+    }
+  }
+}
+
 EglSyncImplementation::EglSyncImplementation()
 : mEglImplementation(NULL),
   mSyncInitialized(false),
@@ -152,10 +204,11 @@ void EglSyncImplementation::InitializeEglSync()
   {
     eglCreateSyncKHR     = reinterpret_cast<PFNEGLCREATESYNCKHRPROC>(eglGetProcAddress("eglCreateSyncKHR"));
     eglClientWaitSyncKHR = reinterpret_cast<PFNEGLCLIENTWAITSYNCKHRPROC>(eglGetProcAddress("eglClientWaitSyncKHR"));
+    eglWaitSyncKHR       = reinterpret_cast<PFNEGLWAITSYNCKHRPROC>(eglGetProcAddress("eglWaitSyncKHR"));
     eglDestroySyncKHR    = reinterpret_cast<PFNEGLDESTROYSYNCKHRPROC>(eglGetProcAddress("eglDestroySyncKHR"));
   }
 
-  if(eglCreateSyncKHR && eglClientWaitSyncKHR && eglDestroySyncKHR)
+  if(eglCreateSyncKHR && eglClientWaitSyncKHR && eglWaitSyncKHR && eglDestroySyncKHR)
   {
     mSyncInitialized = true;
   }
@@ -179,12 +232,15 @@ EglSyncObject::~EglSyncObject()
 
 bool EglSyncObject::IsSynced()
 {
-  if(mPollCounter <= 0)
-  {
-    return true;
-  }
-  --mPollCounter;
-  return false;
+  return true;
+}
+
+void EglSyncObject::Wait()
+{
+}
+
+void EglSyncObject::ClientWait()
+{
 }
 
 EglSyncImplementation::EglSyncImplementation()
diff --git a/dali/internal/graphics/windows-gl/egl-sync-implementation-windows.cpp b/dali/internal/graphics/windows-gl/egl-sync-implementation-windows.cpp
new file mode 100644 (file)
index 0000000..df12970
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/graphics/gles/egl-sync-implementation.h>
+
+// EXTERNAL INCLUDES
+
+#include <dali/integration-api/debug.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/graphics/gles/egl-debug.h>
+#include <dali/internal/graphics/gles/egl-implementation.h>
+
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gLogSyncFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_FENCE_SYNC");
+#endif
+
+namespace Dali
+{
+namespace Internal
+{
+namespace Adaptor
+{
+EglSyncObject::EglSyncObject(EglImplementation& eglImpl)
+: mPollCounter(3),
+  mEglImplementation(eglImpl)
+{
+}
+
+EglSyncObject::~EglSyncObject()
+{
+}
+
+bool EglSyncObject::IsSynced()
+{
+  return true;
+}
+
+void EglSyncObject::Wait()
+{
+}
+
+void EglSyncObject::ClientWait()
+{
+}
+
+EglSyncImplementation::EglSyncImplementation()
+: mEglImplementation(NULL),
+  mSyncInitialized(false),
+  mSyncInitializeFailed(false)
+{
+}
+
+EglSyncImplementation::~EglSyncImplementation()
+{
+}
+
+void EglSyncImplementation::Initialize(EglImplementation* eglImpl)
+{
+  mEglImplementation = eglImpl;
+}
+
+Integration::GraphicsSyncAbstraction::SyncObject* EglSyncImplementation::CreateSyncObject()
+{
+  DALI_ASSERT_ALWAYS(mEglImplementation && "Sync Implementation not initialized");
+  return new EglSyncObject(*mEglImplementation);
+}
+
+void EglSyncImplementation::DestroySyncObject(Integration::GraphicsSyncAbstraction::SyncObject* syncObject)
+{
+  DALI_ASSERT_ALWAYS(mEglImplementation && "Sync Implementation not initialized");
+  delete static_cast<EglSyncObject*>(syncObject);
+}
+
+void EglSyncImplementation::InitializeEglSync()
+{
+}
+
+} // namespace Adaptor
+} // namespace Internal
+} // namespace Dali
index 72a4537..c5265f9 100644 (file)
@@ -27,7 +27,7 @@ namespace Dali
 {
 const unsigned int ADAPTOR_MAJOR_VERSION = 2;
 const unsigned int ADAPTOR_MINOR_VERSION = 3;
-const unsigned int ADAPTOR_MICRO_VERSION = 10;
+const unsigned int ADAPTOR_MICRO_VERSION = 11;
 const char* const  ADAPTOR_BUILD_DATE    = __DATE__ " " __TIME__;
 
 #ifdef DEBUG_ENABLED
index dd2fb0d..cc82170 100644 (file)
@@ -17,7 +17,7 @@
 
 Name:       dali2-adaptor
 Summary:    The DALi Tizen Adaptor
-Version:    2.3.10
+Version:    2.3.11
 Release:    1
 Group:      System/Libraries
 License:    Apache-2.0 and BSD-3-Clause and MIT