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#define ILLEGAL_XFERMODE_MODE ((SkXfermode::Mode)-1) 19 20// baseclass for filters that store a color and mode 21class SkModeColorFilter : public SkColorFilter { 22public: 23 SkModeColorFilter(SkColor color) { 24 fColor = color; 25 fMode = ILLEGAL_XFERMODE_MODE; 26 this->updateCache(); 27 } 28 29 SkModeColorFilter(SkColor color, SkXfermode::Mode mode) { 30 fColor = color; 31 fMode = mode; 32 this->updateCache(); 33 }; 34 35 SkColor getColor() const { return fColor; } 36 SkXfermode::Mode getMode() const { return fMode; } 37 bool isModeValid() const { return ILLEGAL_XFERMODE_MODE != fMode; } 38 SkPMColor getPMColor() const { return fPMColor; } 39 40 virtual bool asColorMode(SkColor* color, SkXfermode::Mode* mode) const SK_OVERRIDE { 41 if (ILLEGAL_XFERMODE_MODE == fMode) { 42 return false; 43 } 44 45 if (color) { 46 *color = fColor; 47 } 48 if (mode) { 49 *mode = fMode; 50 } 51 return true; 52 } 53 54 virtual uint32_t getFlags() const SK_OVERRIDE { 55 return fProc16 ? (kAlphaUnchanged_Flag | kHasFilter16_Flag) : 0; 56 } 57 58 virtual void filterSpan(const SkPMColor shader[], int count, 59 SkPMColor result[]) const SK_OVERRIDE { 60 SkPMColor color = fPMColor; 61 SkXfermodeProc proc = fProc; 62 63 for (int i = 0; i < count; i++) { 64 result[i] = proc(color, shader[i]); 65 } 66 } 67 68 virtual void filterSpan16(const uint16_t shader[], int count, 69 uint16_t result[]) const SK_OVERRIDE { 70 SkASSERT(this->getFlags() & kHasFilter16_Flag); 71 72 SkPMColor color = fPMColor; 73 SkXfermodeProc16 proc16 = fProc16; 74 75 for (int i = 0; i < count; i++) { 76 result[i] = proc16(color, shader[i]); 77 } 78 } 79 80#ifndef SK_IGNORE_TO_STRING 81 virtual void toString(SkString* str) const SK_OVERRIDE { 82 str->append("SkModeColorFilter: color: 0x"); 83 str->appendHex(fColor); 84 str->append(" mode: "); 85 str->append(SkXfermode::ModeName(fMode)); 86 } 87#endif 88 89#if SK_SUPPORT_GPU 90 virtual GrEffectRef* asNewEffect(GrContext*) const SK_OVERRIDE; 91#endif 92 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkModeColorFilter) 93 94protected: 95 virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE { 96 this->INHERITED::flatten(buffer); 97 buffer.writeColor(fColor); 98 buffer.writeUInt(fMode); 99 } 100 101 SkModeColorFilter(SkReadBuffer& buffer) { 102 fColor = buffer.readColor(); 103 fMode = (SkXfermode::Mode)buffer.readUInt(); 104 if (buffer.isValid()) { 105 this->updateCache(); 106 buffer.validate(SkIsValidMode(fMode)); 107 } 108 } 109 110private: 111 SkColor fColor; 112 SkXfermode::Mode fMode; 113 // cache 114 SkPMColor fPMColor; 115 SkXfermodeProc fProc; 116 SkXfermodeProc16 fProc16; 117 118 void updateCache() { 119 fPMColor = SkPreMultiplyColor(fColor); 120 fProc = SkXfermode::GetProc(fMode); 121 fProc16 = SkXfermode::GetProc16(fMode, fColor); 122 } 123 124 typedef SkColorFilter INHERITED; 125}; 126 127/////////////////////////////////////////////////////////////////////////////// 128#if SK_SUPPORT_GPU 129#include "GrBlend.h" 130#include "GrEffect.h" 131#include "GrEffectUnitTest.h" 132#include "GrTBackendEffectFactory.h" 133#include "gl/GrGLEffect.h" 134#include "SkGr.h" 135 136namespace { 137/** 138 * A definition of blend equation for one coefficient. Generates a 139 * blend_coeff * value "expression". 140 */ 141template<typename ColorExpr> 142static inline ColorExpr blend_term(SkXfermode::Coeff coeff, 143 const ColorExpr& src, 144 const ColorExpr& dst, 145 const ColorExpr& value) { 146 switch (coeff) { 147 default: 148 SkFAIL("Unexpected xfer coeff."); 149 case SkXfermode::kZero_Coeff: /** 0 */ 150 return ColorExpr(0); 151 case SkXfermode::kOne_Coeff: /** 1 */ 152 return value; 153 case SkXfermode::kSC_Coeff: 154 return src * value; 155 case SkXfermode::kISC_Coeff: 156 return (ColorExpr(1) - src) * dst; 157 case SkXfermode::kDC_Coeff: 158 return dst * value; 159 case SkXfermode::kIDC_Coeff: 160 return (ColorExpr(1) - dst) * value; 161 case SkXfermode::kSA_Coeff: /** src alpha */ 162 return src.a() * value; 163 case SkXfermode::kISA_Coeff: /** inverse src alpha (i.e. 1 - sa) */ 164 return (typename ColorExpr::AExpr(1) - src.a()) * value; 165 case SkXfermode::kDA_Coeff: /** dst alpha */ 166 return dst.a() * value; 167 case SkXfermode::kIDA_Coeff: /** inverse dst alpha (i.e. 1 - da) */ 168 return (typename ColorExpr::AExpr(1) - dst.a()) * value; 169 } 170} 171/** 172 * Creates a color filter expression which modifies the color by 173 * the specified color filter. 174 */ 175template <typename ColorExpr> 176static inline ColorExpr color_filter_expression(const SkXfermode::Mode& mode, 177 const ColorExpr& filterColor, 178 const ColorExpr& inColor) { 179 SkXfermode::Coeff colorCoeff; 180 SkXfermode::Coeff filterColorCoeff; 181 SkAssertResult(SkXfermode::ModeAsCoeff(mode, &filterColorCoeff, &colorCoeff)); 182 return blend_term(colorCoeff, filterColor, inColor, inColor) + 183 blend_term(filterColorCoeff, filterColor, inColor, filterColor); 184} 185 186} 187 188class ModeColorFilterEffect : public GrEffect { 189public: 190 static GrEffectRef* Create(const GrColor& c, SkXfermode::Mode mode) { 191 // TODO: Make the effect take the coeffs rather than mode since we already do the 192 // conversion here. 193 SkXfermode::Coeff srcCoeff, dstCoeff; 194 if (!SkXfermode::ModeAsCoeff(mode, &srcCoeff, &dstCoeff)) { 195 SkDebugf("Failing to create color filter for mode %d\n", mode); 196 return NULL; 197 } 198 AutoEffectUnref effect(SkNEW_ARGS(ModeColorFilterEffect, (c, mode))); 199 return CreateEffectRef(effect); 200 } 201 202 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE; 203 204 bool willUseFilterColor() const { 205 SkXfermode::Coeff dstCoeff; 206 SkXfermode::Coeff srcCoeff; 207 SkAssertResult(SkXfermode::ModeAsCoeff(fMode, &srcCoeff, &dstCoeff)); 208 if (SkXfermode::kZero_Coeff == srcCoeff) { 209 return GrBlendCoeffRefsSrc(sk_blend_to_grblend(dstCoeff)); 210 } 211 return true; 212 } 213 214 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { 215 return GrTBackendEffectFactory<ModeColorFilterEffect>::getInstance(); 216 } 217 218 static const char* Name() { return "ModeColorFilterEffect"; } 219 220 SkXfermode::Mode mode() const { return fMode; } 221 GrColor color() const { return fColor; } 222 223 class GLEffect : public GrGLEffect { 224 public: 225 GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) 226 : INHERITED(factory) { 227 } 228 229 virtual void emitCode(GrGLShaderBuilder* builder, 230 const GrDrawEffect& drawEffect, 231 EffectKey key, 232 const char* outputColor, 233 const char* inputColor, 234 const TransformedCoordsArray& coords, 235 const TextureSamplerArray& samplers) SK_OVERRIDE { 236 SkXfermode::Mode mode = drawEffect.castEffect<ModeColorFilterEffect>().mode(); 237 238 SkASSERT(SkXfermode::kDst_Mode != mode); 239 const char* colorFilterColorUniName = NULL; 240 if (drawEffect.castEffect<ModeColorFilterEffect>().willUseFilterColor()) { 241 fFilterColorUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, 242 kVec4f_GrSLType, "FilterColor", 243 &colorFilterColorUniName); 244 } 245 246 GrGLSLExpr4 filter = 247 color_filter_expression(mode, GrGLSLExpr4(colorFilterColorUniName), GrGLSLExpr4(inputColor)); 248 249 builder->fsCodeAppendf("\t%s = %s;\n", outputColor, filter.c_str()); 250 } 251 252 static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) { 253 const ModeColorFilterEffect& colorModeFilter = drawEffect.castEffect<ModeColorFilterEffect>(); 254 // The SL code does not depend on filter color at the moment, so no need to represent it 255 // in the key. 256 EffectKey modeKey = colorModeFilter.mode(); 257 return modeKey; 258 } 259 260 virtual void setData(const GrGLUniformManager& uman, const GrDrawEffect& drawEffect) SK_OVERRIDE { 261 if (fFilterColorUni.isValid()) { 262 const ModeColorFilterEffect& colorModeFilter = drawEffect.castEffect<ModeColorFilterEffect>(); 263 GrGLfloat c[4]; 264 GrColorToRGBAFloat(colorModeFilter.color(), c); 265 uman.set4fv(fFilterColorUni, 1, c); 266 } 267 } 268 269 private: 270 271 GrGLUniformManager::UniformHandle fFilterColorUni; 272 typedef GrGLEffect INHERITED; 273 }; 274 275 GR_DECLARE_EFFECT_TEST; 276 277private: 278 ModeColorFilterEffect(GrColor color, SkXfermode::Mode mode) 279 : fMode(mode), 280 fColor(color) { 281 282 SkXfermode::Coeff dstCoeff; 283 SkXfermode::Coeff srcCoeff; 284 SkAssertResult(SkXfermode::ModeAsCoeff(fMode, &srcCoeff, &dstCoeff)); 285 // These could be calculated from the blend equation with template trickery.. 286 if (SkXfermode::kZero_Coeff == dstCoeff && !GrBlendCoeffRefsDst(sk_blend_to_grblend(srcCoeff))) { 287 this->setWillNotUseInputColor(); 288 } 289 } 290 291 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { 292 const ModeColorFilterEffect& s = CastEffect<ModeColorFilterEffect>(other); 293 return fMode == s.fMode && fColor == s.fColor; 294 } 295 296 SkXfermode::Mode fMode; 297 GrColor fColor; 298 299 typedef GrEffect 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_EFFECT_TEST(ModeColorFilterEffect); 400GrEffectRef* 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 412GrEffectRef* SkModeColorFilter::asNewEffect(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 446 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Src_SkModeColorFilter) 447 448protected: 449 Src_SkModeColorFilter(SkReadBuffer& buffer) 450 : INHERITED(buffer) {} 451 452private: 453 typedef SkModeColorFilter INHERITED; 454}; 455 456class SrcOver_SkModeColorFilter : public SkModeColorFilter { 457public: 458 SrcOver_SkModeColorFilter(SkColor color) 459 : INHERITED(color, SkXfermode::kSrcOver_Mode) { 460 fColor32Proc = SkBlitRow::ColorProcFactory(); 461 } 462 463 virtual uint32_t getFlags() const SK_OVERRIDE { 464 if (SkGetPackedA32(this->getPMColor()) == 0xFF) { 465 return kAlphaUnchanged_Flag | kHasFilter16_Flag; 466 } else { 467 return 0; 468 } 469 } 470 471 virtual void filterSpan(const SkPMColor shader[], int count, 472 SkPMColor result[]) const SK_OVERRIDE { 473 fColor32Proc(result, shader, count, this->getPMColor()); 474 } 475 476 virtual void filterSpan16(const uint16_t shader[], int count, 477 uint16_t result[]) const SK_OVERRIDE { 478 SkASSERT(this->getFlags() & kHasFilter16_Flag); 479 sk_memset16(result, SkPixel32ToPixel16(this->getPMColor()), count); 480 } 481 482 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SrcOver_SkModeColorFilter) 483 484protected: 485 SrcOver_SkModeColorFilter(SkReadBuffer& buffer) 486 : INHERITED(buffer) { 487 fColor32Proc = SkBlitRow::ColorProcFactory(); 488 } 489 490private: 491 492 SkBlitRow::ColorProc fColor32Proc; 493 494 typedef SkModeColorFilter INHERITED; 495}; 496 497/////////////////////////////////////////////////////////////////////////////// 498 499SkColorFilter* SkColorFilter::CreateModeFilter(SkColor color, 500 SkXfermode::Mode mode) { 501 unsigned alpha = SkColorGetA(color); 502 503 // first collaps some modes if possible 504 505 if (SkXfermode::kClear_Mode == mode) { 506 color = 0; 507 mode = SkXfermode::kSrc_Mode; 508 } else if (SkXfermode::kSrcOver_Mode == mode) { 509 if (0 == alpha) { 510 mode = SkXfermode::kDst_Mode; 511 } else if (255 == alpha) { 512 mode = SkXfermode::kSrc_Mode; 513 } 514 // else just stay srcover 515 } 516 517 // weed out combinations that are noops, and just return null 518 if (SkXfermode::kDst_Mode == mode || 519 (0 == alpha && (SkXfermode::kSrcOver_Mode == mode || 520 SkXfermode::kDstOver_Mode == mode || 521 SkXfermode::kDstOut_Mode == mode || 522 SkXfermode::kSrcATop_Mode == mode || 523 SkXfermode::kXor_Mode == mode || 524 SkXfermode::kDarken_Mode == mode)) || 525 (0xFF == alpha && SkXfermode::kDstIn_Mode == mode)) { 526 return NULL; 527 } 528 529 switch (mode) { 530 case SkXfermode::kSrc_Mode: 531 return SkNEW_ARGS(Src_SkModeColorFilter, (color)); 532 case SkXfermode::kSrcOver_Mode: 533 return SkNEW_ARGS(SrcOver_SkModeColorFilter, (color)); 534 default: 535 return SkNEW_ARGS(SkModeColorFilter, (color, mode)); 536 } 537} 538 539/////////////////////////////////////////////////////////////////////////////// 540 541static SkScalar byte_to_scale(U8CPU byte) { 542 if (0xFF == byte) { 543 // want to get this exact 544 return 1; 545 } else { 546 return byte * 0.00392156862745f; 547 } 548} 549 550SkColorFilter* SkColorFilter::CreateLightingFilter(SkColor mul, SkColor add) { 551 SkColorMatrix matrix; 552 matrix.setScale(byte_to_scale(SkColorGetR(mul)), 553 byte_to_scale(SkColorGetG(mul)), 554 byte_to_scale(SkColorGetB(mul)), 555 1); 556 matrix.postTranslate(SkIntToScalar(SkColorGetR(add)), 557 SkIntToScalar(SkColorGetG(add)), 558 SkIntToScalar(SkColorGetB(add)), 559 0); 560 return SkColorMatrixFilter::Create(matrix); 561} 562 563SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkColorFilter) 564 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkModeColorFilter) 565 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(Src_SkModeColorFilter) 566 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SrcOver_SkModeColorFilter) 567SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END 568