132001f49Smrg/*
232001f49Smrg * Test GL_ARB_vertex_buffer_object
332001f49Smrg * Also test GL_ARB_vertex_array_object if supported
432001f49Smrg *
532001f49Smrg * Brian Paul
632001f49Smrg * 16 Sep 2003
732001f49Smrg */
832001f49Smrg
932001f49Smrg
1032001f49Smrg#include <assert.h>
1132001f49Smrg#include <stdio.h>
1232001f49Smrg#include <stdlib.h>
1332001f49Smrg#include <string.h>
1432001f49Smrg#include <math.h>
1532001f49Smrg#include <GL/glew.h>
1632001f49Smrg#include "glut_wrap.h"
1732001f49Smrg
1832001f49Smrg#define NUM_OBJECTS 10
1932001f49Smrg
2032001f49Smrgstruct object
2132001f49Smrg{
2232001f49Smrg   GLuint ArrayObjectID; /** GL_ARB_vertex_array_object */
2332001f49Smrg   GLuint VertexBufferID;
2432001f49Smrg   GLuint ColorBufferID;
2532001f49Smrg   GLuint ElementsBufferID;
2632001f49Smrg   GLuint NumVerts;
2732001f49Smrg   GLuint VertexOffset;
2832001f49Smrg   GLuint ColorOffset;
2932001f49Smrg   GLuint VertexStride;
3032001f49Smrg   GLuint ColorStride;
3132001f49Smrg   GLuint NumElements;
3232001f49Smrg   GLuint MaxElement;
3332001f49Smrg};
3432001f49Smrg
3532001f49Smrgstatic struct object Objects[NUM_OBJECTS];
3632001f49Smrgstatic GLuint NumObjects;
3732001f49Smrg
3832001f49Smrgstatic GLuint Win;
3932001f49Smrg
4032001f49Smrgstatic GLfloat Xrot = 0, Yrot = 0, Zrot = 0;
4132001f49Smrgstatic GLboolean Anim = GL_TRUE;
4232001f49Smrgstatic GLboolean Have_ARB_vertex_array_object = GL_FALSE;
4332001f49Smrg
4432001f49Smrg
4532001f49Smrgstatic void CheckError(int line)
4632001f49Smrg{
4732001f49Smrg   GLenum err = glGetError();
4832001f49Smrg   if (err) {
4932001f49Smrg      printf("GL Error 0x%x at line %d\n", (int) err, line);
5032001f49Smrg   }
5132001f49Smrg}
5232001f49Smrg
5332001f49Smrg
5432001f49Smrgstatic void DrawObject( const struct object *obj )
5532001f49Smrg{
5632001f49Smrg   if (Have_ARB_vertex_array_object && obj->ArrayObjectID) {
5732001f49Smrg      glBindVertexArray(obj->ArrayObjectID);
5832001f49Smrg
5932001f49Smrg      if (obj->NumElements > 0) {
6032001f49Smrg         /* indexed arrays */
6132001f49Smrg         glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, obj->ElementsBufferID);
6232001f49Smrg         glDrawRangeElements(GL_LINE_LOOP, 0, obj->MaxElement,
6332001f49Smrg                             obj->NumElements, GL_UNSIGNED_INT, NULL);
6432001f49Smrg      }
6532001f49Smrg      else {
6632001f49Smrg         /* non-indexed arrays */
6732001f49Smrg         glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
6832001f49Smrg         glDrawArrays(GL_LINE_LOOP, 0, obj->NumVerts);
6932001f49Smrg      }
7032001f49Smrg
7132001f49Smrg      glBindVertexArray(0);
7232001f49Smrg   }
7332001f49Smrg   else {
7432001f49Smrg      /* no vertex array objects, must set vertex/color pointers per draw */
7532001f49Smrg
7632001f49Smrg      glBindBufferARB(GL_ARRAY_BUFFER_ARB, obj->VertexBufferID);
7732001f49Smrg      glVertexPointer(3, GL_FLOAT, obj->VertexStride, (const void *) (size_t) obj->VertexOffset);
7832001f49Smrg      glEnableClientState(GL_VERTEX_ARRAY);
7932001f49Smrg
8032001f49Smrg      /* test push/pop attrib */
8132001f49Smrg      /* XXX this leads to a segfault with NVIDIA's 53.36 driver */
8232001f49Smrg#if 0
8332001f49Smrg      if (1)
8432001f49Smrg      {
8532001f49Smrg         glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
8632001f49Smrg         /*glVertexPointer(3, GL_FLOAT, 0, (const void *) (size_t) (obj->VertexOffset + 10000));*/
8732001f49Smrg         glBindBufferARB(GL_ARRAY_BUFFER_ARB, 999999);
8832001f49Smrg         glPopClientAttrib();
8932001f49Smrg      }
9032001f49Smrg#endif
9132001f49Smrg      glBindBufferARB(GL_ARRAY_BUFFER_ARB, obj->ColorBufferID);
9232001f49Smrg      glColorPointer(3, GL_FLOAT, obj->ColorStride, (const void *) (size_t) obj->ColorOffset);
9332001f49Smrg      glEnableClientState(GL_COLOR_ARRAY);
9432001f49Smrg
9532001f49Smrg      if (obj->NumElements > 0) {
9632001f49Smrg         /* indexed arrays */
9732001f49Smrg         glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, obj->ElementsBufferID);
9832001f49Smrg         glDrawElements(GL_LINE_LOOP, obj->NumElements, GL_UNSIGNED_INT, NULL);
9932001f49Smrg      }
10032001f49Smrg      else {
10132001f49Smrg         /* non-indexed arrays */
10232001f49Smrg         glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
10332001f49Smrg         glDrawArrays(GL_LINE_LOOP, 0, obj->NumVerts);
10432001f49Smrg      }
10532001f49Smrg   }
10632001f49Smrg}
10732001f49Smrg
10832001f49Smrg
10932001f49Smrgstatic void Idle( void )
11032001f49Smrg{
11132001f49Smrg   Zrot = 0.05 * glutGet(GLUT_ELAPSED_TIME);
11232001f49Smrg   glutPostRedisplay();
11332001f49Smrg}
11432001f49Smrg
11532001f49Smrg
11632001f49Smrgstatic void Display( void )
11732001f49Smrg{
11832001f49Smrg   int i;
11932001f49Smrg
12032001f49Smrg   glClear( GL_COLOR_BUFFER_BIT );
12132001f49Smrg
12232001f49Smrg   for (i = 0; i < NumObjects; i++) {
12332001f49Smrg      float x = 7.0 * ((float) i / (NumObjects-1) - 0.5);
12432001f49Smrg      glPushMatrix();
12532001f49Smrg      glTranslatef(x, 0, 0);
12632001f49Smrg      glRotatef(Xrot, 1, 0, 0);
12732001f49Smrg      glRotatef(Yrot, 0, 1, 0);
12832001f49Smrg      glRotatef(Zrot, 0, 0, 1);
12932001f49Smrg
13032001f49Smrg      DrawObject(Objects + i);
13132001f49Smrg
13232001f49Smrg      glPopMatrix();
13332001f49Smrg   }
13432001f49Smrg
13532001f49Smrg   CheckError(__LINE__);
13632001f49Smrg   glutSwapBuffers();
13732001f49Smrg}
13832001f49Smrg
13932001f49Smrg
14032001f49Smrgstatic void Reshape( int width, int height )
14132001f49Smrg{
14232001f49Smrg   float ar = (float) width / (float) height;
14332001f49Smrg   glViewport( 0, 0, width, height );
14432001f49Smrg   glMatrixMode( GL_PROJECTION );
14532001f49Smrg   glLoadIdentity();
14632001f49Smrg   glFrustum( -ar, ar, -1.0, 1.0, 5.0, 25.0 );
14732001f49Smrg   glMatrixMode( GL_MODELVIEW );
14832001f49Smrg   glLoadIdentity();
14932001f49Smrg   glTranslatef( 0.0, 0.0, -15.0 );
15032001f49Smrg}
15132001f49Smrg
15232001f49Smrg
15332001f49Smrgstatic void FreeBuffers(void)
15432001f49Smrg{
15532001f49Smrg   int i;
15632001f49Smrg   for (i = 0; i < NUM_OBJECTS; i++) {
15732001f49Smrg      glDeleteBuffersARB(1, &Objects[i].VertexBufferID);
15832001f49Smrg      glDeleteBuffersARB(1, &Objects[i].ColorBufferID);
15932001f49Smrg      glDeleteBuffersARB(1, &Objects[i].ElementsBufferID);
16032001f49Smrg   }
16132001f49Smrg}
16232001f49Smrg
16332001f49Smrg
16432001f49Smrgstatic void Key( unsigned char key, int x, int y )
16532001f49Smrg{
16632001f49Smrg   const GLfloat step = 3.0;
16732001f49Smrg   (void) x;
16832001f49Smrg   (void) y;
16932001f49Smrg   switch (key) {
17032001f49Smrg      case 'a':
17132001f49Smrg         Anim = !Anim;
17232001f49Smrg         if (Anim)
17332001f49Smrg            glutIdleFunc(Idle);
17432001f49Smrg         else
17532001f49Smrg            glutIdleFunc(NULL);
17632001f49Smrg         break;
17732001f49Smrg      case 'z':
17832001f49Smrg         Zrot -= step;
17932001f49Smrg         break;
18032001f49Smrg      case 'Z':
18132001f49Smrg         Zrot += step;
18232001f49Smrg         break;
18332001f49Smrg      case 27:
18432001f49Smrg         FreeBuffers();
18532001f49Smrg         glutDestroyWindow(Win);
18632001f49Smrg         exit(0);
18732001f49Smrg         break;
18832001f49Smrg   }
18932001f49Smrg   glutPostRedisplay();
19032001f49Smrg}
19132001f49Smrg
19232001f49Smrg
19332001f49Smrgstatic void SpecialKey( int key, int x, int y )
19432001f49Smrg{
19532001f49Smrg   const GLfloat step = 3.0;
19632001f49Smrg   (void) x;
19732001f49Smrg   (void) y;
19832001f49Smrg   switch (key) {
19932001f49Smrg      case GLUT_KEY_UP:
20032001f49Smrg         Xrot -= step;
20132001f49Smrg         break;
20232001f49Smrg      case GLUT_KEY_DOWN:
20332001f49Smrg         Xrot += step;
20432001f49Smrg         break;
20532001f49Smrg      case GLUT_KEY_LEFT:
20632001f49Smrg         Yrot -= step;
20732001f49Smrg         break;
20832001f49Smrg      case GLUT_KEY_RIGHT:
20932001f49Smrg         Yrot += step;
21032001f49Smrg         break;
21132001f49Smrg   }
21232001f49Smrg   glutPostRedisplay();
21332001f49Smrg}
21432001f49Smrg
21532001f49Smrg
21632001f49Smrg/**
21732001f49Smrg * If GL_ARB_vertex_array_object is supported, create an array object
21832001f49Smrg * and set all the per-array state.
21932001f49Smrg */
22032001f49Smrgstatic void
22132001f49SmrgCreateVertexArrayObject(struct object *obj)
22232001f49Smrg{
22332001f49Smrg   glGenVertexArrays(1, &obj->ArrayObjectID);
22432001f49Smrg   glBindVertexArray(obj->ArrayObjectID);
22532001f49Smrg
22632001f49Smrg   glBindBufferARB(GL_ARRAY_BUFFER_ARB, obj->VertexBufferID);
22732001f49Smrg   glVertexPointer(3, GL_FLOAT, obj->VertexStride, (const void *) (size_t) obj->VertexOffset);
22832001f49Smrg   glEnableClientState(GL_VERTEX_ARRAY);
22932001f49Smrg
23032001f49Smrg   glBindBufferARB(GL_ARRAY_BUFFER_ARB, obj->ColorBufferID);
23132001f49Smrg   glColorPointer(3, GL_FLOAT, obj->ColorStride, (const void *) (size_t) obj->ColorOffset);
23232001f49Smrg   glEnableClientState(GL_COLOR_ARRAY);
23332001f49Smrg
23432001f49Smrg   glBindVertexArray(0);
23532001f49Smrg}
23632001f49Smrg
23732001f49Smrg
23832001f49Smrg/*
23932001f49Smrg * Non-interleaved position/color data.
24032001f49Smrg */
24132001f49Smrgstatic void MakeObject1(struct object *obj)
24232001f49Smrg{
24332001f49Smrg   GLfloat *v, *c;
24432001f49Smrg   void *p;
24532001f49Smrg   int i;
24632001f49Smrg   GLubyte buffer[500];
24732001f49Smrg
24832001f49Smrg   for (i = 0; i < 500; i++)
24932001f49Smrg      buffer[i] = i & 0xff;
25032001f49Smrg
25132001f49Smrg   obj->VertexBufferID = 0;
25232001f49Smrg   glGenBuffersARB(1, &obj->VertexBufferID);
25332001f49Smrg   obj->ColorBufferID = obj->VertexBufferID;
25432001f49Smrg   assert(obj->VertexBufferID != 0);
25532001f49Smrg   glBindBufferARB(GL_ARRAY_BUFFER_ARB, obj->VertexBufferID);
25632001f49Smrg   glBufferDataARB(GL_ARRAY_BUFFER_ARB, 500, buffer, GL_STATIC_DRAW_ARB);
25732001f49Smrg
25832001f49Smrg   for (i = 0; i < 500; i++)
25932001f49Smrg      buffer[i] = 0;
26032001f49Smrg
26132001f49Smrg   glGetBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, 500, buffer);
26232001f49Smrg
26332001f49Smrg   for (i = 0; i < 500; i++)
26432001f49Smrg      assert(buffer[i] == (i & 0xff));
26532001f49Smrg
26632001f49Smrg   glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_MAPPED_ARB, &i);
26732001f49Smrg   assert(!i);
26832001f49Smrg
26932001f49Smrg   glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_USAGE_ARB, &i);
27032001f49Smrg
27132001f49Smrg   v = (GLfloat *) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
27232001f49Smrg
27332001f49Smrg   /* do some sanity tests */
27432001f49Smrg   glGetBufferPointervARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_MAP_POINTER_ARB, &p);
27532001f49Smrg   assert(p == v);
27632001f49Smrg
27732001f49Smrg   glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &i);
27832001f49Smrg   assert(i == 500);
27932001f49Smrg
28032001f49Smrg   glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_USAGE_ARB, &i);
28132001f49Smrg   assert(i == GL_STATIC_DRAW_ARB);
28232001f49Smrg
28332001f49Smrg   glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_ACCESS_ARB, &i);
28432001f49Smrg   assert(i == GL_WRITE_ONLY_ARB);
28532001f49Smrg
28632001f49Smrg   glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_MAPPED_ARB, &i);
28732001f49Smrg   assert(i);
28832001f49Smrg
28932001f49Smrg   /* Make rectangle */
29032001f49Smrg   v[0] = -1;  v[1] = -1;  v[2] = 0;
29132001f49Smrg   v[3] =  1;  v[4] = -1;  v[5] = 0;
29232001f49Smrg   v[6] =  1;  v[7] =  1;  v[8] = 0;
29332001f49Smrg   v[9] = -1;  v[10] = 1;  v[11] = 0;
29432001f49Smrg   c = v + 12;
29532001f49Smrg   c[0] = 1;  c[1] = 0;  c[2] = 0;
29632001f49Smrg   c[3] = 1;  c[4] = 0;  c[5] = 0;
29732001f49Smrg   c[6] = 1;  c[7] = 0;  c[8] = 1;
29832001f49Smrg   c[9] = 1;  c[10] = 0;  c[11] = 1;
29932001f49Smrg   obj->NumVerts = 4;
30032001f49Smrg   obj->VertexOffset = 0;
30132001f49Smrg   obj->ColorOffset = 3 * sizeof(GLfloat) * obj->NumVerts;
30232001f49Smrg   obj->VertexStride = 0;
30332001f49Smrg   obj->ColorStride = 0;
30432001f49Smrg   obj->NumElements = 0;
30532001f49Smrg   obj->MaxElement = 0;
30632001f49Smrg
30732001f49Smrg   glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
30832001f49Smrg
30932001f49Smrg   glGetBufferPointervARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_MAP_POINTER_ARB, &p);
31032001f49Smrg   assert(!p);
31132001f49Smrg
31232001f49Smrg   glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_MAPPED_ARB, &i);
31332001f49Smrg   assert(!i);
31432001f49Smrg
31532001f49Smrg   if (Have_ARB_vertex_array_object) {
31632001f49Smrg      CreateVertexArrayObject(obj);
31732001f49Smrg   }
31832001f49Smrg}
31932001f49Smrg
32032001f49Smrg
32132001f49Smrg/*
32232001f49Smrg * Interleaved position/color data.
32332001f49Smrg */
32432001f49Smrgstatic void MakeObject2(struct object *obj)
32532001f49Smrg{
32632001f49Smrg   GLfloat *v;
32732001f49Smrg   int start = 40; /* bytes, to test non-zero array offsets */
32832001f49Smrg
32932001f49Smrg   glGenBuffersARB(1, &obj->VertexBufferID);
33032001f49Smrg   obj->ColorBufferID = obj->VertexBufferID;
33132001f49Smrg
33232001f49Smrg   glBindBufferARB(GL_ARRAY_BUFFER_ARB, obj->VertexBufferID);
33332001f49Smrg   glBufferDataARB(GL_ARRAY_BUFFER_ARB, 1000, NULL, GL_STATIC_DRAW_ARB);
33432001f49Smrg   v = (GLfloat *) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
33532001f49Smrg
33632001f49Smrg   v += start / sizeof(GLfloat);
33732001f49Smrg
33832001f49Smrg   /* Make triangle: interleaved colors, then positions */
33932001f49Smrg   /*   R            G          B           X           Y            Z  */
34032001f49Smrg   v[0] = 0;   v[1] = 1;   v[2] = 0;   v[3] = -1;  v[4] = -1;   v[5] = 0;
34132001f49Smrg   v[6] = 0;   v[7] = 1;   v[8] = 0;   v[9] = 1;   v[10] = -1;  v[11] = 0;
34232001f49Smrg   v[12] = 1;  v[13] = 1;  v[14] = 0;  v[15] = 0;  v[16] =  1;  v[17] = 0;
34332001f49Smrg
34432001f49Smrg   obj->NumVerts = 3;
34532001f49Smrg   obj->VertexOffset = start + 3 * sizeof(GLfloat);
34632001f49Smrg   obj->ColorOffset = start;
34732001f49Smrg   obj->VertexStride = 6 * sizeof(GLfloat);
34832001f49Smrg   obj->ColorStride = 6 * sizeof(GLfloat);
34932001f49Smrg
35032001f49Smrg   obj->NumElements = 0;
35132001f49Smrg   obj->MaxElement = 0;
35232001f49Smrg
35332001f49Smrg   glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
35432001f49Smrg
35532001f49Smrg   if (Have_ARB_vertex_array_object) {
35632001f49Smrg      CreateVertexArrayObject(obj);
35732001f49Smrg   }
35832001f49Smrg}
35932001f49Smrg
36032001f49Smrg
36132001f49Smrg/*
36232001f49Smrg * Use an index buffer and glDrawElements().
36332001f49Smrg */
36432001f49Smrgstatic void MakeObject3(struct object *obj)
36532001f49Smrg{
36632001f49Smrg   GLfloat vertexData[1000];
36732001f49Smrg   GLfloat *v, *c;
36832001f49Smrg   GLuint *i;
36932001f49Smrg   int bytes;
37032001f49Smrg
37132001f49Smrg   /* Make rectangle */
37232001f49Smrg   v = vertexData;
37332001f49Smrg   v[0] = -1;  v[1] = -0.5;  v[2] = 0;
37432001f49Smrg   v[3] =  1;  v[4] = -0.5;  v[5] = 0;
37532001f49Smrg   v[6] =  1;  v[7] =  0.5;  v[8] = 0;
37632001f49Smrg   v[9] = -1;  v[10] = 0.5;  v[11] = 0;
37732001f49Smrg   c = vertexData + 12;
37832001f49Smrg   c[0] = 0;  c[1] = 0;  c[2] = 1;
37932001f49Smrg   c[3] = 0;  c[4] = 0;  c[5] = 1;
38032001f49Smrg   c[6] = 0;  c[7] = 1;  c[8] = 1;
38132001f49Smrg   c[9] = 0;  c[10] = 1;  c[11] = 1;
38232001f49Smrg   obj->NumVerts = 4;
38332001f49Smrg   obj->VertexOffset = 0;
38432001f49Smrg   obj->ColorOffset = 3 * sizeof(GLfloat) * obj->NumVerts;
38532001f49Smrg   obj->VertexStride = 0;
38632001f49Smrg   obj->ColorStride = 0;
38732001f49Smrg
38832001f49Smrg   bytes = obj->NumVerts * (3 + 3) * sizeof(GLfloat);
38932001f49Smrg
39032001f49Smrg   /* Don't use glMap/UnmapBuffer for this object */
39132001f49Smrg   glGenBuffersARB(1, &obj->VertexBufferID);
39232001f49Smrg   obj->ColorBufferID = obj->VertexBufferID;
39332001f49Smrg
39432001f49Smrg   glBindBufferARB(GL_ARRAY_BUFFER_ARB, obj->VertexBufferID);
39532001f49Smrg   glBufferDataARB(GL_ARRAY_BUFFER_ARB, bytes, vertexData, GL_STATIC_DRAW_ARB);
39632001f49Smrg
39732001f49Smrg   /* Setup a buffer of indices to test the ELEMENTS path */
39832001f49Smrg   glGenBuffersARB(1, &obj->ElementsBufferID);
39932001f49Smrg   glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, obj->ElementsBufferID);
40032001f49Smrg   glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 100, NULL, GL_STATIC_DRAW_ARB);
40132001f49Smrg   i = (GLuint *) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_READ_WRITE_ARB);
40232001f49Smrg   i[0] = 0;
40332001f49Smrg   i[1] = 1;
40432001f49Smrg   i[2] = 2;
40532001f49Smrg   i[3] = 3;
40632001f49Smrg   glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
40732001f49Smrg   obj->NumElements = 4;
40832001f49Smrg   obj->MaxElement = 3;
40932001f49Smrg
41032001f49Smrg   if (Have_ARB_vertex_array_object) {
41132001f49Smrg      CreateVertexArrayObject(obj);
41232001f49Smrg   }
41332001f49Smrg}
41432001f49Smrg
41532001f49Smrg
41632001f49Smrg/*
41732001f49Smrg * Vertex and color data in different buffers.
41832001f49Smrg */
41932001f49Smrgstatic void MakeObject4(struct object *obj)
42032001f49Smrg{
42132001f49Smrg   static const GLfloat vertexData[] = {
42232001f49Smrg      0,   -1,  0,
42332001f49Smrg      0.5,  0,  0,
42432001f49Smrg      0,    1,  0,
42532001f49Smrg      -0.5, 0,  0
42632001f49Smrg   };
42732001f49Smrg   static const GLfloat colorData[] = {
42832001f49Smrg      1,    1,   1,
42932001f49Smrg      1,    1,   0,
43032001f49Smrg      .5,  .5,   0,
43132001f49Smrg      1,    1,   0
43232001f49Smrg   };
43332001f49Smrg
43432001f49Smrg   obj->VertexOffset = 0;
43532001f49Smrg   obj->VertexStride = 0;
43632001f49Smrg   obj->ColorOffset = 0;
43732001f49Smrg   obj->ColorStride = 0;
43832001f49Smrg   obj->NumVerts = 4;
43932001f49Smrg
44032001f49Smrg   glGenBuffersARB(1, &obj->VertexBufferID);
44132001f49Smrg   glBindBufferARB(GL_ARRAY_BUFFER_ARB, obj->VertexBufferID);
44232001f49Smrg   glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(vertexData), vertexData,
44332001f49Smrg                   GL_STATIC_DRAW_ARB);
44432001f49Smrg
44532001f49Smrg   glGenBuffersARB(1, &obj->ColorBufferID);
44632001f49Smrg   glBindBufferARB(GL_ARRAY_BUFFER_ARB, obj->ColorBufferID);
44732001f49Smrg   glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(colorData), colorData,
44832001f49Smrg                   GL_STATIC_DRAW_ARB);
44932001f49Smrg
45032001f49Smrg   /* Setup a buffer of indices to test the ELEMENTS path */
45132001f49Smrg   obj->ElementsBufferID = 0;
45232001f49Smrg   obj->NumElements = 0;
45332001f49Smrg   obj->MaxElement = 0;
45432001f49Smrg
45532001f49Smrg   if (Have_ARB_vertex_array_object) {
45632001f49Smrg      CreateVertexArrayObject(obj);
45732001f49Smrg   }
45832001f49Smrg}
45932001f49Smrg
46032001f49Smrg
46132001f49Smrg
46232001f49Smrgstatic void Init( void )
46332001f49Smrg{
46432001f49Smrg   if (!glutExtensionSupported("GL_ARB_vertex_buffer_object")) {
46532001f49Smrg      printf("GL_ARB_vertex_buffer_object not found!\n");
46632001f49Smrg      exit(0);
46732001f49Smrg   }
46832001f49Smrg   printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
46932001f49Smrg
47032001f49Smrg   Have_ARB_vertex_array_object =
47132001f49Smrg      glutExtensionSupported("GL_ARB_vertex_array_object");
47232001f49Smrg
47332001f49Smrg   printf("Using GL_ARB_vertex_array_object: %s\n",
47432001f49Smrg          (Have_ARB_vertex_array_object ? "yes" : "no"));
47532001f49Smrg
47632001f49Smrg
47732001f49Smrg   /* Test buffer object deletion */
47832001f49Smrg   if (1) {
47932001f49Smrg      static GLubyte data[1000];
48032001f49Smrg      GLuint id = 999;
48132001f49Smrg      glBindBufferARB(GL_ARRAY_BUFFER_ARB, id);
48232001f49Smrg      glBufferDataARB(GL_ARRAY_BUFFER_ARB, 1000, data, GL_STATIC_DRAW_ARB);
48332001f49Smrg      glVertexPointer(3, GL_FLOAT, 0, (void *) 0);
48432001f49Smrg      glDeleteBuffersARB(1, &id);
48532001f49Smrg      assert(!glIsBufferARB(id));
48632001f49Smrg      glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
48732001f49Smrg      glVertexPointer(3, GL_FLOAT, 0, (void *) 0);
48832001f49Smrg      assert(!glIsBufferARB(id));
48932001f49Smrg   }
49032001f49Smrg
49132001f49Smrg   memset(Objects, 0, sizeof(Objects));
49232001f49Smrg   MakeObject1(Objects + 0);
49332001f49Smrg   MakeObject2(Objects + 1);
49432001f49Smrg   MakeObject3(Objects + 2);
49532001f49Smrg   MakeObject4(Objects + 3);
49632001f49Smrg   NumObjects = 4;
49732001f49Smrg}
49832001f49Smrg
49932001f49Smrg
50032001f49Smrgint main( int argc, char *argv[] )
50132001f49Smrg{
50232001f49Smrg   glutInit( &argc, argv );
50332001f49Smrg   glutInitWindowPosition( 0, 0 );
50432001f49Smrg   glutInitWindowSize( 600, 300 );
50532001f49Smrg   glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE );
50632001f49Smrg   Win = glutCreateWindow(argv[0]);
50732001f49Smrg   glewInit();
50832001f49Smrg   glutReshapeFunc( Reshape );
50932001f49Smrg   glutKeyboardFunc( Key );
51032001f49Smrg   glutSpecialFunc( SpecialKey );
51132001f49Smrg   glutDisplayFunc( Display );
51232001f49Smrg   if (Anim)
51332001f49Smrg      glutIdleFunc(Idle);
51432001f49Smrg   Init();
51532001f49Smrg   glutMainLoop();
51632001f49Smrg   return 0;
51732001f49Smrg}
518