00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include <errno.h>
00038 #include <stdlib.h>
00039 #include <string.h>
00040
00041 #include <vlc/vlc.h>
00042 #include <vlc/intf.h>
00043 #include <vlc/vout.h>
00044
00045 #include <windows.h>
00046 #include <ddraw.h>
00047 #include <commctrl.h>
00048
00049 #ifndef UNDER_CE
00050 # include <multimon.h>
00051 #endif
00052 #undef GetSystemMetrics
00053
00054 #ifndef MONITOR_DEFAULTTONEAREST
00055 # define MONITOR_DEFAULTTONEAREST 2
00056 #endif
00057
00058 #include "vout.h"
00059
00060
00061
00062
00063
00064
00065 #include <initguid.h>
00066 DEFINE_GUID( IID_IDirectDraw2, 0xB3A6F3E0,0x2B43,0x11CF,0xA2,0xDE,0x00,0xAA,0x00,0xB9,0x33,0x56 );
00067 DEFINE_GUID( IID_IDirectDrawSurface2, 0x57805885,0x6eec,0x11cf,0x94,0x41,0xa8,0x23,0x03,0xc1,0x0e,0x27 );
00068
00069
00070
00071
00072 static int OpenVideo ( vlc_object_t * );
00073 static void CloseVideo ( vlc_object_t * );
00074
00075 static int Init ( vout_thread_t * );
00076 static void End ( vout_thread_t * );
00077 static int Manage ( vout_thread_t * );
00078 static void Display ( vout_thread_t *, picture_t * );
00079 static void SetPalette( vout_thread_t *, uint16_t *, uint16_t *, uint16_t * );
00080
00081 static int NewPictureVec ( vout_thread_t *, picture_t *, int );
00082 static void FreePictureVec ( vout_thread_t *, picture_t *, int );
00083 static int UpdatePictureStruct( vout_thread_t *, picture_t *, int );
00084
00085 static int DirectXInitDDraw ( vout_thread_t *p_vout );
00086 static void DirectXCloseDDraw ( vout_thread_t *p_vout );
00087 static int DirectXCreateDisplay ( vout_thread_t *p_vout );
00088 static void DirectXCloseDisplay ( vout_thread_t *p_vout );
00089 static int DirectXCreateSurface ( vout_thread_t *p_vout,
00090 LPDIRECTDRAWSURFACE2 *, int, int, int );
00091 static void DirectXCloseSurface ( vout_thread_t *p_vout,
00092 LPDIRECTDRAWSURFACE2 );
00093 static int DirectXCreateClipper ( vout_thread_t *p_vout );
00094 static void DirectXGetDDrawCaps ( vout_thread_t *p_vout );
00095 static int DirectXLockSurface ( vout_thread_t *p_vout, picture_t *p_pic );
00096 static int DirectXUnlockSurface ( vout_thread_t *p_vout, picture_t *p_pic );
00097
00098 static DWORD DirectXFindColorkey( vout_thread_t *p_vout, uint32_t *i_color );
00099
00100 void SwitchWallpaperMode( vout_thread_t *, vlc_bool_t );
00101
00102
00103 static int FindDevicesCallback( vlc_object_t *, char const *,
00104 vlc_value_t, vlc_value_t, void * );
00105 static int WallpaperCallback( vlc_object_t *, char const *,
00106 vlc_value_t, vlc_value_t, void * );
00107
00108
00109
00110
00111 #define HW_YUV_TEXT N_("Use hardware YUV->RGB conversions")
00112 #define HW_YUV_LONGTEXT N_( \
00113 "Try to use hardware acceleration for YUV->RGB conversions. " \
00114 "This option doesn't have any effect when using overlays." )
00115
00116 #define SYSMEM_TEXT N_("Use video buffers in system memory")
00117 #define SYSMEM_LONGTEXT N_( \
00118 "Create video buffers in system memory instead of video memory. This " \
00119 "isn't recommended as usually using video memory allows to benefit from " \
00120 "more hardware acceleration (like rescaling or YUV->RGB conversions). " \
00121 "This option doesn't have any effect when using overlays." )
00122
00123 #define TRIPLEBUF_TEXT N_("Use triple buffering for overlays")
00124 #define TRIPLEBUF_LONGTEXT N_( \
00125 "Try to use triple buffering when using YUV overlays. That results in " \
00126 "much better video quality (no flickering)." )
00127
00128 #define DEVICE_TEXT N_("Name of desired display device")
00129 #define DEVICE_LONGTEXT N_("In a multiple monitor configuration, you can " \
00130 "specify the Windows device name of the display that you want the video " \
00131 "window to open on. For example, \"\\\\.\\DISPLAY1\" or " \
00132 "\"\\\\.\\DISPLAY2\"." )
00133
00134 #define WALLPAPER_TEXT N_("Enable wallpaper mode ")
00135 #define WALLPAPER_LONGTEXT N_( \
00136 "The wallpaper mode allows you to display the video as the desktop " \
00137 "background. Note that this feature only works in overlay mode and " \
00138 "the desktop must not already have a wallpaper." )
00139
00140 static char *ppsz_dev[] = { "" };
00141 static char *ppsz_dev_text[] = { N_("Default") };
00142
00143 vlc_module_begin();
00144 set_shortname( "DirectX" );
00145 set_category( CAT_VIDEO );
00146 set_subcategory( SUBCAT_VIDEO_VOUT );
00147 add_bool( "directx-hw-yuv", 1, NULL, HW_YUV_TEXT, HW_YUV_LONGTEXT,
00148 VLC_TRUE );
00149 add_bool( "directx-use-sysmem", 0, NULL, SYSMEM_TEXT, SYSMEM_LONGTEXT,
00150 VLC_TRUE );
00151 add_bool( "directx-3buffering", 1, NULL, TRIPLEBUF_TEXT,
00152 TRIPLEBUF_LONGTEXT, VLC_TRUE );
00153
00154 add_string( "directx-device", "", NULL, DEVICE_TEXT, DEVICE_LONGTEXT,
00155 VLC_TRUE );
00156 change_string_list( ppsz_dev, ppsz_dev_text, FindDevicesCallback );
00157 change_action_add( FindDevicesCallback, N_("Refresh list") );
00158
00159 add_bool( "directx-wallpaper", 0, NULL, WALLPAPER_TEXT, WALLPAPER_LONGTEXT,
00160 VLC_TRUE );
00161
00162 set_description( _("DirectX video output") );
00163 set_capability( "video output", 100 );
00164 add_shortcut( "directx" );
00165 set_callbacks( OpenVideo, CloseVideo );
00166
00167
00168 linked_with_a_crap_library_which_uses_atexit( );
00169 vlc_module_end();
00170
00171 #if 0
00172
00173
00174 WNDCLASS wndclass;
00175 if( GetClassInfo( GetModuleHandle(NULL), "VLC DirectX", &wndclass ) )
00176 UnregisterClass( "VLC DirectX", GetModuleHandle(NULL) );
00177 #endif
00178
00179
00180
00181
00182
00183
00184 static int OpenVideo( vlc_object_t *p_this )
00185 {
00186 vout_thread_t * p_vout = (vout_thread_t *)p_this;
00187 vlc_value_t val;
00188 HMODULE huser32;
00189
00190
00191 p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
00192 if( p_vout->p_sys == NULL )
00193 {
00194 msg_Err( p_vout, "out of memory" );
00195 return VLC_ENOMEM;
00196 }
00197 memset( p_vout->p_sys, 0, sizeof( vout_sys_t ) );
00198
00199
00200 p_vout->pf_init = Init;
00201 p_vout->pf_end = End;
00202 p_vout->pf_manage = Manage;
00203 p_vout->pf_render = NULL;
00204 p_vout->pf_display = Display;
00205
00206 p_vout->p_sys->p_ddobject = NULL;
00207 p_vout->p_sys->p_display = NULL;
00208 p_vout->p_sys->p_current_surface = NULL;
00209 p_vout->p_sys->p_clipper = NULL;
00210 p_vout->p_sys->hwnd = p_vout->p_sys->hvideownd = NULL;
00211 p_vout->p_sys->hparent = p_vout->p_sys->hfswnd = NULL;
00212 p_vout->p_sys->i_changes = 0;
00213 p_vout->p_sys->b_wallpaper = 0;
00214 vlc_mutex_init( p_vout, &p_vout->p_sys->lock );
00215 SetRectEmpty( &p_vout->p_sys->rect_display );
00216 SetRectEmpty( &p_vout->p_sys->rect_parent );
00217
00218
00219 p_vout->p_sys->hmonitor = NULL;
00220 p_vout->p_sys->p_display_driver = NULL;
00221 p_vout->p_sys->MonitorFromWindow = NULL;
00222 p_vout->p_sys->GetMonitorInfo = NULL;
00223 if( (huser32 = GetModuleHandle( _T("USER32") ) ) )
00224 {
00225 p_vout->p_sys->MonitorFromWindow = (HMONITOR (WINAPI *)( HWND, DWORD ))
00226 GetProcAddress( huser32, _T("MonitorFromWindow") );
00227 p_vout->p_sys->GetMonitorInfo =
00228 #ifndef UNICODE
00229 GetProcAddress( huser32, "GetMonitorInfoA" );
00230 #else
00231 GetProcAddress( huser32, _T("GetMonitorInfoW") );
00232 #endif
00233 }
00234
00235 var_Create( p_vout, "overlay", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
00236 var_Create( p_vout, "directx-use-sysmem", VLC_VAR_BOOL|VLC_VAR_DOINHERIT );
00237 var_Create( p_vout, "directx-hw-yuv", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
00238 var_Create( p_vout, "directx-3buffering", VLC_VAR_BOOL|VLC_VAR_DOINHERIT );
00239 var_Create( p_vout, "directx-device", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
00240 var_Create( p_vout, "video-title", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
00241
00242 p_vout->p_sys->b_cursor_hidden = 0;
00243 p_vout->p_sys->i_lastmoved = mdate();
00244
00245
00246 p_vout->p_sys->i_window_width = p_vout->i_window_width;
00247 p_vout->p_sys->i_window_height = p_vout->i_window_height;
00248
00249
00250
00251
00252
00253
00254
00255
00256 msg_Dbg( p_vout, "creating DirectXEventThread" );
00257 p_vout->p_sys->p_event =
00258 vlc_object_create( p_vout, sizeof(event_thread_t) );
00259 p_vout->p_sys->p_event->p_vout = p_vout;
00260 if( vlc_thread_create( p_vout->p_sys->p_event, "DirectX Events Thread",
00261 E_(DirectXEventThread), 0, 1 ) )
00262 {
00263 msg_Err( p_vout, "cannot create DirectXEventThread" );
00264 vlc_object_destroy( p_vout->p_sys->p_event );
00265 p_vout->p_sys->p_event = NULL;
00266 goto error;
00267 }
00268
00269 if( p_vout->p_sys->p_event->b_error )
00270 {
00271 msg_Err( p_vout, "DirectXEventThread failed" );
00272 goto error;
00273 }
00274
00275 vlc_object_attach( p_vout->p_sys->p_event, p_vout );
00276
00277 msg_Dbg( p_vout, "DirectXEventThread running" );
00278
00279
00280 if( DirectXInitDDraw( p_vout ) )
00281 {
00282 msg_Err( p_vout, "cannot initialize DirectDraw" );
00283 goto error;
00284 }
00285
00286
00287 if( DirectXCreateDisplay( p_vout ) )
00288 {
00289 msg_Err( p_vout, "cannot initialize DirectDraw" );
00290 goto error;
00291 }
00292
00293
00294
00295 var_Get( p_vout, "video-on-top", &val );
00296 var_Set( p_vout, "video-on-top", val );
00297
00298
00299
00300 var_Create( p_vout, "directx-wallpaper", VLC_VAR_BOOL|VLC_VAR_DOINHERIT );
00301 val.psz_string = _("Wallpaper");
00302 var_Change( p_vout, "directx-wallpaper", VLC_VAR_SETTEXT, &val, NULL );
00303 var_AddCallback( p_vout, "directx-wallpaper", WallpaperCallback, NULL );
00304 var_Get( p_vout, "directx-wallpaper", &val );
00305 var_Set( p_vout, "directx-wallpaper", val );
00306
00307 return VLC_SUCCESS;
00308
00309 error:
00310 CloseVideo( VLC_OBJECT(p_vout) );
00311 return VLC_EGENERIC;
00312 }
00313
00314
00315
00316
00317
00318
00319
00320 static int Init( vout_thread_t *p_vout )
00321 {
00322 int i_chroma_backup;
00323 vlc_value_t val;
00324
00325
00326 var_Get( p_vout, "overlay", &val );
00327 p_vout->p_sys->b_using_overlay = val.b_bool;
00328 var_Get( p_vout, "directx-use-sysmem", &val );
00329 p_vout->p_sys->b_use_sysmem = val.b_bool;
00330 var_Get( p_vout, "directx-hw-yuv", &val );
00331 p_vout->p_sys->b_hw_yuv = val.b_bool;
00332 var_Get( p_vout, "directx-3buffering", &val );
00333 p_vout->p_sys->b_3buf_overlay = val.b_bool;
00334
00335
00336
00337
00338 if( !p_vout->p_sys->p_ddobject &&
00339 DirectXInitDDraw( p_vout ) != VLC_SUCCESS )
00340 {
00341 msg_Err( p_vout, "cannot initialize DirectDraw" );
00342 return VLC_EGENERIC;
00343 }
00344
00345
00346 if( !p_vout->p_sys->p_display &&
00347 DirectXCreateDisplay( p_vout ) != VLC_SUCCESS )
00348 {
00349 msg_Err( p_vout, "cannot initialize DirectDraw" );
00350 return VLC_EGENERIC;
00351 }
00352
00353
00354
00355
00356 p_vout->output.i_width = p_vout->render.i_width;
00357 p_vout->output.i_height = p_vout->render.i_height;
00358 p_vout->output.i_aspect = p_vout->render.i_aspect;
00359 p_vout->fmt_out = p_vout->fmt_in;
00360 E_(DirectXUpdateRects)( p_vout, VLC_TRUE );
00361
00362 #define MAX_DIRECTBUFFERS 1
00363
00364
00365
00366
00367
00368 switch( p_vout->render.i_chroma )
00369 {
00370 case VLC_FOURCC('Y','U','Y','2'):
00371 case VLC_FOURCC('Y','U','N','V'):
00372 p_vout->output.i_chroma = VLC_FOURCC('Y','U','Y','2');
00373 break;
00374 case VLC_FOURCC('U','Y','V','Y'):
00375 case VLC_FOURCC('U','Y','N','V'):
00376 case VLC_FOURCC('Y','4','2','2'):
00377 p_vout->output.i_chroma = VLC_FOURCC('U','Y','V','Y');
00378 break;
00379 case VLC_FOURCC('Y','V','Y','U'):
00380 p_vout->output.i_chroma = VLC_FOURCC('Y','V','Y','U');
00381 break;
00382 default:
00383 p_vout->output.i_chroma = VLC_FOURCC('Y','V','1','2');
00384 break;
00385 }
00386
00387 NewPictureVec( p_vout, p_vout->p_picture, MAX_DIRECTBUFFERS );
00388
00389 i_chroma_backup = p_vout->output.i_chroma;
00390
00391 if( !I_OUTPUTPICTURES )
00392 {
00393
00394 if( p_vout->output.i_chroma != VLC_FOURCC('I','4','2','0') )
00395 {
00396 p_vout->output.i_chroma = VLC_FOURCC('Y','V','1','2');
00397 NewPictureVec( p_vout, p_vout->p_picture, MAX_DIRECTBUFFERS );
00398 }
00399 if( !I_OUTPUTPICTURES )
00400 {
00401
00402 p_vout->output.i_chroma = VLC_FOURCC('Y','U','Y','2');
00403 NewPictureVec( p_vout, p_vout->p_picture, MAX_DIRECTBUFFERS );
00404 }
00405 }
00406
00407 if( !I_OUTPUTPICTURES )
00408 {
00409
00410 p_vout->output.i_chroma = i_chroma_backup;
00411 p_vout->p_sys->b_using_overlay = 0;
00412 NewPictureVec( p_vout, p_vout->p_picture, MAX_DIRECTBUFFERS );
00413 }
00414
00415
00416 PostMessage( p_vout->p_sys->hwnd, WM_VLC_CHANGE_TEXT, 0, 0 );
00417
00418 p_vout->fmt_out.i_chroma = p_vout->output.i_chroma;
00419 return VLC_SUCCESS;
00420 }
00421
00422
00423
00424
00425
00426
00427
00428 static void End( vout_thread_t *p_vout )
00429 {
00430 FreePictureVec( p_vout, p_vout->p_picture, I_OUTPUTPICTURES );
00431
00432 DirectXCloseDisplay( p_vout );
00433 DirectXCloseDDraw( p_vout );
00434
00435 return;
00436 }
00437
00438
00439
00440
00441
00442
00443 static void CloseVideo( vlc_object_t *p_this )
00444 {
00445 vout_thread_t * p_vout = (vout_thread_t *)p_this;
00446
00447 msg_Dbg( p_vout, "CloseVideo" );
00448
00449 if( p_vout->p_sys->p_event )
00450 {
00451 vlc_object_detach( p_vout->p_sys->p_event );
00452
00453
00454 p_vout->p_sys->p_event->b_die = VLC_TRUE;
00455
00456
00457
00458 if( p_vout->p_sys->hwnd )
00459 {
00460 PostMessage( p_vout->p_sys->hwnd, WM_NULL, 0, 0);
00461 }
00462
00463 vlc_thread_join( p_vout->p_sys->p_event );
00464 vlc_object_destroy( p_vout->p_sys->p_event );
00465 }
00466
00467 vlc_mutex_destroy( &p_vout->p_sys->lock );
00468
00469
00470 SwitchWallpaperMode( p_vout, VLC_FALSE );
00471
00472 if( p_vout->p_sys )
00473 {
00474 free( p_vout->p_sys );
00475 p_vout->p_sys = NULL;
00476 }
00477 }
00478
00479
00480
00481
00482
00483
00484
00485 static int Manage( vout_thread_t *p_vout )
00486 {
00487 WINDOWPLACEMENT window_placement;
00488
00489
00490
00491 vlc_mutex_lock( &p_vout->p_sys->lock );
00492 if( p_vout->p_sys->hparent && !p_vout->b_fullscreen )
00493 {
00494 RECT rect_parent;
00495 POINT point;
00496
00497 vlc_mutex_unlock( &p_vout->p_sys->lock );
00498
00499 GetClientRect( p_vout->p_sys->hparent, &rect_parent );
00500 point.x = point.y = 0;
00501 ClientToScreen( p_vout->p_sys->hparent, &point );
00502 OffsetRect( &rect_parent, point.x, point.y );
00503
00504 if( !EqualRect( &rect_parent, &p_vout->p_sys->rect_parent ) )
00505 {
00506 p_vout->p_sys->rect_parent = rect_parent;
00507
00508
00509
00510 SetWindowPos( p_vout->p_sys->hwnd, 0, 1, 1,
00511 rect_parent.right - rect_parent.left,
00512 rect_parent.bottom - rect_parent.top, 0 );
00513
00514 SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0,
00515 rect_parent.right - rect_parent.left,
00516 rect_parent.bottom - rect_parent.top, 0 );
00517 }
00518 }
00519 else
00520 {
00521 vlc_mutex_unlock( &p_vout->p_sys->lock );
00522 }
00523
00524
00525
00526
00527 if( p_vout->p_sys->i_changes & DX_POSITION_CHANGE )
00528 {
00529 p_vout->p_sys->i_changes &= ~DX_POSITION_CHANGE;
00530
00531
00532 if( p_vout->p_sys->MonitorFromWindow &&
00533 p_vout->p_sys->hmonitor !=
00534 p_vout->p_sys->MonitorFromWindow( p_vout->p_sys->hwnd,
00535 MONITOR_DEFAULTTONEAREST ) )
00536 {
00537
00538 p_vout->i_changes |= VOUT_PICTURE_BUFFERS_CHANGE;
00539 }
00540 }
00541
00542
00543 if( p_vout->i_changes & VOUT_CROP_CHANGE ||
00544 p_vout->i_changes & VOUT_ASPECT_CHANGE )
00545 {
00546 p_vout->i_changes &= ~VOUT_CROP_CHANGE;
00547 p_vout->i_changes &= ~VOUT_ASPECT_CHANGE;
00548
00549 p_vout->fmt_out.i_x_offset = p_vout->fmt_in.i_x_offset;
00550 p_vout->fmt_out.i_y_offset = p_vout->fmt_in.i_y_offset;
00551 p_vout->fmt_out.i_visible_width = p_vout->fmt_in.i_visible_width;
00552 p_vout->fmt_out.i_visible_height = p_vout->fmt_in.i_visible_height;
00553 p_vout->fmt_out.i_aspect = p_vout->fmt_in.i_aspect;
00554 p_vout->fmt_out.i_sar_num = p_vout->fmt_in.i_sar_num;
00555 p_vout->fmt_out.i_sar_den = p_vout->fmt_in.i_sar_den;
00556 p_vout->output.i_aspect = p_vout->fmt_in.i_aspect;
00557 E_(DirectXUpdateRects)( p_vout, VLC_TRUE );
00558 }
00559
00560
00561
00562
00563
00564
00565 if( p_vout->p_sys->i_changes & DX_WALLPAPER_CHANGE )
00566 {
00567 SwitchWallpaperMode( p_vout, !p_vout->p_sys->b_wallpaper );
00568 p_vout->p_sys->i_changes &= ~DX_WALLPAPER_CHANGE;
00569 E_(DirectXUpdateOverlay)( p_vout );
00570 }
00571
00572
00573
00574
00575 if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE
00576 || p_vout->p_sys->i_changes & VOUT_FULLSCREEN_CHANGE )
00577 {
00578 vlc_value_t val;
00579 HWND hwnd = (p_vout->p_sys->hparent && p_vout->p_sys->hfswnd) ?
00580 p_vout->p_sys->hfswnd : p_vout->p_sys->hwnd;
00581
00582 p_vout->b_fullscreen = ! p_vout->b_fullscreen;
00583
00584
00585 window_placement.length = sizeof(WINDOWPLACEMENT);
00586 GetWindowPlacement( hwnd, &window_placement );
00587 if( p_vout->b_fullscreen )
00588 {
00589
00590 int i_style = WS_CLIPCHILDREN | WS_VISIBLE;
00591 SetWindowLong( hwnd, GWL_STYLE, i_style );
00592
00593 if( p_vout->p_sys->hparent )
00594 {
00595
00596
00597 POINT point = {0,0};
00598 RECT rect;
00599 ClientToScreen( p_vout->p_sys->hwnd, &point );
00600 GetClientRect( p_vout->p_sys->hwnd, &rect );
00601 SetWindowPos( hwnd, 0, point.x, point.y,
00602 rect.right, rect.bottom,
00603 SWP_NOZORDER|SWP_FRAMECHANGED );
00604 GetWindowPlacement( hwnd, &window_placement );
00605 }
00606
00607
00608 window_placement.showCmd = SW_SHOWMAXIMIZED;
00609 SetWindowPlacement( hwnd, &window_placement );
00610 SetWindowPos( hwnd, 0, 0, 0, 0, 0,
00611 SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED);
00612
00613 if( p_vout->p_sys->hparent )
00614 {
00615 RECT rect;
00616 GetClientRect( hwnd, &rect );
00617 SetParent( p_vout->p_sys->hwnd, hwnd );
00618 SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0,
00619 rect.right, rect.bottom,
00620 SWP_NOZORDER|SWP_FRAMECHANGED );
00621 }
00622
00623 SetForegroundWindow( hwnd );
00624 }
00625 else
00626 {
00627
00628 SetWindowLong( hwnd, GWL_STYLE, p_vout->p_sys->i_window_style );
00629
00630
00631 window_placement.showCmd = SW_SHOWNORMAL;
00632 SetWindowPlacement( hwnd, &window_placement );
00633 SetWindowPos( hwnd, 0, 0, 0, 0, 0,
00634 SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED);
00635
00636 if( p_vout->p_sys->hparent )
00637 {
00638 RECT rect;
00639 GetClientRect( p_vout->p_sys->hparent, &rect );
00640 SetParent( p_vout->p_sys->hwnd, p_vout->p_sys->hparent );
00641 SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0,
00642 rect.right, rect.bottom,
00643 SWP_NOZORDER|SWP_FRAMECHANGED );
00644
00645 ShowWindow( hwnd, SW_HIDE );
00646 SetForegroundWindow( p_vout->p_sys->hparent );
00647 }
00648
00649
00650 PostMessage( p_vout->p_sys->hwnd, WM_VLC_SHOW_MOUSE, 0, 0 );
00651 }
00652
00653
00654 val.b_bool = p_vout->b_fullscreen;
00655 var_Set( p_vout, "fullscreen", val );
00656
00657 p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
00658 p_vout->p_sys->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
00659 }
00660
00661
00662
00663
00664 if( p_vout->b_fullscreen && !p_vout->p_sys->b_cursor_hidden &&
00665 (mdate() - p_vout->p_sys->i_lastmoved) > 5000000 )
00666 {
00667 POINT point;
00668 HWND hwnd;
00669
00670
00671 GetCursorPos( &point );
00672 hwnd = WindowFromPoint(point);
00673 if( hwnd == p_vout->p_sys->hwnd || hwnd == p_vout->p_sys->hvideownd )
00674 {
00675 PostMessage( p_vout->p_sys->hwnd, WM_VLC_HIDE_MOUSE, 0, 0 );
00676 }
00677 else
00678 {
00679 p_vout->p_sys->i_lastmoved = mdate();
00680 }
00681 }
00682
00683
00684
00685
00686 if( p_vout->p_sys->b_on_top_change )
00687 {
00688 vlc_value_t val;
00689 HMENU hMenu = GetSystemMenu( p_vout->p_sys->hwnd, FALSE );
00690
00691 var_Get( p_vout, "video-on-top", &val );
00692
00693
00694 if( val.b_bool && !( GetWindowLong( p_vout->p_sys->hwnd, GWL_EXSTYLE )
00695 & WS_EX_TOPMOST ) )
00696 {
00697 CheckMenuItem( hMenu, IDM_TOGGLE_ON_TOP,
00698 MF_BYCOMMAND | MFS_CHECKED );
00699 SetWindowPos( p_vout->p_sys->hwnd, HWND_TOPMOST, 0, 0, 0, 0,
00700 SWP_NOSIZE | SWP_NOMOVE );
00701 }
00702 else
00703
00704 if( !val.b_bool && ( GetWindowLong( p_vout->p_sys->hwnd, GWL_EXSTYLE )
00705 & WS_EX_TOPMOST ) )
00706 {
00707 CheckMenuItem( hMenu, IDM_TOGGLE_ON_TOP,
00708 MF_BYCOMMAND | MFS_UNCHECKED );
00709 SetWindowPos( p_vout->p_sys->hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
00710 SWP_NOSIZE | SWP_NOMOVE );
00711 }
00712
00713 p_vout->p_sys->b_on_top_change = VLC_FALSE;
00714 }
00715
00716
00717 if( p_vout->p_sys->p_event->b_die )
00718 {
00719 return VLC_EGENERIC;
00720 }
00721
00722 return VLC_SUCCESS;
00723 }
00724
00725
00726
00727
00728
00729
00730
00731 static void Display( vout_thread_t *p_vout, picture_t *p_pic )
00732 {
00733 HRESULT dxresult;
00734
00735 if( (p_vout->p_sys->p_display == NULL) )
00736 {
00737 msg_Warn( p_vout, "no display!" );
00738 return;
00739 }
00740
00741
00742
00743 if( IDirectDrawSurface2_IsLost( p_vout->p_sys->p_display )
00744 == DDERR_SURFACELOST )
00745 {
00746 if( IDirectDrawSurface2_Restore( p_vout->p_sys->p_display ) == DD_OK &&
00747 p_vout->p_sys->b_using_overlay )
00748 E_(DirectXUpdateOverlay)( p_vout );
00749 }
00750
00751 if( !p_vout->p_sys->b_using_overlay )
00752 {
00753 DDBLTFX ddbltfx;
00754
00755
00756 memset( &ddbltfx, 0, sizeof(DDBLTFX) );
00757 ddbltfx.dwSize = sizeof(DDBLTFX);
00758 ddbltfx.dwDDFX = DDBLTFX_NOTEARING;
00759
00760
00761 dxresult = IDirectDrawSurface2_Blt( p_vout->p_sys->p_display,
00762 &p_vout->p_sys->rect_dest_clipped,
00763 p_pic->p_sys->p_surface,
00764 &p_vout->p_sys->rect_src_clipped,
00765 DDBLT_ASYNC, &ddbltfx );
00766 if( dxresult != DD_OK )
00767 {
00768 msg_Warn( p_vout, "could not blit surface (error %li)", dxresult );
00769 return;
00770 }
00771
00772 }
00773 else
00774 {
00775
00776 if( p_pic->p_sys->p_front_surface == p_pic->p_sys->p_surface )
00777 {
00778 return;
00779 }
00780
00781 dxresult = IDirectDrawSurface2_Flip( p_pic->p_sys->p_front_surface,
00782 NULL, DDFLIP_WAIT );
00783 if( dxresult != DD_OK )
00784 {
00785 msg_Warn( p_vout, "could not flip overlay (error %li)", dxresult );
00786 }
00787
00788
00789 p_vout->p_sys->p_current_surface = p_pic->p_sys->p_front_surface;
00790
00791
00792 if( DirectXLockSurface( p_vout, p_pic ) )
00793 {
00794
00795 msg_Warn( p_vout, "cannot lock surface" );
00796 return;
00797 }
00798 DirectXUnlockSurface( p_vout, p_pic );
00799 }
00800 }
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810 BOOL WINAPI DirectXEnumCallback( GUID* p_guid, LPTSTR psz_desc,
00811 LPTSTR psz_drivername, VOID* p_context,
00812 HMONITOR hmon )
00813 {
00814 vout_thread_t *p_vout = (vout_thread_t *)p_context;
00815 vlc_value_t device;
00816
00817 msg_Dbg( p_vout, "DirectXEnumCallback: %s, %s", psz_desc, psz_drivername );
00818
00819 if( hmon )
00820 {
00821 var_Get( p_vout, "directx-device", &device );
00822
00823 if( ( !device.psz_string || !*device.psz_string ) &&
00824 hmon == p_vout->p_sys->hmonitor )
00825 {
00826 if( device.psz_string ) free( device.psz_string );
00827 }
00828 else if( strcmp( psz_drivername, device.psz_string ) == 0 )
00829 {
00830 MONITORINFO monitor_info;
00831 monitor_info.cbSize = sizeof( MONITORINFO );
00832
00833 if( p_vout->p_sys->GetMonitorInfo( hmon, &monitor_info ) )
00834 {
00835 RECT rect;
00836
00837
00838 GetWindowRect( p_vout->p_sys->hwnd, &rect );
00839 if( !IntersectRect( &rect, &rect, &monitor_info.rcWork ) )
00840 {
00841 rect.left = monitor_info.rcWork.left;
00842 rect.top = monitor_info.rcWork.top;
00843 msg_Dbg( p_vout, "DirectXEnumCallback: Setting window "
00844 "position to %d,%d", rect.left, rect.top );
00845 SetWindowPos( p_vout->p_sys->hwnd, NULL,
00846 rect.left, rect.top, 0, 0,
00847 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
00848 }
00849 }
00850
00851 p_vout->p_sys->hmonitor = hmon;
00852 if( device.psz_string ) free( device.psz_string );
00853 }
00854 else
00855 {
00856 if( device.psz_string ) free( device.psz_string );
00857 return TRUE;
00858 }
00859
00860 msg_Dbg( p_vout, "selecting %s, %s", psz_desc, psz_drivername );
00861 p_vout->p_sys->p_display_driver = malloc( sizeof(GUID) );
00862 if( p_vout->p_sys->p_display_driver )
00863 memcpy( p_vout->p_sys->p_display_driver, p_guid, sizeof(GUID) );
00864 }
00865
00866 return TRUE;
00867 }
00868
00869
00870
00871
00872
00873
00874 static int DirectXInitDDraw( vout_thread_t *p_vout )
00875 {
00876 HRESULT dxresult;
00877 HRESULT (WINAPI *OurDirectDrawCreate)(GUID *,LPDIRECTDRAW *,IUnknown *);
00878 HRESULT (WINAPI *OurDirectDrawEnumerateEx)( LPDDENUMCALLBACKEXA, LPVOID,
00879 DWORD );
00880 LPDIRECTDRAW p_ddobject;
00881
00882 msg_Dbg( p_vout, "DirectXInitDDraw" );
00883
00884
00885 p_vout->p_sys->hddraw_dll = LoadLibrary(_T("DDRAW.DLL"));
00886 if( p_vout->p_sys->hddraw_dll == NULL )
00887 {
00888 msg_Warn( p_vout, "DirectXInitDDraw failed loading ddraw.dll" );
00889 goto error;
00890 }
00891
00892 OurDirectDrawCreate =
00893 (void *)GetProcAddress( p_vout->p_sys->hddraw_dll,
00894 _T("DirectDrawCreate") );
00895 if( OurDirectDrawCreate == NULL )
00896 {
00897 msg_Err( p_vout, "DirectXInitDDraw failed GetProcAddress" );
00898 goto error;
00899 }
00900
00901 OurDirectDrawEnumerateEx =
00902 (void *)GetProcAddress( p_vout->p_sys->hddraw_dll,
00903 #ifndef UNICODE
00904 "DirectDrawEnumerateExA" );
00905 #else
00906 _T("DirectDrawEnumerateExW") );
00907 #endif
00908
00909 if( OurDirectDrawEnumerateEx && p_vout->p_sys->MonitorFromWindow )
00910 {
00911 vlc_value_t device;
00912
00913 var_Get( p_vout, "directx-device", &device );
00914 if( device.psz_string )
00915 {
00916 msg_Dbg( p_vout, "directx-device: %s", device.psz_string );
00917 free( device.psz_string );
00918 }
00919
00920 p_vout->p_sys->hmonitor =
00921 p_vout->p_sys->MonitorFromWindow( p_vout->p_sys->hwnd,
00922 MONITOR_DEFAULTTONEAREST );
00923
00924
00925 OurDirectDrawEnumerateEx( DirectXEnumCallback, p_vout,
00926 DDENUM_ATTACHEDSECONDARYDEVICES );
00927 }
00928
00929
00930 dxresult = OurDirectDrawCreate( p_vout->p_sys->p_display_driver,
00931 &p_ddobject, NULL );
00932 if( dxresult != DD_OK )
00933 {
00934 msg_Err( p_vout, "DirectXInitDDraw cannot initialize DDraw" );
00935 goto error;
00936 }
00937
00938
00939 dxresult = IDirectDraw_QueryInterface( p_ddobject, &IID_IDirectDraw2,
00940 (LPVOID *)&p_vout->p_sys->p_ddobject );
00941
00942 IDirectDraw_Release( p_ddobject );
00943 if( dxresult != DD_OK )
00944 {
00945 msg_Err( p_vout, "cannot get IDirectDraw2 interface" );
00946 goto error;
00947 }
00948
00949
00950
00951 dxresult = IDirectDraw2_SetCooperativeLevel( p_vout->p_sys->p_ddobject,
00952 NULL, DDSCL_NORMAL );
00953 if( dxresult != DD_OK )
00954 {
00955 msg_Err( p_vout, "cannot set direct draw cooperative level" );
00956 goto error;
00957 }
00958
00959
00960 if( p_vout->p_sys->hmonitor && p_vout->p_sys->GetMonitorInfo )
00961 {
00962 MONITORINFO monitor_info;
00963 monitor_info.cbSize = sizeof( MONITORINFO );
00964 p_vout->p_sys->GetMonitorInfo( p_vout->p_sys->hmonitor,
00965 &monitor_info );
00966 p_vout->p_sys->rect_display = monitor_info.rcMonitor;
00967 }
00968 else
00969 {
00970 p_vout->p_sys->rect_display.left = 0;
00971 p_vout->p_sys->rect_display.top = 0;
00972 p_vout->p_sys->rect_display.right = GetSystemMetrics(SM_CXSCREEN);
00973 p_vout->p_sys->rect_display.bottom = GetSystemMetrics(SM_CYSCREEN);
00974 }
00975
00976 msg_Dbg( p_vout, "screen dimensions (%ix%i,%ix%i)",
00977 p_vout->p_sys->rect_display.left,
00978 p_vout->p_sys->rect_display.top,
00979 p_vout->p_sys->rect_display.right,
00980 p_vout->p_sys->rect_display.bottom );
00981
00982
00983 DirectXGetDDrawCaps( p_vout );
00984
00985 msg_Dbg( p_vout, "End DirectXInitDDraw" );
00986 return VLC_SUCCESS;
00987
00988 error:
00989 if( p_vout->p_sys->p_ddobject )
00990 IDirectDraw2_Release( p_vout->p_sys->p_ddobject );
00991 if( p_vout->p_sys->hddraw_dll )
00992 FreeLibrary( p_vout->p_sys->hddraw_dll );
00993 p_vout->p_sys->hddraw_dll = NULL;
00994 p_vout->p_sys->p_ddobject = NULL;
00995 return VLC_EGENERIC;
00996 }
00997
00998
00999
01000
01001
01002
01003
01004 static int DirectXCreateDisplay( vout_thread_t *p_vout )
01005 {
01006 HRESULT dxresult;
01007 DDSURFACEDESC ddsd;
01008 LPDIRECTDRAWSURFACE p_display;
01009
01010 msg_Dbg( p_vout, "DirectXCreateDisplay" );
01011
01012
01013
01014 memset( &ddsd, 0, sizeof( DDSURFACEDESC ));
01015 ddsd.dwSize = sizeof(DDSURFACEDESC);
01016 ddsd.dwFlags = DDSD_CAPS;
01017 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
01018
01019 dxresult = IDirectDraw2_CreateSurface( p_vout->p_sys->p_ddobject,
01020 &ddsd, &p_display, NULL );
01021 if( dxresult != DD_OK )
01022 {
01023 msg_Err( p_vout, "cannot get primary surface (error %li)", dxresult );
01024 return VLC_EGENERIC;
01025 }
01026
01027 dxresult = IDirectDrawSurface_QueryInterface( p_display,
01028 &IID_IDirectDrawSurface2,
01029 (LPVOID *)&p_vout->p_sys->p_display );
01030
01031 IDirectDrawSurface_Release( p_display );
01032 if ( dxresult != DD_OK )
01033 {
01034 msg_Err( p_vout, "cannot query IDirectDrawSurface2 interface "
01035 "(error %li)", dxresult );
01036 return VLC_EGENERIC;
01037 }
01038
01039
01040 DirectXCreateClipper( p_vout );
01041
01042
01043 p_vout->p_sys->i_colorkey = 1;
01044 p_vout->p_sys->i_rgb_colorkey =
01045 DirectXFindColorkey( p_vout, &p_vout->p_sys->i_colorkey );
01046
01047
01048 SetClassLong( p_vout->p_sys->hvideownd, GCL_HBRBACKGROUND,
01049 (LONG)CreateSolidBrush( p_vout->p_sys->i_rgb_colorkey ) );
01050 InvalidateRect( p_vout->p_sys->hvideownd, NULL, TRUE );
01051 E_(DirectXUpdateRects)( p_vout, VLC_TRUE );
01052
01053 return VLC_SUCCESS;
01054 }
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064 static int DirectXCreateClipper( vout_thread_t *p_vout )
01065 {
01066 HRESULT dxresult;
01067
01068 msg_Dbg( p_vout, "DirectXCreateClipper" );
01069
01070
01071 dxresult = IDirectDraw2_CreateClipper( p_vout->p_sys->p_ddobject, 0,
01072 &p_vout->p_sys->p_clipper, NULL );
01073 if( dxresult != DD_OK )
01074 {
01075 msg_Warn( p_vout, "cannot create clipper (error %li)", dxresult );
01076 goto error;
01077 }
01078
01079
01080 dxresult = IDirectDrawClipper_SetHWnd( p_vout->p_sys->p_clipper, 0,
01081 p_vout->p_sys->hvideownd );
01082 if( dxresult != DD_OK )
01083 {
01084 msg_Warn( p_vout, "cannot attach clipper to window (error %li)",
01085 dxresult );
01086 goto error;
01087 }
01088
01089
01090 dxresult = IDirectDrawSurface_SetClipper(p_vout->p_sys->p_display,
01091 p_vout->p_sys->p_clipper);
01092 if( dxresult != DD_OK )
01093 {
01094 msg_Warn( p_vout, "cannot attach clipper to surface (error %li)",
01095 dxresult );
01096 goto error;
01097 }
01098
01099 return VLC_SUCCESS;
01100
01101 error:
01102 if( p_vout->p_sys->p_clipper )
01103 {
01104 IDirectDrawClipper_Release( p_vout->p_sys->p_clipper );
01105 }
01106 p_vout->p_sys->p_clipper = NULL;
01107 return VLC_EGENERIC;
01108 }
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120 static int DirectXCreateSurface( vout_thread_t *p_vout,
01121 LPDIRECTDRAWSURFACE2 *pp_surface_final,
01122 int i_chroma, int b_overlay,
01123 int i_backbuffers )
01124 {
01125 HRESULT dxresult;
01126 LPDIRECTDRAWSURFACE p_surface;
01127 DDSURFACEDESC ddsd;
01128
01129
01130 if( b_overlay )
01131 {
01132
01133
01134
01135
01136
01137
01138
01139
01140 memset( &ddsd, 0, sizeof( DDSURFACEDESC ));
01141 ddsd.dwSize = sizeof(DDSURFACEDESC);
01142 ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
01143 ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
01144 ddsd.ddpfPixelFormat.dwFourCC = i_chroma;
01145 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
01146 ddsd.dwFlags |= (i_backbuffers ? DDSD_BACKBUFFERCOUNT : 0);
01147 ddsd.ddsCaps.dwCaps = DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY;
01148 ddsd.ddsCaps.dwCaps |= (i_backbuffers ? DDSCAPS_COMPLEX | DDSCAPS_FLIP
01149 : 0 );
01150 ddsd.dwHeight = p_vout->render.i_height;
01151 ddsd.dwWidth = p_vout->render.i_width;
01152 ddsd.dwBackBufferCount = i_backbuffers;
01153
01154 dxresult = IDirectDraw2_CreateSurface( p_vout->p_sys->p_ddobject,
01155 &ddsd, &p_surface, NULL );
01156 if( dxresult != DD_OK )
01157 {
01158 *pp_surface_final = NULL;
01159 return VLC_EGENERIC;
01160 }
01161 }
01162
01163 if( !b_overlay )
01164 {
01165 vlc_bool_t b_rgb_surface =
01166 ( i_chroma == VLC_FOURCC('R','G','B','2') )
01167 || ( i_chroma == VLC_FOURCC('R','V','1','5') )
01168 || ( i_chroma == VLC_FOURCC('R','V','1','6') )
01169 || ( i_chroma == VLC_FOURCC('R','V','2','4') )
01170 || ( i_chroma == VLC_FOURCC('R','V','3','2') );
01171
01172 memset( &ddsd, 0, sizeof( DDSURFACEDESC ) );
01173 ddsd.dwSize = sizeof(DDSURFACEDESC);
01174 ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
01175 ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH | DDSD_CAPS;
01176 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
01177 ddsd.dwHeight = p_vout->render.i_height;
01178 ddsd.dwWidth = p_vout->render.i_width;
01179
01180 if( p_vout->p_sys->b_use_sysmem )
01181 ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
01182 else
01183 ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
01184
01185 if( !b_rgb_surface )
01186 {
01187 ddsd.dwFlags |= DDSD_PIXELFORMAT;
01188 ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
01189 ddsd.ddpfPixelFormat.dwFourCC = i_chroma;
01190 }
01191
01192 dxresult = IDirectDraw2_CreateSurface( p_vout->p_sys->p_ddobject,
01193 &ddsd, &p_surface, NULL );
01194 if( dxresult != DD_OK )
01195 {
01196 *pp_surface_final = NULL;
01197 return VLC_EGENERIC;
01198 }
01199 }
01200
01201
01202 dxresult = IDirectDrawSurface_QueryInterface( p_surface,
01203 &IID_IDirectDrawSurface2,
01204 (LPVOID *)pp_surface_final );
01205 IDirectDrawSurface_Release( p_surface );
01206 if ( dxresult != DD_OK )
01207 {
01208 msg_Err( p_vout, "cannot query IDirectDrawSurface2 interface "
01209 "(error %li)", dxresult );
01210 *pp_surface_final = NULL;
01211 return VLC_EGENERIC;
01212 }
01213
01214 if( b_overlay )
01215 {
01216
01217
01218 p_vout->p_sys->p_current_surface = *pp_surface_final;
01219 if( E_(DirectXUpdateOverlay)( p_vout ) != VLC_SUCCESS )
01220 {
01221 IDirectDrawSurface2_Release( *pp_surface_final );
01222 *pp_surface_final = NULL;
01223 msg_Err( p_vout, "overlay unuseable (might already be in use)" );
01224 return VLC_EGENERIC;
01225 }
01226 }
01227
01228 return VLC_SUCCESS;
01229 }
01230
01231
01232
01233
01234
01235
01236
01237
01238 int E_(DirectXUpdateOverlay)( vout_thread_t *p_vout )
01239 {
01240 DDOVERLAYFX ddofx;
01241 DWORD dwFlags;
01242 HRESULT dxresult;
01243 RECT rect_src = p_vout->p_sys->rect_src_clipped;
01244 RECT rect_dest = p_vout->p_sys->rect_dest_clipped;
01245
01246 if( !p_vout->p_sys->b_using_overlay ) return VLC_EGENERIC;
01247
01248 if( p_vout->p_sys->b_wallpaper )
01249 {
01250 int i_x, i_y, i_width, i_height;
01251
01252 rect_src.left = p_vout->fmt_out.i_x_offset;
01253 rect_src.top = p_vout->fmt_out.i_y_offset;
01254 rect_src.right = rect_src.left + p_vout->fmt_out.i_visible_width;
01255 rect_src.bottom = rect_src.top + p_vout->fmt_out.i_visible_height;
01256
01257 rect_dest = p_vout->p_sys->rect_display;
01258 vout_PlacePicture( p_vout, rect_dest.right, rect_dest.bottom,
01259 &i_x, &i_y, &i_width, &i_height );
01260
01261 rect_dest.left += i_x;
01262 rect_dest.right = rect_dest.left + i_width;
01263 rect_dest.top += i_y;
01264 rect_dest.bottom = rect_dest.top + i_height;
01265 }
01266
01267 vlc_mutex_lock( &p_vout->p_sys->lock );
01268 if( p_vout->p_sys->p_current_surface == NULL )
01269 {
01270 vlc_mutex_unlock( &p_vout->p_sys->lock );
01271 return VLC_EGENERIC;
01272 }
01273
01274
01275
01276
01277
01278 memset(&ddofx, 0, sizeof(DDOVERLAYFX));
01279 ddofx.dwSize = sizeof(DDOVERLAYFX);
01280 ddofx.dckDestColorkey.dwColorSpaceLowValue = p_vout->p_sys->i_colorkey;
01281 ddofx.dckDestColorkey.dwColorSpaceHighValue = p_vout->p_sys->i_colorkey;
01282
01283 dwFlags = DDOVER_SHOW | DDOVER_KEYDESTOVERRIDE;
01284
01285 dxresult = IDirectDrawSurface2_UpdateOverlay(
01286 p_vout->p_sys->p_current_surface,
01287 &rect_src, p_vout->p_sys->p_display, &rect_dest,
01288 dwFlags, &ddofx );
01289
01290 vlc_mutex_unlock( &p_vout->p_sys->lock );
01291
01292 if(dxresult != DD_OK)
01293 {
01294 msg_Warn( p_vout, "DirectXUpdateOverlay cannot move/resize overlay" );
01295 return VLC_EGENERIC;
01296 }
01297
01298 return VLC_SUCCESS;
01299 }
01300
01301
01302
01303
01304
01305
01306 static void DirectXCloseDDraw( vout_thread_t *p_vout )
01307 {
01308 msg_Dbg( p_vout, "DirectXCloseDDraw" );
01309 if( p_vout->p_sys->p_ddobject != NULL )
01310 {
01311 IDirectDraw2_Release(p_vout->p_sys->p_ddobject);
01312 p_vout->p_sys->p_ddobject = NULL;
01313 }
01314
01315 if( p_vout->p_sys->hddraw_dll != NULL )
01316 {
01317 FreeLibrary( p_vout->p_sys->hddraw_dll );
01318 p_vout->p_sys->hddraw_dll = NULL;
01319 }
01320
01321 if( p_vout->p_sys->p_display_driver != NULL )
01322 {
01323 free( p_vout->p_sys->p_display_driver );
01324 p_vout->p_sys->p_display_driver = NULL;
01325 }
01326
01327 p_vout->p_sys->hmonitor = NULL;
01328 }
01329
01330
01331
01332
01333
01334
01335 static void DirectXCloseDisplay( vout_thread_t *p_vout )
01336 {
01337 msg_Dbg( p_vout, "DirectXCloseDisplay" );
01338
01339 if( p_vout->p_sys->p_clipper != NULL )
01340 {
01341 msg_Dbg( p_vout, "DirectXCloseDisplay clipper" );
01342 IDirectDrawClipper_Release( p_vout->p_sys->p_clipper );
01343 p_vout->p_sys->p_clipper = NULL;
01344 }
01345
01346 if( p_vout->p_sys->p_display != NULL )
01347 {
01348 msg_Dbg( p_vout, "DirectXCloseDisplay display" );
01349 IDirectDrawSurface2_Release( p_vout->p_sys->p_display );
01350 p_vout->p_sys->p_display = NULL;
01351 }
01352 }
01353
01354
01355
01356
01357
01358
01359 static void DirectXCloseSurface( vout_thread_t *p_vout,
01360 LPDIRECTDRAWSURFACE2 p_surface )
01361 {
01362 msg_Dbg( p_vout, "DirectXCloseSurface" );
01363 if( p_surface != NULL )
01364 {
01365 IDirectDrawSurface2_Release( p_surface );
01366 }
01367 }
01368
01369
01370
01371
01372
01373
01374 static int NewPictureVec( vout_thread_t *p_vout, picture_t *p_pic,
01375 int i_num_pics )
01376 {
01377 int i;
01378 int i_ret = VLC_SUCCESS;
01379 LPDIRECTDRAWSURFACE2 p_surface;
01380
01381 msg_Dbg( p_vout, "NewPictureVec overlay:%s chroma:%.4s",
01382 p_vout->p_sys->b_using_overlay ? "yes" : "no",
01383 (char *)&p_vout->output.i_chroma );
01384
01385 I_OUTPUTPICTURES = 0;
01386
01387
01388
01389
01390
01391
01392
01393 if( p_vout->p_sys->b_using_overlay )
01394 {
01395
01396
01397
01398 if( p_vout->p_sys->b_3buf_overlay )
01399 i_ret = DirectXCreateSurface( p_vout, &p_surface,
01400 p_vout->output.i_chroma,
01401 p_vout->p_sys->b_using_overlay,
01402 2 );
01403
01404 if( !p_vout->p_sys->b_3buf_overlay || i_ret != VLC_SUCCESS )
01405 {
01406
01407 i_ret = DirectXCreateSurface( p_vout, &p_surface,
01408 p_vout->output.i_chroma,
01409 p_vout->p_sys->b_using_overlay,
01410 0 );
01411 }
01412
01413 if( i_ret == VLC_SUCCESS )
01414 {
01415 DDSCAPS dds_caps;
01416 picture_t front_pic;
01417 picture_sys_t front_pic_sys;
01418 front_pic.p_sys = &front_pic_sys;
01419
01420
01421 p_pic[0].p_sys = malloc( sizeof( picture_sys_t ) );
01422 if( p_pic[0].p_sys == NULL )
01423 {
01424 DirectXCloseSurface( p_vout, p_surface );
01425 return VLC_ENOMEM;
01426 }
01427
01428
01429 p_pic[0].p_sys->p_front_surface = p_surface;
01430
01431
01432 memset( &dds_caps, 0, sizeof( DDSCAPS ) );
01433 dds_caps.dwCaps = DDSCAPS_BACKBUFFER;
01434 if( DD_OK != IDirectDrawSurface2_GetAttachedSurface(
01435 p_surface, &dds_caps,
01436 &p_pic[0].p_sys->p_surface ) )
01437 {
01438 msg_Warn( p_vout, "NewPictureVec could not get back buffer" );
01439
01440 p_pic[0].p_sys->p_surface = p_surface;
01441 }
01442
01443
01444 p_vout->p_sys->p_current_surface = front_pic.p_sys->p_surface =
01445 p_pic[0].p_sys->p_front_surface;
01446
01447
01448 if( DirectXLockSurface( p_vout, &front_pic ) == VLC_SUCCESS )
01449 {
01450 int i,j;
01451 for( i = 0; i < front_pic.i_planes; i++ )
01452 for( j = 0; j < front_pic.p[i].i_visible_lines; j++)
01453 memset( front_pic.p[i].p_pixels + j *
01454 front_pic.p[i].i_pitch, 127,
01455 front_pic.p[i].i_visible_pitch );
01456
01457 DirectXUnlockSurface( p_vout, &front_pic );
01458 }
01459
01460 E_(DirectXUpdateOverlay)( p_vout );
01461 I_OUTPUTPICTURES = 1;
01462 msg_Dbg( p_vout, "YUV overlay created successfully" );
01463 }
01464 }
01465
01466
01467
01468
01469
01470
01471
01472 if( !p_vout->p_sys->b_using_overlay )
01473 {
01474 if( p_vout->p_sys->b_hw_yuv )
01475 {
01476 DWORD i_codes;
01477 DWORD *pi_codes;
01478 vlc_bool_t b_result = VLC_FALSE;
01479
01480
01481
01482
01483 if( IDirectDraw2_GetFourCCCodes( p_vout->p_sys->p_ddobject,
01484 &i_codes, NULL ) == DD_OK )
01485 {
01486 pi_codes = malloc( i_codes * sizeof(DWORD) );
01487 if( pi_codes && IDirectDraw2_GetFourCCCodes(
01488 p_vout->p_sys->p_ddobject, &i_codes, pi_codes ) == DD_OK )
01489 {
01490 for( i = 0; i < (int)i_codes; i++ )
01491 {
01492 if( p_vout->output.i_chroma == pi_codes[i] )
01493 {
01494 b_result = VLC_TRUE;
01495 break;
01496 }
01497 }
01498 }
01499 }
01500
01501 if( b_result )
01502 i_ret = DirectXCreateSurface( p_vout, &p_surface,
01503 p_vout->output.i_chroma,
01504 0 ,
01505 0 );
01506 else
01507 p_vout->p_sys->b_hw_yuv = VLC_FALSE;
01508 }
01509
01510 if( i_ret || !p_vout->p_sys->b_hw_yuv )
01511 {
01512
01513 DDPIXELFORMAT ddpfPixelFormat;
01514
01515 ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
01516 IDirectDrawSurface2_GetPixelFormat( p_vout->p_sys->p_display,
01517 &ddpfPixelFormat );
01518
01519 if( ddpfPixelFormat.dwFlags & DDPF_RGB )
01520 {
01521 switch( ddpfPixelFormat.dwRGBBitCount )
01522 {
01523 case 8:
01524 p_vout->output.i_chroma = VLC_FOURCC('R','G','B','2');
01525 p_vout->output.pf_setpalette = SetPalette;
01526 break;
01527 case 15:
01528 p_vout->output.i_chroma = VLC_FOURCC('R','V','1','5');
01529 break;
01530 case 16:
01531 p_vout->output.i_chroma = VLC_FOURCC('R','V','1','6');
01532 break;
01533 case 24:
01534 p_vout->output.i_chroma = VLC_FOURCC('R','V','2','4');
01535 break;
01536 case 32:
01537 p_vout->output.i_chroma = VLC_FOURCC('R','V','3','2');
01538 break;
01539 default:
01540 msg_Err( p_vout, "unknown screen depth" );
01541 return VLC_EGENERIC;
01542 }
01543 p_vout->output.i_rmask = ddpfPixelFormat.dwRBitMask;
01544 p_vout->output.i_gmask = ddpfPixelFormat.dwGBitMask;
01545 p_vout->output.i_bmask = ddpfPixelFormat.dwBBitMask;
01546 }
01547
01548 p_vout->p_sys->b_hw_yuv = 0;
01549
01550 i_ret = DirectXCreateSurface( p_vout, &p_surface,
01551 p_vout->output.i_chroma,
01552 0 ,
01553 0 );
01554
01555 if( i_ret && !p_vout->p_sys->b_use_sysmem )
01556 {
01557
01558 p_vout->p_sys->b_use_sysmem = 1;
01559
01560 i_ret = DirectXCreateSurface( p_vout, &p_surface,
01561 p_vout->output.i_chroma,
01562 0 ,
01563 0 );
01564 }
01565 }
01566
01567 if( i_ret == VLC_SUCCESS )
01568 {
01569
01570 p_pic[0].p_sys = malloc( sizeof( picture_sys_t ) );
01571 if( p_pic[0].p_sys == NULL )
01572 {
01573 DirectXCloseSurface( p_vout, p_surface );
01574 return VLC_ENOMEM;
01575 }
01576
01577 p_pic[0].p_sys->p_surface = p_pic[0].p_sys->p_front_surface
01578 = p_surface;
01579
01580 I_OUTPUTPICTURES = 1;
01581
01582 msg_Dbg( p_vout, "created plain surface of chroma:%.4s",
01583 (char *)&p_vout->output.i_chroma );
01584 }
01585 }
01586
01587
01588
01589
01590 for( i = 0; i < I_OUTPUTPICTURES; i++ )
01591 {
01592 p_pic[i].i_status = DESTROYED_PICTURE;
01593 p_pic[i].i_type = DIRECT_PICTURE;
01594 p_pic[i].b_slow = VLC_TRUE;
01595 p_pic[i].pf_lock = DirectXLockSurface;
01596 p_pic[i].pf_unlock = DirectXUnlockSurface;
01597 PP_OUTPUTPICTURE[i] = &p_pic[i];
01598
01599 if( DirectXLockSurface( p_vout, &p_pic[i] ) != VLC_SUCCESS )
01600 {
01601
01602 FreePictureVec( p_vout, p_pic, I_OUTPUTPICTURES );
01603 I_OUTPUTPICTURES = 0;
01604 msg_Err( p_vout, "cannot lock surface" );
01605 return VLC_EGENERIC;
01606 }
01607 DirectXUnlockSurface( p_vout, &p_pic[i] );
01608 }
01609
01610 msg_Dbg( p_vout, "End NewPictureVec (%s)",
01611 I_OUTPUTPICTURES ? "succeeded" : "failed" );
01612
01613 return VLC_SUCCESS;
01614 }
01615
01616
01617
01618
01619
01620
01621 static void FreePictureVec( vout_thread_t *p_vout, picture_t *p_pic,
01622 int i_num_pics )
01623 {
01624 int i;
01625
01626 vlc_mutex_lock( &p_vout->p_sys->lock );
01627 p_vout->p_sys->p_current_surface = 0;
01628 vlc_mutex_unlock( &p_vout->p_sys->lock );
01629
01630 for( i = 0; i < i_num_pics; i++ )
01631 {
01632 DirectXCloseSurface( p_vout, p_pic[i].p_sys->p_front_surface );
01633
01634 for( i = 0; i < i_num_pics; i++ )
01635 {
01636 free( p_pic[i].p_sys );
01637 }
01638 }
01639 }
01640
01641
01642
01643
01644
01645
01646 static int UpdatePictureStruct( vout_thread_t *p_vout, picture_t *p_pic,
01647 int i_chroma )
01648 {
01649 switch( p_vout->output.i_chroma )
01650 {
01651 case VLC_FOURCC('R','G','B','2'):
01652 case VLC_FOURCC('R','V','1','5'):
01653 case VLC_FOURCC('R','V','1','6'):
01654 case VLC_FOURCC('R','V','2','4'):
01655 case VLC_FOURCC('R','V','3','2'):
01656 p_pic->p->p_pixels = p_pic->p_sys->ddsd.lpSurface;
01657 p_pic->p->i_lines = p_vout->output.i_height;
01658 p_pic->p->i_visible_lines = p_vout->output.i_height;
01659 p_pic->p->i_pitch = p_pic->p_sys->ddsd.lPitch;
01660 switch( p_vout->output.i_chroma )
01661 {
01662 case VLC_FOURCC('R','G','B','2'):
01663 p_pic->p->i_pixel_pitch = 1;
01664 break;
01665 case VLC_FOURCC('R','V','1','5'):
01666 case VLC_FOURCC('R','V','1','6'):
01667 p_pic->p->i_pixel_pitch = 2;
01668 break;
01669 case VLC_FOURCC('R','V','2','4'):
01670 p_pic->p->i_pixel_pitch = 3;
01671 break;
01672 case VLC_FOURCC('R','V','3','2'):
01673 p_pic->p->i_pixel_pitch = 4;
01674 break;
01675 default:
01676 return VLC_EGENERIC;
01677 }
01678 p_pic->p->i_visible_pitch = p_vout->output.i_width *
01679 p_pic->p->i_pixel_pitch;
01680 p_pic->i_planes = 1;
01681 break;
01682
01683 case VLC_FOURCC('Y','V','1','2'):
01684 case VLC_FOURCC('I','4','2','0'):
01685
01686
01687
01688 p_vout->output.i_chroma = VLC_FOURCC('I','4','2','0');
01689
01690 p_pic->Y_PIXELS = p_pic->p_sys->ddsd.lpSurface;
01691 p_pic->p[Y_PLANE].i_lines = p_vout->output.i_height;
01692 p_pic->p[Y_PLANE].i_visible_lines = p_vout->output.i_height;
01693 p_pic->p[Y_PLANE].i_pitch = p_pic->p_sys->ddsd.lPitch;
01694 p_pic->p[Y_PLANE].i_pixel_pitch = 1;
01695 p_pic->p[Y_PLANE].i_visible_pitch = p_vout->output.i_width *
01696 p_pic->p[Y_PLANE].i_pixel_pitch;
01697
01698 p_pic->V_PIXELS = p_pic->Y_PIXELS
01699 + p_pic->p[Y_PLANE].i_lines * p_pic->p[Y_PLANE].i_pitch;
01700 p_pic->p[V_PLANE].i_lines = p_vout->output.i_height / 2;
01701 p_pic->p[V_PLANE].i_visible_lines = p_vout->output.i_height / 2;
01702 p_pic->p[V_PLANE].i_pitch = p_pic->p[Y_PLANE].i_pitch / 2;
01703 p_pic->p[V_PLANE].i_pixel_pitch = 1;
01704 p_pic->p[V_PLANE].i_visible_pitch = p_vout->output.i_width / 2 *
01705 p_pic->p[V_PLANE].i_pixel_pitch;
01706
01707 p_pic->U_PIXELS = p_pic->V_PIXELS
01708 + p_pic->p[V_PLANE].i_lines * p_pic->p[V_PLANE].i_pitch;
01709 p_pic->p[U_PLANE].i_lines = p_vout->output.i_height / 2;
01710 p_pic->p[U_PLANE].i_visible_lines = p_vout->output.i_height / 2;
01711 p_pic->p[U_PLANE].i_pitch = p_pic->p[Y_PLANE].i_pitch / 2;
01712 p_pic->p[U_PLANE].i_pixel_pitch = 1;
01713 p_pic->p[U_PLANE].i_visible_pitch = p_vout->output.i_width / 2 *
01714 p_pic->p[U_PLANE].i_pixel_pitch;
01715
01716 p_pic->i_planes = 3;
01717 break;
01718
01719 case VLC_FOURCC('I','Y','U','V'):
01720
01721 p_pic->Y_PIXELS = p_pic->p_sys->ddsd.lpSurface;
01722 p_pic->p[Y_PLANE].i_lines = p_vout->output.i_height;
01723 p_pic->p[Y_PLANE].i_visible_lines = p_vout->output.i_height;
01724 p_pic->p[Y_PLANE].i_pitch = p_pic->p_sys->ddsd.lPitch;
01725 p_pic->p[Y_PLANE].i_pixel_pitch = 1;
01726 p_pic->p[Y_PLANE].i_visible_pitch = p_vout->output.i_width *
01727 p_pic->p[Y_PLANE].i_pixel_pitch;
01728
01729 p_pic->U_PIXELS = p_pic->Y_PIXELS
01730 + p_pic->p[Y_PLANE].i_lines * p_pic->p[Y_PLANE].i_pitch;
01731 p_pic->p[U_PLANE].i_lines = p_vout->output.i_height / 2;
01732 p_pic->p[U_PLANE].i_visible_lines = p_vout->output.i_height / 2;
01733 p_pic->p[U_PLANE].i_pitch = p_pic->p[Y_PLANE].i_pitch / 2;
01734 p_pic->p[U_PLANE].i_pixel_pitch = 1;
01735 p_pic->p[U_PLANE].i_visible_pitch = p_vout->output.i_width / 2 *
01736 p_pic->p[U_PLANE].i_pixel_pitch;
01737
01738 p_pic->V_PIXELS = p_pic->U_PIXELS
01739 + p_pic->p[U_PLANE].i_lines * p_pic->p[U_PLANE].i_pitch;
01740 p_pic->p[V_PLANE].i_lines = p_vout->output.i_height / 2;
01741 p_pic->p[V_PLANE].i_visible_lines = p_vout->output.i_height / 2;
01742 p_pic->p[V_PLANE].i_pitch = p_pic->p[Y_PLANE].i_pitch / 2;
01743 p_pic->p[V_PLANE].i_pixel_pitch = 1;
01744 p_pic->p[V_PLANE].i_visible_pitch = p_vout->output.i_width / 2 *
01745 p_pic->p[V_PLANE].i_pixel_pitch;
01746
01747 p_pic->i_planes = 3;
01748 break;
01749
01750 case VLC_FOURCC('U','Y','V','Y'):
01751 case VLC_FOURCC('Y','U','Y','2'):
01752
01753 p_pic->p->p_pixels = p_pic->p_sys->ddsd.lpSurface;
01754 p_pic->p->i_lines = p_vout->output.i_height;
01755 p_pic->p->i_visible_lines = p_vout->output.i_height;
01756 p_pic->p->i_pitch = p_pic->p_sys->ddsd.lPitch;
01757 p_pic->p->i_pixel_pitch = 2;
01758 p_pic->p->i_visible_pitch = p_vout->output.i_width *
01759 p_pic->p->i_pixel_pitch;
01760
01761 p_pic->i_planes = 1;
01762 break;
01763
01764 default:
01765
01766 msg_Err( p_vout, "never heard of chroma 0x%.8x (%4.4s)",
01767 p_vout->output.i_chroma,
01768 (char*)&p_vout->output.i_chroma );
01769 return VLC_EGENERIC;
01770 }
01771
01772 return VLC_SUCCESS;
01773 }
01774
01775
01776
01777
01778
01779
01780
01781 static void DirectXGetDDrawCaps( vout_thread_t *p_vout )
01782 {
01783 DDCAPS ddcaps;
01784 HRESULT dxresult;
01785
01786
01787
01788 memset( &ddcaps, 0, sizeof( DDCAPS ));
01789 ddcaps.dwSize = sizeof(DDCAPS);
01790 dxresult = IDirectDraw2_GetCaps( p_vout->p_sys->p_ddobject,
01791 &ddcaps, NULL );
01792 if(dxresult != DD_OK )
01793 {
01794 msg_Warn( p_vout, "cannot get caps" );
01795 }
01796 else
01797 {
01798 vlc_bool_t bHasOverlay, bHasOverlayFourCC, bCanDeinterlace,
01799 bHasColorKey, bCanStretch, bCanBltFourcc,
01800 bAlignBoundarySrc, bAlignBoundaryDest,
01801 bAlignSizeSrc, bAlignSizeDest;
01802
01803
01804 bHasOverlay = (ddcaps.dwCaps & DDCAPS_OVERLAY) ? 1 : 0;
01805
01806 bHasOverlayFourCC = (ddcaps.dwCaps & DDCAPS_OVERLAYFOURCC) ? 1 : 0;
01807
01808 bCanDeinterlace = (ddcaps.dwCaps & DDCAPS2_CANFLIPODDEVEN) ? 1 : 0;
01809
01810 bHasColorKey = (ddcaps.dwCaps & DDCAPS_COLORKEY) ? 1 : 0;
01811
01812 bCanStretch = (ddcaps.dwCaps & DDCAPS_OVERLAYSTRETCH) ? 1 : 0;
01813
01814 bCanBltFourcc = (ddcaps.dwCaps & DDCAPS_BLTFOURCC) ? 1 : 0;
01815
01816 bAlignBoundarySrc = (ddcaps.dwCaps & DDCAPS_ALIGNBOUNDARYSRC) ? 1 : 0;
01817
01818 bAlignBoundaryDest = (ddcaps.dwCaps & DDCAPS_ALIGNBOUNDARYDEST) ? 1:0;
01819
01820 bAlignSizeSrc = (ddcaps.dwCaps & DDCAPS_ALIGNSIZESRC) ? 1 : 0;
01821
01822 bAlignSizeDest = (ddcaps.dwCaps & DDCAPS_ALIGNSIZEDEST) ? 1 : 0;
01823
01824 msg_Dbg( p_vout, "DirectDraw Capabilities: overlay=%i yuvoverlay=%i "
01825 "can_deinterlace_overlay=%i colorkey=%i stretch=%i "
01826 "bltfourcc=%i",
01827 bHasOverlay, bHasOverlayFourCC, bCanDeinterlace,
01828 bHasColorKey, bCanStretch, bCanBltFourcc );
01829
01830 if( bAlignBoundarySrc || bAlignBoundaryDest ||
01831 bAlignSizeSrc || bAlignSizeDest )
01832 {
01833 if( bAlignBoundarySrc ) p_vout->p_sys->i_align_src_boundary =
01834 ddcaps.dwAlignBoundarySrc;
01835 if( bAlignBoundaryDest ) p_vout->p_sys->i_align_dest_boundary =
01836 ddcaps.dwAlignBoundaryDest;
01837 if( bAlignSizeDest ) p_vout->p_sys->i_align_src_size =
01838 ddcaps.dwAlignSizeSrc;
01839 if( bAlignSizeDest ) p_vout->p_sys->i_align_dest_size =
01840 ddcaps.dwAlignSizeDest;
01841
01842 msg_Dbg( p_vout, "align_boundary_src=%i,%i "
01843 "align_boundary_dest=%i,%i "
01844 "align_size_src=%i,%i align_size_dest=%i,%i",
01845 bAlignBoundarySrc, p_vout->p_sys->i_align_src_boundary,
01846 bAlignBoundaryDest, p_vout->p_sys->i_align_dest_boundary,
01847 bAlignSizeSrc, p_vout->p_sys->i_align_src_size,
01848 bAlignSizeDest, p_vout->p_sys->i_align_dest_size );
01849 }
01850
01851
01852 if( !bCanBltFourcc ) p_vout->p_sys->b_hw_yuv = FALSE;
01853 }
01854 }
01855
01856
01857
01858
01859
01860
01861
01862 static int DirectXLockSurface( vout_thread_t *p_vout, picture_t *p_pic )
01863 {
01864 HRESULT dxresult;
01865
01866
01867 memset( &p_pic->p_sys->ddsd, 0, sizeof( DDSURFACEDESC ));
01868 p_pic->p_sys->ddsd.dwSize = sizeof(DDSURFACEDESC);
01869 dxresult = IDirectDrawSurface2_Lock( p_pic->p_sys->p_surface,
01870 NULL, &p_pic->p_sys->ddsd,
01871 DDLOCK_NOSYSLOCK | DDLOCK_WAIT,
01872 NULL );
01873 if( dxresult != DD_OK )
01874 {
01875 if( dxresult == DDERR_INVALIDPARAMS )
01876 {
01877
01878
01879 dxresult = IDirectDrawSurface2_Lock( p_pic->p_sys->p_surface, NULL,
01880 &p_pic->p_sys->ddsd,
01881 DDLOCK_WAIT, NULL);
01882 }
01883 if( dxresult == DDERR_SURFACELOST )
01884 {
01885
01886
01887
01888
01889
01890 if( p_vout->p_sys->b_using_overlay )
01891 IDirectDrawSurface2_Restore( p_pic->p_sys->p_front_surface );
01892 else
01893 IDirectDrawSurface2_Restore( p_pic->p_sys->p_surface );
01894
01895 dxresult = IDirectDrawSurface2_Lock( p_pic->p_sys->p_surface, NULL,
01896 &p_pic->p_sys->ddsd,
01897 DDLOCK_WAIT, NULL);
01898 #if 0
01899 if( dxresult == DDERR_SURFACELOST )
01900 msg_Dbg( p_vout, "DirectXLockSurface: DDERR_SURFACELOST" );
01901 #endif
01902 }
01903 if( dxresult != DD_OK )
01904 {
01905 return VLC_EGENERIC;
01906 }
01907 }
01908
01909
01910
01911 if( UpdatePictureStruct( p_vout, p_pic, p_vout->output.i_chroma )
01912 != VLC_SUCCESS )
01913 {
01914 DirectXUnlockSurface( p_vout, p_pic );
01915 return VLC_EGENERIC;
01916 }
01917 else
01918 return VLC_SUCCESS;
01919 }
01920
01921
01922
01923
01924 static int DirectXUnlockSurface( vout_thread_t *p_vout, picture_t *p_pic )
01925 {
01926
01927 if( IDirectDrawSurface2_Unlock( p_pic->p_sys->p_surface, NULL ) == DD_OK )
01928 return VLC_SUCCESS;
01929 else
01930 return VLC_EGENERIC;
01931 }
01932
01933
01934
01935
01936 static DWORD DirectXFindColorkey( vout_thread_t *p_vout, uint32_t *pi_color )
01937 {
01938 DDSURFACEDESC ddsd;
01939 HRESULT dxresult;
01940 COLORREF i_rgb = 0;
01941 uint32_t i_pixel_backup;
01942 HDC hdc;
01943
01944 ddsd.dwSize = sizeof(ddsd);
01945 dxresult = IDirectDrawSurface2_Lock( p_vout->p_sys->p_display, NULL,
01946 &ddsd, DDLOCK_WAIT, NULL );
01947 if( dxresult != DD_OK ) return 0;
01948
01949 i_pixel_backup = *(uint32_t *)ddsd.lpSurface;
01950
01951 switch( ddsd.ddpfPixelFormat.dwRGBBitCount )
01952 {
01953 case 4:
01954 *(uint8_t *)ddsd.lpSurface = *pi_color | (*pi_color << 4);
01955 break;
01956 case 8:
01957 *(uint8_t *)ddsd.lpSurface = *pi_color;
01958 break;
01959 case 15:
01960 case 16:
01961 *(uint16_t *)ddsd.lpSurface = *pi_color;
01962 break;
01963 case 24:
01964
01965 *pi_color = 0;
01966 default:
01967 *(uint32_t *)ddsd.lpSurface = *pi_color;
01968 break;
01969 }
01970
01971 IDirectDrawSurface2_Unlock( p_vout->p_sys->p_display, NULL );
01972
01973 if( IDirectDrawSurface2_GetDC( p_vout->p_sys->p_display, &hdc ) == DD_OK )
01974 {
01975 i_rgb = GetPixel( hdc, 0, 0 );
01976 IDirectDrawSurface2_ReleaseDC( p_vout->p_sys->p_display, hdc );
01977 }
01978
01979 ddsd.dwSize = sizeof(ddsd);
01980 dxresult = IDirectDrawSurface2_Lock( p_vout->p_sys->p_display, NULL,
01981 &ddsd, DDLOCK_WAIT, NULL );
01982 if( dxresult != DD_OK ) return i_rgb;
01983
01984 *(uint32_t *)ddsd.lpSurface = i_pixel_backup;
01985
01986 IDirectDrawSurface2_Unlock( p_vout->p_sys->p_display, NULL );
01987
01988 return i_rgb;
01989 }
01990
01991
01992
01993
01994 void SwitchWallpaperMode( vout_thread_t *p_vout, vlc_bool_t b_on )
01995 {
01996 HWND hwnd;
01997
01998 if( p_vout->p_sys->b_wallpaper == b_on ) return;
01999
02000 hwnd = FindWindow( _T("Progman"), NULL );
02001 if( hwnd ) hwnd = FindWindowEx( hwnd, NULL, _T("SHELLDLL_DefView"), NULL );
02002 if( hwnd ) hwnd = FindWindowEx( hwnd, NULL, _T("SysListView32"), NULL );
02003 if( !hwnd )
02004 {
02005 msg_Warn( p_vout, "couldn't find \"SysListView32\" window, "
02006 "wallpaper mode not supported" );
02007 return;
02008 }
02009
02010 p_vout->p_sys->b_wallpaper = b_on;
02011
02012 msg_Dbg( p_vout, "wallpaper mode %s", b_on ? "enabled" : "disabled" );
02013
02014 if( p_vout->p_sys->b_wallpaper )
02015 {
02016 p_vout->p_sys->color_bkg = ListView_GetBkColor( hwnd );
02017 p_vout->p_sys->color_bkgtxt = ListView_GetTextBkColor( hwnd );
02018
02019 ListView_SetBkColor( hwnd, p_vout->p_sys->i_rgb_colorkey );
02020 ListView_SetTextBkColor( hwnd, p_vout->p_sys->i_rgb_colorkey );
02021 }
02022 else if( hwnd )
02023 {
02024 ListView_SetBkColor( hwnd, p_vout->p_sys->color_bkg );
02025 ListView_SetTextBkColor( hwnd, p_vout->p_sys->color_bkgtxt );
02026 }
02027
02028
02029 InvalidateRect( hwnd, NULL, TRUE );
02030 UpdateWindow( hwnd );
02031 }
02032
02033
02034
02035
02036 BOOL WINAPI DirectXEnumCallback2( GUID* p_guid, LPTSTR psz_desc,
02037 LPTSTR psz_drivername, VOID* p_context,
02038 HMONITOR hmon )
02039 {
02040 module_config_t *p_item = (module_config_t *)p_context;
02041
02042 p_item->ppsz_list =
02043 (char **)realloc( p_item->ppsz_list,
02044 (p_item->i_list+2) * sizeof(char *) );
02045 p_item->ppsz_list_text =
02046 (char **)realloc( p_item->ppsz_list_text,
02047 (p_item->i_list+2) * sizeof(char *) );
02048
02049 p_item->ppsz_list[p_item->i_list] = strdup( psz_drivername );
02050 p_item->ppsz_list_text[p_item->i_list] = NULL;
02051 p_item->i_list++;
02052 p_item->ppsz_list[p_item->i_list] = NULL;
02053 p_item->ppsz_list_text[p_item->i_list] = NULL;
02054
02055 return TRUE;
02056 }
02057
02058 static int FindDevicesCallback( vlc_object_t *p_this, char const *psz_name,
02059 vlc_value_t newval, vlc_value_t oldval, void *d)
02060 {
02061 HRESULT (WINAPI *OurDirectDrawEnumerateEx)( LPDDENUMCALLBACKEXA, LPVOID,
02062 DWORD );
02063 HINSTANCE hddraw_dll;
02064
02065 module_config_t *p_item;
02066 int i;
02067
02068 p_item = config_FindConfig( p_this, psz_name );
02069 if( !p_item ) return VLC_SUCCESS;
02070
02071
02072 if( p_item->i_list )
02073 {
02074
02075 for( i = 1; i < p_item->i_list; i++ )
02076 {
02077 free( p_item->ppsz_list[i] );
02078 free( p_item->ppsz_list_text[i] );
02079 }
02080
02081 p_item->ppsz_list[i] = NULL;
02082 p_item->ppsz_list_text[i] = NULL;
02083 }
02084 p_item->i_list = 1;
02085
02086
02087 hddraw_dll = LoadLibrary(_T("DDRAW.DLL"));
02088 if( hddraw_dll == NULL ) return VLC_SUCCESS;
02089
02090 OurDirectDrawEnumerateEx =
02091 #ifndef UNICODE
02092 (void *)GetProcAddress( hddraw_dll, "DirectDrawEnumerateExA" );
02093 #else
02094 (void *)GetProcAddress( hddraw_dll, _T("DirectDrawEnumerateExW") );
02095 #endif
02096
02097 if( OurDirectDrawEnumerateEx )
02098 {
02099
02100 OurDirectDrawEnumerateEx( DirectXEnumCallback2, p_item,
02101 DDENUM_ATTACHEDSECONDARYDEVICES );
02102 }
02103
02104 FreeLibrary( hddraw_dll );
02105
02106
02107 p_item->b_dirty = VLC_TRUE;
02108
02109 return VLC_SUCCESS;
02110 }
02111
02112 static int WallpaperCallback( vlc_object_t *p_this, char const *psz_cmd,
02113 vlc_value_t oldval, vlc_value_t newval,
02114 void *p_data )
02115 {
02116 vout_thread_t *p_vout = (vout_thread_t *)p_this;
02117
02118 if( (newval.b_bool && !p_vout->p_sys->b_wallpaper) ||
02119 (!newval.b_bool && p_vout->p_sys->b_wallpaper) )
02120 {
02121 playlist_t *p_playlist;
02122
02123 p_playlist =
02124 (playlist_t *)vlc_object_find( p_this, VLC_OBJECT_PLAYLIST,
02125 FIND_PARENT );
02126 if( p_playlist )
02127 {
02128
02129
02130 var_Create( p_playlist, "directx-wallpaper", VLC_VAR_BOOL );
02131 var_Set( p_playlist, "directx-wallpaper", newval );
02132
02133 vlc_object_release( p_playlist );
02134 }
02135
02136 p_vout->p_sys->i_changes |= DX_WALLPAPER_CHANGE;
02137 }
02138
02139 return VLC_SUCCESS;
02140 }
02141
02142
02143
02144
02145 static void SetPalette( vout_thread_t *p_vout,
02146 uint16_t *red, uint16_t *green, uint16_t *blue )
02147 {
02148 msg_Err( p_vout, "FIXME: SetPalette unimplemented" );
02149 }