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 *****************************************************************************/
34 #include <vlc_common.h>
35 #include <vlc_plugin.h>
36 #include <vlc_playlist.h>
37 #include <vlc_vout_display.h>
44 #ifndef WS_NONAVDONEBUTTON
45 # define WS_NONAVDONEBUTTON 0
48 /*****************************************************************************
50 *****************************************************************************/
51 static int Open (vlc_object_t *);
52 static void Close(vlc_object_t *);
55 set_category(CAT_VIDEO)
56 set_subcategory(SUBCAT_VIDEO_VOUT)
57 #ifdef MODULE_NAME_IS_wingapi
59 set_description(N_("Windows GAPI video output"))
60 set_capability("vout display", 20)
63 set_description(N_("Windows GDI video output"))
64 set_capability("vout display", 10)
66 set_callbacks(Open, Close)
70 /*****************************************************************************
72 *****************************************************************************/
73 static picture_pool_t *Pool (vout_display_t *, unsigned);
74 static void Display(vout_display_t *, picture_t *);
75 static int Control(vout_display_t *, int, va_list);
76 static void Manage (vout_display_t *);
78 static int Init(vout_display_t *, video_format_t *, int, int);
79 static void Clean(vout_display_t *);
82 static int Open(vlc_object_t *object)
84 vout_display_t *vd = (vout_display_t *)object;
85 vout_display_sys_t *sys;
87 vd->sys = sys = calloc(1, sizeof(*sys));
91 #ifdef MODULE_NAME_IS_wingapi
93 sys->gapi_dll = LoadLibrary(_T("GX.DLL"));
95 msg_Warn(vd, "failed loading gx.dll");
100 GXOpenDisplay = (void *)GetProcAddress(sys->gapi_dll,
101 _T("?GXOpenDisplay@@YAHPAUHWND__@@K@Z"));
102 GXCloseDisplay = (void *)GetProcAddress(sys->gapi_dll,
103 _T("?GXCloseDisplay@@YAHXZ"));
104 GXBeginDraw = (void *)GetProcAddress(sys->gapi_dll,
105 _T("?GXBeginDraw@@YAPAXXZ"));
106 GXEndDraw = (void *)GetProcAddress(sys->gapi_dll,
107 _T("?GXEndDraw@@YAHXZ"));
108 GXGetDisplayProperties = (void *)GetProcAddress(sys->gapi_dll,
109 _T("?GXGetDisplayProperties@@YA?AUGXDisplayProperties@@XZ"));
110 GXSuspend = (void *)GetProcAddress(sys->gapi_dll,
111 _T("?GXSuspend@@YAHXZ"));
112 GXResume = GetProcAddress(sys->gapi_dll,
113 _T("?GXResume@@YAHXZ"));
115 if (!GXOpenDisplay || !GXCloseDisplay ||
116 !GXBeginDraw || !GXEndDraw ||
117 !GXGetDisplayProperties || !GXSuspend || !GXResume) {
118 msg_Err(vd, "failed GetProcAddress on gapi.dll");
123 msg_Dbg(vd, "GAPI DLL loaded");
130 video_format_t fmt = vd->fmt;
131 if (Init(vd, &fmt, fmt.i_width, fmt.i_height))
134 vout_display_info_t info = vd->info;
135 info.is_slow = false;
136 info.has_double_click = true;
137 info.has_hide_mouse = false;
138 info.has_pictures_invalid = true;
146 vd->display = Display;
148 vd->control = Control;
152 Close(VLC_OBJECT(vd));
157 static void Close(vlc_object_t *object)
159 vout_display_t *vd = (vout_display_t *)object;
165 #ifdef MODULE_NAME_IS_wingapi
166 FreeLibrary(vd->sys->gapi_dll);
173 static picture_pool_t *Pool(vout_display_t *vd, unsigned count)
176 return vd->sys->pool;
178 static void Display(vout_display_t *vd, picture_t *picture)
180 vout_display_sys_t *sys = vd->sys;
182 #ifdef MODULE_NAME_IS_wingapi
185 #define rect_src vd->sys->rect_src
186 #define rect_src_clipped vd->sys->rect_src_clipped
187 #define rect_dest vd->sys->rect_dest
188 #define rect_dest_clipped vd->sys->rect_dest_clipped
189 RECT rect_dst = rect_dest_clipped;
190 HDC hdc = GetDC(sys->hvideownd);
192 OffsetRect(&rect_dst, -rect_dest.left, -rect_dest.top);
193 SelectObject(sys->off_dc, sys->off_bitmap);
195 if (rect_dest_clipped.right - rect_dest_clipped.left !=
196 rect_src_clipped.right - rect_src_clipped.left ||
197 rect_dest_clipped.bottom - rect_dest_clipped.top !=
198 rect_src_clipped.bottom - rect_src_clipped.top) {
199 StretchBlt(hdc, rect_dst.left, rect_dst.top,
200 rect_dst.right, rect_dst.bottom,
202 rect_src_clipped.left, rect_src_clipped.top,
203 rect_src_clipped.right, rect_src_clipped.bottom,
206 BitBlt(hdc, rect_dst.left, rect_dst.top,
207 rect_dst.right, rect_dst.bottom,
209 rect_src_clipped.left, rect_src_clipped.top,
213 ReleaseDC(sys->hvideownd, hdc);
215 #undef rect_src_clipped
217 #undef rect_dest_clipped
220 picture_Release(picture);
224 static int Control(vout_display_t *vd, int query, va_list args)
227 case VOUT_DISPLAY_RESET_PICTURES:
231 return CommonControl(vd, query, args);
235 static void Manage(vout_display_t *vd)
240 #ifdef MODULE_NAME_IS_wingapi
241 struct picture_sys_t {
245 static int Lock(picture_t *picture)
247 vout_display_t *vd = picture->p_sys->vd;
248 vout_display_sys_t *sys = vd->sys;
251 if (sys->rect_dest_clipped.right - sys->rect_dest_clipped.left != vd->fmt.i_width ||
252 sys->rect_dest_clipped.bottom - sys->rect_dest_clipped.top != vd->fmt.i_height)
256 GXDisplayProperties gxdisplayprop = GXGetDisplayProperties();
257 uint8_t *p_pic_buffer = GXBeginDraw();
259 msg_Err(vd, "GXBeginDraw error %d ", GetLastError());
262 p_pic_buffer += sys->rect_dest.top * gxdisplayprop.cbyPitch +
263 sys->rect_dest.left * gxdisplayprop.cbxPitch;
266 picture->p[0].i_pitch = gxdisplayprop.cbyPitch;
267 picture->p[0].p_pixels = p_pic_buffer;
271 static void Unlock(picture_t *picture)
273 vout_display_t *vd = picture->p_sys->vd;
279 static int Init(vout_display_t *vd,
280 video_format_t *fmt, int width, int height)
282 vout_display_sys_t *sys = vd->sys;
285 RECT *display = &sys->rect_display;
288 #ifdef MODULE_NAME_IS_wingapi
289 display->right = GXGetDisplayProperties().cxWidth;
290 display->bottom = GXGetDisplayProperties().cyHeight;
292 display->right = GetSystemMetrics(SM_CXSCREEN);;
293 display->bottom = GetSystemMetrics(SM_CYSCREEN);;
296 /* Initialize an offscreen bitmap for direct buffer operations. */
299 HDC window_dc = GetDC(sys->hvideownd);
302 #ifdef MODULE_NAME_IS_wingapi
303 GXDisplayProperties gx_displayprop = GXGetDisplayProperties();
304 sys->i_depth = gx_displayprop.cBPP;
307 sys->i_depth = GetDeviceCaps(window_dc, PLANES) *
308 GetDeviceCaps(window_dc, BITSPIXEL);
312 msg_Dbg(vd, "GDI depth is %i", sys->i_depth);
313 switch (sys->i_depth) {
315 fmt->i_chroma = VLC_CODEC_RGB8;
318 fmt->i_chroma = VLC_CODEC_RGB15;
319 fmt->i_rmask = 0x7c00;
320 fmt->i_gmask = 0x03e0;
321 fmt->i_bmask = 0x001f;
324 fmt->i_chroma = VLC_CODEC_RGB16;
325 fmt->i_rmask = 0xf800;
326 fmt->i_gmask = 0x07e0;
327 fmt->i_bmask = 0x001f;
330 fmt->i_chroma = VLC_CODEC_RGB24;
331 fmt->i_rmask = 0x00ff0000;
332 fmt->i_gmask = 0x0000ff00;
333 fmt->i_bmask = 0x000000ff;
336 fmt->i_chroma = VLC_CODEC_RGB32;
337 fmt->i_rmask = 0x00ff0000;
338 fmt->i_gmask = 0x0000ff00;
339 fmt->i_bmask = 0x000000ff;
342 msg_Err(vd, "screen depth %i not supported", sys->i_depth);
345 fmt->i_width = width;
346 fmt->i_height = height;
348 uint8_t *p_pic_buffer;
350 #ifdef MODULE_NAME_IS_wingapi
351 GXOpenDisplay(sys->hvideownd, GX_FULLSCREEN);
352 EventThreadUpdateTitle(sys->event, VOUT_TITLE " (WinGAPI output)");
354 /* Filled by pool::lock() */
358 /* Initialize offscreen bitmap */
359 BITMAPINFO *bi = &sys->bitmapinfo;
360 memset(bi, 0, sizeof(BITMAPINFO) + 3 * sizeof(RGBQUAD));
361 if (sys->i_depth > 8) {
362 ((DWORD*)bi->bmiColors)[0] = fmt->i_rmask;
363 ((DWORD*)bi->bmiColors)[1] = fmt->i_gmask;
364 ((DWORD*)bi->bmiColors)[2] = fmt->i_bmask;;
367 BITMAPINFOHEADER *bih = &sys->bitmapinfo.bmiHeader;
368 bih->biSize = sizeof(BITMAPINFOHEADER);
369 bih->biSizeImage = 0;
371 bih->biCompression = (sys->i_depth == 15 ||
372 sys->i_depth == 16) ? BI_BITFIELDS : BI_RGB;
373 bih->biBitCount = sys->i_depth;
374 bih->biWidth = fmt->i_width;
375 bih->biHeight = -fmt->i_height;
376 bih->biClrImportant = 0;
378 bih->biXPelsPerMeter = 0;
379 bih->biYPelsPerMeter = 0;
381 i_pic_pitch = bih->biBitCount * bih->biWidth / 8;
382 sys->off_bitmap = CreateDIBSection(window_dc,
385 &p_pic_buffer, NULL, 0);
387 sys->off_dc = CreateCompatibleDC(window_dc);
389 SelectObject(sys->off_dc, sys->off_bitmap);
390 ReleaseDC(sys->hvideownd, window_dc);
392 EventThreadUpdateTitle(sys->event, VOUT_TITLE " (WinGDI output)");
396 picture_resource_t rsc;
397 memset(&rsc, 0, sizeof(rsc));
398 #ifdef MODULE_NAME_IS_wingapi
399 rsc.p_sys = malloc(sizeof(*rsc.p_sys));
404 rsc.p[0].p_pixels = p_pic_buffer;
405 rsc.p[0].i_lines = fmt->i_height;
406 rsc.p[0].i_pitch = i_pic_pitch;;
408 picture_t *picture = picture_NewFromResource(fmt, &rsc);
410 picture_pool_configuration_t cfg;
411 memset(&cfg, 0, sizeof(cfg));
412 cfg.picture_count = 1;
413 cfg.picture = &picture;
414 #ifdef MODULE_NAME_IS_wingapi
418 sys->pool = picture_pool_NewExtended(&cfg);
424 UpdateRects(vd, NULL, NULL, true);
429 static void Clean(vout_display_t *vd)
431 vout_display_sys_t *sys = vd->sys;
434 picture_pool_Delete(sys->pool);
437 #ifdef MODULE_NAME_IS_wingapi
441 DeleteDC(sys->off_dc);
443 DeleteObject(sys->off_bitmap);