[Tizen] Fix typo error at ArrayBuffer bind + minor backport
[platform/core/uifw/dali-adaptor.git] / dali / internal / graphics / gles-impl / gles-context.cpp
index 1d981bc..c6f0728 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
@@ -34,6 +34,7 @@
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
 #include <map>
+#include <unordered_map>
 
 namespace Dali::Graphics::GLES
 {
@@ -53,24 +54,42 @@ struct Context::Impl
    * that VertexInputState has been set correctly for the pipeline.
    *
    */
-  void BindProgramVAO(GLES::ProgramImpl* program, const VertexInputState& vertexInputState)
+  void BindProgramVAO(const GLES::ProgramImpl* program, const VertexInputState& vertexInputState)
   {
+    // Calculate attributes location hash unordered.
+    std::size_t hash = 0;
+    for(const auto& attr : vertexInputState.attributes)
+    {
+      hash ^= std::hash<uint32_t>{}(attr.location);
+    }
+
     auto& gl   = *mController.GetGL();
     auto  iter = mProgramVAOMap.find(program);
     if(iter != mProgramVAOMap.end())
     {
-      if(mProgramVAOCurrentState != iter->second)
+      auto attributeIter = iter->second.find(hash);
+      if(attributeIter != iter->second.end())
       {
-        mProgramVAOCurrentState = iter->second;
-        gl.BindVertexArray(iter->second);
+        if(mProgramVAOCurrentState != attributeIter->second)
+        {
+          mProgramVAOCurrentState = attributeIter->second;
+          gl.BindVertexArray(attributeIter->second);
+
+          // Binding VAO seems to reset the index buffer binding so the cache must be reset
+          mGlStateCache.mBoundElementArrayBufferId = 0;
+        }
+        return;
       }
-      return;
     }
 
     uint32_t vao;
     gl.GenVertexArrays(1, &vao);
     gl.BindVertexArray(vao);
-    mProgramVAOMap[program] = vao;
+
+    // Binding VAO seems to reset the index buffer binding so the cache must be reset
+    mGlStateCache.mBoundElementArrayBufferId = 0;
+
+    mProgramVAOMap[program][hash] = vao;
     for(const auto& attr : vertexInputState.attributes)
     {
       gl.EnableVertexAttribArray(attr.location);
@@ -206,9 +225,9 @@ struct Context::Impl
   const GLES::RenderPass*   mCurrentRenderPass{nullptr};
 
   // Each context must have own VAOs as they cannot be shared
-  std::map<GLES::ProgramImpl*, uint32_t> mProgramVAOMap;              ///< GL program-VAO map
-  uint32_t                               mProgramVAOCurrentState{0u}; ///< Currently bound VAO
-  GLStateCache                           mGlStateCache{};             ///< GL status cache
+  std::unordered_map<const GLES::ProgramImpl*, std::map<std::size_t, uint32_t>> mProgramVAOMap;              ///< GL program-VAO map
+  uint32_t                                                                      mProgramVAOCurrentState{0u}; ///< Currently bound VAO
+  GLStateCache                                                                  mGlStateCache{};             ///< GL status cache
 
   bool mGlContextCreated{false}; ///< True if the OpenGL context has been created
 
@@ -938,13 +957,31 @@ void Context::GenerateMipmap(GLenum target)
 
 void Context::BindBuffer(GLenum target, uint32_t bufferId)
 {
-  if(mImpl->mGlStateCache.mBoundArrayBufferId != bufferId)
+  switch(target)
   {
-    mImpl->mGlStateCache.mBoundArrayBufferId = bufferId;
-
-    auto& gl = *mImpl->mController.GetGL();
-    gl.BindBuffer(target, bufferId);
+    case GL_ARRAY_BUFFER:
+    {
+      if(mImpl->mGlStateCache.mBoundArrayBufferId == bufferId)
+      {
+        return;
+      }
+      mImpl->mGlStateCache.mBoundArrayBufferId = bufferId;
+      break;
+    }
+    case GL_ELEMENT_ARRAY_BUFFER:
+    {
+      if(mImpl->mGlStateCache.mBoundElementArrayBufferId == bufferId)
+      {
+        return;
+      }
+      mImpl->mGlStateCache.mBoundElementArrayBufferId = bufferId;
+      break;
+    }
   }
+
+  // Cache miss. Bind buffer.
+  auto& gl = *mImpl->mController.GetGL();
+  gl.BindBuffer(target, bufferId);
 }
 
 void Context::DrawBuffers(uint32_t count, const GLenum* buffers)
@@ -1009,6 +1046,34 @@ void Context::InvalidateCachedPipeline(GLES::Pipeline* pipeline)
   {
     mImpl->mCurrentPipeline = nullptr;
   }
+
+  // Remove cached VAO map
+  auto* gl = mImpl->mController.GetGL();
+  if(gl)
+  {
+    const auto* program = pipeline->GetCreateInfo().programState->program;
+    if(program)
+    {
+      const auto* programImpl = static_cast<const GLES::Program*>(program)->GetImplementation();
+      if(programImpl)
+      {
+        auto iter = mImpl->mProgramVAOMap.find(programImpl);
+        if(iter != mImpl->mProgramVAOMap.end())
+        {
+          for(auto& attributeHashPair : iter->second)
+          {
+            auto vao = attributeHashPair.second;
+            gl->DeleteVertexArrays(1, &vao);
+            if(mImpl->mProgramVAOCurrentState == vao)
+            {
+              mImpl->mProgramVAOCurrentState = 0u;
+            }
+          }
+          mImpl->mProgramVAOMap.erase(iter);
+        }
+      }
+    }
+  }
 }
 
 void Context::PrepareForNativeRendering()