summaryrefslogtreecommitdiff
path: root/libs/hwui
diff options
context:
space:
mode:
Diffstat (limited to 'libs/hwui')
-rw-r--r--libs/hwui/Android.mk2
-rw-r--r--libs/hwui/FrameInfo.cpp28
-rw-r--r--libs/hwui/FrameInfo.h116
-rw-r--r--libs/hwui/JankTracker.cpp159
-rw-r--r--libs/hwui/JankTracker.h71
-rw-r--r--libs/hwui/renderthread/CanvasContext.cpp46
-rw-r--r--libs/hwui/renderthread/CanvasContext.h26
-rw-r--r--libs/hwui/renderthread/DrawFrameTask.cpp16
-rw-r--r--libs/hwui/renderthread/DrawFrameTask.h9
-rw-r--r--libs/hwui/renderthread/RenderProxy.cpp52
-rw-r--r--libs/hwui/renderthread/RenderProxy.h8
-rw-r--r--libs/hwui/renderthread/RenderThread.cpp9
-rw-r--r--libs/hwui/renderthread/RenderThread.h12
-rw-r--r--libs/hwui/renderthread/TimeLord.cpp8
-rw-r--r--libs/hwui/renderthread/TimeLord.h4
-rw-r--r--libs/hwui/tests/main.cpp5
-rw-r--r--libs/hwui/utils/Macros.h8
-rw-r--r--libs/hwui/utils/RingBuffer.h71
18 files changed, 58 insertions, 592 deletions
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 507472aa61a8..49560ffdd628 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -18,7 +18,6 @@ ifeq ($(USE_OPENGL_RENDERER),true)
AssetAtlas.cpp \
DamageAccumulator.cpp \
FontRenderer.cpp \
- FrameInfo.cpp \
GammaFontRenderer.cpp \
Caches.cpp \
DisplayList.cpp \
@@ -33,7 +32,6 @@ ifeq ($(USE_OPENGL_RENDERER),true)
GradientCache.cpp \
Image.cpp \
Interpolator.cpp \
- JankTracker.cpp \
Layer.cpp \
LayerCache.cpp \
LayerRenderer.cpp \
diff --git a/libs/hwui/FrameInfo.cpp b/libs/hwui/FrameInfo.cpp
deleted file mode 100644
index 6da1fa808d0a..000000000000
--- a/libs/hwui/FrameInfo.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2015 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 "FrameInfo.h"
-
-#include <cstring>
-
-namespace android {
-namespace uirenderer {
-
-void FrameInfo::importUiThreadInfo(int64_t* info) {
- memcpy(mFrameInfo, info, UI_THREAD_FRAME_INFO_SIZE * sizeof(int64_t));
-}
-
-} /* namespace uirenderer */
-} /* namespace android */
diff --git a/libs/hwui/FrameInfo.h b/libs/hwui/FrameInfo.h
deleted file mode 100644
index 3c3167721d2b..000000000000
--- a/libs/hwui/FrameInfo.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-#ifndef FRAMEINFO_H_
-#define FRAMEINFO_H_
-
-#include "utils/Macros.h"
-
-#include <cutils/compiler.h>
-#include <utils/Timers.h>
-
-#include <memory.h>
-
-namespace android {
-namespace uirenderer {
-
-#define UI_THREAD_FRAME_INFO_SIZE 9
-
-HWUI_ENUM(FrameInfoIndex,
- kFlags = 0,
- kIntendedVsync,
- kVsync,
- kOldestInputEvent,
- kNewestInputEvent,
- kHandleInputStart,
- kAnimationStart,
- kPerformTraversalsStart,
- kDrawStart,
- // End of UI frame info
-
- kSyncStart,
- kIssueDrawCommandsStart,
- kSwapBuffers,
- kFrameCompleted,
-
- // Must be the last value!
- kNumIndexes
-);
-
-HWUI_ENUM(FrameInfoFlags,
- kWindowLayoutChanged = 1 << 0,
- kRTAnimation = 1 << 1,
- kSurfaceCanvas = 1 << 2,
-);
-
-class ANDROID_API UiFrameInfoBuilder {
-public:
- UiFrameInfoBuilder(int64_t* buffer) : mBuffer(buffer) {
- memset(mBuffer, 0, UI_THREAD_FRAME_INFO_SIZE * sizeof(int64_t));
- }
-
- UiFrameInfoBuilder& setVsync(nsecs_t vsyncTime, nsecs_t intendedVsync) {
- mBuffer[FrameInfoIndex::kVsync] = vsyncTime;
- mBuffer[FrameInfoIndex::kIntendedVsync] = intendedVsync;
- return *this;
- }
-
- UiFrameInfoBuilder& addFlag(FrameInfoFlagsEnum flag) {
- mBuffer[FrameInfoIndex::kFlags] |= static_cast<uint64_t>(flag);
- return *this;
- }
-
-private:
- int64_t* mBuffer;
-};
-
-class FrameInfo {
-public:
- void importUiThreadInfo(int64_t* info);
-
- void markSyncStart() {
- mFrameInfo[FrameInfoIndex::kSyncStart] = systemTime(CLOCK_MONOTONIC);
- }
-
- void markIssueDrawCommandsStart() {
- mFrameInfo[FrameInfoIndex::kIssueDrawCommandsStart] = systemTime(CLOCK_MONOTONIC);
- }
-
- void markSwapBuffers() {
- mFrameInfo[FrameInfoIndex::kSwapBuffers] = systemTime(CLOCK_MONOTONIC);
- }
-
- void markFrameCompleted() {
- mFrameInfo[FrameInfoIndex::kFrameCompleted] = systemTime(CLOCK_MONOTONIC);
- }
-
- int64_t operator[](FrameInfoIndexEnum index) const {
- if (index == FrameInfoIndex::kNumIndexes) return 0;
- return mFrameInfo[static_cast<int>(index)];
- }
-
- int64_t operator[](int index) const {
- if (index < 0 || index >= FrameInfoIndex::kNumIndexes) return 0;
- return mFrameInfo[static_cast<int>(index)];
- }
-
-private:
- int64_t mFrameInfo[FrameInfoIndex::kNumIndexes];
-};
-
-} /* namespace uirenderer */
-} /* namespace android */
-
-#endif /* FRAMEINFO_H_ */
diff --git a/libs/hwui/JankTracker.cpp b/libs/hwui/JankTracker.cpp
deleted file mode 100644
index f7c81953b67b..000000000000
--- a/libs/hwui/JankTracker.cpp
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (C) 2015 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 "JankTracker.h"
-
-#include <algorithm>
-#include <cstdio>
-#include <inttypes.h>
-
-namespace android {
-namespace uirenderer {
-
-static const char* JANK_TYPE_NAMES[] = {
- "Missed Vsync",
- "High input latency",
- "Slow UI thread",
- "Slow bitmap uploads",
- "Slow draw",
-};
-
-struct Comparison {
- FrameInfoIndexEnum start;
- FrameInfoIndexEnum end;
-};
-
-static const Comparison COMPARISONS[] = {
- {FrameInfoIndex::kIntendedVsync, FrameInfoIndex::kVsync},
- {FrameInfoIndex::kOldestInputEvent, FrameInfoIndex::kVsync},
- {FrameInfoIndex::kVsync, FrameInfoIndex::kSyncStart},
- {FrameInfoIndex::kSyncStart, FrameInfoIndex::kIssueDrawCommandsStart},
- {FrameInfoIndex::kIssueDrawCommandsStart, FrameInfoIndex::kFrameCompleted},
-};
-
-// If the event exceeds 10 seconds throw it away, this isn't a jank event
-// it's an ANR and will be handled as such
-static const int64_t IGNORE_EXCEEDING = seconds_to_nanoseconds(10);
-
-/*
- * Frames that are exempt from jank metrics.
- * First-draw frames, for example, are expected to
- * be slow, this is hidden from the user with window animations and
- * other tricks
- *
- * Similarly, we don't track direct-drawing via Surface:lockHardwareCanvas()
- * for now
- *
- * TODO: kSurfaceCanvas can negatively impact other drawing by using up
- * time on the RenderThread, figure out how to attribute that as a jank-causer
- */
-static const int64_t EXEMPT_FRAMES_FLAGS
- = FrameInfoFlags::kWindowLayoutChanged
- | FrameInfoFlags::kSurfaceCanvas;
-
-JankTracker::JankTracker(nsecs_t frameIntervalNanos) {
- reset();
- setFrameInterval(frameIntervalNanos);
-}
-
-void JankTracker::setFrameInterval(nsecs_t frameInterval) {
- mFrameInterval = frameInterval;
- mThresholds[kMissedVsync] = 1;
- /*
- * Due to interpolation and sample rate differences between the touch
- * panel and the display (example, 85hz touch panel driving a 60hz display)
- * we call high latency 1.5 * frameinterval
- *
- * NOTE: Be careful when tuning this! A theoretical 1,000hz touch panel
- * on a 60hz display will show kOldestInputEvent - kIntendedVsync of being 15ms
- * Thus this must always be larger than frameInterval, or it will fail
- */
- mThresholds[kHighInputLatency] = static_cast<int64_t>(1.5 * frameInterval);
-
- // Note that these do not add up to 1. This is intentional. It's to deal
- // with variance in values, and should be sort of an upper-bound on what
- // is reasonable to expect.
- mThresholds[kSlowUI] = static_cast<int64_t>(.5 * frameInterval);
- mThresholds[kSlowSync] = static_cast<int64_t>(.2 * frameInterval);
- mThresholds[kSlowRT] = static_cast<int64_t>(.75 * frameInterval);
-
-}
-
-void JankTracker::addFrame(const FrameInfo& frame) {
- using namespace FrameInfoIndex;
- mTotalFrameCount++;
- // Fast-path for jank-free frames
- int64_t totalDuration = frame[kFrameCompleted] - frame[kIntendedVsync];
- uint32_t framebucket = std::min(
- static_cast<typeof sizeof(mFrameCounts)>(ns2ms(totalDuration)),
- sizeof(mFrameCounts) / sizeof(mFrameCounts[0]));
- // Keep the fast path as fast as possible.
- if (CC_LIKELY(totalDuration < mFrameInterval)) {
- mFrameCounts[framebucket]++;
- return;
- }
-
- if (frame[kFlags] & EXEMPT_FRAMES_FLAGS) {
- return;
- }
-
- mFrameCounts[framebucket]++;
- mJankFrameCount++;
-
- for (int i = 0; i < NUM_BUCKETS; i++) {
- int64_t delta = frame[COMPARISONS[i].end] - frame[COMPARISONS[i].start];
- if (delta >= mThresholds[i] && delta < IGNORE_EXCEEDING) {
- mBuckets[i].count++;
- }
- }
-}
-
-void JankTracker::dump(int fd) {
- FILE* file = fdopen(fd, "a");
- fprintf(file, "\nFrame stats:");
- fprintf(file, "\n Total frames rendered: %u", mTotalFrameCount);
- fprintf(file, "\n Janky frames: %u (%.2f%%)", mJankFrameCount,
- (float) mJankFrameCount / (float) mTotalFrameCount * 100.0f);
- fprintf(file, "\n 90th percentile: %ums", findPercentile(90));
- fprintf(file, "\n 95th percentile: %ums", findPercentile(95));
- fprintf(file, "\n 99th percentile: %ums", findPercentile(99));
- for (int i = 0; i < NUM_BUCKETS; i++) {
- fprintf(file, "\n Number %s: %u", JANK_TYPE_NAMES[i], mBuckets[i].count);
- }
- fprintf(file, "\n");
- fflush(file);
-}
-
-void JankTracker::reset() {
- memset(mBuckets, 0, sizeof(mBuckets));
- memset(mFrameCounts, 0, sizeof(mFrameCounts));
- mTotalFrameCount = 0;
- mJankFrameCount = 0;
-}
-
-uint32_t JankTracker::findPercentile(int percentile) {
- int pos = percentile * mTotalFrameCount / 100;
- int remaining = mTotalFrameCount - pos;
- for (int i = sizeof(mFrameCounts) / sizeof(mFrameCounts[0]) - 1; i >= 0; i--) {
- remaining -= mFrameCounts[i];
- if (remaining <= 0) {
- return i;
- }
- }
- return 0;
-}
-
-} /* namespace uirenderer */
-} /* namespace android */
diff --git a/libs/hwui/JankTracker.h b/libs/hwui/JankTracker.h
deleted file mode 100644
index 3d4929b215c6..000000000000
--- a/libs/hwui/JankTracker.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-#ifndef JANKTRACKER_H_
-#define JANKTRACKER_H_
-
-#include "FrameInfo.h"
-#include "renderthread/TimeLord.h"
-#include "utils/RingBuffer.h"
-
-#include <memory>
-
-namespace android {
-namespace uirenderer {
-
-enum JankType {
- kMissedVsync = 0,
- kHighInputLatency,
- kSlowUI,
- kSlowSync,
- kSlowRT,
-
- // must be last
- NUM_BUCKETS,
-};
-
-struct JankBucket {
- // Number of frames that hit this bucket
- uint32_t count;
-};
-
-// TODO: Replace DrawProfiler with this
-class JankTracker {
-public:
- JankTracker(nsecs_t frameIntervalNanos);
-
- void setFrameInterval(nsecs_t frameIntervalNanos);
-
- void addFrame(const FrameInfo& frame);
-
- void dump(int fd);
- void reset();
-
-private:
- uint32_t findPercentile(int p);
-
- JankBucket mBuckets[NUM_BUCKETS];
- int64_t mThresholds[NUM_BUCKETS];
- uint32_t mFrameCounts[128];
-
- int64_t mFrameInterval;
- uint32_t mTotalFrameCount;
- uint32_t mJankFrameCount;
-};
-
-} /* namespace uirenderer */
-} /* namespace android */
-
-#endif /* JANKTRACKER_H_ */
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 2eaa7719227c..75bd0676d70a 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -47,8 +47,7 @@ CanvasContext::CanvasContext(RenderThread& thread, bool translucent,
, mOpaque(!translucent)
, mCanvas(NULL)
, mHaveNewSurface(false)
- , mRootRenderNode(rootRenderNode)
- , mCurrentFrameInfo(NULL) {
+ , mRootRenderNode(rootRenderNode) {
mAnimationContext = contextFactory->createAnimationContext(mRenderThread.timeLord());
mRenderThread.renderState().registerCanvasContext(this);
}
@@ -153,13 +152,9 @@ void CanvasContext::processLayerUpdate(DeferredLayerUpdater* layerUpdater) {
}
}
-void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo) {
+void CanvasContext::prepareTree(TreeInfo& info) {
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) {
@@ -209,7 +204,6 @@ void CanvasContext::draw() {
"drawRenderNode called on a context with no canvas or surface!");
profiler().markPlaybackStart();
- mCurrentFrameInfo->markIssueDrawCommandsStart();
SkRect dirty;
mDamageAccumulator.finish(&dirty);
@@ -247,19 +241,12 @@ void CanvasContext::draw() {
profiler().markPlaybackEnd();
- // Even if we decided to cancel the frame, from the perspective of jank
- // metrics the frame was swapped at this point
- mCurrentFrameInfo->markSwapBuffers();
-
if (status & DrawGlInfo::kStatusDrew) {
swapBuffers();
} else {
mEglManager.cancelFrame();
}
- // TODO: Use a fence for real completion?
- mCurrentFrameInfo->markFrameCompleted();
- mRenderThread.jankTracker().addFrame(*mCurrentFrameInfo);
profiler().finishFrame();
}
@@ -272,14 +259,9 @@ 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, frameInfo);
+ prepareTree(info);
if (info.out.canDrawThisFrame) {
draw();
}
@@ -392,28 +374,6 @@ 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 < 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 */
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 0e8be9d9ed59..0cc2c7c2811a 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -17,14 +17,7 @@
#ifndef CANVASCONTEXT_H_
#define CANVASCONTEXT_H_
-#include "DamageAccumulator.h"
-#include "DrawProfiler.h"
-#include "IContextFactory.h"
-#include "FrameInfo.h"
-#include "RenderNode.h"
-#include "utils/RingBuffer.h"
-#include "renderthread/RenderTask.h"
-#include "renderthread/RenderThread.h"
+#include <set>
#include <cutils/compiler.h>
#include <EGL/egl.h>
@@ -32,7 +25,14 @@
#include <utils/Functor.h>
#include <utils/Vector.h>
-#include <set>
+#include "../DamageAccumulator.h"
+#include "../DrawProfiler.h"
+#include "../IContextFactory.h"
+#include "../RenderNode.h"
+#include "RenderTask.h"
+#include "RenderThread.h"
+
+#define FUNCTOR_PROCESS_DELAY 4
namespace android {
namespace uirenderer {
@@ -75,7 +75,7 @@ public:
void setOpaque(bool opaque);
void makeCurrent();
void processLayerUpdate(DeferredLayerUpdater* layerUpdater);
- void prepareTree(TreeInfo& info, int64_t* uiFrameInfo);
+ void prepareTree(TreeInfo& info);
void draw();
void destroy();
@@ -103,9 +103,6 @@ public:
DrawProfiler& profiler() { return mProfiler; }
- void dumpFrames(int fd);
- void resetFrameStats();
-
private:
friend class RegisterFrameCallbackTask;
// TODO: Replace with something better for layer & other GL object
@@ -136,9 +133,6 @@ private:
const sp<RenderNode> mRootRenderNode;
DrawProfiler mProfiler;
- FrameInfo* mCurrentFrameInfo;
- // Ring buffer large enough for 1 second worth of frames
- RingBuffer<FrameInfo, 60> mFrames;
std::set<RenderNode*> mPrefetechedLayers;
};
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 23a020233f27..97b31a95f278 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -34,6 +34,8 @@ namespace renderthread {
DrawFrameTask::DrawFrameTask()
: mRenderThread(NULL)
, mContext(NULL)
+ , mFrameTimeNanos(0)
+ , mRecordDurationNanos(0)
, mDensity(1.0f) // safe enough default
, mSyncResult(kSync_OK) {
}
@@ -66,12 +68,18 @@ void DrawFrameTask::removeLayerUpdate(DeferredLayerUpdater* layer) {
}
}
-int DrawFrameTask::drawFrame() {
+int DrawFrameTask::drawFrame(nsecs_t frameTimeNanos, nsecs_t recordDurationNanos) {
LOG_ALWAYS_FATAL_IF(!mContext, "Cannot drawFrame with no CanvasContext!");
mSyncResult = kSync_OK;
+ mFrameTimeNanos = frameTimeNanos;
+ mRecordDurationNanos = recordDurationNanos;
postAndWait();
+ // Reset the single-frame data
+ mFrameTimeNanos = 0;
+ mRecordDurationNanos = 0;
+
return mSyncResult;
}
@@ -85,7 +93,7 @@ void DrawFrameTask::run() {
ATRACE_NAME("DrawFrame");
mContext->profiler().setDensity(mDensity);
- mContext->profiler().startFrame();
+ mContext->profiler().startFrame(mRecordDurationNanos);
bool canUnblockUiThread;
bool canDrawThisFrame;
@@ -114,7 +122,7 @@ void DrawFrameTask::run() {
bool DrawFrameTask::syncFrameState(TreeInfo& info) {
ATRACE_CALL();
- mRenderThread->timeLord().vsyncReceived(mFrameInfo[FrameInfoIndex::kVsync]);
+ mRenderThread->timeLord().vsyncReceived(mFrameTimeNanos);
mContext->makeCurrent();
Caches::getInstance().textureCache.resetMarkInUse();
@@ -122,7 +130,7 @@ bool DrawFrameTask::syncFrameState(TreeInfo& info) {
mContext->processLayerUpdate(mLayers[i].get());
}
mLayers.clear();
- mContext->prepareTree(info, mFrameInfo);
+ mContext->prepareTree(info);
// This is after the prepareTree so that any pending operations
// (RenderNode tree state, prefetched layers, etc...) will be flushed.
diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h
index eccb87f29383..28f6cb26fb57 100644
--- a/libs/hwui/renderthread/DrawFrameTask.h
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -25,7 +25,6 @@
#include "RenderTask.h"
#include "../Rect.h"
-#include "../FrameInfo.h"
#include "../TreeInfo.h"
namespace android {
@@ -63,9 +62,7 @@ public:
void removeLayerUpdate(DeferredLayerUpdater* layer);
void setDensity(float density) { mDensity = density; }
- int drawFrame();
-
- int64_t* frameInfo() { return mFrameInfo; }
+ int drawFrame(nsecs_t frameTimeNanos, nsecs_t recordDurationNanos);
virtual void run();
@@ -83,12 +80,12 @@ private:
/*********************************************
* Single frame data
*********************************************/
+ nsecs_t mFrameTimeNanos;
+ nsecs_t mRecordDurationNanos;
float mDensity;
std::vector< sp<DeferredLayerUpdater> > mLayers;
int mSyncResult;
-
- int64_t mFrameInfo[UI_THREAD_FRAME_INFO_SIZE];
};
} /* namespace renderthread */
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 088c65b939ef..6d063a4b0ce0 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -16,14 +16,14 @@
#include "RenderProxy.h"
-#include "DeferredLayerUpdater.h"
-#include "DisplayList.h"
-#include "LayerRenderer.h"
-#include "Rect.h"
-#include "renderthread/CanvasContext.h"
-#include "renderthread/RenderTask.h"
-#include "renderthread/RenderThread.h"
-#include "utils/Macros.h"
+#include "CanvasContext.h"
+#include "RenderTask.h"
+#include "RenderThread.h"
+
+#include "../DeferredLayerUpdater.h"
+#include "../DisplayList.h"
+#include "../LayerRenderer.h"
+#include "../Rect.h"
namespace android {
namespace uirenderer {
@@ -52,11 +52,6 @@ namespace renderthread {
MethodInvokeRenderTask* task = new MethodInvokeRenderTask((RunnableMethod) Bridge_ ## method); \
ARGS(method) *args = (ARGS(method) *) task->payload()
-HWUI_ENUM(DumpFlags,
- kFrameStats = 1 << 0,
- kReset = 1 << 1,
-);
-
CREATE_BRIDGE4(createContext, RenderThread* thread, bool translucent,
RenderNode* rootRenderNode, IContextFactory* contextFactory) {
return new CanvasContext(*args->thread, args->translucent,
@@ -97,7 +92,7 @@ void RenderProxy::destroyContext() {
}
CREATE_BRIDGE2(setFrameInterval, RenderThread* thread, nsecs_t frameIntervalNanos) {
- args->thread->setFrameInterval(args->frameIntervalNanos);
+ args->thread->timeLord().setFrameInterval(args->frameIntervalNanos);
return NULL;
}
@@ -180,8 +175,7 @@ CREATE_BRIDGE7(setup, CanvasContext* context, int width, int height,
}
void RenderProxy::setup(int width, int height, const Vector3& lightCenter, float lightRadius,
- uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha, float density) {
- mDrawFrameTask.setDensity(density);
+ uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
SETUP_TASK(setup);
args->context = mContext;
args->width = width;
@@ -205,12 +199,10 @@ void RenderProxy::setOpaque(bool opaque) {
post(task);
}
-int64_t* RenderProxy::frameInfo() {
- return mDrawFrameTask.frameInfo();
-}
-
-int RenderProxy::syncAndDrawFrame() {
- return mDrawFrameTask.drawFrame();
+int RenderProxy::syncAndDrawFrame(nsecs_t frameTimeNanos, nsecs_t recordDurationNanos,
+ float density) {
+ mDrawFrameTask.setDensity(density);
+ return mDrawFrameTask.drawFrame(frameTimeNanos, recordDurationNanos);
}
CREATE_BRIDGE1(destroy, CanvasContext* context) {
@@ -379,28 +371,19 @@ void RenderProxy::notifyFramePending() {
mRenderThread.queueAtFront(task);
}
-CREATE_BRIDGE3(dumpProfileInfo, CanvasContext* context, int fd, int dumpFlags) {
+CREATE_BRIDGE2(dumpProfileInfo, CanvasContext* context, int fd) {
args->context->profiler().dumpData(args->fd);
-
- if (args->dumpFlags & DumpFlags::kFrameStats) {
- args->context->dumpFrames(args->fd);
- }
- if (args->dumpFlags & DumpFlags::kReset) {
- args->context->resetFrameStats();
- }
return NULL;
}
-void RenderProxy::dumpProfileInfo(int fd, int dumpFlags) {
+void RenderProxy::dumpProfileInfo(int fd) {
SETUP_TASK(dumpProfileInfo);
args->context = mContext;
args->fd = fd;
- args->dumpFlags = dumpFlags;
postAndWait(task);
}
-CREATE_BRIDGE2(outputLogBuffer, int fd, RenderThread* thread) {
- args->thread->jankTracker().dump(args->fd);
+CREATE_BRIDGE1(outputLogBuffer, int fd) {
RenderNode::outputLogBuffer(args->fd);
return NULL;
}
@@ -408,7 +391,6 @@ CREATE_BRIDGE2(outputLogBuffer, int fd, RenderThread* thread) {
void RenderProxy::outputLogBuffer(int fd) {
SETUP_TASK(outputLogBuffer);
args->fd = fd;
- args->thread = &RenderThread::getInstance();
staticPostAndWait(task);
}
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index d86f1fca466f..fd1fe05ffbdb 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -71,10 +71,10 @@ public:
ANDROID_API void updateSurface(const sp<ANativeWindow>& window);
ANDROID_API bool pauseSurface(const sp<ANativeWindow>& window);
ANDROID_API void setup(int width, int height, const Vector3& lightCenter, float lightRadius,
- uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha, float density);
+ uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
ANDROID_API void setOpaque(bool opaque);
- ANDROID_API int64_t* frameInfo();
- ANDROID_API int syncAndDrawFrame();
+ ANDROID_API int syncAndDrawFrame(nsecs_t frameTimeNanos, nsecs_t recordDurationNanos,
+ float density);
ANDROID_API void destroy();
ANDROID_API static void invokeFunctor(Functor* functor, bool waitForCompletion);
@@ -95,7 +95,7 @@ public:
ANDROID_API void stopDrawing();
ANDROID_API void notifyFramePending();
- ANDROID_API void dumpProfileInfo(int fd, int dumpFlags);
+ ANDROID_API void dumpProfileInfo(int fd);
ANDROID_API static void outputLogBuffer(int fd);
ANDROID_API void setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t size);
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index 7a8c3cee088d..84826b7a3bff 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -143,8 +143,7 @@ RenderThread::RenderThread() : Thread(true), Singleton<RenderThread>()
, mFrameCallbackTaskPending(false)
, mFrameCallbackTask(0)
, mRenderState(NULL)
- , mEglManager(NULL)
- , mJankTracker(NULL) {
+ , mEglManager(NULL) {
mFrameCallbackTask = new DispatchFrameCallbacks(this);
mLooper = new Looper(false);
run("RenderThread");
@@ -154,11 +153,6 @@ RenderThread::~RenderThread() {
LOG_ALWAYS_FATAL("Can't destroy the render thread");
}
-void RenderThread::setFrameInterval(nsecs_t frameInterval) {
- mTimeLord.setFrameInterval(frameInterval);
- mJankTracker->setFrameInterval(frameInterval);
-}
-
void RenderThread::initializeDisplayEventReceiver() {
LOG_ALWAYS_FATAL_IF(mDisplayEventReceiver, "Initializing a second DisplayEventReceiver?");
mDisplayEventReceiver = new DisplayEventReceiver();
@@ -175,7 +169,6 @@ void RenderThread::initThreadLocals() {
initializeDisplayEventReceiver();
mEglManager = new EglManager(*this);
mRenderState = new RenderState(*this);
- mJankTracker = new JankTracker(mTimeLord.frameIntervalNanos());
}
int RenderThread::displayEventReceiverCallback(int fd, int events, void* data) {
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index 8a28a35aabc2..99c2e1527ea2 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -19,8 +19,8 @@
#include "RenderTask.h"
-#include "../JankTracker.h"
-#include "TimeLord.h"
+#include <memory>
+#include <set>
#include <cutils/compiler.h>
#include <utils/Looper.h>
@@ -28,8 +28,7 @@
#include <utils/Singleton.h>
#include <utils/Thread.h>
-#include <memory>
-#include <set>
+#include "TimeLord.h"
namespace android {
@@ -86,12 +85,9 @@ public:
// the next vsync. If it is not currently registered this does nothing.
void pushBackFrameCallback(IFrameCallback* callback);
- void setFrameInterval(nsecs_t frameInterval);
-
TimeLord& timeLord() { return mTimeLord; }
RenderState& renderState() { return *mRenderState; }
EglManager& eglManager() { return *mEglManager; }
- JankTracker& jankTracker() { return *mJankTracker; }
protected:
virtual bool threadLoop();
@@ -136,8 +132,6 @@ private:
TimeLord mTimeLord;
RenderState* mRenderState;
EglManager* mEglManager;
-
- JankTracker* mJankTracker;
};
} /* namespace renderthread */
diff --git a/libs/hwui/renderthread/TimeLord.cpp b/libs/hwui/renderthread/TimeLord.cpp
index f846d6a44473..f18749317ab6 100644
--- a/libs/hwui/renderthread/TimeLord.cpp
+++ b/libs/hwui/renderthread/TimeLord.cpp
@@ -32,7 +32,7 @@ bool TimeLord::vsyncReceived(nsecs_t vsync) {
return false;
}
-nsecs_t TimeLord::computeFrameTimeNanos() {
+nsecs_t TimeLord::computeFrameTimeMs() {
// Logic copied from Choreographer.java
nsecs_t now = systemTime(CLOCK_MONOTONIC);
nsecs_t jitterNanos = now - mFrameTimeNanos;
@@ -40,11 +40,7 @@ nsecs_t TimeLord::computeFrameTimeNanos() {
nsecs_t lastFrameOffset = jitterNanos % mFrameIntervalNanos;
mFrameTimeNanos = now - lastFrameOffset;
}
- return mFrameTimeNanos;
-}
-
-nsecs_t TimeLord::computeFrameTimeMs() {
- return nanoseconds_to_milliseconds(computeFrameTimeNanos());
+ return nanoseconds_to_milliseconds(mFrameTimeNanos);
}
} /* namespace renderthread */
diff --git a/libs/hwui/renderthread/TimeLord.h b/libs/hwui/renderthread/TimeLord.h
index 5464399234fb..7c155d28feef 100644
--- a/libs/hwui/renderthread/TimeLord.h
+++ b/libs/hwui/renderthread/TimeLord.h
@@ -29,13 +29,9 @@ class RenderThread;
class TimeLord {
public:
void setFrameInterval(nsecs_t intervalNanos) { mFrameIntervalNanos = intervalNanos; }
- nsecs_t frameIntervalNanos() const { return mFrameIntervalNanos; }
-
// returns true if the vsync is newer, false if it was rejected for staleness
bool vsyncReceived(nsecs_t vsync);
- nsecs_t latestVsync() { return mFrameTimeNanos; }
nsecs_t computeFrameTimeMs();
- nsecs_t computeFrameTimeNanos();
private:
friend class RenderThread;
diff --git a/libs/hwui/tests/main.cpp b/libs/hwui/tests/main.cpp
index 33b8103cdb84..2d99e9f7686c 100644
--- a/libs/hwui/tests/main.cpp
+++ b/libs/hwui/tests/main.cpp
@@ -88,7 +88,7 @@ int main(int argc, char* argv[]) {
proxy->initialize(surface);
float lightX = width / 2.0;
proxy->setup(width, height, (Vector3){lightX, dp(-200.0f), dp(800.0f)},
- dp(800.0f), 255 * 0.075, 255 * 0.15, gDisplay.density);
+ dp(800.0f), 255 * 0.075, 255 * 0.15);
android::uirenderer::Rect DUMMY;
@@ -116,7 +116,8 @@ int main(int argc, char* argv[]) {
cards[ci]->mutateStagingProperties().setTranslationY(i);
cards[ci]->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
}
- proxy->syncAndDrawFrame();
+ nsecs_t frameTimeNs = systemTime(CLOCK_MONOTONIC);
+ proxy->syncAndDrawFrame(frameTimeNs, 0, gDisplay.density);
usleep(12000);
}
diff --git a/libs/hwui/utils/Macros.h b/libs/hwui/utils/Macros.h
index 068b32b3fe68..5b7c87ceef8f 100644
--- a/libs/hwui/utils/Macros.h
+++ b/libs/hwui/utils/Macros.h
@@ -29,12 +29,4 @@
friend inline int compare_type(const Type& lhs, const Type& rhs) { return lhs.compare(rhs); } \
friend inline hash_t hash_type(const Type& entry) { return entry.hash(); }
-#define HWUI_ENUM(name, ...) \
- namespace name { \
- enum _##name { \
- __VA_ARGS__ \
- }; \
- } \
- typedef enum name::_##name name##Enum
-
#endif /* MACROS_H */
diff --git a/libs/hwui/utils/RingBuffer.h b/libs/hwui/utils/RingBuffer.h
deleted file mode 100644
index 62b22fdcef42..000000000000
--- a/libs/hwui/utils/RingBuffer.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-#ifndef RINGBUFFER_H_
-#define RINGBUFFER_H_
-
-#include "utils/Macros.h"
-
-#include <stddef.h>
-
-namespace android {
-namespace uirenderer {
-
-template<class T, size_t SIZE>
-class RingBuffer {
- PREVENT_COPY_AND_ASSIGN(RingBuffer);
-
-public:
- RingBuffer() : mHead(-1), mCount(0) {}
- ~RingBuffer() {}
-
- size_t capacity() { return SIZE; }
- size_t size() { return mCount; }
-
- T& next() {
- mHead = (mHead + 1) % SIZE;
- if (mCount < SIZE) {
- mCount++;
- }
- return mBuffer[mHead];
- }
-
- T& front() {
- return this[0];
- }
-
- T& back() {
- return this[size() - 1];
- }
-
- T& operator[](size_t index) {
- return mBuffer[(mHead + index + 1) % mCount];
- }
-
- void clear() {
- mCount = 0;
- mHead = -1;
- }
-
-private:
- T mBuffer[SIZE];
- int mHead;
- size_t mCount;
-};
-
-}; // namespace uirenderer
-}; // namespace android
-
-#endif /* RINGBUFFER_H_ */