• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1Contributing to SkJumper
2========================
3
4SkJumper is the execution engine of SkRasterPipeline, a system we've been using
5to accelerate CPU-bound work inside Skia, most notably color-space conversions
6and color-correct drawing.
7
8(This is where I'd put my link to design document if I had one...)
9
10SkJumper is more annoying to contribute to than most Skia code because of its
11offline compilation step.  You'll need particular tools installed on your
12machine and to tell GN about them.  This document is designed to guide you
13through this process and ease some of that annoyance.
14
15One-time Setup
16--------------
17
18To generate stage code you need Clang 5.0, objdump, and ccache.  It's best that
19Clang is exactly the same version we typically use (as of writing 5.0.0) and
20you'll need objdump to be compiled with support for x86-64, ARMv7, and ARMv8.
21
22The easiest way to satisfy these contraints is to get your hands on a Mac and
23install Xcode, Xcode command line tools, and [Homebrew](https://brew.sh).  Once
24you have `brew` installed, run these commands to get the tools you need:
25
26<!--?prettify lang=sh?-->
27
28    ls -d /usr/include >/dev/null || xcode-select --install
29    brew install llvm binutils ccache
30
31Setting up GN
32-------------------------
33
34With your tools installed, tell GN about them
35
36    skia_jumper_clang = path/to/clang-5.0
37    skia_jumper_objdump = path/to/gobjdump
38    skia_jumper_ccache = path/to/ccache
39
40then regenerate and build as normal.
41
42If you look in your GN out directory, you should now see a bunch of `.o` files,
43and `git status` should show no changes to `src/jumper/SkJumper_generated*.S`.
44That's good.  Those object files are the intermediates we parse to produce
45the assembly files.  We just leave them around in case you want to look at
46them yourself.
47
48Make A Change
49-------------
50
51Let's use the `from_srgb` stage as a little playground to make a real change.
52Linearizing sRGB encoded bytes is slow, so let's pretend we've decided to trade
53quality for speed, approximating the existing implementation with a simple square.
54
55Open up `SkJumper_stages.cpp` and find the `from_srgb` stage.  It'll look like
56
57<!--?prettify lang=cc?-->
58
59    STAGE(from_srgb) {
60        r = from_srgb(r);
61        g = from_srgb(g);
62        b = from_srgb(b);
63    }
64
65Let's replace whatever's there with our fast approximation:
66
67<!--?prettify lang=cc?-->
68
69    STAGE(from_srgb) {
70        r *= r;
71        g *= g;
72        b *= b;
73    }
74
75When you save and re-Ninja, you should now see changes to
76`src/jumper/SkJumper_generated.S` and `src/jumper/SkJumper_generated_win.S`.
77If you can't read assembly, no big deal.  If you can, run `git diff`.  You
78should see the various `sk_from_srgb_*` functions get dramatically simpler,
79something like three multiplies and a couple other bookkeeping instructions.
80
81It's not unusual for isolated changes in one stage to cause seemingly unrelated
82changes in another.  When adding or removing any code you'll usually see all
83the comments in branch instructions change a little bit, but the actual
84instruction on the left won't change.  When adding or removing uses of
85constants, you'll often see both the comment and instruction on the left change
86for other loads of constants from memory, especially on x86-64.  You'll also
87see some code that looks like garbage change; those are the constants.  If
88any of this worries you, please do go running to someone who knows more for
89help, but odds are everything is fine.
90
91At this point things should just be business as usual.  Any time you change
92`SkJumper_stages.cpp`, Ninja ought to notice and regenerate the assembly files.
93
94Adding a new Stage
95------------------
96
97Adding a new stage is a lot like changing an existing stage.  Edit
98`SkJumper_stages.cpp`, build Skia, test, repeat until correct.
99
100You'll just need to also edit `SkRasterPipeline.h` to add your new stage to the
101macro listing all the stages.  The stage name is the handle normal Skia code
102uses to refer to the stage abstractly, and the wiring between
103`SkRasterPipeline::foo` and `STAGE(foo) { ... }` should work automatically.
104