blob: c9c060877ee1a02575744b501cd1f495569bdf91 [file] [log] [blame]
/*
* 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<void(size_t, size_t, size_t, size_t)> SkRasterPipeline::compile() const {
if (this->empty()) {
return [](size_t, size_t, size_t, size_t) {};
}
void** program = fAlloc->makeArray<void*>(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);
};
}