diff options
author | reed <reed@google.com> | 2016-03-16 12:29:01 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-03-16 12:29:01 -0700 |
commit | 830dfd87a7707f687e13da5be645e75c746a2cf5 (patch) | |
tree | 27554aeb706c0932962c81eb87e81e0c1e19fece | |
parent | f594b4c6df896f71fe2288c9a910bd67dad5a90b (diff) |
add blitprocs to shaders
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1793883002
Review URL: https://codereview.chromium.org/1793883002
-rw-r--r-- | include/core/SkShader.h | 17 | ||||
-rw-r--r-- | src/core/SkBlitter_PM4f.cpp | 101 | ||||
-rw-r--r-- | src/core/SkColorShader.h | 3 | ||||
-rw-r--r-- | src/core/SkShader.cpp | 40 |
4 files changed, 135 insertions, 26 deletions
diff --git a/include/core/SkShader.h b/include/core/SkShader.h index 8002f630c4..39ffd86f3a 100644 --- a/include/core/SkShader.h +++ b/include/core/SkShader.h @@ -142,6 +142,18 @@ public: virtual void shadeSpan4f(int x, int y, SkPM4f[], int count); + struct BlitState { + Context* fCtx; + SkXfermode* fXfer; + enum { N = 2 }; + void* fStorage[N]; + }; + typedef void (*BlitProc)(BlitState*, + int x, int y, const SkPixmap&, int count, const SkAlpha[]); + BlitProc chooseBlitProc(const SkImageInfo& info, BlitState* state) { + return this->onChooseBlitProc(info, state); + } + /** * The const void* ctx is only const because all the implementations are const. * This can be changed to non-const if a new shade proc needs to change the ctx. @@ -175,6 +187,11 @@ public: const SkMatrix& getTotalInverse() const { return fTotalInverse; } MatrixClass getInverseClass() const { return (MatrixClass)fTotalInverseClass; } const SkMatrix& getCTM() const { return fCTM; } + + virtual BlitProc onChooseBlitProc(const SkImageInfo&, BlitState*) { + return nullptr; + } + private: SkMatrix fCTM; SkMatrix fTotalInverse; diff --git a/src/core/SkBlitter_PM4f.cpp b/src/core/SkBlitter_PM4f.cpp index 179aec3557..da669a2df1 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)) { diff --git a/src/core/SkColorShader.h b/src/core/SkColorShader.h index 7f817b54be..cc3ec45e08 100644 --- a/src/core/SkColorShader.h +++ b/src/core/SkColorShader.h @@ -35,6 +35,9 @@ public: void shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) override; void shadeSpan4f(int x, int y, SkPM4f[], int count) override; + protected: + BlitProc onChooseBlitProc(const SkImageInfo&, BlitState*) override; + private: SkPM4f fPM4f; SkPMColor fPMColor; diff --git a/src/core/SkShader.cpp b/src/core/SkShader.cpp index 1413a6ee73..cb0517bf64 100644 --- a/src/core/SkShader.cpp +++ b/src/core/SkShader.cpp @@ -361,6 +361,46 @@ void SkColorShader::toString(SkString* str) const { /////////////////////////////////////////////////////////////////////////////// +static void D32_BlitProc(SkShader::Context::BlitState* state, int x, int y, const SkPixmap& dst, + int count, const SkAlpha aa[]) { + SkXfermode::D32Proc proc = (SkXfermode::D32Proc)state->fStorage[0]; + const SkPM4f* src = (const SkPM4f*)state->fStorage[1]; + proc(state->fXfer, dst.writable_addr32(x, y), src, count, aa); +} + +static void D64_BlitProc(SkShader::Context::BlitState* state, int x, int y, const SkPixmap& dst, + int count, const SkAlpha aa[]) { + SkXfermode::D64Proc proc = (SkXfermode::D64Proc)state->fStorage[0]; + const SkPM4f* src = (const SkPM4f*)state->fStorage[1]; + proc(state->fXfer, dst.writable_addr64(x, y), src, count, aa); +} + +SkShader::Context::BlitProc +SkColorShader::ColorShaderContext::onChooseBlitProc(const SkImageInfo& info, BlitState* state) { + uint32_t flags = SkXfermode::kSrcIsSingle_D32Flag; + if (fPM4f.a() == 1) { + flags |= SkXfermode::kSrcIsOpaque_D32Flag; + } + switch (info.colorType()) { + case kN32_SkColorType: + if (info.isSRGB()) { + flags |= SkXfermode::kDstIsSRGB_D32Flag; + } + state->fStorage[0] = (void*)SkXfermode::GetD32Proc(state->fXfer, flags); + state->fStorage[1] = &fPM4f; + return D32_BlitProc; + case kRGBA_F16_SkColorType: + flags |= SkXfermode::kDstIsFloat16_D64Flag; + state->fStorage[0] = (void*)SkXfermode::GetD64Proc(state->fXfer, flags); + state->fStorage[1] = &fPM4f; + return D64_BlitProc; + default: + return nullptr; + } +} + +/////////////////////////////////////////////////////////////////////////////// + SkFlattenable* SkEmptyShader::CreateProc(SkReadBuffer&) { return SkShader::MakeEmptyShader().release(); } |