2002-09-28 19:17:34 +00:00
/******************************************************************************
* vo_directx . c : Directx v2 or later DirectDraw interface for MPlayer
2004-04-13 13:33:03 +00:00
* Copyright ( c ) 2002 - 2004 Sascha Sommer < saschasommer @ freenet . de > .
2002-09-28 19:17:34 +00:00
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place - Suite 330 , Boston , MA 02111 , USA .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include <windows.h>
# include <windowsx.h>
# include <ddraw.h>
2004-02-29 20:33:07 +00:00
# include <stdio.h>
2002-09-28 19:17:34 +00:00
# include <stdlib.h>
# include <errno.h>
# include "config.h"
# include "video_out.h"
# include "video_out_internal.h"
# include "fastmemcpy.h"
# include "../input/input.h"
2003-02-09 20:18:23 +00:00
# include "../osdep/keycodes.h"
2004-03-13 16:37:12 +00:00
# include "../input/mouse.h"
2002-09-28 19:17:34 +00:00
# include "../mp_msg.h"
2002-12-21 23:49:33 +00:00
# include "aspect.h"
2003-09-21 10:31:22 +00:00
# include "geometry.h"
2002-09-28 19:17:34 +00:00
2004-08-26 22:15:26 +00:00
# ifndef WM_XBUTTONDOWN
# define WM_XBUTTONDOWN 0x020B
# define WM_XBUTTONUP 0x020C
# define WM_XBUTTONDBLCLK 0x020D
# endif
2004-10-22 13:37:43 +00:00
static LPDIRECTDRAWCOLORCONTROL g_cc = NULL ; //color control interface
2004-02-29 20:33:07 +00:00
static LPDIRECTDRAW7 g_lpdd = NULL ; //DirectDraw Object
static LPDIRECTDRAWSURFACE7 g_lpddsPrimary = NULL ; //Primary Surface: viewport through the Desktop
static LPDIRECTDRAWSURFACE7 g_lpddsOverlay = NULL ; //Overlay Surface
static LPDIRECTDRAWSURFACE7 g_lpddsBack = NULL ; //Back surface
2002-10-06 16:56:42 +00:00
static LPDIRECTDRAWCLIPPER g_lpddclipper ; //clipper object, can only be used without overlay
2004-02-29 20:33:07 +00:00
static DDSURFACEDESC2 ddsdsf ; //surface descripiton needed for locking
2002-10-17 13:17:56 +00:00
static HINSTANCE hddraw_dll ; //handle to ddraw.dll
2002-09-28 19:17:34 +00:00
static RECT rd ; //rect of our stretched image
static RECT rs ; //rect of our source image
static HWND hWnd = NULL ; //handle to the window
2004-02-29 20:33:07 +00:00
static HWND hWndFS = NULL ; //fullscreen window
2002-09-28 19:17:34 +00:00
static uint32_t image_width , image_height ; //image width and height
static uint32_t d_image_width , d_image_height ; //image width and height zoomed
static uint8_t * image = NULL ; //image data
2003-08-17 12:55:21 +00:00
static uint32_t image_format = 0 ; //image format
static uint32_t primary_image_format ;
2004-02-29 20:33:07 +00:00
static uint32_t vm_height = 0 ;
static uint32_t vm_width = 0 ;
static uint32_t vm_bpp = 0 ;
2002-09-28 19:17:34 +00:00
static uint32_t dstride ; //surface stride
2002-10-09 19:03:17 +00:00
static uint32_t nooverlay = 0 ; //NonOverlay mode
2002-10-06 16:56:42 +00:00
static DWORD destcolorkey ; //colorkey for our surface
static COLORREF windowcolor = RGB ( 0 , 0 , 16 ) ; //windowcolor == colorkey
2004-02-29 20:33:07 +00:00
static int adapter_count = 0 ;
static GUID selected_guid ;
static GUID * selected_guid_ptr = NULL ;
2004-05-01 20:21:03 +00:00
static float window_aspect ;
2002-09-28 19:17:34 +00:00
extern void mplayer_put_key ( int code ) ; //let mplayer handel the keyevents
2002-12-30 23:14:31 +00:00
extern void vo_draw_text ( int dxs , int dys , void ( * draw_alpha ) ( int x0 , int y0 , int w , int h , unsigned char * src , unsigned char * srca , int stride ) ) ;
2002-09-28 19:17:34 +00:00
extern int vo_doublebuffering ; //tribblebuffering
2003-09-21 10:31:22 +00:00
extern int vo_fs ;
2003-10-09 17:28:16 +00:00
extern int vo_directrendering ;
2003-11-30 16:36:10 +00:00
extern int vo_ontop ;
2004-08-22 18:57:45 +00:00
extern int vo_rootwin ;
2004-02-29 20:33:07 +00:00
extern int vidmode ;
2002-09-28 19:17:34 +00:00
/*****************************************************************************
* DirectDraw GUIDs .
* Defining them here allows us to get rid of the dxguid library during
* the linking stage .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-02-29 20:33:07 +00:00
static const GUID IID_IDirectDraw7 =
2002-12-30 23:14:31 +00:00
{
2004-02-29 20:33:07 +00:00
0x15e65ec0 , 0x3b9c , 0x11d2 , { 0xb9 , 0x2f , 0x00 , 0x60 , 0x97 , 0x97 , 0xea , 0x5b }
2002-12-30 23:14:31 +00:00
} ;
2002-09-28 19:17:34 +00:00
2004-10-22 13:37:43 +00:00
static const GUID IID_IDirectDrawColorControl =
{
0x4b9f0ee0 , 0x0d7e , 0x11d0 , { 0x9b , 0x06 , 0x00 , 0xa0 , 0xc9 , 0x03 , 0xa3 , 0xb8 }
} ;
2002-09-28 19:17:34 +00:00
typedef struct directx_fourcc_caps
{
char * img_format_name ; //human readable name
uint32_t img_format ; //as MPlayer image format
uint32_t drv_caps ; //what hw supports with this format
DDPIXELFORMAT g_ddpfOverlay ; //as Directx Sourface description
} directx_fourcc_caps ;
static directx_fourcc_caps g_ddpf [ ] =
{
{ " YV12 " , IMGFMT_YV12 , 0 , { sizeof ( DDPIXELFORMAT ) , DDPF_FOURCC , MAKEFOURCC ( ' Y ' , ' V ' , ' 1 ' , ' 2 ' ) , 0 , 0 , 0 , 0 , 0 } } ,
{ " I420 " , IMGFMT_I420 , 0 , { sizeof ( DDPIXELFORMAT ) , DDPF_FOURCC , MAKEFOURCC ( ' I ' , ' 4 ' , ' 2 ' , ' 0 ' ) , 0 , 0 , 0 , 0 , 0 } } , //yv12 with swapped uv
{ " IYUV " , IMGFMT_IYUV , 0 , { sizeof ( DDPIXELFORMAT ) , DDPF_FOURCC , MAKEFOURCC ( ' I ' , ' Y ' , ' U ' , ' V ' ) , 0 , 0 , 0 , 0 , 0 } } , //same as i420
{ " YVU9 " , IMGFMT_YVU9 , 0 , { sizeof ( DDPIXELFORMAT ) , DDPF_FOURCC , MAKEFOURCC ( ' Y ' , ' V ' , ' U ' , ' 9 ' ) , 0 , 0 , 0 , 0 , 0 } } ,
{ " YUY2 " , IMGFMT_YUY2 , 0 , { sizeof ( DDPIXELFORMAT ) , DDPF_FOURCC , MAKEFOURCC ( ' Y ' , ' U ' , ' Y ' , ' 2 ' ) , 0 , 0 , 0 , 0 , 0 } } ,
2004-05-01 20:21:03 +00:00
{ " UYVY " , IMGFMT_UYVY , 0 , { sizeof ( DDPIXELFORMAT ) , DDPF_FOURCC , MAKEFOURCC ( ' U ' , ' Y ' , ' V ' , ' Y ' ) , 0 , 0 , 0 , 0 , 0 } } ,
2002-09-28 19:17:34 +00:00
{ " RGB15 " , IMGFMT_RGB15 , 0 , { sizeof ( DDPIXELFORMAT ) , DDPF_RGB , 0 , 16 , 0x0000001F , 0x000003E0 , 0x00007C00 , 0 } } , //RGB 5:5:5
{ " BGR15 " , IMGFMT_BGR15 , 0 , { sizeof ( DDPIXELFORMAT ) , DDPF_RGB , 0 , 16 , 0x00007C00 , 0x000003E0 , 0x0000001F , 0 } } ,
2003-08-17 20:01:22 +00:00
{ " RGB16 " , IMGFMT_RGB16 , 0 , { sizeof ( DDPIXELFORMAT ) , DDPF_RGB , 0 , 16 , 0x0000001F , 0x000007E0 , 0x0000F800 , 0 } } , //RGB 5:6:5
{ " BGR16 " , IMGFMT_BGR16 , 0 , { sizeof ( DDPIXELFORMAT ) , DDPF_RGB , 0 , 16 , 0x0000F800 , 0x000007E0 , 0x0000001F , 0 } } ,
2002-09-28 19:17:34 +00:00
{ " RGB24 " , IMGFMT_RGB24 , 0 , { sizeof ( DDPIXELFORMAT ) , DDPF_RGB , 0 , 24 , 0x000000FF , 0x0000FF00 , 0x00FF0000 , 0 } } ,
{ " BGR24 " , IMGFMT_BGR24 , 0 , { sizeof ( DDPIXELFORMAT ) , DDPF_RGB , 0 , 24 , 0x00FF0000 , 0x0000FF00 , 0x000000FF , 0 } } ,
{ " RGB32 " , IMGFMT_RGB32 , 0 , { sizeof ( DDPIXELFORMAT ) , DDPF_RGB , 0 , 32 , 0x000000FF , 0x0000FF00 , 0x00FF0000 , 0 } } ,
{ " BGR32 " , IMGFMT_BGR32 , 0 , { sizeof ( DDPIXELFORMAT ) , DDPF_RGB , 0 , 32 , 0x00FF0000 , 0x0000FF00 , 0x000000FF , 0 } }
} ;
# define NUM_FORMATS (sizeof(g_ddpf) / sizeof(g_ddpf[0]))
2002-11-11 15:22:10 +00:00
static vo_info_t info =
2002-09-28 19:17:34 +00:00
{
" Directx DDraw YUV/RGB/BGR renderer " ,
" directx " ,
" Sascha Sommer <saschasommer@freenet.de> " ,
" "
} ;
2002-11-11 15:22:10 +00:00
LIBVO_EXTERN ( directx )
2002-09-28 19:17:34 +00:00
static void draw_alpha ( int x0 , int y0 , int w , int h , unsigned char * src ,
unsigned char * srca , int stride )
{
switch ( image_format ) {
case IMGFMT_YV12 :
case IMGFMT_I420 :
case IMGFMT_IYUV :
case IMGFMT_YVU9 :
2002-12-19 12:01:50 +00:00
vo_draw_alpha_yv12 ( w , h , src , srca , stride , ( ( uint8_t * ) image ) + dstride * y0 + x0 , dstride ) ;
2002-09-28 19:17:34 +00:00
break ;
case IMGFMT_YUY2 :
2002-12-19 12:01:50 +00:00
vo_draw_alpha_yuy2 ( w , h , src , srca , stride , ( ( uint8_t * ) image ) + dstride * y0 + 2 * x0 , dstride ) ;
2002-09-28 19:17:34 +00:00
break ;
case IMGFMT_UYVY :
2002-12-19 12:01:50 +00:00
vo_draw_alpha_yuy2 ( w , h , src , srca , stride , ( ( uint8_t * ) image ) + dstride * y0 + 2 * x0 + 1 , dstride ) ;
2002-09-28 19:17:34 +00:00
break ;
case IMGFMT_RGB15 :
case IMGFMT_BGR15 :
vo_draw_alpha_rgb15 ( w , h , src , srca , stride , ( ( uint8_t * ) image ) + dstride * y0 + 2 * x0 , dstride ) ;
break ;
case IMGFMT_RGB16 :
case IMGFMT_BGR16 :
vo_draw_alpha_rgb16 ( w , h , src , srca , stride , ( ( uint8_t * ) image ) + dstride * y0 + 2 * x0 , dstride ) ;
break ;
case IMGFMT_RGB24 :
case IMGFMT_BGR24 :
vo_draw_alpha_rgb24 ( w , h , src , srca , stride , ( ( uint8_t * ) image ) + dstride * y0 + 4 * x0 , dstride ) ;
break ;
case IMGFMT_RGB32 :
case IMGFMT_BGR32 :
vo_draw_alpha_rgb32 ( w , h , src , srca , stride , ( ( uint8_t * ) image ) + dstride * y0 + 4 * x0 , dstride ) ;
break ;
}
}
static void draw_osd ( void )
{
vo_draw_text ( image_width , image_height , draw_alpha ) ;
}
static uint32_t
query_format ( uint32_t format )
{
uint32_t i = 0 ;
while ( i < NUM_FORMATS )
{
if ( g_ddpf [ i ] . img_format = = format )
return g_ddpf [ i ] . drv_caps ;
i + + ;
}
return 0 ;
}
static uint32_t Directx_CreatePrimarySurface ( )
{
2004-02-29 20:33:07 +00:00
DDSURFACEDESC2 ddsd ;
2002-09-28 19:17:34 +00:00
//cleanup
if ( g_lpddsPrimary ) g_lpddsPrimary - > lpVtbl - > Release ( g_lpddsPrimary ) ;
g_lpddsPrimary = NULL ;
2004-02-29 20:33:07 +00:00
2004-03-13 16:48:52 +00:00
if ( vidmode ) g_lpdd - > lpVtbl - > SetDisplayMode ( g_lpdd , vm_width , vm_height , vm_bpp , vo_refresh_rate , 0 ) ;
2004-02-29 20:33:07 +00:00
ZeroMemory ( & ddsd , sizeof ( ddsd ) ) ;
2002-09-28 19:17:34 +00:00
ddsd . dwSize = sizeof ( ddsd ) ;
//set flags and create a primary surface.
ddsd . dwFlags = DDSD_CAPS ;
ddsd . ddsCaps . dwCaps = DDSCAPS_PRIMARYSURFACE ;
if ( g_lpdd - > lpVtbl - > CreateSurface ( g_lpdd , & ddsd , & g_lpddsPrimary , NULL ) = = DD_OK )
mp_msg ( MSGT_VO , MSGL_DBG3 , " <vo_directx><INFO>primary surface created \n " ) ;
else
{
mp_msg ( MSGT_VO , MSGL_FATAL , " <vo_directx><FATAL ERROR>could not create primary surface \n " ) ;
return 1 ;
}
return 0 ;
}
static uint32_t Directx_CreateOverlay ( uint32_t imgfmt )
{
HRESULT ddrval ;
2004-02-29 20:33:07 +00:00
DDSURFACEDESC2 ddsdOverlay ;
2002-09-28 19:17:34 +00:00
uint32_t i = 0 ;
while ( i < NUM_FORMATS + 1 & & imgfmt ! = g_ddpf [ i ] . img_format )
{
i + + ;
}
if ( ! g_lpdd | | ! g_lpddsPrimary )
return 1 ;
//cleanup
if ( g_lpddsOverlay ) g_lpddsOverlay - > lpVtbl - > Release ( g_lpddsOverlay ) ;
if ( g_lpddsBack ) g_lpddsBack - > lpVtbl - > Release ( g_lpddsBack ) ;
g_lpddsOverlay = NULL ;
g_lpddsBack = NULL ;
//create our overlay
ZeroMemory ( & ddsdOverlay , sizeof ( ddsdOverlay ) ) ;
ddsdOverlay . dwSize = sizeof ( ddsdOverlay ) ;
ddsdOverlay . ddsCaps . dwCaps = DDSCAPS_OVERLAY | DDSCAPS_FLIP | DDSCAPS_COMPLEX | DDSCAPS_VIDEOMEMORY ;
ddsdOverlay . dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_BACKBUFFERCOUNT | DDSD_PIXELFORMAT ;
ddsdOverlay . dwWidth = image_width ;
ddsdOverlay . dwHeight = image_height ;
ddsdOverlay . dwBackBufferCount = 2 ;
ddsdOverlay . ddpfPixelFormat = g_ddpf [ i ] . g_ddpfOverlay ;
if ( vo_doublebuffering ) //tribblebuffering
{
if ( g_lpdd - > lpVtbl - > CreateSurface ( g_lpdd , & ddsdOverlay , & g_lpddsOverlay , NULL ) = = DD_OK )
{
mp_msg ( MSGT_VO , MSGL_V , " <vo_directx><INFO>overlay with format %s created \n " , g_ddpf [ i ] . img_format_name ) ;
//get the surface directly attached to the primary (the back buffer)
ddsdOverlay . ddsCaps . dwCaps = DDSCAPS_BACKBUFFER ;
if ( g_lpddsOverlay - > lpVtbl - > GetAttachedSurface ( g_lpddsOverlay , & ddsdOverlay . ddsCaps , & g_lpddsBack ) ! = DD_OK )
{
mp_msg ( MSGT_VO , MSGL_FATAL , " <vo_directx><FATAL ERROR>can't get attached surface \n " ) ;
return 1 ;
}
return 0 ;
}
vo_doublebuffering = 0 ; //disable tribblebuffering
mp_msg ( MSGT_VO , MSGL_V , " <vo_directx><WARN>cannot create tribblebuffer overlay with format %s \n " , g_ddpf [ i ] . img_format_name ) ;
}
//single buffer
mp_msg ( MSGT_VO , MSGL_V , " <vo_directx><INFO>using singlebuffer overlay \n " ) ;
ddsdOverlay . dwBackBufferCount = 0 ;
ddsdOverlay . ddsCaps . dwCaps = DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY ;
ddsdOverlay . dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT ;
ddsdOverlay . ddpfPixelFormat = g_ddpf [ i ] . g_ddpfOverlay ;
// try to create the overlay surface
ddrval = g_lpdd - > lpVtbl - > CreateSurface ( g_lpdd , & ddsdOverlay , & g_lpddsOverlay , NULL ) ;
if ( ddrval ! = DD_OK )
{
2003-08-17 12:55:21 +00:00
if ( ddrval = = DDERR_INVALIDPIXELFORMAT ) mp_msg ( MSGT_VO , MSGL_V , " <vo_directx><ERROR> invalid pixelformat: %s \n " , g_ddpf [ i ] . img_format_name ) ;
else mp_msg ( MSGT_VO , MSGL_ERR , " <vo_directx><ERROR> " ) ;
switch ( ddrval )
2002-09-28 19:17:34 +00:00
{
case DDERR_INCOMPATIBLEPRIMARY :
{ mp_msg ( MSGT_VO , MSGL_ERR , " incompatible primary surface \n " ) ; break ; }
case DDERR_INVALIDCAPS :
{ mp_msg ( MSGT_VO , MSGL_ERR , " invalid caps \n " ) ; break ; }
case DDERR_INVALIDOBJECT :
{ mp_msg ( MSGT_VO , MSGL_ERR , " invalid object \n " ) ; break ; }
case DDERR_INVALIDPARAMS :
{ mp_msg ( MSGT_VO , MSGL_ERR , " invalid parameters \n " ) ; break ; }
case DDERR_NODIRECTDRAWHW :
{ mp_msg ( MSGT_VO , MSGL_ERR , " no directdraw hardware \n " ) ; break ; }
case DDERR_NOEMULATION :
2003-10-04 17:29:08 +00:00
{ mp_msg ( MSGT_VO , MSGL_ERR , " can't emulate \n " ) ; break ; }
2002-09-28 19:17:34 +00:00
case DDERR_NOFLIPHW :
{ mp_msg ( MSGT_VO , MSGL_ERR , " hardware can't do flip \n " ) ; break ; }
case DDERR_NOOVERLAYHW :
{ mp_msg ( MSGT_VO , MSGL_ERR , " hardware can't do overlay \n " ) ; break ; }
case DDERR_OUTOFMEMORY :
{ mp_msg ( MSGT_VO , MSGL_ERR , " not enough system memory \n " ) ; break ; }
case DDERR_UNSUPPORTEDMODE :
{ mp_msg ( MSGT_VO , MSGL_ERR , " unsupported mode \n " ) ; break ; }
case DDERR_OUTOFVIDEOMEMORY :
{ mp_msg ( MSGT_VO , MSGL_ERR , " not enough video memory \n " ) ; break ; }
2004-04-07 22:51:42 +00:00
default :
mp_msg ( MSGT_VO , MSGL_ERR , " create surface failed with 0x%x \n " , ddrval ) ;
2002-09-28 19:17:34 +00:00
}
return 1 ;
}
g_lpddsBack = g_lpddsOverlay ;
return 0 ;
}
static uint32_t Directx_CreateBackpuffer ( )
{
2004-02-29 20:33:07 +00:00
DDSURFACEDESC2 ddsd ;
2002-09-28 19:17:34 +00:00
//cleanup
if ( g_lpddsBack ) g_lpddsBack - > lpVtbl - > Release ( g_lpddsBack ) ;
g_lpddsBack = NULL ;
ZeroMemory ( & ddsd , sizeof ( ddsd ) ) ;
ddsd . dwSize = sizeof ( ddsd ) ;
ddsd . ddsCaps . dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY ;
ddsd . dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT ;
ddsd . dwWidth = image_width ;
ddsd . dwHeight = image_height ;
if ( g_lpdd - > lpVtbl - > CreateSurface ( g_lpdd , & ddsd , & g_lpddsBack , 0 ) ! = DD_OK )
{
mp_msg ( MSGT_VO , MSGL_FATAL , " <vo_directx><FATAL ERROR>can't create backpuffer \n " ) ;
return 1 ;
}
mp_msg ( MSGT_VO , MSGL_DBG3 , " <vo_directx><INFO>backbuffer created \n " ) ;
return 0 ;
}
static void uninit ( void )
{
2004-10-22 13:37:43 +00:00
if ( g_cc ! = NULL )
{
g_cc - > lpVtbl - > Release ( g_cc ) ;
}
g_cc = NULL ;
2002-09-28 19:17:34 +00:00
if ( g_lpddclipper ! = NULL ) g_lpddclipper - > lpVtbl - > Release ( g_lpddclipper ) ;
2003-03-19 15:28:11 +00:00
g_lpddclipper = NULL ;
2002-09-28 19:17:34 +00:00
mp_msg ( MSGT_VO , MSGL_DBG3 , " <vo_directx><INFO>clipper released \n " ) ;
if ( g_lpddsBack ! = NULL ) g_lpddsBack - > lpVtbl - > Release ( g_lpddsBack ) ;
g_lpddsBack = NULL ;
mp_msg ( MSGT_VO , MSGL_DBG3 , " <vo_directx><INFO>back surface released \n " ) ;
2003-08-17 12:55:21 +00:00
if ( vo_doublebuffering & & ! nooverlay )
2002-09-28 19:17:34 +00:00
{
if ( g_lpddsOverlay ! = NULL ) g_lpddsOverlay - > lpVtbl - > Release ( g_lpddsOverlay ) ;
g_lpddsOverlay = NULL ;
mp_msg ( MSGT_VO , MSGL_DBG3 , " <vo_directx><INFO>overlay surface released \n " ) ;
}
if ( g_lpddsPrimary ! = NULL ) g_lpddsPrimary - > lpVtbl - > Release ( g_lpddsPrimary ) ;
2002-10-09 19:03:17 +00:00
g_lpddsPrimary = NULL ;
mp_msg ( MSGT_VO , MSGL_DBG3 , " <vo_directx><INFO>primary released \n " ) ;
2004-02-29 20:33:07 +00:00
if ( hWndFS ) DestroyWindow ( hWndFS ) ;
2002-10-06 16:56:42 +00:00
if ( hWnd ! = NULL ) DestroyWindow ( hWnd ) ;
mp_msg ( MSGT_VO , MSGL_DBG3 , " <vo_directx><INFO>window destroyed \n " ) ;
2004-02-29 20:33:07 +00:00
if ( g_lpdd ! = NULL ) {
if ( vidmode ) g_lpdd - > lpVtbl - > RestoreDisplayMode ( g_lpdd ) ;
g_lpdd - > lpVtbl - > Release ( g_lpdd ) ;
}
2002-09-28 19:17:34 +00:00
mp_msg ( MSGT_VO , MSGL_DBG3 , " <vo_directx><INFO>directdrawobject released \n " ) ;
2002-10-17 13:17:56 +00:00
FreeLibrary ( hddraw_dll ) ;
hddraw_dll = NULL ;
mp_msg ( MSGT_VO , MSGL_DBG3 , " <vo_directx><INFO>ddraw.dll freed \n " ) ;
2002-09-28 19:17:34 +00:00
mp_msg ( MSGT_VO , MSGL_DBG3 , " <vo_directx><INFO>uninited \n " ) ;
}
2004-02-29 20:33:07 +00:00
static BOOL WINAPI EnumCallbackEx ( GUID FAR * lpGUID , LPSTR lpDriverDescription , LPSTR lpDriverName , LPVOID lpContext , HMONITOR hm )
{
mp_msg ( MSGT_VO , MSGL_INFO , " <vo_directx> adapter %d: " , adapter_count ) ;
if ( ! lpGUID )
{
mp_msg ( MSGT_VO , MSGL_INFO , " %s " , " Primary Display Adapter " ) ;
}
else
{
mp_msg ( MSGT_VO , MSGL_INFO , " %s " , lpDriverDescription ) ;
}
2004-03-13 16:48:52 +00:00
if ( adapter_count = = vo_adapter_num ) {
2004-02-29 20:33:07 +00:00
if ( ! lpGUID )
selected_guid_ptr = NULL ;
else
{
selected_guid = * lpGUID ;
selected_guid_ptr = & selected_guid ;
}
mp_msg ( MSGT_VO , MSGL_INFO , " \t \t <-- " ) ;
}
mp_msg ( MSGT_VO , MSGL_INFO , " \n " ) ;
adapter_count + + ;
return 1 ; // list all adapters
}
2002-09-28 19:17:34 +00:00
static uint32_t Directx_InitDirectDraw ( )
{
2004-02-29 20:33:07 +00:00
HRESULT ( WINAPI * OurDirectDrawCreateEx ) ( GUID * , LPVOID * , REFIID , IUnknown FAR * ) ;
2002-09-28 19:17:34 +00:00
LPDIRECTDRAW lpDDraw ;
2004-02-29 20:33:07 +00:00
DDSURFACEDESC2 ddsd ;
LPDIRECTDRAWENUMERATEEX OurDirectDrawEnumerateEx ;
2002-09-28 19:17:34 +00:00
mp_msg ( MSGT_VO , MSGL_DBG3 , " <vo_directx><INFO>Initing DirectDraw \n " ) ;
//load direct draw DLL: based on videolans code
hddraw_dll = LoadLibrary ( " DDRAW.DLL " ) ;
if ( hddraw_dll = = NULL )
{
mp_msg ( MSGT_VO , MSGL_FATAL , " <vo_directx><FATAL ERROR>failed loading ddraw.dll \n " ) ;
return 1 ;
}
2004-02-29 20:33:07 +00:00
2004-03-13 16:48:52 +00:00
if ( vo_adapter_num ) { //display other than default
2004-02-29 20:33:07 +00:00
OurDirectDrawEnumerateEx = ( LPDIRECTDRAWENUMERATEEX ) GetProcAddress ( hddraw_dll , " DirectDrawEnumerateExA " ) ;
if ( ! OurDirectDrawEnumerateEx ) {
FreeLibrary ( hddraw_dll ) ;
hddraw_dll = NULL ;
mp_msg ( MSGT_VO , MSGL_FATAL , " <vo_directx><FATAL ERROR>failed geting proc address: DirectDrawEnumerateEx \n " ) ;
mp_msg ( MSGT_VO , MSGL_FATAL , " <vo_directx><FATAL ERROR>no directx 7 or higher installed \n " ) ;
return 1 ;
}
// enumerate all display devices attached to the desktop
OurDirectDrawEnumerateEx ( EnumCallbackEx , NULL , DDENUM_ATTACHEDSECONDARYDEVICES ) ;
2004-03-13 16:48:52 +00:00
if ( vo_adapter_num > = adapter_count )
mp_msg ( MSGT_VO , MSGL_ERR , " Selected adapter (%d) doesn't exist: Default Display Adapter selected \n " , vo_adapter_num ) ;
2002-09-28 19:17:34 +00:00
}
2004-02-29 20:33:07 +00:00
OurDirectDrawCreateEx = ( void * ) GetProcAddress ( hddraw_dll , " DirectDrawCreateEx " ) ;
if ( OurDirectDrawCreateEx = = NULL )
{
FreeLibrary ( hddraw_dll ) ;
hddraw_dll = NULL ;
mp_msg ( MSGT_VO , MSGL_FATAL , " <vo_directx><FATAL ERROR>failed geting proc address: DirectDrawCreateEx \n " ) ;
return 1 ;
}
// initialize DirectDraw and create directx v7 object
if ( OurDirectDrawCreateEx ( selected_guid_ptr , ( VOID * * ) & g_lpdd , & IID_IDirectDraw7 , NULL ) ! = DD_OK )
2002-09-28 19:17:34 +00:00
{
FreeLibrary ( hddraw_dll ) ;
hddraw_dll = NULL ;
mp_msg ( MSGT_VO , MSGL_FATAL , " <vo_directx><FATAL ERROR>can't initialize ddraw \n " ) ;
return 1 ;
}
2004-02-29 20:33:07 +00:00
//get current screen siz for selected monitor ...
ddsd . dwSize = sizeof ( ddsd ) ;
ddsd . dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT ;
g_lpdd - > lpVtbl - > GetDisplayMode ( g_lpdd , & ddsd ) ;
if ( vo_screenwidth & & vo_screenheight )
{
vm_height = vo_screenheight ;
vm_width = vo_screenwidth ;
}
else
2002-09-28 19:17:34 +00:00
{
2004-02-29 20:33:07 +00:00
vm_height = ddsd . dwHeight ;
vm_width = ddsd . dwWidth ;
}
if ( vo_dbpp ) vm_bpp = vo_dbpp ;
else vm_bpp = ddsd . ddpfPixelFormat . dwRGBBitCount ;
if ( vidmode ) {
if ( g_lpdd - > lpVtbl - > SetCooperativeLevel ( g_lpdd , hWnd , DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN ) ! = DD_OK )
{
mp_msg ( MSGT_VO , MSGL_FATAL , " <vo_directx><FATAL ERROR>can't set cooperativelevel for exclusive mode \n " ) ;
return 1 ;
}
/*SetDisplayMode(ddobject,width,height,bpp,refreshrate,aditionalflags)*/
if ( g_lpdd - > lpVtbl - > SetDisplayMode ( g_lpdd , vm_width , vm_height , vm_bpp , 0 , 0 ) ! = DD_OK )
{
mp_msg ( MSGT_VO , MSGL_FATAL , " <vo_directx><FATAL ERROR>can't set displaymode \n " ) ;
return 1 ;
}
2004-03-13 16:48:52 +00:00
mp_msg ( MSGT_VO , MSGL_V , " <vo_directx><INFO>Inited adapter %i for %i x %i @ %i \n " , vo_adapter_num , vm_width , vm_height , vm_bpp ) ;
2004-02-29 20:33:07 +00:00
return 0 ;
}
if ( g_lpdd - > lpVtbl - > SetCooperativeLevel ( g_lpdd , hWnd , DDSCL_NORMAL ) ! = DD_OK ) // or DDSCL_SETFOCUSWINDOW
{
2002-09-28 19:17:34 +00:00
mp_msg ( MSGT_VO , MSGL_FATAL , " <vo_directx><FATAL ERROR>could not set cooperativelevel for hardwarecheck \n " ) ;
return 1 ;
}
mp_msg ( MSGT_VO , MSGL_DBG3 , " <vo_directx><INFO>DirectDraw Inited \n " ) ;
return 0 ;
}
static void check_events ( void )
{
MSG msg ;
while ( PeekMessage ( & msg , NULL , 0 , 0 , PM_REMOVE ) )
{
TranslateMessage ( & msg ) ;
DispatchMessage ( & msg ) ;
}
}
2004-02-29 20:33:07 +00:00
static uint32_t Directx_ManageDisplay ( )
2002-09-28 19:17:34 +00:00
{
HRESULT ddrval ;
DDCAPS capsDrv ;
DDOVERLAYFX ovfx ;
2002-12-30 23:14:31 +00:00
DWORD dwUpdateFlags = 0 ;
2004-05-01 20:21:03 +00:00
int width , height ;
if ( vo_fs | | vidmode ) {
aspect ( & width , & height , A_ZOOM ) ;
rd . left = ( vo_screenwidth - width ) / 2 ;
rd . top = ( vo_screenheight - height ) / 2 ;
if ( ShowCursor ( FALSE ) > = 0 ) while ( ShowCursor ( FALSE ) > = 0 ) { }
}
else {
POINT pt ;
pt . x = 0 ; //overlayposition relative to the window
pt . y = 0 ;
ClientToScreen ( hWnd , & pt ) ;
GetClientRect ( hWnd , & rd ) ;
width = rd . right - rd . left ;
height = rd . bottom - rd . top ;
rd . left = pt . x ;
rd . top = pt . y ;
if ( ! nooverlay & & ( ! width | | ! height ) ) {
/*window is minimized*/
ddrval = g_lpddsOverlay - > lpVtbl - > UpdateOverlay ( g_lpddsOverlay , NULL , g_lpddsPrimary , NULL , DDOVER_HIDE , NULL ) ;
return 0 ;
}
if ( vo_keepaspect ) {
int tmpheight = ( ( float ) width / window_aspect ) ;
tmpheight + = tmpheight % 2 ;
if ( tmpheight > height ) {
width = ( ( float ) height * window_aspect ) ;
width + = width % 2 ;
}
else height = tmpheight ;
}
2004-05-18 17:51:25 +00:00
while ( ShowCursor ( TRUE ) < = 0 ) { }
2004-05-01 20:21:03 +00:00
}
rd . right = rd . left + width ;
rd . bottom = rd . top + height ;
2004-02-29 20:33:07 +00:00
2002-12-30 23:14:31 +00:00
/*ok, let's workaround some overlay limitations*/
if ( ! nooverlay )
{
uint32_t uStretchFactor1000 ; //minimum stretch
uint32_t xstretch1000 , ystretch1000 ;
/*get driver capabilities*/
ZeroMemory ( & capsDrv , sizeof ( capsDrv ) ) ;
capsDrv . dwSize = sizeof ( capsDrv ) ;
if ( g_lpdd - > lpVtbl - > GetCaps ( g_lpdd , & capsDrv , NULL ) ! = DD_OK ) return 1 ;
2004-05-18 17:51:25 +00:00
/*get minimum stretch, depends on display adaptor and mode (refresh rate!) */
uStretchFactor1000 = capsDrv . dwMinOverlayStretch > 1000 ? capsDrv . dwMinOverlayStretch : 1000 ;
rd . right = ( ( width + rd . left ) * uStretchFactor1000 + 999 ) / 1000 ;
rd . bottom = ( height + rd . top ) * uStretchFactor1000 / 1000 ;
/*calculate xstretch1000 and ystretch1000*/
xstretch1000 = ( ( rd . right - rd . left ) * 1000 ) / image_width ;
ystretch1000 = ( ( rd . bottom - rd . top ) * 1000 ) / image_height ;
rs . left = 0 ;
rs . right = image_width ;
rs . top = 0 ;
rs . bottom = image_height ;
if ( rd . left < 0 ) rs . left = ( - rd . left * 1000 ) / xstretch1000 ;
if ( rd . top < 0 ) rs . top = ( - rd . top * 1000 ) / ystretch1000 ;
if ( rd . right > vo_screenwidth ) rs . right = ( ( vo_screenwidth - rd . left ) * 1000 ) / xstretch1000 ;
if ( rd . bottom > vo_screenheight ) rs . bottom = ( ( vo_screenheight - rd . top ) * 1000 ) / ystretch1000 ;
2002-12-30 23:14:31 +00:00
/*do not allow to zoom or shrink if hardware isn't able to do so*/
if ( ( width < image_width ) & & ! ( capsDrv . dwFXCaps & DDFXCAPS_OVERLAYSHRINKX ) )
{
if ( capsDrv . dwFXCaps & DDFXCAPS_OVERLAYSHRINKXN ) mp_msg ( MSGT_VO , MSGL_ERR , " <vo_directx><ERROR>can only shrinkN \n " ) ;
else mp_msg ( MSGT_VO , MSGL_ERR , " <vo_directx><ERROR>can't shrink x \n " ) ;
2004-05-01 20:21:03 +00:00
rd . right = rd . left + image_width ;
2002-12-30 23:14:31 +00:00
}
else if ( ( width > image_width ) & & ! ( capsDrv . dwFXCaps & DDFXCAPS_OVERLAYSTRETCHX ) )
2002-09-28 19:17:34 +00:00
{
2002-12-30 23:14:31 +00:00
if ( capsDrv . dwFXCaps & DDFXCAPS_OVERLAYSTRETCHXN ) mp_msg ( MSGT_VO , MSGL_ERR , " <vo_directx><ERROR>can only stretchN \n " ) ;
else mp_msg ( MSGT_VO , MSGL_ERR , " <vo_directx><ERROR>can't stretch x \n " ) ;
2004-05-01 20:21:03 +00:00
rd . right = rd . left + image_width ;
2002-09-28 19:17:34 +00:00
}
2002-12-30 23:14:31 +00:00
if ( ( height < image_height ) & & ! ( capsDrv . dwFXCaps & DDFXCAPS_OVERLAYSHRINKY ) )
2002-09-28 19:17:34 +00:00
{
2002-12-30 23:14:31 +00:00
if ( capsDrv . dwFXCaps & DDFXCAPS_OVERLAYSHRINKYN ) mp_msg ( MSGT_VO , MSGL_ERR , " <vo_directx><ERROR>can only shrinkN \n " ) ;
else mp_msg ( MSGT_VO , MSGL_ERR , " <vo_directx><ERROR>can't shrink y \n " ) ;
2004-05-01 20:21:03 +00:00
rd . bottom = rd . top + image_height ;
2002-09-28 19:17:34 +00:00
}
2002-12-30 23:14:31 +00:00
else if ( ( height > image_height ) & & ! ( capsDrv . dwFXCaps & DDFXCAPS_OVERLAYSTRETCHY ) )
{
if ( capsDrv . dwFXCaps & DDFXCAPS_OVERLAYSTRETCHYN ) mp_msg ( MSGT_VO , MSGL_ERR , " <vo_directx><ERROR>can only stretchN \n " ) ;
else mp_msg ( MSGT_VO , MSGL_ERR , " <vo_directx><ERROR>can't stretch y \n " ) ;
2004-05-01 20:21:03 +00:00
rd . bottom = rd . top + image_height ;
2004-05-18 17:51:25 +00:00
}
2002-12-30 23:14:31 +00:00
/*the last thing to check are alignment restrictions
these expressions ( x & - y ) just do alignment by dropping low order bits . . .
so to round up , we add first , then truncate */
2004-05-01 20:21:03 +00:00
if ( ( capsDrv . dwCaps & DDCAPS_ALIGNBOUNDARYSRC ) & & capsDrv . dwAlignBoundarySrc )
rs . left = ( rs . left + capsDrv . dwAlignBoundarySrc / 2 ) & - ( signed ) ( capsDrv . dwAlignBoundarySrc ) ;
if ( ( capsDrv . dwCaps & DDCAPS_ALIGNSIZESRC ) & & capsDrv . dwAlignSizeSrc )
rs . right = rs . left + ( ( rs . right - rs . left + capsDrv . dwAlignSizeSrc / 2 ) & - ( signed ) ( capsDrv . dwAlignSizeSrc ) ) ;
if ( ( capsDrv . dwCaps & DDCAPS_ALIGNBOUNDARYDEST ) & & capsDrv . dwAlignBoundaryDest )
rd . left = ( rd . left + capsDrv . dwAlignBoundaryDest / 2 ) & - ( signed ) ( capsDrv . dwAlignBoundaryDest ) ;
if ( ( capsDrv . dwCaps & DDCAPS_ALIGNSIZEDEST ) & & capsDrv . dwAlignSizeDest )
rd . right = rd . left + ( ( rd . right - rd . left ) & - ( signed ) ( capsDrv . dwAlignSizeDest ) ) ;
2002-12-30 23:14:31 +00:00
/*create an overlay FX structure to specify a destination color key*/
ZeroMemory ( & ovfx , sizeof ( ovfx ) ) ;
ovfx . dwSize = sizeof ( ovfx ) ;
2004-02-29 20:33:07 +00:00
if ( vo_fs | | vidmode )
2002-12-30 23:14:31 +00:00
{
ovfx . dckDestColorkey . dwColorSpaceLowValue = 0 ;
ovfx . dckDestColorkey . dwColorSpaceHighValue = 0 ;
}
else
{
ovfx . dckDestColorkey . dwColorSpaceLowValue = destcolorkey ;
ovfx . dckDestColorkey . dwColorSpaceHighValue = destcolorkey ;
}
// set the flags we'll send to UpdateOverlay //DDOVER_AUTOFLIP|DDOVERFX_MIRRORLEFTRIGHT|DDOVERFX_MIRRORUPDOWN could be usefull?;
dwUpdateFlags = DDOVER_SHOW | DDOVER_DDFX ;
/*if hardware can't do colorkeying set the window on top*/
if ( capsDrv . dwCKeyCaps & DDCKEYCAPS_DESTOVERLAY ) dwUpdateFlags | = DDOVER_KEYDESTOVERRIDE ;
2003-11-30 16:36:10 +00:00
else vo_ontop = 1 ;
2002-09-28 19:17:34 +00:00
}
2004-02-29 20:33:07 +00:00
else
{
2004-08-24 11:02:12 +00:00
g_lpddclipper - > lpVtbl - > SetHWnd ( g_lpddclipper , 0 , ( vo_fs & & ! vidmode ) ? hWndFS : hWnd ) ;
2004-02-29 20:33:07 +00:00
}
if ( ! vidmode & & ! vo_fs ) {
2004-05-01 20:21:03 +00:00
RECT rdw = rd ;
AdjustWindowRect ( & rdw , WS_OVERLAPPEDWINDOW | WS_SIZEBOX , FALSE ) ;
// printf("window: %i %i %ix%i\n",rdw.left,rdw.top,rdw.right - rdw.left,rdw.bottom - rdw.top);
2004-08-22 18:57:45 +00:00
SetWindowPos ( hWnd , ( vo_ontop ) ? HWND_TOPMOST : ( vo_rootwin ? HWND_BOTTOM : HWND_NOTOPMOST ) , rdw . left , rdw . top , rdw . right - rdw . left , rdw . bottom - rdw . top , SWP_NOOWNERZORDER ) ;
2004-02-29 20:33:07 +00:00
}
2004-08-24 11:02:12 +00:00
else SetWindowPos ( vidmode ? hWnd : hWndFS , vo_rootwin ? HWND_BOTTOM : HWND_TOPMOST , 0 , 0 , 0 , 0 , SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER ) ;
2002-12-30 23:14:31 +00:00
2004-05-01 20:21:03 +00:00
/*for nonoverlay mode we are finished, for overlay mode we have to display the overlay first*/
2002-12-30 23:14:31 +00:00
if ( nooverlay ) return 0 ;
2004-05-01 20:21:03 +00:00
/*make sure the overlay is inside the screen*/
if ( rd . left < 0 ) rd . left = 0 ;
if ( rd . right > vo_screenwidth ) rd . right = vo_screenwidth ;
if ( rd . top < 0 ) rd . top = 0 ;
if ( rd . bottom > vo_screenheight ) rd . bottom = vo_screenheight ;
2002-12-30 23:14:31 +00:00
2004-05-01 20:21:03 +00:00
// printf("overlay: %i %i %ix%i\n",rd.left,rd.top,rd.right - rd.left,rd.bottom - rd.top);
2002-10-06 16:56:42 +00:00
ddrval = g_lpddsOverlay - > lpVtbl - > UpdateOverlay ( g_lpddsOverlay , & rs , g_lpddsPrimary , & rd , dwUpdateFlags , & ovfx ) ;
2002-09-28 19:17:34 +00:00
if ( FAILED ( ddrval ) )
{
2002-12-30 23:14:31 +00:00
// one cause might be the driver lied about minimum stretch
2002-09-28 19:17:34 +00:00
// we should try upping the destination size a bit, or
// perhaps shrinking the source size
mp_msg ( MSGT_VO , MSGL_ERR , " <vo_directx><ERROR>UpdateOverlay failed \n " ) ;
mp_msg ( MSGT_VO , MSGL_ERR , " <vo_directx><ERROR>Overlay:x1:%i,y1:%i,x2:%i,y2:%i,w:%i,h:%i \n " , rd . left , rd . top , rd . right , rd . bottom , rd . right - rd . left , rd . bottom - rd . top ) ;
mp_msg ( MSGT_VO , MSGL_ERR , " <vo_directx><ERROR> " ) ;
switch ( ddrval )
{
case DDERR_NOSTRETCHHW :
{ mp_msg ( MSGT_VO , MSGL_ERR , " hardware can't stretch: try to size the window back \n " ) ; break ; }
case DDERR_INVALIDRECT :
{ mp_msg ( MSGT_VO , MSGL_ERR , " invalid rectangle \n " ) ; break ; }
case DDERR_INVALIDPARAMS :
{ mp_msg ( MSGT_VO , MSGL_ERR , " invalid parameters \n " ) ; break ; }
case DDERR_HEIGHTALIGN :
{ mp_msg ( MSGT_VO , MSGL_ERR , " height align \n " ) ; break ; }
case DDERR_XALIGN :
{ mp_msg ( MSGT_VO , MSGL_ERR , " x align \n " ) ; break ; }
case DDERR_UNSUPPORTED :
{ mp_msg ( MSGT_VO , MSGL_ERR , " unsupported \n " ) ; break ; }
case DDERR_INVALIDSURFACETYPE :
{ mp_msg ( MSGT_VO , MSGL_ERR , " invalid surfacetype \n " ) ; break ; }
case DDERR_INVALIDOBJECT :
{ mp_msg ( MSGT_VO , MSGL_ERR , " invalid object \n " ) ; break ; }
case DDERR_SURFACELOST :
{
mp_msg ( MSGT_VO , MSGL_ERR , " surfaces lost \n " ) ;
g_lpddsOverlay - > lpVtbl - > Restore ( g_lpddsOverlay ) ; //restore and try again
g_lpddsPrimary - > lpVtbl - > Restore ( g_lpddsPrimary ) ;
ddrval = g_lpddsOverlay - > lpVtbl - > UpdateOverlay ( g_lpddsOverlay , & rs , g_lpddsPrimary , & rd , dwUpdateFlags , & ovfx ) ;
if ( ddrval ! = DD_OK ) mp_msg ( MSGT_VO , MSGL_FATAL , " <vo_directx><FATAL ERROR>UpdateOverlay failed again \n " ) ;
break ;
}
2004-04-07 22:51:42 +00:00
default :
mp_msg ( MSGT_VO , MSGL_ERR , " 0x%x \n " , ddrval ) ;
2002-09-28 19:17:34 +00:00
}
2002-12-30 23:14:31 +00:00
/*ok we can't do anything about it -> hide overlay*/
2002-09-28 19:17:34 +00:00
if ( ddrval ! = DD_OK )
{
ddrval = g_lpddsOverlay - > lpVtbl - > UpdateOverlay ( g_lpddsOverlay , NULL , g_lpddsPrimary , NULL , DDOVER_HIDE , NULL ) ;
return 1 ;
}
}
return 0 ;
}
//find out supported overlay pixelformats
static uint32_t Directx_CheckOverlayPixelformats ( )
{
DDCAPS capsDrv ;
HRESULT ddrval ;
2004-02-29 20:33:07 +00:00
DDSURFACEDESC2 ddsdOverlay ;
2002-09-28 19:17:34 +00:00
uint32_t i ;
uint32_t formatcount = 0 ;
//get driver caps to determine overlay support
ZeroMemory ( & capsDrv , sizeof ( capsDrv ) ) ;
capsDrv . dwSize = sizeof ( capsDrv ) ;
ddrval = g_lpdd - > lpVtbl - > GetCaps ( g_lpdd , & capsDrv , NULL ) ;
if ( FAILED ( ddrval ) )
{
mp_msg ( MSGT_VO , MSGL_ERR , " <vo_directx><ERROR>failed getting ddrawcaps \n " ) ;
return 1 ;
}
if ( ! ( capsDrv . dwCaps & DDCAPS_OVERLAY ) )
{
mp_msg ( MSGT_VO , MSGL_ERR , " <vo_directx><ERROR>Your card doesn't support overlay \n " ) ;
return 1 ;
}
mp_msg ( MSGT_VO , MSGL_V , " <vo_directx><INFO>testing supported overlay pixelformats \n " ) ;
//it is not possible to query for pixel formats supported by the
//overlay hardware: try out various formats till one works
ZeroMemory ( & ddsdOverlay , sizeof ( ddsdOverlay ) ) ;
ddsdOverlay . dwSize = sizeof ( ddsdOverlay ) ;
ddsdOverlay . ddsCaps . dwCaps = DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY ;
ddsdOverlay . dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT ;
ddsdOverlay . dwWidth = 300 ;
ddsdOverlay . dwHeight = 280 ;
ddsdOverlay . dwBackBufferCount = 0 ;
//try to create an overlay surface using one of the pixel formats in our global list
i = 0 ;
do
{
ddsdOverlay . ddpfPixelFormat = g_ddpf [ i ] . g_ddpfOverlay ;
ddrval = g_lpdd - > lpVtbl - > CreateSurface ( g_lpdd , & ddsdOverlay , & g_lpddsOverlay , NULL ) ;
if ( ddrval = = DD_OK )
{
mp_msg ( MSGT_VO , MSGL_V , " <vo_directx><FORMAT OVERLAY>%i %s supported \n " , i , g_ddpf [ i ] . img_format_name ) ;
g_ddpf [ i ] . drv_caps = VFCAP_CSP_SUPPORTED | VFCAP_OSD | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_HWSCALE_UP ;
formatcount + + ; }
else mp_msg ( MSGT_VO , MSGL_V , " <vo_directx><FORMAT OVERLAY>%i %s not supported \n " , i , g_ddpf [ i ] . img_format_name ) ;
if ( g_lpddsOverlay ! = NULL ) { g_lpddsOverlay - > lpVtbl - > Release ( g_lpddsOverlay ) ; g_lpddsOverlay = NULL ; }
} while ( + + i < NUM_FORMATS ) ;
mp_msg ( MSGT_VO , MSGL_V , " <vo_directx><INFO>Your card supports %i of %i overlayformats \n " , formatcount , NUM_FORMATS ) ;
if ( formatcount = = 0 )
{
mp_msg ( MSGT_VO , MSGL_V , " <vo_directx><WARN>Your card supports overlay, but we couldn't create one \n " ) ;
mp_msg ( MSGT_VO , MSGL_V , " <vo_directx><INFO>This can have the following reasons: \n " ) ;
mp_msg ( MSGT_VO , MSGL_V , " <vo_directx><INFO>- you are already using an overlay with another app \n " ) ;
mp_msg ( MSGT_VO , MSGL_V , " <vo_directx><INFO>- you don't have enough videomemory \n " ) ;
mp_msg ( MSGT_VO , MSGL_V , " <vo_directx><INFO>- vo_directx doesn't support the cards overlay pixelformat \n " ) ;
return 1 ;
}
if ( capsDrv . dwFXCaps & DDFXCAPS_OVERLAYMIRRORLEFTRIGHT ) mp_msg ( MSGT_VO , MSGL_V , " <vo_directx><INFO>can mirror left right \n " ) ; //I don't have hardware which
if ( capsDrv . dwFXCaps & DDFXCAPS_OVERLAYMIRRORUPDOWN ) mp_msg ( MSGT_VO , MSGL_V , " <vo_directx><INFO>can mirror up down \n " ) ; //supports those send me one and I'll implement ;)
return 0 ;
}
//find out the Pixelformat of the Primary Surface
static uint32_t Directx_CheckPrimaryPixelformat ( )
{
uint32_t i = 0 ;
uint32_t formatcount = 0 ;
DDPIXELFORMAT ddpf ;
2004-02-29 20:33:07 +00:00
DDSURFACEDESC2 ddsd ;
2002-10-06 16:56:42 +00:00
HDC hdc ;
HRESULT hres ;
2002-12-30 23:14:31 +00:00
COLORREF rgbT = RGB ( 0 , 0 , 0 ) ;
2002-09-28 19:17:34 +00:00
mp_msg ( MSGT_VO , MSGL_V , " <vo_directx><INFO>checking primary surface \n " ) ;
memset ( & ddpf , 0 , sizeof ( DDPIXELFORMAT ) ) ;
ddpf . dwSize = sizeof ( DDPIXELFORMAT ) ;
//we have to create a primary surface first
if ( Directx_CreatePrimarySurface ( ) ! = 0 ) return 1 ;
if ( g_lpddsPrimary - > lpVtbl - > GetPixelFormat ( g_lpddsPrimary , & ddpf ) ! = DD_OK )
{
mp_msg ( MSGT_VO , MSGL_FATAL , " <vo_directx><FATAL ERROR>can't get pixelformat \n " ) ;
return 1 ;
}
while ( i < NUM_FORMATS )
{
if ( g_ddpf [ i ] . g_ddpfOverlay . dwRGBBitCount = = ddpf . dwRGBBitCount )
{
if ( g_ddpf [ i ] . g_ddpfOverlay . dwRBitMask = = ddpf . dwRBitMask )
{
mp_msg ( MSGT_VO , MSGL_V , " <vo_directx><FORMAT PRIMARY>%i %s supported \n " , i , g_ddpf [ i ] . img_format_name ) ;
2002-10-11 14:48:07 +00:00
g_ddpf [ i ] . drv_caps = VFCAP_CSP_SUPPORTED | VFCAP_OSD ;
2002-09-28 19:17:34 +00:00
formatcount + + ;
2003-08-17 12:55:21 +00:00
primary_image_format = g_ddpf [ i ] . img_format ;
2002-09-28 19:17:34 +00:00
}
}
i + + ;
}
2002-10-06 16:56:42 +00:00
//get the colorkey for overlay mode
destcolorkey = CLR_INVALID ;
if ( windowcolor ! = CLR_INVALID & & g_lpddsPrimary - > lpVtbl - > GetDC ( g_lpddsPrimary , & hdc ) = = DD_OK )
{
rgbT = GetPixel ( hdc , 0 , 0 ) ;
SetPixel ( hdc , 0 , 0 , windowcolor ) ;
g_lpddsPrimary - > lpVtbl - > ReleaseDC ( g_lpddsPrimary , hdc ) ;
}
// read back the converted color
ddsd . dwSize = sizeof ( ddsd ) ;
while ( ( hres = g_lpddsPrimary - > lpVtbl - > Lock ( g_lpddsPrimary , NULL , & ddsd , 0 , NULL ) ) = = DDERR_WASSTILLDRAWING )
;
if ( hres = = DD_OK )
{
destcolorkey = * ( DWORD * ) ddsd . lpSurface ;
if ( ddsd . ddpfPixelFormat . dwRGBBitCount < 32 )
destcolorkey & = ( 1 < < ddsd . ddpfPixelFormat . dwRGBBitCount ) - 1 ;
g_lpddsPrimary - > lpVtbl - > Unlock ( g_lpddsPrimary , NULL ) ;
}
if ( windowcolor ! = CLR_INVALID & & g_lpddsPrimary - > lpVtbl - > GetDC ( g_lpddsPrimary , & hdc ) = = DD_OK )
{
SetPixel ( hdc , 0 , 0 , rgbT ) ;
g_lpddsPrimary - > lpVtbl - > ReleaseDC ( g_lpddsPrimary , hdc ) ;
}
//release primary
2002-09-28 19:17:34 +00:00
g_lpddsPrimary - > lpVtbl - > Release ( g_lpddsPrimary ) ;
g_lpddsPrimary = NULL ;
if ( formatcount = = 0 )
{
mp_msg ( MSGT_VO , MSGL_FATAL , " <vo_directx><FATAL ERROR>Unknown Pixelformat \n " ) ;
return 1 ;
}
return 0 ;
}
//function handles input
static LRESULT CALLBACK WndProc ( HWND hWnd , UINT message , WPARAM wParam , LPARAM lParam )
{
switch ( message )
{
2004-04-13 13:33:03 +00:00
case WM_MOUSEACTIVATE :
return MA_ACTIVATEANDEAT ;
2004-02-29 20:33:07 +00:00
case WM_NCACTIVATE :
{
if ( vidmode & & adapter_count > 2 ) //only disable if more than one adapter.
return 0 ;
break ;
}
2002-09-28 19:17:34 +00:00
case WM_DESTROY :
{
2002-10-06 16:56:42 +00:00
PostQuitMessage ( 0 ) ;
return 0 ;
2002-09-28 19:17:34 +00:00
}
case WM_CLOSE :
{
2003-11-23 16:59:57 +00:00
mp_input_queue_cmd ( mp_input_parse_cmd ( " quit " ) ) ;
2002-09-28 19:17:34 +00:00
return 0 ;
}
case WM_WINDOWPOSCHANGED :
{
//printf("Windowposchange\n");
2002-10-06 16:56:42 +00:00
if ( g_lpddsBack ! = NULL ) //or it will crash with -vm
{
2002-12-30 23:14:31 +00:00
Directx_ManageDisplay ( 0 , 0 ) ;
2002-10-06 16:56:42 +00:00
}
2002-09-28 19:17:34 +00:00
break ;
}
case WM_SYSCOMMAND :
{
switch ( wParam )
{ //kill screensaver etc.
//note: works only when the window is active
//you can workaround this by disabling the allow screensaver option in
//the link to the app
case SC_SCREENSAVE :
case SC_MONITORPOWER :
mp_msg ( MSGT_VO , MSGL_V , " <vo_directx><INFO>killing screensaver \n " ) ;
return 0 ;
}
}
case WM_KEYDOWN :
{
switch ( wParam )
{
case VK_LEFT :
{ mplayer_put_key ( KEY_LEFT ) ; break ; }
case VK_UP :
{ mplayer_put_key ( KEY_UP ) ; break ; }
case VK_RIGHT :
{ mplayer_put_key ( KEY_RIGHT ) ; break ; }
case VK_DOWN :
{ mplayer_put_key ( KEY_DOWN ) ; break ; }
case VK_TAB :
{ mplayer_put_key ( KEY_TAB ) ; break ; }
2003-11-23 16:59:57 +00:00
case VK_BACK :
{ mplayer_put_key ( KEY_BS ) ; break ; }
2002-09-28 19:17:34 +00:00
case VK_DELETE :
{ mplayer_put_key ( KEY_DELETE ) ; break ; }
case VK_INSERT :
{ mplayer_put_key ( KEY_INSERT ) ; break ; }
case VK_HOME :
{ mplayer_put_key ( KEY_HOME ) ; break ; }
case VK_END :
2003-04-09 18:55:49 +00:00
{ mplayer_put_key ( KEY_END ) ; break ; }
2002-09-28 19:17:34 +00:00
case VK_PRIOR :
{ mplayer_put_key ( KEY_PAGE_UP ) ; break ; }
case VK_NEXT :
{ mplayer_put_key ( KEY_PAGE_DOWN ) ; break ; }
case VK_ESCAPE :
{ mplayer_put_key ( KEY_ESC ) ; break ; }
}
break ;
}
case WM_CHAR :
{
mplayer_put_key ( wParam ) ;
break ;
}
2004-03-13 16:37:12 +00:00
case WM_LBUTTONDOWN :
{
if ( ! vo_nomouse_input )
mplayer_put_key ( MOUSE_BTN0 ) ;
break ;
}
case WM_MBUTTONDOWN :
{
if ( ! vo_nomouse_input )
mplayer_put_key ( MOUSE_BTN1 ) ;
break ;
}
case WM_RBUTTONDOWN :
{
if ( ! vo_nomouse_input )
mplayer_put_key ( MOUSE_BTN2 ) ;
break ;
}
case WM_MOUSEWHEEL :
{
if ( vo_nomouse_input )
break ;
int x = GET_WHEEL_DELTA_WPARAM ( wParam ) ;
if ( x > 0 )
mplayer_put_key ( MOUSE_BTN3 ) ;
else
mplayer_put_key ( MOUSE_BTN4 ) ;
break ;
}
2004-08-26 22:15:26 +00:00
case WM_XBUTTONDOWN :
{
if ( vo_nomouse_input )
break ;
if ( HIWORD ( wParam ) = = 1 )
mplayer_put_key ( MOUSE_BTN5 ) ;
else
mplayer_put_key ( MOUSE_BTN6 ) ;
break ;
}
2002-09-28 19:17:34 +00:00
}
return DefWindowProc ( hWnd , message , wParam , lParam ) ;
}
2004-02-29 20:33:07 +00:00
2002-12-30 23:14:31 +00:00
static uint32_t preinit ( const char * arg )
2002-09-28 19:17:34 +00:00
{
HINSTANCE hInstance = GetModuleHandle ( NULL ) ;
2003-04-20 12:31:23 +00:00
HICON mplayericon = NULL ;
char exedir [ MAX_PATH ] ;
2002-09-28 19:17:34 +00:00
WNDCLASS wc ;
2002-10-09 19:03:17 +00:00
if ( arg )
{
2003-02-23 19:18:28 +00:00
if ( strstr ( arg , " noaccel " ) )
2002-10-09 19:03:17 +00:00
{
mp_msg ( MSGT_VO , MSGL_V , " <vo_directx><INFO>disabled overlay \n " ) ;
nooverlay = 1 ;
}
}
2004-02-29 20:33:07 +00:00
/*load icon from the main app*/
2003-04-20 12:31:23 +00:00
if ( GetModuleFileName ( NULL , exedir , MAX_PATH ) )
{
2004-02-29 20:33:07 +00:00
mplayericon = ExtractIcon ( hInstance , exedir , 0 ) ;
2003-04-20 12:31:23 +00:00
}
if ( ! mplayericon ) mplayericon = LoadIcon ( NULL , IDI_APPLICATION ) ;
2002-12-30 23:14:31 +00:00
wc . style = CS_HREDRAW | CS_VREDRAW ;
wc . lpfnWndProc = WndProc ;
wc . cbClsExtra = 0 ;
wc . cbWndExtra = 0 ;
wc . hInstance = hInstance ;
wc . hCursor = LoadCursor ( NULL , IDC_ARROW ) ;
2003-04-20 12:31:23 +00:00
wc . hIcon = mplayericon ;
2004-02-29 20:33:07 +00:00
wc . hbrBackground = CreateSolidBrush ( vidmode ? RGB ( 0 , 0 , 0 ) : windowcolor ) ;
2004-07-19 23:11:26 +00:00
wc . lpszClassName = " MPlayer - The Movie Player " ;
2002-12-30 23:14:31 +00:00
wc . lpszMenuName = NULL ;
RegisterClass ( & wc ) ;
2004-02-29 20:33:07 +00:00
hWnd = CreateWindowEx ( vidmode ? WS_EX_TOPMOST : 0 ,
2004-07-19 23:19:50 +00:00
" MPlayer - The Movie Player " , " " , ( vidmode ) ? WS_POPUP : WS_OVERLAPPEDWINDOW | WS_SIZEBOX ,
2004-02-29 20:33:07 +00:00
CW_USEDEFAULT , CW_USEDEFAULT , 100 , 100 , NULL , NULL , hInstance , NULL ) ;
wc . hbrBackground = CreateSolidBrush ( RGB ( 0 , 0 , 0 ) ) ;
wc . lpszClassName = " MPlayer - Fullscreen " ;
RegisterClass ( & wc ) ;
2004-08-24 11:02:12 +00:00
if ( ! vidmode ) hWndFS = CreateWindow ( " MPlayer - Fullscreen " , " MPlayer Fullscreen " , WS_POPUP , 0 , 0 , GetSystemMetrics ( SM_CXSCREEN ) , GetSystemMetrics ( SM_CYSCREEN ) , hWnd , NULL , hInstance , NULL ) ;
2004-02-29 20:33:07 +00:00
mp_msg ( MSGT_VO , MSGL_DBG3 , " <vo_directx><INFO>initial mplayer windows created \n " ) ;
if ( Directx_InitDirectDraw ( ) ! = 0 ) return 1 ; //init DirectDraw
if ( Directx_CheckPrimaryPixelformat ( ) ! = 0 ) return 1 ;
if ( ! nooverlay & & Directx_CheckOverlayPixelformats ( ) = = 0 ) //check for supported hardware
{
mp_msg ( MSGT_VO , MSGL_V , " <vo_directx><INFO>hardware supports overlay \n " ) ;
nooverlay = 0 ;
}
else //if we can't have overlay we create a backpuffer with the same imageformat as the primary surface
{
mp_msg ( MSGT_VO , MSGL_V , " <vo_directx><INFO>using backpuffer \n " ) ;
nooverlay = 1 ;
}
mp_msg ( MSGT_VO , MSGL_DBG3 , " <vo_directx><INFO>preinit succesfully finished \n " ) ;
2002-09-28 19:17:34 +00:00
return 0 ;
}
static uint32_t draw_slice ( uint8_t * src [ ] , int stride [ ] , int w , int h , int x , int y )
{
uint8_t * s ;
uint8_t * d ;
2002-12-18 07:34:32 +00:00
uint32_t i = 0 , uvstride = dstride / 2 ;
2002-09-28 19:17:34 +00:00
// copy Y
d = image + dstride * y + x ;
s = src [ 0 ] ;
for ( i = 0 ; i < h ; i + + ) {
memcpy ( d , s , w ) ;
s + = stride [ 0 ] ;
2002-12-18 07:34:32 +00:00
d + = dstride ;
2002-09-28 19:17:34 +00:00
}
w / = 2 ; h / = 2 ; x / = 2 ; y / = 2 ;
// copy U
2002-12-18 07:34:32 +00:00
d = image + dstride * image_height + uvstride * y + x ;
2002-12-30 23:14:31 +00:00
if ( image_format = = IMGFMT_YV12 ) s = src [ 2 ] ;
2002-09-28 19:17:34 +00:00
else s = src [ 1 ] ;
for ( i = 0 ; i < h ; i + + ) {
memcpy ( d , s , w ) ;
s + = stride [ 1 ] ;
2002-12-18 07:34:32 +00:00
d + = uvstride ;
2002-09-28 19:17:34 +00:00
}
// copy V
2002-12-18 07:34:32 +00:00
d = image + dstride * image_height + uvstride * ( image_height / 2 ) + uvstride * y + x ;
2002-12-30 23:14:31 +00:00
if ( image_format = = IMGFMT_YV12 ) s = src [ 1 ] ;
2002-09-28 19:17:34 +00:00
else s = src [ 2 ] ;
for ( i = 0 ; i < h ; i + + ) {
memcpy ( d , s , w ) ;
s + = stride [ 2 ] ;
2002-12-18 07:34:32 +00:00
d + = uvstride ;
2002-09-28 19:17:34 +00:00
}
return 0 ;
}
static void flip_page ( void )
{
HRESULT dxresult ;
2002-12-21 23:49:33 +00:00
g_lpddsBack - > lpVtbl - > Unlock ( g_lpddsBack , NULL ) ;
2002-09-28 19:17:34 +00:00
if ( vo_doublebuffering )
{
// flip to the next image in the sequence
dxresult = g_lpddsOverlay - > lpVtbl - > Flip ( g_lpddsOverlay , NULL , DDFLIP_WAIT ) ;
if ( dxresult = = DDERR_SURFACELOST )
{
mp_msg ( MSGT_VO , MSGL_ERR , " <vo_directx><ERROR><vo_directx><INFO>Restoring Surface \n " ) ;
g_lpddsBack - > lpVtbl - > Restore ( g_lpddsBack ) ;
dxresult = g_lpddsOverlay - > lpVtbl - > Flip ( g_lpddsOverlay , NULL , DDFLIP_WAIT ) ;
}
if ( dxresult ! = DD_OK ) mp_msg ( MSGT_VO , MSGL_ERR , " <vo_directx><ERROR>can't flip page \n " ) ;
}
2002-12-19 12:01:50 +00:00
if ( nooverlay )
2002-09-28 19:17:34 +00:00
{
DDBLTFX ddbltfx ;
// ask for the "NOTEARING" option
memset ( & ddbltfx , 0 , sizeof ( DDBLTFX ) ) ;
ddbltfx . dwSize = sizeof ( DDBLTFX ) ;
ddbltfx . dwDDFX = DDBLTFX_NOTEARING ;
g_lpddsPrimary - > lpVtbl - > Blt ( g_lpddsPrimary , & rd , g_lpddsBack , NULL , DDBLT_WAIT , & ddbltfx ) ;
}
2002-12-19 12:01:50 +00:00
g_lpddsBack - > lpVtbl - > Lock ( g_lpddsBack , NULL , & ddsdsf , DDLOCK_NOSYSLOCK | DDLOCK_WAIT , NULL ) ;
2003-10-09 17:28:16 +00:00
if ( vo_directrendering & & ( dstride ! = ddsdsf . lPitch ) ) {
mp_msg ( MSGT_VO , MSGL_WARN , " <vo_directx><WARN>stride changed !!!! disabling direct rendering \n " ) ;
vo_directrendering = 0 ;
}
2002-12-19 12:01:50 +00:00
dstride = ddsdsf . lPitch ;
image = ddsdsf . lpSurface ;
2002-09-28 19:17:34 +00:00
}
static uint32_t draw_frame ( uint8_t * src [ ] )
{
memcpy ( image , * src , dstride * image_height ) ;
return 0 ;
}
static uint32_t get_image ( mp_image_t * mpi )
{
if ( mpi - > flags & MP_IMGFLAG_READABLE ) { mp_msg ( MSGT_VO , MSGL_V , " <vo_directx><ERROR>slow video ram \n " ) ; return VO_FALSE ; }
if ( mpi - > type = = MP_IMGTYPE_STATIC ) { mp_msg ( MSGT_VO , MSGL_V , " <vo_directx><ERROR>not static \n " ) ; return VO_FALSE ; }
if ( ( mpi - > width = = dstride ) | | ( mpi - > flags & ( MP_IMGFLAG_ACCEPT_STRIDE | MP_IMGFLAG_ACCEPT_WIDTH ) ) )
{
2002-12-30 23:14:31 +00:00
if ( mpi - > flags & MP_IMGFLAG_PLANAR )
2002-09-28 19:17:34 +00:00
{
2002-12-30 23:14:31 +00:00
if ( image_format = = IMGFMT_YV12 )
2002-09-28 19:17:34 +00:00
{
mpi - > planes [ 2 ] = image + dstride * image_height ;
mpi - > planes [ 1 ] = image + dstride * image_height + dstride * image_height / 4 ;
2002-12-30 23:14:31 +00:00
mpi - > stride [ 1 ] = mpi - > stride [ 2 ] = dstride / 2 ;
2002-09-28 19:17:34 +00:00
}
2002-12-30 23:14:31 +00:00
else if ( image_format = = IMGFMT_IYUV | | image_format = = IMGFMT_I420 )
2002-09-28 19:17:34 +00:00
{
mpi - > planes [ 1 ] = image + dstride * image_height ;
mpi - > planes [ 2 ] = image + dstride * image_height + dstride * image_height / 4 ;
2002-12-30 23:14:31 +00:00
mpi - > stride [ 1 ] = mpi - > stride [ 2 ] = dstride / 2 ;
}
else if ( image_format = = IMGFMT_YVU9 )
{
mpi - > planes [ 2 ] = image + dstride * image_height ;
mpi - > planes [ 1 ] = image + dstride * image_height + dstride * image_height / 16 ;
mpi - > stride [ 1 ] = mpi - > stride [ 2 ] = dstride / 4 ;
2002-09-28 19:17:34 +00:00
}
}
2002-12-30 23:14:31 +00:00
mpi - > planes [ 0 ] = image ;
mpi - > stride [ 0 ] = dstride ;
mpi - > width = image_width ;
mpi - > height = image_height ;
2002-09-28 19:17:34 +00:00
mpi - > flags | = MP_IMGFLAG_DIRECT ;
mp_msg ( MSGT_VO , MSGL_DBG3 , " <vo_directx><INFO>Direct Rendering ENABLED \n " ) ;
return VO_TRUE ;
}
return VO_FALSE ;
}
static uint32_t put_image ( mp_image_t * mpi ) {
uint32_t i = 0 ;
uint8_t * d ;
uint8_t * s ;
uint32_t x = mpi - > x ;
uint32_t y = mpi - > y ;
uint32_t w = mpi - > w ;
uint32_t h = mpi - > h ;
2002-12-30 23:14:31 +00:00
if ( ( mpi - > flags & MP_IMGFLAG_DIRECT ) | | ( mpi - > flags & MP_IMGFLAG_DRAW_CALLBACK ) )
2002-09-28 19:17:34 +00:00
{
mp_msg ( MSGT_VO , MSGL_DBG3 , " <vo_directx><INFO>put_image: nothing to do: drawslices \n " ) ;
return VO_TRUE ;
}
if ( mpi - > flags & MP_IMGFLAG_PLANAR )
{
2002-12-30 23:14:31 +00:00
if ( image_format ! = IMGFMT_YVU9 ) draw_slice ( mpi - > planes , mpi - > stride , mpi - > w , mpi - > h , 0 , 0 ) ;
else
2002-09-28 19:17:34 +00:00
{
// copy Y
d = image + dstride * y + x ;
s = mpi - > planes [ 0 ] ;
for ( i = 0 ; i < h ; i + + ) {
memcpy ( d , s , w ) ;
s + = mpi - > stride [ 0 ] ;
d + = dstride ;
}
2002-12-21 23:49:33 +00:00
w / = 4 ; h / = 4 ; x / = 4 ; y / = 4 ;
2002-09-28 19:17:34 +00:00
// copy V
2002-12-21 23:49:33 +00:00
d = image + dstride * image_height + dstride * y / 4 + x ;
2002-12-30 23:14:31 +00:00
s = mpi - > planes [ 2 ] ;
2002-09-28 19:17:34 +00:00
for ( i = 0 ; i < h ; i + + ) {
memcpy ( d , s , w ) ;
s + = mpi - > stride [ 1 ] ;
2002-12-21 23:49:33 +00:00
d + = dstride / 4 ;
2002-09-28 19:17:34 +00:00
}
// copy U
2002-12-21 23:49:33 +00:00
d = image + dstride * image_height + dstride * image_height / 16 + dstride / 4 * y + x ;
2002-12-30 23:14:31 +00:00
s = mpi - > planes [ 1 ] ;
2002-09-28 19:17:34 +00:00
for ( i = 0 ; i < h ; i + + ) {
memcpy ( d , s , w ) ;
s + = mpi - > stride [ 2 ] ;
2002-12-21 23:49:33 +00:00
d + = dstride / 4 ;
2002-09-28 19:17:34 +00:00
}
}
}
else //packed
{
memcpy ( image , mpi - > planes [ 0 ] , image_height * dstride ) ;
}
return VO_TRUE ;
}
static uint32_t
config ( uint32_t width , uint32_t height , uint32_t d_width , uint32_t d_height , uint32_t options , char * title , uint32_t format )
{
2004-09-22 16:26:53 +00:00
RECT rd ;
2004-02-29 20:33:07 +00:00
vo_screenwidth = GetSystemMetrics ( SM_CXSCREEN ) ;
vo_screenheight = GetSystemMetrics ( SM_CYSCREEN ) ;
vo_fs = options & 0x01 ;
2002-09-28 19:17:34 +00:00
image_format = format ;
image_width = width ;
image_height = height ;
2002-12-21 23:49:33 +00:00
d_image_width = d_width ;
d_image_height = d_height ;
2004-09-22 16:26:53 +00:00
if ( format ! = primary_image_format ) nooverlay = 0 ;
2002-12-21 23:49:33 +00:00
aspect_save_orig ( image_width , image_height ) ;
aspect_save_prescale ( d_image_width , d_image_height ) ;
2004-02-29 20:33:07 +00:00
if ( vidmode ) {
vo_screenwidth = vm_width ;
vo_screenheight = vm_height ;
}
aspect_save_screenres ( vo_screenwidth , vo_screenheight ) ;
aspect ( & d_image_width , & d_image_height , A_NOZOOM ) ;
2004-05-01 20:21:03 +00:00
window_aspect = ( float ) d_image_width / ( float ) d_image_height ;
2004-02-29 20:33:07 +00:00
vo_dx = 0 ;
vo_dy = 0 ;
if ( ! vidmode ) {
if ( vo_geometry ) {
vo_dx = ( vo_screenwidth - d_image_width ) / 2 ; vo_dy = ( vo_screenheight - d_image_height ) / 2 ;
geometry ( & vo_dx , & vo_dy , & d_image_width , & d_image_height , vo_screenwidth , vo_screenheight ) ;
}
else {
GetWindowRect ( hWnd , & rd ) ;
vo_dx = rd . left ;
vo_dy = rd . top ;
}
rd . left = vo_dx ;
rd . top = vo_dy ;
rd . right = rd . left + d_image_width ;
rd . bottom = rd . top + d_image_height ;
2004-05-18 17:51:25 +00:00
AdjustWindowRect ( & rd , WS_OVERLAPPEDWINDOW | WS_SIZEBOX , FALSE ) ;
SetWindowPos ( hWnd , NULL , vo_dx , vo_dy , rd . right - rd . left , rd . bottom - rd . top , SWP_SHOWWINDOW | SWP_NOOWNERZORDER ) ;
2004-02-29 20:33:07 +00:00
}
else ShowWindow ( hWnd , SW_SHOW ) ;
if ( vo_fs & & ! vidmode ) ShowWindow ( hWndFS , SW_SHOW ) ;
SetWindowText ( hWnd , title ) ;
2003-09-21 10:31:22 +00:00
2004-02-29 20:33:07 +00:00
if ( vidmode ) vo_fs = 0 ;
2002-12-30 23:14:31 +00:00
/*release all surfaces*/
2002-10-09 19:03:17 +00:00
if ( g_lpddsBack ! = NULL ) g_lpddsBack - > lpVtbl - > Release ( g_lpddsBack ) ;
g_lpddsBack = NULL ;
if ( vo_doublebuffering )
{
if ( g_lpddsOverlay ! = NULL ) g_lpddsOverlay - > lpVtbl - > Release ( g_lpddsOverlay ) ;
}
g_lpddsOverlay = NULL ;
if ( g_lpddsPrimary ! = NULL ) g_lpddsPrimary - > lpVtbl - > Release ( g_lpddsPrimary ) ;
g_lpddsPrimary = NULL ;
mp_msg ( MSGT_VO , MSGL_DBG3 , " <vo_directx><INFO>overlay surfaces released \n " ) ;
2004-02-29 20:33:07 +00:00
2002-12-30 23:14:31 +00:00
/*create the surfaces*/
if ( Directx_CreatePrimarySurface ( ) ) return 1 ;
if ( ! nooverlay & & Directx_CreateOverlay ( image_format ) )
{
2003-08-17 12:55:21 +00:00
if ( format = = primary_image_format ) nooverlay = 1 ; /*overlay creation failed*/
else {
mp_msg ( MSGT_VO , MSGL_FATAL , " <vo_directx><FATAL ERROR>can't use overlay mode: please use -vo directx:noaccel \n " ) ;
return 1 ;
}
2002-12-30 23:14:31 +00:00
}
if ( nooverlay )
{
if ( Directx_CreateBackpuffer ( ) )
{
mp_msg ( MSGT_VO , MSGL_FATAL , " <vo_directx><FATAL ERROR>can't get the driver to work on your system :( \n " ) ;
return 1 ;
}
mp_msg ( MSGT_VO , MSGL_V , " <vo_directx><INFO>back surface created \n " ) ;
vo_doublebuffering = 0 ;
/*create clipper for nonoverlay mode*/
if ( g_lpddclipper ) g_lpddclipper - > lpVtbl - > Release ( g_lpddclipper ) ;
g_lpddclipper = NULL ;
if ( g_lpdd - > lpVtbl - > CreateClipper ( g_lpdd , 0 , & g_lpddclipper , NULL ) ! = DD_OK ) { mp_msg ( MSGT_VO , MSGL_FATAL , " <vo_directx><FATAL ERROR>can't create clipper \n " ) ; return 1 ; }
if ( g_lpddclipper - > lpVtbl - > SetHWnd ( g_lpddclipper , 0 , hWnd ) ! = DD_OK ) { mp_msg ( MSGT_VO , MSGL_FATAL , " <vo_directx><FATAL ERROR>can't associate clipper with window \n " ) ; return 1 ; }
if ( g_lpddsPrimary - > lpVtbl - > SetClipper ( g_lpddsPrimary , g_lpddclipper ) ! = DD_OK ) { mp_msg ( MSGT_VO , MSGL_FATAL , " <vo_directx><FATAL ERROR>can't associate primary surface with clipper \n " ) ; return 1 ; }
mp_msg ( MSGT_VO , MSGL_DBG3 , " <vo_directx><INFO>clipper succesfully created \n " ) ;
2004-10-22 13:37:43 +00:00
} else {
if ( DD_OK ! = g_lpddsOverlay - > lpVtbl - > QueryInterface ( g_lpddsOverlay , & IID_IDirectDrawColorControl , ( void * * ) & g_cc ) )
mp_msg ( MSGT_VO , MSGL_V , " <vo_directx><WARN>unable to get DirectDraw ColorControl interface \n " ) ;
2002-12-30 23:14:31 +00:00
}
2004-02-29 20:33:07 +00:00
Directx_ManageDisplay ( ) ;
memset ( & ddsdsf , 0 , sizeof ( DDSURFACEDESC2 ) ) ;
ddsdsf . dwSize = sizeof ( DDSURFACEDESC2 ) ;
2002-09-28 19:17:34 +00:00
g_lpddsBack - > lpVtbl - > Lock ( g_lpddsBack , NULL , & ddsdsf , DDLOCK_NOSYSLOCK | DDLOCK_WAIT , NULL ) ;
dstride = ddsdsf . lPitch ;
image = ddsdsf . lpSurface ;
return 0 ;
}
2004-10-22 13:37:43 +00:00
//function to set color controls
// brightness [0, 10000]
// contrast [0, 20000]
// hue [-180, 180]
// saturation [0, 20000]
static uint32_t color_ctrl_set ( char * what , int value )
{
uint32_t r = VO_NOTIMPL ;
DDCOLORCONTROL dcc ;
//printf("\n*** %s = %d\n", what, value);
if ( ! g_cc ) {
//printf("\n *** could not get color control interface!!!\n");
return VO_NOTIMPL ;
}
ZeroMemory ( & dcc , sizeof ( dcc ) ) ;
dcc . dwSize = sizeof ( dcc ) ;
if ( ! strcmp ( what , " brightness " ) ) {
dcc . dwFlags = DDCOLOR_BRIGHTNESS ;
dcc . lBrightness = ( value + 100 ) * 10000 / 200 ;
r = VO_TRUE ;
} else if ( ! strcmp ( what , " contrast " ) ) {
dcc . dwFlags = DDCOLOR_CONTRAST ;
dcc . lContrast = ( value + 100 ) * 20000 / 200 ;
r = VO_TRUE ;
} else if ( ! strcmp ( what , " hue " ) ) {
dcc . dwFlags = DDCOLOR_HUE ;
dcc . lHue = value * 180 / 100 ;
r = VO_TRUE ;
} else if ( ! strcmp ( what , " saturation " ) ) {
dcc . dwFlags = DDCOLOR_SATURATION ;
dcc . lSaturation = ( value + 100 ) * 20000 / 200 ;
r = VO_TRUE ;
}
if ( r = = VO_TRUE ) {
g_cc - > lpVtbl - > SetColorControls ( g_cc , & dcc ) ;
}
return r ;
}
//analoguous to color_ctrl_set
static uint32_t color_ctrl_get ( char * what , int * value )
{
uint32_t r = VO_NOTIMPL ;
DDCOLORCONTROL dcc ;
if ( ! g_cc ) {
//printf("\n *** could not get color control interface!!!\n");
return VO_NOTIMPL ;
}
ZeroMemory ( & dcc , sizeof ( dcc ) ) ;
dcc . dwSize = sizeof ( dcc ) ;
if ( g_cc - > lpVtbl - > GetColorControls ( g_cc , & dcc ) ! = DD_OK ) {
return r ;
}
if ( ! strcmp ( what , " brightness " ) & & ( dcc . dwFlags & DDCOLOR_BRIGHTNESS ) ) {
* value = dcc . lBrightness * 200 / 10000 - 100 ;
r = VO_TRUE ;
} else if ( ! strcmp ( what , " contrast " ) & & ( dcc . dwFlags & DDCOLOR_CONTRAST ) ) {
* value = dcc . lContrast * 200 / 20000 - 100 ;
r = VO_TRUE ;
} else if ( ! strcmp ( what , " hue " ) & & ( dcc . dwFlags & DDCOLOR_HUE ) ) {
* value = dcc . lHue * 100 / 180 ;
r = VO_TRUE ;
} else if ( ! strcmp ( what , " saturation " ) & & ( dcc . dwFlags & DDCOLOR_SATURATION ) ) {
* value = dcc . lSaturation * 200 / 20000 - 100 ;
r = VO_TRUE ;
}
// printf("\n*** %s = %d\n", what, *value);
return r ;
}
2002-09-28 19:17:34 +00:00
static uint32_t control ( uint32_t request , void * data , . . . )
{
switch ( request ) {
case VOCTRL_GET_IMAGE :
return get_image ( data ) ;
case VOCTRL_QUERY_FORMAT :
return query_format ( * ( ( uint32_t * ) data ) ) ;
case VOCTRL_DRAW_IMAGE :
return put_image ( data ) ;
2003-11-30 16:36:10 +00:00
case VOCTRL_ONTOP :
2004-02-29 20:33:07 +00:00
if ( vidmode )
2003-11-30 16:36:10 +00:00
{
mp_msg ( MSGT_VO , MSGL_ERR , " <vo_directx><ERROR>ontop has no meaning in exclusive mode \n " ) ;
}
else
{
if ( vo_ontop ) vo_ontop = 0 ;
else vo_ontop = 1 ;
2004-02-29 20:33:07 +00:00
Directx_ManageDisplay ( ) ;
2003-11-30 16:36:10 +00:00
}
return VO_TRUE ;
2004-08-22 19:01:56 +00:00
case VOCTRL_ROOTWIN :
if ( vidmode )
{
mp_msg ( MSGT_VO , MSGL_ERR , " <vo_directx><ERROR>rootwin has no meaning in exclusive mode \n " ) ;
}
else
{
if ( vo_rootwin ) vo_rootwin = 0 ;
else vo_rootwin = 1 ;
Directx_ManageDisplay ( ) ;
}
return VO_TRUE ;
2002-09-28 19:17:34 +00:00
case VOCTRL_FULLSCREEN :
{
2004-02-29 20:33:07 +00:00
if ( vidmode )
2002-09-28 19:17:34 +00:00
{
mp_msg ( MSGT_VO , MSGL_ERR , " <vo_directx><ERROR>currently we do not allow to switch from exclusive to windowed mode \n " ) ;
}
else
{
2004-08-22 18:57:45 +00:00
if ( ! vo_fs )
{
vo_fs = 1 ;
ShowWindow ( hWndFS , SW_SHOW ) ;
ShowWindow ( hWnd , SW_HIDE ) ;
}
else
{
vo_fs = 0 ;
ShowWindow ( hWndFS , SW_HIDE ) ;
ShowWindow ( hWnd , SW_SHOW ) ;
}
2004-02-29 20:33:07 +00:00
Directx_ManageDisplay ( ) ;
break ;
2002-09-28 19:17:34 +00:00
}
return VO_TRUE ;
}
2004-10-22 13:37:43 +00:00
case VOCTRL_SET_EQUALIZER : {
va_list ap ;
int value ;
va_start ( ap , data ) ;
value = va_arg ( ap , int ) ;
va_end ( ap ) ;
return color_ctrl_set ( data , value ) ;
}
case VOCTRL_GET_EQUALIZER : {
va_list ap ;
int * value ;
va_start ( ap , data ) ;
value = va_arg ( ap , int * ) ;
va_end ( ap ) ;
return color_ctrl_get ( data , value ) ;
}
2002-09-28 19:17:34 +00:00
} ;
return VO_NOTIMPL ;
}