xserver: Branch 'master' - 10 commits
Adam Jackson
ajax at kemper.freedesktop.org
Tue Jun 28 16:57:26 UTC 2016
hw/xfree86/drivers/modesetting/driver.c | 277 +++++++++++++++++-
hw/xfree86/drivers/modesetting/drmmode_display.c | 338 ++++++++++++++++++++---
hw/xfree86/drivers/modesetting/drmmode_display.h | 28 +
hw/xfree86/modes/xf86Crtc.h | 4
hw/xfree86/modes/xf86RandR12.c | 4
include/scrnintstr.h | 14
randr/randrstr.h | 18 +
randr/rrcrtc.c | 131 +++++++-
8 files changed, 726 insertions(+), 88 deletions(-)
New commits:
commit b83dede9cb930cf55249ad8e935f3c4d4328e2d9
Author: Alex Goins <agoins at nvidia.com>
Date: Thu Jun 16 20:06:56 2016 -0700
modesetting: Implement PRIME syncing as a source
Implements (Start/Stop)FlippingPixmapTracking, PresentSharedPixmap, and
RequestSharedPixmapNotifyDamage, the source functions for PRIME
synchronization and double buffering. Allows modesetting driver to be used
as a source with PRIME synchronization.
v1: N/A
v2: N/A
v3: N/A
v4: Initial commit
v5: Move disabling of reverse PRIME on sink to sink commit
v6: Rebase onto ToT
v7: Unchanged
Reviewed-by: Dave Airlie <airlied at redhat.com>
Signed-off-by: Alex Goins <agoins at nvidia.com>
diff --git a/hw/xfree86/drivers/modesetting/driver.c b/hw/xfree86/drivers/modesetting/driver.c
index 160cbc9..256ca95 100644
--- a/hw/xfree86/drivers/modesetting/driver.c
+++ b/hw/xfree86/drivers/modesetting/driver.c
@@ -577,6 +577,8 @@ redisplay_dirty(ScreenPtr screen, PixmapDirtyUpdatePtr dirty)
static void
ms_dirty_update(ScreenPtr screen)
{
+ modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(screen));
+
RegionPtr region;
PixmapDirtyUpdatePtr ent;
@@ -586,12 +588,42 @@ ms_dirty_update(ScreenPtr screen)
xorg_list_for_each_entry(ent, &screen->pixmap_dirty_list, ent) {
region = DamageRegion(ent->damage);
if (RegionNotEmpty(region)) {
+ msPixmapPrivPtr ppriv =
+ msGetPixmapPriv(&ms->drmmode, ent->slave_dst);
+
+ if (ppriv->notify_on_damage) {
+ ppriv->notify_on_damage = FALSE;
+
+ ent->slave_dst->drawable.pScreen->
+ SharedPixmapNotifyDamage(ent->slave_dst);
+ }
+
+ /* Requested manual updating */
+ if (ppriv->defer_dirty_update)
+ continue;
+
redisplay_dirty(screen, ent);
DamageEmpty(ent->damage);
}
}
}
+static PixmapDirtyUpdatePtr
+ms_dirty_get_ent(ScreenPtr screen, PixmapPtr slave_dst)
+{
+ PixmapDirtyUpdatePtr ent;
+
+ if (xorg_list_is_empty(&screen->pixmap_dirty_list))
+ return NULL;
+
+ xorg_list_for_each_entry(ent, &screen->pixmap_dirty_list, ent) {
+ if (ent->slave_dst == slave_dst)
+ return ent;
+ }
+
+ return NULL;
+}
+
static void
msBlockHandler(ScreenPtr pScreen, void *pTimeout, void *pReadmask)
{
@@ -1017,6 +1049,90 @@ msDisableSharedPixmapFlipping(RRCrtcPtr crtc)
}
static Bool
+msStartFlippingPixmapTracking(RRCrtcPtr crtc, PixmapPtr src,
+ PixmapPtr slave_dst1, PixmapPtr slave_dst2,
+ int x, int y, int dst_x, int dst_y,
+ Rotation rotation)
+{
+ ScreenPtr pScreen = src->drawable.pScreen;
+ modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(pScreen));
+
+ msPixmapPrivPtr ppriv1 = msGetPixmapPriv(&ms->drmmode, slave_dst1),
+ ppriv2 = msGetPixmapPriv(&ms->drmmode, slave_dst2);
+
+ if (!PixmapStartDirtyTracking(src, slave_dst1, x, y,
+ dst_x, dst_y, rotation)) {
+ return FALSE;
+ }
+
+ if (!PixmapStartDirtyTracking(src, slave_dst2, x, y,
+ dst_x, dst_y, rotation)) {
+ PixmapStopDirtyTracking(src, slave_dst1);
+ return FALSE;
+ }
+
+ ppriv1->slave_src = src;
+ ppriv2->slave_src = src;
+
+ ppriv1->dirty = ms_dirty_get_ent(pScreen, slave_dst1);
+ ppriv2->dirty = ms_dirty_get_ent(pScreen, slave_dst2);
+
+ ppriv1->defer_dirty_update = TRUE;
+ ppriv2->defer_dirty_update = TRUE;
+
+ return TRUE;
+}
+
+static Bool
+msPresentSharedPixmap(PixmapPtr slave_dst)
+{
+ ScreenPtr pScreen = slave_dst->drawable.pScreen;
+ modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(pScreen));
+
+ msPixmapPrivPtr ppriv = msGetPixmapPriv(&ms->drmmode, slave_dst);
+
+ RegionPtr region = DamageRegion(ppriv->dirty->damage);
+
+ if (RegionNotEmpty(region)) {
+ redisplay_dirty(ppriv->slave_src->drawable.pScreen, ppriv->dirty);
+ DamageEmpty(ppriv->dirty->damage);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static Bool
+msStopFlippingPixmapTracking(PixmapPtr src,
+ PixmapPtr slave_dst1, PixmapPtr slave_dst2)
+{
+ ScreenPtr pScreen = src->drawable.pScreen;
+ modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(pScreen));
+
+ msPixmapPrivPtr ppriv1 = msGetPixmapPriv(&ms->drmmode, slave_dst1),
+ ppriv2 = msGetPixmapPriv(&ms->drmmode, slave_dst2);
+
+ Bool ret = TRUE;
+
+ ret &= PixmapStopDirtyTracking(src, slave_dst1);
+ ret &= PixmapStopDirtyTracking(src, slave_dst2);
+
+ if (ret) {
+ ppriv1->slave_src = NULL;
+ ppriv2->slave_src = NULL;
+
+ ppriv1->dirty = NULL;
+ ppriv2->dirty = NULL;
+
+ ppriv1->defer_dirty_update = FALSE;
+ ppriv2->defer_dirty_update = FALSE;
+ }
+
+ return ret;
+}
+
+static Bool
CreateScreenResources(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
@@ -1083,6 +1199,8 @@ CreateScreenResources(ScreenPtr pScreen)
pScrPriv->rrEnableSharedPixmapFlipping = msEnableSharedPixmapFlipping;
pScrPriv->rrDisableSharedPixmapFlipping = msDisableSharedPixmapFlipping;
+ pScrPriv->rrStartFlippingPixmapTracking = msStartFlippingPixmapTracking;
+
return ret;
}
@@ -1146,6 +1264,20 @@ msSetSharedPixmapBacking(PixmapPtr ppix, void *fd_handle)
}
static Bool
+msRequestSharedPixmapNotifyDamage(PixmapPtr ppix)
+{
+ ScreenPtr screen = ppix->drawable.pScreen;
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ modesettingPtr ms = modesettingPTR(scrn);
+
+ msPixmapPrivPtr ppriv = msGetPixmapPriv(&ms->drmmode, ppix);
+
+ ppriv->notify_on_damage = TRUE;
+
+ return TRUE;
+}
+
+static Bool
msSharedPixmapNotifyDamage(PixmapPtr ppix)
{
Bool ret = FALSE;
@@ -1343,6 +1475,11 @@ ScreenInit(ScreenPtr pScreen, int argc, char **argv)
pScreen->StopPixmapTracking = PixmapStopDirtyTracking;
pScreen->SharedPixmapNotifyDamage = msSharedPixmapNotifyDamage;
+ pScreen->RequestSharedPixmapNotifyDamage =
+ msRequestSharedPixmapNotifyDamage;
+
+ pScreen->PresentSharedPixmap = msPresentSharedPixmap;
+ pScreen->StopFlippingPixmapTracking = msStopFlippingPixmapTracking;
if (!xf86CrtcScreenInit(pScreen))
return FALSE;
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.h b/hw/xfree86/drivers/modesetting/drmmode_display.h
index 3161bba..6d2c0a4 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.h
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.h
@@ -152,9 +152,15 @@ typedef struct _msPixmapPriv {
DamagePtr slave_damage;
- /** Fields for flipping shared pixmaps */
+ /** Sink fields for flipping shared pixmaps */
int flip_seq; /* seq of current page flip event handler */
Bool wait_for_damage; /* if we have requested damage notification from source */
+
+ /** Source fields for flipping shared pixmaps */
+ Bool defer_dirty_update; /* if we want to manually update */
+ PixmapDirtyUpdatePtr dirty; /* cached dirty ent to avoid searching list */
+ PixmapPtr slave_src; /* if we exported shared pixmap, dirty tracking src */
+ Bool notify_on_damage; /* if sink has requested damage notification */
} msPixmapPrivRec, *msPixmapPrivPtr;
extern DevPrivateKeyRec msPixmapPrivateKeyRec;
commit 44cb9578c0e5e10568826bc3ecbed97d358bba3c
Author: Alex Goins <agoins at nvidia.com>
Date: Thu Jun 16 20:06:55 2016 -0700
modesetting: Disable Reverse PRIME for i915
Reverse PRIME seems to be designed with discrete graphics as a sink in
mind, designed to do an extra copy from sysmem to vidmem to prevent a
discrete chip from needing to scan out from sysmem.
The criteria it used to detect this case is if we are a GPU screen and
Glamor accelerated. It's possible for i915 to fulfill these conditions,
despite the fact that the additional copy doesn't make sense for i915.
Normally, you could just set AccelMethod = none as an option for the device
and call it a day. However, when running with modesetting as both the sink
and the source, Glamor must be enabled.
Ideally, you would be able to set AccelMethod individually for devices
using the same driver, but there seems to be a bug in X option parsing that
makes all devices on a driver inherit the options from the first detected
device. Thus, glamor needs to be enabled for all or for none until that bug
(if it's even a bug) is fixed.
Nonetheless, it probably doesn't make sense to do the extra copy on i915
even if Glamor is enabled for the device, so this is more user friendly by
not requiring users to disable acceleration for i915.
v1: N/A
v2: N/A
v3: N/A
v4: Initial commit
v5: Unchanged
v6: Rebase onto ToT
v7: NULL check and free drmVersionPtr
Reviewed-by: Dave Airlie <airlied at redhat.com>
Signed-off-by: Alex Goins <agoins at nvidia.com>
diff --git a/hw/xfree86/drivers/modesetting/driver.c b/hw/xfree86/drivers/modesetting/driver.c
index 2d66a4b..160cbc9 100644
--- a/hw/xfree86/drivers/modesetting/driver.c
+++ b/hw/xfree86/drivers/modesetting/driver.c
@@ -1385,9 +1385,22 @@ ScreenInit(ScreenPtr pScreen, int argc, char **argv)
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Failed to initialize the Present extension.\n");
}
- /* enable reverse prime if we are a GPU screen, and accelerated */
- if (pScreen->isGPU)
+ /* enable reverse prime if we are a GPU screen, and accelerated, and not
+ * i915. i915 is happy scanning out from sysmem. */
+ if (pScreen->isGPU) {
+ drmVersionPtr version;
+
+ /* enable if we are an accelerated GPU screen */
ms->drmmode.reverse_prime_offload_mode = TRUE;
+
+ /* disable if we detect i915 */
+ if ((version = drmGetVersion(ms->drmmode.fd))) {
+ if (!strncmp("i915", version->name, version->name_len)) {
+ ms->drmmode.reverse_prime_offload_mode = FALSE;
+ }
+ drmFreeVersion(version);
+ }
+ }
}
#endif
commit f6fef2a171366156c4c6807de7fe086f04f41b7b
Author: Alex Goins <agoins at nvidia.com>
Date: Thu Jun 16 20:06:54 2016 -0700
modesetting: Blacklist USB transport devices from PRIME sync
UDL (USB 2.0 DisplayLink DRM driver) and other drivers for USB transport devices
have strange semantics when it comes to vblank events, due to their inability to
get the actual vblank info.
When doing a page flip, UDL instantly raises a vblank event without waiting for
vblank. It also has no support for DRM_IOCTL_WAIT_VBLANK, and has some strange
behavior with how it handles damage when page flipping.
It's possible to get something semi-working by hacking around these issues,
but even then there isn't much value-add vs single buffered PRIME, and it
reduces maintainability and adds additional risks to the modesetting driver
when running with more well-behaved DRM drivers.
Work needs to be done on UDL in order to properly support synchronized
PRIME. For now, just blacklist it, causing RandR to fall back to
unsynchronized PRIME.
This patch originally blacklisted UDL by name, but it was pointed out that there
are other USB transport device drivers with similar limitations, so it was
expanded to blacklist all USB transport devices.
v1: N/A
v2: N/A
v3: Initial commit
v4: Move check to driver.c for consistency/visibility
v5: Refactor to accomodate earlier changes
v6: Rebase onto ToT
v7: Expand to blacklist all USB transport devices, not just UDL
Signed-off-by: Alex Goins <agoins at nvidia.com>
Reviewed-by: Hans de Goede <hdegoede at redhat.com>
Reviewed-by: Dave Airlie <airlied at redhat.com>
diff --git a/hw/xfree86/drivers/modesetting/driver.c b/hw/xfree86/drivers/modesetting/driver.c
index ab3b028..2d66a4b 100644
--- a/hw/xfree86/drivers/modesetting/driver.c
+++ b/hw/xfree86/drivers/modesetting/driver.c
@@ -973,6 +973,7 @@ msEnableSharedPixmapFlipping(RRCrtcPtr crtc, PixmapPtr front, PixmapPtr back)
ScreenPtr screen = crtc->pScreen;
ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
modesettingPtr ms = modesettingPTR(scrn);
+ EntityInfoPtr pEnt = ms->pEnt;
xf86CrtcPtr xf86Crtc = crtc->devPrivate;
if (!xf86Crtc)
@@ -986,6 +987,19 @@ msEnableSharedPixmapFlipping(RRCrtcPtr crtc, PixmapPtr front, PixmapPtr back)
if (ms->drmmode.reverse_prime_offload_mode)
return FALSE;
+#if XSERVER_PLATFORM_BUS
+ if (pEnt->location.type == BUS_PLATFORM) {
+ char *syspath =
+ xf86_platform_device_odev_attributes(pEnt->location.id.plat)->
+ syspath;
+
+ /* Not supported for devices using USB transport due to misbehaved
+ * vblank events */
+ if (syspath && strstr(syspath, "usb"))
+ return FALSE;
+ }
+#endif
+
return drmmode_EnableSharedPixmapFlipping(xf86Crtc, &ms->drmmode,
front, back);
}
commit 500853086dd5fbfe6d2b3e30923fdc4d8c262cf0
Author: Alex Goins <agoins at nvidia.com>
Date: Thu Jun 16 20:06:53 2016 -0700
modesetting: Suspend and resume flipping with DPMS
DPMS would prevent page flip / vblank events from being raised, freezing
the screen until PRIME flipping was reinitialized. To handle DPMS cleanly,
suspend PRIME page flipping when DPMS mode is not on, and resume it when
DPMS mode is on.
v1: Initial commit
v2: Moved flipping_active check from previous commit to here
v3: Unchanged
v4: Unchanged
v5: Move flipping_active check to sink support commit
v6: Rebase onto ToT
v7: Unchanged
Reviewed-by: Dave Airlie <airlied at redhat.com>
Signed-off-by: Alex Goins <agoins at nvidia.com>
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c
index 2915b78..fb93348 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.c
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.c
@@ -1405,12 +1405,22 @@ drmmode_output_dpms(xf86OutputPtr output, int mode)
drmModeConnectorSetProperty(drmmode->fd, koutput->connector_id,
drmmode_output->dpms_enum_id, mode);
- if (mode == DPMSModeOn && crtc) {
+ if (crtc) {
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
- if (drmmode_crtc->need_modeset)
- drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation,
- crtc->x, crtc->y);
+
+ if (mode == DPMSModeOn) {
+ if (drmmode_crtc->need_modeset)
+ drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation,
+ crtc->x, crtc->y);
+
+ if (drmmode_crtc->enable_flipping)
+ drmmode_InitSharedPixmapFlipping(crtc, drmmode_crtc->drmmode);
+ } else {
+ if (drmmode_crtc->enable_flipping)
+ drmmode_FiniSharedPixmapFlipping(crtc, drmmode_crtc->drmmode);
+ }
}
+
return;
}
commit 80e64dae8af1eb3bb225b00fd800c6924883cf46
Author: Alex Goins <agoins at nvidia.com>
Date: Thu Jun 16 20:06:52 2016 -0700
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 at redhat.com>
Signed-off-by: Alex Goins <agoins at nvidia.com>
diff --git a/hw/xfree86/drivers/modesetting/driver.c b/hw/xfree86/drivers/modesetting/driver.c
index 97a7404..ab3b028 100644
--- a/hw/xfree86/drivers/modesetting/driver.c
+++ b/hw/xfree86/drivers/modesetting/driver.c
@@ -529,20 +529,14 @@ dispatch_dirty(ScreenPtr pScreen)
}
static void
-dispatch_dirty_crtc(ScrnInfoPtr scrn, xf86CrtcPtr crtc)
+dispatch_dirty_pixmap(ScrnInfoPtr scrn, xf86CrtcPtr crtc, PixmapPtr ppix)
{
modesettingPtr ms = modesettingPTR(scrn);
- drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
- PixmapPtr pixmap = drmmode_crtc->prime_pixmap;
- DamagePtr damage = drmmode_crtc->slave_damage;
- msPixmapPrivPtr ppriv = msGetPixmapPriv(&ms->drmmode, pixmap);
+ msPixmapPrivPtr ppriv = msGetPixmapPriv(&ms->drmmode, ppix);
+ DamagePtr damage = ppriv->slave_damage;
int fb_id = ppriv->fb_id;
- int ret;
-
- ret = dispatch_dirty_region(scrn, pixmap, damage, fb_id);
- if (ret) {
- }
+ dispatch_dirty_region(scrn, ppix, damage, fb_id);
}
static void
@@ -558,10 +552,11 @@ dispatch_slave_dirty(ScreenPtr pScreen)
if (!drmmode_crtc)
continue;
- if (!drmmode_crtc->prime_pixmap)
- continue;
- dispatch_dirty_crtc(scrn, crtc);
+ if (drmmode_crtc->prime_pixmap)
+ dispatch_dirty_pixmap(scrn, crtc, drmmode_crtc->prime_pixmap);
+ if (drmmode_crtc->prime_pixmap_back)
+ dispatch_dirty_pixmap(scrn, crtc, drmmode_crtc->prime_pixmap_back);
}
}
@@ -973,9 +968,45 @@ msUpdatePacked(ScreenPtr pScreen, shadowBufPtr pBuf)
}
static Bool
+msEnableSharedPixmapFlipping(RRCrtcPtr crtc, PixmapPtr front, PixmapPtr back)
+{
+ ScreenPtr screen = crtc->pScreen;
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ modesettingPtr ms = modesettingPTR(scrn);
+ xf86CrtcPtr xf86Crtc = crtc->devPrivate;
+
+ if (!xf86Crtc)
+ return FALSE;
+
+ /* Not supported if we can't flip */
+ if (!ms->drmmode.pageflip)
+ return FALSE;
+
+ /* Not currently supported with reverse PRIME */
+ if (ms->drmmode.reverse_prime_offload_mode)
+ return FALSE;
+
+ return drmmode_EnableSharedPixmapFlipping(xf86Crtc, &ms->drmmode,
+ front, back);
+}
+
+static void
+msDisableSharedPixmapFlipping(RRCrtcPtr crtc)
+{
+ ScreenPtr screen = crtc->pScreen;
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ modesettingPtr ms = modesettingPTR(scrn);
+ xf86CrtcPtr xf86Crtc = crtc->devPrivate;
+
+ if (xf86Crtc)
+ drmmode_DisableSharedPixmapFlipping(xf86Crtc, &ms->drmmode);
+}
+
+static Bool
CreateScreenResources(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
+ rrScrPrivPtr pScrPriv = rrGetScrPriv(pScreen);
modesettingPtr ms = modesettingPTR(pScrn);
PixmapPtr rootPixmap;
Bool ret;
@@ -1034,6 +1065,10 @@ CreateScreenResources(ScreenPtr pScreen)
return FALSE;
}
}
+
+ pScrPriv->rrEnableSharedPixmapFlipping = msEnableSharedPixmapFlipping;
+ pScrPriv->rrDisableSharedPixmapFlipping = msDisableSharedPixmapFlipping;
+
return ret;
}
@@ -1097,6 +1132,39 @@ msSetSharedPixmapBacking(PixmapPtr ppix, void *fd_handle)
}
static Bool
+msSharedPixmapNotifyDamage(PixmapPtr ppix)
+{
+ Bool ret = FALSE;
+ int c;
+
+ ScreenPtr screen = ppix->drawable.pScreen;
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ modesettingPtr ms = modesettingPTR(scrn);
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+
+ msPixmapPrivPtr ppriv = msGetPixmapPriv(&ms->drmmode, ppix);
+
+ if (!ppriv->wait_for_damage)
+ return ret;
+ ppriv->wait_for_damage = FALSE;
+
+ for (c = 0; c < xf86_config->num_crtc; c++) {
+ xf86CrtcPtr crtc = xf86_config->crtc[c];
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
+ if (!drmmode_crtc)
+ continue;
+ if (!(drmmode_crtc->prime_pixmap && drmmode_crtc->prime_pixmap_back))
+ continue;
+
+ // Received damage on master screen pixmap, schedule present on vblank
+ ret |= drmmode_SharedPixmapPresentOnVBlank(ppix, crtc, &ms->drmmode);
+ }
+
+ return ret;
+}
+
+static Bool
SetMaster(ScrnInfoPtr pScrn)
{
modesettingPtr ms = modesettingPTR(pScrn);
@@ -1260,6 +1328,8 @@ ScreenInit(ScreenPtr pScreen, int argc, char **argv)
pScreen->StartPixmapTracking = PixmapStartDirtyTracking;
pScreen->StopPixmapTracking = PixmapStopDirtyTracking;
+ pScreen->SharedPixmapNotifyDamage = msSharedPixmapNotifyDamage;
+
if (!xf86CrtcScreenInit(pScreen))
return FALSE;
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c
index cce9a33..2915b78 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.c
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.c
@@ -229,6 +229,239 @@ drmmode_SetSlaveBO(PixmapPtr ppix,
return TRUE;
}
+static Bool
+drmmode_SharedPixmapPresent(PixmapPtr ppix, xf86CrtcPtr crtc,
+ drmmode_ptr drmmode)
+{
+ ScreenPtr master = crtc->randr_crtc->pScreen->current_master;
+
+ if (master->PresentSharedPixmap(ppix)) {
+ /* Success, queue flip to back target */
+ if (drmmode_SharedPixmapFlip(ppix, crtc, drmmode))
+ return TRUE;
+
+ xf86DrvMsg(drmmode->scrn->scrnIndex, X_WARNING,
+ "drmmode_SharedPixmapFlip() failed, trying again next vblank\n");
+
+ return drmmode_SharedPixmapPresentOnVBlank(ppix, crtc, drmmode);
+ }
+
+ /* Failed to present, try again on next vblank after damage */
+ if (master->RequestSharedPixmapNotifyDamage) {
+ msPixmapPrivPtr ppriv = msGetPixmapPriv(drmmode, ppix);
+
+ /* Set flag first in case we are immediately notified */
+ ppriv->wait_for_damage = TRUE;
+
+ if (master->RequestSharedPixmapNotifyDamage(ppix))
+ return TRUE;
+ else
+ ppriv->wait_for_damage = FALSE;
+ }
+
+ /* Damage notification not available, just try again on vblank */
+ return drmmode_SharedPixmapPresentOnVBlank(ppix, crtc, drmmode);
+}
+
+struct vblank_event_args {
+ PixmapPtr frontTarget;
+ PixmapPtr backTarget;
+ xf86CrtcPtr crtc;
+ drmmode_ptr drmmode;
+ Bool flip;
+};
+static void
+drmmode_SharedPixmapVBlankEventHandler(uint64_t frame, uint64_t usec,
+ void *data)
+{
+ struct vblank_event_args *args = data;
+
+ drmmode_crtc_private_ptr drmmode_crtc = args->crtc->driver_private;
+
+ if (args->flip) {
+ /* frontTarget is being displayed, update crtc to reflect */
+ drmmode_crtc->prime_pixmap = args->frontTarget;
+ drmmode_crtc->prime_pixmap_back = args->backTarget;
+
+ /* Safe to present on backTarget, no longer displayed */
+ drmmode_SharedPixmapPresent(args->backTarget, args->crtc, args->drmmode);
+ } else {
+ /* backTarget is still being displayed, present on frontTarget */
+ drmmode_SharedPixmapPresent(args->frontTarget, args->crtc, args->drmmode);
+ }
+
+ free(args);
+}
+
+static void
+drmmode_SharedPixmapVBlankEventAbort(void *data)
+{
+ struct vblank_event_args *args = data;
+
+ msGetPixmapPriv(args->drmmode, args->frontTarget)->flip_seq = 0;
+
+ free(args);
+}
+
+Bool
+drmmode_SharedPixmapPresentOnVBlank(PixmapPtr ppix, xf86CrtcPtr crtc,
+ drmmode_ptr drmmode)
+{
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ msPixmapPrivPtr ppriv = msGetPixmapPriv(drmmode, ppix);
+
+ drmVBlank vbl;
+ struct vblank_event_args *event_args;
+
+ if (ppix == drmmode_crtc->prime_pixmap)
+ return FALSE; /* Already flipped to this pixmap */
+ if (ppix != drmmode_crtc->prime_pixmap_back)
+ return FALSE; /* Pixmap is not a scanout pixmap for CRTC */
+
+ event_args = calloc(1, sizeof(*event_args));
+ if (!event_args)
+ return FALSE;
+
+ event_args->frontTarget = ppix;
+ event_args->backTarget = drmmode_crtc->prime_pixmap;
+ event_args->crtc = crtc;
+ event_args->drmmode = drmmode;
+ event_args->flip = FALSE;
+
+ ppriv->flip_seq =
+ ms_drm_queue_alloc(crtc, event_args,
+ drmmode_SharedPixmapVBlankEventHandler,
+ drmmode_SharedPixmapVBlankEventAbort);
+
+ vbl.request.type =
+ DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT | drmmode_crtc->vblank_pipe;
+ vbl.request.sequence = 1;
+ vbl.request.signal = (unsigned long) ppriv->flip_seq;
+
+ return drmWaitVBlank(drmmode->fd, &vbl) >= 0;
+}
+
+Bool
+drmmode_SharedPixmapFlip(PixmapPtr frontTarget, xf86CrtcPtr crtc,
+ drmmode_ptr drmmode)
+{
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ msPixmapPrivPtr ppriv_front = msGetPixmapPriv(drmmode, frontTarget);
+
+ struct vblank_event_args *event_args;
+
+ event_args = calloc(1, sizeof(*event_args));
+ if (!event_args)
+ return FALSE;
+
+ event_args->frontTarget = frontTarget;
+ event_args->backTarget = drmmode_crtc->prime_pixmap;
+ event_args->crtc = crtc;
+ event_args->drmmode = drmmode;
+ event_args->flip = TRUE;
+
+ ppriv_front->flip_seq =
+ ms_drm_queue_alloc(crtc, event_args,
+ drmmode_SharedPixmapVBlankEventHandler,
+ drmmode_SharedPixmapVBlankEventAbort);
+
+ if (drmModePageFlip(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
+ ppriv_front->fb_id, DRM_MODE_PAGE_FLIP_EVENT,
+ (void *)(intptr_t) ppriv_front->flip_seq) < 0) {
+ ms_drm_abort_seq(crtc->scrn, ppriv_front->flip_seq);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static Bool
+drmmode_InitSharedPixmapFlipping(xf86CrtcPtr crtc, drmmode_ptr drmmode)
+{
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
+ if (!drmmode_crtc->enable_flipping)
+ return FALSE;
+
+ if (drmmode_crtc->flipping_active)
+ return TRUE;
+
+ drmmode_crtc->flipping_active =
+ drmmode_SharedPixmapPresent(drmmode_crtc->prime_pixmap_back,
+ crtc, drmmode);
+
+ return drmmode_crtc->flipping_active;
+}
+
+static void
+drmmode_FiniSharedPixmapFlipping(xf86CrtcPtr crtc, drmmode_ptr drmmode)
+{
+ uint32_t seq;
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
+ if (!drmmode_crtc->flipping_active)
+ return;
+
+ drmmode_crtc->flipping_active = FALSE;
+
+ /* Abort page flip event handler on prime_pixmap */
+ seq = msGetPixmapPriv(drmmode, drmmode_crtc->prime_pixmap)->flip_seq;
+ if (seq)
+ ms_drm_abort_seq(crtc->scrn, seq);
+
+ /* Abort page flip event handler on prime_pixmap_back */
+ seq = msGetPixmapPriv(drmmode,
+ drmmode_crtc->prime_pixmap_back)->flip_seq;
+ if (seq)
+ ms_drm_abort_seq(crtc->scrn, seq);
+}
+
+static Bool drmmode_set_target_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix,
+ PixmapPtr *target);
+
+Bool
+drmmode_EnableSharedPixmapFlipping(xf86CrtcPtr crtc, drmmode_ptr drmmode,
+ PixmapPtr front, PixmapPtr back)
+{
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
+ drmmode_crtc->enable_flipping = TRUE;
+
+ /* Set front scanout pixmap */
+ drmmode_crtc->enable_flipping &=
+ drmmode_set_target_scanout_pixmap(crtc, front,
+ &drmmode_crtc->prime_pixmap);
+ if (!drmmode_crtc->enable_flipping)
+ return FALSE;
+
+ /* Set back scanout pixmap */
+ drmmode_crtc->enable_flipping &=
+ drmmode_set_target_scanout_pixmap(crtc, back,
+ &drmmode_crtc->prime_pixmap_back);
+ if (!drmmode_crtc->enable_flipping) {
+ drmmode_set_target_scanout_pixmap(crtc, NULL,
+ &drmmode_crtc->prime_pixmap);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void
+drmmode_DisableSharedPixmapFlipping(xf86CrtcPtr crtc, drmmode_ptr drmmode)
+{
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
+ drmmode_crtc->enable_flipping = FALSE;
+
+ drmmode_FiniSharedPixmapFlipping(crtc, drmmode);
+
+ drmmode_set_target_scanout_pixmap(crtc, NULL, &drmmode_crtc->prime_pixmap);
+
+ drmmode_set_target_scanout_pixmap(crtc, NULL,
+ &drmmode_crtc->prime_pixmap_back);
+}
+
static void
drmmode_ConvertFromKMode(ScrnInfoPtr scrn,
drmModeModeInfo * kmode, DisplayModePtr mode)
@@ -499,6 +732,9 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
drmmode_crtc->need_modeset = FALSE;
crtc->funcs->dpms(crtc, DPMSModeOn);
+ if (drmmode_crtc->prime_pixmap_back)
+ drmmode_InitSharedPixmapFlipping(crtc, drmmode);
+
/* go through all the outputs and force DPMS them back on? */
for (i = 0; i < xf86_config->num_output; i++) {
xf86OutputPtr output = xf86_config->output[i];
@@ -629,7 +865,8 @@ drmmode_crtc_gamma_set(xf86CrtcPtr crtc, uint16_t * red, uint16_t * green,
}
static Bool
-drmmode_set_scanout_pixmap_gpu(xf86CrtcPtr crtc, PixmapPtr ppix)
+drmmode_set_target_scanout_pixmap_gpu(xf86CrtcPtr crtc, PixmapPtr ppix,
+ PixmapPtr *target)
{
ScreenPtr screen = xf86ScrnToScreen(crtc->scrn);
PixmapPtr screenpix = screen->GetScreenPixmap(screen);
@@ -638,13 +875,14 @@ drmmode_set_scanout_pixmap_gpu(xf86CrtcPtr crtc, PixmapPtr ppix)
drmmode_ptr drmmode = drmmode_crtc->drmmode;
int c, total_width = 0, max_height = 0, this_x = 0;
- if (drmmode_crtc->prime_pixmap) {
- PixmapStopDirtyTracking(drmmode_crtc->prime_pixmap, screenpix);
+ if (*target) {
+ PixmapStopDirtyTracking(*target, screenpix);
if (drmmode->fb_id) {
drmModeRmFB(drmmode->fd, drmmode->fb_id);
drmmode->fb_id = 0;
}
drmmode_crtc->prime_pixmap_x = 0;
+ *target = NULL;
}
if (!ppix)
@@ -679,41 +917,43 @@ drmmode_set_scanout_pixmap_gpu(xf86CrtcPtr crtc, PixmapPtr ppix)
}
drmmode_crtc->prime_pixmap_x = this_x;
PixmapStartDirtyTracking(ppix, screenpix, 0, 0, this_x, 0, RR_Rotate_0);
+ *target = ppix;
return TRUE;
}
static Bool
-drmmode_set_scanout_pixmap_cpu(xf86CrtcPtr crtc, PixmapPtr ppix)
+drmmode_set_target_scanout_pixmap_cpu(xf86CrtcPtr crtc, PixmapPtr ppix,
+ PixmapPtr *target)
{
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
drmmode_ptr drmmode = drmmode_crtc->drmmode;
msPixmapPrivPtr ppriv;
void *ptr;
- if (drmmode_crtc->prime_pixmap) {
- ppriv = msGetPixmapPriv(drmmode, drmmode_crtc->prime_pixmap);
+ if (*target) {
+ ppriv = msGetPixmapPriv(drmmode, *target);
drmModeRmFB(drmmode->fd, ppriv->fb_id);
ppriv->fb_id = 0;
- }
- if (drmmode_crtc->slave_damage) {
- DamageUnregister(drmmode_crtc->slave_damage);
- drmmode_crtc->slave_damage = NULL;
+ if (ppriv->slave_damage) {
+ DamageUnregister(ppriv->slave_damage);
+ ppriv->slave_damage = NULL;
+ }
}
if (!ppix)
return TRUE;
ppriv = msGetPixmapPriv(drmmode, ppix);
- if (!drmmode_crtc->slave_damage) {
- drmmode_crtc->slave_damage = DamageCreate(NULL, NULL,
- DamageReportNone,
- TRUE,
- crtc->randr_crtc->pScreen,
- NULL);
+ if (!ppriv->slave_damage) {
+ ppriv->slave_damage = DamageCreate(NULL, NULL,
+ DamageReportNone,
+ TRUE,
+ crtc->randr_crtc->pScreen,
+ NULL);
}
ptr = drmmode_map_slave_bo(drmmode, ppriv);
ppix->devPrivate.ptr = ptr;
- DamageRegister(&ppix->drawable, drmmode_crtc->slave_damage);
+ DamageRegister(&ppix->drawable, ppriv->slave_damage);
if (ppriv->fb_id == 0) {
drmModeAddFB(drmmode->fd, ppix->drawable.width,
@@ -722,25 +962,34 @@ drmmode_set_scanout_pixmap_cpu(xf86CrtcPtr crtc, PixmapPtr ppix)
ppix->drawable.bitsPerPixel,
ppix->devKind, ppriv->backing_bo->handle, &ppriv->fb_id);
}
+ *target = ppix;
return TRUE;
}
static Bool
-drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
+drmmode_set_target_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix,
+ PixmapPtr *target)
{
- Bool ret;
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
drmmode_ptr drmmode = drmmode_crtc->drmmode;
if (drmmode->reverse_prime_offload_mode)
- ret = drmmode_set_scanout_pixmap_gpu(crtc, ppix);
+ return drmmode_set_target_scanout_pixmap_gpu(crtc, ppix, target);
else
- ret = drmmode_set_scanout_pixmap_cpu(crtc, ppix);
+ return drmmode_set_target_scanout_pixmap_cpu(crtc, ppix, target);
+}
- if (ret)
- drmmode_crtc->prime_pixmap = ppix;
+static Bool
+drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
+{
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
- return ret;
+ /* Use DisableSharedPixmapFlipping before switching to single buf */
+ if (drmmode_crtc->enable_flipping)
+ return FALSE;
+
+ return drmmode_set_target_scanout_pixmap(crtc, ppix,
+ &drmmode_crtc->prime_pixmap);
}
static void *
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.h b/hw/xfree86/drivers/modesetting/drmmode_display.h
index 36c6e91..3161bba 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.h
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.h
@@ -99,12 +99,12 @@ typedef struct {
struct dumb_bo *cursor_bo;
Bool cursor_up;
uint16_t lut_r[256], lut_g[256], lut_b[256];
- DamagePtr slave_damage;
drmmode_bo rotate_bo;
unsigned rotate_fb_id;
PixmapPtr prime_pixmap;
+ PixmapPtr prime_pixmap_back;
unsigned prime_pixmap_x;
/**
@@ -120,6 +120,9 @@ typedef struct {
/** @} */
Bool need_modeset;
+
+ Bool enable_flipping;
+ Bool flipping_active;
} drmmode_crtc_private_rec, *drmmode_crtc_private_ptr;
typedef struct {
@@ -146,6 +149,12 @@ typedef struct {
typedef struct _msPixmapPriv {
uint32_t fb_id;
struct dumb_bo *backing_bo; /* if this pixmap is backed by a dumb bo */
+
+ DamagePtr slave_damage;
+
+ /** Fields for flipping shared pixmaps */
+ int flip_seq; /* seq of current page flip event handler */
+ Bool wait_for_damage; /* if we have requested damage notification from source */
} msPixmapPrivRec, *msPixmapPrivPtr;
extern DevPrivateKeyRec msPixmapPrivateKeyRec;
@@ -164,6 +173,14 @@ Bool drmmode_SetSlaveBO(PixmapPtr ppix,
drmmode_ptr drmmode,
int fd_handle, int pitch, int size);
+Bool drmmode_EnableSharedPixmapFlipping(xf86CrtcPtr crtc, drmmode_ptr drmmode,
+ PixmapPtr front, PixmapPtr back);
+Bool drmmode_SharedPixmapPresentOnVBlank(PixmapPtr frontTarget, xf86CrtcPtr crtc,
+ drmmode_ptr drmmode);
+Bool drmmode_SharedPixmapFlip(PixmapPtr frontTarget, xf86CrtcPtr crtc,
+ drmmode_ptr drmmode);
+void drmmode_DisableSharedPixmapFlipping(xf86CrtcPtr crtc, drmmode_ptr drmmode);
+
extern Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp);
void drmmode_adjust_frame(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int x, int y);
extern Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode, Bool set_hw);
commit 378c85a8848679eaa3c2881f3ba8b686e59df25e
Author: Alex Goins <agoins at nvidia.com>
Date: Thu Jun 16 20:06:51 2016 -0700
modesetting: Always load ms->drmmode.pageflip
ms->drmmode.pageflip was only loaded from options if ms->drmmode.glamor was
defined, otherwise it would always assume FALSE.
PRIME Synchronization requires ms->drmmode.pageflip even if we aren't using
glamor, so load it unconditionally.
v1: N/A
v2: N/A
v3: N/A
v4: N/A
v5: Initial commit
v6: Rebase onto ToT
v7: Unchanged
Reviewed-by: Dave Airlie <airlied at redhat.com>
Signed-off-by: Alex Goins <agoins at nvidia.com>
diff --git a/hw/xfree86/drivers/modesetting/driver.c b/hw/xfree86/drivers/modesetting/driver.c
index 0059e56..97a7404 100644
--- a/hw/xfree86/drivers/modesetting/driver.c
+++ b/hw/xfree86/drivers/modesetting/driver.c
@@ -873,10 +873,7 @@ PreInit(ScrnInfoPtr pScrn, int flags)
try_enable_glamor(pScrn);
- if (ms->drmmode.glamor) {
- ms->drmmode.pageflip =
- xf86ReturnOptValBool(ms->drmmode.Options, OPTION_PAGEFLIP, TRUE);
- } else {
+ if (!ms->drmmode.glamor) {
Bool prefer_shadow = TRUE;
ret = drmGetCap(ms->fd, DRM_CAP_DUMB_PREFER_SHADOW, &value);
@@ -892,10 +889,11 @@ PreInit(ScrnInfoPtr pScrn, int flags)
"ShadowFB: preferred %s, enabled %s\n",
prefer_shadow ? "YES" : "NO",
ms->drmmode.shadow_enable ? "YES" : "NO");
-
- ms->drmmode.pageflip = FALSE;
}
+ ms->drmmode.pageflip =
+ xf86ReturnOptValBool(ms->drmmode.Options, OPTION_PAGEFLIP, TRUE);
+
pScrn->capabilities = 0;
#ifdef DRM_CAP_PRIME
ret = drmGetCap(ms->fd, DRM_CAP_PRIME, &value);
commit b773a9c8126222e5fed2904d012fbf917a9f22fd
Author: Alex Goins <agoins at nvidia.com>
Date: Thu Jun 16 20:06:50 2016 -0700
modesetting: Always tear down scanout pixmap
drmmode_set_scanout_pixmap_(cpu/gpu) would only do teardown if ppix ==
NULL. This meant that if there were consecutive calls to
SetScanoutPixmap(ppix != NULL) without calls to SetScanoutPixmap(ppix ==
NULL) in between, earlier calls would be leaked. RRReplaceScanoutPixmap()
does this today.
Instead, when setting a scanout pixmap, always do teardown of the existing
scanout pixmap before setting up the new one. Then, if there is no new one
to set up, stop there.
This maintains the previous behavior in all cases except those with
multiple consecutive calls to SetScanoutPixmap(ppix != NULL).
v1: N/A
v2: N/A
v3: N/A
v4: N/A
v5: Initial commit
v6: Rebase onto ToT
v7: Unchanged
Reviewed-by: Dave Airlie <airlied at redhat.com>
Signed-off-by: Alex Goins <agoins at nvidia.com>
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c
index 89c468b..cce9a33 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.c
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.c
@@ -638,17 +638,18 @@ drmmode_set_scanout_pixmap_gpu(xf86CrtcPtr crtc, PixmapPtr ppix)
drmmode_ptr drmmode = drmmode_crtc->drmmode;
int c, total_width = 0, max_height = 0, this_x = 0;
- if (!ppix) {
- if (drmmode_crtc->prime_pixmap) {
- PixmapStopDirtyTracking(drmmode_crtc->prime_pixmap, screenpix);
- if (drmmode->fb_id) {
- drmModeRmFB(drmmode->fd, drmmode->fb_id);
- drmmode->fb_id = 0;
- }
+ if (drmmode_crtc->prime_pixmap) {
+ PixmapStopDirtyTracking(drmmode_crtc->prime_pixmap, screenpix);
+ if (drmmode->fb_id) {
+ drmModeRmFB(drmmode->fd, drmmode->fb_id);
+ drmmode->fb_id = 0;
}
drmmode_crtc->prime_pixmap_x = 0;
- return TRUE;
}
+
+ if (!ppix)
+ return TRUE;
+
/* iterate over all the attached crtcs to work out the bounding box */
for (c = 0; c < xf86_config->num_crtc; c++) {
xf86CrtcPtr iter = xf86_config->crtc[c];
@@ -689,18 +690,18 @@ drmmode_set_scanout_pixmap_cpu(xf86CrtcPtr crtc, PixmapPtr ppix)
msPixmapPrivPtr ppriv;
void *ptr;
- if (!ppix) {
- if (drmmode_crtc->prime_pixmap) {
- ppriv = msGetPixmapPriv(drmmode, drmmode_crtc->prime_pixmap);
- drmModeRmFB(drmmode->fd, ppriv->fb_id);
- ppriv->fb_id = 0;
- }
- if (drmmode_crtc->slave_damage) {
- DamageUnregister(drmmode_crtc->slave_damage);
- drmmode_crtc->slave_damage = NULL;
- }
- return TRUE;
+ if (drmmode_crtc->prime_pixmap) {
+ ppriv = msGetPixmapPriv(drmmode, drmmode_crtc->prime_pixmap);
+ drmModeRmFB(drmmode->fd, ppriv->fb_id);
+ ppriv->fb_id = 0;
}
+ if (drmmode_crtc->slave_damage) {
+ DamageUnregister(drmmode_crtc->slave_damage);
+ drmmode_crtc->slave_damage = NULL;
+ }
+
+ if (!ppix)
+ return TRUE;
ppriv = msGetPixmapPriv(drmmode, ppix);
if (!drmmode_crtc->slave_damage) {
commit f4c37eeee7953df1fe0e3196eda452acf0078e61
Author: Alex Goins <agoins at nvidia.com>
Date: Thu Jun 16 20:06:49 2016 -0700
modesetting: Internal storage of scanout pixmaps
modesetting relied on randr_crtc->scanout_pixmap being consistent with
calls to SetScanoutPixmap, which is very fragile and makes a lot of
assumptions about the caller's behavior.
For example, RRReplaceScanoutPixmap(), when dropping off with !size_fits,
will set randr_crtc->scanout_pixmap = NULL and then call SetScanoutPixmap.
Without this patch, drmmode_set_scanout_pixmap_(cpu/gpu) will think that
there is no scanout pixmap to tear down, because it's already been set to
NULL.
By keeping track of the scanout pixmap in its internal state, modesetting
can avoid these types of bugs and reduce constraints on calling
conventions.
v1: N/A
v2: N/A
v3: N/A
v4: N/A
v5: Initial commit
v6: Rebase onto ToT
v7: Unchanged
Reviewed-by: Dave Airlie <airlied at redhat.com>
Signed-off-by: Alex Goins <agoins at nvidia.com>
diff --git a/hw/xfree86/drivers/modesetting/driver.c b/hw/xfree86/drivers/modesetting/driver.c
index 1604044..0059e56 100644
--- a/hw/xfree86/drivers/modesetting/driver.c
+++ b/hw/xfree86/drivers/modesetting/driver.c
@@ -532,10 +532,10 @@ static void
dispatch_dirty_crtc(ScrnInfoPtr scrn, xf86CrtcPtr crtc)
{
modesettingPtr ms = modesettingPTR(scrn);
- PixmapPtr pixmap = crtc->randr_crtc->scanout_pixmap;
- msPixmapPrivPtr ppriv = msGetPixmapPriv(&ms->drmmode, pixmap);
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ PixmapPtr pixmap = drmmode_crtc->prime_pixmap;
DamagePtr damage = drmmode_crtc->slave_damage;
+ msPixmapPrivPtr ppriv = msGetPixmapPriv(&ms->drmmode, pixmap);
int fb_id = ppriv->fb_id;
int ret;
@@ -554,10 +554,11 @@ dispatch_slave_dirty(ScreenPtr pScreen)
for (c = 0; c < xf86_config->num_crtc; c++) {
xf86CrtcPtr crtc = xf86_config->crtc[c];
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
- if (!crtc->randr_crtc)
+ if (!drmmode_crtc)
continue;
- if (!crtc->randr_crtc->scanout_pixmap)
+ if (!drmmode_crtc->prime_pixmap)
continue;
dispatch_dirty_crtc(scrn, crtc);
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c
index 7e5901a..89c468b 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.c
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.c
@@ -454,10 +454,10 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
drmmode_ConvertToKMode(crtc->scrn, &kmode, mode);
fb_id = drmmode->fb_id;
- if (crtc->randr_crtc->scanout_pixmap) {
+ if (drmmode_crtc->prime_pixmap) {
if (!drmmode->reverse_prime_offload_mode) {
msPixmapPrivPtr ppriv =
- msGetPixmapPriv(drmmode, crtc->randr_crtc->scanout_pixmap);
+ msGetPixmapPriv(drmmode, drmmode_crtc->prime_pixmap);
fb_id = ppriv->fb_id;
x = 0;
} else
@@ -639,8 +639,8 @@ drmmode_set_scanout_pixmap_gpu(xf86CrtcPtr crtc, PixmapPtr ppix)
int c, total_width = 0, max_height = 0, this_x = 0;
if (!ppix) {
- if (crtc->randr_crtc->scanout_pixmap) {
- PixmapStopDirtyTracking(crtc->randr_crtc->scanout_pixmap, screenpix);
+ if (drmmode_crtc->prime_pixmap) {
+ PixmapStopDirtyTracking(drmmode_crtc->prime_pixmap, screenpix);
if (drmmode->fb_id) {
drmModeRmFB(drmmode->fd, drmmode->fb_id);
drmmode->fb_id = 0;
@@ -690,8 +690,8 @@ drmmode_set_scanout_pixmap_cpu(xf86CrtcPtr crtc, PixmapPtr ppix)
void *ptr;
if (!ppix) {
- if (crtc->randr_crtc->scanout_pixmap) {
- ppriv = msGetPixmapPriv(drmmode, crtc->randr_crtc->scanout_pixmap);
+ if (drmmode_crtc->prime_pixmap) {
+ ppriv = msGetPixmapPriv(drmmode, drmmode_crtc->prime_pixmap);
drmModeRmFB(drmmode->fd, ppriv->fb_id);
ppriv->fb_id = 0;
}
@@ -727,13 +727,19 @@ drmmode_set_scanout_pixmap_cpu(xf86CrtcPtr crtc, PixmapPtr ppix)
static Bool
drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
{
+ Bool ret;
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
drmmode_ptr drmmode = drmmode_crtc->drmmode;
if (drmmode->reverse_prime_offload_mode)
- return drmmode_set_scanout_pixmap_gpu(crtc, ppix);
+ ret = drmmode_set_scanout_pixmap_gpu(crtc, ppix);
else
- return drmmode_set_scanout_pixmap_cpu(crtc, ppix);
+ ret = drmmode_set_scanout_pixmap_cpu(crtc, ppix);
+
+ if (ret)
+ drmmode_crtc->prime_pixmap = ppix;
+
+ return ret;
}
static void *
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.h b/hw/xfree86/drivers/modesetting/drmmode_display.h
index 6b94641..36c6e91 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.h
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.h
@@ -103,7 +103,10 @@ typedef struct {
drmmode_bo rotate_bo;
unsigned rotate_fb_id;
+
+ PixmapPtr prime_pixmap;
unsigned prime_pixmap_x;
+
/**
* @{ MSC (vblank count) handling for the PRESENT extension.
*
commit 1bdbc7e764ed7bf7c1ae46287dec368aa7c7e80d
Author: Alex Goins <agoins at nvidia.com>
Date: Thu Jun 16 20:06:47 2016 -0700
randr/xf86: Add PRIME Synchronization / Double Buffer
Changes PRIME to use double buffering and synchronization if all required
driver functions are available.
rrcrtc.c:
Changes rrSetupPixmapSharing() to use double buffering and
synchronization in the case that all required driver functions are
available. Otherwise, falls back to unsynchronized single buffer.
Changes RRCrtcDetachScanoutPixmap() to properly clean up in the case of
double buffering.
Moves StopPixmapTracking() from rrDestroySharedPixmap() to
RRCrtcDetachScanoutPixmap().
Changes RRReplaceScanoutPixmap() to fail if we are using double buffering,
as it would need a second ppix parameter to function with double buffering,
and AFAICT no driver I've implemented double buffered source support in uses
RRReplaceScanoutPixmap().
randrstr.h:
Adds scanout_pixmap_back to struct _rrCrtc to facilitate PRIME
double buffering.
xf86Crtc.h:
Adds current_scanout_back to _xf86Crtc to facilitate detection
of changes to it in xf86RandR12CrtcSet().
xf86RandR12.c:
Changes xf86RandR12CrtcSet() to detect changes in
scanout_pixmap_back.
Adds scanout_pixmap_back to struct _rrCrtc to facilitate PRIME double
buffering.
v1: Initial commit
v2: Rename PresentTrackedFlippingPixmap to PresentSharedPixmap
v3: Refactor to accomodate moving (rr)StartFlippingPixmapTracking and
(rr)(Enable/Disable)SharedPixmapFlipping to rrScrPrivRec from ScreenRec
Add fallback if flipping funcs fail
v4: Detach scanout pixmap when destroying scanout_pixmap_back, to avoid
dangling pointers in some drivers
v5: Disable RRReplaceScanoutPixmap for double-buffered PRIME, it would need an
ABI change with support for 2 pixmaps if it were to be supported, but AFAICT
no driver that actually supports double-buffered PRIME uses it.
Refactor to use rrEnableSharedPixmapFlipping() as a substitute for
rrCrtcSetScanoutPixmap() in the flipping case.
Remove extraneous pSlaveScrPriv from DetachScanoutPixmap()
Remove extraneous protopix and pScrPriv from rrSetupPixmapSharing()
v6: Rebase onto ToT
v7: Unchanged
Reviewed-by: Dave Airlie <airlied at redhat.com>
Signed-off-by: Alex Goins <agoins at nvidia.com>
diff --git a/hw/xfree86/modes/xf86Crtc.h b/hw/xfree86/modes/xf86Crtc.h
index fb1dd4f..14ba9d7 100644
--- a/hw/xfree86/modes/xf86Crtc.h
+++ b/hw/xfree86/modes/xf86Crtc.h
@@ -405,6 +405,10 @@ struct _xf86Crtc {
/* Added in ABI version 5
*/
PixmapPtr current_scanout;
+
+ /* Added in ABI version 6
+ */
+ PixmapPtr current_scanout_back;
};
typedef struct _xf86OutputFuncs {
diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c
index 4a21766..9f93270 100644
--- a/hw/xfree86/modes/xf86RandR12.c
+++ b/hw/xfree86/modes/xf86RandR12.c
@@ -1154,7 +1154,8 @@ xf86RandR12CrtcSet(ScreenPtr pScreen,
if (rotation != crtc->rotation)
changed = TRUE;
- if (crtc->current_scanout != randr_crtc->scanout_pixmap)
+ if (crtc->current_scanout != randr_crtc->scanout_pixmap ||
+ crtc->current_scanout_back != randr_crtc->scanout_pixmap_back)
changed = TRUE;
transform = RRCrtcGetTransform(randr_crtc);
@@ -1219,6 +1220,7 @@ xf86RandR12CrtcSet(ScreenPtr pScreen,
xf86SaveModeContents(&crtc->desiredMode, &mode);
crtc->desiredRotation = rotation;
crtc->current_scanout = randr_crtc->scanout_pixmap;
+ crtc->current_scanout_back = randr_crtc->scanout_pixmap_back;
if (transform) {
crtc->desiredTransform = *transform;
crtc->desiredTransformPresent = TRUE;
diff --git a/randr/randrstr.h b/randr/randrstr.h
index 3e37df7..ada1348 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -130,6 +130,7 @@ struct _rrCrtc {
struct pict_f_transform f_inverse;
PixmapPtr scanout_pixmap;
+ PixmapPtr scanout_pixmap_back;
};
struct _rrOutput {
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index ea91ab7..089fc1a 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -366,9 +366,6 @@ rrDestroySharedPixmap(RRCrtcPtr crtc, PixmapPtr pPixmap) {
ScreenPtr master = crtc->pScreen->current_master;
if (master && pPixmap->master_pixmap) {
- PixmapPtr mscreenpix = master->GetScreenPixmap(master);
-
- master->StopPixmapTracking(mscreenpix, pPixmap);
/*
* Unref the pixmap twice: once for the original reference, and once
* for the reference implicitly added by PixmapShareToSlave.
@@ -387,11 +384,29 @@ RRCrtcDetachScanoutPixmap(RRCrtcPtr crtc)
{
rrScrPriv(crtc->pScreen);
- pScrPriv->rrCrtcSetScanoutPixmap(crtc, NULL);
if (crtc->scanout_pixmap) {
+ ScreenPtr master = crtc->pScreen->current_master;
+ PixmapPtr mscreenpix = master->GetScreenPixmap(master);
+
+ if (crtc->scanout_pixmap_back) {
+ pScrPriv->rrDisableSharedPixmapFlipping(crtc);
+
+ master->StopFlippingPixmapTracking(mscreenpix,
+ crtc->scanout_pixmap,
+ crtc->scanout_pixmap_back);
+
+ rrDestroySharedPixmap(crtc, crtc->scanout_pixmap_back);
+ crtc->scanout_pixmap_back = NULL;
+ }
+ else {
+ pScrPriv->rrCrtcSetScanoutPixmap(crtc, NULL);
+ master->StopPixmapTracking(mscreenpix, crtc->scanout_pixmap);
+ }
+
rrDestroySharedPixmap(crtc, crtc->scanout_pixmap);
+ crtc->scanout_pixmap = NULL;
}
- crtc->scanout_pixmap = NULL;
+
RRCrtcChanged(crtc, TRUE);
}
@@ -400,9 +415,7 @@ rrCreateSharedPixmap(RRCrtcPtr crtc, ScreenPtr master,
int width, int height, int depth,
int x, int y, Rotation rotation)
{
- Bool ret;
PixmapPtr mpix, spix;
- rrScrPriv(crtc->pScreen);
mpix = master->CreatePixmap(master, width, height, depth,
CREATE_PIXMAP_USAGE_SHARED);
@@ -415,13 +428,6 @@ rrCreateSharedPixmap(RRCrtcPtr crtc, ScreenPtr master,
return NULL;
}
- ret = pScrPriv->rrCrtcSetScanoutPixmap(crtc, spix);
- if (ret == FALSE) {
- rrDestroySharedPixmap(crtc, spix);
- ErrorF("randr: failed to set shadow slave pixmap\n");
- return NULL;
- }
-
return spix;
}
@@ -430,16 +436,30 @@ rrSetupPixmapSharing(RRCrtcPtr crtc, int width, int height,
int x, int y, Rotation rotation)
{
ScreenPtr master = crtc->pScreen->current_master;
+ rrScrPrivPtr pMasterScrPriv = rrGetScrPriv(master);
+ rrScrPrivPtr pSlaveScrPriv = rrGetScrPriv(crtc->pScreen);
+
int depth;
PixmapPtr mscreenpix;
- PixmapPtr spix;
-
- /* create a pixmap on the master screen,
- then get a shared handle for it
- create a shared pixmap on the slave screen using the handle
- set the master screen to do dirty updates to the shared pixmap
- from the screen pixmap.
- set slave screen to scanout shared linear pixmap
+ PixmapPtr spix_front;
+
+ /* Create a pixmap on the master screen, then get a shared handle for it.
+ Create a shared pixmap on the slave screen using the handle.
+
+ If sync == FALSE --
+ Set slave screen to scanout shared linear pixmap.
+ Set the master screen to do dirty updates to the shared pixmap
+ from the screen pixmap on its own accord.
+
+ If sync == TRUE --
+ If any of the below steps fail, clean up and fall back to sync == FALSE.
+ Create another shared pixmap on the slave screen using the handle.
+ Set slave screen to prepare for scanout and flipping between shared
+ linear pixmaps.
+ Set the master screen to do dirty updates to the shared pixmaps from the
+ screen pixmap when prompted to by us or the slave.
+ Prompt the master to do a dirty update on the first shared pixmap, then
+ defer to the slave.
*/
mscreenpix = master->GetScreenPixmap(master);
@@ -452,16 +472,65 @@ rrSetupPixmapSharing(RRCrtcPtr crtc, int width, int height,
return TRUE;
}
- spix = rrCreateSharedPixmap(crtc, master,
- width, height, depth,
- x, y, rotation);
- if (spix == NULL) {
+ spix_front = rrCreateSharedPixmap(crtc, master,
+ width, height, depth,
+ x, y, rotation);
+ if (spix_front == NULL) {
return FALSE;
}
- crtc->scanout_pixmap = spix;
+ /* Both source and sink must support required ABI funcs for flipping */
+ if (pSlaveScrPriv->rrEnableSharedPixmapFlipping &&
+ pSlaveScrPriv->rrDisableSharedPixmapFlipping &&
+ pMasterScrPriv->rrStartFlippingPixmapTracking &&
+ master->PresentSharedPixmap &&
+ master->StopFlippingPixmapTracking) {
+
+ PixmapPtr spix_back = rrCreateSharedPixmap(crtc, master,
+ width, height, depth,
+ x, y, rotation);
+ if (spix_back == NULL)
+ goto fail;
+
+ if (!pSlaveScrPriv->rrEnableSharedPixmapFlipping(crtc,
+ spix_front, spix_back))
+ goto fail;
+
+ crtc->scanout_pixmap = spix_front;
+ crtc->scanout_pixmap_back = spix_back;
+
+ if (!pMasterScrPriv->rrStartFlippingPixmapTracking(crtc, mscreenpix,
+ spix_front,
+ spix_back,
+ x, y, 0, 0,
+ rotation)) {
+ pSlaveScrPriv->rrDisableSharedPixmapFlipping(crtc);
+ goto fail;
+ }
+
+ master->PresentSharedPixmap(spix_front);
+
+ return TRUE;
+
+fail: /* If flipping funcs fail, just fall back to unsynchronized */
+ if (spix_back)
+ rrDestroySharedPixmap(crtc, spix_back);
+
+ crtc->scanout_pixmap = NULL;
+ crtc->scanout_pixmap_back = NULL;
+ }
+
+ ErrorF("randr: falling back to unsynchronized pixmap sharing\n");
+
+ if (!pSlaveScrPriv->rrCrtcSetScanoutPixmap(crtc, spix_front)) {
+ rrDestroySharedPixmap(crtc, spix_front);
+ ErrorF("randr: failed to set shadow slave pixmap\n");
+ return FALSE;
+ }
+ crtc->scanout_pixmap = spix_front;
+
+ master->StartPixmapTracking(mscreenpix, spix_front, x, y, 0, 0, rotation);
- master->StartPixmapTracking(mscreenpix, spix, x, y, 0, 0, rotation);
return TRUE;
}
@@ -1751,6 +1820,12 @@ RRReplaceScanoutPixmap(DrawablePtr pDrawable, PixmapPtr pPixmap, Bool enable)
if (!crtc->scanout_pixmap && !enable)
continue;
+ /* not supported with double buffering, needs ABI change for 2 ppix */
+ if (crtc->scanout_pixmap_back) {
+ ret = FALSE;
+ continue;
+ }
+
size_fits = (crtc->mode &&
crtc->x == pDrawable->x &&
crtc->y == pDrawable->y &&
commit b601f96a5915a2c486b389483b291797e6fdf617
Author: Alex Goins <agoins at nvidia.com>
Date: Thu Jun 16 20:06:46 2016 -0700
xf86: Add PRIME flipping functions to Screen
Adds typedefs for (*RRStartFlippingPixmapTrackingProcPtr),
(*RREnableSharedPixmapFlippingProcPtr),
and (*RRDisableSharedPixmapFlippingProcPtr) in randrstr.h.
Adds typedefs for (*PresentSharedPixmapProcPtr),
(*SharedPixmapNotifyDamageProcPtr),
(*RequestSharedPixmapNotifyDamageProcPtr), and
(*StopFlippingPixmapTrackingProcPtr) in scrnintstr.h.
Adds RR(Enable/Disable)SharedPixmapFlipping, and
RRStartFlippingPixmapTracking to rrScrnPrivRec.
Adds StopFlippingPixmapTracking, PresentSharedPixmap,
SharedPixmapNotifyDamage, and RequestSharedPixmapNotifyDamage to ScreenRec.
rrScrnPrivRec used for functions that use RandR-private data types, and
ScreenRec used for the rest.
RREnableSharedPixmapFlipping will allow the sink driver to setup for
flipping between two shared pixmaps.
RRDisableSharedPixmapFlipping will allow the sink driver to do teardown
associated with flipping between two shared pixmaps.
(RRStart/Stop)FlippingPixmapTracking are merely the double-buffered
equivalents of (Start/Stop)PixmapTracking, allowing the source driver to do
whatever setup and teardown necessary for presenting on the two shared
pixmaps.
PresentSharedPixmap is a function exposed by the source driver for the X
server or sink driver to call to request a present on a given shared
pixmap. This way, presents can be driven by the sink's vblank instead of a
timer or similar mechanism.
SharedPixmapNotifyDamage and RequestSharedPixmapNotifyDamage are OPTIONAL
(even for double-buffered PRIME) functions exposed by the sink driver and
the source driver, respectively. By calling
master->RequestSharedPixmapNotifyDamage(ppix), the sink driver can request
for the source driver to call slave->SharedPixmapNotifyDamage(ppix) in
response to damage on the master screen pixmap tracked by ppix.
v1: Initial commit
v2: Rename PresentTrackedFlippingPixmap to PresentSharedPixmap
Add SharedPixmapNotifyDamage / RequestSharedPixmapNotifyDamage
v3: Add RRCrtcPtr as a parameter to StartFlippingPixmapTracking
Move functions that use RandR-private data types to rrScrnPrivRec.
v4: Unchanged
v5: Add front and back parameters to RREnableSharedPixmapFlippingProcPtr
v6: Rebase onto ToT
v7: Unchanged
Reviewed-by: Dave Airlie <airlied at redhat.com>
Signed-off-by: Alex Goins <agoins at nvidia.com>
diff --git a/include/scrnintstr.h b/include/scrnintstr.h
index 63ef55c..c5dadc7 100644
--- a/include/scrnintstr.h
+++ b/include/scrnintstr.h
@@ -349,8 +349,17 @@ typedef Bool (*StartPixmapTrackingProcPtr)(PixmapPtr, PixmapPtr,
int dst_x, int dst_y,
Rotation rotation);
+typedef Bool (*PresentSharedPixmapProcPtr)(PixmapPtr);
+
+typedef Bool (*RequestSharedPixmapNotifyDamageProcPtr)(PixmapPtr);
+
typedef Bool (*StopPixmapTrackingProcPtr)(PixmapPtr, PixmapPtr);
+typedef Bool (*StopFlippingPixmapTrackingProcPtr)(PixmapPtr,
+ PixmapPtr, PixmapPtr);
+
+typedef Bool (*SharedPixmapNotifyDamageProcPtr)(PixmapPtr);
+
typedef Bool (*ReplaceScanoutPixmapProcPtr)(DrawablePtr, PixmapPtr, Bool);
typedef WindowPtr (*XYToWindowProcPtr)(ScreenPtr pScreen,
@@ -605,6 +614,11 @@ typedef struct _Screen {
StartPixmapTrackingProcPtr StartPixmapTracking;
StopPixmapTrackingProcPtr StopPixmapTracking;
+ SharedPixmapNotifyDamageProcPtr SharedPixmapNotifyDamage;
+ RequestSharedPixmapNotifyDamageProcPtr RequestSharedPixmapNotifyDamage;
+ PresentSharedPixmapProcPtr PresentSharedPixmap;
+ StopFlippingPixmapTrackingProcPtr StopFlippingPixmapTracking;
+
struct xorg_list pixmap_dirty_list;
ReplaceScanoutPixmapProcPtr ReplaceScanoutPixmap;
diff --git a/randr/randrstr.h b/randr/randrstr.h
index 472721a..3e37df7 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -278,6 +278,19 @@ typedef Bool (*RRSetConfigProcPtr) (ScreenPtr pScreen,
typedef Bool (*RRCrtcSetScanoutPixmapProcPtr)(RRCrtcPtr crtc, PixmapPtr pixmap);
+typedef Bool (*RRStartFlippingPixmapTrackingProcPtr)(RRCrtcPtr, PixmapPtr,
+ PixmapPtr, PixmapPtr,
+ int x, int y,
+ int dst_x, int dst_y,
+ Rotation rotation);
+
+typedef Bool (*RREnableSharedPixmapFlippingProcPtr)(RRCrtcPtr,
+ PixmapPtr front,
+ PixmapPtr back);
+
+typedef void (*RRDisableSharedPixmapFlippingProcPtr)(RRCrtcPtr);
+
+
typedef struct _rrScrPriv {
/*
* 'public' part of the structure; DDXen fill this in
@@ -304,6 +317,10 @@ typedef struct _rrScrPriv {
/* TODO #if RANDR_15_INTERFACE */
RRCrtcSetScanoutPixmapProcPtr rrCrtcSetScanoutPixmap;
+ RRStartFlippingPixmapTrackingProcPtr rrStartFlippingPixmapTracking;
+ RREnableSharedPixmapFlippingProcPtr rrEnableSharedPixmapFlipping;
+ RRDisableSharedPixmapFlippingProcPtr rrDisableSharedPixmapFlipping;
+
RRProviderSetOutputSourceProcPtr rrProviderSetOutputSource;
RRProviderSetOffloadSinkProcPtr rrProviderSetOffloadSink;
RRProviderGetPropertyProcPtr rrProviderGetProperty;
More information about the xorg-commit
mailing list