| OLD | NEW |
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2012 Google Inc. | 3 * Copyright 2012 Google Inc. |
| 4 * | 4 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 #include "GrAAConvexPathRenderer.h" | 9 #include "GrAAConvexPathRenderer.h" |
| 10 | 10 |
| (...skipping 500 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 511 static GrGeometryProcessor* Create() { | 511 static GrGeometryProcessor* Create() { |
| 512 GR_CREATE_STATIC_PROCESSOR(gQuadEdgeEffect, QuadEdgeEffect, ()); | 512 GR_CREATE_STATIC_PROCESSOR(gQuadEdgeEffect, QuadEdgeEffect, ()); |
| 513 gQuadEdgeEffect->ref(); | 513 gQuadEdgeEffect->ref(); |
| 514 return gQuadEdgeEffect; | 514 return gQuadEdgeEffect; |
| 515 } | 515 } |
| 516 | 516 |
| 517 virtual ~QuadEdgeEffect() {} | 517 virtual ~QuadEdgeEffect() {} |
| 518 | 518 |
| 519 static const char* Name() { return "QuadEdge"; } | 519 static const char* Name() { return "QuadEdge"; } |
| 520 | 520 |
| 521 const GrShaderVar& inQuadEdge() const { return fInQuadEdge; } | 521 const GrAttribute* inPosition() const { return fInPosition; } |
| 522 const GrAttribute* inQuadEdge() const { return fInQuadEdge; } |
| 522 | 523 |
| 523 virtual const GrBackendGeometryProcessorFactory& getFactory() const SK_OVERR
IDE { | 524 virtual const GrBackendGeometryProcessorFactory& getFactory() const SK_OVERR
IDE { |
| 524 return GrTBackendGeometryProcessorFactory<QuadEdgeEffect>::getInstance()
; | 525 return GrTBackendGeometryProcessorFactory<QuadEdgeEffect>::getInstance()
; |
| 525 } | 526 } |
| 526 | 527 |
| 527 class GLProcessor : public GrGLGeometryProcessor { | 528 class GLProcessor : public GrGLGeometryProcessor { |
| 528 public: | 529 public: |
| 529 GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&
) | 530 GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&
) |
| 530 : INHERITED (factory) {} | 531 : INHERITED (factory) {} |
| 531 | 532 |
| 532 virtual void emitCode(const EmitArgs& args) SK_OVERRIDE { | 533 virtual void emitCode(const EmitArgs& args) SK_OVERRIDE { |
| 534 const QuadEdgeEffect& qe = args.fGP.cast<QuadEdgeEffect>(); |
| 535 GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); |
| 536 |
| 533 GrGLVertToFrag v(kVec4f_GrSLType); | 537 GrGLVertToFrag v(kVec4f_GrSLType); |
| 534 args.fPB->addVarying("QuadEdge", &v); | 538 args.fPB->addVarying("QuadEdge", &v); |
| 539 vsBuilder->codeAppendf("%s = %s;", v.vsOut(), qe.inQuadEdge()->fName
); |
| 540 |
| 541 // setup coord outputs |
| 542 vsBuilder->codeAppendf("%s = %s;", vsBuilder->positionCoords(), qe.i
nPosition()->fName); |
| 543 vsBuilder->codeAppendf("%s = %s;", vsBuilder->localCoords(), qe.inPo
sition()->fName); |
| 544 |
| 545 // setup position varying |
| 546 vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPositi
on(), |
| 547 vsBuilder->uViewM(), qe.inPosition()->fName); |
| 535 | 548 |
| 536 GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilde
r(); | 549 GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilde
r(); |
| 537 | 550 |
| 538 SkAssertResult(fsBuilder->enableFeature( | 551 SkAssertResult(fsBuilder->enableFeature( |
| 539 GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature)
); | 552 GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature)
); |
| 540 fsBuilder->codeAppendf("float edgeAlpha;"); | 553 fsBuilder->codeAppendf("float edgeAlpha;"); |
| 541 | 554 |
| 542 // keep the derivative instructions outside the conditional | 555 // keep the derivative instructions outside the conditional |
| 543 fsBuilder->codeAppendf("vec2 duvdx = dFdx(%s.xy);", v.fsIn()); | 556 fsBuilder->codeAppendf("vec2 duvdx = dFdx(%s.xy);", v.fsIn()); |
| 544 fsBuilder->codeAppendf("vec2 duvdy = dFdy(%s.xy);", v.fsIn()); | 557 fsBuilder->codeAppendf("vec2 duvdy = dFdy(%s.xy);", v.fsIn()); |
| 545 fsBuilder->codeAppendf("if (%s.z > 0.0 && %s.w > 0.0) {", v.fsIn(),
v.fsIn()); | 558 fsBuilder->codeAppendf("if (%s.z > 0.0 && %s.w > 0.0) {", v.fsIn(),
v.fsIn()); |
| 546 // today we know z and w are in device space. We could use derivativ
es | 559 // today we know z and w are in device space. We could use derivativ
es |
| 547 fsBuilder->codeAppendf("edgeAlpha = min(min(%s.z, %s.w) + 0.5, 1.0);
", v.fsIn(), | 560 fsBuilder->codeAppendf("edgeAlpha = min(min(%s.z, %s.w) + 0.5, 1.0);
", v.fsIn(), |
| 548 v.fsIn()); | 561 v.fsIn()); |
| 549 fsBuilder->codeAppendf ("} else {"); | 562 fsBuilder->codeAppendf ("} else {"); |
| 550 fsBuilder->codeAppendf("vec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y," | 563 fsBuilder->codeAppendf("vec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y," |
| 551 " 2.0*%s.x*duvdy.x - duvdy.y);"
, | 564 " 2.0*%s.x*duvdy.x - duvdy.y);"
, |
| 552 v.fsIn(), v.fsIn()); | 565 v.fsIn(), v.fsIn()); |
| 553 fsBuilder->codeAppendf("edgeAlpha = (%s.x*%s.x - %s.y);", v.fsIn(),
v.fsIn(), | 566 fsBuilder->codeAppendf("edgeAlpha = (%s.x*%s.x - %s.y);", v.fsIn(),
v.fsIn(), |
| 554 v.fsIn()); | 567 v.fsIn()); |
| 555 fsBuilder->codeAppendf("edgeAlpha = " | 568 fsBuilder->codeAppendf("edgeAlpha = " |
| 556 "clamp(0.5 - edgeAlpha / length(gF), 0.0, 1.0
);}"); | 569 "clamp(0.5 - edgeAlpha / length(gF), 0.0, 1.0
);}"); |
| 557 | 570 |
| 558 | 571 fsBuilder->codeAppendf("%s = vec4(edgeAlpha);", args.fOutputCoverage
); |
| 559 fsBuilder->codeAppendf("%s = %s;", args.fOutput, | |
| 560 (GrGLSLExpr4(args.fInput) * GrGLSLExpr1("edge
Alpha")).c_str()); | |
| 561 | |
| 562 const GrShaderVar& inQuadEdge = args.fGP.cast<QuadEdgeEffect>().inQu
adEdge(); | |
| 563 GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); | |
| 564 vsBuilder->codeAppendf("\t%s = %s;\n", v.vsOut(), inQuadEdge.c_str()
); | |
| 565 | |
| 566 // setup position varying | |
| 567 vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPositi
on(), | |
| 568 vsBuilder->uViewM(), vsBuilder->inPosition())
; | |
| 569 } | 572 } |
| 570 | 573 |
| 571 static inline void GenKey(const GrProcessor&, const GrGLCaps&, GrProcess
orKeyBuilder*) {} | 574 static inline void GenKey(const GrProcessor&, const GrGLCaps&, GrProcess
orKeyBuilder*) {} |
| 572 | 575 |
| 573 virtual void setData(const GrGLProgramDataManager&, const GrProcessor&)
SK_OVERRIDE {} | 576 virtual void setData(const GrGLProgramDataManager&, const GrProcessor&)
SK_OVERRIDE {} |
| 574 | 577 |
| 575 private: | 578 private: |
| 576 typedef GrGLGeometryProcessor INHERITED; | 579 typedef GrGLGeometryProcessor INHERITED; |
| 577 }; | 580 }; |
| 578 | 581 |
| 579 private: | 582 private: |
| 580 QuadEdgeEffect() | 583 QuadEdgeEffect() { |
| 581 : fInQuadEdge(this->addVertexAttrib(GrShaderVar("inQuadEdge", | 584 fInPosition = &this->addVertexAttrib(GrAttribute("inPosition", kVec2f_Gr
VertexAttribType)); |
| 582 kVec4f_GrSLType, | 585 fInQuadEdge = &this->addVertexAttrib(GrAttribute("inQuadEdge", kVec4f_Gr
VertexAttribType)); |
| 583 GrShaderVar::kAttribute_
TypeModifier))) { | |
| 584 } | 586 } |
| 585 | 587 |
| 586 virtual bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE { | 588 virtual bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE { |
| 587 return true; | 589 return true; |
| 588 } | 590 } |
| 589 | 591 |
| 590 virtual void onComputeInvariantOutput(GrInvariantOutput* inout) const SK_OVE
RRIDE { | 592 virtual void onComputeInvariantOutput(GrInvariantOutput* inout) const SK_OVE
RRIDE { |
| 591 inout->mulByUnknownAlpha(); | 593 inout->mulByUnknownAlpha(); |
| 592 } | 594 } |
| 593 | 595 |
| 594 const GrShaderVar& fInQuadEdge; | 596 const GrAttribute* fInPosition; |
| 597 const GrAttribute* fInQuadEdge; |
| 595 | 598 |
| 596 GR_DECLARE_GEOMETRY_PROCESSOR_TEST; | 599 GR_DECLARE_GEOMETRY_PROCESSOR_TEST; |
| 597 | 600 |
| 598 typedef GrFragmentProcessor INHERITED; | 601 typedef GrFragmentProcessor INHERITED; |
| 599 }; | 602 }; |
| 600 | 603 |
| 601 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(QuadEdgeEffect); | 604 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(QuadEdgeEffect); |
| 602 | 605 |
| 603 GrGeometryProcessor* QuadEdgeEffect::TestCreate(SkRandom* random, | 606 GrGeometryProcessor* QuadEdgeEffect::TestCreate(SkRandom* random, |
| 604 GrContext*, | 607 GrContext*, |
| 605 const GrDrawTargetCaps& caps, | 608 const GrDrawTargetCaps& caps, |
| 606 GrTexture*[]) { | 609 GrTexture*[]) { |
| 607 // Doesn't work without derivative instructions. | 610 // Doesn't work without derivative instructions. |
| 608 return caps.shaderDerivativeSupport() ? QuadEdgeEffect::Create() : NULL; | 611 return caps.shaderDerivativeSupport() ? QuadEdgeEffect::Create() : NULL; |
| 609 } | 612 } |
| 610 | 613 |
| 611 /////////////////////////////////////////////////////////////////////////////// | 614 /////////////////////////////////////////////////////////////////////////////// |
| 612 | 615 |
| 613 bool GrAAConvexPathRenderer::canDrawPath(const GrDrawTarget* target, | 616 bool GrAAConvexPathRenderer::canDrawPath(const GrDrawTarget* target, |
| 614 const GrDrawState*, | 617 const GrDrawState*, |
| 615 const SkPath& path, | 618 const SkPath& path, |
| 616 const SkStrokeRec& stroke, | 619 const SkStrokeRec& stroke, |
| 617 bool antiAlias) const { | 620 bool antiAlias) const { |
| 618 return (target->caps()->shaderDerivativeSupport() && antiAlias && | 621 return (target->caps()->shaderDerivativeSupport() && antiAlias && |
| 619 stroke.isFillStyle() && !path.isInverseFillType() && path.isConvex()
); | 622 stroke.isFillStyle() && !path.isInverseFillType() && path.isConvex()
); |
| 620 } | 623 } |
| 621 | 624 |
| 622 namespace { | |
| 623 | |
| 624 // position + edge | |
| 625 extern const GrVertexAttrib gPathAttribs[] = { | |
| 626 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding
}, | |
| 627 {kVec4f_GrVertexAttribType, sizeof(SkPoint), kGeometryProcessor_GrVertexAttr
ibBinding} | |
| 628 }; | |
| 629 | |
| 630 }; | |
| 631 | |
| 632 bool GrAAConvexPathRenderer::onDrawPath(GrDrawTarget* target, | 625 bool GrAAConvexPathRenderer::onDrawPath(GrDrawTarget* target, |
| 633 GrDrawState* drawState, | 626 GrDrawState* drawState, |
| 634 const SkPath& origPath, | 627 const SkPath& origPath, |
| 635 const SkStrokeRec&, | 628 const SkStrokeRec&, |
| 636 bool antiAlias) { | 629 bool antiAlias) { |
| 637 | 630 |
| 638 const SkPath* path = &origPath; | 631 const SkPath* path = &origPath; |
| 639 if (path->isEmpty()) { | 632 if (path->isEmpty()) { |
| 640 return true; | 633 return true; |
| 641 } | 634 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 671 // We can't simply use the path bounds because we may degenerate cubics to q
uads which produces | 664 // We can't simply use the path bounds because we may degenerate cubics to q
uads which produces |
| 672 // new control points outside the original convex hull. | 665 // new control points outside the original convex hull. |
| 673 SkRect devBounds; | 666 SkRect devBounds; |
| 674 if (!get_segments(*path, viewMatrix, &segments, &fanPt, &vCount, &iCount, &d
evBounds)) { | 667 if (!get_segments(*path, viewMatrix, &segments, &fanPt, &vCount, &iCount, &d
evBounds)) { |
| 675 return false; | 668 return false; |
| 676 } | 669 } |
| 677 | 670 |
| 678 // Our computed verts should all be within one pixel of the segment control
points. | 671 // Our computed verts should all be within one pixel of the segment control
points. |
| 679 devBounds.outset(SK_Scalar1, SK_Scalar1); | 672 devBounds.outset(SK_Scalar1, SK_Scalar1); |
| 680 | 673 |
| 681 drawState->setVertexAttribs<gPathAttribs>(SK_ARRAY_COUNT(gPathAttribs), size
of(QuadVertex)); | |
| 682 | |
| 683 GrGeometryProcessor* quadProcessor = QuadEdgeEffect::Create(); | 674 GrGeometryProcessor* quadProcessor = QuadEdgeEffect::Create(); |
| 684 drawState->setGeometryProcessor(quadProcessor)->unref(); | 675 drawState->setGeometryProcessor(quadProcessor)->unref(); |
| 685 | 676 |
| 686 GrDrawTarget::AutoReleaseGeometry arg(target, vCount, drawState->getVertexSt
ride(), iCount); | 677 GrDrawTarget::AutoReleaseGeometry arg(target, vCount, quadProcessor->getVert
exStride(), iCount); |
| 678 SkASSERT(quadProcessor->getVertexStride() == sizeof(QuadVertex)); |
| 687 if (!arg.succeeded()) { | 679 if (!arg.succeeded()) { |
| 688 return false; | 680 return false; |
| 689 } | 681 } |
| 690 verts = reinterpret_cast<QuadVertex*>(arg.vertices()); | 682 verts = reinterpret_cast<QuadVertex*>(arg.vertices()); |
| 691 idxs = reinterpret_cast<uint16_t*>(arg.indices()); | 683 idxs = reinterpret_cast<uint16_t*>(arg.indices()); |
| 692 | 684 |
| 693 SkSTArray<kPreallocDrawCnt, Draw, true> draws; | 685 SkSTArray<kPreallocDrawCnt, Draw, true> draws; |
| 694 create_vertices(segments, fanPt, &draws, verts, idxs); | 686 create_vertices(segments, fanPt, &draws, verts, idxs); |
| 695 | 687 |
| 696 // Check devBounds | 688 // Check devBounds |
| (...skipping 16 matching lines...) Expand all Loading... |
| 713 vOffset, // start vertex | 705 vOffset, // start vertex |
| 714 0, // start index | 706 0, // start index |
| 715 draw.fVertexCnt, | 707 draw.fVertexCnt, |
| 716 draw.fIndexCnt, | 708 draw.fIndexCnt, |
| 717 &devBounds); | 709 &devBounds); |
| 718 vOffset += draw.fVertexCnt; | 710 vOffset += draw.fVertexCnt; |
| 719 } | 711 } |
| 720 | 712 |
| 721 return true; | 713 return true; |
| 722 } | 714 } |
| OLD | NEW |