Merge "Add APIs for intercepting http request in web engine." into devel/master
[platform/core/uifw/dali-adaptor.git] / dali / internal / graphics / gles-impl / gles-graphics-reflection.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 #include "gles-graphics-reflection.h"
19 #include <dali/integration-api/gl-abstraction.h>
20 #include <dali/integration-api/gl-defines.h>
21
22 #include <vector>
23 #include "egl-graphics-controller.h"
24
25 #include <GLES3/gl3.h>
26 #include <GLES3/gl31.h>
27
28 #include "gles-graphics-program.h"
29
30 #include <iostream>
31
32 namespace
33 {
34 Dali::Graphics::VertexInputAttributeFormat GetVertexAttributeTypeFormat(GLenum type)
35 {
36   switch(type)
37   {
38     case GL_FLOAT:
39       return Dali::Graphics::VertexInputAttributeFormat::FLOAT;
40     case GL_FLOAT_VEC2:
41       return Dali::Graphics::VertexInputAttributeFormat::VEC2;
42     case GL_FLOAT_VEC3:
43       return Dali::Graphics::VertexInputAttributeFormat::VEC3;
44     case GL_FLOAT_VEC4:
45       return Dali::Graphics::VertexInputAttributeFormat::VEC4;
46     case GL_INT:
47       return Dali::Graphics::VertexInputAttributeFormat::INTEGER;
48     default:
49       return Dali::Graphics::VertexInputAttributeFormat::UNDEFINED;
50   }
51 }
52
53 uint32_t GetGLDataTypeSize(GLenum type)
54 {
55   // There are many more types than what are covered here, but
56   // they are not supported in dali.
57   switch(type)
58   {
59     case GL_FLOAT: // "float", 1 float, 4 bytes
60       return 4;
61     case GL_FLOAT_VEC2: // "vec2", 2 floats, 8 bytes
62       return 8;
63     case GL_FLOAT_VEC3: // "vec3", 3 floats, 12 bytes
64       return 12;
65     case GL_FLOAT_VEC4: // "vec4", 4 floats, 16 bytes
66       return 16;
67     case GL_INT: // "int", 1 integer, 4 bytes
68       return 4;
69     case GL_FLOAT_MAT2: // "mat2", 4 floats, 16 bytes
70       return 16;
71     case GL_FLOAT_MAT3: // "mat3", 3 vec3, 36 bytes
72       return 36;
73     case GL_FLOAT_MAT4: // "mat4", 4 vec4, 64 bytes
74       return 64;
75     default:
76       return 0;
77   }
78 }
79
80 bool IsSampler(GLenum type)
81 {
82   return type == GL_SAMPLER_2D || type == GL_SAMPLER_3D || type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES;
83 }
84
85 bool SortUniformInfoByLocation(Dali::Graphics::UniformInfo a, Dali::Graphics::UniformInfo b)
86 {
87   return a.location < b.location;
88 }
89
90 bool SortUniformExtraInfoByLocation(Dali::Graphics::GLES::Reflection::UniformExtraInfo a, Dali::Graphics::GLES::Reflection::UniformExtraInfo b)
91 {
92   return a.location < b.location;
93 }
94
95 } // namespace
96
97 namespace Dali::Graphics::GLES
98 {
99 Reflection::Reflection(GLES::ProgramImpl& program, Graphics::EglGraphicsController& controller)
100 : Graphics::Reflection(),
101   mController(controller),
102   mProgram(program)
103 {
104 }
105
106 Reflection::~Reflection() = default;
107
108 void Reflection::BuildVertexAttributeReflection()
109 {
110   auto glProgram = mProgram.GetGlProgram();
111
112   int    written, size, location, maxLength, nAttribs;
113   GLenum type;
114   char*  name;
115
116   auto gl = mController.GetGL();
117
118   gl->GetProgramiv(glProgram, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxLength);
119   gl->GetProgramiv(glProgram, GL_ACTIVE_ATTRIBUTES, &nAttribs);
120
121   mVertexInputAttributes.clear();
122   mVertexInputAttributes.resize(nAttribs);
123
124   name = new GLchar[maxLength];
125   for(int i = 0; i < nAttribs; i++)
126   {
127     gl->GetActiveAttrib(glProgram, i, maxLength, &written, &size, &type, name);
128     location = gl->GetAttribLocation(glProgram, name);
129
130     if(location >= 0)
131     {
132       AttributeInfo attributeInfo;
133       attributeInfo.location = location;
134       attributeInfo.name     = name;
135       attributeInfo.format   = GetVertexAttributeTypeFormat(type);
136       mVertexInputAttributes.insert(mVertexInputAttributes.begin() + location, attributeInfo);
137     }
138   }
139   delete[] name;
140 }
141
142 void Reflection::BuildUniformReflection()
143 {
144   auto glProgram = mProgram.GetGlProgram();
145
146   int   maxLen;
147   char* name;
148
149   int numUniforms = 0;
150
151   auto gl = mController.GetGL();
152
153   gl->GetProgramiv(glProgram, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLen);
154   gl->GetProgramiv(glProgram, GL_ACTIVE_UNIFORMS, &numUniforms);
155
156   mUniformBlocks.clear();
157   mDefaultUniformBlock.members.clear();
158   mUniformOpaques.clear();
159
160   name = new char[maxLen];
161
162   mStandaloneUniformExtraInfos.clear();
163
164   for(int i = 0; i < numUniforms; ++i)
165   {
166     int    elementCount;
167     GLenum type;
168     int    written;
169     gl->GetActiveUniform(glProgram, i, maxLen, &written, &elementCount, &type, name);
170     int location = gl->GetUniformLocation(glProgram, name);
171
172     Dali::Graphics::UniformInfo uniformInfo;
173
174     uniformInfo.name = name;
175     if(elementCount > 1)
176     {
177       auto iter = std::string(uniformInfo.name).find("[", 0);
178       if(iter != std::string::npos)
179       {
180         uniformInfo.name = std::string(name).substr(0, iter);
181       }
182     }
183
184     uniformInfo.uniformClass = IsSampler(type) ? Dali::Graphics::UniformClass::COMBINED_IMAGE_SAMPLER : Dali::Graphics::UniformClass::UNIFORM;
185     uniformInfo.location     = IsSampler(type) ? 0 : location;
186     uniformInfo.binding      = IsSampler(type) ? location : 0;
187     uniformInfo.bufferIndex  = 0;
188
189     if(IsSampler(type))
190     {
191       mUniformOpaques.push_back(uniformInfo);
192     }
193     else
194     {
195       mDefaultUniformBlock.members.push_back(uniformInfo);
196       mStandaloneUniformExtraInfos.emplace_back(location, GetGLDataTypeSize(type), uniformInfo.offset, elementCount, type);
197     }
198   }
199
200   // Re-order according to uniform locations.
201
202   if(mDefaultUniformBlock.members.size() > 1)
203   {
204     std::sort(mDefaultUniformBlock.members.begin(), mDefaultUniformBlock.members.end(), SortUniformInfoByLocation);
205     std::sort(mStandaloneUniformExtraInfos.begin(), mStandaloneUniformExtraInfos.end(), SortUniformExtraInfoByLocation);
206   }
207
208   if(mUniformOpaques.size() > 1)
209   {
210     std::sort(mUniformOpaques.begin(), mUniformOpaques.end(), SortUniformInfoByLocation);
211   }
212
213   // Calculate the uniform offset
214   for(unsigned int i = 0; i < mDefaultUniformBlock.members.size(); ++i)
215   {
216     if(i == 0)
217     {
218       mDefaultUniformBlock.members[i].offset = 0;
219     }
220     else
221     {
222       uint32_t previousUniformLocation = mDefaultUniformBlock.members[i - 1].location;
223       auto     previousUniform         = std::find_if(mStandaloneUniformExtraInfos.begin(), mStandaloneUniformExtraInfos.end(), [&previousUniformLocation](const UniformExtraInfo& iter) { return iter.location == previousUniformLocation; });
224       if(previousUniform != mStandaloneUniformExtraInfos.end())
225       {
226         mDefaultUniformBlock.members[i].offset = mDefaultUniformBlock.members[i - 1].offset + (previousUniform->size * previousUniform->arraySize);
227         mStandaloneUniformExtraInfos[i].offset = mDefaultUniformBlock.members[i].offset;
228       }
229     }
230   }
231
232   if(mDefaultUniformBlock.members.size() > 0)
233   {
234     uint32_t lastUniformLocation = mDefaultUniformBlock.members.back().location;
235     auto     lastUniform         = std::find_if(mStandaloneUniformExtraInfos.begin(), mStandaloneUniformExtraInfos.end(), [&lastUniformLocation](const UniformExtraInfo& iter) { return iter.location == lastUniformLocation; });
236     if(lastUniform != mStandaloneUniformExtraInfos.end())
237     {
238       mDefaultUniformBlock.size = mDefaultUniformBlock.members.back().offset + (lastUniform->size * lastUniform->arraySize);
239       mUniformBlocks.push_back(mDefaultUniformBlock);
240     }
241   }
242   else
243   {
244     mDefaultUniformBlock.size = 0;
245   }
246
247   delete[] name;
248 }
249
250 // TODO: Maybe this is not needed if uniform block is not support by dali shaders?
251 void Reflection::BuildUniformBlockReflection()
252 {
253   auto gl               = mController.GetGL();
254   auto glProgram        = mProgram.GetGlProgram();
255   int  numUniformBlocks = 0;
256   gl->GetProgramiv(glProgram, GL_ACTIVE_UNIFORM_BLOCKS, &numUniformBlocks);
257
258   mUniformBlocks.clear();
259   mUniformBlocks.resize(numUniformBlocks);
260
261   int uniformBlockMaxLength = 0;
262   gl->GetProgramiv(glProgram, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &uniformBlockMaxLength);
263
264   char* uniformBlockName = new char[uniformBlockMaxLength];
265   for(int i = 0; i < numUniformBlocks; i++)
266   {
267     int length;
268     int blockBinding;
269     int blockDataSize;
270     gl->GetActiveUniformBlockName(glProgram, i, uniformBlockMaxLength, &length, uniformBlockName);
271     gl->GetActiveUniformBlockiv(glProgram, i, GL_UNIFORM_BLOCK_BINDING, &blockBinding);
272     gl->GetActiveUniformBlockiv(glProgram, i, GL_UNIFORM_BLOCK_DATA_SIZE, &blockDataSize);
273
274     Dali::Graphics::UniformBlockInfo uniformBlockInfo;
275     uniformBlockInfo.name    = uniformBlockName;
276     uniformBlockInfo.size    = blockDataSize;
277     uniformBlockInfo.binding = blockBinding;
278
279     int nUnis;
280     gl->GetActiveUniformBlockiv(glProgram, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &nUnis);
281     int* unifIndexes = new GLint[nUnis];
282     gl->GetActiveUniformBlockiv(glProgram, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, unifIndexes);
283     char* uniformName{};
284     int   maxUniLen;
285     gl->GetProgramiv(glProgram, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniLen);
286
287     for(int unif = 0; unif < nUnis; ++unif)
288     {
289       int    uniIndex = unifIndexes[unif];
290       int    size;
291       GLenum type;
292
293       gl->GetActiveUniform(glProgram, uniIndex, maxUniLen, &length, &size, &type, uniformName);
294       int location = gl->GetUniformLocation(glProgram, uniformName);
295
296       Dali::Graphics::UniformInfo uniform;
297       uniform.name     = uniformName;
298       uniform.location = location;
299       uniformBlockInfo.members.push_back(uniform);
300     }
301
302     delete[] unifIndexes;
303
304     mUniformBlocks.push_back(uniformBlockInfo);
305   }
306   delete[] uniformBlockName;
307 }
308
309 uint32_t Reflection::GetVertexAttributeLocation(const std::string& name) const
310 {
311   for(auto&& attr : mVertexInputAttributes)
312   {
313     if(attr.name == name)
314     {
315       return attr.location;
316     }
317   }
318   return ERROR_ATTRIBUTE_NOT_FOUND;
319 }
320
321 Dali::Graphics::VertexInputAttributeFormat Reflection::GetVertexAttributeFormat(uint32_t location) const
322 {
323   if(location >= mVertexInputAttributes.size())
324   {
325     return Dali::Graphics::VertexInputAttributeFormat::UNDEFINED;
326   }
327
328   return mVertexInputAttributes[location].format;
329 }
330
331 std::string Reflection::GetVertexAttributeName(uint32_t location) const
332 {
333   if(location >= mVertexInputAttributes.size())
334   {
335     return std::string();
336   }
337
338   return mVertexInputAttributes[location].name;
339 }
340
341 std::vector<uint32_t> Reflection::GetVertexAttributeLocations() const
342 {
343   std::vector<uint32_t> locations;
344   for(auto&& attr : mVertexInputAttributes)
345   {
346     if(attr.format != Dali::Graphics::VertexInputAttributeFormat::UNDEFINED)
347     {
348       locations.push_back(attr.location);
349     }
350   }
351
352   return locations;
353 }
354
355 uint32_t Reflection::GetUniformBlockCount() const
356 {
357   return mUniformBlocks.size();
358 }
359
360 uint32_t Reflection::GetUniformBlockBinding(uint32_t index) const
361 {
362   return index < mUniformBlocks.size() ? mUniformBlocks[index].binding : 0u;
363 }
364
365 uint32_t Reflection::GetUniformBlockSize(uint32_t index) const
366 {
367   return index < mUniformBlocks.size() ? mUniformBlocks[index].size : 0u;
368 }
369
370 bool Reflection::GetUniformBlock(uint32_t index, Dali::Graphics::UniformBlockInfo& out) const
371 {
372   if(index >= mUniformBlocks.size())
373   {
374     return false;
375   }
376
377   const auto& block = mUniformBlocks[index];
378
379   out.name          = block.name;
380   out.binding       = block.binding;
381   out.descriptorSet = block.descriptorSet;
382   auto membersSize  = block.members.size();
383   out.members.resize(membersSize);
384   out.size = block.size;
385   for(auto i = 0u; i < out.members.size(); ++i)
386   {
387     const auto& memberUniform   = block.members[i];
388     out.members[i].name         = memberUniform.name;
389     out.members[i].binding      = block.binding;
390     out.members[i].uniformClass = Graphics::UniformClass::UNIFORM;
391     out.members[i].offset       = memberUniform.offset;
392     out.members[i].location     = memberUniform.location;
393   }
394
395   return true;
396 }
397
398 std::vector<uint32_t> Reflection::GetUniformBlockLocations() const
399 {
400   std::vector<uint32_t> retval{};
401   for(auto&& ubo : mUniformBlocks)
402   {
403     retval.emplace_back(ubo.binding);
404   }
405   return retval;
406 }
407
408 std::string Reflection::GetUniformBlockName(uint32_t blockIndex) const
409 {
410   if(blockIndex < mUniformBlocks.size())
411   {
412     return mUniformBlocks[blockIndex].name;
413   }
414   else
415   {
416     return std::string();
417   }
418 }
419
420 uint32_t Reflection::GetUniformBlockMemberCount(uint32_t blockIndex) const
421 {
422   if(blockIndex < mUniformBlocks.size())
423   {
424     return static_cast<uint32_t>(mUniformBlocks[blockIndex].members.size());
425   }
426   else
427   {
428     return 0u;
429   }
430 }
431
432 std::string Reflection::GetUniformBlockMemberName(uint32_t blockIndex, uint32_t memberLocation) const
433 {
434   if(blockIndex < mUniformBlocks.size() && memberLocation < mUniformBlocks[blockIndex].members.size())
435   {
436     return mUniformBlocks[blockIndex].members[memberLocation].name;
437   }
438   else
439   {
440     return std::string();
441   }
442 }
443
444 uint32_t Reflection::GetUniformBlockMemberOffset(uint32_t blockIndex, uint32_t memberLocation) const
445 {
446   if(blockIndex < mUniformBlocks.size() && memberLocation < mUniformBlocks[blockIndex].members.size())
447   {
448     return mUniformBlocks[blockIndex].members[memberLocation].offset;
449   }
450   else
451   {
452     return 0u;
453   }
454 }
455
456 bool Reflection::GetNamedUniform(const std::string& name, Dali::Graphics::UniformInfo& out) const
457 {
458   auto index = 0u;
459   for(auto&& ubo : mUniformBlocks)
460   {
461     for(auto&& member : ubo.members)
462     {
463       if(name == member.name || name == (ubo.name + "." + member.name))
464       {
465         out.name         = name;
466         out.location     = member.location;
467         out.binding      = ubo.binding;
468         out.bufferIndex  = index;
469         out.offset       = member.offset;
470         out.uniformClass = Graphics::UniformClass::UNIFORM;
471         return true;
472       }
473     }
474     index++;
475   }
476
477   // check samplers
478   for(auto&& uniform : mUniformOpaques)
479   {
480     if(uniform.name == name)
481     {
482       out.uniformClass = Graphics::UniformClass::COMBINED_IMAGE_SAMPLER;
483       out.binding      = uniform.binding;
484       out.name         = name;
485       out.offset       = 0;
486       out.location     = uniform.location;
487       return true;
488     }
489   }
490
491   return false;
492 }
493
494 std::vector<GLenum> Reflection::GetStandaloneUniformTypes() const
495 {
496   std::vector<GLenum> retval{};
497   for(auto&& uniform : mStandaloneUniformExtraInfos)
498   {
499     retval.emplace_back(uniform.type);
500   }
501
502   return retval;
503 }
504
505 const std::vector<Reflection::UniformExtraInfo>& Reflection::GetStandaloneUniformExtraInfo() const
506 {
507   return mStandaloneUniformExtraInfos;
508 }
509
510 std::vector<Dali::Graphics::UniformInfo> Reflection::GetSamplers() const
511 {
512   return mUniformOpaques;
513 }
514
515 Graphics::ShaderLanguage Reflection::GetLanguage() const
516 {
517   auto gl = mController.GetGL();
518
519   int majorVersion, minorVersion;
520   gl->GetIntegerv(GL_MAJOR_VERSION, &majorVersion);
521   gl->GetIntegerv(GL_MINOR_VERSION, &minorVersion);
522   printf("GL Version (integer) : %d.%d\n", majorVersion, minorVersion);
523   printf("GLSL Version : %s\n", gl->GetString(GL_SHADING_LANGUAGE_VERSION));
524
525   // TODO: the language version is hardcoded for now, but we may use what we get
526   // from GL_SHADING_LANGUAGE_VERSION?
527   return Graphics::ShaderLanguage::GLSL_3_2;
528 }
529
530 } // namespace Dali::Graphics::GLES