Reflatten YUVA image on each request.

It should now be rare to require a RGBA texture from a YUVA image (e.g.
in image filter)

Removes a thread-safety issue. A step towards allowing clients to pump
new data into the planes and be sure Skia wont draw the old contents.

Bug: skia:11873

Change-Id: I007cf28e477155f85ed9f1c6cc4547f9dbbb73fd
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/397319
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/GrImageTextureMaker.cpp b/src/gpu/GrImageTextureMaker.cpp
index 9be3a99..18df956 100644
--- a/src/gpu/GrImageTextureMaker.cpp
+++ b/src/gpu/GrImageTextureMaker.cpp
@@ -57,12 +57,6 @@
         const SkRect* subset,
         const SkRect* domain,
         GrSamplerState samplerState) {
-    // Check whether it's already been flattened.
-    if (fImage->fRGBView.proxy()) {
-        return this->INHERITED::createFragmentProcessor(textureMatrix, subset, domain,
-                                                        samplerState);
-    }
-
     // Check to see if the client has given us pre-mipped textures or if we can generate them
     // If not disable mip mapping.
     if (samplerState.mipmapped() == GrMipmapped::kYes &&
diff --git a/src/image/SkImage_GpuYUVA.cpp b/src/image/SkImage_GpuYUVA.cpp
index 38867f2..32f4a9d 100644
--- a/src/image/SkImage_GpuYUVA.cpp
+++ b/src/image/SkImage_GpuYUVA.cpp
@@ -62,17 +62,12 @@
                     image->alphaType(),
                     std::move(targetCS))
         , fYUVAProxies(image->fYUVAProxies)
-        , fRGBView(image->fRGBView)
         // Since null fFromColorSpace means no GrColorSpaceXform, we turn a null
         // image->refColorSpace() into an explicit SRGB.
         , fFromColorSpace(image->colorSpace() ? image->refColorSpace() : SkColorSpace::MakeSRGB()) {
-    // We should either have a RGB proxy *or* a set of YUVA proxies.
-    SkASSERT(fYUVAProxies.isValid() != SkToBool(image->fRGBView));
 }
 
 bool SkImage_GpuYUVA::setupMipmapsForPlanes(GrRecordingContext* context) const {
-    // We shouldn't get here if the planes were already flattened to RGBA.
-    SkASSERT(fYUVAProxies.isValid() && !fRGBView);
     if (!context || !fContext->priv().matches(context)) {
         return false;
     }
@@ -116,35 +111,18 @@
     }
 
     GrSurfaceProxy* proxies[SkYUVAInfo::kMaxPlanes] = {};
-    size_t numProxies;
-    if (fRGBView) {
-        // Either we've already flushed the flattening draw or the flattening is unflushed. In the
-        // latter case it should still be ok to just pass fRGBView proxy because it in turn depends
-        // on the planar proxies and will cause all of their work to flush as well.
-        proxies[0] = fRGBView.proxy();
-        numProxies = 1;
-    } else {
-        numProxies = fYUVAProxies.numPlanes();
-        for (size_t i = 0; i < numProxies; ++i) {
-            proxies[i] = fYUVAProxies.proxy(i);
-        }
+    size_t numProxies = fYUVAProxies.numPlanes();
+    for (size_t i = 0; i < numProxies; ++i) {
+        proxies[i] = fYUVAProxies.proxy(i);
     }
     return dContext->priv().flushSurfaces({proxies, numProxies},
                                           SkSurface::BackendSurfaceAccess::kNoAccess,
                                           info);
 }
 
-bool SkImage_GpuYUVA::onHasMipmaps() const {
-    if (fRGBView) {
-        return fRGBView.asTextureProxy()->mipmapped() == GrMipmapped::kYes;
-    }
-    return fYUVAProxies.mipmapped() == GrMipmapped::kYes;
-}
+bool SkImage_GpuYUVA::onHasMipmaps() const { return fYUVAProxies.mipmapped() == GrMipmapped::kYes; }
 
 size_t SkImage_GpuYUVA::onTextureSize() const {
-    if (fRGBView) {
-        return fRGBView.asTextureProxy()->gpuMemorySize();
-    }
     size_t size = 0;
     for (int i = 0; i < fYUVAProxies.numPlanes(); ++i) {
         size += fYUVAProxies.proxy(i)->gpuMemorySize();
@@ -174,97 +152,35 @@
     return sk_sp<SkImage>(new SkImage_GpuYUVA(fContext, this, std::move(newCS)));
 }
 
-static GrSurfaceProxyView render_to_rgb(GrRecordingContext* context,
-                                        const SkColorInfo& colorInfo,
-                                        const GrYUVATextureProxies& proxies,
-                                        SkColorSpace* fromColorSpace,
-                                        GrMipmapped mipmapped,
-                                        SkBudgeted budgeted) {
-    GrImageInfo ii(colorInfo, proxies.yuvaInfo().dimensions());
-    auto surfaceFillContext = GrSurfaceFillContext::Make(context,
-                                                         std::move(ii),
-                                                         SkBackingFit::kExact,
-                                                         /*sample count*/ 1,
-                                                         mipmapped,
-                                                         GrProtected::kNo,
-                                                         kTopLeft_GrSurfaceOrigin,
-                                                         budgeted);
-    if (!surfaceFillContext) {
+std::tuple<GrSurfaceProxyView, GrColorType> SkImage_GpuYUVA::onAsView(
+        GrRecordingContext* context,
+        GrMipmapped mipmapped,
+        GrImageTexGenPolicy) const {
+    if (!fContext->priv().matches(context)) {
+        return {};
+    }
+    auto sfc = GrSurfaceFillContext::Make(context,
+                                          this->imageInfo(),
+                                          SkBackingFit::kExact,
+                                          /*sample count*/ 1,
+                                          mipmapped,
+                                          GrProtected::kNo,
+                                          kTopLeft_GrSurfaceOrigin,
+                                          SkBudgeted::kYes);
+    if (!sfc) {
         return {};
     }
 
     const GrCaps& caps = *context->priv().caps();
-
-    auto fp = GrYUVtoRGBEffect::Make(proxies, GrSamplerState::Filter::kNearest, caps);
-    if (fromColorSpace) {
+    auto fp = GrYUVtoRGBEffect::Make(fYUVAProxies, GrSamplerState::Filter::kNearest, caps);
+    if (fFromColorSpace) {
         fp = GrColorSpaceXformEffect::Make(std::move(fp),
-                                           fromColorSpace,         colorInfo.alphaType(),
-                                           colorInfo.colorSpace(), colorInfo.alphaType());
+                                           fFromColorSpace.get(), this->alphaType(),
+                                           this->colorSpace()   , this->alphaType());
     }
+    sfc->fillWithFP(std::move(fp));
 
-    surfaceFillContext->fillWithFP(std::move(fp));
-
-    return surfaceFillContext->readSurfaceView();
-}
-
-bool SkImage_GpuYUVA::flattenToRGB(GrRecordingContext* context, GrMipmapped mipmapped) const {
-    if (fRGBView.proxy()) {
-        if (mipmapped                                       == GrMipmapped::kYes &&
-            fRGBView.proxy()->asTextureProxy()->mipmapped() == GrMipmapped::kNo) {
-            GrSurfaceProxyView mippedView = GrCopyBaseMipMapToView(context, fRGBView);
-            if (!mippedView) {
-                return false;
-            }
-            fRGBView = std::move(mippedView);
-            return true;
-        }
-        return true;
-    }
-
-    if (!context || !fContext->priv().matches(context)) {
-        return false;
-    }
-
-    GrSurfaceProxyView rgbView = render_to_rgb(context,
-                                               this->imageInfo().colorInfo(),
-                                               fYUVAProxies,
-                                               fFromColorSpace.get(),
-                                               mipmapped,
-                                               SkBudgeted::kYes);
-    if (!rgbView) {
-        return false;
-    }
-    fRGBView = std::move(rgbView);
-    fYUVAProxies = {};
-    return true;
-}
-
-std::tuple<GrSurfaceProxyView, GrColorType> SkImage_GpuYUVA::onAsView(
-        GrRecordingContext* context,
-        GrMipmapped mipmapped,
-        GrImageTexGenPolicy policy) const {
-    if (!fContext->priv().matches(context)) {
-        return {};
-    }
-    if (policy != GrImageTexGenPolicy::kDraw) {
-        SkBudgeted budgeted = policy == GrImageTexGenPolicy::kNew_Uncached_Budgeted
-                                      ? SkBudgeted::kYes
-                                      : SkBudgeted::kNo;
-        if (fRGBView) {
-            return {CopyView(context, fRGBView, mipmapped, policy), GrColorType::kRGBA_8888};
-        }
-        auto view = render_to_rgb(context,
-                                  this->imageInfo().colorInfo(),
-                                  fYUVAProxies,
-                                  fFromColorSpace.get(),
-                                  mipmapped,
-                                  budgeted);
-        return {std::move(view), GrColorType::kRGBA_8888};
-    }
-    if (!this->flattenToRGB(context, mipmapped)) {
-        return {};
-    }
-    return {fRGBView, GrColorType::kRGBA_8888};
+    return {sfc->readSurfaceView(), sfc->imageInfo().colorType()};
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/image/SkImage_GpuYUVA.h b/src/image/SkImage_GpuYUVA.h
index d0741c7..a026901 100644
--- a/src/image/SkImage_GpuYUVA.h
+++ b/src/image/SkImage_GpuYUVA.h
@@ -34,11 +34,7 @@
 
     GrSemaphoresSubmitted onFlush(GrDirectContext*, const GrFlushInfo&) override;
 
-    bool onIsTextureBacked() const override {
-        // We should have YUVA proxies or a RGBA proxy,but not both.
-        SkASSERT(fYUVAProxies.isValid() != SkToBool(fRGBView));
-        return true;
-    }
+    bool onIsTextureBacked() const override { return true; }
 
     size_t onTextureSize() const override;
 
@@ -51,14 +47,6 @@
 
     bool setupMipmapsForPlanes(GrRecordingContext*) const;
 
-#if GR_TEST_UTILS
-    bool testingOnly_IsFlattened() const {
-        // We should only have the flattened proxy or the planar proxies at one point in time.
-        SkASSERT(SkToBool(fRGBView) != fYUVAProxies.isValid());
-        return SkToBool(fRGBView.proxy());
-    }
-#endif
-
 private:
     SkImage_GpuYUVA(sk_sp<GrImageContext>, const SkImage_GpuYUVA* image, sk_sp<SkColorSpace>);
 
@@ -66,15 +54,10 @@
                                                          GrMipmapped,
                                                          GrImageTexGenPolicy) const override;
 
-    bool flattenToRGB(GrRecordingContext*, GrMipmapped) const;
+    GrSurfaceProxyView flattenToRGB(GrRecordingContext*, GrMipmapped) const;
 
     mutable GrYUVATextureProxies     fYUVAProxies;
 
-    // This is only allocated when the image needs to be flattened rather than
-    // using the separate YUVA planes. From thence forth we will only use the
-    // the RGBView.
-    mutable GrSurfaceProxyView       fRGBView;
-
     // If this is non-null then the planar data should be converted from fFromColorSpace to
     // this->colorSpace(). Otherwise we assume the planar data (post YUV->RGB conversion) is already
     // in this->colorSpace().
diff --git a/tests/ImageTest.cpp b/tests/ImageTest.cpp
index bbba12c..05eed79 100644
--- a/tests/ImageTest.cpp
+++ b/tests/ImageTest.cpp
@@ -1474,15 +1474,6 @@
     // Flushing image 2 should flush.
     i2->flushAndSubmit(dContext);
     REPORTER_ASSERT(reporter, numSubmits() == 1);
-    // Since we just did a simple image draw it should not have been flattened.
-    REPORTER_ASSERT(reporter,
-                    !static_cast<SkImage_GpuYUVA*>(as_IB(i2.get()))->testingOnly_IsFlattened());
-    REPORTER_ASSERT(reporter, static_cast<SkImage_GpuYUVA*>(as_IB(i2.get()))->isTextureBacked());
-
-    // Flatten it and repeat.
-    as_IB(i2.get())->asView(dContext, GrMipmapped::kNo);
-    REPORTER_ASSERT(reporter,
-                    static_cast<SkImage_GpuYUVA*>(as_IB(i2.get()))->testingOnly_IsFlattened());
     REPORTER_ASSERT(reporter, static_cast<SkImage_GpuYUVA*>(as_IB(i2.get()))->isTextureBacked());
     s->getCanvas()->drawImage(i2, 0, 0);
     // Flushing image 0 should do nothing, but submit is still called.
@@ -1494,28 +1485,6 @@
     // Flushing image 2 should flush.
     i2->flushAndSubmit(dContext);
     REPORTER_ASSERT(reporter, numSubmits() == 1);
-
-    // Test case where flatten happens before the first flush.
-    i2 = make_yuva_image(dContext);
-    // On some systems where preferVRAMUseOverFlushes is false (ANGLE on Windows) the above may
-    // actually flush in order to make textures for the YUV planes. TODO: Remove this when we
-    // make the YUVA planes from backend textures rather than pixmaps that the context must upload.
-    // Calling numSubmits rebases the flush count from here.
-    numSubmits();
-    as_IB(i2.get())->asView(dContext, GrMipmapped::kNo);
-    REPORTER_ASSERT(reporter,
-                    static_cast<SkImage_GpuYUVA*>(as_IB(i2.get()))->testingOnly_IsFlattened());
-    REPORTER_ASSERT(reporter, static_cast<SkImage_GpuYUVA*>(as_IB(i2.get()))->isTextureBacked());
-    s->getCanvas()->drawImage(i2, 0, 0);
-    // Flushing image 0 should do nothing, but submit is still called.
-    i0->flushAndSubmit(dContext);
-    REPORTER_ASSERT(reporter, numSubmits() == 1);
-    // Flushing image 1 do nothing, but submit is still called.
-    i1->flushAndSubmit(dContext);
-    REPORTER_ASSERT(reporter, numSubmits() == 1);
-    // Flushing image 2 should flush, but submit is still called.
-    i2->flushAndSubmit(dContext);
-    REPORTER_ASSERT(reporter, numSubmits() == 1);
 }
 
 #include "src/shaders/SkImageShader.h"