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