Update GrCCClipProcessor to support an input FP.

GrReducedClip will now combine both analytic and CCPR FPs using child
FPs instead of via RunInSeries. (There is still an fShader component
which, if present, is combined via RunInSeries for now.)

Change-Id: Ia7e0ced1e64927b94a8e64adfb5a773c2c175963
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/297808
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
Commit-Queue: John Stiles <johnstiles@google.com>
This commit is contained in:
John Stiles 2020-06-19 15:32:16 -04:00 committed by Skia Commit-Bot
parent a061b4a782
commit 956ec8a8bc
7 changed files with 73 additions and 49 deletions

View File

@ -908,36 +908,41 @@ int GrReducedClip::numAnalyticFPs() const {
std::unique_ptr<GrFragmentProcessor> GrReducedClip::finishAndDetachAnalyticFPs(
GrRecordingContext* context, const SkMatrixProvider& matrixProvider,
GrCoverageCountingPathRenderer* ccpr, uint32_t opsTaskID) {
std::vector<std::unique_ptr<GrFragmentProcessor>> clipFPs;
clipFPs.reserve(fCCPRClipPaths.size() + 2);
// Combine the analytic FP with any CCPR clip processors.
std::unique_ptr<GrFragmentProcessor> clipFP = std::move(fAnalyticFP);
if (fAnalyticFP != nullptr) {
clipFPs.push_back(std::move(fAnalyticFP));
for (const SkPath& ccprClipPath : fCCPRClipPaths) {
SkASSERT(ccpr);
SkASSERT(fHasScissor);
clipFP = ccpr->makeClipProcessor(std::move(clipFP), opsTaskID, ccprClipPath,
fScissor, *fCaps);
}
fCCPRClipPaths.reset();
if (!fCCPRClipPaths.empty()) {
for (const SkPath& ccprClipPath : fCCPRClipPaths) {
SkASSERT(ccpr);
SkASSERT(fHasScissor);
clipFPs.push_back(ccpr->makeClipProcessor(opsTaskID, ccprClipPath, fScissor, *fCaps));
}
fCCPRClipPaths.reset();
}
static const GrColorInfo kCoverageColorInfo = GrColorInfo(GrColorType::kUnknown,
kPremul_SkAlphaType,
nullptr);
if (fShader) {
// Create the shader.
std::unique_ptr<GrFragmentProcessor> shaderFP;
if (fShader != nullptr) {
static const GrColorInfo kCoverageColorInfo{GrColorType::kUnknown, kPremul_SkAlphaType,
nullptr};
GrFPArgs args(context, matrixProvider, kNone_SkFilterQuality, &kCoverageColorInfo);
auto fp = as_SB(fShader)->asFragmentProcessor(args);
if (fp) {
fp = GrFragmentProcessor::SwizzleOutput(std::move(fp), GrSwizzle::AAAA());
clipFPs.push_back(std::move(fp));
shaderFP = as_SB(fShader)->asFragmentProcessor(args);
if (shaderFP != nullptr) {
shaderFP = GrFragmentProcessor::SwizzleOutput(std::move(shaderFP), GrSwizzle::AAAA());
}
}
return clipFPs.empty()
// Combine the clip and shader FPs using RunInSeries. (RunInSeries will automatically return the
// input as-is if we only have one.)
SkSTArray<2, std::unique_ptr<GrFragmentProcessor>> seriesFPs;
if (clipFP != nullptr) {
seriesFPs.push_back(std::move(clipFP));
}
if (shaderFP != nullptr) {
seriesFPs.push_back(std::move(shaderFP));
}
return seriesFPs.empty()
? nullptr
: GrFragmentProcessor::RunInSeries(&clipFPs.front(), clipFPs.size());
: GrFragmentProcessor::RunInSeries(&seriesFPs.front(), seriesFPs.size());
}

View File

@ -19,7 +19,8 @@ static GrSurfaceProxyView make_view(const GrCaps& caps, GrSurfaceProxy* proxy,
return { sk_ref_sp(proxy), GrCCAtlas::kTextureOrigin, swizzle };
}
GrCCClipProcessor::GrCCClipProcessor(const GrCaps& caps,
GrCCClipProcessor::GrCCClipProcessor(std::unique_ptr<GrFragmentProcessor> inputFP,
const GrCaps& caps,
const GrCCClipPath* clipPath,
IsCoverageCount isCoverageCount,
MustCheckBounds mustCheckBounds)
@ -28,9 +29,13 @@ GrCCClipProcessor::GrCCClipProcessor(const GrCaps& caps,
, fIsCoverageCount(IsCoverageCount::kYes == isCoverageCount)
, fMustCheckBounds(MustCheckBounds::kYes == mustCheckBounds) {
auto view = make_view(caps, clipPath->atlasLazyProxy(), fIsCoverageCount);
auto te = GrTextureEffect::Make(std::move(view), kUnknown_SkAlphaType);
te->setSampledWithExplicitCoords();
this->registerChildProcessor(std::move(te));
auto texEffect = GrTextureEffect::Make(std::move(view), kUnknown_SkAlphaType);
texEffect->setSampledWithExplicitCoords();
this->registerChildProcessor(std::move(texEffect));
if (inputFP != nullptr) {
this->registerChildProcessor(std::move(inputFP));
}
}
GrCCClipProcessor::GrCCClipProcessor(const GrCCClipProcessor& that)
@ -38,9 +43,7 @@ GrCCClipProcessor::GrCCClipProcessor(const GrCCClipProcessor& that)
, fClipPath(that.fClipPath)
, fIsCoverageCount(that.fIsCoverageCount)
, fMustCheckBounds(that.fMustCheckBounds) {
auto child = that.childProcessor(0).clone();
child->setSampledWithExplicitCoords();
this->registerChildProcessor(std::move(child));
this->cloneAndRegisterAllChildProcessors(that);
}
std::unique_ptr<GrFragmentProcessor> GrCCClipProcessor::clone() const {
@ -64,6 +67,12 @@ bool GrCCClipProcessor::onIsEqual(const GrFragmentProcessor& fp) const {
that.fIsCoverageCount == fIsCoverageCount && that.fMustCheckBounds == fMustCheckBounds;
}
bool GrCCClipProcessor::hasInputFP() const {
// We always have a `texEffect`, and this accounts for one child.
// The second child will be the input FP, if we have one.
return this->numChildProcessors() > 1;
}
class GrCCClipProcessor::Impl : public GrGLSLFragmentProcessor {
public:
void emitCode(EmitArgs& args) override {
@ -71,7 +80,7 @@ public:
GrGLSLUniformHandler* uniHandler = args.fUniformHandler;
GrGLSLFPFragmentBuilder* f = args.fFragBuilder;
f->codeAppend ("half coverage;");
f->codeAppend("half coverage;");
if (proc.fMustCheckBounds) {
const char* pathIBounds;
@ -89,31 +98,37 @@ public:
&atlasTranslate);
SkString coord;
coord.printf("sk_FragCoord.xy + %s.xy", atlasTranslate);
SkString sample = this->invokeChild(0, args, coord.c_str());
constexpr int kTexEffectFPIndex = 0;
SkString sample = this->invokeChild(kTexEffectFPIndex, args, coord.c_str());
f->codeAppendf("coverage = %s.a;", sample.c_str());
if (proc.fIsCoverageCount) {
auto fillRule = GrFillRuleForSkPath(proc.fClipPath->deviceSpacePath());
if (GrFillRule::kEvenOdd == fillRule) {
f->codeAppend ("half t = mod(abs(coverage), 2);");
f->codeAppend ("coverage = 1 - abs(t - 1);");
f->codeAppend("half t = mod(abs(coverage), 2);");
f->codeAppend("coverage = 1 - abs(t - 1);");
} else {
SkASSERT(GrFillRule::kNonzero == fillRule);
f->codeAppend ("coverage = min(abs(coverage), 1);");
f->codeAppend("coverage = min(abs(coverage), 1);");
}
}
if (proc.fMustCheckBounds) {
f->codeAppend ("} else {");
f->codeAppend ( "coverage = 0;");
f->codeAppend ("}");
f->codeAppend("} else {");
f->codeAppend( "coverage = 0;");
f->codeAppend("}");
}
if (proc.fClipPath->deviceSpacePath().isInverseFillType()) {
f->codeAppend ("coverage = 1 - coverage;");
f->codeAppend("coverage = 1 - coverage;");
}
f->codeAppendf("%s = %s * coverage;", args.fOutputColor, args.fInputColor);
constexpr int kInputFPIndex = 1;
SkString inputColor = proc.hasInputFP()
? this->invokeChild(kInputFPIndex, args.fInputColor, args)
: SkString(args.fInputColor);
f->codeAppendf("%s = %s * coverage;", args.fOutputColor, inputColor.c_str());
}
void onSetData(const GrGLSLProgramDataManager& pdman,

View File

@ -24,13 +24,15 @@ public:
kYes = true
};
GrCCClipProcessor(const GrCaps&, const GrCCClipPath*, IsCoverageCount, MustCheckBounds);
GrCCClipProcessor(std::unique_ptr<GrFragmentProcessor>, const GrCaps&, const GrCCClipPath*,
IsCoverageCount, MustCheckBounds);
const char* name() const override { return "GrCCClipProcessor"; }
std::unique_ptr<GrFragmentProcessor> clone() const override;
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
bool onIsEqual(const GrFragmentProcessor&) const override;
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
bool hasInputFP() const;
private:
explicit GrCCClipProcessor(const GrCCClipProcessor&);

View File

@ -186,8 +186,8 @@ void GrCoverageCountingPathRenderer::recordOp(std::unique_ptr<GrCCDrawPathsOp> o
}
std::unique_ptr<GrFragmentProcessor> GrCoverageCountingPathRenderer::makeClipProcessor(
uint32_t opsTaskID, const SkPath& deviceSpacePath, const SkIRect& accessRect,
const GrCaps& caps) {
std::unique_ptr<GrFragmentProcessor> inputFP, uint32_t opsTaskID,
const SkPath& deviceSpacePath, const SkIRect& accessRect, const GrCaps& caps) {
SkASSERT(!fFlushing);
uint32_t key = deviceSpacePath.getGenerationID();
@ -218,7 +218,8 @@ std::unique_ptr<GrFragmentProcessor> GrCoverageCountingPathRenderer::makeClipPro
CoverageType::kFP16_CoverageCount == fCoverageType);
auto mustCheckBounds = GrCCClipProcessor::MustCheckBounds(
!clipPath.pathDevIBounds().contains(accessRect));
return std::make_unique<GrCCClipProcessor>(caps, &clipPath, isCoverageCount, mustCheckBounds);
return std::make_unique<GrCCClipProcessor>(
std::move(inputFP), caps, &clipPath, isCoverageCount, mustCheckBounds);
}
void GrCoverageCountingPathRenderer::preFlush(

View File

@ -63,8 +63,8 @@ public:
}
std::unique_ptr<GrFragmentProcessor> makeClipProcessor(
uint32_t oplistID, const SkPath& deviceSpacePath, const SkIRect& accessRect,
const GrCaps&);
std::unique_ptr<GrFragmentProcessor> inputFP, uint32_t opsTaskID,
const SkPath& deviceSpacePath, const SkIRect& accessRect, const GrCaps& caps);
// GrOnFlushCallbackObject overrides.
void preFlush(GrOnFlushResourceProvider*, const uint32_t* opsTaskIDs,

View File

@ -17,7 +17,7 @@ sk_sp<GrCoverageCountingPathRenderer> GrCoverageCountingPathRenderer::CreateIfSu
}
std::unique_ptr<GrFragmentProcessor> GrCoverageCountingPathRenderer::makeClipProcessor(
uint32_t opsTaskID, const SkPath& deviceSpacePath, const SkIRect& accessRect,
const GrCaps& caps) {
std::unique_ptr<GrFragmentProcessor> inputFP, uint32_t opsTaskID,
const SkPath& deviceSpacePath, const SkIRect& accessRect, const GrCaps& caps) {
return nullptr;
}

View File

@ -42,7 +42,8 @@ private:
SkIRect getConservativeBounds() const final { return fPath.getBounds().roundOut(); }
bool apply(GrRecordingContext* context, GrRenderTargetContext* rtc, bool useHWAA,
bool hasUserStencilSettings, GrAppliedClip* out, SkRect* bounds) const override {
out->addCoverageFP(fCCPR->makeClipProcessor(rtc->priv().testingOnly_getOpsTaskID(), fPath,
out->addCoverageFP(fCCPR->makeClipProcessor(/*inputFP=*/nullptr,
rtc->priv().testingOnly_getOpsTaskID(), fPath,
SkIRect::MakeWH(rtc->width(), rtc->height()),
*context->priv().caps()));
return true;