| 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 402465f9f0eee7686aa5bfa9d6dbd236b809426e..41ca670fdbf197fd260b626b664b0632c3ac79af 100644
 | 
| --- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
 | 
| +++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
 | 
| @@ -60,36 +60,13 @@ namespace {
 | 
|  
 | 
|  const float s_resourceAdjustedRatio = 0.5;
 | 
|  
 | 
| -class ScopedTextureUnit0BindingRestorer {
 | 
| -  STACK_ALLOCATED();
 | 
| -  WTF_MAKE_NONCOPYABLE(ScopedTextureUnit0BindingRestorer);
 | 
| -
 | 
| - public:
 | 
| -  ScopedTextureUnit0BindingRestorer(gpu::gles2::GLES2Interface* gl,
 | 
| -                                    GLenum activeTextureUnit,
 | 
| -                                    GLuint textureUnitZeroId)
 | 
| -      : m_gl(gl),
 | 
| -        m_oldActiveTextureUnit(activeTextureUnit),
 | 
| -        m_oldTextureUnitZeroId(textureUnitZeroId) {
 | 
| -    m_gl->ActiveTexture(GL_TEXTURE0);
 | 
| -  }
 | 
| -  ~ScopedTextureUnit0BindingRestorer() {
 | 
| -    m_gl->BindTexture(GL_TEXTURE_2D, m_oldTextureUnitZeroId);
 | 
| -    m_gl->ActiveTexture(m_oldActiveTextureUnit);
 | 
| -  }
 | 
| -
 | 
| - private:
 | 
| -  gpu::gles2::GLES2Interface* m_gl;
 | 
| -  GLenum m_oldActiveTextureUnit;
 | 
| -  GLuint m_oldTextureUnitZeroId;
 | 
| -};
 | 
| -
 | 
|  static bool shouldFailDrawingBufferCreationForTesting = false;
 | 
|  
 | 
|  }  // namespace
 | 
|  
 | 
|  PassRefPtr<DrawingBuffer> DrawingBuffer::create(
 | 
|      std::unique_ptr<WebGraphicsContext3DProvider> contextProvider,
 | 
| +    Client* client,
 | 
|      const IntSize& size,
 | 
|      bool premultipliedAlpha,
 | 
|      bool wantAlphaChannel,
 | 
| @@ -136,7 +113,7 @@ PassRefPtr<DrawingBuffer> DrawingBuffer::create(
 | 
|      extensionsUtil->ensureExtensionEnabled("GL_EXT_discard_framebuffer");
 | 
|  
 | 
|    RefPtr<DrawingBuffer> drawingBuffer = adoptRef(new DrawingBuffer(
 | 
| -      std::move(contextProvider), std::move(extensionsUtil),
 | 
| +      std::move(contextProvider), std::move(extensionsUtil), client,
 | 
|        discardFramebufferSupported, wantAlphaChannel, premultipliedAlpha,
 | 
|        preserve, webGLVersion, wantDepthBuffer, wantStencilBuffer,
 | 
|        chromiumImageUsage));
 | 
| @@ -154,6 +131,7 @@ void DrawingBuffer::forceNextDrawingBufferCreationToFail() {
 | 
|  DrawingBuffer::DrawingBuffer(
 | 
|      std::unique_ptr<WebGraphicsContext3DProvider> contextProvider,
 | 
|      std::unique_ptr<Extensions3DUtil> extensionsUtil,
 | 
| +    Client* client,
 | 
|      bool discardFramebufferSupported,
 | 
|      bool wantAlphaChannel,
 | 
|      bool premultipliedAlpha,
 | 
| @@ -162,7 +140,8 @@ DrawingBuffer::DrawingBuffer(
 | 
|      bool wantDepth,
 | 
|      bool wantStencil,
 | 
|      ChromiumImageUsage chromiumImageUsage)
 | 
| -    : m_preserveDrawingBuffer(preserve),
 | 
| +    : m_client(client),
 | 
| +      m_preserveDrawingBuffer(preserve),
 | 
|        m_webGLVersion(webGLVersion),
 | 
|        m_contextProvider(std::move(contextProvider)),
 | 
|        m_gl(m_contextProvider->contextGL()),
 | 
| @@ -174,8 +153,6 @@ DrawingBuffer::DrawingBuffer(
 | 
|        m_wantDepth(wantDepth),
 | 
|        m_wantStencil(wantStencil),
 | 
|        m_chromiumImageUsage(chromiumImageUsage) {
 | 
| -  memset(m_colorMask, 0, 4 * sizeof(GLboolean));
 | 
| -  memset(m_clearColor, 0, 4 * sizeof(GLfloat));
 | 
|    // Used by browser tests to detect the use of a DrawingBuffer.
 | 
|    TRACE_EVENT_INSTANT0("test_gpu", "DrawingBufferCreation",
 | 
|                         TRACE_EVENT_SCOPE_GLOBAL);
 | 
| @@ -229,7 +206,7 @@ void DrawingBuffer::setFilterQuality(SkFilterQuality filterQuality) {
 | 
|  }
 | 
|  
 | 
|  bool DrawingBuffer::requiresAlphaChannelToBePreserved() {
 | 
| -  return !m_drawFramebufferBinding &&
 | 
| +  return m_client->DrawingBufferClientIsBoundForDraw() &&
 | 
|           defaultBufferRequiresAlphaChannelToBePreserved();
 | 
|  }
 | 
|  
 | 
| @@ -265,6 +242,7 @@ std::unique_ptr<cc::SharedBitmap> DrawingBuffer::createOrRecycleBitmap() {
 | 
|  bool DrawingBuffer::PrepareTextureMailbox(
 | 
|      cc::TextureMailbox* outMailbox,
 | 
|      std::unique_ptr<cc::SingleReleaseCallback>* outReleaseCallback) {
 | 
| +  ScopedStateRestorer scopedStateRestorer(this);
 | 
|    bool forceGpuResult = false;
 | 
|    return prepareTextureMailboxInternal(outMailbox, outReleaseCallback,
 | 
|                                         forceGpuResult);
 | 
| @@ -299,7 +277,7 @@ bool DrawingBuffer::prepareTextureMailboxInternal(
 | 
|  
 | 
|    // Resolve the multisampled buffer into m_backColorBuffer texture.
 | 
|    if (m_antiAliasingMode != None)
 | 
| -    commit();
 | 
| +    resolveMultisampleFramebufferInternal();
 | 
|  
 | 
|    if (m_softwareRendering && !forceGpuResult) {
 | 
|      return finishPrepareTextureMailboxSoftware(outMailbox, outReleaseCallback);
 | 
| @@ -344,14 +322,10 @@ bool DrawingBuffer::finishPrepareTextureMailboxGpu(
 | 
|      cc::TextureMailbox* outMailbox,
 | 
|      std::unique_ptr<cc::SingleReleaseCallback>* outReleaseCallback) {
 | 
|    if (m_webGLVersion > WebGL1) {
 | 
| +    m_stateRestorer->setPixelUnpackBufferBindingDirty();
 | 
|      m_gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
 | 
|    }
 | 
|  
 | 
| -  // We must restore the texture binding since creating new textures,
 | 
| -  // consuming and producing mailboxes changes it.
 | 
| -  ScopedTextureUnit0BindingRestorer restorer(m_gl, m_activeTextureUnit,
 | 
| -                                             m_texture2DBinding);
 | 
| -
 | 
|    // Specify the buffer that we will put in the mailbox.
 | 
|    RefPtr<ColorBuffer> colorBufferForMailbox;
 | 
|    if (m_preserveDrawingBuffer == Discard) {
 | 
| @@ -367,6 +341,7 @@ bool DrawingBuffer::finishPrepareTextureMailboxGpu(
 | 
|      if (m_discardFramebufferSupported) {
 | 
|        const GLenum attachments[3] = {GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT,
 | 
|                                       GL_STENCIL_ATTACHMENT};
 | 
| +      m_stateRestorer->setFramebufferBindingDirty();
 | 
|        m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo);
 | 
|        m_gl->DiscardFramebufferEXT(GL_FRAMEBUFFER, 3, attachments);
 | 
|      }
 | 
| @@ -414,9 +389,6 @@ bool DrawingBuffer::finishPrepareTextureMailboxGpu(
 | 
|    // Point |m_frontColorBuffer| to the buffer that we are now presenting.
 | 
|    m_frontColorBuffer = colorBufferForMailbox;
 | 
|  
 | 
| -  // Restore any state that we may have dirtied, and update dirty bits.
 | 
| -  restoreFramebufferBindings();
 | 
| -  restorePixelUnpackBufferBindings();
 | 
|    m_contentsChanged = false;
 | 
|    setBufferClearNeeded(true);
 | 
|    return true;
 | 
| @@ -465,6 +437,8 @@ void DrawingBuffer::mailboxReleasedSoftware(
 | 
|  }
 | 
|  
 | 
|  PassRefPtr<StaticBitmapImage> DrawingBuffer::transferToStaticBitmapImage() {
 | 
| +  ScopedStateRestorer scopedStateRestorer(this);
 | 
| +
 | 
|    // This can be null if the context is lost before the first call to
 | 
|    // grContext().
 | 
|    GrContext* grContext = m_contextProvider->grContext();
 | 
| @@ -618,18 +592,35 @@ DrawingBuffer::ColorBuffer::ColorBuffer(DrawingBuffer* drawingBuffer,
 | 
|  }
 | 
|  
 | 
|  DrawingBuffer::ColorBuffer::~ColorBuffer() {
 | 
| -  gpu::gles2::GLES2Interface* gl = drawingBuffer->contextGL();
 | 
| +  gpu::gles2::GLES2Interface* gl = drawingBuffer->m_gl;
 | 
|    if (receiveSyncToken.HasData())
 | 
|      gl->WaitSyncTokenCHROMIUM(receiveSyncToken.GetConstData());
 | 
|    if (imageId) {
 | 
|      gl->BindTexture(parameters.target, textureId);
 | 
|      gl->ReleaseTexImage2DCHROMIUM(parameters.target, imageId);
 | 
|      gl->DestroyImageCHROMIUM(imageId);
 | 
| +    switch (parameters.target) {
 | 
| +      case GL_TEXTURE_2D:
 | 
| +        // Restore the texture binding for GL_TEXTURE_2D, since the client will
 | 
| +        // expect the previous state.
 | 
| +        if (drawingBuffer->m_client)
 | 
| +          drawingBuffer->m_client->DrawingBufferClientRestoreTexture2DBinding();
 | 
| +        break;
 | 
| +      case GC3D_TEXTURE_RECTANGLE_ARB:
 | 
| +        // Rectangle textures aren't exposed to WebGL, so don't bother
 | 
| +        // restoring this state (there is no meaningful way to restore it).
 | 
| +        break;
 | 
| +      default:
 | 
| +        NOTREACHED();
 | 
| +        break;
 | 
| +    }
 | 
|    }
 | 
|    gl->DeleteTextures(1, &textureId);
 | 
|  }
 | 
|  
 | 
|  bool DrawingBuffer::initialize(const IntSize& size, bool useMultisampling) {
 | 
| +  ScopedStateRestorer scopedStateRestorer(this);
 | 
| +
 | 
|    if (m_gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR) {
 | 
|      // Need to try to restore the context again later.
 | 
|      return false;
 | 
| @@ -661,6 +652,7 @@ bool DrawingBuffer::initialize(const IntSize& size, bool useMultisampling) {
 | 
|        m_antiAliasingMode == ScreenSpaceAntialiasing;
 | 
|    m_sampleCount = std::min(4, maxSampleCount);
 | 
|  
 | 
| +  m_stateRestorer->setFramebufferBindingDirty();
 | 
|    m_gl->GenFramebuffers(1, &m_fbo);
 | 
|    m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo);
 | 
|    if (wantExplicitResolve()) {
 | 
| @@ -668,7 +660,7 @@ bool DrawingBuffer::initialize(const IntSize& size, bool useMultisampling) {
 | 
|      m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_multisampleFBO);
 | 
|      m_gl->GenRenderbuffers(1, &m_multisampleRenderbuffer);
 | 
|    }
 | 
| -  if (!reset(size))
 | 
| +  if (!resizeFramebufferInternal(size))
 | 
|      return false;
 | 
|  
 | 
|    if (m_depthStencilBuffer) {
 | 
| @@ -693,11 +685,11 @@ bool DrawingBuffer::copyToPlatformTexture(gpu::gles2::GLES2Interface* gl,
 | 
|                                            bool premultiplyAlpha,
 | 
|                                            bool flipY,
 | 
|                                            SourceDrawingBuffer sourceBuffer) {
 | 
| +  ScopedStateRestorer scopedStateRestorer(this);
 | 
| +
 | 
|    if (m_contentsChanged) {
 | 
| -    if (m_antiAliasingMode != None) {
 | 
| -      commit();
 | 
| -      restoreFramebufferBindings();
 | 
| -    }
 | 
| +    if (m_antiAliasingMode != None)
 | 
| +      resolveMultisampleFramebufferInternal();
 | 
|      m_gl->Flush();
 | 
|    }
 | 
|  
 | 
| @@ -753,10 +745,6 @@ bool DrawingBuffer::copyToPlatformTexture(gpu::gles2::GLES2Interface* gl,
 | 
|    return true;
 | 
|  }
 | 
|  
 | 
| -GLuint DrawingBuffer::framebuffer() const {
 | 
| -  return m_fbo;
 | 
| -}
 | 
| -
 | 
|  WebLayer* DrawingBuffer::platformLayer() {
 | 
|    if (!m_layer) {
 | 
|      m_layer = wrapUnique(
 | 
| @@ -810,6 +798,8 @@ void DrawingBuffer::beginDestruction() {
 | 
|  
 | 
|    if (m_layer)
 | 
|      GraphicsLayer::unregisterContentsLayer(m_layer->layer());
 | 
| +
 | 
| +  m_client = nullptr;
 | 
|  }
 | 
|  
 | 
|  bool DrawingBuffer::resizeDefaultFramebuffer(const IntSize& size) {
 | 
| @@ -819,6 +809,8 @@ bool DrawingBuffer::resizeDefaultFramebuffer(const IntSize& size) {
 | 
|    attachColorBufferToReadFramebuffer();
 | 
|  
 | 
|    if (wantExplicitResolve()) {
 | 
| +    m_stateRestorer->setFramebufferBindingDirty();
 | 
| +    m_stateRestorer->setRenderbufferBindingDirty();
 | 
|      m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_multisampleFBO);
 | 
|      m_gl->BindRenderbuffer(GL_RENDERBUFFER, m_multisampleRenderbuffer);
 | 
|      m_gl->RenderbufferStorageMultisampleCHROMIUM(
 | 
| @@ -833,6 +825,8 @@ bool DrawingBuffer::resizeDefaultFramebuffer(const IntSize& size) {
 | 
|    }
 | 
|  
 | 
|    if (wantDepthOrStencil()) {
 | 
| +    m_stateRestorer->setFramebufferBindingDirty();
 | 
| +    m_stateRestorer->setRenderbufferBindingDirty();
 | 
|      m_gl->BindFramebuffer(GL_FRAMEBUFFER,
 | 
|                            m_multisampleFBO ? m_multisampleFBO : m_fbo);
 | 
|      if (!m_depthStencilBuffer)
 | 
| @@ -859,17 +853,25 @@ bool DrawingBuffer::resizeDefaultFramebuffer(const IntSize& size) {
 | 
|    }
 | 
|  
 | 
|    if (wantExplicitResolve()) {
 | 
| +    m_stateRestorer->setFramebufferBindingDirty();
 | 
|      m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_multisampleFBO);
 | 
|      if (m_gl->CheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
 | 
|        return false;
 | 
|    }
 | 
|  
 | 
| +  m_stateRestorer->setFramebufferBindingDirty();
 | 
|    m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo);
 | 
|    return m_gl->CheckFramebufferStatus(GL_FRAMEBUFFER) ==
 | 
|           GL_FRAMEBUFFER_COMPLETE;
 | 
|  }
 | 
|  
 | 
|  void DrawingBuffer::clearFramebuffers(GLbitfield clearMask) {
 | 
| +  ScopedStateRestorer scopedStateRestorer(this);
 | 
| +  clearFramebuffersInternal(clearMask);
 | 
| +}
 | 
| +
 | 
| +void DrawingBuffer::clearFramebuffersInternal(GLbitfield clearMask) {
 | 
| +  m_stateRestorer->setFramebufferBindingDirty();
 | 
|    // We will clear the multisample FBO, but we also need to clear the
 | 
|    // non-multisampled buffer.
 | 
|    if (m_multisampleFBO) {
 | 
| @@ -898,7 +900,12 @@ IntSize DrawingBuffer::adjustSize(const IntSize& desiredSize,
 | 
|    return adjustedSize;
 | 
|  }
 | 
|  
 | 
| -bool DrawingBuffer::reset(const IntSize& newSize) {
 | 
| +bool DrawingBuffer::resize(const IntSize& newSize) {
 | 
| +  ScopedStateRestorer scopedStateRestorer(this);
 | 
| +  return resizeFramebufferInternal(newSize);
 | 
| +}
 | 
| +
 | 
| +bool DrawingBuffer::resizeFramebufferInternal(const IntSize& newSize) {
 | 
|    CHECK(!newSize.isEmpty());
 | 
|    IntSize adjustedSize = adjustSize(newSize, m_size, m_maxTextureSize);
 | 
|    if (adjustedSize.isEmpty())
 | 
| @@ -923,6 +930,7 @@ bool DrawingBuffer::reset(const IntSize& newSize) {
 | 
|        return false;
 | 
|    }
 | 
|  
 | 
| +  m_stateRestorer->setClearStateDirty();
 | 
|    m_gl->Disable(GL_SCISSOR_TEST);
 | 
|    m_gl->ClearColor(0, 0, 0,
 | 
|                     defaultBufferRequiresAlphaChannelToBePreserved() ? 1 : 0);
 | 
| @@ -940,17 +948,25 @@ bool DrawingBuffer::reset(const IntSize& newSize) {
 | 
|      m_gl->StencilMaskSeparate(GL_FRONT, 0xFFFFFFFF);
 | 
|    }
 | 
|  
 | 
| -  clearFramebuffers(clearMask);
 | 
| +  clearFramebuffersInternal(clearMask);
 | 
|    return true;
 | 
|  }
 | 
|  
 | 
| -void DrawingBuffer::commit() {
 | 
| +void DrawingBuffer::resolveAndBindForReadAndDraw() {
 | 
| +  {
 | 
| +    ScopedStateRestorer scopedStateRestorer(this);
 | 
| +    resolveMultisampleFramebufferInternal();
 | 
| +  }
 | 
| +  m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo);
 | 
| +}
 | 
| +
 | 
| +void DrawingBuffer::resolveMultisampleFramebufferInternal() {
 | 
| +  m_stateRestorer->setFramebufferBindingDirty();
 | 
|    if (wantExplicitResolve() && !m_contentsChangeCommitted) {
 | 
| +    m_stateRestorer->setClearStateDirty();
 | 
|      m_gl->BindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, m_multisampleFBO);
 | 
|      m_gl->BindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, m_fbo);
 | 
| -
 | 
| -    if (m_scissorEnabled)
 | 
| -      m_gl->Disable(GL_SCISSOR_TEST);
 | 
| +    m_gl->Disable(GL_SCISSOR_TEST);
 | 
|  
 | 
|      int width = m_size.width();
 | 
|      int height = m_size.height();
 | 
| @@ -969,52 +985,17 @@ void DrawingBuffer::commit() {
 | 
|              .disable_multisampling_color_mask_usage) {
 | 
|        m_gl->ClearColor(0, 0, 0, 1);
 | 
|        m_gl->ColorMask(false, false, false, true);
 | 
| -      m_gl->Clear(GL_COLOR_BUFFER_BIT);
 | 
| -
 | 
| -      m_gl->ClearColor(m_clearColor[0], m_clearColor[1], m_clearColor[2],
 | 
| -                       m_clearColor[3]);
 | 
| -      m_gl->ColorMask(m_colorMask[0], m_colorMask[1], m_colorMask[2],
 | 
| -                      m_colorMask[3]);
 | 
|      }
 | 
| -
 | 
| -    if (m_scissorEnabled)
 | 
| -      m_gl->Enable(GL_SCISSOR_TEST);
 | 
|    }
 | 
|  
 | 
|    m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo);
 | 
| -  if (m_antiAliasingMode == ScreenSpaceAntialiasing) {
 | 
| +  if (m_antiAliasingMode == ScreenSpaceAntialiasing)
 | 
|      m_gl->ApplyScreenSpaceAntialiasingCHROMIUM();
 | 
| -  }
 | 
|    m_contentsChangeCommitted = true;
 | 
|  }
 | 
|  
 | 
| -void DrawingBuffer::restorePixelUnpackBufferBindings() {
 | 
| -  if (m_webGLVersion > WebGL1) {
 | 
| -    m_gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pixelUnpackBufferBinding);
 | 
| -  }
 | 
| -}
 | 
| -
 | 
|  void DrawingBuffer::restoreFramebufferBindings() {
 | 
| -  if (m_drawFramebufferBinding && m_readFramebufferBinding) {
 | 
| -    if (m_drawFramebufferBinding == m_readFramebufferBinding) {
 | 
| -      m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_readFramebufferBinding);
 | 
| -    } else {
 | 
| -      m_gl->BindFramebuffer(GL_READ_FRAMEBUFFER, m_readFramebufferBinding);
 | 
| -      m_gl->BindFramebuffer(GL_DRAW_FRAMEBUFFER, m_drawFramebufferBinding);
 | 
| -    }
 | 
| -    return;
 | 
| -  }
 | 
| -  if (!m_drawFramebufferBinding && !m_readFramebufferBinding) {
 | 
| -    bind(GL_FRAMEBUFFER);
 | 
| -    return;
 | 
| -  }
 | 
| -  if (!m_drawFramebufferBinding) {
 | 
| -    bind(GL_DRAW_FRAMEBUFFER);
 | 
| -    m_gl->BindFramebuffer(GL_READ_FRAMEBUFFER, m_readFramebufferBinding);
 | 
| -  } else {
 | 
| -    bind(GL_READ_FRAMEBUFFER);
 | 
| -    m_gl->BindFramebuffer(GL_DRAW_FRAMEBUFFER, m_drawFramebufferBinding);
 | 
| -  }
 | 
| +  m_client->DrawingBufferClientRestoreFramebufferBinding();
 | 
|  }
 | 
|  
 | 
|  bool DrawingBuffer::multisample() const {
 | 
| @@ -1026,15 +1007,13 @@ void DrawingBuffer::bind(GLenum target) {
 | 
|                          wantExplicitResolve() ? m_multisampleFBO : m_fbo);
 | 
|  }
 | 
|  
 | 
| -void DrawingBuffer::setPackAlignment(GLint param) {
 | 
| -  m_packAlignment = param;
 | 
| -}
 | 
| -
 | 
|  bool DrawingBuffer::paintRenderingResultsToImageData(
 | 
|      int& width,
 | 
|      int& height,
 | 
|      SourceDrawingBuffer sourceBuffer,
 | 
|      WTF::ArrayBufferContents& contents) {
 | 
| +  ScopedStateRestorer scopedStateRestorer(this);
 | 
| +
 | 
|    ASSERT(!m_premultipliedAlpha);
 | 
|    width = size().width();
 | 
|    height = size().height();
 | 
| @@ -1050,6 +1029,7 @@ bool DrawingBuffer::paintRenderingResultsToImageData(
 | 
|                                    WTF::ArrayBufferContents::DontInitialize);
 | 
|  
 | 
|    GLuint fbo = 0;
 | 
| +  m_stateRestorer->setFramebufferBindingDirty();
 | 
|    if (sourceBuffer == FrontBuffer && m_frontColorBuffer) {
 | 
|      m_gl->GenFramebuffers(1, &fbo);
 | 
|      m_gl->BindFramebuffer(GL_FRAMEBUFFER, fbo);
 | 
| @@ -1057,7 +1037,7 @@ bool DrawingBuffer::paintRenderingResultsToImageData(
 | 
|                                 m_frontColorBuffer->parameters.target,
 | 
|                                 m_frontColorBuffer->textureId, 0);
 | 
|    } else {
 | 
| -    m_gl->BindFramebuffer(GL_FRAMEBUFFER, framebuffer());
 | 
| +    m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo);
 | 
|    }
 | 
|  
 | 
|    readBackFramebuffer(static_cast<unsigned char*>(pixels.data()), width, height,
 | 
| @@ -1070,8 +1050,6 @@ bool DrawingBuffer::paintRenderingResultsToImageData(
 | 
|      m_gl->DeleteFramebuffers(1, &fbo);
 | 
|    }
 | 
|  
 | 
| -  restoreFramebufferBindings();
 | 
| -
 | 
|    pixels.transfer(contents);
 | 
|    return true;
 | 
|  }
 | 
| @@ -1081,11 +1059,9 @@ void DrawingBuffer::readBackFramebuffer(unsigned char* pixels,
 | 
|                                          int height,
 | 
|                                          ReadbackOrder readbackOrder,
 | 
|                                          WebGLImageConversion::AlphaOp op) {
 | 
| -  if (m_packAlignment > 4)
 | 
| -    m_gl->PixelStorei(GL_PACK_ALIGNMENT, 1);
 | 
| +  m_stateRestorer->setPixelPackAlignmentDirty();
 | 
| +  m_gl->PixelStorei(GL_PACK_ALIGNMENT, 1);
 | 
|    m_gl->ReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
 | 
| -  if (m_packAlignment > 4)
 | 
| -    m_gl->PixelStorei(GL_PACK_ALIGNMENT, m_packAlignment);
 | 
|  
 | 
|    size_t bufferSize = 4 * width * height;
 | 
|  
 | 
| @@ -1127,6 +1103,9 @@ void DrawingBuffer::flipVertically(uint8_t* framebuffer,
 | 
|  
 | 
|  RefPtr<DrawingBuffer::ColorBuffer> DrawingBuffer::createColorBuffer(
 | 
|      const IntSize& size) {
 | 
| +  m_stateRestorer->setFramebufferBindingDirty();
 | 
| +  m_stateRestorer->setTextureBindingDirty();
 | 
| +
 | 
|    // Select the Parameters for the texture object. Allocate the backing
 | 
|    // GpuMemoryBuffer and GLImage, if one is going to be used.
 | 
|    ColorBufferParameters parameters;
 | 
| @@ -1179,6 +1158,8 @@ RefPtr<DrawingBuffer::ColorBuffer> DrawingBuffer::createColorBuffer(
 | 
|    if (imageId && !m_wantAlphaChannel &&
 | 
|        contextProvider()->getCapabilities().chromium_image_rgb_emulation) {
 | 
|      GLuint fbo = 0;
 | 
| +
 | 
| +    m_stateRestorer->setClearStateDirty();
 | 
|      m_gl->GenFramebuffers(1, &fbo);
 | 
|      m_gl->BindFramebuffer(GL_FRAMEBUFFER, fbo);
 | 
|      m_gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
 | 
| @@ -1189,17 +1170,15 @@ RefPtr<DrawingBuffer::ColorBuffer> DrawingBuffer::createColorBuffer(
 | 
|      m_gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
 | 
|                                 parameters.target, 0, 0);
 | 
|      m_gl->DeleteFramebuffers(1, &fbo);
 | 
| -    restoreFramebufferBindings();
 | 
| -    m_gl->ClearColor(m_clearColor[0], m_clearColor[1], m_clearColor[2],
 | 
| -                     m_clearColor[3]);
 | 
| -    m_gl->ColorMask(m_colorMask[0], m_colorMask[1], m_colorMask[2],
 | 
| -                    m_colorMask[3]);
 | 
|    }
 | 
|  
 | 
|    return adoptRef(new ColorBuffer(this, parameters, size, textureId, imageId));
 | 
|  }
 | 
|  
 | 
|  void DrawingBuffer::attachColorBufferToReadFramebuffer() {
 | 
| +  m_stateRestorer->setFramebufferBindingDirty();
 | 
| +  m_stateRestorer->setTextureBindingDirty();
 | 
| +
 | 
|    m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo);
 | 
|  
 | 
|    GLenum target = m_backColorBuffer->parameters.target;
 | 
| @@ -1213,9 +1192,6 @@ void DrawingBuffer::attachColorBufferToReadFramebuffer() {
 | 
|    else
 | 
|      m_gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, id,
 | 
|                                 0);
 | 
| -
 | 
| -  restoreTextureBindings();
 | 
| -  restoreFramebufferBindings();
 | 
|  }
 | 
|  
 | 
|  bool DrawingBuffer::wantExplicitResolve() {
 | 
| @@ -1240,11 +1216,33 @@ GLenum DrawingBuffer::getMultisampledRenderbufferFormat() {
 | 
|    return GL_RGB8_OES;
 | 
|  }
 | 
|  
 | 
| -void DrawingBuffer::restoreTextureBindings() {
 | 
| -  // This class potentially modifies the bindings for GL_TEXTURE_2D and
 | 
| -  // GL_TEXTURE_RECTANGLE. Only GL_TEXTURE_2D needs to be restored since
 | 
| -  // the public interface for WebGL does not support GL_TEXTURE_RECTANGLE.
 | 
| -  m_gl->BindTexture(GL_TEXTURE_2D, m_texture2DBinding);
 | 
| +DrawingBuffer::ScopedStateRestorer::ScopedStateRestorer(
 | 
| +    DrawingBuffer* drawingBuffer)
 | 
| +    : m_drawingBuffer(drawingBuffer) {
 | 
| +  DCHECK(!m_drawingBuffer->m_stateRestorer);
 | 
| +  m_drawingBuffer->m_stateRestorer = this;
 | 
| +}
 | 
| +
 | 
| +DrawingBuffer::ScopedStateRestorer::~ScopedStateRestorer() {
 | 
| +  m_drawingBuffer->m_stateRestorer = nullptr;
 | 
| +  Client* client = m_drawingBuffer->m_client;
 | 
| +  if (!client)
 | 
| +    return;
 | 
| +
 | 
| +  if (m_clearStateDirty) {
 | 
| +    client->DrawingBufferClientRestoreScissorTest();
 | 
| +    client->DrawingBufferClientRestoreMaskAndClearValues();
 | 
| +  }
 | 
| +  if (m_pixelPackAlignmentDirty)
 | 
| +    client->DrawingBufferClientRestorePixelPackAlignment();
 | 
| +  if (m_textureBindingDirty)
 | 
| +    client->DrawingBufferClientRestoreTexture2DBinding();
 | 
| +  if (m_renderbufferBindingDirty)
 | 
| +    client->DrawingBufferClientRestoreRenderbufferBinding();
 | 
| +  if (m_framebufferBindingDirty)
 | 
| +    client->DrawingBufferClientRestoreFramebufferBinding();
 | 
| +  if (m_pixelUnpackBufferBindingDirty)
 | 
| +    client->DrawingBufferClientRestorePixelUnpackBufferBinding();
 | 
|  }
 | 
|  
 | 
|  bool DrawingBuffer::shouldUseChromiumImage() {
 | 
| 
 |