From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Birunthan Mohanathas <birunthan@mohanathas.com>
Date: Fri, 30 Nov 2018 12:44:12 +0200
Subject: disable_color_correct_rendering.patch

This adds a --disable-color-correct-rendering switch. In Electron 2.0,
`--disable-features=ColorCorrectRendering` could be
used to make the app use the display color space (e.g. P3 on Macs)
instead of color correcting to sRGB. Because color correct rendering is
always enabled on Chromium 62 and later and because
`--force-color-profile` has no effect on macOS, apps that need e.g. P3
colors are currently stuck on Electron 2.0.

This restores the functionality removed in
https://chromium-review.googlesource.com/698347 in the form of the
`--disable-color-correct-rendering` switch.

This can be removed once web content (including WebGL) learn how
to deal with color spaces. That is being tracked at
https://crbug.com/634542 and https://crbug.com/711107.

diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index bb7ff971823db702991a3167b5b0ac1b3dd4a6c9..e5afad68300bdd6ac109b3c9b94d3c200d164456 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -1762,6 +1762,10 @@ void LayerTreeHostImpl::SetIsLikelyToRequireADraw(
 
 gfx::ColorSpace LayerTreeHostImpl::GetRasterColorSpace(
     gfx::ContentColorUsage content_color_usage) const {
+  if (!settings_.enable_color_correct_rendering) {
+    return {};
+  }
+
   constexpr gfx::ColorSpace srgb = gfx::ColorSpace::CreateSRGB();
 
   // If we are likely to software composite the resource, we use sRGB because
diff --git a/cc/trees/layer_tree_settings.h b/cc/trees/layer_tree_settings.h
index e5a58655788be3bd1c86e238e34bbadf8012bc48..2a2de85e89a8a0f803b7c987620a259b26281d8d 100644
--- a/cc/trees/layer_tree_settings.h
+++ b/cc/trees/layer_tree_settings.h
@@ -99,6 +99,8 @@ class CC_EXPORT LayerTreeSettings {
   bool use_rgba_4444 = false;
   bool unpremultiply_and_dither_low_bit_depth_tiles = false;
 
+  bool enable_color_correct_rendering = true;
+
   // If set to true, the compositor may selectively defer image decodes to the
   // Image Decode Service and raster tiles without images until the decode is
   // ready.
diff --git a/components/viz/common/display/renderer_settings.h b/components/viz/common/display/renderer_settings.h
index 2e32385af86c6156c4197393248d70c470cdd4b5..350f56238e1c01cc6073555933f57df8cafca050 100644
--- a/components/viz/common/display/renderer_settings.h
+++ b/components/viz/common/display/renderer_settings.h
@@ -23,6 +23,7 @@ class VIZ_COMMON_EXPORT RendererSettings {
   RendererSettings(const RendererSettings& other);
   ~RendererSettings();
 
+  bool enable_color_correct_rendering = true;
   bool allow_antialiasing = true;
   bool force_antialiasing = false;
   bool force_blending_with_shaders = false;
diff --git a/components/viz/host/renderer_settings_creation.cc b/components/viz/host/renderer_settings_creation.cc
index 5575c90cf05ec43bc787711f1d44b8dd58ead99c..a544d836159522751c1262370d8c156220662c0f 100644
--- a/components/viz/host/renderer_settings_creation.cc
+++ b/components/viz/host/renderer_settings_creation.cc
@@ -16,6 +16,7 @@
 #include "components/viz/common/features.h"
 #include "components/viz/common/switches.h"
 #include "ui/base/ui_base_switches.h"
+#include "ui/gfx/switches.h"
 
 #if defined(OS_APPLE)
 #include "ui/base/cocoa/remote_layer_api.h"
@@ -53,6 +54,8 @@ bool GetSwitchValueAsInt(const base::CommandLine* command_line,
 RendererSettings CreateRendererSettings() {
   RendererSettings renderer_settings;
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+  renderer_settings.enable_color_correct_rendering =
+      !command_line->HasSwitch(switches::kDisableColorCorrectRendering);
   renderer_settings.partial_swap_enabled =
       !command_line->HasSwitch(switches::kUIDisablePartialSwap);
 #if defined(OS_APPLE)
diff --git a/components/viz/service/display/gl_renderer.cc b/components/viz/service/display/gl_renderer.cc
index e5179c0e4971bc593860b1e5b606fec651e6756b..1f3343600c6203c84586f6e4dcdc5976d9cf44f3 100644
--- a/components/viz/service/display/gl_renderer.cc
+++ b/components/viz/service/display/gl_renderer.cc
@@ -86,6 +86,9 @@
 
 using gpu::gles2::GLES2Interface;
 
+#define PATCH_CS(color_space) \
+  (settings_->enable_color_correct_rendering ? color_space : gfx::ColorSpace())
+
 namespace viz {
 namespace {
 
@@ -639,8 +642,9 @@ void GLRenderer::DoDrawQuad(const DrawQuad* quad,
 void GLRenderer::DrawDebugBorderQuad(const DebugBorderDrawQuad* quad) {
   SetBlendEnabled(quad->ShouldDrawWithBlending());
 
-  SetUseProgram(ProgramKey::DebugBorder(), gfx::ColorSpace::CreateSRGB(),
-                CurrentRenderPassColorSpace());
+  SetUseProgram(ProgramKey::DebugBorder(),
+                PATCH_CS(gfx::ColorSpace::CreateSRGB()),
+                PATCH_CS(CurrentRenderPassColorSpace()));
 
   // Use the full quad_rect for debug quads to not move the edges based on
   // partial swaps.
@@ -1620,7 +1624,8 @@ void GLRenderer::ChooseRPDQProgram(DrawRenderPassDrawQuadParams* params,
           params->use_color_matrix, tint_gl_composited_content_,
           params->apply_shader_based_rounded_corner &&
               ShouldApplyRoundedCorner(params->quad)),
-      params->contents_and_bypass_color_space, target_color_space);
+          PATCH_CS(params->contents_and_bypass_color_space),
+          PATCH_CS(target_color_space));
 }
 
 void GLRenderer::UpdateRPDQUniforms(DrawRenderPassDrawQuadParams* params) {
@@ -2094,15 +2099,16 @@ void GLRenderer::DrawSolidColorQuad(const SolidColorDrawQuad* quad,
   SetUseProgram(ProgramKey::SolidColor(use_aa ? USE_AA : NO_AA,
                                        tint_gl_composited_content_,
                                        ShouldApplyRoundedCorner(quad)),
-                CurrentRenderPassColorSpace(), CurrentRenderPassColorSpace());
+                PATCH_CS(CurrentRenderPassColorSpace()),
+                PATCH_CS(CurrentRenderPassColorSpace()));
 
   gfx::ColorSpace quad_color_space = gfx::ColorSpace::CreateSRGB();
   SkColor4f color_f = SkColor4f::FromColor(color);
 
   // Apply color transform if the color space or source and target do not match.
-  if (quad_color_space != CurrentRenderPassColorSpace()) {
+  if (PATCH_CS(quad_color_space) != PATCH_CS(CurrentRenderPassColorSpace())) {
     const gfx::ColorTransform* color_transform =
-        GetColorTransform(quad_color_space, CurrentRenderPassColorSpace());
+        GetColorTransform(PATCH_CS(quad_color_space), PATCH_CS(CurrentRenderPassColorSpace()));
     gfx::ColorTransform::TriStim col(color_f.fR, color_f.fG, color_f.fB);
     color_transform->Transform(&col, 1);
     color_f.fR = col.x();
@@ -2277,7 +2283,8 @@ void GLRenderer::DrawContentQuadAA(const ContentDrawQuadBase* quad,
                                               : NON_PREMULTIPLIED_ALPHA,
                        false, false, tint_gl_composited_content_,
                        ShouldApplyRoundedCorner(quad)),
-      quad_resource_lock.color_space(), CurrentRenderPassColorSpace());
+      PATCH_CS(quad_resource_lock.color_space()),
+      PATCH_CS(CurrentRenderPassColorSpace()));
 
   if (current_program_->tint_color_matrix_location() != -1) {
     auto matrix = cc::DebugColors::TintCompositedContentColorTransformMatrix();
@@ -2376,7 +2383,8 @@ void GLRenderer::DrawContentQuadNoAA(const ContentDrawQuadBase* quad,
                        !quad->ShouldDrawWithBlending(), has_tex_clamp_rect,
                        tint_gl_composited_content_,
                        ShouldApplyRoundedCorner(quad)),
-      quad_resource_lock.color_space(), CurrentRenderPassColorSpace());
+      PATCH_CS(quad_resource_lock.color_space()),
+      PATCH_CS(CurrentRenderPassColorSpace()));
 
   if (current_program_->tint_color_matrix_location() != -1) {
     auto matrix = cc::DebugColors::TintCompositedContentColorTransformMatrix();
@@ -2486,7 +2494,8 @@ void GLRenderer::DrawYUVVideoQuad(const YUVVideoDrawQuad* quad,
   // The source color space should never be RGB.
   DCHECK_NE(src_color_space, src_color_space.GetAsFullRangeRGB());
 
-  gfx::ColorSpace dst_color_space = CurrentRenderPassColorSpace();
+  gfx::ColorSpace dst_color_space =
+      PATCH_CS(CurrentRenderPassColorSpace());
 
 #if defined(OS_WIN)
   // Force sRGB output on Windows for overlay candidate video quads to match
@@ -2661,7 +2670,8 @@ void GLRenderer::DrawStreamVideoQuad(const StreamVideoDrawQuad* quad,
 
   SetUseProgram(ProgramKey::VideoStream(tex_coord_precision,
                                         ShouldApplyRoundedCorner(quad)),
-                lock.color_space(), CurrentRenderPassColorSpace());
+                PATCH_CS(lock.color_space()),
+                PATCH_CS(CurrentRenderPassColorSpace()));
 
   DCHECK_EQ(GL_TEXTURE0, GetActiveTextureUnit(gl_));
   gl_->BindTexture(GL_TEXTURE_EXTERNAL_OES, lock.texture_id());
@@ -2728,8 +2738,8 @@ void GLRenderer::FlushTextureQuadCache(BoundGeometry flush_binding) {
       draw_cache_.nearest_neighbor ? GL_NEAREST : GL_LINEAR);
 
   // Bind the program to the GL state.
-  SetUseProgram(draw_cache_.program_key, locked_quad.color_space(),
-                CurrentRenderPassColorSpace(),
+  SetUseProgram(draw_cache_.program_key, PATCH_CS(locked_quad.color_space()),
+                PATCH_CS(CurrentRenderPassColorSpace()),
                 /*adjust_src_white_level=*/draw_cache_.is_video_frame);
 
   if (current_program_->rounded_corner_rect_location() != -1) {
@@ -3546,7 +3556,9 @@ void GLRenderer::SetUseProgram(const ProgramKey& program_key_no_color,
                                const gfx::ColorSpace& src_color_space,
                                const gfx::ColorSpace& dst_color_space,
                                bool adjust_src_white_level) {
-  DCHECK(dst_color_space.IsValid());
+  if (settings_->enable_color_correct_rendering) {
+    DCHECK(dst_color_space.IsValid());
+  }
   gfx::ColorSpace adjusted_src_color_space = src_color_space;
   if (adjust_src_white_level) {
     // If the input color space is HDR, and it did not specify a white level,
@@ -3926,9 +3938,9 @@ void GLRenderer::CopyRenderPassDrawQuadToOverlayResource(
         cc::MathUtil::CheckedRoundUp(iosurface_height, iosurface_multiple);
   }
 
-  *overlay_texture =
-      FindOrCreateOverlayTexture(params.quad->render_pass_id, iosurface_width,
-                                 iosurface_height, RootRenderPassColorSpace());
+  *overlay_texture = FindOrCreateOverlayTexture(
+      params.quad->render_pass_id, iosurface_width, iosurface_height,
+      PATCH_CS(RootRenderPassColorSpace()));
   *new_bounds = gfx::RectF(updated_dst_rect.origin(),
                            gfx::SizeF((*overlay_texture)->texture.size()));
 
@@ -4148,8 +4160,8 @@ void GLRenderer::FlushOverdrawFeedback(const gfx::Rect& output_rect) {
 
   PrepareGeometry(SHARED_BINDING);
 
-  SetUseProgram(ProgramKey::DebugBorder(), gfx::ColorSpace::CreateSRGB(),
-                CurrentRenderPassColorSpace());
+  SetUseProgram(ProgramKey::DebugBorder(), PATCH_CS(gfx::ColorSpace::CreateSRGB()),
+                PATCH_CS(CurrentRenderPassColorSpace()));
 
   gfx::Transform render_matrix;
   render_matrix.Translate(0.5 * output_rect.width() + output_rect.x(),
@@ -4278,3 +4290,5 @@ GLRenderer::OverlayTexture::OverlayTexture() = default;
 GLRenderer::OverlayTexture::~OverlayTexture() = default;
 
 }  // namespace viz
+
+#undef PATCH_CS
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc
index d7439d851d6c027a20bf09a258603939b5c19f1e..72162a468f63543c508a3d34e357be1dfcdeba51 100644
--- a/content/browser/gpu/gpu_process_host.cc
+++ b/content/browser/gpu/gpu_process_host.cc
@@ -221,6 +221,7 @@ GpuTerminationStatus ConvertToGpuTerminationStatus(
 
 // Command-line switches to propagate to the GPU process.
 static const char* const kSwitchNames[] = {
+    switches::kDisableColorCorrectRendering,
     sandbox::policy::switches::kDisableSeccompFilterSandbox,
     sandbox::policy::switches::kGpuSandboxAllowSysVShm,
     sandbox::policy::switches::kGpuSandboxFailuresFatal,
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 74f19cb9c196510c19daffcd98c1577ec541ea54..0a65b9be576a437cc036af211230292d2c2c3c03 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -225,6 +225,7 @@
 #include "ui/accessibility/accessibility_switches.h"
 #include "ui/base/ui_base_switches.h"
 #include "ui/display/display_switches.h"
+#include "ui/gfx/switches.h"
 #include "ui/gl/gl_switches.h"
 #include "ui/native_theme/native_theme_features.h"
 #include "url/origin.h"
@@ -3313,6 +3314,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
   // Propagate the following switches to the renderer command line (along
   // with any associated values) if present in the browser command line.
   static const char* const kSwitchNames[] = {
+    switches::kDisableColorCorrectRendering,
     network::switches::kExplicitlyAllowedPorts,
     switches::kDisableInProcessStackTraces,
     sandbox::policy::switches::kDisableSeccompFilterSandbox,
diff --git a/third_party/blink/renderer/platform/graphics/canvas_color_params.cc b/third_party/blink/renderer/platform/graphics/canvas_color_params.cc
index 0501709a855b9fae82ab06c4e143b42058ddc12e..e0a457aab29acda134d1da9c798b5472c9bdb627 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_color_params.cc
+++ b/third_party/blink/renderer/platform/graphics/canvas_color_params.cc
@@ -4,6 +4,7 @@
 
 #include "third_party/blink/renderer/platform/graphics/canvas_color_params.h"
 
+#include "base/command_line.h"
 #include "cc/paint/skia_paint_canvas.h"
 #include "components/viz/common/resources/resource_format_utils.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@@ -12,6 +13,7 @@
 #include "third_party/khronos/GLES3/gl3.h"
 #include "third_party/skia/include/core/SkSurfaceProps.h"
 #include "ui/gfx/color_space.h"
+#include "ui/gfx/switches.h"
 
 namespace blink {
 
@@ -95,6 +97,11 @@ uint8_t CanvasColorParams::BytesPerPixel() const {
 }
 
 gfx::ColorSpace CanvasColorParams::GetSamplerGfxColorSpace() const {
+  auto* cmd_line = base::CommandLine::ForCurrentProcess();
+  if (cmd_line->HasSwitch(switches::kDisableColorCorrectRendering)) {
+    return gfx::ColorSpace();
+  }
+
   // TODO(ccameron): If we add support for uint8srgb as a pixel format, this
   // will need to take into account whether or not this texture will be sampled
   // in linear or nonlinear space.
@@ -102,6 +109,11 @@ gfx::ColorSpace CanvasColorParams::GetSamplerGfxColorSpace() const {
 }
 
 gfx::ColorSpace CanvasColorParams::GetStorageGfxColorSpace() const {
+  auto* cmd_line = base::CommandLine::ForCurrentProcess();
+  if (cmd_line->HasSwitch(switches::kDisableColorCorrectRendering)) {
+    return gfx::ColorSpace();
+  }
+
   return CanvasColorSpaceToGfxColorSpace(color_space_);
 }
 
diff --git a/third_party/blink/renderer/platform/widget/compositing/layer_tree_settings.cc b/third_party/blink/renderer/platform/widget/compositing/layer_tree_settings.cc
index 95e818f1406eb1a73a746b73a608137ab5c6e894..6e1d3b3b1add4eda90560856b6915d46796d4b4b 100644
--- a/third_party/blink/renderer/platform/widget/compositing/layer_tree_settings.cc
+++ b/third_party/blink/renderer/platform/widget/compositing/layer_tree_settings.cc
@@ -23,6 +23,7 @@
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 #include "ui/base/ui_base_features.h"
 #include "ui/base/ui_base_switches.h"
+#include "ui/gfx/switches.h"
 #include "ui/native_theme/native_theme_features.h"
 #include "ui/native_theme/overlay_scrollbar_constants_aura.h"
 
@@ -178,6 +179,9 @@ cc::LayerTreeSettings GenerateLayerTreeSettings(
   settings.main_frame_before_activation_enabled =
       cmd.HasSwitch(cc::switches::kEnableMainFrameBeforeActivation);
 
+  settings.enable_color_correct_rendering =
+      !cmd.HasSwitch(::switches::kDisableColorCorrectRendering);
+
   // Checkerimaging is not supported for synchronous single-threaded mode, which
   // is what the renderer uses if its not threaded.
   settings.enable_checker_imaging =
diff --git a/ui/gfx/mac/io_surface.cc b/ui/gfx/mac/io_surface.cc
index ec83bd814a0d5d6802b349d08b22013a0d99e015..043e769e7db9773de2054dcc66f13f062823f58f 100644
--- a/ui/gfx/mac/io_surface.cc
+++ b/ui/gfx/mac/io_surface.cc
@@ -18,6 +18,7 @@
 #include "base/trace_event/trace_event.h"
 #include "ui/gfx/buffer_format_util.h"
 #include "ui/gfx/icc_profile.h"
+#include "ui/gfx/switches.h"
 
 namespace gfx {
 
@@ -126,6 +127,14 @@ void IOSurfaceMachPortTraits::Release(mach_port_t port) {
 // Common method used by IOSurfaceSetColorSpace and IOSurfaceCanSetColorSpace.
 bool IOSurfaceSetColorSpace(IOSurfaceRef io_surface,
                             const ColorSpace& color_space) {
+  auto* cmd_line = base::CommandLine::ForCurrentProcess();
+  if (cmd_line->HasSwitch(switches::kDisableColorCorrectRendering)) {
+    base::ScopedCFTypeRef<CFDataRef> system_icc(
+        CGColorSpaceCopyICCProfile(base::mac::GetSystemColorSpace()));
+    IOSurfaceSetValue(io_surface, CFSTR("IOSurfaceColorSpace"), system_icc);
+    return true;
+  }
+
   // Allow but ignore invalid color spaces.
   if (!color_space.IsValid())
     return true;
@@ -286,6 +295,15 @@ IOSurfaceRef CreateIOSurface(const gfx::Size& size,
     DCHECK_EQ(kIOReturnSuccess, r);
   }
 
+  auto* cmd_line = base::CommandLine::ForCurrentProcess();
+  if (cmd_line->HasSwitch(switches::kDisableColorCorrectRendering)) {
+    CGColorSpaceRef color_space = base::mac::GetSystemColorSpace();
+    base::ScopedCFTypeRef<CFDataRef> color_space_icc(
+        CGColorSpaceCopyICCProfile(color_space));
+    IOSurfaceSetValue(surface, CFSTR("IOSurfaceColorSpace"), color_space_icc);
+    return surface;
+  }
+
   // Ensure that all IOSurfaces start as sRGB.
   if (__builtin_available(macos 10.12, *)) {
     IOSurfaceSetValue(surface, CFSTR("IOSurfaceColorSpace"), kCGColorSpaceSRGB);
diff --git a/ui/gfx/switches.cc b/ui/gfx/switches.cc
index 16eeda0d910c555aae074fe1ed8ba04c4be76d9e..095b704442f55e978c7f60e9c97c2abe20b131a7 100644
--- a/ui/gfx/switches.cc
+++ b/ui/gfx/switches.cc
@@ -10,6 +10,7 @@ namespace switches {
 // Scale factor to apply to every animation duration. Must be >= 0.0. This will
 // only apply to LinearAnimation and its subclasses.
 const char kAnimationDurationScale[] = "animation-duration-scale";
+const char kDisableColorCorrectRendering[] = "disable-color-correct-rendering";
 
 // Force disables font subpixel positioning. This affects the character glyph
 // sharpness, kerning, hinting and layout.
diff --git a/ui/gfx/switches.h b/ui/gfx/switches.h
index fa86fc52621f4cf12bad58f8c1dd7ca6b29a307c..6b98b75c05643036ecd0fb71a8682ee1088ac52e 100644
--- a/ui/gfx/switches.h
+++ b/ui/gfx/switches.h
@@ -11,6 +11,8 @@
 namespace switches {
 
 GFX_SWITCHES_EXPORT extern const char kAnimationDurationScale[];
+GFX_SWITCHES_EXPORT extern const char kDisableColorCorrectRendering[];
+
 GFX_SWITCHES_EXPORT extern const char kDisableFontSubpixelPositioning[];
 GFX_SWITCHES_EXPORT extern const char kDisableYuv420Biplanar[];
 GFX_SWITCHES_EXPORT extern const char kEnableNativeGpuMemoryBuffers[];
