X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fvideo_output%2Fdisplay.c;h=41cea68e52991dce46d58c40a020525842a355e8;hb=a3988310d257c5eee3b372a6fa7e3251e64c72c7;hp=538f6ef4238551c4821a345a8fe82241aece4a71;hpb=4825526146311e12940ccb89160b7f1900362d7d;p=vlc diff --git a/src/video_output/display.c b/src/video_output/display.c index 538f6ef423..41cea68e52 100644 --- a/src/video_output/display.c +++ b/src/video_output/display.c @@ -40,6 +40,10 @@ #include "event.h" +/* It must be present as long as a vout_display_t must be created using a dummy + * vout (as an opengl provider) */ +#define ALLOW_DUMMY_VOUT + static void SplitterClose(vout_display_t *vd); /***************************************************************************** @@ -47,14 +51,17 @@ static void SplitterClose(vout_display_t *vd); *****************************************************************************/ static picture_t *VideoBufferNew(filter_t *filter) { + vout_display_t *vd = (vout_display_t*)filter->p_owner; const video_format_t *fmt = &filter->fmt_out.video; - picture_t *picture = picture_New(fmt->i_chroma, - fmt->i_width, fmt->i_height, - fmt->i_aspect); - if (!picture) - msg_Err(filter, "Failed to allocate picture"); - return picture; + assert(vd->fmt.i_chroma == fmt->i_chroma && + vd->fmt.i_width == fmt->i_width && + vd->fmt.i_height == fmt->i_height); + + picture_pool_t *pool = vout_display_Pool(vd, 3); + if (!pool) + return NULL; + return picture_pool_Get(pool); } static void VideoBufferDelete(filter_t *filter, picture_t *picture) { @@ -62,19 +69,19 @@ static void VideoBufferDelete(filter_t *filter, picture_t *picture) picture_Release(picture); } -static int FilterAllocationInit(filter_t *filter, void *data) +static int FilterAllocationInit(filter_t *filter, void *vd) { - VLC_UNUSED(data); - - filter->pf_vout_buffer_new = VideoBufferNew; - filter->pf_vout_buffer_del = VideoBufferDelete; + filter->pf_video_buffer_new = VideoBufferNew; + filter->pf_video_buffer_del = VideoBufferDelete; + filter->p_owner = vd; return VLC_SUCCESS; } static void FilterAllocationClean(filter_t *filter) { - filter->pf_vout_buffer_new = NULL; - filter->pf_vout_buffer_del = NULL; + filter->pf_video_buffer_new = NULL; + filter->pf_video_buffer_del = NULL; + filter->p_owner = NULL; } /***************************************************************************** @@ -98,7 +105,6 @@ static vout_display_t *vout_display_New(vlc_object_t *obj, /* Picture buffer does not have the concept of aspect ratio */ video_format_Copy(&vd->fmt, fmt); - vd->fmt.i_aspect = 0; vd->fmt.i_sar_num = 0; vd->fmt.i_sar_den = 0; @@ -108,7 +114,7 @@ static vout_display_t *vout_display_New(vlc_object_t *obj, vd->info.has_pictures_invalid = false; vd->cfg = cfg; - vd->get = NULL; + vd->pool = NULL; vd->prepare = NULL; vd->display = NULL; vd->control = NULL; @@ -122,7 +128,6 @@ static vout_display_t *vout_display_New(vlc_object_t *obj, if (load_module) { vd->module = module_need(vd, "vout display", module, module && *module != '\0'); if (!vd->module) { - vlc_object_detach(vd); vlc_object_release(vd); return NULL; } @@ -137,8 +142,6 @@ static vout_display_t *vout_display_New(vlc_object_t *obj, */ static void vout_display_Delete(vout_display_t *vd) { - vlc_object_detach(vd); - if (vd->module) module_unneed(vd, vd->module); @@ -161,7 +164,8 @@ static int vout_display_Control(vout_display_t *vd, int query, ...) } static void vout_display_Manage(vout_display_t *vd) { - vd->manage(vd); + if (vd->manage) + vd->manage(vd); } /* */ @@ -204,14 +208,10 @@ void vout_display_PlacePicture(vout_display_place_t *place, return; /* */ - unsigned width; - unsigned height; unsigned display_width; unsigned display_height; if (cfg->is_display_filled) { - width = source->i_visible_width; - height = source->i_visible_height; display_width = cfg->display.width; display_height = cfg->display.height; } else { @@ -219,17 +219,17 @@ void vout_display_PlacePicture(vout_display_place_t *place, cfg_tmp.display.width = 0; cfg_tmp.display.height = 0; - vout_display_GetDefaultDisplaySize(&width, &height, + vout_display_GetDefaultDisplaySize(&display_width, &display_height, source, &cfg_tmp); - display_width = width; - display_height = height; if (do_clipping) { display_width = __MIN(display_width, cfg->display.width); display_height = __MIN(display_height, cfg->display.height); } } + const unsigned width = source->i_visible_width; + const unsigned height = source->i_visible_height; /* Compute the height if we use the width to fill up display_width */ const int64_t scaled_height = (int64_t)height * display_width * cfg->display.sar.num * source->i_sar_den / width / source->i_sar_num / cfg->display.sar.den; /* And the same but switching width/height */ @@ -275,22 +275,9 @@ struct vout_display_owner_sys_t { bool is_wrapper; /* Is the current display a wrapper */ vout_display_t *wrapper; /* Vout display wrapper */ - /* mouse state */ - struct { - vlc_mouse_t state; - - mtime_t last_pressed; - mtime_t last_moved; - bool is_hidden; - - /* */ - mtime_t double_click_timeout; - mtime_t hide_timeout; - } mouse; - /* */ vout_display_cfg_t cfg; - bool is_on_top_initial; + unsigned wm_state_initial; struct { unsigned num; unsigned den; @@ -306,15 +293,6 @@ struct vout_display_owner_sys_t { } crop_saved; /* */ - bool reset_pictures; - - bool ch_fullscreen; - bool is_fullscreen; - - bool ch_display_size; - int display_width; - int display_height; - bool ch_display_filled; bool is_display_filled; @@ -324,8 +302,8 @@ struct vout_display_owner_sys_t { int den; } zoom; - bool ch_on_top; - bool is_on_top; + bool ch_wm_state; + unsigned wm_state; bool ch_sar; struct { @@ -346,8 +324,43 @@ struct vout_display_owner_sys_t { /* */ video_format_t source; filter_chain_t *filters; + + /* Lock protecting the variables used by + * VoutDisplayEvent(ie vout_display_SendEvent) */ + vlc_mutex_t lock; + + /* mouse state */ + struct { + vlc_mouse_t state; + + mtime_t last_pressed; + mtime_t last_moved; + bool is_hidden; + bool ch_activity; + + /* */ + mtime_t double_click_timeout; + mtime_t hide_timeout; + } mouse; + + bool reset_pictures; + + bool ch_fullscreen; + bool is_fullscreen; + + bool ch_display_size; + int display_width; + int display_height; + bool display_is_fullscreen; + bool display_is_forced; + +#ifdef ALLOW_DUMMY_VOUT + vlc_mouse_t vout_mouse; +#endif }; +static void DummyVoutSendDisplayEventMouse(vout_thread_t *, vlc_mouse_t *fallback, const vlc_mouse_t *m); + static void VoutDisplayCreateRender(vout_display_t *vd) { vout_display_owner_sys_t *osys = vd->owner.sys; @@ -355,12 +368,10 @@ static void VoutDisplayCreateRender(vout_display_t *vd) osys->filters = NULL; video_format_t v_src = vd->source; - v_src.i_aspect = 0; v_src.i_sar_num = 0; v_src.i_sar_den = 0; video_format_t v_dst = vd->fmt; - v_dst.i_aspect = 0; v_dst.i_sar_num = 0; v_dst.i_sar_den = 0; @@ -375,11 +386,11 @@ static void VoutDisplayCreateRender(vout_display_t *vd) if (!convert) return; - msg_Err(vd, "A filter to adapt decoder to display is needed"); + msg_Dbg(vd, "A filter to adapt decoder to display is needed"); osys->filters = filter_chain_New(vd, "video filter2", false, FilterAllocationInit, - FilterAllocationClean, NULL); + FilterAllocationClean, vd); assert(osys->filters); /* TODO critical */ /* */ @@ -421,82 +432,39 @@ static void VoutDisplayResetRender(vout_display_t *vd) VoutDisplayDestroyRender(vd); VoutDisplayCreateRender(vd); } -static void VoutDisplayEventMouse(vout_display_t *vd, const vlc_mouse_t *mouse) +static void VoutDisplayEventMouse(vout_display_t *vd, int event, va_list args) { vout_display_owner_sys_t *osys = vd->owner.sys; - /* */ - vlc_mouse_t m = *mouse; - - /* Emulate double-click if needed */ - if (!vd->info.has_double_click && - vlc_mouse_HasPressed(&osys->mouse.state, &m, MOUSE_BUTTON_LEFT)) { - const mtime_t i_date = mdate(); - - if (i_date - osys->mouse.last_pressed < osys->mouse.double_click_timeout ) { - m.b_double_click = true; - osys->mouse.last_pressed = 0; - } else { - osys->mouse.last_pressed = mdate(); - } - } + vlc_mutex_lock(&osys->lock); /* */ - osys->mouse.state = m; - - vout_SendDisplayEventMouse(osys->vout, &m); - - /* */ - osys->mouse.is_hidden = false; - if (!vd->info.has_hide_mouse) - osys->mouse.last_moved = mdate(); - vout_SendEventMouseVisible(osys->vout); -} - -static void VoutDisplayEvent(vout_display_t *vd, int event, va_list args) -{ - vout_display_owner_sys_t *osys = vd->owner.sys; + vlc_mouse_t m = osys->mouse.state; + bool is_ignored = false; switch (event) { - case VOUT_DISPLAY_EVENT_CLOSE: { - msg_Dbg(vd, "VoutDisplayEvent 'close'"); - vout_SendEventClose(osys->vout); - break; - } - case VOUT_DISPLAY_EVENT_KEY: { - const int key = (int)va_arg(args, int); - msg_Dbg(vd, "VoutDisplayEvent 'key' 0x%2.2x", key); - vout_SendEventKey(osys->vout, key); - break; - } case VOUT_DISPLAY_EVENT_MOUSE_STATE: { const int x = (int)va_arg(args, int); const int y = (int)va_arg(args, int); const int button_mask = (int)va_arg(args, int); - vlc_mouse_t m; - vlc_mouse_Init(&m); m.i_x = x; m.i_y = y; m.i_pressed = button_mask; - - VoutDisplayEventMouse(vd, &m); break; } case VOUT_DISPLAY_EVENT_MOUSE_MOVED: { const int x = (int)va_arg(args, int); const int y = (int)va_arg(args, int); if (x != osys->mouse.state.i_x || y != osys->mouse.state.i_y) { - msg_Dbg(vd, "VoutDisplayEvent 'mouse' @%d,%d", x, y); + //msg_Dbg(vd, "VoutDisplayEvent 'mouse' @%d,%d", x, y); - /* */ - vlc_mouse_t m = osys->mouse.state; m.i_x = x; m.i_y = y; m.b_double_click = false; - - VoutDisplayEventMouse(vd, &m); + } else { + is_ignored = true; } break; } @@ -505,55 +473,137 @@ static void VoutDisplayEvent(vout_display_t *vd, int event, va_list args) const int button = (int)va_arg(args, int); const int button_mask = 1 << button; - /* Ignore inconistent event */ - if (event == VOUT_DISPLAY_EVENT_MOUSE_PRESSED && (osys->mouse.state.i_pressed & button_mask)) - break; - if (event == VOUT_DISPLAY_EVENT_MOUSE_RELEASED && !(osys->mouse.state.i_pressed & button_mask)) + /* Ignore inconsistent event */ + if ((event == VOUT_DISPLAY_EVENT_MOUSE_PRESSED && (osys->mouse.state.i_pressed & button_mask)) || + (event == VOUT_DISPLAY_EVENT_MOUSE_RELEASED && !(osys->mouse.state.i_pressed & button_mask))) { + is_ignored = true; break; + } /* */ msg_Dbg(vd, "VoutDisplayEvent 'mouse button' %d t=%d", button, event); - vlc_mouse_t m = osys->mouse.state; m.b_double_click = false; if (event == VOUT_DISPLAY_EVENT_MOUSE_PRESSED) m.i_pressed |= button_mask; else m.i_pressed &= ~button_mask; - - VoutDisplayEventMouse(vd, &m); break; } - case VOUT_DISPLAY_EVENT_MOUSE_DOUBLE_CLICK: { + case VOUT_DISPLAY_EVENT_MOUSE_DOUBLE_CLICK: msg_Dbg(vd, "VoutDisplayEvent 'double click'"); - vlc_mouse_t m = osys->mouse.state; m.b_double_click = true; - VoutDisplayEventMouse(vd, &m); break; + default: + assert(0); } + if (is_ignored) { + vlc_mutex_unlock(&osys->lock); + return; + } + + /* Emulate double-click if needed */ + if (!vd->info.has_double_click && + vlc_mouse_HasPressed(&osys->mouse.state, &m, MOUSE_BUTTON_LEFT)) { + const mtime_t i_date = mdate(); + + if (i_date - osys->mouse.last_pressed < osys->mouse.double_click_timeout ) { + m.b_double_click = true; + osys->mouse.last_pressed = 0; + } else { + osys->mouse.last_pressed = mdate(); + } + } + + /* */ + osys->mouse.state = m; + + /* */ + osys->mouse.ch_activity = true; + if (!vd->info.has_hide_mouse) + osys->mouse.last_moved = mdate(); + + /* */ + vout_SendEventMouseVisible(osys->vout); +#ifdef ALLOW_DUMMY_VOUT + DummyVoutSendDisplayEventMouse(osys->vout, &osys->vout_mouse, &m); +#else + vout_SendDisplayEventMouse(osys->vout, &m); +#endif + vlc_mutex_unlock(&osys->lock); +} + +static void VoutDisplayEvent(vout_display_t *vd, int event, va_list args) +{ + vout_display_owner_sys_t *osys = vd->owner.sys; + + switch (event) { + case VOUT_DISPLAY_EVENT_CLOSE: { + msg_Dbg(vd, "VoutDisplayEvent 'close'"); + vout_SendEventClose(osys->vout); + break; + } + case VOUT_DISPLAY_EVENT_KEY: { + const int key = (int)va_arg(args, int); + msg_Dbg(vd, "VoutDisplayEvent 'key' 0x%2.2x", key); + vout_SendEventKey(osys->vout, key); + break; + } + case VOUT_DISPLAY_EVENT_MOUSE_STATE: + case VOUT_DISPLAY_EVENT_MOUSE_MOVED: + case VOUT_DISPLAY_EVENT_MOUSE_PRESSED: + case VOUT_DISPLAY_EVENT_MOUSE_RELEASED: + case VOUT_DISPLAY_EVENT_MOUSE_DOUBLE_CLICK: + VoutDisplayEventMouse(vd, event, args); + break; + case VOUT_DISPLAY_EVENT_FULLSCREEN: { const int is_fullscreen = (int)va_arg(args, int); msg_Dbg(vd, "VoutDisplayEvent 'fullscreen' %d", is_fullscreen); - if (!is_fullscreen == !osys->is_fullscreen) - break; - osys->ch_fullscreen = true; - osys->is_fullscreen = is_fullscreen; + vlc_mutex_lock(&osys->lock); + if (!is_fullscreen != !osys->is_fullscreen) { + osys->ch_fullscreen = true; + osys->is_fullscreen = is_fullscreen; + } + vlc_mutex_unlock(&osys->lock); + break; + } + + case VOUT_DISPLAY_EVENT_WINDOW_STATE: { + const unsigned state = va_arg(args, unsigned); + + msg_Dbg(vd, "VoutDisplayEvent 'window state' %u", state); + + vlc_mutex_lock(&osys->lock); + if (state != osys->wm_state) { + osys->ch_wm_state = true; + osys->wm_state = state; + } + vlc_mutex_unlock(&osys->lock); break; } case VOUT_DISPLAY_EVENT_DISPLAY_SIZE: { const int width = (int)va_arg(args, int); const int height = (int)va_arg(args, int); - msg_Dbg(vd, "VoutDisplayEvent 'resize' %dx%d", width, height); + const bool is_fullscreen = (bool)va_arg(args, int); + msg_Dbg(vd, "VoutDisplayEvent 'resize' %dx%d %s", + width, height, is_fullscreen ? "fullscreen" : "window"); /* */ - osys->ch_display_size = true; - osys->display_width = width; - osys->display_height = height; + vlc_mutex_lock(&osys->lock); + + osys->ch_display_size = true; + osys->display_width = width; + osys->display_height = height; + osys->display_is_fullscreen = is_fullscreen; + osys->display_is_forced = false; + + vlc_mutex_unlock(&osys->lock); break; } @@ -562,7 +612,10 @@ static void VoutDisplayEvent(vout_display_t *vd, int event, va_list args) /* */ assert(vd->info.has_pictures_invalid); + + vlc_mutex_lock(&osys->lock); osys->reset_pictures = true; + vlc_mutex_unlock(&osys->lock); break; } default: @@ -585,7 +638,7 @@ static void VoutDisplayDelWindow(vout_display_t *vd, vout_window_t *window) vout_DeleteDisplayWindow(osys->vout, vd, window); } -void vout_ManageDisplay(vout_display_t *vd) +void vout_ManageDisplay(vout_display_t *vd, bool allow_reset_pictures) { vout_display_owner_sys_t *osys = vd->owner.sys; @@ -593,69 +646,107 @@ void vout_ManageDisplay(vout_display_t *vd) /* Handle mouse timeout */ const mtime_t date = mdate(); + bool hide_mouse = false; + + vlc_mutex_lock(&osys->lock); + if (!osys->mouse.is_hidden && osys->mouse.last_moved + osys->mouse.hide_timeout < date) { + osys->mouse.is_hidden = hide_mouse = true; + } else if (osys->mouse.ch_activity) { + osys->mouse.is_hidden = false; + } + osys->mouse.ch_activity = false; + vlc_mutex_unlock(&osys->lock); + + if (hide_mouse) { if (!vd->info.has_hide_mouse) { msg_Dbg(vd, "auto hidding mouse"); vout_display_Control(vd, VOUT_DISPLAY_HIDE_MOUSE); } - osys->mouse.is_hidden = true; - vout_SendEventMouseHidden(osys->vout); } - bool reset_pictures = false; + bool reset_render = false; for (;;) { - if (!osys->ch_fullscreen && - !osys->ch_display_size && - !osys->reset_pictures && + + vlc_mutex_lock(&osys->lock); + + bool ch_fullscreen = osys->ch_fullscreen; + bool is_fullscreen = osys->is_fullscreen; + osys->ch_fullscreen = false; + + bool ch_wm_state = osys->ch_wm_state; + unsigned wm_state = osys->wm_state; + osys->ch_wm_state = false; + + bool ch_display_size = osys->ch_display_size; + int display_width = osys->display_width; + int display_height = osys->display_height; + bool display_is_fullscreen = osys->display_is_fullscreen; + bool display_is_forced = osys->display_is_forced; + osys->ch_display_size = false; + + bool reset_pictures; + if (allow_reset_pictures) { + reset_pictures = osys->reset_pictures; + osys->reset_pictures = false; + } else { + reset_pictures = false; + } + + vlc_mutex_unlock(&osys->lock); + + if (!ch_fullscreen && + !ch_display_size && + !reset_pictures && !osys->ch_display_filled && !osys->ch_zoom && - !osys->ch_on_top && + !ch_wm_state && !osys->ch_sar && !osys->ch_crop) break; /* */ - if (osys->ch_fullscreen) { + if (ch_fullscreen) { vout_display_cfg_t cfg = osys->cfg; - cfg.is_fullscreen = osys->is_fullscreen; + cfg.is_fullscreen = is_fullscreen; cfg.display.width = cfg.is_fullscreen ? 0 : osys->width_saved; cfg.display.height = cfg.is_fullscreen ? 0 : osys->height_saved; if (vout_display_Control(vd, VOUT_DISPLAY_CHANGE_FULLSCREEN, &cfg)) { msg_Err(vd, "Failed to set fullscreen"); - osys->is_fullscreen = osys->cfg.is_fullscreen; + is_fullscreen = osys->cfg.is_fullscreen; } - osys->cfg.is_fullscreen = osys->is_fullscreen; - osys->ch_fullscreen = false; + osys->cfg.is_fullscreen = is_fullscreen; /* */ vout_SendEventFullscreen(osys->vout, osys->cfg.is_fullscreen); } /* */ - if (osys->ch_display_size) { + if (ch_display_size) { vout_display_cfg_t cfg = osys->cfg; - cfg.display.width = osys->display_width; - cfg.display.height = osys->display_height; + cfg.display.width = display_width; + cfg.display.height = display_height; - if (vout_display_Control(vd, VOUT_DISPLAY_CHANGE_DISPLAY_SIZE, &cfg)) { - msg_Err(vd, "Failed to resize display"); + if (!cfg.is_fullscreen != !display_is_fullscreen || + vout_display_Control(vd, VOUT_DISPLAY_CHANGE_DISPLAY_SIZE, &cfg, display_is_forced)) { + if (!cfg.is_fullscreen == !display_is_fullscreen) + msg_Err(vd, "Failed to resize display"); /* We ignore the resized */ - osys->display_width = osys->cfg.display.width; - osys->display_height = osys->cfg.display.height; + display_width = osys->cfg.display.width; + display_height = osys->cfg.display.height; } - osys->cfg.display.width = osys->display_width; - osys->cfg.display.height = osys->display_height; + osys->cfg.display.width = display_width; + osys->cfg.display.height = display_height; - if (!osys->is_fullscreen) { - osys->width_saved = osys->display_width; - osys->height_saved = osys->display_height; + if (!display_is_fullscreen) { + osys->width_saved = display_width; + osys->height_saved = display_height; } - osys->ch_display_size = false; } /* */ if (osys->ch_display_filled) { @@ -692,9 +783,18 @@ void vout_ManageDisplay(vout_display_t *vd) osys->zoom.num = osys->cfg.zoom.num; osys->zoom.den = osys->cfg.zoom.den; } else if (cfg.is_display_filled) { - osys->ch_display_size = true; - osys->display_width = (int64_t)vd->source.i_width * osys->zoom.num / osys->zoom.den; - osys->display_height = (int64_t)vd->source.i_height * osys->zoom.num / osys->zoom.den; + const int display_width = (int64_t)vd->source.i_width * osys->zoom.num / osys->zoom.den; + const int display_height = (int64_t)vd->source.i_height * osys->zoom.num / osys->zoom.den; + + vlc_mutex_lock(&osys->lock); + + osys->ch_display_size = true; + osys->display_width = display_width; + osys->display_height = display_height; + osys->display_is_fullscreen = osys->cfg.is_fullscreen; + osys->display_is_forced = true; + + vlc_mutex_unlock(&osys->lock); } osys->cfg.zoom.num = osys->zoom.num; @@ -704,19 +804,15 @@ void vout_ManageDisplay(vout_display_t *vd) vout_SendEventZoom(osys->vout, osys->cfg.zoom.num, osys->cfg.zoom.den); } /* */ - if (osys->ch_on_top) { - bool is_on_top = osys->is_on_top; - - if (vout_display_Control(vd, VOUT_DISPLAY_CHANGE_ON_TOP, is_on_top)) { + if (ch_wm_state) { + if (vout_display_Control(vd, VOUT_DISPLAY_CHANGE_WINDOW_STATE, wm_state)) { msg_Err(vd, "Failed to set on top"); - is_on_top = osys->is_on_top_initial; + wm_state = osys->wm_state; } - osys->is_on_top_initial = - osys->is_on_top = is_on_top; - osys->ch_on_top = false; + osys->wm_state_initial = wm_state; /* */ - vout_SendEventOnTop(osys->vout, osys->is_on_top_initial); + vout_SendEventOnTop(osys->vout, osys->wm_state_initial); } /* */ if (osys->ch_sar) { @@ -811,17 +907,15 @@ void vout_ManageDisplay(vout_display_t *vd) } /* */ - if (osys->reset_pictures) { + if (reset_pictures) { if (vout_display_Control(vd, VOUT_DISPLAY_RESET_PICTURES)) { /* FIXME what to do here ? */ msg_Err(vd, "Failed to reset pictures (probably fatal)"); } - reset_pictures = true; - - osys->reset_pictures = false; + reset_render = true; } } - if (reset_pictures) + if (reset_render) VoutDisplayResetRender(vd); } @@ -829,7 +923,11 @@ bool vout_AreDisplayPicturesInvalid(vout_display_t *vd) { vout_display_owner_sys_t *osys = vd->owner.sys; - return osys->reset_pictures; + vlc_mutex_lock(&osys->lock); + const bool reset_pictures = osys->reset_pictures; + vlc_mutex_unlock(&osys->lock); + + return reset_pictures; } bool vout_IsDisplayFiltered(vout_display_t *vd) @@ -843,8 +941,7 @@ picture_t *vout_FilterDisplay(vout_display_t *vd, picture_t *picture) { vout_display_owner_sys_t *osys = vd->owner.sys; - if (!osys->filters) - return picture; + assert(osys->filters); return filter_chain_VideoFilter(osys->filters, picture); } @@ -852,10 +949,12 @@ void vout_SetDisplayFullscreen(vout_display_t *vd, bool is_fullscreen) { vout_display_owner_sys_t *osys = vd->owner.sys; + vlc_mutex_lock(&osys->lock); if (!osys->is_fullscreen != !is_fullscreen) { osys->ch_fullscreen = true; osys->is_fullscreen = is_fullscreen; } + vlc_mutex_unlock(&osys->lock); } void vout_SetDisplayFilled(vout_display_t *vd, bool is_filled) @@ -872,21 +971,26 @@ void vout_SetDisplayZoom(vout_display_t *vd, int num, int den) { vout_display_owner_sys_t *osys = vd->owner.sys; - if (osys->zoom.num != num || osys->zoom.den != den) { + if (osys->is_display_filled || + osys->zoom.num != num || osys->zoom.den != den) { osys->ch_zoom = true; osys->zoom.num = num; osys->zoom.den = den; } } -void vout_SetDisplayOnTop(vout_display_t *vd, bool is_on_top) + +void vout_SetWindowState(vout_display_t *vd, unsigned state) { vout_display_owner_sys_t *osys = vd->owner.sys; - if (!osys->is_on_top != !is_on_top) { - osys->ch_on_top = true; - osys->is_on_top = is_on_top; + vlc_mutex_lock(&osys->lock); + if (osys->wm_state != state) { + osys->ch_wm_state = true; + osys->wm_state = state; } + vlc_mutex_unlock(&osys->lock); } + void vout_SetDisplayAspect(vout_display_t *vd, unsigned sar_num, unsigned sar_den) { vout_display_owner_sys_t *osys = vd->owner.sys; @@ -916,7 +1020,13 @@ void vout_SetDisplayCrop(vout_display_t *vd, osys->ch_crop = true; } } - +vout_opengl_t *vout_GetDisplayOpengl(vout_display_t *vd) +{ + vout_opengl_t *gl; + if (vout_display_Control(vd, VOUT_DISPLAY_GET_OPENGL, &gl)) + return NULL; + return gl; +} static vout_display_t *DisplayNew(vout_thread_t *vout, const video_format_t *source_org, @@ -932,7 +1042,7 @@ static vout_display_t *DisplayNew(vout_thread_t *vout, vout_display_cfg_t *cfg = &osys->cfg; *cfg = state->cfg; - osys->is_on_top_initial = state->is_on_top;; + osys->wm_state_initial = VOUT_WINDOW_STATE_NORMAL; osys->sar_initial.num = state->sar.num; osys->sar_initial.den = state->sar.den; vout_display_GetDefaultDisplaySize(&cfg->display.width, &cfg->display.height, @@ -942,6 +1052,8 @@ static vout_display_t *DisplayNew(vout_thread_t *vout, osys->is_wrapper = is_wrapper; osys->wrapper = wrapper; + vlc_mutex_init(&osys->lock); + vlc_mouse_Init(&osys->mouse.state); osys->mouse.last_moved = mdate(); osys->mouse.double_click_timeout = double_click_timeout; @@ -954,6 +1066,8 @@ static vout_display_t *DisplayNew(vout_thread_t *vout, osys->is_display_filled = cfg->is_display_filled; osys->zoom.num = cfg->zoom.num; osys->zoom.den = cfg->zoom.den; + osys->wm_state = state->is_on_top ? VOUT_WINDOW_STATE_ABOVE + : VOUT_WINDOW_STATE_NORMAL; osys->source = *source_org; @@ -974,6 +1088,9 @@ static vout_display_t *DisplayNew(vout_thread_t *vout, osys->sar.num = osys->sar_initial.num ? osys->sar_initial.num : source.i_sar_num; osys->sar.den = osys->sar_initial.den ? osys->sar_initial.den : source.i_sar_den; +#ifdef ALLOW_DUMMY_VOUT + vlc_mouse_Init(&osys->vout_mouse); +#endif vout_display_owner_t owner; if (owner_ptr) { @@ -1000,8 +1117,8 @@ static vout_display_t *DisplayNew(vout_thread_t *vout, if (osys->sar.num != source_org->i_sar_num || osys->sar.den != source_org->i_sar_den) osys->ch_sar = true; - if (osys->is_on_top) - osys->ch_on_top = true; + if (osys->wm_state != osys->wm_state_initial) + osys->ch_wm_state = true; if (osys->crop.x != source_org->i_x_offset || osys->crop.y != source_org->i_y_offset || osys->crop.width != source_org->i_visible_width || @@ -1018,7 +1135,7 @@ void vout_DeleteDisplay(vout_display_t *vd, vout_display_state_t *state) if (state) { if (!osys->is_wrapper ) state->cfg = osys->cfg; - state->is_on_top = osys->is_on_top_initial; + state->is_on_top = (osys->wm_state & VOUT_WINDOW_STATE_ABOVE) != 0; state->sar.num = osys->sar_initial.num; state->sar.den = osys->sar_initial.den; } @@ -1027,6 +1144,7 @@ void vout_DeleteDisplay(vout_display_t *vd, vout_display_state_t *state) if (osys->is_wrapper) SplitterClose(vd); vout_display_Delete(vd); + vlc_mutex_destroy(&osys->lock); free(osys); } @@ -1044,17 +1162,11 @@ vout_display_t *vout_NewDisplay(vout_thread_t *vout, double_click_timeout, hide_timeout, NULL); } -static void SplitterClose(vout_display_t *vd) -{ - VLC_UNUSED(vd); - assert(0); -} - -#if 0 /***************************************************************************** * *****************************************************************************/ struct vout_display_sys_t { + picture_pool_t *pool; video_splitter_t *splitter; /* */ @@ -1085,7 +1197,7 @@ static void SplitterDelWindow(vout_display_t *vd, vout_window_t *window) } static void SplitterEvent(vout_display_t *vd, int event, va_list args) { - vout_display_owner_sys_t *osys = vd->owner.sys; + //vout_display_owner_sys_t *osys = vd->owner.sys; switch (event) { #if 0 @@ -1111,10 +1223,12 @@ static void SplitterEvent(vout_display_t *vd, int event, va_list args) } } -static picture_t *SplitterGet(vout_display_t *vd) +static picture_pool_t *SplitterPool(vout_display_t *vd, unsigned count) { - /* TODO pool ? */ - return picture_NewFromFormat(&vd->fmt); + vout_display_sys_t *sys = vd->sys; + if (!sys->pool) + sys->pool = picture_pool_NewFromFormat(&vd->fmt, count); + return sys->pool; } static void SplitterPrepare(vout_display_t *vd, picture_t *picture) { @@ -1130,26 +1244,10 @@ static void SplitterPrepare(vout_display_t *vd, picture_t *picture) } for (int i = 0; i < sys->count; i++) { - /* */ - sys->picture[i] = vout_FilterDisplay(sys->display[i], sys->picture[i]); - if (!sys->picture[i]) - continue; - - /* */ - picture_t *direct = vout_display_Get(sys->display[i]); - if (!direct) { - msg_Err(vd, "Failed to get a direct buffer"); - picture_Release(sys->picture[i]); - sys->picture[i] = NULL; - continue; - } - - /* FIXME not always needed (easy when there is a osys->filters) */ - picture_Copy(direct, sys->picture[i]); - picture_Release(sys->picture[i]); - sys->picture[i] = direct; - - vout_display_Prepare(sys->display[i], sys->picture[i]); + if (vout_IsDisplayFiltered(sys->display[i])) + sys->picture[i] = vout_FilterDisplay(sys->display[i], sys->picture[i]); + if (sys->picture[i]) + vout_display_Prepare(sys->display[i], sys->picture[i]); } } static void SplitterDisplay(vout_display_t *vd, picture_t *picture) @@ -1171,7 +1269,7 @@ static void SplitterManage(vout_display_t *vd) vout_display_sys_t *sys = vd->sys; for (int i = 0; i < sys->count; i++) - vout_ManageDisplay(sys->display[i]); + vout_ManageDisplay(sys->display[i], true); } static int SplitterPictureNew(video_splitter_t *splitter, picture_t *picture[]) @@ -1179,8 +1277,13 @@ static int SplitterPictureNew(video_splitter_t *splitter, picture_t *picture[]) vout_display_sys_t *wsys = splitter->p_owner->wrapper->sys; for (int i = 0; i < wsys->count; i++) { - /* TODO pool ? */ - picture[i] = picture_NewFromFormat(&wsys->display[i]->source); + if (vout_IsDisplayFiltered(wsys->display[i])) { + /* TODO use a pool ? */ + picture[i] = picture_NewFromFormat(&wsys->display[i]->source); + } else { + picture_pool_t *pool = vout_display_Pool(wsys->display[i], 1); + picture[i] = pool ? picture_pool_Get(pool) : NULL; + } if (!picture[i]) { for (int j = 0; j < i; j++) picture_Release(picture[j]); @@ -1205,6 +1308,9 @@ static void SplitterClose(vout_display_t *vd) free(splitter->p_owner); video_splitter_Delete(splitter); + if (sys->pool) + picture_pool_Delete(sys->pool); + /* */ for (int i = 0; i < sys->count; i++) vout_DeleteDisplay(sys->display[i], NULL); @@ -1242,8 +1348,9 @@ vout_display_t *vout_NewSplitter(vout_thread_t *vout, if (!sys->picture ) abort(); sys->splitter = splitter; + sys->pool = NULL; - wrapper->get = SplitterGet; + wrapper->pool = SplitterPool; wrapper->prepare = SplitterPrepare; wrapper->display = SplitterDisplay; wrapper->control = SplitterControl; @@ -1293,7 +1400,6 @@ vout_display_t *vout_NewSplitter(vout_thread_t *vout, return wrapper; } -#endif /***************************************************************************** * TODO move out @@ -1301,6 +1407,19 @@ vout_display_t *vout_NewSplitter(vout_thread_t *vout, #include "vout_internal.h" void vout_SendDisplayEventMouse(vout_thread_t *vout, const vlc_mouse_t *m) { + vlc_mouse_t tmp; + + /* The check on p_spu is needed as long as ALLOW_DUMMY_VOUT is defined */ + if (vout->p->p_spu && spu_ProcessMouse( vout->p->p_spu, m, &vout->p->display.vd->source)) + return; + + vlc_mutex_lock( &vout->p->vfilter_lock ); + if (vout->p->vfilter_chain) { + if (!filter_chain_MouseFilter(vout->p->vfilter_chain, &tmp, m)) + m = &tmp; + } + vlc_mutex_unlock( &vout->p->vfilter_lock ); + if (vlc_mouse_HasMoved(&vout->p->mouse, m)) { vout_SendEventMouseMoved(vout, m->i_x, m->i_y); } @@ -1325,12 +1444,32 @@ void vout_SendDisplayEventMouse(vout_thread_t *vout, const vlc_mouse_t *m) vout_SendEventMouseDoubleClick(vout); vout->p->mouse = *m; } +#ifdef ALLOW_DUMMY_VOUT +static void DummyVoutSendDisplayEventMouse(vout_thread_t *vout, vlc_mouse_t *fallback, const vlc_mouse_t *m) +{ + vout_thread_sys_t p; + + if (!vout->p) { + p.mouse = *fallback; + vlc_mutex_init(&p.vfilter_lock); + p.vfilter_chain = NULL; + p.p_spu = NULL; + vout->p = &p; + } + vout_SendDisplayEventMouse(vout, m); + if (vout->p == &p) { + vlc_mutex_destroy(&p.vfilter_lock); + *fallback = p.mouse; + vout->p = NULL; + } +} +#endif vout_window_t * vout_NewDisplayWindow(vout_thread_t *vout, vout_display_t *vd, const vout_window_cfg_t *cfg) { VLC_UNUSED(vd); vout_window_cfg_t cfg_override = *cfg; - if( !config_GetInt( vout, "embedded-video" ) ) + if( !var_InheritBool( vout, "embedded-video" ) ) cfg_override.is_standalone = true; return vout_window_New(VLC_OBJECT(vout), NULL, &cfg_override);