static int Init (vout_thread_t *);
static void Deinit (vout_thread_t *);
+static void Render (vout_thread_t *, picture_t *);
static void Display (vout_thread_t *, picture_t *);
static int Manage (vout_thread_t *);
if ((vt = xcb_aux_find_visual_by_attrs (scr, XCB_VISUAL_CLASS_TRUE_COLOR,
scr->root_depth)) != NULL)
msg_Dbg (vout, "using TrueColor visual ID %d", (int)vt->visual_id);
-#if 0
else
+#if 0
if ((vt = xcb_aux_find_visual_by_attrs (scr, XCB_VISUAL_CLASS_STATIC_COLOR,
scr->root_depth)) != NULL)
msg_Dbg (vout, "using static color visual ID %d", (int)vt->visual_id);
-#endif
else
+#endif
if ((scr->root_depth == 8)
&& (vt = xcb_aux_find_visual_by_attrs (scr, XCB_VISUAL_CLASS_STATIC_GRAY,
scr->root_depth)) != NULL)
goto error;
}
vout->fmt_out.i_chroma = vout->output.i_chroma;
+ if (!gray)
+ {
+ vout->output.i_rmask = vt->red_mask;
+ vout->output.i_gmask = vt->green_mask;
+ vout->output.i_bmask = vt->blue_mask;
+ }
/* Create colormap (needed to select non-default visual) */
p_sys->cmap = xcb_generate_id (p_sys->conn);
}
}
+ /* Get window */
+ /* FIXME: WTH to put as initial width/height values??? */
+ p_sys->embed = vout_RequestXWindow (vout, &(int){ 0 }, &(int){ 0 },
+ &(unsigned){ 0 }, &(unsigned){ 0 });
+ if (p_sys->embed == NULL)
+ {
+ msg_Err (vout, "parent window not available");
+ goto error;
+ }
+
vout->pf_init = Init;
vout->pf_end = Deinit;
+ vout->pf_render = Render;
vout->pf_display = Display;
vout->pf_manage = Manage;
return VLC_SUCCESS;
vout_thread_t *vout = (vout_thread_t *)obj;
vout_sys_t *p_sys = vout->p_sys;
- assert (p_sys->embed == NULL);
+ if (p_sys->embed)
+ vout_ReleaseWindow (p_sys->embed);
/* colormap is garbage-ollected by X (?) */
if (p_sys->conn)
xcb_disconnect (p_sys->conn);
struct picture_sys_t
{
- xcb_connection_t *conn;
- xcb_image_t *image;
- xcb_shm_seg_t segment;
+ xcb_connection_t *conn; /* Shared connection to X server */
+ xcb_image_t *image; /* Picture buffer */
+ xcb_image_t *native; /* Rendered picture buffer (in X server format) */
+ xcb_shm_seg_t segment; /* Shared memory segment X ID */
};
-static void PictureRelease (picture_t *pic);
-static void PictureShmRelease (picture_t *pic);
#define SHM_ERR ((void *)(intptr_t)(-1))
static int PictureInit (vout_thread_t *vout, picture_t *pic)
shm = SHM_ERR;
}
}
+ else
+ priv->segment = 0;
const unsigned real_width = pic->p->i_pitch / (p_sys->bpp >> 3);
/* FIXME: anyway to getthing more intuitive than that?? */
goto error;
}
if (shm != SHM_ERR && xcb_image_native (p_sys->conn, img, 0) == NULL)
- {
- msg_Err (vout, "incompatible X server image format");
- xcb_image_destroy (img);
- goto error;
- }
+ msg_Warn (vout, "incompatible X server image format");
priv->conn = p_sys->conn;
priv->image = img;
+ priv->native = NULL;
pic->p_sys = priv;
pic->p->p_pixels = img->data;
- pic->pf_release = (shm != SHM_ERR) ? PictureShmRelease
- : PictureRelease;
pic->i_status = DESTROYED_PICTURE;
pic->i_type = DIRECT_PICTURE;
return VLC_SUCCESS;
error:
if (shm != SHM_ERR)
shmdt (shm);
- free (p_sys);
+ free (priv);
return VLC_EGENERIC;
}
/**
* Release picture private data
*/
-static void PictureRelease (picture_t *pic)
+static void PictureDeinit (picture_t *pic)
{
struct picture_sys_t *p_sys = pic->p_sys;
+ if (p_sys->segment != 0)
+ {
+ xcb_shm_detach (p_sys->conn, p_sys->segment);
+ shmdt (p_sys->image->data);
+ }
+ if ((p_sys->native != NULL) && (p_sys->native != p_sys->image))
+ xcb_image_destroy (p_sys->native);
xcb_image_destroy (p_sys->image);
free (p_sys);
}
-/**
- * Release shared memory picture private data
- */
-static void PictureShmRelease (picture_t *pic)
-{
- struct picture_sys_t *p_sys = pic->p_sys;
-
- xcb_shm_detach (p_sys->conn, p_sys->segment);
- shmdt (p_sys->image->data);
- PictureRelease (pic);
-}
-
/**
* Allocate drawable window and picture buffers.
*/
const xcb_screen_t *screen = p_sys->screen;
unsigned x, y, width, height;
- /* Determine parent window */
+ /* Determine parent window and size */
if (vout->b_fullscreen)
{
- p_sys->embed = NULL;
p_sys->parent = screen->root;
width = screen->width_in_pixels;
height = screen->height_in_pixels;
}
else
{
- p_sys->embed = vout_RequestXWindow (vout, &(int){ 0 }, &(int){ 0 },
- &width, &height);
- if (p_sys->embed == NULL)
- {
- msg_Err (vout, "cannot get window");
- return VLC_EGENERIC;
- }
p_sys->parent = p_sys->embed->handle.xid;
+
+ /* Subscribe to parent window resize events */
+ const uint32_t value = XCB_EVENT_MASK_STRUCTURE_NOTIFY;
+ xcb_change_window_attributes (p_sys->conn, p_sys->parent,
+ XCB_CW_EVENT_MASK, &value);
+
+ xcb_get_geometry_cookie_t ck;
+ ck = xcb_get_geometry (p_sys->conn, p_sys->parent);
+
+ xcb_get_geometry_reply_t *geo;
+ xcb_generic_error_t *err;
+ geo = xcb_get_geometry_reply (p_sys->conn, ck, &err);
+ width = geo->width;
+ height = geo->height;
+ free (geo);
}
vout_PlacePicture (vout, width, height, &x, &y, &width, &height);
/* Create window */
const uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK
| XCB_CW_COLORMAP;
- uint32_t values[] = {
+ const uint32_t values[] = {
/* XCB_CW_BACK_PIXEL */
screen->black_pixel,
/* XCB_CW_EVENT_MASK */
vout_sys_t *p_sys = vout->p_sys;
while (I_OUTPUTPICTURES > 0)
- picture_Release (PP_OUTPUTPICTURE[--I_OUTPUTPICTURES]);
+ PictureDeinit (PP_OUTPUTPICTURE[--I_OUTPUTPICTURES]);
xcb_unmap_window (p_sys->conn, p_sys->window);
xcb_destroy_window (p_sys->conn, p_sys->window);
- vout_ReleaseWindow (p_sys->embed);
- p_sys->embed = NULL;
}
+/**
+ * Prepares an image ahead of display.
+ */
+static void Render (vout_thread_t *vout, picture_t *pic)
+{
+ vout_sys_t *p_sys = vout->p_sys;
+ picture_sys_t *priv = pic->p_sys;
+
+ if ((priv->native != NULL) && (priv->native != priv->image))
+ xcb_image_destroy (priv->native);
+ priv->native = xcb_image_native (p_sys->conn, priv->image, 1);
+}
+
+
/**
* Sends an image to the X server.
*/
{
vout_sys_t *p_sys = vout->p_sys;
picture_sys_t *priv = pic->p_sys;
- xcb_image_t *img = priv->image;
+ xcb_image_t *img = priv->image, *native = priv->native;
- if (img->base == NULL)
+ if ((native == img) && (img->base == NULL))
{
xcb_shm_segment_info_t info = {
.shmseg = priv->segment,
0, 0, 0, 0, img->width, img->height, 0);
}
else
- {
- xcb_image_t *native = xcb_image_native (p_sys->conn, img, 1);
-
- if (native == NULL)
- return;
-
+ if (native != NULL)
xcb_image_put (p_sys->conn, p_sys->window, p_sys->gc, native, 0, 0, 0);
- if (native != img)
- xcb_image_destroy (native);
- }
xcb_flush (p_sys->conn);
}
xcb_generic_event_t *ev;
while ((ev = xcb_poll_for_event (p_sys->conn)) != NULL)
- ProcessEvent (vout, ev);
+ ProcessEvent (vout, p_sys->conn, p_sys->window, ev);
if (xcb_connection_has_error (p_sys->conn))
{