Merge "[ATSPI] Add MoveOuted interface" into devel/master
[platform/core/uifw/dali-adaptor.git] / dali / internal / graphics / gles-impl / gles-graphics-command-buffer.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 "gles-graphics-command-buffer.h"
20
21 // INTERNAL INCLUDES
22 #include "egl-graphics-controller.h"
23 #include "gles-graphics-buffer.h"
24 #include "gles-graphics-framebuffer.h"
25 #include "gles-graphics-pipeline.h"
26 #include "gles-graphics-render-pass.h"
27 #include "gles-graphics-render-target.h"
28 #include "gles-graphics-texture.h"
29
30 namespace Dali::Graphics::GLES
31 {
32 class CommandPool
33 {
34   static const uint32_t COMMAND_POOL_DEFAULT_INCREMENT = 1024 * 32; // 32kb banks
35   static const uint32_t MEMORY_POOL_DEFAULT_INCREMENT  = 1024;      // 4kb memory pool increment
36   static const uint32_t MEMORY_POOL_DEFAULT_ALIGNMENT  = 64;        // 64bytes alignment
37
38   template<class T>
39   struct Block
40   {
41     Block() = default;
42     ~Block()
43     {
44       if(ptr)
45       {
46         free(ptr);
47       }
48     }
49
50     T*        ptr{nullptr};
51     uint32_t  dataSize{0u};
52     uint32_t  capacity{0u};
53     inline T& operator[](int index) const
54     {
55       return ptr[index];
56     }
57
58     inline void clear()
59     {
60       free(ptr);
61       capacity = 0;
62       dataSize = 0;
63     }
64
65     inline void resize(int newSize)
66     {
67       ptr      = reinterpret_cast<T*>(realloc(ptr, newSize * sizeof(T)));
68       capacity = newSize;
69       dataSize = newSize;
70     }
71
72     inline T* data() const
73     {
74       return ptr;
75     }
76
77     inline uint32_t size() const
78     {
79       return dataSize;
80     }
81   };
82   // This memory pool guarantees all items will be placed
83   // in the continuous memory area but returned pointers are relative
84   // and require translation before using
85   template<class T, int Increment, int Alignment = 0>
86   struct MemoryPool
87   {
88     Block<T>  data;
89     inline T& operator[](int index)
90     {
91       return data[index];
92     }
93     MemoryPool() = default;
94
95     IndirectPtr<T> Allocate(uint32_t count)
96     {
97       // set fixed capacity
98       if(fixedCapacity && data.size() != fixedCapacity)
99       {
100         data.resize(fixedCapacity);
101         totalCapacity = data.size();
102       }
103
104       // or resize dynamically
105       else if(data.size() <= offset + count)
106       {
107         data.resize(data.size() + Increment);
108
109         // update base pointer, required for address translation
110         totalCapacity = data.size();
111       }
112
113       basePtr = data.data();
114
115       IndirectPtr<T> retval{uint32_t(uintptr_t(&data[offset]) - uintptr_t(basePtr)), &basePtr};
116       size += count;
117       offset += count;
118
119       // align offset if needed (only if type size is 1)
120       if(Alignment && sizeof(T) == 1)
121       {
122         offset = ((offset / Alignment) * Alignment) + ((offset % Alignment) ? Alignment : 0);
123       }
124       return retval;
125     }
126
127     // Rolls back pool
128     void Rollback()
129     {
130       offset = 0;
131       size   = 0;
132     }
133
134     // Discards all data and storage
135     void Clear()
136     {
137       data.clear();
138       totalCapacity = 0;
139       offset        = 0;
140       size          = 0;
141     }
142
143     uint32_t offset{0u};
144     uint32_t totalCapacity{0u};
145     uint32_t size{0u};
146     uint32_t increment{Increment};
147     uint32_t alignment{Alignment};
148     uint32_t fixedCapacity{0u};
149     void*    basePtr{nullptr};
150   };
151
152   MemoryPool<uint8_t, MEMORY_POOL_DEFAULT_INCREMENT, MEMORY_POOL_DEFAULT_ALIGNMENT>  memoryPool;
153   MemoryPool<Command, COMMAND_POOL_DEFAULT_INCREMENT, MEMORY_POOL_DEFAULT_ALIGNMENT> commandPool;
154
155 public:
156   CommandPool() = default;
157   CommandPool(uint32_t fixedCapacity)
158   {
159     commandPool.fixedCapacity = fixedCapacity;
160     memoryPool.fixedCapacity  = fixedCapacity * 1024;
161   }
162
163   /**
164    * Return value may become invalid if pool is resized (by allocating another command)
165    * @param type
166    * @return
167    */
168   Command* AllocateCommand(CommandType type)
169   {
170     auto command  = commandPool.Allocate(1);
171     command->type = type;
172     auto* cmd     = command.Ptr();
173     return cmd;
174   }
175
176   template<class T>
177   IndirectPtr<T> Allocate(uint32_t count)
178   {
179     const auto typeSize       = sizeof(T);
180     const auto memoryRequired = typeSize * count;
181     auto       ptr            = memoryPool.Allocate(memoryRequired);
182
183     // Convert generic pointer and return
184     return IndirectPtr<T>{ptr.ptr, ptr.base};
185   }
186
187   // New (should not be needed)
188   template<class T>
189   T* New(uint32_t count)
190   {
191     auto ptr = Allocate<T>(count);
192     for(auto i = 0u; i < count; ++i)
193     {
194       new(&ptr[i]) T();
195     }
196     return ptr;
197   }
198
199   // TODO: explicit delete?
200   void Rollback(bool discard)
201   {
202     if(discard)
203     {
204       commandPool.Clear();
205       memoryPool.Clear();
206     }
207     else
208     {
209       commandPool.Rollback();
210       memoryPool.Rollback();
211     }
212   }
213
214   const Command* GetCommands(uint32_t& size) const
215   {
216     size = commandPool.size;
217     return commandPool.data.ptr;
218   }
219 };
220
221 CommandBuffer::CommandBuffer(const Graphics::CommandBufferCreateInfo& createInfo, EglGraphicsController& controller)
222 : CommandBufferResource(createInfo, controller)
223 {
224   mCommandPool = std::make_unique<CommandPool>(createInfo.fixedCapacity);
225 }
226
227 CommandBuffer::~CommandBuffer() = default;
228
229 void CommandBuffer::BindVertexBuffers(uint32_t                             firstBinding,
230                                       std::vector<const Graphics::Buffer*> buffers,
231                                       std::vector<uint32_t>                offsets)
232 {
233   auto command                                         = mCommandPool->AllocateCommand(CommandType::BIND_VERTEX_BUFFERS);
234   command->bindVertexBuffers.vertexBufferBindingsCount = firstBinding + buffers.size();
235   auto pBindings                                       = mCommandPool->Allocate<GLES::VertexBufferBindingDescriptor>(firstBinding + buffers.size());
236
237   command->bindVertexBuffers.vertexBufferBindings = pBindings;
238   auto index                                      = firstBinding;
239   for(auto& buf : buffers)
240   {
241     pBindings[index].buffer = static_cast<const GLES::Buffer*>(buf);
242     pBindings[index].offset = offsets[index - firstBinding];
243     index++;
244   }
245 }
246
247 void CommandBuffer::BindUniformBuffers(const std::vector<Graphics::UniformBufferBinding>& bindings)
248 {
249   auto command = mCommandPool->AllocateCommand(CommandType::BIND_UNIFORM_BUFFER);
250
251   auto& cmd     = *command;
252   auto& bindCmd = cmd.bindUniformBuffers;
253
254   // temporary static set of binding slots (thread local)
255   static const auto MAX_UNIFORM_BUFFER_BINDINGS = 64; // TODO: this should be read from introspection
256
257   // TODO: could use vector?
258   static thread_local UniformBufferBindingDescriptor sTempBindings[MAX_UNIFORM_BUFFER_BINDINGS];
259
260   // reset temp bindings
261   memset(sTempBindings, 0, sizeof(UniformBufferBindingDescriptor) * MAX_UNIFORM_BUFFER_BINDINGS);
262
263   auto maxBinding = 0u;
264
265   // find max binding and standalone UBO
266   for(const auto& binding : bindings)
267   {
268     if(binding.buffer)
269     {
270       auto glesBuffer = static_cast<const GLES::Buffer*>(binding.buffer);
271       if(glesBuffer->IsCPUAllocated()) // standalone uniforms
272       {
273         bindCmd.standaloneUniformsBufferBinding.buffer   = glesBuffer;
274         bindCmd.standaloneUniformsBufferBinding.offset   = binding.offset;
275         bindCmd.standaloneUniformsBufferBinding.binding  = binding.binding;
276         bindCmd.standaloneUniformsBufferBinding.emulated = true;
277       }
278       else // Bind regular UBO
279       {
280         auto& slot    = sTempBindings[binding.binding];
281         slot.buffer   = glesBuffer;
282         slot.offset   = binding.offset;
283         slot.binding  = binding.binding;
284         slot.emulated = false;
285         maxBinding    = std::max(maxBinding, binding.binding);
286       }
287     }
288   }
289   bindCmd.uniformBufferBindings      = nullptr;
290   bindCmd.uniformBufferBindingsCount = 0u;
291
292   // copy data
293   if(maxBinding)
294   {
295     auto destBindings = mCommandPool->Allocate<UniformBufferBindingDescriptor>(maxBinding + 1);
296     // copy
297     memcpy(destBindings.Ptr(), sTempBindings, sizeof(UniformBufferBindingDescriptor) * (maxBinding + 1));
298     bindCmd.uniformBufferBindings      = destBindings;
299     bindCmd.uniformBufferBindingsCount = maxBinding + 1;
300   }
301 }
302
303 void CommandBuffer::BindPipeline(const Graphics::Pipeline& pipeline)
304 {
305   auto command                   = mCommandPool->AllocateCommand(CommandType::BIND_PIPELINE);
306   command->bindPipeline.pipeline = static_cast<const GLES::Pipeline*>(&pipeline);
307 }
308
309 void CommandBuffer::BindTextures(std::vector<TextureBinding>& textureBindings)
310 {
311   auto  command                        = mCommandPool->AllocateCommand(CommandType::BIND_TEXTURES);
312   auto& bindTexturesCmd                = command->bindTextures;
313   bindTexturesCmd.textureBindings      = mCommandPool->Allocate<TextureBinding>(textureBindings.size());
314   bindTexturesCmd.textureBindingsCount = textureBindings.size();
315   memcpy(bindTexturesCmd.textureBindings.Ptr(), textureBindings.data(), sizeof(TextureBinding) * textureBindings.size());
316 }
317
318 void CommandBuffer::BindSamplers(std::vector<SamplerBinding>& samplerBindings)
319 {
320   auto  command                        = mCommandPool->AllocateCommand(CommandType::BIND_SAMPLERS);
321   auto& bindSamplersCmd                = command->bindSamplers;
322   bindSamplersCmd.samplerBindings      = mCommandPool->Allocate<SamplerBinding>(samplerBindings.size());
323   bindSamplersCmd.samplerBindingsCount = samplerBindings.size();
324   memcpy(bindSamplersCmd.samplerBindings.Ptr(), samplerBindings.data(), sizeof(TextureBinding) * samplerBindings.size());
325 }
326
327 void CommandBuffer::BindPushConstants(void*    data,
328                                       uint32_t size,
329                                       uint32_t binding)
330 {
331 }
332
333 void CommandBuffer::BindIndexBuffer(const Graphics::Buffer& buffer,
334                                     uint32_t                offset,
335                                     Format                  format)
336 {
337   auto command                    = mCommandPool->AllocateCommand(CommandType::BIND_INDEX_BUFFER);
338   command->bindIndexBuffer.buffer = static_cast<const GLES::Buffer*>(&buffer);
339   command->bindIndexBuffer.offset = offset;
340   command->bindIndexBuffer.format = format;
341 }
342
343 void CommandBuffer::BeginRenderPass(
344   Graphics::RenderPass*   renderPass,
345   Graphics::RenderTarget* renderTarget,
346   Rect2D                  renderArea,
347   std::vector<ClearValue> clearValues)
348 {
349   auto  command                    = mCommandPool->AllocateCommand(CommandType::BEGIN_RENDERPASS);
350   auto& cmd                        = *command;
351   cmd.beginRenderPass.renderPass   = static_cast<GLES::RenderPass*>(renderPass);
352   cmd.beginRenderPass.renderTarget = static_cast<GLES::RenderTarget*>(renderTarget);
353   cmd.beginRenderPass.renderArea   = renderArea;
354
355   cmd.beginRenderPass.clearValues = mCommandPool->Allocate<ClearValue>(clearValues.size());
356   memcpy(cmd.beginRenderPass.clearValues.Ptr(), clearValues.data(), sizeof(ClearValue) * clearValues.size());
357   cmd.beginRenderPass.clearValuesCount = clearValues.size();
358 }
359
360 void CommandBuffer::EndRenderPass(Graphics::SyncObject* syncObject)
361 {
362   auto command                      = mCommandPool->AllocateCommand(CommandType::END_RENDERPASS);
363   command->endRenderPass.syncObject = static_cast<GLES::SyncObject*>(syncObject);
364 }
365
366 void CommandBuffer::ExecuteCommandBuffers(std::vector<const Graphics::CommandBuffer*>&& commandBuffers)
367 {
368   auto  command    = mCommandPool->AllocateCommand(CommandType::EXECUTE_COMMAND_BUFFERS);
369   auto& cmd        = command->executeCommandBuffers;
370   cmd.buffers      = mCommandPool->Allocate<const GLES::CommandBuffer*>(commandBuffers.size());
371   cmd.buffersCount = commandBuffers.size();
372   for(auto i = 0u; i < cmd.buffersCount; ++i)
373   {
374     cmd.buffers[i] = static_cast<const GLES::CommandBuffer*>(commandBuffers[i]);
375   }
376 }
377
378 void CommandBuffer::Draw(
379   uint32_t vertexCount,
380   uint32_t instanceCount,
381   uint32_t firstVertex,
382   uint32_t firstInstance)
383 {
384   auto  command          = mCommandPool->AllocateCommand(CommandType::DRAW);
385   auto& cmd              = command->draw;
386   cmd.type               = DrawCallDescriptor::Type::DRAW;
387   cmd.draw.vertexCount   = vertexCount;
388   cmd.draw.instanceCount = instanceCount;
389   cmd.draw.firstInstance = firstInstance;
390   cmd.draw.firstVertex   = firstVertex;
391 }
392
393 void CommandBuffer::DrawIndexed(
394   uint32_t indexCount,
395   uint32_t instanceCount,
396   uint32_t firstIndex,
397   int32_t  vertexOffset,
398   uint32_t firstInstance)
399 {
400   auto  command                 = mCommandPool->AllocateCommand(CommandType::DRAW_INDEXED);
401   auto& cmd                     = command->draw;
402   cmd.type                      = DrawCallDescriptor::Type::DRAW_INDEXED;
403   cmd.drawIndexed.firstIndex    = firstIndex;
404   cmd.drawIndexed.firstInstance = firstInstance;
405   cmd.drawIndexed.indexCount    = indexCount;
406   cmd.drawIndexed.vertexOffset  = vertexOffset;
407   cmd.drawIndexed.instanceCount = instanceCount;
408 }
409
410 void CommandBuffer::DrawIndexedIndirect(
411   Graphics::Buffer& buffer,
412   uint32_t          offset,
413   uint32_t          drawCount,
414   uint32_t          stride)
415 {
416   auto  command                     = mCommandPool->AllocateCommand(CommandType::DRAW_INDEXED_INDIRECT);
417   auto& cmd                         = command->draw;
418   cmd.type                          = DrawCallDescriptor::Type::DRAW_INDEXED_INDIRECT;
419   cmd.drawIndexedIndirect.buffer    = static_cast<const GLES::Buffer*>(&buffer);
420   cmd.drawIndexedIndirect.offset    = offset;
421   cmd.drawIndexedIndirect.drawCount = drawCount;
422   cmd.drawIndexedIndirect.stride    = stride;
423 }
424
425 void CommandBuffer::Reset()
426 {
427   mCommandPool->Rollback(false);
428 }
429
430 void CommandBuffer::SetScissor(Graphics::Rect2D value)
431 {
432   auto command            = mCommandPool->AllocateCommand(CommandType::SET_SCISSOR);
433   command->scissor.region = value;
434 }
435
436 void CommandBuffer::SetScissorTestEnable(bool value)
437 {
438   auto command                = mCommandPool->AllocateCommand(CommandType::SET_SCISSOR_TEST);
439   command->scissorTest.enable = value;
440 }
441
442 void CommandBuffer::SetViewport(Viewport value)
443 {
444   auto command             = mCommandPool->AllocateCommand(CommandType::SET_VIEWPORT);
445   command->viewport.region = value;
446 }
447
448 void CommandBuffer::SetViewportEnable(bool value)
449 {
450   // There is no GL equivalent
451 }
452
453 void CommandBuffer::SetColorMask(bool enabled)
454 {
455   auto command               = mCommandPool->AllocateCommand(CommandType::SET_COLOR_MASK);
456   command->colorMask.enabled = enabled;
457 }
458
459 void CommandBuffer::ClearStencilBuffer()
460 {
461   mCommandPool->AllocateCommand(CommandType::CLEAR_STENCIL_BUFFER);
462 }
463
464 void CommandBuffer::SetStencilTestEnable(bool stencilEnable)
465 {
466   auto command                 = mCommandPool->AllocateCommand(CommandType::SET_STENCIL_TEST_ENABLE);
467   command->stencilTest.enabled = stencilEnable;
468 }
469
470 void CommandBuffer::SetStencilWriteMask(uint32_t writeMask)
471 {
472   auto command                   = mCommandPool->AllocateCommand(CommandType::SET_STENCIL_WRITE_MASK);
473   command->stencilWriteMask.mask = writeMask;
474 }
475
476 void CommandBuffer::SetStencilOp(Graphics::StencilOp failOp,
477                                  Graphics::StencilOp passOp,
478                                  Graphics::StencilOp depthFailOp)
479 {
480   auto  command   = mCommandPool->AllocateCommand(CommandType::SET_STENCIL_OP);
481   auto& cmd       = command->stencilOp;
482   cmd.failOp      = failOp;
483   cmd.passOp      = passOp;
484   cmd.depthFailOp = depthFailOp;
485 }
486
487 void CommandBuffer::SetStencilFunc(Graphics::CompareOp compareOp,
488                                    uint32_t            reference,
489                                    uint32_t            compareMask)
490 {
491   auto  command   = mCommandPool->AllocateCommand(CommandType::SET_STENCIL_FUNC);
492   auto& cmd       = command->stencilFunc;
493   cmd.compareOp   = compareOp;
494   cmd.compareMask = compareMask;
495   cmd.reference   = reference;
496 }
497
498 void CommandBuffer::SetDepthCompareOp(Graphics::CompareOp compareOp)
499 {
500   auto command             = mCommandPool->AllocateCommand(CommandType::SET_DEPTH_COMPARE_OP);
501   command->depth.compareOp = compareOp;
502 }
503
504 void CommandBuffer::SetDepthTestEnable(bool depthTestEnable)
505 {
506   auto command               = mCommandPool->AllocateCommand(CommandType::SET_DEPTH_TEST_ENABLE);
507   command->depth.testEnabled = depthTestEnable;
508 }
509 void CommandBuffer::SetDepthWriteEnable(bool depthWriteEnable)
510 {
511   auto command                = mCommandPool->AllocateCommand(CommandType::SET_DEPTH_WRITE_ENABLE);
512   command->depth.writeEnabled = depthWriteEnable;
513 }
514 void CommandBuffer::ClearDepthBuffer()
515 {
516   mCommandPool->AllocateCommand(CommandType::CLEAR_DEPTH_BUFFER);
517 }
518
519 void CommandBuffer::PresentRenderTarget(GLES::RenderTarget* renderTarget)
520 {
521   auto command                                 = mCommandPool->AllocateCommand(CommandType::PRESENT_RENDER_TARGET);
522   command->presentRenderTarget.targetToPresent = renderTarget;
523 }
524
525 [[nodiscard]] const Command* CommandBuffer::GetCommands(uint32_t& size) const
526 {
527   return mCommandPool->GetCommands(size);
528 }
529
530 void CommandBuffer::DestroyResource()
531 {
532   // Nothing to do
533 }
534
535 bool CommandBuffer::InitializeResource()
536 {
537   // Nothing to do
538   return true;
539 }
540
541 void CommandBuffer::DiscardResource()
542 {
543   GetController().DiscardResource(this);
544 }
545
546 } // namespace Dali::Graphics::GLES