• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2015 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 SkOpts_DEFINED
9 #define SkOpts_DEFINED
10 
11 #include "include/core/SkTypes.h"
12 #include "include/private/SkOpts_spi.h"
13 #include "src/core/SkRasterPipelineOpList.h"
14 #include "src/core/SkXfermodePriv.h"
15 
16 /**
17  * SkOpts (short for SkOptimizations) is a mechanism where we can ship with multiple implementations
18  * of a set of functions and dynamically choose the best one at runtime (e.g. the call to
19  * SkGraphics::Init(), which calls SkOpts::Init()) depending on the detected CPU features. This is
20  * also referred to as having "specializations" of a given function.
21  *
22  * For example, Skia might be compiled to support CPUs that only have the sse2 instruction set
23  * (https://en.wikipedia.org/wiki/X86_instruction_listings#SSE2_instructions)
24  * but may be run on a more modern CPU that supports sse42 instructions.
25  * (https://en.wikipedia.org/wiki/SSE4)
26  * SkOpts allow Skia to have two versions of a CRC32 checksum function, one that uses normal C++
27  * code (e.g. loops, bit operations, table lookups) and one that makes use of the _mm_crc32_u64
28  * intrinsic function which uses the SSE4.2 crc32 machine instruction under the hood. This hash
29  * function is declared here in the SkOpts namespace, and then the implementation (see SkOpts.cpp)
30  * is deferred to a function of the same name in the sse2:: namespace (the minimum Skia is compiled
31  * with) using DEFINE_DEFAULT.
32  *
33  * All implementations of this hash function are done in a header file file in //src/opts
34  * (e.g. //src/opts/SkChecksum_opts.h). ifdefs guard each of the implementations, such that only
35  * one implementation is possible for a given SK_CPU_SSE_LEVEL. This header will be compiled
36  * *multiple* times with a different SK_CPU_SSE_LEVEL each compilation.
37  *
38  * Each CPU instruction set that we want specializations for has a .cpp file in //src/opts which
39  * defines an Init() function that replaces the function pointers in the SkOpts namespace with the
40  * ones from the specialized namespace (e.g. sse42::). These .cpp files don't implement the
41  * specializations, they just refer to the specialization created in the header files (e.g.
42  * SkChecksum_opts.h).
43  *
44  * At compile time:
45  *   - SkOpts.cpp is compiled with the minimum CPU level (e.g. SSE2). Because this
46  *     file includes all the headers in //src/opts/, those headers add "the default implementation"
47  *     of all their functions to the SK_OPTS_NS namespace (e.g. sse2::hash_fn).
48  *   - Each of the specialized .cpp files in //src/opts/ are compiled with their respective
49  *     compiler flags. Because the specialized .cpp file includes the headers that implement the
50  *     functions using intrinsics or other CPU-specific code, those specialized functions end up
51  *     in the specialized namespace, e.g. (sse42::hash_fn).
52  *
53  * At link time, the default implementations and all specializations of all SkOpts functions are
54  * included in the resulting library/binary file.
55  *
56  * At runtime, SkOpts::Init() will run the appropriate Init functions that the current CPU level
57  * supports specializations for (e.g. Init_sse42, Init_ssse3). Note multiple Init functions can
58  * be called as CPU instruction sets are typically super sets of older instruction sets
59  */
60 
61 struct SkBitmapProcState;
62 struct SkRasterPipelineStage;
63 namespace skvm {
64 struct InterpreterInstruction;
65 class TraceHook;
66 }
67 
68 namespace SkOpts {
69     // Call to replace pointers to portable functions with pointers to CPU-specific functions.
70     // Thread-safe and idempotent.
71     // Called by SkGraphics::Init().
72     void Init();
73 
74     // Declare function pointers here...
75 
76     // May return nullptr if we haven't specialized the given Mode.
77     extern SkXfermode* (*create_xfermode)(SkBlendMode);
78 
79     extern void (*blit_mask_d32_a8)(SkPMColor*, size_t, const SkAlpha*, size_t, SkColor, int, int);
80     extern void (*blit_row_color32)(SkPMColor*, const SkPMColor*, int, SkPMColor);
81     extern void (*blit_row_s32a_opaque)(SkPMColor*, const SkPMColor*, int, U8CPU);
82 
83     // Swizzle input into some sort of 8888 pixel, {premul,unpremul} x {rgba,bgra}.
84     typedef void (*Swizzle_8888_u32)(uint32_t*, const uint32_t*, int);
85     extern Swizzle_8888_u32 RGBA_to_BGRA,          // i.e. just swap RB
86                             RGBA_to_rgbA,          // i.e. just premultiply
87                             RGBA_to_bgrA,          // i.e. swap RB and premultiply
88                             inverted_CMYK_to_RGB1, // i.e. convert color space
89                             inverted_CMYK_to_BGR1; // i.e. convert color space
90 
91     typedef void (*Swizzle_8888_u8)(uint32_t*, const uint8_t*, int);
92     extern Swizzle_8888_u8 RGB_to_RGB1,     // i.e. insert an opaque alpha
93                            RGB_to_BGR1,     // i.e. swap RB and insert an opaque alpha
94                            gray_to_RGB1,    // i.e. expand to color channels + an opaque alpha
95                            grayA_to_RGBA,   // i.e. expand to color channels
96                            grayA_to_rgbA;   // i.e. expand to color channels and premultiply
97 
98     extern void (*memset16)(uint16_t[], uint16_t, int);
99     extern void (*memset32)(uint32_t[], uint32_t, int);
100     extern void (*memset64)(uint64_t[], uint64_t, int);
101 
102     extern void (*rect_memset16)(uint16_t[], uint16_t, int, size_t, int);
103     extern void (*rect_memset32)(uint32_t[], uint32_t, int, size_t, int);
104     extern void (*rect_memset64)(uint64_t[], uint64_t, int, size_t, int);
105 
106     extern float (*cubic_solver)(float, float, float, float);
107 
108     static inline uint32_t hash(const void* data, size_t bytes, uint32_t seed=0) {
109         // hash_fn is defined in SkOpts_spi.h so it can be used by //modules
110         return hash_fn(data, bytes, seed);
111     }
112 
113     // SkBitmapProcState optimized Shader, Sample, or Matrix procs.
114     extern void (*S32_alpha_D32_filter_DX)(const SkBitmapProcState&,
115                                            const uint32_t* xy, int count, SkPMColor*);
116     extern void (*S32_alpha_D32_filter_DXDY)(const SkBitmapProcState&,
117                                              const uint32_t* xy, int count, SkPMColor*);
118 
119     // We can't necessarily express the type of SkRasterPipeline stage functions here,
120     // so we just use this void(*)(void) as a stand-in.
121     using StageFn = void(*)(void);
122     extern StageFn ops_highp[kNumRasterPipelineHighpOps], just_return_highp;
123     extern StageFn ops_lowp [kNumRasterPipelineLowpOps ], just_return_lowp;
124 
125     extern void (*start_pipeline_highp)(size_t,size_t,size_t,size_t, SkRasterPipelineStage*);
126     extern void (*start_pipeline_lowp )(size_t,size_t,size_t,size_t, SkRasterPipelineStage*);
127 
128     extern size_t raster_pipeline_lowp_stride;
129     extern size_t raster_pipeline_highp_stride;
130 
131     extern void (*interpret_skvm)(const skvm::InterpreterInstruction insts[], int ninsts,
132                                   int nregs, int loop, const int strides[],
133                                   skvm::TraceHook* traceHooks[], int nTraceHooks,
134                                   int nargs, int n, void* args[]);
135 }  // namespace SkOpts
136 
137 #endif // SkOpts_DEFINED
138