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