+static guint load_tex(gchar *filename)
+{
+ GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
+ guchar *pixels = gdk_pixbuf_get_pixels(pixbuf);
+ int width = gdk_pixbuf_get_width(pixbuf);
+ int height = gdk_pixbuf_get_height(pixbuf);
+ int alpha = gdk_pixbuf_get_has_alpha(pixbuf);
+ guint tex;
+ glGenTextures(1, &tex);
+ glBindTexture(GL_TEXTURE_2D, tex);
+ glTexImage2D(GL_TEXTURE_2D, 0, 4, width, height, 0,
+ (alpha ? GL_RGBA : GL_RGB), GL_UNSIGNED_BYTE, pixels);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
+ g_object_unref(pixbuf);
+ return tex;
+}
+
+gchar *gl_program_log(guint program, int *_len)
+{
+ gchar *buf = NULL;
+ int len = 0;
+ glGetProgramiv(program, GL_INFO_LOG_LENGTH, &len);
+ if (len > 0) {
+ buf = g_malloc(len);
+ glGetProgramInfoLog(program, len, &len, buf);
+ }
+ if (_len)
+ *_len = len;
+ return buf;
+}
+
+static void load_shader(gchar *filename)
+{
+ gchar *source;
+ gboolean status = g_file_get_contents(filename, &source, NULL, NULL);
+ if (!status)
+ g_error("Failed to load shader");
+
+ guint program = glCreateProgram();
+ if (!program)
+ g_error("Error creating program");
+
+ guint shader = glCreateShader(GL_VERTEX_SHADER_ARB);
+ if (!shader)
+ g_error("Error creating shader");
+
+ glShaderSource(shader, 1, (const gchar**)&source, NULL);
+ if (glGetError())
+ g_error("Error setting shader source");
+
+ glCompileShader(shader);
+ if (glGetError())
+ g_error("Error compiling shader");
+
+ glAttachShader(program, shader);
+ if (glGetError())
+ g_error("Error attaching shader");
+
+ glLinkProgram(program);
+ if (glGetError())
+ g_error("Error linking program");
+
+ glUseProgram(program);
+ if (glGetError())
+ g_error("Error using program:\n%s", gl_program_log(program, NULL));
+}
+