Make GPU unit tests use GrContexts of different GL types.
Review URL: https://codereview.appspot.com/7281046

git-svn-id: http://skia.googlecode.com/svn/trunk@7540 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/tests/ClipCacheTest.cpp b/tests/ClipCacheTest.cpp
index c80ba63..aebbef5 100644
--- a/tests/ClipCacheTest.cpp
+++ b/tests/ClipCacheTest.cpp
@@ -9,6 +9,7 @@
 #include "Test.h"
 // This is a GR test
 #if SK_SUPPORT_GPU
+#include "GrContextFactory.h"
 #include "SkGpuDevice.h"
 #include "../../src/gpu/GrClipMaskManager.h"
 
@@ -216,10 +217,20 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-static void TestClipCache(skiatest::Reporter* reporter, GrContext* context) {
+static void TestClipCache(skiatest::Reporter* reporter, GrContextFactory* factory) {
+    for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) {
+        GrContextFactory::GLContextType glType = static_cast<GrContextFactory::GLContextType>(type);
+        if (!GrContextFactory::IsRenderingGLContext(glType)) {
+            continue;
+        }
+        GrContext* context = factory->get(glType);
+        if (NULL == context) {
+            continue;
+        }
 
-    test_cache(reporter, context);
-    test_clip_bounds(reporter, context);
+        test_cache(reporter, context);
+        test_clip_bounds(reporter, context);
+    }
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/tests/GLProgramsTest.cpp b/tests/GLProgramsTest.cpp
index 3106377..b93f9c3 100644
--- a/tests/GLProgramsTest.cpp
+++ b/tests/GLProgramsTest.cpp
@@ -14,6 +14,7 @@
 
 #include "gl/GrGpuGL.h"
 #include "GrBackendEffectFactory.h"
+#include "GrContextFactory.h"
 #include "effects/GrConfigConversionEffect.h"
 
 #include "SkRandom.h"
@@ -147,9 +148,14 @@
     return true;
 }
 
-static void GLProgramsTest(skiatest::Reporter* reporter, GrContext* context) {
-    GrGpuGL* shadersGpu = static_cast<GrGpuGL*>(context->getGpu());
-    REPORTER_ASSERT(reporter, shadersGpu->programUnitTest());
+static void GLProgramsTest(skiatest::Reporter* reporter, GrContextFactory* factory) {
+    for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) {
+        GrContext* context = factory->get(static_cast<GrContextFactory::GLContextType>(type));
+        if (NULL != context) {
+            GrGpuGL* shadersGpu = static_cast<GrGpuGL*>(context->getGpu());
+            REPORTER_ASSERT(reporter, shadersGpu->programUnitTest());
+        }
+    }
 }
 
 #include "TestClassDef.h"
diff --git a/tests/GpuBitmapCopyTest.cpp b/tests/GpuBitmapCopyTest.cpp
index 63e3cca..74299da 100644
--- a/tests/GpuBitmapCopyTest.cpp
+++ b/tests/GpuBitmapCopyTest.cpp
@@ -9,6 +9,7 @@
 #if SK_SUPPORT_GPU
 
 #include "GrContext.h"
+#include "GrContextFactory.h"
 #include "SkBitmap.h"
 #include "SkCanvas.h"
 #include "SkColor.h"
@@ -117,88 +118,106 @@
 
 // Stripped down version of TestBitmapCopy that checks basic fields (width, height, config, genID)
 // to ensure that they were copied properly.
-static void TestGpuBitmapCopy(skiatest::Reporter* reporter, GrContext* grContext) {
+static void TestGpuBitmapCopy(skiatest::Reporter* reporter, GrContextFactory* factory) {
 #ifdef SK_BUILD_FOR_ANDROID // https://code.google.com/p/skia/issues/detail?id=753
     return;
 #endif
-    if (NULL == grContext) {
-        return;
-    }
-    static const Pair gPairs[] = {
-        { SkBitmap::kNo_Config,         "000"  },
-        { SkBitmap::kARGB_4444_Config,  "011"  },
-        { SkBitmap::kARGB_8888_Config,  "011"  },
-    };
+    for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) {
+        GrContextFactory::GLContextType glType = static_cast<GrContextFactory::GLContextType>(type);
+        if (!GrContextFactory::IsRenderingGLContext(glType)) {
+            continue;
+        }
+#if SK_ANGLE // This test breaks ANGLE: memcmps fail and readpixels return value is false.
+        if (type == GrContextFactory::kANGLE_GLContextType) {
+            continue;
+        }
+#endif
 
-    const int W = 20;
-    const int H = 33;
-
-    for (size_t i = 0; i < SK_ARRAY_COUNT(gPairs); i++) {
-        SkBitmap src, dst;
-
-        SkGpuDevice* device = SkNEW_ARGS(SkGpuDevice, (grContext, gPairs[i].fConfig, W, H));
-        SkAutoUnref aur(device);
-        src = device->accessBitmap(false);
-        device->clear(SK_ColorWHITE);
-
-        // Draw something different to the same portion of the bitmap that we will extract as a
-        // subset, so that comparing the pixels of the subset will be meaningful.
-        SkIRect subsetRect = SkIRect::MakeLTRB(W/2, H/2, W, H);
-        SkCanvas drawingCanvas(device);
-        SkPaint paint;
-        paint.setColor(SK_ColorRED);
-        drawingCanvas.drawRect(SkRect::MakeFromIRect(subsetRect), paint);
-
-        // Extract a subset. If this succeeds we will test copying the subset.
-        SkBitmap subset;
-        const bool extracted = src.extractSubset(&subset, subsetRect);
-        if (extracted) {
-            TestSubsetHelpers(reporter, subset);
+        GrContext* grContext = factory->get(glType);
+        if (NULL == grContext) {
+            continue;
         }
 
-        for (size_t j = 0; j < SK_ARRAY_COUNT(gPairs); j++) {
-            dst.reset();
-            bool success = src.deepCopyTo(&dst, gPairs[j].fConfig);
-            bool expected = gPairs[i].fValid[j] != '0';
-            if (success != expected) {
-                SkString str;
-                str.printf("SkBitmap::deepCopyTo from %s to %s. expected %s returned %s",
-                           gConfigName[i], gConfigName[j], boolStr(expected),
-                           boolStr(success));
-                reporter->reportFailed(str);
-            }
 
-            bool canSucceed = src.canCopyTo(gPairs[j].fConfig);
-            if (success != canSucceed) {
-                SkString str;
-                str.printf("SkBitmap::deepCopyTo from %s to %s returned %s,"
-                           "but canCopyTo returned %s",
-                           gConfigName[i], gConfigName[j], boolStr(success),
-                           boolStr(canSucceed));
-                reporter->reportFailed(str);
-            }
+        if (NULL == grContext) {
+            return;
+        }
+        static const Pair gPairs[] = {
+            { SkBitmap::kNo_Config,         "000"  },
+            { SkBitmap::kARGB_4444_Config,  "011"  },
+            { SkBitmap::kARGB_8888_Config,  "011"  },
+        };
 
-            TestIndividualCopy(reporter, gPairs[j].fConfig, success, src, dst);
+        const int W = 20;
+        const int H = 33;
 
-            // Test copying the subset bitmap, using both copyTo and deepCopyTo.
+        for (size_t i = 0; i < SK_ARRAY_COUNT(gPairs); i++) {
+            SkBitmap src, dst;
+
+            SkGpuDevice* device = SkNEW_ARGS(SkGpuDevice, (grContext, gPairs[i].fConfig, W, H));
+            SkAutoUnref aur(device);
+            src = device->accessBitmap(false);
+            device->clear(SK_ColorWHITE);
+
+            // Draw something different to the same portion of the bitmap that we will extract as a
+            // subset, so that comparing the pixels of the subset will be meaningful.
+            SkIRect subsetRect = SkIRect::MakeLTRB(W/2, H/2, W, H);
+            SkCanvas drawingCanvas(device);
+            SkPaint paint;
+            paint.setColor(SK_ColorRED);
+            drawingCanvas.drawRect(SkRect::MakeFromIRect(subsetRect), paint);
+
+            // Extract a subset. If this succeeds we will test copying the subset.
+            SkBitmap subset;
+            const bool extracted = src.extractSubset(&subset, subsetRect);
             if (extracted) {
-                SkBitmap subsetCopy;
-                success = subset.copyTo(&subsetCopy, gPairs[j].fConfig);
-                REPORTER_ASSERT(reporter, success == expected);
-                REPORTER_ASSERT(reporter, success == canSucceed);
-                TestIndividualCopy(reporter, gPairs[j].fConfig, success, subset, subsetCopy, false,
-                                   &subsetRect);
-
-                // Reset the bitmap so that a failed copyTo will leave it in the expected state.
-                subsetCopy.reset();
-                success = subset.deepCopyTo(&subsetCopy, gPairs[j].fConfig);
-                REPORTER_ASSERT(reporter, success == expected);
-                REPORTER_ASSERT(reporter, success == canSucceed);
-                TestIndividualCopy(reporter, gPairs[j].fConfig, success, subset, subsetCopy, true,
-                                   &subsetRect);
+                TestSubsetHelpers(reporter, subset);
             }
-        } // for (size_t j = ...
-    } // for (size_t i = ...
+
+            for (size_t j = 0; j < SK_ARRAY_COUNT(gPairs); j++) {
+                dst.reset();
+                bool success = src.deepCopyTo(&dst, gPairs[j].fConfig);
+                bool expected = gPairs[i].fValid[j] != '0';
+                if (success != expected) {
+                    SkString str;
+                    str.printf("SkBitmap::deepCopyTo from %s to %s. expected %s returned %s",
+                               gConfigName[i], gConfigName[j], boolStr(expected),
+                               boolStr(success));
+                    reporter->reportFailed(str);
+                }
+
+                bool canSucceed = src.canCopyTo(gPairs[j].fConfig);
+                if (success != canSucceed) {
+                    SkString str;
+                    str.printf("SkBitmap::deepCopyTo from %s to %s returned %s,"
+                               "but canCopyTo returned %s",
+                               gConfigName[i], gConfigName[j], boolStr(success),
+                               boolStr(canSucceed));
+                    reporter->reportFailed(str);
+                }
+
+                TestIndividualCopy(reporter, gPairs[j].fConfig, success, src, dst);
+
+                // Test copying the subset bitmap, using both copyTo and deepCopyTo.
+                if (extracted) {
+                    SkBitmap subsetCopy;
+                    success = subset.copyTo(&subsetCopy, gPairs[j].fConfig);
+                    REPORTER_ASSERT(reporter, success == expected);
+                    REPORTER_ASSERT(reporter, success == canSucceed);
+                    TestIndividualCopy(reporter, gPairs[j].fConfig, success, subset, subsetCopy, false,
+                                       &subsetRect);
+
+                    // Reset the bitmap so that a failed copyTo will leave it in the expected state.
+                    subsetCopy.reset();
+                    success = subset.deepCopyTo(&subsetCopy, gPairs[j].fConfig);
+                    REPORTER_ASSERT(reporter, success == expected);
+                    REPORTER_ASSERT(reporter, success == canSucceed);
+                    TestIndividualCopy(reporter, gPairs[j].fConfig, success, subset, subsetCopy, true,
+                                       &subsetRect);
+                }
+            } // for (size_t j = ...
+        } // for (size_t i = ...
+    } // GrContextFactory::GLContextType
 }
 
 #include "TestClassDef.h"
diff --git a/tests/HashCacheTest.cpp b/tests/HashCacheTest.cpp
index f26dd8a..d58b86c 100644
--- a/tests/HashCacheTest.cpp
+++ b/tests/HashCacheTest.cpp
@@ -63,7 +63,7 @@
 };
 
 ////////////////////////////////////////////////////////////////////////////////
-static void TestHashCache(skiatest::Reporter* reporter, GrContext* context) {
+static void TestHashCache(skiatest::Reporter* reporter) {
 
     GrTHashTable<HashElement, HashKey, 4> cache;
 
@@ -165,6 +165,6 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 #include "TestClassDef.h"
-DEFINE_GPUTESTCLASS("HashCache", HashCacheTestClass, TestHashCache)
+DEFINE_TESTCLASS("HashCache", HashCacheTestClass, TestHashCache)
 
 #endif
diff --git a/tests/PremulAlphaRoundTripTest.cpp b/tests/PremulAlphaRoundTripTest.cpp
index 8321c94..b25d358 100644
--- a/tests/PremulAlphaRoundTripTest.cpp
+++ b/tests/PremulAlphaRoundTripTest.cpp
@@ -12,6 +12,7 @@
 #include "SkDevice.h"
 
 #if SK_SUPPORT_GPU
+#include "GrContextFactory.h"
 #include "SkGpuDevice.h"
 #endif
 
@@ -46,61 +47,75 @@
     SkCanvas::kRGBA_Unpremul_Config8888,
 };
 
-void PremulAlphaRoundTripTest(skiatest::Reporter* reporter,
-                              GrContext* context) {
+void PremulAlphaRoundTripTest(skiatest::Reporter* reporter, GrContextFactory* factory) {
     SkAutoTUnref<SkDevice> device;
     for (int dtype = 0; dtype < 2; ++dtype) {
-        if (0 == dtype) {
-            device.reset(new SkDevice(SkBitmap::kARGB_8888_Config,
-                                          256,
-                                          256,
-                                          false));
-        } else {
-#if !SK_SUPPORT_GPU || defined(SK_SCALAR_IS_FIXED)
-            // GPU device known not to work in the fixed pt build.
-            continue;
-#else
-            device.reset(new SkGpuDevice(context,
-                                             SkBitmap::kARGB_8888_Config,
-                                             256,
-                                             256));
-#endif
+
+        int glCtxTypeCnt = 1;
+#if SK_SUPPORT_GPU
+        if (0 != dtype)  {
+            glCtxTypeCnt = GrContextFactory::kGLContextTypeCnt;
         }
-        SkCanvas canvas(device);
+#endif
+        for (int glCtxType = 0; glCtxType < glCtxTypeCnt; ++glCtxType) {
+            if (0 == dtype) {
+                device.reset(new SkDevice(SkBitmap::kARGB_8888_Config,
+                                              256,
+                                              256,
+                                              false));
+            } else {
+#if SK_SUPPORT_GPU
+                GrContextFactory::GLContextType type =
+                    static_cast<GrContextFactory::GLContextType>(glCtxType);
+                if (!GrContextFactory::IsRenderingGLContext(type)) {
+                    continue;
+                }
+                GrContext* context = factory->get(type);
+                if (NULL == context) {
+                    continue;
+                }
 
-        SkBitmap readBmp1;
-        readBmp1.setConfig(SkBitmap::kARGB_8888_Config, 256, 256);
-        readBmp1.allocPixels();
-        SkBitmap readBmp2;
-        readBmp2.setConfig(SkBitmap::kARGB_8888_Config, 256, 256);
-        readBmp2.allocPixels();
+                device.reset(new SkGpuDevice(context, SkBitmap::kARGB_8888_Config, 256, 256));
+#else
+                continue;
+#endif
+            }
+            SkCanvas canvas(device);
 
-        for (size_t upmaIdx = 0;
-             upmaIdx < SK_ARRAY_COUNT(gUnpremulConfigs);
-             ++upmaIdx) {
-            fillCanvas(&canvas, gUnpremulConfigs[upmaIdx]);
-            {
+            SkBitmap readBmp1;
+            readBmp1.setConfig(SkBitmap::kARGB_8888_Config, 256, 256);
+            readBmp1.allocPixels();
+            SkBitmap readBmp2;
+            readBmp2.setConfig(SkBitmap::kARGB_8888_Config, 256, 256);
+            readBmp2.allocPixels();
+
+            for (size_t upmaIdx = 0;
+                 upmaIdx < SK_ARRAY_COUNT(gUnpremulConfigs);
+                 ++upmaIdx) {
+                fillCanvas(&canvas, gUnpremulConfigs[upmaIdx]);
+                {
+                    SkAutoLockPixels alp1(readBmp1);
+                    SkAutoLockPixels alp2(readBmp2);
+                    sk_bzero(readBmp1.getPixels(), readBmp1.getSafeSize());
+                    sk_bzero(readBmp2.getPixels(), readBmp2.getSafeSize());
+                }
+
+                canvas.readPixels(&readBmp1, 0, 0, gUnpremulConfigs[upmaIdx]);
+                canvas.writePixels(readBmp1, 0, 0, gUnpremulConfigs[upmaIdx]);
+                canvas.readPixels(&readBmp2, 0, 0, gUnpremulConfigs[upmaIdx]);
+
                 SkAutoLockPixels alp1(readBmp1);
                 SkAutoLockPixels alp2(readBmp2);
-                sk_bzero(readBmp1.getPixels(), readBmp1.getSafeSize());
-                sk_bzero(readBmp2.getPixels(), readBmp2.getSafeSize());
-            }
-
-            canvas.readPixels(&readBmp1, 0, 0, gUnpremulConfigs[upmaIdx]);
-            canvas.writePixels(readBmp1, 0, 0, gUnpremulConfigs[upmaIdx]);
-            canvas.readPixels(&readBmp2, 0, 0, gUnpremulConfigs[upmaIdx]);
-
-            SkAutoLockPixels alp1(readBmp1);
-            SkAutoLockPixels alp2(readBmp2);
-            uint32_t* pixels1 =
-                reinterpret_cast<uint32_t*>(readBmp1.getPixels());
-            uint32_t* pixels2 =
-                reinterpret_cast<uint32_t*>(readBmp2.getPixels());
-            bool success = true;
-            for (int y = 0; y < 256 && success; ++y) {
-                for (int x = 0; x < 256 && success; ++x) {
-                    int i = y * 256 + x;
-                    REPORTER_ASSERT(reporter, success = pixels1[i] == pixels2[i]);
+                uint32_t* pixels1 =
+                    reinterpret_cast<uint32_t*>(readBmp1.getPixels());
+                uint32_t* pixels2 =
+                    reinterpret_cast<uint32_t*>(readBmp2.getPixels());
+                bool success = true;
+                for (int y = 0; y < 256 && success; ++y) {
+                    for (int x = 0; x < 256 && success; ++x) {
+                        int i = y * 256 + x;
+                        REPORTER_ASSERT(reporter, success = pixels1[i] == pixels2[i]);
+                    }
                 }
             }
         }
diff --git a/tests/ReadPixelsTest.cpp b/tests/ReadPixelsTest.cpp
index a33e819..41ecccf 100644
--- a/tests/ReadPixelsTest.cpp
+++ b/tests/ReadPixelsTest.cpp
@@ -14,6 +14,7 @@
 #include "SkRegion.h"
 #if SK_SUPPORT_GPU
 #include "SkGpuDevice.h"
+#include "GrContextFactory.h"
 #endif
 
 
@@ -254,7 +255,7 @@
     }
 }
 
-void ReadPixelsTest(skiatest::Reporter* reporter, GrContext* context) {
+void ReadPixelsTest(skiatest::Reporter* reporter, GrContextFactory* factory) {
     const SkIRect testRects[] = {
         // entire thing
         DEV_RECT,
@@ -303,92 +304,102 @@
     };
 
     for (int dtype = 0; dtype < 2; ++dtype) {
-        SkAutoTUnref<SkDevice> device;
-        if (0 == dtype) {
-            device.reset(new SkDevice(SkBitmap::kARGB_8888_Config,
-                                          DEV_W,
-                                          DEV_H,
-                                          false));
-        } else {
-// GPU device known not to work in the fixed pt build.
-#if defined(SK_SCALAR_IS_FIXED) || !SK_SUPPORT_GPU
-            continue;
-#else
-            device.reset(new SkGpuDevice(context,
-                                             SkBitmap::kARGB_8888_Config,
-                                             DEV_W,
-                                             DEV_H));
-#endif
+        int glCtxTypeCnt = 1;
+#if SK_SUPPORT_GPU
+        if (0 != dtype)  {
+            glCtxTypeCnt = GrContextFactory::kGLContextTypeCnt;
         }
-        SkCanvas canvas(device);
-        fillCanvas(&canvas);
-
-        static const SkCanvas::Config8888 gReadConfigs[] = {
-            SkCanvas::kNative_Premul_Config8888,
-            SkCanvas::kNative_Unpremul_Config8888,
-/**
- * There is a bug in Ganesh (http://code.google.com/p/skia/issues/detail?id=438)
- * that causes the readback of pixels from BGRA canvas to an RGBA bitmap to
- * fail. This should be removed as soon as the issue above is resolved.
- */
-#if !defined(SK_BUILD_FOR_ANDROID)
-            SkCanvas::kBGRA_Premul_Config8888,
-            SkCanvas::kBGRA_Unpremul_Config8888,
 #endif
-            SkCanvas::kRGBA_Premul_Config8888,
-            SkCanvas::kRGBA_Unpremul_Config8888,
-        };
-        for (size_t rect = 0; rect < SK_ARRAY_COUNT(testRects); ++rect) {
-            const SkIRect& srcRect = testRects[rect];
-            for (BitmapInit bmi = kFirstBitmapInit;
-                 bmi < kBitmapInitCnt;
-                 bmi = nextBMI(bmi)) {
-                for (size_t c = 0; c < SK_ARRAY_COUNT(gReadConfigs); ++c) {
-                    SkCanvas::Config8888 config8888 = gReadConfigs[c];
-                    SkBitmap bmp;
-                    init_bitmap(&bmp, srcRect, bmi);
-
-                    // if the bitmap has pixels allocated before the readPixels,
-                    // note that and fill them with pattern
-                    bool startsWithPixels = !bmp.isNull();
-                    if (startsWithPixels) {
-                        fillBitmap(&bmp);
-                    }
-                    uint32_t idBefore = canvas.getDevice()->accessBitmap(false).getGenerationID();
-                    bool success =
-                        canvas.readPixels(&bmp, srcRect.fLeft,
-                                          srcRect.fTop, config8888);
-                    uint32_t idAfter = canvas.getDevice()->accessBitmap(false).getGenerationID();
-
-                    // we expect to succeed when the read isn't fully clipped
-                    // out.
-                    bool expectSuccess = SkIRect::Intersects(srcRect, DEV_RECT);
-                    // determine whether we expected the read to succeed.
-                    REPORTER_ASSERT(reporter, success == expectSuccess);
-                    // read pixels should never change the gen id
-                    REPORTER_ASSERT(reporter, idBefore == idAfter);
-
-                    if (success || startsWithPixels) {
-                        checkRead(reporter, bmp, srcRect.fLeft, srcRect.fTop,
-                                  success, startsWithPixels, config8888);
-                    } else {
-                        // if we had no pixels beforehand and the readPixels
-                        // failed then our bitmap should still not have pixels
-                        REPORTER_ASSERT(reporter, bmp.isNull());
-                    }
+        for (int glCtxType = 0; glCtxType < glCtxTypeCnt; ++glCtxType) {
+            SkAutoTUnref<SkDevice> device;
+            if (0 == dtype) {
+                device.reset(new SkDevice(SkBitmap::kARGB_8888_Config, DEV_W, DEV_H, false));
+            } else {
+#if SK_SUPPORT_GPU
+                GrContextFactory::GLContextType type =
+                    static_cast<GrContextFactory::GLContextType>(glCtxType);
+                if (!GrContextFactory::IsRenderingGLContext(type)) {
+                    continue;
                 }
-                // check the old webkit version of readPixels that clips the
-                // bitmap size
-                SkBitmap wkbmp;
-                bool success = canvas.readPixels(srcRect, &wkbmp);
-                SkIRect clippedRect = DEV_RECT;
-                if (clippedRect.intersect(srcRect)) {
-                    REPORTER_ASSERT(reporter, success);
-                    checkRead(reporter, wkbmp, clippedRect.fLeft,
-                              clippedRect.fTop, true, false,
-                              SkCanvas::kNative_Premul_Config8888);
-                } else {
-                    REPORTER_ASSERT(reporter, !success);
+                GrContext* context = factory->get(type);
+                if (NULL == context) {
+                    continue;
+                }
+                device.reset(new SkGpuDevice(context, SkBitmap::kARGB_8888_Config, DEV_W, DEV_H));
+#else
+                continue;
+#endif
+            }
+            SkCanvas canvas(device);
+            fillCanvas(&canvas);
+
+            static const SkCanvas::Config8888 gReadConfigs[] = {
+                SkCanvas::kNative_Premul_Config8888,
+                SkCanvas::kNative_Unpremul_Config8888,
+/**
+    * There is a bug in Ganesh (http://code.google.com/p/skia/issues/detail?id=438)
+    * that causes the readback of pixels from BGRA canvas to an RGBA bitmap to
+    * fail. This should be removed as soon as the issue above is resolved.
+    */
+#if !defined(SK_BUILD_FOR_ANDROID)
+                SkCanvas::kBGRA_Premul_Config8888,
+                SkCanvas::kBGRA_Unpremul_Config8888,
+#endif
+                SkCanvas::kRGBA_Premul_Config8888,
+                SkCanvas::kRGBA_Unpremul_Config8888,
+            };
+            for (size_t rect = 0; rect < SK_ARRAY_COUNT(testRects); ++rect) {
+                const SkIRect& srcRect = testRects[rect];
+                for (BitmapInit bmi = kFirstBitmapInit;
+                     bmi < kBitmapInitCnt;
+                     bmi = nextBMI(bmi)) {
+                    for (size_t c = 0; c < SK_ARRAY_COUNT(gReadConfigs); ++c) {
+                        SkCanvas::Config8888 config8888 = gReadConfigs[c];
+                        SkBitmap bmp;
+                        init_bitmap(&bmp, srcRect, bmi);
+
+                        // if the bitmap has pixels allocated before the readPixels,
+                        // note that and fill them with pattern
+                        bool startsWithPixels = !bmp.isNull();
+                        if (startsWithPixels) {
+                            fillBitmap(&bmp);
+                        }
+                        uint32_t idBefore = canvas.getDevice()->accessBitmap(false).getGenerationID();
+                        bool success =
+                            canvas.readPixels(&bmp, srcRect.fLeft,
+                                              srcRect.fTop, config8888);
+                        uint32_t idAfter = canvas.getDevice()->accessBitmap(false).getGenerationID();
+
+                        // we expect to succeed when the read isn't fully clipped
+                        // out.
+                        bool expectSuccess = SkIRect::Intersects(srcRect, DEV_RECT);
+                        // determine whether we expected the read to succeed.
+                        REPORTER_ASSERT(reporter, success == expectSuccess);
+                        // read pixels should never change the gen id
+                        REPORTER_ASSERT(reporter, idBefore == idAfter);
+
+                        if (success || startsWithPixels) {
+                            checkRead(reporter, bmp, srcRect.fLeft, srcRect.fTop,
+                                      success, startsWithPixels, config8888);
+                        } else {
+                            // if we had no pixels beforehand and the readPixels
+                            // failed then our bitmap should still not have pixels
+                            REPORTER_ASSERT(reporter, bmp.isNull());
+                        }
+                    }
+                    // check the old webkit version of readPixels that clips the
+                    // bitmap size
+                    SkBitmap wkbmp;
+                    bool success = canvas.readPixels(srcRect, &wkbmp);
+                    SkIRect clippedRect = DEV_RECT;
+                    if (clippedRect.intersect(srcRect)) {
+                        REPORTER_ASSERT(reporter, success);
+                        checkRead(reporter, wkbmp, clippedRect.fLeft,
+                                  clippedRect.fTop, true, false,
+                                  SkCanvas::kNative_Premul_Config8888);
+                    } else {
+                        REPORTER_ASSERT(reporter, !success);
+                    }
                 }
             }
         }
diff --git a/tests/ReadWriteAlphaTest.cpp b/tests/ReadWriteAlphaTest.cpp
index eea78ce..a3bf5de 100644
--- a/tests/ReadWriteAlphaTest.cpp
+++ b/tests/ReadWriteAlphaTest.cpp
@@ -11,97 +11,103 @@
 
 #include "Test.h"
 #include "SkGpuDevice.h"
+#include "GrContextFactory.h"
 
 static const int X_SIZE = 12;
 static const int Y_SIZE = 12;
 
-static void ReadWriteAlphaTest(skiatest::Reporter* reporter, GrContext* context) {
-
-#if SK_SCALAR_IS_FIXED
-    // GPU device known not to work in the fixed pt build.
-    return;
-#endif
-
-    unsigned char textureData[X_SIZE][Y_SIZE];
-
-    memset(textureData, 0, X_SIZE * Y_SIZE);
-
-    GrTextureDesc desc;
-
-    // let Skia know we will be using this texture as a render target
-    desc.fFlags     = kRenderTarget_GrTextureFlagBit;
-    // it is a single channel texture
-    desc.fConfig    = kAlpha_8_GrPixelConfig;
-    desc.fWidth     = X_SIZE;
-    desc.fHeight    = Y_SIZE;
-
-    // We are initializing the texture with zeros here
-    GrTexture* texture = context->createUncachedTexture(desc, textureData, 0);
-    if (!texture) {
-        return;
-    }
-
-    GrAutoUnref au(texture);
-
-    // create a distinctive texture
-    for (int y = 0; y < Y_SIZE; ++y) {
-        for (int x = 0; x < X_SIZE; ++x) {
-            textureData[x][y] = x*Y_SIZE+y;
+static void ReadWriteAlphaTest(skiatest::Reporter* reporter, GrContextFactory* factory) {
+    for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) {
+        GrContextFactory::GLContextType glType = static_cast<GrContextFactory::GLContextType>(type);
+        if (!GrContextFactory::IsRenderingGLContext(glType)) {
+            continue;
         }
-    }
+        GrContext* context = factory->get(glType);
+        if (NULL == context) {
+            continue;
+        }
 
-    // upload the texture
-    texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
-                         textureData, 0);
+        unsigned char textureData[X_SIZE][Y_SIZE];
 
-    unsigned char readback[X_SIZE][Y_SIZE];
+        memset(textureData, 0, X_SIZE * Y_SIZE);
 
-    // clear readback to something non-zero so we can detect readback failures
-    memset(readback, 0x1, X_SIZE * Y_SIZE);
+        GrTextureDesc desc;
 
-    // read the texture back
-    texture->readPixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
-                        readback, 0);
+        // let Skia know we will be using this texture as a render target
+        desc.fFlags     = kRenderTarget_GrTextureFlagBit;
+        // it is a single channel texture
+        desc.fConfig    = kAlpha_8_GrPixelConfig;
+        desc.fWidth     = X_SIZE;
+        desc.fHeight    = Y_SIZE;
 
-    // make sure the original & read back versions match
-    bool match = true;
+        // We are initializing the texture with zeros here
+        GrTexture* texture = context->createUncachedTexture(desc, textureData, 0);
+        if (!texture) {
+            return;
+        }
 
-    for (int y = 0; y < Y_SIZE; ++y) {
-        for (int x = 0; x < X_SIZE; ++x) {
-            if (textureData[x][y] != readback[x][y]) {
-                match = false;
+        GrAutoUnref au(texture);
+
+        // create a distinctive texture
+        for (int y = 0; y < Y_SIZE; ++y) {
+            for (int x = 0; x < X_SIZE; ++x) {
+                textureData[x][y] = x*Y_SIZE+y;
             }
         }
-    }
 
-    REPORTER_ASSERT(reporter, match);
+        // upload the texture
+        texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
+                             textureData, 0);
 
-    // Now try writing on the single channel texture
-    SkAutoTUnref<SkDevice> device(new SkGpuDevice(context, texture->asRenderTarget()));
-    SkCanvas canvas(device);
+        unsigned char readback[X_SIZE][Y_SIZE];
 
-    SkPaint paint;
+        // clear readback to something non-zero so we can detect readback failures
+        memset(readback, 0x1, X_SIZE * Y_SIZE);
 
-    const SkRect rect = SkRect::MakeLTRB(-10, -10, X_SIZE + 10, Y_SIZE + 10);
+        // read the texture back
+        texture->readPixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
+                            readback, 0);
 
-    paint.setColor(SK_ColorWHITE);
+        // make sure the original & read back versions match
+        bool match = true;
 
-    canvas.drawRect(rect, paint);
-
-    texture->readPixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
-                        readback, 0);
-
-    match = true;
-
-    for (int y = 0; y < Y_SIZE; ++y) {
-        for (int x = 0; x < X_SIZE; ++x) {
-            if (0xFF != readback[x][y]) {
-                match = false;
+        for (int y = 0; y < Y_SIZE; ++y) {
+            for (int x = 0; x < X_SIZE; ++x) {
+                if (textureData[x][y] != readback[x][y]) {
+                    match = false;
+                }
             }
         }
-    }
 
-    REPORTER_ASSERT(reporter, match);
+        REPORTER_ASSERT(reporter, match);
+
+        // Now try writing on the single channel texture
+        SkAutoTUnref<SkDevice> device(new SkGpuDevice(context, texture->asRenderTarget()));
+        SkCanvas canvas(device);
+
+        SkPaint paint;
+
+        const SkRect rect = SkRect::MakeLTRB(-10, -10, X_SIZE + 10, Y_SIZE + 10);
+
+        paint.setColor(SK_ColorWHITE);
+
+        canvas.drawRect(rect, paint);
+
+        texture->readPixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
+                            readback, 0);
+
+        match = true;
+
+        for (int y = 0; y < Y_SIZE; ++y) {
+            for (int x = 0; x < X_SIZE; ++x) {
+                if (0xFF != readback[x][y]) {
+                    match = false;
+                }
+            }
+        }
+
+        REPORTER_ASSERT(reporter, match);
+    }
 }
 
 #ifndef SK_BUILD_FOR_ANDROID
diff --git a/tests/Test.cpp b/tests/Test.cpp
index de5e793..e0b997a 100644
--- a/tests/Test.cpp
+++ b/tests/Test.cpp
@@ -84,33 +84,20 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 #if SK_SUPPORT_GPU
-    static SkAutoTUnref<SkNativeGLContext> gGLContext;
-    static SkAutoTUnref<GrContext> gGrContext;
+#include "GrContextFactory.h"
+GrContextFactory gGrContextFactory;
 #endif
 
-void GpuTest::DestroyContext() {
+GrContextFactory* GpuTest::GetGrContextFactory() {
 #if SK_SUPPORT_GPU
-    // preserve this order, we want gGrContext destroyed before gGLContext
-    gGrContext.reset(NULL);
-    gGLContext.reset(NULL);
+    return &gGrContextFactory;
+#else
+    return NULL;
 #endif
 }
 
-
-GrContext* GpuTest::GetContext() {
+void GpuTest::DestroyContexts() {
 #if SK_SUPPORT_GPU
-    if (NULL == gGrContext.get()) {
-        gGLContext.reset(new SkNativeGLContext());
-        if (gGLContext.get()->init(800, 600)) {
-            GrBackendContext ctx = reinterpret_cast<GrBackendContext>(gGLContext.get()->gl());
-            gGrContext.reset(GrContext::Create(kOpenGL_GrBackend, ctx));
-        }
-    }
-    if (gGLContext.get()) {
-        gGLContext.get()->makeCurrent();
-    }
-    return gGrContext.get();
-#else
-    return NULL;
+    gGrContextFactory.destroyContexts();
 #endif
 }
diff --git a/tests/Test.h b/tests/Test.h
index 2cbd00b..2dca0e6 100644
--- a/tests/Test.h
+++ b/tests/Test.h
@@ -12,8 +12,7 @@
 #include "SkString.h"
 #include "SkTRegistry.h"
 
-class GrContext;
-class SkGLContext;
+class GrContextFactory;
 
 namespace skiatest {
 
@@ -100,13 +99,9 @@
 
     class GpuTest : public Test{
     public:
-        GpuTest() : Test() {
-            fContext = GetContext();
-        }
-        static GrContext* GetContext();
-        static void DestroyContext();
-    protected:
-        GrContext* fContext;
+        GpuTest() : Test() {}
+        static GrContextFactory* GetGrContextFactory();
+        static void DestroyContexts();
     private:
     };
 
diff --git a/tests/TestClassDef.h b/tests/TestClassDef.h
index ffef2a1..ee4b139 100644
--- a/tests/TestClassDef.h
+++ b/tests/TestClassDef.h
@@ -17,30 +17,28 @@
         void MyTestFunction(skiatest::Reporter*)
 */
 
-#define DEFINE_TESTCLASS(uiname, classname, function)                       \
-    namespace skiatest {                                                    \
-        class classname : public Test {                                     \
-        public:                                                             \
-            static Test* Factory(void*) { return SkNEW(classname); }        \
-        protected:                                                          \
-            virtual void onGetName(SkString* name) { name->set(uiname); }   \
-            virtual void onRun(Reporter* reporter) { function(reporter); }  \
-        };                                                                  \
-        static TestRegistry gReg(classname::Factory);                       \
+#define DEFINE_TESTCLASS(uiname, classname, function)                                   \
+    namespace skiatest {                                                                \
+        class classname : public Test {                                                 \
+        public:                                                                         \
+            static Test* Factory(void*) { return SkNEW(classname); }                    \
+        protected:                                                                      \
+            virtual void onGetName(SkString* name) SK_OVERRIDE { name->set(uiname); }   \
+            virtual void onRun(Reporter* reporter) SK_OVERRIDE { function(reporter); }  \
+        };                                                                              \
+        static TestRegistry gReg(classname::Factory);                                   \
     }
 
-#define DEFINE_GPUTESTCLASS(uiname, classname, function)                    \
-    namespace skiatest {                                                    \
-        class classname : public GpuTest {                                  \
-        public:                                                             \
-            static Test* Factory(void*) { return SkNEW(classname); }        \
-        protected:                                                          \
-            virtual void onGetName(SkString* name) { name->set(uiname); }   \
-            virtual void onRun(Reporter* reporter) {                        \
-                if (fContext) {                                             \
-                    function(reporter, fContext);                           \
-                }                                                           \
-            }                                                               \
-        };                                                                  \
-        static TestRegistry gReg(classname::Factory);                       \
+#define DEFINE_GPUTESTCLASS(uiname, classname, function)                                \
+    namespace skiatest {                                                                \
+        class classname : public GpuTest {                                              \
+        public:                                                                         \
+            static Test* Factory(void*) { return SkNEW(classname); }                    \
+        protected:                                                                      \
+            virtual void onGetName(SkString* name) SK_OVERRIDE { name->set(uiname); }   \
+            virtual void onRun(Reporter* reporter) SK_OVERRIDE {                        \
+                function(reporter, GetGrContextFactory());                              \
+            }                                                                           \
+        };                                                                              \
+        static TestRegistry gReg(classname::Factory);                                   \
     }
diff --git a/tests/WritePixelsTest.cpp b/tests/WritePixelsTest.cpp
index 715d8f7..14b2c51 100644
--- a/tests/WritePixelsTest.cpp
+++ b/tests/WritePixelsTest.cpp
@@ -14,8 +14,10 @@
 #include "SkRegion.h"
 #if SK_SUPPORT_GPU
 #include "SkGpuDevice.h"
+#include "GrContextFactory.h"
 #else
 class GrContext;
+class GrContextFactory;
 #endif
 
 static const int DEV_W = 100, DEV_H = 100;
@@ -346,7 +348,7 @@
     return true;
 }
 
-void WritePixelsTest(skiatest::Reporter* reporter, GrContext* context) {
+void WritePixelsTest(skiatest::Reporter* reporter, GrContextFactory* factory) {
     SkCanvas canvas;
 
     const SkIRect testRects[] = {
@@ -397,36 +399,64 @@
     };
 
     for (size_t i = 0; i < SK_ARRAY_COUNT(gCanvasConfigs); ++i) {
-        SkAutoTUnref<SkDevice> device(createDevice(gCanvasConfigs[i], context));
-        SkCanvas canvas(device);
+        int glCtxTypeCnt = 1;
+#if SK_SUPPORT_GPU
+        if (kGpu_DevType == gCanvasConfigs[i].fDevType)  {
+            glCtxTypeCnt = GrContextFactory::kGLContextTypeCnt;
+        }
+#endif
+        for (int glCtxType = 0; glCtxType < glCtxTypeCnt; ++glCtxType) {
+            GrContext* context = NULL;
+#if SK_SUPPORT_GPU
+            if (kGpu_DevType == gCanvasConfigs[i].fDevType) {
+                GrContextFactory::GLContextType type =
+                    static_cast<GrContextFactory::GLContextType>(glCtxType);
+#if SK_ANGLE // This test breaks ANGLE with GL errors in texsubimage2D. Disable until debugged.
+                if (type == GrContextFactory::kANGLE_GLContextType) {
+                    continue;
+                }
+#endif
+                if (!GrContextFactory::IsRenderingGLContext(type)) {
+                    continue;
+                }
+                context = factory->get(type);
+                if (NULL == context) {
+                    continue;
+                }
+            }
+#endif
 
-        static const SkCanvas::Config8888 gSrcConfigs[] = {
-            SkCanvas::kNative_Premul_Config8888,
-            SkCanvas::kNative_Unpremul_Config8888,
-            SkCanvas::kBGRA_Premul_Config8888,
-            SkCanvas::kBGRA_Unpremul_Config8888,
-            SkCanvas::kRGBA_Premul_Config8888,
-            SkCanvas::kRGBA_Unpremul_Config8888,
-        };
-        for (size_t r = 0; r < SK_ARRAY_COUNT(testRects); ++r) {
-            const SkIRect& rect = testRects[r];
-            for (int tightBmp = 0; tightBmp < 2; ++tightBmp) {
-                for (size_t c = 0; c < SK_ARRAY_COUNT(gSrcConfigs); ++c) {
-                    fillCanvas(&canvas);
-                    SkCanvas::Config8888 config8888 = gSrcConfigs[c];
-                    SkBitmap bmp;
-                    REPORTER_ASSERT(reporter, setupBitmap(&bmp, config8888, rect.width(), rect.height(), SkToBool(tightBmp)));
-                    uint32_t idBefore = canvas.getDevice()->accessBitmap(false).getGenerationID();
-                    canvas.writePixels(bmp, rect.fLeft, rect.fTop, config8888);
-                    uint32_t idAfter = canvas.getDevice()->accessBitmap(false).getGenerationID();
-                    REPORTER_ASSERT(reporter, checkWrite(reporter, &canvas, bmp, rect.fLeft, rect.fTop, config8888));
+            SkAutoTUnref<SkDevice> device(createDevice(gCanvasConfigs[i], context));
+            SkCanvas canvas(device);
 
-                    // we should change the genID iff pixels were actually written.
-                    SkIRect canvasRect = SkIRect::MakeSize(canvas.getDeviceSize());
-                    SkIRect writeRect = SkIRect::MakeXYWH(rect.fLeft, rect.fTop,
-                                                          bmp.width(), bmp.height());
-                    bool intersects = SkIRect::Intersects(canvasRect, writeRect) ;
-                    REPORTER_ASSERT(reporter, intersects == (idBefore != idAfter));
+            static const SkCanvas::Config8888 gSrcConfigs[] = {
+                SkCanvas::kNative_Premul_Config8888,
+                SkCanvas::kNative_Unpremul_Config8888,
+                SkCanvas::kBGRA_Premul_Config8888,
+                SkCanvas::kBGRA_Unpremul_Config8888,
+                SkCanvas::kRGBA_Premul_Config8888,
+                SkCanvas::kRGBA_Unpremul_Config8888,
+            };
+            for (size_t r = 0; r < SK_ARRAY_COUNT(testRects); ++r) {
+                const SkIRect& rect = testRects[r];
+                for (int tightBmp = 0; tightBmp < 2; ++tightBmp) {
+                    for (size_t c = 0; c < SK_ARRAY_COUNT(gSrcConfigs); ++c) {
+                        fillCanvas(&canvas);
+                        SkCanvas::Config8888 config8888 = gSrcConfigs[c];
+                        SkBitmap bmp;
+                        REPORTER_ASSERT(reporter, setupBitmap(&bmp, config8888, rect.width(), rect.height(), SkToBool(tightBmp)));
+                        uint32_t idBefore = canvas.getDevice()->accessBitmap(false).getGenerationID();
+                        canvas.writePixels(bmp, rect.fLeft, rect.fTop, config8888);
+                        uint32_t idAfter = canvas.getDevice()->accessBitmap(false).getGenerationID();
+                        REPORTER_ASSERT(reporter, checkWrite(reporter, &canvas, bmp, rect.fLeft, rect.fTop, config8888));
+
+                        // we should change the genID iff pixels were actually written.
+                        SkIRect canvasRect = SkIRect::MakeSize(canvas.getDeviceSize());
+                        SkIRect writeRect = SkIRect::MakeXYWH(rect.fLeft, rect.fTop,
+                                                              bmp.width(), bmp.height());
+                        bool intersects = SkIRect::Intersects(canvasRect, writeRect) ;
+                        REPORTER_ASSERT(reporter, intersects == (idBefore != idAfter));
+                    }
                 }
             }
         }
diff --git a/tests/skia_test.cpp b/tests/skia_test.cpp
index 8a1feae..18c8c84 100644
--- a/tests/skia_test.cpp
+++ b/tests/skia_test.cpp
@@ -154,7 +154,7 @@
 #endif
 
     SkGraphics::Term();
-    GpuTest::DestroyContext();
+    GpuTest::DestroyContexts();
 
     return (failCount == 0) ? 0 : 1;
 }