OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2015 Google Inc. | 3 * Copyright 2015 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 #include "GrBatchTest.h" | 9 #include "GrBatchTest.h" |
10 #include "GrColor.h" | 10 #include "GrColor.h" |
11 #include "GrDrawContext.h" | 11 #include "GrDrawContext.h" |
12 #include "GrDrawContextPriv.h" | |
13 #include "GrDrawingManager.h" | 12 #include "GrDrawingManager.h" |
14 #include "GrOvalRenderer.h" | 13 #include "GrOvalRenderer.h" |
15 #include "GrPathRenderer.h" | 14 #include "GrPathRenderer.h" |
16 #include "GrRenderTarget.h" | 15 #include "GrRenderTarget.h" |
17 #include "GrRenderTargetPriv.h" | 16 #include "GrRenderTargetPriv.h" |
18 #include "GrResourceProvider.h" | 17 #include "GrResourceProvider.h" |
19 #include "SkSurfacePriv.h" | 18 #include "SkSurfacePriv.h" |
20 | 19 |
21 #include "batches/GrBatch.h" | 20 #include "batches/GrBatch.h" |
22 #include "batches/GrDrawAtlasBatch.h" | 21 #include "batches/GrDrawAtlasBatch.h" |
23 #include "batches/GrDrawVerticesBatch.h" | 22 #include "batches/GrDrawVerticesBatch.h" |
24 #include "batches/GrRectBatchFactory.h" | 23 #include "batches/GrRectBatchFactory.h" |
25 #include "batches/GrNinePatch.h" // TODO Factory | 24 #include "batches/GrNinePatch.h" // TODO Factory |
26 | 25 |
27 #include "effects/GrRRectEffect.h" | 26 #include "effects/GrRRectEffect.h" |
28 | 27 |
29 #include "text/GrAtlasTextContext.h" | 28 #include "text/GrAtlasTextContext.h" |
30 #include "text/GrStencilAndCoverTextContext.h" | 29 #include "text/GrStencilAndCoverTextContext.h" |
31 | 30 |
32 #include "../private/GrAuditTrail.h" | 31 #include "../private/GrAuditTrail.h" |
33 | 32 |
34 #define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == fDrawingM
anager->getContext()) | 33 #define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == fDrawingM
anager->getContext()) |
35 #define ASSERT_SINGLE_OWNER \ | 34 #define ASSERT_SINGLE_OWNER \ |
36 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);) | 35 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);) |
37 #define ASSERT_SINGLE_OWNER_PRIV \ | |
38 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fDrawContext->fSing
leOwner);) | |
39 #define RETURN_IF_ABANDONED if (fDrawingManager->abandoned()) { return; } | 36 #define RETURN_IF_ABANDONED if (fDrawingManager->abandoned()) { return; } |
40 #define RETURN_FALSE_IF_ABANDONED if (fDrawingManager->abandoned()) { return fa
lse; } | 37 #define RETURN_FALSE_IF_ABANDONED if (fDrawingManager->abandoned()) { return fa
lse; } |
41 #define RETURN_FALSE_IF_ABANDONED_PRIV if (fDrawContext->fDrawingManager->aband
oned()) { return false; } | |
42 #define RETURN_NULL_IF_ABANDONED if (fDrawingManager->abandoned()) { return nu
llptr; } | 38 #define RETURN_NULL_IF_ABANDONED if (fDrawingManager->abandoned()) { return nu
llptr; } |
43 | 39 |
44 class AutoCheckFlush { | 40 class AutoCheckFlush { |
45 public: | 41 public: |
46 AutoCheckFlush(GrDrawingManager* drawingManager) : fDrawingManager(drawingMa
nager) { | 42 AutoCheckFlush(GrDrawingManager* drawingManager) : fDrawingManager(drawingMa
nager) { |
47 SkASSERT(fDrawingManager); | 43 SkASSERT(fDrawingManager); |
48 } | 44 } |
49 ~AutoCheckFlush() { fDrawingManager->getContext()->flushIfNecessary(); } | 45 ~AutoCheckFlush() { fDrawingManager->getContext()->flushIfNecessary(); } |
50 | 46 |
51 private: | 47 private: |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
247 } | 243 } |
248 | 244 |
249 static bool view_matrix_ok_for_aa_fill_rect(const SkMatrix& viewMatrix) { | 245 static bool view_matrix_ok_for_aa_fill_rect(const SkMatrix& viewMatrix) { |
250 return viewMatrix.preservesRightAngles(); | 246 return viewMatrix.preservesRightAngles(); |
251 } | 247 } |
252 | 248 |
253 static bool should_apply_coverage_aa(const GrPaint& paint, GrRenderTarget* rt) { | 249 static bool should_apply_coverage_aa(const GrPaint& paint, GrRenderTarget* rt) { |
254 return paint.isAntiAlias() && !rt->isUnifiedMultisampled(); | 250 return paint.isAntiAlias() && !rt->isUnifiedMultisampled(); |
255 } | 251 } |
256 | 252 |
257 GrDrawBatch* GrDrawContext::getFillRectBatch(const GrPaint& paint, | |
258 const SkMatrix& viewMatrix, | |
259 const SkRect& rect) { | |
260 | |
261 GrDrawBatch* batch = nullptr; | |
262 if (should_apply_coverage_aa(paint, fRenderTarget)) { | |
263 // The fill path can handle rotation but not skew. | |
264 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) { | |
265 SkRect devBoundRect; | |
266 viewMatrix.mapRect(&devBoundRect, rect); | |
267 batch = GrRectBatchFactory::CreateAAFill(paint.getColor(), viewMatri
x, | |
268 rect, devBoundRect); | |
269 } | |
270 } else { | |
271 // filled BW rect | |
272 batch = GrRectBatchFactory::CreateNonAAFill(paint.getColor(), viewMatrix
, rect, | |
273 nullptr, nullptr); | |
274 } | |
275 | |
276 return batch; | |
277 } | |
278 | |
279 void GrDrawContext::drawRect(const GrClip& clip, | 253 void GrDrawContext::drawRect(const GrClip& clip, |
280 const GrPaint& paint, | 254 const GrPaint& paint, |
281 const SkMatrix& viewMatrix, | 255 const SkMatrix& viewMatrix, |
282 const SkRect& rect, | 256 const SkRect& rect, |
283 const GrStrokeInfo* strokeInfo) { | 257 const GrStrokeInfo* strokeInfo) { |
284 ASSERT_SINGLE_OWNER | 258 ASSERT_SINGLE_OWNER |
285 RETURN_IF_ABANDONED | 259 RETURN_IF_ABANDONED |
286 SkDEBUGCODE(this->validate();) | 260 SkDEBUGCODE(this->validate();) |
287 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawRect"); | 261 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawRect"); |
288 | 262 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
322 if (paint.isConstantBlendedColor(&clearColor)) { | 296 if (paint.isConstantBlendedColor(&clearColor)) { |
323 this->getDrawTarget()->clear(nullptr, clearColor, true, fRen
derTarget); | 297 this->getDrawTarget()->clear(nullptr, clearColor, true, fRen
derTarget); |
324 return; | 298 return; |
325 } | 299 } |
326 } | 300 } |
327 } | 301 } |
328 } | 302 } |
329 | 303 |
330 bool snapToPixelCenters = false; | 304 bool snapToPixelCenters = false; |
331 SkAutoTUnref<GrDrawBatch> batch; | 305 SkAutoTUnref<GrDrawBatch> batch; |
332 if (width < 0) { | 306 if (should_apply_coverage_aa(paint, fRenderTarget)) { |
333 batch.reset(this->getFillRectBatch(paint, viewMatrix, rect)); | 307 if (width >= 0) { |
334 } else { | |
335 GrColor color = paint.getColor(); | |
336 | |
337 if (should_apply_coverage_aa(paint, fRenderTarget)) { | |
338 // The stroke path needs the rect to remain axis aligned (no rotatio
n or skew). | 308 // The stroke path needs the rect to remain axis aligned (no rotatio
n or skew). |
339 if (viewMatrix.rectStaysRect()) { | 309 if (viewMatrix.rectStaysRect()) { |
340 batch.reset(GrRectBatchFactory::CreateAAStroke(color, viewMatrix
, rect, | 310 batch.reset(GrRectBatchFactory::CreateAAStroke(paint.getColor(),
viewMatrix, rect, |
341 *strokeInfo)); | 311 *strokeInfo)); |
342 } | 312 } |
343 } else { | 313 } else { |
344 // Non-AA hairlines are snapped to pixel centers to make which pixel
s are hit | 314 // The fill path can handle rotation but not skew. |
345 // deterministic | 315 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) { |
346 snapToPixelCenters = (0 == width && !fRenderTarget->isUnifiedMultisa
mpled()); | 316 SkRect devBoundRect; |
347 batch.reset(GrRectBatchFactory::CreateNonAAStroke(color, viewMatrix,
rect, | 317 viewMatrix.mapRect(&devBoundRect, rect); |
348 width, snapToPixel
Centers)); | 318 batch.reset(GrRectBatchFactory::CreateAAFill(paint.getColor(), v
iewMatrix, rect, |
| 319 devBoundRect)); |
| 320 } |
| 321 } |
| 322 } else if (width >= 0) { |
| 323 // Non-AA hairlines are snapped to pixel centers to make which pixels ar
e hit deterministic |
| 324 snapToPixelCenters = (0 == width && !fRenderTarget->isUnifiedMultisample
d()); |
| 325 batch.reset(GrRectBatchFactory::CreateNonAAStroke(paint.getColor(), view
Matrix, rect, |
| 326 width, snapToPixelCent
ers)); |
349 | 327 |
350 // Depending on sub-pixel coordinates and the particular GPU, we may
lose a corner of | 328 // Depending on sub-pixel coordinates and the particular GPU, we may los
e a corner of |
351 // hairline rects. We jam all the vertices to pixel centers to avoid
this, but not | 329 // hairline rects. We jam all the vertices to pixel centers to avoid thi
s, but not when |
352 // when MSAA is enabled because it can cause ugly artifacts. | 330 // MSAA is enabled because it can cause ugly artifacts. |
353 } | 331 } else { |
| 332 // filled BW rect |
| 333 batch.reset(GrRectBatchFactory::CreateNonAAFill(paint.getColor(), viewMa
trix, rect, |
| 334 nullptr, nullptr)); |
354 } | 335 } |
355 | 336 |
356 if (batch) { | 337 if (batch) { |
357 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip); | 338 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip); |
358 | 339 |
359 if (snapToPixelCenters) { | 340 if (snapToPixelCenters) { |
360 pipelineBuilder.setState(GrPipelineBuilder::kSnapVerticesToPixelCent
ers_Flag, | 341 pipelineBuilder.setState(GrPipelineBuilder::kSnapVerticesToPixelCent
ers_Flag, |
361 snapToPixelCenters); | 342 snapToPixelCenters); |
362 } | 343 } |
363 | 344 |
364 this->getDrawTarget()->drawBatch(pipelineBuilder, batch); | 345 this->getDrawTarget()->drawBatch(pipelineBuilder, batch); |
365 return; | 346 return; |
366 } | 347 } |
367 | 348 |
368 SkPath path; | 349 SkPath path; |
369 path.setIsVolatile(true); | 350 path.setIsVolatile(true); |
370 path.addRect(rect); | 351 path.addRect(rect); |
371 this->internalDrawPath(clip, paint, viewMatrix, path, | 352 this->internalDrawPath(clip, paint, viewMatrix, path, |
372 strokeInfo ? *strokeInfo : GrStrokeInfo::FillInfo()); | 353 strokeInfo ? *strokeInfo : GrStrokeInfo::FillInfo()); |
373 } | 354 } |
374 | 355 |
375 bool GrDrawContextPriv::drawAndStencilRect(const SkIRect* scissorRect, | |
376 const GrStencilSettings& ss, | |
377 SkRegion::Op op, | |
378 bool invert, | |
379 bool doAA, | |
380 const SkMatrix& viewMatrix, | |
381 const SkRect& rect) { | |
382 ASSERT_SINGLE_OWNER_PRIV | |
383 RETURN_FALSE_IF_ABANDONED_PRIV | |
384 SkDEBUGCODE(fDrawContext->validate();) | |
385 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::stencilRect"); | |
386 | |
387 AutoCheckFlush acf(fDrawContext->fDrawingManager); | |
388 | |
389 GrPaint paint; | |
390 paint.setAntiAlias(doAA); | |
391 paint.setCoverageSetOpXPFactory(op, invert); | |
392 | |
393 SkAutoTUnref<GrDrawBatch> batch(fDrawContext->getFillRectBatch(paint, viewMa
trix, rect)); | |
394 if (batch) { | |
395 GrPipelineBuilder pipelineBuilder(paint, fDrawContext->fRenderTarget, Gr
Clip::WideOpen()); | |
396 pipelineBuilder.setStencil(ss); | |
397 | |
398 fDrawContext->getDrawTarget()->drawBatch(pipelineBuilder, batch, scissor
Rect); | |
399 return true; | |
400 } | |
401 | |
402 SkPath path; | |
403 path.setIsVolatile(true); | |
404 path.addRect(rect); | |
405 return this->drawAndStencilPath(scissorRect, ss, op, invert, doAA, viewMatri
x, path); | |
406 } | |
407 | |
408 void GrDrawContext::fillRectToRect(const GrClip& clip, | 356 void GrDrawContext::fillRectToRect(const GrClip& clip, |
409 const GrPaint& paint, | 357 const GrPaint& paint, |
410 const SkMatrix& viewMatrix, | 358 const SkMatrix& viewMatrix, |
411 const SkRect& rectToDraw, | 359 const SkRect& rectToDraw, |
412 const SkRect& localRect) { | 360 const SkRect& localRect) { |
413 ASSERT_SINGLE_OWNER | 361 ASSERT_SINGLE_OWNER |
414 RETURN_IF_ABANDONED | 362 RETURN_IF_ABANDONED |
415 SkDEBUGCODE(this->validate();) | 363 SkDEBUGCODE(this->validate();) |
416 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::fillRectToRect"); | 364 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::fillRectToRect"); |
417 | 365 |
(...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
846 } | 794 } |
847 | 795 |
848 // Note that internalDrawPath may sw-rasterize the path into a scratch textu
re. | 796 // Note that internalDrawPath may sw-rasterize the path into a scratch textu
re. |
849 // Scratch textures can be recycled after they are returned to the texture | 797 // Scratch textures can be recycled after they are returned to the texture |
850 // cache. This presents a potential hazard for buffered drawing. However, | 798 // cache. This presents a potential hazard for buffered drawing. However, |
851 // the writePixels that uploads to the scratch will perform a flush so we're | 799 // the writePixels that uploads to the scratch will perform a flush so we're |
852 // OK. | 800 // OK. |
853 this->internalDrawPath(clip, paint, viewMatrix, path, strokeInfo); | 801 this->internalDrawPath(clip, paint, viewMatrix, path, strokeInfo); |
854 } | 802 } |
855 | 803 |
856 bool GrDrawContextPriv::drawAndStencilPath(const SkIRect* scissorRect, | |
857 const GrStencilSettings& ss, | |
858 SkRegion::Op op, | |
859 bool invert, | |
860 bool doAA, | |
861 const SkMatrix& viewMatrix, | |
862 const SkPath& path) { | |
863 ASSERT_SINGLE_OWNER_PRIV | |
864 RETURN_FALSE_IF_ABANDONED_PRIV | |
865 SkDEBUGCODE(fDrawContext->validate();) | |
866 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawPath"); | |
867 | |
868 if (path.isEmpty() && path.isInverseFillType()) { | |
869 this->drawAndStencilRect(scissorRect, ss, op, invert, false, SkMatrix::I
(), | |
870 SkRect::MakeIWH(fDrawContext->fRenderTarget->wi
dth(), | |
871 fDrawContext->fRenderTarget->he
ight())); | |
872 return true; | |
873 } | |
874 | |
875 AutoCheckFlush acf(fDrawContext->fDrawingManager); | |
876 | |
877 // An Assumption here is that path renderer would use some form of tweaking | |
878 // the src color (either the input alpha or in the frag shader) to implement | |
879 // aa. If we have some future driver-mojo path AA that can do the right | |
880 // thing WRT to the blend then we'll need some query on the PR. | |
881 bool useCoverageAA = doAA && !fDrawContext->fRenderTarget->isUnifiedMultisam
pled(); | |
882 bool isStencilDisabled = true; | |
883 bool isStencilBufferMSAA = fDrawContext->fRenderTarget->isStencilBufferMulti
sampled(); | |
884 | |
885 const GrPathRendererChain::DrawType type = | |
886 useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType | |
887 : GrPathRendererChain::kColor_DrawType; | |
888 | |
889 GrPathRenderer::CanDrawPathArgs canDrawArgs; | |
890 canDrawArgs.fShaderCaps = fDrawContext->fDrawingManager->getContext()->caps(
)->shaderCaps(); | |
891 canDrawArgs.fViewMatrix = &viewMatrix; | |
892 canDrawArgs.fPath = &path; | |
893 canDrawArgs.fStroke = &GrStrokeInfo::FillInfo(); | |
894 canDrawArgs.fAntiAlias = useCoverageAA; | |
895 canDrawArgs.fIsStencilDisabled = isStencilDisabled; | |
896 canDrawArgs.fIsStencilBufferMSAA = isStencilBufferMSAA; | |
897 | |
898 // Don't allow the SW renderer | |
899 GrPathRenderer* pr = fDrawContext->fDrawingManager->getPathRenderer(canDrawA
rgs, false, type); | |
900 if (!pr) { | |
901 return false; | |
902 } | |
903 | |
904 GrPaint paint; | |
905 paint.setCoverageSetOpXPFactory(op, invert); | |
906 | |
907 // TODO: it is unfortunate that we have to convert this to a GrClip to | |
908 // call drawPath. | |
909 GrClip clip; | |
910 if (scissorRect) { | |
911 clip.setIRect(*scissorRect); | |
912 } | |
913 | |
914 GrPipelineBuilder pipelineBuilder(paint, fDrawContext->fRenderTarget, clip); | |
915 pipelineBuilder.setStencil(ss); | |
916 | |
917 GrPathRenderer::DrawPathArgs args; | |
918 args.fTarget = fDrawContext->getDrawTarget(); | |
919 args.fResourceProvider = fDrawContext->fDrawingManager->getContext()->resour
ceProvider(); | |
920 args.fPipelineBuilder = &pipelineBuilder; | |
921 args.fColor = GrColor_WHITE; | |
922 args.fViewMatrix = &viewMatrix; | |
923 args.fPath = &path; | |
924 args.fStroke = &GrStrokeInfo::FillInfo(); | |
925 args.fAntiAlias = useCoverageAA; | |
926 pr->drawPath(args); | |
927 return true; | |
928 } | |
929 | |
930 void GrDrawContext::internalDrawPath(const GrClip& clip, | 804 void GrDrawContext::internalDrawPath(const GrClip& clip, |
931 const GrPaint& paint, | 805 const GrPaint& paint, |
932 const SkMatrix& viewMatrix, | 806 const SkMatrix& viewMatrix, |
933 const SkPath& path, | 807 const SkPath& path, |
934 const GrStrokeInfo& strokeInfo) { | 808 const GrStrokeInfo& strokeInfo) { |
935 ASSERT_SINGLE_OWNER | 809 ASSERT_SINGLE_OWNER |
936 RETURN_IF_ABANDONED | 810 RETURN_IF_ABANDONED |
937 SkASSERT(!path.isEmpty()); | 811 SkASSERT(!path.isEmpty()); |
938 | 812 |
939 // An Assumption here is that path renderer would use some form of tweaking | 813 // An Assumption here is that path renderer would use some form of tweaking |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1030 } | 904 } |
1031 | 905 |
1032 void GrDrawContext::drawBatch(GrPipelineBuilder* pipelineBuilder, GrDrawBatch* b
atch) { | 906 void GrDrawContext::drawBatch(GrPipelineBuilder* pipelineBuilder, GrDrawBatch* b
atch) { |
1033 ASSERT_SINGLE_OWNER | 907 ASSERT_SINGLE_OWNER |
1034 RETURN_IF_ABANDONED | 908 RETURN_IF_ABANDONED |
1035 SkDEBUGCODE(this->validate();) | 909 SkDEBUGCODE(this->validate();) |
1036 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawBatch"); | 910 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawBatch"); |
1037 | 911 |
1038 this->getDrawTarget()->drawBatch(*pipelineBuilder, batch); | 912 this->getDrawTarget()->drawBatch(*pipelineBuilder, batch); |
1039 } | 913 } |
OLD | NEW |