X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fvideo_output%2Fxcb%2Fxcb.c;h=99520d99b531e7abf5f92fdbbb8555ae196e95d5;hb=b87b85154479ddc7fe05f93cc5c9e642a8d772ec;hp=33101e8c8f72bacba8666ac660dc93f69ddd7afd;hpb=4c06a308e892439a5e8955f0fc2f29b56a5797de;p=vlc diff --git a/modules/video_output/xcb/xcb.c b/modules/video_output/xcb/xcb.c index 33101e8c8f..99520d99b5 100644 --- a/modules/video_output/xcb/xcb.c +++ b/modules/video_output/xcb/xcb.c @@ -88,6 +88,7 @@ struct vout_sys_t 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 *); @@ -148,13 +149,13 @@ static int Open (vlc_object_t *obj) 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) @@ -202,6 +203,12 @@ static int Open (vlc_object_t *obj) 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); @@ -226,8 +233,19 @@ static int Open (vlc_object_t *obj) } } + /* 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; @@ -246,7 +264,8 @@ static void Close (vlc_object_t *obj) 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); @@ -255,13 +274,12 @@ static void Close (vlc_object_t *obj) 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) @@ -313,6 +331,8 @@ 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?? */ @@ -339,18 +359,13 @@ static int PictureInit (vout_thread_t *vout, picture_t *pic) 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; @@ -358,7 +373,7 @@ static int PictureInit (vout_thread_t *vout, picture_t *pic) error: if (shm != SHM_ERR) shmdt (shm); - free (p_sys); + free (priv); return VLC_EGENERIC; } @@ -366,26 +381,21 @@ error: /** * 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. */ @@ -395,24 +405,31 @@ static int Init (vout_thread_t *vout) 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); @@ -438,7 +455,7 @@ static int Init (vout_thread_t *vout) /* 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 */ @@ -492,14 +509,26 @@ static void Deinit (vout_thread_t *vout) 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. */ @@ -507,9 +536,9 @@ static void Display (vout_thread_t *vout, picture_t *pic) { 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, @@ -521,16 +550,8 @@ static void Display (vout_thread_t *vout, picture_t *pic) 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); } @@ -543,7 +564,7 @@ static int Manage (vout_thread_t *vout) 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)) {