• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
14 namespace angle
15 {
16 
17 // MemoryBuffer implementation.
~MemoryBuffer()18 MemoryBuffer::~MemoryBuffer()
19 {
20     free(mData);
21     mData = nullptr;
22 }
23 
resize(size_t size)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 
fill(uint8_t datum)59 void MemoryBuffer::fill(uint8_t datum)
60 {
61     if (!empty())
62     {
63         std::fill(mData, mData + mSize, datum);
64     }
65 }
66 
MemoryBuffer(MemoryBuffer && other)67 MemoryBuffer::MemoryBuffer(MemoryBuffer &&other) : MemoryBuffer()
68 {
69     *this = std::move(other);
70 }
71 
operator =(MemoryBuffer && other)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 namespace
80 {
81 static constexpr uint32_t kDefaultScratchBufferLifetime = 1000u;
82 
83 }  // anonymous namespace
84 
85 // ScratchBuffer implementation.
ScratchBuffer()86 ScratchBuffer::ScratchBuffer() : ScratchBuffer(kDefaultScratchBufferLifetime) {}
87 
ScratchBuffer(uint32_t lifetime)88 ScratchBuffer::ScratchBuffer(uint32_t lifetime) : mLifetime(lifetime), mResetCounter(lifetime) {}
89 
~ScratchBuffer()90 ScratchBuffer::~ScratchBuffer() {}
91 
ScratchBuffer(ScratchBuffer && other)92 ScratchBuffer::ScratchBuffer(ScratchBuffer &&other)
93 {
94     *this = std::move(other);
95 }
96 
operator =(ScratchBuffer && other)97 ScratchBuffer &ScratchBuffer::operator=(ScratchBuffer &&other)
98 {
99     std::swap(mLifetime, other.mLifetime);
100     std::swap(mResetCounter, other.mResetCounter);
101     std::swap(mScratchMemory, other.mScratchMemory);
102     return *this;
103 }
104 
get(size_t requestedSize,MemoryBuffer ** memoryBufferOut)105 bool ScratchBuffer::get(size_t requestedSize, MemoryBuffer **memoryBufferOut)
106 {
107     return getImpl(requestedSize, memoryBufferOut, Optional<uint8_t>::Invalid());
108 }
109 
getInitialized(size_t requestedSize,MemoryBuffer ** memoryBufferOut,uint8_t initValue)110 bool ScratchBuffer::getInitialized(size_t requestedSize,
111                                    MemoryBuffer **memoryBufferOut,
112                                    uint8_t initValue)
113 {
114     return getImpl(requestedSize, memoryBufferOut, Optional<uint8_t>(initValue));
115 }
116 
getImpl(size_t requestedSize,MemoryBuffer ** memoryBufferOut,Optional<uint8_t> initValue)117 bool ScratchBuffer::getImpl(size_t requestedSize,
118                             MemoryBuffer **memoryBufferOut,
119                             Optional<uint8_t> initValue)
120 {
121     if (mScratchMemory.size() == requestedSize)
122     {
123         mResetCounter    = mLifetime;
124         *memoryBufferOut = &mScratchMemory;
125         return true;
126     }
127 
128     if (mScratchMemory.size() > requestedSize)
129     {
130         tick();
131     }
132 
133     if (mScratchMemory.size() < requestedSize)
134     {
135         if (!mScratchMemory.resize(requestedSize))
136         {
137             return false;
138         }
139         mResetCounter = mLifetime;
140         if (initValue.valid())
141         {
142             mScratchMemory.fill(initValue.value());
143         }
144     }
145 
146     ASSERT(mScratchMemory.size() >= requestedSize);
147 
148     *memoryBufferOut = &mScratchMemory;
149     return true;
150 }
151 
tick()152 void ScratchBuffer::tick()
153 {
154     if (mResetCounter > 0)
155     {
156         --mResetCounter;
157         if (mResetCounter == 0)
158         {
159             clear();
160         }
161     }
162 }
163 
clear()164 void ScratchBuffer::clear()
165 {
166     mResetCounter = mLifetime;
167     if (mScratchMemory.size() > 0)
168     {
169         mScratchMemory.clear();
170     }
171 }
172 
173 }  // namespace angle
174