1281b33fdd909ee3f43192cdf950ce00e3df62407mtklein/*
2281b33fdd909ee3f43192cdf950ce00e3df62407mtklein * Copyright 2016 Google Inc.
3281b33fdd909ee3f43192cdf950ce00e3df62407mtklein *
4281b33fdd909ee3f43192cdf950ce00e3df62407mtklein * Use of this source code is governed by a BSD-style license that can be
5281b33fdd909ee3f43192cdf950ce00e3df62407mtklein * found in the LICENSE file.
6281b33fdd909ee3f43192cdf950ce00e3df62407mtklein */
7281b33fdd909ee3f43192cdf950ce00e3df62407mtklein
8281b33fdd909ee3f43192cdf950ce00e3df62407mtklein#ifndef SkRasterPipeline_DEFINED
9281b33fdd909ee3f43192cdf950ce00e3df62407mtklein#define SkRasterPipeline_DEFINED
10281b33fdd909ee3f43192cdf950ce00e3df62407mtklein
110a76b413eac46ec218b367c5456709059557f5dbMike Klein#include "SkArenaAlloc.h"
12d37d5d96493604c12cfaa2d64bcbd32c41b01f3bMike Klein#include "SkImageInfo.h"
13281b33fdd909ee3f43192cdf950ce00e3df62407mtklein#include "SkNx.h"
14281b33fdd909ee3f43192cdf950ce00e3df62407mtklein#include "SkTArray.h"
15281b33fdd909ee3f43192cdf950ce00e3df62407mtklein#include "SkTypes.h"
160a76b413eac46ec218b367c5456709059557f5dbMike Klein#include <functional>
17cc63173634e773eac5de0b92f05d117ed2bdca84Mike Klein#include <vector>
18281b33fdd909ee3f43192cdf950ce00e3df62407mtklein
19bba02c203190a19bce7eb60887c4ae64041c8ae8Mike Kleinstruct SkJumper_constants;
203b92b6907a6b9f7020a7589ad07cad2472fe4e86Mike Kleinstruct SkJumper_Engine;
21c91e3877a57ef140b688627b8c0acaafbefc9034Mike Reedstruct SkPM4f;
22b24704d35f67f5b460be9c92794892e06adceb46Mike Klein
23281b33fdd909ee3f43192cdf950ce00e3df62407mtklein/**
24281b33fdd909ee3f43192cdf950ce00e3df62407mtklein * SkRasterPipeline provides a cheap way to chain together a pixel processing pipeline.
25281b33fdd909ee3f43192cdf950ce00e3df62407mtklein *
26281b33fdd909ee3f43192cdf950ce00e3df62407mtklein * It's particularly designed for situations where the potential pipeline is extremely
27281b33fdd909ee3f43192cdf950ce00e3df62407mtklein * combinatoric: {N dst formats} x {M source formats} x {K mask formats} x {C transfer modes} ...
28281b33fdd909ee3f43192cdf950ce00e3df62407mtklein * No one wants to write specialized routines for all those combinations, and if we did, we'd
29281b33fdd909ee3f43192cdf950ce00e3df62407mtklein * end up bloating our code size dramatically.  SkRasterPipeline stages can be chained together
30281b33fdd909ee3f43192cdf950ce00e3df62407mtklein * at runtime, so we can scale this problem linearly rather than combinatorically.
31281b33fdd909ee3f43192cdf950ce00e3df62407mtklein *
32b8d88d72cbe9cc3dde91eaf58e928b34748526a7Mike Klein * Each stage is represented by a function conforming to a common interface and by an
33b8d88d72cbe9cc3dde91eaf58e928b34748526a7Mike Klein * arbitrary context pointer.  The stage funciton arguments and calling convention are
34b8d88d72cbe9cc3dde91eaf58e928b34748526a7Mike Klein * designed to maximize the amount of data we can pass along the pipeline cheaply, and
35b8d88d72cbe9cc3dde91eaf58e928b34748526a7Mike Klein * vary depending on CPU feature detection.
36281b33fdd909ee3f43192cdf950ce00e3df62407mtklein *
37b8d88d72cbe9cc3dde91eaf58e928b34748526a7Mike Klein * If you'd like to see how this works internally, you want to start digging around src/jumper.
38281b33fdd909ee3f43192cdf950ce00e3df62407mtklein */
39281b33fdd909ee3f43192cdf950ce00e3df62407mtklein
401f49f26353997195030aeab41c8665e1860d2958Mike Klein#define SK_RASTER_PIPELINE_STAGES(M)                             \
417fee90cb5eda2345bb8ec9be706aea1a09866005Mike Klein    M(callback)                                                  \
429f2b3d1fbfa16146184a13b778fbe2fa5355c51bMike Klein    M(move_src_dst) M(move_dst_src)                              \
43279091ef85eec98969b72805bbf613f1c0660380Mike Reed    M(clamp_0) M(clamp_1) M(clamp_a) M(clamp_a_dst)              \
44883c9bce671fb955574a6c0e46f57f57189bd6c6Mike Reed    M(unpremul) M(premul) M(premul_dst)                          \
45111f8a9eea6980a70a300e3a8bfd758257310fe2Mike Klein    M(set_rgb) M(swap_rb)                                        \
46279091ef85eec98969b72805bbf613f1c0660380Mike Reed    M(from_srgb) M(from_srgb_dst) M(to_srgb)                     \
47c91e3877a57ef140b688627b8c0acaafbefc9034Mike Reed    M(black_color) M(white_color) M(uniform_color)               \
48c91e3877a57ef140b688627b8c0acaafbefc9034Mike Reed    M(seed_shader) M(dither)                                     \
49111f8a9eea6980a70a300e3a8bfd758257310fe2Mike Klein    M(load_a8)   M(load_a8_dst)   M(store_a8)   M(gather_a8)     \
50111f8a9eea6980a70a300e3a8bfd758257310fe2Mike Klein    M(load_g8)   M(load_g8_dst)                 M(gather_g8)     \
51111f8a9eea6980a70a300e3a8bfd758257310fe2Mike Klein    M(load_565)  M(load_565_dst)  M(store_565)  M(gather_565)    \
52111f8a9eea6980a70a300e3a8bfd758257310fe2Mike Klein    M(load_4444) M(load_4444_dst) M(store_4444) M(gather_4444)   \
53111f8a9eea6980a70a300e3a8bfd758257310fe2Mike Klein    M(load_f16)  M(load_f16_dst)  M(store_f16)  M(gather_f16)    \
54279091ef85eec98969b72805bbf613f1c0660380Mike Reed    M(load_f32)  M(load_f32_dst)  M(store_f32)                   \
55111f8a9eea6980a70a300e3a8bfd758257310fe2Mike Klein    M(load_8888) M(load_8888_dst) M(store_8888) M(gather_8888)   \
56111f8a9eea6980a70a300e3a8bfd758257310fe2Mike Klein    M(load_bgra) M(load_bgra_dst) M(store_bgra) M(gather_bgra)   \
571da27ef853ae3e701b7f4aae670c21684396dcceMatt Sarett    M(load_u16_be) M(load_rgb_u16_be) M(store_u16_be)            \
585bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett    M(load_tables_u16_be) M(load_tables_rgb_u16_be)              \
599959f723c33d609519c265abb5c4f48cba71fd6fMike Reed    M(load_tables) M(load_rgba) M(store_rgba)                    \
60babd93e11290067da65567ea02f556c251a67c71Mike Klein    M(scale_u8) M(scale_1_float)                                 \
61babd93e11290067da65567ea02f556c251a67c71Mike Klein    M(lerp_u8) M(lerp_565) M(lerp_1_float)                       \
621f49f26353997195030aeab41c8665e1860d2958Mike Klein    M(dstatop) M(dstin) M(dstout) M(dstover)                     \
631f49f26353997195030aeab41c8665e1860d2958Mike Klein    M(srcatop) M(srcin) M(srcout) M(srcover)                     \
641f49f26353997195030aeab41c8665e1860d2958Mike Klein    M(clear) M(modulate) M(multiply) M(plus_) M(screen) M(xor_)  \
651f49f26353997195030aeab41c8665e1860d2958Mike Klein    M(colorburn) M(colordodge) M(darken) M(difference)           \
661f49f26353997195030aeab41c8665e1860d2958Mike Klein    M(exclusion) M(hardlight) M(lighten) M(overlay) M(softlight) \
67bb33833ed25c30007e4ea3cd3de6df728407f94eMike Klein    M(hue) M(saturation) M(color) M(luminosity)                  \
68506262665c9b02514dea9a4da3211a00fdf02dbeMike Klein    M(srcover_rgba_8888)                                         \
6906a65e2799eaead18f778792801406aff4aec0d9Mike Klein    M(luminance_to_alpha)                                        \
707aad8cc2ff7a580bd5852d57289ace8c8dced6f5Mike Reed    M(matrix_translate) M(matrix_scale_translate)                \
710264095cfd1aa205b0af218c7e5abbaff8a5db0cMike Reed    M(matrix_2x3) M(matrix_3x4) M(matrix_4x5) M(matrix_4x3)      \
72c01e7dff5fa013832b808f72ac74d81eaa1cb145Mike Klein    M(matrix_perspective)                                        \
73cfcf624c39683a8364fa7f22235b787a23675780Mike Klein    M(parametric_r) M(parametric_g) M(parametric_b)              \
745476128f0a88217414f05e6a7ee518cdb411d026raftias    M(parametric_a)                                              \
755476128f0a88217414f05e6a7ee518cdb411d026raftias    M(table_r) M(table_g) M(table_b) M(table_a)                  \
76c17dc24fa9994eacc640d3adc6633a02fd96d3fcMike Klein    M(lab_to_xyz)                                                \
779f85d68887a61f93656dbfacdd3f978d510c02eeMike Klein    M(clamp_x)   M(mirror_x)   M(repeat_x)                       \
789f85d68887a61f93656dbfacdd3f978d510c02eeMike Klein    M(clamp_y)   M(mirror_y)   M(repeat_y)                       \
799f85d68887a61f93656dbfacdd3f978d510c02eeMike Klein    M(clamp_x_1) M(mirror_x_1) M(repeat_x_1)                     \
80b0b17d1e5375a65b8956a8990d63e0d02357fdafMike Klein    M(bilinear_nx) M(bilinear_px) M(bilinear_ny) M(bilinear_py)  \
81b0b17d1e5375a65b8956a8990d63e0d02357fdafMike Klein    M(bicubic_n3x) M(bicubic_n1x) M(bicubic_p1x) M(bicubic_p3x)  \
82b0b17d1e5375a65b8956a8990d63e0d02357fdafMike Klein    M(bicubic_n3y) M(bicubic_n1y) M(bicubic_p1y) M(bicubic_p3y)  \
83c86e470c190934a2f7680ed10cf9fad757e1ab75Florin Malita    M(save_xy) M(accumulate)                                     \
844de1304297d7220b223c829bf386f97815db1654Herb Derby    M(evenly_spaced_gradient)                                    \
856533159f2c83d0af51f79c3d85461580e2346080Mike Reed    M(gauss_a_to_rgba) M(gradient)                               \
865c7960be57010bf61db3d4ce879a3194687b5af9Mike Klein    M(evenly_spaced_2_stop_gradient)                             \
875c7960be57010bf61db3d4ce879a3194687b5af9Mike Klein    M(xy_to_unit_angle)                                          \
88090fbf86cf90dd326b3b3b59cde0a46b63a594a6Herb Derby    M(xy_to_radius)                                              \
899026fe13a751582e58e98f9bf735c18b4719d7feFlorin Malita    M(xy_to_2pt_conical_quadratic_min)                           \
909026fe13a751582e58e98f9bf735c18b4719d7feFlorin Malita    M(xy_to_2pt_conical_quadratic_max)                           \
919026fe13a751582e58e98f9bf735c18b4719d7feFlorin Malita    M(xy_to_2pt_conical_linear)                                  \
929026fe13a751582e58e98f9bf735c18b4719d7feFlorin Malita    M(mask_2pt_conical_degenerates) M(apply_vector_mask)         \
93e522f4c455d0d5dbe813f38d16c0d4cd46fa5deeMatt Sarett    M(byte_tables) M(byte_tables_rgb)                            \
943b92b6907a6b9f7020a7589ad07cad2472fe4e86Mike Klein    M(rgb_to_hsl) M(hsl_to_rgb)                                  \
953b92b6907a6b9f7020a7589ad07cad2472fe4e86Mike Klein    M(store_8888_2d)
96aebfb45104eeb6dab5dbbedda13c2eaa7b7f7868Mike Klein
97281b33fdd909ee3f43192cdf950ce00e3df62407mtkleinclass SkRasterPipeline {
98281b33fdd909ee3f43192cdf950ce00e3df62407mtkleinpublic:
99b24704d35f67f5b460be9c92794892e06adceb46Mike Klein    explicit SkRasterPipeline(SkArenaAlloc*);
100b24704d35f67f5b460be9c92794892e06adceb46Mike Klein
101b24704d35f67f5b460be9c92794892e06adceb46Mike Klein    SkRasterPipeline(const SkRasterPipeline&) = delete;
102b24704d35f67f5b460be9c92794892e06adceb46Mike Klein    SkRasterPipeline(SkRasterPipeline&&)      = default;
103b24704d35f67f5b460be9c92794892e06adceb46Mike Klein
104b24704d35f67f5b460be9c92794892e06adceb46Mike Klein    SkRasterPipeline& operator=(const SkRasterPipeline&) = delete;
105b24704d35f67f5b460be9c92794892e06adceb46Mike Klein    SkRasterPipeline& operator=(SkRasterPipeline&&)      = default;
106b24704d35f67f5b460be9c92794892e06adceb46Mike Klein
107b24704d35f67f5b460be9c92794892e06adceb46Mike Klein    void reset();
108281b33fdd909ee3f43192cdf950ce00e3df62407mtklein
109fa9f241a85c55c32a3fe2ae0324811de998f7a2eMike Klein    enum StockStage {
110aebfb45104eeb6dab5dbbedda13c2eaa7b7f7868Mike Klein    #define M(stage) stage,
111aebfb45104eeb6dab5dbbedda13c2eaa7b7f7868Mike Klein        SK_RASTER_PIPELINE_STAGES(M)
112aebfb45104eeb6dab5dbbedda13c2eaa7b7f7868Mike Klein    #undef M
113fa9f241a85c55c32a3fe2ae0324811de998f7a2eMike Klein    };
11426bea5d55735367152378bae14453e9666d1c625Mike Klein    void append(StockStage, void* = nullptr);
11526bea5d55735367152378bae14453e9666d1c625Mike Klein    void append(StockStage stage, const void* ctx) { this->append(stage, const_cast<void*>(ctx)); }
116fa9f241a85c55c32a3fe2ae0324811de998f7a2eMike Klein
1179a5c47f4effba3b48a9a8c7c144b72b532d06efemtklein    // Append all stages to this pipeline.
1189a5c47f4effba3b48a9a8c7c144b72b532d06efemtklein    void extend(const SkRasterPipeline&);
1199a5c47f4effba3b48a9a8c7c144b72b532d06efemtklein
120319ba3d3a177498095c31696e0aec8b3af25f663Mike Klein    // Runs the pipeline walking x through [x,x+n).
121761d27c4d76bbd553c10cfe835d572b6fa33cf26Mike Klein    void run(size_t x, size_t y, size_t n) const;
122c789b61167dd98efc3c3bfcf9673eef24c2e57f4Mike Klein
1233b92b6907a6b9f7020a7589ad07cad2472fe4e86Mike Klein    // Runs the pipeline in 2d from (x,y) inclusive to (x+w,y+h) exclusive.
1243b92b6907a6b9f7020a7589ad07cad2472fe4e86Mike Klein    void run_2d(size_t x, size_t y, size_t w, size_t h) const;
1253b92b6907a6b9f7020a7589ad07cad2472fe4e86Mike Klein
1260a76b413eac46ec218b367c5456709059557f5dbMike Klein    // Allocates a thunk which amortizes run() setup cost in alloc.
127761d27c4d76bbd553c10cfe835d572b6fa33cf26Mike Klein    std::function<void(size_t, size_t, size_t)> compile() const;
1280a76b413eac46ec218b367c5456709059557f5dbMike Klein
1293928c6b6165cf2d13d3b5f50762d7f621706a946Mike Klein    void dump() const;
1303928c6b6165cf2d13d3b5f50762d7f621706a946Mike Klein
131d37d5d96493604c12cfaa2d64bcbd32c41b01f3bMike Klein    // Conversion from sRGB can be subtly tricky when premultiplication is involved.
132d37d5d96493604c12cfaa2d64bcbd32c41b01f3bMike Klein    // Use these helpers to keep things sane.
1338c8cb5bfc547229422a33db5c344fe1542bf00a7Mike Klein    void append_from_srgb(SkAlphaType);
134279091ef85eec98969b72805bbf613f1c0660380Mike Reed    void append_from_srgb_dst(SkAlphaType);
135d37d5d96493604c12cfaa2d64bcbd32c41b01f3bMike Klein
1366b59bf424c9d9d8a72d3c002871f143e6aff623eMike Reed    // Appends a stage for the specified matrix. Tries to optimize the stage by analyzing
1376b59bf424c9d9d8a72d3c002871f143e6aff623eMike Reed    // the type of matrix.
1386b59bf424c9d9d8a72d3c002871f143e6aff623eMike Reed    void append_matrix(SkArenaAlloc*, const SkMatrix&);
1396b59bf424c9d9d8a72d3c002871f143e6aff623eMike Reed
140c91e3877a57ef140b688627b8c0acaafbefc9034Mike Reed    // Appends a stage for the uniform color. Tries to optimize the stage based on the color.
141c91e3877a57ef140b688627b8c0acaafbefc9034Mike Reed    void append_uniform_color(SkArenaAlloc*, const SkPM4f& color);
142c91e3877a57ef140b688627b8c0acaafbefc9034Mike Reed
143b24704d35f67f5b460be9c92794892e06adceb46Mike Klein    bool empty() const { return fStages == nullptr; }
144b24704d35f67f5b460be9c92794892e06adceb46Mike Klein
145b24704d35f67f5b460be9c92794892e06adceb46Mike Kleinprivate:
146b24704d35f67f5b460be9c92794892e06adceb46Mike Klein    struct StageList {
147b24704d35f67f5b460be9c92794892e06adceb46Mike Klein        StageList* prev;
148b24704d35f67f5b460be9c92794892e06adceb46Mike Klein        StockStage stage;
149b24704d35f67f5b460be9c92794892e06adceb46Mike Klein        void*      ctx;
150b24704d35f67f5b460be9c92794892e06adceb46Mike Klein    };
151b24704d35f67f5b460be9c92794892e06adceb46Mike Klein
1523b92b6907a6b9f7020a7589ad07cad2472fe4e86Mike Klein    const SkJumper_Engine& build_pipeline(void**) const;
153b24704d35f67f5b460be9c92794892e06adceb46Mike Klein    void unchecked_append(StockStage, void*);
1548729e5bbf7c436fd7c7c13182adbbfb419f566b5Mike Klein
155b24704d35f67f5b460be9c92794892e06adceb46Mike Klein    SkArenaAlloc* fAlloc;
156b24704d35f67f5b460be9c92794892e06adceb46Mike Klein    StageList*    fStages;
1579fff11133d1890a2733e8a61ba976492fe800c99Mike Klein    int           fNumStages;
158b24704d35f67f5b460be9c92794892e06adceb46Mike Klein    int           fSlotsNeeded;
159b24704d35f67f5b460be9c92794892e06adceb46Mike Klein};
160b24704d35f67f5b460be9c92794892e06adceb46Mike Klein
161b24704d35f67f5b460be9c92794892e06adceb46Mike Kleintemplate <size_t bytes>
162b24704d35f67f5b460be9c92794892e06adceb46Mike Kleinclass SkRasterPipeline_ : public SkRasterPipeline {
163b24704d35f67f5b460be9c92794892e06adceb46Mike Kleinpublic:
164b24704d35f67f5b460be9c92794892e06adceb46Mike Klein    SkRasterPipeline_()
16514a6430b7bcf92bcabf4aef18805969d1335aab1Florin Malita        : SkRasterPipeline(&fBuiltinAlloc) {}
1661859f69d20e433b86714e5b9002121f2b20a5fc6Mike Klein
167aebfb45104eeb6dab5dbbedda13c2eaa7b7f7868Mike Kleinprivate:
16814a6430b7bcf92bcabf4aef18805969d1335aab1Florin Malita    SkSTArenaAlloc<bytes> fBuiltinAlloc;
169281b33fdd909ee3f43192cdf950ce00e3df62407mtklein};
170281b33fdd909ee3f43192cdf950ce00e3df62407mtklein
171b24704d35f67f5b460be9c92794892e06adceb46Mike Klein
172281b33fdd909ee3f43192cdf950ce00e3df62407mtklein#endif//SkRasterPipeline_DEFINED
173