| Index: third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
 | 
| diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
 | 
| index 155558732ef1c1bfd811b51a7aaa3b5d72de3334..4b66b55401270c1b8809b2be484b83a71a199d7a 100644
 | 
| --- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
 | 
| +++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
 | 
| @@ -576,6 +576,19 @@ DrawingBuffer::CreateOrRecycleColorBuffer() {
 | 
|    return CreateColorBuffer(size_);
 | 
|  }
 | 
|  
 | 
| +DrawingBuffer::ScopedRGBEmulationForBlitFramebuffer::
 | 
| +    ScopedRGBEmulationForBlitFramebuffer(DrawingBuffer* drawing_buffer)
 | 
| +    : drawing_buffer_(drawing_buffer) {
 | 
| +  doing_work_ = drawing_buffer->SetupRGBEmulationForBlitFramebuffer();
 | 
| +}
 | 
| +
 | 
| +DrawingBuffer::ScopedRGBEmulationForBlitFramebuffer::
 | 
| +    ~ScopedRGBEmulationForBlitFramebuffer() {
 | 
| +  if (doing_work_) {
 | 
| +    drawing_buffer_->CleanupRGBEmulationForBlitFramebuffer();
 | 
| +  }
 | 
| +}
 | 
| +
 | 
|  DrawingBuffer::ColorBuffer::ColorBuffer(
 | 
|      DrawingBuffer* drawing_buffer,
 | 
|      const ColorBufferParameters& parameters,
 | 
| @@ -599,6 +612,10 @@ DrawingBuffer::ColorBuffer::~ColorBuffer() {
 | 
|    if (image_id) {
 | 
|      gl->BindTexture(parameters.target, texture_id);
 | 
|      gl->ReleaseTexImage2DCHROMIUM(parameters.target, image_id);
 | 
| +    if (rgb_workaround_texture_id) {
 | 
| +      gl->BindTexture(parameters.target, rgb_workaround_texture_id);
 | 
| +      gl->ReleaseTexImage2DCHROMIUM(parameters.target, image_id);
 | 
| +    }
 | 
|      gl->DestroyImageCHROMIUM(image_id);
 | 
|      switch (parameters.target) {
 | 
|        case GL_TEXTURE_2D:
 | 
| @@ -618,6 +635,10 @@ DrawingBuffer::ColorBuffer::~ColorBuffer() {
 | 
|      gpu_memory_buffer.reset();
 | 
|    }
 | 
|    gl->DeleteTextures(1, &texture_id);
 | 
| +  if (rgb_workaround_texture_id) {
 | 
| +    // Avoid deleting this texture if it was unused.
 | 
| +    gl->DeleteTextures(1, &rgb_workaround_texture_id);
 | 
| +  }
 | 
|  }
 | 
|  
 | 
|  bool DrawingBuffer::Initialize(const IntSize& size, bool use_multisampling) {
 | 
| @@ -1258,6 +1279,78 @@ GLenum DrawingBuffer::GetMultisampledRenderbufferFormat() {
 | 
|    return GL_RGB8_OES;
 | 
|  }
 | 
|  
 | 
| +bool DrawingBuffer::SetupRGBEmulationForBlitFramebuffer() {
 | 
| +  // We only need to do this work if:
 | 
| +  //  - The user has selected alpha:false and antialias:false
 | 
| +  //  - We are using CHROMIUM_image with RGB emulation
 | 
| +  // macOS is the only platform on which this is necessary.
 | 
| +
 | 
| +  if (want_alpha_channel_ || anti_aliasing_mode_ != kNone)
 | 
| +    return false;
 | 
| +
 | 
| +  if (!(ShouldUseChromiumImage() &&
 | 
| +        ContextProvider()->GetCapabilities().chromium_image_rgb_emulation))
 | 
| +    return false;
 | 
| +
 | 
| +  if (!back_color_buffer_)
 | 
| +    return false;
 | 
| +
 | 
| +  // If for some reason the back buffer doesn't have a CHROMIUM_image,
 | 
| +  // don't proceed with this workaround.
 | 
| +  if (!back_color_buffer_->image_id)
 | 
| +    return false;
 | 
| +
 | 
| +  // Before allowing the BlitFramebuffer call to go through, it's necessary
 | 
| +  // to swap out the RGBA texture that's bound to the CHROMIUM_image
 | 
| +  // instance with an RGB texture. BlitFramebuffer requires the internal
 | 
| +  // formats of the source and destination to match when doing a
 | 
| +  // multisample resolve, and the best way to achieve this without adding
 | 
| +  // more full-screen blits is to hook up a true RGB texture to the
 | 
| +  // underlying IOSurface. Unfortunately, on macOS, this rendering path
 | 
| +  // destroys the alpha channel and requires a fixup afterward, which is
 | 
| +  // why it isn't used all the time.
 | 
| +
 | 
| +  GLuint rgb_texture = back_color_buffer_->rgb_workaround_texture_id;
 | 
| +  GLenum target = GC3D_TEXTURE_RECTANGLE_ARB;
 | 
| +  if (!rgb_texture) {
 | 
| +    gl_->GenTextures(1, &rgb_texture);
 | 
| +    gl_->BindTexture(target, rgb_texture);
 | 
| +    gl_->TexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 | 
| +    gl_->TexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 | 
| +    gl_->TexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 | 
| +    gl_->TexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 | 
| +
 | 
| +    // Bind this texture to the CHROMIUM_image instance that the color
 | 
| +    // buffer owns. This is an expensive operation, so it's important that
 | 
| +    // the result be cached.
 | 
| +    gl_->BindTexImage2DWithInternalformatCHROMIUM(target, GL_RGB,
 | 
| +                                                  back_color_buffer_->image_id);
 | 
| +    back_color_buffer_->rgb_workaround_texture_id = rgb_texture;
 | 
| +  }
 | 
| +
 | 
| +  gl_->FramebufferTexture2D(GL_DRAW_FRAMEBUFFER_ANGLE, GL_COLOR_ATTACHMENT0,
 | 
| +                            target, rgb_texture, 0);
 | 
| +  return true;
 | 
| +}
 | 
| +
 | 
| +void DrawingBuffer::CleanupRGBEmulationForBlitFramebuffer() {
 | 
| +  // This will only be called if SetupRGBEmulationForBlitFramebuffer was.
 | 
| +  // Put the framebuffer back the way it was, and clear the alpha channel.
 | 
| +  DCHECK(back_color_buffer_);
 | 
| +  DCHECK(back_color_buffer_->image_id);
 | 
| +  GLenum target = GC3D_TEXTURE_RECTANGLE_ARB;
 | 
| +  gl_->FramebufferTexture2D(GL_DRAW_FRAMEBUFFER_ANGLE, GL_COLOR_ATTACHMENT0,
 | 
| +                            target, back_color_buffer_->texture_id, 0);
 | 
| +  // Clear the alpha channel.
 | 
| +  gl_->ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
 | 
| +  gl_->Disable(GL_SCISSOR_TEST);
 | 
| +  gl_->ClearColor(0, 0, 0, 1);
 | 
| +  gl_->Clear(GL_COLOR_BUFFER_BIT);
 | 
| +  DCHECK(client_);
 | 
| +  client_->DrawingBufferClientRestoreScissorTest();
 | 
| +  client_->DrawingBufferClientRestoreMaskAndClearValues();
 | 
| +}
 | 
| +
 | 
|  DrawingBuffer::ScopedStateRestorer::ScopedStateRestorer(
 | 
|      DrawingBuffer* drawing_buffer)
 | 
|      : drawing_buffer_(drawing_buffer) {
 | 
| 
 |