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