Chromium Code Reviews| Index: src/core/SkSpriteBlitterU64.cpp |
| diff --git a/src/core/SkSpriteBlitterU64.cpp b/src/core/SkSpriteBlitterU64.cpp |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..5c6647dc019e67be65d8d3cd05530bcd93e1c834 |
| --- /dev/null |
| +++ b/src/core/SkSpriteBlitterU64.cpp |
| @@ -0,0 +1,168 @@ |
| + |
| +/* |
| + * Copyright 2006 The Android Open Source Project |
| + * |
| + * Use of this source code is governed by a BSD-style license that can be |
| + * found in the LICENSE file. |
|
herb_g
2016/02/19 21:36:46
I think this should be:
/*
* Copyright 2016 Googl
reed1
2016/02/20 19:37:17
Done.
|
| + */ |
| + |
| + |
| +#include "SkSpriteBlitter.h" |
| +#include "SkColorFilter.h" |
| +#include "SkHalf.h" |
| +#include "SkNx.h" |
| +#include "SkPM4f.h" |
| +#include "SkPM4fPriv.h" |
| +#include "SkTemplates.h" |
| +#include "SkUtils.h" |
| +#include "SkXfermode.h" |
| + |
| +/////////////////////////////////////////////////////////////////////////////////////////////////// |
| + |
| +typedef void (*SkLoadSpanProc)(const SkPixmap&, int x, int y, SkPM4f span[], int count); |
| + |
| +static void load_l32(const SkPixmap& src, int x, int y, SkPM4f span[], int count) { |
| + SkASSERT(count > 0); |
| + const uint32_t* addr = src.addr32(x, y); |
| + SkASSERT(src.addr32(x + count - 1, y)); |
| + |
| + for (int i = 0; i < count; ++i) { |
| + (SkNx_cast<float>(Sk4b::Load(&addr[i])) * Sk4f(1.0f/255)).store(span[i].fVec); |
|
f(malita)
2016/02/19 20:38:43
Is there a benefit to loading Sk4f(1/255) outside
mtklein
2016/02/19 20:41:17
It's very hoistable. I'd only move it out of the
|
| + } |
| +} |
| + |
| +static void load_s32(const SkPixmap& src, int x, int y, SkPM4f span[], int count) { |
| + SkASSERT(count > 0); |
| + const uint32_t* addr = src.addr32(x, y); |
| + SkASSERT(src.addr32(x + count - 1, y)); |
| + |
| + for (int i = 0; i < count; ++i) { |
| + srgb_to_linear(SkNx_cast<float>(Sk4b::Load(&addr[i])) * Sk4f(1.0f/255)).store(span[i].fVec); |
| + } |
| +} |
| + |
| +static void load_f16(const SkPixmap& src, int x, int y, SkPM4f span[], int count) { |
| + SkASSERT(count > 0); |
| + const uint64_t* addr = src.addr64(x, y); |
| + SkASSERT(src.addr64(x + count - 1, y)); |
| + |
| + for (int i = 0; i < count; ++i) { |
| + SkHalfToFloat_01(addr[i]).store(span[i].fVec); |
| + } |
| +} |
| + |
| +static SkLoadSpanProc choose_loadspanproc(const SkImageInfo& info) { |
| + switch (info.colorType()) { |
| + case kN32_SkColorType: |
| + return info.isSRGB() ? load_s32 : load_l32; |
| + case kRGBA_F16_SkColorType: |
| + return load_f16; |
| + default: |
| + return nullptr; |
| + } |
| +} |
| + |
| +/////////////////////////////////////////////////////////////////////////////////////////////////// |
| + |
| +typedef void (*SkFilterSpanProc)(const SkPaint& paint, SkPM4f span[], int count); |
| + |
| +static void noop_filterspan(const SkPaint& paint, SkPM4f[], int) { |
| + SkASSERT(!paint.getColorFilter()); |
| + SkASSERT(0xFF == paint.getAlpha()); |
| +} |
| + |
| +static void alpha_filterspan(const SkPaint& paint, SkPM4f span[], int count) { |
| + SkASSERT(!paint.getColorFilter()); |
| + SkASSERT(0xFF != paint.getAlpha()); |
| + const Sk4f scale = Sk4f(paint.getAlpha() * (1.0f/255)); |
| + for (int i = 0; i < count; ++i) { |
| + (Sk4f::Load(span[i].fVec) * scale).store(span[i].fVec); |
| + } |
| +} |
| + |
| +static void colorfilter_filterspan(const SkPaint& paint, SkPM4f span[], int count) { |
| + SkASSERT(paint.getColorFilter()); |
| + SkASSERT(0xFF == paint.getAlpha()); |
| + paint.getColorFilter()->filterSpan4f(span, count, span); |
| +} |
| + |
| +static void colorfilter_alpha_filterspan(const SkPaint& paint, SkPM4f span[], int count) { |
| + SkASSERT(paint.getColorFilter()); |
| + SkASSERT(0xFF != paint.getAlpha()); |
| + alpha_filterspan(paint, span, count); |
| + paint.getColorFilter()->filterSpan4f(span, count, span); |
| +} |
| + |
| +static SkFilterSpanProc choose_filterspanproc(const SkPaint& paint) { |
| + if (paint.getColorFilter()) { |
| + return 0xFF == paint.getAlpha() ? colorfilter_filterspan : colorfilter_alpha_filterspan; |
| + } else { |
| + return 0xFF == paint.getAlpha() ? noop_filterspan : alpha_filterspan; |
| + } |
| +} |
| + |
| +/////////////////////////////////////////////////////////////////////////////////////////////////// |
| + |
| +static SkXfermode::Mode get_mode(const SkXfermode* xfer) { |
| + SkXfermode::Mode mode; |
| + if (!SkXfermode::AsMode(xfer, &mode)) { |
| + mode = SkXfermode::kSrcOver_Mode; |
| + } |
| + return mode; |
| +} |
| + |
| +class Sprite_D64 : public SkSpriteBlitter { |
| +public: |
| + Sprite_D64(const SkPixmap& src, const SkPaint& paint) : INHERITED(src) { |
| + fLoader = choose_loadspanproc(src.info()); |
| + fFilter = choose_filterspanproc(paint); |
| + fState = { paint.getXfermode(), SkXfermode::kDstIsFloat16_U64Flag }; |
| + fXfer = SkXfermode::GetU64ProcN(get_mode(fState.fXfer), fState.fFlags); |
| + fBuffer = new SkPM4f[src.width()]; |
| + } |
| + |
| + ~Sprite_D64() { |
| + delete[] fBuffer; |
| + } |
| + |
| + 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); |
| + } |
| + } |
| + |
| +protected: |
| + SkLoadSpanProc fLoader; |
| + SkFilterSpanProc fFilter; |
| + SkXfermode::U64State fState; |
| + SkXfermode::U64ProcN fXfer; |
| + SkPM4f* fBuffer; |
|
f(malita)
2016/02/19 20:38:43
SkAutoTMalloc?
|
| + |
| +private: |
| + typedef SkSpriteBlitter INHERITED; |
| +}; |
| + |
| + |
| +SkSpriteBlitter* SkSpriteBlitter::ChooseD64(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_D64>(source, paint); |
| + default: |
| + return nullptr; |
| + } |
| +} |