Make GrTextureProducer take optional subset and domain rects
Split bicubic into separate functions. Removes usage of null GrSamplerState::Filter to indicate bicubic. Bug: skia:10344 Change-Id: Ife649ba84afe3a06d7d8fb0d46677ce96fc264dc Reviewed-on: https://skia-review.googlesource.com/c/skia/+/302636 Reviewed-by: Michael Ludwig <michaelludwig@google.com> Commit-Queue: Brian Salomon <bsalomon@google.com>
This commit is contained in:
parent
252a3c0e11
commit
0ea330703e
@ -60,50 +60,48 @@ GrSurfaceProxyView GrYUVAImageTextureMaker::refOriginalTextureProxyView(GrMipMap
|
||||
|
||||
std::unique_ptr<GrFragmentProcessor> GrYUVAImageTextureMaker::createFragmentProcessor(
|
||||
const SkMatrix& textureMatrix,
|
||||
const SkRect& constraintRect,
|
||||
FilterConstraint filterConstraint,
|
||||
bool coordsLimitedToConstraintRect,
|
||||
GrSamplerState::WrapMode wrapX,
|
||||
GrSamplerState::WrapMode wrapY,
|
||||
const GrSamplerState::Filter* filterOrNullForBicubic) {
|
||||
const SkRect* subset,
|
||||
const SkRect* domain,
|
||||
GrSamplerState samplerState) {
|
||||
// Check whether it's already been flattened.
|
||||
if (fImage->fRGBView.proxy()) {
|
||||
return this->INHERITED::createFragmentProcessor(
|
||||
textureMatrix, constraintRect, filterConstraint, coordsLimitedToConstraintRect,
|
||||
wrapX, wrapY, filterOrNullForBicubic);
|
||||
return this->INHERITED::createFragmentProcessor(textureMatrix, subset, domain,
|
||||
samplerState);
|
||||
}
|
||||
|
||||
GrSamplerState::Filter filter =
|
||||
filterOrNullForBicubic ? *filterOrNullForBicubic : GrSamplerState::Filter::kNearest;
|
||||
|
||||
// Check to see if the client has given us pre-mipped textures or we can generate them
|
||||
// If not, fall back to bilerp. Also fall back to bilerp when a domain is requested
|
||||
if (GrSamplerState::Filter::kMipMap == filter &&
|
||||
(filterConstraint == GrTextureProducer::kYes_FilterConstraint ||
|
||||
!fImage->setupMipmapsForPlanes(this->context()))) {
|
||||
filter = GrSamplerState::Filter::kBilerp;
|
||||
}
|
||||
|
||||
// Cannot rely on GrTextureProducer's domain infrastructure since we need to calculate domain's
|
||||
// per plane, which may be different, so respect the filterConstraint without any additional
|
||||
// analysis.
|
||||
const SkRect* domain = nullptr;
|
||||
if (filterConstraint == GrTextureProducer::kYes_FilterConstraint) {
|
||||
domain = &constraintRect;
|
||||
if (samplerState.filter() == GrSamplerState::Filter::kMipMap &&
|
||||
(subset || !fImage->setupMipmapsForPlanes(this->context()))) {
|
||||
samplerState.setFilterMode(GrSamplerState::Filter::kBilerp);
|
||||
}
|
||||
|
||||
const auto& caps = *fImage->context()->priv().caps();
|
||||
const SkMatrix& m = filterOrNullForBicubic ? textureMatrix : SkMatrix::I();
|
||||
GrSamplerState sampler(wrapX, wrapY, filter);
|
||||
auto fp = GrYUVtoRGBEffect::Make(fImage->fViews, fImage->fYUVAIndices, fImage->fYUVColorSpace,
|
||||
sampler, caps, m, domain);
|
||||
if (!filterOrNullForBicubic) {
|
||||
fp = GrBicubicEffect::Make(std::move(fp),
|
||||
fImage->alphaType(),
|
||||
textureMatrix,
|
||||
GrBicubicEffect::Kernel::kMitchell,
|
||||
GrBicubicEffect::Direction::kXY);
|
||||
samplerState, caps, textureMatrix, subset, domain);
|
||||
if (fImage->fFromColorSpace) {
|
||||
fp = GrColorSpaceXformEffect::Make(std::move(fp), fImage->fFromColorSpace.get(),
|
||||
fImage->alphaType(), fImage->colorSpace(),
|
||||
kPremul_SkAlphaType);
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
||||
std::unique_ptr<GrFragmentProcessor> GrYUVAImageTextureMaker::createBicubicFragmentProcessor(
|
||||
const SkMatrix& textureMatrix,
|
||||
const SkRect* subset,
|
||||
const SkRect* domain,
|
||||
GrSamplerState::WrapMode wrapX,
|
||||
GrSamplerState::WrapMode wrapY) {
|
||||
const auto& caps = *fImage->context()->priv().caps();
|
||||
GrSamplerState samplerState(wrapX, wrapY, GrSamplerState::Filter::kNearest);
|
||||
auto fp = GrYUVtoRGBEffect::Make(fImage->fViews, fImage->fYUVAIndices, fImage->fYUVColorSpace,
|
||||
samplerState, caps, SkMatrix::I(), subset, domain);
|
||||
fp = GrBicubicEffect::Make(std::move(fp),
|
||||
fImage->alphaType(),
|
||||
textureMatrix,
|
||||
GrBicubicEffect::Kernel::kMitchell,
|
||||
GrBicubicEffect::Direction::kXY);
|
||||
if (fImage->fFromColorSpace) {
|
||||
fp = GrColorSpaceXformEffect::Make(std::move(fp),
|
||||
fImage->fFromColorSpace.get(), fImage->alphaType(),
|
||||
|
@ -35,14 +35,17 @@ class GrYUVAImageTextureMaker final : public GrTextureMaker {
|
||||
public:
|
||||
GrYUVAImageTextureMaker(GrRecordingContext* context, const SkImage* client);
|
||||
|
||||
std::unique_ptr<GrFragmentProcessor> createFragmentProcessor(
|
||||
std::unique_ptr<GrFragmentProcessor> createFragmentProcessor(const SkMatrix& textureMatrix,
|
||||
const SkRect* subset,
|
||||
const SkRect* domain,
|
||||
GrSamplerState) override;
|
||||
|
||||
std::unique_ptr<GrFragmentProcessor> createBicubicFragmentProcessor(
|
||||
const SkMatrix& textureMatrix,
|
||||
const SkRect& constraintRect,
|
||||
FilterConstraint filterConstraint,
|
||||
bool coordsLimitedToConstraintRect,
|
||||
const SkRect* subset,
|
||||
const SkRect* domain,
|
||||
GrSamplerState::WrapMode wrapX,
|
||||
GrSamplerState::WrapMode wrapY,
|
||||
const GrSamplerState::Filter* filterOrNullForBicubic) override;
|
||||
GrSamplerState::WrapMode wrapY) override;
|
||||
|
||||
bool isPlanar() const override { return true; }
|
||||
|
||||
|
@ -77,29 +77,19 @@ GrSurfaceProxyView GrTextureAdjuster::onView(GrMipMapped mipMapped) {
|
||||
|
||||
std::unique_ptr<GrFragmentProcessor> GrTextureAdjuster::createFragmentProcessor(
|
||||
const SkMatrix& textureMatrix,
|
||||
const SkRect& constraintRect,
|
||||
FilterConstraint filterConstraint,
|
||||
bool coordsLimitedToConstraintRect,
|
||||
GrSamplerState::WrapMode wrapX,
|
||||
GrSamplerState::WrapMode wrapY,
|
||||
const GrSamplerState::Filter* filterOrNullForBicubic) {
|
||||
GrSurfaceProxyView view;
|
||||
if (filterOrNullForBicubic) {
|
||||
view = this->view(*filterOrNullForBicubic);
|
||||
} else {
|
||||
view = this->view(GrMipMapped::kNo);
|
||||
}
|
||||
if (!view) {
|
||||
return nullptr;
|
||||
}
|
||||
SkASSERT(view.asTextureProxy());
|
||||
|
||||
return this->createFragmentProcessorForSubsetAndFilter(std::move(view),
|
||||
textureMatrix,
|
||||
coordsLimitedToConstraintRect,
|
||||
filterConstraint,
|
||||
constraintRect,
|
||||
wrapX,
|
||||
wrapY,
|
||||
filterOrNullForBicubic);
|
||||
const SkRect* subset,
|
||||
const SkRect* domain,
|
||||
GrSamplerState samplerState) {
|
||||
return this->createFragmentProcessorForView(
|
||||
this->view(samplerState.filter()), textureMatrix, subset, domain, samplerState);
|
||||
}
|
||||
|
||||
std::unique_ptr<GrFragmentProcessor> GrTextureAdjuster::createBicubicFragmentProcessor(
|
||||
const SkMatrix& textureMatrix,
|
||||
const SkRect* subset,
|
||||
const SkRect* domain,
|
||||
GrSamplerState::WrapMode wrapX,
|
||||
GrSamplerState::WrapMode wrapY) {
|
||||
return this->createBicubicFragmentProcessorForView(
|
||||
this->view(GrMipMapped::kNo), textureMatrix, subset, domain, wrapX, wrapY);
|
||||
}
|
||||
|
@ -23,14 +23,17 @@ public:
|
||||
GrTextureAdjuster(GrRecordingContext*, GrSurfaceProxyView, const GrColorInfo&,
|
||||
uint32_t uniqueID);
|
||||
|
||||
std::unique_ptr<GrFragmentProcessor> createFragmentProcessor(
|
||||
std::unique_ptr<GrFragmentProcessor> createFragmentProcessor(const SkMatrix& textureMatrix,
|
||||
const SkRect* subset,
|
||||
const SkRect* domain,
|
||||
GrSamplerState) override;
|
||||
|
||||
std::unique_ptr<GrFragmentProcessor> createBicubicFragmentProcessor(
|
||||
const SkMatrix& textureMatrix,
|
||||
const SkRect& constraintRect,
|
||||
FilterConstraint,
|
||||
bool coordsLimitedToConstraintRect,
|
||||
const SkRect* subset,
|
||||
const SkRect* domain,
|
||||
GrSamplerState::WrapMode wrapX,
|
||||
GrSamplerState::WrapMode wrapY,
|
||||
const GrSamplerState::Filter* filterOrNullForBicubic) override;
|
||||
GrSamplerState::WrapMode wrapY) override;
|
||||
|
||||
private:
|
||||
GrSurfaceProxyView onView(GrMipMapped) override;
|
||||
|
@ -24,28 +24,20 @@ GrSurfaceProxyView GrTextureMaker::onView(GrMipMapped mipMapped) {
|
||||
|
||||
std::unique_ptr<GrFragmentProcessor> GrTextureMaker::createFragmentProcessor(
|
||||
const SkMatrix& textureMatrix,
|
||||
const SkRect& constraintRect,
|
||||
FilterConstraint filterConstraint,
|
||||
bool coordsLimitedToConstraintRect,
|
||||
GrSamplerState::WrapMode wrapX,
|
||||
GrSamplerState::WrapMode wrapY,
|
||||
const GrSamplerState::Filter* filterOrNullForBicubic) {
|
||||
const SkRect* subset,
|
||||
const SkRect* domain,
|
||||
GrSamplerState sampler) {
|
||||
GrSurfaceProxyView view;
|
||||
if (filterOrNullForBicubic) {
|
||||
view = this->view(*filterOrNullForBicubic);
|
||||
} else {
|
||||
view = this->view(GrMipMapped::kNo);
|
||||
}
|
||||
if (!view) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return this->createFragmentProcessorForSubsetAndFilter(std::move(view),
|
||||
textureMatrix,
|
||||
coordsLimitedToConstraintRect,
|
||||
filterConstraint,
|
||||
constraintRect,
|
||||
wrapX,
|
||||
wrapY,
|
||||
filterOrNullForBicubic);
|
||||
return this->createFragmentProcessorForView(
|
||||
this->view(sampler.filter()), textureMatrix, subset, domain, sampler);
|
||||
}
|
||||
|
||||
std::unique_ptr<GrFragmentProcessor> GrTextureMaker::createBicubicFragmentProcessor(
|
||||
const SkMatrix& textureMatrix,
|
||||
const SkRect* subset,
|
||||
const SkRect* domain,
|
||||
GrSamplerState::WrapMode wrapX,
|
||||
GrSamplerState::WrapMode wrapY) {
|
||||
return this->createBicubicFragmentProcessorForView(
|
||||
this->view(GrMipMapped::kNo), textureMatrix, subset, domain, wrapX, wrapY);
|
||||
}
|
||||
|
@ -16,14 +16,17 @@
|
||||
*/
|
||||
class GrTextureMaker : public GrTextureProducer {
|
||||
public:
|
||||
std::unique_ptr<GrFragmentProcessor> createFragmentProcessor(
|
||||
std::unique_ptr<GrFragmentProcessor> createFragmentProcessor(const SkMatrix& textureMatrix,
|
||||
const SkRect* subset,
|
||||
const SkRect* domain,
|
||||
GrSamplerState) override;
|
||||
|
||||
std::unique_ptr<GrFragmentProcessor> createBicubicFragmentProcessor(
|
||||
const SkMatrix& textureMatrix,
|
||||
const SkRect& constraintRect,
|
||||
FilterConstraint filterConstraint,
|
||||
bool coordsLimitedToConstraintRect,
|
||||
const SkRect* subset,
|
||||
const SkRect* domain,
|
||||
GrSamplerState::WrapMode wrapX,
|
||||
GrSamplerState::WrapMode wrapY,
|
||||
const GrSamplerState::Filter* filterOrNullForBicubic) override;
|
||||
GrSamplerState::WrapMode wrapY) override;
|
||||
|
||||
protected:
|
||||
GrTextureMaker(GrRecordingContext* context, const GrImageInfo& info)
|
||||
|
@ -20,58 +20,68 @@
|
||||
#include "src/gpu/effects/GrBicubicEffect.h"
|
||||
#include "src/gpu/effects/GrTextureEffect.h"
|
||||
|
||||
std::unique_ptr<GrFragmentProcessor> GrTextureProducer::createFragmentProcessorForSubsetAndFilter(
|
||||
std::unique_ptr<GrFragmentProcessor> GrTextureProducer::createFragmentProcessorForView(
|
||||
GrSurfaceProxyView view,
|
||||
const SkMatrix& textureMatrix,
|
||||
bool coordsLimitedToConstraintRect,
|
||||
FilterConstraint filterConstraint,
|
||||
const SkRect& constraintRect,
|
||||
GrSamplerState::WrapMode wrapX,
|
||||
GrSamplerState::WrapMode wrapY,
|
||||
const GrSamplerState::Filter* filterOrNullForBicubic) {
|
||||
const SkRect* subset,
|
||||
const SkRect* domain,
|
||||
GrSamplerState samplerState) {
|
||||
if (!view) {
|
||||
return nullptr;
|
||||
}
|
||||
SkRect tempSubset;
|
||||
|
||||
const SkRect* subset = nullptr;
|
||||
if (filterConstraint == kYes_FilterConstraint) {
|
||||
subset = &constraintRect;
|
||||
} else if (!view.proxy()->isFullyLazy() && !view.proxy()->isFunctionallyExact()) {
|
||||
if (!subset && !view.proxy()->isFullyLazy() && !view.proxy()->isFunctionallyExact()) {
|
||||
tempSubset = view.proxy()->getBoundsRect();
|
||||
subset = &tempSubset;
|
||||
}
|
||||
|
||||
const auto& caps = *fContext->priv().caps();
|
||||
if (filterOrNullForBicubic) {
|
||||
GrSamplerState samplerState(wrapX, wrapY, *filterOrNullForBicubic);
|
||||
if (subset) {
|
||||
if (coordsLimitedToConstraintRect) {
|
||||
return GrTextureEffect::MakeSubset(std::move(view), this->alphaType(),
|
||||
textureMatrix, samplerState, *subset,
|
||||
constraintRect, caps);
|
||||
} else {
|
||||
return GrTextureEffect::MakeSubset(std::move(view), this->alphaType(),
|
||||
textureMatrix, samplerState, *subset, caps);
|
||||
}
|
||||
if (subset) {
|
||||
if (domain) {
|
||||
return GrTextureEffect::MakeSubset(std::move(view), this->alphaType(), textureMatrix,
|
||||
samplerState, *subset, *domain, caps);
|
||||
} else {
|
||||
return GrTextureEffect::Make(std::move(view), this->alphaType(), textureMatrix,
|
||||
samplerState, caps);
|
||||
return GrTextureEffect::MakeSubset(std::move(view), this->alphaType(), textureMatrix,
|
||||
samplerState, *subset, caps);
|
||||
}
|
||||
} else {
|
||||
static constexpr auto kDir = GrBicubicEffect::Direction::kXY;
|
||||
static constexpr auto kKernel = GrBicubicEffect::Kernel::kMitchell;
|
||||
if (subset) {
|
||||
if (coordsLimitedToConstraintRect) {
|
||||
return GrBicubicEffect::MakeSubset(std::move(view), this->alphaType(),
|
||||
textureMatrix, wrapX, wrapY, *subset,
|
||||
constraintRect, kKernel, kDir, caps);
|
||||
} else {
|
||||
return GrBicubicEffect::MakeSubset(std::move(view), this->alphaType(),
|
||||
textureMatrix, wrapX, wrapY, *subset, kKernel,
|
||||
kDir, caps);
|
||||
}
|
||||
return GrTextureEffect::Make(std::move(view), this->alphaType(), textureMatrix,
|
||||
samplerState, caps);
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<GrFragmentProcessor> GrTextureProducer::createBicubicFragmentProcessorForView(
|
||||
GrSurfaceProxyView view,
|
||||
const SkMatrix& textureMatrix,
|
||||
const SkRect* subset,
|
||||
const SkRect* domain,
|
||||
GrSamplerState::WrapMode wrapX,
|
||||
GrSamplerState::WrapMode wrapY) {
|
||||
if (!view) {
|
||||
return nullptr;
|
||||
}
|
||||
SkRect tempSubset;
|
||||
|
||||
if (!subset && !view.proxy()->isFullyLazy() && !view.proxy()->isFunctionallyExact()) {
|
||||
tempSubset = view.proxy()->getBoundsRect();
|
||||
subset = &tempSubset;
|
||||
}
|
||||
|
||||
const auto& caps = *fContext->priv().caps();
|
||||
static constexpr auto kDir = GrBicubicEffect::Direction::kXY;
|
||||
static constexpr auto kKernel = GrBicubicEffect::Kernel::kMitchell;
|
||||
if (subset) {
|
||||
if (domain) {
|
||||
return GrBicubicEffect::MakeSubset(std::move(view), this->alphaType(), textureMatrix,
|
||||
wrapX, wrapY, *subset, *domain, kKernel, kDir, caps);
|
||||
} else {
|
||||
return GrBicubicEffect::Make(std::move(view), this->alphaType(), textureMatrix, wrapX,
|
||||
wrapY, kKernel, kDir, caps);
|
||||
return GrBicubicEffect::MakeSubset(std::move(view), this->alphaType(), textureMatrix,
|
||||
wrapX, wrapY, *subset, kKernel, kDir, caps);
|
||||
}
|
||||
} else {
|
||||
return GrBicubicEffect::Make(std::move(view), this->alphaType(), textureMatrix, wrapX,
|
||||
wrapY, kKernel, kDir, caps);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,39 +34,52 @@ class GrTextureProducer : public SkNoncopyable {
|
||||
public:
|
||||
virtual ~GrTextureProducer() = default;
|
||||
|
||||
enum FilterConstraint {
|
||||
kYes_FilterConstraint,
|
||||
kNo_FilterConstraint,
|
||||
};
|
||||
|
||||
/**
|
||||
/**
|
||||
* Helper for creating a fragment processor to sample the texture with a given filtering mode.
|
||||
* It attempts to avoid making texture copies or using shader tiling whenever possible.
|
||||
* Attempts to avoid unnecessary copies (e.g. for planar sources or subsets) by generating more
|
||||
* complex shader code.
|
||||
*
|
||||
* @param textureMatrix Matrix used to access the texture. It is applied to
|
||||
* the local coords. The post-transformed coords should
|
||||
* be in texel units (rather than normalized) with
|
||||
* respect to this Producer's bounds (width()/height()).
|
||||
* @param constraintRect A rect that represents the area of the texture to be
|
||||
* sampled. It must be contained in the Producer's
|
||||
* bounds as defined by width()/height().
|
||||
* @param filterConstriant Indicates whether filtering is limited to
|
||||
* constraintRect.
|
||||
* @param coordsLimitedToConstraintRect Is it known that textureMatrix*localCoords is bound
|
||||
* by the portion of the texture indicated by
|
||||
* constraintRect (without consideration of filter
|
||||
* width, just the raw coords).
|
||||
* @param filterOrNullForBicubic If non-null indicates the filter mode. If null means
|
||||
* use bicubic filtering.
|
||||
* @param subset If not null, a subset of the texture to restrict
|
||||
* sampling to. The wrap modes apply to this subset.
|
||||
* @param domain If not null, a known limit on the texture coordinates
|
||||
* that will be accessed. Applies after textureMatrix.
|
||||
* @param sampler Sampler state. Wrap modes applies to subset if not
|
||||
* null, otherwise to the entire source.
|
||||
**/
|
||||
virtual std::unique_ptr<GrFragmentProcessor> createFragmentProcessor(
|
||||
const SkMatrix& textureMatrix,
|
||||
const SkRect& constraintRect,
|
||||
FilterConstraint filterConstraint,
|
||||
bool coordsLimitedToConstraintRect,
|
||||
const SkRect* subset,
|
||||
const SkRect* domain,
|
||||
GrSamplerState sampler) = 0;
|
||||
|
||||
/**
|
||||
* Similar createFragmentProcessor but produces a fragment processor that does bicubic
|
||||
* interpolation of the source. Attempts to avoid unnecessary copies (e.g. for planar sources or
|
||||
* subsets) by generating more complex shader code.
|
||||
*
|
||||
* @param textureMatrix Matrix used to access the texture. It is applied to
|
||||
* the local coords. The post-transformed coords should
|
||||
* be in texel units (rather than normalized) with
|
||||
* respect to this Producer's bounds (width()/height()).
|
||||
* @param subset If not null, a subset of the texture to restrict
|
||||
* sampling to. The wrap modes apply to this subset.
|
||||
* @param domain If not null, a known limit on the texture coordinates
|
||||
* that will be accessed. Applies after textureMatrix.
|
||||
* @param wrapX Wrap mode on x axis. Applied to subset if not null,
|
||||
* otherwise to the entire source.
|
||||
* @param wrapY Wrap mode on y axis. Applied to subset if not null,
|
||||
* otherwise to the entire source.
|
||||
*/
|
||||
virtual std::unique_ptr<GrFragmentProcessor> createBicubicFragmentProcessor(
|
||||
const SkMatrix& textureMatrix,
|
||||
const SkRect* subset,
|
||||
const SkRect* domain,
|
||||
GrSamplerState::WrapMode wrapX,
|
||||
GrSamplerState::WrapMode wrapY,
|
||||
const GrSamplerState::Filter* filterOrNullForBicubic) = 0;
|
||||
GrSamplerState::WrapMode wrapY) = 0;
|
||||
|
||||
/**
|
||||
* Returns a texture view, possibly with MIP maps. The request for MIP maps may not be honored
|
||||
@ -92,15 +105,22 @@ protected:
|
||||
GrTextureProducer(GrRecordingContext* context, const GrImageInfo& imageInfo)
|
||||
: fContext(context), fImageInfo(imageInfo) {}
|
||||
|
||||
std::unique_ptr<GrFragmentProcessor> createFragmentProcessorForSubsetAndFilter(
|
||||
// Helper for making a texture effect from a single proxy view.
|
||||
std::unique_ptr<GrFragmentProcessor> createFragmentProcessorForView(
|
||||
GrSurfaceProxyView view,
|
||||
const SkMatrix& textureMatrix,
|
||||
bool coordsLimitedToConstraintRect,
|
||||
FilterConstraint filterConstraint,
|
||||
const SkRect& constraintRect,
|
||||
const SkRect* subset,
|
||||
const SkRect* domain,
|
||||
GrSamplerState sampler);
|
||||
|
||||
// Helper for making a bicubic effect from a single proxy view.
|
||||
std::unique_ptr<GrFragmentProcessor> createBicubicFragmentProcessorForView(
|
||||
GrSurfaceProxyView view,
|
||||
const SkMatrix& textureMatrix,
|
||||
const SkRect* subset,
|
||||
const SkRect* domain,
|
||||
GrSamplerState::WrapMode wrapX,
|
||||
GrSamplerState::WrapMode wrapY,
|
||||
const GrSamplerState::Filter* filterOrNullForBicubic);
|
||||
GrSamplerState::WrapMode wrapY);
|
||||
|
||||
GrRecordingContext* context() const { return fContext; }
|
||||
|
||||
|
@ -436,14 +436,8 @@ static void draw_texture_producer(GrRecordingContext* context,
|
||||
if (mf && as_MFB(mf)->hasFragmentProcessor()) {
|
||||
mf = nullptr;
|
||||
}
|
||||
const GrSamplerState::Filter* filterMode = doBicubic ? nullptr : &fm;
|
||||
|
||||
GrTextureProducer::FilterConstraint constraintMode;
|
||||
if (SkCanvas::kFast_SrcRectConstraint == constraint) {
|
||||
constraintMode = GrTextureAdjuster::kNo_FilterConstraint;
|
||||
} else {
|
||||
constraintMode = GrTextureAdjuster::kYes_FilterConstraint;
|
||||
}
|
||||
bool restrictToSubset = SkCanvas::kStrict_SrcRectConstraint == constraint;
|
||||
|
||||
// If we have to outset for AA then we will generate texture coords outside the src rect. The
|
||||
// same happens for any mask filter that extends the bounds rendered in the dst.
|
||||
@ -451,13 +445,12 @@ static void draw_texture_producer(GrRecordingContext* context,
|
||||
bool coordsAllInsideSrcRect = aaFlags == GrQuadAAFlags::kNone && !mf;
|
||||
|
||||
// Check for optimization to drop the src rect constraint when on bilerp.
|
||||
if (filterMode && GrSamplerState::Filter::kBilerp == *filterMode &&
|
||||
GrTextureAdjuster::kYes_FilterConstraint == constraintMode && coordsAllInsideSrcRect &&
|
||||
!producer->isPlanar()) {
|
||||
if (!doBicubic && fm == GrSamplerState::Filter::kBilerp && restrictToSubset &&
|
||||
coordsAllInsideSrcRect && !producer->isPlanar()) {
|
||||
SkMatrix combinedMatrix;
|
||||
combinedMatrix.setConcat(ctm, srcToDst);
|
||||
if (can_ignore_bilerp_constraint(*producer, src, combinedMatrix, rtc->numSamples())) {
|
||||
constraintMode = GrTextureAdjuster::kNo_FilterConstraint;
|
||||
restrictToSubset = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -469,8 +462,14 @@ static void draw_texture_producer(GrRecordingContext* context,
|
||||
return;
|
||||
}
|
||||
}
|
||||
auto fp = producer->createFragmentProcessor(textureMatrix, src, constraintMode,
|
||||
coordsAllInsideSrcRect, wm, wm, filterMode);
|
||||
const SkRect* subset = restrictToSubset ? &src : nullptr;
|
||||
const SkRect* domain = coordsAllInsideSrcRect ? &src : nullptr;
|
||||
std::unique_ptr<GrFragmentProcessor> fp;
|
||||
if (doBicubic) {
|
||||
fp = producer->createBicubicFragmentProcessor(textureMatrix, subset, domain, wm, wm);
|
||||
} else {
|
||||
fp = producer->createFragmentProcessor(textureMatrix, subset, domain, {wm, fm});
|
||||
}
|
||||
fp = GrColorSpaceXformEffect::Make(std::move(fp),
|
||||
producer->colorSpace(), producer->alphaType(),
|
||||
rtc->colorInfo().colorSpace(), kPremul_SkAlphaType);
|
||||
|
@ -265,11 +265,12 @@ std::unique_ptr<GrFragmentProcessor> GrTextureEffect::MakeBilerpWithInset(
|
||||
GrSamplerState::WrapMode wx,
|
||||
GrSamplerState::WrapMode wy,
|
||||
const SkRect& subset,
|
||||
const SkRect* domain,
|
||||
SkVector inset,
|
||||
const GrCaps& caps,
|
||||
const float border[4]) {
|
||||
GrSamplerState sampler(wx, wy, GrSamplerState::Filter::kBilerp);
|
||||
Sampling sampling(*view.proxy(), sampler, subset, nullptr, border, caps, inset);
|
||||
Sampling sampling(*view.proxy(), sampler, subset, domain, border, caps, inset);
|
||||
SkMatrix final;
|
||||
bool lazyProxyNormalization;
|
||||
get_matrix(matrix, view, &final, &lazyProxyNormalization);
|
||||
|
@ -74,7 +74,8 @@ public:
|
||||
* subset. When subset is an integer rectangle this clamping avoids the hw bilerp filtering from
|
||||
* reading texels just outside the subset rect. This factory allows a custom inset clamping
|
||||
* distance rather than 0.5, allowing those neighboring texels to influence the bilerped sample
|
||||
* result.
|
||||
* result. If there is a known restriction on the post-matrix texture coords it can be specified
|
||||
* using domain.
|
||||
*/
|
||||
static std::unique_ptr<GrFragmentProcessor> MakeBilerpWithInset(
|
||||
GrSurfaceProxyView,
|
||||
@ -83,6 +84,7 @@ public:
|
||||
GrSamplerState::WrapMode wx,
|
||||
GrSamplerState::WrapMode wy,
|
||||
const SkRect& subset,
|
||||
const SkRect* domain,
|
||||
SkVector inset,
|
||||
const GrCaps& caps,
|
||||
const float border[4] = kDefaultBorder);
|
||||
|
@ -36,7 +36,8 @@ std::unique_ptr<GrFragmentProcessor> GrYUVtoRGBEffect::Make(GrSurfaceProxyView v
|
||||
GrSamplerState samplerState,
|
||||
const GrCaps& caps,
|
||||
const SkMatrix& localMatrix,
|
||||
const SkRect* subset) {
|
||||
const SkRect* subset,
|
||||
const SkRect* domain) {
|
||||
int numPlanes;
|
||||
SkAssertResult(SkYUVAIndex::AreValidIndices(yuvaIndices, &numPlanes));
|
||||
|
||||
@ -56,6 +57,7 @@ std::unique_ptr<GrFragmentProcessor> GrYUVtoRGBEffect::Make(GrSurfaceProxyView v
|
||||
SkISize dimensions = views[i].proxy()->dimensions();
|
||||
SkTCopyOnFirstWrite<SkMatrix> planeMatrix(&SkMatrix::I());
|
||||
SkRect planeSubset;
|
||||
SkRect planeDomain;
|
||||
bool makeBilerpWithSnap = false;
|
||||
float sx = 1.f,
|
||||
sy = 1.f;
|
||||
@ -73,6 +75,19 @@ std::unique_ptr<GrFragmentProcessor> GrYUVtoRGBEffect::Make(GrSurfaceProxyView v
|
||||
dimensions.height() == yDimensions.height() / 2 + 1) {
|
||||
sy = 0.5f;
|
||||
}
|
||||
*planeMatrix.writable() = SkMatrix::Scale(sx, sy);
|
||||
if (subset) {
|
||||
planeSubset = {subset->fLeft * sx,
|
||||
subset->fTop * sy,
|
||||
subset->fRight * sx,
|
||||
subset->fBottom * sy};
|
||||
}
|
||||
if (domain) {
|
||||
planeDomain = {domain->fLeft * sx,
|
||||
domain->fTop * sy,
|
||||
domain->fRight * sx,
|
||||
domain->fBottom * sy};
|
||||
}
|
||||
// This promotion of nearest to bilinear for UV planes exists to mimic libjpeg[-turbo]'s
|
||||
// do_fancy_upsampling option. We will filter the subsampled plane, however we want to
|
||||
// filter at a fixed point for each logical image pixel to simulate nearest neighbor.
|
||||
@ -82,18 +97,25 @@ std::unique_ptr<GrFragmentProcessor> GrYUVtoRGBEffect::Make(GrSurfaceProxyView v
|
||||
makeBilerpWithSnap = snapX || snapY;
|
||||
snap[0] |= snapX;
|
||||
snap[1] |= snapY;
|
||||
if (domain) {
|
||||
// The outer YUVToRGB effect will ensure sampling happens at pixel centers
|
||||
// within this plane.
|
||||
planeDomain = {std::floor(planeDomain.fLeft) + 0.5f,
|
||||
std::floor(planeDomain.fTop) + 0.5f,
|
||||
std::floor(planeDomain.fRight) + 0.5f,
|
||||
std::floor(planeDomain.fBottom) + 0.5f};
|
||||
}
|
||||
}
|
||||
*planeMatrix.writable() = SkMatrix::Scale(sx, sy);
|
||||
} else {
|
||||
if (subset) {
|
||||
planeSubset = {subset->fLeft * sx,
|
||||
subset->fTop * sy,
|
||||
subset->fRight * sx,
|
||||
subset->fBottom * sy};
|
||||
planeSubset = *subset;
|
||||
}
|
||||
if (domain) {
|
||||
planeDomain = *domain;
|
||||
}
|
||||
} else if (subset) {
|
||||
planeSubset = *subset;
|
||||
}
|
||||
if (subset) {
|
||||
SkASSERT(samplerState.filter() != GrSamplerState::Filter::kMipMap);
|
||||
if (makeBilerpWithSnap) {
|
||||
// The plane is subsampled and we have an overall subset on the image. We're
|
||||
// emulating do_fancy_upsampling using bilerp but snapping look ups to the y-plane
|
||||
@ -104,10 +126,15 @@ std::unique_ptr<GrFragmentProcessor> GrYUVtoRGBEffect::Make(GrSurfaceProxyView v
|
||||
// we use this custom inset factory which applies the wrap mode to planeSubset but
|
||||
// allows the bilerp sampling to read pixels from the plane that are just outside
|
||||
// planeSubset.
|
||||
SkRect* domainRect = domain ? &planeDomain : nullptr;
|
||||
planeFPs[i] = GrTextureEffect::MakeBilerpWithInset(
|
||||
views[i], kUnknown_SkAlphaType, *planeMatrix, samplerState.wrapModeX(),
|
||||
samplerState.wrapModeY(), planeSubset, {sx/2.f, sy/2.f}, caps,
|
||||
samplerState.wrapModeY(), planeSubset, domainRect, {sx/2.f, sy/2.f}, caps,
|
||||
planeBorders[i]);
|
||||
} else if (domain) {
|
||||
planeFPs[i] = GrTextureEffect::MakeSubset(views[i], kUnknown_SkAlphaType,
|
||||
*planeMatrix, samplerState, planeSubset,
|
||||
planeDomain, caps, planeBorders[i]);
|
||||
} else {
|
||||
SkASSERT(samplerState.filter() != GrSamplerState::Filter::kMipMap);
|
||||
planeFPs[i] = GrTextureEffect::MakeSubset(views[i], kUnknown_SkAlphaType,
|
||||
|
@ -21,7 +21,8 @@ public:
|
||||
GrSamplerState samplerState,
|
||||
const GrCaps&,
|
||||
const SkMatrix& localMatrix = SkMatrix::I(),
|
||||
const SkRect* subset = nullptr);
|
||||
const SkRect* subset = nullptr,
|
||||
const SkRect* domain = nullptr);
|
||||
#ifdef SK_DEBUG
|
||||
SkString dumpInfo() const override;
|
||||
#endif
|
||||
|
@ -302,20 +302,22 @@ std::unique_ptr<GrFragmentProcessor> SkImageShader::asFragmentProcessor(
|
||||
// quality setting. This completely ignores the complexity of the drawVertices case
|
||||
// where explicit local coords are provided by the caller.
|
||||
bool doBicubic;
|
||||
GrSamplerState::Filter textureFilterMode = GrSkFilterQualityToGrFilterMode(
|
||||
GrSamplerState::Filter fm = GrSkFilterQualityToGrFilterMode(
|
||||
fImage->width(), fImage->height(), this->resolveFiltering(args.fFilterQuality),
|
||||
args.fMatrixProvider.localToDevice(), *lm,
|
||||
args.fContext->priv().options().fSharpenMipmappedTextures, &doBicubic);
|
||||
const GrSamplerState::Filter* filterOrNull = doBicubic ? nullptr : &textureFilterMode;
|
||||
auto fp = producer->createFragmentProcessor(lmInverse, SkRect::Make(fImage->dimensions()),
|
||||
GrTextureProducer::kNo_FilterConstraint, false, wmX,
|
||||
wmY, filterOrNull);
|
||||
std::unique_ptr<GrFragmentProcessor> fp;
|
||||
if (doBicubic) {
|
||||
fp = producer->createBicubicFragmentProcessor(lmInverse, nullptr, nullptr, wmX, wmY);
|
||||
} else {
|
||||
fp = producer->createFragmentProcessor(lmInverse, nullptr, nullptr, {wmX, wmY, fm});
|
||||
}
|
||||
|
||||
fp = GrColorSpaceXformEffect::Make(std::move(fp), fImage->colorSpace(), producer->alphaType(),
|
||||
args.fDstColorInfo->colorSpace(), kPremul_SkAlphaType);
|
||||
if (!fp) {
|
||||
return nullptr;
|
||||
}
|
||||
fp = GrColorSpaceXformEffect::Make(std::move(fp), fImage->colorSpace(), producer->alphaType(),
|
||||
args.fDstColorInfo->colorSpace(), kPremul_SkAlphaType);
|
||||
bool isAlphaOnly = SkColorTypeIsAlphaOnly(fImage->colorType());
|
||||
if (isAlphaOnly) {
|
||||
return fp;
|
||||
|
Loading…
Reference in New Issue
Block a user