Make an embeddable container to hold linear pipelines.

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1998793002

Review-Url: https://codereview.chromium.org/1998793002
This commit is contained in:
herb 2016-05-19 14:19:23 -07:00 committed by Commit bot
parent 82ec6e59b8
commit 57a69dc013
3 changed files with 62 additions and 46 deletions

View File

@ -129,12 +129,11 @@ public:
fFilterQuality = info->fFilterQuality;
fMatrixTypeMask = info->fRealInvMatrix.getType();
// Need to ensure that our pipeline is created at a 16byte aligned address
fShaderPipeline = (SkLinearBitmapPipeline*)SkAlign16((intptr_t)fShaderStorage);
new (fShaderPipeline) SkLinearBitmapPipeline(info->fRealInvMatrix, info->fFilterQuality,
info->fTileModeX, info->fTileModeY,
info->fPaintColor,
info->fPixmap);
fShaderPipeline.init(
info->fRealInvMatrix, info->fFilterQuality,
info->fTileModeX, info->fTileModeY,
info->fPaintColor,
info->fPixmap);
// To implement the old shadeSpan entry-point, we need to efficiently convert our native
// floats into SkPMColor. The SkXfermode::D32Procs do exactly that.
@ -143,14 +142,6 @@ public:
fXferProc = SkXfermode::GetD32Proc(xfer.get(), 0);
}
~LinearPipelineContext() override {
// since we did a manual new, we need to manually destroy as well.
fShaderPipeline->~SkLinearBitmapPipeline();
if (fBlitterPipeline != nullptr) {
fBlitterPipeline->~SkLinearBitmapPipeline();
}
}
void shadeSpan4f(int x, int y, SkPM4f dstC[], int count) override {
fShaderPipeline->shadeSpan4f(x, y, dstC, count);
}
@ -173,23 +164,19 @@ public:
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,
&fBlitterPipeline, *fShaderPipeline,
fMatrixTypeMask,
fXMode, fYMode,
fFilterQuality, fSrcPixmap,
fAlpha, mode, dstInfo))
{
state->fStorage[0] = fBlitterPipeline;
state->fStorage[0] = fBlitterPipeline.get();
state->fBlitBW = &LinearPipelineContext::ForwardToPipeline;
return true;
}
// Did not successfully create a pipeline so don't destruct it.
fBlitterPipeline = nullptr;
return false;
}
@ -199,23 +186,16 @@ public:
pipeline->blitSpan(x, y, addr, count);
}
private:
enum {
kActualSize = sizeof(SkLinearBitmapPipeline),
kPaddedSize = SkAlignPtr(kActualSize + 12),
};
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;
SkEmbeddableLinearPipeline fShaderPipeline;
SkEmbeddableLinearPipeline fBlitterPipeline;
SkXfermode::D32Proc fXferProc;
SkPixmap fSrcPixmap;
float fAlpha;
SkShader::TileMode fXMode;
SkShader::TileMode fYMode;
SkMatrix::TypeMask fMatrixTypeMask;
SkFilterQuality fFilterQuality;
typedef BitmapProcInfoContext INHERITED;
};

View File

@ -891,7 +891,7 @@ SkLinearBitmapPipeline::SkLinearBitmapPipeline(
}
bool SkLinearBitmapPipeline::ClonePipelineForBlitting(
void* blitterStorage,
SkEmbeddableLinearPipeline* pipelineStorage,
const SkLinearBitmapPipeline& pipeline,
SkMatrix::TypeMask matrixMask,
SkShader::TileMode xTileMode,
@ -920,7 +920,7 @@ bool SkLinearBitmapPipeline::ClonePipelineForBlitting(
return false;
}
new (blitterStorage) SkLinearBitmapPipeline(pipeline, srcPixmap, xferMode, dstInfo);
pipelineStorage->init(pipeline, srcPixmap, xferMode, dstInfo);
return true;
}

View File

@ -13,6 +13,13 @@
#include "SkMatrix.h"
#include "SkShader.h"
class SkEmbeddableLinearPipeline;
///////////////////////////////////////////////////////////////////////////////////////////////////
// SkLinearBitmapPipeline - encapsulates all the machinery for doing floating point pixel
// processing in a linear color space.
// Note: this class has unusual alignment requirements due to its use of SIMD instructions. The
// class SkEmbeddableLinearPipeline below manages these requirements.
class SkLinearBitmapPipeline {
public:
SkLinearBitmapPipeline(
@ -22,10 +29,14 @@ public:
SkColor paintColor,
const SkPixmap& srcPixmap);
SkLinearBitmapPipeline(
const SkLinearBitmapPipeline& pipeline,
const SkPixmap& srcPixmap,
SkXfermode::Mode xferMode,
const SkImageInfo& dstInfo);
static bool ClonePipelineForBlitting(
void* blitterStorage,
SkEmbeddableLinearPipeline* pipelineStorage,
const SkLinearBitmapPipeline& pipeline,
SkMatrix::TypeMask matrixMask,
SkShader::TileMode xTileMode,
@ -87,12 +98,6 @@ public:
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;
@ -101,4 +106,35 @@ private:
DestinationInterface* fLastStage;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
// SkEmbeddableLinearPipeline - manage stricter alignment needs for SkLinearBitmapPipeline.
class SkEmbeddableLinearPipeline {
public:
SkEmbeddableLinearPipeline() { }
~SkEmbeddableLinearPipeline() {
if (get() != nullptr) {
get()->~SkLinearBitmapPipeline();
}
}
template <typename... Args>
void init(Args&&... args) {
// Ensure that our pipeline is created at a 16 byte aligned address.
fPipeline = (SkLinearBitmapPipeline*)SkAlign16((intptr_t)fPipelineStorage);
new (fPipeline) SkLinearBitmapPipeline{std::forward<Args>(args)...};
}
SkLinearBitmapPipeline* get() const { return fPipeline; }
SkLinearBitmapPipeline& operator*() const { return *this->get(); }
SkLinearBitmapPipeline* operator->() const { return this->get(); }
private:
enum {
kActualSize = sizeof(SkLinearBitmapPipeline),
kPaddedSize = SkAlignPtr(kActualSize + 12),
};
void* fPipelineStorage[kPaddedSize / sizeof(void*)];
SkLinearBitmapPipeline* fPipeline{nullptr};
};
#endif // SkLinearBitmapPipeline_DEFINED