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