VirtualBox

Changeset 64919 in vbox for trunk/src/VBox/Additions/linux


Ignore:
Timestamp:
Dec 16, 2016 4:56:09 PM (8 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
112332
Message:

bugref:8677: Additions/Graphics/Wayland: Fedora 25 issues: fix sending virtual screen offset hints (recent guests only). If the hints are not for disjoint screen areas (GNOME Shell requires this), replace them with default ones. Having valid hints lets us know the virtual screen layout inside GNOME Shell/Wayland unless the user has manually changed it inside the guest, and we need this information to get the (absolute) pointer input mapping right. The code also detects and handles separately the special cases of the fbdev console being active and X.Org (a single large framebuffer for all screens in video memory).

Location:
trunk/src/VBox/Additions/linux/drm
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/linux/drm/README.testing

    r63772 r64919  
    1 This document lists things which have been known to fail in the past with the drm video driver and which should be tested regularly, e.g. when making code changes or before releases.
     1This document lists things which have been known to fail in the past with the
     2drm video driver and which should be tested regularly, e.g. when making code
     3changes or before releases.
    24
    35 * Test that "auto-resize" is enabled in the GUI if user space supports it.
    4  * Test that old versions of Plymouth which do not report rectangles (pre-0.9.0/2014-05-20) update the screen correctly.
     6 * Test that old versions of Plymouth which do not report rectangles
     7   (pre-0.9.0/2014-05-20) update the screen correctly.
     8 * Having valid, non-overlapping offset hints on all screens has caused
     9   mouse integration and/or screen updates to break for fbdev, X.Org or
     10   GNOME Shell/Wayland.
     11 * Note that if a multi-screen VM is booted with only one screen enabled
     12   the fbdev console will be disabled on the others until reboot.  Test this
     13   configuration.
  • trunk/src/VBox/Additions/linux/drm/vbox_drv.h

    r64830 r64919  
    9797    bool any_pitch;
    9898    unsigned num_crtcs;
    99     bool vga2_clone;
    10099    /** Amount of available VRAM, including space used for buffers. */
    101100    uint32_t full_vram_size;
     
    129128    uint32_t input_mapping_width;
    130129    uint32_t input_mapping_height;
     130    /** Is user-space using an X.Org-style layout of one large frame-buffer
     131     * encompassing all screen ones or is the fbdev console active? */
     132    bool single_framebuffer;
    131133    uint32_t cursor_width;
    132134    uint32_t cursor_height;
     
    169171    uint32_t fb_offset;
    170172    bool cursor_enabled;
     173    uint16_t x_hint;
     174    uint16_t y_hint;
    171175};
    172176
  • trunk/src/VBox/Additions/linux/drm/vbox_irq.c

    r64425 r64919  
    8585}
    8686
     87/** Check that the position hints provided by the host are suitable for GNOME
     88 * shell (i.e. all screens disjoint and hints for all enabled screens) and if
     89 * not replace them with default ones.  Providing valid hints improves the
     90 * chances that we will get a known screen layout for pointer mapping. */
     91static void validate_or_set_position_hints(struct vbox_private *vbox)
     92{
     93    int i, j;
     94    uint16_t currentx = 0;
     95    bool valid = true;
     96
     97    for (i = 0; i < vbox->num_crtcs; ++i) {
     98        for (j = 0; j < i; ++j) {
     99            struct VBVAMODEHINT *hintsi = &vbox->last_mode_hints[i];
     100            struct VBVAMODEHINT *hintsj = &vbox->last_mode_hints[j];
     101
     102            if (hintsi->fEnabled && hintsj->fEnabled) {
     103                if ((hintsi->dx >= 0xffff || hintsi->dy >= 0xffff ||
     104                     hintsj->dx >= 0xffff || hintsj->dy >= 0xffff) ||
     105                    (hintsi->dx < hintsj->dx + (hintsj->cx & 0x8fff) &&
     106                     hintsi->dx + (hintsi->cx & 0x8fff) > hintsj->dx) ||
     107                    (hintsi->dy < hintsj->dy + (hintsj->cy & 0x8fff) &&
     108                     hintsi->dy + (hintsi->cy & 0x8fff) > hintsj->dy))
     109                    valid = false;
     110            }
     111        }
     112    }
     113    if (!valid)
     114        for (i = 0; i < vbox->num_crtcs; ++i) {
     115            if (vbox->last_mode_hints[i].fEnabled) {
     116                vbox->last_mode_hints[i].dx = currentx;
     117                vbox->last_mode_hints[i].dy = 0;
     118                currentx += vbox->last_mode_hints[i].cx & 0x8fff;
     119            }
     120        }
     121}
     122
    87123/**
    88  * Query the host for
     124 * Query the host for the most recent video mode hints.
    89125 */
    90126static void vbox_update_mode_hints(struct vbox_private *vbox)
     
    105141        return;
    106142    }
     143    validate_or_set_position_hints(vbox);
    107144#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
    108145    drm_modeset_lock_all(dev);
     
    120157            vbox_connector->mode_hint.width = hints->cx & 0x8fff;
    121158            vbox_connector->mode_hint.height = hints->cy & 0x8fff;
     159            vbox_connector->vbox_crtc->x_hint = hints->dx;
     160            vbox_connector->vbox_crtc->y_hint = hints->dy;
    122161            vbox_connector->mode_hint.disconnected = disconnected;
    123162            if (vbox_connector->vbox_crtc->disconnected != disconnected) {
     
    127166                vbox_connector->vbox_crtc->disconnected = disconnected;
    128167            }
    129 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
    130             if ((hints->dx < 0xffff) && (hints->dy < 0xffff)) {
    131                 drm_object_property_set_value(&connector->base,
    132                     dev->mode_config.suggested_x_property, hints->dx & 0x8fff);
    133                 drm_object_property_set_value(&connector->base,
    134                     dev->mode_config.suggested_y_property, hints->dy & 0x8fff);
    135             }
    136 #endif
    137168        }
    138169    }
  • trunk/src/VBox/Additions/linux/drm/vbox_mode.c

    r64830 r64919  
    7474    unsigned crtc_id;
    7575    uint16_t flags;
     76    int32_t x_offset, y_offset;
    7677
    7778    vbox = crtc->dev->dev_private;
     
    8586    pitch = crtc->enabled ? CRTC_FB(crtc)->pitches[0] : width * bpp / 8;
    8687#endif
     88    x_offset = vbox->single_framebuffer ? crtc->x : vbox_crtc->x_hint;
     89    y_offset = vbox->single_framebuffer ? crtc->y : vbox_crtc->y_hint;
    8790    /* This is the old way of setting graphics modes.  It assumed one screen
    8891     * and a frame-buffer at the start of video RAM.  On older versions of
     
    101104    flags |= (vbox_crtc->disconnected ? VBVA_SCREEN_F_DISABLED : 0);
    102105    VBoxHGSMIProcessDisplayInfo(&vbox->submit_info, vbox_crtc->crtc_id,
    103                                 crtc->x, crtc->y,
     106                                x_offset, y_offset,
    104107                                crtc->x * bpp / 8 + crtc->y * pitch,
    105108                                pitch, width, height,
     
    171174}
    172175
     176/* Try to map the layout of virtual screens to the range of the input device.
     177 * Return true if we need to re-set the crtc modes due to screen offset
     178 * changes. */
     179static bool vbox_set_up_input_mapping(struct vbox_private *vbox)
     180{
     181    struct drm_crtc *crtci;
     182    struct drm_connector *connectori;
     183    struct drm_framebuffer *fb1 = NULL;
     184    bool single_framebuffer = true;
     185    bool old_single_framebuffer = vbox->single_framebuffer;
     186    uint16_t width = 0, height = 0;
     187
     188    /* Are we using an X.Org-style single large frame-buffer for all crtcs?
     189     * If so then screen layout can be deduced from the crtc offsets.
     190     * Same fall-back if this is the fbdev frame-buffer. */
     191    list_for_each_entry(crtci, &vbox->dev->mode_config.crtc_list, head) {
     192        if (fb1 == NULL) {
     193            fb1 = CRTC_FB(crtci);
     194            if (to_vbox_framebuffer(fb1) == &vbox->fbdev->afb)
     195                break;
     196        } else if (CRTC_FB(crtci) != NULL && fb1 != CRTC_FB(crtci))
     197            single_framebuffer = false;
     198    }
     199    if (single_framebuffer) {
     200        list_for_each_entry(crtci, &vbox->dev->mode_config.crtc_list, head) {
     201            if (to_vbox_crtc(crtci)->crtc_id == 0) {
     202                vbox->single_framebuffer = true;
     203                vbox->input_mapping_width = CRTC_FB(crtci)->width;
     204                vbox->input_mapping_height = CRTC_FB(crtci)->height;
     205                return old_single_framebuffer != vbox->single_framebuffer;
     206            }
     207        }
     208    }
     209    /* Otherwise calculate the total span of all screens. */
     210    list_for_each_entry(connectori, &vbox->dev->mode_config.connector_list,
     211                        head) {
     212        struct vbox_connector *vbox_connector = to_vbox_connector(connectori);
     213        struct vbox_crtc *vbox_crtc = vbox_connector->vbox_crtc;
     214
     215        width = max(width, (uint16_t) (vbox_crtc->x_hint +
     216                    vbox_connector->mode_hint.width));
     217        height = max(height, (uint16_t) (vbox_crtc->y_hint +
     218                    vbox_connector->mode_hint.height));
     219    }
     220    vbox->single_framebuffer = false;
     221    vbox->input_mapping_width = width;
     222    vbox->input_mapping_height = height;
     223    return old_single_framebuffer != vbox->single_framebuffer;
     224}
     225
    173226static int vbox_crtc_do_set_base(struct drm_crtc *crtc,
    174227                struct drm_framebuffer *old_fb,
     
    215268    /* vbox_set_start_address_crt1(crtc, (u32)gpu_addr); */
    216269    vbox_crtc->fb_offset = gpu_addr;
    217     if (vbox_crtc->crtc_id == 0) {
    218         vbox->input_mapping_width = CRTC_FB(crtc)->width;
    219         vbox->input_mapping_height = CRTC_FB(crtc)->height;
     270    if (vbox_set_up_input_mapping(vbox)) {
     271        struct drm_crtc *crtci;
     272
     273        list_for_each_entry(crtci, &vbox->dev->mode_config.crtc_list, head) {
     274            vbox_set_view(crtc);
     275            vbox_do_modeset(crtci, &crtci->mode);
     276        }
    220277    }
    221278    return 0;
     
    242299    if (!rc)
    243300        vbox_do_modeset(crtc, mode);
    244     /* Note that the input mapping is always relative to the first screen. */
    245301    VBoxHGSMIUpdateInputMapping(&vbox->submit_info, 0, 0,
    246302                                vbox->input_mapping_width,
     
    505561    }
    506562    vbox_set_edid(connector, preferred_width, preferred_height);
     563#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
     564    drm_object_property_set_value(&connector->base,
     565        vbox->dev->mode_config.suggested_x_property,
     566        vbox_connector->vbox_crtc->x_hint);
     567    drm_object_property_set_value(&connector->base,
     568        vbox->dev->mode_config.suggested_y_property,
     569        vbox_connector->vbox_crtc->y_hint);
     570#endif
    507571    return num_modes;
    508572}
     
    592656    drm_mode_create_suggested_offset_properties(dev);
    593657    drm_object_attach_property(&connector->base,
    594                                dev->mode_config.suggested_x_property, 0);
     658                               dev->mode_config.suggested_x_property, -1);
    595659    drm_object_attach_property(&connector->base,
    596                                dev->mode_config.suggested_y_property, 0);
     660                               dev->mode_config.suggested_y_property, -1);
    597661#endif
    598662#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
     
    763827                      | VBOX_MOUSE_POINTER_SHAPE
    764828                      | VBOX_MOUSE_POINTER_ALPHA;
     829    int32_t crtc_x = vbox->single_framebuffer ? crtc->x : to_vbox_crtc(crtc)->x_hint;
     830    int32_t crtc_y = vbox->single_framebuffer ? crtc->y : to_vbox_crtc(crtc)->y_hint;
    765831    uint32_t host_x, host_y;
    766832    uint32_t hot_x = 0;
     
    769835
    770836    /* We compare these to unsigned later and don't need to handle negative. */
    771     if (x + crtc->x < 0 || y + crtc->y < 0 || vbox->cursor_data_size == 0)
     837    if (x + crtc_x < 0 || y + crtc_y < 0 || vbox->cursor_data_size == 0)
    772838        return 0;
    773     rc = VBoxHGSMICursorPosition(&vbox->submit_info, true, x + crtc->x,
    774                                  y + crtc->y, &host_x, &host_y);
     839    rc = VBoxHGSMICursorPosition(&vbox->submit_info, true, x + crtc_x,
     840                                 y + crtc_y, &host_x, &host_y);
    775841    /* Work around a bug after save and restore in 5.0.20 and earlier. */
    776842    if (RT_FAILURE(rc) || (host_x == 0 && host_y == 0))
     
    778844               : rc == VERR_NO_MEMORY ? -ENOMEM
    779845               : -EINVAL;
    780     if (x + crtc->x < host_x)
    781         hot_x = min(host_x - x - crtc->x, vbox->cursor_width);
    782     if (y + crtc->y < host_y)
    783         hot_y = min(host_y - y - crtc->y, vbox->cursor_height);
     846    if (x + crtc_x < host_x)
     847        hot_x = min(host_x - x - crtc_x, vbox->cursor_width);
     848    if (y + crtc_y < host_y)
     849        hot_y = min(host_y - y - crtc_y, vbox->cursor_height);
    784850    if (hot_x == vbox->cursor_hot_x && hot_y == vbox->cursor_hot_y)
    785851        return 0;
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette