aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar reed <reed@google.com>2016-03-16 12:29:01 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-03-16 12:29:01 -0700
commit830dfd87a7707f687e13da5be645e75c746a2cf5 (patch)
tree27554aeb706c0932962c81eb87e81e0c1e19fece
parentf594b4c6df896f71fe2288c9a910bd67dad5a90b (diff)
add blitprocs to shaders
-rw-r--r--include/core/SkShader.h17
-rw-r--r--src/core/SkBlitter_PM4f.cpp101
-rw-r--r--src/core/SkColorShader.h3
-rw-r--r--src/core/SkShader.cpp40
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();
}