Merge "Report tests using Draw*BaseVertex as NotSupported" am: f96636fdfa
[platform/upstream/VK-GL-CTS.git] / framework / delibs / decpp / deArrayBuffer.hpp
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 } // 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>
77 ArrayBuffer<T,Alignment,Stride>::ArrayBuffer (void) throw()
78         : m_ptr (DE_NULL)
79         , m_cap (0)
80 {
81 }
82
83 template <typename T, size_t Alignment, size_t Stride>
84 ArrayBuffer<T,Alignment,Stride>::ArrayBuffer (size_t numElements)
85         : m_ptr (DE_NULL)
86         , m_cap (0)
87 {
88         if (numElements)
89         {
90                 // \note no need to allocate stride for the last element, sizeof(T) is enough. Also handles cases where sizeof(T) > Stride
91                 const size_t    storageSize     = (numElements - 1) * Stride + sizeof(T);
92                 void* const             ptr                     = detail::ArrayBuffer_AlignedMalloc(storageSize, Alignment);
93
94                 if (!ptr)
95                         throw std::bad_alloc();
96
97                 m_ptr = ptr;
98                 m_cap = numElements;
99         }
100 }
101
102 template <typename T, size_t Alignment, size_t Stride>
103 ArrayBuffer<T,Alignment,Stride>::ArrayBuffer (const T* ptr, size_t numElements)
104         : m_ptr (DE_NULL)
105         , m_cap (0)
106 {
107         if (numElements)
108         {
109                 // create new buffer of wanted size, copy to it, and swap to it
110                 ArrayBuffer<T,Alignment,Stride> tmp(numElements);
111
112                 if (Stride == sizeof(T))
113                 {
114                         // tightly packed
115                         const size_t storageSize = sizeof(T) * numElements;
116                         deMemcpy(tmp.m_ptr, ptr, (int)storageSize);
117                 }
118                 else
119                 {
120                         // sparsely packed
121                         for (size_t ndx = 0; ndx < numElements; ++ndx)
122                                 *tmp.getElementPtr(ndx) = ptr[ndx];
123                 }
124
125                 swap(tmp);
126         }
127 }
128
129 template <typename T, size_t Alignment, size_t Stride>
130 ArrayBuffer<T,Alignment,Stride>::ArrayBuffer (const ArrayBuffer<T,Alignment,Stride>& other)
131         : m_ptr (DE_NULL)
132         , m_cap (0)
133 {
134         if (other.m_cap)
135         {
136                 // copy to temporary and swap to it
137
138                 const size_t    storageSize =   (other.m_cap - 1) * Stride + sizeof(T);
139                 ArrayBuffer             tmp                             (other.m_cap);
140
141                 deMemcpy(tmp.m_ptr, other.m_ptr, (int)storageSize);
142                 swap(tmp);
143         }
144 }
145
146 template <typename T, size_t Alignment, size_t Stride>
147 ArrayBuffer<T,Alignment,Stride>::~ArrayBuffer (void) throw()
148 {
149         clear();
150 }
151
152 template <typename T, size_t Alignment, size_t Stride>
153 ArrayBuffer<T,Alignment,Stride>& ArrayBuffer<T,Alignment,Stride>::operator= (const ArrayBuffer& other)
154 {
155         ArrayBuffer copied(other);
156         swap(copied);
157         return *this;
158 }
159
160 template <typename T, size_t Alignment, size_t Stride>
161 void ArrayBuffer<T,Alignment,Stride>::clear (void) throw()
162 {
163         detail::ArrayBuffer_AlignedFree(m_ptr);
164
165         m_ptr = DE_NULL;
166         m_cap = 0;
167 }
168
169 template <typename T, size_t Alignment, size_t Stride>
170 void ArrayBuffer<T,Alignment,Stride>::setStorage (size_t numElements)
171 {
172         // create new buffer of the wanted size, swap to it
173         ArrayBuffer<T,Alignment,Stride> newBuffer(numElements);
174         swap(newBuffer);
175 }
176
177 template <typename T, size_t Alignment, size_t Stride>
178 void ArrayBuffer<T,Alignment,Stride>::swap (ArrayBuffer& other) throw()
179 {
180         void* const             otherPtr = other.m_ptr;
181         const size_t    otherCap = other.m_cap;
182
183         other.m_ptr = m_ptr;
184         other.m_cap = m_cap;
185         m_ptr           = otherPtr;
186         m_cap           = otherCap;
187 }
188
189 template <typename T, size_t Alignment, size_t Stride>
190 size_t ArrayBuffer<T,Alignment,Stride>::size (void) const throw()
191 {
192         return m_cap;
193 }
194
195 template <typename T, size_t Alignment, size_t Stride>
196 bool ArrayBuffer<T,Alignment,Stride>::empty (void) const throw()
197 {
198         return size() == 0;
199 }
200
201 template <typename T, size_t Alignment, size_t Stride>
202 T* ArrayBuffer<T,Alignment,Stride>::getElementPtr (size_t elementNdx) throw()
203 {
204         return (T*)(((deUint8*)m_ptr) + Stride * elementNdx);
205 }
206
207 template <typename T, size_t Alignment, size_t Stride>
208 const T* ArrayBuffer<T,Alignment,Stride>::getElementPtr (size_t elementNdx) const throw()
209 {
210         return (T*)(((deUint8*)m_ptr) + Stride * elementNdx);
211 }
212
213 template <typename T, size_t Alignment, size_t Stride>
214 void* ArrayBuffer<T,Alignment,Stride>::getPtr (void) throw()
215 {
216         return m_ptr;
217 }
218
219 template <typename T, size_t Alignment, size_t Stride>
220 const void* ArrayBuffer<T,Alignment,Stride>::getPtr (void) const throw()
221 {
222         return m_ptr;
223 }
224
225 } // de
226
227 #endif // _DEARRAYBUFFER_HPP