Fix most for kernel 4.14
[AGL/meta-agl-demo.git] / recipes-graphics / wayland / weston / 0001-Add-virtual-output-support.patch
1 From b6d084f68434fea7402d4989d4d8344523b1a939 Mon Sep 17 00:00:00 2001
2 From: Harunobu Kurokawa <harunobu.kurokawa.dn@renesas.com>
3 Date: Thu, 10 Aug 2017 15:42:38 +0900
4 Subject: [PATCH 1/4] Add virtual output support
5
6 This patch is ported to weston 2.0.0.
7
8 ----------
9 Author: Damian Hobson-Garcia <dhobsong@igel.co.jp>
10 Date:   Thu Apr 27 16:47:00 2017 +0900
11
12 Following patch ported to Weston 1.11 with minor updates
13   ----------
14   Author: Grigory Kletsko <grigory.kletsko@cogentembedded.com>
15   Date:   Wed Nov 2 17:14:43 2016 +0300
16
17   To enable virtual output set "virtual" property in core section
18   to desirable number of virtual outputs. Then add settings to
19   each virtual output in output sections. Name of the outputs
20   will be virtual1, virtual2... etc.
21   ------------
22 ---
23  libweston/compositor-drm.c | 352 +++++++++++++++++++++++++++++++++++++++++++++
24  libweston/compositor-drm.h |   1 +
25  2 files changed, 353 insertions(+)
26
27 diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c
28 index 1d38f05..d0f07e9 100644
29 --- a/libweston/compositor-drm.c
30 +++ b/libweston/compositor-drm.c
31 @@ -182,6 +182,11 @@ struct drm_output {
32  
33         struct vaapi_recorder *recorder;
34         struct wl_listener recorder_frame_listener;
35 +
36 +       /* not real output device */
37 +       int virtual;
38 +       /* Timer for updating frame */
39 +       struct wl_event_source *virtual_finish_frame_timer;
40  };
41  
42  /*
43 @@ -211,6 +216,9 @@ struct drm_sprite {
44  
45  static struct gl_renderer_interface *gl_renderer;
46  
47 +static int
48 +recorder_enable(struct drm_backend *b, struct drm_output *output);
49 +
50  static const char default_seat[] = "seat0";
51  
52  static inline struct drm_output *
53 @@ -2347,6 +2355,99 @@ connector_get_current_mode(drmModeConnector *connector, int drm_fd,
54  }
55  
56  static int
57 +virtual_output_set_mode(struct weston_output *base,
58 +                   enum weston_drm_backend_output_mode mode,
59 +                   const char *modeline)
60 +{
61 +       struct drm_output *output = to_drm_output(base);
62 +       struct drm_backend *b = to_drm_backend(base->compositor);
63 +       struct weston_config *config = wet_get_config(b->compositor);
64 +
65 +       struct drm_mode *drm_mode, *next, *current;
66 +       char *s;
67 +       int valid_mode;
68 +       int recorded_output;
69 +       int width, height, scale, fps;
70 +       struct weston_config_section *section;
71 +       uint32_t transform;
72 +       drmModeModeInfo crtc_mode;
73 +
74 +       output->base.make = "CogentEmbedded,Inc";
75 +
76 +       section = weston_config_get_section(config, "output", "name",
77 +                                           output->base.name);
78 +
79 +       weston_config_section_get_bool(section, "recorder", &recorded_output, 0);
80 +
81 +       if (recorded_output) {
82 +               output->base.model = "Virtual RTP Display";
83 +       } else {
84 +               output->base.model = "Virtual Display";
85 +       }
86 +
87 +       output->base.serial_number = "";
88 +       wl_list_init(&output->base.mode_list);
89 +
90 +       if (mode == WESTON_DRM_BACKEND_OUTPUT_PREFERRED) {
91 +               if (modeline && sscanf(modeline, "%dx%d@%d", &width, &height, &fps) >= 3)
92 +                       valid_mode = 1;
93 +       }
94 +
95 +       weston_config_section_get_int(section, "scale", &scale, 1);
96 +       weston_config_section_get_string(section, "transform", &s, "normal");
97 +       if (weston_parse_transform(s, &transform) < 0)
98 +               weston_log("Invalid transform \"%s\" for output %s\n",
99 +                          s, output->base.name);
100 +       free(s);
101 +
102 +       weston_config_section_get_string(section, "seat", &s, "");
103 +       free(s);
104 +
105 +       output->original_crtc = NULL;
106 +       output->dpms_prop = NULL;
107 +
108 +       /* set static mode */
109 +       if (valid_mode) {
110 +               /* TODO: calculate proper mode settings to get desirable framerate */
111 +               drmModeModeInfo static_drm_mode = {
112 +                       width * height * fps,
113 +                       width, 0, 0, width, width,
114 +                       height, 0, 0, height, height,
115 +                       fps * 1000,
116 +                       0, //flags
117 +                       0, //type
118 +                       "virtual"
119 +               };
120 +               drm_mode = drm_output_add_mode(output, &static_drm_mode);
121 +               if (!drm_mode)
122 +                       goto err_free;
123 +
124 +               drm_mode->base.refresh = fps * 1000;
125 +       }
126 +
127 +       current = drm_output_choose_initial_mode(b, output, mode, &modeline,
128 +                                                &crtc_mode);
129 +       if (!current)
130 +               goto err_free;
131 +       output->base.current_mode = &current->base;
132 +       output->base.current_mode->flags |= WL_OUTPUT_MODE_CURRENT;
133 +
134 +       return 0;
135 +
136 +err_free:
137 +       drmModeFreeCrtc(output->original_crtc);
138 +       output->original_crtc = NULL;
139 +
140 +       wl_list_for_each_safe(drm_mode, next, &output->base.mode_list,
141 +                                                       base.link) {
142 +               wl_list_remove(&drm_mode->base.link);
143 +               free(drm_mode);
144 +       }
145 +
146 +       return -1;
147 +}
148 +
149 +static int
150  drm_output_set_mode(struct weston_output *base,
151                     enum weston_drm_backend_output_mode mode,
152                     const char *modeline)
153 @@ -2357,6 +2458,8 @@ drm_output_set_mode(struct weston_output *base,
154         struct drm_mode *drm_mode, *next, *current;
155         drmModeModeInfo crtc_mode;
156         int i;
157 +       if ( output->virtual == 1 )
158 +               return virtual_output_set_mode(base, mode, modeline);
159  
160         output->base.make = "unknown";
161         output->base.model = "unknown";
162 @@ -2453,6 +2556,10 @@ drm_output_enable(struct weston_output *base)
163                 weston_log("Failed to initialize backlight\n");
164         }
165  
166 +       /* enable GST recording-streaming */
167 +       if (b->enable_recorder)
168 +               recorder_enable(b, output);
169 +
170         output->base.start_repaint_loop = drm_output_start_repaint_loop;
171         output->base.repaint = drm_output_repaint;
172         output->base.assign_planes = drm_assign_planes;
173 @@ -2630,6 +2737,227 @@ create_output_for_connector(struct drm_backend *b,
174  }
175  
176  static void
177 +virtual_output_deinit(struct weston_output *base)
178 +{
179 +       struct drm_output *output = to_drm_output(base);
180 +       struct drm_backend *b = to_drm_backend(base->compositor);
181 +
182 +       if (b->use_pixman)
183 +               drm_output_fini_pixman(output);
184 +       else
185 +               drm_output_fini_egl(output);
186 +
187 +       weston_plane_release(&output->fb_plane);
188 +       weston_plane_release(&output->cursor_plane);
189 +}
190 +
191 +static void
192 +virtual_output_destroy(struct weston_output *base)
193 +{
194 +       struct drm_output *output = to_drm_output(base);
195 +
196 +       if (output->base.enabled)
197 +               virtual_output_deinit(&output->base);
198 +
199 +       weston_output_destroy(&output->base);
200 +
201 +       free(output);
202 +}
203 +
204 +static void
205 +virtual_output_start_repaint_loop(struct weston_output *output)
206 +{
207 +       struct timespec now;
208 +
209 +       weston_compositor_read_presentation_clock(output->compositor, &now);
210 +       weston_output_finish_frame(output, &now, WP_PRESENTATION_FEEDBACK_INVALID);
211 +}
212 +
213 +
214 +static int
215 +virtual_output_repaint(struct weston_output *output_base,
216 +                  pixman_region32_t *damage)
217 +{
218 +       struct drm_output *output = (struct drm_output *) output_base;
219 +       struct timespec ts;
220 +       uint32_t msec_next;
221 +       uint32_t msec_current;
222 +
223 +       msec_next = (output->base.frame_time + 1000000UL / output->base.current_mode->refresh) ;
224 +
225 +       if (output->disable_pending || output->destroy_pending)
226 +               return -1;
227 +
228 +       if (!output->next)
229 +               drm_output_render(output, damage);
230 +       if (!output->next)
231 +               return -1;
232 +
233 +       drm_output_set_cursor(output);
234 +
235 +       output->page_flip_pending = 1;
236 +
237 +       weston_compositor_read_presentation_clock(output_base->compositor, &ts);
238 +
239 +       msec_current = ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
240 +
241 +       /*
242 +        * If we somehow late with updating frame, then fireup timer immediately (1 msec)
243 +        */
244 +       wl_event_source_timer_update(output->virtual_finish_frame_timer, (msec_next > msec_current)  ?
245 +                                    msec_next - msec_current : 1);
246 +
247 +       return 0;
248 +}
249 +
250 +static int
251 +virtual_finish_frame_handler(void *data)
252 +{
253 +       struct drm_output *output = (struct drm_output *) data;
254 +       struct timespec ts;
255 +
256 +       /* We don't set page_flip_pending on start_repaint_loop, in that case
257 +        * we just want to page flip to the current buffer to get an accurate
258 +        * timestamp */
259 +       if (output->page_flip_pending) {
260 +               drm_output_release_fb(output, output->current);
261 +               output->current = output->next;
262 +               output->next = NULL;
263 +       }
264 +
265 +       output->page_flip_pending = 0;
266 +
267 +       if (output->destroy_pending)
268 +               drm_output_destroy(&output->base);
269 +       else if (!output->vblank_pending) {
270 +               weston_compositor_read_presentation_clock(output->base.compositor, &ts);
271 +
272 +               weston_output_finish_frame(&output->base, &ts,
273 +                       WP_PRESENTATION_FEEDBACK_INVALID);
274 +
275 +               /* We can't call this from frame_notify, because the output's
276 +                * repaint needed flag is cleared just after that */
277 +               if (output->recorder)
278 +                       weston_output_schedule_repaint(&output->base);
279 +       }
280 +
281 +       return 1;
282 +}
283 +
284 +static int
285 +virtual_output_enable(struct weston_output *base)
286 +{
287 +       struct drm_output *output = to_drm_output(base);
288 +       struct drm_backend *b = to_drm_backend(base->compositor);
289 +       struct weston_mode *m;
290 +
291 +       if (b->use_pixman) {
292 +               if (drm_output_init_pixman(output, b) < 0) {
293 +                       weston_log("Failed to init output pixman state\n");
294 +                       goto err_free;
295 +               }
296 +       } else if (drm_output_init_egl(output, b) < 0) {
297 +               weston_log("Failed to init output gl state\n");
298 +               goto err_free;
299 +       }
300 +
301 +       output->base.start_repaint_loop = virtual_output_start_repaint_loop;
302 +       output->base.repaint = virtual_output_repaint;
303 +       output->base.assign_planes = NULL;
304 +       output->base.set_dpms = NULL;
305 +       output->base.switch_mode = drm_output_switch_mode;
306 +
307 +       output->base.gamma_size = 0;
308 +       output->base.set_gamma = drm_output_set_gamma;
309 +
310 +       output->base.subpixel = WL_OUTPUT_SUBPIXEL_NONE; //drm_subpixel_to_wayland(connector->subpixel);
311 +
312 +       weston_plane_init(&output->cursor_plane, b->compositor,
313 +                         INT32_MIN, INT32_MIN);
314 +       weston_plane_init(&output->fb_plane, b->compositor, 0, 0);
315 +
316 +       weston_compositor_stack_plane(b->compositor, &output->cursor_plane, NULL);
317 +       weston_compositor_stack_plane(b->compositor, &output->fb_plane,
318 +                                     &b->compositor->primary_plane);
319 +
320 +       weston_log("Output %s, ()\n",
321 +                  output->base.name);
322 +       wl_list_for_each(m, &output->base.mode_list, link)
323 +               weston_log_continue(STAMP_SPACE "mode %dx%d@%.1f\n",
324 +                                   m->width, m->height, m->refresh / 1000.0);
325 +
326 +       /* enable GST recording-streaming */
327 +       if (b->enable_recorder)
328 +               recorder_enable(b, output);
329 +
330 +       return 0;
331 +
332 +err_free:
333 +
334 +       return -1;
335 +}
336 +
337 +
338 +static int
339 +virtual_output_disable(struct weston_output *base)
340 +{
341 +       struct drm_output *output = to_drm_output(base);
342 +
343 +       if (output->base.enabled)
344 +               virtual_output_deinit(&output->base);
345 +
346 +       output->disable_pending = 0;
347 +
348 +       weston_log("Disabling output %s\n", output->base.name);
349 +
350 +       return 0;
351 +}
352 +
353 +/*
354 + * Virtual output connector that could be used for simulating output
355 + * device for clients and/or streaming of video
356 + */
357 +static int
358 +create_output_for_virtual_connector(struct drm_backend *b,
359 +                                   struct udev_device *drm_device)
360 +{
361 +       struct wl_event_loop *loop;
362 +       struct drm_output *output;
363 +       static int virtual_id = 1; /* as other outputs numbered */
364 +       char name[32], *s;
365 +
366 +       output = zalloc(sizeof *output);
367 +       if (output == NULL)
368 +               return -1;
369 +
370 +       output->pipe = 0;
371 +       output->connector_id = 0;
372 +
373 +       /* this is virtual output */
374 +       output->virtual = 1;
375 +
376 +       output->backlight = NULL;
377 +
378 +       loop = wl_display_get_event_loop(b->compositor->wl_display);
379 +       output->virtual_finish_frame_timer = wl_event_loop_add_timer(loop, virtual_finish_frame_handler, output);
380 +
381 +       output->base.enable = virtual_output_enable;
382 +       output->base.destroy = virtual_output_destroy;
383 +       output->base.disable = virtual_output_disable;
384 +
385 +       output->destroy_pending = 0;
386 +       output->disable_pending = 0;
387 +       output->original_crtc = NULL;
388 +       snprintf(name, 32, "virtual%d", virtual_id++);
389 +       output->base.name = strdup(name);
390 +
391 +       weston_output_init(&output->base, b->compositor);
392 +       weston_compositor_add_pending_output(&output->base, b->compositor);
393 +
394 +       return 0;
395 +}
396 +
397 +static void
398  create_sprites(struct drm_backend *b)
399  {
400         struct drm_sprite *sprite;
401 @@ -2701,9 +3029,12 @@ destroy_sprites(struct drm_backend *backend)
402  static int
403  create_outputs(struct drm_backend *b, struct udev_device *drm_device)
404  {
405 +       struct weston_config_section *section;
406 +       struct weston_config *config = wet_get_config(b->compositor);
407         drmModeConnector *connector;
408         drmModeRes *resources;
409         int i;
410 +       int virtual;
411  
412         resources = drmModeGetResources(b->drm.fd);
413         if (!resources) {
414 @@ -2735,6 +3066,14 @@ create_outputs(struct drm_backend *b, struct udev_device *drm_device)
415                 }
416         }
417  
418 +       section = weston_config_get_section(config, "core", NULL, NULL);
419 +       weston_config_section_get_int(section, "virtual", &virtual, 0);
420 +
421 +       for (i = 0; i < virtual; i++) {
422 +               if (create_output_for_virtual_connector(b, drm_device) < 0)
423 +                       continue;
424 +       }
425 +
426         if (wl_list_empty(&b->compositor->output_list) &&
427             wl_list_empty(&b->compositor->pending_output_list))
428                 weston_log("No currently active connector found.\n");
429 @@ -3181,6 +3520,12 @@ renderer_switch_binding(struct weston_keyboard *keyboard, uint32_t time,
430         switch_to_gl_renderer(b);
431  }
432  
433 +static const struct weston_drm_output_api virtual_api = {
434 +       virtual_output_set_mode,
435 +       drm_output_set_gbm_format,
436 +       drm_output_set_seat,
437 +};
438 +
439  static const struct weston_drm_output_api api = {
440         drm_output_set_mode,
441         drm_output_set_gbm_format,
442 @@ -3346,6 +3691,13 @@ drm_backend_create(struct weston_compositor *compositor,
443                 goto err_udev_monitor;
444         }
445  
446 +       ret = weston_plugin_api_register(compositor, WESTON_DRM_VIRTUAL_OUTPUT_API_NAME,
447 +                                        &virtual_api, sizeof(virtual_api));
448 +
449 +       if (ret < 0) {
450 +               weston_log("Failed to register output API.\n");
451 +               goto err_udev_monitor;
452 +       }
453         return b;
454  
455  err_udev_monitor:
456 diff --git a/libweston/compositor-drm.h b/libweston/compositor-drm.h
457 index 2e2995a..00171c8 100644
458 --- a/libweston/compositor-drm.h
459 +++ b/libweston/compositor-drm.h
460 @@ -53,6 +53,7 @@ enum weston_drm_backend_output_mode {
461  };
462  
463  #define WESTON_DRM_OUTPUT_API_NAME "weston_drm_output_api_v1"
464 +#define WESTON_DRM_VIRTUAL_OUTPUT_API_NAME "weston_virtual_output_api_v1"
465  
466  struct weston_drm_output_api {
467         /** The mode to be used by the output. Refer to the documentation
468 -- 
469 2.9.2
470