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" |
11 #include "GrAAHairLinePathRenderer.h" | 11 #include "GrAAHairLinePathRenderer.h" |
12 #include "GrAARectRenderer.h" | 12 #include "GrAARectRenderer.h" |
13 #include "GrDrawTargetCaps.h" | 13 #include "GrDrawTargetCaps.h" |
14 #include "GrGpu.h" | |
15 #include "GrPaint.h" | 14 #include "GrPaint.h" |
16 #include "GrPathRenderer.h" | 15 #include "GrPathRenderer.h" |
17 #include "GrRenderTarget.h" | 16 #include "GrRenderTarget.h" |
18 #include "GrStencilBuffer.h" | 17 #include "GrStencilBuffer.h" |
19 #include "GrSWMaskHelper.h" | 18 #include "GrSWMaskHelper.h" |
20 #include "SkRasterClip.h" | 19 #include "SkRasterClip.h" |
21 #include "SkStrokeRec.h" | 20 #include "SkStrokeRec.h" |
22 #include "SkTLazy.h" | 21 #include "SkTLazy.h" |
23 #include "effects/GrTextureDomain.h" | 22 #include "effects/GrTextureDomain.h" |
24 #include "effects/GrConvexPolyEffect.h" | 23 #include "effects/GrConvexPolyEffect.h" |
25 #include "effects/GrRRectEffect.h" | 24 #include "effects/GrRRectEffect.h" |
26 | 25 |
27 #define GR_AA_CLIP 1 | 26 #define GR_AA_CLIP 1 |
28 | 27 |
29 typedef SkClipStack::Element Element; | 28 typedef SkClipStack::Element Element; |
30 | 29 |
31 //////////////////////////////////////////////////////////////////////////////// | 30 //////////////////////////////////////////////////////////////////////////////// |
32 namespace { | 31 namespace { |
33 // set up the draw state to enable the aa clipping mask. Besides setting up the | 32 // set up the draw state to enable the aa clipping mask. Besides setting up the |
34 // stage matrix this also alters the vertex layout | 33 // stage matrix this also alters the vertex layout |
35 void setup_drawstate_aaclip(GrGpu* gpu, | 34 void setup_drawstate_aaclip(GrDrawTarget* gpu, |
36 GrTexture* result, | 35 GrTexture* result, |
37 const SkIRect &devBound) { | 36 const SkIRect &devBound) { |
38 GrDrawState* drawState = gpu->drawState(); | 37 GrDrawState* drawState = gpu->drawState(); |
39 SkASSERT(drawState); | 38 SkASSERT(drawState); |
40 | 39 |
41 SkMatrix mat; | 40 SkMatrix mat; |
42 // We want to use device coords to compute the texture coordinates. We set o
ur matrix to be | 41 // We want to use device coords to compute the texture coordinates. We set o
ur matrix to be |
43 // equal to the view matrix followed by an offset to the devBound, and then
a scaling matrix to | 42 // equal to the view matrix followed by an offset to the devBound, and then
a scaling matrix to |
44 // normalized coords. We apply this matrix to the vertex positions rather th
an local coords. | 43 // normalized coords. We apply this matrix to the vertex positions rather th
an local coords. |
45 mat.setIDiv(result->width(), result->height()); | 44 mat.setIDiv(result->width(), result->height()); |
46 mat.preTranslate(SkIntToScalar(-devBound.fLeft), | 45 mat.preTranslate(SkIntToScalar(-devBound.fLeft), |
47 SkIntToScalar(-devBound.fTop)); | 46 SkIntToScalar(-devBound.fTop)); |
48 mat.preConcat(drawState->getViewMatrix()); | 47 mat.preConcat(drawState->getViewMatrix()); |
49 | 48 |
50 SkIRect domainTexels = SkIRect::MakeWH(devBound.width(), devBound.height()); | 49 SkIRect domainTexels = SkIRect::MakeWH(devBound.width(), devBound.height()); |
51 // This could be a long-lived effect that is cached with the alpha-mask. | 50 // This could be a long-lived effect that is cached with the alpha-mask. |
52 drawState->addCoverageProcessor( | 51 drawState->addCoverageProcessor( |
53 GrTextureDomainEffect::Create(result, | 52 GrTextureDomainEffect::Create(result, |
54 mat, | 53 mat, |
55 GrTextureDomain::MakeTexelDomain(result, d
omainTexels), | 54 GrTextureDomain::MakeTexelDomain(result, d
omainTexels), |
56 GrTextureDomain::kDecal_Mode, | 55 GrTextureDomain::kDecal_Mode, |
57 GrTextureParams::kNone_FilterMode, | 56 GrTextureParams::kNone_FilterMode, |
58 kPosition_GrCoordSet))->unref(); | 57 kPosition_GrCoordSet))->unref(); |
59 } | 58 } |
60 | 59 |
61 bool path_needs_SW_renderer(GrContext* context, | 60 bool path_needs_SW_renderer(GrContext* context, |
62 GrGpu* gpu, | 61 GrDrawTarget* gpu, |
63 const SkPath& origPath, | 62 const SkPath& origPath, |
64 const SkStrokeRec& stroke, | 63 const SkStrokeRec& stroke, |
65 bool doAA) { | 64 bool doAA) { |
66 // the gpu alpha mask will draw the inverse paths as non-inverse to a temp b
uffer | 65 // the gpu alpha mask will draw the inverse paths as non-inverse to a temp b
uffer |
67 SkTCopyOnFirstWrite<SkPath> path(origPath); | 66 SkTCopyOnFirstWrite<SkPath> path(origPath); |
68 if (path->isInverseFillType()) { | 67 if (path->isInverseFillType()) { |
69 path.writable()->toggleInverseFillType(); | 68 path.writable()->toggleInverseFillType(); |
70 } | 69 } |
71 // last (false) parameter disallows use of the SW path renderer | 70 // last (false) parameter disallows use of the SW path renderer |
72 GrPathRendererChain::DrawType type = doAA ? | 71 GrPathRendererChain::DrawType type = doAA ? |
(...skipping 17 matching lines...) Expand all Loading... |
90 // of whether it would invoke the GrSoftwarePathRenderer. | 89 // of whether it would invoke the GrSoftwarePathRenderer. |
91 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); | 90 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); |
92 | 91 |
93 for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.get();
iter.next()) { | 92 for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.get();
iter.next()) { |
94 const Element* element = iter.get(); | 93 const Element* element = iter.get(); |
95 // rects can always be drawn directly w/o using the software path | 94 // rects can always be drawn directly w/o using the software path |
96 // Skip rrects once we're drawing them directly. | 95 // Skip rrects once we're drawing them directly. |
97 if (Element::kRect_Type != element->getType()) { | 96 if (Element::kRect_Type != element->getType()) { |
98 SkPath path; | 97 SkPath path; |
99 element->asPath(&path); | 98 element->asPath(&path); |
100 if (path_needs_SW_renderer(this->getContext(), fGpu, path, stroke, e
lement->isAA())) { | 99 if (path_needs_SW_renderer(this->getContext(), fClipTarget, path, st
roke, |
| 100 element->isAA())) { |
101 return true; | 101 return true; |
102 } | 102 } |
103 } | 103 } |
104 } | 104 } |
105 return false; | 105 return false; |
106 } | 106 } |
107 | 107 |
108 bool GrClipMaskManager::installClipEffects(const GrReducedClip::ElementList& ele
ments, | 108 bool GrClipMaskManager::installClipEffects(const GrReducedClip::ElementList& ele
ments, |
109 GrDrawState::AutoRestoreEffects* are, | 109 GrDrawState::AutoRestoreEffects* are, |
110 const SkVector& clipToRTOffset, | 110 const SkVector& clipToRTOffset, |
111 const SkRect* drawBounds) { | 111 const SkRect* drawBounds) { |
112 | 112 |
113 GrDrawState* drawState = fGpu->drawState(); | 113 GrDrawState* drawState = fClipTarget->drawState(); |
114 SkRect boundsInClipSpace; | 114 SkRect boundsInClipSpace; |
115 if (drawBounds) { | 115 if (drawBounds) { |
116 boundsInClipSpace = *drawBounds; | 116 boundsInClipSpace = *drawBounds; |
117 boundsInClipSpace.offset(-clipToRTOffset.fX, -clipToRTOffset.fY); | 117 boundsInClipSpace.offset(-clipToRTOffset.fX, -clipToRTOffset.fY); |
118 } | 118 } |
119 | 119 |
120 are->set(drawState); | 120 are->set(drawState); |
121 GrRenderTarget* rt = drawState->getRenderTarget(); | 121 GrRenderTarget* rt = drawState->getRenderTarget(); |
122 GrReducedClip::ElementList::Iter iter(elements); | 122 GrReducedClip::ElementList::Iter iter(elements); |
123 | 123 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
181 SkRect rect = iter.get()->getRect(); | 181 SkRect rect = iter.get()->getRect(); |
182 rect.offset(clipToRTOffset.fX, clipToRTOffset.fY); | 182 rect.offset(clipToRTOffset.fX, clipToRTOffset.fY); |
183 fp.reset(GrConvexPolyEffect::Create(edgeType, rect)); | 183 fp.reset(GrConvexPolyEffect::Create(edgeType, rect)); |
184 break; | 184 break; |
185 } | 185 } |
186 default: | 186 default: |
187 break; | 187 break; |
188 } | 188 } |
189 if (fp) { | 189 if (fp) { |
190 if (!setARE) { | 190 if (!setARE) { |
191 are->set(fGpu->drawState()); | 191 are->set(fClipTarget->drawState()); |
192 setARE = true; | 192 setARE = true; |
193 } | 193 } |
194 fGpu->drawState()->addCoverageProcessor(fp); | 194 fClipTarget->drawState()->addCoverageProcessor(fp); |
195 } else { | 195 } else { |
196 failed = true; | 196 failed = true; |
197 break; | 197 break; |
198 } | 198 } |
199 } | 199 } |
200 iter.next(); | 200 iter.next(); |
201 } | 201 } |
202 | 202 |
203 if (failed) { | 203 if (failed) { |
204 are->set(NULL); | 204 are->set(NULL); |
(...skipping 11 matching lines...) Expand all Loading... |
216 GrDrawState::AutoRestoreStencil* ars, | 216 GrDrawState::AutoRestoreStencil* ars, |
217 ScissorState* scissorState) { | 217 ScissorState* scissorState) { |
218 fCurrClipMaskType = kNone_ClipMaskType; | 218 fCurrClipMaskType = kNone_ClipMaskType; |
219 | 219 |
220 GrReducedClip::ElementList elements(16); | 220 GrReducedClip::ElementList elements(16); |
221 int32_t genID; | 221 int32_t genID; |
222 GrReducedClip::InitialState initialState; | 222 GrReducedClip::InitialState initialState; |
223 SkIRect clipSpaceIBounds; | 223 SkIRect clipSpaceIBounds; |
224 bool requiresAA; | 224 bool requiresAA; |
225 | 225 |
226 GrDrawState* drawState = fGpu->drawState(); | 226 GrDrawState* drawState = fClipTarget->drawState(); |
227 | 227 |
228 const GrRenderTarget* rt = drawState->getRenderTarget(); | 228 const GrRenderTarget* rt = drawState->getRenderTarget(); |
229 // GrDrawTarget should have filtered this for us | 229 // GrDrawTarget should have filtered this for us |
230 SkASSERT(rt); | 230 SkASSERT(rt); |
231 | 231 |
232 bool ignoreClip = !drawState->isClipState() || clipDataIn->fClipStack->isWid
eOpen(); | 232 bool ignoreClip = !drawState->isClipState() || clipDataIn->fClipStack->isWid
eOpen(); |
233 if (!ignoreClip) { | 233 if (!ignoreClip) { |
234 SkIRect clipSpaceRTIBounds = SkIRect::MakeWH(rt->width(), rt->height()); | 234 SkIRect clipSpaceRTIBounds = SkIRect::MakeWH(rt->width(), rt->height()); |
235 clipSpaceRTIBounds.offset(clipDataIn->fOrigin); | 235 clipSpaceRTIBounds.offset(clipDataIn->fOrigin); |
236 GrReducedClip::ReduceClipStack(*clipDataIn->fClipStack, | 236 GrReducedClip::ReduceClipStack(*clipDataIn->fClipStack, |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 initialState, | 295 initialState, |
296 elements, | 296 elements, |
297 clipSpaceIBounds); | 297 clipSpaceIBounds); |
298 } | 298 } |
299 | 299 |
300 if (result) { | 300 if (result) { |
301 // The mask's top left coord should be pinned to the rounded-out top
left corner of | 301 // The mask's top left coord should be pinned to the rounded-out top
left corner of |
302 // clipSpace bounds. We determine the mask's position WRT to the ren
der target here. | 302 // clipSpace bounds. We determine the mask's position WRT to the ren
der target here. |
303 SkIRect rtSpaceMaskBounds = clipSpaceIBounds; | 303 SkIRect rtSpaceMaskBounds = clipSpaceIBounds; |
304 rtSpaceMaskBounds.offset(-clipDataIn->fOrigin); | 304 rtSpaceMaskBounds.offset(-clipDataIn->fOrigin); |
305 are->set(fGpu->drawState()); | 305 are->set(fClipTarget->drawState()); |
306 setup_drawstate_aaclip(fGpu, result, rtSpaceMaskBounds); | 306 setup_drawstate_aaclip(fClipTarget, result, rtSpaceMaskBounds); |
307 this->setDrawStateStencil(ars); | 307 this->setDrawStateStencil(ars); |
308 return true; | 308 return true; |
309 } | 309 } |
310 // if alpha clip mask creation fails fall through to the non-AA code pat
hs | 310 // if alpha clip mask creation fails fall through to the non-AA code pat
hs |
311 } | 311 } |
312 #endif // GR_AA_CLIP | 312 #endif // GR_AA_CLIP |
313 | 313 |
314 // Either a hard (stencil buffer) clip was explicitly requested or an anti-a
liased clip couldn't | 314 // Either a hard (stencil buffer) clip was explicitly requested or an anti-a
liased clip couldn't |
315 // be created. In either case, free up the texture in the anti-aliased mask
cache. | 315 // be created. In either case, free up the texture in the anti-aliased mask
cache. |
316 // TODO: this may require more investigation. Ganesh performs a lot of utili
ty draws (e.g., | 316 // TODO: this may require more investigation. Ganesh performs a lot of utili
ty draws (e.g., |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
377 break; | 377 break; |
378 } | 378 } |
379 } | 379 } |
380 | 380 |
381 } | 381 } |
382 | 382 |
383 //////////////////////////////////////////////////////////////////////////////// | 383 //////////////////////////////////////////////////////////////////////////////// |
384 bool GrClipMaskManager::drawElement(GrTexture* target, | 384 bool GrClipMaskManager::drawElement(GrTexture* target, |
385 const SkClipStack::Element* element, | 385 const SkClipStack::Element* element, |
386 GrPathRenderer* pr) { | 386 GrPathRenderer* pr) { |
387 GrDrawState* drawState = fGpu->drawState(); | 387 GrDrawState* drawState = fClipTarget->drawState(); |
388 | 388 |
389 drawState->setRenderTarget(target->asRenderTarget()); | 389 drawState->setRenderTarget(target->asRenderTarget()); |
390 | 390 |
391 // TODO: Draw rrects directly here. | 391 // TODO: Draw rrects directly here. |
392 switch (element->getType()) { | 392 switch (element->getType()) { |
393 case Element::kEmpty_Type: | 393 case Element::kEmpty_Type: |
394 SkDEBUGFAIL("Should never get here with an empty element."); | 394 SkDEBUGFAIL("Should never get here with an empty element."); |
395 break; | 395 break; |
396 case Element::kRect_Type: | 396 case Element::kRect_Type: |
397 // TODO: Do rects directly to the accumulator using a aa-rect GrProc
essor that covers | 397 // TODO: Do rects directly to the accumulator using a aa-rect GrProc
essor that covers |
398 // the entire mask bounds and writes 0 outside the rect. | 398 // the entire mask bounds and writes 0 outside the rect. |
399 if (element->isAA()) { | 399 if (element->isAA()) { |
400 this->getContext()->getAARectRenderer()->fillAARect(fGpu, | 400 this->getContext()->getAARectRenderer()->fillAARect(fClipTarget, |
401 element->get
Rect(), | 401 element->get
Rect(), |
402 SkMatrix::I(
), | 402 SkMatrix::I(
), |
403 element->get
Rect()); | 403 element->get
Rect()); |
404 } else { | 404 } else { |
405 fGpu->drawSimpleRect(element->getRect()); | 405 fClipTarget->drawSimpleRect(element->getRect()); |
406 } | 406 } |
407 return true; | 407 return true; |
408 default: { | 408 default: { |
409 SkPath path; | 409 SkPath path; |
410 element->asPath(&path); | 410 element->asPath(&path); |
411 path.setIsVolatile(true); | 411 path.setIsVolatile(true); |
412 if (path.isInverseFillType()) { | 412 if (path.isInverseFillType()) { |
413 path.toggleInverseFillType(); | 413 path.toggleInverseFillType(); |
414 } | 414 } |
415 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); | 415 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); |
416 if (NULL == pr) { | 416 if (NULL == pr) { |
417 GrPathRendererChain::DrawType type; | 417 GrPathRendererChain::DrawType type; |
418 type = element->isAA() ? GrPathRendererChain::kColorAntiAlias_Dr
awType : | 418 type = element->isAA() ? GrPathRendererChain::kColorAntiAlias_Dr
awType : |
419 GrPathRendererChain::kColor_DrawType; | 419 GrPathRendererChain::kColor_DrawType; |
420 pr = this->getContext()->getPathRenderer(path, stroke, fGpu, fal
se, type); | 420 pr = this->getContext()->getPathRenderer(path, stroke, fClipTarg
et, false, type); |
421 } | 421 } |
422 if (NULL == pr) { | 422 if (NULL == pr) { |
423 return false; | 423 return false; |
424 } | 424 } |
425 pr->drawPath(path, stroke, fGpu, element->isAA()); | 425 pr->drawPath(path, stroke, fClipTarget, element->isAA()); |
426 break; | 426 break; |
427 } | 427 } |
428 } | 428 } |
429 return true; | 429 return true; |
430 } | 430 } |
431 | 431 |
432 bool GrClipMaskManager::canStencilAndDrawElement(GrTexture* target, | 432 bool GrClipMaskManager::canStencilAndDrawElement(GrTexture* target, |
433 const SkClipStack::Element* ele
ment, | 433 const SkClipStack::Element* ele
ment, |
434 GrPathRenderer** pr) { | 434 GrPathRenderer** pr) { |
435 GrDrawState* drawState = fGpu->drawState(); | 435 GrDrawState* drawState = fClipTarget->drawState(); |
436 drawState->setRenderTarget(target->asRenderTarget()); | 436 drawState->setRenderTarget(target->asRenderTarget()); |
437 | 437 |
438 if (Element::kRect_Type == element->getType()) { | 438 if (Element::kRect_Type == element->getType()) { |
439 return true; | 439 return true; |
440 } else { | 440 } else { |
441 // We shouldn't get here with an empty clip element. | 441 // We shouldn't get here with an empty clip element. |
442 SkASSERT(Element::kEmpty_Type != element->getType()); | 442 SkASSERT(Element::kEmpty_Type != element->getType()); |
443 SkPath path; | 443 SkPath path; |
444 element->asPath(&path); | 444 element->asPath(&path); |
445 if (path.isInverseFillType()) { | 445 if (path.isInverseFillType()) { |
446 path.toggleInverseFillType(); | 446 path.toggleInverseFillType(); |
447 } | 447 } |
448 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); | 448 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); |
449 GrPathRendererChain::DrawType type = element->isAA() ? | 449 GrPathRendererChain::DrawType type = element->isAA() ? |
450 GrPathRendererChain::kStencilAndColorAntiAlias_DrawType : | 450 GrPathRendererChain::kStencilAndColorAntiAlias_DrawType : |
451 GrPathRendererChain::kStencilAndColor_DrawType; | 451 GrPathRendererChain::kStencilAndColor_DrawType; |
452 *pr = this->getContext()->getPathRenderer(path, stroke, fGpu, false, typ
e); | 452 *pr = this->getContext()->getPathRenderer(path, stroke, fClipTarget, fal
se, type); |
453 return SkToBool(*pr); | 453 return SkToBool(*pr); |
454 } | 454 } |
455 } | 455 } |
456 | 456 |
457 void GrClipMaskManager::mergeMask(GrTexture* dstMask, | 457 void GrClipMaskManager::mergeMask(GrTexture* dstMask, |
458 GrTexture* srcMask, | 458 GrTexture* srcMask, |
459 SkRegion::Op op, | 459 SkRegion::Op op, |
460 const SkIRect& dstBound, | 460 const SkIRect& dstBound, |
461 const SkIRect& srcBound) { | 461 const SkIRect& srcBound) { |
462 GrDrawState::AutoViewMatrixRestore avmr; | 462 GrDrawState::AutoViewMatrixRestore avmr; |
463 GrDrawState* drawState = fGpu->drawState(); | 463 GrDrawState* drawState = fClipTarget->drawState(); |
464 SkAssertResult(avmr.setIdentity(drawState)); | 464 SkAssertResult(avmr.setIdentity(drawState)); |
465 GrDrawState::AutoRestoreEffects are(drawState); | 465 GrDrawState::AutoRestoreEffects are(drawState); |
466 | 466 |
467 drawState->setRenderTarget(dstMask->asRenderTarget()); | 467 drawState->setRenderTarget(dstMask->asRenderTarget()); |
468 | 468 |
469 setup_boolean_blendcoeffs(drawState, op); | 469 setup_boolean_blendcoeffs(drawState, op); |
470 | 470 |
471 SkMatrix sampleM; | 471 SkMatrix sampleM; |
472 sampleM.setIDiv(srcMask->width(), srcMask->height()); | 472 sampleM.setIDiv(srcMask->width(), srcMask->height()); |
473 | 473 |
474 drawState->addColorProcessor( | 474 drawState->addColorProcessor( |
475 GrTextureDomainEffect::Create(srcMask, | 475 GrTextureDomainEffect::Create(srcMask, |
476 sampleM, | 476 sampleM, |
477 GrTextureDomain::MakeTexelDomain(srcMask,
srcBound), | 477 GrTextureDomain::MakeTexelDomain(srcMask,
srcBound), |
478 GrTextureDomain::kDecal_Mode, | 478 GrTextureDomain::kDecal_Mode, |
479 GrTextureParams::kNone_FilterMode))->unref
(); | 479 GrTextureParams::kNone_FilterMode))->unref
(); |
480 fGpu->drawSimpleRect(SkRect::Make(dstBound)); | 480 fClipTarget->drawSimpleRect(SkRect::Make(dstBound)); |
481 } | 481 } |
482 | 482 |
483 GrTexture* GrClipMaskManager::createTempMask(int width, int height) { | 483 GrTexture* GrClipMaskManager::createTempMask(int width, int height) { |
484 GrSurfaceDesc desc; | 484 GrSurfaceDesc desc; |
485 desc.fFlags = kRenderTarget_GrSurfaceFlag|kNoStencil_GrSurfaceFlag; | 485 desc.fFlags = kRenderTarget_GrSurfaceFlag|kNoStencil_GrSurfaceFlag; |
486 desc.fWidth = width; | 486 desc.fWidth = width; |
487 desc.fHeight = height; | 487 desc.fHeight = height; |
488 desc.fConfig = kAlpha_8_GrPixelConfig; | 488 desc.fConfig = kAlpha_8_GrPixelConfig; |
489 | 489 |
490 return fGpu->getContext()->refScratchTexture(desc, GrContext::kApprox_Scratc
hTexMatch); | 490 return this->getContext()->refScratchTexture(desc, GrContext::kApprox_Scratc
hTexMatch); |
491 } | 491 } |
492 | 492 |
493 //////////////////////////////////////////////////////////////////////////////// | 493 //////////////////////////////////////////////////////////////////////////////// |
494 // Return the texture currently in the cache if it exists. Otherwise, return NUL
L | 494 // Return the texture currently in the cache if it exists. Otherwise, return NUL
L |
495 GrTexture* GrClipMaskManager::getCachedMaskTexture(int32_t elementsGenID, | 495 GrTexture* GrClipMaskManager::getCachedMaskTexture(int32_t elementsGenID, |
496 const SkIRect& clipSpaceIBoun
ds) { | 496 const SkIRect& clipSpaceIBoun
ds) { |
497 bool cached = fAACache.canReuse(elementsGenID, clipSpaceIBounds); | 497 bool cached = fAACache.canReuse(elementsGenID, clipSpaceIBounds); |
498 if (!cached) { | 498 if (!cached) { |
499 return NULL; | 499 return NULL; |
500 } | 500 } |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
553 SkIntToScalar(-clipSpaceIBounds.fLeft), | 553 SkIntToScalar(-clipSpaceIBounds.fLeft), |
554 SkIntToScalar(-clipSpaceIBounds.fTop) | 554 SkIntToScalar(-clipSpaceIBounds.fTop) |
555 }; | 555 }; |
556 // The texture may be larger than necessary, this rect represents the part o
f the texture | 556 // The texture may be larger than necessary, this rect represents the part o
f the texture |
557 // we populate with a rasterization of the clip. | 557 // we populate with a rasterization of the clip. |
558 SkIRect maskSpaceIBounds = SkIRect::MakeWH(clipSpaceIBounds.width(), clipSpa
ceIBounds.height()); | 558 SkIRect maskSpaceIBounds = SkIRect::MakeWH(clipSpaceIBounds.width(), clipSpa
ceIBounds.height()); |
559 | 559 |
560 // Set the matrix so that rendered clip elements are transformed to mask spa
ce from clip space. | 560 // Set the matrix so that rendered clip elements are transformed to mask spa
ce from clip space. |
561 SkMatrix translate; | 561 SkMatrix translate; |
562 translate.setTranslate(clipToMaskOffset); | 562 translate.setTranslate(clipToMaskOffset); |
563 GrDrawTarget::AutoGeometryAndStatePush agasp(fGpu, GrDrawTarget::kReset_ASRI
nit, &translate); | 563 GrDrawTarget::AutoGeometryAndStatePush agasp(fClipTarget, GrDrawTarget::kRes
et_ASRInit, |
| 564 &translate); |
564 | 565 |
565 GrDrawState* drawState = fGpu->drawState(); | 566 GrDrawState* drawState = fClipTarget->drawState(); |
566 | 567 |
567 // We're drawing a coverage mask and want coverage to be run through the ble
nd function. | 568 // We're drawing a coverage mask and want coverage to be run through the ble
nd function. |
568 drawState->enableState(GrDrawState::kCoverageDrawing_StateBit); | 569 drawState->enableState(GrDrawState::kCoverageDrawing_StateBit); |
569 | 570 |
570 // The scratch texture that we are drawing into can be substantially larger
than the mask. Only | 571 // The scratch texture that we are drawing into can be substantially larger
than the mask. Only |
571 // clear the part that we care about. | 572 // clear the part that we care about. |
572 fGpu->clear(&maskSpaceIBounds, | 573 fClipTarget->clear(&maskSpaceIBounds, |
573 GrReducedClip::kAllIn_InitialState == initialState ? 0xffffffff
: 0x00000000, | 574 GrReducedClip::kAllIn_InitialState == initialState ? 0xff
ffffff : 0x00000000, |
574 true, | 575 true, |
575 result->asRenderTarget()); | 576 result->asRenderTarget()); |
576 | 577 |
577 // When we use the stencil in the below loop it is important to have this cl
ip installed. | 578 // When we use the stencil in the below loop it is important to have this cl
ip installed. |
578 // The second pass that zeros the stencil buffer renders the rect maskSpaceI
Bounds so the first | 579 // The second pass that zeros the stencil buffer renders the rect maskSpaceI
Bounds so the first |
579 // pass must not set values outside of this bounds or stencil values outside
the rect won't be | 580 // pass must not set values outside of this bounds or stencil values outside
the rect won't be |
580 // cleared. | 581 // cleared. |
581 GrDrawTarget::AutoClipRestore acr(fGpu, maskSpaceIBounds); | 582 GrDrawTarget::AutoClipRestore acr(fClipTarget, maskSpaceIBounds); |
582 drawState->enableState(GrDrawState::kClip_StateBit); | 583 drawState->enableState(GrDrawState::kClip_StateBit); |
583 | 584 |
584 SkAutoTUnref<GrTexture> temp; | 585 SkAutoTUnref<GrTexture> temp; |
585 // walk through each clip element and perform its set op | 586 // walk through each clip element and perform its set op |
586 for (GrReducedClip::ElementList::Iter iter = elements.headIter(); iter.get()
; iter.next()) { | 587 for (GrReducedClip::ElementList::Iter iter = elements.headIter(); iter.get()
; iter.next()) { |
587 const Element* element = iter.get(); | 588 const Element* element = iter.get(); |
588 SkRegion::Op op = element->getOp(); | 589 SkRegion::Op op = element->getOp(); |
589 bool invert = element->isInverseFilled(); | 590 bool invert = element->isInverseFilled(); |
590 | 591 |
591 if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDiffere
nce_Op == op) { | 592 if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDiffere
nce_Op == op) { |
(...skipping 18 matching lines...) Expand all Loading... |
610 if (!temp) { | 611 if (!temp) { |
611 temp.reset(this->createTempMask(maskSpaceIBounds.fRight, | 612 temp.reset(this->createTempMask(maskSpaceIBounds.fRight, |
612 maskSpaceIBounds.fBottom)); | 613 maskSpaceIBounds.fBottom)); |
613 if (!temp) { | 614 if (!temp) { |
614 fAACache.reset(); | 615 fAACache.reset(); |
615 return NULL; | 616 return NULL; |
616 } | 617 } |
617 } | 618 } |
618 dst = temp; | 619 dst = temp; |
619 // clear the temp target and set blend to replace | 620 // clear the temp target and set blend to replace |
620 fGpu->clear(&maskSpaceElementIBounds, | 621 fClipTarget->clear(&maskSpaceElementIBounds, |
621 invert ? 0xffffffff : 0x00000000, | 622 invert ? 0xffffffff : 0x00000000, |
622 true, | 623 true, |
623 dst->asRenderTarget()); | 624 dst->asRenderTarget()); |
624 setup_boolean_blendcoeffs(drawState, SkRegion::kReplace_Op); | 625 setup_boolean_blendcoeffs(drawState, SkRegion::kReplace_Op); |
625 | 626 |
626 } else { | 627 } else { |
627 // draw directly into the result with the stencil set to make th
e pixels affected | 628 // draw directly into the result with the stencil set to make th
e pixels affected |
628 // by the clip shape be non-zero. | 629 // by the clip shape be non-zero. |
629 dst = result; | 630 dst = result; |
630 GR_STATIC_CONST_SAME_STENCIL(kStencilInElement, | 631 GR_STATIC_CONST_SAME_STENCIL(kStencilInElement, |
(...skipping 26 matching lines...) Expand all Loading... |
657 // Draw to the exterior pixels (those with a zero stencil value)
. | 658 // Draw to the exterior pixels (those with a zero stencil value)
. |
658 drawState->setAlpha(invert ? 0xff : 0x00); | 659 drawState->setAlpha(invert ? 0xff : 0x00); |
659 GR_STATIC_CONST_SAME_STENCIL(kDrawOutsideElement, | 660 GR_STATIC_CONST_SAME_STENCIL(kDrawOutsideElement, |
660 kZero_StencilOp, | 661 kZero_StencilOp, |
661 kZero_StencilOp, | 662 kZero_StencilOp, |
662 kEqual_StencilFunc, | 663 kEqual_StencilFunc, |
663 0xffff, | 664 0xffff, |
664 0x0000, | 665 0x0000, |
665 0xffff); | 666 0xffff); |
666 drawState->setStencil(kDrawOutsideElement); | 667 drawState->setStencil(kDrawOutsideElement); |
667 fGpu->drawSimpleRect(clipSpaceIBounds); | 668 fClipTarget->drawSimpleRect(clipSpaceIBounds); |
668 drawState->disableStencil(); | 669 drawState->disableStencil(); |
669 } | 670 } |
670 } else { | 671 } else { |
671 // all the remaining ops can just be directly draw into the accumula
tion buffer | 672 // all the remaining ops can just be directly draw into the accumula
tion buffer |
672 drawState->setAlpha(0xff); | 673 drawState->setAlpha(0xff); |
673 setup_boolean_blendcoeffs(drawState, op); | 674 setup_boolean_blendcoeffs(drawState, op); |
674 this->drawElement(result, element); | 675 this->drawElement(result, element); |
675 } | 676 } |
676 } | 677 } |
677 | 678 |
678 fCurrClipMaskType = kAlpha_ClipMaskType; | 679 fCurrClipMaskType = kAlpha_ClipMaskType; |
679 return result; | 680 return result; |
680 } | 681 } |
681 | 682 |
682 //////////////////////////////////////////////////////////////////////////////// | 683 //////////////////////////////////////////////////////////////////////////////// |
683 // Create a 1-bit clip mask in the stencil buffer. 'devClipBounds' are in device | 684 // Create a 1-bit clip mask in the stencil buffer. 'devClipBounds' are in device |
684 // (as opposed to canvas) coordinates | 685 // (as opposed to canvas) coordinates |
685 bool GrClipMaskManager::createStencilClipMask(int32_t elementsGenID, | 686 bool GrClipMaskManager::createStencilClipMask(int32_t elementsGenID, |
686 GrReducedClip::InitialState initia
lState, | 687 GrReducedClip::InitialState initia
lState, |
687 const GrReducedClip::ElementList&
elements, | 688 const GrReducedClip::ElementList&
elements, |
688 const SkIRect& clipSpaceIBounds, | 689 const SkIRect& clipSpaceIBounds, |
689 const SkIPoint& clipSpaceToStencil
Offset) { | 690 const SkIPoint& clipSpaceToStencil
Offset) { |
690 | 691 |
691 SkASSERT(kNone_ClipMaskType == fCurrClipMaskType); | 692 SkASSERT(kNone_ClipMaskType == fCurrClipMaskType); |
692 | 693 |
693 GrDrawState* drawState = fGpu->drawState(); | 694 GrDrawState* drawState = fClipTarget->drawState(); |
694 SkASSERT(drawState->isClipState()); | 695 SkASSERT(drawState->isClipState()); |
695 | 696 |
696 GrRenderTarget* rt = drawState->getRenderTarget(); | 697 GrRenderTarget* rt = drawState->getRenderTarget(); |
697 SkASSERT(rt); | 698 SkASSERT(rt); |
698 | 699 |
699 // TODO: dynamically attach a SB when needed. | 700 // TODO: dynamically attach a SB when needed. |
700 GrStencilBuffer* stencilBuffer = rt->getStencilBuffer(); | 701 GrStencilBuffer* stencilBuffer = rt->getStencilBuffer(); |
701 if (NULL == stencilBuffer) { | 702 if (NULL == stencilBuffer) { |
702 return false; | 703 return false; |
703 } | 704 } |
704 | 705 |
705 if (stencilBuffer->mustRenderClip(elementsGenID, clipSpaceIBounds, clipSpace
ToStencilOffset)) { | 706 if (stencilBuffer->mustRenderClip(elementsGenID, clipSpaceIBounds, clipSpace
ToStencilOffset)) { |
706 stencilBuffer->setLastClip(elementsGenID, clipSpaceIBounds, clipSpaceToS
tencilOffset); | 707 stencilBuffer->setLastClip(elementsGenID, clipSpaceIBounds, clipSpaceToS
tencilOffset); |
707 | 708 |
708 // Set the matrix so that rendered clip elements are transformed from cl
ip to stencil space. | 709 // Set the matrix so that rendered clip elements are transformed from cl
ip to stencil space. |
709 SkVector translate = { | 710 SkVector translate = { |
710 SkIntToScalar(clipSpaceToStencilOffset.fX), | 711 SkIntToScalar(clipSpaceToStencilOffset.fX), |
711 SkIntToScalar(clipSpaceToStencilOffset.fY) | 712 SkIntToScalar(clipSpaceToStencilOffset.fY) |
712 }; | 713 }; |
713 SkMatrix matrix; | 714 SkMatrix matrix; |
714 matrix.setTranslate(translate); | 715 matrix.setTranslate(translate); |
715 GrDrawTarget::AutoGeometryAndStatePush agasp(fGpu, GrDrawTarget::kReset_
ASRInit, &matrix); | 716 GrDrawTarget::AutoGeometryAndStatePush agasp(fClipTarget, GrDrawTarget::
kReset_ASRInit, |
716 drawState = fGpu->drawState(); | 717 &matrix); |
| 718 drawState = fClipTarget->drawState(); |
717 | 719 |
718 drawState->setRenderTarget(rt); | 720 drawState->setRenderTarget(rt); |
719 | 721 |
720 // We set the current clip to the bounds so that our recursive draws are
scissored to them. | 722 // We set the current clip to the bounds so that our recursive draws are
scissored to them. |
721 SkIRect stencilSpaceIBounds(clipSpaceIBounds); | 723 SkIRect stencilSpaceIBounds(clipSpaceIBounds); |
722 stencilSpaceIBounds.offset(clipSpaceToStencilOffset); | 724 stencilSpaceIBounds.offset(clipSpaceToStencilOffset); |
723 GrDrawTarget::AutoClipRestore acr(fGpu, stencilSpaceIBounds); | 725 GrDrawTarget::AutoClipRestore acr(fClipTarget, stencilSpaceIBounds); |
724 drawState->enableState(GrDrawState::kClip_StateBit); | 726 drawState->enableState(GrDrawState::kClip_StateBit); |
725 | 727 |
726 #if !VISUALIZE_COMPLEX_CLIP | 728 #if !VISUALIZE_COMPLEX_CLIP |
727 drawState->enableState(GrDrawState::kNoColorWrites_StateBit); | 729 drawState->enableState(GrDrawState::kNoColorWrites_StateBit); |
728 #endif | 730 #endif |
729 | 731 |
730 int clipBit = stencilBuffer->bits(); | 732 int clipBit = stencilBuffer->bits(); |
731 SkASSERT((clipBit <= 16) && "Ganesh only handles 16b or smaller stencil
buffers"); | 733 SkASSERT((clipBit <= 16) && "Ganesh only handles 16b or smaller stencil
buffers"); |
732 clipBit = (1 << (clipBit-1)); | 734 clipBit = (1 << (clipBit-1)); |
733 | 735 |
734 fGpu->clearStencilClip(stencilSpaceIBounds, | 736 fClipTarget->clearStencilClip(stencilSpaceIBounds, |
735 GrReducedClip::kAllIn_InitialState == initialStat
e, | 737 GrReducedClip::kAllIn_InitialState == init
ialState, |
736 rt); | 738 rt); |
737 | 739 |
738 // walk through each clip element and perform its set op | 740 // walk through each clip element and perform its set op |
739 // with the existing clip. | 741 // with the existing clip. |
740 for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.ge
t(); iter.next()) { | 742 for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.ge
t(); iter.next()) { |
741 const Element* element = iter.get(); | 743 const Element* element = iter.get(); |
742 bool fillInverted = false; | 744 bool fillInverted = false; |
743 // enabled at bottom of loop | 745 // enabled at bottom of loop |
744 drawState->disableState(GrGpu::kModifyStencilClip_StateBit); | 746 drawState->disableState(kModifyStencilClip_StateBit); |
745 // if the target is MSAA then we want MSAA enabled when the clip is
soft | 747 // if the target is MSAA then we want MSAA enabled when the clip is
soft |
746 if (rt->isMultisampled()) { | 748 if (rt->isMultisampled()) { |
747 drawState->setState(GrDrawState::kHWAntialias_StateBit, element-
>isAA()); | 749 drawState->setState(GrDrawState::kHWAntialias_StateBit, element-
>isAA()); |
748 } | 750 } |
749 | 751 |
750 // This will be used to determine whether the clip shape can be rend
ered into the | 752 // This will be used to determine whether the clip shape can be rend
ered into the |
751 // stencil with arbitrary stencil settings. | 753 // stencil with arbitrary stencil settings. |
752 GrPathRenderer::StencilSupport stencilSupport; | 754 GrPathRenderer::StencilSupport stencilSupport; |
753 | 755 |
754 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); | 756 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); |
755 | 757 |
756 SkRegion::Op op = element->getOp(); | 758 SkRegion::Op op = element->getOp(); |
757 | 759 |
758 GrPathRenderer* pr = NULL; | 760 GrPathRenderer* pr = NULL; |
759 SkPath clipPath; | 761 SkPath clipPath; |
760 if (Element::kRect_Type == element->getType()) { | 762 if (Element::kRect_Type == element->getType()) { |
761 stencilSupport = GrPathRenderer::kNoRestriction_StencilSupport; | 763 stencilSupport = GrPathRenderer::kNoRestriction_StencilSupport; |
762 fillInverted = false; | 764 fillInverted = false; |
763 } else { | 765 } else { |
764 element->asPath(&clipPath); | 766 element->asPath(&clipPath); |
765 fillInverted = clipPath.isInverseFillType(); | 767 fillInverted = clipPath.isInverseFillType(); |
766 if (fillInverted) { | 768 if (fillInverted) { |
767 clipPath.toggleInverseFillType(); | 769 clipPath.toggleInverseFillType(); |
768 } | 770 } |
769 pr = this->getContext()->getPathRenderer(clipPath, | 771 pr = this->getContext()->getPathRenderer(clipPath, |
770 stroke, | 772 stroke, |
771 fGpu, | 773 fClipTarget, |
772 false, | 774 false, |
773 GrPathRendererChain::kS
tencilOnly_DrawType, | 775 GrPathRendererChain::kS
tencilOnly_DrawType, |
774 &stencilSupport); | 776 &stencilSupport); |
775 if (NULL == pr) { | 777 if (NULL == pr) { |
776 return false; | 778 return false; |
777 } | 779 } |
778 } | 780 } |
779 | 781 |
780 int passes; | 782 int passes; |
781 GrStencilSettings stencilSettings[GrStencilSettings::kMaxStencilClip
Passes]; | 783 GrStencilSettings stencilSettings[GrStencilSettings::kMaxStencilClip
Passes]; |
(...skipping 16 matching lines...) Expand all Loading... |
798 GR_STATIC_CONST_SAME_STENCIL(gDrawToStencil, | 800 GR_STATIC_CONST_SAME_STENCIL(gDrawToStencil, |
799 kIncClamp_StencilOp, | 801 kIncClamp_StencilOp, |
800 kIncClamp_StencilOp, | 802 kIncClamp_StencilOp, |
801 kAlways_StencilFunc, | 803 kAlways_StencilFunc, |
802 0xffff, | 804 0xffff, |
803 0x0000, | 805 0x0000, |
804 0xffff); | 806 0xffff); |
805 SET_RANDOM_COLOR | 807 SET_RANDOM_COLOR |
806 if (Element::kRect_Type == element->getType()) { | 808 if (Element::kRect_Type == element->getType()) { |
807 *drawState->stencil() = gDrawToStencil; | 809 *drawState->stencil() = gDrawToStencil; |
808 fGpu->drawSimpleRect(element->getRect()); | 810 fClipTarget->drawSimpleRect(element->getRect()); |
809 } else { | 811 } else { |
810 if (!clipPath.isEmpty()) { | 812 if (!clipPath.isEmpty()) { |
811 if (canRenderDirectToStencil) { | 813 if (canRenderDirectToStencil) { |
812 *drawState->stencil() = gDrawToStencil; | 814 *drawState->stencil() = gDrawToStencil; |
813 pr->drawPath(clipPath, stroke, fGpu, false); | 815 pr->drawPath(clipPath, stroke, fClipTarget, false); |
814 } else { | 816 } else { |
815 pr->stencilPath(clipPath, stroke, fGpu); | 817 pr->stencilPath(clipPath, stroke, fClipTarget); |
816 } | 818 } |
817 } | 819 } |
818 } | 820 } |
819 } | 821 } |
820 | 822 |
821 // now we modify the clip bit by rendering either the clip | 823 // now we modify the clip bit by rendering either the clip |
822 // element directly or a bounding rect of the entire clip. | 824 // element directly or a bounding rect of the entire clip. |
823 drawState->enableState(GrGpu::kModifyStencilClip_StateBit); | 825 drawState->enableState(kModifyStencilClip_StateBit); |
824 for (int p = 0; p < passes; ++p) { | 826 for (int p = 0; p < passes; ++p) { |
825 *drawState->stencil() = stencilSettings[p]; | 827 *drawState->stencil() = stencilSettings[p]; |
826 if (canDrawDirectToClip) { | 828 if (canDrawDirectToClip) { |
827 if (Element::kRect_Type == element->getType()) { | 829 if (Element::kRect_Type == element->getType()) { |
828 SET_RANDOM_COLOR | 830 SET_RANDOM_COLOR |
829 fGpu->drawSimpleRect(element->getRect()); | 831 fClipTarget->drawSimpleRect(element->getRect()); |
830 } else { | 832 } else { |
831 SET_RANDOM_COLOR | 833 SET_RANDOM_COLOR |
832 pr->drawPath(clipPath, stroke, fGpu, false); | 834 pr->drawPath(clipPath, stroke, fClipTarget, false); |
833 } | 835 } |
834 } else { | 836 } else { |
835 SET_RANDOM_COLOR | 837 SET_RANDOM_COLOR |
836 // The view matrix is setup to do clip space -> stencil spac
e translation, so | 838 // The view matrix is setup to do clip space -> stencil spac
e translation, so |
837 // draw rect in clip space. | 839 // draw rect in clip space. |
838 fGpu->drawSimpleRect(SkRect::Make(clipSpaceIBounds)); | 840 fClipTarget->drawSimpleRect(SkRect::Make(clipSpaceIBounds)); |
839 } | 841 } |
840 } | 842 } |
841 } | 843 } |
842 } | 844 } |
843 // set this last because recursive draws may overwrite it back to kNone. | 845 // set this last because recursive draws may overwrite it back to kNone. |
844 SkASSERT(kNone_ClipMaskType == fCurrClipMaskType); | 846 SkASSERT(kNone_ClipMaskType == fCurrClipMaskType); |
845 fCurrClipMaskType = kStencil_ClipMaskType; | 847 fCurrClipMaskType = kStencil_ClipMaskType; |
846 return true; | 848 return true; |
847 } | 849 } |
848 | 850 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
898 return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings); | 900 return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings); |
899 } | 901 } |
900 } | 902 } |
901 | 903 |
902 void GrClipMaskManager::setDrawStateStencil(GrDrawState::AutoRestoreStencil* ars
) { | 904 void GrClipMaskManager::setDrawStateStencil(GrDrawState::AutoRestoreStencil* ars
) { |
903 // We make two copies of the StencilSettings here (except in the early | 905 // We make two copies of the StencilSettings here (except in the early |
904 // exit scenario. One copy from draw state to the stack var. Then another | 906 // exit scenario. One copy from draw state to the stack var. Then another |
905 // from the stack var to the gpu. We could make this class hold a ptr to | 907 // from the stack var to the gpu. We could make this class hold a ptr to |
906 // GrGpu's fStencilSettings and eliminate the stack copy here. | 908 // GrGpu's fStencilSettings and eliminate the stack copy here. |
907 | 909 |
908 const GrDrawState& drawState = fGpu->getDrawState(); | 910 const GrDrawState& drawState = fClipTarget->getDrawState(); |
909 | 911 |
910 // use stencil for clipping if clipping is enabled and the clip | 912 // use stencil for clipping if clipping is enabled and the clip |
911 // has been written into the stencil. | 913 // has been written into the stencil. |
912 GrClipMaskManager::StencilClipMode clipMode; | 914 GrClipMaskManager::StencilClipMode clipMode; |
913 if (this->isClipInStencil() && drawState.isClipState()) { | 915 if (this->isClipInStencil() && drawState.isClipState()) { |
914 clipMode = GrClipMaskManager::kRespectClip_StencilClipMode; | 916 clipMode = GrClipMaskManager::kRespectClip_StencilClipMode; |
915 // We can't be modifying the clip and respecting it at the same time. | 917 // We can't be modifying the clip and respecting it at the same time. |
916 SkASSERT(!drawState.isStateFlagEnabled( | 918 SkASSERT(!drawState.isStateFlagEnabled(kModifyStencilClip_StateBit)); |
917 GrGpu::kModifyStencilClip_StateBit)); | 919 } else if (drawState.isStateFlagEnabled(kModifyStencilClip_StateBit)) { |
918 } else if (drawState.isStateFlagEnabled( | |
919 GrGpu::kModifyStencilClip_StateBit)) { | |
920 clipMode = GrClipMaskManager::kModifyClip_StencilClipMode; | 920 clipMode = GrClipMaskManager::kModifyClip_StencilClipMode; |
921 } else { | 921 } else { |
922 clipMode = GrClipMaskManager::kIgnoreClip_StencilClipMode; | 922 clipMode = GrClipMaskManager::kIgnoreClip_StencilClipMode; |
923 } | 923 } |
924 | 924 |
925 GrStencilSettings settings; | 925 GrStencilSettings settings; |
926 // The GrGpu client may not be using the stencil buffer but we may need to | 926 // The GrGpu client may not be using the stencil buffer but we may need to |
927 // enable it in order to respect a stencil clip. | 927 // enable it in order to respect a stencil clip. |
928 if (drawState.getStencil().isDisabled()) { | 928 if (drawState.getStencil().isDisabled()) { |
929 if (GrClipMaskManager::kRespectClip_StencilClipMode == clipMode) { | 929 if (GrClipMaskManager::kRespectClip_StencilClipMode == clipMode) { |
930 settings = basic_apply_stencil_clip_settings(); | 930 settings = basic_apply_stencil_clip_settings(); |
931 } else { | 931 } else { |
932 return; | 932 return; |
933 } | 933 } |
934 } else { | 934 } else { |
935 settings = drawState.getStencil(); | 935 settings = drawState.getStencil(); |
936 } | 936 } |
937 | 937 |
938 // TODO: dynamically attach a stencil buffer | 938 // TODO: dynamically attach a stencil buffer |
939 int stencilBits = 0; | 939 int stencilBits = 0; |
940 GrStencilBuffer* stencilBuffer = drawState.getRenderTarget()->getStencilBuff
er(); | 940 GrStencilBuffer* stencilBuffer = drawState.getRenderTarget()->getStencilBuff
er(); |
941 if (stencilBuffer) { | 941 if (stencilBuffer) { |
942 stencilBits = stencilBuffer->bits(); | 942 stencilBits = stencilBuffer->bits(); |
943 } | 943 } |
944 | 944 |
945 SkASSERT(fGpu->caps()->stencilWrapOpsSupport() || !settings.usesWrapOp()); | 945 SkASSERT(fClipTarget->caps()->stencilWrapOpsSupport() || !settings.usesWrapO
p()); |
946 SkASSERT(fGpu->caps()->twoSidedStencilSupport() || !settings.isTwoSided()); | 946 SkASSERT(fClipTarget->caps()->twoSidedStencilSupport() || !settings.isTwoSid
ed()); |
947 this->adjustStencilParams(&settings, clipMode, stencilBits); | 947 this->adjustStencilParams(&settings, clipMode, stencilBits); |
948 ars->set(fGpu->drawState()); | 948 ars->set(fClipTarget->drawState()); |
949 fGpu->drawState()->setStencil(settings); | 949 fClipTarget->drawState()->setStencil(settings); |
950 } | 950 } |
951 | 951 |
952 void GrClipMaskManager::adjustStencilParams(GrStencilSettings* settings, | 952 void GrClipMaskManager::adjustStencilParams(GrStencilSettings* settings, |
953 StencilClipMode mode, | 953 StencilClipMode mode, |
954 int stencilBitCnt) { | 954 int stencilBitCnt) { |
955 SkASSERT(stencilBitCnt > 0); | 955 SkASSERT(stencilBitCnt > 0); |
956 | 956 |
957 if (kModifyClip_StencilClipMode == mode) { | 957 if (kModifyClip_StencilClipMode == mode) { |
958 // We assume that this clip manager itself is drawing to the GrGpu and | 958 // We assume that this clip manager itself is drawing to the GrGpu and |
959 // has already setup the correct values. | 959 // has already setup the correct values. |
960 return; | 960 return; |
961 } | 961 } |
962 | 962 |
963 unsigned int clipBit = (1 << (stencilBitCnt - 1)); | 963 unsigned int clipBit = (1 << (stencilBitCnt - 1)); |
964 unsigned int userBits = clipBit - 1; | 964 unsigned int userBits = clipBit - 1; |
965 | 965 |
966 GrStencilSettings::Face face = GrStencilSettings::kFront_Face; | 966 GrStencilSettings::Face face = GrStencilSettings::kFront_Face; |
967 bool twoSided = fGpu->caps()->twoSidedStencilSupport(); | 967 bool twoSided = fClipTarget->caps()->twoSidedStencilSupport(); |
968 | 968 |
969 bool finished = false; | 969 bool finished = false; |
970 while (!finished) { | 970 while (!finished) { |
971 GrStencilFunc func = settings->func(face); | 971 GrStencilFunc func = settings->func(face); |
972 uint16_t writeMask = settings->writeMask(face); | 972 uint16_t writeMask = settings->writeMask(face); |
973 uint16_t funcMask = settings->funcMask(face); | 973 uint16_t funcMask = settings->funcMask(face); |
974 uint16_t funcRef = settings->funcRef(face); | 974 uint16_t funcRef = settings->funcRef(face); |
975 | 975 |
976 SkASSERT((unsigned) func < kStencilFuncCount); | 976 SkASSERT((unsigned) func < kStencilFuncCount); |
977 | 977 |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1102 | 1102 |
1103 fCurrClipMaskType = kAlpha_ClipMaskType; | 1103 fCurrClipMaskType = kAlpha_ClipMaskType; |
1104 return result; | 1104 return result; |
1105 } | 1105 } |
1106 | 1106 |
1107 //////////////////////////////////////////////////////////////////////////////// | 1107 //////////////////////////////////////////////////////////////////////////////// |
1108 void GrClipMaskManager::purgeResources() { | 1108 void GrClipMaskManager::purgeResources() { |
1109 fAACache.purgeResources(); | 1109 fAACache.purgeResources(); |
1110 } | 1110 } |
1111 | 1111 |
1112 void GrClipMaskManager::setGpu(GrGpu* gpu) { | 1112 void GrClipMaskManager::setClipTarget(GrClipTarget* clipTarget) { |
1113 fGpu = gpu; | 1113 fClipTarget = clipTarget; |
1114 fAACache.setContext(gpu->getContext()); | 1114 fAACache.setContext(clipTarget->getContext()); |
1115 } | 1115 } |
1116 | 1116 |
1117 void GrClipMaskManager::adjustPathStencilParams(GrStencilSettings* settings) { | 1117 void GrClipMaskManager::adjustPathStencilParams(GrStencilSettings* settings) { |
1118 const GrDrawState& drawState = fGpu->getDrawState(); | 1118 const GrDrawState& drawState = fClipTarget->getDrawState(); |
1119 GrClipMaskManager::StencilClipMode clipMode; | 1119 GrClipMaskManager::StencilClipMode clipMode; |
1120 if (this->isClipInStencil() && drawState.isClipState()) { | 1120 if (this->isClipInStencil() && drawState.isClipState()) { |
1121 clipMode = GrClipMaskManager::kRespectClip_StencilClipMode; | 1121 clipMode = GrClipMaskManager::kRespectClip_StencilClipMode; |
1122 // We can't be modifying the clip and respecting it at the same time. | 1122 // We can't be modifying the clip and respecting it at the same time. |
1123 SkASSERT(!drawState.isStateFlagEnabled( | 1123 SkASSERT(!drawState.isStateFlagEnabled(kModifyStencilClip_StateBit)); |
1124 GrGpu::kModifyStencilClip_StateBit)); | 1124 } else if (drawState.isStateFlagEnabled(kModifyStencilClip_StateBit)) { |
1125 } else if (drawState.isStateFlagEnabled( | |
1126 GrGpu::kModifyStencilClip_StateBit)) { | |
1127 clipMode = GrClipMaskManager::kModifyClip_StencilClipMode; | 1125 clipMode = GrClipMaskManager::kModifyClip_StencilClipMode; |
1128 } else { | 1126 } else { |
1129 clipMode = GrClipMaskManager::kIgnoreClip_StencilClipMode; | 1127 clipMode = GrClipMaskManager::kIgnoreClip_StencilClipMode; |
1130 } | 1128 } |
1131 | 1129 |
1132 // TODO: dynamically attach a stencil buffer | 1130 // TODO: dynamically attach a stencil buffer |
1133 int stencilBits = 0; | 1131 int stencilBits = 0; |
1134 GrStencilBuffer* stencilBuffer = | 1132 GrStencilBuffer* stencilBuffer = drawState.getRenderTarget()->getStencilBuff
er(); |
1135 drawState.getRenderTarget()->getStencilBuffer(); | |
1136 if (stencilBuffer) { | 1133 if (stencilBuffer) { |
1137 stencilBits = stencilBuffer->bits(); | 1134 stencilBits = stencilBuffer->bits(); |
1138 this->adjustStencilParams(settings, clipMode, stencilBits); | 1135 this->adjustStencilParams(settings, clipMode, stencilBits); |
1139 } | 1136 } |
1140 } | 1137 } |
OLD | NEW |