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
This commit is contained in:
herb 2016-05-26 10:56:17 -07:00 committed by Commit bot
parent 2bec26a716
commit a62038c478

View File

@ -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();
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;
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<SkSpriteBlitter_memcpy>(source);
if (SkSpriteBlitter_Src_SrcOver::Supports(dst, source, paint)) {
blitter = allocator->createT<SkSpriteBlitter_Src_SrcOver>(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;
}
}