blob: 1fc8329de781185f7fee25667b5a26bb89e3fe03 [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"
Mike Kleind37d5d92016-12-14 13:38:24 +000012#include "SkImageInfo.h"
mtklein281b33f2016-07-12 15:01:26 -070013#include "SkNx.h"
14#include "SkTArray.h"
15#include "SkTypes.h"
Mike Klein0a76b412017-05-22 12:01:59 -040016#include <functional>
Mike Kleincc631732016-12-06 09:17:55 -050017#include <vector>
mtklein281b33f2016-07-12 15:01:26 -070018
Mike Kleinbba02c22017-06-02 10:03:30 -040019struct SkJumper_constants;
Mike Kleinb24704d2017-05-24 07:53:00 -040020
mtklein281b33f2016-07-12 15:01:26 -070021/**
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 *
30 * Each stage is represented by a function conforming to a common interface, SkRasterPipeline::Fn,
31 * and by an arbitrary context pointer. Fn's arguments, and sometimes custom calling convention,
32 * are designed to maximize the amount of data we can pass along the pipeline cheaply.
33 * On many machines all arguments stay in registers the entire time.
34 *
Mike Kleinc8dd6bc2016-09-28 10:43:53 -040035 * The meaning of the arguments to Fn are sometimes fixed:
mtklein281b33f2016-07-12 15:01:26 -070036 * - The Stage* always represents the current stage, mainly providing access to ctx().
Mike Kleinc8dd6bc2016-09-28 10:43:53 -040037 * - The first size_t is always the destination x coordinate.
38 * (If you need y, put it in your context.)
39 * - The second size_t is always tail: 0 when working on a full 4-pixel slab,
40 * or 1..3 when using only the bottom 1..3 lanes of each register.
mtklein281b33f2016-07-12 15:01:26 -070041 * - By the time the shader's done, the first four vectors should hold source red,
42 * green, blue, and alpha, up to 4 pixels' worth each.
43 *
Mike Kleinc8dd6bc2016-09-28 10:43:53 -040044 * Sometimes arguments are flexible:
mtklein281b33f2016-07-12 15:01:26 -070045 * - In the shader, the first four vectors can be used for anything, e.g. sample coordinates.
46 * - The last four vectors are scratch registers that can be used to communicate between
47 * stages; transfer modes use these to hold the original destination pixel components.
48 *
49 * On some platforms the last four vectors are slower to work with than the other arguments.
50 *
51 * When done mutating its arguments and/or context, a stage can either:
52 * 1) call st->next() with its mutated arguments, chaining to the next stage of the pipeline; or
53 * 2) return, indicating the pipeline is complete for these pixels.
54 *
Mike Kleinc8dd6bc2016-09-28 10:43:53 -040055 * Some stages that typically return are those that write a color to a destination pointer,
mtklein281b33f2016-07-12 15:01:26 -070056 * but any stage can short-circuit the rest of the pipeline by returning instead of calling next().
57 */
58
Mike Kleinc8dd6bc2016-09-28 10:43:53 -040059// TODO: There may be a better place to stuff tail, e.g. in the bottom alignment bits of
60// the Stage*. This mostly matters on 64-bit Windows where every register is precious.
61
Mike Klein1f49f262016-10-31 19:49:27 -040062#define SK_RASTER_PIPELINE_STAGES(M) \
Mike Klein7fee90c2017-04-07 16:55:09 -040063 M(callback) \
Mike Klein8c8cb5b2017-01-06 10:21:56 -050064 M(move_src_dst) M(move_dst_src) M(swap) \
Mike Reed279091e2017-06-27 16:58:00 -040065 M(clamp_0) M(clamp_1) M(clamp_a) M(clamp_a_dst) \
Mike Kleind5de0132016-11-28 09:33:02 -050066 M(unpremul) M(premul) \
Mike Reed279091e2017-06-27 16:58:00 -040067 M(set_rgb) M(swap_rb) M(swap_rb_dst) \
68 M(from_srgb) M(from_srgb_dst) M(to_srgb) \
Mike Klein581e6982017-05-03 13:05:13 -040069 M(constant_color) M(seed_shader) M(dither) \
Mike Reed279091e2017-06-27 16:58:00 -040070 M(load_a8) M(load_a8_dst) M(store_a8) \
71 M(load_g8) M(load_g8_dst) \
72 M(load_565) M(load_565_dst) M(store_565) \
73 M(load_4444) M(load_4444_dst) M(store_4444) \
74 M(load_f16) M(load_f16_dst) M(store_f16) \
75 M(load_f32) M(load_f32_dst) M(store_f32) \
76 M(load_8888) M(load_8888_dst) M(store_8888) \
Matt Sarett1da27ef2017-01-19 17:14:07 -050077 M(load_u16_be) M(load_rgb_u16_be) M(store_u16_be) \
Matt Sarett5bee0b62017-01-19 12:04:32 -050078 M(load_tables_u16_be) M(load_tables_rgb_u16_be) \
Mike Reed9959f722017-05-15 09:34:22 -040079 M(load_tables) M(load_rgba) M(store_rgba) \
Mike Kleinbabd93e2016-11-30 16:05:10 -050080 M(scale_u8) M(scale_1_float) \
81 M(lerp_u8) M(lerp_565) M(lerp_1_float) \
Mike Klein1f49f262016-10-31 19:49:27 -040082 M(dstatop) M(dstin) M(dstout) M(dstover) \
83 M(srcatop) M(srcin) M(srcout) M(srcover) \
84 M(clear) M(modulate) M(multiply) M(plus_) M(screen) M(xor_) \
85 M(colorburn) M(colordodge) M(darken) M(difference) \
86 M(exclusion) M(hardlight) M(lighten) M(overlay) M(softlight) \
Mike Kleinbb338332017-05-04 12:42:52 -040087 M(hue) M(saturation) M(color) M(luminosity) \
Mike Klein50626262017-05-25 13:06:57 -040088 M(srcover_rgba_8888) \
Mike Klein06a65e22016-11-17 12:39:09 -050089 M(luminance_to_alpha) \
Mike Reed02640952017-05-19 15:32:13 -040090 M(matrix_2x3) M(matrix_3x4) M(matrix_4x5) M(matrix_4x3) \
Mike Kleinc01e7df2016-11-17 16:27:10 -050091 M(matrix_perspective) \
Mike Kleincfcf6242016-11-16 09:01:30 -050092 M(parametric_r) M(parametric_g) M(parametric_b) \
raftias54761282016-12-01 13:44:07 -050093 M(parametric_a) \
94 M(table_r) M(table_g) M(table_b) M(table_a) \
Mike Kleinc17dc242017-04-20 16:21:57 -040095 M(lab_to_xyz) \
Mike Klein9f85d682017-05-23 07:52:01 -040096 M(clamp_x) M(mirror_x) M(repeat_x) \
97 M(clamp_y) M(mirror_y) M(repeat_y) \
98 M(clamp_x_1) M(mirror_x_1) M(repeat_x_1) \
Mike Kleinb04c3522016-11-28 11:55:58 -050099 M(gather_a8) M(gather_g8) M(gather_i8) \
100 M(gather_565) M(gather_4444) M(gather_8888) M(gather_f16) \
Mike Kleinb0b17d12016-12-09 16:25:44 -0500101 M(bilinear_nx) M(bilinear_px) M(bilinear_ny) M(bilinear_py) \
102 M(bicubic_n3x) M(bicubic_n1x) M(bicubic_p1x) M(bicubic_p3x) \
103 M(bicubic_n3y) M(bicubic_n1y) M(bicubic_p1y) M(bicubic_p3y) \
Florin Malitac86e4702017-01-20 08:41:34 -0500104 M(save_xy) M(accumulate) \
Herb Derby4de13042017-05-15 10:49:39 -0400105 M(evenly_spaced_gradient) \
Mike Reed65331592017-05-24 16:45:34 -0400106 M(gauss_a_to_rgba) M(gradient) \
Mike Klein5c7960b2017-05-11 10:59:22 -0400107 M(evenly_spaced_2_stop_gradient) \
108 M(xy_to_unit_angle) \
Herb Derby090fbf82017-05-08 15:10:36 -0400109 M(xy_to_radius) \
Matt Sarette522f4c2017-02-22 13:02:31 -0500110 M(byte_tables) M(byte_tables_rgb) \
Dominic Mazzoni394d4142017-02-14 11:15:31 -0800111 M(rgb_to_hsl) \
112 M(hsl_to_rgb)
Mike Kleinaebfb452016-10-25 10:27:33 -0400113
mtklein281b33f2016-07-12 15:01:26 -0700114class SkRasterPipeline {
115public:
Mike Kleinb24704d2017-05-24 07:53:00 -0400116 explicit SkRasterPipeline(SkArenaAlloc*);
117
118 SkRasterPipeline(const SkRasterPipeline&) = delete;
119 SkRasterPipeline(SkRasterPipeline&&) = default;
120
121 SkRasterPipeline& operator=(const SkRasterPipeline&) = delete;
122 SkRasterPipeline& operator=(SkRasterPipeline&&) = default;
123
124 void reset();
mtklein281b33f2016-07-12 15:01:26 -0700125
Mike Kleinfa9f2412016-09-29 13:40:01 -0400126 enum StockStage {
Mike Kleinaebfb452016-10-25 10:27:33 -0400127 #define M(stage) stage,
128 SK_RASTER_PIPELINE_STAGES(M)
129 #undef M
Mike Kleinfa9f2412016-09-29 13:40:01 -0400130 };
Mike Klein26bea5d2016-10-05 10:36:38 -0400131 void append(StockStage, void* = nullptr);
132 void append(StockStage stage, const void* ctx) { this->append(stage, const_cast<void*>(ctx)); }
Mike Kleinfa9f2412016-09-29 13:40:01 -0400133
mtklein9a5c47f2016-07-22 11:05:04 -0700134 // Append all stages to this pipeline.
135 void extend(const SkRasterPipeline&);
136
Mike Klein319ba3d2017-01-20 15:11:54 -0500137 // Runs the pipeline walking x through [x,x+n).
Mike Klein761d27c2017-06-01 12:37:08 -0400138 void run(size_t x, size_t y, size_t n) const;
Mike Kleinc789b612016-11-30 13:45:06 -0500139
Mike Klein0a76b412017-05-22 12:01:59 -0400140 // Allocates a thunk which amortizes run() setup cost in alloc.
Mike Klein761d27c2017-06-01 12:37:08 -0400141 std::function<void(size_t, size_t, size_t)> compile() const;
Mike Klein0a76b412017-05-22 12:01:59 -0400142
Mike Klein3928c6b2016-11-15 16:18:38 -0500143 void dump() const;
144
Mike Kleind37d5d92016-12-14 13:38:24 +0000145 // Conversion from sRGB can be subtly tricky when premultiplication is involved.
146 // Use these helpers to keep things sane.
Mike Klein8c8cb5b2017-01-06 10:21:56 -0500147 void append_from_srgb(SkAlphaType);
Mike Reed279091e2017-06-27 16:58:00 -0400148 void append_from_srgb_dst(SkAlphaType);
Mike Kleind37d5d92016-12-14 13:38:24 +0000149
Mike Kleinb24704d2017-05-24 07:53:00 -0400150 bool empty() const { return fStages == nullptr; }
Mike Klein1859f692017-05-22 08:28:45 -0400151
mtklein281b33f2016-07-12 15:01:26 -0700152private:
Mike Kleineeccbf72017-06-05 11:02:15 -0400153 using StartPipelineFn = void(size_t,size_t,size_t,void**,const SkJumper_constants*);
Mike Kleinbba02c22017-06-02 10:03:30 -0400154
Mike Kleinb24704d2017-05-24 07:53:00 -0400155 struct StageList {
156 StageList* prev;
157 StockStage stage;
158 void* ctx;
159 };
160
Mike Kleinbba02c22017-06-02 10:03:30 -0400161 StartPipelineFn* build_pipeline(void**) const;
Mike Kleinb24704d2017-05-24 07:53:00 -0400162 void unchecked_append(StockStage, void*);
Mike Kleinb24704d2017-05-24 07:53:00 -0400163
164 SkArenaAlloc* fAlloc;
165 StageList* fStages;
Mike Klein9fff1112017-05-24 11:37:52 -0400166 int fNumStages;
Mike Kleinb24704d2017-05-24 07:53:00 -0400167 int fSlotsNeeded;
mtklein281b33f2016-07-12 15:01:26 -0700168};
169
Mike Kleinb24704d2017-05-24 07:53:00 -0400170template <size_t bytes>
171class SkRasterPipeline_ : public SkRasterPipeline {
172public:
173 SkRasterPipeline_()
Florin Malita14a64302017-05-24 14:53:44 -0400174 : SkRasterPipeline(&fBuiltinAlloc) {}
Mike Kleinb24704d2017-05-24 07:53:00 -0400175
176private:
Florin Malita14a64302017-05-24 14:53:44 -0400177 SkSTArenaAlloc<bytes> fBuiltinAlloc;
Mike Kleinb24704d2017-05-24 07:53:00 -0400178};
179
180
mtklein281b33f2016-07-12 15:01:26 -0700181#endif//SkRasterPipeline_DEFINED