Merge "Add APIs of webview back forward list" into devel/master
[platform/core/uifw/dali-adaptor.git] / dali / internal / graphics / gles-impl / gles-context.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-context.h"
19 #include <dali/integration-api/gl-abstraction.h>
20 #include <dali/integration-api/gl-defines.h>
21 #include "egl-graphics-controller.h"
22 #include "gles-graphics-buffer.h"
23 #include "gles-graphics-pipeline.h"
24 #include "gles-graphics-program.h"
25
26 namespace Dali::Graphics::GLES
27 {
28 struct Context::Impl
29 {
30   Impl(EglGraphicsController& controller)
31   : mController(controller)
32   {
33   }
34
35   ~Impl() = default;
36
37   EglGraphicsController& mController;
38
39   const GLES::Pipeline* mCurrentPipeline{nullptr}; ///< Currently bound pipeline
40   const GLES::Pipeline* mNewPipeline{nullptr};     ///< New pipeline to be set on flush
41
42   std::vector<Graphics::TextureBinding> mCurrentTextureBindings{};
43   std::vector<Graphics::SamplerBinding> mCurrentSamplerBindings{};
44   GLES::IndexBufferBindingDescriptor    mCurrentIndexBufferBinding{};
45
46   struct VertexBufferBinding
47   {
48     GLES::Buffer* buffer{nullptr};
49     uint32_t      offset{0u};
50   };
51
52   // Currently bound buffers
53   std::vector<VertexBufferBindingDescriptor> mCurrentVertexBufferBindings{};
54
55   // Currently bound UBOs (check if it's needed per program!)
56   std::vector<UniformBufferBindingDescriptor> mCurrentUBOBindings{};
57   UniformBufferBindingDescriptor              mCurrentStandaloneUBOBinding{};
58 };
59
60 Context::Context(EglGraphicsController& controller)
61 {
62   mImpl = std::make_unique<Impl>(controller);
63 }
64
65 Context::~Context() = default;
66
67 void Context::Flush(bool reset, const GLES::DrawCallDescriptor& drawCall)
68 {
69   auto& gl = *mImpl->mController.GetGL();
70
71   // Change pipeline
72   if(mImpl->mNewPipeline)
73   {
74     // Execute states if different
75     mImpl->mCurrentPipeline = mImpl->mNewPipeline;
76     mImpl->mNewPipeline     = nullptr;
77   }
78   mImpl->mCurrentPipeline->GetPipeline().Bind(nullptr);
79
80   // Blend state
81   ResolveBlendState();
82
83   // Resolve rasterization state
84   ResolveRasterizationState();
85
86   // Resolve uniform buffers
87   ResolveUniformBuffers();
88
89   // Bind textures
90   for(const auto& binding : mImpl->mCurrentTextureBindings)
91   {
92     auto texture = const_cast<GLES::Texture*>(static_cast<const GLES::Texture*>(binding.texture));
93
94     // Texture may not have been initialized yet...(tbm_surface timing issue?)
95     if(!texture->GetGLTexture())
96     {
97       // Attempt to reinitialize
98       // @todo need to put this somewhere else where it isn't const.
99       // Maybe post it back on end of initialize queue if initialization fails?
100       texture->InitializeResource();
101     }
102
103     texture->Bind(binding);
104     texture->Prepare(); // @todo also non-const.
105   }
106
107   // for each attribute bind vertices
108   const auto& pipelineState = mImpl->mCurrentPipeline->GetCreateInfo();
109   const auto& vi            = pipelineState.vertexInputState;
110   for(const auto& attr : vi->attributes)
111   {
112     // Enable location
113     gl.EnableVertexAttribArray(attr.location);
114     const auto& bufferSlot    = mImpl->mCurrentVertexBufferBindings[attr.binding];
115     const auto& bufferBinding = vi->bufferBindings[attr.binding];
116
117     auto glesBuffer = bufferSlot.buffer->GetGLBuffer();
118
119     // Bind buffer
120     gl.BindBuffer(GL_ARRAY_BUFFER, glesBuffer);
121     gl.VertexAttribPointer(attr.location,
122                            GLVertexFormat(attr.format).size,
123                            GLVertexFormat(attr.format).format,
124                            GL_FALSE,
125                            bufferBinding.stride,
126                            reinterpret_cast<void*>(attr.offset));
127   }
128
129   // Resolve topology
130   const auto& ia = mImpl->mCurrentPipeline->GetCreateInfo().inputAssemblyState;
131
132   // Bind uniforms
133
134   // Resolve draw call
135   switch(drawCall.type)
136   {
137     case DrawCallDescriptor::Type::DRAW:
138     {
139       gl.DrawArrays(GLESTopology(ia->topology),
140                     drawCall.draw.firstVertex,
141                     drawCall.draw.vertexCount);
142       break;
143     }
144     case DrawCallDescriptor::Type::DRAW_INDEXED:
145     {
146       const auto& binding    = mImpl->mCurrentIndexBufferBinding;
147       const auto* glesBuffer = binding.buffer;
148       gl.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, glesBuffer->GetGLBuffer());
149       auto indexBufferFormat = GLIndexFormat(binding.format).format;
150       gl.DrawElements(GLESTopology(ia->topology),
151                       drawCall.drawIndexed.indexCount,
152                       indexBufferFormat,
153                       reinterpret_cast<void*>(binding.offset));
154       break;
155     }
156     case DrawCallDescriptor::Type::DRAW_INDEXED_INDIRECT:
157     {
158       break;
159     }
160   }
161
162   ClearState();
163 }
164
165 void Context::BindTextures(const std::vector<Graphics::TextureBinding>& bindings)
166 {
167   // for each texture allocate slot
168   for(const auto& binding : bindings)
169   {
170     // Resize binding array if needed
171     if(mImpl->mCurrentTextureBindings.size() <= binding.binding)
172     {
173       mImpl->mCurrentTextureBindings.resize(binding.binding + 1);
174     }
175     // Store the binding details
176     mImpl->mCurrentTextureBindings[binding.binding] = binding;
177   }
178 }
179
180 void Context::BindVertexBuffers(const std::vector<GLES::VertexBufferBindingDescriptor>& bindings)
181 {
182   if(bindings.size() > mImpl->mCurrentVertexBufferBindings.size())
183   {
184     mImpl->mCurrentVertexBufferBindings.resize(bindings.size());
185   }
186   // Copy only set slots
187   std::copy_if(bindings.begin(), bindings.end(), mImpl->mCurrentVertexBufferBindings.begin(), [](auto& item) {
188     return (nullptr != item.buffer);
189   });
190 }
191
192 void Context::BindIndexBuffer(const IndexBufferBindingDescriptor& indexBufferBinding)
193 {
194   mImpl->mCurrentIndexBufferBinding = indexBufferBinding;
195 }
196
197 void Context::BindPipeline(const GLES::Pipeline* newPipeline)
198 {
199   mImpl->mNewPipeline = newPipeline;
200 }
201
202 void Context::BindUniformBuffers(const std::vector<UniformBufferBindingDescriptor>& uboBindings,
203                                  const UniformBufferBindingDescriptor&              standaloneBindings)
204 {
205   if(standaloneBindings.buffer)
206   {
207     mImpl->mCurrentStandaloneUBOBinding = standaloneBindings;
208   }
209
210   if(uboBindings.size() >= mImpl->mCurrentUBOBindings.size())
211   {
212     mImpl->mCurrentUBOBindings.resize(uboBindings.size() + 1);
213   }
214
215   auto it = uboBindings.begin();
216   for(auto i = 0u; i < uboBindings.size(); ++i)
217   {
218     if(it->buffer)
219     {
220       mImpl->mCurrentUBOBindings[i] = *it;
221     }
222   }
223 }
224
225 void Context::ResolveBlendState()
226 {
227   const auto& state = mImpl->mCurrentPipeline->GetCreateInfo();
228   const auto& bs    = state.colorBlendState;
229   auto&       gl    = *mImpl->mController.GetGL();
230
231   // TODO: prevent leaking the state
232   if(!bs)
233   {
234     return;
235   }
236
237   bs->blendEnable ? gl.Enable(GL_BLEND) : gl.Disable(GL_BLEND);
238   if(!bs->blendEnable)
239   {
240     return;
241   }
242
243   gl.BlendFunc(GLBlendFunc(bs->srcColorBlendFactor), GLBlendFunc(bs->dstColorBlendFactor));
244
245   if((GLBlendFunc(bs->srcColorBlendFactor) == GLBlendFunc(bs->srcAlphaBlendFactor)) &&
246      (GLBlendFunc(bs->dstColorBlendFactor) == GLBlendFunc(bs->dstAlphaBlendFactor)))
247   {
248     gl.BlendFunc(GLBlendFunc(bs->srcColorBlendFactor), GLBlendFunc(bs->dstColorBlendFactor));
249   }
250   else
251   {
252     gl.BlendFuncSeparate(GLBlendFunc(bs->srcColorBlendFactor),
253                          GLBlendFunc(bs->dstColorBlendFactor),
254                          GLBlendFunc(bs->srcAlphaBlendFactor),
255                          GLBlendFunc(bs->dstAlphaBlendFactor));
256   }
257   if(GLBlendOp(bs->colorBlendOp) == GLBlendOp(bs->alphaBlendOp))
258   {
259     gl.BlendEquation(GLBlendOp(bs->colorBlendOp));
260   }
261   else
262   {
263     gl.BlendEquationSeparate(GLBlendOp(bs->colorBlendOp), GLBlendOp(bs->alphaBlendOp));
264   }
265 }
266
267 void Context::ResolveRasterizationState()
268 {
269   const auto& state = mImpl->mCurrentPipeline->GetCreateInfo();
270   const auto& rs    = state.rasterizationState;
271   auto&       gl    = *mImpl->mController.GetGL();
272
273   // TODO: prevent leaking the state
274   if(!rs)
275   {
276     return;
277   }
278
279   if(rs->cullMode == CullMode::NONE)
280   {
281     gl.Disable(GL_CULL_FACE);
282   }
283   else
284   {
285     gl.Enable(GL_CULL_FACE);
286     gl.CullFace(GLCullMode(rs->cullMode));
287   }
288
289   // TODO: implement polygon mode (fill, line, points)
290   //       seems like we don't support it (no glPolygonMode())
291 }
292
293 void Context::ResolveUniformBuffers()
294 {
295   // Resolve standalone uniforms if we have binding
296   if(mImpl->mCurrentStandaloneUBOBinding.buffer)
297   {
298     ResolveStandaloneUniforms();
299   }
300 }
301
302 void Context::ResolveStandaloneUniforms()
303 {
304   auto& gl = *mImpl->mController.GetGL();
305
306   // Find reflection for program
307   const auto program = static_cast<const GLES::Program*>(mImpl->mCurrentPipeline->GetCreateInfo().programState->program);
308
309   const auto& reflection = program->GetReflection();
310
311   auto extraInfos = reflection.GetStandaloneUniformExtraInfo();
312
313   const auto ptr = reinterpret_cast<const char*>(mImpl->mCurrentStandaloneUBOBinding.buffer->GetCPUAllocatedAddress());
314
315   for(const auto& info : extraInfos)
316   {
317     auto type   = GLTypeConversion(info.type).type;
318     auto offset = info.offset;
319     switch(type)
320     {
321       case GLType::FLOAT_VEC2:
322       {
323         gl.Uniform2fv(info.location, info.arraySize, reinterpret_cast<const float*>(&ptr[offset]));
324         break;
325       }
326       case GLType::FLOAT_VEC3:
327       {
328         gl.Uniform3fv(info.location, info.arraySize, reinterpret_cast<const float*>(&ptr[offset]));
329         break;
330       }
331       case GLType::FLOAT_VEC4:
332       {
333         gl.Uniform4fv(info.location, info.arraySize, reinterpret_cast<const float*>(&ptr[offset]));
334         break;
335       }
336       case GLType::INT_VEC2:
337       {
338         gl.Uniform2iv(info.location, info.arraySize, reinterpret_cast<const GLint*>(&ptr[offset]));
339         break;
340       }
341       case GLType::INT_VEC3:
342       {
343         gl.Uniform3iv(info.location, info.arraySize, reinterpret_cast<const GLint*>(&ptr[offset]));
344         break;
345       }
346       case GLType::INT_VEC4:
347       {
348         gl.Uniform4iv(info.location, info.arraySize, reinterpret_cast<const GLint*>(&ptr[offset]));
349         break;
350       }
351       case GLType::BOOL:
352       {
353         // not supported by DALi
354         break;
355       }
356       case GLType::BOOL_VEC2:
357       {
358         // not supported by DALi
359         break;
360       }
361       case GLType::BOOL_VEC3:
362       {
363         // not supported by DALi
364         break;
365       }
366       case GLType::BOOL_VEC4:
367       {
368         // not supported by DALi
369         break;
370       }
371       case GLType::FLOAT:
372       {
373         gl.Uniform1fv(info.location, info.arraySize, reinterpret_cast<const float*>(&ptr[offset]));
374         break;
375       }
376       case GLType::FLOAT_MAT2:
377       {
378         gl.UniformMatrix2fv(info.location, info.arraySize, GL_FALSE, reinterpret_cast<const float*>(&ptr[offset]));
379         break;
380       }
381       case GLType::FLOAT_MAT3:
382       {
383         gl.UniformMatrix3fv(info.location, info.arraySize, GL_FALSE, reinterpret_cast<const float*>(&ptr[offset]));
384         break;
385       }
386       case GLType::FLOAT_MAT4:
387       {
388         gl.UniformMatrix4fv(info.location, info.arraySize, GL_FALSE, reinterpret_cast<const float*>(&ptr[offset]));
389         break;
390       }
391       case GLType::SAMPLER_2D:
392       {
393         break;
394       }
395       case GLType::SAMPLER_CUBE:
396       {
397         break;
398       }
399       default:
400       {
401       }
402     }
403   }
404 }
405
406 void Context::ClearState()
407 {
408   mImpl->mCurrentTextureBindings.clear();
409 }
410
411 } // namespace Dali::Graphics::GLES