From: Brian Osman Date: Mon, 10 Apr 2017 17:42:48 +0000 (-0400) Subject: PM/UPM conversion improvements X-Git-Tag: accepted/tizen/5.0/unified/20181102.025319~46^2~59 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9f903e4a58c4639a2a17d0761400852009e6e936;p=platform%2Fupstream%2FlibSkiaSharp.git PM/UPM conversion improvements Snap input values to N / 255 before doing PM/UPM conversions, and add a new round-to-nearest conversion pair. With the pre-snapping, that pair is chosen by (almost?) every GPU we have. This now lets us round trip perfectly on Mali GPUs (which were falling back to SW before). Bug: skia: Change-Id: I0cebf1382e1c829aedfef4ec1614d7fa980057b5 Reviewed-on: https://skia-review.googlesource.com/11520 Reviewed-by: Brian Salomon Commit-Queue: Brian Osman --- diff --git a/src/gpu/effects/GrConfigConversionEffect.cpp b/src/gpu/effects/GrConfigConversionEffect.cpp index 07225f1..566a1af 100644 --- a/src/gpu/effects/GrConfigConversionEffect.cpp +++ b/src/gpu/effects/GrConfigConversionEffect.cpp @@ -27,7 +27,11 @@ public: // could optimize this case, but we aren't for now. args.fInputColor = "vec4(1)"; } - fragBuilder->codeAppendf("vec4 color = %s;", args.fInputColor); + + // Aggressively round to the nearest exact (N / 255) floating point value. This lets us + // find a round-trip preserving pair on some GPUs that do odd byte to float conversion. + fragBuilder->codeAppendf("vec4 color = floor(%s * 255.0 + 0.5) / 255.0;", + args.fInputColor); switch (cce.pmConversion()) { case GrConfigConversionEffect::kMulByAlpha_RoundUp_PMConversion: @@ -42,6 +46,11 @@ public: fragBuilder->codeAppend( "color.rgb = floor(color.rgb * color.a * 255.0 + 0.001) / 255.0;"); break; + case GrConfigConversionEffect::kMulByAlpha_RoundNearest_PMConversion: + fragBuilder->codeAppend( + "color.rgb = floor(color.rgb * color.a * 255.0 + 0.5) / 255.0;"); + break; + case GrConfigConversionEffect::kDivByAlpha_RoundUp_PMConversion: fragBuilder->codeAppend( "color.rgb = color.a <= 0.0 ? vec3(0,0,0) : ceil(color.rgb / color.a * 255.0) / 255.0;"); @@ -50,6 +59,11 @@ public: fragBuilder->codeAppend( "color.rgb = color.a <= 0.0 ? vec3(0,0,0) : floor(color.rgb / color.a * 255.0) / 255.0;"); break; + case GrConfigConversionEffect::kDivByAlpha_RoundNearest_PMConversion: + fragBuilder->codeAppend( + "color.rgb = color.a <= 0.0 ? vec3(0,0,0) : floor(color.rgb / color.a * 255.0 + 0.5) / 255.0;"); + break; + default: SkFAIL("Unknown conversion op."); break; @@ -155,13 +169,15 @@ void GrConfigConversionEffect::TestForPreservingPMConversions(GrContext* context } static const PMConversion kConversionRules[][2] = { + {kDivByAlpha_RoundNearest_PMConversion, kMulByAlpha_RoundNearest_PMConversion}, {kDivByAlpha_RoundDown_PMConversion, kMulByAlpha_RoundUp_PMConversion}, {kDivByAlpha_RoundUp_PMConversion, kMulByAlpha_RoundDown_PMConversion}, }; - bool failed = true; + uint32_t bestFailCount = 0xFFFFFFFF; + size_t bestRule = 0; - for (size_t i = 0; i < SK_ARRAY_COUNT(kConversionRules) && failed; ++i) { + for (size_t i = 0; i < SK_ARRAY_COUNT(kConversionRules) && bestFailCount; ++i) { *pmToUPMRule = kConversionRules[i][0]; *upmToPMRule = kConversionRules[i][1]; @@ -211,19 +227,27 @@ void GrConfigConversionEffect::TestForPreservingPMConversions(GrContext* context continue; } - failed = false; - for (int y = 0; y < kSize && !failed; ++y) { + uint32_t failCount = 0; + for (int y = 0; y < kSize; ++y) { for (int x = 0; x <= y; ++x) { if (firstRead[kSize * y + x] != secondRead[kSize * y + x]) { - failed = true; - break; + if (++failCount >= bestFailCount) { + break; + } } } } + if (failCount < bestFailCount) { + bestFailCount = failCount; + bestRule = i; + } } - if (failed) { + if (bestFailCount > 0) { *pmToUPMRule = kPMConversionCnt; *upmToPMRule = kPMConversionCnt; + } else { + *pmToUPMRule = kConversionRules[bestRule][0]; + *upmToPMRule = kConversionRules[bestRule][1]; } } diff --git a/src/gpu/effects/GrConfigConversionEffect.h b/src/gpu/effects/GrConfigConversionEffect.h index e5fa10c..4cc2aeb 100644 --- a/src/gpu/effects/GrConfigConversionEffect.h +++ b/src/gpu/effects/GrConfigConversionEffect.h @@ -22,8 +22,11 @@ public: enum PMConversion { kMulByAlpha_RoundUp_PMConversion = 0, kMulByAlpha_RoundDown_PMConversion, + kMulByAlpha_RoundNearest_PMConversion, + kDivByAlpha_RoundUp_PMConversion, kDivByAlpha_RoundDown_PMConversion, + kDivByAlpha_RoundNearest_PMConversion, kPMConversionCnt };