summaryrefslogtreecommitdiffstats
path: root/libs/hwui/renderthread/CanvasContext.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/hwui/renderthread/CanvasContext.cpp')
-rw-r--r--libs/hwui/renderthread/CanvasContext.cpp93
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 */