add new blit2 methods in support of antialiased hairlines

before:
   9M	1	528µs	530µs	539µs	607µs	5%	▁▁▁▁▁▁▁▁█▂	8888	path_hairline_small_AA_quad

after:
   9M	1	355µs	356µs	358µs	375µs	2%	▂▁▁▁▁▁▁▁▁█	8888	path_hairline_small_AA_quad

BUG=skia:

does require new baselines (bug chrome is guarded)

Review URL: https://codereview.chromium.org/1060153003
This commit is contained in:
reed 2015-04-14 18:39:57 -07:00 committed by Commit bot
parent c3c5990ac0
commit dd83031b98
4 changed files with 124 additions and 90 deletions

View File

@ -1,4 +1,3 @@
/* /*
* Copyright 2006 The Android Open Source Project * Copyright 2006 The Android Open Source Project
* *
@ -6,10 +5,15 @@
* found in the LICENSE file. * found in the LICENSE file.
*/ */
#ifndef SkBlitter_DEFINED #ifndef SkBlitter_DEFINED
#define SkBlitter_DEFINED #define SkBlitter_DEFINED
#ifdef SK_SUPPORT_LEGACY_BLITANTIH2V2
#define SK_BLITANTIH2V2_VIRTUAL
#else
#define SK_BLITANTIH2V2_VIRTUAL virtual
#endif
#include "SkBitmap.h" #include "SkBitmap.h"
#include "SkBitmapProcShader.h" #include "SkBitmapProcShader.h"
#include "SkMask.h" #include "SkMask.h"
@ -55,6 +59,35 @@ public:
*/ */
virtual const SkBitmap* justAnOpaqueColor(uint32_t* value); virtual const SkBitmap* justAnOpaqueColor(uint32_t* value);
// (x, y), (x + 1, y)
SK_BLITANTIH2V2_VIRTUAL void blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) {
int16_t runs[3];
uint8_t aa[2];
runs[0] = 1;
runs[1] = 1;
runs[2] = 0;
aa[0] = SkToU8(a0);
aa[1] = SkToU8(a1);
this->blitAntiH(x, y, aa, runs);
}
// (x, y), (x, y + 1)
SK_BLITANTIH2V2_VIRTUAL void blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) {
int16_t runs[2];
uint8_t aa[1];
runs[0] = 1;
runs[1] = 0;
aa[0] = SkToU8(a0);
this->blitAntiH(x, y, aa, runs);
// reset in case the clipping blitter modified runs
runs[0] = 1;
runs[1] = 0;
aa[0] = SkToU8(a1);
this->blitAntiH(x, y + 1, aa, runs);
}
/** /**
* Special method just to identify the null blitter, which is returned * Special method just to identify the null blitter, which is returned
* from Choose() if the request cannot be fulfilled. Default impl * from Choose() if the request cannot be fulfilled. Default impl

View File

@ -106,6 +106,25 @@ void SkARGB32_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
} }
} }
#ifndef SK_SUPPORT_LEGACY_BLITANTIH2V2
void SkARGB32_Blitter::blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) {
uint32_t* device = fDevice.getAddr32(x, y);
SkDEBUGCODE((void)fDevice.getAddr32(x + 1, y);)
device[0] = SkBlendARGB32(fPMColor, device[0], a0);
device[1] = SkBlendARGB32(fPMColor, device[1], a1);
}
void SkARGB32_Blitter::blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) {
uint32_t* device = fDevice.getAddr32(x, y);
SkDEBUGCODE((void)fDevice.getAddr32(x, y + 1);)
device[0] = SkBlendARGB32(fPMColor, device[0], a0);
device = (uint32_t*)((char*)device + fDevice.rowBytes());
device[0] = SkBlendARGB32(fPMColor, device[0], a1);
}
#endif
////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////
#define solid_8_pixels(mask, dst, color) \ #define solid_8_pixels(mask, dst, color) \
@ -180,6 +199,25 @@ void SkARGB32_Opaque_Blitter::blitMask(const SkMask& mask,
} }
} }
#ifndef SK_SUPPORT_LEGACY_BLITANTIH2V2
void SkARGB32_Opaque_Blitter::blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) {
uint32_t* device = fDevice.getAddr32(x, y);
SkDEBUGCODE((void)fDevice.getAddr32(x + 1, y);)
device[0] = SkFastFourByteInterp(fPMColor, device[0], a0);
device[1] = SkFastFourByteInterp(fPMColor, device[1], a1);
}
void SkARGB32_Opaque_Blitter::blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) {
uint32_t* device = fDevice.getAddr32(x, y);
SkDEBUGCODE((void)fDevice.getAddr32(x, y + 1);)
device[0] = SkFastFourByteInterp(fPMColor, device[0], a0);
device = (uint32_t*)((char*)device + fDevice.rowBytes());
device[0] = SkFastFourByteInterp(fPMColor, device[0], a1);
}
#endif
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
void SkARGB32_Blitter::blitV(int x, int y, int height, SkAlpha alpha) { void SkARGB32_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
@ -256,6 +294,25 @@ void SkARGB32_Black_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
} }
} }
#ifndef SK_SUPPORT_LEGACY_BLITANTIH2V2
void SkARGB32_Black_Blitter::blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) {
uint32_t* device = fDevice.getAddr32(x, y);
SkDEBUGCODE((void)fDevice.getAddr32(x + 1, y);)
device[0] = (a0 << SK_A32_SHIFT) + SkAlphaMulQ(device[0], 256 - a0);
device[1] = (a1 << SK_A32_SHIFT) + SkAlphaMulQ(device[1], 256 - a1);
}
void SkARGB32_Black_Blitter::blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) {
uint32_t* device = fDevice.getAddr32(x, y);
SkDEBUGCODE((void)fDevice.getAddr32(x, y + 1);)
device[0] = (a0 << SK_A32_SHIFT) + SkAlphaMulQ(device[0], 256 - a0);
device = (uint32_t*)((char*)device + fDevice.rowBytes());
device[0] = (a1 << SK_A32_SHIFT) + SkAlphaMulQ(device[0], 256 - a1);
}
#endif
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Special version of SkBlitRow::Factory32 that knows we're in kSrc_Mode, // Special version of SkBlitRow::Factory32 that knows we're in kSrc_Mode,

View File

@ -120,6 +120,10 @@ public:
virtual void blitRect(int x, int y, int width, int height); virtual void blitRect(int x, int y, int width, int height);
virtual void blitMask(const SkMask&, const SkIRect&); virtual void blitMask(const SkMask&, const SkIRect&);
virtual const SkBitmap* justAnOpaqueColor(uint32_t*); virtual const SkBitmap* justAnOpaqueColor(uint32_t*);
#ifndef SK_SUPPORT_LEGACY_BLITANTIH2V2
void blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) override;
void blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) override;
#endif
protected: protected:
SkColor fColor; SkColor fColor;
@ -140,6 +144,10 @@ public:
SkARGB32_Opaque_Blitter(const SkBitmap& device, const SkPaint& paint) SkARGB32_Opaque_Blitter(const SkBitmap& device, const SkPaint& paint)
: INHERITED(device, paint) { SkASSERT(paint.getAlpha() == 0xFF); } : INHERITED(device, paint) { SkASSERT(paint.getAlpha() == 0xFF); }
virtual void blitMask(const SkMask&, const SkIRect&); virtual void blitMask(const SkMask&, const SkIRect&);
#ifndef SK_SUPPORT_LEGACY_BLITANTIH2V2
void blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) override;
void blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) override;
#endif
private: private:
typedef SkARGB32_Blitter INHERITED; typedef SkARGB32_Blitter INHERITED;
@ -150,6 +158,10 @@ public:
SkARGB32_Black_Blitter(const SkBitmap& device, const SkPaint& paint) SkARGB32_Black_Blitter(const SkBitmap& device, const SkPaint& paint)
: INHERITED(device, paint) {} : INHERITED(device, paint) {}
virtual void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]); virtual void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]);
#ifndef SK_SUPPORT_LEGACY_BLITANTIH2V2
void blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) override;
void blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) override;
#endif
private: private:
typedef SkARGB32_Opaque_Blitter INHERITED; typedef SkARGB32_Opaque_Blitter INHERITED;

View File

@ -154,70 +154,29 @@ public:
class Horish_SkAntiHairBlitter : public SkAntiHairBlitter { class Horish_SkAntiHairBlitter : public SkAntiHairBlitter {
public: public:
SkFixed drawCap(int x, SkFixed fy, SkFixed dy, int mod64) override { SkFixed drawCap(int x, SkFixed fy, SkFixed dy, int mod64) override {
int16_t runs[2];
uint8_t aa[1];
runs[0] = 1;
runs[1] = 0;
fy += SK_Fixed1/2; fy += SK_Fixed1/2;
SkBlitter* blitter = this->getBlitter();
int lower_y = fy >> 16; int lower_y = fy >> 16;
uint8_t a = (uint8_t)(fy >> 8); uint8_t a = (uint8_t)(fy >> 8);
unsigned ma = SmallDot6Scale(a, mod64); unsigned a0 = SmallDot6Scale(255 - a, mod64);
if (ma) { unsigned a1 = SmallDot6Scale(a, mod64);
aa[0] = ApplyGamma(gamma, ma); this->getBlitter()->blitAntiV2(x, lower_y - 1, a0, a1);
blitter->blitAntiH(x, lower_y, aa, runs);
// the clipping blitters might edit runs, but should not affect us return fy + dy - SK_Fixed1/2;
SkASSERT(runs[0] == 1);
SkASSERT(runs[1] == 0);
}
ma = SmallDot6Scale(255 - a, mod64);
if (ma) {
aa[0] = ApplyGamma(gamma, ma);
blitter->blitAntiH(x, lower_y - 1, aa, runs);
// the clipping blitters might edit runs, but should not affect us
SkASSERT(runs[0] == 1);
SkASSERT(runs[1] == 0);
}
fy += dy;
return fy - SK_Fixed1/2;
} }
SkFixed drawLine(int x, int stopx, SkFixed fy, SkFixed dy) override { SkFixed drawLine(int x, int stopx, SkFixed fy, SkFixed dy) override {
SkASSERT(x < stopx); SkASSERT(x < stopx);
int16_t runs[2];
uint8_t aa[1];
runs[0] = 1;
runs[1] = 0;
fy += SK_Fixed1/2; fy += SK_Fixed1/2;
SkBlitter* blitter = this->getBlitter(); SkBlitter* blitter = this->getBlitter();
do { do {
int lower_y = fy >> 16; int lower_y = fy >> 16;
uint8_t a = (uint8_t)(fy >> 8); uint8_t a = (uint8_t)(fy >> 8);
if (a) { blitter->blitAntiV2(x, lower_y - 1, 255 - a, a);
aa[0] = a;
blitter->blitAntiH(x, lower_y, aa, runs);
// the clipping blitters might edit runs, but should not affect us
SkASSERT(runs[0] == 1);
SkASSERT(runs[1] == 0);
}
a = 255 - a;
if (a) {
aa[0] = a;
blitter->blitAntiH(x, lower_y - 1, aa, runs);
// the clipping blitters might edit runs, but should not affect us
SkASSERT(runs[0] == 1);
SkASSERT(runs[1] == 0);
}
fy += dy; fy += dy;
} while (++x < stopx); } while (++x < stopx);
return fy - SK_Fixed1/2; return fy - SK_Fixed1/2;
} }
}; };
@ -266,53 +225,26 @@ public:
class Vertish_SkAntiHairBlitter : public SkAntiHairBlitter { class Vertish_SkAntiHairBlitter : public SkAntiHairBlitter {
public: public:
SkFixed drawCap(int y, SkFixed fx, SkFixed dx, int mod64) override { SkFixed drawCap(int y, SkFixed fx, SkFixed dx, int mod64) override {
int16_t runs[3];
uint8_t aa[2];
runs[0] = 1;
runs[2] = 0;
fx += SK_Fixed1/2; fx += SK_Fixed1/2;
int x = fx >> 16; int x = fx >> 16;
uint8_t a = (uint8_t)(fx >> 8); uint8_t a = (uint8_t)(fx >> 8);
this->getBlitter()->blitAntiH2(x - 1, y,
aa[0] = SmallDot6Scale(255 - a, mod64); SmallDot6Scale(255 - a, mod64), SmallDot6Scale(a, mod64));
aa[1] = SmallDot6Scale(a, mod64);
// the clippng blitters might overwrite this guy, so we have to reset it each time return fx + dx - SK_Fixed1/2;
runs[1] = 1;
this->getBlitter()->blitAntiH(x - 1, y, aa, runs);
// the clipping blitters might edit runs, but should not affect us
SkASSERT(runs[0] == 1);
SkASSERT(runs[2] == 0);
fx += dx;
return fx - SK_Fixed1/2;
} }
SkFixed drawLine(int y, int stopy, SkFixed fx, SkFixed dx) override { SkFixed drawLine(int y, int stopy, SkFixed fx, SkFixed dx) override {
SkASSERT(y < stopy); SkASSERT(y < stopy);
int16_t runs[3];
uint8_t aa[2];
runs[0] = 1;
runs[2] = 0;
fx += SK_Fixed1/2; fx += SK_Fixed1/2;
do { do {
int x = fx >> 16; int x = fx >> 16;
uint8_t a = (uint8_t)(fx >> 8); uint8_t a = (uint8_t)(fx >> 8);
this->getBlitter()->blitAntiH2(x - 1, y, 255 - a, a);
aa[0] = 255 - a;
aa[1] = a;
// the clippng blitters might overwrite this guy, so we have to reset it each time
runs[1] = 1;
this->getBlitter()->blitAntiH(x - 1, y, aa, runs);
// the clipping blitters might edit runs, but should not affect us
SkASSERT(runs[0] == 1);
SkASSERT(runs[2] == 0);
fx += dx; fx += dx;
} while (++y < stopy); } while (++y < stopy);
return fx - SK_Fixed1/2; return fx - SK_Fixed1/2;
} }
}; };