* vout_directx.c: Windows DirectX video output display method
*****************************************************************************
* 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>
*
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 );
}
p_vout->p_sys->b_event_thread_die = 1;
/* we need to be sure DirectXEventThread won't stay stuck in GetMessage,
* 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);
vlc_thread_join( p_vout->p_sys->event_thread_id );
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->p_sys->i_changes &= ~VOUT_SCALE_CHANGE;
}
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->p_sys->i_changes &= ~VOUT_SIZE_CHANGE;
}
{
HRESULT dxresult;
- intf_WarnMsg( 8, "vout: vout_Display" );
-
if( (p_vout->p_sys->p_display == NULL) )
{
intf_WarnMsg( 3, "vout error: vout_Display no display!!" );
/* Blit video surface to 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,
- NULL,
+ &p_vout->p_sys->rect_src_clipped,
0, &ddbltfx );
+ }
+
if( dxresult != DD_OK )
{
intf_WarnMsg( 3, "vout: could not Blit the surface" );
{
/* 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 ) )
{
return;
}
- /* set currently displayed pic !!! faux*/
- p_vout->p_sys->p_current_surface = p_pic->p_sys->p_surface;
+ /* set currently displayed pic */
+ p_vout->p_sys->p_current_surface = p_pic->p_sys->p_front_surface;
}
- intf_WarnMsg( 8, "vout: vout_Display End" );
}
ddsd.dwFlags = DDSD_CAPS |
DDSD_HEIGHT |
DDSD_WIDTH |
- //DDSD_BACKBUFFERCOUNT |
+ DDSD_BACKBUFFERCOUNT |
DDSD_PIXELFORMAT;
ddsd.ddsCaps.dwCaps = DDSCAPS_OVERLAY |
- // DDSCAPS_COMPLEX |
- //DDSCAPS_FLIP |
+ DDSCAPS_COMPLEX |
+ DDSCAPS_FLIP |
DDSCAPS_VIDEOMEMORY;
ddsd.dwHeight = p_vout->render.i_height;
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,
&ddsd,
p_vout->output.i_chroma = p_vout->render.i_chroma;
/* hack */
+#if 1
if( p_vout->render.i_chroma == FOURCC_I420 )
p_vout->output.i_chroma = FOURCC_YV12;
+#endif
/* First we try to create an overlay surface.
* It looks like with most hardware it's not possible to create several
if( DirectXCreateSurface( p_vout, &p_surface, p_vout->output.i_chroma,
p_vout->p_sys->b_using_overlay ) )
{
+ DDSCAPS dds_caps;
+
/* Allocate internal structure */
p_pic[0].p_sys = malloc( sizeof( picture_sys_t ) );
if( p_pic[0].p_sys == NULL )
DirectXCloseSurface( p_vout, p_surface );
return -1;
}
- p_pic[0].p_sys->p_surface = p_surface;
- p_vout->p_sys->p_current_surface = p_surface;
+
+ /* 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_vout->p_sys->p_current_surface= p_pic[0].p_sys->p_front_surface;
DirectXUpdateOverlay( p_vout );
I_OUTPUTPICTURES = 1;
}
return -1;
}
p_pic[i].p_sys->p_surface = p_surface;
+ p_pic[i].p_sys->p_front_surface = NULL;
I_OUTPUTPICTURES++;
}
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 );
for( i = 0; i < i_num_pics; i++ )
p_pic->i_planes = 1;
break;
-#if 0
+
case FOURCC_I420:
p_pic->Y_PIXELS = p_pic->p_sys->ddsd.lpSurface;
p_pic->i_planes = 3;
break;
+#if 0
case FOURCC_Y211:
p_pic->p->p_pixels = p_pic->p_sys->p_image->data
* vout_events.c: Windows DirectX video output events handler
*****************************************************************************
* 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>
*
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:
if( p_vout->p_sys->b_cursor )
{
p_vout->p_sys->i_lastmoved = mdate();
}
}
+ DispatchMessage(&msg);
break;
case WM_RBUTTONUP:
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 */
-
- /* exit application */
- p_main->p_intf->b_die = 1;
}
intf_WarnMsg( 3, "vout: DirectXEventThread Terminating" );
/* register the window class */
if (!RegisterClassEx(&wc))
{
- intf_WarnMsg( 3, "vout: DirectXCreateWindow register window FAILED" );
- return (1);
+ /* 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);
+ }
}
/* when you create a window you give the dimensions you wish it to have.
"VLC DirectX", /* window title bar text */
WS_OVERLAPPEDWINDOW
| WS_SIZEBOX, /* window style */
- 10, /* default X coordinate */
- 10, /* default Y coordinate */
+ CW_USEDEFAULT, /* default X coordinate */
+ 0, /* default Y coordinate */
rect_window.right - rect_window.left, /* window width */
rect_window.bottom - rect_window.top, /* window height */
NULL, /* no parent window */
*****************************************************************************/
static void DirectXCloseWindow( vout_thread_t *p_vout )
{
- HINSTANCE hInstance;
-
intf_WarnMsg( 3, "vout: DirectXCloseWindow" );
if( p_vout->p_sys->hwnd != NULL )
{
p_vout->p_sys->hwnd = NULL;
}
- hInstance = GetModuleHandle(NULL);
- UnregisterClass( "VLC DirectX", /* class name */
- hInstance ); /* handle to application instance */
+ /* We don't unregister the Window Class because it could lead to race
+ * conditions and it will be done anyway by the system when the app will
+ * exit */
/* free window background brush */
if( p_vout->p_sys->hbrush != NULL )
p_vout->p_sys->i_window_height );
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 );
/* signal the size change */
/* the user wants to close the window */
case WM_CLOSE:
intf_WarnMsg( 4, "vout: WinProc WM_CLOSE" );
+ /* exit application */
+ p_main->p_intf->b_die = 1;
+ return 0;
break;
/* the window has been closed so shut down everything now */
case WM_DESTROY:
intf_WarnMsg( 4, "vout: WinProc WM_DESTROY" );
- /* exit application */
- p_main->p_intf->b_die = 1;
+ /* just destroy the window */
PostQuitMessage( 0 );
return 0;
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
default:
intf_WarnMsg( 4, "vout: WinProc WM Default %i", message );