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

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

Issue 1152733009: Screenspace AA tessellated path rendering. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Make GLPrograms test generate only simple fills. Created 4 years, 3 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/GrTessellator.cpp ('k') | no next file » | 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 "GrAuditTrail.h" 10 #include "GrAuditTrail.h"
11 #include "GrBatchFlushState.h" 11 #include "GrBatchFlushState.h"
12 #include "GrBatchTest.h" 12 #include "GrBatchTest.h"
13 #include "GrClip.h" 13 #include "GrClip.h"
14 #include "GrDefaultGeoProcFactory.h" 14 #include "GrDefaultGeoProcFactory.h"
15 #include "GrDrawTarget.h"
15 #include "GrMesh.h" 16 #include "GrMesh.h"
16 #include "GrPathUtils.h" 17 #include "GrPathUtils.h"
17 #include "GrPipelineBuilder.h" 18 #include "GrPipelineBuilder.h"
18 #include "GrResourceCache.h" 19 #include "GrResourceCache.h"
19 #include "GrResourceProvider.h" 20 #include "GrResourceProvider.h"
20 #include "GrTessellator.h" 21 #include "GrTessellator.h"
21 #include "SkGeometry.h" 22 #include "SkGeometry.h"
22 23
23 #include "batches/GrVertexBatch.h" 24 #include "batches/GrVertexBatch.h"
24 25
25 #include <stdio.h> 26 #include <stdio.h>
26 27
28 #define SK_DISABLE_SCREENSPACE_TESS_AA_PATH_RENDERER
29
27 /* 30 /*
28 * This path renderer tessellates the path into triangles using GrTessellator, u ploads the triangles 31 * This path renderer tessellates the path into triangles using GrTessellator, u ploads the
29 * to a vertex buffer, and renders them with a single draw call. It does not cur rently do 32 * triangles to a vertex buffer, and renders them with a single draw call. It ca n do screenspace
30 * antialiasing, so it must be used in conjunction with multisampling. 33 * antialiasing with a one-pixel coverage ramp.
31 */ 34 */
32 namespace { 35 namespace {
33 36
34 struct TessInfo { 37 struct TessInfo {
35 SkScalar fTolerance; 38 SkScalar fTolerance;
36 int fCount; 39 int fCount;
37 }; 40 };
38 41
39 // When the SkPathRef genID changes, invalidate a corresponding GrResource descr ibed by key. 42 // When the SkPathRef genID changes, invalidate a corresponding GrResource descr ibed by key.
40 class PathInvalidator : public SkPathRef::GenIDChangeListener { 43 class PathInvalidator : public SkPathRef::GenIDChangeListener {
(...skipping 16 matching lines...) Expand all
57 const TessInfo* info = static_cast<const TessInfo*>(data->data()); 60 const TessInfo* info = static_cast<const TessInfo*>(data->data());
58 if (info->fTolerance == 0 || info->fTolerance < 3.0f * tol) { 61 if (info->fTolerance == 0 || info->fTolerance < 3.0f * tol) {
59 *actualCount = info->fCount; 62 *actualCount = info->fCount;
60 return true; 63 return true;
61 } 64 }
62 return false; 65 return false;
63 } 66 }
64 67
65 class StaticVertexAllocator : public GrTessellator::VertexAllocator { 68 class StaticVertexAllocator : public GrTessellator::VertexAllocator {
66 public: 69 public:
67 StaticVertexAllocator(GrResourceProvider* resourceProvider, bool canMapVB) 70 StaticVertexAllocator(size_t stride, GrResourceProvider* resourceProvider, b ool canMapVB)
68 : fResourceProvider(resourceProvider) 71 : VertexAllocator(stride)
72 , fResourceProvider(resourceProvider)
69 , fCanMapVB(canMapVB) 73 , fCanMapVB(canMapVB)
70 , fVertices(nullptr) { 74 , fVertices(nullptr) {
71 } 75 }
72 SkPoint* lock(int vertexCount) override { 76 void* lock(int vertexCount) override {
73 size_t size = vertexCount * sizeof(SkPoint); 77 size_t size = vertexCount * stride();
74 fVertexBuffer.reset(fResourceProvider->createBuffer( 78 fVertexBuffer.reset(fResourceProvider->createBuffer(
75 size, kVertex_GrBufferType, kStatic_GrAccessPattern, 0)); 79 size, kVertex_GrBufferType, kStatic_GrAccessPattern, 0));
76 if (!fVertexBuffer.get()) { 80 if (!fVertexBuffer.get()) {
77 return nullptr; 81 return nullptr;
78 } 82 }
79 if (fCanMapVB) { 83 if (fCanMapVB) {
80 fVertices = static_cast<SkPoint*>(fVertexBuffer->map()); 84 fVertices = fVertexBuffer->map();
81 } else { 85 } else {
82 fVertices = new SkPoint[vertexCount]; 86 fVertices = sk_malloc_throw(vertexCount * stride());
83 } 87 }
84 return fVertices; 88 return fVertices;
85 } 89 }
86 void unlock(int actualCount) override { 90 void unlock(int actualCount) override {
87 if (fCanMapVB) { 91 if (fCanMapVB) {
88 fVertexBuffer->unmap(); 92 fVertexBuffer->unmap();
89 } else { 93 } else {
90 fVertexBuffer->updateData(fVertices, actualCount * sizeof(SkPoint)); 94 fVertexBuffer->updateData(fVertices, actualCount * stride());
91 delete[] fVertices; 95 sk_free(fVertices);
92 } 96 }
93 fVertices = nullptr; 97 fVertices = nullptr;
94 } 98 }
95 GrBuffer* vertexBuffer() { return fVertexBuffer.get(); } 99 GrBuffer* vertexBuffer() { return fVertexBuffer.get(); }
96 private: 100 private:
97 SkAutoTUnref<GrBuffer> fVertexBuffer; 101 SkAutoTUnref<GrBuffer> fVertexBuffer;
98 GrResourceProvider* fResourceProvider; 102 GrResourceProvider* fResourceProvider;
99 bool fCanMapVB; 103 bool fCanMapVB;
100 SkPoint* fVertices; 104 void* fVertices;
105 };
106
107 class DynamicVertexAllocator : public GrTessellator::VertexAllocator {
108 public:
109 DynamicVertexAllocator(size_t stride, GrVertexBatch::Target* target)
110 : VertexAllocator(stride)
111 , fTarget(target)
112 , fVertexBuffer(nullptr)
113 , fVertices(nullptr) {
114 }
115 void* lock(int vertexCount) override {
116 fVertexCount = vertexCount;
117 fVertices = fTarget->makeVertexSpace(stride(), vertexCount, &fVertexBuff er, &fFirstVertex);
118 return fVertices;
119 }
120 void unlock(int actualCount) override {
121 fTarget->putBackVertices(fVertexCount - actualCount, stride());
122 fVertices = nullptr;
123 }
124 const GrBuffer* vertexBuffer() const { return fVertexBuffer; }
125 int firstVertex() const { return fFirstVertex; }
126 private:
127 GrVertexBatch::Target* fTarget;
128 const GrBuffer* fVertexBuffer;
129 int fVertexCount;
130 int fFirstVertex;
131 void* fVertices;
101 }; 132 };
102 133
103 } // namespace 134 } // namespace
104 135
105 GrTessellatingPathRenderer::GrTessellatingPathRenderer() { 136 GrTessellatingPathRenderer::GrTessellatingPathRenderer() {
106 } 137 }
107 138
108 bool GrTessellatingPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) cons t { 139 bool GrTessellatingPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) cons t {
109 // This path renderer can draw fill styles but does not do antialiasing. It can do convex and 140 // This path renderer can draw fill styles, and can do screenspace antialias ing via a
110 // concave paths, but we'll leave the convex ones to simpler algorithms. We pass on paths that 141 // one-pixel coverage ramp. It can do convex and concave paths, but we'll le ave the convex
111 // have styles, though they may come back around after applying the styling information to the 142 // ones to simpler algorithms. We pass on paths that have styles, though the y may come back
112 // geometry to create a filled path. We also skip paths that don't have a ke y since the real 143 // around after applying the styling information to the geometry to create a filled path. In
113 // advantage of this path renderer comes from caching the tessellated geomet ry. 144 // the non-AA case, We skip paths thta don't have a key since the real advan tage of this path
114 return !args.fShape->style().applies() && args.fShape->style().isSimpleFill( ) && 145 // renderer comes from caching the tessellated geometry. In the AA case, we do not cache, so we
115 !args.fAntiAlias && args.fShape->hasUnstyledKey() && !args.fShape->kn ownToBeConvex(); 146 // accept paths without keys.
147 if (!args.fShape->style().isSimpleFill() || args.fShape->knownToBeConvex()) {
148 return false;
149 }
150 if (args.fAntiAlias) {
151 #ifdef SK_DISABLE_SCREENSPACE_TESS_AA_PATH_RENDERER
152 return false;
153 #else
154 SkPath path;
155 args.fShape->asPath(&path);
156 if (path.countVerbs() > 10) {
157 return false;
158 }
159 #endif
160 } else if (!args.fShape->hasUnstyledKey()) {
161 return false;
162 }
163 return true;
116 } 164 }
117 165
118 class TessellatingPathBatch : public GrVertexBatch { 166 class TessellatingPathBatch : public GrVertexBatch {
119 public: 167 public:
120 DEFINE_BATCH_CLASS_ID 168 DEFINE_BATCH_CLASS_ID
121 169
122 static GrDrawBatch* Create(const GrColor& color, 170 static GrDrawBatch* Create(const GrColor& color,
123 const GrShape& shape, 171 const GrShape& shape,
124 const SkMatrix& viewMatrix, 172 const SkMatrix& viewMatrix,
125 SkRect clipBounds) { 173 SkIRect devClipBounds,
126 return new TessellatingPathBatch(color, shape, viewMatrix, clipBounds); 174 bool antiAlias) {
175 return new TessellatingPathBatch(color, shape, viewMatrix, devClipBounds , antiAlias);
127 } 176 }
128 177
129 const char* name() const override { return "TessellatingPathBatch"; } 178 const char* name() const override { return "TessellatingPathBatch"; }
130 179
131 void computePipelineOptimizations(GrInitInvariantOutput* color, 180 void computePipelineOptimizations(GrInitInvariantOutput* color,
132 GrInitInvariantOutput* coverage, 181 GrInitInvariantOutput* coverage,
133 GrBatchToXPOverrides* overrides) const ove rride { 182 GrBatchToXPOverrides* overrides) const ove rride {
134 color->setKnownFourComponents(fColor); 183 color->setKnownFourComponents(fColor);
135 coverage->setUnknownSingleComponent(); 184 coverage->setUnknownSingleComponent();
136 } 185 }
137 186
138 private: 187 private:
139 void initBatchTracker(const GrXPOverridesForBatch& overrides) override { 188 void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
140 // Handle any color overrides 189 // Handle any color overrides
141 if (!overrides.readsColor()) { 190 if (!overrides.readsColor()) {
142 fColor = GrColor_ILLEGAL; 191 fColor = GrColor_ILLEGAL;
143 } 192 }
144 overrides.getOverrideColorIfSet(&fColor); 193 overrides.getOverrideColorIfSet(&fColor);
145 fPipelineInfo = overrides; 194 fPipelineInfo = overrides;
146 } 195 }
147 196
148 void draw(Target* target, const GrGeometryProcessor* gp) const { 197 SkPath getPath() const {
149 GrResourceProvider* rp = target->resourceProvider(); 198 SkASSERT(!fShape.style().applies());
150 SkScalar screenSpaceTol = GrPathUtils::kDefaultTolerance;
151 SkScalar tol = GrPathUtils::scaleToleranceToSrc(screenSpaceTol, fViewMat rix,
152 fShape.bounds());
153
154 SkPath path; 199 SkPath path;
155 fShape.asPath(&path); 200 fShape.asPath(&path);
156 bool inverseFill = path.isInverseFillType(); 201 return path;
202 }
203
204 void draw(Target* target, const GrGeometryProcessor* gp) const {
205 SkASSERT(!fAntiAlias);
206 GrResourceProvider* rp = target->resourceProvider();
207 bool inverseFill = fShape.inverseFilled();
157 // construct a cache key from the path's genID and the view matrix 208 // construct a cache key from the path's genID and the view matrix
158 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain() ; 209 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain() ;
159 GrUniqueKey key; 210 GrUniqueKey key;
160 static constexpr int kClipBoundsCnt = sizeof(fClipBounds) / sizeof(uint3 2_t); 211 static constexpr int kClipBoundsCnt = sizeof(fDevClipBounds) / sizeof(ui nt32_t);
161 int shapeKeyDataCnt = fShape.unstyledKeySize(); 212 int shapeKeyDataCnt = fShape.unstyledKeySize();
162 SkASSERT(shapeKeyDataCnt >= 0); 213 SkASSERT(shapeKeyDataCnt >= 0);
163 GrUniqueKey::Builder builder(&key, kDomain, shapeKeyDataCnt + kClipBound sCnt); 214 GrUniqueKey::Builder builder(&key, kDomain, shapeKeyDataCnt + kClipBound sCnt);
164 fShape.writeUnstyledKey(&builder[0]); 215 fShape.writeUnstyledKey(&builder[0]);
165 // For inverse fills, the tessellation is dependent on clip bounds. 216 // For inverse fills, the tessellation is dependent on clip bounds.
166 if (inverseFill) { 217 if (inverseFill) {
167 memcpy(&builder[shapeKeyDataCnt], &fClipBounds, sizeof(fClipBounds)) ; 218 memcpy(&builder[shapeKeyDataCnt], &fDevClipBounds, sizeof(fDevClipBo unds));
168 } else { 219 } else {
169 memset(&builder[shapeKeyDataCnt], 0, sizeof(fClipBounds)); 220 memset(&builder[shapeKeyDataCnt], 0, sizeof(fDevClipBounds));
170 } 221 }
171 builder.finish(); 222 builder.finish();
172 SkAutoTUnref<GrBuffer> cachedVertexBuffer(rp->findAndRefTByUniqueKey<GrB uffer>(key)); 223 SkAutoTUnref<GrBuffer> cachedVertexBuffer(rp->findAndRefTByUniqueKey<GrB uffer>(key));
173 int actualCount; 224 int actualCount;
225 SkScalar tol = GrPathUtils::kDefaultTolerance;
226 tol = GrPathUtils::scaleToleranceToSrc(tol, fViewMatrix, fShape.bounds() );
174 if (cache_match(cachedVertexBuffer.get(), tol, &actualCount)) { 227 if (cache_match(cachedVertexBuffer.get(), tol, &actualCount)) {
175 this->drawVertices(target, gp, cachedVertexBuffer.get(), 0, actualCo unt); 228 this->drawVertices(target, gp, cachedVertexBuffer.get(), 0, actualCo unt);
176 return; 229 return;
177 } 230 }
178 231
232 SkRect clipBounds = SkRect::Make(fDevClipBounds);
233
234 SkMatrix vmi;
235 if (!fViewMatrix.invert(&vmi)) {
236 return;
237 }
238 vmi.mapRect(&clipBounds);
179 bool isLinear; 239 bool isLinear;
180 bool canMapVB = GrCaps::kNone_MapFlags != target->caps().mapBufferFlags( ); 240 bool canMapVB = GrCaps::kNone_MapFlags != target->caps().mapBufferFlags( );
181 StaticVertexAllocator allocator(rp, canMapVB); 241 StaticVertexAllocator allocator(gp->getVertexStride(), rp, canMapVB);
182 int count = GrTessellator::PathToTriangles(path, tol, fClipBounds, &allo cator, &isLinear); 242 int count = GrTessellator::PathToTriangles(getPath(), tol, clipBounds, & allocator,
243 false, GrColor(), false, &isL inear);
183 if (count == 0) { 244 if (count == 0) {
184 return; 245 return;
185 } 246 }
186 this->drawVertices(target, gp, allocator.vertexBuffer(), 0, count); 247 this->drawVertices(target, gp, allocator.vertexBuffer(), 0, count);
187 TessInfo info; 248 TessInfo info;
188 info.fTolerance = isLinear ? 0 : tol; 249 info.fTolerance = isLinear ? 0 : tol;
189 info.fCount = count; 250 info.fCount = count;
190 key.setCustomData(SkData::MakeWithCopy(&info, sizeof(info))); 251 key.setCustomData(SkData::MakeWithCopy(&info, sizeof(info)));
191 rp->assignUniqueKeyToResource(key, allocator.vertexBuffer()); 252 rp->assignUniqueKeyToResource(key, allocator.vertexBuffer());
192 } 253 }
193 254
255 void drawAA(Target* target, const GrGeometryProcessor* gp) const {
256 SkASSERT(fAntiAlias);
257 SkPath path = getPath();
258 if (path.isEmpty()) {
259 return;
260 }
261 SkRect clipBounds = SkRect::Make(fDevClipBounds);
262 path.transform(fViewMatrix);
263 SkScalar tol = GrPathUtils::kDefaultTolerance;
264 bool isLinear;
265 DynamicVertexAllocator allocator(gp->getVertexStride(), target);
266 bool canTweakAlphaForCoverage = fPipelineInfo.canTweakAlphaForCoverage() ;
267 int count = GrTessellator::PathToTriangles(path, tol, clipBounds, &alloc ator,
268 true, fColor, canTweakAlphaFo rCoverage,
269 &isLinear);
270 if (count == 0) {
271 return;
272 }
273 drawVertices(target, gp, allocator.vertexBuffer(), allocator.firstVertex (), count);
274 }
275
194 void onPrepareDraws(Target* target) const override { 276 void onPrepareDraws(Target* target) const override {
195 sk_sp<GrGeometryProcessor> gp; 277 sk_sp<GrGeometryProcessor> gp;
196 { 278 {
197 using namespace GrDefaultGeoProcFactory; 279 using namespace GrDefaultGeoProcFactory;
198 280
199 Color color(fColor); 281 Color color(fColor);
200 LocalCoords localCoords(fPipelineInfo.readsLocalCoords() ? 282 LocalCoords localCoords(fPipelineInfo.readsLocalCoords() ?
201 LocalCoords::kUsePosition_Type : 283 LocalCoords::kUsePosition_Type :
202 LocalCoords::kUnused_Type); 284 LocalCoords::kUnused_Type);
203 Coverage::Type coverageType; 285 Coverage::Type coverageType;
204 if (fPipelineInfo.readsCoverage()) { 286 if (fAntiAlias) {
287 color = Color(Color::kAttribute_Type);
288 if (fPipelineInfo.canTweakAlphaForCoverage()) {
289 coverageType = Coverage::kSolid_Type;
290 } else {
291 coverageType = Coverage::kAttribute_Type;
292 }
293 } else if (fPipelineInfo.readsCoverage()) {
205 coverageType = Coverage::kSolid_Type; 294 coverageType = Coverage::kSolid_Type;
206 } else { 295 } else {
207 coverageType = Coverage::kNone_Type; 296 coverageType = Coverage::kNone_Type;
208 } 297 }
209 Coverage coverage(coverageType); 298 Coverage coverage(coverageType);
210 gp = GrDefaultGeoProcFactory::Make(color, coverage, localCoords, fVi ewMatrix); 299 if (fAntiAlias) {
300 gp = GrDefaultGeoProcFactory::MakeForDeviceSpace(color, coverage , localCoords,
301 fViewMatrix);
302 } else {
303 gp = GrDefaultGeoProcFactory::Make(color, coverage, localCoords, fViewMatrix);
304 }
211 } 305 }
212 this->draw(target, gp.get()); 306 if (fAntiAlias) {
307 this->drawAA(target, gp.get());
308 } else {
309 this->draw(target, gp.get());
310 }
213 } 311 }
214 312
215 void drawVertices(Target* target, const GrGeometryProcessor* gp, const GrBuf fer* vb, 313 void drawVertices(Target* target, const GrGeometryProcessor* gp, const GrBuf fer* vb,
216 int firstVertex, int count) const { 314 int firstVertex, int count) const {
217 SkASSERT(gp->getVertexStride() == sizeof(SkPoint));
218
219 GrPrimitiveType primitiveType = TESSELLATOR_WIREFRAME ? kLines_GrPrimiti veType 315 GrPrimitiveType primitiveType = TESSELLATOR_WIREFRAME ? kLines_GrPrimiti veType
220 : kTriangles_GrPri mitiveType; 316 : kTriangles_GrPri mitiveType;
221 GrMesh mesh; 317 GrMesh mesh;
222 mesh.init(primitiveType, vb, firstVertex, count); 318 mesh.init(primitiveType, vb, firstVertex, count);
223 target->draw(gp, mesh); 319 target->draw(gp, mesh);
224 } 320 }
225 321
226 bool onCombineIfPossible(GrBatch*, const GrCaps&) override { return false; } 322 bool onCombineIfPossible(GrBatch*, const GrCaps&) override { return false; }
227 323
228 TessellatingPathBatch(const GrColor& color, 324 TessellatingPathBatch(const GrColor& color,
229 const GrShape& shape, 325 const GrShape& shape,
230 const SkMatrix& viewMatrix, 326 const SkMatrix& viewMatrix,
231 const SkRect& clipBounds) 327 const SkIRect& devClipBounds,
328 bool antiAlias)
232 : INHERITED(ClassID()) 329 : INHERITED(ClassID())
233 , fColor(color) 330 , fColor(color)
234 , fShape(shape) 331 , fShape(shape)
235 , fViewMatrix(viewMatrix) { 332 , fViewMatrix(viewMatrix)
236 const SkRect& pathBounds = shape.bounds(); 333 , fDevClipBounds(devClipBounds)
237 fClipBounds = clipBounds; 334 , fAntiAlias(antiAlias) {
238 // Because the clip bounds are used to add a contour for inverse fills, they must also 335 SkRect devBounds;
239 // include the path bounds. 336 viewMatrix.mapRect(&devBounds, shape.bounds());
240 fClipBounds.join(pathBounds); 337 if (shape.inverseFilled()) {
241 const SkRect& srcBounds = shape.inverseFilled() ? fClipBounds : pathBoun ds; 338 // Because the clip bounds are used to add a contour for inverse fil ls, they must also
242 this->setTransformedBounds(srcBounds, viewMatrix, HasAABloat::kNo, IsZer oArea::kNo); 339 // include the path bounds.
340 devBounds.join(SkRect::Make(fDevClipBounds));
341 }
342 this->setBounds(devBounds, HasAABloat::kNo, IsZeroArea::kNo);
243 } 343 }
244 344
245 GrColor fColor; 345 GrColor fColor;
246 GrShape fShape; 346 GrShape fShape;
247 SkMatrix fViewMatrix; 347 SkMatrix fViewMatrix;
248 SkRect fClipBounds; // in source space 348 SkIRect fDevClipBounds;
349 bool fAntiAlias;
249 GrXPOverridesForBatch fPipelineInfo; 350 GrXPOverridesForBatch fPipelineInfo;
250 351
251 typedef GrVertexBatch INHERITED; 352 typedef GrVertexBatch INHERITED;
252 }; 353 };
253 354
254 bool GrTessellatingPathRenderer::onDrawPath(const DrawPathArgs& args) { 355 bool GrTessellatingPathRenderer::onDrawPath(const DrawPathArgs& args) {
255 GR_AUDIT_TRAIL_AUTO_FRAME(args.fDrawContext->auditTrail(), 356 GR_AUDIT_TRAIL_AUTO_FRAME(args.fDrawContext->auditTrail(),
256 "GrTessellatingPathRenderer::onDrawPath"); 357 "GrTessellatingPathRenderer::onDrawPath");
257 SkASSERT(!args.fAntiAlias);
258
259 SkIRect clipBoundsI; 358 SkIRect clipBoundsI;
260 args.fClip->getConservativeBounds(args.fDrawContext->width(), args.fDrawCont ext->height(), 359 args.fClip->getConservativeBounds(args.fDrawContext->width(), args.fDrawCont ext->height(),
261 &clipBoundsI); 360 &clipBoundsI);
262 SkRect clipBounds = SkRect::Make(clipBoundsI);
263 SkMatrix vmi;
264 if (!args.fViewMatrix->invert(&vmi)) {
265 return false;
266 }
267 vmi.mapRect(&clipBounds);
268 SkPath path;
269 args.fShape->asPath(&path);
270 SkAutoTUnref<GrDrawBatch> batch(TessellatingPathBatch::Create(args.fPaint->g etColor(), 361 SkAutoTUnref<GrDrawBatch> batch(TessellatingPathBatch::Create(args.fPaint->g etColor(),
271 *args.fShape, 362 *args.fShape,
272 *args.fViewMat rix, clipBounds)); 363 *args.fViewMat rix,
364 clipBoundsI,
365 args.fAntiAlia s));
273 366
274 GrPipelineBuilder pipelineBuilder(*args.fPaint, args.fDrawContext->mustUseHW AA(*args.fPaint)); 367 GrPipelineBuilder pipelineBuilder(*args.fPaint, args.fDrawContext->mustUseHW AA(*args.fPaint));
275 pipelineBuilder.setUserStencil(args.fUserStencilSettings); 368 pipelineBuilder.setUserStencil(args.fUserStencilSettings);
276 369
277 args.fDrawContext->drawBatch(pipelineBuilder, *args.fClip, batch); 370 args.fDrawContext->drawBatch(pipelineBuilder, *args.fClip, batch);
278 371
279 return true; 372 return true;
280 } 373 }
281 374
282 //////////////////////////////////////////////////////////////////////////////// /////////////////// 375 //////////////////////////////////////////////////////////////////////////////// ///////////////////
283 376
284 #ifdef GR_TEST_UTILS 377 #ifdef GR_TEST_UTILS
285 378
286 DRAW_BATCH_TEST_DEFINE(TesselatingPathBatch) { 379 DRAW_BATCH_TEST_DEFINE(TesselatingPathBatch) {
287 GrColor color = GrRandomColor(random); 380 GrColor color = GrRandomColor(random);
288 SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random); 381 SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random);
289 SkPath path = GrTest::TestPath(random); 382 SkPath path = GrTest::TestPath(random);
290 SkRect clipBounds = GrTest::TestRect(random); 383 SkIRect devClipBounds = SkIRect::MakeXYWH(
291 SkMatrix vmi; 384 random->nextU(), random->nextU(), random->nextU(), random->nextU());
292 bool result = viewMatrix.invert(&vmi); 385 bool antiAlias = random->nextBool();
293 if (!result) {
294 SkFAIL("Cannot invert matrix\n");
295 }
296 vmi.mapRect(&clipBounds);
297 GrStyle style; 386 GrStyle style;
298 do { 387 do {
299 GrTest::TestStyle(random, &style); 388 GrTest::TestStyle(random, &style);
300 } while (style.strokeRec().isHairlineStyle()); 389 } while (!style.isSimpleFill());
301 GrShape shape(path, style); 390 GrShape shape(path, style);
302 return TessellatingPathBatch::Create(color, shape, viewMatrix, clipBounds); 391 return TessellatingPathBatch::Create(color, shape, viewMatrix, devClipBounds , antiAlias);
303 } 392 }
304 393
305 #endif 394 #endif
OLDNEW
« no previous file with comments | « src/gpu/GrTessellator.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698