• 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 #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