| 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() { | 
|  |