Reland DeferredTextureImageData low-bit-depth/dithering support
authorEric Karl <ericrk@chromium.org>
Fri, 16 Jun 2017 16:08:15 +0000 (09:08 -0700)
committerSkia Commit-Bot <skia-commit-bot@chromium.org>
Fri, 16 Jun 2017 17:03:09 +0000 (17:03 +0000)
Merge to M60

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

Updated to handle colorspace + 4444 colortype correctly.

No-Tree-Checks: true
No-Try: true
No-Presubmit: true
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>
Reviewed-on: https://skia-review.googlesource.com/20128

gm/deferredtextureimage.cpp
include/core/SkImage.h
src/core/SkAutoPixmapStorage.cpp
src/core/SkAutoPixmapStorage.h
src/image/SkImage.cpp
src/image/SkImage_Gpu.cpp
tests/ImageTest.cpp

index 9c1fe6a..b034a4e 100644 (file)
@@ -17,7 +17,9 @@
 // Helper function that uploads the given SkImage using MakeFromDeferredTextureImageData and then
 // draws the uploaded version at the specified coordinates.
 static void DrawDeferredTextureImageData(SkCanvas* canvas,
-                                         SkImage::DeferredTextureImageUsageParams* params) {
+                                         const char* resourceName,
+                                         SkImage::DeferredTextureImageUsageParams* params,
+                                         SkColorType dstColorType) {
     GrContext* context = canvas->getGrContext();
     if (!context) {
         skiagm::GM::DrawGpuOnlyMessage(canvas);
@@ -27,14 +29,14 @@ static void DrawDeferredTextureImageData(SkCanvas* canvas,
 
 
 
-    sk_sp<SkImage> encodedImage = GetResourceAsImage("mandrill_512.png");
+    sk_sp<SkImage> encodedImage = GetResourceAsImage(resourceName);
     if (!encodedImage) {
         SkDebugf("\nCould not load resource.\n");
         return;
     }
 
     size_t requiredMemoryInBytes = encodedImage->getDeferredTextureImageData(
-        *proxy, params, 1, nullptr, canvas->imageInfo().colorSpace());
+        *proxy, params, 1, nullptr, canvas->imageInfo().colorSpace(), dstColorType);
     if (requiredMemoryInBytes == 0) {
         SkDebugf("\nCould not create DeferredTextureImageData.\n");
         return;
@@ -43,7 +45,7 @@ static void DrawDeferredTextureImageData(SkCanvas* canvas,
     std::vector<uint8_t> memory;
     memory.resize(requiredMemoryInBytes);
     encodedImage->getDeferredTextureImageData(
-        *proxy, params, 1, memory.data(), canvas->imageInfo().colorSpace());
+        *proxy, params, 1, memory.data(), canvas->imageInfo().colorSpace(), dstColorType);
     sk_sp<SkImage> uploadedEncodedImage = SkImage::MakeFromDeferredTextureImageData(
         context, memory.data(), SkBudgeted::kNo);
 
@@ -52,14 +54,14 @@ static void DrawDeferredTextureImageData(SkCanvas* canvas,
 
 
     SkBitmap bitmap;
-    if (!GetResourceAsBitmap("mandrill_512.png", &bitmap)) {
+    if (!GetResourceAsBitmap(resourceName, &bitmap)) {
         SkDebugf("\nCould not decode resource.\n");
         return;
     }
     sk_sp<SkImage> decodedImage = SkImage::MakeFromBitmap(bitmap);
 
     requiredMemoryInBytes = decodedImage->getDeferredTextureImageData(
-        *proxy, params, 1, nullptr, canvas->imageInfo().colorSpace());
+        *proxy, params, 1, nullptr, canvas->imageInfo().colorSpace(), dstColorType);
     if (requiredMemoryInBytes == 0) {
         SkDebugf("\nCould not create DeferredTextureImageData.\n");
         return;
@@ -67,15 +69,16 @@ static void DrawDeferredTextureImageData(SkCanvas* canvas,
 
     memory.resize(requiredMemoryInBytes);
     decodedImage->getDeferredTextureImageData(
-        *proxy, params, 1, memory.data(), canvas->imageInfo().colorSpace());
+        *proxy, params, 1, memory.data(), canvas->imageInfo().colorSpace(), dstColorType);
     sk_sp<SkImage> uploadedDecodedImage = SkImage::MakeFromDeferredTextureImageData(
         context, memory.data(), SkBudgeted::kNo);
 
-    canvas->drawImage(uploadedDecodedImage, 512 + 20, 10);
+    canvas->drawImage(uploadedDecodedImage, encodedImage->width() + 20, 10);
 }
 
 static void DrawDeferredTextureImageMipMapTree(SkCanvas* canvas, SkImage* image,
-                                               SkImage::DeferredTextureImageUsageParams* params) {
+                                               SkImage::DeferredTextureImageUsageParams* params,
+                                               SkColorType dstColorType) {
     GrContext* context = canvas->getGrContext();
     if (!context) {
         skiagm::GM::DrawGpuOnlyMessage(canvas);
@@ -88,7 +91,7 @@ static void DrawDeferredTextureImageMipMapTree(SkCanvas* canvas, SkImage* image,
 
     int mipLevelCount = SkMipMap::ComputeLevelCount(image->width(), image->height());
     size_t requiredMemoryInBytes = image->getDeferredTextureImageData(
-        *proxy, params, 1, nullptr, canvas->imageInfo().colorSpace());
+        *proxy, params, 1, nullptr, canvas->imageInfo().colorSpace(), dstColorType);
     if (requiredMemoryInBytes == 0) {
         SkDebugf("\nCould not create DeferredTextureImageData.\n");
         return;
@@ -97,7 +100,7 @@ static void DrawDeferredTextureImageMipMapTree(SkCanvas* canvas, SkImage* image,
     std::vector<uint8_t> memory;
     memory.resize(requiredMemoryInBytes);
     image->getDeferredTextureImageData(
-        *proxy, params, 1, memory.data(), canvas->imageInfo().colorSpace());
+        *proxy, params, 1, memory.data(), canvas->imageInfo().colorSpace(), dstColorType);
     sk_sp<SkImage> uploadedImage = SkImage::MakeFromDeferredTextureImageData(
         context, memory.data(), SkBudgeted::kNo);
 
@@ -145,13 +148,19 @@ static void DrawDeferredTextureImageMipMapTree(SkCanvas* canvas, SkImage* image,
 DEF_SIMPLE_GM(deferred_texture_image_none, canvas, 512 + 512 + 30, 512 + 20) {
     auto params = SkImage::DeferredTextureImageUsageParams(SkMatrix::MakeScale(1.f, 1.f),
                                                            kNone_SkFilterQuality, 0);
-    DrawDeferredTextureImageData(canvas, &params);
+    DrawDeferredTextureImageData(canvas, "mandrill_512.png", &params, kN32_SkColorType);
 }
 
 DEF_SIMPLE_GM(deferred_texture_image_low, canvas, 512 + 512 + 30, 512 + 20) {
     auto params = SkImage::DeferredTextureImageUsageParams(SkMatrix::MakeScale(1.f, 1.f),
                                                            kLow_SkFilterQuality, 0);
-    DrawDeferredTextureImageData(canvas, &params);
+    DrawDeferredTextureImageData(canvas, "mandrill_512.png", &params, kN32_SkColorType);
+}
+
+DEF_SIMPLE_GM(deferred_texture_image_low_dithered, canvas, 180 + 180 + 30, 180 + 20) {
+    auto params = SkImage::DeferredTextureImageUsageParams(SkMatrix::MakeScale(0.25f, 0.25f),
+                                                           kLow_SkFilterQuality, 0);
+    DrawDeferredTextureImageData(canvas, "dog.jpg", &params, kARGB_4444_SkColorType);
 }
 
 DEF_SIMPLE_GM(deferred_texture_image_medium_encoded, canvas, 512 + 512 + 30, 1110) {
@@ -163,7 +172,7 @@ DEF_SIMPLE_GM(deferred_texture_image_medium_encoded, canvas, 512 + 512 + 30, 111
 
     auto params = SkImage::DeferredTextureImageUsageParams(SkMatrix::MakeScale(0.25f, 0.25f),
                                                            kMedium_SkFilterQuality, 0);
-    DrawDeferredTextureImageMipMapTree(canvas, encodedImage.get(), &params);
+    DrawDeferredTextureImageMipMapTree(canvas, encodedImage.get(), &params, kN32_SkColorType);
 }
 
 DEF_SIMPLE_GM(deferred_texture_image_medium_decoded, canvas, 512 + 512 + 30, 1110) {
@@ -176,13 +185,13 @@ DEF_SIMPLE_GM(deferred_texture_image_medium_decoded, canvas, 512 + 512 + 30, 111
 
     auto params = SkImage::DeferredTextureImageUsageParams(SkMatrix::MakeScale(0.25f, 0.25f),
                                                            kMedium_SkFilterQuality, 0);
-    DrawDeferredTextureImageMipMapTree(canvas, decodedImage.get(), &params);
+    DrawDeferredTextureImageMipMapTree(canvas, decodedImage.get(), &params, kN32_SkColorType);
 }
 
 DEF_SIMPLE_GM(deferred_texture_image_high, canvas, 512 + 512 + 30, 512 + 20) {
     auto params = SkImage::DeferredTextureImageUsageParams(SkMatrix::MakeScale(1.f, 1.f),
                                                            kHigh_SkFilterQuality, 0);
-    DrawDeferredTextureImageData(canvas, &params);
+    DrawDeferredTextureImageData(canvas, "mandrill_512.png", &params, kN32_SkColorType);
 }
 
 DEF_SIMPLE_GM(deferred_texture_image_medium_encoded_indexed, canvas, 128 + 128 + 30, 340) {
@@ -194,7 +203,7 @@ DEF_SIMPLE_GM(deferred_texture_image_medium_encoded_indexed, canvas, 128 + 128 +
 
     auto params = SkImage::DeferredTextureImageUsageParams(SkMatrix::MakeScale(0.25f, 0.25f),
                                                            kMedium_SkFilterQuality, 0);
-    DrawDeferredTextureImageMipMapTree(canvas, encodedImage.get(), &params);
+    DrawDeferredTextureImageMipMapTree(canvas, encodedImage.get(), &params, kN32_SkColorType);
 }
 
 DEF_SIMPLE_GM(deferred_texture_image_medium_decoded_indexed, canvas, 128 + 128 + 30, 340) {
@@ -207,7 +216,7 @@ DEF_SIMPLE_GM(deferred_texture_image_medium_decoded_indexed, canvas, 128 + 128 +
 
     auto params = SkImage::DeferredTextureImageUsageParams(SkMatrix::MakeScale(0.25f, 0.25f),
                                                            kMedium_SkFilterQuality, 0);
-    DrawDeferredTextureImageMipMapTree(canvas, decodedImage.get(), &params);
+    DrawDeferredTextureImageMipMapTree(canvas, decodedImage.get(), &params, kN32_SkColorType);
 }
 
 #endif
index 729e43d..63c9b7c 100644 (file)
@@ -463,12 +463,18 @@ public:
      * dstColorSpace is the color space of the surface where this texture will ultimately be used.
      * If the method determines that mip-maps are needed, this helps determine the correct strategy
      * for building them (gamma-correct or not).
+     *
+     * dstColorType is the color type of the surface where this texture will ultimately be used.
+     * This determines the format with which the image will be uploaded to the GPU. If dstColorType
+     * does not support color spaces (low bit depth types such as ARGB_4444), then dstColorSpace
+     * must be null.
      */
     size_t getDeferredTextureImageData(const GrContextThreadSafeProxy&,
                                        const DeferredTextureImageUsageParams[],
                                        int paramCnt,
                                        void* buffer,
-                                       SkColorSpace* dstColorSpace = nullptr) const;
+                                       SkColorSpace* dstColorSpace = nullptr,
+                                       SkColorType dstColorType = kN32_SkColorType) const;
 
     /**
      * Returns a texture-backed image from data produced in SkImage::getDeferredTextureImageData.
index 865b3a6..5ad1939 100644 (file)
@@ -14,6 +14,16 @@ SkAutoPixmapStorage::~SkAutoPixmapStorage() {
     this->freeStorage();
 }
 
+SkAutoPixmapStorage& SkAutoPixmapStorage::operator=(SkAutoPixmapStorage&& other) {
+    this->fStorage = other.fStorage;
+    this->INHERITED::reset(other.info(), this->fStorage, other.rowBytes(), other.ctable());
+
+    other.fStorage = nullptr;
+    other.INHERITED::reset();
+
+    return *this;
+}
+
 size_t SkAutoPixmapStorage::AllocSize(const SkImageInfo& info, size_t* rowBytes) {
     size_t rb = info.minRowBytes();
     if (rowBytes) {
index 66c5655..6342a41 100644 (file)
@@ -17,6 +17,11 @@ public:
     ~SkAutoPixmapStorage();
 
     /**
+    * Leave the moved-from object in a free-but-valid state.
+    */
+    SkAutoPixmapStorage& operator=(SkAutoPixmapStorage&& other);
+
+    /**
     *  Try to allocate memory for the pixels needed to match the specified Info. On success
     *  return true and fill out the pixmap to point to that memory. The storage will be freed
     *  when this object is destroyed, or if another call to tryAlloc() or alloc() is made.
index 3e525b3..3da7830 100644 (file)
@@ -348,7 +348,8 @@ sk_sp<SkImage> SkImage::MakeFromTexture(GrContext* ctx,
 size_t SkImage::getDeferredTextureImageData(const GrContextThreadSafeProxy&,
                                             const DeferredTextureImageUsageParams[],
                                             int paramCnt, void* buffer,
-                                            SkColorSpace* dstColorSpace) const {
+                                            SkColorSpace* dstColorSpace,
+                                            SkColorType dstColorType) const {
     return 0;
 }
 
index efdd2d7..0db9abb 100644 (file)
@@ -577,10 +577,22 @@ private:
                offsetof(DeferredTextureImage, member), \
                sizeof(DeferredTextureImage::member));
 
+static bool SupportsColorSpace(SkColorType colorType) {
+    switch (colorType) {
+        case kRGBA_8888_SkColorType:
+        case kBGRA_8888_SkColorType:
+        case kRGBA_F16_SkColorType:
+            return true;
+        default:
+            return false;
+    }
+}
+
 size_t SkImage::getDeferredTextureImageData(const GrContextThreadSafeProxy& proxy,
                                             const DeferredTextureImageUsageParams params[],
                                             int paramCnt, void* buffer,
-                                            SkColorSpace* dstColorSpace) const {
+                                            SkColorSpace* dstColorSpace,
+                                            SkColorType dstColorType) const {
     // Some quick-rejects where is makes no sense to return CPU data
     //  e.g.
     //      - texture backed
@@ -593,6 +605,12 @@ size_t SkImage::getDeferredTextureImageData(const GrContextThreadSafeProxy& prox
         return 0;
     }
 
+    bool supportsColorSpace = SupportsColorSpace(dstColorType);
+    // Quick reject if the caller requests a color space with an unsupported color type.
+    if (SkToBool(dstColorSpace) && !supportsColorSpace) {
+        return 0;
+    }
+
     // Extract relevant min/max values from the params array.
     int lowestPreScaleMipLevel = params[0].fPreScaleMipLevel;
     SkFilterQuality highestFilterQuality = params[0].fQuality;
@@ -637,7 +655,8 @@ size_t SkImage::getDeferredTextureImageData(const GrContextThreadSafeProxy& prox
     SkAutoPixmapStorage pixmap;
     SkImageInfo info;
     size_t pixelSize = 0;
-    if (!isScaled && this->peekPixels(&pixmap) && !pixmap.ctable()) {
+    if (!isScaled && this->peekPixels(&pixmap) && !pixmap.ctable() &&
+        pixmap.info().colorType() == dstColorType) {
         info = pixmap.info();
         pixelSize = SkAlign8(pixmap.getSafeSize());
         if (!dstColorSpace) {
@@ -660,24 +679,35 @@ size_t SkImage::getDeferredTextureImageData(const GrContextThreadSafeProxy& prox
                 info = info.makeColorSpace(nullptr);
             }
         }
-        if (kIndex_8_SkColorType == info.colorType()) {
-            // Force Index8 to be N32 instead. Index8 is unsupported in Ganesh.
-            info = info.makeColorType(kN32_SkColorType);
-        }
+        // Force color type to be the requested type.
+        info = info.makeColorType(dstColorType);
         pixelSize = SkAlign8(SkAutoPixmapStorage::AllocSize(info, nullptr));
         if (fillMode) {
-            pixmap.alloc(info);
+            // Always decode to N32 and convert to the requested type if necessary.
+            SkImageInfo decodeInfo = info.makeColorType(kN32_SkColorType);
+            SkAutoPixmapStorage decodePixmap;
+            decodePixmap.alloc(decodeInfo);
+
             if (isScaled) {
-                if (!this->scalePixels(pixmap, scaleFilterQuality,
+                if (!this->scalePixels(decodePixmap, scaleFilterQuality,
                                        SkImage::kDisallow_CachingHint)) {
                     return 0;
                 }
             } else {
-                if (!this->readPixels(pixmap, 0, 0, SkImage::kDisallow_CachingHint)) {
+                if (!this->readPixels(decodePixmap, 0, 0, SkImage::kDisallow_CachingHint)) {
                     return 0;
                 }
             }
-            SkASSERT(!pixmap.ctable());
+            SkASSERT(!decodePixmap.ctable());
+
+            if (decodeInfo.colorType() != info.colorType()) {
+                pixmap.alloc(info);
+                // Convert and copy the decoded pixmap to the target pixmap.
+                decodePixmap.readPixels(pixmap.info(), pixmap.writable_addr(), pixmap.rowBytes(), 0,
+                                        0);
+            } else {
+                pixmap = std::move(decodePixmap);
+            }
         }
     }
     int mipMapLevelCount = 1;
@@ -715,10 +745,11 @@ size_t SkImage::getDeferredTextureImageData(const GrContextThreadSafeProxy& prox
     SkColorSpaceTransferFn fn;
     if (info.colorSpace()) {
         SkASSERT(dstColorSpace);
+        SkASSERT(supportsColorSpace);
         colorSpaceOffset = size;
         colorSpaceSize = info.colorSpace()->writeToMemory(nullptr);
         size += colorSpaceSize;
-    } else if (this->colorSpace() && this->colorSpace()->isNumericalTransferFn(&fn)) {
+    } else if (supportsColorSpace && this->colorSpace() && this->colorSpace()->isNumericalTransferFn(&fn)) {
         // In legacy mode, preserve the color space tag on the SkImage.  This is only
         // supported if the color space has a parametric transfer function.
         SkASSERT(!dstColorSpace);
@@ -742,6 +773,7 @@ size_t SkImage::getDeferredTextureImageData(const GrContextThreadSafeProxy& prox
     SkDestinationSurfaceColorMode colorMode = SkDestinationSurfaceColorMode::kLegacy;
     if (proxy.fCaps->srgbSupport() && SkToBool(dstColorSpace) &&
         info.colorSpace() && info.colorSpace()->gammaCloseToSRGB()) {
+        SkASSERT(supportsColorSpace);
         colorMode = SkDestinationSurfaceColorMode::kGammaAndColorSpaceAware;
     }
 
index c747b8e..972843b 100644 (file)
@@ -1041,21 +1041,23 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DeferredTextureImage, reporter, ctxInfo) {
     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();
@@ -1063,21 +1065,34 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DeferredTextureImage, reporter, ctxInfo) {
             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 },
     };
 
 
@@ -1090,7 +1105,8 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DeferredTextureImage, reporter, ctxInfo) {
 
         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.",
@@ -1101,12 +1117,14 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DeferredTextureImage, reporter, ctxInfo) {
             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 }) {