xref: /aosp_15_r20/external/deqp/framework/delibs/decpp/deArrayBuffer.hpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 #ifndef _DEARRAYBUFFER_HPP
2 #define _DEARRAYBUFFER_HPP
3 /*-------------------------------------------------------------------------
4  * drawElements C++ Base Library
5  * -----------------------------
6  *
7  * Copyright 2014 The Android Open Source Project
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Array buffer
24  *//*--------------------------------------------------------------------*/
25 
26 #include "deDefs.hpp"
27 #include "deMemory.h"
28 
29 #include <new>
30 
31 namespace de
32 {
33 namespace detail
34 {
35 
36 void *ArrayBuffer_AlignedMalloc(size_t numBytes, size_t alignment);
37 void ArrayBuffer_AlignedFree(void *);
38 
39 } // namespace detail
40 
41 //! Array buffer self-test.
42 void ArrayBuffer_selfTest(void);
43 
44 /*--------------------------------------------------------------------*//*!
45  * \brief Contiguous array that does not initialize its elements.
46  *//*--------------------------------------------------------------------*/
47 template <typename T, size_t Alignment = (sizeof(T) > 4 ? 4 : sizeof(T)), size_t Stride = sizeof(T)>
48 class ArrayBuffer
49 {
50 public:
51     DE_STATIC_ASSERT(Stride >= sizeof(T));
52 
53     ArrayBuffer(void) throw();
54     ArrayBuffer(size_t numElements);
55     ArrayBuffer(const T *ptr, size_t numElements);
56     ArrayBuffer(const ArrayBuffer &other);
57     ~ArrayBuffer(void) throw();
58     ArrayBuffer &operator=(const ArrayBuffer &other);
59 
60     void clear(void) throw();
61     void setStorage(size_t numElements); // !< \note after a succesful call buffer contents are undefined
62     void swap(ArrayBuffer &other) throw();
63     size_t size(void) const throw();
64     bool empty(void) const throw();
65 
66     T *getElementPtr(size_t elementNdx) throw();
67     const T *getElementPtr(size_t elementNdx) const throw();
68     void *getPtr(void) throw();
69     const void *getPtr(void) const throw();
70 
71 private:
72     void *m_ptr;
73     size_t m_cap;
74 } DE_WARN_UNUSED_TYPE;
75 
76 template <typename T, size_t Alignment, size_t Stride>
ArrayBuffer(void)77 ArrayBuffer<T, Alignment, Stride>::ArrayBuffer(void) throw() : m_ptr(DE_NULL)
78                                                              , m_cap(0)
79 {
80 }
81 
82 template <typename T, size_t Alignment, size_t Stride>
ArrayBuffer(size_t numElements)83 ArrayBuffer<T, Alignment, Stride>::ArrayBuffer(size_t numElements) : m_ptr(DE_NULL)
84                                                                    , m_cap(0)
85 {
86     if (numElements)
87     {
88         // \note no need to allocate stride for the last element, sizeof(T) is enough. Also handles cases where sizeof(T) > Stride
89         const size_t storageSize = (numElements - 1) * Stride + sizeof(T);
90         void *const ptr          = detail::ArrayBuffer_AlignedMalloc(storageSize, Alignment);
91 
92         if (!ptr)
93             throw std::bad_alloc();
94 
95         m_ptr = ptr;
96         m_cap = numElements;
97     }
98 }
99 
100 template <typename T, size_t Alignment, size_t Stride>
ArrayBuffer(const T * ptr,size_t numElements)101 ArrayBuffer<T, Alignment, Stride>::ArrayBuffer(const T *ptr, size_t numElements) : m_ptr(DE_NULL)
102                                                                                  , m_cap(0)
103 {
104     if (numElements)
105     {
106         // create new buffer of wanted size, copy to it, and swap to it
107         ArrayBuffer<T, Alignment, Stride> tmp(numElements);
108 
109         if (Stride == sizeof(T))
110         {
111             // tightly packed
112             const size_t storageSize = sizeof(T) * numElements;
113             deMemcpy(tmp.m_ptr, ptr, (int)storageSize);
114         }
115         else
116         {
117             // sparsely packed
118             for (size_t ndx = 0; ndx < numElements; ++ndx)
119                 *tmp.getElementPtr(ndx) = ptr[ndx];
120         }
121 
122         swap(tmp);
123     }
124 }
125 
126 template <typename T, size_t Alignment, size_t Stride>
ArrayBuffer(const ArrayBuffer<T,Alignment,Stride> & other)127 ArrayBuffer<T, Alignment, Stride>::ArrayBuffer(const ArrayBuffer<T, Alignment, Stride> &other)
128     : m_ptr(DE_NULL)
129     , m_cap(0)
130 {
131     if (other.m_cap)
132     {
133         // copy to temporary and swap to it
134 
135         const size_t storageSize = (other.m_cap - 1) * Stride + sizeof(T);
136         ArrayBuffer tmp(other.m_cap);
137 
138         deMemcpy(tmp.m_ptr, other.m_ptr, (int)storageSize);
139         swap(tmp);
140     }
141 }
142 
143 template <typename T, size_t Alignment, size_t Stride>
~ArrayBuffer(void)144 ArrayBuffer<T, Alignment, Stride>::~ArrayBuffer(void) throw()
145 {
146     clear();
147 }
148 
149 template <typename T, size_t Alignment, size_t Stride>
operator =(const ArrayBuffer & other)150 ArrayBuffer<T, Alignment, Stride> &ArrayBuffer<T, Alignment, Stride>::operator=(const ArrayBuffer &other)
151 {
152     ArrayBuffer copied(other);
153     swap(copied);
154     return *this;
155 }
156 
157 template <typename T, size_t Alignment, size_t Stride>
clear(void)158 void ArrayBuffer<T, Alignment, Stride>::clear(void) throw()
159 {
160     detail::ArrayBuffer_AlignedFree(m_ptr);
161 
162     m_ptr = DE_NULL;
163     m_cap = 0;
164 }
165 
166 template <typename T, size_t Alignment, size_t Stride>
setStorage(size_t numElements)167 void ArrayBuffer<T, Alignment, Stride>::setStorage(size_t numElements)
168 {
169     // create new buffer of the wanted size, swap to it
170     ArrayBuffer<T, Alignment, Stride> newBuffer(numElements);
171     swap(newBuffer);
172 }
173 
174 template <typename T, size_t Alignment, size_t Stride>
swap(ArrayBuffer & other)175 void ArrayBuffer<T, Alignment, Stride>::swap(ArrayBuffer &other) throw()
176 {
177     void *const otherPtr  = other.m_ptr;
178     const size_t otherCap = other.m_cap;
179 
180     other.m_ptr = m_ptr;
181     other.m_cap = m_cap;
182     m_ptr       = otherPtr;
183     m_cap       = otherCap;
184 }
185 
186 template <typename T, size_t Alignment, size_t Stride>
size(void) const187 size_t ArrayBuffer<T, Alignment, Stride>::size(void) const throw()
188 {
189     return m_cap;
190 }
191 
192 template <typename T, size_t Alignment, size_t Stride>
empty(void) const193 bool ArrayBuffer<T, Alignment, Stride>::empty(void) const throw()
194 {
195     return size() == 0;
196 }
197 
198 template <typename T, size_t Alignment, size_t Stride>
getElementPtr(size_t elementNdx)199 T *ArrayBuffer<T, Alignment, Stride>::getElementPtr(size_t elementNdx) throw()
200 {
201     return (T *)(((uint8_t *)m_ptr) + Stride * elementNdx);
202 }
203 
204 template <typename T, size_t Alignment, size_t Stride>
getElementPtr(size_t elementNdx) const205 const T *ArrayBuffer<T, Alignment, Stride>::getElementPtr(size_t elementNdx) const throw()
206 {
207     return (T *)(((uint8_t *)m_ptr) + Stride * elementNdx);
208 }
209 
210 template <typename T, size_t Alignment, size_t Stride>
getPtr(void)211 void *ArrayBuffer<T, Alignment, Stride>::getPtr(void) throw()
212 {
213     return m_ptr;
214 }
215 
216 template <typename T, size_t Alignment, size_t Stride>
getPtr(void) const217 const void *ArrayBuffer<T, Alignment, Stride>::getPtr(void) const throw()
218 {
219     return m_ptr;
220 }
221 
222 } // namespace de
223 
224 #endif // _DEARRAYBUFFER_HPP
225