/*
 * Copyright 2016 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkLinearBitmapPipeline.h"

#include <algorithm>
#include <cmath>
#include <limits>
#include <tuple>

#include "SkLinearBitmapPipeline_core.h"
#include "SkLinearBitmapPipeline_matrix.h"
#include "SkLinearBitmapPipeline_tile.h"
#include "SkLinearBitmapPipeline_sample.h"
#include "SkNx.h"
#include "SkOpts.h"
#include "SkPM4f.h"

////////////////////////////////////////////////////////////////////////////////////////////////////
// SkLinearBitmapPipeline::Stage
template<typename Base, size_t kSize, typename Next>
SkLinearBitmapPipeline::Stage<Base, kSize, Next>::~Stage() {
    if (fIsInitialized) {
        this->get()->~Base();
    }
}

template<typename Base, size_t kSize, typename Next>
template<typename Variant, typename... Args>
void SkLinearBitmapPipeline::Stage<Base, kSize, Next>::initStage(Next* next, Args&& ... args) {
    SkASSERTF(sizeof(Variant) <= sizeof(fSpace),
              "Size Variant: %d, Space: %d", sizeof(Variant), sizeof(fSpace));

    new (&fSpace) Variant(next, std::forward<Args>(args)...);
    fIsInitialized = true;
};

template<typename Base, size_t kSize, typename Next>
template<typename Variant, typename... Args>
void SkLinearBitmapPipeline::Stage<Base, kSize, Next>::initSink(Args&& ... args) {
    SkASSERTF(sizeof(Variant) <= sizeof(fSpace),
              "Size Variant: %d, Space: %d", sizeof(Variant), sizeof(fSpace));
    new (&fSpace) Variant(std::forward<Args>(args)...);
    fIsInitialized = true;
};

namespace  {

////////////////////////////////////////////////////////////////////////////////////////////////////
// Matrix Stage
// PointProcessor uses a strategy to help complete the work of the different stages. The strategy
// must implement the following methods:
// * processPoints(xs, ys) - must mutate the xs and ys for the stage.
// * maybeProcessSpan(span, next) - This represents a horizontal series of pixels
//   to work over.
//   span - encapsulation of span.
//   next - a pointer to the next stage.
//   maybeProcessSpan - returns false if it can not process the span and needs to fallback to
//                      point lists for processing.
template<typename Strategy, typename Next>
class MatrixStage final : public SkLinearBitmapPipeline::PointProcessorInterface {
public:
    template <typename... Args>
    MatrixStage(Next* next, Args&&... args)
        : fNext{next}
        , fStrategy{std::forward<Args>(args)...}{ }

    MatrixStage(Next* next, MatrixStage* stage)
        : fNext{next}
        , fStrategy{stage->fStrategy} { }

    void SK_VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override {
        fStrategy.processPoints(&xs, &ys);
        fNext->pointListFew(n, xs, ys);
    }

    void SK_VECTORCALL pointList4(Sk4s xs, Sk4s ys) override {
        fStrategy.processPoints(&xs, &ys);
        fNext->pointList4(xs, ys);
    }

    // The span you pass must not be empty.
    void pointSpan(Span span) override {
        SkASSERT(!span.isEmpty());
        if (!fStrategy.maybeProcessSpan(span, fNext)) {
            span_fallback(span, this);
        }
    }

private:
    Next* const fNext;
    Strategy fStrategy;
};

template <typename Next = SkLinearBitmapPipeline::PointProcessorInterface>
using TranslateMatrix = MatrixStage<TranslateMatrixStrategy, Next>;

template <typename Next = SkLinearBitmapPipeline::PointProcessorInterface>
using ScaleMatrix = MatrixStage<ScaleMatrixStrategy, Next>;

template <typename Next = SkLinearBitmapPipeline::PointProcessorInterface>
using AffineMatrix = MatrixStage<AffineMatrixStrategy, Next>;

template <typename Next = SkLinearBitmapPipeline::PointProcessorInterface>
using PerspectiveMatrix = MatrixStage<PerspectiveMatrixStrategy, Next>;


////////////////////////////////////////////////////////////////////////////////////////////////////
// Tile Stage

template<typename XStrategy, typename YStrategy, typename Next>
class CombinedTileStage final : public SkLinearBitmapPipeline::PointProcessorInterface {
public:
    CombinedTileStage(Next* next, SkISize dimensions)
        : fNext{next}
        , fXStrategy{dimensions.width()}
        , fYStrategy{dimensions.height()}{ }

    CombinedTileStage(Next* next, CombinedTileStage* stage)
        : fNext{next}
        , fXStrategy{stage->fXStrategy}
        , fYStrategy{stage->fYStrategy} { }

    void SK_VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override {
        fXStrategy.tileXPoints(&xs);
        fYStrategy.tileYPoints(&ys);
        fNext->pointListFew(n, xs, ys);
    }

    void SK_VECTORCALL pointList4(Sk4s xs, Sk4s ys) override {
        fXStrategy.tileXPoints(&xs);
        fYStrategy.tileYPoints(&ys);
        fNext->pointList4(xs, ys);
    }

    // The span you pass must not be empty.
    void pointSpan(Span span) override {
        SkASSERT(!span.isEmpty());
        SkPoint start; SkScalar length; int count;
        std::tie(start, length, count) = span;

        if (span.count() == 1) {
            // DANGER:
            // The explicit casts from float to Sk4f are not usually necessary, but are here to
            // work around an MSVC 2015u2 c++ code generation bug. This is tracked using skia bug
            // 5566.
            this->pointListFew(1, Sk4f{span.startX()}, Sk4f{span.startY()});
            return;
        }

        SkScalar x = X(start);
        SkScalar y = fYStrategy.tileY(Y(start));
        Span yAdjustedSpan{{x, y}, length, count};

        if (!fXStrategy.maybeProcessSpan(yAdjustedSpan, fNext)) {
            span_fallback(span, this);
        }
    }

private:
    Next* const fNext;
    XStrategy fXStrategy;
    YStrategy fYStrategy;
};

////////////////////////////////////////////////////////////////////////////////////////////////////
// Specialized Samplers

// RGBA8888UnitRepeatSrc - A sampler that takes advantage of the fact the the src and destination
// are the same format and do not need in transformations in pixel space. Therefore, there is no
// need to convert them to HiFi pixel format.
class RGBA8888UnitRepeatSrc final : public SkLinearBitmapPipeline::SampleProcessorInterface,
                                    public SkLinearBitmapPipeline::DestinationInterface {
public:
    RGBA8888UnitRepeatSrc(const uint32_t* src, int32_t width)
        : fSrc{src}, fWidth{width} { }

    void SK_VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override {
        SkASSERT(fDest + n <= fEnd);
        // At this point xs and ys should be >= 0, so trunc is the same as floor.
        Sk4i iXs = SkNx_cast<int>(xs);
        Sk4i iYs = SkNx_cast<int>(ys);

        if (n >= 1) *fDest++ = *this->pixelAddress(iXs[0], iYs[0]);
        if (n >= 2) *fDest++ = *this->pixelAddress(iXs[1], iYs[1]);
        if (n >= 3) *fDest++ = *this->pixelAddress(iXs[2], iYs[2]);
    }

    void SK_VECTORCALL pointList4(Sk4s xs, Sk4s ys) override {
        SkASSERT(fDest + 4 <= fEnd);
        Sk4i iXs = SkNx_cast<int>(xs);
        Sk4i iYs = SkNx_cast<int>(ys);
        *fDest++ = *this->pixelAddress(iXs[0], iYs[0]);
        *fDest++ = *this->pixelAddress(iXs[1], iYs[1]);
        *fDest++ = *this->pixelAddress(iXs[2], iYs[2]);
        *fDest++ = *this->pixelAddress(iXs[3], iYs[3]);
    }

    void pointSpan(Span span) override {
        SkASSERT(fDest + span.count() <= fEnd);
        if (span.length() != 0.0f) {
            int32_t x = SkScalarTruncToInt(span.startX());
            int32_t y = SkScalarTruncToInt(span.startY());
            const uint32_t* src = this->pixelAddress(x, y);
            memmove(fDest, src, span.count() * sizeof(uint32_t));
            fDest += span.count();
        }
    }

    void repeatSpan(Span span, int32_t repeatCount) override {
        SkASSERT(fDest + span.count() * repeatCount <= fEnd);

        int32_t x = SkScalarTruncToInt(span.startX());
        int32_t y = SkScalarTruncToInt(span.startY());
        const uint32_t* src = this->pixelAddress(x, y);
        uint32_t* dest = fDest;
        while (repeatCount --> 0) {
            memmove(dest, src, span.count() * sizeof(uint32_t));
            dest += span.count();
        }
        fDest = dest;
    }

    void setDestination(void* dst, int count) override  {
        fDest = static_cast<uint32_t*>(dst);
        fEnd = fDest + count;
    }

private:
    const uint32_t* pixelAddress(int32_t x, int32_t y) {
        return &fSrc[fWidth * y + x];
    }
    const uint32_t* const fSrc;
    const int32_t         fWidth;
    uint32_t*             fDest;
    uint32_t*             fEnd;
};

// RGBA8888UnitRepeatSrc - A sampler that takes advantage of the fact the the src and destination
// are the same format and do not need in transformations in pixel space. Therefore, there is no
// need to convert them to HiFi pixel format.
class RGBA8888UnitRepeatSrcOver final : public SkLinearBitmapPipeline::SampleProcessorInterface,
                                        public SkLinearBitmapPipeline::DestinationInterface {
public:
    RGBA8888UnitRepeatSrcOver(const uint32_t* src, int32_t width)
        : fSrc{src}, fWidth{width} { }

    void SK_VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override {
        SkASSERT(fDest + n <= fEnd);
        // At this point xs and ys should be >= 0, so trunc is the same as floor.
        Sk4i iXs = SkNx_cast<int>(xs);
        Sk4i iYs = SkNx_cast<int>(ys);

        if (n >= 1) blendPixelAt(iXs[0], iYs[0]);
        if (n >= 2) blendPixelAt(iXs[1], iYs[1]);
        if (n >= 3) blendPixelAt(iXs[2], iYs[2]);
    }

    void SK_VECTORCALL pointList4(Sk4s xs, Sk4s ys) override {
        SkASSERT(fDest + 4 <= fEnd);
        Sk4i iXs = SkNx_cast<int>(xs);
        Sk4i iYs = SkNx_cast<int>(ys);
        blendPixelAt(iXs[0], iYs[0]);
        blendPixelAt(iXs[1], iYs[1]);
        blendPixelAt(iXs[2], iYs[2]);
        blendPixelAt(iXs[3], iYs[3]);
    }

    void pointSpan(Span span) override {
        if (span.length() != 0.0f) {
            this->repeatSpan(span, 1);
        }
    }

    void repeatSpan(Span span, int32_t repeatCount) override {
        SkASSERT(fDest + span.count() * repeatCount <= fEnd);
        SkASSERT(span.count() > 0);
        SkASSERT(repeatCount > 0);

        int32_t x = (int32_t)span.startX();
        int32_t y = (int32_t)span.startY();
        const uint32_t* beginSpan = this->pixelAddress(x, y);

        SkOpts::srcover_srgb_srgb(fDest, beginSpan, span.count() * repeatCount, span.count());

        fDest += span.count() * repeatCount;

        SkASSERT(fDest <= fEnd);
    }

    void setDestination(void* dst, int count) override  {
        SkASSERT(count > 0);
        fDest = static_cast<uint32_t*>(dst);
        fEnd = fDest + count;
    }

private:
    const uint32_t* pixelAddress(int32_t x, int32_t y) {
        return &fSrc[fWidth * y + x];
    }

    void blendPixelAt(int32_t x, int32_t y) {
        const uint32_t* src = this->pixelAddress(x, y);
        SkOpts::srcover_srgb_srgb(fDest, src, 1, 1);
        fDest += 1;
    }

    const uint32_t* const fSrc;
    const int32_t         fWidth;
    uint32_t*             fDest;
    uint32_t*             fEnd;
};

using Blender = SkLinearBitmapPipeline::BlendProcessorInterface;

////////////////////////////////////////////////////////////////////////////////////////////////////
// Pixel Blender Stage
template <SkAlphaType alphaType>
class SrcFPPixel final : public Blender {
public:
    SrcFPPixel(float postAlpha) : fPostAlpha{postAlpha} { }
    SrcFPPixel(const SrcFPPixel& Blender) : fPostAlpha(Blender.fPostAlpha) {}
    void SK_VECTORCALL blendPixel(Sk4f pixel) override {
        SkASSERT(fDst + 1 <= fEnd );
        this->srcPixel(fDst, pixel, 0);
        fDst += 1;
    }

    void SK_VECTORCALL blend4Pixels(Sk4f p0, Sk4f p1, Sk4f p2, Sk4f p3) override {
        SkASSERT(fDst + 4 <= fEnd);
        SkPM4f* dst = fDst;
        this->srcPixel(dst, p0, 0);
        this->srcPixel(dst, p1, 1);
        this->srcPixel(dst, p2, 2);
        this->srcPixel(dst, p3, 3);
        fDst += 4;
    }

    void setDestination(void* dst, int count) override {
        fDst = static_cast<SkPM4f*>(dst);
        fEnd = fDst + count;
    }

private:
    void SK_VECTORCALL srcPixel(SkPM4f* dst, Sk4f pixel, int index) {
        check_pixel(pixel);

        Sk4f newPixel = pixel;
        if (alphaType == kUnpremul_SkAlphaType) {
            newPixel = Premultiply(pixel);
        }
        newPixel = newPixel * fPostAlpha;
        newPixel.store(dst + index);
    }
    static Sk4f SK_VECTORCALL Premultiply(Sk4f pixel) {
        float alpha = pixel[3];
        return pixel * Sk4f{alpha, alpha, alpha, 1.0f};
    }

    SkPM4f* fDst;
    SkPM4f* fEnd;
    float   fPostAlpha;
};

static SkLinearBitmapPipeline::BlendProcessorInterface* choose_blender_for_shading(
    SkAlphaType alphaType,
    float postAlpha,
    SkLinearBitmapPipeline::BlenderStage* blenderStage) {
    if (alphaType == kUnpremul_SkAlphaType) {
        blenderStage->initSink<SrcFPPixel<kUnpremul_SkAlphaType>>(postAlpha);
    } else {
        // kOpaque_SkAlphaType is treated the same as kPremul_SkAlphaType
        blenderStage->initSink<SrcFPPixel<kPremul_SkAlphaType>>(postAlpha);
    }
    return blenderStage->get();
}

}  // namespace

////////////////////////////////////////////////////////////////////////////////////////////////////
// SkLinearBitmapPipeline
SkLinearBitmapPipeline::~SkLinearBitmapPipeline() {}

SkLinearBitmapPipeline::SkLinearBitmapPipeline(
    const SkMatrix& inverse,
    SkFilterQuality filterQuality,
    SkShader::TileMode xTile, SkShader::TileMode yTile,
    SkColor paintColor,
    const SkPixmap& srcPixmap)
{
    SkISize dimensions = srcPixmap.info().dimensions();
    const SkImageInfo& srcImageInfo = srcPixmap.info();

    SkMatrix adjustedInverse = inverse;
    if (filterQuality == kNone_SkFilterQuality) {
        if (inverse.getScaleX() >= 0.0f) {
            adjustedInverse.setTranslateX(
                nextafterf(inverse.getTranslateX(), std::floor(inverse.getTranslateX())));
        }
        if (inverse.getScaleY() >= 0.0f) {
            adjustedInverse.setTranslateY(
                nextafterf(inverse.getTranslateY(), std::floor(inverse.getTranslateY())));
        }
    }

    SkScalar dx = adjustedInverse.getScaleX();

    // If it is an index 8 color type, the sampler converts to unpremul for better fidelity.
    SkAlphaType alphaType = srcImageInfo.alphaType();
    if (srcPixmap.colorType() == kIndex_8_SkColorType) {
        alphaType = kUnpremul_SkAlphaType;
    }

    float postAlpha = SkColorGetA(paintColor) * (1.0f / 255.0f);
    // As the stages are built, the chooser function may skip a stage. For example, with the
    // identity matrix, the matrix stage is skipped, and the tilerStage is the first stage.
    auto blenderStage = choose_blender_for_shading(alphaType, postAlpha, &fBlenderStage);
    auto samplerStage = this->chooseSampler(
        blenderStage, filterQuality, xTile, yTile, srcPixmap, paintColor);
    auto tilerStage   = this->chooseTiler(
        samplerStage, dimensions, xTile, yTile, filterQuality, dx);
    fFirstStage       = this->chooseMatrix(tilerStage, adjustedInverse);
    fLastStage        = blenderStage;
}

bool SkLinearBitmapPipeline::ClonePipelineForBlitting(
    SkEmbeddableLinearPipeline* pipelineStorage,
    const SkLinearBitmapPipeline& pipeline,
    SkMatrix::TypeMask matrixMask,
    SkShader::TileMode xTileMode,
    SkShader::TileMode yTileMode,
    SkFilterQuality filterQuality,
    const SkPixmap& srcPixmap,
    float finalAlpha,
    SkBlendMode blendMode,
    const SkImageInfo& dstInfo)
{
    if (blendMode == SkBlendMode::kSrcOver && srcPixmap.info().alphaType() == kOpaque_SkAlphaType) {
        blendMode = SkBlendMode::kSrc;
    }

    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().gammaCloseToSRGB() || !dstInfo.gammaCloseToSRGB()) {
        return false;
    }

    if (blendMode != SkBlendMode::kSrc && blendMode != SkBlendMode::kSrcOver) {
        return false;
    }

    pipelineStorage->init(pipeline, srcPixmap, blendMode, dstInfo);

    return true;
}

SkLinearBitmapPipeline::SkLinearBitmapPipeline(
    const SkLinearBitmapPipeline& pipeline,
    const SkPixmap& srcPixmap,
    SkBlendMode mode,
    const SkImageInfo& dstInfo)
{
    SkASSERT(mode == SkBlendMode::kSrc || mode == SkBlendMode::kSrcOver);
    SkASSERT(srcPixmap.info().colorType() == dstInfo.colorType()
             && srcPixmap.info().colorType() == kRGBA_8888_SkColorType);

    SampleProcessorInterface* sampleStage;
    if (mode == SkBlendMode::kSrc) {
        auto sampler = fMemory.createT<RGBA8888UnitRepeatSrc>(
            srcPixmap.writable_addr32(0, 0), srcPixmap.rowBytes() / 4);
        sampleStage = sampler;
        fLastStage = sampler;
    } else {
        auto sampler = fMemory.createT<RGBA8888UnitRepeatSrcOver>(
            srcPixmap.writable_addr32(0, 0), srcPixmap.rowBytes() / 4);
        sampleStage = sampler;
        fLastStage = sampler;
    }

    auto tilerStage = pipeline.fTileStageCloner(sampleStage, &fMemory);
    auto matrixStage = pipeline.fMatrixStageCloner(tilerStage, &fMemory);
    fFirstStage = matrixStage;
}

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
    // math correct through the different stages. Count is the number of pixel to produce.
    // Since the code samples at pixel centers, length is the distance from the center of the
    // first pixel to the center of the last pixel. This implies that length is count-1.
    fFirstStage->pointSpan(Span{{x + 0.5f, y + 0.5f}, count - 1.0f, count});
}

SkLinearBitmapPipeline::PointProcessorInterface*
SkLinearBitmapPipeline::chooseMatrix(PointProcessorInterface* next, const SkMatrix& inverse) {
    if (inverse.hasPerspective()) {
        auto matrixStage = fMemory.createT<PerspectiveMatrix<>>(
            next,
            SkVector{inverse.getTranslateX(), inverse.getTranslateY()},
            SkVector{inverse.getScaleX(), inverse.getScaleY()},
            SkVector{inverse.getSkewX(), inverse.getSkewY()},
            SkVector{inverse.getPerspX(), inverse.getPerspY()},
            inverse.get(SkMatrix::kMPersp2));
        fMatrixStageCloner =
            [matrixStage](PointProcessorInterface* cloneNext, MemoryAllocator* memory) {
                return memory->createT<PerspectiveMatrix<>>(cloneNext, matrixStage);
            };
        return matrixStage;
    } else if (inverse.getSkewX() != 0.0f || inverse.getSkewY() != 0.0f) {
        auto matrixStage = fMemory.createT<AffineMatrix<>>(
            next,
            SkVector{inverse.getTranslateX(), inverse.getTranslateY()},
            SkVector{inverse.getScaleX(), inverse.getScaleY()},
            SkVector{inverse.getSkewX(), inverse.getSkewY()});
        fMatrixStageCloner =
            [matrixStage](PointProcessorInterface* cloneNext, MemoryAllocator* memory) {
                return memory->createT<AffineMatrix<>>(cloneNext, matrixStage);
            };
        return matrixStage;
    } else if (inverse.getScaleX() != 1.0f || inverse.getScaleY() != 1.0f) {
        auto matrixStage = fMemory.createT<ScaleMatrix<>>(
            next,
            SkVector{inverse.getTranslateX(), inverse.getTranslateY()},
            SkVector{inverse.getScaleX(), inverse.getScaleY()});
        fMatrixStageCloner =
            [matrixStage](PointProcessorInterface* cloneNext, MemoryAllocator* memory) {
                return memory->createT<ScaleMatrix<>>(cloneNext, matrixStage);
            };
        return matrixStage;
    } else if (inverse.getTranslateX() != 0.0f || inverse.getTranslateY() != 0.0f) {
        auto matrixStage = fMemory.createT<TranslateMatrix<>>(
            next,
            SkVector{inverse.getTranslateX(), inverse.getTranslateY()});
        fMatrixStageCloner =
            [matrixStage](PointProcessorInterface* cloneNext, MemoryAllocator* memory) {
                return memory->createT<TranslateMatrix<>>(cloneNext, matrixStage);
            };
        return matrixStage;
    } else {
        fMatrixStageCloner = [](PointProcessorInterface* cloneNext, MemoryAllocator* memory) {
            return cloneNext;
        };
        return next;
    }
}

template <typename Tiler>
SkLinearBitmapPipeline::PointProcessorInterface* SkLinearBitmapPipeline::createTiler(
    SampleProcessorInterface* next, SkISize dimensions) {
    auto tilerStage = fMemory.createT<Tiler>(next, dimensions);
    fTileStageCloner =
        [tilerStage](SampleProcessorInterface* cloneNext,
                     MemoryAllocator* memory) -> PointProcessorInterface* {
            return memory->createT<Tiler>(cloneNext, tilerStage);
        };
    return tilerStage;
}

template <typename XStrategy>
SkLinearBitmapPipeline::PointProcessorInterface* SkLinearBitmapPipeline::chooseTilerYMode(
    SampleProcessorInterface* next, SkShader::TileMode yMode, SkISize dimensions) {
    switch (yMode) {
        case SkShader::kClamp_TileMode: {
            using Tiler = CombinedTileStage<XStrategy, YClampStrategy, SampleProcessorInterface>;
            return this->createTiler<Tiler>(next, dimensions);
        }
        case SkShader::kRepeat_TileMode: {
            using Tiler = CombinedTileStage<XStrategy, YRepeatStrategy, SampleProcessorInterface>;
            return this->createTiler<Tiler>(next, dimensions);
        }
        case SkShader::kMirror_TileMode: {
            using Tiler = CombinedTileStage<XStrategy, YMirrorStrategy, SampleProcessorInterface>;
            return this->createTiler<Tiler>(next, dimensions);
        }
    }

    // Should never get here.
    SkFAIL("Not all Y tile cases covered.");
    return nullptr;
}

SkLinearBitmapPipeline::PointProcessorInterface* SkLinearBitmapPipeline::chooseTiler(
    SampleProcessorInterface* next,
    SkISize dimensions,
    SkShader::TileMode xMode,
    SkShader::TileMode yMode,
    SkFilterQuality filterQuality,
    SkScalar dx)
{
    switch (xMode) {
        case SkShader::kClamp_TileMode:
            return this->chooseTilerYMode<XClampStrategy>(next, yMode, dimensions);
        case SkShader::kRepeat_TileMode:
            if (dx == 1.0f && filterQuality == kNone_SkFilterQuality) {
                return this->chooseTilerYMode<XRepeatUnitScaleStrategy>(next, yMode, dimensions);
            } else {
                return this->chooseTilerYMode<XRepeatStrategy>(next, yMode, dimensions);
            }
        case SkShader::kMirror_TileMode:
            return this->chooseTilerYMode<XMirrorStrategy>(next, yMode, dimensions);
    }

    // Should never get here.
    SkFAIL("Not all X tile cases covered.");
    return nullptr;
}

template <SkColorType colorType>
SkLinearBitmapPipeline::PixelAccessorInterface*
    SkLinearBitmapPipeline::chooseSpecificAccessor(
    const SkPixmap& srcPixmap)
{
    if (srcPixmap.info().gammaCloseToSRGB()) {
        using Accessor = PixelAccessor<colorType, kSRGB_SkGammaType>;
        return fMemory.createT<Accessor>(srcPixmap);
    } else {
        using Accessor = PixelAccessor<colorType, kLinear_SkGammaType>;
        return fMemory.createT<Accessor>(srcPixmap);
    }
}

SkLinearBitmapPipeline::PixelAccessorInterface* SkLinearBitmapPipeline::choosePixelAccessor(
    const SkPixmap& srcPixmap,
    const SkColor A8TintColor)
{
    const SkImageInfo& imageInfo = srcPixmap.info();

    switch (imageInfo.colorType()) {
        case kAlpha_8_SkColorType: {
            using Accessor = PixelAccessor<kAlpha_8_SkColorType, kLinear_SkGammaType>;
            return fMemory.createT<Accessor>(srcPixmap, A8TintColor);
        }
        case kARGB_4444_SkColorType:
            return this->chooseSpecificAccessor<kARGB_4444_SkColorType>(srcPixmap);
        case kRGB_565_SkColorType:
            return this->chooseSpecificAccessor<kRGB_565_SkColorType>(srcPixmap);
        case kRGBA_8888_SkColorType:
            return this->chooseSpecificAccessor<kRGBA_8888_SkColorType>(srcPixmap);
        case kBGRA_8888_SkColorType:
            return this->chooseSpecificAccessor<kBGRA_8888_SkColorType>(srcPixmap);
        case kIndex_8_SkColorType:
            return this->chooseSpecificAccessor<kIndex_8_SkColorType>(srcPixmap);
        case kGray_8_SkColorType:
            return this->chooseSpecificAccessor<kGray_8_SkColorType>(srcPixmap);
        case kRGBA_F16_SkColorType: {
            using Accessor = PixelAccessor<kRGBA_F16_SkColorType, kLinear_SkGammaType>;
            return fMemory.createT<Accessor>(srcPixmap);
        }
        default:
            // Should never get here.
            SkFAIL("Pixel source not supported.");
            return nullptr;
    }
}

SkLinearBitmapPipeline::SampleProcessorInterface* SkLinearBitmapPipeline::chooseSampler(
    Blender* next,
    SkFilterQuality filterQuality,
    SkShader::TileMode xTile, SkShader::TileMode yTile,
    const SkPixmap& srcPixmap,
    const SkColor A8TintColor)
{
    const SkImageInfo& imageInfo = srcPixmap.info();
    SkISize dimensions = imageInfo.dimensions();

    // Special case samplers with fully expanded templates
    if (imageInfo.gammaCloseToSRGB()) {
        if (filterQuality == kNone_SkFilterQuality) {
            switch (imageInfo.colorType()) {
                case kN32_SkColorType: {
                    using Sampler =
                    NearestNeighborSampler<
                        PixelAccessor<kN32_SkColorType, kSRGB_SkGammaType>, Blender>;
                    return fMemory.createT<Sampler>(next, srcPixmap);
                }
                case kIndex_8_SkColorType: {
                    using Sampler =
                    NearestNeighborSampler<
                        PixelAccessor<kIndex_8_SkColorType, kSRGB_SkGammaType>, Blender>;
                    return fMemory.createT<Sampler>(next, srcPixmap);
                }
                default:
                    break;
            }
        } else {
            switch (imageInfo.colorType()) {
                case kN32_SkColorType: {
                    using Sampler =
                    BilerpSampler<
                        PixelAccessor<kN32_SkColorType, kSRGB_SkGammaType>, Blender>;
                    return fMemory.createT<Sampler>(next, dimensions, xTile, yTile, srcPixmap);
                }
                case kIndex_8_SkColorType: {
                    using Sampler =
                    BilerpSampler<
                        PixelAccessor<kIndex_8_SkColorType, kSRGB_SkGammaType>, Blender>;
                    return fMemory.createT<Sampler>(next, dimensions, xTile, yTile, srcPixmap);
                }
                default:
                    break;
            }
        }
    }

    auto pixelAccessor = this->choosePixelAccessor(srcPixmap, A8TintColor);
    // General cases.
    if (filterQuality == kNone_SkFilterQuality) {
        using Sampler = NearestNeighborSampler<PixelAccessorShim, Blender>;
        return fMemory.createT<Sampler>(next, pixelAccessor);
    } else {
        using Sampler = BilerpSampler<PixelAccessorShim, Blender>;
        return fMemory.createT<Sampler>(next, dimensions, xTile, yTile, pixelAccessor);
    }
}
