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