diff options
Diffstat (limited to 'meta-rcar-gen2/recipes-graphics/wayland/weston/0001-Add-virtual-output-support.patch')
-rw-r--r-- | meta-rcar-gen2/recipes-graphics/wayland/weston/0001-Add-virtual-output-support.patch | 391 |
1 files changed, 391 insertions, 0 deletions
diff --git a/meta-rcar-gen2/recipes-graphics/wayland/weston/0001-Add-virtual-output-support.patch b/meta-rcar-gen2/recipes-graphics/wayland/weston/0001-Add-virtual-output-support.patch new file mode 100644 index 0000000..51c2671 --- /dev/null +++ b/meta-rcar-gen2/recipes-graphics/wayland/weston/0001-Add-virtual-output-support.patch @@ -0,0 +1,391 @@ +From f26e3ef1f484319a6c803158af16050574363587 Mon Sep 17 00:00:00 2001 +From: Grigory Kletsko <grigory.kletsko@cogentembedded.com> +Date: Wed, 2 Nov 2016 17:14:43 +0300 +Subject: [PATCH 1/2] Add virtual output support + +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. + +Signed-off-by: Grigory Kletsko <grigory.kletsko@cogentembedded.com> +Signed-off-by: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +--- + src/compositor-drm.c | 329 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 329 insertions(+) + +diff --git a/src/compositor-drm.c b/src/compositor-drm.c +index ab493ad..09611a4 100644 +--- a/src/compositor-drm.c ++++ b/src/compositor-drm.c +@@ -193,6 +193,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; + }; + + /* +@@ -1337,6 +1342,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->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 + * +@@ -2459,6 +2491,289 @@ 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, 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, ++ 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 *ec, ++ 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, *configured; ++ struct weston_mode *m; ++ struct weston_config_section *section; ++ drmModeModeInfo modeline; ++ int i, width, height, scale, fps; ++ int recorded_output; ++ char name[32], *s; ++ enum output_config config; ++ uint32_t transform; ++ ++ 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(ec->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"; ++ } ++ ++ weston_config_section_get_string(section, "mode", &s, "preferred"); ++ if (strcmp(s, "off") == 0) ++ config = OUTPUT_CONFIG_OFF; ++ else if (sscanf(s, "%dx%d@%d", &width, &height, &fps) == 3) ++ config = OUTPUT_CONFIG_MODE; ++ else if (parse_modeline(s, &modeline) == 0) ++ config = OUTPUT_CONFIG_MODELINE; ++ else { ++ weston_log("Invalid mode \"%s\" for output %s\n", ++ s, output->base.name); ++ width = 1280; ++ height = 720; ++ fps = 60; ++ config = OUTPUT_CONFIG_MODE; ++ } ++ free(s); ++ ++ 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 (get_gbm_format_from_section(section, ++ ec->format, ++ &output->format) == -1) ++ output->format = ec->format; ++ ++ weston_config_section_get_string(section, "seat", &s, ""); ++ setup_output_seat_constraint(ec, &output->base, s); ++ free(s); ++ ++ output->pipe = i; ++ ec->crtc_allocator |= (1 << output->crtc_id); ++ output->connector_id = 0; ++ ec->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 (1) { ++ /* 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 (config == OUTPUT_CONFIG_OFF) { ++ weston_log("Disabling output %s\n", output->base.name); ++ drmModeSetCrtc(ec->drm.fd, output->crtc_id, ++ 0, 0, 0, 0, 0, NULL); ++ goto err_free; ++ } ++ ++ wl_list_for_each_reverse(drm_mode, &output->base.mode_list, base.link) { ++ if (config == OUTPUT_CONFIG_MODE && ++ width == drm_mode->base.width && ++ height == drm_mode->base.height) ++ configured = drm_mode; ++ } ++ ++ output->base.current_mode = &configured->base; ++ ++ if (output->base.current_mode == NULL) { ++ weston_log("no available modes for %s\n", output->base.name); ++ goto err_free; ++ } ++ ++ output->base.current_mode->flags |= WL_OUTPUT_MODE_CURRENT; ++ ++ weston_output_init(&output->base, ec->compositor, x, y, ++ 100, 100 * height / width, /* FIXME: calculate proper mm_width and mm_height */ ++ transform, scale); ++ ++ if (ec->use_pixman) { ++ if (drm_output_init_pixman(output, ec) < 0) { ++ weston_log("Failed to init output pixman state\n"); ++ goto err_output; ++ } ++ } else if (drm_output_init_egl(output, ec) < 0) { ++ weston_log("Failed to init output gl state\n"); ++ goto err_output; ++ } ++ ++ output->backlight = NULL; ++ ++ weston_compositor_add_output(ec->compositor, &output->base); ++ ++ output->base.connection_internal = 1; ++ ++ loop = wl_display_get_event_loop(ec->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, ec->compositor, 0, 0); ++ weston_plane_init(&output->fb_plane, ec->compositor, 0, 0); ++ ++ weston_compositor_stack_plane(ec->compositor, &output->cursor_plane, NULL); ++ weston_compositor_stack_plane(ec->compositor, &output->fb_plane, ++ &ec->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); ++ } ++ ++ ec->crtc_allocator &= ~(1 << output->crtc_id); ++ ec->connector_allocator &= ~(1 << output->connector_id); ++ free(output); ++ ++ return -1; ++} ++ ++static void + create_sprites(struct drm_backend *b) + { + struct drm_sprite *sprite; +@@ -2531,10 +2846,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) { +@@ -2580,6 +2897,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); +-- +2.7.4 + |