]> git.sesse.net Git - vlc/blob - modules/video_output/msw/glwin32.c
10d52d471e61449dccf3a698a7c85b1701515f04
[vlc] / modules / video_output / msw / glwin32.c
1 /*****************************************************************************
2  * glwin32.c: Windows OpenGL provider
3  *****************************************************************************
4  * Copyright (C) 2001-2009 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Gildas Bazin <gbazin@videolan.org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23 #ifdef HAVE_CONFIG_H
24 # include "config.h"
25 #endif
26
27 #include <vlc_common.h>
28 #include <vlc_plugin.h>
29 #include <vlc_vout_display.h>
30
31 #include <windows.h>
32 #include <ddraw.h>
33 #include <commctrl.h>
34
35 #include <multimon.h>
36 #undef GetSystemMetrics
37
38 #ifndef MONITOR_DEFAULTTONEAREST
39 #   define MONITOR_DEFAULTTONEAREST 2
40 #endif
41
42 #include "../opengl.h"
43 #include "common.h"
44
45 /*****************************************************************************
46  * Module descriptor
47  *****************************************************************************/
48 static int  Open (vlc_object_t *);
49 static void Close(vlc_object_t *);
50
51 vlc_module_begin()
52     set_category(CAT_VIDEO)
53     set_subcategory(SUBCAT_VIDEO_VOUT)
54     set_shortname("OpenGL")
55     set_description(N_("OpenGL video output"))
56     set_capability("vout display", 20)
57     add_shortcut("glwin32")
58     add_shortcut("opengl")
59     set_callbacks(Open, Close)
60
61     /* FIXME: Hack to avoid unregistering our window class */
62     cannot_unload_broken_library ()
63 vlc_module_end()
64
65 #if 0 /* FIXME */
66     /* check if we registered a window class because we need to
67      * unregister it */
68     WNDCLASS wndclass;
69     if(GetClassInfo(GetModuleHandle(NULL), "VLC DirectX", &wndclass))
70         UnregisterClass("VLC DirectX", GetModuleHandle(NULL));
71 #endif
72
73
74 /*****************************************************************************
75  * Local prototypes.
76  *****************************************************************************/
77 static picture_pool_t *Pool  (vout_display_t *, unsigned);
78 static void           Prepare(vout_display_t *, picture_t *);
79 static void           Display(vout_display_t *, picture_t *);
80 static int            Control(vout_display_t *, int, va_list);
81 static void           Manage (vout_display_t *);
82
83 static void           Swap   (vout_opengl_t *);
84
85 /**
86  * It creates an OpenGL vout display.
87  */
88 static int Open(vlc_object_t *object)
89 {
90     vout_display_t *vd = (vout_display_t *)object;
91     vout_display_sys_t *sys;
92
93     /* Allocate structure */
94     vd->sys = sys = calloc(1, sizeof(*sys));
95     if (!sys)
96         return VLC_ENOMEM;
97
98     /* */
99     if (CommonInit(vd))
100         goto error;
101
102     EventThreadUpdateTitle(sys->event, VOUT_TITLE " (OpenGL output)");
103
104     /* */
105     sys->hGLDC = GetDC(sys->hvideownd);
106
107     /* Set the pixel format for the DC */
108     PIXELFORMATDESCRIPTOR pfd;
109     memset(&pfd, 0, sizeof(pfd));
110     pfd.nSize = sizeof(pfd);
111     pfd.nVersion = 1;
112     pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
113     pfd.iPixelType = PFD_TYPE_RGBA;
114     pfd.cColorBits = 24;
115     pfd.cDepthBits = 16;
116     pfd.iLayerType = PFD_MAIN_PLANE;
117     SetPixelFormat(sys->hGLDC,
118                    ChoosePixelFormat(sys->hGLDC, &pfd), &pfd);
119
120     /* Create and enable the render context */
121     sys->hGLRC = wglCreateContext(sys->hGLDC);
122     wglMakeCurrent(sys->hGLDC, sys->hGLRC);
123
124     /* */
125     sys->gl.lock = NULL;
126     sys->gl.unlock = NULL;
127     sys->gl.swap = Swap;
128     sys->gl.sys = vd;
129
130     video_format_t fmt = vd->fmt;
131     if (vout_display_opengl_Init(&sys->vgl, &fmt, &sys->gl))
132         goto error;
133
134     vout_display_info_t info = vd->info;
135     info.has_double_click = true;
136     info.has_hide_mouse = true;
137     info.has_pictures_invalid = true;
138     info.has_event_thread = true;
139
140    /* Setup vout_display now that everything is fine */
141     vd->fmt  = fmt;
142     vd->info = info;
143
144     vd->pool    = Pool;
145     vd->prepare = Prepare;
146     vd->display = Display;
147     vd->control = Control;
148     vd->manage  = Manage;
149
150     return VLC_SUCCESS;
151
152 error:
153     Close(object);
154     return VLC_EGENERIC;
155 }
156
157 /**
158  * It destroys an OpenGL vout display.
159  */
160 static void Close(vlc_object_t *object)
161 {
162     vout_display_t *vd = (vout_display_t *)object;
163     vout_display_sys_t *sys = vd->sys;
164
165     if (sys->vgl.gl)
166         vout_display_opengl_Clean(&sys->vgl);
167
168     if (sys->hGLDC && sys->hGLRC)
169         wglMakeCurrent(NULL, NULL);
170     if (sys->hGLRC)
171         wglDeleteContext(sys->hGLRC);
172     if (sys->hGLDC)
173         ReleaseDC(sys->hvideownd, sys->hGLDC);
174
175     CommonClean(vd);
176
177     free(sys);
178 }
179
180 /* */
181 static picture_pool_t *Pool(vout_display_t *vd, unsigned count)
182 {
183     vout_display_sys_t *sys = vd->sys;
184     VLC_UNUSED(count);
185
186     if (!sys->pool)
187         sys->pool = vout_display_opengl_GetPool(&sys->vgl);
188     return sys->pool;
189 }
190
191 static void Prepare(vout_display_t *vd, picture_t *picture)
192 {
193     vout_display_sys_t *sys = vd->sys;
194
195     vout_display_opengl_Prepare(&sys->vgl, picture);
196 }
197
198 static void Display(vout_display_t *vd, picture_t *picture)
199 {
200     vout_display_sys_t *sys = vd->sys;
201
202     vout_display_opengl_Display(&sys->vgl, &vd->source);
203
204     picture_Release(picture);
205
206     CommonDisplay(vd);
207 }
208
209 static int Control(vout_display_t *vd, int query, va_list args)
210 {
211     switch (query) {
212     case VOUT_DISPLAY_GET_OPENGL: {
213         vout_opengl_t **gl = va_arg(args, vout_opengl_t **);
214         *gl = &vd->sys->gl;
215         return VLC_SUCCESS;
216     }
217     default:
218         return CommonControl(vd, query, args);
219     }
220 }
221
222 static void Manage (vout_display_t *vd)
223 {
224     vout_display_sys_t *sys = vd->sys;
225
226     CommonManage(vd);
227
228     const int width  = sys->rect_dest.right  - sys->rect_dest.left;
229     const int height = sys->rect_dest.bottom - sys->rect_dest.top;
230     glViewport(0, 0, width, height);
231 }
232
233 static void Swap(vout_opengl_t *gl)
234 {
235     vout_display_t *vd = gl->sys;
236
237     SwapBuffers(vd->sys->hGLDC);
238 }
239