| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2006 The Android Open Source Project | 2 * Copyright 2006 The Android Open Source Project |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkBlitRow.h" | 8 #include "SkBlitRow.h" |
| 9 #include "SkColorFilter.h" | 9 #include "SkColorFilter.h" |
| 10 #include "SkColorPriv.h" | 10 #include "SkColorPriv.h" |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 58 | 58 |
| 59 SkFlattenable* SkModeColorFilter::CreateProc(SkReadBuffer& buffer) { | 59 SkFlattenable* SkModeColorFilter::CreateProc(SkReadBuffer& buffer) { |
| 60 SkColor color = buffer.readColor(); | 60 SkColor color = buffer.readColor(); |
| 61 SkXfermode::Mode mode = (SkXfermode::Mode)buffer.readUInt(); | 61 SkXfermode::Mode mode = (SkXfermode::Mode)buffer.readUInt(); |
| 62 return SkColorFilter::CreateModeFilter(color, mode); | 62 return SkColorFilter::CreateModeFilter(color, mode); |
| 63 } | 63 } |
| 64 | 64 |
| 65 /////////////////////////////////////////////////////////////////////////////// | 65 /////////////////////////////////////////////////////////////////////////////// |
| 66 #if SK_SUPPORT_GPU | 66 #if SK_SUPPORT_GPU |
| 67 #include "GrBlend.h" | 67 #include "GrBlend.h" |
| 68 #include "GrFragmentProcessor.h" | |
| 69 #include "GrInvariantOutput.h" | 68 #include "GrInvariantOutput.h" |
| 70 #include "GrProcessorUnitTest.h" | 69 #include "effects/GrXfermodeFragmentProcessor.h" |
| 70 #include "effects/GrConstColorProcessor.h" |
| 71 #include "SkGr.h" | 71 #include "SkGr.h" |
| 72 #include "gl/GrGLFragmentProcessor.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 alrea
dy 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 nullptr; | |
| 136 } | |
| 137 return new 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 const char* name() const override { return "ModeColorFilterEffect"; } | |
| 151 | |
| 152 SkXfermode::Mode mode() const { return fMode; } | |
| 153 GrColor color() const { return fColor; } | |
| 154 | |
| 155 class GLProcessor : public GrGLFragmentProcessor { | |
| 156 public: | |
| 157 GLProcessor(const GrProcessor&) { | |
| 158 } | |
| 159 | |
| 160 virtual void emitCode(EmitArgs& args) override { | |
| 161 SkXfermode::Mode mode = args.fFp.cast<ModeColorFilterEffect>().mode(
); | |
| 162 | |
| 163 SkASSERT(SkXfermode::kDst_Mode != mode); | |
| 164 const char* colorFilterColorUniName = nullptr; | |
| 165 if (args.fFp.cast<ModeColorFilterEffect>().willUseFilterColor()) { | |
| 166 fFilterColorUni = args.fBuilder->addUniform( | |
| 167 GrGLProgramBuilder::kFragm
ent_Visibility, | |
| 168 kVec4f_GrSLType, kDefault_
GrSLPrecision, | |
| 169 "FilterColor", | |
| 170 &colorFilterColorUniName); | |
| 171 } | |
| 172 | |
| 173 GrGLSLExpr4 filter = | |
| 174 color_filter_expression(mode, GrGLSLExpr4(colorFilterColorUniNam
e), | |
| 175 GrGLSLExpr4(args.fInputColor)); | |
| 176 | |
| 177 args.fBuilder->getFragmentShaderBuilder()-> | |
| 178 codeAppendf("\t%s = %s;\n", args.fOutputColor, filter.c_str(
)); | |
| 179 } | |
| 180 | |
| 181 static void GenKey(const GrProcessor& fp, const GrGLSLCaps&, | |
| 182 GrProcessorKeyBuilder* b) { | |
| 183 const ModeColorFilterEffect& colorModeFilter = fp.cast<ModeColorFilt
erEffect>(); | |
| 184 // The SL code does not depend on filter color at the moment, so no
need to represent it | |
| 185 // in the key. | |
| 186 b->add32(colorModeFilter.mode()); | |
| 187 } | |
| 188 | |
| 189 protected: | |
| 190 virtual void onSetData(const GrGLProgramDataManager& pdman, | |
| 191 const GrProcessor& fp) override { | |
| 192 if (fFilterColorUni.isValid()) { | |
| 193 const ModeColorFilterEffect& colorModeFilter = fp.cast<ModeColor
FilterEffect>(); | |
| 194 GrGLfloat c[4]; | |
| 195 GrColorToRGBAFloat(colorModeFilter.color(), c); | |
| 196 pdman.set4fv(fFilterColorUni, 1, c); | |
| 197 } | |
| 198 } | |
| 199 | |
| 200 private: | |
| 201 | |
| 202 GrGLProgramDataManager::UniformHandle fFilterColorUni; | |
| 203 typedef GrGLFragmentProcessor INHERITED; | |
| 204 }; | |
| 205 | |
| 206 GR_DECLARE_FRAGMENT_PROCESSOR_TEST; | |
| 207 | |
| 208 private: | |
| 209 ModeColorFilterEffect(GrColor color, SkXfermode::Mode mode) | |
| 210 : fMode(mode), | |
| 211 fColor(color) { | |
| 212 this->initClassID<ModeColorFilterEffect>(); | |
| 213 } | |
| 214 | |
| 215 GrGLFragmentProcessor* onCreateGLInstance() const override { return new GLPr
ocessor(*this); } | |
| 216 | |
| 217 virtual void onGetGLProcessorKey(const GrGLSLCaps& caps, | |
| 218 GrProcessorKeyBuilder* b) const override { | |
| 219 GLProcessor::GenKey(*this, caps, b); | |
| 220 } | |
| 221 | |
| 222 bool onIsEqual(const GrFragmentProcessor& other) const override { | |
| 223 const ModeColorFilterEffect& s = other.cast<ModeColorFilterEffect>(); | |
| 224 return fMode == s.fMode && fColor == s.fColor; | |
| 225 } | |
| 226 | |
| 227 void onComputeInvariantOutput(GrInvariantOutput* inout) const override; | |
| 228 | |
| 229 SkXfermode::Mode fMode; | |
| 230 GrColor fColor; | |
| 231 | |
| 232 typedef GrFragmentProcessor INHERITED; | |
| 233 }; | |
| 234 | |
| 235 namespace { | |
| 236 | |
| 237 /** Function color_component_to_int tries to reproduce the GLSL rounding. The sp
ec doesn't specify | |
| 238 * to which direction the 0.5 goes. | |
| 239 */ | |
| 240 static inline int color_component_to_int(float value) { | |
| 241 return sk_float_round2int(SkTMax(0.f, SkTMin(1.f, value)) * 255.f); | |
| 242 } | |
| 243 | |
| 244 /** MaskedColorExpr is used to evaluate the color and valid color component flag
s through the | |
| 245 * blending equation. It has members similar to GrGLSLExpr so that it can be use
d with the | |
| 246 * templated helpers above. | |
| 247 */ | |
| 248 class MaskedColorExpr { | |
| 249 public: | |
| 250 MaskedColorExpr(const float color[], uint32_t flags) | |
| 251 : fFlags(flags) { | |
| 252 fColor[0] = color[0]; | |
| 253 fColor[1] = color[1]; | |
| 254 fColor[2] = color[2]; | |
| 255 fColor[3] = color[3]; | |
| 256 } | |
| 257 | |
| 258 MaskedColorExpr(float v, uint32_t flags = kRGBA_GrColorComponentFlags) | |
| 259 : fFlags(flags) { | |
| 260 fColor[0] = v; | |
| 261 fColor[1] = v; | |
| 262 fColor[2] = v; | |
| 263 fColor[3] = v; | |
| 264 } | |
| 265 | |
| 266 MaskedColorExpr operator*(const MaskedColorExpr& other) const { | |
| 267 float tmp[4]; | |
| 268 tmp[0] = fColor[0] * other.fColor[0]; | |
| 269 tmp[1] = fColor[1] * other.fColor[1]; | |
| 270 tmp[2] = fColor[2] * other.fColor[2]; | |
| 271 tmp[3] = fColor[3] * other.fColor[3]; | |
| 272 | |
| 273 return MaskedColorExpr(tmp, fFlags & other.fFlags); | |
| 274 } | |
| 275 | |
| 276 MaskedColorExpr operator+(const MaskedColorExpr& other) const { | |
| 277 float tmp[4]; | |
| 278 tmp[0] = fColor[0] + other.fColor[0]; | |
| 279 tmp[1] = fColor[1] + other.fColor[1]; | |
| 280 tmp[2] = fColor[2] + other.fColor[2]; | |
| 281 tmp[3] = fColor[3] + other.fColor[3]; | |
| 282 | |
| 283 return MaskedColorExpr(tmp, fFlags & other.fFlags); | |
| 284 } | |
| 285 | |
| 286 MaskedColorExpr operator-(const MaskedColorExpr& other) const { | |
| 287 float tmp[4]; | |
| 288 tmp[0] = fColor[0] - other.fColor[0]; | |
| 289 tmp[1] = fColor[1] - other.fColor[1]; | |
| 290 tmp[2] = fColor[2] - other.fColor[2]; | |
| 291 tmp[3] = fColor[3] - other.fColor[3]; | |
| 292 | |
| 293 return MaskedColorExpr(tmp, fFlags & other.fFlags); | |
| 294 } | |
| 295 | |
| 296 MaskedColorExpr a() const { | |
| 297 uint32_t flags = (fFlags & kA_GrColorComponentFlag) ? kRGBA_GrColorCompo
nentFlags : 0; | |
| 298 return MaskedColorExpr(fColor[3], flags); | |
| 299 } | |
| 300 | |
| 301 GrColor getColor() const { | |
| 302 return GrColorPackRGBA(color_component_to_int(fColor[0]), | |
| 303 color_component_to_int(fColor[1]), | |
| 304 color_component_to_int(fColor[2]), | |
| 305 color_component_to_int(fColor[3])); | |
| 306 } | |
| 307 | |
| 308 uint32_t getValidComponents() const { return fFlags; } | |
| 309 | |
| 310 typedef MaskedColorExpr AExpr; | |
| 311 private: | |
| 312 float fColor[4]; | |
| 313 uint32_t fFlags; | |
| 314 }; | |
| 315 | |
| 316 } | |
| 317 | |
| 318 void ModeColorFilterEffect::onComputeInvariantOutput(GrInvariantOutput* inout) c
onst { | |
| 319 float inputColor[4]; | |
| 320 GrColorToRGBAFloat(inout->color(), inputColor); | |
| 321 float filterColor[4]; | |
| 322 GrColorToRGBAFloat(fColor, filterColor); | |
| 323 MaskedColorExpr result = | |
| 324 color_filter_expression(fMode, | |
| 325 MaskedColorExpr(filterColor, kRGBA_GrColorCompon
entFlags), | |
| 326 MaskedColorExpr(inputColor, inout->validFlags())
); | |
| 327 | |
| 328 // Check if we will use the input color | |
| 329 SkXfermode::Coeff dstCoeff; | |
| 330 SkXfermode::Coeff srcCoeff; | |
| 331 SkAssertResult(SkXfermode::ModeAsCoeff(fMode, &srcCoeff, &dstCoeff)); | |
| 332 GrInvariantOutput::ReadInput readInput = GrInvariantOutput::kWill_ReadInput; | |
| 333 // These could be calculated from the blend equation with template trickery.
. | |
| 334 if (SkXfermode::kZero_Coeff == dstCoeff && | |
| 335 !GrBlendCoeffRefsDst(sk_blend_to_grblend(srcCoeff))) { | |
| 336 readInput = GrInvariantOutput::kWillNot_ReadInput; | |
| 337 } | |
| 338 inout->setToOther(result.getValidComponents(), result.getColor(), readInput)
; | |
| 339 } | |
| 340 | |
| 341 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ModeColorFilterEffect); | |
| 342 const GrFragmentProcessor* ModeColorFilterEffect::TestCreate(GrProcessorTestData
* d) { | |
| 343 SkXfermode::Mode mode = SkXfermode::kDst_Mode; | |
| 344 while (SkXfermode::kDst_Mode == mode) { | |
| 345 mode = static_cast<SkXfermode::Mode>(d->fRandom->nextRangeU(0, SkXfermod
e::kLastCoeffMode)); | |
| 346 } | |
| 347 | |
| 348 // pick a random premul color | |
| 349 uint8_t alpha = d->fRandom->nextULessThan(256); | |
| 350 GrColor color = GrColorPackRGBA(d->fRandom->nextRangeU(0, alpha), | |
| 351 d->fRandom->nextRangeU(0, alpha), | |
| 352 d->fRandom->nextRangeU(0, alpha), | |
| 353 alpha); | |
| 354 return ModeColorFilterEffect::Create(color, mode); | |
| 355 } | |
| 356 | 72 |
| 357 bool SkModeColorFilter::asFragmentProcessors(GrContext*, GrProcessorDataManager*
, | 73 bool SkModeColorFilter::asFragmentProcessors(GrContext*, GrProcessorDataManager*
, |
| 358 SkTDArray<GrFragmentProcessor*>* ar
ray) const { | 74 SkTDArray<const GrFragmentProcessor
*>* array) const { |
| 359 if (SkXfermode::kDst_Mode != fMode) { | 75 if (SkXfermode::kDst_Mode != fMode) { |
| 360 GrFragmentProcessor* frag = ModeColorFilterEffect::Create(SkColor2GrColo
r(fColor), fMode); | 76 SkAutoTUnref<const GrFragmentProcessor> constFP( |
| 361 if (frag) { | 77 GrConstColorProcessor::Create(SkColor2GrColor(fColor), |
| 78 GrConstColorProcessor::kIgnore_InputMo
de)); |
| 79 const GrFragmentProcessor* fp = |
| 80 GrXfermodeFragmentProcessor::CreateFromSrcProcessor(constFP, fMode); |
| 81 if (fp) { |
| 82 #ifdef SK_DEBUG |
| 83 // With a solid color input this should always be able to compute th
e blended color |
| 84 // (at least for coeff modes) |
| 85 if (fMode <= SkXfermode::kLastCoeffMode) { |
| 86 static SkRandom gRand; |
| 87 GrInvariantOutput io(GrPremulColor(gRand.nextU()), kRGBA_GrColor
ComponentFlags, |
| 88 false); |
| 89 fp->computeInvariantOutput(&io); |
| 90 SkASSERT(io.validFlags() == kRGBA_GrColorComponentFlags); |
| 91 } |
| 92 #endif |
| 362 if (array) { | 93 if (array) { |
| 363 *array->append() = frag; | 94 *array->append() = fp; |
| 364 } else { | 95 } else { |
| 365 frag->unref(); | 96 fp->unref(); |
| 366 SkDEBUGCODE(frag = nullptr;) | 97 SkDEBUGCODE(fp = nullptr;) |
| 367 } | 98 } |
| 368 return true; | 99 return true; |
| 369 } | 100 } |
| 370 } | 101 } |
| 371 return false; | 102 return false; |
| 372 } | 103 } |
| 373 | 104 |
| 374 #endif | 105 #endif |
| 375 | 106 |
| 376 /////////////////////////////////////////////////////////////////////////////// | 107 /////////////////////////////////////////////////////////////////////////////// |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 461 byte_to_scale(SkColorGetG(mul)), | 192 byte_to_scale(SkColorGetG(mul)), |
| 462 byte_to_scale(SkColorGetB(mul)), | 193 byte_to_scale(SkColorGetB(mul)), |
| 463 1); | 194 1); |
| 464 matrix.postTranslate(SkIntToScalar(SkColorGetR(add)), | 195 matrix.postTranslate(SkIntToScalar(SkColorGetR(add)), |
| 465 SkIntToScalar(SkColorGetG(add)), | 196 SkIntToScalar(SkColorGetG(add)), |
| 466 SkIntToScalar(SkColorGetB(add)), | 197 SkIntToScalar(SkColorGetB(add)), |
| 467 0); | 198 0); |
| 468 return SkColorMatrixFilter::Create(matrix); | 199 return SkColorMatrixFilter::Create(matrix); |
| 469 } | 200 } |
| 470 | 201 |
| OLD | NEW |