e25c114f94
Change-Id: I63ce1643364c6d2dd50e3622d66c64bdb3091418 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/550704 Reviewed-by: John Stiles <johnstiles@google.com> Commit-Queue: Herb Derby <herb@google.com>
448 lines
16 KiB
C++
448 lines
16 KiB
C++
/*
|
|
* Copyright 2016 Google Inc.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*/
|
|
|
|
#include "bench/Benchmark.h"
|
|
|
|
#include "include/core/SkBitmap.h"
|
|
#include "include/core/SkData.h"
|
|
#include "include/core/SkExecutor.h"
|
|
#include "include/core/SkImage.h"
|
|
#include "include/core/SkPixmap.h"
|
|
#include "include/core/SkStream.h"
|
|
#include "include/effects/SkGradientShader.h"
|
|
#include "include/private/SkTo.h"
|
|
#include "include/utils/SkRandom.h"
|
|
#include "src/core/SkAutoPixmapStorage.h"
|
|
#include "src/pdf/SkPDFUnion.h"
|
|
#include "src/utils/SkFloatToDecimal.h"
|
|
#include "tools/Resources.h"
|
|
|
|
namespace {
|
|
struct WStreamWriteTextBenchmark : public Benchmark {
|
|
std::unique_ptr<SkWStream> fWStream;
|
|
WStreamWriteTextBenchmark() : fWStream(new SkNullWStream) {}
|
|
const char* onGetName() override { return "WStreamWriteText"; }
|
|
bool isSuitableFor(Backend backend) override {
|
|
return backend == kNonRendering_Backend;
|
|
}
|
|
void onDraw(int loops, SkCanvas*) override {
|
|
while (loops-- > 0) {
|
|
for (int i = 1000; i-- > 0;) {
|
|
fWStream->writeText("HELLO SKIA!\n");
|
|
}
|
|
}
|
|
}
|
|
};
|
|
} // namespace
|
|
|
|
DEF_BENCH(return new WStreamWriteTextBenchmark;)
|
|
|
|
// Test speed of SkFloatToDecimal for typical floats that
|
|
// might be found in a PDF document.
|
|
struct PDFScalarBench : public Benchmark {
|
|
PDFScalarBench(const char* n, float (*f)(SkRandom*)) : fName(n), fNextFloat(f) {}
|
|
const char* fName;
|
|
float (*fNextFloat)(SkRandom*);
|
|
bool isSuitableFor(Backend b) override {
|
|
return b == kNonRendering_Backend;
|
|
}
|
|
const char* onGetName() override { return fName; }
|
|
void onDraw(int loops, SkCanvas*) override {
|
|
SkRandom random;
|
|
char dst[kMaximumSkFloatToDecimalLength];
|
|
while (loops-- > 0) {
|
|
auto f = fNextFloat(&random);
|
|
(void)SkFloatToDecimal(f, dst);
|
|
}
|
|
}
|
|
};
|
|
|
|
float next_common(SkRandom* random) {
|
|
return random->nextRangeF(-500.0f, 1500.0f);
|
|
}
|
|
float next_any(SkRandom* random) {
|
|
union { uint32_t u; float f; };
|
|
u = random->nextU();
|
|
static_assert(sizeof(float) == sizeof(uint32_t), "");
|
|
return f;
|
|
}
|
|
|
|
DEF_BENCH(return new PDFScalarBench("PDFScalar_common", next_common);)
|
|
DEF_BENCH(return new PDFScalarBench("PDFScalar_random", next_any);)
|
|
|
|
#ifdef SK_SUPPORT_PDF
|
|
|
|
#include "src/pdf/SkPDFBitmap.h"
|
|
#include "src/pdf/SkPDFDocumentPriv.h"
|
|
#include "src/pdf/SkPDFShader.h"
|
|
#include "src/pdf/SkPDFUtils.h"
|
|
|
|
namespace {
|
|
class PDFImageBench : public Benchmark {
|
|
public:
|
|
PDFImageBench() {}
|
|
~PDFImageBench() override {}
|
|
|
|
protected:
|
|
const char* onGetName() override { return "PDFImage"; }
|
|
bool isSuitableFor(Backend backend) override {
|
|
return backend == kNonRendering_Backend;
|
|
}
|
|
void onDelayedSetup() override {
|
|
sk_sp<SkImage> img(GetResourceAsImage("images/color_wheel.png"));
|
|
if (img) {
|
|
// force decoding, throw away reference to encoded data.
|
|
SkAutoPixmapStorage pixmap;
|
|
pixmap.alloc(SkImageInfo::MakeN32Premul(img->dimensions()));
|
|
if (img->readPixels(nullptr, pixmap, 0, 0)) {
|
|
fImage = SkImage::MakeRasterCopy(pixmap);
|
|
}
|
|
}
|
|
}
|
|
void onDraw(int loops, SkCanvas*) override {
|
|
if (!fImage) {
|
|
return;
|
|
}
|
|
while (loops-- > 0) {
|
|
SkNullWStream nullStream;
|
|
SkPDFDocument doc(&nullStream, SkPDF::Metadata());
|
|
doc.beginPage(256, 256);
|
|
(void)SkPDFSerializeImage(fImage.get(), &doc);
|
|
}
|
|
}
|
|
|
|
private:
|
|
sk_sp<SkImage> fImage;
|
|
};
|
|
|
|
class PDFJpegImageBench : public Benchmark {
|
|
public:
|
|
PDFJpegImageBench() {}
|
|
~PDFJpegImageBench() override {}
|
|
|
|
protected:
|
|
const char* onGetName() override { return "PDFJpegImage"; }
|
|
bool isSuitableFor(Backend backend) override {
|
|
return backend == kNonRendering_Backend;
|
|
}
|
|
void onDelayedSetup() override {
|
|
sk_sp<SkImage> img(GetResourceAsImage("images/mandrill_512_q075.jpg"));
|
|
if (!img) { return; }
|
|
sk_sp<SkData> encoded = img->refEncodedData();
|
|
SkASSERT(encoded);
|
|
if (!encoded) { return; }
|
|
fImage = img;
|
|
}
|
|
void onDraw(int loops, SkCanvas*) override {
|
|
if (!fImage) {
|
|
SkDEBUGFAIL("");
|
|
return;
|
|
}
|
|
while (loops-- > 0) {
|
|
SkNullWStream nullStream;
|
|
SkPDFDocument doc(&nullStream, SkPDF::Metadata());
|
|
doc.beginPage(256, 256);
|
|
(void)SkPDFSerializeImage(fImage.get(), &doc);
|
|
}
|
|
}
|
|
|
|
private:
|
|
sk_sp<SkImage> fImage;
|
|
};
|
|
|
|
/** Test calling DEFLATE on a 78k PDF command stream. Used for measuring
|
|
alternate zlib settings, usage, and library versions. */
|
|
class PDFCompressionBench : public Benchmark {
|
|
public:
|
|
PDFCompressionBench() {}
|
|
~PDFCompressionBench() override {}
|
|
|
|
protected:
|
|
const char* onGetName() override { return "PDFCompression"; }
|
|
bool isSuitableFor(Backend backend) override {
|
|
return backend == kNonRendering_Backend;
|
|
}
|
|
void onDelayedSetup() override {
|
|
fAsset = GetResourceAsStream("pdf_command_stream.txt");
|
|
}
|
|
void onDraw(int loops, SkCanvas*) override {
|
|
SkASSERT(fAsset);
|
|
if (!fAsset) { return; }
|
|
while (loops-- > 0) {
|
|
SkNullWStream wStream;
|
|
SkPDFDocument doc(&wStream, SkPDF::Metadata());
|
|
doc.beginPage(256, 256);
|
|
(void)SkPDFStreamOut(nullptr, fAsset->duplicate(), &doc, true);
|
|
}
|
|
}
|
|
|
|
private:
|
|
std::unique_ptr<SkStreamAsset> fAsset;
|
|
};
|
|
|
|
struct PDFColorComponentBench : public Benchmark {
|
|
bool isSuitableFor(Backend b) override {
|
|
return b == kNonRendering_Backend;
|
|
}
|
|
const char* onGetName() override { return "PDFColorComponent"; }
|
|
void onDraw(int loops, SkCanvas*) override {
|
|
char dst[5];
|
|
while (loops-- > 0) {
|
|
for (int i = 0; i < 256; ++i) {
|
|
(void)SkPDFUtils::ColorToDecimal(SkToU8(i), dst);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
struct PDFShaderBench : public Benchmark {
|
|
sk_sp<SkShader> fShader;
|
|
const char* onGetName() final { return "PDFShader"; }
|
|
bool isSuitableFor(Backend b) final { return b == kNonRendering_Backend; }
|
|
void onDelayedSetup() final {
|
|
const SkPoint pts[2] = {{0.0f, 0.0f}, {100.0f, 100.0f}};
|
|
const SkColor colors[] = {
|
|
SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE,
|
|
SK_ColorWHITE, SK_ColorBLACK,
|
|
};
|
|
fShader = SkGradientShader::MakeLinear(
|
|
pts, colors, nullptr, std::size(colors),
|
|
SkTileMode::kClamp);
|
|
}
|
|
void onDraw(int loops, SkCanvas*) final {
|
|
SkASSERT(fShader);
|
|
while (loops-- > 0) {
|
|
SkNullWStream nullStream;
|
|
SkPDFDocument doc(&nullStream, SkPDF::Metadata());
|
|
doc.beginPage(256, 256);
|
|
(void) SkPDFMakeShader(&doc, fShader.get(), SkMatrix::I(),
|
|
{0, 0, 400, 400}, SkColors::kBlack);
|
|
}
|
|
}
|
|
};
|
|
|
|
struct WritePDFTextBenchmark : public Benchmark {
|
|
std::unique_ptr<SkWStream> fWStream;
|
|
WritePDFTextBenchmark() : fWStream(new SkNullWStream) {}
|
|
const char* onGetName() override { return "WritePDFText"; }
|
|
bool isSuitableFor(Backend backend) override {
|
|
return backend == kNonRendering_Backend;
|
|
}
|
|
void onDraw(int loops, SkCanvas*) override {
|
|
static const char kHello[] = "HELLO SKIA!\n";
|
|
static const char kBinary[] = "\001\002\003\004\005\006";
|
|
while (loops-- > 0) {
|
|
for (int i = 1000; i-- > 0;) {
|
|
SkPDFWriteTextString(fWStream.get(), kHello, strlen(kHello));
|
|
SkPDFWriteByteString(fWStream.get(), kBinary, strlen(kBinary));
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
// Test for regression chromium:947381
|
|
// with 5c83ae81aa : 2364.99 microsec
|
|
// without 5c83ae81aa : 302821.78 microsec
|
|
struct PDFClipPathBenchmark : public Benchmark {
|
|
SkPath fPath;
|
|
void onDelayedSetup() override {
|
|
SkBitmap bitmap;
|
|
bitmap.allocN32Pixels(256, 256);
|
|
bitmap.eraseColor(SK_ColorWHITE);
|
|
{
|
|
SkCanvas tmp(bitmap);
|
|
SkPaint paint;
|
|
paint.setAntiAlias(false);
|
|
paint.setStyle(SkPaint::kStroke_Style);
|
|
paint.setStrokeWidth(10);
|
|
for (int r : {20, 40, 60, 80, 100, 120}) {
|
|
tmp.drawCircle(128, 128, (float)r, paint);
|
|
}
|
|
}
|
|
fPath.reset();
|
|
for (int y = 0; y < 256; ++y) {
|
|
SkColor current = bitmap.getColor(0, y);
|
|
int start = 0;
|
|
for (int x = 0; x < 256; ++x) {
|
|
SkColor color = bitmap.getColor(x, y);
|
|
if (color == current) {
|
|
continue;
|
|
}
|
|
if (color == SK_ColorBLACK) {
|
|
start = x;
|
|
} else {
|
|
fPath.addRect(SkRect::Make(SkIRect{start, y, x, y + 1}));
|
|
}
|
|
current = color;
|
|
}
|
|
if (current == SK_ColorBLACK) {
|
|
fPath.addRect(SkRect::Make(SkIRect{start, y, 256, y + 1}));
|
|
}
|
|
}
|
|
}
|
|
const char* onGetName() override { return "PDFClipPath"; }
|
|
bool isSuitableFor(Backend backend) override {
|
|
return backend == kNonRendering_Backend;
|
|
}
|
|
void onDraw(int loops, SkCanvas*) override {
|
|
while (loops-- > 0) {
|
|
SkNullWStream wStream;
|
|
SkPDFDocument doc(&wStream, SkPDF::Metadata());
|
|
SkCanvas* canvas = doc.beginPage(256, 256);
|
|
canvas->clipPath(fPath);
|
|
canvas->translate(4.0f/3, 4.0f/3);
|
|
canvas->clipPath(fPath);
|
|
canvas->clear(SK_ColorRED);
|
|
doc.endPage();
|
|
}
|
|
}
|
|
};
|
|
|
|
} // namespace
|
|
DEF_BENCH(return new PDFImageBench;)
|
|
DEF_BENCH(return new PDFJpegImageBench;)
|
|
DEF_BENCH(return new PDFCompressionBench;)
|
|
DEF_BENCH(return new PDFColorComponentBench;)
|
|
DEF_BENCH(return new PDFShaderBench;)
|
|
DEF_BENCH(return new WritePDFTextBenchmark;)
|
|
DEF_BENCH(return new PDFClipPathBenchmark;)
|
|
|
|
#ifdef SK_PDF_ENABLE_SLOW_TESTS
|
|
#include "include/core/SkExecutor.h"
|
|
namespace {
|
|
void big_pdf_test(SkDocument* doc, const SkBitmap& background) {
|
|
static const char* kText[] = {
|
|
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do",
|
|
"eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad",
|
|
"minim veniam, quis nostrud exercitation ullamco laboris nisi ut",
|
|
"aliquip ex ea commodo consequat. Duis aute irure dolor in",
|
|
"reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla",
|
|
"pariatur. Excepteur sint occaecat cupidatat non proident, sunt in",
|
|
"culpa qui officia deserunt mollit anim id est laborum.",
|
|
"",
|
|
"Sed ut perspiciatis, unde omnis iste natus error sit voluptatem",
|
|
"accusantium doloremque laudantium, totam rem aperiam eaque ipsa, quae",
|
|
"ab illo inventore veritatis et quasi architecto beatae vitae dicta",
|
|
"sunt, explicabo. Nemo enim ipsam voluptatem, quia voluptas sit,",
|
|
"aspernatur aut odit aut fugit, sed quia consequuntur magni dolores",
|
|
"eos, qui ratione voluptatem sequi nesciunt, neque porro quisquam est,",
|
|
"qui dolorem ipsum, quia dolor sit amet consectetur adipiscing velit,",
|
|
"sed quia non numquam do eius modi tempora incididunt, ut labore et",
|
|
"dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam,",
|
|
"quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi",
|
|
"ut aliquid ex ea commodi consequatur? Quis autem vel eum iure",
|
|
"reprehenderit, qui in ea voluptate velit esse, quam nihil molestiae",
|
|
"consequatur, vel illum, qui dolorem eum fugiat, quo voluptas nulla",
|
|
"pariatur?",
|
|
"",
|
|
"At vero eos et accusamus et iusto odio dignissimos ducimus, qui",
|
|
"blanditiis praesentium voluptatum deleniti atque corrupti, quos",
|
|
"dolores et quas molestias excepturi sint, obcaecati cupiditate non",
|
|
"provident, similique sunt in culpa, qui officia deserunt mollitia",
|
|
"animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis",
|
|
"est et expedita distinctio. Nam libero tempore, cum soluta nobis est",
|
|
"eligendi optio, cumque nihil impedit, quo minus id, quod maxime",
|
|
"placeat, facere possimus, omnis voluptas assumenda est, omnis dolor",
|
|
"repellendus. Temporibus autem quibusdam et aut officiis debitis aut",
|
|
"rerum necessitatibus saepe eveniet, ut et voluptates repudiandae sint",
|
|
"et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente",
|
|
"delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut",
|
|
"perferendis doloribus asperiores repellat",
|
|
"",
|
|
"Sed ut perspiciatis, unde omnis iste natus error sit voluptatem",
|
|
"accusantium doloremque laudantium, totam rem aperiam eaque ipsa, quae",
|
|
"ab illo inventore veritatis et quasi architecto beatae vitae dicta",
|
|
"sunt, explicabo. Nemo enim ipsam voluptatem, quia voluptas sit,",
|
|
"aspernatur aut odit aut fugit, sed quia consequuntur magni dolores",
|
|
"eos, qui ratione voluptatem sequi nesciunt, neque porro quisquam est,",
|
|
"qui dolorem ipsum, quia dolor sit amet consectetur adipiscing velit,",
|
|
"sed quia non numquam do eius modi tempora incididunt, ut labore et",
|
|
"dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam,",
|
|
"quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi",
|
|
"ut aliquid ex ea commodi consequatur? Quis autem vel eum iure",
|
|
"reprehenderit, qui in ea voluptate velit esse, quam nihil molestiae",
|
|
"consequatur, vel illum, qui dolorem eum fugiat, quo voluptas nulla",
|
|
"pariatur?",
|
|
"",
|
|
};
|
|
SkCanvas* canvas = nullptr;
|
|
float x = 36;
|
|
float y = 36;
|
|
constexpr size_t kLineCount = std::size(kText);
|
|
constexpr int kLoopCount = 200;
|
|
SkFont font;
|
|
SkPaint paint;
|
|
for (int loop = 0; loop < kLoopCount; ++loop) {
|
|
for (size_t line = 0; line < kLineCount; ++line) {
|
|
y += font.getSpacing();
|
|
if (!canvas || y > 792 - 36) {
|
|
y = 36 + font.getSpacing();
|
|
canvas = doc->beginPage(612, 792);
|
|
background.notifyPixelsChanged();
|
|
canvas->drawBitmap(background, 0, 0);
|
|
}
|
|
canvas->drawString(kText[line], x, y, font, paint);
|
|
}
|
|
}
|
|
}
|
|
|
|
SkBitmap make_background() {
|
|
SkBitmap background;
|
|
SkBitmap bitmap;
|
|
bitmap.allocN32Pixels(32, 32);
|
|
bitmap.eraseColor(SK_ColorWHITE);
|
|
SkCanvas tmp(bitmap);
|
|
SkPaint gray;
|
|
gray.setColor(SkColorSetARGB(0xFF, 0xEE, 0xEE, 0xEE));
|
|
tmp.drawRect({0,0,16,16}, gray);
|
|
tmp.drawRect({16,16,32,32}, gray);
|
|
SkPaint shader;
|
|
shader.setShader(
|
|
SkShader::MakeBitmapShader(
|
|
bitmap, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode));
|
|
background.allocN32Pixels(612, 792);
|
|
SkCanvas tmp2(background);
|
|
tmp2.drawPaint(shader);
|
|
return background;
|
|
}
|
|
|
|
struct PDFBigDocBench : public Benchmark {
|
|
bool fFast;
|
|
SkBitmap fBackground;
|
|
std::unique_ptr<SkExecutor> fExecutor;
|
|
PDFBigDocBench(bool fast) : fFast(fast) {}
|
|
void onDelayedSetup() override {
|
|
fBackground = make_background();
|
|
fExecutor = fFast ? SkExecutor::MakeFIFOThreadPool() : nullptr;
|
|
}
|
|
const char* onGetName() override {
|
|
static const char kNameFast[] = "PDFBigDocBench_fast";
|
|
static const char kNameSlow[] = "PDFBigDocBench_slow";
|
|
return fFast ? kNameFast : kNameSlow;
|
|
}
|
|
bool isSuitableFor(Backend backend) override { return backend == kNonRendering_Backend; }
|
|
void onDraw(int loops, SkCanvas*) override {
|
|
while (loops-- > 0) {
|
|
#ifdef SK_PDF_TEST_BIGDOCBENCH_OUTPUT
|
|
SkFILEWStream wStream("/tmp/big_pdf.pdf");
|
|
#else
|
|
SkNullWStream wStream;
|
|
#endif
|
|
SkPDF::Metadata metadata;
|
|
metadata.fExecutor = fExecutor.get();
|
|
auto doc = SkPDF::MakeDocument(&wStream, metadata);
|
|
big_pdf_test(doc.get(), fBackground);
|
|
}
|
|
}
|
|
};
|
|
} // namespace
|
|
DEF_BENCH(return new PDFBigDocBench(false);)
|
|
DEF_BENCH(return new PDFBigDocBench(true);)
|
|
#endif
|
|
|
|
#endif // SK_SUPPORT_PDF
|