add -pict option to bench, which draws everything through a picture, and then
authorreed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Tue, 31 Mar 2009 03:48:49 +0000 (03:48 +0000)
committerreed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Tue, 31 Mar 2009 03:48:49 +0000 (03:48 +0000)
compares the result to the original draws

git-svn-id: http://skia.googlecode.com/svn/trunk@139 2bbb7eff-a529-9590-31e7-b0007b416f81

Makefile
bench/main.cpp
include/effects/SkNWayCanvas.h [new file with mode: 0644]
src/effects/SkNWayCanvas.cpp [new file with mode: 0644]

index dc55591..fe37323 100644 (file)
--- 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
index 77f49dc..f92277a 100644 (file)
@@ -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 (file)
index 0000000..2394037
--- /dev/null
@@ -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<SkCanvas*> fList;
+    
+    class Iter;
+
+    typedef SkCanvas INHERITED;
+};
+
+
+#endif
+
diff --git a/src/effects/SkNWayCanvas.cpp b/src/effects/SkNWayCanvas.cpp
new file mode 100644 (file)
index 0000000..d60f259
--- /dev/null
@@ -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<SkCanvas*>& 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<SkCanvas*>& 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);
+}
+
+