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 "GrAAConvexPathRenderer.h" | 9 #include "GrAAConvexPathRenderer.h" |
10 #include "GrAAHairLinePathRenderer.h" | 10 #include "GrAAHairLinePathRenderer.h" |
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
323 // use both stencil and scissor test to the bounds for the final draw. | 323 // use both stencil and scissor test to the bounds for the final draw. |
324 SkIRect scissorSpaceIBounds(clipSpaceIBounds); | 324 SkIRect scissorSpaceIBounds(clipSpaceIBounds); |
325 scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset); | 325 scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset); |
326 scissorState->set(scissorSpaceIBounds); | 326 scissorState->set(scissorSpaceIBounds); |
327 this->setDrawStateStencil(drawState, ars); | 327 this->setDrawStateStencil(drawState, ars); |
328 return true; | 328 return true; |
329 } | 329 } |
330 | 330 |
331 namespace { | 331 namespace { |
332 //////////////////////////////////////////////////////////////////////////////// | 332 //////////////////////////////////////////////////////////////////////////////// |
333 // set up the OpenGL blend function to perform the specified | 333 // Set a coverage drawing XPF on the drawState for the given op and invertCovera
ge mode |
334 // boolean operation for alpha clip mask creation | 334 void set_coverage_drawing_xpf(SkRegion::Op op, bool invertCoverage, GrDrawState*
drawState) { |
335 void setup_boolean_blendcoeffs(SkRegion::Op op, GrDrawState* drawState) { | 335 SkASSERT(op <= SkRegion::kLastOp); |
336 // TODO: once we have a coverageDrawing XP this will all use that instead of
PD | 336 drawState->setCoverageSetOpXPFactory(op, invertCoverage); |
337 switch (op) { | |
338 case SkRegion::kReplace_Op: | |
339 drawState->setPorterDuffXPFactory(kOne_GrBlendCoeff, kZero_GrBlendCo
eff); | |
340 break; | |
341 case SkRegion::kIntersect_Op: | |
342 drawState->setPorterDuffXPFactory(kDC_GrBlendCoeff, kZero_GrBlendCoe
ff); | |
343 break; | |
344 case SkRegion::kUnion_Op: | |
345 drawState->setPorterDuffXPFactory(kOne_GrBlendCoeff, kISC_GrBlendCoe
ff); | |
346 break; | |
347 case SkRegion::kXOR_Op: | |
348 drawState->setPorterDuffXPFactory(kIDC_GrBlendCoeff, kISC_GrBlendCoe
ff); | |
349 break; | |
350 case SkRegion::kDifference_Op: | |
351 drawState->setPorterDuffXPFactory(kZero_GrBlendCoeff, kISC_GrBlendCo
eff); | |
352 break; | |
353 case SkRegion::kReverseDifference_Op: | |
354 drawState->setPorterDuffXPFactory(kIDC_GrBlendCoeff, kZero_GrBlendCo
eff); | |
355 break; | |
356 default: | |
357 SkASSERT(false); | |
358 break; | |
359 } | |
360 } | 337 } |
361 } | 338 } |
362 | 339 |
363 //////////////////////////////////////////////////////////////////////////////// | 340 //////////////////////////////////////////////////////////////////////////////// |
364 bool GrClipMaskManager::drawElement(GrDrawState* drawState, | 341 bool GrClipMaskManager::drawElement(GrDrawState* drawState, |
365 GrColor color, | |
366 GrTexture* target, | 342 GrTexture* target, |
367 const SkClipStack::Element* element, | 343 const SkClipStack::Element* element, |
368 GrPathRenderer* pr) { | 344 GrPathRenderer* pr) { |
369 GrDrawTarget::AutoGeometryPush agp(fClipTarget); | 345 GrDrawTarget::AutoGeometryPush agp(fClipTarget); |
370 | 346 |
371 drawState->setRenderTarget(target->asRenderTarget()); | 347 drawState->setRenderTarget(target->asRenderTarget()); |
372 | 348 |
| 349 // The color we use to draw does not matter since we will always be using a
GrCoverageSetOpXP |
| 350 // which ignores color. |
| 351 GrColor color = GrColor_WHITE; |
| 352 |
373 // TODO: Draw rrects directly here. | 353 // TODO: Draw rrects directly here. |
374 switch (element->getType()) { | 354 switch (element->getType()) { |
375 case Element::kEmpty_Type: | 355 case Element::kEmpty_Type: |
376 SkDEBUGFAIL("Should never get here with an empty element."); | 356 SkDEBUGFAIL("Should never get here with an empty element."); |
377 break; | 357 break; |
378 case Element::kRect_Type: | 358 case Element::kRect_Type: |
379 // TODO: Do rects directly to the accumulator using a aa-rect GrProc
essor that covers | 359 // TODO: Do rects directly to the accumulator using a aa-rect GrProc
essor that covers |
380 // the entire mask bounds and writes 0 outside the rect. | 360 // the entire mask bounds and writes 0 outside the rect. |
381 if (element->isAA()) { | 361 if (element->isAA()) { |
382 this->getContext()->getAARectRenderer()->fillAARect(fClipTarget, | 362 this->getContext()->getAARectRenderer()->fillAARect(fClipTarget, |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
444 void GrClipMaskManager::mergeMask(GrDrawState* drawState, | 424 void GrClipMaskManager::mergeMask(GrDrawState* drawState, |
445 GrTexture* dstMask, | 425 GrTexture* dstMask, |
446 GrTexture* srcMask, | 426 GrTexture* srcMask, |
447 SkRegion::Op op, | 427 SkRegion::Op op, |
448 const SkIRect& dstBound, | 428 const SkIRect& dstBound, |
449 const SkIRect& srcBound) { | 429 const SkIRect& srcBound) { |
450 SkAssertResult(drawState->setIdentityViewMatrix()); | 430 SkAssertResult(drawState->setIdentityViewMatrix()); |
451 | 431 |
452 drawState->setRenderTarget(dstMask->asRenderTarget()); | 432 drawState->setRenderTarget(dstMask->asRenderTarget()); |
453 | 433 |
454 setup_boolean_blendcoeffs(op, drawState); | 434 // We want to invert the coverage here |
| 435 set_coverage_drawing_xpf(op, false, drawState); |
455 | 436 |
456 SkMatrix sampleM; | 437 SkMatrix sampleM; |
457 sampleM.setIDiv(srcMask->width(), srcMask->height()); | 438 sampleM.setIDiv(srcMask->width(), srcMask->height()); |
458 | 439 |
459 drawState->addColorProcessor( | 440 drawState->addCoverageProcessor( |
460 GrTextureDomainEffect::Create(srcMask, | 441 GrTextureDomainEffect::Create(srcMask, |
461 sampleM, | 442 sampleM, |
462 GrTextureDomain::MakeTexelDomain(srcMask,
srcBound), | 443 GrTextureDomain::MakeTexelDomain(srcMask,
srcBound), |
463 GrTextureDomain::kDecal_Mode, | 444 GrTextureDomain::kDecal_Mode, |
464 GrTextureParams::kNone_FilterMode))->unref
(); | 445 GrTextureParams::kNone_FilterMode))->unref
(); |
| 446 // The color passed in here does not matter since the coverageSetOpXP won't
read it. |
465 fClipTarget->drawSimpleRect(drawState, GrColor_WHITE, SkRect::Make(dstBound)
); | 447 fClipTarget->drawSimpleRect(drawState, GrColor_WHITE, SkRect::Make(dstBound)
); |
466 } | 448 } |
467 | 449 |
468 GrTexture* GrClipMaskManager::createTempMask(int width, int height) { | 450 GrTexture* GrClipMaskManager::createTempMask(int width, int height) { |
469 GrSurfaceDesc desc; | 451 GrSurfaceDesc desc; |
470 desc.fFlags = kRenderTarget_GrSurfaceFlag|kNoStencil_GrSurfaceFlag; | 452 desc.fFlags = kRenderTarget_GrSurfaceFlag|kNoStencil_GrSurfaceFlag; |
471 desc.fWidth = width; | 453 desc.fWidth = width; |
472 desc.fHeight = height; | 454 desc.fHeight = height; |
473 desc.fConfig = kAlpha_8_GrPixelConfig; | 455 desc.fConfig = kAlpha_8_GrPixelConfig; |
474 | 456 |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
560 GrDrawTarget::AutoClipRestore acr(fClipTarget, maskSpaceIBounds); | 542 GrDrawTarget::AutoClipRestore acr(fClipTarget, maskSpaceIBounds); |
561 SkAutoTUnref<GrTexture> temp; | 543 SkAutoTUnref<GrTexture> temp; |
562 | 544 |
563 // walk through each clip element and perform its set op | 545 // walk through each clip element and perform its set op |
564 for (GrReducedClip::ElementList::Iter iter = elements.headIter(); iter.get()
; iter.next()) { | 546 for (GrReducedClip::ElementList::Iter iter = elements.headIter(); iter.get()
; iter.next()) { |
565 const Element* element = iter.get(); | 547 const Element* element = iter.get(); |
566 SkRegion::Op op = element->getOp(); | 548 SkRegion::Op op = element->getOp(); |
567 bool invert = element->isInverseFilled(); | 549 bool invert = element->isInverseFilled(); |
568 if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDiffere
nce_Op == op) { | 550 if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDiffere
nce_Op == op) { |
569 GrDrawState drawState(translate); | 551 GrDrawState drawState(translate); |
570 // We're drawing a coverage mask and want coverage to be run through
the blend function. | 552 drawState.enableState(GrDrawState::kClip_StateBit); |
571 drawState.enableState(GrDrawState::kCoverageDrawing_StateBit | | |
572 GrDrawState::kClip_StateBit); | |
573 | 553 |
574 GrPathRenderer* pr = NULL; | 554 GrPathRenderer* pr = NULL; |
575 bool useTemp = !this->canStencilAndDrawElement(&drawState, result, &
pr, element); | 555 bool useTemp = !this->canStencilAndDrawElement(&drawState, result, &
pr, element); |
576 GrTexture* dst; | 556 GrTexture* dst; |
577 // This is the bounds of the clip element in the space of the alpha-
mask. The temporary | 557 // This is the bounds of the clip element in the space of the alpha-
mask. The temporary |
578 // mask buffer can be substantially larger than the actually clip st
ack element. We | 558 // mask buffer can be substantially larger than the actually clip st
ack element. We |
579 // touch the minimum number of pixels necessary and use decal mode t
o combine it with | 559 // touch the minimum number of pixels necessary and use decal mode t
o combine it with |
580 // the accumulator. | 560 // the accumulator. |
581 SkIRect maskSpaceElementIBounds; | 561 SkIRect maskSpaceElementIBounds; |
582 | 562 |
(...skipping 13 matching lines...) Expand all Loading... |
596 fAACache.reset(); | 576 fAACache.reset(); |
597 return NULL; | 577 return NULL; |
598 } | 578 } |
599 } | 579 } |
600 dst = temp; | 580 dst = temp; |
601 // clear the temp target and set blend to replace | 581 // clear the temp target and set blend to replace |
602 fClipTarget->clear(&maskSpaceElementIBounds, | 582 fClipTarget->clear(&maskSpaceElementIBounds, |
603 invert ? 0xffffffff : 0x00000000, | 583 invert ? 0xffffffff : 0x00000000, |
604 true, | 584 true, |
605 dst->asRenderTarget()); | 585 dst->asRenderTarget()); |
606 setup_boolean_blendcoeffs(SkRegion::kReplace_Op, &drawState); | 586 set_coverage_drawing_xpf(SkRegion::kReplace_Op, invert, &drawSta
te); |
607 } else { | 587 } else { |
608 // draw directly into the result with the stencil set to make th
e pixels affected | 588 // draw directly into the result with the stencil set to make th
e pixels affected |
609 // by the clip shape be non-zero. | 589 // by the clip shape be non-zero. |
610 dst = result; | 590 dst = result; |
611 GR_STATIC_CONST_SAME_STENCIL(kStencilInElement, | 591 GR_STATIC_CONST_SAME_STENCIL(kStencilInElement, |
612 kReplace_StencilOp, | 592 kReplace_StencilOp, |
613 kReplace_StencilOp, | 593 kReplace_StencilOp, |
614 kAlways_StencilFunc, | 594 kAlways_StencilFunc, |
615 0xffff, | 595 0xffff, |
616 0xffff, | 596 0xffff, |
617 0xffff); | 597 0xffff); |
618 drawState.setStencil(kStencilInElement); | 598 drawState.setStencil(kStencilInElement); |
619 setup_boolean_blendcoeffs(op, &drawState); | 599 set_coverage_drawing_xpf(op, invert, &drawState); |
620 } | 600 } |
621 | 601 |
622 // We have to backup the drawstate because the drawElement call may
call into | 602 if (!this->drawElement(&drawState, dst, element, pr)) { |
623 // renderers which consume it. | |
624 GrDrawState backupDrawState(drawState); | |
625 | |
626 if (!this->drawElement(&drawState, invert ? GrColor_TRANS_BLACK : | |
627 GrColor_WHITE, dst, elem
ent, pr)) { | |
628 fAACache.reset(); | 603 fAACache.reset(); |
629 return NULL; | 604 return NULL; |
630 } | 605 } |
631 | 606 |
| 607 GrDrawState backgroundDrawState(translate); |
| 608 backgroundDrawState.enableState(GrDrawState::kClip_StateBit); |
| 609 backgroundDrawState.setRenderTarget(result->asRenderTarget()); |
| 610 |
632 if (useTemp) { | 611 if (useTemp) { |
633 // Now draw into the accumulator using the real operation and th
e temp buffer as a | 612 // Now draw into the accumulator using the real operation and th
e temp buffer as a |
634 // texture | 613 // texture |
635 this->mergeMask(&backupDrawState, | 614 this->mergeMask(&backgroundDrawState, |
636 result, | 615 result, |
637 temp, | 616 temp, |
638 op, | 617 op, |
639 maskSpaceIBounds, | 618 maskSpaceIBounds, |
640 maskSpaceElementIBounds); | 619 maskSpaceElementIBounds); |
641 } else { | 620 } else { |
| 621 set_coverage_drawing_xpf(op, !invert, &backgroundDrawState); |
642 // Draw to the exterior pixels (those with a zero stencil value)
. | 622 // Draw to the exterior pixels (those with a zero stencil value)
. |
643 GR_STATIC_CONST_SAME_STENCIL(kDrawOutsideElement, | 623 GR_STATIC_CONST_SAME_STENCIL(kDrawOutsideElement, |
644 kZero_StencilOp, | 624 kZero_StencilOp, |
645 kZero_StencilOp, | 625 kZero_StencilOp, |
646 kEqual_StencilFunc, | 626 kEqual_StencilFunc, |
647 0xffff, | 627 0xffff, |
648 0x0000, | 628 0x0000, |
649 0xffff); | 629 0xffff); |
650 backupDrawState.setStencil(kDrawOutsideElement); | 630 backgroundDrawState.setStencil(kDrawOutsideElement); |
651 fClipTarget->drawSimpleRect(&backupDrawState, | 631 // The color passed in here does not matter since the coverageSe
tOpXP won't read it. |
652 invert ? GrColor_WHITE : GrColor_TRA
NS_BLACK, | 632 fClipTarget->drawSimpleRect(&backgroundDrawState, GrColor_WHITE,
clipSpaceIBounds); |
653 clipSpaceIBounds); | |
654 } | 633 } |
655 } else { | 634 } else { |
656 GrDrawState drawState(translate); | 635 GrDrawState drawState(translate); |
657 drawState.enableState(GrDrawState::kCoverageDrawing_StateBit | | 636 drawState.enableState(GrDrawState::kClip_StateBit); |
658 GrDrawState::kClip_StateBit); | |
659 | 637 |
660 // all the remaining ops can just be directly draw into the accumula
tion buffer | 638 // all the remaining ops can just be directly draw into the accumula
tion buffer |
661 setup_boolean_blendcoeffs(op, &drawState); | 639 set_coverage_drawing_xpf(op, false, &drawState); |
662 this->drawElement(&drawState, GrColor_WHITE, result, element); | 640 // The color passed in here does not matter since the coverageSetOpX
P won't read it. |
| 641 this->drawElement(&drawState, result, element); |
663 } | 642 } |
664 } | 643 } |
665 | 644 |
666 fCurrClipMaskType = kAlpha_ClipMaskType; | 645 fCurrClipMaskType = kAlpha_ClipMaskType; |
667 return result; | 646 return result; |
668 } | 647 } |
669 | 648 |
670 //////////////////////////////////////////////////////////////////////////////// | 649 //////////////////////////////////////////////////////////////////////////////// |
671 // Create a 1-bit clip mask in the stencil buffer. 'devClipBounds' are in device | 650 // Create a 1-bit clip mask in the stencil buffer. 'devClipBounds' are in device |
672 // (as opposed to canvas) coordinates | 651 // (as opposed to canvas) coordinates |
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1081 } | 1060 } |
1082 | 1061 |
1083 void GrClipMaskManager::adjustPathStencilParams(const GrStencilBuffer* stencilBu
ffer, | 1062 void GrClipMaskManager::adjustPathStencilParams(const GrStencilBuffer* stencilBu
ffer, |
1084 GrStencilSettings* settings) { | 1063 GrStencilSettings* settings) { |
1085 // TODO: dynamically attach a stencil buffer | 1064 // TODO: dynamically attach a stencil buffer |
1086 if (stencilBuffer) { | 1065 if (stencilBuffer) { |
1087 int stencilBits = stencilBuffer->bits(); | 1066 int stencilBits = stencilBuffer->bits(); |
1088 this->adjustStencilParams(settings, fClipMode, stencilBits); | 1067 this->adjustStencilParams(settings, fClipMode, stencilBits); |
1089 } | 1068 } |
1090 } | 1069 } |
OLD | NEW |