summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSøren Sandmann <sandmann@redhat.com>2005-04-13 18:45:19 +0000
committerSøren Sandmann Pedersen <ssp@src.gnome.org>2005-04-13 18:45:19 +0000
commitc473b680e68edf6552f8e19de7094ad03c6e5a60 (patch)
tree8ef1e799f82364a942d8727e49450a5c3c078355
parent90a4ddb18dffa8a8d972f34b867c8b0c2759095f (diff)
downloadmetacity-c473b680e68edf6552f8e19de7094ad03c6e5a60.tar.gz
Commit first attempt at using GL
Wed Apr 13 14:39:54 2005 Søren Sandmann <sandmann@redhat.com> * Commit first attempt at using GL For to those following along at home: It won't work unless you patch your X server.
-rw-r--r--ChangeLog7
-rw-r--r--src/Makefile.am6
-rw-r--r--src/compositor.c652
-rw-r--r--src/compositor.h3
-rw-r--r--src/cwindow.c1490
-rw-r--r--src/cwindow.h5
-rw-r--r--src/lmcbits.c93
-rw-r--r--src/lmcbits.h54
-rw-r--r--src/lmctexture.c777
-rw-r--r--src/lmctexture.h28
-rw-r--r--src/ui.h2
11 files changed, 2406 insertions, 711 deletions
diff --git a/ChangeLog b/ChangeLog
index 7d29a599..315a3698 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+Wed Apr 13 14:39:54 2005 Søren Sandmann <sandmann@redhat.com>
+
+ * Commit first attempt at using GL
+
+ For to those following along at home: It won't work unless you
+ patch your X server.
+
Mon Mar 28 15:34:37 2005 Søren Sandmann <sandmann@redhat.com>
* Merge changes on head.
diff --git a/src/Makefile.am b/src/Makefile.am
index 2535656d..daafe050 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -94,6 +94,10 @@ metacity_SOURCES= \
workspace.h \
xprops.c \
xprops.h \
+ lmcbits.c \
+ lmcbits.h \
+ lmctexture.c \
+ lmctexture.h \
$(EGGFILES)
# by setting libmetacity_private_la_CFLAGS, the files shared with
@@ -135,7 +139,7 @@ bin_PROGRAMS=metacity metacity-theme-viewer
libexec_PROGRAMS=metacity-dialog
EFENCE=
-metacity_LDADD=@METACITY_LIBS@ $(EFENCE)
+metacity_LDADD=@METACITY_LIBS@ $(EFENCE) -lGL -lGLU
metacity_theme_viewer_LDADD= @METACITY_LIBS@ libmetacity-private.la
metacity_dialog_LDADD=@METACITY_LIBS@
diff --git a/src/compositor.c b/src/compositor.c
index 3d7f46bc..67df2392 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -30,11 +30,17 @@
#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>
+#include "lmcbits.h"
+#include "lmctexture.h"
#endif /* HAVE_COMPOSITE_EXTENSIONS */
@@ -43,9 +49,9 @@
struct MetaCompositor
{
MetaDisplay *display;
-
- World *world;
-
+
+ World *world;
+
int composite_error_base;
int composite_event_base;
int damage_error_base;
@@ -65,6 +71,8 @@ struct MetaCompositor
guint debug_updates : 1;
GList *ignored_damage;
+
+ Window gl_window;
};
#ifdef HAVE_COMPOSITE_EXTENSIONS
@@ -72,7 +80,8 @@ static void
free_window_hash_value (void *v)
{
CWindow *cwindow = v;
-
+
+ g_print ("freeing cwindow %lx\n", cwindow_get_xwindow (cwindow));
cwindow_free (cwindow);
}
#endif /* HAVE_COMPOSITE_EXTENSIONS */
@@ -94,28 +103,66 @@ print_region (Display *dpy, const char *name, XserverRegion region)
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 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;
}
MetaCompositor*
@@ -203,7 +250,7 @@ meta_compositor_new (MetaDisplay *display)
free_window_hash_value);
compositor->enabled = TRUE;
-
+
return compositor;
#else /* HAVE_COMPOSITE_EXTENSIONS */
return (void*) 0xdeadbeef; /* non-NULL value */
@@ -214,7 +261,7 @@ void
meta_compositor_set_debug_updates (MetaCompositor *compositor,
gboolean debug_updates)
{
- compositor->debug_updates = !!debug_updates;
+ compositor->debug_updates = !!debug_updates;
}
#ifdef HAVE_COMPOSITE_EXTENSIONS
@@ -224,7 +271,7 @@ remove_repair_idle (MetaCompositor *compositor)
if (compositor->repair_idle)
{
meta_topic (META_DEBUG_COMPOSITOR, "Damage idle removed\n");
-
+
g_source_remove (compositor->repair_idle);
compositor->repair_idle = 0;
}
@@ -247,6 +294,7 @@ meta_compositor_unref (MetaCompositor *compositor)
#endif /* HAVE_COMPOSITE_EXTENSIONS */
}
+
#ifdef HAVE_COMPOSITE_EXTENSIONS
static void
draw_windows (MetaCompositor *compositor,
@@ -267,27 +315,27 @@ draw_windows (MetaCompositor *compositor,
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))
+ if (!cwindow_is_translucent (cwindow) &&
+ !cwindow_get_input_only (cwindow) && cwindow_get_viewable (cwindow))
{
XserverRegion opaque = cwindow_get_opaque_region (cwindow);
-
+
XFixesSubtractRegion (dpy, region_below, region_below, opaque);
-
+
XFixesDestroyRegion (dpy, opaque);
}
-
+
draw_windows (compositor, screen, list->next, region_below, picture);
-
+
XFixesDestroyRegion (dpy, region_below);
-
- XFixesSetPictureClipRegion (dpy, picture, 0, 0, damaged_region);
- cwindow_draw (cwindow, picture);
+
+ if (cwindow_get_viewable (cwindow) && cwindow_get_xwindow (cwindow) != compositor->gl_window)
+ cwindow_draw (cwindow, picture, damaged_region);
}
static Picture
create_root_buffer (MetaScreen *screen, Pixmap *pixmap)
{
- GC gc;
Display *display = screen->display->xdisplay;
Pixmap buffer_pixmap;
XGCValues value;
@@ -313,9 +361,9 @@ create_root_buffer (MetaScreen *screen, Pixmap *pixmap)
0, 0);
if (pixmap)
- *pixmap = buffer_pixmap;
+ *pixmap = buffer_pixmap;
else
- XFreePixmap (display, buffer_pixmap);
+ XFreePixmap (display, buffer_pixmap);
return buffer_picture;
}
@@ -329,19 +377,21 @@ paint_buffer (MetaScreen *screen,
GC gc;
value.function = GXcopy;
value.subwindow_mode = IncludeInferiors;
-
+
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,
@@ -353,7 +403,7 @@ do_paint_screen (MetaCompositor *compositor,
if (damage_region == None)
{
XRectangle r;
-
+
r.x = 0;
r.y = 0;
r.width = screen->width;
@@ -369,15 +419,123 @@ do_paint_screen (MetaCompositor *compositor,
region,
damage_region);
}
+
+#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
- meta_error_trap_push (compositor->display);
- XFixesSetPictureClipRegion (xdisplay,
- picture, 0, 0,
- region);
+ if (USE_RENDER)
+ {
+ meta_error_trap_push (compositor->display);
+ XFixesSetPictureClipRegion (xdisplay,
+ picture, 0, 0,
+ region);
+ }
+ else
+ {
+ GList *list;
+
+ glShadeModel (GL_FLAT);
+ glDisable (GL_TEXTURE_2D);
+ glDisable (GL_BLEND);
+
+ glViewport (0, 0, 1600, 1200);
+
+#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 0
+ glColor4f (g_random_double (),
+ g_random_double (),
+ g_random_double (),
+ 1.0);
+#endif
+
+#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);
+
+ glEnd ();
+#endif
+
+ glLoadIdentity();
+
+ gluOrtho2D (0, 1600, 1200, 0);
+ glDisable (GL_SCISSOR_TEST);
+ }
+
draw_windows (compositor, screen, screen->compositor_windows, region, picture);
- meta_error_trap_pop (compositor->display, FALSE);
-
+ 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);
+ glXSwapBuffers (screen->display->xdisplay, compositor->gl_window);
+ glFinish();
+
+#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
+ }
+
+
return region;
}
@@ -398,48 +556,56 @@ paint_screen (MetaCompositor *compositor,
xdisplay = screen->display->xdisplay;
- buffer_picture = create_root_buffer (screen, &pixmap);
-
+ 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);
+ screen->xroot, screen->root_picture);
- XFixesSetPictureClipRegion (xdisplay,
- screen->root_picture,
- 0, 0, region);
-
- XFixesSetPictureClipRegion (xdisplay, buffer_picture, 0, 0, None);
-
- if (compositor->debug_updates)
+ 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);
- }
-
+ 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);
+ world_paint (compositor->world, buffer_picture);
#endif
-
- paint_buffer (screen, pixmap, damage_region);
-
- XFreePixmap (screen->display->xdisplay, pixmap);
+
+ paint_buffer (screen, pixmap, damage_region);
+
+ XFreePixmap (screen->display->xdisplay, pixmap);
+ }
XFixesDestroyRegion (xdisplay, region);
-
-
- /* XFixesSetPictureClipRegion (xdisplay, buffer_picture, 0, 0, None); */
- XRenderFreePicture (xdisplay, buffer_picture);
-
- /* meta_display_ungrab (screen->display); */
+ if (USE_RENDER)
+ {
+ /* XFixesSetPictureClipRegion (xdisplay, buffer_picture, 0, 0, None); */
+ XRenderFreePicture (xdisplay, buffer_picture);
+
+ /* meta_display_ungrab (screen->display); */
+ }
XSync (screen->display->xdisplay, False);
}
@@ -458,6 +624,11 @@ do_repair (MetaCompositor *compositor)
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,
@@ -492,19 +663,19 @@ ensure_repair_idle (MetaCompositor *compositor)
return;
if (!compositor->world)
- {
+ {
compositor->world = world_new (compositor->display->xdisplay,
meta_display_screen_for_x_screen (
- compositor->display,
- ScreenOfDisplay (compositor->display->xdisplay,
- DefaultScreen (compositor->display->xdisplay))));
+ 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
- }
+ }
compositor->repair_idle = g_idle_add_full (META_PRIORITY_COMPOSITE,
meta_compositor_repair_now, compositor, NULL);
@@ -522,7 +693,7 @@ meta_compositor_invalidate_region (MetaCompositor *compositor,
if (screen->damage_region == None)
screen->damage_region =
XFixesCreateRegion (compositor->display->xdisplay, NULL, 0);
-
+
#if 0
if (compositor->debug_updates)
{
@@ -535,7 +706,7 @@ meta_compositor_invalidate_region (MetaCompositor *compositor,
XSync (screen->display->xdisplay, False);
}
#endif
-
+
#if 0
print_region (compositor->display->xdisplay, "invalidate", invalid_area);
meta_print_top_of_stack (4);
@@ -555,12 +726,19 @@ process_damage_notify (MetaCompositor *compositor,
XDamageNotifyEvent *event)
{
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;
+ }
cwindow_process_damage_notify (cwindow, event);
}
@@ -572,7 +750,12 @@ handle_restacking (MetaCompositor *compositor,
CWindow *above)
{
GList *window_link, *above_link;
- MetaScreen *screen = cwindow_get_screen (cwindow);
+ MetaScreen *screen;
+
+ if (!cwindow)
+ return;
+
+ screen = cwindow_get_screen (cwindow);
window_link = g_list_find (screen->compositor_windows, cwindow);
above_link = g_list_find (screen->compositor_windows, above);
@@ -584,6 +767,24 @@ handle_restacking (MetaCompositor *compositor,
}
}
+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);
+ }
+ }
+}
+
#ifdef HAVE_COMPOSITE_EXTENSIONS
static void
process_configure_notify (MetaCompositor *compositor,
@@ -593,13 +794,23 @@ process_configure_notify (MetaCompositor *compositor,
cwindow = g_hash_table_lookup (compositor->window_hash,
&event->window);
- if (cwindow == NULL)
- return;
+ g_print ("configure: %lx above %lx\n", event->window, event->above);
- cwindow_process_configure_notify (cwindow, event);
+ if (cwindow == NULL)
+ {
+ g_print ("no window for event->window\n");
+ return;
+ }
+
+ g_print ("gl window: %lx\n", compositor->gl_window);
handle_restacking (compositor, cwindow,
g_hash_table_lookup (compositor->window_hash, &event->above));
+
+ cwindow_process_configure_notify (cwindow, event);
+
+ raise_gl_window (compositor);
+
}
#endif /* HAVE_COMPOSITE_EXTENSIONS */
@@ -612,7 +823,7 @@ process_expose (MetaCompositor *compositor,
XserverRegion region;
MetaScreen *screen;
XRectangle r;
-
+
screen = meta_display_screen_for_root (compositor->display,
event->window);
@@ -628,7 +839,7 @@ process_expose (MetaCompositor *compositor,
meta_compositor_invalidate_region (compositor,
screen,
region);
-
+
XFixesDestroyRegion (compositor->display->xdisplay, region);
}
@@ -641,11 +852,11 @@ process_map (MetaCompositor *compositor,
{
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,
@@ -671,18 +882,17 @@ 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_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
@@ -760,6 +970,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);
}
@@ -806,6 +1017,8 @@ process_reparent (MetaCompositor *compositor,
event_screen = meta_display_screen_for_root (compositor->display,
event->event);
+
+ g_print ("reparent\n");
if (event_screen == NULL || event_screen->root_picture == None)
{
@@ -850,6 +1063,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);
}
@@ -858,6 +1072,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);
}
@@ -935,7 +1150,12 @@ meta_compositor_add_window (MetaCompositor *compositor,
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);
@@ -956,7 +1176,7 @@ meta_compositor_add_window (MetaCompositor *compositor,
"mapped" : "unmapped");
cwindow = cwindow_new (compositor, xwindow, attrs);
-
+
/* FIXME this assertion can fail somehow... */
g_assert (attrs->map_state != IsUnviewable);
@@ -971,9 +1191,9 @@ meta_compositor_add_window (MetaCompositor *compositor,
/* schedule paint of the new window */
region = cwindow_extents (cwindow);
-
+
meta_compositor_invalidate_region (compositor, screen, region);
-
+
XFixesDestroyRegion (compositor->display->xdisplay, region);
#endif /* HAVE_COMPOSITE_EXTENSIONS */
}
@@ -1009,8 +1229,8 @@ meta_compositor_remove_window (MetaCompositor *compositor,
if (cwindow_get_last_painted_extents (cwindow))
{
meta_compositor_invalidate_region (compositor,
- screen,
- cwindow_get_last_painted_extents (cwindow));
+ screen,
+ cwindow_get_last_painted_extents (cwindow));
cwindow_set_last_painted_extents (cwindow, None);
}
@@ -1024,15 +1244,24 @@ 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;
- XserverRegion region;
if (!compositor->enabled)
return; /* no extension */
@@ -1066,49 +1295,88 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
CompositeRedirectManual);
XSync (screen->display->xdisplay, True);
-
- meta_topic (META_DEBUG_COMPOSITOR, "Subwindows redirected, we are now the compositing manager\n");
-
+
+ /* 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 = 0xd0d0;
- 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;
- region = XFixesCreateRegion (compositor->display->xdisplay, &r, 1);
+ GLXContext context;
+ XSetWindowAttributes attr;
+
+ XVisualInfo *visual = init_gl (compositor->display->xdisplay, 0, &context);
-
+ g_print ("dfepth: %d\n", visual->depth);
+ g_print ("visual: %lx\n", visual->visualid);
+
+ attr.colormap = XCreateColormap(compositor->display->xdisplay, screen->xroot, visual->visual,
+ AllocNone);
+
+ w = XCreateWindow (compositor->display->xdisplay, screen->xroot, 0, 0, 1600, 1200, 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 */
}
@@ -1179,9 +1447,9 @@ meta_compositor_damage_window (MetaCompositor *compositor,
return;
region = cwindow_extents (cwindow);
-
+
meta_compositor_invalidate_region (compositor, cwindow_get_screen (cwindow), region);
-
+
XFixesDestroyRegion (compositor->display->xdisplay, region);
#endif /* HAVE_COMPOSITE_EXTENSIONS */
}
@@ -1190,24 +1458,24 @@ void
meta_compositor_stop_compositing (MetaCompositor *compositor,
MetaWindow *window)
{
- CWindow *cwindow;
- cwindow = window_to_cwindow (compositor, window);
-
- if (cwindow)
- cwindow_freeze (cwindow);
+ 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);
+ CWindow *cwindow;
+ cwindow = window_to_cwindow (compositor, window);
+
+ if (cwindow)
+ cwindow_thaw (cwindow);
+
+ meta_compositor_repair_now (compositor);
}
static void
@@ -1246,13 +1514,13 @@ meta_compositor_genie (MetaCompositor *compositor,
{
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;
@@ -1292,7 +1560,7 @@ meta_compositor_genie (MetaCompositor *compositor,
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;
@@ -1301,11 +1569,11 @@ meta_compositor_genie (MetaCompositor *compositor,
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;
@@ -1328,35 +1596,35 @@ meta_compositor_genie (MetaCompositor *compositor,
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);
+ 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);
+ 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);
}
@@ -1371,10 +1639,16 @@ meta_compositor_set_translucent (MetaCompositor *compositor,
MetaWindow *window,
gboolean translucent)
{
- CWindow *cwindow = window_to_cwindow (compositor, window);
-
- if (cwindow)
+ CWindow *cwindow = window_to_cwindow (compositor, window);
+
+ if (cwindow)
{
- cwindow_set_translucent (cwindow, translucent);
+ cwindow_set_translucent (cwindow, translucent);
}
}
+
+XID
+meta_compositor_get_gl_window (MetaCompositor *compositor)
+{
+ return compositor->gl_window;
+}
diff --git a/src/compositor.h b/src/compositor.h
index b9ac949d..1426a314 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -69,4 +69,7 @@ meta_compositor_set_translucent (MetaCompositor *compositor,
gboolean
meta_compositor_repair_now (MetaCompositor *compositor);
+XID
+meta_compositor_get_gl_window (MetaCompositor *compositor);
+
#endif /* META_COMPOSITOR_H */
diff --git a/src/cwindow.c b/src/cwindow.c
index 9b85b86e..48161909 100644
--- a/src/cwindow.c
+++ b/src/cwindow.c
@@ -1,3 +1,5 @@
+#include <sys/types.h>
+#include <sys/shm.h>
#include <X11/Xlib.h>
#include "cwindow.h"
#include "errors.h"
@@ -7,6 +9,10 @@
#include <math.h>
#include <string.h>
#include <X11/extensions/shape.h>
+#include <X11/extensions/XShm.h>
+#include "lmctexture.h"
+#include "window.h"
+
#define SHADOW_RADIUS 6
#define SHADOW_OPACITY (.25)
@@ -20,17 +26,17 @@ typedef struct FreezeInfo FreezeInfo;
struct Geometry
{
- int x;
- int y;
- int width;
- int height;
- int border_width;
+ int x;
+ int y;
+ int width;
+ int height;
+ int border_width;
};
struct FreezeInfo
{
- Geometry geometry;
- Pixmap pixmap;
+ Geometry geometry;
+ Pixmap pixmap;
};
/* Unlike MetaWindow, there's one of these for _all_ toplevel windows,
@@ -42,37 +48,48 @@ struct FreezeInfo
*/
struct CWindow
{
- Window xwindow;
-
-#ifdef HAVE_COMPOSITE_EXTENSIONS
- MetaCompositor *compositor;
-
- Geometry geometry;
-
- Damage damage;
- XserverRegion last_painted_extents;
-
- XserverRegion border_size;
+ Window xwindow;
+#ifdef HAVE_COMPOSITE_EXTENSIONS
+ MetaCompositor *compositor;
+
+ Geometry geometry;
+
+ Damage damage;
+ XserverRegion last_painted_extents;
+
+ XserverRegion border_size;
+
Picture shadow;
- FreezeInfo *freeze_info;
-
- unsigned int managed : 1;
- unsigned int damaged : 1;
- unsigned int viewable : 1;
- unsigned int input_only : 1;
- unsigned int translucent : 1;
-
- unsigned int screen_index : 8;
-
- Visual *visual;
-
- Distortion *distortions;
- int n_distortions;
-
+ FreezeInfo *freeze_info;
+
+ unsigned int managed : 1;
+ unsigned int damaged : 1;
+ unsigned int viewable : 1;
+ unsigned int input_only : 1;
+ unsigned int translucent : 1;
+
+ unsigned int screen_index : 8;
+
+ Visual *visual;
+
+ Distortion *distortions;
+ int n_distortions;
+
int shadow_width;
int shadow_height;
+
+ int depth;
+ XImage *image;
+ XShmSegmentInfo shm_info;
+ Pixmap shm_pixmap;
+ GC shm_gc;
+ LmcBits *bits;
+ XserverRegion parts_region;
+ LmcTexture *texture;
+
+ long damage_serial;
#endif
};
@@ -82,29 +99,30 @@ static Display *cwindow_get_xdisplay (CWindow *cwindow);
void
cwindow_free (CWindow *cwindow)
{
- g_assert (cwindow->damage != None);
-
- meta_error_trap_push (meta_compositor_get_display (cwindow->compositor));
- /* This seems to cause an error if the window
- * is destroyed?
- */
- XDamageDestroy (cwindow_get_xdisplay (cwindow), cwindow->damage);
-
- /* Free our window pixmap name */
- if (cwindow->freeze_info)
- cwindow_thaw (cwindow);
-
- meta_error_trap_pop (meta_compositor_get_display (cwindow->compositor),
- FALSE);
-
- g_free (cwindow);
+ g_assert (cwindow->damage != None);
+
+ meta_error_trap_push (meta_compositor_get_display (cwindow->compositor));
+ /* This seems to cause an error if the window
+ * is destroyed?
+ */
+ g_print ("destroying damage for %lx\n", cwindow->xwindow);
+ XDamageDestroy (cwindow_get_xdisplay (cwindow), cwindow->damage);
+
+ /* Free our window pixmap name */
+ if (cwindow->freeze_info)
+ cwindow_thaw (cwindow);
+
+ meta_error_trap_pop (meta_compositor_get_display (cwindow->compositor),
+ FALSE);
+
+ g_free (cwindow);
}
#endif /* HAVE_COMPOSITE_EXTENSIONS */
static void
create_shadow (CWindow *cwindow)
{
- if (!cwindow->shadow)
+ if (USE_RENDER && !cwindow->shadow)
{
cwindow->shadow = shadow_picture (cwindow_get_xdisplay (cwindow),
cwindow_get_screen (cwindow)->xroot,
@@ -118,7 +136,7 @@ create_shadow (CWindow *cwindow)
static void
delete_shadow (CWindow *cwindow)
{
- if (cwindow->shadow)
+ if (USE_RENDER && cwindow->shadow)
{
XRenderFreePicture (cwindow_get_xdisplay (cwindow), cwindow->shadow);
cwindow->shadow = None;
@@ -129,165 +147,296 @@ delete_shadow (CWindow *cwindow)
XserverRegion
cwindow_extents (CWindow *cwindow)
{
- Geometry *geometry;
- XRectangle r;
-
- if (cwindow->freeze_info)
- geometry = &cwindow->freeze_info->geometry;
- else
- geometry = &cwindow->geometry;
-
- r.x = geometry->x;
- r.y = geometry->y;
- r.width = geometry->width;
- r.height = geometry->height;
-
- create_shadow (cwindow);
-
- if (cwindow->shadow)
- {
- r.x = geometry->x + SHADOW_OFFSET;
- r.y = geometry->y;
- r.width = cwindow->shadow_width;
- r.height = cwindow->shadow_height;
- }
-
- return XFixesCreateRegion (cwindow_get_xdisplay (cwindow), &r, 1);
+ Geometry *geometry;
+ XRectangle r;
+
+ if (cwindow->freeze_info)
+ geometry = &cwindow->freeze_info->geometry;
+ else
+ geometry = &cwindow->geometry;
+
+ r.x = geometry->x;
+ r.y = geometry->y;
+ r.width = geometry->width;
+ r.height = geometry->height;
+
+ create_shadow (cwindow);
+
+ if (cwindow->shadow)
+ {
+ r.x = geometry->x + SHADOW_OFFSET;
+ r.y = geometry->y;
+ r.width = cwindow->shadow_width;
+ r.height = cwindow->shadow_height;
+ }
+
+ return XFixesCreateRegion (cwindow_get_xdisplay (cwindow), &r, 1);
}
#endif /* HAVE_COMPOSITE_EXTENSIONS */
static gboolean
cwindow_has_alpha (CWindow *cwindow)
{
- XRenderPictFormat *format;
-
- format = XRenderFindVisualFormat (cwindow_get_xdisplay (cwindow),
- cwindow_get_visual (cwindow));
-
- return format->direct.alpha;
+ if (USE_RENDER)
+ {
+ XRenderPictFormat *format;
+
+ format = XRenderFindVisualFormat (cwindow_get_xdisplay (cwindow),
+ cwindow_get_visual (cwindow));
+
+ return format->direct.alpha;
+ }
+ else
+ {
+ return TRUE;
+ }
}
XserverRegion
cwindow_get_opaque_region (CWindow *cwindow)
{
- XRectangle rect;
- Geometry *geometry;
-
- if (cwindow->translucent || cwindow_get_input_only (cwindow) ||
- !cwindow_get_viewable (cwindow) || cwindow_has_alpha (cwindow) ||
- cwindow->n_distortions)
+ if (!USE_RENDER || cwindow->translucent || cwindow_get_input_only (cwindow) ||
+ !cwindow_get_viewable (cwindow) || cwindow_has_alpha (cwindow) ||
+ cwindow->n_distortions)
{
- return XFixesCreateRegion (cwindow_get_xdisplay (cwindow), NULL, 0);
+ return XFixesCreateRegion (cwindow_get_xdisplay (cwindow), NULL, 0);
}
- else
+ else
{
- XserverRegion region = XFixesCreateRegionFromWindow (cwindow_get_xdisplay (cwindow),
- cwindow->xwindow, ShapeBounding);
-
- XFixesTranslateRegion (cwindow_get_xdisplay (cwindow),
- region,
- cwindow_get_x (cwindow),
- cwindow_get_y (cwindow));
-
- return region;
-#if 0
-
- if (cwindow->freeze_info)
- geometry = &cwindow->freeze_info->geometry;
- else
- geometry = &cwindow->geometry;
-
- rect.x = geometry->x;
- rect.y = geometry->y;
- rect.width = geometry->width;
- rect.height = geometry->height;
-
- return XFixesCreateRegion (cwindow_get_xdisplay (cwindow), &rect, 1);
-#endif
+ XserverRegion region = XFixesCreateRegionFromWindow (
+ cwindow_get_xdisplay (cwindow),
+ cwindow->xwindow, ShapeBounding);
+
+ XFixesTranslateRegion (cwindow_get_xdisplay (cwindow),
+ region,
+ cwindow_get_x (cwindow),
+ cwindow_get_y (cwindow));
+
+ return region;
}
}
static void
cwindow_queue_paint (CWindow *cwindow)
{
- XserverRegion region;
- MetaScreen *screen;
-
- create_shadow (cwindow);
-
- region = cwindow_extents (cwindow);
- screen = cwindow_get_screen (cwindow);
-
- meta_compositor_invalidate_region (cwindow->compositor,
- screen,
- region);
-
- XFixesDestroyRegion (cwindow_get_xdisplay (cwindow), region);
+ XserverRegion region;
+ MetaScreen *screen;
+
+ create_shadow (cwindow);
+
+ region = cwindow_extents (cwindow);
+ screen = cwindow_get_screen (cwindow);
+
+ meta_compositor_invalidate_region (cwindow->compositor,
+ screen,
+ region);
+
+ XFixesDestroyRegion (cwindow_get_xdisplay (cwindow), region);
}
void
cwindow_set_translucent (CWindow *cwindow, gboolean translucent)
{
#if 0
- cwindow->translucent = !!translucent;
+ cwindow->translucent = !!translucent;
#endif
-
- cwindow_queue_paint (cwindow);
+
+ cwindow_queue_paint (cwindow);
}
Drawable
cwindow_get_drawable (CWindow *cwindow)
{
- if (cwindow->freeze_info)
+ if (cwindow->freeze_info)
{
- return cwindow->freeze_info->pixmap;
+ return cwindow->freeze_info->pixmap;
}
- else
+ else
{
- return cwindow->xwindow;
+ return cwindow->xwindow;
}
}
void
cwindow_destroy_last_painted_extents (CWindow *cwindow)
{
- if (cwindow->last_painted_extents)
+ if (cwindow->last_painted_extents)
{
- XFixesDestroyRegion (cwindow_get_xdisplay (cwindow), cwindow->last_painted_extents);
- cwindow->last_painted_extents = None;
+ XFixesDestroyRegion (cwindow_get_xdisplay (cwindow), cwindow->last_painted_extents);
+ cwindow->last_painted_extents = None;
}
}
void
cwindow_set_last_painted_extents (CWindow *cwindow, XserverRegion extents)
{
- cwindow_destroy_last_painted_extents (cwindow);
- cwindow->last_painted_extents = extents;
+ cwindow_destroy_last_painted_extents (cwindow);
+ cwindow->last_painted_extents = extents;
}
MetaScreen*
cwindow_get_screen (CWindow *cwindow)
{
- MetaScreen *screen;
- GSList *tmp;
-
- screen = NULL;
- tmp = meta_compositor_get_display (cwindow->compositor)->screens;
- while (tmp != NULL)
+ MetaScreen *screen;
+ GSList *tmp;
+
+ screen = NULL;
+ tmp = meta_compositor_get_display (cwindow->compositor)->screens;
+ while (tmp != NULL)
{
- MetaScreen *s = tmp->data;
-
- if (s->number == cwindow->screen_index)
+ MetaScreen *s = tmp->data;
+
+ if (s->number == cwindow->screen_index)
{
- screen = s;
- break;
+ screen = s;
+ break;
}
-
- tmp = tmp->next;
+
+ tmp = tmp->next;
}
- g_assert (screen != NULL);
-
- return screen;
+ g_assert (screen != NULL);
+
+ return screen;
+}
+
+/* From luminocity */
+static void
+destroy_bits (gpointer data)
+{
+ XShmSegmentInfo *shm_info = data;
+
+ shmdt (shm_info->shmaddr);
+
+ g_free (shm_info);
+}
+
+static gboolean
+create_window_image (CWindow *cwindow)
+{
+ Display *xdisplay = cwindow_get_xdisplay (cwindow);
+ int image_size;
+ XGCValues gcv;
+ LmcBitsFormat format;
+ Geometry *geometry = cwindow->freeze_info?
+ &cwindow->freeze_info->geometry :
+ &cwindow->geometry;
+
+ g_return_val_if_fail (cwindow->image == NULL, False);
+
+ if (cwindow->depth == 16 &&
+ cwindow->visual->red_mask == 0xf800 &&
+ cwindow->visual->green_mask == 0x7e0 &&
+ cwindow->visual->blue_mask == 0x1f)
+ {
+ format = LMC_BITS_RGB_16;
+ }
+ else if (cwindow->depth == 24 &&
+ cwindow->visual->red_mask == 0xff0000 &&
+ cwindow->visual->green_mask == 0xff00 &&
+ cwindow->visual->blue_mask == 0xff)
+ {
+ format = LMC_BITS_RGB_32;
+ }
+ else if (cwindow->depth == 32 &&
+ cwindow->visual->red_mask == 0xff0000 &&
+ cwindow->visual->green_mask == 0xff00 &&
+ cwindow->visual->blue_mask == 0xff)
+ {
+ format = LMC_BITS_ARGB_32;
+ }
+ else
+ {
+ g_warning ("Unknown visual format depth=%d, r=%#lx/g=%#lx/b=%#lx",
+ cwindow->depth, cwindow->visual->red_mask, cwindow->visual->green_mask, cwindow->visual->blue_mask);
+
+ return FALSE;
+ }
+
+ cwindow->image = XCreateImage (xdisplay,
+ cwindow->visual,
+ cwindow->depth,
+ ZPixmap,
+ 0,
+ 0,
+ geometry->width,
+ geometry->height,
+ 32,
+ 0);
+ if (!cwindow->image)
+ return FALSE;
+
+ image_size = (cwindow->image->bytes_per_line * geometry->height);
+
+ cwindow->shm_info.shmid = shmget (IPC_PRIVATE, image_size, IPC_CREAT|0600);
+ if (cwindow->shm_info.shmid < 0)
+ {
+ XDestroyImage (cwindow->image);
+ cwindow->image = NULL;
+ return FALSE;
+ }
+
+ cwindow->shm_info.shmaddr = (char *) shmat (cwindow->shm_info.shmid, 0, 0);
+ if (cwindow->shm_info.shmaddr == ((char *) -1))
+ {
+ XDestroyImage (cwindow->image);
+ cwindow->image = NULL;
+ shmctl (cwindow->shm_info.shmid, IPC_RMID, 0);
+ return FALSE;
+ }
+
+ meta_error_trap_push_with_return (meta_compositor_get_display (cwindow->compositor));
+
+ cwindow->shm_info.readOnly = False;
+ XShmAttach (xdisplay, &cwindow->shm_info);
+ XSync (xdisplay, False);
+
+ if (meta_error_trap_pop_with_return (meta_compositor_get_display (cwindow->compositor), FALSE))
+ {
+ XDestroyImage (cwindow->image);
+ cwindow->image = NULL;
+ shmdt (&cwindow->shm_info.shmaddr);
+ shmctl (cwindow->shm_info.shmid, IPC_RMID, 0);
+ return FALSE;
+ }
+
+ /* Detach now so we clean up on abnormal exit */
+ shmctl (cwindow->shm_info.shmid, IPC_RMID, 0);
+
+ cwindow->image->data = cwindow->shm_info.shmaddr;
+ cwindow->image->obdata = (char *) &cwindow->shm_info;
+ cwindow->shm_pixmap = XShmCreatePixmap (xdisplay,
+ cwindow->xwindow,
+ cwindow->image->data,
+ &cwindow->shm_info,
+ geometry->width,
+ geometry->height,
+ cwindow->depth);
+
+ gcv.graphics_exposures = False;
+ gcv.subwindow_mode = IncludeInferiors;
+ cwindow->shm_gc = XCreateGC (xdisplay,
+ cwindow->xwindow,
+ GCGraphicsExposures|GCSubwindowMode,
+ &gcv);
+
+ cwindow->bits = lmc_bits_new (format,
+ geometry->width, geometry->height,
+ cwindow->image->data,
+ cwindow->image->bytes_per_line,
+ destroy_bits,
+ g_memdup (&cwindow->shm_info, sizeof (XShmSegmentInfo)));
+
+ return TRUE;
+}
+
+static void
+initialize_damage (CWindow *cwindow)
+{
+ create_window_image (cwindow);
+
+ cwindow->damage_serial = 0;
+
+ cwindow_queue_paint (cwindow);
}
CWindow *
@@ -295,195 +444,219 @@ cwindow_new (MetaCompositor *compositor,
Window xwindow,
XWindowAttributes *attrs)
{
- CWindow *cwindow;
- Damage damage;
-
- /* Create Damage object to monitor window damage */
- meta_error_trap_push (meta_compositor_get_display (compositor));
- damage = XDamageCreate (meta_compositor_get_display (compositor)->xdisplay,
- xwindow, XDamageReportNonEmpty);
- meta_error_trap_pop (meta_compositor_get_display (compositor), FALSE);
-
- if (damage == None)
- return NULL;
-
- cwindow = g_new0 (CWindow, 1);
-
- cwindow->compositor = compositor;
- cwindow->xwindow = xwindow;
- cwindow->screen_index = XScreenNumberOfScreen (attrs->screen);
- cwindow->damage = damage;
-
- cwindow->freeze_info = NULL;
-
- cwindow->geometry.x = attrs->x;
- cwindow->geometry.y = attrs->y;
- cwindow->geometry.width = attrs->width;
- cwindow->geometry.height = attrs->height;
- cwindow->geometry.border_width = attrs->border_width;
-
- if (attrs->class == InputOnly)
- cwindow->input_only = TRUE;
- else
- cwindow->input_only = FALSE;
-
- cwindow->visual = attrs->visual;
-
- /* viewable == mapped for the root window, since root can't be unmapped */
- cwindow->viewable = (attrs->map_state == IsViewable);
-
- return cwindow;
+ CWindow *cwindow;
+ Damage damage;
+ gboolean is_gl_window;
+
+ /* Create Damage object to monitor window damage */
+ meta_error_trap_push (meta_compositor_get_display (compositor));
+ g_print ("creating damage for %lx\n", xwindow);
+
+ is_gl_window = (xwindow == meta_compositor_get_gl_window (compositor));
+
+ if (!is_gl_window)
+ {
+ damage = XDamageCreate (meta_compositor_get_display (compositor)->xdisplay,
+ xwindow, XDamageReportNonEmpty);
+ }
+ else
+ {
+ damage = None;
+ }
+
+ meta_error_trap_pop (meta_compositor_get_display (compositor), FALSE);
+
+ if (damage == None && !is_gl_window)
+ return NULL;
+
+ cwindow = g_new0 (CWindow, 1);
+
+ cwindow->compositor = compositor;
+ cwindow->xwindow = xwindow;
+ cwindow->screen_index = XScreenNumberOfScreen (attrs->screen);
+ cwindow->damage = damage;
+ cwindow->depth = attrs->depth;
+
+ if (is_gl_window)
+ {
+ return cwindow;
+ }
+
+ cwindow->freeze_info = NULL;
+
+ cwindow->geometry.x = attrs->x;
+ cwindow->geometry.y = attrs->y;
+ cwindow->geometry.width = attrs->width;
+ cwindow->geometry.height = attrs->height;
+ cwindow->geometry.border_width = attrs->border_width;
+
+ if (attrs->class == InputOnly)
+ cwindow->input_only = TRUE;
+ else
+ cwindow->input_only = FALSE;
+
+ cwindow->visual = attrs->visual;
+
+ /* viewable == mapped for the root window, since root can't be unmapped */
+ cwindow->viewable = (attrs->map_state == IsViewable);
+
+ cwindow->parts_region = XFixesCreateRegion (cwindow_get_xdisplay (cwindow), 0, 0);
+
+ if (!cwindow->input_only)
+ initialize_damage (cwindow);
+
+ return cwindow;
}
XID *
cwindow_get_xid_address (CWindow *cwindow)
{
- return &cwindow->xwindow;
+ return &cwindow->xwindow;
}
static Display *
cwindow_get_xdisplay (CWindow *cwindow)
{
- return meta_compositor_get_display (cwindow->compositor)->xdisplay;
+ return meta_compositor_get_display (cwindow->compositor)->xdisplay;
}
Window
cwindow_get_xwindow (CWindow *cwindow)
{
- return cwindow->xwindow;
+ return cwindow->xwindow;
}
gboolean
cwindow_get_viewable (CWindow *cwindow)
{
- return cwindow->viewable;
+ return cwindow->viewable;
}
gboolean
cwindow_get_input_only (CWindow *cwindow)
{
- return cwindow->input_only;
+ return cwindow->input_only;
}
Visual *
cwindow_get_visual (CWindow *cwindow)
{
- return cwindow->visual;
+ return cwindow->visual;
}
XserverRegion
cwindow_get_last_painted_extents (CWindow *cwindow)
{
- return cwindow->last_painted_extents;
+ return cwindow->last_painted_extents;
}
int
cwindow_get_x (CWindow *cwindow)
{
- return cwindow->geometry.x;
+ return cwindow->geometry.x;
}
int
cwindow_get_y (CWindow *cwindow)
{
- return cwindow->geometry.y;
+ return cwindow->geometry.y;
}
int
cwindow_get_width (CWindow *cwindow)
{
- return cwindow->geometry.width;
+ return cwindow->geometry.width;
}
int
cwindow_get_height (CWindow *cwindow)
{
- return cwindow->geometry.height;
+ return cwindow->geometry.height;
}
int
cwindow_get_border_width (CWindow *cwindow)
{
- return cwindow->geometry.border_width;
+ return cwindow->geometry.border_width;
}
Damage
cwindow_get_damage (CWindow *cwindow)
{
- return cwindow->damage;
+ return cwindow->damage;
}
MetaCompositor *
cwindow_get_compositor (CWindow *cwindow)
{
- return cwindow->compositor;
+ return cwindow->compositor;
}
void
cwindow_set_x (CWindow *cwindow, int x)
{
- cwindow->geometry.x = x;
+ cwindow->geometry.x = x;
}
void
cwindow_set_y (CWindow *cwindow, int y)
{
- cwindow->geometry.y = y;
+ cwindow->geometry.y = y;
}
void
cwindow_set_width (CWindow *cwindow, int width)
{
- cwindow->geometry.width = width;
+ cwindow->geometry.width = width;
}
void
cwindow_set_height (CWindow *cwindow, int height)
{
- cwindow->geometry.height = height;
+ cwindow->geometry.height = height;
}
void
cwindow_set_viewable (CWindow *cwindow, gboolean viewable)
{
- viewable = !!viewable;
- if (cwindow->viewable != viewable)
+ viewable = !!viewable;
+ if (cwindow->viewable != viewable)
{
- cwindow_queue_paint (cwindow);
- cwindow->viewable = viewable;
+ cwindow_queue_paint (cwindow);
+ cwindow->viewable = viewable;
}
}
void
cwindow_set_border_width (CWindow *cwindow, int border_width)
{
- cwindow->geometry.border_width = border_width;
+ cwindow->geometry.border_width = border_width;
}
static XFixed
double_to_fixed (gdouble d)
{
- return XDoubleToFixed (d);
+ return XDoubleToFixed (d);
}
static void
convert_matrix (Matrix3 *matrix, XTransform *trans)
{
#if 0
- matrix3_transpose (matrix);
+ matrix3_transpose (matrix);
#endif
- trans->matrix[0][0] = double_to_fixed (matrix->coeff[0][0]);
- trans->matrix[1][0] = double_to_fixed (matrix->coeff[1][0]);
- trans->matrix[2][0] = double_to_fixed (matrix->coeff[2][0]);
- trans->matrix[0][1] = double_to_fixed (matrix->coeff[0][1]);
- trans->matrix[1][1] = double_to_fixed (matrix->coeff[1][1]);
- trans->matrix[2][1] = double_to_fixed (matrix->coeff[2][1]);
- trans->matrix[0][2] = double_to_fixed (matrix->coeff[0][2]);
- trans->matrix[1][2] = double_to_fixed (matrix->coeff[1][2]);
- trans->matrix[2][2] = double_to_fixed (matrix->coeff[2][2]);
+ trans->matrix[0][0] = double_to_fixed (matrix->coeff[0][0]);
+ trans->matrix[1][0] = double_to_fixed (matrix->coeff[1][0]);
+ trans->matrix[2][0] = double_to_fixed (matrix->coeff[2][0]);
+ trans->matrix[0][1] = double_to_fixed (matrix->coeff[0][1]);
+ trans->matrix[1][1] = double_to_fixed (matrix->coeff[1][1]);
+ trans->matrix[2][1] = double_to_fixed (matrix->coeff[2][1]);
+ trans->matrix[0][2] = double_to_fixed (matrix->coeff[0][2]);
+ trans->matrix[1][2] = double_to_fixed (matrix->coeff[1][2]);
+ trans->matrix[2][2] = double_to_fixed (matrix->coeff[2][2]);
}
gboolean
@@ -502,35 +675,35 @@ cwindow_is_translucent (CWindow *cwindow)
static XRectangle
bbox (Quad *q)
{
- int x1, x2, y1, y2;
- XRectangle result;
- int i;
-
- x2 = x1 = q->points[0].x;
- y2 = y1 = q->points[0].y;
-
- for (i = 0; i < 4; ++i)
- x1 = MIN (x1, q->points[i].x);
-
- for (i = 0; i < 4; ++i)
- y1 = MIN (y1, q->points[i].y);
-
- for (i = 0; i < 4; ++i)
- x2 = MAX (x2, q->points[i].x);
-
- for (i = 0; i < 4; ++i)
- y2 = MAX (y2, q->points[i].y);
-
- result.x = x1;
- result.y = y1;
- result.width = x2 - x1 + 1;
- result.height = y2 - y1 + 1;
-
+ int x1, x2, y1, y2;
+ XRectangle result;
+ int i;
+
+ x2 = x1 = q->points[0].x;
+ y2 = y1 = q->points[0].y;
+
+ for (i = 0; i < 4; ++i)
+ x1 = MIN (x1, q->points[i].x);
+
+ for (i = 0; i < 4; ++i)
+ y1 = MIN (y1, q->points[i].y);
+
+ for (i = 0; i < 4; ++i)
+ x2 = MAX (x2, q->points[i].x);
+
+ for (i = 0; i < 4; ++i)
+ y2 = MAX (y2, q->points[i].y);
+
+ result.x = x1;
+ result.y = y1;
+ result.width = x2 - x1 + 1;
+ result.height = y2 - y1 + 1;
+
#if 0
- g_print ("bbox: %d %d %d %d\n", result.x, result.y, result.width, result.height);
+ g_print ("bbox: %d %d %d %d\n", result.x, result.y, result.width, result.height);
#endif
-
- return result;
+
+ return result;
}
static void
@@ -539,152 +712,216 @@ compute_transform (int x, int y,
Quad *destination,
XTransform *transform)
{
- int tx, ty;
- int i;
- Quad tmp = *destination;
- Matrix3 matrix;
-
- /* Translate destination so it starts in (x, y);
- *
- * We will position it correctly with the composite request
- * Coordinates are source coordinates
- *
- * I believe this is a hackaround a bug in render transformation (basically
- * it translates source coordinates, not destination as it's supposed to).
- */
- tx = bbox (&tmp).x - x;
- ty = bbox (&tmp).y - y;
-
- for (i = 0; i < 4; ++i)
+ int tx, ty;
+ int i;
+ Quad tmp = *destination;
+ Matrix3 matrix;
+
+ /* Translate destination so it starts in (x, y);
+ *
+ * We will position it correctly with the composite request
+ * Coordinates are source coordinates
+ *
+ * I believe this is a hackaround a bug in render transformation (basically
+ * it translates source coordinates, not destination as it's supposed to).
+ */
+ tx = bbox (&tmp).x - x;
+ ty = bbox (&tmp).y - y;
+
+ for (i = 0; i < 4; ++i)
{
- tmp.points[i].x -= tx;
- tmp.points[i].y -= ty;
+ tmp.points[i].x -= tx;
+ tmp.points[i].y -= ty;
}
-
- /* Compute the matrix */
- matrix3_identity (&matrix);
-
+
+ /* Compute the matrix */
+ matrix3_identity (&matrix);
+
#if 0
- matrix3_translate (&matrix, (gdouble)-x, (gdouble)-y);
+ matrix3_translate (&matrix, (gdouble)-x, (gdouble)-y);
#endif
-
+
#if 0
- g_print ("mapping from %d %d %d %d to (%d %d) (%d %d) (%d %d) (%d %d)\n", x, y, width, height,
- tmp.points[0].x, tmp.points[0].y,
- tmp.points[1].x, tmp.points[1].y,
- tmp.points[2].x, tmp.points[2].y,
- tmp.points[3].x, tmp.points[3].y);
+ g_print ("mapping from %d %d %d %d to (%d %d) (%d %d) (%d %d) (%d %d)\n", x, y, width, height,
+ tmp.points[0].x, tmp.points[0].y,
+ tmp.points[1].x, tmp.points[1].y,
+ tmp.points[2].x, tmp.points[2].y,
+ tmp.points[3].x, tmp.points[3].y);
#endif
-
- transform_matrix_perspective (x, y,
- x + width - 1,
- y + height - 1,
-
- tmp.points[0].x, tmp.points[0].y,
- tmp.points[1].x, tmp.points[1].y,
- tmp.points[2].x, tmp.points[2].y,
- tmp.points[3].x, tmp.points[3].y,
-
- &matrix);
-
- matrix3_invert (&matrix);
-
- /* convert to XTransform */
- convert_matrix (&matrix, transform);
+
+ transform_matrix_perspective (x, y,
+ x + width - 1,
+ y + height - 1,
+
+ tmp.points[0].x, tmp.points[0].y,
+ tmp.points[1].x, tmp.points[1].y,
+ tmp.points[2].x, tmp.points[2].y,
+ tmp.points[3].x, tmp.points[3].y,
+
+ &matrix);
+
+ matrix3_invert (&matrix);
+
+ /* convert to XTransform */
+ convert_matrix (&matrix, transform);
}
static void
print_region (Display *dpy, const char *name, XserverRegion region)
{
- 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);
+ 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);
}
void
cwindow_process_damage_notify (CWindow *cwindow, XDamageNotifyEvent *event)
{
- XserverRegion region;
- MetaScreen *screen;
- MetaWindow *window;
+ MetaScreen *screen;
+ MetaWindow *window;
+
+ window = meta_display_lookup_x_window (meta_compositor_get_display (cwindow->compositor),
+ cwindow_get_xwindow (cwindow));
+ if (window)
+ g_print ("damage on %lx (%s)\n", cwindow->xwindow, window->title);
+ else
+ g_print ("damage on unknown window\n");
+
+ screen = cwindow_get_screen (cwindow);
+
+ if (cwindow->xwindow == screen->xroot)
+ g_print ("huh????\n");
+
+ if (USE_RENDER)
+ {
+ XserverRegion region;
+ region = XFixesCreateRegion (cwindow_get_xdisplay (cwindow), NULL, 0);
+
+ /* translate region to screen; can error if window of damage is
+ * destroyed
+ */
+ meta_error_trap_push (meta_compositor_get_display (cwindow->compositor));
+ XDamageSubtract (cwindow_get_xdisplay (cwindow),
+ cwindow_get_damage (cwindow), None, region);
+ meta_error_trap_pop (meta_compositor_get_display (cwindow->compositor), FALSE);
+
+ XFixesTranslateRegion (cwindow_get_xdisplay (cwindow),
+ region,
+ cwindow_get_x (cwindow),
+ cwindow_get_y (cwindow));
+
+ if (!cwindow->freeze_info)
+ {
+ meta_compositor_invalidate_region (cwindow->compositor, screen, region);
+ }
+
+ XFixesDestroyRegion (cwindow_get_xdisplay (cwindow), region);
+ /* ignore damage on frozen window */
+ }
+ else
+ {
+ XserverRegion region;
+
+ region = XFixesCreateRegion (cwindow_get_xdisplay (cwindow), NULL, 0);
+
+ meta_error_trap_push (meta_compositor_get_display (cwindow->compositor));
+#if 0
+ g_print ("cleaning damage for %lx\n", cwindow->xwindow);
+#endif
+ XDamageSubtract (cwindow_get_xdisplay (cwindow),
+ cwindow_get_damage (cwindow),
+ None,
+ region);
+ meta_error_trap_pop (meta_compositor_get_display (cwindow->compositor), FALSE);
+
+ XFixesUnionRegion (cwindow_get_xdisplay (cwindow),
+ cwindow->parts_region, cwindow->parts_region, region);
- window = meta_display_lookup_x_window (meta_compositor_get_display (cwindow->compositor),
- cwindow_get_xwindow (cwindow));
#if 0
- if (window)
- g_print ("damage on %lx (%s)\n", cwindow->xwindow, window->title);
- else
- g_print ("damage on unknown window\n");
+ print_region (cwindow_get_xdisplay (cwindow), "parts region is now", cwindow->parts_region);
#endif
- region = XFixesCreateRegion (cwindow_get_xdisplay (cwindow), NULL, 0);
-
- /* translate region to screen; can error if window of damage is
- * destroyed
- */
- meta_error_trap_push (meta_compositor_get_display (cwindow->compositor));
- XDamageSubtract (cwindow_get_xdisplay (cwindow),
- cwindow_get_damage (cwindow), None, region);
- meta_error_trap_pop (meta_compositor_get_display (cwindow->compositor), FALSE);
-
- XFixesTranslateRegion (cwindow_get_xdisplay (cwindow),
- region,
- cwindow_get_x (cwindow),
- cwindow_get_y (cwindow));
-
- screen = cwindow_get_screen (cwindow);
-
- /* ignore damage on frozen window */
- if (!cwindow->freeze_info)
- {
- meta_compositor_invalidate_region (cwindow->compositor, screen, region);
+ XFixesTranslateRegion (cwindow_get_xdisplay (cwindow),
+ region,
+ cwindow_get_x (cwindow),
+ cwindow_get_y (cwindow));
+
+ meta_compositor_invalidate_region (cwindow->compositor, screen, region);
+
+ XFixesDestroyRegion (cwindow_get_xdisplay (cwindow), region);
+
+#if 0
+ XFixesDestroyRegion (cwindow_get_xdisplay (cwindow), region);
+
+ rect.width = screen->width;
+ rect.height = screen->height;
+ rect.x = 0;
+ rect.y = 0;
+
+ region = XFixesCreateRegion (cwindow_get_xdisplay (cwindow), &rect, 1);
+
+#endif
}
-
- XFixesDestroyRegion (cwindow_get_xdisplay (cwindow), region);
}
+static void
+destroy_window_image (CWindow *cwindow);
+
void
cwindow_process_configure_notify (CWindow *cwindow, XConfigureEvent *event)
{
- MetaScreen *screen;
- int old_width, old_height;
-
- screen = cwindow_get_screen (cwindow);
-
- if (cwindow_get_last_painted_extents (cwindow) && !cwindow->freeze_info)
+ MetaScreen *screen;
+ int old_width, old_height;
+
+ screen = cwindow_get_screen (cwindow);
+
+ if (cwindow->xwindow == meta_compositor_get_gl_window (cwindow->compositor))
+ return;
+
+ if (cwindow_get_last_painted_extents (cwindow) && !cwindow->freeze_info)
{
- meta_compositor_invalidate_region (cwindow->compositor, screen, cwindow_get_last_painted_extents (cwindow));
- cwindow_set_last_painted_extents (cwindow, None);
+ meta_compositor_invalidate_region (cwindow->compositor, screen, cwindow_get_last_painted_extents (cwindow));
+ cwindow_set_last_painted_extents (cwindow, None);
+ }
+
+ cwindow_set_x (cwindow, event->x);
+ cwindow_set_y (cwindow, event->y);
+ old_width = cwindow_get_width (cwindow);
+ cwindow_set_width (cwindow, event->width);
+ old_height = cwindow_get_height (cwindow);
+ cwindow_set_height (cwindow, event->height);
+ cwindow_set_border_width (cwindow, event->border_width);
+
+ if (cwindow->freeze_info)
+ {
+ return;
+ }
+ else
+ {
+ if (old_width != cwindow_get_width (cwindow) ||
+ old_height != cwindow_get_height (cwindow))
+ {
+ if (cwindow->texture)
+ {
+ lmc_texture_unref (cwindow->texture);
+ cwindow->texture = NULL;
+ }
+
+ destroy_window_image (cwindow);
+ initialize_damage (cwindow);
+ }
+
+#if 0
+ if (USE_RENDER)
+#endif
+ cwindow_queue_paint (cwindow);
}
-
- cwindow_set_x (cwindow, event->x);
- cwindow_set_y (cwindow, event->y);
- old_width = cwindow_get_width (cwindow);
- cwindow_set_width (cwindow, event->width);
- old_height = cwindow_get_height (cwindow);
- cwindow_set_height (cwindow, event->height);
- cwindow_set_border_width (cwindow, event->border_width);
-
- if (cwindow->freeze_info)
- {
- return;
- }
- else
- {
- if (old_width != cwindow_get_width (cwindow) ||
- old_height != cwindow_get_height (cwindow))
- {
- delete_shadow (cwindow);
- }
-
- cwindow_queue_paint (cwindow);
- }
}
void
@@ -692,172 +929,387 @@ cwindow_set_transformation (CWindow *cwindow,
const Distortion *distortions,
int n_distortions)
{
- if (cwindow->distortions)
+ if (cwindow->distortions)
{
- g_free (cwindow->distortions);
- cwindow->distortions = NULL;
- cwindow->n_distortions = 0;
+ g_free (cwindow->distortions);
+ cwindow->distortions = NULL;
+ cwindow->n_distortions = 0;
}
-
- if (n_distortions)
+
+ if (n_distortions)
{
- cwindow->distortions = g_memdup (distortions, n_distortions * sizeof (Distortion));
- cwindow->n_distortions = n_distortions;
+ cwindow->distortions = g_memdup (distortions, n_distortions * sizeof (Distortion));
+ cwindow->n_distortions = n_distortions;
}
}
void
cwindow_freeze (CWindow *cwindow)
{
- if (!cwindow)
- return;
+ if (!cwindow)
+ return;
- if (cwindow->freeze_info)
+ if (cwindow->freeze_info)
{
- meta_print_backtrace();
- return;
+ meta_print_backtrace();
+ return;
}
-
- meta_error_trap_push (meta_compositor_get_display (cwindow->compositor));
-
- cwindow->freeze_info = g_new (FreezeInfo, 1);
- cwindow->freeze_info->geometry = cwindow->geometry;
-
- cwindow->freeze_info->pixmap =
- XCompositeNameWindowPixmap (cwindow_get_xdisplay (cwindow),
- cwindow->xwindow);
-
- meta_error_trap_pop (meta_compositor_get_display (cwindow->compositor), FALSE);
+
+ meta_error_trap_push (meta_compositor_get_display (cwindow->compositor));
+
+ cwindow->freeze_info = g_new (FreezeInfo, 1);
+ cwindow->freeze_info->geometry = cwindow->geometry;
+
+ cwindow->freeze_info->pixmap =
+ XCompositeNameWindowPixmap (cwindow_get_xdisplay (cwindow),
+ cwindow->xwindow);
+
+ meta_error_trap_pop (meta_compositor_get_display (cwindow->compositor), FALSE);
}
void
cwindow_thaw (CWindow *cwindow)
{
- if (!cwindow->freeze_info)
- return;
+ if (!cwindow->freeze_info)
+ return;
+
+ if (cwindow_get_last_painted_extents (cwindow))
+ {
+ meta_compositor_invalidate_region (cwindow->compositor,
+ cwindow_get_screen (cwindow),
+ cwindow_get_last_painted_extents (cwindow));
+ cwindow_set_last_painted_extents (cwindow, None);
+ }
+
+ if (!USE_RENDER)
+ {
+
+ if (cwindow->texture)
+ {
+ lmc_texture_unref (cwindow->texture);
+ cwindow->texture = NULL;
+ }
+
+ destroy_window_image (cwindow);
+ initialize_damage (cwindow);
+ }
+ else
+ {
+ if (cwindow->freeze_info->pixmap)
+ XFreePixmap (cwindow_get_xdisplay (cwindow),
+ cwindow->freeze_info->pixmap);
+ }
+
+ g_free (cwindow->freeze_info);
+ cwindow->freeze_info = NULL;
+
+ delete_shadow (cwindow);
+
+ cwindow_queue_paint (cwindow);
+}
+
+static void
+cwindow_undamage (CWindow *cwindow);
+
+
+static GdkRectangle *
+server_region_to_gdk_rects (Display *dpy, XserverRegion region, int *n_rects)
+{
+ int dummy, i;
+ XRectangle *xrects;
+ GdkRectangle *gdk_rects;
+
+ if (!n_rects)
+ n_rects = &dummy;
- if (cwindow_get_last_painted_extents (cwindow))
+ if (!region)
{
- meta_compositor_invalidate_region (cwindow->compositor, cwindow_get_screen (cwindow),
- cwindow_get_last_painted_extents (cwindow));
- cwindow_set_last_painted_extents (cwindow, None);
+ *n_rects = 0;
+ return NULL;
+ }
+
+ xrects = XFixesFetchRegion (dpy, region, n_rects);
+
+ gdk_rects = g_new (GdkRectangle, *n_rects);
+
+ for (i = 0; i < *n_rects; ++i)
+ {
+ gdk_rects[i].x = xrects[i].x;
+ gdk_rects[i].y = xrects[i].y;
+ gdk_rects[i].width = xrects[i].width;
+ gdk_rects[i].height = xrects[i].height;
+ }
+
+ return gdk_rects;
+}
+
+static void
+destroy_window_image (CWindow *cwindow)
+{
+ Display *xdisplay = cwindow_get_xdisplay (cwindow);
+
+ if (cwindow->image)
+ {
+ XShmDetach (xdisplay, &cwindow->shm_info);
+ XSync (xdisplay, False);
+
+ cwindow->image->data = NULL;
+ cwindow->image->obdata = NULL;
+ XDestroyImage (cwindow->image);
+ cwindow->image = NULL;
+
+ XFreePixmap (xdisplay, cwindow->shm_pixmap);
+ cwindow->shm_pixmap = None;
+
+ XFreeGC (xdisplay, cwindow->shm_gc);
+ cwindow->shm_gc = None;
+
+ lmc_bits_unref (cwindow->bits);
+ cwindow->bits = NULL;
}
-
-
- if (cwindow->freeze_info->pixmap)
- XFreePixmap (cwindow_get_xdisplay (cwindow),
- cwindow->freeze_info->pixmap);
-
- g_free (cwindow->freeze_info);
- cwindow->freeze_info = NULL;
-
- delete_shadow (cwindow);
-
- cwindow_queue_paint (cwindow);
}
void
-cwindow_draw (CWindow *cwindow, Picture destination)
+cwindow_draw (CWindow *cwindow,
+ Picture destination,
+ XserverRegion clip_region)
{
- XRenderPictFormat *format;
- int i;
- Picture picture;
- XRenderPictureAttributes pa;
-
- if (cwindow_get_input_only (cwindow))
- return;
-
- if (!cwindow_get_viewable (cwindow))
- return;
-
- format = XRenderFindVisualFormat (cwindow_get_xdisplay (cwindow),
- cwindow_get_visual (cwindow));
-
- pa.subwindow_mode = IncludeInferiors;
- picture = XRenderCreatePicture (cwindow_get_xdisplay (cwindow),
- cwindow_get_drawable (cwindow),
- format,
- CPSubwindowMode,
- &pa);
-
- if (cwindow->n_distortions)
+ XRenderPictFormat *format;
+ int i;
+ Picture picture;
+ XRenderPictureAttributes pa;
+
+ if (cwindow_get_input_only (cwindow))
+ return;
+
+ if (!cwindow_get_viewable (cwindow))
+ return;
+
+ if (USE_RENDER)
{
- for (i = 0; i < cwindow->n_distortions; ++i)
+ Display *xdisplay = cwindow_get_xdisplay (cwindow);
+
+ XFixesSetPictureClipRegion (xdisplay, picture, 0, 0, clip_region);
+ format = XRenderFindVisualFormat (xdisplay,
+ cwindow_get_visual (cwindow));
+
+ pa.subwindow_mode = IncludeInferiors;
+ picture = XRenderCreatePicture (xdisplay,
+ cwindow_get_drawable (cwindow),
+ format,
+ CPSubwindowMode,
+ &pa);
+
+ if (cwindow->n_distortions)
+ {
+ for (i = 0; i < cwindow->n_distortions; ++i)
+ {
+ XTransform transform;
+
+ Distortion *dist = &cwindow->distortions[i];
+ compute_transform (dist->source.x,
+ dist->source.y,
+ dist->source.width, dist->source.height,
+ &dist->destination, &transform);
+
+ /* Draw window */
+ XRenderSetPictureTransform (xdisplay, picture, &transform);
+ XRenderSetPictureFilter (xdisplay, picture, "bilinear", 0, 0);
+
+ XRenderComposite (xdisplay,
+ PictOpOver, /* PictOpOver for alpha, PictOpSrc without */
+ picture,
+ cwindow_get_screen (cwindow)->trans_picture,
+ destination,
+ dist->source.x, dist->source.y,
+ 0, 0,
+ bbox (&dist->destination).x, bbox (&dist->destination).y,
+ bbox (&dist->destination).width, bbox (&dist->destination).height);
+ }
+ }
+ else
{
- XTransform transform;
-
- Distortion *dist = &cwindow->distortions[i];
- compute_transform (dist->source.x,
- dist->source.y,
- dist->source.width, dist->source.height,
- &dist->destination, &transform);
-
- /* Draw window */
- XRenderSetPictureTransform (cwindow_get_xdisplay (cwindow), picture, &transform);
- XRenderSetPictureFilter (cwindow_get_xdisplay (cwindow), picture, "bilinear", 0, 0);
-
- XRenderComposite (cwindow_get_xdisplay (cwindow),
- PictOpOver, /* PictOpOver for alpha, PictOpSrc without */
- picture,
- cwindow_get_screen (cwindow)->trans_picture,
- destination,
- dist->source.x, dist->source.y,
- 0, 0,
- bbox (&dist->destination).x, bbox (&dist->destination).y,
- bbox (&dist->destination).width, bbox (&dist->destination).height);
+ Display *dpy = xdisplay;
+ Geometry *geometry = cwindow->freeze_info?
+ &cwindow->freeze_info->geometry :
+ &cwindow->geometry;
+
+ XserverRegion shadow_clip;
+ XserverRegion old_clip = XFixesCreateRegionFromPicture (dpy, destination);
+
+ shadow_clip = cwindow_get_opaque_region (cwindow);
+
+ XFixesSubtractRegion (dpy, shadow_clip, old_clip, shadow_clip);
+
+ XFixesSetPictureClipRegion (dpy, destination, 0, 0, shadow_clip);
+
+ if (!cwindow->translucent && !cwindow_has_alpha (cwindow))
+ {
+ create_shadow (cwindow);
+
+ XRenderComposite (xdisplay, PictOpOver,
+ cwindow->shadow, None, destination,
+ 0, 0,
+ 0, 0,
+ geometry->x + SHADOW_OFFSET, geometry->y,
+ cwindow->shadow_width, cwindow->shadow_height);
+ }
+
+ XFixesSetPictureClipRegion (dpy, destination, 0, 0, old_clip);
+
+ XRenderComposite (xdisplay,
+ PictOpOver, /* PictOpOver for alpha, PictOpSrc without */
+ picture,
+ cwindow->translucent? cwindow_get_screen (cwindow)->trans_picture : None,
+ destination,
+ 0, 0, 0, 0,
+ geometry->x,
+ geometry->y,
+ geometry->width,
+ geometry->height);
+
+ XFixesDestroyRegion (dpy, old_clip);
+ XFixesDestroyRegion (dpy, shadow_clip);
}
}
- else
+ else
{
- Display *dpy = cwindow_get_xdisplay (cwindow);
- Geometry *geometry = cwindow->freeze_info?
+ GdkRectangle *rects;
+ int n_rects;
+ GdkRegion *gdk_clip_region;
+
+ Geometry *geometry = cwindow->freeze_info?
+ &cwindow->freeze_info->geometry :
+ &cwindow->geometry;
+
+#if 0
+ g_print ("drawing: %lx\n", cwindow->xwindow);
+#endif
+
+ cwindow_undamage (cwindow);
+
+ if (!cwindow->texture)
+ {
+ cwindow->texture = lmc_texture_new (cwindow->bits);
+ }
+
+ g_assert (cwindow->texture);
+
+ rects = server_region_to_gdk_rects (cwindow_get_xdisplay (cwindow),
+ clip_region, &n_rects);
+
+ gdk_clip_region = gdk_region_new ();
+
+ for (i = 0; i < n_rects; ++i)
+ gdk_region_union_with_rect (gdk_clip_region, &rects[i]);
+
+ if (rects)
+ {
+ gdk_region_offset (gdk_clip_region, -geometry->x, -geometry->y);
+ lmc_texture_draw (cwindow->texture, 1.0, geometry->x, geometry->y, gdk_clip_region);
+ gdk_region_offset (gdk_clip_region, geometry->x, geometry->y);
+ }
+ else
+ lmc_texture_draw (cwindow->texture, 1.0, geometry->x, geometry->y, NULL);
+
+ gdk_region_destroy (gdk_clip_region);
+ }
+
+ if (cwindow_get_last_painted_extents (cwindow))
+ cwindow_destroy_last_painted_extents (cwindow);
+
+ cwindow_set_last_painted_extents (cwindow, cwindow_extents (cwindow));
+
+ if (USE_RENDER)
+ XRenderFreePicture (cwindow_get_xdisplay (cwindow), picture);
+}
+
+
+static void
+cwindow_undamage (CWindow *cwindow)
+{
+ Display *xdisplay = cwindow_get_xdisplay (cwindow);
+ Window xwindow = cwindow->xwindow;
+ gboolean get_all;
+ Geometry *geometry = cwindow->freeze_info?
&cwindow->freeze_info->geometry :
&cwindow->geometry;
-
- XserverRegion shadow_clip;
- XserverRegion old_clip = XFixesCreateRegionFromPicture (dpy, destination);
-
- shadow_clip = cwindow_get_opaque_region (cwindow);
-
- XFixesSubtractRegion (dpy, shadow_clip, old_clip, shadow_clip);
-
- XFixesSetPictureClipRegion (dpy, destination, 0, 0, shadow_clip);
-
- if (!cwindow->translucent && !cwindow_has_alpha (cwindow))
- {
- create_shadow (cwindow);
-
- XRenderComposite (cwindow_get_xdisplay (cwindow), PictOpOver,
- cwindow->shadow, None, destination,
- 0, 0,
- 0, 0,
- geometry->x + SHADOW_OFFSET, geometry->y,
- cwindow->shadow_width, cwindow->shadow_height);
- }
-
- XFixesSetPictureClipRegion (dpy, destination, 0, 0, old_clip);
-
- XRenderComposite (cwindow_get_xdisplay (cwindow),
- PictOpOver, /* PictOpOver for alpha, PictOpSrc without */
- picture,
- cwindow->translucent? cwindow_get_screen (cwindow)->trans_picture : None,
- destination,
- 0, 0, 0, 0,
- geometry->x,
- geometry->y,
- geometry->width,
- geometry->height);
-
- XFixesDestroyRegion (dpy, old_clip);
- XFixesDestroyRegion (dpy, shadow_clip);
+
+ if (!cwindow->image)
+ return;
+
+ if (cwindow->input_only)
+ return;
+
+ if (!cwindow->viewable)
+ return;
+
+ /* If we've already undamaged at least once at this size, just get the
+ * part that changed. Otherwise, we get everything.
+ */
+ get_all = cwindow->damage_serial == 0;
+ cwindow->damage_serial = NextRequest (xdisplay);
+
+ /* Window could go away at any point */
+ if (cwindow->damage)
+ {
}
-
- if (cwindow_get_last_painted_extents (cwindow))
- cwindow_destroy_last_painted_extents (cwindow);
-
- cwindow_set_last_painted_extents (cwindow, cwindow_extents (cwindow));
-
- XRenderFreePicture (cwindow_get_xdisplay (cwindow), picture);
+ else
+ g_print ("No damage\n");
+
+#if 0
+ get_all = TRUE;
+#endif
+
+ if (get_all)
+ {
+ if (cwindow->texture)
+ {
+ lmc_texture_unref (cwindow->texture);
+ cwindow->texture = NULL;
+ }
+
+ destroy_window_image (cwindow);
+ create_window_image (cwindow);
+ }
+
+ if (!get_all)
+ XFixesSetGCClipRegion (xdisplay, cwindow->shm_gc,
+ 0, 0, cwindow->parts_region);
+ else
+ XFixesSetGCClipRegion (xdisplay, cwindow->shm_gc,
+ 0, 0, None);
+
+#if 0
+ g_print ("copying: %lx\n", cwindow->xwindow);
+#endif
+ XCopyArea (xdisplay,
+ cwindow_get_drawable (cwindow),
+ cwindow->shm_pixmap,
+ cwindow->shm_gc,
+ 0, 0,
+ geometry->width, geometry->height,
+ 0, 0);
+
+ XSync (xdisplay, False);
+
+ if (!get_all && cwindow->texture)
+ {
+ GdkRectangle *rects;
+ int n_rects, i;
+
+ rects = server_region_to_gdk_rects (cwindow_get_xdisplay (cwindow),
+ cwindow->parts_region, &n_rects);
+
+ for (i = 0; i < n_rects; ++i)
+ {
+ lmc_texture_update_rect (cwindow->texture, &(rects[i]));
+
+ }
+ }
+
+ XFixesDestroyRegion (cwindow_get_xdisplay (cwindow), cwindow->parts_region);
+ cwindow->parts_region = XFixesCreateRegion (cwindow_get_xdisplay (cwindow), 0, 0);
}
@@ -933,7 +1385,7 @@ make_gaussian_map (Display *dpy, double r)
* height+ | | | |
* center +-----+-------------------+-----+
*/
-
+
static unsigned char
sum_gaussian (conv *map, double opacity, int x, int y, int width, int height)
{
@@ -955,21 +1407,21 @@ sum_gaussian (conv *map, double opacity, int x, int y, int width, int height)
* 0 <= x + (fx - center) x + fx - center < width
* center - x <= fx fx < width + center - x
*/
-
+
fx_start = center - x;
if (fx_start < 0)
fx_start = 0;
fx_end = width + center - x;
if (fx_end > g_size)
fx_end = g_size;
-
+
fy_start = center - y;
if (fy_start < 0)
fy_start = 0;
fy_end = height + center - y;
if (fy_end > g_size)
fy_end = g_size;
-
+
g_line = g_line + fy_start * g_size + fx_start;
v = 0;
@@ -993,14 +1445,14 @@ presum_gaussian (conv *map)
{
int center = map->size/2;
int opacity, x, y;
-
+
Gsize = map->size;
-
+
if (shadowCorner)
g_free ((void *)shadowCorner);
if (shadowTop)
g_free ((void *)shadowTop);
-
+
shadowCorner = (unsigned char *)(g_malloc ((Gsize + 1) * (Gsize + 1) * 26));
shadowTop = (unsigned char *)(g_malloc ((Gsize + 1) * 26));
@@ -1055,7 +1507,7 @@ make_shadow (Display *dpy, double opacity, int width, int height)
/*
* Build the gaussian in sections
*/
-
+
/*
* center (fill the complete data array)
*/
@@ -1074,7 +1526,7 @@ make_shadow (Display *dpy, double opacity, int width, int height)
xlimit = gsize;
if (xlimit > swidth / 2)
xlimit = (swidth + 1) / 2;
-
+
for (y = 0; y < ylimit; y++)
for (x = 0; x < xlimit; x++)
{
@@ -1087,7 +1539,7 @@ make_shadow (Display *dpy, double opacity, int width, int height)
data[(sheight - y - 1) * swidth + (swidth - x - 1)] = d;
data[y * swidth + (swidth - x - 1)] = d;
}
-
+
/*
* top/bottom
*/
@@ -1104,7 +1556,7 @@ make_shadow (Display *dpy, double opacity, int width, int height)
memset (&data[(sheight - y - 1) * swidth + gsize], d, x_diff);
}
}
-
+
/*
* sides
*/
@@ -1121,7 +1573,7 @@ make_shadow (Display *dpy, double opacity, int width, int height)
data[y * swidth + (swidth - x - 1)] = d;
}
}
-
+
return ximage;
}
@@ -1139,7 +1591,7 @@ shadow_picture (Display *dpy, Window root,
gaussianMap = make_gaussian_map(dpy, SHADOW_RADIUS);
presum_gaussian (gaussianMap);
}
-
+
shadowImage = make_shadow (dpy, opacity, width, height);
if (!shadowImage)
return None;
@@ -1152,7 +1604,7 @@ shadow_picture (Display *dpy, Window root,
XDestroyImage (shadowImage);
return None;
}
-
+
shadowPicture = XRenderCreatePicture (dpy, shadowPixmap,
XRenderFindStandardFormat (dpy, PictStandardA8),
0, 0);
@@ -1162,7 +1614,7 @@ shadow_picture (Display *dpy, Window root,
XFreePixmap (dpy, shadowPixmap);
return None;
}
-
+
gc = XCreateGC (dpy, shadowPixmap, 0, 0);
if (!gc)
{
diff --git a/src/cwindow.h b/src/cwindow.h
index a31e213c..b2224faf 100644
--- a/src/cwindow.h
+++ b/src/cwindow.h
@@ -5,6 +5,8 @@
#include <glib.h>
#include "screen.h"
+#define USE_RENDER 0
+
typedef struct CWindow CWindow;
typedef struct Quad Quad;
typedef struct Point Point;
@@ -98,7 +100,8 @@ void cwindow_process_damage_notify (CWindow *cwindo
void cwindow_process_configure_notify (CWindow *cwindow,
XConfigureEvent *event);
void cwindow_draw (CWindow *cwindow,
- Picture destination);
+ Picture destination,
+ XserverRegion clip);
void cwindow_freeze (CWindow *cwindow);
void cwindow_thaw (CWindow *cwindow);
void cwindow_set_translucent (CWindow *cwindow, gboolean translucent);
diff --git a/src/lmcbits.c b/src/lmcbits.c
new file mode 100644
index 00000000..88fa99c3
--- /dev/null
+++ b/src/lmcbits.c
@@ -0,0 +1,93 @@
+#include "lmcbits.h"
+
+LmcBits *
+lmc_bits_new (LmcBitsFormat format,
+ int width,
+ int height,
+ guchar *data,
+ int rowstride,
+ GDestroyNotify notify,
+ gpointer notify_data)
+{
+ LmcBits *bits = g_new0 (LmcBits, 1);
+
+ bits->ref_count = 1;
+
+ bits->format = format;
+ bits->width = width;
+ bits->height = height;
+ bits->data_ = data;
+ bits->rowstride = rowstride;
+ bits->notify = notify;
+ bits->notify_data = notify_data;
+
+ return bits;
+}
+
+LmcBits *
+lmc_bits_new_from_pixbuf (GdkPixbuf *pixbuf)
+{
+ return lmc_bits_new (gdk_pixbuf_get_has_alpha (pixbuf) ? LMC_BITS_RGBA_MSB_32 : LMC_BITS_RGB_24,
+ gdk_pixbuf_get_width (pixbuf),
+ gdk_pixbuf_get_height (pixbuf),
+ gdk_pixbuf_get_pixels (pixbuf),
+ gdk_pixbuf_get_rowstride (pixbuf),
+ (GDestroyNotify)g_object_unref,
+ g_object_ref (pixbuf));
+}
+
+LmcBits *
+lmc_bits_ref (LmcBits *bits)
+{
+ g_atomic_int_inc (&bits->ref_count);
+
+ return bits;
+}
+
+void
+lmc_bits_unref (LmcBits *bits)
+{
+ if (g_atomic_int_dec_and_test (&bits->ref_count))
+ {
+ if (bits->notify)
+ bits->notify (bits->notify_data);
+
+ g_free (bits);
+ }
+}
+
+
+guchar *
+lmc_bits_lock (LmcBits *bits)
+{
+ guchar *result;
+
+ result = bits->data_;
+
+ return result;
+}
+
+void
+lmc_bits_unlock (LmcBits *bits)
+{
+}
+
+gboolean
+lmc_bits_has_alpha (LmcBits *bits)
+{
+ switch (bits->format)
+ {
+ case LMC_BITS_RGB_16:
+ return FALSE;
+ case LMC_BITS_RGB_24:
+ return FALSE;
+ case LMC_BITS_RGB_32:
+ return FALSE;
+ case LMC_BITS_RGBA_MSB_32:
+ return TRUE;
+ case LMC_BITS_ARGB_32:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
diff --git a/src/lmcbits.h b/src/lmcbits.h
new file mode 100644
index 00000000..76b8a954
--- /dev/null
+++ b/src/lmcbits.h
@@ -0,0 +1,54 @@
+#ifndef __LMC_BITS_H__
+#define __LMC_BITS_H__
+
+#include <glib.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
+G_BEGIN_DECLS
+
+typedef struct _LmcBits LmcBits;
+
+typedef enum {
+ LMC_BITS_RGB_16,
+ LMC_BITS_RGB_24,
+ LMC_BITS_RGB_32,
+ LMC_BITS_RGBA_MSB_32,
+ LMC_BITS_ARGB_32
+} LmcBitsFormat;
+
+struct _LmcBits
+{
+ int ref_count;
+
+ LmcBitsFormat format;
+ int width;
+ int height;
+ int rowstride;
+
+ GDestroyNotify notify;
+ gpointer notify_data;
+
+ guchar *data_;
+};
+
+LmcBits *lmc_bits_new (LmcBitsFormat format,
+ int width,
+ int height,
+ guchar *data,
+ int rowstride,
+ GDestroyNotify notify,
+ gpointer notify_data);
+
+LmcBits *lmc_bits_new_from_pixbuf (GdkPixbuf *pixbuf);
+
+LmcBits *lmc_bits_ref (LmcBits *bits);
+void lmc_bits_unref (LmcBits *bits);
+
+guchar *lmc_bits_lock (LmcBits *bits);
+void lmc_bits_unlock (LmcBits *bits);
+
+gboolean lmc_bits_has_alpha (LmcBits *bits);
+
+G_END_DECLS
+
+#endif /* __LMC_BITS_H__ */
diff --git a/src/lmctexture.c b/src/lmctexture.c
new file mode 100644
index 00000000..cdc51669
--- /dev/null
+++ b/src/lmctexture.c
@@ -0,0 +1,777 @@
+#include "lmctexture.h"
+#include <string.h>
+#include <GL/glu.h>
+
+typedef struct Tile Tile;
+
+struct Tile
+{
+ GdkRectangle geometry;
+ GLuint texture;
+};
+
+struct _LmcTexture
+{
+ /*< private >*/
+ int ref_count;
+
+ LmcBits *bits;
+
+ GList *tiles;
+};
+
+static int
+get_max_texture_width (void)
+{
+ return 512;
+ return GL_MAX_TEXTURE_SIZE;
+}
+
+static int
+get_max_texture_height (void)
+{
+ return 512;
+ return GL_MAX_TEXTURE_SIZE;
+}
+
+static void
+dump_error (const char *context)
+{
+ /* glGetError() is a server roundtrip */
+ GLenum err;
+
+ err = glGetError ();
+ if (err != GL_NO_ERROR)
+ {
+ const GLubyte *message = gluErrorString (err);
+ g_warning ("GL Error: %s [at %s]\n", message, context);
+ }
+}
+
+static int
+power_of_two_less_than_or_equal (int v)
+{
+ int t = 1;
+
+#if 0
+ g_print ("input: %d\n", v);
+#endif
+
+ g_return_val_if_fail (v >= 1, -1);
+
+ while (t <= v)
+ t *= 2;
+
+ t /= 2;
+
+#if 0
+ g_print ("output: %d\n", t);
+#endif
+
+ return t;
+}
+
+static GList *
+get_tile_sizes (int width, int height)
+{
+ GList *l1, *l2;
+ GList *vertical, *horizontal, *tile_sizes;
+ int x, y;
+ int max_texture_width;
+ int max_texture_height;
+
+ g_return_val_if_fail (width > 0, NULL);
+ g_return_val_if_fail (height > 0, NULL);
+
+ max_texture_width = get_max_texture_width ();
+ max_texture_height = get_max_texture_height ();
+
+#if 0
+ g_print ("maxw, maxh: %d %d\n", max_texture_width,
+ max_texture_height);
+#endif
+
+ horizontal = NULL;
+ while (width)
+ {
+ int t = power_of_two_less_than_or_equal (MIN (width, max_texture_width));
+
+ horizontal = g_list_prepend (horizontal, GINT_TO_POINTER (t));
+
+ width -= t;
+ }
+
+ vertical = NULL;
+ while (height)
+ {
+ int t = power_of_two_less_than_or_equal (MIN (height, max_texture_height));
+
+ vertical = g_list_prepend (vertical, GINT_TO_POINTER (t));
+
+ height -= t;
+ }
+
+ tile_sizes = NULL;
+ x = 0;
+ for (l1 = horizontal; l1 != NULL; l1 = l1->next)
+ {
+ y = 0;
+ for (l2 = vertical; l2 != NULL; l2 = l2->next)
+ {
+ GdkRectangle *rect = g_new0 (GdkRectangle, 1);
+
+ rect->width = GPOINTER_TO_INT (l1->data);
+ rect->height = GPOINTER_TO_INT (l2->data);
+ rect->x = x;
+ rect->y = y;
+
+ tile_sizes = g_list_prepend (tile_sizes, rect);
+
+ y += GPOINTER_TO_INT (l2->data);
+ }
+
+ x += GPOINTER_TO_INT (l1->data);
+ }
+
+ g_list_free (horizontal);
+ g_list_free (vertical);
+
+ return tile_sizes;
+}
+
+static guchar *
+create_buffer (LmcBits *bits,
+ GdkRectangle *rect)
+{
+ guchar *buffer = g_malloc (4 * rect->width * rect->height);
+ int i, j;
+ int bpp;
+
+ switch (bits->format)
+ {
+ case LMC_BITS_RGB_16:
+ bpp = 2;
+ break;
+ case LMC_BITS_RGB_24:
+ bpp = 3;
+ break;
+ case LMC_BITS_RGB_32:
+ case LMC_BITS_RGBA_MSB_32:
+ case LMC_BITS_ARGB_32:
+ bpp = 4;
+ break;
+ default:
+ g_assert_not_reached ();
+ bpp = 4;
+ break;
+ }
+
+ for (j = 0; j < rect->height; j++)
+ {
+ guchar *src;
+ guint32 *dest;
+ gint src_max;
+
+ dest = (guint32 *)buffer + rect->width * j;
+
+ if (j + rect->y >= bits->height)
+ {
+ memset (dest, 0, rect->width * 4);
+ continue;
+ }
+
+ src = bits->data_ + bits->rowstride * (j + rect->y) + bpp * rect->x;
+ src_max = MIN (rect->width, bits->width - rect->x);
+
+ for (i = 0; i < src_max; i++)
+ {
+ guchar r,g,b,a;
+
+ switch (bits->format)
+ {
+ case LMC_BITS_RGB_16:
+ {
+ guint16 t = *(guint16 *)src;
+ guint tr, tg, tb;
+
+ tr = t & 0xf800;
+ r = (tr >> 8) + (tr >> 13);
+
+ tg = t & 0x07e0;
+ g = (tg >> 3) + (tg >> 9);
+
+ tb = t & 0x001f;
+ b = (tb << 3) + (tb >> 2);
+
+ a = 0xff;
+ }
+ break;
+ case LMC_BITS_RGB_24:
+ r = src[0];
+ g = src[1];
+ b = src[2];
+ a = 0xff;
+ break;
+ case LMC_BITS_RGB_32:
+ {
+ guint32 t = *(guint32 *)src;
+ r = (t >> 16) & 0xff;
+ g = (t >> 8) & 0xff;
+ b = t & 0xff;
+ a = 0xff;
+ }
+ break;
+ case LMC_BITS_RGBA_MSB_32:
+ {
+ guint tr, tg, tb;
+
+ a = src[3];
+ tr = src[0] * a + 0x80;
+ r = (tr + (tr >> 8)) >> 8;
+ tg = src[1] * a + 0x80;
+ g = (tg + (tg >> 8)) >> 8;
+ tb = src[2] * a + 0x80;
+ b = (tb + (tb >> 8)) >> 8;
+ }
+ break;
+ case LMC_BITS_ARGB_32:
+ {
+ guint32 t = *(guint32 *)src;
+ r = (t >> 16) & 0xff;
+ g = (t >> 8) & 0xff;
+ b = t & 0xff;
+ a = t >> 24;
+ }
+ break;
+ default:
+ g_assert_not_reached();
+ r = g = b = a = 0; /* Quiet GCC */
+ break;
+ }
+
+ *dest = (a << 24) | (r << 16) | (g << 8) | b;
+
+ src += bpp;
+ dest++;
+ }
+
+ for (; i < rect->width; i++)
+ {
+ *dest = 0;
+ dest++;
+ }
+ }
+
+ return buffer;
+}
+
+static GLuint
+allocate_texture_name (void)
+{
+ GLuint name;
+ glGenTextures (1, &name);
+ return name;
+}
+
+static Tile *
+tile_new (LmcBits *bits,
+ GdkRectangle *tile_geometry)
+{
+ Tile *tile = g_new (Tile, 1);
+ guchar *buffer;
+
+ tile->geometry = *tile_geometry;
+ tile->texture = allocate_texture_name ();
+
+#if 0
+ g_print ("allocated %p (%d)\n", tile, tile->texture);
+#endif
+
+ buffer = create_buffer (bits, tile_geometry);
+
+#if 0
+ g_print ("%x\n", *(int *)buffer);
+#endif
+
+ glBindTexture (GL_TEXTURE_2D, tile->texture);
+
+ dump_error ("TexImage2D");
+
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ dump_error ("TexImage2D");
+
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ dump_error ("TexImage2D");
+
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ dump_error ("TexImage2D");
+
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ dump_error ("TexImage2D");
+
+ glPixelStorei (GL_UNPACK_ROW_LENGTH, tile->geometry.width);
+ dump_error ("TexImage2D");
+
+ glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
+
+ dump_error ("TexImage2D");
+
+ glTexImage2D (GL_TEXTURE_2D, 0 /* level */, GL_RGBA,
+ tile->geometry.width, tile->geometry.height, 0 /* border */,
+ GL_BGRA, GL_UNSIGNED_BYTE, buffer);
+
+ dump_error ("TexImage2D");
+
+ g_free (buffer);
+
+ return tile;
+}
+
+static void
+tile_free (Tile *tile)
+{
+#if 0
+ g_print ("deleting %p, %d\n", tile, tile->texture);
+#endif
+ glDeleteTextures (1, &(tile->texture));
+
+ g_free (tile);
+}
+
+static GList *
+load_bits (LmcBits *bits)
+{
+ GList *tile_sizes = get_tile_sizes (bits->width, bits->height);
+ GList *list, *tiles = NULL;
+
+ for (list = tile_sizes; list != NULL; list = list->next)
+ {
+ GdkRectangle *tile_size = list->data;
+
+ Tile *tile = tile_new (bits, tile_size);
+
+ tiles = g_list_prepend (tiles, tile);
+ }
+
+ for (list = tile_sizes; list != NULL; list = list->next)
+ g_free (list->data);
+ g_list_free (tile_sizes);
+
+ return tiles;
+}
+
+LmcTexture*
+lmc_texture_new (LmcBits *bits)
+{
+ LmcTexture *texture;
+
+ g_return_val_if_fail (bits != NULL, NULL);
+
+ texture = g_new0 (LmcTexture, 1);
+
+ texture->bits = lmc_bits_ref (bits);
+
+ texture->tiles = load_bits (bits);
+
+ texture->ref_count = 1;
+
+ return texture;
+}
+
+LmcTexture*
+lmc_texture_ref (LmcTexture *texture)
+{
+ texture->ref_count++;
+ return texture;
+}
+
+void
+lmc_texture_unref (LmcTexture *texture)
+{
+ if (--texture->ref_count == 0)
+ {
+ GList *list;
+
+ lmc_bits_unref (texture->bits);
+
+ for (list = texture->tiles; list != NULL; list = list->next)
+ tile_free (list->data);
+
+ g_list_free (texture->tiles);
+
+ g_free (texture);
+ }
+ else
+ g_print ("new value: %d\n", texture->ref_count);
+}
+
+#if 0
+static gboolean
+xrect_intersect (const XRectangle *src1, const XRectangle *src2, XRectangle *dest)
+{
+ gint dest_x, dest_y;
+ gint dest_w, dest_h;
+ gint return_val;
+
+ g_return_val_if_fail (src1 != NULL, FALSE);
+ g_return_val_if_fail (src2 != NULL, FALSE);
+ g_return_val_if_fail (dest != NULL, FALSE);
+
+ return_val = FALSE;
+
+ dest_x = MAX (src1->x, src2->x);
+ dest_y = MAX (src1->y, src2->y);
+ dest_w = MIN (src1->x + src1->width, src2->x + src2->width) - dest_x;
+ dest_h = MIN (src1->y + src1->height, src2->y + src2->height) - dest_y;
+
+ if (dest_w > 0 && dest_h > 0)
+ {
+ dest->x = dest_x;
+ dest->y = dest_y;
+ dest->width = dest_w;
+ dest->height = dest_h;
+ return_val = TRUE;
+ }
+ else
+ {
+ dest->width = 0;
+ dest->height = 0;
+ }
+
+ return return_val;
+}
+#endif
+
+void
+lmc_texture_update_rect (LmcTexture *texture,
+ GdkRectangle *rect)
+{
+ GList *list;
+
+ for (list = texture->tiles; list != NULL; list = list->next)
+ {
+ Tile *tile = list->data;
+ GdkRectangle intersection;
+
+ if (gdk_rectangle_intersect (&(tile->geometry), rect, &intersection))
+ {
+ guchar *buffer;
+#if 0
+ int i;
+#endif
+
+ glBindTexture (GL_TEXTURE_2D, tile->texture);
+
+ buffer = create_buffer (texture->bits, &intersection);
+
+#if 0
+ for (i = 0; i < 4 * intersection.width * intersection.height; ++i)
+ buffer[i] = g_random_int ();
+#endif
+
+#if 0
+ g_print ("updating %d %d %d %d\n",
+ intersection.x, intersection.y, intersection.width, intersection.height);
+#endif
+
+ intersection.x -= tile->geometry.x;
+ intersection.y -= tile->geometry.y;
+
+#if 0
+ g_print ("tile %d %d %d %d\n",
+ tile->geometry.x, tile->geometry.y, tile->geometry.width, tile->geometry.height);
+#endif
+
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ dump_error ("TexImage2D");
+
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ dump_error ("TexImage2D");
+
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ dump_error ("TexImage2D");
+
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ dump_error ("TexImage2D");
+
+ glPixelStorei (GL_UNPACK_ROW_LENGTH, intersection.width);
+ dump_error ("TexImage2D");
+
+ glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
+
+ glTexSubImage2D (GL_TEXTURE_2D, 0,
+ intersection.x,
+ intersection.y,
+ intersection.width,
+ intersection.height,
+ GL_BGRA, GL_UNSIGNED_BYTE,
+ buffer);
+
+ dump_error ("glTexSubImage2D");
+
+ g_free (buffer);
+ }
+ }
+}
+
+static void
+set_clip_region (GdkRegion *region, int x, int y)
+{
+
+ GdkRectangle *rects;
+ int n_rects, i;
+
+ /* clear stencil buffer */
+ glClearStencil (0);
+ glClear (GL_STENCIL_BUFFER_BIT);
+ glStencilFunc (GL_NEVER, 1, 1);
+
+ glEnable (GL_STENCIL_TEST);
+
+ glStencilOp (GL_REPLACE, GL_REPLACE, GL_REPLACE);
+
+ /* draw region to stencil buffer */
+
+ gdk_region_offset (region, x, y);
+
+ gdk_region_get_rectangles (region, &rects, &n_rects);
+
+ glDisable (GL_TEXTURE_2D);
+ for (i = 0; i < n_rects; ++i)
+ {
+ glBegin(GL_QUADS);
+
+ glVertex3i (rects[i].x, rects[i].y, 0);
+ glVertex3i (rects[i].x + rects[i].width, rects[i].y, 0);
+ glVertex3i (rects[i].x + rects[i].width, rects[i].y + rects[i].height, 0);
+ glVertex3i (rects[i].x, rects[i].y + rects[i].height, 0);
+
+ glEnd ();
+ }
+
+ g_free (rects);
+
+ gdk_region_offset (region, -x, -y);
+
+ glStencilFunc (GL_EQUAL, 0x1, 0x1);
+ glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP);
+
+ glEnable (GL_TEXTURE_2D);
+}
+
+static void
+unset_clip_region ()
+{
+ glDisable (GL_STENCIL_TEST);
+}
+
+static gboolean
+region_intersects_rect (GdkRegion *region, GdkRectangle *rect)
+{
+ return (gdk_region_rect_in (region, rect) != GDK_OVERLAP_RECTANGLE_OUT);
+
+}
+
+static void
+print_gdk_region (const char *name, GdkRegion *region)
+{
+ GdkRectangle *rects;
+ int i, n_rects;
+
+ gdk_region_get_rectangles (region, &rects, &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);
+ g_free (rects);
+}
+
+/**
+ * lmc_texture_draw:
+ * @texture:
+ * @alpha:
+ * @x:
+ * @y:
+ * @clip:
+ *
+ * Draw the texture, the clip is in window coordinates.
+ **/
+void
+lmc_texture_draw (LmcTexture *texture,
+ double alpha,
+ int x,
+ int y,
+ GdkRegion *clip)
+{
+ GList *list;
+
+ glPushAttrib (GL_TEXTURE_BIT);
+ glEnable (GL_TEXTURE_2D);
+ glDisable (GL_LIGHTING);
+
+ dump_error ("gldisable light");
+
+ /* Setup alhpa */
+
+ glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable (GL_BLEND);
+
+#if 0
+ glShadeModel(GL_SMOOTH);
+#endif
+ dump_error ("glenable");
+
+ g_assert (glIsEnabled (GL_TEXTURE_2D));
+
+#if 0
+ g_print ("alpha %f\n", alpha);
+#endif
+
+ set_clip_region (clip, x, y);
+
+#if 0
+ glColor4f (g_random_double(),
+ g_random_double(),
+ g_random_double(), 0.3);
+
+ glBegin (GL_QUADS);
+
+ glVertex3i (0, 0, 0);
+ glVertex3i (1600, 0, 0);
+ glVertex3i (1600, 1200, 0);
+ glVertex3i (0, 1200, 0);
+
+ glEnd ();
+
+ goto out;
+#endif
+
+ glColor4f (1.0, 1.0, 1.0, alpha);
+
+ /* Emit quads */
+ for (list = texture->tiles; list != NULL; list = list->next)
+ {
+ Tile *tile = list->data;
+
+ if ((!clip || region_intersects_rect (clip, &tile->geometry)))
+ {
+ int translated_x = tile->geometry.x + x;
+ int translated_y = tile->geometry.y + y;
+
+ glBindTexture (GL_TEXTURE_2D, tile->texture);
+#if 0
+ g_print ("bound %p, %d\n", tile, tile->texture);
+#endif
+
+ dump_error ("glbindtexture");
+
+ glBegin (GL_QUADS);
+
+ /* corner 1 */
+#if 0
+ glColor4f (1.0, 0.2, 0.2, alpha);
+#endif
+ glTexCoord2f (0.0, 0.0);
+ glVertex3i (translated_x, translated_y, 0);
+
+ /* corner 2 */
+#if 0
+ glColor4f (0.0, 0.4, 0.2, alpha);
+#endif
+ glTexCoord2f (1.0, 0.0);
+ glVertex3i (translated_x + tile->geometry.width, translated_y, 0);
+
+ /* corner 3 */
+#if 0
+ glColor4f (0.0, 0.2, 0.8, alpha);
+#endif
+ glTexCoord2f (1.0, 1.0);
+ glVertex3i (translated_x + tile->geometry.width, translated_y + tile->geometry.height, 0);
+
+ /* corner 4 */
+#if 0
+ glColor4f (0.8, 0.8, 0.0, alpha);
+#endif
+ glTexCoord2f (0.0, 1.0);
+ glVertex3i (translated_x, translated_y + tile->geometry.height, 0);
+
+ glEnd ();
+ dump_error ("glEnd");
+
+ unset_clip_region ();
+
+ glColor4f (0.8, 0.0, 0.8, 0.2);
+
+ glDisable (GL_TEXTURE_2D);
+ glBegin (GL_QUADS);
+ glVertex3i (translated_x, translated_y, 0);
+ glVertex3i (translated_x + tile->geometry.width, translated_y, 0);
+ glVertex3i (translated_x + tile->geometry.width,
+ translated_y + tile->geometry.height, 0);
+ glVertex3i (translated_x, translated_y + tile->geometry.height, 0);
+ glEnd ();
+ glEnable (GL_TEXTURE_2D);
+
+ set_clip_region (clip, x, y);
+ glColor4f (1.0, 1.0, 1.0, alpha);
+ }
+
+ else
+ {
+#if 0
+ int translated_x = tile->geometry.x + x;
+ int translated_y = tile->geometry.y + y;
+
+ print_gdk_region ("clip", clip);
+
+ glColor4f (g_random_double(),
+ g_random_double(),
+ g_random_double(), 0.2);
+
+ glDisable (GL_TEXTURE_2D);
+ glBegin (GL_QUADS);
+ glVertex3i (translated_x, translated_y, 0);
+ glVertex3i (translated_x + tile->geometry.width, translated_y, 0);
+ glVertex3i (translated_x + tile->geometry.width,
+ translated_y + tile->geometry.height, 0);
+ glVertex3i (translated_x, translated_y + tile->geometry.height, 0);
+ glEnd ();
+ glEnable (GL_TEXTURE_2D);
+ glColor4f (1.0, 1.0, 1.0, alpha);
+#endif
+ }
+ }
+
+ glDisable (GL_TEXTURE_2D);
+
+#if 0
+ glColor4f (0.0, 0.0, 0.0, 0.1);
+ for (list = texture->tiles; list != NULL; list = list->next)
+ {
+ Tile *tile = list->data;
+ int translated_x = tile->geometry.x + x;
+ int translated_y = tile->geometry.y + y;
+
+ glBegin (GL_QUADS);
+#if 0
+ glColor4f (g_random_double(),
+ g_random_double(),
+ g_random_double(), 0.3);
+#endif
+ glVertex3i (translated_x, translated_y, 0);
+ glVertex3i (translated_x + tile->geometry.width, translated_y, 0);
+ glVertex3i (translated_x + tile->geometry.width,
+ translated_y + tile->geometry.height, 0);
+ glVertex3i (translated_x, translated_y + tile->geometry.height, 0);
+
+ glEnd ();
+ }
+#endif
+
+ unset_clip_region ();
+
+ out:
+
+ glPopAttrib ();
+}
diff --git a/src/lmctexture.h b/src/lmctexture.h
new file mode 100644
index 00000000..4ceac076
--- /dev/null
+++ b/src/lmctexture.h
@@ -0,0 +1,28 @@
+#ifndef __LMC_TEXTURE_H__
+#define __LMC_TEXTURE_H__
+
+#include "lmcbits.h"
+#include "lmctypes.h"
+#include <gdk/gdk.h>
+
+#include <X11/Xutil.h> /* For Region */
+#include <GL/gl.h> /* For GLuint */
+
+G_BEGIN_DECLS
+
+typedef struct _LmcTexture LmcTexture;
+
+LmcTexture* lmc_texture_new (LmcBits *bits);
+LmcTexture* lmc_texture_ref (LmcTexture *texture);
+void lmc_texture_unref (LmcTexture *texture);
+void lmc_texture_update_rect (LmcTexture *texture,
+ GdkRectangle *rect);
+void lmc_texture_draw (LmcTexture *texture,
+ double alpha,
+ int x,
+ int y,
+ GdkRegion *clip);
+
+G_END_DECLS
+
+#endif /* __LMC_TEXTURE_H__ */
diff --git a/src/ui.h b/src/ui.h
index 34c81e2e..1bb22f95 100644
--- a/src/ui.h
+++ b/src/ui.h
@@ -32,7 +32,7 @@
/* This is between GTK_PRIORITY_RESIZE (+10) and GTK_PRIORITY_REDRAW (+20) */
#define META_PRIORITY_RESIZE (G_PRIORITY_HIGH_IDLE + 15)
/* lower than GTK_PRIORITY_REDRAW */
-#define META_PRIORITY_COMPOSITE (G_PRIORITY_HIGH_IDLE + 10)
+#define META_PRIORITY_COMPOSITE (G_PRIORITY_HIGH_IDLE + 30)
typedef struct _MetaUI MetaUI;