/** * Control for vout display */ static int Control(vout_display_t *vd, int query, va_list args) { VLC_UNUSED(args); vout_display_sys_t *sys = vd->sys; switch (query) { case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE: /* We have to ignore what is requested */ vout_display_SendEventPicturesInvalid(vd); return VLC_SUCCESS; case VOUT_DISPLAY_RESET_PICTURES: if (sys->pool) picture_pool_Release(sys->pool); sys->pool = NULL; vd->fmt.i_width = aa_imgwidth(sys->aa_context); vd->fmt.i_height = aa_imgheight(sys->aa_context); return VLC_SUCCESS; case VOUT_DISPLAY_HIDE_MOUSE: aa_hidemouse(sys->aa_context); return VLC_SUCCESS; default: msg_Err(vd, "Unsupported query in vout display aalib"); return VLC_EGENERIC; } }
static void Manage(vout_display_t *vd) { vout_display_sys_t *sys = vd->sys; CommonManage(vd); if (sys->changes & DX_POSITION_CHANGE) { /* Update overlay */ if (sys->use_overlay) DirectXUpdateOverlay(vd, NULL); /* Check if we are still on the same monitor */ HMONITOR hmon = MonitorFromWindow(sys->hwnd, MONITOR_DEFAULTTONEAREST); if (sys->hmonitor != hmon) { vout_display_SendEventPicturesInvalid(vd); } /* */ sys->changes &= ~DX_POSITION_CHANGE; } /* Wallpaper mode change */ vlc_mutex_lock(&sys->lock); const bool ch_wallpaper = sys->ch_wallpaper; const bool wallpaper_requested = sys->wallpaper_requested; sys->ch_wallpaper = false; vlc_mutex_unlock(&sys->lock); if (ch_wallpaper) WallpaperChange(vd, wallpaper_requested); /* */ if (sys->restore_overlay) DirectXUpdateOverlay(vd, NULL); }
static int Control( vout_display_t *vd, int i_query, va_list ap ) { vout_display_sys_t *sys = vd->sys; switch( i_query ) { case VOUT_DISPLAY_CHANGE_SOURCE_ASPECT: { const video_format_t *p_source; vout_display_place_t place; video_format_t fmt; msg_Dbg( vd, "VOUT_DISPLAY_CHANGE_SOURCE_ASPECT" ); p_source = va_arg( ap, const video_format_t * ); video_format_ApplyRotation( &fmt, p_source ); vout_display_PlacePicture( &place, &fmt, vd->cfg, false ); if( place.width != (unsigned) sys->i_width && place.height != (unsigned) sys->i_height ) { if( vd->info.has_pictures_invalid ) { msg_Warn( vd, "ratio changed: invalidate pictures" ); vout_display_SendEventPicturesInvalid( vd ); } else return VLC_EGENERIC; } return VLC_SUCCESS; } case VOUT_DISPLAY_CHANGE_FULLSCREEN: return VLC_SUCCESS; case VOUT_DISPLAY_RESET_PICTURES: msg_Dbg( vd, "VOUT_DISPLAY_RESET_PICTURES" ); EcoreMainLoopCallSync( vd, EvasResetMainloopCb ); BuffersClean( vd ); if( sys->p_pool ) { picture_pool_Release( sys->p_pool ); sys->p_pool = NULL; } return VLC_SUCCESS; case VOUT_DISPLAY_CHANGE_ZOOM: case VOUT_DISPLAY_CHANGE_SOURCE_CROP: case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE: case VOUT_DISPLAY_CHANGE_DISPLAY_FILLED: case VOUT_DISPLAY_HIDE_MOUSE: return VLC_EGENERIC; default: msg_Warn( vd, "Unknown request in evas_output" ); return VLC_EGENERIC; } }
static void Prepare(vout_display_t *vd, picture_t *picture, subpicture_t *subpicture) { vout_display_sys_t *sys = vd->sys; LPDIRECT3DSURFACE9 surface = picture->p_sys->surface; #if 0 picture_Release(picture); VLC_UNUSED(subpicture); #else /* FIXME it is a bit ugly, we need the surface to be unlocked for * rendering. * The clean way would be to release the picture (and ensure that * the vout doesn't keep a reference). But because of the vout * wrapper, we can't */ Direct3DUnlockSurface(picture); VLC_UNUSED(subpicture); #endif /* check if device is still available */ HRESULT hr = IDirect3DDevice9_TestCooperativeLevel(sys->d3ddev); if (FAILED(hr)) { if (hr == D3DERR_DEVICENOTRESET && !sys->reset_device) { vout_display_SendEventPicturesInvalid(vd); sys->reset_device = true; sys->lost_not_ready = false; } if (hr == D3DERR_DEVICELOST && !sys->lost_not_ready) { /* Device is lost but not yet ready for reset. */ sys->lost_not_ready = true; } return; } d3d_region_t picture_region; if (!Direct3DImportPicture(vd, &picture_region, surface)) { int subpicture_region_count = 0; d3d_region_t *subpicture_region = NULL; if (subpicture) Direct3DImportSubpicture(vd, &subpicture_region_count, &subpicture_region, subpicture); Direct3DRenderScene(vd, &picture_region, subpicture_region_count, subpicture_region); Direct3DDeleteRegions(sys->d3dregion_count, sys->d3dregion); sys->d3dregion_count = subpicture_region_count; sys->d3dregion = subpicture_region; } }
static void Manage (vout_display_t *vd) { vout_display_sys_t *sys = vd->sys; CommonManage(vd); /* Desktop mode change */ vlc_mutex_lock(&sys->lock); const bool ch_desktop = sys->ch_desktop; sys->ch_desktop = false; vlc_mutex_unlock(&sys->lock); if (ch_desktop) { sys->reopen_device = true; vout_display_SendEventPicturesInvalid(vd); } #if 0 /* * Position Change */ if (sys->changes & DX_POSITION_CHANGE) { #if 0 /* need that when bicubic filter is available */ RECT rect; UINT width, height; GetClientRect(p_sys->hvideownd, &rect); width = rect.right-rect.left; height = rect.bottom-rect.top; if (width != p_sys->d3dpp.BackBufferWidth || height != p_sys->d3dpp.BackBufferHeight) { msg_Dbg(vd, "resizing device back buffers to (%lux%lu)", width, height); // need to reset D3D device to resize back buffer if (VLC_SUCCESS != Direct3DResetDevice(vd, width, height)) return VLC_EGENERIC; } #endif sys->changes &= ~DX_POSITION_CHANGE; } #endif }
/** * Control for vout display */ static int Control(vout_display_t *vd, int query, va_list args) { vout_display_sys_t *sys = vd->sys; switch (query) { case VOUT_DISPLAY_HIDE_MOUSE: SDL_ShowCursor(0); return VLC_SUCCESS; case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE: { const vout_display_cfg_t *cfg = va_arg(args, const vout_display_cfg_t *); /* */ sys->display = SDL_SetVideoMode(cfg->display.width, cfg->display.height, sys->display_bpp, sys->display_flags); if (!sys->display) { sys->display = SDL_SetVideoMode(vd->cfg->display.width, vd->cfg->display.height, sys->display_bpp, sys->display_flags); return VLC_EGENERIC; } if (sys->overlay) vout_display_PlacePicture(&sys->place, &vd->source, cfg, !sys->overlay); else vout_display_SendEventPicturesInvalid(vd); return VLC_SUCCESS; } case VOUT_DISPLAY_CHANGE_FULLSCREEN: { vout_display_cfg_t cfg = *va_arg(args, const vout_display_cfg_t *); /* Fix flags */ sys->display_flags &= ~(SDL_FULLSCREEN | SDL_RESIZABLE); sys->display_flags |= cfg.is_fullscreen ? SDL_FULLSCREEN : SDL_RESIZABLE; if (cfg.is_fullscreen) { cfg.display.width = sys->desktop_width; cfg.display.height = sys->desktop_height; } if (sys->overlay) { sys->display = SDL_SetVideoMode(cfg.display.width, cfg.display.height, sys->display_bpp, sys->display_flags); vout_display_PlacePicture(&sys->place, &vd->source, &cfg, !sys->overlay); } vout_display_SendEventDisplaySize(vd, cfg.display.width, cfg.display.height, cfg.is_fullscreen); return VLC_SUCCESS; } case VOUT_DISPLAY_CHANGE_ZOOM: case VOUT_DISPLAY_CHANGE_DISPLAY_FILLED: case VOUT_DISPLAY_CHANGE_SOURCE_ASPECT: { const vout_display_cfg_t *cfg; const video_format_t *source; if (query == VOUT_DISPLAY_CHANGE_SOURCE_ASPECT) { source = va_arg(args, const video_format_t *); cfg = vd->cfg; } else { source = &vd->source; cfg = va_arg(args, const vout_display_cfg_t *); } if (sys->overlay) { sys->display = SDL_SetVideoMode(cfg->display.width, cfg->display.height, sys->display_bpp, sys->display_flags); vout_display_PlacePicture(&sys->place, source, cfg, !sys->overlay); } else { vout_display_SendEventPicturesInvalid(vd); } return VLC_SUCCESS; }
/** * It copies picture surface into a texture and renders into a scene. * * This function is intented for higher end 3D cards, with pixel shader support * and at least 64 MiB of video RAM. */ static void Direct3DRenderScene(vout_display_t *vd, LPDIRECT3DSURFACE9 surface) { vout_display_sys_t *sys = vd->sys; LPDIRECT3DDEVICE9 d3ddev = sys->d3ddev; HRESULT hr; // check if device is still available hr = IDirect3DDevice9_TestCooperativeLevel(d3ddev); if (FAILED(hr)) { if (hr == D3DERR_DEVICENOTRESET && !sys->reset_device) { vout_display_SendEventPicturesInvalid(vd); sys->reset_device = true; } return; } /* */ LPDIRECT3DTEXTURE9 d3dtex = sys->d3dtex; LPDIRECT3DVERTEXBUFFER9 d3dvtc = sys->d3dvtc; /* Clear the backbuffer and the zbuffer */ hr = IDirect3DDevice9_Clear(d3ddev, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); if (FAILED(hr)) { msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr); return; } /* retrieve picture surface */ LPDIRECT3DSURFACE9 d3dsrc = surface; if (!d3dsrc) { msg_Dbg(vd, "no surface to render ?"); return; } /* retrieve texture top-level surface */ LPDIRECT3DSURFACE9 d3ddest; hr = IDirect3DTexture9_GetSurfaceLevel(d3dtex, 0, &d3ddest); if (FAILED(hr)) { msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr); return; } /* Copy picture surface into texture surface * color space conversion and scaling happen here */ RECT src = vd->sys->rect_src_clipped; RECT dst = vd->sys->rect_dest_clipped; hr = IDirect3DDevice9_StretchRect(d3ddev, d3dsrc, &src, d3ddest, &dst, D3DTEXF_LINEAR); IDirect3DSurface9_Release(d3ddest); if (FAILED(hr)) { msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr); return; } /* Update the vertex buffer */ CUSTOMVERTEX *vertices; hr = IDirect3DVertexBuffer9_Lock(d3dvtc, 0, 0, (void **)&vertices, D3DLOCK_DISCARD); if (FAILED(hr)) { msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr); return; } /* Setup vertices */ const float f_width = vd->sys->d3dpp.BackBufferWidth; const float f_height = vd->sys->d3dpp.BackBufferHeight; /* -0.5f is a "feature" of DirectX and it seems to apply to Direct3d also */ /* http://www.sjbrown.co.uk/2003/05/01/fix-directx-rasterisation/ */ vertices[0].x = -0.5f; // left vertices[0].y = -0.5f; // top vertices[0].z = 0.0f; vertices[0].diffuse = D3DCOLOR_ARGB(255, 255, 255, 255); vertices[0].rhw = 1.0f; vertices[0].tu = 0.0f; vertices[0].tv = 0.0f; vertices[1].x = f_width - 0.5f; // right vertices[1].y = -0.5f; // top vertices[1].z = 0.0f; vertices[1].diffuse = D3DCOLOR_ARGB(255, 255, 255, 255); vertices[1].rhw = 1.0f; vertices[1].tu = 1.0f; vertices[1].tv = 0.0f; vertices[2].x = f_width - 0.5f; // right vertices[2].y = f_height - 0.5f; // bottom vertices[2].z = 0.0f; vertices[2].diffuse = D3DCOLOR_ARGB(255, 255, 255, 255); vertices[2].rhw = 1.0f; vertices[2].tu = 1.0f; vertices[2].tv = 1.0f; vertices[3].x = -0.5f; // left vertices[3].y = f_height - 0.5f; // bottom vertices[3].z = 0.0f; vertices[3].diffuse = D3DCOLOR_ARGB(255, 255, 255, 255); vertices[3].rhw = 1.0f; vertices[3].tu = 0.0f; vertices[3].tv = 1.0f; hr= IDirect3DVertexBuffer9_Unlock(d3dvtc); if (FAILED(hr)) { msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr); return; } // Begin the scene hr = IDirect3DDevice9_BeginScene(d3ddev); if (FAILED(hr)) { msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr); return; } // Setup our texture. Using textures introduces the texture stage states, // which govern how textures get blended together (in the case of multiple // textures) and lighting information. In this case, we are modulating // (blending) our texture with the diffuse color of the vertices. hr = IDirect3DDevice9_SetTexture(d3ddev, 0, (LPDIRECT3DBASETEXTURE9)d3dtex); if (FAILED(hr)) { msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr); IDirect3DDevice9_EndScene(d3ddev); return; } // Render the vertex buffer contents hr = IDirect3DDevice9_SetStreamSource(d3ddev, 0, d3dvtc, 0, sizeof(CUSTOMVERTEX)); if (FAILED(hr)) { msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr); IDirect3DDevice9_EndScene(d3ddev); return; } // we use FVF instead of vertex shader hr = IDirect3DDevice9_SetFVF(d3ddev, D3DFVF_CUSTOMVERTEX); if (FAILED(hr)) { msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr); IDirect3DDevice9_EndScene(d3ddev); return; } // draw rectangle hr = IDirect3DDevice9_DrawPrimitive(d3ddev, D3DPT_TRIANGLEFAN, 0, 2); if (FAILED(hr)) { msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr); IDirect3DDevice9_EndScene(d3ddev); return; } // End the scene hr = IDirect3DDevice9_EndScene(d3ddev); if (FAILED(hr)) { msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr); return; } }
static int Control (vout_display_t *vd, int query, va_list ap) { vout_display_sys_t *sys = vd->sys; switch (query) { case VOUT_DISPLAY_CHANGE_FULLSCREEN: { const vout_display_cfg_t *c = va_arg (ap, const vout_display_cfg_t *); return vout_window_SetFullScreen (sys->embed, c->is_fullscreen); } case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE: { const vout_display_cfg_t *p_cfg = (const vout_display_cfg_t*)va_arg (ap, const vout_display_cfg_t *); const bool is_forced = (bool)va_arg (ap, int); if (is_forced) { /* Changing the dimensions of the parent window takes place * asynchronously (in the X server). Also it might fail or result * in different dimensions than requested. Request the size change * and return a failure since the size is not (yet) changed. * If the change eventually succeeds, HandleParentStructure() * will trigger a non-forced display size change later. */ vout_window_SetSize (sys->embed, p_cfg->display.width, p_cfg->display.height); return VLC_EGENERIC; } vout_display_place_t place; vout_display_PlacePicture (&place, &vd->source, p_cfg, false); if (place.width != vd->fmt.i_visible_width || place.height != vd->fmt.i_visible_height) { vout_display_SendEventPicturesInvalid (vd); return VLC_SUCCESS; } /* Move the picture within the window */ const uint32_t values[] = { place.x, place.y }; xcb_configure_window (sys->conn, sys->window, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, values); return VLC_SUCCESS; } case VOUT_DISPLAY_CHANGE_WINDOW_STATE: { unsigned state = va_arg (ap, unsigned); return vout_window_SetState (sys->embed, state); } case VOUT_DISPLAY_CHANGE_ZOOM: case VOUT_DISPLAY_CHANGE_DISPLAY_FILLED: case VOUT_DISPLAY_CHANGE_SOURCE_ASPECT: case VOUT_DISPLAY_CHANGE_SOURCE_CROP: /* I am not sure it is always necessary, but it is way simpler ... */ vout_display_SendEventPicturesInvalid (vd); return VLC_SUCCESS; case VOUT_DISPLAY_RESET_PICTURES: { ResetPictures (vd); vout_display_place_t place; vout_display_PlacePicture (&place, &vd->source, vd->cfg, false); vd->fmt.i_width = vd->source.i_width * place.width / vd->source.i_visible_width; vd->fmt.i_height = vd->source.i_height * place.height / vd->source.i_visible_height; vd->fmt.i_visible_width = place.width; vd->fmt.i_visible_height = place.height; vd->fmt.i_x_offset = vd->source.i_x_offset * place.width / vd->source.i_visible_width; vd->fmt.i_y_offset = vd->source.i_y_offset * place.height / vd->source.i_visible_height; return VLC_SUCCESS; } /* Hide the mouse. It will be send when * vout_display_t::info.b_hide_mouse is false */ case VOUT_DISPLAY_HIDE_MOUSE: xcb_change_window_attributes (sys->conn, sys->embed->handle.xid, XCB_CW_CURSOR, &(uint32_t){ sys->cursor }); xcb_flush (sys->conn); return VLC_SUCCESS; default: msg_Err (vd, "Unknown request in XCB vout display"); return VLC_EGENERIC; } }
/***************************************************************************** * UpdateRects: update clipping rectangles ***************************************************************************** * This function is called when the window position or size are changed, and * its job is to update the source and destination RECTs used to display the * picture. *****************************************************************************/ void UpdateRects(vout_display_t *vd, const vout_display_cfg_t *cfg, const video_format_t *source, bool is_forced) { vout_display_sys_t *sys = vd->sys; #define rect_src sys->rect_src #define rect_src_clipped sys->rect_src_clipped #define rect_dest sys->rect_dest #define rect_dest_clipped sys->rect_dest_clipped RECT rect; POINT point; /* */ if (!cfg) cfg = vd->cfg; if (!source) source = &vd->source; /* Retrieve the window size */ GetClientRect(sys->hwnd, &rect); /* Retrieve the window position */ point.x = point.y = 0; ClientToScreen(sys->hwnd, &point); /* If nothing changed, we can return */ bool has_moved; bool is_resized; EventThreadUpdateWindowPosition(sys->event, &has_moved, &is_resized, point.x, point.y, rect.right, rect.bottom); if (is_resized) vout_display_SendEventDisplaySize(vd, rect.right, rect.bottom, cfg->is_fullscreen); if (!is_forced && !has_moved && !is_resized ) return; /* Update the window position and size */ vout_display_cfg_t place_cfg = *cfg; place_cfg.display.width = rect.right; place_cfg.display.height = rect.bottom; vout_display_place_t place; vout_display_PlacePicture(&place, source, &place_cfg, false); EventThreadUpdateSourceAndPlace(sys->event, source, &place); #if defined(MODULE_NAME_IS_wingapi) if (place.width != vd->fmt.i_width || place.height != vd->fmt.i_height) vout_display_SendEventPicturesInvalid(vd); #endif if (sys->hvideownd) SetWindowPos(sys->hvideownd, 0, place.x, place.y, place.width, place.height, SWP_NOCOPYBITS|SWP_NOZORDER|SWP_ASYNCWINDOWPOS); /* Destination image position and dimensions */ #if defined(MODULE_NAME_IS_direct3d) rect_dest.left = 0; rect_dest.right = place.width; rect_dest.top = 0; rect_dest.bottom = place.height; #else rect_dest.left = point.x + place.x; rect_dest.right = rect_dest.left + place.width; rect_dest.top = point.y + place.y; rect_dest.bottom = rect_dest.top + place.height; #ifdef MODULE_NAME_IS_directx /* Apply overlay hardware constraints */ if (sys->use_overlay) AlignRect(&rect_dest, sys->i_align_dest_boundary, sys->i_align_dest_size); #endif #endif #if defined(MODULE_NAME_IS_directx) || defined(MODULE_NAME_IS_direct3d) /* UpdateOverlay directdraw function doesn't automatically clip to the * display size so we need to do it otherwise it will fail * It is also needed for d3d to avoid exceding our surface size */ /* Clip the destination window */ if (!IntersectRect(&rect_dest_clipped, &rect_dest, &sys->rect_display)) { SetRectEmpty(&rect_src_clipped); goto exit; } #ifndef NDEBUG msg_Dbg(vd, "DirectXUpdateRects image_dst_clipped coords:" " %li,%li,%li,%li", rect_dest_clipped.left, rect_dest_clipped.top, rect_dest_clipped.right, rect_dest_clipped.bottom); #endif #else /* AFAIK, there are no clipping constraints in Direct3D, OpenGL and GDI */ rect_dest_clipped = rect_dest; #endif /* the 2 following lines are to fix a bug when clicking on the desktop */ if ((rect_dest_clipped.right - rect_dest_clipped.left) == 0 || (rect_dest_clipped.bottom - rect_dest_clipped.top) == 0) { SetRectEmpty(&rect_src_clipped); goto exit; } /* src image dimensions */ rect_src.left = 0; rect_src.top = 0; rect_src.right = source->i_width; rect_src.bottom = source->i_height; /* Clip the source image */ rect_src_clipped.left = source->i_x_offset + (rect_dest_clipped.left - rect_dest.left) * source->i_visible_width / (rect_dest.right - rect_dest.left); rect_src_clipped.right = source->i_x_offset + source->i_visible_width - (rect_dest.right - rect_dest_clipped.right) * source->i_visible_width / (rect_dest.right - rect_dest.left); rect_src_clipped.top = source->i_y_offset + (rect_dest_clipped.top - rect_dest.top) * source->i_visible_height / (rect_dest.bottom - rect_dest.top); rect_src_clipped.bottom = source->i_y_offset + source->i_visible_height - (rect_dest.bottom - rect_dest_clipped.bottom) * source->i_visible_height / (rect_dest.bottom - rect_dest.top); #ifdef MODULE_NAME_IS_directx /* Apply overlay hardware constraints */ if (sys->use_overlay) AlignRect(&rect_src_clipped, sys->i_align_src_boundary, sys->i_align_src_size); #elif defined(MODULE_NAME_IS_direct3d) /* Needed at least with YUV content */ rect_src_clipped.left &= ~1; rect_src_clipped.right &= ~1; rect_src_clipped.top &= ~1; rect_src_clipped.bottom &= ~1; #endif #ifndef NDEBUG msg_Dbg(vd, "DirectXUpdateRects image_src_clipped" " coords: %li,%li,%li,%li", rect_src_clipped.left, rect_src_clipped.top, rect_src_clipped.right, rect_src_clipped.bottom); #endif #ifdef MODULE_NAME_IS_directx /* The destination coordinates need to be relative to the current * directdraw primary surface (display) */ rect_dest_clipped.left -= sys->rect_display.left; rect_dest_clipped.right -= sys->rect_display.left; rect_dest_clipped.top -= sys->rect_display.top; rect_dest_clipped.bottom -= sys->rect_display.top; #endif CommonChangeThumbnailClip(vd, true); exit: /* Signal the change in size/position */ sys->changes |= DX_POSITION_CHANGE; #undef rect_src #undef rect_src_clipped #undef rect_dest #undef rect_dest_clipped }
static int Control (vout_display_t *vd, int query, va_list ap) { vout_display_sys_t *sys = vd->sys; switch (query) { case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE: { const vout_display_cfg_t *p_cfg = (const vout_display_cfg_t*)va_arg (ap, const vout_display_cfg_t *); vout_display_place_t place; vout_display_PlacePicture (&place, &vd->source, p_cfg, false); if (place.width != vd->fmt.i_visible_width || place.height != vd->fmt.i_visible_height) { vout_display_SendEventPicturesInvalid (vd); return VLC_SUCCESS; } /* Move the picture within the window */ const uint32_t values[] = { place.x, place.y }; xcb_configure_window (sys->conn, sys->window, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, values); return VLC_SUCCESS; } case VOUT_DISPLAY_CHANGE_ZOOM: case VOUT_DISPLAY_CHANGE_DISPLAY_FILLED: case VOUT_DISPLAY_CHANGE_SOURCE_ASPECT: case VOUT_DISPLAY_CHANGE_SOURCE_CROP: /* I am not sure it is always necessary, but it is way simpler ... */ vout_display_SendEventPicturesInvalid (vd); return VLC_SUCCESS; case VOUT_DISPLAY_RESET_PICTURES: { ResetPictures (vd); vout_display_place_t place; vout_display_PlacePicture (&place, &vd->source, vd->cfg, false); video_format_t src; video_format_ApplyRotation(&src, &vd->source); vd->fmt.i_width = src.i_width * place.width / src.i_visible_width; vd->fmt.i_height = src.i_height * place.height / src.i_visible_height; vd->fmt.i_visible_width = place.width; vd->fmt.i_visible_height = place.height; vd->fmt.i_x_offset = src.i_x_offset * place.width / src.i_visible_width; vd->fmt.i_y_offset = src.i_y_offset * place.height / src.i_visible_height; return VLC_SUCCESS; } /* Hide the mouse. It will be send when * vout_display_t::info.b_hide_mouse is false */ case VOUT_DISPLAY_HIDE_MOUSE: xcb_change_window_attributes (sys->conn, sys->embed->handle.xid, XCB_CW_CURSOR, &(uint32_t){ sys->cursor }); xcb_flush (sys->conn); return VLC_SUCCESS; default: msg_Err (vd, "Unknown request in XCB vout display"); return VLC_EGENERIC; } }
static int Control (vout_display_t *vd, int query, va_list ap) { vout_display_sys_t *p_sys = vd->sys; switch (query) { case VOUT_DISPLAY_CHANGE_FULLSCREEN: { const vout_display_cfg_t *c = va_arg (ap, const vout_display_cfg_t *); return vout_window_SetFullScreen (p_sys->embed, c->is_fullscreen); } case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE: { const vout_display_cfg_t *p_cfg = (const vout_display_cfg_t*)va_arg (ap, const vout_display_cfg_t *); const bool is_forced = (bool)va_arg (ap, int); if (is_forced && vout_window_SetSize (p_sys->embed, p_cfg->display.width, p_cfg->display.height)) return VLC_EGENERIC; vout_display_place_t place; vout_display_PlacePicture (&place, &vd->source, p_cfg, false); if (place.width != vd->fmt.i_visible_width || place.height != vd->fmt.i_visible_height) { vout_display_SendEventPicturesInvalid (vd); return VLC_SUCCESS; } /* Move the picture within the window */ const uint32_t values[] = { place.x, place.y }; xcb_configure_window (p_sys->conn, p_sys->window, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, values); return VLC_SUCCESS; } case VOUT_DISPLAY_CHANGE_WINDOW_STATE: { unsigned state = va_arg (ap, unsigned); return vout_window_SetState (p_sys->embed, state); } case VOUT_DISPLAY_CHANGE_ZOOM: case VOUT_DISPLAY_CHANGE_DISPLAY_FILLED: case VOUT_DISPLAY_CHANGE_SOURCE_ASPECT: case VOUT_DISPLAY_CHANGE_SOURCE_CROP: /* I am not sure it is always necessary, but it is way simpler ... */ vout_display_SendEventPicturesInvalid (vd); return VLC_SUCCESS; case VOUT_DISPLAY_RESET_PICTURES: { ResetPictures (vd); vout_display_place_t place; vout_display_PlacePicture (&place, &vd->source, vd->cfg, false); vd->fmt.i_width = vd->source.i_width * place.width / vd->source.i_visible_width; vd->fmt.i_height = vd->source.i_height * place.height / vd->source.i_visible_height; vd->fmt.i_visible_width = place.width; vd->fmt.i_visible_height = place.height; vd->fmt.i_x_offset = vd->source.i_x_offset * place.width / vd->source.i_visible_width; vd->fmt.i_y_offset = vd->source.i_y_offset * place.height / vd->source.i_visible_height; return VLC_SUCCESS; } /* Hide the mouse. It will be send when * vout_display_t::info.b_hide_mouse is false */ case VOUT_DISPLAY_HIDE_MOUSE: xcb_change_window_attributes (p_sys->conn, p_sys->embed->handle.xid, XCB_CW_CURSOR, &(uint32_t){ p_sys->cursor }); xcb_flush (p_sys->conn); return VLC_SUCCESS; default: msg_Err (vd, "Unknown request in XCB vout display"); return VLC_EGENERIC; } }