Merge "Clean up the code to build successfully on macOS" into devel/master
[platform/core/uifw/dali-core.git] / dali / internal / render / gl-resources / context.h
index 664c3a4..fe4d2dd 100644 (file)
@@ -1,8 +1,8 @@
-#ifndef __DALI_INTERNAL_CONTEXT_H__
-#define __DALI_INTERNAL_CONTEXT_H__
+#ifndef DALI_INTERNAL_CONTEXT_H
+#define DALI_INTERNAL_CONTEXT_H
 
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -24,6 +24,7 @@
 #include <dali/public-api/math/rect.h>
 #include <dali/public-api/math/vector4.h>
 #include <dali/public-api/rendering/renderer.h>
+#include <dali/devel-api/common/owner-container.h>
 #include <dali/integration-api/debug.h>
 #include <dali/integration-api/gl-abstraction.h>
 #include <dali/integration-api/gl-defines.h>
@@ -59,12 +60,13 @@ public:
    * Size of the VertexAttributeArray enables
    * GLES specification states that there's minimum of 8
    */
-  static const unsigned int MAX_ATTRIBUTE_CACHE_SIZE = 8;
+  static constexpr unsigned int MAX_ATTRIBUTE_CACHE_SIZE = 8;
 
-  static const unsigned int MAX_TEXTURE_UNITS = 8; // for GLES 2.0 8 is guaranteed, which is more than DALi uses anyways
+  static constexpr unsigned int MAX_TEXTURE_UNITS = 8; // for GLES 2.0 8 is guaranteed, which is more than DALi uses anyways
+  static constexpr unsigned int MAX_TEXTURE_TARGET = 3; // We support only GL_TEXTURE_2D, GL_TEXTURE_CUBE_MAP and GL_TEXTURE_EXTERNAL_OES now
 
   /**
-   * Creates the Dali Context object.
+   * Creates the Dali Context object for surface rendering only.
    * This method does not create an OpenGL context i.e. that is done from outside dali-core.
    * @pre Context has not been created.
    * @exception Context already created.
@@ -73,6 +75,16 @@ public:
   Context( Integration::GlAbstraction& glAbstraction );
 
   /**
+   * Creates the Dali Context object for texture (and surface rendering if required).
+   * This method does not create an OpenGL context i.e. that is done from outside dali-core.
+   * @pre Context has not been created.
+   * @exception Context already created.
+   * @param glAbstraction the gl abstraction.
+   * @param contexts The list of scene contexts (for surface rendering)
+   */
+  Context( Integration::GlAbstraction& glAbstraction, OwnerContainer< Context* >* contexts );
+
+  /**
    * Destructor
    */
   ~Context();
@@ -122,6 +134,63 @@ public:
     DALI_LOG_INFO(Debug::Filter::gRender, Debug::General, "GL %s = %s\n", stringName, reinterpret_cast< const char * >( GetString( stringId ) ) );
   }
 
+  /**
+   * Reset the cached buffer ids.
+   */
+  void ResetBufferCache()
+  {
+    // reset the cached buffer id's
+    // fixes problem where some drivers will a generate a buffer with the
+    // same id, as the last deleted buffer id.
+    mBoundArrayBufferId = 0;
+    mBoundElementArrayBufferId = 0;
+    mBoundTransformFeedbackBufferId = 0;
+  }
+
+  /**
+   * Reset the cached texture ids.
+   */
+  void ResetTextureCache()
+  {
+    // reset the cached texture id's in case the driver re-uses them
+    // when creating new textures
+    for(unsigned int i = 0; i < MAX_TEXTURE_UNITS; ++i)
+    {
+      for(unsigned int j = 0; j < MAX_TEXTURE_TARGET; ++j)
+      {
+        mBoundTextureId[i][j] = 0;
+      }
+    }
+  }
+
+  /**
+   * Get an index of the cached texture list from the texture target.
+   * @param target The texture target
+   * @return The index of the cached texture list
+   */
+  static constexpr int16_t GetTextureIndexFromGlFormat(int target)
+  {
+    switch(target)
+    {
+      case GL_TEXTURE_2D:
+      {
+        return 0;
+      }
+      case GL_TEXTURE_CUBE_MAP:
+      {
+        return 1;
+      }
+      case GL_TEXTURE_EXTERNAL_OES:
+      {
+        return 2;
+      }
+      default:
+      {
+        return -1;
+      }
+    }
+  }
+
   /****************************************************************************************
    * The following methods are forwarded to Dali::Integration::GlAbstraction.
    * In some cases the GL state is recorded, to avoid duplicate calls with the same state.
@@ -130,6 +199,22 @@ public:
    ****************************************************************************************/
 
   /**
+   * Wrapper for IsSurfacelessContextSupported of Dali::Integration::GlAbstraction
+   */
+  bool IsSurfacelessContextSupported() const
+  {
+    return mGlAbstraction.IsSurfacelessContextSupported();
+  }
+
+  /**
+   * Wrapper for TextureRequiresConverting of Dali::Integration::GlAbstraction
+   */
+  bool TextureRequiresConverting( const GLenum imageGlFormat, const GLenum textureGlFormat, const bool isSubImage ) const
+  {
+    return mGlAbstraction.TextureRequiresConverting( imageGlFormat, textureGlFormat, isSubImage );
+  }
+
+  /**
    * Wrapper for OpenGL ES 2.0 glActiveTexture()
    */
   void ActiveTexture( TextureUnit textureUnit )
@@ -264,11 +349,8 @@ public:
    */
   void BindTextureForUnit( TextureUnit textureunit, int target, GLuint texture )
   {
-    if( mBoundTextureId[ textureunit ] != texture )
-    {
-      ActiveTexture( textureunit );
-      BindTexture( target, texture );
-    }
+    ActiveTexture(textureunit);
+    BindTexture(target, texture);
   }
 
   /**
@@ -276,12 +358,22 @@ public:
    */
   void BindTexture( int target, GLuint texture )
   {
-    if (mBoundTextureId[ mActiveTextureUnit ] != texture)
+    int16_t index = GetTextureIndexFromGlFormat(target);
+    if(index >= 0)
     {
-      mBoundTextureId[ mActiveTextureUnit ] = texture;
+      if(mBoundTextureId[ mActiveTextureUnit ][index] != texture)
+      {
+        mBoundTextureId[ mActiveTextureUnit ][index] = texture;
 
+        LOG_GL("BindTexture target(%d) %d\n", target, texture);
+        CHECK_GL(mGlAbstraction, mGlAbstraction.BindTexture(target, texture));
+      }
+    }
+    else
+    {
+      // Don't use cache
       LOG_GL("BindTexture target(%d) %d\n", target, texture);
-      CHECK_GL( mGlAbstraction, mGlAbstraction.BindTexture(target, texture) );
+      CHECK_GL(mGlAbstraction, mGlAbstraction.BindTexture(target, texture));
     }
   }
 
@@ -316,8 +408,16 @@ public:
    */
   void BlendEquation(GLenum mode)
   {
-    // use BlendEquationSeparate to set the rgb and alpha modes the same
-    BlendEquationSeparate( mode, mode );
+    // DO NOT USE BlendEquationSeparate to set the same rgb and alpha modes
+    // KHR blending extensions require use of glBlendEquation
+
+    if( mBlendEquationSeparateModeRGB != mode || mBlendEquationSeparateModeAlpha != mode )
+    {
+      mBlendEquationSeparateModeRGB = mode;
+      mBlendEquationSeparateModeAlpha = mode;
+      LOG_GL("BlendEquation %d\n", mode);
+      CHECK_GL( mGlAbstraction, mGlAbstraction.BlendEquation( mode ) );
+    }
   }
 
   /**
@@ -590,19 +690,26 @@ public:
    */
   void DeleteBuffers(GLsizei n, const GLuint* buffers)
   {
-    // @todo: this is to prevent mesh destructor from doing GL calls when DALi core is being deleted
-    // can be taken out once render manages either knows about meshes or gpubuffers and can tell them directly that context is lost
     if( this->IsGlContextCreated() )
     {
       LOG_GL("DeleteBuffers %d %p\n", n, buffers);
       CHECK_GL( mGlAbstraction, mGlAbstraction.DeleteBuffers(n, buffers) );
     }
-    // reset the cached buffer id's
-    // fixes problem where some drivers will a generate a buffer with the
-    // same id, as the last deleted buffer id.
-    mBoundArrayBufferId = 0;
-    mBoundElementArrayBufferId = 0;
-    mBoundTransformFeedbackBufferId = 0;
+
+    ResetBufferCache();
+
+    // Need to reset the buffer cache in the surface contexts
+    // This will only be executed by the surfaceless context when there are contexts for surface rendering
+    if ( mSceneContexts )
+    {
+      for ( auto&& context : *mSceneContexts )
+      {
+        if ( context )
+        {
+          context->ResetBufferCache();
+        }
+      }
+    }
   }
 
   /**
@@ -642,11 +749,19 @@ public:
     LOG_GL("DeleteTextures %d %p\n", n, textures);
     CHECK_GL( mGlAbstraction, mGlAbstraction.DeleteTextures(n, textures) );
 
-    // reset the cached texture id's incase the driver re-uses them
-    // when creating new textures
-    for( unsigned int i=0; i < MAX_TEXTURE_UNITS; ++i )
+    ResetTextureCache();
+
+    // Need to reset the texture cache in the scene contexts
+    // This will only be executed by the surfaceless context when there are contexts for surface rendering
+    if ( mSceneContexts )
     {
-       mBoundTextureId[ i ] = 0;
+      for ( auto&& context : *mSceneContexts )
+      {
+        if ( context )
+        {
+          context->ResetTextureCache();
+        }
+      }
     }
   }
 
@@ -1474,10 +1589,15 @@ public:
    */
   void StencilFunc(GLenum func, GLint ref, GLuint mask)
   {
+    if( ( func != mStencilFunc ) || ( ref != mStencilFuncRef ) || ( mask != mStencilFuncMask ) )
+    {
+      mStencilFunc = func;
+      mStencilFuncRef = ref;
+      mStencilFuncMask = mask;
 
-
-    LOG_GL("StencilFunc %x %d %d\n", func, ref, mask);
-    CHECK_GL( mGlAbstraction, mGlAbstraction.StencilFunc(func, ref, mask) );
+      LOG_GL("StencilFunc %x %d %d\n", func, ref, mask);
+      CHECK_GL( mGlAbstraction, mGlAbstraction.StencilFunc(func, ref, mask) );
+    }
   }
 
   /**
@@ -1517,8 +1637,15 @@ public:
    */
   void StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
   {
-    LOG_GL("StencilOp %x %x %x\n", fail, zfail, zpass);
-    CHECK_GL( mGlAbstraction, mGlAbstraction.StencilOp(fail, zfail, zpass) );
+    if( ( fail != mStencilOpFail ) || ( zfail != mStencilOpDepthFail ) || ( zpass != mStencilOpDepthPass ) )
+    {
+      mStencilOpFail = fail;
+      mStencilOpDepthFail = zfail;
+      mStencilOpDepthPass = zpass;
+
+      LOG_GL("StencilOp %x %x %x\n", fail, zfail, zpass);
+      CHECK_GL( mGlAbstraction, mGlAbstraction.StencilOp(fail, zfail, zpass) );
+    }
   }
 
   /**
@@ -1608,7 +1735,7 @@ public:
   }
 
   /**
-   * Wrapper for OpenGL ES 3.0 glUnmapBubffer()
+   * Wrapper for OpenGL ES 3.0 glUnmapBuffer()
    */
   GLboolean UnmapBuffer(GLenum target)
   {
@@ -1616,6 +1743,7 @@ public:
     GLboolean val = CHECK_GL( mGlAbstraction, mGlAbstraction.UnmapBuffer(target) );
     return val;
   }
+
   /**
    * Wrapper for OpenGL ES 2.0 glViewport()
    */
@@ -1623,7 +1751,11 @@ public:
   {
     // check if its same as already set
     Rect<int> newViewport( x, y, width, height );
-    if( mViewPort != newViewport )
+
+    // Temporarily disable the viewport caching, as the implementation of GLES driver in Tizen platform
+    // share a global viewport between multiple contexts, therefore glViewport has to be called every
+    // time after glBindFramebuffer regardless of the same vewport size in the same context.
+//    if( mViewPort != newViewport )
     {
       // set new one
       LOG_GL("Viewport %d %d %d %d\n", x, y, width, height);
@@ -1633,6 +1765,15 @@ public:
   }
 
   /**
+   * Wrapper for OpenGL ES 3.2 and GL_KHR_blend_equation_advanced extention glBlendBarrier()
+   */
+  void BlendBarrier()
+  {
+    LOG_GL( "BlendBarrier\n" );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.BlendBarrier() );
+  }
+
+  /**
    * Get the implementation defined MAX_TEXTURE_SIZE. This values is cached when the context is created
    * @return The implementation defined MAX_TEXTURE_SIZE
    */
@@ -1711,7 +1852,7 @@ private: // Data
 
   // glBindTexture() state
   TextureUnit mActiveTextureUnit;
-  GLuint mBoundTextureId[ MAX_TEXTURE_UNITS ];  ///< The ID passed to glBindTexture()
+  GLuint mBoundTextureId[ MAX_TEXTURE_UNITS ][MAX_TEXTURE_TARGET];  ///< The ID passed to glBindTexture()
 
   // glBlendColor() state
   Vector4 mBlendColor; ///< Blend color
@@ -1726,6 +1867,14 @@ private: // Data
   GLenum mBlendEquationSeparateModeRGB;    ///< Controls RGB blend mode
   GLenum mBlendEquationSeparateModeAlpha;  ///< Controls Alpha blend mode
 
+  // glStencilFunc() and glStencilOp() state.
+  GLenum mStencilFunc;
+  GLint mStencilFuncRef;
+  GLuint mStencilFuncMask;
+  GLenum mStencilOpFail;
+  GLenum mStencilOpDepthFail;
+  GLenum mStencilOpDepthPass;
+
   GLenum mDepthFunction;  ///The depth function
 
   GLint mMaxTextureSize;      ///< return value from GetIntegerv(GL_MAX_TEXTURE_SIZE)
@@ -1742,10 +1891,12 @@ private: // Data
   bool mVertexAttributeCurrentState[ MAX_ATTRIBUTE_CACHE_SIZE ];   ///< Current state on the driver for Enable Vertex Attribute
 
   FrameBufferStateCache mFrameBufferStateCache;   ///< frame buffer state cache
+
+  OwnerContainer< Context* >* mSceneContexts;      ///< The pointer of the container of contexts for surface rendering
 };
 
 } // namespace Internal
 
 } // namespace Dali
 
-#endif // __DALI_INTERNAL_CONTEXT_H__
+#endif // DALI_INTERNAL_CONTEXT_H