Commit f9d9f469 authored by Gildas Bazin's avatar Gildas Bazin

* Added double-buffering for the directx plugin in overlay mode.
* Several directx bug-fixes:
    - implemented the right behaviour on exit.
    - fixed bug preventing the creation of several windows.
        (the wall filter is working now :-))
    - fixed unnecessary background redraws (it made the video flicker).
    - fixed bug where we were losing the video display because of lost
        surfaces in video memory.
    - when using hardware overlay, the output window will now specify:
        "(using hardware overlay)".
parent 83098c80
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* vout_directx.c: Windows DirectX video output display method * vout_directx.c: Windows DirectX video output display method
***************************************************************************** *****************************************************************************
* Copyright (C) 2001 VideoLAN * Copyright (C) 2001 VideoLAN
* $Id: vout_directx.c,v 1.19 2002/01/17 23:02:45 gbazin Exp $ * $Id: vout_directx.c,v 1.20 2002/01/27 22:14:52 gbazin Exp $
* *
* Authors: Gildas Bazin <gbazin@netcourrier.com> * Authors: Gildas Bazin <gbazin@netcourrier.com>
* *
...@@ -285,6 +285,11 @@ static int vout_Init( vout_thread_t *p_vout ) ...@@ -285,6 +285,11 @@ static int vout_Init( vout_thread_t *p_vout )
NewPictureVec( p_vout, p_vout->p_picture, MAX_DIRECTBUFFERS ); NewPictureVec( p_vout, p_vout->p_picture, MAX_DIRECTBUFFERS );
/* Change the window title bar text */
if( p_vout->p_sys->b_using_overlay )
SetWindowText( p_vout->p_sys->hwnd,
"VLC DirectX (using hardware overlay)" );
return( 0 ); return( 0 );
} }
...@@ -315,7 +320,8 @@ static void vout_Destroy( vout_thread_t *p_vout ) ...@@ -315,7 +320,8 @@ static void vout_Destroy( vout_thread_t *p_vout )
p_vout->p_sys->b_event_thread_die = 1; p_vout->p_sys->b_event_thread_die = 1;
/* we need to be sure DirectXEventThread won't stay stuck in GetMessage, /* we need to be sure DirectXEventThread won't stay stuck in GetMessage,
* so we send a fake message */ * so we send a fake message */
if( p_vout->p_sys->i_event_thread_status == THREAD_READY ) if( p_vout->p_sys->i_event_thread_status == THREAD_READY &&
p_vout->p_sys->hwnd )
{ {
PostMessage( p_vout->p_sys->hwnd, WM_CHAR, (WPARAM)'q', 0); PostMessage( p_vout->p_sys->hwnd, WM_CHAR, (WPARAM)'q', 0);
vlc_thread_join( p_vout->p_sys->event_thread_id ); vlc_thread_join( p_vout->p_sys->event_thread_id );
...@@ -457,8 +463,6 @@ static void vout_Display( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -457,8 +463,6 @@ static void vout_Display( vout_thread_t *p_vout, picture_t *p_pic )
{ {
HRESULT dxresult; HRESULT dxresult;
intf_WarnMsg( 8, "vout: vout_Display" );
if( (p_vout->p_sys->p_display == NULL) ) if( (p_vout->p_sys->p_display == NULL) )
{ {
intf_WarnMsg( 3, "vout error: vout_Display no display!!" ); intf_WarnMsg( 3, "vout error: vout_Display no display!!" );
...@@ -476,10 +480,24 @@ static void vout_Display( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -476,10 +480,24 @@ static void vout_Display( vout_thread_t *p_vout, picture_t *p_pic )
/* Blit video surface to display */ /* Blit video surface to display */
dxresult = IDirectDrawSurface3_Blt(p_vout->p_sys->p_display, dxresult = IDirectDrawSurface3_Blt(p_vout->p_sys->p_display,
&p_vout->p_sys->rect_dest, &p_vout->p_sys->rect_dest_clipped,
p_pic->p_sys->p_surface,
&p_vout->p_sys->rect_src_clipped,
0, &ddbltfx );
if ( dxresult == DDERR_SURFACELOST )
{
/* Our surface can be lost so be sure
* to check this and restore it if needed */
IDirectDrawSurface3_Restore( p_vout->p_sys->p_display );
/* Now that the surface has been restored try to display again */
dxresult = IDirectDrawSurface3_Blt(p_vout->p_sys->p_display,
&p_vout->p_sys->rect_dest_clipped,
p_pic->p_sys->p_surface, p_pic->p_sys->p_surface,
NULL, &p_vout->p_sys->rect_src_clipped,
0, &ddbltfx ); 0, &ddbltfx );
}
if( dxresult != DD_OK ) if( dxresult != DD_OK )
{ {
intf_WarnMsg( 3, "vout: could not Blit the surface" ); intf_WarnMsg( 3, "vout: could not Blit the surface" );
...@@ -491,7 +509,23 @@ static void vout_Display( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -491,7 +509,23 @@ static void vout_Display( vout_thread_t *p_vout, picture_t *p_pic )
{ {
/* Flip the overlay buffers */ /* Flip the overlay buffers */
//dxresult = IDirectDrawSurface3_Flip(p_pic->p_sys->p_surface, NULL, 0 ); dxresult = IDirectDrawSurface3_Flip( p_pic->p_sys->p_front_surface,
NULL, DDFLIP_WAIT );
if ( dxresult == DDERR_SURFACELOST )
{
/* Our surface can be lost so be sure
* to check this and restore it if needed */
IDirectDrawSurface3_Restore( p_vout->p_sys->p_display );
IDirectDrawSurface3_Restore( p_pic->p_sys->p_front_surface );
/* Now that the surface has been restored try to display again */
dxresult = IDirectDrawSurface3_Flip( p_pic->p_sys->p_front_surface,
NULL, DDFLIP_WAIT );
DirectXUpdateOverlay( p_vout );
}
if( dxresult != DD_OK )
intf_WarnMsg( 8, "vout: couldn't flip overlay surface" );
if( !DirectXGetSurfaceDesc( p_pic ) ) if( !DirectXGetSurfaceDesc( p_pic ) )
{ {
...@@ -507,11 +541,10 @@ static void vout_Display( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -507,11 +541,10 @@ static void vout_Display( vout_thread_t *p_vout, picture_t *p_pic )
return; return;
} }
/* set currently displayed pic !!! faux*/ /* set currently displayed pic */
p_vout->p_sys->p_current_surface = p_pic->p_sys->p_surface; p_vout->p_sys->p_current_surface = p_pic->p_sys->p_front_surface;
} }
intf_WarnMsg( 8, "vout: vout_Display End" );
} }
...@@ -758,15 +791,15 @@ static int DirectXCreateSurface( vout_thread_t *p_vout, ...@@ -758,15 +791,15 @@ static int DirectXCreateSurface( vout_thread_t *p_vout,
ddsd.dwFlags = DDSD_CAPS | ddsd.dwFlags = DDSD_CAPS |
DDSD_HEIGHT | DDSD_HEIGHT |
DDSD_WIDTH | DDSD_WIDTH |
//DDSD_BACKBUFFERCOUNT | DDSD_BACKBUFFERCOUNT |
DDSD_PIXELFORMAT; DDSD_PIXELFORMAT;
ddsd.ddsCaps.dwCaps = DDSCAPS_OVERLAY | ddsd.ddsCaps.dwCaps = DDSCAPS_OVERLAY |
// DDSCAPS_COMPLEX | DDSCAPS_COMPLEX |
//DDSCAPS_FLIP | DDSCAPS_FLIP |
DDSCAPS_VIDEOMEMORY; DDSCAPS_VIDEOMEMORY;
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;
ddsd.dwBackBufferCount = 0; /* One back buffer */ ddsd.dwBackBufferCount = 1; /* One back buffer */
dxresult = IDirectDraw2_CreateSurface( p_vout->p_sys->p_ddobject, dxresult = IDirectDraw2_CreateSurface( p_vout->p_sys->p_ddobject,
&ddsd, &ddsd,
...@@ -975,8 +1008,10 @@ static int NewPictureVec( vout_thread_t *p_vout, picture_t *p_pic, ...@@ -975,8 +1008,10 @@ static int NewPictureVec( vout_thread_t *p_vout, picture_t *p_pic,
p_vout->output.i_chroma = p_vout->render.i_chroma; p_vout->output.i_chroma = p_vout->render.i_chroma;
/* hack */ /* hack */
#if 1
if( p_vout->render.i_chroma == FOURCC_I420 ) if( p_vout->render.i_chroma == FOURCC_I420 )
p_vout->output.i_chroma = FOURCC_YV12; p_vout->output.i_chroma = FOURCC_YV12;
#endif
/* First we try to create an overlay surface. /* First we try to create an overlay surface.
* It looks like with most hardware it's not possible to create several * It looks like with most hardware it's not possible to create several
...@@ -991,6 +1026,8 @@ static int NewPictureVec( vout_thread_t *p_vout, picture_t *p_pic, ...@@ -991,6 +1026,8 @@ static int NewPictureVec( vout_thread_t *p_vout, picture_t *p_pic,
if( DirectXCreateSurface( p_vout, &p_surface, p_vout->output.i_chroma, if( DirectXCreateSurface( p_vout, &p_surface, p_vout->output.i_chroma,
p_vout->p_sys->b_using_overlay ) ) p_vout->p_sys->b_using_overlay ) )
{ {
DDSCAPS dds_caps;
/* Allocate internal structure */ /* Allocate internal structure */
p_pic[0].p_sys = malloc( sizeof( picture_sys_t ) ); p_pic[0].p_sys = malloc( sizeof( picture_sys_t ) );
if( p_pic[0].p_sys == NULL ) if( p_pic[0].p_sys == NULL )
...@@ -998,8 +1035,25 @@ static int NewPictureVec( vout_thread_t *p_vout, picture_t *p_pic, ...@@ -998,8 +1035,25 @@ static int NewPictureVec( vout_thread_t *p_vout, picture_t *p_pic,
DirectXCloseSurface( p_vout, p_surface ); DirectXCloseSurface( p_vout, p_surface );
return -1; return -1;
} }
/* set front buffer */
p_pic[0].p_sys->p_front_surface = p_surface;
/* Get the back buffer */
memset( &dds_caps, 0, sizeof( DDSCAPS ));
dds_caps.dwCaps = DDSCAPS_BACKBUFFER;
if( DD_OK != IDirectDrawSurface3_GetAttachedSurface(
p_surface, &dds_caps,
&p_pic[0].p_sys->p_surface ) )
{
intf_WarnMsg( 3, "vout: NewPictureVec couldn't get "
"back buffer" );
/* front buffer is the same as back buffer */
p_pic[0].p_sys->p_surface = p_surface; p_pic[0].p_sys->p_surface = p_surface;
p_vout->p_sys->p_current_surface = p_surface; }
p_vout->p_sys->p_current_surface= p_pic[0].p_sys->p_front_surface;
DirectXUpdateOverlay( p_vout ); DirectXUpdateOverlay( p_vout );
I_OUTPUTPICTURES = 1; I_OUTPUTPICTURES = 1;
} }
...@@ -1030,6 +1084,7 @@ static int NewPictureVec( vout_thread_t *p_vout, picture_t *p_pic, ...@@ -1030,6 +1084,7 @@ static int NewPictureVec( vout_thread_t *p_vout, picture_t *p_pic,
return -1; return -1;
} }
p_pic[i].p_sys->p_surface = p_surface; p_pic[i].p_sys->p_surface = p_surface;
p_pic[i].p_sys->p_front_surface = NULL;
I_OUTPUTPICTURES++; I_OUTPUTPICTURES++;
} }
...@@ -1083,6 +1138,12 @@ static void FreePictureVec( vout_thread_t *p_vout, picture_t *p_pic, ...@@ -1083,6 +1138,12 @@ static void FreePictureVec( vout_thread_t *p_vout, picture_t *p_pic,
for( i = 0; i < i_num_pics; i++ ) for( i = 0; i < i_num_pics; i++ )
{ {
#if 0
if( p_pic->p_sys->p_front_surface &&
( p_pic->p_sys->p_surface != p_pic->p_sys->p_front_surface ) )
DirectXCloseSurface( p_vout, p_pic[i].p_sys->p_front_surface );
#endif
DirectXCloseSurface( p_vout, p_pic[i].p_sys->p_surface ); DirectXCloseSurface( p_vout, p_pic[i].p_sys->p_surface );
for( i = 0; i < i_num_pics; i++ ) for( i = 0; i < i_num_pics; i++ )
...@@ -1158,7 +1219,7 @@ static int UpdatePictureStruct( vout_thread_t *p_vout, picture_t *p_pic, ...@@ -1158,7 +1219,7 @@ static int UpdatePictureStruct( vout_thread_t *p_vout, picture_t *p_pic,
p_pic->i_planes = 1; p_pic->i_planes = 1;
break; break;
#if 0
case FOURCC_I420: case FOURCC_I420:
p_pic->Y_PIXELS = p_pic->p_sys->ddsd.lpSurface; p_pic->Y_PIXELS = p_pic->p_sys->ddsd.lpSurface;
...@@ -1184,6 +1245,7 @@ static int UpdatePictureStruct( vout_thread_t *p_vout, picture_t *p_pic, ...@@ -1184,6 +1245,7 @@ static int UpdatePictureStruct( vout_thread_t *p_vout, picture_t *p_pic,
p_pic->i_planes = 3; p_pic->i_planes = 3;
break; break;
#if 0
case FOURCC_Y211: case FOURCC_Y211:
p_pic->p->p_pixels = p_pic->p_sys->p_image->data p_pic->p->p_pixels = p_pic->p_sys->p_image->data
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* vout_directx.h: Windows DirectX video output header file * vout_directx.h: Windows DirectX video output header file
***************************************************************************** *****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN * Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: vout_directx.h,v 1.2 2002/01/17 23:02:45 gbazin Exp $ * $Id: vout_directx.h,v 1.3 2002/01/27 22:14:52 gbazin Exp $
* *
* Authors: Gildas Bazin <gbazin@netcourrier.com> * Authors: Gildas Bazin <gbazin@netcourrier.com>
* *
...@@ -88,6 +88,7 @@ typedef struct picture_sys_s ...@@ -88,6 +88,7 @@ typedef struct picture_sys_s
{ {
LPDIRECTDRAWSURFACE3 p_surface; LPDIRECTDRAWSURFACE3 p_surface;
DDSURFACEDESC ddsd; DDSURFACEDESC ddsd;
LPDIRECTDRAWSURFACE3 p_front_surface;
} picture_sys_t; } picture_sys_t;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* vout_events.c: Windows DirectX video output events handler * vout_events.c: Windows DirectX video output events handler
***************************************************************************** *****************************************************************************
* Copyright (C) 2001 VideoLAN * Copyright (C) 2001 VideoLAN
* $Id: vout_events.c,v 1.9 2002/01/21 07:00:21 gbazin Exp $ * $Id: vout_events.c,v 1.10 2002/01/27 22:14:52 gbazin Exp $
* *
* Authors: Gildas Bazin <gbazin@netcourrier.com> * Authors: Gildas Bazin <gbazin@netcourrier.com>
* *
...@@ -102,16 +102,6 @@ void DirectXEventThread( vout_thread_t *p_vout ) ...@@ -102,16 +102,6 @@ void DirectXEventThread( vout_thread_t *p_vout )
switch( msg.message ) switch( msg.message )
{ {
#if 0
case WM_PAINT:
intf_WarnMsg( 4, "vout: vout_Manage WM_PAINT" );
break;
case WM_ERASEBKGND:
intf_WarnMsg( 4, "vout: vout_Manage WM_ERASEBKGND" );
break;
#endif
case WM_MOUSEMOVE: case WM_MOUSEMOVE:
if( p_vout->p_sys->b_cursor ) if( p_vout->p_sys->b_cursor )
{ {
...@@ -126,6 +116,7 @@ void DirectXEventThread( vout_thread_t *p_vout ) ...@@ -126,6 +116,7 @@ void DirectXEventThread( vout_thread_t *p_vout )
p_vout->p_sys->i_lastmoved = mdate(); p_vout->p_sys->i_lastmoved = mdate();
} }
} }
DispatchMessage(&msg);
break; break;
case WM_RBUTTONUP: case WM_RBUTTONUP:
...@@ -221,11 +212,9 @@ void DirectXEventThread( vout_thread_t *p_vout ) ...@@ -221,11 +212,9 @@ void DirectXEventThread( vout_thread_t *p_vout )
if( msg.message == WM_QUIT ) if( msg.message == WM_QUIT )
{ {
intf_WarnMsg( 3, "vout: DirectXEventThread WM_QUIT" ); intf_WarnMsg( 3, "vout: DirectXEventThread WM_QUIT... "
"shouldn't happen!!" );
p_vout->p_sys->hwnd = NULL; /* Window already destroyed */ p_vout->p_sys->hwnd = NULL; /* Window already destroyed */
/* exit application */
p_main->p_intf->b_die = 1;
} }
intf_WarnMsg( 3, "vout: DirectXEventThread Terminating" ); intf_WarnMsg( 3, "vout: DirectXEventThread Terminating" );
...@@ -322,9 +311,14 @@ static int DirectXCreateWindow( vout_thread_t *p_vout ) ...@@ -322,9 +311,14 @@ static int DirectXCreateWindow( vout_thread_t *p_vout )
/* register the window class */ /* register the window class */
if (!RegisterClassEx(&wc)) if (!RegisterClassEx(&wc))
{ {
intf_WarnMsg( 3, "vout: DirectXCreateWindow register window FAILED" ); /* Check why it failed. If it's because one already exists then fine */
WNDCLASS wndclass;
if( !GetClassInfo( hInstance, "VLC DirectX", &wndclass ) )
{
intf_ErrMsg( "vout: DirectXCreateWindow RegisterClass FAILED" );
return (1); return (1);
} }
}
/* when you create a window you give the dimensions you wish it to have. /* when you create a window you give the dimensions you wish it to have.
* Unfortunatly these dimensions will include the borders and title bar. * Unfortunatly these dimensions will include the borders and title bar.
...@@ -341,8 +335,8 @@ static int DirectXCreateWindow( vout_thread_t *p_vout ) ...@@ -341,8 +335,8 @@ static int DirectXCreateWindow( vout_thread_t *p_vout )
"VLC DirectX", /* window title bar text */ "VLC DirectX", /* window title bar text */
WS_OVERLAPPEDWINDOW WS_OVERLAPPEDWINDOW
| WS_SIZEBOX, /* window style */ | WS_SIZEBOX, /* window style */
10, /* default X coordinate */ CW_USEDEFAULT, /* default X coordinate */
10, /* default Y coordinate */ 0, /* default Y coordinate */
rect_window.right - rect_window.left, /* window width */ rect_window.right - rect_window.left, /* window width */
rect_window.bottom - rect_window.top, /* window height */ rect_window.bottom - rect_window.top, /* window height */
NULL, /* no parent window */ NULL, /* no parent window */
...@@ -373,8 +367,6 @@ static int DirectXCreateWindow( vout_thread_t *p_vout ) ...@@ -373,8 +367,6 @@ static int DirectXCreateWindow( vout_thread_t *p_vout )
*****************************************************************************/ *****************************************************************************/
static void DirectXCloseWindow( vout_thread_t *p_vout ) static void DirectXCloseWindow( vout_thread_t *p_vout )
{ {
HINSTANCE hInstance;
intf_WarnMsg( 3, "vout: DirectXCloseWindow" ); intf_WarnMsg( 3, "vout: DirectXCloseWindow" );
if( p_vout->p_sys->hwnd != NULL ) if( p_vout->p_sys->hwnd != NULL )
{ {
...@@ -382,9 +374,9 @@ static void DirectXCloseWindow( vout_thread_t *p_vout ) ...@@ -382,9 +374,9 @@ static void DirectXCloseWindow( vout_thread_t *p_vout )
p_vout->p_sys->hwnd = NULL; p_vout->p_sys->hwnd = NULL;
} }
hInstance = GetModuleHandle(NULL); /* We don't unregister the Window Class because it could lead to race
UnregisterClass( "VLC DirectX", /* class name */ * conditions and it will be done anyway by the system when the app will
hInstance ); /* handle to application instance */ * exit */
/* free window background brush */ /* free window background brush */
if( p_vout->p_sys->hbrush != NULL ) if( p_vout->p_sys->hbrush != NULL )
...@@ -514,7 +506,8 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message, ...@@ -514,7 +506,8 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message,
p_vout->p_sys->i_window_height ); p_vout->p_sys->i_window_height );
DirectXUpdateRects( p_vout ); DirectXUpdateRects( p_vout );
if( p_vout->p_sys->b_using_overlay ) if( p_vout->p_sys->b_using_overlay &&
!p_vout->p_sys->b_event_thread_die )
DirectXUpdateOverlay( p_vout ); DirectXUpdateOverlay( p_vout );
/* signal the size change */ /* signal the size change */
...@@ -535,13 +528,15 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message, ...@@ -535,13 +528,15 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message,
/* the user wants to close the window */ /* the user wants to close the window */
case WM_CLOSE: case WM_CLOSE:
intf_WarnMsg( 4, "vout: WinProc WM_CLOSE" ); intf_WarnMsg( 4, "vout: WinProc WM_CLOSE" );
/* exit application */
p_main->p_intf->b_die = 1;
return 0;
break; break;
/* the window has been closed so shut down everything now */ /* the window has been closed so shut down everything now */
case WM_DESTROY: case WM_DESTROY:
intf_WarnMsg( 4, "vout: WinProc WM_DESTROY" ); intf_WarnMsg( 4, "vout: WinProc WM_DESTROY" );
/* exit application */ /* just destroy the window */
p_main->p_intf->b_die = 1;
PostQuitMessage( 0 ); PostQuitMessage( 0 );
return 0; return 0;
break; break;
...@@ -556,6 +551,34 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message, ...@@ -556,6 +551,34 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message,
} }
break; break;
#if 0
case WM_PAINT:
intf_WarnMsg( 4, "vout: WinProc WM_PAINT" );
break;
#endif
case WM_ERASEBKGND:
p_vout = (vout_thread_t *)GetWindowLong( hwnd, GWL_USERDATA );
if( !p_vout->p_sys->b_using_overlay )
{
/* We want to eliminate unnecessary background redraws which create
* an annoying flickering */
int i_width, i_height, i_x, i_y;
RECT rect_temp;
GetClipBox( (HDC)wParam, &rect_temp );
#if 0
intf_WarnMsg( 4, "vout: WinProc WM_ERASEBKGND %i,%i,%i,%i",
rect_temp.left, rect_temp.top,
rect_temp.right, rect_temp.bottom );
#endif
vout_PlacePicture( p_vout, p_vout->p_sys->i_window_width,
p_vout->p_sys->i_window_height,
&i_x, &i_y, &i_width, &i_height );
ExcludeClipRect( (HDC)wParam, i_x, i_y,
i_x + i_width, i_y + i_height );
}
break;
#if 0 #if 0
default: default:
intf_WarnMsg( 4, "vout: WinProc WM Default %i", message ); intf_WarnMsg( 4, "vout: WinProc WM Default %i", message );
......
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