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