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_vout_display.h>
43 #ifndef WS_NONAVDONEBUTTON
44 # define WS_NONAVDONEBUTTON 0
47 /*****************************************************************************
49 *****************************************************************************/
50 static int Open (vlc_object_t *);
51 static void Close(vlc_object_t *);
54 set_category(CAT_VIDEO)
55 set_subcategory(SUBCAT_VIDEO_VOUT)
57 set_description(N_("Windows GDI video output"))
58 set_capability("vout display", 110)
59 set_callbacks(Open, Close)
63 /*****************************************************************************
65 *****************************************************************************/
66 static picture_pool_t *Pool (vout_display_t *, unsigned);
67 static void Display(vout_display_t *, picture_t *, subpicture_t *subpicture);
68 static int Control(vout_display_t *, int, va_list);
69 static void Manage (vout_display_t *);
71 static int Init(vout_display_t *, video_format_t *, int, int);
72 static void Clean(vout_display_t *);
75 static int Open(vlc_object_t *object)
77 vout_display_t *vd = (vout_display_t *)object;
78 vout_display_sys_t *sys;
80 vd->sys = sys = calloc(1, sizeof(*sys));
88 video_format_t fmt = vd->fmt;
89 if (Init(vd, &fmt, fmt.i_width, fmt.i_height))
92 vout_display_info_t info = vd->info;
94 info.has_double_click = true;
95 info.has_hide_mouse = false;
96 info.has_pictures_invalid = true;
104 vd->display = Display;
106 vd->control = Control;
110 Close(VLC_OBJECT(vd));
115 static void Close(vlc_object_t *object)
117 vout_display_t *vd = (vout_display_t *)object;
127 static picture_pool_t *Pool(vout_display_t *vd, unsigned count)
130 return vd->sys->pool;
132 static void Display(vout_display_t *vd, picture_t *picture, subpicture_t *subpicture)
134 vout_display_sys_t *sys = vd->sys;
136 #define rect_src vd->sys->rect_src
137 #define rect_src_clipped vd->sys->rect_src_clipped
138 #define rect_dest vd->sys->rect_dest
139 #define rect_dest_clipped vd->sys->rect_dest_clipped
140 RECT rect_dst = rect_dest_clipped;
141 HDC hdc = GetDC(sys->hvideownd);
143 OffsetRect(&rect_dst, -rect_dest.left, -rect_dest.top);
144 SelectObject(sys->off_dc, sys->off_bitmap);
146 if (rect_dest_clipped.right - rect_dest_clipped.left !=
147 rect_src_clipped.right - rect_src_clipped.left ||
148 rect_dest_clipped.bottom - rect_dest_clipped.top !=
149 rect_src_clipped.bottom - rect_src_clipped.top) {
150 StretchBlt(hdc, rect_dst.left, rect_dst.top,
151 rect_dst.right, rect_dst.bottom,
153 rect_src_clipped.left, rect_src_clipped.top,
154 rect_src_clipped.right, rect_src_clipped.bottom,
157 BitBlt(hdc, rect_dst.left, rect_dst.top,
158 rect_dst.right, rect_dst.bottom,
160 rect_src_clipped.left, rect_src_clipped.top,
164 ReleaseDC(sys->hvideownd, hdc);
166 #undef rect_src_clipped
168 #undef rect_dest_clipped
170 picture_Release(picture);
171 VLC_UNUSED(subpicture);
175 static int Control(vout_display_t *vd, int query, va_list args)
178 case VOUT_DISPLAY_RESET_PICTURES:
182 return CommonControl(vd, query, args);
186 static void Manage(vout_display_t *vd)
191 static int Init(vout_display_t *vd,
192 video_format_t *fmt, int width, int height)
194 vout_display_sys_t *sys = vd->sys;
197 RECT *display = &sys->rect_display;
200 display->right = GetSystemMetrics(SM_CXSCREEN);;
201 display->bottom = GetSystemMetrics(SM_CYSCREEN);;
203 /* Initialize an offscreen bitmap for direct buffer operations. */
206 HDC window_dc = GetDC(sys->hvideownd);
209 sys->i_depth = GetDeviceCaps(window_dc, PLANES) *
210 GetDeviceCaps(window_dc, BITSPIXEL);
213 msg_Dbg(vd, "GDI depth is %i", sys->i_depth);
214 switch (sys->i_depth) {
216 fmt->i_chroma = VLC_CODEC_RGB8;
219 fmt->i_chroma = VLC_CODEC_RGB15;
220 fmt->i_rmask = 0x7c00;
221 fmt->i_gmask = 0x03e0;
222 fmt->i_bmask = 0x001f;
225 fmt->i_chroma = VLC_CODEC_RGB16;
226 fmt->i_rmask = 0xf800;
227 fmt->i_gmask = 0x07e0;
228 fmt->i_bmask = 0x001f;
231 fmt->i_chroma = VLC_CODEC_RGB24;
232 fmt->i_rmask = 0x00ff0000;
233 fmt->i_gmask = 0x0000ff00;
234 fmt->i_bmask = 0x000000ff;
237 fmt->i_chroma = VLC_CODEC_RGB32;
238 fmt->i_rmask = 0x00ff0000;
239 fmt->i_gmask = 0x0000ff00;
240 fmt->i_bmask = 0x000000ff;
243 msg_Err(vd, "screen depth %i not supported", sys->i_depth);
246 fmt->i_width = width;
247 fmt->i_height = height;
251 /* Initialize offscreen bitmap */
252 BITMAPINFO *bi = &sys->bitmapinfo;
253 memset(bi, 0, sizeof(BITMAPINFO) + 3 * sizeof(RGBQUAD));
254 if (sys->i_depth > 8) {
255 ((DWORD*)bi->bmiColors)[0] = fmt->i_rmask;
256 ((DWORD*)bi->bmiColors)[1] = fmt->i_gmask;
257 ((DWORD*)bi->bmiColors)[2] = fmt->i_bmask;;
260 BITMAPINFOHEADER *bih = &sys->bitmapinfo.bmiHeader;
261 bih->biSize = sizeof(BITMAPINFOHEADER);
262 bih->biSizeImage = 0;
264 bih->biCompression = (sys->i_depth == 15 ||
265 sys->i_depth == 16) ? BI_BITFIELDS : BI_RGB;
266 bih->biBitCount = sys->i_depth;
267 bih->biWidth = fmt->i_width;
268 bih->biHeight = -fmt->i_height;
269 bih->biClrImportant = 0;
271 bih->biXPelsPerMeter = 0;
272 bih->biYPelsPerMeter = 0;
274 i_pic_pitch = bih->biBitCount * bih->biWidth / 8;
275 sys->off_bitmap = CreateDIBSection(window_dc,
278 &p_pic_buffer, NULL, 0);
280 sys->off_dc = CreateCompatibleDC(window_dc);
282 SelectObject(sys->off_dc, sys->off_bitmap);
283 ReleaseDC(sys->hvideownd, window_dc);
285 EventThreadUpdateTitle(sys->event, VOUT_TITLE " (WinGDI output)");
288 picture_resource_t rsc;
289 memset(&rsc, 0, sizeof(rsc));
290 rsc.p[0].p_pixels = p_pic_buffer;
291 rsc.p[0].i_lines = fmt->i_height;
292 rsc.p[0].i_pitch = i_pic_pitch;;
294 picture_t *picture = picture_NewFromResource(fmt, &rsc);
296 picture_pool_configuration_t cfg;
297 memset(&cfg, 0, sizeof(cfg));
298 cfg.picture_count = 1;
299 cfg.picture = &picture;
300 sys->pool = picture_pool_NewExtended(&cfg);
306 UpdateRects(vd, NULL, NULL, true);
311 static void Clean(vout_display_t *vd)
313 vout_display_sys_t *sys = vd->sys;
316 picture_pool_Delete(sys->pool);
320 DeleteDC(sys->off_dc);
322 DeleteObject(sys->off_bitmap);