Merge tag 'JH7110_515_SDK_v5.2.1' into jh7110-mm-devel
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
# From https://mirrors.edge.kernel.org/pub/linux/kernel/firmware/sha256sums.asc
|
||||
sha256 2fb22a5d7d23bf1f5800ab8152b39a00a445fbf4923de5a01b59d3f6253f0a9f linux-firmware-20210919.tar.xz
|
||||
sha256 8b1acfa16f1ee94732a6acb50d9d6c835cf53af11068bd89ed207bbe04a1e951 linux-firmware-20230515.tar.xz
|
||||
|
||||
# Hash for license files
|
||||
sha256 8116433f4004fc0c24d72b3d9e497808b724aa0e5e1cd63fc1bf66b715b1e2e9 LICENCE.Abilis
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#
|
||||
################################################################################
|
||||
|
||||
LINUX_FIRMWARE_VERSION = 20210919
|
||||
LINUX_FIRMWARE_VERSION = 20230515
|
||||
LINUX_FIRMWARE_SOURCE = linux-firmware-$(LINUX_FIRMWARE_VERSION).tar.xz
|
||||
LINUX_FIRMWARE_SITE = $(BR2_KERNEL_MIRROR)/linux/kernel/firmware
|
||||
LINUX_FIRMWARE_INSTALL_IMAGES = YES
|
||||
@@ -82,7 +82,8 @@ LINUX_FIRMWARE_FILES += \
|
||||
rtl_bt/rtl8821c_config.bin rtl_bt/rtl8821c_fw.bin \
|
||||
rtl_bt/rtl8822b_config.bin rtl_bt/rtl8822b_fw.bin \
|
||||
rtl_bt/rtl8822cs_config.bin rtl_bt/rtl8822cs_fw.bin \
|
||||
rtl_bt/rtl8822cu_config.bin rtl_bt/rtl8822cu_fw.bin
|
||||
rtl_bt/rtl8822cu_config.bin rtl_bt/rtl8822cu_fw.bin \
|
||||
rtl_bt/rtl8852bu_config.bin rtl_bt/rtl8852bu_fw.bin
|
||||
LINUX_FIRMWARE_ALL_LICENSE_FILES += LICENCE.rtlwifi_firmware.txt
|
||||
endif
|
||||
|
||||
@@ -502,7 +503,15 @@ LINUX_FIRMWARE_ALL_LICENSE_FILES += LICENCE.iwlwifi_firmware
|
||||
endif
|
||||
|
||||
ifeq ($(BR2_PACKAGE_LINUX_FIRMWARE_IWLWIFI_AX210),y)
|
||||
ifeq ($(BR2_PACKAGE_HOST_LINUX_HEADERS_CUSTOM_5_15),y)
|
||||
LINUX_FIRMWARE_FILES += iwlwifi-ty-a0-gf-a0-59.ucode
|
||||
else ifeq ($(BR2_PACKAGE_HOST_LINUX_HEADERS_CUSTOM_5_10),y)
|
||||
LINUX_FIRMWARE_FILES += iwlwifi-ty-a0-gf-a0-59.ucode
|
||||
else
|
||||
LINUX_FIRMWARE_FILES += \
|
||||
iwlwifi-ty-a0-gf-a0-72.ucode \
|
||||
iwlwifi-ty-a0-gf-a0.pnvm
|
||||
endif
|
||||
LINUX_FIRMWARE_ALL_LICENSE_FILES += LICENCE.iwlwifi_firmware
|
||||
endif
|
||||
|
||||
|
||||
@@ -0,0 +1,768 @@
|
||||
Setting weston primary display by export WESTON_SET_PRIMARY=HDMI-A-1 or
|
||||
WESTON_SET_PRIMARY=DSI-1
|
||||
|
||||
Signed-off-by: Leo Lu <leo.lu@starfivetech.com>
|
||||
|
||||
--- a/compositor/main.c 2023-06-02 13:52:25.541476191 +0800
|
||||
+++ b/compositor/main.c 2023-06-02 16:54:50.142022438 +0800
|
||||
@@ -2068,11 +2068,10 @@ drm_head_prepare_enable(struct wet_compo
|
||||
struct weston_head *head)
|
||||
{
|
||||
const char *name = weston_head_get_name(head);
|
||||
- struct weston_config_section *section;
|
||||
+ struct weston_config_section *section = head->section;
|
||||
char *output_name = NULL;
|
||||
char *mode = NULL;
|
||||
|
||||
- section = drm_config_find_controlling_output_section(wet->config, name);
|
||||
if (section) {
|
||||
/* skip outputs that are explicitly off, or non-desktop and not
|
||||
* explicitly enabled. The backend turns them off automatically.
|
||||
@@ -2102,11 +2101,9 @@ static bool
|
||||
drm_head_should_force_enable(struct wet_compositor *wet,
|
||||
struct weston_head *head)
|
||||
{
|
||||
- const char *name = weston_head_get_name(head);
|
||||
- struct weston_config_section *section;
|
||||
+ struct weston_config_section *section = head->section;
|
||||
bool force;
|
||||
|
||||
- section = drm_config_find_controlling_output_section(wet->config, name);
|
||||
if (!section)
|
||||
return false;
|
||||
|
||||
@@ -2114,6 +2111,25 @@ drm_head_should_force_enable(struct wet_
|
||||
return force;
|
||||
}
|
||||
|
||||
+static bool
|
||||
+drm_head_update_output_section(struct weston_head *head)
|
||||
+{
|
||||
+ struct weston_compositor *compositor = head->compositor;
|
||||
+ struct wet_compositor *wet = to_wet_compositor(compositor);
|
||||
+ const char *name = weston_head_get_name(head);
|
||||
+ struct weston_config_section *section;
|
||||
+
|
||||
+ if (head->section)
|
||||
+ return true;
|
||||
+
|
||||
+ section = drm_config_find_controlling_output_section(wet->config, name);
|
||||
+ if (!section)
|
||||
+ return false;
|
||||
+
|
||||
+ head->section = section;
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
static void
|
||||
drm_try_attach(struct weston_output *output,
|
||||
struct wet_head_array *add,
|
||||
@@ -2309,6 +2325,7 @@ drm_heads_changed(struct wl_listener *li
|
||||
* output.
|
||||
*/
|
||||
while ((head = weston_compositor_iterate_heads(compositor, head))) {
|
||||
+ drm_head_update_output_section(head);
|
||||
connected = weston_head_is_connected(head);
|
||||
enabled = weston_head_is_enabled(head);
|
||||
changed = weston_head_is_device_changed(head);
|
||||
--- a/desktop-shell/shell.c 2023-06-02 13:52:25.545476210 +0800
|
||||
+++ b/desktop-shell/shell.c 2023-06-02 16:54:50.158022573 +0800
|
||||
@@ -3977,6 +3977,9 @@ shell_fade_done_for_output(struct weston
|
||||
struct shell_output *shell_output = data;
|
||||
struct desktop_shell *shell = shell_output->shell;
|
||||
|
||||
+ if (!shell_output->fade.view)
|
||||
+ return;
|
||||
+
|
||||
shell_output->fade.animation = NULL;
|
||||
switch (shell_output->fade.type) {
|
||||
case FADE_IN:
|
||||
@@ -4010,7 +4013,8 @@ shell_fade_create_surface_for_output(str
|
||||
|
||||
weston_surface_set_size(surface, shell_output->output->width, shell_output->output->height);
|
||||
weston_view_set_position(view, shell_output->output->x, shell_output->output->y);
|
||||
- weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1.0);
|
||||
+ weston_view_set_output(view, shell_output->output);
|
||||
+ weston_surface_set_color(surface, 0, 0.0, 0.0, 1.0);
|
||||
weston_layer_entry_insert(&compositor->fade_layer.view_list,
|
||||
&view->layer_link);
|
||||
pixman_region32_init(&surface->input);
|
||||
@@ -4824,8 +4828,11 @@ shell_output_destroy(struct shell_output
|
||||
}
|
||||
|
||||
if (shell_output->fade.view) {
|
||||
- /* destroys the view as well */
|
||||
- weston_surface_destroy(shell_output->fade.view->surface);
|
||||
+ struct weston_view *view = shell_output->fade.view;
|
||||
+ shell_output->fade.view = NULL;
|
||||
+
|
||||
+ /* destroys the view as well */
|
||||
+ weston_surface_destroy(view->surface);
|
||||
}
|
||||
|
||||
if (shell_output->fade.startup_timer)
|
||||
@@ -4930,11 +4937,24 @@ static void
|
||||
handle_output_move(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct desktop_shell *shell;
|
||||
+ struct weston_output *output = data;
|
||||
+ struct weston_compositor *compositor = output->compositor;
|
||||
|
||||
shell = container_of(listener, struct desktop_shell,
|
||||
output_move_listener);
|
||||
|
||||
- shell_for_each_layer(shell, handle_output_move_layer, data);
|
||||
+ if (shell->lock_surface)
|
||||
+ shell->lock_surface->committed(shell->lock_surface, 0, 0);
|
||||
+
|
||||
+ /* Only move normal layers for non-default output */
|
||||
+ if (output != get_default_output(compositor)) {
|
||||
+ shell_for_each_layer(shell, handle_output_move_layer, data);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ handle_output_move_layer(shell, &shell->lock_layer, data);
|
||||
+ handle_output_move_layer(shell, &shell->background_layer, data);
|
||||
+ handle_output_move_layer(shell, &shell->panel_layer, data);
|
||||
}
|
||||
|
||||
static void
|
||||
--- a/include/libweston/libweston.h 2023-06-02 13:52:25.545476210 +0800
|
||||
+++ b/include/libweston/libweston.h 2023-06-02 16:54:50.162022607 +0800
|
||||
@@ -261,6 +261,8 @@ struct weston_head {
|
||||
|
||||
/** Current content protection status */
|
||||
enum weston_hdcp_protection current_protection;
|
||||
+ struct weston_config_section *section; /**< config section **/
|
||||
+
|
||||
};
|
||||
|
||||
/** Content producer for heads
|
||||
@@ -2153,6 +2155,10 @@ struct weston_color_profile *
|
||||
weston_compositor_load_icc_file(struct weston_compositor *compositor,
|
||||
const char *path);
|
||||
|
||||
+void
|
||||
+weston_compositor_reflow_outputs(struct weston_compositor *compositor,
|
||||
+ struct weston_output *resized_output, int delta_width);
|
||||
+
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
--- a/libweston/backend-drm/drm.c 2023-06-02 13:52:25.549476228 +0800
|
||||
+++ b/libweston/backend-drm/drm.c 2023-06-02 16:54:50.162022607 +0800
|
||||
@@ -65,8 +65,56 @@
|
||||
#include "linux-dmabuf.h"
|
||||
#include "linux-dmabuf-unstable-v1-server-protocol.h"
|
||||
#include "linux-explicit-synchronization.h"
|
||||
+#include <libweston/config-parser.h>
|
||||
|
||||
static const char default_seat[] = "seat0";
|
||||
+static inline bool
|
||||
+drm_head_is_external(struct drm_head *head)
|
||||
+{
|
||||
+ drmModeConnector *conn = head->connector.conn;
|
||||
+ switch (conn->connector_type) {
|
||||
+ case DRM_MODE_CONNECTOR_LVDS:
|
||||
+ case DRM_MODE_CONNECTOR_eDP:
|
||||
+ case DRM_MODE_CONNECTOR_DSI:
|
||||
+ return false;
|
||||
+ default:
|
||||
+ return true;
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+
|
||||
+static void
|
||||
+drm_backend_update_outputs(struct drm_backend *b)
|
||||
+{
|
||||
+ struct weston_output *primary;
|
||||
+ struct weston_output *output;
|
||||
+ int x, y, next_x, next_y;
|
||||
+ next_x = next_y = 0;
|
||||
+ if (!b->primary_head)
|
||||
+ return;
|
||||
+
|
||||
+ primary = b->primary_head->base.output;
|
||||
+ if (!primary)
|
||||
+ return;
|
||||
+
|
||||
+ /* Move primary output to (0,0) */
|
||||
+ wl_list_remove(&primary->link);
|
||||
+ wl_list_insert(&b->compositor->output_list, &primary->link);
|
||||
+
|
||||
+ wl_list_for_each(output, &b->compositor->output_list, link) {
|
||||
+ if (output->destroying)
|
||||
+ continue;
|
||||
+
|
||||
+ x = next_x;
|
||||
+ y = next_y;
|
||||
+ next_x += output->width;
|
||||
+ weston_output_move(output, x, y);
|
||||
+ }
|
||||
+
|
||||
+ weston_compositor_damage_all(b->compositor);
|
||||
+}
|
||||
+
|
||||
+
|
||||
|
||||
static void
|
||||
drm_backend_create_faked_zpos(struct drm_backend *b)
|
||||
@@ -458,10 +506,13 @@ drm_output_repaint(struct weston_output
|
||||
pixman_region32_t *damage,
|
||||
void *repaint_data)
|
||||
{
|
||||
+ struct drm_backend *b = to_drm_backend(output_base->compositor);
|
||||
struct drm_pending_state *pending_state = repaint_data;
|
||||
struct drm_output *output = to_drm_output(output_base);
|
||||
struct drm_output_state *state = NULL;
|
||||
struct drm_plane_state *scanout_state;
|
||||
+ struct timespec now;
|
||||
+ int64_t now_ms;
|
||||
|
||||
assert(!output->virtual);
|
||||
|
||||
@@ -470,6 +521,20 @@ drm_output_repaint(struct weston_output
|
||||
|
||||
assert(!output->state_last);
|
||||
|
||||
+ weston_compositor_read_presentation_clock(b->compositor, &now);
|
||||
+ now_ms = timespec_to_msec(&now);
|
||||
+ if (now_ms < b->last_resize_ms + DRM_RESIZE_FREEZE_MS) {
|
||||
+ /* Resize fullscreen/maxmium views(not always success) */
|
||||
+ if (now_ms < b->last_resize_ms + DRM_RESIZE_FREEZE_MS)
|
||||
+ wl_signal_emit(&b->compositor->output_resized_signal,
|
||||
+ output);
|
||||
+
|
||||
+ weston_output_damage(output_base);
|
||||
+ weston_output_finish_frame(output_base, NULL,
|
||||
+ WP_PRESENTATION_FEEDBACK_INVALID);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
/* If planes have been disabled in the core, we might not have
|
||||
* hit assign_planes at all, so might not have valid output state
|
||||
* here. */
|
||||
@@ -716,6 +781,7 @@ drm_output_switch_mode(struct weston_out
|
||||
* content.
|
||||
*/
|
||||
b->state_invalid = true;
|
||||
+ output->state_invalid = true;
|
||||
|
||||
if (b->use_pixman) {
|
||||
drm_output_fini_pixman(output);
|
||||
@@ -1253,6 +1319,7 @@ drm_output_attach_head(struct weston_out
|
||||
struct weston_head *head_base)
|
||||
{
|
||||
struct drm_backend *b = to_drm_backend(output_base->compositor);
|
||||
+ struct drm_output *output = to_drm_output(output_base);
|
||||
|
||||
if (wl_list_length(&output_base->head_list) >= MAX_CLONED_CONNECTORS)
|
||||
return -1;
|
||||
@@ -1270,6 +1337,7 @@ drm_output_attach_head(struct weston_out
|
||||
* will not clear the flag before this output is updated?
|
||||
*/
|
||||
b->state_invalid = true;
|
||||
+ output->state_invalid = true;
|
||||
|
||||
weston_output_schedule_repaint(output_base);
|
||||
|
||||
@@ -1281,6 +1349,7 @@ drm_output_detach_head(struct weston_out
|
||||
struct weston_head *head_base)
|
||||
{
|
||||
struct drm_backend *b = to_drm_backend(output_base->compositor);
|
||||
+ struct drm_output *output = to_drm_output(output_base);
|
||||
|
||||
if (!output_base->enabled)
|
||||
return;
|
||||
@@ -1289,6 +1358,7 @@ drm_output_detach_head(struct weston_out
|
||||
* be driven. */
|
||||
/* XXX: Ideally we'd do this per-output, not globally. */
|
||||
b->state_invalid = true;
|
||||
+ output->state_invalid = true;
|
||||
|
||||
weston_output_schedule_repaint(output_base);
|
||||
}
|
||||
@@ -1777,6 +1847,8 @@ drm_output_detach_crtc(struct drm_output
|
||||
|
||||
/* Force resetting unused CRTCs */
|
||||
b->state_invalid = true;
|
||||
+ output->state_invalid = true;
|
||||
+
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -1820,6 +1892,8 @@ drm_output_enable(struct weston_output *
|
||||
output->base.set_dpms = drm_set_dpms;
|
||||
output->base.switch_mode = drm_output_switch_mode;
|
||||
output->base.set_gamma = drm_output_set_gamma;
|
||||
+ output->state_invalid = true;
|
||||
+
|
||||
|
||||
weston_log("Output %s (crtc %d) video modes:\n",
|
||||
output->base.name, output->crtc->crtc_id);
|
||||
@@ -2155,8 +2229,7 @@ drm_head_create(struct drm_backend *back
|
||||
|
||||
head->backlight = backlight_init(drm_device, conn->connector_type);
|
||||
|
||||
- if (conn->connector_type == DRM_MODE_CONNECTOR_LVDS ||
|
||||
- conn->connector_type == DRM_MODE_CONNECTOR_eDP)
|
||||
+ if (!drm_head_is_external(head))
|
||||
weston_head_set_internal(&head->base);
|
||||
|
||||
if (drm_head_read_current_setup(head, backend) < 0) {
|
||||
@@ -2317,43 +2390,6 @@ drm_backend_add_connector(struct drm_bac
|
||||
return ret;
|
||||
}
|
||||
|
||||
-/** Find all connectors of the fd and create drm_head or drm_writeback objects
|
||||
- * (depending on the type of connector they are) for each of them
|
||||
- *
|
||||
- * These objects are added to the DRM-backend lists of heads and writebacks.
|
||||
- *
|
||||
- * @param b The DRM-backend structure
|
||||
- * @param drm_device udev device pointer
|
||||
- * @param resources The DRM resources, it is taken with drmModeGetResources
|
||||
- * @return 0 on success, -1 on failure
|
||||
- */
|
||||
-static int
|
||||
-drm_backend_discover_connectors(struct drm_backend *b, struct udev_device *drm_device,
|
||||
- drmModeRes *resources)
|
||||
-{
|
||||
- drmModeConnector *conn;
|
||||
- int i, ret;
|
||||
-
|
||||
- b->min_width = resources->min_width;
|
||||
- b->max_width = resources->max_width;
|
||||
- b->min_height = resources->min_height;
|
||||
- b->max_height = resources->max_height;
|
||||
-
|
||||
- for (i = 0; i < resources->count_connectors; i++) {
|
||||
- uint32_t connector_id = resources->connectors[i];
|
||||
-
|
||||
- conn = drmModeGetConnector(b->drm.fd, connector_id);
|
||||
- if (!conn)
|
||||
- continue;
|
||||
-
|
||||
- ret = drm_backend_add_connector(b, conn, drm_device);
|
||||
- if (ret < 0)
|
||||
- drmModeFreeConnector(conn);
|
||||
- }
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
static bool
|
||||
resources_has_connector(drmModeRes *resources, uint32_t connector_id)
|
||||
{
|
||||
@@ -2365,22 +2401,56 @@ resources_has_connector(drmModeRes *reso
|
||||
return false;
|
||||
}
|
||||
|
||||
-static void
|
||||
+/* based on compositor/main.c#drm_head_prepare_enable() */
|
||||
+static bool
|
||||
+drm_head_is_available(struct weston_head *head)
|
||||
+{
|
||||
+ struct weston_config_section *section;
|
||||
+ char *mode = NULL;
|
||||
+ section = head->section;
|
||||
+ if (!section)
|
||||
+ return true;
|
||||
+
|
||||
+ /* skip outputs that are explicitly off, or non-desktop and not
|
||||
+ * explicitly enabled.
|
||||
+ */
|
||||
+ weston_config_section_get_string(section, "mode", &mode, NULL);
|
||||
+ if (mode && strcmp(mode, "off") == 0) {
|
||||
+ free(mode);
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ if (!mode && weston_head_is_non_desktop(head))
|
||||
+ return false;
|
||||
+
|
||||
+ free(mode);
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static int
|
||||
drm_backend_update_connectors(struct drm_backend *b, struct udev_device *drm_device)
|
||||
{
|
||||
drmModeRes *resources;
|
||||
drmModeConnector *conn;
|
||||
struct weston_head *base, *base_next;
|
||||
- struct drm_head *head;
|
||||
+ struct drm_head *head, *old_primary_head;
|
||||
struct drm_writeback *writeback, *writeback_next;
|
||||
+ drm_head_match_t *match = b->head_matches;
|
||||
+ struct timespec now;
|
||||
uint32_t connector_id;
|
||||
int i, ret;
|
||||
|
||||
resources = drmModeGetResources(b->drm.fd);
|
||||
if (!resources) {
|
||||
weston_log("drmModeGetResources failed\n");
|
||||
- return;
|
||||
+ return -1;
|
||||
}
|
||||
+
|
||||
+ b->min_width = resources->min_width;
|
||||
+ b->max_width = resources->max_width;
|
||||
+ b->min_height = resources->min_height;
|
||||
+ b->max_height = resources->max_height;
|
||||
|
||||
/* collect new connectors that have appeared, e.g. MST */
|
||||
for (i = 0; i < resources->count_connectors; i++) {
|
||||
@@ -2438,6 +2508,50 @@ drm_backend_update_connectors(struct drm
|
||||
}
|
||||
|
||||
drmModeFreeResources(resources);
|
||||
+
|
||||
+ old_primary_head = b->primary_head;
|
||||
+ b->primary_head = NULL;
|
||||
+
|
||||
+ wl_list_for_each_safe(base, base_next,
|
||||
+ &b->compositor->head_list, compositor_link)
|
||||
+ weston_head_set_connection_status(base, false);
|
||||
+
|
||||
+ /* Re-connect matched heads and find primary head */
|
||||
+ while (*match) {
|
||||
+ wl_list_for_each_safe(base, base_next,
|
||||
+ &b->compositor->head_list,
|
||||
+ compositor_link) {
|
||||
+ drmModeConnector *conn;
|
||||
+
|
||||
+ if (!drm_head_is_available(base))
|
||||
+ continue;
|
||||
+
|
||||
+ head = to_drm_head(base);
|
||||
+ conn = head->connector.conn;
|
||||
+
|
||||
+ if (conn->connection != DRM_MODE_CONNECTED ||
|
||||
+ !(*match)(b, head))
|
||||
+ continue;
|
||||
+
|
||||
+ weston_head_set_connection_status(base, true);
|
||||
+
|
||||
+ if (!b->primary_head) {
|
||||
+ b->primary_head = head;
|
||||
+ }
|
||||
+ }
|
||||
+ match++;
|
||||
+ }
|
||||
+ drm_backend_update_outputs(b);
|
||||
+
|
||||
+ weston_compositor_read_presentation_clock(b->compositor, &now);
|
||||
+ b->last_update_ms = timespec_to_msec(&now);
|
||||
+
|
||||
+ /* Assume primary output's size changed */
|
||||
+ if (b->primary_head && old_primary_head &&
|
||||
+ b->primary_head != old_primary_head)
|
||||
+ b->last_resize_ms = b->last_update_ms;
|
||||
+
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static enum wdrm_connector_property
|
||||
@@ -2528,6 +2642,7 @@ udev_event_is_conn_prop_change(struct dr
|
||||
return 1;
|
||||
}
|
||||
|
||||
+
|
||||
static int
|
||||
udev_drm_event(int fd, uint32_t mask, void *data)
|
||||
{
|
||||
@@ -2542,6 +2657,7 @@ udev_drm_event(int fd, uint32_t mask, vo
|
||||
drm_backend_update_conn_props(b, conn_id, prop_id);
|
||||
else
|
||||
drm_backend_update_connectors(b, event);
|
||||
+
|
||||
}
|
||||
|
||||
udev_device_unref(event);
|
||||
@@ -2609,6 +2725,8 @@ session_notify(struct wl_listener *liste
|
||||
weston_compositor_wake(compositor);
|
||||
weston_compositor_damage_all(compositor);
|
||||
b->state_invalid = true;
|
||||
+ wl_list_for_each(output, &compositor->output_list, base.link)
|
||||
+ output->state_invalid = true;
|
||||
udev_input_enable(&b->input);
|
||||
} else {
|
||||
weston_log("deactivating session\n");
|
||||
@@ -2969,6 +3087,14 @@ recorder_binding(struct weston_keyboard
|
||||
}
|
||||
#endif
|
||||
|
||||
+static void
|
||||
+output_create_notify(struct wl_listener *listener, void *data)
|
||||
+{
|
||||
+ struct drm_backend *b = container_of(listener, struct drm_backend,
|
||||
+ output_create_listener);
|
||||
+
|
||||
+ drm_backend_update_outputs(b);
|
||||
+}
|
||||
|
||||
static const struct weston_drm_output_api api = {
|
||||
drm_output_set_mode,
|
||||
@@ -2976,6 +3102,46 @@ static const struct weston_drm_output_ap
|
||||
drm_output_set_seat,
|
||||
};
|
||||
|
||||
+enum drm_head_mode {
|
||||
+ DRM_HEAD_MODE_DEFAULT,
|
||||
+ DRM_HEAD_MODE_PRIMARY,
|
||||
+
|
||||
+};
|
||||
+
|
||||
+static bool
|
||||
+drm_head_match_primary(struct drm_backend *b, struct drm_head *head)
|
||||
+{
|
||||
+ const char *buf = getenv("WESTON_SET_PRIMARY");
|
||||
+ return buf && !strcmp(buf, head->base.name);
|
||||
+}
|
||||
+
|
||||
+static bool
|
||||
+drm_head_match_external(struct drm_backend *b, struct drm_head *head)
|
||||
+{
|
||||
+ return drm_head_is_external(head);
|
||||
+}
|
||||
+
|
||||
+static bool
|
||||
+drm_head_match_internal(struct drm_backend *b, struct drm_head *head)
|
||||
+{
|
||||
+ return !drm_head_is_external(head);
|
||||
+}
|
||||
+
|
||||
+#define DRM_HEAD_MAX_MATCHES 5
|
||||
+static drm_head_match_t drm_head_matches[][DRM_HEAD_MAX_MATCHES] = {
|
||||
+ [DRM_HEAD_MODE_DEFAULT] = {
|
||||
+ drm_head_match_primary,
|
||||
+ drm_head_match_internal,
|
||||
+ drm_head_match_external,
|
||||
+ NULL,
|
||||
+ },
|
||||
+ [DRM_HEAD_MODE_PRIMARY] = {
|
||||
+ drm_head_match_primary,
|
||||
+ NULL,
|
||||
+ },
|
||||
+
|
||||
+};
|
||||
+
|
||||
static struct drm_backend *
|
||||
drm_backend_create(struct weston_compositor *compositor,
|
||||
struct weston_drm_backend_config *config)
|
||||
@@ -2986,6 +3152,7 @@ drm_backend_create(struct weston_composi
|
||||
const char *seat_id = default_seat;
|
||||
const char *session_seat;
|
||||
struct weston_drm_format_array *scanout_formats;
|
||||
+ enum drm_head_mode head_mode = DRM_HEAD_MODE_DEFAULT;
|
||||
drmModeRes *res;
|
||||
int ret;
|
||||
|
||||
@@ -3002,6 +3169,9 @@ drm_backend_create(struct weston_composi
|
||||
if (b == NULL)
|
||||
return NULL;
|
||||
|
||||
+
|
||||
+ b->head_matches = drm_head_matches[head_mode];
|
||||
+
|
||||
b->state_invalid = true;
|
||||
b->drm.fd = -1;
|
||||
|
||||
@@ -3097,7 +3267,7 @@ drm_backend_create(struct weston_composi
|
||||
}
|
||||
|
||||
wl_list_init(&b->writeback_connector_list);
|
||||
- if (drm_backend_discover_connectors(b, drm_device, res) < 0) {
|
||||
+ if (drm_backend_update_connectors(b, drm_device) < 0) {
|
||||
weston_log("Failed to create heads for %s\n", b->drm.filename);
|
||||
goto err_udev_input;
|
||||
}
|
||||
@@ -3135,6 +3305,9 @@ drm_backend_create(struct weston_composi
|
||||
}
|
||||
|
||||
udev_device_unref(drm_device);
|
||||
+ b->output_create_listener.notify = output_create_notify;
|
||||
+ wl_signal_add(&b->compositor->output_created_signal,
|
||||
+ &b->output_create_listener);
|
||||
|
||||
weston_compositor_add_debug_binding(compositor, KEY_O,
|
||||
planes_binding, b);
|
||||
@@ -3196,7 +3369,7 @@ drm_backend_create(struct weston_composi
|
||||
weston_log("Failed to register virtual output API.\n");
|
||||
goto err_udev_monitor;
|
||||
}
|
||||
-
|
||||
+
|
||||
return b;
|
||||
|
||||
err_udev_monitor:
|
||||
--- a/libweston/backend-drm/drm-internal.h 2023-06-02 13:52:25.549476228 +0800
|
||||
+++ b/libweston/backend-drm/drm-internal.h 2023-06-02 16:54:50.162022607 +0800
|
||||
@@ -109,7 +109,11 @@
|
||||
weston_log_scope_printf((b)->debug, __VA_ARGS__)
|
||||
|
||||
#define MAX_CLONED_CONNECTORS 4
|
||||
+#define DRM_RESIZE_FREEZE_MS 600
|
||||
|
||||
+struct drm_head;
|
||||
+struct drm_backend;
|
||||
+typedef bool (*drm_head_match_t) (struct drm_backend *, struct drm_head *);
|
||||
|
||||
/**
|
||||
* Represents the values of an enum-type KMS property
|
||||
@@ -311,6 +315,17 @@ struct drm_backend {
|
||||
bool fb_modifiers;
|
||||
|
||||
struct weston_log_scope *debug;
|
||||
+
|
||||
+ bool pending_update;
|
||||
+ int64_t last_update_ms;
|
||||
+ int64_t last_resize_ms;
|
||||
+
|
||||
+ bool single_head;
|
||||
+ bool head_fallback;
|
||||
+ bool head_fallback_all;
|
||||
+ drm_head_match_t *head_matches;
|
||||
+ struct drm_head *primary_head;
|
||||
+ struct wl_listener output_create_listener;
|
||||
};
|
||||
|
||||
struct drm_mode {
|
||||
@@ -574,6 +589,7 @@ struct drm_output {
|
||||
bool virtual;
|
||||
|
||||
submit_frame_cb virtual_submit_frame;
|
||||
+ bool state_invalid;
|
||||
};
|
||||
|
||||
static inline struct drm_head *
|
||||
--- a/libweston/compositor.c 2023-06-02 13:52:25.553476246 +0800
|
||||
+++ b/libweston/compositor.c 2023-06-02 16:54:50.162022607 +0800
|
||||
@@ -101,6 +101,8 @@ weston_compositor_build_view_list(struct
|
||||
static char *
|
||||
weston_output_create_heads_string(struct weston_output *output);
|
||||
|
||||
+static struct weston_layer *get_view_layer(struct weston_view *view);
|
||||
+
|
||||
static struct weston_paint_node *
|
||||
weston_paint_node_create(struct weston_surface *surface,
|
||||
struct weston_view *view,
|
||||
@@ -157,6 +159,26 @@ weston_paint_node_destroy(struct weston_
|
||||
free(pnode);
|
||||
}
|
||||
|
||||
+
|
||||
+
|
||||
+
|
||||
+
|
||||
+static bool
|
||||
+weston_compositor_is_static_layer(struct weston_layer *layer)
|
||||
+{
|
||||
+ if (!layer)
|
||||
+ return false;
|
||||
+
|
||||
+ switch (layer->position) {
|
||||
+ case WESTON_LAYER_POSITION_BACKGROUND:
|
||||
+ case WESTON_LAYER_POSITION_UI:
|
||||
+ case WESTON_LAYER_POSITION_FADE:
|
||||
+ return true;
|
||||
+ default:
|
||||
+ return false;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/** Send wl_output events for mode and scale changes
|
||||
*
|
||||
* \param head Send on all resources bound to this head.
|
||||
@@ -255,10 +277,6 @@ weston_mode_switch_finish(struct weston_
|
||||
mode_changed, scale_changed);
|
||||
}
|
||||
|
||||
-static void
|
||||
-weston_compositor_reflow_outputs(struct weston_compositor *compositor,
|
||||
- struct weston_output *resized_output, int delta_width);
|
||||
-
|
||||
/**
|
||||
* \ingroup output
|
||||
*/
|
||||
@@ -270,7 +288,6 @@ weston_output_mode_set_native(struct wes
|
||||
int ret;
|
||||
int mode_changed = 0, scale_changed = 0;
|
||||
int32_t old_width;
|
||||
-
|
||||
if (!output->switch_mode)
|
||||
return -1;
|
||||
|
||||
@@ -284,7 +301,6 @@ weston_output_mode_set_native(struct wes
|
||||
output->current_scale = scale;
|
||||
}
|
||||
}
|
||||
-
|
||||
old_width = output->width;
|
||||
output->native_mode = mode;
|
||||
output->native_scale = scale;
|
||||
@@ -1375,6 +1391,22 @@ weston_view_assign_output(struct weston_
|
||||
new_output = NULL;
|
||||
max = 0;
|
||||
mask = 0;
|
||||
+
|
||||
+ /* The static views should bind to the specific output */
|
||||
+ if (weston_compositor_is_static_layer(get_view_layer(ev))) {
|
||||
+ struct weston_view *view = ev;
|
||||
+
|
||||
+ while (view && !(output = view->output))
|
||||
+ view = view->geometry.parent;
|
||||
+
|
||||
+ if (output && !output->destroying)
|
||||
+ ev->output_mask |= 1u << output->id;
|
||||
+ else
|
||||
+ weston_view_set_output(ev, NULL);
|
||||
+
|
||||
+ weston_surface_assign_output(ev->surface);
|
||||
+ return;
|
||||
+ }
|
||||
pixman_region32_init(®ion);
|
||||
wl_list_for_each(output, &ec->output_list, link) {
|
||||
if (output->destroying)
|
||||
@@ -2944,12 +2976,13 @@ weston_output_repaint(struct weston_outp
|
||||
if (output->dirty)
|
||||
weston_output_update_matrix(output);
|
||||
|
||||
+ output->repaint_needed = false;
|
||||
r = output->repaint(output, &output_damage, repaint_data);
|
||||
-
|
||||
pixman_region32_fini(&output_damage);
|
||||
|
||||
- output->repaint_needed = false;
|
||||
- if (r == 0)
|
||||
+ if (output->repaint_needed)
|
||||
+ output->repaint_status = REPAINT_SCHEDULED;
|
||||
+ else if (r == 0)
|
||||
output->repaint_status = REPAINT_AWAITING_COMPLETION;
|
||||
|
||||
weston_compositor_repick(ec);
|
||||
@@ -6007,7 +6040,7 @@ weston_head_get_destroy_listener(struct
|
||||
}
|
||||
|
||||
/* Move other outputs when one is resized so the space remains contiguous. */
|
||||
-static void
|
||||
+WL_EXPORT void
|
||||
weston_compositor_reflow_outputs(struct weston_compositor *compositor,
|
||||
struct weston_output *resized_output, int delta_width)
|
||||
{
|
||||
@@ -6371,11 +6404,11 @@ weston_compositor_remove_output(struct w
|
||||
weston_paint_node_destroy(pnode);
|
||||
}
|
||||
assert(wl_list_empty(&output->paint_node_z_order_list));
|
||||
-
|
||||
/*
|
||||
* Use view_list in case the output did not go through repaint
|
||||
* after a view came on it, lacking a paint node. Just to be sure.
|
||||
*/
|
||||
+ weston_compositor_build_view_list(compositor, NULL);
|
||||
wl_list_for_each(view, &compositor->view_list, link) {
|
||||
if (view->output_mask & (1u << output->id))
|
||||
weston_view_assign_output(view);
|
||||
@@ -0,0 +1,510 @@
|
||||
Weston support mirror mode.Use 'export WESTON_ENABLE_MIRROR=1' to enable mirror mode.
|
||||
|
||||
Signed-off-by: Leo Lu <leo.lu@starfivetech.com>
|
||||
|
||||
|
||||
--- a/clients/desktop-shell.c 2023-06-12 20:36:17.698156132 +0800
|
||||
+++ b/clients/desktop-shell.c 2023-06-13 15:21:06.196116306 +0800
|
||||
@@ -1060,9 +1060,14 @@ desktop_shell_configure(void *data,
|
||||
struct wl_surface *surface,
|
||||
int32_t width, int32_t height)
|
||||
{
|
||||
- struct window *window = wl_surface_get_user_data(surface);
|
||||
- struct surface *s = window_get_user_data(window);
|
||||
+ struct window *window;
|
||||
+ struct surface *s;
|
||||
|
||||
+ if (!surface)
|
||||
+ return;
|
||||
+
|
||||
+ window = wl_surface_get_user_data(surface);
|
||||
+ s = window_get_user_data(window);
|
||||
s->configure(data, desktop_shell, edges, window, width, height);
|
||||
}
|
||||
|
||||
--- a/desktop-shell/shell.c 2023-06-12 20:36:17.702156089 +0800
|
||||
+++ b/desktop-shell/shell.c 2023-06-13 15:21:06.208116334 +0800
|
||||
@@ -4263,6 +4263,9 @@ weston_view_set_initial_position(struct
|
||||
}
|
||||
|
||||
wl_list_for_each(output, &compositor->output_list, link) {
|
||||
+ if (output->unavailable)
|
||||
+ continue;
|
||||
+
|
||||
if (pixman_region32_contains_point(&output->region, ix, iy, NULL)) {
|
||||
target_output = output;
|
||||
break;
|
||||
--- a/include/libweston/libweston.h 2023-06-12 20:36:17.702156089 +0800
|
||||
+++ b/include/libweston/libweston.h 2023-06-13 15:21:06.224116373 +0800
|
||||
@@ -411,7 +411,11 @@ struct weston_output {
|
||||
*/
|
||||
void (*detach_head)(struct weston_output *output,
|
||||
struct weston_head *head);
|
||||
+
|
||||
+ bool unavailable;
|
||||
};
|
||||
+#define weston_output_valid(o) \
|
||||
+ ((o) && !(o)->destroying && !(o)->unavailable)
|
||||
|
||||
enum weston_pointer_motion_mask {
|
||||
WESTON_POINTER_MOTION_ABS = 1 << 0,
|
||||
--- a/libweston/backend-drm/drm.c 2023-06-12 20:36:17.706156047 +0800
|
||||
+++ b/libweston/backend-drm/drm.c 2023-06-13 15:21:06.236116402 +0800
|
||||
@@ -67,6 +67,7 @@
|
||||
#include "linux-explicit-synchronization.h"
|
||||
#include <libweston/config-parser.h>
|
||||
|
||||
+
|
||||
static const char default_seat[] = "seat0";
|
||||
static inline bool
|
||||
drm_head_is_external(struct drm_head *head)
|
||||
@@ -86,7 +87,7 @@ drm_head_is_external(struct drm_head *he
|
||||
static void
|
||||
drm_backend_update_outputs(struct drm_backend *b)
|
||||
{
|
||||
- struct weston_output *primary;
|
||||
+ struct weston_output *primary,*base;
|
||||
struct weston_output *output;
|
||||
int x, y, next_x, next_y;
|
||||
next_x = next_y = 0;
|
||||
@@ -94,6 +95,26 @@ drm_backend_update_outputs(struct drm_ba
|
||||
return;
|
||||
|
||||
primary = b->primary_head->base.output;
|
||||
+
|
||||
+ if (b->mirror_mode) {
|
||||
+ wl_list_for_each(base, &b->compositor->output_list, link) {
|
||||
+ struct drm_output *output = to_drm_output(base);
|
||||
+ bool is_mirror = base != primary;
|
||||
+
|
||||
+ if (output->is_mirror == is_mirror)
|
||||
+ continue;
|
||||
+
|
||||
+ /* Make mirrors unavailable for normal views */
|
||||
+ output->base.unavailable = is_mirror;
|
||||
+
|
||||
+ output->is_mirror = is_mirror;
|
||||
+ output->state_invalid = true;
|
||||
+
|
||||
+ weston_log("Output %s changed to %s output\n",
|
||||
+ base->name, is_mirror ? "mirror" : "main");
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
if (!primary)
|
||||
return;
|
||||
|
||||
@@ -394,6 +415,45 @@ drm_output_render_pixman(struct drm_outp
|
||||
return drm_fb_ref(output->dumb[output->current_image]);
|
||||
}
|
||||
|
||||
+static struct drm_fb *
|
||||
+drm_output_get_fb(struct drm_pending_state *pending_state,
|
||||
+ struct weston_output *output_base)
|
||||
+{
|
||||
+ struct drm_output *output = to_drm_output(output_base);
|
||||
+ struct drm_plane_state *scanout_state;
|
||||
+ struct drm_output_state *state;
|
||||
+ struct drm_fb *fb = output->scanout_plane->state_cur->fb;
|
||||
+
|
||||
+ state = drm_pending_state_get_output(pending_state, output);
|
||||
+ if (!state)
|
||||
+ return fb;
|
||||
+
|
||||
+ scanout_state =
|
||||
+ drm_output_state_get_existing_plane(state,
|
||||
+ output->scanout_plane);
|
||||
+ if (!scanout_state || !scanout_state->fb)
|
||||
+ return fb;
|
||||
+
|
||||
+ return scanout_state->fb;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+drm_output_try_destroy_wrap_fb(struct drm_output *output)
|
||||
+{
|
||||
+ if (output->wrap[0]) {
|
||||
+ drm_fb_unref(output->wrap[0]);
|
||||
+ output->wrap[0] = NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (output->wrap[1]) {
|
||||
+ drm_fb_unref(output->wrap[1]);
|
||||
+ output->wrap[1] = NULL;
|
||||
+ }
|
||||
+
|
||||
+ output->next_wrap = 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
void
|
||||
drm_output_render(struct drm_output_state *state, pixman_region32_t *damage)
|
||||
{
|
||||
@@ -404,17 +464,48 @@ drm_output_render(struct drm_output_stat
|
||||
struct drm_property_info *damage_info =
|
||||
&scanout_plane->props[WDRM_PLANE_FB_DAMAGE_CLIPS];
|
||||
struct drm_backend *b = to_drm_backend(c);
|
||||
- struct drm_fb *fb;
|
||||
+ struct drm_mode *mode;
|
||||
+ struct drm_fb *fb = NULL;
|
||||
pixman_region32_t scanout_damage;
|
||||
pixman_box32_t *rects;
|
||||
int n_rects;
|
||||
-
|
||||
+ int sw, sh, dx, dy, dw, dh;
|
||||
+ float scale_rate ;
|
||||
+ int scale_w , scale_h;
|
||||
/* If we already have a client buffer promoted to scanout, then we don't
|
||||
* want to render. */
|
||||
scanout_state = drm_output_state_get_plane(state, scanout_plane);
|
||||
if (scanout_state->fb)
|
||||
return;
|
||||
|
||||
+ if (!output->is_mirror) {
|
||||
+ struct drm_output *tmp;
|
||||
+
|
||||
+ /* Repaint all mirrors when updating main output */
|
||||
+ wl_list_for_each(tmp, &b->compositor->output_list, base.link)
|
||||
+ if (tmp->is_mirror)
|
||||
+ weston_output_schedule_repaint(&tmp->base);
|
||||
+ } else {
|
||||
+ if (!b->primary_head)
|
||||
+ goto out;
|
||||
+
|
||||
+
|
||||
+ fb = drm_output_get_fb(state->pending_state,
|
||||
+ b->primary_head->base.output);
|
||||
+ if (fb) {
|
||||
+ drm_fb_ref(fb);
|
||||
+
|
||||
+ pixman_region32_init(&scanout_damage);
|
||||
+ wl_signal_emit(&output->base.frame_signal,
|
||||
+ &scanout_damage);
|
||||
+ pixman_region32_fini(&scanout_damage);
|
||||
+ } else {
|
||||
+ weston_compositor_damage_all(b->compositor);
|
||||
+ }
|
||||
+
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
/*
|
||||
* If we don't have any damage on the primary plane, and we already
|
||||
* have a renderer buffer active, we can reuse it; else we pass
|
||||
@@ -433,25 +524,57 @@ drm_output_render(struct drm_output_stat
|
||||
} else {
|
||||
fb = drm_output_render_gl(state, damage);
|
||||
}
|
||||
-
|
||||
+out:
|
||||
if (!fb) {
|
||||
drm_plane_state_put_back(scanout_state);
|
||||
return;
|
||||
}
|
||||
|
||||
+ sw = fb->width;
|
||||
+ sh = fb->height;
|
||||
+
|
||||
+ dx = output->plane_bounds.x1;
|
||||
+ dy = output->plane_bounds.y1;
|
||||
+ dw = output->plane_bounds.x2 - output->plane_bounds.x1;
|
||||
+ dh = output->plane_bounds.y2 - output->plane_bounds.y1;
|
||||
+
|
||||
+ if (!dw || !dh) {
|
||||
+ mode = to_drm_mode(output->base.current_mode);
|
||||
+ dw = mode->mode_info.hdisplay;
|
||||
+ dh = mode->mode_info.vdisplay;
|
||||
+ }
|
||||
+
|
||||
+ if(sw != dw || sh != dh) {
|
||||
+ scale_rate =(float ) sw / (float) sh ;
|
||||
+ scale_h = (float) dw / scale_rate;
|
||||
+ if(scale_h <= dh)
|
||||
+ dh = scale_h;
|
||||
+ else {
|
||||
+ scale_w = dh * scale_rate ;
|
||||
+ if(scale_w <= dw)
|
||||
+ dw = scale_w;
|
||||
+ }
|
||||
+ }
|
||||
+ else {
|
||||
+ dw = sw;
|
||||
+ dh = sh;
|
||||
+ }
|
||||
+
|
||||
scanout_state->fb = fb;
|
||||
scanout_state->output = output;
|
||||
-
|
||||
+ fb = NULL ;
|
||||
scanout_state->src_x = 0;
|
||||
scanout_state->src_y = 0;
|
||||
- scanout_state->src_w = fb->width << 16;
|
||||
- scanout_state->src_h = fb->height << 16;
|
||||
+ scanout_state->src_w = sw << 16;
|
||||
+ scanout_state->src_h = sh << 16;
|
||||
|
||||
- scanout_state->dest_x = 0;
|
||||
- scanout_state->dest_y = 0;
|
||||
- scanout_state->dest_w = output->base.current_mode->width;
|
||||
- scanout_state->dest_h = output->base.current_mode->height;
|
||||
+ scanout_state->dest_x = dx;
|
||||
+ scanout_state->dest_x = dy;
|
||||
+ scanout_state->dest_w = dw;
|
||||
+ scanout_state->dest_h = dh;
|
||||
|
||||
+ if (output->is_mirror)
|
||||
+ return;
|
||||
pixman_region32_subtract(&c->primary_plane.damage,
|
||||
&c->primary_plane.damage, damage);
|
||||
|
||||
@@ -499,6 +622,7 @@ drm_output_render(struct drm_output_stat
|
||||
&scanout_state->damage_blob_id);
|
||||
|
||||
pixman_region32_fini(&scanout_damage);
|
||||
+
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -1275,8 +1399,8 @@ drm_output_fini_pixman(struct drm_output
|
||||
/* Destroying the Pixman surface will destroy all our buffers,
|
||||
* regardless of refcount. Ensure we destroy them here. */
|
||||
if (!b->shutting_down &&
|
||||
- output->scanout_plane->state_cur->fb &&
|
||||
- output->scanout_plane->state_cur->fb->type == BUFFER_PIXMAN_DUMB) {
|
||||
+ output->scanout_plane->state_cur->fb && (output->is_mirror ||
|
||||
+ output->scanout_plane->state_cur->fb->type == BUFFER_PIXMAN_DUMB)) {
|
||||
drm_plane_reset_state(output->scanout_plane);
|
||||
}
|
||||
|
||||
@@ -1955,6 +2079,8 @@ drm_output_destroy(struct weston_output
|
||||
assert(!output->state_last);
|
||||
drm_output_state_free(output->state_cur);
|
||||
|
||||
+ drm_output_try_destroy_wrap_fb(output);
|
||||
+
|
||||
free(output);
|
||||
}
|
||||
|
||||
@@ -3155,6 +3281,7 @@ drm_backend_create(struct weston_composi
|
||||
enum drm_head_mode head_mode = DRM_HEAD_MODE_DEFAULT;
|
||||
drmModeRes *res;
|
||||
int ret;
|
||||
+ char * buf;
|
||||
|
||||
session_seat = getenv("XDG_SEAT");
|
||||
if (session_seat)
|
||||
@@ -3172,6 +3299,13 @@ drm_backend_create(struct weston_composi
|
||||
|
||||
b->head_matches = drm_head_matches[head_mode];
|
||||
|
||||
+ buf = getenv("WESTON_ENABLE_MIRROR");
|
||||
+ if (buf && buf[0] == '1') {
|
||||
+ b->mirror_mode = true;
|
||||
+ weston_log("Entering mirror mode.\n");
|
||||
+ }
|
||||
+
|
||||
+
|
||||
b->state_invalid = true;
|
||||
b->drm.fd = -1;
|
||||
|
||||
@@ -3183,7 +3317,7 @@ drm_backend_create(struct weston_composi
|
||||
b->debug = weston_compositor_add_log_scope(compositor, "drm-backend",
|
||||
"Debug messages from DRM/KMS backend\n",
|
||||
NULL, NULL, NULL);
|
||||
-
|
||||
+
|
||||
compositor->backend = &b->base;
|
||||
|
||||
if (parse_gbm_format(config->gbm_format, DRM_FORMAT_XRGB8888, &b->gbm_format) < 0)
|
||||
--- a/libweston/backend-drm/drm-gbm.c 2023-06-12 20:36:17.706156047 +0800
|
||||
+++ b/libweston/backend-drm/drm-gbm.c 2023-06-13 15:21:06.240116411 +0800
|
||||
@@ -265,8 +265,8 @@ drm_output_fini_egl(struct drm_output *o
|
||||
/* Destroying the GBM surface will destroy all our GBM buffers,
|
||||
* regardless of refcount. Ensure we destroy them here. */
|
||||
if (!b->shutting_down &&
|
||||
- output->scanout_plane->state_cur->fb &&
|
||||
- output->scanout_plane->state_cur->fb->type == BUFFER_GBM_SURFACE) {
|
||||
+ output->scanout_plane->state_cur->fb && (output->is_mirror ||
|
||||
+ output->scanout_plane->state_cur->fb->type == BUFFER_GBM_SURFACE)) {
|
||||
drm_plane_reset_state(output->scanout_plane);
|
||||
}
|
||||
|
||||
--- a/libweston/backend-drm/drm-internal.h 2023-06-12 20:36:17.706156047 +0800
|
||||
+++ b/libweston/backend-drm/drm-internal.h 2023-06-13 15:21:06.240116411 +0800
|
||||
@@ -326,6 +326,8 @@ struct drm_backend {
|
||||
drm_head_match_t *head_matches;
|
||||
struct drm_head *primary_head;
|
||||
struct wl_listener output_create_listener;
|
||||
+
|
||||
+ bool mirror_mode;
|
||||
};
|
||||
|
||||
struct drm_mode {
|
||||
@@ -495,6 +497,7 @@ struct drm_plane {
|
||||
struct wl_list link;
|
||||
|
||||
struct weston_drm_format_array formats;
|
||||
+ bool can_scale;
|
||||
};
|
||||
|
||||
struct drm_connector {
|
||||
@@ -581,6 +584,10 @@ struct drm_output {
|
||||
int current_image;
|
||||
pixman_region32_t previous_damage;
|
||||
|
||||
+ /* Wrap fb for scale/rotate usage */
|
||||
+ struct drm_fb *wrap[2];
|
||||
+ int next_wrap;
|
||||
+
|
||||
struct vaapi_recorder *recorder;
|
||||
struct wl_listener recorder_frame_listener;
|
||||
|
||||
@@ -590,6 +597,10 @@ struct drm_output {
|
||||
|
||||
submit_frame_cb virtual_submit_frame;
|
||||
bool state_invalid;
|
||||
+
|
||||
+ bool is_mirror;
|
||||
+
|
||||
+ pixman_box32_t plane_bounds;
|
||||
};
|
||||
|
||||
static inline struct drm_head *
|
||||
--- a/libweston/backend-drm/state-propose.c 2023-06-12 20:36:17.706156047 +0800
|
||||
+++ b/libweston/backend-drm/state-propose.c 2023-06-13 15:21:06.240116411 +0800
|
||||
@@ -54,6 +54,21 @@ static const char *const drm_output_prop
|
||||
[DRM_OUTPUT_PROPOSE_STATE_PLANES_ONLY] = "plane-only state"
|
||||
};
|
||||
|
||||
+static bool
|
||||
+drm_is_mirroring(struct drm_backend *b)
|
||||
+{
|
||||
+ struct drm_output *tmp;
|
||||
+
|
||||
+ if (!b->mirror_mode)
|
||||
+ return false;
|
||||
+
|
||||
+ wl_list_for_each(tmp, &b->compositor->output_list, base.link)
|
||||
+ if (tmp->is_mirror)
|
||||
+ return true;
|
||||
+
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
static const char *
|
||||
drm_propose_state_mode_to_string(enum drm_output_propose_state_mode mode)
|
||||
{
|
||||
@@ -466,7 +481,7 @@ drm_output_try_view_on_plane(struct drm_
|
||||
|
||||
switch (plane->type) {
|
||||
case WDRM_PLANE_TYPE_CURSOR:
|
||||
- if (b->cursors_are_broken) {
|
||||
+ if (b->cursors_are_broken || drm_is_mirroring(b)) {
|
||||
availability = NO_PLANES_ACCEPTED;
|
||||
goto out;
|
||||
}
|
||||
@@ -1102,7 +1117,10 @@ drm_assign_planes(struct weston_output *
|
||||
drm_debug(b, "\t[repaint] preparing state for output %s (%lu)\n",
|
||||
output_base->name, (unsigned long) output_base->id);
|
||||
|
||||
- if (!b->sprites_are_broken && !output->virtual) {
|
||||
+ /* Force single plane in mirror mode */
|
||||
+ if (drm_is_mirroring(b)) {
|
||||
+ drm_debug(b, "\t[state] no overlay plane in mirror mode\n");
|
||||
+ } else if (!b->sprites_are_broken && !output->virtual) {
|
||||
drm_debug(b, "\t[repaint] trying planes-only build state\n");
|
||||
state = drm_output_propose_state(output_base, pending_state, mode);
|
||||
if (!state) {
|
||||
--- a/libweston/compositor.c 2023-06-12 20:36:17.706156047 +0800
|
||||
+++ b/libweston/compositor.c 2023-06-13 15:21:06.244116421 +0800
|
||||
@@ -1409,7 +1409,7 @@ weston_view_assign_output(struct weston_
|
||||
}
|
||||
pixman_region32_init(®ion);
|
||||
wl_list_for_each(output, &ec->output_list, link) {
|
||||
- if (output->destroying)
|
||||
+ if (!weston_output_valid(output))
|
||||
continue;
|
||||
|
||||
pixman_region32_intersect(®ion, &ev->transform.boundingbox,
|
||||
@@ -5213,6 +5213,9 @@ bind_output(struct wl_client *client,
|
||||
static void
|
||||
weston_head_add_global(struct weston_head *head)
|
||||
{
|
||||
+ if (head->global || !weston_output_valid(head->output))
|
||||
+ return;
|
||||
+
|
||||
head->global = wl_global_create(head->compositor->wl_display,
|
||||
&wl_output_interface, 3,
|
||||
head, bind_output);
|
||||
@@ -5248,6 +5251,15 @@ weston_head_remove_global(struct weston_
|
||||
wl_list_init(&head->xdg_output_resource_list);
|
||||
}
|
||||
|
||||
+static void
|
||||
+weston_head_update_global(struct weston_head *head)
|
||||
+{
|
||||
+ if (weston_output_valid(head->output))
|
||||
+ weston_head_add_global(head);
|
||||
+ else
|
||||
+ weston_head_remove_global(head);
|
||||
+}
|
||||
+
|
||||
/** Get the backing object of wl_output
|
||||
*
|
||||
* \param resource A wl_output protocol object.
|
||||
@@ -6045,12 +6057,18 @@ weston_compositor_reflow_outputs(struct
|
||||
struct weston_output *resized_output, int delta_width)
|
||||
{
|
||||
struct weston_output *output;
|
||||
+ struct weston_head *head;
|
||||
bool start_resizing = false;
|
||||
|
||||
if (!delta_width)
|
||||
return;
|
||||
|
||||
wl_list_for_each(output, &compositor->output_list, link) {
|
||||
+ wl_list_for_each(head, &output->head_list, output_link)
|
||||
+ weston_head_update_global(head);
|
||||
+
|
||||
+ if (!weston_output_valid(output))
|
||||
+ continue;
|
||||
if (output == resized_output) {
|
||||
start_resizing = true;
|
||||
continue;
|
||||
@@ -6265,11 +6283,11 @@ weston_compositor_add_output(struct west
|
||||
wl_list_insert(compositor->output_list.prev, &output->link);
|
||||
output->enabled = true;
|
||||
|
||||
+ wl_signal_emit(&compositor->output_created_signal, output);
|
||||
+
|
||||
wl_list_for_each(head, &output->head_list, output_link)
|
||||
weston_head_add_global(head);
|
||||
|
||||
- wl_signal_emit(&compositor->output_created_signal, output);
|
||||
-
|
||||
/*
|
||||
* Use view_list, as paint nodes have not been created for this
|
||||
* output yet. Any existing view might touch this new output.
|
||||
--- a/libweston/input.c 2023-06-12 20:36:17.706156047 +0800
|
||||
+++ b/libweston/input.c 2023-06-13 15:21:06.244116421 +0800
|
||||
@@ -1688,6 +1688,10 @@ weston_pointer_clamp(struct weston_point
|
||||
wl_list_for_each(output, &ec->output_list, link) {
|
||||
if (pointer->seat->output && pointer->seat->output != output)
|
||||
continue;
|
||||
+
|
||||
+ if (output->unavailable)
|
||||
+ continue;
|
||||
+
|
||||
if (pixman_region32_contains_point(&output->region,
|
||||
x, y, NULL))
|
||||
valid = 1;
|
||||
@@ -1757,6 +1761,9 @@ weston_pointer_handle_output_destroy(str
|
||||
y = wl_fixed_to_int(pointer->y);
|
||||
|
||||
wl_list_for_each(output, &ec->output_list, link) {
|
||||
+ if (output->unavailable)
|
||||
+ continue;
|
||||
+
|
||||
if (pixman_region32_contains_point(&output->region,
|
||||
x, y, NULL))
|
||||
return;
|
||||
Reference in New Issue
Block a user