Implement runtime switch to select default renderer mode
Add a system property debug.hwui.default_renderer, which allows
to set rendering mode to OpenGL (default), Skia OpenGL or Vulkan.
Change-Id: I8bca5bacc5108f77437e340ac61f2d8db8cc4c39
diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp
index 112ba11..d0ae1d4 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -63,6 +63,7 @@
ProfileType Properties::sProfileType = ProfileType::None;
bool Properties::sDisableProfileBars = false;
+RenderPipelineType Properties::sRenderPipelineType = RenderPipelineType::NotInitialized;
bool Properties::waitForGpuCompletion = false;
bool Properties::forceDrawFrame = false;
@@ -205,5 +206,21 @@
return sProfileType;
}
+RenderPipelineType Properties::getRenderPipelineType() {
+ if (RenderPipelineType::NotInitialized != sRenderPipelineType) {
+ return sRenderPipelineType;
+ }
+ char prop[PROPERTY_VALUE_MAX];
+ property_get(PROPERTY_DEFAULT_RENDERER, prop, "opengl");
+ if (!strcmp(prop, "skiagl") ) {
+ sRenderPipelineType = RenderPipelineType::SkiaGL;
+ } else if (!strcmp(prop, "vulkan") ) {
+ sRenderPipelineType = RenderPipelineType::Vulkan;
+ } else { //"opengl"
+ sRenderPipelineType = RenderPipelineType::OpenGL;
+ }
+ return sRenderPipelineType;
+}
+
}; // namespace uirenderer
}; // namespace android
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index cdfc081..880a90e 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -153,6 +153,12 @@
#define PROPERTY_FILTER_TEST_OVERHEAD "debug.hwui.filter_test_overhead"
+/**
+ * Allows to set rendering pipeline mode to OpenGL (default), Skia OpenGL
+ * or Vulkan.
+ */
+#define PROPERTY_DEFAULT_RENDERER "debug.hwui.default_renderer"
+
///////////////////////////////////////////////////////////////////////////////
// Runtime configuration properties
///////////////////////////////////////////////////////////////////////////////
@@ -245,6 +251,13 @@
ShowRegion
};
+enum class RenderPipelineType {
+ OpenGL = 0,
+ SkiaGL,
+ Vulkan,
+ NotInitialized = 128
+};
+
/**
* Renderthread-only singleton which manages several static rendering properties. Most of these
* are driven by system properties which are queried once at initialization, and again if init()
@@ -292,6 +305,7 @@
static int overrideSpotShadowStrength;
static ProfileType getProfileType();
+ static RenderPipelineType getRenderPipelineType();
// Should be used only by test apps
static bool waitForGpuCompletion;
@@ -304,6 +318,7 @@
private:
static ProfileType sProfileType;
static bool sDisableProfileBars;
+ static RenderPipelineType sRenderPipelineType;
}; // class Caches
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 0a48a0c..582c3ea 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -61,6 +61,28 @@
namespace uirenderer {
namespace renderthread {
+CanvasContext* CanvasContext::create(RenderThread& thread,
+ bool translucent, RenderNode* rootRenderNode, IContextFactory* contextFactory) {
+
+ auto renderType = Properties::getRenderPipelineType();
+ switch (renderType) {
+ case RenderPipelineType::OpenGL:
+ return new CanvasContext(thread, translucent, rootRenderNode, contextFactory);
+ case RenderPipelineType::SkiaGL:
+ //TODO: implement SKIA GL
+ LOG_ALWAYS_FATAL("skiaGL canvas type not implemented.");
+ break;
+ case RenderPipelineType::Vulkan:
+ //TODO: implement Vulkan
+ LOG_ALWAYS_FATAL("Vulkan canvas type not implemented.");
+ break;
+ default:
+ LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t) renderType);
+ break;
+ }
+ return nullptr;
+}
+
CanvasContext::CanvasContext(RenderThread& thread, bool translucent,
RenderNode* rootRenderNode, IContextFactory* contextFactory)
: mRenderThread(thread)
@@ -789,6 +811,11 @@
return mFrameNumber;
}
+bool CanvasContext::isSkiaEnabled() {
+ auto renderType = Properties::getRenderPipelineType();
+ return RenderPipelineType::SkiaGL == renderType || RenderPipelineType::Vulkan == renderType;
+}
+
} /* namespace renderthread */
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 528e29e..3e3c6e6 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -72,8 +72,8 @@
// TODO: Rename to Renderer or some other per-window, top-level manager
class CanvasContext : public IFrameCallback {
public:
- CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode,
- IContextFactory* contextFactory);
+ static CanvasContext* create(RenderThread& thread, bool translucent,
+ RenderNode* rootRenderNode, IContextFactory* contextFactory);
virtual ~CanvasContext();
// Won't take effect until next EGLSurface creation
@@ -107,6 +107,7 @@
static void trimMemory(RenderThread& thread, int level);
static void invokeFunctor(RenderThread& thread, Functor* functor);
+ static bool isSkiaEnabled();
Layer* createTextureLayer();
@@ -167,6 +168,9 @@
ANDROID_API int64_t getFrameNumber();
private:
+ CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode,
+ IContextFactory* contextFactory);
+
friend class RegisterFrameCallbackTask;
// TODO: Replace with something better for layer & other GL object
// lifecycle tracking
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 10a17f8..c689544 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -55,7 +55,7 @@
CREATE_BRIDGE4(createContext, RenderThread* thread, bool translucent,
RenderNode* rootRenderNode, IContextFactory* contextFactory) {
- return new CanvasContext(*args->thread, args->translucent,
+ return CanvasContext::create(*args->thread, args->translucent,
args->rootRenderNode, args->contextFactory);
}
diff --git a/libs/hwui/tests/unit/RenderNodeTests.cpp b/libs/hwui/tests/unit/RenderNodeTests.cpp
index fb5be0f..132601e 100644
--- a/libs/hwui/tests/unit/RenderNodeTests.cpp
+++ b/libs/hwui/tests/unit/RenderNodeTests.cpp
@@ -105,8 +105,9 @@
RENDERTHREAD_TEST(RenderNode, prepareTree_nullableDisplayList) {
ContextFactory contextFactory;
- CanvasContext canvasContext(renderThread, false, nullptr, &contextFactory);
- TreeInfo info(TreeInfo::MODE_RT_ONLY, canvasContext);
+ std::unique_ptr<CanvasContext> canvasContext(CanvasContext::create(
+ renderThread, false, nullptr, &contextFactory));
+ TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get());
DamageAccumulator damageAccumulator;
info.damageAccumulator = &damageAccumulator;
info.observer = nullptr;
@@ -128,5 +129,5 @@
nullDLNode->prepareTree(info);
}
- canvasContext.destroy(nullptr);
+ canvasContext->destroy(nullptr);
}