1 
2 #ifndef DISPWIN_H
3 
4 /*
5  * Argyll Color Correction System
6  * Display target patch window
7  *
8  * Author: Graeme W. Gill
9  * Date:   4/10/96
10  *
11  * Copyright 1998 - 2013 Graeme W. Gill
12  * All rights reserved.
13  *
14  * This material is licenced under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 :-
15  * see the License.txt file for licencing details.
16  */
17 
18 /*
19  * Hmm. Should make display settling time a user overridable parameter,
20  * to allow for very fast response displays such as oled ?
21  */
22 
23 #define PATCH_UPDATE_DELAY 200		/* default & minimum patch update delay allowance */
24 #define INSTRUMENT_REACTIONTIME 0	/* default nominal instrument reaction time */
25 
26 /* Display rise and fall time model. This is CRT like */
27 #define DISPLAY_RISE_TIME 0.04		/* Assumed rise time to 90% of target level */
28 #define DISPLAY_FALL_TIME 0.25		/* Assumed fall time to 90% of target level */
29 #define DISPLAY_SETTLE_AIM 0.1		/* Aim for 0.2 Delta E */
30 
31 #ifdef NT
32 #define OEMRESOURCE
33 #if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0501
34 #define _WIN32_WINNT 0x0501
35 #endif
36 #if !defined(WINVER) || WINVER < 0x0501
37 #if defined(WINVER)
38 # undef WINVER
39 #endif
40 #define WINVER 0x0501
41 #endif
42 #include <windows.h>
43 #include <icm.h>
44 
45 #if(WINVER < 0x0500)
46 #error Require WINVER >= 0x500 to compile (multi-monitor API needed)
47 #endif
48 
49 #ifndef COLORMGMTCAPS	/* In case SDK is out of date */
50 
51 #define COLORMGMTCAPS   121
52 
53 #define CM_NONE             0x00000000
54 #define CM_DEVICE_ICM       0x00000001
55 #define CM_GAMMA_RAMP       0x00000002
56 #define CM_CMYK_COLOR       0x00000004
57 
58 #endif	/* !COLORMGMTCAPS */
59 
60 /* Avoid shlwapi.h - there are problems in using it in latter SDKs */
61 #ifndef WINSHLWAPI
62 #define WINSHLWAPI DECLSPEC_IMPORT
63 #endif
64 
65 WINSHLWAPI LPSTR WINAPI PathFindFileNameA(LPCSTR);
66 WINSHLWAPI LPWSTR WINAPI PathFindFileNameW(LPCWSTR);
67 
68 #ifdef UNICODE
69 #define PathFindFileNameX PathFindFileNameW
70 #else
71 #define PathFindFileNameX PathFindFileNameA
72 #endif
73 
74 #endif /* NT */
75 
76 #ifdef UNIX_APPLE	/* Assume OS X Cocoa */
77 
78 #include <Carbon/Carbon.h>		/* To declare CGDirectDisplayID  */
79 
80 #endif /* UNIX_APPLE */
81 
82 #if defined(UNIX_X11)
83 #include <X11/Xlib.h>
84 #include <X11/Xutil.h>
85 #include <X11/Xatom.h>
86 #include <X11/extensions/xf86vmode.h>
87 #include <X11/extensions/dpms.h>
88 #include <X11/extensions/Xinerama.h>
89 #include <X11/extensions/Xrandr.h>
90 #include <X11/extensions/scrnsaver.h>
91 #include <X11/extensions/dpms.h>
92 #endif /* UNIX_X11 */
93 
94 /* - - - - - - - - - - - - - - - - - - - - - - - */
95 
96 /* Profile instalation/association scope */
97 typedef enum {
98 	p_scope_user     = 0,		/* (user profiles) Linux, OS X & Vista */
99 	p_scope_local    = 1,		/* (local system profiles) Linux, OS X & vista */
100 	p_scope_system   = 2,		/* (system supplied profiles) OS X. [ Linux, Vista same as local ] */
101 	p_scope_network  = 3		/* (shared network profiles) [ OS X. Linux, Vista same as local ] */
102 } p_scope;
103 
104 /* - - - - - - - - - - - - - - - - - - - - - - - */
105 /* Enumerate and list all the available displays */
106 
107 /* Structure to store infomation about possible displays */
108 typedef struct {
109 	char *name;			/* Display name */
110 	char *description;	/* Description of display or URL */
111 	int sx,sy;			/* Displays offset in pixels */
112 	int sw,sh;			/* Displays width and height in pixels*/
113 #ifdef NT
114 	char monid[128];	/* Monitor ID */
115 	int prim;			/* NZ if primary display monitor */
116 #endif /* NT */
117 #ifdef UNIX_APPLE
118 	CGDirectDisplayID ddid;
119 #endif /* UNIX_APPLE */
120 #if defined(UNIX_X11)
121 	int screen;				/* Screen to select */
122 	int uscreen;			/* Underlying screen */
123 	int rscreen;			/* Underlying RAMDAC screen */
124 	Atom icc_atom;			/* ICC profile root atom for this display */
125 	unsigned char *edid;	/* 128 or 256 bytes of monitor EDID, NULL if none */
126 	int edid_len;			/* 128 or 256 */
127 
128 #if RANDR_MAJOR == 1 && RANDR_MINOR >= 2
129 	/* Xrandr stuff - output is connected 1:1 to a display */
130 	RRCrtc crtc;				/* Associated crtc */
131 	RROutput output;			/* Associated output */
132 	Atom icc_out_atom;			/* ICC profile atom for this output */
133 #endif /* randr >= V 1.2 */
134 #endif /* UNIX_X11 */
135 } disppath;
136 
137 /* Return pointer to list of disppath. Last will be NULL. */
138 /* Return NULL on failure. */
139 /* Call free_disppaths() to free up allocation */
140 disppath **get_displays();
141 
142 void free_disppaths(disppath **paths);
143 
144 /* Delete the display at the given index from the paths */
145 void del_disppath(disppath **paths, int ix);
146 
147 /* Return the given display given its index 0..n-1 */
148 disppath *get_a_display(int ix);
149 
150 void free_a_disppath(disppath *path);
151 
152 extern int callback_ddebug;		/* Diagnostic global for get_displays() and get_a_display() */
153 
154 /* - - - - - - - - - - - - - - - - - - - - - - - */
155 /* Structure to handle RAMDAC values */
156 struct _ramdac {
157 
158 	/* Should have separate frame buffer depth + representation to account */
159 	/* for floating point frame buffers, even though this isn't currently used. */
160 
161 	int fdepth;		/* Frame buffer depth, typically 8, could be more. */
162 	int rdepth;		/* Expected ramdac index depth. May be different to fdepth */
163 					/* if there is another level of mapping between the frame buffer */
164 					/* and ramdac, i.e. X11 DirectorColor Colormap. */
165 
166 	int ndepth;		/* Actual ramdac depth, typically = rdepth */
167 	int nent;		/* Number of entries, = 2^ndepth, typically = 2^rdepth, */
168 					/* but may be different for some video cards. */
169 					/* Will be 0 if ramdac is not accessible */
170 
171 	double *v[3];	/* nent entries for RGB, values 0.0 - 1.0 */
172 
173 	/* Clone ourselves */
174 	struct _ramdac *(*clone)(struct _ramdac *p);
175 
176 	/* Set the curves to linear */
177 	void (*setlin)(struct _ramdac *p);
178 
179 	/* Destroy ourselves */
180 	void (*del)(struct _ramdac *p);
181 }; typedef struct _ramdac ramdac;
182 
183 
184 /* - - - - - - - - - - - - - - - - - - - - - - - */
185 /* Dispwin object */
186 /* This is used by all the different test patch window types, */
187 /* dispwin, webwin, madvrwin and ccwin. */
188 /* !!!! Make changes in dispwin.c, webwin.c, madvrwin.c & ccwin.c !!!!  */
189 /* !!!! if this structure gets changed. !!!! */
190 
191 /* Full screen background handling */
192 typedef enum {
193 	dw_bg_black   = 0,		/* Black background */
194 	dw_bg_grey    = 1,		/* Grey background */
195 	dw_bg_cvideo  = 2,		/* Constant Average Video background */
196 	dw_bg_clight  = 3		/* Constant Average Light background */
197 } dw_bg_type;
198 
199 struct _dispwin {
200 
201 /* private: */
202 	char *name;			/* Display path (ie. '\\.\DISPLAY1') */
203 						/* or "10.0.0.1:0.0" */
204 	char *description;	/* Description of display */
205 
206 	/* Plot instance information */
207 	int sx,sy;			/* Screen offset in pixels */
208 	int sw,sh;			/* Screen width and height in pixels*/
209 	int ww,wh;			/* Window width and height */
210 	int tx,ty;			/* Test area within window offset in pixels */
211 	int tw,th;			/* Test area width and height in pixels */
212 
213 	double rgb[3];		/* Current color (full resolution, full range) */
214 	double s_rgb[3];	/* Current color (possibly scaled range) */
215 	double r_rgb[3];	/* Current color (raster value) */
216 	int out_tvenc;		/* 1 to use RGB Video Level encoding */
217 	int patch_delay;	/* Measured patch update latency delay in msec, default 200 */
218 	int inst_reaction;	/* Measured instrument reaction time delay in msec, default 0 */
219 	double rise_time;	/* Display settling rise time */
220 	double fall_time;	/* Display settling fall time */
221 	double de_aim;		/* Display settling deltaE aim */
222 	int min_update_delay;	/* Minimum overall update latency delay, default 20, */
223 							/* overriden by EnvVar */
224 	double settle_mult;	/* Settling time multiplier */
225 	int do_resp_time_del;	/* NZ to compute and use expected display response time */
226 	int do_update_del;		/* NZ to do update delay */
227 	double extra_update_delay;	/* Test window internal extra delay (used in delay cal.) */
228 	int nowin;			/* Don't create a test window */
229 	int native;			/*  X0 = use current per channel calibration curve */
230 						/*  X1 = set native linear output and use ramdac high precision */
231 						/*  0X = use current color management cLut (MadVR) */
232 						/*  1X = disable color management cLUT (MadVR) */
233 	ramdac *oor;		/* Original orgininal ramdac contents, NULL if not accessible */
234 	ramdac *or;			/* Original ramdac contents, NULL if not accessible, restored on exit */
235 	ramdac *r;			/* Ramdac in use for native mode or general use */
236 	double width, height;	/* Orginial size in mm or % */
237 	int fullscreen;		/* NZ if full screen background (default black) */
238 	dw_bg_type bge;		/* Full screen background color (ccwin only) */
239 	double area;		/* Patch area for bge calc 0..1 */
240 
241 	char *callout;		/* if not NULL - set color Shell callout routine */
242 
243 	/* Linked list to automate SIGKILL cleanup */
244 	struct _dispwin *next;
245 
246 #ifdef NT
247 	char monid[128];	/* Monitor ID (ie. 'Monitor\MEA1773\{4D36E96E-E325-11CE-BFC1-08002BE10318}\0015'*/
248 	HDC hdc;			/* Handle to display */
249 	char *AppName;
250 	HWND hwnd;			/* Window handle */
251 	HCURSOR curs;		/* Invisible cursor */
252 
253 	MSG msg;
254 	ATOM arv;
255 
256 	int xo, yo, wi, he;	/* Window location & size */
257 	athread *mth;		/* Window message thread */
258 	int inited;
259 	int quit;			/* Request to quit */
260 
261 	volatile int colupd;		/* Color update count */
262 	volatile int colupde;		/* Color update count echo */
263 
264 #endif /* NT */
265 
266 #ifdef UNIX_APPLE
267 	CGDirectDisplayID ddid;
268 	void *osx_cntx;			/* OSX specific info */
269 	int btf;				/* Flag, nz if window has been brought to the front once */
270 	int winclose;			/* Flag, set to nz if window was closed */
271 #endif /* UNIX_APPLE */
272 
273 #if defined(UNIX_X11)
274 	Display *mydisplay;
275 	int myscreen;			/* Usual or virtual screen with Xinerama */
276 	int myuscreen;			/* Underlying screen */
277 	int myrscreen;			/* Underlying RAMDAC screen */
278 	Atom icc_atom;			/* ICC profile root atom for this display */
279 	unsigned char *edid;	/* 128 or 256 bytes of monitor EDID, NULL if none */
280 	int edid_len;			/* 128 or 256 */
281 
282 	int shift[3];			/* Bit shift to create RGB value from components */
283 	int *rmap[3];			/* Map of fdepth to rdepth values */
284 
285 #if RANDR_MAJOR == 1 && RANDR_MINOR >= 2
286 	/* Xrandr stuff - output is connected 1:1 to a display */
287 	RRCrtc crtc;				/* Associated crtc */
288 	RROutput output;			/* Associated output */
289 	Atom icc_out_atom;			/* ICC profile atom for this output */
290 #endif /* randr >= V 1.2 */
291 
292 	/* Test window access */
293 	Window mywindow;
294 	GC mygc;
295 
296     /* Screensaver state */
297 	int xsssuspend;				/* Was able to suspend the screensaver using XScreenSaverSuspend */
298 
299 	int xssvalid;				/* Was able to save & disable X screensaver using XSetScreenSaver */
300 	int timeout, interval;
301 	int prefer_blanking;
302 	int allow_exposures;
303 
304 	int xssrunning;				/* Disabled xscreensaver */
305 
306 	int gnomessrunning;			/* Disabled gnome screensaver and is was enabled */
307 	pid_t gnomepid;				/* gnome-screensaver-command -i pid */
308 
309 	int kdessrunning;			/* Disabled kde screensaver and is was enabled */
310 
311 	int dpmsenabled;			/* DPMS is enabled */
312 
313 #endif /* UNIX_X11 */
314 
315 	void *pcntx;				/* Private context (ie., webwin, ccwin) */
316 	volatile unsigned int ncix, ccix;	/* Counters to trigger webwin colorchange */
317 	volatile int mg_stop;				/* Stop flag */
318 
319 	volatile int cberror;		/* NZ if error detected in a callback routine */
320 	int ddebug;					/* >0 to print debug to stderr */
321 
322 	int warned;		/* Warning message has been issued */
323 
324 /* public: */
325 	int fdepth;		/* Frame buffer depth, typically 8, could be more */
326 	int rdepth;		/* Expected ramdac index depth. May be different to fdepth */
327 					/* if there is another level of mapping between the frame buffer */
328 					/* and ramdac, i.e. X11 DirectorColor Colormap. */
329 
330 	int ndepth;		/* Actual ramdac depth, typically = rdepth */
331 	int nent;		/* Number of entries, = s^ndepth, typically = 2^rdepth, */
332 					/* but may be different for some video cards. */
333 					/* Will be 0 if ramdac is not accessible */
334 
335 	int edepth;		/* Notional frame buffer/ramdac entry size in bits. (Bits actually used  */
336 					/* may be less). This is just used to scale out_tvenc appropriately. */
337 
338 	/* Get RAMDAC values. ->del() when finished. */
339 	/* Return NULL if not possible */
340 	ramdac *(*get_ramdac)(struct _dispwin *p);
341 
342 	/* Set the RAMDAC values. */
343 	/* Return nz if not possible */
344 	int (*set_ramdac)(struct _dispwin *p, ramdac *r, int persist);
345 
346 	/* Install a display profile and make */
347 	/* it the defult for this display. */
348 	/* Return nz if failed */
349 	int (*install_profile)(struct _dispwin *p, char *fname, ramdac *r, p_scope scope);
350 
351 	/* Un-install a display profile. */
352 	/* Return nz if failed */
353 	int (*uninstall_profile)(struct _dispwin *p, char *fname, p_scope scope);
354 
355 	/* Get the currently installed display profile and return it as an icmFile. */
356 	/* Return the name as well, up to mxlen chars, excluding nul. */
357 	/* Return NULL if failed */
358 	icmFile *(*get_profile)(struct _dispwin *p, char *name, int mxlen);
359 
360 	/* Set a color (values 0.0 - 1.0) */
361 	/* Return nz on error */
362 	int (*set_color)(struct _dispwin *p, double r, double g, double b);
363 
364 	/* Set/unset the fullscreen black flag. */
365 	/* Will only change on next set_col() */
366 	/* Return nz on error */
367 	int (*set_fc)(struct _dispwin *p, int fullscreen);
368 
369 	/* Change the patch display parameters. */
370 	/* Optional - may be NULL */
371 	int (*set_patch_win)(struct _dispwin *p,
372 		double hoff, double voff,		/* Offset from c. in fraction of screen, -1.0 .. 1.0 */
373 		double area,					/* Patch area 0..1 */
374 		dw_bg_type bge					/* Background */
375 	);
376 
377 	/* set patch user info */
378 	/* Return nz on error */
379 	int (*set_pinfo)(struct _dispwin *p, int pno, int tno);
380 
381 	/* Set a patch delay and instrument reaction time values. */
382 	/* The overall delay between patch change and triggering */
383 	/* the instrument is (patch_delay + display_settle - inst_reaction) */
384 	/* and will never be less than the min_update_delay value. */
385 	void (*set_update_delay)(struct _dispwin *p, int patch_delay, int inst_reaction);
386 
387 	/* Set the display settling time constants. Use -ve value to leave current value */
388 	/* unchanged. (These values are used as part of the update delay calculations - see above). */
389 	void (*set_settling_delay)(struct _dispwin *p, double rise_time, double fall_time, double de_aim);
390 
391 	/* Enable or disable the update delay. This is used to disable the update delay */
392 	/* when measuring the patch_delay and inst_reaction */
393 	void (*enable_update_delay)(struct _dispwin *p, int enable);
394 
395 	/* Set a shell set color callout command line */
396 	void (*set_callout)(struct _dispwin *p, char *callout);
397 
398 
399 	/* Destroy ourselves */
400 	void (*del)(struct _dispwin *p);
401 
402 }; typedef struct _dispwin dispwin;
403 
404 /* Create a RAMDAC access and display test window, default white */
405 dispwin *new_dispwin(
406 	disppath *screen,				/* Screen to calibrate. */
407 	double width, double height,	/* Width and height in mm */
408 	double hoff, double voff,		/* Offset from c. in fraction of screen, range -1.0 .. 1.0 */
409 	int nowin,						/* NZ if no window should be created - RAMDAC access only */
410 	int native,						/* X0 = use current per channel calibration curve */
411 									/* X1 = set native linear output and use ramdac high precn. */
412 									/* 0X = use current color management cLut (MadVR) */
413 									/* 1X = disable color management cLUT (MadVR) */
414 	int *noramdac,					/* Return nz if no ramdac access. native is set to X0 */
415 	int *nocm,						/* Return nz if no CM cLUT access. native is set to 0X */
416 	int out_tvenc,					/* 1 = use RGB Video Level encoding */
417 	int fullscreen,					/* NZ if whole screen should be filled with black */
418 	int override,					/* NZ if override_redirect is to be used on X11 */
419 	int ddebug						/* >0 to print debug statements to stderr */
420 );
421 
422 /* Shared implementation */
423 void dispwin_set_default_delays(dispwin *p);
424 void dispwin_set_update_delay(dispwin *p, int patch_delay, int inst_reaction);
425 void dispwin_set_settling_delay(dispwin *p, double rise_time, double fall_time, double de_aim);
426 void dispwin_enable_update_delay(dispwin *p, int enable);
427 int dispwin_compute_delay(dispwin *p, double *orgb);
428 
429 ramdac *dispwin_clone_ramdac(ramdac *r);
430 void dispwin_setlin_ramdac(ramdac *r);
431 void dispwin_del_ramdac(ramdac *r);
432 
433 
434 
435 #define DISPWIN_H
436 #endif /* DISPWIN_H */
437 
438