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 228