blob: 4cf7779118551388242992ae99839e91688fd814 [file] [log] [blame]
daniel@transgaming.comb80a1902012-12-20 20:57:09 +00001//
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 Jonesc7a41042014-06-23 12:03:25 -07009#include "libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h"
Geoff Lang0b7eef72014-06-12 14:10:47 -040010#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
11#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h"
daniel@transgaming.comb80a1902012-12-20 20:57:09 +000012#include "libGLESv2/renderer/vertexconversion.h"
Brandon Jonesd38f9262014-06-18 16:26:45 -070013#include "libGLESv2/renderer/BufferImpl.h"
Jamie Madill87939712013-07-02 11:57:01 -040014#include "libGLESv2/VertexAttribute.h"
daniel@transgaming.comb80a1902012-12-20 20:57:09 +000015#include "libGLESv2/Buffer.h"
16
daniel@transgaming.comb80a1902012-12-20 20:57:09 +000017namespace rx
18{
19
Geoff Lang91fa9ce2014-07-04 17:30:27 -040020VertexBuffer9::VertexBuffer9(rx::Renderer9 *renderer) : mRenderer(renderer)
daniel@transgaming.comb80a1902012-12-20 20:57:09 +000021{
22 mVertexBuffer = NULL;
23 mBufferSize = 0;
24 mDynamicUsage = false;
daniel@transgaming.comb80a1902012-12-20 20:57:09 +000025}
26
27VertexBuffer9::~VertexBuffer9()
28{
Geoff Langea228632013-07-30 15:17:12 -040029 SafeRelease(mVertexBuffer);
daniel@transgaming.comb80a1902012-12-20 20:57:09 +000030}
31
Geoff Langf7100b92014-09-08 16:17:08 -040032gl::Error VertexBuffer9::initialize(unsigned int size, bool dynamicUsage)
daniel@transgaming.comb80a1902012-12-20 20:57:09 +000033{
Geoff Langea228632013-07-30 15:17:12 -040034 SafeRelease(mVertexBuffer);
daniel@transgaming.comb80a1902012-12-20 20:57:09 +000035
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 Langf7100b92014-09-08 16:17:08 -040050 return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal vertex buffer of size, %lu.", size);
daniel@transgaming.comb80a1902012-12-20 20:57:09 +000051 }
52 }
53
54 mBufferSize = size;
55 mDynamicUsage = dynamicUsage;
Geoff Langf7100b92014-09-08 16:17:08 -040056 return gl::Error(GL_NO_ERROR);
daniel@transgaming.comb80a1902012-12-20 20:57:09 +000057}
58
59VertexBuffer9 *VertexBuffer9::makeVertexBuffer9(VertexBuffer *vertexBuffer)
60{
apatrick@chromium.org8b400b12013-01-30 21:53:40 +000061 ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer9*, vertexBuffer));
daniel@transgaming.comb80a1902012-12-20 20:57:09 +000062 return static_cast<VertexBuffer9*>(vertexBuffer);
63}
64
Geoff Langf7100b92014-09-08 16:17:08 -040065gl::Error VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData &currentValue,
66 GLint start, GLsizei count, GLsizei instances, unsigned int offset)
daniel@transgaming.comb80a1902012-12-20 20:57:09 +000067{
Geoff Langf7100b92014-09-08 16:17:08 -040068 if (!mVertexBuffer)
daniel@transgaming.comb80a1902012-12-20 20:57:09 +000069 {
Geoff Langf7100b92014-09-08 16:17:08 -040070 return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized.");
71 }
daniel@transgaming.comb80a1902012-12-20 20:57:09 +000072
Geoff Langf7100b92014-09-08 16:17:08 -040073 gl::Buffer *buffer = attrib.buffer.get();
daniel@transgaming.comb80a1902012-12-20 20:57:09 +000074
Geoff Langf7100b92014-09-08 16:17:08 -040075 int inputStride = gl::ComputeVertexAttributeStride(attrib);
76 int elementSize = gl::ComputeVertexAttributeTypeSize(attrib);
daniel@transgaming.comb80a1902012-12-20 20:57:09 +000077
Geoff Langf7100b92014-09-08 16:17:08 -040078 DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0;
Geoff Langa36ead42013-08-02 11:54:08 -040079
Geoff Langf7100b92014-09-08 16:17:08 -040080 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 Langa36ead42013-08-02 11:54:08 -040099 {
Geoff Langf7100b92014-09-08 16:17:08 -0400100 BufferImpl *storage = buffer->getImplementation();
101 input = static_cast<const uint8_t*>(storage->getData()) + static_cast<int>(attrib.offset);
daniel@transgaming.comb80a1902012-12-20 20:57:09 +0000102 }
103 else
104 {
Geoff Langf7100b92014-09-08 16:17:08 -0400105 input = static_cast<const uint8_t*>(attrib.pointer);
daniel@transgaming.comb80a1902012-12-20 20:57:09 +0000106 }
daniel@transgaming.comb80a1902012-12-20 20:57:09 +0000107 }
108 else
109 {
Geoff Langf7100b92014-09-08 16:17:08 -0400110 input = reinterpret_cast<const uint8_t*>(currentValue.FloatValues);
daniel@transgaming.comb80a1902012-12-20 20:57:09 +0000111 }
Geoff Langf7100b92014-09-08 16:17:08 -0400112
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.comb80a1902012-12-20 20:57:09 +0000135}
136
Geoff Langf7100b92014-09-08 16:17:08 -0400137gl::Error VertexBuffer9::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances,
138 unsigned int *outSpaceRequired) const
daniel@transgaming.comb80a1902012-12-20 20:57:09 +0000139{
Geoff Langa36ead42013-08-02 11:54:08 -0400140 return spaceRequired(attrib, count, instances, outSpaceRequired);
daniel@transgaming.comb80a1902012-12-20 20:57:09 +0000141}
142
daniel@transgaming.comb80a1902012-12-20 20:57:09 +0000143unsigned int VertexBuffer9::getBufferSize() const
144{
145 return mBufferSize;
146}
147
Geoff Langf7100b92014-09-08 16:17:08 -0400148gl::Error VertexBuffer9::setBufferSize(unsigned int size)
daniel@transgaming.comb80a1902012-12-20 20:57:09 +0000149{
150 if (size > mBufferSize)
151 {
152 return initialize(size, mDynamicUsage);
153 }
154 else
155 {
Geoff Langf7100b92014-09-08 16:17:08 -0400156 return gl::Error(GL_NO_ERROR);
daniel@transgaming.comb80a1902012-12-20 20:57:09 +0000157 }
158}
159
Geoff Langf7100b92014-09-08 16:17:08 -0400160gl::Error VertexBuffer9::discard()
daniel@transgaming.comb80a1902012-12-20 20:57:09 +0000161{
Geoff Langf7100b92014-09-08 16:17:08 -0400162 if (!mVertexBuffer)
daniel@transgaming.comb80a1902012-12-20 20:57:09 +0000163 {
Geoff Langf7100b92014-09-08 16:17:08 -0400164 return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized.");
daniel@transgaming.com097674f2012-12-20 21:09:00 +0000165 }
Geoff Langf7100b92014-09-08 16:17:08 -0400166
167 void *dummy;
168 HRESULT result;
169
170 result = mVertexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
171 if (FAILED(result))
daniel@transgaming.com097674f2012-12-20 21:09:00 +0000172 {
Geoff Langf7100b92014-09-08 16:17:08 -0400173 return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal buffer for discarding, HRESULT: 0x%08x", result);
daniel@transgaming.comb80a1902012-12-20 20:57:09 +0000174 }
Geoff Langf7100b92014-09-08 16:17:08 -0400175
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.comb80a1902012-12-20 20:57:09 +0000183}
184
185IDirect3DVertexBuffer9 * VertexBuffer9::getBuffer() const
186{
187 return mVertexBuffer;
188}
189
Geoff Langf7100b92014-09-08 16:17:08 -0400190gl::Error VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances,
191 unsigned int *outSpaceRequired) const
daniel@transgaming.comb80a1902012-12-20 20:57:09 +0000192{
Jamie Madill80177872014-02-04 16:04:10 -0500193 gl::VertexFormat vertexFormat(attrib, GL_FLOAT);
Geoff Lang91fa9ce2014-07-04 17:30:27 -0400194 const d3d9::VertexFormat &d3d9VertexInfo = d3d9::GetVertexFormatInfo(mRenderer->getCapsDeclTypes(), vertexFormat);
daniel@transgaming.comb80a1902012-12-20 20:57:09 +0000195
Brandon Jones5bf98292014-06-06 17:19:38 -0700196 if (attrib.enabled)
daniel@transgaming.comb80a1902012-12-20 20:57:09 +0000197 {
Geoff Langa36ead42013-08-02 11:54:08 -0400198 unsigned int elementCount = 0;
Brandon Jones5bf98292014-06-06 17:19:38 -0700199 if (instances == 0 || attrib.divisor == 0)
shannon.woods%transgaming.com@gtempaccount.comcf8d2f82013-04-13 03:37:34 +0000200 {
Geoff Langa36ead42013-08-02 11:54:08 -0400201 elementCount = count;
shannon.woods%transgaming.com@gtempaccount.comcf8d2f82013-04-13 03:37:34 +0000202 }
203 else
204 {
Jamie Madillaff80842014-08-04 10:47:56 -0400205 // Round up to divisor, if possible
206 elementCount = rx::UnsignedCeilDivide(static_cast<unsigned int>(instances), attrib.divisor);
Geoff Langa36ead42013-08-02 11:54:08 -0400207 }
208
Geoff Lang91fa9ce2014-07-04 17:30:27 -0400209 if (d3d9VertexInfo.outputElementSize <= std::numeric_limits<unsigned int>::max() / elementCount)
Geoff Langa36ead42013-08-02 11:54:08 -0400210 {
211 if (outSpaceRequired)
212 {
Geoff Lang91fa9ce2014-07-04 17:30:27 -0400213 *outSpaceRequired = d3d9VertexInfo.outputElementSize * elementCount;
Geoff Langa36ead42013-08-02 11:54:08 -0400214 }
Geoff Langf7100b92014-09-08 16:17:08 -0400215 return gl::Error(GL_NO_ERROR);
Geoff Langa36ead42013-08-02 11:54:08 -0400216 }
217 else
218 {
Geoff Langf7100b92014-09-08 16:17:08 -0400219 return gl::Error(GL_OUT_OF_MEMORY, "New vertex buffer size would result in an overflow.");
shannon.woods%transgaming.com@gtempaccount.comcf8d2f82013-04-13 03:37:34 +0000220 }
daniel@transgaming.comb80a1902012-12-20 20:57:09 +0000221 }
222 else
223 {
Geoff Langa36ead42013-08-02 11:54:08 -0400224 const unsigned int elementSize = 4;
225 if (outSpaceRequired)
226 {
227 *outSpaceRequired = elementSize * 4;
228 }
Geoff Langf7100b92014-09-08 16:17:08 -0400229 return gl::Error(GL_NO_ERROR);
daniel@transgaming.comb80a1902012-12-20 20:57:09 +0000230 }
231}
232
233}