Changeset 5db972ab2ed21e8f265bdef23304f2435ba3ea7b

Show
Ignore:
Timestamp:
26/01/05 09:18:46 (4 years ago)
Author:
Gildas Bazin <gbazin@videolan.org>
git-committer:
Gildas Bazin <gbazin@videolan.org> 1106727526 +0000
git-parent:

[47cc1b226d86c821b6dc16b1a21d715f0d043b77]

git-author:
Gildas Bazin <gbazin@videolan.org> 1106727526 +0000
Message:

* modules/video_output/wingdi.c: improvements + embedded support + GAPI support for WinCE. Needs some more work as well for fullscreen support.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • modules/video_output/Modules.am

    r2059d3c r5db972a  
    77SOURCES_svgalib = svgalib.c 
    88SOURCES_wingdi = wingdi.c 
     9SOURCES_gapi = wingdi.c 
    910SOURCES_mga = mga.c 
    1011SOURCES_hd1000v = hd1000v.cpp 
  • modules/video_output/wingdi.c

    r56b5483 r5db972a  
    66 * 
    77 * Authors: Samuel Hocevar <sam@zoy.org> 
     8 *          Gildas Bazin <gbazin@videolan.org> 
    89 * 
    910 * This program is free software; you can redistribute it and/or modify 
     
    3132#include <vlc/vout.h> 
    3233 
     34#include <windows.h> 
    3335#define WIN32_LEAN_AND_MEAN 
    34 #include <windows.h> 
     36 
     37#ifdef UNDER_CE 
     38#   include <aygshell.h> 
     39#   define MENU_HEIGHT 26 
     40#else 
     41#   define SHFS_HIDESIPBUTTON 0 
     42#   define MENU_HEIGHT 0 
     43#   define NM_CUSTOMDRAW 0 
     44#endif 
     45 
     46#undef MODULE_NAME_IS_gapi 
     47#ifdef MODULE_NAME_IS_gapi 
     48    typedef struct GXDisplayProperties { 
     49        DWORD cxWidth; 
     50        DWORD cyHeight; 
     51        long cbxPitch; 
     52        long cbyPitch; 
     53        long cBPP; 
     54        DWORD ffFormat; 
     55    } GXDisplayProperties; 
     56 
     57    typedef struct GXScreenRect { 
     58        DWORD dwTop; 
     59        DWORD dwLeft; 
     60        DWORD dwWidth; 
     61        DWORD dwHeight; 
     62    } GXScreenRect; 
     63 
     64#   define GX_FULLSCREEN    0x01 
     65#   define GX_NORMALKEYS    0x02 
     66#   define GX_LANDSCAPEKEYS 0x03 
     67 
     68#   ifndef kfLandscape 
     69#       define kfLandscape      0x8 
     70#       define kfPalette        0x10 
     71#       define kfDirect         0x20 
     72#       define kfDirect555      0x40 
     73#       define kfDirect565      0x80 
     74#       define kfDirect888      0x100 
     75#       define kfDirect444      0x200 
     76#       define kfDirectInverted 0x400 
     77#   endif 
     78#endif /* MODULE_NAME_IS_gapi */ 
    3579 
    3680#define MAX_DIRECTBUFFERS 10 
    3781 
     82#ifdef UNDER_CE 
     83#ifndef WS_OVERLAPPEDWINDOW 
     84#   define WS_OVERLAPPEDWINDOW 0xcf0000 
     85#endif 
     86#ifndef WS_EX_NOPARENTNOTIFY 
     87#   define WS_EX_NOPARENTNOTIFY 4 
     88#endif 
     89#ifndef WS_EX_APPWINDOW 
     90#define WS_EX_APPWINDOW 0x40000 
     91#endif 
     92#define SetWindowLongPtr SetWindowLong 
     93#define GetWindowLongPtr GetWindowLong 
     94#define GWLP_USERDATA GWL_USERDATA 
     95#endif //UNDER_CE 
     96 
     97#ifndef WS_NONAVDONEBUTTON 
     98#define WS_NONAVDONEBUTTON 0 
     99#endif 
    38100/***************************************************************************** 
    39101 * Local prototypes 
     
    46108static int  Manage    ( vout_thread_t * ); 
    47109static void Render    ( vout_thread_t *, picture_t * ); 
    48 static void Display   ( vout_thread_t *, picture_t * ); 
     110#ifdef MODULE_NAME_IS_gapi 
     111static void DisplayGAPI( vout_thread_t *, picture_t * ); 
     112#else 
     113static void DisplayGDI( vout_thread_t *, picture_t * ); 
     114#endif 
    49115static void SetPalette( vout_thread_t *, uint16_t *, uint16_t *, uint16_t * ); 
    50116 
     
    52118static long FAR PASCAL WndProc ( HWND, UINT, WPARAM, LPARAM ); 
    53119static void InitBuffers        ( vout_thread_t * ); 
     120static void UpdateRects        ( vout_thread_t *, vlc_bool_t ); 
    54121 
    55122/***************************************************************************** 
     
    62129 
    63130    /* Our video output window */ 
    64     HWND window; 
     131    HWND hwnd; 
     132    HWND hvideownd; 
     133    HWND hfswnd; 
    65134    int  i_depth; 
     135    HWND                 hparent;             /* Handle of the parent window */ 
     136    WNDPROC              pf_wndproc;             /* Window handling callback */ 
     137    volatile uint16_t    i_changes;     /* changes made to the video display */ 
     138    RECT window_placement; 
     139 
     140    /* Window position and size */ 
     141    int          i_window_x; 
     142    int          i_window_y; 
     143    int          i_window_width; 
     144    int          i_window_height; 
     145    int          render_width; 
     146    int          render_height; 
     147 
     148    /* Coordinates of src and dest images (used when blitting to display) */ 
     149    RECT         rect_src; 
     150    RECT         rect_src_clipped; 
     151    RECT         rect_dest; 
     152    RECT         rect_dest_clipped; 
     153    RECT         rect_parent; 
     154    RECT         rect_display; 
    66155 
    67156    /* Our offscreen bitmap and its framebuffer */ 
     
    74163    RGBQUAD    green; 
    75164    RGBQUAD    blue; 
     165 
     166    /* WINCE stuff */ 
     167    HWND hMenu; 
     168    HWND hTaskBar; 
     169    vlc_bool_t   b_video_display; 
     170 
     171#ifdef MODULE_NAME_IS_gapi 
     172    HINSTANCE  gapi_dll;                    /* handle of the opened gapi dll */ 
     173 
     174    /* GAPI functions */ 
     175    int (*GXOpenDisplay)( HWND hWnd, DWORD dwFlags ); 
     176    int (*GXCloseDisplay)(); 
     177    void *(*GXBeginDraw)(); 
     178    int (*GXEndDraw)(); 
     179    GXDisplayProperties (*GXGetDisplayProperties)(); 
     180    int (*GXSuspend)(); 
     181    int (*GXResume)(); 
     182#endif 
    76183}; 
    77184 
     185#define GXOpenDisplay p_vout->p_sys->GXOpenDisplay 
     186#define GXCloseDisplay p_vout->p_sys->GXCloseDisplay 
     187#define GXBeginDraw p_vout->p_sys->GXBeginDraw 
     188#define GXEndDraw p_vout->p_sys->GXEndDraw 
     189#define GXGetDisplayProperties p_vout->p_sys->GXGetDisplayProperties 
     190#define GXSuspend p_vout->p_sys->GXSuspend 
     191#define GXResume p_vout->p_sys->GXResume 
     192 
     193#define DX_POSITION_CHANGE 0x1000 
     194 
    78195/***************************************************************************** 
    79196 * Module descriptor 
    80197 *****************************************************************************/ 
    81198vlc_module_begin(); 
     199#ifdef MODULE_NAME_IS_gapi 
     200    set_description( _("Windows GAPI video output") ); 
     201    set_capability( "video output", 20 ); 
     202#else 
    82203    set_description( _("Windows GDI video output") ); 
    83204    set_capability( "video output", 10 ); 
     205#endif 
    84206    set_callbacks( OpenVideo, CloseVideo ); 
    85207vlc_module_end(); 
     
    93215    vlc_value_t val; 
    94216 
    95     p_vout->p_sys = malloc( sizeof(vout_sys_t) ); 
    96     if( !p_vout->p_sys ) 
    97     { 
    98         return VLC_ENOMEM; 
    99     } 
    100  
    101     p_vout->p_sys->p_event = vlc_object_create( p_vout, VLC_OBJECT_GENERIC ); 
     217    p_vout->p_sys = (vout_sys_t *)malloc( sizeof(vout_sys_t) ); 
     218    if( !p_vout->p_sys ) return VLC_ENOMEM; 
     219 
     220#ifdef MODULE_NAME_IS_gapi 
     221    /* Load GAPI */ 
     222    p_vout->p_sys->gapi_dll = LoadLibrary( _T("GX.DLL") ); 
     223    if( p_vout->p_sys->gapi_dll == NULL ) 
     224    { 
     225        msg_Warn( p_vout, "failed loading gx.dll" ); 
     226        free( p_vout->p_sys ); 
     227        return VLC_EGENERIC; 
     228    } 
     229 
     230    GXOpenDisplay = (void *)GetProcAddress( p_vout->p_sys->gapi_dll, 
     231        _T("?GXOpenDisplay@@YAHPAUHWND__@@K@Z") ); 
     232    GXCloseDisplay = (void *)GetProcAddress( p_vout->p_sys->gapi_dll, 
     233        _T("?GXCloseDisplay@@YAHXZ") ); 
     234    GXBeginDraw = (void *)GetProcAddress( p_vout->p_sys->gapi_dll, 
     235        _T("?GXBeginDraw@@YAPAXXZ") ); 
     236    GXEndDraw = (void *)GetProcAddress( p_vout->p_sys->gapi_dll, 
     237        _T("?GXEndDraw@@YAHXZ") ); 
     238    GXGetDisplayProperties = (void *)GetProcAddress( p_vout->p_sys->gapi_dll, 
     239        _T("?GXGetDisplayProperties@@YA?AUGXDisplayProperties@@XZ") ); 
     240    GXSuspend = (void *)GetProcAddress( p_vout->p_sys->gapi_dll, 
     241        _T("?GXSuspend@@YAHXZ") ); 
     242    GXResume = GetProcAddress( p_vout->p_sys->gapi_dll, 
     243        _T("?GXResume@@YAHXZ") ); 
     244 
     245    if( !GXOpenDisplay || !GXCloseDisplay || !GXBeginDraw || !GXEndDraw || 
     246        !GXGetDisplayProperties || !GXSuspend || !GXResume ) 
     247    { 
     248        msg_Err( p_vout, "failed GetProcAddress on gapi.dll" ); 
     249        free( p_vout->p_sys ); 
     250        return VLC_EGENERIC; 
     251    } 
     252 
     253    msg_Dbg( p_vout, "GAPI DLL loaded" ); 
     254 
     255    p_vout->p_sys->render_width = p_vout->render.i_width; 
     256    p_vout->p_sys->render_height = p_vout->render.i_height; 
     257#endif 
     258 
     259    p_vout->p_sys->p_event = (vlc_object_t *) 
     260        vlc_object_create( p_vout, VLC_OBJECT_GENERIC ); 
    102261    if( !p_vout->p_sys->p_event ) 
    103262    { 
     
    109268    val.p_address = (void *)p_vout; 
    110269    var_Set( p_vout->p_sys->p_event, "p_vout", val ); 
     270 
     271    SetRectEmpty( &p_vout->p_sys->rect_display ); 
     272    SetRectEmpty( &p_vout->p_sys->rect_parent ); 
     273 
     274    if( vlc_thread_create( p_vout->p_sys->p_event, "GDI Event Thread", 
     275                           EventThread, 0, 1 ) ) 
     276    { 
     277        msg_Err( p_vout, "cannot spawn EventThread" ); 
     278        return VLC_ETHREAD; 
     279    } 
    111280 
    112281    p_vout->pf_init = Init; 
     
    114283    p_vout->pf_manage = Manage; 
    115284    p_vout->pf_render = Render; 
    116     p_vout->pf_display = Display; 
     285#ifdef MODULE_NAME_IS_gapi 
     286    p_vout->pf_display = DisplayGAPI; 
     287#else 
     288    p_vout->pf_display = DisplayGDI; 
     289#endif 
     290    p_vout->p_sys->i_changes = 0; 
    117291 
    118292    return VLC_SUCCESS; 
     
    125299{ 
    126300    vout_thread_t * p_vout = (vout_thread_t *)p_this; 
     301 
     302#ifdef MODULE_NAME_IS_gapi 
     303    GXCloseDisplay(); 
     304    FreeLibrary( p_vout->p_sys->gapi_dll ); 
     305#endif 
     306 
     307    p_vout->p_sys->p_event->b_die = VLC_TRUE; 
     308    PostMessage( p_vout->p_sys->hwnd, WM_NULL, 0, 0 ); 
     309    vlc_thread_join( p_vout->p_sys->p_event ); 
    127310 
    128311    var_Destroy( p_vout->p_sys->p_event, "p_vout" ); 
     
    139322    picture_t *p_pic; 
    140323 
    141     if( vlc_thread_create( p_vout->p_sys->p_event, "GDI Event Thread", 
    142                            EventThread, 0, 1 ) ) 
    143     { 
    144         msg_Err( p_vout, "cannot spawn EventThread" ); 
    145         return VLC_ETHREAD; 
    146     } 
     324    p_vout->p_sys->rect_display.left = 0; 
     325    p_vout->p_sys->rect_display.top = 0; 
     326    p_vout->p_sys->rect_display.right  = GetSystemMetrics(SM_CXSCREEN); 
     327    p_vout->p_sys->rect_display.bottom = GetSystemMetrics(SM_CYSCREEN); 
     328 
     329    p_vout->p_sys->b_video_display = VLC_TRUE; 
     330    p_vout->p_sys->p_event->b_die = VLC_FALSE; 
    147331 
    148332    I_OUTPUTPICTURES = 0; 
     
    151335    switch( p_vout->p_sys->i_depth ) 
    152336    { 
    153         case 8: 
    154             p_vout->output.i_chroma = VLC_FOURCC('R','G','B','2'); 
    155             p_vout->output.pf_setpalette = SetPalette; 
    156             break; 
    157         case 24: 
    158             p_vout->output.i_chroma = VLC_FOURCC('R','V','2','4'); 
    159             p_vout->output.i_rmask  = 0x00ff0000; 
    160             p_vout->output.i_gmask  = 0x0000ff00; 
    161             p_vout->output.i_bmask  = 0x000000ff; 
    162             break; 
    163         case 32: 
    164             p_vout->output.i_chroma = VLC_FOURCC('R','V','3','2'); 
    165             p_vout->output.i_rmask  = 0x00ff0000; 
    166             p_vout->output.i_gmask  = 0x0000ff00; 
    167             p_vout->output.i_bmask  = 0x000000ff; 
    168             break; 
    169         default: 
    170         case 16: 
    171             p_vout->output.i_chroma = VLC_FOURCC('R','V','1','5'); 
    172             p_vout->output.i_rmask  = 0x7c00; 
    173             p_vout->output.i_gmask  = 0x03e0; 
    174             p_vout->output.i_bmask  = 0x001f; 
    175             break; 
    176     } 
    177  
     337    case 8: 
     338        p_vout->output.i_chroma = VLC_FOURCC('R','G','B','2'); 
     339        p_vout->output.pf_setpalette = SetPalette; 
     340        break; 
     341    case 15: 
     342        p_vout->output.i_chroma = VLC_FOURCC('R','V','1','5'); 
     343        p_vout->output.i_rmask  = 0x7c00; 
     344        p_vout->output.i_gmask  = 0x03e0; 
     345        p_vout->output.i_bmask  = 0x001f; 
     346        break; 
     347    case 16: 
     348        p_vout->output.i_chroma = VLC_FOURCC('R','V','1','6'); 
     349        p_vout->output.i_rmask  = 0xf800; 
     350        p_vout->output.i_gmask  = 0x07e0; 
     351        p_vout->output.i_bmask  = 0x001f; 
     352        break; 
     353    case 24: 
     354        p_vout->output.i_chroma = VLC_FOURCC('R','V','2','4'); 
     355        p_vout->output.i_rmask  = 0x00ff0000; 
     356        p_vout->output.i_gmask  = 0x0000ff00; 
     357        p_vout->output.i_bmask  = 0x000000ff; 
     358        break; 
     359    case 32: 
     360        p_vout->output.i_chroma = VLC_FOURCC('R','V','3','2'); 
     361        p_vout->output.i_rmask  = 0x00ff0000; 
     362        p_vout->output.i_gmask  = 0x0000ff00; 
     363        p_vout->output.i_bmask  = 0x000000ff; 
     364        break; 
     365    default: 
     366        msg_Err( p_vout, "screen depth %i not supported", 
     367                 p_vout->p_sys->i_depth ); 
     368        return VLC_EGENERIC; 
     369        break; 
     370    } 
     371 
     372#ifdef MODULE_NAME_IS_gapi 
     373    p_vout->output.i_width  = p_vout->p_sys->render_width; 
     374    p_vout->output.i_height = p_vout->p_sys->render_height; 
     375#else 
    178376    p_vout->output.i_width  = p_vout->render.i_width; 
    179377    p_vout->output.i_height = p_vout->render.i_height; 
     378#endif 
    180379    p_vout->output.i_aspect = p_vout->render.i_aspect; 
    181380 
     
    196395 
    197396        /* Allocate the picture */ 
    198         if( p_pic == NULL ) 
    199         { 
    200             break; 
    201         } 
    202  
    203         vout_AllocatePicture( p_vout, p_pic, p_vout->output.i_chroma, 
     397        if( p_pic == NULL ) break; 
     398 
     399        vout_AllocatePicture( VLC_OBJECT(p_vout), p_pic, 
     400                              p_vout->output.i_chroma, 
    204401                              p_vout->output.i_width, p_vout->output.i_height, 
    205402                              p_vout->output.i_aspect ); 
    206403 
    207         if( p_pic->i_planes == 0 ) 
    208         { 
    209             break; 
    210         } 
     404        if( p_pic->i_planes == 0 ) break; 
    211405 
    212406        p_pic->i_status = DESTROYED_PICTURE; 
     
    234428        free( PP_OUTPUTPICTURE[ i_index ]->p_data_orig ); 
    235429    } 
    236  
    237     p_vout->p_sys->p_event->b_die = VLC_TRUE; 
    238     PostMessage( p_vout->p_sys->window, WM_NULL, 0, 0 ); 
    239     vlc_thread_join( p_vout->p_sys->p_event ); 
    240430} 
    241431 
     
    248438static int Manage( vout_thread_t *p_vout ) 
    249439{ 
     440#ifndef UNDER_CE 
     441    WINDOWPLACEMENT window_placement; 
     442#endif 
     443 
     444    /* If we do not control our window, we check for geometry changes 
     445     * ourselves because the parent might not send us its events. */ 
     446    if( p_vout->p_sys->hparent && !p_vout->b_fullscreen ) 
     447    { 
     448        RECT rect_parent; 
     449        POINT point; 
     450 
     451        GetClientRect( p_vout->p_sys->hparent, &rect_parent ); 
     452        point.x = point.y = 0; 
     453        ClientToScreen( p_vout->p_sys->hparent, &point ); 
     454        OffsetRect( &rect_parent, point.x, point.y ); 
     455 
     456        if( !EqualRect( &rect_parent, &p_vout->p_sys->rect_parent ) ) 
     457        { 
     458            int i_x, i_y, i_width, i_height; 
     459            p_vout->p_sys->rect_parent = rect_parent; 
     460 
     461            /* This one is to force the update even if only 
     462             * the position has changed */ 
     463            SetWindowPos( p_vout->p_sys->hwnd, 0, 1, 1, 
     464                          rect_parent.right - rect_parent.left, 
     465                          rect_parent.bottom - rect_parent.top, 0 ); 
     466 
     467            SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0, 
     468                          rect_parent.right - rect_parent.left, 
     469                          rect_parent.bottom - rect_parent.top, 0 ); 
     470 
     471            vout_PlacePicture( p_vout, rect_parent.right - rect_parent.left, 
     472                               rect_parent.bottom - rect_parent.top, 
     473                               &i_x, &i_y, &i_width, &i_height ); 
     474 
     475            SetWindowPos( p_vout->p_sys->hvideownd, HWND_TOP, 
     476                          i_x, i_y, i_width, i_height, 0 ); 
     477        } 
     478    } 
     479 
     480    /* We used to call the Win32 PeekMessage function here to read the window 
     481     * messages. But since window can stay blocked into this function for a 
     482     * long time (for example when you move your window on the screen), I 
     483     * decided to isolate PeekMessage in another thread. */ 
     484 
     485    /* 
     486     * Fullscreen change 
     487     */ 
     488    if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE 
     489        || p_vout->p_sys->i_changes & VOUT_FULLSCREEN_CHANGE ) 
     490    { 
     491        int i_style = 0; 
     492        vlc_value_t val; 
     493 
     494        HWND hwnd = (p_vout->p_sys->hparent && p_vout->p_sys->hfswnd) ? 
     495            p_vout->p_sys->hfswnd : p_vout->p_sys->hwnd; 
     496 
     497        p_vout->b_fullscreen = ! p_vout->b_fullscreen; 
     498 
     499        /* We need to switch between Maximized and Normal sized window */ 
     500#ifndef UNDER_CE 
     501        window_placement.length = sizeof(WINDOWPLACEMENT); 
     502        GetWindowPlacement( hwnd, &window_placement ); 
     503#endif 
     504        if( p_vout->b_fullscreen ) 
     505        { 
     506#ifndef UNDER_CE 
     507            /* Change window style, no borders and no title bar */ 
     508            int i_style = WS_CLIPCHILDREN | WS_VISIBLE; 
     509            SetWindowLong( hwnd, GWL_STYLE, i_style ); 
     510 
     511            if( p_vout->p_sys->hparent ) 
     512            { 
     513                /* Retrieve current window position so fullscreen will happen 
     514                 * on the right screen */ 
     515                POINT point = {0,0}; 
     516                RECT rect; 
     517                ClientToScreen( p_vout->p_sys->hwnd, &point ); 
     518                GetClientRect( p_vout->p_sys->hwnd, &rect ); 
     519                SetWindowPos( hwnd, 0, point.x, point.y, 
     520                              rect.right, rect.bottom, 
     521                              SWP_NOZORDER|SWP_FRAMECHANGED ); 
     522                GetWindowPlacement( hwnd, &window_placement ); 
     523            } 
     524 
     525            /* Maximize window */ 
     526            window_placement.showCmd = SW_SHOWMAXIMIZED; 
     527            SetWindowPlacement( hwnd, &window_placement ); 
     528            SetWindowPos( hwnd, 0, 0, 0, 0, 0, 
     529                          SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED); 
     530#endif 
     531 
     532            if( p_vout->p_sys->hparent ) 
     533            { 
     534                RECT rect; 
     535                GetClientRect( hwnd, &rect ); 
     536                SetParent( p_vout->p_sys->hwnd, hwnd ); 
     537                SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0, 
     538                              rect.right, rect.bottom, 
     539                              SWP_NOZORDER|SWP_FRAMECHANGED ); 
     540            } 
     541 
     542            ShowWindow( hwnd, SW_SHOW ); 
     543            SetForegroundWindow( hwnd ); 
     544        } 
     545        else 
     546        { 
     547            /* Change window style, no borders and no title bar */ 
     548            //SetWindowLong( hwnd, GWL_STYLE, p_vout->p_sys->i_window_style ); 
     549 
     550#ifndef UNDER_CE 
     551            /* Normal window */ 
     552            window_placement.showCmd = SW_SHOWNORMAL; 
     553            SetWindowPlacement( hwnd, &window_placement ); 
     554            SetWindowPos( hwnd, 0, 0, 0, 0, 0, 
     555                          SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED); 
     556#endif 
     557 
     558            if( p_vout->p_sys->hparent ) 
     559            { 
     560                RECT rect; 
     561                GetClientRect( p_vout->p_sys->hparent, &rect ); 
     562                SetParent( p_vout->p_sys->hwnd, p_vout->p_sys->hparent ); 
     563                SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0, 
     564                              rect.right, rect.bottom, 
     565                              SWP_NOZORDER|SWP_FRAMECHANGED ); 
     566 
     567                ShowWindow( hwnd, SW_HIDE ); 
     568                SetForegroundWindow( p_vout->p_sys->hparent ); 
     569            } 
     570 
     571            /* Make sure the mouse cursor is displayed */ 
     572            //PostMessage( p_vout->p_sys->hwnd, WM_VLC_SHOW_MOUSE, 0, 0 ); 
     573        } 
     574 
     575#ifdef MODULE_NAME_IS_gapi 
     576        GXCloseDisplay(); 
     577#endif 
     578 
     579        /* Change window style, borders and title bar */ 
     580        ShowWindow( p_vout->p_sys->hwnd, SW_SHOW ); 
     581        UpdateWindow( p_vout->p_sys->hwnd ); 
     582 
     583#ifdef MODULE_NAME_IS_gapi 
     584        GXOpenDisplay( p_vout->p_sys->hvideownd, GX_FULLSCREEN ); 
     585#endif 
     586 
     587        /* Update the object variable and trigger callback */ 
     588        val.b_bool = p_vout->b_fullscreen; 
     589        var_Set( p_vout, "fullscreen", val ); 
     590 
     591        p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE; 
     592        p_vout->p_sys->i_changes &= ~VOUT_FULLSCREEN_CHANGE; 
     593    } 
     594 
    250595    return VLC_SUCCESS; 
    251596} 
     
    262607 * Display: displays previously rendered output 
    263608 *****************************************************************************/ 
    264 static void Display( vout_thread_t *p_vout, picture_t *p_pic ) 
    265 
    266     /* No need to do anything, the fake direct buffers stay as they are */ 
    267     HDC hdc; 
     609#define rect_src p_vout->p_sys->rect_src 
     610#define rect_src_clipped p_vout->p_sys->rect_src_clipped 
     611#define rect_dest p_vout->p_sys->rect_dest 
     612#define rect_dest_clipped p_vout->p_sys->rect_dest_clipped 
     613 
     614#ifndef MODULE_NAME_IS_gapi 
     615static void DisplayGDI( vout_thread_t *p_vout, picture_t *p_pic ) 
     616
     617    vout_sys_t *p_sys = p_vout->p_sys; 
    268618    int i_src_bytes, i_dest_bytes; 
    269  
    270     hdc = GetDC( p_vout->p_sys->window ); 
    271     SelectObject( p_vout->p_sys->off_dc, p_vout->p_sys->off_bitmap ); 
    272  
     619    RECT rect_dst = rect_dest_clipped; 
     620    HDC hdc = GetDC( p_sys->hvideownd ); 
     621 
     622    OffsetRect( &rect_dst, -rect_dest.left, -rect_dest.top ); 
     623    SelectObject( p_sys->off_dc, p_sys->off_bitmap ); 
     624 
     625#if 1 
    273626    /* Stupid GDI is upside-down */ 
    274     i_src_bytes = p_pic->p->i_visible_lines * p_pic->p->i_pitch; 
     627    i_src_bytes = p_pic->p->i_lines * p_pic->p->i_pitch; 
    275628    i_dest_bytes = 0; 
    276629 
     
    279632        i_src_bytes -= p_pic->p->i_pitch; 
    280633 
    281         p_vout->p_vlc->pf_memcpy( p_vout->p_sys->p_buffer + i_dest_bytes, 
     634        p_vout->p_vlc->pf_memcpy( p_sys->p_buffer + i_dest_bytes, 
    282635                                  p_pic->p->p_pixels + i_src_bytes, 
    283636                                  p_pic->p->i_visible_pitch ); 
     
    285638        i_dest_bytes += p_pic->p->i_pitch; 
    286639    } 
    287  
    288     BitBlt( hdc, 0, 0, p_vout->output.i_width, p_vout->output.i_height, 
    289             p_vout->p_sys->off_dc, 0, 0, SRCCOPY ); 
    290  
    291     ReleaseDC( p_vout->p_sys->window, hdc ); 
     640#endif 
     641 
     642    if( rect_dest_clipped.right - rect_dest_clipped.left != 
     643        rect_src_clipped.right - rect_src_clipped.left || 
     644        rect_dest_clipped.bottom - rect_dest_clipped.top != 
     645        rect_src_clipped.bottom - rect_src_clipped.top ) 
     646    { 
     647        StretchBlt( hdc, rect_dst.left, rect_dst.top, 
     648                    rect_dst.right, rect_dst.bottom, 
     649                    p_sys->off_dc, rect_src_clipped.left, rect_src_clipped.top, 
     650                    rect_src_clipped.right, rect_src_clipped.bottom, SRCCOPY ); 
     651    } 
     652    else 
     653    { 
     654        BitBlt( hdc, rect_dst.left, rect_dst.top, 
     655                rect_dst.right, rect_dst.bottom, 
     656                p_sys->off_dc, rect_src_clipped.left, 
     657                rect_src_clipped.top, SRCCOPY ); 
     658    } 
     659 
     660    ReleaseDC( p_sys->hwnd, hdc ); 
    292661} 
    293  
     662#else 
     663 
     664static void DisplayGAPI( vout_thread_t *p_vout, picture_t *p_pic ) 
     665
     666    vout_sys_t *p_sys = p_vout->p_sys; 
     667    int i_x, i_y, i_width, i_height; 
     668    RECT video_rect; 
     669    POINT point; 
     670 
     671    /* Undo the display */ 
     672    if( ( GetForegroundWindow() != GetParent(p_sys->hwnd) ) || 
     673        ( p_sys->b_video_display == VLC_FALSE ) ) 
     674    { 
     675        return; 
     676    } 
     677 
     678    GetClientRect( p_sys->hwnd, &video_rect); 
     679    vout_PlacePicture( p_vout, video_rect.right - video_rect.left, 
     680                       video_rect.bottom - video_rect.top, 
     681                       &i_x, &i_y, &i_width, &i_height ); 
     682    point.x = point.y = 0; 
     683    ClientToScreen( p_sys->hwnd, &point ); 
     684    i_x += point.x + video_rect.left; 
     685    i_y += point.y + video_rect.top; 
     686 
     687    if( i_width != p_vout->output.i_width || 
     688        i_height != p_vout->output.i_height ) 
     689    { 
     690        p_sys->render_width = i_width; 
     691        p_sys->render_height = i_height; 
     692        p_vout->i_changes |= VOUT_SIZE_CHANGE; 
     693    } 
     694    else 
     695    { 
     696        GXDisplayProperties gxdisplayprop; 
     697        RECT display_rect, dest_rect; 
     698        uint8_t *p_dest, *p_src = p_pic->p->p_pixels; 
     699 
     700        video_rect.left = i_x; video_rect.top = i_y; 
     701        video_rect.right = i_x + i_width; 
     702        video_rect.bottom = i_y + i_height; 
     703 
     704        gxdisplayprop = GXGetDisplayProperties(); 
     705        display_rect.left = 0; display_rect.top = 0; 
     706        display_rect.right = gxdisplayprop.cxWidth; 
     707        display_rect.bottom = gxdisplayprop.cyHeight; 
     708 
     709        if( !IntersectRect( &dest_rect, &video_rect, &display_rect ) ) 
     710        { 
     711            return; 
     712        } 
     713 
     714#if 0 
     715        msg_Err( p_vout, "video (%d,%d,%d,%d) display (%d,%d,%d,%d) " 
     716                 "dest (%d,%d,%d,%d)", 
     717                 video_rect.left, video_rect.right, 
     718                 video_rect.top, video_rect.bottom, 
     719                 display_rect.left, display_rect.right, 
     720                 display_rect.top, display_rect.bottom, 
     721                 dest_rect.left, dest_rect.right, 
     722                 dest_rect.top, dest_rect.bottom ); 
     723#endif 
     724 
     725        if( !(p_dest = GXBeginDraw()) ) 
     726        { 
     727            msg_Err( p_vout, "GXBeginDraw error %d ", GetLastError() ); 
     728            return; 
     729        } 
     730 
     731        p_src += (dest_rect.left - video_rect.left) * gxdisplayprop.cbxPitch + 
     732            (dest_rect.top - video_rect.top) * p_pic->p->i_pitch; 
     733        p_dest += dest_rect.left * gxdisplayprop.cbxPitch + 
     734            dest_rect.top * gxdisplayprop.cbyPitch; 
     735        i_width = dest_rect.right - dest_rect.left; 
     736        i_height = dest_rect.bottom - dest_rect.top; 
     737 
     738        while( i_height-- ) 
     739        { 
     740            p_vout->p_vlc->pf_memcpy( p_dest, p_src, 
     741                                      i_width * gxdisplayprop.cbxPitch ); 
     742            p_src += p_pic->p->i_pitch; 
     743            p_dest += gxdisplayprop.cbyPitch; 
     744        } 
     745    } 
     746 
     747    GXEndDraw(); 
     748
     749#endif 
     750 
     751#undef rect_src 
     752#undef rect_src_clipped 
     753#undef rect_dest 
     754#undef rect_dest_clipped 
    294755/***************************************************************************** 
    295756 * SetPalette: sets an 8 bpp palette 
     
    306767static void EventThread ( vlc_object_t *p_event ) 
    307768{ 
    308     vout_thread_t * p_vout; 
    309     vlc_value_t     val; 
    310  
    311     HINSTANCE  instance; 
     769    vout_thread_t *p_vout; 
     770    vlc_value_t   val; 
     771 
     772    int        i_style; 
    312773    WNDCLASS   wc; 
    313774    MSG        msg; 
    314775 
    315 #ifdef UNDER_CE 
    316     wchar_t *psz_class = L"VOUT"; 
    317     wchar_t *psz_title = L"Video Output"; 
    318 #else 
    319     char *psz_class = "VOUT"; 
    320     char *psz_title = "Video Output"; 
    321 #endif 
    322  
    323776    var_Get( p_event, "p_vout", &val ); 
    324777    p_vout = (vout_thread_t *)val.p_address; 
    325  
    326     instance = GetModuleHandle( NULL ); 
    327778 
    328779    /* Register window class */ 
     
    332783    wc.cbClsExtra     = 0; 
    333784    wc.cbWndExtra     = 0; 
    334     wc.hInstance      = instance
     785    wc.hInstance      = GetModuleHandle(NULL)
    335786    wc.hIcon          = 0; 
    336     wc.hCursor        = 0
     787    wc.hCursor        = LoadCursor(NULL, IDC_ARROW)
    337788    wc.hbrBackground  = (HBRUSH)GetStockObject( BLACK_BRUSH ); 
    338789    wc.lpszMenuName   = 0; 
    339     wc.lpszClassName  = psz_class; 
    340  
     790    wc.lpszClassName  = _T("VLC WinGDI"); 
    341791    RegisterClass( &wc ); 
    342792 
     793    /* Register the video sub-window class */ 
     794    wc.lpszClassName = _T("VLC WinGDI video"); wc.hIcon = 0; 
     795    RegisterClass(&wc); 
     796 
    343797    /* Create output window */ 
    344     p_vout->p_sys->window = 
    345              CreateWindow( psz_class, psz_title, 
    346                            WS_VISIBLE | WS_SIZEBOX | WS_CAPTION, 
    347                            CW_USEDEFAULT, CW_USEDEFAULT, 
    348                            p_vout->render.i_width, 
    349                            p_vout->render.i_height + 10, 
    350                            NULL, NULL, instance, (LPVOID)p_vout ); 
     798    p_vout->p_sys->hparent = p_vout->p_sys->hwnd = (HWND) 
     799        vout_RequestWindow( p_vout, &p_vout->p_sys->i_window_x, 
     800                            &p_vout->p_sys->i_window_y, 
     801                            (unsigned int *)&p_vout->p_sys->i_window_width, 
     802                            (unsigned int *)&p_vout->p_sys->i_window_height ); 
     803 
     804    ShowWindow( p_vout->p_sys->hparent, SW_SHOW ); 
     805 
     806    if( p_vout->p_sys->hparent ) 
     807        i_style = WS_VISIBLE|WS_CLIPCHILDREN|WS_CHILD; 
     808    else 
     809        i_style = WS_OVERLAPPEDWINDOW|WS_SIZEBOX|WS_VISIBLE|WS_CLIPCHILDREN; 
     810 
     811    p_vout->p_sys->hwnd = 
     812        CreateWindow( _T("VLC WinGDI"), _T(VOUT_TITLE), i_style, 
     813                      (p_vout->p_sys->i_window_x < 0) ? CW_USEDEFAULT : 
     814                      p_vout->p_sys->i_window_x,   /* default X coordinate */ 
     815                      (p_vout->p_sys->i_window_y < 0) ? CW_USEDEFAULT : 
     816                      p_vout->p_sys->i_window_y,   /* default Y coordinate */ 
     817                      p_vout->p_sys->i_window_width, 
     818                      p_vout->p_sys->i_window_height + 10, 
     819                      p_vout->p_sys->hparent, NULL, 
     820                      GetModuleHandle(NULL), (LPVOID)p_vout ); 
     821 
     822    if( !p_vout->p_sys->hwnd ) 
     823    { 
     824        msg_Warn( p_vout, "couldn't create window" ); 
     825        return; 
     826    } 
     827    msg_Warn( p_vout, "Created WinGDI window" ); 
     828 
     829    if( p_vout->p_sys->hparent ) 
     830    { 
     831        LONG i_style; 
     832 
     833        /* We don't want the window owner to overwrite our client area */ 
     834        i_style = GetWindowLong( p_vout->p_sys->hparent, GWL_STYLE ); 
     835 
     836        if( !(i_style & WS_CLIPCHILDREN) ) 
     837            /* Hmmm, apparently this is a blocking call... */ 
     838            SetWindowLong( p_vout->p_sys->hparent, GWL_STYLE, 
     839                           i_style | WS_CLIPCHILDREN ); 
     840 
     841        /* Create our fullscreen window */ 
     842        p_vout->p_sys->hfswnd = 
     843            CreateWindowEx( WS_EX_APPWINDOW, _T("VLC WinGDI"), 
     844                            _T(VOUT_TITLE), 
     845                            WS_NONAVDONEBUTTON|WS_CLIPCHILDREN, 
     846                            CW_USEDEFAULT, CW_USEDEFAULT, 
     847                            CW_USEDEFAULT, CW_USEDEFAULT, 
     848                            NULL, NULL, GetModuleHandle(NULL), NULL ); 
     849    } 
     850 
     851    /* Display our window */ 
     852    ShowWindow( p_vout->p_sys->hwnd, SW_SHOW ); 
     853    UpdateWindow( p_vout->p_sys->hwnd ); 
     854 
     855    /* Create video sub-window */ 
     856    p_vout->p_sys->hvideownd = 
     857        CreateWindow( _T("VLC WinGDI video"), _T(""),   /* window class */ 
     858                    WS_CHILD | WS_VISIBLE,                   /* window style */ 
     859                    CW_USEDEFAULT, CW_USEDEFAULT,     /* default coordinates */ 
     860                    CW_USEDEFAULT, CW_USEDEFAULT, 
     861                    p_vout->p_sys->hwnd,                  /* parent window */ 
     862                    NULL, GetModuleHandle(NULL), 
     863                    (LPVOID)p_vout );            /* send p_vout to WM_CREATE */ 
     864 
     865    ShowWindow( p_vout->p_sys->hvideownd, SW_SHOW ); 
    351866 
    352867    /* Initialize offscreen buffer */ 
     
    356871    vlc_thread_ready( p_event ); 
    357872 
    358     /* Display our window */ 
    359     ShowWindow( p_vout->p_sys->window, SW_SHOWNORMAL ); 
    360     UpdateWindow( p_vout->p_sys->window ); 
    361  
    362     while( !p_event->b_die 
    363              && GetMessage( &msg, p_vout->p_sys->window, 0, 0 ) ) 
    364     { 
    365         if( p_event->b_die ) 
    366         { 
    367             break; 
    368         } 
     873    while( !p_event->b_die && GetMessage( &msg, 0, 0, 0 ) ) 
     874    { 
     875        /* Check if we are asked to exit */ 
     876        if( p_event->b_die ) break; 
    369877 
    370878        switch( msg.message ) 
     
    390898            break; 
    391899 
     900#ifdef MODULE_NAME_IS_gapi 
     901        case WM_KILLFOCUS: 
     902            GXSuspend(); 
     903            break; 
     904 
     905        case WM_SETFOCUS: 
     906            GXResume(); 
     907            break; 
     908#endif 
     909 
    392910        default: 
    393911            TranslateMessage( &msg ); 
     
    397915    } 
    398916 
    399     DestroyWindow( p_vout->p_sys->window ); 
     917    msg_Dbg( p_vout, "CloseWindow" ); 
     918 
     919    DestroyWindow( p_vout->p_sys->hwnd ); 
     920    if( p_vout->p_sys->hfswnd ) DestroyWindow( p_vout->p_sys->hfswnd ); 
     921 
     922    if( p_vout->p_sys->hparent ) 
     923        vout_ReleaseWindow( p_vout, (void *)p_vout->p_sys->hparent ); 
    400924 
    401925    DeleteDC( p_vout->p_sys->off_dc ); 
     
    404928 
    405929/***************************************************************************** 
     930 * UpdateRects: update clipping rectangles 
     931 ***************************************************************************** 
     932 * This function is called when the window position or size are changed, and 
     933 * its job is to update the source and destination RECTs used to display the 
     934 * picture. 
     935 *****************************************************************************/ 
     936static void UpdateRects( vout_thread_t *p_vout, vlc_bool_t b_force ) 
     937{ 
     938#define rect_src p_vout->p_sys->rect_src 
     939#define rect_src_clipped p_vout->p_sys->rect_src_clipped 
     940#define rect_dest p_vout->p_sys->rect_dest 
     941#define rect_dest_clipped p_vout->p_sys->rect_dest_clipped 
     942 
     943    int i_width, i_height, i_x, i_y; 
     944 
     945    RECT  rect; 
     946    POINT point; 
     947 
     948    /* Retrieve the window size */ 
     949    GetClientRect( p_vout->p_sys->hwnd, &rect ); 
     950 
     951    /* Retrieve the window position */ 
     952    point.x = point.y = 0; 
     953    ClientToScreen( p_vout->p_sys->hwnd, &point ); 
     954 
     955    /* If nothing changed, we can return */ 
     956    if( !b_force 
     957         && p_vout->p_sys->i_window_width == rect.right 
     958         && p_vout->p_sys->i_window_height == rect.bottom 
     959         && p_vout->p_sys->i_window_x == point.x 
     960         && p_vout->p_sys->i_window_y == point.y ) 
     961    { 
     962        return; 
     963    } 
     964 
     965    /* Update the window position and size */ 
     966    p_vout->p_sys->i_window_x = point.x; 
     967    p_vout->p_sys->i_window_y = point.y; 
     968    p_vout->p_sys->i_window_width = rect.right; 
     969    p_vout->p_sys->i_window_height = rect.bottom; 
     970 
     971    vout_PlacePicture( p_vout, rect.right, rect.bottom, 
     972                       &i_x, &i_y, &i_width, &i_height ); 
     973 
     974    if( p_vout->p_sys->hvideownd ) 
     975        SetWindowPos( p_vout->p_sys->hvideownd, HWND_TOP, 
     976                      i_x, i_y, i_width, i_height, 0 ); 
     977 
     978    /* Destination image position and dimensions */ 
     979    rect_dest.left = point.x + i_x; 
     980    rect_dest.right = rect_dest.left + i_width; 
     981    rect_dest.top = point.y + i_y; 
     982    rect_dest.bottom = rect_dest.top + i_height; 
     983 
     984    /* Clip the destination window */ 
     985    if( !IntersectRect( &rect_dest_clipped, &rect_dest, 
     986                        &p_vout->p_sys->rect_display ) ) 
     987    { 
     988        SetRectEmpty( &rect_src_clipped ); 
     989        return; 
     990    } 
     991 
     992#if 0 
     993    msg_Dbg( p_vout, "image_dst_clipped coords: %i,%i,%i,%i", 
     994                     rect_dest_clipped.left, rect_dest_clipped.top, 
     995                     rect_dest_clipped.right, rect_dest_clipped.bottom ); 
     996#endif 
     997 
     998    /* the 2 following lines are to fix a bug when clicking on the desktop */ 
     999    if( (rect_dest_clipped.right - rect_dest_clipped.left)==0 || 
     1000        (rect_dest_clipped.bottom - rect_dest_clipped.top)==0 ) 
     1001    { 
     1002        SetRectEmpty( &rect_src_clipped ); 
     1003        return; 
     1004    } 
     1005 
     1006    /* src image dimensions */ 
     1007    rect_src.left = 0; 
     1008    rect_src.top = 0; 
     1009    rect_src.right = p_vout->output.i_width; 
     1010    rect_src.bottom = p_vout->output.i_height; 
     1011 
     1012    /* Clip the source image */ 
     1013    rect_src_clipped.left = (rect_dest_clipped.left - rect_dest.left) * 
     1014      p_vout->output.i_width / (rect_dest.right - rect_dest.left); 
     1015    rect_src_clipped.right = p_vout->output.i_width - 
     1016      (rect_dest.right - rect_dest_clipped.right) * p_vout->output.i_width / 
     1017      (rect_dest.right - rect_dest.left); 
     1018    rect_src_clipped.top = (rect_dest_clipped.top - rect_dest.top) * 
     1019      p_vout->output.i_height / (rect_dest.bottom - rect_dest.top); 
     1020    rect_src_clipped.bottom = p_vout->output.i_height - 
     1021      (rect_dest.bottom - rect_dest_clipped.bottom) * p_vout->output.i_height / 
     1022      (rect_dest.bottom - rect_dest.top); 
     1023 
     1024#if 0 
     1025    msg_Dbg( p_vout, "image_src_clipped coords: %i,%i,%i,%i", 
     1026                     rect_src_clipped.left, rect_src_clipped.top, 
     1027                    &nb