-#ifndef __DALI_INTERNAL_CONTEXT_H__
-#define __DALI_INTERNAL_CONTEXT_H__
+#ifndef DALI_INTERNAL_CONTEXT_H
+#define DALI_INTERNAL_CONTEXT_H
/*
- * Copyright (c) 2016 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.
#include <dali/public-api/common/dali-common.h>
#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>
-#include <dali/devel-api/rendering/renderer.h>
#include <dali/internal/render/common/performance-monitor.h>
#include <dali/internal/render/gl-resources/texture-units.h>
#include <dali/internal/render/gl-resources/frame-buffer-state-cache.h>
* 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.
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();
*/
void PrintGlString(const char* stringName, GLenum stringId)
{
- DALI_LOG_INFO(Debug::Filter::gRender, Debug::General, "GL %s = %s\n", stringName, (const char *)GetString( stringId ) );
+ 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;
+ }
+ }
}
/****************************************************************************************
****************************************************************************************/
/**
+ * 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 )
* @param textureunit to bind to
* @param texture to bind
*/
- void BindTextureForUnit( TextureUnit textureunit, GLuint texture )
+ void BindTextureForUnit( TextureUnit textureunit, int target, GLuint texture )
{
- if( mBound2dTextureId[ textureunit ] != texture )
- {
- ActiveTexture( textureunit );
- Bind2dTexture( texture );
- }
+ ActiveTexture(textureunit);
+ BindTexture(target, texture);
}
/**
- * Wrapper for OpenGL ES 2.0 glBindTexture(GL_TEXTURE_2D)
+ * Wrapper for OpenGL ES 2.0 glBindTexture( target )
*/
- void Bind2dTexture( GLuint texture )
+ void BindTexture( int target, GLuint texture )
{
- if (mBound2dTextureId[ mActiveTextureUnit ] != texture)
+ int16_t index = GetTextureIndexFromGlFormat(target);
+ if(index >= 0)
{
- mBound2dTextureId[ mActiveTextureUnit ] = texture;
+ if(mBoundTextureId[ mActiveTextureUnit ][index] != texture)
+ {
+ mBoundTextureId[ mActiveTextureUnit ][index] = texture;
- LOG_GL("BindTexture GL_TEXTURE_2D %d\n", texture);
- CHECK_GL( mGlAbstraction, mGlAbstraction.BindTexture(GL_TEXTURE_2D, 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));
}
}
*/
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 ) );
+ }
}
/**
*/
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();
+ }
+ }
+ }
}
/**
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 )
{
- mBound2dTextureId[ i ] = 0;
+ for ( auto&& context : *mSceneContexts )
+ {
+ if ( context )
+ {
+ context->ResetTextureCache();
+ }
+ }
}
}
*/
void DepthFunc(GLenum func)
{
- LOG_GL("DepthFunc %x\n", func);
- CHECK_GL( mGlAbstraction, mGlAbstraction.DepthFunc(func) );
+ if( func != mDepthFunction )
+ {
+ mDepthFunction = func;
+ LOG_GL("DepthFunc %x\n", func);
+ CHECK_GL( mGlAbstraction, mGlAbstraction.DepthFunc(func) );
+ }
}
/**
*/
void DepthMask(GLboolean flag)
{
+ bool booleanFlag = flag != GL_FALSE;
// only change state if needed
- if( flag != mDepthMaskEnabled )
+ if( booleanFlag != mDepthMaskEnabled )
{
- mDepthMaskEnabled = flag;
- LOG_GL("DepthMask %s\n", flag ? "True" : "False");
+ mDepthMaskEnabled = booleanFlag;
+ LOG_GL("DepthMask %s\n", booleanFlag ? "True" : "False");
CHECK_GL( mGlAbstraction, mGlAbstraction.DepthMask( mDepthMaskEnabled ) );
}
}
*/
void Scissor(GLint x, GLint y, GLsizei width, GLsizei height)
{
- LOG_GL("Scissor %d %d %d %d\n", x, y, width, height);
- CHECK_GL( mGlAbstraction, mGlAbstraction.Scissor(x, y, width, height) );
+ GLint cx, cy, cw, ch;
+
+ // scissor's value should be set based on the default system coordinates.
+ // when the surface is rotated, the input valus already were set with the rotated angle.
+ // So, re-calculation is needed.
+ if(mSurfaceOrientation == 90)
+ {
+ cx = mViewPort.height - (y + height);
+ cy = x;
+ cw = height;
+ ch = width;
+ }
+ else if(mSurfaceOrientation == 180)
+ {
+ cx = mViewPort.width - (x + width);
+ cy = mViewPort.height - (y + height);
+ cw = width;
+ ch = height;
+ }
+ else if(mSurfaceOrientation == 270)
+ {
+ cx = y;
+ cy = mViewPort.width - (x + width);
+ cw = height;
+ ch = width;
+ }
+ else
+ {
+ cx = x;
+ cy = y;
+ cw = width;
+ ch = height;
+ }
+
+ LOG_GL("Scissor %d %d %d %d\n", cx, cy, cw, ch);
+ CHECK_GL(mGlAbstraction, mGlAbstraction.Scissor(cx, cy, cw, ch));
}
/**
*/
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) );
+ }
}
/**
*/
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) );
+ }
}
/**
}
/**
- * Wrapper for OpenGL ES 3.0 glUnmapBubffer()
+ * Wrapper for OpenGL ES 3.0 glUnmapBuffer()
*/
GLboolean UnmapBuffer(GLenum target)
{
GLboolean val = CHECK_GL( mGlAbstraction, mGlAbstraction.UnmapBuffer(target) );
return val;
}
+
/**
* Wrapper for OpenGL ES 2.0 glViewport()
*/
void Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
{
// check if its same as already set
- Rect<int> newViewport( x, y, width, height );
- if( mViewPort != newViewport )
+ GLsizei cw, ch;
+
+ // viewport's value shoud be set based on the default system size.
+ // when the surface is rotated, the input width and height already were swapped.
+ // So, re-swapping is needed.
+ if(mSurfaceOrientation == 90 || mSurfaceOrientation == 270)
+ {
+ cw = height;
+ ch = width;
+ }
+ else
+ {
+ cw = width;
+ ch = height;
+ }
+
+ // User uses the rotated viewport size.
+ Rect<int> newViewport(x, y, width, height);
+
+ // 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);
- CHECK_GL( mGlAbstraction, mGlAbstraction.Viewport(x, y, width, height) );
+ LOG_GL("Viewport %d %d %d %d\n", x, y, cw, ch);
+ CHECK_GL(mGlAbstraction, mGlAbstraction.Viewport(x, y, cw, ch));
mViewPort = newViewport; // remember new one
}
}
/**
+ * 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
*/
return mMaxTextureSize;
}
+ void SetSurfaceOrientation(int orientation)
+ {
+ LOG_GL( "SetSurfaceOrientation: orientation: %d\n", orientation );
+ mSurfaceOrientation = orientation;
+ }
+
/**
* Get the current viewport.
* @return Viewport rectangle.
// glBindTexture() state
TextureUnit mActiveTextureUnit;
- GLuint mBound2dTextureId[ MAX_TEXTURE_UNITS ]; ///< The ID passed to glBindTexture(GL_TEXTURE_2D)
+ GLuint mBoundTextureId[ MAX_TEXTURE_UNITS ][MAX_TEXTURE_TARGET]; ///< The ID passed to glBindTexture()
// glBlendColor() state
Vector4 mBlendColor; ///< Blend color
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)
Vector4 mClearColor; ///< clear color
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
+
+ int mSurfaceOrientation;
};
} // namespace Internal
} // namespace Dali
-#endif // __DALI_INTERNAL_CONTEXT_H__
+#endif // DALI_INTERNAL_CONTEXT_H