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:
parent
b1c42bbdcf
commit
13201e74f4
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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&);
|
||||
|
Loading…
Reference in New Issue
Block a user