Ensure we don't touch shutdowned EglGraphicsController 79/318579/7
authorEunki, Hong <eunkiki.hong@samsung.com>
Wed, 2 Oct 2024 11:13:00 +0000 (20:13 +0900)
committerEunki Hong <eunkiki.hong@samsung.com>
Thu, 10 Oct 2024 01:46:08 +0000 (01:46 +0000)
Let we make IsShuttingDown() API as static,
so we can ask it without raw pointer of graphics controller.

Most of API in GLES::Resource hold the eglController as l-value.
So if someone try to get graphics controller after shutting down,
it might make some crash.

To avoid these kind of issue, let we ensure to call DiscardResource
only if graphics controller is not in shutting down.

TODO : native image should be called DiscardResource() even if it is shutting
downed. How can we ensure it?

Change-Id: I87ec5d96d8c12c054f00db346564f7bae8d5d3bb
Signed-off-by: Eunki, Hong <eunkiki.hong@samsung.com>
15 files changed:
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/gles-graphics-buffer.cpp
dali/internal/graphics/gles-impl/gles-graphics-framebuffer.cpp
dali/internal/graphics/gles-impl/gles-graphics-pipeline-cache.cpp
dali/internal/graphics/gles-impl/gles-graphics-pipeline.cpp
dali/internal/graphics/gles-impl/gles-graphics-program.cpp
dali/internal/graphics/gles-impl/gles-graphics-shader.cpp
dali/internal/graphics/gles-impl/gles-graphics-texture.cpp
dali/internal/graphics/gles-impl/gles-sync-object.cpp
dali/internal/graphics/gles-impl/gles-sync-pool.cpp
dali/internal/graphics/gles-impl/gles2-graphics-memory.cpp
dali/internal/graphics/gles-impl/gles3-graphics-memory.cpp
dali/internal/graphics/tizen/egl-sync-implementation-tizen.cpp

index aa37c0234d704ea826e3db46272bc964e382cc21..8a63e50f7762ec6eb30fb6585e0571298684b208 100644 (file)
@@ -70,8 +70,21 @@ struct GLESDeleter
 
   void operator()(T* object)
   {
-    // Discard resource (add it to discard queue)
-    object->DiscardResource();
+    // GLES object deleter should skip discard queue if controller shutting down
+    if(DALI_LIKELY(!EglGraphicsController::IsShuttingDown()))
+    {
+      // Discard resource (add it to discard queue)
+      object->DiscardResource();
+    }
+    else
+    {
+      // Destroy and delete object otherwise
+      if(DALI_LIKELY(object))
+      {
+        object->DestroyResource();
+      }
+      delete object;
+    }
   }
 };
 
@@ -130,8 +143,15 @@ T0* CastObject(T1* apiObject)
 const uint32_t TEXTURE_UPLOAD_MAX_BUFER_SIZE_MB = 1;
 
 DALI_INIT_TRACE_FILTER(gTraceFilter, DALI_TRACE_EGL, false);
+
+bool gIsShuttingDown = true; ///< Global static flag to ensure that we have single graphics controller instance per each UpdateRender thread loop.
 } // namespace
 
+bool EglGraphicsController::IsShuttingDown()
+{
+  return gIsShuttingDown;
+}
+
 EglGraphicsController::EglGraphicsController()
 : mTextureDependencyChecker(*this),
   mSyncPool(*this)
@@ -151,6 +171,7 @@ EglGraphicsController::~EglGraphicsController()
 void EglGraphicsController::InitializeGLES(Integration::GlAbstraction& glAbstraction)
 {
   DALI_LOG_RELEASE_INFO("Initializing Graphics Controller Phase 1\n");
+
   mGlAbstraction  = &glAbstraction;
   mContext        = std::make_unique<GLES::Context>(*this, mGlAbstraction);
   mCurrentContext = mContext.get();
@@ -162,6 +183,9 @@ void EglGraphicsController::Initialize(Integration::GraphicsSyncAbstraction& syn
   DALI_LOG_RELEASE_INFO("Initializing Graphics Controller Phase 2\n");
   auto* syncImplPtr = static_cast<Internal::Adaptor::EglSyncImplementation*>(&syncImplementation);
 
+  DALI_ASSERT_ALWAYS(gIsShuttingDown && "Don't initialize Phase 2 EglGraphicsController twice");
+  gIsShuttingDown = false;
+
   mEglSyncImplementation = syncImplPtr;
   mGraphics              = &graphicsInterface;
 }
@@ -193,6 +217,28 @@ void EglGraphicsController::WaitIdle()
   Flush();
 }
 
+void EglGraphicsController::Shutdown()
+{
+  DALI_ASSERT_ALWAYS(!gIsShuttingDown && "Don't call EglGraphicsController::Shutdown twice");
+  gIsShuttingDown = true;
+
+  // Final flush
+  Flush();
+
+  if(mContext)
+  {
+    mContext->GlContextDestroyed();
+  }
+
+  for(auto&& context : mSurfaceContexts)
+  {
+    if(context.second)
+    {
+      context.second->GlContextDestroyed();
+    }
+  }
+}
+
 void EglGraphicsController::PresentRenderTarget(RenderTarget* renderTarget)
 {
   GLES::CommandBuffer* presentCommandBuffer{nullptr};
@@ -383,8 +429,7 @@ void EglGraphicsController::CreateSurfaceContext(Dali::Integration::RenderSurfac
 void EglGraphicsController::DeleteSurfaceContext(Dali::Integration::RenderSurfaceInterface* surface)
 {
   mSurfaceContexts.erase(std::remove_if(
-                           mSurfaceContexts.begin(), mSurfaceContexts.end(), [surface](SurfaceContextPair& iter)
-                           { return surface == iter.first; }),
+                           mSurfaceContexts.begin(), mSurfaceContexts.end(), [surface](SurfaceContextPair& iter) { return surface == iter.first; }),
                          mSurfaceContexts.end());
 }
 
@@ -406,8 +451,7 @@ void EglGraphicsController::ActivateSurfaceContext(Dali::Integration::RenderSurf
 {
   if(surface && mGraphics->IsResourceContextSupported())
   {
-    auto iter = std::find_if(mSurfaceContexts.begin(), mSurfaceContexts.end(), [surface](SurfaceContextPair& iter)
-                             { return (iter.first == surface); });
+    auto iter = std::find_if(mSurfaceContexts.begin(), mSurfaceContexts.end(), [surface](SurfaceContextPair& iter) { return (iter.first == surface); });
 
     if(iter != mSurfaceContexts.end())
     {
@@ -496,8 +540,7 @@ void EglGraphicsController::ProcessCommandBuffer(const GLES::CommandBuffer& comm
   auto       count    = 0u;
   const auto commands = commandBuffer.GetCommands(count);
 
-  DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_EGL_CONTROLLER_PROCESS", [&](std::ostringstream& oss)
-                                          { oss << "[commandCount:" << count << "]"; });
+  DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_EGL_CONTROLLER_PROCESS", [&](std::ostringstream& oss) { oss << "[commandCount:" << count << "]"; });
 
   for(auto i = 0u; i < count; ++i)
   {
index fcf85c96d4a51c86afd49fd1a1eb8965134338d3..b14a5aa229843ed73a419f1d2e15edd824372ced 100644 (file)
@@ -68,6 +68,11 @@ class TextureDependencyChecker;
 class EglGraphicsController : public Graphics::Controller
 {
 public:
+  /**
+   * @brief Get whether is graphics controller shutting down or not.
+   */
+  static bool IsShuttingDown();
+
   /**
    * @brief Constructor
    */
@@ -142,26 +147,7 @@ public:
   /**
    * @copydoc Dali::Graphics::Shutdown()
    */
-  void Shutdown() override
-  {
-    mIsShuttingDown = true;
-
-    // Final flush
-    Flush();
-
-    if(mContext)
-    {
-      mContext->GlContextDestroyed();
-    }
-
-    for(auto&& context : mSurfaceContexts)
-    {
-      if(context.second)
-      {
-        context.second->GlContextDestroyed();
-      }
-    }
-  }
+  void Shutdown() override;
 
   /**
    * @copydoc Dali::Graphics::Destroy()
@@ -350,7 +336,7 @@ public: // ResourceId relative API.
 public:
   [[nodiscard]] Integration::GlAbstraction* GetGL() const
   {
-    if(mIsShuttingDown)
+    if(DALI_UNLIKELY(IsShuttingDown()))
     {
       return nullptr;
     }
@@ -740,11 +726,6 @@ public:
     mGLESVersion = glesVersion;
   }
 
-  bool IsShuttingDown() const
-  {
-    return mIsShuttingDown;
-  }
-
   /**
    * @brief Reset texture cache in the contexts
    */
@@ -894,8 +875,6 @@ private:
   GLES::GLESVersion mGLESVersion{GLES::GLESVersion::GLES_20}; ///< Runtime supported GLES version
   uint32_t          mTextureUploadTotalCPUMemoryUsed{0u};
 
-  bool mIsShuttingDown{false}; ///< Indicates whether the controller is shutting down
-
   std::queue<const GLES::CommandBuffer*> mPresentationCommandBuffers{}; ///< Queue of reusable command buffers used by presentation engine
 
   void* mSharedContext{nullptr}; ///< Shared EGL context
index 44dd8f41444bf5494bceb2eb12c5a0197b0f44ac..bfcccd6a10db0ffbccd66fc9dec9f544cf1c8968 100644 (file)
@@ -38,6 +38,12 @@ SyncObject::~SyncObject()
 
 void SyncObject::DestroyResource()
 {
+  if(DALI_UNLIKELY(EglGraphicsController::IsShuttingDown()))
+  {
+    return;
+  }
+  mEglSyncImplementation.DestroySyncObject(mEglSyncObject);
+  mEglSyncObject = nullptr;
 }
 
 bool SyncObject::InitializeResource()
@@ -51,8 +57,7 @@ void SyncObject::DiscardResource()
 {
   // Called from custom deleter.
   // Don't use discard queue, drop immediately.
-  mEglSyncImplementation.DestroySyncObject(mEglSyncObject);
-  mEglSyncObject = nullptr;
+  DestroyResource();
 }
 
 bool SyncObject::IsSynced()
index d2fbaaf32823e12114c4a7e2afccffbde481f950..107e4212b69dedd0e04d4da0ddf8aa5048098001 100644 (file)
@@ -125,6 +125,11 @@ void Buffer::InitializeCPUBuffer()
 
 void Buffer::InitializeGPUBuffer()
 {
+  if(DALI_UNLIKELY(EglGraphicsController::IsShuttingDown()))
+  {
+    return;
+  }
+
   auto context = mController.GetCurrentContext();
   auto gl      = mController.GetGL();
   if(!gl || !context)
@@ -160,10 +165,13 @@ void Buffer::DestroyResource()
   // Deestroy GPU allocation
   else
   {
-    auto gl = mController.GetGL();
-    if(gl)
+    if(DALI_LIKELY(!EglGraphicsController::IsShuttingDown()))
     {
-      gl->DeleteBuffers(1, &mBufferId);
+      auto gl = mController.GetGL();
+      if(gl)
+      {
+        gl->DeleteBuffers(1, &mBufferId);
+      }
     }
   }
 }
index 6695fbf7cfec87bc9631f7663ef9e4de438a57a0..e7b83313887947eba79987c03b1d7f9fc1d78e96 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.
@@ -179,23 +179,26 @@ bool Framebuffer::InitializeResource()
 
 void Framebuffer::DestroyResource()
 {
-  auto context = mController.GetCurrentContext();
-  auto gl      = mController.GetGL();
-  if(gl && context && mInitialized)
+  if(DALI_LIKELY(!EglGraphicsController::IsShuttingDown()))
   {
-    if(mDepthBufferId)
+    auto context = mController.GetCurrentContext();
+    auto gl      = mController.GetGL();
+    if(gl && context && mInitialized)
     {
-      gl->DeleteRenderbuffers(1, &mDepthBufferId);
-    }
-    if(mStencilBufferId)
-    {
-      gl->DeleteRenderbuffers(1, &mStencilBufferId);
-    }
+      if(mDepthBufferId)
+      {
+        gl->DeleteRenderbuffers(1, &mDepthBufferId);
+      }
+      if(mStencilBufferId)
+      {
+        gl->DeleteRenderbuffers(1, &mStencilBufferId);
+      }
 
-    context->DeleteFramebuffers(1, &mFramebufferId);
+      context->DeleteFramebuffers(1, &mFramebufferId);
 
-    mFramebufferId = 0u;
-    mInitialized   = false;
+      mFramebufferId = 0u;
+      mInitialized   = false;
+    }
   }
 }
 
index 4f9c8d785f3ec66cb1d1da915947964582b2fda2..3f2fe69ba0940bec06fa7f3046283b338f13a7af 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.
@@ -39,26 +39,18 @@ struct CachedObjectDeleter
 
   void operator()(T* object)
   {
-    // Discard resource (add it to discard queue)
-    object->DiscardResource();
-  }
-};
-
-template<>
-struct CachedObjectDeleter<GLES::Program>
-{
-  CachedObjectDeleter() = default;
-
-  void operator()(GLES::Program* object)
-  {
-    // Program deleter should skip discard queue if controller shutting down
-    if(!object->GetController().IsShuttingDown())
+    // Discard resource (add it to discard queue) if controller is not shutting down
+    if(DALI_LIKELY(!EglGraphicsController::IsShuttingDown()))
     {
       object->DiscardResource();
     }
     else
     {
-      // delete object otherwise
+      // Destroy and delete object otherwise
+      if(DALI_LIKELY(object))
+      {
+        object->DestroyResource();
+      }
       delete object;
     }
   }
index a927fadc81123c830f7c3842fcbf9018a070d41e..19d9a7dca3467659d0fd280f24bf2186ae86cfe7 100644 (file)
@@ -91,6 +91,11 @@ auto& PipelineImpl::GetController() const
 
 void PipelineImpl::Bind(const uint32_t glProgram) const
 {
+  if(DALI_UNLIKELY(EglGraphicsController::IsShuttingDown()))
+  {
+    return; // Early out if shutting down
+  }
+
   if(auto gl = GetController().GetGL())
   {
     gl->UseProgram(glProgram);
index 0da8eb0d0d0f6087e54125b0819b3238b305e609..ec3f3afdb7eca500d718ba56799879c4529e9a6a 100644 (file)
@@ -122,6 +122,11 @@ ProgramImpl::~ProgramImpl() = default;
 
 bool ProgramImpl::Destroy()
 {
+  if(DALI_UNLIKELY(EglGraphicsController::IsShuttingDown()))
+  {
+    return false; // Early out if shutting down
+  }
+
   if(mImpl->glProgram)
   {
     auto gl = mImpl->controller.GetGL();
@@ -352,6 +357,11 @@ void ProgramImpl::UpdateStandaloneUniformBlock(const char* ptr)
 
   const auto& extraInfos = reflection.GetStandaloneUniformExtraInfo();
 
+  if(DALI_UNLIKELY(EglGraphicsController::IsShuttingDown()))
+  {
+    return; // Early out if shutting down
+  }
+
   auto* gl = GetController().GetGL();
   if(!gl)
   {
index 2a4ba73db205884ff1f26030778b0fb16ecf682d..94e6191b9ed2b155e744f45a5c9dc91b68db68e1 100644 (file)
@@ -155,8 +155,8 @@ struct ShaderImpl::Impl
   std::vector<uint8_t>   sourcePreprocessed{};
 
   size_t sourceOffset{0u}; /// byte offset of source data from original CreateInfo.
-                             /// It will be changed after call StripLegacyCodeIfNeeded
-                             /// More detail, createInfo.sourceData[0] == source[0] == (original CreateInfo).sourceData[sourceOffset];
+                           /// It will be changed after call StripLegacyCodeIfNeeded
+                           /// More detail, createInfo.sourceData[0] == source[0] == (original CreateInfo).sourceData[sourceOffset];
 
   uint32_t glShader{};
   uint32_t refCount{0u};
@@ -171,7 +171,7 @@ ShaderImpl::ShaderImpl(const Graphics::ShaderCreateInfo& createInfo, Graphics::E
 
 ShaderImpl::~ShaderImpl()
 {
-  if(!mImpl->controller.IsShuttingDown())
+  if(DALI_LIKELY(!EglGraphicsController::IsShuttingDown()))
   {
     mImpl->Destroy();
   }
@@ -302,6 +302,11 @@ Shader::~Shader()
 {
   if(!mShader->Release())
   {
+    if(DALI_UNLIKELY(EglGraphicsController::IsShuttingDown()))
+    {
+      return; // Early out if shutting down
+    }
+
     GetImplementation()->GetController().GetPipelineCache().MarkShaderCacheFlushRequired();
   }
 }
@@ -313,11 +318,7 @@ Shader::~Shader()
 
 void Shader::DiscardResource()
 {
-  auto& controller = GetImplementation()->GetController();
-  if(!controller.IsShuttingDown())
-  {
-    controller.DiscardResource(this);
-  }
+  GetImplementation()->GetController().DiscardResource(this);
 }
 
 uint32_t Shader::GetGLSLVersion() const
index cd4b66d0c8226f7658e0342093e2d8aba325281b..7471f5c6c6888fd95283c07b062fa2cb23c72b51 100644 (file)
@@ -310,20 +310,26 @@ bool Texture::InitializeTexture()
 
 void Texture::DestroyResource()
 {
-  auto gl = mController.GetGL();
-  if(!gl)
+  if(DALI_LIKELY(!EglGraphicsController::IsShuttingDown()))
   {
-    return;
-  }
+    auto gl = mController.GetGL();
+    if(!gl)
+    {
+      return;
+    }
 
-  // This is a proper destructor
-  if(mTextureId)
-  {
-    gl->DeleteTextures(1, &mTextureId);
-  }
-  if(mCreateInfo.nativeImagePtr)
-  {
-    mCreateInfo.nativeImagePtr->DestroyResource();
+    // This is a proper destructor
+    if(mTextureId)
+    {
+      gl->DeleteTextures(1, &mTextureId);
+    }
+
+    // TODO : Shouldn't we call DestroyResource even if shutting down?
+    // For now, we use EglExtensions API at DestroyResource. So just block for now.
+    if(mCreateInfo.nativeImagePtr)
+    {
+      mCreateInfo.nativeImagePtr->DestroyResource();
+    }
   }
 }
 
index 1d1bc1197d43c8adfd3e987c27de0fbc3e4113a8..bfaccecf43cf18ea35756d89ee87c08d675c409e 100644 (file)
@@ -36,6 +36,15 @@ SyncObject::~SyncObject()
 
 void SyncObject::DestroyResource()
 {
+  if(DALI_LIKELY(!EglGraphicsController::IsShuttingDown()))
+  {
+    auto gl = mController.GetGL();
+    if(gl)
+    {
+      gl->DeleteSync(mGlSyncObject);
+    }
+    mGlSyncObject = 0;
+  }
 }
 
 bool SyncObject::InitializeResource()
@@ -53,12 +62,7 @@ void SyncObject::DiscardResource()
 {
   // Called from custom deleter.
   // Don't use discard queue, drop immediately.
-  auto gl = mController.GetGL();
-  if(gl)
-  {
-    gl->DeleteSync(mGlSyncObject);
-  }
-  mGlSyncObject = 0;
+  DestroyResource();
 }
 
 bool SyncObject::IsSynced()
index c4cd3991697fadc14fee037395b80660b8c03fc1..6077414f47cc86cf88636c74df336922ede1f578 100644 (file)
@@ -52,7 +52,7 @@ AgingSyncObject::AgingSyncObject(Graphics::EglGraphicsController& controller, co
 
 AgingSyncObject::~AgingSyncObject()
 {
-  if(!controller.IsShuttingDown())
+  if(DALI_LIKELY(!EglGraphicsController::IsShuttingDown()))
   {
     if(egl)
     {
index 6ad22f8c47d06af32bf59e0986272bcec640a9c2..6d3f1492b766780fdd3ebec4b0149c63aa719053 100644 (file)
@@ -78,28 +78,31 @@ void* Memory2::LockRegion(uint32_t offset, uint32_t size)
 
 void Memory2::Unlock(bool flush)
 {
-  if(auto gl = mController.GetGL())
+  if(DALI_LIKELY(!EglGraphicsController::IsShuttingDown()))
   {
-    // for buffer...
-    if(mMapObjectType == MapObjectType::BUFFER && mMappedPointer)
+    if(auto gl = mController.GetGL())
     {
-      auto buffer = static_cast<GLES::Buffer*>(mMapBufferInfo.buffer);
-      if(!buffer->IsCPUAllocated())
+      // for buffer...
+      if(mMapObjectType == MapObjectType::BUFFER && mMappedPointer)
       {
-        buffer->Bind(BufferUsage::VERTEX_BUFFER);
-        gl->BufferSubData(GL_ARRAY_BUFFER, GLintptr(mMapBufferInfo.offset), GLsizeiptr(mMapBufferInfo.size), mMappedPointer);
+        auto buffer = static_cast<GLES::Buffer*>(mMapBufferInfo.buffer);
+        if(!buffer->IsCPUAllocated())
+        {
+          buffer->Bind(BufferUsage::VERTEX_BUFFER);
+          gl->BufferSubData(GL_ARRAY_BUFFER, GLintptr(mMapBufferInfo.offset), GLsizeiptr(mMapBufferInfo.size), mMappedPointer);
+        }
       }
-    }
 
-    if(mIsAllocatedLocally)
-    {
-      free(mMappedPointer);
-      mMappedPointer = nullptr;
-    }
+      if(mIsAllocatedLocally)
+      {
+        free(mMappedPointer);
+        mMappedPointer = nullptr;
+      }
 
-    if(flush)
-    {
-      Flush();
+      if(flush)
+      {
+        Flush();
+      }
     }
   }
 }
index 18e78616a7f19669b3ff21f32746ecc7d4295ba2..c0aec279bbc3707dd7674216ddbe250c0812f093 100644 (file)
@@ -49,25 +49,28 @@ Memory3::~Memory3()
 
 void* Memory3::LockRegion(uint32_t offset, uint32_t size)
 {
-  if(auto gl = mController.GetGL())
+  if(DALI_LIKELY(!EglGraphicsController::IsShuttingDown()))
   {
-    if(mMapObjectType == MapObjectType::BUFFER)
+    if(auto gl = mController.GetGL())
     {
-      auto buffer = static_cast<GLES::Buffer*>(mMapBufferInfo.buffer);
-
-      if(buffer->IsCPUAllocated())
-      {
-        using Ptr      = char*;
-        mMappedPointer = Ptr(buffer->GetCPUAllocatedAddress()) + offset;
-      }
-      else
+      if(mMapObjectType == MapObjectType::BUFFER)
       {
-        gl->BindBuffer(GL_COPY_WRITE_BUFFER, buffer->GetGLBuffer());
-        void* ptr      = nullptr;
-        ptr            = gl->MapBufferRange(GL_COPY_WRITE_BUFFER, GLintptr(mMapBufferInfo.offset), GLsizeiptr(mMapBufferInfo.size), GL_MAP_WRITE_BIT);
-        mMappedPointer = ptr;
+        auto buffer = static_cast<GLES::Buffer*>(mMapBufferInfo.buffer);
+
+        if(buffer->IsCPUAllocated())
+        {
+          using Ptr      = char*;
+          mMappedPointer = Ptr(buffer->GetCPUAllocatedAddress()) + offset;
+        }
+        else
+        {
+          gl->BindBuffer(GL_COPY_WRITE_BUFFER, buffer->GetGLBuffer());
+          void* ptr      = nullptr;
+          ptr            = gl->MapBufferRange(GL_COPY_WRITE_BUFFER, GLintptr(mMapBufferInfo.offset), GLsizeiptr(mMapBufferInfo.size), GL_MAP_WRITE_BIT);
+          mMappedPointer = ptr;
+        }
+        return mMappedPointer;
       }
-      return mMappedPointer;
     }
   }
   return nullptr;
@@ -75,21 +78,24 @@ void* Memory3::LockRegion(uint32_t offset, uint32_t size)
 
 void Memory3::Unlock(bool flush)
 {
-  if(auto gl = mController.GetGL())
+  if(DALI_LIKELY(!EglGraphicsController::IsShuttingDown()))
   {
-    if(mMapObjectType == MapObjectType::BUFFER && mMappedPointer)
+    if(auto gl = mController.GetGL())
     {
-      auto buffer = static_cast<GLES::Buffer*>(mMapBufferInfo.buffer);
-      if(!buffer->IsCPUAllocated())
+      if(mMapObjectType == MapObjectType::BUFFER && mMappedPointer)
       {
-        gl->BindBuffer(GL_COPY_WRITE_BUFFER, buffer->GetGLBuffer());
-        gl->UnmapBuffer(GL_COPY_WRITE_BUFFER);
+        auto buffer = static_cast<GLES::Buffer*>(mMapBufferInfo.buffer);
+        if(!buffer->IsCPUAllocated())
+        {
+          gl->BindBuffer(GL_COPY_WRITE_BUFFER, buffer->GetGLBuffer());
+          gl->UnmapBuffer(GL_COPY_WRITE_BUFFER);
+        }
       }
-    }
 
-    if(flush)
-    {
-      Flush();
+      if(flush)
+      {
+        Flush();
+      }
     }
 
     mMappedPointer = nullptr;
index 41c771a3ced6c4ce19521a639129148cc550911a..a334a91d94318bc3922a0b39235eb975f8d69267 100644 (file)
@@ -158,6 +158,11 @@ EglSyncImplementation::EglSyncImplementation()
 
 EglSyncImplementation::~EglSyncImplementation()
 {
+  for(auto& syncObject : mSyncObjects)
+  {
+    delete static_cast<EglSyncObject*>(syncObject);
+  }
+  mSyncObjects.Clear();
 }
 
 void EglSyncImplementation::Initialize(EglImplementation* eglImpl)