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