X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Fgraphics%2Fgles%2Fegl-implementation.cpp;h=d674055eb22ca56da887b739f7d2e816c2c48a81;hb=1d0d7873858fd2010b71e5db8f03654fb307370f;hp=be463f7fab2f0768a05f2669e4bc90f05c7fcd36;hpb=7f66199426a7e8e76fab46617e108ebeddd566fb;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 be463f7..d674055 100755 --- a/dali/internal/graphics/gles/egl-implementation.cpp +++ b/dali/internal/graphics/gles/egl-implementation.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 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. @@ -20,8 +20,8 @@ #include // EXTERNAL INCLUDES +#include #include - #include // INTERNAL INCLUDES @@ -33,6 +33,14 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wold-style-cast" +namespace +{ + const uint32_t THRESHOLD_SWAPBUFFER_COUNT = 5; + const uint32_t CHECK_EXTENSION_NUMBER = 2; + const std::string EGL_KHR_SURFACELESS_CONTEXT = "EGL_KHR_surfaceless_context"; + const std::string EGL_KHR_CREATE_CONTEXT = "EGL_KHR_create_context"; +} + namespace Dali { @@ -55,7 +63,8 @@ namespace Adaptor EglImplementation::EglImplementation( int multiSamplingLevel, Integration::DepthBufferAvailable depthBufferRequired, - Integration::StencilBufferAvailable stencilBufferRequired ) + Integration::StencilBufferAvailable stencilBufferRequired , + Integration::PartialUpdateAvailable partialUpdateRequired ) : mContextAttribs(), mEglNativeDisplay( 0 ), mEglNativeWindow( 0 ), @@ -66,12 +75,19 @@ EglImplementation::EglImplementation( int multiSamplingLevel, mCurrentEglSurface( 0 ), mCurrentEglContext( EGL_NO_CONTEXT ), mMultiSamplingLevel( multiSamplingLevel ), + mGlesVersion( 30 ), mColorDepth( COLOR_DEPTH_24 ), mGlesInitialized( false ), mIsOwnSurface( true ), mIsWindow( true ), mDepthBufferRequired( depthBufferRequired == Integration::DepthBufferAvailable::TRUE ), - mStencilBufferRequired( stencilBufferRequired == Integration::StencilBufferAvailable::TRUE ) + mStencilBufferRequired( stencilBufferRequired == Integration::StencilBufferAvailable::TRUE ), + mPartialUpdateRequired( partialUpdateRequired == Integration::PartialUpdateAvailable::TRUE ), + mIsSurfacelessContextSupported( false ), + mIsKhrCreateContextSupported( false ), + mSwapBufferCountAfterResume( 0 ), + mEglSetDamageRegionKHR( 0 ), + mEglSwapBuffersWithDamageKHR( 0 ) { } @@ -86,12 +102,18 @@ bool EglImplementation::InitializeGles( EGLNativeDisplayType display, bool isOwn { mEglNativeDisplay = display; - //@todo see if we can just EGL_DEFAULT_DISPLAY instead - mEglDisplay = eglGetDisplay(mEglNativeDisplay); - EGLint error = eglGetError(); + // Try to get the display connection for the native display first + mEglDisplay = eglGetDisplay( mEglNativeDisplay ); - if( mEglDisplay == NULL && error != EGL_SUCCESS ) + if( mEglDisplay == EGL_NO_DISPLAY ) { + // If failed, try to get the default display connection + mEglDisplay = eglGetDisplay( EGL_DEFAULT_DISPLAY ); + } + + if( mEglDisplay == EGL_NO_DISPLAY ) + { + // Still failed to get a display connection throw Dali::DaliException( "", "OpenGL ES is not supported"); } @@ -103,40 +125,42 @@ 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; + uint32_t extensionCheckCount = 0; + while( std::getline( stream, currentExtension, ' ' ) && extensionCheckCount < CHECK_EXTENSION_NUMBER ) + { + if( currentExtension == EGL_KHR_SURFACELESS_CONTEXT ) + { + mIsSurfacelessContextSupported = true; + extensionCheckCount++; + } + if( currentExtension == EGL_KHR_CREATE_CONTEXT ) + { + mIsKhrCreateContextSupported = true; + extensionCheckCount++; + } + } + + mGlesInitialized = true; + // We want to display this information all the time, so use the LogMessage directly Integration::Log::LogMessage(Integration::Log::DebugInfo, "EGL Information\n" + " PartialUpdate %d\n" " Vendor: %s\n" " Version: %s\n" " Client APIs: %s\n" " Extensions: %s\n", + mPartialUpdateRequired, eglQueryString( mEglDisplay, EGL_VENDOR ), eglQueryString( mEglDisplay, EGL_VERSION ), eglQueryString( mEglDisplay, EGL_CLIENT_APIS ), - eglQueryString( mEglDisplay, EGL_EXTENSIONS )); + extensionStr); return mGlesInitialized; } @@ -157,6 +181,18 @@ bool EglImplementation::CreateContext() 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)); + mEglSetDamageRegionKHR = reinterpret_cast(eglGetProcAddress("eglSetDamageRegionKHR")); + if (!mEglSetDamageRegionKHR) + { + DALI_LOG_ERROR("Coudn't find eglSetDamageRegionKHR!\n"); + mPartialUpdateRequired = false; + } + mEglSwapBuffersWithDamageKHR = reinterpret_cast(eglGetProcAddress("eglSwapBuffersWithDamageKHR")); + if (!mEglSwapBuffersWithDamageKHR) + { + DALI_LOG_ERROR("Coudn't find eglSwapBuffersWithDamageKHR!\n"); + mPartialUpdateRequired = false; + } return true; } @@ -178,15 +214,28 @@ bool EglImplementation::CreateWindowContext( EGLContext& eglContext ) mEglWindowContexts.push_back( eglContext ); + mEglSetDamageRegionKHR = reinterpret_cast(eglGetProcAddress("eglSetDamageRegionKHR")); + if (!mEglSetDamageRegionKHR) + { + DALI_LOG_ERROR("Coudn't find eglSetDamageRegionKHR!\n"); + mPartialUpdateRequired = false; + } + mEglSwapBuffersWithDamageKHR = reinterpret_cast(eglGetProcAddress("eglSwapBuffersWithDamageKHR")); + if (!mEglSwapBuffersWithDamageKHR) + { + DALI_LOG_ERROR("Coudn't find eglSwapBuffersWithDamageKHR!\n"); + mPartialUpdateRequired = false; + } return true; } void EglImplementation::DestroyContext( EGLContext& eglContext ) { - DALI_ASSERT_ALWAYS( mEglContext && "no EGL context" ); - - eglDestroyContext( mEglDisplay, eglContext ); - eglContext = 0; + if( eglContext ) + { + eglDestroyContext( mEglDisplay, eglContext ); + eglContext = 0; + } } void EglImplementation::DestroySurface( EGLSurface& eglSurface ) @@ -211,8 +260,6 @@ void EglImplementation::MakeContextCurrent( EGLSurface eglSurface, EGLContext eg if(mIsOwnSurface) { - glFinish(); - eglMakeCurrent( mEglDisplay, eglSurface, eglSurface, eglContext ); mCurrentEglContext = eglContext; @@ -240,8 +287,6 @@ void EglImplementation::MakeCurrent( EGLNativePixmapType pixmap, EGLSurface eglS if(mIsOwnSurface) { - glFinish(); - eglMakeCurrent( mEglDisplay, eglSurface, eglSurface, mEglContext ); mCurrentEglContext = mEglContext; @@ -305,7 +350,94 @@ void EglImplementation::SwapBuffers( EGLSurface& eglSurface ) { if ( eglSurface != EGL_NO_SURFACE ) // skip if using surfaceless context { +#ifndef DALI_PROFILE_UBUNTU + if( mSwapBufferCountAfterResume < THRESHOLD_SWAPBUFFER_COUNT ) + { + DALI_LOG_RELEASE_INFO( "EglImplementation::SwapBuffers started.\n" ); + } +#endif //DALI_PROFILE_UBUNTU + + // DALI_LOG_ERROR("EglImplementation::SwapBuffers()\n"); eglSwapBuffers( mEglDisplay, eglSurface ); + +#ifndef DALI_PROFILE_UBUNTU + if( mSwapBufferCountAfterResume < THRESHOLD_SWAPBUFFER_COUNT ) + { + DALI_LOG_RELEASE_INFO( "EglImplementation::SwapBuffers finished.\n" ); + mSwapBufferCountAfterResume++; + } +#endif //DALI_PROFILE_UBUNTU + } +} + +EGLint EglImplementation::GetBufferAge(EGLSurface& eglSurface) const +{ + EGLint age = 0; + eglQuerySurface(mEglDisplay, eglSurface, EGL_BUFFER_AGE_EXT, &age); + if (age < 0) + { + DALI_LOG_ERROR("eglQuerySurface(%d)\n", eglGetError()); + age = 0; + } + + // 0 - invalid buffer + // 1, 2, 3 + if (age > 3) + { + DALI_LOG_ERROR("EglImplementation::GetBufferAge() buffer age %d > 3\n", age); + age = 0; // shoudn't be more than 3 back buffers, if there is just reset, I don't want to add extra history level + } + + return age; +} + +void EglImplementation::SetDamageRegion( EGLSurface& eglSurface, std::vector< Rect< int > >& damagedRects ) +{ + if( !mPartialUpdateRequired ) + { + return; + } + + if( eglSurface != EGL_NO_SURFACE ) // skip if using surfaceless context + { + EGLBoolean result = mEglSetDamageRegionKHR( mEglDisplay, eglSurface, reinterpret_cast< int* >( damagedRects.data() ), 1 ); + if (result == EGL_FALSE) + { + DALI_LOG_ERROR( "eglSetDamageRegionKHR(%d)\n", eglGetError() ); + } + } +} + +void EglImplementation::SwapBuffers(EGLSurface& eglSurface, const std::vector>& damagedRects) +{ + if (eglSurface != EGL_NO_SURFACE ) // skip if using surfaceless context + { + if (!mPartialUpdateRequired ) + { + SwapBuffers(eglSurface); + return; + } + +#ifndef DALI_PROFILE_UBUNTU + if( mSwapBufferCountAfterResume < THRESHOLD_SWAPBUFFER_COUNT ) + { + DALI_LOG_RELEASE_INFO( "EglImplementation::SwapBuffers started.\n" ); + } +#endif //DALI_PROFILE_UBUNTU + + EGLBoolean result = mEglSwapBuffersWithDamageKHR(mEglDisplay, eglSurface, reinterpret_cast(const_cast< std::vector< Rect< int > >& >( damagedRects ).data()), damagedRects.size()); + if (result == EGL_FALSE) + { + DALI_LOG_ERROR("eglSwapBuffersWithDamageKHR(%d)\n", eglGetError()); + } + +#ifndef DALI_PROFILE_UBUNTU + if( mSwapBufferCountAfterResume < THRESHOLD_SWAPBUFFER_COUNT ) + { + DALI_LOG_RELEASE_INFO( "EglImplementation::SwapBuffers finished.\n" ); + mSwapBufferCountAfterResume++; + } +#endif //DALI_PROFILE_UBUNTU } } @@ -319,15 +451,14 @@ 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; @@ -347,29 +478,18 @@ void EglImplementation::ChooseConfig( bool isWindowType, ColorDepth depth ) configAttribs.PushBack( EGL_RENDERABLE_TYPE ); -#if DALI_GLES_VERSION >= 30 - -#ifdef _ARCH_ARM_ - 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 ); -#endif // _ARCH_ARM_ - -#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( mGlesVersion >= 30 ) + { + configAttribs.PushBack( EGL_OPENGL_ES3_BIT_KHR ); + } + else + { + configAttribs.PushBack( EGL_OPENGL_ES2_BIT ); + } -#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 ); @@ -378,18 +498,9 @@ void EglImplementation::ChooseConfig( bool isWindowType, ColorDepth depth ) configAttribs.PushBack( EGL_BLUE_SIZE ); configAttribs.PushBack( 8 ); - 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 ); -#else - // There is a bug in the desktop emulator - // setting EGL_ALPHA_SIZE to 8 results in eglChooseConfig failing - configAttribs.PushBack( 8 ); -#endif // _ARCH_ARM_ - } +// For underlay video playback, we also need to set the alpha value of the 24/32bit window. + configAttribs.PushBack( EGL_ALPHA_SIZE ); + configAttribs.PushBack( 8 ); configAttribs.PushBack( EGL_DEPTH_SIZE ); configAttribs.PushBack( mDepthBufferRequired ? 24 : 0 ); @@ -407,8 +518,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. Retrying 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) { @@ -438,14 +566,28 @@ 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( mIsKhrCreateContextSupported ) { - 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( mGlesVersion / 10 ); } + mContextAttribs.PushBack( EGL_NONE ); + + return true; } EGLSurface EglImplementation::CreateSurfaceWindow( EGLNativeWindowType window, ColorDepth depth ) @@ -490,14 +632,17 @@ bool EglImplementation::ReplaceSurfaceWindow( EGLNativeWindowType window, EGLSur // the surface is bound to the context, so set the context to null MakeContextNull(); - // destroy the surface - DestroySurface( eglSurface ); + if( eglSurface ) + { + // destroy the surface + 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( eglSurface, eglContext ); + MakeContextCurrent( newEglSurface, eglContext ); return contextLost; } @@ -516,6 +661,16 @@ bool EglImplementation::ReplaceSurfacePixmap( EGLNativePixmapType pixmap, EGLSur return contextLost; } +void EglImplementation::SetGlesVersion( const int32_t glesVersion ) +{ + mGlesVersion = glesVersion; +} + +void EglImplementation::SetFirstFrameAfterResume() +{ + mSwapBufferCountAfterResume = 0; +} + EGLDisplay EglImplementation::GetDisplay() const { return mEglDisplay; @@ -526,6 +681,30 @@ EGLContext EglImplementation::GetContext() const return mEglContext; } +int32_t EglImplementation::GetGlesVersion() const +{ + return mGlesVersion; +} + +bool EglImplementation::IsSurfacelessContextSupported() const +{ + return mIsSurfacelessContextSupported; +} + +void EglImplementation::WaitClient() +{ + // Wait for EGL to finish executing all rendering calls for the current context + if ( eglWaitClient() != EGL_TRUE ) + { + TEST_EGL_ERROR("eglWaitClient"); + } +} + +bool EglImplementation::IsPartialUpdateRequired() const +{ + return mPartialUpdateRequired; +} + } // namespace Adaptor } // namespace Internal