/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "Benchmark.h"
#include "SkCanvas.h"
#include "SkColor.h"
#include "SkPaint.h"
#include "SkPicture.h"
#include "SkPictureRecorder.h"
#include "SkPoint.h"
#include "SkRandom.h"
#include "SkRect.h"
#include "SkString.h"

class PictureRecordBench : public Benchmark {
public:
    PictureRecordBench(const char name[])  {
        fName.printf("picture_record_%s", name);
    }

    virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
        return backend == kNonRendering_Backend;
    }

    enum {
        PICTURE_WIDTH = 1000,
        PICTURE_HEIGHT = 4000,
    };
protected:
    virtual const char* onGetName() SK_OVERRIDE {
        return fName.c_str();
    }
private:
    SkString fName;
    typedef Benchmark INHERITED;
};


static const int kMaxLoopsPerCanvas = 10000;

/*
 *  An SkPicture has internal dictionaries to store bitmaps, matrices, paints,
 *  and regions.  This bench populates those dictionaries to test the speed of
 *  reading and writing to those particular dictionary data structures.
 */
class DictionaryRecordBench : public PictureRecordBench {
public:
    DictionaryRecordBench() : INHERITED("dictionaries") {}

protected:
    virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE {
        SkPictureRecorder recorder;
        SkCanvas* canvas = recorder.beginRecording(PICTURE_WIDTH, PICTURE_HEIGHT);

        const SkPoint translateDelta = getTranslateDelta(loops);

        for (int i = 0; i < loops; i++) {
            if (0 == i % kMaxLoopsPerCanvas) {
                SkAutoTUnref<SkPicture> picture(recorder.endRecording());
                canvas = recorder.beginRecording(PICTURE_WIDTH, PICTURE_HEIGHT);
            }

            SkColor color = SK_ColorYELLOW + (i % 255);
            SkIRect rect = SkIRect::MakeWH(i % PICTURE_WIDTH, i % PICTURE_HEIGHT);

            canvas->save();

            // set the clip to the given region
            SkRegion region;
            region.setRect(rect);
            canvas->clipRegion(region);

            // fill the clip with a color
            SkPaint paint;
            paint.setColor(color);
            canvas->drawPaint(paint);

            // set a matrix on the canvas
            SkMatrix matrix;
            matrix.setRotate(SkIntToScalar(i % 360));
            canvas->setMatrix(matrix);

            // create a simple bitmap
            SkBitmap bitmap;
            bitmap.allocPixels(SkImageInfo::Make(10, 10,
                                                 kRGB_565_SkColorType, kOpaque_SkAlphaType));

            // draw a single color into the bitmap
            SkCanvas bitmapCanvas(bitmap);
            bitmapCanvas.drawColor(SkColorSetA(color, i % 255));

            // draw the bitmap onto the canvas
            canvas->drawBitmapMatrix(bitmap, matrix);

            canvas->restore();
            canvas->translate(translateDelta.fX, translateDelta.fY);
        }
        SkAutoTUnref<SkPicture> cleanup(recorder.endRecording());
    }

    SkPoint getTranslateDelta(int M) {
        SkIPoint canvasSize = onGetSize();
        return SkPoint::Make(SkIntToScalar((PICTURE_WIDTH - canvasSize.fX)/M),
                             SkIntToScalar((PICTURE_HEIGHT- canvasSize.fY)/M));
    }
private:
    typedef PictureRecordBench INHERITED;
};

/*
 *  Populates the SkPaint dictionary with a large number of unique paint
 *  objects that differ only by color
 */
class UniquePaintDictionaryRecordBench : public PictureRecordBench {
public:
    UniquePaintDictionaryRecordBench() : INHERITED("unique_paint_dictionary") { }

protected:
    virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE {
        SkRandom rand;
        SkPaint paint;
        SkPictureRecorder recorder;
        SkCanvas* canvas = recorder.beginRecording(PICTURE_WIDTH, PICTURE_HEIGHT);
        for (int i = 0; i < loops; i++) {
            if (0 == i % kMaxLoopsPerCanvas) {
                SkAutoTUnref<SkPicture> picture(recorder.endRecording());
                canvas = recorder.beginRecording(PICTURE_WIDTH, PICTURE_HEIGHT);
            }
            paint.setColor(rand.nextU());
            canvas->drawPaint(paint);
        }
        SkAutoTUnref<SkPicture> cleanup(recorder.endRecording());
    }

private:
    typedef PictureRecordBench INHERITED;
};

/*
 *  Populates the SkPaint dictionary with a number of unique paint
 *  objects that get reused repeatedly.
 *
 *  Re-creating the paint objects in the inner loop slows the benchmark down 10%.
 *  Using setColor(i % objCount) instead of a random color creates a very high rate
 *  of hash conflicts, slowing us down 12%.
 */
class RecurringPaintDictionaryRecordBench : public PictureRecordBench {
public:
    RecurringPaintDictionaryRecordBench() : INHERITED("recurring_paint_dictionary") {
        SkRandom rand;
        for (int i = 0; i < ObjCount; i++) {
            fPaint[i].setColor(rand.nextU());
        }
    }

    enum {
        ObjCount = 100,  // number of unique paint objects
    };
protected:
    virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE {
        SkPictureRecorder recorder;
        SkCanvas* canvas = recorder.beginRecording(PICTURE_WIDTH, PICTURE_HEIGHT, NULL, 0);
        for (int i = 0; i < loops; i++) {
            canvas->drawPaint(fPaint[i % ObjCount]);
        }
    }

private:
    SkPaint fPaint [ObjCount];
    typedef PictureRecordBench INHERITED;
};

///////////////////////////////////////////////////////////////////////////////

DEF_BENCH( return new DictionaryRecordBench(); )
DEF_BENCH( return new UniquePaintDictionaryRecordBench(); )
DEF_BENCH( return new RecurringPaintDictionaryRecordBench(); )
