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