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