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