1 /*****************************************************************************
2 * wingdi.c : Win32 / WinCE GDI video output plugin for vlc
3 *****************************************************************************
4 * Copyright (C) 2002-2009 the VideoLAN team
7 * Authors: Gildas Bazin <gbazin@videolan.org>
8 * Samuel Hocevar <sam@zoy.org>
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.
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.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
33 #include <vlc_common.h>
34 #include <vlc_plugin.h>
35 #include <vlc_interface.h>
36 #include <vlc_playlist.h>
43 /*#ifdef MODULE_NAME_IS_wingapi
44 typedef struct GXDisplayProperties {
51 } GXDisplayProperties;
53 typedef struct GXScreenRect {
60 # define GX_FULLSCREEN 0x01
61 # define GX_NORMALKEYS 0x02
62 # define GX_LANDSCAPEKEYS 0x03
65 # define kfLandscape 0x8
66 # define kfPalette 0x10
67 # define kfDirect 0x20
68 # define kfDirect555 0x40
69 # define kfDirect565 0x80
70 # define kfDirect888 0x100
71 # define kfDirect444 0x200
72 # define kfDirectInverted 0x400
74 #endif */ /* MODULE_NAME_IS_wingapi */
78 #define MAX_DIRECTBUFFERS 10
81 #ifndef WS_OVERLAPPEDWINDOW
82 # define WS_OVERLAPPEDWINDOW 0xcf0000
84 #ifndef WS_EX_NOPARENTNOTIFY
85 # define WS_EX_NOPARENTNOTIFY 4
87 #ifndef WS_EX_APPWINDOW
88 #define WS_EX_APPWINDOW 0x40000
90 //#define SetWindowLongPtr SetWindowLong
91 //#define GetWindowLongPtr GetWindowLong
92 //#define GWLP_USERDATA GWL_USERDATA
93 #define AdjustWindowRect(a,b,c)
96 #ifndef WS_NONAVDONEBUTTON
97 #define WS_NONAVDONEBUTTON 0
99 /*****************************************************************************
101 *****************************************************************************/
102 static int OpenVideo ( vlc_object_t * );
103 static void CloseVideo ( vlc_object_t * );
105 static int Init ( vout_thread_t * );
106 static void End ( vout_thread_t * );
107 static int Manage ( vout_thread_t * );
108 static void Render ( vout_thread_t *, picture_t * );
109 #ifdef MODULE_NAME_IS_wingapi
110 static void FirstDisplayGAPI( vout_thread_t *, picture_t * );
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 * );
115 static void FirstDisplayGDI( vout_thread_t *, picture_t * );
116 static void DisplayGDI( vout_thread_t *, picture_t * );
118 static void SetPalette( vout_thread_t *, uint16_t *, uint16_t *, uint16_t * );
120 static void InitBuffers ( vout_thread_t * );
124 #define DX_POSITION_CHANGE 0x1000
126 /*****************************************************************************
128 *****************************************************************************/
130 set_category( CAT_VIDEO )
131 set_subcategory( SUBCAT_VIDEO_VOUT )
132 #ifdef MODULE_NAME_IS_wingapi
133 set_shortname( "Windows GAPI" )
134 set_description( N_("Windows GAPI video output") )
135 set_capability( "video output", 20 )
137 set_shortname( "Windows GDI" )
138 set_description( N_("Windows GDI video output") )
139 set_capability( "video output", 10 )
141 set_callbacks( OpenVideo, CloseVideo )
144 /*****************************************************************************
145 * OpenVideo: activate GDI video thread output method
146 *****************************************************************************/
147 static int OpenVideo ( vlc_object_t *p_this )
149 vout_thread_t * p_vout = (vout_thread_t *)p_this;
151 p_vout->p_sys = (vout_sys_t *)calloc( 1, sizeof(vout_sys_t) );
152 if( !p_vout->p_sys ) return VLC_ENOMEM;
154 #ifdef MODULE_NAME_IS_wingapi
156 p_vout->p_sys->gapi_dll = LoadLibrary( _T("GX.DLL") );
157 if( p_vout->p_sys->gapi_dll == NULL )
159 msg_Warn( p_vout, "failed loading gx.dll" );
160 free( p_vout->p_sys );
164 GXOpenDisplay = (void *)GetProcAddress( p_vout->p_sys->gapi_dll,
165 _T("?GXOpenDisplay@@YAHPAUHWND__@@K@Z") );
166 GXCloseDisplay = (void *)GetProcAddress( p_vout->p_sys->gapi_dll,
167 _T("?GXCloseDisplay@@YAHXZ") );
168 GXBeginDraw = (void *)GetProcAddress( p_vout->p_sys->gapi_dll,
169 _T("?GXBeginDraw@@YAPAXXZ") );
170 GXEndDraw = (void *)GetProcAddress( p_vout->p_sys->gapi_dll,
171 _T("?GXEndDraw@@YAHXZ") );
172 GXGetDisplayProperties = (void *)GetProcAddress( p_vout->p_sys->gapi_dll,
173 _T("?GXGetDisplayProperties@@YA?AUGXDisplayProperties@@XZ") );
174 GXSuspend = (void *)GetProcAddress( p_vout->p_sys->gapi_dll,
175 _T("?GXSuspend@@YAHXZ") );
176 GXResume = GetProcAddress( p_vout->p_sys->gapi_dll,
177 _T("?GXResume@@YAHXZ") );
179 if( !GXOpenDisplay || !GXCloseDisplay || !GXBeginDraw || !GXEndDraw ||
180 !GXGetDisplayProperties || !GXSuspend || !GXResume )
182 msg_Err( p_vout, "failed GetProcAddress on gapi.dll" );
183 free( p_vout->p_sys );
187 msg_Dbg( p_vout, "GAPI DLL loaded" );
189 p_vout->p_sys->render_width = p_vout->render.i_width;
190 p_vout->p_sys->render_height = p_vout->render.i_height;
193 p_vout->p_sys->p_event = (vlc_object_t *)
194 vlc_object_create( p_vout, sizeof( vlc_object_t ) );
195 if( !p_vout->p_sys->p_event )
197 free( p_vout->p_sys );
201 p_vout->pf_init = Init;
202 p_vout->pf_end = End;
203 p_vout->pf_manage = Manage;
204 p_vout->pf_render = Render;
205 #ifdef MODULE_NAME_IS_wingapi
206 p_vout->pf_display = FirstDisplayGAPI;
208 p_vout->p_sys->b_focus = 0;
209 p_vout->p_sys->b_parent_focus = 0;
212 p_vout->pf_display = FirstDisplayGDI;
215 p_vout->p_sys->hwnd = p_vout->p_sys->hvideownd = NULL;
216 p_vout->p_sys->hparent = p_vout->p_sys->hfswnd = NULL;
217 p_vout->p_sys->i_changes = 0;
218 vlc_mutex_init( &p_vout->p_sys->lock );
219 SetRectEmpty( &p_vout->p_sys->rect_display );
220 SetRectEmpty( &p_vout->p_sys->rect_parent );
222 var_Create( p_vout, "video-title", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
223 var_Create( p_vout, "disable-screensaver", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
225 p_vout->p_sys->b_cursor_hidden = 0;
226 p_vout->p_sys->i_lastmoved = mdate();
227 p_vout->p_sys->i_mouse_hide_timeout =
228 var_GetInteger(p_vout, "mouse-hide-timeout") * 1000;
230 /* Set main window's size */
231 p_vout->p_sys->i_window_width = p_vout->i_window_width;
232 p_vout->p_sys->i_window_height = p_vout->i_window_height;
234 if ( CreateEventThread( p_vout ) )
238 /* Variable to indicate if the window should be on top of others */
239 /* Trigger a callback right now */
240 var_TriggerCallback( p_vout, "video-on-top" );
242 DisableScreensaver ( p_vout );
248 CloseVideo( VLC_OBJECT(p_vout) );
253 /*****************************************************************************
254 * CloseVideo: deactivate the GDI video output
255 *****************************************************************************/
256 static void CloseVideo ( vlc_object_t *p_this )
258 vout_thread_t * p_vout = (vout_thread_t *)p_this;
260 StopEventThread( p_vout );
263 RestoreScreensaver( p_vout );
266 #ifdef MODULE_NAME_IS_wingapi
267 FreeLibrary( p_vout->p_sys->gapi_dll );
270 free( p_vout->p_sys );
271 p_vout->p_sys = NULL;
274 /*****************************************************************************
275 * Init: initialize video thread output method
276 *****************************************************************************/
277 static int Init( vout_thread_t *p_vout )
281 /* Initialize offscreen buffer */
282 InitBuffers( p_vout );
284 p_vout->p_sys->rect_display.left = 0;
285 p_vout->p_sys->rect_display.top = 0;
286 p_vout->p_sys->rect_display.right = GetSystemMetrics(SM_CXSCREEN);
287 p_vout->p_sys->rect_display.bottom = GetSystemMetrics(SM_CYSCREEN);
289 I_OUTPUTPICTURES = 0;
291 /* Initialize the output structure */
292 switch( p_vout->p_sys->i_depth )
295 p_vout->output.i_chroma = VLC_CODEC_RGB8;
296 p_vout->output.pf_setpalette = SetPalette;
299 p_vout->output.i_chroma = VLC_CODEC_RGB15;
300 p_vout->output.i_rmask = 0x7c00;
301 p_vout->output.i_gmask = 0x03e0;
302 p_vout->output.i_bmask = 0x001f;
305 p_vout->output.i_chroma = VLC_CODEC_RGB16;
306 p_vout->output.i_rmask = 0xf800;
307 p_vout->output.i_gmask = 0x07e0;
308 p_vout->output.i_bmask = 0x001f;
311 p_vout->output.i_chroma = VLC_CODEC_RGB24;
312 p_vout->output.i_rmask = 0x00ff0000;
313 p_vout->output.i_gmask = 0x0000ff00;
314 p_vout->output.i_bmask = 0x000000ff;
317 p_vout->output.i_chroma = VLC_CODEC_RGB32;
318 p_vout->output.i_rmask = 0x00ff0000;
319 p_vout->output.i_gmask = 0x0000ff00;
320 p_vout->output.i_bmask = 0x000000ff;
323 msg_Err( p_vout, "screen depth %i not supported",
324 p_vout->p_sys->i_depth );
329 p_pic = &p_vout->p_picture[0];
331 #ifdef MODULE_NAME_IS_wingapi
332 p_vout->output.i_width = 0;
333 p_vout->output.i_height = 0;
334 p_pic->pf_lock = GAPILockSurface;
335 p_pic->pf_unlock = GAPIUnlockSurface;
337 GAPILockSurface( p_vout, p_pic );
338 p_vout->i_changes = 0;
339 p_vout->output.i_width = p_vout->p_sys->render_width;
340 p_vout->output.i_height = p_vout->p_sys->render_height;
343 p_vout->output.i_width = p_vout->render.i_width;
344 p_vout->output.i_height = p_vout->render.i_height;
346 p_vout->fmt_out = p_vout->fmt_in;
347 p_vout->fmt_out.i_chroma = p_vout->output.i_chroma;
350 p_vout->output.i_aspect = p_vout->render.i_aspect;
352 p_pic->p->p_pixels = p_vout->p_sys->p_pic_buffer;
353 p_pic->p->i_lines = p_vout->output.i_height;
354 p_pic->p->i_visible_lines = p_vout->output.i_height;
355 p_pic->p->i_pitch = p_vout->p_sys->i_pic_pitch;
356 p_pic->p->i_pixel_pitch = p_vout->p_sys->i_pic_pixel_pitch;
357 p_pic->p->i_visible_pitch = p_vout->output.i_width *
358 p_pic->p->i_pixel_pitch;
360 p_pic->i_status = DESTROYED_PICTURE;
361 p_pic->i_type = DIRECT_PICTURE;
363 PP_OUTPUTPICTURE[ I_OUTPUTPICTURES++ ] = p_pic;
365 /* Change the window title bar text */
366 PostMessage( p_vout->p_sys->hwnd, WM_VLC_CHANGE_TEXT, 0, 0 );
367 UpdateRects( p_vout, true );
372 /*****************************************************************************
373 * End: terminate video thread output method
374 *****************************************************************************/
375 static void End( vout_thread_t *p_vout )
377 #ifdef MODULE_NAME_IS_wingapi
380 DeleteDC( p_vout->p_sys->off_dc );
381 DeleteObject( p_vout->p_sys->off_bitmap );
385 /*****************************************************************************
386 * Manage: handle events
387 *****************************************************************************
388 * This function should be called regularly by video output thread. It manages
389 * console events. It returns a non null value on error.
390 *****************************************************************************/
391 static int Manage( vout_thread_t *p_vout )
393 /* If we do not control our window, we check for geometry changes
394 * ourselves because the parent might not send us its events. */
395 vlc_mutex_lock( &p_vout->p_sys->lock );
396 if( p_vout->p_sys->hparent && !p_vout->b_fullscreen )
401 vlc_mutex_unlock( &p_vout->p_sys->lock );
403 GetClientRect( p_vout->p_sys->hparent, &rect_parent );
404 point.x = point.y = 0;
405 ClientToScreen( p_vout->p_sys->hparent, &point );
406 OffsetRect( &rect_parent, point.x, point.y );
408 if( !EqualRect( &rect_parent, &p_vout->p_sys->rect_parent ) )
410 int i_x, i_y, i_width, i_height;
411 p_vout->p_sys->rect_parent = rect_parent;
413 /* This one is to force the update even if only
414 * the position has changed */
415 SetWindowPos( p_vout->p_sys->hwnd, 0, 1, 1,
416 rect_parent.right - rect_parent.left,
417 rect_parent.bottom - rect_parent.top, 0 );
419 SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0,
420 rect_parent.right - rect_parent.left,
421 rect_parent.bottom - rect_parent.top, 0 );
423 vout_PlacePicture( p_vout, rect_parent.right - rect_parent.left,
424 rect_parent.bottom - rect_parent.top,
425 &i_x, &i_y, &i_width, &i_height );
427 SetWindowPos( p_vout->p_sys->hvideownd, HWND_TOP,
428 i_x, i_y, i_width, i_height, 0 );
433 vlc_mutex_unlock( &p_vout->p_sys->lock );
436 /* autoscale toggle */
437 if( p_vout->i_changes & VOUT_SCALE_CHANGE )
439 p_vout->i_changes &= ~VOUT_SCALE_CHANGE;
441 p_vout->b_autoscale = var_GetBool( p_vout, "autoscale" );
442 p_vout->i_zoom = (int) ZOOM_FP_FACTOR;
444 UpdateRects( p_vout, true );
448 if( p_vout->i_changes & VOUT_ZOOM_CHANGE )
450 p_vout->i_changes &= ~VOUT_ZOOM_CHANGE;
452 p_vout->b_autoscale = false;
454 (int)( ZOOM_FP_FACTOR * var_GetFloat( p_vout, "scale" ) );
455 UpdateRects( p_vout, true );
458 /* Check for cropping / aspect changes */
459 if( p_vout->i_changes & VOUT_CROP_CHANGE ||
460 p_vout->i_changes & VOUT_ASPECT_CHANGE )
462 p_vout->i_changes &= ~VOUT_CROP_CHANGE;
463 p_vout->i_changes &= ~VOUT_ASPECT_CHANGE;
465 p_vout->fmt_out.i_x_offset = p_vout->fmt_in.i_x_offset;
466 p_vout->fmt_out.i_y_offset = p_vout->fmt_in.i_y_offset;
467 p_vout->fmt_out.i_visible_width = p_vout->fmt_in.i_visible_width;
468 p_vout->fmt_out.i_visible_height = p_vout->fmt_in.i_visible_height;
469 p_vout->fmt_out.i_aspect = p_vout->fmt_in.i_aspect;
470 p_vout->fmt_out.i_sar_num = p_vout->fmt_in.i_sar_num;
471 p_vout->fmt_out.i_sar_den = p_vout->fmt_in.i_sar_den;
472 p_vout->output.i_aspect = p_vout->fmt_in.i_aspect;
473 UpdateRects( p_vout, true );
479 if( p_vout->p_sys->i_changes & DX_POSITION_CHANGE )
481 p_vout->p_sys->i_changes &= ~DX_POSITION_CHANGE;
484 /* We used to call the Win32 PeekMessage function here to read the window
485 * messages. But since window can stay blocked into this function for a
486 * long time (for example when you move your window on the screen), I
487 * decided to isolate PeekMessage in another thread. */
492 if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE
493 || p_vout->p_sys->i_changes & VOUT_FULLSCREEN_CHANGE )
495 Win32ToggleFullscreen( p_vout );
497 p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
498 p_vout->p_sys->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
504 if( p_vout->b_fullscreen && !p_vout->p_sys->b_cursor_hidden &&
505 (mdate() - p_vout->p_sys->i_lastmoved) >
506 p_vout->p_sys->i_mouse_hide_timeout )
511 /* Hide the cursor only if it is inside our window */
512 GetCursorPos( &point );
513 hwnd = WindowFromPoint(point);
514 if( hwnd == p_vout->p_sys->hwnd || hwnd == p_vout->p_sys->hvideownd )
516 PostMessage( p_vout->p_sys->hwnd, WM_VLC_HIDE_MOUSE, 0, 0 );
520 p_vout->p_sys->i_lastmoved = mdate();
525 * "Always on top" status change
527 if( p_vout->p_sys->b_on_top_change )
530 HMENU hMenu = GetSystemMenu( p_vout->p_sys->hwnd, FALSE );
532 var_Get( p_vout, "video-on-top", &val );
534 /* Set the window on top if necessary */
535 if( val.b_bool && !( GetWindowLong( p_vout->p_sys->hwnd, GWL_EXSTYLE )
538 CheckMenuItem( hMenu, IDM_TOGGLE_ON_TOP,
539 MF_BYCOMMAND | MFS_CHECKED );
540 SetWindowPos( p_vout->p_sys->hwnd, HWND_TOPMOST, 0, 0, 0, 0,
541 SWP_NOSIZE | SWP_NOMOVE );
544 /* The window shouldn't be on top */
545 if( !val.b_bool && ( GetWindowLong( p_vout->p_sys->hwnd, GWL_EXSTYLE )
548 CheckMenuItem( hMenu, IDM_TOGGLE_ON_TOP,
549 MF_BYCOMMAND | MFS_UNCHECKED );
550 SetWindowPos( p_vout->p_sys->hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
551 SWP_NOSIZE | SWP_NOMOVE );
554 p_vout->p_sys->b_on_top_change = false;
557 /* Check if the event thread is still running */
558 if( !vlc_object_alive (p_vout->p_sys->p_event) )
560 return VLC_EGENERIC; /* exit */
566 /*****************************************************************************
567 * Render: render previously calculated output
568 *****************************************************************************/
569 static void Render( vout_thread_t *p_vout, picture_t *p_pic )
571 /* No need to do anything, the fake direct buffers stay as they are */
576 /*****************************************************************************
577 * Display: displays previously rendered output
578 *****************************************************************************/
579 #define rect_src p_vout->p_sys->rect_src
580 #define rect_src_clipped p_vout->p_sys->rect_src_clipped
581 #define rect_dest p_vout->p_sys->rect_dest
582 #define rect_dest_clipped p_vout->p_sys->rect_dest_clipped
584 #ifndef MODULE_NAME_IS_wingapi
585 static void DisplayGDI( vout_thread_t *p_vout, picture_t *p_pic )
587 vout_sys_t *p_sys = p_vout->p_sys;
588 RECT rect_dst = rect_dest_clipped;
589 HDC hdc = GetDC( p_sys->hvideownd );
591 OffsetRect( &rect_dst, -rect_dest.left, -rect_dest.top );
592 SelectObject( p_sys->off_dc, p_sys->off_bitmap );
594 if( rect_dest_clipped.right - rect_dest_clipped.left !=
595 rect_src_clipped.right - rect_src_clipped.left ||
596 rect_dest_clipped.bottom - rect_dest_clipped.top !=
597 rect_src_clipped.bottom - rect_src_clipped.top )
599 StretchBlt( hdc, rect_dst.left, rect_dst.top,
600 rect_dst.right, rect_dst.bottom,
601 p_sys->off_dc, rect_src_clipped.left, rect_src_clipped.top,
602 rect_src_clipped.right, rect_src_clipped.bottom, SRCCOPY );
606 BitBlt( hdc, rect_dst.left, rect_dst.top,
607 rect_dst.right, rect_dst.bottom,
608 p_sys->off_dc, rect_src_clipped.left,
609 rect_src_clipped.top, SRCCOPY );
612 ReleaseDC( p_sys->hvideownd, hdc );
615 static void FirstDisplayGDI( vout_thread_t *p_vout, picture_t *p_pic )
618 ** Video window is initially hidden, show it now since we got a
621 SetWindowPos( p_vout->p_sys->hvideownd, 0, 0, 0, 0, 0,
629 /* get initial picture presented */
630 DisplayGDI(p_vout, p_pic);
632 /* use and restores proper display function for further pictures */
633 p_vout->pf_display = DisplayGDI;
638 static int GAPILockSurface( vout_thread_t *p_vout, picture_t *p_pic )
640 vout_sys_t *p_sys = p_vout->p_sys;
641 int i_x, i_y, i_width, i_height;
645 GetClientRect( p_sys->hwnd, &video_rect);
646 vout_PlacePicture( p_vout, video_rect.right - video_rect.left,
647 video_rect.bottom - video_rect.top,
648 &i_x, &i_y, &i_width, &i_height );
649 point.x = point.y = 0;
650 ClientToScreen( p_sys->hwnd, &point );
651 i_x += point.x + video_rect.left;
652 i_y += point.y + video_rect.top;
654 if( i_width != p_vout->output.i_width ||
655 i_height != p_vout->output.i_height )
657 GXDisplayProperties gxdisplayprop = GXGetDisplayProperties();
659 p_sys->render_width = i_width;
660 p_sys->render_height = i_height;
661 p_vout->i_changes |= VOUT_SIZE_CHANGE;
663 msg_Dbg( p_vout, "vout size change (%ix%i -> %ix%i)",
664 i_width, i_height, p_vout->output.i_width,
665 p_vout->output.i_height );
667 p_vout->p_sys->i_pic_pixel_pitch = gxdisplayprop.cbxPitch;
668 p_vout->p_sys->i_pic_pitch = gxdisplayprop.cbyPitch;
673 GXDisplayProperties gxdisplayprop;
674 RECT display_rect, dest_rect;
675 uint8_t *p_dest, *p_src = p_pic->p->p_pixels;
677 video_rect.left = i_x; video_rect.top = i_y;
678 video_rect.right = i_x + i_width;
679 video_rect.bottom = i_y + i_height;
681 gxdisplayprop = GXGetDisplayProperties();
682 display_rect.left = 0; display_rect.top = 0;
683 display_rect.right = gxdisplayprop.cxWidth;
684 display_rect.bottom = gxdisplayprop.cyHeight;
686 if( !IntersectRect( &dest_rect, &video_rect, &display_rect ) )
692 msg_Err( p_vout, "video (%d,%d,%d,%d) display (%d,%d,%d,%d) "
693 "dest (%d,%d,%d,%d)",
694 video_rect.left, video_rect.right,
695 video_rect.top, video_rect.bottom,
696 display_rect.left, display_rect.right,
697 display_rect.top, display_rect.bottom,
698 dest_rect.left, dest_rect.right,
699 dest_rect.top, dest_rect.bottom );
702 if( !(p_dest = GXBeginDraw()) )
705 msg_Err( p_vout, "GXBeginDraw error %d ", GetLastError() );
710 p_src += (dest_rect.left - video_rect.left) * gxdisplayprop.cbxPitch +
711 (dest_rect.top - video_rect.top) * p_pic->p->i_pitch;
712 p_dest += dest_rect.left * gxdisplayprop.cbxPitch +
713 dest_rect.top * gxdisplayprop.cbyPitch;
714 i_width = dest_rect.right - dest_rect.left;
715 i_height = dest_rect.bottom - dest_rect.top;
717 p_pic->p->p_pixels = p_dest;
723 static int GAPIUnlockSurface( vout_thread_t *p_vout, picture_t *p_pic )
729 static void DisplayGAPI( vout_thread_t *p_vout, picture_t *p_pic )
733 static void FirstDisplayGAPI( vout_thread_t *p_vout, picture_t *p_pic )
735 /* get initial picture presented through D3D */
736 DisplayGAPI(p_vout, p_pic);
739 ** Video window is initially hidden, show it now since we got a
742 SetWindowPos( p_vout->p_sys->hvideownd, 0, 0, 0, 0, 0,
750 /* use and restores proper display function for further pictures */
751 p_vout->pf_display = DisplayGAPI;
757 #undef rect_src_clipped
759 #undef rect_dest_clipped
760 /*****************************************************************************
761 * SetPalette: sets an 8 bpp palette
762 *****************************************************************************/
763 static void SetPalette( vout_thread_t *p_vout,
764 uint16_t *red, uint16_t *green, uint16_t *blue )
766 msg_Err( p_vout, "FIXME: SetPalette unimplemented" );
769 /*****************************************************************************
770 * InitBuffers: initialize an offscreen bitmap for direct buffer operations.
771 *****************************************************************************/
772 static void InitBuffers( vout_thread_t *p_vout )
774 BITMAPINFOHEADER *p_header = &p_vout->p_sys->bitmapinfo.bmiHeader;
775 BITMAPINFO *p_info = &p_vout->p_sys->bitmapinfo;
776 HDC window_dc = GetDC( p_vout->p_sys->hvideownd );
778 /* Get screen properties */
779 #ifdef MODULE_NAME_IS_wingapi
780 GXDisplayProperties gx_displayprop = GXGetDisplayProperties();
781 p_vout->p_sys->i_depth = gx_displayprop.cBPP;
783 p_vout->p_sys->i_depth = GetDeviceCaps( window_dc, PLANES ) *
784 GetDeviceCaps( window_dc, BITSPIXEL );
786 msg_Dbg( p_vout, "GDI depth is %i", p_vout->p_sys->i_depth );
788 #ifdef MODULE_NAME_IS_wingapi
789 GXOpenDisplay( p_vout->p_sys->hvideownd, GX_FULLSCREEN );
793 /* Initialize offscreen bitmap */
794 memset( p_info, 0, sizeof( BITMAPINFO ) + 3 * sizeof( RGBQUAD ) );
796 p_header->biSize = sizeof( BITMAPINFOHEADER );
797 p_header->biSizeImage = 0;
798 p_header->biPlanes = 1;
799 switch( p_vout->p_sys->i_depth )
802 p_header->biBitCount = 8;
803 p_header->biCompression = BI_RGB;
804 /* FIXME: we need a palette here */
807 p_header->biBitCount = 15;
808 p_header->biCompression = BI_BITFIELDS;//BI_RGB;
809 ((DWORD*)p_info->bmiColors)[0] = 0x00007c00;
810 ((DWORD*)p_info->bmiColors)[1] = 0x000003e0;
811 ((DWORD*)p_info->bmiColors)[2] = 0x0000001f;
814 p_header->biBitCount = 16;
815 p_header->biCompression = BI_BITFIELDS;//BI_RGB;
816 ((DWORD*)p_info->bmiColors)[0] = 0x0000f800;
817 ((DWORD*)p_info->bmiColors)[1] = 0x000007e0;
818 ((DWORD*)p_info->bmiColors)[2] = 0x0000001f;
821 p_header->biBitCount = 24;
822 p_header->biCompression = BI_RGB;
823 ((DWORD*)p_info->bmiColors)[0] = 0x00ff0000;
824 ((DWORD*)p_info->bmiColors)[1] = 0x0000ff00;
825 ((DWORD*)p_info->bmiColors)[2] = 0x000000ff;
828 p_header->biBitCount = 32;
829 p_header->biCompression = BI_RGB;
830 ((DWORD*)p_info->bmiColors)[0] = 0x00ff0000;
831 ((DWORD*)p_info->bmiColors)[1] = 0x0000ff00;
832 ((DWORD*)p_info->bmiColors)[2] = 0x000000ff;
835 msg_Err( p_vout, "screen depth %i not supported",
836 p_vout->p_sys->i_depth );
840 p_header->biWidth = p_vout->render.i_width;
841 p_header->biHeight = -p_vout->render.i_height;
842 p_header->biClrImportant = 0;
843 p_header->biClrUsed = 0;
844 p_header->biXPelsPerMeter = 0;
845 p_header->biYPelsPerMeter = 0;
847 p_vout->p_sys->i_pic_pixel_pitch = p_header->biBitCount / 8;
848 p_vout->p_sys->i_pic_pitch = p_header->biBitCount * p_header->biWidth / 8;
850 p_vout->p_sys->off_bitmap =
851 CreateDIBSection( window_dc, (BITMAPINFO *)p_header, DIB_RGB_COLORS,
852 (void**)&p_vout->p_sys->p_pic_buffer, NULL, 0 );
854 p_vout->p_sys->off_dc = CreateCompatibleDC( window_dc );
856 SelectObject( p_vout->p_sys->off_dc, p_vout->p_sys->off_bitmap );
857 ReleaseDC( p_vout->p_sys->hvideownd, window_dc );