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