2 * Test GL_ARB_vertex_buffer_object
3 * Also test GL_ARB_vertex_array_object if supported
18 #define NUM_OBJECTS 10
22 GLuint ArrayObjectID
; /** GL_ARB_vertex_array_object */
23 GLuint VertexBufferID
;
25 GLuint ElementsBufferID
;
34 static struct object Objects
[NUM_OBJECTS
];
35 static GLuint NumObjects
;
39 static GLfloat Xrot
= 0, Yrot
= 0, Zrot
= 0;
40 static GLboolean Anim
= GL_TRUE
;
41 static GLboolean Have_ARB_vertex_array_object
= GL_FALSE
;
44 static void CheckError(int line
)
46 GLenum err
= glGetError();
48 printf("GL Error 0x%x at line %d\n", (int) err
, line
);
53 static void DrawObject( const struct object
*obj
)
55 if (Have_ARB_vertex_array_object
&& obj
->ArrayObjectID
) {
56 glBindVertexArray(obj
->ArrayObjectID
);
58 if (obj
->NumElements
> 0) {
60 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB
, obj
->ElementsBufferID
);
61 glDrawElements(GL_LINE_LOOP
, obj
->NumElements
, GL_UNSIGNED_INT
, NULL
);
64 /* non-indexed arrays */
65 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB
, 0);
66 glDrawArrays(GL_LINE_LOOP
, 0, obj
->NumVerts
);
72 /* no vertex array objects, must set vertex/color pointers per draw */
74 glBindBufferARB(GL_ARRAY_BUFFER_ARB
, obj
->VertexBufferID
);
75 glVertexPointer(3, GL_FLOAT
, obj
->VertexStride
, (void *) obj
->VertexOffset
);
76 glEnable(GL_VERTEX_ARRAY
);
78 /* test push/pop attrib */
79 /* XXX this leads to a segfault with NVIDIA's 53.36 driver */
83 glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT
);
84 /*glVertexPointer(3, GL_FLOAT, 0, (void *) (obj->VertexOffset + 10000));*/
85 glBindBufferARB(GL_ARRAY_BUFFER_ARB
, 999999);
89 glBindBufferARB(GL_ARRAY_BUFFER_ARB
, obj
->ColorBufferID
);
90 glColorPointer(3, GL_FLOAT
, obj
->ColorStride
, (void *) obj
->ColorOffset
);
91 glEnable(GL_COLOR_ARRAY
);
93 if (obj
->NumElements
> 0) {
95 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB
, obj
->ElementsBufferID
);
96 glDrawElements(GL_LINE_LOOP
, obj
->NumElements
, GL_UNSIGNED_INT
, NULL
);
99 /* non-indexed arrays */
100 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB
, 0);
101 glDrawArrays(GL_LINE_LOOP
, 0, obj
->NumVerts
);
107 static void Idle( void )
109 Zrot
= 0.05 * glutGet(GLUT_ELAPSED_TIME
);
114 static void Display( void )
118 glClear( GL_COLOR_BUFFER_BIT
);
120 for (i
= 0; i
< NumObjects
; i
++) {
121 float x
= 7.0 * ((float) i
/ (NumObjects
-1) - 0.5);
123 glTranslatef(x
, 0, 0);
124 glRotatef(Xrot
, 1, 0, 0);
125 glRotatef(Yrot
, 0, 1, 0);
126 glRotatef(Zrot
, 0, 0, 1);
128 DrawObject(Objects
+ i
);
133 CheckError(__LINE__
);
138 static void Reshape( int width
, int height
)
140 float ar
= (float) width
/ (float) height
;
141 glViewport( 0, 0, width
, height
);
142 glMatrixMode( GL_PROJECTION
);
144 glFrustum( -ar
, ar
, -1.0, 1.0, 5.0, 25.0 );
145 glMatrixMode( GL_MODELVIEW
);
147 glTranslatef( 0.0, 0.0, -15.0 );
151 static void FreeBuffers(void)
154 for (i
= 0; i
< NUM_OBJECTS
; i
++) {
155 glDeleteBuffersARB(1, &Objects
[i
].VertexBufferID
);
156 glDeleteBuffersARB(1, &Objects
[i
].ColorBufferID
);
157 glDeleteBuffersARB(1, &Objects
[i
].ElementsBufferID
);
162 static void Key( unsigned char key
, int x
, int y
)
164 const GLfloat step
= 3.0;
183 glutDestroyWindow(Win
);
191 static void SpecialKey( int key
, int x
, int y
)
193 const GLfloat step
= 3.0;
215 * If GL_ARB_vertex_array_object is supported, create an array object
216 * and set all the per-array state.
219 CreateVertexArrayObject(struct object
*obj
)
221 glGenVertexArrays(1, &obj
->ArrayObjectID
);
222 glBindVertexArray(obj
->ArrayObjectID
);
224 glBindBufferARB(GL_ARRAY_BUFFER_ARB
, obj
->VertexBufferID
);
225 glVertexPointer(3, GL_FLOAT
, obj
->VertexStride
, (void *) obj
->VertexOffset
);
226 glEnable(GL_VERTEX_ARRAY
);
228 glBindBufferARB(GL_ARRAY_BUFFER_ARB
, obj
->ColorBufferID
);
229 glColorPointer(3, GL_FLOAT
, obj
->ColorStride
, (void *) obj
->ColorOffset
);
230 glEnable(GL_COLOR_ARRAY
);
232 glBindVertexArray(0);
237 * Non-interleaved position/color data.
239 static void MakeObject1(struct object
*obj
)
246 for (i
= 0; i
< 500; i
++)
247 buffer
[i
] = i
& 0xff;
249 obj
->VertexBufferID
= 0;
250 glGenBuffersARB(1, &obj
->VertexBufferID
);
251 obj
->ColorBufferID
= obj
->VertexBufferID
;
252 assert(obj
->VertexBufferID
!= 0);
253 glBindBufferARB(GL_ARRAY_BUFFER_ARB
, obj
->VertexBufferID
);
254 glBufferDataARB(GL_ARRAY_BUFFER_ARB
, 500, buffer
, GL_STATIC_DRAW_ARB
);
256 for (i
= 0; i
< 500; i
++)
259 glGetBufferSubDataARB(GL_ARRAY_BUFFER_ARB
, 0, 500, buffer
);
261 for (i
= 0; i
< 500; i
++)
262 assert(buffer
[i
] == (i
& 0xff));
264 glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB
, GL_BUFFER_MAPPED_ARB
, &i
);
267 glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB
, GL_BUFFER_USAGE_ARB
, &i
);
269 v
= (GLfloat
*) glMapBufferARB(GL_ARRAY_BUFFER_ARB
, GL_WRITE_ONLY_ARB
);
271 /* do some sanity tests */
272 glGetBufferPointervARB(GL_ARRAY_BUFFER_ARB
, GL_BUFFER_MAP_POINTER_ARB
, &p
);
275 glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB
, GL_BUFFER_SIZE_ARB
, &i
);
278 glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB
, GL_BUFFER_USAGE_ARB
, &i
);
279 assert(i
== GL_STATIC_DRAW_ARB
);
281 glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB
, GL_BUFFER_ACCESS_ARB
, &i
);
282 assert(i
== GL_WRITE_ONLY_ARB
);
284 glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB
, GL_BUFFER_MAPPED_ARB
, &i
);
288 v
[0] = -1; v
[1] = -1; v
[2] = 0;
289 v
[3] = 1; v
[4] = -1; v
[5] = 0;
290 v
[6] = 1; v
[7] = 1; v
[8] = 0;
291 v
[9] = -1; v
[10] = 1; v
[11] = 0;
293 c
[0] = 1; c
[1] = 0; c
[2] = 0;
294 c
[3] = 1; c
[4] = 0; c
[5] = 0;
295 c
[6] = 1; c
[7] = 0; c
[8] = 1;
296 c
[9] = 1; c
[10] = 0; c
[11] = 1;
298 obj
->VertexOffset
= 0;
299 obj
->ColorOffset
= 3 * sizeof(GLfloat
) * obj
->NumVerts
;
300 obj
->VertexStride
= 0;
301 obj
->ColorStride
= 0;
302 obj
->NumElements
= 0;
304 glUnmapBufferARB(GL_ARRAY_BUFFER_ARB
);
306 glGetBufferPointervARB(GL_ARRAY_BUFFER_ARB
, GL_BUFFER_MAP_POINTER_ARB
, &p
);
309 glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB
, GL_BUFFER_MAPPED_ARB
, &i
);
312 if (Have_ARB_vertex_array_object
) {
313 CreateVertexArrayObject(obj
);
319 * Interleaved position/color data.
321 static void MakeObject2(struct object
*obj
)
324 int start
= 40; /* bytes, to test non-zero array offsets */
326 glGenBuffersARB(1, &obj
->VertexBufferID
);
327 obj
->ColorBufferID
= obj
->VertexBufferID
;
329 glBindBufferARB(GL_ARRAY_BUFFER_ARB
, obj
->VertexBufferID
);
330 glBufferDataARB(GL_ARRAY_BUFFER_ARB
, 1000, NULL
, GL_STATIC_DRAW_ARB
);
331 v
= (GLfloat
*) glMapBufferARB(GL_ARRAY_BUFFER_ARB
, GL_WRITE_ONLY_ARB
);
333 v
+= start
/ sizeof(GLfloat
);
335 /* Make triangle: interleaved colors, then positions */
337 v
[0] = 0; v
[1] = 1; v
[2] = 0; v
[3] = -1; v
[4] = -1; v
[5] = 0;
338 v
[6] = 0; v
[7] = 1; v
[8] = 0; v
[9] = 1; v
[10] = -1; v
[11] = 0;
339 v
[12] = 1; v
[13] = 1; v
[14] = 0; v
[15] = 0; v
[16] = 1; v
[17] = 0;
342 obj
->VertexOffset
= start
+ 3 * sizeof(GLfloat
);
343 obj
->ColorOffset
= start
;
344 obj
->VertexStride
= 6 * sizeof(GLfloat
);
345 obj
->ColorStride
= 6 * sizeof(GLfloat
);
347 obj
->NumElements
= 0;
349 glUnmapBufferARB(GL_ARRAY_BUFFER_ARB
);
351 if (Have_ARB_vertex_array_object
) {
352 CreateVertexArrayObject(obj
);
358 * Use an index buffer and glDrawElements().
360 static void MakeObject3(struct object
*obj
)
362 GLfloat vertexData
[1000];
369 v
[0] = -1; v
[1] = -0.5; v
[2] = 0;
370 v
[3] = 1; v
[4] = -0.5; v
[5] = 0;
371 v
[6] = 1; v
[7] = 0.5; v
[8] = 0;
372 v
[9] = -1; v
[10] = 0.5; v
[11] = 0;
374 c
[0] = 0; c
[1] = 0; c
[2] = 1;
375 c
[3] = 0; c
[4] = 0; c
[5] = 1;
376 c
[6] = 0; c
[7] = 1; c
[8] = 1;
377 c
[9] = 0; c
[10] = 1; c
[11] = 1;
379 obj
->VertexOffset
= 0;
380 obj
->ColorOffset
= 3 * sizeof(GLfloat
) * obj
->NumVerts
;
381 obj
->VertexStride
= 0;
382 obj
->ColorStride
= 0;
384 bytes
= obj
->NumVerts
* (3 + 3) * sizeof(GLfloat
);
386 /* Don't use glMap/UnmapBuffer for this object */
387 glGenBuffersARB(1, &obj
->VertexBufferID
);
388 obj
->ColorBufferID
= obj
->VertexBufferID
;
390 glBindBufferARB(GL_ARRAY_BUFFER_ARB
, obj
->VertexBufferID
);
391 glBufferDataARB(GL_ARRAY_BUFFER_ARB
, bytes
, vertexData
, GL_STATIC_DRAW_ARB
);
393 /* Setup a buffer of indices to test the ELEMENTS path */
394 glGenBuffersARB(1, &obj
->ElementsBufferID
);
395 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB
, obj
->ElementsBufferID
);
396 glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB
, 100, NULL
, GL_STATIC_DRAW_ARB
);
397 i
= (GLuint
*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB
, GL_READ_WRITE_ARB
);
402 glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB
);
403 obj
->NumElements
= 4;
405 if (Have_ARB_vertex_array_object
) {
406 CreateVertexArrayObject(obj
);
412 * Vertex and color data in different buffers.
414 static void MakeObject4(struct object
*obj
)
416 static const GLfloat vertexData
[] = {
422 static const GLfloat colorData
[] = {
429 obj
->VertexOffset
= 0;
430 obj
->VertexStride
= 0;
431 obj
->ColorOffset
= 0;
432 obj
->ColorStride
= 0;
435 glGenBuffersARB(1, &obj
->VertexBufferID
);
436 glBindBufferARB(GL_ARRAY_BUFFER_ARB
, obj
->VertexBufferID
);
437 glBufferDataARB(GL_ARRAY_BUFFER_ARB
, sizeof(vertexData
), vertexData
,
440 glGenBuffersARB(1, &obj
->ColorBufferID
);
441 glBindBufferARB(GL_ARRAY_BUFFER_ARB
, obj
->ColorBufferID
);
442 glBufferDataARB(GL_ARRAY_BUFFER_ARB
, sizeof(colorData
), colorData
,
445 /* Setup a buffer of indices to test the ELEMENTS path */
446 obj
->ElementsBufferID
= 0;
447 obj
->NumElements
= 0;
449 if (Have_ARB_vertex_array_object
) {
450 CreateVertexArrayObject(obj
);
456 static void Init( void )
458 if (!glutExtensionSupported("GL_ARB_vertex_buffer_object")) {
459 printf("GL_ARB_vertex_buffer_object not found!\n");
462 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER
));
464 Have_ARB_vertex_array_object
=
465 glutExtensionSupported("GL_ARB_vertex_array_object");
467 printf("Using GL_ARB_vertex_array_object: %s\n",
468 (Have_ARB_vertex_array_object
? "yes" : "no"));
471 /* Test buffer object deletion */
473 static GLubyte data
[1000];
475 glBindBufferARB(GL_ARRAY_BUFFER_ARB
, id
);
476 glBufferDataARB(GL_ARRAY_BUFFER_ARB
, 1000, data
, GL_STATIC_DRAW_ARB
);
477 glVertexPointer(3, GL_FLOAT
, 0, (void *) 0);
478 glDeleteBuffersARB(1, &id
);
479 assert(!glIsBufferARB(id
));
480 glBindBufferARB(GL_ARRAY_BUFFER_ARB
, 0);
481 glVertexPointer(3, GL_FLOAT
, 0, (void *) 0);
482 assert(!glIsBufferARB(id
));
485 memset(Objects
, 0, sizeof(Objects
));
486 MakeObject1(Objects
+ 0);
487 MakeObject2(Objects
+ 1);
488 MakeObject3(Objects
+ 2);
489 MakeObject4(Objects
+ 3);
494 int main( int argc
, char *argv
[] )
496 glutInit( &argc
, argv
);
497 glutInitWindowPosition( 0, 0 );
498 glutInitWindowSize( 600, 300 );
499 glutInitDisplayMode( GLUT_RGB
| GLUT_DOUBLE
);
500 Win
= glutCreateWindow(argv
[0]);
502 glutReshapeFunc( Reshape
);
503 glutKeyboardFunc( Key
);
504 glutSpecialFunc( SpecialKey
);
505 glutDisplayFunc( Display
);