+ DCPOMATIC_ASSERT (_canvas);
+ DCPOMATIC_ASSERT (_context);
+ auto r = _canvas->SetCurrent (*_context);
+ DCPOMATIC_ASSERT (r);
+
+#ifdef DCPOMATIC_WINDOWS
+ r = glewInit();
+ if (r != GLEW_OK) {
+ throw GLError(reinterpret_cast<char const*>(glewGetErrorString(r)));
+ }
+#endif
+
+ auto get_information = [this](GLenum name) {
+ auto s = glGetString (name);
+ if (s) {
+ _information[name] = std::string (reinterpret_cast<char const *>(s));
+ }
+ };
+
+ get_information (GL_VENDOR);
+ get_information (GL_RENDERER);
+ get_information (GL_VERSION);
+ get_information (GL_SHADING_LANGUAGE_VERSION);
+
+ glGenVertexArrays(1, &_vao);
+ check_gl_error ("glGenVertexArrays");
+ GLuint vbo;
+ glGenBuffers(1, &vbo);
+ check_gl_error ("glGenBuffers");
+ GLuint ebo;
+ glGenBuffers(1, &ebo);
+ check_gl_error ("glGenBuffers");
+
+ glBindVertexArray(_vao);
+ check_gl_error ("glBindVertexArray");
+
+ glBindBuffer(GL_ARRAY_BUFFER, vbo);
+ check_gl_error ("glBindBuffer");
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
+ check_gl_error ("glBindBuffer");
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
+ check_gl_error ("glBufferData");
+
+ /* position attribute to vertex shader (location = 0) */
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), nullptr);
+ glEnableVertexAttribArray(0);
+ /* texture coord attribute to vertex shader (location = 1) */
+ glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), reinterpret_cast<void*>(3 * sizeof(float)));
+ glEnableVertexAttribArray(1);
+ check_gl_error ("glEnableVertexAttribArray");
+
+ auto compile = [](GLenum type, char const* source) -> GLuint {
+ auto shader = glCreateShader(type);
+ DCPOMATIC_ASSERT (shader);
+ GLchar const * src[] = { static_cast<GLchar const *>(source) };
+ glShaderSource(shader, 1, src, nullptr);
+ check_gl_error ("glShaderSource");
+ glCompileShader(shader);
+ check_gl_error ("glCompileShader");
+ GLint ok;
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &ok);
+ if (!ok) {
+ GLint log_length;
+ glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length);
+ string log;
+ if (log_length > 0) {
+ char* log_char = new char[log_length];
+ glGetShaderInfoLog(shader, log_length, nullptr, log_char);
+ log = string(log_char);
+ delete[] log_char;
+ }
+ glDeleteShader(shader);
+ throw GLError(String::compose("Could not compile shader (%1)", log).c_str(), -1);
+ }
+ return shader;
+ };
+
+ auto vertex_shader = compile (GL_VERTEX_SHADER, vertex_source);
+ auto fragment_shader = compile (GL_FRAGMENT_SHADER, fragment_source);
+
+ auto program = glCreateProgram();
+ check_gl_error ("glCreateProgram");
+ glAttachShader (program, vertex_shader);
+ check_gl_error ("glAttachShader");
+ glAttachShader (program, fragment_shader);
+ check_gl_error ("glAttachShader");
+ glLinkProgram (program);
+ check_gl_error ("glLinkProgram");
+ GLint ok;
+ glGetProgramiv (program, GL_LINK_STATUS, &ok);
+ if (!ok) {
+ GLint log_length;
+ glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length);
+ string log;
+ if (log_length > 0) {
+ char* log_char = new char[log_length];
+ glGetProgramInfoLog(program, log_length, nullptr, log_char);
+ log = string(log_char);
+ delete[] log_char;
+ }
+ glDeleteProgram (program);
+ throw GLError(String::compose("Could not link shader (%1)", log).c_str(), -1);
+ }
+ glDeleteShader (vertex_shader);
+ glDeleteShader (fragment_shader);
+
+ glUseProgram (program);