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>
This commit is contained in:
parent
816db16d19
commit
d0f35c241c
@ -57,12 +57,6 @@ std::unique_ptr<GrFragmentProcessor> GrYUVAImageTextureMaker::createFragmentProc
|
||||
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 &&
|
||||
|
@ -62,17 +62,12 @@ SkImage_GpuYUVA::SkImage_GpuYUVA(sk_sp<GrImageContext> context,
|
||||
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 @@ GrSemaphoresSubmitted SkImage_GpuYUVA::onFlush(GrDirectContext* dContext, const
|
||||
}
|
||||
|
||||
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 @@ sk_sp<SkImage> SkImage_GpuYUVA::onReinterpretColorSpace(sk_sp<SkColorSpace> newC
|
||||
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()};
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -34,11 +34,7 @@ public:
|
||||
|
||||
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 @@ public:
|
||||
|
||||
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 @@ private:
|
||||
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().
|
||||
|
@ -1474,15 +1474,6 @@ DEF_GPUTEST_FOR_ALL_CONTEXTS(ImageFlush, reporter, ctxInfo) {
|
||||
// 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 @@ DEF_GPUTEST_FOR_ALL_CONTEXTS(ImageFlush, reporter, ctxInfo) {
|
||||
// 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"
|
||||
|
Loading…
Reference in New Issue
Block a user