Merge "Fixed an issue the triple tap did not work." into devel/master
[platform/core/uifw/dali-core.git] / dali / internal / render / shaders / program.cpp
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/render/shaders/program.h>
20
21 // EXTERNAL INCLUDES
22 #include <cstring>
23 #include <map>
24
25 // INTERNAL INCLUDES
26 #include <dali/devel-api/common/hash.h>
27 #include <dali/graphics-api/graphics-controller.h>
28 #include <dali/graphics-api/graphics-program.h>
29 #include <dali/graphics-api/graphics-reflection.h>
30 #include <dali/integration-api/debug.h>
31 #include <dali/integration-api/gl-defines.h>
32 #include <dali/internal/common/shader-data.h>
33 #include <dali/internal/render/common/performance-monitor.h>
34 #include <dali/internal/render/shaders/program-cache.h>
35 #include <dali/public-api/common/constants.h>
36 #include <dali/public-api/common/dali-common.h>
37 #include <dali/public-api/common/dali-vector.h>
38
39 namespace Dali
40 {
41 namespace Internal
42 {
43 // LOCAL STUFF
44 namespace
45 {
46 const unsigned int NUMBER_OF_DEFAULT_UNIFORMS = static_cast<unsigned int>(Program::DefaultUniformIndex::COUNT);
47
48 /**
49  * List of all default uniforms used for quicker lookup
50  */
51 size_t DEFAULT_UNIFORM_HASHTABLE[NUMBER_OF_DEFAULT_UNIFORMS] =
52   {
53     CalculateHash(std::string("uModelMatrix")),
54     CalculateHash(std::string("uMvpMatrix")),
55     CalculateHash(std::string("uViewMatrix")),
56     CalculateHash(std::string("uModelView")),
57     CalculateHash(std::string("uNormalMatrix")),
58     CalculateHash(std::string("uProjection")),
59     CalculateHash(std::string("uSize")),
60     CalculateHash(std::string("uColor"))};
61
62 } // namespace
63
64 // IMPLEMENTATION
65
66 Program* Program::New(ProgramCache& cache, Internal::ShaderDataPtr shaderData, Graphics::Controller& gfxController, Graphics::UniquePtr<Graphics::Program>&& gfxProgram)
67 {
68   uint32_t programId{0u};
69
70   // Get program id and use it as hash for the cache
71   // in order to maintain current functionality as long as needed
72   gfxController.GetProgramParameter(*gfxProgram, 1, &programId);
73
74   size_t shaderHash = programId;
75
76   Program* program = cache.GetProgram(shaderHash);
77
78   if(nullptr == program)
79   {
80     // program not found so create it
81     program = new Program(cache, shaderData, gfxController, std::move(gfxProgram));
82     cache.AddProgram(shaderHash, program);
83   }
84
85   return program;
86 }
87
88 Program::Program(ProgramCache& cache, Internal::ShaderDataPtr shaderData, Graphics::Controller& controller, Graphics::UniquePtr<Graphics::Program>&& gfxProgram)
89 : mCache(cache),
90   mProjectionMatrix(nullptr),
91   mViewMatrix(nullptr),
92   mGfxProgram(std::move(gfxProgram)),
93   mGfxController(controller),
94   mProgramData(shaderData)
95 {
96   BuildReflection(controller.GetProgramReflection(*mGfxProgram.get()));
97 }
98
99 Program::~Program() = default;
100
101 void Program::BuildReflection(const Graphics::Reflection& graphicsReflection)
102 {
103   mReflectionDefaultUniforms.clear();
104   mReflectionDefaultUniforms.resize(NUMBER_OF_DEFAULT_UNIFORMS);
105
106   auto uniformBlockCount = graphicsReflection.GetUniformBlockCount();
107
108   // add uniform block fields
109   for(auto i = 0u; i < uniformBlockCount; ++i)
110   {
111     Graphics::UniformBlockInfo uboInfo;
112     graphicsReflection.GetUniformBlock(i, uboInfo);
113
114     // for each member store data
115     for(const auto& item : uboInfo.members)
116     {
117       auto hashValue = CalculateHash(item.name);
118       mReflection.emplace_back(ReflectionUniformInfo{hashValue, false, item});
119
120       // update buffer index
121       mReflection.back().uniformInfo.bufferIndex = i;
122
123       // Update default uniforms
124       for(auto j = 0u; j < NUMBER_OF_DEFAULT_UNIFORMS; ++j)
125       {
126         if(hashValue == DEFAULT_UNIFORM_HASHTABLE[j])
127         {
128           mReflectionDefaultUniforms[j] = mReflection.back();
129           break;
130         }
131       }
132     }
133   }
134
135   // add samplers
136   auto samplers = graphicsReflection.GetSamplers();
137   for(const auto& sampler : samplers)
138   {
139     mReflection.emplace_back(ReflectionUniformInfo{CalculateHash(sampler.name), false, sampler});
140   }
141
142   // check for potential collisions
143   std::map<size_t, bool> hashTest;
144   bool                   hasCollisions(false);
145   for(auto&& item : mReflection)
146   {
147     if(hashTest.find(item.hashValue) == hashTest.end())
148     {
149       hashTest[item.hashValue] = false;
150     }
151     else
152     {
153       hashTest[item.hashValue] = true;
154       hasCollisions            = true;
155     }
156   }
157
158   // update collision flag for further use
159   if(hasCollisions)
160   {
161     for(auto&& item : mReflection)
162     {
163       item.hasCollision = hashTest[item.hashValue];
164     }
165   }
166 }
167
168 bool Program::GetUniform(const std::string& name, size_t hashedName, Graphics::UniformInfo& out) const
169 {
170   if(mReflection.empty())
171   {
172     return false;
173   }
174
175   hashedName = !hashedName ? CalculateHash(name, '[') : hashedName;
176
177   for(const ReflectionUniformInfo& item : mReflection)
178   {
179     if(item.hashValue == hashedName)
180     {
181       if(!item.hasCollision || item.uniformInfo.name == name)
182       {
183         out = item.uniformInfo;
184         return true;
185       }
186       else
187       {
188         return false;
189       }
190     }
191   }
192   return false;
193 }
194
195 const Graphics::UniformInfo* Program::GetDefaultUniform(DefaultUniformIndex defaultUniformIndex) const
196 {
197   if(mReflectionDefaultUniforms.empty())
198   {
199     return nullptr;
200   }
201
202   const auto value = &mReflectionDefaultUniforms[static_cast<uint32_t>(defaultUniformIndex)];
203   return &value->uniformInfo;
204 }
205
206 } // namespace Internal
207
208 } // namespace Dali