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