<commit_before>/*
 * Copyright 2015 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 "SkImage.h"
#include "SkSurface.h"

class Image2RasterBench : public Benchmark {
public:
    Image2RasterBench() {
        fName.set("native_image_to_raster_surface");
    }

    bool isSuitableFor(Backend backend) override {
        return kGPU_Backend == backend || kRaster_Backend == backend;
    }

protected:
    const char* onGetName() override {
        return fName.c_str();
    }

    // We explicitly want to bench drawing a Image [cpu or gpu backed] into a raster target,
    // to ensure that we can cache the read-back in the case of gpu -> raster
    //
    void onPerCanvasPreDraw(SkCanvas* canvas) override {
        // create an Image reflecting the canvas (gpu or cpu)
        SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100);
        SkAutoTUnref<SkSurface> surface(canvas->newSurface(info));
        canvas->drawColor(SK_ColorRED);
        fImage.reset(surface->newImageSnapshot());

        // create a cpu-backed Surface
        fRasterSurface.reset(SkSurface::NewRaster(info));
    }

    void onPerCanvasPostDraw(SkCanvas*) override {
        // Release the image and raster surface here to prevent out of order destruction
        // between these and the gpu interface.
        fRasterSurface.reset(nullptr);
        fImage.reset(nullptr);
    }

    void onDraw(int loops, SkCanvas*) override {
        for (int i = 0; i < loops; i++) {
            for (int inner = 0; inner < 10; ++inner) {
                fRasterSurface->getCanvas()->drawImage(fImage, 0, 0);
            }
        }
    }

private:
    SkString                fName;
    SkAutoTUnref<SkImage>   fImage;
    SkAutoTUnref<SkSurface> fRasterSurface;

    typedef Benchmark INHERITED;
};


DEF_BENCH( return new Image2RasterBench; )<commit_msg>add bench for sprite-like drawing w/ imagefilters<commit_after>/*
 * Copyright 2015 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 "SkImage.h"
#include "SkSurface.h"

class Image2RasterBench : public Benchmark {
public:
    Image2RasterBench() {
        fName.set("native_image_to_raster_surface");
    }

    bool isSuitableFor(Backend backend) override {
        return kGPU_Backend == backend || kRaster_Backend == backend;
    }

protected:
    const char* onGetName() override {
        return fName.c_str();
    }

    // We explicitly want to bench drawing a Image [cpu or gpu backed] into a raster target,
    // to ensure that we can cache the read-back in the case of gpu -> raster
    //
    void onPerCanvasPreDraw(SkCanvas* canvas) override {
        // create an Image reflecting the canvas (gpu or cpu)
        SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100);
        SkAutoTUnref<SkSurface> surface(canvas->newSurface(info));
        canvas->drawColor(SK_ColorRED);
        fImage.reset(surface->newImageSnapshot());

        // create a cpu-backed Surface
        fRasterSurface.reset(SkSurface::NewRaster(info));
    }

    void onPerCanvasPostDraw(SkCanvas*) override {
        // Release the image and raster surface here to prevent out of order destruction
        // between these and the gpu interface.
        fRasterSurface.reset(nullptr);
        fImage.reset(nullptr);
    }

    void onDraw(int loops, SkCanvas*) override {
        for (int i = 0; i < loops; i++) {
            for (int inner = 0; inner < 10; ++inner) {
                fRasterSurface->getCanvas()->drawImage(fImage, 0, 0);
            }
        }
    }

private:
    SkString                fName;
    SkAutoTUnref<SkImage>   fImage;
    SkAutoTUnref<SkSurface> fRasterSurface;

    typedef Benchmark INHERITED;
};
DEF_BENCH( return new Image2RasterBench; )

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

#include "SkOffsetImageFilter.h"

#if SK_SUPPORT_GPU
#include "SkGrPixelRef.h"
#endif

enum MyDrawType {
    kSprite_Type,
    kBitmap_Type,
    kImage_Type,
};

/*
 *  Want to time drawing images/bitmaps via drawSprite, and via drawBitmap/drawImage but with
 *  a non-scaling matrix and a clip that is tight to the image bounds. In this scenario, we
 *  should be able to match the speed of drawSprite.
 *
 *  An optimal result should be that all three types: sprite/bitmap/image draw at the same speed.
 */
class ImageFilterSpriteBench : public Benchmark {
    SkAutoTUnref<SkImage>       fImage;
    SkBitmap                    fBitmap;
    SkString                    fName;
    MyDrawType                  fType;

public:
    ImageFilterSpriteBench(MyDrawType dt, const char suffix[]) : fType(dt) {
        fName.printf("image-filter-sprite-draw-%s", suffix);
    }

    bool isSuitableFor(Backend backend) override {
        return kGPU_Backend == backend || kRaster_Backend == backend;
    }

protected:
    bool isVisual() override {
        return true;
    }

    const char* onGetName() override {
        return fName.c_str();
    }

    void onPerCanvasPreDraw(SkCanvas* canvas) override {
        const SkImageInfo info = SkImageInfo::MakeN32Premul(500, 500);
        SkAutoTUnref<SkSurface> surface(canvas->newSurface(info));

        surface->getCanvas()->drawColor(SK_ColorRED);
        fImage.reset(surface->newImageSnapshot());

        fBitmap.setInfo(info);
        if (fImage->getTexture()) {
#if SK_SUPPORT_GPU
            fBitmap.setPixelRef(new SkGrPixelRef(info, fImage->getTexture()))->unref();
#endif
        } else {
            SkPixmap pmap;
            if (!fImage->peekPixels(&pmap)) {
                sk_throw();
            }
            fBitmap.installPixels(pmap.info(), pmap.writable_addr(), pmap.rowBytes());
        }
    }

    void onPerCanvasPostDraw(SkCanvas*) override {
        // Release the image and raster surface here to prevent out of order destruction
        // between these and the gpu interface.
        fImage.reset(nullptr);
        fBitmap.reset();
    }

    void onDraw(int loops, SkCanvas* canvas) override {
        // This clip is important; it allows the drawImage/drawBitmap code to fall into the
        // fast (sprite) case, since the imagefilter's output should match.
        //
        // When we address skbug.com/4526 we should be able to remove the need for this clip.
        //
        canvas->clipRect(SkRect::MakeIWH(fImage->width(), fImage->height()));

        const SkScalar kDelta = 10;
        SkPaint paint;
        for (int i = 0; i < loops; i++) {
            for (int inner = 0; inner < 10; ++inner) {
                // build the filter everytime, so we don't accidentally draw a cached version,
                // since the point of this bench is to time the actual imagefilter
                // handling/overhead.
                SkAutoTUnref<SkImageFilter> filter(SkOffsetImageFilter::Create(kDelta, kDelta));
                paint.setImageFilter(filter);

                switch (fType) {
                    case kSprite_Type:
                        canvas->drawSprite(fBitmap, 0, 0, &paint);
                        break;
                    case kBitmap_Type:
                        canvas->drawBitmap(fBitmap, 0, 0, &paint);
                        break;
                    case kImage_Type:
                        canvas->drawImage(fImage, 0, 0, &paint);
                        break;
                }
            }
        }
    }

private:
    typedef Benchmark INHERITED;
};
DEF_BENCH( return new ImageFilterSpriteBench(kSprite_Type, "sprite"); )
DEF_BENCH( return new ImageFilterSpriteBench(kBitmap_Type, "bitmap"); )
DEF_BENCH( return new ImageFilterSpriteBench(kImage_Type,  "image"); )

{'fraction_non_alphanumeric': 0.10886172650878534, 'fraction_numerical': 0.008403361344537815, 'mean_word_length': 2.2838628762541804, 'pattern_counts': {'":': 0, '<': 18, '<?xml version=': 0, '>': 38, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '767980', 'n_tokens_mistral': 2359, 'n_tokens_neox': 2255, 'n_words': 646}