Reland DeferredTextureImageData low-bit-depth/dithering support

Cause DeferredTextureImageData functionality to support low bit depth
(4444, 565) image formats (with dithering).

Updated to handle colorspace + 4444 colortype correctly.

Bug: 720105
Change-Id: Ib7e14d937849f4f6b08fda6992a240bb203d0089
Reviewed-on: https://skia-review.googlesource.com/19094
Commit-Queue: Eric Karl <ericrk@chromium.org>
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/tests/ImageTest.cpp b/tests/ImageTest.cpp
index 5b28f00..84f9084 100644
--- a/tests/ImageTest.cpp
+++ b/tests/ImageTest.cpp
@@ -1024,21 +1024,23 @@
     struct {
         std::function<sk_sp<SkImage> ()>                      fImageFactory;
         std::vector<SkImage::DeferredTextureImageUsageParams> fParams;
+        sk_sp<SkColorSpace>                                   fColorSpace;
+        SkColorType                                           fColorType;
         SkFilterQuality                                       fExpectedQuality;
         int                                                   fExpectedScaleFactor;
         bool                                                  fExpectation;
     } testCases[] = {
         { create_image,          {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
-          kNone_SkFilterQuality, 1, true },
+          nullptr, kN32_SkColorType, kNone_SkFilterQuality, 1, true },
         { create_codec_image,    {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
-          kNone_SkFilterQuality, 1, true },
+          nullptr, kN32_SkColorType, kNone_SkFilterQuality, 1, true },
         { create_data_image,     {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
-          kNone_SkFilterQuality, 1, true },
+          nullptr, kN32_SkColorType, kNone_SkFilterQuality, 1, true },
         { create_picture_image,  {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
-          kNone_SkFilterQuality, 1, false },
+          nullptr, kN32_SkColorType, kNone_SkFilterQuality, 1, false },
         { [context] { return create_gpu_image(context); },
           {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
-          kNone_SkFilterQuality, 1, false },
+          nullptr, kN32_SkColorType, kNone_SkFilterQuality, 1, false },
         // Create a texture image in a another GrContext.
         { [testContext, otherContextInfo] {
             otherContextInfo.testContext()->makeCurrent();
@@ -1046,21 +1048,34 @@
             testContext->makeCurrent();
             return otherContextImage;
           }, {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
-          kNone_SkFilterQuality, 1, false },
+          nullptr, kN32_SkColorType, kNone_SkFilterQuality, 1, false },
         // Create an image that is too large to upload.
         { createLarge, {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
-          kNone_SkFilterQuality, 1, false },
+          nullptr, kN32_SkColorType, kNone_SkFilterQuality, 1, false },
         // Create an image that is too large, but is scaled to an acceptable size.
         { createLarge, {{SkMatrix::I(), kMedium_SkFilterQuality, 4}},
-          kMedium_SkFilterQuality, 16, true},
+          nullptr, kN32_SkColorType, kMedium_SkFilterQuality, 16, true},
         // Create an image with multiple low filter qualities, make sure we round up.
         { createLarge, {{SkMatrix::I(), kNone_SkFilterQuality, 4},
                         {SkMatrix::I(), kMedium_SkFilterQuality, 4}},
-          kMedium_SkFilterQuality, 16, true},
+          nullptr, kN32_SkColorType, kMedium_SkFilterQuality, 16, true},
         // Create an image with multiple prescale levels, make sure we chose the minimum scale.
         { createLarge, {{SkMatrix::I(), kMedium_SkFilterQuality, 5},
                         {SkMatrix::I(), kMedium_SkFilterQuality, 4}},
-          kMedium_SkFilterQuality, 16, true},
+          nullptr, kN32_SkColorType, kMedium_SkFilterQuality, 16, true},
+        // Create a images which are decoded to a 4444 backing.
+        { create_image,       {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
+          nullptr, kARGB_4444_SkColorType, kNone_SkFilterQuality, 1, true },
+        { create_codec_image, {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
+          nullptr, kARGB_4444_SkColorType, kNone_SkFilterQuality, 1, true },
+        { create_data_image,  {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
+          nullptr, kARGB_4444_SkColorType, kNone_SkFilterQuality, 1, true },
+        // Valid SkColorSpace and SkColorType.
+        { create_data_image,  {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
+          SkColorSpace::MakeSRGB(), kN32_SkColorType, kNone_SkFilterQuality, 1, true },
+        // Invalid SkColorSpace and SkColorType.
+        { create_data_image,  {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
+          SkColorSpace::MakeSRGB(), kARGB_4444_SkColorType, kNone_SkFilterQuality, 1, false },
     };
 
 
@@ -1073,7 +1088,8 @@
 
         size_t size = image->getDeferredTextureImageData(*proxy, testCase.fParams.data(),
                                                          static_cast<int>(testCase.fParams.size()),
-                                                         nullptr, nullptr);
+                                                         nullptr, testCase.fColorSpace.get(),
+                                                         testCase.fColorType);
         static const char *const kFS[] = { "fail", "succeed" };
         if (SkToBool(size) != testCase.fExpectation) {
             ERRORF(reporter,  "This image was expected to %s but did not.",
@@ -1084,12 +1100,14 @@
             void* misaligned = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(buffer) + 3);
             if (image->getDeferredTextureImageData(*proxy, testCase.fParams.data(),
                                                    static_cast<int>(testCase.fParams.size()),
-                                                   misaligned, nullptr)) {
+                                                   misaligned, testCase.fColorSpace.get(),
+                                                   testCase.fColorType)) {
                 ERRORF(reporter, "Should fail when buffer is misaligned.");
             }
             if (!image->getDeferredTextureImageData(*proxy, testCase.fParams.data(),
                                                     static_cast<int>(testCase.fParams.size()),
-                                                    buffer, nullptr)) {
+                                                    buffer, testCase.fColorSpace.get(),
+                                                   testCase.fColorType)) {
                 ERRORF(reporter, "deferred image size succeeded but creation failed.");
             } else {
                 for (auto budgeted : { SkBudgeted::kNo, SkBudgeted::kYes }) {