1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
|
/*
* Copyright 2009, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// This file contains the declaration for the Buffer, VertexBuffer and
// IndexBuffer classes.
#ifndef O3D_CORE_CROSS_BUFFER_H_
#define O3D_CORE_CROSS_BUFFER_H_
#include <vector>
#include "core/cross/field.h"
#include "core/cross/named_object.h"
#include "core/cross/types.h"
#include "base/scoped_ptr.h"
namespace o3d {
class RawData;
class Features;
// class Buffer -----------------------------
//
// DESIGN GOALS:the Buffer object is a low level container for a flat list of
// floating point or integer values. These are used to define geometry,
// parameter buffers and to hold animation data.
//
// The default implementation of the Buffer doesn't do much. Each render system
// (e.g. D3D, OGL, etc) should derive its own version of a Buffer that handles
// the underlying data resources appropriately
// The Buffer object is a low level container for a flat list of
// floating point or integer values. These are currently used to define
// geometry. Buffer is an abstract class and only declares the interface for
// buffer operations. Data storage needs to be allocated by derived classes.
class Buffer : public NamedObject {
public:
typedef SmartPointer<Buffer> Ref;
// Defines how you want to access a buffer when locking.
enum AccessMode {
NONE = 0,
READ_ONLY = 1,
WRITE_ONLY = 2,
READ_WRITE = 3,
};
// Yes, 65534 is the correct number. Specifically the Intel 945 only allows
// 65534 elements.
static const unsigned MAX_SMALL_INDEX = 65534;
// Yes, Sadly many modern cards only support 1048575 vertices.
static const unsigned MAX_LARGE_INDEX = 1048575;
// A four-character identifier used in the binary serialization format
// (not exposed to Javascript)
static const char *kSerializationID;
explicit Buffer(ServiceLocator* service_locator);
~Buffer();
// Allocates memory for the data to be stored in the buffer
bool AllocateElements(unsigned int num_elements);
// Frees any data currently allocated for this buffer.
void Free();
// Creates a field on this buffer
// Parameters:
// field_type: type of field.
// num_components: number of components.
// Returns:
// Pointer to created field.
Field* CreateField(const ObjectBase::Class* field_type,
unsigned num_components);
// Creates a field on this buffer
//
// this is for Javascript
//
// Paramters:
// field_type_name: name of type of field.
// num_components: number of components.
// Returns:
// Pointer to created field.
Field* CreateFieldByClassName(const String& field_type_name,
unsigned num_components);
// Removes a field
// Parameters:
// field: Field to remove.
void RemoveField(Field* field);
// Returns the stride of the buffer.
unsigned int stride() const {
return stride_;
}
// Returns the number of components per element. In other words the sum
// of all the components in all fields.
unsigned int total_components() const {
return total_components_;
}
// Returns the field change count. Anytime a field is added, removed or
// changed this value is incremented. Streams track it so they know
// to rebuild vertex declarations based on the buffer changing format.
unsigned int field_change_count() const {
return field_change_count_;
}
// Obtains a pointer to the memory location where the data is stored.
// This method should get called before data stored in the buffer can be
// modified. From C++ use LockAs
// Parameters:
// access_mode: How you want to access the data.
// buffer_data: pointer to void pointer to receive pointer to data.
// Returns:
// true if the operation succeeds.
bool Lock(AccessMode access_mode, void** buffer_data);
// Notifies that updates to the buffer data are completed. Once Unlock
// is called data should not be modified any more.
bool Unlock();
// Gets the number of elements.
unsigned int num_elements() const {
return num_elements_;
}
// Gets the array of fields.
const FieldRefArray& fields() const {
return fields_;
}
// Returns the size of the buffer in bytes.
size_t GetSizeInBytes() const {
return num_elements_ * stride_;
}
// A typed version of Lock
template <typename T>
bool LockAs(AccessMode access_mode, T** buffer_data) {
return Lock(access_mode, reinterpret_cast<void**>(buffer_data));
}
// De-serializes the data contained in |raw_data|
// The entire contents of |raw_data| from start to finish will
// be used
bool Set(o3d::RawData *raw_data);
// De-serializes the data contained in |raw_data|
// starting at byte offset |offset| and using |length|
// bytes
bool Set(o3d::RawData *raw_data,
size_t offset,
size_t length);
protected:
// The concrete version of AllocateElements.
virtual bool ConcreteAllocate(size_t size_in_bytes) = 0;
// The concrete version of Free
virtual void ConcreteFree() = 0;
// The concrete version of Lock. Platform specific versions of buffers
// need to override this.
//
// Parameters:
// access_mode: How you want to access the data. buffer_data: pointer to
// void pointer to receive pointer to data.
// Returns:
// true if the operation succeeds.
virtual bool ConcreteLock(AccessMode access_mode, void** buffer_data) = 0;
// The concrete version of Unlock. Platform specific versions of buffers need
// to override this.
virtual bool ConcreteUnlock() = 0;
private:
// Takes the data currently allocated and copies it to new data of a different
// stride.
// Parameters:
// new_stride: stride of new buffer.
// field_to_remove: address of field. If NULL no field is removed.
bool ReshuffleBuffer(unsigned int new_stride, Field* field_to_remove);
void AdjustBufferMemoryInfo(bool add);
Features* features_;
// Fields.
FieldRefArray fields_;
// The number of times fields have been added or removed. Streams
// can track this value so they can know if they need to update.
unsigned int field_change_count_;
// The total number of components in all fields.
unsigned int total_components_;
// The stride of the buffer.
unsigned int stride_;
// The current number of elements in the buffer.
unsigned int num_elements_;
// The mode the buffer is currently being accessed so we can fail if a
// different mode is requested
AccessMode access_mode_;
// The number of times this buffer has been locked.
int lock_count_;
// Pointer to data when it's locked.
void* locked_data_;
O3D_DECL_CLASS(Buffer, NamedObject);
};
// VertexBufferBase is just here so VertexBuffer and SourceBuffer can share IDL
// glue.
class VertexBufferBase : public Buffer {
public:
typedef SmartPointer<VertexBufferBase> Ref;
protected:
explicit VertexBufferBase(ServiceLocator* service_locator);
private:
O3D_DECL_CLASS(VertexBufferBase, Buffer);
DISALLOW_COPY_AND_ASSIGN(VertexBufferBase);
};
// VertexBuffer is Buffer object used for storing vertex data for geometry
// (e.g. vertex positions, normals, colors, etc). It is an abstract class
// declaring the interface only. Each rendering platform should derive its own
// implementation of the interface.
//
// NOTE: You can not READ data from a VertexBuffer.
class VertexBuffer : public VertexBufferBase {
public:
typedef SmartPointer<VertexBuffer> Ref;
protected:
explicit VertexBuffer(ServiceLocator* service_locator);
private:
friend class IClassManager;
static ObjectBase::Ref Create(ServiceLocator* service_locator);
O3D_DECL_CLASS(VertexBuffer, VertexBufferBase);
DISALLOW_COPY_AND_ASSIGN(VertexBuffer);
};
// SourceBuffer is a buffer object stored in system memory. It is used as
// the source for skinning, morph targets, etc.
class SourceBuffer : public VertexBufferBase {
public:
typedef SmartPointer<SourceBuffer> Ref;
~SourceBuffer();
protected:
// Overridden from Buffer.
virtual bool ConcreteAllocate(size_t size_in_bytes);
// Overridden from Buffer.
virtual bool ConcreteLock(AccessMode access_mode, void **buffer_data);
// Overridden from Buffer.
virtual bool ConcreteUnlock();
explicit SourceBuffer(ServiceLocator* service_locator);
protected:
// Frees the buffer if it exists.
void ConcreteFree();
private:
friend class IClassManager;
static ObjectBase::Ref Create(ServiceLocator* service_locator);
scoped_array<char> buffer_; // The actual data for this buffer.
O3D_DECL_CLASS(SourceBuffer, VertexBufferBase);
DISALLOW_COPY_AND_ASSIGN(SourceBuffer);
};
// IndexBuffer is a buffer object used for storing geometry index data (e.g.
// triangle indices). It is an abstract class declaring the interface only.
// Each rendering platform should derive its own implementation of the
// interface.
//
// NOTE: You can not READ data from an IndexBuffer.
class IndexBuffer : public Buffer {
public:
typedef SmartPointer<IndexBuffer> Ref;
Field* index_field() const;
// De-serializes the data contained in |raw_data|
// The entire contents of |raw_data| from start to finish will
// be used
bool Set(o3d::RawData *raw_data) {
return Buffer::Set(raw_data);
}
// De-serializes the data contained in |raw_data|
// starting at byte offset |offset| and using |length|
// bytes
bool Set(o3d::RawData *raw_data,
size_t offset,
size_t length) {
return Buffer::Set(raw_data, offset, length);
}
protected:
explicit IndexBuffer(ServiceLocator* service_locator);
private:
friend class IClassManager;
static ObjectBase::Ref Create(ServiceLocator* service_locator);
O3D_DECL_CLASS(IndexBuffer, Buffer);
DISALLOW_COPY_AND_ASSIGN(IndexBuffer);
};
// BufferLockHelper can be used to lock a buffer in a safe way in that it will
// unlock the buffer on destruction so you can use it like this
//
// {
// BufferLockHelper helper(my_buffer);
// void* data = helper.GetData();
// if (data) {
// .. do something with data here ..
// }
// }
//
// Because there is no need to call Unlock it is much easier to deal with error
// conditions.
class BufferLockHelper {
public:
explicit BufferLockHelper(Buffer* buffer);
~BufferLockHelper();
// Gets a pointer to the data of the buffer, locking the buffer if necessary.
// Returns:
// Pointer to data in buffer or NULL if there was an error.
void* GetData(Buffer::AccessMode access_mode);
// Typed version of GetData
template <typename T>
T* GetDataAs(Buffer::AccessMode access_mode) {
return reinterpret_cast<T*>(GetData(access_mode));
}
private:
Buffer* buffer_;
void* data_;
bool locked_;
DISALLOW_COPY_AND_ASSIGN(BufferLockHelper);
};
} // namespace o3d
#endif // O3D_CORE_CROSS_BUFFER_H_
|