Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(539)

Side by Side Diff: src/gpu/GrClipMaskManager.cpp

Issue 23926019: Stateful PathRenderer implementation (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: clean up Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 1
2 /* 2 /*
3 * Copyright 2012 Google Inc. 3 * Copyright 2012 Google Inc.
4 * 4 *
5 * Use of this source code is governed by a BSD-style license that can be 5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file. 6 * found in the LICENSE file.
7 */ 7 */
8 8
9 #include "GrClipMaskManager.h" 9 #include "GrClipMaskManager.h"
10 #include "GrAAConvexPathRenderer.h" 10 #include "GrAAConvexPathRenderer.h"
(...skipping 11 matching lines...) Expand all
22 #include "SkStrokeRec.h" 22 #include "SkStrokeRec.h"
23 #include "SkTLazy.h" 23 #include "SkTLazy.h"
24 24
25 #define GR_AA_CLIP 1 25 #define GR_AA_CLIP 1
26 26
27 typedef SkClipStack::Element Element; 27 typedef SkClipStack::Element Element;
28 28
29 using namespace GrReducedClip; 29 using namespace GrReducedClip;
30 30
31 //////////////////////////////////////////////////////////////////////////////// 31 ////////////////////////////////////////////////////////////////////////////////
32 namespace {
33 // set up the draw state to enable the aa clipping mask. Besides setting up the 32 // set up the draw state to enable the aa clipping mask. Besides setting up the
34 // stage matrix this also alters the vertex layout 33 // stage matrix this also alters the vertex layout
35 void setup_drawstate_aaclip(GrGpu* gpu, 34 static void setup_drawstate_aaclip(GrGpu* gpu,
36 GrTexture* result, 35 GrTexture* result,
37 const SkIRect &devBound) { 36 const SkIRect &devBound) {
38 GrDrawState* drawState = gpu->drawState(); 37 GrDrawState* drawState = gpu->drawState();
39 SkASSERT(drawState); 38 SkASSERT(drawState);
40 39
41 SkMatrix mat; 40 SkMatrix mat;
42 // We want to use device coords to compute the texture coordinates. We set o ur matrix to be 41 // We want to use device coords to compute the texture coordinates. We set o ur matrix to be
43 // equal to the view matrix followed by an offset to the devBound, and then a scaling matrix to 42 // equal to the view matrix followed by an offset to the devBound, and then a scaling matrix to
44 // normalized coords. We apply this matrix to the vertex positions rather th an local coords. 43 // normalized coords. We apply this matrix to the vertex positions rather th an local coords.
45 mat.setIDiv(result->width(), result->height()); 44 mat.setIDiv(result->width(), result->height());
46 mat.preTranslate(SkIntToScalar(-devBound.fLeft), 45 mat.preTranslate(SkIntToScalar(-devBound.fLeft),
47 SkIntToScalar(-devBound.fTop)); 46 SkIntToScalar(-devBound.fTop));
48 mat.preConcat(drawState->getViewMatrix()); 47 mat.preConcat(drawState->getViewMatrix());
49 48
50 SkIRect domainTexels = SkIRect::MakeWH(devBound.width(), devBound.height()); 49 SkIRect domainTexels = SkIRect::MakeWH(devBound.width(), devBound.height());
51 // This could be a long-lived effect that is cached with the alpha-mask. 50 // This could be a long-lived effect that is cached with the alpha-mask.
52 drawState->addCoverageEffect( 51 drawState->addCoverageEffect(
53 GrTextureDomainEffect::Create(result, 52 GrTextureDomainEffect::Create(result,
54 mat, 53 mat,
55 GrTextureDomainEffect::MakeTexelDomain(res ult, domainTexels), 54 GrTextureDomainEffect::MakeTexelDomain(res ult, domainTexels),
56 GrTextureDomainEffect::kDecal_WrapMode, 55 GrTextureDomainEffect::kDecal_WrapMode,
57 GrTextureParams::kNone_FilterMode, 56 GrTextureParams::kNone_FilterMode,
58 GrEffect::kPosition_CoordsType))->unref(); 57 GrEffect::kPosition_CoordsType))->unref();
59 } 58 }
60 59
61 bool path_needs_SW_renderer(GrContext* context, 60 static bool path_needs_SW_renderer(GrContext* context,
62 GrGpu* gpu, 61 GrGpu* gpu,
63 const SkPath& origPath, 62 const SkPath& origPath,
64 const SkStrokeRec& stroke, 63 const SkStrokeRec& stroke,
65 bool doAA) { 64 bool doAA) {
66 // the gpu alpha mask will draw the inverse paths as non-inverse to a temp b uffer
67 SkTCopyOnFirstWrite<SkPath> path(origPath);
68 if (path->isInverseFillType()) {
69 path.writable()->toggleInverseFillType();
70 }
71 // last (false) parameter disallows use of the SW path renderer
72 GrPathRendererChain::DrawType type = doAA ? 65 GrPathRendererChain::DrawType type = doAA ?
73 GrPathRendererChain::kColorAntiAlias_Dr awType : 66 GrPathRendererChain::kColorAntiAlias_Dr awType :
74 GrPathRendererChain::kColor_DrawType; 67 GrPathRendererChain::kColor_DrawType;
68 // the gpu alpha mask will draw the inverse paths as non-inverse to a temp b uffer
69 SkPath::FillType fillType = SkPath::ConvertToNonInverseFillType(origPath.get FillType());
75 70
76 return NULL == context->getPathRenderer(*path, stroke, gpu, false, type); 71 // the 'false' parameter disallows use of the SW path renderer
77 } 72 return NULL == context->getPathRenderer(origPath, stroke, gpu, false, type, fillType);
78
79 } 73 }
80 74
81 /* 75 /*
82 * This method traverses the clip stack to see if the GrSoftwarePathRenderer 76 * This method traverses the clip stack to see if the GrSoftwarePathRenderer
83 * will be used on any element. If so, it returns true to indicate that the 77 * will be used on any element. If so, it returns true to indicate that the
84 * entire clip should be rendered in SW and then uploaded en masse to the gpu. 78 * entire clip should be rendered in SW and then uploaded en masse to the gpu.
85 */ 79 */
86 bool GrClipMaskManager::useSWOnlyPath(const ElementList& elements) { 80 bool GrClipMaskManager::useSWOnlyPath(const ElementList& elements) {
87 81
88 // TODO: generalize this function so that when 82 // TODO: generalize this function so that when
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
260 break; 254 break;
261 default: 255 default:
262 SkASSERT(false); 256 SkASSERT(false);
263 break; 257 break;
264 } 258 }
265 } 259 }
266 260
267 } 261 }
268 262
269 //////////////////////////////////////////////////////////////////////////////// 263 ////////////////////////////////////////////////////////////////////////////////
270 bool GrClipMaskManager::drawElement(GrTexture* target, 264 bool GrClipMaskManager::drawFilledPath(GrTexture* target,
271 const SkClipStack::Element* element, 265 GrPathRenderer* pathRenderer,
272 GrPathRenderer* pr) { 266 bool isAA) {
273 GrDrawState* drawState = fGpu->drawState(); 267 GrDrawState* drawState = fGpu->drawState();
274 268
275 drawState->setRenderTarget(target->asRenderTarget()); 269 drawState->setRenderTarget(target->asRenderTarget());
270
271 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
272 pathRenderer->drawPath(stroke, fGpu, isAA);
273 return true;
274 }
275
276 bool GrClipMaskManager::drawElement(GrTexture* target,
277 const SkClipStack::Element* element) {
278 GrDrawState* drawState = fGpu->drawState();
279
280 drawState->setRenderTarget(target->asRenderTarget());
276 281
277 switch (element->getType()) { 282 switch (element->getType()) {
278 case Element::kRect_Type: 283 case Element::kRect_Type:
279 // TODO: Do rects directly to the accumulator using a aa-rect GrEffe ct that covers the 284 // TODO: Do rects directly to the accumulator using a aa-rect GrEffe ct that covers the
280 // entire mask bounds and writes 0 outside the rect. 285 // entire mask bounds and writes 0 outside the rect.
281 if (element->isAA()) { 286 if (element->isAA()) {
282 getContext()->getAARectRenderer()->fillAARect(fGpu, 287 getContext()->getAARectRenderer()->fillAARect(fGpu,
283 fGpu, 288 fGpu,
284 element->getRect() , 289 element->getRect() ,
285 SkMatrix::I(), 290 SkMatrix::I(),
286 element->getRect() , 291 element->getRect() ,
287 false); 292 false);
288 } else { 293 } else {
289 fGpu->drawSimpleRect(element->getRect(), NULL); 294 fGpu->drawSimpleRect(element->getRect(), NULL);
290 } 295 }
291 return true; 296 return true;
292 case Element::kPath_Type: { 297 case Element::kPath_Type: {
293 SkTCopyOnFirstWrite<SkPath> path(element->getPath());
294 if (path->isInverseFillType()) {
295 path.writable()->toggleInverseFillType();
296 }
297 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); 298 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
298 if (NULL == pr) { 299 GrPathRendererChain::DrawType type;
299 GrPathRendererChain::DrawType type; 300 type = element->isAA() ? GrPathRendererChain::kColorAntiAlias_DrawTy pe :
300 type = element->isAA() ? GrPathRendererChain::kColorAntiAlias_Dr awType : 301 GrPathRendererChain::kColor_DrawType;
301 GrPathRendererChain::kColor_DrawType; 302 SkPath::FillType fillType = element->getPath().getFillType();
302 pr = this->getContext()->getPathRenderer(*path, stroke, fGpu, fa lse, type); 303 GrPathRenderer* pr = this->getContext()->getPathRenderer(
303 } 304 element->getPath(),
305 stroke, fGpu, false, type,
306 SkPath::ConvertToNonInverseFillType(fillType ));
304 if (NULL == pr) { 307 if (NULL == pr) {
305 return false; 308 return false;
306 } 309 }
307 pr->drawPath(element->getPath(), stroke, fGpu, element->isAA()); 310 pr->drawPath(stroke, fGpu, element->isAA());
308 break; 311 break;
309 } 312 }
310 default: 313 default:
311 // something is wrong if we're trying to draw an empty element. 314 // something is wrong if we're trying to draw an empty element.
312 GrCrash("Unexpected element type"); 315 GrCrash("Unexpected element type");
313 return false; 316 return false;
314 } 317 }
315 return true; 318 return true;
316 } 319 }
317 320
318 bool GrClipMaskManager::canStencilAndDrawElement(GrTexture* target, 321 bool GrClipMaskManager::canStencilAndDrawElement(GrTexture* target,
319 const SkClipStack::Element* ele ment, 322 const SkClipStack::Element* ele ment,
320 GrPathRenderer** pr) { 323 GrPathRenderer** pr) {
321 GrDrawState* drawState = fGpu->drawState(); 324 GrDrawState* drawState = fGpu->drawState();
322 drawState->setRenderTarget(target->asRenderTarget()); 325 drawState->setRenderTarget(target->asRenderTarget());
323 326
324 switch (element->getType()) { 327 switch (element->getType()) {
325 case Element::kRect_Type: 328 case Element::kRect_Type:
326 return true; 329 return true;
327 case Element::kPath_Type: { 330 case Element::kPath_Type: {
328 SkTCopyOnFirstWrite<SkPath> path(element->getPath());
329 if (path->isInverseFillType()) {
330 path.writable()->toggleInverseFillType();
331 }
332 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); 331 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
333 GrPathRendererChain::DrawType type = element->isAA() ? 332 GrPathRendererChain::DrawType type = element->isAA() ?
334 GrPathRendererChain::kStencilAndColorAntiAlias_DrawType : 333 GrPathRendererChain::kStencilAndColorAntiAlias_DrawType :
335 GrPathRendererChain::kStencilAndColor_DrawType; 334 GrPathRendererChain::kStencilAndColor_DrawType;
336 *pr = this->getContext()->getPathRenderer(*path, stroke, fGpu, false , type); 335 SkPath::FillType fillType = element->getPath().getFillType();
336 *pr = this->getContext()->getPathRenderer(element->getPath(),
337 stroke, fGpu, false, type,
338 SkPath::ConvertToNonInverseFi llType(fillType));
337 return NULL != *pr; 339 return NULL != *pr;
338 } 340 }
339 default: 341 default:
340 // something is wrong if we're trying to draw an empty element. 342 // something is wrong if we're trying to draw an empty element.
341 GrCrash("Unexpected element type"); 343 GrCrash("Unexpected element type");
342 return false; 344 return false;
343 } 345 }
344 } 346 }
345 347
346 void GrClipMaskManager::mergeMask(GrTexture* dstMask, 348 void GrClipMaskManager::mergeMask(GrTexture* dstMask,
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
517 kAlways_StencilFunc, 519 kAlways_StencilFunc,
518 0xffff, 520 0xffff,
519 0xffff, 521 0xffff,
520 0xffff); 522 0xffff);
521 drawState->setStencil(kStencilInElement); 523 drawState->setStencil(kStencilInElement);
522 setup_boolean_blendcoeffs(drawState, op); 524 setup_boolean_blendcoeffs(drawState, op);
523 } 525 }
524 526
525 drawState->setAlpha(invert ? 0x00 : 0xff); 527 drawState->setAlpha(invert ? 0x00 : 0xff);
526 528
527 if (!this->drawElement(dst, element, pr)) { 529 if (NULL != pr) {
528 fAACache.reset(); 530 this->drawFilledPath(dst, pr, element->isAA());
529 return NULL; 531 } else {
532 if (!this->drawElement(dst, element)) {
533 fAACache.reset();
534 return NULL;
535 }
530 } 536 }
531 537
532 if (useTemp) { 538 if (useTemp) {
533 // Now draw into the accumulator using the real operation and th e temp buffer as a 539 // Now draw into the accumulator using the real operation and th e temp buffer as a
534 // texture 540 // texture
535 this->mergeMask(result, 541 this->mergeMask(result,
536 temp.texture(), 542 temp.texture(),
537 op, 543 op,
538 maskSpaceIBounds, 544 maskSpaceIBounds,
539 maskSpaceElementIBounds); 545 maskSpaceElementIBounds);
540 } else { 546 } else {
541 // Draw to the exterior pixels (those with a zero stencil value) . 547 // Draw to the exterior pixels (those with a zero stencil value) .
542 drawState->setAlpha(invert ? 0xff : 0x00); 548 drawState->setAlpha(invert ? 0xff : 0x00);
543 GR_STATIC_CONST_SAME_STENCIL(kDrawOutsideElement, 549 GR_STATIC_CONST_SAME_STENCIL(kDrawOutsideElement,
544 kZero_StencilOp, 550 kZero_StencilOp,
545 kZero_StencilOp, 551 kZero_StencilOp,
546 kEqual_StencilFunc, 552 kEqual_StencilFunc,
547 0xffff, 553 0xffff,
548 0x0000, 554 0x0000,
549 0xffff); 555 0xffff);
550 drawState->setStencil(kDrawOutsideElement); 556 drawState->setStencil(kDrawOutsideElement);
551 fGpu->drawSimpleRect(clipSpaceIBounds); 557 fGpu->drawSimpleRect(clipSpaceIBounds);
552 drawState->disableStencil(); 558 drawState->disableStencil();
553 } 559 }
554 } else { 560 } else {
555 // all the remaining ops can just be directly draw into the accumula tion buffer 561 // all the remaining ops can just be directly drawn into the accumul ation buffer
556 drawState->setAlpha(0xff); 562 drawState->setAlpha(0xff);
557 setup_boolean_blendcoeffs(drawState, op); 563 setup_boolean_blendcoeffs(drawState, op);
558 this->drawElement(result, element); 564 this->drawElement(result, element);
559 } 565 }
560 } 566 }
561 567
562 fCurrClipMaskType = kAlpha_ClipMaskType; 568 fCurrClipMaskType = kAlpha_ClipMaskType;
563 return result; 569 return result;
564 } 570 }
565 571
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
632 638
633 // This will be used to determine whether the clip shape can be rend ered into the 639 // This will be used to determine whether the clip shape can be rend ered into the
634 // stencil with arbitrary stencil settings. 640 // stencil with arbitrary stencil settings.
635 GrPathRenderer::StencilSupport stencilSupport; 641 GrPathRenderer::StencilSupport stencilSupport;
636 642
637 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); 643 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
638 644
639 SkRegion::Op op = element->getOp(); 645 SkRegion::Op op = element->getOp();
640 646
641 GrPathRenderer* pr = NULL; 647 GrPathRenderer* pr = NULL;
642 SkTCopyOnFirstWrite<SkPath> clipPath;
643 if (Element::kRect_Type == element->getType()) { 648 if (Element::kRect_Type == element->getType()) {
644 stencilSupport = GrPathRenderer::kNoRestriction_StencilSupport; 649 stencilSupport = GrPathRenderer::kNoRestriction_StencilSupport;
645 fillInverted = false; 650 fillInverted = false;
646 } else { 651 } else {
647 SkASSERT(Element::kPath_Type == element->getType()); 652 SkASSERT(Element::kPath_Type == element->getType());
648 clipPath.init(element->getPath()); 653 fillInverted = element->getPath().isInverseFillType();
649 fillInverted = clipPath->isInverseFillType(); 654 SkPath::FillType fill = element->getPath().getFillType();
650 if (fillInverted) { 655 pr = this->getContext()->getPathRenderer(element->getPath(),
651 clipPath.writable()->toggleInverseFillType();
652 }
653 pr = this->getContext()->getPathRenderer(*clipPath,
654 stroke, 656 stroke,
655 fGpu, 657 fGpu,
656 false, 658 false,
657 GrPathRendererChain::kS tencilOnly_DrawType, 659 GrPathRendererChain::kS tencilOnly_DrawType,
660 SkPath::ConvertToNonInv erseFillType(fill),
658 &stencilSupport); 661 &stencilSupport);
659 if (NULL == pr) { 662 if (NULL == pr) {
660 return false; 663 return false;
661 } 664 }
662 } 665 }
663 666
664 int passes; 667 int passes;
665 GrStencilSettings stencilSettings[GrStencilSettings::kMaxStencilClip Passes]; 668 GrStencilSettings stencilSettings[GrStencilSettings::kMaxStencilClip Passes];
666 669
667 bool canRenderDirectToStencil = 670 bool canRenderDirectToStencil =
(...skipping 17 matching lines...) Expand all
685 kAlways_StencilFunc, 688 kAlways_StencilFunc,
686 0xffff, 689 0xffff,
687 0x0000, 690 0x0000,
688 0xffff); 691 0xffff);
689 SET_RANDOM_COLOR 692 SET_RANDOM_COLOR
690 if (Element::kRect_Type == element->getType()) { 693 if (Element::kRect_Type == element->getType()) {
691 *drawState->stencil() = gDrawToStencil; 694 *drawState->stencil() = gDrawToStencil;
692 fGpu->drawSimpleRect(element->getRect(), NULL); 695 fGpu->drawSimpleRect(element->getRect(), NULL);
693 } else { 696 } else {
694 SkASSERT(Element::kPath_Type == element->getType()); 697 SkASSERT(Element::kPath_Type == element->getType());
695 if (!clipPath->isEmpty()) { 698 if (NULL != pr) {
696 if (canRenderDirectToStencil) { 699 if (canRenderDirectToStencil) {
697 *drawState->stencil() = gDrawToStencil; 700 *drawState->stencil() = gDrawToStencil;
698 pr->drawPath(*clipPath, stroke, fGpu, false); 701 pr->drawPath(stroke, fGpu, false);
699 } else { 702 } else {
700 pr->stencilPath(*clipPath, stroke, fGpu); 703 pr->stencilPath(stroke, fGpu);
701 } 704 }
702 } 705 }
703 } 706 }
704 } 707 }
705 708
706 // now we modify the clip bit by rendering either the clip 709 // now we modify the clip bit by rendering either the clip
707 // element directly or a bounding rect of the entire clip. 710 // element directly or a bounding rect of the entire clip.
708 drawState->enableState(GrGpu::kModifyStencilClip_StateBit); 711 drawState->enableState(GrGpu::kModifyStencilClip_StateBit);
709 for (int p = 0; p < passes; ++p) { 712 for (int p = 0; p < passes; ++p) {
710 *drawState->stencil() = stencilSettings[p]; 713 *drawState->stencil() = stencilSettings[p];
711 if (canDrawDirectToClip) { 714 if (canDrawDirectToClip) {
712 if (Element::kRect_Type == element->getType()) { 715 if (Element::kRect_Type == element->getType()) {
713 SET_RANDOM_COLOR 716 SET_RANDOM_COLOR
714 fGpu->drawSimpleRect(element->getRect(), NULL); 717 fGpu->drawSimpleRect(element->getRect(), NULL);
715 } else { 718 } else {
716 SkASSERT(Element::kPath_Type == element->getType()); 719 SkASSERT(Element::kPath_Type == element->getType());
717 SET_RANDOM_COLOR 720 SET_RANDOM_COLOR
718 pr->drawPath(*clipPath, stroke, fGpu, false); 721 pr->drawPath(stroke, fGpu, false);
719 } 722 }
720 } else { 723 } else {
721 SET_RANDOM_COLOR 724 SET_RANDOM_COLOR
722 // The view matrix is setup to do clip space -> stencil spac e translation, so 725 // The view matrix is setup to do clip space -> stencil spac e translation, so
723 // draw rect in clip space. 726 // draw rect in clip space.
724 fGpu->drawSimpleRect(SkRect::MakeFromIRect(clipSpaceIBounds) , NULL); 727 fGpu->drawSimpleRect(SkRect::MakeFromIRect(clipSpaceIBounds) , NULL);
725 } 728 }
726 } 729 }
727 } 730 }
728 } 731 }
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after
1005 1008
1006 //////////////////////////////////////////////////////////////////////////////// 1009 ////////////////////////////////////////////////////////////////////////////////
1007 void GrClipMaskManager::releaseResources() { 1010 void GrClipMaskManager::releaseResources() {
1008 fAACache.releaseResources(); 1011 fAACache.releaseResources();
1009 } 1012 }
1010 1013
1011 void GrClipMaskManager::setGpu(GrGpu* gpu) { 1014 void GrClipMaskManager::setGpu(GrGpu* gpu) {
1012 fGpu = gpu; 1015 fGpu = gpu;
1013 fAACache.setContext(gpu->getContext()); 1016 fAACache.setContext(gpu->getContext());
1014 } 1017 }
OLDNEW
« no previous file with comments | « src/gpu/GrClipMaskManager.h ('k') | src/gpu/GrContext.cpp » ('j') | src/gpu/GrPathRenderer.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698