Merge branch 'devel/master' into tizen
[platform/core/uifw/dali-adaptor.git] / dali / internal / graphics / gles-impl / egl-graphics-controller.cpp
index 2f3d5aa..bee69ec 100644 (file)
 #include <dali/integration-api/debug.h>
 #include <dali/integration-api/gl-abstraction.h>
 #include <dali/integration-api/gl-defines.h>
+#include <dali/integration-api/graphics-sync-abstraction.h>
+#include <dali/internal/graphics/gles-impl/egl-sync-object.h>
 #include <dali/internal/graphics/gles-impl/gles-graphics-command-buffer.h>
 #include <dali/internal/graphics/gles-impl/gles-graphics-pipeline.h>
+#include <dali/internal/graphics/gles-impl/gles-graphics-program.h>
 #include <dali/internal/graphics/gles-impl/gles-graphics-render-pass.h>
 #include <dali/internal/graphics/gles-impl/gles-graphics-render-target.h>
 #include <dali/internal/graphics/gles-impl/gles-graphics-shader.h>
 #include <dali/internal/graphics/gles-impl/gles-graphics-texture.h>
 #include <dali/internal/graphics/gles-impl/gles-graphics-types.h>
+#include <dali/internal/graphics/gles-impl/gles-sync-object.h>
 #include <dali/internal/graphics/gles-impl/gles3-graphics-memory.h>
+#include <dali/internal/graphics/gles/egl-sync-implementation.h>
 #include <dali/public-api/common/dali-common.h>
-#include "gles-graphics-program.h"
 
 // Uncomment the following define to turn on frame dumping
 //#define ENABLE_COMMAND_BUFFER_FRAME_DUMP 1
@@ -96,6 +100,9 @@ T0* CastObject(T1* apiObject)
   return static_cast<T0*>(apiObject);
 }
 
+// Maximum size of texture upload buffer.
+const uint32_t TEXTURE_UPLOAD_MAX_BUFER_SIZE_MB = 1;
+
 } // namespace
 
 EglGraphicsController::~EglGraphicsController() = default;
@@ -108,12 +115,14 @@ void EglGraphicsController::InitializeGLES(Integration::GlAbstraction& glAbstrac
   mCurrentContext = mContext.get();
 }
 
-void EglGraphicsController::Initialize(Integration::GlSyncAbstraction&          glSyncAbstraction,
+void EglGraphicsController::Initialize(Integration::GraphicsSyncAbstraction&    syncImplementation,
                                        Integration::GlContextHelperAbstraction& glContextHelperAbstraction,
                                        Internal::Adaptor::GraphicsInterface&    graphicsInterface)
 {
   DALI_LOG_RELEASE_INFO("Initializing New Graphics Controller #2\n");
-  mGlSyncAbstraction          = &glSyncAbstraction;
+  auto* syncImplPtr = static_cast<Internal::Adaptor::EglSyncImplementation*>(&syncImplementation);
+
+  mEglSyncImplementation      = syncImplPtr;
   mGlContextHelperAbstraction = &glContextHelperAbstraction;
   mGraphics                   = &graphicsInterface;
 }
@@ -135,11 +144,20 @@ void EglGraphicsController::SubmitCommandBuffers(const SubmitInfo& submitInfo)
 
 void EglGraphicsController::PresentRenderTarget(RenderTarget* renderTarget)
 {
-  // Use command buffer to execute presentation (we should pool it)
-  CommandBufferCreateInfo info;
-  info.SetLevel(CommandBufferLevel::PRIMARY);
-  info.fixedCapacity        = 1; // only one command
-  auto presentCommandBuffer = new GLES::CommandBuffer(info, *this);
+  GLES::CommandBuffer* presentCommandBuffer{nullptr};
+  if(mPresentationCommandBuffers.empty())
+  {
+    CommandBufferCreateInfo info;
+    info.SetLevel(CommandBufferLevel::PRIMARY);
+    info.fixedCapacity   = 1; // only one command
+    presentCommandBuffer = new GLES::CommandBuffer(info, *this);
+  }
+  else
+  {
+    presentCommandBuffer = const_cast<GLES::CommandBuffer*>(mPresentationCommandBuffers.front());
+    presentCommandBuffer->Reset();
+    mPresentationCommandBuffers.pop();
+  }
   presentCommandBuffer->PresentRenderTarget(static_cast<GLES::RenderTarget*>(renderTarget));
   SubmitInfo submitInfo;
   submitInfo.cmdBuffer = {presentCommandBuffer};
@@ -149,6 +167,8 @@ void EglGraphicsController::PresentRenderTarget(RenderTarget* renderTarget)
 
 void EglGraphicsController::ResolvePresentRenderTarget(GLES::RenderTarget* renderTarget)
 {
+  mCurrentContext->InvalidateDepthStencilBuffers();
+
   auto* rt = static_cast<GLES::RenderTarget*>(renderTarget);
   if(rt->GetCreateInfo().surface)
   {
@@ -164,18 +184,18 @@ Integration::GlAbstraction& EglGraphicsController::GetGlAbstraction()
   return *mGlAbstraction;
 }
 
-Integration::GlSyncAbstraction& EglGraphicsController::GetGlSyncAbstraction()
-{
-  DALI_ASSERT_DEBUG(mGlSyncAbstraction && "Graphics controller not initialized");
-  return *mGlSyncAbstraction;
-}
-
 Integration::GlContextHelperAbstraction& EglGraphicsController::GetGlContextHelperAbstraction()
 {
   DALI_ASSERT_DEBUG(mGlContextHelperAbstraction && "Graphics controller not initialized");
   return *mGlContextHelperAbstraction;
 }
 
+Internal::Adaptor::EglSyncImplementation& EglGraphicsController::GetEglSyncImplementation()
+{
+  DALI_ASSERT_DEBUG(mEglSyncImplementation && "Sync implementation not initialized");
+  return *mEglSyncImplementation;
+}
+
 Graphics::UniquePtr<CommandBuffer> EglGraphicsController::CreateCommandBuffer(
   const CommandBufferCreateInfo&       commandBufferCreateInfo,
   Graphics::UniquePtr<CommandBuffer>&& oldCommandBuffer)
@@ -245,6 +265,19 @@ Graphics::UniquePtr<RenderTarget> EglGraphicsController::CreateRenderTarget(cons
   return NewObject<GLES::RenderTarget>(renderTargetCreateInfo, *this, std::move(oldRenderTarget));
 }
 
+Graphics::UniquePtr<SyncObject> EglGraphicsController::CreateSyncObject(const SyncObjectCreateInfo& syncObjectCreateInfo,
+                                                                        UniquePtr<SyncObject>&&     oldSyncObject)
+{
+  if(GetGLESVersion() < GLES::GLESVersion::GLES_30)
+  {
+    return NewObject<EGL::SyncObject>(syncObjectCreateInfo, *this, std::move(oldSyncObject));
+  }
+  else
+  {
+    return NewObject<GLES::SyncObject>(syncObjectCreateInfo, *this, std::move(oldSyncObject));
+  }
+}
+
 const Graphics::Reflection& EglGraphicsController::GetProgramReflection(const Graphics::Program& program)
 {
   return static_cast<const Graphics::GLES::Program*>(&program)->GetReflection();
@@ -266,6 +299,7 @@ void EglGraphicsController::DeleteSurfaceContext(Dali::RenderSurfaceInterface* s
 void EglGraphicsController::ActivateResourceContext()
 {
   mCurrentContext = mContext.get();
+  mCurrentContext->GlContextCreated();
 }
 
 void EglGraphicsController::ActivateSurfaceContext(Dali::RenderSurfaceInterface* surface)
@@ -279,6 +313,7 @@ void EglGraphicsController::ActivateSurfaceContext(Dali::RenderSurfaceInterface*
     if(iter != mSurfaceContexts.end())
     {
       mCurrentContext = iter->second.get();
+      mCurrentContext->GlContextCreated();
     }
   }
 }
@@ -312,8 +347,14 @@ void EglGraphicsController::ProcessDiscardQueues()
   // Process Framebuffers
   ProcessDiscardQueue<GLES::Framebuffer>(mDiscardFramebufferQueue);
 
+  // Process RenderPass
+  ProcessDiscardQueue<GLES::RenderPass>(mDiscardRenderPassQueue);
+
+  // Process RenderTarget
+  ProcessDiscardQueue<GLES::RenderTarget>(mDiscardRenderTargetQueue);
+
   // Process pipelines
-  ProcessDiscardQueue<GLES::Pipeline>(mDiscardPipelineQueue);
+  ProcessDiscardQueue(mDiscardPipelineQueue);
 
   // Process programs
   ProcessDiscardQueue<GLES::Program>(mDiscardProgramQueue);
@@ -342,8 +383,11 @@ void EglGraphicsController::ProcessCreateQueues()
 
 void EglGraphicsController::ProcessCommandBuffer(const GLES::CommandBuffer& commandBuffer)
 {
-  for(auto& cmd : commandBuffer.GetCommands())
+  auto       count    = 0u;
+  const auto commands = commandBuffer.GetCommands(count);
+  for(auto i = 0u; i < count; ++i)
   {
+    auto& cmd = commands[i];
     // process command
     switch(cmd.type)
     {
@@ -354,19 +398,19 @@ void EglGraphicsController::ProcessCommandBuffer(const GLES::CommandBuffer& comm
       }
       case GLES::CommandType::BIND_TEXTURES:
       {
-        mCurrentContext->BindTextures(cmd.bindTextures.textureBindings);
+        mCurrentContext->BindTextures(cmd.bindTextures.textureBindings.Ptr(), cmd.bindTextures.textureBindingsCount);
         break;
       }
       case GLES::CommandType::BIND_VERTEX_BUFFERS:
       {
-        auto& bindings = cmd.bindVertexBuffers.vertexBufferBindings;
-        mCurrentContext->BindVertexBuffers(bindings);
+        auto bindings = cmd.bindVertexBuffers.vertexBufferBindings.Ptr();
+        mCurrentContext->BindVertexBuffers(bindings, cmd.bindVertexBuffers.vertexBufferBindingsCount);
         break;
       }
       case GLES::CommandType::BIND_UNIFORM_BUFFER:
       {
         auto& bindings = cmd.bindUniformBuffers;
-        mCurrentContext->BindUniformBuffers(bindings.uniformBufferBindings, bindings.standaloneUniformsBufferBinding);
+        mCurrentContext->BindUniformBuffers(bindings.uniformBufferBindingsCount ? bindings.uniformBufferBindings.Ptr() : nullptr, bindings.uniformBufferBindingsCount, bindings.standaloneUniformsBufferBinding);
         break;
       }
       case GLES::CommandType::BIND_INDEX_BUFFER:
@@ -406,14 +450,7 @@ void EglGraphicsController::ProcessCommandBuffer(const GLES::CommandBuffer& comm
       }
       case GLES::CommandType::SET_SCISSOR_TEST:
       {
-        if(cmd.scissorTest.enable)
-        {
-          mGlAbstraction->Enable(GL_SCISSOR_TEST);
-        }
-        else
-        {
-          mGlAbstraction->Disable(GL_SCISSOR_TEST);
-        }
+        mCurrentContext->SetScissorTestEnabled(cmd.scissorTest.enable);
         break;
       }
       case GLES::CommandType::SET_VIEWPORT: // @todo Consider correcting for orientation here?
@@ -504,14 +541,24 @@ void EglGraphicsController::ProcessCommandBuffer(const GLES::CommandBuffer& comm
       case GLES::CommandType::END_RENDERPASS:
       {
         mCurrentContext->EndRenderPass();
+
+        auto syncObject = const_cast<GLES::SyncObject*>(static_cast<const GLES::SyncObject*>(cmd.endRenderPass.syncObject));
+        if(syncObject)
+        {
+          syncObject->InitializeResource();
+        }
         break;
       }
       case GLES::CommandType::PRESENT_RENDER_TARGET:
       {
         ResolvePresentRenderTarget(cmd.presentRenderTarget.targetToPresent);
 
-        // push this command buffer to the discard queue
-        mDiscardCommandBufferQueue.push(const_cast<GLES::CommandBuffer*>(&commandBuffer));
+        // The command buffer will be pushed into the queue of presentation command buffers
+        // for further reuse.
+        if(commandBuffer.GetCreateInfo().fixedCapacity == 1)
+        {
+          mPresentationCommandBuffers.push(&commandBuffer);
+        }
         break;
       }
       case GLES::CommandType::EXECUTE_COMMAND_BUFFERS:
@@ -520,8 +567,10 @@ void EglGraphicsController::ProcessCommandBuffer(const GLES::CommandBuffer& comm
         // todo: check validity of the secondaries
         //       there are operations which are illigal to be done
         //       within secondaries.
-        for(auto& buf : cmd.executeCommandBuffers.buffers)
+        auto buffers = cmd.executeCommandBuffers.buffers.Ptr();
+        for(auto j = 0u; j < cmd.executeCommandBuffers.buffersCount; ++j)
         {
+          auto& buf = buffers[j];
           ProcessCommandBuffer(*static_cast<const GLES::CommandBuffer*>(buf));
         }
         break;
@@ -532,10 +581,6 @@ void EglGraphicsController::ProcessCommandBuffer(const GLES::CommandBuffer& comm
 
 void EglGraphicsController::ProcessCommandQueues()
 {
-  // TODO: command queue per context, sync between queues should be
-  // done externally
-  currentFramebuffer = nullptr;
-
   DUMP_FRAME_START();
 
   while(!mCommandQueue.empty())
@@ -563,11 +608,12 @@ void EglGraphicsController::ProcessTextureUpdateQueue()
       // GPU memory must be already allocated.
 
       // Check if it needs conversion
-      auto*       texture    = static_cast<GLES::Texture*>(info.dstTexture);
-      const auto& createInfo = texture->GetCreateInfo();
-      auto        srcFormat  = GLES::GLTextureFormatType(info.srcFormat).format;
-      auto        destFormat = GLES::GLTextureFormatType(createInfo.format).format;
-      auto        destType   = GLES::GLTextureFormatType(createInfo.format).type;
+      auto*       texture            = static_cast<GLES::Texture*>(info.dstTexture);
+      const auto& createInfo         = texture->GetCreateInfo();
+      auto        srcFormat          = GLES::GLTextureFormatType(info.srcFormat).format;
+      auto        srcType            = GLES::GLTextureFormatType(info.srcFormat).type;
+      auto        destInternalFormat = GLES::GLTextureFormatType(createInfo.format).internalFormat;
+      auto        destFormat         = GLES::GLTextureFormatType(createInfo.format).format;
 
       // From render-texture.cpp
       const bool isSubImage(info.dstOffset2D.x != 0 || info.dstOffset2D.y != 0 ||
@@ -581,55 +627,78 @@ void EglGraphicsController::ProcessTextureUpdateQueue()
         // 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;
       }
 
-      switch(createInfo.textureType)
-      {
-        // Texture 2D
-        case Graphics::TextureType::TEXTURE_2D:
-        {
+      // Calculate the maximum mipmap level for the texture
+      texture->SetMaxMipMapLevel(std::max(texture->GetMaxMipMapLevel(), info.level));
 
-          mGlAbstraction->PixelStorei(GL_UNPACK_ALIGNMENT, 1);
+      GLenum bindTarget{GL_TEXTURE_2D};
+      GLenum target{GL_TEXTURE_2D};
 
-          mGlAbstraction->BindTexture(GL_TEXTURE_2D, texture->GetGLTexture());
+      if(createInfo.textureType == Graphics::TextureType::TEXTURE_CUBEMAP)
+      {
+        bindTarget = GL_TEXTURE_CUBE_MAP;
+        target     = GL_TEXTURE_CUBE_MAP_POSITIVE_X + info.layer;
+      }
 
-          mGlAbstraction->TexSubImage2D(GL_TEXTURE_2D,
-                                        info.level,
-                                        info.dstOffset2D.x,
-                                        info.dstOffset2D.y,
-                                        info.srcExtent2D.width,
-                                        info.srcExtent2D.height,
-                                        destFormat,
-                                        destType,
-                                        sourceBuffer);
-          break;
+      mGlAbstraction->PixelStorei(GL_UNPACK_ALIGNMENT, 1);
+      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);
         }
-        // Texture Cubemap
-        case Graphics::TextureType::TEXTURE_CUBEMAP:
+        else
         {
-          mGlAbstraction->PixelStorei(GL_UNPACK_ALIGNMENT, 1);
-
-          mGlAbstraction->BindTexture(GL_TEXTURE_CUBE_MAP, texture->GetGLTexture());
-
-          mGlAbstraction->TexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + info.layer,
+          mGlAbstraction->CompressedTexImage2D(target,
+                                               info.level,
+                                               destInternalFormat,
+                                               info.srcExtent2D.width,
+                                               info.srcExtent2D.height,
+                                               0,
+                                               info.srcSize,
+                                               sourceBuffer);
+        }
+      }
+      else
+      {
+        if(!texture->IsCompressed())
+        {
+          mGlAbstraction->TexSubImage2D(target,
                                         info.level,
                                         info.dstOffset2D.x,
                                         info.dstOffset2D.y,
                                         info.srcExtent2D.width,
                                         info.srcExtent2D.height,
-                                        destFormat,
-                                        destType,
+                                        srcFormat,
+                                        srcType,
                                         sourceBuffer);
-
-
-          break;
         }
-        default:
+        else
         {
-          // nothing?
+          mGlAbstraction->CompressedTexSubImage2D(target,
+                                                  info.level,
+                                                  info.dstOffset2D.x,
+                                                  info.dstOffset2D.y,
+                                                  info.srcExtent2D.width,
+                                                  info.srcExtent2D.height,
+                                                  srcFormat,
+                                                  info.srcSize,
+                                                  sourceBuffer);
         }
       }
-
       // free staging memory
       free(source.memorySource.memory);
     }
@@ -666,6 +735,8 @@ void EglGraphicsController::UpdateTextures(const std::vector<TextureUpdateInfo>&
                   reinterpret_cast<char*>(source.memorySource.memory) + info.srcSize,
                   stagingBuffer);
 
+        mTextureUploadTotalCPUMemoryUsed += info.srcSize;
+
         // store staging buffer
         source.memorySource.memory = stagingBuffer;
         break;
@@ -682,6 +753,31 @@ void EglGraphicsController::UpdateTextures(const std::vector<TextureUpdateInfo>&
       }
     }
   }
+
+  // If upload buffer exceeds maximum size, flush.
+  if(mTextureUploadTotalCPUMemoryUsed > TEXTURE_UPLOAD_MAX_BUFER_SIZE_MB * 1024)
+  {
+    Flush();
+    mTextureUploadTotalCPUMemoryUsed = 0;
+  }
+}
+
+void EglGraphicsController::ProcessTextureMipmapGenerationQueue()
+{
+  while(!mTextureMipmapGenerationRequests.empty())
+  {
+    auto* texture = mTextureMipmapGenerationRequests.front();
+
+    mCurrentContext->BindTexture(texture->GetGlTarget(), texture->GetTextureTypeId(), texture->GetGLTexture());
+    mCurrentContext->GenerateMipmap(texture->GetGlTarget());
+
+    mTextureMipmapGenerationRequests.pop();
+  }
+}
+
+void EglGraphicsController::GenerateTextureMipmaps(const Graphics::Texture& texture)
+{
+  mTextureMipmapGenerationRequests.push(static_cast<const GLES::Texture*>(&texture));
 }
 
 Graphics::UniquePtr<Memory> EglGraphicsController::MapBufferRange(const MapBufferInfo& mapInfo)