1 
2 
3 /*
4  * Argyll Color Correction System
5  * Web Display target patch window
6  *
7  * Author: Graeme W. Gill
8  * Date:   3/4/12
9  *
10  * Copyright 2013 Graeme W. Gill
11  * All rights reserved.
12  *
13  * This material is licenced under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 :-
14  * see the License.txt file for licencing details.
15  */
16 
17 #include <stdio.h>
18 #include <string.h>
19 #ifdef NT
20 # include <winsock2.h>
21 # include <shlwapi.h>
22 #endif
23 #include "copyright.h"
24 #include "aconfig.h"
25 #include "icc.h"
26 #include "numsup.h"
27 #include "cgats.h"
28 #include "conv.h"
29 #include "dispwin.h"
30 #include "madvrwin.h"
31 #include "conv.h"
32 #include "mongoose.h"
33 
34 #define ENABLE_RAMDAC
35 
36 #undef DEBUG
37 //#define STANDALONE_TEST
38 
39 #ifdef DEBUG
40 #define errout stderr
41 # define debug(xx)	fprintf(errout, xx )
42 # define debug2(xx)	fprintf xx
43 # define debugr(xx)	fprintf(errout, xx )
44 # define debugr2(xx)	fprintf xx
45 # define debugrr(xx)	fprintf(errout, xx )
46 # define debugrr2(xx)	fprintf xx
47 # define debugrr2l(lev, xx)	fprintf xx
48 #else
49 #define errout stderr
50 # define debug(xx)
51 # define debug2(xx)
52 # define debugr(xx) if (p->ddebug) fprintf(errout, xx )
53 # define debugr2(xx) if (p->ddebug) fprintf xx
54 # define debugrr(xx) if (callback_ddebug) fprintf(errout, xx )
55 # define debugrr2(xx) if (callback_ddebug) fprintf xx
56 # define debugrr2l(lev, xx) if (callback_ddebug >= lev) fprintf xx
57 #endif
58 
59 /* ----------------------------------------------- */
60 /* MadVR functions */
61 
62 #ifndef KEY_WOW64_32KEY
63 # define KEY_WOW64_32KEY (0x0200)
64 #endif
65 
66 /* Incase shlwapi.h doesn't declare this */
67 #include <pshpack1.h>
68 typedef struct _ADLLVERSIONINFO2
69 {
70     DLLVERSIONINFO info1;
71     DWORD dwFlags;
72     ULONGLONG ullVersion;
73 } ADLLVERSIONINFO2;
74 #include <poppack.h>
75 
76 HMODULE HcNetDll = NULL;
77 BOOL (WINAPI *madVR_BlindConnect)(BOOL searchLan, DWORD timeOut) = NULL;
78 BOOL (WINAPI *madVR_GetVersion)(DWORD *version);
79 BOOL (WINAPI *madVR_SetOsdText)(LPCWSTR text);
80 BOOL (WINAPI *madVR_Disable3dlut)() = NULL;
81 BOOL (WINAPI *madVR_GetDeviceGammaRamp)(LPVOID ramp) = NULL;
82 BOOL (WINAPI *madVR_SetDeviceGammaRamp)(LPVOID ramp) = NULL;
83 BOOL (WINAPI *madVR_GetPatternConfig)(int *patternAreaInPercent, int *backgroundLevelInPercent,
84                                       int *backgroundMode, int *blackBorderWidth) = NULL;
85 BOOL (WINAPI *madVR_SetPatternConfig)(int patternAreaInPercent, int backgroundLevelInPercent,
86                                       int backgroundMode, int blackBorderWidth) = NULL;
87 BOOL (WINAPI *madVR_ShowRGB)(double r, double g, double b) = NULL;
88 BOOL (WINAPI *madVR_SetProgressBarPos)(int currentPos, int maxPos);
89 BOOL (WINAPI *madVR_Disconnect)() = NULL;
90 
91 /* Locate and populate the MadVR functions */
92 /* Return NZ on failure */
initMadVR(dispwin * p)93 static int initMadVR(dispwin *p) {
94 	wchar_t *dllname;
95 	WCHAR modname[MAX_PATH];
96 	DWORD hnd;
97 	DWORD len = 0;
98 	WORD v1 = 0, v2 = 0, v3 = 0, v4 = 0;		/* MadVR version */
99 
100 	if (sizeof(dllname) > 4)		/* Compiled as 64 bit */
101 		dllname = L"madHcNet64.dll";
102 	else
103 		dllname = L"madHcNet32.dll";
104 
105 	if ((HcNetDll = LoadLibraryW(dllname)) == NULL) {
106 		HKEY hk1;
107     	if (RegOpenKeyExW(HKEY_CLASSES_ROOT, L"CLSID\\{E1A8B82A-32CE-4B0D-BE0D-AA68C772E423}\\InprocServer32", 0, KEY_QUERY_VALUE | KEY_WOW64_32KEY, &hk1) == ERROR_SUCCESS) {
108 			DWORD size;
109 			LPWSTR us1;
110 			int i1;
111 			size = MAX_PATH * 2 + 2;
112 		    us1 = (LPWSTR) LocalAlloc(LPTR, size + 20);
113 		    i1 = RegQueryValueExW(hk1, NULL, NULL, NULL, (LPBYTE) us1, &size);
114 			if (i1 == ERROR_MORE_DATA) {
115 				LocalFree(us1);
116 				us1 = (LPWSTR) LocalAlloc(LPTR, size + 20);
117 				i1 = RegQueryValueExW(hk1, NULL, NULL, NULL, (LPBYTE) us1, &size);
118 			}
119 			if (i1 == ERROR_SUCCESS) {
120 				for (i1 = lstrlenW(us1) - 2; i1 > 0; i1--)
121 					if (us1[i1] == L'\\') {
122 						us1[i1 + 1] = 0;
123 						break;
124 					}
125 				wcscat(us1, dllname);
126 				HcNetDll = LoadLibraryW(us1);
127 			}
128 			LocalFree(us1);
129 			RegCloseKey(hk1);
130 		}
131 	}
132 	if (HcNetDll != NULL) {
133 		HRESULT (WINAPI *dllgetver)(ADLLVERSIONINFO2 *) = NULL;
134 
135 		*(FARPROC*)&dllgetver = GetProcAddress(HcNetDll, "DllGetVersion");
136 
137 		if (dllgetver != NULL) {
138 			ADLLVERSIONINFO2 ver;
139 
140 			ver.info1.cbSize = sizeof(ADLLVERSIONINFO2);
141 			dllgetver(&ver);
142 
143 			v1 = 0xffff & (ver.ullVersion >> 48);
144 			v2 = 0xffff & (ver.ullVersion >> 32);
145 			v3 = 0xffff & (ver.ullVersion >> 16);
146 			v4 = 0xffff & ver.ullVersion;
147 
148 		} else  {
149 			debugr2((errout,"MadVR DllGetVersion failed - can't determine DLL version\n"));
150 		}
151 	}
152 
153 	if (HcNetDll != NULL) {
154 		*(FARPROC*)&madVR_BlindConnect       = GetProcAddress(HcNetDll, "madVR_BlindConnect");
155 		*(FARPROC*)&madVR_GetVersion         = GetProcAddress(HcNetDll, "madVR_GetVersion");
156 		*(FARPROC*)&madVR_SetOsdText         = GetProcAddress(HcNetDll, "madVR_SetOsdText");
157 		*(FARPROC*)&madVR_Disable3dlut       = GetProcAddress(HcNetDll, "madVR_Disable3dlut");
158 		*(FARPROC*)&madVR_GetDeviceGammaRamp = GetProcAddress(HcNetDll, "madVR_GetDeviceGammaRamp");
159 		*(FARPROC*)&madVR_SetDeviceGammaRamp = GetProcAddress(HcNetDll, "madVR_SetDeviceGammaRamp");
160 		*(FARPROC*)&madVR_GetPatternConfig   = GetProcAddress(HcNetDll, "madVR_GetPatternConfig");
161 		*(FARPROC*)&madVR_SetPatternConfig   = GetProcAddress(HcNetDll, "madVR_SetPatternConfig");
162 		*(FARPROC*)&madVR_ShowRGB            = GetProcAddress(HcNetDll, "madVR_ShowRGB");
163 		*(FARPROC*)&madVR_SetProgressBarPos  = GetProcAddress(HcNetDll, "madVR_SetProgressBarPos");
164 		*(FARPROC*)&madVR_Disconnect         = GetProcAddress(HcNetDll, "madVR_Disconnect");
165 
166 		if (madVR_BlindConnect
167 		 && madVR_GetVersion
168 		 && madVR_SetOsdText
169 		 && madVR_Disable3dlut
170 		 && madVR_GetDeviceGammaRamp
171 		 && madVR_SetDeviceGammaRamp
172 		 && madVR_GetPatternConfig
173 		 && madVR_SetPatternConfig
174 		 && madVR_ShowRGB
175 		 && madVR_SetProgressBarPos
176 		 && madVR_Disconnect) {
177 			DWORD ver = 0;
178 			/* Return value is unclear */
179 			if (!madVR_GetVersion(&ver))
180 				debugr2((errout,"MadVR_GetVersion failed - can't determine MadVR version\n"));
181 
182 			debugr2((errout,"Found all required functions in %ls V%d.%d.%d.%d MadVR V%x.%x.%x.%x functions\n",dllname,v1,v2,v3,v4, 0xff & (ver >> 24), 0xff & (ver >> 16), 0xff & (ver >> 8), 0xff & ver));
183 			return 0;
184 		}
185 		debugr2((errout,"Failed to locate MadVR function in %ls %d.%d.%d.%d\n",dllname,v1,v2,v3,v4));
186 		FreeLibrary(HcNetDll);
187 	} else {
188 		debugr2((errout,"Failed to load %ls\n",dllname));
189 	}
190 	return 1;
191 }
192 
deinitMadVR(dispwin * p)193 static void deinitMadVR(dispwin *p) {
194 	if (HcNetDll != NULL) {
195 		FreeLibrary(HcNetDll);
196 		HcNetDll = NULL;
197 	}
198 }
199 
200 /* ----------------------------------------------- */
201 
202 /* Get RAMDAC values. ->del() when finished. */
203 /* Return NULL if not possible */
madvrwin_get_ramdac(dispwin * p)204 static ramdac *madvrwin_get_ramdac(dispwin *p) {
205 	ramdac *r = NULL;
206 
207 #ifdef ENABLE_RAMDAC
208 	WORD vals[3][256];		/* 256 x 16 bit elements (Quantize) */
209 	int i, j;
210 
211 	debugr("madvrwin_get_ramdac called\n");
212 
213 	/* Allocate a ramdac */
214 	if ((r = (ramdac *)calloc(sizeof(ramdac), 1)) == NULL) {
215 		debugr("madvrwin_get_ramdac failed on malloc()\n");
216 		return NULL;
217 	}
218 	r->fdepth = p->fdepth;
219 	r->rdepth = p->rdepth;
220 	r->ndepth = p->ndepth;
221 	r->nent   = p->nent;
222 
223 	r->clone =  dispwin_clone_ramdac;
224 	r->setlin = dispwin_setlin_ramdac;
225 	r->del =    dispwin_del_ramdac;
226 
227 	for (j = 0; j < 3; j++) {
228 
229 		if ((r->v[j] = (double *)calloc(sizeof(double), r->nent)) == NULL) {
230 			for (j--; j >= 0; j--)
231 				free(r->v[j]);
232 			free(r);
233 			debugr("madvrwin_get_ramdac failed on malloc()\n");
234 			return NULL;
235 		}
236 	}
237 
238 	/* GetDeviceGammaRamp() is hard coded for 3 x 256 entries (Quantize) */
239 	if (r->nent != 256) {
240 		free(r);
241 		debugr2((errout,"GetDeviceGammaRamp() is hard coded for nent == 256, and we've got nent = %d!\n",r->nent));
242 		return NULL;
243 	}
244 
245 	if (!madVR_GetDeviceGammaRamp(vals)) {
246 		free(r);
247 		debugr2((errout,"madvrwin_get_ramdac failed on madVR_GetDeviceGammaRamp()\n"));
248 		return NULL;
249 	}
250 
251 	for (j = 0; j < 3; j++) {
252 		for (i = 0; i < r->nent; i++) {
253 			r->v[j][i] = vals[j][i]/65535.0;
254 		}
255 	}
256 #endif // ENABLE_RAMDAC
257 	debugr2((errout,"madvrwin_get_ramdac returning 0x%x\n",r));
258 
259 	return r;
260 }
261 
262 /* Set the RAMDAC values. */
263 /* Return nz if not possible */
madvrwin_set_ramdac(dispwin * p,ramdac * r,int persist)264 static int madvrwin_set_ramdac(dispwin *p, ramdac *r, int persist) {
265 	int rv = 1;
266 
267 #ifdef ENABLE_RAMDAC
268 	int i, j;
269 	WORD vals[3][256];		/* 16 bit elements */
270 
271 	debugr("madvrwin_set_ramdac called\n");
272 
273 	for (j = 0; j < 3; j++) {
274 		for (i = 0; i < r->nent; i++) {
275 			double vv = r->v[j][i];
276 			if (vv < 0.0)
277 				vv = 0.0;
278 			else if (vv > 1.0)
279 				vv = 1.0;
280 			vals[j][i] = (int)(65535.0 * vv + 0.5);
281 		}
282 	}
283 
284 	if (!madVR_SetDeviceGammaRamp(vals)) {
285 		debugr2((errout,"madvrwin_set_ramdac failed on madVR_SetDeviceGammaRamp()\n"));
286 		rv = 1;
287 	} else {
288 		debugr("madvrwin_set_ramdac set\n");
289 		rv = 0;
290 	}
291 #endif // ENABLE_RAMDAC
292 	return rv;
293 }
294 
295 /* ----------------------------------------------- */
296 /* Install a display profile and make */
297 /* it the default for this display. */
298 /* Return nz if failed */
madvrwin_install_profile(dispwin * p,char * fname,ramdac * r,p_scope scope)299 int madvrwin_install_profile(dispwin *p, char *fname, ramdac *r, p_scope scope) {
300 	debugr("madVRdisp doesn't support installing profiles\n");
301 	return 1;
302 }
303 
304 /* Un-Install a display profile */
305 /* Return nz if failed, */
madvrwin_uninstall_profile(dispwin * p,char * fname,p_scope scope)306 int madvrwin_uninstall_profile(dispwin *p, char *fname, p_scope scope) {
307 	debugr("madVRdisp doesn't support uninstalling profiles\n");
308 	return 1;
309 }
310 
311 /* Get the currently installed display profile. */
312 /* Return NULL if failed. */
madvrwin_get_profile(dispwin * p,char * name,int mxlen)313 icmFile *madvrwin_get_profile(dispwin *p, char *name, int mxlen) {
314 	debugr("madVRdisp doesn't support getting the current profile\n");
315 	return NULL;
316 }
317 
318 /* ----------------------------------------------- */
319 
320 /* Change the window color. */
321 /* Return 1 on error, 2 on window being closed */
madvrwin_set_color(dispwin * p,double r,double g,double b)322 static int madvrwin_set_color(
323 dispwin *p,
324 double r, double g, double b	/* Color values 0.0 - 1.0 */
325 ) {
326 	int j;
327 	double orgb[3];		/* Previous RGB value */
328 	double kr, kf;
329 	int update_delay = 0;
330 
331 	debugr("madvrwin_set_color called\n");
332 
333 	if (p->nowin)
334 		return 1;
335 
336 	orgb[0] = p->rgb[0]; p->rgb[0] = r;
337 	orgb[1] = p->rgb[1]; p->rgb[1] = g;
338 	orgb[2] = p->rgb[2]; p->rgb[2] = b;
339 
340 	if (!madVR_ShowRGB(p->rgb[0], p->rgb[1], p->rgb[2])) {
341 		debugr2((errout,"madVR_ShowRGB failed\n"));
342 		return 1;
343 	}
344 
345 	/* Allow for display update & instrument delays */
346 	update_delay = dispwin_compute_delay(p, orgb);
347 	debugr2((errout, "madvrwin_set_color delaying %d msec\n",update_delay));
348 	msec_sleep(update_delay);
349 
350 	return 0;
351 }
352 
353 /* Set/unset the full screen black flag */
354 /* Return nz on error */
madvrwin_set_fc(dispwin * p,int fullscreen)355 static int madvrwin_set_fc(dispwin *p, int fullscreen) {
356 	int perc, bgperc, bgmode, border;
357 
358 	p->fullscreen = fullscreen;
359 
360 	/* Parameters that shouldn't change can be set to -1, but this doesn't seem */
361 	/* to work for background level, so get current background level */
362 	if (!madVR_GetPatternConfig(&perc, &bgperc, &bgmode, &border)) {
363 		debugr2((errout,"madVR_GetPatternConfig failed\n"));
364 		return 1;
365 	}
366 	debugr2((errout,"madvrwin_set_fc: got pattern config %i, %i, %i, %i\n",
367 	                 perc, bgperc, bgmode, border));
368 
369 	/* Default test window is 10% of the width/height = 1% of the area*/
370 	perc = (int)((p->width/100.0 * 0.1 * p->height/100.0 * 0.1) * 100.0 + 0.5);
371 
372 	/* Background level is 1..100 in percent */
373 	debugr2((errout,"madvrwin_set_fc: setting pattern config %i, %i\n",
374 	                                       perc, fullscreen ? 0 : bgperc));
375 	if (!madVR_SetPatternConfig(perc, fullscreen ? 0 : bgperc, -1, -1)) {
376 		debugr2((errout,"madVR_SetPatternConfig failed\n"));
377 		return 1;
378 	}
379 
380 	return 0;
381 }
382 
383 /* ----------------------------------------------- */
384 /* set patch info */
385 /* Return nz on error */
madvrwin_set_pinfo(dispwin * p,int pno,int tno)386 static int madvrwin_set_pinfo(dispwin *p, int pno, int tno) {
387 
388 	if (!madVR_SetProgressBarPos(pno, tno))
389 		return 1;
390 
391 	return 0;
392 }
393 
394 /* ----------------------------------------------- */
395 /* Set the shell set color callout */
madvrwin_set_callout(dispwin * p,char * callout)396 void madvrwin_set_callout(
397 dispwin *p,
398 char *callout
399 ) {
400 	debugr2((errout,"madvrwin_set_callout called with '%s'\n",callout));
401 
402 	p->callout = strdup(callout);
403 }
404 
405 /* ----------------------------------------------- */
406 /* Destroy ourselves */
madvrwin_del(dispwin * p)407 static void madvrwin_del(
408 dispwin *p
409 ) {
410 
411 	debugr("madvrwin_del called\n");
412 
413 	if (p == NULL)
414 		return;
415 
416 	deinitMadVR(p);
417 
418 	if (p->name != NULL)
419 		free(p->name);
420 	if (p->description != NULL)
421 		free(p->description);
422 	if (p->callout != NULL)
423 		free(p->callout);
424 
425 	/* Since we don't restore the display, delete these here */
426 	if (p->oor != NULL) {
427 		p->oor->del(p->oor);
428 		p->oor = NULL;
429 	}
430 	if (p->or != NULL) {
431 		p->or->del(p->or);
432 		p->or = NULL;
433 	}
434 	if (p->r != NULL) {
435 		p->r->del(p->r);
436 		p->r = NULL;
437 	}
438 
439 	free(p);
440 }
441 
442 /* ----------------------------------------------- */
443 
444 /* Create a web display test window, default grey */
new_madvrwin(double width,double height,double hoff,double voff,int nowin,int native,int * noramdac,int * nocm,int out_tvenc,int fullscreen,int verb,int ddebug)445 dispwin *new_madvrwin(
446 double width, double height,	/* Width and height in mm - turned into % of screen */
447 double hoff, double voff,		/* Offset from center in fraction of screen - ignored */
448 int nowin,						/* NZ if no window should be created - RAMDAC access only */
449 int native,						/* X0 = use current per channel calibration curve */
450 								/* X1 = set native linear output and use ramdac high precn. */
451 								/* 0X = use current color management cLut (MadVR) */
452 								/* 1X = disable color management cLUT (MadVR) */
453 int *noramdac,					/* Return nz if no ramdac access. native is set to X0 */
454 int *nocm,						/* Return nz if no CM cLUT access. native is set to 0X */
455 int out_tvenc,					/* 1 = use RGB Video Level encoding */
456 int fullscreen,					/* NZ if whole screen should be filled with black */
457 int verb,						/* NZ for verbose prompts */
458 int ddebug						/* >0 to print debug statements to stderr */
459 ) {
460 	dispwin *p = NULL;
461 	char *cp;
462 	const char *options[3];
463 	char port[50];
464 
465 	debug("new_madvrwin called with native = %d\n");
466 
467 	if (out_tvenc) {
468 		if (ddebug) fprintf(stderr,"new_madvrwin failed because out_tvenc set\n");
469 		return NULL;
470 	}
471 
472 	if ((p = (dispwin *)calloc(sizeof(dispwin), 1)) == NULL) {
473 		if (ddebug) fprintf(stderr,"new_madvrwin failed because malloc failed\n");
474 		return NULL;
475 	}
476 
477 	/* !!!! Make changes in dispwin.c & webwin.c as well !!!! */
478 	p->name = strdup("Web Window");
479 	p->width = width;
480 	p->height = height;
481 	p->nowin = nowin;
482 	p->native = native;
483 	p->out_tvenc = 0;
484 	p->fullscreen = fullscreen;
485 	p->ddebug = ddebug;
486 	p->get_ramdac          = madvrwin_get_ramdac;
487 	p->set_ramdac          = madvrwin_set_ramdac;
488 	p->install_profile     = madvrwin_install_profile;
489 	p->uninstall_profile   = madvrwin_uninstall_profile;
490 	p->get_profile         = madvrwin_get_profile;
491 	p->set_color           = madvrwin_set_color;
492 	p->set_fc              = madvrwin_set_fc;
493 	p->set_pinfo           = madvrwin_set_pinfo;
494 	p->set_update_delay    = dispwin_set_update_delay;
495 	p->set_settling_delay  = dispwin_set_settling_delay;
496 	p->enable_update_delay = dispwin_enable_update_delay;
497 	p->set_callout         = madvrwin_set_callout;
498 	p->del                 = madvrwin_del;
499 
500 	debugr2((errout, "new_madvrwin got native = %d\n",native));
501 
502 #ifndef ENABLE_RAMDAC
503 	if (noramdac != NULL)
504 		*noramdac = 1;
505 	p->native &= ~1;
506 #endif
507 
508 	p->rgb[0] = p->rgb[1] = p->rgb[2] = 0.5;	/* Set Grey as the initial test color */
509 
510 	dispwin_set_default_delays(p);
511 
512 	p->fdepth = 8;				/* Assume this */
513 	p->rdepth = p->fdepth;		/* Assumed */
514 	p->ndepth = p->rdepth;		/* Assumed */
515 #ifdef ENABLE_RAMDAC
516 	p->nent = (1 << p->ndepth);
517 #else
518 	p->nent = 0;				/* No ramdac */
519 #endif
520 	p->edepth = 16;				/* Assumed */
521 
522 	if (initMadVR(p)) {
523 		debugr2((errout,"Failed to locate MadVR .dll or functions\n"));
524 		free(p);
525 		return NULL;
526 	}
527 
528 	if (!madVR_BlindConnect(1, 1000)) {
529 		debugr2((errout,"Failed to connect to MadVR\n"));
530 		free(p);
531 		return NULL;
532 	}
533 
534 	if (p->native & 2) {
535 		debugr2((errout,"new_madvrwin: disbling 3dLuts\n"));
536 		madVR_Disable3dlut();
537 	}
538 
539 	p->set_fc(p, fullscreen);
540 
541 	/* Create a suitable description */
542 	{
543 		char buf[1000];
544 
545 		sprintf(buf,"ArgyllCMS Patches");
546 		p->description = strdup(buf);
547 
548 		if (verb)
549 			printf("Created MadVR window\n");
550 
551 		madVR_SetOsdText(L"ArgyllCMS Patches");
552 	}
553 
554 #ifdef ENABLE_RAMDAC
555 
556 	/* Save the original ramdac, which gets restored on exit */
557 	if ((p->or = p->get_ramdac(p)) != NULL) {
558 
559 		debugr("Saved original VideoLUT\n");
560 
561 		if (noramdac != NULL)
562 			*noramdac = 0;
563 
564 		/* Copy original ramdac that never gets altered */
565 		if ((p->oor = p->or->clone(p->or)) == NULL) {
566 			madvrwin_del(p);
567 			debugr("ramdac clone failed - memory ?\n");
568 			return NULL;
569 		}
570 
571 		/* Create a working ramdac for native or other use */
572 		if ((p->r = p->or->clone(p->or)) == NULL) {
573 			madvrwin_del(p);
574 			debugr("ramdac clone failed - memory ?\n");
575 			return NULL;
576 		}
577 
578 		/* Setup for native mode == linear RAMDAC */
579 		if ((p->native & 1) == 1) {
580 int ii = 0;
581 			debug("About to setup native mode\n");
582 
583 			/* Since we MadVR does dithering, we don't need to use the VideoLUTs */
584 			/* to emulate higher precision, so simply set it to linear here. */
585 			if ((ii = madVR_SetDeviceGammaRamp(NULL)) == 0) {
586 				madvrwin_del(p);
587 				debugr("Clear gamma ramp failed\n");
588 				return NULL;
589 			}
590 		}
591 
592 	} else {
593 		debugr2((errout,"Unable to access VideoLUT\n"));
594 		if (noramdac != NULL)
595 			*noramdac = 1;
596 		p->oor = p->or = p->r = NULL;
597 	}
598 
599 	if (!p->nowin) {
600 
601 		/* Make sure initial test color is displayed */
602 		madvrwin_set_color(p, p->rgb[0], p->rgb[1], p->rgb[2]);
603 	}
604 #endif
605 
606 	debugr("new_madvrwin: return sucessfully\n");
607 
608 	return p;
609 }
610 
611