/* * Copyright 2017 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "SkJumper.h" #include "SkOpts.h" #include "SkRasterPipeline.h" #include "SkTemplates.h" SkRasterPipeline::StartPipelineFn SkRasterPipeline::build_pipeline(void** ip) const { #ifndef SK_JUMPER_DISABLE_8BIT // We'll try to build a lowp pipeline, but if that fails fallback to a highp float pipeline. void** reset_point = ip; // Stages are stored backwards in fStages, so we reverse here, back to front. *--ip = (void*)SkOpts::just_return_lowp; for (const StageList* st = fStages; st; st = st->prev) { if (st->stage == SkRasterPipeline::clamp_0 || st->stage == SkRasterPipeline::clamp_1) { continue; // No-ops in lowp. } SkOpts::StageFn fn; if (!st->rawFunction && (fn = SkOpts::stages_lowp[st->stage])) { if (st->ctx) { *--ip = st->ctx; } *--ip = (void*)fn; } else { ip = reset_point; break; } } if (ip != reset_point) { return SkOpts::start_pipeline_lowp; } #endif *--ip = (void*)SkOpts::just_return_highp; for (const StageList* st = fStages; st; st = st->prev) { if (st->ctx) { *--ip = st->ctx; } if (st->rawFunction) { *--ip = (void*)st->stage; } else { *--ip = (void*)SkOpts::stages_highp[st->stage]; } } return SkOpts::start_pipeline_highp; } void SkRasterPipeline::run(size_t x, size_t y, size_t w, size_t h) const { if (this->empty()) { return; } // Best to not use fAlloc here... we can't bound how often run() will be called. SkAutoSTMalloc<64, void*> program(fSlotsNeeded); auto start_pipeline = this->build_pipeline(program.get() + fSlotsNeeded); start_pipeline(x,y,x+w,y+h, program.get()); } std::function SkRasterPipeline::compile() const { if (this->empty()) { return [](size_t, size_t, size_t, size_t) {}; } void** program = fAlloc->makeArray(fSlotsNeeded); auto start_pipeline = this->build_pipeline(program + fSlotsNeeded); return [=](size_t x, size_t y, size_t w, size_t h) { start_pipeline(x,y,x+w,y+h, program); }; }