diff options
Diffstat (limited to 'spectro/dispwin.c')
-rw-r--r-- | spectro/dispwin.c | 795 |
1 files changed, 647 insertions, 148 deletions
diff --git a/spectro/dispwin.c b/spectro/dispwin.c index fffbaee..368f707 100644 --- a/spectro/dispwin.c +++ b/spectro/dispwin.c @@ -31,6 +31,10 @@ * Should add dithering support to overcome 8 bit limitations of * non-RAMDAC access or limited RAMDAC depth. (How do we easily * determine the latter ??) + * + * For X11/XRANDR, should we check for and save/restore CscMatrix property ?? + * - or should we assumed that the use intends to use this to manually calibrate the display ?? + * See <http://us.download.nvidia.com/XFree86/Linux-x86/364.12/README/xrandrextension.html#CscMatrix> */ #include <stdio.h> @@ -69,7 +73,7 @@ # endif #endif -#ifdef __APPLE__ +#ifdef UNIX_APPLE /* Note that the new ColorSync API is defined in @@ -113,14 +117,14 @@ typedef float CGFloat; #endif #endif /* !NSINTEGER_DEFINED */ -#include <IOKit/Graphics/IOGraphicsLib.h> +#include <IOKit/graphics/IOGraphicsLib.h> #if __MAC_OS_X_VERSION_MAX_ALLOWED <= 1060 /* This wasn't declared in 10.6, although it is needed */ CFUUIDRef CGDisplayCreateUUIDFromDisplayID (uint32_t displayID); #endif /* < 10.6 */ -#endif /* __APPLE__ */ +#endif /* UNIX_APPLE */ #define VERIFY_TOL (1.0/255.0) #undef DISABLE_RANDR /* Disable XRandR code */ @@ -388,7 +392,7 @@ disppath **get_displays() { #endif /* NT */ -#ifdef __APPLE__ +#ifdef UNIX_APPLE /* Note :- some recent releases of OS X have a feature which */ /* automatically adjusts the screen brigtness with ambient level. */ /* We may have to find a way of disabling this during calibration and profiling. */ @@ -548,7 +552,7 @@ disppath **get_displays() { } free(dids); -#endif /* __APPLE__ */ +#endif /* UNIX_APPLE */ #if defined(UNIX_X11) int i, j, k; @@ -636,8 +640,8 @@ disppath **get_displays() { /* Look at all the screens outputs */ for (jj = j = 0; j < scrnres->noutput; j++) { - XRROutputInfo *outi; - XRRCrtcInfo *crtci; + XRROutputInfo *outi = NULL; + XRRCrtcInfo *crtci = NULL; if ((outi = XRRGetOutputInfo(mydisplay, scrnres, scrnres->outputs[j])) == NULL) { debugrr("XRRGetOutputInfo failed\n"); @@ -649,12 +653,13 @@ disppath **get_displays() { if (outi->connection == RR_Disconnected || outi->crtc == None) { + XRRFreeOutputInfo(outi); continue; } /* Check that the VideoLUT's are accessible */ { - XRRCrtcGamma *crtcgam; + XRRCrtcGamma *crtcgam = NULL; debugrr("Checking XRandR 1.2 VideoLUT access\n"); if ((crtcgam = XRRGetCrtcGamma(mydisplay, outi->crtc)) == NULL @@ -666,8 +671,11 @@ disppath **get_displays() { disps = NULL; j = scrnres->noutput; i = dcount; + XRRFreeOutputInfo(outi); continue; /* Abort XRandR 1.2 */ } + if (crtcgam != NULL) + XRRFreeGamma(crtcgam); } #ifdef NEVER { @@ -692,6 +700,7 @@ disppath **get_displays() { if ((disps = (disppath **)calloc(sizeof(disppath *), 1 + 1)) == NULL) { debugrr("get_displays failed on malloc\n"); XRRFreeCrtcInfo(crtci); + XRRFreeOutputInfo(outi); XRRFreeScreenResources(scrnres); XCloseDisplay(mydisplay); return NULL; @@ -701,6 +710,7 @@ disppath **get_displays() { sizeof(disppath *) * (ndisps + 2))) == NULL) { debugrr("get_displays failed on malloc\n"); XRRFreeCrtcInfo(crtci); + XRRFreeOutputInfo(outi); XRRFreeScreenResources(scrnres); XCloseDisplay(mydisplay); return NULL; @@ -711,6 +721,7 @@ disppath **get_displays() { if ((disps[ndisps] = calloc(sizeof(disppath),1)) == NULL) { debugrr("get_displays failed on malloc\n"); XRRFreeCrtcInfo(crtci); + XRRFreeOutputInfo(outi); XRRFreeScreenResources(scrnres); XCloseDisplay(mydisplay); free_disppaths(disps); @@ -741,6 +752,7 @@ disppath **get_displays() { if ((disps[ndisps]->description = strdup(desc2)) == NULL) { debugrr("get_displays failed on malloc\n"); XRRFreeCrtcInfo(crtci); + XRRFreeOutputInfo(outi); XRRFreeScreenResources(scrnres); XCloseDisplay(mydisplay); free_disppaths(disps); @@ -756,6 +768,7 @@ disppath **get_displays() { if ((disps[ndisps]->name = strdup(dnbuf)) == NULL) { debugrr("get_displays failed on malloc\n"); XRRFreeCrtcInfo(crtci); + XRRFreeOutputInfo(outi); XRRFreeScreenResources(scrnres); XCloseDisplay(mydisplay); free_disppaths(disps); @@ -809,6 +822,7 @@ disppath **get_displays() { if ((disps[ndisps]->edid = malloc(sizeof(unsigned char) * ret_len)) == NULL) { debugrr("get_displays failed on malloc\n"); XRRFreeCrtcInfo(crtci); + XRRFreeOutputInfo(outi); XRRFreeScreenResources(scrnres); XCloseDisplay(mydisplay); free_disppaths(disps); @@ -833,7 +847,6 @@ disppath **get_displays() { } XRRFreeOutputInfo(outi); } - XRRFreeScreenResources(scrnres); } XSetErrorHandler(NULL); @@ -1136,15 +1149,16 @@ void free_a_disppath(disppath *path) { /* ----------------------------------------------- */ -/* For VideoLUT/RAMDAC use, we assume that the number of entries in the RAMDAC */ -/* meshes perfectly with the display raster depth, so that we can */ -/* figure out how to apportion device values. We fail if they don't */ -/* seem to mesh. */ +/* For VideoLUT/RAMDAC use, we assume that the frame buffer */ +/* may map through some intermediate hardware or lookup */ +/* into a RAMDAC index. */ /* !!! Would be nice to add an error message return to dispwin and */ /* !!! pass errors back to it so that the detail can be reported */ /* !!! to the user. */ +static void dispwin_dump_ramdac(FILE *fp, ramdac *r); + /* Get RAMDAC values. ->del() when finished. */ /* Return NULL if not possible */ static ramdac *dispwin_get_ramdac(dispwin *p) { @@ -1168,9 +1182,11 @@ static ramdac *dispwin_get_ramdac(dispwin *p) { debugr("dispwin_get_ramdac failed on malloc()\n"); return NULL; } - r->pdepth = p->pdepth; - r->nent = (1 << p->pdepth); - r->clone = dispwin_clone_ramdac; + r->fdepth = p->fdepth; + r->rdepth = p->rdepth; + r->ndepth = p->ndepth; + r->nent = p->nent; + r->clone = dispwin_clone_ramdac; r->setlin = dispwin_setlin_ramdac; r->del = dispwin_del_ramdac; @@ -1186,9 +1202,9 @@ static ramdac *dispwin_get_ramdac(dispwin *p) { } /* GetDeviceGammaRamp() is hard coded for 3 x 256 entries (Quantize) */ - if (r->nent != 256) { + if (256 != r->nent) { free(r); - debugr2((errout,"GetDeviceGammaRamp() is hard coded for nent == 256, and we've got nent = %d!\n",r->nent)); + debugr2((errout,"GetDeviceGammaRamp number of entries %d inconsistent with expected value %d\n",256,p->nent)); return NULL; } @@ -1204,7 +1220,7 @@ static ramdac *dispwin_get_ramdac(dispwin *p) { } #endif /* NT */ -#ifdef __APPLE__ +#ifdef UNIX_APPLE unsigned int nent; CGGammaValue vals[3][16385]; @@ -1220,8 +1236,8 @@ static ramdac *dispwin_get_ramdac(dispwin *p) { return NULL; } - if (nent != (1 << p->pdepth)) { - debugr2((errout,"CGGetDisplayTransferByTable number of entries %d mismatches screen depth %d\n",nent,p->pdepth)); + if (nent != p->nent) { + debugr2((errout,"CGGetDisplayTransferByTable number of entries %u inconsistent with previous value %d\n",nent,p->nent)); return NULL; } @@ -1231,8 +1247,10 @@ static ramdac *dispwin_get_ramdac(dispwin *p) { return NULL; } - r->pdepth = p->pdepth; - r->nent = (1 << p->pdepth); + r->fdepth = p->fdepth; + r->rdepth = p->rdepth; + r->ndepth = p->ndepth; + r->nent = p->nent; r->clone = dispwin_clone_ramdac; r->setlin = dispwin_setlin_ramdac; r->del = dispwin_del_ramdac; @@ -1252,7 +1270,7 @@ static ramdac *dispwin_get_ramdac(dispwin *p) { r->v[j][i] = vals[j][i]; } } -#endif /* __APPLE__ */ +#endif /* UNIX_APPLE */ #if defined(UNIX_X11) unsigned short vals[3][16384]; @@ -1275,13 +1293,8 @@ static ramdac *dispwin_get_ramdac(dispwin *p) { nent = crtcgam->size; - if (nent > 16384) { - debugr("XRRGetCrtcGammaSize has more entries than we can handle\n"); - return NULL; - } - - if (nent != (1 << p->pdepth)) { - debugr2((errout,"XRRGetCrtcGammaSize number of entries %d mismatches screen depth %d bits\n",nent,(1 << p->pdepth))); + if (nent != p->nent) { + debugr2((errout,"XRRGetCrtcGammaSize number of entries %d inconsistent with previous value\n",nent,p->nent)); return NULL; } @@ -1331,8 +1344,8 @@ static ramdac *dispwin_get_ramdac(dispwin *p) { return NULL; } - if (nent > 16384) { - debugr("XF86VidModeGetGammaRampSize has more entries than we can handle\n"); + if (nent != p->nent) { + debugr2((errout,"XF86VidModeGetGammaRampSize number of entries %d inconsistent with previous value\n",nent,p->nent)); return NULL; } @@ -1340,11 +1353,6 @@ static ramdac *dispwin_get_ramdac(dispwin *p) { debugr("XF86VidModeGetGammaRamp failed\n"); return NULL; } - - if (nent != (1 << p->pdepth)) { - debugr2((errout,"CGGetDisplayTransferByTable number of entries %d mismatches screen depth %d bits\n",nent,(1 << p->pdepth))); - return NULL; - } } /* Allocate a ramdac */ @@ -1353,9 +1361,11 @@ static ramdac *dispwin_get_ramdac(dispwin *p) { return NULL; } - r->pdepth = p->pdepth; - r->nent = (1 << p->pdepth); - r->clone = dispwin_clone_ramdac; + r->fdepth = p->fdepth; + r->rdepth = p->rdepth; + r->ndepth = p->ndepth; + r->nent = p->nent; + r->clone = dispwin_clone_ramdac; r->setlin = dispwin_setlin_ramdac; r->del = dispwin_del_ramdac; for (j = 0; j < 3; j++) { @@ -1379,7 +1389,7 @@ static ramdac *dispwin_get_ramdac(dispwin *p) { return r; } -#ifdef __APPLE__ +#ifdef UNIX_APPLE /* Various support functions */ #if __MAC_OS_X_VERSION_MAX_ALLOWED < 1060 @@ -1643,7 +1653,7 @@ static void *cur_colorsync_ref(dispwin *p) { return cspr; } -#endif /* __APPLE__ */ +#endif /* UNIX_APPLE */ /* Set the RAMDAC values. */ /* Return nz if not possible */ @@ -1666,6 +1676,7 @@ static int dispwin_set_ramdac(dispwin *p, ramdac *r, int persist) { for (j = 0; j < 3; j++) { for (i = 0; i < r->nent; i++) { double vv = r->v[j][i]; + if (vv < 0.0) vv = 0.0; else if (vv > 1.0) @@ -1676,12 +1687,15 @@ static int dispwin_set_ramdac(dispwin *p, ramdac *r, int persist) { if (SetDeviceGammaRamp(p->hdc, vals) == 0) { debugr2((errout,"dispwin_set_ramdac failed on SetDeviceGammaRamp() with error %d\n",GetLastError())); +#ifdef NEVER + dispwin_dump_ramdac(stderr, r); +#endif return 1; } GdiFlush(); #endif /* NT */ -#ifdef __APPLE__ +#ifdef UNIX_APPLE { /* Transient first */ CGGammaValue vals[3][16384]; @@ -2115,7 +2129,7 @@ static int dispwin_set_ramdac(dispwin *p, ramdac *r, int persist) { } #endif /* < 10.6 */ -#endif /* __APPLE__ */ +#endif /* UNIX_APPLE */ #if defined(UNIX_X11) unsigned short vals[3][16384]; @@ -2214,6 +2228,24 @@ ramdac *dispwin_clone_ramdac(ramdac *r) { return nr; } +/* Debug dump ramdac */ +static void dispwin_dump_ramdac(FILE *fp, ramdac *r) { + int i, j; + + fprintf(fp,"Ramdac fdepth %d, rdepth %d, ndepth %d, nent %d\n", + r->fdepth, r->rdepth, r->ndepth, r->nent); + + for (i = 0; i < r->nent; i++) { + int note = 0; + for (j = 0; j < 3; j++) { + if (r->v[j][i] < 0.0 || r->v[j][i] > 1.0 + || (i > 0 && r->v[j][i] < r->v[j][i-1])) + note = 1; + } + fprintf(fp," %d: %f %f %f%s\n",i, r->v[0][i], r->v[1][i], r->v[2][i], note ? " #" : ""); + } +} + /* Set the ramdac values to linear */ void dispwin_setlin_ramdac(ramdac *r) { int i, j; @@ -2522,7 +2554,7 @@ int dispwin_install_profile(dispwin *p, char *fname, ramdac *r, p_scope scope) { } #endif /* OS X || Linux */ -#ifdef __APPLE__ +#ifdef UNIX_APPLE #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 { @@ -2685,7 +2717,7 @@ int dispwin_install_profile(dispwin *p, char *fname, ramdac *r, p_scope scope) { return 0; } #endif /* 10.6 and prior */ -#endif /* __APPLE__ */ +#endif /* UNIX_APPLE */ #if defined(UNIX_X11) && defined(USE_UCMM) { @@ -2862,7 +2894,7 @@ int dispwin_uninstall_profile(dispwin *p, char *fname, p_scope scope) { } } #endif /* OS X || Linux */ -#ifdef __APPLE__ +#ifdef UNIX_APPLE #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 { char *dpath; /* Un-install file path */ @@ -2980,7 +3012,7 @@ int dispwin_uninstall_profile(dispwin *p, char *fname, p_scope scope) { return 0; } #endif /* 10.6 and prior */ -#endif /* __APPLE__ */ +#endif /* UNIX_APPLE */ #if defined(UNIX_X11) && defined(USE_UCMM) { @@ -3043,7 +3075,7 @@ icmFile *dispwin_get_profile(dispwin *p, char *name, int mxlen) { } #endif /* NT */ -#ifdef __APPLE__ +#ifdef UNIX_APPLE #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 { char *dpath; /* Read file path */ @@ -3187,7 +3219,7 @@ icmFile *dispwin_get_profile(dispwin *p, char *name, int mxlen) { return rd_fp; } #endif /* 10.5 and prior */ -#endif /* __APPLE__ */ +#endif /* UNIX_APPLE */ #if defined(UNIX_X11) && defined(USE_UCMM) /* Try and get the currently installed profile from ucmm */ @@ -3454,7 +3486,7 @@ static void dispwin_uninstall_signal_handlers(dispwin *p) { /* ----------------------------------------------- */ /* Test patch window specific declarations */ -#ifdef __APPLE__ +#ifdef UNIX_APPLE @class DWWin; @class DWView; @@ -3467,6 +3499,8 @@ typedef struct { #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1040 NSColorSpace *nscs; /* Colorspace from profile */ #endif + NSRect rect; /* Size and position to create window */ + int err; /* Error code */ } osx_cntx_t; // - - - - - - - - - - - - - - - - - - - - - - - - - @@ -3545,6 +3579,15 @@ unsigned char emptyCursor[43] = { @end +/* Function called back by main thread to trigger a drawRect */ + +static void doSetNeedsDisplay(void *cntx) { + osx_cntx_t *cx = (osx_cntx_t *)cntx; + + [cx->view setNeedsDisplay: YES ]; + + cx->err = 0; +} // - - - - - - - - - - - - - - - - - - - - - - - - - @interface DWWin : NSWindow { @@ -3582,7 +3625,9 @@ unsigned char emptyCursor[43] = { @end /* Create our window */ -static void create_my_win(NSRect rect, osx_cntx_t *cx) { +/* We run this on the main thread using a custom message */ +static void create_my_win(void *cntx) { + osx_cntx_t *cx = (osx_cntx_t *)cntx; dispwin *p = cx->p; SInt32 MacMajVers, MacMinVers, MacBFVers; void *cspr = NULL; /* ColorSync profile ref. */ @@ -3607,7 +3652,7 @@ static void create_my_win(NSRect rect, osx_cntx_t *cx) { } /* Create Window */ - cx->window = [[DWWin alloc] initWithContentRect: rect + cx->window = [[DWWin alloc] initWithContentRect: cx->rect styleMask: NSBorderlessWindowMask backing: NSBackingStoreBuffered defer: YES @@ -3626,7 +3671,8 @@ static void create_my_win(NSRect rect, osx_cntx_t *cx) { /* Moves the window to the front of the screen list within its level, */ /* and show the window (i.e. make it "key") */ - /* Trigger crash on OS X 10.11 El Capitan ? */ + /* Trigger warning on OS X 10.11 El Capitan ? */ + /* (Doesn't happen using 1.6.3 which ran everything in the main thread.) */ [cx->window makeKeyAndOrderFront: nil]; /* Use a null color transform to ensure device values */ @@ -3686,9 +3732,10 @@ static void create_my_win(NSRect rect, osx_cntx_t *cx) { } #endif + cx->err = 0; } -#endif /* __APPLE__ */ +#endif /* UNIX_APPLE */ /* ----------------------------------------------- */ @@ -3726,22 +3773,24 @@ double r, double g, double b /* Color values 0.0 - 1.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 (p->pdepth > 8) - p->r_rgb[j] = (p->s_rgb[j] * 255 * (1 << (p->pdepth - 8))) - /((1 << p->pdepth) - 1.0); + if (p->edepth > 8) + p->r_rgb[j] = (p->s_rgb[j] * 255 * (1 << (p->edepth - 8))) + /((1 << p->edepth) - 1.0); } } //if (p->out_tvenc) { //printf(" %d: 8 bit tv = s_rgb %f %f %f\n",j, p->s_rgb[0], p->s_rgb[1], p->s_rgb[2]); -//printf(" %d: %d bitraster r_rgb %f %f %f\n",j, p->pdepth,p->r_rgb[0], p->r_rgb[1], p->r_rgb[2]); +//printf(" %d: %d bitraster r_rgb %f %f %f\n",j, p->edepth,p->r_rgb[0], p->r_rgb[1], p->r_rgb[2]); //} /* Use ramdac for high precision native output. */ /* The ramdac is used to hold the lsb that the frame buffer */ /* doesn't hold. */ if ((p->native & 1) == 1) { - double prange = p->r->nent - 1.0; + double frange = (1 << p->fdepth) - 1.0; + double rrange = (1 << p->rdepth) - 1.0; + double nrange = p->nent - 1.0; p->r->setlin(p->r); /* In case something else altered this */ @@ -3756,9 +3805,66 @@ double r, double g, double b /* Color values 0.0 - 1.0 */ if (p->out_tvenc && p->edepth > 8) vv = (vv * 255 * (1 << (p->edepth - 8)))/((1 << p->edepth) - 1.0); - tt = (int)(vv * prange + 0.5); - p->r_rgb[j] = (double)tt/prange; /* RAMDAC output Quantized value */ + /* Determine the ramdac index that the quantized frame buffer */ + /* value will make use of */ +#ifdef NT + /* Assume all depths match, or linear mapping between them */ + tt = (int)(vv * frange + 0.5); /* Frame buffer value */ + p->r_rgb[j] = (double)tt/frange; /* Double frame buffer value */ + tt = (int)(tt/frange * rrange + 0.5); /* expected RAMDAC index */ + tt = (int)(tt/rrange * nrange + 0.5); /* actual RAMDAC index */ +#endif +#ifdef UNIX_APPLE + /* We assume linear mapping with perfect rounding between rdepth and ndepth */ + tt = (int)(vv * frange + 0.5); /* Frame buffer value */ + p->r_rgb[j] = (double)tt/frange; /* Double frame buffer value */ + tt = (int)(tt/frange * rrange + 0.5); /* expected RAMDAC index */ + tt = (int)(tt/rrange * nrange + 0.5); /* actual RAMDAC index */ +#endif +#if defined(UNIX_X11) + /* We assume linear mapping with perfect rounding between rdepth and ndepth */ + tt = (int)(vv * frange + 0.5); /* Frame buffer value */ + p->r_rgb[j] = (double)tt/frange; /* Double frame buffer value */ + tt = p->rmap[j][tt]; /* expected RAMDAC index */ + tt = (int)(tt/rrange * nrange + 0.5); /* actual RAMDAC index */ +#endif + +#ifdef NEVER // Just set entry we think will get hit p->r->v[j][tt] = vv; +#else + + /* Set the three entries around target and create ramp either side, + to allow for some video cards not having a precise + definition of what value translates to what frame buffer value. */ + { + int i; + double maxv = 1.0; + + if (p->out_tvenc && p->edepth > 8) + maxv = (maxv * 255 * (1 << (p->edepth - 8)))/((1 << p->edepth) - 1.0); + + if ((tt-1) == 0) { + p->r->v[j][tt-1] = vv; + } else { + for (i = 0; i <= (tt-1); i++) + p->r->v[j][i] = vv * i/(tt-1); + } + + p->r->v[j][tt] = vv; + + if ((tt+1) == (p->r->nent-1)) { + p->r->v[j][tt+1] = vv; + } else { + for (i = tt+1; i < p->r->nent; i++) + p->r->v[j][i] = vv + (maxv - vv) * (i - (tt+1))/((p->r->nent-1) - (tt+1)); + } + +#ifdef NEVER + for (i = 0; i < p->r->nent; i++) + printf("~1 %d, %d -> %f\n",j,i,p->r->v[j][i]); +#endif + } +#endif //printf(" cell[%d] = r_rgb %f, cell val %f\n",tt, p->r_rgb[j], vv); } @@ -3796,7 +3902,9 @@ double r, double g, double b /* Color values 0.0 - 1.0 */ #endif p->colupd++; -//printf("~1 set color %f %f %f\n", p->r_rgb[0], p->r_rgb[1], p->r_rgb[2]); + + debugr2((errout,"dispwin_set_color about to paint color %f %f %f\n", + p->r_rgb[0], p->r_rgb[1], p->r_rgb[2])); /* Trigger a WM_PAINT */ if (!InvalidateRect(p->hwnd, NULL, FALSE)) { @@ -3810,13 +3918,14 @@ double r, double g, double b /* Color values 0.0 - 1.0 */ while (p->colupd != p->colupde && p->cberror == 0) { msec_sleep(10); } -//printf("~1 paint done\n"); + + debugr2((errout,"dispwin_set_color paint done\n")); } #endif /* NT */ /* - - - - - - - - - - - - - - */ -#ifdef __APPLE__ +#ifdef UNIX_APPLE if (p->winclose) { return 2; @@ -3840,11 +3949,7 @@ double r, double g, double b /* Color values 0.0 - 1.0 */ if ((stat = GetCurrentProcess(&cpsn)) != noErr) { debugr2((errout,"GetCurrentProcess returned error %d\n",stat)); } else { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 - if ((stat = TransformProcessType(&cpsn, kProcessTransformToForegroundApplication)) != noErr) { - debugr2((errout,"TransformProcessType returned error %d\n",stat)); - } -#endif /* OS X 10.3 */ + // [window makeGetAndOrderFront:] ?? if ((stat = SetFrontProcess(&cpsn)) != noErr) { debugr2((errout,"SetFrontProcess returned error %d\n",stat)); } @@ -3852,40 +3957,56 @@ double r, double g, double b /* Color values 0.0 - 1.0 */ p->btf = 1; } - /* Trigger an update that fills window with r_rgb[] */ - [((osx_cntx_t *)(p->osx_cntx))->view setNeedsDisplay: YES ]; + /* Prepare to wait for events */ + ui_aboutToWait(); + + debugr2((errout,"dispwin_set_color about to paint color %f %f %f\n", + p->r_rgb[0], p->r_rgb[1], p->r_rgb[2])); + +// [((osx_cntx_t *)(p->osx_cntx))->view setNeedsDisplay: YES ]; + + /* Run the window creation in the main thread and wait for it */ + ui_runInMainThreadAndWait((void *)p->osx_cntx, doSetNeedsDisplay); + + /* Wait for any events generated by paint to complete */ + ui_waitForEvents(); + + debugr2((errout,"dispwin_set_color paint done\n")); if (tpool != nil) [tpool release]; -#endif /* __APPLE__ */ +#endif /* UNIX_APPLE */ /* - - - - - - - - - - - - - - */ #if defined(UNIX_X11) { - Colormap mycmap; - XColor col; - int vali[3]; + unsigned int vali[3]; + unsigned long fbval; /* Indicate that we've got activity to the X11 Screensaver */ XResetScreenSaver(p->mydisplay); - /* Quantize to 16 bit color */ + /* Quantize to frame buffer component depth */ for (j = 0; j < 3; j++) - vali[j] = (int)(65535.0 * p->r_rgb[j] + 0.5); + vali[j] = (int)(((1 << p->fdepth)-1.0) * p->r_rgb[j] + 0.5); - mycmap = DefaultColormap(p->mydisplay, p->myscreen); - col.red = vali[0]; - col.green = vali[1]; - col.blue = vali[2]; - XAllocColor(p->mydisplay, mycmap, &col); - XSetForeground(p->mydisplay, p->mygc, col.pixel); + /* Compose frame buffer pixel value */ + fbval = (vali[0] << p->shift[0]) + | (vali[1] << p->shift[1]) + | (vali[2] << p->shift[2]); + XSetForeground(p->mydisplay, p->mygc, fbval); + + debugr2((errout,"dispwin_set_color about to paint color %f %f %f\n", + p->r_rgb[0], p->r_rgb[1], p->r_rgb[2])); XFillRectangle(p->mydisplay, p->mywindow, p->mygc, p->tx, p->ty, p->tw, p->th); XSync(p->mydisplay, False); /* Make sure it happens */ + + debugr2((errout,"dispwin_set_color paint done\n")); } #endif /* UNXI X11 */ @@ -4029,6 +4150,7 @@ dispwin *p if (p->mth != NULL) { /* Message thread */ p->mth->del(p->mth); } + p->hwnd = NULL; } if (p->hdc != NULL) @@ -4038,7 +4160,7 @@ dispwin *p /* -------------------------------------------------- */ /* -------------------------------------------------- */ -#ifdef __APPLE__ +#ifdef UNIX_APPLE if (p->nowin == 0) { /* We have a window up */ restore_display(p); if (p->osx_cntx != NULL) { /* And we've allocated a context */ @@ -4061,7 +4183,7 @@ dispwin *p // ~~ // CGDisplayShowCursor(p->ddid); -#endif /* __APPLE__ */ +#endif /* UNIX_APPLE */ /* -------------------------------------------------- */ /* -------------------------------------------------- */ @@ -4071,22 +4193,43 @@ dispwin *p if (p->mydisplay != NULL) { if (p->nowin == 0) { /* We have a window up */ - XFreeGC(p->mydisplay, p->mygc); - XDestroyWindow(p->mydisplay, p->mywindow); + if (p->mygc != 0) + XFreeGC(p->mydisplay, p->mygc); + if (p->mywindow != 0) + XDestroyWindow(p->mydisplay, p->mywindow); } XCloseDisplay(p->mydisplay); + p->mydisplay = NULL; + } + { + int j; + for (j = 0; j < 3; j++) { + if (p->rmap[j] != NULL) { + free(p->rmap[j]); + p->rmap[j] = NULL; + } + } } debugr("finished\n"); + if (p->edid != NULL) + free(p->edid); + #endif /* UNXI X11 */ /* -------------------------------------------------- */ - if (p->name != NULL) + if (p->name != NULL) { free(p->name); - if (p->description != NULL) + p->name = NULL; + } + if (p->description != NULL) { free(p->description); - if (p->callout != NULL) + p->description = NULL; + } + if (p->callout != NULL) { free(p->callout); + p->callout = NULL; + } free(p); } @@ -4234,6 +4377,10 @@ static LRESULT CALLBACK MainWndProc( #endif /* NT */ +#ifdef UNIX_APPLE + +#endif /* UNIX_APPLE */ + #if defined(UNIX_X11) /* None */ #endif /* UNXI X11 */ @@ -4241,7 +4388,8 @@ static LRESULT CALLBACK MainWndProc( /* ----------------------------------------------- */ #ifdef NT -/* Thread to handle message processing, so that there is no delay */ +/* Thread to create the window if it doesn'r exist, */ +/* and handle message processing, so that there is no delay */ /* when the main thread is doing other things. */ int win_message_thread(void *pp) { dispwin *p = (dispwin *)pp; @@ -4333,7 +4481,7 @@ int win_message_thread(void *pp) { } if (UnregisterClass(p->AppName, NULL) == 0) { - warning("UnregisterClass failed, lasterr = %d\n",GetLastError()); + warning("UnregisterClass failed, lasterr = %d",GetLastError()); } p->hwnd = NULL; /* Signal it's been deleted */ @@ -4400,7 +4548,10 @@ int ddebug /* >0 to print debug statements to stderr */ ) { dispwin *p = NULL; - debug("new_dispwin called\n"); +#ifndef DEBUG + if (ddebug) +#endif + fprintf(errout, "new_dispwin called\n"); #if defined(UNIX_X11) && defined(USE_UCMM) dispwin_checkfor_colord(); /* Make colord functions available */ @@ -4444,6 +4595,8 @@ int ddebug /* >0 to print debug statements to stderr */ /* Basic object is initialised, so create a window */ + ui_UsingGUI(); + /* -------------------------------------------------- */ #ifdef NT { @@ -4511,7 +4664,7 @@ int ddebug /* >0 to print debug statements to stderr */ p->wh = he; /* It's a bit difficult to know how windows defines the display */ - /* depth. Microsofts doco is fuzzy, and typical values */ + /* depth. Microsoft's doco is fuzzy, and typical values */ /* for BITSPIXEL and PLANES are confusing (What does "32" and "1" */ /* mean ?) NUMCOLORS seems to be -1 on my box, and perhaps */ /* is only applicable to up to 256 paletized colors. The doco */ @@ -4530,12 +4683,17 @@ int ddebug /* >0 to print debug statements to stderr */ } bpp = GetDeviceCaps(p->hdc, COLORRES); if (bpp <= 0) - p->pdepth = 8; /* Assume this is so */ + p->fdepth = 8; /* Assume this is so */ else - p->pdepth = bpp/3; + p->fdepth = bpp/3; + p->rdepth = p->fdepth; /* Assume this is so */ + p->ndepth = 8; /* Assume this is so */ + p->nent = (1 << p->ndepth); p->edepth = 16; + debugr2((errout,"new_dispwin: fdepth %d, rdepth %d, ndepth %d, edepth %d\n", p->fdepth,p->rdepth,p->ndepth,p->edepth)); + if (nowin == 0) { /* We use a thread to process the window messages, so that */ @@ -4549,6 +4707,9 @@ int ddebug /* >0 to print debug statements to stderr */ p->wi = wi; p->he = he; + debugr2((errout,"new_dispwin about to create window\n")); + + /* Create the window and then process events */ if ((p->mth = new_athread(win_message_thread, (void *)p)) == NULL) { debugr2((errout, "new_dispwin: new_athread failed\n")); dispwin_del(p); @@ -4556,6 +4717,9 @@ int ddebug /* >0 to print debug statements to stderr */ } /* Wait for thread to run */ + /* (Hmm. This doesn't actually gurantee that our window has */ + /* been created yet ? */ + // ~~ should sync by sending a custom message and getting notified ? */ while (p->inited == 0) { msec_sleep(20); } @@ -4565,6 +4729,8 @@ int ddebug /* >0 to print debug statements to stderr */ dispwin_del(p); return NULL; } + + debugr2((errout,"new_dispwin window created\n")); } /* Install the signal handler to ensure cleanup */ @@ -4575,7 +4741,7 @@ int ddebug /* >0 to print debug statements to stderr */ /* -------------------------------------------------- */ /* -------------------------------------------------- */ -#ifdef __APPLE__ +#ifdef UNIX_APPLE if ((p->name = strdup(disp->name)) == NULL) { debugr2((errout,"new_dispwin: Malloc failed\n")); @@ -4584,31 +4750,13 @@ int ddebug /* >0 to print debug statements to stderr */ } p->ddid = disp->ddid; /* Display we're working on */ - /* Hmm. Could we use CGDisplayGammaTableCapacity() instead ? */ #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 { CGDisplayModeRef dispmode; CFStringRef pixenc; - int cap = CGDisplayGammaTableCapacity(p->ddid); int fbdepth = 0; - debugr2((errout,"new_dispwin: CGDisplayGammaTableCapacity = %d\n",cap)); - - /* Compute GammaTable depth */ - { - for (p->pdepth = 1; p->pdepth < 17; p->pdepth++) { - if ((1 << p->pdepth) == cap) - break; - } - if (p->pdepth >= 17) { - debugr2((errout,"new_dispwin: failed to extract depth from GammaTableCapacity %d\n",cap)); - dispwin_del(p); - return NULL; - } - debugr2((errout,"new_dispwin: found pixel depth %d bits\n",p->pdepth)); - } - /* Get frame buffer depth for sanity check, but don't actually make used of it */ - + /* Get frame buffer depth */ dispmode = CGDisplayCopyDisplayMode(p->ddid); pixenc = CGDisplayModeCopyPixelEncoding(dispmode); @@ -4625,6 +4773,9 @@ int ddebug /* >0 to print debug statements to stderr */ else if (CFStringCompare(pixenc, CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) fbdepth = 5; + else + fbdepth = 8; /* Assume */ + #ifndef DEBUG if (p->ddebug) #endif @@ -4637,26 +4788,56 @@ int ddebug /* >0 to print debug statements to stderr */ CFRelease(pixenc); CGDisplayModeRelease(dispmode); - if (p->pdepth != fbdepth) { - static int warned = 0; - if (!warned) { - warning("new_dispwin: frame buffer depth %d != GammaTable depth %d\n",fbdepth, p->pdepth); - warned = 1; + p->fdepth = fbdepth; + p->rdepth = p->fdepth; /* We don't know of any HW between frame buffer and VideoLUT */ + + /* Get CGDisplayGammaTable size */ + p->nent = CGDisplayGammaTableCapacity(p->ddid); + + /* Compute GammaTable/VideoLUT/RAMDAC depth */ + { + for (p->ndepth = 1; p->ndepth < 17; p->ndepth++) { + if ((1 << p->ndepth) >= p->nent) + break; + } + if (p->ndepth >= 17) { + debugr2((errout,"new_dispwin: failed to extract depth from GammaTableCapacity %d\n",p->nent)); + dispwin_del(p); + return NULL; + } + debugr2((errout,"new_dispwin: found actual VideoLUT depth %d bits\n",p->ndepth)); + } + + if (p->rdepth > p->ndepth) { + debugr2((errout,"new_dispwin: Frame buffer depth %d > VideoLUT depth %d\n",p->rdepth, p->ndepth)); + dispwin_del(p); + return NULL; + } + + if (p->rdepth != p->ndepth) { + if (!p->warned) { + warning("new_dispwin: Frame buffer depth %d doesn't matcv VideoLUT %d",p->rdepth, p->ndepth); + p->warned = 1; } } } #else - p->pdepth = CGDisplayBitsPerSample(p->ddid); + /* Life is simple */ + p->fdepth = CGDisplayBitsPerSample(p->ddid); + p->rdepth = p->fdepth; + p->ndepth = p->rdepth; + p->nent = (1 << p->ndepth); #endif p->edepth = 16; /* By experiment it seems to be 16 bits too */ + debugr2((errout,"new_dispwin: fdepth %d, rdepth %d, ndepth %d, edepth %d\n", p->fdepth,p->rdepth,p->ndepth,p->edepth)); + if (nowin == 0) { /* Create a window */ osx_cntx_t *cx; CGSize sz; /* Display size in mm */ int wi, he; /* Width and height in pixels */ int xo, yo; /* Window location */ - NSRect wrect; debugr2((errout, "new_dispwin: About to open display '%s'\n",disp->name)); @@ -4716,22 +4897,33 @@ int ddebug /* >0 to print debug statements to stderr */ p->ww = wi; p->wh = he; - wrect.origin.x = xo; - wrect.origin.y = yo; - wrect.size.width = wi; - wrect.size.height = he; + cx->rect.origin.x = xo; + cx->rect.origin.y = yo; + cx->rect.size.width = wi; + cx->rect.size.height = he; + + debugr2((errout,"new_dispwin about to create window\n")); + + /* Prepare to wait for events */ + ui_aboutToWait(); - create_my_win(wrect, cx); + /* Run the window creation in the main thread and wait for it */ + ui_runInMainThreadAndWait((void *)cx, create_my_win); + + /* Wait for events generated by window creation to complete */ + ui_waitForEvents(); if (tpool != nil) [tpool release]; p->winclose = 0; + + debugr2((errout,"new_dispwin window created\n")); } /* Install the signal handler to ensure cleanup */ dispwin_install_signal_handlers(p); -#endif /* __APPLE__ */ +#endif /* UNIX_APPLE */ /* -------------------------------------------------- */ /* -------------------------------------------------- */ @@ -4755,6 +4947,8 @@ int ddebug /* >0 to print debug statements to stderr */ Window rootwindow; char *appname = "TestWin"; Visual *myvisual; + XVisualInfo template, *vinfo; + int nitems = 0; XSetWindowAttributes myattr; XEvent myevent; XTextProperty myappname; @@ -4817,15 +5011,184 @@ int ddebug /* >0 to print debug statements to stderr */ memmove(p->edid, disp->edid, p->edid_len); } - //p->pdepth = DefaultDepth(p->mydisplay, p->myscreen)/3; +#ifdef NEVER +#pragma message("######### dispwin.c DirectColor test is defined! ########") + + /* To test DirectColor Visual when it's not the default:*/ + debugr2((errout,"new_dispwin: Testing DirectColor Visual\n")); + + // test DirectColor visual + template.class = DirectColor; + if ((vinfo = XGetVisualInfo(p->mydisplay, VisualClassMask, &template, &nitems)) == NULL) { + debugr2((errout,"new_dispwin: Unable to find a DirectColor Visual\n")); + dispwin_del(p); + return NULL; + } + myvisual = vinfo->visual; - // Hmm. Should we explicitly get the root window visual, - // since our test window inherits it from root ? +#else myvisual = DefaultVisual(p->mydisplay, p->myscreen); - p->pdepth = myvisual->bits_per_rgb; - p->edepth = 16; +#endif + + /* Expect TrueColor (fixed/no map) or DirectColor (read/write map) Visual - */ + /* anything else is not suitable for high quality color. */ + + /* Get the VisualInfo */ + template.visualid = myvisual->visualid; + vinfo = XGetVisualInfo(p->mydisplay, VisualIDMask, &template, &nitems); + + if (nitems < 1) { + debugr2((errout,"new_dispwin: Failed to get XGetVisualInfo of defalt Visual\n")); + dispwin_del(p); + return NULL; + } + + if (vinfo->class != TrueColor && vinfo->class != DirectColor) { + debugr2((errout,"new_dispwin: Default Visual is not TrueColor or DirectColor\n")); + XFree(vinfo); + dispwin_del(p); + return NULL; + } + + /* Compute per component frame buffer depth */ + { + for (p->fdepth = 1; p->fdepth < 17; p->fdepth++) { + if ((1 << p->fdepth) >= myvisual->map_entries) + break; + } + if (p->fdepth >= 17) { + debugr2((errout,"new_dispwin: failed to extract depth from Visual bits_per_rgb %d\n",myvisual->map_entries)); + XFree(vinfo); + dispwin_del(p); + return NULL; + } + } + p->rdepth = myvisual->bits_per_rgb; /* X11 colormap entry size */ + p->edepth = 16; /* Assumed */ + + /* Check that vinfo->red_mask, green_mask & blue_mask all have */ + /* myvisual->map_entries number of bits set, and determine the shift. */ + { + unsigned long bit; + int depth; + + if (vinfo->red_mask == 0 || vinfo->green_mask == 0 || vinfo->blue_mask == 0) { + debugr2((errout,"new_dispwin: one of default Visual r/g/b masks is 0\n")); + XFree(vinfo); + dispwin_del(p); + return NULL; + } + + for (p->shift[0] = 0, bit = 1; (bit & vinfo->red_mask) == 0; p->shift[0]++, bit <<= 1) + ; + + for (depth = 0; (bit & vinfo->red_mask) != 0; depth++, bit <<= 1) + ; + + if (depth != p->fdepth) { + debugr2((errout,"new_dispwin: Default Visual red mask 0x%x is not %d bits\n",vinfo->red_mask,p->fdepth)); + XFree(vinfo); + dispwin_del(p); + return NULL; + } + + for (p->shift[1] = 0, bit = 1; (bit & vinfo->green_mask) == 0; p->shift[1]++, bit <<= 1) + ; + + for (depth = 0; (bit & vinfo->green_mask) != 0; depth++, bit <<= 1) + ; + + if (depth != p->fdepth) { + debugr2((errout,"new_dispwin: Default Visual green mask 0x%x is not %d bits\n",vinfo->red_mask,p->fdepth)); + XFree(vinfo); + dispwin_del(p); + return NULL; + } + + for (p->shift[2] = 0, bit = 1; (bit & vinfo->blue_mask) == 0; p->shift[2]++, bit <<= 1) + ; + + for (depth = 0; (bit & vinfo->blue_mask) != 0; depth++, bit <<= 1) + ; + + if (depth != p->fdepth) { + debugr2((errout,"new_dispwin: Default Visual blue mask 0x%x is not %d bits\n",vinfo->red_mask,p->fdepth)); + XFree(vinfo); + dispwin_del(p); + return NULL; + } + } + + /* Check the VideoLUT depth */ +#if RANDR_MAJOR == 1 && RANDR_MINOR >= 2 && !defined(DISABLE_RANDR) + if (p->crtc != 0) { /* Using Xrandr 1.2 */ + + if ((p->nent = XRRGetCrtcGammaSize(p->mydisplay, p->crtc)) <= 0) { + p->nent = 0; + } + } else +#endif /* randr >= V 1.2 */ + { + p->nent = 0; + + if (XF86VidModeQueryExtension(p->mydisplay, &evb, &erb) != 0) { + int nent = -1; + + /* Some propietary multi-screen drivers (ie. TwinView & MergedFB) */ + /* don't implement the XVidMode extenstion properly. */ + if (XSetErrorHandler(null_error_handler) == 0) { + debugr("new_dispwin failed on XSetErrorHandler\n"); + XSetErrorHandler(NULL); /* Restore handler */ + XFree(vinfo); + dispwin_del(p); + return NULL; + } + if (XF86VidModeGetGammaRampSize(p->mydisplay, p->myrscreen, &nent) != 0 + && nent != -1) { + p->nent = nent; + } + XSetErrorHandler(NULL); /* Restore handler */ + } + } + + if (p->nent == 0) { + p->ndepth = 0; + + if (!p->warned) { + warning("new_dispwin: VideoLUT is not accessible"); + p->warned = 1; + } + + } else { + if (p->nent > 16384) { + debugr("VideoLUT has more entries than we can handle\n"); + XFree(vinfo); + dispwin_del(p); + return NULL; + } + + /* Compute actual ramdac depth */ + for (p->ndepth = 1; p->ndepth < 17; p->ndepth++) { + if ((1 << p->ndepth) >= p->nent) + break; + } + + if (p->nent != (1 << p->rdepth)) { + if (!p->warned) { + warning("new_dispwin: Expected VideoLUT depth %d doesn't match actual %d",p->rdepth, p->ndepth); + p->warned = 1; + } + } + } + + 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])); if (nowin == 0) { /* Create a window */ + unsigned long attrmask = 0; + XWindowAttributes mywa; + Colormap mycmap = None; + int ncolors, i; + rootwindow = RootWindow(p->mydisplay, p->myscreen); myforeground = BlackPixel(p->mydisplay, p->myscreen); @@ -4887,6 +5250,53 @@ int ddebug /* >0 to print debug statements to stderr */ else myattr.override_redirect = False; + attrmask |= CWBackPixel | CWBitGravity /* Attributes Valumask */ + | CWWinGravity | CWBackingStore | CWOverrideRedirect; + + /* For a DirectColor Visual, set the X11 color map */ + if (vinfo->class == DirectColor) { + Colormap mycmap = None; + XColor *colors; + int ncolors = (1 << p->fdepth), i; + + debugr2((errout,"new_dispwin: setting DirectColor colormap\n")); + + if ((mycmap = XCreateColormap(p->mydisplay, rootwindow, myvisual, AllocAll)) == None) { + debugr2((errout,"new_dispwin: XCreateColormap failed\n")); + XFree(vinfo); + dispwin_del(p); + return NULL; + } + + if ((colors = malloc(sizeof(XColor) * ncolors)) == NULL) { + debugr2((errout,"new_dispwin: Malloc failed for XColors\n")); + XFree(vinfo); + dispwin_del(p); + return NULL; + } + + /* Set a linear mapping */ + for (i = 0; i < ncolors; i++) { + colors[i].pixel = i << p->shift[0] | i << p->shift[1] | i << p->shift[2]; + colors[i].red = + colors[i].green = + colors[i].blue = (unsigned short) (65535.0 * i/(ncolors-1.0) + 0.5); + colors[i].flags = DoRed | DoGreen | DoBlue; + } + + if (!XStoreColors(p->mydisplay, mycmap, colors, ncolors)) { + debugr2((errout,"new_dispwin: DirectColor XStoreColors failed\n")); + free(colors); + XFree(vinfo); + dispwin_del(p); + return NULL; + } + free(colors); + + myattr.colormap = mycmap; + attrmask |= CWColormap; + } + debugr("Opening window\n"); p->mywindow = XCreateWindow( p->mydisplay, rootwindow, @@ -4894,9 +5304,9 @@ int ddebug /* >0 to print debug statements to stderr */ 0, /* Border width */ CopyFromParent, /* Depth */ InputOutput, /* Class */ - CopyFromParent, /* Visual */ - CWBackPixel | CWBitGravity /* Attributes Valumask */ - | CWWinGravity | CWBackingStore | CWOverrideRedirect, +// CopyFromParent, /* Visual */ + myvisual, /* Visual */ + attrmask, /* Attributes Valumask */ &myattr /* Attribute details */ ); @@ -4908,10 +5318,12 @@ int ddebug /* >0 to print debug statements to stderr */ p->mydisplay, p->mywindow, &mywattributes) == 0) { debugr("new_dispwin: XGetWindowAttributes failed\n"); + XFree(vinfo); dispwin_del(p); return NULL; } - p->pdepth = mywattributes.depth/3; + p->fdepth = mywattributes.depth/3; + p->rdepth = p->fdepth; #endif /* Setup TextProperty */ @@ -4926,6 +5338,9 @@ int ddebug /* >0 to print debug statements to stderr */ &mywmhints, NULL); /* No class hints */ + // ~1 should free myappname, but there doesn't seem to be + // a XFreeXTextProperty(&myappname); ??? + /* Set aditional properties */ { Atom optat; @@ -4975,8 +5390,8 @@ int ddebug /* >0 to print debug statements to stderr */ XSelectInput(p->mydisplay,p->mywindow, ExposureMask); + debugr2((errout,"new_dispwin about to raise window\n")); XMapRaised(p->mydisplay,p->mywindow); - debug("Raised window\n"); /* ------------------------------------------------------- */ /* Suspend any screensavers if we can */ @@ -5065,7 +5480,7 @@ int ddebug /* >0 to print debug statements to stderr */ } /* Deal with any pending events */ - debug("About to enter main loop\n"); + debugr("About to enter main loop\n"); while(XPending(p->mydisplay) > 0) { XNextEvent(p->mydisplay, &myevent); switch(myevent.type) { @@ -5079,10 +5494,94 @@ int ddebug /* >0 to print debug statements to stderr */ break; } } + + /* Deal with Colormaps */ + debugr2((errout,"new_dispwin: window created - dealling with colormap\n")); + + if (!XGetWindowAttributes(p->mydisplay, p->mywindow, &mywa)) { + debugr2((errout,"new_dispwin: XGetWindowAttributes failed\n")); + XFree(vinfo); + dispwin_del(p); + return NULL; + } + + mycmap = mywa.colormap; + ncolors = (1 << p->fdepth); + + for (i = 0; i < 3; i++) { + if ((p->rmap[i] = malloc(sizeof(int) * ncolors)) == NULL) { + debugr2((errout,"new_dispwin: Malloc failed for rmap[%d]\n",i)); + XFree(vinfo); + dispwin_del(p); + return NULL; + } + } + + /* Get the X11 colormaps, so that we know how to translate */ + /* between the frame buffer pixel value and the ramdac */ + /* index number. */ + if (mycmap != None) { + XColor *colors; + + debugr2((errout,"new_dispwin: getting colormap\n")); + + if ((colors = malloc(sizeof(XColor) * ncolors)) == NULL) { + debugr2((errout,"new_dispwin: Malloc failed for XColors\n")); + XFree(vinfo); + dispwin_del(p); + return NULL; + } + + for (i = 0; i < ncolors; i++) { + colors[i].pixel = i << p->shift[0] | i << p->shift[1] | i << p->shift[2]; + colors[i].flags = DoRed | DoGreen | DoBlue; + } + + if (!XQueryColors(p->mydisplay, mycmap, colors, ncolors)) { + debugr2((errout,"new_dispwin: DirectColor XQueryColors failed\n")); + free(colors); + XFree(vinfo); + dispwin_del(p); + return NULL; + } + + /* Map from frame buffer value to ramdac index */ + for (i = 0; i < ncolors; i++) { + p->rmap[0][i] = (int)(colors[i].red/65535.0 * ((1 << p->rdepth)-1.0) + 0.5); + p->rmap[1][i] = (int)(colors[i].green/65535.0 * ((1 << p->rdepth)-1.0) + 0.5); + p->rmap[2][i] = (int)(colors[i].blue/65535.0 * ((1 << p->rdepth)-1.0) + 0.5); + +//printf("%d: %d %d %d\n",i,p->rmap[0][i],p->rmap[1][i],p->rmap[2][i]); + } + + free(colors); + + /* Assume a default linear mapping */ + } else { + debugr2((errout,"new_dispwin: assuming a linear colormap\n")); + for (i = 0; i < ncolors; i++) { + p->rmap[0][i] = (int)(i/((1 << p->fdepth)-1.0) * ((1 << p->rdepth)-1.0) + 0.5); + p->rmap[1][i] = (int)(i/((1 << p->fdepth)-1.0) * ((1 << p->rdepth)-1.0) + 0.5); + p->rmap[2][i] = (int)(i/((1 << p->fdepth)-1.0) * ((1 << p->rdepth)-1.0) + 0.5); + } + + if (p->fdepth != p->rdepth) { + static int warned = 0; + if (!warned) { + warning("new_dispwin: frame buffer depth %d != VideoLUT depth %d",p->fdepth, p->rdepth); + warned = 1; + } + } + } + + debugr2((errout,"new_dispwin: dealt with colormap\n")); + } else { /* Install the signal handler to ensure cleanup */ dispwin_install_signal_handlers(p); } + + XFree(vinfo); vinfo = NULL; } #endif /* UNIX X11 */ /* -------------------------------------------------- */ @@ -5750,7 +6249,7 @@ main(int argc, char *argv[]) { if (fa < argc) { strncpy(calname,argv[fa++],MAXNAMEL); calname[MAXNAMEL] = '\000'; if (installprofile == 0 && loadprofile == 0 && verify == 0) - loadfile = 1; /* Load the given profile into the videoLUT */ + loadfile = 1; /* Load the given profile into the VideoLUT */ } #if defined(UNIX_X11) @@ -5949,7 +6448,7 @@ main(int argc, char *argv[]) { /* Should we load calfile instead of installed profile if it's present ??? */ if (loadprofile) { if (calname[0] != '\000') - warning("Profile '%s' provided as argument is being ignored!\n",calname); + warning("Profile '%s' provided as argument is being ignored!",calname); /* Get the current displays profile */ debug2((errout,"Loading calibration from display profile '%s'\n",dw->name)); @@ -5974,7 +6473,7 @@ main(int argc, char *argv[]) { is_ok_icc = 1; /* The profile is OK */ if ((wo = (icmVideoCardGamma *)icco->read_tag(icco, icSigVideoCardGammaTag)) == NULL) { - warning("No vcgt tag found in profile - assuming linear\n"); + warning("No vcgt tag found in profile - assuming linear"); for (i = 0; i < dw->r->nent; i++) { iv = i/(dw->r->nent-1.0); dw->r->v[0][i] = iv; @@ -6008,7 +6507,7 @@ main(int argc, char *argv[]) { } else { /* See if it's a .cal file */ int ncal; int ii, fi, ri, gi, bi; - double cal[3][256]; + double cal[3][MAX_CAL_ENT]; int out_tvenc = 0; /* nz to use (16-235)/255 video encoding */ icco->del(icco); /* Don't need these now */ @@ -6032,8 +6531,8 @@ main(int argc, char *argv[]) { if ((ncal = ccg->t[0].nsets) <= 0) error("No data in set of file '%s'",calname); - if (ncal != 256) - error("Expect 256 data sets in file '%s'",calname); + if (ncal < 2 || ncal > MAX_CAL_ENT) + error("Data set size %d is out of range for '%s'",ncal,calname); if ((fi = ccg->find_kword(ccg, 0, "DEVICE_CLASS")) < 0) error("Calibration file '%s' doesn't contain keyword COLOR_REP",calname); |