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

Side by Side Diff: src/gpu/GrReducedClip.cpp

Issue 2263343002: Move clip mask generation into GrReducedClip (Closed) Base URL: https://skia.googlesource.com/skia.git@upload2_clipclears
Patch Set: msvc 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/GrReducedClip.h ('k') | src/gpu/GrStencilAttachment.h » ('j') | 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 2016 Google Inc. 2 * Copyright 2016 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 "GrReducedClip.h" 8 #include "GrReducedClip.h"
9 9
10 #include "GrAppliedClip.h"
10 #include "GrClip.h" 11 #include "GrClip.h"
12 #include "GrColor.h"
13 #include "GrContextPriv.h"
14 #include "GrDrawContext.h"
15 #include "GrDrawContextPriv.h"
16 #include "GrDrawingManager.h"
17 #include "GrFixedClip.h"
18 #include "GrPathRenderer.h"
19 #include "GrStyle.h"
20 #include "GrUserStencilSettings.h"
11 21
12 typedef SkClipStack::Element Element; 22 typedef SkClipStack::Element Element;
13 23
14 /** 24 /**
15 * There are plenty of optimizations that could be added here. Maybe flips could be folded into 25 * There are plenty of optimizations that could be added here. Maybe flips could be folded into
16 * earlier operations. Or would inserting flips and reversing earlier ops ever b e a win? Perhaps 26 * earlier operations. Or would inserting flips and reversing earlier ops ever b e a win? Perhaps
17 * for the case where the bounds are kInsideOut_BoundsType. We could restrict ea rlier operations 27 * for the case where the bounds are kInsideOut_BoundsType. We could restrict ea rlier operations
18 * based on later intersect operations, and perhaps remove intersect-rects. We c ould optionally 28 * based on later intersect operations, and perhaps remove intersect-rects. We c ould optionally
19 * take a rect in case the caller knows a bound on what is to be drawn through t his clip. 29 * take a rect in case the caller knows a bound on what is to be drawn through t his clip.
20 */ 30 */
(...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after
414 SkASSERT(fHasIBounds); 424 SkASSERT(fHasIBounds);
415 if (!fIBounds.intersect(irect)) { 425 if (!fIBounds.intersect(irect)) {
416 fHasIBounds = false; 426 fHasIBounds = false;
417 fElements.reset(); 427 fElements.reset();
418 fRequiresAA = false; 428 fRequiresAA = false;
419 fInitialState = InitialState::kAllOut; 429 fInitialState = InitialState::kAllOut;
420 return false; 430 return false;
421 } 431 }
422 return true; 432 return true;
423 } 433 }
434
435 ////////////////////////////////////////////////////////////////////////////////
436 // Create a 8-bit clip mask in alpha
437
438 static bool stencil_element(GrDrawContext* dc,
439 const GrFixedClip& clip,
440 const GrUserStencilSettings* ss,
441 const SkMatrix& viewMatrix,
442 const SkClipStack::Element* element) {
443
444 // TODO: Draw rrects directly here.
445 switch (element->getType()) {
446 case Element::kEmpty_Type:
447 SkDEBUGFAIL("Should never get here with an empty element.");
448 break;
449 case Element::kRect_Type:
450 return dc->drawContextPriv().drawAndStencilRect(clip, ss,
451 element->getOp(),
452 element->isInverseFi lled(),
453 element->isAA(),
454 viewMatrix, element- >getRect());
455 break;
456 default: {
457 SkPath path;
458 element->asPath(&path);
459 if (path.isInverseFillType()) {
460 path.toggleInverseFillType();
461 }
462
463 return dc->drawContextPriv().drawAndStencilPath(clip, ss,
464 element->getOp(),
465 element->isInverseFi lled(),
466 element->isAA(), vie wMatrix, path);
467 break;
468 }
469 }
470
471 return false;
472 }
473
474 static void draw_element(GrDrawContext* dc,
475 const GrClip& clip, // TODO: can this just always be Wi deOpen?
476 const GrPaint &paint,
477 const SkMatrix& viewMatrix,
478 const SkClipStack::Element* element) {
479
480 // TODO: Draw rrects directly here.
481 switch (element->getType()) {
482 case Element::kEmpty_Type:
483 SkDEBUGFAIL("Should never get here with an empty element.");
484 break;
485 case Element::kRect_Type:
486 dc->drawRect(clip, paint, viewMatrix, element->getRect());
487 break;
488 default: {
489 SkPath path;
490 element->asPath(&path);
491 if (path.isInverseFillType()) {
492 path.toggleInverseFillType();
493 }
494
495 dc->drawPath(clip, paint, viewMatrix, path, GrStyle::SimpleFill());
496 break;
497 }
498 }
499 }
500
501 bool GrReducedClip::drawAlphaClipMask(GrDrawContext* dc) const {
502 // The texture may be larger than necessary, this rect represents the part o f the texture
503 // we populate with a rasterization of the clip.
504 GrFixedClip clip(SkIRect::MakeWH(fIBounds.width(), fIBounds.height()));
505
506 // The scratch texture that we are drawing into can be substantially larger than the mask. Only
507 // clear the part that we care about.
508 GrColor initialCoverage = InitialState::kAllIn == this->initialState() ? -1 : 0;
509 dc->drawContextPriv().clear(clip, initialCoverage, true);
510
511 // Set the matrix so that rendered clip elements are transformed to mask spa ce from clip space.
512 SkMatrix translate;
513 translate.setTranslate(SkIntToScalar(-fIBounds.left()), SkIntToScalar(-fIBou nds.top()));
514
515 // walk through each clip element and perform its set op
516 for (ElementList::Iter iter(fElements); iter.get(); iter.next()) {
517 const Element* element = iter.get();
518 SkRegion::Op op = element->getOp();
519 bool invert = element->isInverseFilled();
520 if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDiffere nce_Op == op) {
521 // draw directly into the result with the stencil set to make the pi xels affected
522 // by the clip shape be non-zero.
523 static constexpr GrUserStencilSettings kStencilInElement(
524 GrUserStencilSettings::StaticInit<
525 0xffff,
526 GrUserStencilTest::kAlways,
527 0xffff,
528 GrUserStencilOp::kReplace,
529 GrUserStencilOp::kReplace,
530 0xffff>()
531 );
532 if (!stencil_element(dc, clip, &kStencilInElement, translate, elemen t)) {
533 return false;
534 }
535
536 // Draw to the exterior pixels (those with a zero stencil value).
537 static constexpr GrUserStencilSettings kDrawOutsideElement(
538 GrUserStencilSettings::StaticInit<
539 0x0000,
540 GrUserStencilTest::kEqual,
541 0xffff,
542 GrUserStencilOp::kZero,
543 GrUserStencilOp::kZero,
544 0xffff>()
545 );
546 if (!dc->drawContextPriv().drawAndStencilRect(clip, &kDrawOutsideEle ment,
547 op, !invert, false,
548 translate,
549 SkRect::Make(fIBounds) )) {
550 return false;
551 }
552 } else {
553 // all the remaining ops can just be directly draw into the accumula tion buffer
554 GrPaint paint;
555 paint.setAntiAlias(element->isAA());
556 paint.setCoverageSetOpXPFactory(op, false);
557
558 draw_element(dc, clip, paint, translate, element);
559 }
560 }
561
562 return true;
563 }
564
565 ////////////////////////////////////////////////////////////////////////////////
566 // Create a 1-bit clip mask in the stencil buffer.
567
568 class StencilClip final : public GrClip {
569 public:
570 StencilClip(const SkIRect& scissorRect) : fFixedClip(scissorRect) {}
571 const GrFixedClip& fixedClip() const { return fFixedClip; }
572
573 private:
574 bool quickContains(const SkRect&) const final {
575 return false;
576 }
577 void getConservativeBounds(int width, int height, SkIRect* devResult, bool* iior) const final {
578 fFixedClip.getConservativeBounds(width, height, devResult, iior);
579 }
580 bool isRRect(const SkRect& rtBounds, SkRRect* rr, bool* aa) const final {
581 return false;
582 }
583 bool apply(GrContext* context, GrDrawContext* drawContext, bool useHWAA,
584 bool hasUserStencilSettings, GrAppliedClip* out) const final {
585 if (!fFixedClip.apply(context, drawContext, useHWAA, hasUserStencilSetti ngs, out)) {
586 return false;
587 }
588 out->addStencilClip();
589 return true;
590 }
591
592 GrFixedClip fFixedClip;
593
594 typedef GrClip INHERITED;
595 };
596
597 bool GrReducedClip::drawStencilClipMask(GrContext* context,
598 GrDrawContext* drawContext,
599 const SkIPoint& clipOrigin) const {
600 // We set the current clip to the bounds so that our recursive draws are sci ssored to them.
601 StencilClip stencilClip(fIBounds.makeOffset(-clipOrigin.x(), -clipOrigin.y() ));
602
603 bool initialState = InitialState::kAllIn == this->initialState();
604 drawContext->drawContextPriv().clearStencilClip(stencilClip.fixedClip(), ini tialState);
605
606 // Set the matrix so that rendered clip elements are transformed from clip t o stencil space.
607 SkMatrix viewMatrix;
608 viewMatrix.setTranslate(SkIntToScalar(-clipOrigin.x()), SkIntToScalar(-clipO rigin.y()));
609
610 // walk through each clip element and perform its set op
611 // with the existing clip.
612 for (ElementList::Iter iter(fElements); iter.get(); iter.next()) {
613 const Element* element = iter.get();
614 bool useHWAA = element->isAA() && drawContext->isStencilBufferMultisampl ed();
615
616 bool fillInverted = false;
617
618 // This will be used to determine whether the clip shape can be rendered into the
619 // stencil with arbitrary stencil settings.
620 GrPathRenderer::StencilSupport stencilSupport;
621
622 SkRegion::Op op = element->getOp();
623
624 GrPathRenderer* pr = nullptr;
625 SkPath clipPath;
626 if (Element::kRect_Type == element->getType()) {
627 stencilSupport = GrPathRenderer::kNoRestriction_StencilSupport;
628 fillInverted = false;
629 } else {
630 element->asPath(&clipPath);
631 fillInverted = clipPath.isInverseFillType();
632 if (fillInverted) {
633 clipPath.toggleInverseFillType();
634 }
635
636 GrShape shape(clipPath, GrStyle::SimpleFill());
637 GrPathRenderer::CanDrawPathArgs canDrawArgs;
638 canDrawArgs.fShaderCaps = context->caps()->shaderCaps();
639 canDrawArgs.fViewMatrix = &viewMatrix;
640 canDrawArgs.fShape = &shape;
641 canDrawArgs.fAntiAlias = false;
642 canDrawArgs.fHasUserStencilSettings = false;
643 canDrawArgs.fIsStencilBufferMSAA = drawContext->isStencilBufferMulti sampled();
644
645 GrDrawingManager* dm = context->contextPriv().drawingManager();
646 pr = dm->getPathRenderer(canDrawArgs, false,
647 GrPathRendererChain::kStencilOnly_DrawType,
648 &stencilSupport);
649 if (!pr) {
650 return false;
651 }
652 }
653
654 bool canRenderDirectToStencil =
655 GrPathRenderer::kNoRestriction_StencilSupport == stencilSupport;
656 bool drawDirectToClip; // Given the renderer, the element,
657 // fill rule, and set operation should
658 // we render the element directly to
659 // stencil bit used for clipping.
660 GrUserStencilSettings const* const* stencilPasses =
661 GrStencilSettings::GetClipPasses(op, canRenderDirectToStencil, fillI nverted,
662 &drawDirectToClip);
663
664 // draw the element to the client stencil bits if necessary
665 if (!drawDirectToClip) {
666 static constexpr GrUserStencilSettings kDrawToStencil(
667 GrUserStencilSettings::StaticInit<
668 0x0000,
669 GrUserStencilTest::kAlways,
670 0xffff,
671 GrUserStencilOp::kIncMaybeClamp,
672 GrUserStencilOp::kIncMaybeClamp,
673 0xffff>()
674 );
675 if (Element::kRect_Type == element->getType()) {
676 drawContext->drawContextPriv().stencilRect(stencilClip.fixedClip (),
677 &kDrawToStencil, useH WAA,
678 viewMatrix, element-> getRect());
679 } else {
680 if (!clipPath.isEmpty()) {
681 GrShape shape(clipPath, GrStyle::SimpleFill());
682 if (canRenderDirectToStencil) {
683 GrPaint paint;
684 paint.setXPFactory(GrDisableColorXPFactory::Make());
685 paint.setAntiAlias(element->isAA());
686
687 GrPathRenderer::DrawPathArgs args;
688 args.fResourceProvider = context->resourceProvider();
689 args.fPaint = &paint;
690 args.fUserStencilSettings = &kDrawToStencil;
691 args.fDrawContext = drawContext;
692 args.fClip = &stencilClip.fixedClip();
693 args.fViewMatrix = &viewMatrix;
694 args.fShape = &shape;
695 args.fAntiAlias = false;
696 args.fGammaCorrect = false;
697 pr->drawPath(args);
698 } else {
699 GrPathRenderer::StencilPathArgs args;
700 args.fResourceProvider = context->resourceProvider();
701 args.fDrawContext = drawContext;
702 args.fClip = &stencilClip.fixedClip();
703 args.fViewMatrix = &viewMatrix;
704 args.fIsAA = element->isAA();
705 args.fShape = &shape;
706 pr->stencilPath(args);
707 }
708 }
709 }
710 }
711
712 // now we modify the clip bit by rendering either the clip
713 // element directly or a bounding rect of the entire clip.
714 for (GrUserStencilSettings const* const* pass = stencilPasses; *pass; ++ pass) {
715 if (drawDirectToClip) {
716 if (Element::kRect_Type == element->getType()) {
717 drawContext->drawContextPriv().stencilRect(stencilClip, *pas s, useHWAA,
718 viewMatrix, eleme nt->getRect());
719 } else {
720 GrShape shape(clipPath, GrStyle::SimpleFill());
721 GrPaint paint;
722 paint.setXPFactory(GrDisableColorXPFactory::Make());
723 paint.setAntiAlias(element->isAA());
724 GrPathRenderer::DrawPathArgs args;
725 args.fResourceProvider = context->resourceProvider();
726 args.fPaint = &paint;
727 args.fUserStencilSettings = *pass;
728 args.fDrawContext = drawContext;
729 args.fClip = &stencilClip;
730 args.fViewMatrix = &viewMatrix;
731 args.fShape = &shape;
732 args.fAntiAlias = false;
733 args.fGammaCorrect = false;
734 pr->drawPath(args);
735 }
736 } else {
737 // The view matrix is setup to do clip space -> stencil space tr anslation, so
738 // draw rect in clip space.
739 drawContext->drawContextPriv().stencilRect(stencilClip, *pass,
740 false, viewMatrix,
741 SkRect::Make(fIBounds ));
742 }
743 }
744 }
745 return true;
746 }
OLDNEW
« no previous file with comments | « src/gpu/GrReducedClip.h ('k') | src/gpu/GrStencilAttachment.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698