1*4882a593SmuzhiyunFrom 267f9e075009cac9b4ac4dbd24d0d3cd2621f041 Mon Sep 17 00:00:00 2001 2*4882a593SmuzhiyunFrom: Jeffy Chen <jeffy.chen@rock-chips.com> 3*4882a593SmuzhiyunDate: Fri, 3 Jul 2020 12:37:37 +0800 4*4882a593SmuzhiyunSubject: [PATCH 19/93] backend-drm: Support controlling output dynamically 5*4882a593Smuzhiyun 6*4882a593SmuzhiyunUse config file to set output's rotate/down-scale/size/pos/mode/off/ 7*4882a593Smuzhiyunfreeze/input/display-rectangle and prefer/primary output. 8*4882a593Smuzhiyun 9*4882a593SmuzhiyunDefault config file is "/tmp/.weston_drm.conf", can override with 10*4882a593Smuzhiyun"WESTON_DRM_CONFIG" environment. 11*4882a593Smuzhiyun 12*4882a593SmuzhiyunSupported configs format is "output:<output name>:<config>", for 13*4882a593Smuzhiyunexample: 14*4882a593Smuzhiyunecho "output:DSI-1:off" >> /tmp/.weston_drm.conf 15*4882a593Smuzhiyunecho "output:eDP-1:freeze" >> /tmp/.weston_drm.conf 16*4882a593Smuzhiyunecho "output:all:rotate90" >> /tmp/.weston_drm.conf 17*4882a593Smuzhiyunecho "output:all:rect=<100,20,1636,2068>" >> /tmp/.weston_drm.conf 18*4882a593Smuzhiyunecho "output:HDMI-A-1:mode=800x600" >> /tmp/.weston_drm.conf 19*4882a593Smuzhiyunecho "output:HDMI-A-1:pos=100,200" >> /tmp/.weston_drm.conf 20*4882a593Smuzhiyunecho "output:HDMI-A-1:size=1920x1080" >> /tmp/.weston_drm.conf 21*4882a593Smuzhiyunecho "output:HDMI-A-1:prefer" >> /tmp/.weston_drm.conf 22*4882a593Smuzhiyunecho "output:HDMI-A-1:primary" >> /tmp/.weston_drm.conf 23*4882a593Smuzhiyunecho "output:HDMI-A-1:down-scale=0.5" >> /tmp/.weston_drm.conf 24*4882a593Smuzhiyunecho "output:HDMI-A-1:input=*" >> /tmp/.weston_drm.conf 25*4882a593Smuzhiyunecho "output:HDMI-A-1:input=" >> /tmp/.weston_drm.conf 26*4882a593Smuzhiyunecho "output:HDMI-A-1:input=event6" >> /tmp/.weston_drm.conf 27*4882a593Smuzhiyunecho "output:HDMI-A-1:input=goodix*" >> /tmp/.weston_drm.conf 28*4882a593Smuzhiyunecho "output:HDMI-A-1:input=goodix-ts" >> /tmp/.weston_drm.conf 29*4882a593Smuzhiyun 30*4882a593SmuzhiyunSigned-off-by: Jeffy Chen <jeffy.chen@rock-chips.com> 31*4882a593Smuzhiyun--- 32*4882a593Smuzhiyun compositor/main.c | 14 ++ 33*4882a593Smuzhiyun desktop-shell/shell.c | 58 +++++- 34*4882a593Smuzhiyun include/libweston/libweston.h | 7 + 35*4882a593Smuzhiyun libweston/backend-drm/drm-internal.h | 16 ++ 36*4882a593Smuzhiyun libweston/backend-drm/drm.c | 265 ++++++++++++++++++++++++++- 37*4882a593Smuzhiyun libweston/backend-drm/modes.c | 20 +- 38*4882a593Smuzhiyun libweston/compositor.c | 30 ++- 39*4882a593Smuzhiyun libweston/libinput-seat.c | 43 +++++ 40*4882a593Smuzhiyun libweston/libweston-internal.h | 3 + 41*4882a593Smuzhiyun libweston/pixman-renderer.c | 3 + 42*4882a593Smuzhiyun libweston/renderer-gl/gl-renderer.c | 4 + 43*4882a593Smuzhiyun 11 files changed, 437 insertions(+), 26 deletions(-) 44*4882a593Smuzhiyun 45*4882a593Smuzhiyundiff --git a/compositor/main.c b/compositor/main.c 46*4882a593Smuzhiyunindex dcfe85b..d65f8aa 100644 47*4882a593Smuzhiyun--- a/compositor/main.c 48*4882a593Smuzhiyun+++ b/compositor/main.c 49*4882a593Smuzhiyun@@ -2080,6 +2080,20 @@ drm_backend_output_configure(struct weston_output *output, 50*4882a593Smuzhiyun } 51*4882a593Smuzhiyun free(s); 52*4882a593Smuzhiyun 53*4882a593Smuzhiyun+ weston_config_section_get_string(section, "pos", &s, NULL); 54*4882a593Smuzhiyun+ if (s) { 55*4882a593Smuzhiyun+ if (sscanf(s, "%d,%d", &output->x, &output->y) == 2) 56*4882a593Smuzhiyun+ output->fixed_position = true; 57*4882a593Smuzhiyun+ free(s); 58*4882a593Smuzhiyun+ } 59*4882a593Smuzhiyun+ 60*4882a593Smuzhiyun+ weston_config_section_get_string(section, "size", &s, NULL); 61*4882a593Smuzhiyun+ if (s) { 62*4882a593Smuzhiyun+ if (sscanf(s, "%dx%d", &output->width, &output->height) == 2) 63*4882a593Smuzhiyun+ output->fixed_size = true; 64*4882a593Smuzhiyun+ free(s); 65*4882a593Smuzhiyun+ } 66*4882a593Smuzhiyun+ 67*4882a593Smuzhiyun if (api->set_mode(output, mode, modeline) < 0) { 68*4882a593Smuzhiyun weston_log("Cannot configure an output using weston_drm_output_api.\n"); 69*4882a593Smuzhiyun free(modeline); 70*4882a593Smuzhiyundiff --git a/desktop-shell/shell.c b/desktop-shell/shell.c 71*4882a593Smuzhiyunindex 7aa787c..be36b70 100644 72*4882a593Smuzhiyun--- a/desktop-shell/shell.c 73*4882a593Smuzhiyun+++ b/desktop-shell/shell.c 74*4882a593Smuzhiyun@@ -3831,7 +3831,7 @@ weston_view_set_initial_position(struct weston_view *view, 75*4882a593Smuzhiyun int ix = 0, iy = 0; 76*4882a593Smuzhiyun int32_t range_x, range_y; 77*4882a593Smuzhiyun int32_t x, y; 78*4882a593Smuzhiyun- struct weston_output *output, *target_output = NULL; 79*4882a593Smuzhiyun+ struct weston_output *output, *target_output = NULL, *prefer_output = NULL; 80*4882a593Smuzhiyun struct weston_seat *seat; 81*4882a593Smuzhiyun pixman_rectangle32_t area; 82*4882a593Smuzhiyun 83*4882a593Smuzhiyun@@ -3856,16 +3856,20 @@ weston_view_set_initial_position(struct weston_view *view, 84*4882a593Smuzhiyun } 85*4882a593Smuzhiyun } 86*4882a593Smuzhiyun 87*4882a593Smuzhiyun- wl_list_for_each(output, &compositor->output_list, link) { 88*4882a593Smuzhiyun+ wl_list_for_each_reverse(output, &compositor->output_list, link) { 89*4882a593Smuzhiyun if (output->unavailable) 90*4882a593Smuzhiyun continue; 91*4882a593Smuzhiyun 92*4882a593Smuzhiyun- if (pixman_region32_contains_point(&output->region, ix, iy, NULL)) { 93*4882a593Smuzhiyun+ if (output == compositor->prefer_output) 94*4882a593Smuzhiyun+ prefer_output = output; 95*4882a593Smuzhiyun+ 96*4882a593Smuzhiyun+ if (pixman_region32_contains_point(&output->region, ix, iy, NULL)) 97*4882a593Smuzhiyun target_output = output; 98*4882a593Smuzhiyun- break; 99*4882a593Smuzhiyun- } 100*4882a593Smuzhiyun } 101*4882a593Smuzhiyun 102*4882a593Smuzhiyun+ if (prefer_output) 103*4882a593Smuzhiyun+ target_output = prefer_output; 104*4882a593Smuzhiyun+ 105*4882a593Smuzhiyun if (!target_output) { 106*4882a593Smuzhiyun weston_view_set_position(view, 10 + random() % 400, 107*4882a593Smuzhiyun 10 + random() % 400); 108*4882a593Smuzhiyun@@ -4382,6 +4386,41 @@ shell_resize_surface_to_output(struct desktop_shell *shell, 109*4882a593Smuzhiyun output->height); 110*4882a593Smuzhiyun } 111*4882a593Smuzhiyun 112*4882a593Smuzhiyun+static void 113*4882a593Smuzhiyun+handle_output_resize_layer(struct desktop_shell *shell, 114*4882a593Smuzhiyun+ struct weston_layer *layer, void *data) 115*4882a593Smuzhiyun+{ 116*4882a593Smuzhiyun+ struct weston_output *output = data; 117*4882a593Smuzhiyun+ struct weston_view *view; 118*4882a593Smuzhiyun+ 119*4882a593Smuzhiyun+ wl_list_for_each(view, &layer->view_list.link, layer_link.link) { 120*4882a593Smuzhiyun+ struct weston_desktop_surface *desktop_surface; 121*4882a593Smuzhiyun+ struct shell_surface *shsurf; 122*4882a593Smuzhiyun+ bool dirty = false; 123*4882a593Smuzhiyun+ 124*4882a593Smuzhiyun+ if (view->output != output) 125*4882a593Smuzhiyun+ continue; 126*4882a593Smuzhiyun+ 127*4882a593Smuzhiyun+ shsurf = get_shell_surface(view->surface); 128*4882a593Smuzhiyun+ if (!shsurf) 129*4882a593Smuzhiyun+ continue; 130*4882a593Smuzhiyun+ 131*4882a593Smuzhiyun+ desktop_surface = shsurf->desktop_surface; 132*4882a593Smuzhiyun+ if (weston_desktop_surface_get_fullscreen(desktop_surface)) { 133*4882a593Smuzhiyun+ set_fullscreen(shsurf, true, output); 134*4882a593Smuzhiyun+ dirty = true; 135*4882a593Smuzhiyun+ } 136*4882a593Smuzhiyun+ if (weston_desktop_surface_get_maximized(desktop_surface)) { 137*4882a593Smuzhiyun+ set_maximized(shsurf, true); 138*4882a593Smuzhiyun+ dirty = true; 139*4882a593Smuzhiyun+ } 140*4882a593Smuzhiyun+ 141*4882a593Smuzhiyun+ if (dirty) { 142*4882a593Smuzhiyun+ weston_view_geometry_dirty(view); 143*4882a593Smuzhiyun+ weston_surface_damage(view->surface); 144*4882a593Smuzhiyun+ } 145*4882a593Smuzhiyun+ } 146*4882a593Smuzhiyun+} 147*4882a593Smuzhiyun 148*4882a593Smuzhiyun static void 149*4882a593Smuzhiyun handle_output_resized(struct wl_listener *listener, void *data) 150*4882a593Smuzhiyun@@ -4391,8 +4430,13 @@ handle_output_resized(struct wl_listener *listener, void *data) 151*4882a593Smuzhiyun struct weston_output *output = (struct weston_output *)data; 152*4882a593Smuzhiyun struct shell_output *sh_output = find_shell_output_from_weston_output(shell, output); 153*4882a593Smuzhiyun 154*4882a593Smuzhiyun+ if (shell->lock_surface) 155*4882a593Smuzhiyun+ shell->lock_surface->committed(shell->lock_surface, 0, 0); 156*4882a593Smuzhiyun+ 157*4882a593Smuzhiyun shell_resize_surface_to_output(shell, sh_output->background_surface, output); 158*4882a593Smuzhiyun shell_resize_surface_to_output(shell, sh_output->panel_surface, output); 159*4882a593Smuzhiyun+ 160*4882a593Smuzhiyun+ shell_for_each_layer(shell, handle_output_resize_layer, data); 161*4882a593Smuzhiyun } 162*4882a593Smuzhiyun 163*4882a593Smuzhiyun static void 164*4882a593Smuzhiyun@@ -4441,7 +4485,9 @@ handle_output_move_layer(struct desktop_shell *shell, 165*4882a593Smuzhiyun 166*4882a593Smuzhiyun x = view->geometry.x + output->move_x; 167*4882a593Smuzhiyun y = view->geometry.y + output->move_y; 168*4882a593Smuzhiyun- weston_view_set_position(view, x, y); 169*4882a593Smuzhiyun+ 170*4882a593Smuzhiyun+ if (pixman_region32_contains_point(&output->region, x, y, NULL)) 171*4882a593Smuzhiyun+ weston_view_set_position(view, x, y); 172*4882a593Smuzhiyun } 173*4882a593Smuzhiyun } 174*4882a593Smuzhiyun 175*4882a593Smuzhiyundiff --git a/include/libweston/libweston.h b/include/libweston/libweston.h 176*4882a593Smuzhiyunindex a8ec105..84b16fe 100644 177*4882a593Smuzhiyun--- a/include/libweston/libweston.h 178*4882a593Smuzhiyun+++ b/include/libweston/libweston.h 179*4882a593Smuzhiyun@@ -575,6 +575,12 @@ struct weston_output { 180*4882a593Smuzhiyun struct weston_head *head); 181*4882a593Smuzhiyun 182*4882a593Smuzhiyun bool unavailable; 183*4882a593Smuzhiyun+ bool freezing; 184*4882a593Smuzhiyun+ 185*4882a593Smuzhiyun+ bool fixed_position; 186*4882a593Smuzhiyun+ bool fixed_size; 187*4882a593Smuzhiyun+ 188*4882a593Smuzhiyun+ double down_scale; 189*4882a593Smuzhiyun }; 190*4882a593Smuzhiyun #define weston_output_valid(o) \ 191*4882a593Smuzhiyun ((o) && !(o)->destroying && !(o)->unavailable) 192*4882a593Smuzhiyun@@ -1333,6 +1339,7 @@ struct weston_compositor { 193*4882a593Smuzhiyun bool warned_about_unmapped_surface_or_view; 194*4882a593Smuzhiyun 195*4882a593Smuzhiyun enum weston_output_flow output_flow; 196*4882a593Smuzhiyun+ struct weston_output *prefer_output; 197*4882a593Smuzhiyun }; 198*4882a593Smuzhiyun 199*4882a593Smuzhiyun struct weston_solid_buffer_values { 200*4882a593Smuzhiyundiff --git a/libweston/backend-drm/drm-internal.h b/libweston/backend-drm/drm-internal.h 201*4882a593Smuzhiyunindex 037c937..532593e 100644 202*4882a593Smuzhiyun--- a/libweston/backend-drm/drm-internal.h 203*4882a593Smuzhiyun+++ b/libweston/backend-drm/drm-internal.h 204*4882a593Smuzhiyun@@ -115,6 +115,9 @@ 205*4882a593Smuzhiyun 206*4882a593Smuzhiyun #define DRM_RESIZE_FREEZE_MS 600 207*4882a593Smuzhiyun 208*4882a593Smuzhiyun+#define WESTON_DRM_CONFIG_FILE "/tmp/.weston_drm.conf" 209*4882a593Smuzhiyun+#define DRM_CONFIG_UPDATE_MS 100 210*4882a593Smuzhiyun+ 211*4882a593Smuzhiyun /** 212*4882a593Smuzhiyun * Represents the values of an enum-type KMS property 213*4882a593Smuzhiyun */ 214*4882a593Smuzhiyun@@ -364,6 +367,9 @@ struct drm_backend { 215*4882a593Smuzhiyun int virtual_height; 216*4882a593Smuzhiyun 217*4882a593Smuzhiyun bool mirror_mode; 218*4882a593Smuzhiyun+ 219*4882a593Smuzhiyun+ struct wl_event_source *config_timer; 220*4882a593Smuzhiyun+ struct stat config_stat; 221*4882a593Smuzhiyun }; 222*4882a593Smuzhiyun 223*4882a593Smuzhiyun struct drm_mode { 224*4882a593Smuzhiyun@@ -641,6 +647,9 @@ struct drm_output { 225*4882a593Smuzhiyun bool is_mirror; 226*4882a593Smuzhiyun 227*4882a593Smuzhiyun pixman_box32_t plane_bounds; 228*4882a593Smuzhiyun+ 229*4882a593Smuzhiyun+ uint32_t original_transform; 230*4882a593Smuzhiyun+ int64_t last_resize_ms; 231*4882a593Smuzhiyun }; 232*4882a593Smuzhiyun 233*4882a593Smuzhiyun void 234*4882a593Smuzhiyun@@ -739,6 +748,13 @@ drm_mode_list_destroy(struct drm_device *device, struct wl_list *mode_list); 235*4882a593Smuzhiyun void 236*4882a593Smuzhiyun drm_output_print_modes(struct drm_output *output); 237*4882a593Smuzhiyun 238*4882a593Smuzhiyun+struct drm_mode * 239*4882a593Smuzhiyun+drm_output_choose_initial_mode(struct drm_device *device, 240*4882a593Smuzhiyun+ struct drm_output *output, 241*4882a593Smuzhiyun+ enum weston_drm_backend_output_mode mode, 242*4882a593Smuzhiyun+ const char *modeline, 243*4882a593Smuzhiyun+ const drmModeModeInfo *current_mode); 244*4882a593Smuzhiyun+ 245*4882a593Smuzhiyun int 246*4882a593Smuzhiyun drm_output_set_mode(struct weston_output *base, 247*4882a593Smuzhiyun enum weston_drm_backend_output_mode mode, 248*4882a593Smuzhiyundiff --git a/libweston/backend-drm/drm.c b/libweston/backend-drm/drm.c 249*4882a593Smuzhiyunindex d366e2b..23dbe38 100644 250*4882a593Smuzhiyun--- a/libweston/backend-drm/drm.c 251*4882a593Smuzhiyun+++ b/libweston/backend-drm/drm.c 252*4882a593Smuzhiyun@@ -41,6 +41,7 @@ 253*4882a593Smuzhiyun #include <linux/vt.h> 254*4882a593Smuzhiyun #include <assert.h> 255*4882a593Smuzhiyun #include <sys/mman.h> 256*4882a593Smuzhiyun+#include <sys/stat.h> 257*4882a593Smuzhiyun #include <time.h> 258*4882a593Smuzhiyun 259*4882a593Smuzhiyun #include <xf86drm.h> 260*4882a593Smuzhiyun@@ -75,6 +76,8 @@ 261*4882a593Smuzhiyun 262*4882a593Smuzhiyun static const char default_seat[] = "seat0"; 263*4882a593Smuzhiyun 264*4882a593Smuzhiyun+static int config_timer_handler(void *data); 265*4882a593Smuzhiyun+ 266*4882a593Smuzhiyun static inline bool 267*4882a593Smuzhiyun drm_head_is_external(struct drm_head *head) 268*4882a593Smuzhiyun { 269*4882a593Smuzhiyun@@ -508,6 +511,12 @@ drm_output_update_complete(struct drm_output *output, uint32_t flags, 270*4882a593Smuzhiyun return; 271*4882a593Smuzhiyun } 272*4882a593Smuzhiyun 273*4882a593Smuzhiyun+ if (!sec && !usec) { 274*4882a593Smuzhiyun+ weston_output_finish_frame(&output->base, NULL, 275*4882a593Smuzhiyun+ WP_PRESENTATION_FEEDBACK_INVALID); 276*4882a593Smuzhiyun+ return; 277*4882a593Smuzhiyun+ } 278*4882a593Smuzhiyun+ 279*4882a593Smuzhiyun ts.tv_sec = sec; 280*4882a593Smuzhiyun ts.tv_nsec = usec * 1000; 281*4882a593Smuzhiyun 282*4882a593Smuzhiyun@@ -687,8 +696,8 @@ out: 283*4882a593Smuzhiyun return; 284*4882a593Smuzhiyun } 285*4882a593Smuzhiyun 286*4882a593Smuzhiyun- sw = fb->width; 287*4882a593Smuzhiyun- sh = fb->height; 288*4882a593Smuzhiyun+ sw = fb->width * output->base.down_scale; 289*4882a593Smuzhiyun+ sh = fb->height * output->base.down_scale; 290*4882a593Smuzhiyun 291*4882a593Smuzhiyun dx = output->plane_bounds.x1; 292*4882a593Smuzhiyun dy = output->plane_bounds.y1; 293*4882a593Smuzhiyun@@ -830,7 +839,8 @@ drm_output_repaint(struct weston_output *output_base, pixman_region32_t *damage) 294*4882a593Smuzhiyun 295*4882a593Smuzhiyun weston_compositor_read_presentation_clock(b->compositor, &now); 296*4882a593Smuzhiyun now_ms = timespec_to_msec(&now); 297*4882a593Smuzhiyun- if (now_ms < b->last_resize_ms + b->resize_freeze_ms) { 298*4882a593Smuzhiyun+ if (now_ms < b->last_resize_ms + b->resize_freeze_ms || 299*4882a593Smuzhiyun+ now_ms < output->last_resize_ms + b->resize_freeze_ms) { 300*4882a593Smuzhiyun /* Resize fullscreen/maxmium views(not always success) */ 301*4882a593Smuzhiyun if (now_ms < b->last_resize_ms + DRM_RESIZE_FREEZE_MS) 302*4882a593Smuzhiyun wl_signal_emit(&b->compositor->output_resized_signal, 303*4882a593Smuzhiyun@@ -839,7 +849,7 @@ drm_output_repaint(struct weston_output *output_base, pixman_region32_t *damage) 304*4882a593Smuzhiyun weston_output_damage(output_base); 305*4882a593Smuzhiyun weston_output_finish_frame(output_base, NULL, 306*4882a593Smuzhiyun WP_PRESENTATION_FEEDBACK_INVALID); 307*4882a593Smuzhiyun- return 0; 308*4882a593Smuzhiyun+ goto not_repainted; 309*4882a593Smuzhiyun } 310*4882a593Smuzhiyun 311*4882a593Smuzhiyun /* If planes have been disabled in the core, we might not have 312*4882a593Smuzhiyun@@ -870,7 +880,8 @@ drm_output_repaint(struct weston_output *output_base, pixman_region32_t *damage) 313*4882a593Smuzhiyun 314*4882a593Smuzhiyun err: 315*4882a593Smuzhiyun drm_output_state_free(state); 316*4882a593Smuzhiyun- return 0; 317*4882a593Smuzhiyun+not_repainted: 318*4882a593Smuzhiyun+ return 1; 319*4882a593Smuzhiyun } 320*4882a593Smuzhiyun 321*4882a593Smuzhiyun /* Determine the type of vblank synchronization to use for the output. 322*4882a593Smuzhiyun@@ -2294,6 +2305,8 @@ drm_output_enable(struct weston_output *base) 323*4882a593Smuzhiyun output->base.switch_mode = drm_output_switch_mode; 324*4882a593Smuzhiyun output->base.set_gamma = drm_output_set_gamma; 325*4882a593Smuzhiyun 326*4882a593Smuzhiyun+ output->original_transform = output->base.transform; 327*4882a593Smuzhiyun+ 328*4882a593Smuzhiyun output->state_invalid = true; 329*4882a593Smuzhiyun 330*4882a593Smuzhiyun weston_log("Output %s (crtc %d) video modes:\n", 331*4882a593Smuzhiyun@@ -3186,6 +3199,7 @@ drm_destroy(struct weston_compositor *ec) 332*4882a593Smuzhiyun 333*4882a593Smuzhiyun udev_input_destroy(&b->input); 334*4882a593Smuzhiyun 335*4882a593Smuzhiyun+ wl_event_source_remove(b->config_timer); 336*4882a593Smuzhiyun wl_event_source_remove(b->hotplug_timer); 337*4882a593Smuzhiyun wl_event_source_remove(b->udev_drm_source); 338*4882a593Smuzhiyun wl_event_source_remove(b->drm_source); 339*4882a593Smuzhiyun@@ -3606,6 +3620,10 @@ output_create_notify(struct wl_listener *listener, void *data) 340*4882a593Smuzhiyun output_create_listener); 341*4882a593Smuzhiyun 342*4882a593Smuzhiyun drm_backend_update_outputs(b); 343*4882a593Smuzhiyun+ 344*4882a593Smuzhiyun+ /* Force reload config */ 345*4882a593Smuzhiyun+ memset(&b->config_stat, 0, sizeof(b->config_stat)); 346*4882a593Smuzhiyun+ config_timer_handler(b); 347*4882a593Smuzhiyun } 348*4882a593Smuzhiyun 349*4882a593Smuzhiyun static const struct weston_drm_output_api api = { 350*4882a593Smuzhiyun@@ -3615,6 +3633,239 @@ static const struct weston_drm_output_api api = { 351*4882a593Smuzhiyun drm_output_set_max_bpc, 352*4882a593Smuzhiyun }; 353*4882a593Smuzhiyun 354*4882a593Smuzhiyun+static void 355*4882a593Smuzhiyun+drm_output_rotate(struct drm_output *output, int rotate) 356*4882a593Smuzhiyun+{ 357*4882a593Smuzhiyun+ struct drm_backend *b = to_drm_backend(output->base.compositor); 358*4882a593Smuzhiyun+ uint32_t transform = output->original_transform; 359*4882a593Smuzhiyun+ struct timespec now; 360*4882a593Smuzhiyun+ 361*4882a593Smuzhiyun+ /* Hacky way to rotate transform */ 362*4882a593Smuzhiyun+ transform = (transform / 4) * 4 + (transform + rotate) % 4; 363*4882a593Smuzhiyun+ 364*4882a593Smuzhiyun+ if (output->base.transform == transform) 365*4882a593Smuzhiyun+ return; 366*4882a593Smuzhiyun+ 367*4882a593Smuzhiyun+ /* Freeze output when rotating */ 368*4882a593Smuzhiyun+ weston_compositor_read_presentation_clock(b->compositor, &now); 369*4882a593Smuzhiyun+ output->last_resize_ms = timespec_to_msec(&now); 370*4882a593Smuzhiyun+ 371*4882a593Smuzhiyun+ weston_output_set_transform(&output->base, transform); 372*4882a593Smuzhiyun+} 373*4882a593Smuzhiyun+ 374*4882a593Smuzhiyun+static void 375*4882a593Smuzhiyun+drm_output_modeset(struct drm_output *output, const char *modeline) 376*4882a593Smuzhiyun+{ 377*4882a593Smuzhiyun+ struct drm_backend *b = to_drm_backend(output->base.compositor); 378*4882a593Smuzhiyun+ struct drm_head *head = 379*4882a593Smuzhiyun+ to_drm_head(weston_output_get_first_head(&output->base)); 380*4882a593Smuzhiyun+ struct drm_mode *mode; 381*4882a593Smuzhiyun+ struct timespec now; 382*4882a593Smuzhiyun+ 383*4882a593Smuzhiyun+ /* Unable to switch mode, let's retry later */ 384*4882a593Smuzhiyun+ if (output->page_flip_pending || output->atomic_complete_pending) { 385*4882a593Smuzhiyun+ memset(&b->config_stat, 0, sizeof(b->config_stat)); 386*4882a593Smuzhiyun+ return; 387*4882a593Smuzhiyun+ } 388*4882a593Smuzhiyun+ 389*4882a593Smuzhiyun+ mode = drm_output_choose_initial_mode(b->drm, output, 390*4882a593Smuzhiyun+ WESTON_DRM_BACKEND_OUTPUT_PREFERRED, 391*4882a593Smuzhiyun+ modeline, 392*4882a593Smuzhiyun+ &head->inherited_mode); 393*4882a593Smuzhiyun+ 394*4882a593Smuzhiyun+ weston_output_mode_set_native(&output->base, &mode->base, 395*4882a593Smuzhiyun+ output->base.current_scale); 396*4882a593Smuzhiyun+ weston_output_damage(&output->base); 397*4882a593Smuzhiyun+ 398*4882a593Smuzhiyun+ mode = to_drm_mode(output->base.current_mode); 399*4882a593Smuzhiyun+ 400*4882a593Smuzhiyun+ weston_log("Output %s changed to %dx%d@%d for mode(%s)\n", 401*4882a593Smuzhiyun+ output->base.name, 402*4882a593Smuzhiyun+ mode->mode_info.hdisplay, mode->mode_info.vdisplay, 403*4882a593Smuzhiyun+ mode->mode_info.vrefresh, 404*4882a593Smuzhiyun+ modeline); 405*4882a593Smuzhiyun+ 406*4882a593Smuzhiyun+ weston_compositor_read_presentation_clock(b->compositor, &now); 407*4882a593Smuzhiyun+ b->last_update_ms = timespec_to_msec(&now); 408*4882a593Smuzhiyun+} 409*4882a593Smuzhiyun+ 410*4882a593Smuzhiyun+static void 411*4882a593Smuzhiyun+drm_output_set_size(struct drm_output *output, const int w, const int h) 412*4882a593Smuzhiyun+{ 413*4882a593Smuzhiyun+ struct drm_backend *b = to_drm_backend(output->base.compositor); 414*4882a593Smuzhiyun+ struct weston_mode *mode; 415*4882a593Smuzhiyun+ struct timespec now; 416*4882a593Smuzhiyun+ 417*4882a593Smuzhiyun+ if (output->base.fixed_size && 418*4882a593Smuzhiyun+ output->base.current_mode->width == w && 419*4882a593Smuzhiyun+ output->base.current_mode->height == h) 420*4882a593Smuzhiyun+ return; 421*4882a593Smuzhiyun+ 422*4882a593Smuzhiyun+ wl_list_for_each(mode, &output->base.mode_list, link) { 423*4882a593Smuzhiyun+ mode->width = w; 424*4882a593Smuzhiyun+ mode->height = h; 425*4882a593Smuzhiyun+ } 426*4882a593Smuzhiyun+ 427*4882a593Smuzhiyun+ output->base.fixed_size = true; 428*4882a593Smuzhiyun+ 429*4882a593Smuzhiyun+ /* Freeze output when resizing */ 430*4882a593Smuzhiyun+ weston_compositor_read_presentation_clock(b->compositor, &now); 431*4882a593Smuzhiyun+ output->last_resize_ms = timespec_to_msec(&now); 432*4882a593Smuzhiyun+ 433*4882a593Smuzhiyun+ weston_output_set_transform(&output->base, output->base.transform); 434*4882a593Smuzhiyun+ 435*4882a593Smuzhiyun+ if (b->use_pixman) { 436*4882a593Smuzhiyun+ drm_output_fini_pixman(output); 437*4882a593Smuzhiyun+ if (drm_output_init_pixman(output, b) < 0) 438*4882a593Smuzhiyun+ weston_log("failed to init output pixman state with " 439*4882a593Smuzhiyun+ "new mode\n"); 440*4882a593Smuzhiyun+ } else { 441*4882a593Smuzhiyun+ drm_output_fini_egl(output); 442*4882a593Smuzhiyun+ if (drm_output_init_egl(output, b) < 0) 443*4882a593Smuzhiyun+ weston_log("failed to init output egl state with " 444*4882a593Smuzhiyun+ "new mode"); 445*4882a593Smuzhiyun+ } 446*4882a593Smuzhiyun+ 447*4882a593Smuzhiyun+ drm_output_print_modes(output); 448*4882a593Smuzhiyun+} 449*4882a593Smuzhiyun+ 450*4882a593Smuzhiyun+static void 451*4882a593Smuzhiyun+config_handle_output(struct drm_backend *b, const char *name, 452*4882a593Smuzhiyun+ const char *config) 453*4882a593Smuzhiyun+{ 454*4882a593Smuzhiyun+ struct drm_output *output; 455*4882a593Smuzhiyun+ bool is_all = !strcmp(name, "all"); 456*4882a593Smuzhiyun+ 457*4882a593Smuzhiyun+ wl_list_for_each(output, &b->compositor->output_list, base.link) { 458*4882a593Smuzhiyun+ if (!is_all && strcmp(name, output->base.name)) 459*4882a593Smuzhiyun+ continue; 460*4882a593Smuzhiyun+ 461*4882a593Smuzhiyun+ if (!strcmp(config, "primary")) { 462*4882a593Smuzhiyun+ setenv("WESTON_DRM_PRIMARY", name, 1); 463*4882a593Smuzhiyun+ hotplug_timer_handler(b->drm); 464*4882a593Smuzhiyun+ } else if (!strcmp(config, "prefer")) { 465*4882a593Smuzhiyun+ b->compositor->prefer_output = &output->base; 466*4882a593Smuzhiyun+ } else if (!strncmp(config, "rotate", strlen("rotate"))) { 467*4882a593Smuzhiyun+ int rotate = atoi(config + strlen("rotate")) / 90; 468*4882a593Smuzhiyun+ drm_output_rotate(output, rotate); 469*4882a593Smuzhiyun+ } else if (!strncmp(config, "mode=", strlen("mode="))) { 470*4882a593Smuzhiyun+ drm_output_modeset(output, config + strlen("mode=")); 471*4882a593Smuzhiyun+ } else if (!strcmp(config, "freeze")) { 472*4882a593Smuzhiyun+ output->base.freezing = true; 473*4882a593Smuzhiyun+ } else if (!strcmp(config, "off")) { 474*4882a593Smuzhiyun+ output->base.freezing = true; 475*4882a593Smuzhiyun+ if (!output->virtual) 476*4882a593Smuzhiyun+ drm_set_dpms(&output->base, WESTON_DPMS_OFF); 477*4882a593Smuzhiyun+ } else if (!strcmp(config, "unfreeze") || 478*4882a593Smuzhiyun+ !strcmp(config, "on")) { 479*4882a593Smuzhiyun+ if (!output->base.freezing) 480*4882a593Smuzhiyun+ continue; 481*4882a593Smuzhiyun+ 482*4882a593Smuzhiyun+ output->base.freezing = false; 483*4882a593Smuzhiyun+ 484*4882a593Smuzhiyun+ if (!output->virtual) 485*4882a593Smuzhiyun+ drm_set_dpms(&output->base, WESTON_DPMS_ON); 486*4882a593Smuzhiyun+ 487*4882a593Smuzhiyun+ drm_output_update_complete(output, 0, 0, 0); 488*4882a593Smuzhiyun+ output->page_flip_pending = false; 489*4882a593Smuzhiyun+ output->atomic_complete_pending = false; 490*4882a593Smuzhiyun+ 491*4882a593Smuzhiyun+ weston_output_damage(&output->base); 492*4882a593Smuzhiyun+ } else if (!strncmp(config, "down-scale=", 493*4882a593Smuzhiyun+ strlen("down-scale="))) { 494*4882a593Smuzhiyun+ double down_scale = 495*4882a593Smuzhiyun+ atof(config + strlen("down-scale=")); 496*4882a593Smuzhiyun+ if (down_scale == output->base.down_scale || 497*4882a593Smuzhiyun+ down_scale < 0.125 || down_scale > 1) 498*4882a593Smuzhiyun+ continue; 499*4882a593Smuzhiyun+ 500*4882a593Smuzhiyun+ output->base.down_scale = down_scale; 501*4882a593Smuzhiyun+ weston_output_damage(&output->base); 502*4882a593Smuzhiyun+ } else if (!strncmp(config, "size=", strlen("size="))) { 503*4882a593Smuzhiyun+ int w, h; 504*4882a593Smuzhiyun+ 505*4882a593Smuzhiyun+ if (sscanf(config, "size=%dx%d", &w, &h) != 2) 506*4882a593Smuzhiyun+ continue; 507*4882a593Smuzhiyun+ 508*4882a593Smuzhiyun+ drm_output_set_size(output, w, h); 509*4882a593Smuzhiyun+ } else if (!strncmp(config, "pos=", strlen("pos="))) { 510*4882a593Smuzhiyun+ int x, y; 511*4882a593Smuzhiyun+ 512*4882a593Smuzhiyun+ if (sscanf(config, "pos=%d,%d", &x, &y) != 2) 513*4882a593Smuzhiyun+ continue; 514*4882a593Smuzhiyun+ 515*4882a593Smuzhiyun+ weston_output_move(&output->base, x, y); 516*4882a593Smuzhiyun+ output->base.fixed_position = true; 517*4882a593Smuzhiyun+ 518*4882a593Smuzhiyun+ weston_compositor_reflow_outputs(b->compositor); 519*4882a593Smuzhiyun+ } else if (!strncmp(config, "rect=", strlen("rect="))) { 520*4882a593Smuzhiyun+ int x1, y1, x2, y2, ret; 521*4882a593Smuzhiyun+ 522*4882a593Smuzhiyun+ ret = sscanf(config, "rect=<%d,%d,%d,%d>", 523*4882a593Smuzhiyun+ &x1, &y1, &x2, &y2); 524*4882a593Smuzhiyun+ if (ret != 4) 525*4882a593Smuzhiyun+ continue; 526*4882a593Smuzhiyun+ 527*4882a593Smuzhiyun+ output->plane_bounds.x1 = x1; 528*4882a593Smuzhiyun+ output->plane_bounds.y1 = y1; 529*4882a593Smuzhiyun+ output->plane_bounds.x2 = x2; 530*4882a593Smuzhiyun+ output->plane_bounds.y2 = y2; 531*4882a593Smuzhiyun+ weston_output_schedule_repaint(&output->base); 532*4882a593Smuzhiyun+ } else if (!strncmp(config, "input=", strlen("input="))) { 533*4882a593Smuzhiyun+ weston_output_bind_input(&output->base, 534*4882a593Smuzhiyun+ config + strlen("input=")); 535*4882a593Smuzhiyun+ } 536*4882a593Smuzhiyun+ } 537*4882a593Smuzhiyun+} 538*4882a593Smuzhiyun+ 539*4882a593Smuzhiyun+static int 540*4882a593Smuzhiyun+config_timer_handler(void *data) 541*4882a593Smuzhiyun+{ 542*4882a593Smuzhiyun+#define MAX_CONF_LEN 512 543*4882a593Smuzhiyun+#define _STR(x) #x 544*4882a593Smuzhiyun+#define STR(x) _STR(x) 545*4882a593Smuzhiyun+ 546*4882a593Smuzhiyun+ struct drm_backend *b = data; 547*4882a593Smuzhiyun+ struct stat st; 548*4882a593Smuzhiyun+ char type[MAX_CONF_LEN], key[MAX_CONF_LEN], value[MAX_CONF_LEN]; 549*4882a593Smuzhiyun+ const char *config_file; 550*4882a593Smuzhiyun+ FILE *conf_fp; 551*4882a593Smuzhiyun+ 552*4882a593Smuzhiyun+ wl_event_source_timer_update(b->config_timer, DRM_CONFIG_UPDATE_MS); 553*4882a593Smuzhiyun+ 554*4882a593Smuzhiyun+ config_file = getenv("WESTON_DRM_CONFIG"); 555*4882a593Smuzhiyun+ if (!config_file) 556*4882a593Smuzhiyun+ config_file = WESTON_DRM_CONFIG_FILE; 557*4882a593Smuzhiyun+ 558*4882a593Smuzhiyun+ if (stat(config_file, &st) < 0) 559*4882a593Smuzhiyun+ return 0; 560*4882a593Smuzhiyun+ 561*4882a593Smuzhiyun+ if (st.st_mtime && !memcmp(&st, &b->config_stat, sizeof(st))) 562*4882a593Smuzhiyun+ return 0; 563*4882a593Smuzhiyun+ 564*4882a593Smuzhiyun+ conf_fp = fopen(config_file, "r"); 565*4882a593Smuzhiyun+ if (!conf_fp) 566*4882a593Smuzhiyun+ return 0; 567*4882a593Smuzhiyun+ 568*4882a593Smuzhiyun+ /** 569*4882a593Smuzhiyun+ * Parse configs, formated with <type>:<key>:<value> 570*4882a593Smuzhiyun+ * For example: "output:all:rotate90" 571*4882a593Smuzhiyun+ */ 572*4882a593Smuzhiyun+ while (3 == fscanf(conf_fp, 573*4882a593Smuzhiyun+ "%" STR(MAX_CONF_LEN) "[^:]:" 574*4882a593Smuzhiyun+ "%" STR(MAX_CONF_LEN) "[^:]:" 575*4882a593Smuzhiyun+ "%" STR(MAX_CONF_LEN) "[^\n]%*c", type, key, value)) { 576*4882a593Smuzhiyun+ if (!strcmp(type, "output")) 577*4882a593Smuzhiyun+ config_handle_output(b, key, value); 578*4882a593Smuzhiyun+ } 579*4882a593Smuzhiyun+ 580*4882a593Smuzhiyun+ fclose(conf_fp); 581*4882a593Smuzhiyun+ 582*4882a593Smuzhiyun+ stat(config_file, &st); 583*4882a593Smuzhiyun+ b->config_stat = st; 584*4882a593Smuzhiyun+ return 0; 585*4882a593Smuzhiyun+} 586*4882a593Smuzhiyun+ 587*4882a593Smuzhiyun enum drm_head_mode { 588*4882a593Smuzhiyun DRM_HEAD_MODE_DEFAULT, 589*4882a593Smuzhiyun DRM_HEAD_MODE_PRIMARY, 590*4882a593Smuzhiyun@@ -3958,6 +4209,10 @@ drm_backend_create(struct weston_compositor *compositor, 591*4882a593Smuzhiyun b->hotplug_timer = 592*4882a593Smuzhiyun wl_event_loop_add_timer(loop, hotplug_timer_handler, b->drm); 593*4882a593Smuzhiyun 594*4882a593Smuzhiyun+ b->config_timer = 595*4882a593Smuzhiyun+ wl_event_loop_add_timer(loop, config_timer_handler, b); 596*4882a593Smuzhiyun+ config_timer_handler(b); 597*4882a593Smuzhiyun+ 598*4882a593Smuzhiyun return b; 599*4882a593Smuzhiyun 600*4882a593Smuzhiyun err_udev_monitor: 601*4882a593Smuzhiyundiff --git a/libweston/backend-drm/modes.c b/libweston/backend-drm/modes.c 602*4882a593Smuzhiyunindex 7e7865b..f3d2c00 100644 603*4882a593Smuzhiyun--- a/libweston/backend-drm/modes.c 604*4882a593Smuzhiyun+++ b/libweston/backend-drm/modes.c 605*4882a593Smuzhiyun@@ -405,15 +405,19 @@ drm_output_add_mode(struct drm_output *output, const drmModeModeInfo *info) 606*4882a593Smuzhiyun if (mode == NULL) 607*4882a593Smuzhiyun return NULL; 608*4882a593Smuzhiyun 609*4882a593Smuzhiyun- mode->base.flags = 0; 610*4882a593Smuzhiyun- mode->base.width = info->hdisplay; 611*4882a593Smuzhiyun- mode->base.height = info->vdisplay; 612*4882a593Smuzhiyun- 613*4882a593Smuzhiyun- if (b->virtual_width && b->virtual_height) { 614*4882a593Smuzhiyun+ if (output->base.fixed_size) { 615*4882a593Smuzhiyun+ mode->base.width = output->base.width; 616*4882a593Smuzhiyun+ mode->base.height = output->base.height; 617*4882a593Smuzhiyun+ } else if (b->virtual_width && b->virtual_height) { 618*4882a593Smuzhiyun mode->base.width = b->virtual_width; 619*4882a593Smuzhiyun mode->base.height = b->virtual_height; 620*4882a593Smuzhiyun+ } else { 621*4882a593Smuzhiyun+ mode->base.width = info->hdisplay; 622*4882a593Smuzhiyun+ mode->base.height = info->vdisplay; 623*4882a593Smuzhiyun } 624*4882a593Smuzhiyun 625*4882a593Smuzhiyun+ mode->base.flags = 0; 626*4882a593Smuzhiyun+ 627*4882a593Smuzhiyun mode->base.refresh = drm_refresh_rate_mHz(info); 628*4882a593Smuzhiyun mode->mode_info = *info; 629*4882a593Smuzhiyun mode->blob_id = 0; 630*4882a593Smuzhiyun@@ -589,7 +593,7 @@ update_head_from_connector(struct drm_head *head) 631*4882a593Smuzhiyun * @param current_mode Mode currently being displayed on this output 632*4882a593Smuzhiyun * @returns A mode from the output's mode list, or NULL if none available 633*4882a593Smuzhiyun */ 634*4882a593Smuzhiyun-static struct drm_mode * 635*4882a593Smuzhiyun+struct drm_mode * 636*4882a593Smuzhiyun drm_output_choose_initial_mode(struct drm_device *device, 637*4882a593Smuzhiyun struct drm_output *output, 638*4882a593Smuzhiyun enum weston_drm_backend_output_mode mode, 639*4882a593Smuzhiyun@@ -642,8 +646,8 @@ drm_output_choose_initial_mode(struct drm_device *device, 640*4882a593Smuzhiyun } 641*4882a593Smuzhiyun 642*4882a593Smuzhiyun wl_list_for_each_reverse(drm_mode, &output->base.mode_list, base.link) { 643*4882a593Smuzhiyun- if (width == drm_mode->base.width && 644*4882a593Smuzhiyun- height == drm_mode->base.height && 645*4882a593Smuzhiyun+ if (width == drm_mode->mode_info.hdisplay && 646*4882a593Smuzhiyun+ height == drm_mode->mode_info.vdisplay && 647*4882a593Smuzhiyun (refresh == 0 || refresh == drm_mode->mode_info.vrefresh)) { 648*4882a593Smuzhiyun if (!device->aspect_ratio_supported || 649*4882a593Smuzhiyun aspect_ratio == drm_mode->base.aspect_ratio) 650*4882a593Smuzhiyundiff --git a/libweston/compositor.c b/libweston/compositor.c 651*4882a593Smuzhiyunindex 07743ff..877e7a7 100644 652*4882a593Smuzhiyun--- a/libweston/compositor.c 653*4882a593Smuzhiyun+++ b/libweston/compositor.c 654*4882a593Smuzhiyun@@ -3372,6 +3372,11 @@ weston_output_repaint(struct weston_output *output) 655*4882a593Smuzhiyun static void 656*4882a593Smuzhiyun weston_output_schedule_repaint_reset(struct weston_output *output) 657*4882a593Smuzhiyun { 658*4882a593Smuzhiyun+ if (output->idle_repaint_source) { 659*4882a593Smuzhiyun+ wl_event_source_remove(output->idle_repaint_source); 660*4882a593Smuzhiyun+ output->idle_repaint_source = NULL; 661*4882a593Smuzhiyun+ } 662*4882a593Smuzhiyun+ 663*4882a593Smuzhiyun output->repaint_status = REPAINT_NOT_SCHEDULED; 664*4882a593Smuzhiyun TL_POINT(output->compositor, "core_repaint_exit_loop", 665*4882a593Smuzhiyun TLP_OUTPUT(output), TLP_END); 666*4882a593Smuzhiyun@@ -3384,6 +3389,11 @@ weston_output_maybe_repaint(struct weston_output *output, struct timespec *now) 667*4882a593Smuzhiyun int ret = 0; 668*4882a593Smuzhiyun int64_t msec_to_repaint; 669*4882a593Smuzhiyun 670*4882a593Smuzhiyun+ /* If we're sleeping, drop the repaint machinery entirely; we will 671*4882a593Smuzhiyun+ * explicitly repaint it when we come back. */ 672*4882a593Smuzhiyun+ if (output->freezing) 673*4882a593Smuzhiyun+ goto err; 674*4882a593Smuzhiyun+ 675*4882a593Smuzhiyun /* We're not ready yet; come back to make a decision later. */ 676*4882a593Smuzhiyun if (output->repaint_status != REPAINT_SCHEDULED) 677*4882a593Smuzhiyun return ret; 678*4882a593Smuzhiyun@@ -3410,11 +3420,11 @@ weston_output_maybe_repaint(struct weston_output *output, struct timespec *now) 679*4882a593Smuzhiyun * output. */ 680*4882a593Smuzhiyun ret = weston_output_repaint(output); 681*4882a593Smuzhiyun weston_compositor_read_presentation_clock(compositor, now); 682*4882a593Smuzhiyun- if (ret != 0) 683*4882a593Smuzhiyun+ if (ret < 0) 684*4882a593Smuzhiyun goto err; 685*4882a593Smuzhiyun 686*4882a593Smuzhiyun- output->repainted = true; 687*4882a593Smuzhiyun- return ret; 688*4882a593Smuzhiyun+ output->repainted = !ret; 689*4882a593Smuzhiyun+ return 0; 690*4882a593Smuzhiyun 691*4882a593Smuzhiyun err: 692*4882a593Smuzhiyun weston_output_schedule_repaint_reset(output); 693*4882a593Smuzhiyun@@ -3480,7 +3490,7 @@ output_repaint_timer_handler(void *data) 694*4882a593Smuzhiyun struct weston_compositor *compositor = data; 695*4882a593Smuzhiyun struct weston_output *output; 696*4882a593Smuzhiyun struct timespec now; 697*4882a593Smuzhiyun- int ret = 0; 698*4882a593Smuzhiyun+ int ret = 0, repainted = 0; 699*4882a593Smuzhiyun 700*4882a593Smuzhiyun if (!access(getenv("WESTON_FREEZE_DISPLAY") ? : "", F_OK)) { 701*4882a593Smuzhiyun usleep(DEFAULT_REPAINT_WINDOW * 1000); 702*4882a593Smuzhiyun@@ -3497,9 +3507,11 @@ output_repaint_timer_handler(void *data) 703*4882a593Smuzhiyun ret = weston_output_maybe_repaint(output, &now); 704*4882a593Smuzhiyun if (ret) 705*4882a593Smuzhiyun break; 706*4882a593Smuzhiyun+ 707*4882a593Smuzhiyun+ repainted |= output->repainted; 708*4882a593Smuzhiyun } 709*4882a593Smuzhiyun 710*4882a593Smuzhiyun- if (ret == 0) { 711*4882a593Smuzhiyun+ if (ret == 0 && repainted) { 712*4882a593Smuzhiyun if (compositor->backend->repaint_flush) 713*4882a593Smuzhiyun ret = compositor->backend->repaint_flush(compositor); 714*4882a593Smuzhiyun } else { 715*4882a593Smuzhiyun@@ -6544,7 +6556,7 @@ weston_compositor_reflow_outputs(struct weston_compositor *compositor) 716*4882a593Smuzhiyun wl_list_for_each(head, &output->head_list, output_link) 717*4882a593Smuzhiyun weston_head_update_global(head); 718*4882a593Smuzhiyun 719*4882a593Smuzhiyun- if (!weston_output_valid(output)) 720*4882a593Smuzhiyun+ if (!weston_output_valid(output) || output->fixed_position) 721*4882a593Smuzhiyun continue; 722*4882a593Smuzhiyun 723*4882a593Smuzhiyun x = next_x; 724*4882a593Smuzhiyun@@ -7050,6 +7062,9 @@ weston_output_set_transform(struct weston_output *output, 725*4882a593Smuzhiyun 726*4882a593Smuzhiyun weston_compositor_reflow_outputs(output->compositor); 727*4882a593Smuzhiyun 728*4882a593Smuzhiyun+ wl_signal_emit(&output->compositor->output_resized_signal, 729*4882a593Smuzhiyun+ output); 730*4882a593Smuzhiyun+ 731*4882a593Smuzhiyun /* Notify clients of the change for output transform. */ 732*4882a593Smuzhiyun wl_list_for_each(head, &output->head_list, output_link) { 733*4882a593Smuzhiyun wl_resource_for_each(resource, &head->resource_list) { 734*4882a593Smuzhiyun@@ -7288,6 +7303,8 @@ weston_output_init(struct weston_output *output, 735*4882a593Smuzhiyun /* Can't use -1 on uint32_t and 0 is valid enum value */ 736*4882a593Smuzhiyun output->transform = UINT32_MAX; 737*4882a593Smuzhiyun 738*4882a593Smuzhiyun+ output->down_scale = 1.0f; 739*4882a593Smuzhiyun+ 740*4882a593Smuzhiyun pixman_region32_init(&output->damage); 741*4882a593Smuzhiyun pixman_region32_init(&output->region); 742*4882a593Smuzhiyun wl_list_init(&output->mode_list); 743*4882a593Smuzhiyun@@ -7420,7 +7437,6 @@ weston_output_enable(struct weston_output *output) 744*4882a593Smuzhiyun weston_output_transform_scale_init(output, output->transform, output->scale); 745*4882a593Smuzhiyun 746*4882a593Smuzhiyun weston_output_init_geometry(output, output->x, output->y); 747*4882a593Smuzhiyun- weston_output_damage(output); 748*4882a593Smuzhiyun 749*4882a593Smuzhiyun wl_list_init(&output->animation_list); 750*4882a593Smuzhiyun wl_list_init(&output->feedback_list); 751*4882a593Smuzhiyundiff --git a/libweston/libinput-seat.c b/libweston/libinput-seat.c 752*4882a593Smuzhiyunindex 57ff181..100b47d 100644 753*4882a593Smuzhiyun--- a/libweston/libinput-seat.c 754*4882a593Smuzhiyun+++ b/libweston/libinput-seat.c 755*4882a593Smuzhiyun@@ -534,3 +534,46 @@ udev_seat_get_named(struct udev_input *input, const char *seat_name) 756*4882a593Smuzhiyun 757*4882a593Smuzhiyun return udev_seat_create(input, seat_name); 758*4882a593Smuzhiyun } 759*4882a593Smuzhiyun+ 760*4882a593Smuzhiyun+void 761*4882a593Smuzhiyun+weston_output_bind_input(struct weston_output *output, const char *match) 762*4882a593Smuzhiyun+{ 763*4882a593Smuzhiyun+ struct weston_compositor *compositor = output->compositor; 764*4882a593Smuzhiyun+ struct evdev_device *device; 765*4882a593Smuzhiyun+ struct udev_seat *seat; 766*4882a593Smuzhiyun+ const char *sysname, *name; 767*4882a593Smuzhiyun+ int len = strlen(match); 768*4882a593Smuzhiyun+ int clear = !len; 769*4882a593Smuzhiyun+ 770*4882a593Smuzhiyun+ /* Handle pattern match */ 771*4882a593Smuzhiyun+ if (len && match[len - 1] == '*') 772*4882a593Smuzhiyun+ len--; 773*4882a593Smuzhiyun+ 774*4882a593Smuzhiyun+ wl_list_for_each(seat, &compositor->seat_list, base.link) { 775*4882a593Smuzhiyun+ wl_list_for_each(device, &seat->devices_list, link) { 776*4882a593Smuzhiyun+ if (clear) { 777*4882a593Smuzhiyun+ /* Clear all bounded inputs */ 778*4882a593Smuzhiyun+ if (!device->output_name || 779*4882a593Smuzhiyun+ strcmp(device->output_name, output->name)) 780*4882a593Smuzhiyun+ continue; 781*4882a593Smuzhiyun+ 782*4882a593Smuzhiyun+ free(device->output_name); 783*4882a593Smuzhiyun+ device->output_name = NULL; 784*4882a593Smuzhiyun+ continue; 785*4882a593Smuzhiyun+ } 786*4882a593Smuzhiyun+ 787*4882a593Smuzhiyun+ sysname = libinput_device_get_sysname(device->device); 788*4882a593Smuzhiyun+ name = libinput_device_get_name(device->device); 789*4882a593Smuzhiyun+ 790*4882a593Smuzhiyun+ if (!len || !strncmp(name, match, len) || 791*4882a593Smuzhiyun+ !strncmp(sysname, match, len)) { 792*4882a593Smuzhiyun+ if (device->output_name) 793*4882a593Smuzhiyun+ free(device->output_name); 794*4882a593Smuzhiyun+ 795*4882a593Smuzhiyun+ device->output_name = strdup(output->name); 796*4882a593Smuzhiyun+ } 797*4882a593Smuzhiyun+ } 798*4882a593Smuzhiyun+ 799*4882a593Smuzhiyun+ udev_seat_update_output(seat); 800*4882a593Smuzhiyun+ } 801*4882a593Smuzhiyun+} 802*4882a593Smuzhiyundiff --git a/libweston/libweston-internal.h b/libweston/libweston-internal.h 803*4882a593Smuzhiyunindex 8bdac33..39d9e85 100644 804*4882a593Smuzhiyun--- a/libweston/libweston-internal.h 805*4882a593Smuzhiyun+++ b/libweston/libweston-internal.h 806*4882a593Smuzhiyun@@ -193,6 +193,9 @@ weston_output_disable_planes_incr(struct weston_output *output); 807*4882a593Smuzhiyun void 808*4882a593Smuzhiyun weston_output_disable_planes_decr(struct weston_output *output); 809*4882a593Smuzhiyun 810*4882a593Smuzhiyun+void 811*4882a593Smuzhiyun+weston_output_bind_input(struct weston_output *output, const char *name); 812*4882a593Smuzhiyun+ 813*4882a593Smuzhiyun /* weston_plane */ 814*4882a593Smuzhiyun 815*4882a593Smuzhiyun void 816*4882a593Smuzhiyundiff --git a/libweston/pixman-renderer.c b/libweston/pixman-renderer.c 817*4882a593Smuzhiyunindex 62c2cb1..22e7a42 100644 818*4882a593Smuzhiyun--- a/libweston/pixman-renderer.c 819*4882a593Smuzhiyun+++ b/libweston/pixman-renderer.c 820*4882a593Smuzhiyun@@ -158,6 +158,9 @@ pixman_renderer_compute_transform(pixman_transform_t *transform_out, 821*4882a593Smuzhiyun specified buffer transform/scale */ 822*4882a593Smuzhiyun matrix = output->inverse_matrix; 823*4882a593Smuzhiyun 824*4882a593Smuzhiyun+ weston_matrix_scale(&matrix, 825*4882a593Smuzhiyun+ 1 / output->down_scale, 1 / output->down_scale, 1); 826*4882a593Smuzhiyun+ 827*4882a593Smuzhiyun if (ev->transform.enabled) { 828*4882a593Smuzhiyun weston_matrix_multiply(&matrix, &ev->transform.inverse); 829*4882a593Smuzhiyun } else { 830*4882a593Smuzhiyundiff --git a/libweston/renderer-gl/gl-renderer.c b/libweston/renderer-gl/gl-renderer.c 831*4882a593Smuzhiyunindex db4c7b1..3437bf2 100644 832*4882a593Smuzhiyun--- a/libweston/renderer-gl/gl-renderer.c 833*4882a593Smuzhiyun+++ b/libweston/renderer-gl/gl-renderer.c 834*4882a593Smuzhiyun@@ -1685,6 +1685,10 @@ gl_renderer_repaint_output(struct weston_output *output, 835*4882a593Smuzhiyun 836*4882a593Smuzhiyun /* Calculate the global GL matrix */ 837*4882a593Smuzhiyun go->output_matrix = output->matrix; 838*4882a593Smuzhiyun+ 839*4882a593Smuzhiyun+ weston_matrix_scale(&go->output_matrix, 840*4882a593Smuzhiyun+ output->down_scale, output->down_scale, 1); 841*4882a593Smuzhiyun+ 842*4882a593Smuzhiyun weston_matrix_translate(&go->output_matrix, 843*4882a593Smuzhiyun -(output->current_mode->width / 2.0), 844*4882a593Smuzhiyun -(output->current_mode->height / 2.0), 0); 845*4882a593Smuzhiyun-- 846*4882a593Smuzhiyun2.20.1 847*4882a593Smuzhiyun 848