openglsupport.cpp (18637B)
1 // This file is part of Eigen, a lightweight C++ template library 2 // for linear algebra. 3 // 4 // Copyright (C) 2010 Gael Guennebaud <gael.guennebaud@inria.fr> 5 // 6 // This Source Code Form is subject to the terms of the Mozilla 7 // Public License v. 2.0. If a copy of the MPL was not distributed 8 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 10 #include <main.h> 11 #include <iostream> 12 #include <string> 13 14 #if defined(__APPLE_CC__) 15 // Prevent deprecation warnings caused by GLEW on MacOS. 16 #define GL_SILENCE_DEPRECATION 1 17 #endif 18 #include <GL/glew.h> 19 #include <Eigen/OpenGLSupport> 20 #if defined(__APPLE_CC__) 21 #include <GLUT/glut.h> 22 #else 23 #include <GL/freeglut.h> 24 #endif 25 26 using namespace Eigen; 27 28 #define VERIFY_MATRIX(CODE,REF) { \ 29 glMatrixMode(GL_MODELVIEW); \ 30 glLoadIdentity(); \ 31 CODE; \ 32 Matrix<float,4,4,ColMajor> m; m.setZero(); \ 33 glGet(GL_MODELVIEW_MATRIX, m); \ 34 if(!(REF).cast<float>().isApprox(m)) { \ 35 std::cerr << "Expected:\n" << ((REF).cast<float>()) << "\n" << "got\n" << m << "\n\n"; \ 36 } \ 37 VERIFY_IS_APPROX((REF).cast<float>(), m); \ 38 } 39 40 #define VERIFY_UNIFORM(SUFFIX,NAME,TYPE) { \ 41 TYPE value; value.setRandom(); \ 42 TYPE data; \ 43 int loc = glGetUniformLocation(prg_id, #NAME); \ 44 VERIFY((loc!=-1) && "uniform not found"); \ 45 glUniform(loc,value); \ 46 EIGEN_CAT(glGetUniform,SUFFIX)(prg_id,loc,data.data()); \ 47 if(!value.isApprox(data)) { \ 48 std::cerr << "Expected:\n" << value << "\n" << "got\n" << data << "\n\n"; \ 49 } \ 50 VERIFY_IS_APPROX(value, data); \ 51 } 52 53 #define VERIFY_UNIFORMi(NAME,TYPE) { \ 54 TYPE value = TYPE::Random().eval().cast<float>().cast<TYPE::Scalar>(); \ 55 TYPE data; \ 56 int loc = glGetUniformLocation(prg_id, #NAME); \ 57 VERIFY((loc!=-1) && "uniform not found"); \ 58 glUniform(loc,value); \ 59 glGetUniformiv(prg_id,loc,(GLint*)data.data()); \ 60 if(!value.isApprox(data)) { \ 61 std::cerr << "Expected:\n" << value << "\n" << "got\n" << data << "\n\n"; \ 62 } \ 63 VERIFY_IS_APPROX(value, data); \ 64 } 65 66 void printProgramInfoLog(GLuint objectID) 67 { 68 int infologLength, charsWritten; 69 GLchar *infoLog; 70 glGetProgramiv(objectID, GL_INFO_LOG_LENGTH, &infologLength); 71 if(infologLength > 0) 72 { 73 infoLog = new GLchar[infologLength]; 74 glGetProgramInfoLog(objectID, infologLength, &charsWritten, infoLog); 75 if (charsWritten > 0) 76 std::cerr << "Program info : \n" << infoLog << std::endl; 77 delete[] infoLog; 78 } 79 } 80 81 void printShaderInfoLog(GLuint objectID) 82 { 83 int infologLength, charsWritten; 84 GLchar *infoLog; 85 glGetShaderiv(objectID, GL_INFO_LOG_LENGTH, &infologLength); 86 if(infologLength > 0) 87 { 88 infoLog = new GLchar[infologLength]; 89 glGetShaderInfoLog(objectID, infologLength, &charsWritten, infoLog); 90 if (charsWritten > 0) 91 std::cerr << "Shader info : \n" << infoLog << std::endl; 92 delete[] infoLog; 93 } 94 } 95 96 GLint createProgram(const char* vtx, const char* frg, bool print_errors = true) 97 { 98 GLint prg_id = glCreateProgram(); 99 GLint vtx_id = glCreateShader(GL_VERTEX_SHADER); 100 GLint frg_id = glCreateShader(GL_FRAGMENT_SHADER); 101 GLint ok; 102 103 glShaderSource(vtx_id, 1, &vtx, 0); 104 glCompileShader(vtx_id); 105 glGetShaderiv(vtx_id, GL_COMPILE_STATUS, &ok); 106 if(!ok) 107 { 108 if (print_errors) 109 { 110 std::cerr << "vtx compilation failed\n"; 111 std::cerr << "Source:\n" << vtx << "\n"; 112 printShaderInfoLog(vtx_id); 113 } 114 glDeleteShader(vtx_id); 115 return GL_ZERO; 116 } 117 118 glShaderSource(frg_id, 1, &frg, 0); 119 glCompileShader(frg_id); 120 glGetShaderiv(frg_id, GL_COMPILE_STATUS, &ok); 121 if(!ok) 122 { 123 if (print_errors) 124 { 125 std::cerr << "frg compilation failed.\n"; 126 std::cerr << "Source:\n" << frg << "\n"; 127 printShaderInfoLog(frg_id); 128 } 129 glDeleteShader(vtx_id); 130 glDeleteShader(frg_id); 131 return GL_ZERO; 132 } 133 134 glAttachShader(prg_id, vtx_id); 135 glAttachShader(prg_id, frg_id); 136 glLinkProgram(prg_id); 137 138 // Delete shaders once linked. 139 glDeleteShader(vtx_id); 140 glDeleteShader(frg_id); 141 glGetProgramiv(prg_id, GL_LINK_STATUS, &ok); 142 if(!ok) 143 { 144 if (print_errors) 145 { 146 std::cerr << "linking failed.\n"; 147 printProgramInfoLog(prg_id); 148 } 149 glDeleteProgram(prg_id); 150 return GL_ZERO; 151 } 152 153 glUseProgram(prg_id); 154 return prg_id; 155 } 156 157 GLint createProgram(const std::string& vtx, const std::string& frg, bool print_errors = true) 158 { 159 return createProgram(vtx.c_str(), frg.c_str(), print_errors); 160 } 161 162 std::string getGlslVersionString(int gl_major_version, int gl_minor_version) 163 { 164 switch (gl_major_version) 165 { 166 case 2: 167 switch (gl_minor_version) 168 { 169 case 0: 170 return "#version 110"; 171 case 1: 172 return "#version 120"; 173 } 174 break; 175 case 3: 176 switch (gl_minor_version) 177 { 178 case 0: 179 return "#version 130"; 180 case 1: 181 return "#version 140"; 182 case 2: 183 return "#version 150"; 184 case 3: 185 return "#version 330"; 186 } 187 break; 188 case 4: 189 switch (gl_minor_version) 190 { 191 case 0: 192 return "#version 400"; 193 case 1: 194 return "#version 410"; 195 case 2: 196 return "#version 420"; 197 case 3: 198 return "#version 430"; 199 case 4: 200 return "#version 440"; 201 case 5: 202 return "#version 450"; 203 case 6: 204 return "#version 460"; 205 } 206 break; 207 } 208 return ""; 209 } 210 211 void find_and_replace( 212 std::string& str, 213 const std::string& find, 214 const std::string& replace) 215 { 216 size_t loc = 0; 217 size_t flen = find.length(); 218 size_t rlen = replace.length(); 219 while ( (loc = str.find(find, loc)) != std::string::npos) { 220 str.replace(loc, flen, replace); 221 loc += rlen; 222 } 223 } 224 225 // Finds and replaces a set of substrings in a string. 226 std::string format( 227 const std::string& str, 228 const std::vector<std::string>& find, 229 const std::vector<std::string>& replace) 230 { 231 std::string out = str; 232 for (std::size_t i=0; i<find.size(); ++i) { 233 find_and_replace(out, find[i], replace[i]); 234 } 235 return out; 236 } 237 238 // GLUT display function that runs test. Must be run within the display loop 239 // in order to properly destroy resources. 240 void openglsupport_test_loop() 241 { 242 // Get context info. 243 const GLubyte* gl_version_string = glGetString(GL_VERSION); 244 std::cerr << "GL version: " << gl_version_string << std::endl; 245 std::cerr << "GLSL version: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << std::endl; 246 // Parse version from string since GL_MAJOR_VERSION is only supported in GL 3.0+. 247 // Version string guaranteed to be <major>.<minor><vender extension>. 248 GLint gl_major_version = gl_version_string[0] - '0'; 249 GLint gl_minor_version = gl_version_string[2] - '0'; 250 bool legacy_gl = gl_major_version < 3 || (gl_major_version == 3 && gl_minor_version < 2); 251 252 // Fixed-function pipeline removed in OpenGL 3.2. 253 if (legacy_gl) 254 { 255 // Draw a basic triangle. 256 Vector3f v3f; 257 Matrix3f rot; 258 glBegin(GL_POINTS); 259 { 260 glVertex(v3f); 261 glVertex(2*v3f+v3f); 262 glVertex(rot*v3f); 263 } 264 glEnd(); 265 266 // 4x4 matrices 267 Matrix4f mf44; mf44.setRandom(); 268 VERIFY_MATRIX(glLoadMatrix(mf44), mf44); 269 VERIFY_MATRIX(glMultMatrix(mf44), mf44); 270 Matrix4d md44; md44.setRandom(); 271 VERIFY_MATRIX(glLoadMatrix(md44), md44); 272 VERIFY_MATRIX(glMultMatrix(md44), md44); 273 274 // Quaternion 275 Quaterniond qd(AngleAxisd(internal::random<double>(), Vector3d::Random())); 276 VERIFY_MATRIX(glRotate(qd), Projective3d(qd).matrix()); 277 278 Quaternionf qf(AngleAxisf(internal::random<double>(), Vector3f::Random())); 279 VERIFY_MATRIX(glRotate(qf), Projective3f(qf).matrix()); 280 281 // 3D Transform 282 Transform<float,3,AffineCompact> acf3; acf3.matrix().setRandom(); 283 VERIFY_MATRIX(glLoadMatrix(acf3), Projective3f(acf3).matrix()); 284 VERIFY_MATRIX(glMultMatrix(acf3), Projective3f(acf3).matrix()); 285 286 Transform<float,3,Affine> af3(acf3); 287 VERIFY_MATRIX(glLoadMatrix(af3), Projective3f(af3).matrix()); 288 VERIFY_MATRIX(glMultMatrix(af3), Projective3f(af3).matrix()); 289 290 Transform<float,3,Projective> pf3; pf3.matrix().setRandom(); 291 VERIFY_MATRIX(glLoadMatrix(pf3), Projective3f(pf3).matrix()); 292 VERIFY_MATRIX(glMultMatrix(pf3), Projective3f(pf3).matrix()); 293 294 Transform<double,3,AffineCompact> acd3; acd3.matrix().setRandom(); 295 VERIFY_MATRIX(glLoadMatrix(acd3), Projective3d(acd3).matrix()); 296 VERIFY_MATRIX(glMultMatrix(acd3), Projective3d(acd3).matrix()); 297 298 Transform<double,3,Affine> ad3(acd3); 299 VERIFY_MATRIX(glLoadMatrix(ad3), Projective3d(ad3).matrix()); 300 VERIFY_MATRIX(glMultMatrix(ad3), Projective3d(ad3).matrix()); 301 302 Transform<double,3,Projective> pd3; pd3.matrix().setRandom(); 303 VERIFY_MATRIX(glLoadMatrix(pd3), Projective3d(pd3).matrix()); 304 VERIFY_MATRIX(glMultMatrix(pd3), Projective3d(pd3).matrix()); 305 306 // translations (2D and 3D) 307 { 308 Vector2f vf2; vf2.setRandom(); Vector3f vf23; vf23 << vf2, 0; 309 VERIFY_MATRIX(glTranslate(vf2), Projective3f(Translation3f(vf23)).matrix()); 310 Vector2d vd2; vd2.setRandom(); Vector3d vd23; vd23 << vd2, 0; 311 VERIFY_MATRIX(glTranslate(vd2), Projective3d(Translation3d(vd23)).matrix()); 312 313 Vector3f vf3; vf3.setRandom(); 314 VERIFY_MATRIX(glTranslate(vf3), Projective3f(Translation3f(vf3)).matrix()); 315 Vector3d vd3; vd3.setRandom(); 316 VERIFY_MATRIX(glTranslate(vd3), Projective3d(Translation3d(vd3)).matrix()); 317 318 Translation<float,3> tf3; tf3.vector().setRandom(); 319 VERIFY_MATRIX(glTranslate(tf3), Projective3f(tf3).matrix()); 320 321 Translation<double,3> td3; td3.vector().setRandom(); 322 VERIFY_MATRIX(glTranslate(td3), Projective3d(td3).matrix()); 323 } 324 325 // scaling (2D and 3D) 326 { 327 Vector2f vf2; vf2.setRandom(); Vector3f vf23; vf23 << vf2, 1; 328 VERIFY_MATRIX(glScale(vf2), Projective3f(Scaling(vf23)).matrix()); 329 Vector2d vd2; vd2.setRandom(); Vector3d vd23; vd23 << vd2, 1; 330 VERIFY_MATRIX(glScale(vd2), Projective3d(Scaling(vd23)).matrix()); 331 332 Vector3f vf3; vf3.setRandom(); 333 VERIFY_MATRIX(glScale(vf3), Projective3f(Scaling(vf3)).matrix()); 334 Vector3d vd3; vd3.setRandom(); 335 VERIFY_MATRIX(glScale(vd3), Projective3d(Scaling(vd3)).matrix()); 336 337 UniformScaling<float> usf(internal::random<float>()); 338 VERIFY_MATRIX(glScale(usf), Projective3f(usf).matrix()); 339 340 UniformScaling<double> usd(internal::random<double>()); 341 VERIFY_MATRIX(glScale(usd), Projective3d(usd).matrix()); 342 } 343 } else { 344 std::cerr << "Warning: fixed-function pipeline was not tested.\n"; 345 } 346 347 // Dynamic shader substitution variables. 348 // Modern shaders require a version string, and newer runtimes fail to 349 // compile old GLSL versions. Thus, we dynamically set the GLSL version 350 // string based on runtime. Also, pre OpenGL 3.0, the output gl_FragColor was 351 // built-in. This was deprecated in OpenGL 3.0, requiring us to explicitly 352 // define the output variable. 353 std::vector<std::string> glsl_vars; 354 glsl_vars.push_back("${GLSL_VERSION}"); 355 glsl_vars.push_back("${FRAG_OUTPUT_DECLARATION}"); 356 glsl_vars.push_back("${FRAG_OUTPUT_VARIABLE}"); 357 358 std::vector<std::string> glsl_vals; 359 glsl_vals.push_back(getGlslVersionString(gl_major_version, gl_minor_version)); 360 if (gl_major_version >= 3) { 361 glsl_vals.push_back("out vec4 fragColor;"); 362 glsl_vals.push_back("fragColor"); 363 } else { 364 glsl_vals.push_back(""); 365 glsl_vals.push_back("gl_FragColor"); 366 } 367 368 // uniform 369 { 370 // vertex shader. 371 std::string vtx = format( 372 "${GLSL_VERSION}\n" 373 "void main(void) {\n" 374 " gl_Position = vec4(0,0,0,1);\n" 375 "}\n", 376 glsl_vars, glsl_vals); 377 378 #ifdef GL_VERSION_2_0 379 if(GLEW_VERSION_2_0 && GL_VERSION_2_0) 380 { 381 std::string frg = format( 382 "${GLSL_VERSION}\n" 383 "uniform vec2 v2f;\n" 384 "uniform vec3 v3f;\n" 385 "uniform vec4 v4f;\n" 386 "uniform ivec2 v2i;\n" 387 "uniform ivec3 v3i;\n" 388 "uniform ivec4 v4i;\n" 389 "uniform mat2 m2f;\n" 390 "uniform mat3 m3f;\n" 391 "uniform mat4 m4f;\n" 392 "${FRAG_OUTPUT_DECLARATION}\n" 393 "void main(void) { \n" 394 " ${FRAG_OUTPUT_VARIABLE} = vec4(v2f[0]+v3f[0]+v4f[0])+vec4(v2i[0]+v3i[0]+v4i[0])+vec4(m2f[0][0]+m3f[0][0]+m4f[0][0]);\n" 395 "}\n", 396 glsl_vars, glsl_vals); 397 398 GLint prg_id = createProgram(vtx, frg); 399 VERIFY(prg_id > 0 && "Failed to create program."); 400 VERIFY_UNIFORM(fv, v2f, Vector2f); 401 VERIFY_UNIFORM(fv, v3f, Vector3f); 402 VERIFY_UNIFORM(fv, v4f, Vector4f); 403 VERIFY_UNIFORMi(v2i, Vector2i); 404 VERIFY_UNIFORMi(v3i, Vector3i); 405 VERIFY_UNIFORMi(v4i, Vector4i); 406 VERIFY_UNIFORM(fv, m2f, Matrix2f); 407 VERIFY_UNIFORM(fv, m3f, Matrix3f); 408 VERIFY_UNIFORM(fv, m4f, Matrix4f); 409 glDeleteProgram(prg_id); 410 } 411 else 412 #endif 413 std::cerr << "Warning: opengl 2.0 was not tested.\n"; 414 415 #ifdef GL_VERSION_2_1 416 if(GLEW_VERSION_2_1 && GL_VERSION_2_1 && 417 (gl_major_version > 2 || (gl_major_version == 2 && gl_minor_version >= 1))) 418 { 419 std::string frg = format( 420 "${GLSL_VERSION}\n" 421 "uniform mat2x3 m23f;\n" 422 "uniform mat3x2 m32f;\n" 423 "uniform mat2x4 m24f;\n" 424 "uniform mat4x2 m42f;\n" 425 "uniform mat3x4 m34f;\n" 426 "uniform mat4x3 m43f;\n" 427 "${FRAG_OUTPUT_DECLARATION}\n" 428 "void main(void) {\n" 429 " ${FRAG_OUTPUT_VARIABLE} = vec4(m23f[0][0]+m32f[0][0]+m24f[0][0]+m42f[0][0]+m34f[0][0]+m43f[0][0]);\n" 430 "}\n", 431 glsl_vars, glsl_vals); 432 433 GLint prg_id = createProgram(vtx, frg); 434 VERIFY(prg_id > 0 && "Failed to create program."); 435 typedef Matrix<float,2,3> Matrix23f; 436 typedef Matrix<float,3,2> Matrix32f; 437 typedef Matrix<float,2,4> Matrix24f; 438 typedef Matrix<float,4,2> Matrix42f; 439 typedef Matrix<float,3,4> Matrix34f; 440 typedef Matrix<float,4,3> Matrix43f; 441 442 VERIFY_UNIFORM(fv, m23f, Matrix23f); 443 VERIFY_UNIFORM(fv, m32f, Matrix32f); 444 VERIFY_UNIFORM(fv, m24f, Matrix24f); 445 VERIFY_UNIFORM(fv, m42f, Matrix42f); 446 VERIFY_UNIFORM(fv, m34f, Matrix34f); 447 VERIFY_UNIFORM(fv, m43f, Matrix43f); 448 glDeleteProgram(prg_id); 449 } 450 else 451 #endif 452 std::cerr << "Warning: opengl 2.1 was not tested.\n"; 453 454 #ifdef GL_VERSION_3_0 455 if(GLEW_VERSION_3_0 && GL_VERSION_3_0 && gl_major_version >= 3) 456 { 457 std::string frg = format( 458 "${GLSL_VERSION}\n" 459 "uniform uvec2 v2ui;\n" 460 "uniform uvec3 v3ui;\n" 461 "uniform uvec4 v4ui;\n" 462 "${FRAG_OUTPUT_DECLARATION}\n" 463 "void main(void) {\n" 464 " ${FRAG_OUTPUT_VARIABLE} = vec4(v2ui[0]+v3ui[0]+v4ui[0]);\n" 465 "}\n", 466 glsl_vars, glsl_vals); 467 468 GLint prg_id = createProgram(vtx, frg); 469 VERIFY(prg_id > 0 && "Failed to create program."); 470 typedef Matrix<unsigned int,2,1> Vector2ui; 471 typedef Matrix<unsigned int,3,1> Vector3ui; 472 typedef Matrix<unsigned int,4,1> Vector4ui; 473 474 VERIFY_UNIFORMi(v2ui, Vector2ui); 475 VERIFY_UNIFORMi(v3ui, Vector3ui); 476 VERIFY_UNIFORMi(v4ui, Vector4ui); 477 glDeleteProgram(prg_id); 478 } 479 else 480 #endif 481 std::cerr << "Warning: opengl 3.0 was not tested.\n"; 482 483 // dvecn supported if >= 4.1 or ARB_vertex_attrib_64bit 484 bool has_fp64_native = (gl_major_version == 4 && gl_minor_version >= 1); 485 bool has_fp64_extension = false; 486 #ifdef GLEW_ARB_gpu_shader_fp64 487 if(GLEW_ARB_gpu_shader_fp64) 488 { 489 // Check that extension can actually be compiled. 490 if (has_fp64_extension) 491 { 492 std::string frg = format( 493 "${GLSL_VERSION}\n" 494 "#extension GL_ARB_gpu_shader_fp64 : enable\n" 495 "uniform dvec2 dv2;\n" 496 "${FRAG_OUTPUT_DECLARATION}\n" 497 "void main(void) {\n" 498 " ${FRAG_OUTPUT_VARIABLE} = vec4(dv2.x, dv2.y, dv2.x, dv2.y);\n" 499 "}\n", 500 glsl_vars, glsl_vals); 501 GLint prg_id = createProgram(vtx, frg, /*print_errors=*/false); 502 if (prg_id) 503 { 504 has_fp64_extension = true; 505 glDeleteProgram(prg_id); 506 } 507 } 508 } 509 #endif 510 511 if( has_fp64_native || has_fp64_extension ) 512 { 513 std::vector<std::string> glsl_vars_with_extension = glsl_vars; 514 glsl_vars_with_extension.push_back("${GLSL_EXTENSIONS}"); 515 std::vector<std::string> glsl_vals_with_extension = glsl_vals; 516 if (has_fp64_extension) 517 { 518 glsl_vals_with_extension.push_back("#extension GL_ARB_gpu_shader_fp64 : enable"); 519 } 520 else 521 { 522 glsl_vals_with_extension.push_back(""); 523 } 524 525 std::string frg = format( 526 "${GLSL_VERSION}\n" 527 "${GLSL_EXTENSIONS}\n" 528 "uniform dvec2 v2d;\n" 529 "uniform dvec3 v3d;\n" 530 "uniform dvec4 v4d;\n" 531 "${FRAG_OUTPUT_DECLARATION}\n" 532 "void main(void) {\n" 533 " ${FRAG_OUTPUT_VARIABLE} = vec4(v2d[0]+v3d[0]+v4d[0]);\n" 534 "}\n", 535 glsl_vars_with_extension, glsl_vals_with_extension); 536 537 GLint prg_id = createProgram(vtx,frg); 538 VERIFY(prg_id > 0 && "Failed to create program."); 539 VERIFY_UNIFORM(dv, v2d, Vector2d); 540 VERIFY_UNIFORM(dv, v3d, Vector3d); 541 VERIFY_UNIFORM(dv, v4d, Vector4d); 542 glDeleteProgram(prg_id); 543 } 544 else 545 std::cerr << "Warning: dvec (fp64) was not tested.\n"; 546 } 547 548 // Exit loop - Leaving main loop is supported by freeglut, otherwise we 549 // are forced to exit. 550 #ifdef FREEGLUT 551 glutLeaveMainLoop(); 552 // Trigger another display loop iteration. Otherwise, it just hangs. 553 glutPostRedisplay(); 554 #else 555 exit(0); 556 #endif 557 } 558 559 EIGEN_DECLARE_TEST(openglsupport) 560 { 561 int argc = 0; 562 glutInit(&argc, 0); 563 564 GLint glut_display_mode = GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH; 565 566 #ifndef EIGEN_LEGACY_OPENGL 567 // Initialize 3.2+ OpenGL context. 568 #if defined(__APPLE_CC__) 569 glut_display_mode |= GLUT_3_2_CORE_PROFILE; 570 #elif defined(FREEGLUT) 571 glutInitContextVersion(3, 2); 572 glutInitContextFlags(GLUT_FORWARD_COMPATIBLE); 573 glutInitContextProfile(GLUT_CORE_PROFILE); 574 #endif 575 #endif 576 577 glutInitDisplayMode(glut_display_mode); 578 glutInitWindowPosition(0, 0); 579 glutInitWindowSize(10, 10); 580 581 int window = glutCreateWindow("Eigen"); 582 if(window <= 0) 583 { 584 std::cerr << "Error: Unable to create GLUT Window.\n"; 585 exit(1); 586 } 587 588 glewExperimental = GL_TRUE; 589 if(glewInit() != GLEW_OK) 590 { 591 std::cerr << "Warning: Failed to initialize GLEW.\n"; 592 exit(1); 593 } 594 595 // Run test in display, otherwise GLUT fails to clean up and leads to memory 596 // access errors on exit. 597 glutDisplayFunc(openglsupport_test_loop); 598 glutMainLoop(); 599 glutDestroyWindow(window); 600 }