]> git.tdb.fi Git - geometrycompositor.git/blobdiff - source/main.c
Synchronize after subtracting damage from windows
[geometrycompositor.git] / source / main.c
index 970774d2eac52a7ff5350891f8442619287eb265..185c6b4b7bd609e35cfaaa8f28cd7e77fda2e87b 100644 (file)
@@ -25,9 +25,11 @@ typedef struct CompositedWindow
        Damage damage;
        Pixmap pixmap;
        GLXPixmap glx_pixmap;
+       int recreate_pixmap;
        unsigned texture;
        unsigned mask_texture;
        int use_mask;
+       int recreate_mask;
 } CompositedWindow;
 
 typedef struct CompositedMonitor
@@ -111,7 +113,7 @@ static const char *fshader_src =
        "out vec4 frag_color;\n"
        "void main()\n"
        "{\n"
-       "       frag_color = texture(image, texcoord);\n"
+       "  frag_color = texture(image, texcoord);\n"
        "}\n";
 
 static const char *masked_fshader_src =
@@ -269,13 +271,11 @@ unsigned create_2d_texture()
        return texture;
 }
 
-int create_gl_resources(Compositor *compositor, CompositedScreen *screen)
+int create_gl_resources(CompositedScreen *screen)
 {
        unsigned stride;
        int loc;
 
-       use_gl(compositor, screen);
-
        screen->shaders[0] = compile_shader(GL_VERTEX_SHADER, vshader_src);
        screen->shaders[1] = compile_shader(GL_FRAGMENT_SHADER, fshader_src);
        screen->shaders[2] = compile_shader(GL_FRAGMENT_SHADER, masked_fshader_src);
@@ -377,6 +377,7 @@ void create_window_pixmap(Compositor *compositor, CompositedScreen *screen, Comp
 
        window->pixmap = XCompositeNameWindowPixmap(compositor->display, window->window);
        window->glx_pixmap = glXCreatePixmap(compositor->display, screen->fbconfig, window->pixmap, attribs);
+       window->recreate_pixmap = 0;
 }
 
 void update_window_mask(Compositor *compositor, CompositedWindow *window)
@@ -446,6 +447,8 @@ void update_window_mask(Compositor *compositor, CompositedWindow *window)
        glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, data);
 
        free(data);
+
+       window->recreate_mask = 0;
 }
 
 CompositedWindow *add_window(Compositor *compositor, CompositedScreen *screen, Window w)
@@ -488,14 +491,11 @@ CompositedWindow *add_window(Compositor *compositor, CompositedScreen *screen, W
        window->glx_pixmap = None;
 
        XCompositeRedirectWindow(compositor->display, window->window, CompositeRedirectManual);
-       if(window->map_state==IsViewable)
-               create_window_pixmap(compositor, screen, window);
+       window->recreate_pixmap = (window->map_state==IsViewable);
 
        window->texture = create_2d_texture();
        window->mask_texture = create_2d_texture();
-
-       if(window->map_state==IsViewable)
-               update_window_mask(compositor, window);
+       window->recreate_mask = (window->map_state==IsViewable);
 
        XShapeSelectInput(compositor->display, window->window, ShapeNotifyMask);
 
@@ -828,7 +828,9 @@ int initialize_screen(Compositor *compositor, unsigned number)
        if(!initialize_gl(compositor, screen))
                return 0;
 
-       if(!create_gl_resources(compositor, screen))
+       use_gl(compositor, screen);
+
+       if(!create_gl_resources(screen))
                return 0;
 
        xrr_res = XRRGetScreenResources(compositor->display, screen->root);
@@ -1005,7 +1007,10 @@ void process_destroy_window_event(Compositor *compositor, XDestroyWindowEvent *e
 
        if((screen = find_screen_by_root(compositor, event->event)))
                if((window = find_window(screen, event->window)))
+               {
+                       use_gl(compositor, screen);
                        remove_window(compositor, screen, window, 1);
+               }
 }
 
 void process_map_event(Compositor *compositor, XMapEvent *event)
@@ -1022,8 +1027,8 @@ void process_map_event(Compositor *compositor, XMapEvent *event)
                return;
 
        window->map_state = IsViewable;
-       create_window_pixmap(compositor, screen, window);
-       update_window_mask(compositor, window);
+       window->recreate_pixmap = 1;
+       window->recreate_mask = 1;
 
        mark_dirty(compositor, screen);
 }
@@ -1088,8 +1093,7 @@ void process_configure_event(Compositor *compositor, XConfigureEvent *event)
                window->width = event->width;
                window->height = event->height;
                window->border = event->border_width;
-               create_window_pixmap(compositor, screen, window);
-               update_window_mask(compositor, window);
+               window->recreate_pixmap = 1;
        }
        reorder_window(screen, window, event->above);
 
@@ -1132,55 +1136,58 @@ void process_shape_event(Compositor *compositor, XShapeEvent *event)
        window = find_window_global(compositor, event->window, &screen);
        if(window && window->map_state==IsViewable)
        {
-               update_window_mask(compositor, window);
+               window->recreate_mask = 1;
                mark_dirty(compositor, screen);
        }
 }
 
-int process_event(Compositor *compositor)
+void process_events(Compositor *compositor)
 {
+       int pending;
        XEvent event;
-       if(compositor->dirty)
+
+       pending = 0;
+       while((pending || !compositor->dirty) && !terminate_requested)
        {
-               if(!XCheckMaskEvent(compositor->display, -1, &event))
-                       return 0;
-       }
-       else
+               if(!pending)
+                       pending = XPending(compositor->display);
+
                XNextEvent(compositor->display, &event);
+               if(pending)
+                       --pending;
 
-       switch(event.type)
-       {
-       case CreateNotify:
-               process_create_window_event(compositor, &event.xcreatewindow);
-               break;
-       case DestroyNotify:
-               process_destroy_window_event(compositor, &event.xdestroywindow);
-               break;
-       case MapNotify:
-               process_map_event(compositor, &event.xmap);
-               break;
-       case UnmapNotify:
-               process_unmap_event(compositor, &event.xunmap);
-               break;
-       case ReparentNotify:
-               process_reparent_event(compositor, &event.xreparent);
-               break;
-       case ConfigureNotify:
-               process_configure_event(compositor, &event.xconfigure);
-               break;
-       case PropertyNotify:
-               process_property_event(compositor, &event.xproperty);
-               break;
-       default:
-               if(event.type==compositor->damage_event+XDamageNotify)
-                       process_damage_event(compositor, (XDamageNotifyEvent *)&event);
-               else if(event.type==compositor->shape_event+ShapeNotify)
-                       process_shape_event(compositor, (XShapeEvent *)&event);
-               else
-                       printf("Event %d\n", event.type);
+               switch(event.type)
+               {
+               case CreateNotify:
+                       process_create_window_event(compositor, &event.xcreatewindow);
+                       break;
+               case DestroyNotify:
+                       process_destroy_window_event(compositor, &event.xdestroywindow);
+                       break;
+               case MapNotify:
+                       process_map_event(compositor, &event.xmap);
+                       break;
+               case UnmapNotify:
+                       process_unmap_event(compositor, &event.xunmap);
+                       break;
+               case ReparentNotify:
+                       process_reparent_event(compositor, &event.xreparent);
+                       break;
+               case ConfigureNotify:
+                       process_configure_event(compositor, &event.xconfigure);
+                       break;
+               case PropertyNotify:
+                       process_property_event(compositor, &event.xproperty);
+                       break;
+               default:
+                       if(event.type==compositor->damage_event+XDamageNotify)
+                               process_damage_event(compositor, (XDamageNotifyEvent *)&event);
+                       else if(event.type==compositor->shape_event+ShapeNotify)
+                               process_shape_event(compositor, (XShapeEvent *)&event);
+                       else
+                               printf("Event %d\n", event.type);
+               }
        }
-
-       return 1;
 }
 
 void refresh_screen(Compositor *compositor, CompositedScreen *screen)
@@ -1188,6 +1195,11 @@ void refresh_screen(Compositor *compositor, CompositedScreen *screen)
        unsigned i;
        int use_mask;
 
+       for(i=0; i<screen->nwindows; ++i)
+               if(screen->windows[i].map_state==IsViewable)
+                       XDamageSubtract(compositor->display, screen->windows[i].damage, None, None);
+       glXWaitX();
+
        use_gl(compositor, screen);
 
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, screen->framebuffer);
@@ -1199,7 +1211,9 @@ void refresh_screen(Compositor *compositor, CompositedScreen *screen)
        glBindVertexArray(screen->window_vertex_array);
        for(i=0; i<screen->nwindows; ++i)
        {
-               CompositedWindow *window = &screen->windows[i];
+               CompositedWindow *window;
+
+               window = &screen->windows[i];
                if(window->map_state!=IsViewable)
                        continue;
 
@@ -1216,7 +1230,10 @@ 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)
+                       update_window_mask(compositor, window);
 
                glBindTexture(GL_TEXTURE_2D, window->texture);
                compositor->glXBindTexImageEXT(compositor->display, window->glx_pixmap, GLX_FRONT_LEFT_EXT, NULL);
@@ -1289,7 +1306,8 @@ int main()
 
        while(!terminate_requested)
        {
-               if(!process_event(&compositor))
+               process_events(&compositor);
+               if(compositor.dirty && !terminate_requested)
                        refresh_all_screens(&compositor);
        }