89a6010a299d779908ac8e1c12882e2b8b57b3b4
[platform/core/uifw/dali-adaptor.git] / dali / internal / graphics / gles-impl / gles-context.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
18 #include "gles-context.h"
19 #include <dali/integration-api/adaptor-framework/render-surface-interface.h>
20 #include <dali/integration-api/gl-abstraction.h>
21 #include <dali/integration-api/gl-defines.h>
22 #include <dali/internal/graphics/common/graphics-interface.h>
23
24 #include "egl-graphics-controller.h"
25 #include "gles-graphics-buffer.h"
26 #include "gles-graphics-pipeline.h"
27 #include "gles-graphics-program.h"
28 #include "gles-graphics-render-pass.h"
29 #include "gles-graphics-render-target.h"
30
31 namespace Dali::Graphics::GLES
32 {
33 struct Context::Impl
34 {
35   Impl(EglGraphicsController& controller)
36   : mController(controller)
37   {
38   }
39
40   ~Impl() = default;
41
42   /**
43    * Sets the initial GL state.
44    */
45   void InitializeGlState()
46   {
47     auto& gl = *mController.GetGL();
48
49     mGlStateCache.mClearColorSet        = false;
50     mGlStateCache.mColorMask            = true;
51     mGlStateCache.mStencilMask          = 0xFF;
52     mGlStateCache.mBlendEnabled         = false;
53     mGlStateCache.mDepthBufferEnabled   = false;
54     mGlStateCache.mDepthMaskEnabled     = false;
55     mGlStateCache.mScissorTestEnabled   = false;
56     mGlStateCache.mStencilBufferEnabled = false;
57
58     gl.Disable(GL_DITHER);
59
60     mGlStateCache.mBoundArrayBufferId        = 0;
61     mGlStateCache.mBoundElementArrayBufferId = 0;
62     mGlStateCache.mActiveTextureUnit         = 0;
63
64     mGlStateCache.mBlendFuncSeparateSrcRGB   = BlendFactor::ONE;
65     mGlStateCache.mBlendFuncSeparateDstRGB   = BlendFactor::ZERO;
66     mGlStateCache.mBlendFuncSeparateSrcAlpha = BlendFactor::ONE;
67     mGlStateCache.mBlendFuncSeparateDstAlpha = BlendFactor::ZERO;
68
69     // initial state is GL_FUNC_ADD for both RGB and Alpha blend modes
70     mGlStateCache.mBlendEquationSeparateModeRGB   = BlendOp::ADD;
71     mGlStateCache.mBlendEquationSeparateModeAlpha = BlendOp::ADD;
72
73     mGlStateCache.mCullFaceMode = CullMode::NONE; //By default cullface is disabled, front face is set to CCW and cull face is set to back
74
75     //Initialze vertex attribute cache
76     memset(&mGlStateCache.mVertexAttributeCachedState, 0, sizeof(mGlStateCache.mVertexAttributeCachedState));
77     memset(&mGlStateCache.mVertexAttributeCurrentState, 0, sizeof(mGlStateCache.mVertexAttributeCurrentState));
78
79     //Initialize bound 2d texture cache
80     memset(&mGlStateCache.mBoundTextureId, 0, sizeof(mGlStateCache.mBoundTextureId));
81
82     mGlStateCache.mFrameBufferStateCache.Reset();
83   }
84
85   /**
86    * Flushes vertex attribute location changes to the driver
87    */
88   void FlushVertexAttributeLocations()
89   {
90     auto& gl = *mController.GetGL();
91
92     for(unsigned int i = 0; i < MAX_ATTRIBUTE_CACHE_SIZE; ++i)
93     {
94       // see if the cached state is different to the actual state
95       if(mGlStateCache.mVertexAttributeCurrentState[i] != mGlStateCache.mVertexAttributeCachedState[i])
96       {
97         // it's different so make the change to the driver and update the cached state
98         mGlStateCache.mVertexAttributeCurrentState[i] = mGlStateCache.mVertexAttributeCachedState[i];
99
100         if(mGlStateCache.mVertexAttributeCurrentState[i])
101         {
102           gl.EnableVertexAttribArray(i);
103         }
104         else
105         {
106           gl.DisableVertexAttribArray(i);
107         }
108       }
109     }
110   }
111
112   /**
113    * Either enables or disables a vertex attribute location in the cache
114    * The cahnges won't take affect until FlushVertexAttributeLocations is called
115    * @param location attribute location
116    * @param state attribute state
117    */
118   void SetVertexAttributeLocation(unsigned int location, bool state)
119   {
120     auto& gl = *mController.GetGL();
121
122     if(location >= MAX_ATTRIBUTE_CACHE_SIZE)
123     {
124       // not cached, make the gl call through context
125       if(state)
126       {
127         gl.EnableVertexAttribArray(location);
128       }
129       else
130       {
131         gl.DisableVertexAttribArray(location);
132       }
133     }
134     else
135     {
136       // set the cached state, it will be set at the next draw call
137       // if it's different from the current driver state
138       mGlStateCache.mVertexAttributeCachedState[location] = state;
139     }
140   }
141
142   EglGraphicsController& mController;
143
144   const GLES::PipelineImpl* mCurrentPipeline{nullptr}; ///< Currently bound pipeline
145   const GLES::PipelineImpl* mNewPipeline{nullptr};     ///< New pipeline to be set on flush
146
147   std::vector<Graphics::TextureBinding> mCurrentTextureBindings{};
148   std::vector<Graphics::SamplerBinding> mCurrentSamplerBindings{};
149   GLES::IndexBufferBindingDescriptor    mCurrentIndexBufferBinding{};
150
151   struct VertexBufferBinding
152   {
153     GLES::Buffer* buffer{nullptr};
154     uint32_t      offset{0u};
155   };
156
157   // Currently bound buffers
158   std::vector<VertexBufferBindingDescriptor> mCurrentVertexBufferBindings{};
159
160   // Currently bound UBOs (check if it's needed per program!)
161   std::vector<UniformBufferBindingDescriptor> mCurrentUBOBindings{};
162   UniformBufferBindingDescriptor              mCurrentStandaloneUBOBinding{};
163
164   // Current render pass and render target
165   const GLES::RenderTarget* mCurrentRenderTarget{nullptr};
166   const GLES::RenderPass*   mCurrentRenderPass{nullptr};
167
168   GLStateCache mGlStateCache{}; ///< GL status cache
169
170   bool mGlContextCreated{false}; ///< True if the OpenGL context has been created
171 };
172
173 Context::Context(EglGraphicsController& controller)
174 {
175   mImpl = std::make_unique<Impl>(controller);
176 }
177
178 Context::~Context() = default;
179
180 void Context::Flush(bool reset, const GLES::DrawCallDescriptor& drawCall)
181 {
182   auto& gl = *mImpl->mController.GetGL();
183
184   // early out if neither current nor new pipelines are set
185   // this behaviour may be valid so no assert
186   if(!mImpl->mCurrentPipeline && !mImpl->mNewPipeline)
187   {
188     return;
189   }
190
191   // Execute states if pipeline is changed
192   const auto currentProgram = mImpl->mCurrentPipeline ? static_cast<const GLES::Program*>(mImpl->mCurrentPipeline->GetCreateInfo().programState->program) : nullptr;
193
194   // case when new pipeline has been set
195   const GLES::Program* newProgram = nullptr;
196
197   if(mImpl->mNewPipeline)
198   {
199     newProgram = static_cast<const GLES::Program*>(mImpl->mNewPipeline->GetCreateInfo().programState->program);
200   }
201
202   if(mImpl->mNewPipeline && mImpl->mCurrentPipeline != mImpl->mNewPipeline)
203   {
204     if(!currentProgram || currentProgram->GetImplementation()->GetGlProgram() != newProgram->GetImplementation()->GetGlProgram())
205     {
206       mImpl->mNewPipeline->Bind(newProgram->GetImplementation()->GetGlProgram());
207     }
208
209     // Blend state
210     ResolveBlendState();
211
212     // Resolve rasterization state
213     ResolveRasterizationState();
214   }
215
216   // Resolve uniform buffers
217   ResolveUniformBuffers();
218
219   // Bind textures
220   // Map binding# to sampler location
221   const auto& reflection = !newProgram ? currentProgram->GetReflection() : newProgram->GetReflection();
222   const auto& samplers   = reflection.GetSamplers();
223   for(const auto& binding : mImpl->mCurrentTextureBindings)
224   {
225     auto texture = const_cast<GLES::Texture*>(static_cast<const GLES::Texture*>(binding.texture));
226
227     // Texture may not have been initialized yet...(tbm_surface timing issue?)
228     if(!texture->GetGLTexture())
229     {
230       // Attempt to reinitialize
231       // @todo need to put this somewhere else where it isn't const.
232       // Maybe post it back on end of initialize queue if initialization fails?
233       texture->InitializeResource();
234     }
235
236     texture->Bind(binding);
237
238     texture->Prepare(); // @todo also non-const.
239
240     if(binding.binding < samplers.size()) // binding maps to texture unit. (texture bindings should also be in binding order)
241     {
242       // Offset is set to the lexical offset within the frag shader, map it to the texture unit
243       // @todo Explicitly set the texture unit through the graphics interface
244       gl.Uniform1i(samplers[binding.binding].location, samplers[binding.binding].offset);
245     }
246   }
247
248   // for each attribute bind vertices
249   const auto& pipelineState = mImpl->mNewPipeline ? mImpl->mNewPipeline->GetCreateInfo() : mImpl->mCurrentPipeline->GetCreateInfo();
250   const auto& vi            = pipelineState.vertexInputState;
251   for(const auto& attr : vi->attributes)
252   {
253     // Enable location
254     mImpl->SetVertexAttributeLocation(attr.location, true);
255
256     const auto& bufferSlot    = mImpl->mCurrentVertexBufferBindings[attr.binding];
257     const auto& bufferBinding = vi->bufferBindings[attr.binding];
258
259     auto glesBuffer = bufferSlot.buffer->GetGLBuffer();
260
261     // Bind buffer
262     BindBuffer(GL_ARRAY_BUFFER, glesBuffer);
263
264     gl.VertexAttribPointer(attr.location,
265                            GLVertexFormat(attr.format).size,
266                            GLVertexFormat(attr.format).format,
267                            GL_FALSE,
268                            bufferBinding.stride,
269                            reinterpret_cast<void*>(attr.offset));
270   }
271
272   // Resolve topology
273   const auto& ia = pipelineState.inputAssemblyState;
274
275   // Bind uniforms
276
277   // Resolve draw call
278   switch(drawCall.type)
279   {
280     case DrawCallDescriptor::Type::DRAW:
281     {
282       mImpl->mGlStateCache.mFrameBufferStateCache.DrawOperation(mImpl->mGlStateCache.mColorMask,
283                                                                 mImpl->mGlStateCache.DepthBufferWriteEnabled(),
284                                                                 mImpl->mGlStateCache.StencilBufferWriteEnabled());
285       mImpl->FlushVertexAttributeLocations();
286
287       gl.DrawArrays(GLESTopology(ia->topology),
288                     drawCall.draw.firstVertex,
289                     drawCall.draw.vertexCount);
290       break;
291     }
292     case DrawCallDescriptor::Type::DRAW_INDEXED:
293     {
294       const auto& binding = mImpl->mCurrentIndexBufferBinding;
295       BindBuffer(GL_ELEMENT_ARRAY_BUFFER, binding.buffer->GetGLBuffer());
296
297       mImpl->mGlStateCache.mFrameBufferStateCache.DrawOperation(mImpl->mGlStateCache.mColorMask,
298                                                                 mImpl->mGlStateCache.DepthBufferWriteEnabled(),
299                                                                 mImpl->mGlStateCache.StencilBufferWriteEnabled());
300       mImpl->FlushVertexAttributeLocations();
301
302       auto indexBufferFormat = GLIndexFormat(binding.format).format;
303       gl.DrawElements(GLESTopology(ia->topology),
304                       drawCall.drawIndexed.indexCount,
305                       indexBufferFormat,
306                       reinterpret_cast<void*>(binding.offset));
307       break;
308     }
309     case DrawCallDescriptor::Type::DRAW_INDEXED_INDIRECT:
310     {
311       break;
312     }
313   }
314
315   ClearState();
316
317   // Change pipeline
318   if(mImpl->mNewPipeline)
319   {
320     mImpl->mCurrentPipeline = mImpl->mNewPipeline;
321     mImpl->mNewPipeline     = nullptr;
322   }
323 }
324
325 void Context::BindTextures(const std::vector<Graphics::TextureBinding>& bindings)
326 {
327   // for each texture allocate slot
328   for(const auto& binding : bindings)
329   {
330     // Resize binding array if needed
331     if(mImpl->mCurrentTextureBindings.size() <= binding.binding)
332     {
333       mImpl->mCurrentTextureBindings.resize(binding.binding + 1);
334     }
335     // Store the binding details
336     mImpl->mCurrentTextureBindings[binding.binding] = binding;
337   }
338 }
339
340 void Context::BindVertexBuffers(const std::vector<GLES::VertexBufferBindingDescriptor>& bindings)
341 {
342   if(bindings.size() > mImpl->mCurrentVertexBufferBindings.size())
343   {
344     mImpl->mCurrentVertexBufferBindings.resize(bindings.size());
345   }
346   // Copy only set slots
347   std::copy_if(bindings.begin(), bindings.end(), mImpl->mCurrentVertexBufferBindings.begin(), [](auto& item) {
348     return (nullptr != item.buffer);
349   });
350 }
351
352 void Context::BindIndexBuffer(const IndexBufferBindingDescriptor& indexBufferBinding)
353 {
354   mImpl->mCurrentIndexBufferBinding = indexBufferBinding;
355 }
356
357 void Context::BindPipeline(const GLES::Pipeline* newPipeline)
358 {
359   DALI_ASSERT_ALWAYS(newPipeline && "Invalid pipeline");
360   mImpl->mNewPipeline = &newPipeline->GetPipeline();
361 }
362
363 void Context::BindUniformBuffers(const std::vector<UniformBufferBindingDescriptor>& uboBindings,
364                                  const UniformBufferBindingDescriptor&              standaloneBindings)
365 {
366   if(standaloneBindings.buffer)
367   {
368     mImpl->mCurrentStandaloneUBOBinding = standaloneBindings;
369   }
370
371   if(uboBindings.size() >= mImpl->mCurrentUBOBindings.size())
372   {
373     mImpl->mCurrentUBOBindings.resize(uboBindings.size() + 1);
374   }
375
376   auto it = uboBindings.begin();
377   for(auto i = 0u; i < uboBindings.size(); ++i)
378   {
379     if(it->buffer)
380     {
381       mImpl->mCurrentUBOBindings[i] = *it;
382     }
383   }
384 }
385
386 void Context::ResolveBlendState()
387 {
388   const auto& currentBlendState = mImpl->mCurrentPipeline ? mImpl->mCurrentPipeline->GetCreateInfo().colorBlendState : nullptr;
389   const auto& newBlendState     = mImpl->mNewPipeline->GetCreateInfo().colorBlendState;
390
391   // TODO: prevent leaking the state
392   if(!newBlendState)
393   {
394     return;
395   }
396
397   auto& gl = *mImpl->mController.GetGL();
398
399   if(!currentBlendState || currentBlendState->blendEnable != newBlendState->blendEnable)
400   {
401     if(newBlendState->blendEnable != mImpl->mGlStateCache.mBlendEnabled)
402     {
403       mImpl->mGlStateCache.mBlendEnabled = newBlendState->blendEnable;
404       newBlendState->blendEnable ? gl.Enable(GL_BLEND) : gl.Disable(GL_BLEND);
405     }
406   }
407
408   if(!newBlendState->blendEnable)
409   {
410     return;
411   }
412
413   BlendFactor newSrcRGB(newBlendState->srcColorBlendFactor);
414   BlendFactor newDstRGB(newBlendState->dstColorBlendFactor);
415   BlendFactor newSrcAlpha(newBlendState->srcAlphaBlendFactor);
416   BlendFactor newDstAlpha(newBlendState->dstAlphaBlendFactor);
417
418   if(!currentBlendState ||
419      currentBlendState->srcColorBlendFactor != newSrcRGB ||
420      currentBlendState->dstColorBlendFactor != newDstRGB ||
421      currentBlendState->srcAlphaBlendFactor != newSrcAlpha ||
422      currentBlendState->dstAlphaBlendFactor != newDstAlpha)
423   {
424     if((mImpl->mGlStateCache.mBlendFuncSeparateSrcRGB != newSrcRGB) ||
425        (mImpl->mGlStateCache.mBlendFuncSeparateDstRGB != newDstRGB) ||
426        (mImpl->mGlStateCache.mBlendFuncSeparateSrcAlpha != newSrcAlpha) ||
427        (mImpl->mGlStateCache.mBlendFuncSeparateDstAlpha != newDstAlpha))
428     {
429       mImpl->mGlStateCache.mBlendFuncSeparateSrcRGB   = newSrcRGB;
430       mImpl->mGlStateCache.mBlendFuncSeparateDstRGB   = newDstRGB;
431       mImpl->mGlStateCache.mBlendFuncSeparateSrcAlpha = newSrcAlpha;
432       mImpl->mGlStateCache.mBlendFuncSeparateDstAlpha = newDstAlpha;
433
434       if(newSrcRGB == newSrcAlpha && newDstRGB == newDstAlpha)
435       {
436         gl.BlendFunc(GLBlendFunc(newSrcRGB), GLBlendFunc(newDstRGB));
437       }
438       else
439       {
440         gl.BlendFuncSeparate(GLBlendFunc(newSrcRGB), GLBlendFunc(newDstRGB), GLBlendFunc(newSrcAlpha), GLBlendFunc(newDstAlpha));
441       }
442     }
443   }
444
445   if(!currentBlendState ||
446      currentBlendState->colorBlendOp != newBlendState->colorBlendOp ||
447      currentBlendState->alphaBlendOp != newBlendState->alphaBlendOp)
448   {
449     if(mImpl->mGlStateCache.mBlendEquationSeparateModeRGB != newBlendState->colorBlendOp ||
450        mImpl->mGlStateCache.mBlendEquationSeparateModeAlpha != newBlendState->alphaBlendOp)
451     {
452       mImpl->mGlStateCache.mBlendEquationSeparateModeRGB   = newBlendState->colorBlendOp;
453       mImpl->mGlStateCache.mBlendEquationSeparateModeAlpha = newBlendState->alphaBlendOp;
454
455       if(newBlendState->colorBlendOp == newBlendState->alphaBlendOp)
456       {
457         gl.BlendEquation(GLBlendOp(newBlendState->colorBlendOp));
458       }
459       else
460       {
461         gl.BlendEquationSeparate(GLBlendOp(newBlendState->colorBlendOp), GLBlendOp(newBlendState->alphaBlendOp));
462       }
463     }
464   }
465 }
466
467 void Context::ResolveRasterizationState()
468 {
469   const auto& currentRasterizationState = mImpl->mCurrentPipeline ? mImpl->mCurrentPipeline->GetCreateInfo().rasterizationState : nullptr;
470   const auto& newRasterizationState     = mImpl->mNewPipeline->GetCreateInfo().rasterizationState;
471
472   // TODO: prevent leaking the state
473   if(!newRasterizationState)
474   {
475     return;
476   }
477
478   auto& gl = *mImpl->mController.GetGL();
479
480   if(!currentRasterizationState ||
481      currentRasterizationState->cullMode != newRasterizationState->cullMode)
482   {
483     if(mImpl->mGlStateCache.mCullFaceMode != newRasterizationState->cullMode)
484     {
485       mImpl->mGlStateCache.mCullFaceMode = newRasterizationState->cullMode;
486       if(newRasterizationState->cullMode == CullMode::NONE)
487       {
488         gl.Disable(GL_CULL_FACE);
489       }
490       else
491       {
492         gl.Enable(GL_CULL_FACE);
493         gl.CullFace(GLCullMode(newRasterizationState->cullMode));
494       }
495     }
496   }
497   // TODO: implement polygon mode (fill, line, points)
498   //       seems like we don't support it (no glPolygonMode())
499 }
500
501 void Context::ResolveUniformBuffers()
502 {
503   // Resolve standalone uniforms if we have binding
504   if(mImpl->mCurrentStandaloneUBOBinding.buffer)
505   {
506     ResolveStandaloneUniforms();
507   }
508 }
509
510 void Context::ResolveStandaloneUniforms()
511 {
512   // Find reflection for program
513   const auto program = static_cast<const GLES::Program*>(mImpl->mNewPipeline->GetCreateInfo().programState->program);
514   const auto ptr     = reinterpret_cast<const char*>(mImpl->mCurrentStandaloneUBOBinding.buffer->GetCPUAllocatedAddress()) + mImpl->mCurrentStandaloneUBOBinding.offset;
515
516   // Update program uniforms
517   program->GetImplementation()->UpdateStandaloneUniformBlock(ptr);
518 }
519
520 void Context::BeginRenderPass(const BeginRenderPassDescriptor& renderPassBegin)
521 {
522   auto& renderPass   = *renderPassBegin.renderPass;
523   auto& renderTarget = *renderPassBegin.renderTarget;
524
525   const auto& targetInfo = renderTarget.GetCreateInfo();
526
527   auto& gl = *mImpl->mController.GetGL();
528
529   if(targetInfo.surface)
530   {
531     // Bind surface FB
532     BindFrameBuffer(GL_FRAMEBUFFER, 0);
533   }
534   else if(targetInfo.framebuffer)
535   {
536     // bind framebuffer and swap.
537     renderTarget.GetFramebuffer()->Bind();
538   }
539
540   // clear (ideally cache the setup)
541
542   // In GL we assume that the last attachment is depth/stencil (we may need
543   // to cache extra information inside GLES RenderTarget if we want to be
544   // more specific in case of MRT)
545
546   const auto& attachments = *renderPass.GetCreateInfo().attachments;
547   const auto& color0      = attachments[0];
548   GLuint      mask        = 0;
549   if(color0.loadOp == AttachmentLoadOp::CLEAR)
550   {
551     mask |= GL_COLOR_BUFFER_BIT;
552
553     // Set clear color
554     // Something goes wrong here if Alpha mask is GL_TRUE
555     ColorMask(true);
556
557     if(!mImpl->mGlStateCache.mClearColorSet ||
558        mImpl->mGlStateCache.mClearColor.r != renderPassBegin.clearValues[0].color.r ||
559        mImpl->mGlStateCache.mClearColor.g != renderPassBegin.clearValues[0].color.g ||
560        mImpl->mGlStateCache.mClearColor.b != renderPassBegin.clearValues[0].color.b ||
561        mImpl->mGlStateCache.mClearColor.a != renderPassBegin.clearValues[0].color.a)
562     {
563       gl.ClearColor(renderPassBegin.clearValues[0].color.r,
564                     renderPassBegin.clearValues[0].color.g,
565                     renderPassBegin.clearValues[0].color.b,
566                     renderPassBegin.clearValues[0].color.a);
567
568       mImpl->mGlStateCache.mClearColorSet = true;
569       mImpl->mGlStateCache.mClearColor    = Vector4(renderPassBegin.clearValues[0].color.r,
570                                                  renderPassBegin.clearValues[0].color.g,
571                                                  renderPassBegin.clearValues[0].color.b,
572                                                  renderPassBegin.clearValues[0].color.a);
573     }
574   }
575
576   // check for depth stencil
577   if(attachments.size() > 1)
578   {
579     const auto& depthStencil = attachments.back();
580     if(depthStencil.loadOp == AttachmentLoadOp::CLEAR)
581     {
582       if(!mImpl->mGlStateCache.mDepthMaskEnabled)
583       {
584         mImpl->mGlStateCache.mDepthMaskEnabled = true;
585         gl.DepthMask(true);
586       }
587       mask |= GL_DEPTH_BUFFER_BIT;
588     }
589     if(depthStencil.stencilLoadOp == AttachmentLoadOp::CLEAR)
590     {
591       if(mImpl->mGlStateCache.mStencilMask != 0xFF)
592       {
593         mImpl->mGlStateCache.mStencilMask = 0xFF;
594         gl.StencilMask(0xFF);
595       }
596       mask |= GL_STENCIL_BUFFER_BIT;
597     }
598   }
599
600   SetScissorTestEnabled(true);
601   gl.Scissor(renderPassBegin.renderArea.x, renderPassBegin.renderArea.y, renderPassBegin.renderArea.width, renderPassBegin.renderArea.height);
602   ClearBuffer(mask, true);
603   SetScissorTestEnabled(false);
604
605   mImpl->mCurrentRenderPass   = &renderPass;
606   mImpl->mCurrentRenderTarget = &renderTarget;
607 }
608
609 void Context::EndRenderPass()
610 {
611   if(mImpl->mCurrentRenderTarget)
612   {
613     if(mImpl->mCurrentRenderTarget->GetFramebuffer())
614     {
615       auto& gl = *mImpl->mController.GetGL();
616       gl.Flush();
617     }
618   }
619 }
620
621 void Context::ClearState()
622 {
623   mImpl->mCurrentTextureBindings.clear();
624 }
625
626 void Context::ColorMask(bool enabled)
627 {
628   if(enabled != mImpl->mGlStateCache.mColorMask)
629   {
630     mImpl->mGlStateCache.mColorMask = enabled;
631
632     auto& gl = *mImpl->mController.GetGL();
633     gl.ColorMask(enabled, enabled, enabled, enabled);
634   }
635 }
636
637 void Context::ClearStencilBuffer()
638 {
639   ClearBuffer(GL_STENCIL_BUFFER_BIT, false);
640 }
641
642 void Context::ClearDepthBuffer()
643 {
644   ClearBuffer(GL_DEPTH_BUFFER_BIT, false);
645 }
646
647 void Context::ClearBuffer(uint32_t mask, bool forceClear)
648 {
649   mask = mImpl->mGlStateCache.mFrameBufferStateCache.GetClearMask(mask, forceClear, mImpl->mGlStateCache.mScissorTestEnabled);
650   if(mask > 0)
651   {
652     auto& gl = *mImpl->mController.GetGL();
653     gl.Clear(mask);
654   }
655 }
656
657 void Context::InvalidateDepthStencilBuffers()
658 {
659   auto& gl = *mImpl->mController.GetGL();
660
661   GLenum attachments[] = {GL_DEPTH, GL_STENCIL};
662   gl.InvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
663 }
664
665 void Context::SetScissorTestEnabled(bool scissorEnabled)
666 {
667   if(mImpl->mGlStateCache.mScissorTestEnabled != scissorEnabled)
668   {
669     mImpl->mGlStateCache.mScissorTestEnabled = scissorEnabled;
670
671     auto& gl = *mImpl->mController.GetGL();
672     if(scissorEnabled)
673     {
674       gl.Enable(GL_SCISSOR_TEST);
675     }
676     else
677     {
678       gl.Disable(GL_SCISSOR_TEST);
679     }
680   }
681 }
682
683 void Context::SetStencilTestEnable(bool stencilEnable)
684 {
685   if(stencilEnable != mImpl->mGlStateCache.mStencilBufferEnabled)
686   {
687     mImpl->mGlStateCache.mStencilBufferEnabled = stencilEnable;
688
689     auto& gl = *mImpl->mController.GetGL();
690     if(stencilEnable)
691     {
692       gl.Enable(GL_STENCIL_TEST);
693     }
694     else
695     {
696       gl.Disable(GL_STENCIL_TEST);
697     }
698   }
699 }
700
701 void Context::StencilMask(uint32_t writeMask)
702 {
703   if(writeMask != mImpl->mGlStateCache.mStencilMask)
704   {
705     mImpl->mGlStateCache.mStencilMask = writeMask;
706
707     auto& gl = *mImpl->mController.GetGL();
708     gl.StencilMask(writeMask);
709   }
710 }
711
712 void Context::StencilFunc(Graphics::CompareOp compareOp,
713                           uint32_t            reference,
714                           uint32_t            compareMask)
715 {
716   if(compareOp != mImpl->mGlStateCache.mStencilFunc ||
717      reference != mImpl->mGlStateCache.mStencilFuncRef ||
718      compareMask != mImpl->mGlStateCache.mStencilFuncMask)
719   {
720     mImpl->mGlStateCache.mStencilFunc     = compareOp;
721     mImpl->mGlStateCache.mStencilFuncRef  = reference;
722     mImpl->mGlStateCache.mStencilFuncMask = compareMask;
723
724     auto& gl = *mImpl->mController.GetGL();
725     gl.StencilFunc(GLCompareOp(compareOp).op, reference, compareMask);
726   }
727 }
728
729 void Context::StencilOp(Graphics::StencilOp failOp,
730                         Graphics::StencilOp depthFailOp,
731                         Graphics::StencilOp passOp)
732 {
733   if(failOp != mImpl->mGlStateCache.mStencilOpFail ||
734      depthFailOp != mImpl->mGlStateCache.mStencilOpDepthFail ||
735      passOp != mImpl->mGlStateCache.mStencilOpDepthPass)
736   {
737     mImpl->mGlStateCache.mStencilOpFail      = failOp;
738     mImpl->mGlStateCache.mStencilOpDepthFail = depthFailOp;
739     mImpl->mGlStateCache.mStencilOpDepthPass = passOp;
740
741     auto& gl = *mImpl->mController.GetGL();
742     gl.StencilOp(GLStencilOp(failOp).op, GLStencilOp(depthFailOp).op, GLStencilOp(passOp).op);
743   }
744 }
745
746 void Context::SetDepthCompareOp(Graphics::CompareOp compareOp)
747 {
748   if(compareOp != mImpl->mGlStateCache.mDepthFunction)
749   {
750     mImpl->mGlStateCache.mDepthFunction = compareOp;
751     auto& gl                            = *mImpl->mController.GetGL();
752     gl.DepthFunc(GLCompareOp(compareOp).op);
753   }
754 }
755
756 void Context::SetDepthTestEnable(bool depthTestEnable)
757 {
758   if(depthTestEnable != mImpl->mGlStateCache.mDepthBufferEnabled)
759   {
760     mImpl->mGlStateCache.mDepthBufferEnabled = depthTestEnable;
761
762     auto& gl = *mImpl->mController.GetGL();
763     if(depthTestEnable)
764     {
765       gl.Enable(GL_DEPTH_TEST);
766     }
767     else
768     {
769       gl.Disable(GL_DEPTH_TEST);
770     }
771   }
772 }
773
774 void Context::SetDepthWriteEnable(bool depthWriteEnable)
775 {
776   if(depthWriteEnable != mImpl->mGlStateCache.mDepthMaskEnabled)
777   {
778     mImpl->mGlStateCache.mDepthMaskEnabled = depthWriteEnable;
779
780     auto& gl = *mImpl->mController.GetGL();
781     gl.DepthMask(depthWriteEnable);
782   }
783 }
784
785 void Context::ActiveTexture(uint32_t textureBindingIndex)
786 {
787   if(mImpl->mGlStateCache.mActiveTextureUnit != textureBindingIndex)
788   {
789     mImpl->mGlStateCache.mActiveTextureUnit = textureBindingIndex;
790
791     auto& gl = *mImpl->mController.GetGL();
792     gl.ActiveTexture(GL_TEXTURE0 + textureBindingIndex);
793   }
794 }
795
796 void Context::BindTexture(GLenum target, BoundTextureType textureTypeId, uint32_t textureId)
797 {
798   uint32_t typeId = static_cast<uint32_t>(textureTypeId);
799   if(mImpl->mGlStateCache.mBoundTextureId[mImpl->mGlStateCache.mActiveTextureUnit][typeId] != textureId)
800   {
801     mImpl->mGlStateCache.mBoundTextureId[mImpl->mGlStateCache.mActiveTextureUnit][typeId] = textureId;
802
803     auto& gl = *mImpl->mController.GetGL();
804     gl.BindTexture(target, textureId);
805   }
806 }
807
808 void Context::GenerateMipmap(GLenum target)
809 {
810   auto& gl = *mImpl->mController.GetGL();
811   gl.GenerateMipmap(target);
812 }
813
814 void Context::BindBuffer(GLenum target, uint32_t bufferId)
815 {
816   if(mImpl->mGlStateCache.mBoundArrayBufferId != bufferId)
817   {
818     mImpl->mGlStateCache.mBoundArrayBufferId = bufferId;
819
820     auto& gl = *mImpl->mController.GetGL();
821     gl.BindBuffer(target, bufferId);
822   }
823 }
824
825 void Context::DrawBuffers(uint32_t count, const GLenum* buffers)
826 {
827   mImpl->mGlStateCache.mFrameBufferStateCache.DrawOperation(mImpl->mGlStateCache.mColorMask,
828                                                             mImpl->mGlStateCache.DepthBufferWriteEnabled(),
829                                                             mImpl->mGlStateCache.StencilBufferWriteEnabled());
830
831   auto& gl = *mImpl->mController.GetGL();
832   gl.DrawBuffers(count, buffers);
833 }
834
835 void Context::BindFrameBuffer(GLenum target, uint32_t bufferId)
836 {
837   mImpl->mGlStateCache.mFrameBufferStateCache.SetCurrentFrameBuffer(bufferId);
838
839   auto& gl = *mImpl->mController.GetGL();
840   gl.BindFramebuffer(target, bufferId);
841 }
842
843 void Context::GenFramebuffers(uint32_t count, uint32_t* framebuffers)
844 {
845   auto& gl = *mImpl->mController.GetGL();
846   gl.GenFramebuffers(count, framebuffers);
847
848   mImpl->mGlStateCache.mFrameBufferStateCache.FrameBuffersCreated(count, framebuffers);
849 }
850
851 void Context::DeleteFramebuffers(uint32_t count, uint32_t* framebuffers)
852 {
853   mImpl->mGlStateCache.mFrameBufferStateCache.FrameBuffersDeleted(count, framebuffers);
854
855   auto& gl = *mImpl->mController.GetGL();
856   gl.DeleteFramebuffers(count, framebuffers);
857 }
858
859 GLStateCache& Context::GetGLStateCache()
860 {
861   return mImpl->mGlStateCache;
862 }
863
864 void Context::GlContextCreated()
865 {
866   if(!mImpl->mGlContextCreated)
867   {
868     mImpl->mGlContextCreated = true;
869
870     // Set the initial GL state
871     mImpl->InitializeGlState();
872   }
873 }
874
875 void Context::GlContextDestroyed()
876 {
877   mImpl->mGlContextCreated = false;
878 }
879
880 void Context::InvalidateCachedPipeline(GLES::Pipeline* pipeline)
881 {
882   // Since the pipeline is deleted, invalidate the cached pipeline.
883   if(mImpl->mCurrentPipeline == &pipeline->GetPipeline())
884   {
885     mImpl->mCurrentPipeline = nullptr;
886   }
887 }
888
889 } // namespace Dali::Graphics::GLES