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 ArrayBuffer (void) throw(); 52 ArrayBuffer (size_t numElements); 53 ArrayBuffer (const ArrayBuffer& other); 54 ~ArrayBuffer (void) throw(); 55 ArrayBuffer& operator= (const ArrayBuffer& other); 56 57 void clear (void) throw(); 58 void setStorage (size_t numElements); // !< \note after a succesful call buffer contents are undefined 59 void swap (ArrayBuffer& other) throw(); 60 size_t size (void) const throw(); 61 bool empty (void) const throw(); 62 63 T* getElementPtr (size_t elementNdx) throw(); 64 const T* getElementPtr (size_t elementNdx) const throw(); 65 void* getPtr (void) throw(); 66 const void* getPtr (void) const throw(); 67 68 private: 69 void* m_ptr; 70 size_t m_cap; 71 }; 72 73 template <typename T, size_t Alignment, size_t Stride> 74 ArrayBuffer<T,Alignment,Stride>::ArrayBuffer (void) throw() 75 : m_ptr (DE_NULL) 76 , m_cap (0) 77 { 78 } 79 80 template <typename T, size_t Alignment, size_t Stride> 81 ArrayBuffer<T,Alignment,Stride>::ArrayBuffer (size_t numElements) 82 : m_ptr (DE_NULL) 83 , m_cap (0) 84 { 85 if (numElements) 86 { 87 // \note no need to allocate stride for the last element, sizeof(T) is enough. Also handles cases where sizeof(T) > Stride 88 const size_t storageSize = (numElements - 1) * Stride + sizeof(T); 89 void* const ptr = detail::ArrayBuffer_AlignedMalloc(storageSize, Alignment); 90 91 if (!ptr) 92 throw std::bad_alloc(); 93 94 m_ptr = ptr; 95 m_cap = numElements; 96 } 97 } 98 99 template <typename T, size_t Alignment, size_t Stride> 100 ArrayBuffer<T,Alignment,Stride>::ArrayBuffer (const ArrayBuffer<T,Alignment,Stride>& other) 101 : m_ptr (DE_NULL) 102 , m_cap (0) 103 { 104 if (other.m_cap) 105 { 106 // copy to temporary and swap to it 107 108 const size_t storageSize = (other.m_cap - 1) * Stride + sizeof(T); 109 ArrayBuffer tmp (other.m_cap); 110 111 deMemcpy(tmp.m_ptr, other.m_ptr, (int)storageSize); 112 swap(tmp); 113 } 114 } 115 116 template <typename T, size_t Alignment, size_t Stride> 117 ArrayBuffer<T,Alignment,Stride>::~ArrayBuffer (void) throw() 118 { 119 clear(); 120 } 121 122 template <typename T, size_t Alignment, size_t Stride> 123 ArrayBuffer<T,Alignment,Stride>& ArrayBuffer<T,Alignment,Stride>::operator= (const ArrayBuffer& other) 124 { 125 ArrayBuffer copied(other); 126 swap(copied); 127 return *this; 128 } 129 130 template <typename T, size_t Alignment, size_t Stride> 131 void ArrayBuffer<T,Alignment,Stride>::clear (void) throw() 132 { 133 detail::ArrayBuffer_AlignedFree(m_ptr); 134 135 m_ptr = DE_NULL; 136 m_cap = 0; 137 } 138 139 template <typename T, size_t Alignment, size_t Stride> 140 void ArrayBuffer<T,Alignment,Stride>::setStorage (size_t numElements) 141 { 142 // create new buffer of the wanted size, swap to it 143 ArrayBuffer<T,Alignment,Stride> newBuffer(numElements); 144 swap(newBuffer); 145 } 146 147 template <typename T, size_t Alignment, size_t Stride> 148 void ArrayBuffer<T,Alignment,Stride>::swap (ArrayBuffer& other) throw() 149 { 150 void* const otherPtr = other.m_ptr; 151 const size_t otherCap = other.m_cap; 152 153 other.m_ptr = m_ptr; 154 other.m_cap = m_cap; 155 m_ptr = otherPtr; 156 m_cap = otherCap; 157 } 158 159 template <typename T, size_t Alignment, size_t Stride> 160 size_t ArrayBuffer<T,Alignment,Stride>::size (void) const throw() 161 { 162 return m_cap; 163 } 164 165 template <typename T, size_t Alignment, size_t Stride> 166 bool ArrayBuffer<T,Alignment,Stride>::empty (void) const throw() 167 { 168 return size() == 0; 169 } 170 171 template <typename T, size_t Alignment, size_t Stride> 172 T* ArrayBuffer<T,Alignment,Stride>::getElementPtr (size_t elementNdx) throw() 173 { 174 return (T*)(((deUint8*)m_ptr) + Stride * elementNdx); 175 } 176 177 template <typename T, size_t Alignment, size_t Stride> 178 const T* ArrayBuffer<T,Alignment,Stride>::getElementPtr (size_t elementNdx) const throw() 179 { 180 return (T*)(((deUint8*)m_ptr) + Stride * elementNdx); 181 } 182 183 template <typename T, size_t Alignment, size_t Stride> 184 void* ArrayBuffer<T,Alignment,Stride>::getPtr (void) throw() 185 { 186 return m_ptr; 187 } 188 189 template <typename T, size_t Alignment, size_t Stride> 190 const void* ArrayBuffer<T,Alignment,Stride>::getPtr (void) const throw() 191 { 192 return m_ptr; 193 } 194 195 } // de 196 197 #endif // _DEARRAYBUFFER_HPP 198