OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 #include "SkColorMatrixFilter.h" | 8 #include "SkColorMatrixFilter.h" |
9 #include "SkColorMatrix.h" | 9 #include "SkColorMatrix.h" |
10 #include "SkColorPriv.h" | 10 #include "SkColorPriv.h" |
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
342 static GrFragmentProcessor* Create(const SkColorMatrix& matrix) { | 342 static GrFragmentProcessor* Create(const SkColorMatrix& matrix) { |
343 return SkNEW_ARGS(ColorMatrixEffect, (matrix)); | 343 return SkNEW_ARGS(ColorMatrixEffect, (matrix)); |
344 } | 344 } |
345 | 345 |
346 static const char* Name() { return "Color Matrix"; } | 346 static const char* Name() { return "Color Matrix"; } |
347 | 347 |
348 virtual const GrBackendFragmentProcessorFactory& getFactory() const SK_OVERR
IDE { | 348 virtual const GrBackendFragmentProcessorFactory& getFactory() const SK_OVERR
IDE { |
349 return GrTBackendFragmentProcessorFactory<ColorMatrixEffect>::getInstanc
e(); | 349 return GrTBackendFragmentProcessorFactory<ColorMatrixEffect>::getInstanc
e(); |
350 } | 350 } |
351 | 351 |
352 virtual void getConstantColorComponents(GrColor* color, | |
353 uint32_t* validFlags) const SK_OVERR
IDE { | |
354 // We only bother to check whether the alpha channel will be constant. I
f SkColorMatrix had | |
355 // type flags it might be worth checking the other components. | |
356 | |
357 // The matrix is defined such the 4th row determines the output alpha. T
he first four | |
358 // columns of that row multiply the input r, g, b, and a, respectively,
and the last column | |
359 // is the "translation". | |
360 static const uint32_t kRGBAFlags[] = { | |
361 kR_GrColorComponentFlag, | |
362 kG_GrColorComponentFlag, | |
363 kB_GrColorComponentFlag, | |
364 kA_GrColorComponentFlag | |
365 }; | |
366 static const int kShifts[] = { | |
367 GrColor_SHIFT_R, GrColor_SHIFT_G, GrColor_SHIFT_B, GrColor_SHIFT_A, | |
368 }; | |
369 enum { | |
370 kAlphaRowStartIdx = 15, | |
371 kAlphaRowTranslateIdx = 19, | |
372 }; | |
373 | |
374 SkScalar outputA = 0; | |
375 for (int i = 0; i < 4; ++i) { | |
376 // If any relevant component of the color to be passed through the m
atrix is non-const | |
377 // then we can't know the final result. | |
378 if (0 != fMatrix.fMat[kAlphaRowStartIdx + i]) { | |
379 if (!(*validFlags & kRGBAFlags[i])) { | |
380 *validFlags = 0; | |
381 return; | |
382 } else { | |
383 uint32_t component = (*color >> kShifts[i]) & 0xFF; | |
384 outputA += fMatrix.fMat[kAlphaRowStartIdx + i] * component; | |
385 } | |
386 } | |
387 } | |
388 outputA += fMatrix.fMat[kAlphaRowTranslateIdx]; | |
389 *validFlags = kA_GrColorComponentFlag; | |
390 // We pin the color to [0,1]. This would happen to the *final* color out
put from the frag | |
391 // shader but currently the effect does not pin its own output. So in th
e case of over/ | |
392 // underflow this may deviate from the actual result. Maybe the effect s
hould pin its | |
393 // result if the matrix could over/underflow for any component? | |
394 *color = static_cast<uint8_t>(SkScalarPin(outputA, 0, 255)) << GrColor_S
HIFT_A; | |
395 } | |
396 | |
397 GR_DECLARE_FRAGMENT_PROCESSOR_TEST; | 352 GR_DECLARE_FRAGMENT_PROCESSOR_TEST; |
398 | 353 |
399 class GLProcessor : public GrGLFragmentProcessor { | 354 class GLProcessor : public GrGLFragmentProcessor { |
400 public: | 355 public: |
401 // this class always generates the same code. | 356 // this class always generates the same code. |
402 static void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBu
ilder* b) {} | 357 static void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBu
ilder* b) {} |
403 | 358 |
404 GLProcessor(const GrBackendProcessorFactory& factory, | 359 GLProcessor(const GrBackendProcessorFactory& factory, |
405 const GrProcessor&) | 360 const GrProcessor&) |
406 : INHERITED(factory) { | 361 : INHERITED(factory) { |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
464 }; | 419 }; |
465 | 420 |
466 private: | 421 private: |
467 ColorMatrixEffect(const SkColorMatrix& matrix) : fMatrix(matrix) {} | 422 ColorMatrixEffect(const SkColorMatrix& matrix) : fMatrix(matrix) {} |
468 | 423 |
469 virtual bool onIsEqual(const GrProcessor& s) const { | 424 virtual bool onIsEqual(const GrProcessor& s) const { |
470 const ColorMatrixEffect& cme = s.cast<ColorMatrixEffect>(); | 425 const ColorMatrixEffect& cme = s.cast<ColorMatrixEffect>(); |
471 return cme.fMatrix == fMatrix; | 426 return cme.fMatrix == fMatrix; |
472 } | 427 } |
473 | 428 |
| 429 virtual void onComputeInvariantOutput(InvariantOutput* inout) const SK_OVERR
IDE { |
| 430 // We only bother to check whether the alpha channel will be constant. I
f SkColorMatrix had |
| 431 // type flags it might be worth checking the other components. |
| 432 |
| 433 // The matrix is defined such the 4th row determines the output alpha. T
he first four |
| 434 // columns of that row multiply the input r, g, b, and a, respectively,
and the last column |
| 435 // is the "translation". |
| 436 static const uint32_t kRGBAFlags[] = { |
| 437 kR_GrColorComponentFlag, |
| 438 kG_GrColorComponentFlag, |
| 439 kB_GrColorComponentFlag, |
| 440 kA_GrColorComponentFlag |
| 441 }; |
| 442 static const int kShifts[] = { |
| 443 GrColor_SHIFT_R, GrColor_SHIFT_G, GrColor_SHIFT_B, GrColor_SHIFT_A, |
| 444 }; |
| 445 enum { |
| 446 kAlphaRowStartIdx = 15, |
| 447 kAlphaRowTranslateIdx = 19, |
| 448 }; |
| 449 |
| 450 SkScalar outputA = 0; |
| 451 for (int i = 0; i < 4; ++i) { |
| 452 // If any relevant component of the color to be passed through the m
atrix is non-const |
| 453 // then we can't know the final result. |
| 454 if (0 != fMatrix.fMat[kAlphaRowStartIdx + i]) { |
| 455 if (!(inout->fValidFlags & kRGBAFlags[i])) { |
| 456 inout->fValidFlags = 0; |
| 457 return; |
| 458 } else { |
| 459 uint32_t component = (inout->fColor >> kShifts[i]) & 0xFF; |
| 460 outputA += fMatrix.fMat[kAlphaRowStartIdx + i] * component; |
| 461 } |
| 462 } |
| 463 } |
| 464 outputA += fMatrix.fMat[kAlphaRowTranslateIdx]; |
| 465 inout->fValidFlags = kA_GrColorComponentFlag; |
| 466 // We pin the color to [0,1]. This would happen to the *final* color out
put from the frag |
| 467 // shader but currently the effect does not pin its own output. So in th
e case of over/ |
| 468 // underflow this may deviate from the actual result. Maybe the effect s
hould pin its |
| 469 // result if the matrix could over/underflow for any component? |
| 470 inout->fColor = static_cast<uint8_t>(SkScalarPin(outputA, 0, 255)) << Gr
Color_SHIFT_A; |
| 471 inout->fIsSingleComponent = false; |
| 472 } |
| 473 |
474 SkColorMatrix fMatrix; | 474 SkColorMatrix fMatrix; |
475 | 475 |
476 typedef GrFragmentProcessor INHERITED; | 476 typedef GrFragmentProcessor INHERITED; |
477 }; | 477 }; |
478 | 478 |
479 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ColorMatrixEffect); | 479 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ColorMatrixEffect); |
480 | 480 |
481 GrFragmentProcessor* ColorMatrixEffect::TestCreate(SkRandom* random, | 481 GrFragmentProcessor* ColorMatrixEffect::TestCreate(SkRandom* random, |
482 GrContext*, | 482 GrContext*, |
483 const GrDrawTargetCaps&, | 483 const GrDrawTargetCaps&, |
(...skipping 18 matching lines...) Expand all Loading... |
502 str->append("matrix: ("); | 502 str->append("matrix: ("); |
503 for (int i = 0; i < 20; ++i) { | 503 for (int i = 0; i < 20; ++i) { |
504 str->appendScalar(fMatrix.fMat[i]); | 504 str->appendScalar(fMatrix.fMat[i]); |
505 if (i < 19) { | 505 if (i < 19) { |
506 str->append(", "); | 506 str->append(", "); |
507 } | 507 } |
508 } | 508 } |
509 str->append(")"); | 509 str->append(")"); |
510 } | 510 } |
511 #endif | 511 #endif |
OLD | NEW |