Files
argyllcms/spectro/dispwin.h
T
2026-08-20 20:28:40 +01:00

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 */