Revert "Remove SkImage deferred texture image data APIs."

This reverts commit 4f5e1d4ff3fa9f240398c9a08be94beb1c16dad0.

Reason for revert: Unfortunately, we need this in Chrome for a bit longer. Working on understanding why the new path led to regressions. Will re-land this once the new path sticks.

Original change's description:
> Remove SkImage deferred texture image data APIs.
> 
> These APIs existed for Chrome. Chrome is no longer using them.
> 
> Change-Id: I15a5e2f88c7e8d1356188748fc68d4658f6f1849
> Reviewed-on: https://skia-review.googlesource.com/81021
> Reviewed-by: Brian Osman <brianosman@google.com>
> Reviewed-by: Cary Clark <caryclark@google.com>
> Commit-Queue: Brian Salomon <bsalomon@google.com>

TBR=bsalomon@google.com,brianosman@google.com,caryclark@google.com,caryclark@skia.org

# Not skipping CQ checks because original CL landed > 1 day ago.

Change-Id: Ic9f683f262f2e1d0469156360f5ffaee977ca44a
Reviewed-on: https://skia-review.googlesource.com/86280
Reviewed-by: Eric Karl <ericrk@chromium.org>
Commit-Queue: Eric Karl <ericrk@chromium.org>
diff --git a/tests/ImageTest.cpp b/tests/ImageTest.cpp
index 483fbf7..31a5909 100644
--- a/tests/ImageTest.cpp
+++ b/tests/ImageTest.cpp
@@ -967,6 +967,179 @@
     });
 }
 
+static void check_images_same(skiatest::Reporter* reporter, const SkImage* a, const SkImage* b) {
+    if (a->width() != b->width() || a->height() != b->height()) {
+        ERRORF(reporter, "Images must have the same size");
+        return;
+    }
+    if (a->alphaType() != b->alphaType()) {
+        ERRORF(reporter, "Images must have the same alpha type");
+        return;
+    }
+
+    SkImageInfo info = SkImageInfo::MakeN32Premul(a->width(), a->height());
+    SkAutoPixmapStorage apm;
+    SkAutoPixmapStorage bpm;
+
+    apm.alloc(info);
+    bpm.alloc(info);
+
+    if (!a->readPixels(apm, 0, 0)) {
+        ERRORF(reporter, "Could not read image a's pixels");
+        return;
+    }
+    if (!b->readPixels(bpm, 0, 0)) {
+        ERRORF(reporter, "Could not read image b's pixels");
+        return;
+    }
+
+    for (auto y = 0; y < info.height(); ++y) {
+        for (auto x = 0; x < info.width(); ++x) {
+            uint32_t pixelA = *apm.addr32(x, y);
+            uint32_t pixelB = *bpm.addr32(x, y);
+            if (pixelA != pixelB) {
+                ERRORF(reporter, "Expected image pixels to be the same. At %d,%d 0x%08x != 0x%08x",
+                       x, y, pixelA, pixelB);
+                return;
+            }
+        }
+    }
+}
+
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DeferredTextureImage, reporter, ctxInfo) {
+    GrContext* context = ctxInfo.grContext();
+    sk_gpu_test::TestContext* testContext = ctxInfo.testContext();
+    sk_sp<GrContextThreadSafeProxy> proxy = context->threadSafeProxy();
+
+    GrContextFactory otherFactory;
+    ContextInfo otherContextInfo = otherFactory.getContextInfo(ctxInfo.type());
+
+    testContext->makeCurrent();
+    REPORTER_ASSERT(reporter, proxy);
+    auto createLarge = [context] {
+        return create_image_large(context->caps()->maxTextureSize());
+    };
+    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}},
+          nullptr, kN32_SkColorType, kNone_SkFilterQuality, 1, true },
+        { create_codec_image,    {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
+          nullptr, kN32_SkColorType, kNone_SkFilterQuality, 1, true },
+        { create_data_image,     {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
+          nullptr, kN32_SkColorType, kNone_SkFilterQuality, 1, true },
+        { create_picture_image,  {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
+          nullptr, kN32_SkColorType, kNone_SkFilterQuality, 1, false },
+        { [context] { return create_gpu_image(context); },
+          {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
+          nullptr, kN32_SkColorType, kNone_SkFilterQuality, 1, false },
+        // Create a texture image in a another GrContext.
+        { [testContext, otherContextInfo] {
+            otherContextInfo.testContext()->makeCurrent();
+            sk_sp<SkImage> otherContextImage = create_gpu_image(otherContextInfo.grContext());
+            testContext->makeCurrent();
+            return otherContextImage;
+          }, {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
+          nullptr, kN32_SkColorType, kNone_SkFilterQuality, 1, false },
+        // Create an image that is too large to upload.
+        { createLarge, {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
+          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}},
+          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}},
+          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}},
+          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 },
+    };
+
+
+    for (auto testCase : testCases) {
+        sk_sp<SkImage> image(testCase.fImageFactory());
+        if (!image) {
+            ERRORF(reporter, "Failed to create image!");
+            continue;
+        }
+
+        size_t size = image->getDeferredTextureImageData(*proxy, testCase.fParams.data(),
+                                                         static_cast<int>(testCase.fParams.size()),
+                                                         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.",
+                   kFS[testCase.fExpectation]);
+        }
+        if (size) {
+            void* buffer = sk_malloc_throw(size);
+            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, 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, testCase.fColorSpace.get(),
+                                                   testCase.fColorType)) {
+                ERRORF(reporter, "deferred image size succeeded but creation failed.");
+            } else {
+                for (auto budgeted : { SkBudgeted::kNo, SkBudgeted::kYes }) {
+                    sk_sp<SkImage> newImage(
+                        SkImage::MakeFromDeferredTextureImageData(context, buffer, budgeted));
+                    REPORTER_ASSERT(reporter, newImage != nullptr);
+                    if (newImage) {
+                        // Scale the image in software for comparison.
+                        SkImageInfo scaled_info = SkImageInfo::MakeN32(
+                                                    image->width() / testCase.fExpectedScaleFactor,
+                                                    image->height() / testCase.fExpectedScaleFactor,
+                                                    image->alphaType());
+                        SkAutoPixmapStorage scaled;
+                        scaled.alloc(scaled_info);
+                        image->scalePixels(scaled, testCase.fExpectedQuality);
+                        sk_sp<SkImage> scaledImage = SkImage::MakeRasterCopy(scaled);
+                        check_images_same(reporter, scaledImage.get(), newImage.get());
+                    }
+                    // The other context should not be able to create images from texture data
+                    // created by the original context.
+                    sk_sp<SkImage> newImage2(SkImage::MakeFromDeferredTextureImageData(
+                        otherContextInfo.grContext(), buffer, budgeted));
+                    REPORTER_ASSERT(reporter, !newImage2);
+                    testContext->makeCurrent();
+                }
+            }
+            sk_free(buffer);
+        }
+
+        testContext->makeCurrent();
+        context->flush();
+    }
+}
+
 static uint32_t GetIdForBackendObject(GrContext* ctx, GrBackendObject object) {
     if (!object) {
         return 0;