Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(51)

Side by Side Diff: src/gpu/batches/GrTessellatingPathRenderer.cpp

Issue 1957363002: Replace GrStrokeInfo with GrStyle. (Closed) Base URL: https://chromium.googlesource.com/skia.git@resscale
Patch Set: Fix issue where hairlines were going to MSAAPathRenderer Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/gpu/batches/GrStencilAndCoverPathRenderer.cpp ('k') | src/gpu/effects/GrDashingEffect.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2015 Google Inc. 2 * Copyright 2015 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "GrTessellatingPathRenderer.h" 8 #include "GrTessellatingPathRenderer.h"
9 9
10 #include "GrBatchFlushState.h" 10 #include "GrBatchFlushState.h"
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 }; 98 };
99 99
100 } // namespace 100 } // namespace
101 101
102 GrTessellatingPathRenderer::GrTessellatingPathRenderer() { 102 GrTessellatingPathRenderer::GrTessellatingPathRenderer() {
103 } 103 }
104 104
105 bool GrTessellatingPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) cons t { 105 bool GrTessellatingPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) cons t {
106 // This path renderer can draw all fill styles, all stroke styles except hai rlines, but does 106 // This path renderer can draw all fill styles, all stroke styles except hai rlines, but does
107 // not do antialiasing. It can do convex and concave paths, but we'll leave the convex ones to 107 // not do antialiasing. It can do convex and concave paths, but we'll leave the convex ones to
108 // simpler algorithms. 108 // simpler algorithms. Similary, we skip the non-hairlines that can be treat ed as hairline.
109 return !IsStrokeHairlineOrEquivalent(*args.fStroke, *args.fViewMatrix, nullp tr) && 109 // An arbitrary path effect could produce a hairline result so we pass on th ose.
110 !args.fAntiAlias && !args.fPath->isConvex(); 110 return !IsStrokeHairlineOrEquivalent(*args.fStyle, *args.fViewMatrix, nullpt r) &&
111 !args.fStyle->strokeRec().isHairlineStyle() &&
112 !args.fStyle->hasNonDashPathEffect() && !args.fAntiAlias && !args.fPa th->isConvex();
111 } 113 }
112 114
113 class TessellatingPathBatch : public GrVertexBatch { 115 class TessellatingPathBatch : public GrVertexBatch {
114 public: 116 public:
115 DEFINE_BATCH_CLASS_ID 117 DEFINE_BATCH_CLASS_ID
116 118
117 static GrDrawBatch* Create(const GrColor& color, 119 static GrDrawBatch* Create(const GrColor& color,
118 const SkPath& path, 120 const SkPath& path,
119 const GrStrokeInfo& stroke, 121 const GrStyle& style,
120 const SkMatrix& viewMatrix, 122 const SkMatrix& viewMatrix,
121 SkRect clipBounds) { 123 SkRect clipBounds) {
122 return new TessellatingPathBatch(color, path, stroke, viewMatrix, clipBo unds); 124 return new TessellatingPathBatch(color, path, style, viewMatrix, clipBou nds);
123 } 125 }
124 126
125 const char* name() const override { return "TessellatingPathBatch"; } 127 const char* name() const override { return "TessellatingPathBatch"; }
126 128
127 void computePipelineOptimizations(GrInitInvariantOutput* color, 129 void computePipelineOptimizations(GrInitInvariantOutput* color,
128 GrInitInvariantOutput* coverage, 130 GrInitInvariantOutput* coverage,
129 GrBatchToXPOverrides* overrides) const ove rride { 131 GrBatchToXPOverrides* overrides) const ove rride {
130 color->setKnownFourComponents(fColor); 132 color->setKnownFourComponents(fColor);
131 coverage->setUnknownSingleComponent(); 133 coverage->setUnknownSingleComponent();
132 } 134 }
133 135
134 private: 136 private:
135 void initBatchTracker(const GrXPOverridesForBatch& overrides) override { 137 void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
136 // Handle any color overrides 138 // Handle any color overrides
137 if (!overrides.readsColor()) { 139 if (!overrides.readsColor()) {
138 fColor = GrColor_ILLEGAL; 140 fColor = GrColor_ILLEGAL;
139 } 141 }
140 overrides.getOverrideColorIfSet(&fColor); 142 overrides.getOverrideColorIfSet(&fColor);
141 fPipelineInfo = overrides; 143 fPipelineInfo = overrides;
142 } 144 }
143 145
144 void draw(Target* target, const GrGeometryProcessor* gp) const { 146 void draw(Target* target, const GrGeometryProcessor* gp) const {
147 GrResourceProvider* rp = target->resourceProvider();
148 SkScalar screenSpaceTol = GrPathUtils::kDefaultTolerance;
149 SkScalar tol = GrPathUtils::scaleToleranceToSrc(screenSpaceTol, fViewMat rix,
150 fPath.getBounds());
151
152 SkScalar styleScale = SK_Scalar1;
153 if (fStyle.applies()) {
154 styleScale = GrStyle::MatrixToScaleFactor(fViewMatrix);
155 }
156
145 // construct a cache key from the path's genID and the view matrix 157 // construct a cache key from the path's genID and the view matrix
146 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain() ; 158 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain() ;
147 GrUniqueKey key; 159 GrUniqueKey key;
148 int clipBoundsSize32 = 160 int clipBoundsCnt =
149 fPath.isInverseFillType() ? sizeof(fClipBounds) / sizeof(uint32_t) : 0; 161 fPath.isInverseFillType() ? sizeof(fClipBounds) / sizeof(uint32_t) : 0;
150 int strokeDataSize32 = fStroke.computeUniqueKeyFragmentData32Cnt(); 162 int styleDataCnt = GrStyle::KeySize(fStyle, GrStyle::Apply::kPathEffectA ndStrokeRec);
151 GrUniqueKey::Builder builder(&key, kDomain, 2 + clipBoundsSize32 + strok eDataSize32); 163 if (styleDataCnt >= 0) {
Stephen White 2016/05/17 21:34:30 Post-landing driveby: could we just assert this is
152 builder[0] = fPath.getGenerationID(); 164 GrUniqueKey::Builder builder(&key, kDomain, 2 + clipBoundsCnt + styl eDataCnt);
153 builder[1] = fPath.getFillType(); 165 builder[0] = fPath.getGenerationID();
154 // For inverse fills, the tessellation is dependent on clip bounds. 166 builder[1] = fPath.getFillType();
155 if (fPath.isInverseFillType()) { 167 // For inverse fills, the tessellation is dependent on clip bounds.
156 memcpy(&builder[2], &fClipBounds, sizeof(fClipBounds)); 168 if (fPath.isInverseFillType()) {
157 } 169 memcpy(&builder[2], &fClipBounds, sizeof(fClipBounds));
158 fStroke.asUniqueKeyFragment(&builder[2 + clipBoundsSize32]); 170 }
159 builder.finish(); 171 if (styleDataCnt) {
160 GrResourceProvider* rp = target->resourceProvider(); 172 GrStyle::WriteKey(&builder[2 + clipBoundsCnt], fStyle,
161 SkAutoTUnref<GrBuffer> cachedVertexBuffer(rp->findAndRefTByUniqueKey<GrB uffer>(key)); 173 GrStyle::Apply::kPathEffectAndStrokeRec, style Scale);
162 int actualCount; 174 }
163 SkScalar screenSpaceTol = GrPathUtils::kDefaultTolerance; 175 builder.finish();
164 SkScalar tol = GrPathUtils::scaleToleranceToSrc( 176 SkAutoTUnref<GrBuffer> cachedVertexBuffer(rp->findAndRefTByUniqueKey <GrBuffer>(key));
165 screenSpaceTol, fViewMatrix, fPath.getBounds()); 177 int actualCount;
166 if (cache_match(cachedVertexBuffer.get(), tol, &actualCount)) { 178 if (cache_match(cachedVertexBuffer.get(), tol, &actualCount)) {
167 this->drawVertices(target, gp, cachedVertexBuffer.get(), 0, actualCo unt); 179 this->drawVertices(target, gp, cachedVertexBuffer.get(), 0, actu alCount);
168 return; 180 return;
181 }
169 } 182 }
170 183
171 SkPath path; 184 SkPath path;
172 GrStrokeInfo stroke(fStroke); 185 if (fStyle.applies()) {
173 if (stroke.isDashed()) { 186 SkStrokeRec::InitStyle fill;
174 if (!stroke.applyDashToPath(&path, &stroke, fPath)) { 187 SkAssertResult(fStyle.applyToPath(&path, &fill, fPath, styleScale));
175 return; 188 SkASSERT(SkStrokeRec::kFill_InitStyle == fill);
176 }
177 } else { 189 } else {
178 path = fPath; 190 path = fPath;
179 } 191 }
180 if (!stroke.isFillStyle()) {
181 stroke.setResScale(SkScalarAbs(fViewMatrix.getMaxScale()));
182 if (!stroke.applyToPath(&path, path)) {
183 return;
184 }
185 stroke.setFillStyle();
186 }
187 bool isLinear; 192 bool isLinear;
188 bool canMapVB = GrCaps::kNone_MapFlags != target->caps().mapBufferFlags( ); 193 bool canMapVB = GrCaps::kNone_MapFlags != target->caps().mapBufferFlags( );
189 StaticVertexAllocator allocator(rp, canMapVB); 194 StaticVertexAllocator allocator(rp, canMapVB);
190 int count = GrTessellator::PathToTriangles(path, tol, fClipBounds, &allo cator, &isLinear); 195 int count = GrTessellator::PathToTriangles(path, tol, fClipBounds, &allo cator, &isLinear);
191 if (count == 0) { 196 if (count == 0) {
192 return; 197 return;
193 } 198 }
194 this->drawVertices(target, gp, allocator.vertexBuffer(), 0, count); 199 this->drawVertices(target, gp, allocator.vertexBuffer(), 0, count);
195 if (!fPath.isVolatile()) { 200 if (!fPath.isVolatile() && styleDataCnt >= 0) {
196 TessInfo info; 201 TessInfo info;
197 info.fTolerance = isLinear ? 0 : tol; 202 info.fTolerance = isLinear ? 0 : tol;
198 info.fCount = count; 203 info.fCount = count;
199 SkAutoTUnref<SkData> data(SkData::NewWithCopy(&info, sizeof(info))); 204 SkAutoTUnref<SkData> data(SkData::NewWithCopy(&info, sizeof(info)));
200 key.setCustomData(data.get()); 205 key.setCustomData(data.get());
201 rp->assignUniqueKeyToResource(key, allocator.vertexBuffer()); 206 rp->assignUniqueKeyToResource(key, allocator.vertexBuffer());
202 SkPathPriv::AddGenIDChangeListener(fPath, new PathInvalidator(key)); 207 SkPathPriv::AddGenIDChangeListener(fPath, new PathInvalidator(key));
203 } 208 }
204 } 209 }
205 210
(...skipping 27 matching lines...) Expand all
233 : kTriangles_GrPri mitiveType; 238 : kTriangles_GrPri mitiveType;
234 GrMesh mesh; 239 GrMesh mesh;
235 mesh.init(primitiveType, vb, firstVertex, count); 240 mesh.init(primitiveType, vb, firstVertex, count);
236 target->draw(gp, mesh); 241 target->draw(gp, mesh);
237 } 242 }
238 243
239 bool onCombineIfPossible(GrBatch*, const GrCaps&) override { return false; } 244 bool onCombineIfPossible(GrBatch*, const GrCaps&) override { return false; }
240 245
241 TessellatingPathBatch(const GrColor& color, 246 TessellatingPathBatch(const GrColor& color,
242 const SkPath& path, 247 const SkPath& path,
243 const GrStrokeInfo& stroke, 248 const GrStyle& style,
244 const SkMatrix& viewMatrix, 249 const SkMatrix& viewMatrix,
245 const SkRect& clipBounds) 250 const SkRect& clipBounds)
246 : INHERITED(ClassID()) 251 : INHERITED(ClassID())
247 , fColor(color) 252 , fColor(color)
248 , fPath(path) 253 , fPath(path)
249 , fStroke(stroke) 254 , fStyle(style)
250 , fViewMatrix(viewMatrix) { 255 , fViewMatrix(viewMatrix) {
251 const SkRect& pathBounds = path.getBounds(); 256 const SkRect& pathBounds = path.getBounds();
252 fClipBounds = clipBounds; 257 fClipBounds = clipBounds;
253 // Because the clip bounds are used to add a contour for inverse fills, they must also 258 // Because the clip bounds are used to add a contour for inverse fills, they must also
254 // include the path bounds. 259 // include the path bounds.
255 fClipBounds.join(pathBounds); 260 fClipBounds.join(pathBounds);
256 if (path.isInverseFillType()) { 261 if (path.isInverseFillType()) {
257 fBounds = fClipBounds; 262 fBounds = fClipBounds;
258 } else { 263 } else {
259 fBounds = path.getBounds(); 264 fBounds = path.getBounds();
260 } 265 }
261 SkScalar radius = stroke.getInflationRadius(); 266 style.adjustBounds(&fBounds, fBounds);
262 fBounds.outset(radius, radius);
263 viewMatrix.mapRect(&fBounds); 267 viewMatrix.mapRect(&fBounds);
264 } 268 }
265 269
266 GrColor fColor; 270 GrColor fColor;
267 SkPath fPath; 271 SkPath fPath;
268 GrStrokeInfo fStroke; 272 GrStyle fStyle;
269 SkMatrix fViewMatrix; 273 SkMatrix fViewMatrix;
270 SkRect fClipBounds; // in source space 274 SkRect fClipBounds; // in source space
271 GrXPOverridesForBatch fPipelineInfo; 275 GrXPOverridesForBatch fPipelineInfo;
272 276
273 typedef GrVertexBatch INHERITED; 277 typedef GrVertexBatch INHERITED;
274 }; 278 };
275 279
276 bool GrTessellatingPathRenderer::onDrawPath(const DrawPathArgs& args) { 280 bool GrTessellatingPathRenderer::onDrawPath(const DrawPathArgs& args) {
277 GR_AUDIT_TRAIL_AUTO_FRAME(args.fTarget->getAuditTrail(), 281 GR_AUDIT_TRAIL_AUTO_FRAME(args.fTarget->getAuditTrail(),
278 "GrTessellatingPathRenderer::onDrawPath"); 282 "GrTessellatingPathRenderer::onDrawPath");
279 SkASSERT(!args.fAntiAlias); 283 SkASSERT(!args.fAntiAlias);
280 const GrRenderTarget* rt = args.fPipelineBuilder->getRenderTarget(); 284 const GrRenderTarget* rt = args.fPipelineBuilder->getRenderTarget();
281 if (nullptr == rt) { 285 if (nullptr == rt) {
282 return false; 286 return false;
283 } 287 }
284 288
285 SkIRect clipBoundsI; 289 SkIRect clipBoundsI;
286 args.fPipelineBuilder->clip().getConservativeBounds(rt->width(), rt->height( ), &clipBoundsI); 290 args.fPipelineBuilder->clip().getConservativeBounds(rt->width(), rt->height( ), &clipBoundsI);
287 SkRect clipBounds = SkRect::Make(clipBoundsI); 291 SkRect clipBounds = SkRect::Make(clipBoundsI);
288 SkMatrix vmi; 292 SkMatrix vmi;
289 if (!args.fViewMatrix->invert(&vmi)) { 293 if (!args.fViewMatrix->invert(&vmi)) {
290 return false; 294 return false;
291 } 295 }
292 vmi.mapRect(&clipBounds); 296 vmi.mapRect(&clipBounds);
293 SkAutoTUnref<GrDrawBatch> batch(TessellatingPathBatch::Create(args.fColor, * args.fPath, 297 SkAutoTUnref<GrDrawBatch> batch(TessellatingPathBatch::Create(args.fColor, * args.fPath,
294 *args.fStroke, *args.fViewMatrix, 298 *args.fStyle, *args.fViewMatrix,
295 clipBounds)); 299 clipBounds));
296 args.fTarget->drawBatch(*args.fPipelineBuilder, batch); 300 args.fTarget->drawBatch(*args.fPipelineBuilder, batch);
297 301
298 return true; 302 return true;
299 } 303 }
300 304
301 //////////////////////////////////////////////////////////////////////////////// /////////////////// 305 //////////////////////////////////////////////////////////////////////////////// ///////////////////
302 306
303 #ifdef GR_TEST_UTILS 307 #ifdef GR_TEST_UTILS
304 308
305 DRAW_BATCH_TEST_DEFINE(TesselatingPathBatch) { 309 DRAW_BATCH_TEST_DEFINE(TesselatingPathBatch) {
306 GrColor color = GrRandomColor(random); 310 GrColor color = GrRandomColor(random);
307 SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random); 311 SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random);
308 SkPath path = GrTest::TestPath(random); 312 SkPath path = GrTest::TestPath(random);
309 SkRect clipBounds = GrTest::TestRect(random); 313 SkRect clipBounds = GrTest::TestRect(random);
310 SkMatrix vmi; 314 SkMatrix vmi;
311 bool result = viewMatrix.invert(&vmi); 315 bool result = viewMatrix.invert(&vmi);
312 if (!result) { 316 if (!result) {
313 SkFAIL("Cannot invert matrix\n"); 317 SkFAIL("Cannot invert matrix\n");
314 } 318 }
315 vmi.mapRect(&clipBounds); 319 vmi.mapRect(&clipBounds);
316 GrStrokeInfo strokeInfo = GrTest::TestStrokeInfo(random); 320 GrStyle style;
317 return TessellatingPathBatch::Create(color, path, strokeInfo, viewMatrix, cl ipBounds); 321 do {
322 GrTest::TestStyle(random, &style);
323 } while (style.strokeRec().isHairlineStyle());
324 return TessellatingPathBatch::Create(color, path, style, viewMatrix, clipBou nds);
318 } 325 }
319 326
320 #endif 327 #endif
OLDNEW
« no previous file with comments | « src/gpu/batches/GrStencilAndCoverPathRenderer.cpp ('k') | src/gpu/effects/GrDashingEffect.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698