OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 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 "GrAAHairLinePathRenderer.h" | 9 #include "GrAAHairLinePathRenderer.h" |
10 | 10 |
11 #include "GrContext.h" | 11 #include "GrContext.h" |
12 #include "GrDrawState.h" | 12 #include "GrDrawState.h" |
13 #include "GrDrawTargetCaps.h" | 13 #include "GrDrawTargetCaps.h" |
| 14 #include "GrEffect.h" |
14 #include "GrGpu.h" | 15 #include "GrGpu.h" |
15 #include "GrIndexBuffer.h" | 16 #include "GrIndexBuffer.h" |
16 #include "GrPathUtils.h" | 17 #include "GrPathUtils.h" |
| 18 #include "GrTBackendEffectFactory.h" |
17 #include "SkGeometry.h" | 19 #include "SkGeometry.h" |
18 #include "SkStroke.h" | 20 #include "SkStroke.h" |
19 #include "SkTemplates.h" | 21 #include "SkTemplates.h" |
20 | 22 |
21 #include "effects/GrEdgeEffect.h" | 23 #include "gl/GrGLEffect.h" |
| 24 #include "gl/GrGLSL.h" |
22 | 25 |
23 namespace { | 26 namespace { |
24 // quadratics are rendered as 5-sided polys in order to bound the | 27 // quadratics are rendered as 5-sided polys in order to bound the |
25 // AA stroke around the center-curve. See comments in push_quad_index_buffer and | 28 // AA stroke around the center-curve. See comments in push_quad_index_buffer and |
26 // bloat_quad. | 29 // bloat_quad. |
27 static const int kVertsPerQuad = 5; | 30 static const int kVertsPerQuad = 5; |
28 static const int kIdxsPerQuad = 9; | 31 static const int kIdxsPerQuad = 9; |
29 | 32 |
30 static const int kVertsPerLineSeg = 4; | 33 static const int kVertsPerLineSeg = 4; |
31 static const int kIdxsPerLineSeg = 6; | 34 static const int kIdxsPerLineSeg = 6; |
(...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
485 (*vert)[1].fPos.set(SK_ScalarMax, SK_ScalarMax); | 488 (*vert)[1].fPos.set(SK_ScalarMax, SK_ScalarMax); |
486 (*vert)[2].fPos.set(SK_ScalarMax, SK_ScalarMax); | 489 (*vert)[2].fPos.set(SK_ScalarMax, SK_ScalarMax); |
487 (*vert)[3].fPos.set(SK_ScalarMax, SK_ScalarMax); | 490 (*vert)[3].fPos.set(SK_ScalarMax, SK_ScalarMax); |
488 } | 491 } |
489 | 492 |
490 *vert += kVertsPerLineSeg; | 493 *vert += kVertsPerLineSeg; |
491 } | 494 } |
492 | 495 |
493 } | 496 } |
494 | 497 |
| 498 /////////////////////////////////////////////////////////////////////////////// |
| 499 |
| 500 /** |
| 501 * The output of this effect is a hairline edge for quadratics. |
| 502 * Quadratic specified by 0=u^2-v canonical coords. u and v are the first |
| 503 * two components of the vertex attribute. Uses unsigned distance. |
| 504 * Coverage is min(0, 1-distance). 3rd & 4th component unused. |
| 505 * Requires shader derivative instruction support. |
| 506 */ |
| 507 class HairQuadEdgeEffect : public GrEffect { |
| 508 public: |
| 509 |
| 510 static GrEffectRef* Create() { |
| 511 // we go through this so we only have one copy of each effect |
| 512 static GrEffectRef* gHairQuadEdgeEffectRef = |
| 513 CreateEffectRef(AutoEffectUnref(SkNEW(HairQuadEdgeEffect))); |
| 514 static SkAutoTUnref<GrEffectRef> gUnref(gHairQuadEdgeEffectRef); |
| 515 |
| 516 gHairQuadEdgeEffectRef->ref(); |
| 517 return gHairQuadEdgeEffectRef; |
| 518 } |
| 519 |
| 520 virtual ~HairQuadEdgeEffect() {} |
| 521 |
| 522 static const char* Name() { return "HairQuadEdge"; } |
| 523 |
| 524 virtual void getConstantColorComponents(GrColor* color, |
| 525 uint32_t* validFlags) const SK_OVERR
IDE { |
| 526 *validFlags = 0; |
| 527 } |
| 528 |
| 529 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { |
| 530 return GrTBackendEffectFactory<HairQuadEdgeEffect>::getInstance(); |
| 531 } |
| 532 |
| 533 class GLEffect : public GrGLEffect { |
| 534 public: |
| 535 GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) |
| 536 : INHERITED (factory) {} |
| 537 |
| 538 virtual void emitCode(GrGLShaderBuilder* builder, |
| 539 const GrDrawEffect& drawEffect, |
| 540 EffectKey key, |
| 541 const char* outputColor, |
| 542 const char* inputColor, |
| 543 const TextureSamplerArray& samplers) SK_OVERRIDE { |
| 544 const char *vsName, *fsName; |
| 545 const SkString* attrName = |
| 546 builder->getEffectAttributeName(drawEffect.getVertexAttribIndice
s()[0]); |
| 547 builder->fsCodeAppendf("\t\tfloat edgeAlpha;\n"); |
| 548 |
| 549 SkAssertResult(builder->enableFeature( |
| 550 GrGLShaderBuilder::kStandardDeriva
tives_GLSLFeature)); |
| 551 builder->addVarying(kVec4f_GrSLType, "HairQuadEdge", &vsName, &fsNam
e); |
| 552 |
| 553 builder->fsCodeAppendf("\t\tvec2 duvdx = dFdx(%s.xy);\n", fsName); |
| 554 builder->fsCodeAppendf("\t\tvec2 duvdy = dFdy(%s.xy);\n", fsName); |
| 555 builder->fsCodeAppendf("\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.
y,\n" |
| 556 "\t\t 2.0*%s.x*duvdy.x - duvdy.
y);\n", |
| 557 fsName, fsName); |
| 558 builder->fsCodeAppendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsNa
me, fsName, |
| 559 fsName); |
| 560 builder->fsCodeAppend("\t\tedgeAlpha = sqrt(edgeAlpha*edgeAlpha / do
t(gF, gF));\n"); |
| 561 builder->fsCodeAppend("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n"
); |
| 562 |
| 563 SkString modulate; |
| 564 GrGLSLModulate4f(&modulate, inputColor, "edgeAlpha"); |
| 565 builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str()
); |
| 566 |
| 567 builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str()); |
| 568 } |
| 569 |
| 570 static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrG
LCaps&) { |
| 571 return 0x0; |
| 572 } |
| 573 |
| 574 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_
OVERRIDE {} |
| 575 |
| 576 private: |
| 577 typedef GrGLEffect INHERITED; |
| 578 }; |
| 579 |
| 580 private: |
| 581 HairQuadEdgeEffect() { |
| 582 this->addVertexAttrib(kVec4f_GrSLType); |
| 583 } |
| 584 |
| 585 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { |
| 586 return true; |
| 587 } |
| 588 |
| 589 GR_DECLARE_EFFECT_TEST; |
| 590 |
| 591 typedef GrEffect INHERITED; |
| 592 }; |
| 593 |
| 594 GR_DEFINE_EFFECT_TEST(HairQuadEdgeEffect); |
| 595 |
| 596 GrEffectRef* HairQuadEdgeEffect::TestCreate(SkMWCRandom* random, |
| 597 GrContext*, |
| 598 const GrDrawTargetCaps& caps, |
| 599 GrTexture*[]) { |
| 600 // Doesn't work without derivative instructions. |
| 601 return caps.shaderDerivativeSupport() ? HairQuadEdgeEffect::Create() : NULL;
} |
| 602 |
| 603 /////////////////////////////////////////////////////////////////////////////// |
| 604 |
| 605 /** |
| 606 * The output of this effect is a 1-pixel wide line. |
| 607 * Input is 2D implicit device coord line eq (a*x + b*y +c = 0). 4th component u
nused. |
| 608 */ |
| 609 class HairLineEdgeEffect : public GrEffect { |
| 610 public: |
| 611 |
| 612 static GrEffectRef* Create() { |
| 613 // we go through this so we only have one copy of each effect |
| 614 static GrEffectRef* gHairLineEdgeEffectRef = |
| 615 CreateEffectRef(AutoEffectUnref(SkNEW(HairLineEdgeEffect))); |
| 616 static SkAutoTUnref<GrEffectRef> gUnref(gHairLineEdgeEffectRef); |
| 617 |
| 618 gHairLineEdgeEffectRef->ref(); |
| 619 return gHairLineEdgeEffectRef; |
| 620 } |
| 621 |
| 622 virtual ~HairLineEdgeEffect() {} |
| 623 |
| 624 static const char* Name() { return "HairLineEdge"; } |
| 625 |
| 626 virtual void getConstantColorComponents(GrColor* color, |
| 627 uint32_t* validFlags) const SK_OVERR
IDE { |
| 628 *validFlags = 0; |
| 629 } |
| 630 |
| 631 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { |
| 632 return GrTBackendEffectFactory<HairLineEdgeEffect>::getInstance(); |
| 633 } |
| 634 |
| 635 class GLEffect : public GrGLEffect { |
| 636 public: |
| 637 GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) |
| 638 : INHERITED (factory) {} |
| 639 |
| 640 virtual void emitCode(GrGLShaderBuilder* builder, |
| 641 const GrDrawEffect& drawEffect, |
| 642 EffectKey key, |
| 643 const char* outputColor, |
| 644 const char* inputColor, |
| 645 const TextureSamplerArray& samplers) SK_OVERRIDE { |
| 646 const char *vsName, *fsName; |
| 647 const SkString* attrName = |
| 648 builder->getEffectAttributeName(drawEffect.getVertexAttribIndice
s()[0]); |
| 649 builder->fsCodeAppendf("\t\tfloat edgeAlpha;\n"); |
| 650 |
| 651 builder->addVarying(kVec4f_GrSLType, "HairLineEdge", &vsName, &fsNam
e); |
| 652 |
| 653 builder->fsCodeAppendf("\t\tedgeAlpha = abs(dot(vec3(%s.xy,1), %s.xy
z));\n", |
| 654 builder->fragmentPosition(), fsName); |
| 655 builder->fsCodeAppendf("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n
"); |
| 656 |
| 657 SkString modulate; |
| 658 GrGLSLModulate4f(&modulate, inputColor, "edgeAlpha"); |
| 659 builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str()
); |
| 660 |
| 661 builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str()); |
| 662 } |
| 663 |
| 664 static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrG
LCaps&) { |
| 665 return 0x0; |
| 666 } |
| 667 |
| 668 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_
OVERRIDE {} |
| 669 |
| 670 private: |
| 671 typedef GrGLEffect INHERITED; |
| 672 }; |
| 673 |
| 674 private: |
| 675 HairLineEdgeEffect() { |
| 676 this->addVertexAttrib(kVec4f_GrSLType); |
| 677 } |
| 678 |
| 679 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { |
| 680 return true; |
| 681 } |
| 682 |
| 683 GR_DECLARE_EFFECT_TEST; |
| 684 |
| 685 typedef GrEffect INHERITED; |
| 686 }; |
| 687 |
| 688 GR_DEFINE_EFFECT_TEST(HairLineEdgeEffect); |
| 689 |
| 690 GrEffectRef* HairLineEdgeEffect::TestCreate(SkMWCRandom* random, |
| 691 GrContext*, |
| 692 const GrDrawTargetCaps& caps, |
| 693 GrTexture*[]) { |
| 694 return HairLineEdgeEffect::Create(); |
| 695 } |
| 696 |
| 697 /////////////////////////////////////////////////////////////////////////////// |
| 698 |
495 bool GrAAHairLinePathRenderer::createGeom( | 699 bool GrAAHairLinePathRenderer::createGeom( |
496 const SkPath& path, | 700 const SkPath& path, |
497 GrDrawTarget* target, | 701 GrDrawTarget* target, |
498 int* lineCnt, | 702 int* lineCnt, |
499 int* quadCnt, | 703 int* quadCnt, |
500 GrDrawTarget::AutoReleaseGeometry* arg) { | 704 GrDrawTarget::AutoReleaseGeometry* arg) { |
501 GrDrawState* drawState = target->drawState(); | 705 GrDrawState* drawState = target->drawState(); |
502 int rtHeight = drawState->getRenderTarget()->height(); | 706 int rtHeight = drawState->getRenderTarget()->height(); |
503 | 707 |
504 GrIRect devClipBounds; | 708 GrIRect devClipBounds; |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
604 // when we have a mix | 808 // when we have a mix |
605 | 809 |
606 enum { | 810 enum { |
607 // the edge effects share this stage with glyph rendering | 811 // the edge effects share this stage with glyph rendering |
608 // (kGlyphMaskStage in GrTextContext) && SW path rendering | 812 // (kGlyphMaskStage in GrTextContext) && SW path rendering |
609 // (kPathMaskStage in GrSWMaskHelper) | 813 // (kPathMaskStage in GrSWMaskHelper) |
610 kEdgeEffectStage = GrPaint::kTotalStages, | 814 kEdgeEffectStage = GrPaint::kTotalStages, |
611 }; | 815 }; |
612 static const int kEdgeAttrIndex = 1; | 816 static const int kEdgeAttrIndex = 1; |
613 | 817 |
614 GrEffectRef* hairLineEffect = GrEdgeEffect::Create(GrEdgeEffect::kHairLine_E
dgeType); | 818 GrEffectRef* hairLineEffect = HairLineEdgeEffect::Create(); |
615 GrEffectRef* hairQuadEffect = GrEdgeEffect::Create(GrEdgeEffect::kHairQuad_E
dgeType); | 819 GrEffectRef* hairQuadEffect = HairQuadEdgeEffect::Create(); |
616 | 820 |
617 target->setIndexSourceToBuffer(fLinesIndexBuffer); | 821 target->setIndexSourceToBuffer(fLinesIndexBuffer); |
618 int lines = 0; | 822 int lines = 0; |
619 int nBufLines = fLinesIndexBuffer->maxQuads(); | 823 int nBufLines = fLinesIndexBuffer->maxQuads(); |
620 drawState->setEffect(kEdgeEffectStage, hairLineEffect, kEdgeAttrIndex)->unre
f(); | 824 drawState->setEffect(kEdgeEffectStage, hairLineEffect, kEdgeAttrIndex)->unre
f(); |
621 while (lines < lineCnt) { | 825 while (lines < lineCnt) { |
622 int n = GrMin(lineCnt - lines, nBufLines); | 826 int n = GrMin(lineCnt - lines, nBufLines); |
623 target->drawIndexed(kTriangles_GrPrimitiveType, | 827 target->drawIndexed(kTriangles_GrPrimitiveType, |
624 kVertsPerLineSeg*lines, // startV | 828 kVertsPerLineSeg*lines, // startV |
625 0, // startI | 829 0, // startI |
(...skipping 10 matching lines...) Expand all Loading... |
636 target->drawIndexed(kTriangles_GrPrimitiveType, | 840 target->drawIndexed(kTriangles_GrPrimitiveType, |
637 4 * lineCnt + kVertsPerQuad*quads, // startV | 841 4 * lineCnt + kVertsPerQuad*quads, // startV |
638 0, // startI | 842 0, // startI |
639 kVertsPerQuad*n, // vCount | 843 kVertsPerQuad*n, // vCount |
640 kIdxsPerQuad*n); // iCount | 844 kIdxsPerQuad*n); // iCount |
641 quads += n; | 845 quads += n; |
642 } | 846 } |
643 | 847 |
644 return true; | 848 return true; |
645 } | 849 } |
OLD | NEW |