1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2014 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker
7*8975f5c5SAndroid Build Coastguard Worker #include "common/MemoryBuffer.h"
8*8975f5c5SAndroid Build Coastguard Worker
9*8975f5c5SAndroid Build Coastguard Worker #include <algorithm>
10*8975f5c5SAndroid Build Coastguard Worker #include <cstdlib>
11*8975f5c5SAndroid Build Coastguard Worker
12*8975f5c5SAndroid Build Coastguard Worker #include "common/debug.h"
13*8975f5c5SAndroid Build Coastguard Worker
14*8975f5c5SAndroid Build Coastguard Worker namespace angle
15*8975f5c5SAndroid Build Coastguard Worker {
16*8975f5c5SAndroid Build Coastguard Worker
17*8975f5c5SAndroid Build Coastguard Worker // MemoryBuffer implementation.
~MemoryBuffer()18*8975f5c5SAndroid Build Coastguard Worker MemoryBuffer::~MemoryBuffer()
19*8975f5c5SAndroid Build Coastguard Worker {
20*8975f5c5SAndroid Build Coastguard Worker clear();
21*8975f5c5SAndroid Build Coastguard Worker }
22*8975f5c5SAndroid Build Coastguard Worker
resize(size_t size)23*8975f5c5SAndroid Build Coastguard Worker bool MemoryBuffer::resize(size_t size)
24*8975f5c5SAndroid Build Coastguard Worker {
25*8975f5c5SAndroid Build Coastguard Worker if (size == 0)
26*8975f5c5SAndroid Build Coastguard Worker {
27*8975f5c5SAndroid Build Coastguard Worker if (mData)
28*8975f5c5SAndroid Build Coastguard Worker {
29*8975f5c5SAndroid Build Coastguard Worker free(mData);
30*8975f5c5SAndroid Build Coastguard Worker mData = nullptr;
31*8975f5c5SAndroid Build Coastguard Worker mCapacity = 0;
32*8975f5c5SAndroid Build Coastguard Worker }
33*8975f5c5SAndroid Build Coastguard Worker mSize = 0;
34*8975f5c5SAndroid Build Coastguard Worker return true;
35*8975f5c5SAndroid Build Coastguard Worker }
36*8975f5c5SAndroid Build Coastguard Worker
37*8975f5c5SAndroid Build Coastguard Worker if (size == mCapacity)
38*8975f5c5SAndroid Build Coastguard Worker {
39*8975f5c5SAndroid Build Coastguard Worker mSize = size;
40*8975f5c5SAndroid Build Coastguard Worker return true;
41*8975f5c5SAndroid Build Coastguard Worker }
42*8975f5c5SAndroid Build Coastguard Worker
43*8975f5c5SAndroid Build Coastguard Worker // Only reallocate if the size has changed.
44*8975f5c5SAndroid Build Coastguard Worker uint8_t *newMemory = static_cast<uint8_t *>(malloc(sizeof(uint8_t) * size));
45*8975f5c5SAndroid Build Coastguard Worker if (newMemory == nullptr)
46*8975f5c5SAndroid Build Coastguard Worker {
47*8975f5c5SAndroid Build Coastguard Worker return false;
48*8975f5c5SAndroid Build Coastguard Worker }
49*8975f5c5SAndroid Build Coastguard Worker
50*8975f5c5SAndroid Build Coastguard Worker if (mData)
51*8975f5c5SAndroid Build Coastguard Worker {
52*8975f5c5SAndroid Build Coastguard Worker // Copy the intersection of the old data and the new data
53*8975f5c5SAndroid Build Coastguard Worker std::copy(mData, mData + std::min(mSize, size), newMemory);
54*8975f5c5SAndroid Build Coastguard Worker free(mData);
55*8975f5c5SAndroid Build Coastguard Worker }
56*8975f5c5SAndroid Build Coastguard Worker
57*8975f5c5SAndroid Build Coastguard Worker mData = newMemory;
58*8975f5c5SAndroid Build Coastguard Worker mCapacity = size;
59*8975f5c5SAndroid Build Coastguard Worker mSize = size;
60*8975f5c5SAndroid Build Coastguard Worker
61*8975f5c5SAndroid Build Coastguard Worker return true;
62*8975f5c5SAndroid Build Coastguard Worker }
63*8975f5c5SAndroid Build Coastguard Worker
fill(uint8_t datum)64*8975f5c5SAndroid Build Coastguard Worker void MemoryBuffer::fill(uint8_t datum)
65*8975f5c5SAndroid Build Coastguard Worker {
66*8975f5c5SAndroid Build Coastguard Worker if (!empty())
67*8975f5c5SAndroid Build Coastguard Worker {
68*8975f5c5SAndroid Build Coastguard Worker std::fill(mData, mData + mSize, datum);
69*8975f5c5SAndroid Build Coastguard Worker }
70*8975f5c5SAndroid Build Coastguard Worker }
71*8975f5c5SAndroid Build Coastguard Worker
MemoryBuffer(MemoryBuffer && other)72*8975f5c5SAndroid Build Coastguard Worker MemoryBuffer::MemoryBuffer(MemoryBuffer &&other) : MemoryBuffer()
73*8975f5c5SAndroid Build Coastguard Worker {
74*8975f5c5SAndroid Build Coastguard Worker *this = std::move(other);
75*8975f5c5SAndroid Build Coastguard Worker }
76*8975f5c5SAndroid Build Coastguard Worker
operator =(MemoryBuffer && other)77*8975f5c5SAndroid Build Coastguard Worker MemoryBuffer &MemoryBuffer::operator=(MemoryBuffer &&other)
78*8975f5c5SAndroid Build Coastguard Worker {
79*8975f5c5SAndroid Build Coastguard Worker std::swap(mSize, other.mSize);
80*8975f5c5SAndroid Build Coastguard Worker std::swap(mCapacity, other.mCapacity);
81*8975f5c5SAndroid Build Coastguard Worker std::swap(mData, other.mData);
82*8975f5c5SAndroid Build Coastguard Worker return *this;
83*8975f5c5SAndroid Build Coastguard Worker }
84*8975f5c5SAndroid Build Coastguard Worker
85*8975f5c5SAndroid Build Coastguard Worker namespace
86*8975f5c5SAndroid Build Coastguard Worker {
87*8975f5c5SAndroid Build Coastguard Worker static constexpr uint32_t kDefaultScratchBufferLifetime = 1000u;
88*8975f5c5SAndroid Build Coastguard Worker
89*8975f5c5SAndroid Build Coastguard Worker } // anonymous namespace
90*8975f5c5SAndroid Build Coastguard Worker
91*8975f5c5SAndroid Build Coastguard Worker // ScratchBuffer implementation.
ScratchBuffer()92*8975f5c5SAndroid Build Coastguard Worker ScratchBuffer::ScratchBuffer() : ScratchBuffer(kDefaultScratchBufferLifetime) {}
93*8975f5c5SAndroid Build Coastguard Worker
ScratchBuffer(uint32_t lifetime)94*8975f5c5SAndroid Build Coastguard Worker ScratchBuffer::ScratchBuffer(uint32_t lifetime) : mLifetime(lifetime), mResetCounter(lifetime) {}
95*8975f5c5SAndroid Build Coastguard Worker
~ScratchBuffer()96*8975f5c5SAndroid Build Coastguard Worker ScratchBuffer::~ScratchBuffer() {}
97*8975f5c5SAndroid Build Coastguard Worker
ScratchBuffer(ScratchBuffer && other)98*8975f5c5SAndroid Build Coastguard Worker ScratchBuffer::ScratchBuffer(ScratchBuffer &&other)
99*8975f5c5SAndroid Build Coastguard Worker {
100*8975f5c5SAndroid Build Coastguard Worker *this = std::move(other);
101*8975f5c5SAndroid Build Coastguard Worker }
102*8975f5c5SAndroid Build Coastguard Worker
operator =(ScratchBuffer && other)103*8975f5c5SAndroid Build Coastguard Worker ScratchBuffer &ScratchBuffer::operator=(ScratchBuffer &&other)
104*8975f5c5SAndroid Build Coastguard Worker {
105*8975f5c5SAndroid Build Coastguard Worker std::swap(mLifetime, other.mLifetime);
106*8975f5c5SAndroid Build Coastguard Worker std::swap(mResetCounter, other.mResetCounter);
107*8975f5c5SAndroid Build Coastguard Worker std::swap(mScratchMemory, other.mScratchMemory);
108*8975f5c5SAndroid Build Coastguard Worker return *this;
109*8975f5c5SAndroid Build Coastguard Worker }
110*8975f5c5SAndroid Build Coastguard Worker
get(size_t requestedSize,MemoryBuffer ** memoryBufferOut)111*8975f5c5SAndroid Build Coastguard Worker bool ScratchBuffer::get(size_t requestedSize, MemoryBuffer **memoryBufferOut)
112*8975f5c5SAndroid Build Coastguard Worker {
113*8975f5c5SAndroid Build Coastguard Worker return getImpl(requestedSize, memoryBufferOut, Optional<uint8_t>::Invalid());
114*8975f5c5SAndroid Build Coastguard Worker }
115*8975f5c5SAndroid Build Coastguard Worker
getInitialized(size_t requestedSize,MemoryBuffer ** memoryBufferOut,uint8_t initValue)116*8975f5c5SAndroid Build Coastguard Worker bool ScratchBuffer::getInitialized(size_t requestedSize,
117*8975f5c5SAndroid Build Coastguard Worker MemoryBuffer **memoryBufferOut,
118*8975f5c5SAndroid Build Coastguard Worker uint8_t initValue)
119*8975f5c5SAndroid Build Coastguard Worker {
120*8975f5c5SAndroid Build Coastguard Worker return getImpl(requestedSize, memoryBufferOut, Optional<uint8_t>(initValue));
121*8975f5c5SAndroid Build Coastguard Worker }
122*8975f5c5SAndroid Build Coastguard Worker
getImpl(size_t requestedSize,MemoryBuffer ** memoryBufferOut,Optional<uint8_t> initValue)123*8975f5c5SAndroid Build Coastguard Worker bool ScratchBuffer::getImpl(size_t requestedSize,
124*8975f5c5SAndroid Build Coastguard Worker MemoryBuffer **memoryBufferOut,
125*8975f5c5SAndroid Build Coastguard Worker Optional<uint8_t> initValue)
126*8975f5c5SAndroid Build Coastguard Worker {
127*8975f5c5SAndroid Build Coastguard Worker mScratchMemory.setSizeToCapacity();
128*8975f5c5SAndroid Build Coastguard Worker
129*8975f5c5SAndroid Build Coastguard Worker if (mScratchMemory.size() == requestedSize)
130*8975f5c5SAndroid Build Coastguard Worker {
131*8975f5c5SAndroid Build Coastguard Worker mResetCounter = mLifetime;
132*8975f5c5SAndroid Build Coastguard Worker *memoryBufferOut = &mScratchMemory;
133*8975f5c5SAndroid Build Coastguard Worker return true;
134*8975f5c5SAndroid Build Coastguard Worker }
135*8975f5c5SAndroid Build Coastguard Worker
136*8975f5c5SAndroid Build Coastguard Worker if (mScratchMemory.size() > requestedSize)
137*8975f5c5SAndroid Build Coastguard Worker {
138*8975f5c5SAndroid Build Coastguard Worker tick();
139*8975f5c5SAndroid Build Coastguard Worker }
140*8975f5c5SAndroid Build Coastguard Worker
141*8975f5c5SAndroid Build Coastguard Worker if (mScratchMemory.size() < requestedSize)
142*8975f5c5SAndroid Build Coastguard Worker {
143*8975f5c5SAndroid Build Coastguard Worker if (!mScratchMemory.resize(requestedSize))
144*8975f5c5SAndroid Build Coastguard Worker {
145*8975f5c5SAndroid Build Coastguard Worker return false;
146*8975f5c5SAndroid Build Coastguard Worker }
147*8975f5c5SAndroid Build Coastguard Worker mResetCounter = mLifetime;
148*8975f5c5SAndroid Build Coastguard Worker if (initValue.valid())
149*8975f5c5SAndroid Build Coastguard Worker {
150*8975f5c5SAndroid Build Coastguard Worker mScratchMemory.fill(initValue.value());
151*8975f5c5SAndroid Build Coastguard Worker }
152*8975f5c5SAndroid Build Coastguard Worker }
153*8975f5c5SAndroid Build Coastguard Worker
154*8975f5c5SAndroid Build Coastguard Worker ASSERT(mScratchMemory.size() >= requestedSize);
155*8975f5c5SAndroid Build Coastguard Worker
156*8975f5c5SAndroid Build Coastguard Worker *memoryBufferOut = &mScratchMemory;
157*8975f5c5SAndroid Build Coastguard Worker return true;
158*8975f5c5SAndroid Build Coastguard Worker }
159*8975f5c5SAndroid Build Coastguard Worker
tick()160*8975f5c5SAndroid Build Coastguard Worker void ScratchBuffer::tick()
161*8975f5c5SAndroid Build Coastguard Worker {
162*8975f5c5SAndroid Build Coastguard Worker if (mResetCounter > 0)
163*8975f5c5SAndroid Build Coastguard Worker {
164*8975f5c5SAndroid Build Coastguard Worker --mResetCounter;
165*8975f5c5SAndroid Build Coastguard Worker if (mResetCounter == 0)
166*8975f5c5SAndroid Build Coastguard Worker {
167*8975f5c5SAndroid Build Coastguard Worker clear();
168*8975f5c5SAndroid Build Coastguard Worker }
169*8975f5c5SAndroid Build Coastguard Worker }
170*8975f5c5SAndroid Build Coastguard Worker }
171*8975f5c5SAndroid Build Coastguard Worker
clear()172*8975f5c5SAndroid Build Coastguard Worker void ScratchBuffer::clear()
173*8975f5c5SAndroid Build Coastguard Worker {
174*8975f5c5SAndroid Build Coastguard Worker mResetCounter = mLifetime;
175*8975f5c5SAndroid Build Coastguard Worker if (mScratchMemory.size() > 0)
176*8975f5c5SAndroid Build Coastguard Worker {
177*8975f5c5SAndroid Build Coastguard Worker mScratchMemory.clear();
178*8975f5c5SAndroid Build Coastguard Worker }
179*8975f5c5SAndroid Build Coastguard Worker }
180*8975f5c5SAndroid Build Coastguard Worker
181*8975f5c5SAndroid Build Coastguard Worker } // namespace angle
182