Remove RenderThread from EglManager
Refactor to make EglManager re-usable.
Test: hwuiunit passes, hwuimacro works
Change-Id: Ie8e9398c703fada1dc5d8baca5f42485eadea202
diff --git a/libs/hwui/EglReadback.cpp b/libs/hwui/EglReadback.cpp
index a836afe..2d5367b 100644
--- a/libs/hwui/EglReadback.cpp
+++ b/libs/hwui/EglReadback.cpp
@@ -58,7 +58,7 @@
CopyResult EglReadback::copyGraphicBufferInto(GraphicBuffer* graphicBuffer,
Matrix4& texTransform, const Rect& srcRect,
SkBitmap* bitmap) {
- mRenderThread.eglManager().initialize();
+ mRenderThread.requireGlContext();
// TODO: Can't use Image helper since it forces GL_TEXTURE_2D usage via
// GL_OES_EGL_image, which doesn't work since we need samplerExternalOES
// to be able to properly sample from the buffer.
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index b7aa78b..c3357a2 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -166,7 +166,7 @@
}
DeferredLayerUpdater* SkiaOpenGLPipeline::createTextureLayer() {
- mEglManager.initialize();
+ mRenderThread.requireGlContext();
return new DeferredLayerUpdater(mRenderThread.renderState(), createLayer, Layer::Api::OpenGL);
}
@@ -184,6 +184,7 @@
}
if (surface) {
+ mRenderThread.requireGlContext();
const bool wideColorGamut = colorMode == ColorMode::WideColorGamut;
mEglSurface = mEglManager.createSurface(surface, wideColorGamut);
}
@@ -274,7 +275,7 @@
sk_sp<Bitmap> SkiaOpenGLPipeline::allocateHardwareBitmap(renderthread::RenderThread& renderThread,
SkBitmap& skBitmap) {
- renderThread.eglManager().initialize();
+ renderThread.requireGlContext();
sk_sp<GrContext> grContext = sk_ref_sp(renderThread.getGrContext());
const SkImageInfo& info = skBitmap.info();
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 95ca8d9..a36dae4 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -552,7 +552,7 @@
ATRACE_CALL();
if (level >= TRIM_MEMORY_COMPLETE) {
thread.cacheManager().trimMemory(CacheManager::TrimMemoryMode::Complete);
- thread.eglManager().destroy();
+ thread.destroyGlContext();
thread.vulkanManager().destroy();
} else if (level >= TRIM_MEMORY_UI_HIDDEN) {
thread.cacheManager().trimMemory(CacheManager::TrimMemoryMode::UiHidden);
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index 6e239e3..cd21822 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -16,27 +16,19 @@
#include "EglManager.h"
-#include <string>
-
#include <cutils/properties.h>
#include <log/log.h>
+#include <utils/Trace.h>
#include "utils/StringUtils.h"
-#include "Caches.h"
#include "DeviceInfo.h"
#include "Frame.h"
#include "Properties.h"
-#include "RenderThread.h"
-#include "Texture.h"
-#include "renderstate/RenderState.h"
#include <EGL/eglext.h>
-#include <GrContextOptions.h>
-#include <gl/GrGLInterface.h>
-#ifdef HWUI_GLES_WRAP_ENABLED
-#include "debug/GlesDriver.h"
-#endif
+#include <string>
+#include <vector>
#define GLES_VERSION 2
@@ -83,17 +75,21 @@
bool glColorSpace = false;
bool scRGB = false;
bool contextPriority = false;
+ bool surfacelessContext = false;
} EglExtensions;
-EglManager::EglManager(RenderThread& thread)
- : mRenderThread(thread)
- , mEglDisplay(EGL_NO_DISPLAY)
+EglManager::EglManager()
+ : mEglDisplay(EGL_NO_DISPLAY)
, mEglConfig(nullptr)
, mEglConfigWideGamut(nullptr)
, mEglContext(EGL_NO_CONTEXT)
, mPBufferSurface(EGL_NO_SURFACE)
, mCurrentSurface(EGL_NO_SURFACE) {}
+EglManager::~EglManager() {
+ destroy();
+}
+
void EglManager::initialize() {
if (hasEglContext()) return;
@@ -126,26 +122,8 @@
loadConfigs();
createContext();
createPBufferSurface();
- makeCurrent(mPBufferSurface);
+ makeCurrent(mPBufferSurface, nullptr, /* force */ true);
DeviceInfo::initialize();
- mRenderThread.renderState().onGLContextCreated();
-
- if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL) {
-#ifdef HWUI_GLES_WRAP_ENABLED
- debug::GlesDriver* driver = debug::GlesDriver::get();
- sk_sp<const GrGLInterface> glInterface(driver->getSkiaInterface());
-#else
- sk_sp<const GrGLInterface> glInterface(GrGLCreateNativeInterface());
-#endif
- LOG_ALWAYS_FATAL_IF(!glInterface.get());
-
- GrContextOptions options;
- options.fDisableDistanceFieldPaths = true;
- mRenderThread.cacheManager().configureContext(&options);
- sk_sp<GrContext> grContext(GrContext::MakeGL(std::move(glInterface), options));
- LOG_ALWAYS_FATAL_IF(!grContext.get());
- mRenderThread.setGrContext(grContext);
- }
}
void EglManager::initExtensions() {
@@ -170,6 +148,7 @@
EglExtensions.scRGB = extensions.has("EGL_EXT_gl_colorspace_scrgb");
#endif
EglExtensions.contextPriority = extensions.has("EGL_IMG_context_priority");
+ EglExtensions.surfacelessContext = extensions.has("EGL_KHR_surfaceless_context");
}
bool EglManager::hasEglContext() {
@@ -195,7 +174,7 @@
EGL_CONFIG_CAVEAT,
EGL_NONE,
EGL_STENCIL_SIZE,
- Stencil::getStencilSize(),
+ STENCIL_BUFFER_SIZE,
EGL_SURFACE_TYPE,
EGL_WINDOW_BIT | swapBehavior,
EGL_NONE};
@@ -232,7 +211,7 @@
EGL_DEPTH_SIZE,
0,
EGL_STENCIL_SIZE,
- Stencil::getStencilSize(),
+ STENCIL_BUFFER_SIZE,
EGL_SURFACE_TYPE,
EGL_WINDOW_BIT | swapBehavior,
EGL_NONE};
@@ -269,14 +248,14 @@
LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY,
"usePBufferSurface() called on uninitialized GlobalContext!");
- if (mPBufferSurface == EGL_NO_SURFACE) {
+ if (mPBufferSurface == EGL_NO_SURFACE && !EglExtensions.surfacelessContext) {
EGLint attribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
mPBufferSurface = eglCreatePbufferSurface(mEglDisplay, mEglConfig, attribs);
}
}
EGLSurface EglManager::createSurface(EGLNativeWindowType window, bool wideColorGamut) {
- initialize();
+ LOG_ALWAYS_FATAL_IF(!hasEglContext(), "Not initialized");
wideColorGamut = wideColorGamut && EglExtensions.glColorSpace && EglExtensions.scRGB &&
EglExtensions.pixelFormatFloat && EglExtensions.noConfigContext;
@@ -350,10 +329,10 @@
void EglManager::destroy() {
if (mEglDisplay == EGL_NO_DISPLAY) return;
- mRenderThread.setGrContext(nullptr);
- mRenderThread.renderState().onGLContextDestroyed();
eglDestroyContext(mEglDisplay, mEglContext);
- eglDestroySurface(mEglDisplay, mPBufferSurface);
+ if (mPBufferSurface != EGL_NO_SURFACE) {
+ eglDestroySurface(mEglDisplay, mPBufferSurface);
+ }
eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglTerminate(mEglDisplay);
eglReleaseThread();
@@ -364,8 +343,8 @@
mCurrentSurface = EGL_NO_SURFACE;
}
-bool EglManager::makeCurrent(EGLSurface surface, EGLint* errOut) {
- if (isCurrent(surface)) return false;
+bool EglManager::makeCurrent(EGLSurface surface, EGLint* errOut, bool force) {
+ if (!force && isCurrent(surface)) return false;
if (surface == EGL_NO_SURFACE) {
// Ensure we always have a valid surface & context
diff --git a/libs/hwui/renderthread/EglManager.h b/libs/hwui/renderthread/EglManager.h
index ef9effb..ca6d1b8 100644
--- a/libs/hwui/renderthread/EglManager.h
+++ b/libs/hwui/renderthread/EglManager.h
@@ -33,8 +33,12 @@
// and EGLConfig, which are re-used by CanvasContext
class EglManager {
public:
+ explicit EglManager();
+
+ ~EglManager();
+
static const char* eglErrorString();
- // Returns true on success, false on failure
+
void initialize();
bool hasEglContext();
@@ -46,7 +50,7 @@
bool isCurrent(EGLSurface surface) { return mCurrentSurface == surface; }
// Returns true if the current surface changed, false if it was already current
- bool makeCurrent(EGLSurface surface, EGLint* errOut = nullptr);
+ bool makeCurrent(EGLSurface surface, EGLint* errOut = nullptr, bool force = false);
Frame beginFrame(EGLSurface surface);
void damageFrame(const Frame& frame, const SkRect& dirty);
// If this returns true it is mandatory that swapBuffers is called
@@ -61,10 +65,6 @@
void fence();
private:
- friend class RenderThread;
- explicit EglManager(RenderThread& thread);
- // EglContext is never destroyed, method is purposely not implemented
- ~EglManager();
void initExtensions();
void createPBufferSurface();
@@ -72,8 +72,6 @@
void createContext();
EGLint queryBufferAge(EGLSurface surface);
- RenderThread& mRenderThread;
-
EGLDisplay mEglDisplay;
EGLConfig mEglConfig;
EGLConfig mEglConfigWideGamut;
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index 5e067da..711ece4 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -30,6 +30,13 @@
#include "utils/FatVector.h"
#include "utils/TimeUtils.h"
+#ifdef HWUI_GLES_WRAP_ENABLED
+#include "debug/GlesDriver.h"
+#endif
+
+#include <GrContextOptions.h>
+#include <gl/GrGLInterface.h>
+
#include <gui/DisplayEventReceiver.h>
#include <sys/resource.h>
#include <utils/Condition.h>
@@ -163,12 +170,45 @@
nsecs_t frameIntervalNanos = static_cast<nsecs_t>(1000000000 / mDisplayInfo.fps);
mTimeLord.setFrameInterval(frameIntervalNanos);
initializeDisplayEventReceiver();
- mEglManager = new EglManager(*this);
+ mEglManager = new EglManager();
mRenderState = new RenderState(*this);
mVkManager = new VulkanManager(*this);
mCacheManager = new CacheManager(mDisplayInfo);
}
+void RenderThread::requireGlContext() {
+ if (mEglManager->hasEglContext()) {
+ return;
+ }
+ mEglManager->initialize();
+ renderState().onGLContextCreated();
+
+ if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL) {
+#ifdef HWUI_GLES_WRAP_ENABLED
+ debug::GlesDriver* driver = debug::GlesDriver::get();
+ sk_sp<const GrGLInterface> glInterface(driver->getSkiaInterface());
+#else
+ sk_sp<const GrGLInterface> glInterface(GrGLCreateNativeInterface());
+#endif
+ LOG_ALWAYS_FATAL_IF(!glInterface.get());
+
+ GrContextOptions options;
+ options.fDisableDistanceFieldPaths = true;
+ cacheManager().configureContext(&options);
+ sk_sp<GrContext> grContext(GrContext::MakeGL(std::move(glInterface), options));
+ LOG_ALWAYS_FATAL_IF(!grContext.get());
+ setGrContext(grContext);
+ }
+}
+
+void RenderThread::destroyGlContext() {
+ if (mEglManager->hasEglContext()) {
+ setGrContext(nullptr);
+ renderState().onGLContextDestroyed();
+ mEglManager->destroy();
+ }
+}
+
void RenderThread::dumpGraphicsMemory(int fd) {
globalProfileData()->dump(fd);
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index 689f518..4a1fd9e 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -103,6 +103,9 @@
sk_sp<Bitmap> allocateHardwareBitmap(SkBitmap& skBitmap);
void dumpGraphicsMemory(int fd);
+ void requireGlContext();
+ void destroyGlContext();
+
/**
* isCurrent provides a way to query, if the caller is running on
* the render thread.
diff --git a/libs/hwui/tests/common/TestUtils.cpp b/libs/hwui/tests/common/TestUtils.cpp
index 16c5afd..b2fccd4 100644
--- a/libs/hwui/tests/common/TestUtils.cpp
+++ b/libs/hwui/tests/common/TestUtils.cpp
@@ -140,7 +140,7 @@
if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) {
renderThread.vulkanManager().initialize();
} else {
- renderThread.eglManager().initialize();
+ renderThread.requireGlContext();
}
rtCallback(renderThread);
@@ -149,7 +149,7 @@
renderThread.vulkanManager().destroy();
} else {
renderThread.renderState().flush(Caches::FlushMode::Full);
- renderThread.eglManager().destroy();
+ renderThread.destroyGlContext();
}
}
diff --git a/libs/hwui/tests/unit/GpuMemoryTrackerTests.cpp b/libs/hwui/tests/unit/GpuMemoryTrackerTests.cpp
index 9bfb082..08b9679 100644
--- a/libs/hwui/tests/unit/GpuMemoryTrackerTests.cpp
+++ b/libs/hwui/tests/unit/GpuMemoryTrackerTests.cpp
@@ -39,7 +39,7 @@
// current thread can spoof being a GPU thread
static void destroyEglContext() {
if (TestUtils::isRenderThreadRunning()) {
- TestUtils::runOnRenderThread([](RenderThread& thread) { thread.eglManager().destroy(); });
+ TestUtils::runOnRenderThread([](RenderThread& thread) { thread.destroyGlContext(); });
}
}