/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
// INTERNAL INCLUDES
#include <dali/integration-api/adaptor-framework/render-surface-interface.h>
+#include <dali/integration-api/debug.h>
+#include <dali/internal/graphics/common/egl-include.h>
#include <dali/internal/system/common/configuration-manager.h>
#include <dali/internal/system/common/environment-options.h>
#include <dali/internal/window-system/common/display-utils.h> // For Utils::MakeUnique
+#include <dali/internal/window-system/common/window-base.h>
namespace Dali
{
{
namespace Adaptor
{
-EglGraphics::EglGraphics(EnvironmentOptions& environmentOptions)
-: mMultiSamplingLevel(0)
+EglGraphics::EglGraphics(
+ EnvironmentOptions& environmentOptions,
+ const Graphics::GraphicsCreateInfo& info,
+ Integration::DepthBufferAvailable depthBufferRequired,
+ Integration::StencilBufferAvailable stencilBufferRequired,
+ Integration::PartialUpdateAvailable partialUpdateRequired)
+: GraphicsInterface(info, depthBufferRequired, stencilBufferRequired, partialUpdateRequired),
+ mMultiSamplingLevel(info.multiSamplingLevel)
{
- mDepthBufferRequired = static_cast<Integration::DepthBufferAvailable>(environmentOptions.DepthBufferRequired());
- mStencilBufferRequired = static_cast<Integration::StencilBufferAvailable>(environmentOptions.StencilBufferRequired());
- mPartialUpdateRequired = static_cast<Integration::PartialUpdateAvailable>(environmentOptions.PartialUpdateRequired());
- mMultiSamplingLevel = environmentOptions.GetMultiSamplingLevel();
-
if(environmentOptions.GetGlesCallTime() > 0)
{
mGLES = Utils::MakeUnique<GlProxyImplementation>(environmentOptions);
{
}
-void EglGraphics::SetGlesVersion(const int32_t glesVersion)
-{
- if(mEglImplementation)
- {
- mEglImplementation->SetGlesVersion(glesVersion);
- }
-
- mGLES->SetGlesVersion(glesVersion);
-}
-
void EglGraphics::SetIsSurfacelessContextSupported(const bool isSupported)
{
mGLES->SetIsSurfacelessContextSupported(isSupported);
// Make the shared surfaceless context as current before rendering
mEglImplementation->MakeContextCurrent(EGL_NO_SURFACE, mEglImplementation->GetContext());
}
+
+ mGraphicsController.ActivateResourceContext();
+}
+
+void EglGraphics::ActivateSurfaceContext(Dali::Integration::RenderSurfaceInterface* surface)
+{
+ if(surface)
+ {
+ surface->InitializeGraphics();
+ surface->MakeContextCurrent();
+ }
+
+ mGraphicsController.ActivateSurfaceContext(surface);
}
-void EglGraphics::SetFirstFrameAfterResume()
+void EglGraphics::MakeContextCurrent(Graphics::SurfaceId surfaceId)
+{
+ auto search = mSurfaceMap.find(surfaceId);
+ if(DALI_UNLIKELY(search == mSurfaceMap.end()))
+ {
+ DALI_LOG_ERROR("Invalid surface id [%u] used! Ignore\n", surfaceId);
+ DALI_ASSERT_DEBUG(0 && "Invalid srufaceId");
+ return;
+ }
+
+ mEglImplementation->MakeContextCurrent(search->second.surface, search->second.context);
+}
+
+void EglGraphics::PostRender()
+{
+ ActivateResourceContext();
+
+ if(mGraphicsController.GetCurrentContext())
+ {
+ mGraphicsController.GetCurrentContext()->InvalidateDepthStencilBuffers();
+ }
+
+ mGraphicsController.PostRender();
+}
+
+void EglGraphics::Pause()
+{
+}
+
+void EglGraphics::Resume()
{
if(mEglImplementation)
{
}
}
-void EglGraphics::Initialize()
+int EglGraphics::GetBufferAge(Graphics::SurfaceId surfaceId)
+{
+ auto search = mSurfaceMap.find(surfaceId);
+ if(DALI_UNLIKELY(search == mSurfaceMap.end()))
+ {
+ DALI_LOG_ERROR("Invalid surface id [%u] used! Ignore\n", surfaceId);
+ DALI_ASSERT_DEBUG(0 && "Invalid srufaceId");
+ return 0;
+ }
+
+ return mEglImplementation->GetBufferAge(search->second.surface);
+}
+
+void EglGraphics::SetDamageRegion(Graphics::SurfaceId surfaceId, std::vector<Rect<int>>& damagedRegion)
+{
+ auto search = mSurfaceMap.find(surfaceId);
+ if(DALI_UNLIKELY(search == mSurfaceMap.end()))
+ {
+ DALI_LOG_ERROR("Invalid surface id [%u] used! Ignore\n", surfaceId);
+ DALI_ASSERT_DEBUG(0 && "Invalid srufaceId");
+ return;
+ }
+
+ mEglImplementation->SetDamageRegion(search->second.surface, damagedRegion);
+}
+
+void EglGraphics::SwapBuffers(Graphics::SurfaceId surfaceId)
+{
+ auto search = mSurfaceMap.find(surfaceId);
+ if(DALI_UNLIKELY(search == mSurfaceMap.end()))
+ {
+ DALI_LOG_ERROR("Invalid surface id [%u] used! Ignore\n", surfaceId);
+ DALI_ASSERT_DEBUG(0 && "Invalid srufaceId");
+ return;
+ }
+
+ mEglImplementation->SwapBuffers(search->second.surface);
+}
+
+void EglGraphics::SwapBuffers(Graphics::SurfaceId surfaceId, const std::vector<Rect<int>>& damagedRegion)
+{
+ auto search = mSurfaceMap.find(surfaceId);
+ if(DALI_UNLIKELY(search == mSurfaceMap.end()))
+ {
+ DALI_LOG_ERROR("Invalid surface id [%u] used! Ignore\n", surfaceId);
+ DALI_ASSERT_DEBUG(0 && "Invalid srufaceId");
+ return;
+ }
+
+ mEglImplementation->SwapBuffers(search->second.surface, damagedRegion);
+}
+
+void EglGraphics::Initialize(const Dali::DisplayConnection& displayConnection)
{
EglInitialize();
// Sync and context helper require EGL to be initialized first (can't execute in the constructor)
- mGraphicsController.Initialize(*mEglSync.get(), *mEglContextHelper.get());
+ mGraphicsController.Initialize(*mEglSync.get(), *this);
+ InitializeGraphicsAPI(displayConnection);
}
-void EglGraphics::Initialize(bool depth, bool stencil, bool partialRendering, int msaa)
+void EglGraphics::Initialize(const Dali::DisplayConnection& displayConnection, bool depth, bool stencil, bool partialRendering, int msaa)
{
mDepthBufferRequired = static_cast<Integration::DepthBufferAvailable>(depth);
mStencilBufferRequired = static_cast<Integration::StencilBufferAvailable>(stencil);
mMultiSamplingLevel = msaa;
EglInitialize();
+ InitializeGraphicsAPI(displayConnection);
+}
+
+void EglGraphics::InitializeGraphicsAPI(const Dali::DisplayConnection& displayConnection)
+{
+ auto display = displayConnection.GetNativeGraphicsDisplay();
+ auto eglDisplay = display.Get<EGLNativeDisplayType>();
+ mEglImplementation->InitializeGles(eglDisplay);
+}
+
+Dali::Any EglGraphics::GetDisplay() const
+{
+ return {mEglImplementation->GetDisplay()};
}
void EglGraphics::EglInitialize()
{
mEglSync = Utils::MakeUnique<EglSyncImplementation>();
- mEglContextHelper = Utils::MakeUnique<EglContextHelperImplementation>();
mEglImplementation = Utils::MakeUnique<EglImplementation>(mMultiSamplingLevel, mDepthBufferRequired, mStencilBufferRequired, mPartialUpdateRequired);
mEglImageExtensions = Utils::MakeUnique<EglImageExtensions>(mEglImplementation.get());
- mEglSync->Initialize(mEglImplementation.get()); // The sync impl needs the EglDisplay
- mEglContextHelper->Initialize(mEglImplementation.get()); // The context helper impl needs the EglContext
+ mEglSync->Initialize(mEglImplementation.get()); // The sync impl needs the EglDisplay
+}
+
+Graphics::SurfaceId EglGraphics::CreateSurface(Graphics::SurfaceFactory* surfaceFactory, WindowBase* windowBase, ColorDepth colorDepth, int width, int height)
+{
+ // Create the OpenGL context for this window
+ mEglImplementation->ChooseConfig(true, colorDepth);
+ EGLContext context = 0;
+ mEglImplementation->CreateWindowContext(context);
+
+ auto window = windowBase->CreateWindow(width, height);
+ auto eglWindow = reinterpret_cast<EGLNativeWindowType>(window.Get<void*>());
+ auto eglSurface = mEglImplementation->CreateSurfaceWindow(eglWindow, colorDepth);
+
+ auto surfaceId = ++mBaseSurfaceId;
+ mSurfaceMap[surfaceId] = EglSurfaceContext{windowBase, eglSurface, context};
+
+ return surfaceId;
}
-void EglGraphics::ConfigureSurface(Dali::RenderSurfaceInterface* surface)
+void EglGraphics::DestroySurface(Graphics::SurfaceId surfaceId)
+{
+ auto search = mSurfaceMap.find(surfaceId);
+ if(DALI_UNLIKELY(search == mSurfaceMap.end()))
+ {
+ DALI_LOG_ERROR("Invalid surface id [%u] used! Ignore\n", surfaceId);
+ DALI_ASSERT_DEBUG(0 && "Invalid srufaceId");
+ return;
+ }
+
+ mEglImplementation->DestroySurface(search->second.surface);
+ mEglImplementation->DestroyContext(search->second.context);
+ search->second.windowBase->DestroyWindow();
+ mSurfaceMap.erase(search);
+}
+
+bool EglGraphics::ReplaceSurface(Graphics::SurfaceId surfaceId, int width, int height)
+{
+ auto search = mSurfaceMap.find(surfaceId);
+ if(DALI_UNLIKELY(search == mSurfaceMap.end()))
+ {
+ DALI_LOG_ERROR("Invalid surface id [%u] used! Ignore\n", surfaceId);
+ DALI_ASSERT_DEBUG(0 && "Invalid srufaceId");
+ return false;
+ }
+
+ auto& windowBase = search->second.windowBase;
+
+ // Destroy the old graphics window
+ windowBase->DestroyWindow();
+
+ // Create the EGL window
+ Dali::Any window = windowBase->CreateWindow(width, height);
+
+ EGLNativeWindowType eglWindow = window.Get<EGLNativeWindowType>();
+ auto& context = search->second.context;
+ auto& surface = search->second.surface;
+ return mEglImplementation->ReplaceSurfaceWindow(eglWindow, surface, context); // Should update the map.
+}
+
+void EglGraphics::ConfigureSurface(Dali::Integration::RenderSurfaceInterface* surface)
{
DALI_ASSERT_ALWAYS(mEglImplementation && "EGLImplementation not created");
if(!mEglImplementation->ChooseConfig(true, COLOR_DEPTH_32))
{
// Retry to use OpenGL es 2.0
- SetGlesVersion(20);
+ mEglImplementation->SetGlesVersion(20);
+
+ // Mark gles that we will use gles 2.0 version.
+ // After this call, we will not change mGLES version anymore.
+ mGLES->SetGlesVersion(20);
+
mEglImplementation->ChooseConfig(true, COLOR_DEPTH_32);
}
bool isSurfacelessContextSupported = mEglImplementation->IsSurfacelessContextSupported();
SetIsSurfacelessContextSupported(isSurfacelessContextSupported);
- RenderSurfaceInterface* currentSurface = nullptr;
+ Integration::RenderSurfaceInterface* currentSurface = nullptr;
if(isSurfacelessContextSupported)
{
// Create a surfaceless OpenGL context for shared resources
mEglImplementation->CreateContext();
- mEglImplementation->MakeContextCurrent(EGL_NO_SURFACE, mEglImplementation->GetContext());
+ ActivateResourceContext();
}
else
{
currentSurface = surface;
if(currentSurface)
{
- currentSurface->InitializeGraphics();
- currentSurface->MakeContextCurrent();
+ ActivateSurfaceContext(currentSurface);
}
}
- mGLES->ContextCreated();
- SetGlesVersion(mGLES->GetGlesVersion());
+ mGLES->ContextCreated(); // After this call, we can know exact gles version.
+ auto glesVersion = mGLES->GetGlesVersion();
+
+ // Set more detail GLES version to egl and graphics controller.
+ // Note. usually we don't need EGL client's minor version. So don't need to choose config one more time.
+ mEglImplementation->SetGlesVersion(glesVersion);
+ mGraphicsController.SetGLESVersion(static_cast<Graphics::GLES::GLESVersion>(glesVersion));
}
void EglGraphics::Shutdown()
mGraphicsController.Destroy();
}
-GlImplementation& EglGraphics::GetGlesInterface()
-{
- return *mGLES;
-}
-
Integration::GlAbstraction& EglGraphics::GetGlAbstraction() const
{
DALI_ASSERT_DEBUG(mGLES && "GLImplementation not created");
return *mEglSync;
}
-EglContextHelperImplementation& EglGraphics::GetContextHelperImplementation()
-{
- DALI_ASSERT_DEBUG(mEglContextHelper && "EglContextHelperImplementation not created");
- return *mEglContextHelper;
-}
-
EglImageExtensions* EglGraphics::GetImageExtensions()
{
DALI_ASSERT_DEBUG(mEglImageExtensions && "EglImageExtensions not created");
void EglGraphics::CacheConfigurations(ConfigurationManager& configurationManager)
{
mGLES->SetIsAdvancedBlendEquationSupported(configurationManager.IsAdvancedBlendEquationSupported());
+ mGLES->SetIsMultisampledRenderToTextureSupported(configurationManager.IsMultisampledRenderToTextureSupported());
mGLES->SetShadingLanguageVersion(configurationManager.GetShadingLanguageVersion());
}
+void EglGraphics::FrameStart()
+{
+ mGraphicsController.FrameStart();
+}
+
+void EglGraphics::PostRenderDebug()
+{
+ mGLES->PostRender();
+}
+
+void EglGraphics::LogMemoryPools()
+{
+ std::size_t graphicsCapacity = mGraphicsController.GetCapacity();
+ DALI_LOG_RELEASE_INFO(
+ "EglGraphics:\n"
+ " GraphicsController Capacity: %lu\n",
+ graphicsCapacity);
+}
+
} // namespace Adaptor
} // namespace Internal
} // namespace Dali