diff options
Diffstat (limited to 'src/compositor.c')
-rw-r--r-- | src/compositor.c | 1590 |
1 files changed, 964 insertions, 626 deletions
diff --git a/src/compositor.c b/src/compositor.c index d82fadbf..c1b96863 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -26,64 +26,32 @@ #include "errors.h" #include "window.h" #include "frame.h" +#include "matrix.h" +#include <math.h> +#include "cwindow.h" +#include "snow.h" +#include <GL/gl.h> +#include <GL/glu.h> +#include <GL/glx.h> +#include <X11/extensions/shape.h> #ifdef HAVE_COMPOSITE_EXTENSIONS #include <X11/extensions/Xcomposite.h> #include <X11/extensions/Xdamage.h> #include <X11/extensions/Xrender.h> - -#if COMPOSITE_MAJOR > 0 || COMPOSITE_MINOR >= 2 -#define HAVE_NAME_WINDOW_PIXMAP 1 -#endif +#include "lmcbits.h" +#include "lmctexture.h" #endif /* HAVE_COMPOSITE_EXTENSIONS */ -#define SHADOW_OFFSET 3 #define FRAME_INTERVAL_MILLISECONDS ((int)(1000.0/40.0)) -/* Unlike MetaWindow, there's one of these for _all_ toplevel windows, - * override redirect or not. We also track unmapped windows as - * otherwise on window map we'd have to determine where the - * newly-mapped window was in the stack. A MetaCompositorWindow may - * correspond to a metacity window frame rather than an application - * window. - */ -typedef struct -{ - Window xwindow; - -#ifdef HAVE_COMPOSITE_EXTENSIONS - MetaCompositor *compositor; - - int x; - int y; - int width; - int height; - int border_width; - - Damage damage; - XserverRegion last_painted_extents; - - Picture picture; - XserverRegion border_size; - -#if HAVE_NAME_WINDOW_PIXMAP - Pixmap pixmap; -#endif - - unsigned int managed : 1; - unsigned int damaged : 1; - unsigned int viewable : 1; - - unsigned int screen_index : 8; - -#endif -} MetaCompositorWindow; - struct MetaCompositor { MetaDisplay *display; - + + World *world; + int composite_error_base; int composite_event_base; int damage_error_base; @@ -92,62 +60,119 @@ struct MetaCompositor int fixes_event_base; GHashTable *window_hash; - + guint repair_idle; - guint repair_timeout; guint enabled : 1; guint have_composite : 1; guint have_damage : 1; guint have_fixes : 1; -#ifdef HAVE_NAME_WINDOW_PIXMAP guint have_name_window_pixmap : 1; -#endif + guint debug_updates : 1; + + GList *ignored_damage; + + Window gl_window; }; #ifdef HAVE_COMPOSITE_EXTENSIONS static void -meta_compositor_window_free (MetaCompositorWindow *cwindow) +free_window_hash_value (void *v) { - g_assert (cwindow->damage != None); - - meta_error_trap_push (cwindow->compositor->display); - /* This seems to cause an error if the window - * is destroyed? - */ - XDamageDestroy (cwindow->compositor->display->xdisplay, - cwindow->damage); - -#if HAVE_NAME_WINDOW_PIXMAP - /* Free our window pixmap name */ - if (cwindow->pixmap != None) - XFreePixmap (cwindow->compositor->display->xdisplay, - cwindow->pixmap); -#endif - meta_error_trap_pop (cwindow->compositor->display, FALSE); - - g_free (cwindow); + CWindow *cwindow = v; + + g_print ("freeing cwindow %lx\n", cwindow_get_xwindow (cwindow)); + cwindow_free (cwindow); } #endif /* HAVE_COMPOSITE_EXTENSIONS */ -#ifdef HAVE_COMPOSITE_EXTENSIONS static void -free_window_hash_value (void *v) +print_region (Display *dpy, const char *name, XserverRegion region) { - MetaCompositorWindow *cwindow = v; + XRectangle *rects; + int i, n_rects; + + rects = XFixesFetchRegion (dpy, region, &n_rects); + + g_print ("region \"%s\":\n", name); + for (i = 0; i < n_rects; ++i) + g_print (" %d %d %d %d\n", rects[i].x, rects[i].y, rects[i].width, rects[i].height); + XFree (rects); +} - meta_compositor_window_free (cwindow); +static gboolean +update_world (gpointer data) +{ + static double time; + + MetaCompositor *compositor = data; + World *world = compositor->world; + MetaScreen *screen = world_get_screen (world); + XserverRegion region; + + region = world_invalidate (world); + screen = world_get_screen (world); + + meta_compositor_invalidate_region (compositor, screen, region); + XFixesDestroyRegion (compositor->display->xdisplay, region); + + world_set_time (world, time); /* FIXME */ + + region = world_invalidate (world); + meta_compositor_invalidate_region (compositor, screen, region); + XFixesDestroyRegion (compositor->display->xdisplay, region); + + time += 0.001; + + return TRUE; +} + +static XVisualInfo * +init_gl (Display *xdisplay, + int screen, + GLXContext *ctx) +{ + int attrib[] = { GLX_RGBA, + GLX_RED_SIZE, 1, + GLX_GREEN_SIZE, 1, + GLX_BLUE_SIZE, 1, + GLX_STENCIL_SIZE, 1, + GLX_DOUBLEBUFFER, + GLX_DEPTH_SIZE, 1, + None }; + XVisualInfo *visinfo; + GLXContext context; + + visinfo = glXChooseVisual( xdisplay, screen, attrib ); + if (!visinfo) + { + g_printerr ("Error: couldn't get an RGB, Double-buffered visual.\n"); + return NULL; + } + + context = glXCreateContext( xdisplay, visinfo, NULL, True ); + + if (!context) + { + g_printerr ("glXCreateContext failed.\n"); + return NULL; + } + + *ctx = context; + + g_print ("visual depth: %d\n", visinfo->depth); + + return visinfo; } -#endif /* HAVE_COMPOSITE_EXTENSIONS */ MetaCompositor* meta_compositor_new (MetaDisplay *display) { #ifdef HAVE_COMPOSITE_EXTENSIONS MetaCompositor *compositor; - + compositor = g_new0 (MetaCompositor, 1); - + compositor->display = display; if (!XCompositeQueryExtension (display->xdisplay, @@ -162,22 +187,16 @@ meta_compositor_new (MetaDisplay *display) int composite_major, composite_minor; compositor->have_composite = TRUE; - -#if HAVE_NAME_WINDOW_PIXMAP + XCompositeQueryVersion (display->xdisplay, &composite_major, &composite_minor); - -#if 0 - if (composite_major > 0 || composite_minor >= 2) - compositor->have_name_window_pixmap = TRUE; -#endif -#endif + } - + meta_topic (META_DEBUG_COMPOSITOR, "Composite extension event base %d error base %d\n", compositor->composite_event_base, compositor->composite_error_base); - + if (!XDamageQueryExtension (display->xdisplay, &compositor->damage_event_base, &compositor->damage_error_base)) @@ -187,7 +206,7 @@ meta_compositor_new (MetaDisplay *display) } else compositor->have_damage = TRUE; - + meta_topic (META_DEBUG_COMPOSITOR, "Damage extension event base %d error base %d\n", compositor->damage_event_base, compositor->damage_error_base); @@ -201,7 +220,7 @@ meta_compositor_new (MetaDisplay *display) } else compositor->have_fixes = TRUE; - + meta_topic (META_DEBUG_COMPOSITOR, "Fixes extension event base %d error base %d\n", compositor->fixes_event_base, compositor->fixes_error_base); @@ -212,6 +231,15 @@ meta_compositor_new (MetaDisplay *display) META_DISPLAY_HAS_RENDER (compositor->display))) { meta_topic (META_DEBUG_COMPOSITOR, "Failed to find all extensions needed for compositing manager, disabling compositing manager\n"); + + if (!compositor->have_composite) + g_print ("no composite\n"); + if (!compositor->have_fixes) + g_print ("no fixes\n"); + if (!compositor->have_damage) + g_print ("have damage\n"); + + g_assert (!compositor->enabled); return compositor; } @@ -229,24 +257,24 @@ meta_compositor_new (MetaDisplay *display) #endif /* HAVE_COMPOSITE_EXTENSIONS */ } +void +meta_compositor_set_debug_updates (MetaCompositor *compositor, + gboolean debug_updates) +{ + compositor->debug_updates = !!debug_updates; +} + #ifdef HAVE_COMPOSITE_EXTENSIONS static void remove_repair_idle (MetaCompositor *compositor) { - if (compositor->repair_idle || compositor->repair_timeout) - meta_topic (META_DEBUG_COMPOSITOR, "Damage idle removed\n"); - - if (compositor->repair_idle != 0) + if (compositor->repair_idle) { + meta_topic (META_DEBUG_COMPOSITOR, "Damage idle removed\n"); + g_source_remove (compositor->repair_idle); compositor->repair_idle = 0; } - - if (compositor->repair_timeout != 0) - { - g_source_remove (compositor->repair_timeout); - compositor->repair_timeout = 0; - } } #endif /* HAVE_COMPOSITE_EXTENSIONS */ @@ -258,7 +286,7 @@ meta_compositor_unref (MetaCompositor *compositor) * there's no ref() */ remove_repair_idle (compositor); - + if (compositor->window_hash) g_hash_table_destroy (compositor->window_hash); @@ -266,70 +294,121 @@ meta_compositor_unref (MetaCompositor *compositor) #endif /* HAVE_COMPOSITE_EXTENSIONS */ } -#ifdef HAVE_COMPOSITE_EXTENSIONS -static XserverRegion -window_extents (MetaCompositorWindow *cwindow) -{ - XRectangle r; - - r.x = cwindow->x; - r.y = cwindow->y; - r.width = cwindow->width; - r.height = cwindow->height; - - r.width += SHADOW_OFFSET; - r.height += SHADOW_OFFSET; - - return XFixesCreateRegion (cwindow->compositor->display->xdisplay, &r, 1); -} -#endif /* HAVE_COMPOSITE_EXTENSIONS */ +double tmp; +static double last; +static GTimer *timer ; #ifdef HAVE_COMPOSITE_EXTENSIONS static void -window_get_paint_bounds (MetaCompositorWindow *cwindow, - int *x, - int *y, - int *w, - int *h) +draw_windows (MetaCompositor *compositor, + MetaScreen *screen, + GList *list, + XserverRegion damaged_region, + Picture picture) { -#ifdef HAVE_NAME_WINDOW_PIXMAP - if (cwindow->pixmap != None) + CWindow *cwindow; + XserverRegion region_below; + Display *dpy = compositor->display->xdisplay; + + if (!list) + return; + + cwindow = list->data; + + region_below = XFixesCreateRegion (dpy, NULL, 0); + XFixesCopyRegion (dpy, region_below, damaged_region); + + if (!cwindow_is_translucent (cwindow) && + !cwindow_get_input_only (cwindow) && cwindow_get_viewable (cwindow)) { - *x = cwindow->x; - *y = cwindow->y; - *w = cwindow->width + cwindow->border_width * 2; - *h = cwindow->height + cwindow->border_width * 2; + XserverRegion opaque = cwindow_get_opaque_region (cwindow); + + XFixesSubtractRegion (dpy, region_below, region_below, opaque); + + XFixesDestroyRegion (dpy, opaque); } - else + + draw_windows (compositor, screen, list->next, region_below, picture); + + XFixesDestroyRegion (dpy, region_below); + + if (cwindow_get_viewable (cwindow) && cwindow_get_xwindow (cwindow) != compositor->gl_window) + { + cwindow_draw (cwindow, picture, damaged_region); +#if 0 + g_print ("drawing a window: %f\n", (tmp = g_timer_elapsed (timer, NULL)) - last); + last = tmp; #endif - { - *x = cwindow->x + cwindow->border_width; - *y = cwindow->y + cwindow->border_width; - *w = cwindow->width; - *h = cwindow->height; - } + } } -static void -paint_screen (MetaCompositor *compositor, - MetaScreen *screen, - XserverRegion damage_region) +static Picture +create_root_buffer (MetaScreen *screen, Pixmap *pixmap) { - XserverRegion region; - Picture buffer_picture; + Display *display = screen->display->xdisplay; Pixmap buffer_pixmap; - Display *xdisplay; + XGCValues value; XRenderPictFormat *format; - GList *tmp; - GC gc; - - meta_topic (META_DEBUG_COMPOSITOR, "Repainting screen %d root 0x%lx\n", - screen->number, screen->xroot); + Picture buffer_picture; + + buffer_pixmap = XCreatePixmap (display, screen->xroot, + screen->width, + screen->height, + DefaultDepth (display, + screen->number)); + + value.function = GXcopy; + value.subwindow_mode = IncludeInferiors; + + format = XRenderFindVisualFormat (display, + DefaultVisual (display, + screen->number)); + + buffer_picture = XRenderCreatePicture (display, + buffer_pixmap, + format, + 0, 0); + + if (pixmap) + *pixmap = buffer_pixmap; + else + XFreePixmap (display, buffer_pixmap); + + return buffer_picture; +} - /* meta_display_grab (screen->display); */ +static void +paint_buffer (MetaScreen *screen, + Pixmap pixmap, + XserverRegion damage_region) +{ + XGCValues value; + GC gc; + value.function = GXcopy; + value.subwindow_mode = IncludeInferiors; - xdisplay = screen->display->xdisplay; + gc = XCreateGC (screen->display->xdisplay, pixmap, GCFunction | GCSubwindowMode, &value); + if (damage_region) + XFixesSetGCClipRegion (screen->display->xdisplay, gc, 0, 0, damage_region); + + XCopyArea (screen->display->xdisplay, + pixmap, screen->xroot, gc, + 0, 0, screen->width, screen->height, 0, 0); + + XFreeGC (screen->display->xdisplay, gc); +} + +static void +ensure_repair_idle (MetaCompositor *compositor); +static XserverRegion +do_paint_screen (MetaCompositor *compositor, + MetaScreen *screen, + Picture picture, + XserverRegion damage_region) +{ + Display *xdisplay = compositor->display->xdisplay; + XserverRegion region; if (damage_region == None) { XRectangle r; @@ -346,142 +425,224 @@ paint_screen (MetaCompositor *compositor, region = XFixesCreateRegion (xdisplay, NULL, 0); XFixesCopyRegion (compositor->display->xdisplay, - region, - damage_region); + region, + damage_region); } - buffer_pixmap = XCreatePixmap (xdisplay, screen->xroot, - screen->width, - screen->height, - DefaultDepth (xdisplay, - screen->number)); - - gc = XCreateGC (xdisplay, buffer_pixmap, 0, NULL); - XSetForeground (xdisplay, gc, WhitePixel (xdisplay, screen->number)); - XFixesSetGCClipRegion (xdisplay, gc, 0, 0, region); - XFillRectangle (xdisplay, buffer_pixmap, gc, 0, 0, - screen->width, screen->height); +#if 0 + { + XGCValues values; + values.subwindow_mode = IncludeInferiors; + values.foreground = 0x00ff00ff; /* shocking pink */ + GC gc = XCreateGC (screen->display->xdisplay, + screen->xroot, + GCSubwindowMode | GCForeground, &values); + + XFixesSetGCClipRegion (screen->display->xdisplay, gc, + 0, 0, region); + + XFillRectangle (screen->display->xdisplay, screen->xroot, gc, + 0, 0, screen->width, screen->height); + XSync (screen->display->xdisplay, False); + } +#endif - format = XRenderFindVisualFormat (xdisplay, - DefaultVisual (xdisplay, - screen->number)); - buffer_picture = XRenderCreatePicture (xdisplay, - buffer_pixmap, - format, - 0, 0); + if (USE_RENDER) + { + meta_error_trap_push (compositor->display); + XFixesSetPictureClipRegion (xdisplay, + picture, 0, 0, + region); + } + else + { + GList *list; - /* set clip */ - XFixesSetPictureClipRegion (xdisplay, - buffer_picture, 0, 0, - region); + glShadeModel (GL_FLAT); + glDisable (GL_TEXTURE_2D); + glDisable (GL_BLEND); - /* draw windows from bottom to top */ - - meta_error_trap_push (compositor->display); - tmp = g_list_last (screen->compositor_windows); - while (tmp != NULL) - { - MetaCompositorWindow *cwindow = tmp->data; - XRenderColor shadow_color; - MetaWindow *window; + glViewport (0, 0, screen->width, screen->height); - shadow_color.red = 0; - shadow_color.green = 0; - shadow_color.blue = 0; - shadow_color.alpha = 0x90c0; +#if 0 + glClearColor (0.0, 0.5, 0.5, 0.0); + glClear (GL_COLOR_BUFFER_BIT); + + glLoadIdentity (); + + glColor4f (0.8, 0.3, 0.8, 0.8); + + glBegin (GL_TRIANGLES); + + glVertex2f (0.0, 0.0); + glVertex2f (10, 100); + glVertex2f (20, 0.0); + + glEnd (); + + glColor4f (0.2, 0.2, 1.0, 0.5); + + glBegin (GL_TRIANGLES); + + glVertex2f (-1.0, 0.0); + glVertex2f (120, 100); + glVertex2f (200, 23.0); + + glEnd(); +#endif - if (cwindow->picture == None) /* InputOnly */ - goto next; +#if 0 + glColor4f (g_random_double (), + g_random_double (), + g_random_double (), + 1.0); +#endif - if (!cwindow->viewable) - goto next; /* not viewable */ +#if 0 + glBegin (GL_QUADS); + + glVertex2f (-1.0, -1.0); + glVertex2f (1.0, -1.0); + glVertex2f (1.0, 1.0); + glVertex2f (-1.0, 1.0); - if (cwindow->last_painted_extents) - XFixesDestroyRegion (xdisplay, - cwindow->last_painted_extents); + glEnd (); +#endif - cwindow->last_painted_extents = window_extents (cwindow); + glLoadIdentity(); - /* XFixesSubtractRegion (dpy, region, region, 0, 0, w->borderSize, 0, 0); */ + gluOrtho2D (0, screen->width, screen->height, 0); + glDisable (GL_SCISSOR_TEST); + } + + if (!timer) + timer = g_timer_new (); - meta_topic (META_DEBUG_COMPOSITOR, " Compositing window 0x%lx %d,%d %dx%d\n", - cwindow->xwindow, - cwindow->x, cwindow->y, - cwindow->width, cwindow->height); +#if 0 + g_print ("outside: %f\n", (tmp = g_timer_elapsed (timer, NULL)) - last); + last = tmp; +#endif - window = meta_display_lookup_x_window (compositor->display, - cwindow->xwindow); - if (window != NULL && - window == compositor->display->grab_window && - (meta_grab_op_is_resizing (compositor->display->grab_op) || - meta_grab_op_is_moving (compositor->display->grab_op))) - { - /* Draw window transparent while resizing */ - int x, y, w, h; - - window_get_paint_bounds (cwindow, &x, &y, &w, &h); - - XRenderComposite (xdisplay, - PictOpOver, /* PictOpOver for alpha, PictOpSrc without */ - cwindow->picture, - screen->trans_picture, - buffer_picture, - 0, 0, 0, 0, - x, y, w, h); - } - else - { - /* Draw window normally */ - int x, y, w, h; - - window_get_paint_bounds (cwindow, &x, &y, &w, &h); - - /* superlame drop shadow */ - XRenderFillRectangle (xdisplay, PictOpOver, - buffer_picture, - &shadow_color, - cwindow->x + SHADOW_OFFSET, - cwindow->y + SHADOW_OFFSET, - cwindow->width, cwindow->height); - - XRenderComposite (xdisplay, - PictOpSrc, /* PictOpOver for alpha, PictOpSrc without */ - cwindow->picture, - None, - buffer_picture, - 0, 0, 0, 0, - x, y, w, h); - } + draw_windows (compositor, screen, screen->compositor_windows, region, picture); + if (USE_RENDER) + { + meta_error_trap_pop (compositor->display, FALSE); + } + else + { + glShadeModel (GL_FLAT); + glDisable (GL_TEXTURE_2D); + glDisable (GL_BLEND); + + /* FIXME: we should probably grab the server around the raise/swap */ + XRaiseWindow (compositor->display->xdisplay, compositor->gl_window); - next: - tmp = tmp->prev; - } - meta_error_trap_pop (compositor->display, FALSE); +#if 0 + g_print ("painting window: %f\n", (tmp = g_timer_elapsed (timer, NULL)) - last); + last = tmp; +#endif + + glXSwapBuffers (screen->display->xdisplay, compositor->gl_window); - /* Copy buffer to root window */ - meta_topic (META_DEBUG_COMPOSITOR, "Copying buffer to root window 0x%lx picture 0x%lx\n", - screen->xroot, screen->root_picture); +#if 0 + g_print ("in swap: %f\n", (tmp = g_timer_elapsed (timer, NULL)) - last); +#endif + last = tmp; + +#if 0 + glFinish(); +#endif -#if 1 - XFixesSetPictureClipRegion (xdisplay, - screen->root_picture, - 0, 0, region); +#if 0 + g_print ("inside: %f\n", (tmp = g_timer_elapsed (timer, NULL)) - last); + last = tmp; +#endif + +#if 0 + XGCValues values; + values.subwindow_mode = IncludeInferiors; + Window root = RootWindow (screen->display->xdisplay, 0); + GC gc = XCreateGC (screen->display->xdisplay, root, GCSubwindowMode, &values); + + XCopyArea (screen->display->xdisplay, + compositor->gl_window, root, gc, + 0, 0, 1600, 1200, 0, 0); #endif + } - /* XFixesSetPictureClipRegion (xdisplay, buffer_picture, 0, 0, None); */ - XRenderComposite (xdisplay, PictOpSrc, buffer_picture, None, - screen->root_picture, - 0, 0, 0, 0, 0, 0, - screen->width, screen->height); - XFixesDestroyRegion (xdisplay, region); - XFreePixmap (xdisplay, buffer_pixmap); - XRenderFreePicture (xdisplay, buffer_picture); - XFreeGC (xdisplay, gc); - - /* meta_display_ungrab (screen->display); */ + return region; +} +static void +paint_screen (MetaCompositor *compositor, + MetaScreen *screen, + XserverRegion damage_region) +{ + Picture buffer_picture; + Display *xdisplay; + XserverRegion region; + Pixmap pixmap; + + meta_topic (META_DEBUG_COMPOSITOR, "Repainting screen %d root 0x%lx\n", + screen->number, screen->xroot); + + /* meta_display_grab (screen->display); */ + + xdisplay = screen->display->xdisplay; + + if (USE_RENDER) + buffer_picture = create_root_buffer (screen, &pixmap); + else + buffer_picture = None; + + /* set clip */ + region = do_paint_screen (compositor, screen, buffer_picture, damage_region); + + /* Copy buffer to root window */ + meta_topic (META_DEBUG_COMPOSITOR, "Copying buffer to root window 0x%lx picture 0x%lx\n", + screen->xroot, screen->root_picture); + + if (USE_RENDER) + { + + XFixesSetPictureClipRegion (xdisplay, + screen->root_picture, + 0, 0, region); + + XFixesSetPictureClipRegion (xdisplay, buffer_picture, 0, 0, None); + + if (compositor->debug_updates) + { +#define ALPHA 0.5 + XRenderColor hilight = { ALPHA * 0xFFFF, ALPHA * 0xFFFF, ALPHA * 0x0000, ALPHA * 0xFFFF }; + XRenderFillRectangle (screen->display->xdisplay, PictOpOver, + screen->root_picture, &hilight, + 0, 0, screen->width, screen->height); + XSync (xdisplay, False); + g_usleep (20000); + } + +#if 0 + world_paint (compositor->world, buffer_picture); +#endif + + paint_buffer (screen, pixmap, damage_region); + + XFreePixmap (screen->display->xdisplay, pixmap); + } + + XFixesDestroyRegion (xdisplay, region); + + if (USE_RENDER) + { + /* XFixesSetPictureClipRegion (xdisplay, buffer_picture, 0, 0, None); */ + XRenderFreePicture (xdisplay, buffer_picture); + + /* meta_display_ungrab (screen->display); */ + } + XSync (screen->display->xdisplay, False); } #endif /* HAVE_COMPOSITE_EXTENSIONS */ @@ -496,9 +657,14 @@ do_repair (MetaCompositor *compositor) while (tmp != NULL) { MetaScreen *s = tmp->data; - + if (s->damage_region != None) { +#if 0 + print_region (compositor->display->xdisplay, + "damage region", + s->damage_region); +#endif paint_screen (compositor, s, s->damage_region); XFixesDestroyRegion (s->display->xdisplay, @@ -508,17 +674,15 @@ do_repair (MetaCompositor *compositor) tmp = tmp->next; } - + remove_repair_idle (compositor); } #endif /* HAVE_COMPOSITE_EXTENSIONS */ #ifdef HAVE_COMPOSITE_EXTENSIONS -static gboolean -repair_idle_func (void *data) +gboolean +meta_compositor_repair_now (MetaCompositor *compositor) { - MetaCompositor *compositor = data; - compositor->repair_idle = 0; do_repair (compositor); @@ -528,101 +692,66 @@ repair_idle_func (void *data) #ifdef HAVE_COMPOSITE_EXTENSIONS -static gboolean -repair_timeout_func (void *data) -{ - MetaCompositor *compositor = data; - - compositor->repair_timeout = 0; - do_repair (compositor); - - return FALSE; -} -#endif /* HAVE_COMPOSITE_EXTENSIONS */ - -#ifdef HAVE_COMPOSITE_EXTENSIONS -static MetaScreen* -meta_compositor_window_get_screen (MetaCompositorWindow *cwindow) -{ - MetaScreen *screen; - GSList *tmp; - - screen = NULL; - tmp = cwindow->compositor->display->screens; - while (tmp != NULL) - { - MetaScreen *s = tmp->data; - - if (s->number == cwindow->screen_index) - { - screen = s; - break; - } - - tmp = tmp->next; - } - g_assert (screen != NULL); - - return screen; -} -#endif /* HAVE_COMPOSITE_EXTENSIONS */ - -#ifdef HAVE_COMPOSITE_EXTENSIONS static void ensure_repair_idle (MetaCompositor *compositor) { if (compositor->repair_idle != 0) return; - - compositor->repair_idle = g_idle_add_full (META_PRIORITY_COMPOSITE, - repair_idle_func, compositor, NULL); - compositor->repair_timeout = g_timeout_add (FRAME_INTERVAL_MILLISECONDS, - repair_timeout_func, compositor); - - meta_topic (META_DEBUG_COMPOSITOR, "Damage idle queued\n"); -} -#endif /* HAVE_COMPOSITE_EXTENSIONS */ - -#ifdef HAVE_COMPOSITE_EXTENSIONS -static void -merge_and_destroy_damage_region (MetaCompositor *compositor, - MetaScreen *screen, - XserverRegion region) -{ - if (screen->damage_region != None) - { - XFixesUnionRegion (compositor->display->xdisplay, - screen->damage_region, - region, screen->damage_region); - XFixesDestroyRegion (compositor->display->xdisplay, - region); - } - else + + if (!compositor->world) { - screen->damage_region = region; + compositor->world = world_new (compositor->display->xdisplay, + meta_display_screen_for_x_screen ( + compositor->display, + ScreenOfDisplay (compositor->display->xdisplay, + DefaultScreen (compositor->display->xdisplay)))); + + g_print ("screen %p\n", world_get_screen (compositor->world)); + +#if 0 + g_timeout_add_full (G_PRIORITY_HIGH, 50, update_world, compositor, NULL); +#endif } - - ensure_repair_idle (compositor); + + compositor->repair_idle = g_idle_add_full (META_PRIORITY_COMPOSITE, + meta_compositor_repair_now, compositor, NULL); + + meta_topic (META_DEBUG_COMPOSITOR, "Damage idle queued\n"); } #endif /* HAVE_COMPOSITE_EXTENSIONS */ #ifdef HAVE_COMPOSITE_EXTENSIONS -static void -merge_damage_region (MetaCompositor *compositor, - MetaScreen *screen, - XserverRegion region) +void +meta_compositor_invalidate_region (MetaCompositor *compositor, + MetaScreen *screen, + XserverRegion invalid_area) { if (screen->damage_region == None) screen->damage_region = XFixesCreateRegion (compositor->display->xdisplay, NULL, 0); - - meta_topic (META_DEBUG_COMPOSITOR, - "(Merging damage region)\n"); + +#if 0 + if (compositor->debug_updates) + { +# define ALPHA 0.1 + XRenderColor hilight = { ALPHA * 0x0000, ALPHA * 0x1000, ALPHA * 0xFFFF, ALPHA * 0xFFFF }; + XFixesSetPictureClipRegion (screen->display->xdisplay, screen->root_picture, 0, 0, invalid_area); + XRenderFillRectangle (screen->display->xdisplay, PictOpOver, + screen->root_picture, &hilight, + 0, 0, screen->width, screen->height); + XSync (screen->display->xdisplay, False); + } +#endif + +#if 0 + print_region (compositor->display->xdisplay, "invalidate", invalid_area); + meta_print_top_of_stack (4); +#endif XFixesUnionRegion (compositor->display->xdisplay, screen->damage_region, - region, screen->damage_region); - + invalid_area, screen->damage_region); + ensure_repair_idle (compositor); } #endif /* HAVE_COMPOSITE_EXTENSIONS */ @@ -632,135 +761,96 @@ static void process_damage_notify (MetaCompositor *compositor, XDamageNotifyEvent *event) { - MetaCompositorWindow *cwindow; - XserverRegion region; - MetaScreen *screen; + CWindow *cwindow; + +#if 0 + g_print ("damage on %lx\n", event->drawable); +#endif cwindow = g_hash_table_lookup (compositor->window_hash, &event->drawable); + if (cwindow == NULL) - return; + { + g_print ("spurious damage\n"); + return; + } - region = XFixesCreateRegion (compositor->display->xdisplay, NULL, 0); + cwindow_process_damage_notify (cwindow, event); +} +#endif /* HAVE_COMPOSITE_EXTENSIONS */ - /* translate region to screen; can error if window of damage is - * destroyed - */ - meta_error_trap_push (compositor->display); - XDamageSubtract (compositor->display->xdisplay, - cwindow->damage, None, region); - meta_error_trap_pop (compositor->display, FALSE); +static void +handle_restacking (MetaCompositor *compositor, + CWindow *cwindow, + CWindow *above) +{ + GList *window_link, *above_link; + MetaScreen *screen; - XFixesTranslateRegion (compositor->display->xdisplay, - region, - cwindow->x, - cwindow->y); + if (!cwindow) + return; - screen = meta_compositor_window_get_screen (cwindow); + screen = cwindow_get_screen (cwindow); - merge_and_destroy_damage_region (compositor, screen, region); + window_link = g_list_find (screen->compositor_windows, cwindow); + above_link = g_list_find (screen->compositor_windows, above); + + if (window_link->next != above_link) + { + screen->compositor_windows = g_list_delete_link (screen->compositor_windows, window_link); + screen->compositor_windows = g_list_insert_before (screen->compositor_windows, above_link, cwindow); + } +} + +static void +raise_gl_window (MetaCompositor *compositor) +{ + CWindow *cwindow = g_hash_table_lookup (compositor->window_hash, &compositor->gl_window); + if (cwindow) + { + MetaScreen *screen = cwindow_get_screen (cwindow); + GList *gl_link = g_list_find (screen->compositor_windows, cwindow); + + if (gl_link) + { + XRaiseWindow (compositor->display->xdisplay, compositor->gl_window); + screen->compositor_windows = g_list_delete_link (screen->compositor_windows, gl_link); + screen->compositor_windows = g_list_prepend (screen->compositor_windows, cwindow); + } + } } -#endif /* HAVE_COMPOSITE_EXTENSIONS */ #ifdef HAVE_COMPOSITE_EXTENSIONS static void process_configure_notify (MetaCompositor *compositor, XConfigureEvent *event) { - MetaCompositorWindow *cwindow; - MetaScreen *screen; - GList *link; - Window above; - XserverRegion region; + CWindow *cwindow; cwindow = g_hash_table_lookup (compositor->window_hash, &event->window); +#if 0 + g_print ("configure: %lx above %lx\n", event->window, event->above); +#endif + if (cwindow == NULL) - return; - - screen = meta_compositor_window_get_screen (cwindow); - - g_assert (screen != NULL); + { + g_print ("no window for event->window\n"); + return; + } - if (screen->xroot != event->event) - { - meta_topic (META_DEBUG_COMPOSITOR, - "ConfigureNotify for 0x%lx received by 0x%lx not using\n", - event->window, event->event); - return; /* ignore ConfigureNotify not received on root window */ - } +#if 0 + g_print ("gl window: %lx\n", compositor->gl_window); +#endif - meta_topic (META_DEBUG_COMPOSITOR, - "ConfigureNotify for 0x%lx received by 0x%lx %d,%d %dx%d\n", - event->window, event->event, - event->x, event->y, event->width, event->height); - - if (cwindow->last_painted_extents) - { - merge_and_destroy_damage_region (compositor, - screen, - cwindow->last_painted_extents); - cwindow->last_painted_extents = None; - } + handle_restacking (compositor, cwindow, + g_hash_table_lookup (compositor->window_hash, &event->above)); - cwindow->x = event->x; - cwindow->y = event->y; - cwindow->width = event->width; - cwindow->height = event->height; - cwindow->border_width = event->border_width; - - link = g_list_find (screen->compositor_windows, - cwindow); - - g_assert (link != NULL); + cwindow_process_configure_notify (cwindow, event); - if (link->next) - above = ((MetaCompositorWindow*) link->next)->xwindow; - else - above = None; + raise_gl_window (compositor); - if (above != event->above) - { - GList *tmp; - - screen->compositor_windows = - g_list_delete_link (screen->compositor_windows, - link); - link = NULL; - - /* Note that event->above is None if our window is on the bottom */ - tmp = screen->compositor_windows; - while (tmp != NULL) - { - MetaCompositorWindow *t = tmp->data; - - if (t->xwindow == event->above) - { - /* We are above this window, i.e. earlier in list */ - break; - } - - tmp = tmp->next; - } - - if (tmp != NULL) - { - screen->compositor_windows = - g_list_insert_before (screen->compositor_windows, - tmp, - cwindow); - } - else - screen->compositor_windows = - g_list_prepend (screen->compositor_windows, - cwindow); - } - - region = window_extents (cwindow); - merge_damage_region (compositor, - screen, - region); - XFixesDestroyRegion (compositor->display->xdisplay, region); } #endif /* HAVE_COMPOSITE_EXTENSIONS */ @@ -773,21 +863,26 @@ process_expose (MetaCompositor *compositor, XserverRegion region; MetaScreen *screen; XRectangle r; - + screen = meta_display_screen_for_root (compositor->display, event->window); - + if (screen == NULL || screen->root_picture == None) return; - + r.x = 0; r.y = 0; r.width = screen->width; r.height = screen->height; region = XFixesCreateRegion (compositor->display->xdisplay, &r, 1); - merge_and_destroy_damage_region (compositor, screen, region); + meta_compositor_invalidate_region (compositor, + screen, + region); + + XFixesDestroyRegion (compositor->display->xdisplay, region); } + #endif /* HAVE_COMPOSITE_EXTENSIONS */ #ifdef HAVE_COMPOSITE_EXTENSIONS @@ -795,13 +890,13 @@ static void process_map (MetaCompositor *compositor, XMapEvent *event) { - MetaCompositorWindow *cwindow; + CWindow *cwindow; MetaScreen *screen; - + /* See if window was mapped as child of root */ screen = meta_display_screen_for_root (compositor->display, event->event); - + if (screen == NULL || screen->root_picture == None) { meta_topic (META_DEBUG_COMPOSITOR, @@ -827,17 +922,21 @@ process_map (MetaCompositor *compositor, event->window); } else - { - meta_topic (META_DEBUG_COMPOSITOR, - "Map window 0x%lx\n", event->window); - meta_compositor_add_window (compositor, - event->window, &attrs); + { + g_print ("Map window 0x%lx\n", event->window); + meta_compositor_add_window (compositor, + event->window, &attrs); } } else { - cwindow->viewable = TRUE; + cwindow_set_viewable (cwindow, TRUE); } + + /* We don't actually need to invalidate anything, because we will + * get damage events as the server fills the background and the client + * draws the window + */ } #endif /* HAVE_COMPOSITE_EXTENSIONS */ @@ -846,13 +945,13 @@ static void process_unmap (MetaCompositor *compositor, XUnmapEvent *event) { - MetaCompositorWindow *cwindow; + CWindow *cwindow; MetaScreen *screen; - + /* See if window was unmapped as child of root */ screen = meta_display_screen_for_root (compositor->display, event->event); - + if (screen == NULL || screen->root_picture == None) { meta_topic (META_DEBUG_COMPOSITOR, @@ -865,14 +964,14 @@ process_unmap (MetaCompositor *compositor, &event->window); if (cwindow != NULL) { - cwindow->viewable = FALSE; - - if (cwindow->last_painted_extents) + cwindow_set_viewable (cwindow, FALSE); + + if (cwindow_get_last_painted_extents (cwindow)) { - merge_and_destroy_damage_region (compositor, - screen, - cwindow->last_painted_extents); - cwindow->last_painted_extents = None; + meta_compositor_invalidate_region (compositor, + screen, + cwindow_get_last_painted_extents (cwindow)); + cwindow_set_last_painted_extents (cwindow, None); } } } @@ -885,10 +984,10 @@ process_create (MetaCompositor *compositor, { MetaScreen *screen; XWindowAttributes attrs; - + screen = meta_display_screen_for_root (compositor->display, event->parent); - + if (screen == NULL || screen->root_picture == None) { meta_topic (META_DEBUG_COMPOSITOR, @@ -896,7 +995,7 @@ process_create (MetaCompositor *compositor, event->parent, event->window); return; } - + meta_error_trap_push_with_return (compositor->display); XGetWindowAttributes (compositor->display->xdisplay, @@ -911,6 +1010,7 @@ process_create (MetaCompositor *compositor, { meta_topic (META_DEBUG_COMPOSITOR, "Create window 0x%lx, adding\n", event->window); + meta_compositor_add_window (compositor, event->window, &attrs); } @@ -923,10 +1023,10 @@ process_destroy (MetaCompositor *compositor, XDestroyWindowEvent *event) { MetaScreen *screen; - + screen = meta_display_screen_for_root (compositor->display, event->event); - + if (screen == NULL || screen->root_picture == None) { meta_topic (META_DEBUG_COMPOSITOR, @@ -934,7 +1034,7 @@ process_destroy (MetaCompositor *compositor, event->event, event->window); return; } - + meta_topic (META_DEBUG_COMPOSITOR, "Destroy window 0x%lx\n", event->window); meta_compositor_remove_window (compositor, event->window); @@ -952,12 +1052,14 @@ process_reparent (MetaCompositor *compositor, */ MetaScreen *event_screen; MetaScreen *parent_screen; - MetaCompositorWindow *cwindow; + CWindow *cwindow; XWindowAttributes attrs; event_screen = meta_display_screen_for_root (compositor->display, event->event); + g_print ("reparent\n"); + if (event_screen == NULL || event_screen->root_picture == None) { meta_topic (META_DEBUG_COMPOSITOR, @@ -965,11 +1067,11 @@ process_reparent (MetaCompositor *compositor, event->event, event->window); return; } - + meta_topic (META_DEBUG_COMPOSITOR, "Reparent window 0x%lx new parent 0x%lx received on 0x%lx\n", event->window, event->parent, event->event); - + parent_screen = meta_display_screen_for_root (compositor->display, event->parent); @@ -989,11 +1091,11 @@ process_reparent (MetaCompositor *compositor, meta_topic (META_DEBUG_COMPOSITOR, "Window reparented to new screen at %d,%d\n", event->x, event->y); - cwindow->x = event->x; - cwindow->y = event->y; + cwindow_set_x (cwindow, event->x); + cwindow_set_y (cwindow, event->y); return; } - + meta_error_trap_push_with_return (compositor->display); XGetWindowAttributes (compositor->display->xdisplay, @@ -1001,6 +1103,7 @@ process_reparent (MetaCompositor *compositor, if (meta_error_trap_pop_with_return (compositor->display, TRUE) != Success) { + g_print ("attrs\n"); meta_topic (META_DEBUG_COMPOSITOR, "Failed to get attributes for window 0x%lx\n", event->window); } @@ -1009,6 +1112,7 @@ process_reparent (MetaCompositor *compositor, meta_topic (META_DEBUG_COMPOSITOR, "Reparent window 0x%lx into screen 0x%lx, adding\n", event->window, event->parent); + g_print ("adding\n"); meta_compositor_add_window (compositor, event->window, &attrs); } @@ -1023,7 +1127,7 @@ meta_compositor_process_event (MetaCompositor *compositor, #ifdef HAVE_COMPOSITE_EXTENSIONS if (!compositor->enabled) return; /* no extension */ - + /* FIXME support CirculateNotify */ if (event->type == (compositor->damage_event_base + XDamageNotify)) @@ -1079,106 +1183,58 @@ meta_compositor_add_window (MetaCompositor *compositor, XWindowAttributes *attrs) { #ifdef HAVE_COMPOSITE_EXTENSIONS - MetaCompositorWindow *cwindow; + CWindow *cwindow; MetaScreen *screen; - Damage damage; - XRenderPictFormat *format; - XRenderPictureAttributes pa; + XserverRegion region; if (!compositor->enabled) return; /* no extension */ +#if 0 + if (xwindow == compositor->gl_window) + return; +#endif + screen = meta_screen_for_x_screen (attrs->screen); g_assert (screen != NULL); cwindow = g_hash_table_lookup (compositor->window_hash, &xwindow); - + if (cwindow != NULL) { meta_topic (META_DEBUG_COMPOSITOR, "Window 0x%lx already added\n", xwindow); return; } - + meta_topic (META_DEBUG_COMPOSITOR, "Adding window 0x%lx (%s) to compositor\n", xwindow, attrs->map_state == IsViewable ? "mapped" : "unmapped"); - /* Create Damage object to monitor window damage */ - meta_error_trap_push (compositor->display); - damage = XDamageCreate (compositor->display->xdisplay, - xwindow, XDamageReportNonEmpty); - meta_error_trap_pop (compositor->display, FALSE); - - if (damage == None) - return; - - cwindow = g_new0 (MetaCompositorWindow, 1); - - cwindow->compositor = compositor; - cwindow->xwindow = xwindow; - cwindow->screen_index = screen->number; - cwindow->damage = damage; - cwindow->x = attrs->x; - cwindow->y = attrs->y; - cwindow->width = attrs->width; - cwindow->height = attrs->height; - cwindow->border_width = attrs->border_width; - -#if HAVE_NAME_WINDOW_PIXMAP - if (compositor->have_name_window_pixmap) - { - meta_error_trap_push (compositor->display); - cwindow->pixmap = XCompositeNameWindowPixmap (compositor->display->xdisplay, - cwindow->xwindow); - meta_error_trap_pop (compositor->display, FALSE); - } -#endif + cwindow = cwindow_new (compositor, xwindow, attrs); - /* viewable == mapped for the root window, since root can't be unmapped */ - cwindow->viewable = (attrs->map_state == IsViewable); /* FIXME this assertion can fail somehow... */ g_assert (attrs->map_state != IsUnviewable); - pa.subwindow_mode = IncludeInferiors; - - if (attrs->class != InputOnly) - { - format = XRenderFindVisualFormat (compositor->display->xdisplay, - attrs->visual); - cwindow->picture = XRenderCreatePicture (compositor->display->xdisplay, -#if HAVE_NAME_WINDOW_PIXMAP - cwindow->pixmap != None ? - cwindow->pixmap : - cwindow->xwindow, -#else - cwindow->xwindow, -#endif - format, - CPSubwindowMode, - &pa); - } - else - { - cwindow->picture = None; - } - g_hash_table_insert (compositor->window_hash, - &cwindow->xwindow, cwindow); - + cwindow_get_xid_address (cwindow), cwindow); + /* assume cwindow is at the top of the stack as it was either just * created or just reparented to the root window */ screen->compositor_windows = g_list_prepend (screen->compositor_windows, cwindow); - + /* schedule paint of the new window */ - region = window_extents (cwindow); - merge_and_destroy_damage_region (compositor, screen, region); + region = cwindow_extents (cwindow); + + meta_compositor_invalidate_region (compositor, screen, region); + + XFixesDestroyRegion (compositor->display->xdisplay, region); #endif /* HAVE_COMPOSITE_EXTENSIONS */ } @@ -1187,7 +1243,7 @@ meta_compositor_remove_window (MetaCompositor *compositor, Window xwindow) { #ifdef HAVE_COMPOSITE_EXTENSIONS - MetaCompositorWindow *cwindow; + CWindow *cwindow; MetaScreen *screen; if (!compositor->enabled) @@ -1195,27 +1251,27 @@ meta_compositor_remove_window (MetaCompositor *compositor, cwindow = g_hash_table_lookup (compositor->window_hash, &xwindow); - + if (cwindow == NULL) { meta_topic (META_DEBUG_COMPOSITOR, "Window 0x%lx already removed\n", xwindow); return; } - + meta_topic (META_DEBUG_COMPOSITOR, "Removing window 0x%lx (%s) from compositor\n", xwindow, - cwindow->viewable ? "mapped" : "unmapped"); + cwindow_get_viewable (cwindow) ? "mapped" : "unmapped"); - screen = meta_compositor_window_get_screen (cwindow); - - if (cwindow->last_painted_extents) + screen = cwindow_get_screen (cwindow); + + if (cwindow_get_last_painted_extents (cwindow)) { - merge_and_destroy_damage_region (compositor, - screen, - cwindow->last_painted_extents); - cwindow->last_painted_extents = None; + meta_compositor_invalidate_region (compositor, + screen, + cwindow_get_last_painted_extents (cwindow)); + cwindow_set_last_painted_extents (cwindow, None); } screen->compositor_windows = g_list_remove (screen->compositor_windows, @@ -1228,74 +1284,142 @@ meta_compositor_remove_window (MetaCompositor *compositor, #endif /* HAVE_COMPOSITE_EXTENSIONS */ } +static XserverRegion +empty_region (Display *dpy) +{ + XRectangle r; + r.x = 0; + r.y = 0; + r.width = 10; + r.height = 10; + return XFixesCreateRegion (dpy, &r, 1); +} + void meta_compositor_manage_screen (MetaCompositor *compositor, MetaScreen *screen) { #ifdef HAVE_COMPOSITE_EXTENSIONS XRenderPictureAttributes pa; - XRectangle r; XRenderColor c; if (!compositor->enabled) return; /* no extension */ - + /* FIXME we need to handle root window resize by recreating the * root_picture */ g_assert (screen->root_picture == None); - + + /* FIXME add flag for whether we're composite-managing each + * screen and detect failure here + */ + + /* CompositeRedirectSubwindows result in all mapped windows + * getting unmapped/mapped, which confuses Metacity since it + * thinks that non-override redirect windows should only + * be mapped by the window manager. + * + * To work around this, we discard all events generated + * by XCompositeRedirectSubwindows + */ + + XSync (screen->display->xdisplay, False); + /* FIXME add flag for whether we're composite-managing each * screen and detect failure here */ XCompositeRedirectSubwindows (screen->display->xdisplay, - screen->xroot, - CompositeRedirectManual); - meta_topic (META_DEBUG_COMPOSITOR, "Subwindows redirected, we are now the compositing manager\n"); + screen->xroot, + CompositeRedirectManual); + XSync (screen->display->xdisplay, True); + + /* FIMXE: This shouldn't be needed for the gl compositor, but it is. Various stuff gets + * confused if root_picture is None + */ pa.subwindow_mode = IncludeInferiors; - + screen->root_picture = - XRenderCreatePicture (compositor->display->xdisplay, - screen->xroot, - XRenderFindVisualFormat (compositor->display->xdisplay, - DefaultVisual (compositor->display->xdisplay, - screen->number)), - CPSubwindowMode, - &pa); - - g_assert (screen->root_picture != None); - - screen->trans_pixmap = XCreatePixmap (compositor->display->xdisplay, - screen->xroot, 1, 1, 8); - - pa.repeat = True; - screen->trans_picture = - XRenderCreatePicture (compositor->display->xdisplay, - screen->trans_pixmap, - XRenderFindStandardFormat (compositor->display->xdisplay, - PictStandardA8), - CPRepeat, - &pa); - - c.red = c.green = c.blue = 0; - c.alpha = 0xc0c0; - XRenderFillRectangle (compositor->display->xdisplay, - PictOpSrc, - screen->trans_picture, &c, 0, 0, 1, 1); - - /* Damage the whole screen */ - r.x = 0; - r.y = 0; - r.width = screen->width; - r.height = screen->height; + XRenderCreatePicture (compositor->display->xdisplay, + screen->xroot, + XRenderFindVisualFormat (compositor->display->xdisplay, + DefaultVisual (compositor->display->xdisplay, + screen->number)), + CPSubwindowMode, + &pa); + + if (USE_RENDER) + { + meta_topic (META_DEBUG_COMPOSITOR, "Subwindows redirected, we are now the compositing manager\n"); + + g_assert (screen->root_picture != None); + + screen->trans_pixmap = XCreatePixmap (compositor->display->xdisplay, + screen->xroot, 1, 1, 8); + + pa.repeat = True; + screen->trans_picture = + XRenderCreatePicture (compositor->display->xdisplay, + screen->trans_pixmap, + XRenderFindStandardFormat (compositor->display->xdisplay, + PictStandardA8), + CPRepeat, + &pa); + + c.red = c.green = c.blue = 0; + c.alpha = 0xd0d0; + XRenderFillRectangle (compositor->display->xdisplay, + PictOpSrc, + screen->trans_picture, &c, 0, 0, 1, 1); + } + else + { +#if 0 + = XCreateSimpleWindow (compositor->display->xdisplay, screen->xroot, 0, 0, + 1600, + 1200, + 0, 0, 0x00FFFF00); +#endif + Window w; - merge_and_destroy_damage_region (compositor, - screen, - XFixesCreateRegion (compositor->display->xdisplay, - &r, 1)); - + GLXContext context; + XSetWindowAttributes attr; + + XVisualInfo *visual = init_gl (compositor->display->xdisplay, 0, &context); + +#if 0 + g_print ("dfepth: %d\n", visual->depth); + g_print ("visual: %lx\n", visual->visualid); +#endif + + attr.colormap = XCreateColormap(compositor->display->xdisplay, screen->xroot, visual->visual, + AllocNone); + + w = XCreateWindow (compositor->display->xdisplay, screen->xroot, 0, 0, + screen->width, screen->height, 0, + visual->depth, InputOutput, visual->visual, + CWColormap, &attr); + + XSetWindowBackgroundPixmap (compositor->display->xdisplay, w, None); + + XserverRegion e = empty_region (compositor->display->xdisplay); + + /* Make the window "OutputOnly" */ + XFixesSetWindowShapeRegion (compositor->display->xdisplay, w, ShapeInput, + 0, 0, e); + + XRaiseWindow (compositor->display->xdisplay, w); + XMapWindow (compositor->display->xdisplay, w); + + XCompositeUnredirectWindow (compositor->display->xdisplay, w, + CompositeRedirectManual); + + glXMakeCurrent (compositor->display->xdisplay, w, context); + + compositor->gl_window = w; + } #endif /* HAVE_COMPOSITE_EXTENSIONS */ } @@ -1306,7 +1430,7 @@ meta_compositor_unmanage_screen (MetaCompositor *compositor, #ifdef HAVE_COMPOSITE_EXTENSIONS if (!compositor->enabled) return; /* no extension */ - + XRenderFreePicture (screen->display->xdisplay, screen->root_picture); screen->root_picture = None; @@ -1319,41 +1443,255 @@ meta_compositor_unmanage_screen (MetaCompositor *compositor, while (screen->compositor_windows != NULL) { - MetaCompositorWindow *cwindow = screen->compositor_windows->data; - + CWindow *cwindow = screen->compositor_windows->data; + meta_topic (META_DEBUG_COMPOSITOR, - "Unmanage screen for 0x%lx\n", cwindow->xwindow); - meta_compositor_remove_window (compositor, cwindow->xwindow); + "Unmanage screen for 0x%lx\n", cwindow_get_xwindow (cwindow)); + meta_compositor_remove_window (compositor, cwindow_get_xwindow (cwindow)); } #endif /* HAVE_COMPOSITE_EXTENSIONS */ } +static CWindow * +window_to_cwindow (MetaCompositor *compositor, + MetaWindow *window) +{ + Window xwindow; + CWindow *cwindow; + + if (window->frame) + xwindow = window->frame->xwindow; + else + xwindow = window->xwindow; + + cwindow = g_hash_table_lookup (compositor->window_hash, + &xwindow); + + return cwindow; +} + void meta_compositor_damage_window (MetaCompositor *compositor, MetaWindow *window) { #ifdef HAVE_COMPOSITE_EXTENSIONS - Window xwindow; - MetaCompositorWindow *cwindow; - + XserverRegion region; + CWindow *cwindow; + if (!compositor->enabled) return; - + if (window->screen->root_picture == None) return; - if (window->frame) - xwindow = window->frame->xwindow; - else - xwindow = window->xwindow; - - cwindow = g_hash_table_lookup (compositor->window_hash, - &xwindow); + cwindow = window_to_cwindow (compositor, window); + if (cwindow == NULL) return; - merge_and_destroy_damage_region (compositor, - window->screen, - window_extents (cwindow)); + region = cwindow_extents (cwindow); + + meta_compositor_invalidate_region (compositor, cwindow_get_screen (cwindow), region); + + XFixesDestroyRegion (compositor->display->xdisplay, region); #endif /* HAVE_COMPOSITE_EXTENSIONS */ } + +void +meta_compositor_stop_compositing (MetaCompositor *compositor, + MetaWindow *window) +{ + CWindow *cwindow; + cwindow = window_to_cwindow (compositor, window); + + if (cwindow) + cwindow_freeze (cwindow); +} + +void +meta_compositor_start_compositing (MetaCompositor *compositor, + MetaWindow *window) +{ + CWindow *cwindow; + cwindow = window_to_cwindow (compositor, window); + + if (cwindow) + cwindow_thaw (cwindow); + + meta_compositor_repair_now (compositor); +} + +static void +quad_to_quad_interpolate (Quad *start, Quad *end, Quad *dest, gdouble t) +{ + int i; + + for (i = 0; i < 4; ++i) + { + if (i == 3) + { + dest->points[i].x = + start->points[i].x + (end->points[i].x - start->points[i].x) * t; + } + else + { + dest->points[i].x = + start->points[i].x + (end->points[i].x - start->points[i].x) * pow (t, 1.5); + } + if (i == 1) + { + dest->points[i].y = + start->points[i].y + (end->points[i].y - start->points[i].y) * pow (t, 1.5); + } + else + { + dest->points[i].y = + start->points[i].y + (end->points[i].y - start->points[i].y) * t; + } + } +} + +void +meta_compositor_genie (MetaCompositor *compositor, + MetaWindow *window) +{ + int i; + int x, y, w, h; + + /* It's unusably slow right now, and also ugly */ + return; + + Quad start1; + Quad end1; + + Quad start2; + Quad end2; + + CWindow *cwindow = window_to_cwindow (compositor, window); + + if (!cwindow) + return; + + x = cwindow_get_x (cwindow); + y = cwindow_get_y (cwindow); + w = cwindow_get_width (cwindow) + cwindow_get_border_width (cwindow) * 2; + h = cwindow_get_height (cwindow) + cwindow_get_border_width (cwindow) * 2; + + start1.points[0].x = x; + start1.points[0].y = y; + start1.points[1].x = x + w/2 - 1; + start1.points[1].y = y; + start1.points[2].x = x; + start1.points[2].y = y + h - 1; + start1.points[3].x = x + w/2 - 1; + start1.points[3].y = y + h - 1; + + end1.points[0].x = 500; + end1.points[0].y = 200 + 50; + end1.points[1].x = 600; + end1.points[1].y = 200 + 50; + end1.points[2].x = 500; + end1.points[2].y = 200 + 80; + end1.points[3].x = 600; + end1.points[3].y = 200 + 80; + + start2.points[0].x = x + w/2; + start2.points[0].y = y; + start2.points[1].x = x + w - 1; + start2.points[1].y = y; + start2.points[2].x = x + w/2; + start2.points[2].y = y + h - 1; + start2.points[3].x = x + w - 1; + start2.points[3].y = y + h - 1; + + end2.points[0].x = 600; + end2.points[0].y = 200 + 50; + end2.points[1].x = 700; + end2.points[1].y = 200 + 50; + end2.points[2].x = 600; + end2.points[2].y = 200 + 80; + end2.points[3].x = 700; + end2.points[3].y = 200 + 130; + +#define STEPS 50 + + for (i = 0; i < STEPS; ++i) + { + Distortion distortion[2]; + Picture buffer; + Pixmap pixmap; + + quad_to_quad_interpolate (&start1, &end1, &distortion[0].destination, i/((double)STEPS - 1)); + quad_to_quad_interpolate (&start2, &end2, &distortion[1].destination, i/((double)STEPS - 1)); + + distortion[0].source.x = 0; + distortion[0].source.y = 0; + distortion[0].source.width = cwindow_get_width (cwindow) / 2; + distortion[0].source.height = cwindow_get_height (cwindow); + + distortion[1].source.x = cwindow_get_width (cwindow) / 2; + distortion[1].source.y = 0; + distortion[1].source.width = cwindow_get_width (cwindow) / 2; + distortion[1].source.height = cwindow_get_height (cwindow); + + cwindow_set_transformation (cwindow, distortion, 2); + + buffer = create_root_buffer (window->screen, &pixmap); + + { + XRectangle r; + XserverRegion region; + + r.x = 0; + r.y = 0; + r.width = window->screen->width; + r.height = window->screen->height; + + region = XFixesCreateRegion (compositor->display->xdisplay, &r, 1); + + XFixesDestroyRegion (compositor->display->xdisplay, + do_paint_screen (compositor, window->screen, buffer, region)); + XFixesDestroyRegion (compositor->display->xdisplay, region); + } + + cwindow_draw (cwindow, buffer, None); + + XFixesSetPictureClipRegion (compositor->display->xdisplay, + window->screen->root_picture, 0, 0, None); + /* Copy buffer to root window */ + paint_buffer (window->screen, pixmap, None); + + XFreePixmap (compositor->display->xdisplay, pixmap); + + XRenderFreePicture (compositor->display->xdisplay, buffer); + + XSync (compositor->display->xdisplay, False); + } + + cwindow_set_transformation (cwindow, NULL, 0); +} + +MetaDisplay * +meta_compositor_get_display (MetaCompositor *compositor) +{ + return compositor->display; +} + +void +meta_compositor_set_translucent (MetaCompositor *compositor, + MetaWindow *window, + gboolean translucent) +{ + CWindow *cwindow = window_to_cwindow (compositor, window); + + if (cwindow) + { + cwindow_set_translucent (cwindow, translucent); + } +} + +XID +meta_compositor_get_gl_window (MetaCompositor *compositor) +{ + return compositor->gl_window; +} |