Commit ff4158b4 authored by Gildas Bazin's avatar Gildas Bazin

* modules/video_output/directx/*: we now create a video sub-window which is a...

* modules/video_output/directx/*: we now create a video sub-window which is a child of the main window and which always fit exactly the size of the video.
  As a result the overlay color key is only painted in the video area and the rest of the window is pure black.
parent 9883237c
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* vout.c: Windows DirectX video output display method * vout.c: Windows DirectX video output display method
***************************************************************************** *****************************************************************************
* Copyright (C) 2001 VideoLAN * Copyright (C) 2001 VideoLAN
* $Id: directx.c,v 1.23 2003/10/17 16:40:09 gbazin Exp $ * $Id: directx.c,v 1.24 2003/11/19 23:44:35 gbazin Exp $
* *
* Authors: Gildas Bazin <gbazin@netcourrier.com> * Authors: Gildas Bazin <gbazin@netcourrier.com>
* *
...@@ -84,6 +84,8 @@ static void DirectXGetDDrawCaps ( vout_thread_t *p_vout ); ...@@ -84,6 +84,8 @@ static void DirectXGetDDrawCaps ( vout_thread_t *p_vout );
static int DirectXLockSurface ( vout_thread_t *p_vout, picture_t *p_pic ); static int DirectXLockSurface ( vout_thread_t *p_vout, picture_t *p_pic );
static int DirectXUnlockSurface ( vout_thread_t *p_vout, picture_t *p_pic ); static int DirectXUnlockSurface ( vout_thread_t *p_vout, picture_t *p_pic );
static DWORD DirectXFindColorkey( vout_thread_t *p_vout, uint32_t i_color );
/* Object variables callbacks */ /* Object variables callbacks */
static int OnTopCallback( vlc_object_t *, char const *, static int OnTopCallback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * ); vlc_value_t, vlc_value_t, void * );
...@@ -157,7 +159,6 @@ static int OpenVideo( vlc_object_t *p_this ) ...@@ -157,7 +159,6 @@ static int OpenVideo( vlc_object_t *p_this )
p_vout->p_sys->p_display = NULL; p_vout->p_sys->p_display = NULL;
p_vout->p_sys->p_current_surface = NULL; p_vout->p_sys->p_current_surface = NULL;
p_vout->p_sys->p_clipper = NULL; p_vout->p_sys->p_clipper = NULL;
p_vout->p_sys->hbrush = NULL;
p_vout->p_sys->hwnd = NULL; p_vout->p_sys->hwnd = NULL;
p_vout->p_sys->hparent = NULL; p_vout->p_sys->hparent = NULL;
p_vout->p_sys->i_changes = 0; p_vout->p_sys->i_changes = 0;
...@@ -345,9 +346,6 @@ static void CloseVideo( vlc_object_t *p_this ) ...@@ -345,9 +346,6 @@ static void CloseVideo( vlc_object_t *p_this )
var_Destroy( p_vout, "directx-on-top" ); var_Destroy( p_vout, "directx-on-top" );
DirectXCloseDisplay( p_vout );
DirectXCloseDDraw( p_vout );
if( p_vout->p_sys->p_event ) if( p_vout->p_sys->p_event )
{ {
vlc_object_detach( p_vout->p_sys->p_event ); vlc_object_detach( p_vout->p_sys->p_event );
...@@ -366,6 +364,9 @@ static void CloseVideo( vlc_object_t *p_this ) ...@@ -366,6 +364,9 @@ static void CloseVideo( vlc_object_t *p_this )
vlc_object_destroy( p_vout->p_sys->p_event ); vlc_object_destroy( p_vout->p_sys->p_event );
} }
DirectXCloseDisplay( p_vout );
DirectXCloseDDraw( p_vout );
if( p_vout->p_sys ) if( p_vout->p_sys )
{ {
free( p_vout->p_sys ); free( p_vout->p_sys );
...@@ -402,9 +403,7 @@ static int Manage( vout_thread_t *p_vout ) ...@@ -402,9 +403,7 @@ static int Manage( vout_thread_t *p_vout )
|| p_vout->p_sys->i_changes & VOUT_SCALE_CHANGE ) || p_vout->p_sys->i_changes & VOUT_SCALE_CHANGE )
{ {
msg_Dbg( p_vout, "scale change" ); msg_Dbg( p_vout, "scale change" );
if( !p_vout->p_sys->b_using_overlay ) if( p_vout->p_sys->b_using_overlay )
InvalidateRect( p_vout->p_sys->hwnd, NULL, TRUE );
else
DirectXUpdateOverlay( p_vout ); DirectXUpdateOverlay( p_vout );
p_vout->i_changes &= ~VOUT_SCALE_CHANGE; p_vout->i_changes &= ~VOUT_SCALE_CHANGE;
p_vout->p_sys->i_changes &= ~VOUT_SCALE_CHANGE; p_vout->p_sys->i_changes &= ~VOUT_SCALE_CHANGE;
...@@ -417,9 +416,7 @@ static int Manage( vout_thread_t *p_vout ) ...@@ -417,9 +416,7 @@ static int Manage( vout_thread_t *p_vout )
|| p_vout->p_sys->i_changes & VOUT_SIZE_CHANGE ) || p_vout->p_sys->i_changes & VOUT_SIZE_CHANGE )
{ {
msg_Dbg( p_vout, "size change" ); msg_Dbg( p_vout, "size change" );
if( !p_vout->p_sys->b_using_overlay ) if( p_vout->p_sys->b_using_overlay )
InvalidateRect( p_vout->p_sys->hwnd, NULL, TRUE );
else
DirectXUpdateOverlay( p_vout ); DirectXUpdateOverlay( p_vout );
p_vout->i_changes &= ~VOUT_SIZE_CHANGE; p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
p_vout->p_sys->i_changes &= ~VOUT_SIZE_CHANGE; p_vout->p_sys->i_changes &= ~VOUT_SIZE_CHANGE;
...@@ -443,7 +440,7 @@ static int Manage( vout_thread_t *p_vout ) ...@@ -443,7 +440,7 @@ static int Manage( vout_thread_t *p_vout )
/* Maximized window */ /* Maximized window */
window_placement.showCmd = SW_SHOWMAXIMIZED; window_placement.showCmd = SW_SHOWMAXIMIZED;
/* Change window style, no borders and no title bar */ /* Change window style, no borders and no title bar */
SetWindowLong( p_vout->p_sys->hwnd, GWL_STYLE, 0 ); SetWindowLong( p_vout->p_sys->hwnd, GWL_STYLE, WS_CLIPCHILDREN );
} }
else else
...@@ -451,7 +448,7 @@ static int Manage( vout_thread_t *p_vout ) ...@@ -451,7 +448,7 @@ static int Manage( vout_thread_t *p_vout )
/* Normal window */ /* Normal window */
window_placement.showCmd = SW_SHOWNORMAL; window_placement.showCmd = SW_SHOWNORMAL;
/* Change window style, borders and title bar */ /* Change window style, borders and title bar */
SetWindowLong( p_vout->p_sys->hwnd, GWL_STYLE, SetWindowLong( p_vout->p_sys->hwnd, GWL_STYLE, WS_CLIPCHILDREN |
WS_OVERLAPPEDWINDOW | WS_SIZEBOX | WS_VISIBLE ); WS_OVERLAPPEDWINDOW | WS_SIZEBOX | WS_VISIBLE );
} }
...@@ -598,9 +595,24 @@ static void Display( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -598,9 +595,24 @@ static void Display( vout_thread_t *p_vout, picture_t *p_pic )
} }
} }
/* following functions are local */ /* following functions are local */
/*****************************************************************************
* DirectXEnumCallback: Device enumeration
*****************************************************************************
* This callback function is called by DirectDraw once for each
* available DirectDraw device.
*****************************************************************************/
BOOL WINAPI DirectXEnumCallback( GUID* p_guid, LPTSTR psz_desc,
LPTSTR psz_drivername, VOID* p_context,
HMONITOR hmon )
{
vout_thread_t *p_vout = (vout_thread_t *)p_context;
msg_Dbg( p_vout, "DirectXEnumCallback: %s, %s", psz_desc, psz_drivername );
return TRUE; /* Keep enumerating */
}
/***************************************************************************** /*****************************************************************************
* DirectXInitDDraw: Takes care of all the DirectDraw initialisations * DirectXInitDDraw: Takes care of all the DirectDraw initialisations
***************************************************************************** *****************************************************************************
...@@ -608,9 +620,11 @@ static void Display( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -608,9 +620,11 @@ static void Display( vout_thread_t *p_vout, picture_t *p_pic )
*****************************************************************************/ *****************************************************************************/
static int DirectXInitDDraw( vout_thread_t *p_vout ) static int DirectXInitDDraw( vout_thread_t *p_vout )
{ {
HRESULT dxresult; HRESULT dxresult;
HRESULT (WINAPI *OurDirectDrawCreate)(GUID *,LPDIRECTDRAW *,IUnknown *); HRESULT (WINAPI *OurDirectDrawCreate)(GUID *,LPDIRECTDRAW *,IUnknown *);
LPDIRECTDRAW p_ddobject; HRESULT (WINAPI *OurDirectDrawEnumerateEx)( LPDDENUMCALLBACKEXA, LPVOID,
DWORD );
LPDIRECTDRAW p_ddobject;
msg_Dbg( p_vout, "DirectXInitDDraw" ); msg_Dbg( p_vout, "DirectXInitDDraw" );
...@@ -624,12 +638,23 @@ static int DirectXInitDDraw( vout_thread_t *p_vout ) ...@@ -624,12 +638,23 @@ static int DirectXInitDDraw( vout_thread_t *p_vout )
OurDirectDrawCreate = OurDirectDrawCreate =
(void *)GetProcAddress(p_vout->p_sys->hddraw_dll, "DirectDrawCreate"); (void *)GetProcAddress(p_vout->p_sys->hddraw_dll, "DirectDrawCreate");
if ( OurDirectDrawCreate == NULL ) if( OurDirectDrawCreate == NULL )
{ {
msg_Err( p_vout, "DirectXInitDDraw failed GetProcAddress" ); msg_Err( p_vout, "DirectXInitDDraw failed GetProcAddress" );
goto error; goto error;
} }
OurDirectDrawEnumerateEx =
(void *)GetProcAddress( p_vout->p_sys->hddraw_dll,
"DirectDrawEnumerateExA" );
if( OurDirectDrawEnumerateEx )
{
/* Enumerate displays */
OurDirectDrawEnumerateEx( DirectXEnumCallback, p_vout,
DDENUM_ATTACHEDSECONDARYDEVICES );
}
/* Initialize DirectDraw now */ /* Initialize DirectDraw now */
dxresult = OurDirectDrawCreate( NULL, &p_ddobject, NULL ); dxresult = OurDirectDrawCreate( NULL, &p_ddobject, NULL );
if( dxresult != DD_OK ) if( dxresult != DD_OK )
...@@ -652,7 +677,7 @@ static int DirectXInitDDraw( vout_thread_t *p_vout ) ...@@ -652,7 +677,7 @@ static int DirectXInitDDraw( vout_thread_t *p_vout )
/* Set DirectDraw Cooperative level, ie what control we want over Windows /* Set DirectDraw Cooperative level, ie what control we want over Windows
* display */ * display */
dxresult = IDirectDraw2_SetCooperativeLevel( p_vout->p_sys->p_ddobject, dxresult = IDirectDraw2_SetCooperativeLevel( p_vout->p_sys->p_ddobject,
p_vout->p_sys->hwnd, DDSCL_NORMAL ); NULL, DDSCL_NORMAL );
if( dxresult != DD_OK ) if( dxresult != DD_OK )
{ {
msg_Err( p_vout, "cannot set direct draw cooperative level" ); msg_Err( p_vout, "cannot set direct draw cooperative level" );
...@@ -686,7 +711,6 @@ static int DirectXCreateDisplay( vout_thread_t *p_vout ) ...@@ -686,7 +711,6 @@ static int DirectXCreateDisplay( vout_thread_t *p_vout )
HRESULT dxresult; HRESULT dxresult;
DDSURFACEDESC ddsd; DDSURFACEDESC ddsd;
LPDIRECTDRAWSURFACE p_display; LPDIRECTDRAWSURFACE p_display;
DDPIXELFORMAT pixel_format;
msg_Dbg( p_vout, "DirectXCreateDisplay" ); msg_Dbg( p_vout, "DirectXCreateDisplay" );
...@@ -698,8 +722,7 @@ static int DirectXCreateDisplay( vout_thread_t *p_vout ) ...@@ -698,8 +722,7 @@ static int DirectXCreateDisplay( vout_thread_t *p_vout )
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
dxresult = IDirectDraw2_CreateSurface( p_vout->p_sys->p_ddobject, dxresult = IDirectDraw2_CreateSurface( p_vout->p_sys->p_ddobject,
&ddsd, &ddsd, &p_display, NULL );
&p_display, NULL );
if( dxresult != DD_OK ) if( dxresult != DD_OK )
{ {
msg_Err( p_vout, "cannot get primary surface (error %li)", dxresult ); msg_Err( p_vout, "cannot get primary surface (error %li)", dxresult );
...@@ -721,27 +744,20 @@ static int DirectXCreateDisplay( vout_thread_t *p_vout ) ...@@ -721,27 +744,20 @@ static int DirectXCreateDisplay( vout_thread_t *p_vout )
/* The clipper will be used only in non-overlay mode */ /* The clipper will be used only in non-overlay mode */
DirectXCreateClipper( p_vout ); DirectXCreateClipper( p_vout );
/* Make sure the colorkey will be painted */
p_vout->p_sys->i_colorkey = 1;
p_vout->p_sys->i_rgb_colorkey =
DirectXFindColorkey( p_vout, p_vout->p_sys->i_colorkey );
#if 1 /* Create the actual brush */
/* compute the colorkey pixel value from the RGB value we've got */ SetClassLong( p_vout->p_sys->hvideownd, GCL_HBRBACKGROUND,
memset( &pixel_format, 0, sizeof( DDPIXELFORMAT )); (LONG)CreateSolidBrush( p_vout->p_sys->i_rgb_colorkey ) );
pixel_format.dwSize = sizeof( DDPIXELFORMAT ); InvalidateRect( p_vout->p_sys->hvideownd, NULL, TRUE );
dxresult = IDirectDrawSurface2_GetPixelFormat( p_vout->p_sys->p_display, DirectXUpdateRects( p_vout, VLC_TRUE );
&pixel_format );
if( dxresult != DD_OK )
{
msg_Warn( p_vout, "DirectXUpdateOverlay GetPixelFormat failed "
"(error %li)", dxresult );
}
p_vout->p_sys->i_colorkey = (DWORD)((( p_vout->p_sys->i_rgb_colorkey
* pixel_format.dwRBitMask) / 255)
& pixel_format.dwRBitMask );
#endif
return VLC_SUCCESS; return VLC_SUCCESS;
} }
/***************************************************************************** /*****************************************************************************
* DirectXCreateClipper: Create a clipper that will be used when blitting the * DirectXCreateClipper: Create a clipper that will be used when blitting the
* RGB surface to the main display. * RGB surface to the main display.
...@@ -766,8 +782,8 @@ static int DirectXCreateClipper( vout_thread_t *p_vout ) ...@@ -766,8 +782,8 @@ static int DirectXCreateClipper( vout_thread_t *p_vout )
} }
/* Associate the clipper to the window */ /* Associate the clipper to the window */
dxresult = IDirectDrawClipper_SetHWnd(p_vout->p_sys->p_clipper, 0, dxresult = IDirectDrawClipper_SetHWnd( p_vout->p_sys->p_clipper, 0,
p_vout->p_sys->hwnd); p_vout->p_sys->hvideownd );
if( dxresult != DD_OK ) if( dxresult != DD_OK )
{ {
msg_Warn( p_vout, "cannot attach clipper to window (error %li)", msg_Warn( p_vout, "cannot attach clipper to window (error %li)",
...@@ -831,13 +847,9 @@ static int DirectXCreateSurface( vout_thread_t *p_vout, ...@@ -831,13 +847,9 @@ static int DirectXCreateSurface( vout_thread_t *p_vout,
ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC; ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
ddsd.ddpfPixelFormat.dwFourCC = i_chroma; ddsd.ddpfPixelFormat.dwFourCC = i_chroma;
ddsd.dwFlags = DDSD_CAPS | ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
DDSD_HEIGHT |
DDSD_WIDTH |
DDSD_PIXELFORMAT;
ddsd.dwFlags |= (i_backbuffers ? DDSD_BACKBUFFERCOUNT : 0); ddsd.dwFlags |= (i_backbuffers ? DDSD_BACKBUFFERCOUNT : 0);
ddsd.ddsCaps.dwCaps = DDSCAPS_OVERLAY | ddsd.ddsCaps.dwCaps = DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY;
DDSCAPS_VIDEOMEMORY;
ddsd.ddsCaps.dwCaps |= (i_backbuffers ? DDSCAPS_COMPLEX | DDSCAPS_FLIP ddsd.ddsCaps.dwCaps |= (i_backbuffers ? DDSCAPS_COMPLEX | DDSCAPS_FLIP
: 0 ); : 0 );
ddsd.dwHeight = p_vout->render.i_height; ddsd.dwHeight = p_vout->render.i_height;
...@@ -845,8 +857,7 @@ static int DirectXCreateSurface( vout_thread_t *p_vout, ...@@ -845,8 +857,7 @@ static int DirectXCreateSurface( vout_thread_t *p_vout,
ddsd.dwBackBufferCount = i_backbuffers; ddsd.dwBackBufferCount = i_backbuffers;
dxresult = IDirectDraw2_CreateSurface( p_vout->p_sys->p_ddobject, dxresult = IDirectDraw2_CreateSurface( p_vout->p_sys->p_ddobject,
&ddsd, &ddsd, &p_surface, NULL );
&p_surface, NULL );
if( dxresult != DD_OK ) if( dxresult != DD_OK )
{ {
*pp_surface_final = NULL; *pp_surface_final = NULL;
...@@ -866,9 +877,7 @@ static int DirectXCreateSurface( vout_thread_t *p_vout, ...@@ -866,9 +877,7 @@ static int DirectXCreateSurface( vout_thread_t *p_vout,
memset( &ddsd, 0, sizeof( DDSURFACEDESC ) ); memset( &ddsd, 0, sizeof( DDSURFACEDESC ) );
ddsd.dwSize = sizeof(DDSURFACEDESC); ddsd.dwSize = sizeof(DDSURFACEDESC);
ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
ddsd.dwFlags = DDSD_HEIGHT | ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH | DDSD_CAPS;
DDSD_WIDTH |
DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
ddsd.dwHeight = p_vout->render.i_height; ddsd.dwHeight = p_vout->render.i_height;
ddsd.dwWidth = p_vout->render.i_width; ddsd.dwWidth = p_vout->render.i_width;
...@@ -886,8 +895,7 @@ static int DirectXCreateSurface( vout_thread_t *p_vout, ...@@ -886,8 +895,7 @@ static int DirectXCreateSurface( vout_thread_t *p_vout,
} }
dxresult = IDirectDraw2_CreateSurface( p_vout->p_sys->p_ddobject, dxresult = IDirectDraw2_CreateSurface( p_vout->p_sys->p_ddobject,
&ddsd, &ddsd, &p_surface, NULL );
&p_surface, NULL );
if( dxresult != DD_OK ) if( dxresult != DD_OK )
{ {
*pp_surface_final = NULL; *pp_surface_final = NULL;
...@@ -1552,6 +1560,63 @@ static int DirectXUnlockSurface( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -1552,6 +1560,63 @@ static int DirectXUnlockSurface( vout_thread_t *p_vout, picture_t *p_pic )
return VLC_EGENERIC; return VLC_EGENERIC;
} }
/*****************************************************************************
* DirectXFindColorkey: Finds out the 32bits RGB pixel value of the colorkey
*****************************************************************************/
static DWORD DirectXFindColorkey( vout_thread_t *p_vout, uint32_t i_color )
{
DDSURFACEDESC ddsd;
HRESULT dxresult;
COLORREF i_rgb = 0;
uint32_t i_pixel_backup;
HDC hdc;
ddsd.dwSize = sizeof(ddsd);
dxresult = IDirectDrawSurface2_Lock( p_vout->p_sys->p_display, NULL,
&ddsd, DDLOCK_WAIT, NULL );
if( dxresult != DD_OK ) return 0;
i_pixel_backup = *(uint32_t *)ddsd.lpSurface;
switch( ddsd.ddpfPixelFormat.dwRGBBitCount )
{
case 4:
*(uint8_t *)ddsd.lpSurface = 0x11;
break;
case 8:
*(uint8_t *)ddsd.lpSurface = 0x01;
break;
case 16:
*(uint16_t *)ddsd.lpSurface = 0x01;
break;
case 24:
*(uint32_t *)ddsd.lpSurface = 0x0100;
break;
case 32:
*(uint32_t *)ddsd.lpSurface = 0x01;
break;
}
IDirectDrawSurface2_Unlock( p_vout->p_sys->p_display, NULL );
if( IDirectDrawSurface2_GetDC( p_vout->p_sys->p_display, &hdc ) == DD_OK )
{
i_rgb = GetPixel( hdc, 0, 0 );
IDirectDrawSurface2_ReleaseDC( p_vout->p_sys->p_display, hdc );
}
ddsd.dwSize = sizeof(ddsd);
dxresult = IDirectDrawSurface2_Lock( p_vout->p_sys->p_display, NULL,
&ddsd, DDLOCK_WAIT, NULL );
if( dxresult != DD_OK ) return i_rgb;
*(uint32_t *)ddsd.lpSurface = i_pixel_backup;
IDirectDrawSurface2_Unlock( p_vout->p_sys->p_display, NULL );
return i_rgb;
}
/***************************************************************************** /*****************************************************************************
* object variables callbacks: a bunch of object variables are used by the * object variables callbacks: a bunch of object variables are used by the
* interfaces to interact with the vout. * interfaces to interact with the vout.
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* events.c: Windows DirectX video output events handler * events.c: Windows DirectX video output events handler
***************************************************************************** *****************************************************************************
* Copyright (C) 2001 VideoLAN * Copyright (C) 2001 VideoLAN
* $Id: events.c,v 1.28 2003/10/31 18:18:46 gbazin Exp $ * $Id: events.c,v 1.29 2003/11/19 23:44:35 gbazin Exp $
* *
* Authors: Gildas Bazin <gbazin@netcourrier.com> * Authors: Gildas Bazin <gbazin@netcourrier.com>
* *
...@@ -263,7 +263,6 @@ void DirectXEventThread( event_thread_t *p_event ) ...@@ -263,7 +263,6 @@ void DirectXEventThread( event_thread_t *p_event )
static int DirectXCreateWindow( vout_thread_t *p_vout ) static int DirectXCreateWindow( vout_thread_t *p_vout )
{ {
HINSTANCE hInstance; HINSTANCE hInstance;
COLORREF colorkey;
HDC hdc; HDC hdc;
HMENU hMenu; HMENU hMenu;
RECT rect_window; RECT rect_window;
...@@ -275,33 +274,8 @@ static int DirectXCreateWindow( vout_thread_t *p_vout ) ...@@ -275,33 +274,8 @@ static int DirectXCreateWindow( vout_thread_t *p_vout )
/* Get this module's instance */ /* Get this module's instance */
hInstance = GetModuleHandle(NULL); hInstance = GetModuleHandle(NULL);
/* Create a BRUSH that will be used by Windows to paint the window
* background.
* This window background is important for us as it will be used by the
* graphics card to display the overlay.
* This is why we carefully choose the color for this background, the goal
* being to choose a color which isn't complete black but nearly. We
* obviously don't want to use black as a colorkey for the overlay because
* black is one of the most used color and thus would give us undesirable
* effects */
/* the first step is to find the colorkey we want to use. The difficulty
* comes from the potential dithering (depends on the display depth)
* because we need to know the real RGB value of the chosen colorkey */
hdc = GetDC( NULL );
for( colorkey = 0x0a; colorkey < 0xff /* all shades of red */; colorkey++ )
{
if( colorkey == GetNearestColor( hdc, colorkey ) )
{
break;
}
}
msg_Dbg( p_vout, "background color: %i", colorkey );
/* Create the actual brush */
p_vout->p_sys->hbrush = CreateSolidBrush(colorkey);
p_vout->p_sys->i_rgb_colorkey = (int)colorkey;
/* Get the current size of the display and its colour depth */ /* 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.right = GetDeviceCaps( hdc, HORZRES );
p_vout->p_sys->rect_display.bottom = GetDeviceCaps( hdc, VERTRES ); p_vout->p_sys->rect_display.bottom = GetDeviceCaps( hdc, VERTRES );
p_vout->p_sys->i_display_depth = GetDeviceCaps( hdc, BITSPIXEL ); p_vout->p_sys->i_display_depth = GetDeviceCaps( hdc, BITSPIXEL );
...@@ -309,7 +283,6 @@ static int DirectXCreateWindow( vout_thread_t *p_vout ) ...@@ -309,7 +283,6 @@ static int DirectXCreateWindow( vout_thread_t *p_vout )
p_vout->p_sys->rect_display.right, p_vout->p_sys->rect_display.right,
p_vout->p_sys->rect_display.bottom, p_vout->p_sys->rect_display.bottom,
p_vout->p_sys->i_display_depth ); p_vout->p_sys->i_display_depth );
ReleaseDC( NULL, hdc ); ReleaseDC( NULL, hdc );
/* If an external window was specified, we'll draw in it. */ /* If an external window was specified, we'll draw in it. */
...@@ -326,7 +299,7 @@ static int DirectXCreateWindow( vout_thread_t *p_vout ) ...@@ -326,7 +299,7 @@ static int DirectXCreateWindow( vout_thread_t *p_vout )
SetClassLong( p_vout->p_sys->hwnd, SetClassLong( p_vout->p_sys->hwnd,
GCL_STYLE, CS_DBLCLKS ); GCL_STYLE, CS_DBLCLKS );
SetClassLong( p_vout->p_sys->hwnd, SetClassLong( p_vout->p_sys->hwnd,
GCL_HBRBACKGROUND, (LONG)p_vout->p_sys->hbrush ); GCL_HBRBACKGROUND, (LONG)GetStockObject(BLACK_BRUSH) );
SetClassLong( p_vout->p_sys->hwnd, SetClassLong( p_vout->p_sys->hwnd,
GCL_HCURSOR, (LONG)LoadCursor(NULL, IDC_ARROW) ); GCL_HCURSOR, (LONG)LoadCursor(NULL, IDC_ARROW) );
/* Store a p_vout pointer into the window local storage (for later /* Store a p_vout pointer into the window local storage (for later
...@@ -363,7 +336,7 @@ static int DirectXCreateWindow( vout_thread_t *p_vout ) ...@@ -363,7 +336,7 @@ static int DirectXCreateWindow( vout_thread_t *p_vout )
wc.hInstance = hInstance; /* instance */ wc.hInstance = hInstance; /* instance */
wc.hIcon = vlc_icon; /* load the vlc big icon */ wc.hIcon = vlc_icon; /* load the vlc big icon */
wc.hCursor = LoadCursor(NULL, IDC_ARROW); /* default cursor */ wc.hCursor = LoadCursor(NULL, IDC_ARROW); /* default cursor */
wc.hbrBackground = p_vout->p_sys->hbrush; /* background color */ wc.hbrBackground = GetStockObject(BLACK_BRUSH); /* background color */
wc.lpszMenuName = NULL; /* no menu */ wc.lpszMenuName = NULL; /* no menu */
wc.lpszClassName = "VLC DirectX"; /* use a special class */ wc.lpszClassName = "VLC DirectX"; /* use a special class */
wc.hIconSm = vlc_icon; /* load the vlc small icon */ wc.hIconSm = vlc_icon; /* load the vlc small icon */
...@@ -373,13 +346,6 @@ static int DirectXCreateWindow( vout_thread_t *p_vout ) ...@@ -373,13 +346,6 @@ static int DirectXCreateWindow( vout_thread_t *p_vout )
{ {
WNDCLASS wndclass; WNDCLASS wndclass;
/* Free window background brush */
if( p_vout->p_sys->hbrush )
{
DeleteObject( p_vout->p_sys->hbrush );
p_vout->p_sys->hbrush = NULL;
}
if( vlc_icon ) if( vlc_icon )
{ {
DestroyIcon( vlc_icon ); DestroyIcon( vlc_icon );
...@@ -408,7 +374,8 @@ static int DirectXCreateWindow( vout_thread_t *p_vout ) ...@@ -408,7 +374,8 @@ static int DirectXCreateWindow( vout_thread_t *p_vout )
p_vout->p_sys->hwnd = p_vout->p_sys->hwnd =
CreateWindow( "VLC DirectX", /* name of window class */ CreateWindow( "VLC DirectX", /* name of window class */
VOUT_TITLE " (DirectX Output)", /* window title bar text */ VOUT_TITLE " (DirectX Output)", /* window title bar text */
WS_OVERLAPPEDWINDOW | WS_SIZEBOX, /* window style */ WS_OVERLAPPEDWINDOW | WS_SIZEBOX | WS_VISIBLE |
WS_CLIPCHILDREN, /* window style */
CW_USEDEFAULT, /* default X coordinate */ CW_USEDEFAULT, /* default X coordinate */
0, /* default Y coordinate */ 0, /* default Y coordinate */
rect_window.right - rect_window.left, /* window width */ rect_window.right - rect_window.left, /* window width */
...@@ -425,15 +392,20 @@ static int DirectXCreateWindow( vout_thread_t *p_vout ) ...@@ -425,15 +392,20 @@ static int DirectXCreateWindow( vout_thread_t *p_vout )
} }
} }
/* Now display the window */
ShowWindow( p_vout->p_sys->hwnd, SW_SHOW );
/* Create video sub-window. This sub window will always exactly match
* the size of the video, which allows us to use crazy overlay colorkeys
* without having them shown outside of the video area. */
SendMessage( p_vout->p_sys->hwnd, WM_VLC_CREATE_VIDEO_WIN, 0, 0 );
/* Append a "Always On Top" entry in the system menu */ /* Append a "Always On Top" entry in the system menu */
hMenu = GetSystemMenu( p_vout->p_sys->hwnd, FALSE ); hMenu = GetSystemMenu( p_vout->p_sys->hwnd, FALSE );
AppendMenu( hMenu, MF_SEPARATOR, 0, "" ); AppendMenu( hMenu, MF_SEPARATOR, 0, "" );
AppendMenu( hMenu, MF_STRING | MF_UNCHECKED, AppendMenu( hMenu, MF_STRING | MF_UNCHECKED,
IDM_TOGGLE_ON_TOP, "Always on &Top" ); IDM_TOGGLE_ON_TOP, "Always on &Top" );
/* Now display the window */
ShowWindow( p_vout->p_sys->hwnd, SW_SHOW );
return VLC_SUCCESS; return VLC_SUCCESS;
} }