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 #ifndef COMMON_MEMORYBUFFER_H_ 8 #define COMMON_MEMORYBUFFER_H_ 9 10 #include "common/Optional.h" 11 #include "common/angleutils.h" 12 #include "common/debug.h" 13 14 #include <stdint.h> 15 #include <cstddef> 16 17 namespace angle 18 { 19 20 class MemoryBuffer final : NonCopyable 21 { 22 public: 23 MemoryBuffer() = default; 24 ~MemoryBuffer(); 25 26 MemoryBuffer(MemoryBuffer &&other); 27 MemoryBuffer &operator=(MemoryBuffer &&other); 28 29 // Destroy underlying memory 30 void destroy(); 31 32 // Updates mSize to newSize. Updates mCapacity iff newSize > mCapacity 33 [[nodiscard]] bool resize(size_t newSize); 34 35 // Resets mSize to 0. Reserves memory and updates mCapacity iff newSize > mCapacity 36 [[nodiscard]] bool clearAndReserve(size_t newSize); 37 38 // Updates mCapacity iff newSize > mCapacity 39 [[nodiscard]] bool reserve(size_t newSize); 40 41 // Appends content from "other" MemoryBuffer 42 [[nodiscard]] bool append(const MemoryBuffer &other); 43 // Appends content from "[buffer, buffer + bufferSize)" 44 [[nodiscard]] bool appendRaw(const uint8_t *buffer, const size_t bufferSize); 45 46 // Sets size bound by capacity. setSize(size_t size)47 void setSize(size_t size) 48 { 49 ASSERT(size <= mCapacity); 50 mSize = size; 51 } setSizeToCapacity()52 void setSizeToCapacity() { setSize(mCapacity); } 53 54 // Invalidate current content clear()55 void clear() { (void)resize(0); } 56 size()57 size_t size() const { return mSize; } capacity()58 size_t capacity() const { return mCapacity; } empty()59 bool empty() const { return mSize == 0; } 60 data()61 const uint8_t *data() const { return mData; } data()62 uint8_t *data() 63 { 64 ASSERT(mData); 65 return mData; 66 } 67 68 uint8_t &operator[](size_t pos) 69 { 70 ASSERT(mData && pos < mSize); 71 return mData[pos]; 72 } 73 const uint8_t &operator[](size_t pos) const 74 { 75 ASSERT(mData && pos < mSize); 76 return mData[pos]; 77 } 78 79 void fill(uint8_t datum); 80 81 // Only used by unit tests 82 // Validate total bytes allocated during a resize assertTotalAllocatedBytes(size_t totalAllocatedBytes)83 void assertTotalAllocatedBytes(size_t totalAllocatedBytes) const 84 { 85 #if defined(ANGLE_ENABLE_ASSERTS) 86 ASSERT(totalAllocatedBytes == mTotalAllocatedBytes); 87 #endif // ANGLE_ENABLE_ASSERTS 88 } 89 // Validate total bytes copied during a resize assertTotalCopiedBytes(size_t totalCopiedBytes)90 void assertTotalCopiedBytes(size_t totalCopiedBytes) const 91 { 92 #if defined(ANGLE_ENABLE_ASSERTS) 93 ASSERT(totalCopiedBytes == mTotalCopiedBytes); 94 #endif // ANGLE_ENABLE_ASSERTS 95 } 96 97 private: 98 size_t mSize = 0; 99 size_t mCapacity = 0; 100 uint8_t *mData = nullptr; 101 #if defined(ANGLE_ENABLE_ASSERTS) 102 size_t mTotalAllocatedBytes = 0; 103 size_t mTotalCopiedBytes = 0; 104 #endif // ANGLE_ENABLE_ASSERTS 105 }; 106 107 class ScratchBuffer final : NonCopyable 108 { 109 public: 110 ScratchBuffer(); 111 // If we request a scratch buffer requesting a smaller size this many times, release and 112 // recreate the scratch buffer. This ensures we don't have a degenerate case where we are stuck 113 // hogging memory. 114 ScratchBuffer(uint32_t lifetime); 115 ~ScratchBuffer(); 116 117 ScratchBuffer(ScratchBuffer &&other); 118 ScratchBuffer &operator=(ScratchBuffer &&other); 119 120 // Returns true with a memory buffer of the requested size, or false on failure. 121 bool get(size_t requestedSize, MemoryBuffer **memoryBufferOut); 122 123 // Same as get, but ensures new values are initialized to a fixed constant. 124 bool getInitialized(size_t requestedSize, MemoryBuffer **memoryBufferOut, uint8_t initValue); 125 126 // Ticks the release counter for the scratch buffer. Also done implicitly in get(). 127 void tick(); 128 129 void clear(); 130 getMemoryBuffer()131 MemoryBuffer *getMemoryBuffer() { return &mScratchMemory; } 132 133 private: 134 bool getImpl(size_t requestedSize, MemoryBuffer **memoryBufferOut, Optional<uint8_t> initValue); 135 136 uint32_t mLifetime; 137 uint32_t mResetCounter; 138 MemoryBuffer mScratchMemory; 139 }; 140 141 } // namespace angle 142 143 #endif // COMMON_MEMORYBUFFER_H_ 144