blob: 28e334247062ab22e3c8f192f07819c1f86819b0 [file] [log] [blame]
daniel@transgaming.com29787c32012-12-20 20:55:48 +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// VertexBuffer.cpp: Defines the VertexBuffer and derivations, classes that
8// perform graphics API agnostic vertex buffer operations.
9
10#include "libGLESv2/renderer/VertexBuffer.h"
11
12#include "libGLESv2/renderer/Renderer9.h"
13
14namespace rx
15{
16
17unsigned int VertexBuffer::mCurrentSerial = 1;
18
19VertexBuffer::VertexBuffer(rx::Renderer9 *renderer, std::size_t size, DWORD usageFlags) : mRenderer(renderer), mVertexBuffer(NULL)
20{
21 if (size > 0)
22 {
23 // D3D9_REPLACE
24 HRESULT result = mRenderer->createVertexBuffer(size, usageFlags,&mVertexBuffer);
25 mSerial = issueSerial();
26
27 if (FAILED(result))
28 {
29 ERR("Out of memory allocating a vertex buffer of size %lu.", size);
30 }
31 }
daniel@transgaming.coma41d07f2012-12-20 20:55:57 +000032
33 mBufferSize = size;
34 mWritePosition = 0;
35 mRequiredSpace = 0;
daniel@transgaming.com29787c32012-12-20 20:55:48 +000036}
37
38VertexBuffer::~VertexBuffer()
39{
40 if (mVertexBuffer)
41 {
42 mVertexBuffer->Release();
43 }
44}
45
46void VertexBuffer::unmap()
47{
48 if (mVertexBuffer)
49 {
50 mVertexBuffer->Unlock();
51 }
52}
53
54IDirect3DVertexBuffer9 *VertexBuffer::getBuffer() const
55{
56 return mVertexBuffer;
57}
58
59unsigned int VertexBuffer::getSerial() const
60{
61 return mSerial;
62}
63
64unsigned int VertexBuffer::issueSerial()
65{
66 return mCurrentSerial++;
67}
68
daniel@transgaming.coma41d07f2012-12-20 20:55:57 +000069void VertexBuffer::addRequiredSpace(UINT requiredSpace)
daniel@transgaming.com29787c32012-12-20 20:55:48 +000070{
71 mRequiredSpace += requiredSpace;
72}
73
daniel@transgaming.coma41d07f2012-12-20 20:55:57 +000074StreamingVertexBuffer::StreamingVertexBuffer(rx::Renderer9 *renderer, std::size_t initialSize) : VertexBuffer(renderer, initialSize, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY)
daniel@transgaming.com29787c32012-12-20 20:55:48 +000075{
76}
77
78StreamingVertexBuffer::~StreamingVertexBuffer()
79{
80}
81
82void *StreamingVertexBuffer::map(const gl::VertexAttribute &attribute, std::size_t requiredSpace, std::size_t *offset)
83{
84 void *mapPtr = NULL;
85
86 if (mVertexBuffer)
87 {
88 HRESULT result = mVertexBuffer->Lock(mWritePosition, requiredSpace, &mapPtr, D3DLOCK_NOOVERWRITE);
89
90 if (FAILED(result))
91 {
92 ERR("Lock failed with error 0x%08x", result);
93 return NULL;
94 }
95
96 *offset = mWritePosition;
97 mWritePosition += requiredSpace;
98 }
99
100 return mapPtr;
101}
102
103void StreamingVertexBuffer::reserveRequiredSpace()
104{
105 if (mRequiredSpace > mBufferSize)
106 {
107 if (mVertexBuffer)
108 {
109 mVertexBuffer->Release();
110 mVertexBuffer = NULL;
111 }
112
113 mBufferSize = std::max(mRequiredSpace, 3 * mBufferSize / 2); // 1.5 x mBufferSize is arbitrary and should be checked to see we don't have too many reallocations.
114
115 // D3D9_REPLACE
116 HRESULT result = mRenderer->createVertexBuffer(mBufferSize, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, &mVertexBuffer);
117 mSerial = issueSerial();
118
119 if (FAILED(result))
120 {
121 ERR("Out of memory allocating a vertex buffer of size %lu.", mBufferSize);
122 }
123
124 mWritePosition = 0;
125 }
126 else if (mWritePosition + mRequiredSpace > mBufferSize) // Recycle
127 {
128 if (mVertexBuffer)
129 {
130 void *dummy;
131 mVertexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
132 mVertexBuffer->Unlock();
133 }
134
135 mWritePosition = 0;
136 }
137
138 mRequiredSpace = 0;
139}
140
daniel@transgaming.coma41d07f2012-12-20 20:55:57 +0000141StaticVertexBuffer::StaticVertexBuffer(rx::Renderer9 *renderer) : VertexBuffer(renderer, 0, D3DUSAGE_WRITEONLY)
daniel@transgaming.com29787c32012-12-20 20:55:48 +0000142{
143}
144
145StaticVertexBuffer::~StaticVertexBuffer()
146{
147}
148
149void *StaticVertexBuffer::map(const gl::VertexAttribute &attribute, std::size_t requiredSpace, std::size_t *streamOffset)
150{
151 void *mapPtr = NULL;
152
153 if (mVertexBuffer)
154 {
155 HRESULT result = mVertexBuffer->Lock(mWritePosition, requiredSpace, &mapPtr, 0);
156
157 if (FAILED(result))
158 {
159 ERR("Lock failed with error 0x%08x", result);
160 return NULL;
161 }
162
163 int attributeOffset = attribute.mOffset % attribute.stride();
164 VertexElement element = {attribute.mType, attribute.mSize, attribute.stride(), attribute.mNormalized, attributeOffset, mWritePosition};
165 mCache.push_back(element);
166
167 *streamOffset = mWritePosition;
168 mWritePosition += requiredSpace;
169 }
170
171 return mapPtr;
172}
173
174void StaticVertexBuffer::reserveRequiredSpace()
175{
176 if (!mVertexBuffer && mBufferSize == 0)
177 {
178 // D3D9_REPLACE
179 HRESULT result = mRenderer->createVertexBuffer(mRequiredSpace, D3DUSAGE_WRITEONLY, &mVertexBuffer);
180 mSerial = issueSerial();
181
182 if (FAILED(result))
183 {
184 ERR("Out of memory allocating a vertex buffer of size %lu.", mRequiredSpace);
185 }
186
187 mBufferSize = mRequiredSpace;
188 }
189 else if (mVertexBuffer && mBufferSize >= mRequiredSpace)
190 {
191 // Already allocated
192 }
193 else UNREACHABLE(); // Static vertex buffers can't be resized
194
195 mRequiredSpace = 0;
196}
197
198std::size_t StaticVertexBuffer::lookupAttribute(const gl::VertexAttribute &attribute)
199{
200 for (unsigned int element = 0; element < mCache.size(); element++)
201 {
202 if (mCache[element].type == attribute.mType &&
203 mCache[element].size == attribute.mSize &&
204 mCache[element].stride == attribute.stride() &&
205 mCache[element].normalized == attribute.mNormalized)
206 {
207 if (mCache[element].attributeOffset == attribute.mOffset % attribute.stride())
208 {
209 return mCache[element].streamOffset;
210 }
211 }
212 }
213
214 return -1;
215}
216
217}