From a62038c478be1d668b3a1cea6b6974ddb5d90281 Mon Sep 17 00:00:00 2001 From: herb Date: Thu, 26 May 2016 10:56:17 -0700 Subject: [PATCH] Srcover for sprite blitters. In order for this code to run, the gDefaultProfileIsSRGB flag needs to be true. min base min exp percent name 5601856 4689911 0.837207 top25desk_espn.skp_1 3491515 3202806 0.917311 top25desk_facebook.skp_1 5110247 4865740 0.952154 top25desk_weather_com.skp_1 605445 585520 0.96709 top25desk_techcrunch_com.skp_1 1007151 986193 0.979191 top25desk_wikipedia__1_tab_.skp_1 5951286 5889979 0.989699 top25desk_sports_yahoo_com_.skp_1 2825583 2804853 0.992663 top25desk_plus_google_com_11003.skp_1 8839265 8823249 0.998188 top25desk_twitter.skp_1 4169125 4168882 0.999942 top25desk_docs___1_open_documen.skp_1 6615327 6620663 1.00081 top25desk_youtube_com.skp_1 4613903 4647583 1.0073 top25desk_wordpress.skp_1 2532280 2554154 1.00864 top25desk_ebay_com.skp_1 4015689 4063584 1.01193 top25desk_google_com__hl_en_q_b.skp_1 9427478 9579203 1.01609 top25desk_answers_yahoo_com.skp_1 7403901 7542770 1.01876 top25desk_booking_com.skp_1 12249953 12528353 1.02273 top25desk_google_com_search_q_c.skp_1 1078648 1111050 1.03004 top25desk_games_yahoo_com.skp_1 7232627 7481555 1.03442 top25desk_pinterest.skp_1 2996819 3112091 1.03846 top25desk_google_com_calendar_.skp_1 2181531 2271677 1.04132 top25desk_amazon_com.skp_1 925245 987545 1.06733 top25desk_blogger.skp_1 4143359 4442607 1.07222 top25desk_linkedin.skp_1 4370962 4744580 1.08548 top25desk_news_yahoo_com.skp_1 4284025 4735094 1.10529 top25desk_mail_google_com_mail_.skp_1 [mtklein] We measured the noise here to be [-5%, +8%], so most of these changes fall within the noise. We manually confirmed the two above that noise window (yahoo and mail) are also noise... srcover_srgb_srgb() did not figure prominently in their profiles. The espn and facebook improvements look real. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1996683003 Review-Url: https://codereview.chromium.org/1996683003 --- src/core/SkBlitter_Sprite.cpp | 69 ++++++++++++++++++++++++++++++++----------- 1 file changed, 51 insertions(+), 18 deletions(-) diff --git a/src/core/SkBlitter_Sprite.cpp b/src/core/SkBlitter_Sprite.cpp index c0b7430..2ddc5f4 100644 --- a/src/core/SkBlitter_Sprite.cpp +++ b/src/core/SkBlitter_Sprite.cpp @@ -5,6 +5,7 @@ * found in the LICENSE file. */ +#include "SkOpts.h" #include "SkSmallAllocator.h" #include "SkSpriteBlitter.h" @@ -43,7 +44,7 @@ void SkSpriteBlitter::blitMask(const SkMask&, const SkIRect& clip) { // 2. paint has no modifiers (i.e. alpha, colorfilter, etc.) // 3. xfermode needs no blending: e.g. kSrc_Mode or kSrcOver_Mode + opaque src // -class SkSpriteBlitter_memcpy : public SkSpriteBlitter { +class SkSpriteBlitter_Src_SrcOver : public SkSpriteBlitter { public: static bool Supports(const SkPixmap& dst, const SkPixmap& src, const SkPaint& paint) { if (dst.colorType() != src.colorType()) { @@ -68,14 +69,32 @@ public: if (SkXfermode::kSrcOver_Mode == mode && src.isOpaque()) { return true; } - return false; + + // At this point memcpy can't be used. The following check for using SrcOver. + + if (dst.colorType() != kN32_SkColorType + || dst.info().profileType() != kSRGB_SkColorProfileType) { + return false; + } + + return SkXfermode::kSrcOver_Mode == mode; } - SkSpriteBlitter_memcpy(const SkPixmap& src) : INHERITED(src) {} + SkSpriteBlitter_Src_SrcOver(const SkPixmap& src) : INHERITED(src) {} void setup(const SkPixmap& dst, int left, int top, const SkPaint& paint) override { SkASSERT(Supports(dst, fSource, paint)); this->INHERITED::setup(dst, left, top, paint); + SkXfermode::Mode mode; + if (!SkXfermode::AsMode(paint.getXfermode(), &mode)) { + SkFAIL("Should never happen."); + } + + SkASSERT(mode == SkXfermode::kSrcOver_Mode || mode == SkXfermode::kSrc_Mode); + + if (mode == SkXfermode::kSrcOver_Mode && !fSource.isOpaque()) { + fUseMemcpy = false; + } } void blitRect(int x, int y, int width, int height) override { @@ -83,22 +102,37 @@ public: SkASSERT(fDst.info().profileType() == fSource.info().profileType()); SkASSERT(width > 0 && height > 0); - char* dst = (char*)fDst.writable_addr(x, y); - const char* src = (const char*)fSource.addr(x - fLeft, y - fTop); - const size_t dstRB = fDst.rowBytes(); - const size_t srcRB = fSource.rowBytes(); - const size_t bytesToCopy = width << fSource.shiftPerPixel(); - - while (--height >= 0) { - memcpy(dst, src, bytesToCopy); - dst += dstRB; - src += srcRB; + if (fUseMemcpy) { + char* dst = (char*)fDst.writable_addr(x, y); + const char* src = (const char*)fSource.addr(x - fLeft, y - fTop); + const size_t dstRB = fDst.rowBytes(); + const size_t srcRB = fSource.rowBytes(); + const size_t bytesToCopy = width << fSource.shiftPerPixel(); + + while (height --> 0) { + memcpy(dst, src, bytesToCopy); + dst += dstRB; + src += srcRB; + } + } else { + uint32_t* dst = fDst.writable_addr32(x, y); + const uint32_t* src = fSource.addr32(x - fLeft, y - fTop); + const int dstStride = fDst.rowBytesAsPixels(); + const int srcStride = fSource.rowBytesAsPixels(); + + while (height --> 0) { + SkOpts::srcover_srgb_srgb(dst, src, width, width); + dst += dstStride; + src += srcStride; + } } } +private: typedef SkSpriteBlitter INHERITED; -}; + bool fUseMemcpy {true}; +}; // returning null means the caller will call SkBlitter::Choose() and // have wrapped the source bitmap inside a shader @@ -115,10 +149,10 @@ SkBlitter* SkBlitter::ChooseSprite(const SkPixmap& dst, const SkPaint& paint, */ SkASSERT(allocator != nullptr); - SkSpriteBlitter* blitter; + SkSpriteBlitter* blitter = nullptr; - if (SkSpriteBlitter_memcpy::Supports(dst, source, paint)) { - blitter = allocator->createT(source); + if (SkSpriteBlitter_Src_SrcOver::Supports(dst, source, paint)) { + blitter = allocator->createT(source); } else { switch (dst.colorType()) { case kRGB_565_SkColorType: @@ -135,7 +169,6 @@ SkBlitter* SkBlitter::ChooseSprite(const SkPixmap& dst, const SkPaint& paint, blitter = SkSpriteBlitter::ChooseF16(source, paint, allocator); break; default: - blitter = nullptr; break; } } -- 2.7.4