summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJerome Glisse <jglisse@redhat.com>2012-10-24 18:59:36 -0400
committerJerome Glisse <jglisse@redhat.com>2012-10-24 14:47:59 -0400
commit30d8ae33220575af708dde9c411e297922f87a09 (patch)
tree381ac6aacb34da7ffa854d3d92e1685b647f9701
parentfb4cc9ec04c171b74d482bee54f52909d92a1a55 (diff)
add msaa test case
Signed-off-by: Jerome Glisse <jglisse@redhat.com>
-rw-r--r--Makefile2
-rw-r--r--glgears-box-msaa.c541
2 files changed, 542 insertions, 1 deletions
diff --git a/Makefile b/Makefile
index fa4587b..a146fd8 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@ CC = gcc
CFLAGS = -I . -g -O0 -Wall -std=c99 -lGL -lGLU -lm -D_BSD_SOURCE
TARGETS = amd-gpu-name glgears glgears-box glgears-box-cstrealloc \
- gltransformfeedback glclear-depth
+ gltransformfeedback glclear-depth glgears-box-msaa
all: $(TARGETS)
diff --git a/glgears-box-msaa.c b/glgears-box-msaa.c
new file mode 100644
index 0000000..ce18baa
--- /dev/null
+++ b/glgears-box-msaa.c
@@ -0,0 +1,541 @@
+/*
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+/*
+ * This is a port of the infamous "glxgears" demo to straight EGL
+ * Port by Dane Rushton 10 July 2005
+ *
+ * No command line options.
+ * Program runs for 5 seconds then exits, outputing framerate to console
+ */
+#define MAXFRAME 5
+#define PFINISH 1
+#define NSAMPLE 4
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#define GL_GLEXT_PROTOTYPES
+#include <GL/glew.h>
+#include <GL/glut.h>
+
+static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
+static GLint gear1, gear2, gear3;
+static GLfloat angle = 0.0;
+static GLfloat cube_rot = 0.0;
+static GLuint msaa_fbo, gears_fbo, gears_tex;
+static GLuint win_width = 1024;
+static GLuint win_height = 512;
+static GLuint frames = 0;
+static GLuint renderbuffers[8];
+static GLuint nrenderbuffers = 0;
+
+void generate_simple_fbo(unsigned width, unsigned height)
+{
+ GLuint fb;
+ GLenum status;
+ unsigned color, stencil, depth, packed;
+
+ color = stencil = depth = packed = 1;
+
+ /* texture */
+ glGenTextures(1, &gears_tex);
+ glBindTexture(GL_TEXTURE_2D, gears_tex);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ glGenFramebuffers(1, &fb);
+ glBindFramebuffer(GL_FRAMEBUFFER, fb);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gears_tex, 0);
+ status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ fprintf(stderr,
+ "Framebuffer %s color, %s stencil (%s) was not "
+ "complete: 0x%04x\n",
+ color ? "with" : "without",
+ stencil ? "with" : "without",
+ packed ? "packed" : "separate",
+ status);
+ exit(1);
+ }
+ status = glGetError();
+ if (status != GL_NO_ERROR) {
+ fprintf(stderr, "%d Unexpected GL error: 0x%x\n", __LINE__, status);
+ exit(1);
+ }
+ gears_fbo = fb;
+ glClearColor(0.2, 0.4, 0.6, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glGenFramebuffers(1, &fb);
+ glBindFramebuffer(GL_FRAMEBUFFER, fb);
+ if (color) {
+ glGenRenderbuffers(1, &renderbuffers[nrenderbuffers]);
+ glBindRenderbuffer(GL_RENDERBUFFER, renderbuffers[nrenderbuffers]);
+ glRenderbufferStorageMultisample(GL_RENDERBUFFER, NSAMPLE, GL_RGBA, width, height);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffers[nrenderbuffers]);
+ nrenderbuffers++;
+ }
+
+ if (stencil) {
+ const GLenum format = (packed)
+ ? GL_DEPTH24_STENCIL8
+ : GL_STENCIL_INDEX8;
+ const GLenum attachment = (packed)
+ ? GL_DEPTH_STENCIL_ATTACHMENT
+ : GL_STENCIL_ATTACHMENT;
+
+ glGenRenderbuffers(1, &renderbuffers[nrenderbuffers]);
+ glBindRenderbuffer(GL_RENDERBUFFER, renderbuffers[nrenderbuffers]);
+ glRenderbufferStorageMultisample(GL_RENDERBUFFER, NSAMPLE, format, width, height);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, renderbuffers[nrenderbuffers]);
+ nrenderbuffers++;
+ }
+ status = glGetError();
+ if (status != GL_NO_ERROR) {
+ fprintf(stderr, "%d Unexpected GL error: 0x%x %s\n", __LINE__, status, gluErrorString(status));
+ exit(1);
+ }
+
+ if (!packed && depth) {
+ glGenRenderbuffers(1, &renderbuffers[nrenderbuffers]);
+ glBindRenderbuffer(GL_RENDERBUFFER, renderbuffers[nrenderbuffers]);
+ glRenderbufferStorageMultisample(GL_RENDERBUFFER, NSAMPLE, GL_DEPTH_COMPONENT24, width, height);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffers[nrenderbuffers]);
+ nrenderbuffers++;
+ }
+
+ status = glGetError();
+ if (status != GL_NO_ERROR) {
+ fprintf(stderr, "%d Unexpected GL error: 0x%x %s\n", __LINE__, status, gluErrorString(status));
+ exit(1);
+ }
+
+ /* All of the possible combinations that we can generate are required
+ * to be supported by all OpenGL 3.0 implementations, with one
+ * exception. As far as I can tell, implementations are not required
+ * to support separate depth and stencil. That one option is handled
+ * specially.
+ */
+ status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE
+ && !(status == GL_FRAMEBUFFER_UNSUPPORTED && stencil && !packed)) {
+ fprintf(stderr,
+ "Framebuffer %s color, %s stencil (%s) was not "
+ "complete: 0x%04x\n",
+ color ? "with" : "without",
+ stencil ? "with" : "without",
+ packed ? "packed" : "separate",
+ status);
+ exit(1);
+ }
+
+ if (status == GL_FRAMEBUFFER_UNSUPPORTED) {
+ glDeleteRenderbuffers(nrenderbuffers, renderbuffers);
+ glDeleteFramebuffers(1, &fb);
+ fprintf(stderr, "Unsupported framebuffer\n");
+ exit(1);
+ }
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ msaa_fbo = fb;
+}
+
+/*
+ * Draw a gear wheel. You'll probably want to call this function when
+ * building a display list since we do a lot of trig here.
+ *
+ * Input: inner_radius - radius of hole at center
+ * outer_radius - radius at center of teeth
+ * width - width of gear
+ * teeth - number of teeth
+ * tooth_depth - depth of tooth
+ */
+static void gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
+ GLint teeth, GLfloat tooth_depth)
+{
+ GLint i;
+ GLfloat r0, r1, r2;
+ GLfloat angle, da;
+ GLfloat u, v, len;
+
+ r0 = inner_radius;
+ r1 = outer_radius - tooth_depth / 2.0;
+ r2 = outer_radius + tooth_depth / 2.0;
+
+ da = 2.0 * M_PI / teeth / 4.0;
+
+ glShadeModel(GL_FLAT);
+
+ glNormal3f(0.0, 0.0, 1.0);
+
+ /* draw front face */
+ glBegin(GL_QUAD_STRIP);
+ for (i = 0; i <= teeth; i++) {
+ angle = i * 2.0 * M_PI / teeth;
+ glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
+ glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
+ if (i < teeth) {
+ glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
+ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+ width * 0.5);
+ }
+ }
+ glEnd();
+
+ /* draw front sides of teeth */
+ glBegin(GL_QUADS);
+ da = 2.0 * M_PI / teeth / 4.0;
+ for (i = 0; i < teeth; i++) {
+ angle = i * 2.0 * M_PI / teeth;
+
+ glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
+ glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
+ glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
+ width * 0.5);
+ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+ width * 0.5);
+ }
+ glEnd();
+
+ glNormal3f(0.0, 0.0, -1.0);
+
+ /* draw back face */
+ glBegin(GL_QUAD_STRIP);
+ for (i = 0; i <= teeth; i++) {
+ angle = i * 2.0 * M_PI / teeth;
+ glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
+ glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
+ if (i < teeth) {
+ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+ -width * 0.5);
+ glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
+ }
+ }
+ glEnd();
+
+ /* draw back sides of teeth */
+ glBegin(GL_QUADS);
+ da = 2.0 * M_PI / teeth / 4.0;
+ for (i = 0; i < teeth; i++) {
+ angle = i * 2.0 * M_PI / teeth;
+
+ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+ -width * 0.5);
+ glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
+ -width * 0.5);
+ glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
+ glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
+ }
+ glEnd();
+
+ /* draw outward faces of teeth */
+ glBegin(GL_QUAD_STRIP);
+ for (i = 0; i < teeth; i++) {
+ angle = i * 2.0 * M_PI / teeth;
+
+ glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
+ glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
+ u = r2 * cos(angle + da) - r1 * cos(angle);
+ v = r2 * sin(angle + da) - r1 * sin(angle);
+ len = sqrt(u * u + v * v);
+ u /= len;
+ v /= len;
+ glNormal3f(v, -u, 0.0);
+ glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
+ glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
+ glNormal3f(cos(angle), sin(angle), 0.0);
+ glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
+ width * 0.5);
+ glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
+ -width * 0.5);
+ u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);
+ v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);
+ glNormal3f(v, -u, 0.0);
+ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+ width * 0.5);
+ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+ -width * 0.5);
+ glNormal3f(cos(angle), sin(angle), 0.0);
+ }
+
+ glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5);
+ glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5);
+
+ glEnd();
+
+ glShadeModel(GL_SMOOTH);
+
+ /* draw inside radius cylinder */
+ glBegin(GL_QUAD_STRIP);
+ for (i = 0; i <= teeth; i++) {
+ angle = i * 2.0 * M_PI / teeth;
+ glNormal3f(-cos(angle), -sin(angle), 0.0);
+ glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
+ glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
+ }
+ glEnd();
+}
+
+static void draw_gear(void)
+{
+ glBindFramebuffer(GL_FRAMEBUFFER, msaa_fbo);
+#if PFINISH
+ fprintf(stderr, "EE CLEAR FBO -------------------------------------------------\n");
+#endif
+ glClearColor(0.5, 0.5, 0.8, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+#if PFINISH
+ glFinish();
+ fprintf(stderr, "EE CLEAR FBO _________________________________________________\n");
+#endif
+
+#if PFINISH
+ fprintf(stderr, "EE DRAW FBO --------------------------------------------------\n");
+#endif
+ glPushMatrix();
+ glRotatef(view_rotx, 1.0, 0.0, 0.0);
+ glRotatef(view_roty, 0.0, 1.0, 0.0);
+ glRotatef(view_rotz, 0.0, 0.0, 1.0);
+
+ glPushMatrix();
+ glTranslatef(-3.0, -2.0, 0.0);
+ glRotatef(angle, 0.0, 0.0, 1.0);
+ glCallList(gear1);
+ glPopMatrix();
+
+ glPushMatrix();
+ glTranslatef(3.1, -2.0, 0.0);
+ glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0);
+ glCallList(gear2);
+ glPopMatrix();
+
+ glPushMatrix();
+ glTranslatef(-3.1, 4.2, 0.0);
+ glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0);
+ glCallList(gear3);
+ glPopMatrix();
+
+ glPopMatrix();
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+#if PFINISH
+ glFinish();
+ fprintf(stderr, "EE DRAW FBO __________________________________________________\n");
+#endif
+}
+
+static void draw_cube(void)
+{
+ static const GLfloat texcoords[4][2] = {
+ { 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1 }
+ };
+ static const GLfloat vertices[4][2] = {
+ { -1, -1 }, { 1, -1 }, { 1, 1 }, { -1, 1 }
+ };
+ static const GLfloat xforms[6][4] = {
+ { 0, 0, 1, 0 },
+ { 90, 0, 1, 0 },
+ { 180, 0, 1, 0 },
+ { 270, 0, 1, 0 },
+ { 90, 1, 0, 0 },
+ { -90, 1, 0, 0 }
+ };
+ static const GLfloat mat[4] = { 1.0, 1.0, 0.5, 1.0 };
+ float ar;
+ GLint i, j;
+
+#if PFINISH
+ fprintf(stderr, "EE CLEAR -----------------------------------------------------\n");
+#endif
+ glClearColor(0.8, 0.5, 0.5, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+#if PFINISH
+ glFinish();
+ fprintf(stderr, "EE CLEAR _____________________________________________________\n");
+#endif
+
+#if PFINISH
+ fprintf(stderr, "EE DRAW ------------------------------------------------------\n");
+#endif
+ ar = (float)win_width / win_height;
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glFrustum(-ar, ar, -1.0, 1.0, 5.0, 60.0);
+ glMatrixMode(GL_MODELVIEW);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat);
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, gears_tex);
+
+ glPushMatrix();
+ glRotatef(view_rotx, 1.0, 0.0, 0.0);
+ glRotatef(15, 1, 0, 0);
+ glRotatef(cube_rot, 0, 1, 0);
+ glScalef(4, 4, 4);
+
+ for (i = 0; i < 6; i++) {
+ glPushMatrix();
+ glRotatef(xforms[i][0], xforms[i][1], xforms[i][2], xforms[i][3]);
+ glTranslatef(0, 0, 1.1);
+ glBegin(GL_POLYGON);
+ glNormal3f(0, 0, 1);
+ for (j = 0; j < 4; j++) {
+ glTexCoord2fv(texcoords[j]);
+ glVertex2fv(vertices[j]);
+ }
+ glEnd();
+ glPopMatrix();
+ }
+ glPopMatrix();
+
+ glDisable(GL_TEXTURE_2D);
+#if PFINISH
+ glFinish();
+ fprintf(stderr, "EE DRAW ______________________________________________________\n");
+#endif
+}
+
+static void draw(void)
+{
+ glEnable(GL_MULTISAMPLE);
+ draw_gear();
+ glDisable(GL_MULTISAMPLE);
+
+ /* resolve */
+#if PFINISH
+ fprintf(stderr, "EE RESOLVE ---------------------------------------------------\n");
+#endif
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, msaa_fbo);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, gears_fbo);
+ glBlitFramebuffer(0, 0, 512, 512,
+ 0, 0, 512, 512,
+ GL_COLOR_BUFFER_BIT, GL_LINEAR);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+#if PFINISH
+ glFinish();
+ fprintf(stderr, "EE RESOLVE ___________________________________________________\n");
+#endif
+
+ draw_cube();
+ glutSwapBuffers();
+ frames++;
+ if (frames >= MAXFRAME) {
+ glFinish();
+ exit(0);
+ }
+}
+
+static void idle(void)
+{
+ static double t0 = -1.;
+ double dt, t;
+
+ t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
+ if (t0 < 0.0)
+ t0 = t;
+ dt = t - t0;
+ t0 = t;
+
+ angle += 70.0 * dt; /* 70 degrees per second */
+ angle = fmod(angle, 360.0); /* prevents eventual overflow */
+ cube_rot = fmod(cube_rot + 15.0 * dt, 360.0); /* 15 deg/sec */
+
+ glutPostRedisplay();
+}
+
+/* new window size or exposure */
+static void reshape(int width, int height)
+{
+ GLfloat h = (GLfloat) height / (GLfloat) width;
+
+ glViewport(0, 0, (GLint) width, (GLint) height);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glTranslatef(0.0, 0.0, -40.0);
+
+ win_width = width;
+ win_height = height;
+}
+
+static void init(void)
+{
+ static GLfloat pos[4] = { 5.0, 5.0, 10.0, 0.0 };
+ static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 };
+ static GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 };
+ static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 };
+
+ glLightfv(GL_LIGHT0, GL_POSITION, pos);
+ glEnable(GL_CULL_FACE);
+ glEnable(GL_LIGHTING);
+ glEnable(GL_LIGHT0);
+ glEnable(GL_DEPTH_TEST);
+
+ /* make the gears */
+ gear1 = glGenLists(1);
+ glNewList(gear1, GL_COMPILE);
+ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
+ gear(1.0, 4.0, 1.0, 20, 0.7);
+ glEndList();
+
+ gear2 = glGenLists(1);
+ glNewList(gear2, GL_COMPILE);
+ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
+ gear(0.5, 2.0, 2.0, 10, 0.7);
+ glEndList();
+
+ gear3 = glGenLists(1);
+ glNewList(gear3, GL_COMPILE);
+ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
+ gear(1.3, 2.0, 0.5, 10, 0.7);
+ glEndList();
+
+ generate_simple_fbo(512, 512);
+
+ glEnable(GL_NORMALIZE);
+}
+
+int main(int argc, char *argv[])
+{
+ glutInit(&argc, argv);
+ glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE | GLUT_STENCIL);
+ glutInitWindowSize(win_width, win_height);
+ glutCreateWindow("glgears");
+
+ GLenum err = glewInit();
+ if (GLEW_OK != err) {
+ fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
+ return -1;
+ }
+
+ glutIdleFunc(idle);
+ glutReshapeFunc(reshape);
+ glutDisplayFunc(draw);
+
+ init();
+ reshape(win_width, win_height);
+ glutMainLoop();
+ return 0;
+}