Flutter Engine
The Flutter Engine
SkRasterPipeline.cpp
Go to the documentation of this file.
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
9
15#include "modules/skcms/skcms.h"
16#include "src/base/SkVx.h"
18#include "src/core/SkOpts.h"
21
22#include <algorithm>
23#include <cstring>
24#include <vector>
25
26using namespace skia_private;
28
30
32 this->reset();
33}
34
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
45 SkASSERT(op != Op::uniform_color); // Please use appendConstantColor().
46 SkASSERT(op != Op::unbounded_uniform_color); // Please use appendConstantColor().
47 SkASSERT(op != Op::set_rgb); // Please use appendSetRGB().
48 SkASSERT(op != Op::unbounded_set_rgb); // Please use appendSetRGB().
49 SkASSERT(op != Op::parametric); // Please use appendTransferFunction().
50 SkASSERT(op != Op::gamma_); // Please use appendTransferFunction().
51 SkASSERT(op != Op::PQish); // Please use appendTransferFunction().
52 SkASSERT(op != Op::HLGish); // Please use appendTransferFunction().
53 SkASSERT(op != Op::HLGinvish); // Please use appendTransferFunction().
54 SkASSERT(op != Op::stack_checkpoint); // Please use appendStackRewind().
55 SkASSERT(op != Op::stack_rewind); // 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;
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) {
99
100#undef COLOR_TYPE_CASE
101
102 // Odd stage that doesn't have a load variant (appendLoad uses load_a8 + alpha_to_red)
103 case Op::store_r8: {
105 isStore = true;
106 break;
107 }
108 case Op::srcover_rgba_8888: {
110 isLoad = true;
111 isStore = true;
112 break;
113 }
114 case Op::scale_u8:
115 case Op::lerp_u8: {
117 isLoad = true;
118 break;
119 }
120 case Op::scale_565:
121 case Op::lerp_565: {
123 isLoad = true;
124 break;
125 }
126 case Op::emboss: {
127 // Special-case, this op uses a context that holds *two* MemoryCtxs
129 this->addMemoryContext(&embossCtx->add,
131 /*load=*/true, /*store=*/false);
132 this->addMemoryContext(&embossCtx->mul,
134 /*load=*/true, /*store=*/false);
135 break;
136 }
137 case Op::init_lane_masks: {
138 auto* initCtx = (SkRasterPipeline_InitLaneMasksCtx*)ctx;
139 initCtx->tail = this->tailPointer();
140 break;
141 }
142 case Op::branch_if_all_lanes_active: {
143 auto* branchCtx = (SkRasterPipeline_BranchIfAllLanesActiveCtx*)ctx;
144 branchCtx->tail = this->tailPointer();
145 break;
146 }
147 default:
148 break;
149 }
150
151 fStages = fAlloc->make<StageList>(StageList{fStages, op, ctx});
152 fNumStages += 1;
153
154 if (isLoad || isStore) {
156 this->addMemoryContext(
157 (SkRasterPipeline_MemoryCtx*)ctx, SkColorTypeBytesPerPixel(ct), isLoad, isStore);
158 }
159}
160
162 void* ptrCtx;
163 memcpy(&ptrCtx, &ctx, sizeof(ctx));
164 this->append(op, ptrCtx);
165}
166
168 if (src.empty()) {
169 return;
170 }
171 // Create a rewind context if `src` has one already, but we don't. If we _do_ already have one,
172 // we need to keep it, since we already have rewind ops that reference it. Either way, we need
173 // to rewrite all the rewind ops to point to _our_ rewind context; we only get that checkpoint.
174 if (src.fRewindCtx && !fRewindCtx) {
175 fRewindCtx = fAlloc->make<SkRasterPipeline_RewindCtx>();
176 }
177 auto stages = fAlloc->makeArrayDefault<StageList>(src.fNumStages);
178
179 int n = src.fNumStages;
180 const StageList* st = src.fStages;
181 while (n --> 1) {
182 stages[n] = *st;
183 stages[n].prev = &stages[n-1];
184
185 // We make sure that all ops use _our_ stack context and tail pointer.
186 switch (stages[n].stage) {
187 case Op::stack_rewind: {
188 stages[n].ctx = fRewindCtx;
189 break;
190 }
191 case Op::init_lane_masks: {
192 auto* ctx = (SkRasterPipeline_InitLaneMasksCtx*)stages[n].ctx;
193 ctx->tail = this->tailPointer();
194 break;
195 }
196 case Op::branch_if_all_lanes_active: {
197 auto* ctx = (SkRasterPipeline_BranchIfAllLanesActiveCtx*)stages[n].ctx;
198 ctx->tail = this->tailPointer();
199 break;
200 }
201 default:
202 break;
203 }
204
205 st = st->prev;
206 }
207 stages[0] = *st;
208 stages[0].prev = fStages;
209
210 fStages = &stages[src.fNumStages - 1];
211 fNumStages += src.fNumStages;
212 for (const SkRasterPipeline_MemoryCtxInfo& info : src.fMemoryCtxInfos) {
213 this->addMemoryContext(info.context, info.bytesPerPixel, info.load, info.store);
214 }
215}
216
218 const char* name = "";
219 switch (op) {
220 #define M(x) case Op::x: name = #x; break;
222 #undef M
223 }
224 return name;
225}
226
228 SkDebugf("SkRasterPipeline, %d stages\n", fNumStages);
229 std::vector<const char*> stages;
230 for (auto st = fStages; st; st = st->prev) {
231 stages.push_back(GetOpName(st->stage));
232 }
233 std::reverse(stages.begin(), stages.end());
234 for (const char* name : stages) {
235 SkDebugf("\t%s\n", name);
236 }
237 SkDebugf("\n");
238}
239
240void SkRasterPipeline::appendSetRGB(SkArenaAlloc* alloc, const float rgb[3]) {
241 auto arg = alloc->makeArrayDefault<float>(3);
242 arg[0] = rgb[0];
243 arg[1] = rgb[1];
244 arg[2] = rgb[2];
245
246 auto op = Op::unbounded_set_rgb;
247 if (0 <= rgb[0] && rgb[0] <= 1 &&
248 0 <= rgb[1] && rgb[1] <= 1 &&
249 0 <= rgb[2] && rgb[2] <= 1)
250 {
251 op = Op::set_rgb;
252 }
253
254 this->uncheckedAppend(op, arg);
255}
256
258 // r,g,b might be outside [0,1], but alpha should probably always be in [0,1].
259 SkASSERT(0 <= rgba[3] && rgba[3] <= 1);
260
261 if (rgba[0] == 0 && rgba[1] == 0 && rgba[2] == 0 && rgba[3] == 1) {
262 this->append(Op::black_color);
263 } else if (rgba[0] == 1 && rgba[1] == 1 && rgba[2] == 1 && rgba[3] == 1) {
264 this->append(Op::white_color);
265 } else {
266 auto ctx = alloc->make<SkRasterPipeline_UniformColorCtx>();
268 color.store(&ctx->r);
269
270 // uniform_color requires colors in range and can go lowp,
271 // while unbounded_uniform_color supports out-of-range colors too but not lowp.
272 if (0 <= rgba[0] && rgba[0] <= rgba[3] &&
273 0 <= rgba[1] && rgba[1] <= rgba[3] &&
274 0 <= rgba[2] && rgba[2] <= rgba[3]) {
275 // To make loads more direct, we store 8-bit values in 16-bit slots.
276 color = color * 255.0f + 0.5f;
277 ctx->rgba[0] = (uint16_t)color[0];
278 ctx->rgba[1] = (uint16_t)color[1];
279 ctx->rgba[2] = (uint16_t)color[2];
280 ctx->rgba[3] = (uint16_t)color[3];
281 this->uncheckedAppend(Op::uniform_color, ctx);
282 } else {
283 this->uncheckedAppend(Op::unbounded_uniform_color, ctx);
284 }
285 }
286}
287
289 SkMatrix::TypeMask mt = matrix.getType();
290
291 if (mt == SkMatrix::kIdentity_Mask) {
292 return;
293 }
294 if (mt == SkMatrix::kTranslate_Mask) {
295 float* trans = alloc->makeArrayDefault<float>(2);
296 trans[0] = matrix.getTranslateX();
297 trans[1] = matrix.getTranslateY();
298 this->append(Op::matrix_translate, trans);
299 } else if ((mt | (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask)) ==
301 float* scaleTrans = alloc->makeArrayDefault<float>(4);
302 scaleTrans[0] = matrix.getScaleX();
303 scaleTrans[1] = matrix.getScaleY();
304 scaleTrans[2] = matrix.getTranslateX();
305 scaleTrans[3] = matrix.getTranslateY();
306 this->append(Op::matrix_scale_translate, scaleTrans);
307 } else {
308 float* storage = alloc->makeArrayDefault<float>(9);
309 matrix.get9(storage);
310 if (!matrix.hasPerspective()) {
311 // note: asAffine and the 2x3 stage really only need 6 entries
312 this->append(Op::matrix_2x3, storage);
313 } else {
314 this->append(Op::matrix_perspective, storage);
315 }
316 }
317}
318
320 switch (ct) {
321 case kUnknown_SkColorType: SkASSERT(false); break;
322
323 case kAlpha_8_SkColorType: this->append(Op::load_a8, ctx); break;
324 case kA16_unorm_SkColorType: this->append(Op::load_a16, ctx); break;
325 case kA16_float_SkColorType: this->append(Op::load_af16, ctx); break;
326 case kRGB_565_SkColorType: this->append(Op::load_565, ctx); break;
327 case kARGB_4444_SkColorType: this->append(Op::load_4444, ctx); break;
328 case kR8G8_unorm_SkColorType: this->append(Op::load_rg88, ctx); break;
329 case kR16G16_unorm_SkColorType: this->append(Op::load_rg1616, ctx); break;
330 case kR16G16_float_SkColorType: this->append(Op::load_rgf16, ctx); break;
331 case kRGBA_8888_SkColorType: this->append(Op::load_8888, ctx); break;
332 case kRGBA_1010102_SkColorType: this->append(Op::load_1010102, ctx); break;
333 case kR16G16B16A16_unorm_SkColorType:this->append(Op::load_16161616,ctx); break;
335 case kRGBA_F16_SkColorType: this->append(Op::load_f16, ctx); break;
336 case kRGBA_F32_SkColorType: this->append(Op::load_f32, ctx); break;
337 case kRGBA_10x6_SkColorType: this->append(Op::load_10x6, ctx); break;
338
339 case kGray_8_SkColorType: this->append(Op::load_a8, ctx);
340 this->append(Op::alpha_to_gray);
341 break;
342
343 case kR8_unorm_SkColorType: this->append(Op::load_a8, ctx);
344 this->append(Op::alpha_to_red);
345 break;
346
347 case kRGB_888x_SkColorType: this->append(Op::load_8888, ctx);
348 this->append(Op::force_opaque);
349 break;
350
351 case kBGRA_1010102_SkColorType: this->append(Op::load_1010102, ctx);
352 this->append(Op::swap_rb);
353 break;
354
355 case kRGB_101010x_SkColorType: this->append(Op::load_1010102, ctx);
356 this->append(Op::force_opaque);
357 break;
358
359 case kBGR_101010x_SkColorType: this->append(Op::load_1010102, ctx);
360 this->append(Op::force_opaque);
361 this->append(Op::swap_rb);
362 break;
363
364 case kBGRA_10101010_XR_SkColorType: this->append(Op::load_10101010_xr, ctx);
365 this->append(Op::swap_rb);
366 break;
367
368 case kBGR_101010x_XR_SkColorType: this->append(Op::load_1010102_xr, ctx);
369 this->append(Op::force_opaque);
370 this->append(Op::swap_rb);
371 break;
372
373 case kBGRA_8888_SkColorType: this->append(Op::load_8888, ctx);
374 this->append(Op::swap_rb);
375 break;
376
378 this->append(Op::load_8888, ctx);
380 break;
381 }
382}
383
385 switch (ct) {
386 case kUnknown_SkColorType: SkASSERT(false); break;
387
388 case kAlpha_8_SkColorType: this->append(Op::load_a8_dst, ctx); break;
389 case kA16_unorm_SkColorType: this->append(Op::load_a16_dst, ctx); break;
390 case kA16_float_SkColorType: this->append(Op::load_af16_dst, ctx); break;
391 case kRGB_565_SkColorType: this->append(Op::load_565_dst, ctx); break;
392 case kARGB_4444_SkColorType: this->append(Op::load_4444_dst, ctx); break;
393 case kR8G8_unorm_SkColorType: this->append(Op::load_rg88_dst, ctx); break;
394 case kR16G16_unorm_SkColorType: this->append(Op::load_rg1616_dst, ctx); break;
395 case kR16G16_float_SkColorType: this->append(Op::load_rgf16_dst, ctx); break;
396 case kRGBA_8888_SkColorType: this->append(Op::load_8888_dst, ctx); break;
397 case kRGBA_1010102_SkColorType: this->append(Op::load_1010102_dst, ctx); break;
398 case kR16G16B16A16_unorm_SkColorType: this->append(Op::load_16161616_dst,ctx); break;
400 case kRGBA_F16_SkColorType: this->append(Op::load_f16_dst, ctx); break;
401 case kRGBA_F32_SkColorType: this->append(Op::load_f32_dst, ctx); break;
402 case kRGBA_10x6_SkColorType: this->append(Op::load_10x6_dst, ctx); break;
403
404 case kGray_8_SkColorType: this->append(Op::load_a8_dst, ctx);
405 this->append(Op::alpha_to_gray_dst);
406 break;
407
408 case kR8_unorm_SkColorType: this->append(Op::load_a8_dst, ctx);
409 this->append(Op::alpha_to_red_dst);
410 break;
411
412 case kRGB_888x_SkColorType: this->append(Op::load_8888_dst, ctx);
413 this->append(Op::force_opaque_dst);
414 break;
415
416 case kBGRA_1010102_SkColorType: this->append(Op::load_1010102_dst, ctx);
417 this->append(Op::swap_rb_dst);
418 break;
419
420 case kRGB_101010x_SkColorType: this->append(Op::load_1010102_dst, ctx);
421 this->append(Op::force_opaque_dst);
422 break;
423
424 case kBGR_101010x_SkColorType: this->append(Op::load_1010102_dst, ctx);
425 this->append(Op::force_opaque_dst);
426 this->append(Op::swap_rb_dst);
427 break;
428
429 case kBGR_101010x_XR_SkColorType: this->append(Op::load_1010102_xr_dst, ctx);
430 this->append(Op::force_opaque_dst);
431 this->append(Op::swap_rb_dst);
432 break;
433
434 case kBGRA_10101010_XR_SkColorType: this->append(Op::load_10101010_xr_dst, ctx);
435 this->append(Op::swap_rb_dst);
436 break;
437
438 case kBGRA_8888_SkColorType: this->append(Op::load_8888_dst, ctx);
439 this->append(Op::swap_rb_dst);
440 break;
441
443 // TODO: We could remove the double-swap if we had _dst versions of all the TF stages
444 this->append(Op::load_8888_dst, ctx);
445 this->append(Op::swap_src_dst);
447 this->append(Op::swap_src_dst);
448 break;
449 }
450}
451
453 switch (ct) {
454 case kUnknown_SkColorType: SkASSERT(false); break;
455
456 case kAlpha_8_SkColorType: this->append(Op::store_a8, ctx); break;
457 case kR8_unorm_SkColorType: this->append(Op::store_r8, ctx); break;
458 case kA16_unorm_SkColorType: this->append(Op::store_a16, ctx); break;
459 case kA16_float_SkColorType: this->append(Op::store_af16, ctx); break;
460 case kRGB_565_SkColorType: this->append(Op::store_565, ctx); break;
461 case kARGB_4444_SkColorType: this->append(Op::store_4444, ctx); break;
462 case kR8G8_unorm_SkColorType: this->append(Op::store_rg88, ctx); break;
463 case kR16G16_unorm_SkColorType: this->append(Op::store_rg1616, ctx); break;
464 case kR16G16_float_SkColorType: this->append(Op::store_rgf16, ctx); break;
465 case kRGBA_8888_SkColorType: this->append(Op::store_8888, ctx); break;
466 case kRGBA_1010102_SkColorType: this->append(Op::store_1010102, ctx); break;
467 case kR16G16B16A16_unorm_SkColorType: this->append(Op::store_16161616,ctx); break;
469 case kRGBA_F16_SkColorType: this->append(Op::store_f16, ctx); break;
470 case kRGBA_F32_SkColorType: this->append(Op::store_f32, ctx); break;
471 case kRGBA_10x6_SkColorType: this->append(Op::store_10x6, ctx); break;
472
473 case kRGB_888x_SkColorType: this->append(Op::force_opaque);
474 this->append(Op::store_8888, ctx);
475 break;
476
477 case kBGRA_1010102_SkColorType: this->append(Op::swap_rb);
478 this->append(Op::store_1010102, ctx);
479 break;
480
481 case kRGB_101010x_SkColorType: this->append(Op::force_opaque);
482 this->append(Op::store_1010102, ctx);
483 break;
484
485 case kBGR_101010x_SkColorType: this->append(Op::force_opaque);
486 this->append(Op::swap_rb);
487 this->append(Op::store_1010102, ctx);
488 break;
489
490 case kBGR_101010x_XR_SkColorType: this->append(Op::force_opaque);
491 this->append(Op::swap_rb);
492 this->append(Op::store_1010102_xr, ctx);
493 break;
494
495 case kBGRA_10101010_XR_SkColorType: this->append(Op::swap_rb);
496 this->append(Op::store_10101010_xr, ctx);
497 break;
498
499 case kGray_8_SkColorType: this->append(Op::bt709_luminance_or_luma_to_alpha);
500 this->append(Op::store_a8, ctx);
501 break;
502
503 case kBGRA_8888_SkColorType: this->append(Op::swap_rb);
504 this->append(Op::store_8888, ctx);
505 break;
506
509 this->append(Op::store_8888, ctx);
510 break;
511 }
512}
513
515 void* ctx = const_cast<void*>(static_cast<const void*>(&tf));
516 switch (skcms_TransferFunction_getType(&tf)) {
517 case skcms_TFType_Invalid: SkASSERT(false); break;
518
520 if (tf.a == 1 && tf.b == 0 && tf.c == 0 && tf.d == 0 && tf.e == 0 && tf.f == 0) {
521 this->uncheckedAppend(Op::gamma_, ctx);
522 } else {
523 this->uncheckedAppend(Op::parametric, ctx);
524 }
525 break;
526 case skcms_TFType_PQish: this->uncheckedAppend(Op::PQish, ctx); break;
527 case skcms_TFType_HLGish: this->uncheckedAppend(Op::HLGish, ctx); break;
528 case skcms_TFType_HLGinvish: this->uncheckedAppend(Op::HLGinvish, ctx); break;
529 }
530}
531
532// GPUs clamp all color channels to the limits of the format just before the blend step. To match
533// that auto-clamp, the RP blitter uses this helper immediately before appending blending stages.
535 if (SkColorTypeIsNormalized(info.colorType())) {
536 this->uncheckedAppend(Op::clamp_01, nullptr);
537 }
538}
539
541 if (!fRewindCtx) {
542 fRewindCtx = fAlloc->make<SkRasterPipeline_RewindCtx>();
543 }
544 this->uncheckedAppend(Op::stack_rewind, fRewindCtx);
545}
546
547static void prepend_to_pipeline(SkRasterPipelineStage*& ip, SkOpts::StageFn stageFn, void* ctx) {
548 --ip;
549 ip->fn = stageFn;
550 ip->ctx = ctx;
551}
552
553bool SkRasterPipeline::buildLowpPipeline(SkRasterPipelineStage* ip) const {
554 if (gForceHighPrecisionRasterPipeline || fRewindCtx) {
555 return false;
556 }
557 // Stages are stored backwards in fStages; to compensate, we assemble the pipeline in reverse
558 // here, back to front.
559 prepend_to_pipeline(ip, SkOpts::just_return_lowp, /*ctx=*/nullptr);
560 for (const StageList* st = fStages; st; st = st->prev) {
561 int opIndex = (int)st->stage;
562 if (opIndex >= kNumRasterPipelineLowpOps || !SkOpts::ops_lowp[opIndex]) {
563 // This program contains a stage that doesn't exist in lowp.
564 return false;
565 }
566 prepend_to_pipeline(ip, SkOpts::ops_lowp[opIndex], st->ctx);
567 }
568 return true;
569}
570
571void SkRasterPipeline::buildHighpPipeline(SkRasterPipelineStage* ip) const {
572 // We assemble the pipeline in reverse, since the stage list is stored backwards.
574 for (const StageList* st = fStages; st; st = st->prev) {
575 int opIndex = (int)st->stage;
576 prepend_to_pipeline(ip, SkOpts::ops_highp[opIndex], st->ctx);
577 }
578
579 // stack_checkpoint and stack_rewind are only implemented in highp. We only need these stages
580 // when generating long (or looping) pipelines from SkSL. The other stages used by the SkSL
581 // Raster Pipeline generator will only have highp implementations, because we can't execute SkSL
582 // code without floating point.
583 if (fRewindCtx) {
584 const int rewindIndex = (int)Op::stack_checkpoint;
585 prepend_to_pipeline(ip, SkOpts::ops_highp[rewindIndex], fRewindCtx);
586 }
587}
588
589SkRasterPipeline::StartPipelineFn SkRasterPipeline::buildPipeline(SkRasterPipelineStage* ip) const {
590 // We try to build a lowp pipeline first; if that fails, we fall back to a highp float pipeline.
591 if (this->buildLowpPipeline(ip)) {
593 }
594
595 this->buildHighpPipeline(ip);
597}
598
599int SkRasterPipeline::stagesNeeded() const {
600 // Add 1 to budget for a `just_return` stage at the end.
601 int stages = fNumStages + 1;
602
603 // If we have any stack_rewind stages, we will need to inject a stack_checkpoint stage.
604 if (fRewindCtx) {
605 stages += 1;
606 }
607 return stages;
608}
609
610void SkRasterPipeline::run(size_t x, size_t y, size_t w, size_t h) const {
611 if (this->empty()) {
612 return;
613 }
614
615 int stagesNeeded = this->stagesNeeded();
616
617 // Best to not use fAlloc here... we can't bound how often run() will be called.
618 AutoSTMalloc<32, SkRasterPipelineStage> program(stagesNeeded);
619
620 int numMemoryCtxs = fMemoryCtxInfos.size();
622 for (int i = 0; i < numMemoryCtxs; ++i) {
623 patches[i].info = fMemoryCtxInfos[i];
624 patches[i].backup = nullptr;
625 memset(patches[i].scratch, 0, sizeof(patches[i].scratch));
626 }
627
628 auto start_pipeline = this->buildPipeline(program.get() + stagesNeeded);
629 start_pipeline(x, y, x + w, y + h, program.get(),
630 SkSpan{patches.data(), numMemoryCtxs},
631 fTailPointer);
632}
633
634std::function<void(size_t, size_t, size_t, size_t)> SkRasterPipeline::compile() const {
635 if (this->empty()) {
636 return [](size_t, size_t, size_t, size_t) {};
637 }
638
639 int stagesNeeded = this->stagesNeeded();
640
641 SkRasterPipelineStage* program = fAlloc->makeArray<SkRasterPipelineStage>(stagesNeeded);
642
643 int numMemoryCtxs = fMemoryCtxInfos.size();
645 fAlloc->makeArray<SkRasterPipeline_MemoryCtxPatch>(numMemoryCtxs);
646 for (int i = 0; i < numMemoryCtxs; ++i) {
647 patches[i].info = fMemoryCtxInfos[i];
648 patches[i].backup = nullptr;
649 memset(patches[i].scratch, 0, sizeof(patches[i].scratch));
650 }
651 uint8_t* tailPointer = fTailPointer;
652
653 auto start_pipeline = this->buildPipeline(program + stagesNeeded);
654 return [=](size_t x, size_t y, size_t w, size_t h) {
655 start_pipeline(x, y, x + w, y + h, program,
656 SkSpan{patches, numMemoryCtxs},
657 tailPointer);
658 };
659}
660
661void SkRasterPipeline::addMemoryContext(SkRasterPipeline_MemoryCtx* ctx,
662 int bytesPerPixel,
663 bool load,
664 bool store) {
666 std::find_if(fMemoryCtxInfos.begin(), fMemoryCtxInfos.end(),
667 [=](const SkRasterPipeline_MemoryCtxInfo& i) { return i.context == ctx; });
668 if (info != fMemoryCtxInfos.end()) {
669 SkASSERT(bytesPerPixel == info->bytesPerPixel);
670 info->load = info->load || load;
671 info->store = info->store || store;
672 } else {
673 fMemoryCtxInfos.push_back(SkRasterPipeline_MemoryCtxInfo{ctx, bytesPerPixel, load, store});
674 }
675}
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
static const uint32_t rgba[kNumPixels]
static const uint64_t f16[kNumPixels]
#define SkASSERT(cond)
Definition: SkAssert.h:116
SkColorType
Definition: SkColorType.h:19
@ kR16G16B16A16_unorm_SkColorType
pixel with a little endian uint16_t for red, green, blue
Definition: SkColorType.h:50
@ kRGBA_10x6_SkColorType
pixel with 10 used bits (most significant) followed by 6 unused
Definition: SkColorType.h:33
@ kR8_unorm_SkColorType
Definition: SkColorType.h:54
@ kBGR_101010x_SkColorType
pixel with 10 bits each for blue, green, red; in 32-bit word
Definition: SkColorType.h:30
@ kARGB_4444_SkColorType
pixel with 4 bits for alpha, red, green, blue; in 16-bit word
Definition: SkColorType.h:23
@ kR8G8_unorm_SkColorType
pixel with a uint8_t for red and green
Definition: SkColorType.h:43
@ kBGRA_8888_SkColorType
pixel with 8 bits for blue, green, red, alpha; in 32-bit word
Definition: SkColorType.h:26
@ kA16_unorm_SkColorType
pixel with a little endian uint16_t for alpha
Definition: SkColorType.h:48
@ kRGBA_F16_SkColorType
pixel with half floats for red, green, blue, alpha;
Definition: SkColorType.h:38
@ kAlpha_8_SkColorType
pixel with alpha in 8-bit byte
Definition: SkColorType.h:21
@ kRGB_101010x_SkColorType
pixel with 10 bits each for red, green, blue; in 32-bit word
Definition: SkColorType.h:29
@ kSRGBA_8888_SkColorType
Definition: SkColorType.h:53
@ kGray_8_SkColorType
pixel with grayscale level in 8-bit byte
Definition: SkColorType.h:35
@ kRGB_565_SkColorType
pixel with 5 bits red, 6 bits green, 5 bits blue, in 16-bit word
Definition: SkColorType.h:22
@ kBGRA_10101010_XR_SkColorType
pixel with 10 bits each for blue, green, red, alpha; in 64-bit word, extended range
Definition: SkColorType.h:32
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
Definition: SkColorType.h:24
@ kRGB_888x_SkColorType
pixel with 8 bits each for red, green, blue; in 32-bit word
Definition: SkColorType.h:25
@ kBGRA_1010102_SkColorType
10 bits for blue, green, red; 2 bits for alpha; in 32-bit word
Definition: SkColorType.h:28
@ kA16_float_SkColorType
pixel with a half float for alpha
Definition: SkColorType.h:45
@ kRGBA_F32_SkColorType
pixel using C float for red, green, blue, alpha; in 128-bit word
Definition: SkColorType.h:40
@ kRGBA_1010102_SkColorType
10 bits for red, green, blue; 2 bits for alpha; in 32-bit word
Definition: SkColorType.h:27
@ kBGR_101010x_XR_SkColorType
pixel with 10 bits each for blue, green, red; in 32-bit word, extended range
Definition: SkColorType.h:31
@ kR16G16_unorm_SkColorType
pixel with a little endian uint16_t for red and green
Definition: SkColorType.h:49
@ kRGBA_F16Norm_SkColorType
pixel with half floats in [0,1] for red, green, blue, alpha;
Definition: SkColorType.h:36
@ kUnknown_SkColorType
uninitialized
Definition: SkColorType.h:20
@ kR16G16_float_SkColorType
pixel with a half float for red and green
Definition: SkColorType.h:46
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static bool SkColorTypeIsNormalized(SkColorType ct)
SK_API int SkColorTypeBytesPerPixel(SkColorType ct)
Definition: SkImageInfo.cpp:16
#define SK_RASTER_PIPELINE_OPS_ALL(M)
static constexpr int kNumRasterPipelineLowpOps
#define COLOR_TYPE_CASE(stage_ct, sk_ct)
bool gForceHighPrecisionRasterPipeline
static void prepend_to_pipeline(SkRasterPipelineStage *&ip, SkOpts::StageFn stageFn, void *ctx)
SkRasterPipelineOp Op
SI void store(P *ptr, const T &val)
SI T load(const P *ptr)
Definition: Transform_inl.h:98
T * makeArrayDefault(size_t count)
Definition: SkArenaAlloc.h:171
T * makeArray(size_t count)
Definition: SkArenaAlloc.h:181
auto make(Ctor &&ctor) -> decltype(ctor(nullptr))
Definition: SkArenaAlloc.h:120
@ kTranslate_Mask
translation SkMatrix
Definition: SkMatrix.h:193
@ kScale_Mask
scale SkMatrix
Definition: SkMatrix.h:194
@ kIdentity_Mask
identity SkMatrix; all bits clear
Definition: SkMatrix.h:192
bool empty() const
void appendClampIfNormalized(const SkImageInfo &)
void run(size_t x, size_t y, size_t w, size_t h) const
void appendTransferFunction(const skcms_TransferFunction &)
void appendLoad(SkColorType, const SkRasterPipeline_MemoryCtx *)
void appendStore(SkColorType, const SkRasterPipeline_MemoryCtx *)
SkRasterPipeline(SkArenaAlloc *)
void append(SkRasterPipelineOp, void *=nullptr)
void appendSetRGB(SkArenaAlloc *, const float rgb[3])
static const char * GetOpName(SkRasterPipelineOp op)
std::function< void(size_t, size_t, size_t, size_t)> compile() const
void extend(const SkRasterPipeline &)
void appendLoadDst(SkColorType, const SkRasterPipeline_MemoryCtx *)
void appendConstantColor(SkArenaAlloc *, const float rgba[4])
void appendMatrix(SkArenaAlloc *, const SkMatrix &)
int size() const
Definition: SkTArray.h:421
DlColor color
if(end==-1)
Dart_NativeFunction function
Definition: fuchsia.cc:51
double y
double x
static void start_pipeline(size_t dx, size_t dy, size_t xlimit, size_t ylimit, SkRasterPipelineStage *program, SkSpan< SkRasterPipeline_MemoryCtxPatch > memoryCtxPatches, uint8_t *tailPointer)
static void ABI stack_checkpoint(Params *params, SkRasterPipelineStage *program, F r, F g, F b, F a)
static void ABI stack_rewind(Params *params, SkRasterPipelineStage *program, F r, F g, F b, F a)
StageFn just_return_lowp
Definition: SkOpts.cpp:39
StageFn ops_highp[]
Definition: SkOpts.cpp:29
void(*)(void) StageFn
Definition: SkOpts.h:72
void(* start_pipeline_lowp)(size_t, size_t, size_t, size_t, SkRasterPipelineStage *, SkSpan< SkRasterPipeline_MemoryCtxPatch >, uint8_t *)
Definition: SkOpts.cpp:40
void(* start_pipeline_highp)(size_t, size_t, size_t, size_t, SkRasterPipelineStage *, SkSpan< SkRasterPipeline_MemoryCtxPatch >, uint8_t *)
Definition: SkOpts.cpp:31
StageFn just_return_highp
Definition: SkOpts.cpp:30
StageFn ops_lowp[]
Definition: SkOpts.cpp:38
unsigned useCenter Optional< SkMatrix > matrix
Definition: SkRecords.h:258
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
SkScalar w
SkScalar h
skcms_TFType skcms_TransferFunction_getType(const skcms_TransferFunction *tf)
Definition: skcms.cc:183
const skcms_TransferFunction * skcms_sRGB_Inverse_TransferFunction()
Definition: skcms.cc:1591
const skcms_TransferFunction * skcms_sRGB_TransferFunction()
Definition: skcms.cc:1587
@ skcms_TFType_Invalid
Definition: skcms_public.h:55
@ skcms_TFType_HLGish
Definition: skcms_public.h:58
@ skcms_TFType_sRGBish
Definition: skcms_public.h:56
@ skcms_TFType_HLGinvish
Definition: skcms_public.h:59
@ skcms_TFType_PQish
Definition: skcms_public.h:57
SkRasterPipeline_MemoryCtx add
SkRasterPipeline_MemoryCtx mul
SkRasterPipeline_MemoryCtxInfo info
Definition: SkVx.h:83
static SKVX_ALWAYS_INLINE Vec Load(const void *ptr)
Definition: SkVx.h:109