| Index: src/core/SkSpriteBlitter4f.cpp
 | 
| diff --git a/src/core/SkSpriteBlitter4f.cpp b/src/core/SkSpriteBlitter4f.cpp
 | 
| new file mode 100644
 | 
| index 0000000000000000000000000000000000000000..fc4b4809511f1bec8730afdb84b2a0ddcf326b94
 | 
| --- /dev/null
 | 
| +++ b/src/core/SkSpriteBlitter4f.cpp
 | 
| @@ -0,0 +1,137 @@
 | 
| +/*
 | 
| + * 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 "SkSpriteBlitter.h"
 | 
| +#include "SkSpanProcs.h"
 | 
| +#include "SkTemplates.h"
 | 
| +#include "SkXfermode.h"
 | 
| +
 | 
| +class Sprite_4f : public SkSpriteBlitter {
 | 
| +public:
 | 
| +    Sprite_4f(const SkPixmap& src, const SkPaint& paint) : INHERITED(src) {
 | 
| +        fLoader = SkLoadSpanProc_Choose(src.info());
 | 
| +        fFilter = SkFilterSpanProc_Choose(paint);
 | 
| +        fBuffer.reset(src.width());
 | 
| +    }
 | 
| +    
 | 
| +protected:
 | 
| +    SkLoadSpanProc          fLoader;
 | 
| +    SkFilterSpanProc        fFilter;
 | 
| +    SkAutoTMalloc<SkPM4f>   fBuffer;
 | 
| +    
 | 
| +private:
 | 
| +    typedef SkSpriteBlitter INHERITED;
 | 
| +};
 | 
| +
 | 
| +///////////////////////////////////////////////////////////////////////////////////////////////////
 | 
| +
 | 
| +static SkXfermode::Mode get_mode(const SkXfermode* xfer) {
 | 
| +    SkXfermode::Mode mode;
 | 
| +    if (!SkXfermode::AsMode(xfer, &mode)) {
 | 
| +        mode = SkXfermode::kSrcOver_Mode;
 | 
| +    }
 | 
| +    return mode;
 | 
| +}
 | 
| +
 | 
| +class Sprite_F16 : public Sprite_4f {
 | 
| +public:
 | 
| +    Sprite_F16(const SkPixmap& src, const SkPaint& paint) : INHERITED(src, paint) {
 | 
| +        fState = { paint.getXfermode(), SkXfermode::kDstIsFloat16_U64Flag };
 | 
| +        if (src.isOpaque()) {
 | 
| +            fState.fFlags |= SkXfermode::kSrcIsOpaque_U64Flag;
 | 
| +        }
 | 
| +        fXfer = SkXfermode::GetU64ProcN(get_mode(fState.fXfer), fState.fFlags);
 | 
| +    }
 | 
| +
 | 
| +    void blitRect(int x, int y, int width, int height) override {
 | 
| +        SkASSERT(width > 0 && height > 0);
 | 
| +        uint64_t* SK_RESTRICT dst = fDst.writable_addr64(x, y);
 | 
| +        size_t dstRB = fDst.rowBytes();
 | 
| +
 | 
| +        for (int bottom = y + height; y < bottom; ++y) {
 | 
| +            fLoader(fSource, x - fLeft, y - fTop, fBuffer, width);
 | 
| +            fFilter(*fPaint, fBuffer, width);
 | 
| +            fXfer(fState, dst, fBuffer, width, nullptr);
 | 
| +            dst = (uint64_t* SK_RESTRICT)((char*)dst + dstRB);
 | 
| +        }
 | 
| +    }
 | 
| +    
 | 
| +private:
 | 
| +    SkXfermode::U64State    fState;
 | 
| +    SkXfermode::U64ProcN    fXfer;
 | 
| +
 | 
| +    typedef Sprite_4f INHERITED;
 | 
| +};
 | 
| +
 | 
| +
 | 
| +SkSpriteBlitter* SkSpriteBlitter::ChooseF16(const SkPixmap& source, const SkPaint& paint,
 | 
| +                                            SkTBlitterAllocator* allocator) {
 | 
| +    SkASSERT(allocator != nullptr);
 | 
| +
 | 
| +    if (paint.getMaskFilter() != nullptr) {
 | 
| +        return nullptr;
 | 
| +    }
 | 
| +
 | 
| +    switch (source.colorType()) {
 | 
| +        case kN32_SkColorType:
 | 
| +        case kRGBA_F16_SkColorType:
 | 
| +            return allocator->createT<Sprite_F16>(source, paint);
 | 
| +        default:
 | 
| +            return nullptr;
 | 
| +    }
 | 
| +}
 | 
| +
 | 
| +///////////////////////////////////////////////////////////////////////////////////////////////////
 | 
| +
 | 
| +class Sprite_sRGB : public Sprite_4f {
 | 
| +public:
 | 
| +    Sprite_sRGB(const SkPixmap& src, const SkPaint& paint) : INHERITED(src, paint) {
 | 
| +        fState = { paint.getXfermode(), SkXfermode::kDstIsSRGB_PM4fFlag };
 | 
| +        if (src.isOpaque()) {
 | 
| +            fState.fFlags |= SkXfermode::kSrcIsOpaque_PM4fFlag;
 | 
| +        }
 | 
| +        fXfer = SkXfermode::GetPM4fProcN(get_mode(fState.fXfer), fState.fFlags);
 | 
| +    }
 | 
| +    
 | 
| +    void blitRect(int x, int y, int width, int height) override {
 | 
| +        SkASSERT(width > 0 && height > 0);
 | 
| +        uint32_t* SK_RESTRICT dst = fDst.writable_addr32(x, y);
 | 
| +        size_t dstRB = fDst.rowBytes();
 | 
| +        
 | 
| +        for (int bottom = y + height; y < bottom; ++y) {
 | 
| +            fLoader(fSource, x - fLeft, y - fTop, fBuffer, width);
 | 
| +            fFilter(*fPaint, fBuffer, width);
 | 
| +            fXfer(fState, dst, fBuffer, width, nullptr);
 | 
| +            dst = (uint32_t* SK_RESTRICT)((char*)dst + dstRB);
 | 
| +        }
 | 
| +    }
 | 
| +    
 | 
| +protected:
 | 
| +    SkXfermode::PM4fState   fState;
 | 
| +    SkXfermode::PM4fProcN   fXfer;
 | 
| +    
 | 
| +private:
 | 
| +    typedef Sprite_4f INHERITED;
 | 
| +};
 | 
| +
 | 
| +
 | 
| +SkSpriteBlitter* SkSpriteBlitter::ChooseS32(const SkPixmap& source, const SkPaint& paint,
 | 
| +                                            SkTBlitterAllocator* allocator) {
 | 
| +    SkASSERT(allocator != nullptr);
 | 
| +    
 | 
| +    if (paint.getMaskFilter() != nullptr) {
 | 
| +        return nullptr;
 | 
| +    }
 | 
| +    
 | 
| +    switch (source.colorType()) {
 | 
| +        case kN32_SkColorType:
 | 
| +        case kRGBA_F16_SkColorType:
 | 
| +            return allocator->createT<Sprite_sRGB>(source, paint);
 | 
| +        default:
 | 
| +            return nullptr;
 | 
| +    }
 | 
| +}
 | 
| 
 |