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 "GrAAConvexPathRenderer.h" | 9 #include "GrAAConvexPathRenderer.h" |
10 #include "GrAAHairLinePathRenderer.h" | 10 #include "GrAAHairLinePathRenderer.h" |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
49 mat, | 49 mat, |
50 GrTextureDomain::MakeTexelDomain(result, d omainTexels), | 50 GrTextureDomain::MakeTexelDomain(result, d omainTexels), |
51 GrTextureDomain::kDecal_Mode, | 51 GrTextureDomain::kDecal_Mode, |
52 GrTextureParams::kNone_FilterMode, | 52 GrTextureParams::kNone_FilterMode, |
53 kDevice_GrCoordSet))->unref(); | 53 kDevice_GrCoordSet))->unref(); |
54 } | 54 } |
55 | 55 |
56 bool path_needs_SW_renderer(GrContext* context, | 56 bool path_needs_SW_renderer(GrContext* context, |
57 const GrDrawTarget* gpu, | 57 const GrDrawTarget* gpu, |
58 const GrDrawState* drawState, | 58 const GrDrawState* drawState, |
59 const SkMatrix& viewMatrix, | |
59 const SkPath& origPath, | 60 const SkPath& origPath, |
60 const SkStrokeRec& stroke, | 61 const SkStrokeRec& stroke, |
61 bool doAA) { | 62 bool doAA) { |
62 // the gpu alpha mask will draw the inverse paths as non-inverse to a temp b uffer | 63 // the gpu alpha mask will draw the inverse paths as non-inverse to a temp b uffer |
63 SkTCopyOnFirstWrite<SkPath> path(origPath); | 64 SkTCopyOnFirstWrite<SkPath> path(origPath); |
64 if (path->isInverseFillType()) { | 65 if (path->isInverseFillType()) { |
65 path.writable()->toggleInverseFillType(); | 66 path.writable()->toggleInverseFillType(); |
66 } | 67 } |
67 // last (false) parameter disallows use of the SW path renderer | 68 // last (false) parameter disallows use of the SW path renderer |
68 GrPathRendererChain::DrawType type = doAA ? | 69 GrPathRendererChain::DrawType type = doAA ? |
69 GrPathRendererChain::kColorAntiAlias_Dr awType : | 70 GrPathRendererChain::kColorAntiAlias_Dr awType : |
70 GrPathRendererChain::kColor_DrawType; | 71 GrPathRendererChain::kColor_DrawType; |
71 | 72 |
72 return NULL == context->getPathRenderer(gpu, drawState, *path, stroke, false , type); | 73 return NULL == context->getPathRenderer(gpu, drawState, viewMatrix, *path, s troke, false, type); |
73 } | 74 } |
74 } | 75 } |
75 | 76 |
76 /* | 77 /* |
77 * This method traverses the clip stack to see if the GrSoftwarePathRenderer | 78 * This method traverses the clip stack to see if the GrSoftwarePathRenderer |
78 * will be used on any element. If so, it returns true to indicate that the | 79 * will be used on any element. If so, it returns true to indicate that the |
79 * entire clip should be rendered in SW and then uploaded en masse to the gpu. | 80 * entire clip should be rendered in SW and then uploaded en masse to the gpu. |
80 */ | 81 */ |
81 bool GrClipMaskManager::useSWOnlyPath(const GrDrawState* drawState, | 82 bool GrClipMaskManager::useSWOnlyPath(const GrDrawState* drawState, |
83 const SkMatrix& viewMatrix, | |
bsalomon
2014/12/29 20:26:58
Maybe take the skvector translate here instead of
| |
82 const GrReducedClip::ElementList& elements ) { | 84 const GrReducedClip::ElementList& elements ) { |
83 // TODO: generalize this function so that when | 85 // TODO: generalize this function so that when |
84 // a clip gets complex enough it can just be done in SW regardless | 86 // a clip gets complex enough it can just be done in SW regardless |
85 // of whether it would invoke the GrSoftwarePathRenderer. | 87 // of whether it would invoke the GrSoftwarePathRenderer. |
86 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); | 88 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); |
87 | 89 |
88 for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.get(); iter.next()) { | 90 for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.get(); iter.next()) { |
89 const Element* element = iter.get(); | 91 const Element* element = iter.get(); |
90 // rects can always be drawn directly w/o using the software path | 92 // rects can always be drawn directly w/o using the software path |
91 // Skip rrects once we're drawing them directly. | 93 // Skip rrects once we're drawing them directly. |
92 if (Element::kRect_Type != element->getType()) { | 94 if (Element::kRect_Type != element->getType()) { |
93 SkPath path; | 95 SkPath path; |
94 element->asPath(&path); | 96 element->asPath(&path); |
95 if (path_needs_SW_renderer(this->getContext(), fClipTarget, drawStat e, path, stroke, | 97 if (path_needs_SW_renderer(this->getContext(), fClipTarget, drawStat e, viewMatrix, |
96 element->isAA())) { | 98 path, stroke, element->isAA())) { |
97 return true; | 99 return true; |
98 } | 100 } |
99 } | 101 } |
100 } | 102 } |
101 return false; | 103 return false; |
102 } | 104 } |
103 | 105 |
104 bool GrClipMaskManager::installClipEffects(GrDrawState* drawState, | 106 bool GrClipMaskManager::installClipEffects(GrDrawState* drawState, |
105 GrDrawState::AutoRestoreEffects* are, | 107 GrDrawState::AutoRestoreEffects* are, |
106 const GrReducedClip::ElementList& ele ments, | 108 const GrReducedClip::ElementList& ele ments, |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
266 this->setDrawStateStencil(drawState, ars); | 268 this->setDrawStateStencil(drawState, ars); |
267 return true; | 269 return true; |
268 } | 270 } |
269 } | 271 } |
270 | 272 |
271 #if GR_AA_CLIP | 273 #if GR_AA_CLIP |
272 // If MSAA is enabled we can do everything in the stencil buffer. | 274 // If MSAA is enabled we can do everything in the stencil buffer. |
273 if (0 == rt->numSamples() && requiresAA) { | 275 if (0 == rt->numSamples() && requiresAA) { |
274 GrTexture* result = NULL; | 276 GrTexture* result = NULL; |
275 | 277 |
276 if (this->useSWOnlyPath(drawState, elements)) { | 278 // The top-left of the mask corresponds to the top-left corner of the bo unds. |
279 SkVector clipToMaskOffset = { | |
280 SkIntToScalar(-clipSpaceIBounds.fLeft), | |
281 SkIntToScalar(-clipSpaceIBounds.fTop) | |
282 }; | |
283 | |
284 // Set the matrix so that rendered clip elements are transformed to mask space from clip | |
285 // space. | |
286 SkMatrix translate; | |
287 translate.setTranslate(clipToMaskOffset); | |
288 | |
289 if (this->useSWOnlyPath(drawState, translate, elements)) { | |
277 // The clip geometry is complex enough that it will be more efficien t to create it | 290 // The clip geometry is complex enough that it will be more efficien t to create it |
278 // entirely in software | 291 // entirely in software |
279 result = this->createSoftwareClipMask(genID, | 292 result = this->createSoftwareClipMask(genID, |
280 initialState, | 293 initialState, |
281 elements, | 294 elements, |
295 translate, | |
282 clipSpaceIBounds); | 296 clipSpaceIBounds); |
283 } else { | 297 } else { |
284 result = this->createAlphaClipMask(genID, | 298 result = this->createAlphaClipMask(genID, |
285 initialState, | 299 initialState, |
286 elements, | 300 elements, |
301 translate, | |
302 clipToMaskOffset, | |
287 clipSpaceIBounds); | 303 clipSpaceIBounds); |
288 } | 304 } |
289 | 305 |
290 if (result) { | 306 if (result) { |
291 // The mask's top left coord should be pinned to the rounded-out top left corner of | 307 // The mask's top left coord should be pinned to the rounded-out top left corner of |
292 // clipSpace bounds. We determine the mask's position WRT to the ren der target here. | 308 // clipSpace bounds. We determine the mask's position WRT to the ren der target here. |
293 SkIRect rtSpaceMaskBounds = clipSpaceIBounds; | 309 SkIRect rtSpaceMaskBounds = clipSpaceIBounds; |
294 rtSpaceMaskBounds.offset(-clipDataIn->fOrigin); | 310 rtSpaceMaskBounds.offset(-clipDataIn->fOrigin); |
295 setup_drawstate_aaclip(rtSpaceMaskBounds, drawState, result); | 311 setup_drawstate_aaclip(rtSpaceMaskBounds, drawState, result); |
296 this->setDrawStateStencil(drawState, ars); | 312 this->setDrawStateStencil(drawState, ars); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
330 //////////////////////////////////////////////////////////////////////////////// | 346 //////////////////////////////////////////////////////////////////////////////// |
331 // Set a coverage drawing XPF on the drawState for the given op and invertCovera ge mode | 347 // Set a coverage drawing XPF on the drawState for the given op and invertCovera ge mode |
332 void set_coverage_drawing_xpf(SkRegion::Op op, bool invertCoverage, GrDrawState* drawState) { | 348 void set_coverage_drawing_xpf(SkRegion::Op op, bool invertCoverage, GrDrawState* drawState) { |
333 SkASSERT(op <= SkRegion::kLastOp); | 349 SkASSERT(op <= SkRegion::kLastOp); |
334 drawState->setCoverageSetOpXPFactory(op, invertCoverage); | 350 drawState->setCoverageSetOpXPFactory(op, invertCoverage); |
335 } | 351 } |
336 } | 352 } |
337 | 353 |
338 //////////////////////////////////////////////////////////////////////////////// | 354 //////////////////////////////////////////////////////////////////////////////// |
339 bool GrClipMaskManager::drawElement(GrDrawState* drawState, | 355 bool GrClipMaskManager::drawElement(GrDrawState* drawState, |
356 const SkMatrix& viewMatrix, | |
340 GrTexture* target, | 357 GrTexture* target, |
341 const SkClipStack::Element* element, | 358 const SkClipStack::Element* element, |
342 GrPathRenderer* pr) { | 359 GrPathRenderer* pr) { |
343 GrDrawTarget::AutoGeometryPush agp(fClipTarget); | 360 GrDrawTarget::AutoGeometryPush agp(fClipTarget); |
344 | 361 |
345 drawState->setRenderTarget(target->asRenderTarget()); | 362 drawState->setRenderTarget(target->asRenderTarget()); |
346 | 363 |
347 // The color we use to draw does not matter since we will always be using a GrCoverageSetOpXP | 364 // The color we use to draw does not matter since we will always be using a GrCoverageSetOpXP |
348 // which ignores color. | 365 // which ignores color. |
349 GrColor color = GrColor_WHITE; | 366 GrColor color = GrColor_WHITE; |
350 | 367 |
351 // TODO: Draw rrects directly here. | 368 // TODO: Draw rrects directly here. |
352 switch (element->getType()) { | 369 switch (element->getType()) { |
353 case Element::kEmpty_Type: | 370 case Element::kEmpty_Type: |
354 SkDEBUGFAIL("Should never get here with an empty element."); | 371 SkDEBUGFAIL("Should never get here with an empty element."); |
355 break; | 372 break; |
356 case Element::kRect_Type: | 373 case Element::kRect_Type: |
357 // TODO: Do rects directly to the accumulator using a aa-rect GrProc essor that covers | 374 // TODO: Do rects directly to the accumulator using a aa-rect GrProc essor that covers |
358 // the entire mask bounds and writes 0 outside the rect. | 375 // the entire mask bounds and writes 0 outside the rect. |
359 if (element->isAA()) { | 376 if (element->isAA()) { |
377 SkMatrix invert; | |
378 if (!viewMatrix.invert(&invert)) { | |
379 SkDebugf("Could not invert\n"); | |
380 return false; | |
381 } | |
382 SkRect devRect = element->getRect(); | |
383 viewMatrix.mapRect(&devRect); | |
360 this->getContext()->getAARectRenderer()->fillAARect(fClipTarget, | 384 this->getContext()->getAARectRenderer()->fillAARect(fClipTarget, |
361 drawState, | 385 drawState, |
362 color, | 386 color, |
363 SkMatrix::I( ), | 387 viewMatrix, |
388 invert, | |
364 element->get Rect(), | 389 element->get Rect(), |
365 SkMatrix::I( ), | 390 devRect); |
366 element->get Rect()); | |
367 } else { | 391 } else { |
368 fClipTarget->drawSimpleRect(drawState, color, element->getRect() ); | 392 fClipTarget->drawSimpleRect(drawState, color, viewMatrix, elemen t->getRect()); |
369 } | 393 } |
370 return true; | 394 return true; |
371 default: { | 395 default: { |
372 SkPath path; | 396 SkPath path; |
373 element->asPath(&path); | 397 element->asPath(&path); |
374 path.setIsVolatile(true); | 398 path.setIsVolatile(true); |
375 if (path.isInverseFillType()) { | 399 if (path.isInverseFillType()) { |
376 path.toggleInverseFillType(); | 400 path.toggleInverseFillType(); |
377 } | 401 } |
378 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); | 402 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); |
379 if (NULL == pr) { | 403 if (NULL == pr) { |
380 GrPathRendererChain::DrawType type; | 404 GrPathRendererChain::DrawType type; |
381 type = element->isAA() ? GrPathRendererChain::kColorAntiAlias_Dr awType : | 405 type = element->isAA() ? GrPathRendererChain::kColorAntiAlias_Dr awType : |
382 GrPathRendererChain::kColor_DrawType; | 406 GrPathRendererChain::kColor_DrawType; |
383 pr = this->getContext()->getPathRenderer(fClipTarget, drawState, path, stroke, | 407 pr = this->getContext()->getPathRenderer(fClipTarget, drawState, viewMatrix, path, |
384 false, type); | 408 stroke, false, type); |
385 } | 409 } |
386 if (NULL == pr) { | 410 if (NULL == pr) { |
387 return false; | 411 return false; |
388 } | 412 } |
389 | 413 |
390 pr->drawPath(fClipTarget, drawState, color, path, stroke, element->i sAA()); | 414 pr->drawPath(fClipTarget, drawState, color, viewMatrix, path, stroke , element->isAA()); |
391 break; | 415 break; |
392 } | 416 } |
393 } | 417 } |
394 return true; | 418 return true; |
395 } | 419 } |
396 | 420 |
397 bool GrClipMaskManager::canStencilAndDrawElement(GrDrawState* drawState, | 421 bool GrClipMaskManager::canStencilAndDrawElement(GrDrawState* drawState, |
398 GrTexture* target, | 422 GrTexture* target, |
399 GrPathRenderer** pr, | 423 GrPathRenderer** pr, |
400 const SkClipStack::Element* ele ment) { | 424 const SkClipStack::Element* ele ment) { |
401 drawState->setRenderTarget(target->asRenderTarget()); | 425 drawState->setRenderTarget(target->asRenderTarget()); |
402 | 426 |
403 if (Element::kRect_Type == element->getType()) { | 427 if (Element::kRect_Type == element->getType()) { |
404 return true; | 428 return true; |
405 } else { | 429 } else { |
406 // We shouldn't get here with an empty clip element. | 430 // We shouldn't get here with an empty clip element. |
407 SkASSERT(Element::kEmpty_Type != element->getType()); | 431 SkASSERT(Element::kEmpty_Type != element->getType()); |
408 SkPath path; | 432 SkPath path; |
409 element->asPath(&path); | 433 element->asPath(&path); |
410 if (path.isInverseFillType()) { | 434 if (path.isInverseFillType()) { |
411 path.toggleInverseFillType(); | 435 path.toggleInverseFillType(); |
412 } | 436 } |
413 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); | 437 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); |
414 GrPathRendererChain::DrawType type = element->isAA() ? | 438 GrPathRendererChain::DrawType type = element->isAA() ? |
415 GrPathRendererChain::kStencilAndColorAntiAlias_DrawType : | 439 GrPathRendererChain::kStencilAndColorAntiAlias_DrawType : |
416 GrPathRendererChain::kStencilAndColor_DrawType; | 440 GrPathRendererChain::kStencilAndColor_DrawType; |
417 *pr = this->getContext()->getPathRenderer(fClipTarget, drawState, path, stroke, false, | 441 *pr = this->getContext()->getPathRenderer(fClipTarget, drawState, SkMatr ix::I(), path, |
418 type); | 442 stroke, false, type); |
419 return SkToBool(*pr); | 443 return SkToBool(*pr); |
420 } | 444 } |
421 } | 445 } |
422 | 446 |
423 void GrClipMaskManager::mergeMask(GrDrawState* drawState, | 447 void GrClipMaskManager::mergeMask(GrDrawState* drawState, |
424 GrTexture* dstMask, | 448 GrTexture* dstMask, |
425 GrTexture* srcMask, | 449 GrTexture* srcMask, |
426 SkRegion::Op op, | 450 SkRegion::Op op, |
427 const SkIRect& dstBound, | 451 const SkIRect& dstBound, |
428 const SkIRect& srcBound) { | 452 const SkIRect& srcBound) { |
429 drawState->setRenderTarget(dstMask->asRenderTarget()); | 453 drawState->setRenderTarget(dstMask->asRenderTarget()); |
430 | 454 |
431 // We want to invert the coverage here | 455 // We want to invert the coverage here |
432 set_coverage_drawing_xpf(op, false, drawState); | 456 set_coverage_drawing_xpf(op, false, drawState); |
433 | 457 |
434 SkMatrix sampleM; | 458 SkMatrix sampleM; |
435 sampleM.setIDiv(srcMask->width(), srcMask->height()); | 459 sampleM.setIDiv(srcMask->width(), srcMask->height()); |
436 | 460 |
437 drawState->addCoverageProcessor( | 461 drawState->addCoverageProcessor( |
438 GrTextureDomainEffect::Create(srcMask, | 462 GrTextureDomainEffect::Create(srcMask, |
439 sampleM, | 463 sampleM, |
440 GrTextureDomain::MakeTexelDomain(srcMask, srcBound), | 464 GrTextureDomain::MakeTexelDomain(srcMask, srcBound), |
441 GrTextureDomain::kDecal_Mode, | 465 GrTextureDomain::kDecal_Mode, |
442 GrTextureParams::kNone_FilterMode))->unref (); | 466 GrTextureParams::kNone_FilterMode))->unref (); |
443 // The color passed in here does not matter since the coverageSetOpXP won't read it. | 467 // The color passed in here does not matter since the coverageSetOpXP won't read it. |
444 fClipTarget->drawSimpleRect(drawState, GrColor_WHITE, SkRect::Make(dstBound) ); | 468 fClipTarget->drawSimpleRect(drawState, GrColor_WHITE, SkMatrix::I(), SkRect: :Make(dstBound)); |
445 } | 469 } |
446 | 470 |
447 GrTexture* GrClipMaskManager::createTempMask(int width, int height) { | 471 GrTexture* GrClipMaskManager::createTempMask(int width, int height) { |
448 GrSurfaceDesc desc; | 472 GrSurfaceDesc desc; |
449 desc.fFlags = kRenderTarget_GrSurfaceFlag; | 473 desc.fFlags = kRenderTarget_GrSurfaceFlag; |
450 desc.fWidth = width; | 474 desc.fWidth = width; |
451 desc.fHeight = height; | 475 desc.fHeight = height; |
452 if (this->getContext()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) { | 476 if (this->getContext()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) { |
453 desc.fConfig = kAlpha_8_GrPixelConfig; | 477 desc.fConfig = kAlpha_8_GrPixelConfig; |
454 } else { | 478 } else { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
492 | 516 |
493 fAACache.acquireMask(elementsGenID, desc, clipSpaceIBounds); | 517 fAACache.acquireMask(elementsGenID, desc, clipSpaceIBounds); |
494 return fAACache.getLastMask(); | 518 return fAACache.getLastMask(); |
495 } | 519 } |
496 | 520 |
497 //////////////////////////////////////////////////////////////////////////////// | 521 //////////////////////////////////////////////////////////////////////////////// |
498 // Create a 8-bit clip mask in alpha | 522 // Create a 8-bit clip mask in alpha |
499 GrTexture* GrClipMaskManager::createAlphaClipMask(int32_t elementsGenID, | 523 GrTexture* GrClipMaskManager::createAlphaClipMask(int32_t elementsGenID, |
500 GrReducedClip::InitialState in itialState, | 524 GrReducedClip::InitialState in itialState, |
501 const GrReducedClip::ElementLi st& elements, | 525 const GrReducedClip::ElementLi st& elements, |
526 const SkMatrix& translate, | |
bsalomon
2014/12/29 20:26:58
Seems weird to pass essentially the same thing twi
| |
527 const SkVector& clipToMaskOffs et, | |
502 const SkIRect& clipSpaceIBound s) { | 528 const SkIRect& clipSpaceIBound s) { |
503 SkASSERT(kNone_ClipMaskType == fCurrClipMaskType); | 529 SkASSERT(kNone_ClipMaskType == fCurrClipMaskType); |
504 | 530 |
505 // First, check for cached texture | 531 // First, check for cached texture |
506 GrTexture* result = this->getCachedMaskTexture(elementsGenID, clipSpaceIBoun ds); | 532 GrTexture* result = this->getCachedMaskTexture(elementsGenID, clipSpaceIBoun ds); |
507 if (result) { | 533 if (result) { |
508 fCurrClipMaskType = kAlpha_ClipMaskType; | 534 fCurrClipMaskType = kAlpha_ClipMaskType; |
509 return result; | 535 return result; |
510 } | 536 } |
511 | 537 |
512 // There's no texture in the cache. Let's try to allocate it then. | 538 // There's no texture in the cache. Let's try to allocate it then. |
513 result = this->allocMaskTexture(elementsGenID, clipSpaceIBounds, false); | 539 result = this->allocMaskTexture(elementsGenID, clipSpaceIBounds, false); |
514 if (NULL == result) { | 540 if (NULL == result) { |
515 fAACache.reset(); | 541 fAACache.reset(); |
516 return NULL; | 542 return NULL; |
517 } | 543 } |
518 | 544 |
519 // The top-left of the mask corresponds to the top-left corner of the bounds . | |
520 SkVector clipToMaskOffset = { | |
521 SkIntToScalar(-clipSpaceIBounds.fLeft), | |
522 SkIntToScalar(-clipSpaceIBounds.fTop) | |
523 }; | |
524 // The texture may be larger than necessary, this rect represents the part o f the texture | 545 // The texture may be larger than necessary, this rect represents the part o f the texture |
525 // we populate with a rasterization of the clip. | 546 // we populate with a rasterization of the clip. |
526 SkIRect maskSpaceIBounds = SkIRect::MakeWH(clipSpaceIBounds.width(), clipSpa ceIBounds.height()); | 547 SkIRect maskSpaceIBounds = SkIRect::MakeWH(clipSpaceIBounds.width(), clipSpa ceIBounds.height()); |
527 | 548 |
528 // Set the matrix so that rendered clip elements are transformed to mask spa ce from clip space. | |
529 SkMatrix translate; | |
530 translate.setTranslate(clipToMaskOffset); | |
531 | |
532 // The scratch texture that we are drawing into can be substantially larger than the mask. Only | 549 // The scratch texture that we are drawing into can be substantially larger than the mask. Only |
533 // clear the part that we care about. | 550 // clear the part that we care about. |
534 fClipTarget->clear(&maskSpaceIBounds, | 551 fClipTarget->clear(&maskSpaceIBounds, |
535 GrReducedClip::kAllIn_InitialState == initialState ? 0xff ffffff : 0x00000000, | 552 GrReducedClip::kAllIn_InitialState == initialState ? 0xff ffffff : 0x00000000, |
536 true, | 553 true, |
537 result->asRenderTarget()); | 554 result->asRenderTarget()); |
538 | 555 |
539 // When we use the stencil in the below loop it is important to have this cl ip installed. | 556 // When we use the stencil in the below loop it is important to have this cl ip installed. |
540 // The second pass that zeros the stencil buffer renders the rect maskSpaceI Bounds so the first | 557 // The second pass that zeros the stencil buffer renders the rect maskSpaceI Bounds so the first |
541 // pass must not set values outside of this bounds or stencil values outside the rect won't be | 558 // pass must not set values outside of this bounds or stencil values outside the rect won't be |
542 // cleared. | 559 // cleared. |
543 GrDrawTarget::AutoClipRestore acr(fClipTarget, maskSpaceIBounds); | 560 GrDrawTarget::AutoClipRestore acr(fClipTarget, maskSpaceIBounds); |
544 SkAutoTUnref<GrTexture> temp; | 561 SkAutoTUnref<GrTexture> temp; |
545 | 562 |
546 // walk through each clip element and perform its set op | 563 // walk through each clip element and perform its set op |
547 for (GrReducedClip::ElementList::Iter iter = elements.headIter(); iter.get() ; iter.next()) { | 564 for (GrReducedClip::ElementList::Iter iter = elements.headIter(); iter.get() ; iter.next()) { |
548 const Element* element = iter.get(); | 565 const Element* element = iter.get(); |
549 SkRegion::Op op = element->getOp(); | 566 SkRegion::Op op = element->getOp(); |
550 bool invert = element->isInverseFilled(); | 567 bool invert = element->isInverseFilled(); |
551 if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDiffere nce_Op == op) { | 568 if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDiffere nce_Op == op) { |
552 GrDrawState drawState(translate); | 569 GrDrawState drawState; |
553 drawState.enableState(GrDrawState::kClip_StateBit); | 570 drawState.enableState(GrDrawState::kClip_StateBit); |
554 | 571 |
555 GrPathRenderer* pr = NULL; | 572 GrPathRenderer* pr = NULL; |
556 bool useTemp = !this->canStencilAndDrawElement(&drawState, result, & pr, element); | 573 bool useTemp = !this->canStencilAndDrawElement(&drawState, result, & pr, element); |
557 GrTexture* dst; | 574 GrTexture* dst; |
558 // This is the bounds of the clip element in the space of the alpha- mask. The temporary | 575 // This is the bounds of the clip element in the space of the alpha- mask. The temporary |
559 // mask buffer can be substantially larger than the actually clip st ack element. We | 576 // mask buffer can be substantially larger than the actually clip st ack element. We |
560 // touch the minimum number of pixels necessary and use decal mode t o combine it with | 577 // touch the minimum number of pixels necessary and use decal mode t o combine it with |
561 // the accumulator. | 578 // the accumulator. |
562 SkIRect maskSpaceElementIBounds; | 579 SkIRect maskSpaceElementIBounds; |
(...skipping 30 matching lines...) Expand all Loading... | |
593 kReplace_StencilOp, | 610 kReplace_StencilOp, |
594 kReplace_StencilOp, | 611 kReplace_StencilOp, |
595 kAlways_StencilFunc, | 612 kAlways_StencilFunc, |
596 0xffff, | 613 0xffff, |
597 0xffff, | 614 0xffff, |
598 0xffff); | 615 0xffff); |
599 drawState.setStencil(kStencilInElement); | 616 drawState.setStencil(kStencilInElement); |
600 set_coverage_drawing_xpf(op, invert, &drawState); | 617 set_coverage_drawing_xpf(op, invert, &drawState); |
601 } | 618 } |
602 | 619 |
603 if (!this->drawElement(&drawState, dst, element, pr)) { | 620 if (!this->drawElement(&drawState, translate, dst, element, pr)) { |
604 fAACache.reset(); | 621 fAACache.reset(); |
605 return NULL; | 622 return NULL; |
606 } | 623 } |
607 | 624 |
608 if (useTemp) { | 625 if (useTemp) { |
609 GrDrawState backgroundDrawState; | 626 GrDrawState backgroundDrawState; |
610 backgroundDrawState.enableState(GrDrawState::kClip_StateBit); | 627 backgroundDrawState.enableState(GrDrawState::kClip_StateBit); |
611 backgroundDrawState.setRenderTarget(result->asRenderTarget()); | 628 backgroundDrawState.setRenderTarget(result->asRenderTarget()); |
612 | 629 |
613 // Now draw into the accumulator using the real operation and th e temp buffer as a | 630 // Now draw into the accumulator using the real operation and th e temp buffer as a |
614 // texture | 631 // texture |
615 this->mergeMask(&backgroundDrawState, | 632 this->mergeMask(&backgroundDrawState, |
616 result, | 633 result, |
617 temp, | 634 temp, |
618 op, | 635 op, |
619 maskSpaceIBounds, | 636 maskSpaceIBounds, |
620 maskSpaceElementIBounds); | 637 maskSpaceElementIBounds); |
621 } else { | 638 } else { |
622 GrDrawState backgroundDrawState(translate); | 639 GrDrawState backgroundDrawState; |
623 backgroundDrawState.enableState(GrDrawState::kClip_StateBit); | 640 backgroundDrawState.enableState(GrDrawState::kClip_StateBit); |
624 backgroundDrawState.setRenderTarget(result->asRenderTarget()); | 641 backgroundDrawState.setRenderTarget(result->asRenderTarget()); |
625 | 642 |
626 set_coverage_drawing_xpf(op, !invert, &backgroundDrawState); | 643 set_coverage_drawing_xpf(op, !invert, &backgroundDrawState); |
627 // Draw to the exterior pixels (those with a zero stencil value) . | 644 // Draw to the exterior pixels (those with a zero stencil value) . |
628 GR_STATIC_CONST_SAME_STENCIL(kDrawOutsideElement, | 645 GR_STATIC_CONST_SAME_STENCIL(kDrawOutsideElement, |
629 kZero_StencilOp, | 646 kZero_StencilOp, |
630 kZero_StencilOp, | 647 kZero_StencilOp, |
631 kEqual_StencilFunc, | 648 kEqual_StencilFunc, |
632 0xffff, | 649 0xffff, |
633 0x0000, | 650 0x0000, |
634 0xffff); | 651 0xffff); |
635 backgroundDrawState.setStencil(kDrawOutsideElement); | 652 backgroundDrawState.setStencil(kDrawOutsideElement); |
636 // The color passed in here does not matter since the coverageSe tOpXP won't read it. | 653 // The color passed in here does not matter since the coverageSe tOpXP won't read it. |
637 fClipTarget->drawSimpleRect(&backgroundDrawState, GrColor_WHITE, clipSpaceIBounds); | 654 fClipTarget->drawSimpleRect(&backgroundDrawState, GrColor_WHITE, translate, |
655 clipSpaceIBounds); | |
638 } | 656 } |
639 } else { | 657 } else { |
640 GrDrawState drawState(translate); | 658 GrDrawState drawState; |
641 drawState.enableState(GrDrawState::kClip_StateBit); | 659 drawState.enableState(GrDrawState::kClip_StateBit); |
642 | 660 |
643 // all the remaining ops can just be directly draw into the accumula tion buffer | 661 // all the remaining ops can just be directly draw into the accumula tion buffer |
644 set_coverage_drawing_xpf(op, false, &drawState); | 662 set_coverage_drawing_xpf(op, false, &drawState); |
645 // The color passed in here does not matter since the coverageSetOpX P won't read it. | 663 // The color passed in here does not matter since the coverageSetOpX P won't read it. |
646 this->drawElement(&drawState, result, element); | 664 this->drawElement(&drawState, translate, result, element); |
647 } | 665 } |
648 } | 666 } |
649 | 667 |
650 fCurrClipMaskType = kAlpha_ClipMaskType; | 668 fCurrClipMaskType = kAlpha_ClipMaskType; |
651 return result; | 669 return result; |
652 } | 670 } |
653 | 671 |
654 //////////////////////////////////////////////////////////////////////////////// | 672 //////////////////////////////////////////////////////////////////////////////// |
655 // Create a 1-bit clip mask in the stencil buffer. 'devClipBounds' are in device | 673 // Create a 1-bit clip mask in the stencil buffer. 'devClipBounds' are in device |
656 // (as opposed to canvas) coordinates | 674 // (as opposed to canvas) coordinates |
(...skipping 12 matching lines...) Expand all Loading... | |
669 return false; | 687 return false; |
670 } | 688 } |
671 | 689 |
672 if (stencilBuffer->mustRenderClip(elementsGenID, clipSpaceIBounds, clipSpace ToStencilOffset)) { | 690 if (stencilBuffer->mustRenderClip(elementsGenID, clipSpaceIBounds, clipSpace ToStencilOffset)) { |
673 stencilBuffer->setLastClip(elementsGenID, clipSpaceIBounds, clipSpaceToS tencilOffset); | 691 stencilBuffer->setLastClip(elementsGenID, clipSpaceIBounds, clipSpaceToS tencilOffset); |
674 // Set the matrix so that rendered clip elements are transformed from cl ip to stencil space. | 692 // Set the matrix so that rendered clip elements are transformed from cl ip to stencil space. |
675 SkVector translate = { | 693 SkVector translate = { |
676 SkIntToScalar(clipSpaceToStencilOffset.fX), | 694 SkIntToScalar(clipSpaceToStencilOffset.fX), |
677 SkIntToScalar(clipSpaceToStencilOffset.fY) | 695 SkIntToScalar(clipSpaceToStencilOffset.fY) |
678 }; | 696 }; |
679 SkMatrix matrix; | 697 SkMatrix viewMatrix; |
680 matrix.setTranslate(translate); | 698 viewMatrix.setTranslate(translate); |
681 | 699 |
682 // We set the current clip to the bounds so that our recursive draws are scissored to them. | 700 // We set the current clip to the bounds so that our recursive draws are scissored to them. |
683 SkIRect stencilSpaceIBounds(clipSpaceIBounds); | 701 SkIRect stencilSpaceIBounds(clipSpaceIBounds); |
684 stencilSpaceIBounds.offset(clipSpaceToStencilOffset); | 702 stencilSpaceIBounds.offset(clipSpaceToStencilOffset); |
685 GrDrawTarget::AutoClipRestore acr(fClipTarget, stencilSpaceIBounds); | 703 GrDrawTarget::AutoClipRestore acr(fClipTarget, stencilSpaceIBounds); |
686 | 704 |
687 int clipBit = stencilBuffer->bits(); | 705 int clipBit = stencilBuffer->bits(); |
688 SkASSERT((clipBit <= 16) && "Ganesh only handles 16b or smaller stencil buffers"); | 706 SkASSERT((clipBit <= 16) && "Ganesh only handles 16b or smaller stencil buffers"); |
689 clipBit = (1 << (clipBit-1)); | 707 clipBit = (1 << (clipBit-1)); |
690 | 708 |
691 fClipTarget->clearStencilClip(stencilSpaceIBounds, | 709 fClipTarget->clearStencilClip(stencilSpaceIBounds, |
692 GrReducedClip::kAllIn_InitialState == init ialState, | 710 GrReducedClip::kAllIn_InitialState == init ialState, |
693 rt); | 711 rt); |
694 | 712 |
695 // walk through each clip element and perform its set op | 713 // walk through each clip element and perform its set op |
696 // with the existing clip. | 714 // with the existing clip. |
697 for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.ge t(); iter.next()) { | 715 for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.ge t(); iter.next()) { |
698 const Element* element = iter.get(); | 716 const Element* element = iter.get(); |
699 | 717 |
700 GrDrawState drawState(matrix); | 718 GrDrawState drawState; |
701 drawState.setRenderTarget(rt); | 719 drawState.setRenderTarget(rt); |
702 drawState.enableState(GrDrawState::kClip_StateBit); | 720 drawState.enableState(GrDrawState::kClip_StateBit); |
703 | 721 |
704 drawState.setDisableColorXPFactory(); | 722 drawState.setDisableColorXPFactory(); |
705 | 723 |
706 // if the target is MSAA then we want MSAA enabled when the clip is soft | 724 // if the target is MSAA then we want MSAA enabled when the clip is soft |
707 if (rt->isMultisampled()) { | 725 if (rt->isMultisampled()) { |
708 drawState.setState(GrDrawState::kHWAntialias_StateBit, element-> isAA()); | 726 drawState.setState(GrDrawState::kHWAntialias_StateBit, element-> isAA()); |
709 } | 727 } |
710 | 728 |
(...skipping 14 matching lines...) Expand all Loading... | |
725 stencilSupport = GrPathRenderer::kNoRestriction_StencilSupport; | 743 stencilSupport = GrPathRenderer::kNoRestriction_StencilSupport; |
726 fillInverted = false; | 744 fillInverted = false; |
727 } else { | 745 } else { |
728 element->asPath(&clipPath); | 746 element->asPath(&clipPath); |
729 fillInverted = clipPath.isInverseFillType(); | 747 fillInverted = clipPath.isInverseFillType(); |
730 if (fillInverted) { | 748 if (fillInverted) { |
731 clipPath.toggleInverseFillType(); | 749 clipPath.toggleInverseFillType(); |
732 } | 750 } |
733 pr = this->getContext()->getPathRenderer(fClipTarget, | 751 pr = this->getContext()->getPathRenderer(fClipTarget, |
734 &drawState, | 752 &drawState, |
753 viewMatrix, | |
735 clipPath, | 754 clipPath, |
736 stroke, | 755 stroke, |
737 false, | 756 false, |
738 GrPathRendererChain::kS tencilOnly_DrawType, | 757 GrPathRendererChain::kS tencilOnly_DrawType, |
739 &stencilSupport); | 758 &stencilSupport); |
740 if (NULL == pr) { | 759 if (NULL == pr) { |
741 return false; | 760 return false; |
742 } | 761 } |
743 } | 762 } |
744 | 763 |
(...skipping 17 matching lines...) Expand all Loading... | |
762 if (!canDrawDirectToClip) { | 781 if (!canDrawDirectToClip) { |
763 GR_STATIC_CONST_SAME_STENCIL(gDrawToStencil, | 782 GR_STATIC_CONST_SAME_STENCIL(gDrawToStencil, |
764 kIncClamp_StencilOp, | 783 kIncClamp_StencilOp, |
765 kIncClamp_StencilOp, | 784 kIncClamp_StencilOp, |
766 kAlways_StencilFunc, | 785 kAlways_StencilFunc, |
767 0xffff, | 786 0xffff, |
768 0x0000, | 787 0x0000, |
769 0xffff); | 788 0xffff); |
770 if (Element::kRect_Type == element->getType()) { | 789 if (Element::kRect_Type == element->getType()) { |
771 *drawState.stencil() = gDrawToStencil; | 790 *drawState.stencil() = gDrawToStencil; |
772 fClipTarget->drawSimpleRect(&drawState, GrColor_WHITE, eleme nt->getRect()); | 791 fClipTarget->drawSimpleRect(&drawState, GrColor_WHITE, viewM atrix, |
792 element->getRect()); | |
773 } else { | 793 } else { |
774 if (!clipPath.isEmpty()) { | 794 if (!clipPath.isEmpty()) { |
775 GrDrawTarget::AutoGeometryPush agp(fClipTarget); | 795 GrDrawTarget::AutoGeometryPush agp(fClipTarget); |
776 if (canRenderDirectToStencil) { | 796 if (canRenderDirectToStencil) { |
777 *drawState.stencil() = gDrawToStencil; | 797 *drawState.stencil() = gDrawToStencil; |
778 pr->drawPath(fClipTarget, &drawState, GrColor_WHITE, clipPath, stroke, | 798 pr->drawPath(fClipTarget, &drawState, GrColor_WHITE, viewMatrix, |
779 false); | 799 clipPath, stroke, false); |
780 } else { | 800 } else { |
781 pr->stencilPath(fClipTarget, &drawState, clipPath, s troke); | 801 pr->stencilPath(fClipTarget, &drawState, viewMatrix, clipPath, stroke); |
782 } | 802 } |
783 } | 803 } |
784 } | 804 } |
785 } | 805 } |
786 | 806 |
787 // now we modify the clip bit by rendering either the clip | 807 // now we modify the clip bit by rendering either the clip |
788 // element directly or a bounding rect of the entire clip. | 808 // element directly or a bounding rect of the entire clip. |
789 fClipMode = kModifyClip_StencilClipMode; | 809 fClipMode = kModifyClip_StencilClipMode; |
790 for (int p = 0; p < passes; ++p) { | 810 for (int p = 0; p < passes; ++p) { |
791 GrDrawState drawStateCopy(drawState); | 811 GrDrawState drawStateCopy(drawState); |
792 *drawStateCopy.stencil() = stencilSettings[p]; | 812 *drawStateCopy.stencil() = stencilSettings[p]; |
793 | 813 |
794 if (canDrawDirectToClip) { | 814 if (canDrawDirectToClip) { |
795 if (Element::kRect_Type == element->getType()) { | 815 if (Element::kRect_Type == element->getType()) { |
796 fClipTarget->drawSimpleRect(&drawStateCopy, GrColor_WHIT E, | 816 fClipTarget->drawSimpleRect(&drawStateCopy, GrColor_WHIT E, viewMatrix, |
797 element->getRect()); | 817 element->getRect()); |
798 } else { | 818 } else { |
799 GrDrawTarget::AutoGeometryPush agp(fClipTarget); | 819 GrDrawTarget::AutoGeometryPush agp(fClipTarget); |
800 pr->drawPath(fClipTarget, &drawStateCopy, GrColor_WHITE, clipPath, stroke, false); | 820 pr->drawPath(fClipTarget, &drawStateCopy, GrColor_WHITE, viewMatrix, |
821 clipPath, stroke, false); | |
801 } | 822 } |
802 } else { | 823 } else { |
803 // The view matrix is setup to do clip space -> stencil spac e translation, so | 824 // The view matrix is setup to do clip space -> stencil spac e translation, so |
804 // draw rect in clip space. | 825 // draw rect in clip space. |
805 fClipTarget->drawSimpleRect(&drawStateCopy, GrColor_WHITE, | 826 fClipTarget->drawSimpleRect(&drawStateCopy, GrColor_WHITE, v iewMatrix, |
806 SkRect::Make(clipSpaceIBounds)); | 827 SkRect::Make(clipSpaceIBounds)); |
807 } | 828 } |
808 } | 829 } |
809 } | 830 } |
810 } | 831 } |
811 // set this last because recursive draws may overwrite it back to kNone. | 832 // set this last because recursive draws may overwrite it back to kNone. |
812 SkASSERT(kNone_ClipMaskType == fCurrClipMaskType); | 833 SkASSERT(kNone_ClipMaskType == fCurrClipMaskType); |
813 fCurrClipMaskType = kStencil_ClipMaskType; | 834 fCurrClipMaskType = kStencil_ClipMaskType; |
814 fClipMode = kRespectClip_StencilClipMode; | 835 fClipMode = kRespectClip_StencilClipMode; |
815 return true; | 836 return true; |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
982 } | 1003 } |
983 if (!twoSided) { | 1004 if (!twoSided) { |
984 settings->copyFrontSettingsToBack(); | 1005 settings->copyFrontSettingsToBack(); |
985 } | 1006 } |
986 } | 1007 } |
987 | 1008 |
988 //////////////////////////////////////////////////////////////////////////////// | 1009 //////////////////////////////////////////////////////////////////////////////// |
989 GrTexture* GrClipMaskManager::createSoftwareClipMask(int32_t elementsGenID, | 1010 GrTexture* GrClipMaskManager::createSoftwareClipMask(int32_t elementsGenID, |
990 GrReducedClip::InitialState initialState, | 1011 GrReducedClip::InitialState initialState, |
991 const GrReducedClip::Elemen tList& elements, | 1012 const GrReducedClip::Elemen tList& elements, |
1013 const SkMatrix& translate, | |
992 const SkIRect& clipSpaceIBo unds) { | 1014 const SkIRect& clipSpaceIBo unds) { |
993 SkASSERT(kNone_ClipMaskType == fCurrClipMaskType); | 1015 SkASSERT(kNone_ClipMaskType == fCurrClipMaskType); |
994 | 1016 |
995 GrTexture* result = this->getCachedMaskTexture(elementsGenID, clipSpaceIBoun ds); | 1017 GrTexture* result = this->getCachedMaskTexture(elementsGenID, clipSpaceIBoun ds); |
996 if (result) { | 1018 if (result) { |
997 return result; | 1019 return result; |
998 } | 1020 } |
999 | 1021 |
1000 // The mask texture may be larger than necessary. We round out the clip spac e bounds and pin | 1022 // The mask texture may be larger than necessary. We round out the clip spac e bounds and pin |
1001 // the top left corner of the resulting rect to the top left of the texture. | 1023 // the top left corner of the resulting rect to the top left of the texture. |
1002 SkIRect maskSpaceIBounds = SkIRect::MakeWH(clipSpaceIBounds.width(), clipSpa ceIBounds.height()); | 1024 SkIRect maskSpaceIBounds = SkIRect::MakeWH(clipSpaceIBounds.width(), clipSpa ceIBounds.height()); |
1003 | 1025 |
1004 GrSWMaskHelper helper(this->getContext()); | 1026 GrSWMaskHelper helper(this->getContext()); |
1005 | 1027 |
1006 SkMatrix matrix; | 1028 helper.init(maskSpaceIBounds, &translate, false); |
1007 matrix.setTranslate(SkIntToScalar(-clipSpaceIBounds.fLeft), | |
1008 SkIntToScalar(-clipSpaceIBounds.fTop)); | |
1009 | |
1010 helper.init(maskSpaceIBounds, &matrix, false); | |
1011 helper.clear(GrReducedClip::kAllIn_InitialState == initialState ? 0xFF : 0x0 0); | 1029 helper.clear(GrReducedClip::kAllIn_InitialState == initialState ? 0xFF : 0x0 0); |
1012 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); | 1030 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); |
1013 | 1031 |
1014 for (GrReducedClip::ElementList::Iter iter(elements.headIter()) ; iter.get() ; iter.next()) { | 1032 for (GrReducedClip::ElementList::Iter iter(elements.headIter()) ; iter.get() ; iter.next()) { |
1015 const Element* element = iter.get(); | 1033 const Element* element = iter.get(); |
1016 SkRegion::Op op = element->getOp(); | 1034 SkRegion::Op op = element->getOp(); |
1017 | 1035 |
1018 if (SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op == op) { | 1036 if (SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op == op) { |
1019 // Intersect and reverse difference require modifying pixels outside of the geometry | 1037 // Intersect and reverse difference require modifying pixels outside of the geometry |
1020 // that is being "drawn". In both cases we erase all the pixels outs ide of the geometry | 1038 // that is being "drawn". In both cases we erase all the pixels outs ide of the geometry |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1066 } | 1084 } |
1067 | 1085 |
1068 void GrClipMaskManager::adjustPathStencilParams(const GrStencilBuffer* stencilBu ffer, | 1086 void GrClipMaskManager::adjustPathStencilParams(const GrStencilBuffer* stencilBu ffer, |
1069 GrStencilSettings* settings) { | 1087 GrStencilSettings* settings) { |
1070 // TODO: dynamically attach a stencil buffer | 1088 // TODO: dynamically attach a stencil buffer |
1071 if (stencilBuffer) { | 1089 if (stencilBuffer) { |
1072 int stencilBits = stencilBuffer->bits(); | 1090 int stencilBits = stencilBuffer->bits(); |
1073 this->adjustStencilParams(settings, fClipMode, stencilBits); | 1091 this->adjustStencilParams(settings, fClipMode, stencilBits); |
1074 } | 1092 } |
1075 } | 1093 } |
OLD | NEW |