Revert "weston: Fix gst-record uses MONOTONIC time for IVI-Cluster system"
[AGL/meta-agl-demo.git] / recipes-graphics / wayland / weston / 0001-Add-virtual-output-support.patch
1 From c0bb07ba816524d69de22c22fcb7f7b9b95fbb11 Mon Sep 17 00:00:00 2001
2 From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
3 Date: Thu, 27 Apr 2017 16:47:00 +0900
4 Subject: [PATCH 1/3] Add virtual output support
5
6 Following patch ported to Weston 1.11 with minor updates
7 ----------
8 Author: Grigory Kletsko <grigory.kletsko@cogentembedded.com>
9 Date:   Wed Nov 2 17:14:43 2016 +0300
10
11 To enable virtual output set "virtual" property in core section
12 to desirable number of virtual outputs. Then add settings to
13 each virtual output in output sections. Name of the outputs
14 will be virtual1, virtual2... etc.
15 ------------
16 ---
17  src/compositor-drm.c | 310 +++++++++++++++++++++++++++++++++++++++++++++++++++
18  1 file changed, 310 insertions(+)
19
20 diff --git a/src/compositor-drm.c b/src/compositor-drm.c
21 index abc9408..fc5a2ff 100644
22 --- a/src/compositor-drm.c
23 +++ b/src/compositor-drm.c
24 @@ -199,6 +199,11 @@ struct drm_output {
25  
26         struct vaapi_recorder *recorder;
27         struct wl_listener recorder_frame_listener;
28 +
29 +       /* not real output device */
30 +       int virtual;
31 +       /* Timer for updating frame */
32 +       struct wl_event_source *virtual_finish_frame_timer;
33  };
34  
35  /*
36 @@ -1474,6 +1479,33 @@ drm_output_destroy(struct weston_output *output_base)
37         free(output);
38  }
39  
40 +static void
41 +virtual_output_destroy(struct weston_output *output_base)
42 +{
43 +       struct drm_output *output = (struct drm_output *) output_base;
44 +       struct drm_backend *c =
45 +               (struct drm_backend *) output->base.compositor;
46 +
47 +       c->crtc_allocator &= ~(1 << output->crtc_id);
48 +       c->connector_allocator &= ~(1 << output->connector_id);
49 +
50 +       if (c->use_pixman) {
51 +               drm_output_fini_pixman(output);
52 +       } else {
53 +               gl_renderer->output_destroy(output_base);
54 +               gbm_surface_destroy(output->gbm_surface);
55 +       }
56 +
57 +       weston_plane_release(&output->fb_plane);
58 +       weston_plane_release(&output->cursor_plane);
59 +
60 +       weston_output_destroy(&output->base);
61 +
62 +
63 +       wl_event_source_remove(output->virtual_finish_frame_timer);
64 +       free(output);
65 +}
66 +
67  /**
68   * Find the closest-matching mode for a given target
69   *
70 @@ -2649,6 +2681,270 @@ err_free:
71  }
72  
73  static void
74 +virtual_output_start_repaint_loop(struct weston_output *output)
75 +{
76 +       struct timespec now;
77 +
78 +       weston_compositor_read_presentation_clock(output->compositor, &now);
79 +       weston_output_finish_frame(output, &now, WP_PRESENTATION_FEEDBACK_INVALID);
80 +}
81 +
82 +
83 +static int
84 +virtual_output_repaint(struct weston_output *output_base,
85 +                  pixman_region32_t *damage)
86 +{
87 +       struct drm_output *output = (struct drm_output *) output_base;
88 +       struct timespec ts;
89 +       uint32_t msec_next;
90 +       uint32_t msec_current;
91 +
92 +       msec_next = (output->base.frame_time + 1000000UL / output->base.current_mode->refresh) ;
93 +
94 +       if (output->destroy_pending)
95 +               return -1;
96 +
97 +       if (!output->next)
98 +               drm_output_render(output, damage);
99 +       if (!output->next)
100 +               return -1;
101 +
102 +       drm_output_set_cursor(output);
103 +
104 +       output->page_flip_pending = 1;
105 +
106 +       weston_compositor_read_presentation_clock(output_base->compositor, &ts);
107 +
108 +       msec_current = ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
109 +
110 +       /*
111 +        * If we somehow late with updating frame, then fireup timer immediately (1 msec)
112 +        */
113 +       wl_event_source_timer_update(output->virtual_finish_frame_timer, (msec_next > msec_current)  ?
114 +                                    msec_next - msec_current : 1);
115 +
116 +       return 0;
117 +}
118 +
119 +static int
120 +virtual_finish_frame_handler(void *data)
121 +{
122 +       struct drm_output *output = (struct drm_output *) data;
123 +       struct timespec ts;
124 +
125 +       /* We don't set page_flip_pending on start_repaint_loop, in that case
126 +        * we just want to page flip to the current buffer to get an accurate
127 +        * timestamp */
128 +       if (output->page_flip_pending) {
129 +               drm_output_release_fb(output, output->current);
130 +               output->current = output->next;
131 +               output->next = NULL;
132 +       }
133 +
134 +       output->page_flip_pending = 0;
135 +
136 +       if (output->destroy_pending)
137 +               drm_output_destroy(&output->base);
138 +       else if (!output->vblank_pending) {
139 +               weston_compositor_read_presentation_clock(output->base.compositor, &ts);
140 +
141 +               weston_output_finish_frame(&output->base, &ts,
142 +                       WP_PRESENTATION_FEEDBACK_INVALID);
143 +
144 +               /* We can't call this from frame_notify, because the output's
145 +                * repaint needed flag is cleared just after that */
146 +               if (output->recorder)
147 +                       weston_output_schedule_repaint(&output->base);
148 +       }
149 +
150 +       return 1;
151 +}
152 +
153 +/*
154 + * Virtual output connector that could be used for simulating output
155 + * device for clients and/or streaming of video
156 + */
157 +static int
158 +create_output_for_virtual_connector(struct drm_backend *b,
159 +                                   int x, int y, struct udev_device *drm_device)
160 +{
161 +       struct wl_event_loop *loop;
162 +       static int virtual_id = 1; /* as other outputs numbered */
163 +       struct drm_output *output;
164 +       struct drm_mode *drm_mode, *next, *current;
165 +       struct weston_mode *m;
166 +       struct weston_config_section *section;
167 +       int width, height, scale, fps;
168 +       int recorded_output;
169 +       char name[32], *s;
170 +       enum weston_drm_backend_output_mode mode;
171 +       struct weston_drm_backend_output_config config = {{ 0 }};
172 +       uint32_t transform;
173 +       int valid_mode;
174 +       drmModeModeInfo crtc_mode;
175 +
176 +       output = zalloc(sizeof *output);
177 +       if (output == NULL)
178 +               return -1;
179 +
180 +       output->base.subpixel = WL_OUTPUT_SUBPIXEL_NONE; //drm_subpixel_to_wayland(connector->subpixel);
181 +       output->base.make = "CogentEmbedded,Inc";
182 +       output->base.serial_number = "";
183 +       wl_list_init(&output->base.mode_list);
184 +
185 +       snprintf(name, 32, "virtual%d", virtual_id++);
186 +       output->base.name = strdup(name);
187 +
188 +       section = weston_config_get_section(b->compositor->config, "output", "name",
189 +                                           output->base.name);
190 +
191 +       weston_config_section_get_bool(section, "recorder", &recorded_output, 0);
192 +       if (recorded_output) {
193 +               char model[64];
194 +               char *ip;
195 +               int port;
196 +
197 +               weston_config_section_get_string(section, "ip", &ip, "<nil>");
198 +               weston_config_section_get_int(section, "port", &port, -1);
199 +               snprintf(model, 64, "Virtual RTP %s:%d", ip, port);
200 +               output->base.model = strdup(model);
201 +       } else {
202 +               output->base.model = "Virtual Display";
203 +       }
204 +
205 +       mode = b->configure_output(b->compositor, b->use_current_mode,
206 +                                  output->base.name, &config);
207 +
208 +       if (mode == WESTON_DRM_BACKEND_OUTPUT_PREFERRED) {
209 +               if (config.modeline && sscanf(config.modeline, "%dx%d@%d", &width, &height, &fps) >= 3)
210 +                       valid_mode = 1;
211 +       }
212 +
213 +       weston_config_section_get_int(section, "scale", &scale, 1);
214 +       weston_config_section_get_string(section, "transform", &s, "normal");
215 +       if (weston_parse_transform(s, &transform) < 0)
216 +               weston_log("Invalid transform \"%s\" for output %s\n",
217 +                          s, output->base.name);
218 +       free(s);
219 +
220 +       if (parse_gbm_format(config.gbm_format, b->gbm_format, &output->gbm_format) == -1)
221 +               output->gbm_format = b->gbm_format;
222 +
223 +       weston_config_section_get_string(section, "seat", &s, "");
224 +       setup_output_seat_constraint(b, &output->base, s);
225 +       free(s);
226 +
227 +       output->pipe = 0;
228 +       b->crtc_allocator |= (1 << output->crtc_id);
229 +       output->connector_id = 0;
230 +       b->connector_allocator |= (1 << output->connector_id);
231 +
232 +       /* this is virtual output */
233 +       output->virtual = 1;
234 +
235 +
236 +       output->original_crtc = NULL;
237 +       output->dpms_prop = NULL;
238 +
239 +       /* set static mode */
240 +       if (valid_mode) {
241 +               /* TODO: calculate proper mode settings to get desirable framerate */
242 +               drmModeModeInfo static_drm_mode = {
243 +                       width * height * fps,
244 +                       width, 0, 0, width, width,
245 +                       height, 0, 0, height, height,
246 +                       fps * 1000,
247 +                       0, //flags
248 +                       0, //type
249 +                       "virtual"
250 +               };
251 +
252 +               drm_mode = drm_output_add_mode(output, &static_drm_mode);
253 +               if (!drm_mode)
254 +                       goto err_free;
255 +
256 +               drm_mode->base.refresh = fps * 1000;
257 +       }
258 +
259 +       if (mode == WESTON_DRM_BACKEND_OUTPUT_OFF) {
260 +               weston_log("Disabling output %s\n", output->base.name);
261 +               drmModeSetCrtc(b->drm.fd, output->crtc_id,
262 +                              0, 0, 0, 0, 0, NULL);
263 +               goto err_free;
264 +       }
265 +
266 +       current = drm_output_choose_initial_mode(b, output, mode, &config,
267 +                                                &crtc_mode);
268 +       if (!current)
269 +               goto err_free;
270 +       output->base.current_mode = &current->base;
271 +       output->base.current_mode->flags |= WL_OUTPUT_MODE_CURRENT;
272 +
273 +       weston_output_init(&output->base, b->compositor, x, y,
274 +                          100, 100 * height / width, /* FIXME: calculate proper mm_width and mm_height */
275 +                          config.base.transform, config.base.scale);
276 +       if (b->use_pixman) {
277 +               if (drm_output_init_pixman(output, b) < 0) {
278 +                       weston_log("Failed to init output pixman state\n");
279 +                       goto err_output;
280 +               }
281 +       } else if (drm_output_init_egl(output, b) < 0) {
282 +               weston_log("Failed to init output gl state\n");
283 +               goto err_output;
284 +       }
285 +
286 +       output->backlight = NULL;
287 +
288 +       weston_compositor_add_output(b->compositor, &output->base);
289 +
290 +       output->base.connection_internal = 1;
291 +
292 +       loop = wl_display_get_event_loop(b->compositor->wl_display);
293 +       output->virtual_finish_frame_timer = wl_event_loop_add_timer(loop, virtual_finish_frame_handler, output);
294 +
295 +       output->base.start_repaint_loop = virtual_output_start_repaint_loop;
296 +       output->base.repaint = virtual_output_repaint;
297 +       output->base.destroy = virtual_output_destroy;
298 +       output->base.assign_planes = NULL;
299 +       output->base.set_backlight = NULL;
300 +       output->base.set_dpms = NULL;
301 +       output->base.switch_mode = drm_output_switch_mode;
302 +
303 +       output->base.gamma_size = 0;
304 +       output->base.set_gamma = drm_output_set_gamma;
305 +
306 +       weston_plane_init(&output->cursor_plane, b->compositor, 0, 0);
307 +       weston_plane_init(&output->fb_plane, b->compositor, 0, 0);
308 +
309 +       weston_compositor_stack_plane(b->compositor, &output->cursor_plane, NULL);
310 +       weston_compositor_stack_plane(b->compositor, &output->fb_plane,
311 +                                     &b->compositor->primary_plane);
312 +
313 +       weston_log("Output %s, ()\n",
314 +                  output->base.name);
315 +       wl_list_for_each(m, &output->base.mode_list, link)
316 +               weston_log_continue(STAMP_SPACE "mode %dx%d@%.1f\n",
317 +                                   m->width, m->height, m->refresh / 1000.0);
318 +
319 +       return 0;
320 +
321 +err_output:
322 +       weston_output_destroy(&output->base);
323 +err_free:
324 +       wl_list_for_each_safe(drm_mode, next, &output->base.mode_list,
325 +                                                       base.link) {
326 +               wl_list_remove(&drm_mode->base.link);
327 +               free(drm_mode);
328 +       }
329 +
330 +       b->crtc_allocator &= ~(1 << output->crtc_id);
331 +       b->connector_allocator &= ~(1 << output->connector_id);
332 +       free(output);
333 +
334 +       return -1;
335 +}
336 +
337 +static void
338  create_sprites(struct drm_backend *b)
339  {
340         struct drm_sprite *sprite;
341 @@ -2721,10 +3017,12 @@ static int
342  create_outputs(struct drm_backend *b, uint32_t option_connector,
343                struct udev_device *drm_device)
344  {
345 +       struct weston_config_section *section;
346         drmModeConnector *connector;
347         drmModeRes *resources;
348         int i;
349         int x = 0, y = 0;
350 +       int virtual;
351  
352         resources = drmModeGetResources(b->drm.fd);
353         if (!resources) {
354 @@ -2770,6 +3068,18 @@ create_outputs(struct drm_backend *b, uint32_t option_connector,
355                 drmModeFreeConnector(connector);
356         }
357  
358 +       section = weston_config_get_section(b->compositor->config, "core", NULL, NULL);
359 +       weston_config_section_get_int(section, "virtual", &virtual, 0);
360 +
361 +       for (i = 0; i < virtual; i++) {
362 +               if (create_output_for_virtual_connector(b, x, y,
363 +                                                       drm_device) < 0)
364 +                       continue;
365 +               x += container_of(b->compositor->output_list.prev,
366 +                                 struct weston_output,
367 +                                 link)->width;
368 +       }
369 +
370         if (wl_list_empty(&b->compositor->output_list)) {
371                 weston_log("No currently active connector found.\n");
372                 drmModeFreeResources(resources);
373 -- 
374 1.9.1
375