#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>
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;
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);
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)
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);
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);
}
}
+ 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);
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);
glDrawElements(GL_TRIANGLE_STRIP, monitor->nelements, GL_UNSIGNED_SHORT, NULL);
}
+ glBindVertexArray(0);
+
glXSwapBuffers(compositor->display, screen->glx_window);
screen->dirty = 0;