add peekPixels to SkCanvas and SkSurface

fix reference to SkBaseDevice, which was only a problem in no-gpu build

This reverts commit 4fa44a6bf73891b21917fb90d02beef9143bffa3.

R=reed@google.com

Author: reed@chromium.org

Review URL: https://codereview.chromium.org/163603003

git-svn-id: http://skia.googlecode.com/svn/trunk@13432 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gm/aaclip.cpp b/gm/aaclip.cpp
index ec29a4f..5742902 100644
--- a/gm/aaclip.cpp
+++ b/gm/aaclip.cpp
@@ -9,203 +9,11 @@
 #include "SkCanvas.h"
 #include "SkPath.h"
 
-static void test_quadstroke(SkCanvas* canvas) {
-    SkPath path;
-    path.moveTo(6, 0);
-    path.quadTo(150, 150, 0, 6);
-
-    SkPaint paint;
-
-    paint.setAntiAlias(true);
-    paint.setStyle(SkPaint::kStroke_Style);
-    canvas->translate(20, 20);
-
-#if 1
-    canvas->drawPath(path, paint);
-    canvas->translate(100, 0);
-#endif
-
-    paint.setStrokeWidth(1.01f);
-    canvas->drawPath(path, paint);
-}
-
-static void draw_conic(SkCanvas* canvas, SkScalar weight, const SkPaint& paint) {
-    SkPath path;
-    path.moveTo(100, 100);
-    path.conicTo(300, 100, 300, 300, weight);
-    canvas->drawPath(path, paint);
-}
-
-static void test_conic(SkCanvas* canvas) {
-    SkPaint paint;
-    paint.setAntiAlias(true);
-    paint.setStyle(SkPaint::kStroke_Style);
-
-    static const struct {
-        SkScalar fWeight;
-        SkColor  fColor;
-    } gRec[] = {
-        { 2   , SK_ColorRED },
-        { 1   , SK_ColorGREEN },
-        { 0.5f, SK_ColorBLUE },
-    };
-
-    for (SkScalar width = 0; width <= 20; width += 20) {
-        canvas->save();
-        paint.setStrokeWidth(width);
-        for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) {
-            paint.setColor(gRec[i].fColor);
-            draw_conic(canvas, gRec[i].fWeight, paint);
-            canvas->translate(-30, 30);
-        }
-        canvas->restore();
-        canvas->translate(300, 0);
-    }
-}
-
-#include "SkGradientShader.h"
-static void test_shallow_gradient(SkCanvas* canvas, SkScalar width, SkScalar height) {
-    SkColor colors[] = { 0xFF7F7F7F, 0xFF7F7F7F, 0xFF000000 };
-    SkScalar pos[] = { 0, 0.35f, SK_Scalar1 };
-    SkPoint pts[] = { { 0, 0 }, { width, height } };
-    SkShader* s = SkGradientShader::CreateLinear(pts, colors, pos,
-                                                 SK_ARRAY_COUNT(colors),
-                                                 SkShader::kClamp_TileMode);
-    SkPaint paint;
-    paint.setShader(s)->unref();
-    canvas->drawPaint(paint);
-}
-
-#include "SkDashPathEffect.h"
-static void test_giant_dash(SkCanvas* canvas) {
-    SkPaint paint;
-    const SkScalar intervals[] = { SK_Scalar1, SK_Scalar1 };
-
-    paint.setStrokeWidth(2);
-    paint.setPathEffect(new SkDashPathEffect(intervals, 2, 0))->unref();
-
-    SkScalar big = 500 * 1000;
-
-    canvas->drawLine(10, 10, big, 10, paint);
-    canvas->drawLine(-big, 20, 500, 20, paint);
-    canvas->drawLine(-big, 30, big, 30, paint);
-
-    const SkScalar intervals2[] = { 20, 5, 10, 5 };
-    paint.setPathEffect(new SkDashPathEffect(intervals2, 4, 17))->unref();
-
-    canvas->translate(0, 40);
-    SkScalar x = -500;
-    SkScalar width = 3173;
-    for (int i = 0; i < 40; ++i) {
-        if (i > 10)
-        canvas->drawLine(x, 0, x + width, 0, paint);
-        x += 1;
-        canvas->translate(0, 4);
-    }
-}
-
-
-
-// Reproduces bug found here: http://jsfiddle.net/R8Cu5/1/
-//
-#include "SkGradientShader.h"
-static void test_grad(SkCanvas* canvas) {
-    SkPoint pts[] = {
-        { 478.544067f, -84.2041016f },
-        { 602.455933f, 625.204102f },
-    };
-    SkColor colors[] = { SK_ColorBLACK, SK_ColorBLACK, SK_ColorRED, SK_ColorRED };
-    SkScalar pos[] = { 0, 0.3f, 0.3f, 1.0f };
-    SkShader* s = SkGradientShader::CreateLinear(pts, colors, pos, 4, SkShader::kClamp_TileMode);
-    SkPaint p;
-    p.setShader(s)->unref();
-    canvas->drawPaint(p);
-}
-
-static SkCanvas* MakeCanvas(const SkIRect& bounds) {
-    SkBitmap bm;
-    bm.allocN32Pixels(bounds.width(), bounds.height());
-    bm.eraseColor(SK_ColorTRANSPARENT);
-
-    SkCanvas* canvas = new SkCanvas(bm);
-    canvas->translate(-SkIntToScalar(bounds.fLeft), -SkIntToScalar(bounds.fTop));
-    return canvas;
-}
-
-#ifdef SK_DEBUG
-static void GetBitmap(const SkCanvas* canvas, SkBitmap* bm) {
-    *bm = canvas->getDevice()->accessBitmap(false);
-}
-#endif
-
-static void compare_canvas(const SkCanvas* a, const SkCanvas* b) {
-#ifdef SK_DEBUG
-    SkBitmap bma, bmb;
-    GetBitmap(a, &bma);
-    GetBitmap(b, &bmb);
-
-    SkASSERT(bma.width() == bmb.width());
-    SkASSERT(bma.height() == bmb.height());
-
-    bma.lockPixels();
-    bmb.lockPixels();
-    for (int y = 0; y < bma.height(); ++y) {
-        const SkPMColor* rowa = bma.getAddr32(0, y);
-        const SkPMColor* rowb = bmb.getAddr32(0, y);
-        SkASSERT(!memcmp(rowa, rowb, bma.width() << 2));
-
-        for (int x = 1; x < bma.width() - 1; ++x) {
-            SkASSERT(0xFF000000 == rowa[x]);
-            SkASSERT(0xFF000000 == rowb[x]);
-        }
-    }
-#endif
-}
-
-static void drawRectAsPath(SkCanvas* canvas, const SkRect& r, const SkPaint& p) {
-    SkPath path;
-    path.addRect(r);
-    canvas->drawPath(path, p);
-}
-
-static void test_maskFromPath(const SkPath& path) {
-    SkIRect bounds;
-    path.getBounds().roundOut(&bounds);
-
-    SkPaint paint;
-    paint.setAntiAlias(true);
-
-    SkAutoTUnref<SkCanvas> path_canvas(MakeCanvas(bounds));
-    path_canvas->drawPath(path, paint);
-
-    SkAutoTUnref<SkCanvas> rect_canvas(MakeCanvas(bounds));
-    drawRectAsPath(rect_canvas, path.getBounds(), paint);
-
-    compare_canvas(path_canvas, rect_canvas);
-}
-
-static void test_mask() {
-    for (int i = 1; i <= 20; ++i) {
-        const SkScalar dx = SK_Scalar1 / i;
-        const SkRect constr = SkRect::MakeWH(dx, SkIntToScalar(2));
-        for (int n = 2; n < 20; ++n) {
-            SkPath path;
-            path.setFillType(SkPath::kEvenOdd_FillType);
-            SkRect r = constr;
-            while (r.fRight < SkIntToScalar(4)) {
-                path.addRect(r);
-                r.offset(dx, 0);
-            }
-            test_maskFromPath(path);
-        }
-    }
-}
-
 /** Draw a 2px border around the target, then red behind the target;
     set the clip to match the target, then draw >> the target in blue.
 */
 
-static void draw (SkCanvas* canvas, SkRect& target, int x, int y) {
+static void draw(SkCanvas* canvas, SkRect& target, int x, int y) {
     SkPaint borderPaint;
     borderPaint.setColor(SkColorSetRGB(0x0, 0xDD, 0x0));
     borderPaint.setAntiAlias(true);
@@ -228,22 +36,22 @@
     canvas->restore();
 }
 
-static void draw_square (SkCanvas* canvas, int x, int y) {
+static void draw_square(SkCanvas* canvas, int x, int y) {
     SkRect target (SkRect::MakeWH(10 * SK_Scalar1, 10 * SK_Scalar1));
     draw(canvas, target, x, y);
 }
 
-static void draw_column (SkCanvas* canvas, int x, int y) {
+static void draw_column(SkCanvas* canvas, int x, int y) {
     SkRect target (SkRect::MakeWH(1 * SK_Scalar1, 10 * SK_Scalar1));
     draw(canvas, target, x, y);
 }
 
-static void draw_bar (SkCanvas* canvas, int x, int y) {
+static void draw_bar(SkCanvas* canvas, int x, int y) {
     SkRect target (SkRect::MakeWH(10 * SK_Scalar1, 1 * SK_Scalar1));
     draw(canvas, target, x, y);
 }
 
-static void draw_rect_tests (SkCanvas* canvas) {
+static void draw_rect_tests(SkCanvas* canvas) {
     draw_square(canvas, 10, 10);
     draw_column(canvas, 30, 10);
     draw_bar(canvas, 10, 30);
@@ -272,23 +80,6 @@
     }
 
     virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
-        if (false) { test_quadstroke(canvas); return; }
-        if (false) { test_conic(canvas); return; }
-        if (false) {
-            SkRect bounds;
-            canvas->getClipBounds(&bounds);
-            test_shallow_gradient(canvas, bounds.width(), bounds.height()); return;
-        }
-        if (false) {
-            test_giant_dash(canvas); return;
-        }
-        if (false) {
-            test_grad(canvas); return;
-        }
-        if (false) { // avoid bit rot, suppress warning
-            test_mask();
-        }
-
         // Initial pixel-boundary-aligned draw
         draw_rect_tests(canvas);
 
diff --git a/gm/bitmapcopy.cpp b/gm/bitmapcopy.cpp
index 928b403..f210b4a 100644
--- a/gm/bitmapcopy.cpp
+++ b/gm/bitmapcopy.cpp
@@ -62,14 +62,14 @@
 
     virtual void onDraw(SkCanvas* canvas) {
         SkPaint paint;
-        SkScalar horizMargin(SkIntToScalar(10));
-        SkScalar vertMargin(SkIntToScalar(10));
+        SkScalar horizMargin = 10;
+        SkScalar vertMargin = 10;
 
-        SkBitmapDevice devTmp(SkBitmap::kARGB_8888_Config, 40, 40, false);
-        SkCanvas canvasTmp(&devTmp);
+        SkBitmap src;
+        src.allocN32Pixels(40, 40);
+        SkCanvas canvasTmp(src);
 
         draw_checks(&canvasTmp, 40, 40);
-        SkBitmap src = canvasTmp.getTopDevice()->accessBitmap(false);
 
         for (unsigned i = 0; i < NUM_CONFIGS; ++i) {
             if (!src.deepCopyTo(&fDst[i], gConfigs[i])) {
diff --git a/gm/bitmapsource.cpp b/gm/bitmapsource.cpp
index 6d575eb..f40cc15 100644
--- a/gm/bitmapsource.cpp
+++ b/gm/bitmapsource.cpp
@@ -23,8 +23,7 @@
 
     void makeBitmap() {
         fBitmap.allocN32Pixels(100, 100);
-        SkBitmapDevice device(fBitmap);
-        SkCanvas canvas(&device);
+        SkCanvas canvas(fBitmap);
         canvas.clear(0x00000000);
         SkPaint paint;
         paint.setAntiAlias(true);
diff --git a/gm/deviceproperties.cpp b/gm/deviceproperties.cpp
index 8c4649c..2083946 100644
--- a/gm/deviceproperties.cpp
+++ b/gm/deviceproperties.cpp
@@ -5,6 +5,7 @@
  * found in the LICENSE file.
  */
 #include "gm.h"
+#include "SkBitmapDevice.h"
 #include "SkTypeface.h"
 
 namespace skiagm {
diff --git a/gm/displacement.cpp b/gm/displacement.cpp
index ef6207a..b1f097b 100644
--- a/gm/displacement.cpp
+++ b/gm/displacement.cpp
@@ -33,8 +33,7 @@
 
     void make_bitmap() {
         fBitmap.allocN32Pixels(80, 80);
-        SkBitmapDevice device(fBitmap);
-        SkCanvas canvas(&device);
+        SkCanvas canvas(fBitmap);
         canvas.clear(0x00000000);
         SkPaint paint;
         paint.setAntiAlias(true);
@@ -46,8 +45,7 @@
 
     void make_checkerboard(SkBitmap* bitmap, int w, int h) {
         bitmap->allocN32Pixels(w, h);
-        SkBitmapDevice device(*bitmap);
-        SkCanvas canvas(&device);
+        SkCanvas canvas(*bitmap);
         canvas.clear(0x00000000);
         SkPaint darkPaint;
         darkPaint.setColor(0xFF804020);
diff --git a/gm/gammatext.cpp b/gm/gammatext.cpp
index 99642f6..7ee55db 100644
--- a/gm/gammatext.cpp
+++ b/gm/gammatext.cpp
@@ -38,14 +38,14 @@
 #import <ApplicationServices/ApplicationServices.h>
 #define BITMAP_INFO_RGB     (kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host)
 
-static CGContextRef makeCG(const SkBitmap& bm) {
-    if (SkBitmap::kARGB_8888_Config != bm.config() ||
-        NULL == bm.getPixels()) {
+static CGContextRef makeCG(const SkImageInfo& info, const void* addr,
+                           size_t rowBytes) {
+    if (kPMColor_SkColorType != info.colorType() || NULL == addr) {
         return NULL;
     }
     CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
-    CGContextRef cg = CGBitmapContextCreate(bm.getPixels(), bm.width(), bm.height(),
-                                            8, bm.rowBytes(), space, BITMAP_INFO_RGB);
+    CGContextRef cg = CGBitmapContextCreate((void*)addr, info.width(), info.height(),
+                                            8, rowBytes, space, BITMAP_INFO_RGB);
     CFRelease(space);
 
     CGContextSetAllowsFontSubpixelQuantization(cg, false);
@@ -143,7 +143,15 @@
 
     virtual void onDraw(SkCanvas* canvas) {
 #ifdef SK_BUILD_FOR_MAC
-        CGContextRef cg = makeCG(canvas->getDevice()->accessBitmap(false));
+        CGContextRef cg = 0;
+        {
+            SkImageInfo info;
+            size_t rowBytes;
+            const void* addr = canvas->peekPixels(&info, &rowBytes);
+            if (addr) {
+                cg = makeCG(info, addr, rowBytes);
+            }
+        }
 #endif
 
         drawGrad(canvas);
diff --git a/gm/gm.h b/gm/gm.h
index 4da688c..372b781 100644
--- a/gm/gm.h
+++ b/gm/gm.h
@@ -1,15 +1,14 @@
-
 /*
  * Copyright 2011 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
+
 #ifndef skiagm_DEFINED
 #define skiagm_DEFINED
 
 #include "SkBitmap.h"
-#include "SkBitmapDevice.h"
 #include "SkCanvas.h"
 #include "SkPaint.h"
 #include "SkSize.h"
diff --git a/gm/imagefiltersclipped.cpp b/gm/imagefiltersclipped.cpp
index 82873ab..331ea49 100644
--- a/gm/imagefiltersclipped.cpp
+++ b/gm/imagefiltersclipped.cpp
@@ -35,8 +35,7 @@
 
     void make_checkerboard() {
         fCheckerboard.allocN32Pixels(64, 64);
-        SkBitmapDevice device(fCheckerboard);
-        SkCanvas canvas(&device);
+        SkCanvas canvas(fCheckerboard);
         canvas.clear(0x00000000);
         SkPaint darkPaint;
         darkPaint.setColor(0xFF404040);
@@ -58,10 +57,9 @@
     void make_gradient_circle(int width, int height) {
         SkScalar x = SkIntToScalar(width / 2);
         SkScalar y = SkIntToScalar(height / 2);
-        SkScalar radius = SkScalarMul(SkMinScalar(x, y), SkIntToScalar(4) / SkIntToScalar(5));
+        SkScalar radius = SkMinScalar(x, y) * 0.8f;
         fGradientCircle.allocN32Pixels(width, height);
-        SkBitmapDevice device(fGradientCircle);
-        SkCanvas canvas(&device);
+        SkCanvas canvas(fGradientCircle);
         canvas.clear(0x00000000);
         SkColor colors[2];
         colors[0] = SK_ColorWHITE;
diff --git a/gm/imagefiltersgraph.cpp b/gm/imagefiltersgraph.cpp
index 6d5105e..882918c 100644
--- a/gm/imagefiltersgraph.cpp
+++ b/gm/imagefiltersgraph.cpp
@@ -8,6 +8,7 @@
 #include "gm.h"
 
 #include "SkArithmeticMode.h"
+#include "SkDevice.h"
 #include "SkBitmapSource.h"
 #include "SkBlurImageFilter.h"
 #include "SkColorFilter.h"
@@ -93,8 +94,7 @@
 
     void make_bitmap() {
         fBitmap.allocN32Pixels(100, 100);
-        SkBitmapDevice device(fBitmap);
-        SkCanvas canvas(&device);
+        SkCanvas canvas(fBitmap);
         canvas.clear(0x00000000);
         SkPaint paint;
         paint.setAntiAlias(true);
diff --git a/gm/imagefiltersscaled.cpp b/gm/imagefiltersscaled.cpp
index a9c4a10..28b3c9f 100644
--- a/gm/imagefiltersscaled.cpp
+++ b/gm/imagefiltersscaled.cpp
@@ -35,8 +35,7 @@
 
     void make_checkerboard() {
         fCheckerboard.allocN32Pixels(64, 64);
-        SkBitmapDevice device(fCheckerboard);
-        SkCanvas canvas(&device);
+        SkCanvas canvas(fCheckerboard);
         canvas.clear(0x00000000);
         SkPaint darkPaint;
         darkPaint.setColor(0xFF404040);
@@ -60,8 +59,7 @@
         SkScalar y = SkIntToScalar(height / 2);
         SkScalar radius = SkScalarMul(SkMinScalar(x, y), SkIntToScalar(4) / SkIntToScalar(5));
         fGradientCircle.allocN32Pixels(width, height);
-        SkBitmapDevice device(fGradientCircle);
-        SkCanvas canvas(&device);
+        SkCanvas canvas(fGradientCircle);
         canvas.clear(0x00000000);
         SkColor colors[2];
         colors[0] = SK_ColorWHITE;
diff --git a/gm/lighting.cpp b/gm/lighting.cpp
index 1cab553..858976b 100644
--- a/gm/lighting.cpp
+++ b/gm/lighting.cpp
@@ -26,8 +26,7 @@
 
     void make_bitmap() {
         fBitmap.allocN32Pixels(100, 100);
-        SkBitmapDevice device(fBitmap);
-        SkCanvas canvas(&device);
+        SkCanvas canvas(fBitmap);
         canvas.clear(0x00000000);
         SkPaint paint;
         paint.setAntiAlias(true);
@@ -38,7 +37,7 @@
     }
 
     virtual SkISize onISize() {
-        return make_isize(WIDTH, HEIGHT);
+        return SkISize::Make(WIDTH, HEIGHT);
     }
 
     void drawClippedBitmap(SkCanvas* canvas, const SkPaint& paint, int x, int y) {
diff --git a/gm/matrixconvolution.cpp b/gm/matrixconvolution.cpp
index 47a3581..b986cc1 100644
--- a/gm/matrixconvolution.cpp
+++ b/gm/matrixconvolution.cpp
@@ -25,8 +25,7 @@
 
     void make_bitmap() {
         fBitmap.allocN32Pixels(80, 80);
-        SkBitmapDevice device(fBitmap);
-        SkCanvas canvas(&device);
+        SkCanvas canvas(fBitmap);
         canvas.clear(0x00000000);
         SkPaint paint;
         paint.setAntiAlias(true);
diff --git a/gm/morphology.cpp b/gm/morphology.cpp
index 5cfb1c2..a2206b8 100644
--- a/gm/morphology.cpp
+++ b/gm/morphology.cpp
@@ -27,8 +27,7 @@
 
     void make_bitmap() {
         fBitmap.allocN32Pixels(135, 135);
-        SkBitmapDevice device(fBitmap);
-        SkCanvas canvas(&device);
+        SkCanvas canvas(fBitmap);
         canvas.clear(0x0);
         SkPaint paint;
         paint.setAntiAlias(true);
diff --git a/gm/ninepatchstretch.cpp b/gm/ninepatchstretch.cpp
index a14af00..74cc87f 100644
--- a/gm/ninepatchstretch.cpp
+++ b/gm/ninepatchstretch.cpp
@@ -13,10 +13,7 @@
     const int kSize = 2*kFixed + kStretchy;
 
     bitmap->allocN32Pixels(kSize, kSize);
-    SkBaseDevice* dev = new SkBitmapDevice(*bitmap);
-
-    SkCanvas canvas(dev);
-    dev->unref();
+    SkCanvas canvas(*bitmap);
     canvas.clear(SK_ColorTRANSPARENT);
 
     SkRect r = SkRect::MakeWH(SkIntToScalar(kSize), SkIntToScalar(kSize));
diff --git a/gm/offsetimagefilter.cpp b/gm/offsetimagefilter.cpp
index 1b76ba2..0425311 100644
--- a/gm/offsetimagefilter.cpp
+++ b/gm/offsetimagefilter.cpp
@@ -28,8 +28,7 @@
 
     void make_bitmap() {
         fBitmap.allocN32Pixels(80, 80);
-        SkBitmapDevice device(fBitmap);
-        SkCanvas canvas(&device);
+        SkCanvas canvas(fBitmap);
         canvas.clear(0x00000000);
         SkPaint paint;
         paint.setAntiAlias(true);
@@ -40,10 +39,8 @@
     }
 
     void make_checkerboard() {
-        fCheckerboard.setConfig(SkBitmap::kARGB_8888_Config, 80, 80);
-        fCheckerboard.allocPixels();
-        SkBitmapDevice device(fCheckerboard);
-        SkCanvas canvas(&device);
+        fCheckerboard.allocN32Pixels(80, 80);
+        SkCanvas canvas(fCheckerboard);
         canvas.clear(0x00000000);
         SkPaint darkPaint;
         darkPaint.setColor(0xFF404040);
diff --git a/gm/peekpixels.cpp b/gm/peekpixels.cpp
new file mode 100644
index 0000000..c6744d3
--- /dev/null
+++ b/gm/peekpixels.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "gm.h"
+#include "SkCanvas.h"
+#include "SkPath.h"
+#include "SkSurface.h"
+#include "SkPicture.h"
+
+static void draw_content(SkCanvas* canvas) {
+    SkImageInfo info = canvas->imageInfo();
+    SkPaint paint;
+    paint.setAntiAlias(true);
+    canvas->drawCircle(SkScalarHalf(info.width()), SkScalarHalf(info.height()),
+                       SkScalarHalf(info.width()), paint);
+}
+
+class PeekPixelsGM : public skiagm::GM {
+public:
+    PeekPixelsGM() {}
+
+protected:
+    virtual SkString onShortName() SK_OVERRIDE {
+        return SkString("peekpixels");
+    }
+
+    virtual SkISize onISize() SK_OVERRIDE {
+        return SkISize::Make(640, 480);
+    }
+
+    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
+        SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100);
+        SkAutoTUnref<SkSurface> surface(canvas->newSurface(info));
+        if (surface.get()) {
+            SkCanvas* surfCanvas = surface->getCanvas();
+            
+            draw_content(surfCanvas);
+            SkBitmap bitmap;
+            
+            // test peekPixels
+            {
+                SkImageInfo info;
+                size_t rowBytes;
+                const void* addr = surfCanvas->peekPixels(&info, &rowBytes);
+                if (addr && bitmap.installPixels(info, const_cast<void*>(addr),
+                                                 rowBytes, NULL, NULL)) {
+                    canvas->drawBitmap(bitmap, 0, 0, NULL);
+                }
+            }
+            
+            // test ROCanvasPixels
+            canvas->translate(120, 0);
+            SkAutoROCanvasPixels ropixels(surfCanvas);
+            if (ropixels.asROBitmap(&bitmap)) {
+                canvas->drawBitmap(bitmap, 0, 0, NULL);
+            }
+            
+            // test Surface
+            canvas->translate(120, 0);
+            surface->draw(canvas, 0, 0, NULL);
+        }
+    }
+
+    virtual uint32_t onGetFlags() const {
+        // we explicitly test peekPixels and readPixels, neither of which
+        // return something for a picture-backed canvas, so we skip that test.
+        return kSkipPicture_Flag;
+    }
+
+private:
+    typedef skiagm::GM INHERITED;
+};
+
+DEF_GM( return SkNEW(PeekPixelsGM); )
diff --git a/gm/tileimagefilter.cpp b/gm/tileimagefilter.cpp
index d0acad7..319aa3c 100644
--- a/gm/tileimagefilter.cpp
+++ b/gm/tileimagefilter.cpp
@@ -28,8 +28,7 @@
 
     void make_bitmap() {
         fBitmap.allocN32Pixels(80, 80);
-        SkBitmapDevice device(fBitmap);
-        SkCanvas canvas(&device);
+        SkCanvas canvas(fBitmap);
         canvas.clear(0xFF000000);
         SkPaint paint;
         paint.setAntiAlias(true);
@@ -41,8 +40,7 @@
 
     void make_checkerboard() {
         fCheckerboard.allocN32Pixels(80, 80);
-        SkBitmapDevice device(fCheckerboard);
-        SkCanvas canvas(&device);
+        SkCanvas canvas(fCheckerboard);
         canvas.clear(0x00000000);
         SkPaint darkPaint;
         darkPaint.setColor(0xFF404040);
diff --git a/gm/xfermodeimagefilter.cpp b/gm/xfermodeimagefilter.cpp
index f843d40..4469618 100644
--- a/gm/xfermodeimagefilter.cpp
+++ b/gm/xfermodeimagefilter.cpp
@@ -30,8 +30,7 @@
 
     void make_bitmap() {
         fBitmap.allocN32Pixels(80, 80);
-        SkBitmapDevice device(fBitmap);
-        SkCanvas canvas(&device);
+        SkCanvas canvas(fBitmap);
         canvas.clear(0x00000000);
         SkPaint paint;
         paint.setAntiAlias(true);
@@ -43,8 +42,7 @@
 
     void make_checkerboard() {
         fCheckerboard.allocN32Pixels(80, 80);
-        SkBitmapDevice device(fCheckerboard);
-        SkCanvas canvas(&device);
+        SkCanvas canvas(fCheckerboard);
         canvas.clear(0x00000000);
         SkPaint darkPaint;
         darkPaint.setColor(0xFF404040);
diff --git a/gm/xfermodes3.cpp b/gm/xfermodes3.cpp
index bb7d614..76c4b88 100644
--- a/gm/xfermodes3.cpp
+++ b/gm/xfermodes3.cpp
@@ -168,8 +168,11 @@
         if (NULL == layerCanvas) {
             canvas->restore();
         } else {
-            SkBitmap bitmap = layerCanvas->getDevice()->accessBitmap(false);
-            canvas->drawBitmap(bitmap, 0, 0);
+            SkAutoROCanvasPixels ropixels(layerCanvas);
+            SkBitmap bitmap;
+            if (ropixels.asROBitmap(&bitmap)) {
+                canvas->drawBitmap(bitmap, 0, 0);
+            }
         }
 
         r.inset(-SK_ScalarHalf, -SK_ScalarHalf);