Bug Summary

File:root/firefox-clang/obj-x86_64-pc-linux-gnu/gfx/skia/./../../../gfx/skia/skia/src/core/SkRasterPipeline.cpp
Warning:line 237, column 17
Value stored to 'name' during its initialization is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name Unified_cpp_gfx_skia9.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/gfx/skia -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/gfx/skia -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -D _GLIBCXX_ASSERTIONS=1 -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D MOZ_SKIA -D SKIA_IMPLEMENTATION=1 -D SK_PDF_USE_HARFBUZZ_SUBSET=1 -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /root/firefox-clang/gfx/skia -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/gfx/skia -I /root/firefox-clang/gfx/skia/skia -I /root/firefox-clang/gfx/harfbuzz/src -I /root/firefox-clang/gfx/cairo/cairo/src -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/sysprof-6 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/x86_64-linux-gnu/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16/backward -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=pessimizing-move -Wno-error=large-by-value-copy=128 -Wno-error=implicit-int-float-conversion -Wno-error=thread-safety-analysis -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -Wno-character-conversion -Wno-deprecated-declarations -Wno-overloaded-virtual -Wno-sign-compare -Wno-unreachable-code -Wno-unused-function -Wno-implicit-fallthrough -Wno-inconsistent-missing-override -Wno-macro-redefined -Wno-unused-private-field -std=gnu++20 -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fno-implicit-modules -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-09-01-224014-2642839-1 -x c++ Unified_cpp_gfx_skia9.cpp
1/*
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#include "src/core/SkRasterPipeline.h"
9
10#include "include/core/SkColorType.h"
11#include "include/core/SkImageInfo.h"
12#include "include/core/SkMatrix.h"
13#include "include/private/base/SkDebug.h"
14#include "include/private/base/SkTemplates.h"
15#include "modules/skcms/skcms.h"
16#include "src/base/SkVx.h"
17#include "src/core/SkImageInfoPriv.h"
18#include "src/core/SkOpts.h"
19#include "src/core/SkRasterPipelineOpContexts.h"
20#include "src/core/SkRasterPipelineOpList.h"
21
22#include <algorithm>
23#include <cstring>
24#include <vector>
25
26using namespace skia_private;
27using Op = SkRasterPipelineOp;
28
29bool gForceHighPrecisionRasterPipeline;
30
31SkRasterPipeline::SkRasterPipeline(SkArenaAlloc* alloc) : fAlloc(alloc) {
32 this->reset();
33}
34
35void SkRasterPipeline::reset() {
36 // We intentionally leave the alloc alone here; we don't own it.
37 fRewindCtx = nullptr;
38 fStages = nullptr;
39 fTailPointer = nullptr;
40 fNumStages = 0;
41 fMemoryCtxInfos.clear();
42}
43
44void SkRasterPipeline::append(SkRasterPipelineOp op, void* ctx) {
45 SkASSERT(op != Op::uniform_color)static_cast<void>( __builtin_expect(static_cast<bool
>(op != Op::uniform_color), 1) ? static_cast<void>(0
) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d"
": fatal error: \"" "check(%s)" "\"\n", "./../../../gfx/skia/skia/src/core/SkRasterPipeline.cpp"
, 45, "op != Op::uniform_color"); ; sk_abort_no_print(); } while
(false); } } while(false); }() )
; // Please use appendConstantColor().
46 SkASSERT(op != Op::unbounded_uniform_color)static_cast<void>( __builtin_expect(static_cast<bool
>(op != Op::unbounded_uniform_color), 1) ? static_cast<
void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf
("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "./../../../gfx/skia/skia/src/core/SkRasterPipeline.cpp"
, 46, "op != Op::unbounded_uniform_color"); ; sk_abort_no_print
(); } while (false); } } while(false); }() )
; // Please use appendConstantColor().
47 SkASSERT(op != Op::set_rgb)static_cast<void>( __builtin_expect(static_cast<bool
>(op != Op::set_rgb), 1) ? static_cast<void>(0) : []
{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \""
"check(%s)" "\"\n", "./../../../gfx/skia/skia/src/core/SkRasterPipeline.cpp"
, 47, "op != Op::set_rgb"); ; sk_abort_no_print(); } while (false
); } } while(false); }() )
; // Please use appendSetRGB().
48 SkASSERT(op != Op::unbounded_set_rgb)static_cast<void>( __builtin_expect(static_cast<bool
>(op != Op::unbounded_set_rgb), 1) ? static_cast<void>
(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d"
": fatal error: \"" "check(%s)" "\"\n", "./../../../gfx/skia/skia/src/core/SkRasterPipeline.cpp"
, 48, "op != Op::unbounded_set_rgb"); ; sk_abort_no_print(); }
while (false); } } while(false); }() )
; // Please use appendSetRGB().
49 SkASSERT(op != Op::parametric)static_cast<void>( __builtin_expect(static_cast<bool
>(op != Op::parametric), 1) ? static_cast<void>(0) :
[]{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \""
"check(%s)" "\"\n", "./../../../gfx/skia/skia/src/core/SkRasterPipeline.cpp"
, 49, "op != Op::parametric"); ; sk_abort_no_print(); } while
(false); } } while(false); }() )
; // Please use appendTransferFunction().
50 SkASSERT(op != Op::gamma_)static_cast<void>( __builtin_expect(static_cast<bool
>(op != Op::gamma_), 1) ? static_cast<void>(0) : []{
do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \""
"check(%s)" "\"\n", "./../../../gfx/skia/skia/src/core/SkRasterPipeline.cpp"
, 50, "op != Op::gamma_"); ; sk_abort_no_print(); } while (false
); } } while(false); }() )
; // Please use appendTransferFunction().
51 SkASSERT(op != Op::PQish)static_cast<void>( __builtin_expect(static_cast<bool
>(op != Op::PQish), 1) ? static_cast<void>(0) : []{ do
{ if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \""
"check(%s)" "\"\n", "./../../../gfx/skia/skia/src/core/SkRasterPipeline.cpp"
, 51, "op != Op::PQish"); ; sk_abort_no_print(); } while (false
); } } while(false); }() )
; // Please use appendTransferFunction().
52 SkASSERT(op != Op::HLGish)static_cast<void>( __builtin_expect(static_cast<bool
>(op != Op::HLGish), 1) ? static_cast<void>(0) : []{
do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \""
"check(%s)" "\"\n", "./../../../gfx/skia/skia/src/core/SkRasterPipeline.cpp"
, 52, "op != Op::HLGish"); ; sk_abort_no_print(); } while (false
); } } while(false); }() )
; // Please use appendTransferFunction().
53 SkASSERT(op != Op::HLGinvish)static_cast<void>( __builtin_expect(static_cast<bool
>(op != Op::HLGinvish), 1) ? static_cast<void>(0) : [
]{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \""
"check(%s)" "\"\n", "./../../../gfx/skia/skia/src/core/SkRasterPipeline.cpp"
, 53, "op != Op::HLGinvish"); ; sk_abort_no_print(); } while (
false); } } while(false); }() )
; // Please use appendTransferFunction().
54 SkASSERT(op != Op::stack_checkpoint)static_cast<void>( __builtin_expect(static_cast<bool
>(op != Op::stack_checkpoint), 1) ? static_cast<void>
(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d"
": fatal error: \"" "check(%s)" "\"\n", "./../../../gfx/skia/skia/src/core/SkRasterPipeline.cpp"
, 54, "op != Op::stack_checkpoint"); ; sk_abort_no_print(); }
while (false); } } while(false); }() )
; // Please use appendStackRewind().
55 SkASSERT(op != Op::stack_rewind)static_cast<void>( __builtin_expect(static_cast<bool
>(op != Op::stack_rewind), 1) ? static_cast<void>(0)
: []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d"
": fatal error: \"" "check(%s)" "\"\n", "./../../../gfx/skia/skia/src/core/SkRasterPipeline.cpp"
, 55, "op != Op::stack_rewind"); ; sk_abort_no_print(); } while
(false); } } while(false); }() )
; // Please use appendStackRewind().
56 this->uncheckedAppend(op, ctx);
57}
58
59uint8_t* SkRasterPipeline::tailPointer() {
60 if (!fTailPointer) {
61 // All ops in the pipeline that use the tail value share the same value.
62 fTailPointer = fAlloc->make<uint8_t>(0xFF);
63 }
64 return fTailPointer;
65}
66
67void SkRasterPipeline::uncheckedAppend(SkRasterPipelineOp op, void* ctx) {
68 bool isLoad = false, isStore = false;
69 SkColorType ct = kUnknown_SkColorType;
70
71#define COLOR_TYPE_CASE(stage_ct, sk_ct) \
72 case Op::load_##stage_ct: \
73 case Op::load_##stage_ct##_dst: \
74 ct = sk_ct; \
75 isLoad = true; \
76 break; \
77 case Op::store_##stage_ct: \
78 ct = sk_ct; \
79 isStore = true; \
80 break;
81
82 switch (op) {
83 COLOR_TYPE_CASE(a8, kAlpha_8_SkColorType)
84 COLOR_TYPE_CASE(565, kRGB_565_SkColorType)
85 COLOR_TYPE_CASE(4444, kARGB_4444_SkColorType)
86 COLOR_TYPE_CASE(8888, kRGBA_8888_SkColorType)
87 COLOR_TYPE_CASE(rg88, kR8G8_unorm_SkColorType)
88 COLOR_TYPE_CASE(16161616, kR16G16B16A16_unorm_SkColorType)
89 COLOR_TYPE_CASE(a16, kA16_unorm_SkColorType)
90 COLOR_TYPE_CASE(r16, kR16_unorm_SkColorType)
91 COLOR_TYPE_CASE(rg1616, kR16G16_unorm_SkColorType)
92 COLOR_TYPE_CASE(f16, kRGBA_F16_SkColorType)
93 COLOR_TYPE_CASE(af16, kA16_float_SkColorType)
94 COLOR_TYPE_CASE(rf16, kR16_float_SkColorType)
95 COLOR_TYPE_CASE(rgf16, kR16G16_float_SkColorType)
96 COLOR_TYPE_CASE(f32, kRGBA_F32_SkColorType)
97 COLOR_TYPE_CASE(1010102, kRGBA_1010102_SkColorType)
98 COLOR_TYPE_CASE(1010102_xr, kBGR_101010x_XR_SkColorType)
99 COLOR_TYPE_CASE(10101010_xr, kBGRA_10101010_XR_SkColorType)
100 COLOR_TYPE_CASE(10x6, kRGBA_10x6_SkColorType)
101
102#undef COLOR_TYPE_CASE
103
104 case Op::debug_r:
105 case Op::debug_g:
106 case Op::debug_b:
107 case Op::debug_a:
108 case Op::debug_r_255:
109 case Op::debug_g_255:
110 case Op::debug_b_255:
111 case Op::debug_a_255:
112 case Op::debug_x:
113 case Op::debug_y: {
114 ct = kRGBA_8888_SkColorType;
115 isStore = true;
116 break;
117 }
118 // Odd stage that doesn't have a load variant (appendLoad uses load_a8 + alpha_to_red)
119 case Op::store_r8: {
120 ct = kR8_unorm_SkColorType;
121 isStore = true;
122 break;
123 }
124 case Op::srcover_rgba_8888: {
125 ct = kRGBA_8888_SkColorType;
126 isLoad = true;
127 isStore = true;
128 break;
129 }
130 case Op::scale_u8:
131 case Op::lerp_u8: {
132 ct = kAlpha_8_SkColorType;
133 isLoad = true;
134 break;
135 }
136 case Op::scale_565:
137 case Op::lerp_565: {
138 ct = kRGB_565_SkColorType;
139 isLoad = true;
140 break;
141 }
142 case Op::emboss: {
143 // Special-case, this op uses a context that holds *two* MemoryCtxs
144 SkRasterPipelineContexts::EmbossCtx* embossCtx =
145 (SkRasterPipelineContexts::EmbossCtx*)ctx;
146 this->addMemoryContext(&embossCtx->add,
147 SkColorTypeBytesPerPixel(kAlpha_8_SkColorType),
148 /*load=*/true, /*store=*/false);
149 this->addMemoryContext(&embossCtx->mul,
150 SkColorTypeBytesPerPixel(kAlpha_8_SkColorType),
151 /*load=*/true, /*store=*/false);
152 break;
153 }
154 case Op::init_lane_masks: {
155 auto* initCtx = (SkRasterPipelineContexts::InitLaneMasksCtx*)ctx;
156 initCtx->tail = this->tailPointer();
157 break;
158 }
159 case Op::branch_if_all_lanes_active: {
160 auto* branchCtx = (SkRasterPipelineContexts::BranchIfAllLanesActiveCtx*)ctx;
161 branchCtx->tail = this->tailPointer();
162 break;
163 }
164 default:
165 break;
166 }
167
168 fStages = fAlloc->make<StageList>(StageList{fStages, op, ctx});
169 fNumStages += 1;
170
171 if (isLoad || isStore) {
172 SkASSERT(ct != kUnknown_SkColorType)static_cast<void>( __builtin_expect(static_cast<bool
>(ct != kUnknown_SkColorType), 1) ? static_cast<void>
(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d"
": fatal error: \"" "check(%s)" "\"\n", "./../../../gfx/skia/skia/src/core/SkRasterPipeline.cpp"
, 172, "ct != kUnknown_SkColorType"); ; sk_abort_no_print(); }
while (false); } } while(false); }() )
;
173 this->addMemoryContext((SkRasterPipelineContexts::MemoryCtx*)ctx,
174 SkColorTypeBytesPerPixel(ct),
175 isLoad,
176 isStore);
177 }
178}
179
180void SkRasterPipeline::append(SkRasterPipelineOp op, uintptr_t ctx) {
181 void* ptrCtx;
182 memcpy(&ptrCtx, &ctx, sizeof(ctx));
183 this->append(op, ptrCtx);
184}
185
186void SkRasterPipeline::extend(const SkRasterPipeline& src) {
187 if (src.empty()) {
188 return;
189 }
190 // Create a rewind context if `src` has one already, but we don't. If we _do_ already have one,
191 // we need to keep it, since we already have rewind ops that reference it. Either way, we need
192 // to rewrite all the rewind ops to point to _our_ rewind context; we only get that checkpoint.
193 if (src.fRewindCtx && !fRewindCtx) {
194 fRewindCtx = fAlloc->make<SkRasterPipelineContexts::RewindCtx>();
195 }
196 auto stages = fAlloc->makeArrayDefault<StageList>(src.fNumStages);
197
198 int n = src.fNumStages;
199 const StageList* st = src.fStages;
200 while (n --> 1) {
201 stages[n] = *st;
202 stages[n].prev = &stages[n-1];
203
204 // We make sure that all ops use _our_ stack context and tail pointer.
205 switch (stages[n].stage) {
206 case Op::stack_rewind: {
207 stages[n].ctx = fRewindCtx;
208 break;
209 }
210 case Op::init_lane_masks: {
211 auto* ctx = (SkRasterPipelineContexts::InitLaneMasksCtx*)stages[n].ctx;
212 ctx->tail = this->tailPointer();
213 break;
214 }
215 case Op::branch_if_all_lanes_active: {
216 auto* ctx = (SkRasterPipelineContexts::BranchIfAllLanesActiveCtx*)stages[n].ctx;
217 ctx->tail = this->tailPointer();
218 break;
219 }
220 default:
221 break;
222 }
223
224 st = st->prev;
225 }
226 stages[0] = *st;
227 stages[0].prev = fStages;
228
229 fStages = &stages[src.fNumStages - 1];
230 fNumStages += src.fNumStages;
231 for (const SkRasterPipelineContexts::MemoryCtxInfo& info : src.fMemoryCtxInfos) {
232 this->addMemoryContext(info.context, info.bytesPerPixel, info.load, info.store);
233 }
234}
235
236const char* SkRasterPipeline::GetOpName(SkRasterPipelineOp op) {
237 const char* name = "";
Value stored to 'name' during its initialization is never read
238 switch (op) {
239 #define M(x) case Op::x: name = #x; break;
240 SK_RASTER_PIPELINE_OPS_ALL(M)M(move_src_dst) M(move_dst_src) M(swap_src_dst) M(clamp_01) M
(clamp_a_01) M(clamp_gamut) M(premul) M(premul_dst) M(force_opaque
) M(force_opaque_dst) M(set_rgb) M(swap_rb) M(swap_rb_dst) M(
black_color) M(white_color) M(uniform_color) M(uniform_color_dst
) M(seed_shader) M(load_a8) M(load_a8_dst) M(store_a8) M(gather_a8
) M(load_565) M(load_565_dst) M(store_565) M(gather_565) M(load_4444
) M(load_4444_dst) M(store_4444) M(gather_4444) M(load_8888) M
(load_8888_dst) M(store_8888) M(gather_8888) M(load_rg88) M(load_rg88_dst
) M(store_rg88) M(gather_rg88) M(store_r8) M(alpha_to_gray) M
(alpha_to_gray_dst) M(alpha_to_red) M(alpha_to_red_dst) M(bt709_luminance_or_luma_to_alpha
) M(bt709_luminance_or_luma_to_rgb) M(bilerp_clamp_8888) M(load_src
) M(store_src) M(store_src_a) M(load_dst) M(store_dst) M(scale_u8
) M(scale_565) M(scale_1_float) M(scale_native) M( lerp_u8) M
( lerp_565) M( lerp_1_float) M(lerp_native) M(dstatop) M(dstin
) M(dstout) M(dstover) M(srcatop) M(srcin) M(srcout) M(srcover
) M(clear) M(modulate) M(multiply) M(plus_) M(screen) M(xor_)
M(darken) M(difference) M(exclusion) M(hardlight) M(lighten)
M(overlay) M(srcover_rgba_8888) M(matrix_translate) M(matrix_scale_translate
) M(matrix_2x3) M(matrix_perspective) M(decal_x) M(decal_y) M
(decal_x_and_y) M(check_decal_mask) M(clamp_x_1) M(mirror_x_1
) M(repeat_x_1) M(clamp_x_and_y) M(evenly_spaced_gradient) M(
gradient) M(evenly_spaced_2_stop_gradient) M(xy_to_unit_angle
) M(xy_to_radius) M(emboss) M(swizzle) M(debug_x) M(debug_y) M
(debug_r) M(debug_g) M(debug_b) M(debug_a) M(debug_r_255) M(debug_g_255
) M(debug_b_255) M(debug_a_255) M(callback) M(stack_checkpoint
) M(stack_rewind) M(unbounded_set_rgb) M(unbounded_uniform_color
) M(unpremul) M(unpremul_polar) M(dither) M(load_16161616) M(
load_16161616_dst) M(store_16161616) M(gather_16161616) M(load_a16
) M(load_a16_dst) M(store_a16) M(gather_a16) M(load_r16) M(load_r16_dst
) M(store_r16) M(gather_r16) M(load_rg1616) M(load_rg1616_dst
) M(store_rg1616) M(gather_rg1616) M(load_f16) M(load_f16_dst
) M(store_f16) M(gather_f16) M(load_af16) M(load_af16_dst) M(
store_af16) M(gather_af16) M(load_rf16) M(load_rf16_dst) M(store_rf16
) M(gather_rf16) M(load_rgf16) M(load_rgf16_dst) M(store_rgf16
) M(gather_rgf16) M(load_f32) M(load_f32_dst) M(store_f32) M(
gather_f32) M(load_1010102) M(load_1010102_dst) M(store_1010102
) M(gather_1010102) M(load_1010102_xr) M(load_1010102_xr_dst)
M(store_1010102_xr) M(gather_1010102_xr) M(load_10x6) M(load_10x6_dst
) M(store_10x6) M(gather_10x6) M(gather_10101010_xr) M(load_10101010_xr
) M(load_10101010_xr_dst) M(store_10101010_xr) M(store_src_rg
) M(load_src_rg) M(byte_tables) M(colorburn) M(colordodge) M(
softlight) M(hue) M(saturation) M(color) M(luminosity) M(matrix_3x3
) M(matrix_3x4) M(matrix_4x5) M(matrix_4x3) M(parametric) M(gamma_
) M(PQish) M(HLGish) M(HLGinvish) M(ootf) M(rgb_to_hsl) M(hsl_to_rgb
) M(css_lab_to_xyz) M(css_oklab_to_linear_srgb) M(css_oklab_gamut_map_to_linear_srgb
) M(css_hcl_to_lab) M(css_hsl_to_srgb) M(css_hwb_to_srgb) M(gauss_a_to_rgba
) M(mirror_x) M(repeat_x) M(mirror_y) M(repeat_y) M(negate_x)
M(bilerp_clamp_8888_force_highp) M(bicubic_clamp_8888) M(bilinear_setup
) M(bilinear_nx) M(bilinear_px) M(bilinear_ny) M(bilinear_py)
M(bicubic_setup) M(bicubic_n3x) M(bicubic_n1x) M(bicubic_p1x
) M(bicubic_p3x) M(bicubic_n3y) M(bicubic_n1y) M(bicubic_p1y)
M(bicubic_p3y) M(accumulate) M(perlin_noise) M(mipmap_linear_init
) M(mipmap_linear_update) M(mipmap_linear_finish) M(xy_to_2pt_conical_strip
) M(xy_to_2pt_conical_focal_on_circle) M(xy_to_2pt_conical_well_behaved
) M(xy_to_2pt_conical_smaller) M(xy_to_2pt_conical_greater) M
(alter_2pt_conical_compensate_focal) M(alter_2pt_conical_unswap
) M(mask_2pt_conical_nan) M(mask_2pt_conical_degenerates) M(apply_vector_mask
) M(set_base_pointer) M(init_lane_masks) M(store_device_xy01)
M(exchange_src) M(load_condition_mask) M(store_condition_mask
) M(merge_condition_mask) M(merge_inv_condition_mask) M(load_loop_mask
) M(store_loop_mask) M(mask_off_loop_mask) M(reenable_loop_mask
) M(merge_loop_mask) M(case_op) M(continue_op) M(load_return_mask
) M(store_return_mask) M(mask_off_return_mask) M(branch_if_all_lanes_active
) M(branch_if_any_lanes_active) M(branch_if_no_lanes_active) M
(branch_if_no_active_lanes_eq) M(jump) M(bitwise_and_imm_4_ints
) M(bitwise_and_imm_3_ints) M(bitwise_and_imm_2_ints) M(bitwise_and_imm_int
) M(bitwise_and_n_ints) M(bitwise_and_int) M(bitwise_and_2_ints
) M(bitwise_and_3_ints) M(bitwise_and_4_ints) M(bitwise_or_n_ints
) M(bitwise_or_int) M(bitwise_or_2_ints) M(bitwise_or_3_ints)
M(bitwise_or_4_ints) M(bitwise_xor_imm_int) M(bitwise_xor_n_ints
) M(bitwise_xor_int) M(bitwise_xor_2_ints) M(bitwise_xor_3_ints
) M(bitwise_xor_4_ints) M(cast_to_float_from_int) M(cast_to_float_from_2_ints
) M(cast_to_float_from_3_ints) M(cast_to_float_from_4_ints) M
(cast_to_float_from_uint) M(cast_to_float_from_2_uints) M(cast_to_float_from_3_uints
) M(cast_to_float_from_4_uints) M(cast_to_int_from_float) M(cast_to_int_from_2_floats
) M(cast_to_int_from_3_floats) M(cast_to_int_from_4_floats) M
(cast_to_uint_from_float) M(cast_to_uint_from_2_floats) M(cast_to_uint_from_3_floats
) M(cast_to_uint_from_4_floats) M(abs_int) M(abs_2_ints) M(abs_3_ints
) M(abs_4_ints) M(floor_float) M(floor_2_floats) M(floor_3_floats
) M(floor_4_floats) M(ceil_float) M(ceil_2_floats) M(ceil_3_floats
) M(ceil_4_floats) M(invsqrt_float) M(invsqrt_2_floats) M(invsqrt_3_floats
) M(invsqrt_4_floats) M(inverse_mat2) M(inverse_mat3) M(inverse_mat4
) M(sin_float) M(cos_float) M(tan_float) M(asin_float) M(acos_float
) M(atan_float) M(atan2_n_floats) M(sqrt_float) M(pow_n_floats
) M(exp_float) M(exp2_float) M(log_float) M(log2_float) M(refract_4_floats
) M(copy_uniform) M(copy_2_uniforms) M(copy_3_uniforms) M(copy_4_uniforms
) M(copy_constant) M(splat_2_constants) M(splat_3_constants) M
(splat_4_constants) M(copy_slot_masked) M(copy_2_slots_masked
) M(copy_3_slots_masked) M(copy_4_slots_masked) M(copy_from_indirect_unmasked
) M(copy_from_indirect_uniform_unmasked) M(copy_to_indirect_masked
) M(swizzle_copy_to_indirect_masked) M(copy_slot_unmasked) M(
copy_2_slots_unmasked) M(copy_3_slots_unmasked) M(copy_4_slots_unmasked
) M(copy_immutable_unmasked) M(copy_2_immutables_unmasked) M(
copy_3_immutables_unmasked) M(copy_4_immutables_unmasked) M(swizzle_copy_slot_masked
) M(swizzle_copy_2_slots_masked) M(swizzle_copy_3_slots_masked
) M(swizzle_copy_4_slots_masked) M(swizzle_1) M(swizzle_2) M(
swizzle_3) M(swizzle_4) M(shuffle) M(matrix_multiply_2) M(matrix_multiply_3
) M(matrix_multiply_4) M(smoothstep_n_floats) M(dot_2_floats)
M(dot_3_floats) M(dot_4_floats) M(add_imm_float) M(add_n_floats
) M(add_float) M(add_2_floats) M(add_3_floats) M(add_4_floats
) M(add_imm_int) M(add_n_ints) M(add_int) M(add_2_ints) M(add_3_ints
) M(add_4_ints) M(sub_n_floats) M(sub_float) M(sub_2_floats) M
(sub_3_floats) M(sub_4_floats) M(sub_n_ints) M(sub_int) M(sub_2_ints
) M(sub_3_ints) M(sub_4_ints) M(mul_imm_float) M(mul_n_floats
) M(mul_float) M(mul_2_floats) M(mul_3_floats) M(mul_4_floats
) M(mul_imm_int) M(mul_n_ints) M(mul_int) M(mul_2_ints) M(mul_3_ints
) M(mul_4_ints) M(div_n_floats) M(div_float) M(div_2_floats) M
(div_3_floats) M(div_4_floats) M(div_n_ints) M(div_int) M(div_2_ints
) M(div_3_ints) M(div_4_ints) M(div_n_uints) M(div_uint) M(div_2_uints
) M(div_3_uints) M(div_4_uints) M(max_imm_float) M(max_n_floats
) M(max_float) M(max_2_floats) M(max_3_floats) M(max_4_floats
) M(max_n_ints) M(max_int) M(max_2_ints) M(max_3_ints) M(max_4_ints
) M(max_n_uints) M(max_uint) M(max_2_uints) M(max_3_uints) M(
max_4_uints) M(min_imm_float) M(min_n_floats) M(min_float) M(
min_2_floats) M(min_3_floats) M(min_4_floats) M(min_n_ints) M
(min_int) M(min_2_ints) M(min_3_ints) M(min_4_ints) M(min_n_uints
) M(min_uint) M(min_2_uints) M(min_3_uints) M(min_4_uints) M(
mod_n_floats) M(mod_float) M(mod_2_floats) M(mod_3_floats) M(
mod_4_floats) M(mix_n_floats) M(mix_float) M(mix_2_floats) M(
mix_3_floats) M(mix_4_floats) M(mix_n_ints) M(mix_int) M(mix_2_ints
) M(mix_3_ints) M(mix_4_ints) M(cmplt_imm_float) M(cmplt_n_floats
) M(cmplt_float) M(cmplt_2_floats) M(cmplt_3_floats) M(cmplt_4_floats
) M(cmplt_imm_int) M(cmplt_n_ints) M(cmplt_int) M(cmplt_2_ints
) M(cmplt_3_ints) M(cmplt_4_ints) M(cmplt_imm_uint) M(cmplt_n_uints
) M(cmplt_uint) M(cmplt_2_uints) M(cmplt_3_uints) M(cmplt_4_uints
) M(cmple_imm_float) M(cmple_n_floats) M(cmple_float) M(cmple_2_floats
) M(cmple_3_floats) M(cmple_4_floats) M(cmple_imm_int) M(cmple_n_ints
) M(cmple_int) M(cmple_2_ints) M(cmple_3_ints) M(cmple_4_ints
) M(cmple_imm_uint) M(cmple_n_uints) M(cmple_uint) M(cmple_2_uints
) M(cmple_3_uints) M(cmple_4_uints) M(cmpeq_imm_float) M(cmpeq_n_floats
) M(cmpeq_float) M(cmpeq_2_floats) M(cmpeq_3_floats) M(cmpeq_4_floats
) M(cmpeq_imm_int) M(cmpeq_n_ints) M(cmpeq_int) M(cmpeq_2_ints
) M(cmpeq_3_ints) M(cmpeq_4_ints) M(cmpne_imm_float) M(cmpne_n_floats
) M(cmpne_float) M(cmpne_2_floats) M(cmpne_3_floats) M(cmpne_4_floats
) M(cmpne_imm_int) M(cmpne_n_ints) M(cmpne_int) M(cmpne_2_ints
) M(cmpne_3_ints) M(cmpne_4_ints) M(trace_line) M(trace_var) M
(trace_enter) M(trace_exit) M(trace_scope)
241 #undef M
242 }
243 return name;
244}
245
246void SkRasterPipeline::dump() const {
247 SkDebugf("SkRasterPipeline, %d stages\n", fNumStages);
248 std::vector<const char*> stages;
249 for (auto st = fStages; st; st = st->prev) {
250 stages.push_back(GetOpName(st->stage));
251 }
252 std::reverse(stages.begin(), stages.end());
253 for (const char* name : stages) {
254 SkDebugf("\t%s\n", name);
255 }
256 SkDebugf("\n");
257}
258
259void SkRasterPipeline::appendSetRGB(SkArenaAlloc* alloc, const float rgb[3]) {
260 auto arg = alloc->makeArrayDefault<float>(3);
261 arg[0] = rgb[0];
262 arg[1] = rgb[1];
263 arg[2] = rgb[2];
264
265 auto op = Op::unbounded_set_rgb;
266 if (0 <= rgb[0] && rgb[0] <= 1 &&
267 0 <= rgb[1] && rgb[1] <= 1 &&
268 0 <= rgb[2] && rgb[2] <= 1)
269 {
270 op = Op::set_rgb;
271 }
272
273 this->uncheckedAppend(op, arg);
274}
275
276void SkRasterPipeline::appendConstantColor(SkArenaAlloc* alloc, const float rgba[4]) {
277 // r,g,b might be outside [0,1], but alpha should probably always be in [0,1].
278 SkASSERT(0 <= rgba[3] && rgba[3] <= 1)static_cast<void>( __builtin_expect(static_cast<bool
>(0 <= rgba[3] && rgba[3] <= 1), 1) ? static_cast
<void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf
("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "./../../../gfx/skia/skia/src/core/SkRasterPipeline.cpp"
, 278, "0 <= rgba[3] && rgba[3] <= 1"); ; sk_abort_no_print
(); } while (false); } } while(false); }() )
;
279
280 if (rgba[0] == 0 && rgba[1] == 0 && rgba[2] == 0 && rgba[3] == 1) {
281 this->append(Op::black_color);
282 } else if (rgba[0] == 1 && rgba[1] == 1 && rgba[2] == 1 && rgba[3] == 1) {
283 this->append(Op::white_color);
284 } else {
285 auto ctx = alloc->make<SkRasterPipelineContexts::UniformColorCtx>();
286 skvx::float4 color = skvx::float4::Load(rgba);
287 color.store(&ctx->r);
288
289 // uniform_color requires colors in range and can go lowp,
290 // while unbounded_uniform_color supports out-of-range colors too but not lowp.
291 if (0 <= rgba[0] && rgba[0] <= rgba[3] &&
292 0 <= rgba[1] && rgba[1] <= rgba[3] &&
293 0 <= rgba[2] && rgba[2] <= rgba[3]) {
294 // To make loads more direct, we store 8-bit values in 16-bit slots.
295 color = color * 255.0f + 0.5f;
296 ctx->rgba[0] = (uint16_t)color[0];
297 ctx->rgba[1] = (uint16_t)color[1];
298 ctx->rgba[2] = (uint16_t)color[2];
299 ctx->rgba[3] = (uint16_t)color[3];
300 this->uncheckedAppend(Op::uniform_color, ctx);
301 } else {
302 this->uncheckedAppend(Op::unbounded_uniform_color, ctx);
303 }
304 }
305}
306
307void SkRasterPipeline::appendMatrix(SkArenaAlloc* alloc, const SkMatrix& matrix) {
308 SkMatrix::TypeMask mt = matrix.getType();
309
310 if (mt == SkMatrix::kIdentity_Mask) {
311 return;
312 }
313 if (mt == SkMatrix::kTranslate_Mask) {
314 float* trans = alloc->makeArrayDefault<float>(2);
315 trans[0] = matrix.getTranslateX();
316 trans[1] = matrix.getTranslateY();
317 this->append(Op::matrix_translate, trans);
318 } else if ((mt | (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask)) ==
319 (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask)) {
320 float* scaleTrans = alloc->makeArrayDefault<float>(4);
321 scaleTrans[0] = matrix.getScaleX();
322 scaleTrans[1] = matrix.getScaleY();
323 scaleTrans[2] = matrix.getTranslateX();
324 scaleTrans[3] = matrix.getTranslateY();
325 this->append(Op::matrix_scale_translate, scaleTrans);
326 } else {
327 float* storage = alloc->makeArrayDefault<float>(9);
328 matrix.get9(storage);
329 if (!matrix.hasPerspective()) {
330 // note: asAffine and the 2x3 stage really only need 6 entries
331 this->append(Op::matrix_2x3, storage);
332 } else {
333 this->append(Op::matrix_perspective, storage);
334 }
335 }
336}
337
338void SkRasterPipeline::appendLoad(SkColorType ct, const SkRasterPipelineContexts::MemoryCtx* ctx) {
339 switch (ct) {
340 case kUnknown_SkColorType: SkASSERT(false)static_cast<void>( __builtin_expect(static_cast<bool
>(false), 1) ? static_cast<void>(0) : []{ do { if (sk_abort_is_enabled
()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n"
, "./../../../gfx/skia/skia/src/core/SkRasterPipeline.cpp", 340
, "false"); ; sk_abort_no_print(); } while (false); } } while
(false); }() )
; break;
341
342 case kAlpha_8_SkColorType: this->append(Op::load_a8, ctx); break;
343 case kA16_unorm_SkColorType: this->append(Op::load_a16, ctx); break;
344 case kA16_float_SkColorType: this->append(Op::load_af16, ctx); break;
345 case kRGB_565_SkColorType: this->append(Op::load_565, ctx); break;
346 case kARGB_4444_SkColorType: this->append(Op::load_4444, ctx); break;
347 case kR8G8_unorm_SkColorType: this->append(Op::load_rg88, ctx); break;
348 case kR16_unorm_SkColorType: this->append(Op::load_r16, ctx); break;
349 case kR16_float_SkColorType: this->append(Op::load_rf16, ctx); break;
350 case kR16G16_unorm_SkColorType: this->append(Op::load_rg1616, ctx); break;
351 case kR16G16_float_SkColorType: this->append(Op::load_rgf16, ctx); break;
352 case kRGBA_8888_SkColorType: this->append(Op::load_8888, ctx); break;
353 case kRGBA_1010102_SkColorType: this->append(Op::load_1010102, ctx); break;
354 case kR16G16B16A16_unorm_SkColorType:this->append(Op::load_16161616,ctx); break;
355 case kRGBA_F16Norm_SkColorType:
356 case kRGBA_F16_SkColorType: this->append(Op::load_f16, ctx); break;
357 case kRGBA_F32_SkColorType: this->append(Op::load_f32, ctx); break;
358 case kRGBA_10x6_SkColorType: this->append(Op::load_10x6, ctx); break;
359
360 case kGray_8_SkColorType: this->append(Op::load_a8, ctx);
361 this->append(Op::alpha_to_gray);
362 break;
363
364 case kR8_unorm_SkColorType: this->append(Op::load_a8, ctx);
365 this->append(Op::alpha_to_red);
366 break;
367
368 case kRGB_888x_SkColorType: this->append(Op::load_8888, ctx);
369 this->append(Op::force_opaque);
370 break;
371
372 case kBGRA_1010102_SkColorType: this->append(Op::load_1010102, ctx);
373 this->append(Op::swap_rb);
374 break;
375
376 case kRGB_101010x_SkColorType: this->append(Op::load_1010102, ctx);
377 this->append(Op::force_opaque);
378 break;
379
380 case kBGR_101010x_SkColorType: this->append(Op::load_1010102, ctx);
381 this->append(Op::force_opaque);
382 this->append(Op::swap_rb);
383 break;
384
385 case kBGRA_10101010_XR_SkColorType: this->append(Op::load_10101010_xr, ctx);
386 this->append(Op::swap_rb);
387 break;
388
389 case kBGR_101010x_XR_SkColorType: this->append(Op::load_1010102_xr, ctx);
390 this->append(Op::force_opaque);
391 this->append(Op::swap_rb);
392 break;
393 case kRGB_F16F16F16x_SkColorType: this->append(Op::load_f16, ctx);
394 this->append(Op::force_opaque);
395 break;
396
397 case kBGRA_8888_SkColorType: this->append(Op::load_8888, ctx);
398 this->append(Op::swap_rb);
399 break;
400
401 case kSRGBA_8888_SkColorType:
402 this->append(Op::load_8888, ctx);
403 this->appendTransferFunction(*skcms_sRGB_TransferFunction());
404 break;
405 }
406}
407
408void SkRasterPipeline::appendLoadDst(SkColorType ct,
409 const SkRasterPipelineContexts::MemoryCtx* ctx) {
410 switch (ct) {
411 case kUnknown_SkColorType: SkASSERT(false)static_cast<void>( __builtin_expect(static_cast<bool
>(false), 1) ? static_cast<void>(0) : []{ do { if (sk_abort_is_enabled
()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n"
, "./../../../gfx/skia/skia/src/core/SkRasterPipeline.cpp", 411
, "false"); ; sk_abort_no_print(); } while (false); } } while
(false); }() )
; break;
412
413 case kAlpha_8_SkColorType: this->append(Op::load_a8_dst, ctx); break;
414 case kA16_unorm_SkColorType: this->append(Op::load_a16_dst, ctx); break;
415 case kA16_float_SkColorType: this->append(Op::load_af16_dst, ctx); break;
416 case kRGB_565_SkColorType: this->append(Op::load_565_dst, ctx); break;
417 case kARGB_4444_SkColorType: this->append(Op::load_4444_dst, ctx); break;
418 case kR8G8_unorm_SkColorType: this->append(Op::load_rg88_dst, ctx); break;
419 case kR16_unorm_SkColorType: this->append(Op::load_r16_dst, ctx); break;
420 case kR16_float_SkColorType: this->append(Op::load_rf16_dst, ctx); break;
421 case kR16G16_unorm_SkColorType: this->append(Op::load_rg1616_dst, ctx); break;
422 case kR16G16_float_SkColorType: this->append(Op::load_rgf16_dst, ctx); break;
423 case kRGBA_8888_SkColorType: this->append(Op::load_8888_dst, ctx); break;
424 case kRGBA_1010102_SkColorType: this->append(Op::load_1010102_dst, ctx); break;
425 case kR16G16B16A16_unorm_SkColorType: this->append(Op::load_16161616_dst,ctx); break;
426 case kRGBA_F16Norm_SkColorType:
427 case kRGBA_F16_SkColorType: this->append(Op::load_f16_dst, ctx); break;
428 case kRGBA_F32_SkColorType: this->append(Op::load_f32_dst, ctx); break;
429 case kRGBA_10x6_SkColorType: this->append(Op::load_10x6_dst, ctx); break;
430
431 case kGray_8_SkColorType: this->append(Op::load_a8_dst, ctx);
432 this->append(Op::alpha_to_gray_dst);
433 break;
434
435 case kR8_unorm_SkColorType: this->append(Op::load_a8_dst, ctx);
436 this->append(Op::alpha_to_red_dst);
437 break;
438
439 case kRGB_888x_SkColorType: this->append(Op::load_8888_dst, ctx);
440 this->append(Op::force_opaque_dst);
441 break;
442
443 case kBGRA_1010102_SkColorType: this->append(Op::load_1010102_dst, ctx);
444 this->append(Op::swap_rb_dst);
445 break;
446
447 case kRGB_101010x_SkColorType: this->append(Op::load_1010102_dst, ctx);
448 this->append(Op::force_opaque_dst);
449 break;
450
451 case kBGR_101010x_SkColorType: this->append(Op::load_1010102_dst, ctx);
452 this->append(Op::force_opaque_dst);
453 this->append(Op::swap_rb_dst);
454 break;
455
456 case kBGR_101010x_XR_SkColorType: this->append(Op::load_1010102_xr_dst, ctx);
457 this->append(Op::force_opaque_dst);
458 this->append(Op::swap_rb_dst);
459 break;
460
461 case kBGRA_10101010_XR_SkColorType: this->append(Op::load_10101010_xr_dst, ctx);
462 this->append(Op::swap_rb_dst);
463 break;
464 case kRGB_F16F16F16x_SkColorType: this->append(Op::load_f16_dst, ctx);
465 this->append(Op::force_opaque_dst);
466 break;
467
468 case kBGRA_8888_SkColorType: this->append(Op::load_8888_dst, ctx);
469 this->append(Op::swap_rb_dst);
470 break;
471
472 case kSRGBA_8888_SkColorType:
473 // TODO: We could remove the double-swap if we had _dst versions of all the TF stages
474 this->append(Op::load_8888_dst, ctx);
475 this->append(Op::swap_src_dst);
476 this->appendTransferFunction(*skcms_sRGB_TransferFunction());
477 this->append(Op::swap_src_dst);
478 break;
479 }
480}
481
482void SkRasterPipeline::appendStore(SkColorType ct, const SkRasterPipelineContexts::MemoryCtx* ctx) {
483 switch (ct) {
484 case kUnknown_SkColorType: SkASSERT(false)static_cast<void>( __builtin_expect(static_cast<bool
>(false), 1) ? static_cast<void>(0) : []{ do { if (sk_abort_is_enabled
()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n"
, "./../../../gfx/skia/skia/src/core/SkRasterPipeline.cpp", 484
, "false"); ; sk_abort_no_print(); } while (false); } } while
(false); }() )
; break;
485
486 case kAlpha_8_SkColorType: this->append(Op::store_a8, ctx); break;
487 case kR8_unorm_SkColorType: this->append(Op::store_r8, ctx); break;
488 case kA16_unorm_SkColorType: this->append(Op::store_a16, ctx); break;
489 case kA16_float_SkColorType: this->append(Op::store_af16, ctx); break;
490 case kRGB_565_SkColorType: this->append(Op::store_565, ctx); break;
491 case kARGB_4444_SkColorType: this->append(Op::store_4444, ctx); break;
492 case kR8G8_unorm_SkColorType: this->append(Op::store_rg88, ctx); break;
493 case kR16_unorm_SkColorType: this->append(Op::store_r16, ctx); break;
494 case kR16_float_SkColorType: this->append(Op::store_rf16, ctx); break;
495 case kR16G16_unorm_SkColorType: this->append(Op::store_rg1616, ctx); break;
496 case kR16G16_float_SkColorType: this->append(Op::store_rgf16, ctx); break;
497 case kRGBA_8888_SkColorType: this->append(Op::store_8888, ctx); break;
498 case kRGBA_1010102_SkColorType: this->append(Op::store_1010102, ctx); break;
499 case kR16G16B16A16_unorm_SkColorType: this->append(Op::store_16161616,ctx); break;
500 case kRGBA_F16Norm_SkColorType:
501 case kRGBA_F16_SkColorType: this->append(Op::store_f16, ctx); break;
502 case kRGBA_F32_SkColorType: this->append(Op::store_f32, ctx); break;
503 case kRGBA_10x6_SkColorType: this->append(Op::store_10x6, ctx); break;
504
505 case kRGB_888x_SkColorType: this->append(Op::force_opaque);
506 this->append(Op::store_8888, ctx);
507 break;
508
509 case kBGRA_1010102_SkColorType: this->append(Op::swap_rb);
510 this->append(Op::store_1010102, ctx);
511 break;
512
513 case kRGB_101010x_SkColorType: this->append(Op::force_opaque);
514 this->append(Op::store_1010102, ctx);
515 break;
516
517 case kBGR_101010x_SkColorType: this->append(Op::force_opaque);
518 this->append(Op::swap_rb);
519 this->append(Op::store_1010102, ctx);
520 break;
521
522 case kBGR_101010x_XR_SkColorType: this->append(Op::force_opaque);
523 this->append(Op::swap_rb);
524 this->append(Op::store_1010102_xr, ctx);
525 break;
526 case kRGB_F16F16F16x_SkColorType: this->append(Op::force_opaque);
527 this->append(Op::store_f16, ctx);
528 break;
529
530 case kBGRA_10101010_XR_SkColorType: this->append(Op::swap_rb);
531 this->append(Op::store_10101010_xr, ctx);
532 break;
533
534 case kGray_8_SkColorType: this->append(Op::bt709_luminance_or_luma_to_alpha);
535 this->append(Op::store_a8, ctx);
536 break;
537
538 case kBGRA_8888_SkColorType: this->append(Op::swap_rb);
539 this->append(Op::store_8888, ctx);
540 break;
541
542 case kSRGBA_8888_SkColorType:
543 this->appendTransferFunction(*skcms_sRGB_Inverse_TransferFunction());
544 this->append(Op::store_8888, ctx);
545 break;
546 }
547}
548
549void SkRasterPipeline::appendTransferFunction(const skcms_TransferFunction& tf) {
550 void* ctx = const_cast<void*>(static_cast<const void*>(&tf));
551 switch (skcms_TransferFunction_getType(&tf)) {
552 default: SkASSERT(false)static_cast<void>( __builtin_expect(static_cast<bool
>(false), 1) ? static_cast<void>(0) : []{ do { if (sk_abort_is_enabled
()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n"
, "./../../../gfx/skia/skia/src/core/SkRasterPipeline.cpp", 552
, "false"); ; sk_abort_no_print(); } while (false); } } while
(false); }() )
; break;
553
554 case skcms_TFType_sRGBish:
555 if (tf.a == 1 && tf.b == 0 && tf.c == 0 && tf.d == 0 && tf.e == 0 && tf.f == 0) {
556 this->uncheckedAppend(Op::gamma_, ctx);
557 } else {
558 this->uncheckedAppend(Op::parametric, ctx);
559 }
560 break;
561 case skcms_TFType_PQish: this->uncheckedAppend(Op::PQish, ctx); break;
562 case skcms_TFType_HLGish: this->uncheckedAppend(Op::HLGish, ctx); break;
563 case skcms_TFType_HLGinvish: this->uncheckedAppend(Op::HLGinvish, ctx); break;
564 }
565}
566
567// GPUs clamp all color channels to the limits of the format just before the blend step. To match
568// that auto-clamp, the RP blitter uses this helper immediately before appending blending stages.
569void SkRasterPipeline::appendClampIfNormalized(const SkImageInfo& info) {
570 if (SkColorTypeIsNormalized(info.colorType())) {
571 this->uncheckedAppend(Op::clamp_01, nullptr);
572 }
573}
574
575void SkRasterPipeline::appendStackRewind() {
576 if (!fRewindCtx) {
577 fRewindCtx = fAlloc->make<SkRasterPipelineContexts::RewindCtx>();
578 }
579 this->uncheckedAppend(Op::stack_rewind, fRewindCtx);
580}
581
582static void prepend_to_pipeline(SkRasterPipelineStage*& ip, SkOpts::StageFn stageFn, void* ctx) {
583 --ip;
584 ip->fn = stageFn;
585 ip->ctx = ctx;
586}
587
588bool SkRasterPipeline::buildLowpPipeline(SkRasterPipelineStage* ip) const {
589 if (gForceHighPrecisionRasterPipeline || fRewindCtx) {
590 return false;
591 }
592 // Stages are stored backwards in fStages; to compensate, we assemble the pipeline in reverse
593 // here, back to front.
594 prepend_to_pipeline(ip, SkOpts::just_return_lowp, /*ctx=*/nullptr);
595 for (const StageList* st = fStages; st; st = st->prev) {
596 int opIndex = (int)st->stage;
597 if (opIndex >= kNumRasterPipelineLowpOps || !SkOpts::ops_lowp[opIndex]) {
598 // This program contains a stage that doesn't exist in lowp.
599 return false;
600 }
601 prepend_to_pipeline(ip, SkOpts::ops_lowp[opIndex], st->ctx);
602 }
603 return true;
604}
605
606void SkRasterPipeline::buildHighpPipeline(SkRasterPipelineStage* ip) const {
607 // We assemble the pipeline in reverse, since the stage list is stored backwards.
608 prepend_to_pipeline(ip, SkOpts::just_return_highp, /*ctx=*/nullptr);
609 for (const StageList* st = fStages; st; st = st->prev) {
610 int opIndex = (int)st->stage;
611 prepend_to_pipeline(ip, SkOpts::ops_highp[opIndex], st->ctx);
612 }
613
614 // stack_checkpoint and stack_rewind are only implemented in highp. We only need these stages
615 // when generating long (or looping) pipelines from SkSL. The other stages used by the SkSL
616 // Raster Pipeline generator will only have highp implementations, because we can't execute SkSL
617 // code without floating point.
618 if (fRewindCtx) {
619 const int rewindIndex = (int)Op::stack_checkpoint;
620 prepend_to_pipeline(ip, SkOpts::ops_highp[rewindIndex], fRewindCtx);
621 }
622}
623
624SkRasterPipeline::StartPipelineFn SkRasterPipeline::buildPipeline(SkRasterPipelineStage* ip) const {
625 // We try to build a lowp pipeline first; if that fails, we fall back to a highp float pipeline.
626 if (this->buildLowpPipeline(ip)) {
627 return SkOpts::start_pipeline_lowp;
628 }
629
630 this->buildHighpPipeline(ip);
631 return SkOpts::start_pipeline_highp;
632}
633
634int SkRasterPipeline::stagesNeeded() const {
635 // Add 1 to budget for a `just_return` stage at the end.
636 int stages = fNumStages + 1;
637
638 // If we have any stack_rewind stages, we will need to inject a stack_checkpoint stage.
639 if (fRewindCtx) {
640 stages += 1;
641 }
642 return stages;
643}
644
645void SkRasterPipeline::run(size_t x, size_t y, size_t w, size_t h) const {
646 if (this->empty()) {
647 return;
648 }
649
650 int stagesNeeded = this->stagesNeeded();
651
652 // Best to not use fAlloc here... we can't bound how often run() will be called.
653 AutoSTMalloc<32, SkRasterPipelineStage> program(stagesNeeded);
654
655 size_t numMemoryCtxs = fMemoryCtxInfos.size();
656 AutoSTMalloc<2, SkRasterPipelineContexts::MemoryCtxPatch> patches(numMemoryCtxs);
657 for (size_t i = 0; i < numMemoryCtxs; ++i) {
658 patches[i].info = fMemoryCtxInfos[i];
659 patches[i].backup = nullptr;
660 memset(patches[i].scratch, 0, sizeof(patches[i].scratch));
661 }
662
663 auto start_pipeline = this->buildPipeline(program.get() + stagesNeeded);
664 start_pipeline(x, y, x + w, y + h, program.get(),
665 SkSpan{patches.data(), numMemoryCtxs},
666 fTailPointer);
667}
668
669std::function<void(size_t, size_t, size_t, size_t)> SkRasterPipeline::compile() const {
670 if (this->empty()) {
671 return [](size_t, size_t, size_t, size_t) {};
672 }
673
674 int stagesNeeded = this->stagesNeeded();
675
676 SkRasterPipelineStage* program = fAlloc->makeArray<SkRasterPipelineStage>(stagesNeeded);
677
678 size_t numMemoryCtxs = fMemoryCtxInfos.size();
679 SkRasterPipelineContexts::MemoryCtxPatch* patches =
680 fAlloc->makeArray<SkRasterPipelineContexts::MemoryCtxPatch>(numMemoryCtxs);
681 for (size_t i = 0; i < numMemoryCtxs; ++i) {
682 patches[i].info = fMemoryCtxInfos[i];
683 patches[i].backup = nullptr;
684 memset(patches[i].scratch, 0, sizeof(patches[i].scratch));
685 }
686 uint8_t* tailPointer = fTailPointer;
687
688 auto start_pipeline = this->buildPipeline(program + stagesNeeded);
689 return [=](size_t x, size_t y, size_t w, size_t h) {
690 start_pipeline(x, y, x + w, y + h, program,
691 {patches, numMemoryCtxs},
692 tailPointer);
693 };
694}
695
696void SkRasterPipeline::addMemoryContext(SkRasterPipelineContexts::MemoryCtx* ctx,
697 int bytesPerPixel,
698 bool load,
699 bool store) {
700 SkRasterPipelineContexts::MemoryCtxInfo* info = std::find_if(
701 fMemoryCtxInfos.begin(),
702 fMemoryCtxInfos.end(),
703 [=](const SkRasterPipelineContexts::MemoryCtxInfo& i) { return i.context == ctx; });
704 if (info != fMemoryCtxInfos.end()) {
705 SkASSERT(bytesPerPixel == info->bytesPerPixel)static_cast<void>( __builtin_expect(static_cast<bool
>(bytesPerPixel == info->bytesPerPixel), 1) ? static_cast
<void>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf
("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "./../../../gfx/skia/skia/src/core/SkRasterPipeline.cpp"
, 705, "bytesPerPixel == info->bytesPerPixel"); ; sk_abort_no_print
(); } while (false); } } while(false); }() )
;
706 info->load = info->load || load;
707 info->store = info->store || store;
708 } else {
709 fMemoryCtxInfos.push_back(
710 SkRasterPipelineContexts::MemoryCtxInfo{ctx, bytesPerPixel, load, store});
711 }
712}