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