Merge "Add GetBrightness()" into devel/master
[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 Graphics::TextureBinding* bindings, uint32_t count)
326 {
327   // for each texture allocate slot
328   for(auto i = 0u; i < count; ++i)
329   {
330     auto& binding = bindings[i];
331
332     // Resize binding array if needed
333     if(mImpl->mCurrentTextureBindings.size() <= binding.binding)
334     {
335       mImpl->mCurrentTextureBindings.resize(binding.binding + 1);
336     }
337     // Store the binding details
338     mImpl->mCurrentTextureBindings[binding.binding] = binding;
339   }
340 }
341
342 void Context::BindVertexBuffers(const GLES::VertexBufferBindingDescriptor* bindings, uint32_t count)
343 {
344   if(count > mImpl->mCurrentVertexBufferBindings.size())
345   {
346     mImpl->mCurrentVertexBufferBindings.resize(count);
347   }
348   // Copy only set slots
349   std::copy_if(bindings, bindings + count, mImpl->mCurrentVertexBufferBindings.begin(), [](auto& item) {
350     return (nullptr != item.buffer);
351   });
352 }
353
354 void Context::BindIndexBuffer(const IndexBufferBindingDescriptor& indexBufferBinding)
355 {
356   mImpl->mCurrentIndexBufferBinding = indexBufferBinding;
357 }
358
359 void Context::BindPipeline(const GLES::Pipeline* newPipeline)
360 {
361   DALI_ASSERT_ALWAYS(newPipeline && "Invalid pipeline");
362   mImpl->mNewPipeline = &newPipeline->GetPipeline();
363 }
364
365 void Context::BindUniformBuffers(const UniformBufferBindingDescriptor* uboBindings,
366                                  uint32_t                              uboCount,
367                                  const UniformBufferBindingDescriptor& standaloneBindings)
368 {
369   if(standaloneBindings.buffer)
370   {
371     mImpl->mCurrentStandaloneUBOBinding = standaloneBindings;
372   }
373
374   if(uboCount >= mImpl->mCurrentUBOBindings.size())
375   {
376     mImpl->mCurrentUBOBindings.resize(uboCount + 1);
377   }
378
379   auto it = uboBindings;
380   for(auto i = 0u; i < uboCount; ++i)
381   {
382     if(it->buffer)
383     {
384       mImpl->mCurrentUBOBindings[i] = *it;
385     }
386   }
387 }
388
389 void Context::ResolveBlendState()
390 {
391   const auto& currentBlendState = mImpl->mCurrentPipeline ? mImpl->mCurrentPipeline->GetCreateInfo().colorBlendState : nullptr;
392   const auto& newBlendState     = mImpl->mNewPipeline->GetCreateInfo().colorBlendState;
393
394   // TODO: prevent leaking the state
395   if(!newBlendState)
396   {
397     return;
398   }
399
400   auto& gl = *mImpl->mController.GetGL();
401
402   if(!currentBlendState || currentBlendState->blendEnable != newBlendState->blendEnable)
403   {
404     if(newBlendState->blendEnable != mImpl->mGlStateCache.mBlendEnabled)
405     {
406       mImpl->mGlStateCache.mBlendEnabled = newBlendState->blendEnable;
407       newBlendState->blendEnable ? gl.Enable(GL_BLEND) : gl.Disable(GL_BLEND);
408     }
409   }
410
411   if(!newBlendState->blendEnable)
412   {
413     return;
414   }
415
416   BlendFactor newSrcRGB(newBlendState->srcColorBlendFactor);
417   BlendFactor newDstRGB(newBlendState->dstColorBlendFactor);
418   BlendFactor newSrcAlpha(newBlendState->srcAlphaBlendFactor);
419   BlendFactor newDstAlpha(newBlendState->dstAlphaBlendFactor);
420
421   if(!currentBlendState ||
422      currentBlendState->srcColorBlendFactor != newSrcRGB ||
423      currentBlendState->dstColorBlendFactor != newDstRGB ||
424      currentBlendState->srcAlphaBlendFactor != newSrcAlpha ||
425      currentBlendState->dstAlphaBlendFactor != newDstAlpha)
426   {
427     if((mImpl->mGlStateCache.mBlendFuncSeparateSrcRGB != newSrcRGB) ||
428        (mImpl->mGlStateCache.mBlendFuncSeparateDstRGB != newDstRGB) ||
429        (mImpl->mGlStateCache.mBlendFuncSeparateSrcAlpha != newSrcAlpha) ||
430        (mImpl->mGlStateCache.mBlendFuncSeparateDstAlpha != newDstAlpha))
431     {
432       mImpl->mGlStateCache.mBlendFuncSeparateSrcRGB   = newSrcRGB;
433       mImpl->mGlStateCache.mBlendFuncSeparateDstRGB   = newDstRGB;
434       mImpl->mGlStateCache.mBlendFuncSeparateSrcAlpha = newSrcAlpha;
435       mImpl->mGlStateCache.mBlendFuncSeparateDstAlpha = newDstAlpha;
436
437       if(newSrcRGB == newSrcAlpha && newDstRGB == newDstAlpha)
438       {
439         gl.BlendFunc(GLBlendFunc(newSrcRGB), GLBlendFunc(newDstRGB));
440       }
441       else
442       {
443         gl.BlendFuncSeparate(GLBlendFunc(newSrcRGB), GLBlendFunc(newDstRGB), GLBlendFunc(newSrcAlpha), GLBlendFunc(newDstAlpha));
444       }
445     }
446   }
447
448   if(!currentBlendState ||
449      currentBlendState->colorBlendOp != newBlendState->colorBlendOp ||
450      currentBlendState->alphaBlendOp != newBlendState->alphaBlendOp)
451   {
452     if(mImpl->mGlStateCache.mBlendEquationSeparateModeRGB != newBlendState->colorBlendOp ||
453        mImpl->mGlStateCache.mBlendEquationSeparateModeAlpha != newBlendState->alphaBlendOp)
454     {
455       mImpl->mGlStateCache.mBlendEquationSeparateModeRGB   = newBlendState->colorBlendOp;
456       mImpl->mGlStateCache.mBlendEquationSeparateModeAlpha = newBlendState->alphaBlendOp;
457
458       if(newBlendState->colorBlendOp == newBlendState->alphaBlendOp)
459       {
460         gl.BlendEquation(GLBlendOp(newBlendState->colorBlendOp));
461       }
462       else
463       {
464         gl.BlendEquationSeparate(GLBlendOp(newBlendState->colorBlendOp), GLBlendOp(newBlendState->alphaBlendOp));
465       }
466     }
467   }
468 }
469
470 void Context::ResolveRasterizationState()
471 {
472   const auto& currentRasterizationState = mImpl->mCurrentPipeline ? mImpl->mCurrentPipeline->GetCreateInfo().rasterizationState : nullptr;
473   const auto& newRasterizationState     = mImpl->mNewPipeline->GetCreateInfo().rasterizationState;
474
475   // TODO: prevent leaking the state
476   if(!newRasterizationState)
477   {
478     return;
479   }
480
481   auto& gl = *mImpl->mController.GetGL();
482
483   if(!currentRasterizationState ||
484      currentRasterizationState->cullMode != newRasterizationState->cullMode)
485   {
486     if(mImpl->mGlStateCache.mCullFaceMode != newRasterizationState->cullMode)
487     {
488       mImpl->mGlStateCache.mCullFaceMode = newRasterizationState->cullMode;
489       if(newRasterizationState->cullMode == CullMode::NONE)
490       {
491         gl.Disable(GL_CULL_FACE);
492       }
493       else
494       {
495         gl.Enable(GL_CULL_FACE);
496         gl.CullFace(GLCullMode(newRasterizationState->cullMode));
497       }
498     }
499   }
500   // TODO: implement polygon mode (fill, line, points)
501   //       seems like we don't support it (no glPolygonMode())
502 }
503
504 void Context::ResolveUniformBuffers()
505 {
506   // Resolve standalone uniforms if we have binding
507   if(mImpl->mCurrentStandaloneUBOBinding.buffer)
508   {
509     ResolveStandaloneUniforms();
510   }
511 }
512
513 void Context::ResolveStandaloneUniforms()
514 {
515   // Find reflection for program
516   const auto program = static_cast<const GLES::Program*>(mImpl->mNewPipeline->GetCreateInfo().programState->program);
517   const auto ptr     = reinterpret_cast<const char*>(mImpl->mCurrentStandaloneUBOBinding.buffer->GetCPUAllocatedAddress()) + mImpl->mCurrentStandaloneUBOBinding.offset;
518
519   // Update program uniforms
520   program->GetImplementation()->UpdateStandaloneUniformBlock(ptr);
521 }
522
523 void Context::BeginRenderPass(const BeginRenderPassDescriptor& renderPassBegin)
524 {
525   auto& renderPass   = *renderPassBegin.renderPass;
526   auto& renderTarget = *renderPassBegin.renderTarget;
527
528   const auto& targetInfo = renderTarget.GetCreateInfo();
529
530   auto& gl = *mImpl->mController.GetGL();
531
532   if(targetInfo.surface)
533   {
534     // Bind surface FB
535     BindFrameBuffer(GL_FRAMEBUFFER, 0);
536   }
537   else if(targetInfo.framebuffer)
538   {
539     // bind framebuffer and swap.
540     renderTarget.GetFramebuffer()->Bind();
541   }
542
543   // clear (ideally cache the setup)
544
545   // In GL we assume that the last attachment is depth/stencil (we may need
546   // to cache extra information inside GLES RenderTarget if we want to be
547   // more specific in case of MRT)
548
549   const auto& attachments = *renderPass.GetCreateInfo().attachments;
550   const auto& color0      = attachments[0];
551   GLuint      mask        = 0;
552   if(color0.loadOp == AttachmentLoadOp::CLEAR)
553   {
554     mask |= GL_COLOR_BUFFER_BIT;
555
556     // Set clear color
557     // Something goes wrong here if Alpha mask is GL_TRUE
558     ColorMask(true);
559
560     const auto clearValues = renderPassBegin.clearValues.Ptr();
561
562     if(!mImpl->mGlStateCache.mClearColorSet ||
563        mImpl->mGlStateCache.mClearColor.r != clearValues[0].color.r ||
564        mImpl->mGlStateCache.mClearColor.g != clearValues[0].color.g ||
565        mImpl->mGlStateCache.mClearColor.b != clearValues[0].color.b ||
566        mImpl->mGlStateCache.mClearColor.a != clearValues[0].color.a)
567     {
568       gl.ClearColor(clearValues[0].color.r,
569                     clearValues[0].color.g,
570                     clearValues[0].color.b,
571                     clearValues[0].color.a);
572
573       mImpl->mGlStateCache.mClearColorSet = true;
574       mImpl->mGlStateCache.mClearColor    = Vector4(clearValues[0].color.r,
575                                                  clearValues[0].color.g,
576                                                  clearValues[0].color.b,
577                                                  clearValues[0].color.a);
578     }
579   }
580
581   // check for depth stencil
582   if(attachments.size() > 1)
583   {
584     const auto& depthStencil = attachments.back();
585     if(depthStencil.loadOp == AttachmentLoadOp::CLEAR)
586     {
587       if(!mImpl->mGlStateCache.mDepthMaskEnabled)
588       {
589         mImpl->mGlStateCache.mDepthMaskEnabled = true;
590         gl.DepthMask(true);
591       }
592       mask |= GL_DEPTH_BUFFER_BIT;
593     }
594     if(depthStencil.stencilLoadOp == AttachmentLoadOp::CLEAR)
595     {
596       if(mImpl->mGlStateCache.mStencilMask != 0xFF)
597       {
598         mImpl->mGlStateCache.mStencilMask = 0xFF;
599         gl.StencilMask(0xFF);
600       }
601       mask |= GL_STENCIL_BUFFER_BIT;
602     }
603   }
604
605   SetScissorTestEnabled(true);
606   gl.Scissor(renderPassBegin.renderArea.x, renderPassBegin.renderArea.y, renderPassBegin.renderArea.width, renderPassBegin.renderArea.height);
607   ClearBuffer(mask, true);
608   SetScissorTestEnabled(false);
609
610   mImpl->mCurrentRenderPass   = &renderPass;
611   mImpl->mCurrentRenderTarget = &renderTarget;
612 }
613
614 void Context::EndRenderPass()
615 {
616   if(mImpl->mCurrentRenderTarget)
617   {
618     if(mImpl->mCurrentRenderTarget->GetFramebuffer())
619     {
620       auto& gl = *mImpl->mController.GetGL();
621       gl.Flush();
622     }
623   }
624 }
625
626 void Context::ClearState()
627 {
628   mImpl->mCurrentTextureBindings.clear();
629 }
630
631 void Context::ColorMask(bool enabled)
632 {
633   if(enabled != mImpl->mGlStateCache.mColorMask)
634   {
635     mImpl->mGlStateCache.mColorMask = enabled;
636
637     auto& gl = *mImpl->mController.GetGL();
638     gl.ColorMask(enabled, enabled, enabled, enabled);
639   }
640 }
641
642 void Context::ClearStencilBuffer()
643 {
644   ClearBuffer(GL_STENCIL_BUFFER_BIT, false);
645 }
646
647 void Context::ClearDepthBuffer()
648 {
649   ClearBuffer(GL_DEPTH_BUFFER_BIT, false);
650 }
651
652 void Context::ClearBuffer(uint32_t mask, bool forceClear)
653 {
654   mask = mImpl->mGlStateCache.mFrameBufferStateCache.GetClearMask(mask, forceClear, mImpl->mGlStateCache.mScissorTestEnabled);
655   if(mask > 0)
656   {
657     auto& gl = *mImpl->mController.GetGL();
658     gl.Clear(mask);
659   }
660 }
661
662 void Context::InvalidateDepthStencilBuffers()
663 {
664   auto& gl = *mImpl->mController.GetGL();
665
666   GLenum attachments[] = {GL_DEPTH, GL_STENCIL};
667   gl.InvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
668 }
669
670 void Context::SetScissorTestEnabled(bool scissorEnabled)
671 {
672   if(mImpl->mGlStateCache.mScissorTestEnabled != scissorEnabled)
673   {
674     mImpl->mGlStateCache.mScissorTestEnabled = scissorEnabled;
675
676     auto& gl = *mImpl->mController.GetGL();
677     if(scissorEnabled)
678     {
679       gl.Enable(GL_SCISSOR_TEST);
680     }
681     else
682     {
683       gl.Disable(GL_SCISSOR_TEST);
684     }
685   }
686 }
687
688 void Context::SetStencilTestEnable(bool stencilEnable)
689 {
690   if(stencilEnable != mImpl->mGlStateCache.mStencilBufferEnabled)
691   {
692     mImpl->mGlStateCache.mStencilBufferEnabled = stencilEnable;
693
694     auto& gl = *mImpl->mController.GetGL();
695     if(stencilEnable)
696     {
697       gl.Enable(GL_STENCIL_TEST);
698     }
699     else
700     {
701       gl.Disable(GL_STENCIL_TEST);
702     }
703   }
704 }
705
706 void Context::StencilMask(uint32_t writeMask)
707 {
708   if(writeMask != mImpl->mGlStateCache.mStencilMask)
709   {
710     mImpl->mGlStateCache.mStencilMask = writeMask;
711
712     auto& gl = *mImpl->mController.GetGL();
713     gl.StencilMask(writeMask);
714   }
715 }
716
717 void Context::StencilFunc(Graphics::CompareOp compareOp,
718                           uint32_t            reference,
719                           uint32_t            compareMask)
720 {
721   if(compareOp != mImpl->mGlStateCache.mStencilFunc ||
722      reference != mImpl->mGlStateCache.mStencilFuncRef ||
723      compareMask != mImpl->mGlStateCache.mStencilFuncMask)
724   {
725     mImpl->mGlStateCache.mStencilFunc     = compareOp;
726     mImpl->mGlStateCache.mStencilFuncRef  = reference;
727     mImpl->mGlStateCache.mStencilFuncMask = compareMask;
728
729     auto& gl = *mImpl->mController.GetGL();
730     gl.StencilFunc(GLCompareOp(compareOp).op, reference, compareMask);
731   }
732 }
733
734 void Context::StencilOp(Graphics::StencilOp failOp,
735                         Graphics::StencilOp depthFailOp,
736                         Graphics::StencilOp passOp)
737 {
738   if(failOp != mImpl->mGlStateCache.mStencilOpFail ||
739      depthFailOp != mImpl->mGlStateCache.mStencilOpDepthFail ||
740      passOp != mImpl->mGlStateCache.mStencilOpDepthPass)
741   {
742     mImpl->mGlStateCache.mStencilOpFail      = failOp;
743     mImpl->mGlStateCache.mStencilOpDepthFail = depthFailOp;
744     mImpl->mGlStateCache.mStencilOpDepthPass = passOp;
745
746     auto& gl = *mImpl->mController.GetGL();
747     gl.StencilOp(GLStencilOp(failOp).op, GLStencilOp(depthFailOp).op, GLStencilOp(passOp).op);
748   }
749 }
750
751 void Context::SetDepthCompareOp(Graphics::CompareOp compareOp)
752 {
753   if(compareOp != mImpl->mGlStateCache.mDepthFunction)
754   {
755     mImpl->mGlStateCache.mDepthFunction = compareOp;
756     auto& gl                            = *mImpl->mController.GetGL();
757     gl.DepthFunc(GLCompareOp(compareOp).op);
758   }
759 }
760
761 void Context::SetDepthTestEnable(bool depthTestEnable)
762 {
763   if(depthTestEnable != mImpl->mGlStateCache.mDepthBufferEnabled)
764   {
765     mImpl->mGlStateCache.mDepthBufferEnabled = depthTestEnable;
766
767     auto& gl = *mImpl->mController.GetGL();
768     if(depthTestEnable)
769     {
770       gl.Enable(GL_DEPTH_TEST);
771     }
772     else
773     {
774       gl.Disable(GL_DEPTH_TEST);
775     }
776   }
777 }
778
779 void Context::SetDepthWriteEnable(bool depthWriteEnable)
780 {
781   if(depthWriteEnable != mImpl->mGlStateCache.mDepthMaskEnabled)
782   {
783     mImpl->mGlStateCache.mDepthMaskEnabled = depthWriteEnable;
784
785     auto& gl = *mImpl->mController.GetGL();
786     gl.DepthMask(depthWriteEnable);
787   }
788 }
789
790 void Context::ActiveTexture(uint32_t textureBindingIndex)
791 {
792   if(mImpl->mGlStateCache.mActiveTextureUnit != textureBindingIndex)
793   {
794     mImpl->mGlStateCache.mActiveTextureUnit = textureBindingIndex;
795
796     auto& gl = *mImpl->mController.GetGL();
797     gl.ActiveTexture(GL_TEXTURE0 + textureBindingIndex);
798   }
799 }
800
801 void Context::BindTexture(GLenum target, BoundTextureType textureTypeId, uint32_t textureId)
802 {
803   uint32_t typeId = static_cast<uint32_t>(textureTypeId);
804   if(mImpl->mGlStateCache.mBoundTextureId[mImpl->mGlStateCache.mActiveTextureUnit][typeId] != textureId)
805   {
806     mImpl->mGlStateCache.mBoundTextureId[mImpl->mGlStateCache.mActiveTextureUnit][typeId] = textureId;
807
808     auto& gl = *mImpl->mController.GetGL();
809     gl.BindTexture(target, textureId);
810   }
811 }
812
813 void Context::GenerateMipmap(GLenum target)
814 {
815   auto& gl = *mImpl->mController.GetGL();
816   gl.GenerateMipmap(target);
817 }
818
819 void Context::BindBuffer(GLenum target, uint32_t bufferId)
820 {
821   if(mImpl->mGlStateCache.mBoundArrayBufferId != bufferId)
822   {
823     mImpl->mGlStateCache.mBoundArrayBufferId = bufferId;
824
825     auto& gl = *mImpl->mController.GetGL();
826     gl.BindBuffer(target, bufferId);
827   }
828 }
829
830 void Context::DrawBuffers(uint32_t count, const GLenum* buffers)
831 {
832   mImpl->mGlStateCache.mFrameBufferStateCache.DrawOperation(mImpl->mGlStateCache.mColorMask,
833                                                             mImpl->mGlStateCache.DepthBufferWriteEnabled(),
834                                                             mImpl->mGlStateCache.StencilBufferWriteEnabled());
835
836   auto& gl = *mImpl->mController.GetGL();
837   gl.DrawBuffers(count, buffers);
838 }
839
840 void Context::BindFrameBuffer(GLenum target, uint32_t bufferId)
841 {
842   mImpl->mGlStateCache.mFrameBufferStateCache.SetCurrentFrameBuffer(bufferId);
843
844   auto& gl = *mImpl->mController.GetGL();
845   gl.BindFramebuffer(target, bufferId);
846 }
847
848 void Context::GenFramebuffers(uint32_t count, uint32_t* framebuffers)
849 {
850   auto& gl = *mImpl->mController.GetGL();
851   gl.GenFramebuffers(count, framebuffers);
852
853   mImpl->mGlStateCache.mFrameBufferStateCache.FrameBuffersCreated(count, framebuffers);
854 }
855
856 void Context::DeleteFramebuffers(uint32_t count, uint32_t* framebuffers)
857 {
858   mImpl->mGlStateCache.mFrameBufferStateCache.FrameBuffersDeleted(count, framebuffers);
859
860   auto& gl = *mImpl->mController.GetGL();
861   gl.DeleteFramebuffers(count, framebuffers);
862 }
863
864 GLStateCache& Context::GetGLStateCache()
865 {
866   return mImpl->mGlStateCache;
867 }
868
869 void Context::GlContextCreated()
870 {
871   if(!mImpl->mGlContextCreated)
872   {
873     mImpl->mGlContextCreated = true;
874
875     // Set the initial GL state
876     mImpl->InitializeGlState();
877   }
878 }
879
880 void Context::GlContextDestroyed()
881 {
882   mImpl->mGlContextCreated = false;
883 }
884
885 void Context::InvalidateCachedPipeline(GLES::Pipeline* pipeline)
886 {
887   // Since the pipeline is deleted, invalidate the cached pipeline.
888   if(mImpl->mCurrentPipeline == &pipeline->GetPipeline())
889   {
890     mImpl->mCurrentPipeline = nullptr;
891   }
892 }
893
894 } // namespace Dali::Graphics::GLES