summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--randr/randrstr.h1
-rw-r--r--randr/rrcrtc.c70
-rw-r--r--randr/rrprovider.c57
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);
}