diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 46239fca..51636501 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -283,7 +283,6 @@ aarch64-debian-container_prep: -Dwerror=true -Dtest-skip-is-failure=true -Dlauncher-libseat=true - -Ddeprecated-backend-fbdev=true after_script: - ninja -C "$BUILDDIR" coverage-html > "$BUILDDIR/meson-logs/ninja-coverage-html.txt" - ninja -C "$BUILDDIR" coverage-xml diff --git a/README.md b/README.md index 2d093825..5613ed3e 100644 --- a/README.md +++ b/README.md @@ -287,7 +287,7 @@ Details: - Child process execution and management will be outside of libweston. -- The different backends (drm, fbdev, x11, etc) will be an internal +- The different backends (drm, x11, etc) will be an internal detail of libweston. Libweston will not support third party backends. However, hosting programs need to handle backend-specific configuration due to differences in behaviour and @@ -325,8 +325,6 @@ would be roughly like this: - xwayland (depends on X11/xcb libs) -- fbdev-backend (depends on libudev...) - - rdp-backend (depends on freerdp) - weston (the executable, not parallel-installable): diff --git a/compositor/main.c b/compositor/main.c index 3b15a959..91b3d43f 100644 --- a/compositor/main.c +++ b/compositor/main.c @@ -58,7 +58,6 @@ #include #include #include -#include #include #include #include @@ -620,9 +619,6 @@ usage(int error_code) #if defined(BUILD_DRM_COMPOSITOR) "\t\t\t\tdrm-backend.so\n" #endif -#if defined(BUILD_FBDEV_COMPOSITOR) - "\t\t\t\tfbdev-backend.so\n" -#endif #if defined(BUILD_HEADLESS_COMPOSITOR) "\t\t\t\theadless-backend.so\n" #endif @@ -665,14 +661,6 @@ usage(int error_code) " --continue-without-input\tAllow the compositor to start without input devices\n\n"); #endif -#if defined(BUILD_FBDEV_COMPOSITOR) - fprintf(out, - "Options for fbdev-backend.so:\n\n" - " --device=DEVICE\tThe framebuffer device to use\n" - " --seat=SEAT\t\tThe seat that weston should run on, instead of the seat defined in XDG_SEAT\n" - "\n"); -#endif - #if defined(BUILD_HEADLESS_COMPOSITOR) fprintf(out, "Options for headless-backend.so:\n\n" @@ -2822,53 +2810,6 @@ load_rdp_backend(struct weston_compositor *c, return ret; } -static int -fbdev_backend_output_configure(struct weston_output *output) -{ - struct weston_config *wc = wet_get_config(output->compositor); - struct weston_config_section *section; - - section = weston_config_get_section(wc, "output", "name", "fbdev"); - - if (wet_output_set_transform(output, section, - WL_OUTPUT_TRANSFORM_NORMAL, - UINT32_MAX) < 0) { - return -1; - } - - weston_output_set_scale(output, 1); - - return 0; -} - -static int -load_fbdev_backend(struct weston_compositor *c, - int *argc, char **argv, struct weston_config *wc) -{ - struct weston_fbdev_backend_config config = {{ 0, }}; - int ret = 0; - - const struct weston_option fbdev_options[] = { - { WESTON_OPTION_STRING, "device", 0, &config.device }, - { WESTON_OPTION_STRING, "seat", 0, &config.seat_id }, - }; - - parse_options(fbdev_options, ARRAY_LENGTH(fbdev_options), argc, argv); - - config.base.struct_version = WESTON_FBDEV_BACKEND_CONFIG_VERSION; - config.base.struct_size = sizeof(struct weston_fbdev_backend_config); - config.configure_device = configure_input_device; - - wet_set_simple_head_configurator(c, fbdev_backend_output_configure); - - /* load the actual wayland backend and configure it */ - ret = weston_compositor_load_backend(c, WESTON_BACKEND_FBDEV, - &config.base); - - free(config.device); - return ret; -} - static int x11_backend_output_configure(struct weston_output *output) { @@ -3114,8 +3055,6 @@ load_backend(struct weston_compositor *compositor, const char *backend, return load_headless_backend(compositor, argc, argv, config); else if (strstr(backend, "rdp-backend.so")) return load_rdp_backend(compositor, argc, argv, config); - else if (strstr(backend, "fbdev-backend.so")) - return load_fbdev_backend(compositor, argc, argv, config); else if (strstr(backend, "drm-backend.so")) return load_drm_backend(compositor, argc, argv, config); else if (strstr(backend, "x11-backend.so")) diff --git a/doc/sphinx/toc/running-weston.rst b/doc/sphinx/toc/running-weston.rst index 15babf9d..39e95f1b 100644 --- a/doc/sphinx/toc/running-weston.rst +++ b/doc/sphinx/toc/running-weston.rst @@ -6,7 +6,7 @@ underlying environment where it runs on. Ultimately, the back-end is responsible for handling the input and generate an output. Weston, as a libweston user, can be run on different back-ends, including nested, by using the wayland backend, but also on X11 or on a stand-alone back-end like -DRM/KMS and now deprecated fbdev. +DRM/KMS. In most cases, people should allow Weston to choose the backend automatically as it will produce the best results. That happens for instance when running @@ -28,7 +28,6 @@ Available back-ends: * **x11** -- run as a x11 application, nested in a X11 display server instance * **rdp** -- run as an RDP server without local input or output * **headless** -- run without input or output, useful for test suite -* **fbdev** -- run stand-alone on fbdev/evdev (deprecated) The job of gathering all the surfaces (windows) being displayed on an output and stitching them together is performed by a *renderer*. By doing so, it is diff --git a/include/libweston/backend-fbdev.h b/include/libweston/backend-fbdev.h deleted file mode 100644 index 3ed6b0a0..00000000 --- a/include/libweston/backend-fbdev.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright © 2016 Benoit Gschwind - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef WESTON_COMPOSITOR_FBDEV_H -#define WESTON_COMPOSITOR_FBDEV_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include - -#define WESTON_FBDEV_BACKEND_CONFIG_VERSION 3 - -struct libinput_device; - -struct weston_fbdev_backend_config { - struct weston_backend_config base; - - char *device; - - /** Callback used to configure input devices. - * - * This function will be called by the backend when a new input device - * needs to be configured. - * If NULL the device will use the default configuration. - */ - void (*configure_device)(struct weston_compositor *compositor, - struct libinput_device *device); - - /** The seat to be used for input and output. - * - * If seat_id is NULL, the seat is taken from XDG_SEAT environment - * variable. If neither is set, "seat0" is used. The backend will - * take ownership of the seat_id pointer and will free it on - * backend destruction. - */ - char *seat_id; -}; - -#ifdef __cplusplus -} -#endif - -#endif /* WESTON_COMPOSITOR_FBDEV_H */ diff --git a/include/libweston/libweston.h b/include/libweston/libweston.h index 849afd57..18c1f8af 100644 --- a/include/libweston/libweston.h +++ b/include/libweston/libweston.h @@ -1842,7 +1842,6 @@ weston_compositor_add_destroy_listener_once(struct weston_compositor *compositor enum weston_compositor_backend { WESTON_BACKEND_DRM, - WESTON_BACKEND_FBDEV, WESTON_BACKEND_HEADLESS, WESTON_BACKEND_RDP, WESTON_BACKEND_WAYLAND, diff --git a/include/libweston/meson.build b/include/libweston/meson.build index 1ad459bb..8ae10011 100644 --- a/include/libweston/meson.build +++ b/include/libweston/meson.build @@ -12,7 +12,6 @@ install_headers( ) backend_drm_h = files('backend-drm.h') -backend_fbdev_h = files('backend-fbdev.h') backend_headless_h = files('backend-headless.h') backend_rdp_h = files('backend-rdp.h') backend_wayland_h = files('backend-wayland.h') diff --git a/libweston/backend-fbdev/fbdev.c b/libweston/backend-fbdev/fbdev.c deleted file mode 100644 index 0ec5af0c..00000000 --- a/libweston/backend-fbdev/fbdev.c +++ /dev/null @@ -1,996 +0,0 @@ -/* - * Copyright © 2008-2011 Kristian Høgsberg - * Copyright © 2011 Intel Corporation - * Copyright © 2012 Raspberry Pi Foundation - * Copyright © 2013 Philip Withnall - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "shared/helpers.h" -#include -#include -#include "launcher-util.h" -#include "pixman-renderer.h" -#include "libinput-seat.h" -#include "presentation-time-server-protocol.h" - -struct fbdev_backend { - struct weston_backend base; - struct weston_compositor *compositor; - uint32_t prev_state; - - struct udev *udev; - struct udev_input input; - uint32_t output_transform; - struct wl_listener session_listener; -}; - -struct fbdev_screeninfo { - unsigned int x_resolution; /* pixels, visible area */ - unsigned int y_resolution; /* pixels, visible area */ - unsigned int width_mm; /* visible screen width in mm */ - unsigned int height_mm; /* visible screen height in mm */ - unsigned int bits_per_pixel; - - size_t buffer_length; /* length of frame buffer memory in bytes */ - size_t line_length; /* length of a line in bytes */ - char id[16]; /* screen identifier */ - - pixman_format_code_t pixel_format; /* frame buffer pixel format */ - 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; - - struct weston_mode mode; - struct wl_event_source *finish_frame_timer; - - /* framebuffer mmap details */ - size_t buffer_length; - void *fb; - - /* pixman details. */ - pixman_image_t *hw_surface; -}; - -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) -{ - return container_of(base, struct fbdev_output, base); -} - -static inline struct fbdev_backend * -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 int -fbdev_output_start_repaint_loop(struct weston_output *output) -{ - struct timespec ts; - - weston_compositor_read_presentation_clock(output->compositor, &ts); - weston_output_finish_frame(output, &ts, WP_PRESENTATION_FEEDBACK_INVALID); - - return 0; -} - -static int -fbdev_output_repaint(struct weston_output *base, pixman_region32_t *damage, - void *repaint_data) -{ - struct fbdev_output *output = to_fbdev_output(base); - struct weston_compositor *ec = output->base.compositor; - - /* Repaint the damaged region onto the back buffer. */ - pixman_renderer_output_set_buffer(base, output->hw_surface); - ec->renderer->repaint_output(base, damage); - - /* Update the damage region. */ - pixman_region32_subtract(&ec->primary_plane.damage, - &ec->primary_plane.damage, damage); - - /* Schedule the end of the frame. We do not sync this to the frame - * buffer clock because users who want that should be using the DRM - * compositor. FBIO_WAITFORVSYNC blocks and FB_ACTIVATE_VBL requires - * panning, which is broken in most kernel drivers. - * - * Finish the frame synchronised to the specified refresh rate. The - * refresh rate is given in mHz and the interval in ms. */ - wl_event_source_timer_update(output->finish_frame_timer, - 1000000 / output->mode.refresh); - - return 0; -} - -static int -finish_frame_handler(void *data) -{ - struct fbdev_output *output = data; - struct timespec ts; - - weston_compositor_read_presentation_clock(output->base.compositor, &ts); - weston_output_finish_frame(&output->base, &ts, 0); - - return 1; -} - -static pixman_format_code_t -calculate_pixman_format(struct fb_var_screeninfo *vinfo, - struct fb_fix_screeninfo *finfo) -{ - /* Calculate the pixman format supported by the frame buffer from the - * buffer's metadata. Return 0 if no known pixman format is supported - * (since this has depth 0 it's guaranteed to not conflict with any - * actual pixman format). - * - * Documentation on the vinfo and finfo structures: - * http://www.mjmwired.net/kernel/Documentation/fb/api.txt - * - * TODO: Try a bit harder to support other formats, including setting - * the preferred format in the hardware. */ - int type; - - weston_log("Calculating pixman format from:\n" - STAMP_SPACE " - type: %i (aux: %i)\n" - STAMP_SPACE " - visual: %i\n" - STAMP_SPACE " - bpp: %i (grayscale: %i)\n" - STAMP_SPACE " - red: offset: %i, length: %i, MSB: %i\n" - STAMP_SPACE " - green: offset: %i, length: %i, MSB: %i\n" - STAMP_SPACE " - blue: offset: %i, length: %i, MSB: %i\n" - STAMP_SPACE " - transp: offset: %i, length: %i, MSB: %i\n", - finfo->type, finfo->type_aux, finfo->visual, - vinfo->bits_per_pixel, vinfo->grayscale, - vinfo->red.offset, vinfo->red.length, vinfo->red.msb_right, - vinfo->green.offset, vinfo->green.length, - vinfo->green.msb_right, - vinfo->blue.offset, vinfo->blue.length, - vinfo->blue.msb_right, - vinfo->transp.offset, vinfo->transp.length, - vinfo->transp.msb_right); - - /* We only handle packed formats at the moment. */ - if (finfo->type != FB_TYPE_PACKED_PIXELS) - return 0; - - /* We only handle true-colour frame buffers at the moment. */ - switch(finfo->visual) { - case FB_VISUAL_TRUECOLOR: - case FB_VISUAL_DIRECTCOLOR: - if (vinfo->grayscale != 0) - return 0; - break; - default: - return 0; - } - - /* We only support formats with MSBs on the left. */ - if (vinfo->red.msb_right != 0 || vinfo->green.msb_right != 0 || - vinfo->blue.msb_right != 0) - return 0; - - /* Work out the format type from the offsets. We only support RGBA, ARGB - * and ABGR at the moment. */ - type = PIXMAN_TYPE_OTHER; - - if ((vinfo->transp.offset >= vinfo->red.offset || - vinfo->transp.length == 0) && - vinfo->red.offset >= vinfo->green.offset && - vinfo->green.offset >= vinfo->blue.offset) - type = PIXMAN_TYPE_ARGB; - else if (vinfo->red.offset >= vinfo->green.offset && - vinfo->green.offset >= vinfo->blue.offset && - vinfo->blue.offset >= vinfo->transp.offset) - type = PIXMAN_TYPE_RGBA; - else if (vinfo->transp.offset >= vinfo->blue.offset && - vinfo->blue.offset >= vinfo->green.offset && - vinfo->green.offset >= vinfo->red.offset) - type = PIXMAN_TYPE_ABGR; - - if (type == PIXMAN_TYPE_OTHER) - return 0; - - /* Build the format. */ - return PIXMAN_FORMAT(vinfo->bits_per_pixel, type, - vinfo->transp.length, - vinfo->red.length, - vinfo->green.length, - vinfo->blue.length); -} - -static int -calculate_refresh_rate(struct fb_var_screeninfo *vinfo) -{ - uint64_t quot; - - /* Calculate monitor refresh rate. Default is 60 Hz. Units are mHz. */ - quot = (vinfo->upper_margin + vinfo->lower_margin + vinfo->yres); - quot *= (vinfo->left_margin + vinfo->right_margin + vinfo->xres); - quot *= vinfo->pixclock; - - if (quot > 0) { - uint64_t refresh_rate; - - refresh_rate = 1000000000000000LLU / quot; - if (refresh_rate > 200000) - refresh_rate = 200000; /* cap at 200 Hz */ - - if (refresh_rate >= 1000) /* at least 1 Hz */ - return refresh_rate; - } - - return 60 * 1000; /* default to 60 Hz */ -} - -static int -fbdev_query_screen_info(int fd, struct fbdev_screeninfo *info) -{ - struct fb_var_screeninfo varinfo; - struct fb_fix_screeninfo fixinfo; - - /* Probe the device for screen information. */ - if (ioctl(fd, FBIOGET_FSCREENINFO, &fixinfo) < 0 || - ioctl(fd, FBIOGET_VSCREENINFO, &varinfo) < 0) { - return -1; - } - - /* Store the pertinent data. */ - info->x_resolution = varinfo.xres; - info->y_resolution = varinfo.yres; - info->width_mm = varinfo.width; - info->height_mm = varinfo.height; - info->bits_per_pixel = varinfo.bits_per_pixel; - - info->buffer_length = fixinfo.smem_len; - info->line_length = fixinfo.line_length; - strncpy(info->id, fixinfo.id, sizeof(info->id)); - info->id[sizeof(info->id)-1] = '\0'; - - info->pixel_format = calculate_pixman_format(&varinfo, &fixinfo); - info->refresh_rate = calculate_refresh_rate(&varinfo); - - if (info->pixel_format == 0) { - weston_log("Frame buffer uses an unsupported format.\n"); - return -1; - } - - return 1; -} - -static int -fbdev_set_screen_info(int fd, struct fbdev_screeninfo *info) -{ - struct fb_var_screeninfo varinfo; - - /* Grab the current screen information. */ - if (ioctl(fd, FBIOGET_VSCREENINFO, &varinfo) < 0) { - return -1; - } - - /* Update the information. */ - varinfo.xres = info->x_resolution; - varinfo.yres = info->y_resolution; - varinfo.width = info->width_mm; - varinfo.height = info->height_mm; - varinfo.bits_per_pixel = info->bits_per_pixel; - - /* Try to set up an ARGB (x8r8g8b8) pixel format. */ - varinfo.grayscale = 0; - varinfo.transp.offset = 24; - varinfo.transp.length = 0; - varinfo.transp.msb_right = 0; - varinfo.red.offset = 16; - varinfo.red.length = 8; - varinfo.red.msb_right = 0; - varinfo.green.offset = 8; - varinfo.green.length = 8; - varinfo.green.msb_right = 0; - varinfo.blue.offset = 0; - varinfo.blue.length = 8; - varinfo.blue.msb_right = 0; - - /* Set the device's screen information. */ - if (ioctl(fd, FBIOPUT_VSCREENINFO, &varinfo) < 0) { - return -1; - } - - return 1; -} - -static int -fbdev_wakeup_screen(int fd, struct fbdev_screeninfo *info) -{ - struct fb_var_screeninfo varinfo; - - /* Grab the current screen information. */ - if (ioctl(fd, FBIOGET_VSCREENINFO, &varinfo) < 0) { - return -1; - } - - /* force the framebuffer to wake up */ - varinfo.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE; - - /* Set the device's screen information. */ - if (ioctl(fd, FBIOPUT_VSCREENINFO, &varinfo) < 0) { - return -1; - } - - return 1; -} - -/* Returns an FD for the frame buffer device. */ -static int -fbdev_frame_buffer_open(const char *fb_dev, - struct fbdev_screeninfo *screen_info) -{ - int fd = -1; - - weston_log("Opening fbdev frame buffer.\n"); - - /* Open the frame buffer device. */ - fd = open(fb_dev, O_RDWR | O_CLOEXEC); - if (fd < 0) { - weston_log("Failed to open frame buffer device ‘%s’: %s\n", - fb_dev, strerror(errno)); - return -1; - } - - /* Grab the screen info. */ - if (fbdev_query_screen_info(fd, screen_info) < 0) { - weston_log("Failed to get frame buffer info: %s\n", - strerror(errno)); - - close(fd); - return -1; - } - - /* Attempt to wake up the framebuffer device, needed for secondary - * framebuffer devices */ - if (fbdev_wakeup_screen(fd, screen_info) < 0) { - weston_log("Failed to activate framebuffer display. " - "Attempting to open output anyway.\n"); - } - - - return fd; -} - -/* Closes the FD on success or failure. */ -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->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", - strerror(errno)); - output->fb = NULL; - goto out_close; - } - - /* Create a pixman image to wrap the memory mapped frame buffer. */ - output->hw_surface = - pixman_image_create_bits(head->fb_info.pixel_format, - head->fb_info.x_resolution, - head->fb_info.y_resolution, - output->fb, - head->fb_info.line_length); - if (output->hw_surface == NULL) { - weston_log("Failed to create surface for frame buffer.\n"); - goto out_unmap; - } - - /* Success! */ - retval = 0; - -out_unmap: - if (retval != 0 && output->fb != NULL) { - munmap(output->fb, output->buffer_length); - output->fb = NULL; - } - -out_close: - if (fd >= 0) - close(fd); - - return retval; -} - -static void -fbdev_frame_buffer_unmap(struct fbdev_output *output) -{ - if (!output->fb) { - assert(!output->hw_surface); - return; - } - - weston_log("Unmapping fbdev frame buffer.\n"); - - if (output->hw_surface) - pixman_image_unref(output->hw_surface); - output->hw_surface = NULL; - - 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 -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; - const struct pixman_renderer_output_options options = { - .use_shadow = true, - }; - - head = fbdev_output_get_head(output); - - /* Create the frame buffer. */ - fb_fd = fbdev_frame_buffer_open(head->device, &head->fb_info); - if (fb_fd < 0) { - weston_log("Creating frame buffer failed.\n"); - return -1; - } - - if (fbdev_frame_buffer_map(output, fb_fd) < 0) { - weston_log("Mapping frame buffer failed.\n"); - return -1; - } - - output->base.start_repaint_loop = fbdev_output_start_repaint_loop; - output->base.repaint = fbdev_output_repaint; - - if (pixman_renderer_output_create(&output->base, &options) < 0) - goto out_hw_surface; - - loop = wl_display_get_event_loop(backend->compositor->wl_display); - output->finish_frame_timer = - wl_event_loop_add_timer(loop, finish_frame_handler, output); - - weston_log("fbdev output %d×%d px\n", - output->mode.width, output->mode.height); - weston_log_continue(STAMP_SPACE "guessing %d Hz and 96 dpi\n", - output->mode.refresh / 1000); - - return 0; - -out_hw_surface: - fbdev_frame_buffer_unmap(output); - - return -1; -} - -static int -fbdev_output_disable(struct weston_output *base) -{ - struct fbdev_output *output = to_fbdev_output(base); - - if (!base->enabled) - return 0; - - wl_event_source_remove(output->finish_frame_timer); - output->finish_frame_timer = NULL; - - pixman_renderer_output_destroy(&output->base); - fbdev_frame_buffer_unmap(output); - - return 0; -} - -static struct fbdev_head * -fbdev_head_create(struct fbdev_backend *backend, const char *device) -{ - struct fbdev_head *head; - int fb_fd; - - head = zalloc(sizeof *head); - if (!head) - return NULL; - - head->device = strdup(device); - - /* Create the frame buffer. */ - fb_fd = fbdev_frame_buffer_open(head->device, &head->fb_info); - if (fb_fd < 0) { - weston_log("Creating frame buffer head failed.\n"); - goto out_free; - } - close(fb_fd); - - 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); - - weston_compositor_add_head(backend->compositor, &head->base); - - weston_log("Created head '%s' for device %s (%s)\n", - head->base.name, head->device, head->base.model); - - return head; - -out_free: - free(head->device); - free(head); - - return NULL; -} - -static void -fbdev_head_destroy(struct fbdev_head *head) -{ - weston_head_release(&head->base); - free(head->device); - free(head); -} - -static struct weston_output * -fbdev_output_create(struct weston_compositor *compositor, - const char *name) -{ - struct fbdev_output *output; - - weston_log("Creating fbdev output.\n"); - - output = zalloc(sizeof *output); - if (output == NULL) - return NULL; - - output->backend = to_fbdev_backend(compositor); - - weston_output_init(&output->base, compositor, name); - - 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 -fbdev_output_destroy(struct weston_output *base) -{ - struct fbdev_output *output = to_fbdev_output(base); - - weston_log("Destroying fbdev output.\n"); - - fbdev_output_disable(base); - - /* Remove the output. */ - weston_output_release(&output->base); - - free(output); -} - -/* strcmp()-style return values. */ -static int -compare_screen_info (const struct fbdev_screeninfo *a, - const struct fbdev_screeninfo *b) -{ - if (a->x_resolution == b->x_resolution && - a->y_resolution == b->y_resolution && - a->width_mm == b->width_mm && - a->height_mm == b->height_mm && - a->bits_per_pixel == b->bits_per_pixel && - a->pixel_format == b->pixel_format && - a->refresh_rate == b->refresh_rate) - return 0; - - return 1; -} - -static int -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(head->device, &new_screen_info); - if (fb_fd < 0) { - weston_log("Creating frame buffer failed.\n"); - return -1; - } - - /* Check whether the frame buffer details have changed since we were - * disabled. */ - 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, &head->fb_info) < 0) { - weston_log("Failed to restore mode settings. " - "Attempting to re-open output anyway.\n"); - } - - close(fb_fd); - - /* Disable and enable the output so that resources depending on - * the frame buffer X/Y resolution (such as the shadow buffer) - * are re-initialised. */ - fbdev_output_disable(&output->base); - return fbdev_output_enable(&output->base); - } - - /* Map the device if it has the same details as before. */ - if (fbdev_frame_buffer_map(output, fb_fd) < 0) { - weston_log("Mapping frame buffer failed.\n"); - return -1; - } - - return 0; -} - -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); - - udev_unref(backend->udev); - - free(backend); -} - -static void -session_notify(struct wl_listener *listener, void *data) -{ - struct weston_compositor *compositor = data; - struct fbdev_backend *backend = to_fbdev_backend(compositor); - struct weston_output *output; - - if (compositor->session_active) { - weston_log("entering VT\n"); - compositor->state = backend->prev_state; - - wl_list_for_each(output, &compositor->output_list, link) { - fbdev_output_reenable(backend, output); - } - - weston_compositor_damage_all(compositor); - - udev_input_enable(&backend->input); - } else { - weston_log("leaving VT\n"); - udev_input_disable(&backend->input); - - wl_list_for_each(output, &compositor->output_list, link) { - fbdev_frame_buffer_unmap(to_fbdev_output(output)); - } - - backend->prev_state = compositor->state; - weston_compositor_offscreen(compositor); - - /* If we have a repaint scheduled (from the idle handler), make - * sure we cancel that so we don't try to pageflip when we're - * vt switched away. The OFFSCREEN state will prevent - * further attempts at repainting. When we switch - * back, we schedule a repaint, which will process - * pending frame callbacks. */ - - wl_list_for_each(output, - &compositor->output_list, link) { - output->repaint_needed = false; - } - } -} - -static char * -find_framebuffer_device(struct fbdev_backend *b, const char *seat) -{ - struct udev_enumerate *e; - struct udev_list_entry *entry; - const char *path, *device_seat, *id; - char *fb_device_path = NULL; - struct udev_device *device, *fb_device, *pci; - - e = udev_enumerate_new(b->udev); - udev_enumerate_add_match_subsystem(e, "graphics"); - udev_enumerate_add_match_sysname(e, "fb[0-9]*"); - - udev_enumerate_scan_devices(e); - fb_device = NULL; - udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) { - bool is_boot_vga = false; - - path = udev_list_entry_get_name(entry); - device = udev_device_new_from_syspath(b->udev, path); - if (!device) - continue; - device_seat = udev_device_get_property_value(device, "ID_SEAT"); - if (!device_seat) - device_seat = default_seat; - if (strcmp(device_seat, seat)) { - udev_device_unref(device); - continue; - } - - pci = udev_device_get_parent_with_subsystem_devtype(device, - "pci", NULL); - if (pci) { - id = udev_device_get_sysattr_value(pci, "boot_vga"); - if (id && !strcmp(id, "1")) - is_boot_vga = true; - } - - /* If a framebuffer device was found, and this device isn't - * the boot-VGA device, don't use it. */ - if (!is_boot_vga && fb_device) { - udev_device_unref(device); - continue; - } - - /* There can only be one boot_vga device. Try to use it - * at all costs. */ - if (is_boot_vga) { - if (fb_device) - udev_device_unref(fb_device); - fb_device = device; - break; - } - - /* Per the (!is_boot_vga && fb_device) test above, only - * trump existing saved devices with boot-VGA devices, so if - * the test ends up here, this must be the first device seen. */ - assert(!fb_device); - fb_device = device; - } - - udev_enumerate_unref(e); - - if (fb_device) { - fb_device_path = strdup(udev_device_get_devnode(fb_device)); - udev_device_unref(fb_device); - } - - return fb_device_path; -} - -static struct fbdev_backend * -fbdev_backend_create(struct weston_compositor *compositor, - struct weston_fbdev_backend_config *param) -{ - struct fbdev_backend *backend; - const char *seat_id = default_seat; - const char *session_seat; - - session_seat = getenv("XDG_SEAT"); - if (session_seat) - seat_id = session_seat; - if (param->seat_id) - seat_id = param->seat_id; - - weston_log("initializing fbdev backend\n"); - weston_log("warning: the fbdev backend is deprecated, please migrate " - "to the DRM backend\n"); - - backend = zalloc(sizeof *backend); - if (backend == NULL) - return NULL; - - backend->compositor = compositor; - compositor->backend = &backend->base; - if (weston_compositor_set_presentation_clock_software( - compositor) < 0) - goto out_compositor; - - backend->udev = udev_new(); - if (backend->udev == NULL) { - weston_log("Failed to initialize udev context.\n"); - goto out_compositor; - } - - if (!param->device) - param->device = find_framebuffer_device(backend, seat_id); - if (!param->device) { - weston_log("fatal: no framebuffer devices detected.\n"); - goto out_udev; - } - - /* Set up the TTY. */ - backend->session_listener.notify = session_notify; - wl_signal_add(&compositor->session_signal, - &backend->session_listener); - compositor->launcher = - weston_launcher_connect(compositor, seat_id, false); - if (!compositor->launcher) { - weston_log("fatal: your system should either provide the " - "logind D-Bus API, or use seatd.\n"); - goto out_udev; - } - - backend->base.destroy = fbdev_backend_destroy; - backend->base.create_output = fbdev_output_create; - - backend->prev_state = WESTON_COMPOSITOR_ACTIVE; - - weston_setup_vt_switch_bindings(compositor); - - if (pixman_renderer_init(compositor) < 0) - goto out_launcher; - - if (!fbdev_head_create(backend, param->device)) - goto out_launcher; - - free(param->device); - - udev_input_init(&backend->input, compositor, backend->udev, - seat_id, param->configure_device); - - return backend; - -out_launcher: - free(param->device); - weston_launcher_destroy(compositor->launcher); - -out_udev: - udev_unref(backend->udev); - -out_compositor: - weston_compositor_shutdown(compositor); - free(backend); - - return NULL; -} - -static void -config_init_to_defaults(struct weston_fbdev_backend_config *config) -{ - config->device = NULL; - config->seat_id = NULL; -} - -WL_EXPORT int -weston_backend_init(struct weston_compositor *compositor, - struct weston_backend_config *config_base) -{ - struct fbdev_backend *b; - struct weston_fbdev_backend_config config = {{ 0, }}; - - if (config_base == NULL || - config_base->struct_version != WESTON_FBDEV_BACKEND_CONFIG_VERSION || - config_base->struct_size > sizeof(struct weston_fbdev_backend_config)) { - weston_log("fbdev backend config structure is invalid\n"); - return -1; - } - - config_init_to_defaults(&config); - memcpy(&config, config_base, config_base->struct_size); - - b = fbdev_backend_create(compositor, &config); - if (b == NULL) - return -1; - return 0; -} diff --git a/libweston/backend-fbdev/meson.build b/libweston/backend-fbdev/meson.build deleted file mode 100644 index 563ad6c5..00000000 --- a/libweston/backend-fbdev/meson.build +++ /dev/null @@ -1,33 +0,0 @@ -if not get_option('deprecated-backend-fbdev') - subdir_done() -endif - -warning('Support for the deprecated fbdev backend is enabled.') -warning('This feature will be removed in a future version.') - -config_h.set('BUILD_FBDEV_COMPOSITOR', '1') - -srcs_fbdev = [ - 'fbdev.c', - presentation_time_server_protocol_h, -] - -deps_fbdev = [ - dep_libweston_private, - dep_session_helper, - dep_libinput_backend, - dependency('libudev', version: '>= 136'), -] - -plugin_fbdev = shared_library( - 'fbdev-backend', - srcs_fbdev, - include_directories: common_inc, - dependencies: deps_fbdev, - name_prefix: '', - install: true, - install_dir: dir_module_libweston -) -env_modmap += 'fbdev-backend.so=@0@;'.format(plugin_fbdev.full_path()) - -install_headers(backend_fbdev_h, subdir: dir_include_libweston_install) diff --git a/libweston/compositor.c b/libweston/compositor.c index 955e5534..2c1dcf0d 100644 --- a/libweston/compositor.c +++ b/libweston/compositor.c @@ -8261,7 +8261,6 @@ weston_compositor_get_user_data(struct weston_compositor *compositor) static const char * const backend_map[] = { [WESTON_BACKEND_DRM] = "drm-backend.so", - [WESTON_BACKEND_FBDEV] = "fbdev-backend.so", [WESTON_BACKEND_HEADLESS] = "headless-backend.so", [WESTON_BACKEND_RDP] = "rdp-backend.so", [WESTON_BACKEND_WAYLAND] = "wayland-backend.so", diff --git a/libweston/meson.build b/libweston/meson.build index ca660e9a..7638b1c1 100644 --- a/libweston/meson.build +++ b/libweston/meson.build @@ -223,7 +223,6 @@ dep_vertex_clipping = declare_dependency( subdir('color-lcms') subdir('renderer-gl') subdir('backend-drm') -subdir('backend-fbdev') subdir('backend-headless') subdir('backend-rdp') subdir('backend-wayland') diff --git a/man/weston.ini.man b/man/weston.ini.man index d7fc42b3..8aa0d1c2 100644 --- a/man/weston.ini.man +++ b/man/weston.ini.man @@ -130,7 +130,6 @@ directory are: .RS 10 .nf .BR drm-backend.so -.BR fbdev-backend.so .BR headless-backend.so .BR rdp-backend.so .BR wayland-backend.so diff --git a/meson_options.txt b/meson_options.txt index b9340dc2..90ab3832 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -44,16 +44,10 @@ option( value: true, description: 'Weston backend: X11 (nested)' ) -option( - 'deprecated-backend-fbdev', - type: 'boolean', - value: false, - description: 'Weston backend: fbdev (deprecated)' -) option( 'backend-default', type: 'combo', - choices: [ 'auto', 'drm', 'wayland', 'x11', 'fbdev', 'headless' ], + choices: [ 'auto', 'drm', 'wayland', 'x11', 'headless' ], value: 'drm', description: 'Default backend when no parent display server detected' ) diff --git a/tests/weston-test-fixture-compositor.c b/tests/weston-test-fixture-compositor.c index 64325fb1..87ff6bf1 100644 --- a/tests/weston-test-fixture-compositor.c +++ b/tests/weston-test-fixture-compositor.c @@ -202,7 +202,6 @@ backend_to_str(enum weston_compositor_backend b) { static const char * const names[] = { [WESTON_BACKEND_DRM] = "drm-backend.so", - [WESTON_BACKEND_FBDEV] = "fbdev-backend.so", [WESTON_BACKEND_HEADLESS] = "headless-backend.so", [WESTON_BACKEND_RDP] = "rdp-backend.so", [WESTON_BACKEND_WAYLAND] = "wayland-backend.so", @@ -302,13 +301,6 @@ execute_compositor(const struct compositor_setup *setup, } #endif -#ifndef BUILD_FBDEV_COMPOSITOR - if (setup->backend == WESTON_BACKEND_FBDEV) { - fprintf(stderr, "fbdev-backend required but not built, skipping.\n"); - return RESULT_SKIP; - } -#endif - #ifndef BUILD_RDP_COMPOSITOR if (setup->backend == WESTON_BACKEND_RDP) { fprintf(stderr, "RDP-backend required but not built, skipping.\n"); @@ -389,8 +381,7 @@ execute_compositor(const struct compositor_setup *setup, setup->extra_module ? setup->extra_module : ""); prog_args_take(&args, tmp); - if (setup->backend != WESTON_BACKEND_DRM && - setup->backend != WESTON_BACKEND_FBDEV) { + if (setup->backend != WESTON_BACKEND_DRM) { str_printf(&tmp, "--width=%d", setup->width); prog_args_take(&args, tmp);