VirtualBox

Changeset 74581 in vbox for trunk


Ignore:
Timestamp:
Oct 2, 2018 2:01:09 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
125454
Message:

Additions/linux/vboxvideo: better work-around for missing dirty rectangles.
bugref:9235: No screenshot for Linux VM
Background: a long time ago, Linux user-space applications using the DRM
graphics interface did not need to provide the graphics driver with dirty
rectangle information. This was changed to make life easier for virtual
devices like ours, but the version of Plymouth (the splash screen at system
boot) in recent Ubuntu 14.04 versions does not do it. We did some nasty
tricks to make the hardware notice screen updates anyway, and they caused
screenshots in Linux virtual machines not to work (and might have other side
effects).
This changes removes the tricks mentioned above, and instead introduces a
twice-a-second refresh timer in the driver. As this is only intended for that
version of Plymouth, we disable the timer as soon as we either receive dirty
rectangle information, or the user-space client shows that it can handle
screen resizes (which Plymouth cannot, at least that version). Once page flip
support is integrated we could use that as a test instead of the second, but
only if there is actually a need. Twice a second refresh is quite a high
overhead, but it is only incurred in that rare case, and usually only for a
few seconds at that.

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/linux/drm/vbox_drv.c

    r71947 r74581  
    227227
    228228        mutex_lock(&vbox->hw_mutex);
    229         /*
    230          * Disable VBVA when someone releases master in case the next person
    231          * tries tries to do VESA.
    232          */
    233         /** @todo work out if anyone is likely to and whether it will work. */
    234         /*
    235          * Update: we also disable it because if the new master does not do
    236          * dirty rectangle reporting (e.g. old versions of Plymouth) then at
    237          * least the first screen will still be updated. We enable it as soon
    238          * as we receive a dirty rectangle report.
    239          */
    240         vbox_disable_accel(vbox);
     229        /* Start the refresh timer in case the user does not provide dirty
     230         * rectangles. */
     231        vbox->need_refresh_timer = true;
     232        schedule_delayed_work(&vbox->refresh_work, VBOX_REFRESH_PERIOD);
    241233        mutex_unlock(&vbox->hw_mutex);
    242234
     
    257249
    258250        mutex_lock(&vbox->hw_mutex);
    259         vbox_disable_accel(vbox);
     251        vbox->need_refresh_timer = false;
    260252        mutex_unlock(&vbox->hw_mutex);
    261253}
  • trunk/src/VBox/Additions/linux/drm/vbox_drv.h

    r72638 r74581  
    124124#define HOST_FLAGS_OFFSET GUEST_HEAP_USABLE_SIZE
    125125
     126/** How frequently we refresh if the guest is not providing dirty rectangles. */
     127#define VBOX_REFRESH_PERIOD (HZ / 2)
     128
    126129struct vbox_fbdev;
    127130
     
    161164         */
    162165        bool initial_mode_queried;
     166        /**
     167         * Do we know that the current user can send us dirty rectangle information?
     168         * If not, do periodic refreshes until we do know.
     169         */
     170        bool need_refresh_timer;
     171        /**
     172         * As long as the user is not sending us dirty rectangle information,
     173         * refresh the whole screen at regular intervals.
     174         */
     175        struct delayed_work refresh_work;
    163176        struct work_struct hotplug_work;
    164177        u32 input_mapping_width;
  • trunk/src/VBox/Additions/linux/drm/vbox_main.c

    r71947 r74581  
    109109        unsigned int i;
    110110
     111        /* The user can send rectangles, we do not need the timer. */
     112        vbox->need_refresh_timer = false;
    111113        mutex_lock(&vbox->hw_mutex);
    112114        list_for_each_entry(crtc, &fb->dev->mode_config.crtc_list, head) {
    113115                if (CRTC_FB(crtc) == fb) {
    114                         vbox_enable_accel(vbox);
    115116                        for (i = 0; i < num_rects; ++i) {
    116117                                VBVACMDHDR cmd_hdr;
     
    297298
    298299/**
     300 * Our refresh timer call-back.  Only used for guests without dirty rectangle
     301 * support.
     302 */
     303static void vbox_refresh_timer(struct work_struct *work)
     304{
     305        struct vbox_private *vbox = container_of(work, struct vbox_private,
     306                                                                                                 refresh_work.work);
     307        bool have_unblanked = false;
     308        struct drm_crtc *crtci;
     309
     310        if (!vbox->need_refresh_timer)
     311                return;
     312        list_for_each_entry(crtci, &vbox->dev->mode_config.crtc_list, head) {
     313                struct vbox_crtc *vbox_crtc = to_vbox_crtc(crtci);
     314                if (crtci->enabled && !vbox_crtc->blanked)
     315                        have_unblanked = true;
     316        }
     317        if (!have_unblanked)
     318                return;
     319        /* This forces a full refresh. */
     320        vbox_enable_accel(vbox);
     321        /* Schedule the next timer iteration. */
     322        schedule_delayed_work(&vbox->refresh_work, VBOX_REFRESH_PERIOD);
     323}
     324
     325/**
    299326 * Set up our heaps and data exchange buffers in VRAM before handing the rest
    300327 * to the memory manager.
     
    342369                return -ENOMEM;
    343370
    344         return vbox_accel_init(vbox);
     371        ret = vbox_accel_init(vbox);
     372        if (ret)
     373                return ret;
     374        /* Set up the refresh timer for users which do not send dirty rectangles. */
     375        INIT_DELAYED_WORK(&vbox->refresh_work, vbox_refresh_timer);
     376        return 0;
    345377}
    346378
    347379static void vbox_hw_fini(struct vbox_private *vbox)
    348380{
     381        vbox->need_refresh_timer = false;
     382        cancel_delayed_work(&vbox->refresh_work);
    349383        vbox_accel_fini(vbox);
    350384        kfree(vbox->last_mode_hints);
  • trunk/src/VBox/Additions/linux/drm/vbox_mode.c

    r74401 r74581  
    160160        case DRM_MODE_DPMS_ON:
    161161                vbox_crtc->blanked = false;
     162                /* Restart the refresh timer if necessary. */
     163                schedule_delayed_work(&vbox->refresh_work, VBOX_REFRESH_PERIOD);
    162164                break;
    163165        case DRM_MODE_DPMS_STANDBY:
     
    568570                return drm_add_modes_noedid(connector, 800, 600);
    569571        }
     572        /* Also assume that a client which supports hot-plugging also knows
     573         * how to update the screen in a way we can use, the only known
     574         * relevent client which cannot is Plymouth in Ubuntu 14.04. */
     575        vbox->need_refresh_timer = false;
    570576        num_modes = drm_add_modes_noedid(connector, 2560, 1600);
    571577        preferred_width = vbox_connector->mode_hint.width ?
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