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 31namespace de 32{ 33namespace detail 34{ 35 36void* ArrayBuffer_AlignedMalloc (size_t numBytes, size_t alignment); 37void ArrayBuffer_AlignedFree (void*); 38 39} // detail 40 41//! Array buffer self-test. 42void ArrayBuffer_selfTest (void); 43 44/*--------------------------------------------------------------------*//*! 45 * \brief Contiguous array that does not initialize its elements. 46 *//*--------------------------------------------------------------------*/ 47template <typename T, size_t Alignment = (sizeof(T) > 4 ? 4 : sizeof(T)), size_t Stride = sizeof(T)> 48class ArrayBuffer 49{ 50public: 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 68private: 69 void* m_ptr; 70 size_t m_cap; 71}; 72 73template <typename T, size_t Alignment, size_t Stride> 74ArrayBuffer<T,Alignment,Stride>::ArrayBuffer (void) throw() 75 : m_ptr (DE_NULL) 76 , m_cap (0) 77{ 78} 79 80template <typename T, size_t Alignment, size_t Stride> 81ArrayBuffer<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 99template <typename T, size_t Alignment, size_t Stride> 100ArrayBuffer<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 116template <typename T, size_t Alignment, size_t Stride> 117ArrayBuffer<T,Alignment,Stride>::~ArrayBuffer (void) throw() 118{ 119 clear(); 120} 121 122template <typename T, size_t Alignment, size_t Stride> 123ArrayBuffer<T,Alignment,Stride>& ArrayBuffer<T,Alignment,Stride>::operator= (const ArrayBuffer& other) 124{ 125 ArrayBuffer copied(other); 126 swap(copied); 127 return *this; 128} 129 130template <typename T, size_t Alignment, size_t Stride> 131void 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 139template <typename T, size_t Alignment, size_t Stride> 140void 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 147template <typename T, size_t Alignment, size_t Stride> 148void 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 159template <typename T, size_t Alignment, size_t Stride> 160size_t ArrayBuffer<T,Alignment,Stride>::size (void) const throw() 161{ 162 return m_cap; 163} 164 165template <typename T, size_t Alignment, size_t Stride> 166bool ArrayBuffer<T,Alignment,Stride>::empty (void) const throw() 167{ 168 return size() == 0; 169} 170 171template <typename T, size_t Alignment, size_t Stride> 172T* ArrayBuffer<T,Alignment,Stride>::getElementPtr (size_t elementNdx) throw() 173{ 174 return (T*)(((deUint8*)m_ptr) + Stride * elementNdx); 175} 176 177template <typename T, size_t Alignment, size_t Stride> 178const T* ArrayBuffer<T,Alignment,Stride>::getElementPtr (size_t elementNdx) const throw() 179{ 180 return (T*)(((deUint8*)m_ptr) + Stride * elementNdx); 181} 182 183template <typename T, size_t Alignment, size_t Stride> 184void* ArrayBuffer<T,Alignment,Stride>::getPtr (void) throw() 185{ 186 return m_ptr; 187} 188 189template <typename T, size_t Alignment, size_t Stride> 190const void* ArrayBuffer<T,Alignment,Stride>::getPtr (void) const throw() 191{ 192 return m_ptr; 193} 194 195} // de 196 197#endif // _DEARRAYBUFFER_HPP 198