Make SkGpuDevice know its alpha type

Make SkImage_Gpu snapshots opaque if surface is opaque.

BUG=skia:3965

Review URL: https://codereview.chromium.org/1205643002
diff --git a/tests/SurfaceTest.cpp b/tests/SurfaceTest.cpp
index 0114fb6..cfaa669 100644
--- a/tests/SurfaceTest.cpp
+++ b/tests/SurfaceTest.cpp
@@ -30,16 +30,20 @@
     kRasterDirect_SurfaceType,
     kGpu_SurfaceType,
     kGpuScratch_SurfaceType,
+
+    kLastSurfaceType = kGpuScratch_SurfaceType
 };
+static const int kSurfaceTypeCnt = kLastSurfaceType + 1;
 
 static void release_storage(void* pixels, void* context) {
     SkASSERT(pixels == context);
     sk_free(pixels);
 }
 
-static SkSurface* createSurface(SurfaceType surfaceType, GrContext* context,
-                                SkImageInfo* requestedInfo = NULL) {
-    static const SkImageInfo info = SkImageInfo::MakeN32Premul(10, 10);
+static SkSurface* create_surface(SurfaceType surfaceType, GrContext* context,
+                                 SkAlphaType at = kPremul_SkAlphaType,
+                                 SkImageInfo* requestedInfo = NULL) {
+    const SkImageInfo info = SkImageInfo::MakeN32(10, 10, at);
 
     if (requestedInfo) {
         *requestedInfo = info;
@@ -219,8 +223,8 @@
     }
 };
 
-static SkImage* createImage(ImageType imageType, GrContext* context, SkColor color,
-                            ReleaseDataContext* releaseContext) {
+static SkImage* create_image(ImageType imageType, GrContext* context, SkColor color,
+                             ReleaseDataContext* releaseContext) {
     const SkPMColor pmcolor = SkPreMultiplyColor(color);
     const SkImageInfo info = SkImageInfo::MakeN32Premul(10, 10);
     const size_t rowBytes = info.minRowBytes();
@@ -347,7 +351,7 @@
         size_t rowBytes;
 
         releaseCtx.fData = NULL;
-        SkAutoTUnref<SkImage> image(createImage(gRec[i].fType, ctx, color, &releaseCtx));
+        SkAutoTUnref<SkImage> image(create_image(gRec[i].fType, ctx, color, &releaseCtx));
         if (!image.get()) {
             SkDebugf("failed to createImage[%d] %s\n", i, gRec[i].fName);
             continue;   // gpu may not be enabled
@@ -417,8 +421,8 @@
             SkImageInfo info, requestInfo;
             size_t rowBytes;
 
-            SkAutoTUnref<SkSurface> surface(createSurface(gRec[i].fType, context,
-                                                          &requestInfo));
+            SkAutoTUnref<SkSurface> surface(create_surface(gRec[i].fType, context,
+                                                           kPremul_SkAlphaType, &requestInfo));
             surface->getCanvas()->clear(color);
 
             const void* addr = surface->getCanvas()->peekPixels(&info, &rowBytes);
@@ -484,8 +488,8 @@
         for (size_t j = 0; j < SK_ARRAY_COUNT(gRec); ++j) {
             SkImageInfo info, requestInfo;
             
-            SkAutoTUnref<SkSurface> surface(createSurface(gRec[j].fType, context,
-                                                          &requestInfo));
+            SkAutoTUnref<SkSurface> surface(create_surface(gRec[j].fType, context,
+                                                           kPremul_SkAlphaType,  &requestInfo));
             SkCanvas* canvas = surface->getCanvas();
             canvas->clear(0);
 
@@ -501,10 +505,35 @@
     }
 }
 
+static void test_snap_alphatype(skiatest::Reporter* reporter, GrContextFactory* factory) {
+    GrContext* context = NULL;
+#if SK_SUPPORT_GPU
+    context = factory->get(GrContextFactory::kNative_GLContextType);
+    if (NULL == context) {
+        return;
+    }
+#endif
+    for (int opaque = 0; opaque < 2; ++opaque) {
+        SkAlphaType atype = SkToBool(opaque) ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
+        for (int st = 0; st < kSurfaceTypeCnt; ++st) {
+            SurfaceType stype = (SurfaceType)st;
+            SkAutoTUnref<SkSurface> surface(create_surface(stype, context, atype));
+            REPORTER_ASSERT(reporter, surface);
+            if (surface) {
+                SkAutoTUnref<SkImage> image(surface->newImageSnapshot());
+                REPORTER_ASSERT(reporter, image);
+                if (image) {
+                    REPORTER_ASSERT(reporter, image->isOpaque() == SkToBool(opaque));
+                }
+            }
+        }
+    }
+}
+
 static void TestSurfaceCopyOnWrite(skiatest::Reporter* reporter, SurfaceType surfaceType,
                                    GrContext* context) {
     // Verify that the right canvas commands trigger a copy on write
-    SkSurface* surface = createSurface(surfaceType, context);
+    SkSurface* surface = create_surface(surfaceType, context);
     SkAutoTUnref<SkSurface> aur_surface(surface);
     SkCanvas* canvas = surface->getCanvas();
 
@@ -587,7 +616,7 @@
     // This test succeeds by not triggering an assertion.
     // The test verifies that the surface remains writable (usable) after
     // acquiring and releasing a snapshot without triggering a copy on write.
-    SkAutoTUnref<SkSurface> surface(createSurface(surfaceType, context));
+    SkAutoTUnref<SkSurface> surface(create_surface(surfaceType, context));
     SkCanvas* canvas = surface->getCanvas();
     canvas->clear(1);
     surface->newImageSnapshot()->unref();  // Create and destroy SkImage
@@ -602,8 +631,8 @@
     // Bug was caused by onCopyOnWrite releasing the old surface texture
     // back to the scratch texture pool even though the texture is used
     // by and active SkImage_Gpu.
-    SkAutoTUnref<SkSurface> surface1(createSurface(surfaceType, context));
-    SkAutoTUnref<SkSurface> surface2(createSurface(surfaceType, context));
+    SkAutoTUnref<SkSurface> surface1(create_surface(surfaceType, context));
+    SkAutoTUnref<SkSurface> surface2(create_surface(surfaceType, context));
     SkCanvas* canvas1 = surface1->getCanvas();
     SkCanvas* canvas2 = surface2->getCanvas();
     canvas1->clear(1);
@@ -633,7 +662,7 @@
 static void TestGetTexture(skiatest::Reporter* reporter,
                                  SurfaceType surfaceType,
                                  GrContext* context) {
-    SkAutoTUnref<SkSurface> surface(createSurface(surfaceType, context));
+    SkAutoTUnref<SkSurface> surface(create_surface(surfaceType, context));
     SkAutoTUnref<SkImage> image(surface->newImageSnapshot());
     GrTexture* texture = as_IB(image)->getTexture();
     if (surfaceType == kGpu_SurfaceType || surfaceType == kGpuScratch_SurfaceType) {
@@ -700,13 +729,13 @@
     // are made before a canvas is created.
     {
         // Test passes by not asserting
-        SkSurface* surface = createSurface(surfaceType, context);
+        SkSurface* surface = create_surface(surfaceType, context);
         SkAutoTUnref<SkSurface> aur_surface(surface);
         surface->notifyContentWillChange(mode);
         SkDEBUGCODE(surface->validate();)
     }
     {
-        SkSurface* surface = createSurface(surfaceType, context);
+        SkSurface* surface = create_surface(surfaceType, context);
         SkAutoTUnref<SkSurface> aur_surface(surface);
         SkImage* image1 = surface->newImageSnapshot();
         SkAutoTUnref<SkImage> aur_image1(image1);
@@ -740,6 +769,8 @@
 
     test_accessPixels(reporter, factory);
 
+    test_snap_alphatype(reporter, factory);
+
 #if SK_SUPPORT_GPU
     TestGetTexture(reporter, kRaster_SurfaceType, NULL);
     if (factory) {