Merge "Add EnsureFontClientCreated to StyleMonitor" into devel/master
[platform/core/uifw/dali-adaptor.git] / dali / internal / graphics / gles-impl / egl-graphics-controller.cpp
1 /*
2  * Copyright (c) 2023 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 // CLASS HEADER
18 #include <dali/internal/graphics/gles-impl/egl-graphics-controller.h>
19
20 // EXTERNAL INCLUDES
21 #include <dali/public-api/common/dali-common.h>
22
23 // INTERNAL INCLUDES
24 #include <dali/integration-api/adaptor-framework/render-surface-interface.h>
25 #include <dali/integration-api/debug.h>
26 #include <dali/integration-api/gl-abstraction.h>
27 #include <dali/integration-api/gl-defines.h>
28 #include <dali/integration-api/graphics-sync-abstraction.h>
29 #include <dali/integration-api/pixel-data-integ.h>
30 #include <dali/internal/graphics/gles-impl/egl-sync-object.h>
31 #include <dali/internal/graphics/gles-impl/gles-graphics-command-buffer.h>
32 #include <dali/internal/graphics/gles-impl/gles-graphics-pipeline.h>
33 #include <dali/internal/graphics/gles-impl/gles-graphics-program.h>
34 #include <dali/internal/graphics/gles-impl/gles-graphics-render-pass.h>
35 #include <dali/internal/graphics/gles-impl/gles-graphics-render-target.h>
36 #include <dali/internal/graphics/gles-impl/gles-graphics-shader.h>
37 #include <dali/internal/graphics/gles-impl/gles-graphics-texture.h>
38 #include <dali/internal/graphics/gles-impl/gles-graphics-types.h>
39 #include <dali/internal/graphics/gles-impl/gles-sync-object.h>
40 #include <dali/internal/graphics/gles-impl/gles3-graphics-memory.h>
41 #include <dali/internal/graphics/gles/egl-sync-implementation.h>
42
43 #include <dali/internal/graphics/gles/egl-graphics.h>
44
45 #include <any>
46
47 // Uncomment the following define to turn on frame dumping
48 //#define ENABLE_COMMAND_BUFFER_FRAME_DUMP 1
49 #include <dali/internal/graphics/gles-impl/egl-graphics-controller-debug.h>
50 DUMP_FRAME_INIT();
51
52 namespace Dali::Graphics
53 {
54 namespace
55 {
56 /**
57  * @brief Custom deleter for all Graphics objects created
58  * with use of the Controller.
59  *
60  * When Graphics object dies the unique pointer (Graphics::UniquePtr)
61  * doesn't destroy it directly but passes the ownership back
62  * to the Controller. The GLESDeleter is responsible for passing
63  * the object to the discard queue (by calling Resource::DiscardResource()).
64  */
65 template<typename T>
66 struct GLESDeleter
67 {
68   GLESDeleter() = default;
69
70   void operator()(T* object)
71   {
72     // Discard resource (add it to discard queue)
73     object->DiscardResource();
74   }
75 };
76
77 /**
78  * @brief Helper function allocating graphics object
79  *
80  * @param[in] info Create info structure
81  * @param[in] controller Controller object
82  * @param[out] out Unique pointer to the return object
83  */
84 template<class GLESType, class GfxCreateInfo, class T>
85 auto NewObject(const GfxCreateInfo& info, EglGraphicsController& controller, T&& oldObject)
86 {
87   // Use allocator
88   using Type = typename T::element_type;
89   using UPtr = Graphics::UniquePtr<Type>;
90   if(info.allocationCallbacks)
91   {
92     auto* memory = info.allocationCallbacks->allocCallback(
93       sizeof(GLESType),
94       0,
95       info.allocationCallbacks->userData);
96     return UPtr(new(memory) GLESType(info, controller), GLESDeleter<GLESType>());
97   }
98   else // Use standard allocator
99   {
100     return UPtr(new GLESType(info, controller), GLESDeleter<GLESType>());
101   }
102 }
103
104 template<class T0, class T1>
105 T0* CastObject(T1* apiObject)
106 {
107   return static_cast<T0*>(apiObject);
108 }
109
110 // Maximum size of texture upload buffer.
111 const uint32_t TEXTURE_UPLOAD_MAX_BUFER_SIZE_MB = 1;
112
113 } // namespace
114
115 EglGraphicsController::EglGraphicsController()
116 : mTextureDependencyChecker(*this),
117   mSyncPool(*this)
118 {
119 }
120
121 EglGraphicsController::~EglGraphicsController()
122 {
123   while(!mPresentationCommandBuffers.empty())
124   {
125     auto presentCommandBuffer = const_cast<GLES::CommandBuffer*>(mPresentationCommandBuffers.front());
126     delete presentCommandBuffer;
127     mPresentationCommandBuffers.pop();
128   }
129 }
130
131 void EglGraphicsController::InitializeGLES(Integration::GlAbstraction& glAbstraction)
132 {
133   DALI_LOG_RELEASE_INFO("Initializing Graphics Controller Phase 1\n");
134   mGlAbstraction  = &glAbstraction;
135   mContext        = std::make_unique<GLES::Context>(*this);
136   mCurrentContext = mContext.get();
137 }
138
139 void EglGraphicsController::Initialize(Integration::GraphicsSyncAbstraction&    syncImplementation,
140                                        Integration::GlContextHelperAbstraction& glContextHelperAbstraction,
141                                        Internal::Adaptor::GraphicsInterface&    graphicsInterface)
142 {
143   DALI_LOG_RELEASE_INFO("Initializing Graphics Controller Phase 2\n");
144   auto* syncImplPtr = static_cast<Internal::Adaptor::EglSyncImplementation*>(&syncImplementation);
145
146   mEglSyncImplementation      = syncImplPtr;
147   mGlContextHelperAbstraction = &glContextHelperAbstraction;
148   mGraphics                   = &graphicsInterface;
149 }
150
151 void EglGraphicsController::FrameStart()
152 {
153   mCapacity = 0; // Reset the command buffer capacity at the start of the frame.
154 }
155
156 void EglGraphicsController::SubmitCommandBuffers(const SubmitInfo& submitInfo)
157 {
158   for(auto& cmdbuf : submitInfo.cmdBuffer)
159   {
160     // Push command buffers
161     auto* commandBuffer = static_cast<GLES::CommandBuffer*>(cmdbuf);
162     mCapacity += commandBuffer->GetCapacity();
163     mCommandQueue.push(commandBuffer);
164   }
165
166   // If flush bit set, flush all pending tasks
167   if(submitInfo.flags & (0 | SubmitFlagBits::FLUSH))
168   {
169     Flush();
170   }
171 }
172
173 void EglGraphicsController::PresentRenderTarget(RenderTarget* renderTarget)
174 {
175   GLES::CommandBuffer* presentCommandBuffer{nullptr};
176   if(mPresentationCommandBuffers.empty())
177   {
178     CommandBufferCreateInfo info;
179     info.SetLevel(CommandBufferLevel::PRIMARY);
180     info.fixedCapacity   = 1; // only one command
181     presentCommandBuffer = new GLES::CommandBuffer(info, *this);
182   }
183   else
184   {
185     presentCommandBuffer = const_cast<GLES::CommandBuffer*>(mPresentationCommandBuffers.front());
186     presentCommandBuffer->Reset();
187     mPresentationCommandBuffers.pop();
188   }
189   presentCommandBuffer->PresentRenderTarget(static_cast<GLES::RenderTarget*>(renderTarget));
190   SubmitInfo submitInfo;
191   submitInfo.cmdBuffer = {presentCommandBuffer};
192   submitInfo.flags     = 0 | SubmitFlagBits::FLUSH;
193   SubmitCommandBuffers(submitInfo);
194 }
195
196 void EglGraphicsController::ResolvePresentRenderTarget(GLES::RenderTarget* renderTarget)
197 {
198   mCurrentContext->InvalidateDepthStencilBuffers();
199
200   auto* rt = static_cast<GLES::RenderTarget*>(renderTarget);
201   if(rt->GetCreateInfo().surface)
202   {
203     auto* surfaceInterface = reinterpret_cast<Dali::RenderSurfaceInterface*>(rt->GetCreateInfo().surface);
204     surfaceInterface->MakeContextCurrent();
205     surfaceInterface->PostRender();
206   }
207 }
208
209 void EglGraphicsController::PostRender()
210 {
211   mTextureDependencyChecker.Reset();
212   mSyncPool.AgeSyncObjects();
213 }
214
215 Integration::GlAbstraction& EglGraphicsController::GetGlAbstraction()
216 {
217   DALI_ASSERT_DEBUG(mGlAbstraction && "Graphics controller not initialized");
218   return *mGlAbstraction;
219 }
220
221 Integration::GlContextHelperAbstraction& EglGraphicsController::GetGlContextHelperAbstraction()
222 {
223   DALI_ASSERT_DEBUG(mGlContextHelperAbstraction && "Graphics controller not initialized");
224   return *mGlContextHelperAbstraction;
225 }
226
227 Internal::Adaptor::EglSyncImplementation& EglGraphicsController::GetEglSyncImplementation()
228 {
229   DALI_ASSERT_DEBUG(mEglSyncImplementation && "Sync implementation not initialized");
230   return *mEglSyncImplementation;
231 }
232
233 Graphics::UniquePtr<CommandBuffer> EglGraphicsController::CreateCommandBuffer(
234   const CommandBufferCreateInfo&       commandBufferCreateInfo,
235   Graphics::UniquePtr<CommandBuffer>&& oldCommandBuffer)
236 {
237   return NewObject<GLES::CommandBuffer>(commandBufferCreateInfo, *this, std::move(oldCommandBuffer));
238 }
239
240 Graphics::UniquePtr<RenderPass> EglGraphicsController::CreateRenderPass(const RenderPassCreateInfo& renderPassCreateInfo, Graphics::UniquePtr<RenderPass>&& oldRenderPass)
241 {
242   return NewObject<GLES::RenderPass>(renderPassCreateInfo, *this, std::move(oldRenderPass));
243 }
244
245 Graphics::UniquePtr<Texture>
246 EglGraphicsController::CreateTexture(const TextureCreateInfo& textureCreateInfo, Graphics::UniquePtr<Texture>&& oldTexture)
247 {
248   return NewObject<GLES::Texture>(textureCreateInfo, *this, std::move(oldTexture));
249 }
250
251 Graphics::UniquePtr<Buffer> EglGraphicsController::CreateBuffer(
252   const BufferCreateInfo& bufferCreateInfo, Graphics::UniquePtr<Buffer>&& oldBuffer)
253 {
254   return NewObject<GLES::Buffer>(bufferCreateInfo, *this, std::move(oldBuffer));
255 }
256
257 Graphics::UniquePtr<Framebuffer> EglGraphicsController::CreateFramebuffer(
258   const FramebufferCreateInfo& framebufferCreateInfo, Graphics::UniquePtr<Framebuffer>&& oldFramebuffer)
259 {
260   return NewObject<GLES::Framebuffer>(framebufferCreateInfo, *this, std::move(oldFramebuffer));
261 }
262
263 Graphics::UniquePtr<Pipeline> EglGraphicsController::CreatePipeline(
264   const PipelineCreateInfo& pipelineCreateInfo, Graphics::UniquePtr<Graphics::Pipeline>&& oldPipeline)
265 {
266   // Create pipeline cache if needed
267   if(!mPipelineCache)
268   {
269     mPipelineCache = std::make_unique<GLES::PipelineCache>(*this);
270   }
271
272   return mPipelineCache->GetPipeline(pipelineCreateInfo, std::move(oldPipeline));
273 }
274
275 Graphics::UniquePtr<Program> EglGraphicsController::CreateProgram(
276   const ProgramCreateInfo& programCreateInfo, UniquePtr<Program>&& oldProgram)
277 {
278   // Create program cache if needed
279   if(!mPipelineCache)
280   {
281     mPipelineCache = std::make_unique<GLES::PipelineCache>(*this);
282   }
283
284   return mPipelineCache->GetProgram(programCreateInfo, std::move(oldProgram));
285 }
286
287 Graphics::UniquePtr<Shader> EglGraphicsController::CreateShader(const ShaderCreateInfo& shaderCreateInfo, Graphics::UniquePtr<Shader>&& oldShader)
288 {
289   return NewObject<GLES::Shader>(shaderCreateInfo, *this, std::move(oldShader));
290 }
291
292 Graphics::UniquePtr<Sampler> EglGraphicsController::CreateSampler(const SamplerCreateInfo& samplerCreateInfo, Graphics::UniquePtr<Sampler>&& oldSampler)
293 {
294   return NewObject<GLES::Sampler>(samplerCreateInfo, *this, std::move(oldSampler));
295 }
296
297 Graphics::UniquePtr<RenderTarget> EglGraphicsController::CreateRenderTarget(const RenderTargetCreateInfo& renderTargetCreateInfo, Graphics::UniquePtr<RenderTarget>&& oldRenderTarget)
298 {
299   return NewObject<GLES::RenderTarget>(renderTargetCreateInfo, *this, std::move(oldRenderTarget));
300 }
301
302 Graphics::UniquePtr<SyncObject> EglGraphicsController::CreateSyncObject(const SyncObjectCreateInfo& syncObjectCreateInfo,
303                                                                         UniquePtr<SyncObject>&&     oldSyncObject)
304 {
305   if(GetGLESVersion() < GLES::GLESVersion::GLES_30)
306   {
307     return NewObject<EGL::SyncObject>(syncObjectCreateInfo, *this, std::move(oldSyncObject));
308   }
309   else
310   {
311     return NewObject<GLES::SyncObject>(syncObjectCreateInfo, *this, std::move(oldSyncObject));
312   }
313 }
314
315 TextureProperties EglGraphicsController::GetTextureProperties(const Texture& texture)
316 {
317   const GLES::Texture* glesTexture = static_cast<const GLES::Texture*>(&texture);
318   auto                 createInfo  = glesTexture->GetCreateInfo();
319
320   TextureProperties properties{};
321   properties.format       = createInfo.format;
322   properties.compressed   = glesTexture->IsCompressed();
323   properties.extent2D     = createInfo.size;
324   properties.nativeHandle = glesTexture->GetGLTexture();
325   // TODO: Skip format1, emulated, packed, directWriteAccessEnabled of TextureProperties for now
326
327   return properties;
328 }
329
330 const Graphics::Reflection& EglGraphicsController::GetProgramReflection(const Graphics::Program& program)
331 {
332   return static_cast<const Graphics::GLES::Program*>(&program)->GetReflection();
333 }
334
335 void EglGraphicsController::CreateSurfaceContext(Dali::RenderSurfaceInterface* surface)
336 {
337   std::unique_ptr<GLES::Context> context = std::make_unique<GLES::Context>(*this);
338   mSurfaceContexts.push_back(std::move(std::make_pair(surface, std::move(context))));
339 }
340
341 void EglGraphicsController::DeleteSurfaceContext(Dali::RenderSurfaceInterface* surface)
342 {
343   mSurfaceContexts.erase(std::remove_if(
344                            mSurfaceContexts.begin(), mSurfaceContexts.end(), [surface](SurfaceContextPair& iter) { return surface == iter.first; }),
345                          mSurfaceContexts.end());
346 }
347
348 void EglGraphicsController::ActivateResourceContext()
349 {
350   mCurrentContext = mContext.get();
351   mCurrentContext->GlContextCreated();
352   if(!mSharedContext)
353   {
354     auto eglGraphics = dynamic_cast<Dali::Internal::Adaptor::EglGraphics*>(mGraphics);
355     if(eglGraphics)
356     {
357       mSharedContext = eglGraphics->GetEglImplementation().GetContext();
358     }
359   }
360 }
361
362 void EglGraphicsController::ActivateSurfaceContext(Dali::RenderSurfaceInterface* surface)
363 {
364   if(surface && mGraphics->IsResourceContextSupported())
365   {
366     auto iter = std::find_if(mSurfaceContexts.begin(), mSurfaceContexts.end(), [surface](SurfaceContextPair& iter) { return (iter.first == surface); });
367
368     if(iter != mSurfaceContexts.end())
369     {
370       mCurrentContext = iter->second.get();
371       mCurrentContext->GlContextCreated();
372     }
373   }
374 }
375
376 void EglGraphicsController::AddTexture(GLES::Texture& texture)
377 {
378   // Assuming we are on the correct context
379   mCreateTextureQueue.push(&texture);
380 }
381
382 void EglGraphicsController::AddBuffer(GLES::Buffer& buffer)
383 {
384   // Assuming we are on the correct context
385   mCreateBufferQueue.push(&buffer);
386 }
387
388 void EglGraphicsController::AddFramebuffer(GLES::Framebuffer& framebuffer)
389 {
390   // Assuming we are on the correct context
391   mCreateFramebufferQueue.push(&framebuffer);
392 }
393
394 void EglGraphicsController::ProcessDiscardQueues()
395 {
396   // Process textures
397   ProcessDiscardQueue<GLES::Texture>(mDiscardTextureQueue);
398
399   // Process buffers
400   ProcessDiscardQueue<GLES::Buffer>(mDiscardBufferQueue);
401
402   // Process Framebuffers
403   ProcessDiscardQueue<GLES::Framebuffer>(mDiscardFramebufferQueue);
404
405   // Process RenderPass
406   ProcessDiscardQueue<GLES::RenderPass>(mDiscardRenderPassQueue);
407
408   // Process RenderTarget
409   ProcessDiscardQueue<GLES::RenderTarget>(mDiscardRenderTargetQueue);
410
411   // Process pipelines
412   ProcessDiscardQueue(mDiscardPipelineQueue);
413
414   // Process programs
415   ProcessDiscardQueue<GLES::Program>(mDiscardProgramQueue);
416
417   // Process shaders
418   ProcessDiscardQueue<GLES::Shader>(mDiscardShaderQueue);
419
420   // Process samplers
421   ProcessDiscardQueue<GLES::Sampler>(mDiscardSamplerQueue);
422
423   // Process command buffers
424   ProcessDiscardQueue<GLES::CommandBuffer>(mDiscardCommandBufferQueue);
425 }
426
427 void EglGraphicsController::ProcessCreateQueues()
428 {
429   // Process textures
430   ProcessCreateQueue(mCreateTextureQueue);
431
432   // Process buffers
433   ProcessCreateQueue(mCreateBufferQueue);
434
435   // Process framebuffers
436   ProcessCreateQueue(mCreateFramebufferQueue);
437 }
438
439 void EglGraphicsController::ProcessCommandBuffer(const GLES::CommandBuffer& commandBuffer)
440 {
441   auto       count    = 0u;
442   const auto commands = commandBuffer.GetCommands(count);
443   for(auto i = 0u; i < count; ++i)
444   {
445     auto& cmd = commands[i];
446     // process command
447     switch(cmd.type)
448     {
449       case GLES::CommandType::FLUSH:
450       {
451         // Nothing to do here
452         break;
453       }
454       case GLES::CommandType::BIND_TEXTURES:
455       {
456         mCurrentContext->BindTextures(cmd.bindTextures.textureBindings.Ptr(), cmd.bindTextures.textureBindingsCount);
457         break;
458       }
459       case GLES::CommandType::BIND_VERTEX_BUFFERS:
460       {
461         auto bindings = cmd.bindVertexBuffers.vertexBufferBindings.Ptr();
462         mCurrentContext->BindVertexBuffers(bindings, cmd.bindVertexBuffers.vertexBufferBindingsCount);
463         break;
464       }
465       case GLES::CommandType::BIND_UNIFORM_BUFFER:
466       {
467         auto& bindings = cmd.bindUniformBuffers;
468         mCurrentContext->BindUniformBuffers(bindings.uniformBufferBindingsCount ? bindings.uniformBufferBindings.Ptr() : nullptr, bindings.uniformBufferBindingsCount, bindings.standaloneUniformsBufferBinding);
469         break;
470       }
471       case GLES::CommandType::BIND_INDEX_BUFFER:
472       {
473         mCurrentContext->BindIndexBuffer(cmd.bindIndexBuffer);
474         break;
475       }
476       case GLES::CommandType::BIND_SAMPLERS:
477       {
478         break;
479       }
480       case GLES::CommandType::BIND_PIPELINE:
481       {
482         auto pipeline = static_cast<const GLES::Pipeline*>(cmd.bindPipeline.pipeline);
483         mCurrentContext->BindPipeline(pipeline);
484         break;
485       }
486       case GLES::CommandType::DRAW:
487       {
488         mCurrentContext->Flush(false, cmd.draw, mTextureDependencyChecker);
489         break;
490       }
491       case GLES::CommandType::DRAW_INDEXED:
492       {
493         mCurrentContext->Flush(false, cmd.draw, mTextureDependencyChecker);
494         break;
495       }
496       case GLES::CommandType::DRAW_INDEXED_INDIRECT:
497       {
498         mCurrentContext->Flush(false, cmd.draw, mTextureDependencyChecker);
499         break;
500       }
501       case GLES::CommandType::SET_SCISSOR: // @todo Consider correcting for orientation here?
502       {
503         mGlAbstraction->Scissor(cmd.scissor.region.x, cmd.scissor.region.y, cmd.scissor.region.width, cmd.scissor.region.height);
504         break;
505       }
506       case GLES::CommandType::SET_SCISSOR_TEST:
507       {
508         mCurrentContext->SetScissorTestEnabled(cmd.scissorTest.enable);
509         break;
510       }
511       case GLES::CommandType::SET_VIEWPORT: // @todo Consider correcting for orientation here?
512       {
513         mGlAbstraction->Viewport(cmd.viewport.region.x, cmd.viewport.region.y, cmd.viewport.region.width, cmd.viewport.region.height);
514         break;
515       }
516
517       case GLES::CommandType::SET_COLOR_MASK:
518       {
519         mCurrentContext->ColorMask(cmd.colorMask.enabled);
520         break;
521       }
522       case GLES::CommandType::CLEAR_STENCIL_BUFFER:
523       {
524         mCurrentContext->ClearStencilBuffer();
525         break;
526       }
527       case GLES::CommandType::CLEAR_DEPTH_BUFFER:
528       {
529         mCurrentContext->ClearDepthBuffer();
530         break;
531       }
532
533       case GLES::CommandType::SET_STENCIL_TEST_ENABLE:
534       {
535         mCurrentContext->SetStencilTestEnable(cmd.stencilTest.enabled);
536         break;
537       }
538
539       case GLES::CommandType::SET_STENCIL_FUNC:
540       {
541         mCurrentContext->StencilFunc(cmd.stencilFunc.compareOp,
542                                      cmd.stencilFunc.reference,
543                                      cmd.stencilFunc.compareMask);
544         break;
545       }
546
547       case GLES::CommandType::SET_STENCIL_WRITE_MASK:
548       {
549         mCurrentContext->StencilMask(cmd.stencilWriteMask.mask);
550         break;
551       }
552
553       case GLES::CommandType::SET_STENCIL_OP:
554       {
555         mCurrentContext->StencilOp(cmd.stencilOp.failOp,
556                                    cmd.stencilOp.depthFailOp,
557                                    cmd.stencilOp.passOp);
558         break;
559       }
560
561       case GLES::CommandType::SET_DEPTH_COMPARE_OP:
562       {
563         mCurrentContext->SetDepthCompareOp(cmd.depth.compareOp);
564         break;
565       }
566       case GLES::CommandType::SET_DEPTH_TEST_ENABLE:
567       {
568         mCurrentContext->SetDepthTestEnable(cmd.depth.testEnabled);
569         break;
570       }
571       case GLES::CommandType::SET_DEPTH_WRITE_ENABLE:
572       {
573         mCurrentContext->SetDepthWriteEnable(cmd.depth.writeEnabled);
574         break;
575       }
576
577       case GLES::CommandType::BEGIN_RENDERPASS:
578       {
579         auto&       renderTarget = *cmd.beginRenderPass.renderTarget;
580         const auto& targetInfo   = renderTarget.GetCreateInfo();
581
582         if(targetInfo.surface)
583         {
584           // switch to surface context
585           mGraphics->ActivateSurfaceContext(static_cast<Dali::RenderSurfaceInterface*>(targetInfo.surface));
586         }
587         else if(targetInfo.framebuffer)
588         {
589           // switch to resource context
590           mGraphics->ActivateResourceContext();
591         }
592
593         mCurrentContext->BeginRenderPass(cmd.beginRenderPass);
594
595         break;
596       }
597       case GLES::CommandType::END_RENDERPASS:
598       {
599         mCurrentContext->EndRenderPass(mTextureDependencyChecker);
600
601         // This sync object is to enable cpu to wait for rendering to complete, not gpu.
602         // It's only needed for reading the framebuffer texture in the client.
603         auto syncObject = const_cast<GLES::SyncObject*>(static_cast<const GLES::SyncObject*>(cmd.endRenderPass.syncObject));
604         if(syncObject)
605         {
606           syncObject->InitializeResource();
607         }
608         break;
609       }
610       case GLES::CommandType::PRESENT_RENDER_TARGET:
611       {
612         ResolvePresentRenderTarget(cmd.presentRenderTarget.targetToPresent);
613
614         // The command buffer will be pushed into the queue of presentation command buffers
615         // for further reuse.
616         if(commandBuffer.GetCreateInfo().fixedCapacity == 1)
617         {
618           mPresentationCommandBuffers.push(&commandBuffer);
619         }
620         break;
621       }
622       case GLES::CommandType::EXECUTE_COMMAND_BUFFERS:
623       {
624         // Process secondary command buffers
625         // todo: check validity of the secondaries
626         //       there are operations which are illigal to be done
627         //       within secondaries.
628         auto buffers = cmd.executeCommandBuffers.buffers.Ptr();
629         for(auto j = 0u; j < cmd.executeCommandBuffers.buffersCount; ++j)
630         {
631           auto& buf = buffers[j];
632           ProcessCommandBuffer(*static_cast<const GLES::CommandBuffer*>(buf));
633         }
634         break;
635       }
636       case GLES::CommandType::DRAW_NATIVE:
637       {
638         auto* info = &cmd.drawNative.drawNativeInfo;
639
640         mCurrentContext->PrepareForNativeRendering();
641
642         if(info->glesNativeInfo.eglSharedContextStoragePointer)
643         {
644           auto* anyContext = reinterpret_cast<std::any*>(info->glesNativeInfo.eglSharedContextStoragePointer);
645           *anyContext      = mSharedContext;
646         }
647
648         CallbackBase::ExecuteReturn<bool>(*info->callback, info->userData);
649
650         mCurrentContext->RestoreFromNativeRendering();
651         break;
652       }
653     }
654   }
655 }
656
657 void EglGraphicsController::ProcessCommandQueues()
658 {
659   DUMP_FRAME_START();
660
661   while(!mCommandQueue.empty())
662   {
663     auto cmdBuf = mCommandQueue.front();
664     mCommandQueue.pop();
665     DUMP_FRAME_COMMAND_BUFFER(cmdBuf);
666     ProcessCommandBuffer(*cmdBuf);
667   }
668
669   DUMP_FRAME_END();
670 }
671
672 void EglGraphicsController::ProcessTextureUpdateQueue()
673 {
674   while(!mTextureUpdateRequests.empty())
675   {
676     TextureUpdateRequest& request = mTextureUpdateRequests.front();
677
678     auto& info   = request.first;
679     auto& source = request.second;
680
681     switch(source.sourceType)
682     {
683       case Graphics::TextureUpdateSourceInfo::Type::MEMORY:
684       case Graphics::TextureUpdateSourceInfo::Type::PIXEL_DATA:
685       {
686         // GPU memory must be already allocated.
687
688         // Check if it needs conversion
689         auto*       texture            = static_cast<GLES::Texture*>(info.dstTexture);
690         const auto& createInfo         = texture->GetCreateInfo();
691         auto        srcFormat          = GLES::GLTextureFormatType(info.srcFormat).format;
692         auto        srcType            = GLES::GLTextureFormatType(info.srcFormat).type;
693         auto        destInternalFormat = GLES::GLTextureFormatType(createInfo.format).internalFormat;
694         auto        destFormat         = GLES::GLTextureFormatType(createInfo.format).format;
695
696         // From render-texture.cpp
697         const bool isSubImage(info.dstOffset2D.x != 0 || info.dstOffset2D.y != 0 ||
698                               info.srcExtent2D.width != (createInfo.size.width / (1 << info.level)) ||
699                               info.srcExtent2D.height != (createInfo.size.height / (1 << info.level)));
700
701         uint8_t* sourceBuffer;
702         if(source.sourceType == Graphics::TextureUpdateSourceInfo::Type::MEMORY)
703         {
704           sourceBuffer = reinterpret_cast<uint8_t*>(source.memorySource.memory);
705         }
706         else
707         {
708           // Get buffer of PixelData
709           Dali::Integration::PixelDataBuffer pixelBufferData = Dali::Integration::GetPixelDataBuffer(source.pixelDataSource.pixelData);
710
711           sourceBuffer = pixelBufferData.buffer + info.srcOffset;
712         }
713
714         auto                 sourceStride = info.srcStride;
715         std::vector<uint8_t> tempBuffer;
716
717         if(mGlAbstraction->TextureRequiresConverting(srcFormat, destFormat, isSubImage))
718         {
719           // Convert RGB to RGBA if necessary.
720           if(texture->TryConvertPixelData(source.memorySource.memory, info.srcFormat, createInfo.format, info.srcSize, info.srcStride, info.srcExtent2D.width, info.srcExtent2D.height, tempBuffer))
721           {
722             sourceBuffer = &tempBuffer[0];
723             sourceStride = 0u; // Converted buffer compacted. make stride as 0.
724             srcFormat    = destFormat;
725             srcType      = GLES::GLTextureFormatType(createInfo.format).type;
726           }
727         }
728
729         // Calculate the maximum mipmap level for the texture
730         texture->SetMaxMipMapLevel(std::max(texture->GetMaxMipMapLevel(), info.level));
731
732         GLenum bindTarget{GL_TEXTURE_2D};
733         GLenum target{GL_TEXTURE_2D};
734
735         if(createInfo.textureType == Graphics::TextureType::TEXTURE_CUBEMAP)
736         {
737           bindTarget = GL_TEXTURE_CUBE_MAP;
738           target     = GL_TEXTURE_CUBE_MAP_POSITIVE_X + info.layer;
739         }
740
741         mGlAbstraction->PixelStorei(GL_UNPACK_ALIGNMENT, 1);
742         mGlAbstraction->PixelStorei(GL_UNPACK_ROW_LENGTH, sourceStride);
743
744         mCurrentContext->BindTexture(bindTarget, texture->GetTextureTypeId(), texture->GetGLTexture());
745
746         if(!isSubImage)
747         {
748           if(!texture->IsCompressed())
749           {
750             mGlAbstraction->TexImage2D(target,
751                                        info.level,
752                                        destInternalFormat,
753                                        info.srcExtent2D.width,
754                                        info.srcExtent2D.height,
755                                        0,
756                                        srcFormat,
757                                        srcType,
758                                        sourceBuffer);
759           }
760           else
761           {
762             mGlAbstraction->CompressedTexImage2D(target,
763                                                  info.level,
764                                                  destInternalFormat,
765                                                  info.srcExtent2D.width,
766                                                  info.srcExtent2D.height,
767                                                  0,
768                                                  info.srcSize,
769                                                  sourceBuffer);
770           }
771         }
772         else
773         {
774           if(!texture->IsCompressed())
775           {
776             mGlAbstraction->TexSubImage2D(target,
777                                           info.level,
778                                           info.dstOffset2D.x,
779                                           info.dstOffset2D.y,
780                                           info.srcExtent2D.width,
781                                           info.srcExtent2D.height,
782                                           srcFormat,
783                                           srcType,
784                                           sourceBuffer);
785           }
786           else
787           {
788             mGlAbstraction->CompressedTexSubImage2D(target,
789                                                     info.level,
790                                                     info.dstOffset2D.x,
791                                                     info.dstOffset2D.y,
792                                                     info.srcExtent2D.width,
793                                                     info.srcExtent2D.height,
794                                                     srcFormat,
795                                                     info.srcSize,
796                                                     sourceBuffer);
797           }
798         }
799
800         if(source.sourceType == Graphics::TextureUpdateSourceInfo::Type::MEMORY)
801         {
802           // free staging memory
803           free(source.memorySource.memory);
804         }
805         break;
806       }
807       default:
808       {
809         // TODO: other sources
810         break;
811       }
812     }
813
814     mTextureUpdateRequests.pop();
815   }
816 }
817
818 void EglGraphicsController::UpdateTextures(const std::vector<TextureUpdateInfo>&       updateInfoList,
819                                            const std::vector<TextureUpdateSourceInfo>& sourceList)
820 {
821   // Store updates
822   for(auto& info : updateInfoList)
823   {
824     mTextureUpdateRequests.push(std::make_pair(info, sourceList[info.srcReference]));
825     auto& pair = mTextureUpdateRequests.back();
826     switch(pair.second.sourceType)
827     {
828       case Graphics::TextureUpdateSourceInfo::Type::MEMORY:
829       {
830         auto& info   = pair.first;
831         auto& source = pair.second;
832
833         // allocate staging memory and copy the data
834         // TODO: using PBO with GLES3, this is just naive
835         // oldschool way
836
837         uint8_t* stagingBuffer = reinterpret_cast<uint8_t*>(malloc(info.srcSize));
838
839         uint8_t* srcMemory = &reinterpret_cast<uint8_t*>(source.memorySource.memory)[info.srcOffset];
840
841         std::copy(srcMemory, srcMemory + info.srcSize, stagingBuffer);
842
843         mTextureUploadTotalCPUMemoryUsed += info.srcSize;
844
845         // store staging buffer
846         source.memorySource.memory = stagingBuffer;
847         break;
848       }
849       case Graphics::TextureUpdateSourceInfo::Type::PIXEL_DATA:
850       {
851         // Increase CPU memory usage since ownership of PixelData is now on mTextureUpdateRequests.
852         mTextureUploadTotalCPUMemoryUsed += info.srcSize;
853         break;
854       }
855       case Graphics::TextureUpdateSourceInfo::Type::BUFFER:
856       {
857         // TODO, with PBO support
858         break;
859       }
860       case Graphics::TextureUpdateSourceInfo::Type::TEXTURE:
861       {
862         // TODO texture 2 texture in-GPU copy
863         break;
864       }
865     }
866   }
867
868   // If upload buffer exceeds maximum size, flush.
869   if(mTextureUploadTotalCPUMemoryUsed > TEXTURE_UPLOAD_MAX_BUFER_SIZE_MB * 1024 * 1024)
870   {
871     Flush();
872     mTextureUploadTotalCPUMemoryUsed = 0;
873   }
874 }
875
876 void EglGraphicsController::ProcessTextureMipmapGenerationQueue()
877 {
878   while(!mTextureMipmapGenerationRequests.empty())
879   {
880     auto* texture = mTextureMipmapGenerationRequests.front();
881
882     mCurrentContext->BindTexture(texture->GetGlTarget(), texture->GetTextureTypeId(), texture->GetGLTexture());
883     mCurrentContext->GenerateMipmap(texture->GetGlTarget());
884
885     mTextureMipmapGenerationRequests.pop();
886   }
887 }
888
889 void EglGraphicsController::GenerateTextureMipmaps(const Graphics::Texture& texture)
890 {
891   mTextureMipmapGenerationRequests.push(static_cast<const GLES::Texture*>(&texture));
892 }
893
894 Graphics::UniquePtr<Memory> EglGraphicsController::MapBufferRange(const MapBufferInfo& mapInfo)
895 {
896   mGraphics->ActivateResourceContext();
897
898   // Mapping buffer requires the object to be created NOW
899   // Workaround - flush now, otherwise there will be given a staging buffer
900   // in case when the buffer is not there yet
901   ProcessCreateQueues();
902
903   if(GetGLESVersion() < GLES::GLESVersion::GLES_30)
904   {
905     return Graphics::UniquePtr<Memory>(new GLES::Memory2(mapInfo, *this));
906   }
907   else
908   {
909     return Graphics::UniquePtr<Memory>(new GLES::Memory3(mapInfo, *this));
910   }
911 }
912
913 bool EglGraphicsController::GetProgramParameter(Graphics::Program& program, uint32_t parameterId, void* outData)
914 {
915   return static_cast<GLES::Program*>(&program)->GetImplementation()->GetParameter(parameterId, outData);
916 }
917
918 GLES::PipelineCache& EglGraphicsController::GetPipelineCache() const
919 {
920   return *mPipelineCache;
921 }
922
923 } // namespace Dali::Graphics