blob: bdc8c1c7f5f30e274b0882f226e4e8208441b0f1 [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 "impeller/toolkit/interop/fragment_program.h"
#include "impeller/base/validation.h"
namespace impeller::interop {
FragmentProgram::FragmentProgram(const std::shared_ptr<fml::Mapping>& data) {
if (data == nullptr || data->GetSize() == 0) {
VALIDATION_LOG << "No data provided to create fragment program.";
return;
}
auto stages = RuntimeStage::DecodeRuntimeStages(data);
if (!stages.ok()) {
VALIDATION_LOG << "Failed to decode runtime stages: " << stages.status();
return;
}
for (const auto& stage : stages.value()) {
if (auto data = stage.second) {
stages_[stage.first] = std::move(data);
}
}
if (stages_.empty()) {
VALIDATION_LOG << "No valid runtime stages present in fragment program.";
return;
}
is_valid_ = true;
}
FragmentProgram::~FragmentProgram() = default;
bool FragmentProgram::IsValid() const {
return is_valid_;
}
static std::string AvailableStagesAsString(
const std::set<RuntimeStageBackend>& stages) {
std::stringstream stream;
size_t count = 0;
for (const auto& stage : stages) {
stream << RuntimeStageBackendToString(stage);
count++;
if (count != stages.size()) {
stream << ", ";
}
}
return stream.str();
}
std::shared_ptr<RuntimeStage> FragmentProgram::FindRuntimeStage(
RuntimeStageBackend backend) const {
if (backend == RuntimeStageBackend::kOpenGLES3) {
return FindRuntimeStage(RuntimeStageBackend::kOpenGLES);
}
auto found = stages_.find(backend);
if (found == stages_.end()) {
VALIDATION_LOG << "Could not find runtime shader for backend: "
<< RuntimeStageBackendToString(backend)
<< ". Shaders were packaged for "
<< AvailableStagesAsString(GetAvailableStages())
<< ". Check your shader compiler options.";
return nullptr;
}
return found->second;
}
const char* RuntimeStageBackendToString(RuntimeStageBackend backend) {
switch (backend) {
case RuntimeStageBackend::kSkSL:
return "SKSL";
case RuntimeStageBackend::kMetal:
return "Metal";
case RuntimeStageBackend::kOpenGLES:
return "OpenGL ES2";
case RuntimeStageBackend::kOpenGLES3:
return "OpenGL ES3";
case RuntimeStageBackend::kVulkan:
return "Vulkan";
}
return "Unknown";
}
std::set<RuntimeStageBackend> FragmentProgram::GetAvailableStages() const {
std::set<RuntimeStageBackend> stages;
for (const auto& stage : stages_) {
stages.insert(stage.first);
}
return stages;
}
} // namespace impeller::interop