diff options
Diffstat (limited to 'libs/hwui/FrameInfoVisualizer.cpp')
-rw-r--r-- | libs/hwui/FrameInfoVisualizer.cpp | 164 |
1 files changed, 107 insertions, 57 deletions
diff --git a/libs/hwui/FrameInfoVisualizer.cpp b/libs/hwui/FrameInfoVisualizer.cpp index 0411742..7f9d9b9 100644 --- a/libs/hwui/FrameInfoVisualizer.cpp +++ b/libs/hwui/FrameInfoVisualizer.cpp @@ -18,6 +18,7 @@ #include "OpenGLRenderer.h" #include <cutils/compiler.h> +#include <array> #define RETURN_IF_PROFILING_DISABLED() if (CC_LIKELY(mType == ProfileType::None)) return #define RETURN_IF_DISABLED() if (CC_LIKELY(mType == ProfileType::None && !mShowDirtyRegions)) return @@ -26,27 +27,35 @@ #define PROFILE_DRAW_THRESHOLD_STROKE_WIDTH 2 #define PROFILE_DRAW_DP_PER_MS 7 -// Number of floats we want to display from FrameTimingData -// If this is changed make sure to update the indexes below -#define NUM_ELEMENTS 4 - -#define RECORD_INDEX 0 -#define PREPARE_INDEX 1 -#define PLAYBACK_INDEX 2 -#define SWAPBUFFERS_INDEX 3 - // Must be NUM_ELEMENTS in size -static const SkColor ELEMENT_COLORS[] = { 0xcf3e66cc, 0xcf8f00ff, 0xcfdc3912, 0xcfe69800 }; -static const SkColor CURRENT_FRAME_COLOR = 0xcf5faa4d; static const SkColor THRESHOLD_COLOR = 0xff5faa4d; +static const SkColor BAR_FAST_ALPHA = 0x8F000000; +static const SkColor BAR_JANKY_ALPHA = 0xDF000000; // We could get this from TimeLord and use the actual frame interval, but // this is good enough #define FRAME_THRESHOLD 16 +#define FRAME_THRESHOLD_NS 16000000 namespace android { namespace uirenderer { +struct BarSegment { + FrameInfoIndex start; + FrameInfoIndex end; + SkColor color; +}; + +static const std::array<BarSegment,7> Bar {{ + { FrameInfoIndex::IntendedVsync, FrameInfoIndex::HandleInputStart, 0x00796B }, + { FrameInfoIndex::HandleInputStart, FrameInfoIndex::PerformTraversalsStart, 0x388E3C }, + { FrameInfoIndex::PerformTraversalsStart, FrameInfoIndex::DrawStart, 0x689F38}, + { FrameInfoIndex::DrawStart, FrameInfoIndex::SyncStart, 0x2196F3}, + { FrameInfoIndex::SyncStart, FrameInfoIndex::IssueDrawCommandsStart, 0x4FC3F7}, + { FrameInfoIndex::IssueDrawCommandsStart, FrameInfoIndex::SwapBuffers, 0xF44336}, + { FrameInfoIndex::SwapBuffers, FrameInfoIndex::FrameCompleted, 0xFF9800}, +}}; + static int dpToPx(int dp, float density) { return (int) (dp * density + 0.5f); } @@ -64,7 +73,6 @@ void FrameInfoVisualizer::setDensity(float density) { if (CC_UNLIKELY(mDensity != density)) { mDensity = density; mVerticalUnit = dpToPx(PROFILE_DRAW_DP_PER_MS, density); - mHorizontalUnit = dpToPx(PROFILE_DRAW_WIDTH, density); mThresholdStroke = dpToPx(PROFILE_DRAW_THRESHOLD_STROKE_WIDTH, density); } } @@ -93,67 +101,107 @@ void FrameInfoVisualizer::draw(OpenGLRenderer* canvas) { } if (mType == ProfileType::Bars) { - prepareShapes(canvas->getViewportHeight()); + // Patch up the current frame to pretend we ended here. CanvasContext + // will overwrite these values with the real ones after we return. + // This is a bit nicer looking than the vague green bar, as we have + // valid data for almost all the stages and a very good idea of what + // the issue stage will look like, too + FrameInfo& info = mFrameSource.back(); + info.markSwapBuffers(); + info.markFrameCompleted(); + + initializeRects(canvas->getViewportHeight(), canvas->getViewportWidth()); drawGraph(canvas); - drawCurrentFrame(canvas); drawThreshold(canvas); } } void FrameInfoVisualizer::createData() { - if (mRects.get()) return; + if (mFastRects.get()) return; - mRects.reset(new float*[mFrameSource.capacity()]); - for (int i = 0; i < NUM_ELEMENTS; i++) { - // 4 floats per rect - mRects.get()[i] = (float*) calloc(mFrameSource.capacity(), 4 * sizeof(float)); - } + mFastRects.reset(new float[mFrameSource.capacity() * 4]); + mJankyRects.reset(new float[mFrameSource.capacity() * 4]); } void FrameInfoVisualizer::destroyData() { - mRects.reset(nullptr); + mFastRects.reset(nullptr); + mJankyRects.reset(nullptr); } -void FrameInfoVisualizer::addRect(Rect& r, float data, float* shapeOutput) { - r.top = r.bottom - (data * mVerticalUnit); - shapeOutput[0] = r.left; - shapeOutput[1] = r.top; - shapeOutput[2] = r.right; - shapeOutput[3] = r.bottom; - r.bottom = r.top; -} +void FrameInfoVisualizer::initializeRects(const int baseline, const int width) { + // Target the 95% mark for the current frame + float right = width * .95; + float baseLineWidth = right / mFrameSource.capacity(); + mNumFastRects = 0; + mNumJankyRects = 0; + int fast_i = 0, janky_i = 0; + // Set the bottom of all the shapes to the baseline + for (int fi = mFrameSource.size() - 1; fi >= 0; fi--) { + if (mFrameSource[fi][FrameInfoIndex::Flags] & FrameInfoFlags::SkippedFrame) { + continue; + } + float lineWidth = baseLineWidth; + float* rect; + int ri; + // Rects are LTRB + if (mFrameSource[fi].totalDuration() <= FRAME_THRESHOLD_NS) { + rect = mFastRects.get(); + ri = fast_i; + fast_i += 4; + mNumFastRects++; + } else { + rect = mJankyRects.get(); + ri = janky_i; + janky_i += 4; + mNumJankyRects++; + lineWidth *= 2; + } -void FrameInfoVisualizer::prepareShapes(const int baseline) { - Rect r; - r.right = mHorizontalUnit; - for (size_t i = 0; i < mFrameSource.size(); i++) { - const int shapeIndex = i * 4; - r.bottom = baseline; - 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); + rect[ri + 0] = right - lineWidth; + rect[ri + 1] = baseline; + rect[ri + 2] = right; + rect[ri + 3] = baseline; + right -= lineWidth; } } -void FrameInfoVisualizer::drawGraph(OpenGLRenderer* canvas) { - SkPaint paint; - for (int i = 0; i < NUM_ELEMENTS; i++) { - paint.setColor(ELEMENT_COLORS[i]); - canvas->drawRects(mRects.get()[i], mFrameSource.capacity() * 4, &paint); +void FrameInfoVisualizer::nextBarSegment(FrameInfoIndex start, FrameInfoIndex end) { + int fast_i = (mNumFastRects - 1) * 4; + int janky_i = (mNumJankyRects - 1) * 4;; + for (size_t fi = 0; fi < mFrameSource.size(); fi++) { + if (mFrameSource[fi][FrameInfoIndex::Flags] & FrameInfoFlags::SkippedFrame) { + continue; + } + + float* rect; + int ri; + // Rects are LTRB + if (mFrameSource[fi].totalDuration() <= FRAME_THRESHOLD_NS) { + rect = mFastRects.get(); + ri = fast_i; + fast_i -= 4; + } else { + rect = mJankyRects.get(); + ri = janky_i; + janky_i -= 4; + } + + // Set the bottom to the old top (build upwards) + rect[ri + 3] = rect[ri + 1]; + // Move the top up by the duration + rect[ri + 1] -= mVerticalUnit * duration(fi, start, end); } } -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 +void FrameInfoVisualizer::drawGraph(OpenGLRenderer* canvas) { SkPaint paint; - paint.setColor(CURRENT_FRAME_COLOR); - 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); + for (size_t i = 0; i < Bar.size(); i++) { + nextBarSegment(Bar[i].start, Bar[i].end); + paint.setColor(Bar[i].color | BAR_FAST_ALPHA); + canvas->drawRects(mFastRects.get(), mNumFastRects * 4, &paint); + paint.setColor(Bar[i].color | BAR_JANKY_ALPHA); + canvas->drawRects(mJankyRects.get(), mNumJankyRects * 4, &paint); + } } void FrameInfoVisualizer::drawThreshold(OpenGLRenderer* canvas) { @@ -200,13 +248,15 @@ void FrameInfoVisualizer::dumpData(int fd) { fprintf(file, "\n\tDraw\tPrepare\tProcess\tExecute\n"); for (size_t i = 0; i < mFrameSource.size(); i++) { - if (mFrameSource[i][FrameInfoIndex::kIntendedVsync] <= mLastFrameLogged) { + if (mFrameSource[i][FrameInfoIndex::IntendedVsync] <= mLastFrameLogged) { continue; } - mLastFrameLogged = mFrameSource[i][FrameInfoIndex::kIntendedVsync]; + mLastFrameLogged = mFrameSource[i][FrameInfoIndex::IntendedVsync]; fprintf(file, "\t%3.2f\t%3.2f\t%3.2f\t%3.2f\n", - recordDuration(i), prepareDuration(i), - issueDrawDuration(i), swapBuffersDuration(i)); + duration(i, FrameInfoIndex::IntendedVsync, FrameInfoIndex::SyncStart), + duration(i, FrameInfoIndex::SyncStart, FrameInfoIndex::IssueDrawCommandsStart), + duration(i, FrameInfoIndex::IssueDrawCommandsStart, FrameInfoIndex::SwapBuffers), + duration(i, FrameInfoIndex::SwapBuffers, FrameInfoIndex::FrameCompleted)); } fflush(file); |