Index: src/core/SkBitmapProcShader.cpp |
diff --git a/src/core/SkBitmapProcShader.cpp b/src/core/SkBitmapProcShader.cpp |
index c9df4ce248c7c6d6b5a3f947f26aaa36b56d3065..3b90704084884b99f6001adc27245723dfeb6978 100644 |
--- a/src/core/SkBitmapProcShader.cpp |
+++ b/src/core/SkBitmapProcShader.cpp |
@@ -121,12 +121,19 @@ public: |
SkBitmapProcInfo* info) |
: INHERITED(shader, rec, info) |
{ |
+ // Save things off in case we need to build a blitter pipeline. |
+ fSrcPixmap = info->fPixmap; |
+ fAlpha = SkColorGetA(info->fPaintColor) / 255.0f; |
+ fXMode = info->fTileModeX; |
+ fYMode = info->fTileModeY; |
+ fFilterQuality = info->fFilterQuality; |
+ fMatrixTypeMask = info->fRealInvMatrix.getType(); |
+ |
// Need to ensure that our pipeline is created at a 16byte aligned address |
- fPipeline = (SkLinearBitmapPipeline*)SkAlign16((intptr_t)fStorage); |
- float alpha = SkColorGetA(info->fPaintColor) / 255.0f; |
- new (fPipeline) SkLinearBitmapPipeline(info->fRealInvMatrix, info->fFilterQuality, |
+ fShaderPipeline = (SkLinearBitmapPipeline*)SkAlign16((intptr_t)fShaderStorage); |
+ new (fShaderPipeline) SkLinearBitmapPipeline(info->fRealInvMatrix, info->fFilterQuality, |
info->fTileModeX, info->fTileModeY, |
- alpha, |
+ fAlpha, |
info->fPixmap); |
// To implement the old shadeSpan entry-point, we need to efficiently convert our native |
@@ -138,11 +145,14 @@ public: |
~LinearPipelineContext() override { |
// since we did a manual new, we need to manually destroy as well. |
- fPipeline->~SkLinearBitmapPipeline(); |
+ fShaderPipeline->~SkLinearBitmapPipeline(); |
+ if (fBlitterPipeline != nullptr) { |
+ fBlitterPipeline->~SkLinearBitmapPipeline(); |
+ } |
} |
void shadeSpan4f(int x, int y, SkPM4f dstC[], int count) override { |
- fPipeline->shadeSpan4f(x, y, dstC, count); |
+ fShaderPipeline->shadeSpan4f(x, y, dstC, count); |
} |
void shadeSpan(int x, int y, SkPMColor dstC[], int count) override { |
@@ -151,7 +161,7 @@ public: |
while (count > 0) { |
const int n = SkTMin(count, N); |
- fPipeline->shadeSpan4f(x, y, tmp, n); |
+ fShaderPipeline->shadeSpan4f(x, y, tmp, n); |
fXferProc(nullptr, dstC, tmp, n, nullptr); |
dstC += n; |
x += n; |
@@ -159,14 +169,53 @@ public: |
} |
} |
+ bool onChooseBlitProcs(const SkImageInfo& dstInfo, BlitState* state) override { |
+ SkXfermode::Mode mode; |
+ if (!SkXfermode::AsMode(state->fXfer, &mode)) { return false; } |
+ |
+ // Need to ensure that our pipeline is created at a 16byte aligned address |
+ fBlitterPipeline = (SkLinearBitmapPipeline*)SkAlign16((intptr_t)fBlitterStorage); |
+ if (SkLinearBitmapPipeline::ClonePipelineForBlitting( |
+ fBlitterPipeline, *fShaderPipeline, |
+ fMatrixTypeMask, |
+ fXMode, fYMode, |
+ fFilterQuality, fSrcPixmap, |
+ fAlpha, mode, dstInfo)) { |
+ |
+ state->fStorage[0] = fBlitterPipeline; |
+ state->fBlitBW = &LinearPipelineContext::ForwardToPipeline; |
+ |
+ return true; |
+ } |
+ |
+ // Did not successfully create a pipeline so don't destruct it. |
+ fBlitterPipeline = nullptr; |
+ return false; |
+ } |
+ |
+ static void ForwardToPipeline(BlitState* state, int x, int y, const SkPixmap& dst, int count) { |
+ SkLinearBitmapPipeline* pipeline = static_cast<SkLinearBitmapPipeline*>(state->fStorage[0]); |
+ void* addr = dst.writable_addr32(x, y); |
+ pipeline->blitSpan(x, y, addr, count); |
+ } |
+ |
+ |
private: |
enum { |
kActualSize = sizeof(SkLinearBitmapPipeline), |
kPaddedSize = SkAlignPtr(kActualSize + 12), |
}; |
- void* fStorage[kPaddedSize / sizeof(void*)]; |
- SkLinearBitmapPipeline* fPipeline; |
+ void* fShaderStorage[kPaddedSize / sizeof(void*)]; |
+ SkLinearBitmapPipeline* fShaderPipeline; |
+ void* fBlitterStorage[kPaddedSize / sizeof(void*)]; |
+ SkLinearBitmapPipeline* fBlitterPipeline{nullptr}; |
SkXfermode::D32Proc fXferProc; |
+ SkPixmap fSrcPixmap; |
+ float fAlpha; |
+ SkShader::TileMode fXMode; |
+ SkShader::TileMode fYMode; |
+ SkMatrix::TypeMask fMatrixTypeMask; |
+ SkFilterQuality fFilterQuality; |
typedef BitmapProcInfoContext INHERITED; |
}; |