Rename GrAccelData to SkLayerInfo and move it to src/core

Review URL: https://codereview.chromium.org/719133002
diff --git a/gyp/core.gypi b/gyp/core.gypi
index 120a635..abd4a5c 100644
--- a/gyp/core.gypi
+++ b/gyp/core.gypi
@@ -105,6 +105,8 @@
         '<(skia_src_path)/core/SkImageFilter.cpp',
         '<(skia_src_path)/core/SkImageInfo.cpp',
         '<(skia_src_path)/core/SkImageGenerator.cpp',
+        '<(skia_src_path)/core/SkLayerInfo.h',
+        '<(skia_src_path)/core/SkLayerInfo.cpp',
         '<(skia_src_path)/core/SkLocalMatrixShader.cpp',
         '<(skia_src_path)/core/SkLineClipper.cpp',
         '<(skia_src_path)/core/SkMallocPixelRef.cpp',
diff --git a/gyp/gpu.gypi b/gyp/gpu.gypi
index 2cf380b..430bac9 100644
--- a/gyp/gpu.gypi
+++ b/gyp/gpu.gypi
@@ -123,8 +123,6 @@
       '<(skia_src_path)/gpu/GrProgramElement.cpp',
       '<(skia_src_path)/gpu/GrProcessor.cpp',
       '<(skia_src_path)/gpu/GrGpuResourceRef.cpp',
-      '<(skia_src_path)/gpu/GrPictureUtils.h',
-      '<(skia_src_path)/gpu/GrPictureUtils.cpp',
       '<(skia_src_path)/gpu/GrPlotMgr.h',
       '<(skia_src_path)/gpu/GrRecordReplaceDraw.cpp',
       '<(skia_src_path)/gpu/GrRecordReplaceDraw.h',
diff --git a/include/core/SkPicture.h b/include/core/SkPicture.h
index 41d5c1c..4bef2b0 100644
--- a/include/core/SkPicture.h
+++ b/include/core/SkPicture.h
@@ -46,8 +46,7 @@
     SK_DECLARE_INST_COUNT(SkPicture)
 
     // AccelData provides a base class for device-specific acceleration
-    // data. It is added to the picture via a call to a device's optimize
-    // method.
+    // data. It is added to the picture via EXPERIMENTAL_addAccelData.
     class AccelData : public SkRefCnt {
     public:
         typedef uint8_t Domain;
diff --git a/src/core/SkLayerInfo.cpp b/src/core/SkLayerInfo.cpp
new file mode 100644
index 0000000..d427fa7
--- /dev/null
+++ b/src/core/SkLayerInfo.cpp
@@ -0,0 +1,15 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkLayerInfo.h"
+
+SkPicture::AccelData::Key SkLayerInfo::ComputeKey() {
+    static const SkPicture::AccelData::Key gGPUID = SkPicture::AccelData::GenerateDomain();
+
+    return gGPUID;
+}
+
diff --git a/src/gpu/GrPictureUtils.h b/src/core/SkLayerInfo.h
similarity index 61%
rename from src/gpu/GrPictureUtils.h
rename to src/core/SkLayerInfo.h
index f249105..dd0eaf0 100644
--- a/src/gpu/GrPictureUtils.h
+++ b/src/core/SkLayerInfo.h
@@ -5,24 +5,24 @@
  * found in the LICENSE file.
  */
 
-#ifndef GrPictureUtils_DEFINED
-#define GrPictureUtils_DEFINED
+#ifndef SkLayerInfo_DEFINED
+#define SkLayerInfo_DEFINED
 
 #include "SkPicture.h"
 #include "SkTArray.h"
 
-// This class encapsulates the GPU-backend-specific acceleration data
-// for a single SkPicture
-class GrAccelData : public SkPicture::AccelData {
+// This class stores information about the saveLayer/restore pairs found
+// within an SkPicture. It is used by Ganesh to perform layer hoisting.
+class SkLayerInfo : public SkPicture::AccelData {
 public:
-    // Information about a given saveLayer in an SkPicture
-    class SaveLayerInfo {
+    // Information about a given saveLayer/restore block in an SkPicture
+    class BlockInfo {
     public:
-        SaveLayerInfo() : fPicture(NULL), fPaint(NULL) {}
-        ~SaveLayerInfo() { SkSafeUnref(fPicture); SkDELETE(fPaint); }
+        BlockInfo() : fPicture(NULL), fPaint(NULL) {}
+        ~BlockInfo() { SkSafeUnref(fPicture); SkDELETE(fPaint); }
 
         // The picture owning the layer. If the owning picture is the top-most
-        // one (i.e., the picture for which this GrAccelData was created) then
+        // one (i.e., the picture for which this SkLayerInfo was created) then
         // this pointer is NULL. If it is a nested picture then the pointer
         // is non-NULL and owns a ref on the picture.
         const SkPicture* fPicture;
@@ -41,9 +41,9 @@
         SkMatrix fLocalMat;
         // The paint to use on restore. Can be NULL since it is optional.
         const SkPaint* fPaint;
-        // The ID of this saveLayer in the picture. 0 is an invalid ID.
+        // The index of this saveLayer in the picture.
         size_t  fSaveLayerOpID;
-        // The ID of the matching restore in the picture. 0 is an invalid ID.
+        // The index of the matching restore in the picture.
         size_t  fRestoreOpID;
         // True if this saveLayer has at least one other saveLayer nested within it.
         // False otherwise.
@@ -52,28 +52,26 @@
         bool    fIsNested;
     };
 
-    GrAccelData(Key key) : INHERITED(key) { }
+    SkLayerInfo(Key key) : INHERITED(key) { }
 
-    virtual ~GrAccelData() { }
+    BlockInfo& addBlock() { return fBlocks.push_back(); }
 
-    SaveLayerInfo& addSaveLayerInfo() { return fSaveLayerInfo.push_back(); }
+    int numBlocks() const { return fBlocks.count(); }
 
-    int numSaveLayers() const { return fSaveLayerInfo.count(); }
+    const BlockInfo& block(int index) const {
+        SkASSERT(index < fBlocks.count());
 
-    const SaveLayerInfo& saveLayerInfo(int index) const {
-        SkASSERT(index < fSaveLayerInfo.count());
-
-        return fSaveLayerInfo[index];
+        return fBlocks[index];
     }
 
     // We may, in the future, need to pass in the GPUDevice in order to
     // incorporate the clip and matrix state into the key
-    static SkPicture::AccelData::Key ComputeAccelDataKey();
+    static SkPicture::AccelData::Key ComputeKey();
 
 private:
-    SkTArray<SaveLayerInfo, true> fSaveLayerInfo;
+    SkTArray<BlockInfo, true> fBlocks;
 
     typedef SkPicture::AccelData INHERITED;
 };
 
-#endif // GrPictureUtils_DEFINED
+#endif // SkLayerInfo_DEFINED
diff --git a/src/core/SkPictureRecorder.cpp b/src/core/SkPictureRecorder.cpp
index 1604467..3441a0d 100644
--- a/src/core/SkPictureRecorder.cpp
+++ b/src/core/SkPictureRecorder.cpp
@@ -5,6 +5,7 @@
  * found in the LICENSE file.
  */
 
+#include "SkLayerInfo.h"
 #include "SkPictureRecorder.h"
 #include "SkRecord.h"
 #include "SkRecordDraw.h"
@@ -12,12 +13,6 @@
 #include "SkRecordOpts.h"
 #include "SkTypes.h"
 
-// Must place SK_SUPPORT_GPU after other includes so it is defined in the
-// Android framework build.
-#if SK_SUPPORT_GPU
-#include "GrPictureUtils.h"
-#endif
-
 SkPictureRecorder::SkPictureRecorder() {}
 
 SkPictureRecorder::~SkPictureRecorder() {}
@@ -47,37 +42,29 @@
     // TODO: delay as much of this work until just before first playback?
     SkRecordOptimize(fRecord);
 
-#if SK_SUPPORT_GPU
-    SkAutoTUnref<GrAccelData> saveLayerData;
+    SkAutoTUnref<SkLayerInfo> saveLayerData;
 
     if (fBBH && (fFlags & kComputeSaveLayerInfo_RecordFlag)) {
-        SkPicture::AccelData::Key key = GrAccelData::ComputeAccelDataKey();
+        SkPicture::AccelData::Key key = SkLayerInfo::ComputeKey();
 
-        saveLayerData.reset(SkNEW_ARGS(GrAccelData, (key)));
+        saveLayerData.reset(SkNEW_ARGS(SkLayerInfo, (key)));
     }
-#endif
 
     if (fBBH.get()) {
         SkRect cullRect = SkRect::MakeWH(fCullWidth, fCullHeight);
 
-#if SK_SUPPORT_GPU
         if (saveLayerData) {
             SkRecordComputeLayers(cullRect, *fRecord, fBBH.get(), saveLayerData);
         } else {
-#endif
             SkRecordFillBounds(cullRect, *fRecord, fBBH.get());
-#if SK_SUPPORT_GPU
         }
-#endif
     }
 
     SkPicture* pict = SkNEW_ARGS(SkPicture, (fCullWidth, fCullHeight, fRecord.detach(), fBBH.get()));
 
-#if SK_SUPPORT_GPU
     if (saveLayerData) {
         pict->EXPERIMENTAL_addAccelData(saveLayerData);
     }
-#endif
 
     return pict;
 }
diff --git a/src/core/SkRecordDraw.cpp b/src/core/SkRecordDraw.cpp
index 9075e50..e35e5a0 100644
--- a/src/core/SkRecordDraw.cpp
+++ b/src/core/SkRecordDraw.cpp
@@ -5,13 +5,10 @@
  * found in the LICENSE file.
  */
 
+#include "SkLayerInfo.h"
 #include "SkRecordDraw.h"
 #include "SkPatchUtils.h"
 
-#if SK_SUPPORT_GPU
-#include "GrPictureUtils.h"
-#endif
-
 void SkRecordDraw(const SkRecord& record,
                   SkCanvas* canvas,
                   const SkBBoxHierarchy* bbh,
@@ -570,11 +567,10 @@
     SkTDArray<unsigned>   fControlIndices;
 };
 
-#if SK_SUPPORT_GPU
 // SkRecord visitor to gather saveLayer/restore information.
 class CollectLayers : SkNoncopyable {
 public:
-    CollectLayers(const SkRect& cullRect, const SkRecord& record, GrAccelData* accelData)
+    CollectLayers(const SkRect& cullRect, const SkRecord& record, SkLayerInfo* accelData)
         : fSaveLayersInStack(0)
         , fAccelData(accelData)
         , fFillBounds(cullRect, record) {
@@ -624,10 +620,10 @@
     void trackSaveLayers(const DrawPicture& dp) {
         // For sub-pictures, we wrap their layer information within the parent
         // picture's rendering hierarchy
-        SkPicture::AccelData::Key key = GrAccelData::ComputeAccelDataKey();
+        SkPicture::AccelData::Key key = SkLayerInfo::ComputeKey();
 
-        const GrAccelData* childData =
-            static_cast<const GrAccelData*>(dp.picture->EXPERIMENTAL_getAccelData(key));
+        const SkLayerInfo* childData =
+            static_cast<const SkLayerInfo*>(dp.picture->EXPERIMENTAL_getAccelData(key));
         if (!childData) {
             // If the child layer hasn't been generated with saveLayer data we
             // assume the worst (i.e., that it does contain layers which nest
@@ -638,8 +634,8 @@
             return;
         }
 
-        for (int i = 0; i < childData->numSaveLayers(); ++i) {
-            const GrAccelData::SaveLayerInfo& src = childData->saveLayerInfo(i);
+        for (int i = 0; i < childData->numBlocks(); ++i) {
+            const SkLayerInfo::BlockInfo& src = childData->block(i);
 
             FillBounds::Bounds newBound = fFillBounds.adjustAndMap(src.fBounds, dp.paint);
             if (newBound.isEmpty()) {
@@ -648,7 +644,7 @@
 
             this->updateStackForSaveLayer();
 
-            GrAccelData::SaveLayerInfo& dst = fAccelData->addSaveLayerInfo();
+            SkLayerInfo::BlockInfo& dst = fAccelData->addBlock();
 
             // If src.fPicture is NULL the layer is in dp.picture; otherwise
             // it belongs to a sub-picture.
@@ -706,30 +702,29 @@
 
         --fSaveLayersInStack;
 
-        GrAccelData::SaveLayerInfo& slInfo = fAccelData->addSaveLayerInfo();
+        SkLayerInfo::BlockInfo& block = fAccelData->addBlock();
 
-        SkASSERT(NULL == slInfo.fPicture);  // This layer is in the top-most picture
+        SkASSERT(NULL == block.fPicture);  // This layer is in the top-most picture
 
-        slInfo.fBounds = fFillBounds.getBounds(sli.fStartIndex);
-        slInfo.fLocalMat = fFillBounds.ctm();
-        slInfo.fPreMat = SkMatrix::I();
+        block.fBounds = fFillBounds.getBounds(sli.fStartIndex);
+        block.fLocalMat = fFillBounds.ctm();
+        block.fPreMat = SkMatrix::I();
         if (sli.fPaint) {
-            slInfo.fPaint = SkNEW_ARGS(SkPaint, (*sli.fPaint));
+            block.fPaint = SkNEW_ARGS(SkPaint, (*sli.fPaint));
         }
-        slInfo.fSaveLayerOpID = sli.fStartIndex;
-        slInfo.fRestoreOpID = fFillBounds.currentOp();
-        slInfo.fHasNestedLayers = sli.fHasNestedSaveLayer;
-        slInfo.fIsNested = fSaveLayersInStack > 0;
+        block.fSaveLayerOpID = sli.fStartIndex;
+        block.fRestoreOpID = fFillBounds.currentOp();
+        block.fHasNestedLayers = sli.fHasNestedSaveLayer;
+        block.fIsNested = fSaveLayersInStack > 0;
     }
 
     // Used to collect saveLayer information for layer hoisting
     int                   fSaveLayersInStack;
     SkTDArray<SaveLayerInfo> fSaveLayerStack;
-    GrAccelData*          fAccelData;
+    SkLayerInfo*          fAccelData;
 
     SkRecords::FillBounds fFillBounds;
 };
-#endif
 
 }  // namespace SkRecords
 
@@ -744,9 +739,8 @@
     visitor.cleanUp(bbh);
 }
 
-#if SK_SUPPORT_GPU
 void SkRecordComputeLayers(const SkRect& cullRect, const SkRecord& record,
-                           SkBBoxHierarchy* bbh, GrAccelData* data) {
+                           SkBBoxHierarchy* bbh, SkLayerInfo* data) {
     SkRecords::CollectLayers visitor(cullRect, record, data);
 
     for (unsigned curOp = 0; curOp < record.count(); curOp++) {
@@ -756,5 +750,4 @@
 
     visitor.cleanUp(bbh);
 }
-#endif
 
diff --git a/src/core/SkRecordDraw.h b/src/core/SkRecordDraw.h
index 8df64cb..9b39dd6 100644
--- a/src/core/SkRecordDraw.h
+++ b/src/core/SkRecordDraw.h
@@ -14,15 +14,13 @@
 #include "SkMatrix.h"
 #include "SkRecord.h"
 
+class SkLayerInfo;
+
 // Fill a BBH to be used by SkRecordDraw to accelerate playback.
 void SkRecordFillBounds(const SkRect& cullRect, const SkRecord&, SkBBoxHierarchy*);
 
-#if SK_SUPPORT_GPU
-class GrAccelData;
-
 void SkRecordComputeLayers(const SkRect& cullRect, const SkRecord& record,
-                           SkBBoxHierarchy* bbh, GrAccelData* data);
-#endif
+                           SkBBoxHierarchy* bbh, SkLayerInfo* data);
 
 // Draw an SkRecord into an SkCanvas.  A convenience wrapper around SkRecords::Draw.
 void SkRecordDraw(const SkRecord&, SkCanvas*, const SkBBoxHierarchy*, SkDrawPictureCallback*);
diff --git a/src/gpu/GrLayerCache.h b/src/gpu/GrLayerCache.h
index 69b59cf..8dec8e5 100644
--- a/src/gpu/GrLayerCache.h
+++ b/src/gpu/GrLayerCache.h
@@ -9,15 +9,13 @@
 #define GrLayerCache_DEFINED
 
 #include "GrAtlas.h"
-#include "GrPictureUtils.h"
 #include "GrRect.h"
 
 #include "SkChecksum.h"
 #include "SkMessageBus.h"
+#include "SkPicture.h"
 #include "SkTDynamicHash.h"
 
-class SkPicture;
-
 // Set to 0 to disable caching of hoisted layers
 #define GR_CACHE_HOISTED_LAYERS 0
 
diff --git a/src/gpu/GrLayerHoister.cpp b/src/gpu/GrLayerHoister.cpp
index c74913d..bc635ae 100644
--- a/src/gpu/GrLayerHoister.cpp
+++ b/src/gpu/GrLayerHoister.cpp
@@ -11,6 +11,7 @@
 
 #include "SkCanvas.h"
 #include "SkGrPixelRef.h"
+#include "SkLayerInfo.h"
 #include "SkRecordDraw.h"
 #include "SkSurface.h"
 
@@ -18,7 +19,7 @@
 // required texture/render target resources.
 static void prepare_for_hoisting(GrLayerCache* layerCache, 
                                  const SkPicture* topLevelPicture,
-                                 const GrAccelData::SaveLayerInfo& info,
+                                 const SkLayerInfo::BlockInfo& info,
                                  const SkIRect& layerRect,
                                  SkTDArray<GrHoistedLayer>* needRendering,
                                  SkTDArray<GrHoistedLayer>* recycled,
@@ -93,22 +94,22 @@
 
     layerCache->processDeletedPictures();
 
-    SkPicture::AccelData::Key key = GrAccelData::ComputeAccelDataKey();
+    SkPicture::AccelData::Key key = SkLayerInfo::ComputeKey();
 
     const SkPicture::AccelData* topLevelData = topLevelPicture->EXPERIMENTAL_getAccelData(key);
     if (!topLevelData) {
         return;
     }
 
-    const GrAccelData *topLevelGPUData = static_cast<const GrAccelData*>(topLevelData);
-    if (0 == topLevelGPUData->numSaveLayers()) {
+    const SkLayerInfo *topLevelGPUData = static_cast<const SkLayerInfo*>(topLevelData);
+    if (0 == topLevelGPUData->numBlocks()) {
         return;
     }
 
-    atlased->setReserve(atlased->count() + topLevelGPUData->numSaveLayers());
+    atlased->setReserve(atlased->count() + topLevelGPUData->numBlocks());
 
-    for (int i = 0; i < topLevelGPUData->numSaveLayers(); ++i) {
-        const GrAccelData::SaveLayerInfo& info = topLevelGPUData->saveLayerInfo(i);
+    for (int i = 0; i < topLevelGPUData->numBlocks(); ++i) {
+        const SkLayerInfo::BlockInfo& info = topLevelGPUData->block(i);
 
         // TODO: ignore perspective projected layers here?
         bool disallowAtlasing = info.fHasNestedLayers || info.fIsNested ||
@@ -145,21 +146,21 @@
 
     layerCache->processDeletedPictures();
 
-    SkPicture::AccelData::Key key = GrAccelData::ComputeAccelDataKey();
+    SkPicture::AccelData::Key key = SkLayerInfo::ComputeKey();
 
     const SkPicture::AccelData* topLevelData = topLevelPicture->EXPERIMENTAL_getAccelData(key);
     if (!topLevelData) {
         return;
     }
 
-    const GrAccelData *topLevelGPUData = static_cast<const GrAccelData*>(topLevelData);
-    if (0 == topLevelGPUData->numSaveLayers()) {
+    const SkLayerInfo *topLevelGPUData = static_cast<const SkLayerInfo*>(topLevelData);
+    if (0 == topLevelGPUData->numBlocks()) {
         return;
     }
 
     // Find and prepare for hoisting all the layers that intersect the query rect
-    for (int i = 0; i < topLevelGPUData->numSaveLayers(); ++i) {
-        const GrAccelData::SaveLayerInfo& info = topLevelGPUData->saveLayerInfo(i);
+    for (int i = 0; i < topLevelGPUData->numBlocks(); ++i) {
+        const SkLayerInfo::BlockInfo& info = topLevelGPUData->block(i);
         if (info.fIsNested) {
             // Parent layers are currently hoisted while nested layers are not.
             continue;
diff --git a/src/gpu/GrLayerHoister.h b/src/gpu/GrLayerHoister.h
index 0780c1e..12d8a84 100644
--- a/src/gpu/GrLayerHoister.h
+++ b/src/gpu/GrLayerHoister.h
@@ -11,7 +11,6 @@
 #include "SkPicture.h"
 #include "SkTDArray.h"
 
-class GrAccelData;
 struct GrCachedLayer;
 class GrReplacements;
 struct SkRect;
diff --git a/src/gpu/GrPictureUtils.cpp b/src/gpu/GrPictureUtils.cpp
deleted file mode 100644
index e8e965b..0000000
--- a/src/gpu/GrPictureUtils.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "GrPictureUtils.h"
-
-#include "SkBBoxHierarchy.h"
-#include "SkPaintPriv.h"
-#include "SkPatchUtils.h"
-#include "SkRecord.h"
-#include "SkRecords.h"
-
-SkPicture::AccelData::Key GrAccelData::ComputeAccelDataKey() {
-    static const SkPicture::AccelData::Key gGPUID = SkPicture::AccelData::GenerateDomain();
-
-    return gGPUID;
-}
-
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 06f6eb7..124f994 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -15,9 +15,7 @@
 #include "GrContext.h"
 #include "GrBitmapTextContext.h"
 #include "GrDistanceFieldTextContext.h"
-#include "GrLayerCache.h"
 #include "GrLayerHoister.h"
-#include "GrPictureUtils.h"
 #include "GrRecordReplaceDraw.h"
 #include "GrStrokeInfo.h"
 #include "GrTracing.h"
@@ -29,6 +27,7 @@
 #include "SkDrawProcs.h"
 #include "SkGlyphCache.h"
 #include "SkImageFilter.h"
+#include "SkLayerInfo.h"
 #include "SkMaskFilter.h"
 #include "SkPathEffect.h"
 #include "SkPicture.h"
@@ -1796,7 +1795,7 @@
         return false;
     }
 
-    SkPicture::AccelData::Key key = GrAccelData::ComputeAccelDataKey();
+    SkPicture::AccelData::Key key = SkLayerInfo::ComputeKey();
 
     const SkPicture::AccelData* data = mainPicture->EXPERIMENTAL_getAccelData(key);
     if (!data) {
diff --git a/tests/PictureTest.cpp b/tests/PictureTest.cpp
index 3cb145e..5bc6037 100644
--- a/tests/PictureTest.cpp
+++ b/tests/PictureTest.cpp
@@ -16,6 +16,7 @@
 #include "SkError.h"
 #include "SkImageEncoder.h"
 #include "SkImageGenerator.h"
+#include "SkLayerInfo.h"
 #include "SkPaint.h"
 #include "SkPicture.h"
 #include "SkPictureRecorder.h"
@@ -29,7 +30,6 @@
 #if SK_SUPPORT_GPU
 #include "SkSurface.h"
 #include "GrContextFactory.h"
-#include "GrPictureUtils.h"
 #endif
 #include "Test.h"
 
@@ -871,225 +871,210 @@
     REPORTER_ASSERT(reporter, !picture->suitableForGpuRasterization(NULL));
 }
 
-static void test_gpu_picture_optimization(skiatest::Reporter* reporter,
-                                          GrContextFactory* factory) {
-    for (int i= 0; i < GrContextFactory::kGLContextTypeCnt; ++i) {
-        GrContextFactory::GLContextType glCtxType = (GrContextFactory::GLContextType) i;
+#endif
 
-        if (!GrContextFactory::IsRenderingGLContext(glCtxType)) {
-            continue;
-        }
+static void test_savelayer_extraction(skiatest::Reporter* reporter) {
+    static const int kWidth = 100;
+    static const int kHeight = 100;
 
-        GrContext* context = factory->get(glCtxType);
+    // Create complex paint that the bounding box computation code can't
+    // optimize away
+    SkScalar blueToRedMatrix[20] = { 0 };
+    blueToRedMatrix[2] = blueToRedMatrix[18] = SK_Scalar1;
+    SkAutoTUnref<SkColorFilter> blueToRed(SkColorMatrixFilter::Create(blueToRedMatrix));
+    SkAutoTUnref<SkImageFilter> filter(SkColorFilterImageFilter::Create(blueToRed.get()));
 
-        if (NULL == context) {
-            continue;
-        }
+    SkPaint complexPaint;
+    complexPaint.setImageFilter(filter);
 
-        static const int kWidth = 100;
-        static const int kHeight = 100;
+    SkAutoTUnref<SkPicture> pict, child;
+    SkRTreeFactory bbhFactory;
 
-        // Create complex paint that the bounding box computation code can't
-        // optimize away
-        SkScalar blueToRedMatrix[20] = { 0 };
-        blueToRedMatrix[2] = blueToRedMatrix[18] = SK_Scalar1;
-        SkAutoTUnref<SkColorFilter> blueToRed(SkColorMatrixFilter::Create(blueToRedMatrix));
-        SkAutoTUnref<SkImageFilter> filter(SkColorFilterImageFilter::Create(blueToRed.get()));
+    {
+        SkPictureRecorder recorder;
 
-        SkPaint complexPaint;
-        complexPaint.setImageFilter(filter);
+        SkCanvas* c = recorder.beginRecording(SkIntToScalar(kWidth), SkIntToScalar(kHeight),
+                                              &bbhFactory,
+                                              SkPictureRecorder::kComputeSaveLayerInfo_RecordFlag);
 
-        SkAutoTUnref<SkPicture> pict, child;
-        SkRTreeFactory bbhFactory;
+        c->saveLayer(NULL, &complexPaint);
+        c->restore();
 
-        {
-            SkPictureRecorder recorder;
+        child.reset(recorder.endRecording());
+    }
 
-            SkCanvas* c = recorder.beginRecording(SkIntToScalar(kWidth), SkIntToScalar(kHeight),
-                                                  &bbhFactory,
-                                                  SkPictureRecorder::kComputeSaveLayerInfo_RecordFlag);
+    // create a picture with the structure:
+    // 1)
+    //      SaveLayer
+    //      Restore
+    // 2)
+    //      SaveLayer
+    //          Translate
+    //          SaveLayer w/ bound
+    //          Restore
+    //      Restore
+    // 3)
+    //      SaveLayer w/ copyable paint
+    //      Restore
+    // 4)
+    //      SaveLayer
+    //          DrawPicture (which has a SaveLayer/Restore pair)
+    //      Restore
+    // 5)
+    //      SaveLayer
+    //          DrawPicture with Matrix & Paint (with SaveLayer/Restore pair)
+    //      Restore
+    {
+        SkPictureRecorder recorder;
 
-            c->saveLayer(NULL, &complexPaint);
-            c->restore();
-
-            child.reset(recorder.endRecording());
-        }
-
-        // create a picture with the structure:
+        SkCanvas* c = recorder.beginRecording(SkIntToScalar(kWidth),
+                                              SkIntToScalar(kHeight),
+                                              &bbhFactory,
+                                              SkPictureRecorder::kComputeSaveLayerInfo_RecordFlag);
         // 1)
-        //      SaveLayer
-        //      Restore
+        c->saveLayer(NULL, &complexPaint); // layer #0
+        c->restore();
+
         // 2)
-        //      SaveLayer
-        //          Translate
-        //          SaveLayer w/ bound
-        //          Restore
-        //      Restore
+        c->saveLayer(NULL, NULL); // layer #1
+            c->translate(kWidth/2.0f, kHeight/2.0f);
+            SkRect r = SkRect::MakeXYWH(0, 0, kWidth/2, kHeight/2);
+            c->saveLayer(&r, &complexPaint); // layer #2
+            c->restore();
+        c->restore();
+
         // 3)
-        //      SaveLayer w/ copyable paint
-        //      Restore
+        {
+            c->saveLayer(NULL, &complexPaint); // layer #3
+            c->restore();
+        }
+
+        SkPaint layerPaint;
+        layerPaint.setColor(SK_ColorRED);  // Non-alpha only to avoid SaveLayerDrawRestoreNooper
         // 4)
-        //      SaveLayer
-        //          DrawPicture (which has a SaveLayer/Restore pair)
-        //      Restore
-        // 5)
-        //      SaveLayer
-        //          DrawPicture with Matrix & Paint (with SaveLayer/Restore pair)
-        //      Restore
         {
-            SkPictureRecorder recorder;
-
-            SkCanvas* c = recorder.beginRecording(SkIntToScalar(kWidth),
-                                                  SkIntToScalar(kHeight),
-                                                  &bbhFactory,
-                                                  SkPictureRecorder::kComputeSaveLayerInfo_RecordFlag);
-            // 1)
-            c->saveLayer(NULL, &complexPaint); // layer #0
+            c->saveLayer(NULL, &layerPaint);  // layer #4
+                c->drawPicture(child);  // layer #5 inside picture
             c->restore();
+        }
+        // 5
+        {
+            SkPaint picturePaint;
+            SkMatrix trans;
+            trans.setTranslate(10, 10);
 
-            // 2)
-            c->saveLayer(NULL, NULL); // layer #1
-                c->translate(kWidth/2.0f, kHeight/2.0f);
-                SkRect r = SkRect::MakeXYWH(0, 0, kWidth/2, kHeight/2);
-                c->saveLayer(&r, &complexPaint); // layer #2
-                c->restore();
+            c->saveLayer(NULL, &layerPaint);  // layer #6
+                c->drawPicture(child, &trans, &picturePaint); // layer #7 inside picture
             c->restore();
-
-            // 3)
-            {
-                c->saveLayer(NULL, &complexPaint); // layer #3
-                c->restore();
-            }
-
-            SkPaint layerPaint;
-            layerPaint.setColor(SK_ColorRED);  // Non-alpha only to avoid SaveLayerDrawRestoreNooper
-            // 4)
-            {
-                c->saveLayer(NULL, &layerPaint);  // layer #4
-                    c->drawPicture(child);  // layer #5 inside picture
-                c->restore();
-            }
-            // 5
-            {
-                SkPaint picturePaint;
-                SkMatrix trans;
-                trans.setTranslate(10, 10);
-
-                c->saveLayer(NULL, &layerPaint);  // layer #6
-                    c->drawPicture(child, &trans, &picturePaint); // layer #7 inside picture
-                c->restore();
-            }
-
-            pict.reset(recorder.endRecording());
         }
 
-        // Now test out the SaveLayer extraction
-        {
-            SkPicture::AccelData::Key key = GrAccelData::ComputeAccelDataKey();
+        pict.reset(recorder.endRecording());
+    }
 
-            const SkPicture::AccelData* data = pict->EXPERIMENTAL_getAccelData(key);
-            REPORTER_ASSERT(reporter, data);
+    // Now test out the SaveLayer extraction
+    {
+        SkPicture::AccelData::Key key = SkLayerInfo::ComputeKey();
 
-            const GrAccelData *gpuData = static_cast<const GrAccelData*>(data);
-            REPORTER_ASSERT(reporter, 8 == gpuData->numSaveLayers());
+        const SkPicture::AccelData* data = pict->EXPERIMENTAL_getAccelData(key);
+        REPORTER_ASSERT(reporter, data);
 
-            const GrAccelData::SaveLayerInfo& info0 = gpuData->saveLayerInfo(0);
-            // The parent/child layers appear in reverse order
-            const GrAccelData::SaveLayerInfo& info1 = gpuData->saveLayerInfo(2);
-            const GrAccelData::SaveLayerInfo& info2 = gpuData->saveLayerInfo(1);
+        const SkLayerInfo *gpuData = static_cast<const SkLayerInfo*>(data);
+        REPORTER_ASSERT(reporter, 8 == gpuData->numBlocks());
 
-            const GrAccelData::SaveLayerInfo& info3 = gpuData->saveLayerInfo(3);
+        const SkLayerInfo::BlockInfo& info0 = gpuData->block(0);
+        // The parent/child layers appear in reverse order
+        const SkLayerInfo::BlockInfo& info1 = gpuData->block(2);
+        const SkLayerInfo::BlockInfo& info2 = gpuData->block(1);
 
-            // The parent/child layers appear in reverse order
-            const GrAccelData::SaveLayerInfo& info4 = gpuData->saveLayerInfo(5);
-            const GrAccelData::SaveLayerInfo& info5 = gpuData->saveLayerInfo(4);
+        const SkLayerInfo::BlockInfo& info3 = gpuData->block(3);
 
-            // The parent/child layers appear in reverse order
-            const GrAccelData::SaveLayerInfo& info6 = gpuData->saveLayerInfo(7);
-            const GrAccelData::SaveLayerInfo& info7 = gpuData->saveLayerInfo(6);
+        // The parent/child layers appear in reverse order
+        const SkLayerInfo::BlockInfo& info4 = gpuData->block(5);
+        const SkLayerInfo::BlockInfo& info5 = gpuData->block(4);
 
-            REPORTER_ASSERT(reporter, NULL == info0.fPicture);
-            REPORTER_ASSERT(reporter, kWidth == info0.fBounds.width() &&
-                                      kHeight == info0.fBounds.height());
-            REPORTER_ASSERT(reporter, info0.fLocalMat.isIdentity());
-            REPORTER_ASSERT(reporter, info0.fPreMat.isIdentity());
-            REPORTER_ASSERT(reporter, 0 == info0.fBounds.fLeft && 0 == info0.fBounds.fTop);
-            REPORTER_ASSERT(reporter, NULL != info0.fPaint);
-            REPORTER_ASSERT(reporter, !info0.fIsNested && !info0.fHasNestedLayers);
+        // The parent/child layers appear in reverse order
+        const SkLayerInfo::BlockInfo& info6 = gpuData->block(7);
+        const SkLayerInfo::BlockInfo& info7 = gpuData->block(6);
 
-            REPORTER_ASSERT(reporter, NULL == info1.fPicture);
-            REPORTER_ASSERT(reporter, kWidth/2.0 == info1.fBounds.width() &&
-                                      kHeight/2.0 == info1.fBounds.height());
-            REPORTER_ASSERT(reporter, info1.fLocalMat.isIdentity());
-            REPORTER_ASSERT(reporter, info1.fPreMat.isIdentity());
-            REPORTER_ASSERT(reporter, kWidth/2.0 == info1.fBounds.fLeft && 
-                                      kHeight/2.0 == info1.fBounds.fTop);
-            REPORTER_ASSERT(reporter, NULL == info1.fPaint);
-            REPORTER_ASSERT(reporter, !info1.fIsNested &&
-                                      info1.fHasNestedLayers); // has a nested SL
+        REPORTER_ASSERT(reporter, NULL == info0.fPicture);
+        REPORTER_ASSERT(reporter, kWidth == info0.fBounds.width() &&
+                                  kHeight == info0.fBounds.height());
+        REPORTER_ASSERT(reporter, info0.fLocalMat.isIdentity());
+        REPORTER_ASSERT(reporter, info0.fPreMat.isIdentity());
+        REPORTER_ASSERT(reporter, 0 == info0.fBounds.fLeft && 0 == info0.fBounds.fTop);
+        REPORTER_ASSERT(reporter, NULL != info0.fPaint);
+        REPORTER_ASSERT(reporter, !info0.fIsNested && !info0.fHasNestedLayers);
 
-            REPORTER_ASSERT(reporter, NULL == info2.fPicture);
-            REPORTER_ASSERT(reporter, kWidth / 2 == info2.fBounds.width() &&
-                                      kHeight / 2 == info2.fBounds.height()); // bound reduces size
-            REPORTER_ASSERT(reporter, !info2.fLocalMat.isIdentity());
-            REPORTER_ASSERT(reporter, info2.fPreMat.isIdentity());
-            REPORTER_ASSERT(reporter, kWidth / 2 == info2.fBounds.fLeft &&   // translated
-                                      kHeight / 2 == info2.fBounds.fTop);
-            REPORTER_ASSERT(reporter, NULL != info2.fPaint);
-            REPORTER_ASSERT(reporter, info2.fIsNested && !info2.fHasNestedLayers); // is nested
+        REPORTER_ASSERT(reporter, NULL == info1.fPicture);
+        REPORTER_ASSERT(reporter, kWidth/2.0 == info1.fBounds.width() &&
+                                  kHeight/2.0 == info1.fBounds.height());
+        REPORTER_ASSERT(reporter, info1.fLocalMat.isIdentity());
+        REPORTER_ASSERT(reporter, info1.fPreMat.isIdentity());
+        REPORTER_ASSERT(reporter, kWidth/2.0 == info1.fBounds.fLeft && 
+                                  kHeight/2.0 == info1.fBounds.fTop);
+        REPORTER_ASSERT(reporter, NULL == info1.fPaint);
+        REPORTER_ASSERT(reporter, !info1.fIsNested &&
+                                  info1.fHasNestedLayers); // has a nested SL
 
-            REPORTER_ASSERT(reporter, NULL == info3.fPicture);
-            REPORTER_ASSERT(reporter, kWidth == info3.fBounds.width() &&
-                                      kHeight == info3.fBounds.height());
-            REPORTER_ASSERT(reporter, info3.fLocalMat.isIdentity());
-            REPORTER_ASSERT(reporter, info3.fPreMat.isIdentity());
-            REPORTER_ASSERT(reporter, 0 == info3.fBounds.fLeft && 0 == info3.fBounds.fTop);
-            REPORTER_ASSERT(reporter, info3.fPaint);
-            REPORTER_ASSERT(reporter, !info3.fIsNested && !info3.fHasNestedLayers);
+        REPORTER_ASSERT(reporter, NULL == info2.fPicture);
+        REPORTER_ASSERT(reporter, kWidth / 2 == info2.fBounds.width() &&
+                                  kHeight / 2 == info2.fBounds.height()); // bound reduces size
+        REPORTER_ASSERT(reporter, !info2.fLocalMat.isIdentity());
+        REPORTER_ASSERT(reporter, info2.fPreMat.isIdentity());
+        REPORTER_ASSERT(reporter, kWidth / 2 == info2.fBounds.fLeft &&   // translated
+                                  kHeight / 2 == info2.fBounds.fTop);
+        REPORTER_ASSERT(reporter, NULL != info2.fPaint);
+        REPORTER_ASSERT(reporter, info2.fIsNested && !info2.fHasNestedLayers); // is nested
 
-            REPORTER_ASSERT(reporter, NULL == info4.fPicture);
-            REPORTER_ASSERT(reporter, kWidth == info4.fBounds.width() &&
-                                      kHeight == info4.fBounds.height());
-            REPORTER_ASSERT(reporter, 0 == info4.fBounds.fLeft && 0 == info4.fBounds.fTop);
-            REPORTER_ASSERT(reporter, info4.fLocalMat.isIdentity());
-            REPORTER_ASSERT(reporter, info4.fPreMat.isIdentity());
-            REPORTER_ASSERT(reporter, info4.fPaint);
-            REPORTER_ASSERT(reporter, !info4.fIsNested &&
-                                      info4.fHasNestedLayers); // has a nested SL
+        REPORTER_ASSERT(reporter, NULL == info3.fPicture);
+        REPORTER_ASSERT(reporter, kWidth == info3.fBounds.width() &&
+                                  kHeight == info3.fBounds.height());
+        REPORTER_ASSERT(reporter, info3.fLocalMat.isIdentity());
+        REPORTER_ASSERT(reporter, info3.fPreMat.isIdentity());
+        REPORTER_ASSERT(reporter, 0 == info3.fBounds.fLeft && 0 == info3.fBounds.fTop);
+        REPORTER_ASSERT(reporter, info3.fPaint);
+        REPORTER_ASSERT(reporter, !info3.fIsNested && !info3.fHasNestedLayers);
 
-            REPORTER_ASSERT(reporter, child == info5.fPicture); // in a child picture
-            REPORTER_ASSERT(reporter, kWidth == info5.fBounds.width() &&
-                                      kHeight == info5.fBounds.height());
-            REPORTER_ASSERT(reporter, 0 == info5.fBounds.fLeft && 0 == info5.fBounds.fTop);
-            REPORTER_ASSERT(reporter, info5.fLocalMat.isIdentity());
-            REPORTER_ASSERT(reporter, info5.fPreMat.isIdentity());
-            REPORTER_ASSERT(reporter, NULL != info5.fPaint);
-            REPORTER_ASSERT(reporter, info5.fIsNested && !info5.fHasNestedLayers); // is nested
+        REPORTER_ASSERT(reporter, NULL == info4.fPicture);
+        REPORTER_ASSERT(reporter, kWidth == info4.fBounds.width() &&
+                                  kHeight == info4.fBounds.height());
+        REPORTER_ASSERT(reporter, 0 == info4.fBounds.fLeft && 0 == info4.fBounds.fTop);
+        REPORTER_ASSERT(reporter, info4.fLocalMat.isIdentity());
+        REPORTER_ASSERT(reporter, info4.fPreMat.isIdentity());
+        REPORTER_ASSERT(reporter, info4.fPaint);
+        REPORTER_ASSERT(reporter, !info4.fIsNested &&
+                                  info4.fHasNestedLayers); // has a nested SL
 
-            REPORTER_ASSERT(reporter, NULL == info6.fPicture);
-            REPORTER_ASSERT(reporter, kWidth-10 == info6.fBounds.width() &&
-                                      kHeight-10 == info6.fBounds.height());
-            REPORTER_ASSERT(reporter, 10 == info6.fBounds.fLeft && 10 == info6.fBounds.fTop);
-            REPORTER_ASSERT(reporter, info6.fLocalMat.isIdentity());
-            REPORTER_ASSERT(reporter, info6.fPreMat.isIdentity());
-            REPORTER_ASSERT(reporter, info6.fPaint);
-            REPORTER_ASSERT(reporter, !info6.fIsNested &&
-                                      info6.fHasNestedLayers); // has a nested SL
+        REPORTER_ASSERT(reporter, child == info5.fPicture); // in a child picture
+        REPORTER_ASSERT(reporter, kWidth == info5.fBounds.width() &&
+                                  kHeight == info5.fBounds.height());
+        REPORTER_ASSERT(reporter, 0 == info5.fBounds.fLeft && 0 == info5.fBounds.fTop);
+        REPORTER_ASSERT(reporter, info5.fLocalMat.isIdentity());
+        REPORTER_ASSERT(reporter, info5.fPreMat.isIdentity());
+        REPORTER_ASSERT(reporter, NULL != info5.fPaint);
+        REPORTER_ASSERT(reporter, info5.fIsNested && !info5.fHasNestedLayers); // is nested
 
-            REPORTER_ASSERT(reporter, child == info7.fPicture); // in a child picture
-            REPORTER_ASSERT(reporter, kWidth == info7.fBounds.width() &&
-                                      kHeight == info7.fBounds.height());
-            REPORTER_ASSERT(reporter, 0 == info7.fBounds.fLeft && 0 == info7.fBounds.fTop);
-            REPORTER_ASSERT(reporter, info7.fLocalMat.isIdentity());
-            REPORTER_ASSERT(reporter, info7.fPreMat.isIdentity());
-            REPORTER_ASSERT(reporter, NULL != info7.fPaint);
-            REPORTER_ASSERT(reporter, info7.fIsNested && !info7.fHasNestedLayers); // is nested
-        }
+        REPORTER_ASSERT(reporter, NULL == info6.fPicture);
+        REPORTER_ASSERT(reporter, kWidth-10 == info6.fBounds.width() &&
+                                  kHeight-10 == info6.fBounds.height());
+        REPORTER_ASSERT(reporter, 10 == info6.fBounds.fLeft && 10 == info6.fBounds.fTop);
+        REPORTER_ASSERT(reporter, info6.fLocalMat.isIdentity());
+        REPORTER_ASSERT(reporter, info6.fPreMat.isIdentity());
+        REPORTER_ASSERT(reporter, info6.fPaint);
+        REPORTER_ASSERT(reporter, !info6.fIsNested &&
+                                  info6.fHasNestedLayers); // has a nested SL
+
+        REPORTER_ASSERT(reporter, child == info7.fPicture); // in a child picture
+        REPORTER_ASSERT(reporter, kWidth == info7.fBounds.width() &&
+                                  kHeight == info7.fBounds.height());
+        REPORTER_ASSERT(reporter, 0 == info7.fBounds.fLeft && 0 == info7.fBounds.fTop);
+        REPORTER_ASSERT(reporter, info7.fLocalMat.isIdentity());
+        REPORTER_ASSERT(reporter, info7.fPreMat.isIdentity());
+        REPORTER_ASSERT(reporter, NULL != info7.fPaint);
+        REPORTER_ASSERT(reporter, info7.fIsNested && !info7.fHasNestedLayers); // is nested
     }
 }
 
-#endif
-
 static void test_has_text(skiatest::Reporter* reporter) {
     SkPictureRecorder recorder;
 
@@ -1757,14 +1742,9 @@
     test_clip_expansion(reporter);
     test_hierarchical(reporter);
     test_gen_id(reporter);
+    test_savelayer_extraction(reporter);
 }
 
-#if SK_SUPPORT_GPU
-DEF_GPUTEST(GPUPicture, reporter, factory) {
-    test_gpu_picture_optimization(reporter, factory);
-}
-#endif
-
 static void draw_bitmaps(const SkBitmap bitmap, SkCanvas* canvas) {
     const SkPaint paint;
     const SkRect rect = { 5.0f, 5.0f, 8.0f, 8.0f };