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
9 #include "libANGLE/renderer/d3d/d3d9/VertexBuffer9.h"
10 #include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
11 #include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
12 #include "libANGLE/renderer/d3d/d3d9/vertexconversion.h"
13 #include "libANGLE/renderer/d3d/BufferD3D.h"
14 #include "libANGLE/VertexAttribute.h"
15 #include "libANGLE/Buffer.h"
16
17 namespace rx
18 {
19
VertexBuffer9(Renderer9 * renderer)20 VertexBuffer9::VertexBuffer9(Renderer9 *renderer) : mRenderer(renderer)
21 {
22 mVertexBuffer = nullptr;
23 mBufferSize = 0;
24 mDynamicUsage = false;
25 }
26
~VertexBuffer9()27 VertexBuffer9::~VertexBuffer9()
28 {
29 SafeRelease(mVertexBuffer);
30 }
31
initialize(unsigned int size,bool dynamicUsage)32 gl::Error VertexBuffer9::initialize(unsigned int size, bool dynamicUsage)
33 {
34 SafeRelease(mVertexBuffer);
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 {
50 return gl::OutOfMemory()
51 << "Failed to allocate internal vertex buffer of size " << size;
52 }
53 }
54
55 mBufferSize = size;
56 mDynamicUsage = dynamicUsage;
57 return gl::NoError();
58 }
59
storeVertexAttributes(const gl::VertexAttribute & attrib,const gl::VertexBinding & binding,GLenum currentValueType,GLint start,GLsizei count,GLsizei instances,unsigned int offset,const uint8_t * sourceData)60 gl::Error VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib,
61 const gl::VertexBinding &binding,
62 GLenum currentValueType,
63 GLint start,
64 GLsizei count,
65 GLsizei instances,
66 unsigned int offset,
67 const uint8_t *sourceData)
68 {
69 if (!mVertexBuffer)
70 {
71 return gl::OutOfMemory() << "Internal vertex buffer is not initialized.";
72 }
73
74 int inputStride = static_cast<int>(gl::ComputeVertexAttributeStride(attrib, binding));
75 int elementSize = static_cast<int>(gl::ComputeVertexAttributeTypeSize(attrib));
76
77 DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0;
78
79 uint8_t *mapPtr = nullptr;
80
81 auto errorOrMapSize = mRenderer->getVertexSpaceRequired(attrib, binding, count, instances);
82 if (errorOrMapSize.isError())
83 {
84 return errorOrMapSize.getError();
85 }
86
87 unsigned int mapSize = errorOrMapSize.getResult();
88
89 HRESULT result = mVertexBuffer->Lock(offset, mapSize, reinterpret_cast<void**>(&mapPtr), lockFlags);
90 if (FAILED(result))
91 {
92 return gl::OutOfMemory() << "Failed to lock internal vertex buffer, " << gl::FmtHR(result);
93 }
94
95 const uint8_t *input = sourceData;
96
97 if (instances == 0 || binding.getDivisor() == 0)
98 {
99 input += inputStride * start;
100 }
101
102 gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib, currentValueType);
103 const d3d9::VertexFormat &d3dVertexInfo = d3d9::GetVertexFormatInfo(mRenderer->getCapsDeclTypes(), vertexFormatType);
104 bool needsConversion = (d3dVertexInfo.conversionType & VERTEX_CONVERT_CPU) > 0;
105
106 if (!needsConversion && inputStride == elementSize)
107 {
108 size_t copySize = static_cast<size_t>(count) * static_cast<size_t>(inputStride);
109 memcpy(mapPtr, input, copySize);
110 }
111 else
112 {
113 d3dVertexInfo.copyFunction(input, inputStride, count, mapPtr);
114 }
115
116 mVertexBuffer->Unlock();
117
118 return gl::NoError();
119 }
120
getBufferSize() const121 unsigned int VertexBuffer9::getBufferSize() const
122 {
123 return mBufferSize;
124 }
125
setBufferSize(unsigned int size)126 gl::Error VertexBuffer9::setBufferSize(unsigned int size)
127 {
128 if (size > mBufferSize)
129 {
130 return initialize(size, mDynamicUsage);
131 }
132 else
133 {
134 return gl::NoError();
135 }
136 }
137
discard()138 gl::Error VertexBuffer9::discard()
139 {
140 if (!mVertexBuffer)
141 {
142 return gl::OutOfMemory() << "Internal vertex buffer is not initialized.";
143 }
144
145 void *dummy;
146 HRESULT result;
147
148 result = mVertexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
149 if (FAILED(result))
150 {
151 return gl::OutOfMemory() << "Failed to lock internal buffer for discarding, "
152 << gl::FmtHR(result);
153 }
154
155 result = mVertexBuffer->Unlock();
156 if (FAILED(result))
157 {
158 return gl::OutOfMemory() << "Failed to unlock internal buffer for discarding, "
159 << gl::FmtHR(result);
160 }
161
162 return gl::NoError();
163 }
164
getBuffer() const165 IDirect3DVertexBuffer9 * VertexBuffer9::getBuffer() const
166 {
167 return mVertexBuffer;
168 }
169 } // namespace rx
170