1 /*****************************************************************************
2 * wingdi.c : Win32 / WinCE GDI video output plugin for vlc
3 *****************************************************************************
4 * Copyright (C) 2002-2009 VLC authors and VideoLAN
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 it
11 * under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this program; if not, write to the Free Software Foundation,
22 * 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>
42 /*****************************************************************************
44 *****************************************************************************/
45 static int Open (vlc_object_t
*);
46 static void Close(vlc_object_t
*);
49 set_category(CAT_VIDEO
)
50 set_subcategory(SUBCAT_VIDEO_VOUT
)
52 set_description(N_("Windows GDI video output"))
53 set_capability("vout display", 110)
54 set_callbacks(Open
, Close
)
58 /*****************************************************************************
60 *****************************************************************************/
61 struct vout_display_sys_t
63 vout_display_sys_win32_t sys
;
67 /* Our offscreen bitmap and its framebuffer */
73 BITMAPINFO bitmapinfo
;
80 static picture_pool_t
*Pool (vout_display_t
*, unsigned);
81 static void Display(vout_display_t
*, picture_t
*, subpicture_t
*subpicture
);
82 static int Control(vout_display_t
*, int, va_list);
83 static void Manage (vout_display_t
*);
85 static int Init(vout_display_t
*, video_format_t
*, int, int);
86 static void Clean(vout_display_t
*);
89 static int Open(vlc_object_t
*object
)
91 vout_display_t
*vd
= (vout_display_t
*)object
;
92 vout_display_sys_t
*sys
;
94 if ( !vd
->obj
.force
&& vd
->source
.projection_mode
!= PROJECTION_MODE_RECTANGULAR
)
95 return VLC_EGENERIC
; /* let a module who can handle it do it */
97 vd
->sys
= sys
= calloc(1, sizeof(*sys
));
105 video_format_t fmt
= vd
->fmt
;
106 if (Init(vd
, &fmt
, fmt
.i_width
, fmt
.i_height
))
109 vout_display_info_t info
= vd
->info
;
110 info
.is_slow
= false;
111 info
.has_double_click
= true;
112 info
.has_pictures_invalid
= true;
120 vd
->display
= Display
;
122 vd
->control
= Control
;
126 Close(VLC_OBJECT(vd
));
131 static void Close(vlc_object_t
*object
)
133 vout_display_t
*vd
= (vout_display_t
*)object
;
143 static picture_pool_t
*Pool(vout_display_t
*vd
, unsigned count
)
146 return vd
->sys
->sys
.pool
;
149 static void Display(vout_display_t
*vd
, picture_t
*picture
, subpicture_t
*subpicture
)
151 vout_display_sys_t
*sys
= vd
->sys
;
153 #define rect_src vd->sys->rect_src
154 #define rect_src_clipped vd->sys->sys.rect_src_clipped
155 #define rect_dest vd->sys->sys.rect_dest
156 #define rect_dest_clipped vd->sys->sys.rect_dest_clipped
157 RECT rect_dst
= rect_dest_clipped
;
158 HDC hdc
= GetDC(sys
->sys
.hvideownd
);
160 OffsetRect(&rect_dst
, -rect_dest
.left
, -rect_dest
.top
);
161 SelectObject(sys
->off_dc
, sys
->off_bitmap
);
163 if (rect_dest_clipped
.right
- rect_dest_clipped
.left
!=
164 rect_src_clipped
.right
- rect_src_clipped
.left
||
165 rect_dest_clipped
.bottom
- rect_dest_clipped
.top
!=
166 rect_src_clipped
.bottom
- rect_src_clipped
.top
) {
167 StretchBlt(hdc
, rect_dst
.left
, rect_dst
.top
,
168 rect_dst
.right
, rect_dst
.bottom
,
170 rect_src_clipped
.left
, rect_src_clipped
.top
,
171 rect_src_clipped
.right
, rect_src_clipped
.bottom
,
174 BitBlt(hdc
, rect_dst
.left
, rect_dst
.top
,
175 rect_dst
.right
, rect_dst
.bottom
,
177 rect_src_clipped
.left
, rect_src_clipped
.top
,
181 ReleaseDC(sys
->sys
.hvideownd
, hdc
);
183 #undef rect_src_clipped
185 #undef rect_dest_clipped
187 picture_Release(picture
);
188 VLC_UNUSED(subpicture
);
193 static int Control(vout_display_t
*vd
, int query
, va_list args
)
196 case VOUT_DISPLAY_RESET_PICTURES
:
197 vlc_assert_unreachable();
200 return CommonControl(vd
, query
, args
);
205 static void Manage(vout_display_t
*vd
)
210 static int Init(vout_display_t
*vd
,
211 video_format_t
*fmt
, int width
, int height
)
213 vout_display_sys_t
*sys
= vd
->sys
;
216 RECT
*display
= &sys
->sys
.rect_display
;
219 display
->right
= GetSystemMetrics(SM_CXSCREEN
);;
220 display
->bottom
= GetSystemMetrics(SM_CYSCREEN
);;
222 /* Initialize an offscreen bitmap for direct buffer operations. */
225 HDC window_dc
= GetDC(sys
->sys
.hvideownd
);
228 sys
->i_depth
= GetDeviceCaps(window_dc
, PLANES
) *
229 GetDeviceCaps(window_dc
, BITSPIXEL
);
232 msg_Dbg(vd
, "GDI depth is %i", sys
->i_depth
);
233 switch (sys
->i_depth
) {
235 fmt
->i_chroma
= VLC_CODEC_RGB8
;
238 fmt
->i_chroma
= VLC_CODEC_RGB15
;
239 fmt
->i_rmask
= 0x7c00;
240 fmt
->i_gmask
= 0x03e0;
241 fmt
->i_bmask
= 0x001f;
244 fmt
->i_chroma
= VLC_CODEC_RGB16
;
245 fmt
->i_rmask
= 0xf800;
246 fmt
->i_gmask
= 0x07e0;
247 fmt
->i_bmask
= 0x001f;
250 fmt
->i_chroma
= VLC_CODEC_RGB24
;
251 fmt
->i_rmask
= 0x00ff0000;
252 fmt
->i_gmask
= 0x0000ff00;
253 fmt
->i_bmask
= 0x000000ff;
256 fmt
->i_chroma
= VLC_CODEC_RGB32
;
257 fmt
->i_rmask
= 0x00ff0000;
258 fmt
->i_gmask
= 0x0000ff00;
259 fmt
->i_bmask
= 0x000000ff;
262 msg_Err(vd
, "screen depth %i not supported", sys
->i_depth
);
265 fmt
->i_width
= width
;
266 fmt
->i_height
= height
;
270 /* Initialize offscreen bitmap */
271 BITMAPINFO
*bi
= &sys
->bitmapinfo
;
272 memset(bi
, 0, sizeof(BITMAPINFO
) + 3 * sizeof(RGBQUAD
));
273 if (sys
->i_depth
> 8) {
274 ((DWORD
*)bi
->bmiColors
)[0] = fmt
->i_rmask
;
275 ((DWORD
*)bi
->bmiColors
)[1] = fmt
->i_gmask
;
276 ((DWORD
*)bi
->bmiColors
)[2] = fmt
->i_bmask
;;
279 BITMAPINFOHEADER
*bih
= &sys
->bitmapinfo
.bmiHeader
;
280 bih
->biSize
= sizeof(BITMAPINFOHEADER
);
281 bih
->biSizeImage
= 0;
283 bih
->biCompression
= (sys
->i_depth
== 15 ||
284 sys
->i_depth
== 16) ? BI_BITFIELDS
: BI_RGB
;
285 bih
->biBitCount
= sys
->i_depth
;
286 bih
->biWidth
= fmt
->i_width
;
287 bih
->biHeight
= -fmt
->i_height
;
288 bih
->biClrImportant
= 0;
290 bih
->biXPelsPerMeter
= 0;
291 bih
->biYPelsPerMeter
= 0;
293 i_pic_pitch
= bih
->biBitCount
* bih
->biWidth
/ 8;
294 sys
->off_bitmap
= CreateDIBSection(window_dc
,
297 &p_pic_buffer
, NULL
, 0);
299 sys
->off_dc
= CreateCompatibleDC(window_dc
);
301 SelectObject(sys
->off_dc
, sys
->off_bitmap
);
302 ReleaseDC(sys
->sys
.hvideownd
, window_dc
);
304 EventThreadUpdateTitle(sys
->sys
.event
, VOUT_TITLE
" (WinGDI output)");
307 picture_resource_t rsc
;
308 memset(&rsc
, 0, sizeof(rsc
));
309 rsc
.p
[0].p_pixels
= p_pic_buffer
;
310 rsc
.p
[0].i_lines
= fmt
->i_height
;
311 rsc
.p
[0].i_pitch
= i_pic_pitch
;;
313 picture_t
*picture
= picture_NewFromResource(fmt
, &rsc
);
315 sys
->sys
.pool
= picture_pool_New(1, &picture
);
317 sys
->sys
.pool
= NULL
;
319 UpdateRects(vd
, NULL
, true);
324 static void Clean(vout_display_t
*vd
)
326 vout_display_sys_t
*sys
= vd
->sys
;
329 picture_pool_Release(sys
->sys
.pool
);
330 sys
->sys
.pool
= NULL
;
333 DeleteDC(sys
->off_dc
);
335 DeleteObject(sys
->off_bitmap
);