From 6c924ad46c89955e78e071c792ef00df9910b42f Mon Sep 17 00:00:00 2001 From: "reed@android.com" Date: Tue, 31 Mar 2009 03:48:49 +0000 Subject: [PATCH] add -pict option to bench, which draws everything through a picture, and then compares the result to the original draws git-svn-id: http://skia.googlecode.com/svn/trunk@139 2bbb7eff-a529-9590-31e7-b0007b416f81 --- Makefile | 2 + bench/main.cpp | 72 ++++++++- include/effects/SkNWayCanvas.h | 79 ++++++++++ src/effects/SkNWayCanvas.cpp | 279 +++++++++++++++++++++++++++++++++ 4 files changed, 424 insertions(+), 8 deletions(-) create mode 100644 include/effects/SkNWayCanvas.h create mode 100644 src/effects/SkNWayCanvas.cpp diff --git a/Makefile b/Makefile index dc55591592..fe37323623 100644 --- a/Makefile +++ b/Makefile @@ -74,6 +74,8 @@ out/libskia.a: Makefile $(OBJ_LIST) BENCH_SRCS := RectBench.cpp SkBenchmark.cpp main.cpp BitmapBench.cpp BENCH_SRCS := $(addprefix bench/, $(BENCH_SRCS)) +BENCH_SRCS += src/effects/SkNWayCanvas.cpp + # add any optional codecs for this app ifeq ($(SKIA_BUILD_FOR),mac) # BENCH_SRCS += bench/TextBench.cpp diff --git a/bench/main.cpp b/bench/main.cpp index 77f49dcec8..f92277a14b 100644 --- a/bench/main.cpp +++ b/bench/main.cpp @@ -2,11 +2,38 @@ #include "SkColorPriv.h" #include "SkGraphics.h" #include "SkImageEncoder.h" +#include "SkNWayCanvas.h" +#include "SkPicture.h" #include "SkString.h" #include "SkTime.h" #include "SkBenchmark.h" +static void erase(SkBitmap& bm) { + if (bm.config() == SkBitmap::kA8_Config) { + bm.eraseColor(0); + } else { + bm.eraseColor(SK_ColorWHITE); + } +} + +static bool equal(const SkBitmap& bm1, const SkBitmap& bm2) { + if (bm1.width() != bm2.width() || + bm1.height() != bm2.height() || + bm1.config() != bm2.config()) { + return false; + } + + size_t pixelBytes = bm1.width() * bm1.bytesPerPixel(); + for (int y = 0; y < bm1.height(); y++) { + if (memcmp(bm1.getAddr(0, y), bm2.getAddr(0, y), pixelBytes)) { + return false; + } + } + + return true; +} + class Iter { public: Iter() { @@ -91,6 +118,21 @@ static void performRotate(SkCanvas* canvas, int w, int h) { canvas->translate(-x, -y); } +static void compare_pict_to_bitmap(SkPicture* pict, const SkBitmap& bm) { + SkBitmap bm2; + + bm2.setConfig(bm.config(), bm.width(), bm.height()); + bm2.allocPixels(); + erase(bm2); + + SkCanvas canvas(bm2); + canvas.drawPicture(*pict); + + if (!equal(bm, bm2)) { + SkDebugf("----- compare_pict_to_bitmap failed\n"); + } +} + static const struct { SkBitmap::Config fConfig; const char* fName; @@ -128,6 +170,7 @@ int main (int argc, char * const argv[]) { bool forceAA = true; bool doRotate = false; bool doClip = false; + bool doPict = false; SkString outDir; SkBitmap::Config outConfig = SkBitmap::kARGB_8888_Config; @@ -142,6 +185,8 @@ int main (int argc, char * const argv[]) { outDir.append("/"); } } + } else if (strcmp(*argv, "-pict") == 0) { + doPict = true; } else if (strcmp(*argv, "-repeat") == 0) { argv++; if (argv < stop) { @@ -198,12 +243,7 @@ int main (int argc, char * const argv[]) { SkBitmap bm; bm.setConfig(outConfig, dim.fX, dim.fY); bm.allocPixels(); - - if (bm.config() == SkBitmap::kA8_Config) { - bm.eraseColor(0); - } else { - bm.eraseColor(SK_ColorWHITE); - } + erase(bm); SkCanvas canvas(bm); @@ -216,8 +256,24 @@ int main (int argc, char * const argv[]) { SkMSec now = SkTime::GetMSecs(); for (int i = 0; i < repeatDraw; i++) { - SkAutoCanvasRestore acr(&canvas, true); - bench->draw(&canvas); + SkCanvas* c = &canvas; + + SkNWayCanvas nway; + SkPicture* pict = NULL; + if (doPict) { + pict = new SkPicture; + nway.addCanvas(pict->beginRecording(bm.width(), bm.height())); + nway.addCanvas(&canvas); + c = &nway; + } + + SkAutoCanvasRestore acr(c, true); + bench->draw(c); + + if (pict) { + compare_pict_to_bitmap(pict, bm); + pict->unref(); + } } if (repeatDraw > 1) { printf(" %4s:%7.2f", configName, diff --git a/include/effects/SkNWayCanvas.h b/include/effects/SkNWayCanvas.h new file mode 100644 index 0000000000..2394037157 --- /dev/null +++ b/include/effects/SkNWayCanvas.h @@ -0,0 +1,79 @@ + +#ifndef SkNWayCanvas_DEFINED +#define SkNWayCanvas_DEFINED + +#include "SkCanvas.h" + +class SkNWayCanvas : public SkCanvas { +public: + SkNWayCanvas(); + virtual ~SkNWayCanvas(); + + void addCanvas(SkCanvas*); + void removeCanvas(SkCanvas*); + void removeAll(); + + /////////////////////////////////////////////////////////////////////////// + // These are forwarded to the N canvases we're referencing + + virtual int save(SaveFlags flags = kMatrixClip_SaveFlag); + virtual int saveLayer(const SkRect* bounds, const SkPaint* paint, + SaveFlags flags = kARGB_ClipLayer_SaveFlag); + virtual void restore(); + virtual bool translate(SkScalar dx, SkScalar dy); + virtual bool scale(SkScalar sx, SkScalar sy); + virtual bool rotate(SkScalar degrees); + virtual bool skew(SkScalar sx, SkScalar sy); + virtual bool concat(const SkMatrix& matrix); + virtual void setMatrix(const SkMatrix& matrix); + virtual bool clipRect(const SkRect& rect, + SkRegion::Op op = SkRegion::kIntersect_Op); + virtual bool clipPath(const SkPath& path, + SkRegion::Op op = SkRegion::kIntersect_Op); + virtual bool clipRegion(const SkRegion& deviceRgn, + SkRegion::Op op = SkRegion::kIntersect_Op); + + virtual void drawPaint(const SkPaint& paint); + virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[], + const SkPaint& paint); + virtual void drawRect(const SkRect& rect, const SkPaint& paint); + virtual void drawPath(const SkPath& path, const SkPaint& paint); + virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top, + const SkPaint* paint = NULL); + virtual void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src, + const SkRect& dst, const SkPaint* paint = NULL); + virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m, + const SkPaint* paint = NULL); + virtual void drawSprite(const SkBitmap& bitmap, int left, int top, + const SkPaint* paint = NULL); + virtual void drawText(const void* text, size_t byteLength, SkScalar x, + SkScalar y, const SkPaint& paint); + virtual void drawPosText(const void* text, size_t byteLength, + const SkPoint pos[], const SkPaint& paint); + virtual void drawPosTextH(const void* text, size_t byteLength, + const SkScalar xpos[], SkScalar constY, + const SkPaint& paint); + virtual void drawTextOnPath(const void* text, size_t byteLength, + const SkPath& path, const SkMatrix* matrix, + const SkPaint& paint); + virtual void drawPicture(SkPicture& picture); + virtual void drawVertices(VertexMode vmode, int vertexCount, + const SkPoint vertices[], const SkPoint texs[], + const SkColor colors[], SkXfermode* xmode, + const uint16_t indices[], int indexCount, + const SkPaint& paint); + + virtual SkBounder* setBounder(SkBounder* bounder); + virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter); + +private: + SkTDArray fList; + + class Iter; + + typedef SkCanvas INHERITED; +}; + + +#endif + diff --git a/src/effects/SkNWayCanvas.cpp b/src/effects/SkNWayCanvas.cpp new file mode 100644 index 0000000000..d60f259f67 --- /dev/null +++ b/src/effects/SkNWayCanvas.cpp @@ -0,0 +1,279 @@ +#include "SkNWayCanvas.h" + +SkNWayCanvas::SkNWayCanvas() {} + +SkNWayCanvas::~SkNWayCanvas() { + this->removeAll(); +} + +void SkNWayCanvas::addCanvas(SkCanvas* canvas) { + if (canvas) { + canvas->ref(); + *fList.append() = canvas; + } +} + +void SkNWayCanvas::removeCanvas(SkCanvas* canvas) { + int index = fList.find(canvas); + if (index >= 0) { + canvas->unref(); + fList.removeShuffle(index); + } +} + +void SkNWayCanvas::removeAll() { + fList.unrefAll(); + fList.reset(); +} + +/////////////////////////////////////////////////////////////////////////// +// These are forwarded to the N canvases we're referencing + +class SkNWayCanvas::Iter { +public: + Iter(const SkTDArray& list) : fList(list) { + fIndex = 0; + } + bool next() { + if (fIndex < fList.count()) { + fCanvas = fList[fIndex++]; + return true; + } + return false; + } + SkCanvas* operator->() { return fCanvas; } + +private: + const SkTDArray& fList; + int fIndex; + SkCanvas* fCanvas; +}; + +int SkNWayCanvas::save(SaveFlags flags) { + Iter iter(fList); + while (iter.next()) { + iter->save(flags); + } + return this->INHERITED::save(flags); +} + +int SkNWayCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint, + SaveFlags flags) { + Iter iter(fList); + while (iter.next()) { + iter->saveLayer(bounds, paint, flags); + } + return this->INHERITED::saveLayer(bounds, paint, flags); +} + +void SkNWayCanvas::restore() { + Iter iter(fList); + while (iter.next()) { + iter->restore(); + } + this->INHERITED::restore(); +} + +bool SkNWayCanvas::translate(SkScalar dx, SkScalar dy) { + Iter iter(fList); + while (iter.next()) { + iter->translate(dx, dy); + } + return this->INHERITED::translate(dx, dy); +} + +bool SkNWayCanvas::scale(SkScalar sx, SkScalar sy) { + Iter iter(fList); + while (iter.next()) { + iter->scale(sx, sy); + } + return this->INHERITED::scale(sx, sy); +} + +bool SkNWayCanvas::rotate(SkScalar degrees) { + Iter iter(fList); + while (iter.next()) { + iter->rotate(degrees); + } + return this->INHERITED::rotate(degrees); +} + +bool SkNWayCanvas::skew(SkScalar sx, SkScalar sy) { + Iter iter(fList); + while (iter.next()) { + iter->skew(sx, sy); + } + return this->INHERITED::skew(sx, sy); +} + +bool SkNWayCanvas::concat(const SkMatrix& matrix) { + Iter iter(fList); + while (iter.next()) { + iter->concat(matrix); + } + return this->INHERITED::concat(matrix); +} + +void SkNWayCanvas::setMatrix(const SkMatrix& matrix) { + Iter iter(fList); + while (iter.next()) { + iter->setMatrix(matrix); + } + this->INHERITED::setMatrix(matrix); +} + +bool SkNWayCanvas::clipRect(const SkRect& rect, SkRegion::Op op) { + Iter iter(fList); + while (iter.next()) { + iter->clipRect(rect, op); + } + return this->INHERITED::clipRect(rect, op); +} + +bool SkNWayCanvas::clipPath(const SkPath& path, SkRegion::Op op) { + Iter iter(fList); + while (iter.next()) { + iter->clipPath(path, op); + } + return this->INHERITED::clipPath(path, op); +} + +bool SkNWayCanvas::clipRegion(const SkRegion& deviceRgn, SkRegion::Op op) { + Iter iter(fList); + while (iter.next()) { + iter->clipRegion(deviceRgn, op); + } + return this->INHERITED::clipRegion(deviceRgn, op); +} + +void SkNWayCanvas::drawPaint(const SkPaint& paint) { + Iter iter(fList); + while (iter.next()) { + iter->drawPaint(paint); + } +} + +void SkNWayCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], + const SkPaint& paint) { + Iter iter(fList); + while (iter.next()) { + iter->drawPoints(mode, count, pts, paint); + } +} + +void SkNWayCanvas::drawRect(const SkRect& rect, const SkPaint& paint) { + Iter iter(fList); + while (iter.next()) { + iter->drawRect(rect, paint); + } +} + +void SkNWayCanvas::drawPath(const SkPath& path, const SkPaint& paint) { + Iter iter(fList); + while (iter.next()) { + iter->drawPath(path, paint); + } +} + +void SkNWayCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, + const SkPaint* paint) { + Iter iter(fList); + while (iter.next()) { + iter->drawBitmap(bitmap, x, y, paint); + } +} + +void SkNWayCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src, + const SkRect& dst, const SkPaint* paint) { + Iter iter(fList); + while (iter.next()) { + iter->drawBitmapRect(bitmap, src, dst, paint); + } +} + +void SkNWayCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m, + const SkPaint* paint) { + Iter iter(fList); + while (iter.next()) { + iter->drawBitmapMatrix(bitmap, m, paint); + } +} + +void SkNWayCanvas::drawSprite(const SkBitmap& bitmap, int x, int y, + const SkPaint* paint) { + Iter iter(fList); + while (iter.next()) { + iter->drawSprite(bitmap, x, y, paint); + } +} + +void SkNWayCanvas::drawText(const void* text, size_t byteLength, SkScalar x, + SkScalar y, const SkPaint& paint) { + Iter iter(fList); + while (iter.next()) { + iter->drawText(text, byteLength, x, y, paint); + } +} + +void SkNWayCanvas::drawPosText(const void* text, size_t byteLength, + const SkPoint pos[], const SkPaint& paint) { + Iter iter(fList); + while (iter.next()) { + iter->drawPosText(text, byteLength, pos, paint); + } +} + +void SkNWayCanvas::drawPosTextH(const void* text, size_t byteLength, + const SkScalar xpos[], SkScalar constY, + const SkPaint& paint) { + Iter iter(fList); + while (iter.next()) { + iter->drawPosTextH(text, byteLength, xpos, constY, paint); + } +} + +void SkNWayCanvas::drawTextOnPath(const void* text, size_t byteLength, + const SkPath& path, const SkMatrix* matrix, + const SkPaint& paint) { + Iter iter(fList); + while (iter.next()) { + iter->drawTextOnPath(text, byteLength, path, matrix, paint); + } +} + +void SkNWayCanvas::drawPicture(SkPicture& picture) { + Iter iter(fList); + while (iter.next()) { + iter->drawPicture(picture); + } +} + +void SkNWayCanvas::drawVertices(VertexMode vmode, int vertexCount, + const SkPoint vertices[], const SkPoint texs[], + const SkColor colors[], SkXfermode* xmode, + const uint16_t indices[], int indexCount, + const SkPaint& paint) { + Iter iter(fList); + while (iter.next()) { + iter->drawVertices(vmode, vertexCount, vertices, texs, colors, xmode, + indices, indexCount, paint); + } +} + +SkBounder* SkNWayCanvas::setBounder(SkBounder* bounder) { + Iter iter(fList); + while (iter.next()) { + iter->setBounder(bounder); + } + return this->INHERITED::setBounder(bounder); +} + +SkDrawFilter* SkNWayCanvas::setDrawFilter(SkDrawFilter* filter) { + Iter iter(fList); + while (iter.next()) { + iter->setDrawFilter(filter); + } + return this->INHERITED::setDrawFilter(filter); +} + +