diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp index 7baf512bad..c5fd414a48 100644 --- a/src/gpu/GrRenderTargetContext.cpp +++ b/src/gpu/GrRenderTargetContext.cpp @@ -875,10 +875,10 @@ void GrRenderTargetContext::drawAtlas(const GrClip& clip, AutoCheckFlush acf(this->drawingManager()); - std::unique_ptr op = - GrDrawAtlasOp::Make(paint.getColor(), viewMatrix, spriteCount, xform, texRect, colors); - GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone); - this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op)); + GrAAType aaType = this->chooseAAType(GrAA::kNo, GrAllowMixedSamples::kNo); + std::unique_ptr op = GrDrawAtlasOp::Make(std::move(paint), viewMatrix, aaType, + spriteCount, xform, texRect, colors); + this->addDrawOp(clip, std::move(op)); } /////////////////////////////////////////////////////////////////////////////// diff --git a/src/gpu/ops/GrDrawAtlasOp.cpp b/src/gpu/ops/GrDrawAtlasOp.cpp index 1c7251a0bb..b4fc6fac58 100644 --- a/src/gpu/ops/GrDrawAtlasOp.cpp +++ b/src/gpu/ops/GrDrawAtlasOp.cpp @@ -12,23 +12,6 @@ #include "SkRSXform.h" #include "SkRandom.h" -void GrDrawAtlasOp::applyPipelineOptimizations(const PipelineOptimizations& optimizations) { - SkASSERT(fGeoData.count() == 1); - if (optimizations.getOverrideColorIfSet(&fGeoData[0].fColor) && fHasColors) { - size_t vertexStride = - sizeof(SkPoint) + sizeof(SkPoint) + (this->hasColors() ? sizeof(GrColor) : 0); - uint8_t* currVertex = fGeoData[0].fVerts.begin(); - for (int i = 0; i < 4 * fQuadCount; ++i) { - *(reinterpret_cast(currVertex + sizeof(SkPoint))) = fGeoData[0].fColor; - currVertex += vertexStride; - } - } - - fColor = fGeoData[0].fColor; - // We'd like to assert this, but we can't because of GLPrograms test - // SkASSERT(init.readsLocalCoords()); -} - static sk_sp make_gp(bool hasColors, GrColor color, const SkMatrix& viewMatrix) { @@ -42,37 +25,10 @@ static sk_sp make_gp(bool hasColors, LocalCoords::kHasExplicit_Type, viewMatrix); } -void GrDrawAtlasOp::onPrepareDraws(Target* target) const { - // Setup geometry processor - sk_sp gp(make_gp(this->hasColors(), this->color(), this->viewMatrix())); - - int instanceCount = fGeoData.count(); - size_t vertexStride = gp->getVertexStride(); - SkASSERT(vertexStride == - sizeof(SkPoint) + sizeof(SkPoint) + (this->hasColors() ? sizeof(GrColor) : 0)); - - QuadHelper helper; - int numQuads = this->quadCount(); - void* verts = helper.init(target, vertexStride, numQuads); - if (!verts) { - SkDebugf("Could not allocate vertices\n"); - return; - } - - uint8_t* vertPtr = reinterpret_cast(verts); - for (int i = 0; i < instanceCount; i++) { - const Geometry& args = fGeoData[i]; - - size_t allocSize = args.fVerts.count(); - memcpy(vertPtr, args.fVerts.begin(), allocSize); - vertPtr += allocSize; - } - helper.recordDraw(target, gp.get(), this->pipeline()); -} - -GrDrawAtlasOp::GrDrawAtlasOp(GrColor color, const SkMatrix& viewMatrix, int spriteCount, +GrDrawAtlasOp::GrDrawAtlasOp(const Helper::MakeArgs& helperArgs, GrColor color, + const SkMatrix& viewMatrix, GrAAType aaType, int spriteCount, const SkRSXform* xforms, const SkRect* rects, const SkColor* colors) - : INHERITED(ClassID()) { + : INHERITED(ClassID()), fHelper(helperArgs, aaType) { SkASSERT(xforms); SkASSERT(rects); @@ -151,11 +107,48 @@ GrDrawAtlasOp::GrDrawAtlasOp(GrColor color, const SkMatrix& viewMatrix, int spri this->setTransformedBounds(bounds, viewMatrix, HasAABloat::kNo, IsZeroArea::kNo); } +SkString GrDrawAtlasOp::dumpInfo() const { + SkString string; + for (const auto& geo : fGeoData) { + string.appendf("Color: 0x%08x, Quads: %d\n", geo.fColor, geo.fVerts.count() / 4); + } + string += fHelper.dumpInfo(); + string += INHERITED::dumpInfo(); + return string; +} + +void GrDrawAtlasOp::onPrepareDraws(Target* target) const { + // Setup geometry processor + sk_sp gp(make_gp(this->hasColors(), this->color(), this->viewMatrix())); + + int instanceCount = fGeoData.count(); + size_t vertexStride = gp->getVertexStride(); + SkASSERT(vertexStride == + sizeof(SkPoint) + sizeof(SkPoint) + (this->hasColors() ? sizeof(GrColor) : 0)); + + QuadHelper helper; + int numQuads = this->quadCount(); + void* verts = helper.init(target, vertexStride, numQuads); + if (!verts) { + SkDebugf("Could not allocate vertices\n"); + return; + } + + uint8_t* vertPtr = reinterpret_cast(verts); + for (int i = 0; i < instanceCount; i++) { + const Geometry& args = fGeoData[i]; + + size_t allocSize = args.fVerts.count(); + memcpy(vertPtr, args.fVerts.begin(), allocSize); + vertPtr += allocSize; + } + helper.recordDraw(target, gp.get(), fHelper.makePipeline(target)); +} + bool GrDrawAtlasOp::onCombineIfPossible(GrOp* t, const GrCaps& caps) { GrDrawAtlasOp* that = t->cast(); - if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(), - that->bounds(), caps)) { + if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) { return false; } @@ -179,6 +172,26 @@ bool GrDrawAtlasOp::onCombineIfPossible(GrOp* t, const GrCaps& caps) { return true; } +GrDrawOp::FixedFunctionFlags GrDrawAtlasOp::fixedFunctionFlags() const { + return fHelper.fixedFunctionFlags(); +} + +GrDrawOp::RequiresDstTexture GrDrawAtlasOp::finalize(const GrCaps& caps, + const GrAppliedClip* clip) { + GrProcessorAnalysisColor gpColor; + if (this->hasColors()) { + gpColor.setToUnknown(); + } else { + gpColor.setToConstant(fColor); + } + auto result = + fHelper.xpRequiresDstTexture(caps, clip, GrProcessorAnalysisCoverage::kNone, &gpColor); + if (gpColor.isConstant(&fColor)) { + fHasColors = false; + } + return result; +} + #if GR_TEST_UTILS static SkRSXform random_xform(SkRandom* random) { @@ -222,7 +235,7 @@ static void randomize_params(uint32_t count, SkRandom* random, SkTArraynextRangeU(1, 100); SkTArray xforms(spriteCount); @@ -234,10 +247,13 @@ GR_LEGACY_MESH_DRAW_OP_TEST_DEFINE(GrDrawAtlasOp) { randomize_params(spriteCount, random, &xforms, &texRects, &colors, hasColors); SkMatrix viewMatrix = GrTest::TestMatrix(random); + GrAAType aaType = GrAAType::kNone; + if (GrFSAAType::kUnifiedMSAA == fsaaType && random->nextBool()) { + aaType = GrAAType::kMSAA; + } - GrColor color = GrRandomColor(random); - return GrDrawAtlasOp::Make(color, viewMatrix, spriteCount, xforms.begin(), texRects.begin(), - hasColors ? colors.begin() : nullptr); + return GrDrawAtlasOp::Make(std::move(paint), viewMatrix, aaType, spriteCount, xforms.begin(), + texRects.begin(), hasColors ? colors.begin() : nullptr); } #endif diff --git a/src/gpu/ops/GrDrawAtlasOp.h b/src/gpu/ops/GrDrawAtlasOp.h index 79a60988f0..bec2eb1541 100644 --- a/src/gpu/ops/GrDrawAtlasOp.h +++ b/src/gpu/ops/GrDrawAtlasOp.h @@ -11,48 +11,37 @@ #include "GrColor.h" #include "GrDefaultGeoProcFactory.h" #include "GrMeshDrawOp.h" +#include "GrSimpleMeshDrawOpHelper.h" + +class GrDrawAtlasOp final : public GrMeshDrawOp { +private: + using Helper = GrSimpleMeshDrawOpHelper; -class GrDrawAtlasOp final : public GrLegacyMeshDrawOp { public: DEFINE_OP_CLASS_ID - static std::unique_ptr Make(GrColor color, const SkMatrix& viewMatrix, - int spriteCount, const SkRSXform* xforms, - const SkRect* rects, const SkColor* colors) { - return std::unique_ptr( - new GrDrawAtlasOp(color, viewMatrix, spriteCount, xforms, rects, colors)); + static std::unique_ptr Make(GrPaint&& paint, const SkMatrix& viewMatrix, + GrAAType aaType, int spriteCount, const SkRSXform* xforms, + const SkRect* rects, const SkColor* colors) { + return Helper::FactoryHelper(std::move(paint), viewMatrix, aaType, + spriteCount, xforms, rects, colors); } + GrDrawAtlasOp(const Helper::MakeArgs& helperArgs, GrColor color, const SkMatrix& viewMatrix, + GrAAType, int spriteCount, const SkRSXform* xforms, const SkRect* rects, + const SkColor* colors); + const char* name() const override { return "DrawAtlasOp"; } - SkString dumpInfo() const override { - SkString string; - for (const auto& geo : fGeoData) { - string.appendf("Color: 0x%08x, Quads: %d\n", geo.fColor, geo.fVerts.count() / 4); - } - string.append(DumpPipelineInfo(*this->pipeline())); - string.append(INHERITED::dumpInfo()); - return string; - } + SkString dumpInfo() const override; + + FixedFunctionFlags fixedFunctionFlags() const override; + + RequiresDstTexture finalize(const GrCaps& caps, const GrAppliedClip* clip) override; private: - GrDrawAtlasOp(GrColor color, const SkMatrix& viewMatrix, int spriteCount, - const SkRSXform* xforms, const SkRect* rects, const SkColor* colors); - - void getProcessorAnalysisInputs(GrProcessorAnalysisColor* color, - GrProcessorAnalysisCoverage* coverage) const override { - if (this->hasColors()) { - color->setToUnknown(); - } else { - color->setToConstant(fGeoData[0].fColor); - } - *coverage = GrProcessorAnalysisCoverage::kNone; - } - void onPrepareDraws(Target*) const override; - void applyPipelineOptimizations(const PipelineOptimizations&) override; - GrColor color() const { return fColor; } const SkMatrix& viewMatrix() const { return fViewMatrix; } bool hasColors() const { return fHasColors; } @@ -66,13 +55,13 @@ private: }; SkSTArray<1, Geometry, true> fGeoData; - + Helper fHelper; SkMatrix fViewMatrix; GrColor fColor; int fQuadCount; bool fHasColors; - typedef GrLegacyMeshDrawOp INHERITED; + typedef GrMeshDrawOp INHERITED; }; #endif diff --git a/src/gpu/ops/GrSimpleMeshDrawOpHelper.cpp b/src/gpu/ops/GrSimpleMeshDrawOpHelper.cpp index 0d32358bc4..0d97de4c57 100644 --- a/src/gpu/ops/GrSimpleMeshDrawOpHelper.cpp +++ b/src/gpu/ops/GrSimpleMeshDrawOpHelper.cpp @@ -64,7 +64,7 @@ bool GrSimpleMeshDrawOpHelper::isCompatible(const GrSimpleMeshDrawOpHelper& that GrDrawOp::RequiresDstTexture GrSimpleMeshDrawOpHelper::xpRequiresDstTexture( const GrCaps& caps, const GrAppliedClip* clip, GrProcessorAnalysisCoverage geometryCoverage, - GrColor* color) { + GrProcessorAnalysisColor* geometryColor) { SkDEBUGCODE(fDidAnalysis = true); GrProcessorSet::Analysis analysis; if (fProcessors) { @@ -75,7 +75,12 @@ GrDrawOp::RequiresDstTexture GrSimpleMeshDrawOpHelper::xpRequiresDstTexture( : GrProcessorAnalysisCoverage::kNone; } bool isMixedSamples = this->aaType() == GrAAType::kMixedSamples; - analysis = fProcessors->finalize(*color, coverage, clip, isMixedSamples, caps, color); + GrColor overrideColor; + analysis = fProcessors->finalize(*geometryColor, coverage, clip, isMixedSamples, caps, + &overrideColor); + if (analysis.inputColorIsOverridden()) { + *geometryColor = overrideColor; + } } else { analysis = GrProcessorSet::EmptySetAnalysis(); } @@ -86,6 +91,15 @@ GrDrawOp::RequiresDstTexture GrSimpleMeshDrawOpHelper::xpRequiresDstTexture( : GrDrawOp::RequiresDstTexture::kNo; } +GrDrawOp::RequiresDstTexture GrSimpleMeshDrawOpHelper::xpRequiresDstTexture( + const GrCaps& caps, const GrAppliedClip* clip, GrProcessorAnalysisCoverage geometryCoverage, + GrColor* geometryColor) { + GrProcessorAnalysisColor color = *geometryColor; + auto result = this->xpRequiresDstTexture(caps, clip, geometryCoverage, &color); + color.isConstant(geometryColor); + return result; +} + SkString GrSimpleMeshDrawOpHelper::dumpInfo() const { SkString result = this->processors().dumpProcessors(); result.append("AA Type: "); diff --git a/src/gpu/ops/GrSimpleMeshDrawOpHelper.h b/src/gpu/ops/GrSimpleMeshDrawOpHelper.h index 813a3dcdd7..2efd57c76e 100644 --- a/src/gpu/ops/GrSimpleMeshDrawOpHelper.h +++ b/src/gpu/ops/GrSimpleMeshDrawOpHelper.h @@ -52,9 +52,28 @@ public: bool isCompatible(const GrSimpleMeshDrawOpHelper& that, const GrCaps&, const SkRect& thisBounds, const SkRect& thatBounds) const; + /** + * Finalizes the processor set and determines whether the destination must be provided + * to the fragment shader as a texture for blending. + * + * @param geometryCoverage Describes the coverage output of the op's geometry processor + * @param geometryColor An in/out param. As input this informs processor analysis about the + * color the op expects to output from its geometry processor. As output + * this may be set to a known color in which case the op must output this + * color from its geometry processor instead. + */ + GrDrawOp::RequiresDstTexture xpRequiresDstTexture(const GrCaps& caps, const GrAppliedClip* clip, + GrProcessorAnalysisCoverage geometryCoverage, + GrProcessorAnalysisColor* geometryColor); + + /** + * Version of above that can be used by ops that have a constant color geometry processor + * output. The op passes this color as 'geometryColor' and after return if 'geometryColor' has + * changed the op must override its geometry processor color output with the new color. + */ GrDrawOp::RequiresDstTexture xpRequiresDstTexture(const GrCaps&, const GrAppliedClip*, GrProcessorAnalysisCoverage geometryCoverage, - GrColor* color); + GrColor* geometryColor); bool usesLocalCoords() const { SkASSERT(fDidAnalysis); diff --git a/tools/gpu/GrTest.cpp b/tools/gpu/GrTest.cpp index 3b9e44fcb7..b28420bbb8 100644 --- a/tools/gpu/GrTest.cpp +++ b/tools/gpu/GrTest.cpp @@ -316,7 +316,6 @@ void GrDrawingManager::testingOnly_removeOnFlushCallbackObject(GrOnFlushCallback LEGACY_MESH_DRAW_OP_TEST_EXTERN(AAFlatteningConvexPathOp); LEGACY_MESH_DRAW_OP_TEST_EXTERN(AnalyticRectOp); LEGACY_MESH_DRAW_OP_TEST_EXTERN(DefaultPathOp); -LEGACY_MESH_DRAW_OP_TEST_EXTERN(GrDrawAtlasOp); LEGACY_MESH_DRAW_OP_TEST_EXTERN(TextBlobOp); LEGACY_MESH_DRAW_OP_TEST_EXTERN(VerticesOp); @@ -328,6 +327,7 @@ DRAW_OP_TEST_EXTERN(CircleOp); DRAW_OP_TEST_EXTERN(DashOp); DRAW_OP_TEST_EXTERN(DIEllipseOp); DRAW_OP_TEST_EXTERN(EllipseOp); +DRAW_OP_TEST_EXTERN(GrDrawAtlasOp); DRAW_OP_TEST_EXTERN(NonAAFillRectOp); DRAW_OP_TEST_EXTERN(NonAALatticeOp); DRAW_OP_TEST_EXTERN(NonAAStrokeRectOp); @@ -344,7 +344,6 @@ void GrDrawRandomOp(SkRandom* random, GrRenderTargetContext* renderTargetContext DRAW_OP_TEST_ENTRY(AAFlatteningConvexPathOp), DRAW_OP_TEST_ENTRY(AnalyticRectOp), DRAW_OP_TEST_ENTRY(DefaultPathOp), - DRAW_OP_TEST_ENTRY(GrDrawAtlasOp), DRAW_OP_TEST_ENTRY(TextBlobOp), DRAW_OP_TEST_ENTRY(VerticesOp) }; @@ -359,6 +358,7 @@ void GrDrawRandomOp(SkRandom* random, GrRenderTargetContext* renderTargetContext DRAW_OP_TEST_ENTRY(DashOp), DRAW_OP_TEST_ENTRY(DIEllipseOp), DRAW_OP_TEST_ENTRY(EllipseOp), + DRAW_OP_TEST_ENTRY(GrDrawAtlasOp), DRAW_OP_TEST_ENTRY(NonAAFillRectOp), DRAW_OP_TEST_ENTRY(NonAALatticeOp), DRAW_OP_TEST_ENTRY(NonAAStrokeRectOp),