]> git.sesse.net Git - vlc/blob - modules/video_output/directfb.c
Use var_Inherit* instead of var_CreateGet*.
[vlc] / modules / video_output / directfb.c
1 /*****************************************************************************
2  * directfb.c: DirectFB video output display method
3  *****************************************************************************
4  * Copyright (C) 2005-2009 the VideoLAN team
5  *
6  * Authors: Iuri Diniz <iuri@digizap.com.br>
7  *
8  * This code is based in sdl.c and fb.c, thanks for VideoLAN team.
9  *
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.
14  *
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.
19  *
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  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <vlc_common.h>
33 #include <vlc_plugin.h>
34 #include <vlc_vout_display.h>
35 #include <vlc_picture_pool.h>
36
37 #include <directfb.h>
38
39 /*****************************************************************************
40  * Module descriptor
41  *****************************************************************************/
42 static int  Open (vlc_object_t *);
43 static void Close(vlc_object_t *);
44
45 vlc_module_begin()
46     set_shortname("DirectFB")
47     set_category(CAT_VIDEO)
48     set_subcategory(SUBCAT_VIDEO_VOUT)
49     set_description(N_("DirectFB video output http://www.directfb.org/"))
50     set_capability("vout display", 60)
51     add_shortcut("directfb")
52     set_callbacks(Open, Close)
53 vlc_module_end()
54
55 /*****************************************************************************
56  * Local prototypes
57  *****************************************************************************/
58 static picture_pool_t *Pool  (vout_display_t *, unsigned);
59 static void           Display(vout_display_t *, picture_t *);
60 static int            Control(vout_display_t *, int, va_list);
61 static void           Manage (vout_display_t *);
62
63 /* */
64 static int  OpenDisplay (vout_display_t *);
65 static void CloseDisplay(vout_display_t *);
66
67 /* */
68 struct vout_display_sys_t {
69     /* */
70     IDirectFB             *directfb;
71     IDirectFBSurface      *primary;
72     DFBSurfacePixelFormat pixel_format;
73
74     /* */
75     int width;
76     int height;
77
78     /* */
79     picture_pool_t *pool;
80 };
81
82 /* */
83 static int Open(vlc_object_t *object)
84 {
85     vout_display_t *vd = (vout_display_t *)object;
86     vout_display_sys_t *sys;
87
88     /* Allocate structure */
89     vd->sys = sys = malloc(sizeof(*sys));
90     if (!sys)
91         return VLC_ENOMEM;
92
93     sys->directfb = NULL;
94     sys->primary  = NULL;
95     sys->width    = 0;
96     sys->height   = 0;
97     sys->pool     = NULL;
98
99     /* Init DirectFB */
100     if (DirectFBInit(NULL,NULL) != DFB_OK) {
101         msg_Err(vd, "Cannot init DirectFB");
102         free(sys);
103         return VLC_EGENERIC;
104     }
105
106     if (OpenDisplay(vd)) {
107         msg_Err(vd, "Cannot create primary surface");
108         Close(VLC_OBJECT(vd));
109         return VLC_EGENERIC;
110     }
111     vout_display_DeleteWindow(vd, NULL);
112
113     /* */
114     video_format_t fmt = vd->fmt;
115
116     switch (sys->pixel_format) {
117     case DSPF_RGB332:
118         /* 8 bit RGB (1 byte, red 3@5, green 3@2, blue 2@0) */
119         fmt.i_chroma = VLC_CODEC_RGB8;
120         fmt.i_rmask = 0x7 << 5;
121         fmt.i_gmask = 0x7 << 2;
122         fmt.i_bmask = 0x3 << 0;
123         break;
124     case DSPF_RGB16:
125         /* 16 bit RGB (2 byte, red 5@11, green 6@5, blue 5@0) */
126         fmt.i_chroma = VLC_CODEC_RGB16;
127         fmt.i_rmask = 0x1f << 11;
128         fmt.i_gmask = 0x3f <<  5;
129         fmt.i_bmask = 0x1f <<  0;
130         break;
131     case DSPF_RGB24:
132         /* 24 bit RGB (3 byte, red 8@16, green 8@8, blue 8@0) */
133         fmt.i_chroma = VLC_CODEC_RGB24;
134         fmt.i_rmask = 0xff << 16;
135         fmt.i_gmask = 0xff <<  8;
136         fmt.i_bmask = 0xff <<  0;
137         break;
138     case DSPF_RGB32:
139         /* 24 bit RGB (4 byte, nothing@24, red 8@16, green 8@8, blue 8@0) */
140         fmt.i_chroma = VLC_CODEC_RGB32;
141         fmt.i_rmask = 0xff << 16;
142         fmt.i_gmask = 0xff <<  8;
143         fmt.i_bmask = 0xff <<  0;
144         break;
145     default:
146         msg_Err(vd, "unknown screen depth %i", sys->pixel_format);
147         Close(VLC_OBJECT(vd));
148         return VLC_EGENERIC;
149     }
150
151     fmt.i_width  = sys->width;
152     fmt.i_height = sys->height;
153
154     /* */
155     vout_display_info_t info = vd->info;
156     info.has_hide_mouse = true;
157
158     /* */
159     vd->fmt     = fmt;
160     vd->info    = info;
161     vd->pool    = Pool;
162     vd->prepare = NULL;
163     vd->display = Display;
164     vd->control = Control;
165     vd->manage  = Manage;
166
167     /* */
168     vout_display_SendEventFullscreen(vd, true);
169     vout_display_SendEventDisplaySize(vd, fmt.i_width, fmt.i_height, true);
170     return VLC_SUCCESS;
171 }
172
173 static void Close(vlc_object_t *object)
174 {
175     vout_display_t *vd = (vout_display_t *)object;
176     vout_display_sys_t *sys = vd->sys;
177
178     if (sys->pool)
179         picture_pool_Delete(sys->pool);
180
181     CloseDisplay(vd);
182     free(sys);
183 }
184
185 /* */
186 static picture_pool_t *Pool(vout_display_t *vd, unsigned count)
187 {
188     vout_display_sys_t *sys = vd->sys;
189
190     if (!sys->pool)
191         sys->pool = picture_pool_NewFromFormat(&vd->fmt, count);
192     return sys->pool;
193 }
194
195 static void Display(vout_display_t *vd, picture_t *picture)
196 {
197     vout_display_sys_t *sys = vd->sys;
198
199     IDirectFBSurface *primary = sys->primary;
200
201     void *pixels;
202     int  pitch;
203     if (primary->Lock(primary, DSLF_WRITE, &pixels, &pitch) == DFB_OK) {
204         picture_resource_t rsc;
205
206         memset(&rsc, 0, sizeof(rsc));
207         rsc.p[0].p_pixels = pixels;
208         rsc.p[0].i_lines  = sys->height;
209         rsc.p[0].i_pitch  = pitch;
210
211         picture_t *direct = picture_NewFromResource(&vd->fmt, &rsc);
212         if (direct) {
213             picture_Copy(direct, picture);
214             picture_Release(direct);
215         }
216
217         if (primary->Unlock(primary) == DFB_OK)
218             primary->Flip(primary, NULL, 0);
219     }
220     picture_Release(picture);
221 }
222
223 static int Control(vout_display_t *vd, int query, va_list args)
224 {
225     switch (query) {
226     case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE: {
227         const vout_display_cfg_t *cfg = va_arg(args, const vout_display_cfg_t *);
228         if (cfg->display.width  != vd->fmt.i_width ||
229             cfg->display.height != vd->fmt.i_height)
230             return VLC_EGENERIC;
231         return VLC_SUCCESS;
232     }
233     default:
234         msg_Err(vd, "Unsupported query in vout display directfb");
235         return VLC_EGENERIC;
236     }
237 }
238
239 static void Manage (vout_display_t *vd)
240 {
241     VLC_UNUSED(vd);
242 }
243
244 static int OpenDisplay(vout_display_t *vd)
245 {
246     vout_display_sys_t *sys = vd->sys;
247
248     DFBSurfaceDescription dsc;
249     /*dsc.flags = DSDESC_CAPS | DSDESC_HEIGHT | DSDESC_WIDTH;*/
250     dsc.flags = DSDESC_CAPS;
251     dsc.caps  = DSCAPS_PRIMARY | DSCAPS_FLIPPING;
252     /*dsc.width = 352;*/
253     /*dsc.height = 240;*/
254
255     IDirectFB *directfb = NULL;
256     if (DirectFBCreate(&directfb) != DFB_OK || !directfb)
257         return VLC_EGENERIC;
258     sys->directfb = directfb;
259
260     IDirectFBSurface *primary = NULL;
261     if (directfb->CreateSurface(directfb, &dsc, &primary) || !primary)
262         return VLC_EGENERIC;
263     sys->primary = primary;
264
265     primary->GetSize(primary, &sys->width, &sys->height);
266     primary->GetPixelFormat(primary, &sys->pixel_format);
267     primary->FillRectangle(primary, 0, 0, sys->width, sys->height);
268     primary->Flip(primary, NULL, 0);
269
270     return VLC_SUCCESS;
271 }
272
273 static void CloseDisplay(vout_display_t *vd)
274 {
275     vout_display_sys_t *sys = vd->sys;
276
277     IDirectFBSurface *primary = sys->primary;
278     if (primary)
279         primary->Release(primary);
280
281     IDirectFB *directfb = sys->directfb;
282     if (directfb)
283         directfb->Release(directfb);
284 }
285