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

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

Issue 1754563003: Begin weaning GrClipMaskManager off of GrDrawTarget (take 2) (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: update Created 4 years, 9 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
OLDNEW
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
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698