1/* 2 * Copyright 2014 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 "GrConvexPolyEffect.h" 9#include "GrInvariantOutput.h" 10#include "SkPath.h" 11#include "gl/GrGLProcessor.h" 12#include "gl/GrGLSL.h" 13#include "gl/builders/GrGLProgramBuilder.h" 14 15////////////////////////////////////////////////////////////////////////////// 16class AARectEffect : public GrFragmentProcessor { 17public: 18 const SkRect& getRect() const { return fRect; } 19 20 static GrFragmentProcessor* Create(GrPrimitiveEdgeType edgeType, const SkRect& rect) { 21 return SkNEW_ARGS(AARectEffect, (edgeType, rect)); 22 } 23 24 GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; } 25 26 const char* name() const override { return "AARect"; } 27 28 void getGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override; 29 30 GrGLFragmentProcessor* createGLInstance() const override; 31 32private: 33 AARectEffect(GrPrimitiveEdgeType edgeType, const SkRect& rect) 34 : fRect(rect), fEdgeType(edgeType) { 35 this->initClassID<AARectEffect>(); 36 this->setWillReadFragmentPosition(); 37 } 38 39 bool onIsEqual(const GrFragmentProcessor& other) const override { 40 const AARectEffect& aare = other.cast<AARectEffect>(); 41 return fRect == aare.fRect; 42 } 43 44 void onComputeInvariantOutput(GrInvariantOutput* inout) const override { 45 if (fRect.isEmpty()) { 46 // An empty rect will have no coverage anywhere. 47 inout->mulByKnownSingleComponent(0); 48 } else { 49 inout->mulByUnknownSingleComponent(); 50 } 51 } 52 53 SkRect fRect; 54 GrPrimitiveEdgeType fEdgeType; 55 56 typedef GrFragmentProcessor INHERITED; 57 58 GR_DECLARE_FRAGMENT_PROCESSOR_TEST; 59 60}; 61 62GR_DEFINE_FRAGMENT_PROCESSOR_TEST(AARectEffect); 63 64GrFragmentProcessor* AARectEffect::TestCreate(SkRandom* random, 65 GrContext*, 66 const GrDrawTargetCaps& caps, 67 GrTexture*[]) { 68 SkRect rect = SkRect::MakeLTRB(random->nextSScalar1(), 69 random->nextSScalar1(), 70 random->nextSScalar1(), 71 random->nextSScalar1()); 72 GrFragmentProcessor* fp; 73 do { 74 GrPrimitiveEdgeType edgeType = static_cast<GrPrimitiveEdgeType>(random->nextULessThan( 75 kGrProcessorEdgeTypeCnt)); 76 77 fp = AARectEffect::Create(edgeType, rect); 78 } while (NULL == fp); 79 return fp; 80} 81 82////////////////////////////////////////////////////////////////////////////// 83 84class GLAARectEffect : public GrGLFragmentProcessor { 85public: 86 GLAARectEffect(const GrProcessor&); 87 88 virtual void emitCode(GrGLFPBuilder* builder, 89 const GrFragmentProcessor& fp, 90 const char* outputColor, 91 const char* inputColor, 92 const TransformedCoordsArray&, 93 const TextureSamplerArray&) override; 94 95 static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder*); 96 97 void setData(const GrGLProgramDataManager&, const GrProcessor&) override; 98 99private: 100 GrGLProgramDataManager::UniformHandle fRectUniform; 101 SkRect fPrevRect; 102 typedef GrGLFragmentProcessor INHERITED; 103}; 104 105GLAARectEffect::GLAARectEffect(const GrProcessor& effect) { 106 fPrevRect.fLeft = SK_ScalarNaN; 107} 108 109void GLAARectEffect::emitCode(GrGLFPBuilder* builder, 110 const GrFragmentProcessor& fp, 111 const char* outputColor, 112 const char* inputColor, 113 const TransformedCoordsArray&, 114 const TextureSamplerArray& samplers) { 115 const AARectEffect& aare = fp.cast<AARectEffect>(); 116 const char *rectName; 117 // The rect uniform's xyzw refer to (left + 0.5, top + 0.5, right - 0.5, bottom - 0.5), 118 // respectively. 119 fRectUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, 120 kVec4f_GrSLType, 121 kDefault_GrSLPrecision, 122 "rect", 123 &rectName); 124 125 GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder(); 126 const char* fragmentPos = fsBuilder->fragmentPosition(); 127 if (GrProcessorEdgeTypeIsAA(aare.getEdgeType())) { 128 // The amount of coverage removed in x and y by the edges is computed as a pair of negative 129 // numbers, xSub and ySub. 130 fsBuilder->codeAppend("\t\tfloat xSub, ySub;\n"); 131 fsBuilder->codeAppendf("\t\txSub = min(%s.x - %s.x, 0.0);\n", fragmentPos, rectName); 132 fsBuilder->codeAppendf("\t\txSub += min(%s.z - %s.x, 0.0);\n", rectName, fragmentPos); 133 fsBuilder->codeAppendf("\t\tySub = min(%s.y - %s.y, 0.0);\n", fragmentPos, rectName); 134 fsBuilder->codeAppendf("\t\tySub += min(%s.w - %s.y, 0.0);\n", rectName, fragmentPos); 135 // Now compute coverage in x and y and multiply them to get the fraction of the pixel 136 // covered. 137 fsBuilder->codeAppendf("\t\tfloat alpha = (1.0 + max(xSub, -1.0)) * (1.0 + max(ySub, -1.0));\n"); 138 } else { 139 fsBuilder->codeAppendf("\t\tfloat alpha = 1.0;\n"); 140 fsBuilder->codeAppendf("\t\talpha *= (%s.x - %s.x) > -0.5 ? 1.0 : 0.0;\n", fragmentPos, rectName); 141 fsBuilder->codeAppendf("\t\talpha *= (%s.z - %s.x) > -0.5 ? 1.0 : 0.0;\n", rectName, fragmentPos); 142 fsBuilder->codeAppendf("\t\talpha *= (%s.y - %s.y) > -0.5 ? 1.0 : 0.0;\n", fragmentPos, rectName); 143 fsBuilder->codeAppendf("\t\talpha *= (%s.w - %s.y) > -0.5 ? 1.0 : 0.0;\n", rectName, fragmentPos); 144 } 145 146 if (GrProcessorEdgeTypeIsInverseFill(aare.getEdgeType())) { 147 fsBuilder->codeAppend("\t\talpha = 1.0 - alpha;\n"); 148 } 149 fsBuilder->codeAppendf("\t\t%s = %s;\n", outputColor, 150 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_str()); 151} 152 153void GLAARectEffect::setData(const GrGLProgramDataManager& pdman, const GrProcessor& processor) { 154 const AARectEffect& aare = processor.cast<AARectEffect>(); 155 const SkRect& rect = aare.getRect(); 156 if (rect != fPrevRect) { 157 pdman.set4f(fRectUniform, rect.fLeft + 0.5f, rect.fTop + 0.5f, 158 rect.fRight - 0.5f, rect.fBottom - 0.5f); 159 fPrevRect = rect; 160 } 161} 162 163void GLAARectEffect::GenKey(const GrProcessor& processor, const GrGLSLCaps&, 164 GrProcessorKeyBuilder* b) { 165 const AARectEffect& aare = processor.cast<AARectEffect>(); 166 b->add32(aare.getEdgeType()); 167} 168 169void AARectEffect::getGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const { 170 GLAARectEffect::GenKey(*this, caps, b); 171} 172 173GrGLFragmentProcessor* AARectEffect::createGLInstance() const { 174 return SkNEW_ARGS(GLAARectEffect, (*this)); 175} 176 177////////////////////////////////////////////////////////////////////////////// 178 179class GrGLConvexPolyEffect : public GrGLFragmentProcessor { 180public: 181 GrGLConvexPolyEffect(const GrProcessor&); 182 183 virtual void emitCode(GrGLFPBuilder* builder, 184 const GrFragmentProcessor& fp, 185 const char* outputColor, 186 const char* inputColor, 187 const TransformedCoordsArray&, 188 const TextureSamplerArray&) override; 189 190 static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder*); 191 192 void setData(const GrGLProgramDataManager&, const GrProcessor&) override; 193 194private: 195 GrGLProgramDataManager::UniformHandle fEdgeUniform; 196 SkScalar fPrevEdges[3 * GrConvexPolyEffect::kMaxEdges]; 197 typedef GrGLFragmentProcessor INHERITED; 198}; 199 200GrGLConvexPolyEffect::GrGLConvexPolyEffect(const GrProcessor&) { 201 fPrevEdges[0] = SK_ScalarNaN; 202} 203 204void GrGLConvexPolyEffect::emitCode(GrGLFPBuilder* builder, 205 const GrFragmentProcessor& fp, 206 const char* outputColor, 207 const char* inputColor, 208 const TransformedCoordsArray&, 209 const TextureSamplerArray& samplers) { 210 const GrConvexPolyEffect& cpe = fp.cast<GrConvexPolyEffect>(); 211 212 const char *edgeArrayName; 213 fEdgeUniform = builder->addUniformArray(GrGLProgramBuilder::kFragment_Visibility, 214 kVec3f_GrSLType, 215 kDefault_GrSLPrecision, 216 "edges", 217 cpe.getEdgeCount(), 218 &edgeArrayName); 219 GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder(); 220 fsBuilder->codeAppend("\t\tfloat alpha = 1.0;\n"); 221 fsBuilder->codeAppend("\t\tfloat edge;\n"); 222 const char* fragmentPos = fsBuilder->fragmentPosition(); 223 for (int i = 0; i < cpe.getEdgeCount(); ++i) { 224 fsBuilder->codeAppendf("\t\tedge = dot(%s[%d], vec3(%s.x, %s.y, 1));\n", 225 edgeArrayName, i, fragmentPos, fragmentPos); 226 if (GrProcessorEdgeTypeIsAA(cpe.getEdgeType())) { 227 fsBuilder->codeAppend("\t\tedge = clamp(edge, 0.0, 1.0);\n"); 228 } else { 229 fsBuilder->codeAppend("\t\tedge = edge >= 0.5 ? 1.0 : 0.0;\n"); 230 } 231 fsBuilder->codeAppend("\t\talpha *= edge;\n"); 232 } 233 234 // Woe is me. See skbug.com/2149. 235 if (kTegra2_GrGLRenderer == builder->ctxInfo().renderer()) { 236 fsBuilder->codeAppend("\t\tif (-1.0 == alpha) {\n\t\t\tdiscard;\n\t\t}\n"); 237 } 238 239 if (GrProcessorEdgeTypeIsInverseFill(cpe.getEdgeType())) { 240 fsBuilder->codeAppend("\talpha = 1.0 - alpha;\n"); 241 } 242 fsBuilder->codeAppendf("\t%s = %s;\n", outputColor, 243 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_str()); 244} 245 246void GrGLConvexPolyEffect::setData(const GrGLProgramDataManager& pdman, const GrProcessor& effect) { 247 const GrConvexPolyEffect& cpe = effect.cast<GrConvexPolyEffect>(); 248 size_t byteSize = 3 * cpe.getEdgeCount() * sizeof(SkScalar); 249 if (0 != memcmp(fPrevEdges, cpe.getEdges(), byteSize)) { 250 pdman.set3fv(fEdgeUniform, cpe.getEdgeCount(), cpe.getEdges()); 251 memcpy(fPrevEdges, cpe.getEdges(), byteSize); 252 } 253} 254 255void GrGLConvexPolyEffect::GenKey(const GrProcessor& processor, const GrGLSLCaps&, 256 GrProcessorKeyBuilder* b) { 257 const GrConvexPolyEffect& cpe = processor.cast<GrConvexPolyEffect>(); 258 GR_STATIC_ASSERT(kGrProcessorEdgeTypeCnt <= 8); 259 uint32_t key = (cpe.getEdgeCount() << 3) | cpe.getEdgeType(); 260 b->add32(key); 261} 262 263////////////////////////////////////////////////////////////////////////////// 264 265GrFragmentProcessor* GrConvexPolyEffect::Create(GrPrimitiveEdgeType type, const SkPath& path, 266 const SkVector* offset) { 267 if (kHairlineAA_GrProcessorEdgeType == type) { 268 return NULL; 269 } 270 if (path.getSegmentMasks() != SkPath::kLine_SegmentMask || 271 !path.isConvex()) { 272 return NULL; 273 } 274 275 if (path.countPoints() > kMaxEdges) { 276 return NULL; 277 } 278 279 SkPoint pts[kMaxEdges]; 280 SkScalar edges[3 * kMaxEdges]; 281 282 SkPath::Direction dir; 283 SkAssertResult(path.cheapComputeDirection(&dir)); 284 285 SkVector t; 286 if (NULL == offset) { 287 t.set(0, 0); 288 } else { 289 t = *offset; 290 } 291 292 int count = path.getPoints(pts, kMaxEdges); 293 int n = 0; 294 for (int lastPt = count - 1, i = 0; i < count; lastPt = i++) { 295 if (pts[lastPt] != pts[i]) { 296 SkVector v = pts[i] - pts[lastPt]; 297 v.normalize(); 298 if (SkPath::kCCW_Direction == dir) { 299 edges[3 * n] = v.fY; 300 edges[3 * n + 1] = -v.fX; 301 } else { 302 edges[3 * n] = -v.fY; 303 edges[3 * n + 1] = v.fX; 304 } 305 SkPoint p = pts[i] + t; 306 edges[3 * n + 2] = -(edges[3 * n] * p.fX + edges[3 * n + 1] * p.fY); 307 ++n; 308 } 309 } 310 if (path.isInverseFillType()) { 311 type = GrInvertProcessorEdgeType(type); 312 } 313 return Create(type, n, edges); 314} 315 316GrFragmentProcessor* GrConvexPolyEffect::Create(GrPrimitiveEdgeType edgeType, const SkRect& rect) { 317 if (kHairlineAA_GrProcessorEdgeType == edgeType){ 318 return NULL; 319 } 320 return AARectEffect::Create(edgeType, rect); 321} 322 323GrConvexPolyEffect::~GrConvexPolyEffect() {} 324 325void GrConvexPolyEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const { 326 inout->mulByUnknownSingleComponent(); 327} 328 329void GrConvexPolyEffect::getGLProcessorKey(const GrGLSLCaps& caps, 330 GrProcessorKeyBuilder* b) const { 331 GrGLConvexPolyEffect::GenKey(*this, caps, b); 332} 333 334GrGLFragmentProcessor* GrConvexPolyEffect::createGLInstance() const { 335 return SkNEW_ARGS(GrGLConvexPolyEffect, (*this)); 336} 337 338GrConvexPolyEffect::GrConvexPolyEffect(GrPrimitiveEdgeType edgeType, int n, const SkScalar edges[]) 339 : fEdgeType(edgeType) 340 , fEdgeCount(n) { 341 this->initClassID<GrConvexPolyEffect>(); 342 // Factory function should have already ensured this. 343 SkASSERT(n <= kMaxEdges); 344 memcpy(fEdges, edges, 3 * n * sizeof(SkScalar)); 345 // Outset the edges by 0.5 so that a pixel with center on an edge is 50% covered in the AA case 346 // and 100% covered in the non-AA case. 347 for (int i = 0; i < n; ++i) { 348 fEdges[3 * i + 2] += SK_ScalarHalf; 349 } 350 this->setWillReadFragmentPosition(); 351} 352 353bool GrConvexPolyEffect::onIsEqual(const GrFragmentProcessor& other) const { 354 const GrConvexPolyEffect& cpe = other.cast<GrConvexPolyEffect>(); 355 // ignore the fact that 0 == -0 and just use memcmp. 356 return (cpe.fEdgeType == fEdgeType && cpe.fEdgeCount == fEdgeCount && 357 0 == memcmp(cpe.fEdges, fEdges, 3 * fEdgeCount * sizeof(SkScalar))); 358} 359 360////////////////////////////////////////////////////////////////////////////// 361 362GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrConvexPolyEffect); 363 364GrFragmentProcessor* GrConvexPolyEffect::TestCreate(SkRandom* random, 365 GrContext*, 366 const GrDrawTargetCaps& caps, 367 GrTexture*[]) { 368 int count = random->nextULessThan(kMaxEdges) + 1; 369 SkScalar edges[kMaxEdges * 3]; 370 for (int i = 0; i < 3 * count; ++i) { 371 edges[i] = random->nextSScalar1(); 372 } 373 374 GrFragmentProcessor* fp; 375 do { 376 GrPrimitiveEdgeType edgeType = static_cast<GrPrimitiveEdgeType>( 377 random->nextULessThan(kGrProcessorEdgeTypeCnt)); 378 fp = GrConvexPolyEffect::Create(edgeType, count, edges); 379 } while (NULL == fp); 380 return fp; 381} 382