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
This commit is contained in:
herb 2016-04-12 14:07:59 -07:00 committed by Commit bot
parent 9ac5b91957
commit 69076fe5cf
4 changed files with 145 additions and 13 deletions

View File

@ -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;
};

View File

@ -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

View File

@ -776,7 +776,68 @@ 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);

View File

@ -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;