1 //
2 // Copyright (c) 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() : mSize(0), mData(nullptr)
19 {
20 }
21
~MemoryBuffer()22 MemoryBuffer::~MemoryBuffer()
23 {
24 free(mData);
25 mData = nullptr;
26 }
27
resize(size_t size)28 bool MemoryBuffer::resize(size_t size)
29 {
30 if (size == 0)
31 {
32 free(mData);
33 mData = nullptr;
34 mSize = 0;
35 return true;
36 }
37
38 if (size == mSize)
39 {
40 return true;
41 }
42
43 // Only reallocate if the size has changed.
44 uint8_t *newMemory = reinterpret_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 mSize = size;
59
60 return true;
61 }
62
fill(uint8_t datum)63 void MemoryBuffer::fill(uint8_t datum)
64 {
65 if (!empty())
66 {
67 std::fill(mData, mData + mSize, datum);
68 }
69 }
70
MemoryBuffer(MemoryBuffer && other)71 MemoryBuffer::MemoryBuffer(MemoryBuffer &&other) : MemoryBuffer()
72 {
73 *this = std::move(other);
74 }
75
operator =(MemoryBuffer && other)76 MemoryBuffer &MemoryBuffer::operator=(MemoryBuffer &&other)
77 {
78 std::swap(mSize, other.mSize);
79 std::swap(mData, other.mData);
80 return *this;
81 }
82
83 // ScratchBuffer implementation.
84
ScratchBuffer(uint32_t lifetime)85 ScratchBuffer::ScratchBuffer(uint32_t lifetime) : mLifetime(lifetime), mResetCounter(lifetime)
86 {
87 }
88
~ScratchBuffer()89 ScratchBuffer::~ScratchBuffer()
90 {
91 }
92
get(size_t requestedSize,MemoryBuffer ** memoryBufferOut)93 bool ScratchBuffer::get(size_t requestedSize, MemoryBuffer **memoryBufferOut)
94 {
95 return getImpl(requestedSize, memoryBufferOut, Optional<uint8_t>::Invalid());
96 }
97
getInitialized(size_t requestedSize,MemoryBuffer ** memoryBufferOut,uint8_t initValue)98 bool ScratchBuffer::getInitialized(size_t requestedSize,
99 MemoryBuffer **memoryBufferOut,
100 uint8_t initValue)
101 {
102 return getImpl(requestedSize, memoryBufferOut, Optional<uint8_t>(initValue));
103 }
104
getImpl(size_t requestedSize,MemoryBuffer ** memoryBufferOut,Optional<uint8_t> initValue)105 bool ScratchBuffer::getImpl(size_t requestedSize,
106 MemoryBuffer **memoryBufferOut,
107 Optional<uint8_t> initValue)
108 {
109 if (mScratchMemory.size() == requestedSize)
110 {
111 mResetCounter = mLifetime;
112 *memoryBufferOut = &mScratchMemory;
113 return true;
114 }
115
116 if (mScratchMemory.size() > requestedSize)
117 {
118 tick();
119 }
120
121 if (mResetCounter == 0 || mScratchMemory.size() < requestedSize)
122 {
123 mScratchMemory.resize(0);
124 if (!mScratchMemory.resize(requestedSize))
125 {
126 return false;
127 }
128 mResetCounter = mLifetime;
129 if (initValue.valid())
130 {
131 mScratchMemory.fill(initValue.value());
132 }
133 }
134
135 ASSERT(mScratchMemory.size() >= requestedSize);
136
137 *memoryBufferOut = &mScratchMemory;
138 return true;
139 }
140
tick()141 void ScratchBuffer::tick()
142 {
143 if (mResetCounter > 0)
144 {
145 --mResetCounter;
146 }
147 }
148
clear()149 void ScratchBuffer::clear()
150 {
151 mResetCounter = mLifetime;
152 mScratchMemory.resize(0);
153 }
154
155 } // namespace angle
156