Index: src/core/SkBlitter_PM4f.cpp |
diff --git a/src/core/SkBlitter_PM4f.cpp b/src/core/SkBlitter_PM4f.cpp |
index 179aec355743d62d9ce45d9dd486d212275790f1..da669a2df106676309fb059a05568c3f64e3e70e 100644 |
--- a/src/core/SkBlitter_PM4f.cpp |
+++ b/src/core/SkBlitter_PM4f.cpp |
@@ -134,17 +134,25 @@ public: |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
-template <typename State> class SkState_Shader_Blitter : public SkShaderBlitter { |
+template <typename State, bool UseBProc> class SkState_Shader_Blitter : public SkShaderBlitter { |
public: |
SkState_Shader_Blitter(const SkPixmap& device, const SkPaint& paint, |
- SkShader::Context* shaderContext) |
- : INHERITED(device, paint, shaderContext) |
- , fState(device.info(), paint, shaderContext) |
+ const SkShader::Context::BlitState& bstate, |
+ SkShader::Context::BlitProc bproc) |
+ : INHERITED(device, paint, bstate.fCtx) |
+ , fState(device.info(), paint, bstate.fCtx) |
+ , fBState(bstate) |
+ , fBProc(bproc) |
{} |
void blitH(int x, int y, int width) override { |
SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width()); |
+ if (UseBProc) { |
+ fBProc(&fBState, x, y, fDevice, width, nullptr); |
+ return; |
+ } |
+ |
typename State::DstType* device = State::WritableAddr(fDevice, x, y); |
fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width); |
fState.fProcN(fState.fXfer, device, fState.fBuffer, width, nullptr); |
@@ -152,15 +160,21 @@ public: |
void blitV(int x, int y, int height, SkAlpha alpha) override { |
SkASSERT(x >= 0 && y >= 0 && y + height <= fDevice.height()); |
- |
+ |
+ if (UseBProc) { |
+ for (const int bottom = y + height; y < bottom; ++y) { |
+ fBProc(&fBState, x, y, fDevice, 1, &alpha); |
+ } |
+ return; |
+ } |
+ |
typename State::DstType* device = State::WritableAddr(fDevice, x, y); |
- size_t deviceRB = fDevice.rowBytes(); |
- const int bottom = y + height; |
+ size_t deviceRB = fDevice.rowBytes(); |
if (fConstInY) { |
fShaderContext->shadeSpan4f(x, y, fState.fBuffer, 1); |
} |
- for (; y < bottom; ++y) { |
+ for (const int bottom = y + height; y < bottom; ++y) { |
if (!fConstInY) { |
fShaderContext->shadeSpan4f(x, y, fState.fBuffer, 1); |
} |
@@ -173,14 +187,20 @@ public: |
SkASSERT(x >= 0 && y >= 0 && |
x + width <= fDevice.width() && y + height <= fDevice.height()); |
+ if (UseBProc) { |
+ for (const int bottom = y + height; y < bottom; ++y) { |
+ fBProc(&fBState, x, y, fDevice, width, nullptr); |
+ } |
+ return; |
+ } |
+ |
typename State::DstType* device = State::WritableAddr(fDevice, x, y); |
- size_t deviceRB = fDevice.rowBytes(); |
- const int bottom = y + height; |
+ size_t deviceRB = fDevice.rowBytes(); |
if (fConstInY) { |
fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width); |
} |
- for (; y < bottom; ++y) { |
+ for (const int bottom = y + height; y < bottom; ++y) { |
if (!fConstInY) { |
fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width); |
} |
@@ -199,12 +219,16 @@ public: |
} |
int aa = *antialias; |
if (aa) { |
- fShaderContext->shadeSpan4f(x, y, fState.fBuffer, count); |
- if (aa == 255) { |
- fState.fProcN(fState.fXfer, device, fState.fBuffer, count, nullptr); |
+ if (UseBProc && (aa == 255)) { |
+ fBProc(&fBState, x, y, fDevice, count, nullptr); |
} else { |
- for (int i = 0; i < count; ++i) { |
- fState.fProcN(fState.fXfer, &device[i], &fState.fBuffer[i], 1, antialias); |
+ fShaderContext->shadeSpan4f(x, y, fState.fBuffer, count); |
+ if (aa == 255) { |
+ fState.fProcN(fState.fXfer, device, fState.fBuffer, count, nullptr); |
+ } else { |
+ for (int i = 0; i < count; ++i) { |
+ fState.fProcN(fState.fXfer, &device[i], &fState.fBuffer[i], 1, antialias); |
+ } |
} |
} |
} |
@@ -249,17 +273,25 @@ public: |
this->INHERITED::blitMask(mask, clip); |
return; |
} |
- |
+ |
SkASSERT(mask.fBounds.contains(clip)); |
- |
+ |
const int x = clip.fLeft; |
const int width = clip.width(); |
int y = clip.fTop; |
- |
- typename State::DstType* device = State::WritableAddr(fDevice, x, y); |
- const size_t deviceRB = fDevice.rowBytes(); |
const uint8_t* maskRow = (const uint8_t*)mask.getAddr(x, y); |
const size_t maskRB = mask.fRowBytes; |
+ |
+ if (UseBProc) { |
+ for (; y < clip.fBottom; ++y) { |
+ fBProc(&fBState, x, y, fDevice, width, maskRow); |
+ maskRow += maskRB; |
+ } |
+ return; |
+ } |
+ |
+ typename State::DstType* device = State::WritableAddr(fDevice, x, y); |
+ const size_t deviceRB = fDevice.rowBytes(); |
if (fConstInY) { |
fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width); |
@@ -274,13 +306,16 @@ public: |
} |
} |
-private: |
- State fState; |
+protected: |
+ State fState; |
+ SkShader::Context::BlitState fBState; |
+ SkShader::Context::BlitProc fBProc; |
typedef SkShaderBlitter INHERITED; |
}; |
-////////////////////////////////////////////////////////////////////////////////////// |
+/////////////////////////////////////////////////////////////////////////////////////////////////// |
+/////////////////////////////////////////////////////////////////////////////////////////////////// |
static bool is_opaque(const SkPaint& paint, const SkShader::Context* shaderContext) { |
return shaderContext ? SkToBool(shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag) |
@@ -302,6 +337,9 @@ struct State4f { |
SkPM4f fPM4f; |
SkAutoTMalloc<SkPM4f> fBuffer; |
uint32_t fFlags; |
+ |
+ SkShader::Context::BlitState fBState; |
+ SkShader::Context::BlitProc fBProc; |
}; |
struct State32 : State4f { |
@@ -372,9 +410,20 @@ template <typename State> SkBlitter* create(const SkPixmap& device, const SkPain |
SkShader::Context* shaderContext, |
SkTBlitterAllocator* allocator) { |
SkASSERT(allocator != nullptr); |
- |
+ |
if (shaderContext) { |
- return allocator->createT<SkState_Shader_Blitter<State>>(device, paint, shaderContext); |
+ SkShader::Context::BlitState bstate; |
+ bstate.fCtx = shaderContext; |
+ bstate.fXfer = paint.getXfermode(); |
+ |
+ auto bproc = shaderContext->chooseBlitProc(device.info(), &bstate); |
+ if (bproc) { |
+ return allocator->createT<SkState_Shader_Blitter<State, true>>(device, paint, bstate, |
+ bproc); |
+ } else { |
+ return allocator->createT<SkState_Shader_Blitter<State, false>>(device, paint, bstate, |
+ bproc); |
+ } |
} else { |
SkColor color = paint.getColor(); |
if (0 == SkColorGetA(color)) { |