OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2012 Google Inc. | 3 * Copyright 2012 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 #include "GrClipMaskManager.h" | 9 #include "GrClipMaskManager.h" |
10 #include "GrAAConvexPathRenderer.h" | 10 #include "GrAAConvexPathRenderer.h" |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 bool GrClipMaskManager::useSWOnlyPath(const ElementList& elements) { | 87 bool GrClipMaskManager::useSWOnlyPath(const ElementList& elements) { |
88 | 88 |
89 // TODO: generalize this function so that when | 89 // TODO: generalize this function so that when |
90 // a clip gets complex enough it can just be done in SW regardless | 90 // a clip gets complex enough it can just be done in SW regardless |
91 // of whether it would invoke the GrSoftwarePathRenderer. | 91 // of whether it would invoke the GrSoftwarePathRenderer. |
92 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); | 92 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); |
93 | 93 |
94 for (ElementList::Iter iter(elements.headIter()); iter.get(); iter.next()) { | 94 for (ElementList::Iter iter(elements.headIter()); iter.get(); iter.next()) { |
95 const Element* element = iter.get(); | 95 const Element* element = iter.get(); |
96 // rects can always be drawn directly w/o using the software path | 96 // rects can always be drawn directly w/o using the software path |
97 // so only paths need to be checked | 97 // Skip rrects once we're drawing them directly. |
98 if (Element::kPath_Type == element->getType() && | 98 if (Element::kRect_Type != element->getType()) { |
99 path_needs_SW_renderer(this->getContext(), fGpu, | 99 SkPath path; |
100 element->getPath(), | 100 element->asPath(&path); |
101 stroke, | 101 if (path_needs_SW_renderer(this->getContext(), fGpu, path, stroke, e
lement->isAA())) { |
102 element->isAA())) { | 102 return true; |
103 return true; | 103 } |
104 } | 104 } |
105 } | 105 } |
106 return false; | 106 return false; |
107 } | 107 } |
108 | 108 |
109 //////////////////////////////////////////////////////////////////////////////// | 109 //////////////////////////////////////////////////////////////////////////////// |
110 // sort out what kind of clip mask needs to be created: alpha, stencil, | 110 // sort out what kind of clip mask needs to be created: alpha, stencil, |
111 // scissor, or entirely software | 111 // scissor, or entirely software |
112 bool GrClipMaskManager::setupClipping(const GrClipData* clipDataIn, | 112 bool GrClipMaskManager::setupClipping(const GrClipData* clipDataIn, |
113 GrDrawState::AutoRestoreEffects* are, | 113 GrDrawState::AutoRestoreEffects* are, |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
162 if (NULL != devBounds) { | 162 if (NULL != devBounds) { |
163 SkRect boundsInClipSpace = *devBounds; | 163 SkRect boundsInClipSpace = *devBounds; |
164 boundsInClipSpace.offset(SkIntToScalar(clipDataIn->fOrigin.fX), | 164 boundsInClipSpace.offset(SkIntToScalar(clipDataIn->fOrigin.fX), |
165 SkIntToScalar(clipDataIn->fOrigin.fY)); | 165 SkIntToScalar(clipDataIn->fOrigin.fY)); |
166 if (elements.tail()->contains(boundsInClipSpace)) { | 166 if (elements.tail()->contains(boundsInClipSpace)) { |
167 fGpu->disableScissor(); | 167 fGpu->disableScissor(); |
168 this->setGpuStencil(); | 168 this->setGpuStencil(); |
169 return true; | 169 return true; |
170 } | 170 } |
171 } | 171 } |
| 172 Element::Type type = elements.tail()->getType(); |
| 173 bool isAA = GR_AA_CLIP && elements.tail()->isAA(); |
172 SkAutoTUnref<GrEffectRef> effect; | 174 SkAutoTUnref<GrEffectRef> effect; |
173 if (SkClipStack::Element::kPath_Type == elements.tail()->getType()) { | 175 if (SkClipStack::Element::kPath_Type == type) { |
174 const SkPath& path = elements.tail()->getPath(); | 176 const SkPath& path = elements.tail()->getPath(); |
175 bool isAA = GR_AA_CLIP && elements.tail()->isAA(); | |
176 if (rt->isMultisampled()) { | 177 if (rt->isMultisampled()) { |
177 // A coverage effect for AA clipping won't play nicely with MSAA
. | 178 // A coverage effect for AA clipping won't play nicely with MSAA
. |
178 if (!isAA) { | 179 if (!isAA) { |
179 SkVector offset = { SkIntToScalar(-clipDataIn->fOrigin.fX), | 180 SkVector offset = { SkIntToScalar(-clipDataIn->fOrigin.fX), |
180 SkIntToScalar(-clipDataIn->fOrigin.fY) }
; | 181 SkIntToScalar(-clipDataIn->fOrigin.fY) }
; |
181 effect.reset(GrConvexPolyEffect::Create(GrConvexPolyEffect::
kFillNoAA_EdgeType, | 182 effect.reset(GrConvexPolyEffect::Create(GrConvexPolyEffect::
kFillNoAA_EdgeType, |
182 path, &offset)); | 183 path, &offset)); |
183 } | 184 } |
184 } else { | 185 } else { |
185 SkVector offset = { SkIntToScalar(-clipDataIn->fOrigin.fX), | 186 SkVector offset = { SkIntToScalar(-clipDataIn->fOrigin.fX), |
186 SkIntToScalar(-clipDataIn->fOrigin.fY) }; | 187 SkIntToScalar(-clipDataIn->fOrigin.fY) }; |
187 GrConvexPolyEffect::EdgeType type = isAA ? GrConvexPolyEffect::k
FillAA_EdgeType : | 188 GrConvexPolyEffect::EdgeType type = isAA ? GrConvexPolyEffect::k
FillAA_EdgeType : |
188 GrConvexPolyEffect::k
FillNoAA_EdgeType; | 189 GrConvexPolyEffect::k
FillNoAA_EdgeType; |
189 effect.reset(GrConvexPolyEffect::Create(type, path, &offset)); | 190 effect.reset(GrConvexPolyEffect::Create(type, path, &offset)); |
190 } | 191 } |
191 } else if (GR_AA_CLIP && elements.tail()->isAA() && !rt->isMultisampled(
)) { | 192 } else if (isAA && SkClipStack::Element::kRect_Type == type && !rt->isMu
ltisampled()) { |
192 // We only handle AA/non-MSAA rects here. Coverage effect AA isn't M
SAA friendly and | 193 // We only handle AA/non-MSAA rects here. Coverage effect AA isn't M
SAA friendly and |
193 // non-AA rect clips are handled by the scissor. | 194 // non-AA rect clips are handled by the scissor. |
194 SkASSERT(SkClipStack::Element::kRect_Type == elements.tail()->getTyp
e()); | |
195 SkRect rect = elements.tail()->getRect(); | 195 SkRect rect = elements.tail()->getRect(); |
196 SkVector offset = { SkIntToScalar(-clipDataIn->fOrigin.fX), | 196 SkVector offset = { SkIntToScalar(-clipDataIn->fOrigin.fX), |
197 SkIntToScalar(-clipDataIn->fOrigin.fY) }; | 197 SkIntToScalar(-clipDataIn->fOrigin.fY) }; |
198 rect.offset(offset); | 198 rect.offset(offset); |
199 effect.reset(GrConvexPolyEffect::CreateForAAFillRect(rect)); | 199 effect.reset(GrConvexPolyEffect::CreateForAAFillRect(rect)); |
200 // This should never fail. | 200 // This should never fail. |
201 SkASSERT(effect); | 201 SkASSERT(effect); |
202 } | 202 } |
203 if (effect) { | 203 if (effect) { |
204 are->set(fGpu->drawState()); | 204 are->set(fGpu->drawState()); |
205 fGpu->drawState()->addCoverageEffect(effect); | 205 fGpu->drawState()->addCoverageEffect(effect); |
206 SkIRect scissorSpaceIBounds(clipSpaceIBounds); | 206 SkIRect scissorSpaceIBounds(clipSpaceIBounds); |
207 scissorSpaceIBounds.offset(-clipDataIn->fOrigin); | 207 scissorSpaceIBounds.offset(-clipDataIn->fOrigin); |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
325 } | 325 } |
326 | 326 |
327 //////////////////////////////////////////////////////////////////////////////// | 327 //////////////////////////////////////////////////////////////////////////////// |
328 bool GrClipMaskManager::drawElement(GrTexture* target, | 328 bool GrClipMaskManager::drawElement(GrTexture* target, |
329 const SkClipStack::Element* element, | 329 const SkClipStack::Element* element, |
330 GrPathRenderer* pr) { | 330 GrPathRenderer* pr) { |
331 GrDrawState* drawState = fGpu->drawState(); | 331 GrDrawState* drawState = fGpu->drawState(); |
332 | 332 |
333 drawState->setRenderTarget(target->asRenderTarget()); | 333 drawState->setRenderTarget(target->asRenderTarget()); |
334 | 334 |
| 335 // TODO: Draw rrects directly here. |
335 switch (element->getType()) { | 336 switch (element->getType()) { |
| 337 case Element::kEmpty_Type: |
| 338 SkDEBUGFAIL("Should never get here with an empty element."); |
| 339 break; |
336 case Element::kRect_Type: | 340 case Element::kRect_Type: |
337 // TODO: Do rects directly to the accumulator using a aa-rect GrEffe
ct that covers the | 341 // TODO: Do rects directly to the accumulator using a aa-rect GrEffe
ct that covers the |
338 // entire mask bounds and writes 0 outside the rect. | 342 // entire mask bounds and writes 0 outside the rect. |
339 if (element->isAA()) { | 343 if (element->isAA()) { |
340 getContext()->getAARectRenderer()->fillAARect(fGpu, | 344 getContext()->getAARectRenderer()->fillAARect(fGpu, |
341 fGpu, | 345 fGpu, |
342 element->getRect()
, | 346 element->getRect()
, |
343 SkMatrix::I(), | 347 SkMatrix::I(), |
344 element->getRect()
, | 348 element->getRect()
, |
345 false); | 349 false); |
346 } else { | 350 } else { |
347 fGpu->drawSimpleRect(element->getRect(), NULL); | 351 fGpu->drawSimpleRect(element->getRect(), NULL); |
348 } | 352 } |
349 return true; | 353 return true; |
350 case Element::kPath_Type: { | 354 default: { |
351 SkTCopyOnFirstWrite<SkPath> path(element->getPath()); | 355 SkPath path; |
352 if (path->isInverseFillType()) { | 356 element->asPath(&path); |
353 path.writable()->toggleInverseFillType(); | 357 if (path.isInverseFillType()) { |
| 358 path.toggleInverseFillType(); |
354 } | 359 } |
355 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); | 360 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); |
356 if (NULL == pr) { | 361 if (NULL == pr) { |
357 GrPathRendererChain::DrawType type; | 362 GrPathRendererChain::DrawType type; |
358 type = element->isAA() ? GrPathRendererChain::kColorAntiAlias_Dr
awType : | 363 type = element->isAA() ? GrPathRendererChain::kColorAntiAlias_Dr
awType : |
359 GrPathRendererChain::kColor_DrawType; | 364 GrPathRendererChain::kColor_DrawType; |
360 pr = this->getContext()->getPathRenderer(*path, stroke, fGpu, fa
lse, type); | 365 pr = this->getContext()->getPathRenderer(path, stroke, fGpu, fal
se, type); |
361 } | 366 } |
362 if (NULL == pr) { | 367 if (NULL == pr) { |
363 return false; | 368 return false; |
364 } | 369 } |
365 pr->drawPath(element->getPath(), stroke, fGpu, element->isAA()); | 370 pr->drawPath(path, stroke, fGpu, element->isAA()); |
366 break; | 371 break; |
367 } | 372 } |
368 default: | |
369 // something is wrong if we're trying to draw an empty element. | |
370 GrCrash("Unexpected element type"); | |
371 return false; | |
372 } | 373 } |
373 return true; | 374 return true; |
374 } | 375 } |
375 | 376 |
376 bool GrClipMaskManager::canStencilAndDrawElement(GrTexture* target, | 377 bool GrClipMaskManager::canStencilAndDrawElement(GrTexture* target, |
377 const SkClipStack::Element* ele
ment, | 378 const SkClipStack::Element* ele
ment, |
378 GrPathRenderer** pr) { | 379 GrPathRenderer** pr) { |
379 GrDrawState* drawState = fGpu->drawState(); | 380 GrDrawState* drawState = fGpu->drawState(); |
380 drawState->setRenderTarget(target->asRenderTarget()); | 381 drawState->setRenderTarget(target->asRenderTarget()); |
381 | 382 |
382 switch (element->getType()) { | 383 if (Element::kRect_Type == element->getType()) { |
383 case Element::kRect_Type: | 384 return true; |
384 return true; | 385 } else { |
385 case Element::kPath_Type: { | 386 // We shouldn't get here with an empty clip element. |
386 SkTCopyOnFirstWrite<SkPath> path(element->getPath()); | 387 SkASSERT(Element::kEmpty_Type != element->getType()); |
387 if (path->isInverseFillType()) { | 388 SkPath path; |
388 path.writable()->toggleInverseFillType(); | 389 element->asPath(&path); |
389 } | 390 if (path.isInverseFillType()) { |
390 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); | 391 path.toggleInverseFillType(); |
391 GrPathRendererChain::DrawType type = element->isAA() ? | |
392 GrPathRendererChain::kStencilAndColorAntiAlias_DrawType : | |
393 GrPathRendererChain::kStencilAndColor_DrawType; | |
394 *pr = this->getContext()->getPathRenderer(*path, stroke, fGpu, false
, type); | |
395 return NULL != *pr; | |
396 } | 392 } |
397 default: | 393 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); |
398 // something is wrong if we're trying to draw an empty element. | 394 GrPathRendererChain::DrawType type = element->isAA() ? |
399 GrCrash("Unexpected element type"); | 395 GrPathRendererChain::kStencilAndColorAntiAlias_DrawType : |
400 return false; | 396 GrPathRendererChain::kStencilAndColor_DrawType; |
| 397 *pr = this->getContext()->getPathRenderer(path, stroke, fGpu, false, typ
e); |
| 398 return NULL != *pr; |
401 } | 399 } |
402 } | 400 } |
403 | 401 |
404 void GrClipMaskManager::mergeMask(GrTexture* dstMask, | 402 void GrClipMaskManager::mergeMask(GrTexture* dstMask, |
405 GrTexture* srcMask, | 403 GrTexture* srcMask, |
406 SkRegion::Op op, | 404 SkRegion::Op op, |
407 const SkIRect& dstBound, | 405 const SkIRect& dstBound, |
408 const SkIRect& srcBound) { | 406 const SkIRect& srcBound) { |
409 GrDrawState::AutoViewMatrixRestore avmr; | 407 GrDrawState::AutoViewMatrixRestore avmr; |
410 GrDrawState* drawState = fGpu->drawState(); | 408 GrDrawState* drawState = fGpu->drawState(); |
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
693 | 691 |
694 // This will be used to determine whether the clip shape can be rend
ered into the | 692 // This will be used to determine whether the clip shape can be rend
ered into the |
695 // stencil with arbitrary stencil settings. | 693 // stencil with arbitrary stencil settings. |
696 GrPathRenderer::StencilSupport stencilSupport; | 694 GrPathRenderer::StencilSupport stencilSupport; |
697 | 695 |
698 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); | 696 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); |
699 | 697 |
700 SkRegion::Op op = element->getOp(); | 698 SkRegion::Op op = element->getOp(); |
701 | 699 |
702 GrPathRenderer* pr = NULL; | 700 GrPathRenderer* pr = NULL; |
703 SkTCopyOnFirstWrite<SkPath> clipPath; | 701 SkPath clipPath; |
704 if (Element::kRect_Type == element->getType()) { | 702 if (Element::kRect_Type == element->getType()) { |
705 stencilSupport = GrPathRenderer::kNoRestriction_StencilSupport; | 703 stencilSupport = GrPathRenderer::kNoRestriction_StencilSupport; |
706 fillInverted = false; | 704 fillInverted = false; |
707 } else { | 705 } else { |
708 SkASSERT(Element::kPath_Type == element->getType()); | 706 element->asPath(&clipPath); |
709 clipPath.init(element->getPath()); | 707 fillInverted = clipPath.isInverseFillType(); |
710 fillInverted = clipPath->isInverseFillType(); | |
711 if (fillInverted) { | 708 if (fillInverted) { |
712 clipPath.writable()->toggleInverseFillType(); | 709 clipPath.toggleInverseFillType(); |
713 } | 710 } |
714 pr = this->getContext()->getPathRenderer(*clipPath, | 711 pr = this->getContext()->getPathRenderer(clipPath, |
715 stroke, | 712 stroke, |
716 fGpu, | 713 fGpu, |
717 false, | 714 false, |
718 GrPathRendererChain::kS
tencilOnly_DrawType, | 715 GrPathRendererChain::kS
tencilOnly_DrawType, |
719 &stencilSupport); | 716 &stencilSupport); |
720 if (NULL == pr) { | 717 if (NULL == pr) { |
721 return false; | 718 return false; |
722 } | 719 } |
723 } | 720 } |
724 | 721 |
(...skipping 20 matching lines...) Expand all Loading... |
745 kIncClamp_StencilOp, | 742 kIncClamp_StencilOp, |
746 kAlways_StencilFunc, | 743 kAlways_StencilFunc, |
747 0xffff, | 744 0xffff, |
748 0x0000, | 745 0x0000, |
749 0xffff); | 746 0xffff); |
750 SET_RANDOM_COLOR | 747 SET_RANDOM_COLOR |
751 if (Element::kRect_Type == element->getType()) { | 748 if (Element::kRect_Type == element->getType()) { |
752 *drawState->stencil() = gDrawToStencil; | 749 *drawState->stencil() = gDrawToStencil; |
753 fGpu->drawSimpleRect(element->getRect(), NULL); | 750 fGpu->drawSimpleRect(element->getRect(), NULL); |
754 } else { | 751 } else { |
755 SkASSERT(Element::kPath_Type == element->getType()); | 752 if (!clipPath.isEmpty()) { |
756 if (!clipPath->isEmpty()) { | |
757 if (canRenderDirectToStencil) { | 753 if (canRenderDirectToStencil) { |
758 *drawState->stencil() = gDrawToStencil; | 754 *drawState->stencil() = gDrawToStencil; |
759 pr->drawPath(*clipPath, stroke, fGpu, false); | 755 pr->drawPath(clipPath, stroke, fGpu, false); |
760 } else { | 756 } else { |
761 pr->stencilPath(*clipPath, stroke, fGpu); | 757 pr->stencilPath(clipPath, stroke, fGpu); |
762 } | 758 } |
763 } | 759 } |
764 } | 760 } |
765 } | 761 } |
766 | 762 |
767 // now we modify the clip bit by rendering either the clip | 763 // now we modify the clip bit by rendering either the clip |
768 // element directly or a bounding rect of the entire clip. | 764 // element directly or a bounding rect of the entire clip. |
769 drawState->enableState(GrGpu::kModifyStencilClip_StateBit); | 765 drawState->enableState(GrGpu::kModifyStencilClip_StateBit); |
770 for (int p = 0; p < passes; ++p) { | 766 for (int p = 0; p < passes; ++p) { |
771 *drawState->stencil() = stencilSettings[p]; | 767 *drawState->stencil() = stencilSettings[p]; |
772 if (canDrawDirectToClip) { | 768 if (canDrawDirectToClip) { |
773 if (Element::kRect_Type == element->getType()) { | 769 if (Element::kRect_Type == element->getType()) { |
774 SET_RANDOM_COLOR | 770 SET_RANDOM_COLOR |
775 fGpu->drawSimpleRect(element->getRect(), NULL); | 771 fGpu->drawSimpleRect(element->getRect(), NULL); |
776 } else { | 772 } else { |
777 SkASSERT(Element::kPath_Type == element->getType()); | |
778 SET_RANDOM_COLOR | 773 SET_RANDOM_COLOR |
779 pr->drawPath(*clipPath, stroke, fGpu, false); | 774 pr->drawPath(clipPath, stroke, fGpu, false); |
780 } | 775 } |
781 } else { | 776 } else { |
782 SET_RANDOM_COLOR | 777 SET_RANDOM_COLOR |
783 // The view matrix is setup to do clip space -> stencil spac
e translation, so | 778 // The view matrix is setup to do clip space -> stencil spac
e translation, so |
784 // draw rect in clip space. | 779 // draw rect in clip space. |
785 fGpu->drawSimpleRect(SkRect::Make(clipSpaceIBounds), NULL); | 780 fGpu->drawSimpleRect(SkRect::Make(clipSpaceIBounds), NULL); |
786 } | 781 } |
787 } | 782 } |
788 } | 783 } |
789 } | 784 } |
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1091 | 1086 |
1092 // TODO: dynamically attach a stencil buffer | 1087 // TODO: dynamically attach a stencil buffer |
1093 int stencilBits = 0; | 1088 int stencilBits = 0; |
1094 GrStencilBuffer* stencilBuffer = | 1089 GrStencilBuffer* stencilBuffer = |
1095 drawState.getRenderTarget()->getStencilBuffer(); | 1090 drawState.getRenderTarget()->getStencilBuffer(); |
1096 if (NULL != stencilBuffer) { | 1091 if (NULL != stencilBuffer) { |
1097 stencilBits = stencilBuffer->bits(); | 1092 stencilBits = stencilBuffer->bits(); |
1098 this->adjustStencilParams(settings, clipMode, stencilBits); | 1093 this->adjustStencilParams(settings, clipMode, stencilBits); |
1099 } | 1094 } |
1100 } | 1095 } |
OLD | NEW |