1 #include "precompiled.h" 2 // 3 // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. 4 // Use of this source code is governed by a BSD-style license that can be 5 // found in the LICENSE file. 6 // 7 8 // VertexBuffer.cpp: Defines the abstract VertexBuffer class and VertexBufferInterface 9 // class with derivations, classes that perform graphics API agnostic vertex buffer operations. 10 11 #include "libGLESv2/renderer/VertexBuffer.h" 12 #include "libGLESv2/renderer/Renderer.h" 13 #include "libGLESv2/Context.h" 14 15 namespace rx 16 { 17 18 unsigned int VertexBuffer::mNextSerial = 1; 19 20 VertexBuffer::VertexBuffer() 21 { 22 updateSerial(); 23 } 24 25 VertexBuffer::~VertexBuffer() 26 { 27 } 28 29 void VertexBuffer::updateSerial() 30 { 31 mSerial = mNextSerial++; 32 } 33 34 unsigned int VertexBuffer::getSerial() const 35 { 36 return mSerial; 37 } 38 39 VertexBufferInterface::VertexBufferInterface(rx::Renderer *renderer, bool dynamic) : mRenderer(renderer) 40 { 41 mDynamic = dynamic; 42 mWritePosition = 0; 43 mReservedSpace = 0; 44 45 mVertexBuffer = renderer->createVertexBuffer(); 46 } 47 48 VertexBufferInterface::~VertexBufferInterface() 49 { 50 delete mVertexBuffer; 51 } 52 53 unsigned int VertexBufferInterface::getSerial() const 54 { 55 return mVertexBuffer->getSerial(); 56 } 57 58 unsigned int VertexBufferInterface::getBufferSize() const 59 { 60 return mVertexBuffer->getBufferSize(); 61 } 62 63 bool VertexBufferInterface::setBufferSize(unsigned int size) 64 { 65 if (mVertexBuffer->getBufferSize() == 0) 66 { 67 return mVertexBuffer->initialize(size, mDynamic); 68 } 69 else 70 { 71 return mVertexBuffer->setBufferSize(size); 72 } 73 } 74 75 unsigned int VertexBufferInterface::getWritePosition() const 76 { 77 return mWritePosition; 78 } 79 80 void VertexBufferInterface::setWritePosition(unsigned int writePosition) 81 { 82 mWritePosition = writePosition; 83 } 84 85 bool VertexBufferInterface::discard() 86 { 87 return mVertexBuffer->discard(); 88 } 89 90 bool VertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances, 91 unsigned int *outStreamOffset) 92 { 93 unsigned int spaceRequired; 94 if (!mVertexBuffer->getSpaceRequired(attrib, count, instances, &spaceRequired)) 95 { 96 return false; 97 } 98 99 if (mWritePosition + spaceRequired < mWritePosition) 100 { 101 return false; 102 } 103 104 if (!reserveSpace(mReservedSpace)) 105 { 106 return false; 107 } 108 mReservedSpace = 0; 109 110 if (!mVertexBuffer->storeVertexAttributes(attrib, start, count, instances, mWritePosition)) 111 { 112 return false; 113 } 114 115 if (outStreamOffset) 116 { 117 *outStreamOffset = mWritePosition; 118 } 119 120 mWritePosition += spaceRequired; 121 122 return true; 123 } 124 125 bool VertexBufferInterface::storeRawData(const void* data, unsigned int size, unsigned int *outStreamOffset) 126 { 127 if (mWritePosition + size < mWritePosition) 128 { 129 return false; 130 } 131 132 if (!reserveSpace(mReservedSpace)) 133 { 134 return false; 135 } 136 mReservedSpace = 0; 137 138 if (!mVertexBuffer->storeRawData(data, size, mWritePosition)) 139 { 140 return false; 141 } 142 143 if (outStreamOffset) 144 { 145 *outStreamOffset = mWritePosition; 146 } 147 148 mWritePosition += size; 149 150 return true; 151 } 152 153 bool VertexBufferInterface::reserveVertexSpace(const gl::VertexAttribute &attribute, GLsizei count, GLsizei instances) 154 { 155 unsigned int requiredSpace; 156 if (!mVertexBuffer->getSpaceRequired(attribute, count, instances, &requiredSpace)) 157 { 158 return false; 159 } 160 161 // Protect against integer overflow 162 if (mReservedSpace + requiredSpace < mReservedSpace) 163 { 164 return false; 165 } 166 167 mReservedSpace += requiredSpace; 168 return true; 169 } 170 171 bool VertexBufferInterface::reserveRawDataSpace(unsigned int size) 172 { 173 // Protect against integer overflow 174 if (mReservedSpace + size < mReservedSpace) 175 { 176 return false; 177 } 178 179 mReservedSpace += size; 180 return true; 181 } 182 183 VertexBuffer* VertexBufferInterface::getVertexBuffer() const 184 { 185 return mVertexBuffer; 186 } 187 188 189 StreamingVertexBufferInterface::StreamingVertexBufferInterface(rx::Renderer *renderer, std::size_t initialSize) : VertexBufferInterface(renderer, true) 190 { 191 setBufferSize(initialSize); 192 } 193 194 StreamingVertexBufferInterface::~StreamingVertexBufferInterface() 195 { 196 } 197 198 bool StreamingVertexBufferInterface::reserveSpace(unsigned int size) 199 { 200 bool result = true; 201 unsigned int curBufferSize = getBufferSize(); 202 if (size > curBufferSize) 203 { 204 result = setBufferSize(std::max(size, 3 * curBufferSize / 2)); 205 setWritePosition(0); 206 } 207 else if (getWritePosition() + size > curBufferSize) 208 { 209 if (!discard()) 210 { 211 return false; 212 } 213 setWritePosition(0); 214 } 215 216 return result; 217 } 218 219 StaticVertexBufferInterface::StaticVertexBufferInterface(rx::Renderer *renderer) : VertexBufferInterface(renderer, false) 220 { 221 } 222 223 StaticVertexBufferInterface::~StaticVertexBufferInterface() 224 { 225 } 226 227 bool StaticVertexBufferInterface::lookupAttribute(const gl::VertexAttribute &attribute, unsigned int *outStreamOffset) 228 { 229 for (unsigned int element = 0; element < mCache.size(); element++) 230 { 231 if (mCache[element].type == attribute.mType && 232 mCache[element].size == attribute.mSize && 233 mCache[element].stride == attribute.stride() && 234 mCache[element].normalized == attribute.mNormalized) 235 { 236 if (mCache[element].attributeOffset == attribute.mOffset % attribute.stride()) 237 { 238 if (outStreamOffset) 239 { 240 *outStreamOffset = mCache[element].streamOffset; 241 } 242 return true; 243 } 244 } 245 } 246 247 return false; 248 } 249 250 bool StaticVertexBufferInterface::reserveSpace(unsigned int size) 251 { 252 unsigned int curSize = getBufferSize(); 253 if (curSize == 0) 254 { 255 setBufferSize(size); 256 return true; 257 } 258 else if (curSize >= size) 259 { 260 return true; 261 } 262 else 263 { 264 UNREACHABLE(); // Static vertex buffers can't be resized 265 return false; 266 } 267 } 268 269 bool StaticVertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances, 270 unsigned int *outStreamOffset) 271 { 272 unsigned int streamOffset; 273 if (VertexBufferInterface::storeVertexAttributes(attrib, start, count, instances, &streamOffset)) 274 { 275 int attributeOffset = attrib.mOffset % attrib.stride(); 276 VertexElement element = { attrib.mType, attrib.mSize, attrib.stride(), attrib.mNormalized, attributeOffset, streamOffset }; 277 mCache.push_back(element); 278 279 if (outStreamOffset) 280 { 281 *outStreamOffset = streamOffset; 282 } 283 284 return true; 285 } 286 else 287 { 288 return false; 289 } 290 } 291 292 } 293