Bug 1551084 - Part 4. Add support for BGRA to QCMS. r=miko
☠☠ backed out by 1e50992f4133 ☠ ☠
authorAndrew Osmond <aosmond@mozilla.com>
Thu, 09 May 2019 16:45:51 -0400
changeset 475783 2a5ae3eb40ce2eb31f3708a8c82690fa8858ce14
parent 475782 99874bf8941910abd3c10f0ba5a762e7f1dc60f5
child 475784 af04f8907fab2f091180fe0c762dc54fd9091c5c
push id86473
push userrgurzau@mozilla.com
push dateMon, 27 May 2019 21:57:53 +0000
treeherderautoland@92582acb077d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmiko
bugs1551084
milestone69.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1551084 - Part 4. Add support for BGRA to QCMS. r=miko Differential Revision: https://phabricator.services.mozilla.com/D30821
gfx/qcms/qcms.h
gfx/qcms/qcmsint.h
gfx/qcms/transform-altivec.cpp
gfx/qcms/transform-sse1.cpp
gfx/qcms/transform-sse2.cpp
gfx/qcms/transform.cpp
gfx/thebes/gfxPlatform.cpp
gfx/thebes/gfxPlatform.h
--- a/gfx/qcms/qcms.h
+++ b/gfx/qcms/qcms.h
@@ -104,16 +104,17 @@ typedef enum {
 	 * unacceptable performance overhead, so we go with perceptual. */
 	QCMS_INTENT_DEFAULT = QCMS_INTENT_PERCEPTUAL,
 } qcms_intent;
 
 //XXX: I don't really like the _DATA_ prefix
 typedef enum {
 	QCMS_DATA_RGB_8,
 	QCMS_DATA_RGBA_8,
+	QCMS_DATA_BGRA_8,
 	QCMS_DATA_GRAY_8,
 	QCMS_DATA_GRAYA_8
 } qcms_data_type;
 
 /* the names for the following two types are sort of ugly */
 typedef struct
 {
 	double x;
--- a/gfx/qcms/qcmsint.h
+++ b/gfx/qcms/qcmsint.h
@@ -267,33 +267,45 @@ bool get_rgb_colorants(struct matrix *co
 void qcms_transform_data_rgb_out_lut_sse2(const qcms_transform *transform,
                                           const unsigned char *src,
                                           unsigned char *dest,
                                           size_t length);
 void qcms_transform_data_rgba_out_lut_sse2(const qcms_transform *transform,
                                           const unsigned char *src,
                                           unsigned char *dest,
                                           size_t length);
+void qcms_transform_data_bgra_out_lut_sse2(const qcms_transform *transform,
+                                          const unsigned char *src,
+                                          unsigned char *dest,
+                                          size_t length);
 void qcms_transform_data_rgb_out_lut_sse1(const qcms_transform *transform,
                                           const unsigned char *src,
                                           unsigned char *dest,
                                           size_t length);
 void qcms_transform_data_rgba_out_lut_sse1(const qcms_transform *transform,
                                           const unsigned char *src,
                                           unsigned char *dest,
                                           size_t length);
+void qcms_transform_data_bgra_out_lut_sse1(const qcms_transform *transform,
+                                          const unsigned char *src,
+                                          unsigned char *dest,
+                                          size_t length);
 
 void qcms_transform_data_rgb_out_lut_altivec(const qcms_transform *transform,
                                              const unsigned char *src,
                                              unsigned char *dest,
                                              size_t length);
 void qcms_transform_data_rgba_out_lut_altivec(const qcms_transform *transform,
                                               const unsigned char *src,
                                               unsigned char *dest,
                                               size_t length);
+void qcms_transform_data_bgra_out_lut_altivec(const qcms_transform *transform,
+                                              const unsigned char *src,
+                                              unsigned char *dest,
+                                              size_t length);
 
 extern bool qcms_supports_iccv4;
 
 #ifdef _MSC_VER
 
 long __cdecl _InterlockedIncrement(long volatile *);
 long __cdecl _InterlockedDecrement(long volatile *);
 #pragma intrinsic(_InterlockedIncrement)
--- a/gfx/qcms/transform-altivec.cpp
+++ b/gfx/qcms/transform-altivec.cpp
@@ -174,8 +174,16 @@ void qcms_transform_data_rgb_out_lut_alt
 
 void qcms_transform_data_rgba_out_lut_altivec(const qcms_transform *transform,
                                               const unsigned char *src,
                                               unsigned char *dest,
                                               size_t length)
 {
     qcms_transform_data_template_lut_altivec<RGBA_R_INDEX, RGBA_G_INDEX, RGBA_B_INDEX, RGBA_A_INDEX>(transform, src, dest, length);
 }
+
+void qcms_transform_data_bgra_out_lut_altivec(const qcms_transform *transform,
+                                              const unsigned char *src,
+                                              unsigned char *dest,
+                                              size_t length)
+{
+    qcms_transform_data_template_lut_altivec<BGRA_R_INDEX, BGRA_G_INDEX, BGRA_B_INDEX, BGRA_A_INDEX>(transform, src, dest, length);
+}
--- a/gfx/qcms/transform-sse1.cpp
+++ b/gfx/qcms/transform-sse1.cpp
@@ -153,8 +153,16 @@ void qcms_transform_data_rgb_out_lut_sse
 
 void qcms_transform_data_rgba_out_lut_sse1(const qcms_transform *transform,
                                            const unsigned char *src,
                                            unsigned char *dest,
                                            size_t length)
 {
     qcms_transform_data_template_lut_sse1<RGBA_R_INDEX, RGBA_G_INDEX, RGBA_B_INDEX, RGBA_A_INDEX>(transform, src, dest, length);
 }
+
+void qcms_transform_data_bgra_out_lut_sse1(const qcms_transform *transform,
+                                           const unsigned char *src,
+                                           unsigned char *dest,
+                                           size_t length)
+{
+    qcms_transform_data_template_lut_sse1<BGRA_R_INDEX, BGRA_G_INDEX, BGRA_B_INDEX, BGRA_A_INDEX>(transform, src, dest, length);
+}
--- a/gfx/qcms/transform-sse2.cpp
+++ b/gfx/qcms/transform-sse2.cpp
@@ -147,8 +147,16 @@ void qcms_transform_data_rgb_out_lut_sse
 
 void qcms_transform_data_rgba_out_lut_sse2(const qcms_transform *transform,
                                            const unsigned char *src,
                                            unsigned char *dest,
                                            size_t length)
 {
   qcms_transform_data_template_lut_sse2<RGBA_R_INDEX, RGBA_G_INDEX, RGBA_B_INDEX, RGBA_A_INDEX>(transform, src, dest, length);
 }
+
+void qcms_transform_data_bgra_out_lut_sse2(const qcms_transform *transform,
+                                           const unsigned char *src,
+                                           unsigned char *dest,
+                                           size_t length)
+{
+  qcms_transform_data_template_lut_sse2<BGRA_R_INDEX, BGRA_G_INDEX, BGRA_B_INDEX, BGRA_A_INDEX>(transform, src, dest, length);
+}
--- a/gfx/qcms/transform.cpp
+++ b/gfx/qcms/transform.cpp
@@ -389,21 +389,26 @@ static void qcms_transform_data_gray_tem
 	}
 }
 
 static void qcms_transform_data_gray_out_lut(const qcms_transform *transform, const unsigned char *src, unsigned char *dest, size_t length)
 {
 	qcms_transform_data_gray_template_lut<RGBA_R_INDEX, RGBA_G_INDEX, RGBA_B_INDEX>(transform, src, dest, length);
 }
 
-static void qcms_transform_data_graya_out_lut(const qcms_transform *transform, const unsigned char *src, unsigned char *dest, size_t length)
+static void qcms_transform_data_graya_rgba_out_lut(const qcms_transform *transform, const unsigned char *src, unsigned char *dest, size_t length)
 {
 	qcms_transform_data_gray_template_lut<RGBA_R_INDEX, RGBA_G_INDEX, RGBA_B_INDEX, RGBA_A_INDEX>(transform, src, dest, length);
 }
 
+static void qcms_transform_data_graya_bgra_out_lut(const qcms_transform *transform, const unsigned char *src, unsigned char *dest, size_t length)
+{
+	qcms_transform_data_gray_template_lut<BGRA_R_INDEX, BGRA_G_INDEX, BGRA_B_INDEX, BGRA_A_INDEX>(transform, src, dest, length);
+}
+
 template <size_t kRIndex, size_t kGIndex, size_t kBIndex, size_t kAIndex = NO_A_INDEX>
 static void qcms_transform_data_gray_template_precache(const qcms_transform *transform, const unsigned char *src, unsigned char *dest, size_t length)
 {
 	const unsigned int components = A_INDEX_COMPONENTS(kAIndex);
 	unsigned int i;
 	for (i = 0; i < length; i++) {
 		unsigned char device = *src++;
 		unsigned char alpha;
@@ -427,21 +432,26 @@ static void qcms_transform_data_gray_tem
 	}
 }
 
 static void qcms_transform_data_gray_out_precache(const qcms_transform *transform, const unsigned char *src, unsigned char *dest, size_t length)
 {
 	qcms_transform_data_gray_template_precache<RGBA_R_INDEX, RGBA_G_INDEX, RGBA_B_INDEX>(transform, src, dest, length);
 }
 
-static void qcms_transform_data_graya_out_precache(const qcms_transform *transform, const unsigned char *src, unsigned char *dest, size_t length)
+static void qcms_transform_data_graya_rgba_out_precache(const qcms_transform *transform, const unsigned char *src, unsigned char *dest, size_t length)
 {
 	qcms_transform_data_gray_template_precache<RGBA_R_INDEX, RGBA_G_INDEX, RGBA_B_INDEX, RGBA_A_INDEX>(transform, src, dest, length);
 }
 
+static void qcms_transform_data_graya_bgra_out_precache(const qcms_transform *transform, const unsigned char *src, unsigned char *dest, size_t length)
+{
+	qcms_transform_data_gray_template_precache<BGRA_R_INDEX, BGRA_G_INDEX, BGRA_B_INDEX, BGRA_A_INDEX>(transform, src, dest, length);
+}
+
 template <size_t kRIndex, size_t kGIndex, size_t kBIndex, size_t kAIndex = NO_A_INDEX>
 static void qcms_transform_data_template_lut_precache(const qcms_transform *transform, const unsigned char *src, unsigned char *dest, size_t length)
 {
 	const unsigned int components = A_INDEX_COMPONENTS(kAIndex);
 	unsigned int i;
 	const float (*mat)[4] = transform->matrix;
 	for (i = 0; i < length; i++) {
 		unsigned char device_r = src[kRIndex];
@@ -486,16 +496,21 @@ static void qcms_transform_data_rgb_out_
 	qcms_transform_data_template_lut_precache<RGBA_R_INDEX, RGBA_G_INDEX, RGBA_B_INDEX>(transform, src, dest, length);
 }
 
 static void qcms_transform_data_rgba_out_lut_precache(const qcms_transform *transform, const unsigned char *src, unsigned char *dest, size_t length)
 {
 	qcms_transform_data_template_lut_precache<RGBA_R_INDEX, RGBA_G_INDEX, RGBA_B_INDEX, RGBA_A_INDEX>(transform, src, dest, length);
 }
 
+static void qcms_transform_data_bgra_out_lut_precache(const qcms_transform *transform, const unsigned char *src, unsigned char *dest, size_t length)
+{
+	qcms_transform_data_template_lut_precache<BGRA_R_INDEX, BGRA_G_INDEX, BGRA_B_INDEX, BGRA_A_INDEX>(transform, src, dest, length);
+}
+
 // Not used
 /* 
 static void qcms_transform_data_clut(const qcms_transform *transform, const unsigned char *src, unsigned char *dest, size_t length) {
 	unsigned int i;
 	int xy_len = 1;
 	int x_len = transform->grid_size;
 	int len = x_len * x_len;
 	const float* r_table = transform->r_clut;
@@ -736,16 +751,21 @@ static void qcms_transform_data_rgb_out_
 	qcms_transform_data_template_lut<RGBA_R_INDEX, RGBA_G_INDEX, RGBA_B_INDEX>(transform, src, dest, length);
 }
 
 static void qcms_transform_data_rgba_out_lut(const qcms_transform *transform, const unsigned char *src, unsigned char *dest, size_t length)
 {
 	qcms_transform_data_template_lut<RGBA_R_INDEX, RGBA_G_INDEX, RGBA_B_INDEX, RGBA_A_INDEX>(transform, src, dest, length);
 }
 
+static void qcms_transform_data_bgra_out_lut(const qcms_transform *transform, const unsigned char *src, unsigned char *dest, size_t length)
+{
+	qcms_transform_data_template_lut<BGRA_R_INDEX, BGRA_G_INDEX, BGRA_B_INDEX, BGRA_A_INDEX>(transform, src, dest, length);
+}
+
 #if 0
 static void qcms_transform_data_rgb_out_linear(const qcms_transform *transform, const unsigned char *src, unsigned char *dest, size_t length)
 {
 	int i;
 	const float (*mat)[4] = transform->matrix;
 	for (i = 0; i < length; i++) {
 		unsigned char device_r = *src++;
 		unsigned char device_g = *src++;
@@ -1083,29 +1103,40 @@ qcms_transform* qcms_transform_precacheL
 
 #define NO_MEM_TRANSFORM NULL
 
 qcms_transform* qcms_transform_create(
 		qcms_profile *in, qcms_data_type in_type,
 		qcms_profile *out, qcms_data_type out_type,
 		qcms_intent intent)
 {
-	bool precache = false;
+	// Ensure the requested input and output types make sense.
+	bool match = false;
+	if (in_type == QCMS_DATA_RGB_8) {
+		match = out_type == QCMS_DATA_RGB_8;
+	} else if (in_type == QCMS_DATA_RGBA_8) {
+		match = out_type == QCMS_DATA_RGBA_8;
+	} else if (in_type == QCMS_DATA_BGRA_8) {
+		match = out_type == QCMS_DATA_BGRA_8;
+	} else if (in_type == QCMS_DATA_GRAY_8) {
+		match = out_type == QCMS_DATA_RGB_8;
+	} else if (in_type == QCMS_DATA_GRAYA_8) {
+		match = out_type == QCMS_DATA_RGBA_8 || out_type == QCMS_DATA_BGRA_8;
+	}
+	if (!match) {
+		assert(0 && "input/output type");
+		return NULL;
+	}
 
         qcms_transform *transform = transform_alloc();
         if (!transform) {
 		return NULL;
 	}
-	if (out_type != QCMS_DATA_RGB_8 &&
-                out_type != QCMS_DATA_RGBA_8) {
-            assert(0 && "output type");
-	    qcms_transform_release(transform);
-            return NULL;
-        }
 
+	bool precache = false;
 	if (out->output_table_r &&
 			out->output_table_g &&
 			out->output_table_b) {
 		precache = true;
 	}
 
 	// This precache assumes RGB_SIGNATURE (fails on GRAY_SIGNATURE, for instance)
 	if (qcms_supports_iccv4 &&
@@ -1141,62 +1172,70 @@ qcms_transform* qcms_transform_create(
 		if (!transform->output_gamma_lut_r || !transform->output_gamma_lut_g || !transform->output_gamma_lut_b) {
 			qcms_transform_release(transform);
 			return NO_MEM_TRANSFORM;
 		}
 	}
 
         if (in->color_space == RGB_SIGNATURE) {
 		struct matrix in_matrix, out_matrix, result;
-
-		if (in_type != QCMS_DATA_RGB_8 &&
-                    in_type != QCMS_DATA_RGBA_8){
-                	assert(0 && "input type");
-			qcms_transform_release(transform);
-                	return NULL;
-            	}
 		if (precache) {
 #ifdef X86
 		    if (sse_version_available() >= 2) {
-			    if (in_type == QCMS_DATA_RGB_8)
+			    if (in_type == QCMS_DATA_RGB_8) {
 				    transform->transform_fn = qcms_transform_data_rgb_out_lut_sse2;
-			    else
+			    } else if (in_type == QCMS_DATA_RGBA_8) {
 				    transform->transform_fn = qcms_transform_data_rgba_out_lut_sse2;
+			    } else if (in_type == QCMS_DATA_BGRA_8) {
+				    transform->transform_fn = qcms_transform_data_bgra_out_lut_sse2;
+			    }
 
 #if !(defined(_MSC_VER) && defined(_M_AMD64))
                     /* Microsoft Compiler for x64 doesn't support MMX.
                      * SSE code uses MMX so that we disable on x64 */
 		    } else
 		    if (sse_version_available() >= 1) {
-			    if (in_type == QCMS_DATA_RGB_8)
+			    if (in_type == QCMS_DATA_RGB_8) {
 				    transform->transform_fn = qcms_transform_data_rgb_out_lut_sse1;
-			    else
+			    } else if (in_type == QCMS_DATA_RGBA_8) {
 				    transform->transform_fn = qcms_transform_data_rgba_out_lut_sse1;
+			    } else if (in_type == QCMS_DATA_BGRA_8) {
+				    transform->transform_fn = qcms_transform_data_bgra_out_lut_sse1;
+			    }
 #endif
 		    } else
 #endif
 #if (defined(__POWERPC__) || defined(__powerpc__) && !defined(__NO_FPRS__))
 		    if (have_altivec()) {
-			    if (in_type == QCMS_DATA_RGB_8)
+			    if (in_type == QCMS_DATA_RGB_8) {
 				    transform->transform_fn = qcms_transform_data_rgb_out_lut_altivec;
-			    else
+			    } else if (in_type == QCMS_DATA_RGBA_8) {
 				    transform->transform_fn = qcms_transform_data_rgba_out_lut_altivec;
+			    } else if (in_type == QCMS_DATA_BGRA_8) {
+				    transform->transform_fn = qcms_transform_data_bgra_out_lut_altivec;
+			    }
 		    } else
 #endif
 			{
-				if (in_type == QCMS_DATA_RGB_8)
+				if (in_type == QCMS_DATA_RGB_8) {
 					transform->transform_fn = qcms_transform_data_rgb_out_lut_precache;
-				else
+				} else if (in_type == QCMS_DATA_RGBA_8) {
 					transform->transform_fn = qcms_transform_data_rgba_out_lut_precache;
+				} else if (in_type == QCMS_DATA_BGRA_8) {
+					transform->transform_fn = qcms_transform_data_bgra_out_lut_precache;
+				}
 			}
 		} else {
-			if (in_type == QCMS_DATA_RGB_8)
+			if (in_type == QCMS_DATA_RGB_8) {
 				transform->transform_fn = qcms_transform_data_rgb_out_lut;
-			else
+			} else if (in_type == QCMS_DATA_RGBA_8) {
 				transform->transform_fn = qcms_transform_data_rgba_out_lut;
+			} else if (in_type == QCMS_DATA_BGRA_8) {
+				transform->transform_fn = qcms_transform_data_bgra_out_lut;
+			}
 		}
 
 		//XXX: avoid duplicating tables if we can
 		transform->input_gamma_table_r = build_input_gamma_table(in->redTRC);
 		transform->input_gamma_table_g = build_input_gamma_table(in->greenTRC);
 		transform->input_gamma_table_b = build_input_gamma_table(in->blueTRC);
 		if (!transform->input_gamma_table_r || !transform->input_gamma_table_g || !transform->input_gamma_table_b) {
 			qcms_transform_release(transform);
@@ -1232,47 +1271,45 @@ qcms_transform* qcms_transform_create(
 		transform->matrix[0][1] = result.m[1][0];
 		transform->matrix[1][1] = result.m[1][1];
 		transform->matrix[2][1] = result.m[1][2];
 		transform->matrix[0][2] = result.m[2][0];
 		transform->matrix[1][2] = result.m[2][1];
 		transform->matrix[2][2] = result.m[2][2];
 
 	} else if (in->color_space == GRAY_SIGNATURE) {
-		if (in_type != QCMS_DATA_GRAY_8 &&
-				in_type != QCMS_DATA_GRAYA_8){
-			assert(0 && "input type");
-			qcms_transform_release(transform);
-			return NULL;
-		}
-
 		transform->input_gamma_table_gray = build_input_gamma_table(in->grayTRC);
 		if (!transform->input_gamma_table_gray) {
 			qcms_transform_release(transform);
 			return NO_MEM_TRANSFORM;
 		}
 
 		if (precache) {
 			if (in_type == QCMS_DATA_GRAY_8) {
 				transform->transform_fn = qcms_transform_data_gray_out_precache;
-			} else {
-				transform->transform_fn = qcms_transform_data_graya_out_precache;
+			} else if (out_type == QCMS_DATA_RGBA_8) {
+				transform->transform_fn = qcms_transform_data_graya_rgba_out_precache;
+			} else if (out_type == QCMS_DATA_BGRA_8) {
+				transform->transform_fn = qcms_transform_data_graya_bgra_out_precache;
 			}
 		} else {
 			if (in_type == QCMS_DATA_GRAY_8) {
 				transform->transform_fn = qcms_transform_data_gray_out_lut;
-			} else {
-				transform->transform_fn = qcms_transform_data_graya_out_lut;
+			} else if (out_type == QCMS_DATA_RGBA_8) {
+				transform->transform_fn = qcms_transform_data_graya_rgba_out_lut;
+			} else if (out_type == QCMS_DATA_BGRA_8) {
+				transform->transform_fn = qcms_transform_data_graya_bgra_out_lut;
 			}
 		}
 	} else {
 		assert(0 && "unexpected colorspace");
 		qcms_transform_release(transform);
 		return NULL;
 	}
+	assert(transform->transform_fn);
 	return transform;
 }
 
 #if defined(__GNUC__) && defined(__i386__)
 /* we need this to avoid crashes when gcc assumes the stack is 128bit aligned */
 __attribute__((__force_align_arg_pointer__))
 #endif
 void qcms_transform_data(qcms_transform *transform, const void *src, void *dest, size_t length)
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -161,16 +161,17 @@ static Mutex* gGfxPlatformPrefsLock = nu
 // These two may point to the same profile
 static qcms_profile* gCMSOutputProfile = nullptr;
 static qcms_profile* gCMSsRGBProfile = nullptr;
 
 static bool gCMSRGBTransformFailed = false;
 static qcms_transform* gCMSRGBTransform = nullptr;
 static qcms_transform* gCMSInverseRGBTransform = nullptr;
 static qcms_transform* gCMSRGBATransform = nullptr;
+static qcms_transform* gCMSBGRATransform = nullptr;
 
 static bool gCMSInitialized = false;
 static eCMSMode gCMSMode = eCMSMode_Off;
 
 static void ShutdownCMS();
 
 #include "mozilla/gfx/2D.h"
 #include "mozilla/gfx/SourceSurfaceCairo.h"
@@ -2143,30 +2144,50 @@ qcms_transform* gfxPlatform::GetCMSRGBAT
     gCMSRGBATransform =
         qcms_transform_create(inProfile, QCMS_DATA_RGBA_8, outProfile,
                               QCMS_DATA_RGBA_8, QCMS_INTENT_PERCEPTUAL);
   }
 
   return gCMSRGBATransform;
 }
 
+qcms_transform* gfxPlatform::GetCMSBGRATransform() {
+  if (!gCMSBGRATransform) {
+    qcms_profile *inProfile, *outProfile;
+    outProfile = GetCMSOutputProfile();
+    inProfile = GetCMSsRGBProfile();
+
+    if (!inProfile || !outProfile) return nullptr;
+
+    gCMSBGRATransform =
+        qcms_transform_create(inProfile, QCMS_DATA_BGRA_8, outProfile,
+                              QCMS_DATA_BGRA_8, QCMS_INTENT_PERCEPTUAL);
+  }
+
+  return gCMSBGRATransform;
+}
+
 /* Shuts down various transforms and profiles for CMS. */
 static void ShutdownCMS() {
   if (gCMSRGBTransform) {
     qcms_transform_release(gCMSRGBTransform);
     gCMSRGBTransform = nullptr;
   }
   if (gCMSInverseRGBTransform) {
     qcms_transform_release(gCMSInverseRGBTransform);
     gCMSInverseRGBTransform = nullptr;
   }
   if (gCMSRGBATransform) {
     qcms_transform_release(gCMSRGBATransform);
     gCMSRGBATransform = nullptr;
   }
+  if (gCMSBGRATransform) {
+    qcms_transform_release(gCMSBGRATransform);
+    gCMSBGRATransform = nullptr;
+  }
   if (gCMSOutputProfile) {
     qcms_profile_release(gCMSOutputProfile);
 
     // handle the aliased case
     if (gCMSsRGBProfile == gCMSOutputProfile) gCMSsRGBProfile = nullptr;
     gCMSOutputProfile = nullptr;
   }
   if (gCMSsRGBProfile) {
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -538,16 +538,21 @@ class gfxPlatform : public mozilla::laye
    */
   static qcms_transform* GetCMSInverseRGBTransform();
 
   /**
    * Return sRGBA -> output device transform.
    */
   static qcms_transform* GetCMSRGBATransform();
 
+  /**
+   * Return sRGBA -> output device transform.
+   */
+  static qcms_transform* GetCMSBGRATransform();
+
   virtual void FontsPrefsChanged(const char* aPref);
 
   int32_t GetBidiNumeralOption();
 
   /**
    * This is a bit ugly, but useful... force all presContexts to reflow,
    * by toggling a preference that they observe. This is used when
    * something about platform settings changes that might have an effect