| Index: third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp | 
| diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp | 
| index 0dca9165b5c0d6bc54ff70dfccbba8dadcb2cdd6..6b0a69ad959142b547551752e2d26174d16253d1 100644 | 
| --- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp | 
| +++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp | 
| @@ -500,6 +500,28 @@ class ScopedFramebufferRestorer { | 
| Member<WebGLRenderingContextBase> m_context; | 
| }; | 
|  | 
| +class ScopedUnpackParametersResetRestore { | 
| +  STACK_ALLOCATED(); | 
| + | 
| + public: | 
| +  explicit ScopedUnpackParametersResetRestore( | 
| +      WebGLRenderingContextBase* context, | 
| +      bool enabled = true) | 
| +      : m_context(context), m_enabled(enabled) { | 
| +    if (enabled) | 
| +      m_context->resetUnpackParameters(); | 
| +  } | 
| + | 
| +  ~ScopedUnpackParametersResetRestore() { | 
| +    if (m_enabled) | 
| +      m_context->restoreUnpackParameters(); | 
| +  } | 
| + | 
| + private: | 
| +  Member<WebGLRenderingContextBase> m_context; | 
| +  bool m_enabled; | 
| +}; | 
| + | 
| static void formatWebGLStatusString(const StringView& glInfo, | 
| const StringView& infoString, | 
| StringBuilder& builder) { | 
| @@ -4404,7 +4426,7 @@ void WebGLRenderingContextBase::texImageImpl( | 
| } | 
| } | 
|  | 
| -  resetUnpackParameters(); | 
| +  ScopedUnpackParametersResetRestore temporaryResetUnpack(this); | 
| if (functionID == TexImage2D) { | 
| texImage2DBase(target, level, internalformat, imageExtractor.imageWidth(), | 
| imageExtractor.imageHeight(), 0, format, type, | 
| @@ -4421,7 +4443,6 @@ void WebGLRenderingContextBase::texImageImpl( | 
| imageExtractor.imageHeight(), 1, format, type, | 
| needConversion ? data.data() : imagePixelData); | 
| } | 
| -  restoreUnpackParameters(); | 
| } | 
|  | 
| bool WebGLRenderingContextBase::validateTexFunc( | 
| @@ -4607,16 +4628,14 @@ void WebGLRenderingContextBase::texImageHelperDOMArrayBufferView( | 
| return; | 
| } | 
|  | 
| -  if (changeUnpackAlignment) | 
| -    resetUnpackParameters(); | 
| +  ScopedUnpackParametersResetRestore temporaryResetUnpack( | 
| +      this, changeUnpackAlignment); | 
| if (functionID == TexImage2D) | 
| texImage2DBase(target, level, internalformat, width, height, border, format, | 
| type, data); | 
| else if (functionID == TexSubImage2D) | 
| contextGL()->TexSubImage2D(target, level, xoffset, yoffset, width, height, | 
| format, type, data); | 
| -  if (changeUnpackAlignment) | 
| -    restoreUnpackParameters(); | 
| } | 
|  | 
| void WebGLRenderingContextBase::texImage2D(GLenum target, | 
| @@ -4690,7 +4709,7 @@ void WebGLRenderingContextBase::texImageHelperImageData( | 
| return; | 
| } | 
| } | 
| -  resetUnpackParameters(); | 
| +  ScopedUnpackParametersResetRestore temporaryResetUnpack(this); | 
| if (functionID == TexImage2D) { | 
| texImage2DBase(target, level, internalformat, pixels->width(), | 
| pixels->height(), border, format, type, | 
| @@ -4706,7 +4725,6 @@ void WebGLRenderingContextBase::texImageHelperImageData( | 
| pixels->height(), depth, format, type, | 
| needConversion ? data.data() : pixels->data()->data()); | 
| } | 
| -  restoreUnpackParameters(); | 
| } | 
|  | 
| void WebGLRenderingContextBase::texImage2D(GLenum target, | 
| @@ -4799,6 +4817,8 @@ void WebGLRenderingContextBase::texImageCanvasByGPU(HTMLCanvasElement* canvas, | 
| if (!canvas->is3D()) { | 
| ImageBuffer* buffer = canvas->buffer(); | 
| if (buffer && | 
| +        extensionsUtil()->canUseCopyTextureCHROMIUM( | 
| +            targetTexture, targetInternalformat, targetType, targetLevel) && | 
| !buffer->copyToPlatformTexture( | 
| contextGL(), targetTexture, targetInternalformat, targetType, | 
| targetLevel, m_unpackPremultiplyAlpha, m_unpackFlipY)) { | 
| @@ -4839,7 +4859,7 @@ void WebGLRenderingContextBase::texImageByGPU(TexImageByGPUType functionType, | 
| GLint targetLevel = level; | 
| bool possibleDirectCopy = false; | 
| if (functionType == TexImage2DByGPU) { | 
| -    possibleDirectCopy = Extensions3DUtil::canUseCopyTextureCHROMIUM( | 
| +    possibleDirectCopy = extensionsUtil()->canUseCopyTextureCHROMIUM( | 
| target, internalformat, type, level); | 
| } | 
|  | 
| @@ -5017,45 +5037,58 @@ void WebGLRenderingContextBase::texImageHelperHTMLVideoElement( | 
| yoffset, zoffset)) | 
| return; | 
|  | 
| -  if (functionID == TexImage2D) { | 
| +  if (functionID == TexImage2D && GL_TEXTURE_2D == target && | 
| +      extensionsUtil()->canUseCopyTextureCHROMIUM(target, internalformat, type, | 
| +                                                  level)) { | 
| // Go through the fast path doing a GPU-GPU textures copy without a readback | 
| -    // to system memory if possible.  Otherwise, it will fall back to the normal | 
| -    // SW path. | 
| -    if (GL_TEXTURE_2D == target) { | 
| -      if (Extensions3DUtil::canUseCopyTextureCHROMIUM(target, internalformat, | 
| -                                                      type, level) && | 
| -          video->copyVideoTextureToPlatformTexture( | 
| -              contextGL(), texture->object(), internalformat, type, | 
| -              m_unpackPremultiplyAlpha, m_unpackFlipY)) { | 
| -        return; | 
| -      } | 
| +    // to system memory if possible. | 
| +    // Otherwise, it will fall back to the normal SW path. | 
| +    if (video->copyVideoTextureToPlatformTexture( | 
| +            contextGL(), texture->object(), internalformat, type, | 
| +            m_unpackPremultiplyAlpha, m_unpackFlipY)) { | 
| +      return; | 
| +    } | 
| +  } | 
|  | 
| -      // Try using an accelerated image buffer, this allows YUV conversion to be | 
| -      // done on the GPU. | 
| -      std::unique_ptr<ImageBufferSurface> surface = | 
| -          wrapUnique(new AcceleratedImageBufferSurface( | 
| -              IntSize(video->videoWidth(), video->videoHeight()))); | 
| -      if (surface->isValid()) { | 
| -        std::unique_ptr<ImageBuffer> imageBuffer( | 
| -            ImageBuffer::create(std::move(surface))); | 
| -        if (imageBuffer) { | 
| -          // The video element paints an RGBA frame into our surface here. By | 
| -          // using an AcceleratedImageBufferSurface, we enable the | 
| -          // WebMediaPlayer implementation to do any necessary color space | 
| -          // conversion on the GPU (though it | 
| -          // may still do a CPU conversion and upload the results). | 
| -          video->paintCurrentFrame( | 
| -              imageBuffer->canvas(), | 
| -              IntRect(0, 0, video->videoWidth(), video->videoHeight()), | 
| -              nullptr); | 
| - | 
| -          // This is a straight GPU-GPU copy, any necessary color space | 
| -          // conversion was handled in the paintCurrentFrameInContext() call. | 
| -          if (imageBuffer->copyToPlatformTexture( | 
| -                  contextGL(), texture->object(), internalformat, type, level, | 
| -                  m_unpackPremultiplyAlpha, m_unpackFlipY)) { | 
| -            return; | 
| -          } | 
| +  { | 
| +    // Try using optimized CPU-GPU path for some formats: e.g. Y16 and Y8. It | 
| +    // leaves early for other formats or if frame is stored on GPU. | 
| +    ScopedUnpackParametersResetRestore( | 
| +        this, m_unpackFlipY || m_unpackPremultiplyAlpha); | 
| +    if (video->texImageImpl(getTexImageFunctionName(functionID), target, | 
| +                            contextGL(), level, internalformat, format, type, | 
| +                            xoffset, yoffset, zoffset, m_unpackFlipY, | 
| +                            m_unpackPremultiplyAlpha && | 
| +                                m_unpackColorspaceConversion == GL_NONE)) | 
| +      return; | 
| +  } | 
| + | 
| +  if (functionID == TexImage2D && GL_TEXTURE_2D == target && | 
| +      extensionsUtil()->canUseCopyTextureCHROMIUM(target, internalformat, type, | 
| +                                                  level)) { | 
| +    // Try using an accelerated image buffer, this allows YUV conversion to be | 
| +    // done on the GPU. | 
| +    std::unique_ptr<ImageBufferSurface> surface = | 
| +        wrapUnique(new AcceleratedImageBufferSurface( | 
| +            IntSize(video->videoWidth(), video->videoHeight()))); | 
| +    if (surface->isValid()) { | 
| +      std::unique_ptr<ImageBuffer> imageBuffer( | 
| +          ImageBuffer::create(std::move(surface))); | 
| +      if (imageBuffer) { | 
| +        // The video element paints an RGBA frame into our surface here.  By | 
| +        // using an AcceleratedImageBufferSurface, we enable the WebMediaPlayer | 
| +        // implementation to do any necessary color space conversion on the GPU | 
| +        // (though it may still do a CPU conversion and upload the results). | 
| +        video->paintCurrentFrame( | 
| +            imageBuffer->canvas(), | 
| +            IntRect(0, 0, video->videoWidth(), video->videoHeight()), nullptr); | 
| + | 
| +        // This is a straight GPU-GPU copy, any necessary color space conversion | 
| +        // was handled in the paintCurrentFrameInContext() call. | 
| +        if (imageBuffer->copyToPlatformTexture( | 
| +                contextGL(), texture->object(), internalformat, type, level, | 
| +                m_unpackPremultiplyAlpha, m_unpackFlipY)) { | 
| +          return; | 
| } | 
| } | 
| } | 
| @@ -5180,7 +5213,7 @@ void WebGLRenderingContextBase::texImageHelperImageBitmap( | 
| return; | 
| } | 
| } | 
| -  resetUnpackParameters(); | 
| +  ScopedUnpackParametersResetRestore temporaryResetUnpack(this); | 
| if (functionID == TexImage2D) { | 
| texImage2DBase(target, level, internalformat, bitmap->width(), | 
| bitmap->height(), 0, format, type, | 
| @@ -5196,7 +5229,6 @@ void WebGLRenderingContextBase::texImageHelperImageBitmap( | 
| type, | 
| needConversion ? data.data() : pixelDataPtr); | 
| } | 
| -  restoreUnpackParameters(); | 
| } | 
|  | 
| void WebGLRenderingContextBase::texImage2D(GLenum target, | 
|  |