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 free(mData);
21 mData = nullptr;
22 }
23
resize(size_t size)24 bool MemoryBuffer::resize(size_t size)
25 {
26 if (size == 0)
27 {
28 free(mData);
29 mData = nullptr;
30 mSize = 0;
31 return true;
32 }
33
34 if (size == mSize)
35 {
36 return true;
37 }
38
39 // Only reallocate if the size has changed.
40 uint8_t *newMemory = static_cast<uint8_t *>(malloc(sizeof(uint8_t) * size));
41 if (newMemory == nullptr)
42 {
43 return false;
44 }
45
46 if (mData)
47 {
48 // Copy the intersection of the old data and the new data
49 std::copy(mData, mData + std::min(mSize, size), newMemory);
50 free(mData);
51 }
52
53 mData = newMemory;
54 mSize = size;
55
56 return true;
57 }
58
fill(uint8_t datum)59 void MemoryBuffer::fill(uint8_t datum)
60 {
61 if (!empty())
62 {
63 std::fill(mData, mData + mSize, datum);
64 }
65 }
66
MemoryBuffer(MemoryBuffer && other)67 MemoryBuffer::MemoryBuffer(MemoryBuffer &&other) : MemoryBuffer()
68 {
69 *this = std::move(other);
70 }
71
operator =(MemoryBuffer && other)72 MemoryBuffer &MemoryBuffer::operator=(MemoryBuffer &&other)
73 {
74 std::swap(mSize, other.mSize);
75 std::swap(mData, other.mData);
76 return *this;
77 }
78
79 namespace
80 {
81 static constexpr uint32_t kDefaultScratchBufferLifetime = 1000u;
82
83 } // anonymous namespace
84
85 // ScratchBuffer implementation.
ScratchBuffer()86 ScratchBuffer::ScratchBuffer() : ScratchBuffer(kDefaultScratchBufferLifetime) {}
87
ScratchBuffer(uint32_t lifetime)88 ScratchBuffer::ScratchBuffer(uint32_t lifetime) : mLifetime(lifetime), mResetCounter(lifetime) {}
89
~ScratchBuffer()90 ScratchBuffer::~ScratchBuffer() {}
91
ScratchBuffer(ScratchBuffer && other)92 ScratchBuffer::ScratchBuffer(ScratchBuffer &&other)
93 {
94 *this = std::move(other);
95 }
96
operator =(ScratchBuffer && other)97 ScratchBuffer &ScratchBuffer::operator=(ScratchBuffer &&other)
98 {
99 std::swap(mLifetime, other.mLifetime);
100 std::swap(mResetCounter, other.mResetCounter);
101 std::swap(mScratchMemory, other.mScratchMemory);
102 return *this;
103 }
104
get(size_t requestedSize,MemoryBuffer ** memoryBufferOut)105 bool ScratchBuffer::get(size_t requestedSize, MemoryBuffer **memoryBufferOut)
106 {
107 return getImpl(requestedSize, memoryBufferOut, Optional<uint8_t>::Invalid());
108 }
109
getInitialized(size_t requestedSize,MemoryBuffer ** memoryBufferOut,uint8_t initValue)110 bool ScratchBuffer::getInitialized(size_t requestedSize,
111 MemoryBuffer **memoryBufferOut,
112 uint8_t initValue)
113 {
114 return getImpl(requestedSize, memoryBufferOut, Optional<uint8_t>(initValue));
115 }
116
getImpl(size_t requestedSize,MemoryBuffer ** memoryBufferOut,Optional<uint8_t> initValue)117 bool ScratchBuffer::getImpl(size_t requestedSize,
118 MemoryBuffer **memoryBufferOut,
119 Optional<uint8_t> initValue)
120 {
121 if (mScratchMemory.size() == requestedSize)
122 {
123 mResetCounter = mLifetime;
124 *memoryBufferOut = &mScratchMemory;
125 return true;
126 }
127
128 if (mScratchMemory.size() > requestedSize)
129 {
130 tick();
131 }
132
133 if (mScratchMemory.size() < requestedSize)
134 {
135 if (!mScratchMemory.resize(requestedSize))
136 {
137 return false;
138 }
139 mResetCounter = mLifetime;
140 if (initValue.valid())
141 {
142 mScratchMemory.fill(initValue.value());
143 }
144 }
145
146 ASSERT(mScratchMemory.size() >= requestedSize);
147
148 *memoryBufferOut = &mScratchMemory;
149 return true;
150 }
151
tick()152 void ScratchBuffer::tick()
153 {
154 if (mResetCounter > 0)
155 {
156 --mResetCounter;
157 if (mResetCounter == 0)
158 {
159 clear();
160 }
161 }
162 }
163
clear()164 void ScratchBuffer::clear()
165 {
166 mResetCounter = mLifetime;
167 if (mScratchMemory.size() > 0)
168 {
169 mScratchMemory.clear();
170 }
171 }
172
173 } // namespace angle
174