]> git.sesse.net Git - vlc/blob - modules/video_output/wingdi.c
* modules/video_output/wingdi.c, include/video_output.h: disable GAPI when the video...
[vlc] / modules / video_output / wingdi.c
1 /*****************************************************************************
2  * wingdi.c : Win32 / WinCE GDI video output plugin for vlc
3  *****************************************************************************
4  * Copyright (C) 2002 VideoLAN
5  * $Id$
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., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include <stdlib.h>                                      /* malloc(), free() */
29 #include <string.h>
30
31 #include <vlc/vlc.h>
32 #include <vlc/vout.h>
33
34 #include <commctrl.h>
35
36 #ifdef UNDER_CE
37 #   define SHFS_HIDESIPBUTTON   0x0008
38 #   define MENU_HEIGHT 26
39 #else
40 #   define SHFS_HIDESIPBUTTON 0
41 #   define MENU_HEIGHT 0
42 #endif
43
44 #ifdef MODULE_NAME_IS_wingapi
45     typedef struct GXDisplayProperties {
46         DWORD cxWidth;
47         DWORD cyHeight;
48         long cbxPitch;
49         long cbyPitch;
50         long cBPP;
51         DWORD ffFormat;
52     } GXDisplayProperties;
53
54     typedef struct GXScreenRect {
55         DWORD dwTop;
56         DWORD dwLeft;
57         DWORD dwWidth;
58         DWORD dwHeight;
59     } GXScreenRect;
60
61 #   define GX_FULLSCREEN    0x01
62 #   define GX_NORMALKEYS    0x02
63 #   define GX_LANDSCAPEKEYS 0x03
64
65 #   ifndef kfLandscape
66 #       define kfLandscape      0x8
67 #       define kfPalette        0x10
68 #       define kfDirect         0x20
69 #       define kfDirect555      0x40
70 #       define kfDirect565      0x80
71 #       define kfDirect888      0x100
72 #       define kfDirect444      0x200
73 #       define kfDirectInverted 0x400
74 #   endif
75 #endif /* MODULE_NAME_IS_wingapi */
76
77 #define MAX_DIRECTBUFFERS 10
78
79 #ifdef UNDER_CE
80 #ifndef WS_OVERLAPPEDWINDOW
81 #   define WS_OVERLAPPEDWINDOW 0xcf0000
82 #endif
83 #ifndef WS_EX_NOPARENTNOTIFY
84 #   define WS_EX_NOPARENTNOTIFY 4
85 #endif
86 #ifndef WS_EX_APPWINDOW
87 #define WS_EX_APPWINDOW 0x40000
88 #endif
89 #define SetWindowLongPtr SetWindowLong
90 #define GetWindowLongPtr GetWindowLong
91 #define GWLP_USERDATA GWL_USERDATA
92 #endif //UNDER_CE
93
94 #ifndef WS_NONAVDONEBUTTON
95 #define WS_NONAVDONEBUTTON 0
96 #endif
97 /*****************************************************************************
98  * Local prototypes
99  *****************************************************************************/
100 static int  OpenVideo  ( vlc_object_t * );
101 static void CloseVideo ( vlc_object_t * );
102
103 static int  Init      ( vout_thread_t * );
104 static void End       ( vout_thread_t * );
105 static int  Manage    ( vout_thread_t * );
106 static void Render    ( vout_thread_t *, picture_t * );
107 #ifdef MODULE_NAME_IS_wingapi
108 static void DisplayGAPI( vout_thread_t *, picture_t * );
109 static int GAPILockSurface( vout_thread_t *, picture_t * );
110 static int GAPIUnlockSurface( vout_thread_t *, picture_t * );
111 #else
112 static void DisplayGDI( vout_thread_t *, picture_t * );
113 #endif
114 static void SetPalette( vout_thread_t *, uint16_t *, uint16_t *, uint16_t * );
115
116 static void EventThread        ( vlc_object_t * );
117 static long FAR PASCAL WndProc ( HWND, UINT, WPARAM, LPARAM );
118 static void InitBuffers        ( vout_thread_t * );
119 static void UpdateRects        ( vout_thread_t *, vlc_bool_t );
120
121 static int Control( vout_thread_t *p_vout, int i_query, va_list args );
122
123 /*****************************************************************************
124  * Private structure
125  *****************************************************************************/
126 struct vout_sys_t
127 {
128     /* The event thread */
129     vlc_object_t * p_event;
130
131     /* Our video output window */
132     HWND hwnd;
133     HWND hvideownd;
134     HWND hfswnd;
135     int  i_depth;
136     HWND                 hparent;             /* Handle of the parent window */
137     WNDPROC              pf_wndproc;             /* Window handling callback */
138     volatile uint16_t    i_changes;     /* changes made to the video display */
139     RECT window_placement;
140
141     /* Window position and size */
142     int          i_window_x;
143     int          i_window_y;
144     int          i_window_width;
145     int          i_window_height;
146     int          render_width;
147     int          render_height;
148
149     /* Coordinates of src and dest images (used when blitting to display) */
150     RECT         rect_src;
151     RECT         rect_src_clipped;
152     RECT         rect_dest;
153     RECT         rect_dest_clipped;
154     RECT         rect_parent;
155     RECT         rect_display;
156
157     /* Our offscreen bitmap and its framebuffer */
158     HDC        off_dc;
159     HBITMAP    off_bitmap;
160     uint8_t *  p_pic_buffer;
161     int        i_pic_pitch;
162     int        i_pic_pixel_pitch;
163
164     BITMAPINFO bitmapinfo;
165     RGBQUAD    red;
166     RGBQUAD    green;
167     RGBQUAD    blue;
168
169     /* WINCE stuff */
170     HWND hMenu;
171     HWND hTaskBar;
172     vlc_bool_t   b_video_display;
173
174 #ifdef MODULE_NAME_IS_wingapi
175     HINSTANCE  gapi_dll;                    /* handle of the opened gapi dll */
176
177     /* GAPI functions */
178     int (*GXOpenDisplay)( HWND hWnd, DWORD dwFlags );
179     int (*GXCloseDisplay)();
180     void *(*GXBeginDraw)();
181     int (*GXEndDraw)();
182     GXDisplayProperties (*GXGetDisplayProperties)();
183     int (*GXSuspend)();
184     int (*GXResume)();
185 #endif
186 };
187
188 #define GXOpenDisplay p_vout->p_sys->GXOpenDisplay
189 #define GXCloseDisplay p_vout->p_sys->GXCloseDisplay
190 #define GXBeginDraw p_vout->p_sys->GXBeginDraw
191 #define GXEndDraw p_vout->p_sys->GXEndDraw
192 #define GXGetDisplayProperties p_vout->p_sys->GXGetDisplayProperties
193 #define GXSuspend p_vout->p_sys->GXSuspend
194 #define GXResume p_vout->p_sys->GXResume
195
196 #define DX_POSITION_CHANGE 0x1000
197
198 /*****************************************************************************
199  * Module descriptor
200  *****************************************************************************/
201 vlc_module_begin();
202 #ifdef MODULE_NAME_IS_wingapi
203     set_description( _("Windows GAPI video output") );
204     set_capability( "video output", 20 );
205 #else
206     set_description( _("Windows GDI video output") );
207     set_capability( "video output", 10 );
208 #endif
209     set_callbacks( OpenVideo, CloseVideo );
210 vlc_module_end();
211
212 /*****************************************************************************
213  * OpenVideo: activate GDI video thread output method
214  *****************************************************************************/
215 static int OpenVideo ( vlc_object_t *p_this )
216 {
217     vout_thread_t * p_vout = (vout_thread_t *)p_this;
218     vlc_value_t val;
219
220     p_vout->p_sys = (vout_sys_t *)malloc( sizeof(vout_sys_t) );
221     if( !p_vout->p_sys ) return VLC_ENOMEM;
222
223 #ifdef MODULE_NAME_IS_wingapi
224     /* Load GAPI */
225     p_vout->p_sys->gapi_dll = LoadLibrary( _T("GX.DLL") );
226     if( p_vout->p_sys->gapi_dll == NULL )
227     {
228         msg_Warn( p_vout, "failed loading gx.dll" );
229         free( p_vout->p_sys );
230         return VLC_EGENERIC;
231     }
232
233     GXOpenDisplay = (void *)GetProcAddress( p_vout->p_sys->gapi_dll,
234         _T("?GXOpenDisplay@@YAHPAUHWND__@@K@Z") );
235     GXCloseDisplay = (void *)GetProcAddress( p_vout->p_sys->gapi_dll,
236         _T("?GXCloseDisplay@@YAHXZ") );
237     GXBeginDraw = (void *)GetProcAddress( p_vout->p_sys->gapi_dll,
238         _T("?GXBeginDraw@@YAPAXXZ") );
239     GXEndDraw = (void *)GetProcAddress( p_vout->p_sys->gapi_dll,
240         _T("?GXEndDraw@@YAHXZ") );
241     GXGetDisplayProperties = (void *)GetProcAddress( p_vout->p_sys->gapi_dll,
242         _T("?GXGetDisplayProperties@@YA?AUGXDisplayProperties@@XZ") );
243     GXSuspend = (void *)GetProcAddress( p_vout->p_sys->gapi_dll,
244         _T("?GXSuspend@@YAHXZ") );
245     GXResume = GetProcAddress( p_vout->p_sys->gapi_dll,
246         _T("?GXResume@@YAHXZ") );
247
248     if( !GXOpenDisplay || !GXCloseDisplay || !GXBeginDraw || !GXEndDraw ||
249         !GXGetDisplayProperties || !GXSuspend || !GXResume )
250     {
251         msg_Err( p_vout, "failed GetProcAddress on gapi.dll" );
252         free( p_vout->p_sys );
253         return VLC_EGENERIC;
254     }
255
256     msg_Dbg( p_vout, "GAPI DLL loaded" );
257
258     p_vout->p_sys->render_width = p_vout->render.i_width;
259     p_vout->p_sys->render_height = p_vout->render.i_height;
260 #endif
261
262     p_vout->p_sys->p_event = (vlc_object_t *)
263         vlc_object_create( p_vout, VLC_OBJECT_GENERIC );
264     if( !p_vout->p_sys->p_event )
265     {
266         free( p_vout->p_sys );
267         return VLC_ENOMEM;
268     }
269
270     var_Create( p_vout->p_sys->p_event, "p_vout", VLC_VAR_ADDRESS );
271     val.p_address = (void *)p_vout;
272     var_Set( p_vout->p_sys->p_event, "p_vout", val );
273
274     SetRectEmpty( &p_vout->p_sys->rect_display );
275     SetRectEmpty( &p_vout->p_sys->rect_parent );
276
277     if( vlc_thread_create( p_vout->p_sys->p_event, "GDI Event Thread",
278                            EventThread, 0, 1 ) )
279     {
280         msg_Err( p_vout, "cannot spawn EventThread" );
281         return VLC_ETHREAD;
282     }
283
284     p_vout->pf_init = Init;
285     p_vout->pf_end = End;
286     p_vout->pf_manage = Manage;
287     p_vout->pf_render = Render;
288 #ifdef MODULE_NAME_IS_wingapi
289     p_vout->pf_display = DisplayGAPI;
290 #else
291     p_vout->pf_display = DisplayGDI;
292 #endif
293     p_vout->p_sys->i_changes = 0;
294
295     return VLC_SUCCESS;
296 }
297
298 /*****************************************************************************
299  * CloseVideo: deactivate the GDI video output
300  *****************************************************************************/
301 static void CloseVideo ( vlc_object_t *p_this )
302 {
303     vout_thread_t * p_vout = (vout_thread_t *)p_this;
304
305     p_vout->p_sys->p_event->b_die = VLC_TRUE;
306     PostMessage( p_vout->p_sys->hwnd, WM_NULL, 0, 0 );
307     vlc_thread_join( p_vout->p_sys->p_event );
308
309 #ifdef MODULE_NAME_IS_wingapi
310     FreeLibrary( p_vout->p_sys->gapi_dll );
311 #endif
312
313     var_Destroy( p_vout->p_sys->p_event, "p_vout" );
314     vlc_object_destroy( p_vout->p_sys->p_event );
315     free( p_vout->p_sys );
316 }
317
318 /*****************************************************************************
319  * Init: initialize video thread output method
320  *****************************************************************************/
321 static int Init( vout_thread_t *p_vout )
322 {
323     picture_t *p_pic;
324
325     p_vout->p_sys->rect_display.left = 0;
326     p_vout->p_sys->rect_display.top = 0;
327     p_vout->p_sys->rect_display.right  = GetSystemMetrics(SM_CXSCREEN);
328     p_vout->p_sys->rect_display.bottom = GetSystemMetrics(SM_CYSCREEN);
329
330     p_vout->p_sys->b_video_display = VLC_TRUE;
331     p_vout->p_sys->p_event->b_die = VLC_FALSE;
332
333     I_OUTPUTPICTURES = 0;
334
335     /* Initialize the output structure */
336     switch( p_vout->p_sys->i_depth )
337     {
338     case 8:
339         p_vout->output.i_chroma = VLC_FOURCC('R','G','B','2');
340         p_vout->output.pf_setpalette = SetPalette;
341         break;
342     case 15:
343         p_vout->output.i_chroma = VLC_FOURCC('R','V','1','5');
344         p_vout->output.i_rmask  = 0x7c00;
345         p_vout->output.i_gmask  = 0x03e0;
346         p_vout->output.i_bmask  = 0x001f;
347         break;
348     case 16:
349         p_vout->output.i_chroma = VLC_FOURCC('R','V','1','6');
350         p_vout->output.i_rmask  = 0xf800;
351         p_vout->output.i_gmask  = 0x07e0;
352         p_vout->output.i_bmask  = 0x001f;
353         break;
354     case 24:
355         p_vout->output.i_chroma = VLC_FOURCC('R','V','2','4');
356         p_vout->output.i_rmask  = 0x00ff0000;
357         p_vout->output.i_gmask  = 0x0000ff00;
358         p_vout->output.i_bmask  = 0x000000ff;
359         break;
360     case 32:
361         p_vout->output.i_chroma = VLC_FOURCC('R','V','3','2');
362         p_vout->output.i_rmask  = 0x00ff0000;
363         p_vout->output.i_gmask  = 0x0000ff00;
364         p_vout->output.i_bmask  = 0x000000ff;
365         break;
366     default:
367         msg_Err( p_vout, "screen depth %i not supported",
368                  p_vout->p_sys->i_depth );
369         return VLC_EGENERIC;
370         break;
371     }
372
373     p_pic = &p_vout->p_picture[0];
374
375 #ifdef MODULE_NAME_IS_wingapi
376     p_vout->output.i_width  = 0;
377     p_vout->output.i_height = 0;
378     p_pic->pf_lock  = GAPILockSurface;
379     p_pic->pf_unlock = GAPIUnlockSurface;
380     Manage( p_vout );
381     GAPILockSurface( p_vout, p_pic );
382     p_vout->i_changes = 0;
383     p_vout->output.i_width  = p_vout->p_sys->render_width;
384     p_vout->output.i_height = p_vout->p_sys->render_height;
385
386 #else
387     p_vout->output.i_width  = p_vout->render.i_width;
388     p_vout->output.i_height = p_vout->render.i_height;
389 #endif
390     p_vout->output.i_aspect = p_vout->render.i_aspect;
391
392     p_pic->p->p_pixels = p_vout->p_sys->p_pic_buffer;
393     p_pic->p->i_lines = p_vout->output.i_height;
394     p_pic->p->i_visible_lines = p_vout->output.i_height;
395     p_pic->p->i_pitch = p_vout->p_sys->i_pic_pitch;
396     p_pic->p->i_pixel_pitch = p_vout->p_sys->i_pic_pixel_pitch;
397     p_pic->p->i_visible_pitch = p_vout->output.i_width *
398         p_pic->p->i_pixel_pitch;
399     p_pic->i_planes = 1;
400     p_pic->i_status = DESTROYED_PICTURE;
401     p_pic->i_type   = DIRECT_PICTURE;
402
403     PP_OUTPUTPICTURE[ I_OUTPUTPICTURES++ ] = p_pic;
404
405     return VLC_SUCCESS;
406 }
407
408 /*****************************************************************************
409  * End: terminate video thread output method
410  *****************************************************************************/
411 static void End( vout_thread_t *p_vout )
412 {
413 }
414
415 /*****************************************************************************
416  * Manage: handle events
417  *****************************************************************************
418  * This function should be called regularly by video output thread. It manages
419  * console events. It returns a non null value on error.
420  *****************************************************************************/
421 static int Manage( vout_thread_t *p_vout )
422 {
423 #ifndef UNDER_CE
424     WINDOWPLACEMENT window_placement;
425 #endif
426
427     /* If we do not control our window, we check for geometry changes
428      * ourselves because the parent might not send us its events. */
429     if( p_vout->p_sys->hparent && !p_vout->b_fullscreen )
430     {
431         RECT rect_parent;
432         POINT point;
433
434         GetClientRect( p_vout->p_sys->hparent, &rect_parent );
435         point.x = point.y = 0;
436         ClientToScreen( p_vout->p_sys->hparent, &point );
437         OffsetRect( &rect_parent, point.x, point.y );
438
439         if( !EqualRect( &rect_parent, &p_vout->p_sys->rect_parent ) )
440         {
441             int i_x, i_y, i_width, i_height;
442             p_vout->p_sys->rect_parent = rect_parent;
443
444             /* This one is to force the update even if only
445              * the position has changed */
446             SetWindowPos( p_vout->p_sys->hwnd, 0, 1, 1,
447                           rect_parent.right - rect_parent.left,
448                           rect_parent.bottom - rect_parent.top, 0 );
449
450             SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0,
451                           rect_parent.right - rect_parent.left,
452                           rect_parent.bottom - rect_parent.top, 0 );
453
454             vout_PlacePicture( p_vout, rect_parent.right - rect_parent.left,
455                                rect_parent.bottom - rect_parent.top,
456                                &i_x, &i_y, &i_width, &i_height );
457
458             SetWindowPos( p_vout->p_sys->hvideownd, HWND_TOP,
459                           i_x, i_y, i_width, i_height, 0 );
460         }
461     }
462
463     /* We used to call the Win32 PeekMessage function here to read the window
464      * messages. But since window can stay blocked into this function for a
465      * long time (for example when you move your window on the screen), I
466      * decided to isolate PeekMessage in another thread. */
467
468     /*
469      * Fullscreen change
470      */
471     if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE
472         || p_vout->p_sys->i_changes & VOUT_FULLSCREEN_CHANGE )
473     {
474         int i_style = 0;
475         vlc_value_t val;
476
477         HWND hwnd = (p_vout->p_sys->hparent && p_vout->p_sys->hfswnd) ?
478             p_vout->p_sys->hfswnd : p_vout->p_sys->hwnd;
479
480         p_vout->b_fullscreen = ! p_vout->b_fullscreen;
481
482         /* We need to switch between Maximized and Normal sized window */
483 #ifndef UNDER_CE
484         window_placement.length = sizeof(WINDOWPLACEMENT);
485         GetWindowPlacement( hwnd, &window_placement );
486 #endif
487         if( p_vout->b_fullscreen )
488         {
489 #ifndef UNDER_CE
490             /* Change window style, no borders and no title bar */
491             int i_style = WS_CLIPCHILDREN | WS_VISIBLE;
492             SetWindowLong( hwnd, GWL_STYLE, i_style );
493
494             if( p_vout->p_sys->hparent )
495             {
496                 /* Retrieve current window position so fullscreen will happen
497                  * on the right screen */
498                 POINT point = {0,0};
499                 RECT rect;
500                 ClientToScreen( p_vout->p_sys->hwnd, &point );
501                 GetClientRect( p_vout->p_sys->hwnd, &rect );
502                 SetWindowPos( hwnd, 0, point.x, point.y,
503                               rect.right, rect.bottom,
504                               SWP_NOZORDER|SWP_FRAMECHANGED );
505                 GetWindowPlacement( hwnd, &window_placement );
506             }
507
508             /* Maximize window */
509             window_placement.showCmd = SW_SHOWMAXIMIZED;
510             SetWindowPlacement( hwnd, &window_placement );
511             SetWindowPos( hwnd, 0, 0, 0, 0, 0,
512                           SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED);
513 #endif
514
515             if( p_vout->p_sys->hparent )
516             {
517                 RECT rect;
518                 GetClientRect( hwnd, &rect );
519                 SetParent( p_vout->p_sys->hwnd, hwnd );
520                 SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0,
521                               rect.right, rect.bottom,
522                               SWP_NOZORDER|SWP_FRAMECHANGED );
523             }
524
525             ShowWindow( hwnd, SW_SHOW );
526             SetForegroundWindow( hwnd );
527         }
528         else
529         {
530             /* Change window style, no borders and no title bar */
531             //SetWindowLong( hwnd, GWL_STYLE, p_vout->p_sys->i_window_style );
532
533 #ifndef UNDER_CE
534             /* Normal window */
535             window_placement.showCmd = SW_SHOWNORMAL;
536             SetWindowPlacement( hwnd, &window_placement );
537             SetWindowPos( hwnd, 0, 0, 0, 0, 0,
538                           SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED);
539 #endif
540
541             if( p_vout->p_sys->hparent )
542             {
543                 RECT rect;
544                 GetClientRect( p_vout->p_sys->hparent, &rect );
545                 SetParent( p_vout->p_sys->hwnd, p_vout->p_sys->hparent );
546                 SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0,
547                               rect.right, rect.bottom,
548                               SWP_NOZORDER|SWP_FRAMECHANGED );
549
550                 ShowWindow( hwnd, SW_HIDE );
551                 SetForegroundWindow( p_vout->p_sys->hparent );
552             }
553
554             /* Make sure the mouse cursor is displayed */
555             //PostMessage( p_vout->p_sys->hwnd, WM_VLC_SHOW_MOUSE, 0, 0 );
556         }
557
558         /* Change window style, borders and title bar */
559         ShowWindow( p_vout->p_sys->hwnd, SW_SHOW );
560         UpdateWindow( p_vout->p_sys->hwnd );
561
562         /* Update the object variable and trigger callback */
563         val.b_bool = p_vout->b_fullscreen;
564         var_Set( p_vout, "fullscreen", val );
565
566         p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
567         p_vout->p_sys->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
568     }
569
570     return VLC_SUCCESS;
571 }
572
573 /*****************************************************************************
574  * Render: render previously calculated output
575  *****************************************************************************/
576 static void Render( vout_thread_t *p_vout, picture_t *p_pic )
577 {
578     /* No need to do anything, the fake direct buffers stay as they are */
579 }
580
581 /*****************************************************************************
582  * Display: displays previously rendered output
583  *****************************************************************************/
584 #define rect_src p_vout->p_sys->rect_src
585 #define rect_src_clipped p_vout->p_sys->rect_src_clipped
586 #define rect_dest p_vout->p_sys->rect_dest
587 #define rect_dest_clipped p_vout->p_sys->rect_dest_clipped
588
589 #ifndef MODULE_NAME_IS_wingapi
590 static void DisplayGDI( vout_thread_t *p_vout, picture_t *p_pic )
591 {
592     vout_sys_t *p_sys = p_vout->p_sys;
593     RECT rect_dst = rect_dest_clipped;
594     HDC hdc = GetDC( p_sys->hvideownd );
595
596     OffsetRect( &rect_dst, -rect_dest.left, -rect_dest.top );
597     SelectObject( p_sys->off_dc, p_sys->off_bitmap );
598
599     if( rect_dest_clipped.right - rect_dest_clipped.left !=
600         rect_src_clipped.right - rect_src_clipped.left ||
601         rect_dest_clipped.bottom - rect_dest_clipped.top !=
602         rect_src_clipped.bottom - rect_src_clipped.top )
603     {
604         StretchBlt( hdc, rect_dst.left, rect_dst.top,
605                     rect_dst.right, rect_dst.bottom,
606                     p_sys->off_dc, rect_src_clipped.left, rect_src_clipped.top,
607                     rect_src_clipped.right, rect_src_clipped.bottom, SRCCOPY );
608     }
609     else
610     {
611         BitBlt( hdc, rect_dst.left, rect_dst.top,
612                 rect_dst.right, rect_dst.bottom,
613                 p_sys->off_dc, rect_src_clipped.left,
614                 rect_src_clipped.top, SRCCOPY );
615     }
616
617     ReleaseDC( p_sys->hwnd, hdc );
618 }
619 #else
620
621 static int GAPILockSurface( vout_thread_t *p_vout, picture_t *p_pic )
622 {
623     vout_sys_t *p_sys = p_vout->p_sys;
624     int i_x, i_y, i_width, i_height;
625     RECT video_rect;
626     POINT point;
627
628     /* Undo the display */
629     if( ( GetForegroundWindow() != GetParent(p_sys->hwnd) ) ||
630         ( p_sys->b_video_display == VLC_FALSE ) )
631     {
632         //return VLC_EGENERIC;
633     }
634
635     GetClientRect( p_sys->hwnd, &video_rect);
636     vout_PlacePicture( p_vout, video_rect.right - video_rect.left,
637                        video_rect.bottom - video_rect.top,
638                        &i_x, &i_y, &i_width, &i_height );
639     point.x = point.y = 0;
640     ClientToScreen( p_sys->hwnd, &point );
641     i_x += point.x + video_rect.left;
642     i_y += point.y + video_rect.top;
643
644     if( i_width != p_vout->output.i_width ||
645         i_height != p_vout->output.i_height )
646     {
647         GXDisplayProperties gxdisplayprop = GXGetDisplayProperties();
648
649         p_sys->render_width = i_width;
650         p_sys->render_height = i_height;
651         p_vout->i_changes |= VOUT_SIZE_CHANGE;
652
653         msg_Dbg( p_vout, "vout size change (%ix%i -> %ix%i)",
654                  i_width, i_height, p_vout->output.i_width,
655                  p_vout->output.i_height );
656
657         p_vout->p_sys->i_pic_pixel_pitch = gxdisplayprop.cbxPitch;
658         p_vout->p_sys->i_pic_pitch = gxdisplayprop.cbyPitch;
659         return VLC_EGENERIC;
660     }
661     else
662     {
663         GXDisplayProperties gxdisplayprop;
664         RECT display_rect, dest_rect;
665         uint8_t *p_dest, *p_src = p_pic->p->p_pixels;
666
667         video_rect.left = i_x; video_rect.top = i_y;
668         video_rect.right = i_x + i_width;
669         video_rect.bottom = i_y + i_height;
670
671         gxdisplayprop = GXGetDisplayProperties();
672         display_rect.left = 0; display_rect.top = 0;
673         display_rect.right = gxdisplayprop.cxWidth;
674         display_rect.bottom = gxdisplayprop.cyHeight;
675
676         if( !IntersectRect( &dest_rect, &video_rect, &display_rect ) )
677         {
678             return VLC_EGENERIC;
679         }
680
681 #if 0
682         msg_Err( p_vout, "video (%d,%d,%d,%d) display (%d,%d,%d,%d) "
683                  "dest (%d,%d,%d,%d)",
684                  video_rect.left, video_rect.right,
685                  video_rect.top, video_rect.bottom,
686                  display_rect.left, display_rect.right,
687                  display_rect.top, display_rect.bottom,
688                  dest_rect.left, dest_rect.right,
689                  dest_rect.top, dest_rect.bottom );
690 #endif
691
692         if( !(p_dest = GXBeginDraw()) )
693         {
694 #if 0
695             msg_Err( p_vout, "GXBeginDraw error %d ", GetLastError() );
696 #endif
697             return VLC_EGENERIC;
698         }
699
700         p_src += (dest_rect.left - video_rect.left) * gxdisplayprop.cbxPitch +
701             (dest_rect.top - video_rect.top) * p_pic->p->i_pitch;
702         p_dest += dest_rect.left * gxdisplayprop.cbxPitch +
703             dest_rect.top * gxdisplayprop.cbyPitch;
704         i_width = dest_rect.right - dest_rect.left;
705         i_height = dest_rect.bottom - dest_rect.top;
706
707         p_pic->p->p_pixels = p_dest;
708     }
709
710     return VLC_SUCCESS;
711 }
712
713 static int GAPIUnlockSurface( vout_thread_t *p_vout, picture_t *p_pic )
714 {
715     GXEndDraw();
716     return VLC_SUCCESS;
717 }
718
719 static void DisplayGAPI( vout_thread_t *p_vout, picture_t *p_pic )
720 {
721 }
722 #endif
723
724 #undef rect_src
725 #undef rect_src_clipped
726 #undef rect_dest
727 #undef rect_dest_clipped
728 /*****************************************************************************
729  * SetPalette: sets an 8 bpp palette
730  *****************************************************************************/
731 static void SetPalette( vout_thread_t *p_vout,
732                         uint16_t *red, uint16_t *green, uint16_t *blue )
733 {
734     msg_Err( p_vout, "FIXME: SetPalette unimplemented" );
735 }
736
737 /*****************************************************************************
738  * EventThread: Event handling thread
739  *****************************************************************************/
740 static void EventThread ( vlc_object_t *p_event )
741 {
742     vout_thread_t *p_vout;
743     vlc_value_t   val;
744
745     int        i_style;
746     WNDCLASS   wc;
747     MSG        msg;
748
749     /* Initialisations */
750     var_Get( p_event, "p_vout", &val );
751     p_vout = (vout_thread_t *)val.p_address;
752
753     /* Register window class */
754     memset( &wc, 0, sizeof(wc) );
755     wc.style          = CS_HREDRAW | CS_VREDRAW;
756     wc.lpfnWndProc    = (WNDPROC)WndProc;
757     wc.cbClsExtra     = 0;
758     wc.cbWndExtra     = 0;
759     wc.hInstance      = GetModuleHandle(NULL);
760     wc.hIcon          = 0;
761     wc.hCursor        = LoadCursor(NULL, IDC_ARROW);
762     wc.hbrBackground  = (HBRUSH)GetStockObject( BLACK_BRUSH );
763     wc.lpszMenuName   = 0;
764     wc.lpszClassName  = _T("VLC WinGDI");
765     RegisterClass( &wc );
766
767     /* Register the video sub-window class */
768     wc.lpszClassName = _T("VLC WinGDI video"); wc.hIcon = 0;
769     RegisterClass(&wc);
770
771     /* Create output window */
772     p_vout->p_sys->hparent = (HWND)
773         vout_RequestWindow( p_vout, &p_vout->p_sys->i_window_x,
774                             &p_vout->p_sys->i_window_y,
775                             (unsigned int *)&p_vout->p_sys->i_window_width,
776                             (unsigned int *)&p_vout->p_sys->i_window_height );
777
778     ShowWindow( p_vout->p_sys->hparent, SW_SHOW );
779
780     if( p_vout->p_sys->hparent )
781         i_style = WS_VISIBLE|WS_CLIPCHILDREN|WS_CHILD;
782     else
783         i_style = WS_OVERLAPPEDWINDOW|WS_SIZEBOX|WS_VISIBLE|WS_CLIPCHILDREN;
784
785     p_vout->p_sys->hwnd =
786         CreateWindow( _T("VLC WinGDI"), _T(VOUT_TITLE), i_style,
787                       (p_vout->p_sys->i_window_x < 0) ? CW_USEDEFAULT :
788                       p_vout->p_sys->i_window_x,   /* default X coordinate */
789                       (p_vout->p_sys->i_window_y < 0) ? CW_USEDEFAULT :
790                       p_vout->p_sys->i_window_y,   /* default Y coordinate */
791                       p_vout->p_sys->i_window_width,
792                       p_vout->p_sys->i_window_height + 10,
793                       p_vout->p_sys->hparent, NULL,
794                       GetModuleHandle(NULL), (LPVOID)p_vout );
795
796     if( !p_vout->p_sys->hwnd )
797     {
798         msg_Warn( p_vout, "couldn't create window" );
799         return;
800     }
801     msg_Warn( p_vout, "Created WinGDI window" );
802
803     if( p_vout->p_sys->hparent )
804     {
805         LONG i_style;
806
807         /* We don't want the window owner to overwrite our client area */
808         i_style = GetWindowLong( p_vout->p_sys->hparent, GWL_STYLE );
809
810         if( !(i_style & WS_CLIPCHILDREN) )
811             /* Hmmm, apparently this is a blocking call... */
812             SetWindowLong( p_vout->p_sys->hparent, GWL_STYLE,
813                            i_style | WS_CLIPCHILDREN );
814
815         /* Create our fullscreen window */
816         p_vout->p_sys->hfswnd =
817             CreateWindowEx( WS_EX_APPWINDOW, _T("VLC WinGDI"),
818                             _T(VOUT_TITLE),
819                             WS_NONAVDONEBUTTON|WS_CLIPCHILDREN,
820                             CW_USEDEFAULT, CW_USEDEFAULT,
821                             CW_USEDEFAULT, CW_USEDEFAULT,
822                             NULL, NULL, GetModuleHandle(NULL), NULL );
823     }
824
825     /* Display our window */
826     ShowWindow( p_vout->p_sys->hwnd, SW_SHOW );
827     UpdateWindow( p_vout->p_sys->hwnd );
828
829     /* Create video sub-window */
830     p_vout->p_sys->hvideownd =
831         CreateWindow( _T("VLC WinGDI video"), _T(""),   /* window class */
832                     WS_CHILD | WS_VISIBLE,                   /* window style */
833                     CW_USEDEFAULT, CW_USEDEFAULT,     /* default coordinates */
834                     CW_USEDEFAULT, CW_USEDEFAULT,
835                     p_vout->p_sys->hwnd,                  /* parent window */
836                     NULL, GetModuleHandle(NULL),
837                     (LPVOID)p_vout );            /* send p_vout to WM_CREATE */
838
839     /* Initialize offscreen buffer */
840     InitBuffers( p_vout );
841
842     p_vout->pf_control = Control;
843
844     /* Tell the video output we're ready to receive data */
845     vlc_thread_ready( p_event );
846
847     while( !p_event->b_die && GetMessage( &msg, 0, 0, 0 ) )
848     {
849         /* Check if we are asked to exit */
850         if( p_event->b_die ) break;
851
852         switch( msg.message )
853         {
854         case WM_KEYDOWN:
855             switch( msg.wParam )
856             {
857             case VK_ESCAPE:
858                 p_event->p_vlc->b_die = VLC_TRUE;
859                 break;
860             }
861             TranslateMessage( &msg );
862             break;
863
864         case WM_CHAR:
865             switch( msg.wParam )
866             {
867             case 'q':
868             case 'Q':
869                 p_event->p_vlc->b_die = VLC_TRUE;
870                 break;
871             }
872             break;
873
874         default:
875             TranslateMessage( &msg );
876             DispatchMessage( &msg );
877             break;
878         }
879     }
880
881     msg_Dbg( p_vout, "CloseWindow" );
882
883 #ifdef MODULE_NAME_IS_wingapi
884     GXCloseDisplay();
885 #else
886     DeleteDC( p_vout->p_sys->off_dc );
887     DeleteObject( p_vout->p_sys->off_bitmap );
888 #endif
889
890     DestroyWindow( p_vout->p_sys->hwnd );
891     if( p_vout->p_sys->hfswnd ) DestroyWindow( p_vout->p_sys->hfswnd );
892
893     if( p_vout->p_sys->hparent )
894         vout_ReleaseWindow( p_vout, (void *)p_vout->p_sys->hparent );
895 }
896
897 /*****************************************************************************
898  * UpdateRects: update clipping rectangles
899  *****************************************************************************
900  * This function is called when the window position or size are changed, and
901  * its job is to update the source and destination RECTs used to display the
902  * picture.
903  *****************************************************************************/
904 static void UpdateRects( vout_thread_t *p_vout, vlc_bool_t b_force )
905 {
906 #define rect_src p_vout->p_sys->rect_src
907 #define rect_src_clipped p_vout->p_sys->rect_src_clipped
908 #define rect_dest p_vout->p_sys->rect_dest
909 #define rect_dest_clipped p_vout->p_sys->rect_dest_clipped
910
911     int i_width, i_height, i_x, i_y;
912
913     RECT  rect;
914     POINT point;
915
916     /* Retrieve the window size */
917     GetClientRect( p_vout->p_sys->hwnd, &rect );
918
919     /* Retrieve the window position */
920     point.x = point.y = 0;
921     ClientToScreen( p_vout->p_sys->hwnd, &point );
922
923     /* If nothing changed, we can return */
924     if( !b_force
925          && p_vout->p_sys->i_window_width == rect.right
926          && p_vout->p_sys->i_window_height == rect.bottom
927          && p_vout->p_sys->i_window_x == point.x
928          && p_vout->p_sys->i_window_y == point.y )
929     {
930         return;
931     }
932
933     /* Update the window position and size */
934     p_vout->p_sys->i_window_x = point.x;
935     p_vout->p_sys->i_window_y = point.y;
936     p_vout->p_sys->i_window_width = rect.right;
937     p_vout->p_sys->i_window_height = rect.bottom;
938
939     vout_PlacePicture( p_vout, rect.right, rect.bottom,
940                        &i_x, &i_y, &i_width, &i_height );
941
942     if( p_vout->p_sys->hvideownd )
943         SetWindowPos( p_vout->p_sys->hvideownd, HWND_TOP,
944                       i_x, i_y, i_width, i_height, 0 );
945
946     /* Destination image position and dimensions */
947     rect_dest.left = point.x + i_x;
948     rect_dest.right = rect_dest.left + i_width;
949     rect_dest.top = point.y + i_y;
950     rect_dest.bottom = rect_dest.top + i_height;
951
952     /* Clip the destination window */
953     if( !IntersectRect( &rect_dest_clipped, &rect_dest,
954                         &p_vout->p_sys->rect_display ) )
955     {
956         SetRectEmpty( &rect_src_clipped );
957         return;
958     }
959
960 #if 0
961     msg_Dbg( p_vout, "image_dst_clipped coords: %i,%i,%i,%i",
962                      rect_dest_clipped.left, rect_dest_clipped.top,
963                      rect_dest_clipped.right, rect_dest_clipped.bottom );
964 #endif
965
966     /* the 2 following lines are to fix a bug when clicking on the desktop */
967     if( (rect_dest_clipped.right - rect_dest_clipped.left)==0 ||
968         (rect_dest_clipped.bottom - rect_dest_clipped.top)==0 )
969     {
970         SetRectEmpty( &rect_src_clipped );
971         return;
972     }
973
974     /* src image dimensions */
975     rect_src.left = 0;
976     rect_src.top = 0;
977     rect_src.right = p_vout->output.i_width;
978     rect_src.bottom = p_vout->output.i_height;
979
980     /* Clip the source image */
981     rect_src_clipped.left = (rect_dest_clipped.left - rect_dest.left) *
982       p_vout->output.i_width / (rect_dest.right - rect_dest.left);
983     rect_src_clipped.right = p_vout->output.i_width -
984       (rect_dest.right - rect_dest_clipped.right) * p_vout->output.i_width /
985       (rect_dest.right - rect_dest.left);
986     rect_src_clipped.top = (rect_dest_clipped.top - rect_dest.top) *
987       p_vout->output.i_height / (rect_dest.bottom - rect_dest.top);
988     rect_src_clipped.bottom = p_vout->output.i_height -
989       (rect_dest.bottom - rect_dest_clipped.bottom) * p_vout->output.i_height /
990       (rect_dest.bottom - rect_dest.top);
991
992 #if 0
993     msg_Dbg( p_vout, "image_src_clipped coords: %i,%i,%i,%i",
994                      rect_src_clipped.left, rect_src_clipped.top,
995                      rect_src_clipped.right, rect_src_clipped.bottom );
996 #endif
997
998     /* The destination coordinates need to be relative to the current
999      * directdraw primary surface (display) */
1000     rect_dest_clipped.left -= p_vout->p_sys->rect_display.left;
1001     rect_dest_clipped.right -= p_vout->p_sys->rect_display.left;
1002     rect_dest_clipped.top -= p_vout->p_sys->rect_display.top;
1003     rect_dest_clipped.bottom -= p_vout->p_sys->rect_display.top;
1004
1005     /* Signal the change in size/position */
1006     p_vout->p_sys->i_changes |= DX_POSITION_CHANGE;
1007
1008 #undef rect_src
1009 #undef rect_src_clipped
1010 #undef rect_dest
1011 #undef rect_dest_clipped
1012 }
1013
1014 /*****************************************************************************
1015  * Message handler for the main window
1016  *****************************************************************************/
1017 static long FAR PASCAL WndProc( HWND hWnd, UINT message,
1018                                 WPARAM wParam, LPARAM lParam )
1019 {
1020     vout_thread_t *p_vout;
1021
1022     if( message == WM_CREATE )
1023     {
1024         /* Store p_vout for future use */
1025         p_vout = (vout_thread_t *)((CREATESTRUCT *)lParam)->lpCreateParams;
1026         SetWindowLongPtr( hWnd, GWLP_USERDATA, (LONG_PTR)p_vout );
1027         if( p_vout ) msg_Dbg( p_vout, "create: %p", hWnd );
1028     }
1029     else
1030     {
1031         p_vout = (vout_thread_t *)GetWindowLongPtr( hWnd, GWLP_USERDATA );
1032     }
1033
1034 #ifndef UNDER_CE
1035     /* Catch the screensaver and the monitor turn-off */
1036     if( message == WM_SYSCOMMAND &&
1037         ( wParam == SC_SCREENSAVE || wParam == SC_MONITORPOWER ) )
1038     {
1039         //if( p_vout ) msg_Dbg( p_vout, "WinProc WM_SYSCOMMAND screensaver" );
1040         return 0; /* this stops them from happening */
1041     }
1042 #endif
1043
1044     if( !p_vout )
1045     {
1046         /* Hmmm mozilla does manage somehow to save the pointer to our
1047          * windowproc and still calls it after the vout has been closed. */
1048         return DefWindowProc(hWnd, message, wParam, lParam);
1049     }
1050
1051     if( hWnd != p_vout->p_sys->hwnd &&
1052         hWnd != p_vout->p_sys->hvideownd )
1053         return DefWindowProc(hWnd, message, wParam, lParam);
1054
1055     switch( message )
1056     {
1057     case WM_WINDOWPOSCHANGED:
1058         if( hWnd == p_vout->p_sys->hwnd )
1059             UpdateRects( p_vout, VLC_TRUE );
1060         break;
1061
1062     case WM_ACTIVATE:
1063         msg_Err( p_vout, "WM_ACTIVATE: %i", wParam );
1064 #ifdef MODULE_NAME_IS_wingapi
1065         if( wParam == WA_ACTIVE || wParam == WA_CLICKACTIVE )
1066             GXResume();
1067         else if( wParam == WA_INACTIVE )
1068             GXSuspend();
1069 #endif
1070         break;
1071
1072 #ifdef MODULE_NAME_IS_wingapi
1073     case WM_KILLFOCUS:
1074       msg_Err( p_vout, "WM_KILLFOCUS" );
1075         GXSuspend();
1076         break;
1077
1078     case WM_SETFOCUS:
1079       msg_Err( p_vout, "WM_SETFOCUS" );
1080         GXResume();
1081         break;
1082 #endif
1083
1084     case WM_LBUTTONDOWN:
1085         p_vout->p_sys->i_changes |= VOUT_FULLSCREEN_CHANGE;
1086         break;
1087     case WM_MOUSEMOVE:
1088         break;
1089     case WM_LBUTTONUP:
1090         break;
1091
1092     case WM_INITMENUPOPUP:
1093         p_vout->p_sys->b_video_display = VLC_FALSE;
1094         break;
1095
1096     case WM_NOTIFY:
1097         // Redo the video display because menu can be closed
1098         // FIXME verify if p_child_window exits
1099         if( (((NMHDR *)lParam)->code) == NM_CUSTOMDRAW )
1100             p_vout->p_sys->b_video_display = VLC_TRUE;
1101         break;
1102
1103     case WM_DESTROY:
1104         msg_Dbg( p_vout, "WinProc WM_DESTROY" );
1105         PostQuitMessage( 0 );
1106         break;
1107
1108     default:
1109         return DefWindowProc( hWnd, message, wParam, lParam );
1110     }
1111
1112     return 0;
1113 }
1114
1115 /*****************************************************************************
1116  * InitBuffers: initialize an offscreen bitmap for direct buffer operations.
1117  *****************************************************************************/
1118 static void InitBuffers( vout_thread_t *p_vout )
1119 {
1120     BITMAPINFOHEADER *p_header = &p_vout->p_sys->bitmapinfo.bmiHeader;
1121     BITMAPINFO *p_info = &p_vout->p_sys->bitmapinfo;
1122     int i_pixels = p_vout->render.i_height * p_vout->render.i_width;
1123     HDC window_dc = GetDC( p_vout->p_sys->hvideownd );
1124
1125     /* Get screen properties */
1126 #ifdef MODULE_NAME_IS_wingapi
1127     GXDisplayProperties gx_displayprop = GXGetDisplayProperties();
1128     p_vout->p_sys->i_depth = gx_displayprop.cBPP;
1129 #else
1130     p_vout->p_sys->i_depth = GetDeviceCaps( window_dc, PLANES ) *
1131         GetDeviceCaps( window_dc, BITSPIXEL );
1132 #endif
1133     msg_Dbg( p_vout, "GDI depth is %i", p_vout->p_sys->i_depth );
1134
1135 #ifdef MODULE_NAME_IS_wingapi
1136     if( p_vout->b_fullscreen )
1137     {
1138         /* We need to restore Maximized sized window */
1139         GetWindowRect( p_vout->p_sys->hwnd,
1140                        &p_vout->p_sys->window_placement );
1141
1142         /* Maximized window */
1143         if( p_vout->p_sys->hparent )
1144         {
1145             SetWindowPos( GetParent( p_vout->p_sys->hwnd ), HWND_TOP,
1146                           0, 0, GetSystemMetrics(SM_CXSCREEN),
1147                           GetSystemMetrics(SM_CYSCREEN), SWP_SHOWWINDOW );
1148             SetWindowPos( p_vout->p_sys->hwnd, HWND_TOP,
1149                           0, 0, GetSystemMetrics(SM_CXSCREEN),
1150                           GetSystemMetrics(SM_CYSCREEN), SWP_SHOWWINDOW );
1151
1152 #if 0//def UNDER_CE
1153             /* Hide SIP button, taskbar and menubar */
1154             SHFullScreen( GetParent(p_vout->p_sys->hwnd),
1155                           SHFS_HIDESIPBUTTON );
1156             p_vout->p_sys->hTaskBar = FindWindow(_T("HHTaskbar"),NULL);
1157             ShowWindow( p_vout->p_sys->hTaskBar, SW_HIDE);
1158             p_vout->p_sys->hMenu =
1159               SHFindMenuBar( GetParent( p_vout->p_sys->hwnd ) );
1160             ShowWindow( p_vout->p_sys->hMenu,SW_HIDE );
1161 #endif
1162         }
1163         else
1164         {
1165             SetWindowPos( p_vout->p_sys->hwnd, HWND_TOP,
1166                           0, 0, CW_USEDEFAULT, CW_USEDEFAULT, SWP_SHOWWINDOW );
1167         }
1168
1169     }
1170
1171     GXOpenDisplay( p_vout->p_sys->hvideownd, GX_FULLSCREEN );
1172 #else
1173
1174     /* Initialize offscreen bitmap */
1175     memset( p_info, 0, sizeof( BITMAPINFO ) + 3 * sizeof( RGBQUAD ) );
1176
1177     p_header->biSize = sizeof( BITMAPINFOHEADER );
1178     p_header->biSizeImage = 0;
1179     p_header->biPlanes = 1;
1180     switch( p_vout->p_sys->i_depth )
1181     {
1182     case 8:
1183         p_header->biBitCount = 8;
1184         p_header->biCompression = BI_RGB;
1185         /* FIXME: we need a palette here */
1186         break;
1187     case 15:
1188         p_header->biBitCount = 15;
1189         p_header->biCompression = BI_BITFIELDS;//BI_RGB;
1190         ((DWORD*)p_info->bmiColors)[0] = 0x00007c00;
1191         ((DWORD*)p_info->bmiColors)[1] = 0x000003e0;
1192         ((DWORD*)p_info->bmiColors)[2] = 0x0000001f;
1193         break;
1194     case 16:
1195         p_header->biBitCount = 16;
1196         p_header->biCompression = BI_BITFIELDS;//BI_RGB;
1197         ((DWORD*)p_info->bmiColors)[0] = 0x0000f800;
1198         ((DWORD*)p_info->bmiColors)[1] = 0x000007e0;
1199         ((DWORD*)p_info->bmiColors)[2] = 0x0000001f;
1200         break;
1201     case 24:
1202         p_header->biBitCount = 24;
1203         p_header->biCompression = BI_RGB;
1204         ((DWORD*)p_info->bmiColors)[0] = 0x00ff0000;
1205         ((DWORD*)p_info->bmiColors)[1] = 0x0000ff00;
1206         ((DWORD*)p_info->bmiColors)[2] = 0x000000ff;
1207         break;
1208     case 32:
1209         p_header->biBitCount = 32;
1210         p_header->biCompression = BI_RGB;
1211         ((DWORD*)p_info->bmiColors)[0] = 0x00ff0000;
1212         ((DWORD*)p_info->bmiColors)[1] = 0x0000ff00;
1213         ((DWORD*)p_info->bmiColors)[2] = 0x000000ff;
1214         break;
1215     default:
1216         msg_Err( p_vout, "screen depth %i not supported",
1217                  p_vout->p_sys->i_depth );
1218         return;
1219         break;
1220     }
1221     p_header->biWidth = p_vout->render.i_width;
1222     p_header->biHeight = -p_vout->render.i_height;
1223     p_header->biClrImportant = 0;
1224     p_header->biClrUsed = 0;
1225     p_header->biXPelsPerMeter = 0;
1226     p_header->biYPelsPerMeter = 0;
1227
1228     p_vout->p_sys->i_pic_pixel_pitch = p_header->biBitCount / 8;
1229     p_vout->p_sys->i_pic_pitch = p_header->biBitCount * p_header->biWidth / 8;
1230
1231     p_vout->p_sys->off_bitmap =
1232         CreateDIBSection( window_dc, (BITMAPINFO *)p_header, DIB_RGB_COLORS,
1233                           (void**)&p_vout->p_sys->p_pic_buffer, NULL, 0 );
1234
1235     p_vout->p_sys->off_dc = CreateCompatibleDC( window_dc );
1236
1237     SelectObject( p_vout->p_sys->off_dc, p_vout->p_sys->off_bitmap );
1238     ReleaseDC( 0, window_dc );
1239 #endif
1240 }
1241
1242 /*****************************************************************************
1243  * Control: control facility for the vout
1244  *****************************************************************************/
1245 static int Control( vout_thread_t *p_vout, int i_query, va_list args )
1246 {
1247     vlc_bool_t b_bool;
1248
1249     switch( i_query )
1250     {
1251     case VOUT_SET_FOCUS:
1252         b_bool = va_arg( args, vlc_bool_t );
1253 #ifdef MODULE_NAME_IS_wingapi
1254         if( b_bool ) GXResume();
1255         else GXSuspend();
1256 #endif
1257         return VLC_SUCCESS;
1258
1259     default:
1260         return vout_vaControlDefault( p_vout, i_query, args );
1261     }
1262 }