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
14namespace angle
15{
16
17// MemoryBuffer implementation.
18MemoryBuffer::~MemoryBuffer()
19{
20 free(mData);
21 mData = nullptr;
22}
23
24bool 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
59void MemoryBuffer::fill(uint8_t datum)
60{
61 if (!empty())
62 {
63 std::fill(mData, mData + mSize, datum);
64 }
65}
66
67MemoryBuffer::MemoryBuffer(MemoryBuffer &&other) : MemoryBuffer()
68{
69 *this = std::move(other);
70}
71
72MemoryBuffer &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
81ScratchBuffer::ScratchBuffer(uint32_t lifetime) : mLifetime(lifetime), mResetCounter(lifetime) {}
82
83ScratchBuffer::~ScratchBuffer() {}
84
85bool ScratchBuffer::get(size_t requestedSize, MemoryBuffer **memoryBufferOut)
86{
87 return getImpl(requestedSize, memoryBufferOut, Optional<uint8_t>::Invalid());
88}
89
90bool ScratchBuffer::getInitialized(size_t requestedSize,
91 MemoryBuffer **memoryBufferOut,
92 uint8_t initValue)
93{
94 return getImpl(requestedSize, memoryBufferOut, Optional<uint8_t>(initValue));
95}
96
97bool 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
133void ScratchBuffer::tick()
134{
135 if (mResetCounter > 0)
136 {
137 --mResetCounter;
138 }
139}
140
141void ScratchBuffer::clear()
142{
143 mResetCounter = mLifetime;
144 mScratchMemory.resize(0);
145}
146
147} // namespace angle
148