wingdi.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:32k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * wingdi.c : Win32 / WinCE GDI video output plugin for vlc
  3.  *****************************************************************************
  4.  * Copyright (C) 2002-2009 the VideoLAN team
  5.  * $Id: c725d66110c1df8ade309c3318d8ae6a7fc638d8 $
  6.  *
  7.  * Authors: Gildas Bazin <gbazin@videolan.org>
  8.  *          Samuel Hocevar <sam@zoy.org>
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  23.  *****************************************************************************/
  24. /*****************************************************************************
  25.  * Preamble
  26.  *****************************************************************************/
  27. #ifdef HAVE_CONFIG_H
  28. # include "config.h"
  29. #endif
  30. #include <vlc_common.h>
  31. #include <vlc_plugin.h>
  32. #include <vlc_interface.h>
  33. #include <vlc_playlist.h>
  34. #include <vlc_vout.h>
  35. #include <windows.h>
  36. #include <tchar.h>
  37. #include <commctrl.h>
  38. /*#ifdef MODULE_NAME_IS_wingapi
  39.     typedef struct GXDisplayProperties {
  40.         DWORD cxWidth;
  41.         DWORD cyHeight;
  42.         long cbxPitch;
  43.         long cbyPitch;
  44.         long cBPP;
  45.         DWORD ffFormat;
  46.     } GXDisplayProperties;
  47.     typedef struct GXScreenRect {
  48.         DWORD dwTop;
  49.         DWORD dwLeft;
  50.         DWORD dwWidth;
  51.         DWORD dwHeight;
  52.     } GXScreenRect;
  53. #   define GX_FULLSCREEN    0x01
  54. #   define GX_NORMALKEYS    0x02
  55. #   define GX_LANDSCAPEKEYS 0x03
  56. #   ifndef kfLandscape
  57. #       define kfLandscape      0x8
  58. #       define kfPalette        0x10
  59. #       define kfDirect         0x20
  60. #       define kfDirect555      0x40
  61. #       define kfDirect565      0x80
  62. #       define kfDirect888      0x100
  63. #       define kfDirect444      0x200
  64. #       define kfDirectInverted 0x400
  65. #   endif
  66. #endif */ /* MODULE_NAME_IS_wingapi */
  67. #include "vout.h"
  68. #define MAX_DIRECTBUFFERS 10
  69. #ifdef UNDER_CE
  70. #ifndef WS_OVERLAPPEDWINDOW
  71. #   define WS_OVERLAPPEDWINDOW 0xcf0000
  72. #endif
  73. #ifndef WS_EX_NOPARENTNOTIFY
  74. #   define WS_EX_NOPARENTNOTIFY 4
  75. #endif
  76. #ifndef WS_EX_APPWINDOW
  77. #define WS_EX_APPWINDOW 0x40000
  78. #endif
  79. //#define SetWindowLongPtr SetWindowLong
  80. //#define GetWindowLongPtr GetWindowLong
  81. //#define GWLP_USERDATA GWL_USERDATA
  82. #define AdjustWindowRect(a,b,c)
  83. #endif //UNDER_CE
  84. #ifndef WS_NONAVDONEBUTTON
  85. #define WS_NONAVDONEBUTTON 0
  86. #endif
  87. /*****************************************************************************
  88.  * Local prototypes
  89.  *****************************************************************************/
  90. static int  OpenVideo  ( vlc_object_t * );
  91. static void CloseVideo ( vlc_object_t * );
  92. static int  Init      ( vout_thread_t * );
  93. static void End       ( vout_thread_t * );
  94. static int  Manage    ( vout_thread_t * );
  95. static void Render    ( vout_thread_t *, picture_t * );
  96. #ifdef MODULE_NAME_IS_wingapi
  97. static void FirstDisplayGAPI( vout_thread_t *, picture_t * );
  98. static void DisplayGAPI( vout_thread_t *, picture_t * );
  99. static int GAPILockSurface( vout_thread_t *, picture_t * );
  100. static int GAPIUnlockSurface( vout_thread_t *, picture_t * );
  101. #else
  102. static void FirstDisplayGDI( vout_thread_t *, picture_t * );
  103. static void DisplayGDI( vout_thread_t *, picture_t * );
  104. #endif
  105. static void SetPalette( vout_thread_t *, uint16_t *, uint16_t *, uint16_t * );
  106. static void InitBuffers        ( vout_thread_t * );
  107. #define DX_POSITION_CHANGE 0x1000
  108. /*****************************************************************************
  109.  * Module descriptor
  110.  *****************************************************************************/
  111. vlc_module_begin ()
  112.     set_category( CAT_VIDEO )
  113.     set_subcategory( SUBCAT_VIDEO_VOUT )
  114. #ifdef MODULE_NAME_IS_wingapi
  115.     set_shortname( "Windows GAPI" )
  116.     set_description( N_("Windows GAPI video output") )
  117.     set_capability( "video output", 20 )
  118. #else
  119.     set_shortname( "Windows GDI" )
  120.     set_description( N_("Windows GDI video output") )
  121.     set_capability( "video output", 10 )
  122. #endif
  123.     set_callbacks( OpenVideo, CloseVideo )
  124. vlc_module_end ()
  125. /*****************************************************************************
  126.  * OpenVideo: activate GDI video thread output method
  127.  *****************************************************************************/
  128. static int OpenVideo ( vlc_object_t *p_this )
  129. {
  130.     vout_thread_t * p_vout = (vout_thread_t *)p_this;
  131.     p_vout->p_sys = (vout_sys_t *)calloc( 1, sizeof(vout_sys_t) );
  132.     if( !p_vout->p_sys ) return VLC_ENOMEM;
  133. #ifdef MODULE_NAME_IS_wingapi
  134.     /* Load GAPI */
  135.     p_vout->p_sys->gapi_dll = LoadLibrary( _T("GX.DLL") );
  136.     if( p_vout->p_sys->gapi_dll == NULL )
  137.     {
  138.         msg_Warn( p_vout, "failed loading gx.dll" );
  139.         free( p_vout->p_sys );
  140.         return VLC_EGENERIC;
  141.     }
  142.     GXOpenDisplay = (void *)GetProcAddress( p_vout->p_sys->gapi_dll,
  143.         _T("?GXOpenDisplay@@YAHPAUHWND__@@K@Z") );
  144.     GXCloseDisplay = (void *)GetProcAddress( p_vout->p_sys->gapi_dll,
  145.         _T("?GXCloseDisplay@@YAHXZ") );
  146.     GXBeginDraw = (void *)GetProcAddress( p_vout->p_sys->gapi_dll,
  147.         _T("?GXBeginDraw@@YAPAXXZ") );
  148.     GXEndDraw = (void *)GetProcAddress( p_vout->p_sys->gapi_dll,
  149.         _T("?GXEndDraw@@YAHXZ") );
  150.     GXGetDisplayProperties = (void *)GetProcAddress( p_vout->p_sys->gapi_dll,
  151.         _T("?GXGetDisplayProperties@@YA?AUGXDisplayProperties@@XZ") );
  152.     GXSuspend = (void *)GetProcAddress( p_vout->p_sys->gapi_dll,
  153.         _T("?GXSuspend@@YAHXZ") );
  154.     GXResume = GetProcAddress( p_vout->p_sys->gapi_dll,
  155.         _T("?GXResume@@YAHXZ") );
  156.     if( !GXOpenDisplay || !GXCloseDisplay || !GXBeginDraw || !GXEndDraw ||
  157.         !GXGetDisplayProperties || !GXSuspend || !GXResume )
  158.     {
  159.         msg_Err( p_vout, "failed GetProcAddress on gapi.dll" );
  160.         free( p_vout->p_sys );
  161.         return VLC_EGENERIC;
  162.     }
  163.     msg_Dbg( p_vout, "GAPI DLL loaded" );
  164.     p_vout->p_sys->render_width = p_vout->render.i_width;
  165.     p_vout->p_sys->render_height = p_vout->render.i_height;
  166. #endif
  167.     p_vout->p_sys->p_event = (vlc_object_t *)
  168.         vlc_object_create( p_vout, sizeof( vlc_object_t ) );
  169.     if( !p_vout->p_sys->p_event )
  170.     {
  171.         free( p_vout->p_sys );
  172.         return VLC_ENOMEM;
  173.     }
  174.     p_vout->pf_init = Init;
  175.     p_vout->pf_end = End;
  176.     p_vout->pf_manage = Manage;
  177.     p_vout->pf_render = Render;
  178. #ifdef MODULE_NAME_IS_wingapi
  179.     p_vout->pf_display = FirstDisplayGAPI;
  180.     p_vout->p_sys->b_focus = 0;
  181.     p_vout->p_sys->b_parent_focus = 0;
  182. #else
  183.     p_vout->pf_display = FirstDisplayGDI;
  184. #endif
  185.     p_vout->p_sys->hwnd = p_vout->p_sys->hvideownd = NULL;
  186.     p_vout->p_sys->hparent = p_vout->p_sys->hfswnd = NULL;
  187.     p_vout->p_sys->i_changes = 0;
  188.     vlc_mutex_init( &p_vout->p_sys->lock );
  189.     SetRectEmpty( &p_vout->p_sys->rect_display );
  190.     SetRectEmpty( &p_vout->p_sys->rect_parent );
  191.     var_Create( p_vout, "video-title", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
  192.     var_Create( p_vout, "disable-screensaver", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
  193.     p_vout->p_sys->b_cursor_hidden = 0;
  194.     p_vout->p_sys->i_lastmoved = mdate();
  195.     p_vout->p_sys->i_mouse_hide_timeout =
  196.         var_GetInteger(p_vout, "mouse-hide-timeout") * 1000;
  197.     /* Set main window's size */
  198.     p_vout->p_sys->i_window_width = p_vout->i_window_width;
  199.     p_vout->p_sys->i_window_height = p_vout->i_window_height;
  200.     /* Create the EventThread, this thread is created by us to isolate
  201.      * the Win32 PeekMessage function calls. We want to do this because
  202.      * Windows can stay blocked inside this call for a long time, and when
  203.      * this happens it thus blocks vlc's video_output thread.
  204.      * Vout EventThread will take care of the creation of the video
  205.      * window (because PeekMessage has to be called from the same thread which
  206.      * created the window). */
  207.     msg_Dbg( p_vout, "creating Vout EventThread" );
  208.     p_vout->p_sys->p_event =
  209.         vlc_object_create( p_vout, sizeof(event_thread_t) );
  210.     p_vout->p_sys->p_event->p_vout = p_vout;
  211.     p_vout->p_sys->p_event->window_ready = CreateEvent( NULL, TRUE, FALSE, NULL );
  212.     if( vlc_thread_create( p_vout->p_sys->p_event, "Vout Events Thread",
  213.                            EventThread, 0 ) )
  214.     {
  215.         msg_Err( p_vout, "cannot create Vout EventThread" );
  216.         CloseHandle( p_vout->p_sys->p_event->window_ready );
  217.         vlc_object_release( p_vout->p_sys->p_event );
  218.         p_vout->p_sys->p_event = NULL;
  219.         goto error;
  220.     }
  221.     WaitForSingleObject( p_vout->p_sys->p_event->window_ready, INFINITE );
  222.     CloseHandle( p_vout->p_sys->p_event->window_ready );
  223.     if( p_vout->p_sys->p_event->b_error )
  224.     {
  225.         msg_Err( p_vout, "Vout EventThread failed" );
  226.         goto error;
  227.     }
  228.     vlc_object_attach( p_vout->p_sys->p_event, p_vout );
  229.     msg_Dbg( p_vout, "Vout EventThread running" );
  230. #ifndef UNDER_CE
  231.     /* Variable to indicate if the window should be on top of others */
  232.     /* Trigger a callback right now */
  233.     var_TriggerCallback( p_vout, "video-on-top" );
  234.     /* disable screensaver by temporarily changing system settings */
  235.     p_vout->p_sys->i_spi_lowpowertimeout = 0;
  236.     p_vout->p_sys->i_spi_powerofftimeout = 0;
  237.     p_vout->p_sys->i_spi_screensavetimeout = 0;
  238.     if( var_GetBool( p_vout, "disable-screensaver" ) ) {
  239.         msg_Dbg(p_vout, "disabling screen saver");
  240.         SystemParametersInfo(SPI_GETLOWPOWERTIMEOUT,
  241.             0, &(p_vout->p_sys->i_spi_lowpowertimeout), 0);
  242.         if( 0 != p_vout->p_sys->i_spi_lowpowertimeout ) {
  243.             SystemParametersInfo(SPI_SETLOWPOWERTIMEOUT, 0, NULL, 0);
  244.         }
  245.         SystemParametersInfo(SPI_GETPOWEROFFTIMEOUT, 0,
  246.             &(p_vout->p_sys->i_spi_powerofftimeout), 0);
  247.         if( 0 != p_vout->p_sys->i_spi_powerofftimeout ) {
  248.             SystemParametersInfo(SPI_SETPOWEROFFTIMEOUT, 0, NULL, 0);
  249.         }
  250.         SystemParametersInfo(SPI_GETSCREENSAVETIMEOUT, 0,
  251.             &(p_vout->p_sys->i_spi_screensavetimeout), 0);
  252.         if( 0 != p_vout->p_sys->i_spi_screensavetimeout ) {
  253.             SystemParametersInfo(SPI_SETSCREENSAVETIMEOUT, 0, NULL, 0);
  254.         }
  255.     }
  256. #endif
  257.     return VLC_SUCCESS;
  258. error:
  259.     CloseVideo( VLC_OBJECT(p_vout) );
  260.     return VLC_EGENERIC;
  261. }
  262. /*****************************************************************************
  263.  * CloseVideo: deactivate the GDI video output
  264.  *****************************************************************************/
  265. static void CloseVideo ( vlc_object_t *p_this )
  266. {
  267.     vout_thread_t * p_vout = (vout_thread_t *)p_this;
  268.     if( p_vout->b_fullscreen )
  269.     {
  270.         msg_Dbg( p_vout, "Quitting fullscreen" );
  271.         Win32ToggleFullscreen( p_vout );
  272.         /* Force fullscreen in the core for the next video */
  273.         var_SetBool( p_vout, "fullscreen", true );
  274.     }
  275.     if( p_vout->p_sys->p_event )
  276.     {
  277.         vlc_object_detach( p_vout->p_sys->p_event );
  278.         /* Kill Vout EventThread */
  279.         vlc_object_kill( p_vout->p_sys->p_event );
  280.         /* we need to be sure Vout EventThread won't stay stuck in
  281.          * GetMessage, so we send a fake message */
  282.         if( p_vout->p_sys->hwnd )
  283.         {
  284.             PostMessage( p_vout->p_sys->hwnd, WM_NULL, 0, 0);
  285.         }
  286.         vlc_thread_join( p_vout->p_sys->p_event );
  287.         vlc_object_release( p_vout->p_sys->p_event );
  288.     }
  289.     vlc_mutex_destroy( &p_vout->p_sys->lock );
  290. #ifndef UNDER_CE
  291.     /* restore screensaver system settings */
  292.     if( 0 != p_vout->p_sys->i_spi_lowpowertimeout ) {
  293.         SystemParametersInfo(SPI_SETLOWPOWERTIMEOUT,
  294.             p_vout->p_sys->i_spi_lowpowertimeout, NULL, 0);
  295.     }
  296.     if( 0 != p_vout->p_sys->i_spi_powerofftimeout ) {
  297.         SystemParametersInfo(SPI_SETPOWEROFFTIMEOUT,
  298.             p_vout->p_sys->i_spi_powerofftimeout, NULL, 0);
  299.     }
  300.     if( 0 != p_vout->p_sys->i_spi_screensavetimeout ) {
  301.         SystemParametersInfo(SPI_SETSCREENSAVETIMEOUT,
  302.             p_vout->p_sys->i_spi_screensavetimeout, NULL, 0);
  303.     }
  304. #endif
  305. #ifdef MODULE_NAME_IS_wingapi
  306.     FreeLibrary( p_vout->p_sys->gapi_dll );
  307. #endif
  308.     free( p_vout->p_sys );
  309.     p_vout->p_sys = NULL;
  310. }
  311. /*****************************************************************************
  312.  * Init: initialize video thread output method
  313.  *****************************************************************************/
  314. static int Init( vout_thread_t *p_vout )
  315. {
  316.     picture_t *p_pic;
  317.     /* Initialize offscreen buffer */
  318.     InitBuffers( p_vout );
  319.     p_vout->p_sys->rect_display.left = 0;
  320.     p_vout->p_sys->rect_display.top = 0;
  321.     p_vout->p_sys->rect_display.right  = GetSystemMetrics(SM_CXSCREEN);
  322.     p_vout->p_sys->rect_display.bottom = GetSystemMetrics(SM_CYSCREEN);
  323.     I_OUTPUTPICTURES = 0;
  324.     /* Initialize the output structure */
  325.     switch( p_vout->p_sys->i_depth )
  326.     {
  327.     case 8:
  328.         p_vout->output.i_chroma = VLC_FOURCC('R','G','B','2');
  329.         p_vout->output.pf_setpalette = SetPalette;
  330.         break;
  331.     case 15:
  332.         p_vout->output.i_chroma = VLC_FOURCC('R','V','1','5');
  333.         p_vout->output.i_rmask  = 0x7c00;
  334.         p_vout->output.i_gmask  = 0x03e0;
  335.         p_vout->output.i_bmask  = 0x001f;
  336.         break;
  337.     case 16:
  338.         p_vout->output.i_chroma = VLC_FOURCC('R','V','1','6');
  339.         p_vout->output.i_rmask  = 0xf800;
  340.         p_vout->output.i_gmask  = 0x07e0;
  341.         p_vout->output.i_bmask  = 0x001f;
  342.         break;
  343.     case 24:
  344.         p_vout->output.i_chroma = VLC_FOURCC('R','V','2','4');
  345.         p_vout->output.i_rmask  = 0x00ff0000;
  346.         p_vout->output.i_gmask  = 0x0000ff00;
  347.         p_vout->output.i_bmask  = 0x000000ff;
  348.         break;
  349.     case 32:
  350.         p_vout->output.i_chroma = VLC_FOURCC('R','V','3','2');
  351.         p_vout->output.i_rmask  = 0x00ff0000;
  352.         p_vout->output.i_gmask  = 0x0000ff00;
  353.         p_vout->output.i_bmask  = 0x000000ff;
  354.         break;
  355.     default:
  356.         msg_Err( p_vout, "screen depth %i not supported",
  357.                  p_vout->p_sys->i_depth );
  358.         return VLC_EGENERIC;
  359.         break;
  360.     }
  361.     p_pic = &p_vout->p_picture[0];
  362. #ifdef MODULE_NAME_IS_wingapi
  363.     p_vout->output.i_width  = 0;
  364.     p_vout->output.i_height = 0;
  365.     p_pic->pf_lock  = GAPILockSurface;
  366.     p_pic->pf_unlock = GAPIUnlockSurface;
  367.     Manage( p_vout );
  368.     GAPILockSurface( p_vout, p_pic );
  369.     p_vout->i_changes = 0;
  370.     p_vout->output.i_width  = p_vout->p_sys->render_width;
  371.     p_vout->output.i_height = p_vout->p_sys->render_height;
  372. #else
  373.     p_vout->output.i_width  = p_vout->render.i_width;
  374.     p_vout->output.i_height = p_vout->render.i_height;
  375.     p_vout->fmt_out = p_vout->fmt_in;
  376.     p_vout->fmt_out.i_chroma = p_vout->output.i_chroma;
  377. #endif
  378.     p_vout->output.i_aspect = p_vout->render.i_aspect;
  379.     p_pic->p->p_pixels = p_vout->p_sys->p_pic_buffer;
  380.     p_pic->p->i_lines = p_vout->output.i_height;
  381.     p_pic->p->i_visible_lines = p_vout->output.i_height;
  382.     p_pic->p->i_pitch = p_vout->p_sys->i_pic_pitch;
  383.     p_pic->p->i_pixel_pitch = p_vout->p_sys->i_pic_pixel_pitch;
  384.     p_pic->p->i_visible_pitch = p_vout->output.i_width *
  385.         p_pic->p->i_pixel_pitch;
  386.     p_pic->i_planes = 1;
  387.     p_pic->i_status = DESTROYED_PICTURE;
  388.     p_pic->i_type   = DIRECT_PICTURE;
  389.     PP_OUTPUTPICTURE[ I_OUTPUTPICTURES++ ] = p_pic;
  390.     /* Change the window title bar text */
  391.     PostMessage( p_vout->p_sys->hwnd, WM_VLC_CHANGE_TEXT, 0, 0 );
  392.     UpdateRects( p_vout, true );
  393.     return VLC_SUCCESS;
  394. }
  395. /*****************************************************************************
  396.  * End: terminate video thread output method
  397.  *****************************************************************************/
  398. static void End( vout_thread_t *p_vout )
  399. {
  400. #ifdef MODULE_NAME_IS_wingapi
  401.     GXCloseDisplay();
  402. #else
  403.     DeleteDC( p_vout->p_sys->off_dc );
  404.     DeleteObject( p_vout->p_sys->off_bitmap );
  405. #endif
  406. }
  407. /*****************************************************************************
  408.  * Manage: handle events
  409.  *****************************************************************************
  410.  * This function should be called regularly by video output thread. It manages
  411.  * console events. It returns a non null value on error.
  412.  *****************************************************************************/
  413. static int Manage( vout_thread_t *p_vout )
  414. {
  415.     /* If we do not control our window, we check for geometry changes
  416.      * ourselves because the parent might not send us its events. */
  417.     vlc_mutex_lock( &p_vout->p_sys->lock );
  418.     if( p_vout->p_sys->hparent && !p_vout->b_fullscreen )
  419.     {
  420.         RECT rect_parent;
  421.         POINT point;
  422.         vlc_mutex_unlock( &p_vout->p_sys->lock );
  423.         GetClientRect( p_vout->p_sys->hparent, &rect_parent );
  424.         point.x = point.y = 0;
  425.         ClientToScreen( p_vout->p_sys->hparent, &point );
  426.         OffsetRect( &rect_parent, point.x, point.y );
  427.         if( !EqualRect( &rect_parent, &p_vout->p_sys->rect_parent ) )
  428.         {
  429.             int i_x, i_y, i_width, i_height;
  430.             p_vout->p_sys->rect_parent = rect_parent;
  431.             /* This one is to force the update even if only
  432.              * the position has changed */
  433.             SetWindowPos( p_vout->p_sys->hwnd, 0, 1, 1,
  434.                           rect_parent.right - rect_parent.left,
  435.                           rect_parent.bottom - rect_parent.top, 0 );
  436.             SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0,
  437.                           rect_parent.right - rect_parent.left,
  438.                           rect_parent.bottom - rect_parent.top, 0 );
  439.             vout_PlacePicture( p_vout, rect_parent.right - rect_parent.left,
  440.                                rect_parent.bottom - rect_parent.top,
  441.                                &i_x, &i_y, &i_width, &i_height );
  442.             SetWindowPos( p_vout->p_sys->hvideownd, HWND_TOP,
  443.                           i_x, i_y, i_width, i_height, 0 );
  444.         }
  445.     }
  446.     else
  447.     {
  448.         vlc_mutex_unlock( &p_vout->p_sys->lock );
  449.     }
  450.     /* autoscale toggle */
  451.     if( p_vout->i_changes & VOUT_SCALE_CHANGE )
  452.     {
  453.         p_vout->i_changes &= ~VOUT_SCALE_CHANGE;
  454.         p_vout->b_autoscale = var_GetBool( p_vout, "autoscale" );
  455.         p_vout->i_zoom = (int) ZOOM_FP_FACTOR;
  456.         UpdateRects( p_vout, true );
  457.     }
  458.     /* scaling factor */
  459.     if( p_vout->i_changes & VOUT_ZOOM_CHANGE )
  460.     {
  461.         p_vout->i_changes &= ~VOUT_ZOOM_CHANGE;
  462.         p_vout->b_autoscale = false;
  463.         p_vout->i_zoom =
  464.             (int)( ZOOM_FP_FACTOR * var_GetFloat( p_vout, "scale" ) );
  465.         UpdateRects( p_vout, true );
  466.     }
  467.     /* Check for cropping / aspect changes */
  468.     if( p_vout->i_changes & VOUT_CROP_CHANGE ||
  469.         p_vout->i_changes & VOUT_ASPECT_CHANGE )
  470.     {
  471.         p_vout->i_changes &= ~VOUT_CROP_CHANGE;
  472.         p_vout->i_changes &= ~VOUT_ASPECT_CHANGE;
  473.         p_vout->fmt_out.i_x_offset = p_vout->fmt_in.i_x_offset;
  474.         p_vout->fmt_out.i_y_offset = p_vout->fmt_in.i_y_offset;
  475.         p_vout->fmt_out.i_visible_width = p_vout->fmt_in.i_visible_width;
  476.         p_vout->fmt_out.i_visible_height = p_vout->fmt_in.i_visible_height;
  477.         p_vout->fmt_out.i_aspect = p_vout->fmt_in.i_aspect;
  478.         p_vout->fmt_out.i_sar_num = p_vout->fmt_in.i_sar_num;
  479.         p_vout->fmt_out.i_sar_den = p_vout->fmt_in.i_sar_den;
  480.         p_vout->output.i_aspect = p_vout->fmt_in.i_aspect;
  481.         UpdateRects( p_vout, true );
  482.     }
  483.     /*
  484.      * Position Change
  485.      */
  486.     if( p_vout->p_sys->i_changes & DX_POSITION_CHANGE )
  487.     {
  488.         p_vout->p_sys->i_changes &= ~DX_POSITION_CHANGE;
  489.     }
  490.     /* We used to call the Win32 PeekMessage function here to read the window
  491.      * messages. But since window can stay blocked into this function for a
  492.      * long time (for example when you move your window on the screen), I
  493.      * decided to isolate PeekMessage in another thread. */
  494.     /*
  495.      * Fullscreen change
  496.      */
  497.     if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE
  498.         || p_vout->p_sys->i_changes & VOUT_FULLSCREEN_CHANGE )
  499.     {
  500.         Win32ToggleFullscreen( p_vout );
  501.         p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
  502.         p_vout->p_sys->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
  503.     }
  504.     /*
  505.      * Pointer change
  506.      */
  507.     if( p_vout->b_fullscreen && !p_vout->p_sys->b_cursor_hidden &&
  508.         (mdate() - p_vout->p_sys->i_lastmoved) >
  509.             p_vout->p_sys->i_mouse_hide_timeout )
  510.     {
  511.         POINT point;
  512.         HWND hwnd;
  513.         /* Hide the cursor only if it is inside our window */
  514.         GetCursorPos( &point );
  515.         hwnd = WindowFromPoint(point);
  516.         if( hwnd == p_vout->p_sys->hwnd || hwnd == p_vout->p_sys->hvideownd )
  517.         {
  518.             PostMessage( p_vout->p_sys->hwnd, WM_VLC_HIDE_MOUSE, 0, 0 );
  519.         }
  520.         else
  521.         {
  522.             p_vout->p_sys->i_lastmoved = mdate();
  523.         }
  524.     }
  525.     /*
  526.      * "Always on top" status change
  527.      */
  528.     if( p_vout->p_sys->b_on_top_change )
  529.     {
  530.         vlc_value_t val;
  531.         HMENU hMenu = GetSystemMenu( p_vout->p_sys->hwnd, FALSE );
  532.         var_Get( p_vout, "video-on-top", &val );
  533.         /* Set the window on top if necessary */
  534.         if( val.b_bool && !( GetWindowLong( p_vout->p_sys->hwnd, GWL_EXSTYLE )
  535.                            & WS_EX_TOPMOST ) )
  536.         {
  537.             CheckMenuItem( hMenu, IDM_TOGGLE_ON_TOP,
  538.                            MF_BYCOMMAND | MFS_CHECKED );
  539.             SetWindowPos( p_vout->p_sys->hwnd, HWND_TOPMOST, 0, 0, 0, 0,
  540.                           SWP_NOSIZE | SWP_NOMOVE );
  541.         }
  542.         else
  543.         /* The window shouldn't be on top */
  544.         if( !val.b_bool && ( GetWindowLong( p_vout->p_sys->hwnd, GWL_EXSTYLE )
  545.                            & WS_EX_TOPMOST ) )
  546.         {
  547.             CheckMenuItem( hMenu, IDM_TOGGLE_ON_TOP,
  548.                            MF_BYCOMMAND | MFS_UNCHECKED );
  549.             SetWindowPos( p_vout->p_sys->hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
  550.                           SWP_NOSIZE | SWP_NOMOVE );
  551.         }
  552.         p_vout->p_sys->b_on_top_change = false;
  553.     }
  554.     /* Check if the event thread is still running */
  555.     if( !vlc_object_alive (p_vout->p_sys->p_event) )
  556.     {
  557.         return VLC_EGENERIC; /* exit */
  558.     }
  559.     return VLC_SUCCESS;
  560. }
  561. /*****************************************************************************
  562.  * Render: render previously calculated output
  563.  *****************************************************************************/
  564. static void Render( vout_thread_t *p_vout, picture_t *p_pic )
  565. {
  566.     /* No need to do anything, the fake direct buffers stay as they are */
  567.     (void)p_vout;
  568.     (void)p_pic;
  569. }
  570. /*****************************************************************************
  571.  * Display: displays previously rendered output
  572.  *****************************************************************************/
  573. #define rect_src p_vout->p_sys->rect_src
  574. #define rect_src_clipped p_vout->p_sys->rect_src_clipped
  575. #define rect_dest p_vout->p_sys->rect_dest
  576. #define rect_dest_clipped p_vout->p_sys->rect_dest_clipped
  577. #ifndef MODULE_NAME_IS_wingapi
  578. static void DisplayGDI( vout_thread_t *p_vout, picture_t *p_pic )
  579. {
  580.     vout_sys_t *p_sys = p_vout->p_sys;
  581.     RECT rect_dst = rect_dest_clipped;
  582.     HDC hdc = GetDC( p_sys->hvideownd );
  583.     OffsetRect( &rect_dst, -rect_dest.left, -rect_dest.top );
  584.     SelectObject( p_sys->off_dc, p_sys->off_bitmap );
  585.     if( rect_dest_clipped.right - rect_dest_clipped.left !=
  586.         rect_src_clipped.right - rect_src_clipped.left ||
  587.         rect_dest_clipped.bottom - rect_dest_clipped.top !=
  588.         rect_src_clipped.bottom - rect_src_clipped.top )
  589.     {
  590.         StretchBlt( hdc, rect_dst.left, rect_dst.top,
  591.                     rect_dst.right, rect_dst.bottom,
  592.                     p_sys->off_dc, rect_src_clipped.left, rect_src_clipped.top,
  593.                     rect_src_clipped.right, rect_src_clipped.bottom, SRCCOPY );
  594.     }
  595.     else
  596.     {
  597.         BitBlt( hdc, rect_dst.left, rect_dst.top,
  598.                 rect_dst.right, rect_dst.bottom,
  599.                 p_sys->off_dc, rect_src_clipped.left,
  600.                 rect_src_clipped.top, SRCCOPY );
  601.     }
  602.     ReleaseDC( p_sys->hvideownd, hdc );
  603. }
  604. static void FirstDisplayGDI( vout_thread_t *p_vout, picture_t *p_pic )
  605. {
  606.     /*
  607.     ** Video window is initially hidden, show it now since we got a
  608.     ** picture to show.
  609.     */
  610.     SetWindowPos( p_vout->p_sys->hvideownd, 0, 0, 0, 0, 0,
  611.         SWP_ASYNCWINDOWPOS|
  612.         SWP_FRAMECHANGED|
  613.         SWP_SHOWWINDOW|
  614.         SWP_NOMOVE|
  615.         SWP_NOSIZE|
  616.         SWP_NOZORDER );
  617.     /* get initial picture presented */
  618.     DisplayGDI(p_vout, p_pic);
  619.     /* use and restores proper display function for further pictures */
  620.     p_vout->pf_display = DisplayGDI;
  621. }
  622. #else
  623. static int GAPILockSurface( vout_thread_t *p_vout, picture_t *p_pic )
  624. {
  625.     vout_sys_t *p_sys = p_vout->p_sys;
  626.     int i_x, i_y, i_width, i_height;
  627.     RECT video_rect;
  628.     POINT point;
  629.     GetClientRect( p_sys->hwnd, &video_rect);
  630.     vout_PlacePicture( p_vout, video_rect.right - video_rect.left,
  631.                        video_rect.bottom - video_rect.top,
  632.                        &i_x, &i_y, &i_width, &i_height );
  633.     point.x = point.y = 0;
  634.     ClientToScreen( p_sys->hwnd, &point );
  635.     i_x += point.x + video_rect.left;
  636.     i_y += point.y + video_rect.top;
  637.     if( i_width != p_vout->output.i_width ||
  638.         i_height != p_vout->output.i_height )
  639.     {
  640.         GXDisplayProperties gxdisplayprop = GXGetDisplayProperties();
  641.         p_sys->render_width = i_width;
  642.         p_sys->render_height = i_height;
  643.         p_vout->i_changes |= VOUT_SIZE_CHANGE;
  644.         msg_Dbg( p_vout, "vout size change (%ix%i -> %ix%i)",
  645.                  i_width, i_height, p_vout->output.i_width,
  646.                  p_vout->output.i_height );
  647.         p_vout->p_sys->i_pic_pixel_pitch = gxdisplayprop.cbxPitch;
  648.         p_vout->p_sys->i_pic_pitch = gxdisplayprop.cbyPitch;
  649.         return VLC_EGENERIC;
  650.     }
  651.     else
  652.     {
  653.         GXDisplayProperties gxdisplayprop;
  654.         RECT display_rect, dest_rect;
  655.         uint8_t *p_dest, *p_src = p_pic->p->p_pixels;
  656.         video_rect.left = i_x; video_rect.top = i_y;
  657.         video_rect.right = i_x + i_width;
  658.         video_rect.bottom = i_y + i_height;
  659.         gxdisplayprop = GXGetDisplayProperties();
  660.         display_rect.left = 0; display_rect.top = 0;
  661.         display_rect.right = gxdisplayprop.cxWidth;
  662.         display_rect.bottom = gxdisplayprop.cyHeight;
  663.         if( !IntersectRect( &dest_rect, &video_rect, &display_rect ) )
  664.         {
  665.             return VLC_EGENERIC;
  666.         }
  667. #if 0
  668.         msg_Err( p_vout, "video (%d,%d,%d,%d) display (%d,%d,%d,%d) "
  669.                  "dest (%d,%d,%d,%d)",
  670.                  video_rect.left, video_rect.right,
  671.                  video_rect.top, video_rect.bottom,
  672.                  display_rect.left, display_rect.right,
  673.                  display_rect.top, display_rect.bottom,
  674.                  dest_rect.left, dest_rect.right,
  675.                  dest_rect.top, dest_rect.bottom );
  676. #endif
  677.         if( !(p_dest = GXBeginDraw()) )
  678.         {
  679. #if 0
  680.             msg_Err( p_vout, "GXBeginDraw error %d ", GetLastError() );
  681. #endif
  682.             return VLC_EGENERIC;
  683.         }
  684.         p_src += (dest_rect.left - video_rect.left) * gxdisplayprop.cbxPitch +
  685.             (dest_rect.top - video_rect.top) * p_pic->p->i_pitch;
  686.         p_dest += dest_rect.left * gxdisplayprop.cbxPitch +
  687.             dest_rect.top * gxdisplayprop.cbyPitch;
  688.         i_width = dest_rect.right - dest_rect.left;
  689.         i_height = dest_rect.bottom - dest_rect.top;
  690.         p_pic->p->p_pixels = p_dest;
  691.     }
  692.     return VLC_SUCCESS;
  693. }
  694. static int GAPIUnlockSurface( vout_thread_t *p_vout, picture_t *p_pic )
  695. {
  696.     GXEndDraw();
  697.     return VLC_SUCCESS;
  698. }
  699. static void DisplayGAPI( vout_thread_t *p_vout, picture_t *p_pic )
  700. {
  701. }
  702. static void FirstDisplayGAPI( vout_thread_t *p_vout, picture_t *p_pic )
  703. {
  704.     /* get initial picture presented through D3D */
  705.     DisplayGAPI(p_vout, p_pic);
  706.     /*
  707.     ** Video window is initially hidden, show it now since we got a
  708.     ** picture to show.
  709.     */
  710.     SetWindowPos( p_vout->p_sys->hvideownd, 0, 0, 0, 0, 0,
  711.         SWP_ASYNCWINDOWPOS|
  712.         SWP_FRAMECHANGED|
  713.         SWP_SHOWWINDOW|
  714.         SWP_NOMOVE|
  715.         SWP_NOSIZE|
  716.         SWP_NOZORDER );
  717.     /* use and restores proper display function for further pictures */
  718.     p_vout->pf_display = DisplayGAPI;
  719. }
  720. #endif
  721. #undef rect_src
  722. #undef rect_src_clipped
  723. #undef rect_dest
  724. #undef rect_dest_clipped
  725. /*****************************************************************************
  726.  * SetPalette: sets an 8 bpp palette
  727.  *****************************************************************************/
  728. static void SetPalette( vout_thread_t *p_vout,
  729.                         uint16_t *red, uint16_t *green, uint16_t *blue )
  730. {
  731.     msg_Err( p_vout, "FIXME: SetPalette unimplemented" );
  732. }
  733. /*****************************************************************************
  734.  * InitBuffers: initialize an offscreen bitmap for direct buffer operations.
  735.  *****************************************************************************/
  736. static void InitBuffers( vout_thread_t *p_vout )
  737. {
  738.     BITMAPINFOHEADER *p_header = &p_vout->p_sys->bitmapinfo.bmiHeader;
  739.     BITMAPINFO *p_info = &p_vout->p_sys->bitmapinfo;
  740.     HDC window_dc = GetDC( p_vout->p_sys->hvideownd );
  741.     /* Get screen properties */
  742. #ifdef MODULE_NAME_IS_wingapi
  743.     GXDisplayProperties gx_displayprop = GXGetDisplayProperties();
  744.     p_vout->p_sys->i_depth = gx_displayprop.cBPP;
  745. #else
  746.     p_vout->p_sys->i_depth = GetDeviceCaps( window_dc, PLANES ) *
  747.         GetDeviceCaps( window_dc, BITSPIXEL );
  748. #endif
  749.     msg_Dbg( p_vout, "GDI depth is %i", p_vout->p_sys->i_depth );
  750. #ifdef MODULE_NAME_IS_wingapi
  751.     GXOpenDisplay( p_vout->p_sys->hvideownd, GX_FULLSCREEN );
  752. #else
  753.     /* Initialize offscreen bitmap */
  754.     memset( p_info, 0, sizeof( BITMAPINFO ) + 3 * sizeof( RGBQUAD ) );
  755.     p_header->biSize = sizeof( BITMAPINFOHEADER );
  756.     p_header->biSizeImage = 0;
  757.     p_header->biPlanes = 1;
  758.     switch( p_vout->p_sys->i_depth )
  759.     {
  760.     case 8:
  761.         p_header->biBitCount = 8;
  762.         p_header->biCompression = BI_RGB;
  763.         /* FIXME: we need a palette here */
  764.         break;
  765.     case 15:
  766.         p_header->biBitCount = 15;
  767.         p_header->biCompression = BI_BITFIELDS;//BI_RGB;
  768.         ((DWORD*)p_info->bmiColors)[0] = 0x00007c00;
  769.         ((DWORD*)p_info->bmiColors)[1] = 0x000003e0;
  770.         ((DWORD*)p_info->bmiColors)[2] = 0x0000001f;
  771.         break;
  772.     case 16:
  773.         p_header->biBitCount = 16;
  774.         p_header->biCompression = BI_BITFIELDS;//BI_RGB;
  775.         ((DWORD*)p_info->bmiColors)[0] = 0x0000f800;
  776.         ((DWORD*)p_info->bmiColors)[1] = 0x000007e0;
  777.         ((DWORD*)p_info->bmiColors)[2] = 0x0000001f;
  778.         break;
  779.     case 24:
  780.         p_header->biBitCount = 24;
  781.         p_header->biCompression = BI_RGB;
  782.         ((DWORD*)p_info->bmiColors)[0] = 0x00ff0000;
  783.         ((DWORD*)p_info->bmiColors)[1] = 0x0000ff00;
  784.         ((DWORD*)p_info->bmiColors)[2] = 0x000000ff;
  785.         break;
  786.     case 32:
  787.         p_header->biBitCount = 32;
  788.         p_header->biCompression = BI_RGB;
  789.         ((DWORD*)p_info->bmiColors)[0] = 0x00ff0000;
  790.         ((DWORD*)p_info->bmiColors)[1] = 0x0000ff00;
  791.         ((DWORD*)p_info->bmiColors)[2] = 0x000000ff;
  792.         break;
  793.     default:
  794.         msg_Err( p_vout, "screen depth %i not supported",
  795.                  p_vout->p_sys->i_depth );
  796.         return;
  797.         break;
  798.     }
  799.     p_header->biWidth = p_vout->render.i_width;
  800.     p_header->biHeight = -p_vout->render.i_height;
  801.     p_header->biClrImportant = 0;
  802.     p_header->biClrUsed = 0;
  803.     p_header->biXPelsPerMeter = 0;
  804.     p_header->biYPelsPerMeter = 0;
  805.     p_vout->p_sys->i_pic_pixel_pitch = p_header->biBitCount / 8;
  806.     p_vout->p_sys->i_pic_pitch = p_header->biBitCount * p_header->biWidth / 8;
  807.     p_vout->p_sys->off_bitmap =
  808.         CreateDIBSection( window_dc, (BITMAPINFO *)p_header, DIB_RGB_COLORS,
  809.                           (void**)&p_vout->p_sys->p_pic_buffer, NULL, 0 );
  810.     p_vout->p_sys->off_dc = CreateCompatibleDC( window_dc );
  811.     SelectObject( p_vout->p_sys->off_dc, p_vout->p_sys->off_bitmap );
  812.     ReleaseDC( p_vout->p_sys->hvideownd, window_dc );
  813. #endif
  814. }