[PATCH weston v3 33/36] compositor-fbdev: migrate to head-based output API
Pekka Paalanen
ppaalanen at gmail.com
Tue Oct 31 11:48:43 UTC 2017
From: Pekka Paalanen <pekka.paalanen at collabora.co.uk>
Implement the head-based output API in this backend, and stop relying on
the implicit weston_output::head.
The split between fbdev_head and fbdev_output is somewhat arbitrary.
There is no hotplug or unplug, and there is always 1:1 relationship.
Struct fbdev_screeninfo could have been split as well, but it would not
have made much difference.
I chose fbdev_output to carry the mmap details (buffer_length is now
duplicated here), and fbdev_head to carry the display parameters and
device node path. The device node identifies the head, similar to a
connector.
The backend init creates a head. The compositor uses it to create an
output. Libweston core attaches the head automatically after creating
the output. The attach hook is a suitable place to set up the video
modes on the output as they are dictated by the head, it would be too
late at enable() time.
Signed-off-by: Pekka Paalanen <pekka.paalanen at collabora.co.uk>
---
libweston/compositor-fbdev.c | 189 ++++++++++++++++++++++++++++++-------------
1 file changed, 133 insertions(+), 56 deletions(-)
diff --git a/libweston/compositor-fbdev.c b/libweston/compositor-fbdev.c
index d7576236..e3053e0b 100644
--- a/libweston/compositor-fbdev.c
+++ b/libweston/compositor-fbdev.c
@@ -78,6 +78,14 @@ struct fbdev_screeninfo {
unsigned int refresh_rate; /* Hertz */
};
+struct fbdev_head {
+ struct weston_head base;
+
+ /* Frame buffer details. */
+ char *device;
+ struct fbdev_screeninfo fb_info;
+};
+
struct fbdev_output {
struct fbdev_backend *backend;
struct weston_output base;
@@ -85,10 +93,9 @@ struct fbdev_output {
struct weston_mode mode;
struct wl_event_source *finish_frame_timer;
- /* Frame buffer details. */
- char *device;
- struct fbdev_screeninfo fb_info;
- void *fb; /* length is fb_info.buffer_length */
+ /* framebuffer mmap details */
+ size_t buffer_length;
+ void *fb;
/* pixman details. */
pixman_image_t *hw_surface;
@@ -96,6 +103,12 @@ struct fbdev_output {
static const char default_seat[] = "seat0";
+static inline struct fbdev_head *
+to_fbdev_head(struct weston_head *base)
+{
+ return container_of(base, struct fbdev_head, base);
+}
+
static inline struct fbdev_output *
to_fbdev_output(struct weston_output *base)
{
@@ -108,6 +121,16 @@ to_fbdev_backend(struct weston_compositor *base)
return container_of(base->backend, struct fbdev_backend, base);
}
+static struct fbdev_head *
+fbdev_output_get_head(struct fbdev_output *output)
+{
+ if (wl_list_length(&output->base.head_list) != 1)
+ return NULL;
+
+ return container_of(output->base.head_list.next,
+ struct fbdev_head, base.output_link);
+}
+
static void
fbdev_output_start_repaint_loop(struct weston_output *output)
{
@@ -368,13 +391,17 @@ fbdev_frame_buffer_open(const char *fb_dev,
static int
fbdev_frame_buffer_map(struct fbdev_output *output, int fd)
{
+ struct fbdev_head *head;
int retval = -1;
+ head = fbdev_output_get_head(output);
+
weston_log("Mapping fbdev frame buffer.\n");
/* Map the frame buffer. Write-only mode, since we don't want to read
* anything back (because it's slow). */
- output->fb = mmap(NULL, output->fb_info.buffer_length,
+ output->buffer_length = head->fb_info.buffer_length;
+ output->fb = mmap(NULL, output->buffer_length,
PROT_WRITE, MAP_SHARED, fd, 0);
if (output->fb == MAP_FAILED) {
weston_log("Failed to mmap frame buffer: %s\n",
@@ -385,11 +412,11 @@ fbdev_frame_buffer_map(struct fbdev_output *output, int fd)
/* Create a pixman image to wrap the memory mapped frame buffer. */
output->hw_surface =
- pixman_image_create_bits(output->fb_info.pixel_format,
- output->fb_info.x_resolution,
- output->fb_info.y_resolution,
+ pixman_image_create_bits(head->fb_info.pixel_format,
+ head->fb_info.x_resolution,
+ head->fb_info.y_resolution,
output->fb,
- output->fb_info.line_length);
+ head->fb_info.line_length);
if (output->hw_surface == NULL) {
weston_log("Failed to create surface for frame buffer.\n");
goto out_unmap;
@@ -400,7 +427,7 @@ fbdev_frame_buffer_map(struct fbdev_output *output, int fd)
out_unmap:
if (retval != 0 && output->fb != NULL) {
- munmap(output->fb, output->fb_info.buffer_length);
+ munmap(output->fb, output->buffer_length);
output->fb = NULL;
}
@@ -425,13 +452,37 @@ fbdev_frame_buffer_unmap(struct fbdev_output *output)
pixman_image_unref(output->hw_surface);
output->hw_surface = NULL;
- if (munmap(output->fb, output->fb_info.buffer_length) < 0)
+ if (munmap(output->fb, output->buffer_length) < 0)
weston_log("Failed to munmap frame buffer: %s\n",
strerror(errno));
output->fb = NULL;
}
+
+static int
+fbdev_output_attach_head(struct weston_output *output_base,
+ struct weston_head *head_base)
+{
+ struct fbdev_output *output = to_fbdev_output(output_base);
+ struct fbdev_head *head = to_fbdev_head(head_base);
+
+ /* Clones not supported. */
+ if (!wl_list_empty(&output->base.head_list))
+ return -1;
+
+ /* only one static mode in list */
+ output->mode.flags = WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
+ output->mode.width = head->fb_info.x_resolution;
+ output->mode.height = head->fb_info.y_resolution;
+ output->mode.refresh = head->fb_info.refresh_rate;
+ wl_list_init(&output->base.mode_list);
+ wl_list_insert(&output->base.mode_list, &output->mode.link);
+ output->base.current_mode = &output->mode;
+
+ return 0;
+}
+
static void fbdev_output_destroy(struct weston_output *base);
static int
@@ -439,11 +490,14 @@ fbdev_output_enable(struct weston_output *base)
{
struct fbdev_output *output = to_fbdev_output(base);
struct fbdev_backend *backend = to_fbdev_backend(base->compositor);
+ struct fbdev_head *head;
int fb_fd;
struct wl_event_loop *loop;
+ head = fbdev_output_get_head(output);
+
/* Create the frame buffer. */
- fb_fd = fbdev_frame_buffer_open(output->device, &output->fb_info);
+ fb_fd = fbdev_frame_buffer_open(head->device, &head->fb_info);
if (fb_fd < 0) {
weston_log("Creating frame buffer failed.\n");
return -1;
@@ -494,64 +548,80 @@ fbdev_output_disable(struct weston_output *base)
return 0;
}
-static int
-fbdev_output_create(struct fbdev_backend *backend,
- const char *device)
+static struct fbdev_head *
+fbdev_head_create(struct fbdev_backend *backend, const char *device)
{
- struct fbdev_output *output;
- struct weston_head *head;
+ struct fbdev_head *head;
int fb_fd;
- weston_log("Creating fbdev output.\n");
-
- output = zalloc(sizeof *output);
- if (output == NULL)
- return -1;
+ head = zalloc(sizeof *head);
+ if (!head)
+ return NULL;
- output->backend = backend;
- output->device = strdup(device);
+ head->device = strdup(device);
/* Create the frame buffer. */
- fb_fd = fbdev_frame_buffer_open(device, &output->fb_info);
+ fb_fd = fbdev_frame_buffer_open(head->device, &head->fb_info);
if (fb_fd < 0) {
- weston_log("Creating frame buffer failed.\n");
+ weston_log("Creating frame buffer head failed.\n");
goto out_free;
}
+ close(fb_fd);
- weston_output_init(&output->base, backend->compositor, "fbdev");
+ weston_head_init(&head->base, "fbdev");
+ weston_head_set_connection_status(&head->base, true);
+ weston_head_set_monitor_strings(&head->base, "unknown",
+ head->fb_info.id, NULL);
+ weston_head_set_subpixel(&head->base, WL_OUTPUT_SUBPIXEL_UNKNOWN);
+ weston_head_set_physical_size(&head->base, head->fb_info.width_mm,
+ head->fb_info.height_mm);
- output->base.destroy = fbdev_output_destroy;
- output->base.disable = fbdev_output_disable;
- output->base.enable = fbdev_output_enable;
+ weston_compositor_add_head(backend->compositor, &head->base);
- /* only one static mode in list */
- output->mode.flags =
- WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
- output->mode.width = output->fb_info.x_resolution;
- output->mode.height = output->fb_info.y_resolution;
- output->mode.refresh = output->fb_info.refresh_rate;
- wl_list_insert(&output->base.mode_list, &output->mode.link);
+ weston_log("Created head '%s' for device %s (%s)\n",
+ head->base.name, head->device, head->base.model);
- output->base.current_mode = &output->mode;
+ return head;
- head = &output->base.head;
- weston_head_set_monitor_strings(head, "unknown", output->fb_info.id,
- NULL);
- weston_head_set_subpixel(head, WL_OUTPUT_SUBPIXEL_UNKNOWN);
- weston_head_set_physical_size(head, output->fb_info.width_mm,
- output->fb_info.height_mm);
+out_free:
+ free(head->device);
+ free(head);
- close(fb_fd);
+ return NULL;
+}
- weston_compositor_add_pending_output(&output->base, backend->compositor);
+static void
+fbdev_head_destroy(struct fbdev_head *head)
+{
+ weston_head_release(&head->base);
+ free(head->device);
+ free(head);
+}
- return 0;
+static struct weston_output *
+fbdev_output_create(struct weston_compositor *compositor,
+ const char *name)
+{
+ struct fbdev_output *output;
-out_free:
- free(output->device);
- free(output);
+ weston_log("Creating fbdev output.\n");
- return -1;
+ output = zalloc(sizeof *output);
+ if (output == NULL)
+ return NULL;
+
+ output->backend = to_fbdev_backend(compositor);
+
+ weston_output_init(&output->base, compositor, "fbdev");
+
+ output->base.destroy = fbdev_output_destroy;
+ output->base.disable = fbdev_output_disable;
+ output->base.enable = fbdev_output_enable;
+ output->base.attach_head = fbdev_output_attach_head;
+
+ weston_compositor_add_pending_output(&output->base, compositor);
+
+ return &output->base;
}
static void
@@ -566,7 +636,6 @@ fbdev_output_destroy(struct weston_output *base)
/* Remove the output. */
weston_output_release(&output->base);
- free(output->device);
free(output);
}
@@ -592,14 +661,17 @@ fbdev_output_reenable(struct fbdev_backend *backend,
struct weston_output *base)
{
struct fbdev_output *output = to_fbdev_output(base);
+ struct fbdev_head *head;
struct fbdev_screeninfo new_screen_info;
int fb_fd;
+ head = fbdev_output_get_head(output);
+
weston_log("Re-enabling fbdev output.\n");
assert(output->base.enabled);
/* Create the frame buffer. */
- fb_fd = fbdev_frame_buffer_open(output->device, &new_screen_info);
+ fb_fd = fbdev_frame_buffer_open(head->device, &new_screen_info);
if (fb_fd < 0) {
weston_log("Creating frame buffer failed.\n");
return -1;
@@ -607,9 +679,9 @@ fbdev_output_reenable(struct fbdev_backend *backend,
/* Check whether the frame buffer details have changed since we were
* disabled. */
- if (compare_screen_info (&output->fb_info, &new_screen_info) != 0) {
+ if (compare_screen_info(&head->fb_info, &new_screen_info) != 0) {
/* Perform a mode-set to restore the old mode. */
- if (fbdev_set_screen_info(fb_fd, &output->fb_info) < 0) {
+ if (fbdev_set_screen_info(fb_fd, &head->fb_info) < 0) {
weston_log("Failed to restore mode settings. "
"Attempting to re-open output anyway.\n");
}
@@ -636,12 +708,16 @@ static void
fbdev_backend_destroy(struct weston_compositor *base)
{
struct fbdev_backend *backend = to_fbdev_backend(base);
+ struct weston_head *head, *next;
udev_input_destroy(&backend->input);
/* Destroy the output. */
weston_compositor_shutdown(base);
+ wl_list_for_each_safe(head, next, &base->head_list, compositor_link)
+ fbdev_head_destroy(to_fbdev_head(head));
+
/* Chain up. */
weston_launcher_destroy(base->launcher);
@@ -738,6 +814,7 @@ fbdev_backend_create(struct weston_compositor *compositor,
backend->base.destroy = fbdev_backend_destroy;
backend->base.restore = fbdev_restore;
+ backend->base.create_output = fbdev_output_create;
backend->prev_state = WESTON_COMPOSITOR_ACTIVE;
@@ -746,7 +823,7 @@ fbdev_backend_create(struct weston_compositor *compositor,
if (pixman_renderer_init(compositor) < 0)
goto out_launcher;
- if (fbdev_output_create(backend, param->device) < 0)
+ if (!fbdev_head_create(backend, param->device))
goto out_launcher;
udev_input_init(&backend->input, compositor, backend->udev,
--
2.13.6
More information about the wayland-devel
mailing list