diff options
author | herb <herb@google.com> | 2016-04-12 14:07:59 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-04-12 14:07:59 -0700 |
commit | 69076fe5cf88c45b8dac4ca44bc5845f8817a57e (patch) | |
tree | 398cfe8125cbfa4c77ddba52420aaf1415ebac98 | |
parent | 9ac5b91957e59eeddebfae9630204f217c20cd4e (diff) |
Blitter for repeat RGBA8888->RGBA8888.
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1852613002
Review URL: https://codereview.chromium.org/1852613002
-rw-r--r-- | src/core/SkBitmapProcShader.cpp | 67 | ||||
-rw-r--r-- | src/core/SkBitmapProcShader.h | 2 | ||||
-rw-r--r-- | src/core/SkLinearBitmapPipeline.cpp | 61 | ||||
-rw-r--r-- | src/core/SkLinearBitmapPipeline.h | 28 |
4 files changed, 145 insertions, 13 deletions
diff --git a/src/core/SkBitmapProcShader.cpp b/src/core/SkBitmapProcShader.cpp index c9df4ce248..3b90704084 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; }; diff --git a/src/core/SkBitmapProcShader.h b/src/core/SkBitmapProcShader.h index 4df2614ca4..f6492f1887 100644 --- a/src/core/SkBitmapProcShader.h +++ b/src/core/SkBitmapProcShader.h @@ -50,7 +50,7 @@ private: typedef SkShader INHERITED; }; -enum {kSkBlitterContextSize = 2400}; +enum {kSkBlitterContextSize = 3100}; // Commonly used allocator. It currently is only used to allocate up to 3 objects. The total // bytes requested is calculated using one of our large shaders, its context size plus the size of diff --git a/src/core/SkLinearBitmapPipeline.cpp b/src/core/SkLinearBitmapPipeline.cpp index 539547af9a..cf69e974dd 100644 --- a/src/core/SkLinearBitmapPipeline.cpp +++ b/src/core/SkLinearBitmapPipeline.cpp @@ -776,8 +776,69 @@ SkLinearBitmapPipeline::SkLinearBitmapPipeline( fLastStage = blenderStage; } +bool SkLinearBitmapPipeline::ClonePipelineForBlitting( + void* blitterStorage, + const SkLinearBitmapPipeline& pipeline, + SkMatrix::TypeMask matrixMask, + SkShader::TileMode xTileMode, + SkShader::TileMode yTileMode, + SkFilterQuality filterQuality, + const SkPixmap& srcPixmap, + float finalAlpha, + SkXfermode::Mode xferMode, + const SkImageInfo& dstInfo) +{ + if (matrixMask & ~SkMatrix::kTranslate_Mask ) { return false; } + if (filterQuality != SkFilterQuality::kNone_SkFilterQuality) { return false; } + if (finalAlpha != 1.0f) { return false; } + if (srcPixmap.info().colorType() != kRGBA_8888_SkColorType + || dstInfo.colorType() != kRGBA_8888_SkColorType) { return false; } + + if (srcPixmap.info().profileType() != dstInfo.profileType()) { return false; } + + if (xTileMode != SkShader::kRepeat_TileMode || yTileMode != SkShader::kRepeat_TileMode) { + return false; + } + + if (xferMode == SkXfermode::kSrcOver_Mode + && srcPixmap.info().alphaType() == kOpaque_SkAlphaType) { + xferMode = SkXfermode::kSrc_Mode; + } + + if (xferMode != SkXfermode::kSrc_Mode) { return false; } + + new (blitterStorage) SkLinearBitmapPipeline(pipeline, srcPixmap, xferMode, dstInfo); + + return true; +} + +SkLinearBitmapPipeline::SkLinearBitmapPipeline( + const SkLinearBitmapPipeline& pipeline, + const SkPixmap& srcPixmap, + SkXfermode::Mode mode, + const SkImageInfo& dstInfo) +{ + SkASSERT(mode == SkXfermode::kSrc_Mode); + SkASSERT(srcPixmap.info().colorType() == dstInfo.colorType() + && srcPixmap.info().colorType() == kRGBA_8888_SkColorType); + + fSampleStage.initSink<RGBA8888UnitRepeat>(srcPixmap.writable_addr32(0, 0), srcPixmap.width()); + auto sampleStage = fSampleStage.get(); + auto tilerStage = pipeline.fTileStage.cloneStageTo(sampleStage, &fTileStage); + tilerStage = (tilerStage != nullptr) ? tilerStage : sampleStage; + auto matrixStage = pipeline.fMatrixStage.cloneStageTo(tilerStage, &fMatrixStage); + matrixStage = (matrixStage != nullptr) ? matrixStage : tilerStage; + fFirstStage = matrixStage; + fLastStage = fSampleStage.getInterface<DestinationInterface, RGBA8888UnitRepeat>(); +} + void SkLinearBitmapPipeline::shadeSpan4f(int x, int y, SkPM4f* dst, int count) { SkASSERT(count > 0); + this->blitSpan(x, y, dst, count); +} + +void SkLinearBitmapPipeline::blitSpan(int x, int y, void* dst, int count) { + SkASSERT(count > 0); fLastStage->setDestination(dst, count); // The count and length arguments start out in a precise relation in order to keep the diff --git a/src/core/SkLinearBitmapPipeline.h b/src/core/SkLinearBitmapPipeline.h index 548302ef9a..a6a84b5c8c 100644 --- a/src/core/SkLinearBitmapPipeline.h +++ b/src/core/SkLinearBitmapPipeline.h @@ -21,9 +21,25 @@ public: SkShader::TileMode xTile, SkShader::TileMode yTile, float postAlpha, const SkPixmap& srcPixmap); + + + + static bool ClonePipelineForBlitting( + void* blitterStorage, + const SkLinearBitmapPipeline& pipeline, + SkMatrix::TypeMask matrixMask, + SkShader::TileMode xTileMode, + SkShader::TileMode yTileMode, + SkFilterQuality filterQuality, + const SkPixmap& srcPixmap, + float finalAlpha, + SkXfermode::Mode xferMode, + const SkImageInfo& dstInfo); + ~SkLinearBitmapPipeline(); void shadeSpan4f(int x, int y, SkPM4f* dst, int count); + void blitSpan(int32_t x, int32_t y, void* dst, int count); template<typename Base, size_t kSize, typename Next = void> class Stage { @@ -65,12 +81,18 @@ public: class DestinationInterface; // These values were generated by the assert above in Stage::init{Sink|Stage}. - using MatrixStage = Stage<PointProcessorInterface, 160, PointProcessorInterface>; - using TileStage = Stage<PointProcessorInterface, 160, SampleProcessorInterface>; + using MatrixStage = Stage<PointProcessorInterface, 160, PointProcessorInterface>; + using TileStage = Stage<PointProcessorInterface, 160, SampleProcessorInterface>; using SampleStage = Stage<SampleProcessorInterface, 100, BlendProcessorInterface>; - using BlenderStage = Stage<BlendProcessorInterface, 80>; + using BlenderStage = Stage<BlendProcessorInterface, 40>; private: + SkLinearBitmapPipeline( + const SkLinearBitmapPipeline& pipeline, + const SkPixmap& srcPixmap, + SkXfermode::Mode xferMode, + const SkImageInfo& dstInfo); + PointProcessorInterface* fFirstStage; MatrixStage fMatrixStage; TileStage fTileStage; |