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:
parent
a061b4a782
commit
956ec8a8bc
@ -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());
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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&);
|
||||
|
@ -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(
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user