1fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck/*
2fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck * Copyright (C) 2014 The Android Open Source Project
3fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck *
4fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck * Licensed under the Apache License, Version 2.0 (the "License");
5fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck * you may not use this file except in compliance with the License.
6fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck * You may obtain a copy of the License at
7fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck *
8fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck *      http://www.apache.org/licenses/LICENSE-2.0
9fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck *
10fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck * Unless required by applicable law or agreed to in writing, software
11fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck * distributed under the License is distributed on an "AS IS" BASIS,
12fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck * See the License for the specific language governing permissions and
14fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck * limitations under the License.
15fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck */
16fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck#include "DrawProfiler.h"
17fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
18fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck#include <cutils/compiler.h>
19fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
20fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck#include "OpenGLRenderer.h"
21fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck#include "Properties.h"
22fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
23fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck#define DEFAULT_MAX_FRAMES 128
24fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
2523d307c8d88f4a3849163b9e5b7cd11d0d4f372cJohn Reck#define RETURN_IF_PROFILING_DISABLED() if (CC_LIKELY(mType == kNone)) return
2623d307c8d88f4a3849163b9e5b7cd11d0d4f372cJohn Reck#define RETURN_IF_DISABLED() if (CC_LIKELY(mType == kNone && !mShowDirtyRegions)) return
27fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
28fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck#define NANOS_TO_MILLIS_FLOAT(nanos) ((nanos) * 0.000001f)
29fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
30fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck#define PROFILE_DRAW_WIDTH 3
31fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck#define PROFILE_DRAW_THRESHOLD_STROKE_WIDTH 2
32fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck#define PROFILE_DRAW_DP_PER_MS 7
33fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
34fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck// Number of floats we want to display from FrameTimingData
35fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck// If this is changed make sure to update the indexes below
36fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck#define NUM_ELEMENTS 4
37fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
38fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck#define RECORD_INDEX 0
39fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck#define PREPARE_INDEX 1
40fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck#define PLAYBACK_INDEX 2
41fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck#define SWAPBUFFERS_INDEX 3
42fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
43fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck// Must be NUM_ELEMENTS in size
44fe5e7b7346a54537b980796ceeca66bfdbd05561John Reckstatic const SkColor ELEMENT_COLORS[] = { 0xcf3e66cc, 0xcf8f00ff, 0xcfdc3912, 0xcfe69800 };
45fe5e7b7346a54537b980796ceeca66bfdbd05561John Reckstatic const SkColor CURRENT_FRAME_COLOR = 0xcf5faa4d;
46fe5e7b7346a54537b980796ceeca66bfdbd05561John Reckstatic const SkColor THRESHOLD_COLOR = 0xff5faa4d;
47fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
48fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck// We could get this from TimeLord and use the actual frame interval, but
49fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck// this is good enough
50fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck#define FRAME_THRESHOLD 16
51fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
52fe5e7b7346a54537b980796ceeca66bfdbd05561John Recknamespace android {
53fe5e7b7346a54537b980796ceeca66bfdbd05561John Recknamespace uirenderer {
54fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
55fe5e7b7346a54537b980796ceeca66bfdbd05561John Reckstatic int dpToPx(int dp, float density) {
56fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    return (int) (dp * density + 0.5f);
57fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck}
58fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
59fe5e7b7346a54537b980796ceeca66bfdbd05561John ReckDrawProfiler::DrawProfiler()
60fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        : mType(kNone)
61fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        , mDensity(0)
62fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        , mData(NULL)
63fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        , mDataSize(0)
64fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        , mCurrentFrame(-1)
65fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        , mPreviousTime(0)
66fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        , mVerticalUnit(0)
67fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        , mHorizontalUnit(0)
6823d307c8d88f4a3849163b9e5b7cd11d0d4f372cJohn Reck        , mThresholdStroke(0)
6923d307c8d88f4a3849163b9e5b7cd11d0d4f372cJohn Reck        , mShowDirtyRegions(false)
7023d307c8d88f4a3849163b9e5b7cd11d0d4f372cJohn Reck        , mFlashToggle(false) {
71fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    setDensity(1);
72fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck}
73fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
74fe5e7b7346a54537b980796ceeca66bfdbd05561John ReckDrawProfiler::~DrawProfiler() {
75fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    destroyData();
76fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck}
77fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
78fe5e7b7346a54537b980796ceeca66bfdbd05561John Reckvoid DrawProfiler::setDensity(float density) {
79fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    if (CC_UNLIKELY(mDensity != density)) {
80fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        mDensity = density;
81fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        mVerticalUnit = dpToPx(PROFILE_DRAW_DP_PER_MS, density);
82fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        mHorizontalUnit = dpToPx(PROFILE_DRAW_WIDTH, density);
83fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        mThresholdStroke = dpToPx(PROFILE_DRAW_THRESHOLD_STROKE_WIDTH, density);
84fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    }
85fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck}
86fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
87fe5e7b7346a54537b980796ceeca66bfdbd05561John Reckvoid DrawProfiler::startFrame(nsecs_t recordDurationNanos) {
8823d307c8d88f4a3849163b9e5b7cd11d0d4f372cJohn Reck    RETURN_IF_PROFILING_DISABLED();
89fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    mData[mCurrentFrame].record = NANOS_TO_MILLIS_FLOAT(recordDurationNanos);
90fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    mPreviousTime = systemTime(CLOCK_MONOTONIC);
91fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck}
92fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
93fe5e7b7346a54537b980796ceeca66bfdbd05561John Reckvoid DrawProfiler::markPlaybackStart() {
9423d307c8d88f4a3849163b9e5b7cd11d0d4f372cJohn Reck    RETURN_IF_PROFILING_DISABLED();
95fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    nsecs_t now = systemTime(CLOCK_MONOTONIC);
96fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    mData[mCurrentFrame].prepare = NANOS_TO_MILLIS_FLOAT(now - mPreviousTime);
97fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    mPreviousTime = now;
98fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck}
99fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
100fe5e7b7346a54537b980796ceeca66bfdbd05561John Reckvoid DrawProfiler::markPlaybackEnd() {
10123d307c8d88f4a3849163b9e5b7cd11d0d4f372cJohn Reck    RETURN_IF_PROFILING_DISABLED();
102fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    nsecs_t now = systemTime(CLOCK_MONOTONIC);
103fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    mData[mCurrentFrame].playback = NANOS_TO_MILLIS_FLOAT(now - mPreviousTime);
104fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    mPreviousTime = now;
105fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck}
106fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
107fe5e7b7346a54537b980796ceeca66bfdbd05561John Reckvoid DrawProfiler::finishFrame() {
10823d307c8d88f4a3849163b9e5b7cd11d0d4f372cJohn Reck    RETURN_IF_PROFILING_DISABLED();
109fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    nsecs_t now = systemTime(CLOCK_MONOTONIC);
110fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    mData[mCurrentFrame].swapBuffers = NANOS_TO_MILLIS_FLOAT(now - mPreviousTime);
111fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    mPreviousTime = now;
112fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    mCurrentFrame = (mCurrentFrame + 1) % mDataSize;
113fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck}
114fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
115e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reckvoid DrawProfiler::unionDirty(SkRect* dirty) {
116fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    RETURN_IF_DISABLED();
117fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    // Not worth worrying about minimizing the dirty region for debugging, so just
118fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    // dirty the entire viewport.
119fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    if (dirty) {
12023d307c8d88f4a3849163b9e5b7cd11d0d4f372cJohn Reck        mDirtyRegion = *dirty;
121fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        dirty->setEmpty();
122fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    }
123fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck}
124fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
125fe5e7b7346a54537b980796ceeca66bfdbd05561John Reckvoid DrawProfiler::draw(OpenGLRenderer* canvas) {
12623d307c8d88f4a3849163b9e5b7cd11d0d4f372cJohn Reck    RETURN_IF_DISABLED();
12723d307c8d88f4a3849163b9e5b7cd11d0d4f372cJohn Reck
12823d307c8d88f4a3849163b9e5b7cd11d0d4f372cJohn Reck    if (mShowDirtyRegions) {
12923d307c8d88f4a3849163b9e5b7cd11d0d4f372cJohn Reck        mFlashToggle = !mFlashToggle;
13023d307c8d88f4a3849163b9e5b7cd11d0d4f372cJohn Reck        if (mFlashToggle) {
13123d307c8d88f4a3849163b9e5b7cd11d0d4f372cJohn Reck            SkPaint paint;
13223d307c8d88f4a3849163b9e5b7cd11d0d4f372cJohn Reck            paint.setColor(0x7fff0000);
13323d307c8d88f4a3849163b9e5b7cd11d0d4f372cJohn Reck            canvas->drawRect(mDirtyRegion.fLeft, mDirtyRegion.fTop,
13423d307c8d88f4a3849163b9e5b7cd11d0d4f372cJohn Reck                    mDirtyRegion.fRight, mDirtyRegion.fBottom, &paint);
13523d307c8d88f4a3849163b9e5b7cd11d0d4f372cJohn Reck        }
136fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    }
137fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
13823d307c8d88f4a3849163b9e5b7cd11d0d4f372cJohn Reck    if (mType == kBars) {
13923d307c8d88f4a3849163b9e5b7cd11d0d4f372cJohn Reck        prepareShapes(canvas->getViewportHeight());
14023d307c8d88f4a3849163b9e5b7cd11d0d4f372cJohn Reck        drawGraph(canvas);
14123d307c8d88f4a3849163b9e5b7cd11d0d4f372cJohn Reck        drawCurrentFrame(canvas);
14223d307c8d88f4a3849163b9e5b7cd11d0d4f372cJohn Reck        drawThreshold(canvas);
14323d307c8d88f4a3849163b9e5b7cd11d0d4f372cJohn Reck    }
144fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck}
145fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
146fe5e7b7346a54537b980796ceeca66bfdbd05561John Reckvoid DrawProfiler::createData() {
147fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    if (mData) return;
148fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
149fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    mDataSize = property_get_int32(PROPERTY_PROFILE_MAXFRAMES, DEFAULT_MAX_FRAMES);
150fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    if (mDataSize <= 0) mDataSize = 1;
151fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    if (mDataSize > 4096) mDataSize = 4096; // Reasonable maximum
152fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    mData = (FrameTimingData*) calloc(mDataSize, sizeof(FrameTimingData));
153fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    mRects = new float*[NUM_ELEMENTS];
154fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    for (int i = 0; i < NUM_ELEMENTS; i++) {
155fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        // 4 floats per rect
156fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        mRects[i] = (float*) calloc(mDataSize, 4 * sizeof(float));
157fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    }
158fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    mCurrentFrame = 0;
159fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck}
160fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
161fe5e7b7346a54537b980796ceeca66bfdbd05561John Reckvoid DrawProfiler::destroyData() {
162fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    delete mData;
163fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    mData = NULL;
164fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck}
165fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
166fe5e7b7346a54537b980796ceeca66bfdbd05561John Reckvoid DrawProfiler::addRect(Rect& r, float data, float* shapeOutput) {
167fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    r.top = r.bottom - (data * mVerticalUnit);
168fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    shapeOutput[0] = r.left;
169fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    shapeOutput[1] = r.top;
170fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    shapeOutput[2] = r.right;
171fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    shapeOutput[3] = r.bottom;
172fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    r.bottom = r.top;
173fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck}
174fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
175fe5e7b7346a54537b980796ceeca66bfdbd05561John Reckvoid DrawProfiler::prepareShapes(const int baseline) {
176fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    Rect r;
177fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    r.right = mHorizontalUnit;
178fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    for (int i = 0; i < mDataSize; i++) {
179fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        const int shapeIndex = i * 4;
180fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        r.bottom = baseline;
181fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        addRect(r, mData[i].record, mRects[RECORD_INDEX] + shapeIndex);
182fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        addRect(r, mData[i].prepare, mRects[PREPARE_INDEX] + shapeIndex);
183fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        addRect(r, mData[i].playback, mRects[PLAYBACK_INDEX] + shapeIndex);
184fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        addRect(r, mData[i].swapBuffers, mRects[SWAPBUFFERS_INDEX] + shapeIndex);
185fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        r.translate(mHorizontalUnit, 0);
186fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    }
187fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck}
188fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
189fe5e7b7346a54537b980796ceeca66bfdbd05561John Reckvoid DrawProfiler::drawGraph(OpenGLRenderer* canvas) {
190fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    SkPaint paint;
191fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    for (int i = 0; i < NUM_ELEMENTS; i++) {
192fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        paint.setColor(ELEMENT_COLORS[i]);
193fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        canvas->drawRects(mRects[i], mDataSize * 4, &paint);
194fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    }
195fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck}
196fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
197fe5e7b7346a54537b980796ceeca66bfdbd05561John Reckvoid DrawProfiler::drawCurrentFrame(OpenGLRenderer* canvas) {
198fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    // This draws a solid rect over the entirety of the current frame's shape
199fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    // To do so we use the bottom of mRects[0] and the top of mRects[NUM_ELEMENTS-1]
200fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    // which will therefore fully overlap the previously drawn rects
201fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    SkPaint paint;
202fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    paint.setColor(CURRENT_FRAME_COLOR);
203fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    const int i = mCurrentFrame * 4;
204fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    canvas->drawRect(mRects[0][i], mRects[NUM_ELEMENTS-1][i+1], mRects[0][i+2],
205fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck            mRects[0][i+3], &paint);
206fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck}
207fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
208fe5e7b7346a54537b980796ceeca66bfdbd05561John Reckvoid DrawProfiler::drawThreshold(OpenGLRenderer* canvas) {
209fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    SkPaint paint;
210fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    paint.setColor(THRESHOLD_COLOR);
211fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    paint.setStrokeWidth(mThresholdStroke);
212fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
213fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    float pts[4];
214fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    pts[0] = 0.0f;
215fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    pts[1] = pts[3] = canvas->getViewportHeight() - (FRAME_THRESHOLD * mVerticalUnit);
216fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    pts[2] = canvas->getViewportWidth();
217fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    canvas->drawLines(pts, 4, &paint);
218fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck}
219fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
220fe5e7b7346a54537b980796ceeca66bfdbd05561John ReckDrawProfiler::ProfileType DrawProfiler::loadRequestedProfileType() {
221fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    ProfileType type = kNone;
222fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    char buf[PROPERTY_VALUE_MAX] = {'\0',};
223fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    if (property_get(PROPERTY_PROFILE, buf, "") > 0) {
224fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        if (!strcmp(buf, PROPERTY_PROFILE_VISUALIZE_BARS)) {
225fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck            type = kBars;
226fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        } else if (!strcmp(buf, "true")) {
227fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck            type = kConsole;
228fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        }
229fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    }
230fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    return type;
231fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck}
232fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
233fe5e7b7346a54537b980796ceeca66bfdbd05561John Reckbool DrawProfiler::loadSystemProperties() {
23423d307c8d88f4a3849163b9e5b7cd11d0d4f372cJohn Reck    bool changed = false;
235fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    ProfileType newType = loadRequestedProfileType();
236fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    if (newType != mType) {
237fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        mType = newType;
238fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        if (mType == kNone) {
239fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck            destroyData();
240fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        } else {
241fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck            createData();
242fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        }
24323d307c8d88f4a3849163b9e5b7cd11d0d4f372cJohn Reck        changed = true;
244fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    }
24523d307c8d88f4a3849163b9e5b7cd11d0d4f372cJohn Reck    bool showDirty = property_get_bool(PROPERTY_DEBUG_SHOW_DIRTY_REGIONS, false);
24623d307c8d88f4a3849163b9e5b7cd11d0d4f372cJohn Reck    if (showDirty != mShowDirtyRegions) {
24723d307c8d88f4a3849163b9e5b7cd11d0d4f372cJohn Reck        mShowDirtyRegions = showDirty;
24823d307c8d88f4a3849163b9e5b7cd11d0d4f372cJohn Reck        changed = true;
24923d307c8d88f4a3849163b9e5b7cd11d0d4f372cJohn Reck    }
25023d307c8d88f4a3849163b9e5b7cd11d0d4f372cJohn Reck    return changed;
251fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck}
252fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
253fe5e7b7346a54537b980796ceeca66bfdbd05561John Reckvoid DrawProfiler::dumpData(int fd) {
25423d307c8d88f4a3849163b9e5b7cd11d0d4f372cJohn Reck    RETURN_IF_PROFILING_DISABLED();
255fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
256fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    // This method logs the last N frames (where N is <= mDataSize) since the
257fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    // last call to dumpData(). In other words if there's a dumpData(), draw frame,
258fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    // dumpData(), the last dumpData() should only log 1 frame.
259fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
260fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    const FrameTimingData emptyData = {0, 0, 0, 0};
261fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
262fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    FILE *file = fdopen(fd, "a");
263fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    fprintf(file, "\n\tDraw\tPrepare\tProcess\tExecute\n");
264fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
265fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    for (int frameOffset = 1; frameOffset <= mDataSize; frameOffset++) {
266fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        int i = (mCurrentFrame + frameOffset) % mDataSize;
267fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        if (!memcmp(mData + i, &emptyData, sizeof(FrameTimingData))) {
268fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck            continue;
269fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        }
270fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck        fprintf(file, "\t%3.2f\t%3.2f\t%3.2f\t%3.2f\n",
271fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck                mData[i].record, mData[i].prepare, mData[i].playback, mData[i].swapBuffers);
272fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    }
273fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    // reset the buffer
274fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    memset(mData, 0, sizeof(FrameTimingData) * mDataSize);
275fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    mCurrentFrame = 0;
276fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
277fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    fflush(file);
278fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck}
279fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
280fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck} /* namespace uirenderer */
281fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck} /* namespace android */
282