summaryrefslogtreecommitdiffstats
path: root/recipes-graphics/wayland/weston/0001-Add-virtual-output-support.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes-graphics/wayland/weston/0001-Add-virtual-output-support.patch')
-rw-r--r--recipes-graphics/wayland/weston/0001-Add-virtual-output-support.patch375
1 files changed, 375 insertions, 0 deletions
diff --git a/recipes-graphics/wayland/weston/0001-Add-virtual-output-support.patch b/recipes-graphics/wayland/weston/0001-Add-virtual-output-support.patch
new file mode 100644
index 00000000..6373f94e
--- /dev/null
+++ b/recipes-graphics/wayland/weston/0001-Add-virtual-output-support.patch
@@ -0,0 +1,375 @@
+From c0bb07ba816524d69de22c22fcb7f7b9b95fbb11 Mon Sep 17 00:00:00 2001
+From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
+Date: Thu, 27 Apr 2017 16:47:00 +0900
+Subject: [PATCH 1/3] Add virtual output support
+
+Following patch ported to Weston 1.11 with minor updates
+----------
+Author: Grigory Kletsko <grigory.kletsko@cogentembedded.com>
+Date: Wed Nov 2 17:14:43 2016 +0300
+
+To enable virtual output set "virtual" property in core section
+to desirable number of virtual outputs. Then add settings to
+each virtual output in output sections. Name of the outputs
+will be virtual1, virtual2... etc.
+------------
+---
+ src/compositor-drm.c | 310 +++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 310 insertions(+)
+
+diff --git a/src/compositor-drm.c b/src/compositor-drm.c
+index abc9408..fc5a2ff 100644
+--- a/src/compositor-drm.c
++++ b/src/compositor-drm.c
+@@ -199,6 +199,11 @@ struct drm_output {
+
+ struct vaapi_recorder *recorder;
+ struct wl_listener recorder_frame_listener;
++
++ /* not real output device */
++ int virtual;
++ /* Timer for updating frame */
++ struct wl_event_source *virtual_finish_frame_timer;
+ };
+
+ /*
+@@ -1474,6 +1479,33 @@ drm_output_destroy(struct weston_output *output_base)
+ free(output);
+ }
+
++static void
++virtual_output_destroy(struct weston_output *output_base)
++{
++ struct drm_output *output = (struct drm_output *) output_base;
++ struct drm_backend *c =
++ (struct drm_backend *) output->base.compositor;
++
++ c->crtc_allocator &= ~(1 << output->crtc_id);
++ c->connector_allocator &= ~(1 << output->connector_id);
++
++ if (c->use_pixman) {
++ drm_output_fini_pixman(output);
++ } else {
++ gl_renderer->output_destroy(output_base);
++ gbm_surface_destroy(output->gbm_surface);
++ }
++
++ weston_plane_release(&output->fb_plane);
++ weston_plane_release(&output->cursor_plane);
++
++ weston_output_destroy(&output->base);
++
++
++ wl_event_source_remove(output->virtual_finish_frame_timer);
++ free(output);
++}
++
+ /**
+ * Find the closest-matching mode for a given target
+ *
+@@ -2649,6 +2681,270 @@ err_free:
+ }
+
+ static void
++virtual_output_start_repaint_loop(struct weston_output *output)
++{
++ struct timespec now;
++
++ weston_compositor_read_presentation_clock(output->compositor, &now);
++ weston_output_finish_frame(output, &now, WP_PRESENTATION_FEEDBACK_INVALID);
++}
++
++
++static int
++virtual_output_repaint(struct weston_output *output_base,
++ pixman_region32_t *damage)
++{
++ struct drm_output *output = (struct drm_output *) output_base;
++ struct timespec ts;
++ uint32_t msec_next;
++ uint32_t msec_current;
++
++ msec_next = (output->base.frame_time + 1000000UL / output->base.current_mode->refresh) ;
++
++ if (output->destroy_pending)
++ return -1;
++
++ if (!output->next)
++ drm_output_render(output, damage);
++ if (!output->next)
++ return -1;
++
++ drm_output_set_cursor(output);
++
++ output->page_flip_pending = 1;
++
++ weston_compositor_read_presentation_clock(output_base->compositor, &ts);
++
++ msec_current = ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
++
++ /*
++ * If we somehow late with updating frame, then fireup timer immediately (1 msec)
++ */
++ wl_event_source_timer_update(output->virtual_finish_frame_timer, (msec_next > msec_current) ?
++ msec_next - msec_current : 1);
++
++ return 0;
++}
++
++static int
++virtual_finish_frame_handler(void *data)
++{
++ struct drm_output *output = (struct drm_output *) data;
++ struct timespec ts;
++
++ /* We don't set page_flip_pending on start_repaint_loop, in that case
++ * we just want to page flip to the current buffer to get an accurate
++ * timestamp */
++ if (output->page_flip_pending) {
++ drm_output_release_fb(output, output->current);
++ output->current = output->next;
++ output->next = NULL;
++ }
++
++ output->page_flip_pending = 0;
++
++ if (output->destroy_pending)
++ drm_output_destroy(&output->base);
++ else if (!output->vblank_pending) {
++ weston_compositor_read_presentation_clock(output->base.compositor, &ts);
++
++ weston_output_finish_frame(&output->base, &ts,
++ WP_PRESENTATION_FEEDBACK_INVALID);
++
++ /* We can't call this from frame_notify, because the output's
++ * repaint needed flag is cleared just after that */
++ if (output->recorder)
++ weston_output_schedule_repaint(&output->base);
++ }
++
++ return 1;
++}
++
++/*
++ * Virtual output connector that could be used for simulating output
++ * device for clients and/or streaming of video
++ */
++static int
++create_output_for_virtual_connector(struct drm_backend *b,
++ int x, int y, struct udev_device *drm_device)
++{
++ struct wl_event_loop *loop;
++ static int virtual_id = 1; /* as other outputs numbered */
++ struct drm_output *output;
++ struct drm_mode *drm_mode, *next, *current;
++ struct weston_mode *m;
++ struct weston_config_section *section;
++ int width, height, scale, fps;
++ int recorded_output;
++ char name[32], *s;
++ enum weston_drm_backend_output_mode mode;
++ struct weston_drm_backend_output_config config = {{ 0 }};
++ uint32_t transform;
++ int valid_mode;
++ drmModeModeInfo crtc_mode;
++
++ output = zalloc(sizeof *output);
++ if (output == NULL)
++ return -1;
++
++ output->base.subpixel = WL_OUTPUT_SUBPIXEL_NONE; //drm_subpixel_to_wayland(connector->subpixel);
++ output->base.make = "CogentEmbedded,Inc";
++ output->base.serial_number = "";
++ wl_list_init(&output->base.mode_list);
++
++ snprintf(name, 32, "virtual%d", virtual_id++);
++ output->base.name = strdup(name);
++
++ section = weston_config_get_section(b->compositor->config, "output", "name",
++ output->base.name);
++
++ weston_config_section_get_bool(section, "recorder", &recorded_output, 0);
++ if (recorded_output) {
++ char model[64];
++ char *ip;
++ int port;
++
++ weston_config_section_get_string(section, "ip", &ip, "<nil>");
++ weston_config_section_get_int(section, "port", &port, -1);
++ snprintf(model, 64, "Virtual RTP %s:%d", ip, port);
++ output->base.model = strdup(model);
++ } else {
++ output->base.model = "Virtual Display";
++ }
++
++ mode = b->configure_output(b->compositor, b->use_current_mode,
++ output->base.name, &config);
++
++ if (mode == WESTON_DRM_BACKEND_OUTPUT_PREFERRED) {
++ if (config.modeline && sscanf(config.modeline, "%dx%d@%d", &width, &height, &fps) >= 3)
++ valid_mode = 1;
++ }
++
++ weston_config_section_get_int(section, "scale", &scale, 1);
++ weston_config_section_get_string(section, "transform", &s, "normal");
++ if (weston_parse_transform(s, &transform) < 0)
++ weston_log("Invalid transform \"%s\" for output %s\n",
++ s, output->base.name);
++ free(s);
++
++ if (parse_gbm_format(config.gbm_format, b->gbm_format, &output->gbm_format) == -1)
++ output->gbm_format = b->gbm_format;
++
++ weston_config_section_get_string(section, "seat", &s, "");
++ setup_output_seat_constraint(b, &output->base, s);
++ free(s);
++
++ output->pipe = 0;
++ b->crtc_allocator |= (1 << output->crtc_id);
++ output->connector_id = 0;
++ b->connector_allocator |= (1 << output->connector_id);
++
++ /* this is virtual output */
++ output->virtual = 1;
++
++
++ output->original_crtc = NULL;
++ output->dpms_prop = NULL;
++
++ /* set static mode */
++ if (valid_mode) {
++ /* TODO: calculate proper mode settings to get desirable framerate */
++ drmModeModeInfo static_drm_mode = {
++ width * height * fps,
++ width, 0, 0, width, width,
++ height, 0, 0, height, height,
++ fps * 1000,
++ 0, //flags
++ 0, //type
++ "virtual"
++ };
++
++ drm_mode = drm_output_add_mode(output, &static_drm_mode);
++ if (!drm_mode)
++ goto err_free;
++
++ drm_mode->base.refresh = fps * 1000;
++ }
++
++ if (mode == WESTON_DRM_BACKEND_OUTPUT_OFF) {
++ weston_log("Disabling output %s\n", output->base.name);
++ drmModeSetCrtc(b->drm.fd, output->crtc_id,
++ 0, 0, 0, 0, 0, NULL);
++ goto err_free;
++ }
++
++ current = drm_output_choose_initial_mode(b, output, mode, &config,
++ &crtc_mode);
++ if (!current)
++ goto err_free;
++ output->base.current_mode = &current->base;
++ output->base.current_mode->flags |= WL_OUTPUT_MODE_CURRENT;
++
++ weston_output_init(&output->base, b->compositor, x, y,
++ 100, 100 * height / width, /* FIXME: calculate proper mm_width and mm_height */
++ config.base.transform, config.base.scale);
++ if (b->use_pixman) {
++ if (drm_output_init_pixman(output, b) < 0) {
++ weston_log("Failed to init output pixman state\n");
++ goto err_output;
++ }
++ } else if (drm_output_init_egl(output, b) < 0) {
++ weston_log("Failed to init output gl state\n");
++ goto err_output;
++ }
++
++ output->backlight = NULL;
++
++ weston_compositor_add_output(b->compositor, &output->base);
++
++ output->base.connection_internal = 1;
++
++ loop = wl_display_get_event_loop(b->compositor->wl_display);
++ output->virtual_finish_frame_timer = wl_event_loop_add_timer(loop, virtual_finish_frame_handler, output);
++
++ output->base.start_repaint_loop = virtual_output_start_repaint_loop;
++ output->base.repaint = virtual_output_repaint;
++ output->base.destroy = virtual_output_destroy;
++ output->base.assign_planes = NULL;
++ output->base.set_backlight = NULL;
++ output->base.set_dpms = NULL;
++ output->base.switch_mode = drm_output_switch_mode;
++
++ output->base.gamma_size = 0;
++ output->base.set_gamma = drm_output_set_gamma;
++
++ weston_plane_init(&output->cursor_plane, b->compositor, 0, 0);
++ weston_plane_init(&output->fb_plane, b->compositor, 0, 0);
++
++ weston_compositor_stack_plane(b->compositor, &output->cursor_plane, NULL);
++ weston_compositor_stack_plane(b->compositor, &output->fb_plane,
++ &b->compositor->primary_plane);
++
++ weston_log("Output %s, ()\n",
++ output->base.name);
++ wl_list_for_each(m, &output->base.mode_list, link)
++ weston_log_continue(STAMP_SPACE "mode %dx%d@%.1f\n",
++ m->width, m->height, m->refresh / 1000.0);
++
++ return 0;
++
++err_output:
++ weston_output_destroy(&output->base);
++err_free:
++ wl_list_for_each_safe(drm_mode, next, &output->base.mode_list,
++ base.link) {
++ wl_list_remove(&drm_mode->base.link);
++ free(drm_mode);
++ }
++
++ b->crtc_allocator &= ~(1 << output->crtc_id);
++ b->connector_allocator &= ~(1 << output->connector_id);
++ free(output);
++
++ return -1;
++}
++
++static void
+ create_sprites(struct drm_backend *b)
+ {
+ struct drm_sprite *sprite;
+@@ -2721,10 +3017,12 @@ static int
+ create_outputs(struct drm_backend *b, uint32_t option_connector,
+ struct udev_device *drm_device)
+ {
++ struct weston_config_section *section;
+ drmModeConnector *connector;
+ drmModeRes *resources;
+ int i;
+ int x = 0, y = 0;
++ int virtual;
+
+ resources = drmModeGetResources(b->drm.fd);
+ if (!resources) {
+@@ -2770,6 +3068,18 @@ create_outputs(struct drm_backend *b, uint32_t option_connector,
+ drmModeFreeConnector(connector);
+ }
+
++ section = weston_config_get_section(b->compositor->config, "core", NULL, NULL);
++ weston_config_section_get_int(section, "virtual", &virtual, 0);
++
++ for (i = 0; i < virtual; i++) {
++ if (create_output_for_virtual_connector(b, x, y,
++ drm_device) < 0)
++ continue;
++ x += container_of(b->compositor->output_list.prev,
++ struct weston_output,
++ link)->width;
++ }
++
+ if (wl_list_empty(&b->compositor->output_list)) {
+ weston_log("No currently active connector found.\n");
+ drmModeFreeResources(resources);
+--
+1.9.1
+