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