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