Revert "Move GrDomainEffect functionality into GrTextureEffect and delete"
This reverts commit 988af46dd203ec03d6bc3ac91bb6520dbb032ebf.
Reason for revert: <INSERT REASONING HERE>
Original change's description:
> Move GrDomainEffect functionality into GrTextureEffect and delete
> the former.
>
> New factories for GrTextureEffect have two main variants:
> MakeTexelSubset(): adjusts the input integer rectangle to account for
> filtering
>
> MakeSubset(): assumes caller has calculated the exact rectangle needed
> as floats.
>
> Currently this disables filtering for shader-based mirroring or repeat.
> Will fix this later. The old effect also did not support this.
>
> Change-Id: If47d8ecfbb349b0d7b39ab5ba864fe3cc1b139e4
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/265518
> Commit-Queue: Brian Salomon <bsalomon@google.com>
> Reviewed-by: Michael Ludwig <michaelludwig@google.com>
TBR=bsalomon@google.com,michaelludwig@google.com
Change-Id: Ib81a79798668cd7df7d07f72a5113be9fc74180c
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/266536
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
diff --git a/gm/texturedomaineffect.cpp b/gm/texturedomaineffect.cpp
index ee06e6b..5400492 100644
--- a/gm/texturedomaineffect.cpp
+++ b/gm/texturedomaineffect.cpp
@@ -25,6 +25,7 @@
#include "src/gpu/GrRenderTargetContextPriv.h"
#include "src/gpu/GrSamplerState.h"
#include "src/gpu/GrTextureProxy.h"
+#include "src/gpu/effects/GrTextureDomain.h"
#include "tools/gpu/TestOps.h"
#include <memory>
@@ -32,7 +33,7 @@
namespace skiagm {
/**
- * This GM directly exercises GrTextureEffect::MakeTexelSubset.
+ * This GM directly exercises GrDomainEffect.
*/
class TextureDomainEffect : public GpuGM {
public:
@@ -53,8 +54,8 @@
SkISize onISize() override {
const SkScalar canvasWidth =
- kDrawPad + 2 * ((kTargetWidth + 2 * kDrawPad) * GrSamplerState::kWrapModeCount +
- kTestPad * GrSamplerState::kWrapModeCount);
+ kDrawPad + 2 * ((kTargetWidth + 2 * kDrawPad) * GrTextureDomain::kModeCount +
+ kTestPad * GrTextureDomain::kModeCount);
return SkISize::Make(SkScalarCeilToInt(canvasWidth), 800);
}
@@ -116,23 +117,20 @@
for (int tm = 0; tm < textureMatrices.count(); ++tm) {
for (size_t d = 0; d < SK_ARRAY_COUNT(texelDomains); ++d) {
SkScalar x = kDrawPad + kTestPad;
- for (int m = 0; m < GrSamplerState::kWrapModeCount; ++m) {
- auto wm = static_cast<GrSamplerState::WrapMode>(m);
+ for (int m = 0; m < GrTextureDomain::kModeCount; ++m) {
+ GrTextureDomain::Mode mode = (GrTextureDomain::Mode) m;
if (fFilter != GrSamplerState::Filter::kNearest &&
- (wm == GrSamplerState::WrapMode::kRepeat ||
- wm == GrSamplerState::WrapMode::kMirrorRepeat)) {
+ (mode == GrTextureDomain::kRepeat_Mode ||
+ mode == GrTextureDomain::kMirrorRepeat_Mode)) {
// [Mirror] Repeat mode doesn't produce correct results with bilerp
// filtering
continue;
}
- GrSamplerState sampler(wm, fFilter);
- const auto& caps = *context->priv().caps();
- auto fp1 = GrTextureEffect::MakeTexelSubset(proxy,
- fBitmap.alphaType(),
- textureMatrices[tm],
- sampler,
- texelDomains[d],
- caps);
+ auto fp1 = GrTextureEffect::Make(proxy, fBitmap.alphaType(),
+ textureMatrices[tm], fFilter);
+ fp1 = GrDomainEffect::Make(
+ std::move(fp1), GrTextureDomain::MakeTexelDomain(texelDomains[d], mode),
+ mode, fFilter);
if (!fp1) {
continue;
}
@@ -147,7 +145,6 @@
// Draw again with a translated local rect and compensating translate matrix.
drawRect = localRect.makeOffset(x, y);
static constexpr SkVector kT = {-100, 300};
-
if (auto op = sk_gpu_test::test_ops::MakeRect(context,
std::move(fp2),
drawRect,
diff --git a/gm/yuvtorgbeffect.cpp b/gm/yuvtorgbeffect.cpp
index deb5cb7..37313bc 100644
--- a/gm/yuvtorgbeffect.cpp
+++ b/gm/yuvtorgbeffect.cpp
@@ -126,10 +126,11 @@
{ indices[i][2], SkColorChannel::kR },
{ -1, SkColorChannel::kA }
};
- const auto& caps = *context->priv().caps();
- std::unique_ptr<GrFragmentProcessor> fp(GrYUVtoRGBEffect::Make(
- proxies, yuvaIndices, static_cast<SkYUVColorSpace>(space),
- GrSamplerState::Filter::kNearest, caps));
+
+ std::unique_ptr<GrFragmentProcessor> fp(
+ GrYUVtoRGBEffect::Make(proxies, yuvaIndices,
+ static_cast<SkYUVColorSpace>(space),
+ GrSamplerState::Filter::kNearest));
if (fp) {
GrPaint grPaint;
grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
@@ -243,10 +244,9 @@
GrPaint grPaint;
grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
- const auto& caps = *context->priv().caps();
auto fp = GrYUVtoRGBEffect::Make(proxies, yuvaIndices,
static_cast<SkYUVColorSpace>(space),
- GrSamplerState::Filter::kNearest, caps);
+ GrSamplerState::Filter::kNearest);
if (fp) {
SkMatrix viewMatrix;
viewMatrix.setTranslate(x, y);
@@ -354,10 +354,8 @@
}
const SkRect* domainPtr = j > 0 ? &domain : nullptr;
- const auto& caps = *context->priv().caps();
- std::unique_ptr<GrFragmentProcessor> fp(
- GrYUVtoRGBEffect::Make(proxies, yuvaIndices, kJPEG_SkYUVColorSpace,
- kFilters[i], caps, SkMatrix::I(), domainPtr));
+ std::unique_ptr<GrFragmentProcessor> fp(GrYUVtoRGBEffect::Make(proxies, yuvaIndices,
+ kJPEG_SkYUVColorSpace, kFilters[i], SkMatrix::I(), domainPtr));
if (fp) {
GrPaint grPaint;
grPaint.addColorFragmentProcessor(std::move(fp));
diff --git a/src/core/SkBlurMF.cpp b/src/core/SkBlurMF.cpp
index 5102f9e..d6df230 100644
--- a/src/core/SkBlurMF.cpp
+++ b/src/core/SkBlurMF.cpp
@@ -28,6 +28,7 @@
#include "src/gpu/GrShaderCaps.h"
#include "src/gpu/GrStyle.h"
#include "src/gpu/GrTextureProxy.h"
+#include "src/gpu/effects/GrTextureDomain.h"
#include "src/gpu/effects/GrTextureEffect.h"
#include "src/gpu/effects/generated/GrCircleBlurFragmentProcessor.h"
#include "src/gpu/effects/generated/GrRRectBlurEffect.h"
diff --git a/src/core/SkGpuBlurUtils.cpp b/src/core/SkGpuBlurUtils.cpp
index f63f31e..514e85a 100644
--- a/src/core/SkGpuBlurUtils.cpp
+++ b/src/core/SkGpuBlurUtils.cpp
@@ -311,15 +311,17 @@
}
GrPaint paint;
- std::unique_ptr<GrFragmentProcessor> fp;
+ auto fp = GrTextureEffect::Make(std::move(srcProxy), srcAlphaType, SkMatrix::I(),
+ GrSamplerState::Filter::kBilerp);
if (i == 1) {
- GrSamplerState::WrapMode wrapMode;
+ // GrDomainEffect does not support kRepeat_Mode with GrSamplerState::Filter.
+ GrTextureDomain::Mode domainMode;
if (mode == SkTileMode::kClamp) {
- wrapMode = GrSamplerState::WrapMode::kClamp;
+ domainMode = GrTextureDomain::kClamp_Mode;
} else {
- // GrTextureEffect does not support WrapMode::k[Mirror]Repeat with
- // GrSamplerState::Filter::kBilerp. So we use kClampToBorder.
- wrapMode = GrSamplerState::WrapMode::kClampToBorder;
+ // GrDomainEffect does not support k[Mirror]Repeat with GrSamplerState::Filter.
+ // So we use decal.
+ domainMode = GrTextureDomain::kDecal_Mode;
}
SkRect domain = SkRect::Make(*contentRect);
domain.inset((i < scaleFactorX) ? SK_ScalarHalf + SK_ScalarNearlyZero : 0.0f,
@@ -331,14 +333,8 @@
if (domain.fBottom < domain.fTop) {
domain.fTop = domain.fBottom = SkScalarAve(domain.fTop, domain.fBottom);
}
- const auto& caps = *context->priv().caps();
- GrSamplerState sampler(wrapMode, GrSamplerState::Filter::kBilerp);
- fp = GrTextureEffect::MakeSubset(std::move(srcProxy), srcAlphaType, SkMatrix::I(),
- sampler, domain, caps);
+ fp = GrDomainEffect::Make(std::move(fp), domain, domainMode, true);
srcRect.offset(-srcOffset);
- } else {
- fp = GrTextureEffect::Make(std::move(srcProxy), srcAlphaType, SkMatrix::I(),
- GrSamplerState::Filter::kBilerp);
}
paint.addColorFragmentProcessor(std::move(fp));
paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
@@ -392,9 +388,11 @@
}
GrPaint paint;
- const auto& caps = *context->priv().caps();
- auto fp = GrTextureEffect::MakeTexelSubset(std::move(srcProxy), srcAlphaType, SkMatrix::I(),
- GrSamplerState::Filter::kBilerp, srcBounds, caps);
+ SkRect domain = GrTextureDomain::MakeTexelDomain(srcBounds, GrTextureDomain::kClamp_Mode,
+ GrTextureDomain::kClamp_Mode);
+ auto fp = GrTextureEffect::Make(std::move(srcProxy), srcAlphaType, SkMatrix::I(),
+ GrSamplerState::Filter::kBilerp);
+ fp = GrDomainEffect::Make(std::move(fp), domain, GrTextureDomain::kClamp_Mode, true);
paint.addColorFragmentProcessor(std::move(fp));
paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
GrFixedClip clip(SkIRect::MakeSize(dstSize));
diff --git a/src/core/SkGpuBlurUtils.h b/src/core/SkGpuBlurUtils.h
index 47bb9f0..53463e8 100644
--- a/src/core/SkGpuBlurUtils.h
+++ b/src/core/SkGpuBlurUtils.h
@@ -10,6 +10,7 @@
#if SK_SUPPORT_GPU
#include "src/gpu/GrRenderTargetContext.h"
+#include "src/gpu/effects/GrTextureDomain.h"
class GrContext;
class GrTexture;
diff --git a/src/effects/imagefilters/SkArithmeticImageFilter.cpp b/src/effects/imagefilters/SkArithmeticImageFilter.cpp
index ecca33e..8a08602 100644
--- a/src/effects/imagefilters/SkArithmeticImageFilter.cpp
+++ b/src/effects/imagefilters/SkArithmeticImageFilter.cpp
@@ -25,6 +25,7 @@
#include "src/gpu/GrTextureProxy.h"
#include "src/gpu/SkGr.h"
#include "src/gpu/effects/GrSkSLFP.h"
+#include "src/gpu/effects/GrTextureDomain.h"
#include "src/gpu/effects/generated/GrConstColorProcessor.h"
#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
@@ -347,17 +348,18 @@
GrPaint paint;
std::unique_ptr<GrFragmentProcessor> bgFP;
- const auto& caps = *ctx.getContext()->priv().caps();
- GrSamplerState sampler(GrSamplerState::WrapMode::kClampToBorder,
- GrSamplerState::Filter::kNearest);
if (backgroundProxy) {
SkIRect bgSubset = background->subset();
SkMatrix backgroundMatrix = SkMatrix::MakeTrans(
SkIntToScalar(bgSubset.left() - backgroundOffset.fX),
SkIntToScalar(bgSubset.top() - backgroundOffset.fY));
- bgFP = GrTextureEffect::MakeTexelSubset(std::move(backgroundProxy), background->alphaType(),
- backgroundMatrix, sampler, bgSubset, caps);
+ bgFP = GrTextureEffect::Make(std::move(backgroundProxy), background->alphaType(),
+ backgroundMatrix, GrSamplerState::Filter::kNearest);
+ bgFP = GrDomainEffect::Make(
+ std::move(bgFP),
+ GrTextureDomain::MakeTexelDomain(bgSubset, GrTextureDomain::kDecal_Mode),
+ GrTextureDomain::kDecal_Mode, false);
bgFP = GrColorSpaceXformEffect::Make(std::move(bgFP), background->getColorSpace(),
background->alphaType(),
ctx.colorSpace());
@@ -371,14 +373,18 @@
SkMatrix foregroundMatrix = SkMatrix::MakeTrans(
SkIntToScalar(fgSubset.left() - foregroundOffset.fX),
SkIntToScalar(fgSubset.top() - foregroundOffset.fY));
- auto fgFP = GrTextureEffect::MakeTexelSubset(std::move(foregroundProxy),
- foreground->alphaType(), foregroundMatrix,
- sampler, fgSubset, caps);
- fgFP = GrColorSpaceXformEffect::Make(std::move(fgFP),
- foreground->getColorSpace(),
- foreground->alphaType(),
- ctx.colorSpace());
- paint.addColorFragmentProcessor(std::move(fgFP));
+ auto foregroundFP =
+ GrTextureEffect::Make(std::move(foregroundProxy), foreground->alphaType(),
+ foregroundMatrix, GrSamplerState::Filter::kNearest);
+ foregroundFP = GrDomainEffect::Make(
+ std::move(foregroundFP),
+ GrTextureDomain::MakeTexelDomain(fgSubset, GrTextureDomain::kDecal_Mode),
+ GrTextureDomain::kDecal_Mode, false);
+ foregroundFP = GrColorSpaceXformEffect::Make(std::move(foregroundFP),
+ foreground->getColorSpace(),
+ foreground->alphaType(),
+ ctx.colorSpace());
+ paint.addColorFragmentProcessor(std::move(foregroundFP));
static auto effect = std::get<0>(SkRuntimeEffect::Make(SkString(SKSL_ARITHMETIC_SRC)));
ArithmeticFPInputs inputs;
diff --git a/src/effects/imagefilters/SkXfermodeImageFilter.cpp b/src/effects/imagefilters/SkXfermodeImageFilter.cpp
index 0a80ea2..8924456 100644
--- a/src/effects/imagefilters/SkXfermodeImageFilter.cpp
+++ b/src/effects/imagefilters/SkXfermodeImageFilter.cpp
@@ -22,7 +22,9 @@
#include "src/gpu/GrRecordingContextPriv.h"
#include "src/gpu/GrRenderTargetContext.h"
#include "src/gpu/GrTextureProxy.h"
+
#include "src/gpu/SkGr.h"
+#include "src/gpu/effects/GrTextureDomain.h"
#include "src/gpu/effects/GrTextureEffect.h"
#include "src/gpu/effects/generated/GrConstColorProcessor.h"
#endif
@@ -258,17 +260,18 @@
GrPaint paint;
std::unique_ptr<GrFragmentProcessor> bgFP;
- const auto& caps = *ctx.getContext()->priv().caps();
- GrSamplerState sampler(GrSamplerState::WrapMode::kClampToBorder,
- GrSamplerState::Filter::kNearest);
if (backgroundProxy) {
SkIRect bgSubset = background->subset();
SkMatrix bgMatrix = SkMatrix::MakeTrans(
SkIntToScalar(bgSubset.left() - backgroundOffset.fX),
SkIntToScalar(bgSubset.top() - backgroundOffset.fY));
- bgFP = GrTextureEffect::MakeTexelSubset(std::move(backgroundProxy), background->alphaType(),
- bgMatrix, sampler, bgSubset, caps);
+ bgFP = GrTextureEffect::Make(std::move(backgroundProxy), background->alphaType(), bgMatrix,
+ GrSamplerState::Filter::kNearest);
+ bgFP = GrDomainEffect::Make(
+ std::move(bgFP),
+ GrTextureDomain::MakeTexelDomain(bgSubset, GrTextureDomain::kDecal_Mode),
+ GrTextureDomain::kDecal_Mode, false);
bgFP = GrColorSpaceXformEffect::Make(std::move(bgFP), background->getColorSpace(),
background->alphaType(),
ctx.colorSpace());
@@ -282,14 +285,18 @@
SkMatrix fgMatrix = SkMatrix::MakeTrans(
SkIntToScalar(fgSubset.left() - foregroundOffset.fX),
SkIntToScalar(fgSubset.top() - foregroundOffset.fY));
- auto fgFP = GrTextureEffect::MakeTexelSubset(std::move(foregroundProxy),
- foreground->alphaType(), fgMatrix, sampler,
- fgSubset, caps);
- fgFP = GrColorSpaceXformEffect::Make(std::move(fgFP),
- foreground->getColorSpace(),
- foreground->alphaType(),
- ctx.colorSpace());
- paint.addColorFragmentProcessor(std::move(fgFP));
+ auto foregroundFP =
+ GrTextureEffect::Make(std::move(foregroundProxy), foreground->alphaType(), fgMatrix,
+ GrSamplerState::Filter::kNearest);
+ foregroundFP = GrDomainEffect::Make(
+ std::move(foregroundFP),
+ GrTextureDomain::MakeTexelDomain(fgSubset, GrTextureDomain::kDecal_Mode),
+ GrTextureDomain::kDecal_Mode, false);
+ foregroundFP = GrColorSpaceXformEffect::Make(std::move(foregroundFP),
+ foreground->getColorSpace(),
+ foreground->alphaType(),
+ ctx.colorSpace());
+ paint.addColorFragmentProcessor(std::move(foregroundFP));
std::unique_ptr<GrFragmentProcessor> xferFP = this->makeFGFrag(std::move(bgFP));
diff --git a/src/gpu/GrImageTextureMaker.cpp b/src/gpu/GrImageTextureMaker.cpp
index cc6f145..ead5dfe 100644
--- a/src/gpu/GrImageTextureMaker.cpp
+++ b/src/gpu/GrImageTextureMaker.cpp
@@ -8,7 +8,6 @@
#include "src/gpu/GrImageTextureMaker.h"
#include "src/gpu/GrColorSpaceXform.h"
-#include "src/gpu/GrContextPriv.h"
#include "src/gpu/GrRecordingContextPriv.h"
#include "src/gpu/SkGr.h"
#include "src/gpu/effects/GrYUVtoRGBEffect.h"
@@ -114,9 +113,8 @@
domain = &constraintRect;
}
- const auto& caps = *fImage->context()->priv().caps();
- auto fp = GrYUVtoRGBEffect::Make(fImage->fProxies, fImage->fYUVAIndices, fImage->fYUVColorSpace,
- filter, caps, textureMatrix, domain);
+ auto fp = GrYUVtoRGBEffect::Make(fImage->fProxies, fImage->fYUVAIndices,
+ fImage->fYUVColorSpace, filter, textureMatrix, domain);
if (fImage->fFromColorSpace) {
fp = GrColorSpaceXformEffect::Make(std::move(fp), fImage->fFromColorSpace.get(),
fImage->alphaType(), fImage->colorSpace());
diff --git a/src/gpu/GrProcessor.h b/src/gpu/GrProcessor.h
index f3ae030..fe6b12b 100644
--- a/src/gpu/GrProcessor.h
+++ b/src/gpu/GrProcessor.h
@@ -107,6 +107,7 @@
kGrDistanceFieldA8TextGeoProc_ClassID,
kGrDistanceFieldLCDTextGeoProc_ClassID,
kGrDistanceFieldPathGeoProc_ClassID,
+ kGrDomainEffect_ClassID,
kGrDualIntervalGradientColorizer_ClassID,
kGrEllipseEffect_ClassID,
kGrFillRRectOp_Processor_ClassID,
diff --git a/src/gpu/GrProcessorUnitTest.cpp b/src/gpu/GrProcessorUnitTest.cpp
index 21f282b..afd79ed 100644
--- a/src/gpu/GrProcessorUnitTest.cpp
+++ b/src/gpu/GrProcessorUnitTest.cpp
@@ -81,7 +81,7 @@
* we verify the count is as expected. If a new factory is added, then these numbers must be
* manually adjusted.
*/
-static const int kFPFactoryCount = 36;
+static const int kFPFactoryCount = 37;
static const int kGPFactoryCount = 14;
static const int kXPFactoryCount = 4;
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp
index b98386b..bab4d1db 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -45,6 +45,7 @@
#include "src/gpu/SkGr.h"
#include "src/gpu/effects/GrBicubicEffect.h"
#include "src/gpu/effects/GrRRectEffect.h"
+#include "src/gpu/effects/GrTextureDomain.h"
#include "src/gpu/effects/generated/GrColorMatrixFragmentProcessor.h"
#include "src/gpu/geometry/GrQuad.h"
#include "src/gpu/geometry/GrQuadUtils.h"
diff --git a/src/gpu/GrSamplerState.h b/src/gpu/GrSamplerState.h
index fc6b728..848c84c 100644
--- a/src/gpu/GrSamplerState.h
+++ b/src/gpu/GrSamplerState.h
@@ -27,9 +27,6 @@
constexpr GrSamplerState(WrapMode wrapXAndY, Filter filter)
: fWrapModes{wrapXAndY, wrapXAndY}, fFilter(filter) {}
- constexpr GrSamplerState(WrapMode wrapX, WrapMode wrapY, Filter filter)
- : fWrapModes{wrapX, wrapY}, fFilter(filter) {}
-
constexpr GrSamplerState(const WrapMode wrapModes[2], Filter filter)
: fWrapModes{wrapModes[0], wrapModes[1]}, fFilter(filter) {}
diff --git a/src/gpu/GrTextureProducer.cpp b/src/gpu/GrTextureProducer.cpp
index 243582d..46c6134 100644
--- a/src/gpu/GrTextureProducer.cpp
+++ b/src/gpu/GrTextureProducer.cpp
@@ -33,12 +33,15 @@
SkRect localRect = inputProxy->getBoundsRect();
+ bool needsDomain = false;
bool resizing = false;
if (copyParams.fFilter != GrSamplerState::Filter::kNearest) {
- resizing = localRect.width() != dstRect.width() || localRect.height() != dstRect.height();
+ bool resizing = localRect.width() != dstRect.width() ||
+ localRect.height() != dstRect.height();
+ needsDomain = resizing && inputProxy->isFunctionallyExact();
}
- if (copyParams.fFilter == GrSamplerState::Filter::kNearest && !resizing &&
+ if (copyParams.fFilter == GrSamplerState::Filter::kNearest && !needsDomain && !resizing &&
dstWillRequireMipMaps) {
sk_sp<GrTextureProxy> proxy = GrCopyBaseMipMapToTextureProxy(context, inputProxy.get(),
colorType);
@@ -54,13 +57,18 @@
return nullptr;
}
- const auto& caps = *context->priv().caps();
GrPaint paint;
- GrSamplerState sampler(GrSamplerState::WrapMode::kClamp, copyParams.fFilter);
- auto boundsRect = SkIRect::MakeSize(inputProxy->dimensions());
- auto fp = GrTextureEffect::MakeTexelSubset(std::move(inputProxy), kUnknown_SkAlphaType,
- SkMatrix::I(), sampler, boundsRect, localRect, caps);
+ auto fp = GrTextureEffect::Make(std::move(inputProxy), kUnknown_SkAlphaType, SkMatrix::I(),
+ copyParams.fFilter);
+ if (needsDomain) {
+ const SkRect domain = localRect.makeInset(0.5f, 0.5f);
+ // This would cause us to read values from outside the subset. Surely, the caller knows
+ // better!
+ SkASSERT(copyParams.fFilter != GrSamplerState::Filter::kMipMap);
+ fp = GrDomainEffect::Make(std::move(fp), domain, GrTextureDomain::kClamp_Mode,
+ copyParams.fFilter);
+ }
paint.addColorFragmentProcessor(std::move(fp));
paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
@@ -191,19 +199,21 @@
const SkRect& domain,
const GrSamplerState::Filter* filterOrNullForBicubic) {
SkASSERT(kTightCopy_DomainMode != domainMode);
- const auto& caps = *fContext->priv().caps();
+ bool clampToBorderSupport = fContext->priv().caps()->clampToBorderSupport();
SkAlphaType srcAlphaType = this->alphaType();
if (filterOrNullForBicubic) {
- GrSamplerState::WrapMode wrapMode = fDomainNeedsDecal
+ GrSamplerState::WrapMode wrapMode = fDomainNeedsDecal && clampToBorderSupport
? GrSamplerState::WrapMode::kClampToBorder
: GrSamplerState::WrapMode::kClamp;
GrSamplerState samplerState(wrapMode, *filterOrNullForBicubic);
- if (kNoDomain_DomainMode == domainMode) {
- return GrTextureEffect::Make(std::move(proxy), srcAlphaType, textureMatrix,
- samplerState, caps);
+ auto fp =
+ GrTextureEffect::Make(std::move(proxy), srcAlphaType, textureMatrix, samplerState);
+ if (kDomain_DomainMode == domainMode || (fDomainNeedsDecal && !clampToBorderSupport)) {
+ GrTextureDomain::Mode wrapMode = fDomainNeedsDecal ? GrTextureDomain::kDecal_Mode
+ : GrTextureDomain::kClamp_Mode;
+ return GrDomainEffect::Make(std::move(fp), domain, wrapMode, *filterOrNullForBicubic);
}
- return GrTextureEffect::MakeSubset(std::move(proxy), srcAlphaType, textureMatrix,
- samplerState, domain, caps);
+ return fp;
} else {
static const GrSamplerState::WrapMode kClampClamp[] = {
GrSamplerState::WrapMode::kClamp, GrSamplerState::WrapMode::kClamp};
@@ -211,7 +221,6 @@
GrSamplerState::WrapMode::kClampToBorder, GrSamplerState::WrapMode::kClampToBorder};
static constexpr auto kDir = GrBicubicEffect::Direction::kXY;
- bool clampToBorderSupport = caps.clampToBorderSupport();
if (kDomain_DomainMode == domainMode || (fDomainNeedsDecal && !clampToBorderSupport)) {
GrTextureDomain::Mode wrapMode = fDomainNeedsDecal ? GrTextureDomain::kDecal_Mode
: GrTextureDomain::kClamp_Mode;
diff --git a/src/gpu/GrYUVProvider.cpp b/src/gpu/GrYUVProvider.cpp
index 178554a..d974f2e 100644
--- a/src/gpu/GrYUVProvider.cpp
+++ b/src/gpu/GrYUVProvider.cpp
@@ -168,9 +168,8 @@
}
GrPaint paint;
- const auto& caps = *ctx->priv().caps();
auto yuvToRgbProcessor = GrYUVtoRGBEffect::Make(yuvTextureProxies, yuvaIndices, yuvColorSpace,
- GrSamplerState::Filter::kNearest, caps);
+ GrSamplerState::Filter::kNearest);
paint.addColorFragmentProcessor(std::move(yuvToRgbProcessor));
// If the caller expects the pixels in a different color space than the one from the image,
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index ba29ad7..6fa5173 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -43,6 +43,7 @@
#include "src/gpu/GrTracing.h"
#include "src/gpu/SkGr.h"
#include "src/gpu/effects/GrBicubicEffect.h"
+#include "src/gpu/effects/GrTextureDomain.h"
#include "src/gpu/geometry/GrShape.h"
#include "src/gpu/text/GrTextTarget.h"
#include "src/image/SkImage_Base.h"
@@ -935,7 +936,6 @@
// the rest from the SkPaint.
std::unique_ptr<GrFragmentProcessor> fp;
- const auto& caps = *this->caps();
if (needsTextureDomain && (SkCanvas::kStrict_SrcRectConstraint == constraint)) {
// Use a constrained texture domain to avoid color bleeding
SkRect domain;
@@ -955,8 +955,9 @@
static constexpr auto kDir = GrBicubicEffect::Direction::kXY;
fp = GrBicubicEffect::Make(std::move(proxy), texMatrix, domain, kDir, srcAlphaType);
} else {
- fp = GrTextureEffect::MakeSubset(std::move(proxy), srcAlphaType, texMatrix,
- samplerState, domain, caps);
+ fp = GrTextureEffect::Make(std::move(proxy), srcAlphaType, texMatrix, samplerState);
+ fp = GrDomainEffect::Make(std::move(fp), domain, GrTextureDomain::kClamp_Mode,
+ samplerState.filter());
}
} else if (bicubic) {
SkASSERT(GrSamplerState::Filter::kNearest == samplerState.filter());
@@ -964,7 +965,7 @@
static constexpr auto kDir = GrBicubicEffect::Direction::kXY;
fp = GrBicubicEffect::Make(std::move(proxy), texMatrix, wrapMode, kDir, srcAlphaType);
} else {
- fp = GrTextureEffect::Make(std::move(proxy), srcAlphaType, texMatrix, samplerState, caps);
+ fp = GrTextureEffect::Make(std::move(proxy), srcAlphaType, texMatrix, samplerState);
}
fp = GrColorSpaceXformEffect::Make(std::move(fp), bitmap.colorSpace(), bitmap.alphaType(),
diff --git a/src/gpu/effects/GrTextureDomain.cpp b/src/gpu/effects/GrTextureDomain.cpp
index cd15573..ad629c5 100644
--- a/src/gpu/effects/GrTextureDomain.cpp
+++ b/src/gpu/effects/GrTextureDomain.cpp
@@ -319,6 +319,191 @@
///////////////////////////////////////////////////////////////////////////////
+std::unique_ptr<GrFragmentProcessor> GrDomainEffect::Make(std::unique_ptr<GrFragmentProcessor> fp,
+ const SkRect& domain,
+ GrTextureDomain::Mode mode,
+ bool decalIsFiltered) {
+ return Make(std::move(fp), domain, mode, mode, decalIsFiltered);
+}
+
+std::unique_ptr<GrFragmentProcessor> GrDomainEffect::Make(std::unique_ptr<GrFragmentProcessor> fp,
+ const SkRect& domain,
+ GrTextureDomain::Mode modeX,
+ GrTextureDomain::Mode modeY,
+ bool decalIsFiltered) {
+ if (modeX == GrTextureDomain::kIgnore_Mode && modeY == GrTextureDomain::kIgnore_Mode) {
+ return fp;
+ }
+ int count = 0;
+ GrCoordTransform* coordTransform = nullptr;
+ for (auto [transform, ignored] : GrFragmentProcessor::FPCoordTransformRange(*fp)) {
+ ++count;
+ coordTransform = &transform;
+ }
+ // If there are no coord transforms on the passed FP or it's children then there's no need to
+ // enforce a domain.
+ // We have a limitation that only one coord transform is support when overriding local coords.
+ // If that limit were relaxed we would need to add a coord transform for each descendent FP
+ // transform and possibly have multiple domain rects to account for different proxy
+ // normalization and y-reversals.
+ if (count != 1) {
+ return fp;
+ }
+ GrCoordTransform transformCopy = *coordTransform;
+ // Reset the child FP's coord transform.
+ *coordTransform = {};
+ // If both domain modes happen to be ignore, it would be faster to just drop the domain logic
+ // entirely and return the original FP. We'd need a GrMatrixProcessor if the matrix is not
+ // identity, though.
+ return std::unique_ptr<GrFragmentProcessor>(new GrDomainEffect(
+ std::move(fp), transformCopy, domain, modeX, modeY, decalIsFiltered));
+}
+
+std::unique_ptr<GrFragmentProcessor> GrDomainEffect::Make(std::unique_ptr<GrFragmentProcessor> fp,
+ const SkRect& domain,
+ GrTextureDomain::Mode mode,
+ GrSamplerState::Filter filter) {
+ bool filterIfDecal = filter != GrSamplerState::Filter::kNearest;
+ return Make(std::move(fp), domain, mode, filterIfDecal);
+}
+
+std::unique_ptr<GrFragmentProcessor> GrDomainEffect::Make(std::unique_ptr<GrFragmentProcessor> fp,
+ const SkRect& domain,
+ GrTextureDomain::Mode modeX,
+ GrTextureDomain::Mode modeY,
+ GrSamplerState::Filter filter) {
+ bool filterIfDecal = filter != GrSamplerState::Filter::kNearest;
+ return Make(std::move(fp), domain, modeX, modeY, filterIfDecal);
+}
+GrFragmentProcessor::OptimizationFlags GrDomainEffect::Flags(GrFragmentProcessor* fp,
+ GrTextureDomain::Mode modeX,
+ GrTextureDomain::Mode modeY) {
+ auto fpFlags = GrFragmentProcessor::ProcessorOptimizationFlags(fp);
+ if (modeX == GrTextureDomain::kDecal_Mode || modeY == GrTextureDomain::kDecal_Mode) {
+ return fpFlags & ~kPreservesOpaqueInput_OptimizationFlag;
+ }
+ return fpFlags;
+}
+
+GrDomainEffect::GrDomainEffect(std::unique_ptr<GrFragmentProcessor> fp,
+ const GrCoordTransform& coordTransform,
+ const SkRect& domain,
+ GrTextureDomain::Mode modeX,
+ GrTextureDomain::Mode modeY,
+ bool decalIsFiltered)
+ : INHERITED(kGrDomainEffect_ClassID, Flags(fp.get(), modeX, modeY))
+ , fCoordTransform(coordTransform)
+ , fDomain(domain, modeX, modeY)
+ , fDecalIsFiltered(decalIsFiltered) {
+ SkASSERT(fp);
+ fp->setSampledWithExplicitCoords(true);
+ this->registerChildProcessor(std::move(fp));
+ this->addCoordTransform(&fCoordTransform);
+ if (fDomain.modeX() != GrTextureDomain::kDecal_Mode &&
+ fDomain.modeY() != GrTextureDomain::kDecal_Mode) {
+ // Canonicalize this don't care value so we don't have to worry about it elsewhere.
+ fDecalIsFiltered = false;
+ }
+}
+
+GrDomainEffect::GrDomainEffect(const GrDomainEffect& that)
+ : INHERITED(kGrDomainEffect_ClassID, that.optimizationFlags())
+ , fCoordTransform(that.fCoordTransform)
+ , fDomain(that.fDomain)
+ , fDecalIsFiltered(that.fDecalIsFiltered) {
+ auto child = that.childProcessor(0).clone();
+ child->setSampledWithExplicitCoords(true);
+ this->registerChildProcessor(std::move(child));
+ this->addCoordTransform(&fCoordTransform);
+}
+
+void GrDomainEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
+ GrProcessorKeyBuilder* b) const {
+ b->add32(GrTextureDomain::GLDomain::DomainKey(fDomain));
+}
+
+GrGLSLFragmentProcessor* GrDomainEffect::onCreateGLSLInstance() const {
+ class GLSLProcessor : public GrGLSLFragmentProcessor {
+ public:
+ void emitCode(EmitArgs& args) override {
+ const GrDomainEffect& de = args.fFp.cast<GrDomainEffect>();
+ const GrTextureDomain& domain = de.fDomain;
+
+ SkString coords2D =
+ args.fFragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint);
+
+ fGLDomain.sampleProcessor(domain, args.fInputColor, args.fOutputColor, coords2D, this,
+ args, 0);
+ }
+
+ protected:
+ void onSetData(const GrGLSLProgramDataManager& pdman,
+ const GrFragmentProcessor& fp) override {
+ const GrDomainEffect& de = fp.cast<GrDomainEffect>();
+ const GrTextureDomain& domain = de.fDomain;
+ // TODO: Update GrCoordTransform to return a view instead of proxy
+ const GrSurfaceProxy* proxy = de.fCoordTransform.proxy();
+ // If we don't have a proxy the value of the origin doesn't matter
+ GrSurfaceOrigin origin = proxy ? proxy->origin() : kTopLeft_GrSurfaceOrigin;
+ fGLDomain.setData(pdman, domain, proxy, origin, de.fDecalIsFiltered);
+ }
+
+ private:
+ GrTextureDomain::GLDomain fGLDomain;
+ };
+
+ return new GLSLProcessor;
+}
+
+bool GrDomainEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
+ auto& td = sBase.cast<GrDomainEffect>();
+ return fDomain == td.fDomain && fDecalIsFiltered == td.fDecalIsFiltered;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrDomainEffect);
+
+#if GR_TEST_UTILS
+std::unique_ptr<GrFragmentProcessor> GrDomainEffect::TestCreate(GrProcessorTestData* d) {
+ do {
+ GrTextureDomain::Mode modeX =
+ (GrTextureDomain::Mode)d->fRandom->nextULessThan(GrTextureDomain::kModeCount);
+ GrTextureDomain::Mode modeY =
+ (GrTextureDomain::Mode)d->fRandom->nextULessThan(GrTextureDomain::kModeCount);
+ auto child = GrProcessorUnitTest::MakeChildFP(d);
+ const auto* childPtr = child.get();
+ SkRect domain;
+ // We assert if the child's coord transform has a proxy and the domain rect is outside its
+ // bounds.
+ GrFragmentProcessor::CoordTransformIter ctIter(*child);
+ if (!ctIter) {
+ continue;
+ }
+ auto [transform, fp] = *ctIter;
+ if (auto proxy = transform.proxy()) {
+ auto [w, h] = proxy->backingStoreDimensions();
+ domain.fLeft = d->fRandom->nextRangeScalar(0, w);
+ domain.fRight = d->fRandom->nextRangeScalar(0, w);
+ domain.fTop = d->fRandom->nextRangeScalar(0, h);
+ domain.fBottom = d->fRandom->nextRangeScalar(0, h);
+ } else {
+ domain.fLeft = d->fRandom->nextRangeScalar(-100.f, 100.f);
+ domain.fRight = d->fRandom->nextRangeScalar(-100.f, 100.f);
+ domain.fTop = d->fRandom->nextRangeScalar(-100.f, 100.f);
+ domain.fBottom = d->fRandom->nextRangeScalar(-100.f, 100.f);
+ }
+ domain.sort();
+ bool filterIfDecal = d->fRandom->nextBool();
+ auto result = GrDomainEffect::Make(std::move(child), domain, modeX, modeY, filterIfDecal);
+ if (result && result.get() != childPtr) {
+ return result;
+ }
+ } while (true);
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
std::unique_ptr<GrFragmentProcessor> GrDeviceSpaceTextureDecalFragmentProcessor::Make(
sk_sp<GrSurfaceProxy> proxy, const SkIRect& subset, const SkIPoint& deviceSpaceOffset) {
return std::unique_ptr<GrFragmentProcessor>(new GrDeviceSpaceTextureDecalFragmentProcessor(
diff --git a/src/gpu/effects/GrTextureDomain.h b/src/gpu/effects/GrTextureDomain.h
index 70e6766..8e2a6e4 100644
--- a/src/gpu/effects/GrTextureDomain.h
+++ b/src/gpu/effects/GrTextureDomain.h
@@ -231,6 +231,85 @@
int fIndex;
};
+/**
+ * This effect applies a domain rectangle with an edge "mode" to the result of the child FP's coord
+ * transform. Currently the passed FP (including its descendants) must have exactly 1 coord
+ * transform (due to internal program builder restrictions). Also, it's important to note that the
+ * domain rectangle is applied AFTER the corod transform. This allows us to continue to lift the
+ * coord transform to the vertex shader. It might make this nicer for some use cases to add a
+ * pre-coord transform option and try to adjust the domain rect internally to convert to
+ * post-coord transform and keep everything in the vertex shader for simple use cases.
+ */
+class GrDomainEffect : public GrFragmentProcessor {
+public:
+ static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor>,
+ const SkRect& domain,
+ GrTextureDomain::Mode,
+ bool decalIsFiltered);
+
+ static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor>,
+ const SkRect& domain,
+ GrTextureDomain::Mode modeX,
+ GrTextureDomain::Mode modeY,
+ bool decalIsFiltered);
+
+ // These variants infer decalIsFiltered from the Filter mode (true if not kNearest).
+ static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor>,
+ const SkRect& domain,
+ GrTextureDomain::Mode,
+ GrSamplerState::Filter);
+
+ static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor>,
+ const SkRect& domain,
+ GrTextureDomain::Mode modeX,
+ GrTextureDomain::Mode modeY,
+ GrSamplerState::Filter);
+
+ const char* name() const override { return "Domain"; }
+
+ std::unique_ptr<GrFragmentProcessor> clone() const override {
+ return std::unique_ptr<GrFragmentProcessor>(new GrDomainEffect(*this));
+ }
+
+#ifdef SK_DEBUG
+ SkString dumpInfo() const override {
+ SkString str;
+ str.appendf("Domain: [L: %.2f, T: %.2f, R: %.2f, B: %.2f], filterDecal: %d",
+ fDomain.domain().fLeft, fDomain.domain().fTop, fDomain.domain().fRight,
+ fDomain.domain().fBottom, fDecalIsFiltered);
+ str.append(INHERITED::dumpInfo());
+ return str;
+ }
+#endif
+
+private:
+ GrFragmentProcessor::OptimizationFlags Flags(GrFragmentProcessor*, GrTextureDomain::Mode,
+ GrTextureDomain::Mode);
+
+ GrCoordTransform fCoordTransform;
+ GrTextureDomain fDomain;
+ bool fDecalIsFiltered;
+
+ GrDomainEffect(std::unique_ptr<GrFragmentProcessor>,
+ const GrCoordTransform& transform,
+ const SkRect& domain,
+ GrTextureDomain::Mode modeX,
+ GrTextureDomain::Mode modeY,
+ bool decalIsFiltered);
+
+ explicit GrDomainEffect(const GrDomainEffect&);
+
+ GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
+
+ void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
+
+ bool onIsEqual(const GrFragmentProcessor&) const override;
+
+ GR_DECLARE_FRAGMENT_PROCESSOR_TEST
+
+ typedef GrFragmentProcessor INHERITED;
+};
+
class GrDeviceSpaceTextureDecalFragmentProcessor : public GrFragmentProcessor {
public:
static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrSurfaceProxy>,
diff --git a/src/gpu/effects/GrTextureEffect.cpp b/src/gpu/effects/GrTextureEffect.cpp
index c8a52fb..e964a77 100644
--- a/src/gpu/effects/GrTextureEffect.cpp
+++ b/src/gpu/effects/GrTextureEffect.cpp
@@ -8,233 +8,24 @@
#include "src/gpu/effects/GrTextureEffect.h"
#include "include/gpu/GrTexture.h"
-#include "src/gpu/GrTexturePriv.h"
#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
#include "src/gpu/glsl/GrGLSLProgramBuilder.h"
#include "src/sksl/SkSLCPP.h"
#include "src/sksl/SkSLUtil.h"
-namespace {
-struct Span {
- float fA = 0.f, fB = 0.f;
-
- Span makeInset(float o) const {
- Span r = {fA + o, fB - o};
- if (r.fA > r.fB) {
- r.fA = r.fB = (r.fA + r.fB) / 2;
- }
- return r;
- }
-
- bool contains(Span r) const { return fA <= r.fA && fB >= r.fB; }
-};
-} // anonymous namespace
-
-GrTextureEffect::Sampling::Sampling(GrSamplerState sampler, SkISize size, const GrCaps& caps)
- : fHWSampler(sampler) {
- if (!caps.clampToBorderSupport()) {
- if (fHWSampler.wrapModeX() == GrSamplerState::WrapMode::kClampToBorder) {
- fHWSampler.setWrapModeX(GrSamplerState::WrapMode::kClamp);
- fShaderModes[0] = ShaderMode::kDecal;
- Span span{0, (float)size.width()};
- if (sampler.filter() != GrSamplerState::Filter::kNearest) {
- span = span.makeInset(0.5f);
- }
- fShaderSubset.fLeft = span.fA;
- fShaderSubset.fRight = span.fB;
- }
- if (fHWSampler.wrapModeY() == GrSamplerState::WrapMode::kClampToBorder) {
- fHWSampler.setWrapModeY(GrSamplerState::WrapMode::kClamp);
- fShaderModes[1] = ShaderMode::kDecal;
- Span span{0, (float)size.height()};
- if (sampler.filter() != GrSamplerState::Filter::kNearest) {
- span = span.makeInset(0.5f);
- }
- fShaderSubset.fTop = span.fA;
- fShaderSubset.fBottom = span.fB;
- }
- }
-}
-
-GrTextureEffect::Sampling::Sampling(const GrSurfaceProxy& proxy,
- GrSamplerState sampler,
- const SkRect& subset,
- bool adjustForFilter,
- const SkRect* domain,
- const GrCaps& caps) {
- using Mode = GrSamplerState::WrapMode;
- using Filter = GrSamplerState::Filter;
-
- struct Result1D {
- ShaderMode fShaderMode;
- Span fShaderSubset;
- Mode fHWMode;
- Filter fFilter;
- };
-
- auto resolve = [adjustForFilter, filter = sampler.filter(), &caps](int size, Mode mode,
- Span subset, Span domain) {
- float inset;
- Result1D r;
- r.fFilter = filter;
- bool canDoHW = mode != Mode::kClampToBorder || caps.clampToBorderSupport();
- if (canDoHW && size > 0 && subset.fA <= 0 && subset.fB >= size) {
- r.fShaderMode = ShaderMode::kNone;
- r.fHWMode = mode;
- return r;
- }
-
- inset = (adjustForFilter && filter != Filter::kNearest) ? 0.5 : 0;
- auto insetSubset = subset.makeInset(inset);
-
- if (canDoHW && insetSubset.contains(domain)) {
- r.fShaderMode = ShaderMode::kNone;
- r.fHWMode = mode;
- return r;
- }
-
- if (mode == Mode::kRepeat || mode == Mode::kMirrorRepeat) {
- r.fFilter = Filter::kNearest;
- r.fShaderSubset = subset;
- } else {
- r.fShaderSubset = insetSubset;
- }
- r.fShaderMode = static_cast<ShaderMode>(mode);
- r.fHWMode = Mode::kClamp;
- return r;
- };
-
- SkISize dim = proxy.isFullyLazy() ? SkISize{-1, -1} : proxy.backingStoreDimensions();
-
- Span subsetX{subset.fLeft, subset.fRight};
- auto domainX = domain ? Span{domain->fLeft, domain->fRight}
- : Span{SK_FloatNegativeInfinity, SK_FloatInfinity};
- auto x = resolve(dim.width(), sampler.wrapModeX(), subsetX, domainX);
-
- Span subsetY{subset.fTop, subset.fBottom};
- auto domainY = domain ? Span{domain->fTop, domain->fBottom}
- : Span{SK_FloatNegativeInfinity, SK_FloatInfinity};
- auto y = resolve(dim.height(), sampler.wrapModeY(), subsetY, domainY);
-
- fHWSampler = {x.fHWMode, y.fHWMode, std::min(x.fFilter, y.fFilter)};
- fShaderModes[0] = x.fShaderMode;
- fShaderModes[1] = y.fShaderMode;
- fShaderSubset = {x.fShaderSubset.fA, y.fShaderSubset.fA,
- x.fShaderSubset.fB, y.fShaderSubset.fB};
-}
-
-bool GrTextureEffect::Sampling::usesDecal() const {
- return fShaderModes[0] == ShaderMode::kDecal || fShaderModes[1] == ShaderMode::kDecal ||
- fHWSampler.wrapModeX() == GrSamplerState::WrapMode::kClampToBorder ||
- fHWSampler.wrapModeY() == GrSamplerState::WrapMode::kClampToBorder;
-}
-
std::unique_ptr<GrFragmentProcessor> GrTextureEffect::Make(sk_sp<GrSurfaceProxy> proxy,
SkAlphaType alphaType,
const SkMatrix& matrix,
- GrSamplerState::Filter filter) {
+ GrSamplerState sampler) {
return std::unique_ptr<GrFragmentProcessor>(
- new GrTextureEffect(std::move(proxy), alphaType, matrix, Sampling(filter)));
-}
-
-std::unique_ptr<GrFragmentProcessor> GrTextureEffect::Make(sk_sp<GrSurfaceProxy> proxy,
- SkAlphaType alphaType,
- const SkMatrix& matrix,
- GrSamplerState sampler,
- const GrCaps& caps) {
- Sampling sampling(sampler, proxy->dimensions(), caps);
- return std::unique_ptr<GrFragmentProcessor>(
- new GrTextureEffect(std::move(proxy), alphaType, matrix, sampling));
-}
-
-std::unique_ptr<GrFragmentProcessor> GrTextureEffect::MakeTexelSubset(sk_sp<GrSurfaceProxy> proxy,
- SkAlphaType alphaType,
- const SkMatrix& matrix,
- GrSamplerState sampler,
- const SkIRect& subset,
- const GrCaps& caps) {
- Sampling sampling(*proxy, sampler, SkRect::Make(subset), true, nullptr, caps);
- return std::unique_ptr<GrFragmentProcessor>(
- new GrTextureEffect(std::move(proxy), alphaType, matrix, sampling));
-}
-
-std::unique_ptr<GrFragmentProcessor> GrTextureEffect::MakeTexelSubset(sk_sp<GrSurfaceProxy> proxy,
- SkAlphaType alphaType,
- const SkMatrix& matrix,
- GrSamplerState sampler,
- const SkIRect& subset,
- const SkRect& domain,
- const GrCaps& caps) {
- Sampling sampling(*proxy, sampler, SkRect::Make(subset), true, &domain, caps);
- return std::unique_ptr<GrFragmentProcessor>(
- new GrTextureEffect(std::move(proxy), alphaType, matrix, sampling));
-}
-
-std::unique_ptr<GrFragmentProcessor> GrTextureEffect::MakeSubset(sk_sp<GrSurfaceProxy> proxy,
- SkAlphaType alphaType,
- const SkMatrix& matrix,
- GrSamplerState sampler,
- const SkRect& subset,
- const GrCaps& caps) {
- Sampling sampling(*proxy, sampler, subset, false, nullptr, caps);
- return std::unique_ptr<GrFragmentProcessor>(
- new GrTextureEffect(std::move(proxy), alphaType, matrix, sampling));
-}
-
-std::unique_ptr<GrFragmentProcessor> GrTextureEffect::MakeSubset(sk_sp<GrSurfaceProxy> proxy,
- SkAlphaType alphaType,
- const SkMatrix& matrix,
- GrSamplerState sampler,
- const SkRect& subset,
- const SkRect& domain,
- const GrCaps& caps) {
- Sampling sampling(*proxy, sampler, subset, false, &domain, caps);
- return std::unique_ptr<GrFragmentProcessor>(
- new GrTextureEffect(std::move(proxy), alphaType, matrix, sampling));
+ new GrTextureEffect(std::move(proxy), alphaType, matrix, sampler));
}
GrGLSLFragmentProcessor* GrTextureEffect::onCreateGLSLInstance() const {
class Impl : public GrGLSLFragmentProcessor {
- UniformHandle fSubsetUni;
- UniformHandle fDecalUni;
-
public:
void emitCode(EmitArgs& args) override {
- auto appendWrap = [](GrGLSLShaderBuilder* builder, ShaderMode mode, const char* inCoord,
- const char* domainStart, const char* domainEnd, bool is2D,
- const char* out) {
- switch (mode) {
- case ShaderMode::kNone:
- builder->codeAppendf("%s = %s;\n", out, inCoord);
- break;
- case ShaderMode::kDecal:
- // The lookup coordinate to use for decal will be clamped just like
- // kClamp_Mode, it's just that the post-processing will be different, so
- // fall through
- case ShaderMode::kClamp:
- builder->codeAppendf("%s = clamp(%s, %s, %s);", out, inCoord, domainStart,
- domainEnd);
- break;
- case ShaderMode::kRepeat:
- builder->codeAppendf("%s = mod(%s - %s, %s - %s) + %s;", out, inCoord,
- domainStart, domainEnd, domainStart, domainStart);
- break;
- case ShaderMode::kMirrorRepeat: {
- const char* type = is2D ? "float2" : "float";
- builder->codeAppend("{");
- builder->codeAppendf("%s w = %s - %s;", type, domainEnd, domainStart);
- builder->codeAppendf("%s w2 = 2 * w;", type);
- builder->codeAppendf("%s m = mod(%s - %s, w2);", type, inCoord,
- domainStart);
- builder->codeAppendf("%s = mix(m, w2 - m, step(w, m)) + %s;", out,
- domainStart);
- builder->codeAppend("}");
- break;
- }
- }
- };
- auto te = args.fFp.cast<GrTextureEffect>();
const char* coords;
if (args.fFp.coordTransformsApplyToLocalCoords()) {
coords = args.fTransformedCoords[0].fVaryingPoint.c_str();
@@ -242,165 +33,30 @@
coords = "_coords";
}
auto* fb = args.fFragBuilder;
- if (te.fShaderModes[0] == ShaderMode::kNone &&
- te.fShaderModes[1] == ShaderMode::kNone) {
- fb->codeAppendf("%s = ", args.fOutputColor);
- fb->appendTextureLookupAndBlend(args.fInputColor, SkBlendMode::kModulate,
- args.fTexSamplers[0], coords);
- fb->codeAppendf(";");
- } else {
- const char* subsetName;
- SkString uniName("TexDom");
- fSubsetUni = args.fUniformHandler->addUniform(
- kFragment_GrShaderFlag, kHalf4_GrSLType, "subset", &subsetName);
-
- // Always use a local variable for the input coordinates; often callers pass in an
- // expression and we want to cache it across all of its references in the code below
- auto inCoords = fb->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint);
- fb->codeAppend("float2 clampedCoord;");
- SkString start;
- SkString end;
- if (te.fShaderModes[0] == te.fShaderModes[1]) {
- // Doing the domain setup using vectors seems to avoid shader compilation issues
- // on Chromecast, possibly due to reducing shader length.
- start.printf("%s.xy", subsetName);
- end.printf("%s.zw", subsetName);
- appendWrap(fb, te.fShaderModes[0], inCoords.c_str(), start.c_str(), end.c_str(),
- true, "clampedCoord");
- } else {
- SkString origX, origY;
- // Apply x mode to the x coordinate using the left and right edges of the domain
- // rect (stored as the x and z components of the domain uniform).
- start.printf("%s.x", subsetName);
- end.printf("%s.z", subsetName);
- origX.printf("%s.x", inCoords.c_str());
- appendWrap(fb, te.fShaderModes[0], origX.c_str(), start.c_str(), end.c_str(),
- false, "clampedCoord.x");
- // Repeat the same logic for y.
- start.printf("%s.y", subsetName);
- end.printf("%s.w", subsetName);
- origY.printf("%s.y", inCoords.c_str());
- appendWrap(fb, te.fShaderModes[1], origY.c_str(), start.c_str(), end.c_str(),
- false, "clampedCoord.y");
- }
- SkString textureLookup;
- fb->appendTextureLookup(&textureLookup, args.fTexSamplers[0], "clampedCoord");
- fb->codeAppendf("half4 textureColor = %s;", textureLookup.c_str());
-
- // Apply decal mode's transparency interpolation if needed
- bool decalX = te.fShaderModes[0] == ShaderMode::kDecal;
- bool decalY = te.fShaderModes[1] == ShaderMode::kDecal;
- if (decalX || decalY) {
- const char* decalName;
- // Half3 since this will hold texture width, height, and then a step function
- // control param
- fDecalUni = args.fUniformHandler->addUniform(
- kFragment_GrShaderFlag, kHalf3_GrSLType, uniName.c_str(), &decalName);
- // The decal err is the max absolute value between the clamped coordinate and
- // the original pixel coordinate. This will then be clamped to 1.f if it's
- // greater than the control parameter, which simulates kNearest and kBilerp
- // behavior depending on if it's 0 or 1.
- if (decalX && decalY) {
- fb->codeAppendf(
- "half err = max(half(abs(clampedCoord.x - %s.x) * %s.x), "
- " half(abs(clampedCoord.y - %s.y) * %s.y));",
- inCoords.c_str(), decalName, inCoords.c_str(), decalName);
- } else if (decalX) {
- fb->codeAppendf("half err = half(abs(clampedCoord.x - %s.x) * %s.x);",
- inCoords.c_str(), decalName);
- } else {
- SkASSERT(decalY);
- fb->codeAppendf("half err = half(abs(clampedCoord.y - %s.y) * %s.y);",
- inCoords.c_str(), decalName);
- }
-
- // Apply a transform to the error rate, which let's us simulate nearest or
- // bilerp filtering in the same shader. When the texture is nearest filtered,
- // fSizeName.z is set to 0 so this becomes a step function centered at the
- // clamped coordinate. When bilerp, fSizeName.z is set to 1 and it becomes
- // a simple linear blend between texture and transparent.
- fb->codeAppendf(
- "if (err > %s.z) { err = 1.0; } else if (%s.z < 1) { err = 0.0; }",
- decalName, decalName);
- fb->codeAppend("textureColor = mix(textureColor, half4(0), err);");
- }
- fb->codeAppendf("%s = textureColor * %s;", args.fOutputColor, args.fInputColor);
- }
- }
-
- protected:
- void onSetData(const GrGLSLProgramDataManager& pdm,
- const GrFragmentProcessor& fp) override {
- const auto& te = fp.cast<GrTextureEffect>();
- if (fSubsetUni.isValid()) {
- const float w = te.fSampler.peekTexture()->width();
- const float h = te.fSampler.peekTexture()->height();
-
- const auto& s = te.fSubset;
- float rect[] = {s.fLeft, s.fTop, s.fRight, s.fBottom};
- float decalW[3];
-
- if (te.fSampler.view().origin() == kBottomLeft_GrSurfaceOrigin) {
- rect[1] = h - rect[1];
- rect[3] = h - rect[3];
- std::swap(rect[1], rect[3]);
- }
-
- if (te.fSampler.peekTexture()->texturePriv().textureType() !=
- GrTextureType::kRectangle) {
- float iw = 1.f / w;
- float ih = 1.f / h;
- rect[0] *= iw;
- rect[2] *= iw;
- rect[1] *= ih;
- rect[3] *= ih;
- decalW[0] = w;
- decalW[1] = h;
- } else {
- decalW[0] = 1;
- decalW[1] = 1;
- }
- pdm.set4fv(fSubsetUni, 1, rect);
-
- if (fDecalUni.isValid()) {
- bool filter = te.textureSampler(0).samplerState().filter() !=
- GrSamplerState::Filter::kNearest;
- decalW[2] = filter ? 1.f : 0.f;
- pdm.set3fv(fDecalUni, 1, decalW);
- }
- }
+ fb->codeAppendf("%s = ", args.fOutputColor);
+ fb->appendTextureLookupAndBlend(args.fInputColor, SkBlendMode::kModulate,
+ args.fTexSamplers[0], coords);
+ fb->codeAppendf(";");
}
};
return new Impl;
}
-void GrTextureEffect::onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const {
- bool shaderFilter = (fShaderModes[0] == ShaderMode::kDecal ||
- fShaderModes[1] == ShaderMode::kDecal) &&
- fSampler.samplerState().filter() != GrSamplerState::Filter::kNearest;
- auto m0 = static_cast<uint32_t>(fShaderModes[0]);
- auto m1 = static_cast<uint32_t>(fShaderModes[1]);
- b->add32(shaderFilter << 31 | (m0 << 16) | m1);
-}
+void GrTextureEffect::onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const {}
-bool GrTextureEffect::onIsEqual(const GrFragmentProcessor& other) const {
- auto that = other.cast<GrTextureEffect>();
- return fShaderModes[0] == that.fShaderModes[1] && fShaderModes[1] == that.fShaderModes[1] &&
- fSubset == that.fSubset;
+bool GrTextureEffect::onIsEqual(const GrFragmentProcessor&) const { return true; }
+
+static inline bool uses_border(const GrSamplerState s) {
+ return s.wrapModeX() == GrSamplerState::WrapMode::kClampToBorder ||
+ s.wrapModeY() == GrSamplerState::WrapMode::kClampToBorder;
}
GrTextureEffect::GrTextureEffect(sk_sp<GrSurfaceProxy> texture, SkAlphaType alphaType,
- const SkMatrix& matrix, const Sampling& sampling)
+ const SkMatrix& matrix, GrSamplerState sampler)
: GrFragmentProcessor(kGrTextureEffect_ClassID,
- ModulateForSamplerOptFlags(alphaType, sampling.usesDecal()))
+ ModulateForSamplerOptFlags(alphaType, uses_border(sampler)))
, fCoordTransform(matrix, texture.get())
- , fSampler(std::move(texture), sampling.fHWSampler)
- , fSubset(sampling.fShaderSubset)
- , fShaderModes{sampling.fShaderModes[0], sampling.fShaderModes[1]} {
- // We always compare the range even when it isn't used so assert we have canonical don't care
- // values.
- SkASSERT(fShaderModes[0] != ShaderMode::kNone || (fSubset.fLeft == 0 && fSubset.fRight == 0));
- SkASSERT(fShaderModes[1] != ShaderMode::kNone || (fSubset.fTop == 0 && fSubset.fBottom == 0));
+ , fSampler(std::move(texture), sampler) {
this->setTextureSamplerCnt(1);
this->addCoordTransform(&fCoordTransform);
}
@@ -408,9 +64,7 @@
GrTextureEffect::GrTextureEffect(const GrTextureEffect& src)
: INHERITED(kGrTextureEffect_ClassID, src.optimizationFlags())
, fCoordTransform(src.fCoordTransform)
- , fSampler(src.fSampler)
- , fSubset(src.fSubset)
- , fShaderModes{src.fShaderModes[0], src.fShaderModes[1]} {
+ , fSampler(src.fSampler) {
this->setTextureSamplerCnt(1);
this->addCoordTransform(&fCoordTransform);
}
@@ -441,6 +95,6 @@
: GrSamplerState::Filter::kNearest);
const SkMatrix& matrix = GrTest::TestMatrix(testData->fRandom);
- return GrTextureEffect::Make(std::move(proxy), at, matrix, params, *testData->caps());
+ return GrTextureEffect::Make(std::move(proxy), at, matrix, params);
}
#endif
diff --git a/src/gpu/effects/GrTextureEffect.h b/src/gpu/effects/GrTextureEffect.h
index 9e62a48..c6fc305 100644
--- a/src/gpu/effects/GrTextureEffect.h
+++ b/src/gpu/effects/GrTextureEffect.h
@@ -15,117 +15,23 @@
class GrTextureEffect : public GrFragmentProcessor {
public:
- /** Make from a filter. The sampler will be configured with clamp mode. */
- static std::unique_ptr<GrFragmentProcessor> Make(
- sk_sp<GrSurfaceProxy>,
- SkAlphaType,
- const SkMatrix& = SkMatrix::I(),
- GrSamplerState::Filter = GrSamplerState::Filter::kNearest);
-
- /**
- * Make from a full GrSamplerState. Caps are required to determine support for kClampToBorder.
- * This will be emulated in the shader if there is no hardware support.
- */
static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrSurfaceProxy>,
SkAlphaType,
- const SkMatrix&,
- GrSamplerState,
- const GrCaps& caps);
-
- /**
- * Makes a texture effect that samples a subset of a texture. The wrap modes of the
- * GrSampleState are applied to the subset in the shader rather than using HW samplers.
- * The 'subset' parameter specifies the texels in the base level. The shader code will
- * avoid allowing bilerp filtering to read outside the texel window. However, if MIP
- * filtering is used and a shader invocation reads from a level other than the base
- * then it may read texel values that were computed from in part from base level texels
- * outside the window. More specifically, we treat the MIP map case exactly like the
- * bilerp case in terms of how the final texture coords are computed.
- */
- static std::unique_ptr<GrFragmentProcessor> MakeTexelSubset(sk_sp<GrSurfaceProxy>,
- SkAlphaType,
- const SkMatrix&,
- GrSamplerState,
- const SkIRect& subset,
- const GrCaps& caps);
- /**
- * The same as above but also takes a 'domain' that specifies any known limit on the post-
- * matrix texture coords that will be used to sample the texture. Specifying this requires
- * knowledge of how this effect will be nested into a paint, the local coords used with the
- * draw, etc. It is only used to attempt to optimize away the shader subset calculations.
- */
- static std::unique_ptr<GrFragmentProcessor> MakeTexelSubset(sk_sp<GrSurfaceProxy>,
- SkAlphaType,
- const SkMatrix&,
- GrSamplerState,
- const SkIRect& subset,
- const SkRect& domain,
- const GrCaps& caps);
-
- /**
- * This is similar to MakeTexelSubset but takes a float rather than integer subset rect.
- * No adjustment is done for filtering, the texture coordinates are limited to the
- * unmodified subset. The subset should be unnormalized. The effect will apply texture
- * coordinate normalization after subset restriction (logically).
- */
- static std::unique_ptr<GrFragmentProcessor> MakeSubset(sk_sp<GrSurfaceProxy>,
- SkAlphaType,
- const SkMatrix&,
- GrSamplerState,
- const SkRect& subset,
- const GrCaps& caps);
-
- /**
- * The same as above but also takes a 'domain' that specifies any known limit on the post-
- * matrix texture coords that will be used to sample the texture. Specifying this requires
- * knowledge of how this effect will be nested into a paint, the local coords used with the
- * draw, etc. It is only used to attempt to optimize away the shader subset calculations.
- */
- static std::unique_ptr<GrFragmentProcessor> MakeSubset(sk_sp<GrSurfaceProxy>,
- SkAlphaType,
- const SkMatrix&,
- GrSamplerState,
- const SkRect& subset,
- const SkRect& domain,
- const GrCaps& caps);
+ const SkMatrix& = SkMatrix::I(),
+ GrSamplerState = {});
std::unique_ptr<GrFragmentProcessor> clone() const override;
- const char* name() const override { return "TextureEffect"; }
+ const char* name() const override { return "SimpleTextureEffect"; }
private:
- enum class ShaderMode : uint16_t {
- kClamp = static_cast<int>(GrSamplerState::WrapMode::kClamp),
- kRepeat = static_cast<int>(GrSamplerState::WrapMode::kRepeat),
- kMirrorRepeat = static_cast<int>(GrSamplerState::WrapMode::kMirrorRepeat),
- kDecal = static_cast<int>(GrSamplerState::WrapMode::kClampToBorder),
- kNone,
- };
-
- struct Sampling {
- GrSamplerState fHWSampler;
- ShaderMode fShaderModes[2] = {ShaderMode::kNone, ShaderMode::kNone};
- SkRect fShaderSubset = {0, 0, 0, 0};
- Sampling(GrSamplerState::Filter filter) : fHWSampler(filter) {}
- Sampling(GrSamplerState, SkISize, const GrCaps&);
- Sampling(const GrSurfaceProxy& proxy,
- GrSamplerState sampler,
- const SkRect&,
- bool,
- const SkRect*,
- const GrCaps&);
- inline bool usesDecal() const;
- };
-
GrCoordTransform fCoordTransform;
TextureSampler fSampler;
- SkRect fSubset;
- ShaderMode fShaderModes[2];
-
- inline GrTextureEffect(sk_sp<GrSurfaceProxy>, SkAlphaType, const SkMatrix&, const Sampling&);
GrTextureEffect(const GrTextureEffect& src);
+ inline GrTextureEffect(sk_sp<GrSurfaceProxy>, SkAlphaType, const SkMatrix&, GrSamplerState);
+
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
diff --git a/src/gpu/effects/GrYUVtoRGBEffect.cpp b/src/gpu/effects/GrYUVtoRGBEffect.cpp
index a85b810..987db7e 100644
--- a/src/gpu/effects/GrYUVtoRGBEffect.cpp
+++ b/src/gpu/effects/GrYUVtoRGBEffect.cpp
@@ -19,7 +19,6 @@
const SkYUVAIndex yuvaIndices[4],
SkYUVColorSpace yuvColorSpace,
GrSamplerState::Filter filterMode,
- const GrCaps& caps,
const SkMatrix& localMatrix,
const SkRect* domain) {
int numPlanes;
@@ -64,18 +63,16 @@
} else if (domain) {
planeDomain = *domain;
}
-
+ planeFPs[i] =
+ GrTextureEffect::Make(proxies[i], kUnknown_SkAlphaType, *planeMatrix, planeFilter);
if (domain) {
SkASSERT(planeFilter != GrSamplerState::Filter::kMipMap);
if (planeFilter != GrSamplerState::Filter::kNearest) {
// Inset by half a pixel for bilerp, after scaling to the size of the plane
planeDomain.inset(0.5f, 0.5f);
}
- planeFPs[i] = GrTextureEffect::MakeSubset(proxies[i], kUnknown_SkAlphaType,
- *planeMatrix, planeFilter, planeDomain, caps);
- } else {
- planeFPs[i] = GrTextureEffect::Make(proxies[i], kUnknown_SkAlphaType, *planeMatrix,
- planeFilter);
+ planeFPs[i] = GrDomainEffect::Make(std::move(planeFPs[i]), planeDomain,
+ GrTextureDomain::kClamp_Mode, false);
}
}
@@ -190,6 +187,7 @@
UniformHandle fColorSpaceMatrixVar;
UniformHandle fColorSpaceTranslateVar;
+ GrTextureDomain::GLDomain fGLDomains[4];
};
return new GrGLSLYUVtoRGBEffect;
diff --git a/src/gpu/effects/GrYUVtoRGBEffect.h b/src/gpu/effects/GrYUVtoRGBEffect.h
index 6ed3b63..b99de32 100644
--- a/src/gpu/effects/GrYUVtoRGBEffect.h
+++ b/src/gpu/effects/GrYUVtoRGBEffect.h
@@ -10,9 +10,11 @@
#include "include/core/SkTypes.h"
-#include "include/core/SkYUVAIndex.h"
#include "src/gpu/GrCoordTransform.h"
#include "src/gpu/GrFragmentProcessor.h"
+#include "src/gpu/effects/GrTextureDomain.h"
+
+#include "include/core/SkYUVAIndex.h"
class GrYUVtoRGBEffect : public GrFragmentProcessor {
public:
@@ -24,7 +26,6 @@
const SkYUVAIndex indices[4],
SkYUVColorSpace yuvColorSpace,
GrSamplerState::Filter filterMode,
- const GrCaps&,
const SkMatrix& localMatrix = SkMatrix::I(),
const SkRect* domain = nullptr);
#ifdef SK_DEBUG
diff --git a/src/gpu/ops/GrTextureOp.cpp b/src/gpu/ops/GrTextureOp.cpp
index 2eb257c..3b7fafc 100644
--- a/src/gpu/ops/GrTextureOp.cpp
+++ b/src/gpu/ops/GrTextureOp.cpp
@@ -30,6 +30,7 @@
#include "src/gpu/GrTexturePriv.h"
#include "src/gpu/GrTextureProxy.h"
#include "src/gpu/SkGr.h"
+#include "src/gpu/effects/GrTextureDomain.h"
#include "src/gpu/effects/generated/GrClampFragmentProcessor.h"
#include "src/gpu/geometry/GrQuad.h"
#include "src/gpu/geometry/GrQuadBuffer.h"
@@ -1071,21 +1072,13 @@
GrSurfaceProxy* proxy = proxyView.proxy();
std::unique_ptr<GrFragmentProcessor> fp;
+ fp = GrTextureEffect::Make(sk_ref_sp(proxy), alphaType, SkMatrix::I(), filter);
if (domain) {
// Update domain to match what GrTextureOp would do for bilerp, but don't do any
- // normalization since GrTextureEffect handles that and the origin.
+ // normalization since GrTextureDomainEffect handles that and the origin.
SkRect correctedDomain = normalize_domain(filter, {1.f, 1.f, 0.f}, domain);
- const auto& caps = *context->priv().caps();
- SkRect localRect;
- if (localQuad.asRect(&localRect)) {
- fp = GrTextureEffect::MakeSubset(sk_ref_sp(proxy), alphaType, SkMatrix::I(), filter,
- correctedDomain, localRect, caps);
- } else {
- fp = GrTextureEffect::MakeSubset(sk_ref_sp(proxy), alphaType, SkMatrix::I(), filter,
- correctedDomain, caps);
- }
- } else {
- fp = GrTextureEffect::Make(sk_ref_sp(proxy), alphaType, SkMatrix::I(), filter);
+ fp = GrDomainEffect::Make(std::move(fp), correctedDomain, GrTextureDomain::kClamp_Mode,
+ filter);
}
fp = GrColorSpaceXformEffect::Make(std::move(fp), std::move(textureXform));
paint.addColorFragmentProcessor(std::move(fp));
diff --git a/src/image/SkImage_GpuBase.cpp b/src/image/SkImage_GpuBase.cpp
index 6a21b93..44a0275 100644
--- a/src/image/SkImage_GpuBase.cpp
+++ b/src/image/SkImage_GpuBase.cpp
@@ -348,9 +348,8 @@
GrPaint paint;
paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
- const auto& caps = *ctx->priv().caps();
auto fp = GrYUVtoRGBEffect::Make(proxies, yuvaIndices, yuvColorSpace,
- GrSamplerState::Filter::kNearest, caps);
+ GrSamplerState::Filter::kNearest);
if (colorSpaceXform) {
fp = GrColorSpaceXformEffect::Make(std::move(fp), std::move(colorSpaceXform));
}
diff --git a/src/shaders/SkImageShader.cpp b/src/shaders/SkImageShader.cpp
index 2e3bba5..a88c349 100755
--- a/src/shaders/SkImageShader.cpp
+++ b/src/shaders/SkImageShader.cpp
@@ -204,6 +204,22 @@
GrSamplerState::WrapMode wrapModes[] = {tile_mode_to_wrap_mode(fTileModeX),
tile_mode_to_wrap_mode(fTileModeY)};
+ // If either domainX or domainY are un-ignored, a texture domain effect has to be used to
+ // implement the decal mode (while leaving non-decal axes alone). The wrap mode originally
+ // clamp-to-border is reset to clamp since the hw cannot implement it directly.
+ GrTextureDomain::Mode domainX = GrTextureDomain::kIgnore_Mode;
+ GrTextureDomain::Mode domainY = GrTextureDomain::kIgnore_Mode;
+ if (!args.fContext->priv().caps()->clampToBorderSupport()) {
+ if (wrapModes[0] == GrSamplerState::WrapMode::kClampToBorder) {
+ domainX = GrTextureDomain::kDecal_Mode;
+ wrapModes[0] = GrSamplerState::WrapMode::kClamp;
+ }
+ if (wrapModes[1] == GrSamplerState::WrapMode::kClampToBorder) {
+ domainY = GrTextureDomain::kDecal_Mode;
+ wrapModes[1] = GrSamplerState::WrapMode::kClamp;
+ }
+ }
+
// Must set wrap and filter on the sampler before requesting a texture. In two places below
// we check the matrix scale factors to determine how to interpret the filter quality setting.
// This completely ignores the complexity of the drawVertices case where explicit local coords
@@ -224,31 +240,22 @@
lmInverse.postScale(scaleAdjust[0], scaleAdjust[1]);
- const auto& caps = *args.fContext->priv().caps();
-
std::unique_ptr<GrFragmentProcessor> inner;
if (doBicubic) {
- // If either domainX or domainY are un-ignored, a texture domain effect has to be used to
- // implement the decal mode (while leaving non-decal axes alone). The wrap mode originally
- // clamp-to-border is reset to clamp since the hw cannot implement it directly.
- GrTextureDomain::Mode domainX = GrTextureDomain::kIgnore_Mode;
- GrTextureDomain::Mode domainY = GrTextureDomain::kIgnore_Mode;
- if (!caps.clampToBorderSupport()) {
- if (wrapModes[0] == GrSamplerState::WrapMode::kClampToBorder) {
- domainX = GrTextureDomain::kDecal_Mode;
- wrapModes[0] = GrSamplerState::WrapMode::kClamp;
- }
- if (wrapModes[1] == GrSamplerState::WrapMode::kClampToBorder) {
- domainY = GrTextureDomain::kDecal_Mode;
- wrapModes[1] = GrSamplerState::WrapMode::kClamp;
- }
- }
+ // domainX and domainY will properly apply the decal effect with the texture domain used in
+ // the bicubic filter if clamp to border was unsupported in hardware
static constexpr auto kDir = GrBicubicEffect::Direction::kXY;
inner = GrBicubicEffect::Make(std::move(proxy), lmInverse, wrapModes, domainX, domainY,
kDir, srcAlphaType);
} else {
- inner = GrTextureEffect::Make(std::move(proxy), srcAlphaType, lmInverse, samplerState,
- caps);
+ auto dimensions = proxy->dimensions();
+ inner = GrTextureEffect::Make(std::move(proxy), srcAlphaType, lmInverse, samplerState);
+ if (domainX != GrTextureDomain::kIgnore_Mode || domainY != GrTextureDomain::kIgnore_Mode) {
+ SkRect domain = GrTextureDomain::MakeTexelDomain(SkIRect::MakeSize(dimensions),
+ domainX, domainY);
+ inner = GrDomainEffect::Make(std::move(inner), domain, domainX, domainY,
+ samplerState.filter());
+ }
}
inner = GrColorSpaceXformEffect::Make(std::move(inner), fImage->colorSpace(), srcAlphaType,
args.fDstColorInfo->colorSpace());