Merge branch 'mesa_7_5_branch'
[mesa.git] / progs / tests / bufferobj.c
1 /*
2 * Test GL_ARB_vertex_buffer_object
3 * Also test GL_ARB_vertex_array_object if supported
4 *
5 * Brian Paul
6 * 16 Sep 2003
7 */
8
9
10 #include <assert.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <math.h>
15 #include <GL/glew.h>
16 #include <GL/glut.h>
17
18 #define NUM_OBJECTS 10
19
20 struct object
21 {
22 GLuint ArrayObjectID; /** GL_ARB_vertex_array_object */
23 GLuint VertexBufferID;
24 GLuint ColorBufferID;
25 GLuint ElementsBufferID;
26 GLuint NumVerts;
27 GLuint VertexOffset;
28 GLuint ColorOffset;
29 GLuint VertexStride;
30 GLuint ColorStride;
31 GLuint NumElements;
32 };
33
34 static struct object Objects[NUM_OBJECTS];
35 static GLuint NumObjects;
36
37 static GLuint Win;
38
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;
42
43
44 static void CheckError(int line)
45 {
46 GLenum err = glGetError();
47 if (err) {
48 printf("GL Error 0x%x at line %d\n", (int) err, line);
49 }
50 }
51
52
53 static void DrawObject( const struct object *obj )
54 {
55 if (Have_ARB_vertex_array_object && obj->ArrayObjectID) {
56 glBindVertexArray(obj->ArrayObjectID);
57
58 if (obj->NumElements > 0) {
59 /* indexed arrays */
60 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, obj->ElementsBufferID);
61 glDrawElements(GL_LINE_LOOP, obj->NumElements, GL_UNSIGNED_INT, NULL);
62 }
63 else {
64 /* non-indexed arrays */
65 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
66 glDrawArrays(GL_LINE_LOOP, 0, obj->NumVerts);
67 }
68
69 glBindVertexArray(0);
70 }
71 else {
72 /* no vertex array objects, must set vertex/color pointers per draw */
73
74 glBindBufferARB(GL_ARRAY_BUFFER_ARB, obj->VertexBufferID);
75 glVertexPointer(3, GL_FLOAT, obj->VertexStride, (void *) obj->VertexOffset);
76 glEnableClientState(GL_VERTEX_ARRAY);
77
78 /* test push/pop attrib */
79 /* XXX this leads to a segfault with NVIDIA's 53.36 driver */
80 #if 0
81 if (1)
82 {
83 glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
84 /*glVertexPointer(3, GL_FLOAT, 0, (void *) (obj->VertexOffset + 10000));*/
85 glBindBufferARB(GL_ARRAY_BUFFER_ARB, 999999);
86 glPopClientAttrib();
87 }
88 #endif
89 glBindBufferARB(GL_ARRAY_BUFFER_ARB, obj->ColorBufferID);
90 glColorPointer(3, GL_FLOAT, obj->ColorStride, (void *) obj->ColorOffset);
91 glEnableClientState(GL_COLOR_ARRAY);
92
93 if (obj->NumElements > 0) {
94 /* indexed arrays */
95 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, obj->ElementsBufferID);
96 glDrawElements(GL_LINE_LOOP, obj->NumElements, GL_UNSIGNED_INT, NULL);
97 }
98 else {
99 /* non-indexed arrays */
100 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
101 glDrawArrays(GL_LINE_LOOP, 0, obj->NumVerts);
102 }
103 }
104 }
105
106
107 static void Idle( void )
108 {
109 Zrot = 0.05 * glutGet(GLUT_ELAPSED_TIME);
110 glutPostRedisplay();
111 }
112
113
114 static void Display( void )
115 {
116 int i;
117
118 glClear( GL_COLOR_BUFFER_BIT );
119
120 for (i = 0; i < NumObjects; i++) {
121 float x = 7.0 * ((float) i / (NumObjects-1) - 0.5);
122 glPushMatrix();
123 glTranslatef(x, 0, 0);
124 glRotatef(Xrot, 1, 0, 0);
125 glRotatef(Yrot, 0, 1, 0);
126 glRotatef(Zrot, 0, 0, 1);
127
128 DrawObject(Objects + i);
129
130 glPopMatrix();
131 }
132
133 CheckError(__LINE__);
134 glutSwapBuffers();
135 }
136
137
138 static void Reshape( int width, int height )
139 {
140 float ar = (float) width / (float) height;
141 glViewport( 0, 0, width, height );
142 glMatrixMode( GL_PROJECTION );
143 glLoadIdentity();
144 glFrustum( -ar, ar, -1.0, 1.0, 5.0, 25.0 );
145 glMatrixMode( GL_MODELVIEW );
146 glLoadIdentity();
147 glTranslatef( 0.0, 0.0, -15.0 );
148 }
149
150
151 static void FreeBuffers(void)
152 {
153 int i;
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);
158 }
159 }
160
161
162 static void Key( unsigned char key, int x, int y )
163 {
164 const GLfloat step = 3.0;
165 (void) x;
166 (void) y;
167 switch (key) {
168 case 'a':
169 Anim = !Anim;
170 if (Anim)
171 glutIdleFunc(Idle);
172 else
173 glutIdleFunc(NULL);
174 break;
175 case 'z':
176 Zrot -= step;
177 break;
178 case 'Z':
179 Zrot += step;
180 break;
181 case 27:
182 FreeBuffers();
183 glutDestroyWindow(Win);
184 exit(0);
185 break;
186 }
187 glutPostRedisplay();
188 }
189
190
191 static void SpecialKey( int key, int x, int y )
192 {
193 const GLfloat step = 3.0;
194 (void) x;
195 (void) y;
196 switch (key) {
197 case GLUT_KEY_UP:
198 Xrot -= step;
199 break;
200 case GLUT_KEY_DOWN:
201 Xrot += step;
202 break;
203 case GLUT_KEY_LEFT:
204 Yrot -= step;
205 break;
206 case GLUT_KEY_RIGHT:
207 Yrot += step;
208 break;
209 }
210 glutPostRedisplay();
211 }
212
213
214 /**
215 * If GL_ARB_vertex_array_object is supported, create an array object
216 * and set all the per-array state.
217 */
218 static void
219 CreateVertexArrayObject(struct object *obj)
220 {
221 glGenVertexArrays(1, &obj->ArrayObjectID);
222 glBindVertexArray(obj->ArrayObjectID);
223
224 glBindBufferARB(GL_ARRAY_BUFFER_ARB, obj->VertexBufferID);
225 glVertexPointer(3, GL_FLOAT, obj->VertexStride, (void *) obj->VertexOffset);
226 glEnableClientState(GL_VERTEX_ARRAY);
227
228 glBindBufferARB(GL_ARRAY_BUFFER_ARB, obj->ColorBufferID);
229 glColorPointer(3, GL_FLOAT, obj->ColorStride, (void *) obj->ColorOffset);
230 glEnableClientState(GL_COLOR_ARRAY);
231
232 glBindVertexArray(0);
233 }
234
235
236 /*
237 * Non-interleaved position/color data.
238 */
239 static void MakeObject1(struct object *obj)
240 {
241 GLfloat *v, *c;
242 void *p;
243 int i;
244 GLubyte buffer[500];
245
246 for (i = 0; i < 500; i++)
247 buffer[i] = i & 0xff;
248
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);
255
256 for (i = 0; i < 500; i++)
257 buffer[i] = 0;
258
259 glGetBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, 500, buffer);
260
261 for (i = 0; i < 500; i++)
262 assert(buffer[i] == (i & 0xff));
263
264 glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_MAPPED_ARB, &i);
265 assert(!i);
266
267 glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_USAGE_ARB, &i);
268
269 v = (GLfloat *) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
270
271 /* do some sanity tests */
272 glGetBufferPointervARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_MAP_POINTER_ARB, &p);
273 assert(p == v);
274
275 glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &i);
276 assert(i == 500);
277
278 glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_USAGE_ARB, &i);
279 assert(i == GL_STATIC_DRAW_ARB);
280
281 glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_ACCESS_ARB, &i);
282 assert(i == GL_WRITE_ONLY_ARB);
283
284 glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_MAPPED_ARB, &i);
285 assert(i);
286
287 /* Make rectangle */
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;
292 c = v + 12;
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;
297 obj->NumVerts = 4;
298 obj->VertexOffset = 0;
299 obj->ColorOffset = 3 * sizeof(GLfloat) * obj->NumVerts;
300 obj->VertexStride = 0;
301 obj->ColorStride = 0;
302 obj->NumElements = 0;
303
304 glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
305
306 glGetBufferPointervARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_MAP_POINTER_ARB, &p);
307 assert(!p);
308
309 glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_MAPPED_ARB, &i);
310 assert(!i);
311
312 if (Have_ARB_vertex_array_object) {
313 CreateVertexArrayObject(obj);
314 }
315 }
316
317
318 /*
319 * Interleaved position/color data.
320 */
321 static void MakeObject2(struct object *obj)
322 {
323 GLfloat *v;
324 int start = 40; /* bytes, to test non-zero array offsets */
325
326 glGenBuffersARB(1, &obj->VertexBufferID);
327 obj->ColorBufferID = obj->VertexBufferID;
328
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);
332
333 v += start / sizeof(GLfloat);
334
335 /* Make triangle: interleaved colors, then positions */
336 /* R G B X Y Z */
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;
340
341 obj->NumVerts = 3;
342 obj->VertexOffset = start + 3 * sizeof(GLfloat);
343 obj->ColorOffset = start;
344 obj->VertexStride = 6 * sizeof(GLfloat);
345 obj->ColorStride = 6 * sizeof(GLfloat);
346
347 obj->NumElements = 0;
348
349 glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
350
351 if (Have_ARB_vertex_array_object) {
352 CreateVertexArrayObject(obj);
353 }
354 }
355
356
357 /*
358 * Use an index buffer and glDrawElements().
359 */
360 static void MakeObject3(struct object *obj)
361 {
362 GLfloat vertexData[1000];
363 GLfloat *v, *c;
364 GLuint *i;
365 int bytes;
366
367 /* Make rectangle */
368 v = vertexData;
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;
373 c = vertexData + 12;
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;
378 obj->NumVerts = 4;
379 obj->VertexOffset = 0;
380 obj->ColorOffset = 3 * sizeof(GLfloat) * obj->NumVerts;
381 obj->VertexStride = 0;
382 obj->ColorStride = 0;
383
384 bytes = obj->NumVerts * (3 + 3) * sizeof(GLfloat);
385
386 /* Don't use glMap/UnmapBuffer for this object */
387 glGenBuffersARB(1, &obj->VertexBufferID);
388 obj->ColorBufferID = obj->VertexBufferID;
389
390 glBindBufferARB(GL_ARRAY_BUFFER_ARB, obj->VertexBufferID);
391 glBufferDataARB(GL_ARRAY_BUFFER_ARB, bytes, vertexData, GL_STATIC_DRAW_ARB);
392
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);
398 i[0] = 0;
399 i[1] = 1;
400 i[2] = 2;
401 i[3] = 3;
402 glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
403 obj->NumElements = 4;
404
405 if (Have_ARB_vertex_array_object) {
406 CreateVertexArrayObject(obj);
407 }
408 }
409
410
411 /*
412 * Vertex and color data in different buffers.
413 */
414 static void MakeObject4(struct object *obj)
415 {
416 static const GLfloat vertexData[] = {
417 0, -1, 0,
418 0.5, 0, 0,
419 0, 1, 0,
420 -0.5, 0, 0
421 };
422 static const GLfloat colorData[] = {
423 1, 1, 1,
424 1, 1, 0,
425 .5, .5, 0,
426 1, 1, 0
427 };
428
429 obj->VertexOffset = 0;
430 obj->VertexStride = 0;
431 obj->ColorOffset = 0;
432 obj->ColorStride = 0;
433 obj->NumVerts = 4;
434
435 glGenBuffersARB(1, &obj->VertexBufferID);
436 glBindBufferARB(GL_ARRAY_BUFFER_ARB, obj->VertexBufferID);
437 glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(vertexData), vertexData,
438 GL_STATIC_DRAW_ARB);
439
440 glGenBuffersARB(1, &obj->ColorBufferID);
441 glBindBufferARB(GL_ARRAY_BUFFER_ARB, obj->ColorBufferID);
442 glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(colorData), colorData,
443 GL_STATIC_DRAW_ARB);
444
445 /* Setup a buffer of indices to test the ELEMENTS path */
446 obj->ElementsBufferID = 0;
447 obj->NumElements = 0;
448
449 if (Have_ARB_vertex_array_object) {
450 CreateVertexArrayObject(obj);
451 }
452 }
453
454
455
456 static void Init( void )
457 {
458 if (!glutExtensionSupported("GL_ARB_vertex_buffer_object")) {
459 printf("GL_ARB_vertex_buffer_object not found!\n");
460 exit(0);
461 }
462 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
463
464 Have_ARB_vertex_array_object =
465 glutExtensionSupported("GL_ARB_vertex_array_object");
466
467 printf("Using GL_ARB_vertex_array_object: %s\n",
468 (Have_ARB_vertex_array_object ? "yes" : "no"));
469
470
471 /* Test buffer object deletion */
472 if (1) {
473 static GLubyte data[1000];
474 GLuint id = 999;
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));
483 }
484
485 memset(Objects, 0, sizeof(Objects));
486 MakeObject1(Objects + 0);
487 MakeObject2(Objects + 1);
488 MakeObject3(Objects + 2);
489 MakeObject4(Objects + 3);
490 NumObjects = 4;
491 }
492
493
494 int main( int argc, char *argv[] )
495 {
496 glutInit( &argc, argv );
497 glutInitWindowPosition( 0, 0 );
498 glutInitWindowSize( 600, 300 );
499 glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE );
500 Win = glutCreateWindow(argv[0]);
501 glewInit();
502 glutReshapeFunc( Reshape );
503 glutKeyboardFunc( Key );
504 glutSpecialFunc( SpecialKey );
505 glutDisplayFunc( Display );
506 if (Anim)
507 glutIdleFunc(Idle);
508 Init();
509 glutMainLoop();
510 return 0;
511 }