• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021 Google LLC
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "include/core/SkMath.h"
9 #include "src/gpu/GrSubRunAllocator.h"
10 
11 #include <cstddef>
12 #include <memory>
13 #include <new>
14 
15 // -- GrBagOfBytes ---------------------------------------------------------------------------------
GrBagOfBytes(char * bytes,size_t size,size_t firstHeapAllocation)16 GrBagOfBytes::GrBagOfBytes(char* bytes, size_t size, size_t firstHeapAllocation)
17         : fFibProgression(size, firstHeapAllocation) {
18     SkASSERT_RELEASE(size < kMaxByteSize);
19     SkASSERT_RELEASE(firstHeapAllocation < kMaxByteSize);
20 
21     std::size_t space = size;
22     void* ptr = bytes;
23     if (bytes && std::align(kMaxAlignment, sizeof(Block), ptr, space)) {
24         this->setupBytesAndCapacity(bytes, size);
25         new (fEndByte) Block(nullptr, nullptr);
26     }
27 }
28 
GrBagOfBytes(size_t firstHeapAllocation)29 GrBagOfBytes::GrBagOfBytes(size_t firstHeapAllocation)
30         : GrBagOfBytes(nullptr, 0, firstHeapAllocation) {}
31 
~GrBagOfBytes()32 GrBagOfBytes::~GrBagOfBytes() {
33     Block* cursor = reinterpret_cast<Block*>(fEndByte);
34     while (cursor != nullptr) {
35         char* toDelete = cursor->fBlockStart;
36         cursor = cursor->fPrevious;
37         delete [] toDelete;
38     }
39 }
40 
Block(char * previous,char * startOfBlock)41 GrBagOfBytes::Block::Block(char* previous, char* startOfBlock)
42         : fBlockStart{startOfBlock}
43         , fPrevious{reinterpret_cast<Block*>(previous)} {}
44 
alignedBytes(int size,int alignment)45 void* GrBagOfBytes::alignedBytes(int size, int alignment) {
46     SkASSERT_RELEASE(0 < size && size < kMaxByteSize);
47     SkASSERT_RELEASE(0 < alignment && alignment <= kMaxAlignment);
48     SkASSERT_RELEASE(SkIsPow2(alignment));
49 
50     return this->allocateBytes(size, alignment);
51 }
52 
setupBytesAndCapacity(char * bytes,int size)53 void GrBagOfBytes::setupBytesAndCapacity(char* bytes, int size) {
54     // endByte must be aligned to the maximum alignment to allow tracking alignment using capacity;
55     // capacity and endByte are both aligned to max alignment.
56     intptr_t endByte = reinterpret_cast<intptr_t>(bytes + size - sizeof(Block)) & -kMaxAlignment;
57     fEndByte  = reinterpret_cast<char*>(endByte);
58     fCapacity = fEndByte - bytes;
59 }
60 
needMoreBytes(int requestedSize,int alignment)61 void GrBagOfBytes::needMoreBytes(int requestedSize, int alignment) {
62     int nextBlockSize = fFibProgression.nextBlockSize();
63     const int size = PlatformMinimumSizeWithOverhead(
64             std::max(requestedSize, nextBlockSize), alignof(max_align_t));
65     char* const bytes = new char[size];
66     // fEndByte is changed by setupBytesAndCapacity. Remember it to link back to.
67     char* const previousBlock = fEndByte;
68     this->setupBytesAndCapacity(bytes, size);
69 
70     // Make a block to delete these bytes, and points to the previous block.
71     new (fEndByte) Block{previousBlock, bytes};
72 
73     // Make fCapacity the alignment for the requested object.
74     fCapacity = fCapacity & -alignment;
75     SkASSERT(fCapacity >= requestedSize);
76 }
77 
78 // -- GrSubRunAllocator ----------------------------------------------------------------------------
GrSubRunAllocator(char * bytes,int size,int firstHeapAllocation)79 GrSubRunAllocator::GrSubRunAllocator(char* bytes, int size, int firstHeapAllocation)
80         : fAlloc{bytes, SkTo<size_t>(size), SkTo<size_t>(firstHeapAllocation)} {}
81 
GrSubRunAllocator(int firstHeapAllocation)82 GrSubRunAllocator::GrSubRunAllocator(int firstHeapAllocation)
83         : GrSubRunAllocator(nullptr, 0, firstHeapAllocation) {}
84 
alignedBytes(int unsafeSize,int unsafeAlignment)85 void* GrSubRunAllocator::alignedBytes(int unsafeSize, int unsafeAlignment) {
86     return fAlloc.alignedBytes(unsafeSize, unsafeAlignment);
87 }
88