1 /* 2 * Copyright 2006 The Android Open Source Project 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 "SkBlitRow.h" 9 #include "SkColorFilter.h" 10 #include "SkColorPriv.h" 11 #include "SkModeColorFilter.h" 12 #include "SkReadBuffer.h" 13 #include "SkWriteBuffer.h" 14 #include "SkUtils.h" 15 #include "SkString.h" 16 #include "SkValidationUtils.h" 17 #include "SkColorMatrixFilter.h" 18 19 bool SkModeColorFilter::asColorMode(SkColor* color, SkXfermode::Mode* mode) const { 20 if (color) { 21 *color = fColor; 22 } 23 if (mode) { 24 *mode = fMode; 25 } 26 return true; 27 } 28 29 uint32_t SkModeColorFilter::getFlags() const { 30 switch (fMode) { 31 case SkXfermode::kDst_Mode: //!< [Da, Dc] 32 case SkXfermode::kSrcATop_Mode: //!< [Da, Sc * Da + (1 - Sa) * Dc] 33 return kAlphaUnchanged_Flag; 34 default: 35 break; 36 } 37 return 0; 38 } 39 40 void SkModeColorFilter::filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const { 41 SkPMColor color = fPMColor; 42 SkXfermodeProc proc = fProc; 43 44 for (int i = 0; i < count; i++) { 45 result[i] = proc(color, shader[i]); 46 } 47 } 48 49 void SkModeColorFilter::flatten(SkWriteBuffer& buffer) const { 50 buffer.writeColor(fColor); 51 buffer.writeUInt(fMode); 52 } 53 54 void SkModeColorFilter::updateCache() { 55 fPMColor = SkPreMultiplyColor(fColor); 56 fProc = SkXfermode::GetProc(fMode); 57 } 58 59 SkFlattenable* SkModeColorFilter::CreateProc(SkReadBuffer& buffer) { 60 SkColor color = buffer.readColor(); 61 SkXfermode::Mode mode = (SkXfermode::Mode)buffer.readUInt(); 62 return SkColorFilter::CreateModeFilter(color, mode); 63 } 64 65 /////////////////////////////////////////////////////////////////////////////// 66 #if SK_SUPPORT_GPU 67 #include "GrBlend.h" 68 #include "GrFragmentProcessor.h" 69 #include "GrInvariantOutput.h" 70 #include "GrProcessorUnitTest.h" 71 #include "SkGr.h" 72 #include "gl/GrGLProcessor.h" 73 #include "gl/builders/GrGLProgramBuilder.h" 74 75 namespace { 76 /** 77 * A definition of blend equation for one coefficient. Generates a 78 * blend_coeff * value "expression". 79 */ 80 template<typename ColorExpr> 81 static inline ColorExpr blend_term(SkXfermode::Coeff coeff, 82 const ColorExpr& src, 83 const ColorExpr& dst, 84 const ColorExpr& value) { 85 switch (coeff) { 86 default: 87 SkFAIL("Unexpected xfer coeff."); 88 case SkXfermode::kZero_Coeff: /** 0 */ 89 return ColorExpr(0); 90 case SkXfermode::kOne_Coeff: /** 1 */ 91 return value; 92 case SkXfermode::kSC_Coeff: 93 return src * value; 94 case SkXfermode::kISC_Coeff: 95 return (ColorExpr(1) - src) * dst; 96 case SkXfermode::kDC_Coeff: 97 return dst * value; 98 case SkXfermode::kIDC_Coeff: 99 return (ColorExpr(1) - dst) * value; 100 case SkXfermode::kSA_Coeff: /** src alpha */ 101 return src.a() * value; 102 case SkXfermode::kISA_Coeff: /** inverse src alpha (i.e. 1 - sa) */ 103 return (typename ColorExpr::AExpr(1) - src.a()) * value; 104 case SkXfermode::kDA_Coeff: /** dst alpha */ 105 return dst.a() * value; 106 case SkXfermode::kIDA_Coeff: /** inverse dst alpha (i.e. 1 - da) */ 107 return (typename ColorExpr::AExpr(1) - dst.a()) * value; 108 } 109 } 110 /** 111 * Creates a color filter expression which modifies the color by 112 * the specified color filter. 113 */ 114 template <typename ColorExpr> 115 static inline ColorExpr color_filter_expression(const SkXfermode::Mode& mode, 116 const ColorExpr& filterColor, 117 const ColorExpr& inColor) { 118 SkXfermode::Coeff colorCoeff; 119 SkXfermode::Coeff filterColorCoeff; 120 SkAssertResult(SkXfermode::ModeAsCoeff(mode, &filterColorCoeff, &colorCoeff)); 121 return blend_term(colorCoeff, filterColor, inColor, inColor) + 122 blend_term(filterColorCoeff, filterColor, inColor, filterColor); 123 } 124 125 } 126 127 class ModeColorFilterEffect : public GrFragmentProcessor { 128 public: 129 static GrFragmentProcessor* Create(const GrColor& c, SkXfermode::Mode mode) { 130 // TODO: Make the effect take the coeffs rather than mode since we already do the 131 // conversion here. 132 SkXfermode::Coeff srcCoeff, dstCoeff; 133 if (!SkXfermode::ModeAsCoeff(mode, &srcCoeff, &dstCoeff)) { 134 // SkDebugf("Failing to create color filter for mode %d\n", mode); 135 return NULL; 136 } 137 return SkNEW_ARGS(ModeColorFilterEffect, (c, mode)); 138 } 139 140 bool willUseFilterColor() const { 141 SkXfermode::Coeff dstCoeff; 142 SkXfermode::Coeff srcCoeff; 143 SkAssertResult(SkXfermode::ModeAsCoeff(fMode, &srcCoeff, &dstCoeff)); 144 if (SkXfermode::kZero_Coeff == srcCoeff) { 145 return GrBlendCoeffRefsSrc(sk_blend_to_grblend(dstCoeff)); 146 } 147 return true; 148 } 149 150 virtual void getGLProcessorKey(const GrGLSLCaps& caps, 151 GrProcessorKeyBuilder* b) const override { 152 GLProcessor::GenKey(*this, caps, b); 153 } 154 155 GrGLFragmentProcessor* createGLInstance() const override { 156 return SkNEW_ARGS(GLProcessor, (*this)); 157 } 158 159 const char* name() const override { return "ModeColorFilterEffect"; } 160 161 SkXfermode::Mode mode() const { return fMode; } 162 GrColor color() const { return fColor; } 163 164 class GLProcessor : public GrGLFragmentProcessor { 165 public: 166 GLProcessor(const GrProcessor&) { 167 } 168 169 virtual void emitCode(GrGLFPBuilder* builder, 170 const GrFragmentProcessor& fp, 171 const char* outputColor, 172 const char* inputColor, 173 const TransformedCoordsArray&, 174 const TextureSamplerArray&) override { 175 SkXfermode::Mode mode = fp.cast<ModeColorFilterEffect>().mode(); 176 177 SkASSERT(SkXfermode::kDst_Mode != mode); 178 const char* colorFilterColorUniName = NULL; 179 if (fp.cast<ModeColorFilterEffect>().willUseFilterColor()) { 180 fFilterColorUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, 181 kVec4f_GrSLType, kDefault_GrSLPrecision, 182 "FilterColor", 183 &colorFilterColorUniName); 184 } 185 186 GrGLSLExpr4 filter = 187 color_filter_expression(mode, GrGLSLExpr4(colorFilterColorUniName), 188 GrGLSLExpr4(inputColor)); 189 190 builder->getFragmentShaderBuilder()-> 191 codeAppendf("\t%s = %s;\n", outputColor, filter.c_str()); 192 } 193 194 static void GenKey(const GrProcessor& fp, const GrGLSLCaps&, 195 GrProcessorKeyBuilder* b) { 196 const ModeColorFilterEffect& colorModeFilter = fp.cast<ModeColorFilterEffect>(); 197 // The SL code does not depend on filter color at the moment, so no need to represent it 198 // in the key. 199 b->add32(colorModeFilter.mode()); 200 } 201 202 virtual void setData(const GrGLProgramDataManager& pdman, 203 const GrProcessor& fp) override { 204 if (fFilterColorUni.isValid()) { 205 const ModeColorFilterEffect& colorModeFilter = fp.cast<ModeColorFilterEffect>(); 206 GrGLfloat c[4]; 207 GrColorToRGBAFloat(colorModeFilter.color(), c); 208 pdman.set4fv(fFilterColorUni, 1, c); 209 } 210 } 211 212 private: 213 214 GrGLProgramDataManager::UniformHandle fFilterColorUni; 215 typedef GrGLFragmentProcessor INHERITED; 216 }; 217 218 GR_DECLARE_FRAGMENT_PROCESSOR_TEST; 219 220 private: 221 ModeColorFilterEffect(GrColor color, SkXfermode::Mode mode) 222 : fMode(mode), 223 fColor(color) { 224 this->initClassID<ModeColorFilterEffect>(); 225 } 226 227 bool onIsEqual(const GrFragmentProcessor& other) const override { 228 const ModeColorFilterEffect& s = other.cast<ModeColorFilterEffect>(); 229 return fMode == s.fMode && fColor == s.fColor; 230 } 231 232 void onComputeInvariantOutput(GrInvariantOutput* inout) const override; 233 234 SkXfermode::Mode fMode; 235 GrColor fColor; 236 237 typedef GrFragmentProcessor INHERITED; 238 }; 239 240 namespace { 241 242 /** Function color_component_to_int tries to reproduce the GLSL rounding. The spec doesn't specify 243 * to which direction the 0.5 goes. 244 */ 245 static inline int color_component_to_int(float value) { 246 return sk_float_round2int(SkTMax(0.f, SkTMin(1.f, value)) * 255.f); 247 } 248 249 /** MaskedColorExpr is used to evaluate the color and valid color component flags through the 250 * blending equation. It has members similar to GrGLSLExpr so that it can be used with the 251 * templated helpers above. 252 */ 253 class MaskedColorExpr { 254 public: 255 MaskedColorExpr(const float color[], uint32_t flags) 256 : fFlags(flags) { 257 fColor[0] = color[0]; 258 fColor[1] = color[1]; 259 fColor[2] = color[2]; 260 fColor[3] = color[3]; 261 } 262 263 MaskedColorExpr(float v, uint32_t flags = kRGBA_GrColorComponentFlags) 264 : fFlags(flags) { 265 fColor[0] = v; 266 fColor[1] = v; 267 fColor[2] = v; 268 fColor[3] = v; 269 } 270 271 MaskedColorExpr operator*(const MaskedColorExpr& other) const { 272 float tmp[4]; 273 tmp[0] = fColor[0] * other.fColor[0]; 274 tmp[1] = fColor[1] * other.fColor[1]; 275 tmp[2] = fColor[2] * other.fColor[2]; 276 tmp[3] = fColor[3] * other.fColor[3]; 277 278 return MaskedColorExpr(tmp, fFlags & other.fFlags); 279 } 280 281 MaskedColorExpr operator+(const MaskedColorExpr& other) const { 282 float tmp[4]; 283 tmp[0] = fColor[0] + other.fColor[0]; 284 tmp[1] = fColor[1] + other.fColor[1]; 285 tmp[2] = fColor[2] + other.fColor[2]; 286 tmp[3] = fColor[3] + other.fColor[3]; 287 288 return MaskedColorExpr(tmp, fFlags & other.fFlags); 289 } 290 291 MaskedColorExpr operator-(const MaskedColorExpr& other) const { 292 float tmp[4]; 293 tmp[0] = fColor[0] - other.fColor[0]; 294 tmp[1] = fColor[1] - other.fColor[1]; 295 tmp[2] = fColor[2] - other.fColor[2]; 296 tmp[3] = fColor[3] - other.fColor[3]; 297 298 return MaskedColorExpr(tmp, fFlags & other.fFlags); 299 } 300 301 MaskedColorExpr a() const { 302 uint32_t flags = (fFlags & kA_GrColorComponentFlag) ? kRGBA_GrColorComponentFlags : 0; 303 return MaskedColorExpr(fColor[3], flags); 304 } 305 306 GrColor getColor() const { 307 return GrColorPackRGBA(color_component_to_int(fColor[0]), 308 color_component_to_int(fColor[1]), 309 color_component_to_int(fColor[2]), 310 color_component_to_int(fColor[3])); 311 } 312 313 uint32_t getValidComponents() const { return fFlags; } 314 315 typedef MaskedColorExpr AExpr; 316 private: 317 float fColor[4]; 318 uint32_t fFlags; 319 }; 320 321 } 322 323 void ModeColorFilterEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const { 324 float inputColor[4]; 325 GrColorToRGBAFloat(inout->color(), inputColor); 326 float filterColor[4]; 327 GrColorToRGBAFloat(fColor, filterColor); 328 MaskedColorExpr result = 329 color_filter_expression(fMode, 330 MaskedColorExpr(filterColor, kRGBA_GrColorComponentFlags), 331 MaskedColorExpr(inputColor, inout->validFlags())); 332 333 // Check if we will use the input color 334 SkXfermode::Coeff dstCoeff; 335 SkXfermode::Coeff srcCoeff; 336 SkAssertResult(SkXfermode::ModeAsCoeff(fMode, &srcCoeff, &dstCoeff)); 337 GrInvariantOutput::ReadInput readInput = GrInvariantOutput::kWill_ReadInput; 338 // These could be calculated from the blend equation with template trickery.. 339 if (SkXfermode::kZero_Coeff == dstCoeff && 340 !GrBlendCoeffRefsDst(sk_blend_to_grblend(srcCoeff))) { 341 readInput = GrInvariantOutput::kWillNot_ReadInput; 342 } 343 inout->setToOther(result.getValidComponents(), result.getColor(), readInput); 344 } 345 346 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ModeColorFilterEffect); 347 GrFragmentProcessor* ModeColorFilterEffect::TestCreate(SkRandom* rand, 348 GrContext*, 349 const GrDrawTargetCaps&, 350 GrTexture*[]) { 351 SkXfermode::Mode mode = SkXfermode::kDst_Mode; 352 while (SkXfermode::kDst_Mode == mode) { 353 mode = static_cast<SkXfermode::Mode>(rand->nextRangeU(0, SkXfermode::kLastCoeffMode)); 354 } 355 356 // pick a random premul color 357 uint8_t alpha = rand->nextULessThan(256); 358 GrColor color = GrColorPackRGBA(rand->nextRangeU(0, alpha), 359 rand->nextRangeU(0, alpha), 360 rand->nextRangeU(0, alpha), 361 alpha); 362 return ModeColorFilterEffect::Create(color, mode); 363 } 364 365 bool SkModeColorFilter::asFragmentProcessors(GrContext*, 366 SkTDArray<GrFragmentProcessor*>* array) const { 367 if (SkXfermode::kDst_Mode != fMode) { 368 GrFragmentProcessor* frag = ModeColorFilterEffect::Create(SkColor2GrColor(fColor), fMode); 369 if (frag) { 370 if (array) { 371 *array->append() = frag; 372 } 373 return true; 374 } 375 } 376 return false; 377 } 378 379 #endif 380 381 /////////////////////////////////////////////////////////////////////////////// 382 383 class Src_SkModeColorFilter : public SkModeColorFilter { 384 public: 385 Src_SkModeColorFilter(SkColor color) : INHERITED(color, SkXfermode::kSrc_Mode) {} 386 387 void filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const override { 388 sk_memset32(result, this->getPMColor(), count); 389 } 390 391 private: 392 typedef SkModeColorFilter INHERITED; 393 }; 394 395 class SrcOver_SkModeColorFilter : public SkModeColorFilter { 396 public: 397 SrcOver_SkModeColorFilter(SkColor color) : INHERITED(color, SkXfermode::kSrcOver_Mode) { } 398 399 void filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const override { 400 SkBlitRow::Color32(result, shader, count, this->getPMColor()); 401 } 402 403 private: 404 typedef SkModeColorFilter INHERITED; 405 }; 406 407 /////////////////////////////////////////////////////////////////////////////// 408 409 SkColorFilter* SkColorFilter::CreateModeFilter(SkColor color, SkXfermode::Mode mode) { 410 if (!SkIsValidMode(mode)) { 411 return NULL; 412 } 413 414 unsigned alpha = SkColorGetA(color); 415 416 // first collaps some modes if possible 417 418 if (SkXfermode::kClear_Mode == mode) { 419 color = 0; 420 mode = SkXfermode::kSrc_Mode; 421 } else if (SkXfermode::kSrcOver_Mode == mode) { 422 if (0 == alpha) { 423 mode = SkXfermode::kDst_Mode; 424 } else if (255 == alpha) { 425 mode = SkXfermode::kSrc_Mode; 426 } 427 // else just stay srcover 428 } 429 430 // weed out combinations that are noops, and just return null 431 if (SkXfermode::kDst_Mode == mode || 432 (0 == alpha && (SkXfermode::kSrcOver_Mode == mode || 433 SkXfermode::kDstOver_Mode == mode || 434 SkXfermode::kDstOut_Mode == mode || 435 SkXfermode::kSrcATop_Mode == mode || 436 SkXfermode::kXor_Mode == mode || 437 SkXfermode::kDarken_Mode == mode)) || 438 (0xFF == alpha && SkXfermode::kDstIn_Mode == mode)) { 439 return NULL; 440 } 441 442 switch (mode) { 443 case SkXfermode::kSrc_Mode: 444 return SkNEW_ARGS(Src_SkModeColorFilter, (color)); 445 case SkXfermode::kSrcOver_Mode: 446 return SkNEW_ARGS(SrcOver_SkModeColorFilter, (color)); 447 default: 448 return SkNEW_ARGS(SkModeColorFilter, (color, mode)); 449 } 450 } 451 452 /////////////////////////////////////////////////////////////////////////////// 453 454 static SkScalar byte_to_scale(U8CPU byte) { 455 if (0xFF == byte) { 456 // want to get this exact 457 return 1; 458 } else { 459 return byte * 0.00392156862745f; 460 } 461 } 462 463 SkColorFilter* SkColorFilter::CreateLightingFilter(SkColor mul, SkColor add) { 464 SkColorMatrix matrix; 465 matrix.setScale(byte_to_scale(SkColorGetR(mul)), 466 byte_to_scale(SkColorGetG(mul)), 467 byte_to_scale(SkColorGetB(mul)), 468 1); 469 matrix.postTranslate(SkIntToScalar(SkColorGetR(add)), 470 SkIntToScalar(SkColorGetG(add)), 471 SkIntToScalar(SkColorGetB(add)), 472 0); 473 return SkColorMatrixFilter::Create(matrix); 474 } 475 476