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(
|
std::unique_ptr<GrFragmentProcessor> GrYUVAImageTextureMaker::createFragmentProcessor(
|
||||||
const SkMatrix& textureMatrix,
|
const SkMatrix& textureMatrix,
|
||||||
const SkRect& constraintRect,
|
const SkRect* subset,
|
||||||
FilterConstraint filterConstraint,
|
const SkRect* domain,
|
||||||
bool coordsLimitedToConstraintRect,
|
GrSamplerState samplerState) {
|
||||||
GrSamplerState::WrapMode wrapX,
|
|
||||||
GrSamplerState::WrapMode wrapY,
|
|
||||||
const GrSamplerState::Filter* filterOrNullForBicubic) {
|
|
||||||
// Check whether it's already been flattened.
|
// Check whether it's already been flattened.
|
||||||
if (fImage->fRGBView.proxy()) {
|
if (fImage->fRGBView.proxy()) {
|
||||||
return this->INHERITED::createFragmentProcessor(
|
return this->INHERITED::createFragmentProcessor(textureMatrix, subset, domain,
|
||||||
textureMatrix, constraintRect, filterConstraint, coordsLimitedToConstraintRect,
|
samplerState);
|
||||||
wrapX, wrapY, filterOrNullForBicubic);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
// 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 not, fall back to bilerp. Also fall back to bilerp when a domain is requested
|
||||||
if (GrSamplerState::Filter::kMipMap == filter &&
|
if (samplerState.filter() == GrSamplerState::Filter::kMipMap &&
|
||||||
(filterConstraint == GrTextureProducer::kYes_FilterConstraint ||
|
(subset || !fImage->setupMipmapsForPlanes(this->context()))) {
|
||||||
!fImage->setupMipmapsForPlanes(this->context()))) {
|
samplerState.setFilterMode(GrSamplerState::Filter::kBilerp);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& caps = *fImage->context()->priv().caps();
|
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,
|
auto fp = GrYUVtoRGBEffect::Make(fImage->fViews, fImage->fYUVAIndices, fImage->fYUVColorSpace,
|
||||||
sampler, caps, m, domain);
|
samplerState, caps, textureMatrix, subset, domain);
|
||||||
if (!filterOrNullForBicubic) {
|
if (fImage->fFromColorSpace) {
|
||||||
fp = GrBicubicEffect::Make(std::move(fp),
|
fp = GrColorSpaceXformEffect::Make(std::move(fp), fImage->fFromColorSpace.get(),
|
||||||
fImage->alphaType(),
|
fImage->alphaType(), fImage->colorSpace(),
|
||||||
textureMatrix,
|
kPremul_SkAlphaType);
|
||||||
GrBicubicEffect::Kernel::kMitchell,
|
|
||||||
GrBicubicEffect::Direction::kXY);
|
|
||||||
}
|
}
|
||||||
|
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) {
|
if (fImage->fFromColorSpace) {
|
||||||
fp = GrColorSpaceXformEffect::Make(std::move(fp),
|
fp = GrColorSpaceXformEffect::Make(std::move(fp),
|
||||||
fImage->fFromColorSpace.get(), fImage->alphaType(),
|
fImage->fFromColorSpace.get(), fImage->alphaType(),
|
||||||
|
@ -35,14 +35,17 @@ class GrYUVAImageTextureMaker final : public GrTextureMaker {
|
|||||||
public:
|
public:
|
||||||
GrYUVAImageTextureMaker(GrRecordingContext* context, const SkImage* client);
|
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 SkMatrix& textureMatrix,
|
||||||
const SkRect& constraintRect,
|
const SkRect* subset,
|
||||||
FilterConstraint filterConstraint,
|
const SkRect* domain,
|
||||||
bool coordsLimitedToConstraintRect,
|
|
||||||
GrSamplerState::WrapMode wrapX,
|
GrSamplerState::WrapMode wrapX,
|
||||||
GrSamplerState::WrapMode wrapY,
|
GrSamplerState::WrapMode wrapY) override;
|
||||||
const GrSamplerState::Filter* filterOrNullForBicubic) override;
|
|
||||||
|
|
||||||
bool isPlanar() const override { return true; }
|
bool isPlanar() const override { return true; }
|
||||||
|
|
||||||
|
@ -77,29 +77,19 @@ GrSurfaceProxyView GrTextureAdjuster::onView(GrMipMapped mipMapped) {
|
|||||||
|
|
||||||
std::unique_ptr<GrFragmentProcessor> GrTextureAdjuster::createFragmentProcessor(
|
std::unique_ptr<GrFragmentProcessor> GrTextureAdjuster::createFragmentProcessor(
|
||||||
const SkMatrix& textureMatrix,
|
const SkMatrix& textureMatrix,
|
||||||
const SkRect& constraintRect,
|
const SkRect* subset,
|
||||||
FilterConstraint filterConstraint,
|
const SkRect* domain,
|
||||||
bool coordsLimitedToConstraintRect,
|
GrSamplerState samplerState) {
|
||||||
GrSamplerState::WrapMode wrapX,
|
return this->createFragmentProcessorForView(
|
||||||
GrSamplerState::WrapMode wrapY,
|
this->view(samplerState.filter()), textureMatrix, subset, domain, samplerState);
|
||||||
const GrSamplerState::Filter* filterOrNullForBicubic) {
|
}
|
||||||
GrSurfaceProxyView view;
|
|
||||||
if (filterOrNullForBicubic) {
|
std::unique_ptr<GrFragmentProcessor> GrTextureAdjuster::createBicubicFragmentProcessor(
|
||||||
view = this->view(*filterOrNullForBicubic);
|
const SkMatrix& textureMatrix,
|
||||||
} else {
|
const SkRect* subset,
|
||||||
view = this->view(GrMipMapped::kNo);
|
const SkRect* domain,
|
||||||
}
|
GrSamplerState::WrapMode wrapX,
|
||||||
if (!view) {
|
GrSamplerState::WrapMode wrapY) {
|
||||||
return nullptr;
|
return this->createBicubicFragmentProcessorForView(
|
||||||
}
|
this->view(GrMipMapped::kNo), textureMatrix, subset, domain, wrapX, wrapY);
|
||||||
SkASSERT(view.asTextureProxy());
|
|
||||||
|
|
||||||
return this->createFragmentProcessorForSubsetAndFilter(std::move(view),
|
|
||||||
textureMatrix,
|
|
||||||
coordsLimitedToConstraintRect,
|
|
||||||
filterConstraint,
|
|
||||||
constraintRect,
|
|
||||||
wrapX,
|
|
||||||
wrapY,
|
|
||||||
filterOrNullForBicubic);
|
|
||||||
}
|
}
|
||||||
|
@ -23,14 +23,17 @@ public:
|
|||||||
GrTextureAdjuster(GrRecordingContext*, GrSurfaceProxyView, const GrColorInfo&,
|
GrTextureAdjuster(GrRecordingContext*, GrSurfaceProxyView, const GrColorInfo&,
|
||||||
uint32_t uniqueID);
|
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 SkMatrix& textureMatrix,
|
||||||
const SkRect& constraintRect,
|
const SkRect* subset,
|
||||||
FilterConstraint,
|
const SkRect* domain,
|
||||||
bool coordsLimitedToConstraintRect,
|
|
||||||
GrSamplerState::WrapMode wrapX,
|
GrSamplerState::WrapMode wrapX,
|
||||||
GrSamplerState::WrapMode wrapY,
|
GrSamplerState::WrapMode wrapY) override;
|
||||||
const GrSamplerState::Filter* filterOrNullForBicubic) override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GrSurfaceProxyView onView(GrMipMapped) override;
|
GrSurfaceProxyView onView(GrMipMapped) override;
|
||||||
|
@ -24,28 +24,20 @@ GrSurfaceProxyView GrTextureMaker::onView(GrMipMapped mipMapped) {
|
|||||||
|
|
||||||
std::unique_ptr<GrFragmentProcessor> GrTextureMaker::createFragmentProcessor(
|
std::unique_ptr<GrFragmentProcessor> GrTextureMaker::createFragmentProcessor(
|
||||||
const SkMatrix& textureMatrix,
|
const SkMatrix& textureMatrix,
|
||||||
const SkRect& constraintRect,
|
const SkRect* subset,
|
||||||
FilterConstraint filterConstraint,
|
const SkRect* domain,
|
||||||
bool coordsLimitedToConstraintRect,
|
GrSamplerState sampler) {
|
||||||
GrSamplerState::WrapMode wrapX,
|
|
||||||
GrSamplerState::WrapMode wrapY,
|
|
||||||
const GrSamplerState::Filter* filterOrNullForBicubic) {
|
|
||||||
GrSurfaceProxyView view;
|
GrSurfaceProxyView view;
|
||||||
if (filterOrNullForBicubic) {
|
return this->createFragmentProcessorForView(
|
||||||
view = this->view(*filterOrNullForBicubic);
|
this->view(sampler.filter()), textureMatrix, subset, domain, sampler);
|
||||||
} else {
|
}
|
||||||
view = this->view(GrMipMapped::kNo);
|
|
||||||
}
|
std::unique_ptr<GrFragmentProcessor> GrTextureMaker::createBicubicFragmentProcessor(
|
||||||
if (!view) {
|
const SkMatrix& textureMatrix,
|
||||||
return nullptr;
|
const SkRect* subset,
|
||||||
}
|
const SkRect* domain,
|
||||||
|
GrSamplerState::WrapMode wrapX,
|
||||||
return this->createFragmentProcessorForSubsetAndFilter(std::move(view),
|
GrSamplerState::WrapMode wrapY) {
|
||||||
textureMatrix,
|
return this->createBicubicFragmentProcessorForView(
|
||||||
coordsLimitedToConstraintRect,
|
this->view(GrMipMapped::kNo), textureMatrix, subset, domain, wrapX, wrapY);
|
||||||
filterConstraint,
|
|
||||||
constraintRect,
|
|
||||||
wrapX,
|
|
||||||
wrapY,
|
|
||||||
filterOrNullForBicubic);
|
|
||||||
}
|
}
|
||||||
|
@ -16,14 +16,17 @@
|
|||||||
*/
|
*/
|
||||||
class GrTextureMaker : public GrTextureProducer {
|
class GrTextureMaker : public GrTextureProducer {
|
||||||
public:
|
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 SkMatrix& textureMatrix,
|
||||||
const SkRect& constraintRect,
|
const SkRect* subset,
|
||||||
FilterConstraint filterConstraint,
|
const SkRect* domain,
|
||||||
bool coordsLimitedToConstraintRect,
|
|
||||||
GrSamplerState::WrapMode wrapX,
|
GrSamplerState::WrapMode wrapX,
|
||||||
GrSamplerState::WrapMode wrapY,
|
GrSamplerState::WrapMode wrapY) override;
|
||||||
const GrSamplerState::Filter* filterOrNullForBicubic) override;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
GrTextureMaker(GrRecordingContext* context, const GrImageInfo& info)
|
GrTextureMaker(GrRecordingContext* context, const GrImageInfo& info)
|
||||||
|
@ -20,58 +20,68 @@
|
|||||||
#include "src/gpu/effects/GrBicubicEffect.h"
|
#include "src/gpu/effects/GrBicubicEffect.h"
|
||||||
#include "src/gpu/effects/GrTextureEffect.h"
|
#include "src/gpu/effects/GrTextureEffect.h"
|
||||||
|
|
||||||
std::unique_ptr<GrFragmentProcessor> GrTextureProducer::createFragmentProcessorForSubsetAndFilter(
|
std::unique_ptr<GrFragmentProcessor> GrTextureProducer::createFragmentProcessorForView(
|
||||||
GrSurfaceProxyView view,
|
GrSurfaceProxyView view,
|
||||||
const SkMatrix& textureMatrix,
|
const SkMatrix& textureMatrix,
|
||||||
bool coordsLimitedToConstraintRect,
|
const SkRect* subset,
|
||||||
FilterConstraint filterConstraint,
|
const SkRect* domain,
|
||||||
const SkRect& constraintRect,
|
GrSamplerState samplerState) {
|
||||||
GrSamplerState::WrapMode wrapX,
|
if (!view) {
|
||||||
GrSamplerState::WrapMode wrapY,
|
return nullptr;
|
||||||
const GrSamplerState::Filter* filterOrNullForBicubic) {
|
}
|
||||||
SkRect tempSubset;
|
SkRect tempSubset;
|
||||||
|
|
||||||
const SkRect* subset = nullptr;
|
if (!subset && !view.proxy()->isFullyLazy() && !view.proxy()->isFunctionallyExact()) {
|
||||||
if (filterConstraint == kYes_FilterConstraint) {
|
|
||||||
subset = &constraintRect;
|
|
||||||
} else if (!view.proxy()->isFullyLazy() && !view.proxy()->isFunctionallyExact()) {
|
|
||||||
tempSubset = view.proxy()->getBoundsRect();
|
tempSubset = view.proxy()->getBoundsRect();
|
||||||
subset = &tempSubset;
|
subset = &tempSubset;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& caps = *fContext->priv().caps();
|
const auto& caps = *fContext->priv().caps();
|
||||||
if (filterOrNullForBicubic) {
|
if (subset) {
|
||||||
GrSamplerState samplerState(wrapX, wrapY, *filterOrNullForBicubic);
|
if (domain) {
|
||||||
if (subset) {
|
return GrTextureEffect::MakeSubset(std::move(view), this->alphaType(), textureMatrix,
|
||||||
if (coordsLimitedToConstraintRect) {
|
samplerState, *subset, *domain, caps);
|
||||||
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);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
return GrTextureEffect::Make(std::move(view), this->alphaType(), textureMatrix,
|
return GrTextureEffect::MakeSubset(std::move(view), this->alphaType(), textureMatrix,
|
||||||
samplerState, caps);
|
samplerState, *subset, caps);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
static constexpr auto kDir = GrBicubicEffect::Direction::kXY;
|
return GrTextureEffect::Make(std::move(view), this->alphaType(), textureMatrix,
|
||||||
static constexpr auto kKernel = GrBicubicEffect::Kernel::kMitchell;
|
samplerState, caps);
|
||||||
if (subset) {
|
}
|
||||||
if (coordsLimitedToConstraintRect) {
|
}
|
||||||
return GrBicubicEffect::MakeSubset(std::move(view), this->alphaType(),
|
|
||||||
textureMatrix, wrapX, wrapY, *subset,
|
std::unique_ptr<GrFragmentProcessor> GrTextureProducer::createBicubicFragmentProcessorForView(
|
||||||
constraintRect, kKernel, kDir, caps);
|
GrSurfaceProxyView view,
|
||||||
} else {
|
const SkMatrix& textureMatrix,
|
||||||
return GrBicubicEffect::MakeSubset(std::move(view), this->alphaType(),
|
const SkRect* subset,
|
||||||
textureMatrix, wrapX, wrapY, *subset, kKernel,
|
const SkRect* domain,
|
||||||
kDir, caps);
|
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 {
|
} else {
|
||||||
return GrBicubicEffect::Make(std::move(view), this->alphaType(), textureMatrix, wrapX,
|
return GrBicubicEffect::MakeSubset(std::move(view), this->alphaType(), textureMatrix,
|
||||||
wrapY, kKernel, kDir, caps);
|
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:
|
public:
|
||||||
virtual ~GrTextureProducer() = default;
|
virtual ~GrTextureProducer() = default;
|
||||||
|
|
||||||
enum FilterConstraint {
|
/**
|
||||||
kYes_FilterConstraint,
|
|
||||||
kNo_FilterConstraint,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper for creating a fragment processor to sample the texture with a given filtering mode.
|
* 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
|
* @param textureMatrix Matrix used to access the texture. It is applied to
|
||||||
* the local coords. The post-transformed coords should
|
* the local coords. The post-transformed coords should
|
||||||
* be in texel units (rather than normalized) with
|
* be in texel units (rather than normalized) with
|
||||||
* respect to this Producer's bounds (width()/height()).
|
* respect to this Producer's bounds (width()/height()).
|
||||||
* @param constraintRect A rect that represents the area of the texture to be
|
* @param subset If not null, a subset of the texture to restrict
|
||||||
* sampled. It must be contained in the Producer's
|
* sampling to. The wrap modes apply to this subset.
|
||||||
* bounds as defined by width()/height().
|
* @param domain If not null, a known limit on the texture coordinates
|
||||||
* @param filterConstriant Indicates whether filtering is limited to
|
* that will be accessed. Applies after textureMatrix.
|
||||||
* constraintRect.
|
* @param sampler Sampler state. Wrap modes applies to subset if not
|
||||||
* @param coordsLimitedToConstraintRect Is it known that textureMatrix*localCoords is bound
|
* null, otherwise to the entire source.
|
||||||
* 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.
|
|
||||||
**/
|
**/
|
||||||
virtual std::unique_ptr<GrFragmentProcessor> createFragmentProcessor(
|
virtual std::unique_ptr<GrFragmentProcessor> createFragmentProcessor(
|
||||||
const SkMatrix& textureMatrix,
|
const SkMatrix& textureMatrix,
|
||||||
const SkRect& constraintRect,
|
const SkRect* subset,
|
||||||
FilterConstraint filterConstraint,
|
const SkRect* domain,
|
||||||
bool coordsLimitedToConstraintRect,
|
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 wrapX,
|
||||||
GrSamplerState::WrapMode wrapY,
|
GrSamplerState::WrapMode wrapY) = 0;
|
||||||
const GrSamplerState::Filter* filterOrNullForBicubic) = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a texture view, possibly with MIP maps. The request for MIP maps may not be honored
|
* 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)
|
GrTextureProducer(GrRecordingContext* context, const GrImageInfo& imageInfo)
|
||||||
: fContext(context), fImageInfo(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,
|
GrSurfaceProxyView view,
|
||||||
const SkMatrix& textureMatrix,
|
const SkMatrix& textureMatrix,
|
||||||
bool coordsLimitedToConstraintRect,
|
const SkRect* subset,
|
||||||
FilterConstraint filterConstraint,
|
const SkRect* domain,
|
||||||
const SkRect& constraintRect,
|
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 wrapX,
|
||||||
GrSamplerState::WrapMode wrapY,
|
GrSamplerState::WrapMode wrapY);
|
||||||
const GrSamplerState::Filter* filterOrNullForBicubic);
|
|
||||||
|
|
||||||
GrRecordingContext* context() const { return fContext; }
|
GrRecordingContext* context() const { return fContext; }
|
||||||
|
|
||||||
|
@ -436,14 +436,8 @@ static void draw_texture_producer(GrRecordingContext* context,
|
|||||||
if (mf && as_MFB(mf)->hasFragmentProcessor()) {
|
if (mf && as_MFB(mf)->hasFragmentProcessor()) {
|
||||||
mf = nullptr;
|
mf = nullptr;
|
||||||
}
|
}
|
||||||
const GrSamplerState::Filter* filterMode = doBicubic ? nullptr : &fm;
|
|
||||||
|
|
||||||
GrTextureProducer::FilterConstraint constraintMode;
|
bool restrictToSubset = SkCanvas::kStrict_SrcRectConstraint == constraint;
|
||||||
if (SkCanvas::kFast_SrcRectConstraint == constraint) {
|
|
||||||
constraintMode = GrTextureAdjuster::kNo_FilterConstraint;
|
|
||||||
} else {
|
|
||||||
constraintMode = GrTextureAdjuster::kYes_FilterConstraint;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we have to outset for AA then we will generate texture coords outside the src rect. The
|
// 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.
|
// 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;
|
bool coordsAllInsideSrcRect = aaFlags == GrQuadAAFlags::kNone && !mf;
|
||||||
|
|
||||||
// Check for optimization to drop the src rect constraint when on bilerp.
|
// Check for optimization to drop the src rect constraint when on bilerp.
|
||||||
if (filterMode && GrSamplerState::Filter::kBilerp == *filterMode &&
|
if (!doBicubic && fm == GrSamplerState::Filter::kBilerp && restrictToSubset &&
|
||||||
GrTextureAdjuster::kYes_FilterConstraint == constraintMode && coordsAllInsideSrcRect &&
|
coordsAllInsideSrcRect && !producer->isPlanar()) {
|
||||||
!producer->isPlanar()) {
|
|
||||||
SkMatrix combinedMatrix;
|
SkMatrix combinedMatrix;
|
||||||
combinedMatrix.setConcat(ctm, srcToDst);
|
combinedMatrix.setConcat(ctm, srcToDst);
|
||||||
if (can_ignore_bilerp_constraint(*producer, src, combinedMatrix, rtc->numSamples())) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto fp = producer->createFragmentProcessor(textureMatrix, src, constraintMode,
|
const SkRect* subset = restrictToSubset ? &src : nullptr;
|
||||||
coordsAllInsideSrcRect, wm, wm, filterMode);
|
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),
|
fp = GrColorSpaceXformEffect::Make(std::move(fp),
|
||||||
producer->colorSpace(), producer->alphaType(),
|
producer->colorSpace(), producer->alphaType(),
|
||||||
rtc->colorInfo().colorSpace(), kPremul_SkAlphaType);
|
rtc->colorInfo().colorSpace(), kPremul_SkAlphaType);
|
||||||
|
@ -265,11 +265,12 @@ std::unique_ptr<GrFragmentProcessor> GrTextureEffect::MakeBilerpWithInset(
|
|||||||
GrSamplerState::WrapMode wx,
|
GrSamplerState::WrapMode wx,
|
||||||
GrSamplerState::WrapMode wy,
|
GrSamplerState::WrapMode wy,
|
||||||
const SkRect& subset,
|
const SkRect& subset,
|
||||||
|
const SkRect* domain,
|
||||||
SkVector inset,
|
SkVector inset,
|
||||||
const GrCaps& caps,
|
const GrCaps& caps,
|
||||||
const float border[4]) {
|
const float border[4]) {
|
||||||
GrSamplerState sampler(wx, wy, GrSamplerState::Filter::kBilerp);
|
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;
|
SkMatrix final;
|
||||||
bool lazyProxyNormalization;
|
bool lazyProxyNormalization;
|
||||||
get_matrix(matrix, view, &final, &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
|
* 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
|
* 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
|
* 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(
|
static std::unique_ptr<GrFragmentProcessor> MakeBilerpWithInset(
|
||||||
GrSurfaceProxyView,
|
GrSurfaceProxyView,
|
||||||
@ -83,6 +84,7 @@ public:
|
|||||||
GrSamplerState::WrapMode wx,
|
GrSamplerState::WrapMode wx,
|
||||||
GrSamplerState::WrapMode wy,
|
GrSamplerState::WrapMode wy,
|
||||||
const SkRect& subset,
|
const SkRect& subset,
|
||||||
|
const SkRect* domain,
|
||||||
SkVector inset,
|
SkVector inset,
|
||||||
const GrCaps& caps,
|
const GrCaps& caps,
|
||||||
const float border[4] = kDefaultBorder);
|
const float border[4] = kDefaultBorder);
|
||||||
|
@ -36,7 +36,8 @@ std::unique_ptr<GrFragmentProcessor> GrYUVtoRGBEffect::Make(GrSurfaceProxyView v
|
|||||||
GrSamplerState samplerState,
|
GrSamplerState samplerState,
|
||||||
const GrCaps& caps,
|
const GrCaps& caps,
|
||||||
const SkMatrix& localMatrix,
|
const SkMatrix& localMatrix,
|
||||||
const SkRect* subset) {
|
const SkRect* subset,
|
||||||
|
const SkRect* domain) {
|
||||||
int numPlanes;
|
int numPlanes;
|
||||||
SkAssertResult(SkYUVAIndex::AreValidIndices(yuvaIndices, &numPlanes));
|
SkAssertResult(SkYUVAIndex::AreValidIndices(yuvaIndices, &numPlanes));
|
||||||
|
|
||||||
@ -56,6 +57,7 @@ std::unique_ptr<GrFragmentProcessor> GrYUVtoRGBEffect::Make(GrSurfaceProxyView v
|
|||||||
SkISize dimensions = views[i].proxy()->dimensions();
|
SkISize dimensions = views[i].proxy()->dimensions();
|
||||||
SkTCopyOnFirstWrite<SkMatrix> planeMatrix(&SkMatrix::I());
|
SkTCopyOnFirstWrite<SkMatrix> planeMatrix(&SkMatrix::I());
|
||||||
SkRect planeSubset;
|
SkRect planeSubset;
|
||||||
|
SkRect planeDomain;
|
||||||
bool makeBilerpWithSnap = false;
|
bool makeBilerpWithSnap = false;
|
||||||
float sx = 1.f,
|
float sx = 1.f,
|
||||||
sy = 1.f;
|
sy = 1.f;
|
||||||
@ -73,6 +75,19 @@ std::unique_ptr<GrFragmentProcessor> GrYUVtoRGBEffect::Make(GrSurfaceProxyView v
|
|||||||
dimensions.height() == yDimensions.height() / 2 + 1) {
|
dimensions.height() == yDimensions.height() / 2 + 1) {
|
||||||
sy = 0.5f;
|
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
|
// 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
|
// 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.
|
// 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;
|
makeBilerpWithSnap = snapX || snapY;
|
||||||
snap[0] |= snapX;
|
snap[0] |= snapX;
|
||||||
snap[1] |= snapY;
|
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) {
|
if (subset) {
|
||||||
planeSubset = {subset->fLeft * sx,
|
planeSubset = *subset;
|
||||||
subset->fTop * sy,
|
}
|
||||||
subset->fRight * sx,
|
if (domain) {
|
||||||
subset->fBottom * sy};
|
planeDomain = *domain;
|
||||||
}
|
}
|
||||||
} else if (subset) {
|
|
||||||
planeSubset = *subset;
|
|
||||||
}
|
}
|
||||||
if (subset) {
|
if (subset) {
|
||||||
|
SkASSERT(samplerState.filter() != GrSamplerState::Filter::kMipMap);
|
||||||
if (makeBilerpWithSnap) {
|
if (makeBilerpWithSnap) {
|
||||||
// The plane is subsampled and we have an overall subset on the image. We're
|
// 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
|
// 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
|
// 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
|
// allows the bilerp sampling to read pixels from the plane that are just outside
|
||||||
// planeSubset.
|
// planeSubset.
|
||||||
|
SkRect* domainRect = domain ? &planeDomain : nullptr;
|
||||||
planeFPs[i] = GrTextureEffect::MakeBilerpWithInset(
|
planeFPs[i] = GrTextureEffect::MakeBilerpWithInset(
|
||||||
views[i], kUnknown_SkAlphaType, *planeMatrix, samplerState.wrapModeX(),
|
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]);
|
planeBorders[i]);
|
||||||
|
} else if (domain) {
|
||||||
|
planeFPs[i] = GrTextureEffect::MakeSubset(views[i], kUnknown_SkAlphaType,
|
||||||
|
*planeMatrix, samplerState, planeSubset,
|
||||||
|
planeDomain, caps, planeBorders[i]);
|
||||||
} else {
|
} else {
|
||||||
SkASSERT(samplerState.filter() != GrSamplerState::Filter::kMipMap);
|
SkASSERT(samplerState.filter() != GrSamplerState::Filter::kMipMap);
|
||||||
planeFPs[i] = GrTextureEffect::MakeSubset(views[i], kUnknown_SkAlphaType,
|
planeFPs[i] = GrTextureEffect::MakeSubset(views[i], kUnknown_SkAlphaType,
|
||||||
|
@ -21,7 +21,8 @@ public:
|
|||||||
GrSamplerState samplerState,
|
GrSamplerState samplerState,
|
||||||
const GrCaps&,
|
const GrCaps&,
|
||||||
const SkMatrix& localMatrix = SkMatrix::I(),
|
const SkMatrix& localMatrix = SkMatrix::I(),
|
||||||
const SkRect* subset = nullptr);
|
const SkRect* subset = nullptr,
|
||||||
|
const SkRect* domain = nullptr);
|
||||||
#ifdef SK_DEBUG
|
#ifdef SK_DEBUG
|
||||||
SkString dumpInfo() const override;
|
SkString dumpInfo() const override;
|
||||||
#endif
|
#endif
|
||||||
|
@ -302,20 +302,22 @@ std::unique_ptr<GrFragmentProcessor> SkImageShader::asFragmentProcessor(
|
|||||||
// quality setting. This completely ignores the complexity of the drawVertices case
|
// quality setting. This completely ignores the complexity of the drawVertices case
|
||||||
// where explicit local coords are provided by the caller.
|
// where explicit local coords are provided by the caller.
|
||||||
bool doBicubic;
|
bool doBicubic;
|
||||||
GrSamplerState::Filter textureFilterMode = GrSkFilterQualityToGrFilterMode(
|
GrSamplerState::Filter fm = 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);
|
||||||
const GrSamplerState::Filter* filterOrNull = doBicubic ? nullptr : &textureFilterMode;
|
std::unique_ptr<GrFragmentProcessor> fp;
|
||||||
auto fp = producer->createFragmentProcessor(lmInverse, SkRect::Make(fImage->dimensions()),
|
if (doBicubic) {
|
||||||
GrTextureProducer::kNo_FilterConstraint, false, wmX,
|
fp = producer->createBicubicFragmentProcessor(lmInverse, nullptr, nullptr, wmX, wmY);
|
||||||
wmY, filterOrNull);
|
} 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) {
|
if (!fp) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
fp = GrColorSpaceXformEffect::Make(std::move(fp), fImage->colorSpace(), producer->alphaType(),
|
|
||||||
args.fDstColorInfo->colorSpace(), kPremul_SkAlphaType);
|
|
||||||
bool isAlphaOnly = SkColorTypeIsAlphaOnly(fImage->colorType());
|
bool isAlphaOnly = SkColorTypeIsAlphaOnly(fImage->colorType());
|
||||||
if (isAlphaOnly) {
|
if (isAlphaOnly) {
|
||||||
return fp;
|
return fp;
|
||||||
|
Loading…
Reference in New Issue
Block a user