blob: f936ffd7f9bbd98596783963d813a0f6bf21a969 [file] [log] [blame]
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkLinearBitmapPipeline_DEFINED
#define SkLinearBitmapPipeline_DEFINED
#include "SkColor.h"
#include "SkImageInfo.h"
#include "SkMatrix.h"
#include "SkShader.h"
#include "SkSmallAllocator.h"
class SkEmbeddableLinearPipeline;
enum SkGammaType {
kLinear_SkGammaType,
kSRGB_SkGammaType,
};
///////////////////////////////////////////////////////////////////////////////////////////////////
// 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(
const SkMatrix& inverse,
SkFilterQuality filterQuality,
SkShader::TileMode xTile, SkShader::TileMode yTile,
SkColor paintColor,
const SkPixmap& srcPixmap);
SkLinearBitmapPipeline(
const SkLinearBitmapPipeline& pipeline,
const SkPixmap& srcPixmap,
SkBlendMode,
const SkImageInfo& dstInfo);
static bool ClonePipelineForBlitting(
SkEmbeddableLinearPipeline* pipelineStorage,
const SkLinearBitmapPipeline& pipeline,
SkMatrix::TypeMask matrixMask,
SkShader::TileMode xTileMode,
SkShader::TileMode yTileMode,
SkFilterQuality filterQuality,
const SkPixmap& srcPixmap,
float finalAlpha,
SkBlendMode,
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 {
public:
Stage() : fIsInitialized{false} {}
~Stage();
template<typename Variant, typename... Args>
void initStage(Next* next, Args&& ... args);
template<typename Variant, typename... Args>
void initSink(Args&& ... args);
Base* get() const { return reinterpret_cast<Base*>(fSpace); }
Base* operator->() const { return this->get(); }
Base& operator*() const { return *(this->get()); }
private:
mutable char fSpace[kSize];
bool fIsInitialized;
};
class PointProcessorInterface;
class SampleProcessorInterface;
class BlendProcessorInterface;
class DestinationInterface;
class PixelAccessorInterface;
// These values were generated by the assert above in Stage::init{Sink|Stage}.
using SampleStage = Stage<SampleProcessorInterface, 160, BlendProcessorInterface>;
using BlenderStage = Stage<BlendProcessorInterface, 48>;
private:
using MemoryAllocator = SkSmallAllocator<128, 4>;
using MatrixCloner =
std::function<PointProcessorInterface* (PointProcessorInterface*, MemoryAllocator*)>;
using TilerCloner =
std::function<PointProcessorInterface* (SampleProcessorInterface*, MemoryAllocator*)>;
PointProcessorInterface* chooseMatrix(
PointProcessorInterface* next,
const SkMatrix& inverse);
template <typename Tiler>
PointProcessorInterface* createTiler(SampleProcessorInterface* next, SkISize dimensions);
template <typename XStrategy>
PointProcessorInterface* chooseTilerYMode(
SampleProcessorInterface* next, SkShader::TileMode yMode, SkISize dimensions);
PointProcessorInterface* chooseTiler(
SampleProcessorInterface* next,
SkISize dimensions,
SkShader::TileMode xMode, SkShader::TileMode yMode,
SkFilterQuality filterQuality,
SkScalar dx);
template <SkColorType colorType>
PixelAccessorInterface* chooseSpecificAccessor(const SkPixmap& srcPixmap);
PixelAccessorInterface* choosePixelAccessor(
const SkPixmap& srcPixmap,
const SkColor A8TintColor);
SampleProcessorInterface* chooseSampler(
BlendProcessorInterface* next,
SkFilterQuality filterQuality,
SkShader::TileMode xTile, SkShader::TileMode yTile,
const SkPixmap& srcPixmap,
const SkColor A8TintColor);
MemoryAllocator fMemory;
PointProcessorInterface* fFirstStage;
MatrixCloner fMatrixStageCloner;
TilerCloner fTileStageCloner;
BlenderStage fBlenderStage;
DestinationInterface* fLastStage;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
// SkEmbeddableLinearPipeline - manage stricter alignment needs for SkLinearBitmapPipeline.
class SkEmbeddableLinearPipeline {
public:
SkEmbeddableLinearPipeline() { }
~SkEmbeddableLinearPipeline() {
if (fInitialized) {
get()->~SkLinearBitmapPipeline();
}
}
template <typename... Args>
void init(Args&&... args) {
new (fPipelineStorage) SkLinearBitmapPipeline{std::forward<Args>(args)...};
fInitialized = true;
}
SkLinearBitmapPipeline* get() const {
return reinterpret_cast<SkLinearBitmapPipeline*>(fPipelineStorage);
}
SkLinearBitmapPipeline& operator*() const { return *this->get(); }
SkLinearBitmapPipeline* operator->() const { return this->get(); }
private:
alignas(SkLinearBitmapPipeline) mutable char fPipelineStorage[sizeof(SkLinearBitmapPipeline)];
bool fInitialized {false};
};
#endif // SkLinearBitmapPipeline_DEFINED