/***************************************************************************** * Control: control facility for the vout *****************************************************************************/ 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: { POINTL ptl; WinQueryPointerPos( HWND_DESKTOP, &ptl ); if( WinWindowFromPoint( HWND_DESKTOP, &ptl, TRUE ) == sys->client ) { WinShowPointer( HWND_DESKTOP, FALSE ); sys->is_mouse_hidden = true; } return VLC_SUCCESS; } case VOUT_DISPLAY_CHANGE_FULLSCREEN: { vout_display_cfg_t cfg = *va_arg(args, const vout_display_cfg_t *); if( sys->parent_window ) vout_window_SetFullScreen(sys->parent_window, cfg.is_fullscreen); else WinPostMsg( sys->client, WM_VLC_FULLSCREEN_CHANGE, MPFROMLONG( cfg.is_fullscreen ), 0 ); return VLC_SUCCESS; } case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE: { const vout_display_cfg_t *cfg = va_arg(args, const vout_display_cfg_t *); bool is_forced = va_arg(args, int); if( is_forced ) { if( sys->parent_window ) { vout_window_SetSize(sys->parent_window, cfg->display.width, cfg->display.height); /* Workaround : * If changing aspect ratio after resizing a main window, * an embedded window is misplaced. So reposition it, here. */ WinSetWindowPos( WinQueryWindow( sys->parent, QW_PARENT ), HWND_TOP, 0, 1, 0, 0, SWP_MOVE ); WinSetWindowPos( WinQueryWindow( sys->parent, QW_PARENT ), HWND_TOP, 0, 0, 0, 0, SWP_MOVE ); } else WinPostMsg( sys->client, WM_VLC_SIZE_CHANGE, MPFROMLONG( cfg->display.width ), MPFROMLONG( cfg->display.height )); } return VLC_SUCCESS; } case VOUT_DISPLAY_CHANGE_SOURCE_ASPECT: case VOUT_DISPLAY_CHANGE_SOURCE_CROP: { const video_format_t *source = va_arg(args, const video_format_t *); if( query == VOUT_DISPLAY_CHANGE_SOURCE_ASPECT ) { sys->kvas.ulAspectWidth = ( int64_t )source->i_width * source->i_sar_num / source->i_sar_den; sys->kvas.ulAspectHeight = source->i_height; } else { sys->kvas.rclSrcRect.xLeft = source->i_x_offset; sys->kvas.rclSrcRect.yTop = source->i_y_offset; sys->kvas.rclSrcRect.xRight = source->i_x_offset + source->i_visible_width; sys->kvas.rclSrcRect.yBottom = source->i_y_offset + source->i_visible_height; } kvaSetup( &sys->kvas ); return VLC_SUCCESS; } case VOUT_DISPLAY_RESET_PICTURES: case VOUT_DISPLAY_CHANGE_WINDOW_STATE: case VOUT_DISPLAY_CHANGE_DISPLAY_FILLED: case VOUT_DISPLAY_CHANGE_ZOOM: case VOUT_DISPLAY_GET_OPENGL: /* TODO */ break; } msg_Err(vd, "Unsupported query(=%d) in vout display KVA", query); return VLC_EGENERIC; }
/***************************************************************************** * OpenDisplay: open and initialize KVA device ***************************************************************************** * Open and initialize display according to preferences specified in the vout * thread fields. *****************************************************************************/ static int OpenDisplay( vout_display_t *vd, video_format_t *fmt ) { vout_display_sys_t * sys = vd->sys; const vlc_fourcc_t *fallback; bool b_hw_accel = 0; FOURCC i_kva_fourcc; int i_chroma_shift; char sz_title[ 256 ]; RECTL rcl; int w, h; msg_Dbg( vd, "render chroma = %4.4s", ( const char * )&fmt->i_chroma ); for( int pass = 0; pass < 2 && !b_hw_accel; pass++ ) { fallback = ( pass == 0 ) ? vlc_fourcc_GetYUVFallback( fmt->i_chroma ) : vlc_fourcc_GetRGBFallback( fmt->i_chroma ); for( int i = 0; fallback[ i ]; i++ ) { switch( fallback[ i ]) { case VLC_CODEC_YV12: b_hw_accel = sys->kvac.ulInputFormatFlags & KVAF_YV12; i_kva_fourcc = FOURCC_YV12; i_chroma_shift = 1; break; case VLC_CODEC_YUYV: b_hw_accel = sys->kvac.ulInputFormatFlags & KVAF_YUY2; i_kva_fourcc = FOURCC_Y422; i_chroma_shift = 0; break; case VLC_CODEC_YV9: b_hw_accel = sys->kvac.ulInputFormatFlags & KVAF_YVU9; i_kva_fourcc = FOURCC_YVU9; i_chroma_shift = 2; break; case VLC_CODEC_RGB32: b_hw_accel = sys->kvac.ulInputFormatFlags & KVAF_BGR32; i_kva_fourcc = FOURCC_BGR4; i_chroma_shift = 0; break; case VLC_CODEC_RGB24: b_hw_accel = sys->kvac.ulInputFormatFlags & KVAF_BGR24; i_kva_fourcc = FOURCC_BGR3; i_chroma_shift = 0; break; case VLC_CODEC_RGB16: b_hw_accel = sys->kvac.ulInputFormatFlags & KVAF_BGR16; i_kva_fourcc = FOURCC_R565; i_chroma_shift = 0; break; case VLC_CODEC_RGB15: b_hw_accel = sys->kvac.ulInputFormatFlags & KVAF_BGR15; i_kva_fourcc = FOURCC_R555; i_chroma_shift = 0; break; } if( b_hw_accel ) { fmt->i_chroma = fallback[ i ]; break; } } } if( !b_hw_accel ) { msg_Err( vd, "Ooops. There is no fourcc supported by KVA at all."); return VLC_EGENERIC; } /* Set the RGB masks */ fmt->i_rmask = sys->kvac.ulRMask; fmt->i_gmask = sys->kvac.ulGMask; fmt->i_bmask = sys->kvac.ulBMask; msg_Dbg( vd, "output chroma = %4.4s", ( const char * )&fmt->i_chroma ); msg_Dbg( vd, "KVA chroma = %4.4s", ( const char * )&i_kva_fourcc ); w = vd->source.i_width; h = vd->source.i_height; sys->kvas.ulLength = sizeof( KVASETUP ); sys->kvas.szlSrcSize.cx = w; sys->kvas.szlSrcSize.cy = h; sys->kvas.rclSrcRect.xLeft = 0; sys->kvas.rclSrcRect.yTop = 0; sys->kvas.rclSrcRect.xRight = w; sys->kvas.rclSrcRect.yBottom = h; sys->kvas.ulRatio = KVAR_FORCEANY; sys->kvas.ulAspectWidth = w; sys->kvas.ulAspectHeight = h; sys->kvas.fccSrcColor = i_kva_fourcc; sys->kvas.fDither = TRUE; if( kvaSetup( &sys->kvas )) { msg_Err( vd, "cannot set up KVA"); return VLC_EGENERIC; } /* Create the associated picture */ picture_resource_t *rsc = &sys->resource; rsc->p_sys = malloc( sizeof( *rsc->p_sys )); if( !rsc->p_sys ) return VLC_EGENERIC; rsc->p_sys->i_chroma_shift = i_chroma_shift; for( int i = 0; i < PICTURE_PLANE_MAX; i++ ) { rsc->p[ i ].p_pixels = NULL; rsc->p[ i ].i_pitch = 0; rsc->p[ i ].i_lines = 0; } picture_t *picture = picture_NewFromResource( fmt, rsc ); if( !picture ) goto exit_picture; /* Wrap it into a picture pool */ picture_pool_configuration_t pool_cfg; memset( &pool_cfg, 0, sizeof( pool_cfg )); pool_cfg.picture_count = 1; pool_cfg.picture = &picture; pool_cfg.lock = KVALock; pool_cfg.unlock = KVAUnlock; sys->pool = picture_pool_NewExtended( &pool_cfg ); if( !sys->pool ) { picture_Release( picture ); goto exit_picture; } if (vd->cfg->display.title) snprintf( sz_title, sizeof( sz_title ), "%s", vd->cfg->display.title ); else snprintf( sz_title, sizeof( sz_title ), "%s (%4.4s to %4.4s - %s mode KVA output)", VOUT_TITLE, ( char * )&vd->fmt.i_chroma, ( char * )&sys->kvas.fccSrcColor, psz_video_mode[ sys->kvac.ulMode - 1 ]); WinSetWindowText( sys->frame, sz_title ); sys->i_screen_width = WinQuerySysValue( HWND_DESKTOP, SV_CXSCREEN ); sys->i_screen_height = WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN ); if( sys->parent_window ) WinQueryWindowRect( sys->parent, &sys->client_rect ); else { sys->client_rect.xLeft = ( sys->i_screen_width - w ) / 2; sys->client_rect.yBottom = ( sys->i_screen_height - h ) / 2 ; sys->client_rect.xRight = sys->client_rect.xLeft + w; sys->client_rect.yTop = sys->client_rect.yBottom + h; } rcl = sys->client_rect; WinCalcFrameRect( sys->frame, &rcl, FALSE); WinSetWindowPos( sys->frame, HWND_TOP, rcl.xLeft, rcl.yBottom, rcl.xRight - rcl.xLeft, rcl.yTop - rcl.yBottom, SWP_MOVE | SWP_SIZE | SWP_ZORDER | SWP_SHOW | SWP_ACTIVATE ); return VLC_SUCCESS; exit_picture: free( rsc->p_sys ); return VLC_EGENERIC; }
/***************************************************************************** * Control: control facility for the vout *****************************************************************************/ 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: { POINTL ptl; WinQueryPointerPos( HWND_DESKTOP, &ptl ); if( !sys->is_mouse_hidden && WinWindowFromPoint( HWND_DESKTOP, &ptl, TRUE ) == sys->client ) { WinShowPointer( HWND_DESKTOP, FALSE ); sys->is_mouse_hidden = true; } return VLC_SUCCESS; } case VOUT_DISPLAY_CHANGE_FULLSCREEN: { bool fs = va_arg(args, int); WinPostMsg( sys->client, WM_VLC_FULLSCREEN_CHANGE, MPFROMLONG(fs), 0 ); return VLC_SUCCESS; } case VOUT_DISPLAY_CHANGE_WINDOW_STATE: { const unsigned state = va_arg( args, unsigned ); const bool is_on_top = (state & VOUT_WINDOW_STATE_ABOVE) != 0; if( is_on_top ) WinSetWindowPos( sys->frame, HWND_TOP, 0, 0, 0, 0, SWP_ZORDER ); sys->is_on_top = is_on_top; return VLC_SUCCESS; } case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE: case VOUT_DISPLAY_CHANGE_ZOOM: { const vout_display_cfg_t *cfg = va_arg(args, const vout_display_cfg_t *); WinPostMsg( sys->client, WM_VLC_SIZE_CHANGE, MPFROMLONG( cfg->display.width ), MPFROMLONG( cfg->display.height )); return VLC_SUCCESS; } case VOUT_DISPLAY_CHANGE_SOURCE_ASPECT: case VOUT_DISPLAY_CHANGE_SOURCE_CROP: { if( query == VOUT_DISPLAY_CHANGE_SOURCE_ASPECT ) { vout_display_place_t place; vout_display_PlacePicture(&place, &vd->source, vd->cfg, false); sys->kvas.ulAspectWidth = place.width; sys->kvas.ulAspectHeight = place.height; } else { video_format_t src_rot; video_format_ApplyRotation(&src_rot, &vd->source); sys->kvas.rclSrcRect.xLeft = src_rot.i_x_offset; sys->kvas.rclSrcRect.yTop = src_rot.i_y_offset; sys->kvas.rclSrcRect.xRight = src_rot.i_x_offset + src_rot.i_visible_width; sys->kvas.rclSrcRect.yBottom = src_rot.i_y_offset + src_rot.i_visible_height; } kvaSetup( &sys->kvas ); return VLC_SUCCESS; } case VOUT_DISPLAY_RESET_PICTURES: case VOUT_DISPLAY_CHANGE_DISPLAY_FILLED: /* TODO */ break; } msg_Err(vd, "Unsupported query(=%d) in vout display KVA", query); return VLC_EGENERIC; }