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 // VertexBuffer9.cpp: Defines the D3D9 VertexBuffer implementation. 9 10 #include "libGLESv2/renderer/d3d9/VertexBuffer9.h" 11 #include "libGLESv2/renderer/vertexconversion.h" 12 #include "libGLESv2/renderer/BufferStorage.h" 13 #include "libGLESv2/VertexAttribute.h" 14 #include "libGLESv2/renderer/d3d9/Renderer9.h" 15 #include "libGLESv2/renderer/d3d9/formatutils9.h" 16 17 #include "libGLESv2/Buffer.h" 18 19 namespace rx 20 { 21 22 VertexBuffer9::VertexBuffer9(rx::Renderer9 *const renderer) : mRenderer(renderer) 23 { 24 mVertexBuffer = NULL; 25 mBufferSize = 0; 26 mDynamicUsage = false; 27 } 28 29 VertexBuffer9::~VertexBuffer9() 30 { 31 SafeRelease(mVertexBuffer); 32 } 33 34 bool VertexBuffer9::initialize(unsigned int size, bool dynamicUsage) 35 { 36 SafeRelease(mVertexBuffer); 37 38 updateSerial(); 39 40 if (size > 0) 41 { 42 DWORD flags = D3DUSAGE_WRITEONLY; 43 if (dynamicUsage) 44 { 45 flags |= D3DUSAGE_DYNAMIC; 46 } 47 48 HRESULT result = mRenderer->createVertexBuffer(size, flags, &mVertexBuffer); 49 50 if (FAILED(result)) 51 { 52 ERR("Out of memory allocating a vertex buffer of size %lu.", size); 53 return false; 54 } 55 } 56 57 mBufferSize = size; 58 mDynamicUsage = dynamicUsage; 59 return true; 60 } 61 62 VertexBuffer9 *VertexBuffer9::makeVertexBuffer9(VertexBuffer *vertexBuffer) 63 { 64 ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer9*, vertexBuffer)); 65 return static_cast<VertexBuffer9*>(vertexBuffer); 66 } 67 68 bool VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, 69 GLint start, GLsizei count, GLsizei instances, unsigned int offset) 70 { 71 if (mVertexBuffer) 72 { 73 gl::Buffer *buffer = attrib.mBoundBuffer.get(); 74 75 int inputStride = attrib.stride(); 76 int elementSize = attrib.typeSize(); 77 78 DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0; 79 80 void *mapPtr = NULL; 81 82 unsigned int mapSize; 83 if (!spaceRequired(attrib, count, instances, &mapSize)) 84 { 85 return false; 86 } 87 88 HRESULT result = mVertexBuffer->Lock(offset, mapSize, &mapPtr, lockFlags); 89 90 if (FAILED(result)) 91 { 92 ERR("Lock failed with error 0x%08x", result); 93 return false; 94 } 95 96 const char *input = NULL; 97 if (attrib.mArrayEnabled) 98 { 99 if (buffer) 100 { 101 BufferStorage *storage = buffer->getStorage(); 102 input = static_cast<const char*>(storage->getData()) + static_cast<int>(attrib.mOffset); 103 } 104 else 105 { 106 input = static_cast<const char*>(attrib.mPointer); 107 } 108 } 109 else 110 { 111 input = reinterpret_cast<const char*>(currentValue.FloatValues); 112 } 113 114 if (instances == 0 || attrib.mDivisor == 0) 115 { 116 input += inputStride * start; 117 } 118 119 gl::VertexFormat vertexFormat(attrib, currentValue.Type); 120 bool needsConversion = (d3d9::GetVertexConversionType(vertexFormat) & VERTEX_CONVERT_CPU) > 0; 121 122 if (!needsConversion && inputStride == elementSize) 123 { 124 size_t copySize = static_cast<size_t>(count) * static_cast<size_t>(inputStride); 125 memcpy(mapPtr, input, copySize); 126 } 127 else 128 { 129 VertexCopyFunction copyFunction = d3d9::GetVertexCopyFunction(vertexFormat); 130 copyFunction(input, inputStride, count, mapPtr); 131 } 132 133 mVertexBuffer->Unlock(); 134 135 return true; 136 } 137 else 138 { 139 ERR("Vertex buffer not initialized."); 140 return false; 141 } 142 } 143 144 bool VertexBuffer9::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, 145 unsigned int *outSpaceRequired) const 146 { 147 return spaceRequired(attrib, count, instances, outSpaceRequired); 148 } 149 150 unsigned int VertexBuffer9::getBufferSize() const 151 { 152 return mBufferSize; 153 } 154 155 bool VertexBuffer9::setBufferSize(unsigned int size) 156 { 157 if (size > mBufferSize) 158 { 159 return initialize(size, mDynamicUsage); 160 } 161 else 162 { 163 return true; 164 } 165 } 166 167 bool VertexBuffer9::discard() 168 { 169 if (mVertexBuffer) 170 { 171 void *dummy; 172 HRESULT result; 173 174 result = mVertexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD); 175 if (FAILED(result)) 176 { 177 ERR("Discard lock failed with error 0x%08x", result); 178 return false; 179 } 180 181 result = mVertexBuffer->Unlock(); 182 if (FAILED(result)) 183 { 184 ERR("Discard unlock failed with error 0x%08x", result); 185 return false; 186 } 187 188 return true; 189 } 190 else 191 { 192 ERR("Vertex buffer not initialized."); 193 return false; 194 } 195 } 196 197 IDirect3DVertexBuffer9 * VertexBuffer9::getBuffer() const 198 { 199 return mVertexBuffer; 200 } 201 202 bool VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances, 203 unsigned int *outSpaceRequired) 204 { 205 gl::VertexFormat vertexFormat(attrib, GL_FLOAT); 206 unsigned int elementSize = d3d9::GetVertexElementSize(vertexFormat); 207 208 if (attrib.mArrayEnabled) 209 { 210 unsigned int elementCount = 0; 211 if (instances == 0 || attrib.mDivisor == 0) 212 { 213 elementCount = count; 214 } 215 else 216 { 217 if (static_cast<unsigned int>(instances) < std::numeric_limits<unsigned int>::max() - (attrib.mDivisor - 1)) 218 { 219 // Round up 220 elementCount = (static_cast<unsigned int>(instances) + (attrib.mDivisor - 1)) / attrib.mDivisor; 221 } 222 else 223 { 224 elementCount = static_cast<unsigned int>(instances) / attrib.mDivisor; 225 } 226 } 227 228 if (elementSize <= std::numeric_limits<unsigned int>::max() / elementCount) 229 { 230 if (outSpaceRequired) 231 { 232 *outSpaceRequired = elementSize * elementCount; 233 } 234 return true; 235 } 236 else 237 { 238 return false; 239 } 240 } 241 else 242 { 243 const unsigned int elementSize = 4; 244 if (outSpaceRequired) 245 { 246 *outSpaceRequired = elementSize * 4; 247 } 248 return true; 249 } 250 } 251 252 } 253