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"