blob: 809f4045a614cef1bccc1ea56cbfd1987ffdd57b [file] [log] [blame]
mtklein281b33f2016-07-12 15:01:26 -07001/*
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#ifndef SkRasterPipeline_DEFINED
9#define SkRasterPipeline_DEFINED
10
Mike Klein0a76b412017-05-22 12:01:59 -040011#include "SkArenaAlloc.h"
Brian Osman81cbd032018-09-21 11:09:15 -040012#include "SkColor.h"
Mike Kleind37d5d92016-12-14 13:38:24 +000013#include "SkImageInfo.h"
mtklein281b33f2016-07-12 15:01:26 -070014#include "SkNx.h"
15#include "SkTArray.h"
16#include "SkTypes.h"
Mike Klein0a76b412017-05-22 12:01:59 -040017#include <functional>
Mike Kleincc631732016-12-06 09:17:55 -050018#include <vector>
Mike Kleinafa35022018-09-17 16:41:26 -040019#include "../jumper/SkJumper.h"
mtklein281b33f2016-07-12 15:01:26 -070020
21/**
22 * SkRasterPipeline provides a cheap way to chain together a pixel processing pipeline.
23 *
24 * It's particularly designed for situations where the potential pipeline is extremely
25 * combinatoric: {N dst formats} x {M source formats} x {K mask formats} x {C transfer modes} ...
26 * No one wants to write specialized routines for all those combinations, and if we did, we'd
27 * end up bloating our code size dramatically. SkRasterPipeline stages can be chained together
28 * at runtime, so we can scale this problem linearly rather than combinatorically.
29 *
Mike Kleinb8d88d72017-06-29 12:21:22 -040030 * Each stage is represented by a function conforming to a common interface and by an
31 * arbitrary context pointer. The stage funciton arguments and calling convention are
32 * designed to maximize the amount of data we can pass along the pipeline cheaply, and
33 * vary depending on CPU feature detection.
mtklein281b33f2016-07-12 15:01:26 -070034 *
Mike Kleinb8d88d72017-06-29 12:21:22 -040035 * If you'd like to see how this works internally, you want to start digging around src/jumper.
mtklein281b33f2016-07-12 15:01:26 -070036 */
37
Mike Klein3cbcb732017-10-25 12:38:25 -040038#define SK_RASTER_PIPELINE_STAGES(M) \
39 M(callback) \
40 M(move_src_dst) M(move_dst_src) \
Mike Kleineb50f432018-09-07 11:08:53 -040041 M(clamp_0) M(clamp_1) M(clamp_a) M(clamp_a_dst) M(clamp_gamut) \
Mike Klein3cbcb732017-10-25 12:38:25 -040042 M(unpremul) M(premul) M(premul_dst) \
Mike Kleinac568a92018-01-25 09:09:32 -050043 M(force_opaque) M(force_opaque_dst) \
Mike Klein1a3eb522018-10-18 10:11:00 -040044 M(set_rgb) M(unbounded_set_rgb) M(swap_rb) M(swap_rb_dst) \
Mike Klein6f02af92018-06-05 15:11:11 -040045 M(from_srgb) M(to_srgb) \
Mike Kleincd3e13a2018-07-10 15:52:06 +000046 M(black_color) M(white_color) M(uniform_color) M(unbounded_uniform_color) \
Mike Klein3cbcb732017-10-25 12:38:25 -040047 M(seed_shader) M(dither) \
48 M(load_a8) M(load_a8_dst) M(store_a8) M(gather_a8) \
Mike Klein3cbcb732017-10-25 12:38:25 -040049 M(load_565) M(load_565_dst) M(store_565) M(gather_565) \
50 M(load_4444) M(load_4444_dst) M(store_4444) M(gather_4444) \
51 M(load_f16) M(load_f16_dst) M(store_f16) M(gather_f16) \
Mike Klein37854712018-06-26 11:43:06 -040052 M(load_f32) M(load_f32_dst) M(store_f32) M(gather_f32) \
Mike Klein3cbcb732017-10-25 12:38:25 -040053 M(load_8888) M(load_8888_dst) M(store_8888) M(gather_8888) \
Mike Kleinac568a92018-01-25 09:09:32 -050054 M(load_1010102) M(load_1010102_dst) M(store_1010102) M(gather_1010102) \
Mike Kleinb1df5e52018-10-17 17:06:03 -040055 M(alpha_to_gray) M(alpha_to_gray_dst) M(luminance_to_alpha) \
Mike Klein1fa9c432017-12-11 09:59:47 -050056 M(bilerp_clamp_8888) \
Mike Klein6747f522018-05-22 10:32:20 -040057 M(store_u16_be) \
Mike Klein3cbcb732017-10-25 12:38:25 -040058 M(load_rgba) M(store_rgba) \
59 M(scale_u8) M(scale_565) M(scale_1_float) \
60 M( lerp_u8) M( lerp_565) M( lerp_1_float) \
61 M(dstatop) M(dstin) M(dstout) M(dstover) \
62 M(srcatop) M(srcin) M(srcout) M(srcover) \
63 M(clear) M(modulate) M(multiply) M(plus_) M(screen) M(xor_) \
64 M(colorburn) M(colordodge) M(darken) M(difference) \
65 M(exclusion) M(hardlight) M(lighten) M(overlay) M(softlight) \
66 M(hue) M(saturation) M(color) M(luminosity) \
Mike Kleindd9bfe92018-10-17 17:15:07 -040067 M(srcover_rgba_8888) \
Mike Klein3cbcb732017-10-25 12:38:25 -040068 M(matrix_translate) M(matrix_scale_translate) \
Mike Kleinb82edcc2018-07-10 18:25:03 +000069 M(matrix_2x3) M(matrix_3x3) M(matrix_3x4) M(matrix_4x5) M(matrix_4x3) \
Mike Klein3cbcb732017-10-25 12:38:25 -040070 M(matrix_perspective) \
Mike Klein4eebd9e2018-07-11 14:49:51 -040071 M(parametric) M(gamma) \
Mike Klein6747f522018-05-22 10:32:20 -040072 M(mirror_x) M(repeat_x) \
73 M(mirror_y) M(repeat_y) \
74 M(decal_x) M(decal_y) M(decal_x_and_y) \
Mike Reeddfc0e912018-02-16 12:40:18 -050075 M(check_decal_mask) \
Yuqian Lid208a882018-01-04 10:08:42 -050076 M(negate_x) \
Mike Klein3cbcb732017-10-25 12:38:25 -040077 M(bilinear_nx) M(bilinear_px) M(bilinear_ny) M(bilinear_py) \
78 M(bicubic_n3x) M(bicubic_n1x) M(bicubic_p1x) M(bicubic_p3x) \
79 M(bicubic_n3y) M(bicubic_n1y) M(bicubic_p1y) M(bicubic_p3y) \
80 M(save_xy) M(accumulate) \
Mike Kleine95a62f2017-11-01 13:31:28 -040081 M(clamp_x_1) M(mirror_x_1) M(repeat_x_1) \
Mike Klein3cbcb732017-10-25 12:38:25 -040082 M(evenly_spaced_gradient) \
83 M(gradient) \
84 M(evenly_spaced_2_stop_gradient) \
85 M(xy_to_unit_angle) \
86 M(xy_to_radius) \
Yuqian Lid208a882018-01-04 10:08:42 -050087 M(xy_to_2pt_conical_strip) \
88 M(xy_to_2pt_conical_focal_on_circle) \
89 M(xy_to_2pt_conical_well_behaved) \
90 M(xy_to_2pt_conical_smaller) \
91 M(xy_to_2pt_conical_greater) \
92 M(alter_2pt_conical_compensate_focal) \
93 M(alter_2pt_conical_unswap) \
94 M(mask_2pt_conical_nan) \
Mike Klein3cbcb732017-10-25 12:38:25 -040095 M(mask_2pt_conical_degenerates) M(apply_vector_mask) \
Mike Klein6747f522018-05-22 10:32:20 -040096 M(byte_tables) \
Mike Klein3cbcb732017-10-25 12:38:25 -040097 M(rgb_to_hsl) M(hsl_to_rgb) \
Mike Klein3cbcb732017-10-25 12:38:25 -040098 M(gauss_a_to_rgba)
Mike Kleinaebfb452016-10-25 10:27:33 -040099
mtklein281b33f2016-07-12 15:01:26 -0700100class SkRasterPipeline {
101public:
Mike Kleinb24704d2017-05-24 07:53:00 -0400102 explicit SkRasterPipeline(SkArenaAlloc*);
103
104 SkRasterPipeline(const SkRasterPipeline&) = delete;
105 SkRasterPipeline(SkRasterPipeline&&) = default;
106
107 SkRasterPipeline& operator=(const SkRasterPipeline&) = delete;
108 SkRasterPipeline& operator=(SkRasterPipeline&&) = default;
109
110 void reset();
mtklein281b33f2016-07-12 15:01:26 -0700111
Mike Kleinfa9f2412016-09-29 13:40:01 -0400112 enum StockStage {
Mike Kleinaebfb452016-10-25 10:27:33 -0400113 #define M(stage) stage,
114 SK_RASTER_PIPELINE_STAGES(M)
115 #undef M
Mike Kleinfa9f2412016-09-29 13:40:01 -0400116 };
Mike Klein26bea5d2016-10-05 10:36:38 -0400117 void append(StockStage, void* = nullptr);
118 void append(StockStage stage, const void* ctx) { this->append(stage, const_cast<void*>(ctx)); }
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400119 // For raw functions (i.e. from a JIT). Don't use this unless you know exactly what fn needs to
120 // be. :)
121 void append(void* fn, void* ctx);
Mike Kleinfa9f2412016-09-29 13:40:01 -0400122
mtklein9a5c47f2016-07-22 11:05:04 -0700123 // Append all stages to this pipeline.
124 void extend(const SkRasterPipeline&);
125
Mike Klein3b92b692017-07-18 11:30:25 -0400126 // Runs the pipeline in 2d from (x,y) inclusive to (x+w,y+h) exclusive.
Mike Klein45c16fa2017-07-18 18:15:13 -0400127 void run(size_t x, size_t y, size_t w, size_t h) const;
Mike Klein3b92b692017-07-18 11:30:25 -0400128
Mike Klein0a76b412017-05-22 12:01:59 -0400129 // Allocates a thunk which amortizes run() setup cost in alloc.
Mike Klein45c16fa2017-07-18 18:15:13 -0400130 std::function<void(size_t, size_t, size_t, size_t)> compile() const;
Mike Klein0a76b412017-05-22 12:01:59 -0400131
Mike Klein3928c6b2016-11-15 16:18:38 -0500132 void dump() const;
133
Mike Klein073073e2017-08-03 09:42:53 -0400134 // Appends a stage for the specified matrix.
135 // Tries to optimize the stage by analyzing the type of matrix.
Mike Reed6b59bf42017-07-03 21:26:44 -0400136 void append_matrix(SkArenaAlloc*, const SkMatrix&);
137
Mike Klein073073e2017-08-03 09:42:53 -0400138 // Appends a stage for a constant uniform color.
139 // Tries to optimize the stage based on the color.
Mike Klein16776df2017-08-03 10:22:42 -0400140 void append_constant_color(SkArenaAlloc*, const float rgba[4]);
141
Mike Klein16776df2017-08-03 10:22:42 -0400142 void append_constant_color(SkArenaAlloc* alloc, const SkColor4f& color) {
143 this->append_constant_color(alloc, color.vec());
144 }
Mike Reedc91e3872017-07-05 14:12:37 -0400145
Mike Kleinbe569492018-09-14 09:34:21 -0400146 // Like append_constant_color() but only affecting r,g,b, ignoring the alpha channel.
147 void append_set_rgb(SkArenaAlloc*, const float rgb[3]);
148
149 void append_set_rgb(SkArenaAlloc* alloc, const SkColor4f& color) {
150 this->append_set_rgb(alloc, color.vec());
151 }
152
Mike Kleinafa35022018-09-17 16:41:26 -0400153 void append_load (SkColorType, const SkJumper_MemoryCtx*);
154 void append_load_dst(SkColorType, const SkJumper_MemoryCtx*);
155 void append_store (SkColorType, const SkJumper_MemoryCtx*);
156
Mike Klein0a44d5c2018-10-02 11:10:59 -0400157 void append_gamut_clamp_if_normalized(const SkImageInfo&);
158
Mike Kleinb24704d2017-05-24 07:53:00 -0400159 bool empty() const { return fStages == nullptr; }
Mike Klein1859f692017-05-22 08:28:45 -0400160
Mike Kleinafa35022018-09-17 16:41:26 -0400161
mtklein281b33f2016-07-12 15:01:26 -0700162private:
Mike Kleinb24704d2017-05-24 07:53:00 -0400163 struct StageList {
164 StageList* prev;
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400165 uint64_t stage;
Mike Kleinb24704d2017-05-24 07:53:00 -0400166 void* ctx;
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400167 bool rawFunction;
Mike Kleinb24704d2017-05-24 07:53:00 -0400168 };
169
Mike Klein1b9b7d52018-02-27 10:37:40 -0500170 using StartPipelineFn = void(*)(size_t,size_t,size_t,size_t, void** program);
171 StartPipelineFn build_pipeline(void**) const;
172
Mike Kleinb24704d2017-05-24 07:53:00 -0400173 void unchecked_append(StockStage, void*);
Mike Kleinb24704d2017-05-24 07:53:00 -0400174
175 SkArenaAlloc* fAlloc;
176 StageList* fStages;
Mike Klein9fff1112017-05-24 11:37:52 -0400177 int fNumStages;
Mike Kleinb24704d2017-05-24 07:53:00 -0400178 int fSlotsNeeded;
mtklein281b33f2016-07-12 15:01:26 -0700179};
180
Mike Kleinb24704d2017-05-24 07:53:00 -0400181template <size_t bytes>
182class SkRasterPipeline_ : public SkRasterPipeline {
183public:
184 SkRasterPipeline_()
Florin Malita14a64302017-05-24 14:53:44 -0400185 : SkRasterPipeline(&fBuiltinAlloc) {}
Mike Kleinb24704d2017-05-24 07:53:00 -0400186
187private:
Florin Malita14a64302017-05-24 14:53:44 -0400188 SkSTArenaAlloc<bytes> fBuiltinAlloc;
Mike Kleinb24704d2017-05-24 07:53:00 -0400189};
190
191
mtklein281b33f2016-07-12 15:01:26 -0700192#endif//SkRasterPipeline_DEFINED