OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright 2013 Google Inc. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license that can be | |
5 * found in the LICENSE file. | |
6 */ | |
7 | |
8 #include "GrEdgeEffect.h" | |
9 #include "gl/GrGLEffect.h" | |
10 #include "gl/GrGLSL.h" | |
11 #include "GrTBackendEffectFactory.h" | |
12 | |
13 class GrGLEdgeEffect : public GrGLEffect { | |
14 public: | |
15 GrGLEdgeEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) | |
16 : INHERITED (factory) {} | |
17 | |
18 virtual void emitCode(GrGLShaderBuilder* builder, | |
19 const GrDrawEffect& drawEffect, | |
20 EffectKey key, | |
21 const char* outputColor, | |
22 const char* inputColor, | |
23 const TextureSamplerArray& samplers) SK_OVERRIDE { | |
24 const GrEdgeEffect& edgeEffect = drawEffect.castEffect<GrEdgeEffect>(); | |
25 GrEdgeEffect::EdgeType type = edgeEffect.edgeType(); | |
26 | |
27 const char *vsName, *fsName; | |
28 const SkString* attrName = | |
29 builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[ 0]); | |
30 builder->fsCodeAppendf("\t\tfloat edgeAlpha;\n"); | |
31 | |
32 switch (type) { | |
33 case GrEdgeEffect::kHairLine_EdgeType: | |
34 builder->addVarying(kVec4f_GrSLType, "HairEdge", &vsName, &fsName); | |
35 | |
36 builder->fsCodeAppendf("\t\tedgeAlpha = abs(dot(vec3(%s.xy,1), %s.xy z));\n", | |
37 builder->fragmentPosition(), fsName); | |
38 builder->fsCodeAppendf("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n "); | |
39 break; | |
40 case GrEdgeEffect::kQuad_EdgeType: | |
41 GrAssert(builder->ctxInfo().caps()->shaderDerivativeSupport()); | |
42 builder->addVarying(kVec4f_GrSLType, "QuadEdge", &vsName, &fsName); | |
43 | |
44 // keep the derivative instructions outside the conditional | |
45 builder->fsCodeAppendf("\t\tvec2 duvdx = dFdx(%s.xy);\n", fsName); | |
46 builder->fsCodeAppendf("\t\tvec2 duvdy = dFdy(%s.xy);\n", fsName); | |
47 builder->fsCodeAppendf("\t\tif (%s.z > 0.0 && %s.w > 0.0) {\n", fsNa me, fsName); | |
48 // today we know z and w are in device space. We could use derivativ es | |
49 builder->fsCodeAppendf("\t\t\tedgeAlpha = min(min(%s.z, %s.w) + 0.5, 1.0);\n", fsName, | |
50 fsName); | |
51 builder->fsCodeAppendf ("\t\t} else {\n"); | |
52 builder->fsCodeAppendf("\t\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvd x.y,\n" | |
53 "\t\t\t 2.0*%s.x*duvdy.x - duvd y.y);\n", | |
54 fsName, fsName); | |
55 builder->fsCodeAppendf("\t\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fs Name, fsName, | |
56 fsName); | |
57 builder->fsCodeAppendf("\t\t\tedgeAlpha = " | |
58 "clamp(0.5 - edgeAlpha / length(gF), 0.0, 1.0 );\n\t\t}\n"); | |
59 if (kES2_GrGLBinding == builder->ctxInfo().binding()) { | |
60 builder->fHeader.append("#extension GL_OES_standard_derivatives: enable\n"); | |
61 } | |
62 break; | |
63 case GrEdgeEffect::kHairQuad_EdgeType: | |
64 GrAssert(builder->ctxInfo().caps()->shaderDerivativeSupport()); | |
65 builder->addVarying(kVec4f_GrSLType, "HairQuadEdge", &vsName, &fsNam e); | |
66 | |
67 builder->fsCodeAppendf("\t\tvec2 duvdx = dFdx(%s.xy);\n", fsName); | |
68 builder->fsCodeAppendf("\t\tvec2 duvdy = dFdy(%s.xy);\n", fsName); | |
69 builder->fsCodeAppendf("\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx. y,\n" | |
70 "\t\t 2.0*%s.x*duvdy.x - duvdy. y);\n", | |
71 fsName, fsName); | |
72 builder->fsCodeAppendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsNa me, fsName, | |
73 fsName); | |
74 builder->fsCodeAppend("\t\tedgeAlpha = sqrt(edgeAlpha*edgeAlpha / do t(gF, gF));\n"); | |
75 builder->fsCodeAppend("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n" ); | |
76 if (kES2_GrGLBinding == builder->ctxInfo().binding()) { | |
77 builder->fHeader.append("#extension GL_OES_standard_derivatives: enable\n"); | |
78 } | |
79 break; | |
80 }; | |
81 | |
82 SkString modulate; | |
83 GrGLSLModulate4f(&modulate, inputColor, "edgeAlpha"); | |
84 builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str()); | |
85 | |
86 builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str()); | |
87 } | |
88 | |
89 static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCap s&) { | |
90 const GrEdgeEffect& QuadEffect = drawEffect.castEffect<GrEdgeEffect>(); | |
91 | |
92 return QuadEffect.edgeType(); | |
93 } | |
94 | |
95 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVER RIDE { | |
96 } | |
97 | |
98 private: | |
99 typedef GrGLEffect INHERITED; | |
100 }; | |
101 | |
102 /////////////////////////////////////////////////////////////////////////////// | |
103 | |
104 GrEdgeEffect::GrEdgeEffect(EdgeType edgeType) : GrEffect() { | |
105 if (edgeType == kQuad_EdgeType) { | |
106 this->addVertexAttrib(kVec4f_GrSLType); | |
107 } else { | |
robertphillips
2013/03/26 14:09:20
convert the "someday" comment into a "TODO"?
bsalomon
2013/03/26 14:45:30
Done.
| |
108 this->addVertexAttrib(kVec4f_GrSLType); // someday this will matter | |
109 } | |
110 fEdgeType = edgeType; | |
111 } | |
112 | |
113 void GrEdgeEffect::getConstantColorComponents(GrColor* color, uint32_t* validFla gs) const { | |
114 *validFlags = 0; | |
115 } | |
116 | |
117 const GrBackendEffectFactory& GrEdgeEffect::getFactory() const { | |
118 return GrTBackendEffectFactory<GrEdgeEffect>::getInstance(); | |
119 } | |
120 | |
121 /////////////////////////////////////////////////////////////////////////////// | |
122 | |
123 GR_DEFINE_EFFECT_TEST(GrEdgeEffect); | |
124 | |
125 GrEffectRef* GrEdgeEffect::TestCreate(SkMWCRandom* random, | |
126 GrContext*, | |
127 const GrDrawTargetCaps& caps, | |
128 GrTexture*[]) { | |
129 // Only kHairLine works without derivative instructions. | |
130 EdgeType edgeType; | |
131 if (caps.shaderDerivativeSupport()) { | |
132 edgeType = static_cast<EdgeType>(random->nextULessThan(kEdgeTypeCount)); | |
133 } else { | |
134 edgeType = kHairLine_EdgeType; | |
135 } | |
136 return GrEdgeEffect::Create(edgeType); | |
137 } | |
OLD | NEW |