blob: be9f21a2961a1fc9eb11ece259c7af2ebe8db557 [file] [log] [blame]
shannon.woods@transgaming.combdf2d802013-02-28 23:16:20 +00001#include "precompiled.h"
daniel@transgaming.comb80a1902012-12-20 20:57:09 +00002//
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 Langd47e0fc2013-08-29 11:40:43 -040010#include "libGLESv2/renderer/d3d9/VertexBuffer9.h"
daniel@transgaming.comb80a1902012-12-20 20:57:09 +000011#include "libGLESv2/renderer/vertexconversion.h"
shannon.woods@transgaming.comd2811d62013-02-28 23:11:19 +000012#include "libGLESv2/renderer/BufferStorage.h"
Jamie Madill87939712013-07-02 11:57:01 -040013#include "libGLESv2/VertexAttribute.h"
Geoff Langd47e0fc2013-08-29 11:40:43 -040014#include "libGLESv2/renderer/d3d9/Renderer9.h"
Jamie Madill80177872014-02-04 16:04:10 -050015#include "libGLESv2/renderer/d3d9/formatutils9.h"
daniel@transgaming.comb80a1902012-12-20 20:57:09 +000016
17#include "libGLESv2/Buffer.h"
18
daniel@transgaming.comb80a1902012-12-20 20:57:09 +000019namespace rx
20{
21
daniel@transgaming.comb80a1902012-12-20 20:57:09 +000022VertexBuffer9::VertexBuffer9(rx::Renderer9 *const renderer) : mRenderer(renderer)
23{
24 mVertexBuffer = NULL;
25 mBufferSize = 0;
26 mDynamicUsage = false;
daniel@transgaming.comb80a1902012-12-20 20:57:09 +000027}
28
29VertexBuffer9::~VertexBuffer9()
30{
Geoff Langea228632013-07-30 15:17:12 -040031 SafeRelease(mVertexBuffer);
daniel@transgaming.comb80a1902012-12-20 20:57:09 +000032}
33
34bool VertexBuffer9::initialize(unsigned int size, bool dynamicUsage)
35{
Geoff Langea228632013-07-30 15:17:12 -040036 SafeRelease(mVertexBuffer);
daniel@transgaming.comb80a1902012-12-20 20:57:09 +000037
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
62VertexBuffer9 *VertexBuffer9::makeVertexBuffer9(VertexBuffer *vertexBuffer)
63{
apatrick@chromium.org8b400b12013-01-30 21:53:40 +000064 ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer9*, vertexBuffer));
daniel@transgaming.comb80a1902012-12-20 20:57:09 +000065 return static_cast<VertexBuffer9*>(vertexBuffer);
66}
67
Jamie Madilla857c362013-07-02 11:57:02 -040068bool VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData &currentValue,
69 GLint start, GLsizei count, GLsizei instances, unsigned int offset)
daniel@transgaming.comb80a1902012-12-20 20:57:09 +000070{
71 if (mVertexBuffer)
72 {
Brandon Jones5bf98292014-06-06 17:19:38 -070073 gl::Buffer *buffer = attrib.buffer.get();
daniel@transgaming.comb80a1902012-12-20 20:57:09 +000074
Brandon Jones5bf98292014-06-06 17:19:38 -070075 int inputStride = gl::ComputeVertexAttributeStride(attrib);
76 int elementSize = gl::ComputeVertexAttributeTypeSize(attrib);
daniel@transgaming.comb80a1902012-12-20 20:57:09 +000077
78 DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0;
79
80 void *mapPtr = NULL;
Geoff Langa36ead42013-08-02 11:54:08 -040081
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.comb80a1902012-12-20 20:57:09 +000089
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 Jones5bf98292014-06-06 17:19:38 -070097 if (attrib.enabled)
daniel@transgaming.comb80a1902012-12-20 20:57:09 +000098 {
shannon.woods%transgaming.com@gtempaccount.comcf8d2f82013-04-13 03:37:34 +000099 if (buffer)
100 {
101 BufferStorage *storage = buffer->getStorage();
Brandon Jones5bf98292014-06-06 17:19:38 -0700102 input = static_cast<const char*>(storage->getData()) + static_cast<int>(attrib.offset);
shannon.woods%transgaming.com@gtempaccount.comcf8d2f82013-04-13 03:37:34 +0000103 }
104 else
105 {
Brandon Jones5bf98292014-06-06 17:19:38 -0700106 input = static_cast<const char*>(attrib.pointer);
shannon.woods%transgaming.com@gtempaccount.comcf8d2f82013-04-13 03:37:34 +0000107 }
daniel@transgaming.comb80a1902012-12-20 20:57:09 +0000108 }
109 else
110 {
Jamie Madilla857c362013-07-02 11:57:02 -0400111 input = reinterpret_cast<const char*>(currentValue.FloatValues);
daniel@transgaming.comb80a1902012-12-20 20:57:09 +0000112 }
113
Brandon Jones5bf98292014-06-06 17:19:38 -0700114 if (instances == 0 || attrib.divisor == 0)
daniel@transgaming.comb80a1902012-12-20 20:57:09 +0000115 {
116 input += inputStride * start;
117 }
118
Jamie Madill80177872014-02-04 16:04:10 -0500119 gl::VertexFormat vertexFormat(attrib, currentValue.Type);
120 bool needsConversion = (d3d9::GetVertexConversionType(vertexFormat) & VERTEX_CONVERT_CPU) > 0;
121
122 if (!needsConversion && inputStride == elementSize)
daniel@transgaming.comb80a1902012-12-20 20:57:09 +0000123 {
Jamie Madill80b95282014-05-06 13:57:43 -0400124 size_t copySize = static_cast<size_t>(count) * static_cast<size_t>(inputStride);
125 memcpy(mapPtr, input, copySize);
daniel@transgaming.comb80a1902012-12-20 20:57:09 +0000126 }
127 else
128 {
Jamie Madill80177872014-02-04 16:04:10 -0500129 VertexCopyFunction copyFunction = d3d9::GetVertexCopyFunction(vertexFormat);
130 copyFunction(input, inputStride, count, mapPtr);
daniel@transgaming.comb80a1902012-12-20 20:57:09 +0000131 }
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 Langa36ead42013-08-02 11:54:08 -0400144bool VertexBuffer9::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances,
145 unsigned int *outSpaceRequired) const
daniel@transgaming.comb80a1902012-12-20 20:57:09 +0000146{
Geoff Langa36ead42013-08-02 11:54:08 -0400147 return spaceRequired(attrib, count, instances, outSpaceRequired);
daniel@transgaming.comb80a1902012-12-20 20:57:09 +0000148}
149
daniel@transgaming.comb80a1902012-12-20 20:57:09 +0000150unsigned int VertexBuffer9::getBufferSize() const
151{
152 return mBufferSize;
153}
154
155bool 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
167bool VertexBuffer9::discard()
168{
daniel@transgaming.com097674f2012-12-20 21:09:00 +0000169 if (mVertexBuffer)
daniel@transgaming.comb80a1902012-12-20 20:57:09 +0000170 {
daniel@transgaming.com097674f2012-12-20 21:09:00 +0000171 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.comb80a1902012-12-20 20:57:09 +0000193 return false;
194 }
daniel@transgaming.comb80a1902012-12-20 20:57:09 +0000195}
196
197IDirect3DVertexBuffer9 * VertexBuffer9::getBuffer() const
198{
199 return mVertexBuffer;
200}
201
Geoff Langa36ead42013-08-02 11:54:08 -0400202bool VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances,
203 unsigned int *outSpaceRequired)
daniel@transgaming.comb80a1902012-12-20 20:57:09 +0000204{
Jamie Madill80177872014-02-04 16:04:10 -0500205 gl::VertexFormat vertexFormat(attrib, GL_FLOAT);
206 unsigned int elementSize = d3d9::GetVertexElementSize(vertexFormat);
daniel@transgaming.comb80a1902012-12-20 20:57:09 +0000207
Brandon Jones5bf98292014-06-06 17:19:38 -0700208 if (attrib.enabled)
daniel@transgaming.comb80a1902012-12-20 20:57:09 +0000209 {
Geoff Langa36ead42013-08-02 11:54:08 -0400210 unsigned int elementCount = 0;
Brandon Jones5bf98292014-06-06 17:19:38 -0700211 if (instances == 0 || attrib.divisor == 0)
shannon.woods%transgaming.com@gtempaccount.comcf8d2f82013-04-13 03:37:34 +0000212 {
Geoff Langa36ead42013-08-02 11:54:08 -0400213 elementCount = count;
shannon.woods%transgaming.com@gtempaccount.comcf8d2f82013-04-13 03:37:34 +0000214 }
215 else
216 {
Brandon Jones5bf98292014-06-06 17:19:38 -0700217 if (static_cast<unsigned int>(instances) < std::numeric_limits<unsigned int>::max() - (attrib.divisor - 1))
Geoff Langa36ead42013-08-02 11:54:08 -0400218 {
219 // Round up
Brandon Jones5bf98292014-06-06 17:19:38 -0700220 elementCount = (static_cast<unsigned int>(instances) + (attrib.divisor - 1)) / attrib.divisor;
Geoff Langa36ead42013-08-02 11:54:08 -0400221 }
222 else
223 {
Brandon Jones5bf98292014-06-06 17:19:38 -0700224 elementCount = static_cast<unsigned int>(instances) / attrib.divisor;
Geoff Langa36ead42013-08-02 11:54:08 -0400225 }
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.comcf8d2f82013-04-13 03:37:34 +0000239 }
daniel@transgaming.comb80a1902012-12-20 20:57:09 +0000240 }
241 else
242 {
Geoff Langa36ead42013-08-02 11:54:08 -0400243 const unsigned int elementSize = 4;
244 if (outSpaceRequired)
245 {
246 *outSpaceRequired = elementSize * 4;
247 }
248 return true;
daniel@transgaming.comb80a1902012-12-20 20:57:09 +0000249 }
250}
251
252}