2 * Copyright 2021 Google LLC
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #include "include/core/SkMath.h"
9 #include "src/text/gpu/SubRunAllocator.h"
16 namespace sktext::gpu {
18 // -- BagOfBytes ---------------------------------------------------------------------------------
19 BagOfBytes::BagOfBytes(char* bytes, size_t size, size_t firstHeapAllocation)
20 : fFibProgression(size, firstHeapAllocation) {
21 SkASSERT_RELEASE(size < kMaxByteSize);
22 SkASSERT_RELEASE(firstHeapAllocation < kMaxByteSize);
24 std::size_t space = size;
26 if (bytes && std::align(kMaxAlignment, sizeof(Block), ptr, space)) {
27 this->setupBytesAndCapacity(bytes, size);
28 new (fEndByte) Block(nullptr, nullptr);
32 BagOfBytes::BagOfBytes(size_t firstHeapAllocation)
33 : BagOfBytes(nullptr, 0, firstHeapAllocation) {}
35 BagOfBytes::~BagOfBytes() {
36 Block* cursor = reinterpret_cast<Block*>(fEndByte);
37 while (cursor != nullptr) {
38 char* toDelete = cursor->fBlockStart;
39 cursor = cursor->fPrevious;
44 BagOfBytes::Block::Block(char* previous, char* startOfBlock)
45 : fBlockStart{startOfBlock}
46 , fPrevious{reinterpret_cast<Block*>(previous)} {}
48 void* BagOfBytes::alignedBytes(int size, int alignment) {
49 SkASSERT_RELEASE(0 < size && size < kMaxByteSize);
50 SkASSERT_RELEASE(0 < alignment && alignment <= kMaxAlignment);
51 SkASSERT_RELEASE(SkIsPow2(alignment));
53 return this->allocateBytes(size, alignment);
56 void BagOfBytes::setupBytesAndCapacity(char* bytes, int size) {
57 // endByte must be aligned to the maximum alignment to allow tracking alignment using capacity;
58 // capacity and endByte are both aligned to max alignment.
59 intptr_t endByte = reinterpret_cast<intptr_t>(bytes + size - sizeof(Block)) & -kMaxAlignment;
60 fEndByte = reinterpret_cast<char*>(endByte);
61 fCapacity = fEndByte - bytes;
64 void BagOfBytes::needMoreBytes(int requestedSize, int alignment) {
65 int nextBlockSize = fFibProgression.nextBlockSize();
66 const int size = PlatformMinimumSizeWithOverhead(
67 std::max(requestedSize, nextBlockSize), kAllocationAlignment);
68 char* const bytes = new char[size];
69 // fEndByte is changed by setupBytesAndCapacity. Remember it to link back to.
70 char* const previousBlock = fEndByte;
71 this->setupBytesAndCapacity(bytes, size);
73 // Make a block to delete these bytes, and points to the previous block.
74 new (fEndByte) Block{previousBlock, bytes};
76 // Make fCapacity the alignment for the requested object.
77 fCapacity = fCapacity & -alignment;
78 SkASSERT(fCapacity >= requestedSize);
81 // -- SubRunAllocator ----------------------------------------------------------------------------
82 SubRunAllocator::SubRunAllocator(char* bytes, int size, int firstHeapAllocation)
83 : fAlloc{bytes, SkTo<size_t>(size), SkTo<size_t>(firstHeapAllocation)} {
84 SkASSERT_RELEASE(SkTFitsIn<size_t>(size));
85 SkASSERT_RELEASE(SkTFitsIn<size_t>(firstHeapAllocation));
88 SubRunAllocator::SubRunAllocator(int firstHeapAllocation)
89 : SubRunAllocator(nullptr, 0, firstHeapAllocation) { }
91 void* SubRunAllocator::alignedBytes(int unsafeSize, int unsafeAlignment) {
92 return fAlloc.alignedBytes(unsafeSize, unsafeAlignment);
95 } // namespace sktext::gpu