blob: c7f65d416f10ba35925edb0be08e64b22a45d938 [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/base/allocation.h"
#include <algorithm>
#include <cstring>
#include "impeller/base/validation.h"
namespace impeller {
Allocation::Allocation() = default;
Allocation::~Allocation() {
::free(buffer_);
}
uint8_t* Allocation::GetBuffer() const {
return buffer_;
}
size_t Allocation::GetLength() const {
return length_;
}
size_t Allocation::GetReservedLength() const {
return reserved_;
}
bool Allocation::Truncate(size_t length, bool npot) {
const auto reserved = npot ? ReserveNPOT(length) : Reserve(length);
if (!reserved) {
return false;
}
length_ = length;
return true;
}
uint32_t Allocation::NextPowerOfTwoSize(uint32_t x) {
if (x == 0) {
return 1;
}
--x;
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
return x + 1;
}
bool Allocation::ReserveNPOT(size_t reserved) {
// Reserve at least one page of data.
reserved = std::max<size_t>(4096u, reserved);
return Reserve(NextPowerOfTwoSize(reserved));
}
bool Allocation::Reserve(size_t reserved) {
if (reserved <= reserved_) {
return true;
}
auto new_allocation = ::realloc(buffer_, reserved);
if (!new_allocation) {
// If new length is zero, a minimum non-zero sized allocation is returned.
// So this check will not trip and this routine will indicate success as
// expected.
VALIDATION_LOG << "Allocation failed. Out of host memory.";
return false;
}
buffer_ = static_cast<uint8_t*>(new_allocation);
reserved_ = reserved;
return true;
}
std::shared_ptr<fml::Mapping> CreateMappingWithCopy(const uint8_t* contents,
size_t length) {
if (contents == nullptr) {
return nullptr;
}
auto allocation = std::make_shared<Allocation>();
if (!allocation->Truncate(length)) {
return nullptr;
}
std::memmove(allocation->GetBuffer(), contents, length);
return CreateMappingFromAllocation(allocation);
}
std::shared_ptr<fml::Mapping> CreateMappingFromAllocation(
const std::shared_ptr<Allocation>& allocation) {
if (!allocation) {
return nullptr;
}
return std::make_shared<fml::NonOwnedMapping>(
reinterpret_cast<const uint8_t*>(allocation->GetBuffer()), //
allocation->GetLength(), //
[allocation](auto, auto) {} //
);
}
std::shared_ptr<fml::Mapping> CreateMappingWithString(std::string string) {
auto buffer = std::make_shared<std::string>(std::move(string));
return std::make_unique<fml::NonOwnedMapping>(
reinterpret_cast<const uint8_t*>(buffer->c_str()), buffer->length(),
[buffer](auto, auto) {});
}
} // namespace impeller