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