shannon.woods@transgaming.com | bdf2d80 | 2013-02-28 23:16:20 +0000 | [diff] [blame] | 1 | #include "precompiled.h" |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 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 | |
Geoff Lang | d47e0fc | 2013-08-29 11:40:43 -0400 | [diff] [blame] | 10 | #include "libGLESv2/renderer/d3d9/VertexBuffer9.h" |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 11 | #include "libGLESv2/renderer/vertexconversion.h" |
shannon.woods@transgaming.com | d2811d6 | 2013-02-28 23:11:19 +0000 | [diff] [blame] | 12 | #include "libGLESv2/renderer/BufferStorage.h" |
Jamie Madill | 8793971 | 2013-07-02 11:57:01 -0400 | [diff] [blame] | 13 | #include "libGLESv2/VertexAttribute.h" |
Geoff Lang | d47e0fc | 2013-08-29 11:40:43 -0400 | [diff] [blame] | 14 | #include "libGLESv2/renderer/d3d9/Renderer9.h" |
Jamie Madill | 8017787 | 2014-02-04 16:04:10 -0500 | [diff] [blame] | 15 | #include "libGLESv2/renderer/d3d9/formatutils9.h" |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 16 | |
| 17 | #include "libGLESv2/Buffer.h" |
| 18 | |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 19 | namespace rx |
| 20 | { |
| 21 | |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 22 | VertexBuffer9::VertexBuffer9(rx::Renderer9 *const renderer) : mRenderer(renderer) |
| 23 | { |
| 24 | mVertexBuffer = NULL; |
| 25 | mBufferSize = 0; |
| 26 | mDynamicUsage = false; |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 27 | } |
| 28 | |
| 29 | VertexBuffer9::~VertexBuffer9() |
| 30 | { |
Geoff Lang | ea22863 | 2013-07-30 15:17:12 -0400 | [diff] [blame] | 31 | SafeRelease(mVertexBuffer); |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 32 | } |
| 33 | |
| 34 | bool VertexBuffer9::initialize(unsigned int size, bool dynamicUsage) |
| 35 | { |
Geoff Lang | ea22863 | 2013-07-30 15:17:12 -0400 | [diff] [blame] | 36 | SafeRelease(mVertexBuffer); |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 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 | { |
apatrick@chromium.org | 8b400b1 | 2013-01-30 21:53:40 +0000 | [diff] [blame] | 64 | ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer9*, vertexBuffer)); |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 65 | return static_cast<VertexBuffer9*>(vertexBuffer); |
| 66 | } |
| 67 | |
Jamie Madill | a857c36 | 2013-07-02 11:57:02 -0400 | [diff] [blame] | 68 | bool VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, |
| 69 | GLint start, GLsizei count, GLsizei instances, unsigned int offset) |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 70 | { |
| 71 | if (mVertexBuffer) |
| 72 | { |
Brandon Jones | 5bf9829 | 2014-06-06 17:19:38 -0700 | [diff] [blame^] | 73 | gl::Buffer *buffer = attrib.buffer.get(); |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 74 | |
Brandon Jones | 5bf9829 | 2014-06-06 17:19:38 -0700 | [diff] [blame^] | 75 | int inputStride = gl::ComputeVertexAttributeStride(attrib); |
| 76 | int elementSize = gl::ComputeVertexAttributeTypeSize(attrib); |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 77 | |
| 78 | DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0; |
| 79 | |
| 80 | void *mapPtr = NULL; |
Geoff Lang | a36ead4 | 2013-08-02 11:54:08 -0400 | [diff] [blame] | 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); |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 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; |
Brandon Jones | 5bf9829 | 2014-06-06 17:19:38 -0700 | [diff] [blame^] | 97 | if (attrib.enabled) |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 98 | { |
shannon.woods%transgaming.com@gtempaccount.com | cf8d2f8 | 2013-04-13 03:37:34 +0000 | [diff] [blame] | 99 | if (buffer) |
| 100 | { |
| 101 | BufferStorage *storage = buffer->getStorage(); |
Brandon Jones | 5bf9829 | 2014-06-06 17:19:38 -0700 | [diff] [blame^] | 102 | input = static_cast<const char*>(storage->getData()) + static_cast<int>(attrib.offset); |
shannon.woods%transgaming.com@gtempaccount.com | cf8d2f8 | 2013-04-13 03:37:34 +0000 | [diff] [blame] | 103 | } |
| 104 | else |
| 105 | { |
Brandon Jones | 5bf9829 | 2014-06-06 17:19:38 -0700 | [diff] [blame^] | 106 | input = static_cast<const char*>(attrib.pointer); |
shannon.woods%transgaming.com@gtempaccount.com | cf8d2f8 | 2013-04-13 03:37:34 +0000 | [diff] [blame] | 107 | } |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 108 | } |
| 109 | else |
| 110 | { |
Jamie Madill | a857c36 | 2013-07-02 11:57:02 -0400 | [diff] [blame] | 111 | input = reinterpret_cast<const char*>(currentValue.FloatValues); |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 112 | } |
| 113 | |
Brandon Jones | 5bf9829 | 2014-06-06 17:19:38 -0700 | [diff] [blame^] | 114 | if (instances == 0 || attrib.divisor == 0) |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 115 | { |
| 116 | input += inputStride * start; |
| 117 | } |
| 118 | |
Jamie Madill | 8017787 | 2014-02-04 16:04:10 -0500 | [diff] [blame] | 119 | gl::VertexFormat vertexFormat(attrib, currentValue.Type); |
| 120 | bool needsConversion = (d3d9::GetVertexConversionType(vertexFormat) & VERTEX_CONVERT_CPU) > 0; |
| 121 | |
| 122 | if (!needsConversion && inputStride == elementSize) |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 123 | { |
Jamie Madill | 80b9528 | 2014-05-06 13:57:43 -0400 | [diff] [blame] | 124 | size_t copySize = static_cast<size_t>(count) * static_cast<size_t>(inputStride); |
| 125 | memcpy(mapPtr, input, copySize); |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 126 | } |
| 127 | else |
| 128 | { |
Jamie Madill | 8017787 | 2014-02-04 16:04:10 -0500 | [diff] [blame] | 129 | VertexCopyFunction copyFunction = d3d9::GetVertexCopyFunction(vertexFormat); |
| 130 | copyFunction(input, inputStride, count, mapPtr); |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 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 | |
Geoff Lang | a36ead4 | 2013-08-02 11:54:08 -0400 | [diff] [blame] | 144 | bool VertexBuffer9::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, |
| 145 | unsigned int *outSpaceRequired) const |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 146 | { |
Geoff Lang | a36ead4 | 2013-08-02 11:54:08 -0400 | [diff] [blame] | 147 | return spaceRequired(attrib, count, instances, outSpaceRequired); |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 148 | } |
| 149 | |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 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 | { |
daniel@transgaming.com | 097674f | 2012-12-20 21:09:00 +0000 | [diff] [blame] | 169 | if (mVertexBuffer) |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 170 | { |
daniel@transgaming.com | 097674f | 2012-12-20 21:09:00 +0000 | [diff] [blame] | 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."); |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 193 | return false; |
| 194 | } |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 195 | } |
| 196 | |
| 197 | IDirect3DVertexBuffer9 * VertexBuffer9::getBuffer() const |
| 198 | { |
| 199 | return mVertexBuffer; |
| 200 | } |
| 201 | |
Geoff Lang | a36ead4 | 2013-08-02 11:54:08 -0400 | [diff] [blame] | 202 | bool VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances, |
| 203 | unsigned int *outSpaceRequired) |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 204 | { |
Jamie Madill | 8017787 | 2014-02-04 16:04:10 -0500 | [diff] [blame] | 205 | gl::VertexFormat vertexFormat(attrib, GL_FLOAT); |
| 206 | unsigned int elementSize = d3d9::GetVertexElementSize(vertexFormat); |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 207 | |
Brandon Jones | 5bf9829 | 2014-06-06 17:19:38 -0700 | [diff] [blame^] | 208 | if (attrib.enabled) |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 209 | { |
Geoff Lang | a36ead4 | 2013-08-02 11:54:08 -0400 | [diff] [blame] | 210 | unsigned int elementCount = 0; |
Brandon Jones | 5bf9829 | 2014-06-06 17:19:38 -0700 | [diff] [blame^] | 211 | if (instances == 0 || attrib.divisor == 0) |
shannon.woods%transgaming.com@gtempaccount.com | cf8d2f8 | 2013-04-13 03:37:34 +0000 | [diff] [blame] | 212 | { |
Geoff Lang | a36ead4 | 2013-08-02 11:54:08 -0400 | [diff] [blame] | 213 | elementCount = count; |
shannon.woods%transgaming.com@gtempaccount.com | cf8d2f8 | 2013-04-13 03:37:34 +0000 | [diff] [blame] | 214 | } |
| 215 | else |
| 216 | { |
Brandon Jones | 5bf9829 | 2014-06-06 17:19:38 -0700 | [diff] [blame^] | 217 | if (static_cast<unsigned int>(instances) < std::numeric_limits<unsigned int>::max() - (attrib.divisor - 1)) |
Geoff Lang | a36ead4 | 2013-08-02 11:54:08 -0400 | [diff] [blame] | 218 | { |
| 219 | // Round up |
Brandon Jones | 5bf9829 | 2014-06-06 17:19:38 -0700 | [diff] [blame^] | 220 | elementCount = (static_cast<unsigned int>(instances) + (attrib.divisor - 1)) / attrib.divisor; |
Geoff Lang | a36ead4 | 2013-08-02 11:54:08 -0400 | [diff] [blame] | 221 | } |
| 222 | else |
| 223 | { |
Brandon Jones | 5bf9829 | 2014-06-06 17:19:38 -0700 | [diff] [blame^] | 224 | elementCount = static_cast<unsigned int>(instances) / attrib.divisor; |
Geoff Lang | a36ead4 | 2013-08-02 11:54:08 -0400 | [diff] [blame] | 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; |
shannon.woods%transgaming.com@gtempaccount.com | cf8d2f8 | 2013-04-13 03:37:34 +0000 | [diff] [blame] | 239 | } |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 240 | } |
| 241 | else |
| 242 | { |
Geoff Lang | a36ead4 | 2013-08-02 11:54:08 -0400 | [diff] [blame] | 243 | const unsigned int elementSize = 4; |
| 244 | if (outSpaceRequired) |
| 245 | { |
| 246 | *outSpaceRequired = elementSize * 4; |
| 247 | } |
| 248 | return true; |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 249 | } |
| 250 | } |
| 251 | |
| 252 | } |