]> git.tdb.fi Git - geometrycompositor.git/blobdiff - source/main.c
Unbind the vertex array after rendering
[geometrycompositor.git] / source / main.c
index f34acb54885ac30a1e1d5ea18869f6aba83f5151..92537e21a59bf3c01dee00ec66e94bb75109cde1 100644 (file)
@@ -3,6 +3,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <signal.h>
+#include <math.h>
 #include <X11/Xlib.h>
 #include <X11/extensions/Xcomposite.h>
 #include <X11/extensions/Xdamage.h>
@@ -33,6 +34,10 @@ typedef struct CompositedMonitor
        int y;
        unsigned width;
        unsigned height;
+       float keystone_vertical;
+       float cylinder_depth;
+       float vertical_center;
+       float perspective;
        unsigned vertex_buffer;
        unsigned index_buffer;
        unsigned vertex_array;
@@ -455,24 +460,49 @@ void update_monitor_vertices(CompositedScreen *screen, CompositedMonitor *monito
        unsigned short *index_data;
        unsigned x, y;
        unsigned i;
+       float aspect;
+       float cyl_w_sq;
+       float sin_ksv;
+       float cos_ksv;
 
        t = monitor->tessellation;
 
        data_size = (t+1)*(t+1)*4*sizeof(float);
        vertex_data = (float *)malloc(data_size);
+       aspect = (float)monitor->width/monitor->height;
+       cyl_w_sq = 0.25f-(0.5f-monitor->cylinder_depth)*(0.5f-monitor->cylinder_depth);
+       sin_ksv = monitor->keystone_vertical/sqrt(1.0f+monitor->keystone_vertical*monitor->keystone_vertical);
+       cos_ksv = sqrt(1.0f-sin_ksv*sin_ksv);
        for(y=0; y<=t; ++y)
                for(x=0; x<=t; ++x)
                {
-                       float xf, yf;
+                       float xf, yf, z, rz;
+                       float scale;
                        float *v;
 
                        xf = (float)x/t;
                        yf = (float)y/t;
+
                        v = vertex_data+(y*(t+1)+x)*4;
-                       v[0] = xf;
-                       v[1] = yf;
                        v[2] = (monitor->x+xf*monitor->width)/screen->width;
                        v[3] = (monitor->y+yf*monitor->height)/screen->height;
+
+                       z = sqrt(0.25f-(xf-0.5f)*(xf-0.5f)*4.0f*cyl_w_sq)-0.5f+monitor->cylinder_depth;
+                       if(monitor->keystone_vertical>0)
+                       {
+                               rz = (1.0f-yf)/aspect*sin_ksv+z*cos_ksv;
+                               yf = 1.0f-((1.0f-yf)*cos_ksv-z*aspect*sin_ksv);
+                               z = rz;
+                       }
+                       else if(monitor->keystone_vertical<0)
+                       {
+                               rz = z*cos_ksv-yf/aspect*sin_ksv;
+                               yf = yf*cos_ksv+z*aspect*sin_ksv;
+                               z = rz;
+                       }
+                       scale = monitor->perspective/(monitor->perspective+z);
+                       v[0] = 0.5f+(xf-0.5f)*scale;
+                       v[1] = monitor->vertical_center+(yf-monitor->vertical_center)*scale;
                }
        glBindBuffer(GL_ARRAY_BUFFER, monitor->vertex_buffer);
        glBufferData(GL_ARRAY_BUFFER, data_size, vertex_data, GL_STATIC_DRAW);
@@ -499,13 +529,16 @@ void update_monitor_vertices(CompositedScreen *screen, CompositedMonitor *monito
        free(index_data);
 }
 
-int initialize_monitor(Compositor *compositor, CompositedScreen *screen, CompositedMonitor *monitor, XRRScreenResources *xrr_res, unsigned index)
+int initialize_monitor(Compositor *compositor, CompositedScreen *screen, XRRScreenResources *xrr_res, unsigned index)
 {
+       CompositedMonitor *monitor;
        XRROutputInfo *output;
        XRRCrtcInfo *crtc;
        unsigned buffers[2];
        unsigned stride;
 
+       monitor = &screen->monitors[index];
+
        output = XRRGetOutputInfo(compositor->display, xrr_res, xrr_res->outputs[index]);
        monitor->enabled = !!output->crtc;
        if(!monitor->enabled)
@@ -522,11 +555,16 @@ int initialize_monitor(Compositor *compositor, CompositedScreen *screen, Composi
        XRRFreeCrtcInfo(crtc);
        XRRFreeOutputInfo(output);
 
+       monitor->keystone_vertical = 0.0f;
+       monitor->cylinder_depth = 0.0f;
+       monitor->vertical_center = 0.5f;
+       monitor->perspective = 1.0f;
+
        glGenBuffers(2, buffers);
        monitor->vertex_buffer = buffers[0];
        monitor->index_buffer = buffers[1];
 
-       monitor->tessellation = 20;
+       monitor->tessellation = 50;
        update_monitor_vertices(screen, monitor);
        stride = 4*sizeof(float);
 
@@ -583,7 +621,7 @@ int initialize_screen(Compositor *compositor, unsigned number)
        screen->nmonitors = xrr_res->noutput;
        screen->monitors = (CompositedMonitor *)malloc(screen->nmonitors*sizeof(CompositedMonitor));
        for(i=0; i<screen->nmonitors; ++i)
-               if(!initialize_monitor(compositor, screen, &screen->monitors[i], xrr_res, i))
+               if(!initialize_monitor(compositor, screen, xrr_res, i))
                        return 0;
        XRRFreeScreenResources(xrr_res);
 
@@ -684,6 +722,22 @@ void shutdown_screen(Compositor *compositor, CompositedScreen *screen)
                }
        }
 
+       for(i=0; i<screen->nmonitors; ++i)
+               if(screen->monitors[i].enabled)
+               {
+                       glDeleteBuffers(1, &screen->monitors[i].vertex_buffer);
+                       glDeleteBuffers(1, &screen->monitors[i].index_buffer);
+                       glDeleteVertexArrays(1, &screen->monitors[i].vertex_array);
+               }
+
+       glDeleteBuffers(1, &screen->window_vertex_buffer);
+       glDeleteVertexArrays(1, &screen->window_vertex_array);
+       glDeleteFramebuffers(1, &screen->framebuffer);
+       glDeleteTextures(1, &screen->fb_texture);
+       glDeleteProgram(screen->program);
+       glDeleteShader(screen->shaders[0]);
+       glDeleteShader(screen->shaders[1]);
+
        glXMakeContextCurrent(compositor->display, 0, 0, NULL);
        glXDestroyContext(compositor->display, screen->glx_context);
        glXDestroyWindow(compositor->display, screen->glx_window);
@@ -894,7 +948,7 @@ void refresh_screen(Compositor *compositor, CompositedScreen *screen)
                glBindTexture(GL_TEXTURE_2D, window->texture);
                compositor->glXBindTexImageEXT(compositor->display, window->glx_pixmap, GLX_FRONT_LEFT_EXT, NULL);
                glUniform4f(screen->geometry_loc,
-                       (float)window->x/screen->width, (float)(screen->height-window->y-window->height)/screen->height,
+                       (float)window->x/screen->width, ((float)screen->height-window->y-window->height)/screen->height,
                        (float)(window->width+2*window->border)/screen->width, (float)(window->height+2*window->border)/screen->height);
                glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
                compositor->glXReleaseTexImageEXT(compositor->display, window->glx_pixmap, GLX_FRONT_LEFT_EXT);
@@ -922,6 +976,8 @@ void refresh_screen(Compositor *compositor, CompositedScreen *screen)
                glDrawElements(GL_TRIANGLE_STRIP, monitor->nelements, GL_UNSIGNED_SHORT, NULL);
        }
 
+       glBindVertexArray(0);
+
        glXSwapBuffers(compositor->display, screen->glx_window);
 
        screen->dirty = 0;