aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar herb <herb@google.com>2016-04-12 14:07:59 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-04-12 14:07:59 -0700
commit69076fe5cf88c45b8dac4ca44bc5845f8817a57e (patch)
tree398cfe8125cbfa4c77ddba52420aaf1415ebac98
parent9ac5b91957e59eeddebfae9630204f217c20cd4e (diff)
Blitter for repeat RGBA8888->RGBA8888.
-rw-r--r--src/core/SkBitmapProcShader.cpp67
-rw-r--r--src/core/SkBitmapProcShader.h2
-rw-r--r--src/core/SkLinearBitmapPipeline.cpp61
-rw-r--r--src/core/SkLinearBitmapPipeline.h28
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;