[Tizen] Change VAO hash value function
[platform/core/uifw/dali-adaptor.git] / dali / internal / graphics / gles-impl / gles-context.cpp
index c6f0728..ef80683 100644 (file)
@@ -60,11 +60,26 @@ struct Context::Impl
     std::size_t hash = 0;
     for(const auto& attr : vertexInputState.attributes)
     {
-      hash ^= std::hash<uint32_t>{}(attr.location);
+      // Make unordered hash value by location.
+      // Note : This hash function varified for locations only under < 20.
+      std::size_t salt = attr.location + 1;
+      hash += salt << (sizeof(std::size_t) * 6);
+      salt *= salt;
+      salt ^= attr.location;
+      hash += salt << (sizeof(std::size_t) * 4);
+      salt *= salt;
+      hash += salt;
     }
 
-    auto& gl   = *mController.GetGL();
-    auto  iter = mProgramVAOMap.find(program);
+    auto& gl = *mController.GetGL();
+
+    if(DALI_UNLIKELY(!mDiscardedVAOList.empty()))
+    {
+      gl.DeleteVertexArrays(static_cast<Dali::GLsizei>(mDiscardedVAOList.size()), mDiscardedVAOList.data());
+      mDiscardedVAOList.clear();
+    }
+
+    auto iter = mProgramVAOMap.find(program);
     if(iter != mProgramVAOMap.end())
     {
       auto attributeIter = iter->second.find(hash);
@@ -228,6 +243,7 @@ struct Context::Impl
   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
+  std::vector<Dali::GLuint>                                                     mDiscardedVAOList{};
 
   bool mGlContextCreated{false}; ///< True if the OpenGL context has been created
 
@@ -305,31 +321,42 @@ void Context::Flush(bool reset, const GLES::DrawCallDescriptor& drawCall, GLES::
   // Map binding# to sampler location
   const auto& reflection = !newProgram ? currentProgram->GetReflection() : newProgram->GetReflection();
   const auto& samplers   = reflection.GetSamplers();
+
+  uint32_t currentSampler = 0;
+  uint32_t currentElement = 0;
+
+  // @warning Assume that binding.binding is strictly linear in the same order as mCurrentTextureBindings
+  // elements. This avoids having to sort the bindings.
   for(const auto& binding : mImpl->mCurrentTextureBindings)
   {
+    if(currentSampler >= samplers.size())
+    {
+      // Don't bind more textures than there are active samplers.
+      break;
+    }
+
     auto texture = const_cast<GLES::Texture*>(static_cast<const GLES::Texture*>(binding.texture));
 
     // Texture may not have been initialized yet...(tbm_surface timing issue?)
     if(!texture->GetGLTexture())
     {
-      // Attempt to reinitialize
-      // @todo need to put this somewhere else where it isn't const.
-      // Maybe post it back on end of initialize queue if initialization fails?
       texture->InitializeResource();
     }
 
     // Warning, this may cause glWaitSync to occur on the GPU.
     dependencyChecker.CheckNeedsSync(this, texture);
-
     texture->Bind(binding);
-
-    texture->Prepare(); // @todo also non-const.
-
-    if(binding.binding < samplers.size()) // binding maps to texture unit. (texture bindings should also be in binding order)
+    texture->Prepare();
+
+    // @warning Assume that location of array elements is sequential.
+    // @warning GL does not guarantee this, but in practice, it is.
+    gl.Uniform1i(samplers[currentSampler].location + currentElement,
+                 samplers[currentSampler].offset + currentElement);
+    ++currentElement;
+    if(currentElement >= samplers[currentSampler].elementCount)
     {
-      // Offset is set to the lexical offset within the frag shader, map it to the texture unit
-      // @todo Explicitly set the texture unit through the graphics interface
-      gl.Uniform1i(samplers[binding.binding].location, samplers[binding.binding].offset);
+      ++currentSampler;
+      currentElement = 0;
     }
   }
 
@@ -746,6 +773,11 @@ void Context::EndRenderPass(GLES::TextureDependencyChecker& dependencyChecker)
       auto& gl = *mImpl->mController.GetGL();
       gl.Flush();
 
+      if(framebuffer->CaptureRequested())
+      {
+        framebuffer->DrawRenderedBuffer();
+      }
+
       /* @todo Full dependency checking would need to store textures in Begin, and create
        * fence objects here; but we're going to draw all fbos on shared context in serial,
        * so no real need (yet). Might want to consider ensuring order of render passes,
@@ -1063,12 +1095,18 @@ void Context::InvalidateCachedPipeline(GLES::Pipeline* pipeline)
           for(auto& attributeHashPair : iter->second)
           {
             auto vao = attributeHashPair.second;
-            gl->DeleteVertexArrays(1, &vao);
+
+            // Do not delete vao now. (Since Context might not be current.)
+            mImpl->mDiscardedVAOList.emplace_back(vao);
             if(mImpl->mProgramVAOCurrentState == vao)
             {
               mImpl->mProgramVAOCurrentState = 0u;
             }
           }
+
+          // Clear cached Vertex buffer.
+          mImpl->mCurrentVertexBufferBindings.clear();
+
           mImpl->mProgramVAOMap.erase(iter);
         }
       }