/** * clutter_x11_texture_pixmap_set_window: * @texture: the texture to bind * @window: the X window to which the texture should be bound * @automatic: TRUE is automatic window updates, FALSE for manual. * * Sets up a suitable pixmap for the window, using the composite and damage * extensions if possible, and then calls * clutter_x11_texture_pixmap_set_pixmap(). If you want a window in a texture, * you probably want this function, or its older sister, * clutter_glx_texture_pixmap_set_window(). * * Since: 0.8 **/ void clutter_x11_texture_pixmap_set_window (ClutterX11TexturePixmap *texture, Window window) { ClutterX11TexturePixmapPrivate *priv; XWindowAttributes attr; Display *dpy = clutter_x11_get_default_display (); g_return_if_fail (CLUTTER_X11_IS_TEXTURE_PIXMAP (texture)); priv = texture->priv; if (!clutter_x11_has_composite_extension()) return; if (priv->window == window) return; if (priv->window) { clutter_x11_remove_filter (on_x_event_filter_too, (gpointer)texture); } priv->window = window; priv->window_mapped = FALSE; priv->destroyed = FALSE; if (window == None) return; clutter_x11_trap_x_errors (); { if (!XGetWindowAttributes (dpy, window, &attr)) { XSync (dpy, False); clutter_x11_untrap_x_errors (); g_warning ("bad window 0x%x", (guint32)window); priv->window = None; return; } } clutter_x11_untrap_x_errors (); if (priv->window) { XSelectInput (dpy, priv->window, attr.your_event_mask | StructureNotifyMask); clutter_x11_add_filter (on_x_event_filter_too, (gpointer)texture); } g_object_ref (texture); g_object_notify (G_OBJECT (texture), "window"); clutter_x11_texture_pixmap_set_mapped (texture, attr.map_state == IsViewable); clutter_x11_texture_pixmap_sync_window (texture); g_object_unref (texture); }
int main (int argc, char *argv[]) { GstPipeline *pipeline; GstBus *bus; GstElement *srcbin; GstElement *tee; GstElement *queue[N_ACTORS], *sink[N_ACTORS]; GstElement *upload[N_ACTORS]; /* GstElement *effect[N_ACTORS]; */ ClutterActor *stage; GstGLClutterActor *actor[N_ACTORS]; Display *disp; Window stage_win; const gchar *desc; gint i; gint ok = FALSE; ClutterInitError clutter_err = CLUTTER_INIT_ERROR_UNKNOWN; clutter_err = clutter_init (&argc, &argv); if (clutter_err != CLUTTER_INIT_SUCCESS) g_warning ("Failed to initalize clutter: %d\n", clutter_err); gst_init (&argc, &argv); disp = clutter_x11_get_default_display (); if (!clutter_x11_has_composite_extension ()) { g_error ("XComposite extension missing"); } stage = clutter_stage_get_default (); clutter_actor_set_size (CLUTTER_ACTOR (stage), W * COLS + (COLS - 1), H * ROWS + (ROWS - 1)); stage_win = clutter_x11_get_stage_window (CLUTTER_STAGE (stage)); XCompositeRedirectSubwindows (disp, stage_win, CompositeRedirectManual); for (i = 0; i < N_ACTORS; i++) { actor[i] = g_new0 (GstGLClutterActor, 1); actor[i]->stage = stage; actor[i]->win = XCreateSimpleWindow (disp, stage_win, 0, 0, W, H, 0, 0, 0); XMapRaised (disp, actor[i]->win); XSync (disp, FALSE); } /* desc = g_strdup_printf ("v4l2src ! " "video/x-raw, width=640, height=480, framerate=30/1 ! " "videoscale !" "video/x-raw, width=%d, height=%d ! " "identity", W, H); */ desc = g_strdup_printf ("videotestsrc ! " "video/x-raw, format=RGB, width=%d, height=%d !" "identity", W, H); pipeline = GST_PIPELINE (gst_pipeline_new (NULL)); srcbin = gst_parse_bin_from_description (desc, TRUE, NULL); if (!srcbin) g_error ("Source bin creation failed"); tee = gst_element_factory_make ("tee", NULL); gst_bin_add_many (GST_BIN (pipeline), srcbin, tee, NULL); for (i = 0; i < N_ACTORS; i++) { queue[i] = gst_element_factory_make ("queue", NULL); upload[i] = gst_element_factory_make ("glupload", NULL); /* effect[i] = gst_element_factory_make ("gleffects", NULL); */ sink[i] = gst_element_factory_make ("glimagesink", NULL); /* gst_bin_add_many (GST_BIN (pipeline), queue[i], upload[i], effect[i], sink[i], NULL); */ gst_bin_add_many (GST_BIN (pipeline), queue[i], upload[i], sink[i], NULL); } gst_element_link_many (srcbin, tee, NULL); for (i = 0; i < N_ACTORS; i++) { ok |= // gst_element_link_many (tee, queue[i], upload[i], effect[i], sink[i], gst_element_link_many (tee, queue[i], upload[i], sink[i], NULL); } if (!ok) g_error ("Failed to link one or more elements"); /* for (i = 0; i < N_ACTORS; i++) { g_message ("setting effect %d on %s", i + 1, gst_element_get_name (effect[i])); g_object_set (G_OBJECT (effect[i]), "effect", i + 1, NULL); } */ bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); gst_bus_set_sync_handler (bus, (GstBusSyncHandler) create_window, actor, NULL); gst_object_unref (bus); gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING); clutter_actor_show_all (stage); clutter_main (); gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL); gst_object_unref (pipeline); return 0; }
/** * clutter_x11_texture_pixmap_sync_window: * @texture: the texture to bind * * Resets the texture's pixmap from its window, perhaps in response to the * pixmap's invalidation as the window changed size. * * Since: 0.8 **/ void clutter_x11_texture_pixmap_sync_window (ClutterX11TexturePixmap *texture) { ClutterX11TexturePixmapPrivate *priv; Pixmap pixmap; g_return_if_fail (CLUTTER_X11_IS_TEXTURE_PIXMAP (texture)); priv = texture->priv; if (priv->destroyed) return; if (!clutter_x11_has_composite_extension()) { clutter_x11_texture_pixmap_set_pixmap (texture, priv->window); return; } if (priv->window) { XWindowAttributes attr; Display *dpy = clutter_x11_get_default_display (); gboolean mapped, notify_x, notify_y, notify_override_redirect; /* We may get a BadMatch error here if the window is not mapped. * If so, ignore it - pixmap should be set to None in that case anyway */ XSync (dpy, FALSE); clutter_x11_trap_x_errors (); XGetWindowAttributes (dpy, priv->window, &attr); mapped = attr.map_state == IsViewable; if (mapped) pixmap = XCompositeNameWindowPixmap (dpy, priv->window); else pixmap = None; XSync (dpy, FALSE); if (clutter_x11_untrap_x_errors() && pixmap!=None) g_warning("%s: Got X error but pixmap is still set", __FUNCTION__); notify_x = attr.x != priv->window_x; notify_y = attr.y != priv->window_y; notify_override_redirect = attr.override_redirect != priv->override_redirect; priv->window_x = attr.x; priv->window_y = attr.y; priv->override_redirect = attr.override_redirect; g_object_ref (texture); /* guard against unparent */ if (pixmap) { clutter_x11_texture_pixmap_set_pixmap (texture, pixmap); priv->owns_pixmap = TRUE; } clutter_x11_texture_pixmap_set_mapped (texture, mapped); /* could do more clever things with a signal, i guess.. */ if (notify_override_redirect) g_object_notify (G_OBJECT (texture), "window-override-redirect"); if (notify_x) g_object_notify (G_OBJECT (texture), "window-x"); if (notify_y) g_object_notify (G_OBJECT (texture), "window-y"); g_object_unref (texture); } }