X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fmain.c;h=b1247d88d680ec012d36215fc0bede6fcb8f782b;hb=d1f9b38df9dbe416341869c1bd630fe24367673e;hp=bfb01a4dac17ebacaf28d7df339409bc4e699b1c;hpb=7a472cbdabfe572481d6dd532c3aaff59405d6aa;p=geometrycompositor.git diff --git a/source/main.c b/source/main.c index bfb01a4..b1247d8 100644 --- a/source/main.c +++ b/source/main.c @@ -32,6 +32,12 @@ typedef struct CompositedWindow int recreate_mask; } CompositedWindow; +enum +{ + CYLINDRICAL = 1, + SPHERICAL +}; + typedef struct CompositedMonitor { char *name; @@ -41,7 +47,8 @@ typedef struct CompositedMonitor unsigned width; unsigned height; float keystone_vertical; - float cylinder_depth; + float curvature_type; + float curvature_depth; float vertical_center; float perspective; unsigned vertex_buffer; @@ -49,6 +56,8 @@ typedef struct CompositedMonitor unsigned vertex_array; unsigned tessellation; unsigned nelements; + short *geometry_data; + unsigned geometry_data_size; } CompositedMonitor; typedef struct CompositedScreen @@ -71,6 +80,9 @@ typedef struct CompositedScreen unsigned window_vertex_array; unsigned framebuffer; unsigned fb_texture; + Pixmap root_pixmap; + GLXPixmap root_glx_pixmap; + unsigned root_texture; CompositedWindow *windows; unsigned nwindows; unsigned windows_capacity; @@ -89,13 +101,16 @@ typedef struct Compositor PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB; PFNGLXBINDTEXIMAGEEXTPROC glXBindTexImageEXT; PFNGLXRELEASETEXIMAGEEXTPROC glXReleaseTexImageEXT; + Atom root_pmap_atom; Atom correction_atom; Atom monitors_atom; + Atom geometry_data_atom; + Window selection_window; int dirty; } Compositor; static const char *vshader_src = - "#version 150\n" + "#version 130\n" "uniform vec4 geometry;\n" "in vec2 vertex;\n" "in vec2 texture_coord;\n" @@ -107,7 +122,7 @@ static const char *vshader_src = "}\n"; static const char *fshader_src = - "#version 150\n" + "#version 130\n" "uniform sampler2D image;\n" "in vec2 texcoord;\n" "out vec4 frag_color;\n" @@ -117,7 +132,7 @@ static const char *fshader_src = "}\n"; static const char *masked_fshader_src = - "#version 150\n" + "#version 130\n" "uniform sampler2D image;\n" "uniform sampler2D mask;\n" "in vec2 texcoord;\n" @@ -325,6 +340,8 @@ int create_gl_resources(CompositedScreen *screen) glDepthMask(GL_FALSE); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + screen->root_texture = create_2d_texture(); + return 1; } @@ -357,17 +374,11 @@ CompositedWindow *find_window_global(Compositor *compositor, Window w, Composite return NULL; } -void create_window_pixmap(Compositor *compositor, CompositedScreen *screen, CompositedWindow *window) +GLXPixmap pixmap_to_glx_pixmap(Compositor *compositor, CompositedScreen *screen, Pixmap pixmap) { int attribs[5]; unsigned i; - if(window->pixmap) - { - glXDestroyPixmap(compositor->display, window->glx_pixmap); - XFreePixmap(compositor->display, window->pixmap); - } - i = 0; attribs[i++] = GLX_TEXTURE_TARGET_EXT; attribs[i++] = GLX_TEXTURE_2D_EXT; @@ -375,8 +386,19 @@ void create_window_pixmap(Compositor *compositor, CompositedScreen *screen, Comp attribs[i++] = GLX_TEXTURE_FORMAT_RGBA_EXT; attribs[i++] = None; + return glXCreatePixmap(compositor->display, screen->fbconfig, pixmap, attribs); +} + +void create_window_pixmap(Compositor *compositor, CompositedScreen *screen, CompositedWindow *window) +{ + if(window->pixmap) + { + glXDestroyPixmap(compositor->display, window->glx_pixmap); + XFreePixmap(compositor->display, window->pixmap); + } + window->pixmap = XCompositeNameWindowPixmap(compositor->display, window->window); - window->glx_pixmap = glXCreatePixmap(compositor->display, screen->fbconfig, window->pixmap, attribs); + window->glx_pixmap = pixmap_to_glx_pixmap(compositor, screen, window->pixmap); window->recreate_pixmap = 0; } @@ -495,6 +517,7 @@ CompositedWindow *add_window(Compositor *compositor, CompositedScreen *screen, W window->texture = create_2d_texture(); window->mask_texture = create_2d_texture(); + window->use_mask = 0; window->recreate_mask = (window->map_state==IsViewable); XShapeSelectInput(compositor->display, window->window, ShapeNotifyMask); @@ -595,9 +618,9 @@ void update_monitor_vertices(CompositedScreen *screen, CompositedMonitor *monito aspect = (float)monitor->width/monitor->height; - if(monitor->cylinder_depth) + if(monitor->curvature_depth) { - cyl_radius = (monitor->cylinder_depth*monitor->cylinder_depth+0.25f)/(2.0f*monitor->cylinder_depth); + cyl_radius = (monitor->curvature_depth*monitor->curvature_depth+0.25f)/(2.0f*monitor->curvature_depth); cyl_arc = 2.0f*asin(0.5f/cyl_radius); } @@ -622,13 +645,41 @@ void update_monitor_vertices(CompositedScreen *screen, CompositedMonitor *monito v[0] = (float)x/t-0.5f; v[1] = ((float)y/t-0.5f)/aspect; v[2] = 0; - if(monitor->cylinder_depth) + if(monitor->curvature_depth) { - v[2] = (1.0f-cos(v[0]*cyl_arc))*cyl_radius-monitor->cylinder_depth; - v[0] = sin(v[0]*cyl_arc)*cyl_radius; + if(monitor->curvature_type==CYLINDRICAL) + { + v[2] = (1.0f-cos(v[0]*cyl_arc))*cyl_radius-monitor->curvature_depth; + v[0] = sin(v[0]*cyl_arc)*cyl_radius; + } + else if(monitor->curvature_type==SPHERICAL) + { + float r; + + v[0] = tan(v[0]*cyl_arc)*cyl_radius; + v[1] = tan(v[1]*cyl_arc)*cyl_radius; + r = sqrt(v[0]*v[0]+v[1]*v[1]+cyl_radius*cyl_radius)/fabs(cyl_radius); + v[0] /= r; + v[1] /= r; + v[2] = cyl_radius-cyl_radius/r-monitor->curvature_depth; + } } } + monitor->geometry_data[0] = t; + for(i=0; i<3; ++i) + monitor->geometry_data[1+i] = eye[i]*4096; + for(y=0; y<2; ++y) + for(x=0; x<2; ++x) + { + i = 1+(1+y*2+x)*3; + monitor->geometry_data[i] = ((x-0.5f)*distance/monitor->perspective)*4096; + monitor->geometry_data[i+1] = (eye[1]+look[1]*distance-(y-monitor->vertical_center)*look[2]*distance/monitor->perspective/aspect)*4096; + monitor->geometry_data[i+2] = (eye[2]+look[2]*distance+(y-monitor->vertical_center)*look[1]*distance/monitor->perspective/aspect)*4096; + } + for(i=0; i<(t+1)*(t+1)*3; ++i) + monitor->geometry_data[16+i] = vertex_data[i]*4096; + for(y=t; y<=t; --y) for(x=t; x<=t; --x) { @@ -693,6 +744,7 @@ int initialize_monitor(Compositor *compositor, CompositedScreen *screen, XRRScre if(!monitor->enabled) { XRRFreeOutputInfo(output); + monitor->geometry_data = NULL; return 1; } @@ -705,7 +757,8 @@ int initialize_monitor(Compositor *compositor, CompositedScreen *screen, XRRScre XRRFreeOutputInfo(output); monitor->keystone_vertical = 0.0f; - monitor->cylinder_depth = 0.0f; + monitor->curvature_type = CYLINDRICAL; + monitor->curvature_depth = 0.0f; monitor->vertical_center = 0.5f; monitor->perspective = 1.0f; @@ -714,6 +767,8 @@ int initialize_monitor(Compositor *compositor, CompositedScreen *screen, XRRScre monitor->index_buffer = buffers[1]; monitor->tessellation = 50; + monitor->geometry_data_size = (monitor->tessellation+1)*(monitor->tessellation+1)*3+16; + monitor->geometry_data = (short *)malloc(monitor->geometry_data_size*sizeof(short)); update_monitor_vertices(screen, monitor); stride = 4*sizeof(float); @@ -742,6 +797,24 @@ CompositedMonitor *find_monitor_by_name(CompositedScreen *screen, char *name) return NULL; } +CompositedMonitor *find_monitor_by_name_global(Compositor *compositor, char *name, CompositedScreen **screen) +{ + unsigned i, j; + + for(i=0; inscreens; ++i) + for(j=0; jscreens[i].nmonitors; ++j) + if(!strcmp(compositor->screens[i].monitors[j].name, name)) + { + if(screen) + *screen = &compositor->screens[i]; + return &compositor->screens[i].monitors[j]; + } + + if(screen) + *screen = NULL; + return NULL; +} + void update_geometry_correction(Compositor *compositor, CompositedScreen *screen) { Atom prop_type; @@ -770,7 +843,7 @@ void update_geometry_correction(Compositor *compositor, CompositedScreen *screen use_gl(compositor, screen); name_ptr = names; - for(i=0; i*4keystone_vertical = values[i*4]/10000.0f; - monitor->cylinder_depth = values[i*4+1]/10000.0f; - monitor->vertical_center = values[i*4+2]/10000.0f; - monitor->perspective = values[i*4+3]/10000.0f; + monitor->keystone_vertical = values[i*5]/4096.0f; + monitor->curvature_type = values[i*5+1]; + monitor->curvature_depth = values[i*5+2]/4096.0f; + monitor->vertical_center = values[i*5+3]/4096.0f; + monitor->perspective = values[i*5+4]/4096.0f; if(monitor->enabled) update_monitor_vertices(screen, monitor); @@ -796,6 +870,45 @@ void update_geometry_correction(Compositor *compositor, CompositedScreen *screen XFree(values); } +void update_root_pixmap(Compositor *compositor, CompositedScreen *screen) +{ + Atom prop_type; + int prop_format; + unsigned long overflow; + unsigned long length; + long *pixmap; + Window root; + int x, y; + unsigned width; + unsigned height; + unsigned border; + unsigned depth; + + use_gl(compositor, screen); + + if(screen->root_glx_pixmap) + { + glXDestroyPixmap(compositor->display, screen->root_glx_pixmap); + screen->root_glx_pixmap = None; + } + + XGetWindowProperty(compositor->display, screen->root, compositor->root_pmap_atom, 0, 1, False, XA_PIXMAP, + &prop_type, &prop_format, &length, &overflow, (unsigned char **)&pixmap); + if(prop_type!=XA_PIXMAP || prop_format!=32) + { + screen->root_pixmap = None; + return; + } + + screen->root_pixmap = pixmap[0]; + if(XGetGeometry(compositor->display, screen->root_pixmap, &root, &x, &y, &width, &height, &border, &depth)) + screen->root_glx_pixmap = pixmap_to_glx_pixmap(compositor, screen, screen->root_pixmap); + else + screen->root_pixmap = None; + + XFree(pixmap); +} + int initialize_screen(Compositor *compositor, unsigned number) { CompositedScreen *screen; @@ -841,7 +954,11 @@ int initialize_screen(Compositor *compositor, unsigned number) return 0; XRRFreeScreenResources(xrr_res); + screen->root_pixmap = None; + screen->root_glx_pixmap = None; + update_geometry_correction(compositor, screen); + update_root_pixmap(compositor, screen); XQueryTree(compositor->display, screen->root, &dummy_root, &dummy_parent, &children, &nchildren); @@ -912,8 +1029,10 @@ int initialize_compositor(Compositor *compositor) compositor->glXBindTexImageEXT = (PFNGLXBINDTEXIMAGEEXTPROC)glXGetProcAddress((unsigned char *)"glXBindTexImageEXT"); compositor->glXReleaseTexImageEXT = (PFNGLXRELEASETEXIMAGEEXTPROC)glXGetProcAddress((unsigned char *)"glXReleaseTexImageEXT"); - compositor->correction_atom = XInternAtom(compositor->display, "GEOMETRY_CORRECTION", False); - compositor->monitors_atom = XInternAtom(compositor->display, "GEOMETRY_CORRECTION_MONITORS", False); + compositor->root_pmap_atom = XInternAtom(compositor->display, "_XROOTPMAP_ID", False); + compositor->correction_atom = XInternAtom(compositor->display, "_MSP_GEOMETRY_CORRECTION", False); + compositor->monitors_atom = XInternAtom(compositor->display, "_MSP_GEOMETRY_CORRECTION_MONITORS", False); + compositor->geometry_data_atom = XInternAtom(compositor->display, "_MSP_GEOMETRY_CORRECTION_DATA", False); compositor->nscreens = ScreenCount(compositor->display); compositor->screens = (CompositedScreen *)malloc(compositor->nscreens*sizeof(CompositedScreen)); @@ -921,6 +1040,9 @@ int initialize_compositor(Compositor *compositor) if(!initialize_screen(compositor, i)) return 0; + compositor->selection_window = XCreateWindow(compositor->display, compositor->screens[0].root, 0, 0, 1, 1, 0, CopyFromParent, InputOutput, CopyFromParent, 0, NULL); + XSetSelectionOwner(compositor->display, compositor->geometry_data_atom, compositor->selection_window, CurrentTime); + compositor->dirty = 1; return 1; @@ -953,8 +1075,13 @@ void shutdown_screen(Compositor *compositor, CompositedScreen *screen) glDeleteBuffers(1, &screen->monitors[i].index_buffer); glDeleteVertexArrays(1, &screen->monitors[i].vertex_array); } + if(screen->monitors[i].geometry_data) + free(screen->monitors[i].geometry_data); } + glDeleteTextures(1, &screen->root_texture); + glXDestroyPixmap(compositor->display, screen->root_glx_pixmap); + glDeleteBuffers(1, &screen->window_vertex_buffer); glDeleteVertexArrays(1, &screen->window_vertex_array); glDeleteFramebuffers(1, &screen->framebuffer); @@ -964,7 +1091,7 @@ void shutdown_screen(Compositor *compositor, CompositedScreen *screen) for(i=0; i<3; ++i) glDeleteShader(screen->shaders[i]); - glXMakeContextCurrent(compositor->display, 0, 0, NULL); + glXMakeContextCurrent(compositor->display, None, None, NULL); glXDestroyContext(compositor->display, screen->glx_context); glXDestroyWindow(compositor->display, screen->glx_window); XDestroyWindow(compositor->display, screen->render_window); @@ -983,6 +1110,8 @@ void shutdown_compositor(Compositor *compositor) shutdown_screen(compositor, &compositor->screens[i]); free(compositor->screens); + XDestroyWindow(compositor->display, compositor->selection_window); + XCloseDisplay(compositor->display); } @@ -1105,14 +1234,46 @@ void process_property_event(Compositor *compositor, XPropertyEvent *event) { CompositedScreen *screen; - if(event->atom!=compositor->correction_atom) - return; - screen = find_screen_by_root(compositor, event->window); if(!screen) return; - update_geometry_correction(compositor, screen); + if(event->atom==compositor->correction_atom) + update_geometry_correction(compositor, screen); + else if(event->atom==compositor->root_pmap_atom) + update_root_pixmap(compositor, screen); +} + +void process_selection_request_event(Compositor *compositor, XSelectionRequestEvent *event) +{ + Atom prop_type; + int prop_format; + unsigned long overflow; + unsigned long names_length; + XSelectionEvent notify; + + if(event->selection==compositor->geometry_data_atom) + { + char *monitor_name; + CompositedMonitor *monitor; + + XGetWindowProperty(compositor->display, event->requestor, event->property, 0, 64, False, XA_STRING, + &prop_type, &prop_format, &names_length, &overflow, (unsigned char **)&monitor_name); + if(prop_type!=XA_STRING || prop_format!=8) + return; + + monitor = find_monitor_by_name_global(compositor, monitor_name, NULL); + if(monitor && monitor->enabled) + XChangeProperty(compositor->display, event->requestor, event->property, XA_INTEGER, 16, PropModeReplace, (unsigned char *)monitor->geometry_data, monitor->geometry_data_size); + + notify.type = SelectionNotify; + notify.requestor = event->requestor; + notify.selection = event->selection; + notify.target = event->target; + notify.property = (monitor ? event->property : None); + notify.time = event->time; + XSendEvent(compositor->display, event->requestor, False, 0, (XEvent *)¬ify); + } } void process_damage_event(Compositor *compositor, XDamageNotifyEvent *event) @@ -1179,6 +1340,9 @@ void process_events(Compositor *compositor) case PropertyNotify: process_property_event(compositor, &event.xproperty); break; + case SelectionRequest: + process_selection_request_event(compositor, &event.xselectionrequest); + break; default: if(event.type==compositor->damage_event+XDamageNotify) process_damage_event(compositor, (XDamageNotifyEvent *)&event); @@ -1195,15 +1359,32 @@ void refresh_screen(Compositor *compositor, CompositedScreen *screen) unsigned i; int use_mask; + for(i=0; inwindows; ++i) + if(screen->windows[i].map_state==IsViewable) + XDamageSubtract(compositor->display, screen->windows[i].damage, None, None); + glXWaitX(); + use_gl(compositor, screen); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, screen->framebuffer); - glClearColor(0.5f, 0.5f, 0.5f, 0.0f); - glClear(GL_COLOR_BUFFER_BIT); - use_mask = -1; glBindVertexArray(screen->window_vertex_array); + + if(screen->root_pixmap) + { + use_mask = 0; + glUseProgram(screen->program); + glBindTexture(GL_TEXTURE_2D, screen->root_texture); + compositor->glXBindTexImageEXT(compositor->display, screen->root_glx_pixmap, GLX_FRONT_LEFT_EXT, NULL); + glUniform4f(screen->geometry_loc, 0.0f, 0.0f, 1.0f, 1.0f); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + compositor->glXReleaseTexImageEXT(compositor->display, screen->root_glx_pixmap, GLX_FRONT_LEFT_EXT); + } + else + glClear(GL_COLOR_BUFFER_BIT); + for(i=0; inwindows; ++i) { CompositedWindow *window; @@ -1225,8 +1406,6 @@ void refresh_screen(Compositor *compositor, CompositedScreen *screen) glActiveTexture(GL_TEXTURE0); } - XDamageSubtract(compositor->display, window->damage, None, None); - if(window->recreate_pixmap) create_window_pixmap(compositor, screen, window); if(window->recreate_mask) @@ -1242,7 +1421,6 @@ void refresh_screen(Compositor *compositor, CompositedScreen *screen) } glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - glClearColor(0.5f, 0.0f, 0.5f, 0.0f); glClear(GL_COLOR_BUFFER_BIT); glBindTexture(GL_TEXTURE_2D, screen->fb_texture); glEnable(GL_PRIMITIVE_RESTART);