summaryrefslogtreecommitdiffstats
path: root/libs
diff options
context:
space:
mode:
authorJohn Reck <jreck@google.com>2015-05-12 07:17:50 -0700
committerJohn Reck <jreck@google.com>2015-05-12 11:02:07 -0700
commit4c9e59d03c2bca38001225b79d01740b8999adfb (patch)
tree140ff328b9966bdd974a7868c631eebdc1fea76f /libs
parent4bd4121d584e16c700ba08828c675b7f906ff331 (diff)
downloadframeworks_base-4c9e59d03c2bca38001225b79d01740b8999adfb.zip
frameworks_base-4c9e59d03c2bca38001225b79d01740b8999adfb.tar.gz
frameworks_base-4c9e59d03c2bca38001225b79d01740b8999adfb.tar.bz2
Unify DrawProfiler/JankStats
Bug: 20822400 Change-Id: I24345c3120440bfce14e8cbe7e880b39f10b744a
Diffstat (limited to 'libs')
-rw-r--r--libs/hwui/Android.common.mk2
-rw-r--r--libs/hwui/FrameInfoVisualizer.cpp (renamed from libs/hwui/DrawProfiler.cpp)111
-rw-r--r--libs/hwui/FrameInfoVisualizer.h (renamed from libs/hwui/DrawProfiler.h)67
-rw-r--r--libs/hwui/Properties.h14
-rw-r--r--libs/hwui/renderthread/CanvasContext.cpp8
-rw-r--r--libs/hwui/renderthread/CanvasContext.h10
-rw-r--r--libs/hwui/renderthread/DrawFrameTask.cpp2
-rw-r--r--libs/hwui/utils/RingBuffer.h2
8 files changed, 90 insertions, 126 deletions
diff --git a/libs/hwui/Android.common.mk b/libs/hwui/Android.common.mk
index 8a4e609..3e76656 100644
--- a/libs/hwui/Android.common.mk
+++ b/libs/hwui/Android.common.mk
@@ -40,11 +40,11 @@ LOCAL_SRC_FILES := \
DisplayList.cpp \
DisplayListCanvas.cpp \
Dither.cpp \
- DrawProfiler.cpp \
Extensions.cpp \
FboCache.cpp \
FontRenderer.cpp \
FrameInfo.cpp \
+ FrameInfoVisualizer.cpp \
GammaFontRenderer.cpp \
GlopBuilder.cpp \
GradientCache.cpp \
diff --git a/libs/hwui/DrawProfiler.cpp b/libs/hwui/FrameInfoVisualizer.cpp
index 7addef9..0411742 100644
--- a/libs/hwui/DrawProfiler.cpp
+++ b/libs/hwui/FrameInfoVisualizer.cpp
@@ -13,19 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#include "DrawProfiler.h"
-
-#include <cutils/compiler.h>
+#include "FrameInfoVisualizer.h"
#include "OpenGLRenderer.h"
-#define DEFAULT_MAX_FRAMES 128
+#include <cutils/compiler.h>
#define RETURN_IF_PROFILING_DISABLED() if (CC_LIKELY(mType == ProfileType::None)) return
#define RETURN_IF_DISABLED() if (CC_LIKELY(mType == ProfileType::None && !mShowDirtyRegions)) return
-#define NANOS_TO_MILLIS_FLOAT(nanos) ((nanos) * 0.000001f)
-
#define PROFILE_DRAW_WIDTH 3
#define PROFILE_DRAW_THRESHOLD_STROKE_WIDTH 2
#define PROFILE_DRAW_DP_PER_MS 7
@@ -55,15 +51,16 @@ static int dpToPx(int dp, float density) {
return (int) (dp * density + 0.5f);
}
-DrawProfiler::DrawProfiler() {
+FrameInfoVisualizer::FrameInfoVisualizer(FrameInfoSource& source)
+ : mFrameSource(source) {
setDensity(1);
}
-DrawProfiler::~DrawProfiler() {
+FrameInfoVisualizer::~FrameInfoVisualizer() {
destroyData();
}
-void DrawProfiler::setDensity(float density) {
+void FrameInfoVisualizer::setDensity(float density) {
if (CC_UNLIKELY(mDensity != density)) {
mDensity = density;
mVerticalUnit = dpToPx(PROFILE_DRAW_DP_PER_MS, density);
@@ -72,35 +69,7 @@ void DrawProfiler::setDensity(float density) {
}
}
-void DrawProfiler::startFrame(nsecs_t recordDurationNanos) {
- RETURN_IF_PROFILING_DISABLED();
- mData[mCurrentFrame].record = NANOS_TO_MILLIS_FLOAT(recordDurationNanos);
- mPreviousTime = systemTime(CLOCK_MONOTONIC);
-}
-
-void DrawProfiler::markPlaybackStart() {
- RETURN_IF_PROFILING_DISABLED();
- nsecs_t now = systemTime(CLOCK_MONOTONIC);
- mData[mCurrentFrame].prepare = NANOS_TO_MILLIS_FLOAT(now - mPreviousTime);
- mPreviousTime = now;
-}
-
-void DrawProfiler::markPlaybackEnd() {
- RETURN_IF_PROFILING_DISABLED();
- nsecs_t now = systemTime(CLOCK_MONOTONIC);
- mData[mCurrentFrame].playback = NANOS_TO_MILLIS_FLOAT(now - mPreviousTime);
- mPreviousTime = now;
-}
-
-void DrawProfiler::finishFrame() {
- RETURN_IF_PROFILING_DISABLED();
- nsecs_t now = systemTime(CLOCK_MONOTONIC);
- mData[mCurrentFrame].swapBuffers = NANOS_TO_MILLIS_FLOAT(now - mPreviousTime);
- mPreviousTime = now;
- mCurrentFrame = (mCurrentFrame + 1) % mDataSize;
-}
-
-void DrawProfiler::unionDirty(SkRect* dirty) {
+void FrameInfoVisualizer::unionDirty(SkRect* dirty) {
RETURN_IF_DISABLED();
// Not worth worrying about minimizing the dirty region for debugging, so just
// dirty the entire viewport.
@@ -110,7 +79,7 @@ void DrawProfiler::unionDirty(SkRect* dirty) {
}
}
-void DrawProfiler::draw(OpenGLRenderer* canvas) {
+void FrameInfoVisualizer::draw(OpenGLRenderer* canvas) {
RETURN_IF_DISABLED();
if (mShowDirtyRegions) {
@@ -131,27 +100,21 @@ void DrawProfiler::draw(OpenGLRenderer* canvas) {
}
}
-void DrawProfiler::createData() {
- if (mData) return;
+void FrameInfoVisualizer::createData() {
+ if (mRects.get()) return;
- mDataSize = property_get_int32(PROPERTY_PROFILE_MAXFRAMES, DEFAULT_MAX_FRAMES);
- if (mDataSize <= 0) mDataSize = 1;
- if (mDataSize > 4096) mDataSize = 4096; // Reasonable maximum
- mData = (FrameTimingData*) calloc(mDataSize, sizeof(FrameTimingData));
- mRects = new float*[NUM_ELEMENTS];
+ mRects.reset(new float*[mFrameSource.capacity()]);
for (int i = 0; i < NUM_ELEMENTS; i++) {
// 4 floats per rect
- mRects[i] = (float*) calloc(mDataSize, 4 * sizeof(float));
+ mRects.get()[i] = (float*) calloc(mFrameSource.capacity(), 4 * sizeof(float));
}
- mCurrentFrame = 0;
}
-void DrawProfiler::destroyData() {
- delete mData;
- mData = nullptr;
+void FrameInfoVisualizer::destroyData() {
+ mRects.reset(nullptr);
}
-void DrawProfiler::addRect(Rect& r, float data, float* shapeOutput) {
+void FrameInfoVisualizer::addRect(Rect& r, float data, float* shapeOutput) {
r.top = r.bottom - (data * mVerticalUnit);
shapeOutput[0] = r.left;
shapeOutput[1] = r.top;
@@ -160,40 +123,40 @@ void DrawProfiler::addRect(Rect& r, float data, float* shapeOutput) {
r.bottom = r.top;
}
-void DrawProfiler::prepareShapes(const int baseline) {
+void FrameInfoVisualizer::prepareShapes(const int baseline) {
Rect r;
r.right = mHorizontalUnit;
- for (int i = 0; i < mDataSize; i++) {
+ for (size_t i = 0; i < mFrameSource.size(); i++) {
const int shapeIndex = i * 4;
r.bottom = baseline;
- addRect(r, mData[i].record, mRects[RECORD_INDEX] + shapeIndex);
- addRect(r, mData[i].prepare, mRects[PREPARE_INDEX] + shapeIndex);
- addRect(r, mData[i].playback, mRects[PLAYBACK_INDEX] + shapeIndex);
- addRect(r, mData[i].swapBuffers, mRects[SWAPBUFFERS_INDEX] + shapeIndex);
+ addRect(r, recordDuration(i), mRects.get()[RECORD_INDEX] + shapeIndex);
+ addRect(r, prepareDuration(i), mRects.get()[PREPARE_INDEX] + shapeIndex);
+ addRect(r, issueDrawDuration(i), mRects.get()[PLAYBACK_INDEX] + shapeIndex);
+ addRect(r, swapBuffersDuration(i), mRects.get()[SWAPBUFFERS_INDEX] + shapeIndex);
r.translate(mHorizontalUnit, 0);
}
}
-void DrawProfiler::drawGraph(OpenGLRenderer* canvas) {
+void FrameInfoVisualizer::drawGraph(OpenGLRenderer* canvas) {
SkPaint paint;
for (int i = 0; i < NUM_ELEMENTS; i++) {
paint.setColor(ELEMENT_COLORS[i]);
- canvas->drawRects(mRects[i], mDataSize * 4, &paint);
+ canvas->drawRects(mRects.get()[i], mFrameSource.capacity() * 4, &paint);
}
}
-void DrawProfiler::drawCurrentFrame(OpenGLRenderer* canvas) {
+void FrameInfoVisualizer::drawCurrentFrame(OpenGLRenderer* canvas) {
// This draws a solid rect over the entirety of the current frame's shape
// To do so we use the bottom of mRects[0] and the top of mRects[NUM_ELEMENTS-1]
// which will therefore fully overlap the previously drawn rects
SkPaint paint;
paint.setColor(CURRENT_FRAME_COLOR);
- const int i = mCurrentFrame * 4;
- canvas->drawRect(mRects[0][i], mRects[NUM_ELEMENTS-1][i+1], mRects[0][i+2],
- mRects[0][i+3], &paint);
+ const int i = (mFrameSource.size() - 1) * 4;
+ canvas->drawRect(mRects.get()[0][i], mRects.get()[NUM_ELEMENTS-1][i+1],
+ mRects.get()[0][i+2], mRects.get()[0][i+3], &paint);
}
-void DrawProfiler::drawThreshold(OpenGLRenderer* canvas) {
+void FrameInfoVisualizer::drawThreshold(OpenGLRenderer* canvas) {
SkPaint paint;
paint.setColor(THRESHOLD_COLOR);
paint.setStrokeWidth(mThresholdStroke);
@@ -205,7 +168,7 @@ void DrawProfiler::drawThreshold(OpenGLRenderer* canvas) {
canvas->drawLines(pts, 4, &paint);
}
-bool DrawProfiler::consumeProperties() {
+bool FrameInfoVisualizer::consumeProperties() {
bool changed = false;
ProfileType newType = Properties::getProfileType();
if (newType != mType) {
@@ -226,29 +189,25 @@ bool DrawProfiler::consumeProperties() {
return changed;
}
-void DrawProfiler::dumpData(int fd) {
+void FrameInfoVisualizer::dumpData(int fd) {
RETURN_IF_PROFILING_DISABLED();
// This method logs the last N frames (where N is <= mDataSize) since the
// last call to dumpData(). In other words if there's a dumpData(), draw frame,
// dumpData(), the last dumpData() should only log 1 frame.
- const FrameTimingData emptyData = {0, 0, 0, 0};
-
FILE *file = fdopen(fd, "a");
fprintf(file, "\n\tDraw\tPrepare\tProcess\tExecute\n");
- for (int frameOffset = 1; frameOffset <= mDataSize; frameOffset++) {
- int i = (mCurrentFrame + frameOffset) % mDataSize;
- if (!memcmp(mData + i, &emptyData, sizeof(FrameTimingData))) {
+ for (size_t i = 0; i < mFrameSource.size(); i++) {
+ if (mFrameSource[i][FrameInfoIndex::kIntendedVsync] <= mLastFrameLogged) {
continue;
}
+ mLastFrameLogged = mFrameSource[i][FrameInfoIndex::kIntendedVsync];
fprintf(file, "\t%3.2f\t%3.2f\t%3.2f\t%3.2f\n",
- mData[i].record, mData[i].prepare, mData[i].playback, mData[i].swapBuffers);
+ recordDuration(i), prepareDuration(i),
+ issueDrawDuration(i), swapBuffersDuration(i));
}
- // reset the buffer
- memset(mData, 0, sizeof(FrameTimingData) * mDataSize);
- mCurrentFrame = 0;
fflush(file);
}
diff --git a/libs/hwui/DrawProfiler.h b/libs/hwui/FrameInfoVisualizer.h
index ef6101c..f62e34d 100644
--- a/libs/hwui/DrawProfiler.h
+++ b/libs/hwui/FrameInfoVisualizer.h
@@ -16,42 +16,41 @@
#ifndef DRAWPROFILER_H
#define DRAWPROFILER_H
+#include "FrameInfo.h"
#include "Properties.h"
#include "Rect.h"
+#include "utils/RingBuffer.h"
#include <utils/Timers.h>
+#include <memory>
+
namespace android {
namespace uirenderer {
class OpenGLRenderer;
-class DrawProfiler {
+// TODO: This is a bit awkward as it needs to match the thing in CanvasContext
+// A better abstraction here would be nice but iterators are painful
+// and RingBuffer having the size baked into the template is also painful
+// But making DrawProfiler also be templated is ALSO painful
+// At least this is a compile failure if this doesn't match, so there's that.
+typedef RingBuffer<FrameInfo, 120> FrameInfoSource;
+
+class FrameInfoVisualizer {
public:
- DrawProfiler();
- ~DrawProfiler();
+ FrameInfoVisualizer(FrameInfoSource& source);
+ ~FrameInfoVisualizer();
bool consumeProperties();
void setDensity(float density);
- void startFrame(nsecs_t recordDurationNanos = 0);
- void markPlaybackStart();
- void markPlaybackEnd();
- void finishFrame();
-
void unionDirty(SkRect* dirty);
void draw(OpenGLRenderer* canvas);
void dumpData(int fd);
private:
- typedef struct {
- float record;
- float prepare;
- float playback;
- float swapBuffers;
- } FrameTimingData;
-
void createData();
void destroyData();
@@ -61,14 +60,39 @@ private:
void drawCurrentFrame(OpenGLRenderer* canvas);
void drawThreshold(OpenGLRenderer* canvas);
+ static inline float duration(nsecs_t start, nsecs_t end) {
+ float duration = ((end - start) * 0.000001f);
+ return duration > 0.0f ? duration : 0.0f;
+ }
+
+ inline float recordDuration(size_t index) {
+ return duration(
+ mFrameSource[index][FrameInfoIndex::kIntendedVsync],
+ mFrameSource[index][FrameInfoIndex::kSyncStart]);
+ }
+
+ inline float prepareDuration(size_t index) {
+ return duration(
+ mFrameSource[index][FrameInfoIndex::kSyncStart],
+ mFrameSource[index][FrameInfoIndex::kIssueDrawCommandsStart]);
+ }
+
+ inline float issueDrawDuration(size_t index) {
+ return duration(
+ mFrameSource[index][FrameInfoIndex::kIssueDrawCommandsStart],
+ mFrameSource[index][FrameInfoIndex::kSwapBuffers]);
+ }
+
+ inline float swapBuffersDuration(size_t index) {
+ return duration(
+ mFrameSource[index][FrameInfoIndex::kSwapBuffers],
+ mFrameSource[index][FrameInfoIndex::kFrameCompleted]);
+ }
+
ProfileType mType = ProfileType::None;
float mDensity = 0;
- FrameTimingData* mData = nullptr;
- int mDataSize = 0;
-
- int mCurrentFrame = -1;
- nsecs_t mPreviousTime = 0;
+ FrameInfoSource& mFrameSource;
int mVerticalUnit = 0;
int mHorizontalUnit = 0;
@@ -81,11 +105,12 @@ private:
* OpenGLRenderer:drawRects() that makes up all the FrameTimingData:record
* information.
*/
- float** mRects = nullptr;
+ std::unique_ptr<float*> mRects;
bool mShowDirtyRegions = false;
SkRect mDirtyRegion;
bool mFlashToggle = false;
+ nsecs_t mLastFrameLogged = 0;
};
} /* namespace uirenderer */
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index cb5560f..e34444a 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -109,20 +109,6 @@ enum DebugLevel {
#define PROPERTY_PROFILE_VISUALIZE_BARS "visual_bars"
/**
- * System property used to specify the number of frames to be used
- * when doing hardware rendering profiling.
- * The default value of this property is #PROFILE_MAX_FRAMES.
- *
- * When profiling is enabled, the adb shell dumpsys gfxinfo command will
- * output extra information about the time taken to execute by the last
- * frames.
- *
- * Possible values:
- * "60", to set the limit of frames to 60
- */
-#define PROPERTY_PROFILE_MAXFRAMES "debug.hwui.profile.maxframes"
-
-/**
* Used to enable/disable non-rectangular clipping debugging.
*
* The accepted values are:
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 733e5e0..6d7dcf1 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -46,7 +46,8 @@ CanvasContext::CanvasContext(RenderThread& thread, bool translucent,
, mOpaque(!translucent)
, mAnimationContext(contextFactory->createAnimationContext(mRenderThread.timeLord()))
, mRootRenderNode(rootRenderNode)
- , mJankTracker(thread.timeLord().frameIntervalNanos()) {
+ , mJankTracker(thread.timeLord().frameIntervalNanos())
+ , mProfiler(mFrames) {
mRenderThread.renderState().registerCanvasContext(this);
mProfiler.setDensity(mRenderThread.mainDisplayInfo().density);
}
@@ -218,7 +219,6 @@ void CanvasContext::draw() {
return;
}
- profiler().markPlaybackStart();
mCurrentFrameInfo->markIssueDrawCommandsStart();
EGLint width, height;
@@ -251,8 +251,6 @@ void CanvasContext::draw() {
bool drew = mCanvas->finish();
- 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();
@@ -267,7 +265,6 @@ void CanvasContext::draw() {
mCurrentFrameInfo->markFrameCompleted();
mJankTracker.addFrame(*mCurrentFrameInfo);
mRenderThread.jankTracker().addFrame(*mCurrentFrameInfo);
- profiler().finishFrame();
}
// Called by choreographer to do an RT-driven animation
@@ -278,7 +275,6 @@ void CanvasContext::doFrame() {
ATRACE_CALL();
- profiler().startFrame();
int64_t frameInfo[UI_THREAD_FRAME_INFO_SIZE];
UiFrameInfoBuilder(frameInfo)
.addFlag(FrameInfoFlags::kRTAnimation)
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 8163b0f..8d54304 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -18,9 +18,9 @@
#define CANVASCONTEXT_H_
#include "DamageAccumulator.h"
-#include "DrawProfiler.h"
#include "IContextFactory.h"
#include "FrameInfo.h"
+#include "FrameInfoVisualizer.h"
#include "RenderNode.h"
#include "utils/RingBuffer.h"
#include "renderthread/RenderTask.h"
@@ -103,7 +103,7 @@ public:
void stopDrawing();
void notifyFramePending();
- DrawProfiler& profiler() { return mProfiler; }
+ FrameInfoVisualizer& profiler() { return mProfiler; }
void dumpFrames(int fd);
void resetFrameStats();
@@ -140,12 +140,12 @@ private:
const sp<RenderNode> mRootRenderNode;
- DrawProfiler mProfiler;
FrameInfo* mCurrentFrameInfo = nullptr;
- // Ring buffer large enough for 1 second worth of frames
- RingBuffer<FrameInfo, 60> mFrames;
+ // Ring buffer large enough for 2 seconds worth of frames
+ RingBuffer<FrameInfo, 120> mFrames;
std::string mName;
JankTracker mJankTracker;
+ FrameInfoVisualizer mProfiler;
std::set<RenderNode*> mPrefetechedLayers;
};
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 35391b2..83af4ae 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -83,8 +83,6 @@ void DrawFrameTask::postAndWait() {
void DrawFrameTask::run() {
ATRACE_NAME("DrawFrame");
- mContext->profiler().startFrame();
-
bool canUnblockUiThread;
bool canDrawThisFrame;
{
diff --git a/libs/hwui/utils/RingBuffer.h b/libs/hwui/utils/RingBuffer.h
index fc9aec0..6d0a06b 100644
--- a/libs/hwui/utils/RingBuffer.h
+++ b/libs/hwui/utils/RingBuffer.h
@@ -31,7 +31,7 @@ public:
RingBuffer() {}
~RingBuffer() {}
- size_t capacity() { return SIZE; }
+ constexpr size_t capacity() { return SIZE; }
size_t size() { return mCount; }
T& next() {