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(
|
std::unique_ptr<GrFragmentProcessor> GrReducedClip::finishAndDetachAnalyticFPs(
|
||||||
GrRecordingContext* context, const SkMatrixProvider& matrixProvider,
|
GrRecordingContext* context, const SkMatrixProvider& matrixProvider,
|
||||||
GrCoverageCountingPathRenderer* ccpr, uint32_t opsTaskID) {
|
GrCoverageCountingPathRenderer* ccpr, uint32_t opsTaskID) {
|
||||||
std::vector<std::unique_ptr<GrFragmentProcessor>> clipFPs;
|
// Combine the analytic FP with any CCPR clip processors.
|
||||||
clipFPs.reserve(fCCPRClipPaths.size() + 2);
|
std::unique_ptr<GrFragmentProcessor> clipFP = std::move(fAnalyticFP);
|
||||||
|
|
||||||
if (fAnalyticFP != nullptr) {
|
for (const SkPath& ccprClipPath : fCCPRClipPaths) {
|
||||||
clipFPs.push_back(std::move(fAnalyticFP));
|
SkASSERT(ccpr);
|
||||||
|
SkASSERT(fHasScissor);
|
||||||
|
clipFP = ccpr->makeClipProcessor(std::move(clipFP), opsTaskID, ccprClipPath,
|
||||||
|
fScissor, *fCaps);
|
||||||
}
|
}
|
||||||
|
fCCPRClipPaths.reset();
|
||||||
|
|
||||||
if (!fCCPRClipPaths.empty()) {
|
// Create the shader.
|
||||||
for (const SkPath& ccprClipPath : fCCPRClipPaths) {
|
std::unique_ptr<GrFragmentProcessor> shaderFP;
|
||||||
SkASSERT(ccpr);
|
if (fShader != nullptr) {
|
||||||
SkASSERT(fHasScissor);
|
static const GrColorInfo kCoverageColorInfo{GrColorType::kUnknown, kPremul_SkAlphaType,
|
||||||
clipFPs.push_back(ccpr->makeClipProcessor(opsTaskID, ccprClipPath, fScissor, *fCaps));
|
nullptr};
|
||||||
}
|
|
||||||
fCCPRClipPaths.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
static const GrColorInfo kCoverageColorInfo = GrColorInfo(GrColorType::kUnknown,
|
|
||||||
kPremul_SkAlphaType,
|
|
||||||
nullptr);
|
|
||||||
if (fShader) {
|
|
||||||
GrFPArgs args(context, matrixProvider, kNone_SkFilterQuality, &kCoverageColorInfo);
|
GrFPArgs args(context, matrixProvider, kNone_SkFilterQuality, &kCoverageColorInfo);
|
||||||
auto fp = as_SB(fShader)->asFragmentProcessor(args);
|
shaderFP = as_SB(fShader)->asFragmentProcessor(args);
|
||||||
if (fp) {
|
if (shaderFP != nullptr) {
|
||||||
fp = GrFragmentProcessor::SwizzleOutput(std::move(fp), GrSwizzle::AAAA());
|
shaderFP = GrFragmentProcessor::SwizzleOutput(std::move(shaderFP), GrSwizzle::AAAA());
|
||||||
clipFPs.push_back(std::move(fp));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
? 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 };
|
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,
|
const GrCCClipPath* clipPath,
|
||||||
IsCoverageCount isCoverageCount,
|
IsCoverageCount isCoverageCount,
|
||||||
MustCheckBounds mustCheckBounds)
|
MustCheckBounds mustCheckBounds)
|
||||||
@ -28,9 +29,13 @@ GrCCClipProcessor::GrCCClipProcessor(const GrCaps& caps,
|
|||||||
, fIsCoverageCount(IsCoverageCount::kYes == isCoverageCount)
|
, fIsCoverageCount(IsCoverageCount::kYes == isCoverageCount)
|
||||||
, fMustCheckBounds(MustCheckBounds::kYes == mustCheckBounds) {
|
, fMustCheckBounds(MustCheckBounds::kYes == mustCheckBounds) {
|
||||||
auto view = make_view(caps, clipPath->atlasLazyProxy(), fIsCoverageCount);
|
auto view = make_view(caps, clipPath->atlasLazyProxy(), fIsCoverageCount);
|
||||||
auto te = GrTextureEffect::Make(std::move(view), kUnknown_SkAlphaType);
|
auto texEffect = GrTextureEffect::Make(std::move(view), kUnknown_SkAlphaType);
|
||||||
te->setSampledWithExplicitCoords();
|
texEffect->setSampledWithExplicitCoords();
|
||||||
this->registerChildProcessor(std::move(te));
|
this->registerChildProcessor(std::move(texEffect));
|
||||||
|
|
||||||
|
if (inputFP != nullptr) {
|
||||||
|
this->registerChildProcessor(std::move(inputFP));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GrCCClipProcessor::GrCCClipProcessor(const GrCCClipProcessor& that)
|
GrCCClipProcessor::GrCCClipProcessor(const GrCCClipProcessor& that)
|
||||||
@ -38,9 +43,7 @@ GrCCClipProcessor::GrCCClipProcessor(const GrCCClipProcessor& that)
|
|||||||
, fClipPath(that.fClipPath)
|
, fClipPath(that.fClipPath)
|
||||||
, fIsCoverageCount(that.fIsCoverageCount)
|
, fIsCoverageCount(that.fIsCoverageCount)
|
||||||
, fMustCheckBounds(that.fMustCheckBounds) {
|
, fMustCheckBounds(that.fMustCheckBounds) {
|
||||||
auto child = that.childProcessor(0).clone();
|
this->cloneAndRegisterAllChildProcessors(that);
|
||||||
child->setSampledWithExplicitCoords();
|
|
||||||
this->registerChildProcessor(std::move(child));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<GrFragmentProcessor> GrCCClipProcessor::clone() const {
|
std::unique_ptr<GrFragmentProcessor> GrCCClipProcessor::clone() const {
|
||||||
@ -64,6 +67,12 @@ bool GrCCClipProcessor::onIsEqual(const GrFragmentProcessor& fp) const {
|
|||||||
that.fIsCoverageCount == fIsCoverageCount && that.fMustCheckBounds == fMustCheckBounds;
|
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 {
|
class GrCCClipProcessor::Impl : public GrGLSLFragmentProcessor {
|
||||||
public:
|
public:
|
||||||
void emitCode(EmitArgs& args) override {
|
void emitCode(EmitArgs& args) override {
|
||||||
@ -71,7 +80,7 @@ public:
|
|||||||
GrGLSLUniformHandler* uniHandler = args.fUniformHandler;
|
GrGLSLUniformHandler* uniHandler = args.fUniformHandler;
|
||||||
GrGLSLFPFragmentBuilder* f = args.fFragBuilder;
|
GrGLSLFPFragmentBuilder* f = args.fFragBuilder;
|
||||||
|
|
||||||
f->codeAppend ("half coverage;");
|
f->codeAppend("half coverage;");
|
||||||
|
|
||||||
if (proc.fMustCheckBounds) {
|
if (proc.fMustCheckBounds) {
|
||||||
const char* pathIBounds;
|
const char* pathIBounds;
|
||||||
@ -89,31 +98,37 @@ public:
|
|||||||
&atlasTranslate);
|
&atlasTranslate);
|
||||||
SkString coord;
|
SkString coord;
|
||||||
coord.printf("sk_FragCoord.xy + %s.xy", atlasTranslate);
|
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());
|
f->codeAppendf("coverage = %s.a;", sample.c_str());
|
||||||
|
|
||||||
if (proc.fIsCoverageCount) {
|
if (proc.fIsCoverageCount) {
|
||||||
auto fillRule = GrFillRuleForSkPath(proc.fClipPath->deviceSpacePath());
|
auto fillRule = GrFillRuleForSkPath(proc.fClipPath->deviceSpacePath());
|
||||||
if (GrFillRule::kEvenOdd == fillRule) {
|
if (GrFillRule::kEvenOdd == fillRule) {
|
||||||
f->codeAppend ("half t = mod(abs(coverage), 2);");
|
f->codeAppend("half t = mod(abs(coverage), 2);");
|
||||||
f->codeAppend ("coverage = 1 - abs(t - 1);");
|
f->codeAppend("coverage = 1 - abs(t - 1);");
|
||||||
} else {
|
} else {
|
||||||
SkASSERT(GrFillRule::kNonzero == fillRule);
|
SkASSERT(GrFillRule::kNonzero == fillRule);
|
||||||
f->codeAppend ("coverage = min(abs(coverage), 1);");
|
f->codeAppend("coverage = min(abs(coverage), 1);");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (proc.fMustCheckBounds) {
|
if (proc.fMustCheckBounds) {
|
||||||
f->codeAppend ("} else {");
|
f->codeAppend("} else {");
|
||||||
f->codeAppend ( "coverage = 0;");
|
f->codeAppend( "coverage = 0;");
|
||||||
f->codeAppend ("}");
|
f->codeAppend("}");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (proc.fClipPath->deviceSpacePath().isInverseFillType()) {
|
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,
|
void onSetData(const GrGLSLProgramDataManager& pdman,
|
||||||
|
@ -24,13 +24,15 @@ public:
|
|||||||
kYes = true
|
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"; }
|
const char* name() const override { return "GrCCClipProcessor"; }
|
||||||
std::unique_ptr<GrFragmentProcessor> clone() const override;
|
std::unique_ptr<GrFragmentProcessor> clone() const override;
|
||||||
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
|
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
|
||||||
bool onIsEqual(const GrFragmentProcessor&) const override;
|
bool onIsEqual(const GrFragmentProcessor&) const override;
|
||||||
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
|
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
|
||||||
|
bool hasInputFP() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit GrCCClipProcessor(const GrCCClipProcessor&);
|
explicit GrCCClipProcessor(const GrCCClipProcessor&);
|
||||||
|
@ -186,8 +186,8 @@ void GrCoverageCountingPathRenderer::recordOp(std::unique_ptr<GrCCDrawPathsOp> o
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<GrFragmentProcessor> GrCoverageCountingPathRenderer::makeClipProcessor(
|
std::unique_ptr<GrFragmentProcessor> GrCoverageCountingPathRenderer::makeClipProcessor(
|
||||||
uint32_t opsTaskID, const SkPath& deviceSpacePath, const SkIRect& accessRect,
|
std::unique_ptr<GrFragmentProcessor> inputFP, uint32_t opsTaskID,
|
||||||
const GrCaps& caps) {
|
const SkPath& deviceSpacePath, const SkIRect& accessRect, const GrCaps& caps) {
|
||||||
SkASSERT(!fFlushing);
|
SkASSERT(!fFlushing);
|
||||||
|
|
||||||
uint32_t key = deviceSpacePath.getGenerationID();
|
uint32_t key = deviceSpacePath.getGenerationID();
|
||||||
@ -218,7 +218,8 @@ std::unique_ptr<GrFragmentProcessor> GrCoverageCountingPathRenderer::makeClipPro
|
|||||||
CoverageType::kFP16_CoverageCount == fCoverageType);
|
CoverageType::kFP16_CoverageCount == fCoverageType);
|
||||||
auto mustCheckBounds = GrCCClipProcessor::MustCheckBounds(
|
auto mustCheckBounds = GrCCClipProcessor::MustCheckBounds(
|
||||||
!clipPath.pathDevIBounds().contains(accessRect));
|
!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(
|
void GrCoverageCountingPathRenderer::preFlush(
|
||||||
|
@ -63,8 +63,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<GrFragmentProcessor> makeClipProcessor(
|
std::unique_ptr<GrFragmentProcessor> makeClipProcessor(
|
||||||
uint32_t oplistID, const SkPath& deviceSpacePath, const SkIRect& accessRect,
|
std::unique_ptr<GrFragmentProcessor> inputFP, uint32_t opsTaskID,
|
||||||
const GrCaps&);
|
const SkPath& deviceSpacePath, const SkIRect& accessRect, const GrCaps& caps);
|
||||||
|
|
||||||
// GrOnFlushCallbackObject overrides.
|
// GrOnFlushCallbackObject overrides.
|
||||||
void preFlush(GrOnFlushResourceProvider*, const uint32_t* opsTaskIDs,
|
void preFlush(GrOnFlushResourceProvider*, const uint32_t* opsTaskIDs,
|
||||||
|
@ -17,7 +17,7 @@ sk_sp<GrCoverageCountingPathRenderer> GrCoverageCountingPathRenderer::CreateIfSu
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<GrFragmentProcessor> GrCoverageCountingPathRenderer::makeClipProcessor(
|
std::unique_ptr<GrFragmentProcessor> GrCoverageCountingPathRenderer::makeClipProcessor(
|
||||||
uint32_t opsTaskID, const SkPath& deviceSpacePath, const SkIRect& accessRect,
|
std::unique_ptr<GrFragmentProcessor> inputFP, uint32_t opsTaskID,
|
||||||
const GrCaps& caps) {
|
const SkPath& deviceSpacePath, const SkIRect& accessRect, const GrCaps& caps) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,8 @@ private:
|
|||||||
SkIRect getConservativeBounds() const final { return fPath.getBounds().roundOut(); }
|
SkIRect getConservativeBounds() const final { return fPath.getBounds().roundOut(); }
|
||||||
bool apply(GrRecordingContext* context, GrRenderTargetContext* rtc, bool useHWAA,
|
bool apply(GrRecordingContext* context, GrRenderTargetContext* rtc, bool useHWAA,
|
||||||
bool hasUserStencilSettings, GrAppliedClip* out, SkRect* bounds) const override {
|
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()),
|
SkIRect::MakeWH(rtc->width(), rtc->height()),
|
||||||
*context->priv().caps()));
|
*context->priv().caps()));
|
||||||
return true;
|
return true;
|
||||||
|
Loading…
Reference in New Issue
Block a user