Don't flatten images in SkImageShader
Bug: skia:9570 Change-Id: Idd4485b5c5814501fe98fbf2115d89a80a41f5c7 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/299139 Commit-Queue: Brian Salomon <bsalomon@google.com> Reviewed-by: Michael Ludwig <michaelludwig@google.com>
This commit is contained in:
parent
c0ab92c52f
commit
318afe66e6
@ -40,7 +40,7 @@ GrSurfaceProxyView GrImageTextureMaker::refOriginalTextureProxyView(GrMipMapped
|
|||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
GrYUVAImageTextureMaker::GrYUVAImageTextureMaker(GrContext* context, const SkImage* client)
|
GrYUVAImageTextureMaker::GrYUVAImageTextureMaker(GrRecordingContext* context, const SkImage* client)
|
||||||
: INHERITED(context, client->imageInfo())
|
: INHERITED(context, client->imageInfo())
|
||||||
, fImage(static_cast<const SkImage_GpuYUVA*>(client)) {
|
, fImage(static_cast<const SkImage_GpuYUVA*>(client)) {
|
||||||
SkASSERT(as_IB(client)->isYUVA());
|
SkASSERT(as_IB(client)->isYUVA());
|
||||||
@ -94,8 +94,9 @@ std::unique_ptr<GrFragmentProcessor> GrYUVAImageTextureMaker::createFragmentProc
|
|||||||
|
|
||||||
const auto& caps = *fImage->context()->priv().caps();
|
const auto& caps = *fImage->context()->priv().caps();
|
||||||
const SkMatrix& m = filterOrNullForBicubic ? textureMatrix : SkMatrix::I();
|
const SkMatrix& m = filterOrNullForBicubic ? textureMatrix : SkMatrix::I();
|
||||||
|
GrSamplerState sampler(wrapX, wrapY, filter);
|
||||||
auto fp = GrYUVtoRGBEffect::Make(fImage->fViews, fImage->fYUVAIndices, fImage->fYUVColorSpace,
|
auto fp = GrYUVtoRGBEffect::Make(fImage->fViews, fImage->fYUVAIndices, fImage->fYUVColorSpace,
|
||||||
filter, caps, m, domain);
|
sampler, caps, m, domain);
|
||||||
if (!filterOrNullForBicubic) {
|
if (!filterOrNullForBicubic) {
|
||||||
fp = GrBicubicEffect::Make(std::move(fp),
|
fp = GrBicubicEffect::Make(std::move(fp),
|
||||||
fImage->alphaType(),
|
fImage->alphaType(),
|
||||||
|
@ -33,7 +33,7 @@ private:
|
|||||||
/** This class manages the conversion of generator-backed YUVA images to GrTextures. */
|
/** This class manages the conversion of generator-backed YUVA images to GrTextures. */
|
||||||
class GrYUVAImageTextureMaker final : public GrTextureMaker {
|
class GrYUVAImageTextureMaker final : public GrTextureMaker {
|
||||||
public:
|
public:
|
||||||
GrYUVAImageTextureMaker(GrContext* context, const SkImage* client);
|
GrYUVAImageTextureMaker(GrRecordingContext* context, const SkImage* client);
|
||||||
|
|
||||||
std::unique_ptr<GrFragmentProcessor> createFragmentProcessor(
|
std::unique_ptr<GrFragmentProcessor> createFragmentProcessor(
|
||||||
const SkMatrix& textureMatrix,
|
const SkMatrix& textureMatrix,
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
* found in the LICENSE file.
|
* found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "src/shaders/SkImageShader.h"
|
||||||
|
|
||||||
#include "src/core/SkArenaAlloc.h"
|
#include "src/core/SkArenaAlloc.h"
|
||||||
#include "src/core/SkBitmapController.h"
|
#include "src/core/SkBitmapController.h"
|
||||||
#include "src/core/SkColorSpacePriv.h"
|
#include "src/core/SkColorSpacePriv.h"
|
||||||
@ -13,12 +15,12 @@
|
|||||||
#include "src/core/SkOpts.h"
|
#include "src/core/SkOpts.h"
|
||||||
#include "src/core/SkRasterPipeline.h"
|
#include "src/core/SkRasterPipeline.h"
|
||||||
#include "src/core/SkReadBuffer.h"
|
#include "src/core/SkReadBuffer.h"
|
||||||
|
#include "src/core/SkScopeExit.h"
|
||||||
#include "src/core/SkVM.h"
|
#include "src/core/SkVM.h"
|
||||||
#include "src/core/SkWriteBuffer.h"
|
#include "src/core/SkWriteBuffer.h"
|
||||||
#include "src/image/SkImage_Base.h"
|
#include "src/image/SkImage_Base.h"
|
||||||
#include "src/shaders/SkBitmapProcShader.h"
|
#include "src/shaders/SkBitmapProcShader.h"
|
||||||
#include "src/shaders/SkEmptyShader.h"
|
#include "src/shaders/SkEmptyShader.h"
|
||||||
#include "src/shaders/SkImageShader.h"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We are faster in clamp, so always use that tiling when we can.
|
* We are faster in clamp, so always use that tiling when we can.
|
||||||
@ -195,9 +197,12 @@ sk_sp<SkShader> SkImageShader::Make(sk_sp<SkImage> image,
|
|||||||
#if SK_SUPPORT_GPU
|
#if SK_SUPPORT_GPU
|
||||||
|
|
||||||
#include "include/private/GrRecordingContext.h"
|
#include "include/private/GrRecordingContext.h"
|
||||||
|
#include "src/gpu/GrBitmapTextureMaker.h"
|
||||||
#include "src/gpu/GrCaps.h"
|
#include "src/gpu/GrCaps.h"
|
||||||
#include "src/gpu/GrColorInfo.h"
|
#include "src/gpu/GrColorInfo.h"
|
||||||
|
#include "src/gpu/GrImageTextureMaker.h"
|
||||||
#include "src/gpu/GrRecordingContextPriv.h"
|
#include "src/gpu/GrRecordingContextPriv.h"
|
||||||
|
#include "src/gpu/GrTextureAdjuster.h"
|
||||||
#include "src/gpu/SkGr.h"
|
#include "src/gpu/SkGr.h"
|
||||||
#include "src/gpu/effects/GrBicubicEffect.h"
|
#include "src/gpu/effects/GrBicubicEffect.h"
|
||||||
#include "src/gpu/effects/GrTextureEffect.h"
|
#include "src/gpu/effects/GrTextureEffect.h"
|
||||||
@ -210,51 +215,71 @@ std::unique_ptr<GrFragmentProcessor> SkImageShader::asFragmentProcessor(
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This would all be much nicer with std::variant.
|
||||||
|
static constexpr size_t kSize = std::max({sizeof(GrYUVAImageTextureMaker),
|
||||||
|
sizeof(GrTextureAdjuster ),
|
||||||
|
sizeof(GrImageTextureMaker ),
|
||||||
|
sizeof(GrBitmapTextureMaker )});
|
||||||
|
static constexpr size_t kAlign = std::max({alignof(GrYUVAImageTextureMaker),
|
||||||
|
alignof(GrTextureAdjuster ),
|
||||||
|
alignof(GrImageTextureMaker ),
|
||||||
|
alignof(GrBitmapTextureMaker )});
|
||||||
|
std::aligned_storage_t<kSize, kAlign> storage;
|
||||||
|
GrTextureProducer* producer = nullptr;
|
||||||
|
SkScopeExit destroyProducer([&producer]{ if (producer) { producer->~GrTextureProducer(); } });
|
||||||
|
|
||||||
|
uint32_t pinnedUniqueID;
|
||||||
|
SkBitmap bm;
|
||||||
|
if (as_IB(fImage)->isYUVA()) {
|
||||||
|
producer = new (&storage) GrYUVAImageTextureMaker(args.fContext, fImage.get());
|
||||||
|
} else if (GrSurfaceProxyView view =
|
||||||
|
as_IB(fImage)->refPinnedView(args.fContext, &pinnedUniqueID)) {
|
||||||
|
GrColorInfo colorInfo;
|
||||||
|
if (args.fContext->priv().caps()->isFormatSRGB(view.proxy()->backendFormat())) {
|
||||||
|
SkASSERT(fImage->colorType() == kRGBA_8888_SkColorType);
|
||||||
|
colorInfo = GrColorInfo(GrColorType::kRGBA_8888_SRGB, fImage->alphaType(),
|
||||||
|
fImage->refColorSpace());
|
||||||
|
} else {
|
||||||
|
colorInfo = fImage->imageInfo().colorInfo();
|
||||||
|
}
|
||||||
|
producer = new (&storage)
|
||||||
|
GrTextureAdjuster(args.fContext, std::move(view), colorInfo, pinnedUniqueID);
|
||||||
|
} else if (fImage->isLazyGenerated()) {
|
||||||
|
producer = new (&storage)
|
||||||
|
GrImageTextureMaker(args.fContext, fImage.get(), GrImageTexGenPolicy::kDraw);
|
||||||
|
} else if (as_IB(fImage)->getROPixels(&bm)) {
|
||||||
|
producer =
|
||||||
|
new (&storage) GrBitmapTextureMaker(args.fContext, bm, GrImageTexGenPolicy::kDraw);
|
||||||
|
} else {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
GrSamplerState::WrapMode wmX = SkTileModeToWrapMode(fTileModeX),
|
GrSamplerState::WrapMode wmX = SkTileModeToWrapMode(fTileModeX),
|
||||||
wmY = SkTileModeToWrapMode(fTileModeY);
|
wmY = SkTileModeToWrapMode(fTileModeY);
|
||||||
|
// Must set wrap and filter on the sampler before requesting a texture. In two places
|
||||||
// Must set wrap and filter on the sampler before requesting a texture. In two places below
|
// below we check the matrix scale factors to determine how to interpret the filter
|
||||||
// we check the matrix scale factors to determine how to interpret the filter quality setting.
|
// quality setting. This completely ignores the complexity of the drawVertices case
|
||||||
// This completely ignores the complexity of the drawVertices case where explicit local coords
|
// where explicit local coords are provided by the caller.
|
||||||
// are provided by the caller.
|
|
||||||
bool doBicubic;
|
bool doBicubic;
|
||||||
GrSamplerState::Filter textureFilterMode = GrSkFilterQualityToGrFilterMode(
|
GrSamplerState::Filter textureFilterMode = GrSkFilterQualityToGrFilterMode(
|
||||||
fImage->width(), fImage->height(), this->resolveFiltering(args.fFilterQuality),
|
fImage->width(), fImage->height(), this->resolveFiltering(args.fFilterQuality),
|
||||||
args.fMatrixProvider.localToDevice(), *lm,
|
args.fMatrixProvider.localToDevice(), *lm,
|
||||||
args.fContext->priv().options().fSharpenMipmappedTextures, &doBicubic);
|
args.fContext->priv().options().fSharpenMipmappedTextures, &doBicubic);
|
||||||
GrMipMapped mipMapped = GrMipMapped::kNo;
|
const GrSamplerState::Filter* filterOrNull = doBicubic ? nullptr : &textureFilterMode;
|
||||||
if (textureFilterMode == GrSamplerState::Filter::kMipMap) {
|
auto fp = producer->createFragmentProcessor(lmInverse, SkRect::Make(fImage->dimensions()),
|
||||||
mipMapped = GrMipMapped::kYes;
|
GrTextureProducer::kNo_FilterConstraint, false, wmX,
|
||||||
}
|
wmY, filterOrNull);
|
||||||
GrSurfaceProxyView view = as_IB(fImage)->refView(args.fContext, mipMapped);
|
|
||||||
if (!view) {
|
if (!fp) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
SkAlphaType srcAlphaType = fImage->alphaType();
|
|
||||||
|
|
||||||
const auto& caps = *args.fContext->priv().caps();
|
|
||||||
|
|
||||||
std::unique_ptr<GrFragmentProcessor> inner;
|
|
||||||
if (doBicubic) {
|
|
||||||
static constexpr auto kDir = GrBicubicEffect::Direction::kXY;
|
|
||||||
static constexpr auto kKernel = GrBicubicEffect::Kernel::kMitchell;
|
|
||||||
inner = GrBicubicEffect::Make(std::move(view), srcAlphaType, lmInverse, wmX, wmY, kKernel,
|
|
||||||
kDir, caps);
|
|
||||||
} else {
|
|
||||||
GrSamplerState samplerState(wmX, wmY, textureFilterMode);
|
|
||||||
inner = GrTextureEffect::Make(std::move(view), srcAlphaType, lmInverse, samplerState, caps);
|
|
||||||
}
|
|
||||||
inner = GrColorSpaceXformEffect::Make(std::move(inner), fImage->colorSpace(), srcAlphaType,
|
|
||||||
args.fDstColorInfo->colorSpace());
|
|
||||||
|
|
||||||
bool isAlphaOnly = SkColorTypeIsAlphaOnly(fImage->colorType());
|
bool isAlphaOnly = SkColorTypeIsAlphaOnly(fImage->colorType());
|
||||||
if (isAlphaOnly) {
|
if (isAlphaOnly) {
|
||||||
return inner;
|
return fp;
|
||||||
} else if (args.fInputColorIsOpaque) {
|
} else if (args.fInputColorIsOpaque) {
|
||||||
return GrFragmentProcessor::OverrideInput(std::move(inner), SK_PMColor4fWHITE, false);
|
return GrFragmentProcessor::OverrideInput(std::move(fp), SK_PMColor4fWHITE, false);
|
||||||
}
|
}
|
||||||
return GrFragmentProcessor::MulChildByInputAlpha(std::move(inner));
|
return GrFragmentProcessor::MulChildByInputAlpha(std::move(fp));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -888,4 +913,3 @@ skvm::Color SkImageShader::onProgram(skvm::Builder* p,
|
|||||||
SkColorSpaceXformSteps steps{cs,at, dst.colorSpace(),kPremul_SkAlphaType};
|
SkColorSpaceXformSteps steps{cs,at, dst.colorSpace(),kPremul_SkAlphaType};
|
||||||
return steps.program(p, uniforms, c);
|
return steps.program(p, uniforms, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user