blob: da1221b474cafe1fbfed929075404f5d55dec8fa [file] [log] [blame]
ethannicholas1a1b3ac2015-06-10 12:11:17 -07001/*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "GrAALinearizingConvexPathRenderer.h"
ethannicholas1a1b3ac2015-06-10 12:11:17 -07009#include "GrAAConvexTessellator.h"
ethannicholas1a1b3ac2015-06-10 12:11:17 -070010#include "GrDefaultGeoProcFactory.h"
Brian Salomon5ec9def2016-12-20 15:34:05 -050011#include "GrDrawOpTest.h"
ethannicholas1a1b3ac2015-06-10 12:11:17 -070012#include "GrGeometryProcessor.h"
Brian Salomon742e31d2016-12-07 17:06:19 -050013#include "GrOpFlushState.h"
ethannicholas1a1b3ac2015-06-10 12:11:17 -070014#include "GrPathUtils.h"
Brian Salomondad29232016-12-01 16:40:24 -050015#include "GrProcessor.h"
Brian Salomon653f42f2018-07-10 10:07:31 -040016#include "GrRenderTargetContext.h"
17#include "GrShape.h"
bsalomon6663acf2016-05-10 09:14:17 -070018#include "GrStyle.h"
Brian Osmanf9aabff2018-11-13 16:11:38 -050019#include "GrVertexWriter.h"
ethannicholas1a1b3ac2015-06-10 12:11:17 -070020#include "SkGeometry.h"
Brian Salomondad29232016-12-01 16:40:24 -050021#include "SkPathPriv.h"
ethannicholas1a1b3ac2015-06-10 12:11:17 -070022#include "SkString.h"
23#include "SkTraceEvent.h"
egdaniele659a582015-11-13 09:55:43 -080024#include "glsl/GrGLSLGeometryProcessor.h"
Brian Salomon89527432016-12-16 09:52:16 -050025#include "ops/GrMeshDrawOp.h"
Brian Salomonb2955732017-07-13 16:42:55 -040026#include "ops/GrSimpleMeshDrawOpHelper.h"
ethannicholas1a1b3ac2015-06-10 12:11:17 -070027
fmalitabd5d7e72015-06-26 07:18:24 -070028static const int DEFAULT_BUFFER_SIZE = 100;
29
30// The thicker the stroke, the harder it is to produce high-quality results using tessellation. For
31// the time being, we simply drop back to software rendering above this stroke width.
32static const SkScalar kMaxStrokeWidth = 20.0;
ethannicholas1a1b3ac2015-06-10 12:11:17 -070033
34GrAALinearizingConvexPathRenderer::GrAALinearizingConvexPathRenderer() {
35}
36
37///////////////////////////////////////////////////////////////////////////////
38
Chris Dalton5ed44232017-09-07 13:22:46 -060039GrPathRenderer::CanDrawPath
40GrAALinearizingConvexPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -050041 if (GrAAType::kCoverage != args.fAAType) {
Chris Dalton5ed44232017-09-07 13:22:46 -060042 return CanDrawPath::kNo;
fmalitabd5d7e72015-06-26 07:18:24 -070043 }
bsalomon8acedde2016-06-24 10:42:16 -070044 if (!args.fShape->knownToBeConvex()) {
Chris Dalton5ed44232017-09-07 13:22:46 -060045 return CanDrawPath::kNo;
fmalitabd5d7e72015-06-26 07:18:24 -070046 }
bsalomon8acedde2016-06-24 10:42:16 -070047 if (args.fShape->style().pathEffect()) {
Chris Dalton5ed44232017-09-07 13:22:46 -060048 return CanDrawPath::kNo;
fmalitabd5d7e72015-06-26 07:18:24 -070049 }
bsalomon8acedde2016-06-24 10:42:16 -070050 if (args.fShape->inverseFilled()) {
Chris Dalton5ed44232017-09-07 13:22:46 -060051 return CanDrawPath::kNo;
bsalomon6663acf2016-05-10 09:14:17 -070052 }
Brian Osmana98e3992017-06-26 15:14:53 -040053 if (args.fShape->bounds().width() <= 0 && args.fShape->bounds().height() <= 0) {
54 // Stroked zero length lines should draw, but this PR doesn't handle that case
Chris Dalton5ed44232017-09-07 13:22:46 -060055 return CanDrawPath::kNo;
Brian Osmana98e3992017-06-26 15:14:53 -040056 }
bsalomon8acedde2016-06-24 10:42:16 -070057 const SkStrokeRec& stroke = args.fShape->style().strokeRec();
robertphillips8c170972016-09-22 12:42:30 -070058
59 if (stroke.getStyle() == SkStrokeRec::kStroke_Style ||
60 stroke.getStyle() == SkStrokeRec::kStrokeAndFill_Style) {
ethannicholasfea77632015-08-19 12:09:12 -070061 if (!args.fViewMatrix->isSimilarity()) {
Chris Dalton5ed44232017-09-07 13:22:46 -060062 return CanDrawPath::kNo;
ethannicholasfea77632015-08-19 12:09:12 -070063 }
bsalomon6663acf2016-05-10 09:14:17 -070064 SkScalar strokeWidth = args.fViewMatrix->getMaxScale() * stroke.getWidth();
robertphillips8c170972016-09-22 12:42:30 -070065 if (strokeWidth < 1.0f && stroke.getStyle() == SkStrokeRec::kStroke_Style) {
Chris Dalton5ed44232017-09-07 13:22:46 -060066 return CanDrawPath::kNo;
robertphillips8c170972016-09-22 12:42:30 -070067 }
Chris Dalton5ed44232017-09-07 13:22:46 -060068 if (strokeWidth > kMaxStrokeWidth ||
69 !args.fShape->knownToBeClosed() ||
70 stroke.getJoin() == SkPaint::Join::kRound_Join) {
71 return CanDrawPath::kNo;
72 }
73 return CanDrawPath::kYes;
fmalitabd5d7e72015-06-26 07:18:24 -070074 }
Chris Dalton5ed44232017-09-07 13:22:46 -060075 if (stroke.getStyle() != SkStrokeRec::kFill_Style) {
76 return CanDrawPath::kNo;
77 }
78 return CanDrawPath::kYes;
ethannicholas1a1b3ac2015-06-10 12:11:17 -070079}
80
81// extract the result vertices and indices from the GrAAConvexTessellator
82static void extract_verts(const GrAAConvexTessellator& tess,
Brian Osmanf9aabff2018-11-13 16:11:38 -050083 void* vertData,
Brian Osman80879d42019-01-07 16:15:27 -050084 const GrVertexColor& color,
ethannicholas1a1b3ac2015-06-10 12:11:17 -070085 uint16_t firstIndex,
Brian Osman0995fd52019-01-09 09:52:25 -050086 uint16_t* idxs) {
Brian Osmanf9aabff2018-11-13 16:11:38 -050087 GrVertexWriter verts{vertData};
Brian Osmanf3e6b902018-12-28 17:43:50 +000088 for (int i = 0; i < tess.numPts(); ++i) {
Brian Osman80879d42019-01-07 16:15:27 -050089 verts.write(tess.point(i), color, tess.coverage(i));
ethannicholas1a1b3ac2015-06-10 12:11:17 -070090 }
91
92 for (int i = 0; i < tess.numIndices(); ++i) {
93 idxs[i] = tess.index(i) + firstIndex;
94 }
95}
96
Ruiqi Maob609e6d2018-07-17 10:19:38 -040097static sk_sp<GrGeometryProcessor> create_lines_only_gp(const GrShaderCaps* shaderCaps,
98 bool tweakAlphaForCoverage,
Brian Salomon60fb0b22017-06-15 17:09:36 -040099 const SkMatrix& viewMatrix,
Brian Osman80879d42019-01-07 16:15:27 -0500100 bool usesLocalCoords,
101 bool wideColor) {
joshualittdf0c5572015-08-03 11:35:28 -0700102 using namespace GrDefaultGeoProcFactory;
joshualitte494a582015-08-03 09:32:36 -0700103
Brian Osman80879d42019-01-07 16:15:27 -0500104 Coverage::Type coverageType =
105 tweakAlphaForCoverage ? Coverage::kAttributeTweakAlpha_Type : Coverage::kAttribute_Type;
Brian Salomon8c852be2017-01-04 10:44:42 -0500106 LocalCoords::Type localCoordsType =
Brian Osman80879d42019-01-07 16:15:27 -0500107 usesLocalCoords ? LocalCoords::kUsePosition_Type : LocalCoords::kUnused_Type;
108 Color::Type colorType =
109 wideColor ? Color::kPremulWideColorAttribute_Type : Color::kPremulGrColorAttribute_Type;
110
111 return MakeForDeviceSpace(shaderCaps, colorType, coverageType, localCoordsType, viewMatrix);
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700112}
113
Brian Salomonb2955732017-07-13 16:42:55 -0400114namespace {
115
116class AAFlatteningConvexPathOp final : public GrMeshDrawOp {
117private:
118 using Helper = GrSimpleMeshDrawOpHelperWithStencil;
119
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700120public:
Brian Salomon25a88092016-12-01 09:36:50 -0500121 DEFINE_OP_CLASS_ID
Robert Phillipsb97da532019-02-12 15:24:12 -0500122 static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
Robert Phillips7c525e62018-06-12 10:11:12 -0400123 GrPaint&& paint,
Brian Salomonb2955732017-07-13 16:42:55 -0400124 const SkMatrix& viewMatrix,
125 const SkPath& path,
126 SkScalar strokeWidth,
127 SkStrokeRec::Style style,
128 SkPaint::Join join,
129 SkScalar miterLimit,
130 const GrUserStencilSettings* stencilSettings) {
Robert Phillips7c525e62018-06-12 10:11:12 -0400131 return Helper::FactoryHelper<AAFlatteningConvexPathOp>(context, std::move(paint),
132 viewMatrix, path,
Brian Salomonb2955732017-07-13 16:42:55 -0400133 strokeWidth, style, join, miterLimit,
134 stencilSettings);
Brian Salomon780dad12016-12-15 18:08:40 -0500135 }
136
Brian Salomonb2955732017-07-13 16:42:55 -0400137 AAFlatteningConvexPathOp(const Helper::MakeArgs& helperArgs,
Brian Osmancf860852018-10-31 14:04:39 -0400138 const SkPMColor4f& color,
Brian Salomon780dad12016-12-15 18:08:40 -0500139 const SkMatrix& viewMatrix,
140 const SkPath& path,
141 SkScalar strokeWidth,
142 SkStrokeRec::Style style,
143 SkPaint::Join join,
Brian Salomonb2955732017-07-13 16:42:55 -0400144 SkScalar miterLimit,
145 const GrUserStencilSettings* stencilSettings)
146 : INHERITED(ClassID()), fHelper(helperArgs, GrAAType::kCoverage, stencilSettings) {
Brian Salomon780dad12016-12-15 18:08:40 -0500147 fPaths.emplace_back(
148 PathData{color, viewMatrix, path, strokeWidth, style, join, miterLimit});
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700149
bsalomon0432dd62016-06-30 07:19:27 -0700150 // compute bounds
bsalomon88cf17d2016-07-08 06:40:56 -0700151 SkRect bounds = path.getBounds();
bsalomon0432dd62016-06-30 07:19:27 -0700152 SkScalar w = strokeWidth;
153 if (w > 0) {
154 w /= 2;
155 // If the half stroke width is < 1 then we effectively fallback to bevel joins.
156 if (SkPaint::kMiter_Join == join && w > 1.f) {
157 w *= miterLimit;
158 }
bsalomon88cf17d2016-07-08 06:40:56 -0700159 bounds.outset(w, w);
bsalomon0432dd62016-06-30 07:19:27 -0700160 }
bsalomon88cf17d2016-07-08 06:40:56 -0700161 this->setTransformedBounds(bounds, viewMatrix, HasAABloat::kYes, IsZeroArea::kNo);
Brian Osman80879d42019-01-07 16:15:27 -0500162 fWideColor = !SkPMColor4fFitsInBytes(color);
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700163 }
164
Brian Salomonb2955732017-07-13 16:42:55 -0400165 const char* name() const override { return "AAFlatteningConvexPathOp"; }
166
Brian Salomon7d94bb52018-10-12 14:37:19 -0400167 void visitProxies(const VisitProxyFunc& func, VisitorType) const override {
Robert Phillipsb493eeb2017-09-13 13:10:52 -0400168 fHelper.visitProxies(func);
169 }
170
Brian Osman9a390ac2018-11-12 09:47:48 -0500171#ifdef SK_DEBUG
Brian Salomonb2955732017-07-13 16:42:55 -0400172 SkString dumpInfo() const override {
173 SkString string;
174 for (const auto& path : fPaths) {
175 string.appendf(
176 "Color: 0x%08x, StrokeWidth: %.2f, Style: %d, Join: %d, "
177 "MiterLimit: %.2f\n",
Brian Osmancf860852018-10-31 14:04:39 -0400178 path.fColor.toBytes_RGBA(), path.fStrokeWidth, path.fStyle, path.fJoin,
Brian Osman1be2b7c2018-10-29 16:07:15 -0400179 path.fMiterLimit);
Brian Salomonb2955732017-07-13 16:42:55 -0400180 }
181 string += fHelper.dumpInfo();
182 string += INHERITED::dumpInfo();
183 return string;
Brian Salomon92aee3d2016-12-21 09:20:25 -0500184 }
Brian Osman9a390ac2018-11-12 09:47:48 -0500185#endif
Brian Salomon92aee3d2016-12-21 09:20:25 -0500186
Brian Salomonb2955732017-07-13 16:42:55 -0400187 FixedFunctionFlags fixedFunctionFlags() const override { return fHelper.fixedFunctionFlags(); }
188
Chris Dalton4b62aed2019-01-15 11:53:00 -0700189 GrProcessorSet::Analysis finalize(const GrCaps& caps, const GrAppliedClip* clip) override {
190 return fHelper.finalizeProcessors(caps, clip, GrProcessorAnalysisCoverage::kSingleChannel,
191 &fPaths.back().fColor);
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700192 }
193
Brian Salomonb2955732017-07-13 16:42:55 -0400194private:
Brian Salomon7eae3e02018-08-07 14:02:38 +0000195 void draw(Target* target, sk_sp<const GrGeometryProcessor> gp, const GrPipeline* pipeline,
Brian Salomon49348902018-06-26 09:12:38 -0400196 const GrPipeline::FixedDynamicState* fixedDynamicState, int vertexCount,
197 size_t vertexStride, void* vertices, int indexCount, uint16_t* indices) const {
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700198 if (vertexCount == 0 || indexCount == 0) {
199 return;
200 }
Brian Salomon12d22642019-01-29 14:38:50 -0500201 sk_sp<const GrBuffer> vertexBuffer;
Chris Daltonbca46e22017-05-15 11:03:26 -0600202 int firstVertex;
mtklein002c2ce2015-08-26 05:43:22 -0700203 void* verts = target->makeVertexSpace(vertexStride, vertexCount, &vertexBuffer,
Chris Daltonbca46e22017-05-15 11:03:26 -0600204 &firstVertex);
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700205 if (!verts) {
206 SkDebugf("Could not allocate vertices\n");
207 return;
208 }
209 memcpy(verts, vertices, vertexCount * vertexStride);
210
Brian Salomon12d22642019-01-29 14:38:50 -0500211 sk_sp<const GrBuffer> indexBuffer;
Chris Daltonbca46e22017-05-15 11:03:26 -0600212 int firstIndex;
213 uint16_t* idxs = target->makeIndexSpace(indexCount, &indexBuffer, &firstIndex);
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700214 if (!idxs) {
215 SkDebugf("Could not allocate indices\n");
216 return;
217 }
218 memcpy(idxs, indices, indexCount * sizeof(uint16_t));
Brian Salomon7eae3e02018-08-07 14:02:38 +0000219 GrMesh* mesh = target->allocMesh(GrPrimitiveType::kTriangles);
Brian Salomon12d22642019-01-29 14:38:50 -0500220 mesh->setIndexed(std::move(indexBuffer), indexCount, firstIndex, 0, vertexCount - 1,
Brian Salomon7eae3e02018-08-07 14:02:38 +0000221 GrPrimitiveRestart::kNo);
Brian Salomon12d22642019-01-29 14:38:50 -0500222 mesh->setVertexData(std::move(vertexBuffer), firstVertex);
Brian Salomon7eae3e02018-08-07 14:02:38 +0000223 target->draw(std::move(gp), pipeline, fixedDynamicState, mesh);
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700224 }
mtklein002c2ce2015-08-26 05:43:22 -0700225
Brian Salomon91326c32017-08-09 16:02:19 -0400226 void onPrepareDraws(Target* target) override {
Brian Salomon49348902018-06-26 09:12:38 -0400227 auto pipe = fHelper.makePipeline(target);
joshualittdf0c5572015-08-03 11:35:28 -0700228 // Setup GrGeometryProcessor
Ruiqi Maob609e6d2018-07-17 10:19:38 -0400229 sk_sp<GrGeometryProcessor> gp(create_lines_only_gp(target->caps().shaderCaps(),
230 fHelper.compatibleWithAlphaAsCoverage(),
Brian Salomonb2955732017-07-13 16:42:55 -0400231 this->viewMatrix(),
Brian Osman80879d42019-01-07 16:15:27 -0500232 fHelper.usesLocalCoords(),
233 fWideColor));
joshualittdf0c5572015-08-03 11:35:28 -0700234 if (!gp) {
235 SkDebugf("Couldn't create a GrGeometryProcessor\n");
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700236 return;
237 }
238
Brian Osmanf04fb3c2018-11-12 15:34:00 -0500239 size_t vertexStride = gp->vertexStride();
Brian Salomon780dad12016-12-15 18:08:40 -0500240 int instanceCount = fPaths.count();
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700241
Greg Danield5b45932018-06-07 13:15:10 -0400242 int64_t vertexCount = 0;
243 int64_t indexCount = 0;
244 int64_t maxVertices = DEFAULT_BUFFER_SIZE;
245 int64_t maxIndices = DEFAULT_BUFFER_SIZE;
mtklein002c2ce2015-08-26 05:43:22 -0700246 uint8_t* vertices = (uint8_t*) sk_malloc_throw(maxVertices * vertexStride);
247 uint16_t* indices = (uint16_t*) sk_malloc_throw(maxIndices * sizeof(uint16_t));
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700248 for (int i = 0; i < instanceCount; i++) {
Brian Salomon780dad12016-12-15 18:08:40 -0500249 const PathData& args = fPaths[i];
robertphillips8c170972016-09-22 12:42:30 -0700250 GrAAConvexTessellator tess(args.fStyle, args.fStrokeWidth,
251 args.fJoin, args.fMiterLimit);
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700252
253 if (!tess.tessellate(args.fViewMatrix, args.fPath)) {
254 continue;
255 }
256
Greg Danield5b45932018-06-07 13:15:10 -0400257 int currentVertices = tess.numPts();
258 if (vertexCount + currentVertices > static_cast<int>(UINT16_MAX)) {
mtklein002c2ce2015-08-26 05:43:22 -0700259 // if we added the current instance, we would overflow the indices we can store in a
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700260 // uint16_t. Draw what we've got so far and reset.
Brian Salomon7eae3e02018-08-07 14:02:38 +0000261 this->draw(target, gp, pipe.fPipeline, pipe.fFixedDynamicState, vertexCount,
Brian Salomon49348902018-06-26 09:12:38 -0400262 vertexStride, vertices, indexCount, indices);
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700263 vertexCount = 0;
264 indexCount = 0;
265 }
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700266 if (vertexCount + currentVertices > maxVertices) {
267 maxVertices = SkTMax(vertexCount + currentVertices, maxVertices * 2);
Greg Danield5b45932018-06-07 13:15:10 -0400268 if (maxVertices * vertexStride > SK_MaxS32) {
269 sk_free(vertices);
270 sk_free(indices);
271 return;
272 }
mtklein002c2ce2015-08-26 05:43:22 -0700273 vertices = (uint8_t*) sk_realloc_throw(vertices, maxVertices * vertexStride);
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700274 }
Greg Danield5b45932018-06-07 13:15:10 -0400275 int currentIndices = tess.numIndices();
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700276 if (indexCount + currentIndices > maxIndices) {
277 maxIndices = SkTMax(indexCount + currentIndices, maxIndices * 2);
Greg Danield5b45932018-06-07 13:15:10 -0400278 if (maxIndices * sizeof(uint16_t) > SK_MaxS32) {
279 sk_free(vertices);
280 sk_free(indices);
281 return;
282 }
mtklein002c2ce2015-08-26 05:43:22 -0700283 indices = (uint16_t*) sk_realloc_throw(indices, maxIndices * sizeof(uint16_t));
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700284 }
285
Brian Osman80879d42019-01-07 16:15:27 -0500286 extract_verts(tess, vertices + vertexStride * vertexCount,
Brian Osman0995fd52019-01-09 09:52:25 -0500287 GrVertexColor(args.fColor, fWideColor), vertexCount,
288 indices + indexCount);
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700289 vertexCount += currentVertices;
290 indexCount += currentIndices;
291 }
Greg Danield5b45932018-06-07 13:15:10 -0400292 if (vertexCount <= SK_MaxS32 && indexCount <= SK_MaxS32) {
Brian Salomon7eae3e02018-08-07 14:02:38 +0000293 this->draw(target, std::move(gp), pipe.fPipeline, pipe.fFixedDynamicState, vertexCount,
Brian Salomon49348902018-06-26 09:12:38 -0400294 vertexStride, vertices, indexCount, indices);
Greg Danield5b45932018-06-07 13:15:10 -0400295 }
mtklein002c2ce2015-08-26 05:43:22 -0700296 sk_free(vertices);
297 sk_free(indices);
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700298 }
299
Brian Salomon7eae3e02018-08-07 14:02:38 +0000300 CombineResult onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
Brian Salomon780dad12016-12-15 18:08:40 -0500301 AAFlatteningConvexPathOp* that = t->cast<AAFlatteningConvexPathOp>();
Brian Salomonb2955732017-07-13 16:42:55 -0400302 if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) {
Brian Salomon7eae3e02018-08-07 14:02:38 +0000303 return CombineResult::kCannotCombine;
joshualitt8cab9a72015-07-16 09:13:50 -0700304 }
305
Brian Salomon780dad12016-12-15 18:08:40 -0500306 fPaths.push_back_n(that->fPaths.count(), that->fPaths.begin());
Brian Osman80879d42019-01-07 16:15:27 -0500307 fWideColor |= that->fWideColor;
Brian Salomon7eae3e02018-08-07 14:02:38 +0000308 return CombineResult::kMerged;
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700309 }
310
Brian Salomon780dad12016-12-15 18:08:40 -0500311 const SkMatrix& viewMatrix() const { return fPaths[0].fViewMatrix; }
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700312
Brian Salomon780dad12016-12-15 18:08:40 -0500313 struct PathData {
Brian Osmancf860852018-10-31 14:04:39 -0400314 SkPMColor4f fColor;
bsalomon0432dd62016-06-30 07:19:27 -0700315 SkMatrix fViewMatrix;
316 SkPath fPath;
317 SkScalar fStrokeWidth;
robertphillips8c170972016-09-22 12:42:30 -0700318 SkStrokeRec::Style fStyle;
bsalomon0432dd62016-06-30 07:19:27 -0700319 SkPaint::Join fJoin;
320 SkScalar fMiterLimit;
321 };
322
Brian Salomon780dad12016-12-15 18:08:40 -0500323 SkSTArray<1, PathData, true> fPaths;
Brian Salomonb2955732017-07-13 16:42:55 -0400324 Helper fHelper;
Brian Osman80879d42019-01-07 16:15:27 -0500325 bool fWideColor;
reed1b55a962015-09-17 20:16:13 -0700326
Brian Salomonb2955732017-07-13 16:42:55 -0400327 typedef GrMeshDrawOp INHERITED;
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700328};
329
Brian Salomonb2955732017-07-13 16:42:55 -0400330} // anonymous namespace
331
bsalomon0aff2fa2015-07-31 06:48:27 -0700332bool GrAALinearizingConvexPathRenderer::onDrawPath(const DrawPathArgs& args) {
Brian Osman11052242016-10-27 14:47:55 -0400333 GR_AUDIT_TRAIL_AUTO_FRAME(args.fRenderTargetContext->auditTrail(),
joshualittde83b412016-01-14 09:58:36 -0800334 "GrAALinearizingConvexPathRenderer::onDrawPath");
Brian Salomon7c8460e2017-05-12 11:36:10 -0400335 SkASSERT(GrFSAAType::kUnifiedMSAA != args.fRenderTargetContext->fsaaType());
bsalomon8acedde2016-06-24 10:42:16 -0700336 SkASSERT(!args.fShape->isEmpty());
robertphillips8c170972016-09-22 12:42:30 -0700337 SkASSERT(!args.fShape->style().pathEffect());
csmartdaltonecbc12b2016-06-08 10:08:43 -0700338
bsalomon0432dd62016-06-30 07:19:27 -0700339 SkPath path;
340 args.fShape->asPath(&path);
bsalomon8acedde2016-06-24 10:42:16 -0700341 bool fill = args.fShape->style().isSimpleFill();
342 const SkStrokeRec& stroke = args.fShape->style().strokeRec();
bsalomon0432dd62016-06-30 07:19:27 -0700343 SkScalar strokeWidth = fill ? -1.0f : stroke.getWidth();
344 SkPaint::Join join = fill ? SkPaint::Join::kMiter_Join : stroke.getJoin();
345 SkScalar miterLimit = stroke.getMiter();
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700346
Brian Salomonb2955732017-07-13 16:42:55 -0400347 std::unique_ptr<GrDrawOp> op = AAFlatteningConvexPathOp::Make(
Robert Phillips7c525e62018-06-12 10:11:12 -0400348 args.fContext, std::move(args.fPaint), *args.fViewMatrix, path, strokeWidth,
349 stroke.getStyle(), join, miterLimit, args.fUserStencilSettings);
Brian Salomonb2955732017-07-13 16:42:55 -0400350 args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op));
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700351 return true;
352}
353
354///////////////////////////////////////////////////////////////////////////////////////////////////
355
Hal Canary6f6961e2017-01-31 13:50:44 -0500356#if GR_TEST_UTILS
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700357
Brian Salomonb2955732017-07-13 16:42:55 -0400358GR_DRAW_OP_TEST_DEFINE(AAFlatteningConvexPathOp) {
Brian Salomon780dad12016-12-15 18:08:40 -0500359 SkMatrix viewMatrix = GrTest::TestMatrixPreservesRightAngles(random);
bsalomon0432dd62016-06-30 07:19:27 -0700360 SkPath path = GrTest::TestPathConvex(random);
robertphillips8c170972016-09-22 12:42:30 -0700361
362 SkStrokeRec::Style styles[3] = { SkStrokeRec::kFill_Style,
Herb Derby60c05f92016-12-13 15:18:55 -0500363 SkStrokeRec::kStroke_Style,
robertphillips8c170972016-09-22 12:42:30 -0700364 SkStrokeRec::kStrokeAndFill_Style };
365
366 SkStrokeRec::Style style = styles[random->nextU() % 3];
367
368 SkScalar strokeWidth = -1.f;
bsalomon0432dd62016-06-30 07:19:27 -0700369 SkPaint::Join join = SkPaint::kMiter_Join;
370 SkScalar miterLimit = 0.5f;
robertphillips8c170972016-09-22 12:42:30 -0700371
372 if (SkStrokeRec::kFill_Style != style) {
373 strokeWidth = random->nextRangeF(1.0f, 10.0f);
374 if (random->nextBool()) {
375 join = SkPaint::kMiter_Join;
376 } else {
377 join = SkPaint::kBevel_Join;
378 }
379 miterLimit = random->nextRangeF(0.5f, 2.0f);
380 }
Brian Salomonb2955732017-07-13 16:42:55 -0400381 const GrUserStencilSettings* stencilSettings = GrGetRandomStencil(random, context);
Robert Phillips7c525e62018-06-12 10:11:12 -0400382 return AAFlatteningConvexPathOp::Make(context, std::move(paint), viewMatrix, path, strokeWidth,
383 style, join, miterLimit, stencilSettings);
ethannicholas1a1b3ac2015-06-10 12:11:17 -0700384}
385
386#endif