Change device factories to take SkImageInfo instead of SkBitmap::Config

patch from issue 167033002

BUG=skia:
R=reed@google.com

Author: reed@chromium.org

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

git-svn-id: http://skia.googlecode.com/svn/trunk@13463 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/dm/DM.cpp b/dm/DM.cpp
index de2bda7..8a4a382 100644
--- a/dm/DM.cpp
+++ b/dm/DM.cpp
@@ -53,8 +53,8 @@
                            const DM::Expectations& expectations,
                            DM::Reporter* reporter,
                            DM::TaskRunner* tasks) {
-    const SkBitmap::Config _565 = SkBitmap::kRGB_565_Config;
-    const SkBitmap::Config _8888 = SkBitmap::kARGB_8888_Config;
+    const SkColorType _565 = kRGB_565_SkColorType;
+    const SkColorType _8888 = kPMColor_SkColorType;
     const GrContextFactory::GLContextType native = GrContextFactory::kNative_GLContextType;
     const GrContextFactory::GLContextType null   = GrContextFactory::kNull_GLContextType;
     const GrContextFactory::GLContextType debug  = GrContextFactory::kDebug_GLContextType;
diff --git a/dm/DMCpuTask.cpp b/dm/DMCpuTask.cpp
index c538f0a..7a82a75 100644
--- a/dm/DMCpuTask.cpp
+++ b/dm/DMCpuTask.cpp
@@ -14,18 +14,18 @@
                  TaskRunner* taskRunner,
                  const Expectations& expectations,
                  skiagm::GMRegistry::Factory gmFactory,
-                 SkBitmap::Config config)
+                 SkColorType colorType)
     : Task(reporter, taskRunner)
     , fGMFactory(gmFactory)
     , fGM(fGMFactory(NULL))
     , fName(UnderJoin(fGM->shortName(), name))
     , fExpectations(expectations)
-    , fConfig(config)
+    , fColorType(colorType)
     {}
 
 void CpuTask::draw() {
     SkBitmap bitmap;
-    SetupBitmap(fConfig, fGM.get(), &bitmap);
+    SetupBitmap(fColorType, fGM.get(), &bitmap);
 
     SkCanvas canvas(bitmap);
     canvas.concat(fGM->getInitialTransform());
@@ -48,7 +48,7 @@
 }
 
 bool CpuTask::shouldSkip() const {
-    if (SkBitmap::kRGB_565_Config == fConfig && (fGM->getFlags() & skiagm::GM::kSkip565_Flag)) {
+    if (kRGB_565_SkColorType == fColorType && (fGM->getFlags() & skiagm::GM::kSkip565_Flag)) {
         return true;
     }
     if (fGM->getFlags() & skiagm::GM::kGPUOnly_Flag) {
diff --git a/dm/DMCpuTask.h b/dm/DMCpuTask.h
index c1ee715..8e7f531 100644
--- a/dm/DMCpuTask.h
+++ b/dm/DMCpuTask.h
@@ -22,7 +22,7 @@
             TaskRunner*,
             const Expectations&,
             skiagm::GMRegistry::Factory,
-            SkBitmap::Config);
+            SkColorType);
 
     virtual void draw() SK_OVERRIDE;
     virtual bool usesGpu() const SK_OVERRIDE { return false; }
@@ -34,7 +34,7 @@
     SkAutoTDelete<skiagm::GM> fGM;
     const SkString fName;
     const Expectations& fExpectations;
-    const SkBitmap::Config fConfig;
+    const SkColorType fColorType;
 };
 
 }  // namespace DM
diff --git a/dm/DMGpuTask.cpp b/dm/DMGpuTask.cpp
index c0502ee..f787e25 100644
--- a/dm/DMGpuTask.cpp
+++ b/dm/DMGpuTask.cpp
@@ -4,7 +4,7 @@
 #include "DMUtil.h"
 #include "DMWriteTask.h"
 #include "SkCommandLineFlags.h"
-#include "SkGpuDevice.h"
+#include "SkSurface.h"
 #include "SkTLS.h"
 
 namespace DM {
@@ -14,14 +14,14 @@
                  TaskRunner* taskRunner,
                  const Expectations& expectations,
                  skiagm::GMRegistry::Factory gmFactory,
-                 SkBitmap::Config config,
+                 SkColorType colorType,
                  GrContextFactory::GLContextType contextType,
                  int sampleCount)
     : Task(reporter, taskRunner)
     , fGM(gmFactory(NULL))
     , fName(UnderJoin(fGM->shortName(), name))
     , fExpectations(expectations)
-    , fConfig(config)
+    , fColorType(colorType)
     , fContextType(contextType)
     , fSampleCount(sampleCount)
     {}
@@ -41,20 +41,19 @@
 
 void GpuTask::draw() {
     GrContext* gr = get_gr_factory()->get(fContextType);  // Will be owned by device.
-    SkGpuDevice device(gr,
-                       fConfig,
-                       SkScalarCeilToInt(fGM->width()),
-                       SkScalarCeilToInt(fGM->height()),
-                       fSampleCount);
-    SkCanvas canvas(&device);
+    SkImageInfo info = SkImageInfo::Make(SkScalarCeilToInt(fGM->width()),
+                                         SkScalarCeilToInt(fGM->height()),
+                                         fColorType, kPremul_SkAlphaType);
+    SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(gr, info, fSampleCount));
+    SkCanvas* canvas = surface->getCanvas();
 
-    canvas.concat(fGM->getInitialTransform());
-    fGM->draw(&canvas);
-    canvas.flush();
+    canvas->concat(fGM->getInitialTransform());
+    fGM->draw(canvas);
+    canvas->flush();
 
     SkBitmap bitmap;
-    bitmap.setConfig(fConfig, SkScalarCeilToInt(fGM->width()), SkScalarCeilToInt(fGM->height()));
-    canvas.readPixels(&bitmap, 0, 0);
+    bitmap.setConfig(info);
+    canvas->readPixels(&bitmap, 0, 0);
 
 #if GR_CACHE_STATS
     gr->printCacheStats();
diff --git a/dm/DMGpuTask.h b/dm/DMGpuTask.h
index aa350c9..a3fe52b 100644
--- a/dm/DMGpuTask.h
+++ b/dm/DMGpuTask.h
@@ -22,7 +22,7 @@
             TaskRunner*,
             const Expectations&,
             skiagm::GMRegistry::Factory,
-            SkBitmap::Config,
+            SkColorType,
             GrContextFactory::GLContextType,
             int sampleCount);
 
@@ -35,7 +35,7 @@
     SkAutoTDelete<skiagm::GM> fGM;
     const SkString fName;
     const Expectations& fExpectations;
-    const SkBitmap::Config fConfig;
+    const SkColorType fColorType;
     const GrContextFactory::GLContextType fContextType;
     const int fSampleCount;
 };
diff --git a/dm/DMPipeTask.cpp b/dm/DMPipeTask.cpp
index de3897a..163f1e6 100644
--- a/dm/DMPipeTask.cpp
+++ b/dm/DMPipeTask.cpp
@@ -47,7 +47,7 @@
 
 void PipeTask::draw() {
     SkBitmap bitmap;
-    SetupBitmap(fReference.config(), fGM.get(), &bitmap);
+    SetupBitmap(fReference.colorType(), fGM.get(), &bitmap);
 
     SkCanvas canvas(bitmap);
     PipeController pipeController(&canvas, &SkImageDecoder::DecodeMemory);
diff --git a/dm/DMReplayTask.cpp b/dm/DMReplayTask.cpp
index af8669b..3b47962 100644
--- a/dm/DMReplayTask.cpp
+++ b/dm/DMReplayTask.cpp
@@ -27,7 +27,7 @@
     RecordPicture(fGM.get(), &recorded, flags);
 
     SkBitmap bitmap;
-    SetupBitmap(fReference.config(), fGM.get(), &bitmap);
+    SetupBitmap(fReference.colorType(), fGM.get(), &bitmap);
     DrawPicture(&recorded, &bitmap);
     if (!BitmapsEqual(bitmap, fReference)) {
         this->fail();
diff --git a/dm/DMSerializeTask.cpp b/dm/DMSerializeTask.cpp
index 3359f2e..7e45d49 100644
--- a/dm/DMSerializeTask.cpp
+++ b/dm/DMSerializeTask.cpp
@@ -29,7 +29,7 @@
     SkAutoTUnref<SkPicture> reconstructed(SkPicture::CreateFromStream(rStream));
 
     SkBitmap bitmap;
-    SetupBitmap(fReference.config(), fGM.get(), &bitmap);
+    SetupBitmap(fReference.colorType(), fGM.get(), &bitmap);
     DrawPicture(reconstructed, &bitmap);
     if (!BitmapsEqual(bitmap, fReference)) {
         this->fail();
diff --git a/dm/DMTileGridTask.cpp b/dm/DMTileGridTask.cpp
index cd3c7b7..beffbb0 100644
--- a/dm/DMTileGridTask.cpp
+++ b/dm/DMTileGridTask.cpp
@@ -34,12 +34,12 @@
     RecordPicture(fGM.get(), &recorded, SkPicture::kUsePathBoundsForClip_RecordingFlag);
 
     SkBitmap full;
-    SetupBitmap(fReference.config(), fGM.get(), &full);
+    SetupBitmap(fReference.colorType(), fGM.get(), &full);
     SkCanvas fullCanvas(full);
 
     SkBitmap tile;
-    tile.setConfig(fReference.config(), fTileSize.width(), fTileSize.height());
-    tile.allocPixels();
+    tile.allocPixels(SkImageInfo::Make(fTileSize.width(), fTileSize.height(),
+                                       fReference.colorType(), kPremul_SkAlphaType));
     SkCanvas tileCanvas(tile);
 
     SkPaint paint;
diff --git a/dm/DMUtil.cpp b/dm/DMUtil.cpp
index 52efda3..849d1bf 100644
--- a/dm/DMUtil.cpp
+++ b/dm/DMUtil.cpp
@@ -19,10 +19,10 @@
     picture->endRecording();
 }
 
-void SetupBitmap(const SkBitmap::Config config, skiagm::GM* gm, SkBitmap* bitmap) {
+void SetupBitmap(const SkColorType ct, skiagm::GM* gm, SkBitmap* bitmap) {
     const SkISize size = gm->getISize();
-    bitmap->setConfig(config, size.width(), size.height());
-    bitmap->allocPixels();
+    bitmap->allocPixels(SkImageInfo::Make(size.width(), size.height(),
+                                          ct, kPremul_SkAlphaType));
     bitmap->eraseColor(0x00000000);
 }
 
diff --git a/dm/DMUtil.h b/dm/DMUtil.h
index b887d82..a791649 100644
--- a/dm/DMUtil.h
+++ b/dm/DMUtil.h
@@ -16,7 +16,7 @@
 void RecordPicture(skiagm::GM* gm, SkPicture* picture, uint32_t recordFlags = 0);
 
 // Prepare bitmap to have gm draw into it with this config.
-void SetupBitmap(const SkBitmap::Config config, skiagm::GM* gm, SkBitmap* bitmap);
+void SetupBitmap(const SkColorType, skiagm::GM* gm, SkBitmap* bitmap);
 
 // Draw picture to bitmap.
 void DrawPicture(SkPicture* picture, SkBitmap* bitmap);
diff --git a/experimental/PdfViewer/SkTrackDevice.h b/experimental/PdfViewer/SkTrackDevice.h
index a4f40bc..bb6aace 100644
--- a/experimental/PdfViewer/SkTrackDevice.h
+++ b/experimental/PdfViewer/SkTrackDevice.h
@@ -33,6 +33,7 @@
         : SkBitmapDevice(bitmap, deviceProperties)
         , fTracker(NULL) {}
 
+#ifdef SK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG
     SkTrackDevice(SkBitmap::Config config, int width, int height, bool isOpaque = false)
         : SkBitmapDevice(config, width, height, isOpaque)
         , fTracker(NULL) {}
@@ -41,6 +42,7 @@
                   const SkDeviceProperties& deviceProperties)
         : SkBitmapDevice(config, width, height, isOpaque, deviceProperties)
         , fTracker(NULL) {}
+#endif
 
     virtual ~SkTrackDevice() {}
 
diff --git a/include/core/SkBitmapDevice.h b/include/core/SkBitmapDevice.h
index be98c95..1d18155 100644
--- a/include/core/SkBitmapDevice.h
+++ b/include/core/SkBitmapDevice.h
@@ -30,6 +30,7 @@
     */
     SkBitmapDevice(const SkBitmap& bitmap, const SkDeviceProperties& deviceProperties);
 
+#ifdef SK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG
     /**
      *  Create a new raster device and have the pixels be automatically
      *  allocated. The rowBytes of the device will be computed automatically
@@ -61,8 +62,9 @@
      */
     SkBitmapDevice(SkBitmap::Config config, int width, int height, bool isOpaque,
                    const SkDeviceProperties& deviceProperties);
-
-    virtual ~SkBitmapDevice();
+#endif
+    static SkBitmapDevice* Create(const SkImageInfo&,
+                                  const SkDeviceProperties* = NULL);
 
     virtual uint32_t getDeviceCapabilities() SK_OVERRIDE { return 0; }
 
@@ -185,7 +187,7 @@
                               const uint16_t indices[], int indexCount,
                               const SkPaint& paint) SK_OVERRIDE;
     /** The SkBaseDevice passed will be an SkBaseDevice which was returned by a call to
-        onCreateCompatibleDevice on this device with kSaveLayer_Usage.
+        onCreateDevice on this device with kSaveLayer_Usage.
      */
     virtual void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y,
                             const SkPaint&) SK_OVERRIDE;
@@ -260,20 +262,17 @@
 
     friend class SkSurface_Raster;
 
-    void init(SkBitmap::Config config, int width, int height, bool isOpaque);
-
     // used to change the backend's pixels (and possibly config/rowbytes)
     // but cannot change the width/height, so there should be no change to
     // any clip information.
     virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) SK_OVERRIDE;
 
-    /**
-     * Subclasses should override this to implement createCompatibleDevice.
-     */
-    virtual SkBaseDevice* onCreateCompatibleDevice(SkBitmap::Config config,
-                                                   int width, int height,
-                                                   bool isOpaque,
-                                                   Usage usage) SK_OVERRIDE;
+#ifdef SK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG
+    // in support of legacy constructors
+    void init(SkBitmap::Config config, int width, int height, bool isOpaque);
+#endif
+
+    virtual SkBaseDevice* onCreateDevice(const SkImageInfo&, Usage) SK_OVERRIDE;
 
     /** Causes any deferred drawing to the device to be completed.
      */
diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h
index 4be092a..aaaeb3b 100644
--- a/include/core/SkCanvas.h
+++ b/include/core/SkCanvas.h
@@ -1124,8 +1124,7 @@
     friend class SkDrawIter;    // needs setupDrawForLayerDevice()
     friend class AutoDrawLooper;
 
-    SkBaseDevice* createLayerDevice(SkBitmap::Config, int width, int height,
-                                    bool isOpaque);
+    SkBaseDevice* createLayerDevice(const SkImageInfo&);
 
     SkBaseDevice* init(SkBaseDevice*);
 
diff --git a/include/core/SkDevice.h b/include/core/SkDevice.h
index 8da5071..2c85dbd 100644
--- a/include/core/SkDevice.h
+++ b/include/core/SkDevice.h
@@ -16,6 +16,8 @@
 #include "SkColor.h"
 #include "SkDeviceProperties.h"
 
+//#define SK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG
+
 class SkClipStack;
 class SkDraw;
 struct SkIRect;
@@ -41,6 +43,7 @@
 
     virtual ~SkBaseDevice();
 
+#ifdef SK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG
     /**
      *  Creates a device that is of the same type as this device (e.g. SW-raster,
      *  GPU, or PDF). The backing store for this device is created automatically
@@ -55,6 +58,8 @@
     SkBaseDevice* createCompatibleDevice(SkBitmap::Config config,
                                          int width, int height,
                                          bool isOpaque);
+#endif
+    SkBaseDevice* createCompatibleDevice(const SkImageInfo&);
 
     SkMetaData& getMetaData();
 
@@ -279,7 +284,7 @@
                               const uint16_t indices[], int indexCount,
                               const SkPaint& paint) = 0;
     /** The SkDevice passed will be an SkDevice which was returned by a call to
-        onCreateCompatibleDevice on this device with kSaveLayer_Usage.
+        onCreateDevice on this device with kSaveLayer_Usage.
      */
     virtual void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y,
                             const SkPaint&) = 0;
@@ -406,17 +411,23 @@
     // just called by SkCanvas when built as a layer
     void setOrigin(int x, int y) { fOrigin.set(x, y); }
     // just called by SkCanvas for saveLayer
-    SkBaseDevice* createCompatibleDeviceForSaveLayer(SkBitmap::Config config,
-                                                     int width, int height,
-                                                     bool isOpaque);
+    SkBaseDevice* createCompatibleDeviceForSaveLayer(const SkImageInfo&);
 
+#ifdef SK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG
     /**
-     * Subclasses should override this to implement createCompatibleDevice.
+     * Justs exists during the period where clients still "override" this
+     *  signature. They are supported by our base-impl calling this old
+     *  signature from the new one (using ImageInfo).
      */
     virtual SkBaseDevice* onCreateCompatibleDevice(SkBitmap::Config config,
                                                    int width, int height,
-                                                   bool isOpaque,
-                                                   Usage usage) = 0;
+                                                   bool isOpaque, Usage) {
+        return NULL;
+    }
+#endif
+    virtual SkBaseDevice* onCreateDevice(const SkImageInfo&, Usage) {
+        return NULL;
+    }
 
     /** Causes any deferred drawing to the device to be completed.
      */
diff --git a/include/device/xps/SkXPSDevice.h b/include/device/xps/SkXPSDevice.h
index 13ae834..37df14b 100644
--- a/include/device/xps/SkXPSDevice.h
+++ b/include/device/xps/SkXPSDevice.h
@@ -312,11 +312,7 @@
         const SkVector& ppuScale,
         IXpsOMPath* shadedPath);
 
-    // override from SkBaseDevice
-    virtual SkBaseDevice* onCreateCompatibleDevice(SkBitmap::Config config,
-                                                   int width, int height,
-                                                   bool isOpaque,
-                                                   Usage usage) SK_OVERRIDE;
+    virtual SkBaseDevice* onCreateDevice(const SkImageInfo&, Usage) SK_OVERRIDE;
 
     // Disable the default copy and assign implementation.
     SkXPSDevice(const SkXPSDevice&);
diff --git a/include/gpu/SkGpuDevice.h b/include/gpu/SkGpuDevice.h
index 8b2170d..3ccab51 100644
--- a/include/gpu/SkGpuDevice.h
+++ b/include/gpu/SkGpuDevice.h
@@ -37,11 +37,21 @@
 
     /**
      *  New device that will create an offscreen renderTarget based on the
+     *  ImageInfo and sampleCount. The device's storage will not
+     *  count against the GrContext's texture cache budget. The device's pixels
+     *  will be uninitialized. On failure, returns NULL.
+     */
+    static SkGpuDevice* Create(GrContext*, const SkImageInfo&, int sampleCount);
+
+#ifdef SK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG
+    /**
+     *  New device that will create an offscreen renderTarget based on the
      *  config, width, height, and sampleCount. The device's storage will not
      *  count against the GrContext's texture cache budget. The device's pixels
      *  will be uninitialized. TODO: This can fail, replace with a factory function.
      */
     SkGpuDevice(GrContext*, SkBitmap::Config, int width, int height, int sampleCount = 0);
+#endif
 
     /**
      *  DEPRECATED -- need to make this private, call Create(surface)
@@ -163,11 +173,7 @@
     // used by createCompatibleDevice
     SkGpuDevice(GrContext*, GrTexture* texture, bool needClear);
 
-    // override from SkBaseDevice
-    virtual SkBaseDevice* onCreateCompatibleDevice(SkBitmap::Config config,
-                                                   int width, int height,
-                                                   bool isOpaque,
-                                                   Usage usage) SK_OVERRIDE;
+    virtual SkBaseDevice* onCreateDevice(const SkImageInfo&, Usage) SK_OVERRIDE;
 
     virtual SkSurface* newSurface(const SkImageInfo&) SK_OVERRIDE;
 
diff --git a/include/gpu/SkGr.h b/include/gpu/SkGr.h
index db08548..6cfa0fa 100644
--- a/include/gpu/SkGr.h
+++ b/include/gpu/SkGr.h
@@ -50,6 +50,7 @@
  *  kUnknown_PixelConfig if the conversion cannot be done.
  */
 GrPixelConfig SkBitmapConfig2GrPixelConfig(SkBitmap::Config);
+GrPixelConfig SkImageInfo2GrPixelConfig(SkColorType, SkAlphaType);
 bool GrPixelConfig2ColorType(GrPixelConfig, SkColorType*);
 
 static inline GrColor SkColor2GrColor(SkColor c) {
diff --git a/include/pdf/SkPDFDevice.h b/include/pdf/SkPDFDevice.h
index 9b21f8f..0dd0646 100644
--- a/include/pdf/SkPDFDevice.h
+++ b/include/pdf/SkPDFDevice.h
@@ -257,10 +257,7 @@
                 const SkRegion& existingClipRegion);
 
     // override from SkBaseDevice
-    virtual SkBaseDevice* onCreateCompatibleDevice(SkBitmap::Config config,
-                                                   int width, int height,
-                                                   bool isOpaque,
-                                                   Usage usage) SK_OVERRIDE;
+    virtual SkBaseDevice* onCreateDevice(const SkImageInfo&, Usage) SK_OVERRIDE;
 
     void init();
     void cleanUp(bool clearFontUsage);
diff --git a/src/core/SkBitmapDevice.cpp b/src/core/SkBitmapDevice.cpp
index 374bef9..0eff33c 100644
--- a/src/core/SkBitmapDevice.cpp
+++ b/src/core/SkBitmapDevice.cpp
@@ -15,16 +15,60 @@
 #define CHECK_FOR_ANNOTATION(paint) \
     do { if (paint.getAnnotation()) { return; } } while (0)
 
-SkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap)
-    : fBitmap(bitmap) {
-    SkASSERT(SkBitmap::kARGB_4444_Config != bitmap.config());
+static bool valid_for_bitmap_device(const SkImageInfo& info,
+                                    SkAlphaType* newAlphaType) {
+    if (info.width() < 0 || info.height() < 0) {
+        return false;
+    }
+
+    // TODO: can we stop supporting kUnknown in SkBitmkapDevice?
+    if (kUnknown_SkColorType == info.colorType()) {
+        if (newAlphaType) {
+            *newAlphaType = kIgnore_SkAlphaType;
+        }
+        return true;
+    }
+    
+    switch (info.alphaType()) {
+        case kPremul_SkAlphaType:
+        case kOpaque_SkAlphaType:
+            break;
+        default:
+            return false;
+    }
+
+    SkAlphaType canonicalAlphaType = info.alphaType();
+
+    switch (info.colorType()) {
+        case kAlpha_8_SkColorType:
+            break;
+        case kRGB_565_SkColorType:
+            canonicalAlphaType = kOpaque_SkAlphaType;
+            break;
+        case kPMColor_SkColorType:
+            break;
+        default:
+            return false;
+    }
+
+    if (newAlphaType) {
+        *newAlphaType = canonicalAlphaType;
+    }
+    return true;
+}
+
+SkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap) : fBitmap(bitmap) {
+    SkASSERT(valid_for_bitmap_device(bitmap.info(), NULL));
 }
 
 SkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap, const SkDeviceProperties& deviceProperties)
     : SkBaseDevice(deviceProperties)
-    , fBitmap(bitmap) {
+    , fBitmap(bitmap)
+{
+    SkASSERT(valid_for_bitmap_device(bitmap.info(), NULL));
 }
 
+#ifdef SK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG
 void SkBitmapDevice::init(SkBitmap::Config config, int width, int height, bool isOpaque) {
     fBitmap.setConfig(config, width, height, 0, isOpaque ?
                       kOpaque_SkAlphaType : kPremul_SkAlphaType);
@@ -50,8 +94,34 @@
 {
     this->init(config, width, height, isOpaque);
 }
+#endif
+SkBitmapDevice* SkBitmapDevice::Create(const SkImageInfo& origInfo,
+                                       const SkDeviceProperties* props) {
+    SkImageInfo info = origInfo;
+    if (!valid_for_bitmap_device(info, &info.fAlphaType)) {
+        return NULL;
+    }
 
-SkBitmapDevice::~SkBitmapDevice() {
+    SkBitmap bitmap;
+
+    if (kUnknown_SkColorType == info.colorType()) {
+        if (!bitmap.setConfig(info)) {
+            return NULL;
+        }
+    } else {
+        if (!bitmap.allocPixels(info)) {
+            return NULL;
+        }
+        if (!bitmap.info().isOpaque()) {
+            bitmap.eraseColor(SK_ColorTRANSPARENT);
+        }
+    }
+
+    if (props) {
+        return SkNEW_ARGS(SkBitmapDevice, (bitmap, *props));
+    } else {
+        return SkNEW_ARGS(SkBitmapDevice, (bitmap));
+    }
 }
 
 SkImageInfo SkBitmapDevice::imageInfo() const {
@@ -65,18 +135,8 @@
     fBitmap.lockPixels();
 }
 
-SkBaseDevice* SkBitmapDevice::onCreateCompatibleDevice(SkBitmap::Config config,
-                                                       int width, int height,
-                                                       bool isOpaque,
-                                                       Usage usage) {
-    SkBitmapDevice* device = SkNEW_ARGS(SkBitmapDevice,(config, width, height,
-                                        isOpaque, this->getDeviceProperties()));
-    // Check if allocation failed and delete device if it did fail
-    if ((device->width() != width) || (device->height() != height)) {
-        SkDELETE(device);
-        device = NULL;
-    }
-    return device;
+SkBaseDevice* SkBitmapDevice::onCreateDevice(const SkImageInfo& info, Usage usage) {
+    return SkBitmapDevice::Create(info, &this->getDeviceProperties());
 }
 
 void SkBitmapDevice::lockPixels() {
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index f5e91ff..61acf26 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -746,46 +746,6 @@
     return this->internalSave(flags);
 }
 
-#define C32MASK (1 << SkBitmap::kARGB_8888_Config)
-#define C16MASK (1 << SkBitmap::kRGB_565_Config)
-#define C8MASK  (1 << SkBitmap::kA8_Config)
-
-static SkBitmap::Config resolve_config(SkCanvas* canvas,
-                                       const SkIRect& bounds,
-                                       SkCanvas::SaveFlags flags,
-                                       bool* isOpaque) {
-    *isOpaque = (flags & SkCanvas::kHasAlphaLayer_SaveFlag) == 0;
-
-#if 0
-    // loop through and union all the configs we may draw into
-    uint32_t configMask = 0;
-    for (int i = canvas->countLayerDevices() - 1; i >= 0; --i)
-    {
-        SkBaseDevice* device = canvas->getLayerDevice(i);
-        if (device->intersects(bounds))
-            configMask |= 1 << device->config();
-    }
-
-    // if the caller wants alpha or fullcolor, we can't return 565
-    if (flags & (SkCanvas::kFullColorLayer_SaveFlag |
-                 SkCanvas::kHasAlphaLayer_SaveFlag))
-        configMask &= ~C16MASK;
-
-    switch (configMask) {
-    case C8MASK:    // if we only have A8, return that
-        return SkBitmap::kA8_Config;
-
-    case C16MASK:   // if we only have 565, return that
-        return SkBitmap::kRGB_565_Config;
-
-    default:
-        return SkBitmap::kARGB_8888_Config; // default answer
-    }
-#else
-    return SkBitmap::kARGB_8888_Config; // default answer
-#endif
-}
-
 static bool bounds_affects_clip(SkCanvas::SaveFlags flags) {
     return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0;
 }
@@ -840,15 +800,9 @@
 }
 
 static SkBaseDevice* createCompatibleDevice(SkCanvas* canvas,
-                                            SkBitmap::Config config,
-                                            int width, int height,
-                                            bool isOpaque) {
+                                            const SkImageInfo& info) {
     SkBaseDevice* device = canvas->getDevice();
-    if (device) {
-        return device->createCompatibleDevice(config, width, height, isOpaque);
-    } else {
-        return NULL;
-    }
+    return device ? device->createCompatibleDevice(info) : NULL;
 }
 
 int SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint,
@@ -878,16 +832,15 @@
         }
     }
 
-    bool isOpaque;
-    SkBitmap::Config config = resolve_config(this, ir, flags, &isOpaque);
+    bool isOpaque = !SkToBool(flags & kHasAlphaLayer_SaveFlag);
+    SkImageInfo info = SkImageInfo::MakeN32(ir.width(), ir.height(),
+                        isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
 
     SkBaseDevice* device;
     if (paint && paint->getImageFilter()) {
-        device = createCompatibleDevice(this, config, ir.width(), ir.height(),
-                                        isOpaque);
+        device = createCompatibleDevice(this, info);
     } else {
-        device = this->createLayerDevice(config, ir.width(), ir.height(),
-                                         isOpaque);
+        device = this->createLayerDevice(info);
     }
     if (NULL == device) {
         SkDebugf("Unable to create device for layer.");
@@ -1607,16 +1560,9 @@
     return fMCRec->fRasterClip->forceGetBW();
 }
 
-SkBaseDevice* SkCanvas::createLayerDevice(SkBitmap::Config config,
-                                          int width, int height,
-                                          bool isOpaque) {
+SkBaseDevice* SkCanvas::createLayerDevice(const SkImageInfo& info) {
     SkBaseDevice* device = this->getTopDevice();
-    if (device) {
-        return device->createCompatibleDeviceForSaveLayer(config, width, height,
-                                                          isOpaque);
-    } else {
-        return NULL;
-    }
+    return device ? device->createCompatibleDeviceForSaveLayer(info) : NULL;
 }
 
 GrContext* SkCanvas::getGrContext() {
diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp
index 364b106..d69e4af 100644
--- a/src/core/SkDevice.cpp
+++ b/src/core/SkDevice.cpp
@@ -42,19 +42,53 @@
     delete fMetaData;
 }
 
+SkBaseDevice* SkBaseDevice::createCompatibleDevice(const SkImageInfo& info) {
+#ifdef SK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG
+    // We call the old method to support older subclasses.
+    // If they have, we return their device, else we use the new impl.
+    SkBitmap::Config config = SkColorTypeToBitmapConfig(info.colorType());
+    SkBaseDevice* dev = this->onCreateCompatibleDevice(config,
+                                                       info.width(),
+                                                       info.height(),
+                                                       info.isOpaque(),
+                                                       kGeneral_Usage);
+    if (dev) {
+        return dev;
+    }
+    // fall through to new impl
+#endif
+    return this->onCreateDevice(info, kGeneral_Usage);
+}
+
+SkBaseDevice* SkBaseDevice::createCompatibleDeviceForSaveLayer(const SkImageInfo& info) {
+#ifdef SK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG
+    // We call the old method to support older subclasses.
+    // If they have, we return their device, else we use the new impl.
+    SkBitmap::Config config = SkColorTypeToBitmapConfig(info.colorType());
+    SkBaseDevice* dev = this->onCreateCompatibleDevice(config,
+                                                       info.width(),
+                                                       info.height(),
+                                                       info.isOpaque(),
+                                                       kSaveLayer_Usage);
+    if (dev) {
+        return dev;
+    }
+    // fall through to new impl
+#endif
+    return this->onCreateDevice(info, kSaveLayer_Usage);
+}
+
+#ifdef SK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG
 SkBaseDevice* SkBaseDevice::createCompatibleDevice(SkBitmap::Config config,
                                                    int width, int height,
                                                    bool isOpaque) {
-    return this->onCreateCompatibleDevice(config, width, height,
-                                          isOpaque, kGeneral_Usage);
+    SkImageInfo info = SkImageInfo::Make(width, height,
+                                         SkBitmapConfigToColorType(config),
+                                         isOpaque ? kOpaque_SkAlphaType
+                                                  : kPremul_SkAlphaType);
+    return this->createCompatibleDevice(info);
 }
-
-SkBaseDevice* SkBaseDevice::createCompatibleDeviceForSaveLayer(SkBitmap::Config config,
-                                                               int width, int height,
-                                                               bool isOpaque) {
-    return this->onCreateCompatibleDevice(config, width, height,
-                                          isOpaque, kSaveLayer_Usage);
-}
+#endif
 
 SkMetaData& SkBaseDevice::getMetaData() {
     // metadata users are rare, so we lazily allocate it. If that changes we
diff --git a/src/core/SkDeviceImageFilterProxy.h b/src/core/SkDeviceImageFilterProxy.h
index 800e42c..6c968e9 100644
--- a/src/core/SkDeviceImageFilterProxy.h
+++ b/src/core/SkDeviceImageFilterProxy.h
@@ -15,8 +15,7 @@
     SkDeviceImageFilterProxy(SkBaseDevice* device) : fDevice(device) {}
 
     virtual SkBaseDevice* createDevice(int w, int h) SK_OVERRIDE {
-        return fDevice->createCompatibleDevice(SkBitmap::kARGB_8888_Config,
-                                               w, h, false);
+        return fDevice->createCompatibleDevice(SkImageInfo::MakeN32Premul(w, h));
     }
     virtual bool canHandleImageFilter(const SkImageFilter* filter) SK_OVERRIDE {
         return fDevice->canHandleImageFilter(filter);
diff --git a/src/device/xps/SkXPSDevice.cpp b/src/device/xps/SkXPSDevice.cpp
index f2658de..7b97d3f 100644
--- a/src/device/xps/SkXPSDevice.cpp
+++ b/src/device/xps/SkXPSDevice.cpp
@@ -2418,11 +2418,7 @@
     return false;
 }
 
-SkBaseDevice* SkXPSDevice::onCreateCompatibleDevice(SkBitmap::Config config,
-                                                    int width, int height,
-                                                    bool isOpaque,
-                                                    Usage usage) {
-
+SkBaseDevice* SkXPSDevice::onCreateDevice(const SkImageInfo&, Usage) {
 //Conditional for bug compatibility with PDF device.
 #if 0
     if (SkBaseDevice::kGeneral_Usage == usage) {
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index a3af3c3..0782910 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -157,20 +157,6 @@
     return bitmap;
 }
 
-/*
- *  Calling SkBitmapDevice with individual params asks it to allocate pixel memory.
- *  We never want that, so we always need to call it with a bitmap argument
- *  (which says take my allocate (or lack thereof)).
- *
- *  This is a REALLY good reason to finish the clean-up of SkBaseDevice, and have
- *  SkGpuDevice inherit from that instead of SkBitmapDevice.
- */
-static SkBitmap make_bitmap(SkBitmap::Config config, int width, int height, bool isOpaque) {
-    SkBitmap bm;
-    bm.setConfig(config, width, height, isOpaque);
-    return bm;
-}
-
 SkGpuDevice* SkGpuDevice::Create(GrSurface* surface) {
     SkASSERT(NULL != surface);
     if (NULL == surface->asRenderTarget() || NULL == surface->getContext()) {
@@ -232,18 +218,60 @@
     this->setPixelRef(pr)->unref();
 }
 
+SkGpuDevice* SkGpuDevice::Create(GrContext* context, const SkImageInfo& origInfo,
+                                 int sampleCount) {
+    if (kUnknown_SkColorType == origInfo.colorType() ||
+        origInfo.width() < 0 || origInfo.height() < 0) {
+        return NULL;
+    }
+
+    SkImageInfo info = origInfo;
+    // TODO: perhas we can loosen this check now that colortype is more detailed
+    // e.g. can we support both RGBA and BGRA here?
+    if (kRGB_565_SkColorType == info.colorType()) {
+        info.fAlphaType = kOpaque_SkAlphaType;  // force this setting
+    } else {
+        info.fColorType = kPMColor_SkColorType;
+        if (kOpaque_SkAlphaType != info.alphaType()) {
+            info.fAlphaType = kPremul_SkAlphaType;  // force this setting
+        }
+    }
+
+    GrTextureDesc desc;
+    desc.fFlags = kRenderTarget_GrTextureFlagBit;
+    desc.fWidth = info.width();
+    desc.fHeight = info.height();
+    desc.fConfig = SkImageInfo2GrPixelConfig(info.colorType(), info.alphaType());
+    desc.fSampleCnt = sampleCount;
+
+    SkAutoTUnref<GrTexture> texture(context->createUncachedTexture(desc, NULL, 0));
+    if (!texture.get()) {
+        return NULL;
+    }
+    
+    return SkNEW_ARGS(SkGpuDevice, (context, texture.get()));
+}
+
+#ifdef SK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG
+static SkBitmap make_bitmap(SkBitmap::Config config, int width, int height) {
+    SkBitmap bm;
+    bm.setConfig(SkImageInfo::Make(width, height,
+                                   SkBitmapConfigToColorType(config),
+                                   kPremul_SkAlphaType));
+    return bm;
+}
 SkGpuDevice::SkGpuDevice(GrContext* context,
                          SkBitmap::Config config,
                          int width,
                          int height,
                          int sampleCount)
-    : SkBitmapDevice(make_bitmap(config, width, height, false /*isOpaque*/))
+    : SkBitmapDevice(make_bitmap(config, width, height))
 {
     fDrawProcs = NULL;
-
+    
     fContext = context;
     fContext->ref();
-
+    
 #if SK_DISTANCEFIELD_FONTS
     fMainTextContext = SkNEW_ARGS(GrDistanceFieldTextContext, (fContext, fLeakyProperties));
     fFallbackTextContext = SkNEW_ARGS(GrBitmapTextContext, (fContext, fLeakyProperties));
@@ -251,21 +279,21 @@
     fMainTextContext = SkNEW_ARGS(GrBitmapTextContext, (fContext, fLeakyProperties));
     fFallbackTextContext = NULL;
 #endif
-
+    
     fRenderTarget = NULL;
     fNeedClear = false;
-
+    
     if (config != SkBitmap::kRGB_565_Config) {
         config = SkBitmap::kARGB_8888_Config;
     }
-
+    
     GrTextureDesc desc;
     desc.fFlags = kRenderTarget_GrTextureFlagBit;
     desc.fWidth = width;
     desc.fHeight = height;
     desc.fConfig = SkBitmapConfig2GrPixelConfig(config);
     desc.fSampleCnt = sampleCount;
-
+    
     SkImageInfo info;
     if (!GrPixelConfig2ColorType(desc.fConfig, &info.fColorType)) {
         sk_throw();
@@ -273,15 +301,15 @@
     info.fWidth = width;
     info.fHeight = height;
     info.fAlphaType = kPremul_SkAlphaType;
-
+    
     SkAutoTUnref<GrTexture> texture(fContext->createUncachedTexture(desc, NULL, 0));
-
+    
     if (NULL != texture) {
         fRenderTarget = texture->asRenderTarget();
         fRenderTarget->ref();
-
+        
         SkASSERT(NULL != fRenderTarget);
-
+        
         // wrap the bitmap with a pixelref to expose our texture
         SkGrPixelRef* pr = SkNEW_ARGS(SkGrPixelRef, (info, texture));
         this->setPixelRef(pr)->unref();
@@ -291,6 +319,7 @@
         SkASSERT(false);
     }
 }
+#endif
 
 SkGpuDevice::~SkGpuDevice() {
     if (fDrawProcs) {
@@ -1881,20 +1910,17 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-SkBaseDevice* SkGpuDevice::onCreateCompatibleDevice(SkBitmap::Config config,
-                                                    int width, int height,
-                                                    bool isOpaque,
-                                                    Usage usage) {
+SkBaseDevice* SkGpuDevice::onCreateDevice(const SkImageInfo& info, Usage usage) {
     GrTextureDesc desc;
     desc.fConfig = fRenderTarget->config();
     desc.fFlags = kRenderTarget_GrTextureFlagBit;
-    desc.fWidth = width;
-    desc.fHeight = height;
+    desc.fWidth = info.width();
+    desc.fHeight = info.height();
     desc.fSampleCnt = fRenderTarget->numSamples();
 
     SkAutoTUnref<GrTexture> texture;
     // Skia's convention is to only clear a device if it is non-opaque.
-    bool needClear = !isOpaque;
+    bool needClear = !info.isOpaque();
 
 #if CACHE_COMPATIBLE_DEVICE_TEXTURES
     // layers are never draw in repeat modes, so we can request an approx
@@ -1909,7 +1935,8 @@
     if (NULL != texture.get()) {
         return SkNEW_ARGS(SkGpuDevice,(fContext, texture, needClear));
     } else {
-        GrPrintf("---- failed to create compatible device texture [%d %d]\n", width, height);
+        GrPrintf("---- failed to create compatible device texture [%d %d]\n",
+                 info.width(), info.height());
         return NULL;
     }
 }
@@ -1924,7 +1951,7 @@
     : SkBitmapDevice(make_bitmap(context, texture->asRenderTarget())) {
 
     SkASSERT(texture && texture->asRenderTarget());
-    // This constructor is called from onCreateCompatibleDevice. It has locked the RT in the texture
+    // This constructor is called from onCreateDevice. It has locked the RT in the texture
     // cache. We pass true for the third argument so that it will get unlocked.
     this->initFromRenderTarget(context, texture->asRenderTarget(), true);
     fNeedClear = needClear;
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index fa9fa71..c053e8b 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -260,6 +260,29 @@
     }
 }
 
+// alphatype is ignore for now, but if GrPixelConfig is expanded to encompass
+// alpha info, that will be considered.
+GrPixelConfig SkImageInfo2GrPixelConfig(SkColorType ct, SkAlphaType) {
+    switch (ct) {
+        case kUnknown_SkColorType:
+            return kUnknown_GrPixelConfig;
+        case kAlpha_8_SkColorType:
+            return kAlpha_8_GrPixelConfig;
+        case kRGB_565_SkColorType:
+            return kRGB_565_GrPixelConfig;
+        case kARGB_4444_SkColorType:
+            return kRGBA_4444_GrPixelConfig;
+        case kRGBA_8888_SkColorType:
+            return kRGBA_8888_GrPixelConfig;
+        case kBGRA_8888_SkColorType:
+            return kBGRA_8888_GrPixelConfig;
+        case kIndex_8_SkColorType:
+            return kIndex_8_GrPixelConfig;
+    }
+    SkASSERT(0);    // shouldn't get here
+    return kUnknown_GrPixelConfig;
+}
+
 bool GrPixelConfig2ColorType(GrPixelConfig config, SkColorType* ctOut) {
     SkColorType ct;
     switch (config) {
diff --git a/src/image/SkSurface_Gpu.cpp b/src/image/SkSurface_Gpu.cpp
index 58f9ef3..d46d8bc 100644
--- a/src/image/SkSurface_Gpu.cpp
+++ b/src/image/SkSurface_Gpu.cpp
@@ -14,7 +14,6 @@
 public:
     SK_DECLARE_INST_COUNT(SkSurface_Gpu)
 
-    SkSurface_Gpu(GrContext*, const SkImageInfo&, int sampleCount);
     SkSurface_Gpu(GrRenderTarget*);
     virtual ~SkSurface_Gpu();
 
@@ -33,18 +32,6 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-SkSurface_Gpu::SkSurface_Gpu(GrContext* ctx, const SkImageInfo& info,
-                             int sampleCount)
-        : INHERITED(info.fWidth, info.fHeight) {
-    SkBitmap::Config config = SkImageInfoToBitmapConfig(info);
-
-    fDevice = SkNEW_ARGS(SkGpuDevice, (ctx, config, info.fWidth, info.fHeight, sampleCount));
-
-    if (!SkAlphaTypeIsOpaque(info.fAlphaType)) {
-        fDevice->clear(0x0);
-    }
-}
-
 SkSurface_Gpu::SkSurface_Gpu(GrRenderTarget* renderTarget)
         : INHERITED(renderTarget->width(), renderTarget->height()) {
     fDevice = SkNEW_ARGS(SkGpuDevice, (renderTarget->getContext(), renderTarget));
@@ -85,9 +72,10 @@
     // are we sharing our render target with the image?
     SkASSERT(NULL != this->getCachedImage());
     if (rt->asTexture() == SkTextureImageGetTexture(this->getCachedImage())) {
-        SkAutoTUnref<SkGpuDevice> newDevice(SkNEW_ARGS(SkGpuDevice,
-            (fDevice->context(), fDevice->config(), fDevice->width(),
-             fDevice->height(), rt->numSamples())));
+        SkAutoTUnref<SkGpuDevice> newDevice(SkGpuDevice::Create(fDevice->context(),
+                                                     fDevice->imageInfo(),
+                                                     rt->numSamples()));
+        SkASSERT(newDevice.get());
 
         if (kRetain_ContentChangeMode == mode) {
             fDevice->context()->copyTexture(rt->asTexture(),
diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp
index d227dd7..9487dfd 100644
--- a/src/pdf/SkPDFDevice.cpp
+++ b/src/pdf/SkPDFDevice.cpp
@@ -585,13 +585,10 @@
     }
 }
 
-SkBaseDevice* SkPDFDevice::onCreateCompatibleDevice(SkBitmap::Config config,
-                                                    int width, int height,
-                                                    bool isOpaque,
-                                                    Usage usage) {
+SkBaseDevice* SkPDFDevice::onCreateDevice(const SkImageInfo& info, Usage usage) {
     SkMatrix initialTransform;
     initialTransform.reset();
-    SkISize size = SkISize::Make(width, height);
+    SkISize size = SkISize::Make(info.width(), info.height());
     return SkNEW_ARGS(SkPDFDevice, (size, size, initialTransform));
 }
 
diff --git a/src/utils/SkDeferredCanvas.cpp b/src/utils/SkDeferredCanvas.cpp
index de9148b..fc85711 100644
--- a/src/utils/SkDeferredCanvas.cpp
+++ b/src/utils/SkDeferredCanvas.cpp
@@ -168,10 +168,7 @@
 
     virtual GrRenderTarget* accessRenderTarget() SK_OVERRIDE;
 
-    virtual SkBaseDevice* onCreateCompatibleDevice(SkBitmap::Config config,
-                                                   int width, int height,
-                                                   bool isOpaque,
-                                                   Usage usage) SK_OVERRIDE;
+    virtual SkBaseDevice* onCreateDevice(const SkImageInfo&, Usage) SK_OVERRIDE;
 
     virtual void writePixels(const SkBitmap& bitmap, int x, int y,
                                 SkCanvas::Config8888 config8888) SK_OVERRIDE;
@@ -515,10 +512,7 @@
     return immediateDevice()->accessBitmap(false);
 }
 
-SkBaseDevice* DeferredDevice::onCreateCompatibleDevice(
-    SkBitmap::Config config, int width, int height, bool isOpaque,
-    Usage usage) {
-
+SkBaseDevice* DeferredDevice::onCreateDevice(const SkImageInfo& info, Usage usage) {
     // Save layer usage not supported, and not required by SkDeferredCanvas.
     SkASSERT(usage != kSaveLayer_Usage);
     // Create a compatible non-deferred device.
@@ -526,7 +520,7 @@
     // will not be used with a deferred canvas (there is no API for that).
     // And connecting a DeferredDevice to non-deferred canvas can result
     // in unpredictable behavior.
-    return immediateDevice()->createCompatibleDevice(config, width, height, isOpaque);
+    return immediateDevice()->createCompatibleDevice(info);
 }
 
 SkSurface* DeferredDevice::newSurface(const SkImageInfo& info) {
diff --git a/src/utils/SkGatherPixelRefsAndRects.h b/src/utils/SkGatherPixelRefsAndRects.h
index 5159525..90ab0f6 100644
--- a/src/utils/SkGatherPixelRefsAndRects.h
+++ b/src/utils/SkGatherPixelRefsAndRects.h
@@ -28,7 +28,9 @@
         fSize.set(width, height);
         fPRCont = prCont;
         SkSafeRef(fPRCont);
-        fEmptyBitmap.setConfig(SkBitmap::kNo_Config, width, height);
+        fEmptyBitmap.setConfig(SkImageInfo::Make(width, height,
+                                                 kUnknown_SkColorType,
+                                                 kIgnore_SkAlphaType));
     }
 
     virtual ~SkGatherPixelRefsAndRectsDevice() {
@@ -43,6 +45,10 @@
     virtual SkBitmap::Config config() const SK_OVERRIDE {
         return SkBitmap::kNo_Config;
     }
+    virtual SkImageInfo imageInfo() const SK_OVERRIDE {
+        return fEmptyBitmap.info();
+    }
+
     virtual void writePixels(const SkBitmap& bitmap, int x, int y,
                              SkCanvas::Config8888 config8888) SK_OVERRIDE {
         NotSupported();
@@ -326,13 +332,11 @@
         NotSupported();
     }
 
-    virtual SkBaseDevice* onCreateCompatibleDevice(SkBitmap::Config config,
-                                                   int width, int height,
-                                                   bool isOpaque,
-                                                   Usage usage) SK_OVERRIDE {
+    virtual SkBaseDevice* onCreateDevice(const SkImageInfo& info, Usage usage) SK_OVERRIDE {
         // we expect to only get called via savelayer, in which case it is fine.
         SkASSERT(kSaveLayer_Usage == usage);
-        return SkNEW_ARGS(SkGatherPixelRefsAndRectsDevice, (width, height, fPRCont));
+        return SkNEW_ARGS(SkGatherPixelRefsAndRectsDevice,
+                          (info.width(), info.height(), fPRCont));
     }
 
     virtual void flush() SK_OVERRIDE {}
diff --git a/src/utils/SkPictureUtils.cpp b/src/utils/SkPictureUtils.cpp
index 92d0487..a7ec7ae 100644
--- a/src/utils/SkPictureUtils.cpp
+++ b/src/utils/SkPictureUtils.cpp
@@ -172,13 +172,10 @@
     virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) SK_OVERRIDE {
         not_supported();
     }
-    virtual SkBaseDevice* onCreateCompatibleDevice(SkBitmap::Config config,
-                                                   int width, int height,
-                                                   bool isOpaque,
-                                                   Usage usage) SK_OVERRIDE {
+    virtual SkBaseDevice* onCreateDevice(const SkImageInfo& info, Usage usage) SK_OVERRIDE {
         // we expect to only get called via savelayer, in which case it is fine.
         SkASSERT(kSaveLayer_Usage == usage);
-        return SkNEW_ARGS(GatherPixelRefDevice, (width, height, fPRSet));
+        return SkNEW_ARGS(GatherPixelRefDevice, (info.width(), info.height(), fPRSet));
     }
     virtual void flush() SK_OVERRIDE {}
 
diff --git a/tests/CanvasStateTest.cpp b/tests/CanvasStateTest.cpp
index 7c441a4..29e67f2 100644
--- a/tests/CanvasStateTest.cpp
+++ b/tests/CanvasStateTest.cpp
@@ -186,8 +186,9 @@
 
 static void test_draw_filters(skiatest::Reporter* reporter) {
     TestDrawFilter drawFilter;
-    SkBitmapDevice device(SkBitmap::kARGB_8888_Config, 10, 10);
-    SkCanvas canvas(&device);
+    SkBitmap bitmap;
+    bitmap.allocN32Pixels(10, 10);
+    SkCanvas canvas(bitmap);
 
     canvas.setDrawFilter(&drawFilter);
 
@@ -209,8 +210,9 @@
 static void error_callback(SkError code, void* ctx) {}
 
 static void test_soft_clips(skiatest::Reporter* reporter) {
-    SkBitmapDevice device(SkBitmap::kARGB_8888_Config, 10, 10);
-    SkCanvas canvas(&device);
+    SkBitmap bitmap;
+    bitmap.allocN32Pixels(10, 10);
+    SkCanvas canvas(bitmap);
 
     SkRRect roundRect;
     roundRect.setOval(SkRect::MakeWH(5, 5));
diff --git a/tests/GpuBitmapCopyTest.cpp b/tests/GpuBitmapCopyTest.cpp
index fb81e2b..08ceff2 100644
--- a/tests/GpuBitmapCopyTest.cpp
+++ b/tests/GpuBitmapCopyTest.cpp
@@ -122,18 +122,32 @@
             return;
         }
         static const Pair gPairs[] = {
-            { SkBitmap::kNo_Config,         "00"  },
-            { SkBitmap::kARGB_8888_Config,  "01"  },
+            // SkGpuDevice can no longer be Create()ed with kNo_Config
+            // (or kUnknown_SkColorType in the new world), hence much of this
+            // test will be skipped, since it was checking that calling
+            // copyTo or deepCopyTo with src or dst set to kUnknown/kNo would
+            // successfully fail.
+            //
+            // If we can declare that you can *never* create a texture with
+            // kUnknown, then perhaps we can remove this entire test...
+            //
+//            { SkBitmap::kNo_Config,         "00"  },
+//            { SkBitmap::kARGB_8888_Config,  "01"  },
+            { SkBitmap::kARGB_8888_Config,  "1"  },
         };
 
         const int W = 20;
         const int H = 33;
 
         for (size_t i = 0; i < SK_ARRAY_COUNT(gPairs); i++) {
+            SkImageInfo info = SkImageInfo::Make(W, H,
+                                                 SkBitmapConfigToColorType(gPairs[i].fConfig),
+                                                 kPremul_SkAlphaType);
             SkBitmap src, dst;
 
-            SkGpuDevice* device = SkNEW_ARGS(SkGpuDevice, (grContext, gPairs[i].fConfig, W, H));
-            SkAutoUnref aur(device);
+            SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(grContext, info, 0));
+            SkASSERT(device.get());
+
             src = device->accessBitmap(false);
             device->clear(SK_ColorWHITE);
 
diff --git a/tests/ImageFilterTest.cpp b/tests/ImageFilterTest.cpp
index 59504cf..41af243 100644
--- a/tests/ImageFilterTest.cpp
+++ b/tests/ImageFilterTest.cpp
@@ -296,7 +296,9 @@
 #if SK_SUPPORT_GPU
 DEF_GPUTEST(ImageFilterCropRectGPU, reporter, factory) {
     GrContext* context = factory->get(static_cast<GrContextFactory::GLContextType>(0));
-    SkGpuDevice device(context, SkBitmap::kARGB_8888_Config, 100, 100);
-    test_crop_rects(&device, reporter);
+    SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(context,
+                                                         SkImageInfo::MakeN32Premul(100, 100),
+                                                         0));
+    test_crop_rects(device, reporter);
 }
 #endif
diff --git a/tests/LayerDrawLooperTest.cpp b/tests/LayerDrawLooperTest.cpp
index 8f8a6b6..68dd5e0 100644
--- a/tests/LayerDrawLooperTest.cpp
+++ b/tests/LayerDrawLooperTest.cpp
@@ -18,9 +18,15 @@
 #include "SkXfermode.h"
 #include "Test.h"
 
+static SkBitmap make_bm(int w, int h) {
+    SkBitmap bm;
+    bm.allocN32Pixels(w, h);
+    return bm;
+}
+
 class FakeDevice : public SkBitmapDevice {
 public:
-    FakeDevice() : SkBitmapDevice(SkBitmap::kARGB_8888_Config, 100, 100, false) { }
+    FakeDevice() : SkBitmapDevice(make_bm(100, 100)) { }
 
     virtual void drawRect(const SkDraw& draw, const SkRect& r,
                           const SkPaint& paint) SK_OVERRIDE {
diff --git a/tests/PremulAlphaRoundTripTest.cpp b/tests/PremulAlphaRoundTripTest.cpp
index 5e8e8bf..488d93e 100644
--- a/tests/PremulAlphaRoundTripTest.cpp
+++ b/tests/PremulAlphaRoundTripTest.cpp
@@ -36,6 +36,8 @@
 };
 
 DEF_GPUTEST(PremulAlphaRoundTrip, reporter, factory) {
+    const SkImageInfo info = SkImageInfo::MakeN32Premul(256, 256);
+
     SkAutoTUnref<SkBaseDevice> device;
     for (int dtype = 0; dtype < 2; ++dtype) {
 
@@ -47,10 +49,7 @@
 #endif
         for (int glCtxType = 0; glCtxType < glCtxTypeCnt; ++glCtxType) {
             if (0 == dtype) {
-                device.reset(new SkBitmapDevice(SkBitmap::kARGB_8888_Config,
-                                                256,
-                                                256,
-                                                false));
+                device.reset(SkBitmapDevice::Create(info));
             } else {
 #if SK_SUPPORT_GPU
                 GrContextFactory::GLContextType type =
@@ -63,7 +62,7 @@
                     continue;
                 }
 
-                device.reset(new SkGpuDevice(context, SkBitmap::kARGB_8888_Config, 256, 256));
+                device.reset(SkGpuDevice::Create(context, info, 0));
 #else
                 continue;
 #endif
diff --git a/tests/ReadPixelsTest.cpp b/tests/ReadPixelsTest.cpp
index 8f1e0d6..d14e989 100644
--- a/tests/ReadPixelsTest.cpp
+++ b/tests/ReadPixelsTest.cpp
@@ -310,8 +310,8 @@
         for (int glCtxType = 0; glCtxType < glCtxTypeCnt; ++glCtxType) {
             SkAutoTUnref<SkBaseDevice> device;
             if (0 == dtype) {
-                device.reset(new SkBitmapDevice(SkBitmap::kARGB_8888_Config,
-                                                DEV_W, DEV_H, false));
+                SkImageInfo info = SkImageInfo::MakeN32Premul(DEV_W, DEV_H);
+                device.reset(SkBitmapDevice::Create(info));
             } else {
 #if SK_SUPPORT_GPU
                 GrContextFactory::GLContextType type =