OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 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 "GrClipMaskManager.h" | 8 #include "GrClipMaskManager.h" |
9 #include "GrCaps.h" | 9 #include "GrCaps.h" |
10 #include "GrDrawingManager.h" | 10 #include "GrDrawingManager.h" |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
152 } | 152 } |
153 | 153 |
154 GrResourceProvider* GrClipMaskManager::resourceProvider() { | 154 GrResourceProvider* GrClipMaskManager::resourceProvider() { |
155 return fDrawTarget->cmmAccess().resourceProvider(); | 155 return fDrawTarget->cmmAccess().resourceProvider(); |
156 } | 156 } |
157 /* | 157 /* |
158 * This method traverses the clip stack to see if the GrSoftwarePathRenderer | 158 * This method traverses the clip stack to see if the GrSoftwarePathRenderer |
159 * will be used on any element. If so, it returns true to indicate that the | 159 * will be used on any element. If so, it returns true to indicate that the |
160 * entire clip should be rendered in SW and then uploaded en masse to the gpu. | 160 * entire clip should be rendered in SW and then uploaded en masse to the gpu. |
161 */ | 161 */ |
162 bool GrClipMaskManager::useSWOnlyPath(const GrPipelineBuilder& pipelineBuilder, | 162 bool GrClipMaskManager::UseSWOnlyPath(GrContext* context, |
| 163 const GrPipelineBuilder& pipelineBuilder, |
163 const GrRenderTarget* rt, | 164 const GrRenderTarget* rt, |
164 const SkVector& clipToMaskOffset, | 165 const SkVector& clipToMaskOffset, |
165 const GrReducedClip::ElementList& elements
) { | 166 const GrReducedClip::ElementList& elements
) { |
166 // TODO: generalize this function so that when | 167 // TODO: generalize this function so that when |
167 // a clip gets complex enough it can just be done in SW regardless | 168 // a clip gets complex enough it can just be done in SW regardless |
168 // of whether it would invoke the GrSoftwarePathRenderer. | 169 // of whether it would invoke the GrSoftwarePathRenderer. |
169 | 170 |
170 // Set the matrix so that rendered clip elements are transformed to mask spa
ce from clip | 171 // Set the matrix so that rendered clip elements are transformed to mask spa
ce from clip |
171 // space. | 172 // space. |
172 const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMa
skOffset.fY); | 173 const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMa
skOffset.fY); |
173 | 174 |
174 for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.get();
iter.next()) { | 175 for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.get();
iter.next()) { |
175 const Element* element = iter.get(); | 176 const Element* element = iter.get(); |
176 | 177 |
177 SkRegion::Op op = element->getOp(); | 178 SkRegion::Op op = element->getOp(); |
178 bool invert = element->isInverseFilled(); | 179 bool invert = element->isInverseFilled(); |
179 bool needsStencil = invert || | 180 bool needsStencil = invert || |
180 SkRegion::kIntersect_Op == op || SkRegion::kReverseD
ifference_Op == op; | 181 SkRegion::kIntersect_Op == op || SkRegion::kReverseD
ifference_Op == op; |
181 | 182 |
182 if (PathNeedsSWRenderer(this->getContext(), pipelineBuilder.getStencil()
.isDisabled(), | 183 if (PathNeedsSWRenderer(context, pipelineBuilder.getStencil().isDisabled
(), |
183 rt, translate, element, nullptr, needsStencil))
{ | 184 rt, translate, element, nullptr, needsStencil))
{ |
184 return true; | 185 return true; |
185 } | 186 } |
186 } | 187 } |
187 return false; | 188 return false; |
188 } | 189 } |
189 | 190 |
190 bool GrClipMaskManager::getAnalyticClipProcessor(const GrReducedClip::ElementLis
t& elements, | 191 bool GrClipMaskManager::getAnalyticClipProcessor(const GrReducedClip::ElementLis
t& elements, |
191 bool abortIfAA, | 192 bool abortIfAA, |
192 SkVector& clipToRTOffset, | 193 SkVector& clipToRTOffset, |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
309 if (intersect.intersect(clip.irect())) { | 310 if (intersect.intersect(clip.irect())) { |
310 *out = GrClip(intersect); | 311 *out = GrClip(intersect); |
311 } else { | 312 } else { |
312 *out = clip; | 313 *out = clip; |
313 } | 314 } |
314 break; | 315 break; |
315 } | 316 } |
316 } | 317 } |
317 } | 318 } |
318 | 319 |
| 320 bool GrClipMaskManager::setupScissorClip(const GrPipelineBuilder& pipelineBuilde
r, |
| 321 GrPipelineBuilder::AutoRestoreStencil*
ars, |
| 322 const SkIRect& clipScissor, |
| 323 const SkRect* devBounds, |
| 324 GrAppliedClip* out) { |
| 325 if (kRespectClip_StencilClipMode == fClipMode) { |
| 326 fClipMode = kIgnoreClip_StencilClipMode; |
| 327 } |
| 328 |
| 329 GrRenderTarget* rt = pipelineBuilder.getRenderTarget(); |
| 330 |
| 331 SkIRect clipSpaceRTIBounds = SkIRect::MakeWH(rt->width(), rt->height()); |
| 332 SkIRect devBoundsScissor; |
| 333 const SkIRect* scissor = &clipScissor; |
| 334 bool doDevBoundsClip = fDebugClipBatchToBounds && devBounds; |
| 335 if (doDevBoundsClip) { |
| 336 devBounds->roundOut(&devBoundsScissor); |
| 337 if (devBoundsScissor.intersect(clipScissor)) { |
| 338 scissor = &devBoundsScissor; |
| 339 } |
| 340 } |
| 341 |
| 342 if (scissor->contains(clipSpaceRTIBounds)) { |
| 343 // This counts as wide open |
| 344 this->setPipelineBuilderStencil(pipelineBuilder, ars); |
| 345 return true; |
| 346 } |
| 347 |
| 348 if (clipSpaceRTIBounds.intersect(*scissor)) { |
| 349 out->fScissorState.set(clipSpaceRTIBounds); |
| 350 this->setPipelineBuilderStencil(pipelineBuilder, ars); |
| 351 return true; |
| 352 } |
| 353 return false; |
| 354 } |
| 355 |
319 //////////////////////////////////////////////////////////////////////////////// | 356 //////////////////////////////////////////////////////////////////////////////// |
320 // sort out what kind of clip mask needs to be created: alpha, stencil, | 357 // sort out what kind of clip mask needs to be created: alpha, stencil, |
321 // scissor, or entirely software | 358 // scissor, or entirely software |
322 bool GrClipMaskManager::setupClipping(const GrPipelineBuilder& pipelineBuilder, | 359 bool GrClipMaskManager::setupClipping(const GrPipelineBuilder& pipelineBuilder, |
323 GrPipelineBuilder::AutoRestoreStencil* ars
, | 360 GrPipelineBuilder::AutoRestoreStencil* ars
, |
324 const SkRect* devBounds, | 361 const SkRect* devBounds, |
325 GrAppliedClip* out) { | 362 GrAppliedClip* out) { |
326 if (kRespectClip_StencilClipMode == fClipMode) { | 363 if (kRespectClip_StencilClipMode == fClipMode) { |
327 fClipMode = kIgnoreClip_StencilClipMode; | 364 fClipMode = kIgnoreClip_StencilClipMode; |
328 } | 365 } |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
432 // If the stencil buffer is multisampled we can use it to do everything. | 469 // If the stencil buffer is multisampled we can use it to do everything. |
433 if (!rt->isStencilBufferMultisampled() && requiresAA) { | 470 if (!rt->isStencilBufferMultisampled() && requiresAA) { |
434 SkAutoTUnref<GrTexture> result; | 471 SkAutoTUnref<GrTexture> result; |
435 | 472 |
436 // The top-left of the mask corresponds to the top-left corner of the bo
unds. | 473 // The top-left of the mask corresponds to the top-left corner of the bo
unds. |
437 SkVector clipToMaskOffset = { | 474 SkVector clipToMaskOffset = { |
438 SkIntToScalar(-clipSpaceIBounds.fLeft), | 475 SkIntToScalar(-clipSpaceIBounds.fLeft), |
439 SkIntToScalar(-clipSpaceIBounds.fTop) | 476 SkIntToScalar(-clipSpaceIBounds.fTop) |
440 }; | 477 }; |
441 | 478 |
442 if (this->useSWOnlyPath(pipelineBuilder, rt, clipToMaskOffset, elements)
) { | 479 if (UseSWOnlyPath(this->getContext(), pipelineBuilder, rt, clipToMaskOff
set, elements)) { |
443 // The clip geometry is complex enough that it will be more efficien
t to create it | 480 // The clip geometry is complex enough that it will be more efficien
t to create it |
444 // entirely in software | 481 // entirely in software |
445 result.reset(this->createSoftwareClipMask(genID, | 482 result.reset(CreateSoftwareClipMask(this->getContext(), |
446 initialState, | 483 genID, |
447 elements, | 484 initialState, |
448 clipToMaskOffset, | 485 elements, |
449 clipSpaceIBounds)); | 486 clipToMaskOffset, |
| 487 clipSpaceIBounds)); |
450 } else { | 488 } else { |
451 result.reset(this->createAlphaClipMask(genID, | 489 result.reset(CreateAlphaClipMask(this->getContext(), |
452 initialState, | 490 genID, |
453 elements, | 491 initialState, |
454 clipToMaskOffset, | 492 elements, |
455 clipSpaceIBounds)); | 493 clipToMaskOffset, |
456 // If createAlphaClipMask fails it means useSWOnlyPath has a bug | 494 clipSpaceIBounds)); |
| 495 // If createAlphaClipMask fails it means UseSWOnlyPath has a bug |
457 SkASSERT(result); | 496 SkASSERT(result); |
458 } | 497 } |
459 | 498 |
460 if (result) { | 499 if (result) { |
461 // The mask's top left coord should be pinned to the rounded-out top
left corner of | 500 // The mask's top left coord should be pinned to the rounded-out top
left corner of |
462 // clipSpace bounds. We determine the mask's position WRT to the ren
der target here. | 501 // clipSpace bounds. We determine the mask's position WRT to the ren
der target here. |
463 SkIRect rtSpaceMaskBounds = clipSpaceIBounds; | 502 SkIRect rtSpaceMaskBounds = clipSpaceIBounds; |
464 rtSpaceMaskBounds.offset(-clip.origin()); | 503 rtSpaceMaskBounds.offset(-clip.origin()); |
465 out->fClipCoverageFP.reset(create_fp_for_mask(result, rtSpaceMaskBou
nds)); | 504 out->fClipCoverageFP.reset(create_fp_for_mask(result, rtSpaceMaskBou
nds)); |
466 this->setPipelineBuilderStencil(pipelineBuilder, ars); | 505 this->setPipelineBuilderStencil(pipelineBuilder, ars); |
(...skipping 14 matching lines...) Expand all Loading... |
481 // This must occur after createStencilClipMask. That function may change the
scissor. Also, it | 520 // This must occur after createStencilClipMask. That function may change the
scissor. Also, it |
482 // only guarantees that the stencil mask is correct within the bounds it was
passed, so we must | 521 // only guarantees that the stencil mask is correct within the bounds it was
passed, so we must |
483 // use both stencil and scissor test to the bounds for the final draw. | 522 // use both stencil and scissor test to the bounds for the final draw. |
484 SkIRect scissorSpaceIBounds(clipSpaceIBounds); | 523 SkIRect scissorSpaceIBounds(clipSpaceIBounds); |
485 scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset); | 524 scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset); |
486 out->fScissorState.set(scissorSpaceIBounds); | 525 out->fScissorState.set(scissorSpaceIBounds); |
487 this->setPipelineBuilderStencil(pipelineBuilder, ars); | 526 this->setPipelineBuilderStencil(pipelineBuilder, ars); |
488 return true; | 527 return true; |
489 } | 528 } |
490 | 529 |
491 namespace { | 530 static bool stencil_element(GrDrawContext* dc, |
492 //////////////////////////////////////////////////////////////////////////////// | 531 const SkIRect* scissorRect, |
493 // Set a coverage drawing XPF on the pipelineBuilder for the given op and invert
Coverage mode | 532 const GrStencilSettings& ss, |
494 void set_coverage_drawing_xpf(SkRegion::Op op, bool invertCoverage, | 533 const SkMatrix& viewMatrix, |
495 GrPipelineBuilder* pipelineBuilder) { | 534 const SkClipStack::Element* element) { |
496 SkASSERT(op <= SkRegion::kLastOp); | |
497 pipelineBuilder->setCoverageSetOpXPFactory(op, invertCoverage); | |
498 } | |
499 } | |
500 | |
501 //////////////////////////////////////////////////////////////////////////////// | |
502 bool GrClipMaskManager::drawElement(GrPipelineBuilder* pipelineBuilder, | |
503 const SkMatrix& viewMatrix, | |
504 GrTexture* target, | |
505 const SkClipStack::Element* element, | |
506 GrPathRenderer* pr) { | |
507 | |
508 GrRenderTarget* rt = target->asRenderTarget(); | |
509 pipelineBuilder->setRenderTarget(rt); | |
510 | |
511 // The color we use to draw does not matter since we will always be using a
GrCoverageSetOpXP | |
512 // which ignores color. | |
513 GrColor color = GrColor_WHITE; | |
514 | 535 |
515 // TODO: Draw rrects directly here. | 536 // TODO: Draw rrects directly here. |
516 switch (element->getType()) { | 537 switch (element->getType()) { |
517 case Element::kEmpty_Type: | 538 case Element::kEmpty_Type: |
518 SkDEBUGFAIL("Should never get here with an empty element."); | 539 SkDEBUGFAIL("Should never get here with an empty element."); |
519 break; | 540 break; |
520 case Element::kRect_Type: { | 541 case Element::kRect_Type: |
521 // TODO: Do rects directly to the accumulator using a aa-rect GrProc
essor that covers | 542 return dc->stencilRect(scissorRect, ss, |
522 // the entire mask bounds and writes 0 outside the rect. | 543 element->getOp(), element->isInverseFilled(),
element->isAA(), |
523 if (element->isAA()) { | 544 viewMatrix, element->getRect()); |
524 SkRect devRect = element->getRect(); | 545 break; |
525 viewMatrix.mapRect(&devRect); | |
526 | |
527 SkAutoTUnref<GrDrawBatch> batch( | |
528 GrRectBatchFactory::CreateAAFill(color, viewMatrix, elem
ent->getRect(), | |
529 devRect)); | |
530 | |
531 fDrawTarget->drawBatch(*pipelineBuilder, batch); | |
532 } else { | |
533 draw_non_aa_rect(fDrawTarget, *pipelineBuilder, color, viewMatri
x, | |
534 element->getRect()); | |
535 } | |
536 return true; | |
537 } | |
538 default: { | 546 default: { |
539 SkPath path; | 547 SkPath path; |
540 element->asPath(&path); | 548 element->asPath(&path); |
541 if (path.isInverseFillType()) { | 549 if (path.isInverseFillType()) { |
542 path.toggleInverseFillType(); | 550 path.toggleInverseFillType(); |
543 } | 551 } |
544 GrStrokeInfo stroke(SkStrokeRec::kFill_InitStyle); | |
545 if (nullptr == pr) { | |
546 GrPathRendererChain::DrawType type; | |
547 type = element->isAA() ? GrPathRendererChain::kColorAntiAlias_Dr
awType : | |
548 GrPathRendererChain::kColor_DrawType; | |
549 | 552 |
550 GrPathRenderer::CanDrawPathArgs canDrawArgs; | 553 return dc->stencilPath(scissorRect, ss, |
551 canDrawArgs.fShaderCaps = this->getContext()->caps()->shaderCaps
(); | 554 element->getOp(), element->isInverseFilled(),
element->isAA(), |
552 canDrawArgs.fViewMatrix = &viewMatrix; | 555 viewMatrix, path); |
553 canDrawArgs.fPath = &path; | |
554 canDrawArgs.fStroke = &stroke; | |
555 canDrawArgs.fAntiAlias = element->isAA();; | |
556 canDrawArgs.fIsStencilDisabled = pipelineBuilder->getStencil().i
sDisabled(); | |
557 canDrawArgs.fIsStencilBufferMSAA = rt->isStencilBufferMultisampl
ed(); | |
558 | |
559 pr = this->getContext()->drawingManager()->getPathRenderer(canDr
awArgs, false, type); | |
560 } | |
561 if (nullptr == pr) { | |
562 return false; | |
563 } | |
564 GrPathRenderer::DrawPathArgs args; | |
565 args.fTarget = fDrawTarget; | |
566 args.fResourceProvider = this->getContext()->resourceProvider(); | |
567 args.fPipelineBuilder = pipelineBuilder; | |
568 args.fColor = color; | |
569 args.fViewMatrix = &viewMatrix; | |
570 args.fPath = &path; | |
571 args.fStroke = &stroke; | |
572 args.fAntiAlias = element->isAA(); | |
573 pr->drawPath(args); | |
574 break; | 556 break; |
575 } | 557 } |
576 } | 558 } |
577 return true; | 559 |
| 560 return false; |
| 561 } |
| 562 |
| 563 static void draw_element(GrDrawContext* dc, |
| 564 const GrClip& clip, // TODO: can this just always be Wi
deOpen? |
| 565 const GrPaint &paint, |
| 566 const SkMatrix& viewMatrix, |
| 567 const SkClipStack::Element* element) { |
| 568 |
| 569 // TODO: Draw rrects directly here. |
| 570 switch (element->getType()) { |
| 571 case Element::kEmpty_Type: |
| 572 SkDEBUGFAIL("Should never get here with an empty element."); |
| 573 break; |
| 574 case Element::kRect_Type: |
| 575 dc->drawRect(clip, paint, viewMatrix, element->getRect()); |
| 576 break; |
| 577 default: { |
| 578 SkPath path; |
| 579 element->asPath(&path); |
| 580 if (path.isInverseFillType()) { |
| 581 path.toggleInverseFillType(); |
| 582 } |
| 583 |
| 584 dc->drawPath(clip, paint, viewMatrix, path, GrStrokeInfo::FillInfo()
); |
| 585 break; |
| 586 } |
| 587 } |
578 } | 588 } |
579 | 589 |
580 //////////////////////////////////////////////////////////////////////////////// | 590 //////////////////////////////////////////////////////////////////////////////// |
581 // Create a 8-bit clip mask in alpha | 591 // Create a 8-bit clip mask in alpha |
582 | 592 |
583 static void GetClipMaskKey(int32_t clipGenID, const SkIRect& bounds, GrUniqueKey
* key) { | 593 static void GetClipMaskKey(int32_t clipGenID, const SkIRect& bounds, GrUniqueKey
* key) { |
584 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); | 594 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); |
585 GrUniqueKey::Builder builder(key, kDomain, 3); | 595 GrUniqueKey::Builder builder(key, kDomain, 3); |
586 builder[0] = clipGenID; | 596 builder[0] = clipGenID; |
587 builder[1] = SkToU16(bounds.fLeft) | (SkToU16(bounds.fRight) << 16); | 597 builder[1] = SkToU16(bounds.fLeft) | (SkToU16(bounds.fRight) << 16); |
588 builder[2] = SkToU16(bounds.fTop) | (SkToU16(bounds.fBottom) << 16); | 598 builder[2] = SkToU16(bounds.fTop) | (SkToU16(bounds.fBottom) << 16); |
589 } | 599 } |
590 | 600 |
591 GrTexture* GrClipMaskManager::createCachedMask(int width, int height, const GrUn
iqueKey& key, | 601 GrTexture* GrClipMaskManager::CreateAlphaClipMask(GrContext* context, |
592 bool renderTarget) { | 602 int32_t elementsGenID, |
593 GrSurfaceDesc desc; | |
594 desc.fWidth = width; | |
595 desc.fHeight = height; | |
596 desc.fFlags = renderTarget ? kRenderTarget_GrSurfaceFlag : kNone_GrSurfaceFl
ags; | |
597 if (!renderTarget || this->caps()->isConfigRenderable(kAlpha_8_GrPixelConfig
, false)) { | |
598 desc.fConfig = kAlpha_8_GrPixelConfig; | |
599 } else { | |
600 desc.fConfig = kRGBA_8888_GrPixelConfig; | |
601 } | |
602 | |
603 GrTexture* texture = this->resourceProvider()->createApproxTexture(desc, 0); | |
604 if (!texture) { | |
605 return nullptr; | |
606 } | |
607 texture->resourcePriv().setUniqueKey(key); | |
608 return texture; | |
609 } | |
610 | |
611 GrTexture* GrClipMaskManager::createAlphaClipMask(int32_t elementsGenID, | |
612 GrReducedClip::InitialState in
itialState, | 603 GrReducedClip::InitialState in
itialState, |
613 const GrReducedClip::ElementLi
st& elements, | 604 const GrReducedClip::ElementLi
st& elements, |
614 const SkVector& clipToMaskOffs
et, | 605 const SkVector& clipToMaskOffs
et, |
615 const SkIRect& clipSpaceIBound
s) { | 606 const SkIRect& clipSpaceIBound
s) { |
616 GrResourceProvider* resourceProvider = this->resourceProvider(); | 607 GrResourceProvider* resourceProvider = context->resourceProvider(); |
617 GrUniqueKey key; | 608 GrUniqueKey key; |
618 GetClipMaskKey(elementsGenID, clipSpaceIBounds, &key); | 609 GetClipMaskKey(elementsGenID, clipSpaceIBounds, &key); |
619 if (GrTexture* texture = resourceProvider->findAndRefTextureByUniqueKey(key)
) { | 610 if (GrTexture* texture = resourceProvider->findAndRefTextureByUniqueKey(key)
) { |
620 return texture; | 611 return texture; |
621 } | 612 } |
622 | 613 |
623 // There's no texture in the cache. Let's try to allocate it then. | 614 // There's no texture in the cache. Let's try to allocate it then. |
624 SkAutoTUnref<GrTexture> texture(this->createCachedMask( | 615 GrSurfaceDesc desc; |
625 clipSpaceIBounds.width(), clipSpaceIBounds.height(), key, true)); | 616 desc.fWidth = clipSpaceIBounds.width(); |
| 617 desc.fHeight = clipSpaceIBounds.height(); |
| 618 desc.fFlags = kRenderTarget_GrSurfaceFlag; |
| 619 if (context->caps()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) { |
| 620 desc.fConfig = kAlpha_8_GrPixelConfig; |
| 621 } else { |
| 622 desc.fConfig = kRGBA_8888_GrPixelConfig; |
| 623 } |
| 624 |
| 625 SkAutoTUnref<GrTexture> texture(resourceProvider->createApproxTexture(desc,
0)); |
626 if (!texture) { | 626 if (!texture) { |
627 return nullptr; | 627 return nullptr; |
628 } | 628 } |
629 | 629 |
630 // Set the matrix so that rendered clip elements are transformed to mask spa
ce from clip | 630 texture->resourcePriv().setUniqueKey(key); |
631 // space. | 631 |
632 const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMa
skOffset.fY); | 632 SkAutoTUnref<GrDrawContext> dc(context->drawContext(texture->asRenderTarget(
))); |
| 633 if (!dc) { |
| 634 return nullptr; |
| 635 } |
633 | 636 |
634 // The texture may be larger than necessary, this rect represents the part o
f the texture | 637 // The texture may be larger than necessary, this rect represents the part o
f the texture |
635 // we populate with a rasterization of the clip. | 638 // we populate with a rasterization of the clip. |
636 SkIRect maskSpaceIBounds = SkIRect::MakeWH(clipSpaceIBounds.width(), clipSpa
ceIBounds.height()); | 639 SkIRect maskSpaceIBounds = SkIRect::MakeWH(clipSpaceIBounds.width(), clipSpa
ceIBounds.height()); |
637 | 640 |
638 // The scratch texture that we are drawing into can be substantially larger
than the mask. Only | 641 // The scratch texture that we are drawing into can be substantially larger
than the mask. Only |
639 // clear the part that we care about. | 642 // clear the part that we care about. |
640 fDrawTarget->clear(&maskSpaceIBounds, | 643 dc->clear(&maskSpaceIBounds, |
641 GrReducedClip::kAllIn_InitialState == initialState ? 0xff
ffffff : 0x00000000, | 644 GrReducedClip::kAllIn_InitialState == initialState ? 0xffffffff :
0x00000000, |
642 true, | 645 true); |
643 texture->asRenderTarget()); | |
644 | 646 |
645 // When we use the stencil in the below loop it is important to have this cl
ip installed. | 647 // Set the matrix so that rendered clip elements are transformed to mask spa
ce from clip |
| 648 // space. |
| 649 const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMa
skOffset.fY); |
| 650 |
| 651 // It is important that we use maskSpaceIBounds as the stencil rect in the b
elow loop. |
646 // The second pass that zeros the stencil buffer renders the rect maskSpaceI
Bounds so the first | 652 // The second pass that zeros the stencil buffer renders the rect maskSpaceI
Bounds so the first |
647 // pass must not set values outside of this bounds or stencil values outside
the rect won't be | 653 // pass must not set values outside of this bounds or stencil values outside
the rect won't be |
648 // cleared. | 654 // cleared. |
649 const GrClip clip(maskSpaceIBounds); | |
650 | 655 |
651 // walk through each clip element and perform its set op | 656 // walk through each clip element and perform its set op |
652 for (GrReducedClip::ElementList::Iter iter = elements.headIter(); iter.get()
; iter.next()) { | 657 for (GrReducedClip::ElementList::Iter iter = elements.headIter(); iter.get()
; iter.next()) { |
653 const Element* element = iter.get(); | 658 const Element* element = iter.get(); |
654 SkRegion::Op op = element->getOp(); | 659 SkRegion::Op op = element->getOp(); |
655 bool invert = element->isInverseFilled(); | 660 bool invert = element->isInverseFilled(); |
656 if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDiffere
nce_Op == op) { | 661 if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDiffere
nce_Op == op) { |
657 | 662 #ifdef SK_DEBUG |
658 GrPathRenderer* pr = GetPathRenderer(this->getContext(), | 663 GrPathRenderer* pr = GetPathRenderer(context, |
659 texture, translate, element); | 664 texture, translate, element); |
660 if (Element::kRect_Type != element->getType() && !pr) { | 665 if (Element::kRect_Type != element->getType() && !pr) { |
661 // useSWOnlyPath should now filter out all cases where gpu-side
mask merging would | 666 // UseSWOnlyPath should now filter out all cases where gpu-side
mask merging would |
662 // be performed (i.e., pr would be NULL for a non-rect path). Se
e https://bug.skia.org/4519 | 667 // be performed (i.e., pr would be NULL for a non-rect path). |
663 // for rationale and details. | 668 // See https://bug.skia.org/4519 for rationale and details. |
664 SkASSERT(0); | 669 SkASSERT(0); |
665 continue; | 670 } |
| 671 #endif |
| 672 |
| 673 // draw directly into the result with the stencil set to make the pi
xels affected |
| 674 // by the clip shape be non-zero. |
| 675 GR_STATIC_CONST_SAME_STENCIL(kStencilInElement, |
| 676 kReplace_StencilOp, |
| 677 kReplace_StencilOp, |
| 678 kAlways_StencilFunc, |
| 679 0xffff, |
| 680 0xffff, |
| 681 0xffff) |
| 682 if (!stencil_element(dc, &maskSpaceIBounds, kStencilInElement, trans
late, element)) { |
| 683 texture->resourcePriv().removeUniqueKey(); |
| 684 return nullptr; |
666 } | 685 } |
667 | 686 |
668 { | 687 // Draw to the exterior pixels (those with a zero stencil value). |
669 GrPipelineBuilder pipelineBuilder; | 688 GR_STATIC_CONST_SAME_STENCIL(kDrawOutsideElement, |
670 | 689 kZero_StencilOp, |
671 pipelineBuilder.setClip(clip); | 690 kZero_StencilOp, |
672 pipelineBuilder.setRenderTarget(texture->asRenderTarget()); | 691 kEqual_StencilFunc, |
673 SkASSERT(pipelineBuilder.getStencil().isDisabled()); | 692 0xffff, |
674 | 693 0x0000, |
675 // draw directly into the result with the stencil set to make th
e pixels affected | 694 0xffff); |
676 // by the clip shape be non-zero. | 695 if (!dc->stencilRect(&maskSpaceIBounds, kDrawOutsideElement, op, !in
vert, false, |
677 GR_STATIC_CONST_SAME_STENCIL(kStencilInElement, | 696 translate, SkRect::Make(clipSpaceIBounds))) { |
678 kReplace_StencilOp, | 697 texture->resourcePriv().removeUniqueKey(); |
679 kReplace_StencilOp, | 698 return nullptr; |
680 kAlways_StencilFunc, | |
681 0xffff, | |
682 0xffff, | |
683 0xffff); | |
684 pipelineBuilder.setStencil(kStencilInElement); | |
685 set_coverage_drawing_xpf(op, invert, &pipelineBuilder); | |
686 | |
687 if (!this->drawElement(&pipelineBuilder, translate, texture, ele
ment, pr)) { | |
688 texture->resourcePriv().removeUniqueKey(); | |
689 return nullptr; | |
690 } | |
691 } | |
692 | |
693 { | |
694 GrPipelineBuilder backgroundPipelineBuilder; | |
695 backgroundPipelineBuilder.setRenderTarget(texture->asRenderTarge
t()); | |
696 | |
697 set_coverage_drawing_xpf(op, !invert, &backgroundPipelineBuilder
); | |
698 // Draw to the exterior pixels (those with a zero stencil value)
. | |
699 GR_STATIC_CONST_SAME_STENCIL(kDrawOutsideElement, | |
700 kZero_StencilOp, | |
701 kZero_StencilOp, | |
702 kEqual_StencilFunc, | |
703 0xffff, | |
704 0x0000, | |
705 0xffff); | |
706 backgroundPipelineBuilder.setStencil(kDrawOutsideElement); | |
707 | |
708 // The color passed in here does not matter since the coverageSe
tOpXP won't read it. | |
709 draw_non_aa_rect(fDrawTarget, backgroundPipelineBuilder, GrColor
_WHITE, translate, | |
710 SkRect::Make(clipSpaceIBounds)); | |
711 } | 699 } |
712 } else { | 700 } else { |
713 GrPipelineBuilder pipelineBuilder; | 701 // all the remaining ops can just be directly draw into the accumula
tion buffer |
| 702 GrPaint paint; |
| 703 paint.setAntiAlias(element->isAA()); |
| 704 paint.setCoverageSetOpXPFactory(op, false); |
714 | 705 |
715 // all the remaining ops can just be directly draw into the accumula
tion buffer | 706 draw_element(dc, GrClip::WideOpen(), paint, translate, element); |
716 set_coverage_drawing_xpf(op, false, &pipelineBuilder); | |
717 // The color passed in here does not matter since the coverageSetOpX
P won't read it. | |
718 this->drawElement(&pipelineBuilder, translate, texture, element); | |
719 } | 707 } |
720 } | 708 } |
721 | 709 |
722 return texture.detach(); | 710 return texture.detach(); |
723 } | 711 } |
724 | 712 |
725 //////////////////////////////////////////////////////////////////////////////// | 713 //////////////////////////////////////////////////////////////////////////////// |
726 // Create a 1-bit clip mask in the stencil buffer. 'devClipBounds' are in device | 714 // Create a 1-bit clip mask in the stencil buffer. 'devClipBounds' are in device |
727 // (as opposed to canvas) coordinates | 715 // (as opposed to canvas) coordinates |
728 bool GrClipMaskManager::createStencilClipMask(GrRenderTarget* rt, | 716 bool GrClipMaskManager::createStencilClipMask(GrRenderTarget* rt, |
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1074 } else { | 1062 } else { |
1075 finished = true; | 1063 finished = true; |
1076 } | 1064 } |
1077 } | 1065 } |
1078 if (!twoSided) { | 1066 if (!twoSided) { |
1079 settings->copyFrontSettingsToBack(); | 1067 settings->copyFrontSettingsToBack(); |
1080 } | 1068 } |
1081 } | 1069 } |
1082 | 1070 |
1083 //////////////////////////////////////////////////////////////////////////////// | 1071 //////////////////////////////////////////////////////////////////////////////// |
1084 GrTexture* GrClipMaskManager::createSoftwareClipMask(int32_t elementsGenID, | 1072 GrTexture* GrClipMaskManager::CreateSoftwareClipMask(GrContext* context, |
| 1073 int32_t elementsGenID, |
1085 GrReducedClip::InitialState
initialState, | 1074 GrReducedClip::InitialState
initialState, |
1086 const GrReducedClip::Elemen
tList& elements, | 1075 const GrReducedClip::Elemen
tList& elements, |
1087 const SkVector& clipToMaskO
ffset, | 1076 const SkVector& clipToMaskO
ffset, |
1088 const SkIRect& clipSpaceIBo
unds) { | 1077 const SkIRect& clipSpaceIBo
unds) { |
1089 GrUniqueKey key; | 1078 GrUniqueKey key; |
1090 GetClipMaskKey(elementsGenID, clipSpaceIBounds, &key); | 1079 GetClipMaskKey(elementsGenID, clipSpaceIBounds, &key); |
1091 GrResourceProvider* resourceProvider = this->resourceProvider(); | 1080 GrResourceProvider* resourceProvider = context->resourceProvider(); |
1092 if (GrTexture* texture = resourceProvider->findAndRefTextureByUniqueKey(key)
) { | 1081 if (GrTexture* texture = resourceProvider->findAndRefTextureByUniqueKey(key)
) { |
1093 return texture; | 1082 return texture; |
1094 } | 1083 } |
1095 | 1084 |
1096 // The mask texture may be larger than necessary. We round out the clip spac
e bounds and pin | 1085 // The mask texture may be larger than necessary. We round out the clip spac
e bounds and pin |
1097 // the top left corner of the resulting rect to the top left of the texture. | 1086 // the top left corner of the resulting rect to the top left of the texture. |
1098 SkIRect maskSpaceIBounds = SkIRect::MakeWH(clipSpaceIBounds.width(), clipSpa
ceIBounds.height()); | 1087 SkIRect maskSpaceIBounds = SkIRect::MakeWH(clipSpaceIBounds.width(), clipSpa
ceIBounds.height()); |
1099 | 1088 |
1100 GrSWMaskHelper helper(this->getContext()); | 1089 GrSWMaskHelper helper(context); |
1101 | 1090 |
1102 // Set the matrix so that rendered clip elements are transformed to mask spa
ce from clip | 1091 // Set the matrix so that rendered clip elements are transformed to mask spa
ce from clip |
1103 // space. | 1092 // space. |
1104 SkMatrix translate; | 1093 SkMatrix translate; |
1105 translate.setTranslate(clipToMaskOffset); | 1094 translate.setTranslate(clipToMaskOffset); |
1106 | 1095 |
1107 helper.init(maskSpaceIBounds, &translate, false); | 1096 helper.init(maskSpaceIBounds, &translate, false); |
1108 helper.clear(GrReducedClip::kAllIn_InitialState == initialState ? 0xFF : 0x0
0); | 1097 helper.clear(GrReducedClip::kAllIn_InitialState == initialState ? 0xFF : 0x0
0); |
1109 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); | 1098 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); |
1110 | 1099 |
(...skipping 23 matching lines...) Expand all Loading... |
1134 if (Element::kRect_Type == element->getType()) { | 1123 if (Element::kRect_Type == element->getType()) { |
1135 helper.draw(element->getRect(), op, element->isAA(), 0xFF); | 1124 helper.draw(element->getRect(), op, element->isAA(), 0xFF); |
1136 } else { | 1125 } else { |
1137 SkPath path; | 1126 SkPath path; |
1138 element->asPath(&path); | 1127 element->asPath(&path); |
1139 helper.draw(path, stroke, op, element->isAA(), 0xFF); | 1128 helper.draw(path, stroke, op, element->isAA(), 0xFF); |
1140 } | 1129 } |
1141 } | 1130 } |
1142 | 1131 |
1143 // Allocate clip mask texture | 1132 // Allocate clip mask texture |
1144 GrTexture* result = this->createCachedMask(clipSpaceIBounds.width(), clipSpa
ceIBounds.height(), | 1133 GrSurfaceDesc desc; |
1145 key, false); | 1134 desc.fWidth = clipSpaceIBounds.width(); |
1146 if (nullptr == result) { | 1135 desc.fHeight = clipSpaceIBounds.height(); |
| 1136 desc.fConfig = kAlpha_8_GrPixelConfig; |
| 1137 |
| 1138 GrTexture* result = context->resourceProvider()->createApproxTexture(desc, 0
); |
| 1139 if (!result) { |
1147 return nullptr; | 1140 return nullptr; |
1148 } | 1141 } |
| 1142 result->resourcePriv().setUniqueKey(key); |
| 1143 |
1149 helper.toTexture(result); | 1144 helper.toTexture(result); |
1150 | 1145 |
1151 return result; | 1146 return result; |
1152 } | 1147 } |
1153 | 1148 |
1154 //////////////////////////////////////////////////////////////////////////////// | 1149 //////////////////////////////////////////////////////////////////////////////// |
1155 | 1150 |
1156 void GrClipMaskManager::adjustPathStencilParams(const GrStencilAttachment* stenc
ilAttachment, | 1151 void GrClipMaskManager::adjustPathStencilParams(const GrStencilAttachment* stenc
ilAttachment, |
1157 GrStencilSettings* settings) { | 1152 GrStencilSettings* settings) { |
1158 if (stencilAttachment) { | 1153 if (stencilAttachment) { |
1159 int stencilBits = stencilAttachment->bits(); | 1154 int stencilBits = stencilAttachment->bits(); |
1160 this->adjustStencilParams(settings, fClipMode, stencilBits); | 1155 this->adjustStencilParams(settings, fClipMode, stencilBits); |
1161 } | 1156 } |
1162 } | 1157 } |
OLD | NEW |