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