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