xref: /aosp_15_r20/external/angle/src/common/MemoryBuffer.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2014 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 #include "common/MemoryBuffer.h"
8 
9 #include <algorithm>
10 #include <cstdlib>
11 
12 #include "common/debug.h"
13 
14 namespace angle
15 {
16 
17 // MemoryBuffer implementation.
~MemoryBuffer()18 MemoryBuffer::~MemoryBuffer()
19 {
20     clear();
21 }
22 
resize(size_t size)23 bool MemoryBuffer::resize(size_t size)
24 {
25     if (size == 0)
26     {
27         if (mData)
28         {
29             free(mData);
30             mData     = nullptr;
31             mCapacity = 0;
32         }
33         mSize = 0;
34         return true;
35     }
36 
37     if (size == mCapacity)
38     {
39         mSize = size;
40         return true;
41     }
42 
43     // Only reallocate if the size has changed.
44     uint8_t *newMemory = static_cast<uint8_t *>(malloc(sizeof(uint8_t) * size));
45     if (newMemory == nullptr)
46     {
47         return false;
48     }
49 
50     if (mData)
51     {
52         // Copy the intersection of the old data and the new data
53         std::copy(mData, mData + std::min(mSize, size), newMemory);
54         free(mData);
55     }
56 
57     mData     = newMemory;
58     mCapacity = size;
59     mSize     = size;
60 
61     return true;
62 }
63 
fill(uint8_t datum)64 void MemoryBuffer::fill(uint8_t datum)
65 {
66     if (!empty())
67     {
68         std::fill(mData, mData + mSize, datum);
69     }
70 }
71 
MemoryBuffer(MemoryBuffer && other)72 MemoryBuffer::MemoryBuffer(MemoryBuffer &&other) : MemoryBuffer()
73 {
74     *this = std::move(other);
75 }
76 
operator =(MemoryBuffer && other)77 MemoryBuffer &MemoryBuffer::operator=(MemoryBuffer &&other)
78 {
79     std::swap(mSize, other.mSize);
80     std::swap(mCapacity, other.mCapacity);
81     std::swap(mData, other.mData);
82     return *this;
83 }
84 
85 namespace
86 {
87 static constexpr uint32_t kDefaultScratchBufferLifetime = 1000u;
88 
89 }  // anonymous namespace
90 
91 // ScratchBuffer implementation.
ScratchBuffer()92 ScratchBuffer::ScratchBuffer() : ScratchBuffer(kDefaultScratchBufferLifetime) {}
93 
ScratchBuffer(uint32_t lifetime)94 ScratchBuffer::ScratchBuffer(uint32_t lifetime) : mLifetime(lifetime), mResetCounter(lifetime) {}
95 
~ScratchBuffer()96 ScratchBuffer::~ScratchBuffer() {}
97 
ScratchBuffer(ScratchBuffer && other)98 ScratchBuffer::ScratchBuffer(ScratchBuffer &&other)
99 {
100     *this = std::move(other);
101 }
102 
operator =(ScratchBuffer && other)103 ScratchBuffer &ScratchBuffer::operator=(ScratchBuffer &&other)
104 {
105     std::swap(mLifetime, other.mLifetime);
106     std::swap(mResetCounter, other.mResetCounter);
107     std::swap(mScratchMemory, other.mScratchMemory);
108     return *this;
109 }
110 
get(size_t requestedSize,MemoryBuffer ** memoryBufferOut)111 bool ScratchBuffer::get(size_t requestedSize, MemoryBuffer **memoryBufferOut)
112 {
113     return getImpl(requestedSize, memoryBufferOut, Optional<uint8_t>::Invalid());
114 }
115 
getInitialized(size_t requestedSize,MemoryBuffer ** memoryBufferOut,uint8_t initValue)116 bool ScratchBuffer::getInitialized(size_t requestedSize,
117                                    MemoryBuffer **memoryBufferOut,
118                                    uint8_t initValue)
119 {
120     return getImpl(requestedSize, memoryBufferOut, Optional<uint8_t>(initValue));
121 }
122 
getImpl(size_t requestedSize,MemoryBuffer ** memoryBufferOut,Optional<uint8_t> initValue)123 bool ScratchBuffer::getImpl(size_t requestedSize,
124                             MemoryBuffer **memoryBufferOut,
125                             Optional<uint8_t> initValue)
126 {
127     mScratchMemory.setSizeToCapacity();
128 
129     if (mScratchMemory.size() == requestedSize)
130     {
131         mResetCounter    = mLifetime;
132         *memoryBufferOut = &mScratchMemory;
133         return true;
134     }
135 
136     if (mScratchMemory.size() > requestedSize)
137     {
138         tick();
139     }
140 
141     if (mScratchMemory.size() < requestedSize)
142     {
143         if (!mScratchMemory.resize(requestedSize))
144         {
145             return false;
146         }
147         mResetCounter = mLifetime;
148         if (initValue.valid())
149         {
150             mScratchMemory.fill(initValue.value());
151         }
152     }
153 
154     ASSERT(mScratchMemory.size() >= requestedSize);
155 
156     *memoryBufferOut = &mScratchMemory;
157     return true;
158 }
159 
tick()160 void ScratchBuffer::tick()
161 {
162     if (mResetCounter > 0)
163     {
164         --mResetCounter;
165         if (mResetCounter == 0)
166         {
167             clear();
168         }
169     }
170 }
171 
clear()172 void ScratchBuffer::clear()
173 {
174     mResetCounter = mLifetime;
175     if (mScratchMemory.size() > 0)
176     {
177         mScratchMemory.clear();
178     }
179 }
180 
181 }  // namespace angle
182