GrSRGBEffect.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /*
  2. * Copyright 2016 Google Inc.
  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. #include "src/gpu/effects/GrSRGBEffect.h"
  8. #include "src/gpu/GrFragmentProcessor.h"
  9. #include "src/gpu/GrProcessor.h"
  10. #include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
  11. #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
  12. class GrGLSRGBEffect : public GrGLSLFragmentProcessor {
  13. public:
  14. void emitCode(EmitArgs& args) override {
  15. const GrSRGBEffect& srgbe = args.fFp.cast<GrSRGBEffect>();
  16. GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
  17. SkString srgbFuncName;
  18. const GrShaderVar gSrgbArgs[] = {
  19. GrShaderVar("x", kHalf_GrSLType),
  20. };
  21. switch (srgbe.mode()) {
  22. case GrSRGBEffect::Mode::kLinearToSRGB:
  23. fragBuilder->emitFunction(kHalf_GrSLType,
  24. "linear_to_srgb",
  25. SK_ARRAY_COUNT(gSrgbArgs),
  26. gSrgbArgs,
  27. "return (x <= 0.0031308) ? (x * 12.92) "
  28. ": (1.055 * pow(x, 0.416666667) - 0.055);",
  29. &srgbFuncName);
  30. break;
  31. case GrSRGBEffect::Mode::kSRGBToLinear:
  32. fragBuilder->emitFunction(kHalf_GrSLType,
  33. "srgb_to_linear",
  34. SK_ARRAY_COUNT(gSrgbArgs),
  35. gSrgbArgs,
  36. "return (x <= 0.04045) ? (x / 12.92) "
  37. ": pow((x + 0.055) / 1.055, 2.4);",
  38. &srgbFuncName);
  39. break;
  40. }
  41. // Mali Bifrost uses fp16 for mediump. Making the intermediate color variable highp causes
  42. // calculations to be performed with sufficient precision.
  43. fragBuilder->codeAppendf("float4 color = %s;", args.fInputColor);
  44. if (srgbe.alpha() == GrSRGBEffect::Alpha::kPremul) {
  45. fragBuilder->codeAppendf("float nonZeroAlpha = max(color.a, 0.0001);");
  46. fragBuilder->codeAppendf("color = float4(color.rgb / nonZeroAlpha, color.a);");
  47. }
  48. fragBuilder->codeAppendf("color = float4(%s(half(color.r)), %s(half(color.g)), "
  49. "%s(half(color.b)), color.a);",
  50. srgbFuncName.c_str(),
  51. srgbFuncName.c_str(),
  52. srgbFuncName.c_str());
  53. if (srgbe.alpha() == GrSRGBEffect::Alpha::kPremul) {
  54. fragBuilder->codeAppendf("color = float4(color.rgb, 1) * color.a;");
  55. }
  56. fragBuilder->codeAppendf("%s = half4(color);", args.fOutputColor);
  57. }
  58. static inline void GenKey(const GrProcessor& processor, const GrShaderCaps&,
  59. GrProcessorKeyBuilder* b) {
  60. const GrSRGBEffect& srgbe = processor.cast<GrSRGBEffect>();
  61. uint32_t key = static_cast<uint32_t>(srgbe.mode()) |
  62. (static_cast<uint32_t>(srgbe.alpha()) << 1);
  63. b->add32(key);
  64. }
  65. private:
  66. typedef GrGLSLFragmentProcessor INHERITED;
  67. };
  68. ///////////////////////////////////////////////////////////////////////////////
  69. GrSRGBEffect::GrSRGBEffect(Mode mode, Alpha alpha)
  70. : INHERITED(kGrSRGBEffect_ClassID, kPreservesOpaqueInput_OptimizationFlag |
  71. kConstantOutputForConstantInput_OptimizationFlag)
  72. , fMode(mode)
  73. , fAlpha(alpha)
  74. {
  75. }
  76. std::unique_ptr<GrFragmentProcessor> GrSRGBEffect::clone() const { return Make(fMode, fAlpha); }
  77. bool GrSRGBEffect::onIsEqual(const GrFragmentProcessor& s) const {
  78. const GrSRGBEffect& other = s.cast<GrSRGBEffect>();
  79. return other.fMode == fMode;
  80. }
  81. static inline float srgb_to_linear(float srgb) {
  82. return (srgb <= 0.04045f) ? srgb / 12.92f : powf((srgb + 0.055f) / 1.055f, 2.4f);
  83. }
  84. static inline float linear_to_srgb(float linear) {
  85. return (linear <= 0.0031308) ? linear * 12.92f : 1.055f * powf(linear, 1.f / 2.4f) - 0.055f;
  86. }
  87. SkPMColor4f GrSRGBEffect::constantOutputForConstantInput(const SkPMColor4f& inColor) const {
  88. SkColor4f color = inColor.unpremul();
  89. switch (fMode) {
  90. case Mode::kLinearToSRGB:
  91. color = { linear_to_srgb(color.fR), linear_to_srgb(color.fG), linear_to_srgb(color.fB),
  92. color.fA };
  93. break;
  94. case Mode::kSRGBToLinear:
  95. color = { srgb_to_linear(color.fR), srgb_to_linear(color.fG), srgb_to_linear(color.fB),
  96. color.fA };
  97. break;
  98. }
  99. return color.premul();
  100. }
  101. ///////////////////////////////////////////////////////////////////////////////
  102. GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrSRGBEffect);
  103. #if GR_TEST_UTILS
  104. std::unique_ptr<GrFragmentProcessor> GrSRGBEffect::TestCreate(GrProcessorTestData* d) {
  105. Mode testMode = static_cast<Mode>(d->fRandom->nextRangeU(0, 1));
  106. return GrSRGBEffect::Make(testMode, Alpha::kPremul);
  107. }
  108. #endif
  109. ///////////////////////////////////////////////////////////////////////////////
  110. void GrSRGBEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
  111. GrProcessorKeyBuilder* b) const {
  112. GrGLSRGBEffect::GenKey(*this, caps, b);
  113. }
  114. GrGLSLFragmentProcessor* GrSRGBEffect::onCreateGLSLInstance() const {
  115. return new GrGLSRGBEffect;
  116. }