Make PixelData flag that we release buffer after texture upload
[platform/core/uifw/dali-adaptor.git] / dali / internal / graphics / gles-impl / egl-graphics-controller.cpp
index fa90dba..fef6d60 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.
@@ -97,6 +97,24 @@ auto NewObject(const GfxCreateInfo& info, EglGraphicsController& controller, T&&
   }
   else // Use standard allocator
   {
+    // We are given all object for recycling
+    if(oldObject)
+    {
+      auto reusedObject = oldObject.release();
+      // If succeeded, attach the object to the unique_ptr and return it back
+      if(static_cast<GLESType*>(reusedObject)->TryRecycle(info, controller))
+      {
+        return UPtr(reusedObject, GLESDeleter<GLESType>());
+      }
+      else
+      {
+        // can't reuse so kill object by giving it back to original
+        // unique pointer.
+        oldObject.reset(reusedObject);
+      }
+    }
+
+    // Create brand new object
     return UPtr(new GLESType(info, controller), GLESDeleter<GLESType>());
   }
 }
@@ -170,6 +188,11 @@ void EglGraphicsController::SubmitCommandBuffers(const SubmitInfo& submitInfo)
   }
 }
 
+void EglGraphicsController::WaitIdle()
+{
+  Flush();
+}
+
 void EglGraphicsController::PresentRenderTarget(RenderTarget* renderTarget)
 {
   GLES::CommandBuffer* presentCommandBuffer{nullptr};
@@ -275,7 +298,7 @@ Graphics::UniquePtr<Pipeline> EglGraphicsController::CreatePipeline(
 Graphics::UniquePtr<Program> EglGraphicsController::CreateProgram(
   const ProgramCreateInfo& programCreateInfo, UniquePtr<Program>&& oldProgram)
 {
-  // Create program cache if needed
+  // Create pipeline cache if needed
   if(!mPipelineCache)
   {
     mPipelineCache = std::make_unique<GLES::PipelineCache>(*this);
@@ -286,7 +309,12 @@ Graphics::UniquePtr<Program> EglGraphicsController::CreateProgram(
 
 Graphics::UniquePtr<Shader> EglGraphicsController::CreateShader(const ShaderCreateInfo& shaderCreateInfo, Graphics::UniquePtr<Shader>&& oldShader)
 {
-  return NewObject<GLES::Shader>(shaderCreateInfo, *this, std::move(oldShader));
+  // Create pipeline cache if needed
+  if(!mPipelineCache)
+  {
+    mPipelineCache = std::make_unique<GLES::PipelineCache>(*this);
+  }
+  return mPipelineCache->GetShader(shaderCreateInfo, std::move(oldShader));
 }
 
 Graphics::UniquePtr<Sampler> EglGraphicsController::CreateSampler(const SamplerCreateInfo& samplerCreateInfo, Graphics::UniquePtr<Sampler>&& oldSampler)
@@ -312,6 +340,20 @@ Graphics::UniquePtr<SyncObject> EglGraphicsController::CreateSyncObject(const Sy
   }
 }
 
+MemoryRequirements EglGraphicsController::GetBufferMemoryRequirements(Buffer& buffer) const
+{
+  MemoryRequirements requirements{};
+
+  auto gl = GetGL();
+  if(gl)
+  {
+    GLint align;
+    gl->GetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &align);
+    requirements.alignment = align;
+  }
+  return requirements;
+}
+
 TextureProperties EglGraphicsController::GetTextureProperties(const Texture& texture)
 {
   const GLES::Texture* glesTexture = static_cast<const GLES::Texture*>(&texture);
@@ -409,9 +451,17 @@ void EglGraphicsController::ProcessDiscardQueues()
   ProcessDiscardQueue<GLES::RenderTarget>(mDiscardRenderTargetQueue);
 
   // Process pipelines
+  if(mPipelineCache && !mDiscardPipelineQueue.empty())
+  {
+    mPipelineCache->MarkPipelineCacheFlushRequired();
+  }
   ProcessDiscardQueue(mDiscardPipelineQueue);
 
   // Process programs
+  if(mPipelineCache && !mDiscardProgramQueue.empty())
+  {
+    mPipelineCache->MarkProgramCacheFlushRequired();
+  }
   ProcessDiscardQueue<GLES::Program>(mDiscardProgramQueue);
 
   // Process shaders
@@ -698,17 +748,19 @@ void EglGraphicsController::ProcessTextureUpdateQueue()
                               info.srcExtent2D.width != (createInfo.size.width / (1 << info.level)) ||
                               info.srcExtent2D.height != (createInfo.size.height / (1 << info.level)));
 
-        uint8_t* sourceBuffer;
+        uint8_t* sourceBuffer                = nullptr;
+        bool     sourceBufferReleaseRequired = false;
         if(source.sourceType == Graphics::TextureUpdateSourceInfo::Type::MEMORY)
         {
-          sourceBuffer = reinterpret_cast<uint8_t*>(source.memorySource.memory);
+          sourceBuffer                = reinterpret_cast<uint8_t*>(source.memorySource.memory);
+          sourceBufferReleaseRequired = true;
         }
         else
         {
-          // Get buffer of PixelData
           Dali::Integration::PixelDataBuffer pixelBufferData = Dali::Integration::GetPixelDataBuffer(source.pixelDataSource.pixelData);
 
-          sourceBuffer = pixelBufferData.buffer + info.srcOffset;
+          sourceBuffer                = pixelBufferData.buffer + info.srcOffset;
+          sourceBufferReleaseRequired = Dali::Integration::IsPixelDataReleaseAfterUpload(source.pixelDataSource.pixelData) && info.srcOffset == 0u;
         }
 
         auto                 sourceStride = info.srcStride;
@@ -797,10 +849,16 @@ void EglGraphicsController::ProcessTextureUpdateQueue()
           }
         }
 
-        if(source.sourceType == Graphics::TextureUpdateSourceInfo::Type::MEMORY)
+        if(sourceBufferReleaseRequired && sourceBuffer != nullptr)
         {
-          // free staging memory
-          free(source.memorySource.memory);
+          if(source.sourceType == Graphics::TextureUpdateSourceInfo::Type::MEMORY)
+          {
+            free(reinterpret_cast<void*>(sourceBuffer));
+          }
+          else
+          {
+            Dali::Integration::ReleasePixelDataBuffer(source.pixelDataSource.pixelData);
+          }
         }
         break;
       }
@@ -893,12 +951,14 @@ void EglGraphicsController::GenerateTextureMipmaps(const Graphics::Texture& text
 
 Graphics::UniquePtr<Memory> EglGraphicsController::MapBufferRange(const MapBufferInfo& mapInfo)
 {
-  mGraphics->ActivateResourceContext();
-
   // Mapping buffer requires the object to be created NOW
   // Workaround - flush now, otherwise there will be given a staging buffer
   // in case when the buffer is not there yet
-  ProcessCreateQueues();
+  if(!mCreateBufferQueue.empty())
+  {
+    mGraphics->ActivateResourceContext();
+    ProcessCreateQueues();
+  }
 
   if(GetGLESVersion() < GLES::GLESVersion::GLES_30)
   {
@@ -920,4 +980,57 @@ GLES::PipelineCache& EglGraphicsController::GetPipelineCache() const
   return *mPipelineCache;
 }
 
+Graphics::Texture* EglGraphicsController::CreateTextureByResourceId(uint32_t resourceId, const Graphics::TextureCreateInfo& createInfo)
+{
+  Graphics::Texture*                     ret = nullptr;
+  Graphics::UniquePtr<Graphics::Texture> texture;
+
+  auto iter = mExternalTextureResources.find(resourceId);
+  DALI_ASSERT_ALWAYS(iter == mExternalTextureResources.end());
+
+  texture = CreateTexture(createInfo, std::move(texture));
+
+  ret = texture.get();
+
+  mExternalTextureResources.insert(std::make_pair(resourceId, std::move(texture)));
+
+  return ret;
+}
+
+void EglGraphicsController::DiscardTextureFromResourceId(uint32_t resourceId)
+{
+  auto iter = mExternalTextureResources.find(resourceId);
+  if(iter != mExternalTextureResources.end())
+  {
+    mExternalTextureResources.erase(iter);
+  }
+}
+
+Graphics::Texture* EglGraphicsController::GetTextureFromResourceId(uint32_t resourceId)
+{
+  Graphics::Texture* ret = nullptr;
+
+  auto iter = mExternalTextureResources.find(resourceId);
+  if(iter != mExternalTextureResources.end())
+  {
+    ret = iter->second.get();
+  }
+
+  return ret;
+}
+
+Graphics::UniquePtr<Graphics::Texture> EglGraphicsController::ReleaseTextureFromResourceId(uint32_t resourceId)
+{
+  Graphics::UniquePtr<Graphics::Texture> texture;
+
+  auto iter = mExternalTextureResources.find(resourceId);
+  if(iter != mExternalTextureResources.end())
+  {
+    texture = std::move(iter->second);
+    mExternalTextureResources.erase(iter);
+  }
+
+  return texture;
+}
+
 } // namespace Dali::Graphics