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"