aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Brian Salomon <bsalomon@google.com>2017-05-15 16:45:49 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-05-15 21:11:41 +0000
commit05441c40d628f077a92f91bd73bb3ec970ba6f00 (patch)
tree3aff6d30351177e21cba75996aa39eb477231f33 /src
parentab1a34670e553615a95891364113725a104d96cd (diff)
Convert GrOvalOpFactory from GrLegacyMeshDrawOp to GrMeshDrawOp using GrSimpleDrawOpHelper.
Change-Id: Ib9f59ddf1c2c3f2bd0004ae16f842e52f45df8c9 Reviewed-on: https://skia-review.googlesource.com/16832 Commit-Queue: Brian Salomon <bsalomon@google.com> Reviewed-by: Brian Osman <brianosman@google.com>
Diffstat (limited to 'src')
-rw-r--r--src/gpu/GrRenderTargetContext.cpp49
-rw-r--r--src/gpu/ops/GrOvalOpFactory.cpp886
-rw-r--r--src/gpu/ops/GrOvalOpFactory.h41
-rw-r--r--src/gpu/ops/GrSimpleMeshDrawOpHelper.h15
4 files changed, 511 insertions, 480 deletions
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp
index f622053049..0076812845 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -962,16 +962,14 @@ void GrRenderTargetContext::drawRRect(const GrClip& origClip,
GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
if (GrAAType::kCoverage == aaType) {
const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
- std::unique_ptr<GrLegacyMeshDrawOp> op =
- GrOvalOpFactory::MakeRRectOp(paint.getColor(),
- paint.usesDistanceVectorField(),
- viewMatrix,
- rrect,
- stroke,
- shaderCaps);
+ std::unique_ptr<GrDrawOp> op = GrOvalOpFactory::MakeRRectOp(std::move(paint),
+ paint.usesDistanceVectorField(),
+ viewMatrix,
+ rrect,
+ stroke,
+ shaderCaps);
if (op) {
- GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
- this->addLegacyMeshDrawOp(std::move(pipelineBuilder), *clip, std::move(op));
+ this->addDrawOp(*clip, std::move(op));
return;
}
}
@@ -1185,11 +1183,10 @@ void GrRenderTargetContext::drawOval(const GrClip& clip,
GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
if (GrAAType::kCoverage == aaType) {
const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
- std::unique_ptr<GrLegacyMeshDrawOp> op =
- GrOvalOpFactory::MakeOvalOp(paint.getColor(), viewMatrix, oval, stroke, shaderCaps);
+ std::unique_ptr<GrDrawOp> op =
+ GrOvalOpFactory::MakeOvalOp(std::move(paint), viewMatrix, oval, stroke, shaderCaps);
if (op) {
- GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
- this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
+ this->addDrawOp(clip, std::move(op));
return;
}
}
@@ -1219,17 +1216,16 @@ void GrRenderTargetContext::drawArc(const GrClip& clip,
GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
if (GrAAType::kCoverage == aaType) {
const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
- std::unique_ptr<GrLegacyMeshDrawOp> op = GrOvalOpFactory::MakeArcOp(paint.getColor(),
- viewMatrix,
- oval,
- startAngle,
- sweepAngle,
- useCenter,
- style,
- shaderCaps);
+ std::unique_ptr<GrDrawOp> op = GrOvalOpFactory::MakeArcOp(std::move(paint),
+ viewMatrix,
+ oval,
+ startAngle,
+ sweepAngle,
+ useCenter,
+ style,
+ shaderCaps);
if (op) {
- GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
- this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
+ this->addDrawOp(clip, std::move(op));
return;
}
}
@@ -1371,11 +1367,10 @@ void GrRenderTargetContext::drawPath(const GrClip& clip,
if (isOval && !path.isInverseFillType()) {
const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
- std::unique_ptr<GrLegacyMeshDrawOp> op = GrOvalOpFactory::MakeOvalOp(
- paint.getColor(), viewMatrix, ovalRect, style.strokeRec(), shaderCaps);
+ std::unique_ptr<GrDrawOp> op = GrOvalOpFactory::MakeOvalOp(
+ std::move(paint), viewMatrix, ovalRect, style.strokeRec(), shaderCaps);
if (op) {
- GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
- this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
+ this->addDrawOp(clip, std::move(op));
return;
}
}
diff --git a/src/gpu/ops/GrOvalOpFactory.cpp b/src/gpu/ops/GrOvalOpFactory.cpp
index a8081826df..5110ccfb40 100644
--- a/src/gpu/ops/GrOvalOpFactory.cpp
+++ b/src/gpu/ops/GrOvalOpFactory.cpp
@@ -6,7 +6,6 @@
*/
#include "GrOvalOpFactory.h"
-
#include "GrDrawOpTest.h"
#include "GrGeometryProcessor.h"
#include "GrOpFlushState.h"
@@ -24,8 +23,7 @@
#include "glsl/GrGLSLVarying.h"
#include "glsl/GrGLSLVertexShaderBuilder.h"
#include "ops/GrMeshDrawOp.h"
-
-// TODO(joshualitt) - Break this file up during GrOp post implementation cleanup
+#include "ops/GrSimpleMeshDrawOpHelper.h"
namespace {
@@ -608,7 +606,10 @@ static const uint16_t* circle_type_to_indices(bool stroked) {
///////////////////////////////////////////////////////////////////////////////
-class CircleOp final : public GrLegacyMeshDrawOp {
+class CircleOp final : public GrMeshDrawOp {
+private:
+ using Helper = GrSimpleMeshDrawOpHelper;
+
public:
DEFINE_OP_CLASS_ID
@@ -618,15 +619,15 @@ public:
SkScalar fSweepAngleRadians;
bool fUseCenter;
};
- static std::unique_ptr<GrLegacyMeshDrawOp> Make(GrColor color, const SkMatrix& viewMatrix,
- SkPoint center, SkScalar radius,
- const GrStyle& style,
- const ArcParams* arcParams = nullptr) {
+
+ static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint, const SkMatrix& viewMatrix,
+ SkPoint center, SkScalar radius, const GrStyle& style,
+ const ArcParams* arcParams = nullptr) {
SkASSERT(circle_stays_circle(viewMatrix));
- const SkStrokeRec& stroke = style.strokeRec();
if (style.hasPathEffect()) {
return nullptr;
}
+ const SkStrokeRec& stroke = style.strokeRec();
SkStrokeRec::Style recStyle = stroke.getStyle();
if (arcParams) {
// Arc support depends on the style.
@@ -646,6 +647,15 @@ public:
break;
}
}
+ return Helper::FactoryHelper<CircleOp>(std::move(paint), viewMatrix, center, radius, style,
+ arcParams);
+ }
+
+ CircleOp(const Helper::MakeArgs& helperArgs, GrColor color, const SkMatrix& viewMatrix,
+ SkPoint center, SkScalar radius, const GrStyle& style, const ArcParams* arcParams)
+ : GrMeshDrawOp(ClassID()), fHelper(helperArgs, GrAAType::kCoverage) {
+ const SkStrokeRec& stroke = style.strokeRec();
+ SkStrokeRec::Style recStyle = stroke.getStyle();
viewMatrix.mapPoints(&center, 1);
radius = viewMatrix.mapRadius(radius);
@@ -678,8 +688,7 @@ public:
outerRadius += SK_ScalarHalf;
innerRadius -= SK_ScalarHalf;
bool stroked = isStrokeOnly && innerRadius > 0.0f;
- std::unique_ptr<CircleOp> op(new CircleOp());
- op->fViewMatrixIfUsingLocalCoords = viewMatrix;
+ fViewMatrixIfUsingLocalCoords = viewMatrix;
// This makes every point fully inside the intersection plane.
static constexpr SkScalar kUnusedIsectPlane[] = {0.f, 0.f, 1.f};
@@ -710,9 +719,9 @@ public:
} else {
norm1.negate();
}
- op->fClipPlane = true;
+ fClipPlane = true;
if (SkScalarAbs(arcParams->fSweepAngleRadians) > SK_ScalarPI) {
- op->fGeoData.emplace_back(Geometry{
+ fCircles.emplace_back(Circle{
color,
innerRadius,
outerRadius,
@@ -721,10 +730,10 @@ public:
{norm1.fX, norm1.fY, 0.5f},
devBounds,
stroked});
- op->fClipPlaneIsect = false;
- op->fClipPlaneUnion = true;
+ fClipPlaneIsect = false;
+ fClipPlaneUnion = true;
} else {
- op->fGeoData.emplace_back(Geometry{
+ fCircles.emplace_back(Circle{
color,
innerRadius,
outerRadius,
@@ -733,8 +742,8 @@ public:
{kUnusedUnionPlane[0], kUnusedUnionPlane[1], kUnusedUnionPlane[2]},
devBounds,
stroked});
- op->fClipPlaneIsect = true;
- op->fClipPlaneUnion = false;
+ fClipPlaneIsect = true;
+ fClipPlaneUnion = false;
}
} else {
// We clip to a secant of the original circle.
@@ -747,78 +756,69 @@ public:
}
SkScalar d = -norm.dot(startPoint) + 0.5f;
- op->fGeoData.emplace_back(
- Geometry{color,
- innerRadius,
- outerRadius,
- {norm.fX, norm.fY, d},
- {kUnusedIsectPlane[0], kUnusedIsectPlane[1], kUnusedIsectPlane[2]},
- {kUnusedUnionPlane[0], kUnusedUnionPlane[1], kUnusedUnionPlane[2]},
- devBounds,
- stroked});
- op->fClipPlane = true;
- op->fClipPlaneIsect = false;
- op->fClipPlaneUnion = false;
+ fCircles.emplace_back(
+ Circle{color,
+ innerRadius,
+ outerRadius,
+ {norm.fX, norm.fY, d},
+ {kUnusedIsectPlane[0], kUnusedIsectPlane[1], kUnusedIsectPlane[2]},
+ {kUnusedUnionPlane[0], kUnusedUnionPlane[1], kUnusedUnionPlane[2]},
+ devBounds,
+ stroked});
+ fClipPlane = true;
+ fClipPlaneIsect = false;
+ fClipPlaneUnion = false;
}
} else {
- op->fGeoData.emplace_back(
- Geometry{color,
- innerRadius,
- outerRadius,
- {kUnusedIsectPlane[0], kUnusedIsectPlane[1], kUnusedIsectPlane[2]},
- {kUnusedIsectPlane[0], kUnusedIsectPlane[1], kUnusedIsectPlane[2]},
- {kUnusedUnionPlane[0], kUnusedUnionPlane[1], kUnusedUnionPlane[2]},
- devBounds,
- stroked});
- op->fClipPlane = false;
- op->fClipPlaneIsect = false;
- op->fClipPlaneUnion = false;
+ fCircles.emplace_back(
+ Circle{color,
+ innerRadius,
+ outerRadius,
+ {kUnusedIsectPlane[0], kUnusedIsectPlane[1], kUnusedIsectPlane[2]},
+ {kUnusedIsectPlane[0], kUnusedIsectPlane[1], kUnusedIsectPlane[2]},
+ {kUnusedUnionPlane[0], kUnusedUnionPlane[1], kUnusedUnionPlane[2]},
+ devBounds,
+ stroked});
+ fClipPlane = false;
+ fClipPlaneIsect = false;
+ fClipPlaneUnion = false;
}
// Use the original radius and stroke radius for the bounds so that it does not include the
// AA bloat.
radius += halfWidth;
- op->setBounds(
+ this->setBounds(
{center.fX - radius, center.fY - radius, center.fX + radius, center.fY + radius},
HasAABloat::kYes, IsZeroArea::kNo);
- op->fVertCount = circle_type_to_vert_count(stroked);
- op->fIndexCount = circle_type_to_index_count(stroked);
- op->fAllFill = !stroked;
- return std::move(op);
+ fVertCount = circle_type_to_vert_count(stroked);
+ fIndexCount = circle_type_to_index_count(stroked);
+ fAllFill = !stroked;
}
const char* name() const override { return "CircleOp"; }
SkString dumpInfo() const override {
SkString string;
- for (int i = 0; i < fGeoData.count(); ++i) {
+ for (int i = 0; i < fCircles.count(); ++i) {
string.appendf(
"Color: 0x%08x Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f],"
"InnerRad: %.2f, OuterRad: %.2f\n",
- fGeoData[i].fColor, fGeoData[i].fDevBounds.fLeft, fGeoData[i].fDevBounds.fTop,
- fGeoData[i].fDevBounds.fRight, fGeoData[i].fDevBounds.fBottom,
- fGeoData[i].fInnerRadius, fGeoData[i].fOuterRadius);
+ fCircles[i].fColor, fCircles[i].fDevBounds.fLeft, fCircles[i].fDevBounds.fTop,
+ fCircles[i].fDevBounds.fRight, fCircles[i].fDevBounds.fBottom,
+ fCircles[i].fInnerRadius, fCircles[i].fOuterRadius);
}
- string.append(DumpPipelineInfo(*this->pipeline()));
string.append(INHERITED::dumpInfo());
return string;
}
-private:
- CircleOp() : INHERITED(ClassID()) {}
-
- void getProcessorAnalysisInputs(GrProcessorAnalysisColor* color,
- GrProcessorAnalysisCoverage* coverage) const override {
- color->setToConstant(fGeoData[0].fColor);
- *coverage = GrProcessorAnalysisCoverage::kSingleChannel;
+ bool xpRequiresDstTexture(const GrCaps& caps, const GrAppliedClip* clip) override {
+ GrColor* color = &fCircles.front().fColor;
+ return fHelper.xpRequiresDstTexture(caps, clip, GrProcessorAnalysisCoverage::kSingleChannel,
+ color);
}
- void applyPipelineOptimizations(const PipelineOptimizations& optimizations) override {
- optimizations.getOverrideColorIfSet(&fGeoData[0].fColor);
- if (!optimizations.readsLocalCoords()) {
- fViewMatrixIfUsingLocalCoords.reset();
- }
- }
+ FixedFunctionFlags fixedFunctionFlags() const override { return fHelper.fixedFunctionFlags(); }
+private:
void onPrepareDraws(Target* target) const override {
SkMatrix localMatrix;
if (!fViewMatrixIfUsingLocalCoords.invert(&localMatrix)) {
@@ -839,7 +839,6 @@ private:
SkScalar fHalfPlanes[3][3];
};
- int instanceCount = fGeoData.count();
size_t vertexStride = gp->getVertexStride();
SkASSERT(vertexStride ==
sizeof(CircleVertex) - (fClipPlane ? 0 : 3 * sizeof(SkScalar)) -
@@ -864,14 +863,12 @@ private:
}
int currStartVertex = 0;
- for (int i = 0; i < instanceCount; i++) {
- const Geometry& geom = fGeoData[i];
-
- GrColor color = geom.fColor;
- SkScalar innerRadius = geom.fInnerRadius;
- SkScalar outerRadius = geom.fOuterRadius;
+ for (const auto& circle : fCircles) {
+ SkScalar innerRadius = circle.fInnerRadius;
+ SkScalar outerRadius = circle.fOuterRadius;
+ GrColor color = circle.fColor;
+ const SkRect& bounds = circle.fDevBounds;
- const SkRect& bounds = geom.fDevBounds;
CircleVertex* v0 = reinterpret_cast<CircleVertex*>(vertices + 0 * vertexStride);
CircleVertex* v1 = reinterpret_cast<CircleVertex*>(vertices + 1 * vertexStride);
CircleVertex* v2 = reinterpret_cast<CircleVertex*>(vertices + 2 * vertexStride);
@@ -937,39 +934,39 @@ private:
v7->fInnerRadius = innerRadius;
if (fClipPlane) {
- memcpy(v0->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar));
- memcpy(v1->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar));
- memcpy(v2->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar));
- memcpy(v3->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar));
- memcpy(v4->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar));
- memcpy(v5->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar));
- memcpy(v6->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar));
- memcpy(v7->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar));
+ memcpy(v0->fHalfPlanes[0], circle.fClipPlane, 3 * sizeof(SkScalar));
+ memcpy(v1->fHalfPlanes[0], circle.fClipPlane, 3 * sizeof(SkScalar));
+ memcpy(v2->fHalfPlanes[0], circle.fClipPlane, 3 * sizeof(SkScalar));
+ memcpy(v3->fHalfPlanes[0], circle.fClipPlane, 3 * sizeof(SkScalar));
+ memcpy(v4->fHalfPlanes[0], circle.fClipPlane, 3 * sizeof(SkScalar));
+ memcpy(v5->fHalfPlanes[0], circle.fClipPlane, 3 * sizeof(SkScalar));
+ memcpy(v6->fHalfPlanes[0], circle.fClipPlane, 3 * sizeof(SkScalar));
+ memcpy(v7->fHalfPlanes[0], circle.fClipPlane, 3 * sizeof(SkScalar));
}
int unionIdx = 1;
if (fClipPlaneIsect) {
- memcpy(v0->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar));
- memcpy(v1->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar));
- memcpy(v2->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar));
- memcpy(v3->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar));
- memcpy(v4->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar));
- memcpy(v5->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar));
- memcpy(v6->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar));
- memcpy(v7->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar));
+ memcpy(v0->fHalfPlanes[1], circle.fIsectPlane, 3 * sizeof(SkScalar));
+ memcpy(v1->fHalfPlanes[1], circle.fIsectPlane, 3 * sizeof(SkScalar));
+ memcpy(v2->fHalfPlanes[1], circle.fIsectPlane, 3 * sizeof(SkScalar));
+ memcpy(v3->fHalfPlanes[1], circle.fIsectPlane, 3 * sizeof(SkScalar));
+ memcpy(v4->fHalfPlanes[1], circle.fIsectPlane, 3 * sizeof(SkScalar));
+ memcpy(v5->fHalfPlanes[1], circle.fIsectPlane, 3 * sizeof(SkScalar));
+ memcpy(v6->fHalfPlanes[1], circle.fIsectPlane, 3 * sizeof(SkScalar));
+ memcpy(v7->fHalfPlanes[1], circle.fIsectPlane, 3 * sizeof(SkScalar));
unionIdx = 2;
}
if (fClipPlaneUnion) {
- memcpy(v0->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(SkScalar));
- memcpy(v1->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(SkScalar));
- memcpy(v2->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(SkScalar));
- memcpy(v3->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(SkScalar));
- memcpy(v4->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(SkScalar));
- memcpy(v5->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(SkScalar));
- memcpy(v6->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(SkScalar));
- memcpy(v7->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(SkScalar));
+ memcpy(v0->fHalfPlanes[unionIdx], circle.fUnionPlane, 3 * sizeof(SkScalar));
+ memcpy(v1->fHalfPlanes[unionIdx], circle.fUnionPlane, 3 * sizeof(SkScalar));
+ memcpy(v2->fHalfPlanes[unionIdx], circle.fUnionPlane, 3 * sizeof(SkScalar));
+ memcpy(v3->fHalfPlanes[unionIdx], circle.fUnionPlane, 3 * sizeof(SkScalar));
+ memcpy(v4->fHalfPlanes[unionIdx], circle.fUnionPlane, 3 * sizeof(SkScalar));
+ memcpy(v5->fHalfPlanes[unionIdx], circle.fUnionPlane, 3 * sizeof(SkScalar));
+ memcpy(v6->fHalfPlanes[unionIdx], circle.fUnionPlane, 3 * sizeof(SkScalar));
+ memcpy(v7->fHalfPlanes[unionIdx], circle.fUnionPlane, 3 * sizeof(SkScalar));
}
- if (geom.fStroked) {
+ if (circle.fStroked) {
// compute the inner ring
CircleVertex* v0 = reinterpret_cast<CircleVertex*>(vertices + 8 * vertexStride);
CircleVertex* v1 = reinterpret_cast<CircleVertex*>(vertices + 9 * vertexStride);
@@ -983,7 +980,7 @@ private:
// cosine and sine of pi/8
SkScalar c = 0.923579533f;
SkScalar s = 0.382683432f;
- SkScalar r = geom.fInnerRadius;
+ SkScalar r = circle.fInnerRadius;
v0->fPos = center + SkPoint::Make(-s * r, -c * r);
v0->fColor = color;
@@ -1034,36 +1031,36 @@ private:
v7->fInnerRadius = innerRadius;
if (fClipPlane) {
- memcpy(v0->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar));
- memcpy(v1->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar));
- memcpy(v2->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar));
- memcpy(v3->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar));
- memcpy(v4->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar));
- memcpy(v5->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar));
- memcpy(v6->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar));
- memcpy(v7->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar));
+ memcpy(v0->fHalfPlanes[0], circle.fClipPlane, 3 * sizeof(SkScalar));
+ memcpy(v1->fHalfPlanes[0], circle.fClipPlane, 3 * sizeof(SkScalar));
+ memcpy(v2->fHalfPlanes[0], circle.fClipPlane, 3 * sizeof(SkScalar));
+ memcpy(v3->fHalfPlanes[0], circle.fClipPlane, 3 * sizeof(SkScalar));
+ memcpy(v4->fHalfPlanes[0], circle.fClipPlane, 3 * sizeof(SkScalar));
+ memcpy(v5->fHalfPlanes[0], circle.fClipPlane, 3 * sizeof(SkScalar));
+ memcpy(v6->fHalfPlanes[0], circle.fClipPlane, 3 * sizeof(SkScalar));
+ memcpy(v7->fHalfPlanes[0], circle.fClipPlane, 3 * sizeof(SkScalar));
}
int unionIdx = 1;
if (fClipPlaneIsect) {
- memcpy(v0->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar));
- memcpy(v1->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar));
- memcpy(v2->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar));
- memcpy(v3->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar));
- memcpy(v4->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar));
- memcpy(v5->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar));
- memcpy(v6->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar));
- memcpy(v7->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar));
+ memcpy(v0->fHalfPlanes[1], circle.fIsectPlane, 3 * sizeof(SkScalar));
+ memcpy(v1->fHalfPlanes[1], circle.fIsectPlane, 3 * sizeof(SkScalar));
+ memcpy(v2->fHalfPlanes[1], circle.fIsectPlane, 3 * sizeof(SkScalar));
+ memcpy(v3->fHalfPlanes[1], circle.fIsectPlane, 3 * sizeof(SkScalar));
+ memcpy(v4->fHalfPlanes[1], circle.fIsectPlane, 3 * sizeof(SkScalar));
+ memcpy(v5->fHalfPlanes[1], circle.fIsectPlane, 3 * sizeof(SkScalar));
+ memcpy(v6->fHalfPlanes[1], circle.fIsectPlane, 3 * sizeof(SkScalar));
+ memcpy(v7->fHalfPlanes[1], circle.fIsectPlane, 3 * sizeof(SkScalar));
unionIdx = 2;
}
if (fClipPlaneUnion) {
- memcpy(v0->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(SkScalar));
- memcpy(v1->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(SkScalar));
- memcpy(v2->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(SkScalar));
- memcpy(v3->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(SkScalar));
- memcpy(v4->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(SkScalar));
- memcpy(v5->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(SkScalar));
- memcpy(v6->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(SkScalar));
- memcpy(v7->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(SkScalar));
+ memcpy(v0->fHalfPlanes[unionIdx], circle.fUnionPlane, 3 * sizeof(SkScalar));
+ memcpy(v1->fHalfPlanes[unionIdx], circle.fUnionPlane, 3 * sizeof(SkScalar));
+ memcpy(v2->fHalfPlanes[unionIdx], circle.fUnionPlane, 3 * sizeof(SkScalar));
+ memcpy(v3->fHalfPlanes[unionIdx], circle.fUnionPlane, 3 * sizeof(SkScalar));
+ memcpy(v4->fHalfPlanes[unionIdx], circle.fUnionPlane, 3 * sizeof(SkScalar));
+ memcpy(v5->fHalfPlanes[unionIdx], circle.fUnionPlane, 3 * sizeof(SkScalar));
+ memcpy(v6->fHalfPlanes[unionIdx], circle.fUnionPlane, 3 * sizeof(SkScalar));
+ memcpy(v7->fHalfPlanes[unionIdx], circle.fUnionPlane, 3 * sizeof(SkScalar));
}
} else {
// filled
@@ -1074,32 +1071,32 @@ private:
v8->fOuterRadius = outerRadius;
v8->fInnerRadius = innerRadius;
if (fClipPlane) {
- memcpy(v8->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar));
+ memcpy(v8->fHalfPlanes[0], circle.fClipPlane, 3 * sizeof(SkScalar));
}
int unionIdx = 1;
if (fClipPlaneIsect) {
- memcpy(v8->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar));
+ memcpy(v8->fHalfPlanes[1], circle.fIsectPlane, 3 * sizeof(SkScalar));
unionIdx = 2;
}
if (fClipPlaneUnion) {
- memcpy(v8->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(SkScalar));
+ memcpy(v8->fHalfPlanes[unionIdx], circle.fUnionPlane, 3 * sizeof(SkScalar));
}
}
- const uint16_t* primIndices = circle_type_to_indices(geom.fStroked);
- const int primIndexCount = circle_type_to_index_count(geom.fStroked);
+ const uint16_t* primIndices = circle_type_to_indices(circle.fStroked);
+ const int primIndexCount = circle_type_to_index_count(circle.fStroked);
for (int i = 0; i < primIndexCount; ++i) {
*indices++ = primIndices[i] + currStartVertex;
}
- currStartVertex += circle_type_to_vert_count(geom.fStroked);
- vertices += circle_type_to_vert_count(geom.fStroked) * vertexStride;
+ currStartVertex += circle_type_to_vert_count(circle.fStroked);
+ vertices += circle_type_to_vert_count(circle.fStroked) * vertexStride;
}
GrMesh mesh(kTriangles_GrPrimitiveType);
mesh.setIndexed(indexBuffer, fIndexCount, firstIndex);
mesh.setVertices(vertexBuffer, fVertCount, firstVertex);
- target->draw(gp.get(), this->pipeline(), mesh);
+ target->draw(gp.get(), fHelper.makePipeline(target), mesh);
}
bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
@@ -1110,12 +1107,12 @@ private:
return false;
}
- if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
- that->bounds(), caps)) {
+ if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) {
return false;
}
- if (!fViewMatrixIfUsingLocalCoords.cheapEqualTo(that->fViewMatrixIfUsingLocalCoords)) {
+ if (fHelper.usesLocalCoords() &&
+ !fViewMatrixIfUsingLocalCoords.cheapEqualTo(that->fViewMatrixIfUsingLocalCoords)) {
return false;
}
@@ -1125,7 +1122,7 @@ private:
fClipPlaneIsect |= that->fClipPlaneIsect;
fClipPlaneUnion |= that->fClipPlaneUnion;
- fGeoData.push_back_n(that->fGeoData.count(), that->fGeoData.begin());
+ fCircles.push_back_n(that->fCircles.count(), that->fCircles.begin());
this->joinBounds(*that);
fVertCount += that->fVertCount;
fIndexCount += that->fIndexCount;
@@ -1133,7 +1130,7 @@ private:
return true;
}
- struct Geometry {
+ struct Circle {
GrColor fColor;
SkScalar fInnerRadius;
SkScalar fOuterRadius;
@@ -1144,8 +1141,9 @@ private:
bool fStroked;
};
- SkSTArray<1, Geometry, true> fGeoData;
SkMatrix fViewMatrixIfUsingLocalCoords;
+ Helper fHelper;
+ SkSTArray<1, Circle, true> fCircles;
int fVertCount;
int fIndexCount;
bool fAllFill;
@@ -1153,28 +1151,37 @@ private:
bool fClipPlaneIsect;
bool fClipPlaneUnion;
- typedef GrLegacyMeshDrawOp INHERITED;
+ typedef GrMeshDrawOp INHERITED;
};
///////////////////////////////////////////////////////////////////////////////
-class EllipseOp : public GrLegacyMeshDrawOp {
+class EllipseOp : public GrMeshDrawOp {
+private:
+ using Helper = GrSimpleMeshDrawOpHelper;
+
+ struct DeviceSpaceParams {
+ SkPoint fCenter;
+ SkScalar fXRadius;
+ SkScalar fYRadius;
+ SkScalar fInnerXRadius;
+ SkScalar fInnerYRadius;
+ };
+
public:
DEFINE_OP_CLASS_ID
- static std::unique_ptr<GrLegacyMeshDrawOp> Make(GrColor color, const SkMatrix& viewMatrix,
- const SkRect& ellipse,
- const SkStrokeRec& stroke) {
- SkASSERT(viewMatrix.rectStaysRect());
-
+ static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint, const SkMatrix& viewMatrix,
+ const SkRect& ellipse, const SkStrokeRec& stroke) {
+ DeviceSpaceParams params;
// do any matrix crunching before we reset the draw state for device coords
- SkPoint center = SkPoint::Make(ellipse.centerX(), ellipse.centerY());
- viewMatrix.mapPoints(&center, 1);
+ params.fCenter = SkPoint::Make(ellipse.centerX(), ellipse.centerY());
+ viewMatrix.mapPoints(&params.fCenter, 1);
SkScalar ellipseXRadius = SkScalarHalf(ellipse.width());
SkScalar ellipseYRadius = SkScalarHalf(ellipse.height());
- SkScalar xRadius = SkScalarAbs(viewMatrix[SkMatrix::kMScaleX] * ellipseXRadius +
- viewMatrix[SkMatrix::kMSkewX] * ellipseYRadius);
- SkScalar yRadius = SkScalarAbs(viewMatrix[SkMatrix::kMSkewY] * ellipseXRadius +
- viewMatrix[SkMatrix::kMScaleY] * ellipseYRadius);
+ params.fXRadius = SkScalarAbs(viewMatrix[SkMatrix::kMScaleX] * ellipseXRadius +
+ viewMatrix[SkMatrix::kMSkewX] * ellipseYRadius);
+ params.fYRadius = SkScalarAbs(viewMatrix[SkMatrix::kMSkewY] * ellipseXRadius +
+ viewMatrix[SkMatrix::kMScaleY] * ellipseYRadius);
// do (potentially) anisotropic mapping of stroke
SkVector scaledStroke;
@@ -1189,8 +1196,8 @@ public:
SkStrokeRec::kStroke_Style == style || SkStrokeRec::kHairline_Style == style;
bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == style;
- SkScalar innerXRadius = 0;
- SkScalar innerYRadius = 0;
+ params.fInnerXRadius = 0;
+ params.fInnerYRadius = 0;
if (hasStroke) {
if (SkScalarNearlyZero(scaledStroke.length())) {
scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf);
@@ -1200,42 +1207,52 @@ public:
// we only handle thick strokes for near-circular ellipses
if (scaledStroke.length() > SK_ScalarHalf &&
- (SK_ScalarHalf * xRadius > yRadius || SK_ScalarHalf * yRadius > xRadius)) {
+ (0.5f * params.fXRadius > params.fYRadius ||
+ 0.5f * params.fYRadius > params.fXRadius)) {
return nullptr;
}
// we don't handle it if curvature of the stroke is less than curvature of the ellipse
- if (scaledStroke.fX * (yRadius * yRadius) <
- (scaledStroke.fY * scaledStroke.fY) * xRadius ||
- scaledStroke.fY * (xRadius * xRadius) <
- (scaledStroke.fX * scaledStroke.fX) * yRadius) {
+ if (scaledStroke.fX * (params.fXRadius * params.fYRadius) <
+ (scaledStroke.fY * scaledStroke.fY) * params.fXRadius ||
+ scaledStroke.fY * (params.fXRadius * params.fXRadius) <
+ (scaledStroke.fX * scaledStroke.fX) * params.fYRadius) {
return nullptr;
}
// this is legit only if scale & translation (which should be the case at the moment)
if (isStrokeOnly) {
- innerXRadius = xRadius - scaledStroke.fX;
- innerYRadius = yRadius - scaledStroke.fY;
+ params.fInnerXRadius = params.fXRadius - scaledStroke.fX;
+ params.fInnerYRadius = params.fYRadius - scaledStroke.fY;
}
- xRadius += scaledStroke.fX;
- yRadius += scaledStroke.fY;
+ params.fXRadius += scaledStroke.fX;
+ params.fYRadius += scaledStroke.fY;
}
+ return Helper::FactoryHelper<EllipseOp>(std::move(paint), viewMatrix, params, stroke);
+ }
+
+ EllipseOp(const Helper::MakeArgs& helperArgs, GrColor color, const SkMatrix& viewMatrix,
+ const DeviceSpaceParams& params, const SkStrokeRec& stroke)
+ : INHERITED(ClassID()), fHelper(helperArgs, GrAAType::kCoverage) {
+ SkStrokeRec::Style style = stroke.getStyle();
+ bool isStrokeOnly =
+ SkStrokeRec::kStroke_Style == style || SkStrokeRec::kHairline_Style == style;
- std::unique_ptr<EllipseOp> op(new EllipseOp());
- op->fGeoData.emplace_back(
- Geometry{color, xRadius, yRadius, innerXRadius, innerYRadius,
- SkRect::MakeLTRB(center.fX - xRadius, center.fY - yRadius,
- center.fX + xRadius, center.fY + yRadius)});
+ fEllipses.emplace_back(Ellipse{color, params.fXRadius, params.fYRadius,
+ params.fInnerXRadius, params.fInnerYRadius,
+ SkRect::MakeLTRB(params.fCenter.fX - params.fXRadius,
+ params.fCenter.fY - params.fYRadius,
+ params.fCenter.fX + params.fXRadius,
+ params.fCenter.fY + params.fYRadius)});
- op->setBounds(op->fGeoData.back().fDevBounds, HasAABloat::kYes, IsZeroArea::kNo);
+ this->setBounds(fEllipses.back().fDevBounds, HasAABloat::kYes, IsZeroArea::kNo);
// Outset bounds to include half-pixel width antialiasing.
- op->fGeoData[0].fDevBounds.outset(SK_ScalarHalf, SK_ScalarHalf);
+ fEllipses[0].fDevBounds.outset(SK_ScalarHalf, SK_ScalarHalf);
- op->fStroked = isStrokeOnly && innerXRadius > 0 && innerYRadius > 0;
- op->fViewMatrixIfUsingLocalCoords = viewMatrix;
- return std::move(op);
+ fStroked = isStrokeOnly && params.fInnerXRadius > 0 && params.fInnerYRadius > 0;
+ fViewMatrixIfUsingLocalCoords = viewMatrix;
}
const char* name() const override { return "EllipseOp"; }
@@ -1243,7 +1260,7 @@ public:
SkString dumpInfo() const override {
SkString string;
string.appendf("Stroked: %d\n", fStroked);
- for (const auto& geo : fGeoData) {
+ for (const auto& geo : fEllipses) {
string.appendf(
"Color: 0x%08x Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f], "
"XRad: %.2f, YRad: %.2f, InnerXRad: %.2f, InnerYRad: %.2f\n",
@@ -1251,26 +1268,19 @@ public:
geo.fDevBounds.fBottom, geo.fXRadius, geo.fYRadius, geo.fInnerXRadius,
geo.fInnerYRadius);
}
- string.append(DumpPipelineInfo(*this->pipeline()));
string.append(INHERITED::dumpInfo());
return string;
}
-private:
- EllipseOp() : INHERITED(ClassID()) {}
-
- void getProcessorAnalysisInputs(GrProcessorAnalysisColor* color,
- GrProcessorAnalysisCoverage* coverage) const override {
- color->setToConstant(fGeoData[0].fColor);
- *coverage = GrProcessorAnalysisCoverage::kSingleChannel;
+ bool xpRequiresDstTexture(const GrCaps& caps, const GrAppliedClip* clip) override {
+ GrColor* color = &fEllipses.front().fColor;
+ return fHelper.xpRequiresDstTexture(caps, clip, GrProcessorAnalysisCoverage::kSingleChannel,
+ color);
}
- void applyPipelineOptimizations(const PipelineOptimizations& optimizations) override {
- if (!optimizations.readsLocalCoords()) {
- fViewMatrixIfUsingLocalCoords.reset();
- }
- }
+ FixedFunctionFlags fixedFunctionFlags() const override { return fHelper.fixedFunctionFlags(); }
+private:
void onPrepareDraws(Target* target) const override {
SkMatrix localMatrix;
if (!fViewMatrixIfUsingLocalCoords.invert(&localMatrix)) {
@@ -1280,55 +1290,50 @@ private:
// Setup geometry processor
sk_sp<GrGeometryProcessor> gp(new EllipseGeometryProcessor(fStroked, localMatrix));
- int instanceCount = fGeoData.count();
QuadHelper helper;
size_t vertexStride = gp->getVertexStride();
SkASSERT(vertexStride == sizeof(EllipseVertex));
- EllipseVertex* verts =
- reinterpret_cast<EllipseVertex*>(helper.init(target, vertexStride, instanceCount));
+ EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(
+ helper.init(target, vertexStride, fEllipses.count()));
if (!verts) {
return;
}
- for (int i = 0; i < instanceCount; i++) {
- const Geometry& geom = fGeoData[i];
-
- GrColor color = geom.fColor;
- SkScalar xRadius = geom.fXRadius;
- SkScalar yRadius = geom.fYRadius;
+ for (const auto& ellipse : fEllipses) {
+ GrColor color = ellipse.fColor;
+ SkScalar xRadius = ellipse.fXRadius;
+ SkScalar yRadius = ellipse.fYRadius;
// Compute the reciprocals of the radii here to save time in the shader
SkScalar xRadRecip = SkScalarInvert(xRadius);
SkScalar yRadRecip = SkScalarInvert(yRadius);
- SkScalar xInnerRadRecip = SkScalarInvert(geom.fInnerXRadius);
- SkScalar yInnerRadRecip = SkScalarInvert(geom.fInnerYRadius);
-
- const SkRect& bounds = geom.fDevBounds;
+ SkScalar xInnerRadRecip = SkScalarInvert(ellipse.fInnerXRadius);
+ SkScalar yInnerRadRecip = SkScalarInvert(ellipse.fInnerYRadius);
// fOffsets are expanded from xyRadii to include the half-pixel antialiasing width.
SkScalar xMaxOffset = xRadius + SK_ScalarHalf;
SkScalar yMaxOffset = yRadius + SK_ScalarHalf;
// The inner radius in the vertex data must be specified in normalized space.
- verts[0].fPos = SkPoint::Make(bounds.fLeft, bounds.fTop);
+ verts[0].fPos = SkPoint::Make(ellipse.fDevBounds.fLeft, ellipse.fDevBounds.fTop);
verts[0].fColor = color;
verts[0].fOffset = SkPoint::Make(-xMaxOffset, -yMaxOffset);
verts[0].fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip);
verts[0].fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip);
- verts[1].fPos = SkPoint::Make(bounds.fLeft, bounds.fBottom);
+ verts[1].fPos = SkPoint::Make(ellipse.fDevBounds.fLeft, ellipse.fDevBounds.fBottom);
verts[1].fColor = color;
verts[1].fOffset = SkPoint::Make(-xMaxOffset, yMaxOffset);
verts[1].fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip);
verts[1].fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip);
- verts[2].fPos = SkPoint::Make(bounds.fRight, bounds.fBottom);
+ verts[2].fPos = SkPoint::Make(ellipse.fDevBounds.fRight, ellipse.fDevBounds.fBottom);
verts[2].fColor = color;
verts[2].fOffset = SkPoint::Make(xMaxOffset, yMaxOffset);
verts[2].fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip);
verts[2].fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip);
- verts[3].fPos = SkPoint::Make(bounds.fRight, bounds.fTop);
+ verts[3].fPos = SkPoint::Make(ellipse.fDevBounds.fRight, ellipse.fDevBounds.fTop);
verts[3].fColor = color;
verts[3].fOffset = SkPoint::Make(xMaxOffset, -yMaxOffset);
verts[3].fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip);
@@ -1336,14 +1341,13 @@ private:
verts += kVerticesPerQuad;
}
- helper.recordDraw(target, gp.get(), this->pipeline());
+ helper.recordDraw(target, gp.get(), fHelper.makePipeline(target));
}
bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
EllipseOp* that = t->cast<EllipseOp>();
- if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
- that->bounds(), caps)) {
+ if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) {
return false;
}
@@ -1351,16 +1355,17 @@ private:
return false;
}
- if (!fViewMatrixIfUsingLocalCoords.cheapEqualTo(that->fViewMatrixIfUsingLocalCoords)) {
+ if (fHelper.usesLocalCoords() &&
+ !fViewMatrixIfUsingLocalCoords.cheapEqualTo(that->fViewMatrixIfUsingLocalCoords)) {
return false;
}
- fGeoData.push_back_n(that->fGeoData.count(), that->fGeoData.begin());
+ fEllipses.push_back_n(that->fEllipses.count(), that->fEllipses.begin());
this->joinBounds(*that);
return true;
}
- struct Geometry {
+ struct Ellipse {
GrColor fColor;
SkScalar fXRadius;
SkScalar fYRadius;
@@ -1369,36 +1374,48 @@ private:
SkRect fDevBounds;
};
- bool fStroked;
SkMatrix fViewMatrixIfUsingLocalCoords;
- SkSTArray<1, Geometry, true> fGeoData;
+ Helper fHelper;
+ bool fStroked;
+ SkSTArray<1, Ellipse, true> fEllipses;
- typedef GrLegacyMeshDrawOp INHERITED;
+ typedef GrMeshDrawOp INHERITED;
};
/////////////////////////////////////////////////////////////////////////////////////////////////
-class DIEllipseOp : public GrLegacyMeshDrawOp {
+class DIEllipseOp : public GrMeshDrawOp {
+private:
+ using Helper = GrSimpleMeshDrawOpHelper;
+
+ struct DeviceSpaceParams {
+ SkPoint fCenter;
+ SkScalar fXRadius;
+ SkScalar fYRadius;
+ SkScalar fInnerXRadius;
+ SkScalar fInnerYRadius;
+ DIEllipseStyle fStyle;
+ };
+
public:
DEFINE_OP_CLASS_ID
- static std::unique_ptr<GrLegacyMeshDrawOp> Make(GrColor color,
- const SkMatrix& viewMatrix,
- const SkRect& ellipse,
- const SkStrokeRec& stroke) {
- SkPoint center = SkPoint::Make(ellipse.centerX(), ellipse.centerY());
- SkScalar xRadius = SkScalarHalf(ellipse.width());
- SkScalar yRadius = SkScalarHalf(ellipse.height());
+ static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint, const SkMatrix& viewMatrix,
+ const SkRect& ellipse, const SkStrokeRec& stroke) {
+ DeviceSpaceParams params;
+ params.fCenter = SkPoint::Make(ellipse.centerX(), ellipse.centerY());
+ params.fXRadius = SkScalarHalf(ellipse.width());
+ params.fYRadius = SkScalarHalf(ellipse.height());
SkStrokeRec::Style style = stroke.getStyle();
- DIEllipseStyle dieStyle = (SkStrokeRec::kStroke_Style == style)
- ? DIEllipseStyle::kStroke
- : (SkStrokeRec::kHairline_Style == style)
- ? DIEllipseStyle::kHairline
- : DIEllipseStyle::kFill;
-
- SkScalar innerXRadius = 0;
- SkScalar innerYRadius = 0;
+ params.fStyle = (SkStrokeRec::kStroke_Style == style)
+ ? DIEllipseStyle::kStroke
+ : (SkStrokeRec::kHairline_Style == style)
+ ? DIEllipseStyle::kHairline
+ : DIEllipseStyle::kFill;
+
+ params.fInnerXRadius = 0;
+ params.fInnerYRadius = 0;
if (SkStrokeRec::kFill_Style != style && SkStrokeRec::kHairline_Style != style) {
SkScalar strokeWidth = stroke.getWidth();
@@ -1410,30 +1427,40 @@ public:
// we only handle thick strokes for near-circular ellipses
if (strokeWidth > SK_ScalarHalf &&
- (SK_ScalarHalf * xRadius > yRadius || SK_ScalarHalf * yRadius > xRadius)) {
+ (SK_ScalarHalf * params.fXRadius > params.fYRadius ||
+ SK_ScalarHalf * params.fYRadius > params.fXRadius)) {
return nullptr;
}
// we don't handle it if curvature of the stroke is less than curvature of the ellipse
- if (strokeWidth * (yRadius * yRadius) < (strokeWidth * strokeWidth) * xRadius ||
- strokeWidth * (xRadius * xRadius) < (strokeWidth * strokeWidth) * yRadius) {
+ if (strokeWidth * (params.fYRadius * params.fYRadius) <
+ (strokeWidth * strokeWidth) * params.fXRadius) {
+ return nullptr;
+ }
+ if (strokeWidth * (params.fXRadius * params.fXRadius) <
+ (strokeWidth * strokeWidth) * params.fYRadius) {
return nullptr;
}
// set inner radius (if needed)
if (SkStrokeRec::kStroke_Style == style) {
- innerXRadius = xRadius - strokeWidth;
- innerYRadius = yRadius - strokeWidth;
+ params.fInnerXRadius = params.fXRadius - strokeWidth;
+ params.fInnerYRadius = params.fYRadius - strokeWidth;
}
- xRadius += strokeWidth;
- yRadius += strokeWidth;
+ params.fXRadius += strokeWidth;
+ params.fYRadius += strokeWidth;
}
- if (DIEllipseStyle::kStroke == dieStyle) {
- dieStyle = (innerXRadius > 0 && innerYRadius > 0) ? DIEllipseStyle::kStroke
- : DIEllipseStyle::kFill;
+ if (DIEllipseStyle::kStroke == params.fStyle &&
+ (params.fInnerXRadius <= 0 || params.fInnerYRadius <= 0)) {
+ params.fStyle = DIEllipseStyle::kFill;
}
+ return Helper::FactoryHelper<DIEllipseOp>(std::move(paint), params, viewMatrix);
+ }
+ DIEllipseOp(Helper::MakeArgs& helperArgs, GrColor color, const DeviceSpaceParams& params,
+ const SkMatrix& viewMatrix)
+ : INHERITED(ClassID()), fHelper(helperArgs, GrAAType::kCoverage) {
// This expands the outer rect so that after CTM we end up with a half-pixel border
SkScalar a = viewMatrix[SkMatrix::kMScaleX];
SkScalar b = viewMatrix[SkMatrix::kMSkewX];
@@ -1442,22 +1469,22 @@ public:
SkScalar geoDx = SK_ScalarHalf / SkScalarSqrt(a * a + c * c);
SkScalar geoDy = SK_ScalarHalf / SkScalarSqrt(b * b + d * d);
- std::unique_ptr<DIEllipseOp> op(new DIEllipseOp());
- op->fGeoData.emplace_back(Geometry{
- viewMatrix, color, xRadius, yRadius, innerXRadius, innerYRadius, geoDx, geoDy,
- dieStyle,
- SkRect::MakeLTRB(center.fX - xRadius - geoDx, center.fY - yRadius - geoDy,
- center.fX + xRadius + geoDx, center.fY + yRadius + geoDy)});
- op->setTransformedBounds(op->fGeoData[0].fBounds, viewMatrix, HasAABloat::kYes,
- IsZeroArea::kNo);
- return std::move(op);
+ fEllipses.emplace_back(
+ Ellipse{viewMatrix, color, params.fXRadius, params.fYRadius, params.fInnerXRadius,
+ params.fInnerYRadius, geoDx, geoDy, params.fStyle,
+ SkRect::MakeLTRB(params.fCenter.fX - params.fXRadius - geoDx,
+ params.fCenter.fY - params.fYRadius - geoDy,
+ params.fCenter.fX + params.fXRadius + geoDx,
+ params.fCenter.fY + params.fYRadius + geoDy)});
+ this->setTransformedBounds(fEllipses[0].fBounds, viewMatrix, HasAABloat::kYes,
+ IsZeroArea::kNo);
}
const char* name() const override { return "DIEllipseOp"; }
SkString dumpInfo() const override {
SkString string;
- for (const auto& geo : fGeoData) {
+ for (const auto& geo : fEllipses) {
string.appendf(
"Color: 0x%08x Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f], XRad: %.2f, "
"YRad: %.2f, InnerXRad: %.2f, InnerYRad: %.2f, GeoDX: %.2f, "
@@ -1466,55 +1493,46 @@ public:
geo.fBounds.fBottom, geo.fXRadius, geo.fYRadius, geo.fInnerXRadius,
geo.fInnerYRadius, geo.fGeoDx, geo.fGeoDy);
}
- string.append(DumpPipelineInfo(*this->pipeline()));
string.append(INHERITED::dumpInfo());
return string;
}
-private:
- DIEllipseOp() : INHERITED(ClassID()) {}
-
- void getProcessorAnalysisInputs(GrProcessorAnalysisColor* color,
- GrProcessorAnalysisCoverage* coverage) const override {
- color->setToConstant(fGeoData[0].fColor);
- *coverage = GrProcessorAnalysisCoverage::kSingleChannel;
+ bool xpRequiresDstTexture(const GrCaps& caps, const GrAppliedClip* clip) override {
+ GrColor* color = &fEllipses.front().fColor;
+ return fHelper.xpRequiresDstTexture(caps, clip, GrProcessorAnalysisCoverage::kSingleChannel,
+ color);
}
- void applyPipelineOptimizations(const PipelineOptimizations& optimizations) override {
- optimizations.getOverrideColorIfSet(&fGeoData[0].fColor);
- fUsesLocalCoords = optimizations.readsLocalCoords();
- }
+ FixedFunctionFlags fixedFunctionFlags() const override { return fHelper.fixedFunctionFlags(); }
+private:
void onPrepareDraws(Target* target) const override {
// Setup geometry processor
sk_sp<GrGeometryProcessor> gp(
new DIEllipseGeometryProcessor(this->viewMatrix(), this->style()));
- int instanceCount = fGeoData.count();
size_t vertexStride = gp->getVertexStride();
SkASSERT(vertexStride == sizeof(DIEllipseVertex));
QuadHelper helper;
DIEllipseVertex* verts = reinterpret_cast<DIEllipseVertex*>(
- helper.init(target, vertexStride, instanceCount));
+ helper.init(target, vertexStride, fEllipses.count()));
if (!verts) {
return;
}
- for (int i = 0; i < instanceCount; i++) {
- const Geometry& geom = fGeoData[i];
+ for (const auto& ellipse : fEllipses) {
+ GrColor color = ellipse.fColor;
+ SkScalar xRadius = ellipse.fXRadius;
+ SkScalar yRadius = ellipse.fYRadius;
- GrColor color = geom.fColor;
- SkScalar xRadius = geom.fXRadius;
- SkScalar yRadius = geom.fYRadius;
-
- const SkRect& bounds = geom.fBounds;
+ const SkRect& bounds = ellipse.fBounds;
// This adjusts the "radius" to include the half-pixel border
- SkScalar offsetDx = geom.fGeoDx / xRadius;
- SkScalar offsetDy = geom.fGeoDy / yRadius;
+ SkScalar offsetDx = ellipse.fGeoDx / xRadius;
+ SkScalar offsetDy = ellipse.fGeoDy / yRadius;
- SkScalar innerRatioX = xRadius / geom.fInnerXRadius;
- SkScalar innerRatioY = yRadius / geom.fInnerYRadius;
+ SkScalar innerRatioX = xRadius / ellipse.fInnerXRadius;
+ SkScalar innerRatioY = yRadius / ellipse.fInnerYRadius;
verts[0].fPos = SkPoint::Make(bounds.fLeft, bounds.fTop);
verts[0].fColor = color;
@@ -1538,13 +1556,12 @@ private:
verts += kVerticesPerQuad;
}
- helper.recordDraw(target, gp.get(), this->pipeline());
+ helper.recordDraw(target, gp.get(), fHelper.makePipeline(target));
}
bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
DIEllipseOp* that = t->cast<DIEllipseOp>();
- if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
- that->bounds(), caps)) {
+ if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) {
return false;
}
@@ -1557,15 +1574,15 @@ private:
return false;
}
- fGeoData.push_back_n(that->fGeoData.count(), that->fGeoData.begin());
+ fEllipses.push_back_n(that->fEllipses.count(), that->fEllipses.begin());
this->joinBounds(*that);
return true;
}
- const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; }
- DIEllipseStyle style() const { return fGeoData[0].fStyle; }
+ const SkMatrix& viewMatrix() const { return fEllipses[0].fViewMatrix; }
+ DIEllipseStyle style() const { return fEllipses[0].fStyle; }
- struct Geometry {
+ struct Ellipse {
SkMatrix fViewMatrix;
GrColor fColor;
SkScalar fXRadius;
@@ -1578,10 +1595,10 @@ private:
SkRect fBounds;
};
- bool fUsesLocalCoords;
- SkSTArray<1, Geometry, true> fGeoData;
+ Helper fHelper;
+ SkSTArray<1, Ellipse, true> fEllipses;
- typedef GrLegacyMeshDrawOp INHERITED;
+ typedef GrMeshDrawOp INHERITED;
};
///////////////////////////////////////////////////////////////////////////////
@@ -1714,15 +1731,28 @@ static const uint16_t* rrect_type_to_indices(RRectType type) {
// each vertex is also given the normalized x & y distance from the interior rect's edge
// the GP takes the min of those depths +1 to get the normalized distance to the outer edge
-class CircularRRectOp : public GrLegacyMeshDrawOp {
+class CircularRRectOp : public GrMeshDrawOp {
+private:
+ using Helper = GrSimpleMeshDrawOpHelper;
+
public:
DEFINE_OP_CLASS_ID
// A devStrokeWidth <= 0 indicates a fill only. If devStrokeWidth > 0 then strokeOnly indicates
// whether the rrect is only stroked or stroked and filled.
- CircularRRectOp(GrColor color, bool needsDistance, const SkMatrix& viewMatrix,
- const SkRect& devRect, float devRadius, float devStrokeWidth, bool strokeOnly)
- : INHERITED(ClassID()), fViewMatrixIfUsingLocalCoords(viewMatrix) {
+ static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint, bool needsDistance,
+ const SkMatrix& viewMatrix, const SkRect& devRect,
+ float devRadius, float devStrokeWidth, bool strokeOnly) {
+ return Helper::FactoryHelper<CircularRRectOp>(std::move(paint), needsDistance, viewMatrix,
+ devRect, devRadius, devStrokeWidth,
+ strokeOnly);
+ }
+ CircularRRectOp(Helper::MakeArgs& helperArgs, GrColor color, bool needsDistance,
+ const SkMatrix& viewMatrix, const SkRect& devRect, float devRadius,
+ float devStrokeWidth, bool strokeOnly)
+ : INHERITED(ClassID())
+ , fViewMatrixIfUsingLocalCoords(viewMatrix)
+ , fHelper(helperArgs, GrAAType::kCoverage) {
SkRect bounds = devRect;
SkASSERT(!(devStrokeWidth <= 0 && strokeOnly));
SkScalar innerRadius = 0.0f;
@@ -1766,7 +1796,7 @@ public:
// Expand the rect for aa to generate correct vertices.
bounds.outset(SK_ScalarHalf, SK_ScalarHalf);
- fGeoData.emplace_back(Geometry{color, innerRadius, outerRadius, bounds, type});
+ fRRects.emplace_back(RRect{color, innerRadius, outerRadius, bounds, type});
fVertCount = rrect_type_to_vert_count(type);
fIndexCount = rrect_type_to_index_count(type);
fAllFill = (kFill_RRectType == type);
@@ -1776,33 +1806,27 @@ public:
SkString dumpInfo() const override {
SkString string;
- for (int i = 0; i < fGeoData.count(); ++i) {
+ for (int i = 0; i < fRRects.count(); ++i) {
string.appendf(
"Color: 0x%08x Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f],"
"InnerRad: %.2f, OuterRad: %.2f\n",
- fGeoData[i].fColor, fGeoData[i].fDevBounds.fLeft, fGeoData[i].fDevBounds.fTop,
- fGeoData[i].fDevBounds.fRight, fGeoData[i].fDevBounds.fBottom,
- fGeoData[i].fInnerRadius, fGeoData[i].fOuterRadius);
+ fRRects[i].fColor, fRRects[i].fDevBounds.fLeft, fRRects[i].fDevBounds.fTop,
+ fRRects[i].fDevBounds.fRight, fRRects[i].fDevBounds.fBottom,
+ fRRects[i].fInnerRadius, fRRects[i].fOuterRadius);
}
- string.append(DumpPipelineInfo(*this->pipeline()));
string.append(INHERITED::dumpInfo());
return string;
}
-private:
- void getProcessorAnalysisInputs(GrProcessorAnalysisColor* color,
- GrProcessorAnalysisCoverage* coverage) const override {
- color->setToConstant(fGeoData[0].fColor);
- *coverage = GrProcessorAnalysisCoverage::kSingleChannel;
+ bool xpRequiresDstTexture(const GrCaps& caps, const GrAppliedClip* clip) override {
+ GrColor* color = &fRRects.front().fColor;
+ return fHelper.xpRequiresDstTexture(caps, clip, GrProcessorAnalysisCoverage::kSingleChannel,
+ color);
}
- void applyPipelineOptimizations(const PipelineOptimizations& optimizations) override {
- optimizations.getOverrideColorIfSet(&fGeoData[0].fColor);
- if (!optimizations.readsLocalCoords()) {
- fViewMatrixIfUsingLocalCoords.reset();
- }
- }
+ FixedFunctionFlags fixedFunctionFlags() const override { return fHelper.fixedFunctionFlags(); }
+private:
struct CircleVertex {
SkPoint fPos;
GrColor fColor;
@@ -1889,7 +1913,6 @@ private:
sk_sp<GrGeometryProcessor> gp(
new CircleGeometryProcessor(!fAllFill, false, false, false, localMatrix));
- int instanceCount = fGeoData.count();
size_t vertexStride = gp->getVertexStride();
SkASSERT(sizeof(CircleVertex) == vertexStride);
@@ -1912,13 +1935,10 @@ private:
}
int currStartVertex = 0;
- for (int i = 0; i < instanceCount; i++) {
- const Geometry& args = fGeoData[i];
-
- GrColor color = args.fColor;
- SkScalar outerRadius = args.fOuterRadius;
-
- const SkRect& bounds = args.fDevBounds;
+ for (const auto& rrect : fRRects) {
+ GrColor color = rrect.fColor;
+ SkScalar outerRadius = rrect.fOuterRadius;
+ const SkRect& bounds = rrect.fDevBounds;
SkScalar yCoords[4] = {bounds.fTop, bounds.fTop + outerRadius,
bounds.fBottom - outerRadius, bounds.fBottom};
@@ -1927,9 +1947,9 @@ private:
// The inner radius in the vertex data must be specified in normalized space.
// For fills, specifying -1/outerRadius guarantees an alpha of 1.0 at the inner radius.
SkScalar innerRadius =
- args.fType != kFill_RRectType && args.fType != kFillWithDist_RRectType
- ? args.fInnerRadius / args.fOuterRadius
- : -1.0f / args.fOuterRadius;
+ rrect.fType != kFill_RRectType && rrect.fType != kFillWithDist_RRectType
+ ? rrect.fInnerRadius / rrect.fOuterRadius
+ : -1.0f / rrect.fOuterRadius;
for (int i = 0; i < 4; ++i) {
verts->fPos = SkPoint::Make(bounds.fLeft, yCoords[i]);
verts->fColor = color;
@@ -1967,40 +1987,40 @@ private:
//
// Also, the outer offset is a constant vector pointing to the right, which
// guarantees that the distance value along the outer rectangle is constant.
- if (kOverstroke_RRectType == args.fType) {
- SkASSERT(args.fInnerRadius <= 0.0f);
+ if (kOverstroke_RRectType == rrect.fType) {
+ SkASSERT(rrect.fInnerRadius <= 0.0f);
- SkScalar overstrokeOuterRadius = outerRadius - args.fInnerRadius;
+ SkScalar overstrokeOuterRadius = outerRadius - rrect.fInnerRadius;
// this is the normalized distance from the outer rectangle of this
// geometry to the outer edge
- SkScalar maxOffset = -args.fInnerRadius / overstrokeOuterRadius;
+ SkScalar maxOffset = -rrect.fInnerRadius / overstrokeOuterRadius;
FillInOverstrokeVerts(&verts, bounds, outerRadius, overstrokeOuterRadius, maxOffset,
- overstrokeOuterRadius, 0.0f, color);
+ overstrokeOuterRadius, 0.0f, rrect.fColor);
}
- if (kFillWithDist_RRectType == args.fType) {
+ if (kFillWithDist_RRectType == rrect.fType) {
SkScalar halfMinDim = 0.5f * SkTMin(bounds.width(), bounds.height());
SkScalar xOffset = 1.0f - outerRadius / halfMinDim;
FillInOverstrokeVerts(&verts, bounds, outerRadius, halfMinDim, xOffset, halfMinDim,
- -1.0f, color);
+ -1.0f, rrect.fColor);
}
- const uint16_t* primIndices = rrect_type_to_indices(args.fType);
- const int primIndexCount = rrect_type_to_index_count(args.fType);
+ const uint16_t* primIndices = rrect_type_to_indices(rrect.fType);
+ const int primIndexCount = rrect_type_to_index_count(rrect.fType);
for (int i = 0; i < primIndexCount; ++i) {
*indices++ = primIndices[i] + currStartVertex;
}
- currStartVertex += rrect_type_to_vert_count(args.fType);
+ currStartVertex += rrect_type_to_vert_count(rrect.fType);
}
GrMesh mesh(kTriangles_GrPrimitiveType);
mesh.setIndexed(indexBuffer, fIndexCount, firstIndex);
mesh.setVertices(vertexBuffer, fVertCount, firstVertex);
- target->draw(gp.get(), this->pipeline(), mesh);
+ target->draw(gp.get(), fHelper.makePipeline(target), mesh);
}
bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
@@ -2011,16 +2031,16 @@ private:
return false;
}
- if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
- that->bounds(), caps)) {
+ if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) {
return false;
}
- if (!fViewMatrixIfUsingLocalCoords.cheapEqualTo(that->fViewMatrixIfUsingLocalCoords)) {
+ if (fHelper.usesLocalCoords() &&
+ !fViewMatrixIfUsingLocalCoords.cheapEqualTo(that->fViewMatrixIfUsingLocalCoords)) {
return false;
}
- fGeoData.push_back_n(that->fGeoData.count(), that->fGeoData.begin());
+ fRRects.push_back_n(that->fRRects.count(), that->fRRects.begin());
this->joinBounds(*that);
fVertCount += that->fVertCount;
fIndexCount += that->fIndexCount;
@@ -2028,7 +2048,7 @@ private:
return true;
}
- struct Geometry {
+ struct RRect {
GrColor fColor;
SkScalar fInnerRadius;
SkScalar fOuterRadius;
@@ -2036,13 +2056,14 @@ private:
RRectType fType;
};
- SkSTArray<1, Geometry, true> fGeoData;
SkMatrix fViewMatrixIfUsingLocalCoords;
+ Helper fHelper;
int fVertCount;
int fIndexCount;
bool fAllFill;
+ SkSTArray<1, RRect, true> fRRects;
- typedef GrLegacyMeshDrawOp INHERITED;
+ typedef GrMeshDrawOp INHERITED;
};
static const int kNumRRectsInIndexBuffer = 256;
@@ -2068,24 +2089,22 @@ static const GrBuffer* ref_rrect_index_buffer(RRectType type,
};
}
-class EllipticalRRectOp : public GrLegacyMeshDrawOp {
+class EllipticalRRectOp : public GrMeshDrawOp {
+private:
+ using Helper = GrSimpleMeshDrawOpHelper;
+
public:
DEFINE_OP_CLASS_ID
// If devStrokeWidths values are <= 0 indicates then fill only. Otherwise, strokeOnly indicates
// whether the rrect is only stroked or stroked and filled.
- static std::unique_ptr<GrLegacyMeshDrawOp> Make(GrColor color, const SkMatrix& viewMatrix,
- const SkRect& devRect, float devXRadius,
- float devYRadius, SkVector devStrokeWidths,
- bool strokeOnly) {
+ static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint, const SkMatrix& viewMatrix,
+ const SkRect& devRect, float devXRadius, float devYRadius,
+ SkVector devStrokeWidths, bool strokeOnly) {
SkASSERT(devXRadius > 0.5);
SkASSERT(devYRadius > 0.5);
SkASSERT((devStrokeWidths.fX > 0) == (devStrokeWidths.fY > 0));
SkASSERT(!(strokeOnly && devStrokeWidths.fX <= 0));
- SkScalar innerXRadius = 0.0f;
- SkScalar innerYRadius = 0.0f;
- SkRect bounds = devRect;
- bool stroked = false;
if (devStrokeWidths.fX > 0) {
if (SkScalarNearlyZero(devStrokeWidths.length())) {
devStrokeWidths.set(SK_ScalarHalf, SK_ScalarHalf);
@@ -2109,28 +2128,40 @@ public:
(devStrokeWidths.fX * devStrokeWidths.fX) * devYRadius) {
return nullptr;
}
+ }
+ return Helper::FactoryHelper<EllipticalRRectOp>(std::move(paint), viewMatrix, devRect,
+ devXRadius, devYRadius, devStrokeWidths,
+ strokeOnly);
+ }
+ EllipticalRRectOp(Helper::MakeArgs helperArgs, GrColor color, const SkMatrix& viewMatrix,
+ const SkRect& devRect, float devXRadius, float devYRadius,
+ SkVector devStrokeHalfWidths, bool strokeOnly)
+ : INHERITED(ClassID()), fHelper(helperArgs, GrAAType::kCoverage) {
+ SkScalar innerXRadius = 0.0f;
+ SkScalar innerYRadius = 0.0f;
+ SkRect bounds = devRect;
+ bool stroked = false;
+ if (devStrokeHalfWidths.fX > 0) {
// this is legit only if scale & translation (which should be the case at the moment)
if (strokeOnly) {
- innerXRadius = devXRadius - devStrokeWidths.fX;
- innerYRadius = devYRadius - devStrokeWidths.fY;
+ innerXRadius = devXRadius - devStrokeHalfWidths.fX;
+ innerYRadius = devYRadius - devStrokeHalfWidths.fY;
stroked = (innerXRadius >= 0 && innerYRadius >= 0);
}
- devXRadius += devStrokeWidths.fX;
- devYRadius += devStrokeWidths.fY;
- bounds.outset(devStrokeWidths.fX, devStrokeWidths.fY);
+ devXRadius += devStrokeHalfWidths.fX;
+ devYRadius += devStrokeHalfWidths.fY;
+ bounds.outset(devStrokeHalfWidths.fX, devStrokeHalfWidths.fY);
}
- std::unique_ptr<EllipticalRRectOp> op(new EllipticalRRectOp());
- op->fStroked = stroked;
- op->fViewMatrixIfUsingLocalCoords = viewMatrix;
- op->setBounds(bounds, HasAABloat::kYes, IsZeroArea::kNo);
+ fStroked = stroked;
+ fViewMatrixIfUsingLocalCoords = viewMatrix;
+ this->setBounds(bounds, HasAABloat::kYes, IsZeroArea::kNo);
// Expand the rect for aa in order to generate the correct vertices.
bounds.outset(SK_ScalarHalf, SK_ScalarHalf);
- op->fGeoData.emplace_back(
- Geometry{color, devXRadius, devYRadius, innerXRadius, innerYRadius, bounds});
- return std::move(op);
+ fRRects.emplace_back(
+ RRect{color, devXRadius, devYRadius, innerXRadius, innerYRadius, bounds});
}
const char* name() const override { return "EllipticalRRectOp"; }
@@ -2138,7 +2169,7 @@ public:
SkString dumpInfo() const override {
SkString string;
string.appendf("Stroked: %d\n", fStroked);
- for (const auto& geo : fGeoData) {
+ for (const auto& geo : fRRects) {
string.appendf(
"Color: 0x%08x Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f], "
"XRad: %.2f, YRad: %.2f, InnerXRad: %.2f, InnerYRad: %.2f\n",
@@ -2146,27 +2177,19 @@ public:
geo.fDevBounds.fBottom, geo.fXRadius, geo.fYRadius, geo.fInnerXRadius,
geo.fInnerYRadius);
}
- string.append(DumpPipelineInfo(*this->pipeline()));
string.append(INHERITED::dumpInfo());
return string;
}
-private:
- EllipticalRRectOp() : INHERITED(ClassID()) {}
-
- void getProcessorAnalysisInputs(GrProcessorAnalysisColor* color,
- GrProcessorAnalysisCoverage* coverage) const override {
- color->setToConstant(fGeoData[0].fColor);
- *coverage = GrProcessorAnalysisCoverage::kSingleChannel;
+ bool xpRequiresDstTexture(const GrCaps& caps, const GrAppliedClip* clip) override {
+ GrColor* color = &fRRects.front().fColor;
+ return fHelper.xpRequiresDstTexture(caps, clip, GrProcessorAnalysisCoverage::kSingleChannel,
+ color);
}
- void applyPipelineOptimizations(const PipelineOptimizations& optimizations) override {
- optimizations.getOverrideColorIfSet(&fGeoData[0].fColor);
- if (!optimizations.readsLocalCoords()) {
- fViewMatrixIfUsingLocalCoords.reset();
- }
- }
+ FixedFunctionFlags fixedFunctionFlags() const override { return fHelper.fixedFunctionFlags(); }
+private:
void onPrepareDraws(Target* target) const override {
SkMatrix localMatrix;
if (!fViewMatrixIfUsingLocalCoords.invert(&localMatrix)) {
@@ -2176,7 +2199,6 @@ private:
// Setup geometry processor
sk_sp<GrGeometryProcessor> gp(new EllipseGeometryProcessor(fStroked, localMatrix));
- int instanceCount = fGeoData.count();
size_t vertexStride = gp->getVertexStride();
SkASSERT(vertexStride == sizeof(EllipseVertex));
@@ -2188,28 +2210,25 @@ private:
PatternHelper helper(kTriangles_GrPrimitiveType);
EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(
helper.init(target, vertexStride, indexBuffer.get(), kVertsPerStandardRRect,
- indicesPerInstance, instanceCount));
+ indicesPerInstance, fRRects.count()));
if (!verts || !indexBuffer) {
SkDebugf("Could not allocate vertices\n");
return;
}
- for (int i = 0; i < instanceCount; i++) {
- const Geometry& args = fGeoData[i];
-
- GrColor color = args.fColor;
-
+ for (const auto& rrect : fRRects) {
+ GrColor color = rrect.fColor;
// Compute the reciprocals of the radii here to save time in the shader
- SkScalar xRadRecip = SkScalarInvert(args.fXRadius);
- SkScalar yRadRecip = SkScalarInvert(args.fYRadius);
- SkScalar xInnerRadRecip = SkScalarInvert(args.fInnerXRadius);
- SkScalar yInnerRadRecip = SkScalarInvert(args.fInnerYRadius);
+ SkScalar xRadRecip = SkScalarInvert(rrect.fXRadius);
+ SkScalar yRadRecip = SkScalarInvert(rrect.fYRadius);
+ SkScalar xInnerRadRecip = SkScalarInvert(rrect.fInnerXRadius);
+ SkScalar yInnerRadRecip = SkScalarInvert(rrect.fInnerYRadius);
// Extend the radii out half a pixel to antialias.
- SkScalar xOuterRadius = args.fXRadius + SK_ScalarHalf;
- SkScalar yOuterRadius = args.fYRadius + SK_ScalarHalf;
+ SkScalar xOuterRadius = rrect.fXRadius + SK_ScalarHalf;
+ SkScalar yOuterRadius = rrect.fYRadius + SK_ScalarHalf;
- const SkRect& bounds = args.fDevBounds;
+ const SkRect& bounds = rrect.fDevBounds;
SkScalar yCoords[4] = {bounds.fTop, bounds.fTop + yOuterRadius,
bounds.fBottom - yOuterRadius, bounds.fBottom};
@@ -2248,14 +2267,13 @@ private:
verts++;
}
}
- helper.recordDraw(target, gp.get(), this->pipeline());
+ helper.recordDraw(target, gp.get(), fHelper.makePipeline(target));
}
bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
EllipticalRRectOp* that = t->cast<EllipticalRRectOp>();
- if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
- that->bounds(), caps)) {
+ if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) {
return false;
}
@@ -2263,16 +2281,17 @@ private:
return false;
}
- if (!fViewMatrixIfUsingLocalCoords.cheapEqualTo(that->fViewMatrixIfUsingLocalCoords)) {
+ if (fHelper.usesLocalCoords() &&
+ !fViewMatrixIfUsingLocalCoords.cheapEqualTo(that->fViewMatrixIfUsingLocalCoords)) {
return false;
}
- fGeoData.push_back_n(that->fGeoData.count(), that->fGeoData.begin());
+ fRRects.push_back_n(that->fRRects.count(), that->fRRects.begin());
this->joinBounds(*that);
return true;
}
- struct Geometry {
+ struct RRect {
GrColor fColor;
SkScalar fXRadius;
SkScalar fYRadius;
@@ -2281,18 +2300,19 @@ private:
SkRect fDevBounds;
};
- bool fStroked;
SkMatrix fViewMatrixIfUsingLocalCoords;
- SkSTArray<1, Geometry, true> fGeoData;
+ Helper fHelper;
+ bool fStroked;
+ SkSTArray<1, RRect, true> fRRects;
- typedef GrLegacyMeshDrawOp INHERITED;
+ typedef GrMeshDrawOp INHERITED;
};
-static std::unique_ptr<GrLegacyMeshDrawOp> make_rrect_op(GrColor color,
- bool needsDistance,
- const SkMatrix& viewMatrix,
- const SkRRect& rrect,
- const SkStrokeRec& stroke) {
+static std::unique_ptr<GrDrawOp> make_rrect_op(GrPaint&& paint,
+ bool needsDistance,
+ const SkMatrix& viewMatrix,
+ const SkRRect& rrect,
+ const SkStrokeRec& stroke) {
SkASSERT(viewMatrix.rectStaysRect());
SkASSERT(rrect.isSimple());
SkASSERT(!rrect.isOval());
@@ -2350,55 +2370,56 @@ static std::unique_ptr<GrLegacyMeshDrawOp> make_rrect_op(GrColor color,
// if the corners are circles, use the circle renderer
if (isCircular) {
- return std::unique_ptr<GrLegacyMeshDrawOp>(new CircularRRectOp(
- color, needsDistance, viewMatrix, bounds, xRadius, scaledStroke.fX, isStrokeOnly));
+ return CircularRRectOp::Make(std::move(paint), needsDistance, viewMatrix, bounds, xRadius,
+ scaledStroke.fX, isStrokeOnly);
// otherwise we use the ellipse renderer
} else {
- return EllipticalRRectOp::Make(color, viewMatrix, bounds, xRadius, yRadius, scaledStroke,
- isStrokeOnly);
+ return EllipticalRRectOp::Make(std::move(paint), viewMatrix, bounds, xRadius, yRadius,
+ scaledStroke, isStrokeOnly);
}
}
-std::unique_ptr<GrLegacyMeshDrawOp> GrOvalOpFactory::MakeRRectOp(GrColor color,
- bool needsDistance,
- const SkMatrix& viewMatrix,
- const SkRRect& rrect,
- const SkStrokeRec& stroke,
- const GrShaderCaps* shaderCaps) {
+std::unique_ptr<GrDrawOp> GrOvalOpFactory::MakeRRectOp(GrPaint&& paint,
+ bool needsDistance,
+ const SkMatrix& viewMatrix,
+ const SkRRect& rrect,
+ const SkStrokeRec& stroke,
+ const GrShaderCaps* shaderCaps) {
if (rrect.isOval()) {
- return MakeOvalOp(color, viewMatrix, rrect.getBounds(), stroke, shaderCaps);
+ return MakeOvalOp(std::move(paint), viewMatrix, rrect.getBounds(), stroke, shaderCaps);
}
if (!viewMatrix.rectStaysRect() || !rrect.isSimple()) {
return nullptr;
}
- return make_rrect_op(color, needsDistance, viewMatrix, rrect, stroke);
+ return make_rrect_op(std::move(paint), needsDistance, viewMatrix, rrect, stroke);
}
///////////////////////////////////////////////////////////////////////////////
-std::unique_ptr<GrLegacyMeshDrawOp> GrOvalOpFactory::MakeOvalOp(GrColor color,
- const SkMatrix& viewMatrix,
- const SkRect& oval,
- const SkStrokeRec& stroke,
- const GrShaderCaps* shaderCaps) {
+std::unique_ptr<GrDrawOp> GrOvalOpFactory::MakeOvalOp(GrPaint&& paint,
+ const SkMatrix& viewMatrix,
+ const SkRect& oval,
+ const SkStrokeRec& stroke,
+ const GrShaderCaps* shaderCaps) {
// we can draw circles
SkScalar width = oval.width();
if (width > SK_ScalarNearlyZero && SkScalarNearlyEqual(width, oval.height()) &&
circle_stays_circle(viewMatrix)) {
SkPoint center = {oval.centerX(), oval.centerY()};
- return CircleOp::Make(color, viewMatrix, center, width / 2.f, GrStyle(stroke, nullptr));
+ return CircleOp::Make(std::move(paint), viewMatrix, center, width / 2.f,
+ GrStyle(stroke, nullptr));
}
// prefer the device space ellipse op for batchability
if (viewMatrix.rectStaysRect()) {
- return EllipseOp::Make(color, viewMatrix, oval, stroke);
+ return EllipseOp::Make(std::move(paint), viewMatrix, oval, stroke);
}
// Otherwise, if we have shader derivative support, render as device-independent
if (shaderCaps->shaderDerivativeSupport()) {
- return DIEllipseOp::Make(color, viewMatrix, oval, stroke);
+ return DIEllipseOp::Make(std::move(paint), viewMatrix, oval, stroke);
}
return nullptr;
@@ -2406,9 +2427,11 @@ std::unique_ptr<GrLegacyMeshDrawOp> GrOvalOpFactory::MakeOvalOp(GrColor color,
///////////////////////////////////////////////////////////////////////////////
-std::unique_ptr<GrLegacyMeshDrawOp> GrOvalOpFactory::MakeArcOp(
- GrColor color, const SkMatrix& viewMatrix, const SkRect& oval, SkScalar startAngle,
- SkScalar sweepAngle, bool useCenter, const GrStyle& style, const GrShaderCaps* shaderCaps) {
+std::unique_ptr<GrDrawOp> GrOvalOpFactory::MakeArcOp(GrPaint&& paint, const SkMatrix& viewMatrix,
+ const SkRect& oval, SkScalar startAngle,
+ SkScalar sweepAngle, bool useCenter,
+ const GrStyle& style,
+ const GrShaderCaps* shaderCaps) {
SkASSERT(!oval.isEmpty());
SkASSERT(sweepAngle);
SkScalar width = oval.width();
@@ -2421,14 +2444,14 @@ std::unique_ptr<GrLegacyMeshDrawOp> GrOvalOpFactory::MakeArcOp(
SkPoint center = {oval.centerX(), oval.centerY()};
CircleOp::ArcParams arcParams = {SkDegreesToRadians(startAngle), SkDegreesToRadians(sweepAngle),
useCenter};
- return CircleOp::Make(color, viewMatrix, center, width / 2.f, style, &arcParams);
+ return CircleOp::Make(std::move(paint), viewMatrix, center, width / 2.f, style, &arcParams);
}
///////////////////////////////////////////////////////////////////////////////
#if GR_TEST_UTILS
-GR_LEGACY_MESH_DRAW_OP_TEST_DEFINE(CircleOp) {
+GR_DRAW_OP_TEST_DEFINE(CircleOp) {
do {
SkScalar rotate = random->nextSScalar1() * 360.f;
SkScalar translateX = random->nextSScalar1() * 1000.f;
@@ -2438,7 +2461,6 @@ GR_LEGACY_MESH_DRAW_OP_TEST_DEFINE(CircleOp) {
viewMatrix.setRotate(rotate);
viewMatrix.postTranslate(translateX, translateY);
viewMatrix.postScale(scale, scale);
- GrColor color = GrRandomColor(random);
SkRect circle = GrTest::TestSquare(random);
SkPoint center = {circle.centerX(), circle.centerY()};
SkScalar radius = circle.width() / 2.f;
@@ -2451,34 +2473,32 @@ GR_LEGACY_MESH_DRAW_OP_TEST_DEFINE(CircleOp) {
arcParamsTmp.fUseCenter = random->nextBool();
arcParams = &arcParamsTmp;
}
- std::unique_ptr<GrLegacyMeshDrawOp> op = CircleOp::Make(
- color, viewMatrix, center, radius, GrStyle(stroke, nullptr), arcParams);
+ std::unique_ptr<GrDrawOp> op = CircleOp::Make(std::move(paint), viewMatrix, center, radius,
+ GrStyle(stroke, nullptr), arcParams);
if (op) {
return op;
}
} while (true);
}
-GR_LEGACY_MESH_DRAW_OP_TEST_DEFINE(EllipseOp) {
+GR_DRAW_OP_TEST_DEFINE(EllipseOp) {
SkMatrix viewMatrix = GrTest::TestMatrixRectStaysRect(random);
- GrColor color = GrRandomColor(random);
SkRect ellipse = GrTest::TestSquare(random);
- return EllipseOp::Make(color, viewMatrix, ellipse, GrTest::TestStrokeRec(random));
+ return EllipseOp::Make(std::move(paint), viewMatrix, ellipse, GrTest::TestStrokeRec(random));
}
-GR_LEGACY_MESH_DRAW_OP_TEST_DEFINE(DIEllipseOp) {
+GR_DRAW_OP_TEST_DEFINE(DIEllipseOp) {
SkMatrix viewMatrix = GrTest::TestMatrix(random);
- GrColor color = GrRandomColor(random);
SkRect ellipse = GrTest::TestSquare(random);
- return DIEllipseOp::Make(color, viewMatrix, ellipse, GrTest::TestStrokeRec(random));
+ return DIEllipseOp::Make(std::move(paint), viewMatrix, ellipse, GrTest::TestStrokeRec(random));
}
-GR_LEGACY_MESH_DRAW_OP_TEST_DEFINE(RRectOp) {
+GR_DRAW_OP_TEST_DEFINE(RRectOp) {
SkMatrix viewMatrix = GrTest::TestMatrixRectStaysRect(random);
- GrColor color = GrRandomColor(random);
const SkRRect& rrect = GrTest::TestRRectSimple(random);
bool needsDistance = random->nextBool();
- return make_rrect_op(color, needsDistance, viewMatrix, rrect, GrTest::TestStrokeRec(random));
+ return make_rrect_op(std::move(paint), needsDistance, viewMatrix, rrect,
+ GrTest::TestStrokeRec(random));
}
#endif
diff --git a/src/gpu/ops/GrOvalOpFactory.h b/src/gpu/ops/GrOvalOpFactory.h
index 72e0fa28a4..8a51c5301e 100644
--- a/src/gpu/ops/GrOvalOpFactory.h
+++ b/src/gpu/ops/GrOvalOpFactory.h
@@ -11,7 +11,9 @@
#include "GrColor.h"
#include "SkRefCnt.h"
+class GrDrawOp;
class GrLegacyMeshDrawOp;
+class GrPaint;
class GrShaderCaps;
class GrStyle;
class SkMatrix;
@@ -24,26 +26,27 @@ class SkStrokeRec;
*/
class GrOvalOpFactory {
public:
- static std::unique_ptr<GrLegacyMeshDrawOp> MakeOvalOp(GrColor,
- const SkMatrix& viewMatrix,
- const SkRect& oval,
- const SkStrokeRec& stroke,
- const GrShaderCaps* shaderCaps);
- static std::unique_ptr<GrLegacyMeshDrawOp> MakeRRectOp(GrColor,
- bool needsDistance,
- const SkMatrix& viewMatrix,
- const SkRRect& rrect,
- const SkStrokeRec& stroke,
- const GrShaderCaps* shaderCaps);
+ static std::unique_ptr<GrDrawOp> MakeOvalOp(GrPaint&&,
+ const SkMatrix&,
+ const SkRect& oval,
+ const SkStrokeRec&,
+ const GrShaderCaps*);
- static std::unique_ptr<GrLegacyMeshDrawOp> MakeArcOp(GrColor,
- const SkMatrix& viewMatrix,
- const SkRect& oval,
- SkScalar startAngle,
- SkScalar sweepAngle,
- bool useCenter,
- const GrStyle&,
- const GrShaderCaps* shaderCaps);
+ static std::unique_ptr<GrDrawOp> MakeRRectOp(GrPaint&&,
+ bool needsDistance,
+ const SkMatrix&,
+ const SkRRect&,
+ const SkStrokeRec&,
+ const GrShaderCaps*);
+
+ static std::unique_ptr<GrDrawOp> MakeArcOp(GrPaint&&,
+ const SkMatrix&,
+ const SkRect& oval,
+ SkScalar startAngle,
+ SkScalar sweepAngle,
+ bool useCenter,
+ const GrStyle&,
+ const GrShaderCaps*);
};
#endif // GrOvalOpFactory_DEFINED
diff --git a/src/gpu/ops/GrSimpleMeshDrawOpHelper.h b/src/gpu/ops/GrSimpleMeshDrawOpHelper.h
index 03b9b1a96d..427543bc98 100644
--- a/src/gpu/ops/GrSimpleMeshDrawOpHelper.h
+++ b/src/gpu/ops/GrSimpleMeshDrawOpHelper.h
@@ -40,8 +40,10 @@ public:
: fProcessors(args.fProcessorSet)
, fPipelineFlags(args.fSRGBFlags)
, fAAType((int)aaType)
- , fRequiresDstTexture(false) {
+ , fRequiresDstTexture(false)
+ , fUsesLocalCoords(false) {
SkASSERT(!stencilSettings);
+ SkDEBUGCODE(fDidAnalysis = false);
if (GrAATypeIsHW(aaType)) {
fPipelineFlags |= GrPipeline::kHWAntialias_Flag;
}
@@ -83,6 +85,7 @@ public:
bool xpRequiresDstTexture(const GrCaps& caps, const GrAppliedClip* clip,
GrProcessorAnalysisCoverage geometryCoverage, GrColor* color) {
+ SkDEBUGCODE(fDidAnalysis = true);
if (fProcessors) {
GrProcessorAnalysisCoverage coverage = geometryCoverage;
if (GrProcessorAnalysisCoverage::kNone == coverage) {
@@ -94,12 +97,19 @@ public:
GrProcessorSet::Analysis analysis =
fProcessors->finalize(*color, coverage, clip, isMixedSamples, caps, color);
fRequiresDstTexture = analysis.requiresDstTexture();
+ fUsesLocalCoords = analysis.usesLocalCoords();
return analysis.requiresDstTexture();
} else {
+ fUsesLocalCoords = GrProcessorSet::EmptySetAnalysis().usesLocalCoords();
return GrProcessorSet::EmptySetAnalysis().requiresDstTexture();
}
}
+ bool usesLocalCoords() const {
+ SkASSERT(fDidAnalysis);
+ return fUsesLocalCoords;
+ }
+
GrPipeline* makePipeline(GrMeshDrawOp::Target* target) const {
return target->allocPipeline(this->pipelineInitArgs(target));
}
@@ -137,6 +147,8 @@ private:
unsigned fPipelineFlags : 8;
unsigned fAAType : 2;
unsigned fRequiresDstTexture : 1;
+ unsigned fUsesLocalCoords : 1;
+ SkDEBUGCODE(unsigned fDidAnalysis : 1;)
};
/**
@@ -170,6 +182,7 @@ public:
}
using GrSimpleMeshDrawOpHelper::xpRequiresDstTexture;
+ using GrSimpleMeshDrawOpHelper::usesLocalCoords;
bool isCompatible(const GrSimpleMeshDrawOpHelperWithStencil& that, const GrCaps& caps,
const SkRect& aBounds, const SkRect& bBounds) const {