#include #include #include #define GL_GLEXT_PROTOTYPES #if 0 #include #else #include #endif #include #include #include "util.h" EGLDisplay dpy; GLuint vbo; GLint proj_uniform, tex_uniform, pixelsize_uniform, search_rect_uniform, barrier_uniform; GLuint texture; int width, height; GLuint program; GdkPixbuf *pixbuf; int x1, y1; int mwidth, mheight; static int init_shaders() { GLuint v, f; GError *error; gsize length; gchar *p; char msg[512]; GLfloat vertices[4 * 5]; GLint status; g_file_get_contents("wimmel.vert", &p, &length, &error); v = glCreateShader(GL_VERTEX_SHADER); glShaderSource(v, 1, (const GLchar **) &p, NULL); glCompileShader(v); glGetShaderiv(v, GL_COMPILE_STATUS, &status); g_free(p); if (!status) { glGetShaderInfoLog(v, sizeof msg, NULL, msg); fprintf(stderr, "vertex shader info: %s\n", msg); return -1; } g_file_get_contents("wimmel.frag", &p, &length, &error); f = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(f, 1, (const GLchar **) &p, NULL); glCompileShader(f); glGetShaderiv(f, GL_COMPILE_STATUS, &status); g_free(p); if (!status) { glGetShaderInfoLog(f, sizeof msg, NULL, msg); fprintf(stderr, "fragment shader info: %s\n", msg); return -1; } program = glCreateProgram(); glAttachShader(program, v); glAttachShader(program, f); glBindAttribLocation(program, 0, "position"); glBindAttribLocation(program, 1, "texcoord"); glLinkProgram(program); glGetProgramiv(program, GL_LINK_STATUS, &status); if (!status) { glGetProgramInfoLog(program, sizeof msg, NULL, msg); fprintf(stderr, "link info: %s\n", msg); return -1; } glUseProgram(program); proj_uniform = glGetUniformLocation(program, "proj"); tex_uniform = glGetUniformLocation(program, "tex"); pixelsize_uniform = glGetUniformLocation(program, "pixelsize"); search_rect_uniform = glGetUniformLocation(program, "search_rect"); barrier_uniform = glGetUniformLocation(program, "barrier"); vertices[ 0] = 0.0; vertices[ 1] = 0.0; vertices[ 2] = 0.0; vertices[ 3] = 0.0; vertices[ 4] = 0.0; vertices[ 5] = 0.0; vertices[ 6] = 1.0; vertices[ 7] = 0.0; vertices[ 8] = 0.0; vertices[ 9] = 1.0; vertices[10] = 1.0; vertices[11] = 0.0; vertices[12] = 0.0; vertices[13] = 1.0; vertices[14] = 0.0; vertices[15] = 1.0; vertices[16] = 1.0; vertices[17] = 0.0; vertices[18] = 1.0; vertices[19] = 1.0; glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, sizeof vertices, vertices, GL_STATIC_DRAW); return 0; } static void create_texture(GdkPixbuf *pixbuf) { void *data; GLenum format; glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); data = gdk_pixbuf_get_pixels(pixbuf); if (gdk_pixbuf_get_has_alpha(pixbuf)) format = GL_RGBA; else format = GL_RGB; glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, format, GL_UNSIGNED_BYTE, data); } static void draw(void) { float pixelsize[] = { 1.0 / width, 1.0 / height }; static GLfloat proj[16] = { 2., 0., 0., 0., 0., -2., 0., 0., 0., 0., 1., 0., -1., 1., 0., 1. }; float search[4]; int barrier = mwidth * mheight / 2; glClear(GL_COLOR_BUFFER_BIT); glUniformMatrix4fv(proj_uniform, 1, GL_FALSE, proj); glUniform1i(tex_uniform, 0); glUniform2fv(pixelsize_uniform, 1, pixelsize); search[0] = 1.0 * x1 / width; search[1] = 1.0 * y1 / height; search[2] = 1.0 * mwidth / width; search[3] = 1.0 * mheight / height; glUniform4fv(search_rect_uniform, 1, search); glUniform1i(barrier_uniform, barrier); glDisable(GL_BLEND); glBindTexture(GL_TEXTURE_2D, texture); glBindBuffer(GL_ARRAY_BUFFER, vbo); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GL_FLOAT), NULL); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GL_FLOAT), (GLfloat *)0 + 3); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glFinish(); printf("finished\n"); } static void init_gl(void) { GLuint fb, rb; #if 0 glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGBA /*| GLUT_DEPTH */ | GLUT_DOUBLE); glutInitWindowSize(1,1); int window = glutCreateWindow("wimmel"); glutDestroyWindow(window); #else dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); eglInitialize(dpy, NULL, NULL); eglBindAPI(EGL_OPENGL_API); EGLContext ctx = eglCreateContext(dpy, NULL, EGL_NO_CONTEXT, NULL); if (ctx == NULL) { fprintf(stderr, "failed to create context\n"); exit(EXIT_FAILURE); } if (!eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, ctx)) { fprintf(stderr, "failed to make context current\n"); exit(EXIT_FAILURE); } #endif glGenFramebuffersEXT(1, &fb); glGenRenderbuffersEXT(1, &rb); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rb); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, rb); glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA, width, height); if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) { fprintf(stderr, "Framebuffer not complete\n"); exit(EXIT_FAILURE); } } int main(int argc, char **argv) { gint stride; guchar *buffer; g_type_init(); if (argc <= 5) return 1; pixbuf = gdk_pixbuf_new_from_file(argv[1], NULL); if (!pixbuf) return 1; width = gdk_pixbuf_get_width(pixbuf); height = gdk_pixbuf_get_height(pixbuf); init_gl(); x1 = atoi(argv[2]); y1 = atoi(argv[3]); mwidth = atoi(argv[4]); mheight = atoi(argv[5]); init_shaders(); create_texture(pixbuf); glViewport(0,0,width,height); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); draw(); glPixelStorei(GL_PACK_ALIGNMENT, 2); stride = width * 4; buffer = malloc(stride * height); glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer); for (int j = 0; j < height; ++j) { guchar *row = buffer + (height - 1 - j) * stride; for (int i = 0; i < width; ++i) { if (*(row + i*4)) { color_t color = COLOR(255, 0, 0, 0); for (int k = i; k < i+mwidth; k++) { put_pixel(pixbuf, POINT(k, j), color); put_pixel(pixbuf, POINT(k, j+mheight), color); } for (int n = j; n < j+mheight; n++) { put_pixel(pixbuf, POINT(i, n), color); put_pixel(pixbuf, POINT(i+mwidth, n), color); } } } } gdk_pixbuf_save(pixbuf, "output_gl.png", "png", NULL, NULL); free(buffer); g_object_unref(pixbuf); eglTerminate(dpy); return 0; }