modesetting: Implement PRIME syncing as a sink
Implements (Enable/Disable)SharedPixmapFlipping and SharedPixmapNotifyDamage, the sink functions for PRIME synchronization and double buffering. Allows modesetting driver to be used as a sink with PRIME synchronization. Changes dispatch_slave_dirty to flush damage from both scanout pixmaps. Changes drmmode_set_scanout_pixmap*() functions to drmmode_set_target_scanout_pixmap*() that take an additional parameter PixmapPtr *target. Then, treat *target as it did prime_pixmap. This allows me to use it to explicitly set both prime_pixmap and prime_pixmap_back individually. drmmode_set_scanout_pixmap() without the extra parameter remains to cover the single-buffered case, but only works if we aren't already double buffered. driver.c: Add plumbing for rr(Enable/Disable)SharedPixmapFlipping and SharedPixmapNotifyDamage. Change dispatch_dirty_crtc to dispatch_dirty_pixmap, which functions the same but flushes damage associated with a ppriv instead of the crtc, and chanage dispatch_slave_dirty to use it on both scanout pixmaps if applicable. drmmode_display.h: Add flip_seq field to msPixmapPrivRec to keep track of the event handler associated with a given pixmap, if any. Add wait_for_damage field to msPixmapPrivRec to keep track if we have requested a damage notification from the source. Add enable_flipping field to drmmode_crtc_private_rec to keep track if flipping is enabled or disabled. Add prime_pixmap_back to drmmode_crtc_private_rec to keep track of back buffer internally. Add declarations for drmmode_SetupPageFlipFence(), drmmode_EnableSharedPixmapFlipping(), drmmode_DisableSharedPixmapFlipping, drmmode_SharedPixmapFlip(), and drmmode_SharedPixmapPresentOnVBlank(). Move slave damage from crtc to ppriv. drmmode_display.c: Change drmmode_set_scanout_pixmap*() functions to drmmode_set_target_scanout_pixmap*() that take an additional parameter PixmapPtr *target for explicitly setting different scanout pixmaps. Add definitions for functions drmmode_SharedPixmapFlip(), drmmode_SharedPixmapPresentOnVBlank(), drmmode_SharedPixmapPresent(), drmmode_SharedPixmapVBlankEventHandler(), drmmode_SharedPixmapVBlankEventAbort(), drmmode_EnableSharedPixmapFlipping(), and drmmode_DisableSharedPixmapFlipping, drmmode_InitSharedPixmapFlipping(), and drmmode_FiniSharedPixmapFlipping, along with struct vblank_event_args. The control flow is as follows: pScrPriv->rrEnableSharedPixmapFlipping() makes its way to drmmode_EnableSharedPixmapFlipping(), which sets enable_flipping to TRUE and sets both scanout pixmaps prime_pixmap and prime_pixmap_back. When setting a mode, if prime_pixmap is defined, modesetting driver will call drmmode_InitSharedPixmapFlipping(), which if flipping is enabled will call drmmode_SharedPixmapPresent() on scanout_pixmap_back. drmmode_SharedPixmapPresent() requests that for the source to present on the given buffer using master->PresentSharedPixmap(). If it succeeds, it will then attempt to flip to that buffer using drmmode_SharedPixmapFlip(). Flipping shouldn't fail, but if it does, it will raise a warning and try drmmode_SharedPixmapPresent() again on the next vblank using drmmode_SharedPixmapPresentOnVBlank(). master->PresentSharedPixmap() could fail, in most cases because there is no outstanding damage on the mscreenpix tracked by the shared pixmap. In this case, drmmode_SharedPixmapPresent() will attempt to use master->RequestSharedPixmapNotifyDamage() to request for the source driver to call slave->SharedPixmapNotifyDamage() in response to damage on mscreenpix. This will ultimately call into drmmode_SharedPixmapPresentOnVBlank() to retry drmmode_SharedPixmapPresent() on the next vblank after accumulating damage. drmmode_SharedPixmapFlip() sets up page flip event handler by packing struct vblank_event_args with the necessary parameters, and registering drmmode_SharedPixmapVBlankEventHandler() and drmmode_SharedPixmapVBlankEventAbort() with the modesetting DRM event handler queue. Then, it uses the drmModePageFlip() to flip on the next vblank and raise an event. drmmode_SharedPixmapPresentOnVBlank() operates similarly to drmmode_SharedPixmapFlip(), but uses drmWaitVBlank() instead of drmModePageFlip() to raise the event without flipping. On the next vblank, DRM will raise an event that will ultimately be handled by drmmode_SharedPixmapVBlankEventHandler(). If we flipped, it will update prime_pixmap and prime_pixmap_back to reflect that frontTarget is now being displayed, and use drmmode_SharedPixmapPresent(backTarget) to start the process again on the now-hidden shared pixmap. If we didn't flip, it will just use drmmode_SharedPixmapPresent(frontTarget) to start the process again on the still-hidden shared pixmap. Note that presentation generally happens asynchronously, so with these changes alone tearing is reduced, but we can't always guarantee that the present will finish before the flip. These changes are meant to be paired with changes to the sink DRM driver that makes flips wait on fences attached to dmabuf backed buffers. The source driver is responsible for attaching the fences and signaling them when presentation is finished. Note that because presentation is requested in response to a vblank, PRIME sources will now conform to the sink's refresh rate. At teardown, pScrPriv->rrDisableSharedPixmapFlipping() will be called, making its way to drmmode_FiniSharedPixmapFlipping(). There, the event handlers for prime_pixmap and prime_pixmap_back are aborted, freeing the left over parameter structure. Then, prime_pixmap and prime_pixmap back are unset as scanout pixmaps. Register and tear down slave damage per-scanout pixmap instead of per-crtc. v1: Initial commit v2: Renamed PresentTrackedFlippingPixmap to PresentSharedPixmap Renamed flipSeq to flip_seq Warn if flip failed Use SharedPixmapNotifyDamage to retry on next vblank after damage v3: Refactor to accomodate moving (rr)StartFlippingPixmapTracking and (rr)(Enable/Disable)SharedPixmapFlipping to rrScrPrivRec from ScreenRec Do damage tracking on both scanout pixmaps v4: Tweaks to commit message v5: Revise for internal storage of prime pixmap ptrs Move disabling for reverse PRIME from source commit to here Use drmmode_set_target_scanout_pixmap*() to set scanout pixmaps internally to EnableSharedPixmapFlipping(). Don't support flipping if ms->drmmode.pageflip == FALSE. Move flipping_active check to this commit v6: Rebase onto ToT v7: Unchanged Reviewed-by:Dave Airlie <airlied@redhat.com> Signed-off-by:
Alex Goins <agoins@nvidia.com>
Showing
- hw/xfree86/drivers/modesetting/driver.c 83 additions, 13 deletionshw/xfree86/drivers/modesetting/driver.c
- hw/xfree86/drivers/modesetting/drmmode_display.c 273 additions, 24 deletionshw/xfree86/drivers/modesetting/drmmode_display.c
- hw/xfree86/drivers/modesetting/drmmode_display.h 18 additions, 1 deletionhw/xfree86/drivers/modesetting/drmmode_display.h
Loading
Please register or sign in to comment