OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "GrClipMaskManager.h" | 8 #include "GrClipMaskManager.h" |
9 #include "GrCaps.h" | 9 #include "GrCaps.h" |
10 #include "GrDrawingManager.h" | 10 #include "GrDrawingManager.h" |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
55 const SkRect& rect) { | 55 const SkRect& rect) { |
56 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateNonAAFill(color, v
iewMatrix, rect, | 56 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateNonAAFill(color, v
iewMatrix, rect, |
57 nullptr,
nullptr)); | 57 nullptr,
nullptr)); |
58 drawTarget->drawBatch(pipelineBuilder, batch); | 58 drawTarget->drawBatch(pipelineBuilder, batch); |
59 } | 59 } |
60 | 60 |
61 // Does the path in 'element' require SW rendering? If so, return true (and, | 61 // Does the path in 'element' require SW rendering? If so, return true (and, |
62 // optionally, set 'prOut' to NULL. If not, return false (and, optionally, set | 62 // optionally, set 'prOut' to NULL. If not, return false (and, optionally, set |
63 // 'prOut' to the non-SW path renderer that will do the job). | 63 // 'prOut' to the non-SW path renderer that will do the job). |
64 bool GrClipMaskManager::PathNeedsSWRenderer(GrContext* context, | 64 bool GrClipMaskManager::PathNeedsSWRenderer(GrContext* context, |
65 bool isStencilDisabled, | 65 bool hasUserStencilSettings, |
66 const GrRenderTarget* rt, | 66 const GrRenderTarget* rt, |
67 const SkMatrix& viewMatrix, | 67 const SkMatrix& viewMatrix, |
68 const Element* element, | 68 const Element* element, |
69 GrPathRenderer** prOut, | 69 GrPathRenderer** prOut, |
70 bool needsStencil) { | 70 bool needsStencil) { |
71 if (Element::kRect_Type == element->getType()) { | 71 if (Element::kRect_Type == element->getType()) { |
72 // rects can always be drawn directly w/o using the software path | 72 // rects can always be drawn directly w/o using the software path |
73 // TODO: skip rrects once we're drawing them directly. | 73 // TODO: skip rrects once we're drawing them directly. |
74 if (prOut) { | 74 if (prOut) { |
75 *prOut = nullptr; | 75 *prOut = nullptr; |
(...skipping 22 matching lines...) Expand all Loading... |
98 ? GrPathRendererChain::kColorAntiAlias_DrawType | 98 ? GrPathRendererChain::kColorAntiAlias_DrawType |
99 : GrPathRendererChain::kColor_DrawType; | 99 : GrPathRendererChain::kColor_DrawType; |
100 } | 100 } |
101 | 101 |
102 GrPathRenderer::CanDrawPathArgs canDrawArgs; | 102 GrPathRenderer::CanDrawPathArgs canDrawArgs; |
103 canDrawArgs.fShaderCaps = context->caps()->shaderCaps(); | 103 canDrawArgs.fShaderCaps = context->caps()->shaderCaps(); |
104 canDrawArgs.fViewMatrix = &viewMatrix; | 104 canDrawArgs.fViewMatrix = &viewMatrix; |
105 canDrawArgs.fPath = &path; | 105 canDrawArgs.fPath = &path; |
106 canDrawArgs.fStroke = &stroke; | 106 canDrawArgs.fStroke = &stroke; |
107 canDrawArgs.fAntiAlias = element->isAA(); | 107 canDrawArgs.fAntiAlias = element->isAA(); |
108 canDrawArgs.fIsStencilDisabled = isStencilDisabled; | 108 canDrawArgs.fHasUserStencilSettings = hasUserStencilSettings; |
109 canDrawArgs.fIsStencilBufferMSAA = rt->isStencilBufferMultisampled(); | 109 canDrawArgs.fIsStencilBufferMSAA = rt->isStencilBufferMultisampled(); |
110 | 110 |
111 // the 'false' parameter disallows use of the SW path renderer | 111 // the 'false' parameter disallows use of the SW path renderer |
112 GrPathRenderer* pr = context->drawingManager()->getPathRenderer(canDrawA
rgs, false, type); | 112 GrPathRenderer* pr = context->drawingManager()->getPathRenderer(canDrawA
rgs, false, type); |
113 if (prOut) { | 113 if (prOut) { |
114 *prOut = pr; | 114 *prOut = pr; |
115 } | 115 } |
116 return SkToBool(!pr); | 116 return SkToBool(!pr); |
117 } | 117 } |
118 } | 118 } |
119 | 119 |
120 // Determines whether it is possible to draw the element to both the stencil buf
fer and the | 120 // Determines whether it is possible to draw the element to both the stencil buf
fer and the |
121 // alpha mask simultaneously. If so and the element is a path a compatible path
renderer is | 121 // alpha mask simultaneously. If so and the element is a path a compatible path
renderer is |
122 // also returned. | 122 // also returned. |
123 GrPathRenderer* GrClipMaskManager::GetPathRenderer(GrContext* context, | 123 GrPathRenderer* GrClipMaskManager::GetPathRenderer(GrContext* context, |
124 GrTexture* texture, | 124 GrTexture* texture, |
125 const SkMatrix& viewMatrix, | 125 const SkMatrix& viewMatrix, |
126 const SkClipStack::Element* e
lement) { | 126 const SkClipStack::Element* e
lement) { |
127 GrPathRenderer* pr; | 127 GrPathRenderer* pr; |
128 static const bool kNeedsStencil = true; | 128 constexpr bool kNeedsStencil = true; |
129 static const bool kStencilIsDisabled = true; | 129 constexpr bool kHasUserStencilSettings = false; |
130 PathNeedsSWRenderer(context, | 130 PathNeedsSWRenderer(context, |
131 kStencilIsDisabled, | 131 kHasUserStencilSettings, |
132 texture->asRenderTarget(), | 132 texture->asRenderTarget(), |
133 viewMatrix, | 133 viewMatrix, |
134 element, | 134 element, |
135 &pr, | 135 &pr, |
136 kNeedsStencil); | 136 kNeedsStencil); |
137 return pr; | 137 return pr; |
138 } | 138 } |
139 | 139 |
140 GrClipMaskManager::GrClipMaskManager(GrDrawTarget* drawTarget, bool debugClipBat
chToBounds) | 140 GrClipMaskManager::GrClipMaskManager(GrDrawTarget* drawTarget, bool debugClipBat
chToBounds) |
141 : fDrawTarget(drawTarget) | 141 : fDrawTarget(drawTarget) |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
173 const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMa
skOffset.fY); | 173 const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMa
skOffset.fY); |
174 | 174 |
175 for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.get();
iter.next()) { | 175 for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.get();
iter.next()) { |
176 const Element* element = iter.get(); | 176 const Element* element = iter.get(); |
177 | 177 |
178 SkRegion::Op op = element->getOp(); | 178 SkRegion::Op op = element->getOp(); |
179 bool invert = element->isInverseFilled(); | 179 bool invert = element->isInverseFilled(); |
180 bool needsStencil = invert || | 180 bool needsStencil = invert || |
181 SkRegion::kIntersect_Op == op || SkRegion::kReverseD
ifference_Op == op; | 181 SkRegion::kIntersect_Op == op || SkRegion::kReverseD
ifference_Op == op; |
182 | 182 |
183 if (PathNeedsSWRenderer(context, pipelineBuilder.getStencil().isDisabled
(), | 183 if (PathNeedsSWRenderer(context, pipelineBuilder.hasUserStencilSettings(
), |
184 rt, translate, element, nullptr, needsStencil))
{ | 184 rt, translate, element, nullptr, needsStencil))
{ |
185 return true; | 185 return true; |
186 } | 186 } |
187 } | 187 } |
188 return false; | 188 return false; |
189 } | 189 } |
190 | 190 |
191 bool GrClipMaskManager::getAnalyticClipProcessor(const GrReducedClip::ElementLis
t& elements, | 191 bool GrClipMaskManager::getAnalyticClipProcessor(const GrReducedClip::ElementLis
t& elements, |
192 bool abortIfAA, | 192 bool abortIfAA, |
193 SkVector& clipToRTOffset, | 193 SkVector& clipToRTOffset, |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
311 *out = GrClip(intersect); | 311 *out = GrClip(intersect); |
312 } else { | 312 } else { |
313 *out = clip; | 313 *out = clip; |
314 } | 314 } |
315 break; | 315 break; |
316 } | 316 } |
317 } | 317 } |
318 } | 318 } |
319 | 319 |
320 bool GrClipMaskManager::setupScissorClip(const GrPipelineBuilder& pipelineBuilde
r, | 320 bool GrClipMaskManager::setupScissorClip(const GrPipelineBuilder& pipelineBuilde
r, |
321 GrPipelineBuilder::AutoRestoreStencil*
ars, | |
322 const SkIRect& clipScissor, | 321 const SkIRect& clipScissor, |
323 const SkRect* devBounds, | 322 const SkRect* devBounds, |
324 GrAppliedClip* out) { | 323 GrAppliedClip* out) { |
325 if (kRespectClip_StencilClipMode == fClipMode) { | 324 SkASSERT(kModifyClip_StencilClipMode != fClipMode); // TODO: Remove fClipMod
e. |
326 fClipMode = kIgnoreClip_StencilClipMode; | 325 fClipMode = kIgnoreClip_StencilClipMode; |
327 } | |
328 | 326 |
329 GrRenderTarget* rt = pipelineBuilder.getRenderTarget(); | 327 GrRenderTarget* rt = pipelineBuilder.getRenderTarget(); |
330 | 328 |
331 SkIRect clipSpaceRTIBounds = SkIRect::MakeWH(rt->width(), rt->height()); | 329 SkIRect clipSpaceRTIBounds = SkIRect::MakeWH(rt->width(), rt->height()); |
332 SkIRect devBoundsScissor; | 330 SkIRect devBoundsScissor; |
333 const SkIRect* scissor = &clipScissor; | 331 const SkIRect* scissor = &clipScissor; |
334 bool doDevBoundsClip = fDebugClipBatchToBounds && devBounds; | 332 bool doDevBoundsClip = fDebugClipBatchToBounds && devBounds; |
335 if (doDevBoundsClip) { | 333 if (doDevBoundsClip) { |
336 devBounds->roundOut(&devBoundsScissor); | 334 devBounds->roundOut(&devBoundsScissor); |
337 if (devBoundsScissor.intersect(clipScissor)) { | 335 if (devBoundsScissor.intersect(clipScissor)) { |
338 scissor = &devBoundsScissor; | 336 scissor = &devBoundsScissor; |
339 } | 337 } |
340 } | 338 } |
341 | 339 |
342 if (scissor->contains(clipSpaceRTIBounds)) { | 340 if (scissor->contains(clipSpaceRTIBounds)) { |
343 // This counts as wide open | 341 // This counts as wide open |
344 this->setPipelineBuilderStencil(pipelineBuilder, ars); | |
345 return true; | 342 return true; |
346 } | 343 } |
347 | 344 |
348 if (clipSpaceRTIBounds.intersect(*scissor)) { | 345 if (clipSpaceRTIBounds.intersect(*scissor)) { |
349 out->fScissorState.set(clipSpaceRTIBounds); | 346 out->fScissorState.set(clipSpaceRTIBounds); |
350 this->setPipelineBuilderStencil(pipelineBuilder, ars); | |
351 return true; | 347 return true; |
352 } | 348 } |
353 return false; | 349 return false; |
354 } | 350 } |
355 | 351 |
356 //////////////////////////////////////////////////////////////////////////////// | 352 //////////////////////////////////////////////////////////////////////////////// |
357 // sort out what kind of clip mask needs to be created: alpha, stencil, | 353 // sort out what kind of clip mask needs to be created: alpha, stencil, |
358 // scissor, or entirely software | 354 // scissor, or entirely software |
359 bool GrClipMaskManager::setupClipping(const GrPipelineBuilder& pipelineBuilder, | 355 bool GrClipMaskManager::setupClipping(const GrPipelineBuilder& pipelineBuilder, |
360 GrPipelineBuilder::AutoRestoreStencil* ars
, | |
361 const SkRect* devBounds, | 356 const SkRect* devBounds, |
362 GrAppliedClip* out) { | 357 GrAppliedClip* out) { |
363 if (kRespectClip_StencilClipMode == fClipMode) { | 358 if (kRespectClip_StencilClipMode == fClipMode) { |
364 fClipMode = kIgnoreClip_StencilClipMode; | 359 fClipMode = kIgnoreClip_StencilClipMode; |
365 } | 360 } |
366 | 361 |
367 GrReducedClip::ElementList elements; | 362 GrReducedClip::ElementList elements; |
368 int32_t genID = 0; | 363 int32_t genID = 0; |
369 GrReducedClip::InitialState initialState = GrReducedClip::kAllIn_InitialStat
e; | 364 GrReducedClip::InitialState initialState = GrReducedClip::kAllIn_InitialStat
e; |
370 SkIRect clipSpaceIBounds; | 365 SkIRect clipSpaceIBounds; |
371 bool requiresAA = false; | 366 bool requiresAA = false; |
372 GrRenderTarget* rt = pipelineBuilder.getRenderTarget(); | 367 GrRenderTarget* rt = pipelineBuilder.getRenderTarget(); |
373 | 368 |
374 // GrDrawTarget should have filtered this for us | 369 // GrDrawTarget should have filtered this for us |
375 SkASSERT(rt); | 370 SkASSERT(rt); |
376 | 371 |
377 SkIRect clipSpaceRTIBounds = SkIRect::MakeWH(rt->width(), rt->height()); | 372 SkIRect clipSpaceRTIBounds = SkIRect::MakeWH(rt->width(), rt->height()); |
378 GrClip devBoundsClip; | 373 GrClip devBoundsClip; |
379 bool doDevBoundsClip = fDebugClipBatchToBounds && devBounds; | 374 bool doDevBoundsClip = fDebugClipBatchToBounds && devBounds; |
380 if (doDevBoundsClip) { | 375 if (doDevBoundsClip) { |
381 add_rect_to_clip(pipelineBuilder.clip(), *devBounds, &devBoundsClip); | 376 add_rect_to_clip(pipelineBuilder.clip(), *devBounds, &devBoundsClip); |
382 } | 377 } |
383 const GrClip& clip = doDevBoundsClip ? devBoundsClip : pipelineBuilder.clip(
); | 378 const GrClip& clip = doDevBoundsClip ? devBoundsClip : pipelineBuilder.clip(
); |
384 | 379 |
385 if (clip.isWideOpen(clipSpaceRTIBounds)) { | 380 if (clip.isWideOpen(clipSpaceRTIBounds)) { |
386 this->setPipelineBuilderStencil(pipelineBuilder, ars); | |
387 return true; | 381 return true; |
388 } | 382 } |
389 | 383 |
390 // The clip mask manager always draws with a single IRect so we special case
that logic here | 384 // The clip mask manager always draws with a single IRect so we special case
that logic here |
391 // Image filters just use a rect, so we also special case that logic | 385 // Image filters just use a rect, so we also special case that logic |
392 switch (clip.clipType()) { | 386 switch (clip.clipType()) { |
393 case GrClip::kWideOpen_ClipType: | 387 case GrClip::kWideOpen_ClipType: |
394 SkFAIL("Should have caught this with clip.isWideOpen()"); | 388 SkFAIL("Should have caught this with clip.isWideOpen()"); |
395 return true; | 389 return true; |
396 case GrClip::kIRect_ClipType: { | 390 case GrClip::kIRect_ClipType: { |
397 SkIRect scissor = clip.irect(); | 391 SkIRect scissor = clip.irect(); |
398 if (scissor.intersect(clipSpaceRTIBounds)) { | 392 if (scissor.intersect(clipSpaceRTIBounds)) { |
399 out->fScissorState.set(scissor); | 393 out->fScissorState.set(scissor); |
400 this->setPipelineBuilderStencil(pipelineBuilder, ars); | 394 out->fHasStencilClip = kIgnoreClip_StencilClipMode != fClipMode; |
401 return true; | 395 return true; |
402 } | 396 } |
403 return false; | 397 return false; |
404 } | 398 } |
405 case GrClip::kClipStack_ClipType: { | 399 case GrClip::kClipStack_ClipType: { |
406 clipSpaceRTIBounds.offset(clip.origin()); | 400 clipSpaceRTIBounds.offset(clip.origin()); |
407 SkIRect clipSpaceReduceQueryBounds; | 401 SkIRect clipSpaceReduceQueryBounds; |
408 #define DISABLE_DEV_BOUNDS_FOR_CLIP_REDUCTION 0 | 402 #define DISABLE_DEV_BOUNDS_FOR_CLIP_REDUCTION 0 |
409 if (devBounds && !DISABLE_DEV_BOUNDS_FOR_CLIP_REDUCTION) { | 403 if (devBounds && !DISABLE_DEV_BOUNDS_FOR_CLIP_REDUCTION) { |
410 SkIRect devIBounds = devBounds->roundOut(); | 404 SkIRect devIBounds = devBounds->roundOut(); |
411 devIBounds.offset(clip.origin()); | 405 devIBounds.offset(clip.origin()); |
412 if (!clipSpaceReduceQueryBounds.intersect(clipSpaceRTIBounds, de
vIBounds)) { | 406 if (!clipSpaceReduceQueryBounds.intersect(clipSpaceRTIBounds, de
vIBounds)) { |
413 return false; | 407 return false; |
414 } | 408 } |
415 } else { | 409 } else { |
416 clipSpaceReduceQueryBounds = clipSpaceRTIBounds; | 410 clipSpaceReduceQueryBounds = clipSpaceRTIBounds; |
417 } | 411 } |
418 GrReducedClip::ReduceClipStack(*clip.clipStack(), | 412 GrReducedClip::ReduceClipStack(*clip.clipStack(), |
419 clipSpaceReduceQueryBounds, | 413 clipSpaceReduceQueryBounds, |
420 &elements, | 414 &elements, |
421 &genID, | 415 &genID, |
422 &initialState, | 416 &initialState, |
423 &clipSpaceIBounds, | 417 &clipSpaceIBounds, |
424 &requiresAA); | 418 &requiresAA); |
425 if (elements.isEmpty()) { | 419 if (elements.isEmpty()) { |
426 if (GrReducedClip::kAllIn_InitialState == initialState) { | 420 if (GrReducedClip::kAllIn_InitialState == initialState) { |
427 if (clipSpaceIBounds == clipSpaceRTIBounds) { | 421 if (clipSpaceIBounds == clipSpaceRTIBounds) { |
428 this->setPipelineBuilderStencil(pipelineBuilder, ars); | |
429 return true; | 422 return true; |
430 } | 423 } |
431 } else { | 424 } else { |
432 return false; | 425 return false; |
433 } | 426 } |
434 } | 427 } |
435 } break; | 428 } break; |
436 } | 429 } |
437 | 430 |
| 431 SkASSERT(kIgnoreClip_StencilClipMode == fClipMode); // TODO: Remove fClipMod
e. |
| 432 |
438 // An element count of 4 was chosen because of the common pattern in Blink o
f: | 433 // An element count of 4 was chosen because of the common pattern in Blink o
f: |
439 // isect RR | 434 // isect RR |
440 // diff RR | 435 // diff RR |
441 // isect convex_poly | 436 // isect convex_poly |
442 // isect convex_poly | 437 // isect convex_poly |
443 // when drawing rounded div borders. This could probably be tuned based on a | 438 // when drawing rounded div borders. This could probably be tuned based on a |
444 // configuration's relative costs of switching RTs to generate a mask vs | 439 // configuration's relative costs of switching RTs to generate a mask vs |
445 // longer shaders. | 440 // longer shaders. |
446 if (elements.count() <= kMaxAnalyticElements) { | 441 if (elements.count() <= kMaxAnalyticElements) { |
447 SkVector clipToRTOffset = { SkIntToScalar(-clip.origin().fX), | 442 SkVector clipToRTOffset = { SkIntToScalar(-clip.origin().fX), |
448 SkIntToScalar(-clip.origin().fY) }; | 443 SkIntToScalar(-clip.origin().fY) }; |
449 // When there are multiple samples we want to do per-sample clipping, no
t compute a | 444 // When there are multiple samples we want to do per-sample clipping, no
t compute a |
450 // fractional pixel coverage. | 445 // fractional pixel coverage. |
451 bool disallowAnalyticAA = rt->isStencilBufferMultisampled(); | 446 bool disallowAnalyticAA = rt->isStencilBufferMultisampled(); |
452 if (disallowAnalyticAA && !rt->numColorSamples()) { | 447 if (disallowAnalyticAA && !rt->numColorSamples()) { |
453 // With a single color sample, any coverage info is lost from color
once it hits the | 448 // With a single color sample, any coverage info is lost from color
once it hits the |
454 // color buffer anyway, so we may as well use coverage AA if nothing
else in the pipe | 449 // color buffer anyway, so we may as well use coverage AA if nothing
else in the pipe |
455 // is multisampled. | 450 // is multisampled. |
456 disallowAnalyticAA = pipelineBuilder.isHWAntialias() || | 451 disallowAnalyticAA = pipelineBuilder.isHWAntialias() || |
457 !pipelineBuilder.getStencil().isDisabled(); | 452 pipelineBuilder.hasUserStencilSettings(); |
458 } | 453 } |
459 const GrFragmentProcessor* clipFP = nullptr; | 454 const GrFragmentProcessor* clipFP = nullptr; |
460 if (elements.isEmpty() || | 455 if (elements.isEmpty() || |
461 (requiresAA && | 456 (requiresAA && |
462 this->getAnalyticClipProcessor(elements, disallowAnalyticAA, clipTo
RTOffset, devBounds, | 457 this->getAnalyticClipProcessor(elements, disallowAnalyticAA, clipTo
RTOffset, devBounds, |
463 &clipFP))) { | 458 &clipFP))) { |
464 SkIRect scissorSpaceIBounds(clipSpaceIBounds); | 459 SkIRect scissorSpaceIBounds(clipSpaceIBounds); |
465 scissorSpaceIBounds.offset(-clip.origin()); | 460 scissorSpaceIBounds.offset(-clip.origin()); |
466 if (nullptr == devBounds || | 461 if (nullptr == devBounds || |
467 !SkRect::Make(scissorSpaceIBounds).contains(*devBounds)) { | 462 !SkRect::Make(scissorSpaceIBounds).contains(*devBounds)) { |
468 out->fScissorState.set(scissorSpaceIBounds); | 463 out->fScissorState.set(scissorSpaceIBounds); |
469 } | 464 } |
470 this->setPipelineBuilderStencil(pipelineBuilder, ars); | |
471 out->fClipCoverageFP.reset(clipFP); | 465 out->fClipCoverageFP.reset(clipFP); |
472 return true; | 466 return true; |
473 } | 467 } |
474 } | 468 } |
475 | 469 |
476 // If the stencil buffer is multisampled we can use it to do everything. | 470 // If the stencil buffer is multisampled we can use it to do everything. |
477 if (!rt->isStencilBufferMultisampled() && requiresAA) { | 471 if (!rt->isStencilBufferMultisampled() && requiresAA) { |
478 SkAutoTUnref<GrTexture> result; | 472 SkAutoTUnref<GrTexture> result; |
479 | 473 |
480 // The top-left of the mask corresponds to the top-left corner of the bo
unds. | 474 // The top-left of the mask corresponds to the top-left corner of the bo
unds. |
(...skipping 21 matching lines...) Expand all Loading... |
502 // If createAlphaClipMask fails it means UseSWOnlyPath has a bug | 496 // If createAlphaClipMask fails it means UseSWOnlyPath has a bug |
503 SkASSERT(result); | 497 SkASSERT(result); |
504 } | 498 } |
505 | 499 |
506 if (result) { | 500 if (result) { |
507 // The mask's top left coord should be pinned to the rounded-out top
left corner of | 501 // The mask's top left coord should be pinned to the rounded-out top
left corner of |
508 // clipSpace bounds. We determine the mask's position WRT to the ren
der target here. | 502 // clipSpace bounds. We determine the mask's position WRT to the ren
der target here. |
509 SkIRect rtSpaceMaskBounds = clipSpaceIBounds; | 503 SkIRect rtSpaceMaskBounds = clipSpaceIBounds; |
510 rtSpaceMaskBounds.offset(-clip.origin()); | 504 rtSpaceMaskBounds.offset(-clip.origin()); |
511 out->fClipCoverageFP.reset(create_fp_for_mask(result, rtSpaceMaskBou
nds)); | 505 out->fClipCoverageFP.reset(create_fp_for_mask(result, rtSpaceMaskBou
nds)); |
512 this->setPipelineBuilderStencil(pipelineBuilder, ars); | |
513 return true; | 506 return true; |
514 } | 507 } |
515 // if alpha clip mask creation fails fall through to the non-AA code pat
hs | 508 // if alpha clip mask creation fails fall through to the non-AA code pat
hs |
516 } | 509 } |
517 | 510 |
518 // use the stencil clip if we can't represent the clip as a rectangle. | 511 // use the stencil clip if we can't represent the clip as a rectangle. |
519 SkIPoint clipSpaceToStencilSpaceOffset = -clip.origin(); | 512 SkIPoint clipSpaceToStencilSpaceOffset = -clip.origin(); |
520 this->createStencilClipMask(rt, | 513 this->createStencilClipMask(rt, |
521 genID, | 514 genID, |
522 initialState, | 515 initialState, |
523 elements, | 516 elements, |
524 clipSpaceIBounds, | 517 clipSpaceIBounds, |
525 clipSpaceToStencilSpaceOffset); | 518 clipSpaceToStencilSpaceOffset); |
526 | 519 |
527 // This must occur after createStencilClipMask. That function may change the
scissor. Also, it | 520 // This must occur after createStencilClipMask. That function may change the
scissor. Also, it |
528 // only guarantees that the stencil mask is correct within the bounds it was
passed, so we must | 521 // only guarantees that the stencil mask is correct within the bounds it was
passed, so we must |
529 // use both stencil and scissor test to the bounds for the final draw. | 522 // use both stencil and scissor test to the bounds for the final draw. |
530 SkIRect scissorSpaceIBounds(clipSpaceIBounds); | 523 SkIRect scissorSpaceIBounds(clipSpaceIBounds); |
531 scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset); | 524 scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset); |
532 out->fScissorState.set(scissorSpaceIBounds); | 525 out->fScissorState.set(scissorSpaceIBounds); |
533 this->setPipelineBuilderStencil(pipelineBuilder, ars); | 526 SkASSERT(kRespectClip_StencilClipMode == fClipMode); // TODO: Remove fClipMo
de. |
| 527 out->fHasStencilClip = true; |
534 return true; | 528 return true; |
535 } | 529 } |
536 | 530 |
537 static bool stencil_element(GrDrawContext* dc, | 531 static bool stencil_element(GrDrawContext* dc, |
538 const SkIRect* scissorRect, | 532 const SkIRect* scissorRect, |
539 const GrStencilSettings& ss, | 533 const GrUserStencilSettings* ss, |
540 const SkMatrix& viewMatrix, | 534 const SkMatrix& viewMatrix, |
541 const SkClipStack::Element* element) { | 535 const SkClipStack::Element* element) { |
542 | 536 |
543 // TODO: Draw rrects directly here. | 537 // TODO: Draw rrects directly here. |
544 switch (element->getType()) { | 538 switch (element->getType()) { |
545 case Element::kEmpty_Type: | 539 case Element::kEmpty_Type: |
546 SkDEBUGFAIL("Should never get here with an empty element."); | 540 SkDEBUGFAIL("Should never get here with an empty element."); |
547 break; | 541 break; |
548 case Element::kRect_Type: | 542 case Element::kRect_Type: |
549 return dc->drawContextPriv().drawAndStencilRect(scissorRect, ss, | 543 return dc->drawContextPriv().drawAndStencilRect(scissorRect, ss, |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
675 if (Element::kRect_Type != element->getType() && !pr) { | 669 if (Element::kRect_Type != element->getType() && !pr) { |
676 // UseSWOnlyPath should now filter out all cases where gpu-side
mask merging would | 670 // UseSWOnlyPath should now filter out all cases where gpu-side
mask merging would |
677 // be performed (i.e., pr would be NULL for a non-rect path). | 671 // be performed (i.e., pr would be NULL for a non-rect path). |
678 // See https://bug.skia.org/4519 for rationale and details. | 672 // See https://bug.skia.org/4519 for rationale and details. |
679 SkASSERT(0); | 673 SkASSERT(0); |
680 } | 674 } |
681 #endif | 675 #endif |
682 | 676 |
683 // draw directly into the result with the stencil set to make the pi
xels affected | 677 // draw directly into the result with the stencil set to make the pi
xels affected |
684 // by the clip shape be non-zero. | 678 // by the clip shape be non-zero. |
685 static constexpr GrStencilSettings kStencilInElement( | 679 static constexpr GrUserStencilSettings kStencilInElement( |
686 kReplace_StencilOp, | 680 GrUserStencilSettings::StaticInit< |
687 kReplace_StencilOp, | 681 0xffff, |
688 kAlways_StencilFunc, | 682 GrUserStencilTest::kAlways, |
689 0xffff, | 683 0xffff, |
690 0xffff, | 684 GrUserStencilOp::kReplace, |
691 0xffff); | 685 GrUserStencilOp::kReplace, |
692 if (!stencil_element(dc.get(), &maskSpaceIBounds, kStencilInElement, | 686 0xffff>() |
| 687 ); |
| 688 if (!stencil_element(dc.get(), &maskSpaceIBounds, &kStencilInElement
, |
693 translate, element)) { | 689 translate, element)) { |
694 texture->resourcePriv().removeUniqueKey(); | 690 texture->resourcePriv().removeUniqueKey(); |
695 return nullptr; | 691 return nullptr; |
696 } | 692 } |
697 | 693 |
698 // Draw to the exterior pixels (those with a zero stencil value). | 694 // Draw to the exterior pixels (those with a zero stencil value). |
699 static constexpr GrStencilSettings kDrawOutsideElement( | 695 static constexpr GrUserStencilSettings kDrawOutsideElement( |
700 kZero_StencilOp, | 696 GrUserStencilSettings::StaticInit< |
701 kZero_StencilOp, | 697 0x0000, |
702 kEqual_StencilFunc, | 698 GrUserStencilTest::kEqual, |
703 0xffff, | 699 0xffff, |
704 0x0000, | 700 GrUserStencilOp::kZero, |
705 0xffff); | 701 GrUserStencilOp::kZero, |
706 if (!dc->drawContextPriv().drawAndStencilRect(&maskSpaceIBounds, kDr
awOutsideElement, | 702 0xffff>() |
| 703 ); |
| 704 if (!dc->drawContextPriv().drawAndStencilRect(&maskSpaceIBounds, &kD
rawOutsideElement, |
707 op, !invert, false, | 705 op, !invert, false, |
708 translate, | 706 translate, |
709 SkRect::Make(clipSpace
IBounds))) { | 707 SkRect::Make(clipSpace
IBounds))) { |
710 texture->resourcePriv().removeUniqueKey(); | 708 texture->resourcePriv().removeUniqueKey(); |
711 return nullptr; | 709 return nullptr; |
712 } | 710 } |
713 } else { | 711 } else { |
714 // all the remaining ops can just be directly draw into the accumula
tion buffer | 712 // all the remaining ops can just be directly draw into the accumula
tion buffer |
715 GrPaint paint; | 713 GrPaint paint; |
716 paint.setAntiAlias(element->isAA()); | 714 paint.setAntiAlias(element->isAA()); |
(...skipping 30 matching lines...) Expand all Loading... |
747 SkIntToScalar(clipSpaceToStencilOffset.fY) | 745 SkIntToScalar(clipSpaceToStencilOffset.fY) |
748 }; | 746 }; |
749 SkMatrix viewMatrix; | 747 SkMatrix viewMatrix; |
750 viewMatrix.setTranslate(translate); | 748 viewMatrix.setTranslate(translate); |
751 | 749 |
752 // We set the current clip to the bounds so that our recursive draws are
scissored to them. | 750 // We set the current clip to the bounds so that our recursive draws are
scissored to them. |
753 SkIRect stencilSpaceIBounds(clipSpaceIBounds); | 751 SkIRect stencilSpaceIBounds(clipSpaceIBounds); |
754 stencilSpaceIBounds.offset(clipSpaceToStencilOffset); | 752 stencilSpaceIBounds.offset(clipSpaceToStencilOffset); |
755 GrClip clip(stencilSpaceIBounds); | 753 GrClip clip(stencilSpaceIBounds); |
756 | 754 |
757 int clipBit = stencilAttachment->bits(); | |
758 SkASSERT((clipBit <= 16) && "Ganesh only handles 16b or smaller stencil
buffers"); | |
759 clipBit = (1 << (clipBit-1)); | |
760 | |
761 fDrawTarget->cmmAccess().clearStencilClip(stencilSpaceIBounds, | 755 fDrawTarget->cmmAccess().clearStencilClip(stencilSpaceIBounds, |
762 GrReducedClip::kAllIn_InitialState == initialState, rt); | 756 GrReducedClip::kAllIn_InitialState == initialState, rt); |
763 | 757 |
764 // walk through each clip element and perform its set op | 758 // walk through each clip element and perform its set op |
765 // with the existing clip. | 759 // with the existing clip. |
766 for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.ge
t(); iter.next()) { | 760 for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.ge
t(); iter.next()) { |
767 const Element* element = iter.get(); | 761 const Element* element = iter.get(); |
768 | 762 |
769 GrPipelineBuilder pipelineBuilder; | 763 GrPipelineBuilder pipelineBuilder; |
770 pipelineBuilder.setClip(clip); | 764 pipelineBuilder.setClip(clip); |
(...skipping 22 matching lines...) Expand all Loading... |
793 if (Element::kRect_Type == element->getType()) { | 787 if (Element::kRect_Type == element->getType()) { |
794 stencilSupport = GrPathRenderer::kNoRestriction_StencilSupport; | 788 stencilSupport = GrPathRenderer::kNoRestriction_StencilSupport; |
795 fillInverted = false; | 789 fillInverted = false; |
796 } else { | 790 } else { |
797 element->asPath(&clipPath); | 791 element->asPath(&clipPath); |
798 fillInverted = clipPath.isInverseFillType(); | 792 fillInverted = clipPath.isInverseFillType(); |
799 if (fillInverted) { | 793 if (fillInverted) { |
800 clipPath.toggleInverseFillType(); | 794 clipPath.toggleInverseFillType(); |
801 } | 795 } |
802 | 796 |
803 SkASSERT(pipelineBuilder.getStencil().isDisabled()); | 797 SkASSERT(!pipelineBuilder.hasUserStencilSettings()); |
804 | 798 |
805 GrPathRenderer::CanDrawPathArgs canDrawArgs; | 799 GrPathRenderer::CanDrawPathArgs canDrawArgs; |
806 canDrawArgs.fShaderCaps = this->getContext()->caps()->shaderCaps
(); | 800 canDrawArgs.fShaderCaps = this->getContext()->caps()->shaderCaps
(); |
807 canDrawArgs.fViewMatrix = &viewMatrix; | 801 canDrawArgs.fViewMatrix = &viewMatrix; |
808 canDrawArgs.fPath = &clipPath; | 802 canDrawArgs.fPath = &clipPath; |
809 canDrawArgs.fStroke = &stroke; | 803 canDrawArgs.fStroke = &stroke; |
810 canDrawArgs.fAntiAlias = false; | 804 canDrawArgs.fAntiAlias = false; |
811 canDrawArgs.fIsStencilDisabled = pipelineBuilder.getStencil().is
Disabled(); | 805 canDrawArgs.fHasUserStencilSettings = pipelineBuilder.hasUserSte
ncilSettings(); |
812 canDrawArgs.fIsStencilBufferMSAA = rt->isStencilBufferMultisampl
ed(); | 806 canDrawArgs.fIsStencilBufferMSAA = rt->isStencilBufferMultisampl
ed(); |
813 | 807 |
814 pr = this->getContext()->drawingManager()->getPathRenderer(canDr
awArgs, false, | 808 pr = this->getContext()->drawingManager()->getPathRenderer(canDr
awArgs, false, |
815 GrPat
hRendererChain::kStencilOnly_DrawType, | 809 GrPat
hRendererChain::kStencilOnly_DrawType, |
816 &sten
cilSupport); | 810 &sten
cilSupport); |
817 if (nullptr == pr) { | 811 if (nullptr == pr) { |
818 return false; | 812 return false; |
819 } | 813 } |
820 } | 814 } |
821 | 815 |
822 int passes; | |
823 GrStencilSettings stencilSettings[GrStencilSettings::kMaxStencilClip
Passes]; | |
824 | |
825 bool canRenderDirectToStencil = | 816 bool canRenderDirectToStencil = |
826 GrPathRenderer::kNoRestriction_StencilSupport == stencilSupport; | 817 GrPathRenderer::kNoRestriction_StencilSupport == stencilSupport; |
827 bool canDrawDirectToClip; // Given the renderer, the element, | 818 bool drawDirectToClip; // Given the renderer, the element, |
828 // fill rule, and set operation can | 819 // fill rule, and set operation should |
829 // we render the element directly to | 820 // we render the element directly to |
830 // stencil bit used for clipping. | 821 // stencil bit used for clipping. |
831 canDrawDirectToClip = GrStencilSettings::GetClipPasses(op, | 822 GrUserStencilSettings const* const* stencilPasses = |
832 canRenderDire
ctToStencil, | 823 GrStencilSettings::GetClipPasses(op, canRenderDirectToStencil, f
illInverted, |
833 clipBit, | 824 &drawDirectToClip); |
834 fillInverted, | |
835 &passes, | |
836 stencilSettin
gs); | |
837 | 825 |
838 // draw the element to the client stencil bits if necessary | 826 // draw the element to the client stencil bits if necessary |
839 if (!canDrawDirectToClip) { | 827 if (!drawDirectToClip) { |
840 static constexpr GrStencilSettings kDrawToStencil( | 828 static constexpr GrUserStencilSettings kDrawToStencil( |
841 kIncClamp_StencilOp, | 829 GrUserStencilSettings::StaticInit< |
842 kIncClamp_StencilOp, | 830 0x0000, |
843 kAlways_StencilFunc, | 831 GrUserStencilTest::kAlways, |
844 0xffff, | 832 0xffff, |
845 0x0000, | 833 GrUserStencilOp::kIncMaybeClamp, |
846 0xffff); | 834 GrUserStencilOp::kIncMaybeClamp, |
| 835 0xffff>() |
| 836 ); |
847 if (Element::kRect_Type == element->getType()) { | 837 if (Element::kRect_Type == element->getType()) { |
848 *pipelineBuilder.stencil() = kDrawToStencil; | 838 pipelineBuilder.setUserStencil(&kDrawToStencil); |
849 | 839 |
850 draw_non_aa_rect(fDrawTarget, pipelineBuilder, GrColor_WHITE
, viewMatrix, | 840 draw_non_aa_rect(fDrawTarget, pipelineBuilder, GrColor_WHITE
, viewMatrix, |
851 element->getRect()); | 841 element->getRect()); |
852 } else { | 842 } else { |
853 if (!clipPath.isEmpty()) { | 843 if (!clipPath.isEmpty()) { |
854 if (canRenderDirectToStencil) { | 844 if (canRenderDirectToStencil) { |
855 *pipelineBuilder.stencil() = kDrawToStencil; | 845 pipelineBuilder.setUserStencil(&kDrawToStencil); |
856 | 846 |
857 GrPathRenderer::DrawPathArgs args; | 847 GrPathRenderer::DrawPathArgs args; |
858 args.fTarget = fDrawTarget; | 848 args.fTarget = fDrawTarget; |
859 args.fResourceProvider = this->getContext()->resourc
eProvider(); | 849 args.fResourceProvider = this->getContext()->resourc
eProvider(); |
860 args.fPipelineBuilder = &pipelineBuilder; | 850 args.fPipelineBuilder = &pipelineBuilder; |
861 args.fColor = GrColor_WHITE; | 851 args.fColor = GrColor_WHITE; |
862 args.fViewMatrix = &viewMatrix; | 852 args.fViewMatrix = &viewMatrix; |
863 args.fPath = &clipPath; | 853 args.fPath = &clipPath; |
864 args.fStroke = &stroke; | 854 args.fStroke = &stroke; |
865 args.fAntiAlias = false; | 855 args.fAntiAlias = false; |
866 args.fGammaCorrect = false; | 856 args.fGammaCorrect = false; |
867 pr->drawPath(args); | 857 pr->drawPath(args); |
868 } else { | 858 } else { |
869 GrPathRenderer::StencilPathArgs args; | 859 GrPathRenderer::StencilPathArgs args; |
870 args.fTarget = fDrawTarget; | 860 args.fTarget = fDrawTarget; |
871 args.fResourceProvider = this->getContext()->resourc
eProvider(); | 861 args.fResourceProvider = this->getContext()->resourc
eProvider(); |
872 args.fPipelineBuilder = &pipelineBuilder; | 862 args.fPipelineBuilder = &pipelineBuilder; |
873 args.fViewMatrix = &viewMatrix; | 863 args.fViewMatrix = &viewMatrix; |
874 args.fPath = &clipPath; | 864 args.fPath = &clipPath; |
875 pr->stencilPath(args); | 865 pr->stencilPath(args); |
876 } | 866 } |
877 } | 867 } |
878 } | 868 } |
879 } | 869 } |
880 | 870 |
881 // now we modify the clip bit by rendering either the clip | 871 // now we modify the clip bit by rendering either the clip |
882 // element directly or a bounding rect of the entire clip. | 872 // element directly or a bounding rect of the entire clip. |
883 fClipMode = kModifyClip_StencilClipMode; | 873 fClipMode = kModifyClip_StencilClipMode; |
884 for (int p = 0; p < passes; ++p) { | 874 for (GrUserStencilSettings const* const* pass = stencilPasses; *pass
; ++pass) { |
885 *pipelineBuilder.stencil() = stencilSettings[p]; | 875 pipelineBuilder.setUserStencil(*pass); |
886 | 876 |
887 if (canDrawDirectToClip) { | 877 if (drawDirectToClip) { |
888 if (Element::kRect_Type == element->getType()) { | 878 if (Element::kRect_Type == element->getType()) { |
889 draw_non_aa_rect(fDrawTarget, pipelineBuilder, GrColor_W
HITE, viewMatrix, | 879 draw_non_aa_rect(fDrawTarget, pipelineBuilder, GrColor_W
HITE, viewMatrix, |
890 element->getRect()); | 880 element->getRect()); |
891 } else { | 881 } else { |
892 GrPathRenderer::DrawPathArgs args; | 882 GrPathRenderer::DrawPathArgs args; |
893 args.fTarget = fDrawTarget; | 883 args.fTarget = fDrawTarget; |
894 args.fResourceProvider = this->getContext()->resourcePro
vider(); | 884 args.fResourceProvider = this->getContext()->resourcePro
vider(); |
895 args.fPipelineBuilder = &pipelineBuilder; | 885 args.fPipelineBuilder = &pipelineBuilder; |
896 args.fColor = GrColor_WHITE; | 886 args.fColor = GrColor_WHITE; |
897 args.fViewMatrix = &viewMatrix; | 887 args.fViewMatrix = &viewMatrix; |
898 args.fPath = &clipPath; | 888 args.fPath = &clipPath; |
899 args.fStroke = &stroke; | 889 args.fStroke = &stroke; |
900 args.fAntiAlias = false; | 890 args.fAntiAlias = false; |
901 args.fGammaCorrect = false; | 891 args.fGammaCorrect = false; |
902 pr->drawPath(args); | 892 pr->drawPath(args); |
903 } | 893 } |
904 } else { | 894 } else { |
905 // The view matrix is setup to do clip space -> stencil spac
e translation, so | 895 // The view matrix is setup to do clip space -> stencil spac
e translation, so |
906 // draw rect in clip space. | 896 // draw rect in clip space. |
907 draw_non_aa_rect(fDrawTarget, pipelineBuilder, GrColor_WHITE
, viewMatrix, | 897 draw_non_aa_rect(fDrawTarget, pipelineBuilder, GrColor_WHITE
, viewMatrix, |
908 SkRect::Make(clipSpaceIBounds)); | 898 SkRect::Make(clipSpaceIBounds)); |
909 } | 899 } |
910 } | 900 } |
911 } | 901 } |
912 } | 902 } |
913 fClipMode = kRespectClip_StencilClipMode; | 903 fClipMode = kRespectClip_StencilClipMode; |
914 return true; | 904 return true; |
915 } | 905 } |
916 | 906 |
917 // mapping of clip-respecting stencil funcs to normal stencil funcs | |
918 // mapping depends on whether stencil-clipping is in effect. | |
919 static const GrStencilFunc | |
920 gSpecialToBasicStencilFunc[2][kClipStencilFuncCnt] = { | |
921 {// Stencil-Clipping is DISABLED, we are effectively always inside the clip | |
922 // In the Clip Funcs | |
923 kAlways_StencilFunc, // kAlwaysIfInClip_StencilFunc | |
924 kEqual_StencilFunc, // kEqualIfInClip_StencilFunc | |
925 kLess_StencilFunc, // kLessIfInClip_StencilFunc | |
926 kLEqual_StencilFunc, // kLEqualIfInClip_StencilFunc | |
927 // Special in the clip func that forces user's ref to be 0. | |
928 kNotEqual_StencilFunc, // kNonZeroIfInClip_StencilFunc | |
929 // make ref 0 and do normal nequal. | |
930 }, | |
931 {// Stencil-Clipping is ENABLED | |
932 // In the Clip Funcs | |
933 kEqual_StencilFunc, // kAlwaysIfInClip_StencilFunc | |
934 // eq stencil clip bit, mask | |
935 // out user bits. | |
936 | |
937 kEqual_StencilFunc, // kEqualIfInClip_StencilFunc | |
938 // add stencil bit to mask and ref | |
939 | |
940 kLess_StencilFunc, // kLessIfInClip_StencilFunc | |
941 kLEqual_StencilFunc, // kLEqualIfInClip_StencilFunc | |
942 // for both of these we can add | |
943 // the clip bit to the mask and | |
944 // ref and compare as normal | |
945 // Special in the clip func that forces user's ref to be 0. | |
946 kLess_StencilFunc, // kNonZeroIfInClip_StencilFunc | |
947 // make ref have only the clip bit set | |
948 // and make comparison be less | |
949 // 10..0 < 1..user_bits.. | |
950 } | |
951 }; | |
952 | |
953 void GrClipMaskManager::setPipelineBuilderStencil(const GrPipelineBuilder& pipel
ineBuilder, | |
954 GrPipelineBuilder::AutoRestore
Stencil* ars) { | |
955 // We make two copies of the StencilSettings here (except in the early | |
956 // exit scenario. One copy from draw state to the stack var. Then another | |
957 // from the stack var to the gpu. We could make this class hold a ptr to | |
958 // GrGpu's fStencilSettings and eliminate the stack copy here. | |
959 | |
960 // use stencil for clipping if clipping is enabled and the clip | |
961 // has been written into the stencil. | |
962 GrStencilSettings settings; | |
963 | |
964 // The GrGpu client may not be using the stencil buffer but we may need to | |
965 // enable it in order to respect a stencil clip. | |
966 if (pipelineBuilder.getStencil().isDisabled()) { | |
967 if (GrClipMaskManager::kRespectClip_StencilClipMode == fClipMode) { | |
968 static constexpr GrStencilSettings kBasicApplyClipSettings( | |
969 kKeep_StencilOp, | |
970 kKeep_StencilOp, | |
971 kAlwaysIfInClip_StencilFunc, | |
972 0x0000, | |
973 0x0000, | |
974 0x0000); | |
975 settings = kBasicApplyClipSettings; | |
976 } else { | |
977 return; | |
978 } | |
979 } else { | |
980 settings = pipelineBuilder.getStencil(); | |
981 } | |
982 | |
983 int stencilBits = 0; | |
984 GrRenderTarget* rt = pipelineBuilder.getRenderTarget(); | |
985 GrStencilAttachment* stencilAttachment = this->resourceProvider()->attachSte
ncilAttachment(rt); | |
986 if (stencilAttachment) { | |
987 stencilBits = stencilAttachment->bits(); | |
988 } | |
989 | |
990 SkASSERT(this->caps()->stencilWrapOpsSupport() || !settings.usesWrapOp()); | |
991 SkASSERT(this->caps()->twoSidedStencilSupport() || !settings.isTwoSided()); | |
992 this->adjustStencilParams(&settings, fClipMode, stencilBits); | |
993 ars->set(&pipelineBuilder); | |
994 ars->setStencil(settings); | |
995 } | |
996 | |
997 void GrClipMaskManager::adjustStencilParams(GrStencilSettings* settings, | |
998 StencilClipMode mode, | |
999 int stencilBitCnt) { | |
1000 SkASSERT(stencilBitCnt > 0); | |
1001 | |
1002 if (kModifyClip_StencilClipMode == mode) { | |
1003 // We assume that this clip manager itself is drawing to the GrGpu and | |
1004 // has already setup the correct values. | |
1005 return; | |
1006 } | |
1007 | |
1008 unsigned int clipBit = (1 << (stencilBitCnt - 1)); | |
1009 unsigned int userBits = clipBit - 1; | |
1010 | |
1011 GrStencilSettings::Face face = GrStencilSettings::kFront_Face; | |
1012 bool twoSided = this->caps()->twoSidedStencilSupport(); | |
1013 | |
1014 bool finished = false; | |
1015 while (!finished) { | |
1016 GrStencilFunc func = settings->func(face); | |
1017 uint16_t writeMask = settings->writeMask(face); | |
1018 uint16_t funcMask = settings->funcMask(face); | |
1019 uint16_t funcRef = settings->funcRef(face); | |
1020 | |
1021 SkASSERT((unsigned) func < kStencilFuncCnt); | |
1022 | |
1023 writeMask &= userBits; | |
1024 | |
1025 if (func >= kBasicStencilFuncCnt) { | |
1026 int respectClip = kRespectClip_StencilClipMode == mode; | |
1027 if (respectClip) { | |
1028 switch (func) { | |
1029 case kAlwaysIfInClip_StencilFunc: | |
1030 funcMask = clipBit; | |
1031 funcRef = clipBit; | |
1032 break; | |
1033 case kEqualIfInClip_StencilFunc: | |
1034 case kLessIfInClip_StencilFunc: | |
1035 case kLEqualIfInClip_StencilFunc: | |
1036 funcMask = (funcMask & userBits) | clipBit; | |
1037 funcRef = (funcRef & userBits) | clipBit; | |
1038 break; | |
1039 case kNonZeroIfInClip_StencilFunc: | |
1040 funcMask = (funcMask & userBits) | clipBit; | |
1041 funcRef = clipBit; | |
1042 break; | |
1043 default: | |
1044 SkFAIL("Unknown stencil func"); | |
1045 } | |
1046 } else { | |
1047 funcMask &= userBits; | |
1048 funcRef &= userBits; | |
1049 } | |
1050 const GrStencilFunc* table = | |
1051 gSpecialToBasicStencilFunc[respectClip]; | |
1052 func = table[func - kBasicStencilFuncCnt]; | |
1053 SkASSERT(func >= 0 && func < kBasicStencilFuncCnt); | |
1054 } else { | |
1055 funcMask &= userBits; | |
1056 funcRef &= userBits; | |
1057 } | |
1058 | |
1059 settings->setFunc(face, func); | |
1060 settings->setWriteMask(face, writeMask); | |
1061 settings->setFuncMask(face, funcMask); | |
1062 settings->setFuncRef(face, funcRef); | |
1063 | |
1064 if (GrStencilSettings::kFront_Face == face) { | |
1065 face = GrStencilSettings::kBack_Face; | |
1066 finished = !twoSided; | |
1067 } else { | |
1068 finished = true; | |
1069 } | |
1070 } | |
1071 if (!twoSided) { | |
1072 settings->copyFrontSettingsToBack(); | |
1073 } | |
1074 } | |
1075 | |
1076 //////////////////////////////////////////////////////////////////////////////// | 907 //////////////////////////////////////////////////////////////////////////////// |
1077 GrTexture* GrClipMaskManager::CreateSoftwareClipMask(GrContext* context, | 908 GrTexture* GrClipMaskManager::CreateSoftwareClipMask(GrContext* context, |
1078 int32_t elementsGenID, | 909 int32_t elementsGenID, |
1079 GrReducedClip::InitialState
initialState, | 910 GrReducedClip::InitialState
initialState, |
1080 const GrReducedClip::Elemen
tList& elements, | 911 const GrReducedClip::Elemen
tList& elements, |
1081 const SkVector& clipToMaskO
ffset, | 912 const SkVector& clipToMaskO
ffset, |
1082 const SkIRect& clipSpaceIBo
unds) { | 913 const SkIRect& clipSpaceIBo
unds) { |
1083 GrUniqueKey key; | 914 GrUniqueKey key; |
1084 GetClipMaskKey(elementsGenID, clipSpaceIBounds, &key); | 915 GetClipMaskKey(elementsGenID, clipSpaceIBounds, &key); |
1085 GrResourceProvider* resourceProvider = context->resourceProvider(); | 916 GrResourceProvider* resourceProvider = context->resourceProvider(); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1143 GrTexture* result = context->resourceProvider()->createApproxTexture(desc, 0
); | 974 GrTexture* result = context->resourceProvider()->createApproxTexture(desc, 0
); |
1144 if (!result) { | 975 if (!result) { |
1145 return nullptr; | 976 return nullptr; |
1146 } | 977 } |
1147 result->resourcePriv().setUniqueKey(key); | 978 result->resourcePriv().setUniqueKey(key); |
1148 | 979 |
1149 helper.toTexture(result); | 980 helper.toTexture(result); |
1150 | 981 |
1151 return result; | 982 return result; |
1152 } | 983 } |
1153 | |
1154 //////////////////////////////////////////////////////////////////////////////// | |
1155 | |
1156 void GrClipMaskManager::adjustPathStencilParams(const GrStencilAttachment* stenc
ilAttachment, | |
1157 GrStencilSettings* settings) { | |
1158 if (stencilAttachment) { | |
1159 int stencilBits = stencilAttachment->bits(); | |
1160 this->adjustStencilParams(settings, fClipMode, stencilBits); | |
1161 } | |
1162 } | |
OLD | NEW |