X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Fgraphics%2Fgles%2Fegl-implementation.cpp;h=76fa78a62b542c5f900fd721a4c43f5ca985f18d;hb=0e542d2c071b28da232aa2827a18935a01592484;hp=783c06a01a6c5469a27f02c6c9bea3618bd21452;hpb=13c5207cb6fd6564e78f0d8362d0822278e1a213;p=platform%2Fcore%2Fuifw%2Fdali-adaptor.git diff --git a/dali/internal/graphics/gles/egl-implementation.cpp b/dali/internal/graphics/gles/egl-implementation.cpp index 783c06a..76fa78a 100755 --- a/dali/internal/graphics/gles/egl-implementation.cpp +++ b/dali/internal/graphics/gles/egl-implementation.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * Copyright (c) 2019 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. @@ -20,8 +20,8 @@ #include // EXTERNAL INCLUDES +#include #include - #include // INTERNAL INCLUDES @@ -33,6 +33,11 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wold-style-cast" +namespace +{ + const std::string EGL_KHR_SURFACELESS_CONTEXT = "EGL_KHR_surfaceless_context"; +} + namespace Dali { @@ -64,14 +69,16 @@ EglImplementation::EglImplementation( int multiSamplingLevel, mEglConfig( 0 ), mEglContext( 0 ), mCurrentEglSurface( 0 ), + mCurrentEglContext( EGL_NO_CONTEXT ), mMultiSamplingLevel( multiSamplingLevel ), + mGlesVersion( 30 ), mColorDepth( COLOR_DEPTH_24 ), mGlesInitialized( false ), mIsOwnSurface( true ), - mContextCurrent( false ), mIsWindow( true ), mDepthBufferRequired( depthBufferRequired == Integration::DepthBufferAvailable::TRUE ), - mStencilBufferRequired( stencilBufferRequired == Integration::StencilBufferAvailable::TRUE ) + mStencilBufferRequired( stencilBufferRequired == Integration::StencilBufferAvailable::TRUE ), + mIsSurfacelessContextSupported( false ) { } @@ -103,30 +110,34 @@ bool EglImplementation::InitializeGles( EGLNativeDisplayType display, bool isOwn } eglBindAPI(EGL_OPENGL_ES_API); - mContextAttribs.Clear(); - -#if DALI_GLES_VERSION >= 30 - - mContextAttribs.Reserve(5); - mContextAttribs.PushBack( EGL_CONTEXT_MAJOR_VERSION_KHR ); - mContextAttribs.PushBack( DALI_GLES_VERSION / 10 ); - mContextAttribs.PushBack( EGL_CONTEXT_MINOR_VERSION_KHR ); - mContextAttribs.PushBack( DALI_GLES_VERSION % 10 ); - -#else // DALI_GLES_VERSION >= 30 - - mContextAttribs.Reserve(3); - mContextAttribs.PushBack( EGL_CONTEXT_CLIENT_VERSION ); - mContextAttribs.PushBack( 2 ); - -#endif // DALI_GLES_VERSION >= 30 - - mContextAttribs.PushBack( EGL_NONE ); - mGlesInitialized = true; mIsOwnSurface = isOwnSurface; } + // Query EGL extensions to check whether surfaceless context is supported + const char* const extensionStr = eglQueryString( mEglDisplay, EGL_EXTENSIONS ); + std::istringstream stream(extensionStr); + std::string currentExtension; + while ( std::getline( stream, currentExtension, ' ' ) ) + { + if ( currentExtension == EGL_KHR_SURFACELESS_CONTEXT ) + { + mIsSurfacelessContextSupported = true; + break; + } + } + + // We want to display this information all the time, so use the LogMessage directly + Integration::Log::LogMessage(Integration::Log::DebugInfo, "EGL Information\n" + " Vendor: %s\n" + " Version: %s\n" + " Client APIs: %s\n" + " Extensions: %s\n", + eglQueryString( mEglDisplay, EGL_VENDOR ), + eglQueryString( mEglDisplay, EGL_VERSION ), + eglQueryString( mEglDisplay, EGL_CLIENT_APIS ), + extensionStr); + return mGlesInitialized; } @@ -149,32 +160,62 @@ bool EglImplementation::CreateContext() return true; } -void EglImplementation::DestroyContext() +bool EglImplementation::CreateWindowContext( EGLContext& eglContext ) +{ + // make sure a context isn't created twice + DALI_ASSERT_ALWAYS( (eglContext == 0) && "EGL context recreated" ); + + eglContext = eglCreateContext(mEglDisplay, mEglConfig, mEglContext, &(mContextAttribs[0])); + TEST_EGL_ERROR("eglCreateContext render thread"); + + DALI_ASSERT_ALWAYS( EGL_NO_CONTEXT != eglContext && "EGL context not created" ); + + DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_VENDOR : %s ***\n", glGetString(GL_VENDOR)); + DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_RENDERER : %s ***\n", glGetString(GL_RENDERER)); + DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_VERSION : %s ***\n", glGetString(GL_VERSION)); + DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** GL_SHADING_LANGUAGE_VERSION : %s***\n", glGetString(GL_SHADING_LANGUAGE_VERSION)); + DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "*** Supported Extensions ***\n%s\n\n", glGetString(GL_EXTENSIONS)); + + mEglWindowContexts.push_back( eglContext ); + + return true; +} + +void EglImplementation::DestroyContext( EGLContext& eglContext ) { DALI_ASSERT_ALWAYS( mEglContext && "no EGL context" ); - eglDestroyContext( mEglDisplay, mEglContext ); - mEglContext = 0; + eglDestroyContext( mEglDisplay, eglContext ); + eglContext = 0; } -void EglImplementation::DestroySurface() +void EglImplementation::DestroySurface( EGLSurface& eglSurface ) { - if(mIsOwnSurface && mCurrentEglSurface) + if(mIsOwnSurface && eglSurface) { // Make context null to prevent crash in driver side MakeContextNull(); - eglDestroySurface( mEglDisplay, mCurrentEglSurface ); - mCurrentEglSurface = 0; + eglDestroySurface( mEglDisplay, eglSurface ); + eglSurface = 0; } } -void EglImplementation::MakeContextCurrent() +void EglImplementation::MakeContextCurrent( EGLSurface eglSurface, EGLContext eglContext ) { - mContextCurrent = true; + if (mCurrentEglContext == eglContext) + { + return; + } + + mCurrentEglSurface = eglSurface; if(mIsOwnSurface) { - eglMakeCurrent( mEglDisplay, mCurrentEglSurface, mCurrentEglSurface, mEglContext ); + glFinish(); + + eglMakeCurrent( mEglDisplay, eglSurface, eglSurface, eglContext ); + + mCurrentEglContext = eglContext; } EGLint error = eglGetError(); @@ -185,27 +226,25 @@ void EglImplementation::MakeContextCurrent() DALI_ASSERT_ALWAYS(false && "MakeContextCurrent failed!"); } - - // We want to display this information all the time, so use the LogMessage directly - Integration::Log::LogMessage(Integration::Log::DebugInfo, "EGL Information\n" - " Vendor: %s\n" - " Version: %s\n" - " Client APIs: %s\n" - " Extensions: %s\n", - eglQueryString(mEglDisplay, EGL_VENDOR), - eglQueryString(mEglDisplay, EGL_VERSION), - eglQueryString(mEglDisplay, EGL_CLIENT_APIS), - eglQueryString(mEglDisplay, EGL_EXTENSIONS)); } void EglImplementation::MakeCurrent( EGLNativePixmapType pixmap, EGLSurface eglSurface ) { + if (mCurrentEglContext == mEglContext) + { + return; + } + mCurrentEglNativePixmap = pixmap; mCurrentEglSurface = eglSurface; if(mIsOwnSurface) { - eglMakeCurrent( mEglDisplay, mCurrentEglSurface, mCurrentEglSurface, mEglContext ); + glFinish(); + + eglMakeCurrent( mEglDisplay, eglSurface, eglSurface, mEglContext ); + + mCurrentEglContext = mEglContext; } EGLint error = eglGetError(); @@ -220,9 +259,9 @@ void EglImplementation::MakeCurrent( EGLNativePixmapType pixmap, EGLSurface eglS void EglImplementation::MakeContextNull() { - mContextCurrent = false; // clear the current context eglMakeCurrent( mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT ); + mCurrentEglContext = EGL_NO_CONTEXT; } void EglImplementation::TerminateGles() @@ -232,11 +271,18 @@ void EglImplementation::TerminateGles() // Make context null to prevent crash in driver side MakeContextNull(); - if(mIsOwnSurface && mCurrentEglSurface) + for ( auto eglSurface : mEglWindowSurfaces ) { - eglDestroySurface(mEglDisplay, mCurrentEglSurface); + if(mIsOwnSurface && eglSurface) + { + eglDestroySurface(mEglDisplay, eglSurface); + } } eglDestroyContext(mEglDisplay, mEglContext); + for ( auto eglContext : mEglWindowContexts ) + { + eglDestroyContext(mEglDisplay, eglContext); + } eglTerminate(mEglDisplay); @@ -244,6 +290,7 @@ void EglImplementation::TerminateGles() mEglConfig = NULL; mEglContext = NULL; mCurrentEglSurface = NULL; + mCurrentEglContext = EGL_NO_CONTEXT; mGlesInitialized = false; } @@ -254,14 +301,17 @@ bool EglImplementation::IsGlesInitialized() const return mGlesInitialized; } -void EglImplementation::SwapBuffers() +void EglImplementation::SwapBuffers( EGLSurface& eglSurface ) { - eglSwapBuffers( mEglDisplay, mCurrentEglSurface ); + if ( eglSurface != EGL_NO_SURFACE ) // skip if using surfaceless context + { + eglSwapBuffers( mEglDisplay, eglSurface ); + } } -void EglImplementation::CopyBuffers() +void EglImplementation::CopyBuffers( EGLSurface& eglSurface ) { - eglCopyBuffers( mEglDisplay, mCurrentEglSurface, mCurrentEglNativePixmap ); + eglCopyBuffers( mEglDisplay, eglSurface, mCurrentEglNativePixmap ); } void EglImplementation::WaitGL() @@ -269,13 +319,16 @@ void EglImplementation::WaitGL() eglWaitGL(); } -void EglImplementation::ChooseConfig( bool isWindowType, ColorDepth depth ) +bool EglImplementation::ChooseConfig( bool isWindowType, ColorDepth depth ) { if(mEglConfig && isWindowType == mIsWindow && mColorDepth == depth) { - return; + return true; } + bool isTransparent = ( depth == COLOR_DEPTH_32 ); + + mColorDepth = depth; mIsWindow = isWindowType; EGLint numConfigs; @@ -295,29 +348,22 @@ void EglImplementation::ChooseConfig( bool isWindowType, ColorDepth depth ) configAttribs.PushBack( EGL_RENDERABLE_TYPE ); -#if DALI_GLES_VERSION >= 30 - + if( mGlesVersion >= 30 ) + { #ifdef _ARCH_ARM_ - configAttribs.PushBack( EGL_OPENGL_ES3_BIT_KHR ); + configAttribs.PushBack( EGL_OPENGL_ES3_BIT_KHR ); #else - // There is a bug in the desktop emulator - // Requesting for ES3 causes eglCreateContext even though it allows to ask - // for a configuration that supports GLES 3.0 - configAttribs.PushBack( EGL_OPENGL_ES2_BIT ); + configAttribs.PushBack( EGL_OPENGL_ES2_BIT ); #endif // _ARCH_ARM_ + } + else + { + configAttribs.PushBack( EGL_OPENGL_ES2_BIT ); + } -#else // DALI_GLES_VERSION >= 30 - - Integration::Log::LogMessage( Integration::Log::DebugInfo, "Using OpenGL ES 2 \n" ); - configAttribs.PushBack( EGL_OPENGL_ES2_BIT ); - -#endif //DALI_GLES_VERSION >= 30 - -#if DALI_GLES_VERSION >= 30 // TODO: enable this flag when it becomes supported // configAttribs.PushBack( EGL_CONTEXT_FLAGS_KHR ); // configAttribs.PushBack( EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR ); -#endif //DALI_GLES_VERSION >= 30 configAttribs.PushBack( EGL_RED_SIZE ); configAttribs.PushBack( 8 ); @@ -326,15 +372,18 @@ void EglImplementation::ChooseConfig( bool isWindowType, ColorDepth depth ) configAttribs.PushBack( EGL_BLUE_SIZE ); configAttribs.PushBack( 8 ); - configAttribs.PushBack( EGL_ALPHA_SIZE ); + if ( isTransparent ) + { + configAttribs.PushBack( EGL_ALPHA_SIZE ); #ifdef _ARCH_ARM_ - // For underlay video playback, we also need to set the alpha value of the 24/32bit window. - configAttribs.PushBack( 8 ); + // For underlay video playback, we also need to set the alpha value of the 24/32bit window. + configAttribs.PushBack( 8 ); #else - // There is a bug in the desktop emulator - // setting EGL_ALPHA_SIZE to 8 results in eglChooseConfig failing - configAttribs.PushBack( 0 ); + // There is a bug in the desktop emulator + // setting EGL_ALPHA_SIZE to 8 results in eglChooseConfig failing + configAttribs.PushBack( 8 ); #endif // _ARCH_ARM_ + } configAttribs.PushBack( EGL_DEPTH_SIZE ); configAttribs.PushBack( mDepthBufferRequired ? 24 : 0 ); @@ -352,8 +401,25 @@ void EglImplementation::ChooseConfig( bool isWindowType, ColorDepth depth ) #endif // DALI_PROFILE_UBUNTU configAttribs.PushBack( EGL_NONE ); - if ( eglChooseConfig( mEglDisplay, &(configAttribs[0]), &mEglConfig, 1, &numConfigs ) != EGL_TRUE ) + // Ensure number of configs is set to 1 as on some drivers, + // eglChooseConfig succeeds but does not actually create a proper configuration. + if ( ( eglChooseConfig( mEglDisplay, &(configAttribs[0]), &mEglConfig, 1, &numConfigs ) != EGL_TRUE ) || + ( numConfigs != 1 ) ) { + if( mGlesVersion >= 30 ) + { + mEglConfig = NULL; + DALI_LOG_ERROR("Fail to use OpenGL es 3.0. Retring to use OpenGL es 2.0."); + return false; + } + + if ( numConfigs != 1 ) + { + DALI_LOG_ERROR("No configurations found.\n"); + + TEST_EGL_ERROR("eglChooseConfig"); + } + EGLint error = eglGetError(); switch (error) { @@ -383,20 +449,32 @@ void EglImplementation::ChooseConfig( bool isWindowType, ColorDepth depth ) } } DALI_ASSERT_ALWAYS(false && "eglChooseConfig failed!"); + return false; } + Integration::Log::LogMessage(Integration::Log::DebugInfo, "Using OpenGL es %d.%d.\n", mGlesVersion / 10, mGlesVersion % 10 ); - if ( numConfigs != 1 ) + mContextAttribs.Clear(); + if( mGlesVersion >= 30 ) { - DALI_LOG_ERROR("No configurations found.\n"); - - TEST_EGL_ERROR("eglChooseConfig"); + mContextAttribs.Reserve(5); + mContextAttribs.PushBack( EGL_CONTEXT_MAJOR_VERSION_KHR ); + mContextAttribs.PushBack( mGlesVersion / 10 ); + mContextAttribs.PushBack( EGL_CONTEXT_MINOR_VERSION_KHR ); + mContextAttribs.PushBack( mGlesVersion % 10 ); + } + else + { + mContextAttribs.Reserve(3); + mContextAttribs.PushBack( EGL_CONTEXT_CLIENT_VERSION ); + mContextAttribs.PushBack( 2 ); } + mContextAttribs.PushBack( EGL_NONE ); + + return true; } -void EglImplementation::CreateSurfaceWindow( EGLNativeWindowType window, ColorDepth depth ) +EGLSurface EglImplementation::CreateSurfaceWindow( EGLNativeWindowType window, ColorDepth depth ) { - DALI_ASSERT_ALWAYS( ( mCurrentEglSurface == 0 ) && "EGL surface already exists" ); - mEglNativeWindow = window; mColorDepth = depth; mIsWindow = true; @@ -408,6 +486,8 @@ void EglImplementation::CreateSurfaceWindow( EGLNativeWindowType window, ColorDe TEST_EGL_ERROR("eglCreateWindowSurface"); DALI_ASSERT_ALWAYS( mCurrentEglSurface && "Create window surface failed" ); + + return mCurrentEglSurface; } EGLSurface EglImplementation::CreateSurfacePixmap( EGLNativePixmapType pixmap, ColorDepth depth ) @@ -427,7 +507,7 @@ EGLSurface EglImplementation::CreateSurfacePixmap( EGLNativePixmapType pixmap, C return mCurrentEglSurface; } -bool EglImplementation::ReplaceSurfaceWindow( EGLNativeWindowType window ) +bool EglImplementation::ReplaceSurfaceWindow( EGLNativeWindowType window, EGLSurface& eglSurface, EGLContext& eglContext ) { bool contextLost = false; @@ -436,13 +516,13 @@ bool EglImplementation::ReplaceSurfaceWindow( EGLNativeWindowType window ) MakeContextNull(); // destroy the surface - DestroySurface(); + DestroySurface( eglSurface ); // create the EGL surface - CreateSurfaceWindow( window, mColorDepth ); + EGLSurface newEglSurface = CreateSurfaceWindow( window, mColorDepth ); // set the context to be current with the new surface - MakeContextCurrent(); + MakeContextCurrent( newEglSurface, eglContext ); return contextLost; } @@ -461,16 +541,31 @@ bool EglImplementation::ReplaceSurfacePixmap( EGLNativePixmapType pixmap, EGLSur return contextLost; } +void EglImplementation::SetGlesVersion( const int32_t glesVersion ) +{ + mGlesVersion = glesVersion; +} + EGLDisplay EglImplementation::GetDisplay() const { return mEglDisplay; } -EGLDisplay EglImplementation::GetContext() const +EGLContext EglImplementation::GetContext() const { return mEglContext; } +int32_t EglImplementation::GetGlesVersion() const +{ + return mGlesVersion; +} + +bool EglImplementation::IsSurfacelessContextSupported() const +{ + return mIsSurfacelessContextSupported; +} + } // namespace Adaptor } // namespace Internal