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.
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);
}
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;
}
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;
};
#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(
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,
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;
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