xcb_screen_t *screen;
vout_window_t *embed; /* VLC window (when windowed) */
- xcb_visualid_t vid;
+ xcb_visualid_t vid; /* selected visual */
xcb_window_t parent; /* parent X window */
+ xcb_colormap_t cmap; /* colormap for selected visual */
xcb_window_t window; /* drawable X window */
xcb_gcontext_t gc; /* context to put images */
bool shm; /* whether to use MIT-SHM */
- bool gray; /* whether display is grayscale */
uint8_t bpp; /* bits per pixel */
};
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 *);
assert (p_sys->screen);
msg_Dbg (vout, "using screen %d (depth %"PRIu8")", snum, scr->root_depth);
- if (strchr ("\x08\x0f\x10\x18\x20", scr->root_depth) == NULL)
- {
- msg_Err (vout, "unsupported %"PRIu8"-bits color depth",
- scr->root_depth);
- goto error;
- }
-
/* Determine the visual (color depth and palette) */
xcb_visualtype_t *vt = NULL;
- p_sys->gray = false;
+ bool gray = false;
+
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);
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);
else
+#endif
if ((scr->root_depth == 8)
&& (vt = xcb_aux_find_visual_by_attrs (scr, XCB_VISUAL_CLASS_STATIC_GRAY,
scr->root_depth)) != NULL)
{
msg_Dbg (vout, "using static gray visual ID %d", (int)vt->visual_id);
- p_sys->gray = true;
+ gray = true;
}
else
{
}
p_sys->vid = vt->visual_id;
+ /* Determine our input format (normally, done in Init() but X11
+ * never changes its format) */
+ p_sys->bpp = scr->root_depth;
+ switch (scr->root_depth)
+ {
+ case 24:
+ p_sys->bpp = 32;
+ case 32: /* FIXME: untested */
+ vout->output.i_chroma = VLC_FOURCC ('R', 'V', '3', '2');
+ break;
+
+ case 16:
+ vout->output.i_chroma = VLC_FOURCC ('R', 'V', '1', '6');
+ break;
+
+ case 15:
+ p_sys->bpp = 16;
+ vout->output.i_chroma = VLC_FOURCC ('R', 'V', '1', '5');
+ break;
+
+ case 8: /* FIXME: VLC cannot convert */
+ vout->output.i_chroma = gray ? VLC_FOURCC ('G', 'R', 'E', 'Y')
+ : VLC_FOURCC ('R', 'G', 'B', '2');
+ break;
+
+ default:
+ msg_Err (vout, "unsupported %"PRIu8"-bits screen depth",
+ scr->root_depth);
+ 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);
+ xcb_create_colormap (p_sys->conn, XCB_COLORMAP_ALLOC_NONE,
+ p_sys->cmap, scr->root, p_sys->vid);
+
+ /* Check shared memory support */
p_sys->shm = var_CreateGetBool (vout, "x11-shm") > 0;
if (p_sys->shm)
{
}
}
+ /* 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);
free (p_sys);
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_RequestWindow (vout, &(int){ 0 }, &(int){ 0 },
- &width, &height);
- if (p_sys->embed == NULL)
- {
- msg_Err (vout, "cannot get window");
- return VLC_EGENERIC;
- }
- p_sys->parent = (intptr_t)p_sys->embed->handle;
- }
+ p_sys->parent = p_sys->embed->handle.xid;
- /* Determine our input format */
- p_sys->bpp = screen->root_depth;
- switch (screen->root_depth)
- {
- case 24:
- p_sys->bpp = 32;
- case 32: /* FIXME: untested */
- vout->output.i_chroma = VLC_FOURCC ('R', 'V', '3', '2');
- break;
+ /* 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);
- case 16:
- vout->output.i_chroma = VLC_FOURCC ('R', 'V', '1', '6');
- break;
+ xcb_get_geometry_cookie_t ck;
+ ck = xcb_get_geometry (p_sys->conn, p_sys->parent);
- case 15:
- p_sys->bpp = 16;
- vout->output.i_chroma = VLC_FOURCC ('R', 'V', '1', '5');
- break;
-
- case 8: /* FIXME: VLC cannot convert */
- vout->output.i_chroma =
- p_sys->gray ? VLC_FOURCC ('G', 'R', 'E', 'Y')
- : VLC_FOURCC ('R', 'G', 'B', '2');
- break;
-
- default:
- assert (0);
+ 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);
/* FIXME: I don't get the subtlety between output and fmt_out here */
- vout->fmt_out.i_chroma = vout->output.i_chroma;
vout->fmt_out.i_visible_width = width;
vout->fmt_out.i_visible_height = height;
vout->fmt_out.i_sar_num = vout->fmt_out.i_sar_den = 1;
width * VOUT_ASPECT_FACTOR / height;
/* Create window */
- const uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
- uint32_t values[2] = {
+ const uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK
+ | XCB_CW_COLORMAP;
+ const uint32_t values[] = {
/* XCB_CW_BACK_PIXEL */
screen->black_pixel,
/* XCB_CW_EVENT_MASK */
XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE |
XCB_EVENT_MASK_POINTER_MOTION,
+ /* XCB_CW_COLORMAP */
+ p_sys->cmap,
};
xcb_void_cookie_t c;
xcb_window_t window = xcb_generate_id (p_sys->conn);
c = xcb_create_window_checked (p_sys->conn, screen->root_depth, window,
p_sys->parent, x, y, width, height, 0,
XCB_WINDOW_CLASS_INPUT_OUTPUT,
- screen->root_visual, mask, values);
+ p_sys->vid, mask, values);
if (CheckError (vout, "cannot create X11 window", c))
goto error;
p_sys->window = window;
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))
{