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" |
12 #include "GrDrawingManager.h" | 13 #include "GrDrawingManager.h" |
13 #include "GrOvalRenderer.h" | 14 #include "GrOvalRenderer.h" |
14 #include "GrPathRenderer.h" | 15 #include "GrPathRenderer.h" |
15 #include "GrRenderTarget.h" | 16 #include "GrRenderTarget.h" |
16 #include "GrRenderTargetPriv.h" | 17 #include "GrRenderTargetPriv.h" |
17 #include "GrResourceProvider.h" | 18 #include "GrResourceProvider.h" |
18 #include "SkSurfacePriv.h" | 19 #include "SkSurfacePriv.h" |
19 | 20 |
20 #include "batches/GrBatch.h" | 21 #include "batches/GrBatch.h" |
21 #include "batches/GrDrawAtlasBatch.h" | 22 #include "batches/GrDrawAtlasBatch.h" |
22 #include "batches/GrDrawVerticesBatch.h" | 23 #include "batches/GrDrawVerticesBatch.h" |
23 #include "batches/GrRectBatchFactory.h" | 24 #include "batches/GrRectBatchFactory.h" |
24 #include "batches/GrNinePatch.h" // TODO Factory | 25 #include "batches/GrNinePatch.h" // TODO Factory |
25 | 26 |
26 #include "effects/GrRRectEffect.h" | 27 #include "effects/GrRRectEffect.h" |
27 | 28 |
28 #include "text/GrAtlasTextContext.h" | 29 #include "text/GrAtlasTextContext.h" |
29 #include "text/GrStencilAndCoverTextContext.h" | 30 #include "text/GrStencilAndCoverTextContext.h" |
30 | 31 |
31 #include "../private/GrAuditTrail.h" | 32 #include "../private/GrAuditTrail.h" |
32 | 33 |
33 #define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == fDrawingM
anager->getContext()) | 34 #define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == fDrawingM
anager->getContext()) |
34 #define ASSERT_SINGLE_OWNER \ | 35 #define ASSERT_SINGLE_OWNER \ |
35 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);) | 36 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);) |
| 37 #define ASSERT_SINGLE_OWNER_PRIV \ |
| 38 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fDrawContext->fSing
leOwner);) |
36 #define RETURN_IF_ABANDONED if (fDrawingManager->abandoned()) { return; } | 39 #define RETURN_IF_ABANDONED if (fDrawingManager->abandoned()) { return; } |
37 #define RETURN_FALSE_IF_ABANDONED if (fDrawingManager->abandoned()) { return fa
lse; } | 40 #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; } |
38 #define RETURN_NULL_IF_ABANDONED if (fDrawingManager->abandoned()) { return nu
llptr; } | 42 #define RETURN_NULL_IF_ABANDONED if (fDrawingManager->abandoned()) { return nu
llptr; } |
39 | 43 |
40 class AutoCheckFlush { | 44 class AutoCheckFlush { |
41 public: | 45 public: |
42 AutoCheckFlush(GrDrawingManager* drawingManager) : fDrawingManager(drawingMa
nager) { | 46 AutoCheckFlush(GrDrawingManager* drawingManager) : fDrawingManager(drawingMa
nager) { |
43 SkASSERT(fDrawingManager); | 47 SkASSERT(fDrawingManager); |
44 } | 48 } |
45 ~AutoCheckFlush() { fDrawingManager->getContext()->flushIfNecessary(); } | 49 ~AutoCheckFlush() { fDrawingManager->getContext()->flushIfNecessary(); } |
46 | 50 |
47 private: | 51 private: |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
243 } | 247 } |
244 | 248 |
245 static bool view_matrix_ok_for_aa_fill_rect(const SkMatrix& viewMatrix) { | 249 static bool view_matrix_ok_for_aa_fill_rect(const SkMatrix& viewMatrix) { |
246 return viewMatrix.preservesRightAngles(); | 250 return viewMatrix.preservesRightAngles(); |
247 } | 251 } |
248 | 252 |
249 static bool should_apply_coverage_aa(const GrPaint& paint, GrRenderTarget* rt) { | 253 static bool should_apply_coverage_aa(const GrPaint& paint, GrRenderTarget* rt) { |
250 return paint.isAntiAlias() && !rt->isUnifiedMultisampled(); | 254 return paint.isAntiAlias() && !rt->isUnifiedMultisampled(); |
251 } | 255 } |
252 | 256 |
| 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 |
253 void GrDrawContext::drawRect(const GrClip& clip, | 279 void GrDrawContext::drawRect(const GrClip& clip, |
254 const GrPaint& paint, | 280 const GrPaint& paint, |
255 const SkMatrix& viewMatrix, | 281 const SkMatrix& viewMatrix, |
256 const SkRect& rect, | 282 const SkRect& rect, |
257 const GrStrokeInfo* strokeInfo) { | 283 const GrStrokeInfo* strokeInfo) { |
258 ASSERT_SINGLE_OWNER | 284 ASSERT_SINGLE_OWNER |
259 RETURN_IF_ABANDONED | 285 RETURN_IF_ABANDONED |
260 SkDEBUGCODE(this->validate();) | 286 SkDEBUGCODE(this->validate();) |
261 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawRect"); | 287 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawRect"); |
262 | 288 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
296 if (paint.isConstantBlendedColor(&clearColor)) { | 322 if (paint.isConstantBlendedColor(&clearColor)) { |
297 this->getDrawTarget()->clear(nullptr, clearColor, true, fRen
derTarget); | 323 this->getDrawTarget()->clear(nullptr, clearColor, true, fRen
derTarget); |
298 return; | 324 return; |
299 } | 325 } |
300 } | 326 } |
301 } | 327 } |
302 } | 328 } |
303 | 329 |
304 bool snapToPixelCenters = false; | 330 bool snapToPixelCenters = false; |
305 SkAutoTUnref<GrDrawBatch> batch; | 331 SkAutoTUnref<GrDrawBatch> batch; |
306 if (should_apply_coverage_aa(paint, fRenderTarget)) { | 332 if (width < 0) { |
307 if (width >= 0) { | 333 batch.reset(this->getFillRectBatch(paint, viewMatrix, rect)); |
| 334 } else { |
| 335 GrColor color = paint.getColor(); |
| 336 |
| 337 if (should_apply_coverage_aa(paint, fRenderTarget)) { |
308 // The stroke path needs the rect to remain axis aligned (no rotatio
n or skew). | 338 // The stroke path needs the rect to remain axis aligned (no rotatio
n or skew). |
309 if (viewMatrix.rectStaysRect()) { | 339 if (viewMatrix.rectStaysRect()) { |
310 batch.reset(GrRectBatchFactory::CreateAAStroke(paint.getColor(),
viewMatrix, rect, | 340 batch.reset(GrRectBatchFactory::CreateAAStroke(color, viewMatrix
, rect, |
311 *strokeInfo)); | 341 *strokeInfo)); |
312 } | 342 } |
313 } else { | 343 } else { |
314 // The fill path can handle rotation but not skew. | 344 // Non-AA hairlines are snapped to pixel centers to make which pixel
s are hit |
315 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) { | 345 // deterministic |
316 SkRect devBoundRect; | 346 snapToPixelCenters = (0 == width && !fRenderTarget->isUnifiedMultisa
mpled()); |
317 viewMatrix.mapRect(&devBoundRect, rect); | 347 batch.reset(GrRectBatchFactory::CreateNonAAStroke(color, viewMatrix,
rect, |
318 batch.reset(GrRectBatchFactory::CreateAAFill(paint.getColor(), v
iewMatrix, rect, | 348 width, snapToPixel
Centers)); |
319 devBoundRect)); | 349 |
320 } | 350 // Depending on sub-pixel coordinates and the particular GPU, we may
lose a corner of |
| 351 // hairline rects. We jam all the vertices to pixel centers to avoid
this, but not |
| 352 // when MSAA is enabled because it can cause ugly artifacts. |
321 } | 353 } |
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)); | |
327 | |
328 // Depending on sub-pixel coordinates and the particular GPU, we may los
e a corner of | |
329 // hairline rects. We jam all the vertices to pixel centers to avoid thi
s, but not when | |
330 // MSAA is enabled because it can cause ugly artifacts. | |
331 } else { | |
332 // filled BW rect | |
333 batch.reset(GrRectBatchFactory::CreateNonAAFill(paint.getColor(), viewMa
trix, rect, | |
334 nullptr, nullptr)); | |
335 } | 354 } |
336 | 355 |
337 if (batch) { | 356 if (batch) { |
338 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip); | 357 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip); |
339 | 358 |
340 if (snapToPixelCenters) { | 359 if (snapToPixelCenters) { |
341 pipelineBuilder.setState(GrPipelineBuilder::kSnapVerticesToPixelCent
ers_Flag, | 360 pipelineBuilder.setState(GrPipelineBuilder::kSnapVerticesToPixelCent
ers_Flag, |
342 snapToPixelCenters); | 361 snapToPixelCenters); |
343 } | 362 } |
344 | 363 |
345 this->getDrawTarget()->drawBatch(pipelineBuilder, batch); | 364 this->getDrawTarget()->drawBatch(pipelineBuilder, batch); |
346 return; | 365 return; |
347 } | 366 } |
348 | 367 |
349 SkPath path; | 368 SkPath path; |
350 path.setIsVolatile(true); | 369 path.setIsVolatile(true); |
351 path.addRect(rect); | 370 path.addRect(rect); |
352 this->internalDrawPath(clip, paint, viewMatrix, path, | 371 this->internalDrawPath(clip, paint, viewMatrix, path, |
353 strokeInfo ? *strokeInfo : GrStrokeInfo::FillInfo()); | 372 strokeInfo ? *strokeInfo : GrStrokeInfo::FillInfo()); |
354 } | 373 } |
355 | 374 |
| 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(fDrawContext->fAuditTrail, "GrDrawContext::stencil
Rect"); |
| 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 |
356 void GrDrawContext::fillRectToRect(const GrClip& clip, | 408 void GrDrawContext::fillRectToRect(const GrClip& clip, |
357 const GrPaint& paint, | 409 const GrPaint& paint, |
358 const SkMatrix& viewMatrix, | 410 const SkMatrix& viewMatrix, |
359 const SkRect& rectToDraw, | 411 const SkRect& rectToDraw, |
360 const SkRect& localRect) { | 412 const SkRect& localRect) { |
361 ASSERT_SINGLE_OWNER | 413 ASSERT_SINGLE_OWNER |
362 RETURN_IF_ABANDONED | 414 RETURN_IF_ABANDONED |
363 SkDEBUGCODE(this->validate();) | 415 SkDEBUGCODE(this->validate();) |
364 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::fillRectToRect"); | 416 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::fillRectToRect"); |
365 | 417 |
(...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
794 } | 846 } |
795 | 847 |
796 // Note that internalDrawPath may sw-rasterize the path into a scratch textu
re. | 848 // Note that internalDrawPath may sw-rasterize the path into a scratch textu
re. |
797 // Scratch textures can be recycled after they are returned to the texture | 849 // Scratch textures can be recycled after they are returned to the texture |
798 // cache. This presents a potential hazard for buffered drawing. However, | 850 // cache. This presents a potential hazard for buffered drawing. However, |
799 // the writePixels that uploads to the scratch will perform a flush so we're | 851 // the writePixels that uploads to the scratch will perform a flush so we're |
800 // OK. | 852 // OK. |
801 this->internalDrawPath(clip, paint, viewMatrix, path, strokeInfo); | 853 this->internalDrawPath(clip, paint, viewMatrix, path, strokeInfo); |
802 } | 854 } |
803 | 855 |
| 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(fDrawContext->fAuditTrail, "GrDrawContext::drawPat
h"); |
| 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 |
804 void GrDrawContext::internalDrawPath(const GrClip& clip, | 930 void GrDrawContext::internalDrawPath(const GrClip& clip, |
805 const GrPaint& paint, | 931 const GrPaint& paint, |
806 const SkMatrix& viewMatrix, | 932 const SkMatrix& viewMatrix, |
807 const SkPath& path, | 933 const SkPath& path, |
808 const GrStrokeInfo& strokeInfo) { | 934 const GrStrokeInfo& strokeInfo) { |
809 ASSERT_SINGLE_OWNER | 935 ASSERT_SINGLE_OWNER |
810 RETURN_IF_ABANDONED | 936 RETURN_IF_ABANDONED |
811 SkASSERT(!path.isEmpty()); | 937 SkASSERT(!path.isEmpty()); |
812 | 938 |
813 // An Assumption here is that path renderer would use some form of tweaking | 939 // 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... |
904 } | 1030 } |
905 | 1031 |
906 void GrDrawContext::drawBatch(GrPipelineBuilder* pipelineBuilder, GrDrawBatch* b
atch) { | 1032 void GrDrawContext::drawBatch(GrPipelineBuilder* pipelineBuilder, GrDrawBatch* b
atch) { |
907 ASSERT_SINGLE_OWNER | 1033 ASSERT_SINGLE_OWNER |
908 RETURN_IF_ABANDONED | 1034 RETURN_IF_ABANDONED |
909 SkDEBUGCODE(this->validate();) | 1035 SkDEBUGCODE(this->validate();) |
910 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawBatch"); | 1036 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawBatch"); |
911 | 1037 |
912 this->getDrawTarget()->drawBatch(*pipelineBuilder, batch); | 1038 this->getDrawTarget()->drawBatch(*pipelineBuilder, batch); |
913 } | 1039 } |
OLD | NEW |