-
Notifications
You must be signed in to change notification settings - Fork 1.4k
/
VertexBufferObject.java
226 lines (177 loc) · 6.54 KB
/
VertexBufferObject.java
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
package org.andengine.opengl.vbo;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import org.andengine.opengl.shader.ShaderProgram;
import org.andengine.opengl.util.BufferUtils;
import org.andengine.opengl.util.GLState;
import org.andengine.opengl.vbo.attribute.VertexBufferObjectAttributes;
import org.andengine.util.adt.DataConstants;
import android.opengl.GLES20;
/**
* TODO Extract a common base class from {@link VertexBufferObject} and {@link ZeroMemoryVertexBufferObject} (due to significant code duplication).
* For naming, maybe be inspired by the java ByteBuffer naming (i.e. HeapBackedFloatArrayVertexBufferObject, StreamBufferVertexBufferObject, SharedBufferStreamVertexBufferObject).
*
* (c) 2010 Nicolas Gramlich
* (c) 2011 Zynga Inc.
*
* @author Nicolas Gramlich
* @since 14:22:56 - 07.04.2010
*/
public abstract class VertexBufferObject implements IVertexBufferObject {
// ===========================================================
// Constants
// ===========================================================
// ===========================================================
// Fields
// ===========================================================
protected final int mCapacity;
protected final boolean mAutoDispose;
protected final int mUsage;
protected final ByteBuffer mByteBuffer;
protected int mHardwareBufferID = IVertexBufferObject.HARDWARE_BUFFER_ID_INVALID;
protected boolean mDirtyOnHardware = true;
protected boolean mDisposed;
protected final VertexBufferObjectManager mVertexBufferObjectManager;
protected final VertexBufferObjectAttributes mVertexBufferObjectAttributes;
// ===========================================================
// Constructors
// ===========================================================
/**
* @param pVertexBufferObjectManager (optional, if you manage reloading on your own.)
* @param pCapacity
* @param pDrawType
* @param pAutoDispose when passing <code>true</code> this {@link VertexBufferObject} loads itself to the active {@link VertexBufferObjectManager}. <b><u>WARNING:</u></b> When passing <code>false</code> one needs to take care of that by oneself!
* @param pVertexBufferObjectAttributes to be automatically enabled on the {@link ShaderProgram} used in {@link VertexBufferObject#bind(ShaderProgram)}.
*/
public VertexBufferObject(final VertexBufferObjectManager pVertexBufferObjectManager, final int pCapacity, final DrawType pDrawType, final boolean pAutoDispose, final VertexBufferObjectAttributes pVertexBufferObjectAttributes) {
this.mVertexBufferObjectManager = pVertexBufferObjectManager;
this.mCapacity = pCapacity;
this.mUsage = pDrawType.getUsage();
this.mAutoDispose = pAutoDispose;
this.mVertexBufferObjectAttributes = pVertexBufferObjectAttributes;
this.mByteBuffer = BufferUtils.allocateDirectByteBuffer(pCapacity * DataConstants.BYTES_PER_FLOAT);
this.mByteBuffer.order(ByteOrder.nativeOrder());
}
// ===========================================================
// Getter & Setter
// ===========================================================
@Override
public VertexBufferObjectManager getVertexBufferObjectManager() {
return this.mVertexBufferObjectManager;
}
@Override
public boolean isDisposed() {
return this.mDisposed;
}
@Override
public boolean isAutoDispose() {
return this.mAutoDispose;
}
@Override
public int getHardwareBufferID() {
return this.mHardwareBufferID;
}
@Override
public boolean isLoadedToHardware() {
return this.mHardwareBufferID != IVertexBufferObject.HARDWARE_BUFFER_ID_INVALID;
}
@Override
public void setNotLoadedToHardware() {
this.mHardwareBufferID = IVertexBufferObject.HARDWARE_BUFFER_ID_INVALID;
this.mDirtyOnHardware = true;
}
@Override
public boolean isDirtyOnHardware() {
return this.mDirtyOnHardware;
}
@Override
public void setDirtyOnHardware() {
this.mDirtyOnHardware = true;
}
@Override
public int getCapacity() {
return this.mCapacity;
}
@Override
public int getByteCapacity() {
return this.mByteBuffer.capacity();
}
@Override
public int getGPUMemoryByteSize() {
if(this.isLoadedToHardware()) {
return this.getByteCapacity();
} else {
return 0;
}
}
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
protected abstract void onBufferData();
@Override
public void bind(final GLState pGLState) {
if(this.mHardwareBufferID == IVertexBufferObject.HARDWARE_BUFFER_ID_INVALID) {
this.loadToHardware(pGLState);
if(this.mVertexBufferObjectManager != null) {
this.mVertexBufferObjectManager.onVertexBufferObjectLoaded(this);
}
}
pGLState.bindArrayBuffer(this.mHardwareBufferID);
if(this.mDirtyOnHardware) {
this.onBufferData();
this.mDirtyOnHardware = false;
}
}
@Override
public void bind(final GLState pGLState, final ShaderProgram pShaderProgram) {
this.bind(pGLState);
pShaderProgram.bind(pGLState, this.mVertexBufferObjectAttributes);
}
@Override
public void unbind(final GLState pGLState, final ShaderProgram pShaderProgram) {
pShaderProgram.unbind(pGLState);
// pGLState.bindBuffer(0); // TODO Does this have an positive/negative impact on performance?
}
@Override
public void unloadFromHardware(final GLState pGLState) {
pGLState.deleteArrayBuffer(this.mHardwareBufferID);
this.mHardwareBufferID = IVertexBufferObject.HARDWARE_BUFFER_ID_INVALID;
}
@Override
public void draw(final int pPrimitiveType, final int pCount) {
GLES20.glDrawArrays(pPrimitiveType, 0, pCount);
}
@Override
public void draw(final int pPrimitiveType, final int pOffset, final int pCount) {
GLES20.glDrawArrays(pPrimitiveType, pOffset, pCount);
}
@Override
public void dispose() {
if(!this.mDisposed) {
this.mDisposed = true;
if(this.mVertexBufferObjectManager != null) {
this.mVertexBufferObjectManager.onUnloadVertexBufferObject(this);
}
BufferUtils.freeDirectByteBuffer(this.mByteBuffer);
} else {
throw new AlreadyDisposedException();
}
}
@Override
protected void finalize() throws Throwable {
super.finalize();
if(!this.mDisposed) {
this.dispose();
}
}
// ===========================================================
// Methods
// ===========================================================
private void loadToHardware(final GLState pGLState) {
this.mHardwareBufferID = pGLState.generateBuffer();
this.mDirtyOnHardware = true;
}
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
}