Chromium Code Reviews| 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. | |
|
robertphillips
2013/03/31 22:59:08
The quadratic is?
| |
| 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 GrAssert(builder->ctxInfo().caps()->shaderDerivativeSupport()); | |
| 550 builder->addVarying(kVec4f_GrSLType, "HairQuadEdge", &vsName, &fsNam e); | |
| 551 | |
| 552 builder->fsCodeAppendf("\t\tvec2 duvdx = dFdx(%s.xy);\n", fsName); | |
| 553 builder->fsCodeAppendf("\t\tvec2 duvdy = dFdy(%s.xy);\n", fsName); | |
| 554 builder->fsCodeAppendf("\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx. y,\n" | |
| 555 "\t\t 2.0*%s.x*duvdy.x - duvdy. y);\n", | |
| 556 fsName, fsName); | |
| 557 builder->fsCodeAppendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsNa me, fsName, | |
| 558 fsName); | |
| 559 builder->fsCodeAppend("\t\tedgeAlpha = sqrt(edgeAlpha*edgeAlpha / do t(gF, gF));\n"); | |
| 560 builder->fsCodeAppend("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n" ); | |
| 561 if (kES2_GrGLBinding == builder->ctxInfo().binding()) { | |
| 562 builder->fHeader.append("#extension GL_OES_standard_derivatives: enable\n"); | |
| 563 } | |
| 564 | |
| 565 SkString modulate; | |
| 566 GrGLSLModulate4f(&modulate, inputColor, "edgeAlpha"); | |
| 567 builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str() ); | |
| 568 | |
| 569 builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str()); | |
| 570 } | |
| 571 | |
| 572 static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrG LCaps&) { | |
| 573 return 0x0; | |
| 574 } | |
| 575 | |
| 576 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_ OVERRIDE {} | |
| 577 | |
| 578 private: | |
| 579 typedef GrGLEffect INHERITED; | |
| 580 }; | |
| 581 | |
| 582 private: | |
| 583 HairQuadEdgeEffect() { | |
|
robertphillips
2013/03/31 22:59:08
Could we make this a kVec2f_GrSLType?
| |
| 584 this->addVertexAttrib(kVec4f_GrSLType); | |
| 585 } | |
| 586 | |
| 587 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { | |
| 588 return true; | |
| 589 } | |
| 590 | |
| 591 GR_DECLARE_EFFECT_TEST; | |
| 592 | |
| 593 typedef GrEffect INHERITED; | |
| 594 }; | |
| 595 | |
| 596 GR_DEFINE_EFFECT_TEST(HairQuadEdgeEffect); | |
| 597 | |
| 598 GrEffectRef* HairQuadEdgeEffect::TestCreate(SkMWCRandom* random, | |
| 599 GrContext*, | |
| 600 const GrDrawTargetCaps& caps, | |
| 601 GrTexture*[]) { | |
| 602 // Doesn't work without derivative instructions. | |
| 603 GrAssert(caps.shaderDerivativeSupport()); | |
| 604 return HairQuadEdgeEffect::Create(); | |
| 605 } | |
| 606 | |
| 607 /////////////////////////////////////////////////////////////////////////////// | |
| 608 | |
| 609 /** | |
| 610 * The output of this effect is a 1-pixel wide line. | |
| 611 * Input is 2D implicit device coord line eq (a*x + b*y +c = 0). 4th component u nused. | |
| 612 */ | |
| 613 class HairLineEdgeEffect : public GrEffect { | |
| 614 public: | |
| 615 | |
| 616 static GrEffectRef* Create() { | |
| 617 // we go through this so we only have one copy of each effect | |
| 618 static GrEffectRef* gHairLineEdgeEffectRef = | |
| 619 CreateEffectRef(AutoEffectUnref(SkNEW(HairLineEdgeEffect))); | |
| 620 static SkAutoTUnref<GrEffectRef> gUnref(gHairLineEdgeEffectRef); | |
| 621 | |
| 622 gHairLineEdgeEffectRef->ref(); | |
| 623 return gHairLineEdgeEffectRef; | |
| 624 } | |
| 625 | |
| 626 virtual ~HairLineEdgeEffect() {} | |
| 627 | |
| 628 static const char* Name() { return "HairLineEdge"; } | |
| 629 | |
| 630 virtual void getConstantColorComponents(GrColor* color, | |
| 631 uint32_t* validFlags) const SK_OVERR IDE { | |
| 632 *validFlags = 0; | |
| 633 } | |
| 634 | |
| 635 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { | |
| 636 return GrTBackendEffectFactory<HairLineEdgeEffect>::getInstance(); | |
| 637 } | |
| 638 | |
| 639 class GLEffect : public GrGLEffect { | |
| 640 public: | |
| 641 GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) | |
| 642 : INHERITED (factory) {} | |
| 643 | |
| 644 virtual void emitCode(GrGLShaderBuilder* builder, | |
| 645 const GrDrawEffect& drawEffect, | |
| 646 EffectKey key, | |
| 647 const char* outputColor, | |
| 648 const char* inputColor, | |
| 649 const TextureSamplerArray& samplers) SK_OVERRIDE { | |
| 650 const char *vsName, *fsName; | |
| 651 const SkString* attrName = | |
| 652 builder->getEffectAttributeName(drawEffect.getVertexAttribIndice s()[0]); | |
| 653 builder->fsCodeAppendf("\t\tfloat edgeAlpha;\n"); | |
| 654 | |
| 655 builder->addVarying(kVec4f_GrSLType, "HairLineEdge", &vsName, &fsNam e); | |
| 656 | |
| 657 builder->fsCodeAppendf("\t\tedgeAlpha = abs(dot(vec3(%s.xy,1), %s.xy z));\n", | |
| 658 builder->fragmentPosition(), fsName); | |
| 659 builder->fsCodeAppendf("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n "); | |
| 660 | |
| 661 SkString modulate; | |
| 662 GrGLSLModulate4f(&modulate, inputColor, "edgeAlpha"); | |
| 663 builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str() ); | |
| 664 | |
| 665 builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str()); | |
| 666 } | |
| 667 | |
| 668 static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrG LCaps&) { | |
| 669 return 0x0; | |
| 670 } | |
| 671 | |
| 672 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_ OVERRIDE {} | |
| 673 | |
| 674 private: | |
| 675 typedef GrGLEffect INHERITED; | |
| 676 }; | |
| 677 | |
| 678 private: | |
| 679 HairLineEdgeEffect() { | |
| 680 this->addVertexAttrib(kVec4f_GrSLType); | |
| 681 } | |
| 682 | |
| 683 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { | |
| 684 return true; | |
| 685 } | |
| 686 | |
| 687 GR_DECLARE_EFFECT_TEST; | |
| 688 | |
| 689 typedef GrEffect INHERITED; | |
| 690 }; | |
| 691 | |
| 692 GR_DEFINE_EFFECT_TEST(HairLineEdgeEffect); | |
| 693 | |
| 694 GrEffectRef* HairLineEdgeEffect::TestCreate(SkMWCRandom* random, | |
| 695 GrContext*, | |
| 696 const GrDrawTargetCaps& caps, | |
| 697 GrTexture*[]) { | |
| 698 return HairLineEdgeEffect::Create(); | |
| 699 } | |
| 700 | |
| 701 /////////////////////////////////////////////////////////////////////////////// | |
| 702 | |
| 495 bool GrAAHairLinePathRenderer::createGeom( | 703 bool GrAAHairLinePathRenderer::createGeom( |
| 496 const SkPath& path, | 704 const SkPath& path, |
| 497 GrDrawTarget* target, | 705 GrDrawTarget* target, |
| 498 int* lineCnt, | 706 int* lineCnt, |
| 499 int* quadCnt, | 707 int* quadCnt, |
| 500 GrDrawTarget::AutoReleaseGeometry* arg) { | 708 GrDrawTarget::AutoReleaseGeometry* arg) { |
| 501 GrDrawState* drawState = target->drawState(); | 709 GrDrawState* drawState = target->drawState(); |
| 502 int rtHeight = drawState->getRenderTarget()->height(); | 710 int rtHeight = drawState->getRenderTarget()->height(); |
| 503 | 711 |
| 504 GrIRect devClipBounds; | 712 GrIRect devClipBounds; |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 606 // when we have a mix | 814 // when we have a mix |
| 607 | 815 |
| 608 enum { | 816 enum { |
| 609 // the edge effects share this stage with glyph rendering | 817 // the edge effects share this stage with glyph rendering |
| 610 // (kGlyphMaskStage in GrTextContext) && SW path rendering | 818 // (kGlyphMaskStage in GrTextContext) && SW path rendering |
| 611 // (kPathMaskStage in GrSWMaskHelper) | 819 // (kPathMaskStage in GrSWMaskHelper) |
| 612 kEdgeEffectStage = GrPaint::kTotalStages, | 820 kEdgeEffectStage = GrPaint::kTotalStages, |
| 613 }; | 821 }; |
| 614 static const int kEdgeAttrIndex = 1; | 822 static const int kEdgeAttrIndex = 1; |
| 615 | 823 |
| 616 GrEffectRef* hairLineEffect = GrEdgeEffect::Create(GrEdgeEffect::kHairLine_E dgeType); | 824 GrEffectRef* hairLineEffect = HairLineEdgeEffect::Create(); |
| 617 GrEffectRef* hairQuadEffect = GrEdgeEffect::Create(GrEdgeEffect::kHairQuad_E dgeType); | 825 GrEffectRef* hairQuadEffect = HairQuadEdgeEffect::Create(); |
| 618 | 826 |
| 619 target->setIndexSourceToBuffer(fLinesIndexBuffer); | 827 target->setIndexSourceToBuffer(fLinesIndexBuffer); |
| 620 int lines = 0; | 828 int lines = 0; |
| 621 int nBufLines = fLinesIndexBuffer->maxQuads(); | 829 int nBufLines = fLinesIndexBuffer->maxQuads(); |
| 622 drawState->setEffect(kEdgeEffectStage, hairLineEffect, kEdgeAttrIndex)->unre f(); | 830 drawState->setEffect(kEdgeEffectStage, hairLineEffect, kEdgeAttrIndex)->unre f(); |
| 623 while (lines < lineCnt) { | 831 while (lines < lineCnt) { |
| 624 int n = GrMin(lineCnt - lines, nBufLines); | 832 int n = GrMin(lineCnt - lines, nBufLines); |
| 625 target->drawIndexed(kTriangles_GrPrimitiveType, | 833 target->drawIndexed(kTriangles_GrPrimitiveType, |
| 626 kVertsPerLineSeg*lines, // startV | 834 kVertsPerLineSeg*lines, // startV |
| 627 0, // startI | 835 0, // startI |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 638 target->drawIndexed(kTriangles_GrPrimitiveType, | 846 target->drawIndexed(kTriangles_GrPrimitiveType, |
| 639 4 * lineCnt + kVertsPerQuad*quads, // startV | 847 4 * lineCnt + kVertsPerQuad*quads, // startV |
| 640 0, // startI | 848 0, // startI |
| 641 kVertsPerQuad*n, // vCount | 849 kVertsPerQuad*n, // vCount |
| 642 kIdxsPerQuad*n); // iCount | 850 kIdxsPerQuad*n); // iCount |
| 643 quads += n; | 851 quads += n; |
| 644 } | 852 } |
| 645 | 853 |
| 646 return true; | 854 return true; |
| 647 } | 855 } |
| OLD | NEW |