From 03de074d05108fa9fb07c6b847c7163ada5776da Mon Sep 17 00:00:00 2001 From: Stan Iliev Date: Thu, 7 Jul 2016 12:35:54 -0400 Subject: [PATCH] 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 --- libs/hwui/Properties.cpp | 17 +++++++++++++++++ libs/hwui/Properties.h | 15 +++++++++++++++ libs/hwui/renderthread/CanvasContext.cpp | 27 +++++++++++++++++++++++++++ libs/hwui/renderthread/CanvasContext.h | 8 ++++++-- libs/hwui/renderthread/RenderProxy.cpp | 2 +- libs/hwui/tests/unit/RenderNodeTests.cpp | 7 ++++--- 6 files changed, 70 insertions(+), 6 deletions(-) diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp index 112ba1192a07..d0ae1d4733cf 100644 --- a/libs/hwui/Properties.cpp +++ b/libs/hwui/Properties.cpp @@ -63,6 +63,7 @@ int Properties::overrideSpotShadowStrength = -1; 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 @@ ProfileType Properties::getProfileType() { 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 cdfc081dd2ff..880a90e4421f 100644 --- a/libs/hwui/Properties.h +++ b/libs/hwui/Properties.h @@ -153,6 +153,12 @@ enum DebugLevel { #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 @@ enum class StencilClipDebug { 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 @@ public: static int overrideSpotShadowStrength; static ProfileType getProfileType(); + static RenderPipelineType getRenderPipelineType(); // Should be used only by test apps static bool waitForGpuCompletion; @@ -304,6 +318,7 @@ public: 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 0a48a0c0bc68..582c3eaf4789 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -61,6 +61,28 @@ namespace android { 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 @@ int64_t CanvasContext::getFrameNumber() { 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 528e29e0c695..3e3c6e6c9f74 100644 --- a/libs/hwui/renderthread/CanvasContext.h +++ b/libs/hwui/renderthread/CanvasContext.h @@ -72,8 +72,8 @@ enum SwapBehavior { // 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 @@ public: static void trimMemory(RenderThread& thread, int level); static void invokeFunctor(RenderThread& thread, Functor* functor); + static bool isSkiaEnabled(); Layer* createTextureLayer(); @@ -167,6 +168,9 @@ public: 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 10a17f82eced..c689544a9e9a 100644 --- a/libs/hwui/renderthread/RenderProxy.cpp +++ b/libs/hwui/renderthread/RenderProxy.cpp @@ -55,7 +55,7 @@ namespace renderthread { 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 fb5be0fab52d..132601efb543 100644 --- a/libs/hwui/tests/unit/RenderNodeTests.cpp +++ b/libs/hwui/tests/unit/RenderNodeTests.cpp @@ -105,8 +105,9 @@ TEST(RenderNode, releasedCallback) { 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::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 @@ RENDERTHREAD_TEST(RenderNode, prepareTree_nullableDisplayList) { nullDLNode->prepareTree(info); } - canvasContext.destroy(nullptr); + canvasContext->destroy(nullptr); } -- 2.11.0