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