Do sRGB premul/unpremul on the GPU
authorBrian Osman <brianosman@google.com>
Wed, 12 Apr 2017 21:07:22 +0000 (17:07 -0400)
committerSkia Commit-Bot <skia-commit-bot@chromium.org>
Thu, 13 Apr 2017 13:57:50 +0000 (13:57 +0000)
Previously, the early check would decide that sRGB pixel configs were okay
(because they're 8888-unorm). Then we'd go to make the effect and decide
that we didn't want them to work. This led to the software fallback.

The software fallback was obviously slower, but also doing non-linear
premul/unpremul operations. Eventually, whether or not the premul is
linear should be dictated by the destination color space, but for now,
this is an improvement (and only affects the one GM that tests this
feature).

Bug: skia:
Change-Id: I0cf1ad5a7f552135ac1da728c6db2977652a433b
Reviewed-on: https://skia-review.googlesource.com/13321
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>

src/gpu/GrContext.cpp

index 31f1787..7ea4abd 100644 (file)
@@ -919,16 +919,20 @@ sk_sp<GrFragmentProcessor> GrContext::createPMToUPMEffect(sk_sp<GrFragmentProces
     ASSERT_SINGLE_OWNER
     // We should have already called this->testPMConversionsIfNecessary().
     SkASSERT(fDidTestPMConversions);
-    if (kRGBA_half_GrPixelConfig == config) {
-        return GrFragmentProcessor::UnpremulOutput(std::move(fp));
-    } else if (kRGBA_8888_GrPixelConfig == config || kBGRA_8888_GrPixelConfig == config) {
+    // We have specialized effects that guarantee round-trip conversion for these formats
+    if (kRGBA_8888_GrPixelConfig == config || kBGRA_8888_GrPixelConfig == config) {
         GrConfigConversionEffect::PMConversion pmToUPM =
             static_cast<GrConfigConversionEffect::PMConversion>(fPMToUPMConversion);
         if (GrConfigConversionEffect::kPMConversionCnt != pmToUPM) {
             return GrConfigConversionEffect::Make(std::move(fp), pmToUPM);
+        } else {
+            return nullptr;
         }
+    } else {
+        // For everything else (sRGB, half-float, etc...), it doesn't make sense to try and
+        // explicitly round the results. Just do the obvious, naive thing in the shader.
+        return GrFragmentProcessor::UnpremulOutput(std::move(fp));
     }
-    return nullptr;
 }
 
 sk_sp<GrFragmentProcessor> GrContext::createUPMToPMEffect(sk_sp<GrFragmentProcessor> fp,
@@ -936,16 +940,20 @@ sk_sp<GrFragmentProcessor> GrContext::createUPMToPMEffect(sk_sp<GrFragmentProces
     ASSERT_SINGLE_OWNER
     // We should have already called this->testPMConversionsIfNecessary().
     SkASSERT(fDidTestPMConversions);
-    if (kRGBA_half_GrPixelConfig == config) {
-        return GrFragmentProcessor::PremulOutput(std::move(fp));
-    } else if (kRGBA_8888_GrPixelConfig == config || kBGRA_8888_GrPixelConfig == config) {
+    // We have specialized effects that guarantee round-trip conversion for these formats
+    if (kRGBA_8888_GrPixelConfig == config || kBGRA_8888_GrPixelConfig == config) {
         GrConfigConversionEffect::PMConversion upmToPM =
             static_cast<GrConfigConversionEffect::PMConversion>(fUPMToPMConversion);
         if (GrConfigConversionEffect::kPMConversionCnt != upmToPM) {
             return GrConfigConversionEffect::Make(std::move(fp), upmToPM);
+        } else {
+            return nullptr;
         }
+    } else {
+        // For everything else (sRGB, half-float, etc...), it doesn't make sense to try and
+        // explicitly round the results. Just do the obvious, naive thing in the shader.
+        return GrFragmentProcessor::PremulOutput(std::move(fp));
     }
-    return nullptr;
 }
 
 bool GrContext::validPMUPMConversionExists(GrPixelConfig config) const {