/*
 * Copyright (C) 2014 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 "DrawProfiler.h"

#include <cutils/compiler.h>

#include "OpenGLRenderer.h"
#include "Properties.h"

#define DEFAULT_MAX_FRAMES 128

#define RETURN_IF_DISABLED() if (CC_LIKELY(mType == kNone)) 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

// 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;

// We could get this from TimeLord and use the actual frame interval, but
// this is good enough
#define FRAME_THRESHOLD 16

namespace android {
namespace uirenderer {

static int dpToPx(int dp, float density) {
    return (int) (dp * density + 0.5f);
}

DrawProfiler::DrawProfiler()
        : mType(kNone)
        , mDensity(0)
        , mData(NULL)
        , mDataSize(0)
        , mCurrentFrame(-1)
        , mPreviousTime(0)
        , mVerticalUnit(0)
        , mHorizontalUnit(0)
        , mThresholdStroke(0) {
    setDensity(1);
}

DrawProfiler::~DrawProfiler() {
    destroyData();
}

void DrawProfiler::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);
    }
}

void DrawProfiler::startFrame(nsecs_t recordDurationNanos) {
    RETURN_IF_DISABLED();
    mData[mCurrentFrame].record = NANOS_TO_MILLIS_FLOAT(recordDurationNanos);
    mPreviousTime = systemTime(CLOCK_MONOTONIC);
}

void DrawProfiler::markPlaybackStart() {
    RETURN_IF_DISABLED();
    nsecs_t now = systemTime(CLOCK_MONOTONIC);
    mData[mCurrentFrame].prepare = NANOS_TO_MILLIS_FLOAT(now - mPreviousTime);
    mPreviousTime = now;
}

void DrawProfiler::markPlaybackEnd() {
    RETURN_IF_DISABLED();
    nsecs_t now = systemTime(CLOCK_MONOTONIC);
    mData[mCurrentFrame].playback = NANOS_TO_MILLIS_FLOAT(now - mPreviousTime);
    mPreviousTime = now;
}

void DrawProfiler::finishFrame() {
    RETURN_IF_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) {
    RETURN_IF_DISABLED();
    // Not worth worrying about minimizing the dirty region for debugging, so just
    // dirty the entire viewport.
    if (dirty) {
        dirty->setEmpty();
    }
}

void DrawProfiler::draw(OpenGLRenderer* canvas) {
    if (CC_LIKELY(mType != kBars)) {
        return;
    }

    prepareShapes(canvas->getViewportHeight());
    drawGraph(canvas);
    drawCurrentFrame(canvas);
    drawThreshold(canvas);
}

void DrawProfiler::createData() {
    if (mData) 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];
    for (int i = 0; i < NUM_ELEMENTS; i++) {
        // 4 floats per rect
        mRects[i] = (float*) calloc(mDataSize, 4 * sizeof(float));
    }
    mCurrentFrame = 0;
}

void DrawProfiler::destroyData() {
    delete mData;
    mData = NULL;
}

void DrawProfiler::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 DrawProfiler::prepareShapes(const int baseline) {
    Rect r;
    r.right = mHorizontalUnit;
    for (int i = 0; i < mDataSize; 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);
        r.translate(mHorizontalUnit, 0);
    }
}

void DrawProfiler::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);
    }
}

void DrawProfiler::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);
}

void DrawProfiler::drawThreshold(OpenGLRenderer* canvas) {
    SkPaint paint;
    paint.setColor(THRESHOLD_COLOR);
    paint.setStrokeWidth(mThresholdStroke);

    float pts[4];
    pts[0] = 0.0f;
    pts[1] = pts[3] = canvas->getViewportHeight() - (FRAME_THRESHOLD * mVerticalUnit);
    pts[2] = canvas->getViewportWidth();
    canvas->drawLines(pts, 4, &paint);
}

DrawProfiler::ProfileType DrawProfiler::loadRequestedProfileType() {
    ProfileType type = kNone;
    char buf[PROPERTY_VALUE_MAX] = {'\0',};
    if (property_get(PROPERTY_PROFILE, buf, "") > 0) {
        if (!strcmp(buf, PROPERTY_PROFILE_VISUALIZE_BARS)) {
            type = kBars;
        } else if (!strcmp(buf, "true")) {
            type = kConsole;
        }
    }
    return type;
}

bool DrawProfiler::loadSystemProperties() {
    ProfileType newType = loadRequestedProfileType();
    if (newType != mType) {
        mType = newType;
        if (mType == kNone) {
            destroyData();
        } else {
            createData();
        }
        return true;
    }
    return false;
}

void DrawProfiler::dumpData(int fd) {
    RETURN_IF_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))) {
            continue;
        }
        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);
    }
    // reset the buffer
    memset(mData, 0, sizeof(FrameTimingData) * mDataSize);
    mCurrentFrame = 0;

    fflush(file);
}

} /* namespace uirenderer */
} /* namespace android */
