+
+void cleanup_vertex_attribute(GLuint glsl_program_num, const string &attribute_name, GLuint vbo)
+{
+ int attrib = glGetAttribLocation(glsl_program_num, attribute_name.c_str());
+ if (attrib == -1) {
+ return;
+ }
+
+ glDisableVertexAttribArray(attrib);
+ check_error();
+ glDeleteBuffers(1, &vbo);
+ check_error();
+}
+
+unsigned div_round_up(unsigned a, unsigned b)
+{
+ return (a + b - 1) / b;
+}
+
+// Algorithm from http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2.
+unsigned next_power_of_two(unsigned v)
+{
+ v--;
+ v |= v >> 1;
+ v |= v >> 2;
+ v |= v >> 4;
+ v |= v >> 8;
+ v |= v >> 16;
+ v++;
+ return v;
+}
+
+void *get_gl_context_identifier()
+{
+#if defined(__APPLE__)
+ return (void *)CGLGetCurrentContext();
+#elif defined(WIN32)
+ return (void *)wglGetCurrentContext();
+#else
+ void *ret = (void *)eglGetCurrentContext();
+ if (ret != NULL) {
+ return ret;
+ }
+ return (void *)glXGetCurrentContext();
+#endif
+}
+
+void abort_gl_error(GLenum err, const char *filename, int line)
+{
+ const char *err_text = "unknown";
+
+ // All errors listed in the glGetError(3G) man page.
+ switch (err) {
+ case GL_NO_ERROR:
+ err_text = "GL_NO_ERROR"; // Should not happen.
+ break;
+ case GL_INVALID_ENUM:
+ err_text = "GL_INVALID_ENUM";
+ break;
+ case GL_INVALID_VALUE:
+ err_text = "GL_INVALID_VALUE";
+ break;
+ case GL_INVALID_OPERATION:
+ err_text = "GL_INVALID_OPERATION";
+ break;
+ case GL_INVALID_FRAMEBUFFER_OPERATION:
+ err_text = "GL_INVALID_FRAMEBUFFER_OPERATION";
+ break;
+ case GL_OUT_OF_MEMORY:
+ err_text = "GL_OUT_OF_MEMORY";
+ break;
+ case GL_STACK_UNDERFLOW:
+ err_text = "GL_STACK_UNDERFLOW";
+ break;
+ case GL_STACK_OVERFLOW:
+ err_text = "GL_STACK_OVERFLOW";
+ break;
+ }
+ fprintf(stderr, "GL error 0x%x (%s) at %s:%d\n", err, err_text, filename, line);
+ abort();
+}
+
+} // namespace movit