Synchronize framebuffer textures on different contexts
[platform/core/uifw/dali-adaptor.git] / dali / internal / graphics / gles-impl / egl-graphics-controller.cpp
index 84325ae..8717f7f 100644 (file)
 #include <dali/internal/graphics/gles/egl-sync-implementation.h>
 #include <dali/public-api/common/dali-common.h>
 
+#include <dali/internal/graphics/gles/egl-graphics.h>
+
+#include <any>
+
 // Uncomment the following define to turn on frame dumping
 //#define ENABLE_COMMAND_BUFFER_FRAME_DUMP 1
 #include <dali/internal/graphics/gles-impl/egl-graphics-controller-debug.h>
@@ -105,6 +109,12 @@ const uint32_t TEXTURE_UPLOAD_MAX_BUFER_SIZE_MB = 1;
 
 } // namespace
 
+EglGraphicsController::EglGraphicsController()
+: mTextureDependencyChecker(*this),
+  mSyncPool(*this)
+{
+}
+
 EglGraphicsController::~EglGraphicsController()
 {
   while(!mPresentationCommandBuffers.empty())
@@ -186,6 +196,12 @@ void EglGraphicsController::ResolvePresentRenderTarget(GLES::RenderTarget* rende
   }
 }
 
+void EglGraphicsController::PostRender()
+{
+  mTextureDependencyChecker.Reset();
+  mSyncPool.AgeSyncObjects();
+}
+
 Integration::GlAbstraction& EglGraphicsController::GetGlAbstraction()
 {
   DALI_ASSERT_DEBUG(mGlAbstraction && "Graphics controller not initialized");
@@ -308,6 +324,15 @@ void EglGraphicsController::ActivateResourceContext()
 {
   mCurrentContext = mContext.get();
   mCurrentContext->GlContextCreated();
+
+  if(!mSharedContext)
+  {
+    auto eglGraphics = dynamic_cast<Dali::Internal::Adaptor::EglGraphics*>(mGraphics);
+    if(eglGraphics)
+    {
+      mSharedContext = eglGraphics->GetEglImplementation().GetContext();
+    }
+  }
 }
 
 void EglGraphicsController::ActivateSurfaceContext(Dali::RenderSurfaceInterface* surface)
@@ -438,17 +463,17 @@ void EglGraphicsController::ProcessCommandBuffer(const GLES::CommandBuffer& comm
       }
       case GLES::CommandType::DRAW:
       {
-        mCurrentContext->Flush(false, cmd.draw);
+        mCurrentContext->Flush(false, cmd.draw, mTextureDependencyChecker);
         break;
       }
       case GLES::CommandType::DRAW_INDEXED:
       {
-        mCurrentContext->Flush(false, cmd.draw);
+        mCurrentContext->Flush(false, cmd.draw, mTextureDependencyChecker);
         break;
       }
       case GLES::CommandType::DRAW_INDEXED_INDIRECT:
       {
-        mCurrentContext->Flush(false, cmd.draw);
+        mCurrentContext->Flush(false, cmd.draw, mTextureDependencyChecker);
         break;
       }
       case GLES::CommandType::SET_SCISSOR: // @todo Consider correcting for orientation here?
@@ -544,12 +569,15 @@ void EglGraphicsController::ProcessCommandBuffer(const GLES::CommandBuffer& comm
         }
 
         mCurrentContext->BeginRenderPass(cmd.beginRenderPass);
+
         break;
       }
       case GLES::CommandType::END_RENDERPASS:
       {
-        mCurrentContext->EndRenderPass();
+        mCurrentContext->EndRenderPass(mTextureDependencyChecker);
 
+        // This sync object is to enable cpu to wait for rendering to complete, not gpu.
+        // It's only needed for reading the framebuffer texture in the client.
         auto syncObject = const_cast<GLES::SyncObject*>(static_cast<const GLES::SyncObject*>(cmd.endRenderPass.syncObject));
         if(syncObject)
         {
@@ -589,6 +617,12 @@ void EglGraphicsController::ProcessCommandBuffer(const GLES::CommandBuffer& comm
 
         mCurrentContext->PrepareForNativeRendering();
 
+        if(info->glesNativeInfo.eglSharedContextStoragePointer)
+        {
+          auto* anyContext = reinterpret_cast<std::any*>(info->glesNativeInfo.eglSharedContextStoragePointer);
+          *anyContext      = mSharedContext;
+        }
+
         CallbackBase::ExecuteReturn<bool>(*info->callback, info->userData);
 
         mCurrentContext->RestoreFromNativeRendering();
@@ -640,14 +674,19 @@ void EglGraphicsController::ProcessTextureUpdateQueue()
                             info.srcExtent2D.height != (createInfo.size.height / (1 << info.level)));
 
       auto*                sourceBuffer = reinterpret_cast<uint8_t*>(source.memorySource.memory);
+      auto                 sourceStride = info.srcStride;
       std::vector<uint8_t> tempBuffer;
+
       if(mGlAbstraction->TextureRequiresConverting(srcFormat, destFormat, isSubImage))
       {
         // Convert RGB to RGBA if necessary.
-        texture->TryConvertPixelData(source.memorySource.memory, info.srcFormat, createInfo.format, info.srcSize, info.srcExtent2D.width, info.srcExtent2D.height, tempBuffer);
-        sourceBuffer = &tempBuffer[0];
-        srcFormat    = destFormat;
-        srcType      = GLES::GLTextureFormatType(createInfo.format).type;
+        if(texture->TryConvertPixelData(source.memorySource.memory, 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
@@ -663,7 +702,7 @@ void EglGraphicsController::ProcessTextureUpdateQueue()
       }
 
       mGlAbstraction->PixelStorei(GL_UNPACK_ALIGNMENT, 1);
-      mGlAbstraction->PixelStorei(GL_UNPACK_ROW_LENGTH, info.srcStride);
+      mGlAbstraction->PixelStorei(GL_UNPACK_ROW_LENGTH, sourceStride);
 
       mCurrentContext->BindTexture(bindTarget, texture->GetTextureTypeId(), texture->GetGLTexture());
 
@@ -751,10 +790,11 @@ void EglGraphicsController::UpdateTextures(const std::vector<TextureUpdateInfo>&
         // TODO: using PBO with GLES3, this is just naive
         // oldschool way
 
-        char* stagingBuffer = reinterpret_cast<char*>(malloc(info.srcSize));
-        std::copy(&reinterpret_cast<char*>(source.memorySource.memory)[info.srcOffset],
-                  reinterpret_cast<char*>(source.memorySource.memory) + info.srcSize,
-                  stagingBuffer);
+        uint8_t* stagingBuffer = reinterpret_cast<uint8_t*>(malloc(info.srcSize));
+
+        uint8_t* srcMemory = &reinterpret_cast<uint8_t*>(source.memorySource.memory)[info.srcOffset];
+
+        std::copy(srcMemory, srcMemory + info.srcSize, stagingBuffer);
 
         mTextureUploadTotalCPUMemoryUsed += info.srcSize;
 
@@ -776,7 +816,7 @@ void EglGraphicsController::UpdateTextures(const std::vector<TextureUpdateInfo>&
   }
 
   // If upload buffer exceeds maximum size, flush.
-  if(mTextureUploadTotalCPUMemoryUsed > TEXTURE_UPLOAD_MAX_BUFER_SIZE_MB * 1024)
+  if(mTextureUploadTotalCPUMemoryUsed > TEXTURE_UPLOAD_MAX_BUFER_SIZE_MB * 1024 * 1024)
   {
     Flush();
     mTextureUploadTotalCPUMemoryUsed = 0;