summaryrefslogtreecommitdiff
path: root/spectro/dispwin.c
diff options
context:
space:
mode:
Diffstat (limited to 'spectro/dispwin.c')
-rwxr-xr-x[-rw-r--r--]spectro/dispwin.c580
1 files changed, 412 insertions, 168 deletions
diff --git a/spectro/dispwin.c b/spectro/dispwin.c
index 368f707..7761db1 100644..100755
--- a/spectro/dispwin.c
+++ b/spectro/dispwin.c
@@ -17,6 +17,15 @@
/* TTBD
*
+ * Should add support for XRandR 1.5 MST support, so that a Monitor driven
+ * by multiple CRTCs gets treated as a single item. (How does Xinerama emulation
+ * handle this though ?) - i.e. might have to duplicate profile atoms,
+ * set both VideoLUTs when one is set, deal with EDID/ucmm confusion etc.
+ * Note that XRandR Xinerama emulation changes with v1.5 and MST.
+ *
+ * Should look at MSWin & OS X uninstall profile function, and see if
+ * requirement of supplying profile name can be removed (just like X11 case).
+ *
* Should probably check the display attributes (like visual depth)
* and complain if we aren't using 24 bit color or better.
*
@@ -56,7 +65,7 @@
#include "numlib.h"
#include "cgats.h"
#include "conv.h"
-#include "xicc.h"
+# include "xicc.h"
#include "disptechs.h"
#include "dispwin.h"
#include "ui.h"
@@ -66,6 +75,9 @@
#ifdef NT
# include "madvrwin.h"
#endif
+#include "insttypes.h"
+#include "inst.h"
+#include "icoms.h"
#if defined(UNIX_X11)
# include <dlfcn.h>
# if defined(USE_UCMM)
@@ -92,6 +104,7 @@
*/
#include <Foundation/Foundation.h>
+#include <CoreFoundation/CoreFoundation.h>
#include <AppKit/AppKit.h>
@@ -153,8 +166,9 @@ CFUUIDRef CGDisplayCreateUUIDFromDisplayID (uint32_t displayID);
#endif
-/* ----------------------------------------------- */
-/* Dealing with locating displays */
+/* ===================================================================== */
+/* Display enumeration code */
+/* ===================================================================== */
int callback_ddebug = 0; /* Diagnostic global for get_displays() and get_a_display() */
/* and events */
@@ -597,11 +611,16 @@ disppath **get_displays() {
}
#if RANDR_MAJOR == 1 && RANDR_MINOR >= 2 && !defined(DISABLE_RANDR)
- /* Use Xrandr 1.2 if it's available, and if it's not disabled */
+ /* Use Xrandr 1.2 if it's available, and if it's not disabled. */
if (getenv("ARGYLL_IGNORE_XRANDR1_2") == NULL
&& XRRQueryExtension(mydisplay, &evb, &erb) != 0
&& XRRQueryVersion(mydisplay, &majv, &minv)
&& majv == 1 && minv >= 2) {
+ static void *xrr_found = NULL; /* .so handle */
+ static XRRScreenResources *(*_XRRGetScreenResourcesCurrent)
+ (Display *dpy, Window window) = NULL;
+ static RROutput (*_XRRGetOutputPrimary)(Display *dpy, Window window) = NULL;
+ int defsix; /* Default Screen index */
if (XSetErrorHandler(null_error_handler) == 0) {
debugrr("get_displays failed on XSetErrorHandler\n");
@@ -610,20 +629,38 @@ disppath **get_displays() {
return NULL;
}
+ /* Get functions available in Xrandr V1.3 */
+ if (minv >= 3 && xrr_found == NULL) {
+ if ((xrr_found = dlopen("libXrandr.so", RTLD_LAZY)) != NULL) {
+ _XRRGetScreenResourcesCurrent = dlsym(xrr_found, "XRRGetScreenResourcesCurrent");
+ _XRRGetOutputPrimary = dlsym(xrr_found, "XRRGetOutputPrimary");
+ }
+ }
+
+ /* Hmm. Do Xrandr systems alway have only one Screen, */
+ /* just like Xinerama ? */
dcount = ScreenCount(mydisplay);
- /* Go through all the screens */
+ debugrr2((errout,"get_displays using %d XRandR Screens\n",dcount));
+
+ /* Not sure what to do with this. */
+ /* Should we go through X11 screens with this first ? */
+ /* (How does Xrandr translate Screen 1..n to Xinerama ?????) */
+ defsix = DefaultScreen(mydisplay);
+
+ /* In order to be in sync with an application using Xinerama, */
+ /* we need to generate our screen indexes in the same */
+ /* order as Xinerama. */
+
+ /* Go through all the X11 screens */
for (i = 0; i < dcount; i++) {
- static void *xrr_found = NULL; /* .so handle */
- static XRRScreenResources *(*_XRRGetScreenResourcesCurrent)
- (Display *dpy, Window window) = NULL;
XRRScreenResources *scrnres;
- int jj; /* Screen index */
-
- if (minv >= 3 && xrr_found == NULL) {
- if ((xrr_found = dlopen("libXrandr.so", RTLD_LAZY)) != NULL)
- _XRRGetScreenResourcesCurrent = dlsym(xrr_found, "XRRGetScreenResourcesCurrent");
- }
+ int has_primary = 0;
+ int pix = -1; /* CRTC index containing primary */
+ int pop = -1; /* Output index containing primary */
+ int jj; /* Xinerama screen ix */
+ int xj; /* working crtc index */
+ int xk; /* working output index */
if (minv >= 3 && _XRRGetScreenResourcesCurrent != NULL) {
scrnres = _XRRGetScreenResourcesCurrent(mydisplay, RootWindow(mydisplay,i));
@@ -637,70 +674,150 @@ disppath **get_displays() {
free_disppaths(disps);
return NULL;
}
+ /* We have to scan through CRTC's & outputs in the same order */
+ /* as the XRANDR XInerama implementation in the X server. */
+ /* This is a little tricky, as we need to do the primary output, */
+ /* first, while keeping the rest in order. */
+
+ /* Locate the crtc index that contains the primary (if any) */
+ if (minv >= 3 && _XRRGetOutputPrimary != NULL) {
+ XID primary; /* Primary output ID */
+
+ primary = _XRRGetOutputPrimary(mydisplay, RootWindow(mydisplay,i));
+ debugrr2((errout,"XRRGetOutputPrimary returned XID %x\n",primary));
+
+ if (primary != None) {
+ for (j = 0; j < scrnres->ncrtc; j++) {
+ XRRCrtcInfo *crtci = NULL;
+
+ if ((crtci = XRRGetCrtcInfo(mydisplay, scrnres, scrnres->crtcs[j])) == NULL)
+ continue;
+
+ if (crtci->mode == None || crtci->noutput == 0) {
+ XRRFreeCrtcInfo(crtci);
+ continue;
+ }
+
+ for (k = 0; k < crtci->noutput; k++) {
+ if (crtci->outputs[k] == primary) {
+ pix = j;
+ pop = k;
+ }
+ }
+ XRRFreeCrtcInfo(crtci);
+ }
+ if (pix < 0) { /* Didn't locate primary */
+ debugrr2((errout,"Couldn't locate primary CRTC!\n"));
+ } else {
+ debugrr2((errout,"Primary is at CRTC %d Output %d\n",pix,pop));
+ has_primary = 1;
+ }
+ }
+ }
- /* Look at all the screens outputs */
- for (jj = j = 0; j < scrnres->noutput; j++) {
- XRROutputInfo *outi = NULL;
+ /* Look through all the Screens CRTC's */
+ for (jj = xj = j = 0; j < scrnres->ncrtc; j++, xj++) {
+ char *pp;
XRRCrtcInfo *crtci = NULL;
-
- if ((outi = XRRGetOutputInfo(mydisplay, scrnres, scrnres->outputs[j])) == NULL) {
- debugrr("XRRGetOutputInfo failed\n");
- XRRFreeScreenResources(scrnres);
- XCloseDisplay(mydisplay);
- free_disppaths(disps);
- return NULL;
+ XRROutputInfo *outi0 = NULL;
+
+ if (has_primary) {
+ if (j == 0)
+ xj = pix; /* Start with crtc containing primary */
+
+ else if (xj == pix) /* We've up to primary that we've alread done */
+ xj++; /* Skip it */
}
-
- if (outi->connection == RR_Disconnected ||
- outi->crtc == None) {
- XRRFreeOutputInfo(outi);
+
+ if ((crtci = XRRGetCrtcInfo(mydisplay, scrnres, scrnres->crtcs[xj])) == NULL) {
+ debugrr2((errout,"XRRGetCrtcInfo of Screen %d CRTC %d failed\n",i,xj));
+ if (has_primary && j == 0)
+ xj = -1; /* Start at beginning */
continue;
}
- /* Check that the VideoLUT's are accessible */
- {
- XRRCrtcGamma *crtcgam = NULL;
-
- debugrr("Checking XRandR 1.2 VideoLUT access\n");
- if ((crtcgam = XRRGetCrtcGamma(mydisplay, outi->crtc)) == NULL
- || crtcgam->size == 0) {
- fprintf(stderr,"XRandR 1.2 is faulty - falling back to older extensions\n");
+ debugrr2((errout,"XRRGetCrtcInfo of Screen %d CRTC %d has %d Outputs %s Mode\n",i,xj,crtci->noutput,crtci->mode == None ? "No" : "Valid"));
+
+ if (crtci->mode == None || crtci->noutput == 0) {
+ debugrr2((errout,"CRTC skipped as it has no mode or no outputs\n",i,xj,crtci->noutput));
+ XRRFreeCrtcInfo(crtci);
+ if (has_primary && j == 0)
+ xj = -1; /* Start at beginning */
+ continue;
+ }
+
+ /* This CRTC will now be counted as an Xinerama screen */
+ /* For each output of Crtc */
+ for (xk = k = 0; k < crtci->noutput; k++, xk++) {
+ XRROutputInfo *outi = NULL;
+
+ if (has_primary && xj == pix) {
+ if (k == 0)
+ xk = pop; /* Start with primary output */
+ else if (xk == pop) /* We've up to primary that we've alread done */
+ xk++; /* Skip it */
+ }
+
+ if ((outi = XRRGetOutputInfo(mydisplay, scrnres, crtci->outputs[xk])) == NULL) {
+ debugrr2((errout,"XRRGetOutputInfo failed for Screen %d CRTC %d Output %d\n",i,xj,xk));
+ goto next_output;
+ }
+ if (k == 0) /* Save this so we can label any clones */
+ outi0 = outi;
+
+ if (outi->connection == RR_Disconnected) {
+ debugrr2((errout,"Screen %d CRTC %d Output %d is disconnected\n",i,xj,xk));
+ goto next_output;
+ }
+
+ /* Check that the VideoLUT's are accessible */
+ {
+ XRRCrtcGamma *crtcgam = NULL;
+
+ debugrr("Checking XRandR 1.2 VideoLUT access\n");
+ if ((crtcgam = XRRGetCrtcGamma(mydisplay, scrnres->crtcs[xj])) == NULL
+ || crtcgam->size == 0) {
+ fprintf(stderr,"XRRGetCrtcGamma failed - falling back to older extensions\n");
+ if (crtcgam != NULL)
+ XRRFreeGamma(crtcgam);
+ if (outi != NULL && outi != outi0)
+ XRRFreeOutputInfo(outi);
+ if (outi0 != NULL)
+ XRRFreeOutputInfo(outi0);
+ XRRFreeCrtcInfo(crtci);
+ XRRFreeScreenResources(scrnres);
+ free_disppaths(disps);
+ disps = NULL;
+ goto done_xrandr;
+ }
if (crtcgam != NULL)
XRRFreeGamma(crtcgam);
- free_disppaths(disps);
- disps = NULL;
- j = scrnres->noutput;
- i = dcount;
- XRRFreeOutputInfo(outi);
- continue; /* Abort XRandR 1.2 */
}
- if (crtcgam != NULL)
- XRRFreeGamma(crtcgam);
- }
#ifdef NEVER
- {
- Atom *oprops;
- int noprop;
+ {
+ Atom *oprops;
+ int noprop;
- /* Get a list of the properties of the output */
- oprops = XRRListOutputProperties(mydisplay, scrnres->outputs[j], &noprop);
+ /* Get a list of the properties of the output */
+ oprops = XRRListOutputProperties(mydisplay, crtci->outputs[xk], &noprop);
- printf("num props = %d\n", noprop);
- for (k = 0; k < noprop; k++) {
- printf("%d: atom 0x%x, name = '%s'\n", k, oprops[k], XGetAtomName(mydisplay, oprops[k]));
+ printf("num props = %d\n", noprop);
+ for (k = 0; k < noprop; k++) {
+ printf("%d: atom 0x%x, name = '%s'\n", k, oprops[k], XGetAtomName(mydisplay, oprops[k]));
+ }
}
- }
#endif /* NEVER */
- if ((crtci = XRRGetCrtcInfo(mydisplay, scrnres, outi->crtc)) != NULL) {
- char *pp;
-
/* Add the output to the list */
+ debugrr2((errout,"Adding Screen %d CRTC %d Output %d\n",i,xj,xk));
if (disps == NULL) {
if ((disps = (disppath **)calloc(sizeof(disppath *), 1 + 1)) == NULL) {
debugrr("get_displays failed on malloc\n");
XRRFreeCrtcInfo(crtci);
- XRRFreeOutputInfo(outi);
+ if (outi != NULL && outi != outi0)
+ XRRFreeOutputInfo(outi);
+ if (outi0 != NULL)
+ XRRFreeOutputInfo(outi0);
XRRFreeScreenResources(scrnres);
XCloseDisplay(mydisplay);
return NULL;
@@ -710,7 +827,10 @@ disppath **get_displays() {
sizeof(disppath *) * (ndisps + 2))) == NULL) {
debugrr("get_displays failed on malloc\n");
XRRFreeCrtcInfo(crtci);
- XRRFreeOutputInfo(outi);
+ if (outi != NULL && outi != outi0)
+ XRRFreeOutputInfo(outi);
+ if (outi0 != NULL)
+ XRRFreeOutputInfo(outi0);
XRRFreeScreenResources(scrnres);
XCloseDisplay(mydisplay);
return NULL;
@@ -721,44 +841,49 @@ disppath **get_displays() {
if ((disps[ndisps] = calloc(sizeof(disppath),1)) == NULL) {
debugrr("get_displays failed on malloc\n");
XRRFreeCrtcInfo(crtci);
- XRRFreeOutputInfo(outi);
+ if (outi != NULL && outi != outi0)
+ XRRFreeOutputInfo(outi);
+ if (outi0 != NULL)
+ XRRFreeOutputInfo(outi0);
XRRFreeScreenResources(scrnres);
XCloseDisplay(mydisplay);
free_disppaths(disps);
return NULL;
}
- disps[ndisps]->screen = i;
- disps[ndisps]->uscreen = i;
- disps[ndisps]->rscreen = i;
+ disps[ndisps]->screen = i; /* X11 (virtual) Screen */
+ disps[ndisps]->uscreen = jj; /* Xinerama/Xrandr screen */
+ disps[ndisps]->rscreen = jj;
disps[ndisps]->sx = crtci->x;
disps[ndisps]->sy = crtci->y;
disps[ndisps]->sw = crtci->width;
disps[ndisps]->sh = crtci->height;
- disps[ndisps]->crtc = outi->crtc; /* XID of crtc */
- disps[ndisps]->output = scrnres->outputs[j]; /* XID of output */
+ disps[ndisps]->crtc = scrnres->crtcs[xj]; /* XID of CRTC */
+ disps[ndisps]->output = crtci->outputs[xk]; /* XID of output */
- sprintf(desc1,"Screen %d, Output %s",ndisps+1,outi->name);
+ sprintf(desc1,"Monitor %d, Output %s",ndisps+1,outi->name);
sprintf(desc2,"%s at %d, %d, width %d, height %d",desc1,
disps[ndisps]->sx, disps[ndisps]->sy, disps[ndisps]->sw, disps[ndisps]->sh);
- /* See if it is a clone */
- for (k = 0; k < ndisps; k++) {
- if (disps[k]->crtc == disps[ndisps]->crtc) {
- sprintf(desc1, "[ Clone of %d ]",k+1);
- strcat(desc2, desc1);
- }
+ /* If it is a clone */
+ if (k > 0 & outi0 != NULL) {
+ sprintf(desc1, "[ Clone of %s ]",outi0->name);
+ strcat(desc2, desc1);
}
+
if ((disps[ndisps]->description = strdup(desc2)) == NULL) {
debugrr("get_displays failed on malloc\n");
XRRFreeCrtcInfo(crtci);
- XRRFreeOutputInfo(outi);
+ if (outi != NULL && outi != outi0)
+ XRRFreeOutputInfo(outi);
+ if (outi0 != NULL)
+ XRRFreeOutputInfo(outi0);
XRRFreeScreenResources(scrnres);
XCloseDisplay(mydisplay);
free_disppaths(disps);
return NULL;
}
-
+
/* Form the display name */
if ((pp = strrchr(dnbuf, ':')) != NULL) {
if ((pp = strchr(pp, '.')) != NULL) {
@@ -768,27 +893,29 @@ disppath **get_displays() {
if ((disps[ndisps]->name = strdup(dnbuf)) == NULL) {
debugrr("get_displays failed on malloc\n");
XRRFreeCrtcInfo(crtci);
- XRRFreeOutputInfo(outi);
+ if (outi != NULL && outi != outi0)
+ XRRFreeOutputInfo(outi);
+ if (outi0 != NULL)
+ XRRFreeOutputInfo(outi0);
XRRFreeScreenResources(scrnres);
XCloseDisplay(mydisplay);
free_disppaths(disps);
return NULL;
}
debugrr2((errout, "Display %d name = '%s'\n",ndisps,disps[ndisps]->name));
-
+
/* Create the X11 root atom of the default screen */
- /* that may contain the associated ICC profile */
- /* (The _%d variant will probably break with non-Xrandr */
- /* aware software if Xrandr is configured to have more than */
- /* a single virtual screen.) */
+ /* that may contain the associated ICC profile. */
if (jj == 0)
strcpy(desc1, "_ICC_PROFILE");
else
- sprintf(desc1, "_ICC_PROFILE_%d",jj);
+ sprintf(desc1, "_ICC_PROFILE_%d",disps[ndisps]->uscreen);
if ((disps[ndisps]->icc_atom = XInternAtom(mydisplay, desc1, False)) == None)
error("Unable to intern atom '%s'",desc1);
+ debugrr2((errout,"Root atom '%s'\n",desc1));
+
/* Create the atom of the output that may contain the associated ICC profile */
if ((disps[ndisps]->icc_out_atom = XInternAtom(mydisplay, "_ICC_PROFILE", False)) == None)
error("Unable to intern atom '%s'","_ICC_PROFILE");
@@ -810,19 +937,22 @@ disppath **get_displays() {
for (ii = 0; keys[ii][0] != '\000'; ii++) {
/* Get the atom for the EDID data */
if ((edid_atom = XInternAtom(mydisplay, keys[ii], True)) == None) {
- debugrr2((errout, "Unable to intern atom '%s'\n",keys[ii]));
+ // debugrr2((errout, "Unable to intern atom '%s'\n",keys[ii]));
/* Try the next key */
- } else {
- /* Get the EDID_DATA */
- if (XRRGetOutputProperty(mydisplay, scrnres->outputs[j], edid_atom,
+ /* Get the EDID_DATA */
+ } else {
+ if (XRRGetOutputProperty(mydisplay, crtci->outputs[xk], edid_atom,
0, 0x7ffffff, False, False, XA_INTEGER,
&ret_type, &ret_format, &ret_len, &ret_togo, &atomv) == Success
&& (ret_len == 128 || ret_len == 256)) {
if ((disps[ndisps]->edid = malloc(sizeof(unsigned char) * ret_len)) == NULL) {
debugrr("get_displays failed on malloc\n");
XRRFreeCrtcInfo(crtci);
- XRRFreeOutputInfo(outi);
+ if (outi != NULL && outi != outi0)
+ XRRFreeOutputInfo(outi);
+ if (outi0 != NULL)
+ XRRFreeOutputInfo(outi0);
XRRFreeScreenResources(scrnres);
XCloseDisplay(mydisplay);
free_disppaths(disps);
@@ -840,22 +970,30 @@ disppath **get_displays() {
if (keys[ii][0] == '\000')
debugrr2((errout, "Failed to get EDID for display\n"));
}
-
- jj++; /* Next enabled index */
ndisps++; /* Now it's number of displays */
- XRRFreeCrtcInfo(crtci);
+
+ next_output:;
+ if (outi != NULL && outi != outi0)
+ XRRFreeOutputInfo(outi);
+ if (has_primary && xj == pix && k == 0)
+ xk = -1; /* Go to first output */
}
- XRRFreeOutputInfo(outi);
+ next_screen:;
+ if (outi0 != NULL)
+ XRRFreeOutputInfo(outi0);
+ XRRFreeCrtcInfo(crtci);
+ jj++; /* Next Xinerama screen index */
+ if (has_primary && j == 0)
+ xj = -1; /* Go to first screen */
}
XRRFreeScreenResources(scrnres);
}
+ done_xrandr:;
XSetErrorHandler(NULL);
- defsix = DefaultScreen(mydisplay);
}
#endif /* randr >= V 1.2 */
if (disps == NULL) { /* Use Older style identification */
- debugrr("get_displays checking for Xinerama\n");
if (XSetErrorHandler(null_error_handler) == 0) {
debugrr("get_displays failed on XSetErrorHandler\n");
@@ -863,7 +1001,8 @@ disppath **get_displays() {
return NULL;
}
- if (XineramaQueryExtension(mydisplay, &evb, &erb) != 0
+ if (getenv("ARGYLL_IGNORE_XINERAMA") == NULL
+ && XineramaQueryExtension(mydisplay, &evb, &erb) != 0
&& XineramaIsActive(mydisplay)) {
xai = XineramaQueryScreens(mydisplay, &dcount);
@@ -873,10 +1012,10 @@ disppath **get_displays() {
XCloseDisplay(mydisplay);
return NULL;
}
- defsix = 0;
+ debugrr2((errout,"get_displays using %d Xinerama Screens\n",dcount));
} else {
dcount = ScreenCount(mydisplay);
- defsix = DefaultScreen(mydisplay);
+ debugrr2((errout,"get_displays using %d X11 Screens\n",dcount));
}
/* Allocate our list */
@@ -903,7 +1042,10 @@ disppath **get_displays() {
/* Form the display name */
if ((pp = strrchr(dnbuf, ':')) != NULL) {
if ((pp = strchr(pp, '.')) != NULL) {
- sprintf(pp,".%d",i);
+ if (xai != NULL) /* Xinerama */
+ sprintf(pp,".%d",0);
+ else
+ sprintf(pp,".%d",i);
}
}
if ((disps[i]->name = strdup(dnbuf)) == NULL) {
@@ -915,14 +1057,15 @@ disppath **get_displays() {
debugrr2((errout, "Display %d name = '%s'\n",i,disps[i]->name));
if (xai != NULL) { /* Xinerama */
- disps[i]->screen = 0; /* We are asuming Xinerame creates a single virtual screen */
- disps[i]->uscreen = i; /* We are assuming xinerama lists screens in the same order */
+ /* xai[i].screen_number should be == i */
+ disps[i]->screen = 0; /* Assume Xinerame creates a single virtual X11 screen */
+ disps[i]->uscreen = i; /* Underlying Xinerma screen */
disps[i]->rscreen = i;
disps[i]->sx = xai[i].x_org;
disps[i]->sy = xai[i].y_org;
disps[i]->sw = xai[i].width;
disps[i]->sh = xai[i].height;
- } else {
+ } else { /* Plain X11 Screens */
disps[i]->screen = i;
disps[i]->uscreen = i;
disps[i]->rscreen = i;
@@ -992,9 +1135,9 @@ disppath **get_displays() {
&& monitor.model != NULL && monitor.model[0] != '\000')
sprintf(desc1, "%s",monitor.model);
else
- sprintf(desc1,"Screen %d",i+1);
+ sprintf(desc1,"Monitor %d",i+1);
} else
- sprintf(desc1,"Screen %d",i+1);
+ sprintf(desc1,"Monitor %d",i+1);
sprintf(desc2,"%s at %d, %d, width %d, height %d",desc1,
disps[i]->sx, disps[i]->sy, disps[i]->sw, disps[i]->sh);
@@ -1006,14 +1149,15 @@ disppath **get_displays() {
}
}
XSetErrorHandler(NULL);
- }
- /* Put the screen given by the display name at the top */
- {
- disppath *tdispp;
- tdispp = disps[defsix];
- disps[defsix] = disps[0];
- disps[0] = tdispp;
+ /* Put the default Screen the top of the list */
+ if (xai == NULL) {
+ int defsix = DefaultScreen(mydisplay);
+ disppath *tdispp;
+ tdispp = disps[defsix];
+ disps[defsix] = disps[0];
+ disps[0] = tdispp;
+ }
}
if (xai != NULL)
@@ -1087,6 +1231,8 @@ disppath *get_a_display(int ix) {
disppath **paths, *rv = NULL;
int i;
+ debugrr2((errout, "get_a_display called with ix %d\n",ix));
+
if ((paths = get_displays()) == NULL)
return NULL;
@@ -1095,8 +1241,9 @@ disppath *get_a_display(int ix) {
free_disppaths(paths);
return NULL;
}
- if (i == ix)
+ if (i == ix) {
break;
+ }
}
if ((rv = malloc(sizeof(disppath))) == NULL) {
debugrr("get_a_display failed malloc\n");
@@ -1129,6 +1276,8 @@ disppath *get_a_display(int ix) {
memmove(rv->edid, paths[i]->edid, rv->edid_len );
}
#endif
+ debugrr2((errout, " Selected ix %d '%s' %s'\n",i,rv->name,rv->description));
+
free_disppaths(paths);
return rv;
}
@@ -1147,7 +1296,9 @@ void free_a_disppath(disppath *path) {
}
}
-/* ----------------------------------------------- */
+/* ===================================================================== */
+/* RAMDAC access code */
+/* ===================================================================== */
/* For VideoLUT/RAMDAC use, we assume that the frame buffer */
/* may map through some intermediate hardware or lookup */
@@ -1465,7 +1616,7 @@ static char *iprof_path(p_scope scope, char *fname) {
dirname = COLORSYNC_DIR_LOCAL;
else {
dirname = COLORSYNC_DIR_USER;
- if ((home = getenv("HOME")) == NULL){
+ if ((home = login_HOME()) == NULL){
return NULL;
}
}
@@ -2273,7 +2424,10 @@ void dispwin_del_ramdac(ramdac *r) {
free(r);
}
-/* ----------------------------------------------- */
+/* ===================================================================== */
+/* Profile install code */
+/* ===================================================================== */
+
/* Useful function for X11 profile atom settings */
#if defined(UNIX_X11)
@@ -2283,7 +2437,10 @@ static int set_X11_atom(dispwin *p, char *fname) {
unsigned long psize, bread;
unsigned char *atomv;
- debugr("Setting _ICC_PROFILE property\n");
+ if (p->myuscreen == 0)
+ debugr("Setting _ICC_PROFILE property\n");
+ else
+ debugr2((errout,"Setting _ICC_PROFILE_%d property\n",p->myuscreen));
/* Read in the ICC profile, then set the X11 atom value */
#if !defined(O_CREAT) && !defined(_O_CREAT)
@@ -2323,11 +2480,13 @@ static int set_X11_atom(dispwin *p, char *fname) {
fclose(fp);
- XChangeProperty(p->mydisplay, RootWindow(p->mydisplay, 0), p->icc_atom,
+ if (p->icc_atom != None) {
+ XChangeProperty(p->mydisplay, RootWindow(p->mydisplay, 0), p->icc_atom,
XA_CARDINAL, 8, PropModeReplace, atomv, psize);
+ }
#if RANDR_MAJOR == 1 && RANDR_MINOR >= 2 && !defined(DISABLE_RANDR)
- if (p->icc_out_atom != 0) {
+ if (p->icc_out_atom != None) {
/* If Xrandr 1.2, set property on output */
/* This seems to fail on some servers. Ignore the error ? */
if (XSetErrorHandler(null_error_handler) == 0) {
@@ -2351,7 +2510,8 @@ static int set_X11_atom(dispwin *p, char *fname) {
}
#endif /* UNXI X11 */
-/* ----------------------------------------------- */
+/* ---------------------------------------------- */
+
/* See if colord is available */
#if defined(UNIX_X11) && defined(USE_UCMM)
@@ -2373,7 +2533,8 @@ int dispwin_checkfor_colord() {
cd_found = NULL;
- if ((cd_found = dlopen("libcolordcompat.so", RTLD_LAZY)) != NULL) {
+ if (getenv("ARGYLL_USE_COLORD") != NULL
+ && (cd_found = dlopen("libcolordcompat.so", RTLD_LAZY)) != NULL) {
cd_edid_install_profile = dlsym(cd_found, "cd_edid_install_profile");
cd_edid_remove_profile = dlsym(cd_found, "cd_edid_remove_profile");
@@ -2394,7 +2555,6 @@ int dispwin_checkfor_colord() {
#endif
-
/* ----------------------------------------------- */
/* Install a display profile and make */
/* it the default for this display. */
@@ -2630,7 +2790,7 @@ int dispwin_install_profile(dispwin *p, char *fname, ramdac *r, p_scope scope) {
return 0;
}
-#else /* 10.6 and prior */
+#else /* OS X 10.6 and prior */
// Switch to using iprof_path() to simplify ?
{
CMError ev;
@@ -2766,8 +2926,9 @@ int dispwin_install_profile(dispwin *p, char *fname, ramdac *r, p_scope scope) {
/* Un-Install a display profile */
/* Return nz if failed, */
-/* 1 if not sucessfully deleted */
+/* 1 if not successfully deleted */
/* 2 if profile not found */
+/* NT and OS X need fname, *NIX does not. */
int dispwin_uninstall_profile(dispwin *p, char *fname, p_scope scope) {
debugr2((errout,"dispwin_uninstall_profile '%s'\n", fname));
#ifdef NT
@@ -2883,7 +3044,7 @@ int dispwin_uninstall_profile(dispwin *p, char *fname, p_scope scope) {
}
debug2((errout,"Set euid %d and egid %d\n",uid,gid));
}
- /* If setting local system proile and not effective root, but sudo */
+ /* If setting local system profile and not effective root, but sudo */
} else if (scope != p_scope_user && getuid() == 0 && geteuid() != 0) {
if (getenv("SUDO_UID") != NULL
&& getenv("SUDO_GID") != NULL) {
@@ -3029,14 +3190,15 @@ int dispwin_uninstall_profile(dispwin *p, char *fname, p_scope scope) {
if (cd_found)
ev = cd_edid_remove_profile(p->edid, p->edid_len, fname);
else
- ev = ucmm_uninstall_monitor_profile(sc, p->edid, p->edid_len, p->name, fname);
+ ev = ucmm_uninstall_monitor_profile(sc, p->edid, p->edid_len, p->name);
if (ev != ucmm_ok) {
debugr2((errout,"Installing profile '%s' failed with error %d '%s'\n",fname,ev,ucmm_error_string(ev)));
return 1;
}
- XDeleteProperty(p->mydisplay, RootWindow(p->mydisplay, 0), p->icc_atom);
+ if (p->icc_atom != None)
+ XDeleteProperty(p->mydisplay, RootWindow(p->mydisplay, 0), p->icc_atom);
#if RANDR_MAJOR == 1 && RANDR_MINOR >= 2 && !defined(DISABLE_RANDR)
/* If Xrandr 1.2, set property on output */
@@ -3254,6 +3416,7 @@ icmFile *dispwin_get_profile(dispwin *p, char *name, int mxlen) {
debugr2((errout,"Setting X11 atom to profile '%s' failed",profile));
/* Hmm. We ignore this error */
}
+ free(profile);
return rd_fp;
}
if (ev != ucmm_no_profile) {
@@ -3291,9 +3454,14 @@ icmFile *dispwin_get_profile(dispwin *p, char *name, int mxlen) {
#endif /* randr >= V 1.2 */
if (atomv == NULL) {
+ if (p->icc_atom == None) {
+ debugr("Second or subsequent Output doesn't have ICC_PROFILE property\n");
+ return NULL;
+ }
+
if (p->myuscreen != 0)
sprintf(aname, "_ICC_PROFILE_%d",p->myuscreen);
-
+
/* Get the ICC profile property */
if (XGetWindowProperty(p->mydisplay, RootWindow(p->mydisplay, 0), p->icc_atom,
0, 0x7ffffff, False, XA_CARDINAL,
@@ -3336,7 +3504,7 @@ icmFile *dispwin_get_profile(dispwin *p, char *name, int mxlen) {
return NULL;
}
-/* ----------------------------------------------- */
+/* ===================================================================== */
/* Restore the display state and free ramdacs */
static void restore_display(dispwin *p) {
@@ -3416,6 +3584,8 @@ static void dispwin_sighandler(int arg) {
static amutex_static(lock);
dispwin *pp, *np;
+ debugrr("dispwin_sighandler called\n");
+
/* Make sure we don't re-enter */
if (amutex_trylock(lock)) {
return;
@@ -3483,7 +3653,10 @@ static void dispwin_uninstall_signal_handlers(dispwin *p) {
p->next = NULL;
}
-/* ----------------------------------------------- */
+/* ===================================================================== */
+/* Test patch window code */
+/* ===================================================================== */
+
/* Test patch window specific declarations */
#ifdef UNIX_APPLE
@@ -3531,6 +3704,7 @@ unsigned char emptyCursor[43] = {
* the mouse enters the window. This needs the main thread
* to be dedicated to running the event loop, so would involve
* some trickiness after main() in every program.
+ * - we have done this with numlib/ui.c, so this is possible.
*/
- (void)resetCursorRects {
[super resetCursorRects];
@@ -3671,8 +3845,7 @@ static void create_my_win(void *cntx) {
/* Moves the window to the front of the screen list within its level, */
/* and show the window (i.e. make it "key") */
- /* Trigger warning on OS X 10.11 El Capitan ? */
- /* (Doesn't happen using 1.6.3 which ran everything in the main thread.) */
+ /* Trigger warning on OS X 10.11 El Capitan if not run in the main thread. */
[cx->window makeKeyAndOrderFront: nil];
/* Use a null color transform to ensure device values */
@@ -3720,17 +3893,23 @@ static void create_my_win(void *cntx) {
#endif /* >= 10.6 */
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1040
- /* >= 10.6+ device colors don't work on secondary display, need null transform. */
- /* < 10.6 null transform doesn't work. */
+ /* >= 10.6+ device colors don't work on secondary displays and need a null transform. */
+ /* < 10.6 null transform doesn't work, but isn't needed. */
- if (Gestalt(gestaltSystemVersionMajor, &MacMajVers) == noErr
+ if (
+#ifdef NEVER
+ Gestalt(gestaltSystemVersionMajor, &MacMajVers) == noErr
&& Gestalt(gestaltSystemVersionMinor, &MacMinVers) == noErr
&& Gestalt(gestaltSystemVersionBugFix, &MacBFVers) == noErr
&& MacMajVers >= 10 && MacMinVers >= 6
+#else
+ floor(kCFCoreFoundationVersionNumber) >= kCFCoreFoundationVersionNumber10_6
+#endif
+
&& cx->nscs == NULL) {
warning("Unable to create null color transform - test colors may be wrong!");
}
-#endif
+#endif /* >= 1040 */
cx->err = 0;
}
@@ -3750,7 +3929,7 @@ double r, double g, double b /* Color values 0.0 - 1.0 */
double kr, kf;
int update_delay = 0;
- debugr("dispwin_set_color called\n");
+ debugrr2((errout, "dispwin_set_color called on disp '%s'\n",p->name));
if (p->nowin) {
return 1;
@@ -3941,8 +4120,15 @@ double r, double g, double b /* Color values 0.0 - 1.0 */
/* Stop the system going to sleep */
UpdateSystemActivity(OverallAct);
+/*
+ replacement ?
+ IOPMAssertionID assertionID;
+ IOPMAssertionDeclareUserActivity(CFSTR(""), kIOPMUserActiveLocal, &assertionID);
+*/
+
/* Make sure our window is brought to the front at least once, */
/* but not every time, in case the user wants to kill the application. */
+ /* is orderFrontRegardless a replacement ?? */
if (p->btf == 0){
OSStatus stat;
ProcessSerialNumber cpsn;
@@ -4748,6 +4934,11 @@ int ddebug /* >0 to print debug statements to stderr */
dispwin_del(p);
return NULL;
}
+ if ((p->description = strdup(disp->description)) == NULL) {
+ debugr2((errout,"new_dispwin: Malloc failed\n"));
+ dispwin_del(p);
+ return NULL;
+ }
p->ddid = disp->ddid; /* Display we're working on */
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
@@ -4816,7 +5007,7 @@ int ddebug /* >0 to print debug statements to stderr */
if (p->rdepth != p->ndepth) {
if (!p->warned) {
- warning("new_dispwin: Frame buffer depth %d doesn't matcv VideoLUT %d",p->rdepth, p->ndepth);
+ warning("new_dispwin: Frame buffer depth %d doesn't match VideoLUT %d",p->rdepth, p->ndepth);
p->warned = 1;
}
}
@@ -4975,20 +5166,25 @@ int ddebug /* >0 to print debug statements to stderr */
/* open the display */
p->mydisplay = XOpenDisplay(bname);
- if(!p->mydisplay) {
- debugr2((errout,"new_dispwin: Unable to open display '%s'\n",bname));
+ if (!p->mydisplay) {
+ debugrr2((errout,"new_dispwin: Unable to open display '%s'\n",bname));
dispwin_del(p);
free(bname);
return NULL;
}
+ debugrr2((errout,"new_dispwin: Opened display '%s' OK\n",bname));
free(bname);
- debugr("new_dispwin: Opened display OK\n");
if ((p->name = strdup(disp->name)) == NULL) {
debugr2((errout,"new_dispwin: Malloc failed\n"));
dispwin_del(p);
return NULL;
}
+ if ((p->description = strdup(disp->description)) == NULL) {
+ debugr2((errout,"new_dispwin: Malloc failed\n"));
+ dispwin_del(p);
+ return NULL;
+ }
p->myscreen = disp->screen;
p->myuscreen = disp->uscreen;
p->myrscreen = disp->rscreen;
@@ -5181,7 +5377,7 @@ int ddebug /* >0 to print debug statements to stderr */
}
}
- debugr2((errout,"new_dispwin: %s fdepth %d, rdepth %d, ndepth %d, edepth %d, r/g/b shifts %d %d %d\n", vinfo->class != TrueColor ? "TreuColor" : "DirectColor", p->fdepth,p->rdepth,p->ndepth,p->edepth, p->shift[0], p->shift[1], p->shift[2]));
+ debugrr2((errout,"new_dispwin: %s fdepth %d, rdepth %d, ndepth %d, edepth %d, r/g/b shifts %d %d %d\n", vinfo->class != TrueColor ? "TreuColor" : "DirectColor", p->fdepth,p->rdepth,p->ndepth,p->edepth, p->shift[0], p->shift[1], p->shift[2]));
if (nowin == 0) { /* Create a window */
unsigned long attrmask = 0;
@@ -5228,6 +5424,8 @@ int ddebug /* >0 to print debug statements to stderr */
p->ww = wi;
p->wh = he;
+ debugrr2((errout,"new_dispwin: at %d, %d size %d, %d\n",p->tx,p->ty,p->ww,p->wh));
+
/* Setup Size Hints */
mysizehints.flags = PPosition | USSize;
mysizehints.x = xo;
@@ -5630,7 +5828,7 @@ int ddebug /* >0 to print debug statements to stderr */
p->native = native &= ~2;
}
- debugr("new_dispwin: return sucessfully\n");
+ debugr("new_dispwin: return successfully\n");
return p;
}
@@ -5887,7 +6085,8 @@ static int gcc_bug_fix(int i) {
#include "numlib.h"
/* Flag = 0x0000 = default */
-/* Flag & 0x0001 = list ChromCast's */
+/* Flag & 0x0001 = list ChromeCast's */
+/* Flag & 0x0002 = list VTPG's's */
static void usage(int flag, char *diag, ...) {
disppath **dp;
fprintf(stderr,"Test display patch window, Set Video LUTs, Install profiles, Version %s\n",ARGYLL_VERSION_STR);
@@ -5923,13 +6122,13 @@ static void usage(int flag, char *diag, ...) {
free_disppaths(dp);
fprintf(stderr," -dweb[:port] Display via web server at port (default 8080)\n");
fprintf(stderr," -dcc[:n] Display via n'th ChromeCast (default 1, ? for list)\n");
- if (flag & 0x001) {
+ if (flag & 0x0001) {
ccast_id **ids;
if ((ids = get_ccids()) == NULL) {
- fprintf(stderr," ** Error discovering ChromCasts **\n");
+ fprintf(stderr," ** Error discovering ChromeCasts **\n");
} else {
if (ids[0] == NULL)
- fprintf(stderr," ** No ChromCasts found **\n");
+ fprintf(stderr," ** No ChromeCasts found **\n");
else {
int i;
for (i = 0; ids[i] != NULL; i++)
@@ -5942,8 +6141,28 @@ static void usage(int flag, char *diag, ...) {
fprintf(stderr," -dmadvr Display via MadVR Video Renderer\n");
#endif
+#ifdef ENABLE_VTPGLUT
+ fprintf(stderr," -dvtpg[:n] Display via n'th Video Test Patch Generator (default 1, ? for list)\n");
+ if (flag & 0x0002) {
+ icompaths *icmps;
+ if ((icmps = new_icompaths_sel(g_log, icomt_vtpg | icomt_portattr_all)) != NULL) {
+ icompath **paths;
+ if ((paths = icmps->dpaths[dtix_vtpg]) != NULL) {
+ int i;
+ for (i = 0; ; i++) {
+ if (paths[i] == NULL)
+ break;
+ fprintf(stderr," %d = '%s'\n",i+1,paths[i]->name);
+ }
+ } else
+ fprintf(stderr," ** No VTPG's found **\n");
+ }
+ }
+#endif
+
fprintf(stderr," -P ho,vo,ss[,vs] Position test window and scale it\n");
fprintf(stderr," -F Fill whole screen with black background\n");
+ fprintf(stderr," -E Video encode output as (16-235)/255 \"TV\" levels\n");
fprintf(stderr," -i Run forever with random values\n");
fprintf(stderr," -G filename Display RGB colors from CGATS (ie .ti1) file\n");
fprintf(stderr," -C r.rr,g.gg,b.bb Add this RGB color to list to be displayed\n");
@@ -5954,7 +6173,7 @@ static void usage(int flag, char *diag, ...) {
fprintf(stderr," -s filename Save the currently loaded Video LUT to 'filename'\n");
fprintf(stderr," -c Load a linear display calibration\n");
fprintf(stderr," -V Verify that calfile/profile cal. is currently loaded in LUT\n");
- fprintf(stderr," -I Install profile for display and use it's calibration\n");
+ fprintf(stderr," -I Install profile for display and use its calibration\n");
fprintf(stderr," -U Un-install profile for display\n");
fprintf(stderr," -S d Specify the install/uninstall scope for OS X [nlu] or X11/Vista [lu]\n");
fprintf(stderr," d is one of: n = network, l = local system, u = user (default)\n");
@@ -5981,6 +6200,9 @@ main(int argc, char *argv[]) {
#ifdef NT
int madvrdisp = 0; /* NZ for MadVR display */
#endif
+#ifdef ENABLE_VTPGLUT
+ int vtpgdisp = 0; /* NZ for Video Test Pattern Generator, == list index */
+#endif
disppath *disp = NULL; /* Display being used */
double hpatscale = 1.0, vpatscale = 1.0; /* scale factor for test patch size */
double ho = 0.0, vo = 0.0; /* Test window offsets, -1.0 to 1.0 */
@@ -6073,7 +6295,7 @@ main(int argc, char *argv[]) {
ccdisp = atoi(na+3);
if (ccdisp <= 0)
- usage(0,"ChromCast number must be in range 1..N");
+ usage(0,"ChromeCast number must be in range 1..N");
}
fa = nfa;
#ifdef NT
@@ -6082,6 +6304,20 @@ main(int argc, char *argv[]) {
madvrdisp = 1;
fa = nfa;
#endif
+#ifdef ENABLE_VTPGLUT
+ } else if (strncmp(na,"vtpg",4) == 0
+ || strncmp(na,"VTPG",4) == 0) {
+ vtpgdisp = 1;
+ if (na[4] == ':') {
+ if (na[3] < '0' || na[3] > '9')
+ usage(0x0002,"Available VTPG's");
+
+ vtpgdisp = atoi(na+3);
+ if (vtpgdisp <= 0)
+ usage(0,"VTPG number must be in range 1..N");
+ }
+ fa = nfa;
+#endif /* ENABLE_VTPGLUT */
} else {
#if defined(UNIX_X11)
int ix, iv;
@@ -6259,8 +6495,13 @@ main(int argc, char *argv[]) {
#endif
/* Bomb on bad combinations (not all are being detected) */
- if (installprofile && calname[0] == '\000')
- error("Can't install or uninstall a displays profile without profile argument");
+ if (installprofile == 1 && calname[0] == '\000')
+ error("Can't install a displays profile without profile argument");
+
+#if !defined(UNIX)
+ if (installprofile == 2 && calname[0] == '\000')
+ error("Can't uninstall a displays profile without profile argument");
+#endif
if (verify && calname[0] == '\000' && loadprofile == 0)
error("No calibration/profile provided to verify against");
@@ -6285,17 +6526,17 @@ main(int argc, char *argv[]) {
} else if (ccdisp != 0) {
ccast_id **ids;
if ((ids = get_ccids()) == NULL) {
- printf("Error - discovering ChromCasts failed\n");
+ printf("Error - discovering ChromeCasts failed\n");
return -1;
}
if (ids[0] == NULL) {
- printf("Error - there are no ChromCasts to use\n");
+ printf("Error - there are no ChromeCasts to use\n");
return -1;
}
for (i = 0; ids[i] != NULL; i++)
;
if (ccdisp < 1 || ccdisp > i) {
- printf("Error - chosen ChromCasts (%d) is outside list (1..%d)\n",ccdisp,i);
+ printf("Error - chosen ChromeCasts (%d) is outside list (1..%d)\n",ccdisp,i);
return -1;
}
@@ -6427,10 +6668,10 @@ main(int argc, char *argv[]) {
if (rv == 2)
warning("Profile '%s' not found to uninstall!",calname);
else
- error("Error trying to uninstall profile '%s'!",calname);
+ error("Error trying to uninstall profile for display '%s'!",dw->description);
}
if (verb) {
- printf("Un-Installed '%s'\n",calname);
+ printf("Un-Installed profile for display '%s'\n",dw->description);
}
}
@@ -6582,25 +6823,28 @@ main(int argc, char *argv[]) {
dw->r->v[j][i] = val + w * (cal[j][ix+1] - val);
}
}
- /* If the calibration was created with a restricted range video encoding, */
- /* ensure that the installed calibration applies this encoding. */
- if (out_tvenc) {
- for (i = 0; i < dw->r->nent; i++) {
- for (j = 0; j < 3; j++) {
- dw->r->v[j][i] = (dw->r->v[j][i] * (235.0-16.0) + 16.0)/255.0;
-
- /* For video encoding the extra bits of precision are created by bit */
- /* shifting rather than scaling, so we need to scale the fp value to */
- /* account for this. */
- if (dw->edepth > 8)
- dw->r->v[j][i] = (dw->r->v[j][i] * 255 * (1 << (dw->edepth - 8)))
- /((1 << dw->edepth) - 1.0);
- }
+ debug("Got cal file calibration\n");
+ }
+
+ /* If the calibration was created with a restricted range video encoding, */
+ /* ensure that the installed calibration applies this encoding. */
+ if (out_tvenc) {
+ if (verb)
+ printf("Using output TV encoding range of (16-235)/255\n");
+ for (i = 0; i < dw->r->nent; i++) {
+ for (j = 0; j < 3; j++) {
+ dw->r->v[j][i] = (dw->r->v[j][i] * (235.0-16.0) + 16.0)/255.0;
+
+ /* For video encoding the extra bits of precision are created by bit */
+ /* shifting rather than scaling, so we need to scale the fp value to */
+ /* account for this. */
+ if (dw->edepth > 8)
+ dw->r->v[j][i] = (dw->r->v[j][i] * 255 * (1 << (dw->edepth - 8)))
+ /((1 << dw->edepth) - 1.0);
}
}
-
- debug("Got cal file calibration\n");
}
+
if (ccg != NULL)
ccg->del(ccg);
if (icco != NULL)