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
14namespace angle
15{
16
17// MemoryBuffer implementation.
18MemoryBuffer::~MemoryBuffer()
19{
20 if (mData)
21 {
22 free(ptr: mData);
23 mData = nullptr;
24 }
25}
26
27bool MemoryBuffer::resize(size_t size)
28{
29 if (size == 0)
30 {
31 if (mData)
32 {
33 free(ptr: 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(size: 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(first: mData, last: mData + std::min(a: mSize, b: size), result: newMemory);
56 free(ptr: mData);
57 }
58
59 mData = newMemory;
60 mSize = size;
61
62 return true;
63}
64
65void MemoryBuffer::fill(uint8_t datum)
66{
67 if (!empty())
68 {
69 std::fill(first: mData, last: mData + mSize, value: datum);
70 }
71}
72
73MemoryBuffer::MemoryBuffer(MemoryBuffer &&other) : MemoryBuffer()
74{
75 *this = std::move(other);
76}
77
78MemoryBuffer &MemoryBuffer::operator=(MemoryBuffer &&other)
79{
80 std::swap(x&: mSize, y&: other.mSize);
81 std::swap(x&: mData, y&: other.mData);
82 return *this;
83}
84
85namespace
86{
87static constexpr uint32_t kDefaultScratchBufferLifetime = 1000u;
88
89} // anonymous namespace
90
91// ScratchBuffer implementation.
92ScratchBuffer::ScratchBuffer() : ScratchBuffer(kDefaultScratchBufferLifetime) {}
93
94ScratchBuffer::ScratchBuffer(uint32_t lifetime) : mLifetime(lifetime), mResetCounter(lifetime) {}
95
96ScratchBuffer::~ScratchBuffer() {}
97
98ScratchBuffer::ScratchBuffer(ScratchBuffer &&other)
99{
100 *this = std::move(other);
101}
102
103ScratchBuffer &ScratchBuffer::operator=(ScratchBuffer &&other)
104{
105 std::swap(x&: mLifetime, y&: other.mLifetime);
106 std::swap(x&: mResetCounter, y&: other.mResetCounter);
107 std::swap(x&: mScratchMemory, y&: other.mScratchMemory);
108 return *this;
109}
110
111bool ScratchBuffer::get(size_t requestedSize, MemoryBuffer **memoryBufferOut)
112{
113 return getImpl(requestedSize, memoryBufferOut, initValue: Optional<uint8_t>::Invalid());
114}
115
116bool ScratchBuffer::getInitialized(size_t requestedSize,
117 MemoryBuffer **memoryBufferOut,
118 uint8_t initValue)
119{
120 return getImpl(requestedSize, memoryBufferOut, initValue: Optional<uint8_t>(initValue));
121}
122
123bool 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(size: requestedSize))
142 {
143 return false;
144 }
145 mResetCounter = mLifetime;
146 if (initValue.valid())
147 {
148 mScratchMemory.fill(datum: initValue.value());
149 }
150 }
151
152 ASSERT(mScratchMemory.size() >= requestedSize);
153
154 *memoryBufferOut = &mScratchMemory;
155 return true;
156}
157
158void ScratchBuffer::tick()
159{
160 if (mResetCounter > 0)
161 {
162 --mResetCounter;
163 if (mResetCounter == 0)
164 {
165 clear();
166 }
167 }
168}
169
170void ScratchBuffer::clear()
171{
172 mResetCounter = mLifetime;
173 if (mScratchMemory.size() > 0)
174 {
175 mScratchMemory.clear();
176 }
177}
178
179} // namespace angle
180

source code of flutter_engine/third_party/angle/src/common/MemoryBuffer.cpp