aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/core/SkColorFilter.cpp6
-rw-r--r--src/gpu/GrYUVProvider.cpp3
-rw-r--r--src/gpu/effects/GrSRGBEffect.cpp52
-rw-r--r--src/gpu/effects/GrSRGBEffect.h13
-rw-r--r--tests/ApplyGammaTest.cpp31
5 files changed, 69 insertions, 36 deletions
diff --git a/src/core/SkColorFilter.cpp b/src/core/SkColorFilter.cpp
index 6cc8ae8161..d8e68c8db5 100644
--- a/src/core/SkColorFilter.cpp
+++ b/src/core/SkColorFilter.cpp
@@ -216,11 +216,13 @@ public:
#if SK_SUPPORT_GPU
sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext* x, SkColorSpace* cs) const override {
+ // wish our caller would let us know if our input was opaque...
+ GrSRGBEffect::Alpha alpha = GrSRGBEffect::Alpha::kPremul;
switch (fDir) {
case Direction::kLinearToSRGB:
- return GrSRGBEffect::Make(GrSRGBEffect::Mode::kLinearToSRGB);
+ return GrSRGBEffect::Make(GrSRGBEffect::Mode::kLinearToSRGB, alpha);
case Direction::kSRGBToLinear:
- return GrSRGBEffect::Make(GrSRGBEffect::Mode::kSRGBToLinear);
+ return GrSRGBEffect::Make(GrSRGBEffect::Mode::kSRGBToLinear, alpha);
}
return nullptr;
}
diff --git a/src/gpu/GrYUVProvider.cpp b/src/gpu/GrYUVProvider.cpp
index 5ab926be35..df7113911f 100644
--- a/src/gpu/GrYUVProvider.cpp
+++ b/src/gpu/GrYUVProvider.cpp
@@ -148,7 +148,8 @@ sk_sp<GrTextureProxy> GrYUVProvider::refAsTextureProxy(GrContext* ctx,
if (ctx->caps()->srgbWriteControl()) {
paint.setDisableOutputConversionToSRGB(true);
} else {
- paint.addColorFragmentProcessor(GrSRGBEffect::Make(GrSRGBEffect::Mode::kSRGBToLinear));
+ paint.addColorFragmentProcessor(GrSRGBEffect::Make(GrSRGBEffect::Mode::kSRGBToLinear,
+ GrSRGBEffect::Alpha::kOpaque));
}
}
diff --git a/src/gpu/effects/GrSRGBEffect.cpp b/src/gpu/effects/GrSRGBEffect.cpp
index c9a48b3d84..294e7f4551 100644
--- a/src/gpu/effects/GrSRGBEffect.cpp
+++ b/src/gpu/effects/GrSRGBEffect.cpp
@@ -47,18 +47,26 @@ public:
args.fInputColor = "vec4(1)";
}
- fragBuilder->codeAppendf("%s = vec4(%s(%s.r), %s(%s.g), %s(%s.b), %s.a);",
- args.fOutputColor,
- srgbFuncName.c_str(), args.fInputColor,
- srgbFuncName.c_str(), args.fInputColor,
- srgbFuncName.c_str(), args.fInputColor,
- args.fInputColor);
+ fragBuilder->codeAppendf("vec4 color = %s;", args.fInputColor);
+ if (srgbe.alpha() == GrSRGBEffect::Alpha::kPremul) {
+ fragBuilder->codeAppendf("float nonZeroAlpha = max(color.a, 0.00001);");
+ fragBuilder->codeAppendf("color = vec4(color.rgb / nonZeroAlpha, color.a);");
+ }
+ fragBuilder->codeAppendf("color = vec4(%s(color.r), %s(color.g), %s(color.b), color.a);",
+ srgbFuncName.c_str(),
+ srgbFuncName.c_str(),
+ srgbFuncName.c_str());
+ if (srgbe.alpha() == GrSRGBEffect::Alpha::kPremul) {
+ fragBuilder->codeAppendf("color = vec4(color.rgb, 1) * color.a;");
+ }
+ fragBuilder->codeAppendf("%s = color;", args.fOutputColor);
}
static inline void GenKey(const GrProcessor& processor, const GrShaderCaps&,
GrProcessorKeyBuilder* b) {
const GrSRGBEffect& srgbe = processor.cast<GrSRGBEffect>();
- uint32_t key = static_cast<uint32_t>(srgbe.mode());
+ uint32_t key = static_cast<uint32_t>(srgbe.mode()) |
+ (static_cast<uint32_t>(srgbe.alpha()) << 1);
b->add32(key);
}
@@ -68,10 +76,12 @@ private:
///////////////////////////////////////////////////////////////////////////////
-GrSRGBEffect::GrSRGBEffect(Mode mode)
- : INHERITED(kPreservesOpaqueInput_OptimizationFlag |
- kConstantOutputForConstantInput_OptimizationFlag)
- , fMode(mode) {
+GrSRGBEffect::GrSRGBEffect(Mode mode, Alpha alpha)
+ : INHERITED(kPreservesOpaqueInput_OptimizationFlag |
+ kConstantOutputForConstantInput_OptimizationFlag)
+ , fMode(mode)
+ , fAlpha(alpha)
+{
this->initClassID<GrSRGBEffect>();
}
@@ -87,17 +97,19 @@ static inline float linear_to_srgb(float linear) {
return (linear <= 0.0031308) ? linear * 12.92f : 1.055f * powf(linear, 1.f / 2.4f) - 0.055f;
}
-GrColor4f GrSRGBEffect::constantOutputForConstantInput(GrColor4f input) const {
+GrColor4f GrSRGBEffect::constantOutputForConstantInput(GrColor4f color) const {
+ color = color.unpremul();
switch (fMode) {
case Mode::kLinearToSRGB:
- return GrColor4f(linear_to_srgb(input.fRGBA[0]), linear_to_srgb(input.fRGBA[1]),
- linear_to_srgb(input.fRGBA[2]), input.fRGBA[3]);
+ color = GrColor4f(linear_to_srgb(color.fRGBA[0]), linear_to_srgb(color.fRGBA[1]),
+ linear_to_srgb(color.fRGBA[2]), color.fRGBA[3]);
+ break;
case Mode::kSRGBToLinear:
- return GrColor4f(srgb_to_linear(input.fRGBA[0]), srgb_to_linear(input.fRGBA[1]),
- srgb_to_linear(input.fRGBA[2]), input.fRGBA[3]);
+ color = GrColor4f(srgb_to_linear(color.fRGBA[0]), srgb_to_linear(color.fRGBA[1]),
+ srgb_to_linear(color.fRGBA[2]), color.fRGBA[3]);
+ break;
}
- SkFAIL("Unexpected mode");
- return GrColor4f::TransparentBlack();
+ return color.premul();
}
///////////////////////////////////////////////////////////////////////////////
@@ -107,7 +119,7 @@ GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrSRGBEffect);
#if GR_TEST_UTILS
sk_sp<GrFragmentProcessor> GrSRGBEffect::TestCreate(GrProcessorTestData* d) {
Mode testMode = static_cast<Mode>(d->fRandom->nextRangeU(0, 1));
- return GrSRGBEffect::Make(testMode);
+ return GrSRGBEffect::Make(testMode, Alpha::kPremul);
}
#endif
@@ -119,6 +131,6 @@ void GrSRGBEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
}
GrGLSLFragmentProcessor* GrSRGBEffect::onCreateGLSLInstance() const {
- return new GrGLSRGBEffect();
+ return new GrGLSRGBEffect;
}
diff --git a/src/gpu/effects/GrSRGBEffect.h b/src/gpu/effects/GrSRGBEffect.h
index f91224e56d..13d8bc3cb9 100644
--- a/src/gpu/effects/GrSRGBEffect.h
+++ b/src/gpu/effects/GrSRGBEffect.h
@@ -17,19 +17,25 @@ public:
kSRGBToLinear,
};
+ enum class Alpha {
+ kPremul,
+ kOpaque,
+ };
+
/**
* Creates an effect that applies the sRGB transfer function (or its inverse)
*/
- static sk_sp<GrFragmentProcessor> Make(Mode mode) {
- return sk_sp<GrFragmentProcessor>(new GrSRGBEffect(mode));
+ static sk_sp<GrFragmentProcessor> Make(Mode mode, Alpha alpha) {
+ return sk_sp<GrFragmentProcessor>(new GrSRGBEffect(mode, alpha));
}
const char* name() const override { return "sRGB"; }
Mode mode() const { return fMode; }
+ Alpha alpha() const { return fAlpha; }
private:
- GrSRGBEffect(Mode mode);
+ GrSRGBEffect(Mode mode, Alpha);
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
@@ -38,6 +44,7 @@ private:
GrColor4f constantOutputForConstantInput(GrColor4f input) const override;
Mode fMode;
+ Alpha fAlpha;
GR_DECLARE_FRAGMENT_PROCESSOR_TEST
diff --git a/tests/ApplyGammaTest.cpp b/tests/ApplyGammaTest.cpp
index 79dbfc7cd9..83b5968a9b 100644
--- a/tests/ApplyGammaTest.cpp
+++ b/tests/ApplyGammaTest.cpp
@@ -44,10 +44,17 @@ bool check_gamma(uint32_t src, uint32_t dst, bool toSRGB, float error,
result = false;
}
+ // need to unpremul before we can perform srgb magic
+ float invScale = 0;
+ float alpha = SkGetPackedA32(src);
+ if (alpha) {
+ invScale = 255.0f / alpha;
+ }
+
for (int c = 0; c < 3; ++c) {
- uint8_t srcComponent = (src & (0xff << (c * 8))) >> (c * 8);
- float lower = SkTMax(0.f, (float)srcComponent - error);
- float upper = SkTMin(255.f, (float)srcComponent + error);
+ float srcComponent = ((src & (0xff << (c * 8))) >> (c * 8)) * invScale;
+ float lower = SkTMax(0.f, srcComponent - error);
+ float upper = SkTMin(255.f, srcComponent + error);
if (toSRGB) {
lower = linear_to_srgb(lower / 255.f);
upper = linear_to_srgb(upper / 255.f);
@@ -55,14 +62,16 @@ bool check_gamma(uint32_t src, uint32_t dst, bool toSRGB, float error,
lower = srgb_to_linear(lower / 255.f);
upper = srgb_to_linear(upper / 255.f);
}
+ lower *= alpha;
+ upper *= alpha;
SkASSERT(lower >= 0.f && lower <= 255.f);
SkASSERT(upper >= 0.f && upper <= 255.f);
uint8_t dstComponent = (dst & (0xff << (c * 8))) >> (c * 8);
- if (dstComponent < SkScalarFloorToInt(lower * 255.f) ||
- dstComponent > SkScalarCeilToInt(upper * 255.f)) {
+ if (dstComponent < SkScalarFloorToInt(lower) ||
+ dstComponent > SkScalarCeilToInt(upper)) {
result = false;
}
- uint8_t expectedComponent = SkScalarRoundToInt((lower + upper) * 127.5f);
+ uint8_t expectedComponent = SkScalarRoundToInt((lower + upper) * 0.5f);
expectedColor |= expectedComponent << (c * 8);
}
@@ -72,8 +81,8 @@ bool check_gamma(uint32_t src, uint32_t dst, bool toSRGB, float error,
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ApplyGamma, reporter, ctxInfo) {
GrContext* context = ctxInfo.grContext();
- static const int kW = 10;
- static const int kH = 10;
+ static const int kW = 256;
+ static const int kH = 256;
static const size_t kRowBytes = sizeof(uint32_t) * kW;
GrSurfaceDesc baseDesc;
@@ -84,8 +93,10 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ApplyGamma, reporter, ctxInfo) {
const SkImageInfo ii = SkImageInfo::MakeN32Premul(kW, kH);
SkAutoTMalloc<uint32_t> srcPixels(kW * kH);
- for (int i = 0; i < kW * kH; ++i) {
- srcPixels.get()[i] = i;
+ for (int y = 0; y < kH; ++y) {
+ for (int x = 0; x < kW; ++x) {
+ srcPixels.get()[y*kW+x] = SkPreMultiplyARGB(x, y, x, 0xFF);
+ }
}
SkBitmap bm;