fold kClear_Mode into kSrc_Mode, and make kSrc_Mode go faster

Review URL: https://codereview.appspot.com/6851054

git-svn-id: http://skia.googlecode.com/svn/trunk@6451 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
reed@google.com 2012-11-16 13:20:41 +00:00
parent b1c42bbdcf
commit 13201e74f4
3 changed files with 191 additions and 9 deletions

View File

@ -871,6 +871,21 @@ SkBlitter* SkBlitter::Choose(const SkBitmap& device,
}
}
#ifndef SK_IGNORE_FAST_SRCMODE
/*
* If the xfermode is CLEAR, then we can completely ignore the installed
* color/shader/colorfilter, and just pretend we're SRC + color==0. This
* will fall into our optimizations for SRC mode.
*/
if (SkXfermode::IsMode(mode, SkXfermode::kClear_Mode)) {
SkPaint* p = paint.writable();
shader = p->setShader(NULL);
cf = p->setColorFilter(NULL);
mode = p->setXfermodeMode(SkXfermode::kSrc_Mode);
p->setColor(0);
}
#endif
if (NULL == shader) {
#ifdef SK_IGNORE_CF_OPTIMIZATION
if (mode || cf) {

View File

@ -263,6 +263,19 @@ void SkARGB32_Black_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
///////////////////////////////////////////////////////////////////////////////
#ifndef SK_IGNORE_FAST_SRCMODE
// Special version of SkBlitRow::Factory32 that knows we're in kSrc_Mode,
// instead of kSrcOver_Mode
static void blend_srcmode(SkPMColor* SK_RESTRICT device,
const SkPMColor* SK_RESTRICT span,
int count, U8CPU aa) {
int aa256 = SkAlpha255To256(aa);
for (int i = 0; i < count; ++i) {
device[i] = SkFourByteInterp256(span[i], device[i], aa256);
}
}
#endif
SkARGB32_Shader_Blitter::SkARGB32_Shader_Blitter(const SkBitmap& device,
const SkPaint& paint) : INHERITED(device, paint) {
fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * (sizeof(SkPMColor)));
@ -278,6 +291,25 @@ SkARGB32_Shader_Blitter::SkARGB32_Shader_Blitter(const SkBitmap& device,
fProc32 = SkBlitRow::Factory32(flags);
// we call this on the output from the shader + alpha from the aa buffer
fProc32Blend = SkBlitRow::Factory32(flags | SkBlitRow::kGlobalAlpha_Flag32);
fShadeDirectlyIntoDevice = false;
if (fXfermode == NULL) {
if (fShader->getFlags() & SkShader::kOpaqueAlpha_Flag) {
fShadeDirectlyIntoDevice = true;
}
} else {
#ifndef SK_IGNORE_FAST_SRCMODE
SkXfermode::Mode mode;
if (fXfermode->asMode(&mode)) {
if (SkXfermode::kSrc_Mode == mode) {
fShadeDirectlyIntoDevice = true;
fProc32Blend = blend_srcmode;
}
}
#endif
}
fConstInY = SkToBool(fShader->getFlags() & SkShader::kConstInY32_Flag);
}
SkARGB32_Shader_Blitter::~SkARGB32_Shader_Blitter() {
@ -290,7 +322,7 @@ void SkARGB32_Shader_Blitter::blitH(int x, int y, int width) {
uint32_t* device = fDevice.getAddr32(x, y);
if (fXfermode == NULL && (fShader->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
if (fShadeDirectlyIntoDevice) {
fShader->shadeSpan(x, y, device, width);
} else {
SkPMColor* span = fBuffer;
@ -310,8 +342,39 @@ void SkARGB32_Shader_Blitter::blitRect(int x, int y, int width, int height) {
uint32_t* device = fDevice.getAddr32(x, y);
size_t deviceRB = fDevice.rowBytes();
SkShader* shader = fShader;
SkPMColor* span = fBuffer;
if (fXfermode == NULL && (shader->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
if (fConstInY) {
if (fShadeDirectlyIntoDevice) {
// shade the first row directly into the device
fShader->shadeSpan(x, y, device, width);
span = device;
while (--height > 0) {
device = (uint32_t*)((char*)device + deviceRB);
memcpy(device, span, width << 2);
}
} else {
fShader->shadeSpan(x, y, span, width);
SkXfermode* xfer = fXfermode;
if (xfer) {
do {
xfer->xfer32(device, span, width, NULL);
y += 1;
device = (uint32_t*)((char*)device + deviceRB);
} while (--height > 0);
} else {
SkBlitRow::Proc32 proc = fProc32;
do {
proc(device, span, width, 255);
y += 1;
device = (uint32_t*)((char*)device + deviceRB);
} while (--height > 0);
}
}
return;
}
if (fShadeDirectlyIntoDevice) {
void* ctx;
SkShader::ShadeProc shadeProc = fShader->asAShadeProc(&ctx);
if (shadeProc) {
@ -328,7 +391,6 @@ void SkARGB32_Shader_Blitter::blitRect(int x, int y, int width, int height) {
} while (--height > 0);
}
} else {
SkPMColor* span = fBuffer;
SkXfermode* xfer = fXfermode;
if (xfer) {
do {
@ -355,7 +417,7 @@ void SkARGB32_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
uint32_t* device = fDevice.getAddr32(x, y);
SkShader* shader = fShader;
if (fXfermode) {
if (fXfermode && !fShadeDirectlyIntoDevice) {
for (;;) {
SkXfermode* xfer = fXfermode;
@ -379,7 +441,8 @@ void SkARGB32_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
antialias += count;
x += count;
}
} else if (fShader->getFlags() & SkShader::kOpaqueAlpha_Flag) {
} else if (fShadeDirectlyIntoDevice ||
(fShader->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
for (;;) {
int count = *runs;
if (count <= 0) {
@ -400,7 +463,7 @@ void SkARGB32_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
antialias += count;
x += count;
}
} else { // no xfermode but the shader not opaque
} else {
for (;;) {
int count = *runs;
if (count <= 0) {
@ -480,3 +543,102 @@ void SkARGB32_Shader_Blitter::blitMask(const SkMask& mask, const SkIRect& clip)
}
}
#ifndef SK_IGNORE_FAST_SRCMODE
void SkARGB32_Shader_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
SkASSERT(x >= 0 && y >= 0 && y + height <= fDevice.height());
uint32_t* device = fDevice.getAddr32(x, y);
size_t deviceRB = fDevice.rowBytes();
SkShader* shader = fShader;
if (fConstInY) {
SkPMColor c;
fShader->shadeSpan(x, y, &c, 1);
if (fShadeDirectlyIntoDevice) {
if (255 == alpha) {
do {
*device = c;
device = (uint32_t*)((char*)device + deviceRB);
} while (--height > 0);
} else {
do {
*device = SkFourByteInterp(c, *device, alpha);
device = (uint32_t*)((char*)device + deviceRB);
} while (--height > 0);
}
} else {
SkXfermode* xfer = fXfermode;
if (xfer) {
do {
xfer->xfer32(device, &c, 1, &alpha);
device = (uint32_t*)((char*)device + deviceRB);
} while (--height > 0);
} else {
SkBlitRow::Proc32 proc = fProc32;
do {
proc(device, &c, 1, alpha);
device = (uint32_t*)((char*)device + deviceRB);
} while (--height > 0);
}
}
return;
}
if (fShadeDirectlyIntoDevice) {
void* ctx;
SkShader::ShadeProc shadeProc = fShader->asAShadeProc(&ctx);
if (255 == alpha) {
if (shadeProc) {
do {
shadeProc(ctx, x, y, device, 1);
y += 1;
device = (uint32_t*)((char*)device + deviceRB);
} while (--height > 0);
} else {
do {
shader->shadeSpan(x, y, device, 1);
y += 1;
device = (uint32_t*)((char*)device + deviceRB);
} while (--height > 0);
}
} else { // alpha < 255
SkPMColor c;
if (shadeProc) {
do {
shadeProc(ctx, x, y, &c, 1);
*device = SkFourByteInterp(c, *device, alpha);
y += 1;
device = (uint32_t*)((char*)device + deviceRB);
} while (--height > 0);
} else {
do {
shader->shadeSpan(x, y, &c, 1);
*device = SkFourByteInterp(c, *device, alpha);
y += 1;
device = (uint32_t*)((char*)device + deviceRB);
} while (--height > 0);
}
}
} else {
SkPMColor* span = fBuffer;
SkXfermode* xfer = fXfermode;
if (xfer) {
do {
shader->shadeSpan(x, y, span, 1);
xfer->xfer32(device, span, 1, &alpha);
y += 1;
device = (uint32_t*)((char*)device + deviceRB);
} while (--height > 0);
} else {
// can't use fProc, since we need to use an unknown alpha
do {
shader->shadeSpan(x, y, span, 1);
*device = SkFourByteInterp(*span, *device, alpha);
y += 1;
device = (uint32_t*)((char*)device + deviceRB);
} while (--height > 0);
}
}
}
#endif

View File

@ -129,16 +129,21 @@ class SkARGB32_Shader_Blitter : public SkShaderBlitter {
public:
SkARGB32_Shader_Blitter(const SkBitmap& device, const SkPaint& paint);
virtual ~SkARGB32_Shader_Blitter();
virtual void blitH(int x, int y, int width);
virtual void blitH(int x, int y, int width) SK_OVERRIDE;
#ifndef SK_IGNORE_FAST_SRCMODE
virtual void blitV(int x, int y, int height, SkAlpha alpha) SK_OVERRIDE;
#endif
virtual void blitRect(int x, int y, int width, int height) SK_OVERRIDE;
virtual void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]);
virtual void blitMask(const SkMask&, const SkIRect&);
virtual void blitAntiH(int x, int y, const SkAlpha[], const int16_t[]) SK_OVERRIDE;
virtual void blitMask(const SkMask&, const SkIRect&) SK_OVERRIDE;
private:
SkXfermode* fXfermode;
SkPMColor* fBuffer;
SkBlitRow::Proc32 fProc32;
SkBlitRow::Proc32 fProc32Blend;
bool fShadeDirectlyIntoDevice;
bool fConstInY;
// illegal
SkARGB32_Shader_Blitter& operator=(const SkARGB32_Shader_Blitter&);