]> git.tdb.fi Git - geometrycompositor.git/blobdiff - source/main.c
Check that the root pixmap exists before using it
[geometrycompositor.git] / source / main.c
index 30833db0cf7854cc1749a2c789e71a8a71506020..23c061b86fc3a5557dfba3b2266499f29b36ef1c 100644 (file)
@@ -71,6 +71,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,6 +92,7 @@ typedef struct Compositor
        PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB;
        PFNGLXBINDTEXIMAGEEXTPROC glXBindTexImageEXT;
        PFNGLXRELEASETEXIMAGEEXTPROC glXReleaseTexImageEXT;
+       Atom root_pmap_atom;
        Atom correction_atom;
        Atom monitors_atom;
        int dirty;
@@ -271,13 +275,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);
@@ -327,6 +329,8 @@ int create_gl_resources(Compositor *compositor, CompositedScreen *screen)
        glDepthMask(GL_FALSE);
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
 
+       screen->root_texture = create_2d_texture();
+
        return 1;
 }
 
@@ -359,17 +363,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;
@@ -377,8 +375,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;
 }
 
@@ -497,6 +506,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);
@@ -798,6 +808,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 = 0;
+       }
+
+       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 = 0;
+               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;
@@ -830,7 +879,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);
@@ -841,7 +892,11 @@ int initialize_screen(Compositor *compositor, unsigned number)
                        return 0;
        XRRFreeScreenResources(xrr_res);
 
+       screen->root_pixmap = 0;
+       screen->root_glx_pixmap = 0;
+
        update_geometry_correction(compositor, screen);
+       update_root_pixmap(compositor, screen);
 
        XQueryTree(compositor->display, screen->root, &dummy_root, &dummy_parent, &children, &nchildren);
 
@@ -912,6 +967,7 @@ int initialize_compositor(Compositor *compositor)
        compositor->glXBindTexImageEXT = (PFNGLXBINDTEXIMAGEEXTPROC)glXGetProcAddress((unsigned char *)"glXBindTexImageEXT");
        compositor->glXReleaseTexImageEXT = (PFNGLXRELEASETEXIMAGEEXTPROC)glXGetProcAddress((unsigned char *)"glXReleaseTexImageEXT");
 
+       compositor->root_pmap_atom = XInternAtom(compositor->display, "_XROOTPMAP_ID", False);
        compositor->correction_atom = XInternAtom(compositor->display, "GEOMETRY_CORRECTION", False);
        compositor->monitors_atom = XInternAtom(compositor->display, "GEOMETRY_CORRECTION_MONITORS", False);
 
@@ -955,6 +1011,9 @@ void shutdown_screen(Compositor *compositor, CompositedScreen *screen)
                }
        }
 
+       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);
@@ -1007,7 +1066,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)
@@ -1102,14 +1164,14 @@ 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_damage_event(Compositor *compositor, XDamageNotifyEvent *event)
@@ -1192,15 +1254,32 @@ 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);
 
+       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; i<screen->nwindows; ++i)
        {
                CompositedWindow *window;
@@ -1222,8 +1301,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)
@@ -1239,7 +1316,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);