Merge "[AT-SPI] Rework intercepting key events" into devel/master
[platform/core/uifw/dali-adaptor.git] / dali / internal / graphics / gles-impl / egl-graphics-controller.cpp
index b211897..88bc34e 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.
@@ -18,6 +18,7 @@
 #include <dali/internal/graphics/gles-impl/egl-graphics-controller.h>
 
 // EXTERNAL INCLUDES
+#include <dali/integration-api/trace.h>
 #include <dali/public-api/common/dali-common.h>
 
 // INTERNAL INCLUDES
@@ -128,6 +129,7 @@ T0* CastObject(T1* apiObject)
 // Maximum size of texture upload buffer.
 const uint32_t TEXTURE_UPLOAD_MAX_BUFER_SIZE_MB = 1;
 
+DALI_INIT_TRACE_FILTER(gTraceFilter, DALI_TRACE_EGL, false);
 } // namespace
 
 EglGraphicsController::EglGraphicsController()
@@ -150,20 +152,18 @@ void EglGraphicsController::InitializeGLES(Integration::GlAbstraction& glAbstrac
 {
   DALI_LOG_RELEASE_INFO("Initializing Graphics Controller Phase 1\n");
   mGlAbstraction  = &glAbstraction;
-  mContext        = std::make_unique<GLES::Context>(*this);
+  mContext        = std::make_unique<GLES::Context>(*this, mGlAbstraction);
   mCurrentContext = mContext.get();
 }
 
-void EglGraphicsController::Initialize(Integration::GraphicsSyncAbstraction&    syncImplementation,
-                                       Integration::GlContextHelperAbstraction& glContextHelperAbstraction,
-                                       Internal::Adaptor::GraphicsInterface&    graphicsInterface)
+void EglGraphicsController::Initialize(Integration::GraphicsSyncAbstraction& syncImplementation,
+                                       Internal::Adaptor::GraphicsInterface& graphicsInterface)
 {
   DALI_LOG_RELEASE_INFO("Initializing Graphics Controller Phase 2\n");
   auto* syncImplPtr = static_cast<Internal::Adaptor::EglSyncImplementation*>(&syncImplementation);
 
-  mEglSyncImplementation      = syncImplPtr;
-  mGlContextHelperAbstraction = &glContextHelperAbstraction;
-  mGraphics                   = &graphicsInterface;
+  mEglSyncImplementation = syncImplPtr;
+  mGraphics              = &graphicsInterface;
 }
 
 void EglGraphicsController::FrameStart()
@@ -241,10 +241,10 @@ Integration::GlAbstraction& EglGraphicsController::GetGlAbstraction()
   return *mGlAbstraction;
 }
 
-Integration::GlContextHelperAbstraction& EglGraphicsController::GetGlContextHelperAbstraction()
+Integration::GraphicsConfig& EglGraphicsController::GetGraphicsConfig()
 {
-  DALI_ASSERT_DEBUG(mGlContextHelperAbstraction && "Graphics controller not initialized");
-  return *mGlContextHelperAbstraction;
+  DALI_ASSERT_DEBUG(mGlAbstraction && "Graphics controller not initialized");
+  return *mGlAbstraction;
 }
 
 Internal::Adaptor::EglSyncImplementation& EglGraphicsController::GetEglSyncImplementation()
@@ -357,7 +357,7 @@ MemoryRequirements EglGraphicsController::GetBufferMemoryRequirements(Buffer& bu
 TextureProperties EglGraphicsController::GetTextureProperties(const Texture& texture)
 {
   const GLES::Texture* glesTexture = static_cast<const GLES::Texture*>(&texture);
-  auto                 createInfo  = glesTexture->GetCreateInfo();
+  const auto&          createInfo  = glesTexture->GetCreateInfo();
 
   TextureProperties properties{};
   properties.format       = createInfo.format;
@@ -376,7 +376,7 @@ const Graphics::Reflection& EglGraphicsController::GetProgramReflection(const Gr
 
 void EglGraphicsController::CreateSurfaceContext(Dali::RenderSurfaceInterface* surface)
 {
-  std::unique_ptr<GLES::Context> context = std::make_unique<GLES::Context>(*this);
+  std::unique_ptr<GLES::Context> context = std::make_unique<GLES::Context>(*this, mGlAbstraction);
   mSurfaceContexts.push_back(std::move(std::make_pair(surface, std::move(context))));
 }
 
@@ -435,8 +435,10 @@ void EglGraphicsController::AddFramebuffer(GLES::Framebuffer& framebuffer)
 
 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);
@@ -476,6 +478,7 @@ void EglGraphicsController::ProcessDiscardQueues()
 
 void EglGraphicsController::ProcessCreateQueues()
 {
+  DALI_TRACE_SCOPE(gTraceFilter, "DALI_EGL_CONTROLLER_CREATE_QUEUE");
   // Process textures
   ProcessCreateQueue(mCreateTextureQueue);
 
@@ -490,6 +493,11 @@ 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 << "]";
+  });
+
   for(auto i = 0u; i < count; ++i)
   {
     auto& cmd = commands[i];
@@ -687,7 +695,13 @@ void EglGraphicsController::ProcessCommandBuffer(const GLES::CommandBuffer& comm
       {
         auto* info = &cmd.drawNative.drawNativeInfo;
 
-        mCurrentContext->PrepareForNativeRendering();
+        // ISOLATED execution mode will isolate GL graphics context from
+        // DALi renderning pipeline which is the safest way of rendering
+        // the 'injected' code.
+        if(info->executionMode == DrawNativeExecutionMode::ISOLATED)
+        {
+          mCurrentContext->PrepareForNativeRendering();
+        }
 
         if(info->glesNativeInfo.eglSharedContextStoragePointer)
         {
@@ -696,12 +710,26 @@ void EglGraphicsController::ProcessCommandBuffer(const GLES::CommandBuffer& comm
         }
 
         CallbackBase::ExecuteReturn<bool>(*info->callback, info->userData);
-
-        mCurrentContext->RestoreFromNativeRendering();
+        if(info->executionMode == DrawNativeExecutionMode::ISOLATED)
+        {
+          mCurrentContext->RestoreFromNativeRendering();
+        }
+        else
+        {
+          // After native rendering reset all states and caches.
+          // This is going to be called only when DIRECT execution mode is used
+          // and some GL states need to be reset.
+          // This does not guarantee that after execution a custom GL code
+          // the main rendering pipeline will work correctly and it's a responsibility
+          // of developer to make sure the GL states are not interfering with main
+          // rendering pipeline (by restoring/cleaning up GL states after drawing).
+          mCurrentContext->ResetGLESState();
+        }
         break;
       }
     }
   }
+  DALI_TRACE_END(gTraceFilter, "DALI_EGL_CONTROLLER_PROCESS");
 }
 
 void EglGraphicsController::ProcessCommandQueues()
@@ -721,6 +749,11 @@ void EglGraphicsController::ProcessCommandQueues()
 
 void EglGraphicsController::ProcessTextureUpdateQueue()
 {
+  if(mTextureUpdateRequests.empty())
+  {
+    return;
+  }
+  DALI_TRACE_SCOPE(gTraceFilter, "DALI_EGL_CONTROLLER_TEXTURE_UPDATE");
   while(!mTextureUpdateRequests.empty())
   {
     TextureUpdateRequest& request = mTextureUpdateRequests.front();
@@ -748,110 +781,124 @@ 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;
-        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;
+
+          uint8_t* srcBuffer = sourceBuffer;
+
+          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))
+            {
+              srcBuffer    = &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())
+          if(!isSubImage)
           {
-            mGlAbstraction->TexImage2D(target,
-                                       info.level,
-                                       destInternalFormat,
-                                       info.srcExtent2D.width,
-                                       info.srcExtent2D.height,
-                                       0,
-                                       srcFormat,
-                                       srcType,
-                                       sourceBuffer);
+            if(!texture->IsCompressed())
+            {
+              mGlAbstraction->TexImage2D(target,
+                                         info.level,
+                                         destInternalFormat,
+                                         info.srcExtent2D.width,
+                                         info.srcExtent2D.height,
+                                         0,
+                                         srcFormat,
+                                         srcType,
+                                         srcBuffer);
+            }
+            else
+            {
+              mGlAbstraction->CompressedTexImage2D(target,
+                                                   info.level,
+                                                   destInternalFormat,
+                                                   info.srcExtent2D.width,
+                                                   info.srcExtent2D.height,
+                                                   0,
+                                                   info.srcSize,
+                                                   srcBuffer);
+            }
           }
           else
           {
-            mGlAbstraction->CompressedTexImage2D(target,
-                                                 info.level,
-                                                 destInternalFormat,
-                                                 info.srcExtent2D.width,
-                                                 info.srcExtent2D.height,
-                                                 0,
-                                                 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,
+                                            srcBuffer);
+            }
+            else
+            {
+              mGlAbstraction->CompressedTexSubImage2D(target,
+                                                      info.level,
+                                                      info.dstOffset2D.x,
+                                                      info.dstOffset2D.y,
+                                                      info.srcExtent2D.width,
+                                                      info.srcExtent2D.height,
+                                                      srcFormat,
+                                                      info.srcSize,
+                                                      srcBuffer);
+            }
           }
         }
-        else
+
+        if(sourceBufferReleaseRequired && sourceBuffer != nullptr)
         {
-          if(!texture->IsCompressed())
+          if(source.sourceType == Graphics::TextureUpdateSourceInfo::Type::MEMORY)
           {
-            mGlAbstraction->TexSubImage2D(target,
-                                          info.level,
-                                          info.dstOffset2D.x,
-                                          info.dstOffset2D.y,
-                                          info.srcExtent2D.width,
-                                          info.srcExtent2D.height,
-                                          srcFormat,
-                                          srcType,
-                                          sourceBuffer);
+            free(reinterpret_cast<void*>(sourceBuffer));
           }
           else
           {
-            mGlAbstraction->CompressedTexSubImage2D(target,
-                                                    info.level,
-                                                    info.dstOffset2D.x,
-                                                    info.dstOffset2D.y,
-                                                    info.srcExtent2D.width,
-                                                    info.srcExtent2D.height,
-                                                    srcFormat,
-                                                    info.srcSize,
-                                                    sourceBuffer);
+            Dali::Integration::ReleasePixelDataBuffer(source.pixelDataSource.pixelData);
           }
         }
-
-        if(source.sourceType == Graphics::TextureUpdateSourceInfo::Type::MEMORY)
-        {
-          // free staging memory
-          free(source.memorySource.memory);
-        }
         break;
       }
       default:
@@ -886,11 +933,18 @@ void EglGraphicsController::UpdateTextures(const std::vector<TextureUpdateInfo>&
 
         uint8_t* stagingBuffer = reinterpret_cast<uint8_t*>(malloc(info.srcSize));
 
-        uint8_t* srcMemory = &reinterpret_cast<uint8_t*>(source.memorySource.memory)[info.srcOffset];
+        if(DALI_UNLIKELY(stagingBuffer == nullptr))
+        {
+          DALI_LOG_ERROR("malloc is failed. request malloc size : %u\n", info.srcSize);
+        }
+        else
+        {
+          uint8_t* srcMemory = &reinterpret_cast<uint8_t*>(source.memorySource.memory)[info.srcOffset];
 
-        std::copy(srcMemory, srcMemory + info.srcSize, stagingBuffer);
+          std::copy(srcMemory, srcMemory + info.srcSize, stagingBuffer);
 
-        mTextureUploadTotalCPUMemoryUsed += info.srcSize;
+          mTextureUploadTotalCPUMemoryUsed += info.srcSize;
+        }
 
         // store staging buffer
         source.memorySource.memory = stagingBuffer;
@@ -925,6 +979,11 @@ void EglGraphicsController::UpdateTextures(const std::vector<TextureUpdateInfo>&
 
 void EglGraphicsController::ProcessTextureMipmapGenerationQueue()
 {
+  if(mTextureMipmapGenerationRequests.empty())
+  {
+    return;
+  }
+  DALI_TRACE_SCOPE(gTraceFilter, "DALI_EGL_CONTROLLER_TEXTURE_MIPMAP");
   while(!mTextureMipmapGenerationRequests.empty())
   {
     auto* texture = mTextureMipmapGenerationRequests.front();