diff options
Diffstat (limited to 'libs/hwui/renderthread/CanvasContext.cpp')
| -rw-r--r-- | libs/hwui/renderthread/CanvasContext.cpp | 93 |
1 files changed, 66 insertions, 27 deletions
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index b7e1752..9456073 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -16,19 +16,19 @@ #include "CanvasContext.h" -#include <algorithm> -#include <private/hwui/DrawGlInfo.h> -#include <strings.h> - #include "EglManager.h" #include "RenderThread.h" #include "../AnimationContext.h" #include "../Caches.h" #include "../DeferredLayerUpdater.h" -#include "../RenderState.h" +#include "../renderstate/RenderState.h" +#include "../renderstate/Stencil.h" #include "../LayerRenderer.h" #include "../OpenGLRenderer.h" -#include "../Stencil.h" + +#include <algorithm> +#include <private/hwui/DrawGlInfo.h> +#include <strings.h> #define TRIM_MEMORY_COMPLETE 80 #define TRIM_MEMORY_UI_HIDDEN 20 @@ -45,28 +45,29 @@ CanvasContext::CanvasContext(RenderThread& thread, bool translucent, , mBufferPreserved(false) , mSwapBehavior(kSwap_default) , mOpaque(!translucent) - , mCanvas(NULL) + , mCanvas(nullptr) , mHaveNewSurface(false) - , mRootRenderNode(rootRenderNode) { - mAnimationContext = contextFactory->createAnimationContext(mRenderThread.timeLord()); + , mAnimationContext(contextFactory->createAnimationContext(mRenderThread.timeLord())) + , mRootRenderNode(rootRenderNode) + , mCurrentFrameInfo(nullptr) { mRenderThread.renderState().registerCanvasContext(this); + mProfiler.setDensity(mRenderThread.mainDisplayInfo().density); } CanvasContext::~CanvasContext() { destroy(); - delete mAnimationContext; mRenderThread.renderState().unregisterCanvasContext(this); } void CanvasContext::destroy() { stopDrawing(); - setSurface(NULL); + setSurface(nullptr); freePrefetechedLayers(); destroyHardwareResources(); mAnimationContext->destroy(); if (mCanvas) { delete mCanvas; - mCanvas = 0; + mCanvas = nullptr; } } @@ -96,7 +97,7 @@ void CanvasContext::setSurface(ANativeWindow* window) { void CanvasContext::swapBuffers() { if (CC_UNLIKELY(!mEglManager.swapBuffers(mEglSurface))) { - setSurface(NULL); + setSurface(nullptr); } mHaveNewSurface = false; } @@ -128,8 +129,8 @@ bool CanvasContext::pauseSurface(ANativeWindow* window) { } // TODO: don't pass viewport size, it's automatic via EGL -void CanvasContext::setup(int width, int height, const Vector3& lightCenter, - float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) { +void CanvasContext::setup(int width, int height, const Vector3& lightCenter, float lightRadius, + uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) { if (!mCanvas) return; mCanvas->initLight(lightCenter, lightRadius, ambientShadowAlpha, spotShadowAlpha); } @@ -152,9 +153,13 @@ void CanvasContext::processLayerUpdate(DeferredLayerUpdater* layerUpdater) { } } -void CanvasContext::prepareTree(TreeInfo& info) { +void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo) { mRenderThread.removeFrameCallback(this); + mCurrentFrameInfo = &mFrames.next(); + mCurrentFrameInfo->importUiThreadInfo(uiFrameInfo); + mCurrentFrameInfo->markSyncStart(); + info.damageAccumulator = &mDamageAccumulator; info.renderer = mCanvas; if (mPrefetechedLayers.size() && info.mode == TreeInfo::MODE_FULL) { @@ -204,6 +209,7 @@ void CanvasContext::draw() { "drawRenderNode called on a context with no canvas or surface!"); profiler().markPlaybackStart(); + mCurrentFrameInfo->markIssueDrawCommandsStart(); SkRect dirty; mDamageAccumulator.finish(&dirty); @@ -224,29 +230,35 @@ void CanvasContext::draw() { profiler().unionDirty(&dirty); } - status_t status; if (!dirty.isEmpty()) { - status = mCanvas->prepareDirty(dirty.fLeft, dirty.fTop, + mCanvas->prepareDirty(dirty.fLeft, dirty.fTop, dirty.fRight, dirty.fBottom, mOpaque); } else { - status = mCanvas->prepare(mOpaque); + mCanvas->prepare(mOpaque); } Rect outBounds; - status |= mCanvas->drawRenderNode(mRootRenderNode.get(), outBounds); + mCanvas->drawRenderNode(mRootRenderNode.get(), outBounds); profiler().draw(mCanvas); - mCanvas->finish(); + bool drew = mCanvas->finish(); profiler().markPlaybackEnd(); - if (status & DrawGlInfo::kStatusDrew) { + // Even if we decided to cancel the frame, from the perspective of jank + // metrics the frame was swapped at this point + mCurrentFrameInfo->markSwapBuffers(); + + if (drew) { swapBuffers(); } else { mEglManager.cancelFrame(); } + // TODO: Use a fence for real completion? + mCurrentFrameInfo->markFrameCompleted(); + mRenderThread.jankTracker().addFrame(*mCurrentFrameInfo); profiler().finishFrame(); } @@ -259,9 +271,14 @@ void CanvasContext::doFrame() { ATRACE_CALL(); profiler().startFrame(); + int64_t frameInfo[UI_THREAD_FRAME_INFO_SIZE]; + UiFrameInfoBuilder(frameInfo) + .addFlag(FrameInfoFlags::kRTAnimation) + .setVsync(mRenderThread.timeLord().computeFrameTimeNanos(), + mRenderThread.timeLord().latestVsync()); TreeInfo info(TreeInfo::MODE_RT_ONLY, mRenderThread.renderState()); - prepareTree(info); + prepareTree(info, frameInfo); if (info.out.canDrawThisFrame) { draw(); } @@ -275,19 +292,19 @@ void CanvasContext::invokeFunctor(RenderThread& thread, Functor* functor) { mode = DrawGlInfo::kModeProcess; } - thread.renderState().invokeFunctor(functor, mode, NULL); + thread.renderState().invokeFunctor(functor, mode, nullptr); } void CanvasContext::markLayerInUse(RenderNode* node) { if (mPrefetechedLayers.erase(node)) { - node->decStrong(0); + node->decStrong(nullptr); } } static void destroyPrefetechedNode(RenderNode* node) { ALOGW("Incorrectly called buildLayer on View: %s, destroying layer...", node->getName()); node->destroyHardwareResources(); - node->decStrong(0); + node->decStrong(nullptr); } void CanvasContext::freePrefetechedLayers() { @@ -321,7 +338,7 @@ void CanvasContext::buildLayer(RenderNode* node) { mCanvas->markLayersAsBuildLayers(); mCanvas->flushLayerUpdates(); - node->incStrong(0); + node->incStrong(nullptr); mPrefetechedLayers.insert(node); } @@ -374,6 +391,28 @@ void CanvasContext::setTextureAtlas(RenderThread& thread, thread.eglManager().setTextureAtlas(buffer, map, mapSize); } +void CanvasContext::dumpFrames(int fd) { + FILE* file = fdopen(fd, "a"); + fprintf(file, "\n\n---PROFILEDATA---"); + for (size_t i = 0; i < mFrames.size(); i++) { + FrameInfo& frame = mFrames[i]; + if (frame[FrameInfoIndex::kSyncStart] == 0) { + continue; + } + fprintf(file, "\n"); + for (int i = 0; i < static_cast<int>(FrameInfoIndex::kNumIndexes); i++) { + fprintf(file, "%" PRId64 ",", frame[i]); + } + } + fprintf(file, "\n---PROFILEDATA---\n\n"); + fflush(file); +} + +void CanvasContext::resetFrameStats() { + mFrames.clear(); + mRenderThread.jankTracker().reset(); +} + } /* namespace renderthread */ } /* namespace uirenderer */ } /* namespace android */ |
