| 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 |