blob: 94af2799f925266971a634faa3349f14db782768 [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/blobcat/blob_library.h"
#include <string>
namespace impeller {
BlobLibrary::BlobLibrary(std::shared_ptr<fml::Mapping> mapping)
: mapping_(std::move(mapping)) {
if (!mapping_ || mapping_->GetMapping() == nullptr) {
FML_LOG(ERROR) << "Invalid mapping.";
return;
}
BlobHeader header;
std::vector<Blob> blobs;
size_t offset = 0u;
// Read the header.
{
const size_t read_size = sizeof(BlobHeader);
if (mapping_->GetSize() < offset + read_size) {
return;
}
std::memcpy(&header, mapping_->GetMapping() + offset, read_size);
offset += read_size;
// Validate the header.
if (header.magic != kBlobCatMagic) {
FML_LOG(ERROR) << "Invalid blob magic.";
return;
}
blobs.resize(header.blob_count);
}
// Read the blob descriptions.
{
const size_t read_size = sizeof(Blob) * header.blob_count;
::memcpy(blobs.data(), mapping_->GetMapping() + offset, read_size);
offset += read_size; // NOLINT(clang-analyzer-deadcode.DeadStores)
}
// Read the blobs.
{
for (size_t i = 0; i < header.blob_count; i++) {
const auto& blob = blobs[i];
BlobKey key;
key.type = blob.type;
key.name = std::string{reinterpret_cast<const char*>(blob.name)};
auto mapping = std::make_shared<fml::NonOwnedMapping>(
mapping_->GetMapping() + blob.offset, // offset
blob.length, // length
[mapping = mapping_](const uint8_t* data, size_t size) {}
// release proc
);
auto inserted = blobs_.insert({key, mapping});
if (!inserted.second) {
FML_LOG(ERROR) << "Shader library had duplicate shader named "
<< key.name;
return;
}
}
}
is_valid_ = true;
}
BlobLibrary::BlobLibrary(BlobLibrary&&) = default;
BlobLibrary::~BlobLibrary() = default;
bool BlobLibrary::IsValid() const {
return is_valid_;
}
size_t BlobLibrary::GetShaderCount() const {
return blobs_.size();
}
std::shared_ptr<fml::Mapping> BlobLibrary::GetMapping(Blob::ShaderType type,
std::string name) const {
BlobKey key;
key.type = type;
key.name = name;
auto found = blobs_.find(key);
return found == blobs_.end() ? nullptr : found->second;
}
size_t BlobLibrary::IterateAllBlobs(
std::function<bool(Blob::ShaderType type,
const std::string& name,
const std::shared_ptr<fml::Mapping>& mapping)> callback)
const {
if (!IsValid() || !callback) {
return 0u;
}
size_t count = 0u;
for (const auto& blob : blobs_) {
count++;
if (!callback(blob.first.type, blob.first.name, blob.second)) {
break;
}
}
return count;
}
} // namespace impeller