diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk index 5069a9a686fec..a9bd75c561645 100644 --- a/libs/hwui/Android.mk +++ b/libs/hwui/Android.mk @@ -266,6 +266,7 @@ LOCAL_SRC_FILES += \ tests/unit/BakedOpDispatcherTests.cpp \ tests/unit/BakedOpRendererTests.cpp \ tests/unit/BakedOpStateTests.cpp \ + tests/unit/CanvasContextTests.cpp \ tests/unit/CanvasStateTests.cpp \ tests/unit/ClipAreaTests.cpp \ tests/unit/DamageAccumulatorTests.cpp \ diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index fe0f56ad13329..8ed889393c1bf 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -97,6 +97,31 @@ void CanvasContext::destroyLayer(RenderNode* node) { } } +void CanvasContext::invokeFunctor(const RenderThread& thread, Functor* functor) { + ATRACE_CALL(); + auto renderType = Properties::getRenderPipelineType(); + switch (renderType) { + case RenderPipelineType::OpenGL: + OpenGLPipeline::invokeFunctor(thread, functor); + break; + default: + LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t) renderType); + break; + } +} + +void CanvasContext::prepareToDraw(const RenderThread& thread, Bitmap* bitmap) { + auto renderType = Properties::getRenderPipelineType(); + switch (renderType) { + case RenderPipelineType::OpenGL: + OpenGLPipeline::prepareToDraw(thread, bitmap); + break; + default: + LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t) renderType); + break; + } +} + CanvasContext::CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode, IContextFactory* contextFactory, std::unique_ptr renderPipeline) @@ -425,8 +450,11 @@ void CanvasContext::draw() { GpuMemoryTracker::onFrameCompleted(); #ifdef BUGREPORT_FONT_CACHE_USAGE - Caches& caches = Caches::getInstance(); - caches.fontRenderer.getFontRenderer().historyTracker().frameCompleted(); + auto renderType = Properties::getRenderPipelineType(); + if (RenderPipelineType::OpenGL == renderType) { + Caches& caches = Caches::getInstance(); + caches.fontRenderer.getFontRenderer().historyTracker().frameCompleted(); + } #endif } @@ -456,16 +484,6 @@ void CanvasContext::prepareAndDraw(RenderNode* node) { } } -void CanvasContext::invokeFunctor(RenderThread& thread, Functor* functor) { - ATRACE_CALL(); - DrawGlInfo::Mode mode = DrawGlInfo::kModeProcessNoContext; - if (thread.eglManager().hasEglContext()) { - mode = DrawGlInfo::kModeProcess; - } - - thread.renderState().invokeFunctor(functor, mode, nullptr); -} - void CanvasContext::markLayerInUse(RenderNode* node) { if (mPrefetchedLayers.erase(node)) { node->decStrong(nullptr); @@ -520,10 +538,6 @@ void CanvasContext::destroyHardwareResources(TreeObserver* observer) { for (const sp& node : mRenderNodes) { node->destroyHardwareResources(observer); } - Caches& caches = Caches::getInstance(); - // Make sure to release all the textures we were owning as there won't - // be another draw - caches.textureCache.resetMarkInUse(this); mRenderPipeline->onDestroyHardwareResources(); } } diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h index 125f1099b0569..b61eef21087a5 100644 --- a/libs/hwui/renderthread/CanvasContext.h +++ b/libs/hwui/renderthread/CanvasContext.h @@ -85,6 +85,10 @@ public: */ static void destroyLayer(RenderNode* node); + static void invokeFunctor(const RenderThread& thread, Functor* functor); + + static void prepareToDraw(const RenderThread& thread, Bitmap* bitmap); + /* * If Properties::isSkiaEnabled() is true then this will return the Skia * grContext associated with the current RenderPipeline. @@ -121,8 +125,6 @@ public: void destroyHardwareResources(TreeObserver* observer); static void trimMemory(RenderThread& thread, int level); - static void invokeFunctor(RenderThread& thread, Functor* functor); - DeferredLayerUpdater* createTextureLayer(); void stopDrawing(); diff --git a/libs/hwui/renderthread/OpenGLPipeline.cpp b/libs/hwui/renderthread/OpenGLPipeline.cpp index 1ad38031c487e..cca0fca418179 100644 --- a/libs/hwui/renderthread/OpenGLPipeline.cpp +++ b/libs/hwui/renderthread/OpenGLPipeline.cpp @@ -165,6 +165,10 @@ bool OpenGLPipeline::isContextReady() { } void OpenGLPipeline::onDestroyHardwareResources() { + Caches& caches = Caches::getInstance(); + // Make sure to release all the textures we were owning as there won't + // be another draw + caches.textureCache.resetMarkInUse(this); mRenderThread.renderState().flush(Caches::FlushMode::Layers); } @@ -225,6 +229,21 @@ void OpenGLPipeline::destroyLayer(RenderNode* node) { } } +void OpenGLPipeline::prepareToDraw(const RenderThread& thread, Bitmap* bitmap) { + if (Caches::hasInstance() && thread.eglManager().hasEglContext()) { + ATRACE_NAME("Bitmap#prepareToDraw task"); + Caches::getInstance().textureCache.prefetch(bitmap); + } +} + +void OpenGLPipeline::invokeFunctor(const RenderThread& thread, Functor* functor) { + DrawGlInfo::Mode mode = DrawGlInfo::kModeProcessNoContext; + if (thread.eglManager().hasEglContext()) { + mode = DrawGlInfo::kModeProcess; + } + thread.renderState().invokeFunctor(functor, mode, nullptr); +} + } /* namespace renderthread */ } /* namespace uirenderer */ } /* namespace android */ diff --git a/libs/hwui/renderthread/OpenGLPipeline.h b/libs/hwui/renderthread/OpenGLPipeline.h index 2f661dcfec2f1..8722d5983ff9c 100644 --- a/libs/hwui/renderthread/OpenGLPipeline.h +++ b/libs/hwui/renderthread/OpenGLPipeline.h @@ -56,6 +56,8 @@ public: bool createOrUpdateLayer(RenderNode* node, const DamageAccumulator& damageAccumulator) override; static void destroyLayer(RenderNode* node); + static void prepareToDraw(const RenderThread& thread, Bitmap* bitmap); + static void invokeFunctor(const RenderThread& thread, Functor* functor); private: EglManager& mEglManager; diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp index 42da293021b9c..6cb2b9cfac8f8 100644 --- a/libs/hwui/renderthread/RenderProxy.cpp +++ b/libs/hwui/renderthread/RenderProxy.cpp @@ -618,10 +618,7 @@ int RenderProxy::copySurfaceInto(sp& surface, int left, int top, } CREATE_BRIDGE2(prepareToDraw, RenderThread* thread, Bitmap* bitmap) { - if (Caches::hasInstance() && args->thread->eglManager().hasEglContext()) { - ATRACE_NAME("Bitmap#prepareToDraw task"); - Caches::getInstance().textureCache.prefetch(args->bitmap); - } + CanvasContext::prepareToDraw(*args->thread, args->bitmap); args->bitmap->unref(); args->bitmap = nullptr; return nullptr; diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h index c914098b0ea19..d8677e13f60f1 100644 --- a/libs/hwui/renderthread/RenderThread.h +++ b/libs/hwui/renderthread/RenderThread.h @@ -89,8 +89,8 @@ public: void pushBackFrameCallback(IFrameCallback* callback); TimeLord& timeLord() { return mTimeLord; } - RenderState& renderState() { return *mRenderState; } - EglManager& eglManager() { return *mEglManager; } + RenderState& renderState() const { return *mRenderState; } + EglManager& eglManager() const { return *mEglManager; } JankTracker& jankTracker() { return *mJankTracker; } const DisplayInfo& mainDisplayInfo() { return mDisplayInfo; } diff --git a/libs/hwui/tests/unit/CanvasContextTests.cpp b/libs/hwui/tests/unit/CanvasContextTests.cpp new file mode 100644 index 0000000000000..3cc7189e5b4b5 --- /dev/null +++ b/libs/hwui/tests/unit/CanvasContextTests.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "AnimationContext.h" +#include "IContextFactory.h" +#include "renderthread/CanvasContext.h" +#include "tests/common/TestUtils.h" + +using namespace android; +using namespace android::uirenderer; +using namespace android::uirenderer::renderthread; + +class ContextFactory : public IContextFactory { +public: + virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) override { + return new AnimationContext(clock); + } +}; + +RENDERTHREAD_TEST(CanvasContext, create) { + auto rootNode = TestUtils::createNode(0, 0, 200, 400, nullptr); + ContextFactory contextFactory; + std::unique_ptr canvasContext(CanvasContext::create( + renderThread, false, rootNode.get(), &contextFactory)); + + ASSERT_FALSE(canvasContext->hasSurface()); + + canvasContext->destroy(nullptr); +} + +class TestFunctor : public Functor { +public: + bool didProcess = false; + + virtual status_t operator ()(int what, void* data) { + if (what == DrawGlInfo::kModeProcess) { didProcess = true; } + return DrawGlInfo::kStatusDone; + } +}; + +RENDERTHREAD_TEST(CanvasContext, invokeFunctor) { + TestFunctor functor; + ASSERT_FALSE(functor.didProcess); + CanvasContext::invokeFunctor(renderThread, &functor); + ASSERT_TRUE(functor.didProcess); +}