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.
7 // VertexBuffer9.cpp: Defines the D3D9 VertexBuffer implementation.
9 #include "libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h"
10 #include "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
11 #include "libGLESv2/renderer/d3d/d3d9/formatutils9.h"
12 #include "libGLESv2/renderer/vertexconversion.h"
13 #include "libGLESv2/renderer/BufferImpl.h"
14 #include "libGLESv2/VertexAttribute.h"
15 #include "libGLESv2/Buffer.h"
20 VertexBuffer9::VertexBuffer9(rx::Renderer9 *renderer) : mRenderer(renderer)
24 mDynamicUsage = false;
27 VertexBuffer9::~VertexBuffer9()
29 SafeRelease(mVertexBuffer);
32 gl::Error VertexBuffer9::initialize(unsigned int size, bool dynamicUsage)
34 SafeRelease(mVertexBuffer);
40 DWORD flags = D3DUSAGE_WRITEONLY;
43 flags |= D3DUSAGE_DYNAMIC;
46 HRESULT result = mRenderer->createVertexBuffer(size, flags, &mVertexBuffer);
50 return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal vertex buffer of size, %lu.", size);
55 mDynamicUsage = dynamicUsage;
56 return gl::Error(GL_NO_ERROR);
59 VertexBuffer9 *VertexBuffer9::makeVertexBuffer9(VertexBuffer *vertexBuffer)
61 ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer9*, vertexBuffer));
62 return static_cast<VertexBuffer9*>(vertexBuffer);
65 gl::Error VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue,
66 GLint start, GLsizei count, GLsizei instances, unsigned int offset)
70 return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized.");
73 gl::Buffer *buffer = attrib.buffer.get();
75 int inputStride = gl::ComputeVertexAttributeStride(attrib);
76 int elementSize = gl::ComputeVertexAttributeTypeSize(attrib);
78 DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0;
80 uint8_t *mapPtr = NULL;
83 gl::Error error = spaceRequired(attrib, count, instances, &mapSize);
89 HRESULT result = mVertexBuffer->Lock(offset, mapSize, reinterpret_cast<void**>(&mapPtr), lockFlags);
92 return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal vertex buffer, HRESULT: 0x%08x.", result);
95 const uint8_t *input = NULL;
100 BufferImpl *storage = buffer->getImplementation();
101 input = static_cast<const uint8_t*>(storage->getData()) + static_cast<int>(attrib.offset);
105 input = static_cast<const uint8_t*>(attrib.pointer);
110 input = reinterpret_cast<const uint8_t*>(currentValue.FloatValues);
113 if (instances == 0 || attrib.divisor == 0)
115 input += inputStride * start;
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;
122 if (!needsConversion && inputStride == elementSize)
124 size_t copySize = static_cast<size_t>(count) * static_cast<size_t>(inputStride);
125 memcpy(mapPtr, input, copySize);
129 d3dVertexInfo.copyFunction(input, inputStride, count, mapPtr);
132 mVertexBuffer->Unlock();
134 return gl::Error(GL_NO_ERROR);
137 gl::Error VertexBuffer9::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances,
138 unsigned int *outSpaceRequired) const
140 return spaceRequired(attrib, count, instances, outSpaceRequired);
143 unsigned int VertexBuffer9::getBufferSize() const
148 gl::Error VertexBuffer9::setBufferSize(unsigned int size)
150 if (size > mBufferSize)
152 return initialize(size, mDynamicUsage);
156 return gl::Error(GL_NO_ERROR);
160 gl::Error VertexBuffer9::discard()
164 return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized.");
170 result = mVertexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
173 return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal buffer for discarding, HRESULT: 0x%08x", result);
176 result = mVertexBuffer->Unlock();
179 return gl::Error(GL_OUT_OF_MEMORY, "Failed to unlock internal buffer for discarding, HRESULT: 0x%08x", result);
182 return gl::Error(GL_NO_ERROR);
185 IDirect3DVertexBuffer9 * VertexBuffer9::getBuffer() const
187 return mVertexBuffer;
190 gl::Error VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances,
191 unsigned int *outSpaceRequired) const
193 gl::VertexFormat vertexFormat(attrib, GL_FLOAT);
194 const d3d9::VertexFormat &d3d9VertexInfo = d3d9::GetVertexFormatInfo(mRenderer->getCapsDeclTypes(), vertexFormat);
198 unsigned int elementCount = 0;
199 if (instances == 0 || attrib.divisor == 0)
201 elementCount = count;
205 // Round up to divisor, if possible
206 elementCount = rx::UnsignedCeilDivide(static_cast<unsigned int>(instances), attrib.divisor);
209 if (d3d9VertexInfo.outputElementSize <= std::numeric_limits<unsigned int>::max() / elementCount)
211 if (outSpaceRequired)
213 *outSpaceRequired = d3d9VertexInfo.outputElementSize * elementCount;
215 return gl::Error(GL_NO_ERROR);
219 return gl::Error(GL_OUT_OF_MEMORY, "New vertex buffer size would result in an overflow.");
224 const unsigned int elementSize = 4;
225 if (outSpaceRequired)
227 *outSpaceRequired = elementSize * 4;
229 return gl::Error(GL_NO_ERROR);