Backed out changeset ef14be22d6f7 (bug 907196) for Windows bustage.
authorRyan VanderMeulen <ryanvm@gmail.com>
Mon, 13 Jan 2014 10:25:52 -0500
changeset 163197 d9107f528b8095dbe04bed052aeddd6b1ba5cf21
parent 163196 5ed3e52d91e27c5659c6cfc653c4db15477534bf
child 163198 456104e27a9a624fb0b90949eac89481d446f9b3
push id4307
push userryanvm@gmail.com
push dateMon, 13 Jan 2014 22:55:19 +0000
treeherderfx-team@ca88b415afd6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs907196
milestone29.0a1
backs outef14be22d6f7963ba708d89daff536cc9fc956ce
Backed out changeset ef14be22d6f7 (bug 907196) for Windows bustage. CLOSED TREE
gfx/qcms/iccread.c
gfx/qcms/qcms.h
gfx/qcms/qcmsint.h
gfx/qcms/transform.c
gfx/thebes/gfxPlatform.cpp
gfx/thebes/gfxPlatform.h
gfx/thebes/gfxPlatformGtk.cpp
gfx/thebes/gfxPlatformGtk.h
gfx/thebes/gfxPlatformMac.cpp
gfx/thebes/gfxPlatformMac.h
gfx/thebes/gfxWindowsPlatform.cpp
gfx/thebes/gfxWindowsPlatform.h
--- a/gfx/qcms/iccread.c
+++ b/gfx/qcms/iccread.c
@@ -29,33 +29,29 @@
 
 /* It might be worth having a unified limit on content controlled
  * allocation per profile. This would remove the need for many
  * of the arbitrary limits that we used */
 
 typedef uint32_t be32;
 typedef uint16_t be16;
 
-static be32 cpu_to_be32(uint32_t v)
+#if 0
+not used yet
+/* __builtin_bswap isn't available in older gccs
+ * so open code it for now */
+static be32 cpu_to_be32(int32_t v)
 {
 #ifdef IS_LITTLE_ENDIAN
 	return ((v & 0xff) << 24) | ((v & 0xff00) << 8) | ((v & 0xff0000) >> 8) | ((v & 0xff000000) >> 24);
-#else
+	//return __builtin_bswap32(v);
 	return v;
 #endif
 }
-
-static be16 cpu_to_be16(uint16_t v)
-{
-#ifdef IS_LITTLE_ENDIAN
-	return ((v & 0xff) << 8) | ((v & 0xff00) >> 8);
-#else
-	return v;
 #endif
-}
 
 static uint32_t be32_to_cpu(be32 v)
 {
 #ifdef IS_LITTLE_ENDIAN
 	return ((v & 0xff) << 24) | ((v & 0xff00) << 8) | ((v & 0xff0000) >> 8) | ((v & 0xff000000) >> 24);
 	//return __builtin_bswap32(v);
 #else
 	return v;
@@ -134,26 +130,16 @@ static uInt8Number read_uInt8Number(stru
 	return read_u8(mem, offset);
 }
 
 static uInt16Number read_uInt16Number(struct mem_source *mem, size_t offset)
 {
 	return read_u16(mem, offset);
 }
 
-static void write_u32(void *mem, size_t offset, uint32_t value)
-{
-    *((uint32_t *)((unsigned char*)mem + offset)) = cpu_to_be32(value);
-}
-
-static void write_u16(void *mem, size_t offset, uint16_t value)
-{
-    *((uint16_t *)((unsigned char*)mem + offset)) = cpu_to_be16(value);
-}
-
 #define BAD_VALUE_PROFILE NULL
 #define INVALID_PROFILE NULL
 #define NO_MEM_PROFILE NULL
 
 /* An arbitrary 4MB limit on profile size */
 #define MAX_PROFILE_SIZE 1024*1024*4
 #define MAX_TAG_COUNT 1024
 
@@ -857,20 +843,21 @@ static struct curveType *curve_from_gamm
 {
 	struct curveType *curve;
 	int num_entries = 1;
 	curve = malloc(sizeof(struct curveType) + sizeof(uInt16Number)*num_entries);
 	if (!curve)
 		return NULL;
 	curve->count = num_entries;
 	curve->data[0] = float_to_u8Fixed8Number(gamma);
-  	curve->type = CURVE_TYPE;
+  curve->type = CURVE_TYPE;
 	return curve;
 }
 
+
 //XXX: it would be nice if we had a way of ensuring
 // everything in a profile was initialized regardless of how it was created
 
 //XXX: should this also be taking a black_point?
 /* similar to CGColorSpaceCreateCalibratedRGB */
 qcms_profile* qcms_profile_create_rgb_with_gamma(
 		qcms_CIE_xyY white_point,
 		qcms_CIE_xyYTRIPLE primaries,
@@ -1160,219 +1147,68 @@ void qcms_profile_release(qcms_profile *
 	free(profile->blueTRC);
 	free(profile->greenTRC);
 	free(profile->grayTRC);
 	free(profile);
 }
 
 
 #include <stdio.h>
-static void qcms_data_from_file(FILE *file, void **mem, size_t *size)
+qcms_profile* qcms_profile_from_file(FILE *file)
 {
 	uint32_t length, remaining_length;
+	qcms_profile *profile;
 	size_t read_length;
 	be32 length_be;
 	void *data;
 
-	*mem = NULL;
-	*size = 0;
-
 	if (fread(&length_be, 1, sizeof(length_be), file) != sizeof(length_be))
-		return;
+		return BAD_VALUE_PROFILE;
 
 	length = be32_to_cpu(length_be);
 	if (length > MAX_PROFILE_SIZE || length < sizeof(length_be))
-		return;
+		return BAD_VALUE_PROFILE;
 
 	/* allocate room for the entire profile */
 	data = malloc(length);
 	if (!data)
-		return;
+		return NO_MEM_PROFILE;
 
 	/* copy in length to the front so that the buffer will contain the entire profile */
 	*((be32*)data) = length_be;
 	remaining_length = length - sizeof(length_be);
 
 	/* read the rest profile */
 	read_length = fread((unsigned char*)data + sizeof(length_be), 1, remaining_length, file);
 	if (read_length != remaining_length) {
 		free(data);
-		return;
+		return INVALID_PROFILE;
 	}
 
-	/* successfully get the profile.*/
-	*mem = data;
-	*size = length;
-}
-
-qcms_profile* qcms_profile_from_file(FILE *file)
-{
-	uint32_t length;
-	qcms_profile *profile;
-	void *data;
-
-	qcms_data_from_file(file, &data, &length);
-	if ((data == NULL) || (length == 0))
-		return INVALID_PROFILE;
-
 	profile = qcms_profile_from_memory(data, length);
 	free(data);
 	return profile;
 }
 
 qcms_profile* qcms_profile_from_path(const char *path)
 {
 	qcms_profile *profile = NULL;
 	FILE *file = fopen(path, "rb");
 	if (file) {
 		profile = qcms_profile_from_file(file);
 		fclose(file);
 	}
 	return profile;
 }
 
-void qcms_data_from_path(const char *path, void **mem, size_t *size)
-{
-	*mem = NULL;
-	*size  = 0;
-
-	FILE *file = fopen(path, "rb");
-	if (file) {
-		qcms_data_from_file(file, mem, size);
-		fclose(file);
-	}
-}
-
 #ifdef _WIN32
 /* Unicode path version */
 qcms_profile* qcms_profile_from_unicode_path(const wchar_t *path)
 {
 	qcms_profile *profile = NULL;
 	FILE *file = _wfopen(path, L"rb");
 	if (file) {
 		profile = qcms_profile_from_file(file);
 		fclose(file);
 	}
 	return profile;
 }
-
-void qcms_data_from_unicode_path(const wchar_t *path, void **mem, size_t *size)
-{
-	*mem = NULL;
-	*size  = 0;
-	FILE *file = _wfopen(path, L"rb");
-	if (file) {
-		qcms_data_from_file(file, mem, size);
-		fclose(file);
-	}
-}
 #endif
-
-/*
-* This function constructs an ICC profile memory with given header and tag data,
-* which can be read via qcms_profile_from_memory(). that means, we must satisfy
-* the profiler header type check (which seems not complete till now) and proper
-* information to read data from the tag table and tag data elements memory.
-* 
-* To construct a valid ICC profile, its divided into three steps :
-*	(1) construct the r/g/bXYZ part
-*	(2) construct the r/g/bTRC part
-*	(3) construct the profile header
-* this is a hardcode step just for "create_rgb_with_gamma", it is the only
-* requirement till now, maybe we can make this method more general in future,
-*
-* NOTE : some of the parameters below are hardcode, please refer to the ICC documentation.
-*/
-#define ICC_PROFILE_HEADER_LENGTH 128
-void qcms_data_create_rgb_with_gamma(qcms_CIE_xyY white_point, qcms_CIE_xyYTRIPLE primaries, float gamma, void **mem, size_t *size)
-{
-	uint32_t length, offset, index, xyz_count, trc_count;
-	size_t tag_table_offset, tag_data_offset;
-	void *data;
-	struct matrix colorants;
-
-	uint32_t TAG_XYZ[3] = {TAG_rXYZ, TAG_gXYZ, TAG_bXYZ};
-	uint32_t TAG_TRC[3] = {TAG_rTRC, TAG_gTRC, TAG_bTRC};
-
-	if ((mem == NULL) || (size == NULL))
-		return;
-
-	*mem = NULL;
-	*size = 0;
-
-	/* 
-	* total length = icc profile header(128) + tag count(4) + 
-	* (tag table item (12) * total tag (6 = 3 rTRC + 3 rXYZ)) + rTRC elements data (3 * 20)
-	* + rXYZ elements data (3*16), and all tag data elements must start at the 4-byte boundary.
-	*/
-	xyz_count = 3; // rXYZ, gXYZ, bXYZ
-	trc_count = 3; // rTRC, gTRC, bTRC
-	length =  ICC_PROFILE_HEADER_LENGTH + 4 + (12 * (xyz_count + trc_count)) + (xyz_count * 20) + (trc_count * 16);
-	
-	// reserve the total memory.
-	data = malloc(length);
-	if (!data)
-		return;
-	memset(data, 0, length);
-
-	// Part1 : write rXYZ, gXYZ and bXYZ
-	if (!get_rgb_colorants(&colorants, white_point, primaries)) {
-		free(data);
-		return;
-	}
-
-	 // the position of first tag's signature in tag table
-	tag_table_offset = ICC_PROFILE_HEADER_LENGTH + 4;
-	tag_data_offset = ICC_PROFILE_HEADER_LENGTH + 4 +
-	   (12 * (xyz_count + trc_count)); // the start of tag data elements.
-
-	for (index = 0; index < xyz_count; ++index) {
-		// tag table
-		write_u32(data, tag_table_offset, TAG_XYZ[index]);
-		write_u32(data, tag_table_offset+4, tag_data_offset);
-		write_u32(data, tag_table_offset+8, 20); // 20 bytes per TAG_(r/g/b)XYZ tag element
-
-		// tag data element
-		write_u32(data, tag_data_offset, XYZ_TYPE);
-		// reserved 4 bytes.
-		write_u32(data, tag_data_offset+8, double_to_s15Fixed16Number(colorants.m[0][index]));
-		write_u32(data, tag_data_offset+12, double_to_s15Fixed16Number(colorants.m[1][index]));
-		write_u32(data, tag_data_offset+16, double_to_s15Fixed16Number(colorants.m[2][index]));
-
-		tag_table_offset += 12;
-		tag_data_offset += 20;
-	}
-
-	// Part2 : write rTRC, gTRC and bTRC
-	for (index = 0; index < trc_count; ++index) {
-		// tag table
-		write_u32(data, tag_table_offset, TAG_TRC[index]);
-		write_u32(data, tag_table_offset+4, tag_data_offset);
-		write_u32(data, tag_table_offset+8, 14); // 14 bytes per TAG_(r/g/b)TRC element
-
-		// tag data element
-		write_u32(data, tag_data_offset, CURVE_TYPE);
-		// reserved 4 bytes.
-		write_u32(data, tag_data_offset+8, 1); // count
-		write_u16(data, tag_data_offset+12, float_to_u8Fixed8Number(gamma));
-
-		tag_table_offset += 12;
-		tag_data_offset += 16;
-	}
-
-	/* Part3 : write profile header
-	 *
-	 * Important header fields are left empty. This generates a profile for internal use only.
-	 * We should be generating: Profile version (04300000h), Profile signature (acsp), 
-	 * PCS illumiant field. Likewise mandatory profile tags are omitted.
-	 */
-	write_u32(data, 0, length); // the total length of this memory
-	write_u32(data, 12, DISPLAY_DEVICE_PROFILE); // profile->class
-	write_u32(data, 16, RGB_SIGNATURE); // profile->color_space
-	write_u32(data, 20, XYZ_SIGNATURE); // profile->pcs
-	write_u32(data, 64, QCMS_INTENT_PERCEPTUAL); // profile->rendering_intent
-
-	write_u32(data, ICC_PROFILE_HEADER_LENGTH, 6); // total tag count
-
-	// prepare the result
-	*mem = data;
-	*size = length;
-}
--- a/gfx/qcms/qcms.h
+++ b/gfx/qcms/qcms.h
@@ -125,37 +125,26 @@ typedef struct
 typedef struct
 {
 	qcms_CIE_xyY red;
 	qcms_CIE_xyY green;
 	qcms_CIE_xyY blue;
 } qcms_CIE_xyYTRIPLE;
 
 qcms_profile* qcms_profile_create_rgb_with_gamma(
-                qcms_CIE_xyY white_point,
-                qcms_CIE_xyYTRIPLE primaries,
-                float gamma);
-
-void qcms_data_create_rgb_with_gamma(
-                qcms_CIE_xyY white_point,
-                qcms_CIE_xyYTRIPLE primaries,
-                float gamma,
-                void **mem,
-                size_t *size);
+		qcms_CIE_xyY white_point,
+		qcms_CIE_xyYTRIPLE primaries,
+		float gamma);
 
 qcms_profile* qcms_profile_from_memory(const void *mem, size_t size);
 
 qcms_profile* qcms_profile_from_file(FILE *file);
 qcms_profile* qcms_profile_from_path(const char *path);
-
-void qcms_data_from_path(const char *path, void **mem, size_t *size);
-
 #ifdef _WIN32
 qcms_profile* qcms_profile_from_unicode_path(const wchar_t *path);
-void qcms_data_from_unicode_path(const wchar_t *path, void **mem, size_t *size);
 #endif
 qcms_profile* qcms_profile_sRGB(void);
 void qcms_profile_release(qcms_profile *profile);
 
 qcms_bool qcms_profile_is_bogus(qcms_profile *profile);
 qcms_intent qcms_profile_get_rendering_intent(qcms_profile *profile);
 icColorSpaceSignature qcms_profile_get_color_space(qcms_profile *profile);
 
--- a/gfx/qcms/qcmsint.h
+++ b/gfx/qcms/qcmsint.h
@@ -250,17 +250,16 @@ static inline float uInt8Number_to_float
 static inline float uInt16Number_to_float(uInt16Number a)
 {
 	return ((int32_t)a)/65535.f;
 }
 
 
 void precache_release(struct precache_output *p);
 qcms_bool set_rgb_colorants(qcms_profile *profile, qcms_CIE_xyY white_point, qcms_CIE_xyYTRIPLE primaries);
-qcms_bool get_rgb_colorants(struct matrix *colorants, qcms_CIE_xyY white_point, qcms_CIE_xyYTRIPLE primaries);
 
 void qcms_transform_data_rgb_out_lut_sse2(qcms_transform *transform,
                                           unsigned char *src,
                                           unsigned char *dest,
                                           size_t length);
 void qcms_transform_data_rgba_out_lut_sse2(qcms_transform *transform,
                                           unsigned char *src,
                                           unsigned char *dest,
--- a/gfx/qcms/transform.c
+++ b/gfx/qcms/transform.c
@@ -301,24 +301,16 @@ qcms_bool set_rgb_colorants(qcms_profile
 
 	profile->blueColorant.X = double_to_s15Fixed16Number(colorants.m[0][2]);
 	profile->blueColorant.Y = double_to_s15Fixed16Number(colorants.m[1][2]);
 	profile->blueColorant.Z = double_to_s15Fixed16Number(colorants.m[2][2]);
 
 	return true;
 }
 
-qcms_bool get_rgb_colorants(struct matrix *colorants, qcms_CIE_xyY white_point, qcms_CIE_xyYTRIPLE primaries)
-{
-	*colorants = build_RGB_to_XYZ_transfer_matrix(white_point, primaries);
-	*colorants = adapt_matrix_to_D50(*colorants, white_point);
-
-	return (colorants->invalid ? true : false);
-}
-
 #if 0
 static void qcms_transform_data_rgb_out_pow(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
 {
 	int i;
 	float (*mat)[4] = transform->matrix;
 	for (i=0; i<length; i++) {
 		unsigned char device_r = *src++;
 		unsigned char device_g = *src++;
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -1702,33 +1702,20 @@ gfxPlatform::TransformPixel(const gfxRGB
         new (&out) gfxRGBA(packed, gfxRGBA::PACKED_ARGB);
 #endif
     }
 
     else if (&out != &in)
         out = in;
 }
 
-void
-gfxPlatform::GetPlatformCMSOutputProfile(void *&mem, size_t &size)
+qcms_profile *
+gfxPlatform::GetPlatformCMSOutputProfile()
 {
-    mem = nullptr;
-    size = 0;
-}
-
-void
-gfxPlatform::GetCMSOutputProfileData(void *&mem, size_t &size)
-{
-    nsAdoptingCString fname = Preferences::GetCString("gfx.color_management.display_profile");
-    if (!fname.IsEmpty()) {
-        qcms_data_from_path(fname, &mem, &size);
-    }
-    else {
-        gfxPlatform::GetPlatform()->GetPlatformCMSOutputProfile(mem, size);
-    }
+    return nullptr;
 }
 
 void
 gfxPlatform::CreateCMSOutputProfile()
 {
     if (!gCMSOutputProfile) {
         /* Determine if we're using the internal override to force sRGB as
            an output profile for reftests. See Bug 452125.
@@ -1737,24 +1724,25 @@ gfxPlatform::CreateCMSOutputProfile()
            default value of this preference, which means nsIPrefBranch::GetBoolPref
            will typically throw (and leave its out-param untouched).
          */
         if (Preferences::GetBool(GFX_PREF_CMS_FORCE_SRGB, false)) {
             gCMSOutputProfile = GetCMSsRGBProfile();
         }
 
         if (!gCMSOutputProfile) {
-            void* mem = nullptr;
-            size_t size = 0;
+            nsAdoptingCString fname = Preferences::GetCString(GFX_PREF_CMS_DISPLAY_PROFILE);
+            if (!fname.IsEmpty()) {
+                gCMSOutputProfile = qcms_profile_from_path(fname);
+            }
+        }
 
-            GetCMSOutputProfileData(mem, size);
-            if ((mem != nullptr) && (size > 0)) {
-                gCMSOutputProfile = qcms_profile_from_memory(mem, size);
-                free(mem);
-            }
+        if (!gCMSOutputProfile) {
+            gCMSOutputProfile =
+                gfxPlatform::GetPlatform()->GetPlatformCMSOutputProfile();
         }
 
         /* Determine if the profile looks bogus. If so, close the profile
          * and use sRGB instead. See bug 460629, */
         if (gCMSOutputProfile && qcms_profile_is_bogus(gCMSOutputProfile)) {
             NS_ASSERTION(gCMSOutputProfile != GetCMSsRGBProfile(),
                          "Builtin sRGB profile tagged as bogus!!!");
             qcms_profile_release(gCMSOutputProfile);
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -707,21 +707,19 @@ protected:
 private:
     /**
      * Start up Thebes.
      */
     static void Init();
 
     static void CreateCMSOutputProfile();
 
-    static void GetCMSOutputProfileData(void *&mem, size_t &size);
-
     friend void RecordingPrefChanged(const char *aPrefName, void *aClosure);
 
-    virtual void GetPlatformCMSOutputProfile(void *&mem, size_t &size);
+    virtual qcms_profile* GetPlatformCMSOutputProfile();
 
     virtual bool SupportsOffMainThreadCompositing() { return true; }
 
     nsRefPtr<gfxASurface> mScreenReferenceSurface;
     mozilla::RefPtr<mozilla::gfx::DrawTarget> mScreenReferenceDrawTarget;
     nsTArray<uint32_t> mCJKPrefLangs;
     nsCOMPtr<nsIObserver> mSRGBOverrideObserver;
     nsCOMPtr<nsIObserver> mFontPrefsObserver;
--- a/gfx/thebes/gfxPlatformGtk.cpp
+++ b/gfx/thebes/gfxPlatformGtk.cpp
@@ -273,67 +273,61 @@ gfxPlatformGtk::SupportsOffMainThreadCom
 #if defined(MOZ_X11) && !defined(NIGHTLY_BUILD)
   return (PR_GetEnv("MOZ_USE_OMTC") != nullptr) ||
          (PR_GetEnv("MOZ_OMTC_ENABLED") != nullptr);
 #else
   return true;
 #endif
 }
 
-void
-gfxPlatformGtk::GetPlatformCMSOutputProfile(void *&mem, size_t &size)
+qcms_profile *
+gfxPlatformGtk::GetPlatformCMSOutputProfile()
 {
-    mem = nullptr;
-    size = 0;
-
 #ifdef MOZ_X11
     const char EDID1_ATOM_NAME[] = "XFree86_DDC_EDID1_RAWDATA";
     const char ICC_PROFILE_ATOM_NAME[] = "_ICC_PROFILE";
 
     Atom edidAtom, iccAtom;
     Display *dpy = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
     // In xpcshell tests, we never initialize X and hence don't have a Display.
     // In this case, there's no output colour management to be done, so we just
-    // return with nullptr.
-    if (!dpy)
-        return;
- 
+    // return nullptr.
+    if (!dpy) {
+        return nullptr;
+    }
+
     Window root = gdk_x11_get_default_root_xwindow();
 
     Atom retAtom;
     int retFormat;
     unsigned long retLength, retAfter;
     unsigned char *retProperty ;
 
     iccAtom = XInternAtom(dpy, ICC_PROFILE_ATOM_NAME, TRUE);
     if (iccAtom) {
         // read once to get size, once for the data
         if (Success == XGetWindowProperty(dpy, root, iccAtom,
                                           0, INT_MAX /* length */,
                                           False, AnyPropertyType,
                                           &retAtom, &retFormat, &retLength,
                                           &retAfter, &retProperty)) {
+            qcms_profile* profile = nullptr;
 
-            if (retLength > 0) {
-                void *buffer = malloc(retLength);
-                if (buffer) {
-                    memcpy(buffer, retProperty, retLength);
-                    mem = buffer;
-                    size = retLength;
-                }
-            }
+            if (retLength > 0)
+                profile = qcms_profile_from_memory(retProperty, retLength);
 
             XFree(retProperty);
-            if (size > 0) {
+
+            if (profile) {
 #ifdef DEBUG_tor
                 fprintf(stderr,
                         "ICM profile read from %s successfully\n",
                         ICC_PROFILE_ATOM_NAME);
 #endif
-                return;
+                return profile;
             }
         }
     }
 
     edidAtom = XInternAtom(dpy, EDID1_ATOM_NAME, TRUE);
     if (edidAtom) {
         if (Success == XGetWindowProperty(dpy, root, edidAtom, 0, 32,
                                           False, AnyPropertyType,
@@ -342,17 +336,17 @@ gfxPlatformGtk::GetPlatformCMSOutputProf
             double gamma;
             qcms_CIE_xyY whitePoint;
             qcms_CIE_xyYTRIPLE primaries;
 
             if (retLength != 128) {
 #ifdef DEBUG_tor
                 fprintf(stderr, "Short EDID data\n");
 #endif
-                return;
+                return nullptr;
             }
 
             // Format documented in "VESA E-EDID Implementation Guide"
 
             gamma = (100 + retProperty[0x17]) / 100.0;
             whitePoint.x = ((retProperty[0x21] << 2) |
                             (retProperty[0x1a] >> 2 & 3)) / 1024.0;
             whitePoint.y = ((retProperty[0x22] << 2) |
@@ -384,28 +378,33 @@ gfxPlatformGtk::GetPlatformCMSOutputProf
             fprintf(stderr, "EDID whitepoint: %f %f %f\n",
                     whitePoint.x, whitePoint.y, whitePoint.Y);
             fprintf(stderr, "EDID primaries: [%f %f %f] [%f %f %f] [%f %f %f]\n",
                     primaries.Red.x, primaries.Red.y, primaries.Red.Y,
                     primaries.Green.x, primaries.Green.y, primaries.Green.Y,
                     primaries.Blue.x, primaries.Blue.y, primaries.Blue.Y);
 #endif
 
-            qcms_data_create_rgb_with_gamma(whitePoint, primaries, gamma, &mem, &size);
+            qcms_profile* profile =
+                qcms_profile_create_rgb_with_gamma(whitePoint, primaries, gamma);
 
 #ifdef DEBUG_tor
-            if (size > 0) {
+            if (profile) {
                 fprintf(stderr,
                         "ICM profile read from %s successfully\n",
                         EDID1_ATOM_NAME);
             }
 #endif
+
+            return profile;
         }
     }
 #endif
+
+    return nullptr;
 }
 
 
 #if (MOZ_WIDGET_GTK == 2)
 void
 gfxPlatformGtk::SetGdkDrawable(cairo_surface_t *target,
                                GdkDrawable *drawable)
 {
--- a/gfx/thebes/gfxPlatformGtk.h
+++ b/gfx/thebes/gfxPlatformGtk.h
@@ -94,17 +94,17 @@ public:
     virtual gfxImageFormat GetOffscreenFormat();
 
     virtual int GetScreenDepth() const;
 
 protected:
     static gfxFontconfigUtils *sFontconfigUtils;
 
 private:
-    virtual void GetPlatformCMSOutputProfile(void *&mem, size_t &size);
+    virtual qcms_profile *GetPlatformCMSOutputProfile();
 
     virtual bool SupportsOffMainThreadCompositing();
 #ifdef MOZ_X11
     static bool sUseXRender;
 #endif
 };
 
 #endif /* GFX_PLATFORM_GTK_H */
--- a/gfx/thebes/gfxPlatformMac.cpp
+++ b/gfx/thebes/gfxPlatformMac.cpp
@@ -420,44 +420,33 @@ gfxPlatformMac::UseAcceleratedCanvas()
 }
 
 bool
 gfxPlatformMac::SupportsOffMainThreadCompositing()
 {
   return true;
 }
 
-void
-gfxPlatformMac::GetPlatformCMSOutputProfile(void* &mem, size_t &size)
+qcms_profile *
+gfxPlatformMac::GetPlatformCMSOutputProfile()
 {
-    mem = nullptr;
-    size = 0;
-
     CGColorSpaceRef cspace = ::CGDisplayCopyColorSpace(::CGMainDisplayID());
     if (!cspace) {
         cspace = ::CGColorSpaceCreateDeviceRGB();
     }
     if (!cspace) {
-        return;
+        return nullptr;
     }
 
     CFDataRef iccp = ::CGColorSpaceCopyICCProfile(cspace);
 
     ::CFRelease(cspace);
 
     if (!iccp) {
-        return;
+        return nullptr;
     }
 
-    // copy to external buffer
-    size = static_cast<size_t>(::CFDataGetLength(iccp));
-    if (size > 0) {
-        void *data = malloc(size);
-        if (data) {
-            memcpy(data, ::CFDataGetBytePtr(iccp), size);
-            mem = data;
-        } else {
-            size = 0;
-        }
-    }
+    qcms_profile* profile = qcms_profile_from_memory(::CFDataGetBytePtr(iccp), static_cast<size_t>(::CFDataGetLength(iccp)));
 
     ::CFRelease(iccp);
+
+    return profile;
 }
--- a/gfx/thebes/gfxPlatformMac.h
+++ b/gfx/thebes/gfxPlatformMac.h
@@ -77,17 +77,17 @@ public:
     uint32_t GetAntiAliasingThreshold() { return mFontAntiAliasingThreshold; }
 
     virtual already_AddRefed<gfxASurface>
     GetThebesSurfaceForDrawTarget(mozilla::gfx::DrawTarget *aTarget);
 
     virtual already_AddRefed<gfxASurface>
     CreateThebesSurfaceAliasForDrawTarget_hack(mozilla::gfx::DrawTarget *aTarget);
 private:
-    virtual void GetPlatformCMSOutputProfile(void* &mem, size_t &size);
+    virtual qcms_profile* GetPlatformCMSOutputProfile();
 
     virtual bool SupportsOffMainThreadCompositing();
 
     // read in the pref value for the lower threshold on font anti-aliasing
     static uint32_t ReadAntiAliasingThreshold();
 
     uint32_t mFontAntiAliasingThreshold;
 };
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -1046,52 +1046,49 @@ gfxWindowsPlatform::FindFontEntry(const 
     nsRefPtr<gfxFontFamily> ff = FindFontFamily(aName);
     if (!ff)
         return nullptr;
 
     bool aNeedsBold;
     return ff->FindFontForStyle(aFontStyle, aNeedsBold);
 }
 
-void
-gfxWindowsPlatform::GetPlatformCMSOutputProfile(void* &mem, size_t &size)
+qcms_profile*
+gfxWindowsPlatform::GetPlatformCMSOutputProfile()
 {
     WCHAR str[MAX_PATH];
     DWORD size = MAX_PATH;
     BOOL res;
 
-    mem = nullptr;
-    size = 0;
-
     HDC dc = GetDC(nullptr);
     if (!dc)
-        return;
+        return nullptr;
 
 #if _MSC_VER
     __try {
         res = GetICMProfileW(dc, &size, (LPWSTR)&str);
     } __except(GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION) {
         res = FALSE;
     }
 #else
     res = GetICMProfileW(dc, &size, (LPWSTR)&str);
 #endif
 
     ReleaseDC(nullptr, dc);
     if (!res)
-        return;
+        return nullptr;
 
-    qcms_data_from_unicode_path(str, &mem, &size);
-
+    qcms_profile* profile = qcms_profile_from_unicode_path(str);
 #ifdef DEBUG_tor
-    if (size > 0)
+    if (profile)
         fprintf(stderr,
                 "ICM profile read from %s successfully\n",
                 NS_ConvertUTF16toUTF8(str).get());
 #endif
+    return profile;
 }
 
 bool
 gfxWindowsPlatform::GetPrefFontEntries(const nsCString& aKey, nsTArray<nsRefPtr<gfxFontEntry> > *array)
 {
     return mPrefFonts.Get(aKey, array);
 }
 
--- a/gfx/thebes/gfxWindowsPlatform.h
+++ b/gfx/thebes/gfxWindowsPlatform.h
@@ -289,15 +289,15 @@ private:
 #ifdef CAIRO_HAS_D2D_SURFACE
     cairo_device_t *mD2DDevice;
 #endif
     mozilla::RefPtr<IDXGIAdapter1> mAdapter;
     nsRefPtr<mozilla::layers::DeviceManagerD3D9> mDeviceManager;
     mozilla::RefPtr<ID3D11Device> mD3D11Device;
     bool mD3D11DeviceInitialized;
 
-    virtual void GetPlatformCMSOutputProfile(void* &mem, size_t &size);
+    virtual qcms_profile* GetPlatformCMSOutputProfile();
 
     // TODO: unify this with mPrefFonts (NB: holds families, not fonts) in gfxPlatformFontList
     nsDataHashtable<nsCStringHashKey, nsTArray<nsRefPtr<gfxFontEntry> > > mPrefFonts;
 };
 
 #endif /* GFX_WINDOWS_PLATFORM_H */