Merge "Add lock for image loading" into devel/master
[platform/core/uifw/dali-adaptor.git] / dali / internal / graphics / gles-impl / gles-graphics-command-buffer.h
1 #ifndef DALI_GRAPHICS_GLES_COMMAND_BUFFER_H
2 #define DALI_GRAPHICS_GLES_COMMAND_BUFFER_H
3
4 /*
5  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */
20
21 // EXTERNAL INCLUDES
22 #include <dali/graphics-api/graphics-command-buffer.h>
23
24 // INTERNAL INCLUDES
25 #include "egl-graphics-controller.h"
26 #include "gles-graphics-buffer.h"
27 #include "gles-graphics-pipeline.h"
28 #include "gles-graphics-types.h"
29
30 namespace Dali::Graphics::GLES
31 {
32 class Texture;
33 class Pipeline;
34
35 enum class CommandType
36 {
37   FLUSH,
38   BIND_TEXTURES,
39   BIND_SAMPLERS,
40   BIND_VERTEX_BUFFERS,
41   BIND_INDEX_BUFFER,
42   BIND_UNIFORM_BUFFER,
43   BIND_PIPELINE,
44   DRAW,
45   DRAW_INDEXED,
46   DRAW_INDEXED_INDIRECT,
47   SET_SCISSOR,
48   SET_SCISSOR_TEST,
49   SET_VIEWPORT
50 };
51
52 /**
53  * Command structure allocates memory to store a single command
54  */
55 struct Command
56 {
57   Command()
58   {
59   }
60
61   ~Command()
62   {
63   }
64
65   /**
66    * @brief Copy constructor
67    * @param[in] rhs Command
68    */
69   Command(const Command& rhs)
70   {
71     switch(rhs.type)
72     {
73       case CommandType::BIND_VERTEX_BUFFERS:
74       {
75         bindVertexBuffers = rhs.bindVertexBuffers;
76         break;
77       }
78       case CommandType::BIND_INDEX_BUFFER:
79       {
80         bindIndexBuffer = rhs.bindIndexBuffer;
81         break;
82       }
83       case CommandType::BIND_SAMPLERS:
84       {
85         bindSamplers = rhs.bindSamplers;
86         break;
87       }
88       case CommandType::BIND_TEXTURES:
89       {
90         bindTextures = rhs.bindTextures;
91         break;
92       }
93       case CommandType::BIND_PIPELINE:
94       {
95         bindPipeline = rhs.bindPipeline;
96         break;
97       }
98       case CommandType::BIND_UNIFORM_BUFFER:
99       {
100         bindUniformBuffers = rhs.bindUniformBuffers;
101         break;
102       }
103       case CommandType::DRAW:
104       {
105         draw.type = rhs.draw.type;
106         draw.draw = rhs.draw.draw;
107         break;
108       }
109       case CommandType::DRAW_INDEXED:
110       {
111         draw.type        = rhs.draw.type;
112         draw.drawIndexed = rhs.draw.drawIndexed;
113         break;
114       }
115       case CommandType::DRAW_INDEXED_INDIRECT:
116       {
117         draw.type                = rhs.draw.type;
118         draw.drawIndexedIndirect = rhs.draw.drawIndexedIndirect;
119         break;
120       }
121       case CommandType::FLUSH:
122       {
123         // Nothing to do
124         break;
125       }
126       case CommandType::SET_SCISSOR:
127       {
128         scissor.region = rhs.scissor.region;
129         break;
130       }
131       case CommandType::SET_SCISSOR_TEST:
132       {
133         scissorTest.enable = rhs.scissorTest.enable;
134         break;
135       }
136       case CommandType::SET_VIEWPORT:
137       {
138         viewport.region = rhs.viewport.region;
139         break;
140       }
141     }
142     type = rhs.type;
143   }
144
145   /**
146    * @brief Copy constructor
147    * @param[in] rhs Command
148    */
149   Command(Command&& rhs) noexcept
150   {
151     switch(rhs.type)
152     {
153       case CommandType::BIND_VERTEX_BUFFERS:
154       {
155         bindVertexBuffers = std::move(rhs.bindVertexBuffers);
156         break;
157       }
158       case CommandType::BIND_INDEX_BUFFER:
159       {
160         bindIndexBuffer = rhs.bindIndexBuffer;
161         break;
162       }
163       case CommandType::BIND_UNIFORM_BUFFER:
164       {
165         bindUniformBuffers = std::move(rhs.bindUniformBuffers);
166         break;
167       }
168       case CommandType::BIND_SAMPLERS:
169       {
170         bindSamplers = std::move(rhs.bindSamplers);
171         break;
172       }
173       case CommandType::BIND_TEXTURES:
174       {
175         bindTextures = std::move(rhs.bindTextures);
176         break;
177       }
178       case CommandType::BIND_PIPELINE:
179       {
180         bindPipeline = rhs.bindPipeline;
181         break;
182       }
183       case CommandType::DRAW:
184       {
185         draw.type = rhs.draw.type;
186         draw.draw = rhs.draw.draw;
187         break;
188       }
189       case CommandType::DRAW_INDEXED:
190       {
191         draw.type        = rhs.draw.type;
192         draw.drawIndexed = rhs.draw.drawIndexed;
193         break;
194       }
195       case CommandType::DRAW_INDEXED_INDIRECT:
196       {
197         draw.type                = rhs.draw.type;
198         draw.drawIndexedIndirect = rhs.draw.drawIndexedIndirect;
199         break;
200       }
201       case CommandType::FLUSH:
202       {
203         // Nothing to do
204         break;
205       }
206       case CommandType::SET_SCISSOR:
207       {
208         scissor.region = rhs.scissor.region;
209         break;
210       }
211       case CommandType::SET_SCISSOR_TEST:
212       {
213         scissorTest.enable = rhs.scissorTest.enable;
214         break;
215       }
216       case CommandType::SET_VIEWPORT:
217       {
218         viewport.region = rhs.viewport.region;
219         break;
220       }
221     }
222     type = rhs.type;
223   }
224
225   CommandType type{CommandType::FLUSH}; ///< Type of command
226
227   union
228   {
229     struct
230     {
231       std::vector<Graphics::TextureBinding> textureBindings;
232     } bindTextures{};
233
234     // BindSampler command
235     struct
236     {
237       std::vector<Graphics::SamplerBinding> samplerBindings;
238     } bindSamplers;
239
240     struct
241     {
242       using Binding = GLES::VertexBufferBindingDescriptor;
243       std::vector<Binding> vertexBufferBindings;
244     } bindVertexBuffers;
245
246     struct : public IndexBufferBindingDescriptor
247     {
248     } bindIndexBuffer;
249
250     struct
251     {
252       std::vector<UniformBufferBindingDescriptor> uniformBufferBindings{};
253       UniformBufferBindingDescriptor              standaloneUniformsBufferBinding{};
254     } bindUniformBuffers;
255
256     struct
257     {
258       const GLES::Pipeline* pipeline{nullptr};
259     } bindPipeline;
260
261     struct : public DrawCallDescriptor
262     {
263     } draw;
264
265     struct
266     {
267       Graphics::Rect2D region;
268     } scissor;
269
270     struct
271     {
272       bool enable;
273     } scissorTest;
274
275     struct
276     {
277       Graphics::Viewport region;
278     } viewport;
279   };
280 };
281
282 using CommandBufferResource = Resource<Graphics::CommandBuffer, Graphics::CommandBufferCreateInfo>;
283
284 class CommandBuffer : public CommandBufferResource
285 {
286 public:
287   CommandBuffer(const Graphics::CommandBufferCreateInfo& createInfo, EglGraphicsController& controller)
288   : CommandBufferResource(createInfo, controller)
289   {
290   }
291
292   ~CommandBuffer() override = default;
293
294   void BindVertexBuffers(uint32_t                             firstBinding,
295                          std::vector<const Graphics::Buffer*> buffers,
296                          std::vector<uint32_t>                offsets) override
297   {
298     mCommands.emplace_back();
299     mCommands.back().type = CommandType::BIND_VERTEX_BUFFERS;
300     auto& bindings        = mCommands.back().bindVertexBuffers.vertexBufferBindings;
301     if(bindings.size() < firstBinding + buffers.size())
302     {
303       bindings.resize(firstBinding + buffers.size());
304       auto index = firstBinding;
305       for(auto& buf : buffers)
306       {
307         bindings[index].buffer = static_cast<const GLES::Buffer*>(buf);
308         bindings[index].offset = offsets[index - firstBinding];
309         index++;
310       }
311     }
312   }
313
314   void BindUniformBuffers(const std::vector<Graphics::UniformBufferBinding>& bindings) override
315   {
316     mCommands.emplace_back();
317     auto& cmd     = mCommands.back();
318     cmd.type      = CommandType::BIND_UNIFORM_BUFFER;
319     auto& bindCmd = cmd.bindUniformBuffers;
320     for(const auto& binding : bindings)
321     {
322       if(binding.buffer)
323       {
324         auto glesBuffer = static_cast<const GLES::Buffer*>(binding.buffer);
325         if(glesBuffer->IsCPUAllocated()) // standalone uniforms
326         {
327           bindCmd.standaloneUniformsBufferBinding.buffer   = glesBuffer;
328           bindCmd.standaloneUniformsBufferBinding.offset   = binding.offset;
329           bindCmd.standaloneUniformsBufferBinding.binding  = binding.binding;
330           bindCmd.standaloneUniformsBufferBinding.emulated = true;
331         }
332         else // Bind regular UBO
333         {
334           // resize binding slots
335           if(binding.binding >= bindCmd.uniformBufferBindings.size())
336           {
337             bindCmd.uniformBufferBindings.resize(binding.binding + 1);
338           }
339           auto& slot    = bindCmd.uniformBufferBindings[binding.binding];
340           slot.buffer   = glesBuffer;
341           slot.offset   = binding.offset;
342           slot.binding  = binding.binding;
343           slot.emulated = false;
344         }
345       }
346     }
347   }
348
349   void BindPipeline(const Graphics::Pipeline& pipeline) override
350   {
351     mCommands.emplace_back();
352     mCommands.back().type                  = CommandType::BIND_PIPELINE;
353     mCommands.back().bindPipeline.pipeline = static_cast<const GLES::Pipeline*>(&pipeline);
354   }
355
356   void BindTextures(std::vector<TextureBinding>& textureBindings) override
357   {
358     mCommands.emplace_back();
359     mCommands.back().type                         = CommandType::BIND_TEXTURES;
360     mCommands.back().bindTextures.textureBindings = std::move(textureBindings);
361   }
362
363   void BindSamplers(std::vector<SamplerBinding>& samplerBindings) override
364   {
365     mCommands.emplace_back();
366     mCommands.back().bindSamplers.samplerBindings = std::move(samplerBindings);
367   }
368
369   void BindPushConstants(void*    data,
370                          uint32_t size,
371                          uint32_t binding) override
372   {
373   }
374
375   void BindIndexBuffer(const Graphics::Buffer& buffer,
376                        uint32_t                offset,
377                        Format                  format) override
378   {
379     mCommands.emplace_back();
380     mCommands.back().type                   = CommandType::BIND_INDEX_BUFFER;
381     mCommands.back().bindIndexBuffer.buffer = static_cast<const GLES::Buffer*>(&buffer);
382     mCommands.back().bindIndexBuffer.offset = offset;
383     mCommands.back().bindIndexBuffer.format = format;
384   }
385
386   void BeginRenderPass(
387     Graphics::RenderPass&   renderPass,
388     Graphics::RenderTarget& renderTarget,
389     Extent2D                renderArea,
390     std::vector<ClearValue> clearValues) override
391   {
392   }
393
394   /**
395    * @brief Ends current render pass
396    *
397    * This command must be issued in order to finalize the render pass.
398    * It's up to the implementation whether anything has to be done but
399    * the Controller may use end RP marker in order to resolve resource
400    * dependencies (for example, to know when target texture is ready
401    * before passing it to another render pass).
402    */
403   void EndRenderPass() override
404   {
405   }
406
407   void Draw(
408     uint32_t vertexCount,
409     uint32_t instanceCount,
410     uint32_t firstVertex,
411     uint32_t firstInstance) override
412   {
413     mCommands.emplace_back();
414     mCommands.back().type  = CommandType::DRAW;
415     auto& cmd              = mCommands.back().draw;
416     cmd.type               = DrawCallDescriptor::Type::DRAW;
417     cmd.draw.vertexCount   = vertexCount;
418     cmd.draw.instanceCount = instanceCount;
419     cmd.draw.firstInstance = firstInstance;
420     cmd.draw.firstVertex   = firstVertex;
421   }
422
423   void DrawIndexed(
424     uint32_t indexCount,
425     uint32_t instanceCount,
426     uint32_t firstIndex,
427     int32_t  vertexOffset,
428     uint32_t firstInstance) override
429   {
430     mCommands.emplace_back();
431     mCommands.back().type         = CommandType::DRAW_INDEXED;
432     auto& cmd                     = mCommands.back().draw;
433     cmd.type                      = DrawCallDescriptor::Type::DRAW_INDEXED;
434     cmd.drawIndexed.firstIndex    = firstIndex;
435     cmd.drawIndexed.firstInstance = firstInstance;
436     cmd.drawIndexed.indexCount    = indexCount;
437     cmd.drawIndexed.vertexOffset  = vertexOffset;
438     cmd.drawIndexed.instanceCount = instanceCount;
439   }
440
441   void DrawIndexedIndirect(
442     Graphics::Buffer& buffer,
443     uint32_t          offset,
444     uint32_t          drawCount,
445     uint32_t          stride) override
446   {
447     mCommands.emplace_back();
448     mCommands.back().type             = CommandType::DRAW_INDEXED_INDIRECT;
449     auto& cmd                         = mCommands.back().draw;
450     cmd.type                          = DrawCallDescriptor::Type::DRAW_INDEXED_INDIRECT;
451     cmd.drawIndexedIndirect.buffer    = static_cast<const GLES::Buffer*>(&buffer);
452     cmd.drawIndexedIndirect.offset    = offset;
453     cmd.drawIndexedIndirect.drawCount = drawCount;
454     cmd.drawIndexedIndirect.stride    = stride;
455   }
456
457   void Reset() override
458   {
459     mCommands.clear();
460   }
461
462   void SetScissor(Graphics::Rect2D value) override
463   {
464     mCommands.emplace_back();
465     mCommands.back().type           = CommandType::SET_SCISSOR;
466     mCommands.back().scissor.region = value;
467   }
468
469   void SetScissorTestEnable(bool value) override
470   {
471     mCommands.emplace_back();
472     mCommands.back().type               = CommandType::SET_SCISSOR_TEST;
473     mCommands.back().scissorTest.enable = value;
474   }
475
476   void SetViewport(Viewport value) override
477   {
478     mCommands.emplace_back();
479     mCommands.back().type            = CommandType::SET_VIEWPORT;
480     mCommands.back().viewport.region = value;
481   }
482
483   void SetViewportEnable(bool value) override
484   {
485     // There is no GL equivalent
486   }
487
488   [[nodiscard]] const std::vector<Command>& GetCommands() const
489   {
490     return mCommands;
491   }
492
493   void DestroyResource() override
494   {
495     // Nothing to do
496   }
497
498   bool InitializeResource() override
499   {
500     // Nothing to do
501     return true;
502   }
503
504   void DiscardResource() override
505   {
506     // Nothing to do
507   }
508
509 private:
510   std::vector<Command> mCommands;
511 };
512 } // namespace Dali::Graphics::GLES
513
514 #endif