<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[179637] trunk/Tools</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/179637">179637</a></dd>
<dt>Author</dt> <dd>simon.fraser@apple.com</dd>
<dt>Date</dt> <dd>2015-02-04 14:38:46 -0800 (Wed, 04 Feb 2015)</dd>
</dl>
<h3>Log Message</h3>
<pre>LayoutTestHelper should set the color profile of all displays
https://bugs.webkit.org/show_bug.cgi?id=141260
Reviewed by Tim Horton.
WebKitTestRunner can (erroneously) grab the colorspace of the "main" screen.
which is the screen with the active window. Make things more robust by changing
the colorspace of all displays, not just the main screen, when running layout tests.
* DumpRenderTree/mac/Configurations/LayoutTestHelper.xcconfig: Enable ARC
* DumpRenderTree/mac/LayoutTestHelper.m:
(originalColorProfileURLs):
(colorProfileURLForDisplay):
(displayUUIDStrings):
(saveDisplayColorProfiles):
(setDisplayColorProfile):
(restoreDisplayColorProfiles):
(installLayoutTestColorProfile):
(restoreUserColorProfile):
(main):
Store display color profiles by map of UUID strings to URLs (NSUUID and CFUUID are not
toll-free bridged, sadly). Use the map to restore all profiles on exit.
Convert to use more Obj-C types.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsDumpRenderTreemacLayoutTestHelperm">trunk/Tools/DumpRenderTree/mac/LayoutTestHelper.m</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (179636 => 179637)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog        2015-02-04 22:29:01 UTC (rev 179636)
+++ trunk/Tools/ChangeLog        2015-02-04 22:38:46 UTC (rev 179637)
</span><span class="lines">@@ -1,3 +1,29 @@
</span><ins>+2015-02-04 Simon Fraser <simon.fraser@apple.com>
+
+ LayoutTestHelper should set the color profile of all displays
+ https://bugs.webkit.org/show_bug.cgi?id=141260
+
+ Reviewed by Tim Horton.
+
+ WebKitTestRunner can (erroneously) grab the colorspace of the "main" screen.
+ which is the screen with the active window. Make things more robust by changing
+ the colorspace of all displays, not just the main screen, when running layout tests.
+
+ * DumpRenderTree/mac/Configurations/LayoutTestHelper.xcconfig: Enable ARC
+ * DumpRenderTree/mac/LayoutTestHelper.m:
+ (originalColorProfileURLs):
+ (colorProfileURLForDisplay):
+ (displayUUIDStrings):
+ (saveDisplayColorProfiles):
+ (setDisplayColorProfile):
+ (restoreDisplayColorProfiles):
+ (installLayoutTestColorProfile):
+ (restoreUserColorProfile):
+ (main):
+ Store display color profiles by map of UUID strings to URLs (NSUUID and CFUUID are not
+ toll-free bridged, sadly). Use the map to restore all profiles on exit.
+ Convert to use more Obj-C types.
+
</ins><span class="cx"> 2015-02-04 Daniel Bates <dabates@apple.com>
</span><span class="cx">
</span><span class="cx"> test-webkitpy fails on Mac without iphoneos SDK
</span></span></pre></div>
<a id="trunkToolsDumpRenderTreemacLayoutTestHelperm"></a>
<div class="modfile"><h4>Modified: trunk/Tools/DumpRenderTree/mac/LayoutTestHelper.m (179636 => 179637)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/DumpRenderTree/mac/LayoutTestHelper.m        2015-02-04 22:29:01 UTC (rev 179636)
+++ trunk/Tools/DumpRenderTree/mac/LayoutTestHelper.m        2015-02-04 22:38:46 UTC (rev 179637)
</span><span class="lines">@@ -45,73 +45,129 @@
</span><span class="cx">
</span><span class="cx"> static int installColorProfile = false;
</span><span class="cx">
</span><del>-static CFURLRef sUserColorProfileURL;
</del><ins>+static NSMutableDictionary *originalColorProfileURLs()
+{
+ static NSMutableDictionary *sharedInstance;
+ if (!sharedInstance)
+ sharedInstance = [[NSMutableDictionary alloc] init];
+ return sharedInstance;
+}
</ins><span class="cx">
</span><ins>+static NSURL *colorProfileURLForDisplay(NSString *displayUUIDString)
+{
+ CFUUIDRef uuid = CFUUIDCreateFromString(kCFAllocatorDefault, (CFStringRef)displayUUIDString);
+ CFDictionaryRef deviceInfo = ColorSyncDeviceCopyDeviceInfo(kColorSyncDisplayDeviceClass, uuid);
+ CFRelease(uuid);
+ if (!deviceInfo) {
+ NSLog(@"No display attached to system; not setting main display's color profile.");
+ return nil;
+ }
+
+ CFURLRef profileURL;
+ CFDictionaryRef profileInfo = (CFDictionaryRef)CFDictionaryGetValue(deviceInfo, kColorSyncCustomProfiles);
+ if (profileInfo)
+ profileURL = (CFURLRef)CFDictionaryGetValue(profileInfo, CFSTR("1"));
+ else {
+ profileInfo = (CFDictionaryRef)CFDictionaryGetValue(deviceInfo, kColorSyncFactoryProfiles);
+ CFDictionaryRef factoryProfile = (CFDictionaryRef)CFDictionaryGetValue(profileInfo, CFSTR("1"));
+ profileURL = (CFURLRef)CFDictionaryGetValue(factoryProfile, kColorSyncDeviceProfileURL);
+ }
+
+
+ NSURL *url = (NSURL *)CFAutorelease(CFRetain(profileURL));
+ CFRelease(deviceInfo);
+ return url;
+}
+
+static NSArray *displayUUIDStrings()
+{
+ NSMutableArray *result = [NSMutableArray array];
+
+ static const uint32_t maxDisplayCount = 10;
+ CGDirectDisplayID displayIDs[maxDisplayCount] = { 0 };
+ uint32_t displayCount = 0;
+
+ CGError err = CGGetActiveDisplayList(maxDisplayCount, displayIDs, &displayCount);
+ if (err != kCGErrorSuccess) {
+ NSLog(@"Error %d getting active display list; not setting display color profile.", err);
+ return nil;
+ }
+
+ if (!displayCount) {
+ NSLog(@"No display attached to system; not setting display color profile.");
+ return nil;
+ }
+
+ for (uint32_t i = 0; i < displayCount; ++i) {
+ CFUUIDRef displayUUIDRef = CGDisplayCreateUUIDFromDisplayID(displayIDs[i]);
+ [result addObject:(NSString *)CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, displayUUIDRef))];
+ CFRelease(displayUUIDRef);
+ }
+
+ return result;
+}
+
+static void saveDisplayColorProfiles(NSArray *displayUUIDStrings)
+{
+ NSMutableDictionary *userColorProfiles = originalColorProfileURLs();
+
+ for (NSString *UUIDString in displayUUIDStrings) {
+ if ([userColorProfiles objectForKey:UUIDString])
+ continue;
+
+ NSURL *colorProfileURL = colorProfileURLForDisplay(UUIDString);
+ [userColorProfiles setObject:colorProfileURL forKey:UUIDString];
+ }
+}
+
+static void setDisplayColorProfile(NSString *displayUUIDString, NSURL *colorProfileURL)
+{
+ NSDictionary *profileInfo = @{
+ (NSString *)kColorSyncDeviceDefaultProfileID : colorProfileURL
+ };
+
+ CFUUIDRef uuid = CFUUIDCreateFromString(kCFAllocatorDefault, (CFStringRef)displayUUIDString);
+ BOOL success = ColorSyncDeviceSetCustomProfiles(kColorSyncDisplayDeviceClass, uuid, (CFDictionaryRef)profileInfo);
+ if (!success)
+ NSLog(@"Failed to set color profile for display %@! Many pixel tests may fail as a result.", displayUUIDString);
+ CFRelease(uuid);
+}
+
+static void restoreDisplayColorProfiles(NSArray *displayUUIDStrings)
+{
+ NSMutableDictionary* userColorProfiles = originalColorProfileURLs();
+
+ for (NSString *UUIDString in displayUUIDStrings) {
+ NSURL *profileURL = [userColorProfiles objectForKey:UUIDString];
+ if (!profileURL)
+ continue;
+
+ setDisplayColorProfile(UUIDString, profileURL);
+ }
+}
+
</ins><span class="cx"> static void installLayoutTestColorProfile()
</span><span class="cx"> {
</span><span class="cx"> if (!installColorProfile)
</span><span class="cx"> return;
</span><span class="cx">
</span><span class="cx"> // To make sure we get consistent colors (not dependent on the chosen color
</span><del>- // space of the main display), we force the generic RGB color profile.
</del><ins>+ // space of the display), we force the generic sRGB color profile on all displays.
</ins><span class="cx"> // This causes a change the user can see.
</span><del>-
- CFUUIDRef mainDisplayID = CGDisplayCreateUUIDFromDisplayID(CGMainDisplayID());
-
- if (!sUserColorProfileURL) {
- CFDictionaryRef deviceInfo = ColorSyncDeviceCopyDeviceInfo(kColorSyncDisplayDeviceClass, mainDisplayID);
</del><span class="cx">
</span><del>- if (!deviceInfo) {
- NSLog(@"No display attached to system; not setting main display's color profile.");
- CFRelease(mainDisplayID);
- return;
- }
</del><ins>+ NSArray *displays = displayUUIDStrings();
+ saveDisplayColorProfiles(displays);
</ins><span class="cx">
</span><del>- CFDictionaryRef profileInfo = (CFDictionaryRef)CFDictionaryGetValue(deviceInfo, kColorSyncCustomProfiles);
- if (profileInfo) {
- sUserColorProfileURL = (CFURLRef)CFDictionaryGetValue(profileInfo, CFSTR("1"));
- CFRetain(sUserColorProfileURL);
- } else {
- profileInfo = (CFDictionaryRef)CFDictionaryGetValue(deviceInfo, kColorSyncFactoryProfiles);
- CFDictionaryRef factoryProfile = (CFDictionaryRef)CFDictionaryGetValue(profileInfo, CFSTR("1"));
- sUserColorProfileURL = (CFURLRef)CFDictionaryGetValue(factoryProfile, kColorSyncDeviceProfileURL);
- CFRetain(sUserColorProfileURL);
- }
-
- CFRelease(deviceInfo);
- }
-
</del><span class="cx"> ColorSyncProfileRef sRGBProfile = ColorSyncProfileCreateWithName(kColorSyncSRGBProfile);
</span><span class="cx"> CFErrorRef error;
</span><span class="cx"> CFURLRef profileURL = ColorSyncProfileGetURL(sRGBProfile, &error);
</span><span class="cx"> if (!profileURL) {
</span><span class="cx"> NSLog(@"Failed to get URL of Generic RGB color profile! Many pixel tests may fail as a result. Error: %@", error);
</span><del>-
- if (sUserColorProfileURL) {
- CFRelease(sUserColorProfileURL);
- sUserColorProfileURL = 0;
- }
-
- CFRelease(sRGBProfile);
- CFRelease(mainDisplayID);
</del><span class="cx"> return;
</span><span class="cx"> }
</span><del>-
- CFMutableDictionaryRef profileInfo = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
- CFDictionarySetValue(profileInfo, kColorSyncDeviceDefaultProfileID, profileURL);
</del><span class="cx">
</span><del>- if (!ColorSyncDeviceSetCustomProfiles(kColorSyncDisplayDeviceClass, mainDisplayID, profileInfo)) {
- NSLog(@"Failed to set color profile for main display! Many pixel tests may fail as a result.");
-
- if (sUserColorProfileURL) {
- CFRelease(sUserColorProfileURL);
- sUserColorProfileURL = 0;
- }
- }
-
- CFRelease(profileInfo);
- CFRelease(sRGBProfile);
- CFRelease(mainDisplayID);
</del><ins>+ for (NSString *displayUUIDString in displays)
+ setDisplayColorProfile(displayUUIDString, (NSURL *)profileURL);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> static void restoreUserColorProfile(void)
</span><span class="lines">@@ -122,15 +178,8 @@
</span><span class="cx"> // This is used as a signal handler, and thus the calls into ColorSync are unsafe.
</span><span class="cx"> // But we might as well try to restore the user's color profile, we're going down anyway...
</span><span class="cx">
</span><del>- if (!sUserColorProfileURL)
- return;
-
- CFUUIDRef mainDisplayID = CGDisplayCreateUUIDFromDisplayID(CGMainDisplayID());
- CFMutableDictionaryRef profileInfo = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
- CFDictionarySetValue(profileInfo, kColorSyncDeviceDefaultProfileID, sUserColorProfileURL);
- ColorSyncDeviceSetCustomProfiles(kColorSyncDisplayDeviceClass, mainDisplayID, profileInfo);
- CFRelease(mainDisplayID);
- CFRelease(profileInfo);
</del><ins>+ NSArray *displays = displayUUIDStrings();
+ restoreDisplayColorProfiles(displays);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> static void simpleSignalHandler(int sig)
</span><span class="lines">@@ -188,8 +237,6 @@
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><del>- NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
-
</del><span class="cx"> // Hooks the ways we might get told to clean up...
</span><span class="cx"> signal(SIGINT, simpleSignalHandler);
</span><span class="cx"> signal(SIGHUP, simpleSignalHandler);
</span><span class="lines">@@ -210,7 +257,6 @@
</span><span class="cx"> // Restore the profile
</span><span class="cx"> restoreUserColorProfile();
</span><span class="cx">
</span><del>- [pool release];
</del><span class="cx"> return 0;
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre>
</div>
</div>
</body>
</html>