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 if (mData)
21 {
22 free(mData);
23 mData = nullptr;
24 }
25 }
26
resize(size_t size)27 bool MemoryBuffer::resize(size_t size)
28 {
29 if (size == 0)
30 {
31 if (mData)
32 {
33 free(mData);
34 mData = nullptr;
35 }
36 mSize = 0;
37 return true;
38 }
39
40 if (size == mSize)
41 {
42 return true;
43 }
44
45 // Only reallocate if the size has changed.
46 uint8_t *newMemory = static_cast<uint8_t *>(malloc(sizeof(uint8_t) * size));
47 if (newMemory == nullptr)
48 {
49 return false;
50 }
51
52 if (mData)
53 {
54 // Copy the intersection of the old data and the new data
55 std::copy(mData, mData + std::min(mSize, size), newMemory);
56 free(mData);
57 }
58
59 mData = newMemory;
60 mSize = size;
61
62 return true;
63 }
64
fill(uint8_t datum)65 void MemoryBuffer::fill(uint8_t datum)
66 {
67 if (!empty())
68 {
69 std::fill(mData, mData + mSize, datum);
70 }
71 }
72
MemoryBuffer(MemoryBuffer && other)73 MemoryBuffer::MemoryBuffer(MemoryBuffer &&other) : MemoryBuffer()
74 {
75 *this = std::move(other);
76 }
77
operator =(MemoryBuffer && other)78 MemoryBuffer &MemoryBuffer::operator=(MemoryBuffer &&other)
79 {
80 std::swap(mSize, other.mSize);
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 if (mScratchMemory.size() == requestedSize)
128 {
129 mResetCounter = mLifetime;
130 *memoryBufferOut = &mScratchMemory;
131 return true;
132 }
133
134 if (mScratchMemory.size() > requestedSize)
135 {
136 tick();
137 }
138
139 if (mScratchMemory.size() < requestedSize)
140 {
141 if (!mScratchMemory.resize(requestedSize))
142 {
143 return false;
144 }
145 mResetCounter = mLifetime;
146 if (initValue.valid())
147 {
148 mScratchMemory.fill(initValue.value());
149 }
150 }
151
152 ASSERT(mScratchMemory.size() >= requestedSize);
153
154 *memoryBufferOut = &mScratchMemory;
155 return true;
156 }
157
tick()158 void ScratchBuffer::tick()
159 {
160 if (mResetCounter > 0)
161 {
162 --mResetCounter;
163 if (mResetCounter == 0)
164 {
165 clear();
166 }
167 }
168 }
169
clear()170 void ScratchBuffer::clear()
171 {
172 mResetCounter = mLifetime;
173 if (mScratchMemory.size() > 0)
174 {
175 mScratchMemory.clear();
176 }
177 }
178
179 } // namespace angle
180