1/*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkColorFilter.h"
9#include "SkHalf.h"
10#include "SkNx.h"
11#include "SkPaint.h"
12#include "SkPixmap.h"
13#include "SkPM4f.h"
14#include "SkPM4fPriv.h"
15#include "SkSpanProcs.h"
16
17///////////////////////////////////////////////////////////////////////////////////////////////////
18
19static void load_l32(const SkPixmap& src, int x, int y, SkPM4f span[], int count) {
20    SkASSERT(count > 0);
21    const uint32_t* addr = src.addr32(x, y);
22    SkASSERT(src.addr32(x + count - 1, y));
23
24    for (int i = 0; i < count; ++i) {
25        (SkNx_cast<float>(Sk4b::Load(&addr[i])) * Sk4f(1.0f/255)).store(span[i].fVec);
26    }
27}
28
29static void load_s32(const SkPixmap& src, int x, int y, SkPM4f span[], int count) {
30    SkASSERT(count > 0);
31    const uint32_t* addr = src.addr32(x, y);
32    SkASSERT(src.addr32(x + count - 1, y));
33
34    for (int i = 0; i < count; ++i) {
35        srgb_to_linear(SkNx_cast<float>(Sk4b::Load(&addr[i])) * Sk4f(1.0f/255)).store(span[i].fVec);
36    }
37}
38
39static void load_f16(const SkPixmap& src, int x, int y, SkPM4f span[], int count) {
40    SkASSERT(count > 0);
41    const uint64_t* addr = src.addr64(x, y);
42    SkASSERT(src.addr64(x + count - 1, y));
43
44    for (int i = 0; i < count; ++i) {
45        SkHalfToFloat_01(addr[i]).store(span[i].fVec);
46    }
47}
48
49SkLoadSpanProc SkLoadSpanProc_Choose(const SkImageInfo& info) {
50    switch (info.colorType()) {
51        case kN32_SkColorType:
52            return info.isSRGB() ? load_s32 : load_l32;
53        case kRGBA_F16_SkColorType:
54            return load_f16;
55        default:
56            return nullptr;
57    }
58}
59
60///////////////////////////////////////////////////////////////////////////////////////////////////
61
62static void noop_filterspan(const SkPaint& paint, SkPM4f[], int) {
63    SkASSERT(!paint.getColorFilter());
64    SkASSERT(0xFF == paint.getAlpha());
65}
66
67static void alpha_filterspan(const SkPaint& paint, SkPM4f span[], int count) {
68    SkASSERT(!paint.getColorFilter());
69    SkASSERT(0xFF != paint.getAlpha());
70    const Sk4f scale = Sk4f(paint.getAlpha() * (1.0f/255));
71    for (int i = 0; i < count; ++i) {
72        (Sk4f::Load(span[i].fVec) * scale).store(span[i].fVec);
73    }
74}
75
76static void colorfilter_filterspan(const SkPaint& paint, SkPM4f span[], int count) {
77    SkASSERT(paint.getColorFilter());
78    SkASSERT(0xFF == paint.getAlpha());
79    paint.getColorFilter()->filterSpan4f(span, count, span);
80}
81
82static void colorfilter_alpha_filterspan(const SkPaint& paint, SkPM4f span[], int count) {
83    SkASSERT(paint.getColorFilter());
84    SkASSERT(0xFF != paint.getAlpha());
85    alpha_filterspan(paint, span, count);
86    paint.getColorFilter()->filterSpan4f(span, count, span);
87}
88
89SkFilterSpanProc SkFilterSpanProc_Choose(const SkPaint& paint) {
90    if (paint.getColorFilter()) {
91        return 0xFF == paint.getAlpha() ? colorfilter_filterspan : colorfilter_alpha_filterspan;
92    } else {
93        return 0xFF == paint.getAlpha() ? noop_filterspan : alpha_filterspan;
94    }
95}
96