Title: [179637] trunk/Tools
Revision
179637
Author
simon.fra...@apple.com
Date
2015-02-04 14:38:46 -0800 (Wed, 04 Feb 2015)

Log Message

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.

Modified Paths

Diff

Modified: trunk/Tools/ChangeLog (179636 => 179637)


--- trunk/Tools/ChangeLog	2015-02-04 22:29:01 UTC (rev 179636)
+++ trunk/Tools/ChangeLog	2015-02-04 22:38:46 UTC (rev 179637)
@@ -1,3 +1,29 @@
+2015-02-04  Simon Fraser  <simon.fra...@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.
+
 2015-02-04  Daniel Bates  <daba...@apple.com>
 
         test-webkitpy fails on Mac without iphoneos SDK

Modified: trunk/Tools/DumpRenderTree/mac/LayoutTestHelper.m (179636 => 179637)


--- 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)
@@ -45,73 +45,129 @@
 
 static int installColorProfile = false;
 
-static CFURLRef sUserColorProfileURL;
+static NSMutableDictionary *originalColorProfileURLs()
+{
+    static NSMutableDictionary *sharedInstance;
+    if (!sharedInstance)
+        sharedInstance = [[NSMutableDictionary alloc] init];
+    return sharedInstance;
+}
 
+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 = "" *)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);
+    }
+}
+
 static void installLayoutTestColorProfile()
 {
     if (!installColorProfile)
         return;
 
     // To make sure we get consistent colors (not dependent on the chosen color
-    // space of the main display), we force the generic RGB color profile.
+    // space of the display), we force the generic sRGB color profile on all displays.
     // This causes a change the user can see.
-    
-    CFUUIDRef mainDisplayID = CGDisplayCreateUUIDFromDisplayID(CGMainDisplayID());
-    
-    if (!sUserColorProfileURL) {
-        CFDictionaryRef deviceInfo = ColorSyncDeviceCopyDeviceInfo(kColorSyncDisplayDeviceClass, mainDisplayID);
 
-        if (!deviceInfo) {
-            NSLog(@"No display attached to system; not setting main display's color profile.");
-            CFRelease(mainDisplayID);
-            return;
-        }
+    NSArray *displays = displayUUIDStrings();
+    saveDisplayColorProfiles(displays);
 
-        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);
-    }
-
     ColorSyncProfileRef sRGBProfile = ColorSyncProfileCreateWithName(kColorSyncSRGBProfile);
     CFErrorRef error;
     CFURLRef profileURL = ColorSyncProfileGetURL(sRGBProfile, &error);
     if (!profileURL) {
         NSLog(@"Failed to get URL of Generic RGB color profile! Many pixel tests may fail as a result. Error: %@", error);
-        
-        if (sUserColorProfileURL) {
-            CFRelease(sUserColorProfileURL);
-            sUserColorProfileURL = 0;
-        }
-        
-        CFRelease(sRGBProfile);
-        CFRelease(mainDisplayID);
         return;
     }
-        
-    CFMutableDictionaryRef profileInfo = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-    CFDictionarySetValue(profileInfo, kColorSyncDeviceDefaultProfileID, profileURL);
     
-    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);
+    for (NSString *displayUUIDString in displays)
+        setDisplayColorProfile(displayUUIDString, (NSURL *)profileURL);
 }
 
 static void restoreUserColorProfile(void)
@@ -122,15 +178,8 @@
     // This is used as a signal handler, and thus the calls into ColorSync are unsafe.
     // But we might as well try to restore the user's color profile, we're going down anyway...
     
-    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);
+    NSArray *displays = displayUUIDStrings();
+    restoreDisplayColorProfiles(displays);
 }
 
 static void simpleSignalHandler(int sig)
@@ -188,8 +237,6 @@
         }
     }
 
-    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
-
     // Hooks the ways we might get told to clean up...
     signal(SIGINT, simpleSignalHandler);
     signal(SIGHUP, simpleSignalHandler);
@@ -210,7 +257,6 @@
     // Restore the profile
     restoreUserColorProfile();
 
-    [pool release];
     return 0;
 }
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to