449 lines
16 KiB
C
449 lines
16 KiB
C
|
|
#ifndef DISPWIN_H
|
|
|
|
/*
|
|
* Argyll Color Management System
|
|
* Display target patch window
|
|
*
|
|
* Author: Graeme W. Gill
|
|
* Date: 4/10/96
|
|
*
|
|
* Copyright 1998 - 2013 Graeme W. Gill
|
|
* All rights reserved.
|
|
*
|
|
* This material is licenced under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 :-
|
|
* see the License.txt file for licencing details.
|
|
*/
|
|
|
|
/*
|
|
* Hmm. Should make display settling time a user overridable parameter,
|
|
* to allow for very fast response displays such as oled ?
|
|
*/
|
|
|
|
#define PATCH_UPDATE_DELAY 200 /* default & minimum patch update delay allowance */
|
|
#define INSTRUMENT_REACTIONTIME 0 /* default nominal instrument reaction time */
|
|
|
|
/* Display rise and fall time model. This is CRT like */
|
|
#define DISPLAY_RISE_TIME 0.04 /* Assumed rise time to 90% of target level */
|
|
#define DISPLAY_FALL_TIME 0.25 /* Assumed fall time to 90% of target level */
|
|
#define DISPLAY_SETTLE_AIM 0.1 /* Aim for 0.2 Delta E */
|
|
|
|
#ifdef NT
|
|
# define OEMRESOURCE
|
|
|
|
/* Set minimum OS target as XP */
|
|
# if !defined(WINVER) || WINVER < 0x0501
|
|
# if defined(WINVER)
|
|
# undef WINVER
|
|
# endif
|
|
# define WINVER 0x0501
|
|
# endif
|
|
# if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0501
|
|
# if defined(_WIN32_WINNT)
|
|
# undef _WIN32_WINNT
|
|
# endif
|
|
# define _WIN32_WINNT 0x0501
|
|
# endif
|
|
|
|
# include <windows.h>
|
|
# include <icm.h>
|
|
|
|
# if(WINVER < 0x0500)
|
|
# error Require WINVER >= 0x500 to compile (multi-monitor API needed)
|
|
# endif
|
|
|
|
# ifndef COLORMGMTCAPS /* In case SDK is out of date */
|
|
|
|
# define COLORMGMTCAPS 121
|
|
|
|
# define CM_NONE 0x00000000
|
|
# define CM_DEVICE_ICM 0x00000001
|
|
# define CM_GAMMA_RAMP 0x00000002
|
|
# define CM_CMYK_COLOR 0x00000004
|
|
|
|
# endif /* !COLORMGMTCAPS */
|
|
|
|
/* Avoid shlwapi.h - there are problems in using it in latter SDKs */
|
|
# ifndef WINSHLWAPI
|
|
# define WINSHLWAPI DECLSPEC_IMPORT
|
|
# endif
|
|
|
|
WINSHLWAPI LPSTR WINAPI PathFindFileNameA(LPCSTR);
|
|
WINSHLWAPI LPWSTR WINAPI PathFindFileNameW(LPCWSTR);
|
|
|
|
# ifdef UNICODE
|
|
# define PathFindFileNameX PathFindFileNameW
|
|
# else
|
|
# define PathFindFileNameX PathFindFileNameA
|
|
# endif
|
|
|
|
#endif /* NT */
|
|
|
|
#ifdef UNIX_APPLE /* Assume OS X Cocoa */
|
|
|
|
#include <Carbon/Carbon.h> /* To declare CGDirectDisplayID */
|
|
|
|
#endif /* UNIX_APPLE */
|
|
|
|
#if defined(UNIX_X11)
|
|
#include <X11/Xlib.h>
|
|
#include <X11/Xutil.h>
|
|
#include <X11/Xatom.h>
|
|
#include <X11/extensions/xf86vmode.h>
|
|
#include <X11/extensions/dpms.h>
|
|
#include <X11/extensions/Xinerama.h>
|
|
#include <X11/extensions/Xrandr.h>
|
|
#include <X11/extensions/scrnsaver.h>
|
|
#include <X11/extensions/dpms.h>
|
|
#endif /* UNIX_X11 */
|
|
|
|
/* - - - - - - - - - - - - - - - - - - - - - - - */
|
|
|
|
/* Profile instalation/association scope */
|
|
typedef enum {
|
|
p_scope_user = 0, /* (user profiles) Linux, OS X & Vista */
|
|
p_scope_local = 1, /* (local system profiles) Linux, OS X & vista */
|
|
p_scope_system = 2, /* (system supplied profiles) OS X. [ Linux, Vista same as local ] */
|
|
p_scope_network = 3 /* (shared network profiles) [ OS X. Linux, Vista same as local ] */
|
|
} p_scope;
|
|
|
|
/* - - - - - - - - - - - - - - - - - - - - - - - */
|
|
/* Enumerate and list all the available displays */
|
|
|
|
/* Structure to store infomation about possible displays */
|
|
typedef struct {
|
|
char *name; /* Display name */
|
|
char *description; /* Description of display or URL */
|
|
int sx,sy; /* Displays offset in pixels */
|
|
int sw,sh; /* Displays width and height in pixels*/
|
|
#ifdef NT
|
|
char monid[128]; /* Monitor ID */
|
|
int prim; /* NZ if primary display monitor */
|
|
#endif /* NT */
|
|
#ifdef UNIX_APPLE
|
|
CGDirectDisplayID ddid;
|
|
#endif /* UNIX_APPLE */
|
|
#if defined(UNIX_X11)
|
|
int screen; /* X11 (possibly virtual) Screen */
|
|
int uscreen; /* Underlying Xinerma/XRandr screen */
|
|
int rscreen; /* Underlying RAMDAC screen (user override) */
|
|
Atom icc_atom; /* ICC profile root/output atom for this display */
|
|
unsigned char *edid; /* 128 or 256 bytes of monitor EDID, NULL if none */
|
|
int edid_len; /* 128 or 256 */
|
|
|
|
#if RANDR_MAJOR == 1 && RANDR_MINOR >= 2
|
|
/* Xrandr stuff - output is connected 1:1 to a display */
|
|
RRCrtc crtc; /* Associated crtc */
|
|
RROutput output; /* Associated output */
|
|
Atom icc_out_atom; /* ICC profile atom for this output */
|
|
#endif /* randr >= V 1.2 */
|
|
#endif /* UNIX_X11 */
|
|
} disppath;
|
|
|
|
/* Return pointer to list of disppath. Last will be NULL. */
|
|
/* Return NULL on failure. */
|
|
/* Call free_disppaths() to free up allocation */
|
|
disppath **get_displays();
|
|
|
|
void free_disppaths(disppath **paths);
|
|
|
|
/* Delete the display at the given index from the paths */
|
|
void del_disppath(disppath **paths, int ix);
|
|
|
|
/* Return the given display given its index 0..n-1 */
|
|
disppath *get_a_display(int ix);
|
|
|
|
void free_a_disppath(disppath *path);
|
|
|
|
extern int callback_ddebug; /* Diagnostic global for get_displays() and get_a_display() */
|
|
|
|
/* - - - - - - - - - - - - - - - - - - - - - - - */
|
|
/* Structure to handle RAMDAC values */
|
|
struct _ramdac {
|
|
|
|
/* Should have separate frame buffer depth + representation to account */
|
|
/* for floating point frame buffers, even though this isn't currently used. */
|
|
|
|
int fdepth; /* Frame buffer depth, typically 8, could be more. */
|
|
int rdepth; /* Expected ramdac index depth. May be different to fdepth */
|
|
/* if there is another level of mapping between the frame buffer */
|
|
/* and ramdac, i.e. X11 DirectorColor Colormap. */
|
|
|
|
int ndepth; /* Actual ramdac depth, typically = rdepth */
|
|
int nent; /* Number of entries, = 2^ndepth, typically = 2^rdepth, */
|
|
/* but may be different for some video cards. */
|
|
/* Will be 0 if ramdac is not accessible */
|
|
|
|
double *v[3]; /* nent entries for RGB, values 0.0 - 1.0 */
|
|
|
|
/* Clone ourselves */
|
|
struct _ramdac *(*clone)(struct _ramdac *p);
|
|
|
|
/* Set the curves to linear */
|
|
void (*setlin)(struct _ramdac *p);
|
|
|
|
/* Check if the lut has sane display values. */
|
|
/* Return 0 if not sane */
|
|
int (*sane)(struct _ramdac *p);
|
|
|
|
/* Destroy ourselves */
|
|
void (*del)(struct _ramdac *p);
|
|
}; typedef struct _ramdac ramdac;
|
|
|
|
|
|
/* - - - - - - - - - - - - - - - - - - - - - - - */
|
|
/* Dispwin object */
|
|
/* This is used by all the different test patch window types, */
|
|
/* dispwin, webwin, madvrwin and ccwin. */
|
|
/* !!!! Make changes in dispwin.c, webwin.c, madvrwin.c & ccwin.c !!!! */
|
|
/* !!!! if this structure gets changed. !!!! */
|
|
|
|
/* Full screen background handling */
|
|
typedef enum {
|
|
dw_bg_black = 0, /* Black background */
|
|
dw_bg_grey = 1, /* Grey background */
|
|
dw_bg_cvideo = 2, /* Constant Average Video background */
|
|
dw_bg_clight = 3 /* Constant Average Light background */
|
|
} dw_bg_type;
|
|
|
|
struct _dispwin {
|
|
|
|
/* private: */
|
|
char *name; /* Display path (ie. '\\.\DISPLAY1') */
|
|
/* or "10.0.0.1:0.0" */
|
|
char *description; /* Description of display */
|
|
|
|
/* Plot instance information */
|
|
int sx,sy; /* Screen offset in pixels */
|
|
int sw,sh; /* Screen width and height in pixels*/
|
|
int ww,wh; /* Window width and height */
|
|
int tx,ty; /* Test area within window offset in pixels */
|
|
int tw,th; /* Test area width and height in pixels */
|
|
|
|
double rgb[3]; /* Current color (full resolution, full range) */
|
|
double s_rgb[3]; /* Current color (possibly scaled range) */
|
|
double r_rgb[3]; /* Current color (raster value) */
|
|
double icalmax; /* Scale inst. cal. test values by this (0.0 .. 1.0) */
|
|
int out_tvenc; /* 1 to use RGB Video Level encoding */
|
|
int patch_delay; /* Measured patch update latency delay in msec, default 200 */
|
|
int inst_reaction; /* Measured instrument reaction time delay in msec, default 0 */
|
|
double rise_time; /* Display settling rise time */
|
|
double fall_time; /* Display settling fall time */
|
|
double de_aim; /* Display settling deltaE aim */
|
|
int min_update_delay; /* Minimum overall update latency delay, default 20, */
|
|
/* overriden by EnvVar */
|
|
double settle_mult; /* Settling time multiplier */
|
|
int do_resp_time_del; /* NZ to compute and use expected display response time */
|
|
int do_update_del; /* NZ to do update delay */
|
|
double extra_update_delay; /* Test window internal extra delay (used in delay cal.) */
|
|
int nowin; /* Don't create a test window */
|
|
int native; /* X0 = use current per channel calibration curve */
|
|
/* X1 = set native linear output and use ramdac high precision */
|
|
/* 0X = use current color management cLut (MadVR) */
|
|
/* 1X = disable color management cLUT (MadVR) */
|
|
ramdac *oor; /* Original orgininal ramdac contents, NULL if not accessible */
|
|
ramdac *or; /* Original ramdac contents, NULL if not accessible, restored on exit */
|
|
ramdac *r; /* Ramdac in use for native mode or general use */
|
|
double width, height; /* Orginial size in mm or % */
|
|
int fullscreen; /* NZ if full screen background (default black) */
|
|
dw_bg_type bge; /* Full screen background color (ccwin only) */
|
|
double area; /* Patch area for bge calc 0..1 */
|
|
|
|
char *callout; /* if not NULL - set color Shell callout routine */
|
|
|
|
/* Linked list to automate SIGKILL cleanup */
|
|
struct _dispwin *next;
|
|
|
|
#ifdef NT
|
|
char monid[128]; /* Monitor ID (ie. 'Monitor\MEA1773\{4D36E96E-E325-11CE-BFC1-08002BE10318}\0015'*/
|
|
HDC hdc; /* Handle to display */
|
|
char *AppName;
|
|
HWND hwnd; /* Window handle */
|
|
HCURSOR curs; /* Invisible cursor */
|
|
|
|
MSG msg;
|
|
ATOM arv;
|
|
|
|
int xo, yo, wi, he; /* Window location & size */
|
|
athread *mth; /* Window message thread */
|
|
int inited;
|
|
int quit; /* Request to quit */
|
|
|
|
volatile int colupd; /* Color update count */
|
|
volatile int colupde; /* Color update count echo */
|
|
|
|
#endif /* NT */
|
|
|
|
#ifdef UNIX_APPLE
|
|
CGDirectDisplayID ddid;
|
|
void *osx_cntx; /* OSX specific info */
|
|
int btf; /* Flag, nz if window has been brought to the front once */
|
|
int winclose; /* Flag, set to nz if window was closed */
|
|
#endif /* UNIX_APPLE */
|
|
|
|
#if defined(UNIX_X11)
|
|
Display *mydisplay;
|
|
int myscreen; /* Overall X11 (possibly virtual) Screen */
|
|
int myuscreen; /* Underlying Xinerma/Xrandr screen */
|
|
int myrscreen; /* Underlying RAMDAC screen (user override) */
|
|
Atom icc_atom; /* ICC profile root atom for this display */
|
|
unsigned char *edid; /* 128 or 256 bytes of monitor EDID, NULL if none */
|
|
int edid_len; /* 128 or 256 */
|
|
|
|
int shift[3]; /* Bit shift to create RGB value from components */
|
|
int *rmap[3]; /* Map of fdepth to rdepth values */
|
|
|
|
#if RANDR_MAJOR == 1 && RANDR_MINOR >= 2
|
|
/* Xrandr stuff - output is connected 1:1 to a display */
|
|
RRCrtc crtc; /* Associated crtc */
|
|
RROutput output; /* Associated output */
|
|
Atom icc_out_atom; /* ICC profile atom for this output */
|
|
#endif /* randr >= V 1.2 */
|
|
|
|
/* Test window access */
|
|
Window mywindow;
|
|
GC mygc;
|
|
|
|
/* Screensaver state */
|
|
int xsssuspend; /* Was able to suspend the screensaver using XScreenSaverSuspend */
|
|
|
|
int xssvalid; /* Was able to save & disable X screensaver using XSetScreenSaver */
|
|
int timeout, interval;
|
|
int prefer_blanking;
|
|
int allow_exposures;
|
|
|
|
int xssrunning; /* Disabled xscreensaver */
|
|
|
|
int gnomessrunning; /* Disabled gnome screensaver and is was enabled */
|
|
pid_t gnomepid; /* gnome-screensaver-command -i pid */
|
|
|
|
int kdessrunning; /* Disabled kde screensaver and is was enabled */
|
|
|
|
int dpmsenabled; /* DPMS is enabled */
|
|
|
|
#endif /* UNIX_X11 */
|
|
|
|
void *pcntx; /* Private context (ie., webwin, ccwin) */
|
|
volatile unsigned int ncix, ccix; /* Counters to trigger webwin colorchange */
|
|
volatile int mg_stop; /* Stop flag */
|
|
|
|
volatile int cberror; /* NZ if error detected in a callback routine */
|
|
int ddebug; /* >0 to print debug to stderr */
|
|
|
|
int warned; /* Warning message has been issued */
|
|
|
|
/* public: */
|
|
int fdepth; /* Frame buffer depth, typically 8, could be more */
|
|
int rdepth; /* Expected ramdac index depth. May be different to fdepth */
|
|
/* if there is another level of mapping between the frame buffer */
|
|
/* and ramdac, i.e. X11 DirectorColor Colormap. */
|
|
|
|
int ndepth; /* Actual ramdac depth, typically = rdepth */
|
|
int nent; /* Number of entries, = s^ndepth, typically = 2^rdepth, */
|
|
/* but may be different for some video cards. */
|
|
/* Will be 0 if ramdac is not accessible */
|
|
|
|
int edepth; /* Notional frame buffer/ramdac entry size in bits. (Bits actually used */
|
|
/* may be less). This is just used to scale out_tvenc appropriately. */
|
|
|
|
/* Get RAMDAC values. ->del() when finished. */
|
|
/* Return NULL if not possible */
|
|
ramdac *(*get_ramdac)(struct _dispwin *p);
|
|
|
|
/* Set the RAMDAC values. */
|
|
/* Return nz if not possible */
|
|
int (*set_ramdac)(struct _dispwin *p, ramdac *r, int persist);
|
|
|
|
/* Install a display profile and make */
|
|
/* it the defult for this display. */
|
|
/* Return nz if failed */
|
|
int (*install_profile)(struct _dispwin *p, char *fname, ramdac *r, p_scope scope);
|
|
|
|
/* Un-install a display profile. */
|
|
/* Return nz if failed */
|
|
int (*uninstall_profile)(struct _dispwin *p, char *fname, p_scope scope);
|
|
|
|
/* Get the currently installed display profile and return it as an icmFile. */
|
|
/* Return the name as well, up to mxlen chars, excluding nul. */
|
|
/* Return NULL if failed */
|
|
icmFile *(*get_profile)(struct _dispwin *p, char *name, int mxlen);
|
|
|
|
/* Set a color (values 0.0 - 1.0) */
|
|
/* Return nz on error */
|
|
int (*set_color)(struct _dispwin *p, double r, double g, double b);
|
|
|
|
/* Set/unset the fullscreen black flag. */
|
|
/* Will only change on next set_col() */
|
|
/* Return nz on error */
|
|
int (*set_fc)(struct _dispwin *p, int fullscreen);
|
|
|
|
/* Change the patch display parameters. */
|
|
/* Optional - may be NULL */
|
|
int (*set_patch_win)(struct _dispwin *p,
|
|
double hoff, double voff, /* Offset from c. in fraction of screen, -1.0 .. 1.0 */
|
|
double area, /* Patch area 0..1 */
|
|
dw_bg_type bge /* Background */
|
|
);
|
|
|
|
/* set patch user info */
|
|
/* Return nz on error */
|
|
int (*set_pinfo)(struct _dispwin *p, int pno, int tno);
|
|
|
|
/* Set a patch delay and instrument reaction time values. */
|
|
/* The overall delay between patch change and triggering */
|
|
/* the instrument is (patch_delay + display_settle - inst_reaction) */
|
|
/* and will never be less than the min_update_delay value. */
|
|
void (*set_update_delay)(struct _dispwin *p, int patch_delay, int inst_reaction);
|
|
|
|
/* Set the display settling time constants. Use -ve value to leave current value */
|
|
/* unchanged. (These values are used as part of the update delay calculations - see above). */
|
|
void (*set_settling_delay)(struct _dispwin *p, double rise_time, double fall_time, double de_aim);
|
|
|
|
/* Enable or disable the update delay. This is used to disable the update delay */
|
|
/* when measuring the patch_delay and inst_reaction */
|
|
void (*enable_update_delay)(struct _dispwin *p, int enable);
|
|
|
|
/* Set a shell set color callout command line */
|
|
void (*set_callout)(struct _dispwin *p, char *callout);
|
|
|
|
|
|
/* Destroy ourselves */
|
|
void (*del)(struct _dispwin *p);
|
|
|
|
}; typedef struct _dispwin dispwin;
|
|
|
|
/* Create a RAMDAC access and display test window, default white */
|
|
dispwin *new_dispwin(
|
|
disppath *screen, /* Screen to calibrate. */
|
|
double width, double height, /* Width and height in mm */
|
|
double hoff, double voff, /* Offset from c. in fraction of screen, range -1.0 .. 1.0 */
|
|
int nowin, /* NZ if no window should be created - RAMDAC access only */
|
|
int native, /* X0 = use current per channel calibration curve */
|
|
/* X1 = set native linear output and use ramdac high precn. */
|
|
/* 0X = use current color management cLut (MadVR) */
|
|
/* 1X = disable color management cLUT (MadVR) */
|
|
int *noramdac, /* Return nz if no ramdac access. native is set to X0 */
|
|
int *nocm, /* Return nz if no CM cLUT access. native is set to 0X */
|
|
double icalmax, /* Scale inst. cal. test values by this (0.0 .. 1.0) */
|
|
int out_tvenc, /* 1 = use RGB Video Level encoding */
|
|
int fullscreen, /* NZ if whole screen should be filled with black */
|
|
int override, /* NZ if override_redirect is to be used on X11 */
|
|
int ddebug /* >0 to print debug statements to stderr */
|
|
);
|
|
|
|
/* Shared implementation */
|
|
void dispwin_set_default_delays(dispwin *p);
|
|
void dispwin_set_update_delay(dispwin *p, int patch_delay, int inst_reaction);
|
|
void dispwin_set_settling_delay(dispwin *p, double rise_time, double fall_time, double de_aim);
|
|
void dispwin_enable_update_delay(dispwin *p, int enable);
|
|
int dispwin_compute_delay(dispwin *p, double *orgb);
|
|
|
|
ramdac *dispwin_clone_ramdac(ramdac *r);
|
|
void dispwin_setlin_ramdac(ramdac *r);
|
|
int dispwin_sane_ramdac(ramdac *r);
|
|
void dispwin_del_ramdac(ramdac *r);
|
|
|
|
#define DISPWIN_H
|
|
#endif /* DISPWIN_H */
|
|
|