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
trim(size_t size)65 void MemoryBuffer::trim(size_t size)
66 {
67 ASSERT(size <= mSize);
68 mSize = size;
69 }
70
fill(uint8_t datum)71 void MemoryBuffer::fill(uint8_t datum)
72 {
73 if (!empty())
74 {
75 std::fill(mData, mData + mSize, datum);
76 }
77 }
78
MemoryBuffer(MemoryBuffer && other)79 MemoryBuffer::MemoryBuffer(MemoryBuffer &&other) : MemoryBuffer()
80 {
81 *this = std::move(other);
82 }
83
operator =(MemoryBuffer && other)84 MemoryBuffer &MemoryBuffer::operator=(MemoryBuffer &&other)
85 {
86 std::swap(mSize, other.mSize);
87 std::swap(mData, other.mData);
88 return *this;
89 }
90
91 namespace
92 {
93 static constexpr uint32_t kDefaultScratchBufferLifetime = 1000u;
94
95 } // anonymous namespace
96
97 // ScratchBuffer implementation.
ScratchBuffer()98 ScratchBuffer::ScratchBuffer() : ScratchBuffer(kDefaultScratchBufferLifetime) {}
99
ScratchBuffer(uint32_t lifetime)100 ScratchBuffer::ScratchBuffer(uint32_t lifetime) : mLifetime(lifetime), mResetCounter(lifetime) {}
101
~ScratchBuffer()102 ScratchBuffer::~ScratchBuffer() {}
103
ScratchBuffer(ScratchBuffer && other)104 ScratchBuffer::ScratchBuffer(ScratchBuffer &&other)
105 {
106 *this = std::move(other);
107 }
108
operator =(ScratchBuffer && other)109 ScratchBuffer &ScratchBuffer::operator=(ScratchBuffer &&other)
110 {
111 std::swap(mLifetime, other.mLifetime);
112 std::swap(mResetCounter, other.mResetCounter);
113 std::swap(mScratchMemory, other.mScratchMemory);
114 return *this;
115 }
116
get(size_t requestedSize,MemoryBuffer ** memoryBufferOut)117 bool ScratchBuffer::get(size_t requestedSize, MemoryBuffer **memoryBufferOut)
118 {
119 return getImpl(requestedSize, memoryBufferOut, Optional<uint8_t>::Invalid());
120 }
121
getInitialized(size_t requestedSize,MemoryBuffer ** memoryBufferOut,uint8_t initValue)122 bool ScratchBuffer::getInitialized(size_t requestedSize,
123 MemoryBuffer **memoryBufferOut,
124 uint8_t initValue)
125 {
126 return getImpl(requestedSize, memoryBufferOut, Optional<uint8_t>(initValue));
127 }
128
getImpl(size_t requestedSize,MemoryBuffer ** memoryBufferOut,Optional<uint8_t> initValue)129 bool ScratchBuffer::getImpl(size_t requestedSize,
130 MemoryBuffer **memoryBufferOut,
131 Optional<uint8_t> initValue)
132 {
133 if (mScratchMemory.size() == requestedSize)
134 {
135 mResetCounter = mLifetime;
136 *memoryBufferOut = &mScratchMemory;
137 return true;
138 }
139
140 if (mScratchMemory.size() > requestedSize)
141 {
142 tick();
143 }
144
145 if (mScratchMemory.size() < requestedSize)
146 {
147 if (!mScratchMemory.resize(requestedSize))
148 {
149 return false;
150 }
151 mResetCounter = mLifetime;
152 if (initValue.valid())
153 {
154 mScratchMemory.fill(initValue.value());
155 }
156 }
157
158 ASSERT(mScratchMemory.size() >= requestedSize);
159
160 *memoryBufferOut = &mScratchMemory;
161 return true;
162 }
163
tick()164 void ScratchBuffer::tick()
165 {
166 if (mResetCounter > 0)
167 {
168 --mResetCounter;
169 if (mResetCounter == 0)
170 {
171 clear();
172 }
173 }
174 }
175
clear()176 void ScratchBuffer::clear()
177 {
178 mResetCounter = mLifetime;
179 if (mScratchMemory.size() > 0)
180 {
181 mScratchMemory.clear();
182 }
183 }
184
185 } // namespace angle
186