daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 1 | // |
| 2 | // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. |
| 3 | // Use of this source code is governed by a BSD-style license that can be |
| 4 | // found in the LICENSE file. |
| 5 | // |
| 6 | |
| 7 | // VertexBuffer9.cpp: Defines the D3D9 VertexBuffer implementation. |
| 8 | |
Brandon Jones | c7a4104 | 2014-06-23 12:03:25 -0700 | [diff] [blame] | 9 | #include "libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h" |
Geoff Lang | 0b7eef7 | 2014-06-12 14:10:47 -0400 | [diff] [blame] | 10 | #include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" |
| 11 | #include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 12 | #include "libGLESv2/renderer/vertexconversion.h" |
Brandon Jones | d38f926 | 2014-06-18 16:26:45 -0700 | [diff] [blame] | 13 | #include "libGLESv2/renderer/BufferImpl.h" |
Jamie Madill | 8793971 | 2013-07-02 11:57:01 -0400 | [diff] [blame] | 14 | #include "libGLESv2/VertexAttribute.h" |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 15 | #include "libGLESv2/Buffer.h" |
| 16 | |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 17 | namespace rx |
| 18 | { |
| 19 | |
Geoff Lang | 91fa9ce | 2014-07-04 17:30:27 -0400 | [diff] [blame] | 20 | VertexBuffer9::VertexBuffer9(rx::Renderer9 *renderer) : mRenderer(renderer) |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 21 | { |
| 22 | mVertexBuffer = NULL; |
| 23 | mBufferSize = 0; |
| 24 | mDynamicUsage = false; |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 25 | } |
| 26 | |
| 27 | VertexBuffer9::~VertexBuffer9() |
| 28 | { |
Geoff Lang | ea22863 | 2013-07-30 15:17:12 -0400 | [diff] [blame] | 29 | SafeRelease(mVertexBuffer); |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 30 | } |
| 31 | |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 32 | gl::Error VertexBuffer9::initialize(unsigned int size, bool dynamicUsage) |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 33 | { |
Geoff Lang | ea22863 | 2013-07-30 15:17:12 -0400 | [diff] [blame] | 34 | SafeRelease(mVertexBuffer); |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 35 | |
| 36 | updateSerial(); |
| 37 | |
| 38 | if (size > 0) |
| 39 | { |
| 40 | DWORD flags = D3DUSAGE_WRITEONLY; |
| 41 | if (dynamicUsage) |
| 42 | { |
| 43 | flags |= D3DUSAGE_DYNAMIC; |
| 44 | } |
| 45 | |
| 46 | HRESULT result = mRenderer->createVertexBuffer(size, flags, &mVertexBuffer); |
| 47 | |
| 48 | if (FAILED(result)) |
| 49 | { |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 50 | return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal vertex buffer of size, %lu.", size); |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 51 | } |
| 52 | } |
| 53 | |
| 54 | mBufferSize = size; |
| 55 | mDynamicUsage = dynamicUsage; |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 56 | return gl::Error(GL_NO_ERROR); |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 57 | } |
| 58 | |
| 59 | VertexBuffer9 *VertexBuffer9::makeVertexBuffer9(VertexBuffer *vertexBuffer) |
| 60 | { |
apatrick@chromium.org | 8b400b1 | 2013-01-30 21:53:40 +0000 | [diff] [blame] | 61 | ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer9*, vertexBuffer)); |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 62 | return static_cast<VertexBuffer9*>(vertexBuffer); |
| 63 | } |
| 64 | |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 65 | gl::Error VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, |
| 66 | GLint start, GLsizei count, GLsizei instances, unsigned int offset) |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 67 | { |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 68 | if (!mVertexBuffer) |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 69 | { |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 70 | return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized."); |
| 71 | } |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 72 | |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 73 | gl::Buffer *buffer = attrib.buffer.get(); |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 74 | |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [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 | |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 78 | DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0; |
Geoff Lang | a36ead4 | 2013-08-02 11:54:08 -0400 | [diff] [blame] | 79 | |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 80 | uint8_t *mapPtr = NULL; |
| 81 | |
| 82 | unsigned int mapSize; |
| 83 | gl::Error error = spaceRequired(attrib, count, instances, &mapSize); |
| 84 | if (error.isError()) |
| 85 | { |
| 86 | return error; |
| 87 | } |
| 88 | |
| 89 | HRESULT result = mVertexBuffer->Lock(offset, mapSize, reinterpret_cast<void**>(&mapPtr), lockFlags); |
| 90 | if (FAILED(result)) |
| 91 | { |
| 92 | return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal vertex buffer, HRESULT: 0x%08x.", result); |
| 93 | } |
| 94 | |
| 95 | const uint8_t *input = NULL; |
| 96 | if (attrib.enabled) |
| 97 | { |
| 98 | if (buffer) |
Geoff Lang | a36ead4 | 2013-08-02 11:54:08 -0400 | [diff] [blame] | 99 | { |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 100 | BufferImpl *storage = buffer->getImplementation(); |
| 101 | input = static_cast<const uint8_t*>(storage->getData()) + static_cast<int>(attrib.offset); |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 102 | } |
| 103 | else |
| 104 | { |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 105 | input = static_cast<const uint8_t*>(attrib.pointer); |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 106 | } |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 107 | } |
| 108 | else |
| 109 | { |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 110 | input = reinterpret_cast<const uint8_t*>(currentValue.FloatValues); |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 111 | } |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 112 | |
| 113 | if (instances == 0 || attrib.divisor == 0) |
| 114 | { |
| 115 | input += inputStride * start; |
| 116 | } |
| 117 | |
| 118 | gl::VertexFormat vertexFormat(attrib, currentValue.Type); |
| 119 | const d3d9::VertexFormat &d3dVertexInfo = d3d9::GetVertexFormatInfo(mRenderer->getCapsDeclTypes(), vertexFormat); |
| 120 | bool needsConversion = (d3dVertexInfo.conversionType & 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 | d3dVertexInfo.copyFunction(input, inputStride, count, mapPtr); |
| 130 | } |
| 131 | |
| 132 | mVertexBuffer->Unlock(); |
| 133 | |
| 134 | return gl::Error(GL_NO_ERROR); |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 135 | } |
| 136 | |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 137 | gl::Error VertexBuffer9::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, |
| 138 | unsigned int *outSpaceRequired) const |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 139 | { |
Geoff Lang | a36ead4 | 2013-08-02 11:54:08 -0400 | [diff] [blame] | 140 | return spaceRequired(attrib, count, instances, outSpaceRequired); |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 141 | } |
| 142 | |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 143 | unsigned int VertexBuffer9::getBufferSize() const |
| 144 | { |
| 145 | return mBufferSize; |
| 146 | } |
| 147 | |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 148 | gl::Error VertexBuffer9::setBufferSize(unsigned int size) |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 149 | { |
| 150 | if (size > mBufferSize) |
| 151 | { |
| 152 | return initialize(size, mDynamicUsage); |
| 153 | } |
| 154 | else |
| 155 | { |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 156 | return gl::Error(GL_NO_ERROR); |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 157 | } |
| 158 | } |
| 159 | |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 160 | gl::Error VertexBuffer9::discard() |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 161 | { |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 162 | if (!mVertexBuffer) |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 163 | { |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 164 | return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized."); |
daniel@transgaming.com | 097674f | 2012-12-20 21:09:00 +0000 | [diff] [blame] | 165 | } |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 166 | |
| 167 | void *dummy; |
| 168 | HRESULT result; |
| 169 | |
| 170 | result = mVertexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD); |
| 171 | if (FAILED(result)) |
daniel@transgaming.com | 097674f | 2012-12-20 21:09:00 +0000 | [diff] [blame] | 172 | { |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 173 | return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal buffer for discarding, HRESULT: 0x%08x", result); |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 174 | } |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 175 | |
| 176 | result = mVertexBuffer->Unlock(); |
| 177 | if (FAILED(result)) |
| 178 | { |
| 179 | return gl::Error(GL_OUT_OF_MEMORY, "Failed to unlock internal buffer for discarding, HRESULT: 0x%08x", result); |
| 180 | } |
| 181 | |
| 182 | return gl::Error(GL_NO_ERROR); |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 183 | } |
| 184 | |
| 185 | IDirect3DVertexBuffer9 * VertexBuffer9::getBuffer() const |
| 186 | { |
| 187 | return mVertexBuffer; |
| 188 | } |
| 189 | |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 190 | gl::Error VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances, |
| 191 | unsigned int *outSpaceRequired) const |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 192 | { |
Jamie Madill | 8017787 | 2014-02-04 16:04:10 -0500 | [diff] [blame] | 193 | gl::VertexFormat vertexFormat(attrib, GL_FLOAT); |
Geoff Lang | 91fa9ce | 2014-07-04 17:30:27 -0400 | [diff] [blame] | 194 | const d3d9::VertexFormat &d3d9VertexInfo = d3d9::GetVertexFormatInfo(mRenderer->getCapsDeclTypes(), vertexFormat); |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 195 | |
Brandon Jones | 5bf9829 | 2014-06-06 17:19:38 -0700 | [diff] [blame] | 196 | if (attrib.enabled) |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 197 | { |
Geoff Lang | a36ead4 | 2013-08-02 11:54:08 -0400 | [diff] [blame] | 198 | unsigned int elementCount = 0; |
Brandon Jones | 5bf9829 | 2014-06-06 17:19:38 -0700 | [diff] [blame] | 199 | if (instances == 0 || attrib.divisor == 0) |
shannon.woods%transgaming.com@gtempaccount.com | cf8d2f8 | 2013-04-13 03:37:34 +0000 | [diff] [blame] | 200 | { |
Geoff Lang | a36ead4 | 2013-08-02 11:54:08 -0400 | [diff] [blame] | 201 | elementCount = count; |
shannon.woods%transgaming.com@gtempaccount.com | cf8d2f8 | 2013-04-13 03:37:34 +0000 | [diff] [blame] | 202 | } |
| 203 | else |
| 204 | { |
Jamie Madill | aff8084 | 2014-08-04 10:47:56 -0400 | [diff] [blame] | 205 | // Round up to divisor, if possible |
| 206 | elementCount = rx::UnsignedCeilDivide(static_cast<unsigned int>(instances), attrib.divisor); |
Geoff Lang | a36ead4 | 2013-08-02 11:54:08 -0400 | [diff] [blame] | 207 | } |
| 208 | |
Geoff Lang | 91fa9ce | 2014-07-04 17:30:27 -0400 | [diff] [blame] | 209 | if (d3d9VertexInfo.outputElementSize <= std::numeric_limits<unsigned int>::max() / elementCount) |
Geoff Lang | a36ead4 | 2013-08-02 11:54:08 -0400 | [diff] [blame] | 210 | { |
| 211 | if (outSpaceRequired) |
| 212 | { |
Geoff Lang | 91fa9ce | 2014-07-04 17:30:27 -0400 | [diff] [blame] | 213 | *outSpaceRequired = d3d9VertexInfo.outputElementSize * elementCount; |
Geoff Lang | a36ead4 | 2013-08-02 11:54:08 -0400 | [diff] [blame] | 214 | } |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 215 | return gl::Error(GL_NO_ERROR); |
Geoff Lang | a36ead4 | 2013-08-02 11:54:08 -0400 | [diff] [blame] | 216 | } |
| 217 | else |
| 218 | { |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 219 | return gl::Error(GL_OUT_OF_MEMORY, "New vertex buffer size would result in an overflow."); |
shannon.woods%transgaming.com@gtempaccount.com | cf8d2f8 | 2013-04-13 03:37:34 +0000 | [diff] [blame] | 220 | } |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 221 | } |
| 222 | else |
| 223 | { |
Geoff Lang | a36ead4 | 2013-08-02 11:54:08 -0400 | [diff] [blame] | 224 | const unsigned int elementSize = 4; |
| 225 | if (outSpaceRequired) |
| 226 | { |
| 227 | *outSpaceRequired = elementSize * 4; |
| 228 | } |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 229 | return gl::Error(GL_NO_ERROR); |
daniel@transgaming.com | b80a190 | 2012-12-20 20:57:09 +0000 | [diff] [blame] | 230 | } |
| 231 | } |
| 232 | |
| 233 | } |