summaryrefslogtreecommitdiff
path: root/src/compositor.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/compositor.c')
-rw-r--r--src/compositor.c1590
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;
+}