diff options
-rw-r--r-- | randr/randrstr.h | 1 | ||||
-rw-r--r-- | randr/rrcrtc.c | 70 | ||||
-rw-r--r-- | randr/rrprovider.c | 57 |
3 files changed, 124 insertions, 4 deletions
diff --git a/randr/randrstr.h b/randr/randrstr.h index ada1348d2..1baa91226 100644 --- a/randr/randrstr.h +++ b/randr/randrstr.h @@ -935,6 +935,7 @@ extern _X_EXPORT int ProcRRDeleteOutputProperty(ClientPtr client); /* rrprovider.c */ +#define PRIME_SYNC_PROP "PRIME Synchronization" extern _X_EXPORT void RRProviderInitErrorValue(void); diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c index 089fc1a79..8fb2bca8a 100644 --- a/randr/rrcrtc.c +++ b/randr/rrcrtc.c @@ -25,6 +25,8 @@ #include "swaprep.h" #include "mipointer.h" +#include <X11/Xatom.h> + RESTYPE RRCrtcType; /* @@ -432,8 +434,59 @@ rrCreateSharedPixmap(RRCrtcPtr crtc, ScreenPtr master, } static Bool +rrGetPixmapSharingSyncProp(int numOutputs, RROutputPtr * outputs) +{ + /* Determine if the user wants prime syncing */ + int o; + const char *syncStr = PRIME_SYNC_PROP; + Atom syncProp = MakeAtom(syncStr, strlen(syncStr), FALSE); + if (syncProp == None) + return TRUE; + + /* If one output doesn't want sync, no sync */ + for (o = 0; o < numOutputs; o++) { + RRPropertyValuePtr val; + + /* Try pending value first, then current value */ + if ((val = RRGetOutputProperty(outputs[o], syncProp, TRUE)) && + val->data) { + if (!(*(char *) val->data)) + return FALSE; + continue; + } + + if ((val = RRGetOutputProperty(outputs[o], syncProp, FALSE)) && + val->data) { + if (!(*(char *) val->data)) + return FALSE; + continue; + } + } + + return TRUE; +} + +static void +rrSetPixmapSharingSyncProp(char val, int numOutputs, RROutputPtr * outputs) +{ + int o; + const char *syncStr = PRIME_SYNC_PROP; + Atom syncProp = MakeAtom(syncStr, strlen(syncStr), FALSE); + if (syncProp == None) + return; + + for (o = 0; o < numOutputs; o++) { + RRPropertyPtr prop = RRQueryOutputProperty(outputs[o], syncProp); + if (prop) + RRChangeOutputProperty(outputs[o], syncProp, XA_INTEGER, + 8, PropModeReplace, 1, &val, FALSE, TRUE); + } +} + +static Bool rrSetupPixmapSharing(RRCrtcPtr crtc, int width, int height, - int x, int y, Rotation rotation) + int x, int y, Rotation rotation, Bool sync, + int numOutputs, RROutputPtr * outputs) { ScreenPtr master = crtc->pScreen->current_master; rrScrPrivPtr pMasterScrPriv = rrGetScrPriv(master); @@ -480,7 +533,8 @@ rrSetupPixmapSharing(RRCrtcPtr crtc, int width, int height, } /* Both source and sink must support required ABI funcs for flipping */ - if (pSlaveScrPriv->rrEnableSharedPixmapFlipping && + if (sync && + pSlaveScrPriv->rrEnableSharedPixmapFlipping && pSlaveScrPriv->rrDisableSharedPixmapFlipping && pMasterScrPriv->rrStartFlippingPixmapTracking && master->PresentSharedPixmap && @@ -520,7 +574,12 @@ fail: /* If flipping funcs fail, just fall back to unsynchronized */ crtc->scanout_pixmap_back = NULL; } - ErrorF("randr: falling back to unsynchronized pixmap sharing\n"); + if (sync) { /* Wanted sync, didn't get it */ + ErrorF("randr: falling back to unsynchronized pixmap sharing\n"); + + /* Set output property to 0 to indicate to user */ + rrSetPixmapSharingSyncProp(0, numOutputs, outputs); + } if (!pSlaveScrPriv->rrCrtcSetScanoutPixmap(crtc, spix_front)) { rrDestroySharedPixmap(crtc, spix_front); @@ -692,7 +751,10 @@ RRCrtcSet(RRCrtcPtr crtc, return FALSE; if (pScreen->current_master) { - ret = rrSetupPixmapSharing(crtc, width, height, x, y, rotation); + Bool sync = rrGetPixmapSharingSyncProp(numOutputs, outputs); + ret = rrSetupPixmapSharing(crtc, width, height, + x, y, rotation, sync, + numOutputs, outputs); } } #if RANDR_12_INTERFACE diff --git a/randr/rrprovider.c b/randr/rrprovider.c index 8ef47260c..f9df67e0b 100644 --- a/randr/rrprovider.c +++ b/randr/rrprovider.c @@ -25,6 +25,8 @@ #include "randrstr.h" #include "swaprep.h" +#include <X11/Xatom.h> + RESTYPE RRProviderType; /* @@ -259,6 +261,58 @@ ProcRRGetProviderInfo (ClientPtr client) return Success; } +static void +RRInitPrimeSyncProps(ScreenPtr pScreen) +{ + /* + * TODO: When adding support for different sources for different outputs, + * make sure this sets up the output properties only on outputs associated + * with the correct source provider. + */ + + rrScrPrivPtr pScrPriv = rrGetScrPriv(pScreen); + + const char *syncStr = PRIME_SYNC_PROP; + Atom syncProp = MakeAtom(syncStr, strlen(syncStr), TRUE); + + int defaultVal = TRUE; + int validVals[2] = {FALSE, TRUE}; + + int i; + for (i = 0; i < pScrPriv->numOutputs; i++) { + if (!RRQueryOutputProperty(pScrPriv->outputs[i], syncProp)) { + RRConfigureOutputProperty(pScrPriv->outputs[i], syncProp, + TRUE, FALSE, FALSE, + 2, &validVals[0]); + RRChangeOutputProperty(pScrPriv->outputs[i], syncProp, XA_INTEGER, + 8, PropModeReplace, 1, &defaultVal, + FALSE, FALSE); + } + } +} + +static void +RRFiniPrimeSyncProps(ScreenPtr pScreen) +{ + /* + * TODO: When adding support for different sources for different outputs, + * make sure this tears down the output properties only on outputs + * associated with the correct source provider. + */ + + rrScrPrivPtr pScrPriv = rrGetScrPriv(pScreen); + int i; + + const char *syncStr = PRIME_SYNC_PROP; + Atom syncProp = MakeAtom(syncStr, strlen(syncStr), FALSE); + if (syncProp == None) + return; + + for (i = 0; i < pScrPriv->numOutputs; i++) { + RRDeleteOutputProperty(pScrPriv->outputs[i], syncProp); + } +} + int ProcRRSetProviderOutputSource(ClientPtr client) { @@ -286,6 +340,8 @@ ProcRRSetProviderOutputSource(ClientPtr client) pScrPriv->rrProviderSetOutputSource(pScreen, provider, source_provider); + RRInitPrimeSyncProps(pScreen); + provider->changed = TRUE; RRSetChanged(pScreen); @@ -361,6 +417,7 @@ RRProviderCreate(ScreenPtr pScreen, const char *name, void RRProviderDestroy (RRProviderPtr provider) { + RRFiniPrimeSyncProps(provider->pScreen); FreeResource (provider->id, 0); } |