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. |
18 | MemoryBuffer::~MemoryBuffer() |
19 | { |
20 | free(mData); |
21 | mData = nullptr; |
22 | } |
23 | |
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 | |
59 | void MemoryBuffer::fill(uint8_t datum) |
60 | { |
61 | if (!empty()) |
62 | { |
63 | std::fill(mData, mData + mSize, datum); |
64 | } |
65 | } |
66 | |
67 | MemoryBuffer::MemoryBuffer(MemoryBuffer &&other) : MemoryBuffer() |
68 | { |
69 | *this = std::move(other); |
70 | } |
71 | |
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 | // ScratchBuffer implementation. |
80 | |
81 | ScratchBuffer::ScratchBuffer(uint32_t lifetime) : mLifetime(lifetime), mResetCounter(lifetime) {} |
82 | |
83 | ScratchBuffer::~ScratchBuffer() {} |
84 | |
85 | bool ScratchBuffer::get(size_t requestedSize, MemoryBuffer **memoryBufferOut) |
86 | { |
87 | return getImpl(requestedSize, memoryBufferOut, Optional<uint8_t>::Invalid()); |
88 | } |
89 | |
90 | bool ScratchBuffer::getInitialized(size_t requestedSize, |
91 | MemoryBuffer **memoryBufferOut, |
92 | uint8_t initValue) |
93 | { |
94 | return getImpl(requestedSize, memoryBufferOut, Optional<uint8_t>(initValue)); |
95 | } |
96 | |
97 | bool ScratchBuffer::getImpl(size_t requestedSize, |
98 | MemoryBuffer **memoryBufferOut, |
99 | Optional<uint8_t> initValue) |
100 | { |
101 | if (mScratchMemory.size() == requestedSize) |
102 | { |
103 | mResetCounter = mLifetime; |
104 | *memoryBufferOut = &mScratchMemory; |
105 | return true; |
106 | } |
107 | |
108 | if (mScratchMemory.size() > requestedSize) |
109 | { |
110 | tick(); |
111 | } |
112 | |
113 | if (mResetCounter == 0 || mScratchMemory.size() < requestedSize) |
114 | { |
115 | mScratchMemory.resize(0); |
116 | if (!mScratchMemory.resize(requestedSize)) |
117 | { |
118 | return false; |
119 | } |
120 | mResetCounter = mLifetime; |
121 | if (initValue.valid()) |
122 | { |
123 | mScratchMemory.fill(initValue.value()); |
124 | } |
125 | } |
126 | |
127 | ASSERT(mScratchMemory.size() >= requestedSize); |
128 | |
129 | *memoryBufferOut = &mScratchMemory; |
130 | return true; |
131 | } |
132 | |
133 | void ScratchBuffer::tick() |
134 | { |
135 | if (mResetCounter > 0) |
136 | { |
137 | --mResetCounter; |
138 | } |
139 | } |
140 | |
141 | void ScratchBuffer::clear() |
142 | { |
143 | mResetCounter = mLifetime; |
144 | mScratchMemory.resize(0); |
145 | } |
146 | |
147 | } // namespace angle |
148 | |