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