]> git.sesse.net Git - vlc/blob - modules/video_output/directfb.c
6f283a887521d48ec2ef746cc1dda64a39bcab99
[vlc] / modules / video_output / directfb.c
1 /*****************************************************************************
2  * directfb.c: DirectFB video output display method
3  *****************************************************************************
4  * Copyright © 2005-2009 VLC authors and VideoLAN
5  *
6  * Authors: Iuri Diniz <iuridiniz@gmail.com>
7  *          Laurent Aimar <fenrir@videolan.org>
8  *
9  * This code is based in sdl.c and fb.c, thanks for VideoLAN team.
10  *
11  * This program is free software; you can redistribute it and/or modify it
12  * under the terms of the GNU Lesser General Public License as published by
13  * the Free Software Foundation; either version 2.1 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24  *****************************************************************************/
25
26 /*****************************************************************************
27  * Preamble
28  *****************************************************************************/
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
32
33 #include <vlc_common.h>
34 #include <vlc_plugin.h>
35 #include <vlc_vout_display.h>
36 #include <vlc_picture_pool.h>
37
38 #include <directfb.h>
39
40 /*****************************************************************************
41  * Module descriptor
42  *****************************************************************************/
43 static int  Open (vlc_object_t *);
44 static void Close(vlc_object_t *);
45
46 vlc_module_begin()
47     set_shortname("DirectFB")
48     set_category(CAT_VIDEO)
49     set_subcategory(SUBCAT_VIDEO_VOUT)
50     set_description(N_("DirectFB video output http://www.directfb.org/"))
51     set_capability("vout display", 35)
52     add_shortcut("directfb")
53     set_callbacks(Open, Close)
54 vlc_module_end()
55
56 /*****************************************************************************
57  * Local prototypes
58  *****************************************************************************/
59 static picture_pool_t *Pool  (vout_display_t *, unsigned);
60 static void           Display(vout_display_t *, picture_t *, subpicture_t *);
61 static int            Control(vout_display_t *, int, va_list);
62
63 /* */
64 struct vout_display_sys_t {
65     IDirectFB        *directfb;
66     IDirectFBSurface *primary;
67
68     picture_pool_t *pool;
69     picture_t      *pics[3];
70     int             idx;
71 };
72
73 /* */
74 static int Open(vlc_object_t *object)
75 {
76     vout_display_t *vd = (vout_display_t *)object;
77     vout_display_sys_t *sys;
78
79     vd->sys = sys = calloc(1, sizeof(*sys));
80     if (!sys)
81         return VLC_ENOMEM;
82
83     if (DirectFBInit(NULL,NULL) != DFB_OK) {
84         msg_Err(vd, "Cannot init DirectFB");
85         free(sys);
86         return VLC_EGENERIC;
87     }
88
89     DFBSurfaceDescription dsc;
90     dsc.flags = DSDESC_CAPS;
91     dsc.caps  = DSCAPS_PRIMARY | DSCAPS_TRIPLE;
92 #if 0
93     dsc.flags |= DSDESC_HEIGHT | DSDESC_WIDTH;
94     dsc.width = 352;
95     dsc.height = 240;
96 #endif
97
98     IDirectFB *directfb = NULL;
99     if (DirectFBCreate(&directfb) != DFB_OK || !directfb)
100         goto error;
101     sys->directfb = directfb;
102
103     IDirectFBSurface *primary = NULL;
104     if (directfb->CreateSurface(directfb, &dsc, &primary) || !primary)
105         goto error;
106     sys->primary = primary;
107
108     /* */
109     int width;
110     int height;
111
112     primary->GetSize(primary, &width, &height);
113
114     vout_display_DeleteWindow(vd, NULL);
115
116     /* */
117     video_format_t fmt;
118     video_format_ApplyRotation(&fmt, &vd->fmt);
119
120     DFBSurfacePixelFormat pixel_format;
121     sys->primary->GetPixelFormat(sys->primary, &pixel_format);
122     switch (pixel_format) {
123     case DSPF_RGB332:
124         fmt.i_chroma = VLC_CODEC_RGB8;
125         fmt.i_rmask = 0x7 << 5;
126         fmt.i_gmask = 0x7 << 2;
127         fmt.i_bmask = 0x3 << 0;
128         break;
129     case DSPF_RGB16: fmt.i_chroma = VLC_CODEC_RGB16; break;
130     case DSPF_RGB24: fmt.i_chroma = VLC_CODEC_RGB24; break;
131     case DSPF_RGB32: fmt.i_chroma = VLC_CODEC_RGB32; break;
132     default:
133         msg_Err(vd, "unknown screen depth %i", pixel_format);
134         Close(VLC_OBJECT(vd));
135         return VLC_EGENERIC;
136     }
137
138     video_format_FixRgb(&fmt);
139
140     fmt.i_width  = width;
141     fmt.i_height = height;
142     fmt.i_visible_width  = width;
143     fmt.i_visible_height = height;
144
145     /* */
146     vout_display_info_t info = vd->info;
147     info.has_hide_mouse = true;
148
149     /* */
150     vd->fmt     = fmt;
151     vd->info    = info;
152     vd->pool    = Pool;
153     vd->prepare = NULL;
154     vd->display = Display;
155     vd->control = Control;
156     vd->manage  = NULL;
157
158     /* */
159     vout_display_SendEventFullscreen(vd, true);
160     vout_display_SendEventDisplaySize(vd, fmt.i_width, fmt.i_height, true);
161     return VLC_SUCCESS;
162
163 error:
164     msg_Err(vd, "Cannot create primary surface");
165     Close(VLC_OBJECT(vd));
166     return VLC_EGENERIC;
167 }
168
169 static void Close(vlc_object_t *object)
170 {
171     vout_display_t *vd = (vout_display_t *)object;
172     vout_display_sys_t *sys = vd->sys;
173
174     if (sys->pool)
175         picture_pool_Delete(sys->pool);
176
177     IDirectFBSurface *primary = sys->primary;
178     if (primary)
179         primary->Release(primary);
180
181     IDirectFB *directfb = sys->directfb;
182     if (directfb)
183         directfb->Release(directfb);
184
185     free(sys);
186 }
187
188 struct picture_sys_t {
189     vout_display_sys_t *sys;
190 };
191
192 static int Lock(picture_t *pic)
193 {
194     vout_display_sys_t *sys = pic->p_sys->sys;
195     return sys->pics[sys->idx] == pic ? VLC_SUCCESS : VLC_EGENERIC;
196 }
197
198 /* */
199 static picture_pool_t *Pool(vout_display_t *vd, unsigned count)
200 {
201     VLC_UNUSED(count);
202     vout_display_sys_t *sys = vd->sys;
203     IDirectFBSurface *primary = sys->primary;
204
205     if (!sys->pool) {
206         picture_resource_t rsc;
207         memset(&rsc, 0, sizeof(rsc));
208         rsc.p[0].i_lines  = vd->fmt.i_height;
209
210         for (int i = 0; i < 3; i++) {
211             rsc.p_sys = malloc(sizeof(*rsc.p_sys));
212             if (!rsc.p_sys)
213                 goto cleanup;
214             rsc.p_sys->sys = sys;
215             void *pixels;
216             int  pitch;
217             if (primary->Lock(primary, DSLF_WRITE, &pixels, &pitch) != DFB_OK)
218                 goto cleanup;
219
220             rsc.p[0].i_pitch = pitch;
221             rsc.p[0].p_pixels = pixels;
222             primary->Unlock(primary);
223             primary->Flip(primary, NULL, 0);
224
225             sys->pics[i] = picture_NewFromResource(&vd->fmt, &rsc);
226             if (!sys->pics[i]) {
227                 free(rsc.p_sys);
228                 goto cleanup;
229             }
230         }
231
232         picture_pool_configuration_t cfg = {
233             .picture_count  = 3,
234             .picture        = sys->pics,
235             .lock           = Lock,
236             .unlock         = NULL,
237         };
238
239         sys->pool = picture_pool_NewExtended(&cfg);
240     }
241     return sys->pool;
242
243 cleanup:
244     for (int i = 0; i < 2; i++) {
245         if (sys->pics[i]) {
246             free(sys->pics[i]->p_sys);
247             picture_Release(sys->pics[i]);
248         }
249     }
250
251     return NULL;
252 }
253
254 static void Display(vout_display_t *vd, picture_t *picture, subpicture_t *subpicture)
255 {
256     vout_display_sys_t *sys = vd->sys;
257
258     IDirectFBSurface *primary = sys->primary;
259     primary->Flip(primary, NULL, 0);
260     if (++sys->idx >= 3)
261         sys->idx = 0;
262     picture_Release(picture);
263
264     VLC_UNUSED(subpicture);
265 }
266
267 static int Control(vout_display_t *vd, int query, va_list args)
268 {
269     switch (query) {
270     case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE: {
271         const vout_display_cfg_t *cfg = va_arg(args, const vout_display_cfg_t *);
272         if (cfg->display.width  != vd->fmt.i_width ||
273             cfg->display.height != vd->fmt.i_height)
274             return VLC_EGENERIC;
275         return VLC_SUCCESS;
276     }
277     default:
278         msg_Err(vd, "Unsupported query in vout display directfb");
279         return VLC_EGENERIC;
280     }
281 }