blob: b166a497d1d2257c5706763b955dd6eb13ca725b [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <iostream>
#include "flutter/lib/ui/painting/fragment_program.h"
#include "flutter/lib/ui/dart_wrapper.h"
#include "flutter/lib/ui/ui_dart_state.h"
#include "third_party/skia/include/core/SkString.h"
#include "third_party/tonic/converter/dart_converter.h"
#include "third_party/tonic/dart_args.h"
#include "third_party/tonic/dart_binding_macros.h"
#include "third_party/tonic/dart_library_natives.h"
#include "third_party/tonic/typed_data/typed_list.h"
using tonic::ToDart;
namespace flutter {
static void FragmentProgram_constructor(Dart_NativeArguments args) {
DartCallConstructor(&FragmentProgram::Create, args);
}
IMPLEMENT_WRAPPERTYPEINFO(ui, FragmentProgram);
#define FOR_EACH_BINDING(V) \
V(FragmentProgram, init) \
V(FragmentProgram, shader)
FOR_EACH_BINDING(DART_NATIVE_CALLBACK)
void FragmentProgram::RegisterNatives(tonic::DartLibraryNatives* natives) {
natives->Register(
{{"FragmentProgram_constructor", FragmentProgram_constructor, 1, true},
FOR_EACH_BINDING(DART_REGISTER_NATIVE)});
}
void FragmentProgram::init(std::string sksl, bool debugPrintSksl) {
SkRuntimeEffect::Result result =
SkRuntimeEffect::MakeForShader(SkString(sksl));
runtime_effect_ = result.effect;
if (runtime_effect_ == nullptr) {
Dart_ThrowException(tonic::ToDart(
std::string("Invalid SkSL:\n") + sksl.c_str() +
std::string("\nSkSL Error:\n") + result.errorText.c_str()));
return;
}
if (debugPrintSksl) {
FML_DLOG(INFO) << std::string("debugPrintSksl:\n") + sksl.c_str();
}
}
fml::RefPtr<FragmentShader> FragmentProgram::shader(
Dart_Handle shader,
const tonic::Float32List& uniforms,
Dart_Handle samplers) {
auto sampler_shaders =
tonic::DartConverter<std::vector<ImageShader*>>::FromDart(samplers);
size_t uniform_count = uniforms.num_elements();
size_t uniform_data_size =
(uniform_count + 2 * sampler_shaders.size()) * sizeof(float);
sk_sp<SkData> uniform_data = SkData::MakeUninitialized(uniform_data_size);
// uniform_floats must only be referenced BEFORE the call to makeShader below.
auto* uniform_floats =
reinterpret_cast<float*>(uniform_data->writable_data());
for (size_t i = 0; i < uniform_count; i++) {
uniform_floats[i] = uniforms[i];
}
std::vector<sk_sp<SkShader>> sk_samplers(sampler_shaders.size());
for (size_t i = 0; i < sampler_shaders.size(); i++) {
ImageShader* image_shader = sampler_shaders[i];
// The default value for SkSamplingOptions is used because ImageShader
// uses a cached value set by the user in the Dart constructor.
// Users are instructed to make use of this in the Dart docs.
sk_samplers[i] = image_shader->shader(SkSamplingOptions());
uniform_floats[uniform_count + 2 * i] = image_shader->width();
uniform_floats[uniform_count + 2 * i + 1] = image_shader->height();
}
auto sk_shader =
runtime_effect_->makeShader(std::move(uniform_data), sk_samplers.data(),
sk_samplers.size(), nullptr, false);
return FragmentShader::Create(shader, std::move(sk_shader));
}
fml::RefPtr<FragmentProgram> FragmentProgram::Create() {
return fml::MakeRefCounted<FragmentProgram>();
}
FragmentProgram::FragmentProgram() = default;
FragmentProgram::~FragmentProgram() = default;
} // namespace flutter