Commit eff9d25c authored by Gildas Bazin's avatar Gildas Bazin

* modules/video_output/directx/*: first try at multimonitor support (untested).

* src/video_output/video_output.c: small change to allow the directx plugin to destroy/recreate picture buffers on the fly.
parent 658d4d7a
......@@ -2,7 +2,7 @@
* video_output.h : video output thread
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
* $Id: video_output.h,v 1.106 2003/12/09 19:15:03 yoann Exp $
* $Id: video_output.h,v 1.107 2003/12/11 23:12:46 gbazin Exp $
*
* Authors: Vincent Seguin <seguin@via.ecp.fr>
* Samuel Hocevar <sam@via.ecp.fr>
......@@ -177,6 +177,8 @@ struct vout_thread_t
#define VOUT_DEPTH_CHANGE 0x0400
/** change chroma tables */
#define VOUT_CHROMA_CHANGE 0x0800
/** change/recreate picture buffers */
#define VOUT_PICTURE_BUFFERS_CHANGE 0x1000
/**@}*/
/* Alignment flags */
......
......@@ -2,7 +2,7 @@
* vout.c: Windows DirectX video output display method
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: directx.c,v 1.26 2003/12/08 19:50:22 gbazin Exp $
* $Id: directx.c,v 1.27 2003/12/11 23:12:46 gbazin Exp $
*
* Authors: Gildas Bazin <gbazin@netcourrier.com>
*
......@@ -45,6 +45,9 @@
#include <windows.h>
#include <ddraw.h>
#include <multimon.h>
#undef GetSystemMetrics
#include "vout.h"
/*****************************************************************************
......@@ -136,6 +139,7 @@ static int OpenVideo( vlc_object_t *p_this )
{
vout_thread_t * p_vout = (vout_thread_t *)p_this;
vlc_value_t val, text;
HMODULE huser32;
/* Allocate structure */
p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
......@@ -159,11 +163,24 @@ static int OpenVideo( vlc_object_t *p_this )
p_vout->p_sys->hwnd = NULL;
p_vout->p_sys->hparent = NULL;
p_vout->p_sys->i_changes = 0;
SetRectEmpty( &p_vout->p_sys->rect_display );
p_vout->p_sys->b_using_overlay = config_GetInt( p_vout, "overlay" );
p_vout->p_sys->b_use_sysmem = config_GetInt( p_vout, "directx-use-sysmem");
p_vout->p_sys->b_hw_yuv = config_GetInt( p_vout, "directx-hw-yuv" );
p_vout->p_sys->b_3buf_overlay = config_GetInt( p_vout, "directx-3buffering" );
/* Multimonitor stuff */
p_vout->p_sys->hmonitor = NULL;
p_vout->p_sys->p_display_driver = NULL;
p_vout->p_sys->MonitorFromWindow = NULL;
p_vout->p_sys->GetMonitorInfo = NULL;
if( (huser32 = GetModuleHandle( "USER32" ) ) )
{
p_vout->p_sys->MonitorFromWindow =
GetProcAddress( huser32, "MonitorFromWindow" );
p_vout->p_sys->GetMonitorInfo =
GetProcAddress( huser32, "GetMonitorInfoA" );
}
var_Create( p_vout, "overlay", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
var_Create( p_vout, "directx-use-sysmem", VLC_VAR_BOOL|VLC_VAR_DOINHERIT );
var_Create( p_vout, "directx-hw-yuv", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
var_Create( p_vout, "directx-3buffering", VLC_VAR_BOOL|VLC_VAR_DOINHERIT );
p_vout->p_sys->b_cursor_hidden = 0;
p_vout->p_sys->i_lastmoved = mdate();
......@@ -183,9 +200,8 @@ static int OpenVideo( vlc_object_t *p_this )
p_vout->p_sys->p_event =
vlc_object_create( p_vout, sizeof(event_thread_t) );
p_vout->p_sys->p_event->p_vout = p_vout;
if( vlc_thread_create( p_vout->p_sys->p_event,
"DirectX Events Thread", DirectXEventThread,
0, 1 ) )
if( vlc_thread_create( p_vout->p_sys->p_event, "DirectX Events Thread",
DirectXEventThread, 0, 1 ) )
{
msg_Err( p_vout, "cannot create DirectXEventThread" );
vlc_object_destroy( p_vout->p_sys->p_event );
......@@ -241,6 +257,35 @@ static int OpenVideo( vlc_object_t *p_this )
static int Init( vout_thread_t *p_vout )
{
int i_chroma_backup;
vlc_value_t val;
/* Get a few default parameters */
var_Get( p_vout, "overlay", &val );
p_vout->p_sys->b_using_overlay = val.b_bool;
var_Get( p_vout, "directx-use-sysmem", &val );
p_vout->p_sys->b_use_sysmem = val.b_bool;
var_Get( p_vout, "directx-hw-yuv", &val );
p_vout->p_sys->b_hw_yuv = val.b_bool;
var_Get( p_vout, "directx-3buffering", &val );
p_vout->p_sys->b_3buf_overlay = val.b_bool;
/* Initialise DirectDraw if not already done.
* We do this here because on multi-monitor systems we may have to
* re-create the directdraw surfaces. */
if( !p_vout->p_sys->p_ddobject &&
DirectXInitDDraw( p_vout ) != VLC_SUCCESS )
{
msg_Err( p_vout, "cannot initialize DirectDraw" );
return VLC_EGENERIC;
}
/* Create the directx display */
if( !p_vout->p_sys->p_display &&
DirectXCreateDisplay( p_vout ) != VLC_SUCCESS )
{
msg_Err( p_vout, "cannot initialize DirectDraw" );
return VLC_EGENERIC;
}
/* Initialize the output structure.
* Since DirectDraw can do rescaling for us, stick to the default
......@@ -326,6 +371,10 @@ static int Init( vout_thread_t *p_vout )
static void End( vout_thread_t *p_vout )
{
FreePictureVec( p_vout, p_vout->p_picture, I_OUTPUTPICTURES );
DirectXCloseDisplay( p_vout );
DirectXCloseDDraw( p_vout );
return;
}
......@@ -360,9 +409,6 @@ static void CloseVideo( vlc_object_t *p_this )
vlc_object_destroy( p_vout->p_sys->p_event );
}
DirectXCloseDisplay( p_vout );
DirectXCloseDDraw( p_vout );
if( p_vout->p_sys )
{
free( p_vout->p_sys );
......@@ -387,37 +433,32 @@ static int Manage( vout_thread_t *p_vout )
DirectXUpdateRects( p_vout, VLC_FALSE );
}
/* We used to call the Win32 PeekMessage function here to read the window
* messages. But since window can stay blocked into this function for a
* long time (for example when you move your window on the screen), I
* decided to isolate PeekMessage in another thread. */
/*
* Scale Change
* Position Change
*/
if( p_vout->i_changes & VOUT_SCALE_CHANGE
|| p_vout->p_sys->i_changes & VOUT_SCALE_CHANGE )
if( p_vout->p_sys->i_changes & DX_POSITION_CHANGE )
{
msg_Dbg( p_vout, "scale change" );
if( p_vout->p_sys->b_using_overlay )
DirectXUpdateOverlay( p_vout );
p_vout->i_changes &= ~VOUT_SCALE_CHANGE;
p_vout->p_sys->i_changes &= ~VOUT_SCALE_CHANGE;
}
/*
* Size Change
*/
if( p_vout->i_changes & VOUT_SIZE_CHANGE
|| p_vout->p_sys->i_changes & VOUT_SIZE_CHANGE )
{
msg_Dbg( p_vout, "size change" );
if( p_vout->p_sys->b_using_overlay )
DirectXUpdateOverlay( p_vout );
p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
p_vout->p_sys->i_changes &= ~VOUT_SIZE_CHANGE;
/* Check if we are still on the same monitor */
if( p_vout->p_sys->MonitorFromWindow &&
p_vout->p_sys->hmonitor !=
p_vout->p_sys->MonitorFromWindow( p_vout->p_sys->hwnd,
MONITOR_DEFAULTTONEAREST ) )
{
/* This will force the vout core to recreate the picture buffers */
p_vout->i_changes |= VOUT_PICTURE_BUFFERS_CHANGE;
}
p_vout->p_sys->i_changes &= ~DX_POSITION_CHANGE;
}
/* We used to call the Win32 PeekMessage function here to read the window
* messages. But since window can stay blocked into this function for a
* long time (for example when you move your window on the screen), I
* decided to isolate PeekMessage in another thread. */
/*
* Fullscreen change
*/
......@@ -606,6 +647,14 @@ BOOL WINAPI DirectXEnumCallback( GUID* p_guid, LPTSTR psz_desc,
vout_thread_t *p_vout = (vout_thread_t *)p_context;
msg_Dbg( p_vout, "DirectXEnumCallback: %s, %s", psz_desc, psz_drivername );
if( hmon && hmon == p_vout->p_sys->hmonitor )
{
msg_Dbg( p_vout, "selecting %s, %s", psz_desc, psz_drivername );
p_vout->p_sys->p_display_driver = malloc( sizeof(GUID) );
if( p_vout->p_sys->p_display_driver )
memcpy( p_vout->p_sys->p_display_driver, p_guid, sizeof(GUID) );
}
return TRUE; /* Keep enumerating */
}
......@@ -624,7 +673,7 @@ static int DirectXInitDDraw( vout_thread_t *p_vout )
msg_Dbg( p_vout, "DirectXInitDDraw" );
/* load direct draw DLL */
/* Load direct draw DLL */
p_vout->p_sys->hddraw_dll = LoadLibrary("DDRAW.DLL");
if( p_vout->p_sys->hddraw_dll == NULL )
{
......@@ -644,15 +693,20 @@ static int DirectXInitDDraw( vout_thread_t *p_vout )
(void *)GetProcAddress( p_vout->p_sys->hddraw_dll,
"DirectDrawEnumerateExA" );
if( OurDirectDrawEnumerateEx )
if( OurDirectDrawEnumerateEx && p_vout->p_sys->MonitorFromWindow )
{
p_vout->p_sys->hmonitor =
p_vout->p_sys->MonitorFromWindow( p_vout->p_sys->hwnd,
MONITOR_DEFAULTTONEAREST );
/* Enumerate displays */
OurDirectDrawEnumerateEx( DirectXEnumCallback, p_vout,
DDENUM_ATTACHEDSECONDARYDEVICES );
}
/* Initialize DirectDraw now */
dxresult = OurDirectDrawCreate( NULL, &p_ddobject, NULL );
dxresult = OurDirectDrawCreate( p_vout->p_sys->p_display_driver,
&p_ddobject, NULL );
if( dxresult != DD_OK )
{
msg_Err( p_vout, "DirectXInitDDraw cannot initialize DDraw" );
......@@ -680,6 +734,27 @@ static int DirectXInitDDraw( vout_thread_t *p_vout )
goto error;
}
/* Get the size of the current display device */
if( p_vout->p_sys->hmonitor && p_vout->p_sys->GetMonitorInfo )
{
MONITORINFO monitor_info;
monitor_info.cbSize = sizeof( MONITORINFO );
p_vout->p_sys->GetMonitorInfo( p_vout->p_sys->hmonitor,
&monitor_info );
p_vout->p_sys->rect_display = monitor_info.rcMonitor;
}
else
{
p_vout->p_sys->rect_display.left = 0;
p_vout->p_sys->rect_display.top = 0;
p_vout->p_sys->rect_display.right = GetSystemMetrics(SM_CXSCREEN);
p_vout->p_sys->rect_display.bottom = GetSystemMetrics(SM_CYSCREEN);
}
msg_Dbg( p_vout, "screen dimensions %ix%i",
p_vout->p_sys->rect_display.right,
p_vout->p_sys->rect_display.bottom );
/* Probe the capabilities of the hardware */
DirectXGetDDrawCaps( p_vout );
......@@ -992,6 +1067,14 @@ static void DirectXCloseDDraw( vout_thread_t *p_vout )
FreeLibrary( p_vout->p_sys->hddraw_dll );
p_vout->p_sys->hddraw_dll = NULL;
}
if( p_vout->p_sys->p_display_driver != NULL )
{
free( p_vout->p_sys->p_display_driver );
p_vout->p_sys->p_display_driver = NULL;
}
p_vout->p_sys->hmonitor = NULL;
}
/*****************************************************************************
......@@ -1148,11 +1231,11 @@ static int NewPictureVec( vout_thread_t *p_vout, picture_t *p_pic,
* because a few buggy drivers don't mind creating the surface
* even if they don't know about the chroma. */
if( IDirectDraw2_GetFourCCCodes( p_vout->p_sys->p_ddobject,
&i_codes, NULL ) )
&i_codes, NULL ) == DD_OK )
{
pi_codes = malloc( i_codes * sizeof(DWORD) );
if( pi_codes && IDirectDraw2_GetFourCCCodes(
p_vout->p_sys->p_ddobject, &i_codes, pi_codes ) )
p_vout->p_sys->p_ddobject, &i_codes, pi_codes ) == DD_OK )
{
for( i = 0; i < (int)i_codes; i++ )
{
......@@ -1297,6 +1380,8 @@ static void FreePictureVec( vout_thread_t *p_vout, picture_t *p_pic,
free( p_pic[i].p_sys );
}
}
p_vout->p_sys->p_current_surface = 0;
}
/*****************************************************************************
......
......@@ -2,7 +2,7 @@
* events.c: Windows DirectX video output events handler
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: events.c,v 1.31 2003/12/08 19:50:22 gbazin Exp $
* $Id: events.c,v 1.32 2003/12/11 23:12:46 gbazin Exp $
*
* Authors: Gildas Bazin <gbazin@netcourrier.com>
*
......@@ -269,7 +269,6 @@ void DirectXEventThread( event_thread_t *p_event )
static int DirectXCreateWindow( vout_thread_t *p_vout )
{
HINSTANCE hInstance;
HDC hdc;
HMENU hMenu;
RECT rect_window;
......@@ -280,17 +279,6 @@ static int DirectXCreateWindow( vout_thread_t *p_vout )
/* Get this module's instance */
hInstance = GetModuleHandle(NULL);
/* Get the current size of the display and its colour depth */
hdc = GetDC( NULL );
p_vout->p_sys->rect_display.right = GetDeviceCaps( hdc, HORZRES );
p_vout->p_sys->rect_display.bottom = GetDeviceCaps( hdc, VERTRES );
p_vout->p_sys->i_display_depth = GetDeviceCaps( hdc, BITSPIXEL );
msg_Dbg( p_vout, "screen dimensions %ix%i colour depth %i",
p_vout->p_sys->rect_display.right,
p_vout->p_sys->rect_display.bottom,
p_vout->p_sys->i_display_depth );
ReleaseDC( NULL, hdc );
/* If an external window was specified, we'll draw in it. */
var_Get( p_vout->p_vlc, "drawable", &val );
p_vout->p_sys->hparent = p_vout->p_sys->hwnd =
......@@ -502,13 +490,16 @@ void DirectXUpdateRects( vout_thread_t *p_vout, vlc_bool_t b_force )
rect_dest.top = point.y + i_y;
rect_dest.bottom = rect_dest.top + i_height;
/* UpdateOverlay directdraw function doesn't automatically clip to the
* display size so we need to do it otherwise it will fail */
/* Clip the destination window */
IntersectRect( &rect_dest_clipped, &rect_dest,
&p_vout->p_sys->rect_display );
if( !IntersectRect( &rect_dest_clipped, &rect_dest,
&p_vout->p_sys->rect_display ) )
{
SetRectEmpty( &rect_src_clipped );
return;
}
#if 0
msg_Dbg( p_vout, "DirectXUpdateRects image_dst_clipped coords:"
......@@ -550,18 +541,8 @@ void DirectXUpdateRects( vout_thread_t *p_vout, vlc_bool_t b_force )
rect_src_clipped.right, rect_src_clipped.bottom );
#endif
/* Signal the size change */
if( !p_vout->p_sys->p_event->b_die )
{
if( p_vout->p_sys->b_using_overlay )
{
DirectXUpdateOverlay( p_vout );
}
else
{
p_vout->p_sys->i_changes |= VOUT_SIZE_CHANGE;
}
}
/* Signal the change in size/position */
p_vout->p_sys->i_changes |= DX_POSITION_CHANGE;
#undef rect_src
#undef rect_src_clipped
......
......@@ -2,7 +2,7 @@
* vout.h: Windows DirectX video output header file
*****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: vout.h,v 1.9 2003/11/20 17:48:44 gbazin Exp $
* $Id: vout.h,v 1.10 2003/12/11 23:12:46 gbazin Exp $
*
* Authors: Gildas Bazin <gbazin@netcourrier.com>
*
......@@ -51,6 +51,12 @@ struct vout_sys_t
HWND hparent; /* Handle of the parent window */
WNDPROC pf_wndproc; /* Window handling callback */
/* Multi-monitor support */
HMONITOR hmonitor; /* handle of the current monitor */
GUID *p_display_driver;
HMONITOR (WINAPI* MonitorFromWindow)( HWND, DWORD );
BOOL (WINAPI* GetMonitorInfo)( HMONITOR, LPMONITORINFO );
vlc_bool_t b_using_overlay; /* Are we using an overlay surface */
vlc_bool_t b_use_sysmem; /* Should we use system memory for surfaces */
vlc_bool_t b_hw_yuv; /* Should we use hardware YUV->RGB conversions */
......@@ -121,3 +127,4 @@ void DirectXUpdateRects ( vout_thread_t *p_vout, vlc_bool_t b_force );
#define WM_VLC_CREATE_VIDEO_WIN WM_APP + 1
#define WM_VLC_DESTROY_VIDEO_WIN WM_APP + 2
#define IDM_TOGGLE_ON_TOP WM_USER + 1
#define DX_POSITION_CHANGE 0x1000
......@@ -5,7 +5,7 @@
* thread, and destroy a previously oppened video output thread.
*****************************************************************************
* Copyright (C) 2000-2001 VideoLAN
* $Id: video_output.c,v 1.241 2003/11/26 08:18:09 gbazin Exp $
* $Id: video_output.c,v 1.242 2003/12/11 23:12:46 gbazin Exp $
*
* Authors: Vincent Seguin <seguin@via.ecp.fr>
*
......@@ -1008,6 +1008,31 @@ static void RunThread( vout_thread_t *p_vout)
p_vout->chroma.p_module->pf_activate( VLC_OBJECT(p_vout) );
}
}
if( p_vout->i_changes & VOUT_PICTURE_BUFFERS_CHANGE )
{
/* This happens when the picture buffers need to be recreated.
* This is useful on multimonitor displays for instance.
*
* Warning: This only works when the vout creates only 1 picture
* buffer!! */
p_vout->i_changes &= ~VOUT_PICTURE_BUFFERS_CHANGE;
if( !p_vout->b_direct )
{
module_Unneed( p_vout, p_vout->chroma.p_module );
}
vlc_mutex_lock( &p_vout->picture_lock );
p_vout->pf_end( p_vout );
I_OUTPUTPICTURES = I_RENDERPICTURES = 0;
p_vout->b_error = InitThread( p_vout );
vlc_mutex_unlock( &p_vout->picture_lock );
}
}
/*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment