blob: 226f38e1111e455624eb000af728e712037efc49 [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 }
32}
33
34VertexBuffer::~VertexBuffer()
35{
36 if (mVertexBuffer)
37 {
38 mVertexBuffer->Release();
39 }
40}
41
42void VertexBuffer::unmap()
43{
44 if (mVertexBuffer)
45 {
46 mVertexBuffer->Unlock();
47 }
48}
49
50IDirect3DVertexBuffer9 *VertexBuffer::getBuffer() const
51{
52 return mVertexBuffer;
53}
54
55unsigned int VertexBuffer::getSerial() const
56{
57 return mSerial;
58}
59
60unsigned int VertexBuffer::issueSerial()
61{
62 return mCurrentSerial++;
63}
64
65ArrayVertexBuffer::ArrayVertexBuffer(rx::Renderer9 *renderer, std::size_t size, DWORD usageFlags) : VertexBuffer(renderer, size, usageFlags)
66{
67 mBufferSize = size;
68 mWritePosition = 0;
69 mRequiredSpace = 0;
70}
71
72ArrayVertexBuffer::~ArrayVertexBuffer()
73{
74}
75
76void ArrayVertexBuffer::addRequiredSpace(UINT requiredSpace)
77{
78 mRequiredSpace += requiredSpace;
79}
80
81StreamingVertexBuffer::StreamingVertexBuffer(rx::Renderer9 *renderer, std::size_t initialSize) : ArrayVertexBuffer(renderer, initialSize, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY)
82{
83}
84
85StreamingVertexBuffer::~StreamingVertexBuffer()
86{
87}
88
89void *StreamingVertexBuffer::map(const gl::VertexAttribute &attribute, std::size_t requiredSpace, std::size_t *offset)
90{
91 void *mapPtr = NULL;
92
93 if (mVertexBuffer)
94 {
95 HRESULT result = mVertexBuffer->Lock(mWritePosition, requiredSpace, &mapPtr, D3DLOCK_NOOVERWRITE);
96
97 if (FAILED(result))
98 {
99 ERR("Lock failed with error 0x%08x", result);
100 return NULL;
101 }
102
103 *offset = mWritePosition;
104 mWritePosition += requiredSpace;
105 }
106
107 return mapPtr;
108}
109
110void StreamingVertexBuffer::reserveRequiredSpace()
111{
112 if (mRequiredSpace > mBufferSize)
113 {
114 if (mVertexBuffer)
115 {
116 mVertexBuffer->Release();
117 mVertexBuffer = NULL;
118 }
119
120 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.
121
122 // D3D9_REPLACE
123 HRESULT result = mRenderer->createVertexBuffer(mBufferSize, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, &mVertexBuffer);
124 mSerial = issueSerial();
125
126 if (FAILED(result))
127 {
128 ERR("Out of memory allocating a vertex buffer of size %lu.", mBufferSize);
129 }
130
131 mWritePosition = 0;
132 }
133 else if (mWritePosition + mRequiredSpace > mBufferSize) // Recycle
134 {
135 if (mVertexBuffer)
136 {
137 void *dummy;
138 mVertexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
139 mVertexBuffer->Unlock();
140 }
141
142 mWritePosition = 0;
143 }
144
145 mRequiredSpace = 0;
146}
147
148StaticVertexBuffer::StaticVertexBuffer(rx::Renderer9 *renderer) : ArrayVertexBuffer(renderer, 0, D3DUSAGE_WRITEONLY)
149{
150}
151
152StaticVertexBuffer::~StaticVertexBuffer()
153{
154}
155
156void *StaticVertexBuffer::map(const gl::VertexAttribute &attribute, std::size_t requiredSpace, std::size_t *streamOffset)
157{
158 void *mapPtr = NULL;
159
160 if (mVertexBuffer)
161 {
162 HRESULT result = mVertexBuffer->Lock(mWritePosition, requiredSpace, &mapPtr, 0);
163
164 if (FAILED(result))
165 {
166 ERR("Lock failed with error 0x%08x", result);
167 return NULL;
168 }
169
170 int attributeOffset = attribute.mOffset % attribute.stride();
171 VertexElement element = {attribute.mType, attribute.mSize, attribute.stride(), attribute.mNormalized, attributeOffset, mWritePosition};
172 mCache.push_back(element);
173
174 *streamOffset = mWritePosition;
175 mWritePosition += requiredSpace;
176 }
177
178 return mapPtr;
179}
180
181void StaticVertexBuffer::reserveRequiredSpace()
182{
183 if (!mVertexBuffer && mBufferSize == 0)
184 {
185 // D3D9_REPLACE
186 HRESULT result = mRenderer->createVertexBuffer(mRequiredSpace, D3DUSAGE_WRITEONLY, &mVertexBuffer);
187 mSerial = issueSerial();
188
189 if (FAILED(result))
190 {
191 ERR("Out of memory allocating a vertex buffer of size %lu.", mRequiredSpace);
192 }
193
194 mBufferSize = mRequiredSpace;
195 }
196 else if (mVertexBuffer && mBufferSize >= mRequiredSpace)
197 {
198 // Already allocated
199 }
200 else UNREACHABLE(); // Static vertex buffers can't be resized
201
202 mRequiredSpace = 0;
203}
204
205std::size_t StaticVertexBuffer::lookupAttribute(const gl::VertexAttribute &attribute)
206{
207 for (unsigned int element = 0; element < mCache.size(); element++)
208 {
209 if (mCache[element].type == attribute.mType &&
210 mCache[element].size == attribute.mSize &&
211 mCache[element].stride == attribute.stride() &&
212 mCache[element].normalized == attribute.mNormalized)
213 {
214 if (mCache[element].attributeOffset == attribute.mOffset % attribute.stride())
215 {
216 return mCache[element].streamOffset;
217 }
218 }
219 }
220
221 return -1;
222}
223
224}