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

Side by Side Diff: src/gpu/GrClipStackClip.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/GrClipStackClip.h ('k') | src/gpu/GrContext.cpp » ('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 "GrClipStackClip.h" 8 #include "GrClipStackClip.h"
9 9
10 #include "GrAppliedClip.h" 10 #include "GrAppliedClip.h"
11 #include "GrContextPriv.h"
11 #include "GrDrawingManager.h" 12 #include "GrDrawingManager.h"
12 #include "GrDrawContextPriv.h" 13 #include "GrDrawContextPriv.h"
13 #include "GrFixedClip.h" 14 #include "GrFixedClip.h"
14 #include "GrGpuResourcePriv.h" 15 #include "GrGpuResourcePriv.h"
15 #include "GrRenderTargetPriv.h" 16 #include "GrRenderTargetPriv.h"
16 #include "GrStencilAttachment.h" 17 #include "GrStencilAttachment.h"
17 #include "GrSWMaskHelper.h" 18 #include "GrSWMaskHelper.h"
18 #include "effects/GrConvexPolyEffect.h" 19 #include "effects/GrConvexPolyEffect.h"
19 #include "effects/GrRRectEffect.h" 20 #include "effects/GrRRectEffect.h"
20 #include "effects/GrTextureDomain.h" 21 #include "effects/GrTextureDomain.h"
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
143 GrShape shape(path, GrStyle::SimpleFill()); 144 GrShape shape(path, GrStyle::SimpleFill());
144 GrPathRenderer::CanDrawPathArgs canDrawArgs; 145 GrPathRenderer::CanDrawPathArgs canDrawArgs;
145 canDrawArgs.fShaderCaps = context->caps()->shaderCaps(); 146 canDrawArgs.fShaderCaps = context->caps()->shaderCaps();
146 canDrawArgs.fViewMatrix = &viewMatrix; 147 canDrawArgs.fViewMatrix = &viewMatrix;
147 canDrawArgs.fShape = &shape; 148 canDrawArgs.fShape = &shape;
148 canDrawArgs.fAntiAlias = element->isAA(); 149 canDrawArgs.fAntiAlias = element->isAA();
149 canDrawArgs.fHasUserStencilSettings = hasUserStencilSettings; 150 canDrawArgs.fHasUserStencilSettings = hasUserStencilSettings;
150 canDrawArgs.fIsStencilBufferMSAA = drawContext->isStencilBufferMultisamp led(); 151 canDrawArgs.fIsStencilBufferMSAA = drawContext->isStencilBufferMultisamp led();
151 152
152 // the 'false' parameter disallows use of the SW path renderer 153 // the 'false' parameter disallows use of the SW path renderer
153 GrPathRenderer* pr = context->drawingManager()->getPathRenderer(canDrawA rgs, false, type); 154 GrPathRenderer* pr =
155 context->contextPriv().drawingManager()->getPathRenderer(canDrawArgs , false, type);
154 if (prOut) { 156 if (prOut) {
155 *prOut = pr; 157 *prOut = pr;
156 } 158 }
157 return SkToBool(!pr); 159 return SkToBool(!pr);
158 } 160 }
159 } 161 }
160 162
161 /* 163 /*
162 * This method traverses the clip stack to see if the GrSoftwarePathRenderer 164 * This method traverses the clip stack to see if the GrSoftwarePathRenderer
163 * will be used on any element. If so, it returns true to indicate that the 165 * will be used on any element. If so, it returns true to indicate that the
164 * entire clip should be rendered in SW and then uploaded en masse to the gpu. 166 * entire clip should be rendered in SW and then uploaded en masse to the gpu.
165 */ 167 */
166 bool GrClipStackClip::UseSWOnlyPath(GrContext* context, 168 bool GrClipStackClip::UseSWOnlyPath(GrContext* context,
167 bool hasUserStencilSettings, 169 bool hasUserStencilSettings,
168 const GrDrawContext* drawContext, 170 const GrDrawContext* drawContext,
169 const SkVector& clipToMaskOffset, 171 const GrReducedClip& reducedClip) {
170 const ElementList& elements) {
171 // TODO: generalize this function so that when 172 // TODO: generalize this function so that when
172 // a clip gets complex enough it can just be done in SW regardless 173 // a clip gets complex enough it can just be done in SW regardless
173 // of whether it would invoke the GrSoftwarePathRenderer. 174 // of whether it would invoke the GrSoftwarePathRenderer.
174 175
175 // Set the matrix so that rendered clip elements are transformed to mask spa ce from clip 176 // Set the matrix so that rendered clip elements are transformed to mask spa ce from clip
176 // space. 177 // space.
177 const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMa skOffset.fY); 178 SkMatrix translate;
179 translate.setTranslate(SkIntToScalar(-reducedClip.left()), SkIntToScalar(-re ducedClip.top()));
178 180
179 for (ElementList::Iter iter(elements); iter.get(); iter.next()) { 181 for (ElementList::Iter iter(reducedClip.elements()); iter.get(); iter.next() ) {
180 const Element* element = iter.get(); 182 const Element* element = iter.get();
181 183
182 SkRegion::Op op = element->getOp(); 184 SkRegion::Op op = element->getOp();
183 bool invert = element->isInverseFilled(); 185 bool invert = element->isInverseFilled();
184 bool needsStencil = invert || 186 bool needsStencil = invert ||
185 SkRegion::kIntersect_Op == op || SkRegion::kReverseD ifference_Op == op; 187 SkRegion::kIntersect_Op == op || SkRegion::kReverseD ifference_Op == op;
186 188
187 if (PathNeedsSWRenderer(context, hasUserStencilSettings, 189 if (PathNeedsSWRenderer(context, hasUserStencilSettings,
188 drawContext, translate, element, nullptr, needsS tencil)) { 190 drawContext, translate, element, nullptr, needsS tencil)) {
189 return true; 191 return true;
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
344 get_analytic_clip_processor(reducedClip.elements(), disallowAnalytic AA, 346 get_analytic_clip_processor(reducedClip.elements(), disallowAnalytic AA,
345 {-clipX, -clipY}, devBounds, &clipFP)) { 347 {-clipX, -clipY}, devBounds, &clipFP)) {
346 out->addCoverageFP(std::move(clipFP)); 348 out->addCoverageFP(std::move(clipFP));
347 return true; 349 return true;
348 } 350 }
349 } 351 }
350 352
351 // If the stencil buffer is multisampled we can use it to do everything. 353 // If the stencil buffer is multisampled we can use it to do everything.
352 if (!drawContext->isStencilBufferMultisampled() && reducedClip.requiresAA()) { 354 if (!drawContext->isStencilBufferMultisampled() && reducedClip.requiresAA()) {
353 sk_sp<GrTexture> result; 355 sk_sp<GrTexture> result;
354 356 if (UseSWOnlyPath(context, hasUserStencilSettings, drawContext, reducedC lip)) {
355 // The top-left of the mask corresponds to the top-left corner of the bo unds.
356 SkVector clipToMaskOffset = {
357 SkIntToScalar(-reducedClip.left()),
358 SkIntToScalar(-reducedClip.top())
359 };
360
361 if (UseSWOnlyPath(context, hasUserStencilSettings, drawContext,
362 clipToMaskOffset, reducedClip.elements())) {
363 // The clip geometry is complex enough that it will be more efficien t to create it 357 // The clip geometry is complex enough that it will be more efficien t to create it
364 // entirely in software 358 // entirely in software
365 result = CreateSoftwareClipMask(context->textureProvider(), reducedC lip, 359 result = CreateSoftwareClipMask(context->textureProvider(), reducedC lip);
366 clipToMaskOffset);
367 } else { 360 } else {
368 result = CreateAlphaClipMask(context, reducedClip, clipToMaskOffset) ; 361 result = CreateAlphaClipMask(context, reducedClip);
369 // If createAlphaClipMask fails it means UseSWOnlyPath has a bug 362 // If createAlphaClipMask fails it means UseSWOnlyPath has a bug
370 SkASSERT(result); 363 SkASSERT(result);
371 } 364 }
372 365
373 if (result) { 366 if (result) {
374 // The mask's top left coord should be pinned to the rounded-out top left corner of 367 // The mask's top left coord should be pinned to the rounded-out top left corner of
375 // clipSpace bounds. We determine the mask's position WRT to the ren der target here. 368 // clipSpace bounds. We determine the mask's position WRT to the ren der target here.
376 SkIRect rtSpaceMaskBounds = reducedClip.ibounds(); 369 SkIRect rtSpaceMaskBounds = reducedClip.ibounds();
377 rtSpaceMaskBounds.offset(-fOrigin); 370 rtSpaceMaskBounds.offset(-fOrigin);
378 out->addCoverageFP(create_fp_for_mask(result.get(), rtSpaceMaskBound s)); 371 out->addCoverageFP(create_fp_for_mask(result.get(), rtSpaceMaskBound s));
379 return true; 372 return true;
380 } 373 }
381 // if alpha clip mask creation fails fall through to the non-AA code pat hs 374 // if alpha clip mask creation fails fall through to the non-AA code pat hs
382 } 375 }
383 376
384 // use the stencil clip if we can't represent the clip as a rectangle. 377 // use the stencil clip if we can't represent the clip as a rectangle.
385 SkIPoint clipSpaceToStencilSpaceOffset = -fOrigin; 378 // TODO: these need to be swapped over to using a StencilAttachmentProxy
386 CreateStencilClipMask(context, drawContext, reducedClip, clipSpaceToStencilS paceOffset); 379 GrStencilAttachment* stencilAttachment =
380 context->resourceProvider()->attachStencilAttachment(drawContext->access RenderTarget());
381 if (nullptr == stencilAttachment) {
382 SkDebugf("WARNING: failed to attach stencil buffer for clip mask. Clip w ill be ignored.\n");
383 return true;
384 }
385
386 if (stencilAttachment->mustRenderClip(reducedClip.elementsGenID(), reducedCl ip.ibounds(),
387 fOrigin)) {
388 reducedClip.drawStencilClipMask(context, drawContext, fOrigin);
389 stencilAttachment->setLastClip(reducedClip.elementsGenID(), reducedClip. ibounds(),
390 fOrigin);
391 }
387 out->addStencilClip(); 392 out->addStencilClip();
388 return true; 393 return true;
389 } 394 }
390 395
391 static bool stencil_element(GrDrawContext* dc,
392 const GrFixedClip& clip,
393 const GrUserStencilSettings* ss,
394 const SkMatrix& viewMatrix,
395 const SkClipStack::Element* element) {
396
397 // TODO: Draw rrects directly here.
398 switch (element->getType()) {
399 case Element::kEmpty_Type:
400 SkDEBUGFAIL("Should never get here with an empty element.");
401 break;
402 case Element::kRect_Type:
403 return dc->drawContextPriv().drawAndStencilRect(clip, ss,
404 element->getOp(),
405 element->isInverseFi lled(),
406 element->isAA(),
407 viewMatrix, element- >getRect());
408 break;
409 default: {
410 SkPath path;
411 element->asPath(&path);
412 if (path.isInverseFillType()) {
413 path.toggleInverseFillType();
414 }
415
416 return dc->drawContextPriv().drawAndStencilPath(clip, ss,
417 element->getOp(),
418 element->isInverseFi lled(),
419 element->isAA(), vie wMatrix, path);
420 break;
421 }
422 }
423
424 return false;
425 }
426
427 static void draw_element(GrDrawContext* dc,
428 const GrClip& clip, // TODO: can this just always be Wi deOpen?
429 const GrPaint &paint,
430 const SkMatrix& viewMatrix,
431 const SkClipStack::Element* element) {
432
433 // TODO: Draw rrects directly here.
434 switch (element->getType()) {
435 case Element::kEmpty_Type:
436 SkDEBUGFAIL("Should never get here with an empty element.");
437 break;
438 case Element::kRect_Type:
439 dc->drawRect(clip, paint, viewMatrix, element->getRect());
440 break;
441 default: {
442 SkPath path;
443 element->asPath(&path);
444 if (path.isInverseFillType()) {
445 path.toggleInverseFillType();
446 }
447
448 dc->drawPath(clip, paint, viewMatrix, path, GrStyle::SimpleFill());
449 break;
450 }
451 }
452 }
453
454 //////////////////////////////////////////////////////////////////////////////// 396 ////////////////////////////////////////////////////////////////////////////////
455 // Create a 8-bit clip mask in alpha 397 // Create a 8-bit clip mask in alpha
456 398
457 static void GetClipMaskKey(int32_t clipGenID, const SkIRect& bounds, GrUniqueKey * key) { 399 static void GetClipMaskKey(int32_t clipGenID, const SkIRect& bounds, GrUniqueKey * key) {
458 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); 400 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
459 GrUniqueKey::Builder builder(key, kDomain, 3); 401 GrUniqueKey::Builder builder(key, kDomain, 3);
460 builder[0] = clipGenID; 402 builder[0] = clipGenID;
461 builder[1] = SkToU16(bounds.fLeft) | (SkToU16(bounds.fRight) << 16); 403 builder[1] = SkToU16(bounds.fLeft) | (SkToU16(bounds.fRight) << 16);
462 builder[2] = SkToU16(bounds.fTop) | (SkToU16(bounds.fBottom) << 16); 404 builder[2] = SkToU16(bounds.fTop) | (SkToU16(bounds.fBottom) << 16);
463 } 405 }
464 406
465 sk_sp<GrTexture> GrClipStackClip::CreateAlphaClipMask(GrContext* context, 407 sk_sp<GrTexture> GrClipStackClip::CreateAlphaClipMask(GrContext* context,
466 const GrReducedClip& reduc edClip, 408 const GrReducedClip& reduc edClip) {
467 const SkVector& clipToMask Offset) {
468 GrResourceProvider* resourceProvider = context->resourceProvider(); 409 GrResourceProvider* resourceProvider = context->resourceProvider();
469 GrUniqueKey key; 410 GrUniqueKey key;
470 GetClipMaskKey(reducedClip.elementsGenID(), reducedClip.ibounds(), &key); 411 GetClipMaskKey(reducedClip.elementsGenID(), reducedClip.ibounds(), &key);
471 if (GrTexture* texture = resourceProvider->findAndRefTextureByUniqueKey(key) ) { 412 if (GrTexture* texture = resourceProvider->findAndRefTextureByUniqueKey(key) ) {
472 return sk_sp<GrTexture>(texture); 413 return sk_sp<GrTexture>(texture);
473 } 414 }
474 415
475 // There's no texture in the cache. Let's try to allocate it then. 416 // There's no texture in the cache. Let's try to allocate it then.
476 GrPixelConfig config = kRGBA_8888_GrPixelConfig; 417 GrPixelConfig config = kRGBA_8888_GrPixelConfig;
477 if (context->caps()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) { 418 if (context->caps()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) {
478 config = kAlpha_8_GrPixelConfig; 419 config = kAlpha_8_GrPixelConfig;
479 } 420 }
480 421
481 sk_sp<GrDrawContext> dc(context->makeDrawContext(SkBackingFit::kApprox, 422 sk_sp<GrDrawContext> dc(context->makeDrawContext(SkBackingFit::kApprox,
482 reducedClip.width(), 423 reducedClip.width(),
483 reducedClip.height(), 424 reducedClip.height(),
484 config, nullptr)); 425 config, nullptr));
485 if (!dc) { 426 if (!dc) {
486 return nullptr; 427 return nullptr;
487 } 428 }
488
489 // The texture may be larger than necessary, this rect represents the part o f the texture
490 // we populate with a rasterization of the clip.
491 SkIRect maskSpaceIBounds = SkIRect::MakeWH(reducedClip.width(), reducedClip. height());
492 GrFixedClip clip(maskSpaceIBounds);
493 429
494 // The scratch texture that we are drawing into can be substantially larger than the mask. Only 430 if (!reducedClip.drawAlphaClipMask(dc.get())) {
495 // clear the part that we care about. 431 return nullptr;
496 GrColor initialCoverage = InitialState::kAllIn == reducedClip.initialState() ? -1 : 0;
497 dc->drawContextPriv().clear(clip, initialCoverage, true);
498
499 // Set the matrix so that rendered clip elements are transformed to mask spa ce from clip
500 // space.
501 const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMa skOffset.fY);
502
503 // It is important that we use maskSpaceIBounds as the stencil rect in the b elow loop.
504 // The second pass that zeros the stencil buffer renders the rect maskSpaceI Bounds so the first
505 // pass must not set values outside of this bounds or stencil values outside the rect won't be
506 // cleared.
507
508 // walk through each clip element and perform its set op
509 for (ElementList::Iter iter(reducedClip.elements()); iter.get(); iter.next() ) {
510 const Element* element = iter.get();
511 SkRegion::Op op = element->getOp();
512 bool invert = element->isInverseFilled();
513 if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDiffere nce_Op == op) {
514 // draw directly into the result with the stencil set to make the pi xels affected
515 // by the clip shape be non-zero.
516 static constexpr GrUserStencilSettings kStencilInElement(
517 GrUserStencilSettings::StaticInit<
518 0xffff,
519 GrUserStencilTest::kAlways,
520 0xffff,
521 GrUserStencilOp::kReplace,
522 GrUserStencilOp::kReplace,
523 0xffff>()
524 );
525 if (!stencil_element(dc.get(), clip, &kStencilInElement,
526 translate, element)) {
527 return nullptr;
528 }
529
530 // Draw to the exterior pixels (those with a zero stencil value).
531 static constexpr GrUserStencilSettings kDrawOutsideElement(
532 GrUserStencilSettings::StaticInit<
533 0x0000,
534 GrUserStencilTest::kEqual,
535 0xffff,
536 GrUserStencilOp::kZero,
537 GrUserStencilOp::kZero,
538 0xffff>()
539 );
540 if (!dc->drawContextPriv().drawAndStencilRect(clip, &kDrawOutsideEle ment,
541 op, !invert, false,
542 translate,
543 SkRect::Make(reducedCl ip.ibounds()))) {
544 return nullptr;
545 }
546 } else {
547 // all the remaining ops can just be directly draw into the accumula tion buffer
548 GrPaint paint;
549 paint.setAntiAlias(element->isAA());
550 paint.setCoverageSetOpXPFactory(op, false);
551
552 draw_element(dc.get(), clip, paint, translate, element);
553 }
554 } 432 }
555 433
556 sk_sp<GrTexture> texture(dc->asTexture()); 434 sk_sp<GrTexture> texture(dc->asTexture());
557 SkASSERT(texture); 435 SkASSERT(texture);
558 texture->resourcePriv().setUniqueKey(key); 436 texture->resourcePriv().setUniqueKey(key);
559 return texture; 437 return texture;
560 } 438 }
561 439
562 ////////////////////////////////////////////////////////////////////////////////
563 // Create a 1-bit clip mask in the stencil buffer.
564
565 class StencilClip final : public GrClip {
566 public:
567 StencilClip(const SkIRect& scissorRect) : fFixedClip(scissorRect) {}
568 const GrFixedClip& fixedClip() const { return fFixedClip; }
569
570 private:
571 bool quickContains(const SkRect&) const final {
572 return false;
573 }
574 void getConservativeBounds(int width, int height, SkIRect* devResult, bool* iior) const final {
575 fFixedClip.getConservativeBounds(width, height, devResult, iior);
576 }
577 bool isRRect(const SkRect& rtBounds, SkRRect* rr, bool* aa) const final {
578 return false;
579 }
580 bool apply(GrContext* context, GrDrawContext* drawContext, bool useHWAA,
581 bool hasUserStencilSettings, GrAppliedClip* out) const final {
582 if (!fFixedClip.apply(context, drawContext, useHWAA, hasUserStencilSetti ngs, out)) {
583 return false;
584 }
585 out->addStencilClip();
586 return true;
587 }
588
589 GrFixedClip fFixedClip;
590
591 typedef GrClip INHERITED;
592 };
593
594 bool GrClipStackClip::CreateStencilClipMask(GrContext* context,
595 GrDrawContext* drawContext,
596 const GrReducedClip& reducedClip,
597 const SkIPoint& clipSpaceToStencilOf fset) {
598 SkASSERT(drawContext);
599
600 GrStencilAttachment* stencilAttachment = context->resourceProvider()->attach StencilAttachment(
601 drawContext->accessRenderTar get());
602 if (nullptr == stencilAttachment) {
603 return false;
604 }
605
606 // TODO: these need to be swapped over to using a StencilAttachmentProxy
607 if (stencilAttachment->mustRenderClip(reducedClip.elementsGenID(), reducedCl ip.ibounds(),
608 clipSpaceToStencilOffset)) {
609 stencilAttachment->setLastClip(reducedClip.elementsGenID(), reducedClip. ibounds(),
610 clipSpaceToStencilOffset);
611 // Set the matrix so that rendered clip elements are transformed from cl ip to stencil space.
612 SkVector translate = {
613 SkIntToScalar(clipSpaceToStencilOffset.fX),
614 SkIntToScalar(clipSpaceToStencilOffset.fY)
615 };
616 SkMatrix viewMatrix;
617 viewMatrix.setTranslate(translate);
618
619 // We set the current clip to the bounds so that our recursive draws are scissored to them.
620 SkIRect stencilSpaceIBounds(reducedClip.ibounds());
621 stencilSpaceIBounds.offset(clipSpaceToStencilOffset);
622 StencilClip stencilClip(stencilSpaceIBounds);
623
624 bool initialState = InitialState::kAllIn == reducedClip.initialState();
625 drawContext->drawContextPriv().clearStencilClip(stencilClip.fixedClip(), initialState);
626
627 // walk through each clip element and perform its set op
628 // with the existing clip.
629 for (ElementList::Iter iter(reducedClip.elements()); iter.get(); iter.ne xt()) {
630 const Element* element = iter.get();
631 bool useHWAA = element->isAA() && drawContext->isStencilBufferMultis ampled();
632
633 bool fillInverted = false;
634
635 // This will be used to determine whether the clip shape can be rend ered into the
636 // stencil with arbitrary stencil settings.
637 GrPathRenderer::StencilSupport stencilSupport;
638
639 SkRegion::Op op = element->getOp();
640
641 GrPathRenderer* pr = nullptr;
642 SkPath clipPath;
643 if (Element::kRect_Type == element->getType()) {
644 stencilSupport = GrPathRenderer::kNoRestriction_StencilSupport;
645 fillInverted = false;
646 } else {
647 element->asPath(&clipPath);
648 fillInverted = clipPath.isInverseFillType();
649 if (fillInverted) {
650 clipPath.toggleInverseFillType();
651 }
652
653 GrShape shape(clipPath, GrStyle::SimpleFill());
654 GrPathRenderer::CanDrawPathArgs canDrawArgs;
655 canDrawArgs.fShaderCaps = context->caps()->shaderCaps();
656 canDrawArgs.fViewMatrix = &viewMatrix;
657 canDrawArgs.fShape = &shape;
658 canDrawArgs.fAntiAlias = false;
659 canDrawArgs.fHasUserStencilSettings = false;
660 canDrawArgs.fIsStencilBufferMSAA = drawContext->isStencilBufferM ultisampled();
661
662 GrDrawingManager* dm = context->drawingManager();
663 pr = dm->getPathRenderer(canDrawArgs, false,
664 GrPathRendererChain::kStencilOnly_DrawT ype,
665 &stencilSupport);
666 if (!pr) {
667 return false;
668 }
669 }
670
671 bool canRenderDirectToStencil =
672 GrPathRenderer::kNoRestriction_StencilSupport == stencilSupport;
673 bool drawDirectToClip; // Given the renderer, the element,
674 // fill rule, and set operation should
675 // we render the element directly to
676 // stencil bit used for clipping.
677 GrUserStencilSettings const* const* stencilPasses =
678 GrStencilSettings::GetClipPasses(op, canRenderDirectToStencil, f illInverted,
679 &drawDirectToClip);
680
681 // draw the element to the client stencil bits if necessary
682 if (!drawDirectToClip) {
683 static constexpr GrUserStencilSettings kDrawToStencil(
684 GrUserStencilSettings::StaticInit<
685 0x0000,
686 GrUserStencilTest::kAlways,
687 0xffff,
688 GrUserStencilOp::kIncMaybeClamp,
689 GrUserStencilOp::kIncMaybeClamp,
690 0xffff>()
691 );
692 if (Element::kRect_Type == element->getType()) {
693 drawContext->drawContextPriv().stencilRect(stencilClip.fixed Clip(),
694 &kDrawToStencil, useHWAA,
695 viewMatrix, eleme nt->getRect());
696 } else {
697 if (!clipPath.isEmpty()) {
698 GrShape shape(clipPath, GrStyle::SimpleFill());
699 if (canRenderDirectToStencil) {
700 GrPaint paint;
701 paint.setXPFactory(GrDisableColorXPFactory::Make());
702 paint.setAntiAlias(element->isAA());
703
704 GrPathRenderer::DrawPathArgs args;
705 args.fResourceProvider = context->resourceProvider() ;
706 args.fPaint = &paint;
707 args.fUserStencilSettings = &kDrawToStencil;
708 args.fDrawContext = drawContext;
709 args.fClip = &stencilClip.fixedClip();
710 args.fViewMatrix = &viewMatrix;
711 args.fShape = &shape;
712 args.fAntiAlias = false;
713 args.fGammaCorrect = false;
714 pr->drawPath(args);
715 } else {
716 GrPathRenderer::StencilPathArgs args;
717 args.fResourceProvider = context->resourceProvider() ;
718 args.fDrawContext = drawContext;
719 args.fClip = &stencilClip.fixedClip();
720 args.fViewMatrix = &viewMatrix;
721 args.fIsAA = element->isAA();
722 args.fShape = &shape;
723 pr->stencilPath(args);
724 }
725 }
726 }
727 }
728
729 // now we modify the clip bit by rendering either the clip
730 // element directly or a bounding rect of the entire clip.
731 for (GrUserStencilSettings const* const* pass = stencilPasses; *pass ; ++pass) {
732 if (drawDirectToClip) {
733 if (Element::kRect_Type == element->getType()) {
734 drawContext->drawContextPriv().stencilRect(stencilClip, *pass, useHWAA,
735 viewMatrix, e lement->getRect());
736 } else {
737 GrShape shape(clipPath, GrStyle::SimpleFill());
738 GrPaint paint;
739 paint.setXPFactory(GrDisableColorXPFactory::Make());
740 paint.setAntiAlias(element->isAA());
741 GrPathRenderer::DrawPathArgs args;
742 args.fResourceProvider = context->resourceProvider();
743 args.fPaint = &paint;
744 args.fUserStencilSettings = *pass;
745 args.fDrawContext = drawContext;
746 args.fClip = &stencilClip;
747 args.fViewMatrix = &viewMatrix;
748 args.fShape = &shape;
749 args.fAntiAlias = false;
750 args.fGammaCorrect = false;
751 pr->drawPath(args);
752 }
753 } else {
754 // The view matrix is setup to do clip space -> stencil spac e translation, so
755 // draw rect in clip space.
756 drawContext->drawContextPriv().stencilRect(stencilClip, *pas s,
757 false, viewMatrix ,
758 SkRect::Make(redu cedClip.ibounds()));
759 }
760 }
761 }
762 }
763 return true;
764 }
765
766 ////////////////////////////////////////////////////////////////////////////////
767 sk_sp<GrTexture> GrClipStackClip::CreateSoftwareClipMask(GrTextureProvider* texP rovider, 440 sk_sp<GrTexture> GrClipStackClip::CreateSoftwareClipMask(GrTextureProvider* texP rovider,
768 const GrReducedClip& re ducedClip, 441 const GrReducedClip& re ducedClip) {
769 const SkVector& clipToM askOffset) {
770 GrUniqueKey key; 442 GrUniqueKey key;
771 GetClipMaskKey(reducedClip.elementsGenID(), reducedClip.ibounds(), &key); 443 GetClipMaskKey(reducedClip.elementsGenID(), reducedClip.ibounds(), &key);
772 if (GrTexture* texture = texProvider->findAndRefTextureByUniqueKey(key)) { 444 if (GrTexture* texture = texProvider->findAndRefTextureByUniqueKey(key)) {
773 return sk_sp<GrTexture>(texture); 445 return sk_sp<GrTexture>(texture);
774 } 446 }
775 447
776 // The mask texture may be larger than necessary. We round out the clip spac e bounds and pin 448 // The mask texture may be larger than necessary. We round out the clip spac e bounds and pin
777 // the top left corner of the resulting rect to the top left of the texture. 449 // the top left corner of the resulting rect to the top left of the texture.
778 SkIRect maskSpaceIBounds = SkIRect::MakeWH(reducedClip.width(), reducedClip. height()); 450 SkIRect maskSpaceIBounds = SkIRect::MakeWH(reducedClip.width(), reducedClip. height());
779 451
780 GrSWMaskHelper helper(texProvider); 452 GrSWMaskHelper helper(texProvider);
781 453
782 // Set the matrix so that rendered clip elements are transformed to mask spa ce from clip 454 // Set the matrix so that rendered clip elements are transformed to mask spa ce from clip
783 // space. 455 // space.
784 SkMatrix translate; 456 SkMatrix translate;
785 translate.setTranslate(clipToMaskOffset); 457 translate.setTranslate(SkIntToScalar(-reducedClip.left()), SkIntToScalar(-re ducedClip.top()));
786 458
787 helper.init(maskSpaceIBounds, &translate); 459 helper.init(maskSpaceIBounds, &translate);
788 helper.clear(InitialState::kAllIn == reducedClip.initialState() ? 0xFF : 0x0 0); 460 helper.clear(InitialState::kAllIn == reducedClip.initialState() ? 0xFF : 0x0 0);
789 461
790 for (ElementList::Iter iter(reducedClip.elements()); iter.get(); iter.next() ) { 462 for (ElementList::Iter iter(reducedClip.elements()); iter.get(); iter.next() ) {
791 const Element* element = iter.get(); 463 const Element* element = iter.get();
792 SkRegion::Op op = element->getOp(); 464 SkRegion::Op op = element->getOp();
793 465
794 if (SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op == op) { 466 if (SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op == op) {
795 // Intersect and reverse difference require modifying pixels outside of the geometry 467 // Intersect and reverse difference require modifying pixels outside of the geometry
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
830 sk_sp<GrTexture> result(texProvider->createApproxTexture(desc)); 502 sk_sp<GrTexture> result(texProvider->createApproxTexture(desc));
831 if (!result) { 503 if (!result) {
832 return nullptr; 504 return nullptr;
833 } 505 }
834 result->resourcePriv().setUniqueKey(key); 506 result->resourcePriv().setUniqueKey(key);
835 507
836 helper.toTexture(result.get()); 508 helper.toTexture(result.get());
837 509
838 return result; 510 return result;
839 } 511 }
OLDNEW
« no previous file with comments | « src/gpu/GrClipStackClip.h ('k') | src/gpu/GrContext.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698